xref: /onnv-gate/usr/src/cmd/mdb/common/modules/mac/mac.c (revision 8999:45c8fc8bceb7)
18275SEric Cheng /*
28275SEric Cheng  * CDDL HEADER START
38275SEric Cheng  *
48275SEric Cheng  * The contents of this file are subject to the terms of the
58275SEric Cheng  * Common Development and Distribution License (the "License").
68275SEric Cheng  * You may not use this file except in compliance with the License.
78275SEric Cheng  *
88275SEric Cheng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98275SEric Cheng  * or http://www.opensolaris.org/os/licensing.
108275SEric Cheng  * See the License for the specific language governing permissions
118275SEric Cheng  * and limitations under the License.
128275SEric Cheng  *
138275SEric Cheng  * When distributing Covered Code, include this CDDL HEADER in each
148275SEric Cheng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158275SEric Cheng  * If applicable, add the following below this CDDL HEADER, with the
168275SEric Cheng  * fields enclosed by brackets "[]" replaced with your own identifying
178275SEric Cheng  * information: Portions Copyright [yyyy] [name of copyright owner]
188275SEric Cheng  *
198275SEric Cheng  * CDDL HEADER END
208275SEric Cheng  */
218275SEric Cheng /*
228480SGirish.Moodalbail@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
238275SEric Cheng  * Use is subject to license terms.
248275SEric Cheng  */
258275SEric Cheng 
268275SEric Cheng #include <sys/mdb_modapi.h>
278275SEric Cheng #include <sys/types.h>
288275SEric Cheng #include <inet/ip.h>
298275SEric Cheng #include <inet/ip6.h>
308275SEric Cheng 
318275SEric Cheng #include <sys/mac.h>
328275SEric Cheng #include <sys/mac_provider.h>
338275SEric Cheng #include <sys/mac_client.h>
348275SEric Cheng #include <sys/mac_client_impl.h>
358275SEric Cheng #include <sys/mac_flow_impl.h>
368275SEric Cheng #include <sys/mac_soft_ring.h>
378275SEric Cheng 
388275SEric Cheng #define	STRSIZE	64
398275SEric Cheng #define	MAC_RX_SRS_SIZE	 (MAX_RINGS_PER_GROUP * sizeof (uintptr_t))
408275SEric Cheng 
418275SEric Cheng #define	LAYERED_WALKER_FOR_FLOW	"flow_entry_cache"
428275SEric Cheng #define	LAYERED_WALKER_FOR_SRS	"mac_srs_cache"
438275SEric Cheng #define	LAYERED_WALKER_FOR_RING	"mac_ring_cache"
448275SEric Cheng 
458275SEric Cheng /* arguments passed to mac_flow dee-command */
468275SEric Cheng #define	MAC_FLOW_NONE	0x01
478275SEric Cheng #define	MAC_FLOW_ATTR	0x02
488275SEric Cheng #define	MAC_FLOW_PROP	0x04
498275SEric Cheng #define	MAC_FLOW_RX	0x08
508275SEric Cheng #define	MAC_FLOW_TX	0x10
518275SEric Cheng #define	MAC_FLOW_USER	0x20
528275SEric Cheng #define	MAC_FLOW_STATS	0x40
538275SEric Cheng #define	MAC_FLOW_MISC	0x80
548275SEric Cheng 
558275SEric Cheng /* arguments passed to mac_srs dee-command */
568480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_NONE		0x00
578480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_RX		0x01
588480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_TX		0x02
598480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_STAT		0x04
608480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_CPU		0x08
618480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_VERBOSE		0x10
628480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_RXSTAT		(MAC_SRS_RX|MAC_SRS_STAT)
638480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_TXSTAT		(MAC_SRS_TX|MAC_SRS_STAT)
648480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_RXCPU		(MAC_SRS_RX|MAC_SRS_CPU)
658480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_TXCPU		(MAC_SRS_TX|MAC_SRS_CPU)
668480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_RXCPUVERBOSE	(MAC_SRS_RXCPU|MAC_SRS_VERBOSE)
678480SGirish.Moodalbail@Sun.COM #define	MAC_SRS_TXCPUVERBOSE	(MAC_SRS_TXCPU|MAC_SRS_VERBOSE)
688275SEric Cheng 
698275SEric Cheng static char *
708275SEric Cheng mac_flow_proto2str(uint8_t protocol)
718275SEric Cheng {
728275SEric Cheng 	switch (protocol) {
738275SEric Cheng 	case IPPROTO_TCP:
748275SEric Cheng 		return ("tcp");
758275SEric Cheng 	case IPPROTO_UDP:
768275SEric Cheng 		return ("udp");
778275SEric Cheng 	case IPPROTO_SCTP:
788275SEric Cheng 		return ("sctp");
798275SEric Cheng 	case IPPROTO_ICMP:
808275SEric Cheng 		return ("icmp");
818275SEric Cheng 	case IPPROTO_ICMPV6:
828275SEric Cheng 		return ("icmpv6");
838275SEric Cheng 	default:
848275SEric Cheng 		return ("--");
858275SEric Cheng 	}
868275SEric Cheng }
878275SEric Cheng 
888275SEric Cheng static char *
898275SEric Cheng mac_flow_priority2str(mac_priority_level_t prio)
908275SEric Cheng {
918275SEric Cheng 	switch (prio) {
928275SEric Cheng 	case MPL_LOW:
938275SEric Cheng 		return ("low");
948275SEric Cheng 	case MPL_MEDIUM:
958275SEric Cheng 		return ("medium");
968275SEric Cheng 	case MPL_HIGH:
978275SEric Cheng 		return ("high");
988275SEric Cheng 	case MPL_RESET:
998275SEric Cheng 		return ("reset");
1008275SEric Cheng 	default:
1018275SEric Cheng 		return ("--");
1028275SEric Cheng 	}
1038275SEric Cheng }
1048275SEric Cheng 
1058275SEric Cheng /*
1068275SEric Cheng  *  Convert bandwidth in bps to a string in mpbs.
1078275SEric Cheng  */
1088275SEric Cheng static char *
1098275SEric Cheng mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len)
1108275SEric Cheng {
1118275SEric Cheng 	int kbps, mbps;
1128275SEric Cheng 
1138275SEric Cheng 	kbps = (bw % 1000000)/1000;
1148275SEric Cheng 	mbps = bw/1000000;
1158275SEric Cheng 	if ((mbps == 0) && (kbps != 0))
1168275SEric Cheng 		mdb_snprintf(buf, len, "0.%03u", kbps);
1178275SEric Cheng 	else
1188275SEric Cheng 		mdb_snprintf(buf, len, "%5u", mbps);
1198275SEric Cheng 	return (buf);
1208275SEric Cheng }
1218275SEric Cheng 
1228275SEric Cheng static void
1238275SEric Cheng mac_flow_print_header(uint_t args)
1248275SEric Cheng {
1258275SEric Cheng 	switch (args) {
1268275SEric Cheng 	case MAC_FLOW_NONE:
127*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?s %-20s %4s %?s %?s %-16s\n",
128*8999SGirish.Moodalbail@Sun.COM 		    "", "", "LINK", "", "", "MIP");
129*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%<u>%?s %-20s %4s %?s %?s %-16s%</u>\n",
130*8999SGirish.Moodalbail@Sun.COM 		    "ADDR", "FLOW NAME", "ID", "MCIP", "MIP", "NAME");
1318275SEric Cheng 		break;
1328275SEric Cheng 	case MAC_FLOW_ATTR:
1338275SEric Cheng 		mdb_printf("%<u>%?s %-32s %-7s %6s "
1348275SEric Cheng 		    "%-9s %s%</u>\n",
1358275SEric Cheng 		    "ADDR", "FLOW NAME", "PROTO", "PORT",
1368275SEric Cheng 		    "DSFLD:MSK", "IPADDR");
1378275SEric Cheng 		break;
1388275SEric Cheng 	case MAC_FLOW_PROP:
1398275SEric Cheng 		mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n",
1408275SEric Cheng 		    "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY");
1418275SEric Cheng 		break;
1428275SEric Cheng 	case MAC_FLOW_MISC:
143*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%<u>%?s %-24s %10s %10s "
144*8999SGirish.Moodalbail@Sun.COM 		    "%20s %4s%</u>\n",
1458275SEric Cheng 		    "ADDR", "FLOW NAME", "TYPE", "FLAGS",
1468275SEric Cheng 		    "MATCH_FN", "ZONE");
1478275SEric Cheng 		break;
1488275SEric Cheng 	case MAC_FLOW_RX:
149*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?s %-24s %3s %s\n", "", "", "SRS", "RX");
150*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%<u>%?s %-24s %3s %s%</u>\n",
151*8999SGirish.Moodalbail@Sun.COM 		    "ADDR", "FLOW NAME", "CNT", "SRS");
1528275SEric Cheng 		break;
1538275SEric Cheng 	case MAC_FLOW_TX:
1548275SEric Cheng 		mdb_printf("%<u>%?s %-32s %?s %</u>\n",
1558275SEric Cheng 		    "ADDR", "FLOW NAME", "TX_SRS");
1568275SEric Cheng 		break;
1578275SEric Cheng 	case MAC_FLOW_STATS:
158*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%<u>%?s %-32s %16s %16s%</u>\n",
1598275SEric Cheng 		    "ADDR", "FLOW NAME", "RBYTES", "OBYTES");
1608275SEric Cheng 		break;
1618275SEric Cheng 	}
1628275SEric Cheng }
1638275SEric Cheng 
1648275SEric Cheng /*
1658275SEric Cheng  * Display selected fields of the flow_entry_t structure
1668275SEric Cheng  */
1678275SEric Cheng static int
1688275SEric Cheng mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args)
1698275SEric Cheng {
1708275SEric Cheng 	static const mdb_bitmask_t flow_type_bits[] = {
1718275SEric Cheng 		{"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC},
1728275SEric Cheng 		{"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC},
1738275SEric Cheng 		{"M", FLOW_MCAST, FLOW_MCAST},
1748275SEric Cheng 		{"O", FLOW_OTHER, FLOW_OTHER},
1758275SEric Cheng 		{"U", FLOW_USER, FLOW_USER},
1768275SEric Cheng 		{"V", FLOW_VNIC, FLOW_VNIC},
1778275SEric Cheng 		{"NS", FLOW_NO_STATS, FLOW_NO_STATS},
1788275SEric Cheng 		{ NULL, 0, 0 }
1798275SEric Cheng 	};
1808275SEric Cheng #define	FLOW_MAX_TYPE	(sizeof (flow_type_bits) / sizeof (mdb_bitmask_t))
1818275SEric Cheng 
1828275SEric Cheng 	static const mdb_bitmask_t flow_flag_bits[] = {
1838275SEric Cheng 		{"Q", FE_QUIESCE, FE_QUIESCE},
1848275SEric Cheng 		{"W", FE_WAITER, FE_WAITER},
1858275SEric Cheng 		{"T", FE_FLOW_TAB, FE_FLOW_TAB},
1868275SEric Cheng 		{"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH},
1878275SEric Cheng 		{"I", FE_INCIPIENT, FE_INCIPIENT},
1888275SEric Cheng 		{"C", FE_CONDEMNED, FE_CONDEMNED},
1898275SEric Cheng 		{"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH},
1908275SEric Cheng 		{"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH},
1918275SEric Cheng 		{ NULL, 0, 0 }
1928275SEric Cheng 	};
1938275SEric Cheng #define	FLOW_MAX_FLAGS	(sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t))
1948275SEric Cheng 	flow_entry_t		fe;
1958275SEric Cheng 	mac_client_impl_t	mcip;
1968275SEric Cheng 	mac_impl_t		mip;
1978275SEric Cheng 
1988275SEric Cheng 	if (mdb_vread(&fe, sizeof (fe), addr) == -1) {
1998275SEric Cheng 		mdb_warn("failed to read struct flow_entry_s at %p", addr);
2008275SEric Cheng 		return (DCMD_ERR);
2018275SEric Cheng 	}
2028275SEric Cheng 	if (args & MAC_FLOW_USER) {
2038275SEric Cheng 		args &= ~MAC_FLOW_USER;
2048275SEric Cheng 		if (fe.fe_type & FLOW_MCAST) {
2058275SEric Cheng 			if (DCMD_HDRSPEC(flags))
2068275SEric Cheng 				mac_flow_print_header(args);
2078275SEric Cheng 			return (DCMD_OK);
2088275SEric Cheng 		}
2098275SEric Cheng 	}
2108275SEric Cheng 	if (DCMD_HDRSPEC(flags))
2118275SEric Cheng 		mac_flow_print_header(args);
2128275SEric Cheng 	bzero(&mcip, sizeof (mcip));
2138275SEric Cheng 	bzero(&mip, sizeof (mip));
2148275SEric Cheng 	if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip),
2158275SEric Cheng 	    (uintptr_t)fe.fe_mcip) == sizeof (mcip)) {
2168275SEric Cheng 		(void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip);
2178275SEric Cheng 	}
2188275SEric Cheng 	switch (args) {
2198275SEric Cheng 	case MAC_FLOW_NONE: {
220*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s %4d %?p "
221*8999SGirish.Moodalbail@Sun.COM 		    "%?p %-16s\n",
2228275SEric Cheng 		    addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip,
2238275SEric Cheng 		    mcip.mci_mip, mip.mi_name);
2248275SEric Cheng 		break;
2258275SEric Cheng 	}
2268275SEric Cheng 	case MAC_FLOW_ATTR: {
2278275SEric Cheng 		struct 	in_addr	in4;
2288275SEric Cheng 		uintptr_t	desc_addr;
2298275SEric Cheng 		flow_desc_t	fdesc;
2308275SEric Cheng 
2318275SEric Cheng 		desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc);
2328275SEric Cheng 		if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) {
2338275SEric Cheng 			mdb_warn("failed to read struct flow_description at %p",
2348275SEric Cheng 			    desc_addr);
2358275SEric Cheng 			return (DCMD_ERR);
2368275SEric Cheng 		}
2378275SEric Cheng 		mdb_printf("%?p %-32s "
238*8999SGirish.Moodalbail@Sun.COM 		    "%-7s %6d "
2398275SEric Cheng 		    "%4d:%-4d ",
2408275SEric Cheng 		    addr, fe.fe_flow_name,
2418275SEric Cheng 		    mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port,
2428275SEric Cheng 		    fdesc.fd_dsfield, fdesc.fd_dsfield_mask);
2438275SEric Cheng 		if (fdesc.fd_ipversion == IPV4_VERSION) {
2448275SEric Cheng 			IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4);
2458275SEric Cheng 			mdb_printf("%I", in4.s_addr);
2468275SEric Cheng 		} else if (fdesc.fd_ipversion == IPV6_VERSION) {
2478275SEric Cheng 			mdb_printf("%N", &fdesc.fd_local_addr);
2488275SEric Cheng 		} else {
2498275SEric Cheng 			mdb_printf("%s", "--");
2508275SEric Cheng 		}
2518275SEric Cheng 		mdb_printf("\n");
2528275SEric Cheng 		break;
2538275SEric Cheng 	}
2548275SEric Cheng 	case MAC_FLOW_PROP: {
2558275SEric Cheng 		uintptr_t	prop_addr;
2568275SEric Cheng 		char		bwstr[STRSIZE];
2578275SEric Cheng 		mac_resource_props_t	fprop;
2588275SEric Cheng 
2598275SEric Cheng 		prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props);
2608275SEric Cheng 		if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) {
2618275SEric Cheng 			mdb_warn("failed to read struct mac_resoource_props "
2628275SEric Cheng 			    "at %p", prop_addr);
2638275SEric Cheng 			return (DCMD_ERR);
2648275SEric Cheng 		}
2658275SEric Cheng 		mdb_printf("%?p %-32s "
2668275SEric Cheng 		    "%8s %9s\n",
2678275SEric Cheng 		    addr, fe.fe_flow_name,
2688275SEric Cheng 		    mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE),
2698275SEric Cheng 		    mac_flow_priority2str(fprop.mrp_priority));
2708275SEric Cheng 		break;
2718275SEric Cheng 	}
2728275SEric Cheng 	case MAC_FLOW_MISC: {
2738275SEric Cheng 		char		flow_flags[2 * FLOW_MAX_FLAGS];
2748275SEric Cheng 		char		flow_type[2 * FLOW_MAX_TYPE];
2758275SEric Cheng 		GElf_Sym 	sym;
2768275SEric Cheng 		char		func_name[MDB_SYM_NAMLEN] = "";
2778275SEric Cheng 		uintptr_t	func, match_addr;
2788275SEric Cheng 
2798275SEric Cheng 		match_addr = addr + OFFSETOF(flow_entry_t, fe_match);
2808275SEric Cheng 		(void) mdb_vread(&func, sizeof (func), match_addr);
2818275SEric Cheng 		(void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name,
2828275SEric Cheng 		    MDB_SYM_NAMLEN, &sym);
2838275SEric Cheng 		mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb",
2848275SEric Cheng 		    fe.fe_flags, flow_flag_bits);
2858275SEric Cheng 		mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb",
2868275SEric Cheng 		    fe.fe_type, flow_type_bits);
287*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-24s %10s %10s "
288*8999SGirish.Moodalbail@Sun.COM 		    "%20s %4d\n",
2898275SEric Cheng 		    addr, fe.fe_flow_name, flow_type, flow_flags,
2908275SEric Cheng 		    func_name, fe.fe_zoneid);
2918275SEric Cheng 		break;
2928275SEric Cheng 	}
2938275SEric Cheng 	case MAC_FLOW_RX: {
2948480SGirish.Moodalbail@Sun.COM 		uintptr_t	rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0};
2958275SEric Cheng 		int		i;
2968275SEric Cheng 
2978275SEric Cheng 		rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs);
2988275SEric Cheng 		(void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr);
299*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-24s %3d ",
3008480SGirish.Moodalbail@Sun.COM 		    addr, fe.fe_flow_name, fe.fe_rx_srs_cnt);
3018275SEric Cheng 		for (i = 0; i < MAX_RINGS_PER_GROUP; i++) {
3028275SEric Cheng 			if (rx_srs[i] == 0)
3038275SEric Cheng 				continue;
3048275SEric Cheng 			mdb_printf("%p ", rx_srs[i]);
3058275SEric Cheng 		}
3068275SEric Cheng 		mdb_printf("\n");
3078275SEric Cheng 		break;
3088275SEric Cheng 	}
3098275SEric Cheng 	case MAC_FLOW_TX: {
3108275SEric Cheng 		uintptr_t	tx_srs = 0, txaddr;
3118275SEric Cheng 
3128275SEric Cheng 		txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs);
3138275SEric Cheng 		(void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr);
3148275SEric Cheng 		mdb_printf("%?p %-32s %?p\n",
3158275SEric Cheng 		    addr, fe.fe_flow_name, fe.fe_tx_srs);
3168275SEric Cheng 		break;
3178275SEric Cheng 	}
3188275SEric Cheng 	case MAC_FLOW_STATS: {
3198275SEric Cheng 		mdb_printf("%?p %-32s %16llu %16llu\n",
3208275SEric Cheng 		    addr, fe.fe_flow_name, fe.fe_flowstats.fs_rbytes,
3218275SEric Cheng 		    fe.fe_flowstats.fs_obytes);
3228275SEric Cheng 		break;
3238275SEric Cheng 	}
3248275SEric Cheng 	}
3258275SEric Cheng 	return (DCMD_OK);
3268275SEric Cheng }
3278275SEric Cheng 
3288275SEric Cheng /*
3298275SEric Cheng  * Parse the arguments passed to the dcmd and print all or one flow_entry_t
3308275SEric Cheng  * structures
3318275SEric Cheng  */
3328275SEric Cheng static int
3338275SEric Cheng mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3348275SEric Cheng {
3358275SEric Cheng 	uint_t	args = 0;
3368275SEric Cheng 
3378275SEric Cheng 	if (!(flags & DCMD_ADDRSPEC)) {
3388275SEric Cheng 		if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) {
3398275SEric Cheng 			mdb_warn("failed to walk 'mac_flow'");
3408275SEric Cheng 			return (DCMD_ERR);
3418275SEric Cheng 		}
3428275SEric Cheng 		return (DCMD_OK);
3438275SEric Cheng 	}
3448275SEric Cheng 	if ((mdb_getopts(argc, argv,
3458275SEric Cheng 	    'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args,
3468275SEric Cheng 	    'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args,
3478275SEric Cheng 	    'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args,
3488275SEric Cheng 	    'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args,
3498275SEric Cheng 	    't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args,
3508275SEric Cheng 	    's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args,
3518275SEric Cheng 	    'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args) != argc)) {
3528275SEric Cheng 		return (DCMD_USAGE);
3538275SEric Cheng 	}
3548275SEric Cheng 	if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER)))
3558275SEric Cheng 		return (DCMD_USAGE);
3568275SEric Cheng 	/*
3578275SEric Cheng 	 * If no arguments was specified or just "-u" was specified then
3588275SEric Cheng 	 * we default to printing basic information of flows.
3598275SEric Cheng 	 */
3608275SEric Cheng 	if (args == 0 || args == MAC_FLOW_USER)
3618275SEric Cheng 		args |= MAC_FLOW_NONE;
3628275SEric Cheng 
3638275SEric Cheng 	return (mac_flow_dcmd_output(addr, flags, args));
3648275SEric Cheng }
3658275SEric Cheng 
3668275SEric Cheng static void
3678275SEric Cheng mac_flow_help(void)
3688275SEric Cheng {
3698275SEric Cheng 	mdb_printf("If an address is specified, then flow_entry structure at "
3708275SEric Cheng 	    "that address is printed. Otherwise all the flows in the system "
3718275SEric Cheng 	    "are printed.\n");
3728275SEric Cheng 	mdb_printf("Options:\n"
3738275SEric Cheng 	    "\t-u\tdisplay user defined link & vnic flows.\n"
3748275SEric Cheng 	    "\t-a\tdisplay flow attributes\n"
3758275SEric Cheng 	    "\t-p\tdisplay flow properties\n"
3768275SEric Cheng 	    "\t-r\tdisplay rx side information\n"
3778275SEric Cheng 	    "\t-t\tdisplay tx side information\n"
3788275SEric Cheng 	    "\t-s\tdisplay flow statistics\n"
3798275SEric Cheng 	    "\t-m\tdisplay miscellaneous flow information\n\n");
3808275SEric Cheng 	mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n");
3818275SEric Cheng 	mdb_printf("Flow Types:\n");
3828275SEric Cheng 	mdb_printf("\t  P --> FLOW_PRIMARY_MAC\n");
3838275SEric Cheng 	mdb_printf("\t  V --> FLOW_VNIC_MAC\n");
3848275SEric Cheng 	mdb_printf("\t  M --> FLOW_MCAST\n");
3858275SEric Cheng 	mdb_printf("\t  O --> FLOW_OTHER\n");
3868275SEric Cheng 	mdb_printf("\t  U --> FLOW_USER\n");
3878275SEric Cheng 	mdb_printf("\t NS --> FLOW_NO_STATS\n\n");
3888275SEric Cheng 	mdb_printf("Flow Flags:\n");
3898275SEric Cheng 	mdb_printf("\t  Q --> FE_QUIESCE\n");
3908275SEric Cheng 	mdb_printf("\t  W --> FE_WAITER\n");
3918275SEric Cheng 	mdb_printf("\t  T --> FE_FLOW_TAB\n");
3928275SEric Cheng 	mdb_printf("\t  G --> FE_G_FLOW_HASH\n");
3938275SEric Cheng 	mdb_printf("\t  I --> FE_INCIPIENT\n");
3948275SEric Cheng 	mdb_printf("\t  C --> FE_CONDEMNED\n");
3958275SEric Cheng 	mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n");
3968275SEric Cheng 	mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n");
3978275SEric Cheng }
3988275SEric Cheng 
3998275SEric Cheng /*
4008275SEric Cheng  * called once by the debugger when the mac_flow walk begins.
4018275SEric Cheng  */
4028275SEric Cheng static int
4038275SEric Cheng mac_flow_walk_init(mdb_walk_state_t *wsp)
4048275SEric Cheng {
4058275SEric Cheng 	if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) {
4068275SEric Cheng 		mdb_warn("failed to walk 'mac_flow'");
4078275SEric Cheng 		return (WALK_ERR);
4088275SEric Cheng 	}
4098275SEric Cheng 	return (WALK_NEXT);
4108275SEric Cheng }
4118275SEric Cheng 
4128275SEric Cheng /*
4138275SEric Cheng  * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and
4148275SEric Cheng  * mac_ring_t.
4158275SEric Cheng  *
4168275SEric Cheng  * Steps through each flow_entry_t and calls the callback function. If the
4178275SEric Cheng  * user executed ::walk mac_flow, it just prints the address or if the user
4188275SEric Cheng  * executed ::mac_flow it displays selected fields of flow_entry_t structure
4198275SEric Cheng  * by calling "mac_flow_dcmd"
4208275SEric Cheng  */
4218275SEric Cheng static int
4228275SEric Cheng mac_common_walk_step(mdb_walk_state_t *wsp)
4238275SEric Cheng {
4248275SEric Cheng 	int status;
4258275SEric Cheng 
4268275SEric Cheng 	if (wsp->walk_addr == NULL)
4278275SEric Cheng 		return (WALK_DONE);
4288275SEric Cheng 
4298275SEric Cheng 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
4308275SEric Cheng 	    wsp->walk_cbdata);
4318275SEric Cheng 
4328275SEric Cheng 	return (status);
4338275SEric Cheng }
4348275SEric Cheng 
4358275SEric Cheng static char *
4368275SEric Cheng mac_srs_txmode2str(mac_tx_srs_mode_t mode)
4378275SEric Cheng {
4388275SEric Cheng 	switch (mode) {
4398275SEric Cheng 	case SRS_TX_DEFAULT:
4408480SGirish.Moodalbail@Sun.COM 		return ("DEF");
4418275SEric Cheng 	case SRS_TX_SERIALIZE:
4428480SGirish.Moodalbail@Sun.COM 		return ("SER");
4438275SEric Cheng 	case SRS_TX_FANOUT:
4448480SGirish.Moodalbail@Sun.COM 		return ("FO");
4458275SEric Cheng 	case SRS_TX_BW:
4468480SGirish.Moodalbail@Sun.COM 		return ("BW");
4478275SEric Cheng 	case SRS_TX_BW_FANOUT:
4488480SGirish.Moodalbail@Sun.COM 		return ("BWFO");
4498275SEric Cheng 	}
4508275SEric Cheng 	return ("--");
4518275SEric Cheng }
4528275SEric Cheng 
4538275SEric Cheng static void
4548275SEric Cheng mac_srs_help(void)
4558275SEric Cheng {
4568275SEric Cheng 	mdb_printf("If an address is specified, then mac_soft_ring_set "
4578275SEric Cheng 	    "structure at that address is printed. Otherwise all the "
4588275SEric Cheng 	    "SRS in the system are printed.\n");
4598275SEric Cheng 	mdb_printf("Options:\n"
4608275SEric Cheng 	    "\t-r\tdisplay recieve side SRS structures\n"
4618480SGirish.Moodalbail@Sun.COM 	    "\t-t\tdisplay transmit side SRS structures\n"
4628480SGirish.Moodalbail@Sun.COM 	    "\t-s\tdisplay statistics for RX or TX side\n"
4638480SGirish.Moodalbail@Sun.COM 	    "\t-c\tdisplay CPU binding for RX or TX side\n"
4648480SGirish.Moodalbail@Sun.COM 	    "\t-v\tverbose flag for CPU binding to list cpus\n"
4658480SGirish.Moodalbail@Sun.COM 	    "Note: use -r or -t (to specify RX or TX side respectively) along "
4668480SGirish.Moodalbail@Sun.COM 	    "with -c or -s\n");
4678480SGirish.Moodalbail@Sun.COM 	mdb_printf("\n%<u>Interpreting TX Modes%</u>\n");
4688480SGirish.Moodalbail@Sun.COM 	mdb_printf("\t DEF --> Default\n");
4698480SGirish.Moodalbail@Sun.COM 	mdb_printf("\t SER --> Serialize\n");
4708480SGirish.Moodalbail@Sun.COM 	mdb_printf("\t  FO --> Fanout\n");
4718480SGirish.Moodalbail@Sun.COM 	mdb_printf("\t  BW --> Bandwidth\n");
4728480SGirish.Moodalbail@Sun.COM 	mdb_printf("\tBWFO --> Bandwidth Fanout\n");
4738480SGirish.Moodalbail@Sun.COM }
4748480SGirish.Moodalbail@Sun.COM 
4758480SGirish.Moodalbail@Sun.COM /*
4768480SGirish.Moodalbail@Sun.COM  * In verbose mode "::mac_srs -rcv or ::mac_srs -tcv", we print the CPUs
4778480SGirish.Moodalbail@Sun.COM  * assigned to a link and CPUS assigned to the soft rings.
4788480SGirish.Moodalbail@Sun.COM  * 'len' is used for formatting the output and represents the number of
4798480SGirish.Moodalbail@Sun.COM  * spaces between CPU list and Fanout CPU list in the output.
4808480SGirish.Moodalbail@Sun.COM  */
4818480SGirish.Moodalbail@Sun.COM static boolean_t
4828480SGirish.Moodalbail@Sun.COM mac_srs_print_cpu(int *i, uint32_t cnt, uint32_t *cpu_list, int *len)
4838480SGirish.Moodalbail@Sun.COM {
4848480SGirish.Moodalbail@Sun.COM 	int		num = 0;
4858480SGirish.Moodalbail@Sun.COM 
4868480SGirish.Moodalbail@Sun.COM 	if (*i == 0)
4878480SGirish.Moodalbail@Sun.COM 		mdb_printf("(");
4888480SGirish.Moodalbail@Sun.COM 	else
4898480SGirish.Moodalbail@Sun.COM 		mdb_printf(" ");
4908480SGirish.Moodalbail@Sun.COM 	while (*i < cnt) {
4918480SGirish.Moodalbail@Sun.COM 		/* We print 6 CPU's at a time to keep display within 80 cols */
4928480SGirish.Moodalbail@Sun.COM 		if (((num + 1) % 7) == 0) {
4938480SGirish.Moodalbail@Sun.COM 			if (len != NULL)
4948480SGirish.Moodalbail@Sun.COM 				*len = 2;
4958480SGirish.Moodalbail@Sun.COM 			return (B_FALSE);
4968480SGirish.Moodalbail@Sun.COM 		}
4978480SGirish.Moodalbail@Sun.COM 		mdb_printf("%02x%c", cpu_list[*i], ((*i == cnt - 1)?')':','));
4988480SGirish.Moodalbail@Sun.COM 		++*i;
4998480SGirish.Moodalbail@Sun.COM 		++num;
5008480SGirish.Moodalbail@Sun.COM 	}
5018480SGirish.Moodalbail@Sun.COM 	if (len != NULL)
5028480SGirish.Moodalbail@Sun.COM 		*len = (7 - num) * 3;
5038480SGirish.Moodalbail@Sun.COM 	return (B_TRUE);
5048275SEric Cheng }
5058275SEric Cheng 
5068275SEric Cheng static int
5078275SEric Cheng mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
5088275SEric Cheng {
5098480SGirish.Moodalbail@Sun.COM 	uint_t			args = MAC_SRS_NONE;
5108275SEric Cheng 	mac_soft_ring_set_t	srs;
5118480SGirish.Moodalbail@Sun.COM 	mac_client_impl_t	mci;
5128275SEric Cheng 
5138275SEric Cheng 	if (!(flags & DCMD_ADDRSPEC)) {
5148275SEric Cheng 		if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) {
5158275SEric Cheng 			mdb_warn("failed to walk 'mac_srs'");
5168275SEric Cheng 			return (DCMD_ERR);
5178275SEric Cheng 		}
5188275SEric Cheng 		return (DCMD_OK);
5198275SEric Cheng 	}
5208480SGirish.Moodalbail@Sun.COM 	if (mdb_getopts(argc, argv,
5218275SEric Cheng 	    'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args,
5228480SGirish.Moodalbail@Sun.COM 	    't', MDB_OPT_SETBITS, MAC_SRS_TX, &args,
5238480SGirish.Moodalbail@Sun.COM 	    'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args,
5248480SGirish.Moodalbail@Sun.COM 	    'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args,
5258480SGirish.Moodalbail@Sun.COM 	    's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args) != argc) {
5268275SEric Cheng 		return (DCMD_USAGE);
5278275SEric Cheng 	}
5288480SGirish.Moodalbail@Sun.COM 
5298480SGirish.Moodalbail@Sun.COM 	if (argc > 2)
5308275SEric Cheng 		return (DCMD_USAGE);
5318275SEric Cheng 
5328275SEric Cheng 	if (mdb_vread(&srs, sizeof (srs), addr) == -1) {
5338275SEric Cheng 		mdb_warn("failed to read struct mac_soft_ring_set_s at %p",
5348275SEric Cheng 		    addr);
5358275SEric Cheng 		return (DCMD_ERR);
5368275SEric Cheng 	}
5378480SGirish.Moodalbail@Sun.COM 	if (mdb_vread(&mci, sizeof (mci), (uintptr_t)srs.srs_mcip) == -1) {
5388480SGirish.Moodalbail@Sun.COM 		mdb_warn("failed to read struct mac_client_impl_t at %p "
5398480SGirish.Moodalbail@Sun.COM 		    "for SRS %p", srs.srs_mcip, addr);
5408480SGirish.Moodalbail@Sun.COM 		return (DCMD_ERR);
5418480SGirish.Moodalbail@Sun.COM 	}
5428275SEric Cheng 
5438275SEric Cheng 	switch (args) {
5448275SEric Cheng 	case MAC_SRS_RX: {
5458275SEric Cheng 		if (DCMD_HDRSPEC(flags)) {
546*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-20s %-8s %-8s %8s "
547*8999SGirish.Moodalbail@Sun.COM 			    "%8s %3s\n",
5488480SGirish.Moodalbail@Sun.COM 			    "", "", "", "", "MBLK",
5498480SGirish.Moodalbail@Sun.COM 			    "Q", "SR");
550*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-20s %-8s %-8s %8s "
551*8999SGirish.Moodalbail@Sun.COM 			    "%8s %3s%</u>\n",
5528480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "STATE", "TYPE", "CNT",
5538480SGirish.Moodalbail@Sun.COM 			    "BYTES", "CNT");
5548275SEric Cheng 		}
5558275SEric Cheng 		if (srs.srs_type & SRST_TX)
5568275SEric Cheng 			return (DCMD_OK);
5578480SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s %08x %08x "
558*8999SGirish.Moodalbail@Sun.COM 		    "%8d %8d %3d\n",
5598480SGirish.Moodalbail@Sun.COM 		    addr, mci.mci_name, srs.srs_state, srs.srs_type,
5608480SGirish.Moodalbail@Sun.COM 		    srs.srs_count, srs.srs_size, srs.srs_soft_ring_count);
5618275SEric Cheng 		break;
5628275SEric Cheng 	}
5638275SEric Cheng 	case MAC_SRS_TX: {
5648275SEric Cheng 		if (DCMD_HDRSPEC(flags)) {
5658480SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-16s %-4s %-8s "
566*8999SGirish.Moodalbail@Sun.COM 			    "%-8s %8s %8s %3s\n",
5678480SGirish.Moodalbail@Sun.COM 			    "", "", "TX", "",
5688480SGirish.Moodalbail@Sun.COM 			    "", "MBLK", "Q", "SR");
5698480SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-16s %-4s %-8s "
570*8999SGirish.Moodalbail@Sun.COM 			    "%-8s %8s %8s %3s%</u>\n",
5718480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "MODE", "STATE",
5728480SGirish.Moodalbail@Sun.COM 			    "TYPE", "CNT", "BYTES", "CNT");
5738275SEric Cheng 		}
5748275SEric Cheng 		if (!(srs.srs_type & SRST_TX))
5758275SEric Cheng 			return (DCMD_OK);
5768275SEric Cheng 
5778480SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-16s %-4s "
578*8999SGirish.Moodalbail@Sun.COM 		    "%08x %08x %8d %8d %3d\n",
5798480SGirish.Moodalbail@Sun.COM 		    addr, mci.mci_name, mac_srs_txmode2str(srs.srs_tx.st_mode),
5808480SGirish.Moodalbail@Sun.COM 		    srs.srs_state, srs.srs_type, srs.srs_count, srs.srs_size,
5818480SGirish.Moodalbail@Sun.COM 		    srs.srs_oth_ring_count);
5828480SGirish.Moodalbail@Sun.COM 		break;
5838480SGirish.Moodalbail@Sun.COM 	}
5848480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_RXCPU: {
5858480SGirish.Moodalbail@Sun.COM 		mac_cpus_t	mc = srs.srs_cpu;
5868480SGirish.Moodalbail@Sun.COM 
5878480SGirish.Moodalbail@Sun.COM 		if (DCMD_HDRSPEC(flags)) {
5888480SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-20s %-4s %-4s "
5898480SGirish.Moodalbail@Sun.COM 			    "%-6s %-4s %-7s\n",
5908480SGirish.Moodalbail@Sun.COM 			    "", "", "NUM", "POLL",
5918480SGirish.Moodalbail@Sun.COM 			    "WORKER", "INTR", "FANOUT");
5928480SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-20s %-4s %-4s "
5938480SGirish.Moodalbail@Sun.COM 			    "%-6s %-4s %-7s%</u>\n",
5948480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "CPUS", "CPU",
5958480SGirish.Moodalbail@Sun.COM 			    "CPU", "CPU", "CPU_CNT");
5968480SGirish.Moodalbail@Sun.COM 		}
5978480SGirish.Moodalbail@Sun.COM 		if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))
5988480SGirish.Moodalbail@Sun.COM 			return (DCMD_OK);
5998480SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s %-4d %-4d "
6008480SGirish.Moodalbail@Sun.COM 		    "%-6d %-4d %-7d\n",
6018480SGirish.Moodalbail@Sun.COM 		    addr, mci.mci_name, mc.mc_ncpus, mc.mc_pollid,
6028480SGirish.Moodalbail@Sun.COM 		    mc.mc_workerid, mc.mc_intr_cpu, mc.mc_fanout_cnt);
6038480SGirish.Moodalbail@Sun.COM 		break;
6048480SGirish.Moodalbail@Sun.COM 
6058480SGirish.Moodalbail@Sun.COM 	}
6068480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_TXCPU: {
6078480SGirish.Moodalbail@Sun.COM 		mac_cpus_t	mc = srs.srs_cpu;
6088480SGirish.Moodalbail@Sun.COM 
6098480SGirish.Moodalbail@Sun.COM 		if (DCMD_HDRSPEC(flags)) {
6108480SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-20s %-4s %-6s "
6118480SGirish.Moodalbail@Sun.COM 			    "%-4s %-7s\n",
6128480SGirish.Moodalbail@Sun.COM 			    "", "", "NUM", "WORKER",
6138480SGirish.Moodalbail@Sun.COM 			    "INTR", "FANOUT");
6148480SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-20s %-4s %-6s "
6158480SGirish.Moodalbail@Sun.COM 			    "%-4s %-7s%</u>\n",
6168480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "CPUS", "CPU",
6178480SGirish.Moodalbail@Sun.COM 			    "CPU", "CPU_CNT");
6188480SGirish.Moodalbail@Sun.COM 		}
6198480SGirish.Moodalbail@Sun.COM 		if ((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX))
6208480SGirish.Moodalbail@Sun.COM 			return (DCMD_OK);
6218480SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s %-4d "
6228480SGirish.Moodalbail@Sun.COM 		    "%-6d %-4d %-7d\n",
6238480SGirish.Moodalbail@Sun.COM 		    addr, mci.mci_name, mc.mc_ncpus,
6248480SGirish.Moodalbail@Sun.COM 		    mc.mc_workerid, mc.mc_intr_cpu, mc.mc_fanout_cnt);
6258275SEric Cheng 		break;
6268275SEric Cheng 	}
6278480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_RXCPUVERBOSE:
6288480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_TXCPUVERBOSE: {
6298480SGirish.Moodalbail@Sun.COM 		mac_cpus_t	mc = srs.srs_cpu;
6308480SGirish.Moodalbail@Sun.COM 		int		cpu_index = 0, fanout_index = 0, len = 0;
6318480SGirish.Moodalbail@Sun.COM 		boolean_t	cpu_done = B_FALSE, fanout_done = B_FALSE;
6328480SGirish.Moodalbail@Sun.COM 
6338275SEric Cheng 		if (DCMD_HDRSPEC(flags)) {
6348480SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-20s %-20s %-20s\n",
6358480SGirish.Moodalbail@Sun.COM 			    "", "", "CPU_COUNT", "FANOUT_CPU_COUNT");
6368480SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-20s "
6378480SGirish.Moodalbail@Sun.COM 			    "%-20s %-20s%</u>\n",
6388480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME",
6398480SGirish.Moodalbail@Sun.COM 			    "(CPU_LIST)", "(CPU_LIST)");
6408275SEric Cheng 		}
6418480SGirish.Moodalbail@Sun.COM 		if (((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) ||
6428480SGirish.Moodalbail@Sun.COM 		    ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)))
6438480SGirish.Moodalbail@Sun.COM 			return (DCMD_OK);
6448480SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s %-20d %-20d\n", addr, mci.mci_name,
6458480SGirish.Moodalbail@Sun.COM 		    mc.mc_ncpus, mc.mc_fanout_cnt);
6468480SGirish.Moodalbail@Sun.COM 		if (mc.mc_ncpus == 0 && mc.mc_fanout_cnt == 0)
6478480SGirish.Moodalbail@Sun.COM 			break;
6488480SGirish.Moodalbail@Sun.COM 		/* print all cpus and cpus for soft rings */
6498480SGirish.Moodalbail@Sun.COM 		while (!cpu_done || !fanout_done) {
6508480SGirish.Moodalbail@Sun.COM 			boolean_t old_value = cpu_done;
6518480SGirish.Moodalbail@Sun.COM 
6528480SGirish.Moodalbail@Sun.COM 			if (!cpu_done) {
6538480SGirish.Moodalbail@Sun.COM 				mdb_printf("%?s %20s ", "", "");
6548480SGirish.Moodalbail@Sun.COM 				cpu_done = mac_srs_print_cpu(&cpu_index,
6558480SGirish.Moodalbail@Sun.COM 				    mc.mc_ncpus, mc.mc_cpus, &len);
6568480SGirish.Moodalbail@Sun.COM 			}
6578480SGirish.Moodalbail@Sun.COM 			if (!fanout_done) {
6588480SGirish.Moodalbail@Sun.COM 				if (old_value)
6598480SGirish.Moodalbail@Sun.COM 					mdb_printf("%?s %-40s", "", "");
6608480SGirish.Moodalbail@Sun.COM 				else
6618480SGirish.Moodalbail@Sun.COM 					mdb_printf("%*s", len, "");
6628480SGirish.Moodalbail@Sun.COM 				fanout_done = mac_srs_print_cpu(&fanout_index,
6638480SGirish.Moodalbail@Sun.COM 				    mc.mc_fanout_cnt, mc.mc_fanout_cpus, NULL);
6648480SGirish.Moodalbail@Sun.COM 			}
6658480SGirish.Moodalbail@Sun.COM 			mdb_printf("\n");
6668480SGirish.Moodalbail@Sun.COM 		}
6678275SEric Cheng 		break;
6688275SEric Cheng 	}
6698480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_RXSTAT: {
6708480SGirish.Moodalbail@Sun.COM 		mac_srs_rx_t srs_rx = srs.srs_rx;
6718480SGirish.Moodalbail@Sun.COM 
6728480SGirish.Moodalbail@Sun.COM 		if (DCMD_HDRSPEC(flags)) {
673*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-16s %8s %8s "
674*8999SGirish.Moodalbail@Sun.COM 			    "%8s %8s %8s\n",
6758480SGirish.Moodalbail@Sun.COM 			    "", "", "INTR", "POLL",
6768480SGirish.Moodalbail@Sun.COM 			    "CHAIN", "CHAIN", "CHAIN");
677*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-16s %8s %8s "
678*8999SGirish.Moodalbail@Sun.COM 			    "%8s %8s %8s%</u>\n",
6798480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "COUNT", "COUNT",
6808480SGirish.Moodalbail@Sun.COM 			    "<10", "10-50", ">50");
6818480SGirish.Moodalbail@Sun.COM 		}
6828480SGirish.Moodalbail@Sun.COM 		if (srs.srs_type & SRST_TX)
6838480SGirish.Moodalbail@Sun.COM 			return (DCMD_OK);
684*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-16s %8d "
685*8999SGirish.Moodalbail@Sun.COM 		    "%8d %8d "
686*8999SGirish.Moodalbail@Sun.COM 		    "%8d %8d\n",
6878480SGirish.Moodalbail@Sun.COM 		    addr, mci.mci_name, srs_rx.sr_intr_count,
6888480SGirish.Moodalbail@Sun.COM 		    srs_rx.sr_poll_count, srs_rx.sr_chain_cnt_undr10,
6898480SGirish.Moodalbail@Sun.COM 		    srs_rx.sr_chain_cnt_10to50, srs_rx.sr_chain_cnt_over50);
6908480SGirish.Moodalbail@Sun.COM 		break;
6918480SGirish.Moodalbail@Sun.COM 	}
6928480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_TXSTAT: {
6938480SGirish.Moodalbail@Sun.COM 		mac_srs_tx_t srs_tx = srs.srs_tx;
694*8999SGirish.Moodalbail@Sun.COM 		mac_soft_ring_t *s_ringp, s_ring;
695*8999SGirish.Moodalbail@Sun.COM 		boolean_t	first = B_TRUE;
6968480SGirish.Moodalbail@Sun.COM 
6978480SGirish.Moodalbail@Sun.COM 		if (DCMD_HDRSPEC(flags)) {
698*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-20s %?s %8s %8s %8s\n",
699*8999SGirish.Moodalbail@Sun.COM 			    "", "", "SOFT", "DROP", "BLOCK", "UNBLOCK");
700*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-20s %?s %8s %8s %8s%</u>\n",
701*8999SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "RING", "COUNT", "COUNT",
702*8999SGirish.Moodalbail@Sun.COM 			    "COUNT");
7038480SGirish.Moodalbail@Sun.COM 		}
7048480SGirish.Moodalbail@Sun.COM 		if (!(srs.srs_type & SRST_TX))
7058480SGirish.Moodalbail@Sun.COM 			return (DCMD_OK);
7068480SGirish.Moodalbail@Sun.COM 
707*8999SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s ", addr, mci.mci_name);
708*8999SGirish.Moodalbail@Sun.COM 
709*8999SGirish.Moodalbail@Sun.COM 		/*
710*8999SGirish.Moodalbail@Sun.COM 		 * Case of no soft rings, print the info from
711*8999SGirish.Moodalbail@Sun.COM 		 * mac_srs_tx_t.
712*8999SGirish.Moodalbail@Sun.COM 		 */
713*8999SGirish.Moodalbail@Sun.COM 		if (srs.srs_oth_ring_count == 0) {
714*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%?p %8d %8d %8d\n",
715*8999SGirish.Moodalbail@Sun.COM 			    0, srs_tx.st_drop_count, srs_tx.st_blocked_cnt,
716*8999SGirish.Moodalbail@Sun.COM 			    srs_tx.st_unblocked_cnt);
717*8999SGirish.Moodalbail@Sun.COM 			break;
718*8999SGirish.Moodalbail@Sun.COM 		}
719*8999SGirish.Moodalbail@Sun.COM 
720*8999SGirish.Moodalbail@Sun.COM 		for (s_ringp = srs.srs_soft_ring_head; s_ringp != NULL;
721*8999SGirish.Moodalbail@Sun.COM 		    s_ringp = s_ring.s_ring_next) {
722*8999SGirish.Moodalbail@Sun.COM 			(void) mdb_vread(&s_ring, sizeof (s_ring),
723*8999SGirish.Moodalbail@Sun.COM 			    (uintptr_t)s_ringp);
724*8999SGirish.Moodalbail@Sun.COM 			if (first) {
725*8999SGirish.Moodalbail@Sun.COM 				mdb_printf("%?p %8d %8d %8d\n",
726*8999SGirish.Moodalbail@Sun.COM 				    s_ringp, s_ring.s_ring_drops,
727*8999SGirish.Moodalbail@Sun.COM 				    s_ring.s_ring_blocked_cnt,
728*8999SGirish.Moodalbail@Sun.COM 				    s_ring.s_ring_unblocked_cnt);
729*8999SGirish.Moodalbail@Sun.COM 				first = B_FALSE;
730*8999SGirish.Moodalbail@Sun.COM 				continue;
731*8999SGirish.Moodalbail@Sun.COM 			}
732*8999SGirish.Moodalbail@Sun.COM 			mdb_printf("%?s %-20s %?p %8d %8d %8d\n",
733*8999SGirish.Moodalbail@Sun.COM 			    "", "", s_ringp, s_ring.s_ring_drops,
734*8999SGirish.Moodalbail@Sun.COM 			    s_ring.s_ring_blocked_cnt,
735*8999SGirish.Moodalbail@Sun.COM 			    s_ring.s_ring_unblocked_cnt);
736*8999SGirish.Moodalbail@Sun.COM 		}
7378480SGirish.Moodalbail@Sun.COM 		break;
7388480SGirish.Moodalbail@Sun.COM 	}
7398480SGirish.Moodalbail@Sun.COM 	case MAC_SRS_NONE: {
7408480SGirish.Moodalbail@Sun.COM 		if (DCMD_HDRSPEC(flags)) {
7418480SGirish.Moodalbail@Sun.COM 			mdb_printf("%<u>%?s %-20s %?s %?s %-3s%</u>\n",
7428480SGirish.Moodalbail@Sun.COM 			    "ADDR", "LINK_NAME", "FLENT", "HW RING", "DIR");
7438480SGirish.Moodalbail@Sun.COM 		}
7448480SGirish.Moodalbail@Sun.COM 		mdb_printf("%?p %-20s %?p %?p "
7458480SGirish.Moodalbail@Sun.COM 		    "%-3s ",
7468480SGirish.Moodalbail@Sun.COM 		    addr, mci.mci_name, srs.srs_flent, srs.srs_ring,
7478480SGirish.Moodalbail@Sun.COM 		    (srs.srs_type & SRST_TX ? "TX" : "RX"));
7488480SGirish.Moodalbail@Sun.COM 		break;
7498480SGirish.Moodalbail@Sun.COM 	}
7508480SGirish.Moodalbail@Sun.COM 	default:
7518480SGirish.Moodalbail@Sun.COM 		return (DCMD_USAGE);
7528275SEric Cheng 	}
7538275SEric Cheng 	return (DCMD_OK);
7548275SEric Cheng }
7558275SEric Cheng 
7568275SEric Cheng static int
7578275SEric Cheng mac_srs_walk_init(mdb_walk_state_t *wsp)
7588275SEric Cheng {
7598275SEric Cheng 	if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) {
7608275SEric Cheng 		mdb_warn("failed to walk 'mac_srs'");
7618275SEric Cheng 		return (WALK_ERR);
7628275SEric Cheng 	}
7638275SEric Cheng 	return (WALK_NEXT);
7648275SEric Cheng }
7658275SEric Cheng 
7668275SEric Cheng static char *
7678275SEric Cheng mac_ring_state2str(mac_ring_state_t state)
7688275SEric Cheng {
7698275SEric Cheng 	switch (state) {
7708275SEric Cheng 	case MR_FREE:
7718275SEric Cheng 		return ("free");
7728275SEric Cheng 	case MR_NEWLY_ADDED:
7738275SEric Cheng 		return ("new");
7748275SEric Cheng 	case MR_INUSE:
7758275SEric Cheng 		return ("inuse");
7768275SEric Cheng 	}
7778275SEric Cheng 	return ("--");
7788275SEric Cheng }
7798275SEric Cheng 
7808275SEric Cheng static char *
7818275SEric Cheng mac_ring_classify2str(mac_classify_type_t classify)
7828275SEric Cheng {
7838275SEric Cheng 	switch (classify) {
7848275SEric Cheng 	case MAC_NO_CLASSIFIER:
7858275SEric Cheng 		return ("no");
7868275SEric Cheng 	case MAC_SW_CLASSIFIER:
7878275SEric Cheng 		return ("sw");
7888275SEric Cheng 	case MAC_HW_CLASSIFIER:
7898275SEric Cheng 		return ("hw");
7908275SEric Cheng 	}
7918275SEric Cheng 	return ("--");
7928275SEric Cheng }
7938275SEric Cheng 
7948275SEric Cheng static int
7958275SEric Cheng mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
7968275SEric Cheng {
7978275SEric Cheng 	mac_ring_t		ring;
7988275SEric Cheng 	mac_group_t		group;
7998275SEric Cheng 	flow_entry_t		flent;
8008275SEric Cheng 	mac_soft_ring_set_t	srs;
8018275SEric Cheng 
8028275SEric Cheng 	if (!(flags & DCMD_ADDRSPEC)) {
8038275SEric Cheng 		if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) {
8048275SEric Cheng 			mdb_warn("failed to walk 'mac_ring'");
8058275SEric Cheng 			return (DCMD_ERR);
8068275SEric Cheng 		}
8078275SEric Cheng 		return (DCMD_OK);
8088275SEric Cheng 	}
8098275SEric Cheng 	if (mdb_vread(&ring, sizeof (ring), addr) == -1) {
8108275SEric Cheng 		mdb_warn("failed to read struct mac_ring_s at %p", addr);
8118275SEric Cheng 		return (DCMD_ERR);
8128275SEric Cheng 	}
8138275SEric Cheng 	bzero(&flent, sizeof (flent));
8148275SEric Cheng 	if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) {
8158275SEric Cheng 		(void) mdb_vread(&flent, sizeof (flent),
8168275SEric Cheng 		    (uintptr_t)srs.srs_flent);
8178275SEric Cheng 	}
8188275SEric Cheng 	(void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh);
8198275SEric Cheng 	if (DCMD_HDRSPEC(flags)) {
8208275SEric Cheng 		mdb_printf("%<u>%?s %4s %5s %4s %?s "
8218275SEric Cheng 		    "%5s %?s %?s %s %</u>\n",
8228275SEric Cheng 		    "ADDR", "TYPE", "STATE", "FLAG", "GROUP",
8238275SEric Cheng 		    "CLASS", "MIP", "SRS", "FLOW NAME");
8248275SEric Cheng 	}
8258275SEric Cheng 	mdb_printf("%?p %-4s "
8268275SEric Cheng 	    "%5s %04x "
8278275SEric Cheng 	    "%?p %-5s "
8288275SEric Cheng 	    "%?p %?p %s\n",
8298275SEric Cheng 	    addr, ((ring.mr_type == 1)? "RX" : "TX"),
8308275SEric Cheng 	    mac_ring_state2str(ring.mr_state), ring.mr_flag,
8318275SEric Cheng 	    ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type),
8328275SEric Cheng 	    group.mrg_mh, ring.mr_srs, flent.fe_flow_name);
8338275SEric Cheng 	return (DCMD_OK);
8348275SEric Cheng }
8358275SEric Cheng 
8368275SEric Cheng static int
8378275SEric Cheng mac_ring_walk_init(mdb_walk_state_t *wsp)
8388275SEric Cheng {
8398275SEric Cheng 	if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) {
8408275SEric Cheng 		mdb_warn("failed to walk `mac_ring`");
8418275SEric Cheng 		return (WALK_ERR);
8428275SEric Cheng 	}
8438275SEric Cheng 	return (WALK_NEXT);
8448275SEric Cheng }
8458275SEric Cheng 
8468275SEric Cheng static void
8478275SEric Cheng mac_ring_help(void)
8488275SEric Cheng {
8498275SEric Cheng 	mdb_printf("If an address is specified, then mac_ring_t "
8508275SEric Cheng 	    "structure at that address is printed. Otherwise all the "
8518275SEric Cheng 	    "hardware rings in the system are printed.\n");
8528275SEric Cheng }
8538275SEric Cheng 
8548275SEric Cheng /* Supported dee-commands */
8558275SEric Cheng static const mdb_dcmd_t dcmds[] = {
8568275SEric Cheng 	{"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures",
8578275SEric Cheng 	    mac_flow_dcmd, mac_flow_help},
8588480SGirish.Moodalbail@Sun.COM 	{"mac_srs", "?[ -r[s|c[v]] | -t[s|c[v]] ]", "display MAC Soft Ring Set"
8598480SGirish.Moodalbail@Sun.COM 	    " structures", mac_srs_dcmd, mac_srs_help},
8608275SEric Cheng 	{"mac_ring", "?", "display MAC ring (hardware) structures",
8618275SEric Cheng 	    mac_ring_dcmd, mac_ring_help},
8628275SEric Cheng 	{ NULL }
8638275SEric Cheng };
8648275SEric Cheng 
8658275SEric Cheng /* Supported walkers */
8668275SEric Cheng static const mdb_walker_t walkers[] = {
8678275SEric Cheng 	{"mac_flow", "walk list of flow entry structures", mac_flow_walk_init,
8688275SEric Cheng 	    mac_common_walk_step, NULL, NULL},
8698275SEric Cheng 	{"mac_srs", "walk list of mac soft ring set structures",
8708275SEric Cheng 	    mac_srs_walk_init, mac_common_walk_step, NULL, NULL},
8718275SEric Cheng 	{"mac_ring", "walk list of mac ring structures", mac_ring_walk_init,
8728275SEric Cheng 	    mac_common_walk_step, NULL, NULL},
8738275SEric Cheng 	{ NULL }
8748275SEric Cheng };
8758275SEric Cheng 
8768275SEric Cheng static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
8778275SEric Cheng 
8788275SEric Cheng const mdb_modinfo_t *
8798275SEric Cheng _mdb_init(void)
8808275SEric Cheng {
8818275SEric Cheng 	return (&modinfo);
8828275SEric Cheng }
883