1da14cebeSEric Cheng /*
2da14cebeSEric Cheng * CDDL HEADER START
3da14cebeSEric Cheng *
4da14cebeSEric Cheng * The contents of this file are subject to the terms of the
5da14cebeSEric Cheng * Common Development and Distribution License (the "License").
6da14cebeSEric Cheng * You may not use this file except in compliance with the License.
7da14cebeSEric Cheng *
8da14cebeSEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da14cebeSEric Cheng * or http://www.opensolaris.org/os/licensing.
10da14cebeSEric Cheng * See the License for the specific language governing permissions
11da14cebeSEric Cheng * and limitations under the License.
12da14cebeSEric Cheng *
13da14cebeSEric Cheng * When distributing Covered Code, include this CDDL HEADER in each
14da14cebeSEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da14cebeSEric Cheng * If applicable, add the following below this CDDL HEADER, with the
16da14cebeSEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying
17da14cebeSEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner]
18da14cebeSEric Cheng *
19da14cebeSEric Cheng * CDDL HEADER END
20da14cebeSEric Cheng */
21da14cebeSEric Cheng /*
220dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23da14cebeSEric Cheng * Use is subject to license terms.
24da14cebeSEric Cheng */
25da14cebeSEric Cheng
26da14cebeSEric Cheng #include <sys/mdb_modapi.h>
27da14cebeSEric Cheng #include <sys/types.h>
28da14cebeSEric Cheng #include <inet/ip.h>
29da14cebeSEric Cheng #include <inet/ip6.h>
30da14cebeSEric Cheng
31da14cebeSEric Cheng #include <sys/mac.h>
32da14cebeSEric Cheng #include <sys/mac_provider.h>
33da14cebeSEric Cheng #include <sys/mac_client.h>
34da14cebeSEric Cheng #include <sys/mac_client_impl.h>
35da14cebeSEric Cheng #include <sys/mac_flow_impl.h>
36da14cebeSEric Cheng #include <sys/mac_soft_ring.h>
370dc2366fSVenugopal Iyer #include <sys/mac_stat.h>
38da14cebeSEric Cheng
39da14cebeSEric Cheng #define STRSIZE 64
40da14cebeSEric Cheng #define MAC_RX_SRS_SIZE (MAX_RINGS_PER_GROUP * sizeof (uintptr_t))
41da14cebeSEric Cheng
42da14cebeSEric Cheng #define LAYERED_WALKER_FOR_FLOW "flow_entry_cache"
43da14cebeSEric Cheng #define LAYERED_WALKER_FOR_SRS "mac_srs_cache"
44da14cebeSEric Cheng #define LAYERED_WALKER_FOR_RING "mac_ring_cache"
45*3f9e4ab7SRobert Mustacchi #define LAYERED_WALKER_FOR_GROUP "mac_impl_cache"
46da14cebeSEric Cheng
47da14cebeSEric Cheng /* arguments passed to mac_flow dee-command */
48da14cebeSEric Cheng #define MAC_FLOW_NONE 0x01
49da14cebeSEric Cheng #define MAC_FLOW_ATTR 0x02
50da14cebeSEric Cheng #define MAC_FLOW_PROP 0x04
51da14cebeSEric Cheng #define MAC_FLOW_RX 0x08
52da14cebeSEric Cheng #define MAC_FLOW_TX 0x10
53da14cebeSEric Cheng #define MAC_FLOW_USER 0x20
54da14cebeSEric Cheng #define MAC_FLOW_STATS 0x40
55da14cebeSEric Cheng #define MAC_FLOW_MISC 0x80
56da14cebeSEric Cheng
57da14cebeSEric Cheng /* arguments passed to mac_srs dee-command */
582ae51e79SGirish Moodalbail #define MAC_SRS_NONE 0x00
59da14cebeSEric Cheng #define MAC_SRS_RX 0x01
60da14cebeSEric Cheng #define MAC_SRS_TX 0x02
612ae51e79SGirish Moodalbail #define MAC_SRS_STAT 0x04
622ae51e79SGirish Moodalbail #define MAC_SRS_CPU 0x08
632ae51e79SGirish Moodalbail #define MAC_SRS_VERBOSE 0x10
640dc2366fSVenugopal Iyer #define MAC_SRS_INTR 0x20
652ae51e79SGirish Moodalbail #define MAC_SRS_RXSTAT (MAC_SRS_RX|MAC_SRS_STAT)
662ae51e79SGirish Moodalbail #define MAC_SRS_TXSTAT (MAC_SRS_TX|MAC_SRS_STAT)
672ae51e79SGirish Moodalbail #define MAC_SRS_RXCPU (MAC_SRS_RX|MAC_SRS_CPU)
682ae51e79SGirish Moodalbail #define MAC_SRS_TXCPU (MAC_SRS_TX|MAC_SRS_CPU)
692ae51e79SGirish Moodalbail #define MAC_SRS_RXCPUVERBOSE (MAC_SRS_RXCPU|MAC_SRS_VERBOSE)
702ae51e79SGirish Moodalbail #define MAC_SRS_TXCPUVERBOSE (MAC_SRS_TXCPU|MAC_SRS_VERBOSE)
710dc2366fSVenugopal Iyer #define MAC_SRS_RXINTR (MAC_SRS_RX|MAC_SRS_INTR)
720dc2366fSVenugopal Iyer #define MAC_SRS_TXINTR (MAC_SRS_TX|MAC_SRS_INTR)
73da14cebeSEric Cheng
74*3f9e4ab7SRobert Mustacchi /* arguments passed to mac_group dcmd */
75*3f9e4ab7SRobert Mustacchi #define MAC_GROUP_NONE 0x00
76*3f9e4ab7SRobert Mustacchi #define MAC_GROUP_RX 0x01
77*3f9e4ab7SRobert Mustacchi #define MAC_GROUP_TX 0x02
78*3f9e4ab7SRobert Mustacchi #define MAC_GROUP_UNINIT 0x04
79*3f9e4ab7SRobert Mustacchi
80da14cebeSEric Cheng static char *
mac_flow_proto2str(uint8_t protocol)81da14cebeSEric Cheng mac_flow_proto2str(uint8_t protocol)
82da14cebeSEric Cheng {
83da14cebeSEric Cheng switch (protocol) {
84da14cebeSEric Cheng case IPPROTO_TCP:
85da14cebeSEric Cheng return ("tcp");
86da14cebeSEric Cheng case IPPROTO_UDP:
87da14cebeSEric Cheng return ("udp");
88da14cebeSEric Cheng case IPPROTO_SCTP:
89da14cebeSEric Cheng return ("sctp");
90da14cebeSEric Cheng case IPPROTO_ICMP:
91da14cebeSEric Cheng return ("icmp");
92da14cebeSEric Cheng case IPPROTO_ICMPV6:
93da14cebeSEric Cheng return ("icmpv6");
94da14cebeSEric Cheng default:
95da14cebeSEric Cheng return ("--");
96da14cebeSEric Cheng }
97da14cebeSEric Cheng }
98da14cebeSEric Cheng
99da14cebeSEric Cheng static char *
mac_flow_priority2str(mac_priority_level_t prio)100da14cebeSEric Cheng mac_flow_priority2str(mac_priority_level_t prio)
101da14cebeSEric Cheng {
102da14cebeSEric Cheng switch (prio) {
103da14cebeSEric Cheng case MPL_LOW:
104da14cebeSEric Cheng return ("low");
105da14cebeSEric Cheng case MPL_MEDIUM:
106da14cebeSEric Cheng return ("medium");
107da14cebeSEric Cheng case MPL_HIGH:
108da14cebeSEric Cheng return ("high");
109da14cebeSEric Cheng case MPL_RESET:
110da14cebeSEric Cheng return ("reset");
111da14cebeSEric Cheng default:
112da14cebeSEric Cheng return ("--");
113da14cebeSEric Cheng }
114da14cebeSEric Cheng }
115da14cebeSEric Cheng
116da14cebeSEric Cheng /*
1174a3b1d5bSBart Coddens * Convert bandwidth in bps to a string in Mbps.
118da14cebeSEric Cheng */
119da14cebeSEric Cheng static char *
mac_flow_bw2str(uint64_t bw,char * buf,ssize_t len)120da14cebeSEric Cheng mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len)
121da14cebeSEric Cheng {
122da14cebeSEric Cheng int kbps, mbps;
123da14cebeSEric Cheng
124da14cebeSEric Cheng kbps = (bw % 1000000)/1000;
125da14cebeSEric Cheng mbps = bw/1000000;
126da14cebeSEric Cheng if ((mbps == 0) && (kbps != 0))
127da14cebeSEric Cheng mdb_snprintf(buf, len, "0.%03u", kbps);
128da14cebeSEric Cheng else
129da14cebeSEric Cheng mdb_snprintf(buf, len, "%5u", mbps);
130da14cebeSEric Cheng return (buf);
131da14cebeSEric Cheng }
132da14cebeSEric Cheng
133da14cebeSEric Cheng static void
mac_flow_print_header(uint_t args)134da14cebeSEric Cheng mac_flow_print_header(uint_t args)
135da14cebeSEric Cheng {
136da14cebeSEric Cheng switch (args) {
137da14cebeSEric Cheng case MAC_FLOW_NONE:
138fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %4s %?s %?s %-16s\n",
139fcff38ebSGirish Moodalbail "", "", "LINK", "", "", "MIP");
140fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %4s %?s %?s %-16s%</u>\n",
141fcff38ebSGirish Moodalbail "ADDR", "FLOW NAME", "ID", "MCIP", "MIP", "NAME");
142da14cebeSEric Cheng break;
143da14cebeSEric Cheng case MAC_FLOW_ATTR:
144da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %-7s %6s "
145da14cebeSEric Cheng "%-9s %s%</u>\n",
146da14cebeSEric Cheng "ADDR", "FLOW NAME", "PROTO", "PORT",
147da14cebeSEric Cheng "DSFLD:MSK", "IPADDR");
148da14cebeSEric Cheng break;
149da14cebeSEric Cheng case MAC_FLOW_PROP:
150da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n",
151da14cebeSEric Cheng "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY");
152da14cebeSEric Cheng break;
153da14cebeSEric Cheng case MAC_FLOW_MISC:
154fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-24s %10s %10s "
155fcff38ebSGirish Moodalbail "%20s %4s%</u>\n",
156da14cebeSEric Cheng "ADDR", "FLOW NAME", "TYPE", "FLAGS",
157da14cebeSEric Cheng "MATCH_FN", "ZONE");
158da14cebeSEric Cheng break;
159da14cebeSEric Cheng case MAC_FLOW_RX:
160fcff38ebSGirish Moodalbail mdb_printf("%?s %-24s %3s %s\n", "", "", "SRS", "RX");
161fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-24s %3s %s%</u>\n",
162fcff38ebSGirish Moodalbail "ADDR", "FLOW NAME", "CNT", "SRS");
163da14cebeSEric Cheng break;
164da14cebeSEric Cheng case MAC_FLOW_TX:
165da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %?s %</u>\n",
166da14cebeSEric Cheng "ADDR", "FLOW NAME", "TX_SRS");
167da14cebeSEric Cheng break;
168da14cebeSEric Cheng case MAC_FLOW_STATS:
169fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-32s %16s %16s%</u>\n",
170da14cebeSEric Cheng "ADDR", "FLOW NAME", "RBYTES", "OBYTES");
171da14cebeSEric Cheng break;
172da14cebeSEric Cheng }
173da14cebeSEric Cheng }
174da14cebeSEric Cheng
175da14cebeSEric Cheng /*
176da14cebeSEric Cheng * Display selected fields of the flow_entry_t structure
177da14cebeSEric Cheng */
178da14cebeSEric Cheng static int
mac_flow_dcmd_output(uintptr_t addr,uint_t flags,uint_t args)179da14cebeSEric Cheng mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args)
180da14cebeSEric Cheng {
181da14cebeSEric Cheng static const mdb_bitmask_t flow_type_bits[] = {
182da14cebeSEric Cheng {"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC},
183da14cebeSEric Cheng {"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC},
184da14cebeSEric Cheng {"M", FLOW_MCAST, FLOW_MCAST},
185da14cebeSEric Cheng {"O", FLOW_OTHER, FLOW_OTHER},
186da14cebeSEric Cheng {"U", FLOW_USER, FLOW_USER},
187da14cebeSEric Cheng {"V", FLOW_VNIC, FLOW_VNIC},
188da14cebeSEric Cheng {"NS", FLOW_NO_STATS, FLOW_NO_STATS},
189da14cebeSEric Cheng { NULL, 0, 0 }
190da14cebeSEric Cheng };
191da14cebeSEric Cheng #define FLOW_MAX_TYPE (sizeof (flow_type_bits) / sizeof (mdb_bitmask_t))
192da14cebeSEric Cheng
193da14cebeSEric Cheng static const mdb_bitmask_t flow_flag_bits[] = {
194da14cebeSEric Cheng {"Q", FE_QUIESCE, FE_QUIESCE},
195da14cebeSEric Cheng {"W", FE_WAITER, FE_WAITER},
196da14cebeSEric Cheng {"T", FE_FLOW_TAB, FE_FLOW_TAB},
197da14cebeSEric Cheng {"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH},
198da14cebeSEric Cheng {"I", FE_INCIPIENT, FE_INCIPIENT},
199da14cebeSEric Cheng {"C", FE_CONDEMNED, FE_CONDEMNED},
200da14cebeSEric Cheng {"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH},
201da14cebeSEric Cheng {"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH},
202da14cebeSEric Cheng { NULL, 0, 0 }
203da14cebeSEric Cheng };
204da14cebeSEric Cheng #define FLOW_MAX_FLAGS (sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t))
205da14cebeSEric Cheng flow_entry_t fe;
206da14cebeSEric Cheng mac_client_impl_t mcip;
207da14cebeSEric Cheng mac_impl_t mip;
208da14cebeSEric Cheng
209da14cebeSEric Cheng if (mdb_vread(&fe, sizeof (fe), addr) == -1) {
210da14cebeSEric Cheng mdb_warn("failed to read struct flow_entry_s at %p", addr);
211da14cebeSEric Cheng return (DCMD_ERR);
212da14cebeSEric Cheng }
213da14cebeSEric Cheng if (args & MAC_FLOW_USER) {
214da14cebeSEric Cheng args &= ~MAC_FLOW_USER;
215da14cebeSEric Cheng if (fe.fe_type & FLOW_MCAST) {
216da14cebeSEric Cheng if (DCMD_HDRSPEC(flags))
217da14cebeSEric Cheng mac_flow_print_header(args);
218da14cebeSEric Cheng return (DCMD_OK);
219da14cebeSEric Cheng }
220da14cebeSEric Cheng }
221da14cebeSEric Cheng if (DCMD_HDRSPEC(flags))
222da14cebeSEric Cheng mac_flow_print_header(args);
223da14cebeSEric Cheng bzero(&mcip, sizeof (mcip));
224da14cebeSEric Cheng bzero(&mip, sizeof (mip));
225da14cebeSEric Cheng if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip),
226da14cebeSEric Cheng (uintptr_t)fe.fe_mcip) == sizeof (mcip)) {
227da14cebeSEric Cheng (void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip);
228da14cebeSEric Cheng }
229da14cebeSEric Cheng switch (args) {
230da14cebeSEric Cheng case MAC_FLOW_NONE: {
231fcff38ebSGirish Moodalbail mdb_printf("%?p %-20s %4d %?p "
232fcff38ebSGirish Moodalbail "%?p %-16s\n",
233da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip,
234da14cebeSEric Cheng mcip.mci_mip, mip.mi_name);
235da14cebeSEric Cheng break;
236da14cebeSEric Cheng }
237da14cebeSEric Cheng case MAC_FLOW_ATTR: {
238da14cebeSEric Cheng struct in_addr in4;
239da14cebeSEric Cheng uintptr_t desc_addr;
240da14cebeSEric Cheng flow_desc_t fdesc;
241da14cebeSEric Cheng
242da14cebeSEric Cheng desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc);
243da14cebeSEric Cheng if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) {
244da14cebeSEric Cheng mdb_warn("failed to read struct flow_description at %p",
245da14cebeSEric Cheng desc_addr);
246da14cebeSEric Cheng return (DCMD_ERR);
247da14cebeSEric Cheng }
248da14cebeSEric Cheng mdb_printf("%?p %-32s "
249da14cebeSEric Cheng "%-7s %6d "
250da14cebeSEric Cheng "%4d:%-4d ",
251da14cebeSEric Cheng addr, fe.fe_flow_name,
252da14cebeSEric Cheng mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port,
253da14cebeSEric Cheng fdesc.fd_dsfield, fdesc.fd_dsfield_mask);
254da14cebeSEric Cheng if (fdesc.fd_ipversion == IPV4_VERSION) {
255da14cebeSEric Cheng IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4);
256da14cebeSEric Cheng mdb_printf("%I", in4.s_addr);
257da14cebeSEric Cheng } else if (fdesc.fd_ipversion == IPV6_VERSION) {
258da14cebeSEric Cheng mdb_printf("%N", &fdesc.fd_local_addr);
259da14cebeSEric Cheng } else {
260da14cebeSEric Cheng mdb_printf("%s", "--");
261da14cebeSEric Cheng }
262da14cebeSEric Cheng mdb_printf("\n");
263da14cebeSEric Cheng break;
264da14cebeSEric Cheng }
265da14cebeSEric Cheng case MAC_FLOW_PROP: {
266da14cebeSEric Cheng uintptr_t prop_addr;
267da14cebeSEric Cheng char bwstr[STRSIZE];
268da14cebeSEric Cheng mac_resource_props_t fprop;
269da14cebeSEric Cheng
270da14cebeSEric Cheng prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props);
271da14cebeSEric Cheng if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) {
272da14cebeSEric Cheng mdb_warn("failed to read struct mac_resoource_props "
273da14cebeSEric Cheng "at %p", prop_addr);
274da14cebeSEric Cheng return (DCMD_ERR);
275da14cebeSEric Cheng }
276da14cebeSEric Cheng mdb_printf("%?p %-32s "
277da14cebeSEric Cheng "%8s %9s\n",
278da14cebeSEric Cheng addr, fe.fe_flow_name,
279da14cebeSEric Cheng mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE),
280da14cebeSEric Cheng mac_flow_priority2str(fprop.mrp_priority));
281da14cebeSEric Cheng break;
282da14cebeSEric Cheng }
283da14cebeSEric Cheng case MAC_FLOW_MISC: {
284da14cebeSEric Cheng char flow_flags[2 * FLOW_MAX_FLAGS];
285da14cebeSEric Cheng char flow_type[2 * FLOW_MAX_TYPE];
286da14cebeSEric Cheng GElf_Sym sym;
287da14cebeSEric Cheng char func_name[MDB_SYM_NAMLEN] = "";
288da14cebeSEric Cheng uintptr_t func, match_addr;
289da14cebeSEric Cheng
290da14cebeSEric Cheng match_addr = addr + OFFSETOF(flow_entry_t, fe_match);
291da14cebeSEric Cheng (void) mdb_vread(&func, sizeof (func), match_addr);
292da14cebeSEric Cheng (void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name,
293da14cebeSEric Cheng MDB_SYM_NAMLEN, &sym);
294da14cebeSEric Cheng mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb",
295da14cebeSEric Cheng fe.fe_flags, flow_flag_bits);
296da14cebeSEric Cheng mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb",
297da14cebeSEric Cheng fe.fe_type, flow_type_bits);
2982b24ab6bSSebastien Roy mdb_printf("%?p %-24s %10s %10s %20s\n",
2992b24ab6bSSebastien Roy addr, fe.fe_flow_name, flow_type, flow_flags, func_name);
300da14cebeSEric Cheng break;
301da14cebeSEric Cheng }
302da14cebeSEric Cheng case MAC_FLOW_RX: {
3032ae51e79SGirish Moodalbail uintptr_t rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0};
304da14cebeSEric Cheng int i;
305da14cebeSEric Cheng
306da14cebeSEric Cheng rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs);
307da14cebeSEric Cheng (void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr);
308fcff38ebSGirish Moodalbail mdb_printf("%?p %-24s %3d ",
3092ae51e79SGirish Moodalbail addr, fe.fe_flow_name, fe.fe_rx_srs_cnt);
310da14cebeSEric Cheng for (i = 0; i < MAX_RINGS_PER_GROUP; i++) {
311da14cebeSEric Cheng if (rx_srs[i] == 0)
312da14cebeSEric Cheng continue;
313da14cebeSEric Cheng mdb_printf("%p ", rx_srs[i]);
314da14cebeSEric Cheng }
315da14cebeSEric Cheng mdb_printf("\n");
316da14cebeSEric Cheng break;
317da14cebeSEric Cheng }
318da14cebeSEric Cheng case MAC_FLOW_TX: {
319da14cebeSEric Cheng uintptr_t tx_srs = 0, txaddr;
320da14cebeSEric Cheng
321da14cebeSEric Cheng txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs);
322da14cebeSEric Cheng (void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr);
323da14cebeSEric Cheng mdb_printf("%?p %-32s %?p\n",
324da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_tx_srs);
325da14cebeSEric Cheng break;
326da14cebeSEric Cheng }
327da14cebeSEric Cheng case MAC_FLOW_STATS: {
3280dc2366fSVenugopal Iyer uint64_t totibytes = 0;
3290dc2366fSVenugopal Iyer uint64_t totobytes = 0;
3300dc2366fSVenugopal Iyer mac_soft_ring_set_t *mac_srs;
3310dc2366fSVenugopal Iyer mac_rx_stats_t *mac_rx_stat;
3320dc2366fSVenugopal Iyer mac_tx_stats_t *mac_tx_stat;
3330dc2366fSVenugopal Iyer int i;
3340dc2366fSVenugopal Iyer
3350dc2366fSVenugopal Iyer for (i = 0; i < fe.fe_rx_srs_cnt; i++) {
3360dc2366fSVenugopal Iyer mac_srs = (mac_soft_ring_set_t *)(fe.fe_rx_srs[i]);
3370dc2366fSVenugopal Iyer mac_rx_stat = &mac_srs->srs_rx.sr_stat;
3380dc2366fSVenugopal Iyer totibytes += mac_rx_stat->mrs_intrbytes +
3390dc2366fSVenugopal Iyer mac_rx_stat->mrs_pollbytes +
3400dc2366fSVenugopal Iyer mac_rx_stat->mrs_lclbytes;
3410dc2366fSVenugopal Iyer }
3420dc2366fSVenugopal Iyer mac_srs = (mac_soft_ring_set_t *)(fe.fe_tx_srs);
3430dc2366fSVenugopal Iyer if (mac_srs != NULL) {
3440dc2366fSVenugopal Iyer mac_tx_stat = &mac_srs->srs_tx.st_stat;
3450dc2366fSVenugopal Iyer totobytes = mac_tx_stat->mts_obytes;
3460dc2366fSVenugopal Iyer }
347da14cebeSEric Cheng mdb_printf("%?p %-32s %16llu %16llu\n",
3480dc2366fSVenugopal Iyer addr, fe.fe_flow_name, totibytes, totobytes);
3490dc2366fSVenugopal Iyer
350da14cebeSEric Cheng break;
351da14cebeSEric Cheng }
352da14cebeSEric Cheng }
353da14cebeSEric Cheng return (DCMD_OK);
354da14cebeSEric Cheng }
355da14cebeSEric Cheng
356da14cebeSEric Cheng /*
357da14cebeSEric Cheng * Parse the arguments passed to the dcmd and print all or one flow_entry_t
358da14cebeSEric Cheng * structures
359da14cebeSEric Cheng */
360da14cebeSEric Cheng static int
mac_flow_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)361da14cebeSEric Cheng mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
362da14cebeSEric Cheng {
363da14cebeSEric Cheng uint_t args = 0;
364da14cebeSEric Cheng
365da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) {
366da14cebeSEric Cheng if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) {
367da14cebeSEric Cheng mdb_warn("failed to walk 'mac_flow'");
368da14cebeSEric Cheng return (DCMD_ERR);
369da14cebeSEric Cheng }
370da14cebeSEric Cheng return (DCMD_OK);
371da14cebeSEric Cheng }
372da14cebeSEric Cheng if ((mdb_getopts(argc, argv,
373da14cebeSEric Cheng 'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args,
374da14cebeSEric Cheng 'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args,
375da14cebeSEric Cheng 'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args,
376da14cebeSEric Cheng 'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args,
377da14cebeSEric Cheng 't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args,
378da14cebeSEric Cheng 's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args,
379*3f9e4ab7SRobert Mustacchi 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args,
380*3f9e4ab7SRobert Mustacchi NULL) != argc)) {
381da14cebeSEric Cheng return (DCMD_USAGE);
382da14cebeSEric Cheng }
383da14cebeSEric Cheng if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER)))
384da14cebeSEric Cheng return (DCMD_USAGE);
385da14cebeSEric Cheng /*
386da14cebeSEric Cheng * If no arguments was specified or just "-u" was specified then
387da14cebeSEric Cheng * we default to printing basic information of flows.
388da14cebeSEric Cheng */
389da14cebeSEric Cheng if (args == 0 || args == MAC_FLOW_USER)
390da14cebeSEric Cheng args |= MAC_FLOW_NONE;
391da14cebeSEric Cheng
392da14cebeSEric Cheng return (mac_flow_dcmd_output(addr, flags, args));
393da14cebeSEric Cheng }
394da14cebeSEric Cheng
395da14cebeSEric Cheng static void
mac_flow_help(void)396da14cebeSEric Cheng mac_flow_help(void)
397da14cebeSEric Cheng {
398da14cebeSEric Cheng mdb_printf("If an address is specified, then flow_entry structure at "
399da14cebeSEric Cheng "that address is printed. Otherwise all the flows in the system "
400da14cebeSEric Cheng "are printed.\n");
401da14cebeSEric Cheng mdb_printf("Options:\n"
402da14cebeSEric Cheng "\t-u\tdisplay user defined link & vnic flows.\n"
403da14cebeSEric Cheng "\t-a\tdisplay flow attributes\n"
404da14cebeSEric Cheng "\t-p\tdisplay flow properties\n"
405da14cebeSEric Cheng "\t-r\tdisplay rx side information\n"
406da14cebeSEric Cheng "\t-t\tdisplay tx side information\n"
407da14cebeSEric Cheng "\t-s\tdisplay flow statistics\n"
408da14cebeSEric Cheng "\t-m\tdisplay miscellaneous flow information\n\n");
409da14cebeSEric Cheng mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n");
410da14cebeSEric Cheng mdb_printf("Flow Types:\n");
411da14cebeSEric Cheng mdb_printf("\t P --> FLOW_PRIMARY_MAC\n");
412da14cebeSEric Cheng mdb_printf("\t V --> FLOW_VNIC_MAC\n");
413da14cebeSEric Cheng mdb_printf("\t M --> FLOW_MCAST\n");
414da14cebeSEric Cheng mdb_printf("\t O --> FLOW_OTHER\n");
415da14cebeSEric Cheng mdb_printf("\t U --> FLOW_USER\n");
416da14cebeSEric Cheng mdb_printf("\t NS --> FLOW_NO_STATS\n\n");
417da14cebeSEric Cheng mdb_printf("Flow Flags:\n");
418da14cebeSEric Cheng mdb_printf("\t Q --> FE_QUIESCE\n");
419da14cebeSEric Cheng mdb_printf("\t W --> FE_WAITER\n");
420da14cebeSEric Cheng mdb_printf("\t T --> FE_FLOW_TAB\n");
421da14cebeSEric Cheng mdb_printf("\t G --> FE_G_FLOW_HASH\n");
422da14cebeSEric Cheng mdb_printf("\t I --> FE_INCIPIENT\n");
423da14cebeSEric Cheng mdb_printf("\t C --> FE_CONDEMNED\n");
424da14cebeSEric Cheng mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n");
425da14cebeSEric Cheng mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n");
426da14cebeSEric Cheng }
427da14cebeSEric Cheng
428da14cebeSEric Cheng /*
429da14cebeSEric Cheng * called once by the debugger when the mac_flow walk begins.
430da14cebeSEric Cheng */
431da14cebeSEric Cheng static int
mac_flow_walk_init(mdb_walk_state_t * wsp)432da14cebeSEric Cheng mac_flow_walk_init(mdb_walk_state_t *wsp)
433da14cebeSEric Cheng {
434da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) {
435da14cebeSEric Cheng mdb_warn("failed to walk 'mac_flow'");
436da14cebeSEric Cheng return (WALK_ERR);
437da14cebeSEric Cheng }
438da14cebeSEric Cheng return (WALK_NEXT);
439da14cebeSEric Cheng }
440da14cebeSEric Cheng
441da14cebeSEric Cheng /*
442da14cebeSEric Cheng * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and
443da14cebeSEric Cheng * mac_ring_t.
444da14cebeSEric Cheng *
445da14cebeSEric Cheng * Steps through each flow_entry_t and calls the callback function. If the
446da14cebeSEric Cheng * user executed ::walk mac_flow, it just prints the address or if the user
447da14cebeSEric Cheng * executed ::mac_flow it displays selected fields of flow_entry_t structure
448da14cebeSEric Cheng * by calling "mac_flow_dcmd"
449da14cebeSEric Cheng */
450da14cebeSEric Cheng static int
mac_common_walk_step(mdb_walk_state_t * wsp)451da14cebeSEric Cheng mac_common_walk_step(mdb_walk_state_t *wsp)
452da14cebeSEric Cheng {
453da14cebeSEric Cheng int status;
454da14cebeSEric Cheng
455da14cebeSEric Cheng if (wsp->walk_addr == NULL)
456da14cebeSEric Cheng return (WALK_DONE);
457da14cebeSEric Cheng
458da14cebeSEric Cheng status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
459da14cebeSEric Cheng wsp->walk_cbdata);
460da14cebeSEric Cheng
461da14cebeSEric Cheng return (status);
462da14cebeSEric Cheng }
463da14cebeSEric Cheng
464da14cebeSEric Cheng static char *
mac_srs_txmode2str(mac_tx_srs_mode_t mode)465da14cebeSEric Cheng mac_srs_txmode2str(mac_tx_srs_mode_t mode)
466da14cebeSEric Cheng {
467da14cebeSEric Cheng switch (mode) {
468da14cebeSEric Cheng case SRS_TX_DEFAULT:
4692ae51e79SGirish Moodalbail return ("DEF");
470da14cebeSEric Cheng case SRS_TX_SERIALIZE:
4712ae51e79SGirish Moodalbail return ("SER");
472da14cebeSEric Cheng case SRS_TX_FANOUT:
4732ae51e79SGirish Moodalbail return ("FO");
474da14cebeSEric Cheng case SRS_TX_BW:
4752ae51e79SGirish Moodalbail return ("BW");
476da14cebeSEric Cheng case SRS_TX_BW_FANOUT:
4772ae51e79SGirish Moodalbail return ("BWFO");
4780dc2366fSVenugopal Iyer case SRS_TX_AGGR:
4790dc2366fSVenugopal Iyer return ("AG");
4800dc2366fSVenugopal Iyer case SRS_TX_BW_AGGR:
4810dc2366fSVenugopal Iyer return ("BWAG");
482da14cebeSEric Cheng }
483da14cebeSEric Cheng return ("--");
484da14cebeSEric Cheng }
485da14cebeSEric Cheng
486da14cebeSEric Cheng static void
mac_srs_help(void)487da14cebeSEric Cheng mac_srs_help(void)
488da14cebeSEric Cheng {
489da14cebeSEric Cheng mdb_printf("If an address is specified, then mac_soft_ring_set "
490da14cebeSEric Cheng "structure at that address is printed. Otherwise all the "
491da14cebeSEric Cheng "SRS in the system are printed.\n");
492da14cebeSEric Cheng mdb_printf("Options:\n"
493da14cebeSEric Cheng "\t-r\tdisplay recieve side SRS structures\n"
4942ae51e79SGirish Moodalbail "\t-t\tdisplay transmit side SRS structures\n"
4952ae51e79SGirish Moodalbail "\t-s\tdisplay statistics for RX or TX side\n"
4962ae51e79SGirish Moodalbail "\t-c\tdisplay CPU binding for RX or TX side\n"
4972ae51e79SGirish Moodalbail "\t-v\tverbose flag for CPU binding to list cpus\n"
4980dc2366fSVenugopal Iyer "\t-i\tdisplay mac_ring_t and interrupt information\n"
4992ae51e79SGirish Moodalbail "Note: use -r or -t (to specify RX or TX side respectively) along "
5002ae51e79SGirish Moodalbail "with -c or -s\n");
5012ae51e79SGirish Moodalbail mdb_printf("\n%<u>Interpreting TX Modes%</u>\n");
5022ae51e79SGirish Moodalbail mdb_printf("\t DEF --> Default\n");
5032ae51e79SGirish Moodalbail mdb_printf("\t SER --> Serialize\n");
5042ae51e79SGirish Moodalbail mdb_printf("\t FO --> Fanout\n");
5052ae51e79SGirish Moodalbail mdb_printf("\t BW --> Bandwidth\n");
5062ae51e79SGirish Moodalbail mdb_printf("\tBWFO --> Bandwidth Fanout\n");
5070dc2366fSVenugopal Iyer mdb_printf("\t AG --> Aggr\n");
5080dc2366fSVenugopal Iyer mdb_printf("\tBWAG --> Bandwidth Aggr\n");
5092ae51e79SGirish Moodalbail }
5102ae51e79SGirish Moodalbail
5112ae51e79SGirish Moodalbail /*
5122ae51e79SGirish Moodalbail * In verbose mode "::mac_srs -rcv or ::mac_srs -tcv", we print the CPUs
5132ae51e79SGirish Moodalbail * assigned to a link and CPUS assigned to the soft rings.
5142ae51e79SGirish Moodalbail * 'len' is used for formatting the output and represents the number of
5152ae51e79SGirish Moodalbail * spaces between CPU list and Fanout CPU list in the output.
5162ae51e79SGirish Moodalbail */
5172ae51e79SGirish Moodalbail static boolean_t
mac_srs_print_cpu(int * i,uint32_t cnt,uint32_t * cpu_list,int * len)5182ae51e79SGirish Moodalbail mac_srs_print_cpu(int *i, uint32_t cnt, uint32_t *cpu_list, int *len)
5192ae51e79SGirish Moodalbail {
5202ae51e79SGirish Moodalbail int num = 0;
5212ae51e79SGirish Moodalbail
5222ae51e79SGirish Moodalbail if (*i == 0)
5232ae51e79SGirish Moodalbail mdb_printf("(");
5242ae51e79SGirish Moodalbail else
5252ae51e79SGirish Moodalbail mdb_printf(" ");
5262ae51e79SGirish Moodalbail while (*i < cnt) {
5272ae51e79SGirish Moodalbail /* We print 6 CPU's at a time to keep display within 80 cols */
5282ae51e79SGirish Moodalbail if (((num + 1) % 7) == 0) {
5292ae51e79SGirish Moodalbail if (len != NULL)
5302ae51e79SGirish Moodalbail *len = 2;
5312ae51e79SGirish Moodalbail return (B_FALSE);
5322ae51e79SGirish Moodalbail }
5332ae51e79SGirish Moodalbail mdb_printf("%02x%c", cpu_list[*i], ((*i == cnt - 1)?')':','));
5342ae51e79SGirish Moodalbail ++*i;
5352ae51e79SGirish Moodalbail ++num;
5362ae51e79SGirish Moodalbail }
5372ae51e79SGirish Moodalbail if (len != NULL)
5382ae51e79SGirish Moodalbail *len = (7 - num) * 3;
5392ae51e79SGirish Moodalbail return (B_TRUE);
540da14cebeSEric Cheng }
541da14cebeSEric Cheng
542da14cebeSEric Cheng static int
mac_srs_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)543da14cebeSEric Cheng mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
544da14cebeSEric Cheng {
5452ae51e79SGirish Moodalbail uint_t args = MAC_SRS_NONE;
546da14cebeSEric Cheng mac_soft_ring_set_t srs;
5472ae51e79SGirish Moodalbail mac_client_impl_t mci;
548da14cebeSEric Cheng
549da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) {
550da14cebeSEric Cheng if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) {
551da14cebeSEric Cheng mdb_warn("failed to walk 'mac_srs'");
552da14cebeSEric Cheng return (DCMD_ERR);
553da14cebeSEric Cheng }
554da14cebeSEric Cheng return (DCMD_OK);
555da14cebeSEric Cheng }
5562ae51e79SGirish Moodalbail if (mdb_getopts(argc, argv,
557da14cebeSEric Cheng 'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args,
5582ae51e79SGirish Moodalbail 't', MDB_OPT_SETBITS, MAC_SRS_TX, &args,
5592ae51e79SGirish Moodalbail 'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args,
5602ae51e79SGirish Moodalbail 'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args,
5610dc2366fSVenugopal Iyer 'i', MDB_OPT_SETBITS, MAC_SRS_INTR, &args,
562*3f9e4ab7SRobert Mustacchi 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args,
563*3f9e4ab7SRobert Mustacchi NULL) != argc) {
564da14cebeSEric Cheng return (DCMD_USAGE);
565da14cebeSEric Cheng }
5662ae51e79SGirish Moodalbail
5672ae51e79SGirish Moodalbail if (argc > 2)
568da14cebeSEric Cheng return (DCMD_USAGE);
569da14cebeSEric Cheng
570da14cebeSEric Cheng if (mdb_vread(&srs, sizeof (srs), addr) == -1) {
571da14cebeSEric Cheng mdb_warn("failed to read struct mac_soft_ring_set_s at %p",
572da14cebeSEric Cheng addr);
573da14cebeSEric Cheng return (DCMD_ERR);
574da14cebeSEric Cheng }
5752ae51e79SGirish Moodalbail if (mdb_vread(&mci, sizeof (mci), (uintptr_t)srs.srs_mcip) == -1) {
5762ae51e79SGirish Moodalbail mdb_warn("failed to read struct mac_client_impl_t at %p "
5772ae51e79SGirish Moodalbail "for SRS %p", srs.srs_mcip, addr);
5782ae51e79SGirish Moodalbail return (DCMD_ERR);
5792ae51e79SGirish Moodalbail }
580da14cebeSEric Cheng
581da14cebeSEric Cheng switch (args) {
582da14cebeSEric Cheng case MAC_SRS_RX: {
583da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) {
584fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %-8s %-8s %8s "
585fcff38ebSGirish Moodalbail "%8s %3s\n",
5862ae51e79SGirish Moodalbail "", "", "", "", "MBLK",
5872ae51e79SGirish Moodalbail "Q", "SR");
588fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %-8s %-8s %8s "
589fcff38ebSGirish Moodalbail "%8s %3s%</u>\n",
5902ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "STATE", "TYPE", "CNT",
5912ae51e79SGirish Moodalbail "BYTES", "CNT");
592da14cebeSEric Cheng }
593da14cebeSEric Cheng if (srs.srs_type & SRST_TX)
594da14cebeSEric Cheng return (DCMD_OK);
5952ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %08x %08x "
596fcff38ebSGirish Moodalbail "%8d %8d %3d\n",
5972ae51e79SGirish Moodalbail addr, mci.mci_name, srs.srs_state, srs.srs_type,
5982ae51e79SGirish Moodalbail srs.srs_count, srs.srs_size, srs.srs_soft_ring_count);
599da14cebeSEric Cheng break;
600da14cebeSEric Cheng }
601da14cebeSEric Cheng case MAC_SRS_TX: {
602da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) {
6032ae51e79SGirish Moodalbail mdb_printf("%?s %-16s %-4s %-8s "
604fcff38ebSGirish Moodalbail "%-8s %8s %8s %3s\n",
6052ae51e79SGirish Moodalbail "", "", "TX", "",
6062ae51e79SGirish Moodalbail "", "MBLK", "Q", "SR");
6072ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-16s %-4s %-8s "
608fcff38ebSGirish Moodalbail "%-8s %8s %8s %3s%</u>\n",
6092ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "MODE", "STATE",
6102ae51e79SGirish Moodalbail "TYPE", "CNT", "BYTES", "CNT");
611da14cebeSEric Cheng }
612da14cebeSEric Cheng if (!(srs.srs_type & SRST_TX))
613da14cebeSEric Cheng return (DCMD_OK);
614da14cebeSEric Cheng
6152ae51e79SGirish Moodalbail mdb_printf("%?p %-16s %-4s "
616fcff38ebSGirish Moodalbail "%08x %08x %8d %8d %3d\n",
6172ae51e79SGirish Moodalbail addr, mci.mci_name, mac_srs_txmode2str(srs.srs_tx.st_mode),
6182ae51e79SGirish Moodalbail srs.srs_state, srs.srs_type, srs.srs_count, srs.srs_size,
6190dc2366fSVenugopal Iyer srs.srs_tx_ring_count);
620da14cebeSEric Cheng break;
621da14cebeSEric Cheng }
6222ae51e79SGirish Moodalbail case MAC_SRS_RXCPU: {
6232ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu;
6242ae51e79SGirish Moodalbail
625da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) {
6262ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-4s %-4s "
6272ae51e79SGirish Moodalbail "%-6s %-4s %-7s\n",
6282ae51e79SGirish Moodalbail "", "", "NUM", "POLL",
6292ae51e79SGirish Moodalbail "WORKER", "INTR", "FANOUT");
6302ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %-4s %-4s "
6312ae51e79SGirish Moodalbail "%-6s %-4s %-7s%</u>\n",
6322ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "CPUS", "CPU",
6332ae51e79SGirish Moodalbail "CPU", "CPU", "CPU_CNT");
634da14cebeSEric Cheng }
6352ae51e79SGirish Moodalbail if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))
6362ae51e79SGirish Moodalbail return (DCMD_OK);
6372ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-4d %-4d "
6382ae51e79SGirish Moodalbail "%-6d %-4d %-7d\n",
6390dc2366fSVenugopal Iyer addr, mci.mci_name, mc.mc_ncpus, mc.mc_rx_pollid,
6400dc2366fSVenugopal Iyer mc.mc_rx_workerid, mc.mc_rx_intr_cpu, mc.mc_rx_fanout_cnt);
6412ae51e79SGirish Moodalbail break;
6422ae51e79SGirish Moodalbail
6432ae51e79SGirish Moodalbail }
6442ae51e79SGirish Moodalbail case MAC_SRS_TXCPU: {
6452ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu;
6460dc2366fSVenugopal Iyer mac_soft_ring_t *s_ringp, s_ring;
6470dc2366fSVenugopal Iyer boolean_t first = B_TRUE;
6480dc2366fSVenugopal Iyer int i;
6492ae51e79SGirish Moodalbail
6502ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) {
6510dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?s %8s %8s %8s\n",
6520dc2366fSVenugopal Iyer "", "", "SOFT", "WORKER", "INTR", "RETARGETED");
6530dc2366fSVenugopal Iyer mdb_printf("%<u>%?s %-12s %?s %8s %8s %8s%</u>\n",
6540dc2366fSVenugopal Iyer "ADDR", "LINK_NAME", "RING", "CPU", "CPU", "CPU");
6552ae51e79SGirish Moodalbail }
6560dc2366fSVenugopal Iyer if (!(srs.srs_type & SRST_TX))
6572ae51e79SGirish Moodalbail return (DCMD_OK);
6580dc2366fSVenugopal Iyer
6590dc2366fSVenugopal Iyer mdb_printf("%?p %-12s ", addr, mci.mci_name);
6600dc2366fSVenugopal Iyer
6610dc2366fSVenugopal Iyer /*
6620dc2366fSVenugopal Iyer * Case of no soft rings, print the info from
6630dc2366fSVenugopal Iyer * mac_srs_tx_t.
6640dc2366fSVenugopal Iyer */
6650dc2366fSVenugopal Iyer if (srs.srs_tx_ring_count == 0) {
6660dc2366fSVenugopal Iyer mdb_printf("%?p %8d %8d %8d\n",
6670dc2366fSVenugopal Iyer 0, mc.mc_tx_fanout_cpus[0],
6680dc2366fSVenugopal Iyer mc.mc_tx_intr_cpu[0],
6690dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[0]);
6700dc2366fSVenugopal Iyer break;
6710dc2366fSVenugopal Iyer }
6720dc2366fSVenugopal Iyer
6730dc2366fSVenugopal Iyer for (s_ringp = srs.srs_soft_ring_head, i = 0; s_ringp != NULL;
6740dc2366fSVenugopal Iyer s_ringp = s_ring.s_ring_next, i++) {
6750dc2366fSVenugopal Iyer (void) mdb_vread(&s_ring, sizeof (s_ring),
6760dc2366fSVenugopal Iyer (uintptr_t)s_ringp);
6770dc2366fSVenugopal Iyer if (first) {
6780dc2366fSVenugopal Iyer mdb_printf("%?p %8d %8d %8d\n",
6790dc2366fSVenugopal Iyer s_ringp, mc.mc_tx_fanout_cpus[i],
6800dc2366fSVenugopal Iyer mc.mc_tx_intr_cpu[i],
6810dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[i]);
6820dc2366fSVenugopal Iyer first = B_FALSE;
6830dc2366fSVenugopal Iyer continue;
6840dc2366fSVenugopal Iyer }
6850dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?p %8d %8d %8d\n",
6860dc2366fSVenugopal Iyer "", "", s_ringp, mc.mc_tx_fanout_cpus[i],
6870dc2366fSVenugopal Iyer mc.mc_tx_intr_cpu[i], mc.mc_tx_retargeted_cpu[i]);
6880dc2366fSVenugopal Iyer }
6890dc2366fSVenugopal Iyer break;
6900dc2366fSVenugopal Iyer }
6910dc2366fSVenugopal Iyer case MAC_SRS_TXINTR: {
6920dc2366fSVenugopal Iyer mac_cpus_t mc = srs.srs_cpu;
6930dc2366fSVenugopal Iyer mac_soft_ring_t *s_ringp, s_ring;
6940dc2366fSVenugopal Iyer mac_ring_t *m_ringp, m_ring;
6950dc2366fSVenugopal Iyer boolean_t first = B_TRUE;
6960dc2366fSVenugopal Iyer int i;
6970dc2366fSVenugopal Iyer
6980dc2366fSVenugopal Iyer if (DCMD_HDRSPEC(flags)) {
6990dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?s %8s %?s %6s %6s\n",
7000dc2366fSVenugopal Iyer "", "", "SOFT", "WORKER", "MAC", "", "INTR");
7010dc2366fSVenugopal Iyer mdb_printf("%<u>%?s %-12s %?s %8s %?s %6s %6s%</u>\n",
7020dc2366fSVenugopal Iyer "ADDR", "LINK_NAME", "RING", "CPU", "RING",
7030dc2366fSVenugopal Iyer "SHARED", "CPU");
7040dc2366fSVenugopal Iyer }
7050dc2366fSVenugopal Iyer if (!(srs.srs_type & SRST_TX))
7060dc2366fSVenugopal Iyer return (DCMD_OK);
7070dc2366fSVenugopal Iyer
7080dc2366fSVenugopal Iyer mdb_printf("%?p %-12s ", addr, mci.mci_name);
7090dc2366fSVenugopal Iyer
7100dc2366fSVenugopal Iyer /*
7110dc2366fSVenugopal Iyer * Case of no soft rings, print the info from
7120dc2366fSVenugopal Iyer * mac_srs_tx_t.
7130dc2366fSVenugopal Iyer */
7140dc2366fSVenugopal Iyer if (srs.srs_tx_ring_count == 0) {
7150dc2366fSVenugopal Iyer m_ringp = srs.srs_tx.st_arg2;
7160dc2366fSVenugopal Iyer if (m_ringp != NULL) {
7170dc2366fSVenugopal Iyer (void) mdb_vread(&m_ring, sizeof (m_ring),
7180dc2366fSVenugopal Iyer (uintptr_t)m_ringp);
7190dc2366fSVenugopal Iyer mdb_printf("%?p %8d %?p %6d %6d\n",
7200dc2366fSVenugopal Iyer 0, mc.mc_tx_fanout_cpus[0], m_ringp,
7210dc2366fSVenugopal Iyer m_ring.mr_info.mri_intr.mi_ddi_shared,
7220dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[0]);
7230dc2366fSVenugopal Iyer } else {
7240dc2366fSVenugopal Iyer mdb_printf("%?p %8d %?p %6d %6d\n",
7250dc2366fSVenugopal Iyer 0, mc.mc_tx_fanout_cpus[0], 0,
7260dc2366fSVenugopal Iyer 0, mc.mc_tx_retargeted_cpu[0]);
7270dc2366fSVenugopal Iyer }
7280dc2366fSVenugopal Iyer break;
7290dc2366fSVenugopal Iyer }
7300dc2366fSVenugopal Iyer
7310dc2366fSVenugopal Iyer for (s_ringp = srs.srs_soft_ring_head, i = 0; s_ringp != NULL;
7320dc2366fSVenugopal Iyer s_ringp = s_ring.s_ring_next, i++) {
7330dc2366fSVenugopal Iyer (void) mdb_vread(&s_ring, sizeof (s_ring),
7340dc2366fSVenugopal Iyer (uintptr_t)s_ringp);
7350dc2366fSVenugopal Iyer m_ringp = s_ring.s_ring_tx_arg2;
7360dc2366fSVenugopal Iyer (void) mdb_vread(&m_ring, sizeof (m_ring),
7370dc2366fSVenugopal Iyer (uintptr_t)m_ringp);
7380dc2366fSVenugopal Iyer if (first) {
7390dc2366fSVenugopal Iyer mdb_printf("%?p %8d %?p %6d %6d\n",
7400dc2366fSVenugopal Iyer s_ringp, mc.mc_tx_fanout_cpus[i],
7410dc2366fSVenugopal Iyer m_ringp,
7420dc2366fSVenugopal Iyer m_ring.mr_info.mri_intr.mi_ddi_shared,
7430dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[i]);
7440dc2366fSVenugopal Iyer first = B_FALSE;
7450dc2366fSVenugopal Iyer continue;
7460dc2366fSVenugopal Iyer }
7470dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?p %8d %?p %6d %6d\n",
7480dc2366fSVenugopal Iyer "", "", s_ringp, mc.mc_tx_fanout_cpus[i],
7490dc2366fSVenugopal Iyer m_ringp, m_ring.mr_info.mri_intr.mi_ddi_shared,
7500dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[i]);
7510dc2366fSVenugopal Iyer }
7520dc2366fSVenugopal Iyer break;
7530dc2366fSVenugopal Iyer }
7540dc2366fSVenugopal Iyer case MAC_SRS_RXINTR: {
7550dc2366fSVenugopal Iyer mac_cpus_t mc = srs.srs_cpu;
7560dc2366fSVenugopal Iyer mac_ring_t *m_ringp, m_ring;
7570dc2366fSVenugopal Iyer
7580dc2366fSVenugopal Iyer if (DCMD_HDRSPEC(flags)) {
7590dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?s %8s %6s %6s\n",
7600dc2366fSVenugopal Iyer "", "", "MAC", "", "POLL", "INTR");
7610dc2366fSVenugopal Iyer mdb_printf("%<u>%?s %-12s %?s %8s %6s %6s%</u>\n",
7620dc2366fSVenugopal Iyer "ADDR", "LINK_NAME", "RING", "SHARED", "CPU",
7630dc2366fSVenugopal Iyer "CPU");
7640dc2366fSVenugopal Iyer }
7650dc2366fSVenugopal Iyer if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))
7660dc2366fSVenugopal Iyer return (DCMD_OK);
7670dc2366fSVenugopal Iyer
7680dc2366fSVenugopal Iyer mdb_printf("%?p %-12s ", addr, mci.mci_name);
7690dc2366fSVenugopal Iyer
7700dc2366fSVenugopal Iyer m_ringp = srs.srs_ring;
7710dc2366fSVenugopal Iyer if (m_ringp != NULL) {
7720dc2366fSVenugopal Iyer (void) mdb_vread(&m_ring, sizeof (m_ring),
7730dc2366fSVenugopal Iyer (uintptr_t)m_ringp);
7740dc2366fSVenugopal Iyer mdb_printf("%?p %8d %6d %6d\n",
7750dc2366fSVenugopal Iyer m_ringp, m_ring.mr_info.mri_intr.mi_ddi_shared,
7760dc2366fSVenugopal Iyer mc.mc_rx_pollid, mc.mc_rx_intr_cpu);
7770dc2366fSVenugopal Iyer } else {
7780dc2366fSVenugopal Iyer mdb_printf("%?p %8d %6d %6d\n",
7790dc2366fSVenugopal Iyer 0, 0, mc.mc_rx_pollid, mc.mc_rx_intr_cpu);
7800dc2366fSVenugopal Iyer }
781da14cebeSEric Cheng break;
782da14cebeSEric Cheng }
7832ae51e79SGirish Moodalbail case MAC_SRS_RXCPUVERBOSE:
7842ae51e79SGirish Moodalbail case MAC_SRS_TXCPUVERBOSE: {
7852ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu;
7862ae51e79SGirish Moodalbail int cpu_index = 0, fanout_index = 0, len = 0;
7872ae51e79SGirish Moodalbail boolean_t cpu_done = B_FALSE, fanout_done = B_FALSE;
7882ae51e79SGirish Moodalbail
7892ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) {
7902ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-20s %-20s\n",
7912ae51e79SGirish Moodalbail "", "", "CPU_COUNT", "FANOUT_CPU_COUNT");
7922ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s "
7932ae51e79SGirish Moodalbail "%-20s %-20s%</u>\n",
7942ae51e79SGirish Moodalbail "ADDR", "LINK_NAME",
7952ae51e79SGirish Moodalbail "(CPU_LIST)", "(CPU_LIST)");
7962ae51e79SGirish Moodalbail }
7972ae51e79SGirish Moodalbail if (((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) ||
7982ae51e79SGirish Moodalbail ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)))
7992ae51e79SGirish Moodalbail return (DCMD_OK);
8002ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-20d %-20d\n", addr, mci.mci_name,
8010dc2366fSVenugopal Iyer mc.mc_ncpus, mc.mc_rx_fanout_cnt);
8020dc2366fSVenugopal Iyer if (mc.mc_ncpus == 0 && mc.mc_rx_fanout_cnt == 0)
8032ae51e79SGirish Moodalbail break;
8042ae51e79SGirish Moodalbail /* print all cpus and cpus for soft rings */
8052ae51e79SGirish Moodalbail while (!cpu_done || !fanout_done) {
8062ae51e79SGirish Moodalbail boolean_t old_value = cpu_done;
8072ae51e79SGirish Moodalbail
8082ae51e79SGirish Moodalbail if (!cpu_done) {
8092ae51e79SGirish Moodalbail mdb_printf("%?s %20s ", "", "");
8102ae51e79SGirish Moodalbail cpu_done = mac_srs_print_cpu(&cpu_index,
8112ae51e79SGirish Moodalbail mc.mc_ncpus, mc.mc_cpus, &len);
8122ae51e79SGirish Moodalbail }
8132ae51e79SGirish Moodalbail if (!fanout_done) {
8142ae51e79SGirish Moodalbail if (old_value)
8152ae51e79SGirish Moodalbail mdb_printf("%?s %-40s", "", "");
8162ae51e79SGirish Moodalbail else
8172ae51e79SGirish Moodalbail mdb_printf("%*s", len, "");
8182ae51e79SGirish Moodalbail fanout_done = mac_srs_print_cpu(&fanout_index,
8190dc2366fSVenugopal Iyer mc.mc_rx_fanout_cnt,
8200dc2366fSVenugopal Iyer mc.mc_rx_fanout_cpus, NULL);
8212ae51e79SGirish Moodalbail }
8222ae51e79SGirish Moodalbail mdb_printf("\n");
8232ae51e79SGirish Moodalbail }
8242ae51e79SGirish Moodalbail break;
8252ae51e79SGirish Moodalbail }
8262ae51e79SGirish Moodalbail case MAC_SRS_RXSTAT: {
8270dc2366fSVenugopal Iyer mac_rx_stats_t *mac_rx_stat = &srs.srs_rx.sr_stat;
8282ae51e79SGirish Moodalbail
8292ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) {
830fcff38ebSGirish Moodalbail mdb_printf("%?s %-16s %8s %8s "
831fcff38ebSGirish Moodalbail "%8s %8s %8s\n",
8322ae51e79SGirish Moodalbail "", "", "INTR", "POLL",
8332ae51e79SGirish Moodalbail "CHAIN", "CHAIN", "CHAIN");
834fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-16s %8s %8s "
835fcff38ebSGirish Moodalbail "%8s %8s %8s%</u>\n",
8362ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "COUNT", "COUNT",
8372ae51e79SGirish Moodalbail "<10", "10-50", ">50");
8382ae51e79SGirish Moodalbail }
8392ae51e79SGirish Moodalbail if (srs.srs_type & SRST_TX)
8402ae51e79SGirish Moodalbail return (DCMD_OK);
841fcff38ebSGirish Moodalbail mdb_printf("%?p %-16s %8d "
842fcff38ebSGirish Moodalbail "%8d %8d "
843fcff38ebSGirish Moodalbail "%8d %8d\n",
8440dc2366fSVenugopal Iyer addr, mci.mci_name, mac_rx_stat->mrs_intrcnt,
8450dc2366fSVenugopal Iyer mac_rx_stat->mrs_pollcnt, mac_rx_stat->mrs_chaincntundr10,
8460dc2366fSVenugopal Iyer mac_rx_stat->mrs_chaincnt10to50,
8470dc2366fSVenugopal Iyer mac_rx_stat->mrs_chaincntover50);
8482ae51e79SGirish Moodalbail break;
8492ae51e79SGirish Moodalbail }
8502ae51e79SGirish Moodalbail case MAC_SRS_TXSTAT: {
8510dc2366fSVenugopal Iyer mac_tx_stats_t *mac_tx_stat = &srs.srs_tx.st_stat;
852fcff38ebSGirish Moodalbail mac_soft_ring_t *s_ringp, s_ring;
853fcff38ebSGirish Moodalbail boolean_t first = B_TRUE;
8542ae51e79SGirish Moodalbail
8552ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) {
856fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %?s %8s %8s %8s\n",
857fcff38ebSGirish Moodalbail "", "", "SOFT", "DROP", "BLOCK", "UNBLOCK");
858fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %?s %8s %8s %8s%</u>\n",
859fcff38ebSGirish Moodalbail "ADDR", "LINK_NAME", "RING", "COUNT", "COUNT",
860fcff38ebSGirish Moodalbail "COUNT");
8612ae51e79SGirish Moodalbail }
8622ae51e79SGirish Moodalbail if (!(srs.srs_type & SRST_TX))
8632ae51e79SGirish Moodalbail return (DCMD_OK);
8642ae51e79SGirish Moodalbail
865fcff38ebSGirish Moodalbail mdb_printf("%?p %-20s ", addr, mci.mci_name);
866fcff38ebSGirish Moodalbail
867fcff38ebSGirish Moodalbail /*
868fcff38ebSGirish Moodalbail * Case of no soft rings, print the info from
869fcff38ebSGirish Moodalbail * mac_srs_tx_t.
870fcff38ebSGirish Moodalbail */
8710dc2366fSVenugopal Iyer if (srs.srs_tx_ring_count == 0) {
872fcff38ebSGirish Moodalbail mdb_printf("%?p %8d %8d %8d\n",
8730dc2366fSVenugopal Iyer 0, mac_tx_stat->mts_sdrops,
8740dc2366fSVenugopal Iyer mac_tx_stat->mts_blockcnt,
8750dc2366fSVenugopal Iyer mac_tx_stat->mts_unblockcnt);
876fcff38ebSGirish Moodalbail break;
877fcff38ebSGirish Moodalbail }
878fcff38ebSGirish Moodalbail
879fcff38ebSGirish Moodalbail for (s_ringp = srs.srs_soft_ring_head; s_ringp != NULL;
880fcff38ebSGirish Moodalbail s_ringp = s_ring.s_ring_next) {
881fcff38ebSGirish Moodalbail (void) mdb_vread(&s_ring, sizeof (s_ring),
882fcff38ebSGirish Moodalbail (uintptr_t)s_ringp);
8830dc2366fSVenugopal Iyer mac_tx_stat = &s_ring.s_st_stat;
884fcff38ebSGirish Moodalbail if (first) {
885fcff38ebSGirish Moodalbail mdb_printf("%?p %8d %8d %8d\n",
8860dc2366fSVenugopal Iyer s_ringp, mac_tx_stat->mts_sdrops,
8870dc2366fSVenugopal Iyer mac_tx_stat->mts_blockcnt,
8880dc2366fSVenugopal Iyer mac_tx_stat->mts_unblockcnt);
889fcff38ebSGirish Moodalbail first = B_FALSE;
890fcff38ebSGirish Moodalbail continue;
891fcff38ebSGirish Moodalbail }
892fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %?p %8d %8d %8d\n",
8930dc2366fSVenugopal Iyer "", "", s_ringp, mac_tx_stat->mts_sdrops,
8940dc2366fSVenugopal Iyer mac_tx_stat->mts_blockcnt,
8950dc2366fSVenugopal Iyer mac_tx_stat->mts_unblockcnt);
896fcff38ebSGirish Moodalbail }
8972ae51e79SGirish Moodalbail break;
8982ae51e79SGirish Moodalbail }
8992ae51e79SGirish Moodalbail case MAC_SRS_NONE: {
9002ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) {
9012ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %?s %?s %-3s%</u>\n",
9022ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "FLENT", "HW RING", "DIR");
9032ae51e79SGirish Moodalbail }
9042ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %?p %?p "
9052ae51e79SGirish Moodalbail "%-3s ",
9062ae51e79SGirish Moodalbail addr, mci.mci_name, srs.srs_flent, srs.srs_ring,
9072ae51e79SGirish Moodalbail (srs.srs_type & SRST_TX ? "TX" : "RX"));
9082ae51e79SGirish Moodalbail break;
9092ae51e79SGirish Moodalbail }
9102ae51e79SGirish Moodalbail default:
9112ae51e79SGirish Moodalbail return (DCMD_USAGE);
912da14cebeSEric Cheng }
913da14cebeSEric Cheng return (DCMD_OK);
914da14cebeSEric Cheng }
915da14cebeSEric Cheng
916da14cebeSEric Cheng static int
mac_srs_walk_init(mdb_walk_state_t * wsp)917da14cebeSEric Cheng mac_srs_walk_init(mdb_walk_state_t *wsp)
918da14cebeSEric Cheng {
919da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) {
920da14cebeSEric Cheng mdb_warn("failed to walk 'mac_srs'");
921da14cebeSEric Cheng return (WALK_ERR);
922da14cebeSEric Cheng }
923da14cebeSEric Cheng return (WALK_NEXT);
924da14cebeSEric Cheng }
925da14cebeSEric Cheng
926da14cebeSEric Cheng static char *
mac_ring_state2str(mac_ring_state_t state)927da14cebeSEric Cheng mac_ring_state2str(mac_ring_state_t state)
928da14cebeSEric Cheng {
929da14cebeSEric Cheng switch (state) {
930da14cebeSEric Cheng case MR_FREE:
931da14cebeSEric Cheng return ("free");
932da14cebeSEric Cheng case MR_NEWLY_ADDED:
933da14cebeSEric Cheng return ("new");
934da14cebeSEric Cheng case MR_INUSE:
935da14cebeSEric Cheng return ("inuse");
936da14cebeSEric Cheng }
937da14cebeSEric Cheng return ("--");
938da14cebeSEric Cheng }
939da14cebeSEric Cheng
940da14cebeSEric Cheng static char *
mac_ring_classify2str(mac_classify_type_t classify)941da14cebeSEric Cheng mac_ring_classify2str(mac_classify_type_t classify)
942da14cebeSEric Cheng {
943da14cebeSEric Cheng switch (classify) {
944da14cebeSEric Cheng case MAC_NO_CLASSIFIER:
945da14cebeSEric Cheng return ("no");
946da14cebeSEric Cheng case MAC_SW_CLASSIFIER:
947da14cebeSEric Cheng return ("sw");
948da14cebeSEric Cheng case MAC_HW_CLASSIFIER:
949da14cebeSEric Cheng return ("hw");
950da14cebeSEric Cheng }
951da14cebeSEric Cheng return ("--");
952da14cebeSEric Cheng }
953da14cebeSEric Cheng
954da14cebeSEric Cheng static int
mac_ring_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)955da14cebeSEric Cheng mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
956da14cebeSEric Cheng {
957da14cebeSEric Cheng mac_ring_t ring;
958da14cebeSEric Cheng mac_group_t group;
959da14cebeSEric Cheng flow_entry_t flent;
960da14cebeSEric Cheng mac_soft_ring_set_t srs;
961da14cebeSEric Cheng
962da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) {
963da14cebeSEric Cheng if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) {
964da14cebeSEric Cheng mdb_warn("failed to walk 'mac_ring'");
965da14cebeSEric Cheng return (DCMD_ERR);
966da14cebeSEric Cheng }
967da14cebeSEric Cheng return (DCMD_OK);
968da14cebeSEric Cheng }
969da14cebeSEric Cheng if (mdb_vread(&ring, sizeof (ring), addr) == -1) {
970da14cebeSEric Cheng mdb_warn("failed to read struct mac_ring_s at %p", addr);
971da14cebeSEric Cheng return (DCMD_ERR);
972da14cebeSEric Cheng }
973da14cebeSEric Cheng bzero(&flent, sizeof (flent));
974da14cebeSEric Cheng if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) {
975da14cebeSEric Cheng (void) mdb_vread(&flent, sizeof (flent),
976da14cebeSEric Cheng (uintptr_t)srs.srs_flent);
977da14cebeSEric Cheng }
978da14cebeSEric Cheng (void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh);
979da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) {
980da14cebeSEric Cheng mdb_printf("%<u>%?s %4s %5s %4s %?s "
981da14cebeSEric Cheng "%5s %?s %?s %s %</u>\n",
982da14cebeSEric Cheng "ADDR", "TYPE", "STATE", "FLAG", "GROUP",
983da14cebeSEric Cheng "CLASS", "MIP", "SRS", "FLOW NAME");
984da14cebeSEric Cheng }
985da14cebeSEric Cheng mdb_printf("%?p %-4s "
986da14cebeSEric Cheng "%5s %04x "
987da14cebeSEric Cheng "%?p %-5s "
988da14cebeSEric Cheng "%?p %?p %s\n",
989da14cebeSEric Cheng addr, ((ring.mr_type == 1)? "RX" : "TX"),
990da14cebeSEric Cheng mac_ring_state2str(ring.mr_state), ring.mr_flag,
991da14cebeSEric Cheng ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type),
992da14cebeSEric Cheng group.mrg_mh, ring.mr_srs, flent.fe_flow_name);
993da14cebeSEric Cheng return (DCMD_OK);
994da14cebeSEric Cheng }
995da14cebeSEric Cheng
996da14cebeSEric Cheng static int
mac_ring_walk_init(mdb_walk_state_t * wsp)997da14cebeSEric Cheng mac_ring_walk_init(mdb_walk_state_t *wsp)
998da14cebeSEric Cheng {
999da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) {
1000da14cebeSEric Cheng mdb_warn("failed to walk `mac_ring`");
1001da14cebeSEric Cheng return (WALK_ERR);
1002da14cebeSEric Cheng }
1003da14cebeSEric Cheng return (WALK_NEXT);
1004da14cebeSEric Cheng }
1005da14cebeSEric Cheng
1006da14cebeSEric Cheng static void
mac_ring_help(void)1007da14cebeSEric Cheng mac_ring_help(void)
1008da14cebeSEric Cheng {
1009da14cebeSEric Cheng mdb_printf("If an address is specified, then mac_ring_t "
1010da14cebeSEric Cheng "structure at that address is printed. Otherwise all the "
1011da14cebeSEric Cheng "hardware rings in the system are printed.\n");
1012da14cebeSEric Cheng }
1013da14cebeSEric Cheng
1014*3f9e4ab7SRobert Mustacchi /*
1015*3f9e4ab7SRobert Mustacchi * To walk groups we have to have our own somewhat-complicated state machine. We
1016*3f9e4ab7SRobert Mustacchi * basically start by walking the mac_impl_t walker as all groups are stored off
1017*3f9e4ab7SRobert Mustacchi * of the various mac_impl_t in the system. The tx and rx rings are kept
1018*3f9e4ab7SRobert Mustacchi * separately. So we'll need to walk through all the rx rings and then all of
1019*3f9e4ab7SRobert Mustacchi * the tx rings.
1020*3f9e4ab7SRobert Mustacchi */
1021*3f9e4ab7SRobert Mustacchi static int
mac_group_walk_init(mdb_walk_state_t * wsp)1022*3f9e4ab7SRobert Mustacchi mac_group_walk_init(mdb_walk_state_t *wsp)
1023*3f9e4ab7SRobert Mustacchi {
1024*3f9e4ab7SRobert Mustacchi int ret;
1025*3f9e4ab7SRobert Mustacchi
1026*3f9e4ab7SRobert Mustacchi if (wsp->walk_addr != NULL) {
1027*3f9e4ab7SRobert Mustacchi mdb_warn("non-global walks are not supported\n");
1028*3f9e4ab7SRobert Mustacchi return (WALK_ERR);
1029*3f9e4ab7SRobert Mustacchi }
1030*3f9e4ab7SRobert Mustacchi
1031*3f9e4ab7SRobert Mustacchi if ((ret = mdb_layered_walk(LAYERED_WALKER_FOR_GROUP, wsp)) == -1) {
1032*3f9e4ab7SRobert Mustacchi mdb_warn("couldn't walk '%s'", LAYERED_WALKER_FOR_GROUP);
1033*3f9e4ab7SRobert Mustacchi return (ret);
1034*3f9e4ab7SRobert Mustacchi }
1035*3f9e4ab7SRobert Mustacchi
1036*3f9e4ab7SRobert Mustacchi return (WALK_NEXT);
1037*3f9e4ab7SRobert Mustacchi }
1038*3f9e4ab7SRobert Mustacchi
1039*3f9e4ab7SRobert Mustacchi static int
mac_group_walk_step(mdb_walk_state_t * wsp)1040*3f9e4ab7SRobert Mustacchi mac_group_walk_step(mdb_walk_state_t *wsp)
1041*3f9e4ab7SRobert Mustacchi {
1042*3f9e4ab7SRobert Mustacchi int ret;
1043*3f9e4ab7SRobert Mustacchi mac_impl_t mi;
1044*3f9e4ab7SRobert Mustacchi mac_group_t mg;
1045*3f9e4ab7SRobert Mustacchi uintptr_t mgp;
1046*3f9e4ab7SRobert Mustacchi
1047*3f9e4ab7SRobert Mustacchi /*
1048*3f9e4ab7SRobert Mustacchi * Nothing to do if we can't find the layer above us. But the kmem
1049*3f9e4ab7SRobert Mustacchi * walkers are a bit unsporting, they don't actually read in the data
1050*3f9e4ab7SRobert Mustacchi * for us.
1051*3f9e4ab7SRobert Mustacchi */
1052*3f9e4ab7SRobert Mustacchi if (wsp->walk_addr == NULL)
1053*3f9e4ab7SRobert Mustacchi return (WALK_DONE);
1054*3f9e4ab7SRobert Mustacchi
1055*3f9e4ab7SRobert Mustacchi if (mdb_vread(&mi, sizeof (mac_impl_t), wsp->walk_addr) == -1) {
1056*3f9e4ab7SRobert Mustacchi mdb_warn("failed to read mac_impl_t at %p", wsp->walk_addr);
1057*3f9e4ab7SRobert Mustacchi return (DCMD_ERR);
1058*3f9e4ab7SRobert Mustacchi }
1059*3f9e4ab7SRobert Mustacchi
1060*3f9e4ab7SRobert Mustacchi /*
1061*3f9e4ab7SRobert Mustacchi * First go for rx groups, then tx groups.
1062*3f9e4ab7SRobert Mustacchi */
1063*3f9e4ab7SRobert Mustacchi mgp = (uintptr_t)mi.mi_rx_groups;
1064*3f9e4ab7SRobert Mustacchi while (mgp != NULL) {
1065*3f9e4ab7SRobert Mustacchi if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) {
1066*3f9e4ab7SRobert Mustacchi mdb_warn("failed to read mac_group_t at %p", mgp);
1067*3f9e4ab7SRobert Mustacchi return (WALK_ERR);
1068*3f9e4ab7SRobert Mustacchi }
1069*3f9e4ab7SRobert Mustacchi
1070*3f9e4ab7SRobert Mustacchi ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata);
1071*3f9e4ab7SRobert Mustacchi if (ret != WALK_NEXT)
1072*3f9e4ab7SRobert Mustacchi return (ret);
1073*3f9e4ab7SRobert Mustacchi mgp = (uintptr_t)mg.mrg_next;
1074*3f9e4ab7SRobert Mustacchi }
1075*3f9e4ab7SRobert Mustacchi
1076*3f9e4ab7SRobert Mustacchi mgp = (uintptr_t)mi.mi_tx_groups;
1077*3f9e4ab7SRobert Mustacchi while (mgp != NULL) {
1078*3f9e4ab7SRobert Mustacchi if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) {
1079*3f9e4ab7SRobert Mustacchi mdb_warn("failed to read mac_group_t at %p", mgp);
1080*3f9e4ab7SRobert Mustacchi return (WALK_ERR);
1081*3f9e4ab7SRobert Mustacchi }
1082*3f9e4ab7SRobert Mustacchi
1083*3f9e4ab7SRobert Mustacchi ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata);
1084*3f9e4ab7SRobert Mustacchi if (ret != WALK_NEXT)
1085*3f9e4ab7SRobert Mustacchi return (ret);
1086*3f9e4ab7SRobert Mustacchi mgp = (uintptr_t)mg.mrg_next;
1087*3f9e4ab7SRobert Mustacchi }
1088*3f9e4ab7SRobert Mustacchi
1089*3f9e4ab7SRobert Mustacchi return (WALK_NEXT);
1090*3f9e4ab7SRobert Mustacchi }
1091*3f9e4ab7SRobert Mustacchi
1092*3f9e4ab7SRobert Mustacchi static int
mac_group_count_clients(mac_group_t * mgp)1093*3f9e4ab7SRobert Mustacchi mac_group_count_clients(mac_group_t *mgp)
1094*3f9e4ab7SRobert Mustacchi {
1095*3f9e4ab7SRobert Mustacchi int clients = 0;
1096*3f9e4ab7SRobert Mustacchi uintptr_t mcp = (uintptr_t)mgp->mrg_clients;
1097*3f9e4ab7SRobert Mustacchi
1098*3f9e4ab7SRobert Mustacchi while (mcp != NULL) {
1099*3f9e4ab7SRobert Mustacchi mac_grp_client_t c;
1100*3f9e4ab7SRobert Mustacchi
1101*3f9e4ab7SRobert Mustacchi if (mdb_vread(&c, sizeof (c), mcp) == -1) {
1102*3f9e4ab7SRobert Mustacchi mdb_warn("failed to read mac_grp_client_t at %p", mcp);
1103*3f9e4ab7SRobert Mustacchi return (-1);
1104*3f9e4ab7SRobert Mustacchi }
1105*3f9e4ab7SRobert Mustacchi clients++;
1106*3f9e4ab7SRobert Mustacchi mcp = (uintptr_t)c.mgc_next;
1107*3f9e4ab7SRobert Mustacchi }
1108*3f9e4ab7SRobert Mustacchi
1109*3f9e4ab7SRobert Mustacchi return (clients);
1110*3f9e4ab7SRobert Mustacchi }
1111*3f9e4ab7SRobert Mustacchi
1112*3f9e4ab7SRobert Mustacchi static const char *
mac_group_type(mac_group_t * mgp)1113*3f9e4ab7SRobert Mustacchi mac_group_type(mac_group_t *mgp)
1114*3f9e4ab7SRobert Mustacchi {
1115*3f9e4ab7SRobert Mustacchi const char *ret;
1116*3f9e4ab7SRobert Mustacchi
1117*3f9e4ab7SRobert Mustacchi switch (mgp->mrg_type) {
1118*3f9e4ab7SRobert Mustacchi case MAC_RING_TYPE_RX:
1119*3f9e4ab7SRobert Mustacchi ret = "RECEIVE";
1120*3f9e4ab7SRobert Mustacchi break;
1121*3f9e4ab7SRobert Mustacchi case MAC_RING_TYPE_TX:
1122*3f9e4ab7SRobert Mustacchi ret = "TRANSMIT";
1123*3f9e4ab7SRobert Mustacchi break;
1124*3f9e4ab7SRobert Mustacchi default:
1125*3f9e4ab7SRobert Mustacchi ret = "UNKNOWN";
1126*3f9e4ab7SRobert Mustacchi break;
1127*3f9e4ab7SRobert Mustacchi }
1128*3f9e4ab7SRobert Mustacchi
1129*3f9e4ab7SRobert Mustacchi return (ret);
1130*3f9e4ab7SRobert Mustacchi }
1131*3f9e4ab7SRobert Mustacchi
1132*3f9e4ab7SRobert Mustacchi static const char *
mac_group_state(mac_group_t * mgp)1133*3f9e4ab7SRobert Mustacchi mac_group_state(mac_group_t *mgp)
1134*3f9e4ab7SRobert Mustacchi {
1135*3f9e4ab7SRobert Mustacchi const char *ret;
1136*3f9e4ab7SRobert Mustacchi
1137*3f9e4ab7SRobert Mustacchi switch (mgp->mrg_state) {
1138*3f9e4ab7SRobert Mustacchi case MAC_GROUP_STATE_UNINIT:
1139*3f9e4ab7SRobert Mustacchi ret = "UNINT";
1140*3f9e4ab7SRobert Mustacchi break;
1141*3f9e4ab7SRobert Mustacchi case MAC_GROUP_STATE_REGISTERED:
1142*3f9e4ab7SRobert Mustacchi ret = "REGISTERED";
1143*3f9e4ab7SRobert Mustacchi break;
1144*3f9e4ab7SRobert Mustacchi case MAC_GROUP_STATE_RESERVED:
1145*3f9e4ab7SRobert Mustacchi ret = "RESERVED";
1146*3f9e4ab7SRobert Mustacchi break;
1147*3f9e4ab7SRobert Mustacchi case MAC_GROUP_STATE_SHARED:
1148*3f9e4ab7SRobert Mustacchi ret = "SHARED";
1149*3f9e4ab7SRobert Mustacchi break;
1150*3f9e4ab7SRobert Mustacchi default:
1151*3f9e4ab7SRobert Mustacchi ret = "UNKNOWN";
1152*3f9e4ab7SRobert Mustacchi break;
1153*3f9e4ab7SRobert Mustacchi }
1154*3f9e4ab7SRobert Mustacchi
1155*3f9e4ab7SRobert Mustacchi return (ret);
1156*3f9e4ab7SRobert Mustacchi }
1157*3f9e4ab7SRobert Mustacchi
1158*3f9e4ab7SRobert Mustacchi static int
mac_group_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)1159*3f9e4ab7SRobert Mustacchi mac_group_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1160*3f9e4ab7SRobert Mustacchi {
1161*3f9e4ab7SRobert Mustacchi uint_t args = MAC_SRS_NONE;
1162*3f9e4ab7SRobert Mustacchi mac_group_t mg;
1163*3f9e4ab7SRobert Mustacchi int clients;
1164*3f9e4ab7SRobert Mustacchi
1165*3f9e4ab7SRobert Mustacchi if (!(flags & DCMD_ADDRSPEC)) {
1166*3f9e4ab7SRobert Mustacchi if (mdb_walk_dcmd("mac_group", "mac_group", argc, argv) == -1) {
1167*3f9e4ab7SRobert Mustacchi mdb_warn("failed to walk 'mac_group'");
1168*3f9e4ab7SRobert Mustacchi return (DCMD_ERR);
1169*3f9e4ab7SRobert Mustacchi }
1170*3f9e4ab7SRobert Mustacchi
1171*3f9e4ab7SRobert Mustacchi return (DCMD_OK);
1172*3f9e4ab7SRobert Mustacchi }
1173*3f9e4ab7SRobert Mustacchi
1174*3f9e4ab7SRobert Mustacchi if (mdb_getopts(argc, argv,
1175*3f9e4ab7SRobert Mustacchi 'r', MDB_OPT_SETBITS, MAC_GROUP_RX, &args,
1176*3f9e4ab7SRobert Mustacchi 't', MDB_OPT_SETBITS, MAC_GROUP_TX, &args,
1177*3f9e4ab7SRobert Mustacchi 'u', MDB_OPT_SETBITS, MAC_GROUP_UNINIT, &args,
1178*3f9e4ab7SRobert Mustacchi NULL) != argc)
1179*3f9e4ab7SRobert Mustacchi return (DCMD_USAGE);
1180*3f9e4ab7SRobert Mustacchi
1181*3f9e4ab7SRobert Mustacchi if (mdb_vread(&mg, sizeof (mac_group_t), addr) == -1) {
1182*3f9e4ab7SRobert Mustacchi mdb_warn("failed to read mac_group_t at %p", addr);
1183*3f9e4ab7SRobert Mustacchi return (DCMD_ERR);
1184*3f9e4ab7SRobert Mustacchi }
1185*3f9e4ab7SRobert Mustacchi
1186*3f9e4ab7SRobert Mustacchi if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
1187*3f9e4ab7SRobert Mustacchi mdb_printf("%<u>%-?s %-8s %-10s %6s %8s %-?s%</u>\n",
1188*3f9e4ab7SRobert Mustacchi "ADDR", "TYPE", "STATE", "NRINGS", "NCLIENTS", "RINGS");
1189*3f9e4ab7SRobert Mustacchi }
1190*3f9e4ab7SRobert Mustacchi
1191*3f9e4ab7SRobert Mustacchi if ((args & MAC_GROUP_RX) != 0 && mg.mrg_type != MAC_RING_TYPE_RX)
1192*3f9e4ab7SRobert Mustacchi return (DCMD_OK);
1193*3f9e4ab7SRobert Mustacchi if ((args & MAC_GROUP_TX) != 0 && mg.mrg_type != MAC_RING_TYPE_TX)
1194*3f9e4ab7SRobert Mustacchi return (DCMD_OK);
1195*3f9e4ab7SRobert Mustacchi
1196*3f9e4ab7SRobert Mustacchi /*
1197*3f9e4ab7SRobert Mustacchi * By default, don't show uninitialized groups. They're not very
1198*3f9e4ab7SRobert Mustacchi * interesting. They have no rings and no clients.
1199*3f9e4ab7SRobert Mustacchi */
1200*3f9e4ab7SRobert Mustacchi if (mg.mrg_state == MAC_GROUP_STATE_UNINIT &&
1201*3f9e4ab7SRobert Mustacchi (args & MAC_GROUP_UNINIT) == 0)
1202*3f9e4ab7SRobert Mustacchi return (DCMD_OK);
1203*3f9e4ab7SRobert Mustacchi
1204*3f9e4ab7SRobert Mustacchi if (flags & DCMD_PIPE_OUT) {
1205*3f9e4ab7SRobert Mustacchi mdb_printf("%lr\n", addr);
1206*3f9e4ab7SRobert Mustacchi return (DCMD_OK);
1207*3f9e4ab7SRobert Mustacchi }
1208*3f9e4ab7SRobert Mustacchi
1209*3f9e4ab7SRobert Mustacchi clients = mac_group_count_clients(&mg);
1210*3f9e4ab7SRobert Mustacchi mdb_printf("%?p %-8s %-10s %6d %8d %?p\n", addr, mac_group_type(&mg),
1211*3f9e4ab7SRobert Mustacchi mac_group_state(&mg), mg.mrg_cur_count, clients, mg.mrg_rings);
1212*3f9e4ab7SRobert Mustacchi
1213*3f9e4ab7SRobert Mustacchi return (DCMD_OK);
1214*3f9e4ab7SRobert Mustacchi }
1215*3f9e4ab7SRobert Mustacchi
1216da14cebeSEric Cheng /* Supported dee-commands */
1217da14cebeSEric Cheng static const mdb_dcmd_t dcmds[] = {
1218da14cebeSEric Cheng {"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures",
1219da14cebeSEric Cheng mac_flow_dcmd, mac_flow_help},
1220*3f9e4ab7SRobert Mustacchi {"mac_group", "?[-rtu]", "display MAC Ring Groups", mac_group_dcmd,
1221*3f9e4ab7SRobert Mustacchi NULL },
12220dc2366fSVenugopal Iyer {"mac_srs", "?[ -r[i|s|c[v]] | -t[i|s|c[v]] ]",
12230dc2366fSVenugopal Iyer "display MAC Soft Ring Set" " structures", mac_srs_dcmd,
12240dc2366fSVenugopal Iyer mac_srs_help},
1225da14cebeSEric Cheng {"mac_ring", "?", "display MAC ring (hardware) structures",
1226da14cebeSEric Cheng mac_ring_dcmd, mac_ring_help},
1227da14cebeSEric Cheng { NULL }
1228da14cebeSEric Cheng };
1229da14cebeSEric Cheng
1230da14cebeSEric Cheng /* Supported walkers */
1231da14cebeSEric Cheng static const mdb_walker_t walkers[] = {
1232da14cebeSEric Cheng {"mac_flow", "walk list of flow entry structures", mac_flow_walk_init,
1233da14cebeSEric Cheng mac_common_walk_step, NULL, NULL},
1234*3f9e4ab7SRobert Mustacchi {"mac_group", "walk list of ring group structures", mac_group_walk_init,
1235*3f9e4ab7SRobert Mustacchi mac_group_walk_step, NULL, NULL},
1236da14cebeSEric Cheng {"mac_srs", "walk list of mac soft ring set structures",
1237da14cebeSEric Cheng mac_srs_walk_init, mac_common_walk_step, NULL, NULL},
1238da14cebeSEric Cheng {"mac_ring", "walk list of mac ring structures", mac_ring_walk_init,
1239da14cebeSEric Cheng mac_common_walk_step, NULL, NULL},
1240da14cebeSEric Cheng { NULL }
1241da14cebeSEric Cheng };
1242da14cebeSEric Cheng
1243da14cebeSEric Cheng static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
1244da14cebeSEric Cheng
1245da14cebeSEric Cheng const mdb_modinfo_t *
_mdb_init(void)1246da14cebeSEric Cheng _mdb_init(void)
1247da14cebeSEric Cheng {
1248da14cebeSEric Cheng return (&modinfo);
1249da14cebeSEric Cheng }
1250