xref: /illumos-gate/usr/src/cmd/mdb/common/modules/mac/mac.c (revision da14cebe)
1*da14cebeSEric Cheng /*
2*da14cebeSEric Cheng  * CDDL HEADER START
3*da14cebeSEric Cheng  *
4*da14cebeSEric Cheng  * The contents of this file are subject to the terms of the
5*da14cebeSEric Cheng  * Common Development and Distribution License (the "License").
6*da14cebeSEric Cheng  * You may not use this file except in compliance with the License.
7*da14cebeSEric Cheng  *
8*da14cebeSEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*da14cebeSEric Cheng  * or http://www.opensolaris.org/os/licensing.
10*da14cebeSEric Cheng  * See the License for the specific language governing permissions
11*da14cebeSEric Cheng  * and limitations under the License.
12*da14cebeSEric Cheng  *
13*da14cebeSEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
14*da14cebeSEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*da14cebeSEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
16*da14cebeSEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
17*da14cebeSEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
18*da14cebeSEric Cheng  *
19*da14cebeSEric Cheng  * CDDL HEADER END
20*da14cebeSEric Cheng  */
21*da14cebeSEric Cheng /*
22*da14cebeSEric Cheng  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*da14cebeSEric Cheng  * Use is subject to license terms.
24*da14cebeSEric Cheng  */
25*da14cebeSEric Cheng 
26*da14cebeSEric Cheng #include <sys/mdb_modapi.h>
27*da14cebeSEric Cheng #include <sys/types.h>
28*da14cebeSEric Cheng #include <inet/ip.h>
29*da14cebeSEric Cheng #include <inet/ip6.h>
30*da14cebeSEric Cheng 
31*da14cebeSEric Cheng #include <sys/mac.h>
32*da14cebeSEric Cheng #include <sys/mac_provider.h>
33*da14cebeSEric Cheng #include <sys/mac_client.h>
34*da14cebeSEric Cheng #include <sys/mac_client_impl.h>
35*da14cebeSEric Cheng #include <sys/mac_flow_impl.h>
36*da14cebeSEric Cheng #include <sys/mac_soft_ring.h>
37*da14cebeSEric Cheng 
38*da14cebeSEric Cheng #define	STRSIZE	64
39*da14cebeSEric Cheng #define	MAC_RX_SRS_SIZE	 (MAX_RINGS_PER_GROUP * sizeof (uintptr_t))
40*da14cebeSEric Cheng 
41*da14cebeSEric Cheng #define	LAYERED_WALKER_FOR_FLOW	"flow_entry_cache"
42*da14cebeSEric Cheng #define	LAYERED_WALKER_FOR_SRS	"mac_srs_cache"
43*da14cebeSEric Cheng #define	LAYERED_WALKER_FOR_RING	"mac_ring_cache"
44*da14cebeSEric Cheng 
45*da14cebeSEric Cheng /* arguments passed to mac_flow dee-command */
46*da14cebeSEric Cheng #define	MAC_FLOW_NONE	0x01
47*da14cebeSEric Cheng #define	MAC_FLOW_ATTR	0x02
48*da14cebeSEric Cheng #define	MAC_FLOW_PROP	0x04
49*da14cebeSEric Cheng #define	MAC_FLOW_RX	0x08
50*da14cebeSEric Cheng #define	MAC_FLOW_TX	0x10
51*da14cebeSEric Cheng #define	MAC_FLOW_USER	0x20
52*da14cebeSEric Cheng #define	MAC_FLOW_STATS	0x40
53*da14cebeSEric Cheng #define	MAC_FLOW_MISC	0x80
54*da14cebeSEric Cheng 
55*da14cebeSEric Cheng /* arguments passed to mac_srs dee-command */
56*da14cebeSEric Cheng #define	MAC_SRS_RX	0x01
57*da14cebeSEric Cheng #define	MAC_SRS_TX	0x02
58*da14cebeSEric Cheng 
59*da14cebeSEric Cheng static char *
60*da14cebeSEric Cheng mac_flow_proto2str(uint8_t protocol)
61*da14cebeSEric Cheng {
62*da14cebeSEric Cheng 	switch (protocol) {
63*da14cebeSEric Cheng 	case IPPROTO_TCP:
64*da14cebeSEric Cheng 		return ("tcp");
65*da14cebeSEric Cheng 	case IPPROTO_UDP:
66*da14cebeSEric Cheng 		return ("udp");
67*da14cebeSEric Cheng 	case IPPROTO_SCTP:
68*da14cebeSEric Cheng 		return ("sctp");
69*da14cebeSEric Cheng 	case IPPROTO_ICMP:
70*da14cebeSEric Cheng 		return ("icmp");
71*da14cebeSEric Cheng 	case IPPROTO_ICMPV6:
72*da14cebeSEric Cheng 		return ("icmpv6");
73*da14cebeSEric Cheng 	default:
74*da14cebeSEric Cheng 		return ("--");
75*da14cebeSEric Cheng 	}
76*da14cebeSEric Cheng }
77*da14cebeSEric Cheng 
78*da14cebeSEric Cheng static char *
79*da14cebeSEric Cheng mac_flow_priority2str(mac_priority_level_t prio)
80*da14cebeSEric Cheng {
81*da14cebeSEric Cheng 	switch (prio) {
82*da14cebeSEric Cheng 	case MPL_LOW:
83*da14cebeSEric Cheng 		return ("low");
84*da14cebeSEric Cheng 	case MPL_MEDIUM:
85*da14cebeSEric Cheng 		return ("medium");
86*da14cebeSEric Cheng 	case MPL_HIGH:
87*da14cebeSEric Cheng 		return ("high");
88*da14cebeSEric Cheng 	case MPL_RESET:
89*da14cebeSEric Cheng 		return ("reset");
90*da14cebeSEric Cheng 	default:
91*da14cebeSEric Cheng 		return ("--");
92*da14cebeSEric Cheng 	}
93*da14cebeSEric Cheng }
94*da14cebeSEric Cheng 
95*da14cebeSEric Cheng /*
96*da14cebeSEric Cheng  *  Convert bandwidth in bps to a string in mpbs.
97*da14cebeSEric Cheng  */
98*da14cebeSEric Cheng static char *
99*da14cebeSEric Cheng mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len)
100*da14cebeSEric Cheng {
101*da14cebeSEric Cheng 	int kbps, mbps;
102*da14cebeSEric Cheng 
103*da14cebeSEric Cheng 	kbps = (bw % 1000000)/1000;
104*da14cebeSEric Cheng 	mbps = bw/1000000;
105*da14cebeSEric Cheng 	if ((mbps == 0) && (kbps != 0))
106*da14cebeSEric Cheng 		mdb_snprintf(buf, len, "0.%03u", kbps);
107*da14cebeSEric Cheng 	else
108*da14cebeSEric Cheng 		mdb_snprintf(buf, len, "%5u", mbps);
109*da14cebeSEric Cheng 	return (buf);
110*da14cebeSEric Cheng }
111*da14cebeSEric Cheng 
112*da14cebeSEric Cheng static void
113*da14cebeSEric Cheng mac_flow_print_header(uint_t args)
114*da14cebeSEric Cheng {
115*da14cebeSEric Cheng 	switch (args) {
116*da14cebeSEric Cheng 	case MAC_FLOW_NONE:
117*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-32s %-6s %?s %?s %-20s%</u>\n",
118*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "LINKID", "MCIP", "MIP",
119*da14cebeSEric Cheng 		    "MIP NAME");
120*da14cebeSEric Cheng 		break;
121*da14cebeSEric Cheng 	case MAC_FLOW_ATTR:
122*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-32s %-7s %6s "
123*da14cebeSEric Cheng 		    "%-9s %s%</u>\n",
124*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "PROTO", "PORT",
125*da14cebeSEric Cheng 		    "DSFLD:MSK", "IPADDR");
126*da14cebeSEric Cheng 		break;
127*da14cebeSEric Cheng 	case MAC_FLOW_PROP:
128*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n",
129*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY");
130*da14cebeSEric Cheng 		break;
131*da14cebeSEric Cheng 	case MAC_FLOW_MISC:
132*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-32s %10s %10s "
133*da14cebeSEric Cheng 		    "%32s %s%</u>\n",
134*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "TYPE", "FLAGS",
135*da14cebeSEric Cheng 		    "MATCH_FN", "ZONE");
136*da14cebeSEric Cheng 		break;
137*da14cebeSEric Cheng 	case MAC_FLOW_RX:
138*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-24s %-30s %?s "
139*da14cebeSEric Cheng 		    "%?s %7s %s%</u>\n",
140*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "CB_FUNC", "CB_ARG1",
141*da14cebeSEric Cheng 		    "CB_ARG2", "SRS_CNT", "RX_SRS");
142*da14cebeSEric Cheng 		break;
143*da14cebeSEric Cheng 	case MAC_FLOW_TX:
144*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-32s %?s %</u>\n",
145*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "TX_SRS");
146*da14cebeSEric Cheng 		break;
147*da14cebeSEric Cheng 	case MAC_FLOW_STATS:
148*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %-32s %?s %?s%</u>\n",
149*da14cebeSEric Cheng 		    "ADDR", "FLOW NAME", "RBYTES", "OBYTES");
150*da14cebeSEric Cheng 		break;
151*da14cebeSEric Cheng 	}
152*da14cebeSEric Cheng }
153*da14cebeSEric Cheng 
154*da14cebeSEric Cheng /*
155*da14cebeSEric Cheng  * Display selected fields of the flow_entry_t structure
156*da14cebeSEric Cheng  */
157*da14cebeSEric Cheng static int
158*da14cebeSEric Cheng mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args)
159*da14cebeSEric Cheng {
160*da14cebeSEric Cheng 	static const mdb_bitmask_t flow_type_bits[] = {
161*da14cebeSEric Cheng 		{"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC},
162*da14cebeSEric Cheng 		{"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC},
163*da14cebeSEric Cheng 		{"M", FLOW_MCAST, FLOW_MCAST},
164*da14cebeSEric Cheng 		{"O", FLOW_OTHER, FLOW_OTHER},
165*da14cebeSEric Cheng 		{"U", FLOW_USER, FLOW_USER},
166*da14cebeSEric Cheng 		{"V", FLOW_VNIC, FLOW_VNIC},
167*da14cebeSEric Cheng 		{"NS", FLOW_NO_STATS, FLOW_NO_STATS},
168*da14cebeSEric Cheng 		{ NULL, 0, 0 }
169*da14cebeSEric Cheng 	};
170*da14cebeSEric Cheng #define	FLOW_MAX_TYPE	(sizeof (flow_type_bits) / sizeof (mdb_bitmask_t))
171*da14cebeSEric Cheng 
172*da14cebeSEric Cheng 	static const mdb_bitmask_t flow_flag_bits[] = {
173*da14cebeSEric Cheng 		{"Q", FE_QUIESCE, FE_QUIESCE},
174*da14cebeSEric Cheng 		{"W", FE_WAITER, FE_WAITER},
175*da14cebeSEric Cheng 		{"T", FE_FLOW_TAB, FE_FLOW_TAB},
176*da14cebeSEric Cheng 		{"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH},
177*da14cebeSEric Cheng 		{"I", FE_INCIPIENT, FE_INCIPIENT},
178*da14cebeSEric Cheng 		{"C", FE_CONDEMNED, FE_CONDEMNED},
179*da14cebeSEric Cheng 		{"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH},
180*da14cebeSEric Cheng 		{"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH},
181*da14cebeSEric Cheng 		{ NULL, 0, 0 }
182*da14cebeSEric Cheng 	};
183*da14cebeSEric Cheng #define	FLOW_MAX_FLAGS	(sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t))
184*da14cebeSEric Cheng 	flow_entry_t		fe;
185*da14cebeSEric Cheng 	mac_client_impl_t	mcip;
186*da14cebeSEric Cheng 	mac_impl_t		mip;
187*da14cebeSEric Cheng 
188*da14cebeSEric Cheng 	if (mdb_vread(&fe, sizeof (fe), addr) == -1) {
189*da14cebeSEric Cheng 		mdb_warn("failed to read struct flow_entry_s at %p", addr);
190*da14cebeSEric Cheng 		return (DCMD_ERR);
191*da14cebeSEric Cheng 	}
192*da14cebeSEric Cheng 	if (args & MAC_FLOW_USER) {
193*da14cebeSEric Cheng 		args &= ~MAC_FLOW_USER;
194*da14cebeSEric Cheng 		if (fe.fe_type & FLOW_MCAST) {
195*da14cebeSEric Cheng 			if (DCMD_HDRSPEC(flags))
196*da14cebeSEric Cheng 				mac_flow_print_header(args);
197*da14cebeSEric Cheng 			return (DCMD_OK);
198*da14cebeSEric Cheng 		}
199*da14cebeSEric Cheng 	}
200*da14cebeSEric Cheng 	if (DCMD_HDRSPEC(flags))
201*da14cebeSEric Cheng 		mac_flow_print_header(args);
202*da14cebeSEric Cheng 	bzero(&mcip, sizeof (mcip));
203*da14cebeSEric Cheng 	bzero(&mip, sizeof (mip));
204*da14cebeSEric Cheng 	if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip),
205*da14cebeSEric Cheng 	    (uintptr_t)fe.fe_mcip) == sizeof (mcip)) {
206*da14cebeSEric Cheng 		(void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip);
207*da14cebeSEric Cheng 	}
208*da14cebeSEric Cheng 	switch (args) {
209*da14cebeSEric Cheng 	case MAC_FLOW_NONE: {
210*da14cebeSEric Cheng 		mdb_printf("%?p %-32s %6d %?p "
211*da14cebeSEric Cheng 		    "%?p %-20s\n",
212*da14cebeSEric Cheng 		    addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip,
213*da14cebeSEric Cheng 		    mcip.mci_mip, mip.mi_name);
214*da14cebeSEric Cheng 		break;
215*da14cebeSEric Cheng 	}
216*da14cebeSEric Cheng 	case MAC_FLOW_ATTR: {
217*da14cebeSEric Cheng 		struct 	in_addr	in4;
218*da14cebeSEric Cheng 		uintptr_t	desc_addr;
219*da14cebeSEric Cheng 		flow_desc_t	fdesc;
220*da14cebeSEric Cheng 
221*da14cebeSEric Cheng 		desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc);
222*da14cebeSEric Cheng 		if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) {
223*da14cebeSEric Cheng 			mdb_warn("failed to read struct flow_description at %p",
224*da14cebeSEric Cheng 			    desc_addr);
225*da14cebeSEric Cheng 			return (DCMD_ERR);
226*da14cebeSEric Cheng 		}
227*da14cebeSEric Cheng 		mdb_printf("%?p %-32s "
228*da14cebeSEric Cheng 		    "%-7s %6d"
229*da14cebeSEric Cheng 		    "%4d:%-4d ",
230*da14cebeSEric Cheng 		    addr, fe.fe_flow_name,
231*da14cebeSEric Cheng 		    mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port,
232*da14cebeSEric Cheng 		    fdesc.fd_dsfield, fdesc.fd_dsfield_mask);
233*da14cebeSEric Cheng 		if (fdesc.fd_ipversion == IPV4_VERSION) {
234*da14cebeSEric Cheng 			IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4);
235*da14cebeSEric Cheng 			mdb_printf("%I", in4.s_addr);
236*da14cebeSEric Cheng 		} else if (fdesc.fd_ipversion == IPV6_VERSION) {
237*da14cebeSEric Cheng 			mdb_printf("%N", &fdesc.fd_local_addr);
238*da14cebeSEric Cheng 		} else {
239*da14cebeSEric Cheng 			mdb_printf("%s", "--");
240*da14cebeSEric Cheng 		}
241*da14cebeSEric Cheng 		mdb_printf("\n");
242*da14cebeSEric Cheng 		break;
243*da14cebeSEric Cheng 	}
244*da14cebeSEric Cheng 	case MAC_FLOW_PROP: {
245*da14cebeSEric Cheng 		uintptr_t	prop_addr;
246*da14cebeSEric Cheng 		char		bwstr[STRSIZE];
247*da14cebeSEric Cheng 		mac_resource_props_t	fprop;
248*da14cebeSEric Cheng 
249*da14cebeSEric Cheng 		prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props);
250*da14cebeSEric Cheng 		if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) {
251*da14cebeSEric Cheng 			mdb_warn("failed to read struct mac_resoource_props "
252*da14cebeSEric Cheng 			    "at %p", prop_addr);
253*da14cebeSEric Cheng 			return (DCMD_ERR);
254*da14cebeSEric Cheng 		}
255*da14cebeSEric Cheng 		mdb_printf("%?p %-32s "
256*da14cebeSEric Cheng 		    "%8s %9s\n",
257*da14cebeSEric Cheng 		    addr, fe.fe_flow_name,
258*da14cebeSEric Cheng 		    mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE),
259*da14cebeSEric Cheng 		    mac_flow_priority2str(fprop.mrp_priority));
260*da14cebeSEric Cheng 		break;
261*da14cebeSEric Cheng 	}
262*da14cebeSEric Cheng 	case MAC_FLOW_MISC: {
263*da14cebeSEric Cheng 		char		flow_flags[2 * FLOW_MAX_FLAGS];
264*da14cebeSEric Cheng 		char		flow_type[2 * FLOW_MAX_TYPE];
265*da14cebeSEric Cheng 		GElf_Sym 	sym;
266*da14cebeSEric Cheng 		char		func_name[MDB_SYM_NAMLEN] = "";
267*da14cebeSEric Cheng 		uintptr_t	func, match_addr;
268*da14cebeSEric Cheng 
269*da14cebeSEric Cheng 		match_addr = addr + OFFSETOF(flow_entry_t, fe_match);
270*da14cebeSEric Cheng 		(void) mdb_vread(&func, sizeof (func), match_addr);
271*da14cebeSEric Cheng 		(void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name,
272*da14cebeSEric Cheng 		    MDB_SYM_NAMLEN, &sym);
273*da14cebeSEric Cheng 		mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb",
274*da14cebeSEric Cheng 		    fe.fe_flags, flow_flag_bits);
275*da14cebeSEric Cheng 		mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb",
276*da14cebeSEric Cheng 		    fe.fe_type, flow_type_bits);
277*da14cebeSEric Cheng 		mdb_printf("%?p %-32s %10s %10s "
278*da14cebeSEric Cheng 		    "%32s %-d\n",
279*da14cebeSEric Cheng 		    addr, fe.fe_flow_name, flow_type, flow_flags,
280*da14cebeSEric Cheng 		    func_name, fe.fe_zoneid);
281*da14cebeSEric Cheng 		break;
282*da14cebeSEric Cheng 	}
283*da14cebeSEric Cheng 	case MAC_FLOW_RX: {
284*da14cebeSEric Cheng 		uintptr_t	rx_srs[MAX_RINGS_PER_GROUP] = {0};
285*da14cebeSEric Cheng 		char 		cb_fn[MDB_SYM_NAMLEN] = "";
286*da14cebeSEric Cheng 		uintptr_t	cb_fnaddr, fnaddr, rxaddr;
287*da14cebeSEric Cheng 		int		i;
288*da14cebeSEric Cheng 		GElf_Sym 	sym;
289*da14cebeSEric Cheng 
290*da14cebeSEric Cheng 		rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs);
291*da14cebeSEric Cheng 		(void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr);
292*da14cebeSEric Cheng 		fnaddr = addr + OFFSETOF(flow_entry_t, fe_cb_fn);
293*da14cebeSEric Cheng 		(void) mdb_vread(&cb_fnaddr, sizeof (cb_fnaddr), fnaddr);
294*da14cebeSEric Cheng 		(void) mdb_lookup_by_addr(cb_fnaddr, MDB_SYM_EXACT, cb_fn,
295*da14cebeSEric Cheng 		    MDB_SYM_NAMLEN, &sym);
296*da14cebeSEric Cheng 		mdb_printf("%?p %-24s %-30s %?p "
297*da14cebeSEric Cheng 		    "%?p %7d ",
298*da14cebeSEric Cheng 		    addr, fe.fe_flow_name, cb_fn, fe.fe_cb_arg1,
299*da14cebeSEric Cheng 		    fe.fe_cb_arg2, fe.fe_rx_srs_cnt);
300*da14cebeSEric Cheng 		for (i = 0; i < MAX_RINGS_PER_GROUP; i++) {
301*da14cebeSEric Cheng 			if (rx_srs[i] == 0)
302*da14cebeSEric Cheng 				continue;
303*da14cebeSEric Cheng 			mdb_printf("%p ", rx_srs[i]);
304*da14cebeSEric Cheng 		}
305*da14cebeSEric Cheng 		mdb_printf("\n");
306*da14cebeSEric Cheng 		break;
307*da14cebeSEric Cheng 	}
308*da14cebeSEric Cheng 	case MAC_FLOW_TX: {
309*da14cebeSEric Cheng 		uintptr_t	tx_srs = 0, txaddr;
310*da14cebeSEric Cheng 
311*da14cebeSEric Cheng 		txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs);
312*da14cebeSEric Cheng 		(void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr);
313*da14cebeSEric Cheng 		mdb_printf("%?p %-32s %?p\n",
314*da14cebeSEric Cheng 		    addr, fe.fe_flow_name, fe.fe_tx_srs);
315*da14cebeSEric Cheng 		break;
316*da14cebeSEric Cheng 	}
317*da14cebeSEric Cheng 	case MAC_FLOW_STATS: {
318*da14cebeSEric Cheng 		mdb_printf("%?p %-32s %16llu %16llu\n",
319*da14cebeSEric Cheng 		    addr, fe.fe_flow_name, fe.fe_flowstats.fs_rbytes,
320*da14cebeSEric Cheng 		    fe.fe_flowstats.fs_obytes);
321*da14cebeSEric Cheng 		break;
322*da14cebeSEric Cheng 	}
323*da14cebeSEric Cheng 	}
324*da14cebeSEric Cheng 	return (DCMD_OK);
325*da14cebeSEric Cheng }
326*da14cebeSEric Cheng 
327*da14cebeSEric Cheng /*
328*da14cebeSEric Cheng  * Parse the arguments passed to the dcmd and print all or one flow_entry_t
329*da14cebeSEric Cheng  * structures
330*da14cebeSEric Cheng  */
331*da14cebeSEric Cheng static int
332*da14cebeSEric Cheng mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
333*da14cebeSEric Cheng {
334*da14cebeSEric Cheng 	uint_t	args = 0;
335*da14cebeSEric Cheng 
336*da14cebeSEric Cheng 	if (!(flags & DCMD_ADDRSPEC)) {
337*da14cebeSEric Cheng 		if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) {
338*da14cebeSEric Cheng 			mdb_warn("failed to walk 'mac_flow'");
339*da14cebeSEric Cheng 			return (DCMD_ERR);
340*da14cebeSEric Cheng 		}
341*da14cebeSEric Cheng 		return (DCMD_OK);
342*da14cebeSEric Cheng 	}
343*da14cebeSEric Cheng 	if ((mdb_getopts(argc, argv,
344*da14cebeSEric Cheng 	    'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args,
345*da14cebeSEric Cheng 	    'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args,
346*da14cebeSEric Cheng 	    'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args,
347*da14cebeSEric Cheng 	    'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args,
348*da14cebeSEric Cheng 	    't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args,
349*da14cebeSEric Cheng 	    's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args,
350*da14cebeSEric Cheng 	    'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args) != argc)) {
351*da14cebeSEric Cheng 		return (DCMD_USAGE);
352*da14cebeSEric Cheng 	}
353*da14cebeSEric Cheng 	if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER)))
354*da14cebeSEric Cheng 		return (DCMD_USAGE);
355*da14cebeSEric Cheng 	/*
356*da14cebeSEric Cheng 	 * If no arguments was specified or just "-u" was specified then
357*da14cebeSEric Cheng 	 * we default to printing basic information of flows.
358*da14cebeSEric Cheng 	 */
359*da14cebeSEric Cheng 	if (args == 0 || args == MAC_FLOW_USER)
360*da14cebeSEric Cheng 		args |= MAC_FLOW_NONE;
361*da14cebeSEric Cheng 
362*da14cebeSEric Cheng 	return (mac_flow_dcmd_output(addr, flags, args));
363*da14cebeSEric Cheng }
364*da14cebeSEric Cheng 
365*da14cebeSEric Cheng static void
366*da14cebeSEric Cheng mac_flow_help(void)
367*da14cebeSEric Cheng {
368*da14cebeSEric Cheng 	mdb_printf("If an address is specified, then flow_entry structure at "
369*da14cebeSEric Cheng 	    "that address is printed. Otherwise all the flows in the system "
370*da14cebeSEric Cheng 	    "are printed.\n");
371*da14cebeSEric Cheng 	mdb_printf("Options:\n"
372*da14cebeSEric Cheng 	    "\t-u\tdisplay user defined link & vnic flows.\n"
373*da14cebeSEric Cheng 	    "\t-a\tdisplay flow attributes\n"
374*da14cebeSEric Cheng 	    "\t-p\tdisplay flow properties\n"
375*da14cebeSEric Cheng 	    "\t-r\tdisplay rx side information\n"
376*da14cebeSEric Cheng 	    "\t-t\tdisplay tx side information\n"
377*da14cebeSEric Cheng 	    "\t-s\tdisplay flow statistics\n"
378*da14cebeSEric Cheng 	    "\t-m\tdisplay miscellaneous flow information\n\n");
379*da14cebeSEric Cheng 	mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n");
380*da14cebeSEric Cheng 	mdb_printf("Flow Types:\n");
381*da14cebeSEric Cheng 	mdb_printf("\t  P --> FLOW_PRIMARY_MAC\n");
382*da14cebeSEric Cheng 	mdb_printf("\t  V --> FLOW_VNIC_MAC\n");
383*da14cebeSEric Cheng 	mdb_printf("\t  M --> FLOW_MCAST\n");
384*da14cebeSEric Cheng 	mdb_printf("\t  O --> FLOW_OTHER\n");
385*da14cebeSEric Cheng 	mdb_printf("\t  U --> FLOW_USER\n");
386*da14cebeSEric Cheng 	mdb_printf("\t NS --> FLOW_NO_STATS\n\n");
387*da14cebeSEric Cheng 	mdb_printf("Flow Flags:\n");
388*da14cebeSEric Cheng 	mdb_printf("\t  Q --> FE_QUIESCE\n");
389*da14cebeSEric Cheng 	mdb_printf("\t  W --> FE_WAITER\n");
390*da14cebeSEric Cheng 	mdb_printf("\t  T --> FE_FLOW_TAB\n");
391*da14cebeSEric Cheng 	mdb_printf("\t  G --> FE_G_FLOW_HASH\n");
392*da14cebeSEric Cheng 	mdb_printf("\t  I --> FE_INCIPIENT\n");
393*da14cebeSEric Cheng 	mdb_printf("\t  C --> FE_CONDEMNED\n");
394*da14cebeSEric Cheng 	mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n");
395*da14cebeSEric Cheng 	mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n");
396*da14cebeSEric Cheng }
397*da14cebeSEric Cheng 
398*da14cebeSEric Cheng /*
399*da14cebeSEric Cheng  * called once by the debugger when the mac_flow walk begins.
400*da14cebeSEric Cheng  */
401*da14cebeSEric Cheng static int
402*da14cebeSEric Cheng mac_flow_walk_init(mdb_walk_state_t *wsp)
403*da14cebeSEric Cheng {
404*da14cebeSEric Cheng 	if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) {
405*da14cebeSEric Cheng 		mdb_warn("failed to walk 'mac_flow'");
406*da14cebeSEric Cheng 		return (WALK_ERR);
407*da14cebeSEric Cheng 	}
408*da14cebeSEric Cheng 	return (WALK_NEXT);
409*da14cebeSEric Cheng }
410*da14cebeSEric Cheng 
411*da14cebeSEric Cheng /*
412*da14cebeSEric Cheng  * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and
413*da14cebeSEric Cheng  * mac_ring_t.
414*da14cebeSEric Cheng  *
415*da14cebeSEric Cheng  * Steps through each flow_entry_t and calls the callback function. If the
416*da14cebeSEric Cheng  * user executed ::walk mac_flow, it just prints the address or if the user
417*da14cebeSEric Cheng  * executed ::mac_flow it displays selected fields of flow_entry_t structure
418*da14cebeSEric Cheng  * by calling "mac_flow_dcmd"
419*da14cebeSEric Cheng  */
420*da14cebeSEric Cheng static int
421*da14cebeSEric Cheng mac_common_walk_step(mdb_walk_state_t *wsp)
422*da14cebeSEric Cheng {
423*da14cebeSEric Cheng 	int status;
424*da14cebeSEric Cheng 
425*da14cebeSEric Cheng 	if (wsp->walk_addr == NULL)
426*da14cebeSEric Cheng 		return (WALK_DONE);
427*da14cebeSEric Cheng 
428*da14cebeSEric Cheng 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
429*da14cebeSEric Cheng 	    wsp->walk_cbdata);
430*da14cebeSEric Cheng 
431*da14cebeSEric Cheng 	return (status);
432*da14cebeSEric Cheng }
433*da14cebeSEric Cheng 
434*da14cebeSEric Cheng static char *
435*da14cebeSEric Cheng mac_srs_txmode2str(mac_tx_srs_mode_t mode)
436*da14cebeSEric Cheng {
437*da14cebeSEric Cheng 	switch (mode) {
438*da14cebeSEric Cheng 	case SRS_TX_DEFAULT:
439*da14cebeSEric Cheng 		return ("default");
440*da14cebeSEric Cheng 	case SRS_TX_SERIALIZE:
441*da14cebeSEric Cheng 		return ("serialize");
442*da14cebeSEric Cheng 	case SRS_TX_FANOUT:
443*da14cebeSEric Cheng 		return ("fanout");
444*da14cebeSEric Cheng 	case SRS_TX_BW:
445*da14cebeSEric Cheng 		return ("bw");
446*da14cebeSEric Cheng 	case SRS_TX_BW_FANOUT:
447*da14cebeSEric Cheng 		return ("bw fanout");
448*da14cebeSEric Cheng 	}
449*da14cebeSEric Cheng 	return ("--");
450*da14cebeSEric Cheng }
451*da14cebeSEric Cheng 
452*da14cebeSEric Cheng static void
453*da14cebeSEric Cheng mac_srs_help(void)
454*da14cebeSEric Cheng {
455*da14cebeSEric Cheng 	mdb_printf("If an address is specified, then mac_soft_ring_set "
456*da14cebeSEric Cheng 	    "structure at that address is printed. Otherwise all the "
457*da14cebeSEric Cheng 	    "SRS in the system are printed.\n");
458*da14cebeSEric Cheng 	mdb_printf("Options:\n"
459*da14cebeSEric Cheng 	    "\t-r\tdisplay recieve side SRS structures\n"
460*da14cebeSEric Cheng 	    "\t-t\tdisplay transmit side SRS structures\n");
461*da14cebeSEric Cheng }
462*da14cebeSEric Cheng 
463*da14cebeSEric Cheng static int
464*da14cebeSEric Cheng mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
465*da14cebeSEric Cheng {
466*da14cebeSEric Cheng 	uint_t			args = 0;
467*da14cebeSEric Cheng 	mac_soft_ring_set_t	srs;
468*da14cebeSEric Cheng 
469*da14cebeSEric Cheng 	if (!(flags & DCMD_ADDRSPEC)) {
470*da14cebeSEric Cheng 		if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) {
471*da14cebeSEric Cheng 			mdb_warn("failed to walk 'mac_srs'");
472*da14cebeSEric Cheng 			return (DCMD_ERR);
473*da14cebeSEric Cheng 		}
474*da14cebeSEric Cheng 		return (DCMD_OK);
475*da14cebeSEric Cheng 	}
476*da14cebeSEric Cheng 	if ((mdb_getopts(argc, argv,
477*da14cebeSEric Cheng 	    'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args,
478*da14cebeSEric Cheng 	    't', MDB_OPT_SETBITS, MAC_SRS_TX, &args) != argc)) {
479*da14cebeSEric Cheng 		return (DCMD_USAGE);
480*da14cebeSEric Cheng 	}
481*da14cebeSEric Cheng 	if (argc > 1)
482*da14cebeSEric Cheng 		return (DCMD_USAGE);
483*da14cebeSEric Cheng 
484*da14cebeSEric Cheng 	if (mdb_vread(&srs, sizeof (srs), addr) == -1) {
485*da14cebeSEric Cheng 		mdb_warn("failed to read struct mac_soft_ring_set_s at %p",
486*da14cebeSEric Cheng 		    addr);
487*da14cebeSEric Cheng 		return (DCMD_ERR);
488*da14cebeSEric Cheng 	}
489*da14cebeSEric Cheng 
490*da14cebeSEric Cheng 	switch (args) {
491*da14cebeSEric Cheng 	case MAC_SRS_RX: {
492*da14cebeSEric Cheng 		GElf_Sym 	sym;
493*da14cebeSEric Cheng 		char		func_name[MDB_SYM_NAMLEN] = "";
494*da14cebeSEric Cheng 		char		l_proc_name[MDB_SYM_NAMLEN] = "";
495*da14cebeSEric Cheng 		uintptr_t	func, lproc, funcaddr, lprocaddr, rxaddr;
496*da14cebeSEric Cheng 
497*da14cebeSEric Cheng 		if (DCMD_HDRSPEC(flags)) {
498*da14cebeSEric Cheng 			mdb_printf("%<u>%?s %8s %-8s "
499*da14cebeSEric Cheng 			    "%8s %-20s %-s%</u>\n",
500*da14cebeSEric Cheng 			    "ADDR", "MBLK_CNT", "Q_BYTES",
501*da14cebeSEric Cheng 			    "POLL_CNT", "SR_FUNC", "SR_LOWER_FUNC");
502*da14cebeSEric Cheng 		}
503*da14cebeSEric Cheng 		if (srs.srs_type & SRST_TX)
504*da14cebeSEric Cheng 			return (DCMD_OK);
505*da14cebeSEric Cheng 		rxaddr = addr + OFFSETOF(mac_soft_ring_set_t, srs_rx);
506*da14cebeSEric Cheng 		funcaddr = rxaddr + OFFSETOF(mac_srs_rx_t, sr_func);
507*da14cebeSEric Cheng 		lprocaddr = rxaddr + OFFSETOF(mac_srs_rx_t, sr_lower_proc);
508*da14cebeSEric Cheng 		(void) mdb_vread(&func, sizeof (func), funcaddr);
509*da14cebeSEric Cheng 		(void) mdb_vread(&lproc, sizeof (lproc), lprocaddr);
510*da14cebeSEric Cheng 		(void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name,
511*da14cebeSEric Cheng 		    MDB_SYM_NAMLEN, &sym);
512*da14cebeSEric Cheng 		(void) mdb_lookup_by_addr(lproc, MDB_SYM_EXACT, l_proc_name,
513*da14cebeSEric Cheng 		    MDB_SYM_NAMLEN, &sym);
514*da14cebeSEric Cheng 		mdb_printf("%?p %-8d %-8d "
515*da14cebeSEric Cheng 		    "%-8d %-20s %-s\n",
516*da14cebeSEric Cheng 		    addr, srs.srs_count, srs.srs_size,
517*da14cebeSEric Cheng 		    srs.srs_rx.sr_poll_count, func_name, l_proc_name);
518*da14cebeSEric Cheng 		break;
519*da14cebeSEric Cheng 	}
520*da14cebeSEric Cheng 	case MAC_SRS_TX: {
521*da14cebeSEric Cheng 		if (DCMD_HDRSPEC(flags)) {
522*da14cebeSEric Cheng 			mdb_printf("%<u>%?s %-10s %-5s %-7s %-7s "
523*da14cebeSEric Cheng 			    "%-7s %-7s %-7s%</u>\n",
524*da14cebeSEric Cheng 			    "ADDR", "TX_MODE", "WOKEN", "DROP", "BLOCK",
525*da14cebeSEric Cheng 			    "UNBLOCK", "MBLK", "SR_CNT");
526*da14cebeSEric Cheng 		}
527*da14cebeSEric Cheng 		if (!(srs.srs_type & SRST_TX))
528*da14cebeSEric Cheng 			return (DCMD_OK);
529*da14cebeSEric Cheng 
530*da14cebeSEric Cheng 		mdb_printf("%?p %-10s "
531*da14cebeSEric Cheng 		    "%-5d %-7d "
532*da14cebeSEric Cheng 		    "%-7d %-7d "
533*da14cebeSEric Cheng 		    "%-7d %-7d\n",
534*da14cebeSEric Cheng 		    addr, mac_srs_txmode2str(srs.srs_tx.st_mode),
535*da14cebeSEric Cheng 		    srs.srs_tx.st_woken_up, srs.srs_tx.st_drop_count,
536*da14cebeSEric Cheng 		    srs.srs_tx.st_blocked_cnt, srs.srs_tx.st_unblocked_cnt,
537*da14cebeSEric Cheng 		    srs.srs_count, srs.srs_oth_ring_count);
538*da14cebeSEric Cheng 		break;
539*da14cebeSEric Cheng 	}
540*da14cebeSEric Cheng 	default: {
541*da14cebeSEric Cheng 		if (DCMD_HDRSPEC(flags)) {
542*da14cebeSEric Cheng 			mdb_printf("%<u>%?s %?s %?s %?s %-3s "
543*da14cebeSEric Cheng 			    "%-8s %-8s %-7s %</u>\n",
544*da14cebeSEric Cheng 			    "ADDR", "MCIP", "FLENT", "RING", "DIR",
545*da14cebeSEric Cheng 			    "TYPE", "STATE", "SR_CNT");
546*da14cebeSEric Cheng 		}
547*da14cebeSEric Cheng 		mdb_printf("%?p %?p %?p %?p "
548*da14cebeSEric Cheng 		    "%-3s "
549*da14cebeSEric Cheng 		    "%08x %08x %-7d \n",
550*da14cebeSEric Cheng 		    addr, srs.srs_mcip, srs.srs_flent, srs.srs_ring,
551*da14cebeSEric Cheng 		    (srs.srs_type & SRST_TX ? "TX" : "RX"),
552*da14cebeSEric Cheng 		    srs.srs_type, srs.srs_state, srs.srs_soft_ring_count);
553*da14cebeSEric Cheng 		break;
554*da14cebeSEric Cheng 	}
555*da14cebeSEric Cheng 	}
556*da14cebeSEric Cheng 	return (DCMD_OK);
557*da14cebeSEric Cheng }
558*da14cebeSEric Cheng 
559*da14cebeSEric Cheng static int
560*da14cebeSEric Cheng mac_srs_walk_init(mdb_walk_state_t *wsp)
561*da14cebeSEric Cheng {
562*da14cebeSEric Cheng 	if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) {
563*da14cebeSEric Cheng 		mdb_warn("failed to walk 'mac_srs'");
564*da14cebeSEric Cheng 		return (WALK_ERR);
565*da14cebeSEric Cheng 	}
566*da14cebeSEric Cheng 	return (WALK_NEXT);
567*da14cebeSEric Cheng }
568*da14cebeSEric Cheng 
569*da14cebeSEric Cheng static char *
570*da14cebeSEric Cheng mac_ring_state2str(mac_ring_state_t state)
571*da14cebeSEric Cheng {
572*da14cebeSEric Cheng 	switch (state) {
573*da14cebeSEric Cheng 	case MR_FREE:
574*da14cebeSEric Cheng 		return ("free");
575*da14cebeSEric Cheng 	case MR_NEWLY_ADDED:
576*da14cebeSEric Cheng 		return ("new");
577*da14cebeSEric Cheng 	case MR_INUSE:
578*da14cebeSEric Cheng 		return ("inuse");
579*da14cebeSEric Cheng 	}
580*da14cebeSEric Cheng 	return ("--");
581*da14cebeSEric Cheng }
582*da14cebeSEric Cheng 
583*da14cebeSEric Cheng static char *
584*da14cebeSEric Cheng mac_ring_classify2str(mac_classify_type_t classify)
585*da14cebeSEric Cheng {
586*da14cebeSEric Cheng 	switch (classify) {
587*da14cebeSEric Cheng 	case MAC_NO_CLASSIFIER:
588*da14cebeSEric Cheng 		return ("no");
589*da14cebeSEric Cheng 	case MAC_SW_CLASSIFIER:
590*da14cebeSEric Cheng 		return ("sw");
591*da14cebeSEric Cheng 	case MAC_HW_CLASSIFIER:
592*da14cebeSEric Cheng 		return ("hw");
593*da14cebeSEric Cheng 	}
594*da14cebeSEric Cheng 	return ("--");
595*da14cebeSEric Cheng }
596*da14cebeSEric Cheng 
597*da14cebeSEric Cheng static int
598*da14cebeSEric Cheng mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
599*da14cebeSEric Cheng {
600*da14cebeSEric Cheng 	mac_ring_t		ring;
601*da14cebeSEric Cheng 	mac_group_t		group;
602*da14cebeSEric Cheng 	flow_entry_t		flent;
603*da14cebeSEric Cheng 	mac_soft_ring_set_t	srs;
604*da14cebeSEric Cheng 
605*da14cebeSEric Cheng 	if (!(flags & DCMD_ADDRSPEC)) {
606*da14cebeSEric Cheng 		if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) {
607*da14cebeSEric Cheng 			mdb_warn("failed to walk 'mac_ring'");
608*da14cebeSEric Cheng 			return (DCMD_ERR);
609*da14cebeSEric Cheng 		}
610*da14cebeSEric Cheng 		return (DCMD_OK);
611*da14cebeSEric Cheng 	}
612*da14cebeSEric Cheng 	if (mdb_vread(&ring, sizeof (ring), addr) == -1) {
613*da14cebeSEric Cheng 		mdb_warn("failed to read struct mac_ring_s at %p", addr);
614*da14cebeSEric Cheng 		return (DCMD_ERR);
615*da14cebeSEric Cheng 	}
616*da14cebeSEric Cheng 	bzero(&flent, sizeof (flent));
617*da14cebeSEric Cheng 	if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) {
618*da14cebeSEric Cheng 		(void) mdb_vread(&flent, sizeof (flent),
619*da14cebeSEric Cheng 		    (uintptr_t)srs.srs_flent);
620*da14cebeSEric Cheng 	}
621*da14cebeSEric Cheng 	(void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh);
622*da14cebeSEric Cheng 	if (DCMD_HDRSPEC(flags)) {
623*da14cebeSEric Cheng 		mdb_printf("%<u>%?s %4s %5s %4s %?s "
624*da14cebeSEric Cheng 		    "%5s %?s %?s %s %</u>\n",
625*da14cebeSEric Cheng 		    "ADDR", "TYPE", "STATE", "FLAG", "GROUP",
626*da14cebeSEric Cheng 		    "CLASS", "MIP", "SRS", "FLOW NAME");
627*da14cebeSEric Cheng 	}
628*da14cebeSEric Cheng 	mdb_printf("%?p %-4s "
629*da14cebeSEric Cheng 	    "%5s %04x "
630*da14cebeSEric Cheng 	    "%?p %-5s "
631*da14cebeSEric Cheng 	    "%?p %?p %s\n",
632*da14cebeSEric Cheng 	    addr, ((ring.mr_type == 1)? "RX" : "TX"),
633*da14cebeSEric Cheng 	    mac_ring_state2str(ring.mr_state), ring.mr_flag,
634*da14cebeSEric Cheng 	    ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type),
635*da14cebeSEric Cheng 	    group.mrg_mh, ring.mr_srs, flent.fe_flow_name);
636*da14cebeSEric Cheng 	return (DCMD_OK);
637*da14cebeSEric Cheng }
638*da14cebeSEric Cheng 
639*da14cebeSEric Cheng static int
640*da14cebeSEric Cheng mac_ring_walk_init(mdb_walk_state_t *wsp)
641*da14cebeSEric Cheng {
642*da14cebeSEric Cheng 	if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) {
643*da14cebeSEric Cheng 		mdb_warn("failed to walk `mac_ring`");
644*da14cebeSEric Cheng 		return (WALK_ERR);
645*da14cebeSEric Cheng 	}
646*da14cebeSEric Cheng 	return (WALK_NEXT);
647*da14cebeSEric Cheng }
648*da14cebeSEric Cheng 
649*da14cebeSEric Cheng static void
650*da14cebeSEric Cheng mac_ring_help(void)
651*da14cebeSEric Cheng {
652*da14cebeSEric Cheng 	mdb_printf("If an address is specified, then mac_ring_t "
653*da14cebeSEric Cheng 	    "structure at that address is printed. Otherwise all the "
654*da14cebeSEric Cheng 	    "hardware rings in the system are printed.\n");
655*da14cebeSEric Cheng }
656*da14cebeSEric Cheng 
657*da14cebeSEric Cheng /* Supported dee-commands */
658*da14cebeSEric Cheng static const mdb_dcmd_t dcmds[] = {
659*da14cebeSEric Cheng 	{"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures",
660*da14cebeSEric Cheng 	    mac_flow_dcmd, mac_flow_help},
661*da14cebeSEric Cheng 	{"mac_srs", "?[-rt]", "display MAC Soft Ring Set structures",
662*da14cebeSEric Cheng 	    mac_srs_dcmd, mac_srs_help},
663*da14cebeSEric Cheng 	{"mac_ring", "?", "display MAC ring (hardware) structures",
664*da14cebeSEric Cheng 	    mac_ring_dcmd, mac_ring_help},
665*da14cebeSEric Cheng 	{ NULL }
666*da14cebeSEric Cheng };
667*da14cebeSEric Cheng 
668*da14cebeSEric Cheng /* Supported walkers */
669*da14cebeSEric Cheng static const mdb_walker_t walkers[] = {
670*da14cebeSEric Cheng 	{"mac_flow", "walk list of flow entry structures", mac_flow_walk_init,
671*da14cebeSEric Cheng 	    mac_common_walk_step, NULL, NULL},
672*da14cebeSEric Cheng 	{"mac_srs", "walk list of mac soft ring set structures",
673*da14cebeSEric Cheng 	    mac_srs_walk_init, mac_common_walk_step, NULL, NULL},
674*da14cebeSEric Cheng 	{"mac_ring", "walk list of mac ring structures", mac_ring_walk_init,
675*da14cebeSEric Cheng 	    mac_common_walk_step, NULL, NULL},
676*da14cebeSEric Cheng 	{ NULL }
677*da14cebeSEric Cheng };
678*da14cebeSEric Cheng 
679*da14cebeSEric Cheng static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
680*da14cebeSEric Cheng 
681*da14cebeSEric Cheng const mdb_modinfo_t *
682*da14cebeSEric Cheng _mdb_init(void)
683*da14cebeSEric Cheng {
684*da14cebeSEric Cheng 	return (&modinfo);
685*da14cebeSEric Cheng }
686