Print this page
6394 ::mac_flow -s segfaults
Reviewed by: Jason King <jason.brian.king@gmail.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/common/modules/mac/mac.c
+++ new/usr/src/cmd/mdb/common/modules/mac/mac.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/mdb_modapi.h>
27 27 #include <sys/types.h>
28 28 #include <inet/ip.h>
29 29 #include <inet/ip6.h>
30 30
31 31 #include <sys/mac.h>
32 32 #include <sys/mac_provider.h>
33 33 #include <sys/mac_client.h>
34 34 #include <sys/mac_client_impl.h>
35 35 #include <sys/mac_flow_impl.h>
36 36 #include <sys/mac_soft_ring.h>
37 37 #include <sys/mac_stat.h>
38 38
39 39 #define STRSIZE 64
40 40 #define MAC_RX_SRS_SIZE (MAX_RINGS_PER_GROUP * sizeof (uintptr_t))
41 41
42 42 #define LAYERED_WALKER_FOR_FLOW "flow_entry_cache"
43 43 #define LAYERED_WALKER_FOR_SRS "mac_srs_cache"
44 44 #define LAYERED_WALKER_FOR_RING "mac_ring_cache"
45 45 #define LAYERED_WALKER_FOR_GROUP "mac_impl_cache"
46 46
47 47 /* arguments passed to mac_flow dee-command */
48 48 #define MAC_FLOW_NONE 0x01
49 49 #define MAC_FLOW_ATTR 0x02
50 50 #define MAC_FLOW_PROP 0x04
51 51 #define MAC_FLOW_RX 0x08
52 52 #define MAC_FLOW_TX 0x10
53 53 #define MAC_FLOW_USER 0x20
54 54 #define MAC_FLOW_STATS 0x40
55 55 #define MAC_FLOW_MISC 0x80
56 56
57 57 /* arguments passed to mac_srs dee-command */
58 58 #define MAC_SRS_NONE 0x00
59 59 #define MAC_SRS_RX 0x01
60 60 #define MAC_SRS_TX 0x02
61 61 #define MAC_SRS_STAT 0x04
62 62 #define MAC_SRS_CPU 0x08
63 63 #define MAC_SRS_VERBOSE 0x10
64 64 #define MAC_SRS_INTR 0x20
65 65 #define MAC_SRS_RXSTAT (MAC_SRS_RX|MAC_SRS_STAT)
66 66 #define MAC_SRS_TXSTAT (MAC_SRS_TX|MAC_SRS_STAT)
67 67 #define MAC_SRS_RXCPU (MAC_SRS_RX|MAC_SRS_CPU)
68 68 #define MAC_SRS_TXCPU (MAC_SRS_TX|MAC_SRS_CPU)
69 69 #define MAC_SRS_RXCPUVERBOSE (MAC_SRS_RXCPU|MAC_SRS_VERBOSE)
70 70 #define MAC_SRS_TXCPUVERBOSE (MAC_SRS_TXCPU|MAC_SRS_VERBOSE)
71 71 #define MAC_SRS_RXINTR (MAC_SRS_RX|MAC_SRS_INTR)
72 72 #define MAC_SRS_TXINTR (MAC_SRS_TX|MAC_SRS_INTR)
73 73
74 74 /* arguments passed to mac_group dcmd */
75 75 #define MAC_GROUP_NONE 0x00
76 76 #define MAC_GROUP_RX 0x01
77 77 #define MAC_GROUP_TX 0x02
78 78 #define MAC_GROUP_UNINIT 0x04
79 79
80 80 static char *
81 81 mac_flow_proto2str(uint8_t protocol)
82 82 {
83 83 switch (protocol) {
84 84 case IPPROTO_TCP:
85 85 return ("tcp");
86 86 case IPPROTO_UDP:
87 87 return ("udp");
88 88 case IPPROTO_SCTP:
89 89 return ("sctp");
90 90 case IPPROTO_ICMP:
91 91 return ("icmp");
92 92 case IPPROTO_ICMPV6:
93 93 return ("icmpv6");
94 94 default:
95 95 return ("--");
96 96 }
97 97 }
98 98
99 99 static char *
100 100 mac_flow_priority2str(mac_priority_level_t prio)
101 101 {
102 102 switch (prio) {
103 103 case MPL_LOW:
104 104 return ("low");
105 105 case MPL_MEDIUM:
106 106 return ("medium");
107 107 case MPL_HIGH:
108 108 return ("high");
109 109 case MPL_RESET:
110 110 return ("reset");
111 111 default:
112 112 return ("--");
113 113 }
114 114 }
115 115
116 116 /*
117 117 * Convert bandwidth in bps to a string in Mbps.
118 118 */
119 119 static char *
120 120 mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len)
121 121 {
122 122 int kbps, mbps;
123 123
124 124 kbps = (bw % 1000000)/1000;
125 125 mbps = bw/1000000;
126 126 if ((mbps == 0) && (kbps != 0))
127 127 mdb_snprintf(buf, len, "0.%03u", kbps);
128 128 else
129 129 mdb_snprintf(buf, len, "%5u", mbps);
130 130 return (buf);
131 131 }
132 132
133 133 static void
134 134 mac_flow_print_header(uint_t args)
135 135 {
136 136 switch (args) {
137 137 case MAC_FLOW_NONE:
138 138 mdb_printf("%?s %-20s %4s %?s %?s %-16s\n",
139 139 "", "", "LINK", "", "", "MIP");
140 140 mdb_printf("%<u>%?s %-20s %4s %?s %?s %-16s%</u>\n",
141 141 "ADDR", "FLOW NAME", "ID", "MCIP", "MIP", "NAME");
142 142 break;
143 143 case MAC_FLOW_ATTR:
144 144 mdb_printf("%<u>%?s %-32s %-7s %6s "
145 145 "%-9s %s%</u>\n",
146 146 "ADDR", "FLOW NAME", "PROTO", "PORT",
147 147 "DSFLD:MSK", "IPADDR");
148 148 break;
149 149 case MAC_FLOW_PROP:
150 150 mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n",
151 151 "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY");
152 152 break;
153 153 case MAC_FLOW_MISC:
154 154 mdb_printf("%<u>%?s %-24s %10s %10s "
155 155 "%20s %4s%</u>\n",
156 156 "ADDR", "FLOW NAME", "TYPE", "FLAGS",
157 157 "MATCH_FN", "ZONE");
158 158 break;
159 159 case MAC_FLOW_RX:
160 160 mdb_printf("%?s %-24s %3s %s\n", "", "", "SRS", "RX");
161 161 mdb_printf("%<u>%?s %-24s %3s %s%</u>\n",
162 162 "ADDR", "FLOW NAME", "CNT", "SRS");
163 163 break;
164 164 case MAC_FLOW_TX:
165 165 mdb_printf("%<u>%?s %-32s %?s %</u>\n",
166 166 "ADDR", "FLOW NAME", "TX_SRS");
167 167 break;
168 168 case MAC_FLOW_STATS:
169 169 mdb_printf("%<u>%?s %-32s %16s %16s%</u>\n",
170 170 "ADDR", "FLOW NAME", "RBYTES", "OBYTES");
171 171 break;
172 172 }
173 173 }
174 174
175 175 /*
176 176 * Display selected fields of the flow_entry_t structure
177 177 */
178 178 static int
179 179 mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args)
180 180 {
181 181 static const mdb_bitmask_t flow_type_bits[] = {
182 182 {"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC},
183 183 {"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC},
184 184 {"M", FLOW_MCAST, FLOW_MCAST},
185 185 {"O", FLOW_OTHER, FLOW_OTHER},
186 186 {"U", FLOW_USER, FLOW_USER},
187 187 {"V", FLOW_VNIC, FLOW_VNIC},
188 188 {"NS", FLOW_NO_STATS, FLOW_NO_STATS},
189 189 { NULL, 0, 0 }
190 190 };
191 191 #define FLOW_MAX_TYPE (sizeof (flow_type_bits) / sizeof (mdb_bitmask_t))
192 192
193 193 static const mdb_bitmask_t flow_flag_bits[] = {
194 194 {"Q", FE_QUIESCE, FE_QUIESCE},
195 195 {"W", FE_WAITER, FE_WAITER},
196 196 {"T", FE_FLOW_TAB, FE_FLOW_TAB},
197 197 {"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH},
198 198 {"I", FE_INCIPIENT, FE_INCIPIENT},
199 199 {"C", FE_CONDEMNED, FE_CONDEMNED},
200 200 {"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH},
201 201 {"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH},
202 202 { NULL, 0, 0 }
203 203 };
204 204 #define FLOW_MAX_FLAGS (sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t))
205 205 flow_entry_t fe;
206 206 mac_client_impl_t mcip;
207 207 mac_impl_t mip;
208 208
209 209 if (mdb_vread(&fe, sizeof (fe), addr) == -1) {
210 210 mdb_warn("failed to read struct flow_entry_s at %p", addr);
211 211 return (DCMD_ERR);
212 212 }
213 213 if (args & MAC_FLOW_USER) {
214 214 args &= ~MAC_FLOW_USER;
215 215 if (fe.fe_type & FLOW_MCAST) {
216 216 if (DCMD_HDRSPEC(flags))
217 217 mac_flow_print_header(args);
218 218 return (DCMD_OK);
219 219 }
220 220 }
221 221 if (DCMD_HDRSPEC(flags))
222 222 mac_flow_print_header(args);
223 223 bzero(&mcip, sizeof (mcip));
224 224 bzero(&mip, sizeof (mip));
225 225 if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip),
226 226 (uintptr_t)fe.fe_mcip) == sizeof (mcip)) {
227 227 (void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip);
228 228 }
229 229 switch (args) {
230 230 case MAC_FLOW_NONE: {
231 231 mdb_printf("%?p %-20s %4d %?p "
232 232 "%?p %-16s\n",
233 233 addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip,
234 234 mcip.mci_mip, mip.mi_name);
235 235 break;
236 236 }
237 237 case MAC_FLOW_ATTR: {
238 238 struct in_addr in4;
239 239 uintptr_t desc_addr;
240 240 flow_desc_t fdesc;
241 241
242 242 desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc);
243 243 if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) {
244 244 mdb_warn("failed to read struct flow_description at %p",
245 245 desc_addr);
246 246 return (DCMD_ERR);
247 247 }
248 248 mdb_printf("%?p %-32s "
249 249 "%-7s %6d "
250 250 "%4d:%-4d ",
251 251 addr, fe.fe_flow_name,
252 252 mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port,
253 253 fdesc.fd_dsfield, fdesc.fd_dsfield_mask);
254 254 if (fdesc.fd_ipversion == IPV4_VERSION) {
255 255 IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4);
256 256 mdb_printf("%I", in4.s_addr);
257 257 } else if (fdesc.fd_ipversion == IPV6_VERSION) {
258 258 mdb_printf("%N", &fdesc.fd_local_addr);
259 259 } else {
260 260 mdb_printf("%s", "--");
261 261 }
262 262 mdb_printf("\n");
263 263 break;
264 264 }
265 265 case MAC_FLOW_PROP: {
266 266 uintptr_t prop_addr;
267 267 char bwstr[STRSIZE];
268 268 mac_resource_props_t fprop;
269 269
270 270 prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props);
271 271 if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) {
272 272 mdb_warn("failed to read struct mac_resoource_props "
273 273 "at %p", prop_addr);
274 274 return (DCMD_ERR);
275 275 }
276 276 mdb_printf("%?p %-32s "
277 277 "%8s %9s\n",
278 278 addr, fe.fe_flow_name,
279 279 mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE),
280 280 mac_flow_priority2str(fprop.mrp_priority));
281 281 break;
282 282 }
283 283 case MAC_FLOW_MISC: {
284 284 char flow_flags[2 * FLOW_MAX_FLAGS];
285 285 char flow_type[2 * FLOW_MAX_TYPE];
286 286 GElf_Sym sym;
287 287 char func_name[MDB_SYM_NAMLEN] = "";
288 288 uintptr_t func, match_addr;
289 289
290 290 match_addr = addr + OFFSETOF(flow_entry_t, fe_match);
291 291 (void) mdb_vread(&func, sizeof (func), match_addr);
292 292 (void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name,
293 293 MDB_SYM_NAMLEN, &sym);
294 294 mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb",
295 295 fe.fe_flags, flow_flag_bits);
296 296 mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb",
297 297 fe.fe_type, flow_type_bits);
298 298 mdb_printf("%?p %-24s %10s %10s %20s\n",
299 299 addr, fe.fe_flow_name, flow_type, flow_flags, func_name);
300 300 break;
301 301 }
302 302 case MAC_FLOW_RX: {
303 303 uintptr_t rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0};
304 304 int i;
305 305
306 306 rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs);
307 307 (void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr);
308 308 mdb_printf("%?p %-24s %3d ",
309 309 addr, fe.fe_flow_name, fe.fe_rx_srs_cnt);
310 310 for (i = 0; i < MAX_RINGS_PER_GROUP; i++) {
311 311 if (rx_srs[i] == 0)
312 312 continue;
313 313 mdb_printf("%p ", rx_srs[i]);
314 314 }
315 315 mdb_printf("\n");
316 316 break;
317 317 }
318 318 case MAC_FLOW_TX: {
319 319 uintptr_t tx_srs = 0, txaddr;
320 320
↓ open down ↓ |
320 lines elided |
↑ open up ↑ |
321 321 txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs);
322 322 (void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr);
323 323 mdb_printf("%?p %-32s %?p\n",
324 324 addr, fe.fe_flow_name, fe.fe_tx_srs);
325 325 break;
326 326 }
327 327 case MAC_FLOW_STATS: {
328 328 uint64_t totibytes = 0;
329 329 uint64_t totobytes = 0;
330 330 mac_soft_ring_set_t *mac_srs;
331 - mac_rx_stats_t *mac_rx_stat;
332 - mac_tx_stats_t *mac_tx_stat;
331 + mac_rx_stats_t mac_rx_stat;
332 + mac_tx_stats_t mac_tx_stat;
333 333 int i;
334 334
335 + /*
336 + * Sum bytes for all Rx SRS.
337 + */
335 338 for (i = 0; i < fe.fe_rx_srs_cnt; i++) {
336 339 mac_srs = (mac_soft_ring_set_t *)(fe.fe_rx_srs[i]);
337 - mac_rx_stat = &mac_srs->srs_rx.sr_stat;
338 - totibytes += mac_rx_stat->mrs_intrbytes +
339 - mac_rx_stat->mrs_pollbytes +
340 - mac_rx_stat->mrs_lclbytes;
340 + if (mdb_vread(&mac_rx_stat, sizeof (mac_rx_stats_t),
341 + (uintptr_t)&mac_srs->srs_rx.sr_stat) == -1) {
342 + mdb_warn("failed to read mac_rx_stats_t at %p",
343 + &mac_srs->srs_rx.sr_stat);
344 + return (DCMD_ERR);
345 + }
346 +
347 + totibytes += mac_rx_stat.mrs_intrbytes +
348 + mac_rx_stat.mrs_pollbytes +
349 + mac_rx_stat.mrs_lclbytes;
341 350 }
351 +
352 + /*
353 + * Sum bytes for Tx SRS.
354 + */
342 355 mac_srs = (mac_soft_ring_set_t *)(fe.fe_tx_srs);
343 356 if (mac_srs != NULL) {
344 - mac_tx_stat = &mac_srs->srs_tx.st_stat;
345 - totobytes = mac_tx_stat->mts_obytes;
357 + if (mdb_vread(&mac_tx_stat, sizeof (mac_tx_stats_t),
358 + (uintptr_t)&mac_srs->srs_tx.st_stat) == -1) {
359 + mdb_warn("failed to read max_tx_stats_t at %p",
360 + &mac_srs->srs_tx.st_stat);
361 + return (DCMD_ERR);
362 + }
363 +
364 + totobytes = mac_tx_stat.mts_obytes;
346 365 }
366 +
347 367 mdb_printf("%?p %-32s %16llu %16llu\n",
348 368 addr, fe.fe_flow_name, totibytes, totobytes);
349 369
350 370 break;
351 371 }
352 372 }
353 373 return (DCMD_OK);
354 374 }
355 375
356 376 /*
357 377 * Parse the arguments passed to the dcmd and print all or one flow_entry_t
358 378 * structures
359 379 */
360 380 static int
361 381 mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
362 382 {
363 383 uint_t args = 0;
364 384
365 385 if (!(flags & DCMD_ADDRSPEC)) {
366 386 if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) {
367 387 mdb_warn("failed to walk 'mac_flow'");
368 388 return (DCMD_ERR);
369 389 }
370 390 return (DCMD_OK);
371 391 }
372 392 if ((mdb_getopts(argc, argv,
373 393 'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args,
374 394 'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args,
375 395 'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args,
376 396 'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args,
377 397 't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args,
378 398 's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args,
379 399 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args,
380 400 NULL) != argc)) {
381 401 return (DCMD_USAGE);
382 402 }
383 403 if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER)))
384 404 return (DCMD_USAGE);
385 405 /*
386 406 * If no arguments was specified or just "-u" was specified then
387 407 * we default to printing basic information of flows.
388 408 */
389 409 if (args == 0 || args == MAC_FLOW_USER)
390 410 args |= MAC_FLOW_NONE;
391 411
392 412 return (mac_flow_dcmd_output(addr, flags, args));
393 413 }
394 414
395 415 static void
396 416 mac_flow_help(void)
397 417 {
398 418 mdb_printf("If an address is specified, then flow_entry structure at "
399 419 "that address is printed. Otherwise all the flows in the system "
400 420 "are printed.\n");
401 421 mdb_printf("Options:\n"
402 422 "\t-u\tdisplay user defined link & vnic flows.\n"
403 423 "\t-a\tdisplay flow attributes\n"
404 424 "\t-p\tdisplay flow properties\n"
405 425 "\t-r\tdisplay rx side information\n"
406 426 "\t-t\tdisplay tx side information\n"
407 427 "\t-s\tdisplay flow statistics\n"
408 428 "\t-m\tdisplay miscellaneous flow information\n\n");
409 429 mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n");
410 430 mdb_printf("Flow Types:\n");
411 431 mdb_printf("\t P --> FLOW_PRIMARY_MAC\n");
412 432 mdb_printf("\t V --> FLOW_VNIC_MAC\n");
413 433 mdb_printf("\t M --> FLOW_MCAST\n");
414 434 mdb_printf("\t O --> FLOW_OTHER\n");
415 435 mdb_printf("\t U --> FLOW_USER\n");
416 436 mdb_printf("\t NS --> FLOW_NO_STATS\n\n");
417 437 mdb_printf("Flow Flags:\n");
418 438 mdb_printf("\t Q --> FE_QUIESCE\n");
419 439 mdb_printf("\t W --> FE_WAITER\n");
420 440 mdb_printf("\t T --> FE_FLOW_TAB\n");
421 441 mdb_printf("\t G --> FE_G_FLOW_HASH\n");
422 442 mdb_printf("\t I --> FE_INCIPIENT\n");
423 443 mdb_printf("\t C --> FE_CONDEMNED\n");
424 444 mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n");
425 445 mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n");
426 446 }
427 447
428 448 /*
429 449 * called once by the debugger when the mac_flow walk begins.
430 450 */
431 451 static int
432 452 mac_flow_walk_init(mdb_walk_state_t *wsp)
433 453 {
434 454 if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) {
435 455 mdb_warn("failed to walk 'mac_flow'");
436 456 return (WALK_ERR);
437 457 }
438 458 return (WALK_NEXT);
439 459 }
440 460
441 461 /*
442 462 * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and
443 463 * mac_ring_t.
444 464 *
445 465 * Steps through each flow_entry_t and calls the callback function. If the
446 466 * user executed ::walk mac_flow, it just prints the address or if the user
447 467 * executed ::mac_flow it displays selected fields of flow_entry_t structure
448 468 * by calling "mac_flow_dcmd"
449 469 */
450 470 static int
451 471 mac_common_walk_step(mdb_walk_state_t *wsp)
452 472 {
453 473 int status;
454 474
455 475 if (wsp->walk_addr == NULL)
456 476 return (WALK_DONE);
457 477
458 478 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
459 479 wsp->walk_cbdata);
460 480
461 481 return (status);
462 482 }
463 483
464 484 static char *
465 485 mac_srs_txmode2str(mac_tx_srs_mode_t mode)
466 486 {
467 487 switch (mode) {
468 488 case SRS_TX_DEFAULT:
469 489 return ("DEF");
470 490 case SRS_TX_SERIALIZE:
471 491 return ("SER");
472 492 case SRS_TX_FANOUT:
473 493 return ("FO");
474 494 case SRS_TX_BW:
475 495 return ("BW");
476 496 case SRS_TX_BW_FANOUT:
477 497 return ("BWFO");
478 498 case SRS_TX_AGGR:
479 499 return ("AG");
480 500 case SRS_TX_BW_AGGR:
481 501 return ("BWAG");
482 502 }
483 503 return ("--");
484 504 }
485 505
486 506 static void
487 507 mac_srs_help(void)
488 508 {
489 509 mdb_printf("If an address is specified, then mac_soft_ring_set "
490 510 "structure at that address is printed. Otherwise all the "
491 511 "SRS in the system are printed.\n");
492 512 mdb_printf("Options:\n"
493 513 "\t-r\tdisplay recieve side SRS structures\n"
494 514 "\t-t\tdisplay transmit side SRS structures\n"
495 515 "\t-s\tdisplay statistics for RX or TX side\n"
496 516 "\t-c\tdisplay CPU binding for RX or TX side\n"
497 517 "\t-v\tverbose flag for CPU binding to list cpus\n"
498 518 "\t-i\tdisplay mac_ring_t and interrupt information\n"
499 519 "Note: use -r or -t (to specify RX or TX side respectively) along "
500 520 "with -c or -s\n");
501 521 mdb_printf("\n%<u>Interpreting TX Modes%</u>\n");
502 522 mdb_printf("\t DEF --> Default\n");
503 523 mdb_printf("\t SER --> Serialize\n");
504 524 mdb_printf("\t FO --> Fanout\n");
505 525 mdb_printf("\t BW --> Bandwidth\n");
506 526 mdb_printf("\tBWFO --> Bandwidth Fanout\n");
507 527 mdb_printf("\t AG --> Aggr\n");
508 528 mdb_printf("\tBWAG --> Bandwidth Aggr\n");
509 529 }
510 530
511 531 /*
512 532 * In verbose mode "::mac_srs -rcv or ::mac_srs -tcv", we print the CPUs
513 533 * assigned to a link and CPUS assigned to the soft rings.
514 534 * 'len' is used for formatting the output and represents the number of
515 535 * spaces between CPU list and Fanout CPU list in the output.
516 536 */
517 537 static boolean_t
518 538 mac_srs_print_cpu(int *i, uint32_t cnt, uint32_t *cpu_list, int *len)
519 539 {
520 540 int num = 0;
521 541
522 542 if (*i == 0)
523 543 mdb_printf("(");
524 544 else
525 545 mdb_printf(" ");
526 546 while (*i < cnt) {
527 547 /* We print 6 CPU's at a time to keep display within 80 cols */
528 548 if (((num + 1) % 7) == 0) {
529 549 if (len != NULL)
530 550 *len = 2;
531 551 return (B_FALSE);
532 552 }
533 553 mdb_printf("%02x%c", cpu_list[*i], ((*i == cnt - 1)?')':','));
534 554 ++*i;
535 555 ++num;
536 556 }
537 557 if (len != NULL)
538 558 *len = (7 - num) * 3;
539 559 return (B_TRUE);
540 560 }
541 561
542 562 static int
543 563 mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
544 564 {
545 565 uint_t args = MAC_SRS_NONE;
546 566 mac_soft_ring_set_t srs;
547 567 mac_client_impl_t mci;
548 568
549 569 if (!(flags & DCMD_ADDRSPEC)) {
550 570 if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) {
551 571 mdb_warn("failed to walk 'mac_srs'");
552 572 return (DCMD_ERR);
553 573 }
554 574 return (DCMD_OK);
555 575 }
556 576 if (mdb_getopts(argc, argv,
557 577 'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args,
558 578 't', MDB_OPT_SETBITS, MAC_SRS_TX, &args,
559 579 'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args,
560 580 'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args,
561 581 'i', MDB_OPT_SETBITS, MAC_SRS_INTR, &args,
562 582 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args,
563 583 NULL) != argc) {
564 584 return (DCMD_USAGE);
565 585 }
566 586
567 587 if (argc > 2)
568 588 return (DCMD_USAGE);
569 589
570 590 if (mdb_vread(&srs, sizeof (srs), addr) == -1) {
571 591 mdb_warn("failed to read struct mac_soft_ring_set_s at %p",
572 592 addr);
573 593 return (DCMD_ERR);
574 594 }
575 595 if (mdb_vread(&mci, sizeof (mci), (uintptr_t)srs.srs_mcip) == -1) {
576 596 mdb_warn("failed to read struct mac_client_impl_t at %p "
577 597 "for SRS %p", srs.srs_mcip, addr);
578 598 return (DCMD_ERR);
579 599 }
580 600
581 601 switch (args) {
582 602 case MAC_SRS_RX: {
583 603 if (DCMD_HDRSPEC(flags)) {
584 604 mdb_printf("%?s %-20s %-8s %-8s %8s "
585 605 "%8s %3s\n",
586 606 "", "", "", "", "MBLK",
587 607 "Q", "SR");
588 608 mdb_printf("%<u>%?s %-20s %-8s %-8s %8s "
589 609 "%8s %3s%</u>\n",
590 610 "ADDR", "LINK_NAME", "STATE", "TYPE", "CNT",
591 611 "BYTES", "CNT");
592 612 }
593 613 if (srs.srs_type & SRST_TX)
594 614 return (DCMD_OK);
595 615 mdb_printf("%?p %-20s %08x %08x "
596 616 "%8d %8d %3d\n",
597 617 addr, mci.mci_name, srs.srs_state, srs.srs_type,
598 618 srs.srs_count, srs.srs_size, srs.srs_soft_ring_count);
599 619 break;
600 620 }
601 621 case MAC_SRS_TX: {
602 622 if (DCMD_HDRSPEC(flags)) {
603 623 mdb_printf("%?s %-16s %-4s %-8s "
604 624 "%-8s %8s %8s %3s\n",
605 625 "", "", "TX", "",
606 626 "", "MBLK", "Q", "SR");
607 627 mdb_printf("%<u>%?s %-16s %-4s %-8s "
608 628 "%-8s %8s %8s %3s%</u>\n",
609 629 "ADDR", "LINK_NAME", "MODE", "STATE",
610 630 "TYPE", "CNT", "BYTES", "CNT");
611 631 }
612 632 if (!(srs.srs_type & SRST_TX))
613 633 return (DCMD_OK);
614 634
615 635 mdb_printf("%?p %-16s %-4s "
616 636 "%08x %08x %8d %8d %3d\n",
617 637 addr, mci.mci_name, mac_srs_txmode2str(srs.srs_tx.st_mode),
618 638 srs.srs_state, srs.srs_type, srs.srs_count, srs.srs_size,
619 639 srs.srs_tx_ring_count);
620 640 break;
621 641 }
622 642 case MAC_SRS_RXCPU: {
623 643 mac_cpus_t mc = srs.srs_cpu;
624 644
625 645 if (DCMD_HDRSPEC(flags)) {
626 646 mdb_printf("%?s %-20s %-4s %-4s "
627 647 "%-6s %-4s %-7s\n",
628 648 "", "", "NUM", "POLL",
629 649 "WORKER", "INTR", "FANOUT");
630 650 mdb_printf("%<u>%?s %-20s %-4s %-4s "
631 651 "%-6s %-4s %-7s%</u>\n",
632 652 "ADDR", "LINK_NAME", "CPUS", "CPU",
633 653 "CPU", "CPU", "CPU_CNT");
634 654 }
635 655 if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))
636 656 return (DCMD_OK);
637 657 mdb_printf("%?p %-20s %-4d %-4d "
638 658 "%-6d %-4d %-7d\n",
639 659 addr, mci.mci_name, mc.mc_ncpus, mc.mc_rx_pollid,
640 660 mc.mc_rx_workerid, mc.mc_rx_intr_cpu, mc.mc_rx_fanout_cnt);
641 661 break;
642 662
643 663 }
644 664 case MAC_SRS_TXCPU: {
645 665 mac_cpus_t mc = srs.srs_cpu;
646 666 mac_soft_ring_t *s_ringp, s_ring;
647 667 boolean_t first = B_TRUE;
648 668 int i;
649 669
650 670 if (DCMD_HDRSPEC(flags)) {
651 671 mdb_printf("%?s %-12s %?s %8s %8s %8s\n",
652 672 "", "", "SOFT", "WORKER", "INTR", "RETARGETED");
653 673 mdb_printf("%<u>%?s %-12s %?s %8s %8s %8s%</u>\n",
654 674 "ADDR", "LINK_NAME", "RING", "CPU", "CPU", "CPU");
655 675 }
656 676 if (!(srs.srs_type & SRST_TX))
657 677 return (DCMD_OK);
658 678
659 679 mdb_printf("%?p %-12s ", addr, mci.mci_name);
660 680
661 681 /*
662 682 * Case of no soft rings, print the info from
663 683 * mac_srs_tx_t.
664 684 */
665 685 if (srs.srs_tx_ring_count == 0) {
666 686 mdb_printf("%?p %8d %8d %8d\n",
667 687 0, mc.mc_tx_fanout_cpus[0],
668 688 mc.mc_tx_intr_cpu[0],
669 689 mc.mc_tx_retargeted_cpu[0]);
670 690 break;
671 691 }
672 692
673 693 for (s_ringp = srs.srs_soft_ring_head, i = 0; s_ringp != NULL;
674 694 s_ringp = s_ring.s_ring_next, i++) {
675 695 (void) mdb_vread(&s_ring, sizeof (s_ring),
676 696 (uintptr_t)s_ringp);
677 697 if (first) {
678 698 mdb_printf("%?p %8d %8d %8d\n",
679 699 s_ringp, mc.mc_tx_fanout_cpus[i],
680 700 mc.mc_tx_intr_cpu[i],
681 701 mc.mc_tx_retargeted_cpu[i]);
682 702 first = B_FALSE;
683 703 continue;
684 704 }
685 705 mdb_printf("%?s %-12s %?p %8d %8d %8d\n",
686 706 "", "", s_ringp, mc.mc_tx_fanout_cpus[i],
687 707 mc.mc_tx_intr_cpu[i], mc.mc_tx_retargeted_cpu[i]);
688 708 }
689 709 break;
690 710 }
691 711 case MAC_SRS_TXINTR: {
692 712 mac_cpus_t mc = srs.srs_cpu;
693 713 mac_soft_ring_t *s_ringp, s_ring;
694 714 mac_ring_t *m_ringp, m_ring;
695 715 boolean_t first = B_TRUE;
696 716 int i;
697 717
698 718 if (DCMD_HDRSPEC(flags)) {
699 719 mdb_printf("%?s %-12s %?s %8s %?s %6s %6s\n",
700 720 "", "", "SOFT", "WORKER", "MAC", "", "INTR");
701 721 mdb_printf("%<u>%?s %-12s %?s %8s %?s %6s %6s%</u>\n",
702 722 "ADDR", "LINK_NAME", "RING", "CPU", "RING",
703 723 "SHARED", "CPU");
704 724 }
705 725 if (!(srs.srs_type & SRST_TX))
706 726 return (DCMD_OK);
707 727
708 728 mdb_printf("%?p %-12s ", addr, mci.mci_name);
709 729
710 730 /*
711 731 * Case of no soft rings, print the info from
712 732 * mac_srs_tx_t.
713 733 */
714 734 if (srs.srs_tx_ring_count == 0) {
715 735 m_ringp = srs.srs_tx.st_arg2;
716 736 if (m_ringp != NULL) {
717 737 (void) mdb_vread(&m_ring, sizeof (m_ring),
718 738 (uintptr_t)m_ringp);
719 739 mdb_printf("%?p %8d %?p %6d %6d\n",
720 740 0, mc.mc_tx_fanout_cpus[0], m_ringp,
721 741 m_ring.mr_info.mri_intr.mi_ddi_shared,
722 742 mc.mc_tx_retargeted_cpu[0]);
723 743 } else {
724 744 mdb_printf("%?p %8d %?p %6d %6d\n",
725 745 0, mc.mc_tx_fanout_cpus[0], 0,
726 746 0, mc.mc_tx_retargeted_cpu[0]);
727 747 }
728 748 break;
729 749 }
730 750
731 751 for (s_ringp = srs.srs_soft_ring_head, i = 0; s_ringp != NULL;
732 752 s_ringp = s_ring.s_ring_next, i++) {
733 753 (void) mdb_vread(&s_ring, sizeof (s_ring),
734 754 (uintptr_t)s_ringp);
735 755 m_ringp = s_ring.s_ring_tx_arg2;
736 756 (void) mdb_vread(&m_ring, sizeof (m_ring),
737 757 (uintptr_t)m_ringp);
738 758 if (first) {
739 759 mdb_printf("%?p %8d %?p %6d %6d\n",
740 760 s_ringp, mc.mc_tx_fanout_cpus[i],
741 761 m_ringp,
742 762 m_ring.mr_info.mri_intr.mi_ddi_shared,
743 763 mc.mc_tx_retargeted_cpu[i]);
744 764 first = B_FALSE;
745 765 continue;
746 766 }
747 767 mdb_printf("%?s %-12s %?p %8d %?p %6d %6d\n",
748 768 "", "", s_ringp, mc.mc_tx_fanout_cpus[i],
749 769 m_ringp, m_ring.mr_info.mri_intr.mi_ddi_shared,
750 770 mc.mc_tx_retargeted_cpu[i]);
751 771 }
752 772 break;
753 773 }
754 774 case MAC_SRS_RXINTR: {
755 775 mac_cpus_t mc = srs.srs_cpu;
756 776 mac_ring_t *m_ringp, m_ring;
757 777
758 778 if (DCMD_HDRSPEC(flags)) {
759 779 mdb_printf("%?s %-12s %?s %8s %6s %6s\n",
760 780 "", "", "MAC", "", "POLL", "INTR");
761 781 mdb_printf("%<u>%?s %-12s %?s %8s %6s %6s%</u>\n",
762 782 "ADDR", "LINK_NAME", "RING", "SHARED", "CPU",
763 783 "CPU");
764 784 }
765 785 if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))
766 786 return (DCMD_OK);
767 787
768 788 mdb_printf("%?p %-12s ", addr, mci.mci_name);
769 789
770 790 m_ringp = srs.srs_ring;
771 791 if (m_ringp != NULL) {
772 792 (void) mdb_vread(&m_ring, sizeof (m_ring),
773 793 (uintptr_t)m_ringp);
774 794 mdb_printf("%?p %8d %6d %6d\n",
775 795 m_ringp, m_ring.mr_info.mri_intr.mi_ddi_shared,
776 796 mc.mc_rx_pollid, mc.mc_rx_intr_cpu);
777 797 } else {
778 798 mdb_printf("%?p %8d %6d %6d\n",
779 799 0, 0, mc.mc_rx_pollid, mc.mc_rx_intr_cpu);
780 800 }
781 801 break;
782 802 }
783 803 case MAC_SRS_RXCPUVERBOSE:
784 804 case MAC_SRS_TXCPUVERBOSE: {
785 805 mac_cpus_t mc = srs.srs_cpu;
786 806 int cpu_index = 0, fanout_index = 0, len = 0;
787 807 boolean_t cpu_done = B_FALSE, fanout_done = B_FALSE;
788 808
789 809 if (DCMD_HDRSPEC(flags)) {
790 810 mdb_printf("%?s %-20s %-20s %-20s\n",
791 811 "", "", "CPU_COUNT", "FANOUT_CPU_COUNT");
792 812 mdb_printf("%<u>%?s %-20s "
793 813 "%-20s %-20s%</u>\n",
794 814 "ADDR", "LINK_NAME",
795 815 "(CPU_LIST)", "(CPU_LIST)");
796 816 }
797 817 if (((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) ||
798 818 ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)))
799 819 return (DCMD_OK);
800 820 mdb_printf("%?p %-20s %-20d %-20d\n", addr, mci.mci_name,
801 821 mc.mc_ncpus, mc.mc_rx_fanout_cnt);
802 822 if (mc.mc_ncpus == 0 && mc.mc_rx_fanout_cnt == 0)
803 823 break;
804 824 /* print all cpus and cpus for soft rings */
805 825 while (!cpu_done || !fanout_done) {
806 826 boolean_t old_value = cpu_done;
807 827
808 828 if (!cpu_done) {
809 829 mdb_printf("%?s %20s ", "", "");
810 830 cpu_done = mac_srs_print_cpu(&cpu_index,
811 831 mc.mc_ncpus, mc.mc_cpus, &len);
812 832 }
813 833 if (!fanout_done) {
814 834 if (old_value)
815 835 mdb_printf("%?s %-40s", "", "");
816 836 else
817 837 mdb_printf("%*s", len, "");
818 838 fanout_done = mac_srs_print_cpu(&fanout_index,
819 839 mc.mc_rx_fanout_cnt,
820 840 mc.mc_rx_fanout_cpus, NULL);
821 841 }
822 842 mdb_printf("\n");
823 843 }
824 844 break;
825 845 }
826 846 case MAC_SRS_RXSTAT: {
827 847 mac_rx_stats_t *mac_rx_stat = &srs.srs_rx.sr_stat;
828 848
829 849 if (DCMD_HDRSPEC(flags)) {
830 850 mdb_printf("%?s %-16s %8s %8s "
831 851 "%8s %8s %8s\n",
832 852 "", "", "INTR", "POLL",
833 853 "CHAIN", "CHAIN", "CHAIN");
834 854 mdb_printf("%<u>%?s %-16s %8s %8s "
835 855 "%8s %8s %8s%</u>\n",
836 856 "ADDR", "LINK_NAME", "COUNT", "COUNT",
837 857 "<10", "10-50", ">50");
838 858 }
839 859 if (srs.srs_type & SRST_TX)
840 860 return (DCMD_OK);
841 861 mdb_printf("%?p %-16s %8d "
842 862 "%8d %8d "
843 863 "%8d %8d\n",
844 864 addr, mci.mci_name, mac_rx_stat->mrs_intrcnt,
845 865 mac_rx_stat->mrs_pollcnt, mac_rx_stat->mrs_chaincntundr10,
846 866 mac_rx_stat->mrs_chaincnt10to50,
847 867 mac_rx_stat->mrs_chaincntover50);
848 868 break;
849 869 }
850 870 case MAC_SRS_TXSTAT: {
851 871 mac_tx_stats_t *mac_tx_stat = &srs.srs_tx.st_stat;
852 872 mac_soft_ring_t *s_ringp, s_ring;
853 873 boolean_t first = B_TRUE;
854 874
855 875 if (DCMD_HDRSPEC(flags)) {
856 876 mdb_printf("%?s %-20s %?s %8s %8s %8s\n",
857 877 "", "", "SOFT", "DROP", "BLOCK", "UNBLOCK");
858 878 mdb_printf("%<u>%?s %-20s %?s %8s %8s %8s%</u>\n",
859 879 "ADDR", "LINK_NAME", "RING", "COUNT", "COUNT",
860 880 "COUNT");
861 881 }
862 882 if (!(srs.srs_type & SRST_TX))
863 883 return (DCMD_OK);
864 884
865 885 mdb_printf("%?p %-20s ", addr, mci.mci_name);
866 886
867 887 /*
868 888 * Case of no soft rings, print the info from
869 889 * mac_srs_tx_t.
870 890 */
871 891 if (srs.srs_tx_ring_count == 0) {
872 892 mdb_printf("%?p %8d %8d %8d\n",
873 893 0, mac_tx_stat->mts_sdrops,
874 894 mac_tx_stat->mts_blockcnt,
875 895 mac_tx_stat->mts_unblockcnt);
876 896 break;
877 897 }
878 898
879 899 for (s_ringp = srs.srs_soft_ring_head; s_ringp != NULL;
880 900 s_ringp = s_ring.s_ring_next) {
881 901 (void) mdb_vread(&s_ring, sizeof (s_ring),
882 902 (uintptr_t)s_ringp);
883 903 mac_tx_stat = &s_ring.s_st_stat;
884 904 if (first) {
885 905 mdb_printf("%?p %8d %8d %8d\n",
886 906 s_ringp, mac_tx_stat->mts_sdrops,
887 907 mac_tx_stat->mts_blockcnt,
888 908 mac_tx_stat->mts_unblockcnt);
889 909 first = B_FALSE;
890 910 continue;
891 911 }
892 912 mdb_printf("%?s %-20s %?p %8d %8d %8d\n",
893 913 "", "", s_ringp, mac_tx_stat->mts_sdrops,
894 914 mac_tx_stat->mts_blockcnt,
895 915 mac_tx_stat->mts_unblockcnt);
896 916 }
897 917 break;
898 918 }
899 919 case MAC_SRS_NONE: {
900 920 if (DCMD_HDRSPEC(flags)) {
901 921 mdb_printf("%<u>%?s %-20s %?s %?s %-3s%</u>\n",
902 922 "ADDR", "LINK_NAME", "FLENT", "HW RING", "DIR");
903 923 }
904 924 mdb_printf("%?p %-20s %?p %?p "
905 925 "%-3s ",
906 926 addr, mci.mci_name, srs.srs_flent, srs.srs_ring,
907 927 (srs.srs_type & SRST_TX ? "TX" : "RX"));
908 928 break;
909 929 }
910 930 default:
911 931 return (DCMD_USAGE);
912 932 }
913 933 return (DCMD_OK);
914 934 }
915 935
916 936 static int
917 937 mac_srs_walk_init(mdb_walk_state_t *wsp)
918 938 {
919 939 if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) {
920 940 mdb_warn("failed to walk 'mac_srs'");
921 941 return (WALK_ERR);
922 942 }
923 943 return (WALK_NEXT);
924 944 }
925 945
926 946 static char *
927 947 mac_ring_state2str(mac_ring_state_t state)
928 948 {
929 949 switch (state) {
930 950 case MR_FREE:
931 951 return ("free");
932 952 case MR_NEWLY_ADDED:
933 953 return ("new");
934 954 case MR_INUSE:
935 955 return ("inuse");
936 956 }
937 957 return ("--");
938 958 }
939 959
940 960 static char *
941 961 mac_ring_classify2str(mac_classify_type_t classify)
942 962 {
943 963 switch (classify) {
944 964 case MAC_NO_CLASSIFIER:
945 965 return ("no");
946 966 case MAC_SW_CLASSIFIER:
947 967 return ("sw");
948 968 case MAC_HW_CLASSIFIER:
949 969 return ("hw");
950 970 }
951 971 return ("--");
952 972 }
953 973
954 974 static int
955 975 mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
956 976 {
957 977 mac_ring_t ring;
958 978 mac_group_t group;
959 979 flow_entry_t flent;
960 980 mac_soft_ring_set_t srs;
961 981
962 982 if (!(flags & DCMD_ADDRSPEC)) {
963 983 if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) {
964 984 mdb_warn("failed to walk 'mac_ring'");
965 985 return (DCMD_ERR);
966 986 }
967 987 return (DCMD_OK);
968 988 }
969 989 if (mdb_vread(&ring, sizeof (ring), addr) == -1) {
970 990 mdb_warn("failed to read struct mac_ring_s at %p", addr);
971 991 return (DCMD_ERR);
972 992 }
973 993 bzero(&flent, sizeof (flent));
974 994 if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) {
975 995 (void) mdb_vread(&flent, sizeof (flent),
976 996 (uintptr_t)srs.srs_flent);
977 997 }
978 998 (void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh);
979 999 if (DCMD_HDRSPEC(flags)) {
980 1000 mdb_printf("%<u>%?s %4s %5s %4s %?s "
981 1001 "%5s %?s %?s %s %</u>\n",
982 1002 "ADDR", "TYPE", "STATE", "FLAG", "GROUP",
983 1003 "CLASS", "MIP", "SRS", "FLOW NAME");
984 1004 }
985 1005 mdb_printf("%?p %-4s "
986 1006 "%5s %04x "
987 1007 "%?p %-5s "
988 1008 "%?p %?p %s\n",
989 1009 addr, ((ring.mr_type == 1)? "RX" : "TX"),
990 1010 mac_ring_state2str(ring.mr_state), ring.mr_flag,
991 1011 ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type),
992 1012 group.mrg_mh, ring.mr_srs, flent.fe_flow_name);
993 1013 return (DCMD_OK);
994 1014 }
995 1015
996 1016 static int
997 1017 mac_ring_walk_init(mdb_walk_state_t *wsp)
998 1018 {
999 1019 if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) {
1000 1020 mdb_warn("failed to walk `mac_ring`");
1001 1021 return (WALK_ERR);
1002 1022 }
1003 1023 return (WALK_NEXT);
1004 1024 }
1005 1025
1006 1026 static void
1007 1027 mac_ring_help(void)
1008 1028 {
1009 1029 mdb_printf("If an address is specified, then mac_ring_t "
1010 1030 "structure at that address is printed. Otherwise all the "
1011 1031 "hardware rings in the system are printed.\n");
1012 1032 }
1013 1033
1014 1034 /*
1015 1035 * To walk groups we have to have our own somewhat-complicated state machine. We
1016 1036 * basically start by walking the mac_impl_t walker as all groups are stored off
1017 1037 * of the various mac_impl_t in the system. The tx and rx rings are kept
1018 1038 * separately. So we'll need to walk through all the rx rings and then all of
1019 1039 * the tx rings.
1020 1040 */
1021 1041 static int
1022 1042 mac_group_walk_init(mdb_walk_state_t *wsp)
1023 1043 {
1024 1044 int ret;
1025 1045
1026 1046 if (wsp->walk_addr != NULL) {
1027 1047 mdb_warn("non-global walks are not supported\n");
1028 1048 return (WALK_ERR);
1029 1049 }
1030 1050
1031 1051 if ((ret = mdb_layered_walk(LAYERED_WALKER_FOR_GROUP, wsp)) == -1) {
1032 1052 mdb_warn("couldn't walk '%s'", LAYERED_WALKER_FOR_GROUP);
1033 1053 return (ret);
1034 1054 }
1035 1055
1036 1056 return (WALK_NEXT);
1037 1057 }
1038 1058
1039 1059 static int
1040 1060 mac_group_walk_step(mdb_walk_state_t *wsp)
1041 1061 {
1042 1062 int ret;
1043 1063 mac_impl_t mi;
1044 1064 mac_group_t mg;
1045 1065 uintptr_t mgp;
1046 1066
1047 1067 /*
1048 1068 * Nothing to do if we can't find the layer above us. But the kmem
1049 1069 * walkers are a bit unsporting, they don't actually read in the data
1050 1070 * for us.
1051 1071 */
1052 1072 if (wsp->walk_addr == NULL)
1053 1073 return (WALK_DONE);
1054 1074
1055 1075 if (mdb_vread(&mi, sizeof (mac_impl_t), wsp->walk_addr) == -1) {
1056 1076 mdb_warn("failed to read mac_impl_t at %p", wsp->walk_addr);
1057 1077 return (DCMD_ERR);
1058 1078 }
1059 1079
1060 1080 /*
1061 1081 * First go for rx groups, then tx groups.
1062 1082 */
1063 1083 mgp = (uintptr_t)mi.mi_rx_groups;
1064 1084 while (mgp != NULL) {
1065 1085 if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) {
1066 1086 mdb_warn("failed to read mac_group_t at %p", mgp);
1067 1087 return (WALK_ERR);
1068 1088 }
1069 1089
1070 1090 ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata);
1071 1091 if (ret != WALK_NEXT)
1072 1092 return (ret);
1073 1093 mgp = (uintptr_t)mg.mrg_next;
1074 1094 }
1075 1095
1076 1096 mgp = (uintptr_t)mi.mi_tx_groups;
1077 1097 while (mgp != NULL) {
1078 1098 if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) {
1079 1099 mdb_warn("failed to read mac_group_t at %p", mgp);
1080 1100 return (WALK_ERR);
1081 1101 }
1082 1102
1083 1103 ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata);
1084 1104 if (ret != WALK_NEXT)
1085 1105 return (ret);
1086 1106 mgp = (uintptr_t)mg.mrg_next;
1087 1107 }
1088 1108
1089 1109 return (WALK_NEXT);
1090 1110 }
1091 1111
1092 1112 static int
1093 1113 mac_group_count_clients(mac_group_t *mgp)
1094 1114 {
1095 1115 int clients = 0;
1096 1116 uintptr_t mcp = (uintptr_t)mgp->mrg_clients;
1097 1117
1098 1118 while (mcp != NULL) {
1099 1119 mac_grp_client_t c;
1100 1120
1101 1121 if (mdb_vread(&c, sizeof (c), mcp) == -1) {
1102 1122 mdb_warn("failed to read mac_grp_client_t at %p", mcp);
1103 1123 return (-1);
1104 1124 }
1105 1125 clients++;
1106 1126 mcp = (uintptr_t)c.mgc_next;
1107 1127 }
1108 1128
1109 1129 return (clients);
1110 1130 }
1111 1131
1112 1132 static const char *
1113 1133 mac_group_type(mac_group_t *mgp)
1114 1134 {
1115 1135 const char *ret;
1116 1136
1117 1137 switch (mgp->mrg_type) {
1118 1138 case MAC_RING_TYPE_RX:
1119 1139 ret = "RECEIVE";
1120 1140 break;
1121 1141 case MAC_RING_TYPE_TX:
1122 1142 ret = "TRANSMIT";
1123 1143 break;
1124 1144 default:
1125 1145 ret = "UNKNOWN";
1126 1146 break;
1127 1147 }
1128 1148
1129 1149 return (ret);
1130 1150 }
1131 1151
1132 1152 static const char *
1133 1153 mac_group_state(mac_group_t *mgp)
1134 1154 {
1135 1155 const char *ret;
1136 1156
1137 1157 switch (mgp->mrg_state) {
1138 1158 case MAC_GROUP_STATE_UNINIT:
1139 1159 ret = "UNINT";
1140 1160 break;
1141 1161 case MAC_GROUP_STATE_REGISTERED:
1142 1162 ret = "REGISTERED";
1143 1163 break;
1144 1164 case MAC_GROUP_STATE_RESERVED:
1145 1165 ret = "RESERVED";
1146 1166 break;
1147 1167 case MAC_GROUP_STATE_SHARED:
1148 1168 ret = "SHARED";
1149 1169 break;
1150 1170 default:
1151 1171 ret = "UNKNOWN";
1152 1172 break;
1153 1173 }
1154 1174
1155 1175 return (ret);
1156 1176 }
1157 1177
1158 1178 static int
1159 1179 mac_group_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1160 1180 {
1161 1181 uint_t args = MAC_SRS_NONE;
1162 1182 mac_group_t mg;
1163 1183 int clients;
1164 1184
1165 1185 if (!(flags & DCMD_ADDRSPEC)) {
1166 1186 if (mdb_walk_dcmd("mac_group", "mac_group", argc, argv) == -1) {
1167 1187 mdb_warn("failed to walk 'mac_group'");
1168 1188 return (DCMD_ERR);
1169 1189 }
1170 1190
1171 1191 return (DCMD_OK);
1172 1192 }
1173 1193
1174 1194 if (mdb_getopts(argc, argv,
1175 1195 'r', MDB_OPT_SETBITS, MAC_GROUP_RX, &args,
1176 1196 't', MDB_OPT_SETBITS, MAC_GROUP_TX, &args,
1177 1197 'u', MDB_OPT_SETBITS, MAC_GROUP_UNINIT, &args,
1178 1198 NULL) != argc)
1179 1199 return (DCMD_USAGE);
1180 1200
1181 1201 if (mdb_vread(&mg, sizeof (mac_group_t), addr) == -1) {
1182 1202 mdb_warn("failed to read mac_group_t at %p", addr);
1183 1203 return (DCMD_ERR);
1184 1204 }
1185 1205
1186 1206 if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
1187 1207 mdb_printf("%<u>%-?s %-8s %-10s %6s %8s %-?s%</u>\n",
1188 1208 "ADDR", "TYPE", "STATE", "NRINGS", "NCLIENTS", "RINGS");
1189 1209 }
1190 1210
1191 1211 if ((args & MAC_GROUP_RX) != 0 && mg.mrg_type != MAC_RING_TYPE_RX)
1192 1212 return (DCMD_OK);
1193 1213 if ((args & MAC_GROUP_TX) != 0 && mg.mrg_type != MAC_RING_TYPE_TX)
1194 1214 return (DCMD_OK);
1195 1215
1196 1216 /*
1197 1217 * By default, don't show uninitialized groups. They're not very
1198 1218 * interesting. They have no rings and no clients.
1199 1219 */
1200 1220 if (mg.mrg_state == MAC_GROUP_STATE_UNINIT &&
1201 1221 (args & MAC_GROUP_UNINIT) == 0)
1202 1222 return (DCMD_OK);
1203 1223
1204 1224 if (flags & DCMD_PIPE_OUT) {
1205 1225 mdb_printf("%lr\n", addr);
1206 1226 return (DCMD_OK);
1207 1227 }
1208 1228
1209 1229 clients = mac_group_count_clients(&mg);
1210 1230 mdb_printf("%?p %-8s %-10s %6d %8d %?p\n", addr, mac_group_type(&mg),
1211 1231 mac_group_state(&mg), mg.mrg_cur_count, clients, mg.mrg_rings);
1212 1232
1213 1233 return (DCMD_OK);
1214 1234 }
1215 1235
1216 1236 /* Supported dee-commands */
1217 1237 static const mdb_dcmd_t dcmds[] = {
1218 1238 {"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures",
1219 1239 mac_flow_dcmd, mac_flow_help},
1220 1240 {"mac_group", "?[-rtu]", "display MAC Ring Groups", mac_group_dcmd,
1221 1241 NULL },
1222 1242 {"mac_srs", "?[ -r[i|s|c[v]] | -t[i|s|c[v]] ]",
1223 1243 "display MAC Soft Ring Set" " structures", mac_srs_dcmd,
1224 1244 mac_srs_help},
1225 1245 {"mac_ring", "?", "display MAC ring (hardware) structures",
1226 1246 mac_ring_dcmd, mac_ring_help},
1227 1247 { NULL }
1228 1248 };
1229 1249
1230 1250 /* Supported walkers */
1231 1251 static const mdb_walker_t walkers[] = {
1232 1252 {"mac_flow", "walk list of flow entry structures", mac_flow_walk_init,
1233 1253 mac_common_walk_step, NULL, NULL},
1234 1254 {"mac_group", "walk list of ring group structures", mac_group_walk_init,
1235 1255 mac_group_walk_step, NULL, NULL},
1236 1256 {"mac_srs", "walk list of mac soft ring set structures",
1237 1257 mac_srs_walk_init, mac_common_walk_step, NULL, NULL},
1238 1258 {"mac_ring", "walk list of mac ring structures", mac_ring_walk_init,
1239 1259 mac_common_walk_step, NULL, NULL},
1240 1260 { NULL }
1241 1261 };
1242 1262
1243 1263 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
1244 1264
1245 1265 const mdb_modinfo_t *
1246 1266 _mdb_init(void)
1247 1267 {
1248 1268 return (&modinfo);
1249 1269 }
↓ open down ↓ |
893 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX