1da14cebeSEric Cheng /* 2da14cebeSEric Cheng * CDDL HEADER START 3da14cebeSEric Cheng * 4da14cebeSEric Cheng * The contents of this file are subject to the terms of the 5da14cebeSEric Cheng * Common Development and Distribution License (the "License"). 6da14cebeSEric Cheng * You may not use this file except in compliance with the License. 7da14cebeSEric Cheng * 8da14cebeSEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da14cebeSEric Cheng * or http://www.opensolaris.org/os/licensing. 10da14cebeSEric Cheng * See the License for the specific language governing permissions 11da14cebeSEric Cheng * and limitations under the License. 12da14cebeSEric Cheng * 13da14cebeSEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 14da14cebeSEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da14cebeSEric Cheng * If applicable, add the following below this CDDL HEADER, with the 16da14cebeSEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying 17da14cebeSEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner] 18da14cebeSEric Cheng * 19da14cebeSEric Cheng * CDDL HEADER END 20da14cebeSEric Cheng */ 21da14cebeSEric Cheng /* 22*0dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da14cebeSEric Cheng * Use is subject to license terms. 24da14cebeSEric Cheng */ 25da14cebeSEric Cheng 26da14cebeSEric Cheng #include <stdio.h> 27da14cebeSEric Cheng #include <stdlib.h> 28da14cebeSEric Cheng #include <strings.h> 29da14cebeSEric Cheng #include <err.h> 30da14cebeSEric Cheng #include <errno.h> 31c3affd82SMichael Lim #include <fcntl.h> 32da14cebeSEric Cheng #include <kstat.h> 33c3affd82SMichael Lim #include <limits.h> 34da14cebeSEric Cheng #include <unistd.h> 35da14cebeSEric Cheng #include <signal.h> 36da14cebeSEric Cheng #include <sys/dld.h> 3782a2fc47SJames Carlson #include <sys/ddi.h> 38da14cebeSEric Cheng 39da14cebeSEric Cheng #include <libdllink.h> 40da14cebeSEric Cheng #include <libdlflow.h> 41da14cebeSEric Cheng #include <libdlstat.h> 42*0dc2366fSVenugopal Iyer #include <libdlaggr.h> 43da14cebeSEric Cheng 44da14cebeSEric Cheng /* 45da14cebeSEric Cheng * x86 <sys/regs> ERR conflicts with <curses.h> ERR. 46da14cebeSEric Cheng * Include curses.h last. 47da14cebeSEric Cheng */ 48da14cebeSEric Cheng #if defined(ERR) 49da14cebeSEric Cheng #undef ERR 50da14cebeSEric Cheng #endif 51da14cebeSEric Cheng #include <curses.h> 52da14cebeSEric Cheng 53da14cebeSEric Cheng struct flowlist { 54da000602SGirish Moodalbail char flowname[MAXFLOWNAMELEN]; 55c3affd82SMichael Lim char linkname[MAXLINKNAMELEN]; 56da14cebeSEric Cheng datalink_id_t linkid; 57c3affd82SMichael Lim int fd; 58285e94f9SMichael Lim uint64_t ifspeed; 59da14cebeSEric Cheng boolean_t first; 60da14cebeSEric Cheng boolean_t display; 61da14cebeSEric Cheng pktsum_t prevstats; 62da14cebeSEric Cheng pktsum_t diffstats; 63da14cebeSEric Cheng }; 64da14cebeSEric Cheng 65da14cebeSEric Cheng static int maxx, maxy, redraw = 0; 66da14cebeSEric Cheng static volatile uint_t handle_resize = 0, handle_break = 0; 67da14cebeSEric Cheng 68da14cebeSEric Cheng pktsum_t totalstats; 69da14cebeSEric Cheng struct flowlist *stattable = NULL; 70da14cebeSEric Cheng static int statentry = -1, maxstatentries = 0; 71da14cebeSEric Cheng 72da14cebeSEric Cheng #define STATGROWSIZE 16 73da14cebeSEric Cheng 74da14cebeSEric Cheng /* 75da14cebeSEric Cheng * Search for flowlist entry in stattable which matches 76*0dc2366fSVenugopal Iyer * the flowname and linkid. If no match is found, use 77da14cebeSEric Cheng * next available slot. If no slots are available, 78da14cebeSEric Cheng * reallocate table with more slots. 79da14cebeSEric Cheng * 80da14cebeSEric Cheng * Return: *flowlist of matching flow 81da14cebeSEric Cheng * NULL if realloc fails 82da14cebeSEric Cheng */ 83da14cebeSEric Cheng 84da14cebeSEric Cheng static struct flowlist * 85da14cebeSEric Cheng findstat(const char *flowname, datalink_id_t linkid) 86da14cebeSEric Cheng { 87da14cebeSEric Cheng int match = 0; 88da14cebeSEric Cheng struct flowlist *flist; 89da14cebeSEric Cheng 90da14cebeSEric Cheng /* Look for match in the stattable */ 91da14cebeSEric Cheng for (match = 0, flist = stattable; 92da14cebeSEric Cheng match <= statentry; 93da14cebeSEric Cheng match++, flist++) { 94da14cebeSEric Cheng 95da14cebeSEric Cheng if (flist == NULL) 96da14cebeSEric Cheng break; 97da14cebeSEric Cheng /* match the flowname */ 98da14cebeSEric Cheng if (flowname != NULL) { 99da000602SGirish Moodalbail if (strncmp(flowname, flist->flowname, MAXFLOWNAMELEN) 100da14cebeSEric Cheng == NULL) 101da14cebeSEric Cheng return (flist); 102da14cebeSEric Cheng /* match the linkid */ 103da14cebeSEric Cheng } else { 104da14cebeSEric Cheng if (linkid == flist->linkid) 105da14cebeSEric Cheng return (flist); 106da14cebeSEric Cheng } 107da14cebeSEric Cheng } 108da14cebeSEric Cheng 109da14cebeSEric Cheng /* 110da14cebeSEric Cheng * No match found in the table. Store statistics in the next slot. 111da14cebeSEric Cheng * If necessary, make room for this entry. 112da14cebeSEric Cheng */ 113da14cebeSEric Cheng statentry++; 114da14cebeSEric Cheng if ((maxstatentries == 0) || (maxstatentries == statentry)) { 115da14cebeSEric Cheng maxstatentries += STATGROWSIZE; 116da14cebeSEric Cheng stattable = realloc(stattable, 117da14cebeSEric Cheng maxstatentries * sizeof (struct flowlist)); 118da14cebeSEric Cheng if (stattable == NULL) { 119da14cebeSEric Cheng perror("realloc"); 120da14cebeSEric Cheng return (struct flowlist *)(NULL); 121da14cebeSEric Cheng } 122da14cebeSEric Cheng } 123da14cebeSEric Cheng flist = &stattable[statentry]; 124da14cebeSEric Cheng bzero(flist, sizeof (struct flowlist)); 125da14cebeSEric Cheng 126da14cebeSEric Cheng if (flowname != NULL) 127da000602SGirish Moodalbail (void) strncpy(flist->flowname, flowname, MAXFLOWNAMELEN); 128da14cebeSEric Cheng flist->linkid = linkid; 129c3affd82SMichael Lim flist->fd = INT32_MAX; 130c3affd82SMichael Lim 131da14cebeSEric Cheng return (flist); 132da14cebeSEric Cheng } 133da14cebeSEric Cheng 134c3affd82SMichael Lim /*ARGSUSED*/ 135da14cebeSEric Cheng static void 1364ac67f02SAnurag S. Maskey print_flow_stats(dladm_handle_t handle, struct flowlist *flist) 137da14cebeSEric Cheng { 138da14cebeSEric Cheng struct flowlist *fcurr; 139da14cebeSEric Cheng double ikbs, okbs; 140da14cebeSEric Cheng double ipks, opks; 141da14cebeSEric Cheng double dlt; 142da14cebeSEric Cheng int fcount; 143da14cebeSEric Cheng static boolean_t first = B_TRUE; 144da14cebeSEric Cheng 145da14cebeSEric Cheng if (first) { 146da14cebeSEric Cheng first = B_FALSE; 147da14cebeSEric Cheng (void) printw("please wait...\n"); 148da14cebeSEric Cheng return; 149da14cebeSEric Cheng } 150da14cebeSEric Cheng 151da14cebeSEric Cheng for (fcount = 0, fcurr = flist; 152da14cebeSEric Cheng fcount <= statentry; 153da14cebeSEric Cheng fcount++, fcurr++) { 154da14cebeSEric Cheng if (fcurr->flowname && fcurr->display) { 155da14cebeSEric Cheng dlt = (double)fcurr->diffstats.snaptime/(double)NANOSEC; 156da14cebeSEric Cheng ikbs = fcurr->diffstats.rbytes * 8 / dlt / 1024; 157da14cebeSEric Cheng okbs = fcurr->diffstats.obytes * 8 / dlt / 1024; 158da14cebeSEric Cheng ipks = fcurr->diffstats.ipackets / dlt; 159da14cebeSEric Cheng opks = fcurr->diffstats.opackets / dlt; 160da14cebeSEric Cheng (void) printw("%-15.15s", fcurr->flowname); 161c3affd82SMichael Lim (void) printw("%-10.10s", fcurr->linkname); 162da14cebeSEric Cheng (void) printw("%9.2f %9.2f %9.2f %9.2f ", 163da14cebeSEric Cheng ikbs, okbs, ipks, opks); 164da14cebeSEric Cheng (void) printw("\n"); 165da14cebeSEric Cheng } 166da14cebeSEric Cheng } 167da14cebeSEric Cheng } 168da14cebeSEric Cheng 169da14cebeSEric Cheng /*ARGSUSED*/ 170da14cebeSEric Cheng static int 171c3affd82SMichael Lim flow_kstats(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg) 172da14cebeSEric Cheng { 173da14cebeSEric Cheng kstat_ctl_t *kcp = (kstat_ctl_t *)arg; 174da14cebeSEric Cheng kstat_t *ksp; 175da14cebeSEric Cheng struct flowlist *flist; 176da14cebeSEric Cheng pktsum_t currstats, *prevstats, *diffstats; 177da14cebeSEric Cheng 178da14cebeSEric Cheng flist = findstat(attr->fa_flowname, attr->fa_linkid); 179c3affd82SMichael Lim if (flist == NULL) 180c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 181c3affd82SMichael Lim 182c3affd82SMichael Lim flist->display = B_FALSE; 183c3affd82SMichael Lim prevstats = &flist->prevstats; 184c3affd82SMichael Lim diffstats = &flist->diffstats; 185c3affd82SMichael Lim 186c3affd82SMichael Lim (void) dladm_datalink_id2info(handle, attr->fa_linkid, NULL, NULL, 187c3affd82SMichael Lim NULL, flist->linkname, sizeof (flist->linkname)); 188c3affd82SMichael Lim 189da14cebeSEric Cheng 190da14cebeSEric Cheng /* lookup kstat entry */ 191da14cebeSEric Cheng ksp = dladm_kstat_lookup(kcp, NULL, -1, attr->fa_flowname, "flow"); 192da14cebeSEric Cheng 193da14cebeSEric Cheng if (ksp == NULL) 194c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 195da14cebeSEric Cheng 196c3affd82SMichael Lim /* read packet and byte stats */ 197da14cebeSEric Cheng dladm_get_stats(kcp, ksp, &currstats); 198c3affd82SMichael Lim 199da14cebeSEric Cheng if (flist->ifspeed == 0) 200da14cebeSEric Cheng (void) dladm_kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64, 201da14cebeSEric Cheng &flist->ifspeed); 202da14cebeSEric Cheng 203c3affd82SMichael Lim if (flist->first) { 204da14cebeSEric Cheng flist->first = B_FALSE; 205c3affd82SMichael Lim } else { 206da14cebeSEric Cheng dladm_stats_diff(diffstats, &currstats, prevstats); 207c3affd82SMichael Lim if (diffstats->snaptime == 0) 208c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 209da14cebeSEric Cheng dladm_stats_total(&totalstats, diffstats, &totalstats); 210da14cebeSEric Cheng } 211da14cebeSEric Cheng 212da14cebeSEric Cheng bcopy(&currstats, prevstats, sizeof (pktsum_t)); 213c3affd82SMichael Lim flist->display = B_TRUE; 214c3affd82SMichael Lim 215da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 216da14cebeSEric Cheng } 217da14cebeSEric Cheng 218c3affd82SMichael Lim /*ARGSUSED*/ 219da14cebeSEric Cheng static void 2204ac67f02SAnurag S. Maskey print_link_stats(dladm_handle_t handle, struct flowlist *flist) 221da14cebeSEric Cheng { 222da14cebeSEric Cheng struct flowlist *fcurr; 223da14cebeSEric Cheng double ikbs, okbs; 224da14cebeSEric Cheng double ipks, opks; 225da14cebeSEric Cheng double util; 226da14cebeSEric Cheng double dlt; 227da14cebeSEric Cheng int fcount; 228da14cebeSEric Cheng static boolean_t first = B_TRUE; 229da14cebeSEric Cheng 230da14cebeSEric Cheng if (first) { 231da14cebeSEric Cheng first = B_FALSE; 232da14cebeSEric Cheng (void) printw("please wait...\n"); 233da14cebeSEric Cheng return; 234da14cebeSEric Cheng } 235da14cebeSEric Cheng 236da14cebeSEric Cheng for (fcount = 0, fcurr = flist; 237da14cebeSEric Cheng fcount <= statentry; 238da14cebeSEric Cheng fcount++, fcurr++) { 239da14cebeSEric Cheng if ((fcurr->linkid != DATALINK_INVALID_LINKID) && 240da14cebeSEric Cheng fcurr->display) { 241da14cebeSEric Cheng dlt = (double)fcurr->diffstats.snaptime/(double)NANOSEC; 242da14cebeSEric Cheng ikbs = (double)fcurr->diffstats.rbytes * 8 / dlt / 1024; 243da14cebeSEric Cheng okbs = (double)fcurr->diffstats.obytes * 8 / dlt / 1024; 244da14cebeSEric Cheng ipks = (double)fcurr->diffstats.ipackets / dlt; 245da14cebeSEric Cheng opks = (double)fcurr->diffstats.opackets / dlt; 246c3affd82SMichael Lim (void) printw("%-10.10s", fcurr->linkname); 247da14cebeSEric Cheng (void) printw("%9.2f %9.2f %9.2f %9.2f ", 248da14cebeSEric Cheng ikbs, okbs, ipks, opks); 249da14cebeSEric Cheng if (fcurr->ifspeed != 0) 250da14cebeSEric Cheng util = ((ikbs + okbs) * 1024) * 251da14cebeSEric Cheng 100/ fcurr->ifspeed; 252da14cebeSEric Cheng else 253da14cebeSEric Cheng util = (double)0; 254da14cebeSEric Cheng (void) attron(A_BOLD); 255da14cebeSEric Cheng (void) printw(" %6.2f", util); 256da14cebeSEric Cheng (void) attroff(A_BOLD); 257da14cebeSEric Cheng (void) printw("\n"); 258da14cebeSEric Cheng } 259da14cebeSEric Cheng } 260da14cebeSEric Cheng } 261da14cebeSEric Cheng 262da14cebeSEric Cheng /* 263da14cebeSEric Cheng * This function is called through the dladm_walk_datalink_id() walker and 264da14cebeSEric Cheng * calls the dladm_walk_flow() walker. 265da14cebeSEric Cheng */ 266da14cebeSEric Cheng 267da14cebeSEric Cheng /*ARGSUSED*/ 268da14cebeSEric Cheng static int 2694ac67f02SAnurag S. Maskey link_flowstats(dladm_handle_t handle, datalink_id_t linkid, void *arg) 270da14cebeSEric Cheng { 271ad091ee1SMichael Lim dladm_status_t status; 272ad091ee1SMichael Lim 273ad091ee1SMichael Lim status = dladm_walk_flow(flow_kstats, handle, linkid, arg, B_FALSE); 274ad091ee1SMichael Lim if (status == DLADM_STATUS_OK) 275ad091ee1SMichael Lim return (DLADM_WALK_CONTINUE); 276ad091ee1SMichael Lim else 277ad091ee1SMichael Lim return (DLADM_WALK_TERMINATE); 278da14cebeSEric Cheng } 279da14cebeSEric Cheng 280da14cebeSEric Cheng /*ARGSUSED*/ 281da14cebeSEric Cheng static int 2824ac67f02SAnurag S. Maskey link_kstats(dladm_handle_t handle, datalink_id_t linkid, void *arg) 283da14cebeSEric Cheng { 284c3affd82SMichael Lim kstat_ctl_t *kcp = (kstat_ctl_t *)arg; 285c3affd82SMichael Lim struct flowlist *flist; 286c3affd82SMichael Lim pktsum_t currstats, *prevstats, *diffstats; 287c3affd82SMichael Lim datalink_class_t class; 288c3affd82SMichael Lim kstat_t *ksp; 289c3affd82SMichael Lim char dnlink[MAXPATHLEN]; 290da14cebeSEric Cheng 291da14cebeSEric Cheng /* find the flist entry */ 292da14cebeSEric Cheng flist = findstat(NULL, linkid); 293c3affd82SMichael Lim flist->display = B_FALSE; 294da14cebeSEric Cheng if (flist != NULL) { 295da14cebeSEric Cheng prevstats = &flist->prevstats; 296da14cebeSEric Cheng diffstats = &flist->diffstats; 297da14cebeSEric Cheng } else { 298da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 299da14cebeSEric Cheng } 300da14cebeSEric Cheng 301c3affd82SMichael Lim if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL, 302c3affd82SMichael Lim flist->linkname, sizeof (flist->linkname)) != DLADM_STATUS_OK) 303c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 304da14cebeSEric Cheng 305c3affd82SMichael Lim if (flist->fd == INT32_MAX) { 306c3affd82SMichael Lim if (class == DATALINK_CLASS_PHYS) { 307c3affd82SMichael Lim (void) snprintf(dnlink, MAXPATHLEN, "/dev/net/%s", 308c3affd82SMichael Lim flist->linkname); 309c3affd82SMichael Lim if ((flist->fd = open(dnlink, O_RDWR)) < 0) 310c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 311c3affd82SMichael Lim } else { 312c3affd82SMichael Lim flist->fd = -1; 313c3affd82SMichael Lim } 314c3affd82SMichael Lim (void) kstat_chain_update(kcp); 315da14cebeSEric Cheng } 316da14cebeSEric Cheng 317c3affd82SMichael Lim /* lookup kstat entry */ 318c3affd82SMichael Lim ksp = dladm_kstat_lookup(kcp, NULL, -1, flist->linkname, "net"); 319da14cebeSEric Cheng 320da14cebeSEric Cheng if (ksp == NULL) 321c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 322da14cebeSEric Cheng 323da14cebeSEric Cheng /* read packet and byte stats */ 324da14cebeSEric Cheng dladm_get_stats(kcp, ksp, &currstats); 325da14cebeSEric Cheng 326da14cebeSEric Cheng if (flist->ifspeed == 0) 327da14cebeSEric Cheng (void) dladm_kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64, 328da14cebeSEric Cheng &flist->ifspeed); 329da14cebeSEric Cheng 330c3affd82SMichael Lim if (flist->first) { 331da14cebeSEric Cheng flist->first = B_FALSE; 332c3affd82SMichael Lim } else { 333da14cebeSEric Cheng dladm_stats_diff(diffstats, &currstats, prevstats); 334c3affd82SMichael Lim if (diffstats->snaptime == 0) 335c3affd82SMichael Lim return (DLADM_WALK_CONTINUE); 336c3affd82SMichael Lim } 337da14cebeSEric Cheng 338da14cebeSEric Cheng bcopy(&currstats, prevstats, sizeof (*prevstats)); 339c3affd82SMichael Lim flist->display = B_TRUE; 340da14cebeSEric Cheng 341da14cebeSEric Cheng return (DLADM_WALK_CONTINUE); 342da14cebeSEric Cheng } 343da14cebeSEric Cheng 344c3affd82SMichael Lim static void 345c3affd82SMichael Lim closedevnet() 346c3affd82SMichael Lim { 347c3affd82SMichael Lim int index = 0; 348c3affd82SMichael Lim struct flowlist *flist; 349c3affd82SMichael Lim 350c3affd82SMichael Lim /* Close all open /dev/net/ files */ 351*0dc2366fSVenugopal Iyer 352*0dc2366fSVenugopal Iyer for (flist = stattable; index < maxstatentries; index++, flist++) { 353c3affd82SMichael Lim if (flist->linkid == DATALINK_INVALID_LINKID) 354c3affd82SMichael Lim break; 355c3affd82SMichael Lim if (flist->fd != -1 && flist->fd != INT32_MAX) 356c3affd82SMichael Lim (void) close(flist->fd); 357c3affd82SMichael Lim } 358c3affd82SMichael Lim } 359c3affd82SMichael Lim 360da14cebeSEric Cheng /*ARGSUSED*/ 361da14cebeSEric Cheng static void 362da14cebeSEric Cheng sig_break(int s) 363da14cebeSEric Cheng { 364da14cebeSEric Cheng handle_break = 1; 365da14cebeSEric Cheng } 366da14cebeSEric Cheng 367da14cebeSEric Cheng /*ARGSUSED*/ 368da14cebeSEric Cheng static void 369da14cebeSEric Cheng sig_resize(int s) 370da14cebeSEric Cheng { 371da14cebeSEric Cheng handle_resize = 1; 372da14cebeSEric Cheng } 373da14cebeSEric Cheng 374da14cebeSEric Cheng static void 375da14cebeSEric Cheng curses_init() 376da14cebeSEric Cheng { 377da14cebeSEric Cheng maxx = maxx; /* lint */ 378da14cebeSEric Cheng maxy = maxy; /* lint */ 379da14cebeSEric Cheng 380da14cebeSEric Cheng /* Install signal handlers */ 381da14cebeSEric Cheng (void) signal(SIGINT, sig_break); 382da14cebeSEric Cheng (void) signal(SIGQUIT, sig_break); 383da14cebeSEric Cheng (void) signal(SIGTERM, sig_break); 384da14cebeSEric Cheng (void) signal(SIGWINCH, sig_resize); 385da14cebeSEric Cheng 386da14cebeSEric Cheng /* Initialize ncurses */ 387da14cebeSEric Cheng (void) initscr(); 388da14cebeSEric Cheng (void) cbreak(); 389da14cebeSEric Cheng (void) noecho(); 390da14cebeSEric Cheng (void) curs_set(0); 391da14cebeSEric Cheng timeout(0); 392da14cebeSEric Cheng getmaxyx(stdscr, maxy, maxx); 393da14cebeSEric Cheng } 394da14cebeSEric Cheng 395da14cebeSEric Cheng static void 396da14cebeSEric Cheng curses_fin() 397da14cebeSEric Cheng { 398da14cebeSEric Cheng (void) printw("\n"); 399da14cebeSEric Cheng (void) curs_set(1); 400da14cebeSEric Cheng (void) nocbreak(); 401da14cebeSEric Cheng (void) endwin(); 402da14cebeSEric Cheng 403da14cebeSEric Cheng free(stattable); 404da14cebeSEric Cheng } 405da14cebeSEric Cheng 406da14cebeSEric Cheng static void 4074ac67f02SAnurag S. Maskey stat_report(dladm_handle_t handle, kstat_ctl_t *kcp, datalink_id_t linkid, 4084ac67f02SAnurag S. Maskey const char *flowname, int opt) 409da14cebeSEric Cheng { 410da14cebeSEric Cheng 411da14cebeSEric Cheng double dlt, ikbs, okbs, ipks, opks; 412da14cebeSEric Cheng 413da14cebeSEric Cheng struct flowlist *fstable = stattable; 414da14cebeSEric Cheng 415da14cebeSEric Cheng if ((opt != LINK_REPORT) && (opt != FLOW_REPORT)) 416da14cebeSEric Cheng return; 417da14cebeSEric Cheng 418da14cebeSEric Cheng /* Handle window resizes */ 419da14cebeSEric Cheng if (handle_resize) { 420da14cebeSEric Cheng (void) endwin(); 421da14cebeSEric Cheng (void) initscr(); 422da14cebeSEric Cheng (void) cbreak(); 423da14cebeSEric Cheng (void) noecho(); 424da14cebeSEric Cheng (void) curs_set(0); 425da14cebeSEric Cheng timeout(0); 426da14cebeSEric Cheng getmaxyx(stdscr, maxy, maxx); 427da14cebeSEric Cheng redraw = 1; 428da14cebeSEric Cheng handle_resize = 0; 429da14cebeSEric Cheng } 430da14cebeSEric Cheng 431da14cebeSEric Cheng /* Print title */ 432da14cebeSEric Cheng (void) erase(); 433da14cebeSEric Cheng (void) attron(A_BOLD); 434da14cebeSEric Cheng (void) move(0, 0); 435da14cebeSEric Cheng if (opt == FLOW_REPORT) 436da14cebeSEric Cheng (void) printw("%-15.15s", "Flow"); 437da14cebeSEric Cheng (void) printw("%-10.10s", "Link"); 438da14cebeSEric Cheng (void) printw("%9.9s %9.9s %9.9s %9.9s ", 439da14cebeSEric Cheng "iKb/s", "oKb/s", "iPk/s", "oPk/s"); 440da14cebeSEric Cheng if (opt == LINK_REPORT) 441da14cebeSEric Cheng (void) printw(" %6.6s", "%Util"); 442da14cebeSEric Cheng (void) printw("\n"); 443da14cebeSEric Cheng (void) attroff(A_BOLD); 444da14cebeSEric Cheng 445da14cebeSEric Cheng (void) move(2, 0); 446da14cebeSEric Cheng 447da14cebeSEric Cheng /* Print stats for each link or flow */ 448da14cebeSEric Cheng bzero(&totalstats, sizeof (totalstats)); 449da14cebeSEric Cheng if (opt == LINK_REPORT) { 450da14cebeSEric Cheng /* Display all links */ 451da14cebeSEric Cheng if (linkid == DATALINK_ALL_LINKID) { 4524ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(link_kstats, handle, 453da14cebeSEric Cheng (void *)kcp, DATALINK_CLASS_ALL, 454da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 455da14cebeSEric Cheng /* Display 1 link */ 456da14cebeSEric Cheng } else { 4574ac67f02SAnurag S. Maskey (void) link_kstats(handle, linkid, kcp); 458da14cebeSEric Cheng } 4594ac67f02SAnurag S. Maskey print_link_stats(handle, fstable); 460da14cebeSEric Cheng 461da14cebeSEric Cheng } else if (opt == FLOW_REPORT) { 462da14cebeSEric Cheng /* Display 1 flow */ 463da14cebeSEric Cheng if (flowname != NULL) { 464da14cebeSEric Cheng dladm_flow_attr_t fattr; 4654ac67f02SAnurag S. Maskey if (dladm_flow_info(handle, flowname, &fattr) != 466da14cebeSEric Cheng DLADM_STATUS_OK) 467da14cebeSEric Cheng return; 468c3affd82SMichael Lim (void) flow_kstats(handle, &fattr, kcp); 469da14cebeSEric Cheng /* Display all flows on all links */ 470da14cebeSEric Cheng } else if (linkid == DATALINK_ALL_LINKID) { 4714ac67f02SAnurag S. Maskey (void) dladm_walk_datalink_id(link_flowstats, handle, 472da14cebeSEric Cheng (void *)kcp, DATALINK_CLASS_ALL, 473da14cebeSEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 474da14cebeSEric Cheng /* Display all flows on a link */ 475da14cebeSEric Cheng } else if (linkid != DATALINK_INVALID_LINKID) { 4764ac67f02SAnurag S. Maskey (void) dladm_walk_flow(flow_kstats, handle, linkid, kcp, 477da14cebeSEric Cheng B_FALSE); 478da14cebeSEric Cheng } 4794ac67f02SAnurag S. Maskey print_flow_stats(handle, fstable); 480da14cebeSEric Cheng 481da14cebeSEric Cheng /* Print totals */ 482da14cebeSEric Cheng (void) attron(A_BOLD); 483da14cebeSEric Cheng dlt = (double)totalstats.snaptime / (double)NANOSEC; 484da14cebeSEric Cheng ikbs = totalstats.rbytes / dlt / 1024; 485da14cebeSEric Cheng okbs = totalstats.obytes / dlt / 1024; 486da14cebeSEric Cheng ipks = totalstats.ipackets / dlt; 487da14cebeSEric Cheng opks = totalstats.opackets / dlt; 488da14cebeSEric Cheng (void) printw("\n%-25.25s", "Totals"); 489da14cebeSEric Cheng (void) printw("%9.2f %9.2f %9.2f %9.2f ", 490da14cebeSEric Cheng ikbs, okbs, ipks, opks); 491da14cebeSEric Cheng (void) attroff(A_BOLD); 492da14cebeSEric Cheng } 493da14cebeSEric Cheng 494da14cebeSEric Cheng if (redraw) 495da14cebeSEric Cheng (void) clearok(stdscr, 1); 496da14cebeSEric Cheng 497da14cebeSEric Cheng if (refresh() == ERR) 498da14cebeSEric Cheng return; 499da14cebeSEric Cheng 500da14cebeSEric Cheng if (redraw) { 501da14cebeSEric Cheng (void) clearok(stdscr, 0); 502da14cebeSEric Cheng redraw = 0; 503da14cebeSEric Cheng } 504da14cebeSEric Cheng } 505da14cebeSEric Cheng 506da14cebeSEric Cheng /* Exported functions */ 507da14cebeSEric Cheng 508da14cebeSEric Cheng /* 509da14cebeSEric Cheng * Continuously display link or flow statstics using a libcurses 510da14cebeSEric Cheng * based display. 511da14cebeSEric Cheng */ 512da14cebeSEric Cheng 513da14cebeSEric Cheng void 5144ac67f02SAnurag S. Maskey dladm_continuous(dladm_handle_t handle, datalink_id_t linkid, 5154ac67f02SAnurag S. Maskey const char *flowname, int interval, int opt) 516da14cebeSEric Cheng { 517da14cebeSEric Cheng kstat_ctl_t *kcp; 518da14cebeSEric Cheng 519da14cebeSEric Cheng if ((kcp = kstat_open()) == NULL) { 520da14cebeSEric Cheng warn("kstat open operation failed"); 521da14cebeSEric Cheng return; 522da14cebeSEric Cheng } 523da14cebeSEric Cheng 524da14cebeSEric Cheng curses_init(); 525da14cebeSEric Cheng 526da14cebeSEric Cheng for (;;) { 527da14cebeSEric Cheng 528da14cebeSEric Cheng if (handle_break) 529da14cebeSEric Cheng break; 530da14cebeSEric Cheng 5314ac67f02SAnurag S. Maskey stat_report(handle, kcp, linkid, flowname, opt); 532da14cebeSEric Cheng 533da14cebeSEric Cheng (void) sleep(max(1, interval)); 534da14cebeSEric Cheng } 535da14cebeSEric Cheng 536c3affd82SMichael Lim closedevnet(); 537c3affd82SMichael Lim curses_fin(); 538da14cebeSEric Cheng (void) kstat_close(kcp); 539da14cebeSEric Cheng } 540da14cebeSEric Cheng 541da14cebeSEric Cheng /* 542da14cebeSEric Cheng * dladm_kstat_lookup() is a modified version of kstat_lookup which 543da14cebeSEric Cheng * adds the class as a selector. 544da14cebeSEric Cheng */ 545da14cebeSEric Cheng 546da14cebeSEric Cheng kstat_t * 547da14cebeSEric Cheng dladm_kstat_lookup(kstat_ctl_t *kcp, const char *module, int instance, 548da14cebeSEric Cheng const char *name, const char *class) 549da14cebeSEric Cheng { 550da14cebeSEric Cheng kstat_t *ksp = NULL; 551da14cebeSEric Cheng 552da14cebeSEric Cheng for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) { 553da14cebeSEric Cheng if ((module == NULL || strcmp(ksp->ks_module, module) == 0) && 554da14cebeSEric Cheng (instance == -1 || ksp->ks_instance == instance) && 555da14cebeSEric Cheng (name == NULL || strcmp(ksp->ks_name, name) == 0) && 556da14cebeSEric Cheng (class == NULL || strcmp(ksp->ks_class, class) == 0)) 557da14cebeSEric Cheng return (ksp); 558da14cebeSEric Cheng } 559da14cebeSEric Cheng 560da14cebeSEric Cheng errno = ENOENT; 561da14cebeSEric Cheng return (NULL); 562da14cebeSEric Cheng } 563da14cebeSEric Cheng 564da14cebeSEric Cheng /* 565da14cebeSEric Cheng * dladm_get_stats() populates the supplied pktsum_t structure with 566da14cebeSEric Cheng * the input and output packet and byte kstats from the kstat_t 567da14cebeSEric Cheng * found with dladm_kstat_lookup. 568da14cebeSEric Cheng */ 569da14cebeSEric Cheng void 570da14cebeSEric Cheng dladm_get_stats(kstat_ctl_t *kcp, kstat_t *ksp, pktsum_t *stats) 571da14cebeSEric Cheng { 572da14cebeSEric Cheng 573da14cebeSEric Cheng if (kstat_read(kcp, ksp, NULL) == -1) 574da14cebeSEric Cheng return; 575da14cebeSEric Cheng 576da14cebeSEric Cheng stats->snaptime = gethrtime(); 577da14cebeSEric Cheng 578da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64, 579da14cebeSEric Cheng &stats->ipackets) < 0) { 580da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ipackets", KSTAT_DATA_UINT64, 581da14cebeSEric Cheng &stats->ipackets) < 0) 582da14cebeSEric Cheng return; 583da14cebeSEric Cheng } 584da14cebeSEric Cheng 585da14cebeSEric Cheng if (dladm_kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64, 586da14cebeSEric Cheng &stats->opackets) < 0) { 587da14cebeSEric Cheng if (dladm_kstat_value(ksp, "opackets", KSTAT_DATA_UINT64, 588da14cebeSEric Cheng &stats->opackets) < 0) 589da14cebeSEric Cheng return; 590da14cebeSEric Cheng } 591da14cebeSEric Cheng 592da14cebeSEric Cheng if (dladm_kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64, 593da14cebeSEric Cheng &stats->rbytes) < 0) { 594da14cebeSEric Cheng if (dladm_kstat_value(ksp, "rbytes", KSTAT_DATA_UINT64, 595da14cebeSEric Cheng &stats->rbytes) < 0) 596da14cebeSEric Cheng return; 597da14cebeSEric Cheng } 598da14cebeSEric Cheng 599da14cebeSEric Cheng if (dladm_kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64, 600da14cebeSEric Cheng &stats->obytes) < 0) { 601da14cebeSEric Cheng if (dladm_kstat_value(ksp, "obytes", KSTAT_DATA_UINT64, 602da14cebeSEric Cheng &stats->obytes) < 0) 603da14cebeSEric Cheng return; 604da14cebeSEric Cheng } 605da14cebeSEric Cheng 606da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32, 607da14cebeSEric Cheng &stats->ierrors) < 0) { 608da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT64, 609da14cebeSEric Cheng &stats->ierrors) < 0) 610da14cebeSEric Cheng return; 611da14cebeSEric Cheng } 612da14cebeSEric Cheng 613da14cebeSEric Cheng if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32, 614da14cebeSEric Cheng &stats->oerrors) < 0) { 615da14cebeSEric Cheng if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT64, 616da14cebeSEric Cheng &stats->oerrors) < 0) 617da14cebeSEric Cheng return; 618da14cebeSEric Cheng } 619da14cebeSEric Cheng } 620da14cebeSEric Cheng 621da14cebeSEric Cheng int 622da14cebeSEric Cheng dladm_kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf) 623da14cebeSEric Cheng { 624da14cebeSEric Cheng kstat_named_t *knp; 625da14cebeSEric Cheng 626da14cebeSEric Cheng if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL) 627da14cebeSEric Cheng return (-1); 628da14cebeSEric Cheng 629da14cebeSEric Cheng if (knp->data_type != type) 630da14cebeSEric Cheng return (-1); 631da14cebeSEric Cheng 632da14cebeSEric Cheng switch (type) { 633da14cebeSEric Cheng case KSTAT_DATA_UINT64: 634da14cebeSEric Cheng *(uint64_t *)buf = knp->value.ui64; 635da14cebeSEric Cheng break; 636da14cebeSEric Cheng case KSTAT_DATA_UINT32: 637da14cebeSEric Cheng *(uint32_t *)buf = knp->value.ui32; 638da14cebeSEric Cheng break; 639da14cebeSEric Cheng default: 640da14cebeSEric Cheng return (-1); 641da14cebeSEric Cheng } 642da14cebeSEric Cheng 643da14cebeSEric Cheng return (0); 644da14cebeSEric Cheng } 645da14cebeSEric Cheng 646da14cebeSEric Cheng dladm_status_t 6474ac67f02SAnurag S. Maskey dladm_get_single_mac_stat(dladm_handle_t handle, datalink_id_t linkid, 6484ac67f02SAnurag S. Maskey const char *name, uint8_t type, void *val) 649da14cebeSEric Cheng { 650da14cebeSEric Cheng kstat_ctl_t *kcp; 651da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX]; 652da14cebeSEric Cheng uint_t instance; 653da14cebeSEric Cheng char link[DLPI_LINKNAME_MAX]; 654da14cebeSEric Cheng dladm_status_t status; 655da14cebeSEric Cheng uint32_t flags, media; 656da14cebeSEric Cheng kstat_t *ksp; 657da14cebeSEric Cheng dladm_phys_attr_t dpap; 658da14cebeSEric Cheng 6594ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL, 6604ac67f02SAnurag S. Maskey &media, link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK) 661da14cebeSEric Cheng return (status); 662da14cebeSEric Cheng 663da14cebeSEric Cheng if (media != DL_ETHER) 664da14cebeSEric Cheng return (DLADM_STATUS_LINKINVAL); 665da14cebeSEric Cheng 6664ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpap, DLADM_OPT_PERSIST); 667da14cebeSEric Cheng 668da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 669da14cebeSEric Cheng return (status); 670da14cebeSEric Cheng 671da14cebeSEric Cheng status = dladm_parselink(dpap.dp_dev, module, &instance); 672da14cebeSEric Cheng 673da14cebeSEric Cheng if (status != DLADM_STATUS_OK) 674da14cebeSEric Cheng return (status); 675da14cebeSEric Cheng 6763efde6d0SSowmini Varadhan if ((kcp = kstat_open()) == NULL) { 6773efde6d0SSowmini Varadhan warn("kstat_open operation failed"); 6783efde6d0SSowmini Varadhan return (-1); 6793efde6d0SSowmini Varadhan } 6803efde6d0SSowmini Varadhan 681da14cebeSEric Cheng /* 682da14cebeSEric Cheng * The kstat query could fail if the underlying MAC 683da14cebeSEric Cheng * driver was already detached. 684da14cebeSEric Cheng */ 685da14cebeSEric Cheng if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL && 686da14cebeSEric Cheng (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) 687da14cebeSEric Cheng goto bail; 688da14cebeSEric Cheng 689da14cebeSEric Cheng if (kstat_read(kcp, ksp, NULL) == -1) 690da14cebeSEric Cheng goto bail; 691da14cebeSEric Cheng 692da14cebeSEric Cheng if (dladm_kstat_value(ksp, name, type, val) < 0) 693da14cebeSEric Cheng goto bail; 694da14cebeSEric Cheng 695da14cebeSEric Cheng (void) kstat_close(kcp); 696da14cebeSEric Cheng return (DLADM_STATUS_OK); 697da14cebeSEric Cheng 698da14cebeSEric Cheng bail: 699da14cebeSEric Cheng (void) kstat_close(kcp); 700da14cebeSEric Cheng return (dladm_errno2status(errno)); 701da14cebeSEric Cheng } 702da14cebeSEric Cheng 703da14cebeSEric Cheng /* Compute sum of 2 pktsums (s1 = s2 + s3) */ 704da14cebeSEric Cheng void 705da14cebeSEric Cheng dladm_stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 706da14cebeSEric Cheng { 707da14cebeSEric Cheng s1->rbytes = s2->rbytes + s3->rbytes; 708da14cebeSEric Cheng s1->ipackets = s2->ipackets + s3->ipackets; 709da14cebeSEric Cheng s1->ierrors = s2->ierrors + s3->ierrors; 710da14cebeSEric Cheng s1->obytes = s2->obytes + s3->obytes; 711da14cebeSEric Cheng s1->opackets = s2->opackets + s3->opackets; 712da14cebeSEric Cheng s1->oerrors = s2->oerrors + s3->oerrors; 713da14cebeSEric Cheng s1->snaptime = s2->snaptime; 714da14cebeSEric Cheng } 715da14cebeSEric Cheng 716*0dc2366fSVenugopal Iyer #define DIFF_STAT(s2, s3) ((s2) > (s3) ? ((s2) - (s3)) : 0) 7172d40c3b2SPrakash Jalan 7182d40c3b2SPrakash Jalan 719da14cebeSEric Cheng /* Compute differences between 2 pktsums (s1 = s2 - s3) */ 720da14cebeSEric Cheng void 721da14cebeSEric Cheng dladm_stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3) 722da14cebeSEric Cheng { 7232d40c3b2SPrakash Jalan s1->rbytes = DIFF_STAT(s2->rbytes, s3->rbytes); 7242d40c3b2SPrakash Jalan s1->ipackets = DIFF_STAT(s2->ipackets, s3->ipackets); 7252d40c3b2SPrakash Jalan s1->ierrors = DIFF_STAT(s2->ierrors, s3->ierrors); 7262d40c3b2SPrakash Jalan s1->obytes = DIFF_STAT(s2->obytes, s3->obytes); 7272d40c3b2SPrakash Jalan s1->opackets = DIFF_STAT(s2->opackets, s3->opackets); 7282d40c3b2SPrakash Jalan s1->oerrors = DIFF_STAT(s2->oerrors, s3->oerrors); 7292d40c3b2SPrakash Jalan s1->snaptime = DIFF_STAT(s2->snaptime, s3->snaptime); 730da14cebeSEric Cheng } 731*0dc2366fSVenugopal Iyer 732*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_RX_SWLANE "mac_rx_swlane" 733*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_RX_HWLANE "mac_rx_hwlane" 734*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_TX_SWLANE "mac_tx_swlane" 735*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_TX_HWLANE "mac_tx_hwlane" 736*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_MISC_STAT "mac_misc_stat" 737*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_RX_RING "mac_rx_ring" 738*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_TX_RING "mac_tx_ring" 739*0dc2366fSVenugopal Iyer #define DLSTAT_MAC_FANOUT "mac_rx_swlane0_fanout" 740*0dc2366fSVenugopal Iyer 741*0dc2366fSVenugopal Iyer typedef struct { 742*0dc2366fSVenugopal Iyer const char *si_name; 743*0dc2366fSVenugopal Iyer uint_t si_offset; 744*0dc2366fSVenugopal Iyer } stat_info_t; 745*0dc2366fSVenugopal Iyer 746*0dc2366fSVenugopal Iyer #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0])) 747*0dc2366fSVenugopal Iyer 748*0dc2366fSVenugopal Iyer /* Definitions for rx lane stats */ 749*0dc2366fSVenugopal Iyer #define RL_OFF(f) (offsetof(rx_lane_stat_t, f)) 750*0dc2366fSVenugopal Iyer 751*0dc2366fSVenugopal Iyer static stat_info_t rx_hwlane_stats_list[] = { 752*0dc2366fSVenugopal Iyer {"ipackets", RL_OFF(rl_ipackets)}, 753*0dc2366fSVenugopal Iyer {"rbytes", RL_OFF(rl_rbytes)}, 754*0dc2366fSVenugopal Iyer {"intrs", RL_OFF(rl_intrs)}, 755*0dc2366fSVenugopal Iyer {"intrbytes", RL_OFF(rl_intrbytes)}, 756*0dc2366fSVenugopal Iyer {"polls", RL_OFF(rl_polls)}, 757*0dc2366fSVenugopal Iyer {"pollbytes", RL_OFF(rl_pollbytes)}, 758*0dc2366fSVenugopal Iyer {"rxsdrops", RL_OFF(rl_sdrops)}, 759*0dc2366fSVenugopal Iyer {"chainunder10", RL_OFF(rl_chl10)}, 760*0dc2366fSVenugopal Iyer {"chain10to50", RL_OFF(rl_ch10_50)}, 761*0dc2366fSVenugopal Iyer {"chainover50", RL_OFF(rl_chg50)} 762*0dc2366fSVenugopal Iyer }; 763*0dc2366fSVenugopal Iyer #define RX_HWLANE_STAT_SIZE A_CNT(rx_hwlane_stats_list) 764*0dc2366fSVenugopal Iyer 765*0dc2366fSVenugopal Iyer static stat_info_t rx_swlane_stats_list[] = { 766*0dc2366fSVenugopal Iyer {"ipackets", RL_OFF(rl_ipackets)}, 767*0dc2366fSVenugopal Iyer {"rbytes", RL_OFF(rl_rbytes)}, 768*0dc2366fSVenugopal Iyer {"local", RL_OFF(rl_lclpackets)}, 769*0dc2366fSVenugopal Iyer {"localbytes", RL_OFF(rl_lclbytes)}, 770*0dc2366fSVenugopal Iyer {"intrs", RL_OFF(rl_intrs)}, 771*0dc2366fSVenugopal Iyer {"intrbytes", RL_OFF(rl_intrbytes)}, 772*0dc2366fSVenugopal Iyer {"rxsdrops", RL_OFF(rl_sdrops)} 773*0dc2366fSVenugopal Iyer }; 774*0dc2366fSVenugopal Iyer #define RX_SWLANE_STAT_SIZE A_CNT(rx_swlane_stats_list) 775*0dc2366fSVenugopal Iyer 776*0dc2366fSVenugopal Iyer static stat_info_t rx_lane_stats_list[] = { 777*0dc2366fSVenugopal Iyer {"ipackets", RL_OFF(rl_ipackets)}, 778*0dc2366fSVenugopal Iyer {"rbytes", RL_OFF(rl_rbytes)}, 779*0dc2366fSVenugopal Iyer {"local", RL_OFF(rl_lclpackets)}, 780*0dc2366fSVenugopal Iyer {"localbytes", RL_OFF(rl_lclbytes)}, 781*0dc2366fSVenugopal Iyer {"intrs", RL_OFF(rl_intrs)}, 782*0dc2366fSVenugopal Iyer {"intrbytes", RL_OFF(rl_intrbytes)}, 783*0dc2366fSVenugopal Iyer {"polls", RL_OFF(rl_polls)}, 784*0dc2366fSVenugopal Iyer {"rxsdrops", RL_OFF(rl_sdrops)}, 785*0dc2366fSVenugopal Iyer {"pollbytes", RL_OFF(rl_pollbytes)}, 786*0dc2366fSVenugopal Iyer {"chainunder10", RL_OFF(rl_chl10)}, 787*0dc2366fSVenugopal Iyer {"chain10to50", RL_OFF(rl_ch10_50)}, 788*0dc2366fSVenugopal Iyer {"chainover50", RL_OFF(rl_chg50)} 789*0dc2366fSVenugopal Iyer }; 790*0dc2366fSVenugopal Iyer #define RX_LANE_STAT_SIZE A_CNT(rx_lane_stats_list) 791*0dc2366fSVenugopal Iyer 792*0dc2366fSVenugopal Iyer /* Definitions for tx lane stats */ 793*0dc2366fSVenugopal Iyer #define TL_OFF(f) (offsetof(tx_lane_stat_t, f)) 794*0dc2366fSVenugopal Iyer 795*0dc2366fSVenugopal Iyer static stat_info_t tx_lane_stats_list[] = { 796*0dc2366fSVenugopal Iyer {"opackets", TL_OFF(tl_opackets)}, 797*0dc2366fSVenugopal Iyer {"obytes", TL_OFF(tl_obytes)}, 798*0dc2366fSVenugopal Iyer {"blockcnt", TL_OFF(tl_blockcnt)}, 799*0dc2366fSVenugopal Iyer {"unblockcnt", TL_OFF(tl_unblockcnt)}, 800*0dc2366fSVenugopal Iyer {"txsdrops", TL_OFF(tl_sdrops)} 801*0dc2366fSVenugopal Iyer }; 802*0dc2366fSVenugopal Iyer #define TX_LANE_STAT_SIZE A_CNT(tx_lane_stats_list) 803*0dc2366fSVenugopal Iyer 804*0dc2366fSVenugopal Iyer /* Definitions for tx/rx misc stats */ 805*0dc2366fSVenugopal Iyer #define M_OFF(f) (offsetof(misc_stat_t, f)) 806*0dc2366fSVenugopal Iyer 807*0dc2366fSVenugopal Iyer static stat_info_t misc_stats_list[] = { 808*0dc2366fSVenugopal Iyer {"multircv", M_OFF(ms_multircv)}, 809*0dc2366fSVenugopal Iyer {"brdcstrcv", M_OFF(ms_brdcstrcv)}, 810*0dc2366fSVenugopal Iyer {"multixmt", M_OFF(ms_multixmt)}, 811*0dc2366fSVenugopal Iyer {"brdcstxmt", M_OFF(ms_brdcstxmt)}, 812*0dc2366fSVenugopal Iyer {"multircvbytes", M_OFF(ms_multircvbytes)}, 813*0dc2366fSVenugopal Iyer {"brdcstrcvbytes", M_OFF(ms_brdcstrcvbytes)}, 814*0dc2366fSVenugopal Iyer {"multixmtbytes", M_OFF(ms_multixmtbytes)}, 815*0dc2366fSVenugopal Iyer {"brdcstxmtbytes", M_OFF(ms_brdcstxmtbytes)}, 816*0dc2366fSVenugopal Iyer {"txerrors", M_OFF(ms_txerrors)}, 817*0dc2366fSVenugopal Iyer {"macspoofed", M_OFF(ms_macspoofed)}, 818*0dc2366fSVenugopal Iyer {"ipspoofed", M_OFF(ms_ipspoofed)}, 819*0dc2366fSVenugopal Iyer {"dhcpspoofed", M_OFF(ms_dhcpspoofed)}, 820*0dc2366fSVenugopal Iyer {"restricted", M_OFF(ms_restricted)}, 821*0dc2366fSVenugopal Iyer {"ipackets", M_OFF(ms_ipackets)}, 822*0dc2366fSVenugopal Iyer {"rbytes", M_OFF(ms_rbytes)}, 823*0dc2366fSVenugopal Iyer {"local", M_OFF(ms_local)}, 824*0dc2366fSVenugopal Iyer {"localbytes", M_OFF(ms_localbytes)}, 825*0dc2366fSVenugopal Iyer {"intrs", M_OFF(ms_intrs)}, 826*0dc2366fSVenugopal Iyer {"intrbytes", M_OFF(ms_intrbytes)}, 827*0dc2366fSVenugopal Iyer {"polls", M_OFF(ms_polls)}, 828*0dc2366fSVenugopal Iyer {"pollbytes", M_OFF(ms_pollbytes)}, 829*0dc2366fSVenugopal Iyer {"rxsdrops", M_OFF(ms_rxsdrops)}, 830*0dc2366fSVenugopal Iyer {"chainunder10", M_OFF(ms_chainunder10)}, 831*0dc2366fSVenugopal Iyer {"chain10to50", M_OFF(ms_chain10to50)}, 832*0dc2366fSVenugopal Iyer {"chainover50", M_OFF(ms_chainover50)}, 833*0dc2366fSVenugopal Iyer {"obytes", M_OFF(ms_obytes)}, 834*0dc2366fSVenugopal Iyer {"opackets", M_OFF(ms_opackets)}, 835*0dc2366fSVenugopal Iyer {"blockcnt", M_OFF(ms_blockcnt)}, 836*0dc2366fSVenugopal Iyer {"unblockcnt", M_OFF(ms_unblockcnt)}, 837*0dc2366fSVenugopal Iyer {"txsdrops", M_OFF(ms_txsdrops)} 838*0dc2366fSVenugopal Iyer }; 839*0dc2366fSVenugopal Iyer #define MISC_STAT_SIZE A_CNT(misc_stats_list) 840*0dc2366fSVenugopal Iyer 841*0dc2366fSVenugopal Iyer /* Definitions for rx ring stats */ 842*0dc2366fSVenugopal Iyer #define R_OFF(f) (offsetof(ring_stat_t, f)) 843*0dc2366fSVenugopal Iyer 844*0dc2366fSVenugopal Iyer static stat_info_t rx_ring_stats_list[] = { 845*0dc2366fSVenugopal Iyer {"ipackets", R_OFF(r_packets)}, 846*0dc2366fSVenugopal Iyer {"rbytes", R_OFF(r_bytes)} 847*0dc2366fSVenugopal Iyer }; 848*0dc2366fSVenugopal Iyer #define RX_RING_STAT_SIZE A_CNT(rx_ring_stats_list) 849*0dc2366fSVenugopal Iyer 850*0dc2366fSVenugopal Iyer /* Definitions for tx ring stats */ 851*0dc2366fSVenugopal Iyer static stat_info_t tx_ring_stats_list[] = { 852*0dc2366fSVenugopal Iyer {"opackets", R_OFF(r_packets)}, 853*0dc2366fSVenugopal Iyer {"obytes", R_OFF(r_bytes)} 854*0dc2366fSVenugopal Iyer }; 855*0dc2366fSVenugopal Iyer #define TX_RING_STAT_SIZE A_CNT(tx_ring_stats_list) 856*0dc2366fSVenugopal Iyer 857*0dc2366fSVenugopal Iyer /* Definitions for fanout stats */ 858*0dc2366fSVenugopal Iyer #define F_OFF(f) (offsetof(fanout_stat_t, f)) 859*0dc2366fSVenugopal Iyer 860*0dc2366fSVenugopal Iyer static stat_info_t fanout_stats_list[] = { 861*0dc2366fSVenugopal Iyer {"ipackets", F_OFF(f_ipackets)}, 862*0dc2366fSVenugopal Iyer {"rbytes", F_OFF(f_rbytes)}, 863*0dc2366fSVenugopal Iyer }; 864*0dc2366fSVenugopal Iyer #define FANOUT_STAT_SIZE A_CNT(fanout_stats_list) 865*0dc2366fSVenugopal Iyer 866*0dc2366fSVenugopal Iyer /* Definitions for total stats */ 867*0dc2366fSVenugopal Iyer #define T_OFF(f) (offsetof(total_stat_t, f)) 868*0dc2366fSVenugopal Iyer 869*0dc2366fSVenugopal Iyer static stat_info_t total_stats_list[] = { 870*0dc2366fSVenugopal Iyer {"ipackets", T_OFF(ts_ipackets)}, 871*0dc2366fSVenugopal Iyer {"rbytes", T_OFF(ts_rbytes)}, 872*0dc2366fSVenugopal Iyer {"opackets", T_OFF(ts_opackets)}, 873*0dc2366fSVenugopal Iyer {"obytes", T_OFF(ts_obytes)} 874*0dc2366fSVenugopal Iyer }; 875*0dc2366fSVenugopal Iyer #define TOTAL_STAT_SIZE A_CNT(total_stats_list) 876*0dc2366fSVenugopal Iyer 877*0dc2366fSVenugopal Iyer /* Definitions for aggr stats */ 878*0dc2366fSVenugopal Iyer #define AP_OFF(f) (offsetof(aggr_port_stat_t, f)) 879*0dc2366fSVenugopal Iyer 880*0dc2366fSVenugopal Iyer static stat_info_t aggr_port_stats_list[] = { 881*0dc2366fSVenugopal Iyer {"ipackets64", AP_OFF(ap_ipackets)}, 882*0dc2366fSVenugopal Iyer {"rbytes64", AP_OFF(ap_rbytes)}, 883*0dc2366fSVenugopal Iyer {"opackets64", AP_OFF(ap_opackets)}, 884*0dc2366fSVenugopal Iyer {"obytes64", AP_OFF(ap_obytes)} 885*0dc2366fSVenugopal Iyer }; 886*0dc2366fSVenugopal Iyer #define AGGR_PORT_STAT_SIZE A_CNT(aggr_port_stats_list) 887*0dc2366fSVenugopal Iyer 888*0dc2366fSVenugopal Iyer /* Definitions for flow stats */ 889*0dc2366fSVenugopal Iyer #define FL_OFF(f) (offsetof(flow_stat_t, f)) 890*0dc2366fSVenugopal Iyer 891*0dc2366fSVenugopal Iyer static stat_info_t flow_stats_list[] = { 892*0dc2366fSVenugopal Iyer {"ipackets", FL_OFF(fl_ipackets)}, 893*0dc2366fSVenugopal Iyer {"rbytes", FL_OFF(fl_rbytes)}, 894*0dc2366fSVenugopal Iyer {"opackets", FL_OFF(fl_opackets)}, 895*0dc2366fSVenugopal Iyer {"obytes", FL_OFF(fl_obytes)} 896*0dc2366fSVenugopal Iyer }; 897*0dc2366fSVenugopal Iyer #define FLOW_STAT_SIZE A_CNT(flow_stats_list) 898*0dc2366fSVenugopal Iyer 899*0dc2366fSVenugopal Iyer /* Rx lane specific functions */ 900*0dc2366fSVenugopal Iyer void * dlstat_rx_lane_stats(dladm_handle_t, datalink_id_t); 901*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_rx_lane_match(void *, void *); 902*0dc2366fSVenugopal Iyer static void * i_dlstat_rx_lane_stat_entry_diff(void *, void *); 903*0dc2366fSVenugopal Iyer 904*0dc2366fSVenugopal Iyer /* Tx lane specific functions */ 905*0dc2366fSVenugopal Iyer void * dlstat_tx_lane_stats(dladm_handle_t, datalink_id_t); 906*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_tx_lane_match(void *, void *); 907*0dc2366fSVenugopal Iyer static void * i_dlstat_tx_lane_stat_entry_diff(void *, void *); 908*0dc2366fSVenugopal Iyer 909*0dc2366fSVenugopal Iyer /* Rx lane total specific functions */ 910*0dc2366fSVenugopal Iyer void * dlstat_rx_lane_total_stats(dladm_handle_t, 911*0dc2366fSVenugopal Iyer datalink_id_t); 912*0dc2366fSVenugopal Iyer 913*0dc2366fSVenugopal Iyer /* Tx lane total specific functions */ 914*0dc2366fSVenugopal Iyer void * dlstat_tx_lane_total_stats(dladm_handle_t, 915*0dc2366fSVenugopal Iyer datalink_id_t); 916*0dc2366fSVenugopal Iyer 917*0dc2366fSVenugopal Iyer /* Fanout specific functions */ 918*0dc2366fSVenugopal Iyer void * dlstat_fanout_stats(dladm_handle_t, datalink_id_t); 919*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_fanout_match(void *, void *); 920*0dc2366fSVenugopal Iyer static void * i_dlstat_fanout_stat_entry_diff(void *, void *); 921*0dc2366fSVenugopal Iyer 922*0dc2366fSVenugopal Iyer /* Rx ring specific functions */ 923*0dc2366fSVenugopal Iyer void * dlstat_rx_ring_stats(dladm_handle_t, datalink_id_t); 924*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_rx_ring_match(void *, void *); 925*0dc2366fSVenugopal Iyer static void * i_dlstat_rx_ring_stat_entry_diff(void *, void *); 926*0dc2366fSVenugopal Iyer 927*0dc2366fSVenugopal Iyer /* Tx ring specific functions */ 928*0dc2366fSVenugopal Iyer void * dlstat_tx_ring_stats(dladm_handle_t, datalink_id_t); 929*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_tx_ring_match(void *, void *); 930*0dc2366fSVenugopal Iyer static void * i_dlstat_tx_ring_stat_entry_diff(void *, void *); 931*0dc2366fSVenugopal Iyer 932*0dc2366fSVenugopal Iyer /* Rx ring total specific functions */ 933*0dc2366fSVenugopal Iyer void * dlstat_rx_ring_total_stats(dladm_handle_t, 934*0dc2366fSVenugopal Iyer datalink_id_t); 935*0dc2366fSVenugopal Iyer 936*0dc2366fSVenugopal Iyer /* Tx ring total specific functions */ 937*0dc2366fSVenugopal Iyer void * dlstat_tx_ring_total_stats(dladm_handle_t, 938*0dc2366fSVenugopal Iyer datalink_id_t); 939*0dc2366fSVenugopal Iyer 940*0dc2366fSVenugopal Iyer /* Summary specific functions */ 941*0dc2366fSVenugopal Iyer void * dlstat_total_stats(dladm_handle_t, datalink_id_t); 942*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_total_match(void *, void *); 943*0dc2366fSVenugopal Iyer static void * i_dlstat_total_stat_entry_diff(void *, void *); 944*0dc2366fSVenugopal Iyer 945*0dc2366fSVenugopal Iyer /* Aggr port specific functions */ 946*0dc2366fSVenugopal Iyer void * dlstat_aggr_port_stats(dladm_handle_t, datalink_id_t); 947*0dc2366fSVenugopal Iyer static boolean_t i_dlstat_aggr_port_match(void *, void *); 948*0dc2366fSVenugopal Iyer static void * i_dlstat_aggr_port_stat_entry_diff(void *, void *); 949*0dc2366fSVenugopal Iyer 950*0dc2366fSVenugopal Iyer /* Misc stat specific functions */ 951*0dc2366fSVenugopal Iyer void * dlstat_misc_stats(dladm_handle_t, datalink_id_t); 952*0dc2366fSVenugopal Iyer 953*0dc2366fSVenugopal Iyer typedef void * dladm_stat_query_t(dladm_handle_t, datalink_id_t); 954*0dc2366fSVenugopal Iyer typedef boolean_t dladm_stat_match_t(void *, void *); 955*0dc2366fSVenugopal Iyer typedef void * dladm_stat_diff_t(void *, void *); 956*0dc2366fSVenugopal Iyer 957*0dc2366fSVenugopal Iyer typedef struct dladm_stat_desc_s { 958*0dc2366fSVenugopal Iyer dladm_stat_type_t ds_stattype; 959*0dc2366fSVenugopal Iyer dladm_stat_query_t *ds_querystat; 960*0dc2366fSVenugopal Iyer dladm_stat_match_t *ds_matchstat; 961*0dc2366fSVenugopal Iyer dladm_stat_diff_t *ds_diffstat; 962*0dc2366fSVenugopal Iyer uint_t ds_offset; 963*0dc2366fSVenugopal Iyer stat_info_t *ds_statlist; 964*0dc2366fSVenugopal Iyer uint_t ds_statsize; 965*0dc2366fSVenugopal Iyer } dladm_stat_desc_t; 966*0dc2366fSVenugopal Iyer 967*0dc2366fSVenugopal Iyer /* 968*0dc2366fSVenugopal Iyer * dladm_stat_table has one entry for each supported stat. ds_querystat returns 969*0dc2366fSVenugopal Iyer * a chain of 'stat entries' for the queried stat. 970*0dc2366fSVenugopal Iyer * Each stat entry has set of identifiers (ids) and an object containing actual 971*0dc2366fSVenugopal Iyer * stat values. These stat entry objects are chained together in a linked list 972*0dc2366fSVenugopal Iyer * of datatype dladm_stat_chain_t. Head of this list is returned to the caller 973*0dc2366fSVenugopal Iyer * of dladm_link_stat_query. 974*0dc2366fSVenugopal Iyer * 975*0dc2366fSVenugopal Iyer * One node in the chain is shown below: 976*0dc2366fSVenugopal Iyer * 977*0dc2366fSVenugopal Iyer * ------------------------- 978*0dc2366fSVenugopal Iyer * | dc_statentry | 979*0dc2366fSVenugopal Iyer * | -------------- | 980*0dc2366fSVenugopal Iyer * | | ids | | 981*0dc2366fSVenugopal Iyer * | -------------- | 982*0dc2366fSVenugopal Iyer * | | stat fields | | 983*0dc2366fSVenugopal Iyer * | -------------- | 984*0dc2366fSVenugopal Iyer * ------------------------- 985*0dc2366fSVenugopal Iyer * | dc_next ---------|------> to next stat entry 986*0dc2366fSVenugopal Iyer * ------------------------- 987*0dc2366fSVenugopal Iyer * 988*0dc2366fSVenugopal Iyer * In particular, for query DLADM_STAT_RX_LANE, dc_statentry carries pointer to 989*0dc2366fSVenugopal Iyer * object of type rx_lane_stat_entry_t. 990*0dc2366fSVenugopal Iyer * 991*0dc2366fSVenugopal Iyer * dladm_link_stat_query_all returns similar chain. However, instead of storing 992*0dc2366fSVenugopal Iyer * stat fields as raw numbers, it stores those as chain of <name, value> pairs. 993*0dc2366fSVenugopal Iyer * The resulting structure is depicted below: 994*0dc2366fSVenugopal Iyer * 995*0dc2366fSVenugopal Iyer * ------------------------- 996*0dc2366fSVenugopal Iyer * | dc_statentry | 997*0dc2366fSVenugopal Iyer * | -------------- | --------------- 998*0dc2366fSVenugopal Iyer * | | nv_header | | | name, val | 999*0dc2366fSVenugopal Iyer * | -------------- | --------------- 1000*0dc2366fSVenugopal Iyer * | | nve_stats---|----|-->| nv_nextstat--|---> to next name, val pair 1001*0dc2366fSVenugopal Iyer * | -------------- | --------------- 1002*0dc2366fSVenugopal Iyer * ------------------------- 1003*0dc2366fSVenugopal Iyer * | dc_next ---------|------> to next stat entry 1004*0dc2366fSVenugopal Iyer * ------------------------- 1005*0dc2366fSVenugopal Iyer */ 1006*0dc2366fSVenugopal Iyer static dladm_stat_desc_t dladm_stat_table[] = { 1007*0dc2366fSVenugopal Iyer { DLADM_STAT_RX_LANE, dlstat_rx_lane_stats, 1008*0dc2366fSVenugopal Iyer i_dlstat_rx_lane_match, i_dlstat_rx_lane_stat_entry_diff, 1009*0dc2366fSVenugopal Iyer offsetof(rx_lane_stat_entry_t, rle_stats), 1010*0dc2366fSVenugopal Iyer rx_lane_stats_list, RX_LANE_STAT_SIZE}, 1011*0dc2366fSVenugopal Iyer 1012*0dc2366fSVenugopal Iyer { DLADM_STAT_TX_LANE, dlstat_tx_lane_stats, 1013*0dc2366fSVenugopal Iyer i_dlstat_tx_lane_match, i_dlstat_tx_lane_stat_entry_diff, 1014*0dc2366fSVenugopal Iyer offsetof(tx_lane_stat_entry_t, tle_stats), 1015*0dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE}, 1016*0dc2366fSVenugopal Iyer 1017*0dc2366fSVenugopal Iyer { DLADM_STAT_RX_LANE_TOTAL, dlstat_rx_lane_total_stats, 1018*0dc2366fSVenugopal Iyer i_dlstat_rx_lane_match, i_dlstat_rx_lane_stat_entry_diff, 1019*0dc2366fSVenugopal Iyer offsetof(rx_lane_stat_entry_t, rle_stats), 1020*0dc2366fSVenugopal Iyer rx_lane_stats_list, RX_LANE_STAT_SIZE}, 1021*0dc2366fSVenugopal Iyer 1022*0dc2366fSVenugopal Iyer { DLADM_STAT_TX_LANE_TOTAL, dlstat_tx_lane_total_stats, 1023*0dc2366fSVenugopal Iyer i_dlstat_tx_lane_match, i_dlstat_tx_lane_stat_entry_diff, 1024*0dc2366fSVenugopal Iyer offsetof(tx_lane_stat_entry_t, tle_stats), 1025*0dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE}, 1026*0dc2366fSVenugopal Iyer 1027*0dc2366fSVenugopal Iyer { DLADM_STAT_RX_LANE_FOUT, dlstat_fanout_stats, 1028*0dc2366fSVenugopal Iyer i_dlstat_fanout_match, i_dlstat_fanout_stat_entry_diff, 1029*0dc2366fSVenugopal Iyer offsetof(fanout_stat_entry_t, fe_stats), 1030*0dc2366fSVenugopal Iyer fanout_stats_list, FANOUT_STAT_SIZE}, 1031*0dc2366fSVenugopal Iyer 1032*0dc2366fSVenugopal Iyer { DLADM_STAT_RX_RING, dlstat_rx_ring_stats, 1033*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_match, i_dlstat_rx_ring_stat_entry_diff, 1034*0dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats), 1035*0dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE}, 1036*0dc2366fSVenugopal Iyer 1037*0dc2366fSVenugopal Iyer { DLADM_STAT_TX_RING, dlstat_tx_ring_stats, 1038*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_match, i_dlstat_tx_ring_stat_entry_diff, 1039*0dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats), 1040*0dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE}, 1041*0dc2366fSVenugopal Iyer 1042*0dc2366fSVenugopal Iyer { DLADM_STAT_RX_RING_TOTAL, dlstat_rx_ring_total_stats, 1043*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_match, i_dlstat_rx_ring_stat_entry_diff, 1044*0dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats), 1045*0dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE}, 1046*0dc2366fSVenugopal Iyer 1047*0dc2366fSVenugopal Iyer { DLADM_STAT_TX_RING_TOTAL, dlstat_tx_ring_total_stats, 1048*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_match, i_dlstat_tx_ring_stat_entry_diff, 1049*0dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats), 1050*0dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE}, 1051*0dc2366fSVenugopal Iyer 1052*0dc2366fSVenugopal Iyer { DLADM_STAT_TOTAL, dlstat_total_stats, 1053*0dc2366fSVenugopal Iyer i_dlstat_total_match, i_dlstat_total_stat_entry_diff, 1054*0dc2366fSVenugopal Iyer offsetof(total_stat_entry_t, tse_stats), 1055*0dc2366fSVenugopal Iyer total_stats_list, TOTAL_STAT_SIZE}, 1056*0dc2366fSVenugopal Iyer 1057*0dc2366fSVenugopal Iyer { DLADM_STAT_AGGR_PORT, dlstat_aggr_port_stats, 1058*0dc2366fSVenugopal Iyer i_dlstat_aggr_port_match, i_dlstat_aggr_port_stat_entry_diff, 1059*0dc2366fSVenugopal Iyer offsetof(aggr_port_stat_entry_t, ape_stats), 1060*0dc2366fSVenugopal Iyer aggr_port_stats_list, AGGR_PORT_STAT_SIZE}, 1061*0dc2366fSVenugopal Iyer /* 1062*0dc2366fSVenugopal Iyer * We don't support -i <interval> query with misc stats. Several table fields 1063*0dc2366fSVenugopal Iyer * are left uninitialized thus. 1064*0dc2366fSVenugopal Iyer */ 1065*0dc2366fSVenugopal Iyer { DLADM_STAT_MISC, dlstat_misc_stats, 1066*0dc2366fSVenugopal Iyer NULL, NULL, 1067*0dc2366fSVenugopal Iyer 0, 1068*0dc2366fSVenugopal Iyer misc_stats_list, MISC_STAT_SIZE} 1069*0dc2366fSVenugopal Iyer }; 1070*0dc2366fSVenugopal Iyer 1071*0dc2366fSVenugopal Iyer /* Internal functions */ 1072*0dc2366fSVenugopal Iyer static void * 1073*0dc2366fSVenugopal Iyer dlstat_diff_stats(void *arg1, void *arg2, dladm_stat_type_t stattype) 1074*0dc2366fSVenugopal Iyer { 1075*0dc2366fSVenugopal Iyer return (dladm_stat_table[stattype].ds_diffstat(arg1, arg2)); 1076*0dc2366fSVenugopal Iyer } 1077*0dc2366fSVenugopal Iyer 1078*0dc2366fSVenugopal Iyer static boolean_t 1079*0dc2366fSVenugopal Iyer dlstat_match_stats(void *arg1, void *arg2, dladm_stat_type_t stattype) 1080*0dc2366fSVenugopal Iyer { 1081*0dc2366fSVenugopal Iyer return (dladm_stat_table[stattype].ds_matchstat(arg1, arg2)); 1082*0dc2366fSVenugopal Iyer } 1083*0dc2366fSVenugopal Iyer 1084*0dc2366fSVenugopal Iyer /* Diff between two stats */ 1085*0dc2366fSVenugopal Iyer static void 1086*0dc2366fSVenugopal Iyer i_dlstat_diff_stats(void *diff, void *op1, void *op2, 1087*0dc2366fSVenugopal Iyer stat_info_t stats_list[], uint_t size) 1088*0dc2366fSVenugopal Iyer { 1089*0dc2366fSVenugopal Iyer int i; 1090*0dc2366fSVenugopal Iyer 1091*0dc2366fSVenugopal Iyer for (i = 0; i < size; i++) { 1092*0dc2366fSVenugopal Iyer uint64_t *op1_val = (void *) 1093*0dc2366fSVenugopal Iyer ((uchar_t *)op1 + stats_list[i].si_offset); 1094*0dc2366fSVenugopal Iyer uint64_t *op2_val = (void *) 1095*0dc2366fSVenugopal Iyer ((uchar_t *)op2 + stats_list[i].si_offset); 1096*0dc2366fSVenugopal Iyer uint64_t *diff_val = (void *) 1097*0dc2366fSVenugopal Iyer ((uchar_t *)diff + stats_list[i].si_offset); 1098*0dc2366fSVenugopal Iyer 1099*0dc2366fSVenugopal Iyer *diff_val = DIFF_STAT(*op1_val, *op2_val); 1100*0dc2366fSVenugopal Iyer } 1101*0dc2366fSVenugopal Iyer } 1102*0dc2366fSVenugopal Iyer 1103*0dc2366fSVenugopal Iyer /* 1104*0dc2366fSVenugopal Iyer * Perform diff = s1 - s2, where diff, s1, s2 are structure objects of same 1105*0dc2366fSVenugopal Iyer * datatype. slist is list of offsets of the fields within the structure. 1106*0dc2366fSVenugopal Iyer */ 1107*0dc2366fSVenugopal Iyer #define DLSTAT_DIFF_STAT(s1, s2, diff, f, slist, sz) { \ 1108*0dc2366fSVenugopal Iyer if (s2 == NULL) { \ 1109*0dc2366fSVenugopal Iyer bcopy(&s1->f, &diff->f, sizeof (s1->f)); \ 1110*0dc2366fSVenugopal Iyer } else { \ 1111*0dc2366fSVenugopal Iyer i_dlstat_diff_stats(&diff->f, &s1->f, \ 1112*0dc2366fSVenugopal Iyer &s2->f, slist, sz); \ 1113*0dc2366fSVenugopal Iyer } \ 1114*0dc2366fSVenugopal Iyer } 1115*0dc2366fSVenugopal Iyer 1116*0dc2366fSVenugopal Iyer /* Sum two stats */ 1117*0dc2366fSVenugopal Iyer static void 1118*0dc2366fSVenugopal Iyer i_dlstat_sum_stats(void *sum, void *op1, void *op2, 1119*0dc2366fSVenugopal Iyer stat_info_t stats_list[], uint_t size) 1120*0dc2366fSVenugopal Iyer { 1121*0dc2366fSVenugopal Iyer int i; 1122*0dc2366fSVenugopal Iyer 1123*0dc2366fSVenugopal Iyer for (i = 0; i < size; i++) { 1124*0dc2366fSVenugopal Iyer uint64_t *op1_val = (void *) 1125*0dc2366fSVenugopal Iyer ((uchar_t *)op1 + stats_list[i].si_offset); 1126*0dc2366fSVenugopal Iyer uint64_t *op2_val = (void *) 1127*0dc2366fSVenugopal Iyer ((uchar_t *)op2 + stats_list[i].si_offset); 1128*0dc2366fSVenugopal Iyer uint64_t *sum_val = (void *) 1129*0dc2366fSVenugopal Iyer ((uchar_t *)sum + stats_list[i].si_offset); 1130*0dc2366fSVenugopal Iyer 1131*0dc2366fSVenugopal Iyer *sum_val = *op1_val + *op2_val; 1132*0dc2366fSVenugopal Iyer } 1133*0dc2366fSVenugopal Iyer } 1134*0dc2366fSVenugopal Iyer 1135*0dc2366fSVenugopal Iyer /* Look up kstat value */ 1136*0dc2366fSVenugopal Iyer static void 1137*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kstat_ctl_t *kcp, kstat_t *ksp, void *stats, 1138*0dc2366fSVenugopal Iyer stat_info_t stats_list[], uint_t size) 1139*0dc2366fSVenugopal Iyer { 1140*0dc2366fSVenugopal Iyer int i; 1141*0dc2366fSVenugopal Iyer 1142*0dc2366fSVenugopal Iyer if (kstat_read(kcp, ksp, NULL) == -1) 1143*0dc2366fSVenugopal Iyer return; 1144*0dc2366fSVenugopal Iyer 1145*0dc2366fSVenugopal Iyer for (i = 0; i < size; i++) { 1146*0dc2366fSVenugopal Iyer uint64_t *val = (void *) 1147*0dc2366fSVenugopal Iyer ((uchar_t *)stats + stats_list[i].si_offset); 1148*0dc2366fSVenugopal Iyer 1149*0dc2366fSVenugopal Iyer if (dladm_kstat_value(ksp, stats_list[i].si_name, 1150*0dc2366fSVenugopal Iyer KSTAT_DATA_UINT64, val) < 0) 1151*0dc2366fSVenugopal Iyer return; 1152*0dc2366fSVenugopal Iyer } 1153*0dc2366fSVenugopal Iyer } 1154*0dc2366fSVenugopal Iyer 1155*0dc2366fSVenugopal Iyer /* Append linked list list1 to linked list list2 and return resulting list */ 1156*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1157*0dc2366fSVenugopal Iyer i_dlstat_join_lists(dladm_stat_chain_t *list1, dladm_stat_chain_t *list2) 1158*0dc2366fSVenugopal Iyer { 1159*0dc2366fSVenugopal Iyer dladm_stat_chain_t *curr; 1160*0dc2366fSVenugopal Iyer 1161*0dc2366fSVenugopal Iyer if (list1 == NULL) 1162*0dc2366fSVenugopal Iyer return (list2); 1163*0dc2366fSVenugopal Iyer 1164*0dc2366fSVenugopal Iyer /* list1 has at least one element, find last element in list1 */ 1165*0dc2366fSVenugopal Iyer curr = list1; 1166*0dc2366fSVenugopal Iyer while (curr->dc_next != NULL) 1167*0dc2366fSVenugopal Iyer curr = curr->dc_next; 1168*0dc2366fSVenugopal Iyer 1169*0dc2366fSVenugopal Iyer curr->dc_next = list2; 1170*0dc2366fSVenugopal Iyer return (list1); 1171*0dc2366fSVenugopal Iyer } 1172*0dc2366fSVenugopal Iyer 1173*0dc2366fSVenugopal Iyer uint_t default_idlist[] = {0}; 1174*0dc2366fSVenugopal Iyer uint_t default_idlist_size = 1; 1175*0dc2366fSVenugopal Iyer 1176*0dc2366fSVenugopal Iyer typedef enum { 1177*0dc2366fSVenugopal Iyer DLSTAT_RX_RING_IDLIST, 1178*0dc2366fSVenugopal Iyer DLSTAT_TX_RING_IDLIST, 1179*0dc2366fSVenugopal Iyer DLSTAT_RX_HWLANE_IDLIST, 1180*0dc2366fSVenugopal Iyer DLSTAT_TX_HWLANE_IDLIST, 1181*0dc2366fSVenugopal Iyer DLSTAT_FANOUT_IDLIST 1182*0dc2366fSVenugopal Iyer } dlstat_idlist_type_t; 1183*0dc2366fSVenugopal Iyer 1184*0dc2366fSVenugopal Iyer void 1185*0dc2366fSVenugopal Iyer dladm_sort_index_list(uint_t idlist[], uint_t size) 1186*0dc2366fSVenugopal Iyer { 1187*0dc2366fSVenugopal Iyer int i, j; 1188*0dc2366fSVenugopal Iyer 1189*0dc2366fSVenugopal Iyer for (j = 1; j < size; j++) { 1190*0dc2366fSVenugopal Iyer int key = idlist[j]; 1191*0dc2366fSVenugopal Iyer for (i = j - 1; (i >= 0) && (idlist[i] > key); i--) 1192*0dc2366fSVenugopal Iyer idlist[i + 1] = idlist[i]; 1193*0dc2366fSVenugopal Iyer idlist[i + 1] = key; 1194*0dc2366fSVenugopal Iyer } 1195*0dc2366fSVenugopal Iyer } 1196*0dc2366fSVenugopal Iyer 1197*0dc2366fSVenugopal Iyer /* Support for legacy drivers */ 1198*0dc2366fSVenugopal Iyer void 1199*0dc2366fSVenugopal Iyer i_query_legacy_stats(const char *linkname, pktsum_t *stats) 1200*0dc2366fSVenugopal Iyer { 1201*0dc2366fSVenugopal Iyer kstat_ctl_t *kcp; 1202*0dc2366fSVenugopal Iyer kstat_t *ksp; 1203*0dc2366fSVenugopal Iyer 1204*0dc2366fSVenugopal Iyer bzero(stats, sizeof (*stats)); 1205*0dc2366fSVenugopal Iyer 1206*0dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) 1207*0dc2366fSVenugopal Iyer return; 1208*0dc2366fSVenugopal Iyer 1209*0dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, "link", 0, linkname, NULL); 1210*0dc2366fSVenugopal Iyer 1211*0dc2366fSVenugopal Iyer if (ksp != NULL) 1212*0dc2366fSVenugopal Iyer dladm_get_stats(kcp, ksp, stats); 1213*0dc2366fSVenugopal Iyer 1214*0dc2366fSVenugopal Iyer (void) kstat_close(kcp); 1215*0dc2366fSVenugopal Iyer } 1216*0dc2366fSVenugopal Iyer 1217*0dc2366fSVenugopal Iyer void * 1218*0dc2366fSVenugopal Iyer i_dlstat_legacy_rx_lane_stats(const char *linkname) 1219*0dc2366fSVenugopal Iyer { 1220*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1221*0dc2366fSVenugopal Iyer pktsum_t stats; 1222*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 1223*0dc2366fSVenugopal Iyer 1224*0dc2366fSVenugopal Iyer bzero(&stats, sizeof (pktsum_t)); 1225*0dc2366fSVenugopal Iyer 1226*0dc2366fSVenugopal Iyer /* Query for dls stats */ 1227*0dc2366fSVenugopal Iyer i_query_legacy_stats(linkname, &stats); 1228*0dc2366fSVenugopal Iyer 1229*0dc2366fSVenugopal Iyer /* Convert to desired data type */ 1230*0dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1231*0dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL) 1232*0dc2366fSVenugopal Iyer goto done; 1233*0dc2366fSVenugopal Iyer 1234*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY; 1235*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_SWLANE; 1236*0dc2366fSVenugopal Iyer 1237*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets = stats.ipackets; 1238*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs = stats.ipackets; 1239*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes = stats.rbytes; 1240*0dc2366fSVenugopal Iyer 1241*0dc2366fSVenugopal Iyer /* Allocate memory for wrapper */ 1242*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 1243*0dc2366fSVenugopal Iyer if (head == NULL) { 1244*0dc2366fSVenugopal Iyer free(rx_lane_stat_entry); 1245*0dc2366fSVenugopal Iyer goto done; 1246*0dc2366fSVenugopal Iyer } 1247*0dc2366fSVenugopal Iyer 1248*0dc2366fSVenugopal Iyer head->dc_statentry = rx_lane_stat_entry; 1249*0dc2366fSVenugopal Iyer head->dc_next = NULL; 1250*0dc2366fSVenugopal Iyer done: 1251*0dc2366fSVenugopal Iyer return (head); 1252*0dc2366fSVenugopal Iyer } 1253*0dc2366fSVenugopal Iyer 1254*0dc2366fSVenugopal Iyer void * 1255*0dc2366fSVenugopal Iyer i_dlstat_legacy_tx_lane_stats(const char *linkname) 1256*0dc2366fSVenugopal Iyer { 1257*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1258*0dc2366fSVenugopal Iyer pktsum_t stats; 1259*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry; 1260*0dc2366fSVenugopal Iyer 1261*0dc2366fSVenugopal Iyer bzero(&stats, sizeof (pktsum_t)); 1262*0dc2366fSVenugopal Iyer 1263*0dc2366fSVenugopal Iyer /* Query for dls stats */ 1264*0dc2366fSVenugopal Iyer i_query_legacy_stats(linkname, &stats); 1265*0dc2366fSVenugopal Iyer 1266*0dc2366fSVenugopal Iyer /* Convert to desired data type */ 1267*0dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t)); 1268*0dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL) 1269*0dc2366fSVenugopal Iyer goto done; 1270*0dc2366fSVenugopal Iyer 1271*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY; 1272*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_SWLANE; 1273*0dc2366fSVenugopal Iyer 1274*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets = stats.opackets; 1275*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes = stats.obytes; 1276*0dc2366fSVenugopal Iyer 1277*0dc2366fSVenugopal Iyer /* Allocate memory for wrapper */ 1278*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 1279*0dc2366fSVenugopal Iyer if (head == NULL) { 1280*0dc2366fSVenugopal Iyer free(tx_lane_stat_entry); 1281*0dc2366fSVenugopal Iyer goto done; 1282*0dc2366fSVenugopal Iyer } 1283*0dc2366fSVenugopal Iyer 1284*0dc2366fSVenugopal Iyer head->dc_statentry = tx_lane_stat_entry; 1285*0dc2366fSVenugopal Iyer head->dc_next = NULL; 1286*0dc2366fSVenugopal Iyer done: 1287*0dc2366fSVenugopal Iyer return (head); 1288*0dc2366fSVenugopal Iyer } 1289*0dc2366fSVenugopal Iyer 1290*0dc2366fSVenugopal Iyer /* 1291*0dc2366fSVenugopal Iyer * Ideally, we would want an ioctl to return list of ring-ids (or lane-ids) 1292*0dc2366fSVenugopal Iyer * for a given data-link (or mac client). We could then query for specific 1293*0dc2366fSVenugopal Iyer * kstats based on these ring-ids (lane-ids). 1294*0dc2366fSVenugopal Iyer * Ring-ids (or lane-ids) could be returned like any other link properties 1295*0dc2366fSVenugopal Iyer * queried by dladm show-linkprop. However, non-global zones do not have 1296*0dc2366fSVenugopal Iyer * access to this information today. 1297*0dc2366fSVenugopal Iyer * We thus opt for an implementation that relies heavily on kstat internals: 1298*0dc2366fSVenugopal Iyer * i_dlstat_*search routines and i_dlstat_get_idlist. 1299*0dc2366fSVenugopal Iyer */ 1300*0dc2366fSVenugopal Iyer /* rx hwlane specific */ 1301*0dc2366fSVenugopal Iyer static boolean_t 1302*0dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_search(kstat_t *ksp) 1303*0dc2366fSVenugopal Iyer { 1304*0dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 && 1305*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_rx") != 0 && 1306*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "hwlane") != 0 && 1307*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "fanout") == 0 && 1308*0dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0); 1309*0dc2366fSVenugopal Iyer } 1310*0dc2366fSVenugopal Iyer 1311*0dc2366fSVenugopal Iyer /* tx hwlane specific */ 1312*0dc2366fSVenugopal Iyer static boolean_t 1313*0dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_search(kstat_t *ksp) 1314*0dc2366fSVenugopal Iyer { 1315*0dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 && 1316*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_tx") != 0 && 1317*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "hwlane") != 0 && 1318*0dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0); 1319*0dc2366fSVenugopal Iyer } 1320*0dc2366fSVenugopal Iyer 1321*0dc2366fSVenugopal Iyer /* rx fanout specific */ 1322*0dc2366fSVenugopal Iyer static boolean_t 1323*0dc2366fSVenugopal Iyer i_dlstat_fanout_search(kstat_t *ksp) 1324*0dc2366fSVenugopal Iyer { 1325*0dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 && 1326*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_rx") != 0 && 1327*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "swlane") != 0 && 1328*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "fanout") != 0 && 1329*0dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0); 1330*0dc2366fSVenugopal Iyer } 1331*0dc2366fSVenugopal Iyer 1332*0dc2366fSVenugopal Iyer /* rx ring specific */ 1333*0dc2366fSVenugopal Iyer static boolean_t 1334*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_search(kstat_t *ksp) 1335*0dc2366fSVenugopal Iyer { 1336*0dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 && 1337*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_rx") != 0 && 1338*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "ring") != 0 && 1339*0dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0); 1340*0dc2366fSVenugopal Iyer } 1341*0dc2366fSVenugopal Iyer 1342*0dc2366fSVenugopal Iyer /* tx ring specific */ 1343*0dc2366fSVenugopal Iyer static boolean_t 1344*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_search(kstat_t *ksp) 1345*0dc2366fSVenugopal Iyer { 1346*0dc2366fSVenugopal Iyer return (ksp->ks_instance == 0) && 1347*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_tx") != 0 && 1348*0dc2366fSVenugopal Iyer strstr(ksp->ks_name, "ring") != 0 && 1349*0dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0; 1350*0dc2366fSVenugopal Iyer } 1351*0dc2366fSVenugopal Iyer 1352*0dc2366fSVenugopal Iyer typedef boolean_t dladm_search_kstat_t(kstat_t *); 1353*0dc2366fSVenugopal Iyer typedef struct dladm_extract_idlist_s { 1354*0dc2366fSVenugopal Iyer dlstat_idlist_type_t di_type; 1355*0dc2366fSVenugopal Iyer char *di_prefix; 1356*0dc2366fSVenugopal Iyer dladm_search_kstat_t *di_searchkstat; 1357*0dc2366fSVenugopal Iyer } dladm_extract_idlist_t; 1358*0dc2366fSVenugopal Iyer 1359*0dc2366fSVenugopal Iyer static dladm_extract_idlist_t dladm_extract_idlist[] = { 1360*0dc2366fSVenugopal Iyer { DLSTAT_RX_RING_IDLIST, DLSTAT_MAC_RX_RING, 1361*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_search}, 1362*0dc2366fSVenugopal Iyer { DLSTAT_TX_RING_IDLIST, DLSTAT_MAC_TX_RING, 1363*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_search}, 1364*0dc2366fSVenugopal Iyer { DLSTAT_RX_HWLANE_IDLIST, DLSTAT_MAC_RX_HWLANE, 1365*0dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_search}, 1366*0dc2366fSVenugopal Iyer { DLSTAT_TX_HWLANE_IDLIST, DLSTAT_MAC_TX_HWLANE, 1367*0dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_search}, 1368*0dc2366fSVenugopal Iyer { DLSTAT_FANOUT_IDLIST, DLSTAT_MAC_FANOUT, 1369*0dc2366fSVenugopal Iyer i_dlstat_fanout_search} 1370*0dc2366fSVenugopal Iyer }; 1371*0dc2366fSVenugopal Iyer 1372*0dc2366fSVenugopal Iyer static void 1373*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(const char *modname, dlstat_idlist_type_t idlist_type, 1374*0dc2366fSVenugopal Iyer uint_t idlist[], uint_t *size) 1375*0dc2366fSVenugopal Iyer { 1376*0dc2366fSVenugopal Iyer kstat_ctl_t *kcp; 1377*0dc2366fSVenugopal Iyer kstat_t *ksp; 1378*0dc2366fSVenugopal Iyer char *prefix; 1379*0dc2366fSVenugopal Iyer int prefixlen; 1380*0dc2366fSVenugopal Iyer boolean_t (*fptr_searchkstat)(kstat_t *); 1381*0dc2366fSVenugopal Iyer 1382*0dc2366fSVenugopal Iyer *size = 0; 1383*0dc2366fSVenugopal Iyer 1384*0dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) { 1385*0dc2366fSVenugopal Iyer warn("kstat_open operation failed"); 1386*0dc2366fSVenugopal Iyer goto done; 1387*0dc2366fSVenugopal Iyer } 1388*0dc2366fSVenugopal Iyer 1389*0dc2366fSVenugopal Iyer prefix = dladm_extract_idlist[idlist_type].di_prefix; 1390*0dc2366fSVenugopal Iyer fptr_searchkstat = dladm_extract_idlist[idlist_type].di_searchkstat; 1391*0dc2366fSVenugopal Iyer prefixlen = strlen(prefix); 1392*0dc2366fSVenugopal Iyer for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) { 1393*0dc2366fSVenugopal Iyer if ((strcmp(ksp->ks_module, modname) == 0) && 1394*0dc2366fSVenugopal Iyer fptr_searchkstat(ksp)) { 1395*0dc2366fSVenugopal Iyer idlist[(*size)++] = atoi(&ksp->ks_name[prefixlen]); 1396*0dc2366fSVenugopal Iyer } 1397*0dc2366fSVenugopal Iyer } 1398*0dc2366fSVenugopal Iyer dladm_sort_index_list(idlist, *size); 1399*0dc2366fSVenugopal Iyer 1400*0dc2366fSVenugopal Iyer done: 1401*0dc2366fSVenugopal Iyer (void) kstat_close(kcp); 1402*0dc2366fSVenugopal Iyer } 1403*0dc2366fSVenugopal Iyer 1404*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1405*0dc2366fSVenugopal Iyer i_dlstat_query_stats(const char *modname, const char *prefix, 1406*0dc2366fSVenugopal Iyer uint_t idlist[], uint_t idlist_size, 1407*0dc2366fSVenugopal Iyer void * (*fn)(kstat_ctl_t *, kstat_t *, int)) 1408*0dc2366fSVenugopal Iyer { 1409*0dc2366fSVenugopal Iyer kstat_ctl_t *kcp; 1410*0dc2366fSVenugopal Iyer kstat_t *ksp; 1411*0dc2366fSVenugopal Iyer char statname[MAXLINKNAMELEN]; 1412*0dc2366fSVenugopal Iyer int i = 0; 1413*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL, *prev = NULL; 1414*0dc2366fSVenugopal Iyer dladm_stat_chain_t *curr; 1415*0dc2366fSVenugopal Iyer 1416*0dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) { 1417*0dc2366fSVenugopal Iyer warn("kstat_open operation failed"); 1418*0dc2366fSVenugopal Iyer return (NULL); 1419*0dc2366fSVenugopal Iyer } 1420*0dc2366fSVenugopal Iyer 1421*0dc2366fSVenugopal Iyer for (i = 0; i < idlist_size; i++) { 1422*0dc2366fSVenugopal Iyer uint_t index = idlist[i]; 1423*0dc2366fSVenugopal Iyer 1424*0dc2366fSVenugopal Iyer (void) snprintf(statname, sizeof (statname), "%s%d", prefix, 1425*0dc2366fSVenugopal Iyer index); 1426*0dc2366fSVenugopal Iyer 1427*0dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, modname, 0, statname, NULL); 1428*0dc2366fSVenugopal Iyer if (ksp == NULL) 1429*0dc2366fSVenugopal Iyer continue; 1430*0dc2366fSVenugopal Iyer 1431*0dc2366fSVenugopal Iyer curr = malloc(sizeof (dladm_stat_chain_t)); 1432*0dc2366fSVenugopal Iyer if (curr == NULL) 1433*0dc2366fSVenugopal Iyer break; 1434*0dc2366fSVenugopal Iyer 1435*0dc2366fSVenugopal Iyer curr->dc_statentry = fn(kcp, ksp, index); 1436*0dc2366fSVenugopal Iyer if (curr->dc_statentry == NULL) { 1437*0dc2366fSVenugopal Iyer free(curr); 1438*0dc2366fSVenugopal Iyer break; 1439*0dc2366fSVenugopal Iyer } 1440*0dc2366fSVenugopal Iyer 1441*0dc2366fSVenugopal Iyer (void) strlcpy(curr->dc_statheader, statname, 1442*0dc2366fSVenugopal Iyer sizeof (curr->dc_statheader)); 1443*0dc2366fSVenugopal Iyer curr->dc_next = NULL; 1444*0dc2366fSVenugopal Iyer 1445*0dc2366fSVenugopal Iyer if (head == NULL) /* First node */ 1446*0dc2366fSVenugopal Iyer head = curr; 1447*0dc2366fSVenugopal Iyer else 1448*0dc2366fSVenugopal Iyer prev->dc_next = curr; 1449*0dc2366fSVenugopal Iyer 1450*0dc2366fSVenugopal Iyer prev = curr; 1451*0dc2366fSVenugopal Iyer } 1452*0dc2366fSVenugopal Iyer done: 1453*0dc2366fSVenugopal Iyer (void) kstat_close(kcp); 1454*0dc2366fSVenugopal Iyer return (head); 1455*0dc2366fSVenugopal Iyer } 1456*0dc2366fSVenugopal Iyer 1457*0dc2366fSVenugopal Iyer static misc_stat_entry_t * 1458*0dc2366fSVenugopal Iyer i_dlstat_misc_stats(const char *linkname) 1459*0dc2366fSVenugopal Iyer { 1460*0dc2366fSVenugopal Iyer kstat_ctl_t *kcp; 1461*0dc2366fSVenugopal Iyer kstat_t *ksp; 1462*0dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry = NULL; 1463*0dc2366fSVenugopal Iyer 1464*0dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) 1465*0dc2366fSVenugopal Iyer return (NULL); 1466*0dc2366fSVenugopal Iyer 1467*0dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, linkname, 0, DLSTAT_MAC_MISC_STAT, NULL); 1468*0dc2366fSVenugopal Iyer if (ksp == NULL) 1469*0dc2366fSVenugopal Iyer goto done; 1470*0dc2366fSVenugopal Iyer 1471*0dc2366fSVenugopal Iyer misc_stat_entry = calloc(1, sizeof (misc_stat_entry_t)); 1472*0dc2366fSVenugopal Iyer if (misc_stat_entry == NULL) 1473*0dc2366fSVenugopal Iyer goto done; 1474*0dc2366fSVenugopal Iyer 1475*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &misc_stat_entry->mse_stats, 1476*0dc2366fSVenugopal Iyer misc_stats_list, MISC_STAT_SIZE); 1477*0dc2366fSVenugopal Iyer done: 1478*0dc2366fSVenugopal Iyer (void) kstat_close(kcp); 1479*0dc2366fSVenugopal Iyer return (misc_stat_entry); 1480*0dc2366fSVenugopal Iyer } 1481*0dc2366fSVenugopal Iyer 1482*0dc2366fSVenugopal Iyer /* Rx lane statistic specific functions */ 1483*0dc2366fSVenugopal Iyer static boolean_t 1484*0dc2366fSVenugopal Iyer i_dlstat_rx_lane_match(void *arg1, void *arg2) 1485*0dc2366fSVenugopal Iyer { 1486*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s1 = arg1; 1487*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s2 = arg2; 1488*0dc2366fSVenugopal Iyer 1489*0dc2366fSVenugopal Iyer return (s1->rle_index == s2->rle_index && 1490*0dc2366fSVenugopal Iyer s1->rle_id == s2->rle_id); 1491*0dc2366fSVenugopal Iyer } 1492*0dc2366fSVenugopal Iyer 1493*0dc2366fSVenugopal Iyer static void * 1494*0dc2366fSVenugopal Iyer i_dlstat_rx_lane_stat_entry_diff(void *arg1, void *arg2) 1495*0dc2366fSVenugopal Iyer { 1496*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s1 = arg1; 1497*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s2 = arg2; 1498*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *diff_entry; 1499*0dc2366fSVenugopal Iyer 1500*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (rx_lane_stat_entry_t)); 1501*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 1502*0dc2366fSVenugopal Iyer goto done; 1503*0dc2366fSVenugopal Iyer 1504*0dc2366fSVenugopal Iyer diff_entry->rle_index = s1->rle_index; 1505*0dc2366fSVenugopal Iyer diff_entry->rle_id = s1->rle_id; 1506*0dc2366fSVenugopal Iyer 1507*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, rle_stats, rx_lane_stats_list, 1508*0dc2366fSVenugopal Iyer RX_LANE_STAT_SIZE); 1509*0dc2366fSVenugopal Iyer 1510*0dc2366fSVenugopal Iyer done: 1511*0dc2366fSVenugopal Iyer return (diff_entry); 1512*0dc2366fSVenugopal Iyer } 1513*0dc2366fSVenugopal Iyer 1514*0dc2366fSVenugopal Iyer static void * 1515*0dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 1516*0dc2366fSVenugopal Iyer { 1517*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 1518*0dc2366fSVenugopal Iyer 1519*0dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1520*0dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL) 1521*0dc2366fSVenugopal Iyer goto done; 1522*0dc2366fSVenugopal Iyer 1523*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = i; 1524*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_HWLANE; 1525*0dc2366fSVenugopal Iyer 1526*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats, 1527*0dc2366fSVenugopal Iyer rx_hwlane_stats_list, RX_HWLANE_STAT_SIZE); 1528*0dc2366fSVenugopal Iyer 1529*0dc2366fSVenugopal Iyer done: 1530*0dc2366fSVenugopal Iyer return (rx_lane_stat_entry); 1531*0dc2366fSVenugopal Iyer } 1532*0dc2366fSVenugopal Iyer 1533*0dc2366fSVenugopal Iyer /*ARGSUSED*/ 1534*0dc2366fSVenugopal Iyer static void * 1535*0dc2366fSVenugopal Iyer i_dlstat_rx_swlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 1536*0dc2366fSVenugopal Iyer { 1537*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 1538*0dc2366fSVenugopal Iyer 1539*0dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1540*0dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL) 1541*0dc2366fSVenugopal Iyer goto done; 1542*0dc2366fSVenugopal Iyer 1543*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY; 1544*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_SWLANE; 1545*0dc2366fSVenugopal Iyer 1546*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats, 1547*0dc2366fSVenugopal Iyer rx_swlane_stats_list, RX_SWLANE_STAT_SIZE); 1548*0dc2366fSVenugopal Iyer 1549*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets = 1550*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs; 1551*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes = 1552*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrbytes; 1553*0dc2366fSVenugopal Iyer done: 1554*0dc2366fSVenugopal Iyer return (rx_lane_stat_entry); 1555*0dc2366fSVenugopal Iyer } 1556*0dc2366fSVenugopal Iyer 1557*0dc2366fSVenugopal Iyer /*ARGSUSED*/ 1558*0dc2366fSVenugopal Iyer static void * 1559*0dc2366fSVenugopal Iyer i_dlstat_rx_local_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 1560*0dc2366fSVenugopal Iyer { 1561*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *local_stat_entry; 1562*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 1563*0dc2366fSVenugopal Iyer 1564*0dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1565*0dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL) 1566*0dc2366fSVenugopal Iyer goto done; 1567*0dc2366fSVenugopal Iyer 1568*0dc2366fSVenugopal Iyer local_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1569*0dc2366fSVenugopal Iyer if (local_stat_entry == NULL) 1570*0dc2366fSVenugopal Iyer goto done; 1571*0dc2366fSVenugopal Iyer 1572*0dc2366fSVenugopal Iyer local_stat_entry->rle_index = DLSTAT_INVALID_ENTRY; 1573*0dc2366fSVenugopal Iyer local_stat_entry->rle_id = L_LOCAL; 1574*0dc2366fSVenugopal Iyer 1575*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats, 1576*0dc2366fSVenugopal Iyer rx_swlane_stats_list, RX_SWLANE_STAT_SIZE); 1577*0dc2366fSVenugopal Iyer 1578*0dc2366fSVenugopal Iyer local_stat_entry->rle_stats.rl_ipackets = 1579*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_lclpackets; 1580*0dc2366fSVenugopal Iyer local_stat_entry->rle_stats.rl_rbytes = 1581*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_lclbytes; 1582*0dc2366fSVenugopal Iyer 1583*0dc2366fSVenugopal Iyer done: 1584*0dc2366fSVenugopal Iyer free(rx_lane_stat_entry); 1585*0dc2366fSVenugopal Iyer return (local_stat_entry); 1586*0dc2366fSVenugopal Iyer } 1587*0dc2366fSVenugopal Iyer 1588*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1589*0dc2366fSVenugopal Iyer i_dlstat_rx_local_stats(const char *linkname) 1590*0dc2366fSVenugopal Iyer { 1591*0dc2366fSVenugopal Iyer dladm_stat_chain_t *local_stats = NULL; 1592*0dc2366fSVenugopal Iyer 1593*0dc2366fSVenugopal Iyer local_stats = i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_SWLANE, 1594*0dc2366fSVenugopal Iyer default_idlist, default_idlist_size, 1595*0dc2366fSVenugopal Iyer i_dlstat_rx_local_retrieve_stat); 1596*0dc2366fSVenugopal Iyer 1597*0dc2366fSVenugopal Iyer if (local_stats != NULL) { 1598*0dc2366fSVenugopal Iyer (void) strlcpy(local_stats->dc_statheader, "mac_rx_local", 1599*0dc2366fSVenugopal Iyer sizeof (local_stats->dc_statheader)); 1600*0dc2366fSVenugopal Iyer } 1601*0dc2366fSVenugopal Iyer return (local_stats); 1602*0dc2366fSVenugopal Iyer } 1603*0dc2366fSVenugopal Iyer 1604*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1605*0dc2366fSVenugopal Iyer i_dlstat_rx_bcast_stats(const char *linkname) 1606*0dc2366fSVenugopal Iyer { 1607*0dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry; 1608*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1609*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 1610*0dc2366fSVenugopal Iyer 1611*0dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname); 1612*0dc2366fSVenugopal Iyer if (misc_stat_entry == NULL) 1613*0dc2366fSVenugopal Iyer goto done; 1614*0dc2366fSVenugopal Iyer 1615*0dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1616*0dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL) 1617*0dc2366fSVenugopal Iyer goto done; 1618*0dc2366fSVenugopal Iyer 1619*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY; 1620*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_BCAST; 1621*0dc2366fSVenugopal Iyer 1622*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets = 1623*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstrcv + 1624*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multircv; 1625*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs = 1626*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstrcv + 1627*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multircv; 1628*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes = 1629*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstrcvbytes + 1630*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multircvbytes; 1631*0dc2366fSVenugopal Iyer 1632*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 1633*0dc2366fSVenugopal Iyer if (head == NULL) { 1634*0dc2366fSVenugopal Iyer free(rx_lane_stat_entry); 1635*0dc2366fSVenugopal Iyer goto done; 1636*0dc2366fSVenugopal Iyer } 1637*0dc2366fSVenugopal Iyer 1638*0dc2366fSVenugopal Iyer head->dc_statentry = rx_lane_stat_entry; 1639*0dc2366fSVenugopal Iyer head->dc_next = NULL; 1640*0dc2366fSVenugopal Iyer 1641*0dc2366fSVenugopal Iyer free(misc_stat_entry); 1642*0dc2366fSVenugopal Iyer done: 1643*0dc2366fSVenugopal Iyer return (head); 1644*0dc2366fSVenugopal Iyer } 1645*0dc2366fSVenugopal Iyer 1646*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1647*0dc2366fSVenugopal Iyer i_dlstat_rx_defunctlane_stats(const char *linkname) 1648*0dc2366fSVenugopal Iyer { 1649*0dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry; 1650*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1651*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 1652*0dc2366fSVenugopal Iyer 1653*0dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname); 1654*0dc2366fSVenugopal Iyer if (misc_stat_entry == NULL) 1655*0dc2366fSVenugopal Iyer goto done; 1656*0dc2366fSVenugopal Iyer 1657*0dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t)); 1658*0dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL) 1659*0dc2366fSVenugopal Iyer goto done; 1660*0dc2366fSVenugopal Iyer 1661*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY; 1662*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_DFNCT; 1663*0dc2366fSVenugopal Iyer 1664*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets = 1665*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_ipackets; 1666*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes = 1667*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_rbytes; 1668*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs = 1669*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_intrs; 1670*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_polls = 1671*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_polls; 1672*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_sdrops = 1673*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_rxsdrops; 1674*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_chl10 = 1675*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_chainunder10; 1676*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ch10_50 = 1677*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_chain10to50; 1678*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_chg50 = 1679*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_chainover50; 1680*0dc2366fSVenugopal Iyer 1681*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 1682*0dc2366fSVenugopal Iyer if (head == NULL) { 1683*0dc2366fSVenugopal Iyer free(rx_lane_stat_entry); 1684*0dc2366fSVenugopal Iyer goto done; 1685*0dc2366fSVenugopal Iyer } 1686*0dc2366fSVenugopal Iyer 1687*0dc2366fSVenugopal Iyer head->dc_statentry = rx_lane_stat_entry; 1688*0dc2366fSVenugopal Iyer head->dc_next = NULL; 1689*0dc2366fSVenugopal Iyer 1690*0dc2366fSVenugopal Iyer done: 1691*0dc2366fSVenugopal Iyer return (head); 1692*0dc2366fSVenugopal Iyer } 1693*0dc2366fSVenugopal Iyer 1694*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1695*0dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_stats(const char *linkname) 1696*0dc2366fSVenugopal Iyer { 1697*0dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist[MAX_RINGS_PER_GROUP]; 1698*0dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist_size; 1699*0dc2366fSVenugopal Iyer 1700*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_RX_HWLANE_IDLIST, 1701*0dc2366fSVenugopal Iyer rx_hwlane_idlist, &rx_hwlane_idlist_size); 1702*0dc2366fSVenugopal Iyer 1703*0dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_HWLANE, 1704*0dc2366fSVenugopal Iyer rx_hwlane_idlist, rx_hwlane_idlist_size, 1705*0dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_retrieve_stat)); 1706*0dc2366fSVenugopal Iyer } 1707*0dc2366fSVenugopal Iyer 1708*0dc2366fSVenugopal Iyer /*ARGSUSED*/ 1709*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1710*0dc2366fSVenugopal Iyer i_dlstat_rx_swlane_stats(dladm_handle_t dh, datalink_id_t linkid, 1711*0dc2366fSVenugopal Iyer const char *linkname) 1712*0dc2366fSVenugopal Iyer { 1713*0dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_SWLANE, 1714*0dc2366fSVenugopal Iyer default_idlist, default_idlist_size, 1715*0dc2366fSVenugopal Iyer i_dlstat_rx_swlane_retrieve_stat)); 1716*0dc2366fSVenugopal Iyer } 1717*0dc2366fSVenugopal Iyer 1718*0dc2366fSVenugopal Iyer void * 1719*0dc2366fSVenugopal Iyer dlstat_rx_lane_stats(dladm_handle_t dh, datalink_id_t linkid) 1720*0dc2366fSVenugopal Iyer { 1721*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1722*0dc2366fSVenugopal Iyer dladm_stat_chain_t *local_stats = NULL; 1723*0dc2366fSVenugopal Iyer dladm_stat_chain_t *bcast_stats = NULL; 1724*0dc2366fSVenugopal Iyer dladm_stat_chain_t *defunctlane_stats = NULL; 1725*0dc2366fSVenugopal Iyer dladm_stat_chain_t *lane_stats = NULL; 1726*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 1727*0dc2366fSVenugopal Iyer boolean_t is_legacy_driver; 1728*0dc2366fSVenugopal Iyer 1729*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname, 1730*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 1731*0dc2366fSVenugopal Iyer goto done; 1732*0dc2366fSVenugopal Iyer } 1733*0dc2366fSVenugopal Iyer 1734*0dc2366fSVenugopal Iyer /* Check if it is legacy driver */ 1735*0dc2366fSVenugopal Iyer if (dladm_linkprop_is_set(dh, linkid, DLADM_PROP_VAL_CURRENT, 1736*0dc2366fSVenugopal Iyer "_softmac", &is_legacy_driver) != DLADM_STATUS_OK) { 1737*0dc2366fSVenugopal Iyer goto done; 1738*0dc2366fSVenugopal Iyer } 1739*0dc2366fSVenugopal Iyer 1740*0dc2366fSVenugopal Iyer if (is_legacy_driver) { 1741*0dc2366fSVenugopal Iyer head = i_dlstat_legacy_rx_lane_stats(linkname); 1742*0dc2366fSVenugopal Iyer goto done; 1743*0dc2366fSVenugopal Iyer } 1744*0dc2366fSVenugopal Iyer 1745*0dc2366fSVenugopal Iyer local_stats = i_dlstat_rx_local_stats(linkname); 1746*0dc2366fSVenugopal Iyer bcast_stats = i_dlstat_rx_bcast_stats(linkname); 1747*0dc2366fSVenugopal Iyer defunctlane_stats = i_dlstat_rx_defunctlane_stats(linkname); 1748*0dc2366fSVenugopal Iyer lane_stats = i_dlstat_rx_hwlane_stats(linkname); 1749*0dc2366fSVenugopal Iyer if (lane_stats == NULL) 1750*0dc2366fSVenugopal Iyer lane_stats = i_dlstat_rx_swlane_stats(dh, linkid, linkname); 1751*0dc2366fSVenugopal Iyer 1752*0dc2366fSVenugopal Iyer head = i_dlstat_join_lists(local_stats, bcast_stats); 1753*0dc2366fSVenugopal Iyer head = i_dlstat_join_lists(head, defunctlane_stats); 1754*0dc2366fSVenugopal Iyer head = i_dlstat_join_lists(head, lane_stats); 1755*0dc2366fSVenugopal Iyer done: 1756*0dc2366fSVenugopal Iyer return (head); 1757*0dc2366fSVenugopal Iyer } 1758*0dc2366fSVenugopal Iyer 1759*0dc2366fSVenugopal Iyer /* Tx lane statistic specific functions */ 1760*0dc2366fSVenugopal Iyer static boolean_t 1761*0dc2366fSVenugopal Iyer i_dlstat_tx_lane_match(void *arg1, void *arg2) 1762*0dc2366fSVenugopal Iyer { 1763*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s1 = arg1; 1764*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s2 = arg2; 1765*0dc2366fSVenugopal Iyer 1766*0dc2366fSVenugopal Iyer return (s1->tle_index == s2->tle_index && 1767*0dc2366fSVenugopal Iyer s1->tle_id == s2->tle_id); 1768*0dc2366fSVenugopal Iyer } 1769*0dc2366fSVenugopal Iyer 1770*0dc2366fSVenugopal Iyer static void * 1771*0dc2366fSVenugopal Iyer i_dlstat_tx_lane_stat_entry_diff(void *arg1, void *arg2) 1772*0dc2366fSVenugopal Iyer { 1773*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s1 = arg1; 1774*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s2 = arg2; 1775*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *diff_entry; 1776*0dc2366fSVenugopal Iyer 1777*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (tx_lane_stat_entry_t)); 1778*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 1779*0dc2366fSVenugopal Iyer goto done; 1780*0dc2366fSVenugopal Iyer 1781*0dc2366fSVenugopal Iyer diff_entry->tle_index = s1->tle_index; 1782*0dc2366fSVenugopal Iyer diff_entry->tle_id = s1->tle_id; 1783*0dc2366fSVenugopal Iyer 1784*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, tle_stats, tx_lane_stats_list, 1785*0dc2366fSVenugopal Iyer TX_LANE_STAT_SIZE); 1786*0dc2366fSVenugopal Iyer 1787*0dc2366fSVenugopal Iyer done: 1788*0dc2366fSVenugopal Iyer return (diff_entry); 1789*0dc2366fSVenugopal Iyer } 1790*0dc2366fSVenugopal Iyer 1791*0dc2366fSVenugopal Iyer static void * 1792*0dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 1793*0dc2366fSVenugopal Iyer { 1794*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry; 1795*0dc2366fSVenugopal Iyer 1796*0dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t)); 1797*0dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL) 1798*0dc2366fSVenugopal Iyer goto done; 1799*0dc2366fSVenugopal Iyer 1800*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = i; 1801*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_HWLANE; 1802*0dc2366fSVenugopal Iyer 1803*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &tx_lane_stat_entry->tle_stats, 1804*0dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE); 1805*0dc2366fSVenugopal Iyer 1806*0dc2366fSVenugopal Iyer done: 1807*0dc2366fSVenugopal Iyer return (tx_lane_stat_entry); 1808*0dc2366fSVenugopal Iyer } 1809*0dc2366fSVenugopal Iyer 1810*0dc2366fSVenugopal Iyer /*ARGSUSED*/ 1811*0dc2366fSVenugopal Iyer static void * 1812*0dc2366fSVenugopal Iyer i_dlstat_tx_swlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 1813*0dc2366fSVenugopal Iyer { 1814*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry; 1815*0dc2366fSVenugopal Iyer 1816*0dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t)); 1817*0dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL) 1818*0dc2366fSVenugopal Iyer goto done; 1819*0dc2366fSVenugopal Iyer 1820*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY; 1821*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_SWLANE; 1822*0dc2366fSVenugopal Iyer 1823*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &tx_lane_stat_entry->tle_stats, 1824*0dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE); 1825*0dc2366fSVenugopal Iyer 1826*0dc2366fSVenugopal Iyer done: 1827*0dc2366fSVenugopal Iyer return (tx_lane_stat_entry); 1828*0dc2366fSVenugopal Iyer } 1829*0dc2366fSVenugopal Iyer 1830*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1831*0dc2366fSVenugopal Iyer i_dlstat_tx_bcast_stats(const char *linkname) 1832*0dc2366fSVenugopal Iyer { 1833*0dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry; 1834*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1835*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry; 1836*0dc2366fSVenugopal Iyer 1837*0dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname); 1838*0dc2366fSVenugopal Iyer if (misc_stat_entry == NULL) 1839*0dc2366fSVenugopal Iyer goto done; 1840*0dc2366fSVenugopal Iyer 1841*0dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t)); 1842*0dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL) 1843*0dc2366fSVenugopal Iyer goto done; 1844*0dc2366fSVenugopal Iyer 1845*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY; 1846*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_BCAST; 1847*0dc2366fSVenugopal Iyer 1848*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets = 1849*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstxmt + 1850*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multixmt; 1851*0dc2366fSVenugopal Iyer 1852*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes = 1853*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstxmtbytes + 1854*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multixmtbytes; 1855*0dc2366fSVenugopal Iyer 1856*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 1857*0dc2366fSVenugopal Iyer if (head == NULL) { 1858*0dc2366fSVenugopal Iyer free(tx_lane_stat_entry); 1859*0dc2366fSVenugopal Iyer goto done; 1860*0dc2366fSVenugopal Iyer } 1861*0dc2366fSVenugopal Iyer 1862*0dc2366fSVenugopal Iyer head->dc_statentry = tx_lane_stat_entry; 1863*0dc2366fSVenugopal Iyer head->dc_next = NULL; 1864*0dc2366fSVenugopal Iyer 1865*0dc2366fSVenugopal Iyer free(misc_stat_entry); 1866*0dc2366fSVenugopal Iyer done: 1867*0dc2366fSVenugopal Iyer return (head); 1868*0dc2366fSVenugopal Iyer } 1869*0dc2366fSVenugopal Iyer 1870*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1871*0dc2366fSVenugopal Iyer i_dlstat_tx_defunctlane_stats(const char *linkname) 1872*0dc2366fSVenugopal Iyer { 1873*0dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry; 1874*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1875*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry; 1876*0dc2366fSVenugopal Iyer 1877*0dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname); 1878*0dc2366fSVenugopal Iyer if (misc_stat_entry == NULL) 1879*0dc2366fSVenugopal Iyer goto done; 1880*0dc2366fSVenugopal Iyer 1881*0dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t)); 1882*0dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL) 1883*0dc2366fSVenugopal Iyer goto done; 1884*0dc2366fSVenugopal Iyer 1885*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY; 1886*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_DFNCT; 1887*0dc2366fSVenugopal Iyer 1888*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets = 1889*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_opackets; 1890*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes = 1891*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_obytes; 1892*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_sdrops = 1893*0dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_txsdrops; 1894*0dc2366fSVenugopal Iyer 1895*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 1896*0dc2366fSVenugopal Iyer if (head == NULL) { 1897*0dc2366fSVenugopal Iyer free(tx_lane_stat_entry); 1898*0dc2366fSVenugopal Iyer goto done; 1899*0dc2366fSVenugopal Iyer } 1900*0dc2366fSVenugopal Iyer 1901*0dc2366fSVenugopal Iyer head->dc_statentry = tx_lane_stat_entry; 1902*0dc2366fSVenugopal Iyer head->dc_next = NULL; 1903*0dc2366fSVenugopal Iyer 1904*0dc2366fSVenugopal Iyer done: 1905*0dc2366fSVenugopal Iyer return (head); 1906*0dc2366fSVenugopal Iyer } 1907*0dc2366fSVenugopal Iyer 1908*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1909*0dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_stats(const char *linkname) 1910*0dc2366fSVenugopal Iyer { 1911*0dc2366fSVenugopal Iyer uint_t tx_hwlane_idlist[MAX_RINGS_PER_GROUP]; 1912*0dc2366fSVenugopal Iyer uint_t tx_hwlane_idlist_size; 1913*0dc2366fSVenugopal Iyer 1914*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_TX_HWLANE_IDLIST, 1915*0dc2366fSVenugopal Iyer tx_hwlane_idlist, &tx_hwlane_idlist_size); 1916*0dc2366fSVenugopal Iyer 1917*0dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_TX_HWLANE, 1918*0dc2366fSVenugopal Iyer tx_hwlane_idlist, tx_hwlane_idlist_size, 1919*0dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_retrieve_stat)); 1920*0dc2366fSVenugopal Iyer } 1921*0dc2366fSVenugopal Iyer 1922*0dc2366fSVenugopal Iyer /*ARGSUSED*/ 1923*0dc2366fSVenugopal Iyer static dladm_stat_chain_t * 1924*0dc2366fSVenugopal Iyer i_dlstat_tx_swlane_stats(dladm_handle_t dh, datalink_id_t linkid, 1925*0dc2366fSVenugopal Iyer const char *linkname) 1926*0dc2366fSVenugopal Iyer { 1927*0dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_TX_SWLANE, 1928*0dc2366fSVenugopal Iyer default_idlist, default_idlist_size, 1929*0dc2366fSVenugopal Iyer i_dlstat_tx_swlane_retrieve_stat)); 1930*0dc2366fSVenugopal Iyer } 1931*0dc2366fSVenugopal Iyer 1932*0dc2366fSVenugopal Iyer void * 1933*0dc2366fSVenugopal Iyer dlstat_tx_lane_stats(dladm_handle_t dh, datalink_id_t linkid) 1934*0dc2366fSVenugopal Iyer { 1935*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 1936*0dc2366fSVenugopal Iyer dladm_stat_chain_t *bcast_stats = NULL; 1937*0dc2366fSVenugopal Iyer dladm_stat_chain_t *defunctlane_stats = NULL; 1938*0dc2366fSVenugopal Iyer dladm_stat_chain_t *lane_stats; 1939*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 1940*0dc2366fSVenugopal Iyer boolean_t is_legacy_driver; 1941*0dc2366fSVenugopal Iyer 1942*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname, 1943*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 1944*0dc2366fSVenugopal Iyer goto done; 1945*0dc2366fSVenugopal Iyer } 1946*0dc2366fSVenugopal Iyer 1947*0dc2366fSVenugopal Iyer /* Check if it is legacy driver */ 1948*0dc2366fSVenugopal Iyer if (dladm_linkprop_is_set(dh, linkid, DLADM_PROP_VAL_CURRENT, 1949*0dc2366fSVenugopal Iyer "_softmac", &is_legacy_driver) != DLADM_STATUS_OK) { 1950*0dc2366fSVenugopal Iyer goto done; 1951*0dc2366fSVenugopal Iyer } 1952*0dc2366fSVenugopal Iyer 1953*0dc2366fSVenugopal Iyer if (is_legacy_driver) { 1954*0dc2366fSVenugopal Iyer head = i_dlstat_legacy_tx_lane_stats(linkname); 1955*0dc2366fSVenugopal Iyer goto done; 1956*0dc2366fSVenugopal Iyer } 1957*0dc2366fSVenugopal Iyer 1958*0dc2366fSVenugopal Iyer bcast_stats = i_dlstat_tx_bcast_stats(linkname); 1959*0dc2366fSVenugopal Iyer defunctlane_stats = i_dlstat_tx_defunctlane_stats(linkname); 1960*0dc2366fSVenugopal Iyer lane_stats = i_dlstat_tx_hwlane_stats(linkname); 1961*0dc2366fSVenugopal Iyer if (lane_stats == NULL) 1962*0dc2366fSVenugopal Iyer lane_stats = i_dlstat_tx_swlane_stats(dh, linkid, linkname); 1963*0dc2366fSVenugopal Iyer 1964*0dc2366fSVenugopal Iyer head = i_dlstat_join_lists(bcast_stats, defunctlane_stats); 1965*0dc2366fSVenugopal Iyer head = i_dlstat_join_lists(head, lane_stats); 1966*0dc2366fSVenugopal Iyer 1967*0dc2366fSVenugopal Iyer done: 1968*0dc2366fSVenugopal Iyer return (head); 1969*0dc2366fSVenugopal Iyer } 1970*0dc2366fSVenugopal Iyer 1971*0dc2366fSVenugopal Iyer /* Rx lane total statistic specific functions */ 1972*0dc2366fSVenugopal Iyer void * 1973*0dc2366fSVenugopal Iyer dlstat_rx_lane_total_stats(dladm_handle_t dh, datalink_id_t linkid) 1974*0dc2366fSVenugopal Iyer { 1975*0dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL; 1976*0dc2366fSVenugopal Iyer dladm_stat_chain_t *rx_lane_head, *curr; 1977*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *total_stats; 1978*0dc2366fSVenugopal Iyer 1979*0dc2366fSVenugopal Iyer /* Get per rx lane stats */ 1980*0dc2366fSVenugopal Iyer rx_lane_head = dlstat_rx_lane_stats(dh, linkid); 1981*0dc2366fSVenugopal Iyer if (rx_lane_head == NULL) 1982*0dc2366fSVenugopal Iyer goto done; 1983*0dc2366fSVenugopal Iyer 1984*0dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (rx_lane_stat_entry_t)); 1985*0dc2366fSVenugopal Iyer if (total_stats == NULL) 1986*0dc2366fSVenugopal Iyer goto done; 1987*0dc2366fSVenugopal Iyer 1988*0dc2366fSVenugopal Iyer total_stats->rle_index = DLSTAT_INVALID_ENTRY; 1989*0dc2366fSVenugopal Iyer total_stats->rle_id = DLSTAT_INVALID_ENTRY; 1990*0dc2366fSVenugopal Iyer 1991*0dc2366fSVenugopal Iyer for (curr = rx_lane_head; curr != NULL; curr = curr->dc_next) { 1992*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *curr_lane_stats = curr->dc_statentry; 1993*0dc2366fSVenugopal Iyer 1994*0dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->rle_stats, 1995*0dc2366fSVenugopal Iyer &curr_lane_stats->rle_stats, &total_stats->rle_stats, 1996*0dc2366fSVenugopal Iyer rx_lane_stats_list, RX_LANE_STAT_SIZE); 1997*0dc2366fSVenugopal Iyer } 1998*0dc2366fSVenugopal Iyer 1999*0dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t)); 2000*0dc2366fSVenugopal Iyer if (total_head == NULL) { 2001*0dc2366fSVenugopal Iyer free(total_stats); 2002*0dc2366fSVenugopal Iyer goto done; 2003*0dc2366fSVenugopal Iyer } 2004*0dc2366fSVenugopal Iyer 2005*0dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats; 2006*0dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_rx_lane_total", 2007*0dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader)); 2008*0dc2366fSVenugopal Iyer total_head->dc_next = NULL; 2009*0dc2366fSVenugopal Iyer free(rx_lane_head); 2010*0dc2366fSVenugopal Iyer 2011*0dc2366fSVenugopal Iyer done: 2012*0dc2366fSVenugopal Iyer return (total_head); 2013*0dc2366fSVenugopal Iyer } 2014*0dc2366fSVenugopal Iyer 2015*0dc2366fSVenugopal Iyer /* Tx lane total statistic specific functions */ 2016*0dc2366fSVenugopal Iyer void * 2017*0dc2366fSVenugopal Iyer dlstat_tx_lane_total_stats(dladm_handle_t dh, datalink_id_t linkid) 2018*0dc2366fSVenugopal Iyer { 2019*0dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL; 2020*0dc2366fSVenugopal Iyer dladm_stat_chain_t *tx_lane_head, *curr; 2021*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *total_stats; 2022*0dc2366fSVenugopal Iyer 2023*0dc2366fSVenugopal Iyer /* Get per tx lane stats */ 2024*0dc2366fSVenugopal Iyer tx_lane_head = dlstat_tx_lane_stats(dh, linkid); 2025*0dc2366fSVenugopal Iyer if (tx_lane_head == NULL) 2026*0dc2366fSVenugopal Iyer goto done; 2027*0dc2366fSVenugopal Iyer 2028*0dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (tx_lane_stat_entry_t)); 2029*0dc2366fSVenugopal Iyer if (total_stats == NULL) 2030*0dc2366fSVenugopal Iyer goto done; 2031*0dc2366fSVenugopal Iyer 2032*0dc2366fSVenugopal Iyer total_stats->tle_index = DLSTAT_INVALID_ENTRY; 2033*0dc2366fSVenugopal Iyer total_stats->tle_id = DLSTAT_INVALID_ENTRY; 2034*0dc2366fSVenugopal Iyer 2035*0dc2366fSVenugopal Iyer for (curr = tx_lane_head; curr != NULL; curr = curr->dc_next) { 2036*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *curr_lane_stats = curr->dc_statentry; 2037*0dc2366fSVenugopal Iyer 2038*0dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->tle_stats, 2039*0dc2366fSVenugopal Iyer &curr_lane_stats->tle_stats, &total_stats->tle_stats, 2040*0dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE); 2041*0dc2366fSVenugopal Iyer } 2042*0dc2366fSVenugopal Iyer 2043*0dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t)); 2044*0dc2366fSVenugopal Iyer if (total_head == NULL) { 2045*0dc2366fSVenugopal Iyer free(total_stats); 2046*0dc2366fSVenugopal Iyer goto done; 2047*0dc2366fSVenugopal Iyer } 2048*0dc2366fSVenugopal Iyer 2049*0dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats; 2050*0dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_tx_lane_total", 2051*0dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader)); 2052*0dc2366fSVenugopal Iyer total_head->dc_next = NULL; 2053*0dc2366fSVenugopal Iyer free(tx_lane_head); 2054*0dc2366fSVenugopal Iyer 2055*0dc2366fSVenugopal Iyer done: 2056*0dc2366fSVenugopal Iyer return (total_head); 2057*0dc2366fSVenugopal Iyer } 2058*0dc2366fSVenugopal Iyer 2059*0dc2366fSVenugopal Iyer /* Fanout specific functions */ 2060*0dc2366fSVenugopal Iyer static boolean_t 2061*0dc2366fSVenugopal Iyer i_dlstat_fanout_match(void *arg1, void *arg2) 2062*0dc2366fSVenugopal Iyer { 2063*0dc2366fSVenugopal Iyer fanout_stat_entry_t *s1 = arg1; 2064*0dc2366fSVenugopal Iyer fanout_stat_entry_t *s2 = arg2; 2065*0dc2366fSVenugopal Iyer 2066*0dc2366fSVenugopal Iyer return (s1->fe_index == s2->fe_index && 2067*0dc2366fSVenugopal Iyer s1->fe_id == s2->fe_id && 2068*0dc2366fSVenugopal Iyer s1->fe_foutindex == s2->fe_foutindex); 2069*0dc2366fSVenugopal Iyer } 2070*0dc2366fSVenugopal Iyer 2071*0dc2366fSVenugopal Iyer static void * 2072*0dc2366fSVenugopal Iyer i_dlstat_fanout_stat_entry_diff(void *arg1, void *arg2) 2073*0dc2366fSVenugopal Iyer { 2074*0dc2366fSVenugopal Iyer fanout_stat_entry_t *s1 = arg1; 2075*0dc2366fSVenugopal Iyer fanout_stat_entry_t *s2 = arg2; 2076*0dc2366fSVenugopal Iyer fanout_stat_entry_t *diff_entry; 2077*0dc2366fSVenugopal Iyer 2078*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (fanout_stat_entry_t)); 2079*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 2080*0dc2366fSVenugopal Iyer goto done; 2081*0dc2366fSVenugopal Iyer 2082*0dc2366fSVenugopal Iyer diff_entry->fe_index = s1->fe_index; 2083*0dc2366fSVenugopal Iyer diff_entry->fe_id = s1->fe_id; 2084*0dc2366fSVenugopal Iyer diff_entry->fe_foutindex = s1->fe_foutindex; 2085*0dc2366fSVenugopal Iyer 2086*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, fe_stats, fanout_stats_list, 2087*0dc2366fSVenugopal Iyer FANOUT_STAT_SIZE); 2088*0dc2366fSVenugopal Iyer 2089*0dc2366fSVenugopal Iyer done: 2090*0dc2366fSVenugopal Iyer return (diff_entry); 2091*0dc2366fSVenugopal Iyer } 2092*0dc2366fSVenugopal Iyer 2093*0dc2366fSVenugopal Iyer static void * 2094*0dc2366fSVenugopal Iyer i_dlstat_fanout_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 2095*0dc2366fSVenugopal Iyer { 2096*0dc2366fSVenugopal Iyer fanout_stat_entry_t *fanout_stat_entry; 2097*0dc2366fSVenugopal Iyer 2098*0dc2366fSVenugopal Iyer fanout_stat_entry = calloc(1, sizeof (fanout_stat_entry_t)); 2099*0dc2366fSVenugopal Iyer if (fanout_stat_entry == NULL) 2100*0dc2366fSVenugopal Iyer goto done; 2101*0dc2366fSVenugopal Iyer 2102*0dc2366fSVenugopal Iyer /* Set by the caller later */ 2103*0dc2366fSVenugopal Iyer fanout_stat_entry->fe_index = DLSTAT_INVALID_ENTRY; 2104*0dc2366fSVenugopal Iyer fanout_stat_entry->fe_id = DLSTAT_INVALID_ENTRY; 2105*0dc2366fSVenugopal Iyer 2106*0dc2366fSVenugopal Iyer fanout_stat_entry->fe_foutindex = i; 2107*0dc2366fSVenugopal Iyer 2108*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &fanout_stat_entry->fe_stats, 2109*0dc2366fSVenugopal Iyer fanout_stats_list, FANOUT_STAT_SIZE); 2110*0dc2366fSVenugopal Iyer 2111*0dc2366fSVenugopal Iyer done: 2112*0dc2366fSVenugopal Iyer return (fanout_stat_entry); 2113*0dc2366fSVenugopal Iyer } 2114*0dc2366fSVenugopal Iyer 2115*0dc2366fSVenugopal Iyer static void * 2116*0dc2366fSVenugopal Iyer i_dlstat_query_fanout_stats(dladm_handle_t dh, datalink_id_t linkid, 2117*0dc2366fSVenugopal Iyer uint_t idlist[], uint_t idlist_size, 2118*0dc2366fSVenugopal Iyer const char *modname, const char *prefix) 2119*0dc2366fSVenugopal Iyer { 2120*0dc2366fSVenugopal Iyer int i; 2121*0dc2366fSVenugopal Iyer char statprefix[MAXLINKNAMELEN]; 2122*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 2123*0dc2366fSVenugopal Iyer dladm_stat_chain_t *curr, *curr_head; 2124*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL, *prev = NULL; 2125*0dc2366fSVenugopal Iyer uint_t fanout_idlist[MAX_RINGS_PER_GROUP]; 2126*0dc2366fSVenugopal Iyer uint_t fanout_idlist_size; 2127*0dc2366fSVenugopal Iyer 2128*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname, 2129*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2130*0dc2366fSVenugopal Iyer return (NULL); 2131*0dc2366fSVenugopal Iyer } 2132*0dc2366fSVenugopal Iyer 2133*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_FANOUT_IDLIST, 2134*0dc2366fSVenugopal Iyer fanout_idlist, &fanout_idlist_size); 2135*0dc2366fSVenugopal Iyer 2136*0dc2366fSVenugopal Iyer for (i = 0; i < idlist_size; i++) { 2137*0dc2366fSVenugopal Iyer uint_t index = idlist[i]; 2138*0dc2366fSVenugopal Iyer 2139*0dc2366fSVenugopal Iyer (void) snprintf(statprefix, sizeof (statprefix), "%s%d_fanout", 2140*0dc2366fSVenugopal Iyer prefix, index); 2141*0dc2366fSVenugopal Iyer 2142*0dc2366fSVenugopal Iyer curr_head = i_dlstat_query_stats(modname, statprefix, 2143*0dc2366fSVenugopal Iyer fanout_idlist, fanout_idlist_size, 2144*0dc2366fSVenugopal Iyer i_dlstat_fanout_retrieve_stat); 2145*0dc2366fSVenugopal Iyer 2146*0dc2366fSVenugopal Iyer if (curr_head == NULL) /* Last lane */ 2147*0dc2366fSVenugopal Iyer break; 2148*0dc2366fSVenugopal Iyer 2149*0dc2366fSVenugopal Iyer if (head == NULL) /* First lane */ 2150*0dc2366fSVenugopal Iyer head = curr_head; 2151*0dc2366fSVenugopal Iyer else /* Link new lane list to end of previous lane list */ 2152*0dc2366fSVenugopal Iyer prev->dc_next = curr_head; 2153*0dc2366fSVenugopal Iyer 2154*0dc2366fSVenugopal Iyer /* Walk new lane list and set ids */ 2155*0dc2366fSVenugopal Iyer for (curr = curr_head; curr != NULL; curr = curr->dc_next) { 2156*0dc2366fSVenugopal Iyer fanout_stat_entry_t *curr_stats = curr->dc_statentry; 2157*0dc2366fSVenugopal Iyer 2158*0dc2366fSVenugopal Iyer curr_stats->fe_index = index; 2159*0dc2366fSVenugopal Iyer curr_stats->fe_id = L_HWLANE; 2160*0dc2366fSVenugopal Iyer /* 2161*0dc2366fSVenugopal Iyer * Save last pointer of previous linked list. 2162*0dc2366fSVenugopal Iyer * This pointer is used to chain linked lists 2163*0dc2366fSVenugopal Iyer * generated in each iteration. 2164*0dc2366fSVenugopal Iyer */ 2165*0dc2366fSVenugopal Iyer prev = curr; 2166*0dc2366fSVenugopal Iyer } 2167*0dc2366fSVenugopal Iyer } 2168*0dc2366fSVenugopal Iyer 2169*0dc2366fSVenugopal Iyer return (head); 2170*0dc2366fSVenugopal Iyer } 2171*0dc2366fSVenugopal Iyer 2172*0dc2366fSVenugopal Iyer void * 2173*0dc2366fSVenugopal Iyer dlstat_fanout_swlane_and_local_stats(dladm_handle_t dh, datalink_id_t linkid, 2174*0dc2366fSVenugopal Iyer const char *linkname) 2175*0dc2366fSVenugopal Iyer { 2176*0dc2366fSVenugopal Iyer return (i_dlstat_query_fanout_stats(dh, linkid, 2177*0dc2366fSVenugopal Iyer default_idlist, default_idlist_size, linkname, 2178*0dc2366fSVenugopal Iyer DLSTAT_MAC_RX_SWLANE)); 2179*0dc2366fSVenugopal Iyer } 2180*0dc2366fSVenugopal Iyer 2181*0dc2366fSVenugopal Iyer void * 2182*0dc2366fSVenugopal Iyer dlstat_fanout_hwlane_stats(dladm_handle_t dh, datalink_id_t linkid, 2183*0dc2366fSVenugopal Iyer const char *linkname) 2184*0dc2366fSVenugopal Iyer { 2185*0dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist[MAX_RINGS_PER_GROUP]; 2186*0dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist_size; 2187*0dc2366fSVenugopal Iyer 2188*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_RX_HWLANE_IDLIST, 2189*0dc2366fSVenugopal Iyer rx_hwlane_idlist, &rx_hwlane_idlist_size); 2190*0dc2366fSVenugopal Iyer 2191*0dc2366fSVenugopal Iyer return (i_dlstat_query_fanout_stats(dh, linkid, rx_hwlane_idlist, 2192*0dc2366fSVenugopal Iyer rx_hwlane_idlist_size, linkname, DLSTAT_MAC_RX_HWLANE)); 2193*0dc2366fSVenugopal Iyer } 2194*0dc2366fSVenugopal Iyer 2195*0dc2366fSVenugopal Iyer void * 2196*0dc2366fSVenugopal Iyer dlstat_fanout_stats(dladm_handle_t dh, datalink_id_t linkid) 2197*0dc2366fSVenugopal Iyer { 2198*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 2199*0dc2366fSVenugopal Iyer dladm_stat_chain_t *fout_hwlane_stats; 2200*0dc2366fSVenugopal Iyer dladm_stat_chain_t *fout_swlane_and_local_stats; 2201*0dc2366fSVenugopal Iyer fanout_stat_entry_t *fout_stats; 2202*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 2203*0dc2366fSVenugopal Iyer 2204*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname, 2205*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2206*0dc2366fSVenugopal Iyer goto done; 2207*0dc2366fSVenugopal Iyer } 2208*0dc2366fSVenugopal Iyer 2209*0dc2366fSVenugopal Iyer fout_swlane_and_local_stats = 2210*0dc2366fSVenugopal Iyer dlstat_fanout_swlane_and_local_stats(dh, linkid, linkname); 2211*0dc2366fSVenugopal Iyer fout_hwlane_stats = dlstat_fanout_hwlane_stats(dh, linkid, linkname); 2212*0dc2366fSVenugopal Iyer 2213*0dc2366fSVenugopal Iyer if (fout_swlane_and_local_stats == NULL) { 2214*0dc2366fSVenugopal Iyer head = fout_hwlane_stats; 2215*0dc2366fSVenugopal Iyer goto done; 2216*0dc2366fSVenugopal Iyer } 2217*0dc2366fSVenugopal Iyer 2218*0dc2366fSVenugopal Iyer fout_stats = fout_swlane_and_local_stats->dc_statentry; 2219*0dc2366fSVenugopal Iyer 2220*0dc2366fSVenugopal Iyer if (fout_hwlane_stats != NULL) { /* hwlane(s), only local traffic */ 2221*0dc2366fSVenugopal Iyer fout_stats->fe_id = L_LOCAL; 2222*0dc2366fSVenugopal Iyer fout_stats->fe_index = DLSTAT_INVALID_ENTRY; 2223*0dc2366fSVenugopal Iyer } else { /* no hwlane, mix of local+sw classified */ 2224*0dc2366fSVenugopal Iyer fout_stats->fe_id = L_LCLSWLANE; 2225*0dc2366fSVenugopal Iyer fout_stats->fe_index = DLSTAT_INVALID_ENTRY; 2226*0dc2366fSVenugopal Iyer } 2227*0dc2366fSVenugopal Iyer 2228*0dc2366fSVenugopal Iyer fout_swlane_and_local_stats->dc_next = fout_hwlane_stats; 2229*0dc2366fSVenugopal Iyer head = fout_swlane_and_local_stats; 2230*0dc2366fSVenugopal Iyer 2231*0dc2366fSVenugopal Iyer done: 2232*0dc2366fSVenugopal Iyer return (head); 2233*0dc2366fSVenugopal Iyer } 2234*0dc2366fSVenugopal Iyer 2235*0dc2366fSVenugopal Iyer /* Rx ring statistic specific functions */ 2236*0dc2366fSVenugopal Iyer static boolean_t 2237*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_match(void *arg1, void *arg2) 2238*0dc2366fSVenugopal Iyer { 2239*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s1 = arg1; 2240*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s2 = arg2; 2241*0dc2366fSVenugopal Iyer 2242*0dc2366fSVenugopal Iyer return (s1->rle_index == s2->rle_index); 2243*0dc2366fSVenugopal Iyer } 2244*0dc2366fSVenugopal Iyer 2245*0dc2366fSVenugopal Iyer static void * 2246*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_stat_entry_diff(void *arg1, void *arg2) 2247*0dc2366fSVenugopal Iyer { 2248*0dc2366fSVenugopal Iyer ring_stat_entry_t *s1 = arg1; 2249*0dc2366fSVenugopal Iyer ring_stat_entry_t *s2 = arg2; 2250*0dc2366fSVenugopal Iyer ring_stat_entry_t *diff_entry; 2251*0dc2366fSVenugopal Iyer 2252*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (ring_stat_entry_t)); 2253*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 2254*0dc2366fSVenugopal Iyer goto done; 2255*0dc2366fSVenugopal Iyer 2256*0dc2366fSVenugopal Iyer diff_entry->re_index = s1->re_index; 2257*0dc2366fSVenugopal Iyer 2258*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, re_stats, rx_ring_stats_list, 2259*0dc2366fSVenugopal Iyer RX_RING_STAT_SIZE); 2260*0dc2366fSVenugopal Iyer 2261*0dc2366fSVenugopal Iyer done: 2262*0dc2366fSVenugopal Iyer return (diff_entry); 2263*0dc2366fSVenugopal Iyer } 2264*0dc2366fSVenugopal Iyer 2265*0dc2366fSVenugopal Iyer static void * 2266*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 2267*0dc2366fSVenugopal Iyer { 2268*0dc2366fSVenugopal Iyer ring_stat_entry_t *rx_ring_stat_entry; 2269*0dc2366fSVenugopal Iyer 2270*0dc2366fSVenugopal Iyer rx_ring_stat_entry = calloc(1, sizeof (ring_stat_entry_t)); 2271*0dc2366fSVenugopal Iyer if (rx_ring_stat_entry == NULL) 2272*0dc2366fSVenugopal Iyer goto done; 2273*0dc2366fSVenugopal Iyer 2274*0dc2366fSVenugopal Iyer rx_ring_stat_entry->re_index = i; 2275*0dc2366fSVenugopal Iyer 2276*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_ring_stat_entry->re_stats, 2277*0dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE); 2278*0dc2366fSVenugopal Iyer 2279*0dc2366fSVenugopal Iyer done: 2280*0dc2366fSVenugopal Iyer return (rx_ring_stat_entry); 2281*0dc2366fSVenugopal Iyer } 2282*0dc2366fSVenugopal Iyer 2283*0dc2366fSVenugopal Iyer void * 2284*0dc2366fSVenugopal Iyer dlstat_rx_ring_stats(dladm_handle_t dh, datalink_id_t linkid) 2285*0dc2366fSVenugopal Iyer { 2286*0dc2366fSVenugopal Iyer uint_t rx_ring_idlist[MAX_RINGS_PER_GROUP]; 2287*0dc2366fSVenugopal Iyer uint_t rx_ring_idlist_size; 2288*0dc2366fSVenugopal Iyer dladm_phys_attr_t dpa; 2289*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 2290*0dc2366fSVenugopal Iyer char *modname; 2291*0dc2366fSVenugopal Iyer datalink_class_t class; 2292*0dc2366fSVenugopal Iyer 2293*0dc2366fSVenugopal Iyer /* 2294*0dc2366fSVenugopal Iyer * kstats corresponding to physical device rings continue to use 2295*0dc2366fSVenugopal Iyer * device names even if the link is renamed using dladm rename-link. 2296*0dc2366fSVenugopal Iyer * Thus, given a linkid, we lookup the physical device name. 2297*0dc2366fSVenugopal Iyer * However, if an aggr is renamed, kstats corresponding to its 2298*0dc2366fSVenugopal Iyer * pseudo rings are renamed as well. 2299*0dc2366fSVenugopal Iyer */ 2300*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, linkname, 2301*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2302*0dc2366fSVenugopal Iyer return (NULL); 2303*0dc2366fSVenugopal Iyer } 2304*0dc2366fSVenugopal Iyer 2305*0dc2366fSVenugopal Iyer if (class != DATALINK_CLASS_AGGR) { 2306*0dc2366fSVenugopal Iyer if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2307*0dc2366fSVenugopal Iyer DLADM_STATUS_OK) { 2308*0dc2366fSVenugopal Iyer return (NULL); 2309*0dc2366fSVenugopal Iyer } 2310*0dc2366fSVenugopal Iyer modname = dpa.dp_dev; 2311*0dc2366fSVenugopal Iyer } else 2312*0dc2366fSVenugopal Iyer modname = linkname; 2313*0dc2366fSVenugopal Iyer 2314*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(modname, DLSTAT_RX_RING_IDLIST, 2315*0dc2366fSVenugopal Iyer rx_ring_idlist, &rx_ring_idlist_size); 2316*0dc2366fSVenugopal Iyer 2317*0dc2366fSVenugopal Iyer return (i_dlstat_query_stats(modname, DLSTAT_MAC_RX_RING, 2318*0dc2366fSVenugopal Iyer rx_ring_idlist, rx_ring_idlist_size, 2319*0dc2366fSVenugopal Iyer i_dlstat_rx_ring_retrieve_stat)); 2320*0dc2366fSVenugopal Iyer } 2321*0dc2366fSVenugopal Iyer 2322*0dc2366fSVenugopal Iyer /* Tx ring statistic specific functions */ 2323*0dc2366fSVenugopal Iyer static boolean_t 2324*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_match(void *arg1, void *arg2) 2325*0dc2366fSVenugopal Iyer { 2326*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s1 = arg1; 2327*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s2 = arg2; 2328*0dc2366fSVenugopal Iyer 2329*0dc2366fSVenugopal Iyer return (s1->tle_index == s2->tle_index); 2330*0dc2366fSVenugopal Iyer } 2331*0dc2366fSVenugopal Iyer 2332*0dc2366fSVenugopal Iyer static void * 2333*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_stat_entry_diff(void *arg1, void *arg2) 2334*0dc2366fSVenugopal Iyer { 2335*0dc2366fSVenugopal Iyer ring_stat_entry_t *s1 = arg1; 2336*0dc2366fSVenugopal Iyer ring_stat_entry_t *s2 = arg2; 2337*0dc2366fSVenugopal Iyer ring_stat_entry_t *diff_entry; 2338*0dc2366fSVenugopal Iyer 2339*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (ring_stat_entry_t)); 2340*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 2341*0dc2366fSVenugopal Iyer goto done; 2342*0dc2366fSVenugopal Iyer 2343*0dc2366fSVenugopal Iyer diff_entry->re_index = s1->re_index; 2344*0dc2366fSVenugopal Iyer 2345*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, re_stats, tx_ring_stats_list, 2346*0dc2366fSVenugopal Iyer TX_RING_STAT_SIZE); 2347*0dc2366fSVenugopal Iyer 2348*0dc2366fSVenugopal Iyer done: 2349*0dc2366fSVenugopal Iyer return (diff_entry); 2350*0dc2366fSVenugopal Iyer } 2351*0dc2366fSVenugopal Iyer 2352*0dc2366fSVenugopal Iyer static void * 2353*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i) 2354*0dc2366fSVenugopal Iyer { 2355*0dc2366fSVenugopal Iyer ring_stat_entry_t *tx_ring_stat_entry; 2356*0dc2366fSVenugopal Iyer 2357*0dc2366fSVenugopal Iyer tx_ring_stat_entry = calloc(1, sizeof (ring_stat_entry_t)); 2358*0dc2366fSVenugopal Iyer if (tx_ring_stat_entry == NULL) 2359*0dc2366fSVenugopal Iyer goto done; 2360*0dc2366fSVenugopal Iyer 2361*0dc2366fSVenugopal Iyer tx_ring_stat_entry->re_index = i; 2362*0dc2366fSVenugopal Iyer 2363*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &tx_ring_stat_entry->re_stats, 2364*0dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE); 2365*0dc2366fSVenugopal Iyer 2366*0dc2366fSVenugopal Iyer done: 2367*0dc2366fSVenugopal Iyer return (tx_ring_stat_entry); 2368*0dc2366fSVenugopal Iyer } 2369*0dc2366fSVenugopal Iyer 2370*0dc2366fSVenugopal Iyer void * 2371*0dc2366fSVenugopal Iyer dlstat_tx_ring_stats(dladm_handle_t dh, datalink_id_t linkid) 2372*0dc2366fSVenugopal Iyer { 2373*0dc2366fSVenugopal Iyer uint_t tx_ring_idlist[MAX_RINGS_PER_GROUP]; 2374*0dc2366fSVenugopal Iyer uint_t tx_ring_idlist_size; 2375*0dc2366fSVenugopal Iyer dladm_phys_attr_t dpa; 2376*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 2377*0dc2366fSVenugopal Iyer char *modname; 2378*0dc2366fSVenugopal Iyer datalink_class_t class; 2379*0dc2366fSVenugopal Iyer 2380*0dc2366fSVenugopal Iyer /* 2381*0dc2366fSVenugopal Iyer * kstats corresponding to physical device rings continue to use 2382*0dc2366fSVenugopal Iyer * device names even if the link is renamed using dladm rename-link. 2383*0dc2366fSVenugopal Iyer * Thus, given a linkid, we lookup the physical device name. 2384*0dc2366fSVenugopal Iyer * However, if an aggr is renamed, kstats corresponding to its 2385*0dc2366fSVenugopal Iyer * pseudo rings are renamed as well. 2386*0dc2366fSVenugopal Iyer */ 2387*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, linkname, 2388*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2389*0dc2366fSVenugopal Iyer return (NULL); 2390*0dc2366fSVenugopal Iyer } 2391*0dc2366fSVenugopal Iyer 2392*0dc2366fSVenugopal Iyer if (class != DATALINK_CLASS_AGGR) { 2393*0dc2366fSVenugopal Iyer if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) != 2394*0dc2366fSVenugopal Iyer DLADM_STATUS_OK) { 2395*0dc2366fSVenugopal Iyer return (NULL); 2396*0dc2366fSVenugopal Iyer } 2397*0dc2366fSVenugopal Iyer modname = dpa.dp_dev; 2398*0dc2366fSVenugopal Iyer } else 2399*0dc2366fSVenugopal Iyer modname = linkname; 2400*0dc2366fSVenugopal Iyer 2401*0dc2366fSVenugopal Iyer i_dlstat_get_idlist(modname, DLSTAT_TX_RING_IDLIST, 2402*0dc2366fSVenugopal Iyer tx_ring_idlist, &tx_ring_idlist_size); 2403*0dc2366fSVenugopal Iyer 2404*0dc2366fSVenugopal Iyer return (i_dlstat_query_stats(modname, DLSTAT_MAC_TX_RING, 2405*0dc2366fSVenugopal Iyer tx_ring_idlist, tx_ring_idlist_size, 2406*0dc2366fSVenugopal Iyer i_dlstat_tx_ring_retrieve_stat)); 2407*0dc2366fSVenugopal Iyer } 2408*0dc2366fSVenugopal Iyer 2409*0dc2366fSVenugopal Iyer /* Rx ring total statistic specific functions */ 2410*0dc2366fSVenugopal Iyer void * 2411*0dc2366fSVenugopal Iyer dlstat_rx_ring_total_stats(dladm_handle_t dh, datalink_id_t linkid) 2412*0dc2366fSVenugopal Iyer { 2413*0dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL; 2414*0dc2366fSVenugopal Iyer dladm_stat_chain_t *rx_ring_head, *curr; 2415*0dc2366fSVenugopal Iyer ring_stat_entry_t *total_stats; 2416*0dc2366fSVenugopal Iyer 2417*0dc2366fSVenugopal Iyer /* Get per rx ring stats */ 2418*0dc2366fSVenugopal Iyer rx_ring_head = dlstat_rx_ring_stats(dh, linkid); 2419*0dc2366fSVenugopal Iyer if (rx_ring_head == NULL) 2420*0dc2366fSVenugopal Iyer goto done; 2421*0dc2366fSVenugopal Iyer 2422*0dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (ring_stat_entry_t)); 2423*0dc2366fSVenugopal Iyer if (total_stats == NULL) 2424*0dc2366fSVenugopal Iyer goto done; 2425*0dc2366fSVenugopal Iyer 2426*0dc2366fSVenugopal Iyer total_stats->re_index = DLSTAT_INVALID_ENTRY; 2427*0dc2366fSVenugopal Iyer 2428*0dc2366fSVenugopal Iyer for (curr = rx_ring_head; curr != NULL; curr = curr->dc_next) { 2429*0dc2366fSVenugopal Iyer ring_stat_entry_t *curr_ring_stats = curr->dc_statentry; 2430*0dc2366fSVenugopal Iyer 2431*0dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->re_stats, 2432*0dc2366fSVenugopal Iyer &curr_ring_stats->re_stats, &total_stats->re_stats, 2433*0dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE); 2434*0dc2366fSVenugopal Iyer } 2435*0dc2366fSVenugopal Iyer 2436*0dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t)); 2437*0dc2366fSVenugopal Iyer if (total_head == NULL) { 2438*0dc2366fSVenugopal Iyer free(total_stats); 2439*0dc2366fSVenugopal Iyer goto done; 2440*0dc2366fSVenugopal Iyer } 2441*0dc2366fSVenugopal Iyer 2442*0dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats; 2443*0dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_rx_ring_total", 2444*0dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader)); 2445*0dc2366fSVenugopal Iyer total_head->dc_next = NULL; 2446*0dc2366fSVenugopal Iyer free(rx_ring_head); 2447*0dc2366fSVenugopal Iyer 2448*0dc2366fSVenugopal Iyer done: 2449*0dc2366fSVenugopal Iyer return (total_head); 2450*0dc2366fSVenugopal Iyer } 2451*0dc2366fSVenugopal Iyer 2452*0dc2366fSVenugopal Iyer /* Tx ring total statistic specific functions */ 2453*0dc2366fSVenugopal Iyer void * 2454*0dc2366fSVenugopal Iyer dlstat_tx_ring_total_stats(dladm_handle_t dh, datalink_id_t linkid) 2455*0dc2366fSVenugopal Iyer { 2456*0dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL; 2457*0dc2366fSVenugopal Iyer dladm_stat_chain_t *tx_ring_head, *curr; 2458*0dc2366fSVenugopal Iyer ring_stat_entry_t *total_stats; 2459*0dc2366fSVenugopal Iyer 2460*0dc2366fSVenugopal Iyer /* Get per tx ring stats */ 2461*0dc2366fSVenugopal Iyer tx_ring_head = dlstat_tx_ring_stats(dh, linkid); 2462*0dc2366fSVenugopal Iyer if (tx_ring_head == NULL) 2463*0dc2366fSVenugopal Iyer goto done; 2464*0dc2366fSVenugopal Iyer 2465*0dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (ring_stat_entry_t)); 2466*0dc2366fSVenugopal Iyer if (total_stats == NULL) 2467*0dc2366fSVenugopal Iyer goto done; 2468*0dc2366fSVenugopal Iyer 2469*0dc2366fSVenugopal Iyer total_stats->re_index = DLSTAT_INVALID_ENTRY; 2470*0dc2366fSVenugopal Iyer 2471*0dc2366fSVenugopal Iyer for (curr = tx_ring_head; curr != NULL; curr = curr->dc_next) { 2472*0dc2366fSVenugopal Iyer ring_stat_entry_t *curr_ring_stats = curr->dc_statentry; 2473*0dc2366fSVenugopal Iyer 2474*0dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->re_stats, 2475*0dc2366fSVenugopal Iyer &curr_ring_stats->re_stats, &total_stats->re_stats, 2476*0dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE); 2477*0dc2366fSVenugopal Iyer } 2478*0dc2366fSVenugopal Iyer 2479*0dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t)); 2480*0dc2366fSVenugopal Iyer if (total_head == NULL) { 2481*0dc2366fSVenugopal Iyer free(total_stats); 2482*0dc2366fSVenugopal Iyer goto done; 2483*0dc2366fSVenugopal Iyer } 2484*0dc2366fSVenugopal Iyer 2485*0dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats; 2486*0dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_tx_ring_total", 2487*0dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader)); 2488*0dc2366fSVenugopal Iyer total_head->dc_next = NULL; 2489*0dc2366fSVenugopal Iyer free(tx_ring_head); 2490*0dc2366fSVenugopal Iyer 2491*0dc2366fSVenugopal Iyer done: 2492*0dc2366fSVenugopal Iyer return (total_head); 2493*0dc2366fSVenugopal Iyer } 2494*0dc2366fSVenugopal Iyer 2495*0dc2366fSVenugopal Iyer /* Summary statistic specific functions */ 2496*0dc2366fSVenugopal Iyer /*ARGSUSED*/ 2497*0dc2366fSVenugopal Iyer static boolean_t 2498*0dc2366fSVenugopal Iyer i_dlstat_total_match(void *arg1, void *arg2) 2499*0dc2366fSVenugopal Iyer { /* Always single entry for total */ 2500*0dc2366fSVenugopal Iyer return (B_TRUE); 2501*0dc2366fSVenugopal Iyer } 2502*0dc2366fSVenugopal Iyer 2503*0dc2366fSVenugopal Iyer static void * 2504*0dc2366fSVenugopal Iyer i_dlstat_total_stat_entry_diff(void *arg1, void *arg2) 2505*0dc2366fSVenugopal Iyer { 2506*0dc2366fSVenugopal Iyer total_stat_entry_t *s1 = arg1; 2507*0dc2366fSVenugopal Iyer total_stat_entry_t *s2 = arg2; 2508*0dc2366fSVenugopal Iyer total_stat_entry_t *diff_entry; 2509*0dc2366fSVenugopal Iyer 2510*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (total_stat_entry_t)); 2511*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 2512*0dc2366fSVenugopal Iyer goto done; 2513*0dc2366fSVenugopal Iyer 2514*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, tse_stats, total_stats_list, 2515*0dc2366fSVenugopal Iyer TOTAL_STAT_SIZE); 2516*0dc2366fSVenugopal Iyer 2517*0dc2366fSVenugopal Iyer done: 2518*0dc2366fSVenugopal Iyer return (diff_entry); 2519*0dc2366fSVenugopal Iyer } 2520*0dc2366fSVenugopal Iyer 2521*0dc2366fSVenugopal Iyer void * 2522*0dc2366fSVenugopal Iyer dlstat_total_stats(dladm_handle_t dh, datalink_id_t linkid) 2523*0dc2366fSVenugopal Iyer { 2524*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 2525*0dc2366fSVenugopal Iyer dladm_stat_chain_t *rx_total; 2526*0dc2366fSVenugopal Iyer dladm_stat_chain_t *tx_total; 2527*0dc2366fSVenugopal Iyer total_stat_entry_t *total_stat_entry; 2528*0dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry; 2529*0dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry; 2530*0dc2366fSVenugopal Iyer 2531*0dc2366fSVenugopal Iyer /* Get total rx lane stats */ 2532*0dc2366fSVenugopal Iyer rx_total = dlstat_rx_lane_total_stats(dh, linkid); 2533*0dc2366fSVenugopal Iyer if (rx_total == NULL) 2534*0dc2366fSVenugopal Iyer goto done; 2535*0dc2366fSVenugopal Iyer 2536*0dc2366fSVenugopal Iyer /* Get total tx lane stats */ 2537*0dc2366fSVenugopal Iyer tx_total = dlstat_tx_lane_total_stats(dh, linkid); 2538*0dc2366fSVenugopal Iyer if (tx_total == NULL) 2539*0dc2366fSVenugopal Iyer goto done; 2540*0dc2366fSVenugopal Iyer 2541*0dc2366fSVenugopal Iyer /* Build total stat */ 2542*0dc2366fSVenugopal Iyer total_stat_entry = calloc(1, sizeof (total_stat_entry_t)); 2543*0dc2366fSVenugopal Iyer if (total_stat_entry == NULL) 2544*0dc2366fSVenugopal Iyer goto done; 2545*0dc2366fSVenugopal Iyer 2546*0dc2366fSVenugopal Iyer rx_lane_stat_entry = rx_total->dc_statentry; 2547*0dc2366fSVenugopal Iyer tx_lane_stat_entry = tx_total->dc_statentry; 2548*0dc2366fSVenugopal Iyer 2549*0dc2366fSVenugopal Iyer /* Extract total rx ipackets, rbytes */ 2550*0dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_ipackets = 2551*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets; 2552*0dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_rbytes = 2553*0dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes; 2554*0dc2366fSVenugopal Iyer 2555*0dc2366fSVenugopal Iyer /* Extract total tx opackets, obytes */ 2556*0dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_opackets = 2557*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets; 2558*0dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_obytes = 2559*0dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes; 2560*0dc2366fSVenugopal Iyer 2561*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 2562*0dc2366fSVenugopal Iyer if (head == NULL) { 2563*0dc2366fSVenugopal Iyer free(total_stat_entry); 2564*0dc2366fSVenugopal Iyer goto done; 2565*0dc2366fSVenugopal Iyer } 2566*0dc2366fSVenugopal Iyer 2567*0dc2366fSVenugopal Iyer head->dc_statentry = total_stat_entry; 2568*0dc2366fSVenugopal Iyer (void) strlcpy(head->dc_statheader, "mac_lane_total", 2569*0dc2366fSVenugopal Iyer sizeof (head->dc_statheader)); 2570*0dc2366fSVenugopal Iyer head->dc_next = NULL; 2571*0dc2366fSVenugopal Iyer free(rx_total); 2572*0dc2366fSVenugopal Iyer free(tx_total); 2573*0dc2366fSVenugopal Iyer 2574*0dc2366fSVenugopal Iyer done: 2575*0dc2366fSVenugopal Iyer return (head); 2576*0dc2366fSVenugopal Iyer } 2577*0dc2366fSVenugopal Iyer 2578*0dc2366fSVenugopal Iyer /* Aggr total statistic(summed across all component ports) specific functions */ 2579*0dc2366fSVenugopal Iyer void * 2580*0dc2366fSVenugopal Iyer dlstat_aggr_total_stats(dladm_stat_chain_t *head) 2581*0dc2366fSVenugopal Iyer { 2582*0dc2366fSVenugopal Iyer dladm_stat_chain_t *curr; 2583*0dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head; 2584*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *total_stats; 2585*0dc2366fSVenugopal Iyer 2586*0dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (aggr_port_stat_entry_t)); 2587*0dc2366fSVenugopal Iyer if (total_stats == NULL) 2588*0dc2366fSVenugopal Iyer goto done; 2589*0dc2366fSVenugopal Iyer 2590*0dc2366fSVenugopal Iyer total_stats->ape_portlinkid = DATALINK_INVALID_LINKID; 2591*0dc2366fSVenugopal Iyer 2592*0dc2366fSVenugopal Iyer for (curr = head; curr != NULL; curr = curr->dc_next) { 2593*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *curr_aggr_port_stats; 2594*0dc2366fSVenugopal Iyer 2595*0dc2366fSVenugopal Iyer curr_aggr_port_stats = curr->dc_statentry; 2596*0dc2366fSVenugopal Iyer 2597*0dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->ape_stats, 2598*0dc2366fSVenugopal Iyer &curr_aggr_port_stats->ape_stats, &total_stats->ape_stats, 2599*0dc2366fSVenugopal Iyer aggr_port_stats_list, AGGR_PORT_STAT_SIZE); 2600*0dc2366fSVenugopal Iyer } 2601*0dc2366fSVenugopal Iyer 2602*0dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t)); 2603*0dc2366fSVenugopal Iyer if (total_head == NULL) { 2604*0dc2366fSVenugopal Iyer free(total_stats); 2605*0dc2366fSVenugopal Iyer goto done; 2606*0dc2366fSVenugopal Iyer } 2607*0dc2366fSVenugopal Iyer 2608*0dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats; 2609*0dc2366fSVenugopal Iyer total_head->dc_next = NULL; 2610*0dc2366fSVenugopal Iyer 2611*0dc2366fSVenugopal Iyer done: 2612*0dc2366fSVenugopal Iyer return (total_head); 2613*0dc2366fSVenugopal Iyer } 2614*0dc2366fSVenugopal Iyer 2615*0dc2366fSVenugopal Iyer /* Aggr port statistic specific functions */ 2616*0dc2366fSVenugopal Iyer static boolean_t 2617*0dc2366fSVenugopal Iyer i_dlstat_aggr_port_match(void *arg1, void *arg2) 2618*0dc2366fSVenugopal Iyer { 2619*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s1 = arg1; 2620*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s2 = arg2; 2621*0dc2366fSVenugopal Iyer 2622*0dc2366fSVenugopal Iyer return (s1->ape_portlinkid == s2->ape_portlinkid); 2623*0dc2366fSVenugopal Iyer } 2624*0dc2366fSVenugopal Iyer 2625*0dc2366fSVenugopal Iyer static void * 2626*0dc2366fSVenugopal Iyer i_dlstat_aggr_port_stat_entry_diff(void *arg1, void *arg2) 2627*0dc2366fSVenugopal Iyer { 2628*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s1 = arg1; 2629*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s2 = arg2; 2630*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *diff_entry; 2631*0dc2366fSVenugopal Iyer 2632*0dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (aggr_port_stat_entry_t)); 2633*0dc2366fSVenugopal Iyer if (diff_entry == NULL) 2634*0dc2366fSVenugopal Iyer goto done; 2635*0dc2366fSVenugopal Iyer 2636*0dc2366fSVenugopal Iyer diff_entry->ape_portlinkid = s1->ape_portlinkid; 2637*0dc2366fSVenugopal Iyer 2638*0dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, ape_stats, aggr_port_stats_list, 2639*0dc2366fSVenugopal Iyer AGGR_PORT_STAT_SIZE); 2640*0dc2366fSVenugopal Iyer 2641*0dc2366fSVenugopal Iyer done: 2642*0dc2366fSVenugopal Iyer return (diff_entry); 2643*0dc2366fSVenugopal Iyer } 2644*0dc2366fSVenugopal Iyer 2645*0dc2366fSVenugopal Iyer /* 2646*0dc2366fSVenugopal Iyer * Query dls stats for the aggr port. This results in query for stats into 2647*0dc2366fSVenugopal Iyer * the corresponding device driver. 2648*0dc2366fSVenugopal Iyer */ 2649*0dc2366fSVenugopal Iyer static aggr_port_stat_entry_t * 2650*0dc2366fSVenugopal Iyer i_dlstat_single_port_stats(const char *portname, datalink_id_t linkid) 2651*0dc2366fSVenugopal Iyer { 2652*0dc2366fSVenugopal Iyer kstat_ctl_t *kcp; 2653*0dc2366fSVenugopal Iyer kstat_t *ksp; 2654*0dc2366fSVenugopal Iyer char module[DLPI_LINKNAME_MAX]; 2655*0dc2366fSVenugopal Iyer uint_t instance; 2656*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *aggr_port_stat_entry = NULL; 2657*0dc2366fSVenugopal Iyer 2658*0dc2366fSVenugopal Iyer if (dladm_parselink(portname, module, &instance) != DLADM_STATUS_OK) 2659*0dc2366fSVenugopal Iyer goto done; 2660*0dc2366fSVenugopal Iyer 2661*0dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) { 2662*0dc2366fSVenugopal Iyer warn("kstat open operation failed"); 2663*0dc2366fSVenugopal Iyer return (NULL); 2664*0dc2366fSVenugopal Iyer } 2665*0dc2366fSVenugopal Iyer 2666*0dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL); 2667*0dc2366fSVenugopal Iyer if (ksp == NULL) 2668*0dc2366fSVenugopal Iyer goto done; 2669*0dc2366fSVenugopal Iyer 2670*0dc2366fSVenugopal Iyer aggr_port_stat_entry = calloc(1, sizeof (aggr_port_stat_entry_t)); 2671*0dc2366fSVenugopal Iyer if (aggr_port_stat_entry == NULL) 2672*0dc2366fSVenugopal Iyer goto done; 2673*0dc2366fSVenugopal Iyer 2674*0dc2366fSVenugopal Iyer /* Save port's linkid */ 2675*0dc2366fSVenugopal Iyer aggr_port_stat_entry->ape_portlinkid = linkid; 2676*0dc2366fSVenugopal Iyer 2677*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &aggr_port_stat_entry->ape_stats, 2678*0dc2366fSVenugopal Iyer aggr_port_stats_list, AGGR_PORT_STAT_SIZE); 2679*0dc2366fSVenugopal Iyer done: 2680*0dc2366fSVenugopal Iyer (void) kstat_close(kcp); 2681*0dc2366fSVenugopal Iyer return (aggr_port_stat_entry); 2682*0dc2366fSVenugopal Iyer } 2683*0dc2366fSVenugopal Iyer 2684*0dc2366fSVenugopal Iyer void * 2685*0dc2366fSVenugopal Iyer dlstat_aggr_port_stats(dladm_handle_t dh, datalink_id_t linkid) 2686*0dc2366fSVenugopal Iyer { 2687*0dc2366fSVenugopal Iyer dladm_aggr_grp_attr_t ginfo; 2688*0dc2366fSVenugopal Iyer int i; 2689*0dc2366fSVenugopal Iyer dladm_aggr_port_attr_t *portp; 2690*0dc2366fSVenugopal Iyer dladm_phys_attr_t dpa; 2691*0dc2366fSVenugopal Iyer aggr_port_stat_entry_t *aggr_port_stat_entry; 2692*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL, *prev = NULL, *curr; 2693*0dc2366fSVenugopal Iyer dladm_stat_chain_t *total_stats; 2694*0dc2366fSVenugopal Iyer 2695*0dc2366fSVenugopal Iyer /* Get aggr info */ 2696*0dc2366fSVenugopal Iyer bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t)); 2697*0dc2366fSVenugopal Iyer if (dladm_aggr_info(dh, linkid, &ginfo, DLADM_OPT_ACTIVE) 2698*0dc2366fSVenugopal Iyer != DLADM_STATUS_OK) 2699*0dc2366fSVenugopal Iyer goto done; 2700*0dc2366fSVenugopal Iyer /* For every port that is member of this aggr do */ 2701*0dc2366fSVenugopal Iyer for (i = 0; i < ginfo.lg_nports; i++) { 2702*0dc2366fSVenugopal Iyer portp = &(ginfo.lg_ports[i]); 2703*0dc2366fSVenugopal Iyer if (dladm_phys_info(dh, portp->lp_linkid, &dpa, 2704*0dc2366fSVenugopal Iyer DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) { 2705*0dc2366fSVenugopal Iyer goto done; 2706*0dc2366fSVenugopal Iyer } 2707*0dc2366fSVenugopal Iyer 2708*0dc2366fSVenugopal Iyer aggr_port_stat_entry = i_dlstat_single_port_stats(dpa.dp_dev, 2709*0dc2366fSVenugopal Iyer portp->lp_linkid); 2710*0dc2366fSVenugopal Iyer 2711*0dc2366fSVenugopal Iyer /* Create dladm_stat_chain_t object for this stat */ 2712*0dc2366fSVenugopal Iyer curr = malloc(sizeof (dladm_stat_chain_t)); 2713*0dc2366fSVenugopal Iyer if (curr == NULL) { 2714*0dc2366fSVenugopal Iyer free(aggr_port_stat_entry); 2715*0dc2366fSVenugopal Iyer goto done; 2716*0dc2366fSVenugopal Iyer } 2717*0dc2366fSVenugopal Iyer (void) strlcpy(curr->dc_statheader, dpa.dp_dev, 2718*0dc2366fSVenugopal Iyer sizeof (curr->dc_statheader)); 2719*0dc2366fSVenugopal Iyer curr->dc_statentry = aggr_port_stat_entry; 2720*0dc2366fSVenugopal Iyer curr->dc_next = NULL; 2721*0dc2366fSVenugopal Iyer 2722*0dc2366fSVenugopal Iyer /* Chain this aggr port stat entry */ 2723*0dc2366fSVenugopal Iyer /* head of the stat list */ 2724*0dc2366fSVenugopal Iyer if (prev == NULL) 2725*0dc2366fSVenugopal Iyer head = curr; 2726*0dc2366fSVenugopal Iyer else 2727*0dc2366fSVenugopal Iyer prev->dc_next = curr; 2728*0dc2366fSVenugopal Iyer prev = curr; 2729*0dc2366fSVenugopal Iyer } 2730*0dc2366fSVenugopal Iyer 2731*0dc2366fSVenugopal Iyer /* 2732*0dc2366fSVenugopal Iyer * Prepend the stat list with cumulative aggr stats i.e. summed over all 2733*0dc2366fSVenugopal Iyer * component ports 2734*0dc2366fSVenugopal Iyer */ 2735*0dc2366fSVenugopal Iyer total_stats = dlstat_aggr_total_stats(head); 2736*0dc2366fSVenugopal Iyer if (total_stats != NULL) { 2737*0dc2366fSVenugopal Iyer total_stats->dc_next = head; 2738*0dc2366fSVenugopal Iyer head = total_stats; 2739*0dc2366fSVenugopal Iyer } 2740*0dc2366fSVenugopal Iyer 2741*0dc2366fSVenugopal Iyer done: 2742*0dc2366fSVenugopal Iyer free(ginfo.lg_ports); 2743*0dc2366fSVenugopal Iyer return (head); 2744*0dc2366fSVenugopal Iyer } 2745*0dc2366fSVenugopal Iyer 2746*0dc2366fSVenugopal Iyer /* Misc stat specific functions */ 2747*0dc2366fSVenugopal Iyer void * 2748*0dc2366fSVenugopal Iyer dlstat_misc_stats(dladm_handle_t dh, datalink_id_t linkid) 2749*0dc2366fSVenugopal Iyer { 2750*0dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry; 2751*0dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL; 2752*0dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN]; 2753*0dc2366fSVenugopal Iyer 2754*0dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname, 2755*0dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) { 2756*0dc2366fSVenugopal Iyer goto done; 2757*0dc2366fSVenugopal Iyer } 2758*0dc2366fSVenugopal Iyer 2759*0dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname); 2760*0dc2366fSVenugopal Iyer if (misc_stat_entry == NULL) 2761*0dc2366fSVenugopal Iyer goto done; 2762*0dc2366fSVenugopal Iyer 2763*0dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t)); 2764*0dc2366fSVenugopal Iyer if (head == NULL) { 2765*0dc2366fSVenugopal Iyer free(misc_stat_entry); 2766*0dc2366fSVenugopal Iyer goto done; 2767*0dc2366fSVenugopal Iyer } 2768*0dc2366fSVenugopal Iyer 2769*0dc2366fSVenugopal Iyer head->dc_statentry = misc_stat_entry; 2770*0dc2366fSVenugopal Iyer (void) strlcpy(head->dc_statheader, "mac_misc_stat", 2771*0dc2366fSVenugopal Iyer sizeof (head->dc_statheader)); 2772*0dc2366fSVenugopal Iyer head->dc_next = NULL; 2773*0dc2366fSVenugopal Iyer 2774*0dc2366fSVenugopal Iyer done: 2775*0dc2366fSVenugopal Iyer return (head); 2776*0dc2366fSVenugopal Iyer } 2777*0dc2366fSVenugopal Iyer 2778*0dc2366fSVenugopal Iyer /* Exported functions */ 2779*0dc2366fSVenugopal Iyer dladm_stat_chain_t * 2780*0dc2366fSVenugopal Iyer dladm_link_stat_query(dladm_handle_t dh, datalink_id_t linkid, 2781*0dc2366fSVenugopal Iyer dladm_stat_type_t stattype) 2782*0dc2366fSVenugopal Iyer { 2783*0dc2366fSVenugopal Iyer return (dladm_stat_table[stattype].ds_querystat(dh, linkid)); 2784*0dc2366fSVenugopal Iyer } 2785*0dc2366fSVenugopal Iyer 2786*0dc2366fSVenugopal Iyer dladm_stat_chain_t * 2787*0dc2366fSVenugopal Iyer dladm_link_stat_diffchain(dladm_stat_chain_t *op1, dladm_stat_chain_t *op2, 2788*0dc2366fSVenugopal Iyer dladm_stat_type_t stattype) 2789*0dc2366fSVenugopal Iyer { 2790*0dc2366fSVenugopal Iyer dladm_stat_chain_t *op1_curr, *op2_curr; 2791*0dc2366fSVenugopal Iyer dladm_stat_chain_t *diff_curr; 2792*0dc2366fSVenugopal Iyer dladm_stat_chain_t *diff_prev = NULL, *diff_head = NULL; 2793*0dc2366fSVenugopal Iyer 2794*0dc2366fSVenugopal Iyer /* Perform op1 - op2, store result in diff */ 2795*0dc2366fSVenugopal Iyer for (op1_curr = op1; op1_curr != NULL; op1_curr = op1_curr->dc_next) { 2796*0dc2366fSVenugopal Iyer for (op2_curr = op2; op2_curr != NULL; 2797*0dc2366fSVenugopal Iyer op2_curr = op2_curr->dc_next) { 2798*0dc2366fSVenugopal Iyer if (dlstat_match_stats(op1_curr->dc_statentry, 2799*0dc2366fSVenugopal Iyer op2_curr->dc_statentry, stattype)) { 2800*0dc2366fSVenugopal Iyer break; 2801*0dc2366fSVenugopal Iyer } 2802*0dc2366fSVenugopal Iyer } 2803*0dc2366fSVenugopal Iyer diff_curr = malloc(sizeof (dladm_stat_chain_t)); 2804*0dc2366fSVenugopal Iyer if (diff_curr == NULL) 2805*0dc2366fSVenugopal Iyer goto done; 2806*0dc2366fSVenugopal Iyer 2807*0dc2366fSVenugopal Iyer diff_curr->dc_next = NULL; 2808*0dc2366fSVenugopal Iyer 2809*0dc2366fSVenugopal Iyer if (op2_curr == NULL) { 2810*0dc2366fSVenugopal Iyer /* prev iteration did not have this stat entry */ 2811*0dc2366fSVenugopal Iyer diff_curr->dc_statentry = 2812*0dc2366fSVenugopal Iyer dlstat_diff_stats(op1_curr->dc_statentry, 2813*0dc2366fSVenugopal Iyer NULL, stattype); 2814*0dc2366fSVenugopal Iyer } else { 2815*0dc2366fSVenugopal Iyer diff_curr->dc_statentry = 2816*0dc2366fSVenugopal Iyer dlstat_diff_stats(op1_curr->dc_statentry, 2817*0dc2366fSVenugopal Iyer op2_curr->dc_statentry, stattype); 2818*0dc2366fSVenugopal Iyer } 2819*0dc2366fSVenugopal Iyer 2820*0dc2366fSVenugopal Iyer if (diff_curr->dc_statentry == NULL) { 2821*0dc2366fSVenugopal Iyer free(diff_curr); 2822*0dc2366fSVenugopal Iyer goto done; 2823*0dc2366fSVenugopal Iyer } 2824*0dc2366fSVenugopal Iyer 2825*0dc2366fSVenugopal Iyer if (diff_prev == NULL) /* head of the diff stat list */ 2826*0dc2366fSVenugopal Iyer diff_head = diff_curr; 2827*0dc2366fSVenugopal Iyer else 2828*0dc2366fSVenugopal Iyer diff_prev->dc_next = diff_curr; 2829*0dc2366fSVenugopal Iyer diff_prev = diff_curr; 2830*0dc2366fSVenugopal Iyer } 2831*0dc2366fSVenugopal Iyer done: 2832*0dc2366fSVenugopal Iyer return (diff_head); 2833*0dc2366fSVenugopal Iyer } 2834*0dc2366fSVenugopal Iyer 2835*0dc2366fSVenugopal Iyer void 2836*0dc2366fSVenugopal Iyer dladm_link_stat_free(dladm_stat_chain_t *curr) 2837*0dc2366fSVenugopal Iyer { 2838*0dc2366fSVenugopal Iyer while (curr != NULL) { 2839*0dc2366fSVenugopal Iyer dladm_stat_chain_t *tofree = curr; 2840*0dc2366fSVenugopal Iyer 2841*0dc2366fSVenugopal Iyer curr = curr->dc_next; 2842*0dc2366fSVenugopal Iyer free(tofree->dc_statentry); 2843*0dc2366fSVenugopal Iyer free(tofree); 2844*0dc2366fSVenugopal Iyer } 2845*0dc2366fSVenugopal Iyer } 2846*0dc2366fSVenugopal Iyer 2847*0dc2366fSVenugopal Iyer /* Query all link stats */ 2848*0dc2366fSVenugopal Iyer static name_value_stat_t * 2849*0dc2366fSVenugopal Iyer i_dlstat_convert_stats(void *stats, stat_info_t stats_list[], uint_t size) 2850*0dc2366fSVenugopal Iyer { 2851*0dc2366fSVenugopal Iyer int i; 2852*0dc2366fSVenugopal Iyer name_value_stat_t *head_stat = NULL, *prev_stat = NULL; 2853*0dc2366fSVenugopal Iyer name_value_stat_t *curr_stat; 2854*0dc2366fSVenugopal Iyer 2855*0dc2366fSVenugopal Iyer for (i = 0; i < size; i++) { 2856*0dc2366fSVenugopal Iyer uint64_t *val = (void *) 2857*0dc2366fSVenugopal Iyer ((uchar_t *)stats + stats_list[i].si_offset); 2858*0dc2366fSVenugopal Iyer 2859*0dc2366fSVenugopal Iyer curr_stat = calloc(1, sizeof (name_value_stat_t)); 2860*0dc2366fSVenugopal Iyer if (curr_stat == NULL) 2861*0dc2366fSVenugopal Iyer break; 2862*0dc2366fSVenugopal Iyer 2863*0dc2366fSVenugopal Iyer (void) strlcpy(curr_stat->nv_statname, stats_list[i].si_name, 2864*0dc2366fSVenugopal Iyer sizeof (curr_stat->nv_statname)); 2865*0dc2366fSVenugopal Iyer curr_stat->nv_statval = *val; 2866*0dc2366fSVenugopal Iyer curr_stat->nv_nextstat = NULL; 2867*0dc2366fSVenugopal Iyer 2868*0dc2366fSVenugopal Iyer if (head_stat == NULL) /* First node */ 2869*0dc2366fSVenugopal Iyer head_stat = curr_stat; 2870*0dc2366fSVenugopal Iyer else 2871*0dc2366fSVenugopal Iyer prev_stat->nv_nextstat = curr_stat; 2872*0dc2366fSVenugopal Iyer 2873*0dc2366fSVenugopal Iyer prev_stat = curr_stat; 2874*0dc2366fSVenugopal Iyer } 2875*0dc2366fSVenugopal Iyer return (head_stat); 2876*0dc2366fSVenugopal Iyer } 2877*0dc2366fSVenugopal Iyer 2878*0dc2366fSVenugopal Iyer void * 2879*0dc2366fSVenugopal Iyer build_nvs_entry(char *statheader, void *statentry, dladm_stat_type_t stattype) 2880*0dc2366fSVenugopal Iyer { 2881*0dc2366fSVenugopal Iyer name_value_stat_entry_t *name_value_stat_entry; 2882*0dc2366fSVenugopal Iyer dladm_stat_desc_t *stattbl_ptr; 2883*0dc2366fSVenugopal Iyer void *statfields; 2884*0dc2366fSVenugopal Iyer 2885*0dc2366fSVenugopal Iyer stattbl_ptr = &dladm_stat_table[stattype]; 2886*0dc2366fSVenugopal Iyer 2887*0dc2366fSVenugopal Iyer /* Allocate memory for query all stat entry */ 2888*0dc2366fSVenugopal Iyer name_value_stat_entry = calloc(1, sizeof (name_value_stat_entry_t)); 2889*0dc2366fSVenugopal Iyer if (name_value_stat_entry == NULL) 2890*0dc2366fSVenugopal Iyer goto done; 2891*0dc2366fSVenugopal Iyer 2892*0dc2366fSVenugopal Iyer /* Header for these stat fields */ 2893*0dc2366fSVenugopal Iyer (void) strlcpy(name_value_stat_entry->nve_header, statheader, 2894*0dc2366fSVenugopal Iyer sizeof (name_value_stat_entry->nve_header)); 2895*0dc2366fSVenugopal Iyer 2896*0dc2366fSVenugopal Iyer /* Extract stat fields from the statentry */ 2897*0dc2366fSVenugopal Iyer statfields = (uchar_t *)statentry + 2898*0dc2366fSVenugopal Iyer dladm_stat_table[stattype].ds_offset; 2899*0dc2366fSVenugopal Iyer 2900*0dc2366fSVenugopal Iyer /* Convert curr_stat to <statname, statval> pair */ 2901*0dc2366fSVenugopal Iyer name_value_stat_entry->nve_stats = 2902*0dc2366fSVenugopal Iyer i_dlstat_convert_stats(statfields, 2903*0dc2366fSVenugopal Iyer stattbl_ptr->ds_statlist, stattbl_ptr->ds_statsize); 2904*0dc2366fSVenugopal Iyer done: 2905*0dc2366fSVenugopal Iyer return (name_value_stat_entry); 2906*0dc2366fSVenugopal Iyer } 2907*0dc2366fSVenugopal Iyer 2908*0dc2366fSVenugopal Iyer void * 2909*0dc2366fSVenugopal Iyer i_walk_dlstat_chain(dladm_stat_chain_t *stat_head, dladm_stat_type_t stattype) 2910*0dc2366fSVenugopal Iyer { 2911*0dc2366fSVenugopal Iyer dladm_stat_chain_t *curr; 2912*0dc2366fSVenugopal Iyer dladm_stat_chain_t *nvstat_head = NULL, *nvstat_prev = NULL; 2913*0dc2366fSVenugopal Iyer dladm_stat_chain_t *nvstat_curr; 2914*0dc2366fSVenugopal Iyer 2915*0dc2366fSVenugopal Iyer /* 2916*0dc2366fSVenugopal Iyer * For every stat in the chain, build header and convert all 2917*0dc2366fSVenugopal Iyer * its stat fields 2918*0dc2366fSVenugopal Iyer */ 2919*0dc2366fSVenugopal Iyer for (curr = stat_head; curr != NULL; curr = curr->dc_next) { 2920*0dc2366fSVenugopal Iyer nvstat_curr = malloc(sizeof (dladm_stat_chain_t)); 2921*0dc2366fSVenugopal Iyer if (nvstat_curr == NULL) 2922*0dc2366fSVenugopal Iyer break; 2923*0dc2366fSVenugopal Iyer 2924*0dc2366fSVenugopal Iyer nvstat_curr->dc_statentry = build_nvs_entry(curr->dc_statheader, 2925*0dc2366fSVenugopal Iyer curr->dc_statentry, stattype); 2926*0dc2366fSVenugopal Iyer 2927*0dc2366fSVenugopal Iyer if (nvstat_curr->dc_statentry == NULL) { 2928*0dc2366fSVenugopal Iyer free(nvstat_curr); 2929*0dc2366fSVenugopal Iyer break; 2930*0dc2366fSVenugopal Iyer } 2931*0dc2366fSVenugopal Iyer 2932*0dc2366fSVenugopal Iyer nvstat_curr->dc_next = NULL; 2933*0dc2366fSVenugopal Iyer 2934*0dc2366fSVenugopal Iyer if (nvstat_head == NULL) /* First node */ 2935*0dc2366fSVenugopal Iyer nvstat_head = nvstat_curr; 2936*0dc2366fSVenugopal Iyer else 2937*0dc2366fSVenugopal Iyer nvstat_prev->dc_next = nvstat_curr; 2938*0dc2366fSVenugopal Iyer 2939*0dc2366fSVenugopal Iyer nvstat_prev = nvstat_curr; 2940*0dc2366fSVenugopal Iyer } 2941*0dc2366fSVenugopal Iyer done: 2942*0dc2366fSVenugopal Iyer return (nvstat_head); 2943*0dc2366fSVenugopal Iyer } 2944*0dc2366fSVenugopal Iyer 2945*0dc2366fSVenugopal Iyer dladm_stat_chain_t * 2946*0dc2366fSVenugopal Iyer dladm_link_stat_query_all(dladm_handle_t dh, datalink_id_t linkid, 2947*0dc2366fSVenugopal Iyer dladm_stat_type_t stattype) 2948*0dc2366fSVenugopal Iyer { 2949*0dc2366fSVenugopal Iyer dladm_stat_chain_t *stat_head; 2950*0dc2366fSVenugopal Iyer dladm_stat_chain_t *nvstat_head = NULL; 2951*0dc2366fSVenugopal Iyer 2952*0dc2366fSVenugopal Iyer /* Query the requested stat */ 2953*0dc2366fSVenugopal Iyer stat_head = dladm_link_stat_query(dh, linkid, stattype); 2954*0dc2366fSVenugopal Iyer if (stat_head == NULL) 2955*0dc2366fSVenugopal Iyer goto done; 2956*0dc2366fSVenugopal Iyer 2957*0dc2366fSVenugopal Iyer /* 2958*0dc2366fSVenugopal Iyer * Convert every statfield in every stat-entry of stat chain to 2959*0dc2366fSVenugopal Iyer * <statname, statval> pair 2960*0dc2366fSVenugopal Iyer */ 2961*0dc2366fSVenugopal Iyer nvstat_head = i_walk_dlstat_chain(stat_head, stattype); 2962*0dc2366fSVenugopal Iyer 2963*0dc2366fSVenugopal Iyer /* Free stat_head */ 2964*0dc2366fSVenugopal Iyer dladm_link_stat_free(stat_head); 2965*0dc2366fSVenugopal Iyer 2966*0dc2366fSVenugopal Iyer done: 2967*0dc2366fSVenugopal Iyer return (nvstat_head); 2968*0dc2366fSVenugopal Iyer } 2969*0dc2366fSVenugopal Iyer 2970*0dc2366fSVenugopal Iyer void 2971*0dc2366fSVenugopal Iyer dladm_link_stat_query_all_free(dladm_stat_chain_t *curr) 2972*0dc2366fSVenugopal Iyer { 2973*0dc2366fSVenugopal Iyer while (curr != NULL) { 2974*0dc2366fSVenugopal Iyer dladm_stat_chain_t *tofree = curr; 2975*0dc2366fSVenugopal Iyer name_value_stat_entry_t *nv_entry = curr->dc_statentry; 2976*0dc2366fSVenugopal Iyer name_value_stat_t *nv_curr = nv_entry->nve_stats; 2977*0dc2366fSVenugopal Iyer 2978*0dc2366fSVenugopal Iyer while (nv_curr != NULL) { 2979*0dc2366fSVenugopal Iyer name_value_stat_t *nv_tofree = nv_curr; 2980*0dc2366fSVenugopal Iyer 2981*0dc2366fSVenugopal Iyer nv_curr = nv_curr->nv_nextstat; 2982*0dc2366fSVenugopal Iyer free(nv_tofree); 2983*0dc2366fSVenugopal Iyer } 2984*0dc2366fSVenugopal Iyer 2985*0dc2366fSVenugopal Iyer curr = curr->dc_next; 2986*0dc2366fSVenugopal Iyer free(nv_entry); 2987*0dc2366fSVenugopal Iyer free(tofree); 2988*0dc2366fSVenugopal Iyer } 2989*0dc2366fSVenugopal Iyer } 2990*0dc2366fSVenugopal Iyer 2991*0dc2366fSVenugopal Iyer /* flow stats specific routines */ 2992*0dc2366fSVenugopal Iyer flow_stat_t * 2993*0dc2366fSVenugopal Iyer dladm_flow_stat_query(const char *flowname) 2994*0dc2366fSVenugopal Iyer { 2995*0dc2366fSVenugopal Iyer kstat_ctl_t *kcp; 2996*0dc2366fSVenugopal Iyer kstat_t *ksp; 2997*0dc2366fSVenugopal Iyer flow_stat_t *flow_stat = NULL; 2998*0dc2366fSVenugopal Iyer 2999*0dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) 3000*0dc2366fSVenugopal Iyer return (NULL); 3001*0dc2366fSVenugopal Iyer 3002*0dc2366fSVenugopal Iyer flow_stat = calloc(1, sizeof (flow_stat_t)); 3003*0dc2366fSVenugopal Iyer if (flow_stat == NULL) 3004*0dc2366fSVenugopal Iyer goto done; 3005*0dc2366fSVenugopal Iyer 3006*0dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, NULL, -1, flowname, "flow"); 3007*0dc2366fSVenugopal Iyer 3008*0dc2366fSVenugopal Iyer if (ksp != NULL) { 3009*0dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, flow_stat, flow_stats_list, 3010*0dc2366fSVenugopal Iyer FLOW_STAT_SIZE); 3011*0dc2366fSVenugopal Iyer } 3012*0dc2366fSVenugopal Iyer 3013*0dc2366fSVenugopal Iyer done: 3014*0dc2366fSVenugopal Iyer (void) kstat_close(kcp); 3015*0dc2366fSVenugopal Iyer return (flow_stat); 3016*0dc2366fSVenugopal Iyer } 3017*0dc2366fSVenugopal Iyer 3018*0dc2366fSVenugopal Iyer flow_stat_t * 3019*0dc2366fSVenugopal Iyer dladm_flow_stat_diff(flow_stat_t *op1, flow_stat_t *op2) 3020*0dc2366fSVenugopal Iyer { 3021*0dc2366fSVenugopal Iyer flow_stat_t *diff_stat; 3022*0dc2366fSVenugopal Iyer 3023*0dc2366fSVenugopal Iyer diff_stat = calloc(1, sizeof (flow_stat_t)); 3024*0dc2366fSVenugopal Iyer if (diff_stat == NULL) 3025*0dc2366fSVenugopal Iyer goto done; 3026*0dc2366fSVenugopal Iyer 3027*0dc2366fSVenugopal Iyer if (op2 == NULL) { 3028*0dc2366fSVenugopal Iyer bcopy(op1, diff_stat, sizeof (flow_stat_t)); 3029*0dc2366fSVenugopal Iyer } else { 3030*0dc2366fSVenugopal Iyer i_dlstat_diff_stats(diff_stat, op1, op2, flow_stats_list, 3031*0dc2366fSVenugopal Iyer FLOW_STAT_SIZE); 3032*0dc2366fSVenugopal Iyer } 3033*0dc2366fSVenugopal Iyer done: 3034*0dc2366fSVenugopal Iyer return (diff_stat); 3035*0dc2366fSVenugopal Iyer } 3036*0dc2366fSVenugopal Iyer 3037*0dc2366fSVenugopal Iyer void 3038*0dc2366fSVenugopal Iyer dladm_flow_stat_free(flow_stat_t *curr) 3039*0dc2366fSVenugopal Iyer { 3040*0dc2366fSVenugopal Iyer free(curr); 3041*0dc2366fSVenugopal Iyer } 3042*0dc2366fSVenugopal Iyer 3043*0dc2366fSVenugopal Iyer /* Query all flow stats */ 3044*0dc2366fSVenugopal Iyer name_value_stat_entry_t * 3045*0dc2366fSVenugopal Iyer dladm_flow_stat_query_all(const char *flowname) 3046*0dc2366fSVenugopal Iyer { 3047*0dc2366fSVenugopal Iyer flow_stat_t *flow_stat; 3048*0dc2366fSVenugopal Iyer name_value_stat_entry_t *name_value_stat_entry = NULL; 3049*0dc2366fSVenugopal Iyer 3050*0dc2366fSVenugopal Iyer /* Query flow stats */ 3051*0dc2366fSVenugopal Iyer flow_stat = dladm_flow_stat_query(flowname); 3052*0dc2366fSVenugopal Iyer if (flow_stat == NULL) 3053*0dc2366fSVenugopal Iyer goto done; 3054*0dc2366fSVenugopal Iyer 3055*0dc2366fSVenugopal Iyer /* Allocate memory for query all stat entry */ 3056*0dc2366fSVenugopal Iyer name_value_stat_entry = calloc(1, sizeof (name_value_stat_entry_t)); 3057*0dc2366fSVenugopal Iyer if (name_value_stat_entry == NULL) { 3058*0dc2366fSVenugopal Iyer dladm_flow_stat_free(flow_stat); 3059*0dc2366fSVenugopal Iyer goto done; 3060*0dc2366fSVenugopal Iyer } 3061*0dc2366fSVenugopal Iyer 3062*0dc2366fSVenugopal Iyer /* Header for these stat fields */ 3063*0dc2366fSVenugopal Iyer (void) strncpy(name_value_stat_entry->nve_header, flowname, 3064*0dc2366fSVenugopal Iyer MAXFLOWNAMELEN); 3065*0dc2366fSVenugopal Iyer 3066*0dc2366fSVenugopal Iyer /* Convert every statfield in flow_stat to <statname, statval> pair */ 3067*0dc2366fSVenugopal Iyer name_value_stat_entry->nve_stats = 3068*0dc2366fSVenugopal Iyer i_dlstat_convert_stats(flow_stat, flow_stats_list, FLOW_STAT_SIZE); 3069*0dc2366fSVenugopal Iyer 3070*0dc2366fSVenugopal Iyer /* Free flow_stat */ 3071*0dc2366fSVenugopal Iyer dladm_flow_stat_free(flow_stat); 3072*0dc2366fSVenugopal Iyer 3073*0dc2366fSVenugopal Iyer done: 3074*0dc2366fSVenugopal Iyer return (name_value_stat_entry); 3075*0dc2366fSVenugopal Iyer } 3076*0dc2366fSVenugopal Iyer 3077*0dc2366fSVenugopal Iyer void 3078*0dc2366fSVenugopal Iyer dladm_flow_stat_query_all_free(name_value_stat_entry_t *curr) 3079*0dc2366fSVenugopal Iyer { 3080*0dc2366fSVenugopal Iyer name_value_stat_t *nv_curr = curr->nve_stats; 3081*0dc2366fSVenugopal Iyer 3082*0dc2366fSVenugopal Iyer while (nv_curr != NULL) { 3083*0dc2366fSVenugopal Iyer name_value_stat_t *nv_tofree = nv_curr; 3084*0dc2366fSVenugopal Iyer 3085*0dc2366fSVenugopal Iyer nv_curr = nv_curr->nv_nextstat; 3086*0dc2366fSVenugopal Iyer free(nv_tofree); 3087*0dc2366fSVenugopal Iyer } 3088*0dc2366fSVenugopal Iyer } 3089