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