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