xref: /illumos-gate/usr/src/uts/common/io/mac/mac_stat.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2018 Joyent, Inc.
25  */
26 
27 /*
28  * MAC Services Module
29  */
30 
31 #include <sys/types.h>
32 #include <sys/sysmacros.h>
33 #include <sys/stream.h>
34 #include <sys/kstat.h>
35 #include <sys/mac.h>
36 #include <sys/mac_impl.h>
37 #include <sys/mac_client_impl.h>
38 #include <sys/mac_stat.h>
39 #include <sys/mac_soft_ring.h>
40 #include <sys/vlan.h>
41 
42 #define	MAC_KSTAT_NAME	"mac"
43 #define	MAC_KSTAT_CLASS	"net"
44 
45 enum mac_stat {
46 	MAC_STAT_LCL,
47 	MAC_STAT_LCLBYTES,
48 	MAC_STAT_INTRS,
49 	MAC_STAT_INTRBYTES,
50 	MAC_STAT_POLLS,
51 	MAC_STAT_POLLBYTES,
52 	MAC_STAT_RXSDROPS,
53 	MAC_STAT_CHU10,
54 	MAC_STAT_CH10T50,
55 	MAC_STAT_CHO50,
56 	MAC_STAT_BLOCK,
57 	MAC_STAT_UNBLOCK,
58 	MAC_STAT_TXSDROPS,
59 	MAC_STAT_TX_ERRORS,
60 	MAC_STAT_MACSPOOFED,
61 	MAC_STAT_IPSPOOFED,
62 	MAC_STAT_DHCPSPOOFED,
63 	MAC_STAT_RESTRICTED,
64 	MAC_STAT_DHCPDROPPED,
65 	MAC_STAT_MULTIRCVBYTES,
66 	MAC_STAT_BRDCSTRCVBYTES,
67 	MAC_STAT_MULTIXMTBYTES,
68 	MAC_STAT_BRDCSTXMTBYTES
69 };
70 
71 static mac_stat_info_t	i_mac_si[] = {
72 	{ MAC_STAT_IFSPEED,	"ifspeed",	KSTAT_DATA_UINT64,	0 },
73 	{ MAC_STAT_MULTIRCV,	"multircv",	KSTAT_DATA_UINT32,	0 },
74 	{ MAC_STAT_BRDCSTRCV,	"brdcstrcv",	KSTAT_DATA_UINT32,	0 },
75 	{ MAC_STAT_MULTIXMT,	"multixmt",	KSTAT_DATA_UINT32,	0 },
76 	{ MAC_STAT_BRDCSTXMT,	"brdcstxmt",	KSTAT_DATA_UINT32,	0 },
77 	{ MAC_STAT_NORCVBUF,	"norcvbuf",	KSTAT_DATA_UINT32,	0 },
78 	{ MAC_STAT_IERRORS,	"ierrors",	KSTAT_DATA_UINT32,	0 },
79 	{ MAC_STAT_UNKNOWNS,	"unknowns",	KSTAT_DATA_UINT32,	0 },
80 	{ MAC_STAT_NOXMTBUF,	"noxmtbuf",	KSTAT_DATA_UINT32,	0 },
81 	{ MAC_STAT_OERRORS,	"oerrors",	KSTAT_DATA_UINT32,	0 },
82 	{ MAC_STAT_COLLISIONS,	"collisions",	KSTAT_DATA_UINT32,	0 },
83 	{ MAC_STAT_UNDERFLOWS,	"uflo",		KSTAT_DATA_UINT32,	0 },
84 	{ MAC_STAT_OVERFLOWS,	"oflo",		KSTAT_DATA_UINT32,	0 },
85 	{ MAC_STAT_RBYTES,	"rbytes",	KSTAT_DATA_UINT32,	0 },
86 	{ MAC_STAT_IPACKETS,	"ipackets",	KSTAT_DATA_UINT32,	0 },
87 	{ MAC_STAT_OBYTES,	"obytes",	KSTAT_DATA_UINT32,	0 },
88 	{ MAC_STAT_OPACKETS,	"opackets",	KSTAT_DATA_UINT32,	0 },
89 	{ MAC_STAT_RBYTES,	"rbytes64",	KSTAT_DATA_UINT64,	0 },
90 	{ MAC_STAT_IPACKETS,	"ipackets64",	KSTAT_DATA_UINT64,	0 },
91 	{ MAC_STAT_OBYTES,	"obytes64",	KSTAT_DATA_UINT64,	0 },
92 	{ MAC_STAT_OPACKETS,	"opackets64",	KSTAT_DATA_UINT64,	0 }
93 };
94 #define	MAC_NKSTAT \
95 	(sizeof (i_mac_si) / sizeof (mac_stat_info_t))
96 
97 static mac_stat_info_t	i_mac_mod_si[] = {
98 	{ MAC_STAT_LINK_STATE,	"link_state",	KSTAT_DATA_UINT32,
99 	    (uint64_t)LINK_STATE_UNKNOWN },
100 	{ MAC_STAT_LINK_UP,	"link_up",	KSTAT_DATA_UINT32,	0 },
101 	{ MAC_STAT_PROMISC,	"promisc",	KSTAT_DATA_UINT32,	0 }
102 };
103 #define	MAC_MOD_NKSTAT \
104 	(sizeof (i_mac_mod_si) / sizeof (mac_stat_info_t))
105 
106 #define	MAC_MOD_KSTAT_OFFSET	0
107 #define	MAC_KSTAT_OFFSET	MAC_MOD_KSTAT_OFFSET + MAC_MOD_NKSTAT
108 #define	MAC_TYPE_KSTAT_OFFSET	MAC_KSTAT_OFFSET + MAC_NKSTAT
109 
110 /*
111  * Definitions for per rx ring statistics
112  */
113 static mac_stat_info_t  i_mac_rx_ring_si[] = {
114 	{ MAC_STAT_RBYTES,	"rbytes",	KSTAT_DATA_UINT64,	0},
115 	{ MAC_STAT_IPACKETS,	"ipackets",	KSTAT_DATA_UINT64,	0},
116 	{ MAC_STAT_HDROPS,	"hdrops",	KSTAT_DATA_UINT64,	0}
117 };
118 #define	MAC_RX_RING_NKSTAT \
119 	(sizeof (i_mac_rx_ring_si) / sizeof (mac_stat_info_t))
120 
121 /*
122  * Definitions for per tx ring statistics
123  */
124 static mac_stat_info_t  i_mac_tx_ring_si[] = {
125 	{ MAC_STAT_OBYTES,	"obytes",	KSTAT_DATA_UINT64,	0},
126 	{ MAC_STAT_OPACKETS,	"opackets",	KSTAT_DATA_UINT64,	0}
127 };
128 #define	MAC_TX_RING_NKSTAT \
129 	(sizeof (i_mac_tx_ring_si) / sizeof (mac_stat_info_t))
130 
131 
132 /*
133  * Definitions for per software lane tx statistics
134  */
135 static mac_stat_info_t  i_mac_tx_swlane_si[] = {
136 	{ MAC_STAT_OBYTES,	"obytes",	KSTAT_DATA_UINT64,	0},
137 	{ MAC_STAT_OPACKETS,	"opackets",	KSTAT_DATA_UINT64,	0},
138 	{ MAC_STAT_OERRORS,	"oerrors",	KSTAT_DATA_UINT64,	0},
139 	{ MAC_STAT_BLOCK,	"blockcnt",	KSTAT_DATA_UINT64,	0},
140 	{ MAC_STAT_UNBLOCK,	"unblockcnt",	KSTAT_DATA_UINT64,	0},
141 	{ MAC_STAT_TXSDROPS,	"txsdrops",	KSTAT_DATA_UINT64,	0}
142 };
143 #define	MAC_TX_SWLANE_NKSTAT \
144 	(sizeof (i_mac_tx_swlane_si) / sizeof (mac_stat_info_t))
145 
146 /*
147  * Definitions for per software lane rx statistics
148  */
149 static mac_stat_info_t  i_mac_rx_swlane_si[] = {
150 	{ MAC_STAT_IPACKETS,	"ipackets",	KSTAT_DATA_UINT64,	0},
151 	{ MAC_STAT_RBYTES,	"rbytes",	KSTAT_DATA_UINT64,	0},
152 	{ MAC_STAT_LCL,		"local",	KSTAT_DATA_UINT64,	0},
153 	{ MAC_STAT_LCLBYTES,	"localbytes",	KSTAT_DATA_UINT64,	0},
154 	{ MAC_STAT_INTRS,	"intrs",	KSTAT_DATA_UINT64,	0},
155 	{ MAC_STAT_INTRBYTES,	"intrbytes",	KSTAT_DATA_UINT64,	0},
156 	{ MAC_STAT_RXSDROPS,	"rxsdrops",	KSTAT_DATA_UINT64,	0}
157 };
158 #define	MAC_RX_SWLANE_NKSTAT \
159 	(sizeof (i_mac_rx_swlane_si) / sizeof (mac_stat_info_t))
160 
161 /*
162  * Definitions for per hardware lane rx statistics
163  */
164 static mac_stat_info_t  i_mac_rx_hwlane_si[] = {
165 	{ MAC_STAT_IPACKETS,	"ipackets",	KSTAT_DATA_UINT64,	0},
166 	{ MAC_STAT_RBYTES,	"rbytes",	KSTAT_DATA_UINT64,	0},
167 	{ MAC_STAT_INTRS,	"intrs",	KSTAT_DATA_UINT64,	0},
168 	{ MAC_STAT_INTRBYTES,	"intrbytes",	KSTAT_DATA_UINT64,	0},
169 	{ MAC_STAT_POLLS,	"polls",	KSTAT_DATA_UINT64,	0},
170 	{ MAC_STAT_POLLBYTES,	"pollbytes",	KSTAT_DATA_UINT64,	0},
171 	{ MAC_STAT_RXSDROPS,	"rxsdrops",	KSTAT_DATA_UINT64,	0},
172 	{ MAC_STAT_CHU10,	"chainunder10",	KSTAT_DATA_UINT64,	0},
173 	{ MAC_STAT_CH10T50,	"chain10to50",	KSTAT_DATA_UINT64,	0},
174 	{ MAC_STAT_CHO50,	"chainover50",	KSTAT_DATA_UINT64,	0}
175 };
176 #define	MAC_RX_HWLANE_NKSTAT \
177 	(sizeof (i_mac_rx_hwlane_si) / sizeof (mac_stat_info_t))
178 
179 /*
180  * Definitions for misc statistics
181  */
182 static mac_stat_info_t  i_mac_misc_si[] = {
183 	{ MAC_STAT_MULTIRCV,	"multircv",	KSTAT_DATA_UINT64,	0},
184 	{ MAC_STAT_BRDCSTRCV,	"brdcstrcv",	KSTAT_DATA_UINT64,	0},
185 	{ MAC_STAT_MULTIXMT,	"multixmt",	KSTAT_DATA_UINT64,	0},
186 	{ MAC_STAT_BRDCSTXMT,	"brdcstxmt",	KSTAT_DATA_UINT64,	0},
187 	{ MAC_STAT_MULTIRCVBYTES, "multircvbytes",   KSTAT_DATA_UINT64,	0},
188 	{ MAC_STAT_BRDCSTRCVBYTES, "brdcstrcvbytes", KSTAT_DATA_UINT64,	0},
189 	{ MAC_STAT_MULTIXMTBYTES,  "multixmtbytes",  KSTAT_DATA_UINT64,	0},
190 	{ MAC_STAT_BRDCSTXMTBYTES, "brdcstxmtbytes", KSTAT_DATA_UINT64,	0},
191 	{ MAC_STAT_TX_ERRORS,	"txerrors",	KSTAT_DATA_UINT64,	0},
192 	{ MAC_STAT_MACSPOOFED,	"macspoofed",	KSTAT_DATA_UINT64,	0},
193 	{ MAC_STAT_IPSPOOFED,	"ipspoofed",	KSTAT_DATA_UINT64,	0},
194 	{ MAC_STAT_DHCPSPOOFED,	"dhcpspoofed",	KSTAT_DATA_UINT64,	0},
195 	{ MAC_STAT_RESTRICTED,	"restricted",	KSTAT_DATA_UINT64,	0},
196 	{ MAC_STAT_DHCPDROPPED,	"dhcpdropped",	KSTAT_DATA_UINT64,	0},
197 	{ MAC_STAT_IPACKETS,	"ipackets",	KSTAT_DATA_UINT64,	0},
198 	{ MAC_STAT_RBYTES,	"rbytes",	KSTAT_DATA_UINT64,	0},
199 	{ MAC_STAT_LCL,		"local",	KSTAT_DATA_UINT64,	0},
200 	{ MAC_STAT_LCLBYTES,	"localbytes",	KSTAT_DATA_UINT64,	0},
201 	{ MAC_STAT_INTRS,	"intrs",	KSTAT_DATA_UINT64,	0},
202 	{ MAC_STAT_INTRBYTES,	"intrbytes",	KSTAT_DATA_UINT64,	0},
203 	{ MAC_STAT_POLLS,	"polls",	KSTAT_DATA_UINT64,	0},
204 	{ MAC_STAT_POLLBYTES,	"pollbytes",	KSTAT_DATA_UINT64,	0},
205 	{ MAC_STAT_RXSDROPS,	"rxsdrops",	KSTAT_DATA_UINT64,	0},
206 	{ MAC_STAT_CHU10,	"chainunder10",	KSTAT_DATA_UINT64,	0},
207 	{ MAC_STAT_CH10T50,	"chain10to50",	KSTAT_DATA_UINT64,	0},
208 	{ MAC_STAT_CHO50,	"chainover50",	KSTAT_DATA_UINT64,	0},
209 	{ MAC_STAT_OBYTES,	"obytes",	KSTAT_DATA_UINT64,	0},
210 	{ MAC_STAT_OPACKETS,	"opackets",	KSTAT_DATA_UINT64,	0},
211 	{ MAC_STAT_OERRORS,	"oerrors",	KSTAT_DATA_UINT64,	0},
212 	{ MAC_STAT_BLOCK,	"blockcnt",	KSTAT_DATA_UINT64,	0},
213 	{ MAC_STAT_UNBLOCK,	"unblockcnt",	KSTAT_DATA_UINT64,	0},
214 	{ MAC_STAT_TXSDROPS,	"txsdrops",	KSTAT_DATA_UINT64,	0}
215 };
216 #define	MAC_SUMMARY_NKSTAT \
217 	(sizeof (i_mac_misc_si) / sizeof (mac_stat_info_t))
218 
219 /*
220  * Definitions for per hardware lane tx statistics
221  */
222 static mac_stat_info_t  i_mac_tx_hwlane_si[] = {
223 	{ MAC_STAT_OBYTES,	"obytes",	KSTAT_DATA_UINT64,	0},
224 	{ MAC_STAT_OPACKETS,	"opackets",	KSTAT_DATA_UINT64,	0},
225 	{ MAC_STAT_OERRORS,	"oerrors",	KSTAT_DATA_UINT64,	0},
226 	{ MAC_STAT_BLOCK,	"blockcnt",	KSTAT_DATA_UINT64,	0},
227 	{ MAC_STAT_UNBLOCK,	"unblockcnt",	KSTAT_DATA_UINT64,	0},
228 	{ MAC_STAT_TXSDROPS,	"txsdrops",	KSTAT_DATA_UINT64,	0}
229 };
230 #define	MAC_TX_HWLANE_NKSTAT \
231 	(sizeof (i_mac_tx_hwlane_si) / sizeof (mac_stat_info_t))
232 
233 /*
234  * Definitions for per fanout rx statistics
235  */
236 static mac_stat_info_t  i_mac_rx_fanout_si[] = {
237 	{ MAC_STAT_RBYTES,	"rbytes",	KSTAT_DATA_UINT64,	0},
238 	{ MAC_STAT_IPACKETS,	"ipackets",	KSTAT_DATA_UINT64,	0},
239 };
240 #define	MAC_RX_FANOUT_NKSTAT \
241 	(sizeof (i_mac_rx_fanout_si) / sizeof (mac_stat_info_t))
242 
243 /*
244  * Private functions.
245  */
246 
247 typedef struct {
248 	uint_t	si_offset;
249 } stat_info_t;
250 
251 #define	RX_SRS_STAT_OFF(f)	(offsetof(mac_rx_stats_t, f))
252 static stat_info_t rx_srs_stats_list[] = {
253 	{RX_SRS_STAT_OFF(mrs_lclbytes)},
254 	{RX_SRS_STAT_OFF(mrs_lclcnt)},
255 	{RX_SRS_STAT_OFF(mrs_pollcnt)},
256 	{RX_SRS_STAT_OFF(mrs_pollbytes)},
257 	{RX_SRS_STAT_OFF(mrs_intrcnt)},
258 	{RX_SRS_STAT_OFF(mrs_intrbytes)},
259 	{RX_SRS_STAT_OFF(mrs_sdrops)},
260 	{RX_SRS_STAT_OFF(mrs_chaincntundr10)},
261 	{RX_SRS_STAT_OFF(mrs_chaincnt10to50)},
262 	{RX_SRS_STAT_OFF(mrs_chaincntover50)},
263 	{RX_SRS_STAT_OFF(mrs_ierrors)}
264 };
265 #define	RX_SRS_STAT_SIZE		\
266 	(sizeof (rx_srs_stats_list) / sizeof (stat_info_t))
267 
268 #define	TX_SOFTRING_STAT_OFF(f)	(offsetof(mac_tx_stats_t, f))
269 static stat_info_t tx_softring_stats_list[] = {
270 	{TX_SOFTRING_STAT_OFF(mts_obytes)},
271 	{TX_SOFTRING_STAT_OFF(mts_opackets)},
272 	{TX_SOFTRING_STAT_OFF(mts_oerrors)},
273 	{TX_SOFTRING_STAT_OFF(mts_blockcnt)},
274 	{TX_SOFTRING_STAT_OFF(mts_unblockcnt)},
275 	{TX_SOFTRING_STAT_OFF(mts_sdrops)},
276 };
277 #define	TX_SOFTRING_STAT_SIZE		\
278 	(sizeof (tx_softring_stats_list) / sizeof (stat_info_t))
279 
280 static void
281 i_mac_add_stats(void *sum, void *op1, void *op2,
282     stat_info_t stats_list[], uint_t size)
283 {
284 	int	i;
285 
286 	for (i = 0; i < size; i++) {
287 		uint64_t *op1_val = (uint64_t *)
288 		    ((uchar_t *)op1 + stats_list[i].si_offset);
289 		uint64_t *op2_val = (uint64_t *)
290 		    ((uchar_t *)op2 + stats_list[i].si_offset);
291 		uint64_t *sum_val = (uint64_t *)
292 		    ((uchar_t *)sum + stats_list[i].si_offset);
293 
294 		*sum_val =  *op1_val + *op2_val;
295 	}
296 }
297 
298 static int
299 i_mac_driver_stat_update(kstat_t *ksp, int rw)
300 {
301 	mac_impl_t	*mip = ksp->ks_private;
302 	kstat_named_t	*knp = ksp->ks_data;
303 	uint_t		i;
304 	uint64_t	val;
305 	mac_stat_info_t	*msi;
306 	uint_t		msi_index;
307 
308 	if (rw != KSTAT_READ)
309 		return (EACCES);
310 
311 	for (i = 0; i < mip->mi_kstat_count; i++, msi_index++) {
312 		if (i == MAC_MOD_KSTAT_OFFSET) {
313 			msi_index = 0;
314 			msi = i_mac_mod_si;
315 		} else if (i == MAC_KSTAT_OFFSET) {
316 			msi_index = 0;
317 			msi = i_mac_si;
318 		} else if (i == MAC_TYPE_KSTAT_OFFSET) {
319 			msi_index = 0;
320 			msi = mip->mi_type->mt_stats;
321 		}
322 
323 		val = mac_stat_get((mac_handle_t)mip, msi[msi_index].msi_stat);
324 		switch (msi[msi_index].msi_type) {
325 		case KSTAT_DATA_UINT64:
326 			knp->value.ui64 = val;
327 			break;
328 		case KSTAT_DATA_UINT32:
329 			knp->value.ui32 = (uint32_t)val;
330 			break;
331 		default:
332 			ASSERT(B_FALSE);
333 			break;
334 		}
335 
336 		knp++;
337 	}
338 
339 	return (0);
340 }
341 
342 static void
343 i_mac_kstat_init(kstat_named_t *knp, mac_stat_info_t *si, uint_t count)
344 {
345 	int i;
346 	for (i = 0; i < count; i++) {
347 		kstat_named_init(knp, si[i].msi_name, si[i].msi_type);
348 		knp++;
349 	}
350 }
351 
352 static int
353 i_mac_stat_update(kstat_t *ksp, int rw, uint64_t (*fn)(void *, uint_t),
354     mac_stat_info_t *msi, uint_t count)
355 {
356 	kstat_named_t	*knp = ksp->ks_data;
357 	uint_t		i;
358 	uint64_t	val;
359 
360 	if (rw != KSTAT_READ)
361 		return (EACCES);
362 
363 	for (i = 0; i < count; i++) {
364 		val = fn(ksp->ks_private, msi[i].msi_stat);
365 
366 		switch (msi[i].msi_type) {
367 		case KSTAT_DATA_UINT64:
368 			knp->value.ui64 = val;
369 			break;
370 		case KSTAT_DATA_UINT32:
371 			knp->value.ui32 = (uint32_t)val;
372 			break;
373 		default:
374 			ASSERT(B_FALSE);
375 			break;
376 		}
377 		knp++;
378 	}
379 	return (0);
380 }
381 
382 /*
383  * Create kstat with given name - statname, update function - fn
384  * and initialize it with given names - init_stat_info
385  */
386 static kstat_t *
387 i_mac_stat_create(void *handle, const char *modname, const char *statname,
388     int (*fn) (kstat_t *, int),
389     mac_stat_info_t *init_stat_info, uint_t count)
390 {
391 	kstat_t		*ksp;
392 	kstat_named_t	*knp;
393 
394 	ksp = kstat_create(modname, 0, statname, "net",
395 	    KSTAT_TYPE_NAMED, count, 0);
396 
397 	if (ksp == NULL)
398 		return (NULL);
399 
400 	ksp->ks_update = fn;
401 	ksp->ks_private = handle;
402 
403 	knp = (kstat_named_t *)ksp->ks_data;
404 	i_mac_kstat_init(knp, init_stat_info, count);
405 	kstat_install(ksp);
406 
407 	return (ksp);
408 }
409 
410 /*
411  * Per rx ring statistics
412  */
413 uint64_t
414 mac_rx_ring_stat_get(void *handle, uint_t stat)
415 {
416 	mac_ring_t		*ring = (mac_ring_t *)handle;
417 	uint64_t		val = 0;
418 
419 	/*
420 	 * XXX Every ring-capable driver must implement an entry point to
421 	 * query per ring statistics. CR 6893122 tracks this work item.
422 	 * Once this bug is fixed, the framework should fail registration
423 	 * for a driver that does not implement this entry point and
424 	 * assert ring->mr_stat != NULL here.
425 	 */
426 	if (ring->mr_stat != NULL)
427 		ring->mr_stat(ring->mr_driver, stat, &val);
428 
429 	return (val);
430 }
431 
432 static int
433 i_mac_rx_ring_stat_update(kstat_t *ksp, int rw)
434 {
435 	return (i_mac_stat_update(ksp, rw, mac_rx_ring_stat_get,
436 	    i_mac_rx_ring_si, MAC_RX_RING_NKSTAT));
437 }
438 
439 static void
440 i_mac_rx_ring_stat_create(mac_ring_t *ring, const char *modname,
441     const char *statname)
442 {
443 	kstat_t		*ksp;
444 
445 	ksp = i_mac_stat_create(ring, modname, statname,
446 	    i_mac_rx_ring_stat_update, i_mac_rx_ring_si, MAC_RX_RING_NKSTAT);
447 
448 	ring->mr_ksp = ksp;
449 }
450 
451 /*
452  * Per tx ring statistics
453  */
454 uint64_t
455 mac_tx_ring_stat_get(void *handle, uint_t stat)
456 {
457 	mac_ring_t		*ring = (mac_ring_t *)handle;
458 	uint64_t		val = 0;
459 
460 	/*
461 	 * XXX Every ring-capable driver must implement an entry point to
462 	 * query per ring statistics. CR 6893122 tracks this work item.
463 	 * Once this bug is fixed, the framework should fail registration
464 	 * for a driver that does not implement this entry point and
465 	 * assert ring->mr_stat != NULL here.
466 	 */
467 	if (ring->mr_stat != NULL)
468 		ring->mr_stat(ring->mr_driver, stat, &val);
469 
470 	return (val);
471 }
472 
473 static int
474 i_mac_tx_ring_stat_update(kstat_t *ksp, int rw)
475 {
476 	return (i_mac_stat_update(ksp, rw, mac_tx_ring_stat_get,
477 	    i_mac_tx_ring_si, MAC_TX_RING_NKSTAT));
478 }
479 
480 static void
481 i_mac_tx_ring_stat_create(mac_ring_t *ring, const char *modname,
482     const char *statname)
483 {
484 	kstat_t		*ksp;
485 
486 	ksp = i_mac_stat_create(ring, modname, statname,
487 	    i_mac_tx_ring_stat_update, i_mac_tx_ring_si, MAC_TX_RING_NKSTAT);
488 
489 	ring->mr_ksp = ksp;
490 }
491 
492 /*
493  * Per software lane tx statistics
494  */
495 static uint64_t
496 i_mac_tx_swlane_stat_get(void *handle, uint_t stat)
497 {
498 	mac_soft_ring_set_t *mac_srs = (mac_soft_ring_set_t *)handle;
499 	mac_tx_stats_t *mac_tx_stat = &mac_srs->srs_tx.st_stat;
500 
501 	switch (stat) {
502 	case MAC_STAT_OBYTES:
503 		return (mac_tx_stat->mts_obytes);
504 
505 	case MAC_STAT_OPACKETS:
506 		return (mac_tx_stat->mts_opackets);
507 
508 	case MAC_STAT_OERRORS:
509 		return (mac_tx_stat->mts_oerrors);
510 
511 	case MAC_STAT_BLOCK:
512 		return (mac_tx_stat->mts_blockcnt);
513 
514 	case MAC_STAT_UNBLOCK:
515 		return (mac_tx_stat->mts_unblockcnt);
516 
517 	case MAC_STAT_TXSDROPS:
518 		return (mac_tx_stat->mts_sdrops);
519 
520 	default:
521 		return (0);
522 	}
523 }
524 
525 static int
526 i_mac_tx_swlane_stat_update(kstat_t *ksp, int rw)
527 {
528 	return (i_mac_stat_update(ksp, rw, i_mac_tx_swlane_stat_get,
529 	    i_mac_tx_swlane_si, MAC_TX_SWLANE_NKSTAT));
530 }
531 
532 static void
533 i_mac_tx_swlane_stat_create(mac_soft_ring_set_t *mac_srs, const char *modname,
534     const char *statname)
535 {
536 	kstat_t		*ksp;
537 
538 	ksp = i_mac_stat_create(mac_srs, modname, statname,
539 	    i_mac_tx_swlane_stat_update, i_mac_tx_swlane_si,
540 	    MAC_TX_SWLANE_NKSTAT);
541 
542 	mac_srs->srs_ksp = ksp;
543 }
544 
545 /*
546  * Per software lane rx statistics
547  */
548 static uint64_t
549 i_mac_rx_swlane_stat_get(void *handle, uint_t stat)
550 {
551 	mac_soft_ring_set_t	*mac_srs = (mac_soft_ring_set_t *)handle;
552 	mac_rx_stats_t		*mac_rx_stat = &mac_srs->srs_rx.sr_stat;
553 
554 	switch (stat) {
555 	case MAC_STAT_IPACKETS:
556 		return (mac_rx_stat->mrs_intrcnt +
557 		    mac_rx_stat->mrs_lclcnt);
558 
559 	case MAC_STAT_RBYTES:
560 		return (mac_rx_stat->mrs_intrbytes +
561 		    mac_rx_stat->mrs_lclbytes);
562 
563 	case MAC_STAT_LCL:
564 		return (mac_rx_stat->mrs_lclcnt);
565 
566 	case MAC_STAT_LCLBYTES:
567 		return (mac_rx_stat->mrs_lclbytes);
568 
569 	case MAC_STAT_INTRS:
570 		return (mac_rx_stat->mrs_intrcnt);
571 
572 	case MAC_STAT_INTRBYTES:
573 		return (mac_rx_stat->mrs_intrbytes);
574 
575 	case MAC_STAT_RXSDROPS:
576 		return (mac_rx_stat->mrs_sdrops);
577 
578 	default:
579 		return (0);
580 	}
581 }
582 
583 static int
584 i_mac_rx_swlane_stat_update(kstat_t *ksp, int rw)
585 {
586 	return (i_mac_stat_update(ksp, rw, i_mac_rx_swlane_stat_get,
587 	    i_mac_rx_swlane_si, MAC_RX_SWLANE_NKSTAT));
588 }
589 
590 static void
591 i_mac_rx_swlane_stat_create(mac_soft_ring_set_t *mac_srs, const char *modname,
592     const char *statname)
593 {
594 	kstat_t		*ksp;
595 
596 	ksp = i_mac_stat_create(mac_srs, modname, statname,
597 	    i_mac_rx_swlane_stat_update, i_mac_rx_swlane_si,
598 	    MAC_RX_SWLANE_NKSTAT);
599 
600 	mac_srs->srs_ksp = ksp;
601 }
602 
603 
604 /*
605  * Per hardware lane rx statistics
606  */
607 static uint64_t
608 i_mac_rx_hwlane_stat_get(void *handle, uint_t stat)
609 {
610 	mac_soft_ring_set_t	*mac_srs = (mac_soft_ring_set_t *)handle;
611 	mac_rx_stats_t		*mac_rx_stat = &mac_srs->srs_rx.sr_stat;
612 
613 	switch (stat) {
614 	case MAC_STAT_IPACKETS:
615 		return (mac_rx_stat->mrs_intrcnt +
616 		    mac_rx_stat->mrs_pollcnt);
617 
618 	case MAC_STAT_RBYTES:
619 		return (mac_rx_stat->mrs_intrbytes +
620 		    mac_rx_stat->mrs_pollbytes);
621 
622 	case MAC_STAT_INTRS:
623 		return (mac_rx_stat->mrs_intrcnt);
624 
625 	case MAC_STAT_INTRBYTES:
626 		return (mac_rx_stat->mrs_intrbytes);
627 
628 	case MAC_STAT_POLLS:
629 		return (mac_rx_stat->mrs_pollcnt);
630 
631 	case MAC_STAT_POLLBYTES:
632 		return (mac_rx_stat->mrs_pollbytes);
633 
634 	case MAC_STAT_RXSDROPS:
635 		return (mac_rx_stat->mrs_sdrops);
636 
637 	case MAC_STAT_CHU10:
638 		return (mac_rx_stat->mrs_chaincntundr10);
639 
640 	case MAC_STAT_CH10T50:
641 		return (mac_rx_stat->mrs_chaincnt10to50);
642 
643 	case MAC_STAT_CHO50:
644 		return (mac_rx_stat->mrs_chaincntover50);
645 
646 	default:
647 		return (0);
648 	}
649 }
650 
651 static int
652 i_mac_rx_hwlane_stat_update(kstat_t *ksp, int rw)
653 {
654 	return (i_mac_stat_update(ksp, rw, i_mac_rx_hwlane_stat_get,
655 	    i_mac_rx_hwlane_si, MAC_RX_HWLANE_NKSTAT));
656 }
657 
658 static void
659 i_mac_rx_hwlane_stat_create(mac_soft_ring_set_t *mac_srs, const char *modname,
660     const char *statname)
661 {
662 	kstat_t		*ksp;
663 
664 	ksp = i_mac_stat_create(mac_srs, modname, statname,
665 	    i_mac_rx_hwlane_stat_update, i_mac_rx_hwlane_si,
666 	    MAC_RX_HWLANE_NKSTAT);
667 
668 	mac_srs->srs_ksp = ksp;
669 }
670 
671 
672 /*
673  * Misc statistics
674  *
675  * Counts for
676  *	- Multicast/broadcast Rx/Tx counts
677  *	- Tx errors
678  */
679 static uint64_t
680 i_mac_misc_stat_get(void *handle, uint_t stat)
681 {
682 	flow_entry_t		*flent = handle;
683 	mac_client_impl_t	*mcip = flent->fe_mcip;
684 	mac_misc_stats_t	*mac_misc_stat = &mcip->mci_misc_stat;
685 	mac_rx_stats_t		*mac_rx_stat;
686 	mac_tx_stats_t		*mac_tx_stat;
687 
688 	mac_rx_stat = &mac_misc_stat->mms_defunctrxlanestats;
689 	mac_tx_stat = &mac_misc_stat->mms_defuncttxlanestats;
690 
691 	switch (stat) {
692 	case MAC_STAT_MULTIRCV:
693 		return (mac_misc_stat->mms_multircv);
694 
695 	case MAC_STAT_BRDCSTRCV:
696 		return (mac_misc_stat->mms_brdcstrcv);
697 
698 	case MAC_STAT_MULTIXMT:
699 		return (mac_misc_stat->mms_multixmt);
700 
701 	case MAC_STAT_BRDCSTXMT:
702 		return (mac_misc_stat->mms_brdcstxmt);
703 
704 	case MAC_STAT_MULTIRCVBYTES:
705 		return (mac_misc_stat->mms_multircvbytes);
706 
707 	case MAC_STAT_BRDCSTRCVBYTES:
708 		return (mac_misc_stat->mms_brdcstrcvbytes);
709 
710 	case MAC_STAT_MULTIXMTBYTES:
711 		return (mac_misc_stat->mms_multixmtbytes);
712 
713 	case MAC_STAT_BRDCSTXMTBYTES:
714 		return (mac_misc_stat->mms_brdcstxmtbytes);
715 
716 	case MAC_STAT_TX_ERRORS:
717 		return (mac_misc_stat->mms_txerrors);
718 
719 	case MAC_STAT_MACSPOOFED:
720 		return (mac_misc_stat->mms_macspoofed);
721 
722 	case MAC_STAT_IPSPOOFED:
723 		return (mac_misc_stat->mms_ipspoofed);
724 
725 	case MAC_STAT_DHCPSPOOFED:
726 		return (mac_misc_stat->mms_dhcpspoofed);
727 
728 	case MAC_STAT_RESTRICTED:
729 		return (mac_misc_stat->mms_restricted);
730 
731 	case MAC_STAT_DHCPDROPPED:
732 		return (mac_misc_stat->mms_dhcpdropped);
733 
734 	case MAC_STAT_IPACKETS:
735 		return (mac_rx_stat->mrs_intrcnt +
736 		    mac_rx_stat->mrs_pollcnt);
737 
738 	case MAC_STAT_RBYTES:
739 		return (mac_rx_stat->mrs_intrbytes +
740 		    mac_rx_stat->mrs_pollbytes);
741 
742 	case MAC_STAT_LCL:
743 		return (mac_rx_stat->mrs_lclcnt);
744 
745 	case MAC_STAT_LCLBYTES:
746 		return (mac_rx_stat->mrs_lclbytes);
747 
748 	case MAC_STAT_INTRS:
749 		return (mac_rx_stat->mrs_intrcnt);
750 
751 	case MAC_STAT_INTRBYTES:
752 		return (mac_rx_stat->mrs_intrbytes);
753 
754 	case MAC_STAT_POLLS:
755 		return (mac_rx_stat->mrs_pollcnt);
756 
757 	case MAC_STAT_POLLBYTES:
758 		return (mac_rx_stat->mrs_pollbytes);
759 
760 	case MAC_STAT_RXSDROPS:
761 		return (mac_rx_stat->mrs_sdrops);
762 
763 	case MAC_STAT_CHU10:
764 		return (mac_rx_stat->mrs_chaincntundr10);
765 
766 	case MAC_STAT_CH10T50:
767 		return (mac_rx_stat->mrs_chaincnt10to50);
768 
769 	case MAC_STAT_CHO50:
770 		return (mac_rx_stat->mrs_chaincntover50);
771 
772 	case MAC_STAT_OBYTES:
773 		return (mac_tx_stat->mts_obytes);
774 
775 	case MAC_STAT_OPACKETS:
776 		return (mac_tx_stat->mts_opackets);
777 
778 	case MAC_STAT_OERRORS:
779 		return (mac_tx_stat->mts_oerrors);
780 
781 	case MAC_STAT_BLOCK:
782 		return (mac_tx_stat->mts_blockcnt);
783 
784 	case MAC_STAT_UNBLOCK:
785 		return (mac_tx_stat->mts_unblockcnt);
786 
787 	case MAC_STAT_TXSDROPS:
788 		return (mac_tx_stat->mts_sdrops);
789 
790 	default:
791 		return (0);
792 	}
793 }
794 
795 static int
796 i_mac_misc_stat_update(kstat_t *ksp, int rw)
797 {
798 	return (i_mac_stat_update(ksp, rw, i_mac_misc_stat_get,
799 	    i_mac_misc_si, MAC_SUMMARY_NKSTAT));
800 }
801 
802 static void
803 i_mac_misc_stat_create(flow_entry_t *flent, const char *modname,
804     const char *statname)
805 {
806 	kstat_t		*ksp;
807 
808 	ksp = i_mac_stat_create(flent, modname, statname,
809 	    i_mac_misc_stat_update, i_mac_misc_si,
810 	    MAC_SUMMARY_NKSTAT);
811 
812 	flent->fe_misc_stat_ksp = ksp;
813 }
814 
815 /*
816  * Per hardware lane tx statistics
817  */
818 static uint64_t
819 i_mac_tx_hwlane_stat_get(void *handle, uint_t stat)
820 {
821 	mac_soft_ring_t	*ringp = (mac_soft_ring_t *)handle;
822 	mac_tx_stats_t	*mac_tx_stat = &ringp->s_st_stat;
823 
824 	switch (stat) {
825 	case MAC_STAT_OBYTES:
826 		return (mac_tx_stat->mts_obytes);
827 
828 	case MAC_STAT_OPACKETS:
829 		return (mac_tx_stat->mts_opackets);
830 
831 	case MAC_STAT_OERRORS:
832 		return (mac_tx_stat->mts_oerrors);
833 
834 	case MAC_STAT_BLOCK:
835 		return (mac_tx_stat->mts_blockcnt);
836 
837 	case MAC_STAT_UNBLOCK:
838 		return (mac_tx_stat->mts_unblockcnt);
839 
840 	case MAC_STAT_TXSDROPS:
841 		return (mac_tx_stat->mts_sdrops);
842 
843 	default:
844 		return (0);
845 	}
846 }
847 
848 static int
849 i_mac_tx_hwlane_stat_update(kstat_t *ksp, int rw)
850 {
851 	return (i_mac_stat_update(ksp, rw, i_mac_tx_hwlane_stat_get,
852 	    i_mac_tx_hwlane_si, MAC_TX_HWLANE_NKSTAT));
853 }
854 
855 static void
856 i_mac_tx_hwlane_stat_create(mac_soft_ring_t *ringp, const char *modname,
857     const char *statname)
858 {
859 	kstat_t		*ksp;
860 
861 	ksp = i_mac_stat_create(ringp, modname, statname,
862 	    i_mac_tx_hwlane_stat_update, i_mac_tx_hwlane_si,
863 	    MAC_TX_HWLANE_NKSTAT);
864 
865 	ringp->s_ring_ksp = ksp;
866 }
867 
868 /*
869  * Per fanout rx statistics
870  */
871 static uint64_t
872 i_mac_rx_fanout_stat_get(void *handle, uint_t stat)
873 {
874 	mac_soft_ring_t		*tcp_ringp = (mac_soft_ring_t *)handle;
875 	mac_soft_ring_t		*udp_ringp = NULL, *oth_ringp = NULL;
876 	mac_soft_ring_set_t	*mac_srs = tcp_ringp->s_ring_set;
877 	int			index;
878 	uint64_t		val;
879 
880 	mutex_enter(&mac_srs->srs_lock);
881 	/* Extract corresponding udp and oth ring pointers */
882 	for (index = 0; mac_srs->srs_tcp_soft_rings[index] != NULL; index++) {
883 		if (mac_srs->srs_tcp_soft_rings[index] == tcp_ringp) {
884 			udp_ringp = mac_srs->srs_udp_soft_rings[index];
885 			oth_ringp = mac_srs->srs_oth_soft_rings[index];
886 			break;
887 		}
888 	}
889 
890 	ASSERT((udp_ringp != NULL) && (oth_ringp != NULL));
891 
892 	switch (stat) {
893 	case MAC_STAT_RBYTES:
894 		val = (tcp_ringp->s_ring_total_rbytes) +
895 		    (udp_ringp->s_ring_total_rbytes) +
896 		    (oth_ringp->s_ring_total_rbytes);
897 		break;
898 
899 	case MAC_STAT_IPACKETS:
900 		val = (tcp_ringp->s_ring_total_inpkt) +
901 		    (udp_ringp->s_ring_total_inpkt) +
902 		    (oth_ringp->s_ring_total_inpkt);
903 		break;
904 
905 	default:
906 		val = 0;
907 		break;
908 	}
909 	mutex_exit(&mac_srs->srs_lock);
910 	return (val);
911 }
912 
913 static int
914 i_mac_rx_fanout_stat_update(kstat_t *ksp, int rw)
915 {
916 	return (i_mac_stat_update(ksp, rw, i_mac_rx_fanout_stat_get,
917 	    i_mac_rx_fanout_si, MAC_RX_FANOUT_NKSTAT));
918 }
919 
920 static void
921 i_mac_rx_fanout_stat_create(mac_soft_ring_t *ringp, const char *modname,
922     const char *statname)
923 {
924 	kstat_t		*ksp;
925 
926 	ksp = i_mac_stat_create(ringp, modname, statname,
927 	    i_mac_rx_fanout_stat_update, i_mac_rx_fanout_si,
928 	    MAC_RX_FANOUT_NKSTAT);
929 
930 	ringp->s_ring_ksp = ksp;
931 }
932 
933 /*
934  * Exported functions.
935  */
936 
937 /*
938  * Create the "mac" kstat.  The "mac" kstat is comprised of three kinds of
939  * statistics: statistics maintained by the mac module itself, generic mac
940  * statistics maintained by the driver, and MAC-type specific statistics
941  * also maintained by the driver.
942  */
943 void
944 mac_driver_stat_create(mac_impl_t *mip)
945 {
946 	kstat_t		*ksp;
947 	kstat_named_t	*knp;
948 	uint_t		count;
949 	major_t		major = getmajor(mip->mi_phy_dev);
950 
951 	count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount;
952 	ksp = kstat_create((const char *)ddi_major_to_name(major),
953 	    getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME,
954 	    MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0);
955 	if (ksp == NULL)
956 		return;
957 
958 	ksp->ks_update = i_mac_driver_stat_update;
959 	ksp->ks_private = mip;
960 	mip->mi_ksp = ksp;
961 	mip->mi_kstat_count = count;
962 
963 	knp = (kstat_named_t *)ksp->ks_data;
964 	i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT);
965 	knp += MAC_MOD_NKSTAT;
966 	i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT);
967 	if (mip->mi_type->mt_statcount > 0) {
968 		knp += MAC_NKSTAT;
969 		i_mac_kstat_init(knp, mip->mi_type->mt_stats,
970 		    mip->mi_type->mt_statcount);
971 	}
972 
973 	kstat_install(ksp);
974 }
975 
976 /*ARGSUSED*/
977 void
978 mac_driver_stat_delete(mac_impl_t *mip)
979 {
980 	if (mip->mi_ksp != NULL) {
981 		kstat_delete(mip->mi_ksp);
982 		mip->mi_ksp = NULL;
983 		mip->mi_kstat_count = 0;
984 	}
985 }
986 
987 uint64_t
988 mac_driver_stat_default(mac_impl_t *mip, uint_t stat)
989 {
990 	uint_t	stat_index;
991 
992 	if (IS_MAC_STAT(stat)) {
993 		stat_index = stat - MAC_STAT_MIN;
994 		ASSERT(stat_index < MAC_NKSTAT);
995 		return (i_mac_si[stat_index].msi_default);
996 	}
997 	ASSERT(IS_MACTYPE_STAT(stat));
998 	stat_index = stat - MACTYPE_STAT_MIN;
999 	ASSERT(stat_index < mip->mi_type->mt_statcount);
1000 	return (mip->mi_type->mt_stats[stat_index].msi_default);
1001 }
1002 
1003 void
1004 mac_ring_stat_create(mac_ring_t *ring)
1005 {
1006 	mac_impl_t	*mip = ring->mr_mip;
1007 	mac_group_t	*grp = (mac_group_t *)ring->mr_gh;
1008 	char		statname[MAXNAMELEN];
1009 	char		modname[MAXNAMELEN];
1010 
1011 	if (mip->mi_state_flags & MIS_IS_AGGR) {
1012 		(void) strlcpy(modname, mip->mi_clients_list->mci_name,
1013 		    MAXNAMELEN);
1014 	} else
1015 		(void) strlcpy(modname, mip->mi_name, MAXNAMELEN);
1016 
1017 	switch (ring->mr_type) {
1018 	case MAC_RING_TYPE_RX:
1019 		(void) snprintf(statname, sizeof (statname),
1020 		    "mac_rx_ring_%d_%d", grp->mrg_index, ring->mr_index);
1021 		i_mac_rx_ring_stat_create(ring, modname, statname);
1022 		break;
1023 
1024 	case MAC_RING_TYPE_TX:
1025 		(void) snprintf(statname, sizeof (statname), "mac_tx_ring%d",
1026 		    ring->mr_index);
1027 		i_mac_tx_ring_stat_create(ring, modname, statname);
1028 		break;
1029 
1030 	default:
1031 		ASSERT(B_FALSE);
1032 		break;
1033 	}
1034 }
1035 
1036 void
1037 mac_srs_stat_create(mac_soft_ring_set_t *mac_srs)
1038 {
1039 	flow_entry_t	*flent = mac_srs->srs_flent;
1040 	char		statname[MAXNAMELEN];
1041 	boolean_t	is_tx_srs;
1042 
1043 	/* No hardware/software lanes for user defined flows */
1044 	if ((flent->fe_type & FLOW_USER) != 0)
1045 		return;
1046 
1047 	is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0);
1048 
1049 	if (is_tx_srs) {
1050 		mac_srs_tx_t	*srs_tx = &mac_srs->srs_tx;
1051 		mac_ring_t	*ring = srs_tx->st_arg2;
1052 
1053 		if (ring != NULL) {
1054 			(void) snprintf(statname, sizeof (statname),
1055 			    "mac_tx_hwlane%d", ring->mr_index);
1056 		} else {
1057 			(void) snprintf(statname, sizeof (statname),
1058 			    "mac_tx_swlane0");
1059 		}
1060 		i_mac_tx_swlane_stat_create(mac_srs, flent->fe_flow_name,
1061 		    statname);
1062 	} else {
1063 		mac_ring_t	*ring = mac_srs->srs_ring;
1064 
1065 		if (ring == NULL) {
1066 			(void) snprintf(statname, sizeof (statname),
1067 			    "mac_rx_swlane0");
1068 			i_mac_rx_swlane_stat_create(mac_srs,
1069 			    flent->fe_flow_name, statname);
1070 		} else {
1071 			(void) snprintf(statname, sizeof (statname),
1072 			    "mac_rx_hwlane%d", ring->mr_index);
1073 			i_mac_rx_hwlane_stat_create(mac_srs,
1074 			    flent->fe_flow_name, statname);
1075 		}
1076 	}
1077 }
1078 
1079 void
1080 mac_misc_stat_create(flow_entry_t *flent)
1081 {
1082 	char	statname[MAXNAMELEN];
1083 
1084 	/* No misc stats for user defined or mcast/bcast flows */
1085 	if (((flent->fe_type & FLOW_USER) != 0) ||
1086 	    ((flent->fe_type & FLOW_MCAST) != 0))
1087 		return;
1088 
1089 	(void) snprintf(statname, sizeof (statname), "mac_misc_stat");
1090 	i_mac_misc_stat_create(flent, flent->fe_flow_name, statname);
1091 }
1092 
1093 void
1094 mac_soft_ring_stat_create(mac_soft_ring_t *ringp)
1095 {
1096 	mac_soft_ring_set_t	*mac_srs = ringp->s_ring_set;
1097 	flow_entry_t		*flent = ringp->s_ring_mcip->mci_flent;
1098 	mac_ring_t		*ring = (mac_ring_t *)ringp->s_ring_tx_arg2;
1099 	boolean_t		is_tx_srs;
1100 	char			statname[MAXNAMELEN];
1101 
1102 	/* No hardware/software lanes for user defined flows */
1103 	if ((flent->fe_type & FLOW_USER) != 0)
1104 		return;
1105 
1106 	is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0);
1107 	if (is_tx_srs) {	/* tx side hardware lane */
1108 		ASSERT(ring != NULL);
1109 		(void) snprintf(statname, sizeof (statname), "mac_tx_hwlane%d",
1110 		    ring->mr_index);
1111 		i_mac_tx_hwlane_stat_create(ringp, flent->fe_flow_name,
1112 		    statname);
1113 	} else {		/* rx side fanout */
1114 				/* Maintain single stat for (tcp, udp, oth) */
1115 		if (ringp->s_ring_type & ST_RING_TCP) {
1116 			int			index;
1117 			mac_soft_ring_t		*softring;
1118 
1119 			for (index = 0, softring = mac_srs->srs_soft_ring_head;
1120 			    softring != NULL;
1121 			    index++, softring = softring->s_ring_next) {
1122 				if (softring == ringp)
1123 					break;
1124 			}
1125 
1126 			if (mac_srs->srs_ring == NULL) {
1127 				(void) snprintf(statname, sizeof (statname),
1128 				    "mac_rx_swlane0_fanout%d", index/3);
1129 			} else {
1130 				(void) snprintf(statname, sizeof (statname),
1131 				    "mac_rx_hwlane%d_fanout%d",
1132 				    mac_srs->srs_ring->mr_index, index/3);
1133 			}
1134 			i_mac_rx_fanout_stat_create(ringp, flent->fe_flow_name,
1135 			    statname);
1136 		}
1137 	}
1138 }
1139 
1140 void
1141 mac_ring_stat_delete(mac_ring_t *ring)
1142 {
1143 	if (ring->mr_ksp != NULL) {
1144 		kstat_delete(ring->mr_ksp);
1145 		ring->mr_ksp = NULL;
1146 	}
1147 }
1148 
1149 void
1150 mac_srs_stat_delete(mac_soft_ring_set_t *mac_srs)
1151 {
1152 	boolean_t	is_tx_srs;
1153 
1154 	is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0);
1155 	if (!is_tx_srs) {
1156 		/*
1157 		 * Rx ring has been taken away. Before destroying corresponding
1158 		 * SRS, save the stats recorded by that SRS.
1159 		 */
1160 		mac_client_impl_t	*mcip = mac_srs->srs_mcip;
1161 		mac_misc_stats_t	*mac_misc_stat = &mcip->mci_misc_stat;
1162 		mac_rx_stats_t		*mac_rx_stat = &mac_srs->srs_rx.sr_stat;
1163 
1164 		i_mac_add_stats(&mac_misc_stat->mms_defunctrxlanestats,
1165 		    mac_rx_stat, &mac_misc_stat->mms_defunctrxlanestats,
1166 		    rx_srs_stats_list, RX_SRS_STAT_SIZE);
1167 	}
1168 
1169 	if (mac_srs->srs_ksp != NULL) {
1170 		kstat_delete(mac_srs->srs_ksp);
1171 		mac_srs->srs_ksp = NULL;
1172 	}
1173 }
1174 
1175 void
1176 mac_misc_stat_delete(flow_entry_t *flent)
1177 {
1178 	if (flent->fe_misc_stat_ksp != NULL) {
1179 		kstat_delete(flent->fe_misc_stat_ksp);
1180 		flent->fe_misc_stat_ksp = NULL;
1181 	}
1182 }
1183 
1184 void
1185 mac_soft_ring_stat_delete(mac_soft_ring_t *ringp)
1186 {
1187 	mac_soft_ring_set_t	*mac_srs = ringp->s_ring_set;
1188 	boolean_t		is_tx_srs;
1189 
1190 	is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0);
1191 	if (is_tx_srs) {
1192 		/*
1193 		 * Tx ring has been taken away. Before destroying corresponding
1194 		 * soft ring, save the stats recorded by that soft ring.
1195 		 */
1196 		mac_client_impl_t	*mcip = mac_srs->srs_mcip;
1197 		mac_misc_stats_t	*mac_misc_stat = &mcip->mci_misc_stat;
1198 		mac_tx_stats_t		*mac_tx_stat = &ringp->s_st_stat;
1199 
1200 		i_mac_add_stats(&mac_misc_stat->mms_defuncttxlanestats,
1201 		    mac_tx_stat, &mac_misc_stat->mms_defuncttxlanestats,
1202 		    tx_softring_stats_list, TX_SOFTRING_STAT_SIZE);
1203 	}
1204 
1205 	if (ringp->s_ring_ksp) {
1206 		kstat_delete(ringp->s_ring_ksp);
1207 		ringp->s_ring_ksp = NULL;
1208 	}
1209 }
1210 
1211 void
1212 mac_pseudo_ring_stat_rename(mac_impl_t *mip)
1213 {
1214 	mac_group_t	*group;
1215 	mac_ring_t	*ring;
1216 
1217 	/* Recreate pseudo rx ring kstats */
1218 	for (group = mip->mi_rx_groups; group != NULL;
1219 	    group = group->mrg_next) {
1220 		for (ring = group->mrg_rings; ring != NULL;
1221 		    ring = ring->mr_next) {
1222 			mac_ring_stat_delete(ring);
1223 			mac_ring_stat_create(ring);
1224 		}
1225 	}
1226 
1227 	/* Recreate pseudo tx ring kstats */
1228 	for (group = mip->mi_tx_groups; group != NULL;
1229 	    group = group->mrg_next) {
1230 		for (ring = group->mrg_rings; ring != NULL;
1231 		    ring = ring->mr_next) {
1232 			mac_ring_stat_delete(ring);
1233 			mac_ring_stat_create(ring);
1234 		}
1235 	}
1236 }
1237 
1238 void
1239 mac_stat_rename(mac_client_impl_t *mcip)
1240 {
1241 	flow_entry_t		*flent = mcip->mci_flent;
1242 	mac_soft_ring_set_t	*mac_srs;
1243 	mac_soft_ring_t		*ringp;
1244 	int			i, j;
1245 
1246 	ASSERT(flent != NULL);
1247 
1248 	/* Recreate rx SRSes kstats */
1249 	for (i = 0; i < flent->fe_rx_srs_cnt; i++) {
1250 		mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i];
1251 		mac_srs_stat_delete(mac_srs);
1252 		mac_srs_stat_create(mac_srs);
1253 
1254 		/* Recreate rx fanout kstats */
1255 		for (j = 0; j < mac_srs->srs_tcp_ring_count; j++) {
1256 			ringp = mac_srs->srs_tcp_soft_rings[j];
1257 			mac_soft_ring_stat_delete(ringp);
1258 			mac_soft_ring_stat_create(ringp);
1259 		}
1260 	}
1261 
1262 	/* Recreate tx SRS kstats */
1263 	mac_srs = (mac_soft_ring_set_t *)flent->fe_tx_srs;
1264 	mac_srs_stat_delete(mac_srs);
1265 	mac_srs_stat_create(mac_srs);
1266 
1267 	/* Recreate tx sofring kstats */
1268 	for (ringp = mac_srs->srs_soft_ring_head; ringp;
1269 	    ringp = ringp->s_ring_next) {
1270 		mac_soft_ring_stat_delete(ringp);
1271 		mac_soft_ring_stat_create(ringp);
1272 	}
1273 
1274 	/* Recreate misc kstats */
1275 	mac_misc_stat_delete(flent);
1276 	mac_misc_stat_create(flent);
1277 }
1278 
1279 void
1280 mac_tx_srs_stat_recreate(mac_soft_ring_set_t *tx_srs, boolean_t add_stats)
1281 {
1282 	mac_client_impl_t	*mcip = tx_srs->srs_mcip;
1283 	mac_misc_stats_t	*mac_misc_stat = &mcip->mci_misc_stat;
1284 	mac_tx_stats_t		*mac_tx_stat = &tx_srs->srs_tx.st_stat;
1285 
1286 	if (add_stats) {
1287 		/* Add the stats to cumulative stats */
1288 		i_mac_add_stats(&mac_misc_stat->mms_defuncttxlanestats,
1289 		    mac_tx_stat, &mac_misc_stat->mms_defuncttxlanestats,
1290 		    tx_softring_stats_list, TX_SOFTRING_STAT_SIZE);
1291 	}
1292 
1293 	bzero(mac_tx_stat, sizeof (mac_tx_stats_t));
1294 	mac_srs_stat_delete(tx_srs);
1295 	mac_srs_stat_create(tx_srs);
1296 }
1297