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 /*
220dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23da14cebeSEric Cheng * Use is subject to license terms.
24da14cebeSEric Cheng */
25da14cebeSEric Cheng
26*62ef8476SYuri Pankov #include <stddef.h>
27da14cebeSEric Cheng #include <stdio.h>
28da14cebeSEric Cheng #include <stdlib.h>
29da14cebeSEric Cheng #include <strings.h>
30da14cebeSEric Cheng #include <err.h>
31da14cebeSEric Cheng #include <errno.h>
32c3affd82SMichael Lim #include <fcntl.h>
33da14cebeSEric Cheng #include <kstat.h>
34c3affd82SMichael Lim #include <limits.h>
35da14cebeSEric Cheng #include <unistd.h>
36da14cebeSEric Cheng #include <signal.h>
37da14cebeSEric Cheng #include <sys/dld.h>
3882a2fc47SJames Carlson #include <sys/ddi.h>
39da14cebeSEric Cheng
40da14cebeSEric Cheng #include <libdllink.h>
41da14cebeSEric Cheng #include <libdlflow.h>
42da14cebeSEric Cheng #include <libdlstat.h>
430dc2366fSVenugopal Iyer #include <libdlaggr.h>
44da14cebeSEric Cheng
45da14cebeSEric Cheng struct flowlist {
46da000602SGirish Moodalbail char flowname[MAXFLOWNAMELEN];
47c3affd82SMichael Lim char linkname[MAXLINKNAMELEN];
48da14cebeSEric Cheng datalink_id_t linkid;
49c3affd82SMichael Lim int fd;
50285e94f9SMichael Lim uint64_t ifspeed;
51da14cebeSEric Cheng boolean_t first;
52da14cebeSEric Cheng boolean_t display;
53da14cebeSEric Cheng pktsum_t prevstats;
54da14cebeSEric Cheng pktsum_t diffstats;
55da14cebeSEric Cheng };
56da14cebeSEric Cheng
57da14cebeSEric Cheng pktsum_t totalstats;
58da14cebeSEric Cheng struct flowlist *stattable = NULL;
59da14cebeSEric Cheng
60da14cebeSEric Cheng #define STATGROWSIZE 16
61da14cebeSEric Cheng
62da14cebeSEric Cheng /* Exported functions */
63da14cebeSEric Cheng
64da14cebeSEric Cheng /*
65da14cebeSEric Cheng * dladm_kstat_lookup() is a modified version of kstat_lookup which
66da14cebeSEric Cheng * adds the class as a selector.
67da14cebeSEric Cheng */
68da14cebeSEric Cheng kstat_t *
dladm_kstat_lookup(kstat_ctl_t * kcp,const char * module,int instance,const char * name,const char * class)69da14cebeSEric Cheng dladm_kstat_lookup(kstat_ctl_t *kcp, const char *module, int instance,
70da14cebeSEric Cheng const char *name, const char *class)
71da14cebeSEric Cheng {
72da14cebeSEric Cheng kstat_t *ksp = NULL;
73da14cebeSEric Cheng
74da14cebeSEric Cheng for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
75da14cebeSEric Cheng if ((module == NULL || strcmp(ksp->ks_module, module) == 0) &&
76da14cebeSEric Cheng (instance == -1 || ksp->ks_instance == instance) &&
77da14cebeSEric Cheng (name == NULL || strcmp(ksp->ks_name, name) == 0) &&
78da14cebeSEric Cheng (class == NULL || strcmp(ksp->ks_class, class) == 0))
79da14cebeSEric Cheng return (ksp);
80da14cebeSEric Cheng }
81da14cebeSEric Cheng
82da14cebeSEric Cheng errno = ENOENT;
83da14cebeSEric Cheng return (NULL);
84da14cebeSEric Cheng }
85da14cebeSEric Cheng
86da14cebeSEric Cheng /*
87da14cebeSEric Cheng * dladm_get_stats() populates the supplied pktsum_t structure with
88da14cebeSEric Cheng * the input and output packet and byte kstats from the kstat_t
89da14cebeSEric Cheng * found with dladm_kstat_lookup.
90da14cebeSEric Cheng */
91da14cebeSEric Cheng void
dladm_get_stats(kstat_ctl_t * kcp,kstat_t * ksp,pktsum_t * stats)92da14cebeSEric Cheng dladm_get_stats(kstat_ctl_t *kcp, kstat_t *ksp, pktsum_t *stats)
93da14cebeSEric Cheng {
94da14cebeSEric Cheng
95da14cebeSEric Cheng if (kstat_read(kcp, ksp, NULL) == -1)
96da14cebeSEric Cheng return;
97da14cebeSEric Cheng
98da14cebeSEric Cheng stats->snaptime = gethrtime();
99da14cebeSEric Cheng
100da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64,
101da14cebeSEric Cheng &stats->ipackets) < 0) {
102da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ipackets", KSTAT_DATA_UINT64,
103da14cebeSEric Cheng &stats->ipackets) < 0)
104da14cebeSEric Cheng return;
105da14cebeSEric Cheng }
106da14cebeSEric Cheng
107da14cebeSEric Cheng if (dladm_kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64,
108da14cebeSEric Cheng &stats->opackets) < 0) {
109da14cebeSEric Cheng if (dladm_kstat_value(ksp, "opackets", KSTAT_DATA_UINT64,
110da14cebeSEric Cheng &stats->opackets) < 0)
111da14cebeSEric Cheng return;
112da14cebeSEric Cheng }
113da14cebeSEric Cheng
114da14cebeSEric Cheng if (dladm_kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64,
115da14cebeSEric Cheng &stats->rbytes) < 0) {
116da14cebeSEric Cheng if (dladm_kstat_value(ksp, "rbytes", KSTAT_DATA_UINT64,
117da14cebeSEric Cheng &stats->rbytes) < 0)
118da14cebeSEric Cheng return;
119da14cebeSEric Cheng }
120da14cebeSEric Cheng
121da14cebeSEric Cheng if (dladm_kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64,
122da14cebeSEric Cheng &stats->obytes) < 0) {
123da14cebeSEric Cheng if (dladm_kstat_value(ksp, "obytes", KSTAT_DATA_UINT64,
124da14cebeSEric Cheng &stats->obytes) < 0)
125da14cebeSEric Cheng return;
126da14cebeSEric Cheng }
127da14cebeSEric Cheng
128da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32,
129da14cebeSEric Cheng &stats->ierrors) < 0) {
130da14cebeSEric Cheng if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT64,
131da14cebeSEric Cheng &stats->ierrors) < 0)
132da14cebeSEric Cheng return;
133da14cebeSEric Cheng }
134da14cebeSEric Cheng
135da14cebeSEric Cheng if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32,
136da14cebeSEric Cheng &stats->oerrors) < 0) {
137da14cebeSEric Cheng if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT64,
138da14cebeSEric Cheng &stats->oerrors) < 0)
139da14cebeSEric Cheng return;
140da14cebeSEric Cheng }
141da14cebeSEric Cheng }
142da14cebeSEric Cheng
143da14cebeSEric Cheng int
dladm_kstat_value(kstat_t * ksp,const char * name,uint8_t type,void * buf)144da14cebeSEric Cheng dladm_kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf)
145da14cebeSEric Cheng {
146da14cebeSEric Cheng kstat_named_t *knp;
147da14cebeSEric Cheng
148da14cebeSEric Cheng if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL)
149da14cebeSEric Cheng return (-1);
150da14cebeSEric Cheng
151da14cebeSEric Cheng if (knp->data_type != type)
152da14cebeSEric Cheng return (-1);
153da14cebeSEric Cheng
154da14cebeSEric Cheng switch (type) {
155da14cebeSEric Cheng case KSTAT_DATA_UINT64:
156da14cebeSEric Cheng *(uint64_t *)buf = knp->value.ui64;
157da14cebeSEric Cheng break;
158da14cebeSEric Cheng case KSTAT_DATA_UINT32:
159da14cebeSEric Cheng *(uint32_t *)buf = knp->value.ui32;
160da14cebeSEric Cheng break;
161da14cebeSEric Cheng default:
162da14cebeSEric Cheng return (-1);
163da14cebeSEric Cheng }
164da14cebeSEric Cheng
165da14cebeSEric Cheng return (0);
166da14cebeSEric Cheng }
167da14cebeSEric Cheng
168da14cebeSEric 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)1694ac67f02SAnurag S. Maskey dladm_get_single_mac_stat(dladm_handle_t handle, datalink_id_t linkid,
1704ac67f02SAnurag S. Maskey const char *name, uint8_t type, void *val)
171da14cebeSEric Cheng {
172da14cebeSEric Cheng kstat_ctl_t *kcp;
173da14cebeSEric Cheng char module[DLPI_LINKNAME_MAX];
174da14cebeSEric Cheng uint_t instance;
175da14cebeSEric Cheng char link[DLPI_LINKNAME_MAX];
176da14cebeSEric Cheng dladm_status_t status;
177da14cebeSEric Cheng uint32_t flags, media;
178da14cebeSEric Cheng kstat_t *ksp;
179da14cebeSEric Cheng dladm_phys_attr_t dpap;
180da14cebeSEric Cheng
1814ac67f02SAnurag S. Maskey if ((status = dladm_datalink_id2info(handle, linkid, &flags, NULL,
1824ac67f02SAnurag S. Maskey &media, link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK)
183da14cebeSEric Cheng return (status);
184da14cebeSEric Cheng
185da14cebeSEric Cheng if (media != DL_ETHER)
186da14cebeSEric Cheng return (DLADM_STATUS_LINKINVAL);
187da14cebeSEric Cheng
1884ac67f02SAnurag S. Maskey status = dladm_phys_info(handle, linkid, &dpap, DLADM_OPT_PERSIST);
189da14cebeSEric Cheng
190da14cebeSEric Cheng if (status != DLADM_STATUS_OK)
191da14cebeSEric Cheng return (status);
192da14cebeSEric Cheng
193da14cebeSEric Cheng status = dladm_parselink(dpap.dp_dev, module, &instance);
194da14cebeSEric Cheng
195da14cebeSEric Cheng if (status != DLADM_STATUS_OK)
196da14cebeSEric Cheng return (status);
197da14cebeSEric Cheng
1983efde6d0SSowmini Varadhan if ((kcp = kstat_open()) == NULL) {
1993efde6d0SSowmini Varadhan warn("kstat_open operation failed");
2003efde6d0SSowmini Varadhan return (-1);
2013efde6d0SSowmini Varadhan }
2023efde6d0SSowmini Varadhan
203da14cebeSEric Cheng /*
204da14cebeSEric Cheng * The kstat query could fail if the underlying MAC
205da14cebeSEric Cheng * driver was already detached.
206da14cebeSEric Cheng */
207da14cebeSEric Cheng if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL &&
208da14cebeSEric Cheng (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL)
209da14cebeSEric Cheng goto bail;
210da14cebeSEric Cheng
211da14cebeSEric Cheng if (kstat_read(kcp, ksp, NULL) == -1)
212da14cebeSEric Cheng goto bail;
213da14cebeSEric Cheng
214da14cebeSEric Cheng if (dladm_kstat_value(ksp, name, type, val) < 0)
215da14cebeSEric Cheng goto bail;
216da14cebeSEric Cheng
217da14cebeSEric Cheng (void) kstat_close(kcp);
218da14cebeSEric Cheng return (DLADM_STATUS_OK);
219da14cebeSEric Cheng
220da14cebeSEric Cheng bail:
221da14cebeSEric Cheng (void) kstat_close(kcp);
222da14cebeSEric Cheng return (dladm_errno2status(errno));
223da14cebeSEric Cheng }
224da14cebeSEric Cheng
225da14cebeSEric Cheng /* Compute sum of 2 pktsums (s1 = s2 + s3) */
226da14cebeSEric Cheng void
dladm_stats_total(pktsum_t * s1,pktsum_t * s2,pktsum_t * s3)227da14cebeSEric Cheng dladm_stats_total(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3)
228da14cebeSEric Cheng {
229da14cebeSEric Cheng s1->rbytes = s2->rbytes + s3->rbytes;
230da14cebeSEric Cheng s1->ipackets = s2->ipackets + s3->ipackets;
231da14cebeSEric Cheng s1->ierrors = s2->ierrors + s3->ierrors;
232da14cebeSEric Cheng s1->obytes = s2->obytes + s3->obytes;
233da14cebeSEric Cheng s1->opackets = s2->opackets + s3->opackets;
234da14cebeSEric Cheng s1->oerrors = s2->oerrors + s3->oerrors;
235da14cebeSEric Cheng s1->snaptime = s2->snaptime;
236da14cebeSEric Cheng }
237da14cebeSEric Cheng
2380dc2366fSVenugopal Iyer #define DIFF_STAT(s2, s3) ((s2) > (s3) ? ((s2) - (s3)) : 0)
2392d40c3b2SPrakash Jalan
2402d40c3b2SPrakash Jalan
241da14cebeSEric Cheng /* Compute differences between 2 pktsums (s1 = s2 - s3) */
242da14cebeSEric Cheng void
dladm_stats_diff(pktsum_t * s1,pktsum_t * s2,pktsum_t * s3)243da14cebeSEric Cheng dladm_stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3)
244da14cebeSEric Cheng {
2452d40c3b2SPrakash Jalan s1->rbytes = DIFF_STAT(s2->rbytes, s3->rbytes);
2462d40c3b2SPrakash Jalan s1->ipackets = DIFF_STAT(s2->ipackets, s3->ipackets);
2472d40c3b2SPrakash Jalan s1->ierrors = DIFF_STAT(s2->ierrors, s3->ierrors);
2482d40c3b2SPrakash Jalan s1->obytes = DIFF_STAT(s2->obytes, s3->obytes);
2492d40c3b2SPrakash Jalan s1->opackets = DIFF_STAT(s2->opackets, s3->opackets);
2502d40c3b2SPrakash Jalan s1->oerrors = DIFF_STAT(s2->oerrors, s3->oerrors);
2512d40c3b2SPrakash Jalan s1->snaptime = DIFF_STAT(s2->snaptime, s3->snaptime);
252da14cebeSEric Cheng }
2530dc2366fSVenugopal Iyer
2540dc2366fSVenugopal Iyer #define DLSTAT_MAC_RX_SWLANE "mac_rx_swlane"
2550dc2366fSVenugopal Iyer #define DLSTAT_MAC_RX_HWLANE "mac_rx_hwlane"
2560dc2366fSVenugopal Iyer #define DLSTAT_MAC_TX_SWLANE "mac_tx_swlane"
2570dc2366fSVenugopal Iyer #define DLSTAT_MAC_TX_HWLANE "mac_tx_hwlane"
2580dc2366fSVenugopal Iyer #define DLSTAT_MAC_MISC_STAT "mac_misc_stat"
2590dc2366fSVenugopal Iyer #define DLSTAT_MAC_RX_RING "mac_rx_ring"
2600dc2366fSVenugopal Iyer #define DLSTAT_MAC_TX_RING "mac_tx_ring"
2610dc2366fSVenugopal Iyer #define DLSTAT_MAC_FANOUT "mac_rx_swlane0_fanout"
2620dc2366fSVenugopal Iyer
2630dc2366fSVenugopal Iyer typedef struct {
2640dc2366fSVenugopal Iyer const char *si_name;
2650dc2366fSVenugopal Iyer uint_t si_offset;
2660dc2366fSVenugopal Iyer } stat_info_t;
2670dc2366fSVenugopal Iyer
2680dc2366fSVenugopal Iyer #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0]))
2690dc2366fSVenugopal Iyer
2700dc2366fSVenugopal Iyer /* Definitions for rx lane stats */
2710dc2366fSVenugopal Iyer #define RL_OFF(f) (offsetof(rx_lane_stat_t, f))
2720dc2366fSVenugopal Iyer
2730dc2366fSVenugopal Iyer static stat_info_t rx_hwlane_stats_list[] = {
2740dc2366fSVenugopal Iyer {"ipackets", RL_OFF(rl_ipackets)},
2750dc2366fSVenugopal Iyer {"rbytes", RL_OFF(rl_rbytes)},
2760dc2366fSVenugopal Iyer {"intrs", RL_OFF(rl_intrs)},
2770dc2366fSVenugopal Iyer {"intrbytes", RL_OFF(rl_intrbytes)},
2780dc2366fSVenugopal Iyer {"polls", RL_OFF(rl_polls)},
2790dc2366fSVenugopal Iyer {"pollbytes", RL_OFF(rl_pollbytes)},
2800dc2366fSVenugopal Iyer {"rxsdrops", RL_OFF(rl_sdrops)},
2810dc2366fSVenugopal Iyer {"chainunder10", RL_OFF(rl_chl10)},
2820dc2366fSVenugopal Iyer {"chain10to50", RL_OFF(rl_ch10_50)},
2830dc2366fSVenugopal Iyer {"chainover50", RL_OFF(rl_chg50)}
2840dc2366fSVenugopal Iyer };
2850dc2366fSVenugopal Iyer #define RX_HWLANE_STAT_SIZE A_CNT(rx_hwlane_stats_list)
2860dc2366fSVenugopal Iyer
2870dc2366fSVenugopal Iyer static stat_info_t rx_swlane_stats_list[] = {
2880dc2366fSVenugopal Iyer {"ipackets", RL_OFF(rl_ipackets)},
2890dc2366fSVenugopal Iyer {"rbytes", RL_OFF(rl_rbytes)},
2900dc2366fSVenugopal Iyer {"local", RL_OFF(rl_lclpackets)},
2910dc2366fSVenugopal Iyer {"localbytes", RL_OFF(rl_lclbytes)},
2920dc2366fSVenugopal Iyer {"intrs", RL_OFF(rl_intrs)},
2930dc2366fSVenugopal Iyer {"intrbytes", RL_OFF(rl_intrbytes)},
2940dc2366fSVenugopal Iyer {"rxsdrops", RL_OFF(rl_sdrops)}
2950dc2366fSVenugopal Iyer };
2960dc2366fSVenugopal Iyer #define RX_SWLANE_STAT_SIZE A_CNT(rx_swlane_stats_list)
2970dc2366fSVenugopal Iyer
2980dc2366fSVenugopal Iyer static stat_info_t rx_lane_stats_list[] = {
2990dc2366fSVenugopal Iyer {"ipackets", RL_OFF(rl_ipackets)},
3000dc2366fSVenugopal Iyer {"rbytes", RL_OFF(rl_rbytes)},
3010dc2366fSVenugopal Iyer {"local", RL_OFF(rl_lclpackets)},
3020dc2366fSVenugopal Iyer {"localbytes", RL_OFF(rl_lclbytes)},
3030dc2366fSVenugopal Iyer {"intrs", RL_OFF(rl_intrs)},
3040dc2366fSVenugopal Iyer {"intrbytes", RL_OFF(rl_intrbytes)},
3050dc2366fSVenugopal Iyer {"polls", RL_OFF(rl_polls)},
3060dc2366fSVenugopal Iyer {"rxsdrops", RL_OFF(rl_sdrops)},
3070dc2366fSVenugopal Iyer {"pollbytes", RL_OFF(rl_pollbytes)},
3080dc2366fSVenugopal Iyer {"chainunder10", RL_OFF(rl_chl10)},
3090dc2366fSVenugopal Iyer {"chain10to50", RL_OFF(rl_ch10_50)},
3100dc2366fSVenugopal Iyer {"chainover50", RL_OFF(rl_chg50)}
3110dc2366fSVenugopal Iyer };
3120dc2366fSVenugopal Iyer #define RX_LANE_STAT_SIZE A_CNT(rx_lane_stats_list)
3130dc2366fSVenugopal Iyer
3140dc2366fSVenugopal Iyer /* Definitions for tx lane stats */
3150dc2366fSVenugopal Iyer #define TL_OFF(f) (offsetof(tx_lane_stat_t, f))
3160dc2366fSVenugopal Iyer
3170dc2366fSVenugopal Iyer static stat_info_t tx_lane_stats_list[] = {
3180dc2366fSVenugopal Iyer {"opackets", TL_OFF(tl_opackets)},
3190dc2366fSVenugopal Iyer {"obytes", TL_OFF(tl_obytes)},
3200dc2366fSVenugopal Iyer {"blockcnt", TL_OFF(tl_blockcnt)},
3210dc2366fSVenugopal Iyer {"unblockcnt", TL_OFF(tl_unblockcnt)},
3220dc2366fSVenugopal Iyer {"txsdrops", TL_OFF(tl_sdrops)}
3230dc2366fSVenugopal Iyer };
3240dc2366fSVenugopal Iyer #define TX_LANE_STAT_SIZE A_CNT(tx_lane_stats_list)
3250dc2366fSVenugopal Iyer
3260dc2366fSVenugopal Iyer /* Definitions for tx/rx misc stats */
3270dc2366fSVenugopal Iyer #define M_OFF(f) (offsetof(misc_stat_t, f))
3280dc2366fSVenugopal Iyer
3290dc2366fSVenugopal Iyer static stat_info_t misc_stats_list[] = {
3300dc2366fSVenugopal Iyer {"multircv", M_OFF(ms_multircv)},
3310dc2366fSVenugopal Iyer {"brdcstrcv", M_OFF(ms_brdcstrcv)},
3320dc2366fSVenugopal Iyer {"multixmt", M_OFF(ms_multixmt)},
3330dc2366fSVenugopal Iyer {"brdcstxmt", M_OFF(ms_brdcstxmt)},
3340dc2366fSVenugopal Iyer {"multircvbytes", M_OFF(ms_multircvbytes)},
3350dc2366fSVenugopal Iyer {"brdcstrcvbytes", M_OFF(ms_brdcstrcvbytes)},
3360dc2366fSVenugopal Iyer {"multixmtbytes", M_OFF(ms_multixmtbytes)},
3370dc2366fSVenugopal Iyer {"brdcstxmtbytes", M_OFF(ms_brdcstxmtbytes)},
3380dc2366fSVenugopal Iyer {"txerrors", M_OFF(ms_txerrors)},
3390dc2366fSVenugopal Iyer {"macspoofed", M_OFF(ms_macspoofed)},
3400dc2366fSVenugopal Iyer {"ipspoofed", M_OFF(ms_ipspoofed)},
3410dc2366fSVenugopal Iyer {"dhcpspoofed", M_OFF(ms_dhcpspoofed)},
3420dc2366fSVenugopal Iyer {"restricted", M_OFF(ms_restricted)},
3430dc2366fSVenugopal Iyer {"ipackets", M_OFF(ms_ipackets)},
3440dc2366fSVenugopal Iyer {"rbytes", M_OFF(ms_rbytes)},
3450dc2366fSVenugopal Iyer {"local", M_OFF(ms_local)},
3460dc2366fSVenugopal Iyer {"localbytes", M_OFF(ms_localbytes)},
3470dc2366fSVenugopal Iyer {"intrs", M_OFF(ms_intrs)},
3480dc2366fSVenugopal Iyer {"intrbytes", M_OFF(ms_intrbytes)},
3490dc2366fSVenugopal Iyer {"polls", M_OFF(ms_polls)},
3500dc2366fSVenugopal Iyer {"pollbytes", M_OFF(ms_pollbytes)},
3510dc2366fSVenugopal Iyer {"rxsdrops", M_OFF(ms_rxsdrops)},
3520dc2366fSVenugopal Iyer {"chainunder10", M_OFF(ms_chainunder10)},
3530dc2366fSVenugopal Iyer {"chain10to50", M_OFF(ms_chain10to50)},
3540dc2366fSVenugopal Iyer {"chainover50", M_OFF(ms_chainover50)},
3550dc2366fSVenugopal Iyer {"obytes", M_OFF(ms_obytes)},
3560dc2366fSVenugopal Iyer {"opackets", M_OFF(ms_opackets)},
3570dc2366fSVenugopal Iyer {"blockcnt", M_OFF(ms_blockcnt)},
3580dc2366fSVenugopal Iyer {"unblockcnt", M_OFF(ms_unblockcnt)},
3590dc2366fSVenugopal Iyer {"txsdrops", M_OFF(ms_txsdrops)}
3600dc2366fSVenugopal Iyer };
3610dc2366fSVenugopal Iyer #define MISC_STAT_SIZE A_CNT(misc_stats_list)
3620dc2366fSVenugopal Iyer
3630dc2366fSVenugopal Iyer /* Definitions for rx ring stats */
3640dc2366fSVenugopal Iyer #define R_OFF(f) (offsetof(ring_stat_t, f))
3650dc2366fSVenugopal Iyer
3660dc2366fSVenugopal Iyer static stat_info_t rx_ring_stats_list[] = {
3670dc2366fSVenugopal Iyer {"ipackets", R_OFF(r_packets)},
3680dc2366fSVenugopal Iyer {"rbytes", R_OFF(r_bytes)}
3690dc2366fSVenugopal Iyer };
3700dc2366fSVenugopal Iyer #define RX_RING_STAT_SIZE A_CNT(rx_ring_stats_list)
3710dc2366fSVenugopal Iyer
3720dc2366fSVenugopal Iyer /* Definitions for tx ring stats */
3730dc2366fSVenugopal Iyer static stat_info_t tx_ring_stats_list[] = {
3740dc2366fSVenugopal Iyer {"opackets", R_OFF(r_packets)},
3750dc2366fSVenugopal Iyer {"obytes", R_OFF(r_bytes)}
3760dc2366fSVenugopal Iyer };
3770dc2366fSVenugopal Iyer #define TX_RING_STAT_SIZE A_CNT(tx_ring_stats_list)
3780dc2366fSVenugopal Iyer
3790dc2366fSVenugopal Iyer /* Definitions for fanout stats */
3800dc2366fSVenugopal Iyer #define F_OFF(f) (offsetof(fanout_stat_t, f))
3810dc2366fSVenugopal Iyer
3820dc2366fSVenugopal Iyer static stat_info_t fanout_stats_list[] = {
3830dc2366fSVenugopal Iyer {"ipackets", F_OFF(f_ipackets)},
3840dc2366fSVenugopal Iyer {"rbytes", F_OFF(f_rbytes)},
3850dc2366fSVenugopal Iyer };
3860dc2366fSVenugopal Iyer #define FANOUT_STAT_SIZE A_CNT(fanout_stats_list)
3870dc2366fSVenugopal Iyer
3880dc2366fSVenugopal Iyer /* Definitions for total stats */
3890dc2366fSVenugopal Iyer #define T_OFF(f) (offsetof(total_stat_t, f))
3900dc2366fSVenugopal Iyer
3910dc2366fSVenugopal Iyer static stat_info_t total_stats_list[] = {
3920dc2366fSVenugopal Iyer {"ipackets", T_OFF(ts_ipackets)},
3930dc2366fSVenugopal Iyer {"rbytes", T_OFF(ts_rbytes)},
3940dc2366fSVenugopal Iyer {"opackets", T_OFF(ts_opackets)},
3950dc2366fSVenugopal Iyer {"obytes", T_OFF(ts_obytes)}
3960dc2366fSVenugopal Iyer };
3970dc2366fSVenugopal Iyer #define TOTAL_STAT_SIZE A_CNT(total_stats_list)
3980dc2366fSVenugopal Iyer
3990dc2366fSVenugopal Iyer /* Definitions for aggr stats */
4000dc2366fSVenugopal Iyer #define AP_OFF(f) (offsetof(aggr_port_stat_t, f))
4010dc2366fSVenugopal Iyer
4020dc2366fSVenugopal Iyer static stat_info_t aggr_port_stats_list[] = {
4030dc2366fSVenugopal Iyer {"ipackets64", AP_OFF(ap_ipackets)},
4040dc2366fSVenugopal Iyer {"rbytes64", AP_OFF(ap_rbytes)},
4050dc2366fSVenugopal Iyer {"opackets64", AP_OFF(ap_opackets)},
4060dc2366fSVenugopal Iyer {"obytes64", AP_OFF(ap_obytes)}
4070dc2366fSVenugopal Iyer };
4080dc2366fSVenugopal Iyer #define AGGR_PORT_STAT_SIZE A_CNT(aggr_port_stats_list)
4090dc2366fSVenugopal Iyer
4100dc2366fSVenugopal Iyer /* Definitions for flow stats */
4110dc2366fSVenugopal Iyer #define FL_OFF(f) (offsetof(flow_stat_t, f))
4120dc2366fSVenugopal Iyer
4130dc2366fSVenugopal Iyer static stat_info_t flow_stats_list[] = {
4140dc2366fSVenugopal Iyer {"ipackets", FL_OFF(fl_ipackets)},
4150dc2366fSVenugopal Iyer {"rbytes", FL_OFF(fl_rbytes)},
4160dc2366fSVenugopal Iyer {"opackets", FL_OFF(fl_opackets)},
4170dc2366fSVenugopal Iyer {"obytes", FL_OFF(fl_obytes)}
4180dc2366fSVenugopal Iyer };
4190dc2366fSVenugopal Iyer #define FLOW_STAT_SIZE A_CNT(flow_stats_list)
4200dc2366fSVenugopal Iyer
4210dc2366fSVenugopal Iyer /* Rx lane specific functions */
4220dc2366fSVenugopal Iyer void * dlstat_rx_lane_stats(dladm_handle_t, datalink_id_t);
4230dc2366fSVenugopal Iyer static boolean_t i_dlstat_rx_lane_match(void *, void *);
4240dc2366fSVenugopal Iyer static void * i_dlstat_rx_lane_stat_entry_diff(void *, void *);
4250dc2366fSVenugopal Iyer
4260dc2366fSVenugopal Iyer /* Tx lane specific functions */
4270dc2366fSVenugopal Iyer void * dlstat_tx_lane_stats(dladm_handle_t, datalink_id_t);
4280dc2366fSVenugopal Iyer static boolean_t i_dlstat_tx_lane_match(void *, void *);
4290dc2366fSVenugopal Iyer static void * i_dlstat_tx_lane_stat_entry_diff(void *, void *);
4300dc2366fSVenugopal Iyer
4310dc2366fSVenugopal Iyer /* Rx lane total specific functions */
4320dc2366fSVenugopal Iyer void * dlstat_rx_lane_total_stats(dladm_handle_t,
4330dc2366fSVenugopal Iyer datalink_id_t);
4340dc2366fSVenugopal Iyer
4350dc2366fSVenugopal Iyer /* Tx lane total specific functions */
4360dc2366fSVenugopal Iyer void * dlstat_tx_lane_total_stats(dladm_handle_t,
4370dc2366fSVenugopal Iyer datalink_id_t);
4380dc2366fSVenugopal Iyer
4390dc2366fSVenugopal Iyer /* Fanout specific functions */
4400dc2366fSVenugopal Iyer void * dlstat_fanout_stats(dladm_handle_t, datalink_id_t);
4410dc2366fSVenugopal Iyer static boolean_t i_dlstat_fanout_match(void *, void *);
4420dc2366fSVenugopal Iyer static void * i_dlstat_fanout_stat_entry_diff(void *, void *);
4430dc2366fSVenugopal Iyer
4440dc2366fSVenugopal Iyer /* Rx ring specific functions */
4450dc2366fSVenugopal Iyer void * dlstat_rx_ring_stats(dladm_handle_t, datalink_id_t);
4460dc2366fSVenugopal Iyer static boolean_t i_dlstat_rx_ring_match(void *, void *);
4470dc2366fSVenugopal Iyer static void * i_dlstat_rx_ring_stat_entry_diff(void *, void *);
4480dc2366fSVenugopal Iyer
4490dc2366fSVenugopal Iyer /* Tx ring specific functions */
4500dc2366fSVenugopal Iyer void * dlstat_tx_ring_stats(dladm_handle_t, datalink_id_t);
4510dc2366fSVenugopal Iyer static boolean_t i_dlstat_tx_ring_match(void *, void *);
4520dc2366fSVenugopal Iyer static void * i_dlstat_tx_ring_stat_entry_diff(void *, void *);
4530dc2366fSVenugopal Iyer
4540dc2366fSVenugopal Iyer /* Rx ring total specific functions */
4550dc2366fSVenugopal Iyer void * dlstat_rx_ring_total_stats(dladm_handle_t,
4560dc2366fSVenugopal Iyer datalink_id_t);
4570dc2366fSVenugopal Iyer
4580dc2366fSVenugopal Iyer /* Tx ring total specific functions */
4590dc2366fSVenugopal Iyer void * dlstat_tx_ring_total_stats(dladm_handle_t,
4600dc2366fSVenugopal Iyer datalink_id_t);
4610dc2366fSVenugopal Iyer
4620dc2366fSVenugopal Iyer /* Summary specific functions */
4630dc2366fSVenugopal Iyer void * dlstat_total_stats(dladm_handle_t, datalink_id_t);
4640dc2366fSVenugopal Iyer static boolean_t i_dlstat_total_match(void *, void *);
4650dc2366fSVenugopal Iyer static void * i_dlstat_total_stat_entry_diff(void *, void *);
4660dc2366fSVenugopal Iyer
4670dc2366fSVenugopal Iyer /* Aggr port specific functions */
4680dc2366fSVenugopal Iyer void * dlstat_aggr_port_stats(dladm_handle_t, datalink_id_t);
4690dc2366fSVenugopal Iyer static boolean_t i_dlstat_aggr_port_match(void *, void *);
4700dc2366fSVenugopal Iyer static void * i_dlstat_aggr_port_stat_entry_diff(void *, void *);
4710dc2366fSVenugopal Iyer
4720dc2366fSVenugopal Iyer /* Misc stat specific functions */
4730dc2366fSVenugopal Iyer void * dlstat_misc_stats(dladm_handle_t, datalink_id_t);
4740dc2366fSVenugopal Iyer
4750dc2366fSVenugopal Iyer typedef void * dladm_stat_query_t(dladm_handle_t, datalink_id_t);
4760dc2366fSVenugopal Iyer typedef boolean_t dladm_stat_match_t(void *, void *);
4770dc2366fSVenugopal Iyer typedef void * dladm_stat_diff_t(void *, void *);
4780dc2366fSVenugopal Iyer
4790dc2366fSVenugopal Iyer typedef struct dladm_stat_desc_s {
4800dc2366fSVenugopal Iyer dladm_stat_type_t ds_stattype;
4810dc2366fSVenugopal Iyer dladm_stat_query_t *ds_querystat;
4820dc2366fSVenugopal Iyer dladm_stat_match_t *ds_matchstat;
4830dc2366fSVenugopal Iyer dladm_stat_diff_t *ds_diffstat;
4840dc2366fSVenugopal Iyer uint_t ds_offset;
4850dc2366fSVenugopal Iyer stat_info_t *ds_statlist;
4860dc2366fSVenugopal Iyer uint_t ds_statsize;
4870dc2366fSVenugopal Iyer } dladm_stat_desc_t;
4880dc2366fSVenugopal Iyer
4890dc2366fSVenugopal Iyer /*
4900dc2366fSVenugopal Iyer * dladm_stat_table has one entry for each supported stat. ds_querystat returns
4910dc2366fSVenugopal Iyer * a chain of 'stat entries' for the queried stat.
4920dc2366fSVenugopal Iyer * Each stat entry has set of identifiers (ids) and an object containing actual
4930dc2366fSVenugopal Iyer * stat values. These stat entry objects are chained together in a linked list
4940dc2366fSVenugopal Iyer * of datatype dladm_stat_chain_t. Head of this list is returned to the caller
4950dc2366fSVenugopal Iyer * of dladm_link_stat_query.
4960dc2366fSVenugopal Iyer *
4970dc2366fSVenugopal Iyer * One node in the chain is shown below:
4980dc2366fSVenugopal Iyer *
4990dc2366fSVenugopal Iyer * -------------------------
5000dc2366fSVenugopal Iyer * | dc_statentry |
5010dc2366fSVenugopal Iyer * | -------------- |
5020dc2366fSVenugopal Iyer * | | ids | |
5030dc2366fSVenugopal Iyer * | -------------- |
5040dc2366fSVenugopal Iyer * | | stat fields | |
5050dc2366fSVenugopal Iyer * | -------------- |
5060dc2366fSVenugopal Iyer * -------------------------
5070dc2366fSVenugopal Iyer * | dc_next ---------|------> to next stat entry
5080dc2366fSVenugopal Iyer * -------------------------
5090dc2366fSVenugopal Iyer *
5100dc2366fSVenugopal Iyer * In particular, for query DLADM_STAT_RX_LANE, dc_statentry carries pointer to
5110dc2366fSVenugopal Iyer * object of type rx_lane_stat_entry_t.
5120dc2366fSVenugopal Iyer *
5130dc2366fSVenugopal Iyer * dladm_link_stat_query_all returns similar chain. However, instead of storing
5140dc2366fSVenugopal Iyer * stat fields as raw numbers, it stores those as chain of <name, value> pairs.
5150dc2366fSVenugopal Iyer * The resulting structure is depicted below:
5160dc2366fSVenugopal Iyer *
5170dc2366fSVenugopal Iyer * -------------------------
5180dc2366fSVenugopal Iyer * | dc_statentry |
5190dc2366fSVenugopal Iyer * | -------------- | ---------------
5200dc2366fSVenugopal Iyer * | | nv_header | | | name, val |
5210dc2366fSVenugopal Iyer * | -------------- | ---------------
5220dc2366fSVenugopal Iyer * | | nve_stats---|----|-->| nv_nextstat--|---> to next name, val pair
5230dc2366fSVenugopal Iyer * | -------------- | ---------------
5240dc2366fSVenugopal Iyer * -------------------------
5250dc2366fSVenugopal Iyer * | dc_next ---------|------> to next stat entry
5260dc2366fSVenugopal Iyer * -------------------------
5270dc2366fSVenugopal Iyer */
5280dc2366fSVenugopal Iyer static dladm_stat_desc_t dladm_stat_table[] = {
5290dc2366fSVenugopal Iyer { DLADM_STAT_RX_LANE, dlstat_rx_lane_stats,
5300dc2366fSVenugopal Iyer i_dlstat_rx_lane_match, i_dlstat_rx_lane_stat_entry_diff,
5310dc2366fSVenugopal Iyer offsetof(rx_lane_stat_entry_t, rle_stats),
5320dc2366fSVenugopal Iyer rx_lane_stats_list, RX_LANE_STAT_SIZE},
5330dc2366fSVenugopal Iyer
5340dc2366fSVenugopal Iyer { DLADM_STAT_TX_LANE, dlstat_tx_lane_stats,
5350dc2366fSVenugopal Iyer i_dlstat_tx_lane_match, i_dlstat_tx_lane_stat_entry_diff,
5360dc2366fSVenugopal Iyer offsetof(tx_lane_stat_entry_t, tle_stats),
5370dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE},
5380dc2366fSVenugopal Iyer
5390dc2366fSVenugopal Iyer { DLADM_STAT_RX_LANE_TOTAL, dlstat_rx_lane_total_stats,
5400dc2366fSVenugopal Iyer i_dlstat_rx_lane_match, i_dlstat_rx_lane_stat_entry_diff,
5410dc2366fSVenugopal Iyer offsetof(rx_lane_stat_entry_t, rle_stats),
5420dc2366fSVenugopal Iyer rx_lane_stats_list, RX_LANE_STAT_SIZE},
5430dc2366fSVenugopal Iyer
5440dc2366fSVenugopal Iyer { DLADM_STAT_TX_LANE_TOTAL, dlstat_tx_lane_total_stats,
5450dc2366fSVenugopal Iyer i_dlstat_tx_lane_match, i_dlstat_tx_lane_stat_entry_diff,
5460dc2366fSVenugopal Iyer offsetof(tx_lane_stat_entry_t, tle_stats),
5470dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE},
5480dc2366fSVenugopal Iyer
5490dc2366fSVenugopal Iyer { DLADM_STAT_RX_LANE_FOUT, dlstat_fanout_stats,
5500dc2366fSVenugopal Iyer i_dlstat_fanout_match, i_dlstat_fanout_stat_entry_diff,
5510dc2366fSVenugopal Iyer offsetof(fanout_stat_entry_t, fe_stats),
5520dc2366fSVenugopal Iyer fanout_stats_list, FANOUT_STAT_SIZE},
5530dc2366fSVenugopal Iyer
5540dc2366fSVenugopal Iyer { DLADM_STAT_RX_RING, dlstat_rx_ring_stats,
5550dc2366fSVenugopal Iyer i_dlstat_rx_ring_match, i_dlstat_rx_ring_stat_entry_diff,
5560dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats),
5570dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE},
5580dc2366fSVenugopal Iyer
5590dc2366fSVenugopal Iyer { DLADM_STAT_TX_RING, dlstat_tx_ring_stats,
5600dc2366fSVenugopal Iyer i_dlstat_tx_ring_match, i_dlstat_tx_ring_stat_entry_diff,
5610dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats),
5620dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE},
5630dc2366fSVenugopal Iyer
5640dc2366fSVenugopal Iyer { DLADM_STAT_RX_RING_TOTAL, dlstat_rx_ring_total_stats,
5650dc2366fSVenugopal Iyer i_dlstat_rx_ring_match, i_dlstat_rx_ring_stat_entry_diff,
5660dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats),
5670dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE},
5680dc2366fSVenugopal Iyer
5690dc2366fSVenugopal Iyer { DLADM_STAT_TX_RING_TOTAL, dlstat_tx_ring_total_stats,
5700dc2366fSVenugopal Iyer i_dlstat_tx_ring_match, i_dlstat_tx_ring_stat_entry_diff,
5710dc2366fSVenugopal Iyer offsetof(ring_stat_entry_t, re_stats),
5720dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE},
5730dc2366fSVenugopal Iyer
5740dc2366fSVenugopal Iyer { DLADM_STAT_TOTAL, dlstat_total_stats,
5750dc2366fSVenugopal Iyer i_dlstat_total_match, i_dlstat_total_stat_entry_diff,
5760dc2366fSVenugopal Iyer offsetof(total_stat_entry_t, tse_stats),
5770dc2366fSVenugopal Iyer total_stats_list, TOTAL_STAT_SIZE},
5780dc2366fSVenugopal Iyer
5790dc2366fSVenugopal Iyer { DLADM_STAT_AGGR_PORT, dlstat_aggr_port_stats,
5800dc2366fSVenugopal Iyer i_dlstat_aggr_port_match, i_dlstat_aggr_port_stat_entry_diff,
5810dc2366fSVenugopal Iyer offsetof(aggr_port_stat_entry_t, ape_stats),
5820dc2366fSVenugopal Iyer aggr_port_stats_list, AGGR_PORT_STAT_SIZE},
5830dc2366fSVenugopal Iyer /*
5840dc2366fSVenugopal Iyer * We don't support -i <interval> query with misc stats. Several table fields
5850dc2366fSVenugopal Iyer * are left uninitialized thus.
5860dc2366fSVenugopal Iyer */
5870dc2366fSVenugopal Iyer { DLADM_STAT_MISC, dlstat_misc_stats,
5880dc2366fSVenugopal Iyer NULL, NULL,
5890dc2366fSVenugopal Iyer 0,
5900dc2366fSVenugopal Iyer misc_stats_list, MISC_STAT_SIZE}
5910dc2366fSVenugopal Iyer };
5920dc2366fSVenugopal Iyer
5930dc2366fSVenugopal Iyer /* Internal functions */
5940dc2366fSVenugopal Iyer static void *
dlstat_diff_stats(void * arg1,void * arg2,dladm_stat_type_t stattype)5950dc2366fSVenugopal Iyer dlstat_diff_stats(void *arg1, void *arg2, dladm_stat_type_t stattype)
5960dc2366fSVenugopal Iyer {
5970dc2366fSVenugopal Iyer return (dladm_stat_table[stattype].ds_diffstat(arg1, arg2));
5980dc2366fSVenugopal Iyer }
5990dc2366fSVenugopal Iyer
6000dc2366fSVenugopal Iyer static boolean_t
dlstat_match_stats(void * arg1,void * arg2,dladm_stat_type_t stattype)6010dc2366fSVenugopal Iyer dlstat_match_stats(void *arg1, void *arg2, dladm_stat_type_t stattype)
6020dc2366fSVenugopal Iyer {
6030dc2366fSVenugopal Iyer return (dladm_stat_table[stattype].ds_matchstat(arg1, arg2));
6040dc2366fSVenugopal Iyer }
6050dc2366fSVenugopal Iyer
6060dc2366fSVenugopal Iyer /* Diff between two stats */
6070dc2366fSVenugopal Iyer static void
i_dlstat_diff_stats(void * diff,void * op1,void * op2,stat_info_t stats_list[],uint_t size)6080dc2366fSVenugopal Iyer i_dlstat_diff_stats(void *diff, void *op1, void *op2,
6090dc2366fSVenugopal Iyer stat_info_t stats_list[], uint_t size)
6100dc2366fSVenugopal Iyer {
6110dc2366fSVenugopal Iyer int i;
6120dc2366fSVenugopal Iyer
6130dc2366fSVenugopal Iyer for (i = 0; i < size; i++) {
6140dc2366fSVenugopal Iyer uint64_t *op1_val = (void *)
6150dc2366fSVenugopal Iyer ((uchar_t *)op1 + stats_list[i].si_offset);
6160dc2366fSVenugopal Iyer uint64_t *op2_val = (void *)
6170dc2366fSVenugopal Iyer ((uchar_t *)op2 + stats_list[i].si_offset);
6180dc2366fSVenugopal Iyer uint64_t *diff_val = (void *)
6190dc2366fSVenugopal Iyer ((uchar_t *)diff + stats_list[i].si_offset);
6200dc2366fSVenugopal Iyer
6210dc2366fSVenugopal Iyer *diff_val = DIFF_STAT(*op1_val, *op2_val);
6220dc2366fSVenugopal Iyer }
6230dc2366fSVenugopal Iyer }
6240dc2366fSVenugopal Iyer
6250dc2366fSVenugopal Iyer /*
6260dc2366fSVenugopal Iyer * Perform diff = s1 - s2, where diff, s1, s2 are structure objects of same
6270dc2366fSVenugopal Iyer * datatype. slist is list of offsets of the fields within the structure.
6280dc2366fSVenugopal Iyer */
6290dc2366fSVenugopal Iyer #define DLSTAT_DIFF_STAT(s1, s2, diff, f, slist, sz) { \
6300dc2366fSVenugopal Iyer if (s2 == NULL) { \
6310dc2366fSVenugopal Iyer bcopy(&s1->f, &diff->f, sizeof (s1->f)); \
6320dc2366fSVenugopal Iyer } else { \
6330dc2366fSVenugopal Iyer i_dlstat_diff_stats(&diff->f, &s1->f, \
6340dc2366fSVenugopal Iyer &s2->f, slist, sz); \
6350dc2366fSVenugopal Iyer } \
6360dc2366fSVenugopal Iyer }
6370dc2366fSVenugopal Iyer
6380dc2366fSVenugopal Iyer /* Sum two stats */
6390dc2366fSVenugopal Iyer static void
i_dlstat_sum_stats(void * sum,void * op1,void * op2,stat_info_t stats_list[],uint_t size)6400dc2366fSVenugopal Iyer i_dlstat_sum_stats(void *sum, void *op1, void *op2,
6410dc2366fSVenugopal Iyer stat_info_t stats_list[], uint_t size)
6420dc2366fSVenugopal Iyer {
6430dc2366fSVenugopal Iyer int i;
6440dc2366fSVenugopal Iyer
6450dc2366fSVenugopal Iyer for (i = 0; i < size; i++) {
6460dc2366fSVenugopal Iyer uint64_t *op1_val = (void *)
6470dc2366fSVenugopal Iyer ((uchar_t *)op1 + stats_list[i].si_offset);
6480dc2366fSVenugopal Iyer uint64_t *op2_val = (void *)
6490dc2366fSVenugopal Iyer ((uchar_t *)op2 + stats_list[i].si_offset);
6500dc2366fSVenugopal Iyer uint64_t *sum_val = (void *)
6510dc2366fSVenugopal Iyer ((uchar_t *)sum + stats_list[i].si_offset);
6520dc2366fSVenugopal Iyer
6530dc2366fSVenugopal Iyer *sum_val = *op1_val + *op2_val;
6540dc2366fSVenugopal Iyer }
6550dc2366fSVenugopal Iyer }
6560dc2366fSVenugopal Iyer
6570dc2366fSVenugopal Iyer /* Look up kstat value */
6580dc2366fSVenugopal Iyer static void
i_dlstat_get_stats(kstat_ctl_t * kcp,kstat_t * ksp,void * stats,stat_info_t stats_list[],uint_t size)6590dc2366fSVenugopal Iyer i_dlstat_get_stats(kstat_ctl_t *kcp, kstat_t *ksp, void *stats,
6600dc2366fSVenugopal Iyer stat_info_t stats_list[], uint_t size)
6610dc2366fSVenugopal Iyer {
6620dc2366fSVenugopal Iyer int i;
6630dc2366fSVenugopal Iyer
6640dc2366fSVenugopal Iyer if (kstat_read(kcp, ksp, NULL) == -1)
6650dc2366fSVenugopal Iyer return;
6660dc2366fSVenugopal Iyer
6670dc2366fSVenugopal Iyer for (i = 0; i < size; i++) {
6680dc2366fSVenugopal Iyer uint64_t *val = (void *)
6690dc2366fSVenugopal Iyer ((uchar_t *)stats + stats_list[i].si_offset);
6700dc2366fSVenugopal Iyer
6710dc2366fSVenugopal Iyer if (dladm_kstat_value(ksp, stats_list[i].si_name,
6720dc2366fSVenugopal Iyer KSTAT_DATA_UINT64, val) < 0)
6730dc2366fSVenugopal Iyer return;
6740dc2366fSVenugopal Iyer }
6750dc2366fSVenugopal Iyer }
6760dc2366fSVenugopal Iyer
6770dc2366fSVenugopal Iyer /* Append linked list list1 to linked list list2 and return resulting list */
6780dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_join_lists(dladm_stat_chain_t * list1,dladm_stat_chain_t * list2)6790dc2366fSVenugopal Iyer i_dlstat_join_lists(dladm_stat_chain_t *list1, dladm_stat_chain_t *list2)
6800dc2366fSVenugopal Iyer {
6810dc2366fSVenugopal Iyer dladm_stat_chain_t *curr;
6820dc2366fSVenugopal Iyer
6830dc2366fSVenugopal Iyer if (list1 == NULL)
6840dc2366fSVenugopal Iyer return (list2);
6850dc2366fSVenugopal Iyer
6860dc2366fSVenugopal Iyer /* list1 has at least one element, find last element in list1 */
6870dc2366fSVenugopal Iyer curr = list1;
6880dc2366fSVenugopal Iyer while (curr->dc_next != NULL)
6890dc2366fSVenugopal Iyer curr = curr->dc_next;
6900dc2366fSVenugopal Iyer
6910dc2366fSVenugopal Iyer curr->dc_next = list2;
6920dc2366fSVenugopal Iyer return (list1);
6930dc2366fSVenugopal Iyer }
6940dc2366fSVenugopal Iyer
6950dc2366fSVenugopal Iyer uint_t default_idlist[] = {0};
6960dc2366fSVenugopal Iyer uint_t default_idlist_size = 1;
6970dc2366fSVenugopal Iyer
6980dc2366fSVenugopal Iyer typedef enum {
6990dc2366fSVenugopal Iyer DLSTAT_RX_RING_IDLIST,
7000dc2366fSVenugopal Iyer DLSTAT_TX_RING_IDLIST,
7010dc2366fSVenugopal Iyer DLSTAT_RX_HWLANE_IDLIST,
7020dc2366fSVenugopal Iyer DLSTAT_TX_HWLANE_IDLIST,
7030dc2366fSVenugopal Iyer DLSTAT_FANOUT_IDLIST
7040dc2366fSVenugopal Iyer } dlstat_idlist_type_t;
7050dc2366fSVenugopal Iyer
7060dc2366fSVenugopal Iyer void
dladm_sort_index_list(uint_t idlist[],uint_t size)7070dc2366fSVenugopal Iyer dladm_sort_index_list(uint_t idlist[], uint_t size)
7080dc2366fSVenugopal Iyer {
7090dc2366fSVenugopal Iyer int i, j;
7100dc2366fSVenugopal Iyer
7110dc2366fSVenugopal Iyer for (j = 1; j < size; j++) {
7120dc2366fSVenugopal Iyer int key = idlist[j];
7130dc2366fSVenugopal Iyer for (i = j - 1; (i >= 0) && (idlist[i] > key); i--)
7140dc2366fSVenugopal Iyer idlist[i + 1] = idlist[i];
7150dc2366fSVenugopal Iyer idlist[i + 1] = key;
7160dc2366fSVenugopal Iyer }
7170dc2366fSVenugopal Iyer }
7180dc2366fSVenugopal Iyer
7190dc2366fSVenugopal Iyer /* Support for legacy drivers */
7200dc2366fSVenugopal Iyer void
i_query_legacy_stats(const char * linkname,pktsum_t * stats)7210dc2366fSVenugopal Iyer i_query_legacy_stats(const char *linkname, pktsum_t *stats)
7220dc2366fSVenugopal Iyer {
7230dc2366fSVenugopal Iyer kstat_ctl_t *kcp;
7240dc2366fSVenugopal Iyer kstat_t *ksp;
7250dc2366fSVenugopal Iyer
7260dc2366fSVenugopal Iyer bzero(stats, sizeof (*stats));
7270dc2366fSVenugopal Iyer
7280dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL)
7290dc2366fSVenugopal Iyer return;
7300dc2366fSVenugopal Iyer
7310dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, "link", 0, linkname, NULL);
7320dc2366fSVenugopal Iyer
7330dc2366fSVenugopal Iyer if (ksp != NULL)
7340dc2366fSVenugopal Iyer dladm_get_stats(kcp, ksp, stats);
7350dc2366fSVenugopal Iyer
7360dc2366fSVenugopal Iyer (void) kstat_close(kcp);
7370dc2366fSVenugopal Iyer }
7380dc2366fSVenugopal Iyer
7390dc2366fSVenugopal Iyer void *
i_dlstat_legacy_rx_lane_stats(const char * linkname)7400dc2366fSVenugopal Iyer i_dlstat_legacy_rx_lane_stats(const char *linkname)
7410dc2366fSVenugopal Iyer {
7420dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
7430dc2366fSVenugopal Iyer pktsum_t stats;
7440dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
7450dc2366fSVenugopal Iyer
7460dc2366fSVenugopal Iyer bzero(&stats, sizeof (pktsum_t));
7470dc2366fSVenugopal Iyer
7480dc2366fSVenugopal Iyer /* Query for dls stats */
7490dc2366fSVenugopal Iyer i_query_legacy_stats(linkname, &stats);
7500dc2366fSVenugopal Iyer
7510dc2366fSVenugopal Iyer /* Convert to desired data type */
7520dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
7530dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL)
7540dc2366fSVenugopal Iyer goto done;
7550dc2366fSVenugopal Iyer
7560dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
7570dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_SWLANE;
7580dc2366fSVenugopal Iyer
7590dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets = stats.ipackets;
7600dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs = stats.ipackets;
7610dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes = stats.rbytes;
7620dc2366fSVenugopal Iyer
7630dc2366fSVenugopal Iyer /* Allocate memory for wrapper */
7640dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
7650dc2366fSVenugopal Iyer if (head == NULL) {
7660dc2366fSVenugopal Iyer free(rx_lane_stat_entry);
7670dc2366fSVenugopal Iyer goto done;
7680dc2366fSVenugopal Iyer }
7690dc2366fSVenugopal Iyer
7700dc2366fSVenugopal Iyer head->dc_statentry = rx_lane_stat_entry;
7710dc2366fSVenugopal Iyer head->dc_next = NULL;
7720dc2366fSVenugopal Iyer done:
7730dc2366fSVenugopal Iyer return (head);
7740dc2366fSVenugopal Iyer }
7750dc2366fSVenugopal Iyer
7760dc2366fSVenugopal Iyer void *
i_dlstat_legacy_tx_lane_stats(const char * linkname)7770dc2366fSVenugopal Iyer i_dlstat_legacy_tx_lane_stats(const char *linkname)
7780dc2366fSVenugopal Iyer {
7790dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
7800dc2366fSVenugopal Iyer pktsum_t stats;
7810dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry;
7820dc2366fSVenugopal Iyer
7830dc2366fSVenugopal Iyer bzero(&stats, sizeof (pktsum_t));
7840dc2366fSVenugopal Iyer
7850dc2366fSVenugopal Iyer /* Query for dls stats */
7860dc2366fSVenugopal Iyer i_query_legacy_stats(linkname, &stats);
7870dc2366fSVenugopal Iyer
7880dc2366fSVenugopal Iyer /* Convert to desired data type */
7890dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
7900dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL)
7910dc2366fSVenugopal Iyer goto done;
7920dc2366fSVenugopal Iyer
7930dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
7940dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_SWLANE;
7950dc2366fSVenugopal Iyer
7960dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets = stats.opackets;
7970dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes = stats.obytes;
7980dc2366fSVenugopal Iyer
7990dc2366fSVenugopal Iyer /* Allocate memory for wrapper */
8000dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
8010dc2366fSVenugopal Iyer if (head == NULL) {
8020dc2366fSVenugopal Iyer free(tx_lane_stat_entry);
8030dc2366fSVenugopal Iyer goto done;
8040dc2366fSVenugopal Iyer }
8050dc2366fSVenugopal Iyer
8060dc2366fSVenugopal Iyer head->dc_statentry = tx_lane_stat_entry;
8070dc2366fSVenugopal Iyer head->dc_next = NULL;
8080dc2366fSVenugopal Iyer done:
8090dc2366fSVenugopal Iyer return (head);
8100dc2366fSVenugopal Iyer }
8110dc2366fSVenugopal Iyer
8120dc2366fSVenugopal Iyer /*
8130dc2366fSVenugopal Iyer * Ideally, we would want an ioctl to return list of ring-ids (or lane-ids)
8140dc2366fSVenugopal Iyer * for a given data-link (or mac client). We could then query for specific
8150dc2366fSVenugopal Iyer * kstats based on these ring-ids (lane-ids).
8160dc2366fSVenugopal Iyer * Ring-ids (or lane-ids) could be returned like any other link properties
8170dc2366fSVenugopal Iyer * queried by dladm show-linkprop. However, non-global zones do not have
8180dc2366fSVenugopal Iyer * access to this information today.
8190dc2366fSVenugopal Iyer * We thus opt for an implementation that relies heavily on kstat internals:
8200dc2366fSVenugopal Iyer * i_dlstat_*search routines and i_dlstat_get_idlist.
8210dc2366fSVenugopal Iyer */
8220dc2366fSVenugopal Iyer /* rx hwlane specific */
8230dc2366fSVenugopal Iyer static boolean_t
i_dlstat_rx_hwlane_search(kstat_t * ksp)8240dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_search(kstat_t *ksp)
8250dc2366fSVenugopal Iyer {
8260dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 &&
8270dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_rx") != 0 &&
8280dc2366fSVenugopal Iyer strstr(ksp->ks_name, "hwlane") != 0 &&
8290dc2366fSVenugopal Iyer strstr(ksp->ks_name, "fanout") == 0 &&
8300dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0);
8310dc2366fSVenugopal Iyer }
8320dc2366fSVenugopal Iyer
8330dc2366fSVenugopal Iyer /* tx hwlane specific */
8340dc2366fSVenugopal Iyer static boolean_t
i_dlstat_tx_hwlane_search(kstat_t * ksp)8350dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_search(kstat_t *ksp)
8360dc2366fSVenugopal Iyer {
8370dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 &&
8380dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_tx") != 0 &&
8390dc2366fSVenugopal Iyer strstr(ksp->ks_name, "hwlane") != 0 &&
8400dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0);
8410dc2366fSVenugopal Iyer }
8420dc2366fSVenugopal Iyer
8430dc2366fSVenugopal Iyer /* rx fanout specific */
8440dc2366fSVenugopal Iyer static boolean_t
i_dlstat_fanout_search(kstat_t * ksp)8450dc2366fSVenugopal Iyer i_dlstat_fanout_search(kstat_t *ksp)
8460dc2366fSVenugopal Iyer {
8470dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 &&
8480dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_rx") != 0 &&
8490dc2366fSVenugopal Iyer strstr(ksp->ks_name, "swlane") != 0 &&
8500dc2366fSVenugopal Iyer strstr(ksp->ks_name, "fanout") != 0 &&
8510dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0);
8520dc2366fSVenugopal Iyer }
8530dc2366fSVenugopal Iyer
8540dc2366fSVenugopal Iyer /* rx ring specific */
8550dc2366fSVenugopal Iyer static boolean_t
i_dlstat_rx_ring_search(kstat_t * ksp)8560dc2366fSVenugopal Iyer i_dlstat_rx_ring_search(kstat_t *ksp)
8570dc2366fSVenugopal Iyer {
8580dc2366fSVenugopal Iyer return (ksp->ks_instance == 0 &&
8590dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_rx") != 0 &&
8600dc2366fSVenugopal Iyer strstr(ksp->ks_name, "ring") != 0 &&
8610dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0);
8620dc2366fSVenugopal Iyer }
8630dc2366fSVenugopal Iyer
8640dc2366fSVenugopal Iyer /* tx ring specific */
8650dc2366fSVenugopal Iyer static boolean_t
i_dlstat_tx_ring_search(kstat_t * ksp)8660dc2366fSVenugopal Iyer i_dlstat_tx_ring_search(kstat_t *ksp)
8670dc2366fSVenugopal Iyer {
8680dc2366fSVenugopal Iyer return (ksp->ks_instance == 0) &&
8690dc2366fSVenugopal Iyer strstr(ksp->ks_name, "mac_tx") != 0 &&
8700dc2366fSVenugopal Iyer strstr(ksp->ks_name, "ring") != 0 &&
8710dc2366fSVenugopal Iyer strcmp(ksp->ks_class, "net") == 0;
8720dc2366fSVenugopal Iyer }
8730dc2366fSVenugopal Iyer
8740dc2366fSVenugopal Iyer typedef boolean_t dladm_search_kstat_t(kstat_t *);
8750dc2366fSVenugopal Iyer typedef struct dladm_extract_idlist_s {
8760dc2366fSVenugopal Iyer dlstat_idlist_type_t di_type;
8770dc2366fSVenugopal Iyer char *di_prefix;
8780dc2366fSVenugopal Iyer dladm_search_kstat_t *di_searchkstat;
8790dc2366fSVenugopal Iyer } dladm_extract_idlist_t;
8800dc2366fSVenugopal Iyer
8810dc2366fSVenugopal Iyer static dladm_extract_idlist_t dladm_extract_idlist[] = {
8820dc2366fSVenugopal Iyer { DLSTAT_RX_RING_IDLIST, DLSTAT_MAC_RX_RING,
8830dc2366fSVenugopal Iyer i_dlstat_rx_ring_search},
8840dc2366fSVenugopal Iyer { DLSTAT_TX_RING_IDLIST, DLSTAT_MAC_TX_RING,
8850dc2366fSVenugopal Iyer i_dlstat_tx_ring_search},
8860dc2366fSVenugopal Iyer { DLSTAT_RX_HWLANE_IDLIST, DLSTAT_MAC_RX_HWLANE,
8870dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_search},
8880dc2366fSVenugopal Iyer { DLSTAT_TX_HWLANE_IDLIST, DLSTAT_MAC_TX_HWLANE,
8890dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_search},
8900dc2366fSVenugopal Iyer { DLSTAT_FANOUT_IDLIST, DLSTAT_MAC_FANOUT,
8910dc2366fSVenugopal Iyer i_dlstat_fanout_search}
8920dc2366fSVenugopal Iyer };
8930dc2366fSVenugopal Iyer
8940dc2366fSVenugopal Iyer static void
i_dlstat_get_idlist(const char * modname,dlstat_idlist_type_t idlist_type,uint_t idlist[],uint_t * size)8950dc2366fSVenugopal Iyer i_dlstat_get_idlist(const char *modname, dlstat_idlist_type_t idlist_type,
8960dc2366fSVenugopal Iyer uint_t idlist[], uint_t *size)
8970dc2366fSVenugopal Iyer {
8980dc2366fSVenugopal Iyer kstat_ctl_t *kcp;
8990dc2366fSVenugopal Iyer kstat_t *ksp;
9000dc2366fSVenugopal Iyer char *prefix;
9010dc2366fSVenugopal Iyer int prefixlen;
9020dc2366fSVenugopal Iyer boolean_t (*fptr_searchkstat)(kstat_t *);
9030dc2366fSVenugopal Iyer
9040dc2366fSVenugopal Iyer *size = 0;
9050dc2366fSVenugopal Iyer
9060dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) {
9070dc2366fSVenugopal Iyer warn("kstat_open operation failed");
9080dc2366fSVenugopal Iyer goto done;
9090dc2366fSVenugopal Iyer }
9100dc2366fSVenugopal Iyer
9110dc2366fSVenugopal Iyer prefix = dladm_extract_idlist[idlist_type].di_prefix;
9120dc2366fSVenugopal Iyer fptr_searchkstat = dladm_extract_idlist[idlist_type].di_searchkstat;
9130dc2366fSVenugopal Iyer prefixlen = strlen(prefix);
9140dc2366fSVenugopal Iyer for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
9150dc2366fSVenugopal Iyer if ((strcmp(ksp->ks_module, modname) == 0) &&
9160dc2366fSVenugopal Iyer fptr_searchkstat(ksp)) {
9170dc2366fSVenugopal Iyer idlist[(*size)++] = atoi(&ksp->ks_name[prefixlen]);
9180dc2366fSVenugopal Iyer }
9190dc2366fSVenugopal Iyer }
9200dc2366fSVenugopal Iyer dladm_sort_index_list(idlist, *size);
9210dc2366fSVenugopal Iyer
9220dc2366fSVenugopal Iyer done:
9230dc2366fSVenugopal Iyer (void) kstat_close(kcp);
9240dc2366fSVenugopal Iyer }
9250dc2366fSVenugopal Iyer
9260dc2366fSVenugopal 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))9270dc2366fSVenugopal Iyer i_dlstat_query_stats(const char *modname, const char *prefix,
9280dc2366fSVenugopal Iyer uint_t idlist[], uint_t idlist_size,
9290dc2366fSVenugopal Iyer void * (*fn)(kstat_ctl_t *, kstat_t *, int))
9300dc2366fSVenugopal Iyer {
9310dc2366fSVenugopal Iyer kstat_ctl_t *kcp;
9320dc2366fSVenugopal Iyer kstat_t *ksp;
9330dc2366fSVenugopal Iyer char statname[MAXLINKNAMELEN];
9340dc2366fSVenugopal Iyer int i = 0;
9350dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL, *prev = NULL;
9360dc2366fSVenugopal Iyer dladm_stat_chain_t *curr;
9370dc2366fSVenugopal Iyer
9380dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) {
9390dc2366fSVenugopal Iyer warn("kstat_open operation failed");
9400dc2366fSVenugopal Iyer return (NULL);
9410dc2366fSVenugopal Iyer }
9420dc2366fSVenugopal Iyer
9430dc2366fSVenugopal Iyer for (i = 0; i < idlist_size; i++) {
9440dc2366fSVenugopal Iyer uint_t index = idlist[i];
9450dc2366fSVenugopal Iyer
9460dc2366fSVenugopal Iyer (void) snprintf(statname, sizeof (statname), "%s%d", prefix,
9470dc2366fSVenugopal Iyer index);
9480dc2366fSVenugopal Iyer
9490dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, modname, 0, statname, NULL);
9500dc2366fSVenugopal Iyer if (ksp == NULL)
9510dc2366fSVenugopal Iyer continue;
9520dc2366fSVenugopal Iyer
9530dc2366fSVenugopal Iyer curr = malloc(sizeof (dladm_stat_chain_t));
9540dc2366fSVenugopal Iyer if (curr == NULL)
9550dc2366fSVenugopal Iyer break;
9560dc2366fSVenugopal Iyer
9570dc2366fSVenugopal Iyer curr->dc_statentry = fn(kcp, ksp, index);
9580dc2366fSVenugopal Iyer if (curr->dc_statentry == NULL) {
9590dc2366fSVenugopal Iyer free(curr);
9600dc2366fSVenugopal Iyer break;
9610dc2366fSVenugopal Iyer }
9620dc2366fSVenugopal Iyer
9630dc2366fSVenugopal Iyer (void) strlcpy(curr->dc_statheader, statname,
9640dc2366fSVenugopal Iyer sizeof (curr->dc_statheader));
9650dc2366fSVenugopal Iyer curr->dc_next = NULL;
9660dc2366fSVenugopal Iyer
9670dc2366fSVenugopal Iyer if (head == NULL) /* First node */
9680dc2366fSVenugopal Iyer head = curr;
9690dc2366fSVenugopal Iyer else
9700dc2366fSVenugopal Iyer prev->dc_next = curr;
9710dc2366fSVenugopal Iyer
9720dc2366fSVenugopal Iyer prev = curr;
9730dc2366fSVenugopal Iyer }
9740dc2366fSVenugopal Iyer done:
9750dc2366fSVenugopal Iyer (void) kstat_close(kcp);
9760dc2366fSVenugopal Iyer return (head);
9770dc2366fSVenugopal Iyer }
9780dc2366fSVenugopal Iyer
9790dc2366fSVenugopal Iyer static misc_stat_entry_t *
i_dlstat_misc_stats(const char * linkname)9800dc2366fSVenugopal Iyer i_dlstat_misc_stats(const char *linkname)
9810dc2366fSVenugopal Iyer {
9820dc2366fSVenugopal Iyer kstat_ctl_t *kcp;
9830dc2366fSVenugopal Iyer kstat_t *ksp;
9840dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry = NULL;
9850dc2366fSVenugopal Iyer
9860dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL)
9870dc2366fSVenugopal Iyer return (NULL);
9880dc2366fSVenugopal Iyer
9890dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, linkname, 0, DLSTAT_MAC_MISC_STAT, NULL);
9900dc2366fSVenugopal Iyer if (ksp == NULL)
9910dc2366fSVenugopal Iyer goto done;
9920dc2366fSVenugopal Iyer
9930dc2366fSVenugopal Iyer misc_stat_entry = calloc(1, sizeof (misc_stat_entry_t));
9940dc2366fSVenugopal Iyer if (misc_stat_entry == NULL)
9950dc2366fSVenugopal Iyer goto done;
9960dc2366fSVenugopal Iyer
9970dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &misc_stat_entry->mse_stats,
9980dc2366fSVenugopal Iyer misc_stats_list, MISC_STAT_SIZE);
9990dc2366fSVenugopal Iyer done:
10000dc2366fSVenugopal Iyer (void) kstat_close(kcp);
10010dc2366fSVenugopal Iyer return (misc_stat_entry);
10020dc2366fSVenugopal Iyer }
10030dc2366fSVenugopal Iyer
10040dc2366fSVenugopal Iyer /* Rx lane statistic specific functions */
10050dc2366fSVenugopal Iyer static boolean_t
i_dlstat_rx_lane_match(void * arg1,void * arg2)10060dc2366fSVenugopal Iyer i_dlstat_rx_lane_match(void *arg1, void *arg2)
10070dc2366fSVenugopal Iyer {
10080dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s1 = arg1;
10090dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s2 = arg2;
10100dc2366fSVenugopal Iyer
10110dc2366fSVenugopal Iyer return (s1->rle_index == s2->rle_index &&
10120dc2366fSVenugopal Iyer s1->rle_id == s2->rle_id);
10130dc2366fSVenugopal Iyer }
10140dc2366fSVenugopal Iyer
10150dc2366fSVenugopal Iyer static void *
i_dlstat_rx_lane_stat_entry_diff(void * arg1,void * arg2)10160dc2366fSVenugopal Iyer i_dlstat_rx_lane_stat_entry_diff(void *arg1, void *arg2)
10170dc2366fSVenugopal Iyer {
10180dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s1 = arg1;
10190dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s2 = arg2;
10200dc2366fSVenugopal Iyer rx_lane_stat_entry_t *diff_entry;
10210dc2366fSVenugopal Iyer
10220dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (rx_lane_stat_entry_t));
10230dc2366fSVenugopal Iyer if (diff_entry == NULL)
10240dc2366fSVenugopal Iyer goto done;
10250dc2366fSVenugopal Iyer
10260dc2366fSVenugopal Iyer diff_entry->rle_index = s1->rle_index;
10270dc2366fSVenugopal Iyer diff_entry->rle_id = s1->rle_id;
10280dc2366fSVenugopal Iyer
10290dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, rle_stats, rx_lane_stats_list,
10300dc2366fSVenugopal Iyer RX_LANE_STAT_SIZE);
10310dc2366fSVenugopal Iyer
10320dc2366fSVenugopal Iyer done:
10330dc2366fSVenugopal Iyer return (diff_entry);
10340dc2366fSVenugopal Iyer }
10350dc2366fSVenugopal Iyer
10360dc2366fSVenugopal Iyer static void *
i_dlstat_rx_hwlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)10370dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
10380dc2366fSVenugopal Iyer {
10390dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
10400dc2366fSVenugopal Iyer
10410dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
10420dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL)
10430dc2366fSVenugopal Iyer goto done;
10440dc2366fSVenugopal Iyer
10450dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = i;
10460dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_HWLANE;
10470dc2366fSVenugopal Iyer
10480dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats,
10490dc2366fSVenugopal Iyer rx_hwlane_stats_list, RX_HWLANE_STAT_SIZE);
10500dc2366fSVenugopal Iyer
10510dc2366fSVenugopal Iyer done:
10520dc2366fSVenugopal Iyer return (rx_lane_stat_entry);
10530dc2366fSVenugopal Iyer }
10540dc2366fSVenugopal Iyer
10550dc2366fSVenugopal Iyer /*ARGSUSED*/
10560dc2366fSVenugopal Iyer static void *
i_dlstat_rx_swlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)10570dc2366fSVenugopal Iyer i_dlstat_rx_swlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
10580dc2366fSVenugopal Iyer {
10590dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
10600dc2366fSVenugopal Iyer
10610dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
10620dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL)
10630dc2366fSVenugopal Iyer goto done;
10640dc2366fSVenugopal Iyer
10650dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
10660dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_SWLANE;
10670dc2366fSVenugopal Iyer
10680dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats,
10690dc2366fSVenugopal Iyer rx_swlane_stats_list, RX_SWLANE_STAT_SIZE);
10700dc2366fSVenugopal Iyer
10710dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets =
10720dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs;
10730dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes =
10740dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrbytes;
10750dc2366fSVenugopal Iyer done:
10760dc2366fSVenugopal Iyer return (rx_lane_stat_entry);
10770dc2366fSVenugopal Iyer }
10780dc2366fSVenugopal Iyer
10790dc2366fSVenugopal Iyer /*ARGSUSED*/
10800dc2366fSVenugopal Iyer static void *
i_dlstat_rx_local_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)10810dc2366fSVenugopal Iyer i_dlstat_rx_local_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
10820dc2366fSVenugopal Iyer {
10830dc2366fSVenugopal Iyer rx_lane_stat_entry_t *local_stat_entry;
10840dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
10850dc2366fSVenugopal Iyer
10860dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
10870dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL)
10880dc2366fSVenugopal Iyer goto done;
10890dc2366fSVenugopal Iyer
10900dc2366fSVenugopal Iyer local_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
10910dc2366fSVenugopal Iyer if (local_stat_entry == NULL)
10920dc2366fSVenugopal Iyer goto done;
10930dc2366fSVenugopal Iyer
10940dc2366fSVenugopal Iyer local_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
10950dc2366fSVenugopal Iyer local_stat_entry->rle_id = L_LOCAL;
10960dc2366fSVenugopal Iyer
10970dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_lane_stat_entry->rle_stats,
10980dc2366fSVenugopal Iyer rx_swlane_stats_list, RX_SWLANE_STAT_SIZE);
10990dc2366fSVenugopal Iyer
11000dc2366fSVenugopal Iyer local_stat_entry->rle_stats.rl_ipackets =
11010dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_lclpackets;
11020dc2366fSVenugopal Iyer local_stat_entry->rle_stats.rl_rbytes =
11030dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_lclbytes;
11040dc2366fSVenugopal Iyer
11050dc2366fSVenugopal Iyer done:
11060dc2366fSVenugopal Iyer free(rx_lane_stat_entry);
11070dc2366fSVenugopal Iyer return (local_stat_entry);
11080dc2366fSVenugopal Iyer }
11090dc2366fSVenugopal Iyer
11100dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_rx_local_stats(const char * linkname)11110dc2366fSVenugopal Iyer i_dlstat_rx_local_stats(const char *linkname)
11120dc2366fSVenugopal Iyer {
11130dc2366fSVenugopal Iyer dladm_stat_chain_t *local_stats = NULL;
11140dc2366fSVenugopal Iyer
11150dc2366fSVenugopal Iyer local_stats = i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_SWLANE,
11160dc2366fSVenugopal Iyer default_idlist, default_idlist_size,
11170dc2366fSVenugopal Iyer i_dlstat_rx_local_retrieve_stat);
11180dc2366fSVenugopal Iyer
11190dc2366fSVenugopal Iyer if (local_stats != NULL) {
11200dc2366fSVenugopal Iyer (void) strlcpy(local_stats->dc_statheader, "mac_rx_local",
11210dc2366fSVenugopal Iyer sizeof (local_stats->dc_statheader));
11220dc2366fSVenugopal Iyer }
11230dc2366fSVenugopal Iyer return (local_stats);
11240dc2366fSVenugopal Iyer }
11250dc2366fSVenugopal Iyer
11260dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_rx_bcast_stats(const char * linkname)11270dc2366fSVenugopal Iyer i_dlstat_rx_bcast_stats(const char *linkname)
11280dc2366fSVenugopal Iyer {
11290dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry;
11300dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
11310dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
11320dc2366fSVenugopal Iyer
11330dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname);
11340dc2366fSVenugopal Iyer if (misc_stat_entry == NULL)
11350dc2366fSVenugopal Iyer goto done;
11360dc2366fSVenugopal Iyer
11370dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
11380dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL)
11390dc2366fSVenugopal Iyer goto done;
11400dc2366fSVenugopal Iyer
11410dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
11420dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_BCAST;
11430dc2366fSVenugopal Iyer
11440dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets =
11450dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstrcv +
11460dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multircv;
11470dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs =
11480dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstrcv +
11490dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multircv;
11500dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes =
11510dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstrcvbytes +
11520dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multircvbytes;
11530dc2366fSVenugopal Iyer
11540dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
11550dc2366fSVenugopal Iyer if (head == NULL) {
11560dc2366fSVenugopal Iyer free(rx_lane_stat_entry);
11570dc2366fSVenugopal Iyer goto done;
11580dc2366fSVenugopal Iyer }
11590dc2366fSVenugopal Iyer
11600dc2366fSVenugopal Iyer head->dc_statentry = rx_lane_stat_entry;
11610dc2366fSVenugopal Iyer head->dc_next = NULL;
11620dc2366fSVenugopal Iyer
11630dc2366fSVenugopal Iyer free(misc_stat_entry);
11640dc2366fSVenugopal Iyer done:
11650dc2366fSVenugopal Iyer return (head);
11660dc2366fSVenugopal Iyer }
11670dc2366fSVenugopal Iyer
11680dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_rx_defunctlane_stats(const char * linkname)11690dc2366fSVenugopal Iyer i_dlstat_rx_defunctlane_stats(const char *linkname)
11700dc2366fSVenugopal Iyer {
11710dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry;
11720dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
11730dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
11740dc2366fSVenugopal Iyer
11750dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname);
11760dc2366fSVenugopal Iyer if (misc_stat_entry == NULL)
11770dc2366fSVenugopal Iyer goto done;
11780dc2366fSVenugopal Iyer
11790dc2366fSVenugopal Iyer rx_lane_stat_entry = calloc(1, sizeof (rx_lane_stat_entry_t));
11800dc2366fSVenugopal Iyer if (rx_lane_stat_entry == NULL)
11810dc2366fSVenugopal Iyer goto done;
11820dc2366fSVenugopal Iyer
11830dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_index = DLSTAT_INVALID_ENTRY;
11840dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_id = L_DFNCT;
11850dc2366fSVenugopal Iyer
11860dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets =
11870dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_ipackets;
11880dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes =
11890dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_rbytes;
11900dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_intrs =
11910dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_intrs;
11920dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_polls =
11930dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_polls;
11940dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_sdrops =
11950dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_rxsdrops;
11960dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_chl10 =
11970dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_chainunder10;
11980dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ch10_50 =
11990dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_chain10to50;
12000dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_chg50 =
12010dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_chainover50;
12020dc2366fSVenugopal Iyer
12030dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
12040dc2366fSVenugopal Iyer if (head == NULL) {
12050dc2366fSVenugopal Iyer free(rx_lane_stat_entry);
12060dc2366fSVenugopal Iyer goto done;
12070dc2366fSVenugopal Iyer }
12080dc2366fSVenugopal Iyer
12090dc2366fSVenugopal Iyer head->dc_statentry = rx_lane_stat_entry;
12100dc2366fSVenugopal Iyer head->dc_next = NULL;
12110dc2366fSVenugopal Iyer
12120dc2366fSVenugopal Iyer done:
12130dc2366fSVenugopal Iyer return (head);
12140dc2366fSVenugopal Iyer }
12150dc2366fSVenugopal Iyer
12160dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_rx_hwlane_stats(const char * linkname)12170dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_stats(const char *linkname)
12180dc2366fSVenugopal Iyer {
12190dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist[MAX_RINGS_PER_GROUP];
12200dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist_size;
12210dc2366fSVenugopal Iyer
12220dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_RX_HWLANE_IDLIST,
12230dc2366fSVenugopal Iyer rx_hwlane_idlist, &rx_hwlane_idlist_size);
12240dc2366fSVenugopal Iyer
12250dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_HWLANE,
12260dc2366fSVenugopal Iyer rx_hwlane_idlist, rx_hwlane_idlist_size,
12270dc2366fSVenugopal Iyer i_dlstat_rx_hwlane_retrieve_stat));
12280dc2366fSVenugopal Iyer }
12290dc2366fSVenugopal Iyer
12300dc2366fSVenugopal Iyer /*ARGSUSED*/
12310dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_rx_swlane_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)12320dc2366fSVenugopal Iyer i_dlstat_rx_swlane_stats(dladm_handle_t dh, datalink_id_t linkid,
12330dc2366fSVenugopal Iyer const char *linkname)
12340dc2366fSVenugopal Iyer {
12350dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_RX_SWLANE,
12360dc2366fSVenugopal Iyer default_idlist, default_idlist_size,
12370dc2366fSVenugopal Iyer i_dlstat_rx_swlane_retrieve_stat));
12380dc2366fSVenugopal Iyer }
12390dc2366fSVenugopal Iyer
12400dc2366fSVenugopal Iyer void *
dlstat_rx_lane_stats(dladm_handle_t dh,datalink_id_t linkid)12410dc2366fSVenugopal Iyer dlstat_rx_lane_stats(dladm_handle_t dh, datalink_id_t linkid)
12420dc2366fSVenugopal Iyer {
12430dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
12440dc2366fSVenugopal Iyer dladm_stat_chain_t *local_stats = NULL;
12450dc2366fSVenugopal Iyer dladm_stat_chain_t *bcast_stats = NULL;
12460dc2366fSVenugopal Iyer dladm_stat_chain_t *defunctlane_stats = NULL;
12470dc2366fSVenugopal Iyer dladm_stat_chain_t *lane_stats = NULL;
12480dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
12490dc2366fSVenugopal Iyer boolean_t is_legacy_driver;
12500dc2366fSVenugopal Iyer
12510dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
12520dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
12530dc2366fSVenugopal Iyer goto done;
12540dc2366fSVenugopal Iyer }
12550dc2366fSVenugopal Iyer
12560dc2366fSVenugopal Iyer /* Check if it is legacy driver */
12570dc2366fSVenugopal Iyer if (dladm_linkprop_is_set(dh, linkid, DLADM_PROP_VAL_CURRENT,
12580dc2366fSVenugopal Iyer "_softmac", &is_legacy_driver) != DLADM_STATUS_OK) {
12590dc2366fSVenugopal Iyer goto done;
12600dc2366fSVenugopal Iyer }
12610dc2366fSVenugopal Iyer
12620dc2366fSVenugopal Iyer if (is_legacy_driver) {
12630dc2366fSVenugopal Iyer head = i_dlstat_legacy_rx_lane_stats(linkname);
12640dc2366fSVenugopal Iyer goto done;
12650dc2366fSVenugopal Iyer }
12660dc2366fSVenugopal Iyer
12670dc2366fSVenugopal Iyer local_stats = i_dlstat_rx_local_stats(linkname);
12680dc2366fSVenugopal Iyer bcast_stats = i_dlstat_rx_bcast_stats(linkname);
12690dc2366fSVenugopal Iyer defunctlane_stats = i_dlstat_rx_defunctlane_stats(linkname);
12700dc2366fSVenugopal Iyer lane_stats = i_dlstat_rx_hwlane_stats(linkname);
12710dc2366fSVenugopal Iyer if (lane_stats == NULL)
12720dc2366fSVenugopal Iyer lane_stats = i_dlstat_rx_swlane_stats(dh, linkid, linkname);
12730dc2366fSVenugopal Iyer
12740dc2366fSVenugopal Iyer head = i_dlstat_join_lists(local_stats, bcast_stats);
12750dc2366fSVenugopal Iyer head = i_dlstat_join_lists(head, defunctlane_stats);
12760dc2366fSVenugopal Iyer head = i_dlstat_join_lists(head, lane_stats);
12770dc2366fSVenugopal Iyer done:
12780dc2366fSVenugopal Iyer return (head);
12790dc2366fSVenugopal Iyer }
12800dc2366fSVenugopal Iyer
12810dc2366fSVenugopal Iyer /* Tx lane statistic specific functions */
12820dc2366fSVenugopal Iyer static boolean_t
i_dlstat_tx_lane_match(void * arg1,void * arg2)12830dc2366fSVenugopal Iyer i_dlstat_tx_lane_match(void *arg1, void *arg2)
12840dc2366fSVenugopal Iyer {
12850dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s1 = arg1;
12860dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s2 = arg2;
12870dc2366fSVenugopal Iyer
12880dc2366fSVenugopal Iyer return (s1->tle_index == s2->tle_index &&
12890dc2366fSVenugopal Iyer s1->tle_id == s2->tle_id);
12900dc2366fSVenugopal Iyer }
12910dc2366fSVenugopal Iyer
12920dc2366fSVenugopal Iyer static void *
i_dlstat_tx_lane_stat_entry_diff(void * arg1,void * arg2)12930dc2366fSVenugopal Iyer i_dlstat_tx_lane_stat_entry_diff(void *arg1, void *arg2)
12940dc2366fSVenugopal Iyer {
12950dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s1 = arg1;
12960dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s2 = arg2;
12970dc2366fSVenugopal Iyer tx_lane_stat_entry_t *diff_entry;
12980dc2366fSVenugopal Iyer
12990dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (tx_lane_stat_entry_t));
13000dc2366fSVenugopal Iyer if (diff_entry == NULL)
13010dc2366fSVenugopal Iyer goto done;
13020dc2366fSVenugopal Iyer
13030dc2366fSVenugopal Iyer diff_entry->tle_index = s1->tle_index;
13040dc2366fSVenugopal Iyer diff_entry->tle_id = s1->tle_id;
13050dc2366fSVenugopal Iyer
13060dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, tle_stats, tx_lane_stats_list,
13070dc2366fSVenugopal Iyer TX_LANE_STAT_SIZE);
13080dc2366fSVenugopal Iyer
13090dc2366fSVenugopal Iyer done:
13100dc2366fSVenugopal Iyer return (diff_entry);
13110dc2366fSVenugopal Iyer }
13120dc2366fSVenugopal Iyer
13130dc2366fSVenugopal Iyer static void *
i_dlstat_tx_hwlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)13140dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
13150dc2366fSVenugopal Iyer {
13160dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry;
13170dc2366fSVenugopal Iyer
13180dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
13190dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL)
13200dc2366fSVenugopal Iyer goto done;
13210dc2366fSVenugopal Iyer
13220dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = i;
13230dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_HWLANE;
13240dc2366fSVenugopal Iyer
13250dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &tx_lane_stat_entry->tle_stats,
13260dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE);
13270dc2366fSVenugopal Iyer
13280dc2366fSVenugopal Iyer done:
13290dc2366fSVenugopal Iyer return (tx_lane_stat_entry);
13300dc2366fSVenugopal Iyer }
13310dc2366fSVenugopal Iyer
13320dc2366fSVenugopal Iyer /*ARGSUSED*/
13330dc2366fSVenugopal Iyer static void *
i_dlstat_tx_swlane_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)13340dc2366fSVenugopal Iyer i_dlstat_tx_swlane_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
13350dc2366fSVenugopal Iyer {
13360dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry;
13370dc2366fSVenugopal Iyer
13380dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
13390dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL)
13400dc2366fSVenugopal Iyer goto done;
13410dc2366fSVenugopal Iyer
13420dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
13430dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_SWLANE;
13440dc2366fSVenugopal Iyer
13450dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &tx_lane_stat_entry->tle_stats,
13460dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE);
13470dc2366fSVenugopal Iyer
13480dc2366fSVenugopal Iyer done:
13490dc2366fSVenugopal Iyer return (tx_lane_stat_entry);
13500dc2366fSVenugopal Iyer }
13510dc2366fSVenugopal Iyer
13520dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_tx_bcast_stats(const char * linkname)13530dc2366fSVenugopal Iyer i_dlstat_tx_bcast_stats(const char *linkname)
13540dc2366fSVenugopal Iyer {
13550dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry;
13560dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
13570dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry;
13580dc2366fSVenugopal Iyer
13590dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname);
13600dc2366fSVenugopal Iyer if (misc_stat_entry == NULL)
13610dc2366fSVenugopal Iyer goto done;
13620dc2366fSVenugopal Iyer
13630dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
13640dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL)
13650dc2366fSVenugopal Iyer goto done;
13660dc2366fSVenugopal Iyer
13670dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
13680dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_BCAST;
13690dc2366fSVenugopal Iyer
13700dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets =
13710dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstxmt +
13720dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multixmt;
13730dc2366fSVenugopal Iyer
13740dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes =
13750dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_brdcstxmtbytes +
13760dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_multixmtbytes;
13770dc2366fSVenugopal Iyer
13780dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
13790dc2366fSVenugopal Iyer if (head == NULL) {
13800dc2366fSVenugopal Iyer free(tx_lane_stat_entry);
13810dc2366fSVenugopal Iyer goto done;
13820dc2366fSVenugopal Iyer }
13830dc2366fSVenugopal Iyer
13840dc2366fSVenugopal Iyer head->dc_statentry = tx_lane_stat_entry;
13850dc2366fSVenugopal Iyer head->dc_next = NULL;
13860dc2366fSVenugopal Iyer
13870dc2366fSVenugopal Iyer free(misc_stat_entry);
13880dc2366fSVenugopal Iyer done:
13890dc2366fSVenugopal Iyer return (head);
13900dc2366fSVenugopal Iyer }
13910dc2366fSVenugopal Iyer
13920dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_tx_defunctlane_stats(const char * linkname)13930dc2366fSVenugopal Iyer i_dlstat_tx_defunctlane_stats(const char *linkname)
13940dc2366fSVenugopal Iyer {
13950dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry;
13960dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
13970dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry;
13980dc2366fSVenugopal Iyer
13990dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname);
14000dc2366fSVenugopal Iyer if (misc_stat_entry == NULL)
14010dc2366fSVenugopal Iyer goto done;
14020dc2366fSVenugopal Iyer
14030dc2366fSVenugopal Iyer tx_lane_stat_entry = calloc(1, sizeof (tx_lane_stat_entry_t));
14040dc2366fSVenugopal Iyer if (tx_lane_stat_entry == NULL)
14050dc2366fSVenugopal Iyer goto done;
14060dc2366fSVenugopal Iyer
14070dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_index = DLSTAT_INVALID_ENTRY;
14080dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_id = L_DFNCT;
14090dc2366fSVenugopal Iyer
14100dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets =
14110dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_opackets;
14120dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes =
14130dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_obytes;
14140dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_sdrops =
14150dc2366fSVenugopal Iyer misc_stat_entry->mse_stats.ms_txsdrops;
14160dc2366fSVenugopal Iyer
14170dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
14180dc2366fSVenugopal Iyer if (head == NULL) {
14190dc2366fSVenugopal Iyer free(tx_lane_stat_entry);
14200dc2366fSVenugopal Iyer goto done;
14210dc2366fSVenugopal Iyer }
14220dc2366fSVenugopal Iyer
14230dc2366fSVenugopal Iyer head->dc_statentry = tx_lane_stat_entry;
14240dc2366fSVenugopal Iyer head->dc_next = NULL;
14250dc2366fSVenugopal Iyer
14260dc2366fSVenugopal Iyer done:
14270dc2366fSVenugopal Iyer return (head);
14280dc2366fSVenugopal Iyer }
14290dc2366fSVenugopal Iyer
14300dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_tx_hwlane_stats(const char * linkname)14310dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_stats(const char *linkname)
14320dc2366fSVenugopal Iyer {
14330dc2366fSVenugopal Iyer uint_t tx_hwlane_idlist[MAX_RINGS_PER_GROUP];
14340dc2366fSVenugopal Iyer uint_t tx_hwlane_idlist_size;
14350dc2366fSVenugopal Iyer
14360dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_TX_HWLANE_IDLIST,
14370dc2366fSVenugopal Iyer tx_hwlane_idlist, &tx_hwlane_idlist_size);
14380dc2366fSVenugopal Iyer
14390dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_TX_HWLANE,
14400dc2366fSVenugopal Iyer tx_hwlane_idlist, tx_hwlane_idlist_size,
14410dc2366fSVenugopal Iyer i_dlstat_tx_hwlane_retrieve_stat));
14420dc2366fSVenugopal Iyer }
14430dc2366fSVenugopal Iyer
14440dc2366fSVenugopal Iyer /*ARGSUSED*/
14450dc2366fSVenugopal Iyer static dladm_stat_chain_t *
i_dlstat_tx_swlane_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)14460dc2366fSVenugopal Iyer i_dlstat_tx_swlane_stats(dladm_handle_t dh, datalink_id_t linkid,
14470dc2366fSVenugopal Iyer const char *linkname)
14480dc2366fSVenugopal Iyer {
14490dc2366fSVenugopal Iyer return (i_dlstat_query_stats(linkname, DLSTAT_MAC_TX_SWLANE,
14500dc2366fSVenugopal Iyer default_idlist, default_idlist_size,
14510dc2366fSVenugopal Iyer i_dlstat_tx_swlane_retrieve_stat));
14520dc2366fSVenugopal Iyer }
14530dc2366fSVenugopal Iyer
14540dc2366fSVenugopal Iyer void *
dlstat_tx_lane_stats(dladm_handle_t dh,datalink_id_t linkid)14550dc2366fSVenugopal Iyer dlstat_tx_lane_stats(dladm_handle_t dh, datalink_id_t linkid)
14560dc2366fSVenugopal Iyer {
14570dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
14580dc2366fSVenugopal Iyer dladm_stat_chain_t *bcast_stats = NULL;
14590dc2366fSVenugopal Iyer dladm_stat_chain_t *defunctlane_stats = NULL;
14600dc2366fSVenugopal Iyer dladm_stat_chain_t *lane_stats;
14610dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
14620dc2366fSVenugopal Iyer boolean_t is_legacy_driver;
14630dc2366fSVenugopal Iyer
14640dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
14650dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
14660dc2366fSVenugopal Iyer goto done;
14670dc2366fSVenugopal Iyer }
14680dc2366fSVenugopal Iyer
14690dc2366fSVenugopal Iyer /* Check if it is legacy driver */
14700dc2366fSVenugopal Iyer if (dladm_linkprop_is_set(dh, linkid, DLADM_PROP_VAL_CURRENT,
14710dc2366fSVenugopal Iyer "_softmac", &is_legacy_driver) != DLADM_STATUS_OK) {
14720dc2366fSVenugopal Iyer goto done;
14730dc2366fSVenugopal Iyer }
14740dc2366fSVenugopal Iyer
14750dc2366fSVenugopal Iyer if (is_legacy_driver) {
14760dc2366fSVenugopal Iyer head = i_dlstat_legacy_tx_lane_stats(linkname);
14770dc2366fSVenugopal Iyer goto done;
14780dc2366fSVenugopal Iyer }
14790dc2366fSVenugopal Iyer
14800dc2366fSVenugopal Iyer bcast_stats = i_dlstat_tx_bcast_stats(linkname);
14810dc2366fSVenugopal Iyer defunctlane_stats = i_dlstat_tx_defunctlane_stats(linkname);
14820dc2366fSVenugopal Iyer lane_stats = i_dlstat_tx_hwlane_stats(linkname);
14830dc2366fSVenugopal Iyer if (lane_stats == NULL)
14840dc2366fSVenugopal Iyer lane_stats = i_dlstat_tx_swlane_stats(dh, linkid, linkname);
14850dc2366fSVenugopal Iyer
14860dc2366fSVenugopal Iyer head = i_dlstat_join_lists(bcast_stats, defunctlane_stats);
14870dc2366fSVenugopal Iyer head = i_dlstat_join_lists(head, lane_stats);
14880dc2366fSVenugopal Iyer
14890dc2366fSVenugopal Iyer done:
14900dc2366fSVenugopal Iyer return (head);
14910dc2366fSVenugopal Iyer }
14920dc2366fSVenugopal Iyer
14930dc2366fSVenugopal Iyer /* Rx lane total statistic specific functions */
14940dc2366fSVenugopal Iyer void *
dlstat_rx_lane_total_stats(dladm_handle_t dh,datalink_id_t linkid)14950dc2366fSVenugopal Iyer dlstat_rx_lane_total_stats(dladm_handle_t dh, datalink_id_t linkid)
14960dc2366fSVenugopal Iyer {
14970dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL;
14980dc2366fSVenugopal Iyer dladm_stat_chain_t *rx_lane_head, *curr;
14990dc2366fSVenugopal Iyer rx_lane_stat_entry_t *total_stats;
15000dc2366fSVenugopal Iyer
15010dc2366fSVenugopal Iyer /* Get per rx lane stats */
15020dc2366fSVenugopal Iyer rx_lane_head = dlstat_rx_lane_stats(dh, linkid);
15030dc2366fSVenugopal Iyer if (rx_lane_head == NULL)
15040dc2366fSVenugopal Iyer goto done;
15050dc2366fSVenugopal Iyer
15060dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (rx_lane_stat_entry_t));
15070dc2366fSVenugopal Iyer if (total_stats == NULL)
15080dc2366fSVenugopal Iyer goto done;
15090dc2366fSVenugopal Iyer
15100dc2366fSVenugopal Iyer total_stats->rle_index = DLSTAT_INVALID_ENTRY;
15110dc2366fSVenugopal Iyer total_stats->rle_id = DLSTAT_INVALID_ENTRY;
15120dc2366fSVenugopal Iyer
15130dc2366fSVenugopal Iyer for (curr = rx_lane_head; curr != NULL; curr = curr->dc_next) {
15140dc2366fSVenugopal Iyer rx_lane_stat_entry_t *curr_lane_stats = curr->dc_statentry;
15150dc2366fSVenugopal Iyer
15160dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->rle_stats,
15170dc2366fSVenugopal Iyer &curr_lane_stats->rle_stats, &total_stats->rle_stats,
15180dc2366fSVenugopal Iyer rx_lane_stats_list, RX_LANE_STAT_SIZE);
15190dc2366fSVenugopal Iyer }
15200dc2366fSVenugopal Iyer
15210dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t));
15220dc2366fSVenugopal Iyer if (total_head == NULL) {
15230dc2366fSVenugopal Iyer free(total_stats);
15240dc2366fSVenugopal Iyer goto done;
15250dc2366fSVenugopal Iyer }
15260dc2366fSVenugopal Iyer
15270dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats;
15280dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_rx_lane_total",
15290dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader));
15300dc2366fSVenugopal Iyer total_head->dc_next = NULL;
15310dc2366fSVenugopal Iyer free(rx_lane_head);
15320dc2366fSVenugopal Iyer
15330dc2366fSVenugopal Iyer done:
15340dc2366fSVenugopal Iyer return (total_head);
15350dc2366fSVenugopal Iyer }
15360dc2366fSVenugopal Iyer
15370dc2366fSVenugopal Iyer /* Tx lane total statistic specific functions */
15380dc2366fSVenugopal Iyer void *
dlstat_tx_lane_total_stats(dladm_handle_t dh,datalink_id_t linkid)15390dc2366fSVenugopal Iyer dlstat_tx_lane_total_stats(dladm_handle_t dh, datalink_id_t linkid)
15400dc2366fSVenugopal Iyer {
15410dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL;
15420dc2366fSVenugopal Iyer dladm_stat_chain_t *tx_lane_head, *curr;
15430dc2366fSVenugopal Iyer tx_lane_stat_entry_t *total_stats;
15440dc2366fSVenugopal Iyer
15450dc2366fSVenugopal Iyer /* Get per tx lane stats */
15460dc2366fSVenugopal Iyer tx_lane_head = dlstat_tx_lane_stats(dh, linkid);
15470dc2366fSVenugopal Iyer if (tx_lane_head == NULL)
15480dc2366fSVenugopal Iyer goto done;
15490dc2366fSVenugopal Iyer
15500dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (tx_lane_stat_entry_t));
15510dc2366fSVenugopal Iyer if (total_stats == NULL)
15520dc2366fSVenugopal Iyer goto done;
15530dc2366fSVenugopal Iyer
15540dc2366fSVenugopal Iyer total_stats->tle_index = DLSTAT_INVALID_ENTRY;
15550dc2366fSVenugopal Iyer total_stats->tle_id = DLSTAT_INVALID_ENTRY;
15560dc2366fSVenugopal Iyer
15570dc2366fSVenugopal Iyer for (curr = tx_lane_head; curr != NULL; curr = curr->dc_next) {
15580dc2366fSVenugopal Iyer tx_lane_stat_entry_t *curr_lane_stats = curr->dc_statentry;
15590dc2366fSVenugopal Iyer
15600dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->tle_stats,
15610dc2366fSVenugopal Iyer &curr_lane_stats->tle_stats, &total_stats->tle_stats,
15620dc2366fSVenugopal Iyer tx_lane_stats_list, TX_LANE_STAT_SIZE);
15630dc2366fSVenugopal Iyer }
15640dc2366fSVenugopal Iyer
15650dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t));
15660dc2366fSVenugopal Iyer if (total_head == NULL) {
15670dc2366fSVenugopal Iyer free(total_stats);
15680dc2366fSVenugopal Iyer goto done;
15690dc2366fSVenugopal Iyer }
15700dc2366fSVenugopal Iyer
15710dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats;
15720dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_tx_lane_total",
15730dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader));
15740dc2366fSVenugopal Iyer total_head->dc_next = NULL;
15750dc2366fSVenugopal Iyer free(tx_lane_head);
15760dc2366fSVenugopal Iyer
15770dc2366fSVenugopal Iyer done:
15780dc2366fSVenugopal Iyer return (total_head);
15790dc2366fSVenugopal Iyer }
15800dc2366fSVenugopal Iyer
15810dc2366fSVenugopal Iyer /* Fanout specific functions */
15820dc2366fSVenugopal Iyer static boolean_t
i_dlstat_fanout_match(void * arg1,void * arg2)15830dc2366fSVenugopal Iyer i_dlstat_fanout_match(void *arg1, void *arg2)
15840dc2366fSVenugopal Iyer {
15850dc2366fSVenugopal Iyer fanout_stat_entry_t *s1 = arg1;
15860dc2366fSVenugopal Iyer fanout_stat_entry_t *s2 = arg2;
15870dc2366fSVenugopal Iyer
15880dc2366fSVenugopal Iyer return (s1->fe_index == s2->fe_index &&
15890dc2366fSVenugopal Iyer s1->fe_id == s2->fe_id &&
15900dc2366fSVenugopal Iyer s1->fe_foutindex == s2->fe_foutindex);
15910dc2366fSVenugopal Iyer }
15920dc2366fSVenugopal Iyer
15930dc2366fSVenugopal Iyer static void *
i_dlstat_fanout_stat_entry_diff(void * arg1,void * arg2)15940dc2366fSVenugopal Iyer i_dlstat_fanout_stat_entry_diff(void *arg1, void *arg2)
15950dc2366fSVenugopal Iyer {
15960dc2366fSVenugopal Iyer fanout_stat_entry_t *s1 = arg1;
15970dc2366fSVenugopal Iyer fanout_stat_entry_t *s2 = arg2;
15980dc2366fSVenugopal Iyer fanout_stat_entry_t *diff_entry;
15990dc2366fSVenugopal Iyer
16000dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (fanout_stat_entry_t));
16010dc2366fSVenugopal Iyer if (diff_entry == NULL)
16020dc2366fSVenugopal Iyer goto done;
16030dc2366fSVenugopal Iyer
16040dc2366fSVenugopal Iyer diff_entry->fe_index = s1->fe_index;
16050dc2366fSVenugopal Iyer diff_entry->fe_id = s1->fe_id;
16060dc2366fSVenugopal Iyer diff_entry->fe_foutindex = s1->fe_foutindex;
16070dc2366fSVenugopal Iyer
16080dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, fe_stats, fanout_stats_list,
16090dc2366fSVenugopal Iyer FANOUT_STAT_SIZE);
16100dc2366fSVenugopal Iyer
16110dc2366fSVenugopal Iyer done:
16120dc2366fSVenugopal Iyer return (diff_entry);
16130dc2366fSVenugopal Iyer }
16140dc2366fSVenugopal Iyer
16150dc2366fSVenugopal Iyer static void *
i_dlstat_fanout_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)16160dc2366fSVenugopal Iyer i_dlstat_fanout_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
16170dc2366fSVenugopal Iyer {
16180dc2366fSVenugopal Iyer fanout_stat_entry_t *fanout_stat_entry;
16190dc2366fSVenugopal Iyer
16200dc2366fSVenugopal Iyer fanout_stat_entry = calloc(1, sizeof (fanout_stat_entry_t));
16210dc2366fSVenugopal Iyer if (fanout_stat_entry == NULL)
16220dc2366fSVenugopal Iyer goto done;
16230dc2366fSVenugopal Iyer
16240dc2366fSVenugopal Iyer /* Set by the caller later */
16250dc2366fSVenugopal Iyer fanout_stat_entry->fe_index = DLSTAT_INVALID_ENTRY;
16260dc2366fSVenugopal Iyer fanout_stat_entry->fe_id = DLSTAT_INVALID_ENTRY;
16270dc2366fSVenugopal Iyer
16280dc2366fSVenugopal Iyer fanout_stat_entry->fe_foutindex = i;
16290dc2366fSVenugopal Iyer
16300dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &fanout_stat_entry->fe_stats,
16310dc2366fSVenugopal Iyer fanout_stats_list, FANOUT_STAT_SIZE);
16320dc2366fSVenugopal Iyer
16330dc2366fSVenugopal Iyer done:
16340dc2366fSVenugopal Iyer return (fanout_stat_entry);
16350dc2366fSVenugopal Iyer }
16360dc2366fSVenugopal Iyer
16370dc2366fSVenugopal 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)16380dc2366fSVenugopal Iyer i_dlstat_query_fanout_stats(dladm_handle_t dh, datalink_id_t linkid,
16390dc2366fSVenugopal Iyer uint_t idlist[], uint_t idlist_size,
16400dc2366fSVenugopal Iyer const char *modname, const char *prefix)
16410dc2366fSVenugopal Iyer {
16420dc2366fSVenugopal Iyer int i;
16430dc2366fSVenugopal Iyer char statprefix[MAXLINKNAMELEN];
16440dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
16450dc2366fSVenugopal Iyer dladm_stat_chain_t *curr, *curr_head;
16460dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL, *prev = NULL;
16470dc2366fSVenugopal Iyer uint_t fanout_idlist[MAX_RINGS_PER_GROUP];
16480dc2366fSVenugopal Iyer uint_t fanout_idlist_size;
16490dc2366fSVenugopal Iyer
16500dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
16510dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
16520dc2366fSVenugopal Iyer return (NULL);
16530dc2366fSVenugopal Iyer }
16540dc2366fSVenugopal Iyer
16550dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_FANOUT_IDLIST,
16560dc2366fSVenugopal Iyer fanout_idlist, &fanout_idlist_size);
16570dc2366fSVenugopal Iyer
16580dc2366fSVenugopal Iyer for (i = 0; i < idlist_size; i++) {
16590dc2366fSVenugopal Iyer uint_t index = idlist[i];
16600dc2366fSVenugopal Iyer
16610dc2366fSVenugopal Iyer (void) snprintf(statprefix, sizeof (statprefix), "%s%d_fanout",
16620dc2366fSVenugopal Iyer prefix, index);
16630dc2366fSVenugopal Iyer
16640dc2366fSVenugopal Iyer curr_head = i_dlstat_query_stats(modname, statprefix,
16650dc2366fSVenugopal Iyer fanout_idlist, fanout_idlist_size,
16660dc2366fSVenugopal Iyer i_dlstat_fanout_retrieve_stat);
16670dc2366fSVenugopal Iyer
16680dc2366fSVenugopal Iyer if (curr_head == NULL) /* Last lane */
16690dc2366fSVenugopal Iyer break;
16700dc2366fSVenugopal Iyer
16710dc2366fSVenugopal Iyer if (head == NULL) /* First lane */
16720dc2366fSVenugopal Iyer head = curr_head;
16730dc2366fSVenugopal Iyer else /* Link new lane list to end of previous lane list */
16740dc2366fSVenugopal Iyer prev->dc_next = curr_head;
16750dc2366fSVenugopal Iyer
16760dc2366fSVenugopal Iyer /* Walk new lane list and set ids */
16770dc2366fSVenugopal Iyer for (curr = curr_head; curr != NULL; curr = curr->dc_next) {
16780dc2366fSVenugopal Iyer fanout_stat_entry_t *curr_stats = curr->dc_statentry;
16790dc2366fSVenugopal Iyer
16800dc2366fSVenugopal Iyer curr_stats->fe_index = index;
16810dc2366fSVenugopal Iyer curr_stats->fe_id = L_HWLANE;
16820dc2366fSVenugopal Iyer /*
16830dc2366fSVenugopal Iyer * Save last pointer of previous linked list.
16840dc2366fSVenugopal Iyer * This pointer is used to chain linked lists
16850dc2366fSVenugopal Iyer * generated in each iteration.
16860dc2366fSVenugopal Iyer */
16870dc2366fSVenugopal Iyer prev = curr;
16880dc2366fSVenugopal Iyer }
16890dc2366fSVenugopal Iyer }
16900dc2366fSVenugopal Iyer
16910dc2366fSVenugopal Iyer return (head);
16920dc2366fSVenugopal Iyer }
16930dc2366fSVenugopal Iyer
16940dc2366fSVenugopal Iyer void *
dlstat_fanout_swlane_and_local_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)16950dc2366fSVenugopal Iyer dlstat_fanout_swlane_and_local_stats(dladm_handle_t dh, datalink_id_t linkid,
16960dc2366fSVenugopal Iyer const char *linkname)
16970dc2366fSVenugopal Iyer {
16980dc2366fSVenugopal Iyer return (i_dlstat_query_fanout_stats(dh, linkid,
16990dc2366fSVenugopal Iyer default_idlist, default_idlist_size, linkname,
17000dc2366fSVenugopal Iyer DLSTAT_MAC_RX_SWLANE));
17010dc2366fSVenugopal Iyer }
17020dc2366fSVenugopal Iyer
17030dc2366fSVenugopal Iyer void *
dlstat_fanout_hwlane_stats(dladm_handle_t dh,datalink_id_t linkid,const char * linkname)17040dc2366fSVenugopal Iyer dlstat_fanout_hwlane_stats(dladm_handle_t dh, datalink_id_t linkid,
17050dc2366fSVenugopal Iyer const char *linkname)
17060dc2366fSVenugopal Iyer {
17070dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist[MAX_RINGS_PER_GROUP];
17080dc2366fSVenugopal Iyer uint_t rx_hwlane_idlist_size;
17090dc2366fSVenugopal Iyer
17100dc2366fSVenugopal Iyer i_dlstat_get_idlist(linkname, DLSTAT_RX_HWLANE_IDLIST,
17110dc2366fSVenugopal Iyer rx_hwlane_idlist, &rx_hwlane_idlist_size);
17120dc2366fSVenugopal Iyer
17130dc2366fSVenugopal Iyer return (i_dlstat_query_fanout_stats(dh, linkid, rx_hwlane_idlist,
17140dc2366fSVenugopal Iyer rx_hwlane_idlist_size, linkname, DLSTAT_MAC_RX_HWLANE));
17150dc2366fSVenugopal Iyer }
17160dc2366fSVenugopal Iyer
17170dc2366fSVenugopal Iyer void *
dlstat_fanout_stats(dladm_handle_t dh,datalink_id_t linkid)17180dc2366fSVenugopal Iyer dlstat_fanout_stats(dladm_handle_t dh, datalink_id_t linkid)
17190dc2366fSVenugopal Iyer {
17200dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
17210dc2366fSVenugopal Iyer dladm_stat_chain_t *fout_hwlane_stats;
17220dc2366fSVenugopal Iyer dladm_stat_chain_t *fout_swlane_and_local_stats;
17230dc2366fSVenugopal Iyer fanout_stat_entry_t *fout_stats;
17240dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
17250dc2366fSVenugopal Iyer
17260dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
17270dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
17280dc2366fSVenugopal Iyer goto done;
17290dc2366fSVenugopal Iyer }
17300dc2366fSVenugopal Iyer
17310dc2366fSVenugopal Iyer fout_swlane_and_local_stats =
17320dc2366fSVenugopal Iyer dlstat_fanout_swlane_and_local_stats(dh, linkid, linkname);
17330dc2366fSVenugopal Iyer fout_hwlane_stats = dlstat_fanout_hwlane_stats(dh, linkid, linkname);
17340dc2366fSVenugopal Iyer
17350dc2366fSVenugopal Iyer if (fout_swlane_and_local_stats == NULL) {
17360dc2366fSVenugopal Iyer head = fout_hwlane_stats;
17370dc2366fSVenugopal Iyer goto done;
17380dc2366fSVenugopal Iyer }
17390dc2366fSVenugopal Iyer
17400dc2366fSVenugopal Iyer fout_stats = fout_swlane_and_local_stats->dc_statentry;
17410dc2366fSVenugopal Iyer
17420dc2366fSVenugopal Iyer if (fout_hwlane_stats != NULL) { /* hwlane(s), only local traffic */
17430dc2366fSVenugopal Iyer fout_stats->fe_id = L_LOCAL;
17440dc2366fSVenugopal Iyer fout_stats->fe_index = DLSTAT_INVALID_ENTRY;
17450dc2366fSVenugopal Iyer } else { /* no hwlane, mix of local+sw classified */
17460dc2366fSVenugopal Iyer fout_stats->fe_id = L_LCLSWLANE;
17470dc2366fSVenugopal Iyer fout_stats->fe_index = DLSTAT_INVALID_ENTRY;
17480dc2366fSVenugopal Iyer }
17490dc2366fSVenugopal Iyer
17500dc2366fSVenugopal Iyer fout_swlane_and_local_stats->dc_next = fout_hwlane_stats;
17510dc2366fSVenugopal Iyer head = fout_swlane_and_local_stats;
17520dc2366fSVenugopal Iyer
17530dc2366fSVenugopal Iyer done:
17540dc2366fSVenugopal Iyer return (head);
17550dc2366fSVenugopal Iyer }
17560dc2366fSVenugopal Iyer
17570dc2366fSVenugopal Iyer /* Rx ring statistic specific functions */
17580dc2366fSVenugopal Iyer static boolean_t
i_dlstat_rx_ring_match(void * arg1,void * arg2)17590dc2366fSVenugopal Iyer i_dlstat_rx_ring_match(void *arg1, void *arg2)
17600dc2366fSVenugopal Iyer {
17610dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s1 = arg1;
17620dc2366fSVenugopal Iyer rx_lane_stat_entry_t *s2 = arg2;
17630dc2366fSVenugopal Iyer
17640dc2366fSVenugopal Iyer return (s1->rle_index == s2->rle_index);
17650dc2366fSVenugopal Iyer }
17660dc2366fSVenugopal Iyer
17670dc2366fSVenugopal Iyer static void *
i_dlstat_rx_ring_stat_entry_diff(void * arg1,void * arg2)17680dc2366fSVenugopal Iyer i_dlstat_rx_ring_stat_entry_diff(void *arg1, void *arg2)
17690dc2366fSVenugopal Iyer {
17700dc2366fSVenugopal Iyer ring_stat_entry_t *s1 = arg1;
17710dc2366fSVenugopal Iyer ring_stat_entry_t *s2 = arg2;
17720dc2366fSVenugopal Iyer ring_stat_entry_t *diff_entry;
17730dc2366fSVenugopal Iyer
17740dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (ring_stat_entry_t));
17750dc2366fSVenugopal Iyer if (diff_entry == NULL)
17760dc2366fSVenugopal Iyer goto done;
17770dc2366fSVenugopal Iyer
17780dc2366fSVenugopal Iyer diff_entry->re_index = s1->re_index;
17790dc2366fSVenugopal Iyer
17800dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, re_stats, rx_ring_stats_list,
17810dc2366fSVenugopal Iyer RX_RING_STAT_SIZE);
17820dc2366fSVenugopal Iyer
17830dc2366fSVenugopal Iyer done:
17840dc2366fSVenugopal Iyer return (diff_entry);
17850dc2366fSVenugopal Iyer }
17860dc2366fSVenugopal Iyer
17870dc2366fSVenugopal Iyer static void *
i_dlstat_rx_ring_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)17880dc2366fSVenugopal Iyer i_dlstat_rx_ring_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
17890dc2366fSVenugopal Iyer {
17900dc2366fSVenugopal Iyer ring_stat_entry_t *rx_ring_stat_entry;
17910dc2366fSVenugopal Iyer
17920dc2366fSVenugopal Iyer rx_ring_stat_entry = calloc(1, sizeof (ring_stat_entry_t));
17930dc2366fSVenugopal Iyer if (rx_ring_stat_entry == NULL)
17940dc2366fSVenugopal Iyer goto done;
17950dc2366fSVenugopal Iyer
17960dc2366fSVenugopal Iyer rx_ring_stat_entry->re_index = i;
17970dc2366fSVenugopal Iyer
17980dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &rx_ring_stat_entry->re_stats,
17990dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE);
18000dc2366fSVenugopal Iyer
18010dc2366fSVenugopal Iyer done:
18020dc2366fSVenugopal Iyer return (rx_ring_stat_entry);
18030dc2366fSVenugopal Iyer }
18040dc2366fSVenugopal Iyer
18050dc2366fSVenugopal Iyer void *
dlstat_rx_ring_stats(dladm_handle_t dh,datalink_id_t linkid)18060dc2366fSVenugopal Iyer dlstat_rx_ring_stats(dladm_handle_t dh, datalink_id_t linkid)
18070dc2366fSVenugopal Iyer {
18080dc2366fSVenugopal Iyer uint_t rx_ring_idlist[MAX_RINGS_PER_GROUP];
18090dc2366fSVenugopal Iyer uint_t rx_ring_idlist_size;
18100dc2366fSVenugopal Iyer dladm_phys_attr_t dpa;
18110dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
18120dc2366fSVenugopal Iyer char *modname;
18130dc2366fSVenugopal Iyer datalink_class_t class;
18140dc2366fSVenugopal Iyer
18150dc2366fSVenugopal Iyer /*
18160dc2366fSVenugopal Iyer * kstats corresponding to physical device rings continue to use
18170dc2366fSVenugopal Iyer * device names even if the link is renamed using dladm rename-link.
18180dc2366fSVenugopal Iyer * Thus, given a linkid, we lookup the physical device name.
18190dc2366fSVenugopal Iyer * However, if an aggr is renamed, kstats corresponding to its
18200dc2366fSVenugopal Iyer * pseudo rings are renamed as well.
18210dc2366fSVenugopal Iyer */
18220dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, linkname,
18230dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
18240dc2366fSVenugopal Iyer return (NULL);
18250dc2366fSVenugopal Iyer }
18260dc2366fSVenugopal Iyer
18270dc2366fSVenugopal Iyer if (class != DATALINK_CLASS_AGGR) {
18280dc2366fSVenugopal Iyer if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
18290dc2366fSVenugopal Iyer DLADM_STATUS_OK) {
18300dc2366fSVenugopal Iyer return (NULL);
18310dc2366fSVenugopal Iyer }
18320dc2366fSVenugopal Iyer modname = dpa.dp_dev;
18330dc2366fSVenugopal Iyer } else
18340dc2366fSVenugopal Iyer modname = linkname;
18350dc2366fSVenugopal Iyer
18360dc2366fSVenugopal Iyer i_dlstat_get_idlist(modname, DLSTAT_RX_RING_IDLIST,
18370dc2366fSVenugopal Iyer rx_ring_idlist, &rx_ring_idlist_size);
18380dc2366fSVenugopal Iyer
18390dc2366fSVenugopal Iyer return (i_dlstat_query_stats(modname, DLSTAT_MAC_RX_RING,
18400dc2366fSVenugopal Iyer rx_ring_idlist, rx_ring_idlist_size,
18410dc2366fSVenugopal Iyer i_dlstat_rx_ring_retrieve_stat));
18420dc2366fSVenugopal Iyer }
18430dc2366fSVenugopal Iyer
18440dc2366fSVenugopal Iyer /* Tx ring statistic specific functions */
18450dc2366fSVenugopal Iyer static boolean_t
i_dlstat_tx_ring_match(void * arg1,void * arg2)18460dc2366fSVenugopal Iyer i_dlstat_tx_ring_match(void *arg1, void *arg2)
18470dc2366fSVenugopal Iyer {
18480dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s1 = arg1;
18490dc2366fSVenugopal Iyer tx_lane_stat_entry_t *s2 = arg2;
18500dc2366fSVenugopal Iyer
18510dc2366fSVenugopal Iyer return (s1->tle_index == s2->tle_index);
18520dc2366fSVenugopal Iyer }
18530dc2366fSVenugopal Iyer
18540dc2366fSVenugopal Iyer static void *
i_dlstat_tx_ring_stat_entry_diff(void * arg1,void * arg2)18550dc2366fSVenugopal Iyer i_dlstat_tx_ring_stat_entry_diff(void *arg1, void *arg2)
18560dc2366fSVenugopal Iyer {
18570dc2366fSVenugopal Iyer ring_stat_entry_t *s1 = arg1;
18580dc2366fSVenugopal Iyer ring_stat_entry_t *s2 = arg2;
18590dc2366fSVenugopal Iyer ring_stat_entry_t *diff_entry;
18600dc2366fSVenugopal Iyer
18610dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (ring_stat_entry_t));
18620dc2366fSVenugopal Iyer if (diff_entry == NULL)
18630dc2366fSVenugopal Iyer goto done;
18640dc2366fSVenugopal Iyer
18650dc2366fSVenugopal Iyer diff_entry->re_index = s1->re_index;
18660dc2366fSVenugopal Iyer
18670dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, re_stats, tx_ring_stats_list,
18680dc2366fSVenugopal Iyer TX_RING_STAT_SIZE);
18690dc2366fSVenugopal Iyer
18700dc2366fSVenugopal Iyer done:
18710dc2366fSVenugopal Iyer return (diff_entry);
18720dc2366fSVenugopal Iyer }
18730dc2366fSVenugopal Iyer
18740dc2366fSVenugopal Iyer static void *
i_dlstat_tx_ring_retrieve_stat(kstat_ctl_t * kcp,kstat_t * ksp,int i)18750dc2366fSVenugopal Iyer i_dlstat_tx_ring_retrieve_stat(kstat_ctl_t *kcp, kstat_t *ksp, int i)
18760dc2366fSVenugopal Iyer {
18770dc2366fSVenugopal Iyer ring_stat_entry_t *tx_ring_stat_entry;
18780dc2366fSVenugopal Iyer
18790dc2366fSVenugopal Iyer tx_ring_stat_entry = calloc(1, sizeof (ring_stat_entry_t));
18800dc2366fSVenugopal Iyer if (tx_ring_stat_entry == NULL)
18810dc2366fSVenugopal Iyer goto done;
18820dc2366fSVenugopal Iyer
18830dc2366fSVenugopal Iyer tx_ring_stat_entry->re_index = i;
18840dc2366fSVenugopal Iyer
18850dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &tx_ring_stat_entry->re_stats,
18860dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE);
18870dc2366fSVenugopal Iyer
18880dc2366fSVenugopal Iyer done:
18890dc2366fSVenugopal Iyer return (tx_ring_stat_entry);
18900dc2366fSVenugopal Iyer }
18910dc2366fSVenugopal Iyer
18920dc2366fSVenugopal Iyer void *
dlstat_tx_ring_stats(dladm_handle_t dh,datalink_id_t linkid)18930dc2366fSVenugopal Iyer dlstat_tx_ring_stats(dladm_handle_t dh, datalink_id_t linkid)
18940dc2366fSVenugopal Iyer {
18950dc2366fSVenugopal Iyer uint_t tx_ring_idlist[MAX_RINGS_PER_GROUP];
18960dc2366fSVenugopal Iyer uint_t tx_ring_idlist_size;
18970dc2366fSVenugopal Iyer dladm_phys_attr_t dpa;
18980dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
18990dc2366fSVenugopal Iyer char *modname;
19000dc2366fSVenugopal Iyer datalink_class_t class;
19010dc2366fSVenugopal Iyer
19020dc2366fSVenugopal Iyer /*
19030dc2366fSVenugopal Iyer * kstats corresponding to physical device rings continue to use
19040dc2366fSVenugopal Iyer * device names even if the link is renamed using dladm rename-link.
19050dc2366fSVenugopal Iyer * Thus, given a linkid, we lookup the physical device name.
19060dc2366fSVenugopal Iyer * However, if an aggr is renamed, kstats corresponding to its
19070dc2366fSVenugopal Iyer * pseudo rings are renamed as well.
19080dc2366fSVenugopal Iyer */
19090dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, &class, NULL, linkname,
19100dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
19110dc2366fSVenugopal Iyer return (NULL);
19120dc2366fSVenugopal Iyer }
19130dc2366fSVenugopal Iyer
19140dc2366fSVenugopal Iyer if (class != DATALINK_CLASS_AGGR) {
19150dc2366fSVenugopal Iyer if (dladm_phys_info(dh, linkid, &dpa, DLADM_OPT_ACTIVE) !=
19160dc2366fSVenugopal Iyer DLADM_STATUS_OK) {
19170dc2366fSVenugopal Iyer return (NULL);
19180dc2366fSVenugopal Iyer }
19190dc2366fSVenugopal Iyer modname = dpa.dp_dev;
19200dc2366fSVenugopal Iyer } else
19210dc2366fSVenugopal Iyer modname = linkname;
19220dc2366fSVenugopal Iyer
19230dc2366fSVenugopal Iyer i_dlstat_get_idlist(modname, DLSTAT_TX_RING_IDLIST,
19240dc2366fSVenugopal Iyer tx_ring_idlist, &tx_ring_idlist_size);
19250dc2366fSVenugopal Iyer
19260dc2366fSVenugopal Iyer return (i_dlstat_query_stats(modname, DLSTAT_MAC_TX_RING,
19270dc2366fSVenugopal Iyer tx_ring_idlist, tx_ring_idlist_size,
19280dc2366fSVenugopal Iyer i_dlstat_tx_ring_retrieve_stat));
19290dc2366fSVenugopal Iyer }
19300dc2366fSVenugopal Iyer
19310dc2366fSVenugopal Iyer /* Rx ring total statistic specific functions */
19320dc2366fSVenugopal Iyer void *
dlstat_rx_ring_total_stats(dladm_handle_t dh,datalink_id_t linkid)19330dc2366fSVenugopal Iyer dlstat_rx_ring_total_stats(dladm_handle_t dh, datalink_id_t linkid)
19340dc2366fSVenugopal Iyer {
19350dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL;
19360dc2366fSVenugopal Iyer dladm_stat_chain_t *rx_ring_head, *curr;
19370dc2366fSVenugopal Iyer ring_stat_entry_t *total_stats;
19380dc2366fSVenugopal Iyer
19390dc2366fSVenugopal Iyer /* Get per rx ring stats */
19400dc2366fSVenugopal Iyer rx_ring_head = dlstat_rx_ring_stats(dh, linkid);
19410dc2366fSVenugopal Iyer if (rx_ring_head == NULL)
19420dc2366fSVenugopal Iyer goto done;
19430dc2366fSVenugopal Iyer
19440dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (ring_stat_entry_t));
19450dc2366fSVenugopal Iyer if (total_stats == NULL)
19460dc2366fSVenugopal Iyer goto done;
19470dc2366fSVenugopal Iyer
19480dc2366fSVenugopal Iyer total_stats->re_index = DLSTAT_INVALID_ENTRY;
19490dc2366fSVenugopal Iyer
19500dc2366fSVenugopal Iyer for (curr = rx_ring_head; curr != NULL; curr = curr->dc_next) {
19510dc2366fSVenugopal Iyer ring_stat_entry_t *curr_ring_stats = curr->dc_statentry;
19520dc2366fSVenugopal Iyer
19530dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->re_stats,
19540dc2366fSVenugopal Iyer &curr_ring_stats->re_stats, &total_stats->re_stats,
19550dc2366fSVenugopal Iyer rx_ring_stats_list, RX_RING_STAT_SIZE);
19560dc2366fSVenugopal Iyer }
19570dc2366fSVenugopal Iyer
19580dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t));
19590dc2366fSVenugopal Iyer if (total_head == NULL) {
19600dc2366fSVenugopal Iyer free(total_stats);
19610dc2366fSVenugopal Iyer goto done;
19620dc2366fSVenugopal Iyer }
19630dc2366fSVenugopal Iyer
19640dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats;
19650dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_rx_ring_total",
19660dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader));
19670dc2366fSVenugopal Iyer total_head->dc_next = NULL;
19680dc2366fSVenugopal Iyer free(rx_ring_head);
19690dc2366fSVenugopal Iyer
19700dc2366fSVenugopal Iyer done:
19710dc2366fSVenugopal Iyer return (total_head);
19720dc2366fSVenugopal Iyer }
19730dc2366fSVenugopal Iyer
19740dc2366fSVenugopal Iyer /* Tx ring total statistic specific functions */
19750dc2366fSVenugopal Iyer void *
dlstat_tx_ring_total_stats(dladm_handle_t dh,datalink_id_t linkid)19760dc2366fSVenugopal Iyer dlstat_tx_ring_total_stats(dladm_handle_t dh, datalink_id_t linkid)
19770dc2366fSVenugopal Iyer {
19780dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head = NULL;
19790dc2366fSVenugopal Iyer dladm_stat_chain_t *tx_ring_head, *curr;
19800dc2366fSVenugopal Iyer ring_stat_entry_t *total_stats;
19810dc2366fSVenugopal Iyer
19820dc2366fSVenugopal Iyer /* Get per tx ring stats */
19830dc2366fSVenugopal Iyer tx_ring_head = dlstat_tx_ring_stats(dh, linkid);
19840dc2366fSVenugopal Iyer if (tx_ring_head == NULL)
19850dc2366fSVenugopal Iyer goto done;
19860dc2366fSVenugopal Iyer
19870dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (ring_stat_entry_t));
19880dc2366fSVenugopal Iyer if (total_stats == NULL)
19890dc2366fSVenugopal Iyer goto done;
19900dc2366fSVenugopal Iyer
19910dc2366fSVenugopal Iyer total_stats->re_index = DLSTAT_INVALID_ENTRY;
19920dc2366fSVenugopal Iyer
19930dc2366fSVenugopal Iyer for (curr = tx_ring_head; curr != NULL; curr = curr->dc_next) {
19940dc2366fSVenugopal Iyer ring_stat_entry_t *curr_ring_stats = curr->dc_statentry;
19950dc2366fSVenugopal Iyer
19960dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->re_stats,
19970dc2366fSVenugopal Iyer &curr_ring_stats->re_stats, &total_stats->re_stats,
19980dc2366fSVenugopal Iyer tx_ring_stats_list, TX_RING_STAT_SIZE);
19990dc2366fSVenugopal Iyer }
20000dc2366fSVenugopal Iyer
20010dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t));
20020dc2366fSVenugopal Iyer if (total_head == NULL) {
20030dc2366fSVenugopal Iyer free(total_stats);
20040dc2366fSVenugopal Iyer goto done;
20050dc2366fSVenugopal Iyer }
20060dc2366fSVenugopal Iyer
20070dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats;
20080dc2366fSVenugopal Iyer (void) strlcpy(total_head->dc_statheader, "mac_tx_ring_total",
20090dc2366fSVenugopal Iyer sizeof (total_head->dc_statheader));
20100dc2366fSVenugopal Iyer total_head->dc_next = NULL;
20110dc2366fSVenugopal Iyer free(tx_ring_head);
20120dc2366fSVenugopal Iyer
20130dc2366fSVenugopal Iyer done:
20140dc2366fSVenugopal Iyer return (total_head);
20150dc2366fSVenugopal Iyer }
20160dc2366fSVenugopal Iyer
20170dc2366fSVenugopal Iyer /* Summary statistic specific functions */
20180dc2366fSVenugopal Iyer /*ARGSUSED*/
20190dc2366fSVenugopal Iyer static boolean_t
i_dlstat_total_match(void * arg1,void * arg2)20200dc2366fSVenugopal Iyer i_dlstat_total_match(void *arg1, void *arg2)
2021*62ef8476SYuri Pankov {
2022*62ef8476SYuri Pankov /* Always single entry for total */
20230dc2366fSVenugopal Iyer return (B_TRUE);
20240dc2366fSVenugopal Iyer }
20250dc2366fSVenugopal Iyer
20260dc2366fSVenugopal Iyer static void *
i_dlstat_total_stat_entry_diff(void * arg1,void * arg2)20270dc2366fSVenugopal Iyer i_dlstat_total_stat_entry_diff(void *arg1, void *arg2)
20280dc2366fSVenugopal Iyer {
20290dc2366fSVenugopal Iyer total_stat_entry_t *s1 = arg1;
20300dc2366fSVenugopal Iyer total_stat_entry_t *s2 = arg2;
20310dc2366fSVenugopal Iyer total_stat_entry_t *diff_entry;
20320dc2366fSVenugopal Iyer
20330dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (total_stat_entry_t));
20340dc2366fSVenugopal Iyer if (diff_entry == NULL)
20350dc2366fSVenugopal Iyer goto done;
20360dc2366fSVenugopal Iyer
20370dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, tse_stats, total_stats_list,
20380dc2366fSVenugopal Iyer TOTAL_STAT_SIZE);
20390dc2366fSVenugopal Iyer
20400dc2366fSVenugopal Iyer done:
20410dc2366fSVenugopal Iyer return (diff_entry);
20420dc2366fSVenugopal Iyer }
20430dc2366fSVenugopal Iyer
20440dc2366fSVenugopal Iyer void *
dlstat_total_stats(dladm_handle_t dh,datalink_id_t linkid)20450dc2366fSVenugopal Iyer dlstat_total_stats(dladm_handle_t dh, datalink_id_t linkid)
20460dc2366fSVenugopal Iyer {
20470dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
20480dc2366fSVenugopal Iyer dladm_stat_chain_t *rx_total;
20490dc2366fSVenugopal Iyer dladm_stat_chain_t *tx_total;
20500dc2366fSVenugopal Iyer total_stat_entry_t *total_stat_entry;
20510dc2366fSVenugopal Iyer rx_lane_stat_entry_t *rx_lane_stat_entry;
20520dc2366fSVenugopal Iyer tx_lane_stat_entry_t *tx_lane_stat_entry;
20530dc2366fSVenugopal Iyer
20540dc2366fSVenugopal Iyer /* Get total rx lane stats */
20550dc2366fSVenugopal Iyer rx_total = dlstat_rx_lane_total_stats(dh, linkid);
20560dc2366fSVenugopal Iyer if (rx_total == NULL)
20570dc2366fSVenugopal Iyer goto done;
20580dc2366fSVenugopal Iyer
20590dc2366fSVenugopal Iyer /* Get total tx lane stats */
20600dc2366fSVenugopal Iyer tx_total = dlstat_tx_lane_total_stats(dh, linkid);
20610dc2366fSVenugopal Iyer if (tx_total == NULL)
20620dc2366fSVenugopal Iyer goto done;
20630dc2366fSVenugopal Iyer
20640dc2366fSVenugopal Iyer /* Build total stat */
20650dc2366fSVenugopal Iyer total_stat_entry = calloc(1, sizeof (total_stat_entry_t));
20660dc2366fSVenugopal Iyer if (total_stat_entry == NULL)
20670dc2366fSVenugopal Iyer goto done;
20680dc2366fSVenugopal Iyer
20690dc2366fSVenugopal Iyer rx_lane_stat_entry = rx_total->dc_statentry;
20700dc2366fSVenugopal Iyer tx_lane_stat_entry = tx_total->dc_statentry;
20710dc2366fSVenugopal Iyer
20720dc2366fSVenugopal Iyer /* Extract total rx ipackets, rbytes */
20730dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_ipackets =
20740dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_ipackets;
20750dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_rbytes =
20760dc2366fSVenugopal Iyer rx_lane_stat_entry->rle_stats.rl_rbytes;
20770dc2366fSVenugopal Iyer
20780dc2366fSVenugopal Iyer /* Extract total tx opackets, obytes */
20790dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_opackets =
20800dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_opackets;
20810dc2366fSVenugopal Iyer total_stat_entry->tse_stats.ts_obytes =
20820dc2366fSVenugopal Iyer tx_lane_stat_entry->tle_stats.tl_obytes;
20830dc2366fSVenugopal Iyer
20840dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
20850dc2366fSVenugopal Iyer if (head == NULL) {
20860dc2366fSVenugopal Iyer free(total_stat_entry);
20870dc2366fSVenugopal Iyer goto done;
20880dc2366fSVenugopal Iyer }
20890dc2366fSVenugopal Iyer
20900dc2366fSVenugopal Iyer head->dc_statentry = total_stat_entry;
20910dc2366fSVenugopal Iyer (void) strlcpy(head->dc_statheader, "mac_lane_total",
20920dc2366fSVenugopal Iyer sizeof (head->dc_statheader));
20930dc2366fSVenugopal Iyer head->dc_next = NULL;
20940dc2366fSVenugopal Iyer free(rx_total);
20950dc2366fSVenugopal Iyer free(tx_total);
20960dc2366fSVenugopal Iyer
20970dc2366fSVenugopal Iyer done:
20980dc2366fSVenugopal Iyer return (head);
20990dc2366fSVenugopal Iyer }
21000dc2366fSVenugopal Iyer
21010dc2366fSVenugopal Iyer /* Aggr total statistic(summed across all component ports) specific functions */
21020dc2366fSVenugopal Iyer void *
dlstat_aggr_total_stats(dladm_stat_chain_t * head)21030dc2366fSVenugopal Iyer dlstat_aggr_total_stats(dladm_stat_chain_t *head)
21040dc2366fSVenugopal Iyer {
21050dc2366fSVenugopal Iyer dladm_stat_chain_t *curr;
21060dc2366fSVenugopal Iyer dladm_stat_chain_t *total_head;
21070dc2366fSVenugopal Iyer aggr_port_stat_entry_t *total_stats;
21080dc2366fSVenugopal Iyer
21090dc2366fSVenugopal Iyer total_stats = calloc(1, sizeof (aggr_port_stat_entry_t));
21100dc2366fSVenugopal Iyer if (total_stats == NULL)
21110dc2366fSVenugopal Iyer goto done;
21120dc2366fSVenugopal Iyer
21130dc2366fSVenugopal Iyer total_stats->ape_portlinkid = DATALINK_INVALID_LINKID;
21140dc2366fSVenugopal Iyer
21150dc2366fSVenugopal Iyer for (curr = head; curr != NULL; curr = curr->dc_next) {
21160dc2366fSVenugopal Iyer aggr_port_stat_entry_t *curr_aggr_port_stats;
21170dc2366fSVenugopal Iyer
21180dc2366fSVenugopal Iyer curr_aggr_port_stats = curr->dc_statentry;
21190dc2366fSVenugopal Iyer
21200dc2366fSVenugopal Iyer i_dlstat_sum_stats(&total_stats->ape_stats,
21210dc2366fSVenugopal Iyer &curr_aggr_port_stats->ape_stats, &total_stats->ape_stats,
21220dc2366fSVenugopal Iyer aggr_port_stats_list, AGGR_PORT_STAT_SIZE);
21230dc2366fSVenugopal Iyer }
21240dc2366fSVenugopal Iyer
21250dc2366fSVenugopal Iyer total_head = malloc(sizeof (dladm_stat_chain_t));
21260dc2366fSVenugopal Iyer if (total_head == NULL) {
21270dc2366fSVenugopal Iyer free(total_stats);
21280dc2366fSVenugopal Iyer goto done;
21290dc2366fSVenugopal Iyer }
21300dc2366fSVenugopal Iyer
21310dc2366fSVenugopal Iyer total_head->dc_statentry = total_stats;
21320dc2366fSVenugopal Iyer total_head->dc_next = NULL;
21330dc2366fSVenugopal Iyer
21340dc2366fSVenugopal Iyer done:
21350dc2366fSVenugopal Iyer return (total_head);
21360dc2366fSVenugopal Iyer }
21370dc2366fSVenugopal Iyer
21380dc2366fSVenugopal Iyer /* Aggr port statistic specific functions */
21390dc2366fSVenugopal Iyer static boolean_t
i_dlstat_aggr_port_match(void * arg1,void * arg2)21400dc2366fSVenugopal Iyer i_dlstat_aggr_port_match(void *arg1, void *arg2)
21410dc2366fSVenugopal Iyer {
21420dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s1 = arg1;
21430dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s2 = arg2;
21440dc2366fSVenugopal Iyer
21450dc2366fSVenugopal Iyer return (s1->ape_portlinkid == s2->ape_portlinkid);
21460dc2366fSVenugopal Iyer }
21470dc2366fSVenugopal Iyer
21480dc2366fSVenugopal Iyer static void *
i_dlstat_aggr_port_stat_entry_diff(void * arg1,void * arg2)21490dc2366fSVenugopal Iyer i_dlstat_aggr_port_stat_entry_diff(void *arg1, void *arg2)
21500dc2366fSVenugopal Iyer {
21510dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s1 = arg1;
21520dc2366fSVenugopal Iyer aggr_port_stat_entry_t *s2 = arg2;
21530dc2366fSVenugopal Iyer aggr_port_stat_entry_t *diff_entry;
21540dc2366fSVenugopal Iyer
21550dc2366fSVenugopal Iyer diff_entry = malloc(sizeof (aggr_port_stat_entry_t));
21560dc2366fSVenugopal Iyer if (diff_entry == NULL)
21570dc2366fSVenugopal Iyer goto done;
21580dc2366fSVenugopal Iyer
21590dc2366fSVenugopal Iyer diff_entry->ape_portlinkid = s1->ape_portlinkid;
21600dc2366fSVenugopal Iyer
21610dc2366fSVenugopal Iyer DLSTAT_DIFF_STAT(s1, s2, diff_entry, ape_stats, aggr_port_stats_list,
21620dc2366fSVenugopal Iyer AGGR_PORT_STAT_SIZE);
21630dc2366fSVenugopal Iyer
21640dc2366fSVenugopal Iyer done:
21650dc2366fSVenugopal Iyer return (diff_entry);
21660dc2366fSVenugopal Iyer }
21670dc2366fSVenugopal Iyer
21680dc2366fSVenugopal Iyer /*
21690dc2366fSVenugopal Iyer * Query dls stats for the aggr port. This results in query for stats into
21700dc2366fSVenugopal Iyer * the corresponding device driver.
21710dc2366fSVenugopal Iyer */
21720dc2366fSVenugopal Iyer static aggr_port_stat_entry_t *
i_dlstat_single_port_stats(const char * portname,datalink_id_t linkid)21730dc2366fSVenugopal Iyer i_dlstat_single_port_stats(const char *portname, datalink_id_t linkid)
21740dc2366fSVenugopal Iyer {
21750dc2366fSVenugopal Iyer kstat_ctl_t *kcp;
21760dc2366fSVenugopal Iyer kstat_t *ksp;
21770dc2366fSVenugopal Iyer char module[DLPI_LINKNAME_MAX];
21780dc2366fSVenugopal Iyer uint_t instance;
21790dc2366fSVenugopal Iyer aggr_port_stat_entry_t *aggr_port_stat_entry = NULL;
21800dc2366fSVenugopal Iyer
21810dc2366fSVenugopal Iyer if (dladm_parselink(portname, module, &instance) != DLADM_STATUS_OK)
21820dc2366fSVenugopal Iyer goto done;
21830dc2366fSVenugopal Iyer
21840dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL) {
21850dc2366fSVenugopal Iyer warn("kstat open operation failed");
21860dc2366fSVenugopal Iyer return (NULL);
21870dc2366fSVenugopal Iyer }
21880dc2366fSVenugopal Iyer
21890dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, module, instance, "mac", NULL);
21900dc2366fSVenugopal Iyer if (ksp == NULL)
21910dc2366fSVenugopal Iyer goto done;
21920dc2366fSVenugopal Iyer
21930dc2366fSVenugopal Iyer aggr_port_stat_entry = calloc(1, sizeof (aggr_port_stat_entry_t));
21940dc2366fSVenugopal Iyer if (aggr_port_stat_entry == NULL)
21950dc2366fSVenugopal Iyer goto done;
21960dc2366fSVenugopal Iyer
21970dc2366fSVenugopal Iyer /* Save port's linkid */
21980dc2366fSVenugopal Iyer aggr_port_stat_entry->ape_portlinkid = linkid;
21990dc2366fSVenugopal Iyer
22000dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, &aggr_port_stat_entry->ape_stats,
22010dc2366fSVenugopal Iyer aggr_port_stats_list, AGGR_PORT_STAT_SIZE);
22020dc2366fSVenugopal Iyer done:
22030dc2366fSVenugopal Iyer (void) kstat_close(kcp);
22040dc2366fSVenugopal Iyer return (aggr_port_stat_entry);
22050dc2366fSVenugopal Iyer }
22060dc2366fSVenugopal Iyer
22070dc2366fSVenugopal Iyer void *
dlstat_aggr_port_stats(dladm_handle_t dh,datalink_id_t linkid)22080dc2366fSVenugopal Iyer dlstat_aggr_port_stats(dladm_handle_t dh, datalink_id_t linkid)
22090dc2366fSVenugopal Iyer {
22100dc2366fSVenugopal Iyer dladm_aggr_grp_attr_t ginfo;
22110dc2366fSVenugopal Iyer int i;
22120dc2366fSVenugopal Iyer dladm_aggr_port_attr_t *portp;
22130dc2366fSVenugopal Iyer dladm_phys_attr_t dpa;
22140dc2366fSVenugopal Iyer aggr_port_stat_entry_t *aggr_port_stat_entry;
22150dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL, *prev = NULL, *curr;
22160dc2366fSVenugopal Iyer dladm_stat_chain_t *total_stats;
22170dc2366fSVenugopal Iyer
22180dc2366fSVenugopal Iyer /* Get aggr info */
22190dc2366fSVenugopal Iyer bzero(&ginfo, sizeof (dladm_aggr_grp_attr_t));
22200dc2366fSVenugopal Iyer if (dladm_aggr_info(dh, linkid, &ginfo, DLADM_OPT_ACTIVE)
22210dc2366fSVenugopal Iyer != DLADM_STATUS_OK)
22220dc2366fSVenugopal Iyer goto done;
22230dc2366fSVenugopal Iyer /* For every port that is member of this aggr do */
22240dc2366fSVenugopal Iyer for (i = 0; i < ginfo.lg_nports; i++) {
22250dc2366fSVenugopal Iyer portp = &(ginfo.lg_ports[i]);
22260dc2366fSVenugopal Iyer if (dladm_phys_info(dh, portp->lp_linkid, &dpa,
22270dc2366fSVenugopal Iyer DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) {
22280dc2366fSVenugopal Iyer goto done;
22290dc2366fSVenugopal Iyer }
22300dc2366fSVenugopal Iyer
22310dc2366fSVenugopal Iyer aggr_port_stat_entry = i_dlstat_single_port_stats(dpa.dp_dev,
22320dc2366fSVenugopal Iyer portp->lp_linkid);
22330dc2366fSVenugopal Iyer
22340dc2366fSVenugopal Iyer /* Create dladm_stat_chain_t object for this stat */
22350dc2366fSVenugopal Iyer curr = malloc(sizeof (dladm_stat_chain_t));
22360dc2366fSVenugopal Iyer if (curr == NULL) {
22370dc2366fSVenugopal Iyer free(aggr_port_stat_entry);
22380dc2366fSVenugopal Iyer goto done;
22390dc2366fSVenugopal Iyer }
22400dc2366fSVenugopal Iyer (void) strlcpy(curr->dc_statheader, dpa.dp_dev,
22410dc2366fSVenugopal Iyer sizeof (curr->dc_statheader));
22420dc2366fSVenugopal Iyer curr->dc_statentry = aggr_port_stat_entry;
22430dc2366fSVenugopal Iyer curr->dc_next = NULL;
22440dc2366fSVenugopal Iyer
22450dc2366fSVenugopal Iyer /* Chain this aggr port stat entry */
22460dc2366fSVenugopal Iyer /* head of the stat list */
22470dc2366fSVenugopal Iyer if (prev == NULL)
22480dc2366fSVenugopal Iyer head = curr;
22490dc2366fSVenugopal Iyer else
22500dc2366fSVenugopal Iyer prev->dc_next = curr;
22510dc2366fSVenugopal Iyer prev = curr;
22520dc2366fSVenugopal Iyer }
22530dc2366fSVenugopal Iyer
22540dc2366fSVenugopal Iyer /*
22550dc2366fSVenugopal Iyer * Prepend the stat list with cumulative aggr stats i.e. summed over all
22560dc2366fSVenugopal Iyer * component ports
22570dc2366fSVenugopal Iyer */
22580dc2366fSVenugopal Iyer total_stats = dlstat_aggr_total_stats(head);
22590dc2366fSVenugopal Iyer if (total_stats != NULL) {
22600dc2366fSVenugopal Iyer total_stats->dc_next = head;
22610dc2366fSVenugopal Iyer head = total_stats;
22620dc2366fSVenugopal Iyer }
22630dc2366fSVenugopal Iyer
22640dc2366fSVenugopal Iyer done:
22650dc2366fSVenugopal Iyer free(ginfo.lg_ports);
22660dc2366fSVenugopal Iyer return (head);
22670dc2366fSVenugopal Iyer }
22680dc2366fSVenugopal Iyer
22690dc2366fSVenugopal Iyer /* Misc stat specific functions */
22700dc2366fSVenugopal Iyer void *
dlstat_misc_stats(dladm_handle_t dh,datalink_id_t linkid)22710dc2366fSVenugopal Iyer dlstat_misc_stats(dladm_handle_t dh, datalink_id_t linkid)
22720dc2366fSVenugopal Iyer {
22730dc2366fSVenugopal Iyer misc_stat_entry_t *misc_stat_entry;
22740dc2366fSVenugopal Iyer dladm_stat_chain_t *head = NULL;
22750dc2366fSVenugopal Iyer char linkname[MAXLINKNAMELEN];
22760dc2366fSVenugopal Iyer
22770dc2366fSVenugopal Iyer if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
22780dc2366fSVenugopal Iyer DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
22790dc2366fSVenugopal Iyer goto done;
22800dc2366fSVenugopal Iyer }
22810dc2366fSVenugopal Iyer
22820dc2366fSVenugopal Iyer misc_stat_entry = i_dlstat_misc_stats(linkname);
22830dc2366fSVenugopal Iyer if (misc_stat_entry == NULL)
22840dc2366fSVenugopal Iyer goto done;
22850dc2366fSVenugopal Iyer
22860dc2366fSVenugopal Iyer head = malloc(sizeof (dladm_stat_chain_t));
22870dc2366fSVenugopal Iyer if (head == NULL) {
22880dc2366fSVenugopal Iyer free(misc_stat_entry);
22890dc2366fSVenugopal Iyer goto done;
22900dc2366fSVenugopal Iyer }
22910dc2366fSVenugopal Iyer
22920dc2366fSVenugopal Iyer head->dc_statentry = misc_stat_entry;
22930dc2366fSVenugopal Iyer (void) strlcpy(head->dc_statheader, "mac_misc_stat",
22940dc2366fSVenugopal Iyer sizeof (head->dc_statheader));
22950dc2366fSVenugopal Iyer head->dc_next = NULL;
22960dc2366fSVenugopal Iyer
22970dc2366fSVenugopal Iyer done:
22980dc2366fSVenugopal Iyer return (head);
22990dc2366fSVenugopal Iyer }
23000dc2366fSVenugopal Iyer
23010dc2366fSVenugopal Iyer /* Exported functions */
23020dc2366fSVenugopal Iyer dladm_stat_chain_t *
dladm_link_stat_query(dladm_handle_t dh,datalink_id_t linkid,dladm_stat_type_t stattype)23030dc2366fSVenugopal Iyer dladm_link_stat_query(dladm_handle_t dh, datalink_id_t linkid,
23040dc2366fSVenugopal Iyer dladm_stat_type_t stattype)
23050dc2366fSVenugopal Iyer {
23060dc2366fSVenugopal Iyer return (dladm_stat_table[stattype].ds_querystat(dh, linkid));
23070dc2366fSVenugopal Iyer }
23080dc2366fSVenugopal Iyer
23090dc2366fSVenugopal Iyer dladm_stat_chain_t *
dladm_link_stat_diffchain(dladm_stat_chain_t * op1,dladm_stat_chain_t * op2,dladm_stat_type_t stattype)23100dc2366fSVenugopal Iyer dladm_link_stat_diffchain(dladm_stat_chain_t *op1, dladm_stat_chain_t *op2,
23110dc2366fSVenugopal Iyer dladm_stat_type_t stattype)
23120dc2366fSVenugopal Iyer {
23130dc2366fSVenugopal Iyer dladm_stat_chain_t *op1_curr, *op2_curr;
23140dc2366fSVenugopal Iyer dladm_stat_chain_t *diff_curr;
23150dc2366fSVenugopal Iyer dladm_stat_chain_t *diff_prev = NULL, *diff_head = NULL;
23160dc2366fSVenugopal Iyer
23170dc2366fSVenugopal Iyer /* Perform op1 - op2, store result in diff */
23180dc2366fSVenugopal Iyer for (op1_curr = op1; op1_curr != NULL; op1_curr = op1_curr->dc_next) {
23190dc2366fSVenugopal Iyer for (op2_curr = op2; op2_curr != NULL;
23200dc2366fSVenugopal Iyer op2_curr = op2_curr->dc_next) {
23210dc2366fSVenugopal Iyer if (dlstat_match_stats(op1_curr->dc_statentry,
23220dc2366fSVenugopal Iyer op2_curr->dc_statentry, stattype)) {
23230dc2366fSVenugopal Iyer break;
23240dc2366fSVenugopal Iyer }
23250dc2366fSVenugopal Iyer }
23260dc2366fSVenugopal Iyer diff_curr = malloc(sizeof (dladm_stat_chain_t));
23270dc2366fSVenugopal Iyer if (diff_curr == NULL)
23280dc2366fSVenugopal Iyer goto done;
23290dc2366fSVenugopal Iyer
23300dc2366fSVenugopal Iyer diff_curr->dc_next = NULL;
23310dc2366fSVenugopal Iyer
23320dc2366fSVenugopal Iyer if (op2_curr == NULL) {
23330dc2366fSVenugopal Iyer /* prev iteration did not have this stat entry */
23340dc2366fSVenugopal Iyer diff_curr->dc_statentry =
23350dc2366fSVenugopal Iyer dlstat_diff_stats(op1_curr->dc_statentry,
23360dc2366fSVenugopal Iyer NULL, stattype);
23370dc2366fSVenugopal Iyer } else {
23380dc2366fSVenugopal Iyer diff_curr->dc_statentry =
23390dc2366fSVenugopal Iyer dlstat_diff_stats(op1_curr->dc_statentry,
23400dc2366fSVenugopal Iyer op2_curr->dc_statentry, stattype);
23410dc2366fSVenugopal Iyer }
23420dc2366fSVenugopal Iyer
23430dc2366fSVenugopal Iyer if (diff_curr->dc_statentry == NULL) {
23440dc2366fSVenugopal Iyer free(diff_curr);
23450dc2366fSVenugopal Iyer goto done;
23460dc2366fSVenugopal Iyer }
23470dc2366fSVenugopal Iyer
23480dc2366fSVenugopal Iyer if (diff_prev == NULL) /* head of the diff stat list */
23490dc2366fSVenugopal Iyer diff_head = diff_curr;
23500dc2366fSVenugopal Iyer else
23510dc2366fSVenugopal Iyer diff_prev->dc_next = diff_curr;
23520dc2366fSVenugopal Iyer diff_prev = diff_curr;
23530dc2366fSVenugopal Iyer }
23540dc2366fSVenugopal Iyer done:
23550dc2366fSVenugopal Iyer return (diff_head);
23560dc2366fSVenugopal Iyer }
23570dc2366fSVenugopal Iyer
23580dc2366fSVenugopal Iyer void
dladm_link_stat_free(dladm_stat_chain_t * curr)23590dc2366fSVenugopal Iyer dladm_link_stat_free(dladm_stat_chain_t *curr)
23600dc2366fSVenugopal Iyer {
23610dc2366fSVenugopal Iyer while (curr != NULL) {
23620dc2366fSVenugopal Iyer dladm_stat_chain_t *tofree = curr;
23630dc2366fSVenugopal Iyer
23640dc2366fSVenugopal Iyer curr = curr->dc_next;
23650dc2366fSVenugopal Iyer free(tofree->dc_statentry);
23660dc2366fSVenugopal Iyer free(tofree);
23670dc2366fSVenugopal Iyer }
23680dc2366fSVenugopal Iyer }
23690dc2366fSVenugopal Iyer
23700dc2366fSVenugopal Iyer /* Query all link stats */
23710dc2366fSVenugopal Iyer static name_value_stat_t *
i_dlstat_convert_stats(void * stats,stat_info_t stats_list[],uint_t size)23720dc2366fSVenugopal Iyer i_dlstat_convert_stats(void *stats, stat_info_t stats_list[], uint_t size)
23730dc2366fSVenugopal Iyer {
23740dc2366fSVenugopal Iyer int i;
23750dc2366fSVenugopal Iyer name_value_stat_t *head_stat = NULL, *prev_stat = NULL;
23760dc2366fSVenugopal Iyer name_value_stat_t *curr_stat;
23770dc2366fSVenugopal Iyer
23780dc2366fSVenugopal Iyer for (i = 0; i < size; i++) {
23790dc2366fSVenugopal Iyer uint64_t *val = (void *)
23800dc2366fSVenugopal Iyer ((uchar_t *)stats + stats_list[i].si_offset);
23810dc2366fSVenugopal Iyer
23820dc2366fSVenugopal Iyer curr_stat = calloc(1, sizeof (name_value_stat_t));
23830dc2366fSVenugopal Iyer if (curr_stat == NULL)
23840dc2366fSVenugopal Iyer break;
23850dc2366fSVenugopal Iyer
23860dc2366fSVenugopal Iyer (void) strlcpy(curr_stat->nv_statname, stats_list[i].si_name,
23870dc2366fSVenugopal Iyer sizeof (curr_stat->nv_statname));
23880dc2366fSVenugopal Iyer curr_stat->nv_statval = *val;
23890dc2366fSVenugopal Iyer curr_stat->nv_nextstat = NULL;
23900dc2366fSVenugopal Iyer
23910dc2366fSVenugopal Iyer if (head_stat == NULL) /* First node */
23920dc2366fSVenugopal Iyer head_stat = curr_stat;
23930dc2366fSVenugopal Iyer else
23940dc2366fSVenugopal Iyer prev_stat->nv_nextstat = curr_stat;
23950dc2366fSVenugopal Iyer
23960dc2366fSVenugopal Iyer prev_stat = curr_stat;
23970dc2366fSVenugopal Iyer }
23980dc2366fSVenugopal Iyer return (head_stat);
23990dc2366fSVenugopal Iyer }
24000dc2366fSVenugopal Iyer
24010dc2366fSVenugopal Iyer void *
build_nvs_entry(char * statheader,void * statentry,dladm_stat_type_t stattype)24020dc2366fSVenugopal Iyer build_nvs_entry(char *statheader, void *statentry, dladm_stat_type_t stattype)
24030dc2366fSVenugopal Iyer {
24040dc2366fSVenugopal Iyer name_value_stat_entry_t *name_value_stat_entry;
24050dc2366fSVenugopal Iyer dladm_stat_desc_t *stattbl_ptr;
24060dc2366fSVenugopal Iyer void *statfields;
24070dc2366fSVenugopal Iyer
24080dc2366fSVenugopal Iyer stattbl_ptr = &dladm_stat_table[stattype];
24090dc2366fSVenugopal Iyer
24100dc2366fSVenugopal Iyer /* Allocate memory for query all stat entry */
24110dc2366fSVenugopal Iyer name_value_stat_entry = calloc(1, sizeof (name_value_stat_entry_t));
24120dc2366fSVenugopal Iyer if (name_value_stat_entry == NULL)
24130dc2366fSVenugopal Iyer goto done;
24140dc2366fSVenugopal Iyer
24150dc2366fSVenugopal Iyer /* Header for these stat fields */
24160dc2366fSVenugopal Iyer (void) strlcpy(name_value_stat_entry->nve_header, statheader,
24170dc2366fSVenugopal Iyer sizeof (name_value_stat_entry->nve_header));
24180dc2366fSVenugopal Iyer
24190dc2366fSVenugopal Iyer /* Extract stat fields from the statentry */
24200dc2366fSVenugopal Iyer statfields = (uchar_t *)statentry +
24210dc2366fSVenugopal Iyer dladm_stat_table[stattype].ds_offset;
24220dc2366fSVenugopal Iyer
24230dc2366fSVenugopal Iyer /* Convert curr_stat to <statname, statval> pair */
24240dc2366fSVenugopal Iyer name_value_stat_entry->nve_stats =
24250dc2366fSVenugopal Iyer i_dlstat_convert_stats(statfields,
24260dc2366fSVenugopal Iyer stattbl_ptr->ds_statlist, stattbl_ptr->ds_statsize);
24270dc2366fSVenugopal Iyer done:
24280dc2366fSVenugopal Iyer return (name_value_stat_entry);
24290dc2366fSVenugopal Iyer }
24300dc2366fSVenugopal Iyer
24310dc2366fSVenugopal Iyer void *
i_walk_dlstat_chain(dladm_stat_chain_t * stat_head,dladm_stat_type_t stattype)24320dc2366fSVenugopal Iyer i_walk_dlstat_chain(dladm_stat_chain_t *stat_head, dladm_stat_type_t stattype)
24330dc2366fSVenugopal Iyer {
24340dc2366fSVenugopal Iyer dladm_stat_chain_t *curr;
24350dc2366fSVenugopal Iyer dladm_stat_chain_t *nvstat_head = NULL, *nvstat_prev = NULL;
24360dc2366fSVenugopal Iyer dladm_stat_chain_t *nvstat_curr;
24370dc2366fSVenugopal Iyer
24380dc2366fSVenugopal Iyer /*
24390dc2366fSVenugopal Iyer * For every stat in the chain, build header and convert all
24400dc2366fSVenugopal Iyer * its stat fields
24410dc2366fSVenugopal Iyer */
24420dc2366fSVenugopal Iyer for (curr = stat_head; curr != NULL; curr = curr->dc_next) {
24430dc2366fSVenugopal Iyer nvstat_curr = malloc(sizeof (dladm_stat_chain_t));
24440dc2366fSVenugopal Iyer if (nvstat_curr == NULL)
24450dc2366fSVenugopal Iyer break;
24460dc2366fSVenugopal Iyer
24470dc2366fSVenugopal Iyer nvstat_curr->dc_statentry = build_nvs_entry(curr->dc_statheader,
24480dc2366fSVenugopal Iyer curr->dc_statentry, stattype);
24490dc2366fSVenugopal Iyer
24500dc2366fSVenugopal Iyer if (nvstat_curr->dc_statentry == NULL) {
24510dc2366fSVenugopal Iyer free(nvstat_curr);
24520dc2366fSVenugopal Iyer break;
24530dc2366fSVenugopal Iyer }
24540dc2366fSVenugopal Iyer
24550dc2366fSVenugopal Iyer nvstat_curr->dc_next = NULL;
24560dc2366fSVenugopal Iyer
24570dc2366fSVenugopal Iyer if (nvstat_head == NULL) /* First node */
24580dc2366fSVenugopal Iyer nvstat_head = nvstat_curr;
24590dc2366fSVenugopal Iyer else
24600dc2366fSVenugopal Iyer nvstat_prev->dc_next = nvstat_curr;
24610dc2366fSVenugopal Iyer
24620dc2366fSVenugopal Iyer nvstat_prev = nvstat_curr;
24630dc2366fSVenugopal Iyer }
24640dc2366fSVenugopal Iyer done:
24650dc2366fSVenugopal Iyer return (nvstat_head);
24660dc2366fSVenugopal Iyer }
24670dc2366fSVenugopal Iyer
24680dc2366fSVenugopal Iyer dladm_stat_chain_t *
dladm_link_stat_query_all(dladm_handle_t dh,datalink_id_t linkid,dladm_stat_type_t stattype)24690dc2366fSVenugopal Iyer dladm_link_stat_query_all(dladm_handle_t dh, datalink_id_t linkid,
24700dc2366fSVenugopal Iyer dladm_stat_type_t stattype)
24710dc2366fSVenugopal Iyer {
24720dc2366fSVenugopal Iyer dladm_stat_chain_t *stat_head;
24730dc2366fSVenugopal Iyer dladm_stat_chain_t *nvstat_head = NULL;
24740dc2366fSVenugopal Iyer
24750dc2366fSVenugopal Iyer /* Query the requested stat */
24760dc2366fSVenugopal Iyer stat_head = dladm_link_stat_query(dh, linkid, stattype);
24770dc2366fSVenugopal Iyer if (stat_head == NULL)
24780dc2366fSVenugopal Iyer goto done;
24790dc2366fSVenugopal Iyer
24800dc2366fSVenugopal Iyer /*
24810dc2366fSVenugopal Iyer * Convert every statfield in every stat-entry of stat chain to
24820dc2366fSVenugopal Iyer * <statname, statval> pair
24830dc2366fSVenugopal Iyer */
24840dc2366fSVenugopal Iyer nvstat_head = i_walk_dlstat_chain(stat_head, stattype);
24850dc2366fSVenugopal Iyer
24860dc2366fSVenugopal Iyer /* Free stat_head */
24870dc2366fSVenugopal Iyer dladm_link_stat_free(stat_head);
24880dc2366fSVenugopal Iyer
24890dc2366fSVenugopal Iyer done:
24900dc2366fSVenugopal Iyer return (nvstat_head);
24910dc2366fSVenugopal Iyer }
24920dc2366fSVenugopal Iyer
24930dc2366fSVenugopal Iyer void
dladm_link_stat_query_all_free(dladm_stat_chain_t * curr)24940dc2366fSVenugopal Iyer dladm_link_stat_query_all_free(dladm_stat_chain_t *curr)
24950dc2366fSVenugopal Iyer {
24960dc2366fSVenugopal Iyer while (curr != NULL) {
24970dc2366fSVenugopal Iyer dladm_stat_chain_t *tofree = curr;
24980dc2366fSVenugopal Iyer name_value_stat_entry_t *nv_entry = curr->dc_statentry;
24990dc2366fSVenugopal Iyer name_value_stat_t *nv_curr = nv_entry->nve_stats;
25000dc2366fSVenugopal Iyer
25010dc2366fSVenugopal Iyer while (nv_curr != NULL) {
25020dc2366fSVenugopal Iyer name_value_stat_t *nv_tofree = nv_curr;
25030dc2366fSVenugopal Iyer
25040dc2366fSVenugopal Iyer nv_curr = nv_curr->nv_nextstat;
25050dc2366fSVenugopal Iyer free(nv_tofree);
25060dc2366fSVenugopal Iyer }
25070dc2366fSVenugopal Iyer
25080dc2366fSVenugopal Iyer curr = curr->dc_next;
25090dc2366fSVenugopal Iyer free(nv_entry);
25100dc2366fSVenugopal Iyer free(tofree);
25110dc2366fSVenugopal Iyer }
25120dc2366fSVenugopal Iyer }
25130dc2366fSVenugopal Iyer
25140dc2366fSVenugopal Iyer /* flow stats specific routines */
25150dc2366fSVenugopal Iyer flow_stat_t *
dladm_flow_stat_query(const char * flowname)25160dc2366fSVenugopal Iyer dladm_flow_stat_query(const char *flowname)
25170dc2366fSVenugopal Iyer {
25180dc2366fSVenugopal Iyer kstat_ctl_t *kcp;
25190dc2366fSVenugopal Iyer kstat_t *ksp;
25200dc2366fSVenugopal Iyer flow_stat_t *flow_stat = NULL;
25210dc2366fSVenugopal Iyer
25220dc2366fSVenugopal Iyer if ((kcp = kstat_open()) == NULL)
25230dc2366fSVenugopal Iyer return (NULL);
25240dc2366fSVenugopal Iyer
25250dc2366fSVenugopal Iyer flow_stat = calloc(1, sizeof (flow_stat_t));
25260dc2366fSVenugopal Iyer if (flow_stat == NULL)
25270dc2366fSVenugopal Iyer goto done;
25280dc2366fSVenugopal Iyer
25290dc2366fSVenugopal Iyer ksp = dladm_kstat_lookup(kcp, NULL, -1, flowname, "flow");
25300dc2366fSVenugopal Iyer
25310dc2366fSVenugopal Iyer if (ksp != NULL) {
25320dc2366fSVenugopal Iyer i_dlstat_get_stats(kcp, ksp, flow_stat, flow_stats_list,
25330dc2366fSVenugopal Iyer FLOW_STAT_SIZE);
25340dc2366fSVenugopal Iyer }
25350dc2366fSVenugopal Iyer
25360dc2366fSVenugopal Iyer done:
25370dc2366fSVenugopal Iyer (void) kstat_close(kcp);
25380dc2366fSVenugopal Iyer return (flow_stat);
25390dc2366fSVenugopal Iyer }
25400dc2366fSVenugopal Iyer
25410dc2366fSVenugopal Iyer flow_stat_t *
dladm_flow_stat_diff(flow_stat_t * op1,flow_stat_t * op2)25420dc2366fSVenugopal Iyer dladm_flow_stat_diff(flow_stat_t *op1, flow_stat_t *op2)
25430dc2366fSVenugopal Iyer {
25440dc2366fSVenugopal Iyer flow_stat_t *diff_stat;
25450dc2366fSVenugopal Iyer
25460dc2366fSVenugopal Iyer diff_stat = calloc(1, sizeof (flow_stat_t));
25470dc2366fSVenugopal Iyer if (diff_stat == NULL)
25480dc2366fSVenugopal Iyer goto done;
25490dc2366fSVenugopal Iyer
25500dc2366fSVenugopal Iyer if (op2 == NULL) {
25510dc2366fSVenugopal Iyer bcopy(op1, diff_stat, sizeof (flow_stat_t));
25520dc2366fSVenugopal Iyer } else {
25530dc2366fSVenugopal Iyer i_dlstat_diff_stats(diff_stat, op1, op2, flow_stats_list,
25540dc2366fSVenugopal Iyer FLOW_STAT_SIZE);
25550dc2366fSVenugopal Iyer }
25560dc2366fSVenugopal Iyer done:
25570dc2366fSVenugopal Iyer return (diff_stat);
25580dc2366fSVenugopal Iyer }
25590dc2366fSVenugopal Iyer
25600dc2366fSVenugopal Iyer void
dladm_flow_stat_free(flow_stat_t * curr)25610dc2366fSVenugopal Iyer dladm_flow_stat_free(flow_stat_t *curr)
25620dc2366fSVenugopal Iyer {
25630dc2366fSVenugopal Iyer free(curr);
25640dc2366fSVenugopal Iyer }
25650dc2366fSVenugopal Iyer
25660dc2366fSVenugopal Iyer /* Query all flow stats */
25670dc2366fSVenugopal Iyer name_value_stat_entry_t *
dladm_flow_stat_query_all(const char * flowname)25680dc2366fSVenugopal Iyer dladm_flow_stat_query_all(const char *flowname)
25690dc2366fSVenugopal Iyer {
25700dc2366fSVenugopal Iyer flow_stat_t *flow_stat;
25710dc2366fSVenugopal Iyer name_value_stat_entry_t *name_value_stat_entry = NULL;
25720dc2366fSVenugopal Iyer
25730dc2366fSVenugopal Iyer /* Query flow stats */
25740dc2366fSVenugopal Iyer flow_stat = dladm_flow_stat_query(flowname);
25750dc2366fSVenugopal Iyer if (flow_stat == NULL)
25760dc2366fSVenugopal Iyer goto done;
25770dc2366fSVenugopal Iyer
25780dc2366fSVenugopal Iyer /* Allocate memory for query all stat entry */
25790dc2366fSVenugopal Iyer name_value_stat_entry = calloc(1, sizeof (name_value_stat_entry_t));
25800dc2366fSVenugopal Iyer if (name_value_stat_entry == NULL) {
25810dc2366fSVenugopal Iyer dladm_flow_stat_free(flow_stat);
25820dc2366fSVenugopal Iyer goto done;
25830dc2366fSVenugopal Iyer }
25840dc2366fSVenugopal Iyer
25850dc2366fSVenugopal Iyer /* Header for these stat fields */
25860dc2366fSVenugopal Iyer (void) strncpy(name_value_stat_entry->nve_header, flowname,
25870dc2366fSVenugopal Iyer MAXFLOWNAMELEN);
25880dc2366fSVenugopal Iyer
25890dc2366fSVenugopal Iyer /* Convert every statfield in flow_stat to <statname, statval> pair */
25900dc2366fSVenugopal Iyer name_value_stat_entry->nve_stats =
25910dc2366fSVenugopal Iyer i_dlstat_convert_stats(flow_stat, flow_stats_list, FLOW_STAT_SIZE);
25920dc2366fSVenugopal Iyer
25930dc2366fSVenugopal Iyer /* Free flow_stat */
25940dc2366fSVenugopal Iyer dladm_flow_stat_free(flow_stat);
25950dc2366fSVenugopal Iyer
25960dc2366fSVenugopal Iyer done:
25970dc2366fSVenugopal Iyer return (name_value_stat_entry);
25980dc2366fSVenugopal Iyer }
25990dc2366fSVenugopal Iyer
26000dc2366fSVenugopal Iyer void
dladm_flow_stat_query_all_free(name_value_stat_entry_t * curr)26010dc2366fSVenugopal Iyer dladm_flow_stat_query_all_free(name_value_stat_entry_t *curr)
26020dc2366fSVenugopal Iyer {
26030dc2366fSVenugopal Iyer name_value_stat_t *nv_curr = curr->nve_stats;
26040dc2366fSVenugopal Iyer
26050dc2366fSVenugopal Iyer while (nv_curr != NULL) {
26060dc2366fSVenugopal Iyer name_value_stat_t *nv_tofree = nv_curr;
26070dc2366fSVenugopal Iyer
26080dc2366fSVenugopal Iyer nv_curr = nv_curr->nv_nextstat;
26090dc2366fSVenugopal Iyer free(nv_tofree);
26100dc2366fSVenugopal Iyer }
26110dc2366fSVenugopal Iyer }
2612