4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2015 Garrett D'Amore <garret@damore.org>
26 * Copyright 2016 Joyent, Inc.
29 #include <sys/types.h>
30 #include <sys/kstat.h>
33 #include <sys/softmac_impl.h>
35 typedef struct i_softmac_stat_info_s
{
39 } i_softmac_stat_info_t
;
42 * Must be the same order as mac_driver_stat.
44 static i_softmac_stat_info_t i_softmac_driver_si
[] = {
45 { MAC_STAT_IFSPEED
, "ifspeed", "link_speed" },
46 { MAC_STAT_MULTIRCV
, "multircv", NULL
},
47 { MAC_STAT_BRDCSTRCV
, "brdcstrcv", NULL
},
48 { MAC_STAT_MULTIXMT
, "multixmt", NULL
},
49 { MAC_STAT_BRDCSTXMT
, "brdcstxmt", NULL
},
50 { MAC_STAT_NORCVBUF
, "norcvbuf", "rx_no_buf" },
51 { MAC_STAT_IERRORS
, "ierrors", NULL
},
52 { MAC_STAT_UNKNOWNS
, "unknowns", NULL
},
53 { MAC_STAT_NOXMTBUF
, "noxmtbuf", "No Txpkt " },
54 { MAC_STAT_OERRORS
, "oerrors", NULL
},
55 { MAC_STAT_COLLISIONS
, "collisions", NULL
},
56 { MAC_STAT_RBYTES
, "rbytes64", "rbytes" },
57 { MAC_STAT_IPACKETS
, "ipackets64", "ipackets" },
58 { MAC_STAT_OBYTES
, "obytes64", "obytes" },
59 { MAC_STAT_OPACKETS
, "opackets64", "opackets" },
60 { MAC_STAT_UNDERFLOWS
, "uflo", NULL
},
61 { MAC_STAT_OVERFLOWS
, "oflo", NULL
}
64 #define SOFTMAC_DRIVER_SI_SZ \
65 (sizeof (i_softmac_driver_si) / sizeof (i_softmac_driver_si[0]))
68 * Must be the same order as ether_stat.
70 static i_softmac_stat_info_t i_softmac_ether_si
[] = {
71 { ETHER_STAT_ALIGN_ERRORS
, "align_errors",
73 { ETHER_STAT_FCS_ERRORS
, "fcs_errors", "crc_err" },
74 { ETHER_STAT_FIRST_COLLISIONS
, "first_collisions", NULL
},
75 { ETHER_STAT_MULTI_COLLISIONS
, "multi_collisions", NULL
},
76 { ETHER_STAT_SQE_ERRORS
, "sqe_errors", NULL
},
77 { ETHER_STAT_DEFER_XMTS
, "defer_xmts", NULL
},
78 { ETHER_STAT_TX_LATE_COLLISIONS
, "tx_late_collisions",
80 { ETHER_STAT_EX_COLLISIONS
, "ex_collisions",
81 "excessive_collisions" },
82 { ETHER_STAT_MACXMT_ERRORS
, "macxmt_errors", NULL
},
83 { ETHER_STAT_CARRIER_ERRORS
, "carrier_errors", NULL
},
84 { ETHER_STAT_TOOLONG_ERRORS
, "toolong_errors", "length_err" },
85 { ETHER_STAT_MACRCV_ERRORS
, "macrcv_errors",
88 { ETHER_STAT_XCVR_ADDR
, "xcvr_addr", NULL
},
89 { ETHER_STAT_XCVR_ID
, "xcvr_id", NULL
},
90 { ETHER_STAT_XCVR_INUSE
, "xcvr_inuse", NULL
},
92 { ETHER_STAT_CAP_1000FDX
, "cap_1000fdx", NULL
},
93 { ETHER_STAT_CAP_1000HDX
, "cap_1000hdx", NULL
},
94 { ETHER_STAT_CAP_100FDX
, "cap_100fdx", NULL
},
95 { ETHER_STAT_CAP_100HDX
, "cap_100hdx", NULL
},
96 { ETHER_STAT_CAP_10FDX
, "cap_10fdx", NULL
},
97 { ETHER_STAT_CAP_10HDX
, "cap_10hdx", NULL
},
98 { ETHER_STAT_CAP_ASMPAUSE
, "cap_asmpause", NULL
},
99 { ETHER_STAT_CAP_PAUSE
, "cap_pause", NULL
},
100 { ETHER_STAT_CAP_AUTONEG
, "cap_autoneg", NULL
},
102 { ETHER_STAT_ADV_CAP_1000FDX
, "adv_cap_1000fdx", NULL
},
103 { ETHER_STAT_ADV_CAP_1000HDX
, "adv_cap_1000hdx", NULL
},
104 { ETHER_STAT_ADV_CAP_100FDX
, "adv_cap_100fdx", NULL
},
105 { ETHER_STAT_ADV_CAP_100HDX
, "adv_cap_100hdx", NULL
},
106 { ETHER_STAT_ADV_CAP_10FDX
, "adv_cap_10fdx", NULL
},
107 { ETHER_STAT_ADV_CAP_10HDX
, "adv_cap_10hdx", NULL
},
108 { ETHER_STAT_ADV_CAP_ASMPAUSE
, "adv_cap_asmpause", NULL
},
109 { ETHER_STAT_ADV_CAP_PAUSE
, "adv_cap_pause", NULL
},
110 { ETHER_STAT_ADV_CAP_AUTONEG
, "adv_cap_autoneg", NULL
},
112 { ETHER_STAT_LP_CAP_1000FDX
, "lp_cap_1000fdx", NULL
},
113 { ETHER_STAT_LP_CAP_1000HDX
, "lp_cap_1000hdx", NULL
},
114 { ETHER_STAT_LP_CAP_100FDX
, "lp_cap_100fdx", NULL
},
115 { ETHER_STAT_LP_CAP_100HDX
, "lp_cap_100hdx", NULL
},
116 { ETHER_STAT_LP_CAP_10FDX
, "lp_cap_10fdx", NULL
},
117 { ETHER_STAT_LP_CAP_10HDX
, "lp_cap_10hdx", NULL
},
118 { ETHER_STAT_LP_CAP_ASMPAUSE
, "lp_cap_asmpause", NULL
},
119 { ETHER_STAT_LP_CAP_PAUSE
, "lp_cap_pause", NULL
},
120 { ETHER_STAT_LP_CAP_AUTONEG
, "lp_cap_autoneg", NULL
},
122 { ETHER_STAT_LINK_ASMPAUSE
, "link_asmpause", NULL
},
123 { ETHER_STAT_LINK_PAUSE
, "link_pause", NULL
},
124 { ETHER_STAT_LINK_AUTONEG
, "link_autoneg", NULL
},
125 { ETHER_STAT_LINK_DUPLEX
, "link_duplex", "duplex" },
127 { ETHER_STAT_TOOSHORT_ERRORS
, "runt_errors", NULL
},
128 { ETHER_STAT_CAP_REMFAULT
, "cap_rem_fault", NULL
},
129 { ETHER_STAT_ADV_REMFAULT
, "adv_rem_fault", NULL
},
130 { ETHER_STAT_LP_REMFAULT
, "lp_rem_fault", NULL
},
132 { ETHER_STAT_JABBER_ERRORS
, "jabber_errors", NULL
},
133 { ETHER_STAT_CAP_100T4
, "cap_100T4", NULL
},
134 { ETHER_STAT_ADV_CAP_100T4
, "adv_cap_100T4", NULL
},
135 { ETHER_STAT_LP_CAP_100T4
, "lp_cap_100T4", NULL
},
137 { ETHER_STAT_CAP_10GFDX
, "cap_10gfdx", NULL
},
138 { ETHER_STAT_ADV_CAP_10GFDX
, "adv_cap_10gfdx", NULL
},
139 { ETHER_STAT_LP_CAP_1000FDX
, "lp_cap_10gfdx", NULL
},
141 { ETHER_STAT_CAP_40GFDX
, "cap_40gfdx", NULL
},
142 { ETHER_STAT_ADV_CAP_40GFDX
, "adv_cap_40gfdx", NULL
},
143 { ETHER_STAT_LP_CAP_40GFDX
, "lp_cap_40gfdx", NULL
},
145 { ETHER_STAT_CAP_100GFDX
, "cap_100gfdx", NULL
},
146 { ETHER_STAT_ADV_CAP_100GFDX
, "adv_cap_100gfdx", NULL
},
147 { ETHER_STAT_LP_CAP_100GFDX
, "lp_cap_100gfdx", NULL
},
149 { ETHER_STAT_CAP_2500FDX
, "cap_2500fdx", NULL
},
150 { ETHER_STAT_ADV_CAP_2500FDX
, "adv_cap_2500fdx", NULL
},
151 { ETHER_STAT_LP_CAP_2500FDX
, "lp_cap_2500fdx", NULL
},
153 { ETHER_STAT_CAP_5000FDX
, "cap_5000fdx", NULL
},
154 { ETHER_STAT_ADV_CAP_5000FDX
, "adv_cap_5000fdx", NULL
},
155 { ETHER_STAT_LP_CAP_5000FDX
, "lp_cap_5000fdx", NULL
},
157 { ETHER_STAT_CAP_25GFDX
, "cap_25gfdx", NULL
},
158 { ETHER_STAT_ADV_CAP_25GFDX
, "adv_cap_25gfdx", NULL
},
159 { ETHER_STAT_LP_CAP_25GFDX
, "lp_cap_25gfdx", NULL
},
161 { ETHER_STAT_CAP_50GFDX
, "cap_50gfdx", NULL
},
162 { ETHER_STAT_ADV_CAP_50GFDX
, "adv_cap_50gfdx", NULL
},
163 { ETHER_STAT_LP_CAP_50GFDX
, "lp_cap_50gfdx", NULL
},
166 #define SOFTMAC_ETHER_SI_SZ \
167 (sizeof (i_softmac_ether_si) / sizeof (i_softmac_ether_si[0]))
169 static kstat_t
*softmac_hold_dev_kstat(softmac_t
*);
170 static void softmac_rele_dev_kstat(kstat_t
*);
171 static int softmac_get_kstat(kstat_t
*, char *, uint64_t *);
174 softmac_hold_dev_kstat(softmac_t
*softmac
)
176 char drv
[MAXLINKNAMELEN
];
180 if (ddi_parse(softmac
->smac_devname
, drv
, &ppa
) != DDI_SUCCESS
)
184 * Find the kstat by the module name and the instance number.
186 ksp
= kstat_hold_byname(drv
, ppa
, softmac
->smac_devname
, ALL_ZONES
);
190 if ((ksp
->ks_data
!= NULL
) &&
191 (ksp
->ks_type
== KSTAT_TYPE_NAMED
)) {
193 * Update the kstat to get the latest statistics.
195 if (KSTAT_UPDATE(ksp
, KSTAT_READ
) == 0)
206 softmac_rele_dev_kstat(kstat_t
*ksp
)
213 * The kstat needs to be held when calling this function.
216 softmac_get_kstat(kstat_t
*ksp
, char *name
, uint64_t *valp
)
226 * Search the kstat with the given name.
228 for (i
= 0, knp
= KSTAT_NAMED_PTR(ksp
); i
< ksp
->ks_ndata
; i
++, knp
++) {
229 if (strcmp(knp
->name
, name
) == 0) {
230 switch (knp
->data_type
) {
231 case KSTAT_DATA_INT32
:
232 case KSTAT_DATA_UINT32
:
233 *valp
= (uint64_t)(knp
->value
.ui32
);
236 case KSTAT_DATA_INT64
:
237 case KSTAT_DATA_UINT64
:
238 *valp
= knp
->value
.ui64
;
242 case KSTAT_DATA_LONG
:
243 case KSTAT_DATA_ULONG
:
244 *valp
= (uint64_t)knp
->value
.ul
;
248 case KSTAT_DATA_CHAR
:
249 if (strcmp(name
, "duplex") != 0)
251 if (strncmp(knp
->value
.c
, "full", 4) == 0)
252 *valp
= LINK_DUPLEX_FULL
;
253 else if (strncmp(knp
->value
.c
, "half", 4) == 0)
254 *valp
= LINK_DUPLEX_HALF
;
256 *valp
= LINK_DUPLEX_UNKNOWN
;
268 softmac_m_stat(void *arg
, uint_t stat
, uint64_t *val
)
270 softmac_t
*softmac
= arg
;
275 if ((ksp
= softmac_hold_dev_kstat(softmac
)) == NULL
)
278 if (IS_MAC_STAT(stat
)) {
279 i_softmac_stat_info_t
*ssip
= NULL
;
281 for (index
= 0; index
< SOFTMAC_DRIVER_SI_SZ
; index
++) {
282 if (stat
== i_softmac_driver_si
[index
].ssi_stat
) {
283 ssip
= &i_softmac_driver_si
[index
];
291 if ((ret
= softmac_get_kstat(ksp
, ssip
->ssi_name
,
293 ret
= softmac_get_kstat(ksp
, ssip
->ssi_alias
,
297 ASSERT(IS_MACTYPE_STAT(stat
));
299 switch (softmac
->smac_media
) {
301 i_softmac_stat_info_t
*ssip
= NULL
;
303 for (index
= 0; index
< SOFTMAC_ETHER_SI_SZ
; index
++) {
305 i_softmac_ether_si
[index
].ssi_stat
) {
306 ssip
= &i_softmac_ether_si
[index
];
314 if ((ret
= softmac_get_kstat(ksp
,
315 ssip
->ssi_name
, val
)) != 0)
316 ret
= softmac_get_kstat(ksp
,
317 ssip
->ssi_alias
, val
);
328 softmac_rele_dev_kstat(ksp
);