18275SEric Cheng /*
28275SEric Cheng * CDDL HEADER START
38275SEric Cheng *
48275SEric Cheng * The contents of this file are subject to the terms of the
58275SEric Cheng * Common Development and Distribution License (the "License").
68275SEric Cheng * You may not use this file except in compliance with the License.
78275SEric Cheng *
88275SEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98275SEric Cheng * or http://www.opensolaris.org/os/licensing.
108275SEric Cheng * See the License for the specific language governing permissions
118275SEric Cheng * and limitations under the License.
128275SEric Cheng *
138275SEric Cheng * When distributing Covered Code, include this CDDL HEADER in each
148275SEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158275SEric Cheng * If applicable, add the following below this CDDL HEADER, with the
168275SEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying
178275SEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner]
188275SEric Cheng *
198275SEric Cheng * CDDL HEADER END
208275SEric Cheng */
218275SEric Cheng /*
22*11878SVenu.Iyer@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
238275SEric Cheng * Use is subject to license terms.
248275SEric Cheng */
258275SEric Cheng
268275SEric Cheng #include <stdio.h>
278275SEric Cheng #include <stdlib.h>
288275SEric Cheng #include <strings.h>
298275SEric Cheng #include <err.h>
308275SEric Cheng #include <errno.h>
319421SMichael.Lim@Sun.COM #include <fcntl.h>
328275SEric Cheng #include <kstat.h>
339421SMichael.Lim@Sun.COM #include <limits.h>
348275SEric Cheng #include <unistd.h>
358275SEric Cheng #include <signal.h>
368275SEric Cheng #include <sys/dld.h>
379107Sjames.d.carlson@sun.com #include <sys/ddi.h>
388275SEric Cheng
398275SEric Cheng #include <libdllink.h>
408275SEric Cheng #include <libdlflow.h>
418275SEric Cheng #include <libdlstat.h>
42*11878SVenu.Iyer@Sun.COM #include <libdlaggr.h>
438275SEric Cheng
448275SEric Cheng /*
458275SEric Cheng * x86 <sys/regs> ERR conflicts with <curses.h> ERR.
468275SEric Cheng * Include curses.h last.
478275SEric Cheng */
488275SEric Cheng #if defined(ERR)
498275SEric Cheng #undef ERR
508275SEric Cheng #endif
518275SEric Cheng #include <curses.h>
528275SEric Cheng
538275SEric Cheng struct flowlist {
548558SGirish.Moodalbail@Sun.COM char flowname[MAXFLOWNAMELEN];
559421SMichael.Lim@Sun.COM char linkname[MAXLINKNAMELEN];
568275SEric Cheng datalink_id_t linkid;
579421SMichael.Lim@Sun.COM int fd;
588957SMichael.Lim@Sun.COM uint64_t ifspeed;
598275SEric Cheng boolean_t first;
608275SEric Cheng boolean_t display;
618275SEric Cheng pktsum_t prevstats;
628275SEric Cheng pktsum_t diffstats;
638275SEric Cheng };
648275SEric Cheng
658275SEric Cheng static int maxx, maxy, redraw = 0;
668275SEric Cheng static volatile uint_t handle_resize = 0, handle_break = 0;
678275SEric Cheng
688275SEric Cheng pktsum_t totalstats;
698275SEric Cheng struct flowlist *stattable = NULL;
708275SEric Cheng static int statentry = -1, maxstatentries = 0;
718275SEric Cheng
728275SEric Cheng #define STATGROWSIZE 16
738275SEric Cheng
748275SEric Cheng /*
758275SEric Cheng * Search for flowlist entry in stattable which matches
76*11878SVenu.Iyer@Sun.COM * the flowname and linkid. If no match is found, use
778275SEric Cheng * next available slot. If no slots are available,
788275SEric Cheng * reallocate table with more slots.
798275SEric Cheng *
808275SEric Cheng * Return: *flowlist of matching flow
818275SEric Cheng * NULL if realloc fails
828275SEric Cheng */
838275SEric Cheng
848275SEric Cheng static struct flowlist *
findstat(const char * flowname,datalink_id_t linkid)858275SEric Cheng findstat(const char *flowname, datalink_id_t linkid)
868275SEric Cheng {
878275SEric Cheng int match = 0;
888275SEric Cheng struct flowlist *flist;
898275SEric Cheng
908275SEric Cheng /* Look for match in the stattable */
918275SEric Cheng for (match = 0, flist = stattable;
928275SEric Cheng match <= statentry;
938275SEric Cheng match++, flist++) {
948275SEric Cheng
958275SEric Cheng if (flist == NULL)
968275SEric Cheng break;
978275SEric Cheng /* match the flowname */
988275SEric Cheng if (flowname != NULL) {
998558SGirish.Moodalbail@Sun.COM if (strncmp(flowname, flist->flowname, MAXFLOWNAMELEN)
1008275SEric Cheng == NULL)
1018275SEric Cheng return (flist);
1028275SEric Cheng /* match the linkid */
1038275SEric Cheng } else {
1048275SEric Cheng if (linkid == flist->linkid)
1058275SEric Cheng return (flist);
1068275SEric Cheng }
1078275SEric Cheng }
1088275SEric Cheng
1098275SEric Cheng /*
1108275SEric Cheng * No match found in the table. Store statistics in the next slot.
1118275SEric Cheng * If necessary, make room for this entry.
1128275SEric Cheng */
1138275SEric Cheng statentry++;
1148275SEric Cheng if ((maxstatentries == 0) || (maxstatentries == statentry)) {
1158275SEric Cheng maxstatentries += STATGROWSIZE;
1168275SEric Cheng stattable = realloc(stattable,
1178275SEric Cheng maxstatentries * sizeof (struct flowlist));
1188275SEric Cheng if (stattable == NULL) {
1198275SEric Cheng perror("realloc");
1208275SEric Cheng return (struct flowlist *)(NULL);
1218275SEric Cheng }
1228275SEric Cheng }
1238275SEric Cheng flist = &stattable[statentry];
1248275SEric Cheng bzero(flist, sizeof (struct flowlist));
1258275SEric Cheng
1268275SEric Cheng if (flowname != NULL)
1278558SGirish.Moodalbail@Sun.COM (void) strncpy(flist->flowname, flowname, MAXFLOWNAMELEN);
1288275SEric Cheng flist->linkid = linkid;
1299421SMichael.Lim@Sun.COM flist->fd = INT32_MAX;
1309421SMichael.Lim@Sun.COM
1318275SEric Cheng return (flist);
1328275SEric Cheng }
1338275SEric Cheng
1349421SMichael.Lim@Sun.COM /*ARGSUSED*/
1358275SEric Cheng static void
print_flow_stats(dladm_handle_t handle,struct flowlist * flist)1368453SAnurag.Maskey@Sun.COM print_flow_stats(dladm_handle_t handle, struct flowlist *flist)
1378275SEric Cheng {
1388275SEric Cheng struct flowlist *fcurr;
1398275SEric Cheng double ikbs, okbs;
1408275SEric Cheng double ipks, opks;
1418275SEric Cheng double dlt;
1428275SEric Cheng int fcount;
1438275SEric Cheng static boolean_t first = B_TRUE;
1448275SEric Cheng
1458275SEric Cheng if (first) {
1468275SEric Cheng first = B_FALSE;
1478275SEric Cheng (void) printw("please wait...\n");
1488275SEric Cheng return;
1498275SEric Cheng }
1508275SEric Cheng
1518275SEric Cheng for (fcount = 0, fcurr = flist;
1528275SEric Cheng fcount <= statentry;
1538275SEric Cheng fcount++, fcurr++) {
1548275SEric Cheng if (fcurr->flowname && fcurr->display) {
1558275SEric Cheng dlt = (double)fcurr->diffstats.snaptime/(double)NANOSEC;
1568275SEric Cheng ikbs = fcurr->diffstats.rbytes * 8 / dlt / 1024;
1578275SEric Cheng okbs = fcurr->diffstats.obytes * 8 / dlt / 1024;
1588275SEric Cheng ipks = fcurr->diffstats.ipackets / dlt;
1598275SEric Cheng opks = fcurr->diffstats.opackets / dlt;
1608275SEric Cheng (void) printw("%-15.15s", fcurr->flowname);
1619421SMichael.Lim@Sun.COM (void) printw("%-10.10s", fcurr->linkname);
1628275SEric Cheng (void) printw("%9.2f %9.2f %9.2f %9.2f ",
1638275SEric Cheng ikbs, okbs, ipks, opks);
1648275SEric Cheng (void) printw("\n");
1658275SEric Cheng }
1668275SEric Cheng }
1678275SEric Cheng }
1688275SEric Cheng
1698275SEric Cheng /*ARGSUSED*/
1708275SEric Cheng static int
flow_kstats(dladm_handle_t handle,dladm_flow_attr_t * attr,void * arg)1719421SMichael.Lim@Sun.COM flow_kstats(dladm_handle_t handle, dladm_flow_attr_t *attr, void *arg)
1728275SEric Cheng {
1738275SEric Cheng kstat_ctl_t *kcp = (kstat_ctl_t *)arg;
1748275SEric Cheng kstat_t *ksp;
1758275SEric Cheng struct flowlist *flist;
1768275SEric Cheng pktsum_t currstats, *prevstats, *diffstats;
1778275SEric Cheng
1788275SEric Cheng flist = findstat(attr->fa_flowname, attr->fa_linkid);
1799421SMichael.Lim@Sun.COM if (flist == NULL)
1809421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
1819421SMichael.Lim@Sun.COM
1829421SMichael.Lim@Sun.COM flist->display = B_FALSE;
1839421SMichael.Lim@Sun.COM prevstats = &flist->prevstats;
1849421SMichael.Lim@Sun.COM diffstats = &flist->diffstats;
1859421SMichael.Lim@Sun.COM
1869421SMichael.Lim@Sun.COM (void) dladm_datalink_id2info(handle, attr->fa_linkid, NULL, NULL,
1879421SMichael.Lim@Sun.COM NULL, flist->linkname, sizeof (flist->linkname));
1889421SMichael.Lim@Sun.COM
1898275SEric Cheng
1908275SEric Cheng /* lookup kstat entry */
1918275SEric Cheng ksp = dladm_kstat_lookup(kcp, NULL, -1, attr->fa_flowname, "flow");
1928275SEric Cheng
1938275SEric Cheng if (ksp == NULL)
1949421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
1958275SEric Cheng
1969421SMichael.Lim@Sun.COM /* read packet and byte stats */
1978275SEric Cheng dladm_get_stats(kcp, ksp, &currstats);
1989421SMichael.Lim@Sun.COM
1998275SEric Cheng if (flist->ifspeed == 0)
2008275SEric Cheng (void) dladm_kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64,
2018275SEric Cheng &flist->ifspeed);
2028275SEric Cheng
2039421SMichael.Lim@Sun.COM if (flist->first) {
2048275SEric Cheng flist->first = B_FALSE;
2059421SMichael.Lim@Sun.COM } else {
2068275SEric Cheng dladm_stats_diff(diffstats, &currstats, prevstats);
2079421SMichael.Lim@Sun.COM if (diffstats->snaptime == 0)
2089421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
2098275SEric Cheng dladm_stats_total(&totalstats, diffstats, &totalstats);
2108275SEric Cheng }
2118275SEric Cheng
2128275SEric Cheng bcopy(&currstats, prevstats, sizeof (pktsum_t));
2139421SMichael.Lim@Sun.COM flist->display = B_TRUE;
2149421SMichael.Lim@Sun.COM
2158275SEric Cheng return (DLADM_WALK_CONTINUE);
2168275SEric Cheng }
2178275SEric Cheng
2189421SMichael.Lim@Sun.COM /*ARGSUSED*/
2198275SEric Cheng static void
print_link_stats(dladm_handle_t handle,struct flowlist * flist)2208453SAnurag.Maskey@Sun.COM print_link_stats(dladm_handle_t handle, struct flowlist *flist)
2218275SEric Cheng {
2228275SEric Cheng struct flowlist *fcurr;
2238275SEric Cheng double ikbs, okbs;
2248275SEric Cheng double ipks, opks;
2258275SEric Cheng double util;
2268275SEric Cheng double dlt;
2278275SEric Cheng int fcount;
2288275SEric Cheng static boolean_t first = B_TRUE;
2298275SEric Cheng
2308275SEric Cheng if (first) {
2318275SEric Cheng first = B_FALSE;
2328275SEric Cheng (void) printw("please wait...\n");
2338275SEric Cheng return;
2348275SEric Cheng }
2358275SEric Cheng
2368275SEric Cheng for (fcount = 0, fcurr = flist;
2378275SEric Cheng fcount <= statentry;
2388275SEric Cheng fcount++, fcurr++) {
2398275SEric Cheng if ((fcurr->linkid != DATALINK_INVALID_LINKID) &&
2408275SEric Cheng fcurr->display) {
2418275SEric Cheng dlt = (double)fcurr->diffstats.snaptime/(double)NANOSEC;
2428275SEric Cheng ikbs = (double)fcurr->diffstats.rbytes * 8 / dlt / 1024;
2438275SEric Cheng okbs = (double)fcurr->diffstats.obytes * 8 / dlt / 1024;
2448275SEric Cheng ipks = (double)fcurr->diffstats.ipackets / dlt;
2458275SEric Cheng opks = (double)fcurr->diffstats.opackets / dlt;
2469421SMichael.Lim@Sun.COM (void) printw("%-10.10s", fcurr->linkname);
2478275SEric Cheng (void) printw("%9.2f %9.2f %9.2f %9.2f ",
2488275SEric Cheng ikbs, okbs, ipks, opks);
2498275SEric Cheng if (fcurr->ifspeed != 0)
2508275SEric Cheng util = ((ikbs + okbs) * 1024) *
2518275SEric Cheng 100/ fcurr->ifspeed;
2528275SEric Cheng else
2538275SEric Cheng util = (double)0;
2548275SEric Cheng (void) attron(A_BOLD);
2558275SEric Cheng (void) printw(" %6.2f", util);
2568275SEric Cheng (void) attroff(A_BOLD);
2578275SEric Cheng (void) printw("\n");
2588275SEric Cheng }
2598275SEric Cheng }
2608275SEric Cheng }
2618275SEric Cheng
2628275SEric Cheng /*
2638275SEric Cheng * This function is called through the dladm_walk_datalink_id() walker and
2648275SEric Cheng * calls the dladm_walk_flow() walker.
2658275SEric Cheng */
2668275SEric Cheng
2678275SEric Cheng /*ARGSUSED*/
2688275SEric Cheng static int
link_flowstats(dladm_handle_t handle,datalink_id_t linkid,void * arg)2698453SAnurag.Maskey@Sun.COM link_flowstats(dladm_handle_t handle, datalink_id_t linkid, void *arg)
2708275SEric Cheng {
2718621SMichael.Lim@Sun.COM dladm_status_t status;
2728621SMichael.Lim@Sun.COM
2738621SMichael.Lim@Sun.COM status = dladm_walk_flow(flow_kstats, handle, linkid, arg, B_FALSE);
2748621SMichael.Lim@Sun.COM if (status == DLADM_STATUS_OK)
2758621SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
2768621SMichael.Lim@Sun.COM else
2778621SMichael.Lim@Sun.COM return (DLADM_WALK_TERMINATE);
2788275SEric Cheng }
2798275SEric Cheng
2808275SEric Cheng /*ARGSUSED*/
2818275SEric Cheng static int
link_kstats(dladm_handle_t handle,datalink_id_t linkid,void * arg)2828453SAnurag.Maskey@Sun.COM link_kstats(dladm_handle_t handle, datalink_id_t linkid, void *arg)
2838275SEric Cheng {
2849421SMichael.Lim@Sun.COM kstat_ctl_t *kcp = (kstat_ctl_t *)arg;
2859421SMichael.Lim@Sun.COM struct flowlist *flist;
2869421SMichael.Lim@Sun.COM pktsum_t currstats, *prevstats, *diffstats;
2879421SMichael.Lim@Sun.COM datalink_class_t class;
2889421SMichael.Lim@Sun.COM kstat_t *ksp;
2899421SMichael.Lim@Sun.COM char dnlink[MAXPATHLEN];
2908275SEric Cheng
2918275SEric Cheng /* find the flist entry */
2928275SEric Cheng flist = findstat(NULL, linkid);
2939421SMichael.Lim@Sun.COM flist->display = B_FALSE;
2948275SEric Cheng if (flist != NULL) {
2958275SEric Cheng prevstats = &flist->prevstats;
2968275SEric Cheng diffstats = &flist->diffstats;
2978275SEric Cheng } else {
2988275SEric Cheng return (DLADM_WALK_CONTINUE);
2998275SEric Cheng }
3008275SEric Cheng
3019421SMichael.Lim@Sun.COM if (dladm_datalink_id2info(handle, linkid, NULL, &class, NULL,
3029421SMichael.Lim@Sun.COM flist->linkname, sizeof (flist->linkname)) != DLADM_STATUS_OK)
3039421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
3048275SEric Cheng
3059421SMichael.Lim@Sun.COM if (flist->fd == INT32_MAX) {
3069421SMichael.Lim@Sun.COM if (class == DATALINK_CLASS_PHYS) {
3079421SMichael.Lim@Sun.COM (void) snprintf(dnlink, MAXPATHLEN, "/dev/net/%s",
3089421SMichael.Lim@Sun.COM flist->linkname);
3099421SMichael.Lim@Sun.COM if ((flist->fd = open(dnlink, O_RDWR)) < 0)
3109421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
3119421SMichael.Lim@Sun.COM } else {
3129421SMichael.Lim@Sun.COM flist->fd = -1;
3139421SMichael.Lim@Sun.COM }
3149421SMichael.Lim@Sun.COM (void) kstat_chain_update(kcp);
3158275SEric Cheng }
3168275SEric Cheng
3179421SMichael.Lim@Sun.COM /* lookup kstat entry */
3189421SMichael.Lim@Sun.COM ksp = dladm_kstat_lookup(kcp, NULL, -1, flist->linkname, "net");
3198275SEric Cheng
3208275SEric Cheng if (ksp == NULL)
3219421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
3228275SEric Cheng
3238275SEric Cheng /* read packet and byte stats */
3248275SEric Cheng dladm_get_stats(kcp, ksp, &currstats);
3258275SEric Cheng
3268275SEric Cheng if (flist->ifspeed == 0)
3278275SEric Cheng (void) dladm_kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64,
3288275SEric Cheng &flist->ifspeed);
3298275SEric Cheng
3309421SMichael.Lim@Sun.COM if (flist->first) {
3318275SEric Cheng flist->first = B_FALSE;
3329421SMichael.Lim@Sun.COM } else {
3338275SEric Cheng dladm_stats_diff(diffstats, &currstats, prevstats);
3349421SMichael.Lim@Sun.COM if (diffstats->snaptime == 0)
3359421SMichael.Lim@Sun.COM return (DLADM_WALK_CONTINUE);
3369421SMichael.Lim@Sun.COM }
3378275SEric Cheng
3388275SEric Cheng bcopy(&currstats, prevstats, sizeof (*prevstats));
3399421SMichael.Lim@Sun.COM flist->display = B_TRUE;
3408275SEric Cheng
3418275SEric Cheng return (DLADM_WALK_CONTINUE);
3428275SEric Cheng }
3438275SEric Cheng
3449421SMichael.Lim@Sun.COM static void
closedevnet()3459421SMichael.Lim@Sun.COM closedevnet()
3469421SMichael.Lim@Sun.COM {
3479421SMichael.Lim@Sun.COM int index = 0;
3489421SMichael.Lim@Sun.COM struct flowlist *flist;
3499421SMichael.Lim@Sun.COM
3509421SMichael.Lim@Sun.COM /* Close all open /dev/net/ files */
351*11878SVenu.Iyer@Sun.COM
352*11878SVenu.Iyer@Sun.COM for (flist = stattable; index < maxstatentries; index++, flist++) {
3539421SMichael.Lim@Sun.COM if (flist->linkid == DATALINK_INVALID_LINKID)
3549421SMichael.Lim@Sun.COM break;
3559421SMichael.Lim@Sun.COM if (flist->fd != -1 && flist->fd != INT32_MAX)
3569421SMichael.Lim@Sun.COM (void) close(flist->fd);
3579421SMichael.Lim@Sun.COM }
3589421SMichael.Lim@Sun.COM }
3599421SMichael.Lim@Sun.COM
3608275SEric Cheng /*ARGSUSED*/
3618275SEric Cheng static void
sig_break(int s)3628275SEric Cheng sig_break(int s)
3638275SEric Cheng {
3648275SEric Cheng handle_break = 1;
3658275SEric Cheng }
3668275SEric Cheng
3678275SEric Cheng /*ARGSUSED*/
3688275SEric Cheng static void
sig_resize(int s)3698275SEric Cheng sig_resize(int s)
3708275SEric Cheng {
3718275SEric Cheng handle_resize = 1;
3728275SEric Cheng }
3738275SEric Cheng
3748275SEric Cheng static void
curses_init()3758275SEric Cheng curses_init()
3768275SEric Cheng {
3778275SEric Cheng maxx = maxx; /* lint */
3788275SEric Cheng maxy = maxy; /* lint */
3798275SEric Cheng
3808275SEric Cheng /* Install signal handlers */
3818275SEric Cheng (void) signal(SIGINT, sig_break);
3828275SEric Cheng (void) signal(SIGQUIT, sig_break);
3838275SEric Cheng (void) signal(SIGTERM, sig_break);
3848275SEric Cheng (void) signal(SIGWINCH, sig_resize);
3858275SEric Cheng
3868275SEric Cheng /* Initialize ncurses */
3878275SEric Cheng (void) initscr();
3888275SEric Cheng (void) cbreak();
3898275SEric Cheng (void) noecho();
3908275SEric Cheng (void) curs_set(0);
3918275SEric Cheng timeout(0);
3928275SEric Cheng getmaxyx(stdscr, maxy, maxx);
3938275SEric Cheng }
3948275SEric Cheng
3958275SEric Cheng static void
curses_fin()3968275SEric Cheng curses_fin()
3978275SEric Cheng {
3988275SEric Cheng (void) printw("\n");
3998275SEric Cheng (void) curs_set(1);
4008275SEric Cheng (void) nocbreak();
4018275SEric Cheng (void) endwin();
4028275SEric Cheng
4038275SEric Cheng free(stattable);
4048275SEric Cheng }
4058275SEric Cheng
4068275SEric Cheng static void
stat_report(dladm_handle_t handle,kstat_ctl_t * kcp,datalink_id_t linkid,const char * flowname,int opt)4078453SAnurag.Maskey@Sun.COM stat_report(dladm_handle_t handle, kstat_ctl_t *kcp, datalink_id_t linkid,
4088453SAnurag.Maskey@Sun.COM const char *flowname, int opt)
4098275SEric Cheng {
4108275SEric Cheng
4118275SEric Cheng double dlt, ikbs, okbs, ipks, opks;
4128275SEric Cheng
4138275SEric Cheng struct flowlist *fstable = stattable;
4148275SEric Cheng
4158275SEric Cheng if ((opt != LINK_REPORT) && (opt != FLOW_REPORT))
4168275SEric Cheng return;
4178275SEric Cheng
4188275SEric Cheng /* Handle window resizes */
4198275SEric Cheng if (handle_resize) {
4208275SEric Cheng (void) endwin();
4218275SEric Cheng (void) initscr();
4228275SEric Cheng (void) cbreak();
4238275SEric Cheng (void) noecho();
4248275SEric Cheng (void) curs_set(0);
4258275SEric Cheng timeout(0);
4268275SEric Cheng getmaxyx(stdscr, maxy, maxx);
4278275SEric Cheng redraw = 1;
4288275SEric Cheng handle_resize = 0;
4298275SEric Cheng }
4308275SEric Cheng
4318275SEric Cheng /* Print title */
4328275SEric Cheng (void) erase();
4338275SEric Cheng (void) attron(A_BOLD);
4348275SEric Cheng (void) move(0, 0);
4358275SEric Cheng if (opt == FLOW_REPORT)
4368275SEric Cheng (void) printw("%-15.15s", "Flow");
4378275SEric Cheng (void) printw("%-10.10s", "Link");
4388275SEric Cheng (void) printw("%9.9s %9.9s %9.9s %9.9s ",
4398275SEric Cheng "iKb/s", "oKb/s", "iPk/s", "oPk/s");
4408275SEric Cheng if (opt == LINK_REPORT)
4418275SEric Cheng (void) printw(" %6.6s", "%Util");
4428275SEric Cheng (void) printw("\n");
4438275SEric Cheng (void) attroff(A_BOLD);
4448275SEric Cheng
4458275SEric Cheng (void) move(2, 0);
4468275SEric Cheng
4478275SEric Cheng /* Print stats for each link or flow */
4488275SEric Cheng bzero(&totalstats, sizeof (totalstats));
4498275SEric Cheng if (opt == LINK_REPORT) {
4508275SEric Cheng /* Display all links */
4518275SEric Cheng if (linkid == DATALINK_ALL_LINKID) {
4528453SAnurag.Maskey@Sun.COM (void) dladm_walk_datalink_id(link_kstats, handle,
4538275SEric Cheng (void *)kcp, DATALINK_CLASS_ALL,
4548275SEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
4558275SEric Cheng /* Display 1 link */
4568275SEric Cheng } else {
4578453SAnurag.Maskey@Sun.COM (void) link_kstats(handle, linkid, kcp);
4588275SEric Cheng }
4598453SAnurag.Maskey@Sun.COM print_link_stats(handle, fstable);
4608275SEric Cheng
4618275SEric Cheng } else if (opt == FLOW_REPORT) {
4628275SEric Cheng /* Display 1 flow */
4638275SEric Cheng if (flowname != NULL) {
4648275SEric Cheng dladm_flow_attr_t fattr;
4658453SAnurag.Maskey@Sun.COM if (dladm_flow_info(handle, flowname, &fattr) !=
4668275SEric Cheng DLADM_STATUS_OK)
4678275SEric Cheng return;
4689421SMichael.Lim@Sun.COM (void) flow_kstats(handle, &fattr, kcp);
4698275SEric Cheng /* Display all flows on all links */
4708275SEric Cheng } else if (linkid == DATALINK_ALL_LINKID) {
4718453SAnurag.Maskey@Sun.COM (void) dladm_walk_datalink_id(link_flowstats, handle,
4728275SEric Cheng (void *)kcp, DATALINK_CLASS_ALL,
4738275SEric Cheng DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
4748275SEric Cheng /* Display all flows on a link */
4758275SEric Cheng } else if (linkid != DATALINK_INVALID_LINKID) {
4768453SAnurag.Maskey@Sun.COM (void) dladm_walk_flow(flow_kstats, handle, linkid, kcp,
4778275SEric Cheng B_FALSE);
4788275SEric Cheng }
4798453SAnurag.Maskey@Sun.COM print_flow_stats(handle, fstable);
4808275SEric Cheng
4818275SEric Cheng /* Print totals */
4828275SEric Cheng (void) attron(A_BOLD);
4838275SEric Cheng dlt = (double)totalstats.snaptime / (double)NANOSEC;
4848275SEric Cheng ikbs = totalstats.rbytes / dlt / 1024;
4858275SEric Cheng okbs = totalstats.obytes / dlt / 1024;
4868275SEric Cheng ipks = totalstats.ipackets / dlt;
4878275SEric Cheng opks = totalstats.opackets / dlt;
4888275SEric Cheng (void) printw("\n%-25.25s", "Totals");
4898275SEric Cheng (void) printw("%9.2f %9.2f %9.2f %9.2f ",
4908275SEric Cheng ikbs, okbs, ipks, opks);
4918275SEric Cheng (void) attroff(A_BOLD);
4928275SEric Cheng }
4938275SEric Cheng
4948275SEric Cheng if (redraw)
4958275SEric Cheng (void) clearok(stdscr, 1);
4968275SEric Cheng
4978275SEric Cheng if (refresh() == ERR)
4988275SEric Cheng return;
4998275SEric Cheng
5008275SEric Cheng if (redraw) {
5018275SEric Cheng (void) clearok(stdscr, 0);
5028275SEric Cheng redraw = 0;
5038275SEric Cheng }
5048275SEric Cheng }
5058275SEric Cheng
5068275SEric Cheng /* Exported functions */
5078275SEric Cheng
5088275SEric Cheng /*
5098275SEric Cheng * Continuously display link or flow statstics using a libcurses
5108275SEric Cheng * based display.
5118275SEric Cheng */
5128275SEric Cheng
5138275SEric Cheng void
dladm_continuous(dladm_handle_t handle,datalink_id_t linkid,const char * flowname,int interval,int opt)5148453SAnurag.Maskey@Sun.COM dladm_continuous(dladm_handle_t handle, datalink_id_t linkid,
5158453SAnurag.Maskey@Sun.COM const char *flowname, int interval, int opt)
5168275SEric Cheng {
5178275SEric Cheng kstat_ctl_t *kcp;
5188275SEric Cheng
5198275SEric Cheng if ((kcp = kstat_open()) == NULL) {
5208275SEric Cheng warn("kstat open operation failed");
5218275SEric Cheng return;
5228275SEric Cheng }
5238275SEric Cheng
5248275SEric Cheng curses_init();
5258275SEric Cheng
5268275SEric Cheng for (;;) {
5278275SEric Cheng
5288275SEric Cheng if (handle_break)
5298275SEric Cheng break;
5308275SEric Cheng
5318453SAnurag.Maskey@Sun.COM stat_report(handle, kcp, linkid, flowname, opt);
5328275SEric Cheng
5338275SEric Cheng (void) sleep(max(1, interval));
5348275SEric Cheng }
5358275SEric Cheng
5369421SMichael.Lim@Sun.COM closedevnet();
5379421SMichael.Lim@Sun.COM curses_fin();
5388275SEric Cheng (void) kstat_close(kcp);
5398275SEric Cheng }
5408275SEric Cheng
5418275SEric Cheng /*
5428275SEric Cheng * dladm_kstat_lookup() is a modified version of kstat_lookup which
5438275SEric Cheng * adds the class as a selector.
5448275SEric Cheng */
5458275SEric Cheng
5468275SEric Cheng kstat_t *
dladm_kstat_lookup(kstat_ctl_t * kcp,const char * module,int instance,const char * name,const char * class)5478275SEric Cheng dladm_kstat_lookup(kstat_ctl_t *kcp, const char *module, int instance,
5488275SEric Cheng const char *name, const char *class)
5498275SEric Cheng {
5508275SEric Cheng kstat_t *ksp = NULL;
5518275SEric Cheng
5528275SEric Cheng for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
5538275SEric Cheng if ((module == NULL || strcmp(ksp->ks_module, module) == 0) &&
5548275SEric Cheng (instance == -1 || ksp->ks_instance == instance) &&
5558275SEric Cheng (name == NULL || strcmp(ksp->ks_name, name) == 0) &&
5568275SEric Cheng (class == NULL || strcmp(ksp->ks_class, class) == 0))
5578275SEric Cheng return (ksp);
5588275SEric Cheng }
5598275SEric Cheng
5608275SEric Cheng errno = ENOENT;
5618275SEric Cheng return (NULL);
5628275SEric Cheng }
5638275SEric Cheng
5648275SEric Cheng /*
5658275SEric Cheng * dladm_get_stats() populates the supplied pktsum_t structure with
5668275SEric Cheng * the input and output packet and byte kstats from the kstat_t
5678275SEric Cheng * found with dladm_kstat_lookup.
5688275SEric Cheng */
5698275SEric Cheng void
dladm_get_stats(kstat_ctl_t * kcp,kstat_t * ksp,pktsum_t * stats)5708275SEric Cheng dladm_get_stats(kstat_ctl_t *kcp, kstat_t *ksp, pktsum_t *stats)
5718275SEric Cheng {
5728275SEric Cheng
5738275SEric Cheng if (kstat_read(kcp, ksp, NULL) == -1)
5748275SEric Cheng return;
5758275SEric Cheng
5768275SEric Cheng stats->snaptime = gethrtime();
5778275SEric Cheng
5788275SEric Cheng if (dladm_kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64,
5798275SEric Cheng &stats->ipackets) < 0) {
5808275SEric Cheng if (dladm_kstat_value(ksp, "ipackets", KSTAT_DATA_UINT64,
5818275SEric Cheng &stats->ipackets) < 0)
5828275SEric Cheng return;
5838275SEric Cheng }
5848275SEric Cheng
5858275SEric Cheng if (dladm_kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64,
5868275SEric Cheng &stats->opackets) < 0) {
5878275SEric Cheng if (dladm_kstat_value(ksp, "opackets", KSTAT_DATA_UINT64,
5888275SEric Cheng &stats->opackets) < 0)
5898275SEric Cheng return;
5908275SEric Cheng }
5918275SEric Cheng
5928275SEric Cheng if (dladm_kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64,
5938275SEric Cheng &stats->rbytes) < 0) {
5948275SEric Cheng if (dladm_kstat_value(ksp, "rbytes", KSTAT_DATA_UINT64,
5958275SEric Cheng &stats->rbytes) < 0)
5968275SEric Cheng return;
5978275SEric Cheng }
5988275SEric Cheng
5998275SEric Cheng if (dladm_kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64,
6008275SEric Cheng &stats->obytes) < 0) {
6018275SEric Cheng if (dladm_kstat_value(ksp, "obytes", KSTAT_DATA_UINT64,
6028275SEric Cheng &stats->obytes) < 0)
6038275SEric Cheng return;
6048275SEric Cheng }
6058275SEric Cheng
6068275SEric Cheng if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32,
6078275SEric Cheng &stats->ierrors) < 0) {
6088275SEric Cheng if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT64,
6098275SEric Cheng &stats->ierrors) < 0)
6108275SEric Cheng return;
6118275SEric Cheng }
6128275SEric Cheng
6138275SEric Cheng if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32,
6148275SEric Cheng &stats->oerrors) < 0) {
6158275SEric Cheng if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT64,
6168275SEric Cheng &stats->oerrors) < 0)
6178275SEric Cheng return;
6188275SEric Cheng }
6198275SEric Cheng }
6208275SEric Cheng
6218275SEric Cheng int
dladm_kstat_value(kstat_t * ksp,const char * name,uint8_t type,void * buf)6228275SEric Cheng dladm_kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf)
6238275SEric Cheng {
6248275SEric Cheng kstat_named_t *knp;
6258275SEric Cheng
6268275SEric Cheng if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL)
6278275SEric Cheng return (-1);
6288275SEric Cheng
6298275SEric Cheng if (knp->data_type != type)
6308275SEric Cheng return (-1);
6318275SEric Cheng
6328275SEric Cheng switch (type) {
6338275SEric Cheng case KSTAT_DATA_UINT64:
6348275SEric Cheng *(uint64_t *)buf = knp->value.ui64;
6358275SEric Cheng break;
6368275SEric Cheng case KSTAT_DATA_UINT32:
6378275SEric Cheng *(uint32_t *)buf = knp->value.ui32;
6388275SEric Cheng break;
6398275SEric Cheng default:
6408275SEric Cheng return (-1);
6418275SEric Cheng }
6428275SEric Cheng
6438275SEric Cheng return (0);
6448275SEric Cheng }
6458275SEric Cheng
6468275SEric Cheng dladm_status_t
dladm_get_single_mac_stat(dladm_handle_t handle,datalink_id_t linkid,const char * name,uint8_t type,void * val)6478453SAnurag.Maskey@Sun.COM dladm_get_single_mac_stat(dladm_handle_t handle, datalink_id_t linkid,
6488453SAnurag.Maskey@Sun.COM const char *name, uint8_t type, void *val)
6498275SEric Cheng {
6508275SEric Cheng kstat_ctl_t *kcp;
6518275SEric Cheng char module[DLPI_LINKNAME_MAX];
6528275SEric Cheng uint_t instance;
6538275SEric Cheng char link[DLPI_LINKNAME_MAX];
6548275SEric Cheng dladm_status_t status;
6558275SEric Cheng uint32_t flags, media;
6568275SEric Cheng kstat_t *ksp;
6578275SEric Cheng dladm_phys_attr_t dpap;
6588275SEric Cheng
6598453SAnurag.Maskey@Sun.COM if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
6608453SAnurag.Maskey@Sun.COM &media, link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK)
6618275SEric Cheng return (status);
6628275SEric Cheng
6638275SEric Cheng if (media != DL_ETHER)
6648275SEric Cheng return (DLADM_STATUS_LINKINVAL);
6658275SEric Cheng
6668453SAnurag.Maskey@Sun.COM status = dladm_phys_info(handle, linkid, &dpap, DLADM_OPT_PERSIST);
6678275SEric Cheng
6688275SEric Cheng if (status != DLADM_STATUS_OK)
6698275SEric Cheng return (status);
6708275SEric Cheng
6718275SEric Cheng status = dladm_parselink(dpap.dp_dev, module, &instance);
6728275SEric Cheng
6738275SEric Cheng if (status != DLADM_STATUS_OK)
6748275SEric Cheng return (status);
6758275SEric Cheng
6769571SSowmini.Varadhan@Sun.COM if ((kcp = kstat_open()) == NULL) {
6779571SSowmini.Varadhan@Sun.COM warn("kstat_open operation failed");
6789571SSowmini.Varadhan@Sun.COM return (-1);
6799571SSowmini.Varadhan@Sun.COM }
6809571SSowmini.Varadhan@Sun.COM
6818275SEric Cheng /*
6828275SEric Cheng * The kstat query could fail if the underlying MAC
6838275SEric Cheng * driver was already detached.
6848275SEric Cheng */
6858275SEric Cheng if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL &&
6868275SEric Cheng (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL)
6878275SEric Cheng goto bail;
6888275SEric Cheng
6898275SEric Cheng if (kstat_read(kcp, ksp, NULL) == -1)
6908275SEric Cheng goto bail;
6918275SEric Cheng
6928275SEric Cheng if (dladm_kstat_value(ksp, name, type, val) < 0)
6938275SEric Cheng goto bail;
6948275SEric Cheng
6958275SEric Cheng (void) kstat_close(kcp);
6968275SEric Cheng return (DLADM_STATUS_OK);
6978275SEric Cheng
6988275SEric Cheng bail:
6998275SEric Cheng (void) kstat_close(kcp);
7008275SEric Cheng return (dladm_errno2status(errno));
7018275SEric Cheng }
7028275SEric Cheng
7038275SEric Cheng /* Compute sum of 2 pktsums (s1 = s2 + s3) */
7048275SEric Cheng void
dladm_stats_total(pktsum_t * s1,pktsum_t * s2,pktsum_t * s3)7058275SEric Cheng dladm_stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3)
7068275SEric Cheng {
7078275SEric Cheng s1->rbytes = s2->rbytes + s3->rbytes;
7088275SEric Cheng s1->ipackets = s2->ipackets + s3->ipackets;
7098275SEric Cheng s1->ierrors = s2->ierrors + s3->ierrors;
7108275SEric Cheng s1->obytes = s2->obytes + s3->obytes;
7118275SEric Cheng s1->opackets = s2->opackets + s3->opackets;
7128275SEric Cheng s1->oerrors = s2->oerrors + s3->oerrors;
7138275SEric Cheng s1->snaptime = s2->snaptime;
7148275SEric Cheng }
7158275SEric Cheng
716*11878SVenu.Iyer@Sun.COM #define DIFF_STAT(s2, s3) ((s2) > (s3) ? ((s2) - (s3)) : 0)
7179220SPrakash.Jalan@Sun.COM
7189220SPrakash.Jalan@Sun.COM
7198275SEric Cheng /* Compute differences between 2 pktsums (s1 = s2 - s3) */
7208275SEric Cheng void
dladm_stats_diff(pktsum_t * s1,pktsum_t * s2,pktsum_t * s3)7218275SEric Cheng dladm_stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3)
7228275SEric Cheng {
7239220SPrakash.Jalan@Sun.COM s1->rbytes = DIFF_STAT(s2->rbytes, s3->rbytes);
7249220SPrakash.Jalan@Sun.COM s1->ipackets = DIFF_STAT(s2->ipackets, s3->ipackets);
7259220SPrakash.Jalan@Sun.COM s1->ierrors = DIFF_STAT(s2->ierrors, s3->ierrors);
7269220SPrakash.Jalan@Sun.COM s1->obytes = DIFF_STAT(s2->obytes, s3->obytes);
7279220SPrakash.Jalan@Sun.COM s1->opackets = DIFF_STAT(s2->opackets, s3->opackets);
7289220SPrakash.Jalan@Sun.COM s1->oerrors = DIFF_STAT(s2->oerrors, s3->oerrors);
7299220SPrakash.Jalan@Sun.COM s1->snaptime = DIFF_STAT(s2->snaptime, s3->snaptime);
7308275SEric Cheng }
731*11878SVenu.Iyer@Sun.COM
732*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_RX_SWLANE "mac_rx_swlane"
733*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_RX_HWLANE "mac_rx_hwlane"
734*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_TX_SWLANE "mac_tx_swlane"
735*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_TX_HWLANE "mac_tx_hwlane"
736*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_MISC_STAT "mac_misc_stat"
737*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_RX_RING "mac_rx_ring"
738*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_TX_RING "mac_tx_ring"
739*11878SVenu.Iyer@Sun.COM #define DLSTAT_MAC_FANOUT "mac_rx_swlane0_fanout"
740*11878SVenu.Iyer@Sun.COM
741*11878SVenu.Iyer@Sun.COM typedef struct {
742*11878SVenu.Iyer@Sun.COM const char *si_name;
743*11878SVenu.Iyer@Sun.COM uint_t si_offset;
744*11878SVenu.Iyer@Sun.COM } stat_info_t;
745*11878SVenu.Iyer@Sun.COM
746*11878SVenu.Iyer@Sun.COM #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0]))
747*11878SVenu.Iyer@Sun.COM
748*11878SVenu.Iyer@Sun.COM /* Definitions for rx lane stats */
749*11878SVenu.Iyer@Sun.COM #define RL_OFF(f) (offsetof(rx_lane_stat_t, f))
750*11878SVenu.Iyer@Sun.COM
751*11878SVenu.Iyer@Sun.COM static stat_info_t rx_hwlane_stats_list[] = {
752*11878SVenu.Iyer@Sun.COM {"ipackets", RL_OFF(rl_ipackets)},
753*11878SVenu.Iyer@Sun.COM {"rbytes", RL_OFF(rl_rbytes)},
754*11878SVenu.Iyer@Sun.COM {"intrs", RL_OFF(rl_intrs)},
755*11878SVenu.Iyer@Sun.COM {"intrbytes", RL_OFF(rl_intrbytes)},
756*11878SVenu.Iyer@Sun.COM {"polls", RL_OFF(rl_polls)},
757*11878SVenu.Iyer@Sun.COM {"pollbytes", RL_OFF(rl_pollbytes)},
758*11878SVenu.Iyer@Sun.COM {"rxsdrops", RL_OFF(rl_sdrops)},
759*11878SVenu.Iyer@Sun.COM {"chainunder10", RL_OFF(rl_chl10)},
760*11878SVenu.Iyer@Sun.COM {"chain10to50", RL_OFF(rl_ch10_50)},
761*11878SVenu.Iyer@Sun.COM {"chainover50", RL_OFF(rl_chg50)}
762*11878SVenu.Iyer@Sun.COM };
763*11878SVenu.Iyer@Sun.COM #define RX_HWLANE_STAT_SIZE A_CNT(rx_hwlane_stats_list)
764*11878SVenu.Iyer@Sun.COM
765*11878SVenu.Iyer@Sun.COM static stat_info_t rx_swlane_stats_list[] = {
766*11878SVenu.Iyer@Sun.COM {"ipackets", RL_OFF(rl_ipackets)},
767*11878SVenu.Iyer@Sun.COM {"rbytes", RL_OFF(rl_rbytes)},
768*11878SVenu.Iyer@Sun.COM {"local", RL_OFF(rl_lclpackets)},
769*11878SVenu.Iyer@Sun.COM {"localbytes", RL_OFF(rl_lclbytes)},
770*11878SVenu.Iyer@Sun.COM {"intrs", RL_OFF(rl_intrs)},
771*11878SVenu.Iyer@Sun.COM {"intrbytes", RL_OFF(rl_intrbytes)},
772*11878SVenu.Iyer@Sun.COM {"rxsdrops", RL_OFF(rl_sdrops)}
773*11878SVenu.Iyer@Sun.COM };
774*11878SVenu.Iyer@Sun.COM #define RX_SWLANE_STAT_SIZE A_CNT(rx_swlane_stats_list)
775*11878SVenu.Iyer@Sun.COM
776*11878SVenu.Iyer@Sun.COM static stat_info_t rx_lane_stats_list[] = {
777*11878SVenu.Iyer@Sun.COM {"ipackets", RL_OFF(rl_ipackets)},
778*11878SVenu.Iyer@Sun.COM {"rbytes", RL_OFF(rl_rbytes)},
779*11878SVenu.Iyer@Sun.COM {"local", RL_OFF(rl_lclpackets)},
780*11878SVenu.Iyer@Sun.COM {"localbytes", RL_OFF(rl_lclbytes)},
781*11878SVenu.Iyer@Sun.COM {"intrs", RL_OFF(rl_intrs)},
782*11878SVenu.Iyer@Sun.COM {"intrbytes", RL_OFF(rl_intrbytes)},
783*11878SVenu.Iyer@Sun.COM {"polls", RL_OFF(rl_polls)},
784*11878SVenu.Iyer@Sun.COM {"rxsdrops", RL_OFF(rl_sdrops)},
785*11878SVenu.Iyer@Sun.COM {"pollbytes", RL_OFF(rl_pollbytes)},
786*11878SVenu.Iyer@Sun.COM {"chainunder10", RL_OFF(rl_chl10)},
787*11878SVenu.Iyer@Sun.COM {"chain10to50", RL_OFF(rl_ch10_50)},
788*11878SVenu.Iyer@Sun.COM {"chainover50", RL_OFF(rl_chg50)}
789*11878SVenu.Iyer@Sun.COM };
790*11878SVenu.Iyer@Sun.COM #define RX_LANE_STAT_SIZE A_CNT(rx_lane_stats_list)
791*11878SVenu.Iyer@Sun.COM
792*11878SVenu.Iyer@Sun.COM /* Definitions for tx lane stats */
793*11878SVenu.Iyer@Sun.COM #define TL_OFF(f) (offsetof(tx_lane_stat_t, f))
794*11878SVenu.Iyer@Sun.COM
795*11878SVenu.Iyer@Sun.COM static stat_info_t tx_lane_stats_list[] = {
796*11878SVenu.Iyer@Sun.COM {"opackets", TL_OFF(tl_opackets)},
797*11878SVenu.Iyer@Sun.COM {"obytes", TL_OFF(tl_obytes)},
798*11878SVenu.Iyer@Sun.COM {"blockcnt", TL_OFF(tl_blockcnt)},
799*11878SVenu.Iyer@Sun.COM {"unblockcnt", TL_OFF(tl_unblockcnt)},
800*11878SVenu.Iyer@Sun.COM {"txsdrops", TL_OFF(tl_sdrops)}
801*11878SVenu.Iyer@Sun.COM };
802*11878SVenu.Iyer@Sun.COM #define TX_LANE_STAT_SIZE A_CNT(tx_lane_stats_list)
803*11878SVenu.Iyer@Sun.COM
804*11878SVenu.Iyer@Sun.COM /* Definitions for tx/rx misc stats */
805*11878SVenu.Iyer@Sun.COM #define M_OFF(f) (offsetof(misc_stat_t, f))
806*11878SVenu.Iyer@Sun.COM
807*11878SVenu.Iyer@Sun.COM static stat_info_t misc_stats_list[] = {
808*11878SVenu.Iyer@Sun.COM {"multircv", M_OFF(ms_multircv)},
809*11878SVenu.Iyer@Sun.COM {"brdcstrcv", M_OFF(ms_brdcstrcv)},
810*11878SVenu.Iyer@Sun.COM {"multixmt", M_OFF(ms_multixmt)},
811*11878SVenu.Iyer@Sun.COM {"brdcstxmt", M_OFF(ms_brdcstxmt)},
812*11878SVenu.Iyer@Sun.COM {"multircvbytes", M_OFF(ms_multircvbytes)},
813*11878SVenu.Iyer@Sun.COM {"brdcstrcvbytes", M_OFF(ms_brdcstrcvbytes)},
814*11878SVenu.Iyer@Sun.COM {"multixmtbytes", M_OFF(ms_multixmtbytes)},
815*11878SVenu.Iyer@Sun.COM {"brdcstxmtbytes", M_OFF(ms_brdcstxmtbytes)},
816*11878SVenu.Iyer@Sun.COM {"txerrors", M_OFF(ms_txerrors)},
817*11878SVenu.Iyer@Sun.COM {"macspoofed", M_OFF(ms_macspoofed)},
818*11878SVenu.Iyer@Sun.COM {"ipspoofed", M_OFF(ms_ipspoofed)},
819*11878SVenu.Iyer@Sun.COM {"dhcpspoofed", M_OFF(ms_dhcpspoofed)},
820*11878SVenu.Iyer@Sun.COM {"restricted", M_OFF(ms_restricted)},
821*11878SVenu.Iyer@Sun.COM {"ipackets", M_OFF(ms_ipackets)},
822*11878SVenu.Iyer@Sun.COM {"rbytes", M_OFF(ms_rbytes)},
823*11878SVenu.Iyer@Sun.COM {"local", M_OFF(ms_local)},
824*11878SVenu.Iyer@Sun.COM {"localbytes", M_OFF(ms_localbytes)},
825*11878SVenu.Iyer@Sun.COM {"intrs", M_OFF(ms_intrs)},
826*11878SVenu.Iyer@Sun.COM {"intrbytes", M_OFF(ms_intrbytes)},
827*11878SVenu.Iyer@Sun.COM {"polls", M_OFF(ms_polls)},
828*11878SVenu.Iyer@Sun.COM {"pollbytes", M_OFF(ms_pollbytes)},
829*11878SVenu.Iyer@Sun.COM {"rxsdrops", M_OFF(ms_rxsdrops)},
830*11878SVenu.Iyer@Sun.COM {"chainunder10", M_OFF(ms_chainunder10)},
831*11878SVenu.Iyer@Sun.COM {"chain10to50", M_OFF(ms_chain10to50)},
832*11878SVenu.Iyer@Sun.COM {"chainover50", M_OFF(ms_chainover50)},
833*11878SVenu.Iyer@Sun.COM {"obytes", M_OFF(ms_obytes)},
834*11878SVenu.Iyer@Sun.COM {"opackets", M_OFF(ms_opackets)},
835*11878SVenu.Iyer@Sun.COM {"blockcnt", M_OFF(ms_blockcnt)},
836*11878SVenu.Iyer@Sun.COM {"unblockcnt", M_OFF(ms_unblockcnt)},
837*11878SVenu.Iyer@Sun.COM {"txsdrops", M_OFF(ms_txsdrops)}
838*11878SVenu.Iyer@Sun.COM };
839*11878SVenu.Iyer@Sun.COM #define MISC_STAT_SIZE A_CNT(misc_stats_list)
840*11878SVenu.Iyer@Sun.COM
841*11878SVenu.Iyer@Sun.COM /* Definitions for rx ring stats */
842*11878SVenu.Iyer@Sun.COM #define R_OFF(f) (offsetof(ring_stat_t, f))
843*11878SVenu.Iyer@Sun.COM
844*11878SVenu.Iyer@Sun.COM static stat_info_t rx_ring_stats_list[] = {
845*11878SVenu.Iyer@Sun.COM {"ipackets", R_OFF(r_packets)},
846*11878SVenu.Iyer@Sun.COM {"rbytes", R_OFF(r_bytes)}
847*11878SVenu.Iyer@Sun.COM };
848*11878SVenu.Iyer@Sun.COM #define RX_RING_STAT_SIZE A_CNT(rx_ring_stats_list)
849*11878SVenu.Iyer@Sun.COM
850*11878SVenu.Iyer@Sun.COM /* Definitions for tx ring stats */
851*11878SVenu.Iyer@Sun.COM static stat_info_t tx_ring_stats_list[] = {
852*11878SVenu.Iyer@Sun.COM {"opackets", R_OFF(r_packets)},
853*11878SVenu.Iyer@Sun.COM {"obytes", R_OFF(r_bytes)}
854*11878SVenu.Iyer@Sun.COM };
855*11878SVenu.Iyer@Sun.COM #define TX_RING_STAT_SIZE A_CNT(tx_ring_stats_list)
856*11878SVenu.Iyer@Sun.COM
857*11878SVenu.Iyer@Sun.COM /* Definitions for fanout stats */
858*11878SVenu.Iyer@Sun.COM #define F_OFF(f) (offsetof(fanout_stat_t, f))
859*11878SVenu.Iyer@Sun.COM
860*11878SVenu.Iyer@Sun.COM static stat_info_t fanout_stats_list[] = {
861*11878SVenu.Iyer@Sun.COM {"ipackets", F_OFF(f_ipackets)},
862*11878SVenu.Iyer@Sun.COM {"rbytes", F_OFF(f_rbytes)},
863*11878SVenu.Iyer@Sun.COM };
864*11878SVenu.Iyer@Sun.COM #define FANOUT_STAT_SIZE A_CNT(fanout_stats_list)
865*11878SVenu.Iyer@Sun.COM
866*11878SVenu.Iyer@Sun.COM /* Definitions for total stats */
867*11878SVenu.Iyer@Sun.COM #define T_OFF(f) (offsetof(total_stat_t, f))
868*11878SVenu.Iyer@Sun.COM
869*11878SVenu.Iyer@Sun.COM static stat_info_t total_stats_list[] = {
870*11878SVenu.Iyer@Sun.COM {"ipackets", T_OFF(ts_ipackets)},
871*11878SVenu.Iyer@Sun.COM {"rbytes", T_OFF(ts_rbytes)},
872*11878SVenu.Iyer@Sun.COM {"opackets", T_OFF(ts_opackets)},
873*11878SVenu.Iyer@Sun.COM {"obytes", T_OFF(ts_obytes)}
874*11878SVenu.Iyer@Sun.COM };
875*11878SVenu.Iyer@Sun.COM #define TOTAL_STAT_SIZE A_CNT(total_stats_list)
876*11878SVenu.Iyer@Sun.COM
877*11878SVenu.Iyer@Sun.COM /* Definitions for aggr stats */
878*11878SVenu.Iyer@Sun.COM #define AP_OFF(f) (offsetof(aggr_port_stat_t, f))
879*11878SVenu.Iyer@Sun.COM
880*11878SVenu.Iyer@Sun.COM static stat_info_t aggr_port_stats_list[] = {
881*11878SVenu.Iyer@Sun.COM {"ipackets64", AP_OFF(ap_ipackets)},
882*11878SVenu.Iyer@Sun.COM {"rbytes64", AP_OFF(ap_rbytes)},
883*11878SVenu.Iyer@Sun.COM {"opackets64", AP_OFF(ap_opackets)},
884*11878SVenu.Iyer@Sun.COM {"obytes64", AP_OFF(ap_obytes)}
885*11878SVenu.Iyer@Sun.COM };
886*11878SVenu.Iyer@Sun.COM #define AGGR_PORT_STAT_SIZE A_CNT(aggr_port_stats_list)
887*11878SVenu.Iyer@Sun.COM
888*11878SVenu.Iyer@Sun.COM /* Definitions for flow stats */
889*11878SVenu.Iyer@Sun.COM #define FL_OFF(f) (offsetof(flow_stat_t, f))
890*11878SVenu.Iyer@Sun.COM
891*11878SVenu.Iyer@Sun.COM static stat_info_t flow_stats_list[] = {
892*11878SVenu.Iyer@Sun.COM {"ipackets", FL_OFF(fl_ipackets)},
893*11878SVenu.Iyer@Sun.COM {"rbytes", FL_OFF(fl_rbytes)},
894*11878SVenu.Iyer@Sun.COM {"opackets", FL_OFF(fl_opackets)},
895*11878SVenu.Iyer@Sun.COM {"obytes", FL_OFF(fl_obytes)}
896*11878SVenu.Iyer@Sun.COM };
897*11878SVenu.Iyer@Sun.COM #define FLOW_STAT_SIZE A_CNT(flow_stats_list)
898*11878SVenu.Iyer@Sun.COM
899*11878SVenu.Iyer@Sun.COM /* Rx lane specific functions */
900*11878SVenu.Iyer@Sun.COM void * dlstat_rx_lane_stats(dladm_handle_t, datalink_id_t);
901*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_rx_lane_match(void *, void *);
902*11878SVenu.Iyer@Sun.COM static void * i_dlstat_rx_lane_stat_entry_diff(void *, void *);
903*11878SVenu.Iyer@Sun.COM
904*11878SVenu.Iyer@Sun.COM /* Tx lane specific functions */
905*11878SVenu.Iyer@Sun.COM void * dlstat_tx_lane_stats(dladm_handle_t, datalink_id_t);
906*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_tx_lane_match(void *, void *);
907*11878SVenu.Iyer@Sun.COM static void * i_dlstat_tx_lane_stat_entry_diff(void *, void *);
908*11878SVenu.Iyer@Sun.COM
909*11878SVenu.Iyer@Sun.COM /* Rx lane total specific functions */
910*11878SVenu.Iyer@Sun.COM void * dlstat_rx_lane_total_stats(dladm_handle_t,
911*11878SVenu.Iyer@Sun.COM datalink_id_t);
912*11878SVenu.Iyer@Sun.COM
913*11878SVenu.Iyer@Sun.COM /* Tx lane total specific functions */
914*11878SVenu.Iyer@Sun.COM void * dlstat_tx_lane_total_stats(dladm_handle_t,
915*11878SVenu.Iyer@Sun.COM datalink_id_t);
916*11878SVenu.Iyer@Sun.COM
917*11878SVenu.Iyer@Sun.COM /* Fanout specific functions */
918*11878SVenu.Iyer@Sun.COM void * dlstat_fanout_stats(dladm_handle_t, datalink_id_t);
919*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_fanout_match(void *, void *);
920*11878SVenu.Iyer@Sun.COM static void * i_dlstat_fanout_stat_entry_diff(void *, void *);
921*11878SVenu.Iyer@Sun.COM
922*11878SVenu.Iyer@Sun.COM /* Rx ring specific functions */
923*11878SVenu.Iyer@Sun.COM void * dlstat_rx_ring_stats(dladm_handle_t, datalink_id_t);
924*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_rx_ring_match(void *, void *);
925*11878SVenu.Iyer@Sun.COM static void * i_dlstat_rx_ring_stat_entry_diff(void *, void *);
926*11878SVenu.Iyer@Sun.COM
927*11878SVenu.Iyer@Sun.COM /* Tx ring specific functions */
928*11878SVenu.Iyer@Sun.COM void * dlstat_tx_ring_stats(dladm_handle_t, datalink_id_t);
929*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_tx_ring_match(void *, void *);
930*11878SVenu.Iyer@Sun.COM static void * i_dlstat_tx_ring_stat_entry_diff(void *, void *);
931*11878SVenu.Iyer@Sun.COM
932*11878SVenu.Iyer@Sun.COM /* Rx ring total specific functions */
933*11878SVenu.Iyer@Sun.COM void * dlstat_rx_ring_total_stats(dladm_handle_t,
934*11878SVenu.Iyer@Sun.COM datalink_id_t);
935*11878SVenu.Iyer@Sun.COM
936*11878SVenu.Iyer@Sun.COM /* Tx ring total specific functions */
937*11878SVenu.Iyer@Sun.COM void * dlstat_tx_ring_total_stats(dladm_handle_t,
938*11878SVenu.Iyer@Sun.COM datalink_id_t);
939*11878SVenu.Iyer@Sun.COM
940*11878SVenu.Iyer@Sun.COM /* Summary specific functions */
941*11878SVenu.Iyer@Sun.COM void * dlstat_total_stats(dladm_handle_t, datalink_id_t);
942*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_total_match(void *, void *);
943*11878SVenu.Iyer@Sun.COM static void * i_dlstat_total_stat_entry_diff(void *, void *);
944*11878SVenu.Iyer@Sun.COM
945*11878SVenu.Iyer@Sun.COM /* Aggr port specific functions */
946*11878SVenu.Iyer@Sun.COM void * dlstat_aggr_port_stats(dladm_handle_t, datalink_id_t);
947*11878SVenu.Iyer@Sun.COM static boolean_t i_dlstat_aggr_port_match(void *, void *);
948*11878SVenu.Iyer@Sun.COM static void * i_dlstat_aggr_port_stat_entry_diff(void *, void *);
949*11878SVenu.Iyer@Sun.COM
950*11878SVenu.Iyer@Sun.COM /* Misc stat specific functions */
951*11878SVenu.Iyer@Sun.COM void * dlstat_misc_stats(dladm_handle_t, datalink_id_t);
952*11878SVenu.Iyer@Sun.COM
953*11878SVenu.Iyer@Sun.COM typedef void * dladm_stat_query_t(dladm_handle_t, datalink_id_t);
954*11878SVenu.Iyer@Sun.COM typedef boolean_t dladm_stat_match_t(void *, void *);
955*11878SVenu.Iyer@Sun.COM typedef void * dladm_stat_diff_t(void *, void *);
956*11878SVenu.Iyer@Sun.COM
957*11878SVenu.Iyer@Sun.COM typedef struct dladm_stat_desc_s {
958*11878SVenu.Iyer@Sun.COM dladm_stat_type_t ds_stattype;
959*11878SVenu.Iyer@Sun.COM dladm_stat_query_t *ds_querystat;
960*11878SVenu.Iyer@Sun.COM dladm_stat_match_t *ds_matchstat;
961*11878SVenu.Iyer@Sun.COM dladm_stat_diff_t *ds_diffstat;
962*11878SVenu.Iyer@Sun.COM uint_t ds_offset;
963*11878SVenu.Iyer@Sun.COM stat_info_t *ds_statlist;
964*11878SVenu.Iyer@Sun.COM uint_t ds_statsize;
965*11878SVenu.Iyer@Sun.COM } dladm_stat_desc_t;
966*11878SVenu.Iyer@Sun.COM
967*11878SVenu.Iyer@Sun.COM /*
968*11878SVenu.Iyer@Sun.COM * dladm_stat_table has one entry for each supported stat. ds_querystat returns
969*11878SVenu.Iyer@Sun.COM * a chain of 'stat entries' for the queried stat.
970*11878SVenu.Iyer@Sun.COM * Each stat entry has set of identifiers (ids) and an object containing actual
971*11878SVenu.Iyer@Sun.COM * stat values. These stat entry objects are chained together in a linked list
972*11878SVenu.Iyer@Sun.COM * of datatype dladm_stat_chain_t. Head of this list is returned to the caller
973*11878SVenu.Iyer@Sun.COM * of dladm_link_stat_query.
974*11878SVenu.Iyer@Sun.COM *
975*11878SVenu.Iyer@Sun.COM * One node in the chain is shown below:
976*11878SVenu.Iyer@Sun.COM *
977*11878SVenu.Iyer@Sun.COM * -------------------------
978*11878SVenu.Iyer@Sun.COM * | dc_statentry |
979*11878SVenu.Iyer@Sun.COM * | -------------- |
980*11878SVenu.Iyer@Sun.COM * | | ids | |
981*11878SVenu.Iyer@Sun.COM * | -------------- |
982*11878SVenu.Iyer@Sun.COM * | | stat fields | |
983*11878SVenu.Iyer@Sun.COM * | -------------- |
984*11878SVenu.Iyer@Sun.COM * -------------------------
985*11878SVenu.Iyer@Sun.COM * | dc_next ---------|------> to next stat entry
986*11878SVenu.Iyer@Sun.COM * -------------------------
987*11878SVenu.Iyer@Sun.COM *
988*11878SVenu.Iyer@Sun.COM * In particular, for query DLADM_STAT_RX_LANE, dc_statentry carries pointer to
989*11878SVenu.Iyer@Sun.COM * object of type rx_lane_stat_entry_t.
990*11878SVenu.Iyer@Sun.COM *
991*11878SVenu.Iyer@Sun.COM * dladm_link_stat_query_all returns similar chain. However, instead of storing
992*11878SVenu.Iyer@Sun.COM * stat fields as raw numbers, it stores those as chain of <name, value> pairs.
993*11878SVenu.Iyer@Sun.COM * The resulting structure is depicted below:
994*11878SVenu.Iyer@Sun.COM *
995*11878SVenu.Iyer@Sun.COM * -------------------------
996*11878SVenu.Iyer@Sun.COM * | dc_statentry |
997*11878SVenu.Iyer@Sun.COM * | -------------- | ---------------
998*11878SVenu.Iyer@Sun.COM * | | nv_header | | | name, val |
999*11878SVenu.Iyer@Sun.COM * | -------------- | ---------------
1000*11878SVenu.Iyer@Sun.COM * | | nve_stats---|----|-->| nv_nextstat--|---> to next name, val pair
1001*11878SVenu.Iyer@Sun.COM * | -------------- | ---------------
1002*11878SVenu.Iyer@Sun.COM * -------------------------
1003*11878SVenu.Iyer@Sun.COM * | dc_next ---------|------> to next stat entry
1004*11878SVenu.Iyer@Sun.COM * -------------------------
1005*11878SVenu.Iyer@Sun.COM */
1006*11878SVenu.Iyer@Sun.COM static dladm_stat_desc_t dladm_stat_table[] = {
1007*11878SVenu.Iyer@Sun.COM { DLADM_STAT_RX_LANE, dlstat_rx_lane_stats,
1008*11878SVenu.Iyer@Sun.COM i_dlstat_rx_lane_match, i_dlstat_rx_lane_stat_entry_diff,
1009*11878SVenu.Iyer@Sun.COM offsetof(rx_lane_stat_entry_t, rle_stats),
1010*11878SVenu.Iyer@Sun.COM rx_lane_stats_list, RX_LANE_STAT_SIZE},
1011*11878SVenu.Iyer@Sun.COM
1012*11878SVenu.Iyer@Sun.COM { DLADM_STAT_TX_LANE, dlstat_tx_lane_stats,
1013*11878SVenu.Iyer@Sun.COM i_dlstat_tx_lane_match, i_dlstat_tx_lane_stat_entry_diff,
1014*11878SVenu.Iyer@Sun.COM offsetof(tx_lane_stat_entry_t, tle_stats),
1015*11878SVenu.Iyer@Sun.COM tx_lane_stats_list, TX_LANE_STAT_SIZE},
1016*11878SVenu.Iyer@Sun.COM
1017*11878SVenu.Iyer@Sun.COM { DLADM_STAT_RX_LANE_TOTAL, dlstat_rx_lane_total_stats,
1018*11878SVenu.Iyer@Sun.COM i_dlstat_rx_lane_match, i_dlstat_rx_lane_stat_entry_diff,
1019*11878SVenu.Iyer@Sun.COM offsetof(rx_lane_stat_entry_t, rle_stats),
1020*11878SVenu.Iyer@Sun.COM rx_lane_stats_list, RX_LANE_STAT_SIZE},
1021*11878SVenu.Iyer@Sun.COM
1022*11878SVenu.Iyer@Sun.COM { DLADM_STAT_TX_LANE_TOTAL, dlstat_tx_lane_total_stats,
1023*11878SVenu.Iyer@Sun.COM i_dlstat_tx_lane_match, i_dlstat_tx_lane_stat_entry_diff,
1024*11878SVenu.Iyer@Sun.COM offsetof(tx_lane_stat_entry_t, tle_stats),
1025*11878SVenu.Iyer@Sun.COM tx_lane_stats_list, TX_LANE_STAT_SIZE},
1026*11878SVenu.Iyer@Sun.COM
1027*11878SVenu.Iyer@Sun.COM { DLADM_STAT_RX_LANE_FOUT, dlstat_fanout_stats,
1028*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_match, i_dlstat_fanout_stat_entry_diff,
1029*11878SVenu.Iyer@Sun.COM offsetof(fanout_stat_entry_t, fe_stats),
1030*11878SVenu.Iyer@Sun.COM fanout_stats_list, FANOUT_STAT_SIZE},
1031*11878SVenu.Iyer@Sun.COM
1032*11878SVenu.Iyer@Sun.COM { DLADM_STAT_RX_RING, dlstat_rx_ring_stats,
1033*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_match, i_dlstat_rx_ring_stat_entry_diff,
1034*11878SVenu.Iyer@Sun.COM offsetof(ring_stat_entry_t, re_stats),
1035*11878SVenu.Iyer@Sun.COM rx_ring_stats_list, RX_RING_STAT_SIZE},
1036*11878SVenu.Iyer@Sun.COM
1037*11878SVenu.Iyer@Sun.COM { DLADM_STAT_TX_RING, dlstat_tx_ring_stats,
1038*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_match, i_dlstat_tx_ring_stat_entry_diff,
1039*11878SVenu.Iyer@Sun.COM offsetof(ring_stat_entry_t, re_stats),
1040*11878SVenu.Iyer@Sun.COM tx_ring_stats_list, TX_RING_STAT_SIZE},
1041*11878SVenu.Iyer@Sun.COM
1042*11878SVenu.Iyer@Sun.COM { DLADM_STAT_RX_RING_TOTAL, dlstat_rx_ring_total_stats,
1043*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_match, i_dlstat_rx_ring_stat_entry_diff,
1044*11878SVenu.Iyer@Sun.COM offsetof(ring_stat_entry_t, re_stats),
1045*11878SVenu.Iyer@Sun.COM rx_ring_stats_list, RX_RING_STAT_SIZE},
1046*11878SVenu.Iyer@Sun.COM
1047*11878SVenu.Iyer@Sun.COM { DLADM_STAT_TX_RING_TOTAL, dlstat_tx_ring_total_stats,
1048*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_match, i_dlstat_tx_ring_stat_entry_diff,
1049*11878SVenu.Iyer@Sun.COM offsetof(ring_stat_entry_t, re_stats),
1050*11878SVenu.Iyer@Sun.COM tx_ring_stats_list, TX_RING_STAT_SIZE},
1051*11878SVenu.Iyer@Sun.COM
1052*11878SVenu.Iyer@Sun.COM { DLADM_STAT_TOTAL, dlstat_total_stats,
1053*11878SVenu.Iyer@Sun.COM i_dlstat_total_match, i_dlstat_total_stat_entry_diff,
1054*11878SVenu.Iyer@Sun.COM offsetof(total_stat_entry_t, tse_stats),
1055*11878SVenu.Iyer@Sun.COM total_stats_list, TOTAL_STAT_SIZE},
1056*11878SVenu.Iyer@Sun.COM
1057*11878SVenu.Iyer@Sun.COM { DLADM_STAT_AGGR_PORT, dlstat_aggr_port_stats,
1058*11878SVenu.Iyer@Sun.COM i_dlstat_aggr_port_match, i_dlstat_aggr_port_stat_entry_diff,
1059*11878SVenu.Iyer@Sun.COM offsetof(aggr_port_stat_entry_t, ape_stats),
1060*11878SVenu.Iyer@Sun.COM aggr_port_stats_list, AGGR_PORT_STAT_SIZE},
1061*11878SVenu.Iyer@Sun.COM /*
1062*11878SVenu.Iyer@Sun.COM * We don't support -i <interval> query with misc stats. Several table fields
1063*11878SVenu.Iyer@Sun.COM * are left uninitialized thus.
1064*11878SVenu.Iyer@Sun.COM */
1065*11878SVenu.Iyer@Sun.COM { DLADM_STAT_MISC, dlstat_misc_stats,
1066*11878SVenu.Iyer@Sun.COM NULL, NULL,
1067*11878SVenu.Iyer@Sun.COM 0,
1068*11878SVenu.Iyer@Sun.COM misc_stats_list, MISC_STAT_SIZE}
1069*11878SVenu.Iyer@Sun.COM };
1070*11878SVenu.Iyer@Sun.COM
1071*11878SVenu.Iyer@Sun.COM /* Internal functions */
1072*11878SVenu.Iyer@Sun.COM static void *
dlstat_diff_stats(void * arg1,void * arg2,dladm_stat_type_t stattype)1073*11878SVenu.Iyer@Sun.COM dlstat_diff_stats(void *arg1, void *arg2, dladm_stat_type_t stattype)
1074*11878SVenu.Iyer@Sun.COM {
1075*11878SVenu.Iyer@Sun.COM return (dladm_stat_table[stattype].ds_diffstat(arg1, arg2));
1076*11878SVenu.Iyer@Sun.COM }
1077*11878SVenu.Iyer@Sun.COM
1078*11878SVenu.Iyer@Sun.COM static boolean_t
dlstat_match_stats(void * arg1,void * arg2,dladm_stat_type_t stattype)1079*11878SVenu.Iyer@Sun.COM dlstat_match_stats(void *arg1, void *arg2, dladm_stat_type_t stattype)
1080*11878SVenu.Iyer@Sun.COM {
1081*11878SVenu.Iyer@Sun.COM return (dladm_stat_table[stattype].ds_matchstat(arg1, arg2));
1082*11878SVenu.Iyer@Sun.COM }
1083*11878SVenu.Iyer@Sun.COM
1084*11878SVenu.Iyer@Sun.COM /* Diff between two stats */
1085*11878SVenu.Iyer@Sun.COM static void
i_dlstat_diff_stats(void * diff,void * op1,void * op2,stat_info_t stats_list[],uint_t size)1086*11878SVenu.Iyer@Sun.COM i_dlstat_diff_stats(void *diff, void *op1, void *op2,
1087*11878SVenu.Iyer@Sun.COM stat_info_t stats_list[], uint_t size)
1088*11878SVenu.Iyer@Sun.COM {
1089*11878SVenu.Iyer@Sun.COM int i;
1090*11878SVenu.Iyer@Sun.COM
1091*11878SVenu.Iyer@Sun.COM for (i = 0; i < size; i++) {
1092*11878SVenu.Iyer@Sun.COM uint64_t *op1_val = (void *)
1093*11878SVenu.Iyer@Sun.COM ((uchar_t *)op1 + stats_list[i].si_offset);
1094*11878SVenu.Iyer@Sun.COM uint64_t *op2_val = (void *)
1095*11878SVenu.Iyer@Sun.COM ((uchar_t *)op2 + stats_list[i].si_offset);
1096*11878SVenu.Iyer@Sun.COM uint64_t *diff_val = (void *)
1097*11878SVenu.Iyer@Sun.COM ((uchar_t *)diff + stats_list[i].si_offset);
1098*11878SVenu.Iyer@Sun.COM
1099*11878SVenu.Iyer@Sun.COM *diff_val = DIFF_STAT(*op1_val, *op2_val);
1100*11878SVenu.Iyer@Sun.COM }
1101*11878SVenu.Iyer@Sun.COM }
1102*11878SVenu.Iyer@Sun.COM
1103*11878SVenu.Iyer@Sun.COM /*
1104*11878SVenu.Iyer@Sun.COM * Perform diff = s1 - s2, where diff, s1, s2 are structure objects of same
1105*11878SVenu.Iyer@Sun.COM * datatype. slist is list of offsets of the fields within the structure.
1106*11878SVenu.Iyer@Sun.COM */
1107*11878SVenu.Iyer@Sun.COM #define DLSTAT_DIFF_STAT(s1, s2, diff, f, slist, sz) { \
1108*11878SVenu.Iyer@Sun.COM if (s2 == NULL) { \
1109*11878SVenu.Iyer@Sun.COM bcopy(&s1->f, &diff->f, sizeof (s1->f)); \
1110*11878SVenu.Iyer@Sun.COM } else { \
1111*11878SVenu.Iyer@Sun.COM i_dlstat_diff_stats(&diff->f, &s1->f, \
1112*11878SVenu.Iyer@Sun.COM &s2->f, slist, sz); \
1113*11878SVenu.Iyer@Sun.COM } \
1114*11878SVenu.Iyer@Sun.COM }
1115*11878SVenu.Iyer@Sun.COM
1116*11878SVenu.Iyer@Sun.COM /* Sum two stats */
1117*11878SVenu.Iyer@Sun.COM static void
i_dlstat_sum_stats(void * sum,void * op1,void * op2,stat_info_t stats_list[],uint_t size)1118*11878SVenu.Iyer@Sun.COM i_dlstat_sum_stats(void *sum, void *op1, void *op2,
1119*11878SVenu.Iyer@Sun.COM stat_info_t stats_list[], uint_t size)
1120*11878SVenu.Iyer@Sun.COM {
1121*11878SVenu.Iyer@Sun.COM int i;
1122*11878SVenu.Iyer@Sun.COM
1123*11878SVenu.Iyer@Sun.COM for (i = 0; i < size; i++) {
1124*11878SVenu.Iyer@Sun.COM uint64_t *op1_val = (void *)
1125*11878SVenu.Iyer@Sun.COM ((uchar_t *)op1 + stats_list[i].si_offset);
1126*11878SVenu.Iyer@Sun.COM uint64_t *op2_val = (void *)
1127*11878SVenu.Iyer@Sun.COM ((uchar_t *)op2 + stats_list[i].si_offset);
1128*11878SVenu.Iyer@Sun.COM uint64_t *sum_val = (void *)
1129*11878SVenu.Iyer@Sun.COM ((uchar_t *)sum + stats_list[i].si_offset);
1130*11878SVenu.Iyer@Sun.COM
1131*11878SVenu.Iyer@Sun.COM *sum_val = *op1_val + *op2_val;
1132*11878SVenu.Iyer@Sun.COM }
1133*11878SVenu.Iyer@Sun.COM }
1134*11878SVenu.Iyer@Sun.COM
1135*11878SVenu.Iyer@Sun.COM /* Look up kstat value */
1136*11878SVenu.Iyer@Sun.COM static void
i_dlstat_get_stats(kstat_ctl_t * kcp,kstat_t * ksp,void * stats,stat_info_t stats_list[],uint_t size)1137*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kstat_ctl_t *kcp, kstat_t *ksp, void *stats,
1138*11878SVenu.Iyer@Sun.COM stat_info_t stats_list[], uint_t size)
1139*11878SVenu.Iyer@Sun.COM {
1140*11878SVenu.Iyer@Sun.COM int i;
1141*11878SVenu.Iyer@Sun.COM
1142*11878SVenu.Iyer@Sun.COM if (kstat_read(kcp, ksp, NULL) == -1)
1143*11878SVenu.Iyer@Sun.COM return;
1144*11878SVenu.Iyer@Sun.COM
1145*11878SVenu.Iyer@Sun.COM for (i = 0; i < size; i++) {
1146*11878SVenu.Iyer@Sun.COM uint64_t *val = (void *)
1147*11878SVenu.Iyer@Sun.COM ((uchar_t *)stats + stats_list[i].si_offset);
1148*11878SVenu.Iyer@Sun.COM
1149*11878SVenu.Iyer@Sun.COM if (dladm_kstat_value(ksp, stats_list[i].si_name,
1150*11878SVenu.Iyer@Sun.COM KSTAT_DATA_UINT64, val) < 0)
1151*11878SVenu.Iyer@Sun.COM return;
1152*11878SVenu.Iyer@Sun.COM }
1153*11878SVenu.Iyer@Sun.COM }
1154*11878SVenu.Iyer@Sun.COM
1155*11878SVenu.Iyer@Sun.COM /* Append linked list list1 to linked list list2 and return resulting list */
1156*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_join_lists(dladm_stat_chain_t * list1,dladm_stat_chain_t * list2)1157*11878SVenu.Iyer@Sun.COM i_dlstat_join_lists(dladm_stat_chain_t *list1, dladm_stat_chain_t *list2)
1158*11878SVenu.Iyer@Sun.COM {
1159*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *curr;
1160*11878SVenu.Iyer@Sun.COM
1161*11878SVenu.Iyer@Sun.COM if (list1 == NULL)
1162*11878SVenu.Iyer@Sun.COM return (list2);
1163*11878SVenu.Iyer@Sun.COM
1164*11878SVenu.Iyer@Sun.COM /* list1 has at least one element, find last element in list1 */
1165*11878SVenu.Iyer@Sun.COM curr = list1;
1166*11878SVenu.Iyer@Sun.COM while (curr->dc_next != NULL)
1167*11878SVenu.Iyer@Sun.COM curr = curr->dc_next;
1168*11878SVenu.Iyer@Sun.COM
1169*11878SVenu.Iyer@Sun.COM curr->dc_next = list2;
1170*11878SVenu.Iyer@Sun.COM return (list1);
1171*11878SVenu.Iyer@Sun.COM }
1172*11878SVenu.Iyer@Sun.COM
1173*11878SVenu.Iyer@Sun.COM uint_t default_idlist[] = {0};
1174*11878SVenu.Iyer@Sun.COM uint_t default_idlist_size = 1;
1175*11878SVenu.Iyer@Sun.COM
1176*11878SVenu.Iyer@Sun.COM typedef enum {
1177*11878SVenu.Iyer@Sun.COM DLSTAT_RX_RING_IDLIST,
1178*11878SVenu.Iyer@Sun.COM DLSTAT_TX_RING_IDLIST,
1179*11878SVenu.Iyer@Sun.COM DLSTAT_RX_HWLANE_IDLIST,
1180*11878SVenu.Iyer@Sun.COM DLSTAT_TX_HWLANE_IDLIST,
1181*11878SVenu.Iyer@Sun.COM DLSTAT_FANOUT_IDLIST
1182*11878SVenu.Iyer@Sun.COM } dlstat_idlist_type_t;
1183*11878SVenu.Iyer@Sun.COM
1184*11878SVenu.Iyer@Sun.COM void
dladm_sort_index_list(uint_t idlist[],uint_t size)1185*11878SVenu.Iyer@Sun.COM dladm_sort_index_list(uint_t idlist[], uint_t size)
1186*11878SVenu.Iyer@Sun.COM {
1187*11878SVenu.Iyer@Sun.COM int i, j;
1188*11878SVenu.Iyer@Sun.COM
1189*11878SVenu.Iyer@Sun.COM for (j = 1; j < size; j++) {
1190*11878SVenu.Iyer@Sun.COM int key = idlist[j];
1191*11878SVenu.Iyer@Sun.COM for (i = j - 1; (i >= 0) && (idlist[i] > key); i--)
1192*11878SVenu.Iyer@Sun.COM idlist[i + 1] = idlist[i];
1193*11878SVenu.Iyer@Sun.COM idlist[i + 1] = key;
1194*11878SVenu.Iyer@Sun.COM }
1195*11878SVenu.Iyer@Sun.COM }
1196*11878SVenu.Iyer@Sun.COM
1197*11878SVenu.Iyer@Sun.COM /* Support for legacy drivers */
1198*11878SVenu.Iyer@Sun.COM void
i_query_legacy_stats(const char * linkname,pktsum_t * stats)1199*11878SVenu.Iyer@Sun.COM i_query_legacy_stats(const char *linkname, pktsum_t *stats)
1200*11878SVenu.Iyer@Sun.COM {
1201*11878SVenu.Iyer@Sun.COM kstat_ctl_t *kcp;
1202*11878SVenu.Iyer@Sun.COM kstat_t *ksp;
1203*11878SVenu.Iyer@Sun.COM
1204*11878SVenu.Iyer@Sun.COM bzero(stats, sizeof (*stats));
1205*11878SVenu.Iyer@Sun.COM
1206*11878SVenu.Iyer@Sun.COM if ((kcp = kstat_open()) == NULL)
1207*11878SVenu.Iyer@Sun.COM return;
1208*11878SVenu.Iyer@Sun.COM
1209*11878SVenu.Iyer@Sun.COM ksp = dladm_kstat_lookup(kcp, "link", 0, linkname, NULL);
1210*11878SVenu.Iyer@Sun.COM
1211*11878SVenu.Iyer@Sun.COM if (ksp != NULL)
1212*11878SVenu.Iyer@Sun.COM dladm_get_stats(kcp, ksp, stats);
1213*11878SVenu.Iyer@Sun.COM
1214*11878SVenu.Iyer@Sun.COM (void) kstat_close(kcp);
1215*11878SVenu.Iyer@Sun.COM }
1216*11878SVenu.Iyer@Sun.COM
1217*11878SVenu.Iyer@Sun.COM void *
i_dlstat_legacy_rx_lane_stats(const char * linkname)1218*11878SVenu.Iyer@Sun.COM i_dlstat_legacy_rx_lane_stats(const char *linkname)
1219*11878SVenu.Iyer@Sun.COM {
1220*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1221*11878SVenu.Iyer@Sun.COM pktsum_t stats;
1222*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
1223*11878SVenu.Iyer@Sun.COM
1224*11878SVenu.Iyer@Sun.COM bzero(&stats, sizeof (pktsum_t));
1225*11878SVenu.Iyer@Sun.COM
1226*11878SVenu.Iyer@Sun.COM /* Query for dls stats */
1227*11878SVenu.Iyer@Sun.COM i_query_legacy_stats(linkname, &stats);
1228*11878SVenu.Iyer@Sun.COM
1229*11878SVenu.Iyer@Sun.COM /* Convert to desired data type */
1230*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1231*11878SVenu.Iyer@Sun.COM if (rx_lane_stat_entry == NULL)
1232*11878SVenu.Iyer@Sun.COM goto done;
1233*11878SVenu.Iyer@Sun.COM
1234*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
1235*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_id = L_SWLANE;
1236*11878SVenu.Iyer@Sun.COM
1237*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_ipackets = stats.ipackets;
1238*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_intrs = stats.ipackets;
1239*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_rbytes = stats.rbytes;
1240*11878SVenu.Iyer@Sun.COM
1241*11878SVenu.Iyer@Sun.COM /* Allocate memory for wrapper */
1242*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
1243*11878SVenu.Iyer@Sun.COM if (head == NULL) {
1244*11878SVenu.Iyer@Sun.COM free(rx_lane_stat_entry);
1245*11878SVenu.Iyer@Sun.COM goto done;
1246*11878SVenu.Iyer@Sun.COM }
1247*11878SVenu.Iyer@Sun.COM
1248*11878SVenu.Iyer@Sun.COM head->dc_statentry = rx_lane_stat_entry;
1249*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
1250*11878SVenu.Iyer@Sun.COM done:
1251*11878SVenu.Iyer@Sun.COM return (head);
1252*11878SVenu.Iyer@Sun.COM }
1253*11878SVenu.Iyer@Sun.COM
1254*11878SVenu.Iyer@Sun.COM void *
i_dlstat_legacy_tx_lane_stats(const char * linkname)1255*11878SVenu.Iyer@Sun.COM i_dlstat_legacy_tx_lane_stats(const char *linkname)
1256*11878SVenu.Iyer@Sun.COM {
1257*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1258*11878SVenu.Iyer@Sun.COM pktsum_t stats;
1259*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *tx_lane_stat_entry;
1260*11878SVenu.Iyer@Sun.COM
1261*11878SVenu.Iyer@Sun.COM bzero(&stats, sizeof (pktsum_t));
1262*11878SVenu.Iyer@Sun.COM
1263*11878SVenu.Iyer@Sun.COM /* Query for dls stats */
1264*11878SVenu.Iyer@Sun.COM i_query_legacy_stats(linkname, &stats);
1265*11878SVenu.Iyer@Sun.COM
1266*11878SVenu.Iyer@Sun.COM /* Convert to desired data type */
1267*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
1268*11878SVenu.Iyer@Sun.COM if (tx_lane_stat_entry == NULL)
1269*11878SVenu.Iyer@Sun.COM goto done;
1270*11878SVenu.Iyer@Sun.COM
1271*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
1272*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_id = L_SWLANE;
1273*11878SVenu.Iyer@Sun.COM
1274*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_opackets = stats.opackets;
1275*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_obytes = stats.obytes;
1276*11878SVenu.Iyer@Sun.COM
1277*11878SVenu.Iyer@Sun.COM /* Allocate memory for wrapper */
1278*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
1279*11878SVenu.Iyer@Sun.COM if (head == NULL) {
1280*11878SVenu.Iyer@Sun.COM free(tx_lane_stat_entry);
1281*11878SVenu.Iyer@Sun.COM goto done;
1282*11878SVenu.Iyer@Sun.COM }
1283*11878SVenu.Iyer@Sun.COM
1284*11878SVenu.Iyer@Sun.COM head->dc_statentry = tx_lane_stat_entry;
1285*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
1286*11878SVenu.Iyer@Sun.COM done:
1287*11878SVenu.Iyer@Sun.COM return (head);
1288*11878SVenu.Iyer@Sun.COM }
1289*11878SVenu.Iyer@Sun.COM
1290*11878SVenu.Iyer@Sun.COM /*
1291*11878SVenu.Iyer@Sun.COM * Ideally, we would want an ioctl to return list of ring-ids (or lane-ids)
1292*11878SVenu.Iyer@Sun.COM * for a given data-link (or mac client). We could then query for specific
1293*11878SVenu.Iyer@Sun.COM * kstats based on these ring-ids (lane-ids).
1294*11878SVenu.Iyer@Sun.COM * Ring-ids (or lane-ids) could be returned like any other link properties
1295*11878SVenu.Iyer@Sun.COM * queried by dladm show-linkprop. However, non-global zones do not have
1296*11878SVenu.Iyer@Sun.COM * access to this information today.
1297*11878SVenu.Iyer@Sun.COM * We thus opt for an implementation that relies heavily on kstat internals:
1298*11878SVenu.Iyer@Sun.COM * i_dlstat_*search routines and i_dlstat_get_idlist.
1299*11878SVenu.Iyer@Sun.COM */
1300*11878SVenu.Iyer@Sun.COM /* rx hwlane specific */
1301*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_rx_hwlane_search(kstat_t * ksp)1302*11878SVenu.Iyer@Sun.COM i_dlstat_rx_hwlane_search(kstat_t *ksp)
1303*11878SVenu.Iyer@Sun.COM {
1304*11878SVenu.Iyer@Sun.COM return (ksp->ks_instance == 0 &&
1305*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "mac_rx") != 0 &&
1306*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "hwlane") != 0 &&
1307*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "fanout") == 0 &&
1308*11878SVenu.Iyer@Sun.COM strcmp(ksp->ks_class, "net") == 0);
1309*11878SVenu.Iyer@Sun.COM }
1310*11878SVenu.Iyer@Sun.COM
1311*11878SVenu.Iyer@Sun.COM /* tx hwlane specific */
1312*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_tx_hwlane_search(kstat_t * ksp)1313*11878SVenu.Iyer@Sun.COM i_dlstat_tx_hwlane_search(kstat_t *ksp)
1314*11878SVenu.Iyer@Sun.COM {
1315*11878SVenu.Iyer@Sun.COM return (ksp->ks_instance == 0 &&
1316*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "mac_tx") != 0 &&
1317*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "hwlane") != 0 &&
1318*11878SVenu.Iyer@Sun.COM strcmp(ksp->ks_class, "net") == 0);
1319*11878SVenu.Iyer@Sun.COM }
1320*11878SVenu.Iyer@Sun.COM
1321*11878SVenu.Iyer@Sun.COM /* rx fanout specific */
1322*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_fanout_search(kstat_t * ksp)1323*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_search(kstat_t *ksp)
1324*11878SVenu.Iyer@Sun.COM {
1325*11878SVenu.Iyer@Sun.COM return (ksp->ks_instance == 0 &&
1326*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "mac_rx") != 0 &&
1327*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "swlane") != 0 &&
1328*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "fanout") != 0 &&
1329*11878SVenu.Iyer@Sun.COM strcmp(ksp->ks_class, "net") == 0);
1330*11878SVenu.Iyer@Sun.COM }
1331*11878SVenu.Iyer@Sun.COM
1332*11878SVenu.Iyer@Sun.COM /* rx ring specific */
1333*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_rx_ring_search(kstat_t * ksp)1334*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_search(kstat_t *ksp)
1335*11878SVenu.Iyer@Sun.COM {
1336*11878SVenu.Iyer@Sun.COM return (ksp->ks_instance == 0 &&
1337*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "mac_rx") != 0 &&
1338*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "ring") != 0 &&
1339*11878SVenu.Iyer@Sun.COM strcmp(ksp->ks_class, "net") == 0);
1340*11878SVenu.Iyer@Sun.COM }
1341*11878SVenu.Iyer@Sun.COM
1342*11878SVenu.Iyer@Sun.COM /* tx ring specific */
1343*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_tx_ring_search(kstat_t * ksp)1344*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_search(kstat_t *ksp)
1345*11878SVenu.Iyer@Sun.COM {
1346*11878SVenu.Iyer@Sun.COM return (ksp->ks_instance == 0) &&
1347*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "mac_tx") != 0 &&
1348*11878SVenu.Iyer@Sun.COM strstr(ksp->ks_name, "ring") != 0 &&
1349*11878SVenu.Iyer@Sun.COM strcmp(ksp->ks_class, "net") == 0;
1350*11878SVenu.Iyer@Sun.COM }
1351*11878SVenu.Iyer@Sun.COM
1352*11878SVenu.Iyer@Sun.COM typedef boolean_t dladm_search_kstat_t(kstat_t *);
1353*11878SVenu.Iyer@Sun.COM typedef struct dladm_extract_idlist_s {
1354*11878SVenu.Iyer@Sun.COM dlstat_idlist_type_t di_type;
1355*11878SVenu.Iyer@Sun.COM char *di_prefix;
1356*11878SVenu.Iyer@Sun.COM dladm_search_kstat_t *di_searchkstat;
1357*11878SVenu.Iyer@Sun.COM } dladm_extract_idlist_t;
1358*11878SVenu.Iyer@Sun.COM
1359*11878SVenu.Iyer@Sun.COM static dladm_extract_idlist_t dladm_extract_idlist[] = {
1360*11878SVenu.Iyer@Sun.COM { DLSTAT_RX_RING_IDLIST, DLSTAT_MAC_RX_RING,
1361*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_search},
1362*11878SVenu.Iyer@Sun.COM { DLSTAT_TX_RING_IDLIST, DLSTAT_MAC_TX_RING,
1363*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_search},
1364*11878SVenu.Iyer@Sun.COM { DLSTAT_RX_HWLANE_IDLIST, DLSTAT_MAC_RX_HWLANE,
1365*11878SVenu.Iyer@Sun.COM i_dlstat_rx_hwlane_search},
1366*11878SVenu.Iyer@Sun.COM { DLSTAT_TX_HWLANE_IDLIST, DLSTAT_MAC_TX_HWLANE,
1367*11878SVenu.Iyer@Sun.COM i_dlstat_tx_hwlane_search},
1368*11878SVenu.Iyer@Sun.COM { DLSTAT_FANOUT_IDLIST, DLSTAT_MAC_FANOUT,
1369*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_search}
1370*11878SVenu.Iyer@Sun.COM };
1371*11878SVenu.Iyer@Sun.COM
1372*11878SVenu.Iyer@Sun.COM static void
i_dlstat_get_idlist(const char * modname,dlstat_idlist_type_t idlist_type,uint_t idlist[],uint_t * size)1373*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(const char *modname, dlstat_idlist_type_t idlist_type,
1374*11878SVenu.Iyer@Sun.COM uint_t idlist[], uint_t *size)
1375*11878SVenu.Iyer@Sun.COM {
1376*11878SVenu.Iyer@Sun.COM kstat_ctl_t *kcp;
1377*11878SVenu.Iyer@Sun.COM kstat_t *ksp;
1378*11878SVenu.Iyer@Sun.COM char *prefix;
1379*11878SVenu.Iyer@Sun.COM int prefixlen;
1380*11878SVenu.Iyer@Sun.COM boolean_t (*fptr_searchkstat)(kstat_t *);
1381*11878SVenu.Iyer@Sun.COM
1382*11878SVenu.Iyer@Sun.COM *size = 0;
1383*11878SVenu.Iyer@Sun.COM
1384*11878SVenu.Iyer@Sun.COM if ((kcp = kstat_open()) == NULL) {
1385*11878SVenu.Iyer@Sun.COM warn("kstat_open operation failed");
1386*11878SVenu.Iyer@Sun.COM goto done;
1387*11878SVenu.Iyer@Sun.COM }
1388*11878SVenu.Iyer@Sun.COM
1389*11878SVenu.Iyer@Sun.COM prefix = dladm_extract_idlist[idlist_type].di_prefix;
1390*11878SVenu.Iyer@Sun.COM fptr_searchkstat = dladm_extract_idlist[idlist_type].di_searchkstat;
1391*11878SVenu.Iyer@Sun.COM prefixlen = strlen(prefix);
1392*11878SVenu.Iyer@Sun.COM for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
1393*11878SVenu.Iyer@Sun.COM if ((strcmp(ksp->ks_module, modname) == 0) &&
1394*11878SVenu.Iyer@Sun.COM fptr_searchkstat(ksp)) {
1395*11878SVenu.Iyer@Sun.COM idlist[(*size)++] = atoi(&ksp->ks_name[prefixlen]);
1396*11878SVenu.Iyer@Sun.COM }
1397*11878SVenu.Iyer@Sun.COM }
1398*11878SVenu.Iyer@Sun.COM dladm_sort_index_list(idlist, *size);
1399*11878SVenu.Iyer@Sun.COM
1400*11878SVenu.Iyer@Sun.COM done:
1401*11878SVenu.Iyer@Sun.COM (void) kstat_close(kcp);
1402*11878SVenu.Iyer@Sun.COM }
1403*11878SVenu.Iyer@Sun.COM
1404*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_query_stats(const char * modname,const char * prefix,uint_t idlist[],uint_t idlist_size,void * (* fn)(kstat_ctl_t *,kstat_t *,int))1405*11878SVenu.Iyer@Sun.COM i_dlstat_query_stats(const char *modname, const char *prefix,
1406*11878SVenu.Iyer@Sun.COM uint_t idlist[], uint_t idlist_size,
1407*11878SVenu.Iyer@Sun.COM void * (*fn)(kstat_ctl_t *, kstat_t *, int))
1408*11878SVenu.Iyer@Sun.COM {
1409*11878SVenu.Iyer@Sun.COM kstat_ctl_t *kcp;
1410*11878SVenu.Iyer@Sun.COM kstat_t *ksp;
1411*11878SVenu.Iyer@Sun.COM char statname[MAXLINKNAMELEN];
1412*11878SVenu.Iyer@Sun.COM int i = 0;
1413*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL, *prev = NULL;
1414*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *curr;
1415*11878SVenu.Iyer@Sun.COM
1416*11878SVenu.Iyer@Sun.COM if ((kcp = kstat_open()) == NULL) {
1417*11878SVenu.Iyer@Sun.COM warn("kstat_open operation failed");
1418*11878SVenu.Iyer@Sun.COM return (NULL);
1419*11878SVenu.Iyer@Sun.COM }
1420*11878SVenu.Iyer@Sun.COM
1421*11878SVenu.Iyer@Sun.COM for (i = 0; i < idlist_size; i++) {
1422*11878SVenu.Iyer@Sun.COM uint_t index = idlist[i];
1423*11878SVenu.Iyer@Sun.COM
1424*11878SVenu.Iyer@Sun.COM (void) snprintf(statname, sizeof (statname), "%s%d", prefix,
1425*11878SVenu.Iyer@Sun.COM index);
1426*11878SVenu.Iyer@Sun.COM
1427*11878SVenu.Iyer@Sun.COM ksp = dladm_kstat_lookup(kcp, modname, 0, statname, NULL);
1428*11878SVenu.Iyer@Sun.COM if (ksp == NULL)
1429*11878SVenu.Iyer@Sun.COM continue;
1430*11878SVenu.Iyer@Sun.COM
1431*11878SVenu.Iyer@Sun.COM curr = malloc(sizeof (dladm_stat_chain_t));
1432*11878SVenu.Iyer@Sun.COM if (curr == NULL)
1433*11878SVenu.Iyer@Sun.COM break;
1434*11878SVenu.Iyer@Sun.COM
1435*11878SVenu.Iyer@Sun.COM curr->dc_statentry = fn(kcp, ksp, index);
1436*11878SVenu.Iyer@Sun.COM if (curr->dc_statentry == NULL) {
1437*11878SVenu.Iyer@Sun.COM free(curr);
1438*11878SVenu.Iyer@Sun.COM break;
1439*11878SVenu.Iyer@Sun.COM }
1440*11878SVenu.Iyer@Sun.COM
1441*11878SVenu.Iyer@Sun.COM (void) strlcpy(curr->dc_statheader, statname,
1442*11878SVenu.Iyer@Sun.COM sizeof (curr->dc_statheader));
1443*11878SVenu.Iyer@Sun.COM curr->dc_next = NULL;
1444*11878SVenu.Iyer@Sun.COM
1445*11878SVenu.Iyer@Sun.COM if (head == NULL) /* First node */
1446*11878SVenu.Iyer@Sun.COM head = curr;
1447*11878SVenu.Iyer@Sun.COM else
1448*11878SVenu.Iyer@Sun.COM prev->dc_next = curr;
1449*11878SVenu.Iyer@Sun.COM
1450*11878SVenu.Iyer@Sun.COM prev = curr;
1451*11878SVenu.Iyer@Sun.COM }
1452*11878SVenu.Iyer@Sun.COM done:
1453*11878SVenu.Iyer@Sun.COM (void) kstat_close(kcp);
1454*11878SVenu.Iyer@Sun.COM return (head);
1455*11878SVenu.Iyer@Sun.COM }
1456*11878SVenu.Iyer@Sun.COM
1457*11878SVenu.Iyer@Sun.COM static misc_stat_entry_t *
i_dlstat_misc_stats(const char * linkname)1458*11878SVenu.Iyer@Sun.COM i_dlstat_misc_stats(const char *linkname)
1459*11878SVenu.Iyer@Sun.COM {
1460*11878SVenu.Iyer@Sun.COM kstat_ctl_t *kcp;
1461*11878SVenu.Iyer@Sun.COM kstat_t *ksp;
1462*11878SVenu.Iyer@Sun.COM misc_stat_entry_t *misc_stat_entry = NULL;
1463*11878SVenu.Iyer@Sun.COM
1464*11878SVenu.Iyer@Sun.COM if ((kcp = kstat_open()) == NULL)
1465*11878SVenu.Iyer@Sun.COM return (NULL);
1466*11878SVenu.Iyer@Sun.COM
1467*11878SVenu.Iyer@Sun.COM ksp = dladm_kstat_lookup(kcp, linkname, 0, DLSTAT_MAC_MISC_STAT, NULL);
1468*11878SVenu.Iyer@Sun.COM if (ksp == NULL)
1469*11878SVenu.Iyer@Sun.COM goto done;
1470*11878SVenu.Iyer@Sun.COM
1471*11878SVenu.Iyer@Sun.COM misc_stat_entry = calloc(1, sizeof (misc_stat_entry_t));
1472*11878SVenu.Iyer@Sun.COM if (misc_stat_entry == NULL)
1473*11878SVenu.Iyer@Sun.COM goto done;
1474*11878SVenu.Iyer@Sun.COM
1475*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &misc_stat_entry->mse_stats,
1476*11878SVenu.Iyer@Sun.COM misc_stats_list, MISC_STAT_SIZE);
1477*11878SVenu.Iyer@Sun.COM done:
1478*11878SVenu.Iyer@Sun.COM (void) kstat_close(kcp);
1479*11878SVenu.Iyer@Sun.COM return (misc_stat_entry);
1480*11878SVenu.Iyer@Sun.COM }
1481*11878SVenu.Iyer@Sun.COM
1482*11878SVenu.Iyer@Sun.COM /* Rx lane statistic specific functions */
1483*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_rx_lane_match(void * arg1,void * arg2)1484*11878SVenu.Iyer@Sun.COM i_dlstat_rx_lane_match(void *arg1, void *arg2)
1485*11878SVenu.Iyer@Sun.COM {
1486*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *s1 = arg1;
1487*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *s2 = arg2;
1488*11878SVenu.Iyer@Sun.COM
1489*11878SVenu.Iyer@Sun.COM return (s1->rle_index == s2->rle_index &&
1490*11878SVenu.Iyer@Sun.COM s1->rle_id == s2->rle_id);
1491*11878SVenu.Iyer@Sun.COM }
1492*11878SVenu.Iyer@Sun.COM
1493*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_rx_lane_stat_entry_diff(void * arg1,void * arg2)1494*11878SVenu.Iyer@Sun.COM i_dlstat_rx_lane_stat_entry_diff(void *arg1, void *arg2)
1495*11878SVenu.Iyer@Sun.COM {
1496*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *s1 = arg1;
1497*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *s2 = arg2;
1498*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *diff_entry;
1499*11878SVenu.Iyer@Sun.COM
1500*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (rx_lane_stat_entry_t));
1501*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
1502*11878SVenu.Iyer@Sun.COM goto done;
1503*11878SVenu.Iyer@Sun.COM
1504*11878SVenu.Iyer@Sun.COM diff_entry->rle_index = s1->rle_index;
1505*11878SVenu.Iyer@Sun.COM diff_entry->rle_id = s1->rle_id;
1506*11878SVenu.Iyer@Sun.COM
1507*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, rle_stats, rx_lane_stats_list,
1508*11878SVenu.Iyer@Sun.COM RX_LANE_STAT_SIZE);
1509*11878SVenu.Iyer@Sun.COM
1510*11878SVenu.Iyer@Sun.COM done:
1511*11878SVenu.Iyer@Sun.COM return (diff_entry);
1512*11878SVenu.Iyer@Sun.COM }
1513*11878SVenu.Iyer@Sun.COM
1514*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_rx_hwlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)1515*11878SVenu.Iyer@Sun.COM i_dlstat_rx_hwlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
1516*11878SVenu.Iyer@Sun.COM {
1517*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
1518*11878SVenu.Iyer@Sun.COM
1519*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1520*11878SVenu.Iyer@Sun.COM if (rx_lane_stat_entry == NULL)
1521*11878SVenu.Iyer@Sun.COM goto done;
1522*11878SVenu.Iyer@Sun.COM
1523*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_index = i;
1524*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_id = L_HWLANE;
1525*11878SVenu.Iyer@Sun.COM
1526*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats,
1527*11878SVenu.Iyer@Sun.COM rx_hwlane_stats_list, RX_HWLANE_STAT_SIZE);
1528*11878SVenu.Iyer@Sun.COM
1529*11878SVenu.Iyer@Sun.COM done:
1530*11878SVenu.Iyer@Sun.COM return (rx_lane_stat_entry);
1531*11878SVenu.Iyer@Sun.COM }
1532*11878SVenu.Iyer@Sun.COM
1533*11878SVenu.Iyer@Sun.COM /*ARGSUSED*/
1534*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_rx_swlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)1535*11878SVenu.Iyer@Sun.COM i_dlstat_rx_swlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
1536*11878SVenu.Iyer@Sun.COM {
1537*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
1538*11878SVenu.Iyer@Sun.COM
1539*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1540*11878SVenu.Iyer@Sun.COM if (rx_lane_stat_entry == NULL)
1541*11878SVenu.Iyer@Sun.COM goto done;
1542*11878SVenu.Iyer@Sun.COM
1543*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
1544*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_id = L_SWLANE;
1545*11878SVenu.Iyer@Sun.COM
1546*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats,
1547*11878SVenu.Iyer@Sun.COM rx_swlane_stats_list, RX_SWLANE_STAT_SIZE);
1548*11878SVenu.Iyer@Sun.COM
1549*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_ipackets =
1550*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_intrs;
1551*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_rbytes =
1552*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_intrbytes;
1553*11878SVenu.Iyer@Sun.COM done:
1554*11878SVenu.Iyer@Sun.COM return (rx_lane_stat_entry);
1555*11878SVenu.Iyer@Sun.COM }
1556*11878SVenu.Iyer@Sun.COM
1557*11878SVenu.Iyer@Sun.COM /*ARGSUSED*/
1558*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_rx_local_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)1559*11878SVenu.Iyer@Sun.COM i_dlstat_rx_local_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
1560*11878SVenu.Iyer@Sun.COM {
1561*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *local_stat_entry;
1562*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
1563*11878SVenu.Iyer@Sun.COM
1564*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1565*11878SVenu.Iyer@Sun.COM if (rx_lane_stat_entry == NULL)
1566*11878SVenu.Iyer@Sun.COM goto done;
1567*11878SVenu.Iyer@Sun.COM
1568*11878SVenu.Iyer@Sun.COM local_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1569*11878SVenu.Iyer@Sun.COM if (local_stat_entry == NULL)
1570*11878SVenu.Iyer@Sun.COM goto done;
1571*11878SVenu.Iyer@Sun.COM
1572*11878SVenu.Iyer@Sun.COM local_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
1573*11878SVenu.Iyer@Sun.COM local_stat_entry->rle_id = L_LOCAL;
1574*11878SVenu.Iyer@Sun.COM
1575*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats,
1576*11878SVenu.Iyer@Sun.COM rx_swlane_stats_list, RX_SWLANE_STAT_SIZE);
1577*11878SVenu.Iyer@Sun.COM
1578*11878SVenu.Iyer@Sun.COM local_stat_entry->rle_stats.rl_ipackets =
1579*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_lclpackets;
1580*11878SVenu.Iyer@Sun.COM local_stat_entry->rle_stats.rl_rbytes =
1581*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_lclbytes;
1582*11878SVenu.Iyer@Sun.COM
1583*11878SVenu.Iyer@Sun.COM done:
1584*11878SVenu.Iyer@Sun.COM free(rx_lane_stat_entry);
1585*11878SVenu.Iyer@Sun.COM return (local_stat_entry);
1586*11878SVenu.Iyer@Sun.COM }
1587*11878SVenu.Iyer@Sun.COM
1588*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_rx_local_stats(const char * linkname)1589*11878SVenu.Iyer@Sun.COM i_dlstat_rx_local_stats(const char *linkname)
1590*11878SVenu.Iyer@Sun.COM {
1591*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *local_stats = NULL;
1592*11878SVenu.Iyer@Sun.COM
1593*11878SVenu.Iyer@Sun.COM local_stats = i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_SWLANE,
1594*11878SVenu.Iyer@Sun.COM default_idlist, default_idlist_size,
1595*11878SVenu.Iyer@Sun.COM i_dlstat_rx_local_retrieve_stat);
1596*11878SVenu.Iyer@Sun.COM
1597*11878SVenu.Iyer@Sun.COM if (local_stats != NULL) {
1598*11878SVenu.Iyer@Sun.COM (void) strlcpy(local_stats->dc_statheader, "mac_rx_local",
1599*11878SVenu.Iyer@Sun.COM sizeof (local_stats->dc_statheader));
1600*11878SVenu.Iyer@Sun.COM }
1601*11878SVenu.Iyer@Sun.COM return (local_stats);
1602*11878SVenu.Iyer@Sun.COM }
1603*11878SVenu.Iyer@Sun.COM
1604*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_rx_bcast_stats(const char * linkname)1605*11878SVenu.Iyer@Sun.COM i_dlstat_rx_bcast_stats(const char *linkname)
1606*11878SVenu.Iyer@Sun.COM {
1607*11878SVenu.Iyer@Sun.COM misc_stat_entry_t *misc_stat_entry;
1608*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1609*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
1610*11878SVenu.Iyer@Sun.COM
1611*11878SVenu.Iyer@Sun.COM misc_stat_entry = i_dlstat_misc_stats(linkname);
1612*11878SVenu.Iyer@Sun.COM if (misc_stat_entry == NULL)
1613*11878SVenu.Iyer@Sun.COM goto done;
1614*11878SVenu.Iyer@Sun.COM
1615*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1616*11878SVenu.Iyer@Sun.COM if (rx_lane_stat_entry == NULL)
1617*11878SVenu.Iyer@Sun.COM goto done;
1618*11878SVenu.Iyer@Sun.COM
1619*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
1620*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_id = L_BCAST;
1621*11878SVenu.Iyer@Sun.COM
1622*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_ipackets =
1623*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_brdcstrcv +
1624*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_multircv;
1625*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_intrs =
1626*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_brdcstrcv +
1627*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_multircv;
1628*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_rbytes =
1629*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_brdcstrcvbytes +
1630*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_multircvbytes;
1631*11878SVenu.Iyer@Sun.COM
1632*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
1633*11878SVenu.Iyer@Sun.COM if (head == NULL) {
1634*11878SVenu.Iyer@Sun.COM free(rx_lane_stat_entry);
1635*11878SVenu.Iyer@Sun.COM goto done;
1636*11878SVenu.Iyer@Sun.COM }
1637*11878SVenu.Iyer@Sun.COM
1638*11878SVenu.Iyer@Sun.COM head->dc_statentry = rx_lane_stat_entry;
1639*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
1640*11878SVenu.Iyer@Sun.COM
1641*11878SVenu.Iyer@Sun.COM free(misc_stat_entry);
1642*11878SVenu.Iyer@Sun.COM done:
1643*11878SVenu.Iyer@Sun.COM return (head);
1644*11878SVenu.Iyer@Sun.COM }
1645*11878SVenu.Iyer@Sun.COM
1646*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_rx_defunctlane_stats(const char * linkname)1647*11878SVenu.Iyer@Sun.COM i_dlstat_rx_defunctlane_stats(const char *linkname)
1648*11878SVenu.Iyer@Sun.COM {
1649*11878SVenu.Iyer@Sun.COM misc_stat_entry_t *misc_stat_entry;
1650*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1651*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
1652*11878SVenu.Iyer@Sun.COM
1653*11878SVenu.Iyer@Sun.COM misc_stat_entry = i_dlstat_misc_stats(linkname);
1654*11878SVenu.Iyer@Sun.COM if (misc_stat_entry == NULL)
1655*11878SVenu.Iyer@Sun.COM goto done;
1656*11878SVenu.Iyer@Sun.COM
1657*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
1658*11878SVenu.Iyer@Sun.COM if (rx_lane_stat_entry == NULL)
1659*11878SVenu.Iyer@Sun.COM goto done;
1660*11878SVenu.Iyer@Sun.COM
1661*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
1662*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_id = L_DFNCT;
1663*11878SVenu.Iyer@Sun.COM
1664*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_ipackets =
1665*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_ipackets;
1666*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_rbytes =
1667*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_rbytes;
1668*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_intrs =
1669*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_intrs;
1670*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_polls =
1671*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_polls;
1672*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_sdrops =
1673*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_rxsdrops;
1674*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_chl10 =
1675*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_chainunder10;
1676*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_ch10_50 =
1677*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_chain10to50;
1678*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_chg50 =
1679*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_chainover50;
1680*11878SVenu.Iyer@Sun.COM
1681*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
1682*11878SVenu.Iyer@Sun.COM if (head == NULL) {
1683*11878SVenu.Iyer@Sun.COM free(rx_lane_stat_entry);
1684*11878SVenu.Iyer@Sun.COM goto done;
1685*11878SVenu.Iyer@Sun.COM }
1686*11878SVenu.Iyer@Sun.COM
1687*11878SVenu.Iyer@Sun.COM head->dc_statentry = rx_lane_stat_entry;
1688*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
1689*11878SVenu.Iyer@Sun.COM
1690*11878SVenu.Iyer@Sun.COM done:
1691*11878SVenu.Iyer@Sun.COM return (head);
1692*11878SVenu.Iyer@Sun.COM }
1693*11878SVenu.Iyer@Sun.COM
1694*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_rx_hwlane_stats(const char * linkname)1695*11878SVenu.Iyer@Sun.COM i_dlstat_rx_hwlane_stats(const char *linkname)
1696*11878SVenu.Iyer@Sun.COM {
1697*11878SVenu.Iyer@Sun.COM uint_t rx_hwlane_idlist[MAX_RINGS_PER_GROUP];
1698*11878SVenu.Iyer@Sun.COM uint_t rx_hwlane_idlist_size;
1699*11878SVenu.Iyer@Sun.COM
1700*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(linkname, DLSTAT_RX_HWLANE_IDLIST,
1701*11878SVenu.Iyer@Sun.COM rx_hwlane_idlist, &rx_hwlane_idlist_size);
1702*11878SVenu.Iyer@Sun.COM
1703*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_HWLANE,
1704*11878SVenu.Iyer@Sun.COM rx_hwlane_idlist, rx_hwlane_idlist_size,
1705*11878SVenu.Iyer@Sun.COM i_dlstat_rx_hwlane_retrieve_stat));
1706*11878SVenu.Iyer@Sun.COM }
1707*11878SVenu.Iyer@Sun.COM
1708*11878SVenu.Iyer@Sun.COM /*ARGSUSED*/
1709*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_rx_swlane_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)1710*11878SVenu.Iyer@Sun.COM i_dlstat_rx_swlane_stats(dladm_handle_t dh, datalink_id_t linkid,
1711*11878SVenu.Iyer@Sun.COM const char *linkname)
1712*11878SVenu.Iyer@Sun.COM {
1713*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_SWLANE,
1714*11878SVenu.Iyer@Sun.COM default_idlist, default_idlist_size,
1715*11878SVenu.Iyer@Sun.COM i_dlstat_rx_swlane_retrieve_stat));
1716*11878SVenu.Iyer@Sun.COM }
1717*11878SVenu.Iyer@Sun.COM
1718*11878SVenu.Iyer@Sun.COM void *
dlstat_rx_lane_stats(dladm_handle_t dh,datalink_id_t linkid)1719*11878SVenu.Iyer@Sun.COM dlstat_rx_lane_stats(dladm_handle_t dh, datalink_id_t linkid)
1720*11878SVenu.Iyer@Sun.COM {
1721*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1722*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *local_stats = NULL;
1723*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *bcast_stats = NULL;
1724*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *defunctlane_stats = NULL;
1725*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *lane_stats = NULL;
1726*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
1727*11878SVenu.Iyer@Sun.COM boolean_t is_legacy_driver;
1728*11878SVenu.Iyer@Sun.COM
1729*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1730*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
1731*11878SVenu.Iyer@Sun.COM goto done;
1732*11878SVenu.Iyer@Sun.COM }
1733*11878SVenu.Iyer@Sun.COM
1734*11878SVenu.Iyer@Sun.COM /* Check if it is legacy driver */
1735*11878SVenu.Iyer@Sun.COM if (dladm_linkprop_is_set(dh, linkid, DLADM_PROP_VAL_CURRENT,
1736*11878SVenu.Iyer@Sun.COM "_softmac", &is_legacy_driver) != DLADM_STATUS_OK) {
1737*11878SVenu.Iyer@Sun.COM goto done;
1738*11878SVenu.Iyer@Sun.COM }
1739*11878SVenu.Iyer@Sun.COM
1740*11878SVenu.Iyer@Sun.COM if (is_legacy_driver) {
1741*11878SVenu.Iyer@Sun.COM head = i_dlstat_legacy_rx_lane_stats(linkname);
1742*11878SVenu.Iyer@Sun.COM goto done;
1743*11878SVenu.Iyer@Sun.COM }
1744*11878SVenu.Iyer@Sun.COM
1745*11878SVenu.Iyer@Sun.COM local_stats = i_dlstat_rx_local_stats(linkname);
1746*11878SVenu.Iyer@Sun.COM bcast_stats = i_dlstat_rx_bcast_stats(linkname);
1747*11878SVenu.Iyer@Sun.COM defunctlane_stats = i_dlstat_rx_defunctlane_stats(linkname);
1748*11878SVenu.Iyer@Sun.COM lane_stats = i_dlstat_rx_hwlane_stats(linkname);
1749*11878SVenu.Iyer@Sun.COM if (lane_stats == NULL)
1750*11878SVenu.Iyer@Sun.COM lane_stats = i_dlstat_rx_swlane_stats(dh, linkid, linkname);
1751*11878SVenu.Iyer@Sun.COM
1752*11878SVenu.Iyer@Sun.COM head = i_dlstat_join_lists(local_stats, bcast_stats);
1753*11878SVenu.Iyer@Sun.COM head = i_dlstat_join_lists(head, defunctlane_stats);
1754*11878SVenu.Iyer@Sun.COM head = i_dlstat_join_lists(head, lane_stats);
1755*11878SVenu.Iyer@Sun.COM done:
1756*11878SVenu.Iyer@Sun.COM return (head);
1757*11878SVenu.Iyer@Sun.COM }
1758*11878SVenu.Iyer@Sun.COM
1759*11878SVenu.Iyer@Sun.COM /* Tx lane statistic specific functions */
1760*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_tx_lane_match(void * arg1,void * arg2)1761*11878SVenu.Iyer@Sun.COM i_dlstat_tx_lane_match(void *arg1, void *arg2)
1762*11878SVenu.Iyer@Sun.COM {
1763*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *s1 = arg1;
1764*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *s2 = arg2;
1765*11878SVenu.Iyer@Sun.COM
1766*11878SVenu.Iyer@Sun.COM return (s1->tle_index == s2->tle_index &&
1767*11878SVenu.Iyer@Sun.COM s1->tle_id == s2->tle_id);
1768*11878SVenu.Iyer@Sun.COM }
1769*11878SVenu.Iyer@Sun.COM
1770*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_tx_lane_stat_entry_diff(void * arg1,void * arg2)1771*11878SVenu.Iyer@Sun.COM i_dlstat_tx_lane_stat_entry_diff(void *arg1, void *arg2)
1772*11878SVenu.Iyer@Sun.COM {
1773*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *s1 = arg1;
1774*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *s2 = arg2;
1775*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *diff_entry;
1776*11878SVenu.Iyer@Sun.COM
1777*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (tx_lane_stat_entry_t));
1778*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
1779*11878SVenu.Iyer@Sun.COM goto done;
1780*11878SVenu.Iyer@Sun.COM
1781*11878SVenu.Iyer@Sun.COM diff_entry->tle_index = s1->tle_index;
1782*11878SVenu.Iyer@Sun.COM diff_entry->tle_id = s1->tle_id;
1783*11878SVenu.Iyer@Sun.COM
1784*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, tle_stats, tx_lane_stats_list,
1785*11878SVenu.Iyer@Sun.COM TX_LANE_STAT_SIZE);
1786*11878SVenu.Iyer@Sun.COM
1787*11878SVenu.Iyer@Sun.COM done:
1788*11878SVenu.Iyer@Sun.COM return (diff_entry);
1789*11878SVenu.Iyer@Sun.COM }
1790*11878SVenu.Iyer@Sun.COM
1791*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_tx_hwlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)1792*11878SVenu.Iyer@Sun.COM i_dlstat_tx_hwlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
1793*11878SVenu.Iyer@Sun.COM {
1794*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *tx_lane_stat_entry;
1795*11878SVenu.Iyer@Sun.COM
1796*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
1797*11878SVenu.Iyer@Sun.COM if (tx_lane_stat_entry == NULL)
1798*11878SVenu.Iyer@Sun.COM goto done;
1799*11878SVenu.Iyer@Sun.COM
1800*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_index = i;
1801*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_id = L_HWLANE;
1802*11878SVenu.Iyer@Sun.COM
1803*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &tx_lane_stat_entry->tle_stats,
1804*11878SVenu.Iyer@Sun.COM tx_lane_stats_list, TX_LANE_STAT_SIZE);
1805*11878SVenu.Iyer@Sun.COM
1806*11878SVenu.Iyer@Sun.COM done:
1807*11878SVenu.Iyer@Sun.COM return (tx_lane_stat_entry);
1808*11878SVenu.Iyer@Sun.COM }
1809*11878SVenu.Iyer@Sun.COM
1810*11878SVenu.Iyer@Sun.COM /*ARGSUSED*/
1811*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_tx_swlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)1812*11878SVenu.Iyer@Sun.COM i_dlstat_tx_swlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
1813*11878SVenu.Iyer@Sun.COM {
1814*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *tx_lane_stat_entry;
1815*11878SVenu.Iyer@Sun.COM
1816*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
1817*11878SVenu.Iyer@Sun.COM if (tx_lane_stat_entry == NULL)
1818*11878SVenu.Iyer@Sun.COM goto done;
1819*11878SVenu.Iyer@Sun.COM
1820*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
1821*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_id = L_SWLANE;
1822*11878SVenu.Iyer@Sun.COM
1823*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &tx_lane_stat_entry->tle_stats,
1824*11878SVenu.Iyer@Sun.COM tx_lane_stats_list, TX_LANE_STAT_SIZE);
1825*11878SVenu.Iyer@Sun.COM
1826*11878SVenu.Iyer@Sun.COM done:
1827*11878SVenu.Iyer@Sun.COM return (tx_lane_stat_entry);
1828*11878SVenu.Iyer@Sun.COM }
1829*11878SVenu.Iyer@Sun.COM
1830*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_tx_bcast_stats(const char * linkname)1831*11878SVenu.Iyer@Sun.COM i_dlstat_tx_bcast_stats(const char *linkname)
1832*11878SVenu.Iyer@Sun.COM {
1833*11878SVenu.Iyer@Sun.COM misc_stat_entry_t *misc_stat_entry;
1834*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1835*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *tx_lane_stat_entry;
1836*11878SVenu.Iyer@Sun.COM
1837*11878SVenu.Iyer@Sun.COM misc_stat_entry = i_dlstat_misc_stats(linkname);
1838*11878SVenu.Iyer@Sun.COM if (misc_stat_entry == NULL)
1839*11878SVenu.Iyer@Sun.COM goto done;
1840*11878SVenu.Iyer@Sun.COM
1841*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
1842*11878SVenu.Iyer@Sun.COM if (tx_lane_stat_entry == NULL)
1843*11878SVenu.Iyer@Sun.COM goto done;
1844*11878SVenu.Iyer@Sun.COM
1845*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
1846*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_id = L_BCAST;
1847*11878SVenu.Iyer@Sun.COM
1848*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_opackets =
1849*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_brdcstxmt +
1850*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_multixmt;
1851*11878SVenu.Iyer@Sun.COM
1852*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_obytes =
1853*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_brdcstxmtbytes +
1854*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_multixmtbytes;
1855*11878SVenu.Iyer@Sun.COM
1856*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
1857*11878SVenu.Iyer@Sun.COM if (head == NULL) {
1858*11878SVenu.Iyer@Sun.COM free(tx_lane_stat_entry);
1859*11878SVenu.Iyer@Sun.COM goto done;
1860*11878SVenu.Iyer@Sun.COM }
1861*11878SVenu.Iyer@Sun.COM
1862*11878SVenu.Iyer@Sun.COM head->dc_statentry = tx_lane_stat_entry;
1863*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
1864*11878SVenu.Iyer@Sun.COM
1865*11878SVenu.Iyer@Sun.COM free(misc_stat_entry);
1866*11878SVenu.Iyer@Sun.COM done:
1867*11878SVenu.Iyer@Sun.COM return (head);
1868*11878SVenu.Iyer@Sun.COM }
1869*11878SVenu.Iyer@Sun.COM
1870*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_tx_defunctlane_stats(const char * linkname)1871*11878SVenu.Iyer@Sun.COM i_dlstat_tx_defunctlane_stats(const char *linkname)
1872*11878SVenu.Iyer@Sun.COM {
1873*11878SVenu.Iyer@Sun.COM misc_stat_entry_t *misc_stat_entry;
1874*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1875*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *tx_lane_stat_entry;
1876*11878SVenu.Iyer@Sun.COM
1877*11878SVenu.Iyer@Sun.COM misc_stat_entry = i_dlstat_misc_stats(linkname);
1878*11878SVenu.Iyer@Sun.COM if (misc_stat_entry == NULL)
1879*11878SVenu.Iyer@Sun.COM goto done;
1880*11878SVenu.Iyer@Sun.COM
1881*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
1882*11878SVenu.Iyer@Sun.COM if (tx_lane_stat_entry == NULL)
1883*11878SVenu.Iyer@Sun.COM goto done;
1884*11878SVenu.Iyer@Sun.COM
1885*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
1886*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_id = L_DFNCT;
1887*11878SVenu.Iyer@Sun.COM
1888*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_opackets =
1889*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_opackets;
1890*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_obytes =
1891*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_obytes;
1892*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_sdrops =
1893*11878SVenu.Iyer@Sun.COM misc_stat_entry->mse_stats.ms_txsdrops;
1894*11878SVenu.Iyer@Sun.COM
1895*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
1896*11878SVenu.Iyer@Sun.COM if (head == NULL) {
1897*11878SVenu.Iyer@Sun.COM free(tx_lane_stat_entry);
1898*11878SVenu.Iyer@Sun.COM goto done;
1899*11878SVenu.Iyer@Sun.COM }
1900*11878SVenu.Iyer@Sun.COM
1901*11878SVenu.Iyer@Sun.COM head->dc_statentry = tx_lane_stat_entry;
1902*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
1903*11878SVenu.Iyer@Sun.COM
1904*11878SVenu.Iyer@Sun.COM done:
1905*11878SVenu.Iyer@Sun.COM return (head);
1906*11878SVenu.Iyer@Sun.COM }
1907*11878SVenu.Iyer@Sun.COM
1908*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_tx_hwlane_stats(const char * linkname)1909*11878SVenu.Iyer@Sun.COM i_dlstat_tx_hwlane_stats(const char *linkname)
1910*11878SVenu.Iyer@Sun.COM {
1911*11878SVenu.Iyer@Sun.COM uint_t tx_hwlane_idlist[MAX_RINGS_PER_GROUP];
1912*11878SVenu.Iyer@Sun.COM uint_t tx_hwlane_idlist_size;
1913*11878SVenu.Iyer@Sun.COM
1914*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(linkname, DLSTAT_TX_HWLANE_IDLIST,
1915*11878SVenu.Iyer@Sun.COM tx_hwlane_idlist, &tx_hwlane_idlist_size);
1916*11878SVenu.Iyer@Sun.COM
1917*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_stats(linkname, DLSTAT_MAC_TX_HWLANE,
1918*11878SVenu.Iyer@Sun.COM tx_hwlane_idlist, tx_hwlane_idlist_size,
1919*11878SVenu.Iyer@Sun.COM i_dlstat_tx_hwlane_retrieve_stat));
1920*11878SVenu.Iyer@Sun.COM }
1921*11878SVenu.Iyer@Sun.COM
1922*11878SVenu.Iyer@Sun.COM /*ARGSUSED*/
1923*11878SVenu.Iyer@Sun.COM static dladm_stat_chain_t *
i_dlstat_tx_swlane_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)1924*11878SVenu.Iyer@Sun.COM i_dlstat_tx_swlane_stats(dladm_handle_t dh, datalink_id_t linkid,
1925*11878SVenu.Iyer@Sun.COM const char *linkname)
1926*11878SVenu.Iyer@Sun.COM {
1927*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_stats(linkname, DLSTAT_MAC_TX_SWLANE,
1928*11878SVenu.Iyer@Sun.COM default_idlist, default_idlist_size,
1929*11878SVenu.Iyer@Sun.COM i_dlstat_tx_swlane_retrieve_stat));
1930*11878SVenu.Iyer@Sun.COM }
1931*11878SVenu.Iyer@Sun.COM
1932*11878SVenu.Iyer@Sun.COM void *
dlstat_tx_lane_stats(dladm_handle_t dh,datalink_id_t linkid)1933*11878SVenu.Iyer@Sun.COM dlstat_tx_lane_stats(dladm_handle_t dh, datalink_id_t linkid)
1934*11878SVenu.Iyer@Sun.COM {
1935*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
1936*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *bcast_stats = NULL;
1937*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *defunctlane_stats = NULL;
1938*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *lane_stats;
1939*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
1940*11878SVenu.Iyer@Sun.COM boolean_t is_legacy_driver;
1941*11878SVenu.Iyer@Sun.COM
1942*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1943*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
1944*11878SVenu.Iyer@Sun.COM goto done;
1945*11878SVenu.Iyer@Sun.COM }
1946*11878SVenu.Iyer@Sun.COM
1947*11878SVenu.Iyer@Sun.COM /* Check if it is legacy driver */
1948*11878SVenu.Iyer@Sun.COM if (dladm_linkprop_is_set(dh, linkid, DLADM_PROP_VAL_CURRENT,
1949*11878SVenu.Iyer@Sun.COM "_softmac", &is_legacy_driver) != DLADM_STATUS_OK) {
1950*11878SVenu.Iyer@Sun.COM goto done;
1951*11878SVenu.Iyer@Sun.COM }
1952*11878SVenu.Iyer@Sun.COM
1953*11878SVenu.Iyer@Sun.COM if (is_legacy_driver) {
1954*11878SVenu.Iyer@Sun.COM head = i_dlstat_legacy_tx_lane_stats(linkname);
1955*11878SVenu.Iyer@Sun.COM goto done;
1956*11878SVenu.Iyer@Sun.COM }
1957*11878SVenu.Iyer@Sun.COM
1958*11878SVenu.Iyer@Sun.COM bcast_stats = i_dlstat_tx_bcast_stats(linkname);
1959*11878SVenu.Iyer@Sun.COM defunctlane_stats = i_dlstat_tx_defunctlane_stats(linkname);
1960*11878SVenu.Iyer@Sun.COM lane_stats = i_dlstat_tx_hwlane_stats(linkname);
1961*11878SVenu.Iyer@Sun.COM if (lane_stats == NULL)
1962*11878SVenu.Iyer@Sun.COM lane_stats = i_dlstat_tx_swlane_stats(dh, linkid, linkname);
1963*11878SVenu.Iyer@Sun.COM
1964*11878SVenu.Iyer@Sun.COM head = i_dlstat_join_lists(bcast_stats, defunctlane_stats);
1965*11878SVenu.Iyer@Sun.COM head = i_dlstat_join_lists(head, lane_stats);
1966*11878SVenu.Iyer@Sun.COM
1967*11878SVenu.Iyer@Sun.COM done:
1968*11878SVenu.Iyer@Sun.COM return (head);
1969*11878SVenu.Iyer@Sun.COM }
1970*11878SVenu.Iyer@Sun.COM
1971*11878SVenu.Iyer@Sun.COM /* Rx lane total statistic specific functions */
1972*11878SVenu.Iyer@Sun.COM void *
dlstat_rx_lane_total_stats(dladm_handle_t dh,datalink_id_t linkid)1973*11878SVenu.Iyer@Sun.COM dlstat_rx_lane_total_stats(dladm_handle_t dh, datalink_id_t linkid)
1974*11878SVenu.Iyer@Sun.COM {
1975*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *total_head = NULL;
1976*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *rx_lane_head, *curr;
1977*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *total_stats;
1978*11878SVenu.Iyer@Sun.COM
1979*11878SVenu.Iyer@Sun.COM /* Get per rx lane stats */
1980*11878SVenu.Iyer@Sun.COM rx_lane_head = dlstat_rx_lane_stats(dh, linkid);
1981*11878SVenu.Iyer@Sun.COM if (rx_lane_head == NULL)
1982*11878SVenu.Iyer@Sun.COM goto done;
1983*11878SVenu.Iyer@Sun.COM
1984*11878SVenu.Iyer@Sun.COM total_stats = calloc(1, sizeof (rx_lane_stat_entry_t));
1985*11878SVenu.Iyer@Sun.COM if (total_stats == NULL)
1986*11878SVenu.Iyer@Sun.COM goto done;
1987*11878SVenu.Iyer@Sun.COM
1988*11878SVenu.Iyer@Sun.COM total_stats->rle_index = DLSTAT_INVALID_ENTRY;
1989*11878SVenu.Iyer@Sun.COM total_stats->rle_id = DLSTAT_INVALID_ENTRY;
1990*11878SVenu.Iyer@Sun.COM
1991*11878SVenu.Iyer@Sun.COM for (curr = rx_lane_head; curr != NULL; curr = curr->dc_next) {
1992*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *curr_lane_stats = curr->dc_statentry;
1993*11878SVenu.Iyer@Sun.COM
1994*11878SVenu.Iyer@Sun.COM i_dlstat_sum_stats(&total_stats->rle_stats,
1995*11878SVenu.Iyer@Sun.COM &curr_lane_stats->rle_stats, &total_stats->rle_stats,
1996*11878SVenu.Iyer@Sun.COM rx_lane_stats_list, RX_LANE_STAT_SIZE);
1997*11878SVenu.Iyer@Sun.COM }
1998*11878SVenu.Iyer@Sun.COM
1999*11878SVenu.Iyer@Sun.COM total_head = malloc(sizeof (dladm_stat_chain_t));
2000*11878SVenu.Iyer@Sun.COM if (total_head == NULL) {
2001*11878SVenu.Iyer@Sun.COM free(total_stats);
2002*11878SVenu.Iyer@Sun.COM goto done;
2003*11878SVenu.Iyer@Sun.COM }
2004*11878SVenu.Iyer@Sun.COM
2005*11878SVenu.Iyer@Sun.COM total_head->dc_statentry = total_stats;
2006*11878SVenu.Iyer@Sun.COM (void) strlcpy(total_head->dc_statheader, "mac_rx_lane_total",
2007*11878SVenu.Iyer@Sun.COM sizeof (total_head->dc_statheader));
2008*11878SVenu.Iyer@Sun.COM total_head->dc_next = NULL;
2009*11878SVenu.Iyer@Sun.COM free(rx_lane_head);
2010*11878SVenu.Iyer@Sun.COM
2011*11878SVenu.Iyer@Sun.COM done:
2012*11878SVenu.Iyer@Sun.COM return (total_head);
2013*11878SVenu.Iyer@Sun.COM }
2014*11878SVenu.Iyer@Sun.COM
2015*11878SVenu.Iyer@Sun.COM /* Tx lane total statistic specific functions */
2016*11878SVenu.Iyer@Sun.COM void *
dlstat_tx_lane_total_stats(dladm_handle_t dh,datalink_id_t linkid)2017*11878SVenu.Iyer@Sun.COM dlstat_tx_lane_total_stats(dladm_handle_t dh, datalink_id_t linkid)
2018*11878SVenu.Iyer@Sun.COM {
2019*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *total_head = NULL;
2020*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *tx_lane_head, *curr;
2021*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *total_stats;
2022*11878SVenu.Iyer@Sun.COM
2023*11878SVenu.Iyer@Sun.COM /* Get per tx lane stats */
2024*11878SVenu.Iyer@Sun.COM tx_lane_head = dlstat_tx_lane_stats(dh, linkid);
2025*11878SVenu.Iyer@Sun.COM if (tx_lane_head == NULL)
2026*11878SVenu.Iyer@Sun.COM goto done;
2027*11878SVenu.Iyer@Sun.COM
2028*11878SVenu.Iyer@Sun.COM total_stats = calloc(1, sizeof (tx_lane_stat_entry_t));
2029*11878SVenu.Iyer@Sun.COM if (total_stats == NULL)
2030*11878SVenu.Iyer@Sun.COM goto done;
2031*11878SVenu.Iyer@Sun.COM
2032*11878SVenu.Iyer@Sun.COM total_stats->tle_index = DLSTAT_INVALID_ENTRY;
2033*11878SVenu.Iyer@Sun.COM total_stats->tle_id = DLSTAT_INVALID_ENTRY;
2034*11878SVenu.Iyer@Sun.COM
2035*11878SVenu.Iyer@Sun.COM for (curr = tx_lane_head; curr != NULL; curr = curr->dc_next) {
2036*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *curr_lane_stats = curr->dc_statentry;
2037*11878SVenu.Iyer@Sun.COM
2038*11878SVenu.Iyer@Sun.COM i_dlstat_sum_stats(&total_stats->tle_stats,
2039*11878SVenu.Iyer@Sun.COM &curr_lane_stats->tle_stats, &total_stats->tle_stats,
2040*11878SVenu.Iyer@Sun.COM tx_lane_stats_list, TX_LANE_STAT_SIZE);
2041*11878SVenu.Iyer@Sun.COM }
2042*11878SVenu.Iyer@Sun.COM
2043*11878SVenu.Iyer@Sun.COM total_head = malloc(sizeof (dladm_stat_chain_t));
2044*11878SVenu.Iyer@Sun.COM if (total_head == NULL) {
2045*11878SVenu.Iyer@Sun.COM free(total_stats);
2046*11878SVenu.Iyer@Sun.COM goto done;
2047*11878SVenu.Iyer@Sun.COM }
2048*11878SVenu.Iyer@Sun.COM
2049*11878SVenu.Iyer@Sun.COM total_head->dc_statentry = total_stats;
2050*11878SVenu.Iyer@Sun.COM (void) strlcpy(total_head->dc_statheader, "mac_tx_lane_total",
2051*11878SVenu.Iyer@Sun.COM sizeof (total_head->dc_statheader));
2052*11878SVenu.Iyer@Sun.COM total_head->dc_next = NULL;
2053*11878SVenu.Iyer@Sun.COM free(tx_lane_head);
2054*11878SVenu.Iyer@Sun.COM
2055*11878SVenu.Iyer@Sun.COM done:
2056*11878SVenu.Iyer@Sun.COM return (total_head);
2057*11878SVenu.Iyer@Sun.COM }
2058*11878SVenu.Iyer@Sun.COM
2059*11878SVenu.Iyer@Sun.COM /* Fanout specific functions */
2060*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_fanout_match(void * arg1,void * arg2)2061*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_match(void *arg1, void *arg2)
2062*11878SVenu.Iyer@Sun.COM {
2063*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *s1 = arg1;
2064*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *s2 = arg2;
2065*11878SVenu.Iyer@Sun.COM
2066*11878SVenu.Iyer@Sun.COM return (s1->fe_index == s2->fe_index &&
2067*11878SVenu.Iyer@Sun.COM s1->fe_id == s2->fe_id &&
2068*11878SVenu.Iyer@Sun.COM s1->fe_foutindex == s2->fe_foutindex);
2069*11878SVenu.Iyer@Sun.COM }
2070*11878SVenu.Iyer@Sun.COM
2071*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_fanout_stat_entry_diff(void * arg1,void * arg2)2072*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_stat_entry_diff(void *arg1, void *arg2)
2073*11878SVenu.Iyer@Sun.COM {
2074*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *s1 = arg1;
2075*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *s2 = arg2;
2076*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *diff_entry;
2077*11878SVenu.Iyer@Sun.COM
2078*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (fanout_stat_entry_t));
2079*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
2080*11878SVenu.Iyer@Sun.COM goto done;
2081*11878SVenu.Iyer@Sun.COM
2082*11878SVenu.Iyer@Sun.COM diff_entry->fe_index = s1->fe_index;
2083*11878SVenu.Iyer@Sun.COM diff_entry->fe_id = s1->fe_id;
2084*11878SVenu.Iyer@Sun.COM diff_entry->fe_foutindex = s1->fe_foutindex;
2085*11878SVenu.Iyer@Sun.COM
2086*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, fe_stats, fanout_stats_list,
2087*11878SVenu.Iyer@Sun.COM FANOUT_STAT_SIZE);
2088*11878SVenu.Iyer@Sun.COM
2089*11878SVenu.Iyer@Sun.COM done:
2090*11878SVenu.Iyer@Sun.COM return (diff_entry);
2091*11878SVenu.Iyer@Sun.COM }
2092*11878SVenu.Iyer@Sun.COM
2093*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_fanout_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)2094*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
2095*11878SVenu.Iyer@Sun.COM {
2096*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *fanout_stat_entry;
2097*11878SVenu.Iyer@Sun.COM
2098*11878SVenu.Iyer@Sun.COM fanout_stat_entry = calloc(1, sizeof (fanout_stat_entry_t));
2099*11878SVenu.Iyer@Sun.COM if (fanout_stat_entry == NULL)
2100*11878SVenu.Iyer@Sun.COM goto done;
2101*11878SVenu.Iyer@Sun.COM
2102*11878SVenu.Iyer@Sun.COM /* Set by the caller later */
2103*11878SVenu.Iyer@Sun.COM fanout_stat_entry->fe_index = DLSTAT_INVALID_ENTRY;
2104*11878SVenu.Iyer@Sun.COM fanout_stat_entry->fe_id = DLSTAT_INVALID_ENTRY;
2105*11878SVenu.Iyer@Sun.COM
2106*11878SVenu.Iyer@Sun.COM fanout_stat_entry->fe_foutindex = i;
2107*11878SVenu.Iyer@Sun.COM
2108*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &fanout_stat_entry->fe_stats,
2109*11878SVenu.Iyer@Sun.COM fanout_stats_list, FANOUT_STAT_SIZE);
2110*11878SVenu.Iyer@Sun.COM
2111*11878SVenu.Iyer@Sun.COM done:
2112*11878SVenu.Iyer@Sun.COM return (fanout_stat_entry);
2113*11878SVenu.Iyer@Sun.COM }
2114*11878SVenu.Iyer@Sun.COM
2115*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_query_fanout_stats(dladm_handle_t dh,datalink_id_t linkid,uint_t idlist[],uint_t idlist_size,const char * modname,const char * prefix)2116*11878SVenu.Iyer@Sun.COM i_dlstat_query_fanout_stats(dladm_handle_t dh, datalink_id_t linkid,
2117*11878SVenu.Iyer@Sun.COM uint_t idlist[], uint_t idlist_size,
2118*11878SVenu.Iyer@Sun.COM const char *modname, const char *prefix)
2119*11878SVenu.Iyer@Sun.COM {
2120*11878SVenu.Iyer@Sun.COM int i;
2121*11878SVenu.Iyer@Sun.COM char statprefix[MAXLINKNAMELEN];
2122*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
2123*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *curr, *curr_head;
2124*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL, *prev = NULL;
2125*11878SVenu.Iyer@Sun.COM uint_t fanout_idlist[MAX_RINGS_PER_GROUP];
2126*11878SVenu.Iyer@Sun.COM uint_t fanout_idlist_size;
2127*11878SVenu.Iyer@Sun.COM
2128*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
2129*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2130*11878SVenu.Iyer@Sun.COM return (NULL);
2131*11878SVenu.Iyer@Sun.COM }
2132*11878SVenu.Iyer@Sun.COM
2133*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(linkname, DLSTAT_FANOUT_IDLIST,
2134*11878SVenu.Iyer@Sun.COM fanout_idlist, &fanout_idlist_size);
2135*11878SVenu.Iyer@Sun.COM
2136*11878SVenu.Iyer@Sun.COM for (i = 0; i < idlist_size; i++) {
2137*11878SVenu.Iyer@Sun.COM uint_t index = idlist[i];
2138*11878SVenu.Iyer@Sun.COM
2139*11878SVenu.Iyer@Sun.COM (void) snprintf(statprefix, sizeof (statprefix), "%s%d_fanout",
2140*11878SVenu.Iyer@Sun.COM prefix, index);
2141*11878SVenu.Iyer@Sun.COM
2142*11878SVenu.Iyer@Sun.COM curr_head = i_dlstat_query_stats(modname, statprefix,
2143*11878SVenu.Iyer@Sun.COM fanout_idlist, fanout_idlist_size,
2144*11878SVenu.Iyer@Sun.COM i_dlstat_fanout_retrieve_stat);
2145*11878SVenu.Iyer@Sun.COM
2146*11878SVenu.Iyer@Sun.COM if (curr_head == NULL) /* Last lane */
2147*11878SVenu.Iyer@Sun.COM break;
2148*11878SVenu.Iyer@Sun.COM
2149*11878SVenu.Iyer@Sun.COM if (head == NULL) /* First lane */
2150*11878SVenu.Iyer@Sun.COM head = curr_head;
2151*11878SVenu.Iyer@Sun.COM else /* Link new lane list to end of previous lane list */
2152*11878SVenu.Iyer@Sun.COM prev->dc_next = curr_head;
2153*11878SVenu.Iyer@Sun.COM
2154*11878SVenu.Iyer@Sun.COM /* Walk new lane list and set ids */
2155*11878SVenu.Iyer@Sun.COM for (curr = curr_head; curr != NULL; curr = curr->dc_next) {
2156*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *curr_stats = curr->dc_statentry;
2157*11878SVenu.Iyer@Sun.COM
2158*11878SVenu.Iyer@Sun.COM curr_stats->fe_index = index;
2159*11878SVenu.Iyer@Sun.COM curr_stats->fe_id = L_HWLANE;
2160*11878SVenu.Iyer@Sun.COM /*
2161*11878SVenu.Iyer@Sun.COM * Save last pointer of previous linked list.
2162*11878SVenu.Iyer@Sun.COM * This pointer is used to chain linked lists
2163*11878SVenu.Iyer@Sun.COM * generated in each iteration.
2164*11878SVenu.Iyer@Sun.COM */
2165*11878SVenu.Iyer@Sun.COM prev = curr;
2166*11878SVenu.Iyer@Sun.COM }
2167*11878SVenu.Iyer@Sun.COM }
2168*11878SVenu.Iyer@Sun.COM
2169*11878SVenu.Iyer@Sun.COM return (head);
2170*11878SVenu.Iyer@Sun.COM }
2171*11878SVenu.Iyer@Sun.COM
2172*11878SVenu.Iyer@Sun.COM void *
dlstat_fanout_swlane_and_local_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)2173*11878SVenu.Iyer@Sun.COM dlstat_fanout_swlane_and_local_stats(dladm_handle_t dh, datalink_id_t linkid,
2174*11878SVenu.Iyer@Sun.COM const char *linkname)
2175*11878SVenu.Iyer@Sun.COM {
2176*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_fanout_stats(dh, linkid,
2177*11878SVenu.Iyer@Sun.COM default_idlist, default_idlist_size, linkname,
2178*11878SVenu.Iyer@Sun.COM DLSTAT_MAC_RX_SWLANE));
2179*11878SVenu.Iyer@Sun.COM }
2180*11878SVenu.Iyer@Sun.COM
2181*11878SVenu.Iyer@Sun.COM void *
dlstat_fanout_hwlane_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)2182*11878SVenu.Iyer@Sun.COM dlstat_fanout_hwlane_stats(dladm_handle_t dh, datalink_id_t linkid,
2183*11878SVenu.Iyer@Sun.COM const char *linkname)
2184*11878SVenu.Iyer@Sun.COM {
2185*11878SVenu.Iyer@Sun.COM uint_t rx_hwlane_idlist[MAX_RINGS_PER_GROUP];
2186*11878SVenu.Iyer@Sun.COM uint_t rx_hwlane_idlist_size;
2187*11878SVenu.Iyer@Sun.COM
2188*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(linkname, DLSTAT_RX_HWLANE_IDLIST,
2189*11878SVenu.Iyer@Sun.COM rx_hwlane_idlist, &rx_hwlane_idlist_size);
2190*11878SVenu.Iyer@Sun.COM
2191*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_fanout_stats(dh, linkid, rx_hwlane_idlist,
2192*11878SVenu.Iyer@Sun.COM rx_hwlane_idlist_size, linkname, DLSTAT_MAC_RX_HWLANE));
2193*11878SVenu.Iyer@Sun.COM }
2194*11878SVenu.Iyer@Sun.COM
2195*11878SVenu.Iyer@Sun.COM void *
dlstat_fanout_stats(dladm_handle_t dh,datalink_id_t linkid)2196*11878SVenu.Iyer@Sun.COM dlstat_fanout_stats(dladm_handle_t dh, datalink_id_t linkid)
2197*11878SVenu.Iyer@Sun.COM {
2198*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
2199*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *fout_hwlane_stats;
2200*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *fout_swlane_and_local_stats;
2201*11878SVenu.Iyer@Sun.COM fanout_stat_entry_t *fout_stats;
2202*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
2203*11878SVenu.Iyer@Sun.COM
2204*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
2205*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2206*11878SVenu.Iyer@Sun.COM goto done;
2207*11878SVenu.Iyer@Sun.COM }
2208*11878SVenu.Iyer@Sun.COM
2209*11878SVenu.Iyer@Sun.COM fout_swlane_and_local_stats =
2210*11878SVenu.Iyer@Sun.COM dlstat_fanout_swlane_and_local_stats(dh, linkid, linkname);
2211*11878SVenu.Iyer@Sun.COM fout_hwlane_stats = dlstat_fanout_hwlane_stats(dh, linkid, linkname);
2212*11878SVenu.Iyer@Sun.COM
2213*11878SVenu.Iyer@Sun.COM if (fout_swlane_and_local_stats == NULL) {
2214*11878SVenu.Iyer@Sun.COM head = fout_hwlane_stats;
2215*11878SVenu.Iyer@Sun.COM goto done;
2216*11878SVenu.Iyer@Sun.COM }
2217*11878SVenu.Iyer@Sun.COM
2218*11878SVenu.Iyer@Sun.COM fout_stats = fout_swlane_and_local_stats->dc_statentry;
2219*11878SVenu.Iyer@Sun.COM
2220*11878SVenu.Iyer@Sun.COM if (fout_hwlane_stats != NULL) { /* hwlane(s), only local traffic */
2221*11878SVenu.Iyer@Sun.COM fout_stats->fe_id = L_LOCAL;
2222*11878SVenu.Iyer@Sun.COM fout_stats->fe_index = DLSTAT_INVALID_ENTRY;
2223*11878SVenu.Iyer@Sun.COM } else { /* no hwlane, mix of local+sw classified */
2224*11878SVenu.Iyer@Sun.COM fout_stats->fe_id = L_LCLSWLANE;
2225*11878SVenu.Iyer@Sun.COM fout_stats->fe_index = DLSTAT_INVALID_ENTRY;
2226*11878SVenu.Iyer@Sun.COM }
2227*11878SVenu.Iyer@Sun.COM
2228*11878SVenu.Iyer@Sun.COM fout_swlane_and_local_stats->dc_next = fout_hwlane_stats;
2229*11878SVenu.Iyer@Sun.COM head = fout_swlane_and_local_stats;
2230*11878SVenu.Iyer@Sun.COM
2231*11878SVenu.Iyer@Sun.COM done:
2232*11878SVenu.Iyer@Sun.COM return (head);
2233*11878SVenu.Iyer@Sun.COM }
2234*11878SVenu.Iyer@Sun.COM
2235*11878SVenu.Iyer@Sun.COM /* Rx ring statistic specific functions */
2236*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_rx_ring_match(void * arg1,void * arg2)2237*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_match(void *arg1, void *arg2)
2238*11878SVenu.Iyer@Sun.COM {
2239*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *s1 = arg1;
2240*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *s2 = arg2;
2241*11878SVenu.Iyer@Sun.COM
2242*11878SVenu.Iyer@Sun.COM return (s1->rle_index == s2->rle_index);
2243*11878SVenu.Iyer@Sun.COM }
2244*11878SVenu.Iyer@Sun.COM
2245*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_rx_ring_stat_entry_diff(void * arg1,void * arg2)2246*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_stat_entry_diff(void *arg1, void *arg2)
2247*11878SVenu.Iyer@Sun.COM {
2248*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *s1 = arg1;
2249*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *s2 = arg2;
2250*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *diff_entry;
2251*11878SVenu.Iyer@Sun.COM
2252*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (ring_stat_entry_t));
2253*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
2254*11878SVenu.Iyer@Sun.COM goto done;
2255*11878SVenu.Iyer@Sun.COM
2256*11878SVenu.Iyer@Sun.COM diff_entry->re_index = s1->re_index;
2257*11878SVenu.Iyer@Sun.COM
2258*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, re_stats, rx_ring_stats_list,
2259*11878SVenu.Iyer@Sun.COM RX_RING_STAT_SIZE);
2260*11878SVenu.Iyer@Sun.COM
2261*11878SVenu.Iyer@Sun.COM done:
2262*11878SVenu.Iyer@Sun.COM return (diff_entry);
2263*11878SVenu.Iyer@Sun.COM }
2264*11878SVenu.Iyer@Sun.COM
2265*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_rx_ring_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)2266*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
2267*11878SVenu.Iyer@Sun.COM {
2268*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *rx_ring_stat_entry;
2269*11878SVenu.Iyer@Sun.COM
2270*11878SVenu.Iyer@Sun.COM rx_ring_stat_entry = calloc(1, sizeof (ring_stat_entry_t));
2271*11878SVenu.Iyer@Sun.COM if (rx_ring_stat_entry == NULL)
2272*11878SVenu.Iyer@Sun.COM goto done;
2273*11878SVenu.Iyer@Sun.COM
2274*11878SVenu.Iyer@Sun.COM rx_ring_stat_entry->re_index = i;
2275*11878SVenu.Iyer@Sun.COM
2276*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &rx_ring_stat_entry->re_stats,
2277*11878SVenu.Iyer@Sun.COM rx_ring_stats_list, RX_RING_STAT_SIZE);
2278*11878SVenu.Iyer@Sun.COM
2279*11878SVenu.Iyer@Sun.COM done:
2280*11878SVenu.Iyer@Sun.COM return (rx_ring_stat_entry);
2281*11878SVenu.Iyer@Sun.COM }
2282*11878SVenu.Iyer@Sun.COM
2283*11878SVenu.Iyer@Sun.COM void *
dlstat_rx_ring_stats(dladm_handle_t dh,datalink_id_t linkid)2284*11878SVenu.Iyer@Sun.COM dlstat_rx_ring_stats(dladm_handle_t dh, datalink_id_t linkid)
2285*11878SVenu.Iyer@Sun.COM {
2286*11878SVenu.Iyer@Sun.COM uint_t rx_ring_idlist[MAX_RINGS_PER_GROUP];
2287*11878SVenu.Iyer@Sun.COM uint_t rx_ring_idlist_size;
2288*11878SVenu.Iyer@Sun.COM dladm_phys_attr_t dpa;
2289*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
2290*11878SVenu.Iyer@Sun.COM char *modname;
2291*11878SVenu.Iyer@Sun.COM datalink_class_t class;
2292*11878SVenu.Iyer@Sun.COM
2293*11878SVenu.Iyer@Sun.COM /*
2294*11878SVenu.Iyer@Sun.COM * kstats corresponding to physical device rings continue to use
2295*11878SVenu.Iyer@Sun.COM * device names even if the link is renamed using dladm rename-link.
2296*11878SVenu.Iyer@Sun.COM * Thus, given a linkid, we lookup the physical device name.
2297*11878SVenu.Iyer@Sun.COM * However, if an aggr is renamed, kstats corresponding to its
2298*11878SVenu.Iyer@Sun.COM * pseudo rings are renamed as well.
2299*11878SVenu.Iyer@Sun.COM */
2300*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, linkname,
2301*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2302*11878SVenu.Iyer@Sun.COM return (NULL);
2303*11878SVenu.Iyer@Sun.COM }
2304*11878SVenu.Iyer@Sun.COM
2305*11878SVenu.Iyer@Sun.COM if (class != DATALINK_CLASS_AGGR) {
2306*11878SVenu.Iyer@Sun.COM if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
2307*11878SVenu.Iyer@Sun.COM DLADM_STATUS_OK) {
2308*11878SVenu.Iyer@Sun.COM return (NULL);
2309*11878SVenu.Iyer@Sun.COM }
2310*11878SVenu.Iyer@Sun.COM modname = dpa.dp_dev;
2311*11878SVenu.Iyer@Sun.COM } else
2312*11878SVenu.Iyer@Sun.COM modname = linkname;
2313*11878SVenu.Iyer@Sun.COM
2314*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(modname, DLSTAT_RX_RING_IDLIST,
2315*11878SVenu.Iyer@Sun.COM rx_ring_idlist, &rx_ring_idlist_size);
2316*11878SVenu.Iyer@Sun.COM
2317*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_stats(modname, DLSTAT_MAC_RX_RING,
2318*11878SVenu.Iyer@Sun.COM rx_ring_idlist, rx_ring_idlist_size,
2319*11878SVenu.Iyer@Sun.COM i_dlstat_rx_ring_retrieve_stat));
2320*11878SVenu.Iyer@Sun.COM }
2321*11878SVenu.Iyer@Sun.COM
2322*11878SVenu.Iyer@Sun.COM /* Tx ring statistic specific functions */
2323*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_tx_ring_match(void * arg1,void * arg2)2324*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_match(void *arg1, void *arg2)
2325*11878SVenu.Iyer@Sun.COM {
2326*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *s1 = arg1;
2327*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *s2 = arg2;
2328*11878SVenu.Iyer@Sun.COM
2329*11878SVenu.Iyer@Sun.COM return (s1->tle_index == s2->tle_index);
2330*11878SVenu.Iyer@Sun.COM }
2331*11878SVenu.Iyer@Sun.COM
2332*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_tx_ring_stat_entry_diff(void * arg1,void * arg2)2333*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_stat_entry_diff(void *arg1, void *arg2)
2334*11878SVenu.Iyer@Sun.COM {
2335*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *s1 = arg1;
2336*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *s2 = arg2;
2337*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *diff_entry;
2338*11878SVenu.Iyer@Sun.COM
2339*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (ring_stat_entry_t));
2340*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
2341*11878SVenu.Iyer@Sun.COM goto done;
2342*11878SVenu.Iyer@Sun.COM
2343*11878SVenu.Iyer@Sun.COM diff_entry->re_index = s1->re_index;
2344*11878SVenu.Iyer@Sun.COM
2345*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, re_stats, tx_ring_stats_list,
2346*11878SVenu.Iyer@Sun.COM TX_RING_STAT_SIZE);
2347*11878SVenu.Iyer@Sun.COM
2348*11878SVenu.Iyer@Sun.COM done:
2349*11878SVenu.Iyer@Sun.COM return (diff_entry);
2350*11878SVenu.Iyer@Sun.COM }
2351*11878SVenu.Iyer@Sun.COM
2352*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_tx_ring_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)2353*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
2354*11878SVenu.Iyer@Sun.COM {
2355*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *tx_ring_stat_entry;
2356*11878SVenu.Iyer@Sun.COM
2357*11878SVenu.Iyer@Sun.COM tx_ring_stat_entry = calloc(1, sizeof (ring_stat_entry_t));
2358*11878SVenu.Iyer@Sun.COM if (tx_ring_stat_entry == NULL)
2359*11878SVenu.Iyer@Sun.COM goto done;
2360*11878SVenu.Iyer@Sun.COM
2361*11878SVenu.Iyer@Sun.COM tx_ring_stat_entry->re_index = i;
2362*11878SVenu.Iyer@Sun.COM
2363*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &tx_ring_stat_entry->re_stats,
2364*11878SVenu.Iyer@Sun.COM tx_ring_stats_list, TX_RING_STAT_SIZE);
2365*11878SVenu.Iyer@Sun.COM
2366*11878SVenu.Iyer@Sun.COM done:
2367*11878SVenu.Iyer@Sun.COM return (tx_ring_stat_entry);
2368*11878SVenu.Iyer@Sun.COM }
2369*11878SVenu.Iyer@Sun.COM
2370*11878SVenu.Iyer@Sun.COM void *
dlstat_tx_ring_stats(dladm_handle_t dh,datalink_id_t linkid)2371*11878SVenu.Iyer@Sun.COM dlstat_tx_ring_stats(dladm_handle_t dh, datalink_id_t linkid)
2372*11878SVenu.Iyer@Sun.COM {
2373*11878SVenu.Iyer@Sun.COM uint_t tx_ring_idlist[MAX_RINGS_PER_GROUP];
2374*11878SVenu.Iyer@Sun.COM uint_t tx_ring_idlist_size;
2375*11878SVenu.Iyer@Sun.COM dladm_phys_attr_t dpa;
2376*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
2377*11878SVenu.Iyer@Sun.COM char *modname;
2378*11878SVenu.Iyer@Sun.COM datalink_class_t class;
2379*11878SVenu.Iyer@Sun.COM
2380*11878SVenu.Iyer@Sun.COM /*
2381*11878SVenu.Iyer@Sun.COM * kstats corresponding to physical device rings continue to use
2382*11878SVenu.Iyer@Sun.COM * device names even if the link is renamed using dladm rename-link.
2383*11878SVenu.Iyer@Sun.COM * Thus, given a linkid, we lookup the physical device name.
2384*11878SVenu.Iyer@Sun.COM * However, if an aggr is renamed, kstats corresponding to its
2385*11878SVenu.Iyer@Sun.COM * pseudo rings are renamed as well.
2386*11878SVenu.Iyer@Sun.COM */
2387*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, linkname,
2388*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2389*11878SVenu.Iyer@Sun.COM return (NULL);
2390*11878SVenu.Iyer@Sun.COM }
2391*11878SVenu.Iyer@Sun.COM
2392*11878SVenu.Iyer@Sun.COM if (class != DATALINK_CLASS_AGGR) {
2393*11878SVenu.Iyer@Sun.COM if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
2394*11878SVenu.Iyer@Sun.COM DLADM_STATUS_OK) {
2395*11878SVenu.Iyer@Sun.COM return (NULL);
2396*11878SVenu.Iyer@Sun.COM }
2397*11878SVenu.Iyer@Sun.COM modname = dpa.dp_dev;
2398*11878SVenu.Iyer@Sun.COM } else
2399*11878SVenu.Iyer@Sun.COM modname = linkname;
2400*11878SVenu.Iyer@Sun.COM
2401*11878SVenu.Iyer@Sun.COM i_dlstat_get_idlist(modname, DLSTAT_TX_RING_IDLIST,
2402*11878SVenu.Iyer@Sun.COM tx_ring_idlist, &tx_ring_idlist_size);
2403*11878SVenu.Iyer@Sun.COM
2404*11878SVenu.Iyer@Sun.COM return (i_dlstat_query_stats(modname, DLSTAT_MAC_TX_RING,
2405*11878SVenu.Iyer@Sun.COM tx_ring_idlist, tx_ring_idlist_size,
2406*11878SVenu.Iyer@Sun.COM i_dlstat_tx_ring_retrieve_stat));
2407*11878SVenu.Iyer@Sun.COM }
2408*11878SVenu.Iyer@Sun.COM
2409*11878SVenu.Iyer@Sun.COM /* Rx ring total statistic specific functions */
2410*11878SVenu.Iyer@Sun.COM void *
dlstat_rx_ring_total_stats(dladm_handle_t dh,datalink_id_t linkid)2411*11878SVenu.Iyer@Sun.COM dlstat_rx_ring_total_stats(dladm_handle_t dh, datalink_id_t linkid)
2412*11878SVenu.Iyer@Sun.COM {
2413*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *total_head = NULL;
2414*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *rx_ring_head, *curr;
2415*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *total_stats;
2416*11878SVenu.Iyer@Sun.COM
2417*11878SVenu.Iyer@Sun.COM /* Get per rx ring stats */
2418*11878SVenu.Iyer@Sun.COM rx_ring_head = dlstat_rx_ring_stats(dh, linkid);
2419*11878SVenu.Iyer@Sun.COM if (rx_ring_head == NULL)
2420*11878SVenu.Iyer@Sun.COM goto done;
2421*11878SVenu.Iyer@Sun.COM
2422*11878SVenu.Iyer@Sun.COM total_stats = calloc(1, sizeof (ring_stat_entry_t));
2423*11878SVenu.Iyer@Sun.COM if (total_stats == NULL)
2424*11878SVenu.Iyer@Sun.COM goto done;
2425*11878SVenu.Iyer@Sun.COM
2426*11878SVenu.Iyer@Sun.COM total_stats->re_index = DLSTAT_INVALID_ENTRY;
2427*11878SVenu.Iyer@Sun.COM
2428*11878SVenu.Iyer@Sun.COM for (curr = rx_ring_head; curr != NULL; curr = curr->dc_next) {
2429*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *curr_ring_stats = curr->dc_statentry;
2430*11878SVenu.Iyer@Sun.COM
2431*11878SVenu.Iyer@Sun.COM i_dlstat_sum_stats(&total_stats->re_stats,
2432*11878SVenu.Iyer@Sun.COM &curr_ring_stats->re_stats, &total_stats->re_stats,
2433*11878SVenu.Iyer@Sun.COM rx_ring_stats_list, RX_RING_STAT_SIZE);
2434*11878SVenu.Iyer@Sun.COM }
2435*11878SVenu.Iyer@Sun.COM
2436*11878SVenu.Iyer@Sun.COM total_head = malloc(sizeof (dladm_stat_chain_t));
2437*11878SVenu.Iyer@Sun.COM if (total_head == NULL) {
2438*11878SVenu.Iyer@Sun.COM free(total_stats);
2439*11878SVenu.Iyer@Sun.COM goto done;
2440*11878SVenu.Iyer@Sun.COM }
2441*11878SVenu.Iyer@Sun.COM
2442*11878SVenu.Iyer@Sun.COM total_head->dc_statentry = total_stats;
2443*11878SVenu.Iyer@Sun.COM (void) strlcpy(total_head->dc_statheader, "mac_rx_ring_total",
2444*11878SVenu.Iyer@Sun.COM sizeof (total_head->dc_statheader));
2445*11878SVenu.Iyer@Sun.COM total_head->dc_next = NULL;
2446*11878SVenu.Iyer@Sun.COM free(rx_ring_head);
2447*11878SVenu.Iyer@Sun.COM
2448*11878SVenu.Iyer@Sun.COM done:
2449*11878SVenu.Iyer@Sun.COM return (total_head);
2450*11878SVenu.Iyer@Sun.COM }
2451*11878SVenu.Iyer@Sun.COM
2452*11878SVenu.Iyer@Sun.COM /* Tx ring total statistic specific functions */
2453*11878SVenu.Iyer@Sun.COM void *
dlstat_tx_ring_total_stats(dladm_handle_t dh,datalink_id_t linkid)2454*11878SVenu.Iyer@Sun.COM dlstat_tx_ring_total_stats(dladm_handle_t dh, datalink_id_t linkid)
2455*11878SVenu.Iyer@Sun.COM {
2456*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *total_head = NULL;
2457*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *tx_ring_head, *curr;
2458*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *total_stats;
2459*11878SVenu.Iyer@Sun.COM
2460*11878SVenu.Iyer@Sun.COM /* Get per tx ring stats */
2461*11878SVenu.Iyer@Sun.COM tx_ring_head = dlstat_tx_ring_stats(dh, linkid);
2462*11878SVenu.Iyer@Sun.COM if (tx_ring_head == NULL)
2463*11878SVenu.Iyer@Sun.COM goto done;
2464*11878SVenu.Iyer@Sun.COM
2465*11878SVenu.Iyer@Sun.COM total_stats = calloc(1, sizeof (ring_stat_entry_t));
2466*11878SVenu.Iyer@Sun.COM if (total_stats == NULL)
2467*11878SVenu.Iyer@Sun.COM goto done;
2468*11878SVenu.Iyer@Sun.COM
2469*11878SVenu.Iyer@Sun.COM total_stats->re_index = DLSTAT_INVALID_ENTRY;
2470*11878SVenu.Iyer@Sun.COM
2471*11878SVenu.Iyer@Sun.COM for (curr = tx_ring_head; curr != NULL; curr = curr->dc_next) {
2472*11878SVenu.Iyer@Sun.COM ring_stat_entry_t *curr_ring_stats = curr->dc_statentry;
2473*11878SVenu.Iyer@Sun.COM
2474*11878SVenu.Iyer@Sun.COM i_dlstat_sum_stats(&total_stats->re_stats,
2475*11878SVenu.Iyer@Sun.COM &curr_ring_stats->re_stats, &total_stats->re_stats,
2476*11878SVenu.Iyer@Sun.COM tx_ring_stats_list, TX_RING_STAT_SIZE);
2477*11878SVenu.Iyer@Sun.COM }
2478*11878SVenu.Iyer@Sun.COM
2479*11878SVenu.Iyer@Sun.COM total_head = malloc(sizeof (dladm_stat_chain_t));
2480*11878SVenu.Iyer@Sun.COM if (total_head == NULL) {
2481*11878SVenu.Iyer@Sun.COM free(total_stats);
2482*11878SVenu.Iyer@Sun.COM goto done;
2483*11878SVenu.Iyer@Sun.COM }
2484*11878SVenu.Iyer@Sun.COM
2485*11878SVenu.Iyer@Sun.COM total_head->dc_statentry = total_stats;
2486*11878SVenu.Iyer@Sun.COM (void) strlcpy(total_head->dc_statheader, "mac_tx_ring_total",
2487*11878SVenu.Iyer@Sun.COM sizeof (total_head->dc_statheader));
2488*11878SVenu.Iyer@Sun.COM total_head->dc_next = NULL;
2489*11878SVenu.Iyer@Sun.COM free(tx_ring_head);
2490*11878SVenu.Iyer@Sun.COM
2491*11878SVenu.Iyer@Sun.COM done:
2492*11878SVenu.Iyer@Sun.COM return (total_head);
2493*11878SVenu.Iyer@Sun.COM }
2494*11878SVenu.Iyer@Sun.COM
2495*11878SVenu.Iyer@Sun.COM /* Summary statistic specific functions */
2496*11878SVenu.Iyer@Sun.COM /*ARGSUSED*/
2497*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_total_match(void * arg1,void * arg2)2498*11878SVenu.Iyer@Sun.COM i_dlstat_total_match(void *arg1, void *arg2)
2499*11878SVenu.Iyer@Sun.COM { /* Always single entry for total */
2500*11878SVenu.Iyer@Sun.COM return (B_TRUE);
2501*11878SVenu.Iyer@Sun.COM }
2502*11878SVenu.Iyer@Sun.COM
2503*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_total_stat_entry_diff(void * arg1,void * arg2)2504*11878SVenu.Iyer@Sun.COM i_dlstat_total_stat_entry_diff(void *arg1, void *arg2)
2505*11878SVenu.Iyer@Sun.COM {
2506*11878SVenu.Iyer@Sun.COM total_stat_entry_t *s1 = arg1;
2507*11878SVenu.Iyer@Sun.COM total_stat_entry_t *s2 = arg2;
2508*11878SVenu.Iyer@Sun.COM total_stat_entry_t *diff_entry;
2509*11878SVenu.Iyer@Sun.COM
2510*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (total_stat_entry_t));
2511*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
2512*11878SVenu.Iyer@Sun.COM goto done;
2513*11878SVenu.Iyer@Sun.COM
2514*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, tse_stats, total_stats_list,
2515*11878SVenu.Iyer@Sun.COM TOTAL_STAT_SIZE);
2516*11878SVenu.Iyer@Sun.COM
2517*11878SVenu.Iyer@Sun.COM done:
2518*11878SVenu.Iyer@Sun.COM return (diff_entry);
2519*11878SVenu.Iyer@Sun.COM }
2520*11878SVenu.Iyer@Sun.COM
2521*11878SVenu.Iyer@Sun.COM void *
dlstat_total_stats(dladm_handle_t dh,datalink_id_t linkid)2522*11878SVenu.Iyer@Sun.COM dlstat_total_stats(dladm_handle_t dh, datalink_id_t linkid)
2523*11878SVenu.Iyer@Sun.COM {
2524*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
2525*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *rx_total;
2526*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *tx_total;
2527*11878SVenu.Iyer@Sun.COM total_stat_entry_t *total_stat_entry;
2528*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry_t *rx_lane_stat_entry;
2529*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry_t *tx_lane_stat_entry;
2530*11878SVenu.Iyer@Sun.COM
2531*11878SVenu.Iyer@Sun.COM /* Get total rx lane stats */
2532*11878SVenu.Iyer@Sun.COM rx_total = dlstat_rx_lane_total_stats(dh, linkid);
2533*11878SVenu.Iyer@Sun.COM if (rx_total == NULL)
2534*11878SVenu.Iyer@Sun.COM goto done;
2535*11878SVenu.Iyer@Sun.COM
2536*11878SVenu.Iyer@Sun.COM /* Get total tx lane stats */
2537*11878SVenu.Iyer@Sun.COM tx_total = dlstat_tx_lane_total_stats(dh, linkid);
2538*11878SVenu.Iyer@Sun.COM if (tx_total == NULL)
2539*11878SVenu.Iyer@Sun.COM goto done;
2540*11878SVenu.Iyer@Sun.COM
2541*11878SVenu.Iyer@Sun.COM /* Build total stat */
2542*11878SVenu.Iyer@Sun.COM total_stat_entry = calloc(1, sizeof (total_stat_entry_t));
2543*11878SVenu.Iyer@Sun.COM if (total_stat_entry == NULL)
2544*11878SVenu.Iyer@Sun.COM goto done;
2545*11878SVenu.Iyer@Sun.COM
2546*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry = rx_total->dc_statentry;
2547*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry = tx_total->dc_statentry;
2548*11878SVenu.Iyer@Sun.COM
2549*11878SVenu.Iyer@Sun.COM /* Extract total rx ipackets, rbytes */
2550*11878SVenu.Iyer@Sun.COM total_stat_entry->tse_stats.ts_ipackets =
2551*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_ipackets;
2552*11878SVenu.Iyer@Sun.COM total_stat_entry->tse_stats.ts_rbytes =
2553*11878SVenu.Iyer@Sun.COM rx_lane_stat_entry->rle_stats.rl_rbytes;
2554*11878SVenu.Iyer@Sun.COM
2555*11878SVenu.Iyer@Sun.COM /* Extract total tx opackets, obytes */
2556*11878SVenu.Iyer@Sun.COM total_stat_entry->tse_stats.ts_opackets =
2557*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_opackets;
2558*11878SVenu.Iyer@Sun.COM total_stat_entry->tse_stats.ts_obytes =
2559*11878SVenu.Iyer@Sun.COM tx_lane_stat_entry->tle_stats.tl_obytes;
2560*11878SVenu.Iyer@Sun.COM
2561*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
2562*11878SVenu.Iyer@Sun.COM if (head == NULL) {
2563*11878SVenu.Iyer@Sun.COM free(total_stat_entry);
2564*11878SVenu.Iyer@Sun.COM goto done;
2565*11878SVenu.Iyer@Sun.COM }
2566*11878SVenu.Iyer@Sun.COM
2567*11878SVenu.Iyer@Sun.COM head->dc_statentry = total_stat_entry;
2568*11878SVenu.Iyer@Sun.COM (void) strlcpy(head->dc_statheader, "mac_lane_total",
2569*11878SVenu.Iyer@Sun.COM sizeof (head->dc_statheader));
2570*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
2571*11878SVenu.Iyer@Sun.COM free(rx_total);
2572*11878SVenu.Iyer@Sun.COM free(tx_total);
2573*11878SVenu.Iyer@Sun.COM
2574*11878SVenu.Iyer@Sun.COM done:
2575*11878SVenu.Iyer@Sun.COM return (head);
2576*11878SVenu.Iyer@Sun.COM }
2577*11878SVenu.Iyer@Sun.COM
2578*11878SVenu.Iyer@Sun.COM /* Aggr total statistic(summed across all component ports) specific functions */
2579*11878SVenu.Iyer@Sun.COM void *
dlstat_aggr_total_stats(dladm_stat_chain_t * head)2580*11878SVenu.Iyer@Sun.COM dlstat_aggr_total_stats(dladm_stat_chain_t *head)
2581*11878SVenu.Iyer@Sun.COM {
2582*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *curr;
2583*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *total_head;
2584*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *total_stats;
2585*11878SVenu.Iyer@Sun.COM
2586*11878SVenu.Iyer@Sun.COM total_stats = calloc(1, sizeof (aggr_port_stat_entry_t));
2587*11878SVenu.Iyer@Sun.COM if (total_stats == NULL)
2588*11878SVenu.Iyer@Sun.COM goto done;
2589*11878SVenu.Iyer@Sun.COM
2590*11878SVenu.Iyer@Sun.COM total_stats->ape_portlinkid = DATALINK_INVALID_LINKID;
2591*11878SVenu.Iyer@Sun.COM
2592*11878SVenu.Iyer@Sun.COM for (curr = head; curr != NULL; curr = curr->dc_next) {
2593*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *curr_aggr_port_stats;
2594*11878SVenu.Iyer@Sun.COM
2595*11878SVenu.Iyer@Sun.COM curr_aggr_port_stats = curr->dc_statentry;
2596*11878SVenu.Iyer@Sun.COM
2597*11878SVenu.Iyer@Sun.COM i_dlstat_sum_stats(&total_stats->ape_stats,
2598*11878SVenu.Iyer@Sun.COM &curr_aggr_port_stats->ape_stats, &total_stats->ape_stats,
2599*11878SVenu.Iyer@Sun.COM aggr_port_stats_list, AGGR_PORT_STAT_SIZE);
2600*11878SVenu.Iyer@Sun.COM }
2601*11878SVenu.Iyer@Sun.COM
2602*11878SVenu.Iyer@Sun.COM total_head = malloc(sizeof (dladm_stat_chain_t));
2603*11878SVenu.Iyer@Sun.COM if (total_head == NULL) {
2604*11878SVenu.Iyer@Sun.COM free(total_stats);
2605*11878SVenu.Iyer@Sun.COM goto done;
2606*11878SVenu.Iyer@Sun.COM }
2607*11878SVenu.Iyer@Sun.COM
2608*11878SVenu.Iyer@Sun.COM total_head->dc_statentry = total_stats;
2609*11878SVenu.Iyer@Sun.COM total_head->dc_next = NULL;
2610*11878SVenu.Iyer@Sun.COM
2611*11878SVenu.Iyer@Sun.COM done:
2612*11878SVenu.Iyer@Sun.COM return (total_head);
2613*11878SVenu.Iyer@Sun.COM }
2614*11878SVenu.Iyer@Sun.COM
2615*11878SVenu.Iyer@Sun.COM /* Aggr port statistic specific functions */
2616*11878SVenu.Iyer@Sun.COM static boolean_t
i_dlstat_aggr_port_match(void * arg1,void * arg2)2617*11878SVenu.Iyer@Sun.COM i_dlstat_aggr_port_match(void *arg1, void *arg2)
2618*11878SVenu.Iyer@Sun.COM {
2619*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *s1 = arg1;
2620*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *s2 = arg2;
2621*11878SVenu.Iyer@Sun.COM
2622*11878SVenu.Iyer@Sun.COM return (s1->ape_portlinkid == s2->ape_portlinkid);
2623*11878SVenu.Iyer@Sun.COM }
2624*11878SVenu.Iyer@Sun.COM
2625*11878SVenu.Iyer@Sun.COM static void *
i_dlstat_aggr_port_stat_entry_diff(void * arg1,void * arg2)2626*11878SVenu.Iyer@Sun.COM i_dlstat_aggr_port_stat_entry_diff(void *arg1, void *arg2)
2627*11878SVenu.Iyer@Sun.COM {
2628*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *s1 = arg1;
2629*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *s2 = arg2;
2630*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *diff_entry;
2631*11878SVenu.Iyer@Sun.COM
2632*11878SVenu.Iyer@Sun.COM diff_entry = malloc(sizeof (aggr_port_stat_entry_t));
2633*11878SVenu.Iyer@Sun.COM if (diff_entry == NULL)
2634*11878SVenu.Iyer@Sun.COM goto done;
2635*11878SVenu.Iyer@Sun.COM
2636*11878SVenu.Iyer@Sun.COM diff_entry->ape_portlinkid = s1->ape_portlinkid;
2637*11878SVenu.Iyer@Sun.COM
2638*11878SVenu.Iyer@Sun.COM DLSTAT_DIFF_STAT(s1, s2, diff_entry, ape_stats, aggr_port_stats_list,
2639*11878SVenu.Iyer@Sun.COM AGGR_PORT_STAT_SIZE);
2640*11878SVenu.Iyer@Sun.COM
2641*11878SVenu.Iyer@Sun.COM done:
2642*11878SVenu.Iyer@Sun.COM return (diff_entry);
2643*11878SVenu.Iyer@Sun.COM }
2644*11878SVenu.Iyer@Sun.COM
2645*11878SVenu.Iyer@Sun.COM /*
2646*11878SVenu.Iyer@Sun.COM * Query dls stats for the aggr port. This results in query for stats into
2647*11878SVenu.Iyer@Sun.COM * the corresponding device driver.
2648*11878SVenu.Iyer@Sun.COM */
2649*11878SVenu.Iyer@Sun.COM static aggr_port_stat_entry_t *
i_dlstat_single_port_stats(const char * portname,datalink_id_t linkid)2650*11878SVenu.Iyer@Sun.COM i_dlstat_single_port_stats(const char *portname, datalink_id_t linkid)
2651*11878SVenu.Iyer@Sun.COM {
2652*11878SVenu.Iyer@Sun.COM kstat_ctl_t *kcp;
2653*11878SVenu.Iyer@Sun.COM kstat_t *ksp;
2654*11878SVenu.Iyer@Sun.COM char module[DLPI_LINKNAME_MAX];
2655*11878SVenu.Iyer@Sun.COM uint_t instance;
2656*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *aggr_port_stat_entry = NULL;
2657*11878SVenu.Iyer@Sun.COM
2658*11878SVenu.Iyer@Sun.COM if (dladm_parselink(portname, module, &instance) != DLADM_STATUS_OK)
2659*11878SVenu.Iyer@Sun.COM goto done;
2660*11878SVenu.Iyer@Sun.COM
2661*11878SVenu.Iyer@Sun.COM if ((kcp = kstat_open()) == NULL) {
2662*11878SVenu.Iyer@Sun.COM warn("kstat open operation failed");
2663*11878SVenu.Iyer@Sun.COM return (NULL);
2664*11878SVenu.Iyer@Sun.COM }
2665*11878SVenu.Iyer@Sun.COM
2666*11878SVenu.Iyer@Sun.COM ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL);
2667*11878SVenu.Iyer@Sun.COM if (ksp == NULL)
2668*11878SVenu.Iyer@Sun.COM goto done;
2669*11878SVenu.Iyer@Sun.COM
2670*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry = calloc(1, sizeof (aggr_port_stat_entry_t));
2671*11878SVenu.Iyer@Sun.COM if (aggr_port_stat_entry == NULL)
2672*11878SVenu.Iyer@Sun.COM goto done;
2673*11878SVenu.Iyer@Sun.COM
2674*11878SVenu.Iyer@Sun.COM /* Save port's linkid */
2675*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry->ape_portlinkid = linkid;
2676*11878SVenu.Iyer@Sun.COM
2677*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, &aggr_port_stat_entry->ape_stats,
2678*11878SVenu.Iyer@Sun.COM aggr_port_stats_list, AGGR_PORT_STAT_SIZE);
2679*11878SVenu.Iyer@Sun.COM done:
2680*11878SVenu.Iyer@Sun.COM (void) kstat_close(kcp);
2681*11878SVenu.Iyer@Sun.COM return (aggr_port_stat_entry);
2682*11878SVenu.Iyer@Sun.COM }
2683*11878SVenu.Iyer@Sun.COM
2684*11878SVenu.Iyer@Sun.COM void *
dlstat_aggr_port_stats(dladm_handle_t dh,datalink_id_t linkid)2685*11878SVenu.Iyer@Sun.COM dlstat_aggr_port_stats(dladm_handle_t dh, datalink_id_t linkid)
2686*11878SVenu.Iyer@Sun.COM {
2687*11878SVenu.Iyer@Sun.COM dladm_aggr_grp_attr_t ginfo;
2688*11878SVenu.Iyer@Sun.COM int i;
2689*11878SVenu.Iyer@Sun.COM dladm_aggr_port_attr_t *portp;
2690*11878SVenu.Iyer@Sun.COM dladm_phys_attr_t dpa;
2691*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry_t *aggr_port_stat_entry;
2692*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL, *prev = NULL, *curr;
2693*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *total_stats;
2694*11878SVenu.Iyer@Sun.COM
2695*11878SVenu.Iyer@Sun.COM /* Get aggr info */
2696*11878SVenu.Iyer@Sun.COM bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t));
2697*11878SVenu.Iyer@Sun.COM if (dladm_aggr_info(dh, linkid, &ginfo, DLADM_OPT_ACTIVE)
2698*11878SVenu.Iyer@Sun.COM != DLADM_STATUS_OK)
2699*11878SVenu.Iyer@Sun.COM goto done;
2700*11878SVenu.Iyer@Sun.COM /* For every port that is member of this aggr do */
2701*11878SVenu.Iyer@Sun.COM for (i = 0; i < ginfo.lg_nports; i++) {
2702*11878SVenu.Iyer@Sun.COM portp = &(ginfo.lg_ports[i]);
2703*11878SVenu.Iyer@Sun.COM if (dladm_phys_info(dh, portp->lp_linkid, &dpa,
2704*11878SVenu.Iyer@Sun.COM DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) {
2705*11878SVenu.Iyer@Sun.COM goto done;
2706*11878SVenu.Iyer@Sun.COM }
2707*11878SVenu.Iyer@Sun.COM
2708*11878SVenu.Iyer@Sun.COM aggr_port_stat_entry = i_dlstat_single_port_stats(dpa.dp_dev,
2709*11878SVenu.Iyer@Sun.COM portp->lp_linkid);
2710*11878SVenu.Iyer@Sun.COM
2711*11878SVenu.Iyer@Sun.COM /* Create dladm_stat_chain_t object for this stat */
2712*11878SVenu.Iyer@Sun.COM curr = malloc(sizeof (dladm_stat_chain_t));
2713*11878SVenu.Iyer@Sun.COM if (curr == NULL) {
2714*11878SVenu.Iyer@Sun.COM free(aggr_port_stat_entry);
2715*11878SVenu.Iyer@Sun.COM goto done;
2716*11878SVenu.Iyer@Sun.COM }
2717*11878SVenu.Iyer@Sun.COM (void) strlcpy(curr->dc_statheader, dpa.dp_dev,
2718*11878SVenu.Iyer@Sun.COM sizeof (curr->dc_statheader));
2719*11878SVenu.Iyer@Sun.COM curr->dc_statentry = aggr_port_stat_entry;
2720*11878SVenu.Iyer@Sun.COM curr->dc_next = NULL;
2721*11878SVenu.Iyer@Sun.COM
2722*11878SVenu.Iyer@Sun.COM /* Chain this aggr port stat entry */
2723*11878SVenu.Iyer@Sun.COM /* head of the stat list */
2724*11878SVenu.Iyer@Sun.COM if (prev == NULL)
2725*11878SVenu.Iyer@Sun.COM head = curr;
2726*11878SVenu.Iyer@Sun.COM else
2727*11878SVenu.Iyer@Sun.COM prev->dc_next = curr;
2728*11878SVenu.Iyer@Sun.COM prev = curr;
2729*11878SVenu.Iyer@Sun.COM }
2730*11878SVenu.Iyer@Sun.COM
2731*11878SVenu.Iyer@Sun.COM /*
2732*11878SVenu.Iyer@Sun.COM * Prepend the stat list with cumulative aggr stats i.e. summed over all
2733*11878SVenu.Iyer@Sun.COM * component ports
2734*11878SVenu.Iyer@Sun.COM */
2735*11878SVenu.Iyer@Sun.COM total_stats = dlstat_aggr_total_stats(head);
2736*11878SVenu.Iyer@Sun.COM if (total_stats != NULL) {
2737*11878SVenu.Iyer@Sun.COM total_stats->dc_next = head;
2738*11878SVenu.Iyer@Sun.COM head = total_stats;
2739*11878SVenu.Iyer@Sun.COM }
2740*11878SVenu.Iyer@Sun.COM
2741*11878SVenu.Iyer@Sun.COM done:
2742*11878SVenu.Iyer@Sun.COM free(ginfo.lg_ports);
2743*11878SVenu.Iyer@Sun.COM return (head);
2744*11878SVenu.Iyer@Sun.COM }
2745*11878SVenu.Iyer@Sun.COM
2746*11878SVenu.Iyer@Sun.COM /* Misc stat specific functions */
2747*11878SVenu.Iyer@Sun.COM void *
dlstat_misc_stats(dladm_handle_t dh,datalink_id_t linkid)2748*11878SVenu.Iyer@Sun.COM dlstat_misc_stats(dladm_handle_t dh, datalink_id_t linkid)
2749*11878SVenu.Iyer@Sun.COM {
2750*11878SVenu.Iyer@Sun.COM misc_stat_entry_t *misc_stat_entry;
2751*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *head = NULL;
2752*11878SVenu.Iyer@Sun.COM char linkname[MAXLINKNAMELEN];
2753*11878SVenu.Iyer@Sun.COM
2754*11878SVenu.Iyer@Sun.COM if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
2755*11878SVenu.Iyer@Sun.COM DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
2756*11878SVenu.Iyer@Sun.COM goto done;
2757*11878SVenu.Iyer@Sun.COM }
2758*11878SVenu.Iyer@Sun.COM
2759*11878SVenu.Iyer@Sun.COM misc_stat_entry = i_dlstat_misc_stats(linkname);
2760*11878SVenu.Iyer@Sun.COM if (misc_stat_entry == NULL)
2761*11878SVenu.Iyer@Sun.COM goto done;
2762*11878SVenu.Iyer@Sun.COM
2763*11878SVenu.Iyer@Sun.COM head = malloc(sizeof (dladm_stat_chain_t));
2764*11878SVenu.Iyer@Sun.COM if (head == NULL) {
2765*11878SVenu.Iyer@Sun.COM free(misc_stat_entry);
2766*11878SVenu.Iyer@Sun.COM goto done;
2767*11878SVenu.Iyer@Sun.COM }
2768*11878SVenu.Iyer@Sun.COM
2769*11878SVenu.Iyer@Sun.COM head->dc_statentry = misc_stat_entry;
2770*11878SVenu.Iyer@Sun.COM (void) strlcpy(head->dc_statheader, "mac_misc_stat",
2771*11878SVenu.Iyer@Sun.COM sizeof (head->dc_statheader));
2772*11878SVenu.Iyer@Sun.COM head->dc_next = NULL;
2773*11878SVenu.Iyer@Sun.COM
2774*11878SVenu.Iyer@Sun.COM done:
2775*11878SVenu.Iyer@Sun.COM return (head);
2776*11878SVenu.Iyer@Sun.COM }
2777*11878SVenu.Iyer@Sun.COM
2778*11878SVenu.Iyer@Sun.COM /* Exported functions */
2779*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *
dladm_link_stat_query(dladm_handle_t dh,datalink_id_t linkid,dladm_stat_type_t stattype)2780*11878SVenu.Iyer@Sun.COM dladm_link_stat_query(dladm_handle_t dh, datalink_id_t linkid,
2781*11878SVenu.Iyer@Sun.COM dladm_stat_type_t stattype)
2782*11878SVenu.Iyer@Sun.COM {
2783*11878SVenu.Iyer@Sun.COM return (dladm_stat_table[stattype].ds_querystat(dh, linkid));
2784*11878SVenu.Iyer@Sun.COM }
2785*11878SVenu.Iyer@Sun.COM
2786*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *
dladm_link_stat_diffchain(dladm_stat_chain_t * op1,dladm_stat_chain_t * op2,dladm_stat_type_t stattype)2787*11878SVenu.Iyer@Sun.COM dladm_link_stat_diffchain(dladm_stat_chain_t *op1, dladm_stat_chain_t *op2,
2788*11878SVenu.Iyer@Sun.COM dladm_stat_type_t stattype)
2789*11878SVenu.Iyer@Sun.COM {
2790*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *op1_curr, *op2_curr;
2791*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *diff_curr;
2792*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *diff_prev = NULL, *diff_head = NULL;
2793*11878SVenu.Iyer@Sun.COM
2794*11878SVenu.Iyer@Sun.COM /* Perform op1 - op2, store result in diff */
2795*11878SVenu.Iyer@Sun.COM for (op1_curr = op1; op1_curr != NULL; op1_curr = op1_curr->dc_next) {
2796*11878SVenu.Iyer@Sun.COM for (op2_curr = op2; op2_curr != NULL;
2797*11878SVenu.Iyer@Sun.COM op2_curr = op2_curr->dc_next) {
2798*11878SVenu.Iyer@Sun.COM if (dlstat_match_stats(op1_curr->dc_statentry,
2799*11878SVenu.Iyer@Sun.COM op2_curr->dc_statentry, stattype)) {
2800*11878SVenu.Iyer@Sun.COM break;
2801*11878SVenu.Iyer@Sun.COM }
2802*11878SVenu.Iyer@Sun.COM }
2803*11878SVenu.Iyer@Sun.COM diff_curr = malloc(sizeof (dladm_stat_chain_t));
2804*11878SVenu.Iyer@Sun.COM if (diff_curr == NULL)
2805*11878SVenu.Iyer@Sun.COM goto done;
2806*11878SVenu.Iyer@Sun.COM
2807*11878SVenu.Iyer@Sun.COM diff_curr->dc_next = NULL;
2808*11878SVenu.Iyer@Sun.COM
2809*11878SVenu.Iyer@Sun.COM if (op2_curr == NULL) {
2810*11878SVenu.Iyer@Sun.COM /* prev iteration did not have this stat entry */
2811*11878SVenu.Iyer@Sun.COM diff_curr->dc_statentry =
2812*11878SVenu.Iyer@Sun.COM dlstat_diff_stats(op1_curr->dc_statentry,
2813*11878SVenu.Iyer@Sun.COM NULL, stattype);
2814*11878SVenu.Iyer@Sun.COM } else {
2815*11878SVenu.Iyer@Sun.COM diff_curr->dc_statentry =
2816*11878SVenu.Iyer@Sun.COM dlstat_diff_stats(op1_curr->dc_statentry,
2817*11878SVenu.Iyer@Sun.COM op2_curr->dc_statentry, stattype);
2818*11878SVenu.Iyer@Sun.COM }
2819*11878SVenu.Iyer@Sun.COM
2820*11878SVenu.Iyer@Sun.COM if (diff_curr->dc_statentry == NULL) {
2821*11878SVenu.Iyer@Sun.COM free(diff_curr);
2822*11878SVenu.Iyer@Sun.COM goto done;
2823*11878SVenu.Iyer@Sun.COM }
2824*11878SVenu.Iyer@Sun.COM
2825*11878SVenu.Iyer@Sun.COM if (diff_prev == NULL) /* head of the diff stat list */
2826*11878SVenu.Iyer@Sun.COM diff_head = diff_curr;
2827*11878SVenu.Iyer@Sun.COM else
2828*11878SVenu.Iyer@Sun.COM diff_prev->dc_next = diff_curr;
2829*11878SVenu.Iyer@Sun.COM diff_prev = diff_curr;
2830*11878SVenu.Iyer@Sun.COM }
2831*11878SVenu.Iyer@Sun.COM done:
2832*11878SVenu.Iyer@Sun.COM return (diff_head);
2833*11878SVenu.Iyer@Sun.COM }
2834*11878SVenu.Iyer@Sun.COM
2835*11878SVenu.Iyer@Sun.COM void
dladm_link_stat_free(dladm_stat_chain_t * curr)2836*11878SVenu.Iyer@Sun.COM dladm_link_stat_free(dladm_stat_chain_t *curr)
2837*11878SVenu.Iyer@Sun.COM {
2838*11878SVenu.Iyer@Sun.COM while (curr != NULL) {
2839*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *tofree = curr;
2840*11878SVenu.Iyer@Sun.COM
2841*11878SVenu.Iyer@Sun.COM curr = curr->dc_next;
2842*11878SVenu.Iyer@Sun.COM free(tofree->dc_statentry);
2843*11878SVenu.Iyer@Sun.COM free(tofree);
2844*11878SVenu.Iyer@Sun.COM }
2845*11878SVenu.Iyer@Sun.COM }
2846*11878SVenu.Iyer@Sun.COM
2847*11878SVenu.Iyer@Sun.COM /* Query all link stats */
2848*11878SVenu.Iyer@Sun.COM static name_value_stat_t *
i_dlstat_convert_stats(void * stats,stat_info_t stats_list[],uint_t size)2849*11878SVenu.Iyer@Sun.COM i_dlstat_convert_stats(void *stats, stat_info_t stats_list[], uint_t size)
2850*11878SVenu.Iyer@Sun.COM {
2851*11878SVenu.Iyer@Sun.COM int i;
2852*11878SVenu.Iyer@Sun.COM name_value_stat_t *head_stat = NULL, *prev_stat = NULL;
2853*11878SVenu.Iyer@Sun.COM name_value_stat_t *curr_stat;
2854*11878SVenu.Iyer@Sun.COM
2855*11878SVenu.Iyer@Sun.COM for (i = 0; i < size; i++) {
2856*11878SVenu.Iyer@Sun.COM uint64_t *val = (void *)
2857*11878SVenu.Iyer@Sun.COM ((uchar_t *)stats + stats_list[i].si_offset);
2858*11878SVenu.Iyer@Sun.COM
2859*11878SVenu.Iyer@Sun.COM curr_stat = calloc(1, sizeof (name_value_stat_t));
2860*11878SVenu.Iyer@Sun.COM if (curr_stat == NULL)
2861*11878SVenu.Iyer@Sun.COM break;
2862*11878SVenu.Iyer@Sun.COM
2863*11878SVenu.Iyer@Sun.COM (void) strlcpy(curr_stat->nv_statname, stats_list[i].si_name,
2864*11878SVenu.Iyer@Sun.COM sizeof (curr_stat->nv_statname));
2865*11878SVenu.Iyer@Sun.COM curr_stat->nv_statval = *val;
2866*11878SVenu.Iyer@Sun.COM curr_stat->nv_nextstat = NULL;
2867*11878SVenu.Iyer@Sun.COM
2868*11878SVenu.Iyer@Sun.COM if (head_stat == NULL) /* First node */
2869*11878SVenu.Iyer@Sun.COM head_stat = curr_stat;
2870*11878SVenu.Iyer@Sun.COM else
2871*11878SVenu.Iyer@Sun.COM prev_stat->nv_nextstat = curr_stat;
2872*11878SVenu.Iyer@Sun.COM
2873*11878SVenu.Iyer@Sun.COM prev_stat = curr_stat;
2874*11878SVenu.Iyer@Sun.COM }
2875*11878SVenu.Iyer@Sun.COM return (head_stat);
2876*11878SVenu.Iyer@Sun.COM }
2877*11878SVenu.Iyer@Sun.COM
2878*11878SVenu.Iyer@Sun.COM void *
build_nvs_entry(char * statheader,void * statentry,dladm_stat_type_t stattype)2879*11878SVenu.Iyer@Sun.COM build_nvs_entry(char *statheader, void *statentry, dladm_stat_type_t stattype)
2880*11878SVenu.Iyer@Sun.COM {
2881*11878SVenu.Iyer@Sun.COM name_value_stat_entry_t *name_value_stat_entry;
2882*11878SVenu.Iyer@Sun.COM dladm_stat_desc_t *stattbl_ptr;
2883*11878SVenu.Iyer@Sun.COM void *statfields;
2884*11878SVenu.Iyer@Sun.COM
2885*11878SVenu.Iyer@Sun.COM stattbl_ptr = &dladm_stat_table[stattype];
2886*11878SVenu.Iyer@Sun.COM
2887*11878SVenu.Iyer@Sun.COM /* Allocate memory for query all stat entry */
2888*11878SVenu.Iyer@Sun.COM name_value_stat_entry = calloc(1, sizeof (name_value_stat_entry_t));
2889*11878SVenu.Iyer@Sun.COM if (name_value_stat_entry == NULL)
2890*11878SVenu.Iyer@Sun.COM goto done;
2891*11878SVenu.Iyer@Sun.COM
2892*11878SVenu.Iyer@Sun.COM /* Header for these stat fields */
2893*11878SVenu.Iyer@Sun.COM (void) strlcpy(name_value_stat_entry->nve_header, statheader,
2894*11878SVenu.Iyer@Sun.COM sizeof (name_value_stat_entry->nve_header));
2895*11878SVenu.Iyer@Sun.COM
2896*11878SVenu.Iyer@Sun.COM /* Extract stat fields from the statentry */
2897*11878SVenu.Iyer@Sun.COM statfields = (uchar_t *)statentry +
2898*11878SVenu.Iyer@Sun.COM dladm_stat_table[stattype].ds_offset;
2899*11878SVenu.Iyer@Sun.COM
2900*11878SVenu.Iyer@Sun.COM /* Convert curr_stat to <statname, statval> pair */
2901*11878SVenu.Iyer@Sun.COM name_value_stat_entry->nve_stats =
2902*11878SVenu.Iyer@Sun.COM i_dlstat_convert_stats(statfields,
2903*11878SVenu.Iyer@Sun.COM stattbl_ptr->ds_statlist, stattbl_ptr->ds_statsize);
2904*11878SVenu.Iyer@Sun.COM done:
2905*11878SVenu.Iyer@Sun.COM return (name_value_stat_entry);
2906*11878SVenu.Iyer@Sun.COM }
2907*11878SVenu.Iyer@Sun.COM
2908*11878SVenu.Iyer@Sun.COM void *
i_walk_dlstat_chain(dladm_stat_chain_t * stat_head,dladm_stat_type_t stattype)2909*11878SVenu.Iyer@Sun.COM i_walk_dlstat_chain(dladm_stat_chain_t *stat_head, dladm_stat_type_t stattype)
2910*11878SVenu.Iyer@Sun.COM {
2911*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *curr;
2912*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *nvstat_head = NULL, *nvstat_prev = NULL;
2913*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *nvstat_curr;
2914*11878SVenu.Iyer@Sun.COM
2915*11878SVenu.Iyer@Sun.COM /*
2916*11878SVenu.Iyer@Sun.COM * For every stat in the chain, build header and convert all
2917*11878SVenu.Iyer@Sun.COM * its stat fields
2918*11878SVenu.Iyer@Sun.COM */
2919*11878SVenu.Iyer@Sun.COM for (curr = stat_head; curr != NULL; curr = curr->dc_next) {
2920*11878SVenu.Iyer@Sun.COM nvstat_curr = malloc(sizeof (dladm_stat_chain_t));
2921*11878SVenu.Iyer@Sun.COM if (nvstat_curr == NULL)
2922*11878SVenu.Iyer@Sun.COM break;
2923*11878SVenu.Iyer@Sun.COM
2924*11878SVenu.Iyer@Sun.COM nvstat_curr->dc_statentry = build_nvs_entry(curr->dc_statheader,
2925*11878SVenu.Iyer@Sun.COM curr->dc_statentry, stattype);
2926*11878SVenu.Iyer@Sun.COM
2927*11878SVenu.Iyer@Sun.COM if (nvstat_curr->dc_statentry == NULL) {
2928*11878SVenu.Iyer@Sun.COM free(nvstat_curr);
2929*11878SVenu.Iyer@Sun.COM break;
2930*11878SVenu.Iyer@Sun.COM }
2931*11878SVenu.Iyer@Sun.COM
2932*11878SVenu.Iyer@Sun.COM nvstat_curr->dc_next = NULL;
2933*11878SVenu.Iyer@Sun.COM
2934*11878SVenu.Iyer@Sun.COM if (nvstat_head == NULL) /* First node */
2935*11878SVenu.Iyer@Sun.COM nvstat_head = nvstat_curr;
2936*11878SVenu.Iyer@Sun.COM else
2937*11878SVenu.Iyer@Sun.COM nvstat_prev->dc_next = nvstat_curr;
2938*11878SVenu.Iyer@Sun.COM
2939*11878SVenu.Iyer@Sun.COM nvstat_prev = nvstat_curr;
2940*11878SVenu.Iyer@Sun.COM }
2941*11878SVenu.Iyer@Sun.COM done:
2942*11878SVenu.Iyer@Sun.COM return (nvstat_head);
2943*11878SVenu.Iyer@Sun.COM }
2944*11878SVenu.Iyer@Sun.COM
2945*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *
dladm_link_stat_query_all(dladm_handle_t dh,datalink_id_t linkid,dladm_stat_type_t stattype)2946*11878SVenu.Iyer@Sun.COM dladm_link_stat_query_all(dladm_handle_t dh, datalink_id_t linkid,
2947*11878SVenu.Iyer@Sun.COM dladm_stat_type_t stattype)
2948*11878SVenu.Iyer@Sun.COM {
2949*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *stat_head;
2950*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *nvstat_head = NULL;
2951*11878SVenu.Iyer@Sun.COM
2952*11878SVenu.Iyer@Sun.COM /* Query the requested stat */
2953*11878SVenu.Iyer@Sun.COM stat_head = dladm_link_stat_query(dh, linkid, stattype);
2954*11878SVenu.Iyer@Sun.COM if (stat_head == NULL)
2955*11878SVenu.Iyer@Sun.COM goto done;
2956*11878SVenu.Iyer@Sun.COM
2957*11878SVenu.Iyer@Sun.COM /*
2958*11878SVenu.Iyer@Sun.COM * Convert every statfield in every stat-entry of stat chain to
2959*11878SVenu.Iyer@Sun.COM * <statname, statval> pair
2960*11878SVenu.Iyer@Sun.COM */
2961*11878SVenu.Iyer@Sun.COM nvstat_head = i_walk_dlstat_chain(stat_head, stattype);
2962*11878SVenu.Iyer@Sun.COM
2963*11878SVenu.Iyer@Sun.COM /* Free stat_head */
2964*11878SVenu.Iyer@Sun.COM dladm_link_stat_free(stat_head);
2965*11878SVenu.Iyer@Sun.COM
2966*11878SVenu.Iyer@Sun.COM done:
2967*11878SVenu.Iyer@Sun.COM return (nvstat_head);
2968*11878SVenu.Iyer@Sun.COM }
2969*11878SVenu.Iyer@Sun.COM
2970*11878SVenu.Iyer@Sun.COM void
dladm_link_stat_query_all_free(dladm_stat_chain_t * curr)2971*11878SVenu.Iyer@Sun.COM dladm_link_stat_query_all_free(dladm_stat_chain_t *curr)
2972*11878SVenu.Iyer@Sun.COM {
2973*11878SVenu.Iyer@Sun.COM while (curr != NULL) {
2974*11878SVenu.Iyer@Sun.COM dladm_stat_chain_t *tofree = curr;
2975*11878SVenu.Iyer@Sun.COM name_value_stat_entry_t *nv_entry = curr->dc_statentry;
2976*11878SVenu.Iyer@Sun.COM name_value_stat_t *nv_curr = nv_entry->nve_stats;
2977*11878SVenu.Iyer@Sun.COM
2978*11878SVenu.Iyer@Sun.COM while (nv_curr != NULL) {
2979*11878SVenu.Iyer@Sun.COM name_value_stat_t *nv_tofree = nv_curr;
2980*11878SVenu.Iyer@Sun.COM
2981*11878SVenu.Iyer@Sun.COM nv_curr = nv_curr->nv_nextstat;
2982*11878SVenu.Iyer@Sun.COM free(nv_tofree);
2983*11878SVenu.Iyer@Sun.COM }
2984*11878SVenu.Iyer@Sun.COM
2985*11878SVenu.Iyer@Sun.COM curr = curr->dc_next;
2986*11878SVenu.Iyer@Sun.COM free(nv_entry);
2987*11878SVenu.Iyer@Sun.COM free(tofree);
2988*11878SVenu.Iyer@Sun.COM }
2989*11878SVenu.Iyer@Sun.COM }
2990*11878SVenu.Iyer@Sun.COM
2991*11878SVenu.Iyer@Sun.COM /* flow stats specific routines */
2992*11878SVenu.Iyer@Sun.COM flow_stat_t *
dladm_flow_stat_query(const char * flowname)2993*11878SVenu.Iyer@Sun.COM dladm_flow_stat_query(const char *flowname)
2994*11878SVenu.Iyer@Sun.COM {
2995*11878SVenu.Iyer@Sun.COM kstat_ctl_t *kcp;
2996*11878SVenu.Iyer@Sun.COM kstat_t *ksp;
2997*11878SVenu.Iyer@Sun.COM flow_stat_t *flow_stat = NULL;
2998*11878SVenu.Iyer@Sun.COM
2999*11878SVenu.Iyer@Sun.COM if ((kcp = kstat_open()) == NULL)
3000*11878SVenu.Iyer@Sun.COM return (NULL);
3001*11878SVenu.Iyer@Sun.COM
3002*11878SVenu.Iyer@Sun.COM flow_stat = calloc(1, sizeof (flow_stat_t));
3003*11878SVenu.Iyer@Sun.COM if (flow_stat == NULL)
3004*11878SVenu.Iyer@Sun.COM goto done;
3005*11878SVenu.Iyer@Sun.COM
3006*11878SVenu.Iyer@Sun.COM ksp = dladm_kstat_lookup(kcp, NULL, -1, flowname, "flow");
3007*11878SVenu.Iyer@Sun.COM
3008*11878SVenu.Iyer@Sun.COM if (ksp != NULL) {
3009*11878SVenu.Iyer@Sun.COM i_dlstat_get_stats(kcp, ksp, flow_stat, flow_stats_list,
3010*11878SVenu.Iyer@Sun.COM FLOW_STAT_SIZE);
3011*11878SVenu.Iyer@Sun.COM }
3012*11878SVenu.Iyer@Sun.COM
3013*11878SVenu.Iyer@Sun.COM done:
3014*11878SVenu.Iyer@Sun.COM (void) kstat_close(kcp);
3015*11878SVenu.Iyer@Sun.COM return (flow_stat);
3016*11878SVenu.Iyer@Sun.COM }
3017*11878SVenu.Iyer@Sun.COM
3018*11878SVenu.Iyer@Sun.COM flow_stat_t *
dladm_flow_stat_diff(flow_stat_t * op1,flow_stat_t * op2)3019*11878SVenu.Iyer@Sun.COM dladm_flow_stat_diff(flow_stat_t *op1, flow_stat_t *op2)
3020*11878SVenu.Iyer@Sun.COM {
3021*11878SVenu.Iyer@Sun.COM flow_stat_t *diff_stat;
3022*11878SVenu.Iyer@Sun.COM
3023*11878SVenu.Iyer@Sun.COM diff_stat = calloc(1, sizeof (flow_stat_t));
3024*11878SVenu.Iyer@Sun.COM if (diff_stat == NULL)
3025*11878SVenu.Iyer@Sun.COM goto done;
3026*11878SVenu.Iyer@Sun.COM
3027*11878SVenu.Iyer@Sun.COM if (op2 == NULL) {
3028*11878SVenu.Iyer@Sun.COM bcopy(op1, diff_stat, sizeof (flow_stat_t));
3029*11878SVenu.Iyer@Sun.COM } else {
3030*11878SVenu.Iyer@Sun.COM i_dlstat_diff_stats(diff_stat, op1, op2, flow_stats_list,
3031*11878SVenu.Iyer@Sun.COM FLOW_STAT_SIZE);
3032*11878SVenu.Iyer@Sun.COM }
3033*11878SVenu.Iyer@Sun.COM done:
3034*11878SVenu.Iyer@Sun.COM return (diff_stat);
3035*11878SVenu.Iyer@Sun.COM }
3036*11878SVenu.Iyer@Sun.COM
3037*11878SVenu.Iyer@Sun.COM void
dladm_flow_stat_free(flow_stat_t * curr)3038*11878SVenu.Iyer@Sun.COM dladm_flow_stat_free(flow_stat_t *curr)
3039*11878SVenu.Iyer@Sun.COM {
3040*11878SVenu.Iyer@Sun.COM free(curr);
3041*11878SVenu.Iyer@Sun.COM }
3042*11878SVenu.Iyer@Sun.COM
3043*11878SVenu.Iyer@Sun.COM /* Query all flow stats */
3044*11878SVenu.Iyer@Sun.COM name_value_stat_entry_t *
dladm_flow_stat_query_all(const char * flowname)3045*11878SVenu.Iyer@Sun.COM dladm_flow_stat_query_all(const char *flowname)
3046*11878SVenu.Iyer@Sun.COM {
3047*11878SVenu.Iyer@Sun.COM flow_stat_t *flow_stat;
3048*11878SVenu.Iyer@Sun.COM name_value_stat_entry_t *name_value_stat_entry = NULL;
3049*11878SVenu.Iyer@Sun.COM
3050*11878SVenu.Iyer@Sun.COM /* Query flow stats */
3051*11878SVenu.Iyer@Sun.COM flow_stat = dladm_flow_stat_query(flowname);
3052*11878SVenu.Iyer@Sun.COM if (flow_stat == NULL)
3053*11878SVenu.Iyer@Sun.COM goto done;
3054*11878SVenu.Iyer@Sun.COM
3055*11878SVenu.Iyer@Sun.COM /* Allocate memory for query all stat entry */
3056*11878SVenu.Iyer@Sun.COM name_value_stat_entry = calloc(1, sizeof (name_value_stat_entry_t));
3057*11878SVenu.Iyer@Sun.COM if (name_value_stat_entry == NULL) {
3058*11878SVenu.Iyer@Sun.COM dladm_flow_stat_free(flow_stat);
3059*11878SVenu.Iyer@Sun.COM goto done;
3060*11878SVenu.Iyer@Sun.COM }
3061*11878SVenu.Iyer@Sun.COM
3062*11878SVenu.Iyer@Sun.COM /* Header for these stat fields */
3063*11878SVenu.Iyer@Sun.COM (void) strncpy(name_value_stat_entry->nve_header, flowname,
3064*11878SVenu.Iyer@Sun.COM MAXFLOWNAMELEN);
3065*11878SVenu.Iyer@Sun.COM
3066*11878SVenu.Iyer@Sun.COM /* Convert every statfield in flow_stat to <statname, statval> pair */
3067*11878SVenu.Iyer@Sun.COM name_value_stat_entry->nve_stats =
3068*11878SVenu.Iyer@Sun.COM i_dlstat_convert_stats(flow_stat, flow_stats_list, FLOW_STAT_SIZE);
3069*11878SVenu.Iyer@Sun.COM
3070*11878SVenu.Iyer@Sun.COM /* Free flow_stat */
3071*11878SVenu.Iyer@Sun.COM dladm_flow_stat_free(flow_stat);
3072*11878SVenu.Iyer@Sun.COM
3073*11878SVenu.Iyer@Sun.COM done:
3074*11878SVenu.Iyer@Sun.COM return (name_value_stat_entry);
3075*11878SVenu.Iyer@Sun.COM }
3076*11878SVenu.Iyer@Sun.COM
3077*11878SVenu.Iyer@Sun.COM void
dladm_flow_stat_query_all_free(name_value_stat_entry_t * curr)3078*11878SVenu.Iyer@Sun.COM dladm_flow_stat_query_all_free(name_value_stat_entry_t *curr)
3079*11878SVenu.Iyer@Sun.COM {
3080*11878SVenu.Iyer@Sun.COM name_value_stat_t *nv_curr = curr->nve_stats;
3081*11878SVenu.Iyer@Sun.COM
3082*11878SVenu.Iyer@Sun.COM while (nv_curr != NULL) {
3083*11878SVenu.Iyer@Sun.COM name_value_stat_t *nv_tofree = nv_curr;
3084*11878SVenu.Iyer@Sun.COM
3085*11878SVenu.Iyer@Sun.COM nv_curr = nv_curr->nv_nextstat;
3086*11878SVenu.Iyer@Sun.COM free(nv_tofree);
3087*11878SVenu.Iyer@Sun.COM }
3088*11878SVenu.Iyer@Sun.COM }
3089