1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/mdb_modapi.h> 27 #include <sys/types.h> 28 #include <inet/ip.h> 29 #include <inet/ip6.h> 30 31 #include <sys/mac.h> 32 #include <sys/mac_provider.h> 33 #include <sys/mac_client.h> 34 #include <sys/mac_client_impl.h> 35 #include <sys/mac_flow_impl.h> 36 #include <sys/mac_soft_ring.h> 37 38 #define STRSIZE 64 39 #define MAC_RX_SRS_SIZE (MAX_RINGS_PER_GROUP * sizeof (uintptr_t)) 40 41 #define LAYERED_WALKER_FOR_FLOW "flow_entry_cache" 42 #define LAYERED_WALKER_FOR_SRS "mac_srs_cache" 43 #define LAYERED_WALKER_FOR_RING "mac_ring_cache" 44 45 /* arguments passed to mac_flow dee-command */ 46 #define MAC_FLOW_NONE 0x01 47 #define MAC_FLOW_ATTR 0x02 48 #define MAC_FLOW_PROP 0x04 49 #define MAC_FLOW_RX 0x08 50 #define MAC_FLOW_TX 0x10 51 #define MAC_FLOW_USER 0x20 52 #define MAC_FLOW_STATS 0x40 53 #define MAC_FLOW_MISC 0x80 54 55 /* arguments passed to mac_srs dee-command */ 56 #define MAC_SRS_NONE 0x00 57 #define MAC_SRS_RX 0x01 58 #define MAC_SRS_TX 0x02 59 #define MAC_SRS_STAT 0x04 60 #define MAC_SRS_CPU 0x08 61 #define MAC_SRS_VERBOSE 0x10 62 #define MAC_SRS_RXSTAT (MAC_SRS_RX|MAC_SRS_STAT) 63 #define MAC_SRS_TXSTAT (MAC_SRS_TX|MAC_SRS_STAT) 64 #define MAC_SRS_RXCPU (MAC_SRS_RX|MAC_SRS_CPU) 65 #define MAC_SRS_TXCPU (MAC_SRS_TX|MAC_SRS_CPU) 66 #define MAC_SRS_RXCPUVERBOSE (MAC_SRS_RXCPU|MAC_SRS_VERBOSE) 67 #define MAC_SRS_TXCPUVERBOSE (MAC_SRS_TXCPU|MAC_SRS_VERBOSE) 68 69 static char * 70 mac_flow_proto2str(uint8_t protocol) 71 { 72 switch (protocol) { 73 case IPPROTO_TCP: 74 return ("tcp"); 75 case IPPROTO_UDP: 76 return ("udp"); 77 case IPPROTO_SCTP: 78 return ("sctp"); 79 case IPPROTO_ICMP: 80 return ("icmp"); 81 case IPPROTO_ICMPV6: 82 return ("icmpv6"); 83 default: 84 return ("--"); 85 } 86 } 87 88 static char * 89 mac_flow_priority2str(mac_priority_level_t prio) 90 { 91 switch (prio) { 92 case MPL_LOW: 93 return ("low"); 94 case MPL_MEDIUM: 95 return ("medium"); 96 case MPL_HIGH: 97 return ("high"); 98 case MPL_RESET: 99 return ("reset"); 100 default: 101 return ("--"); 102 } 103 } 104 105 /* 106 * Convert bandwidth in bps to a string in mpbs. 107 */ 108 static char * 109 mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len) 110 { 111 int kbps, mbps; 112 113 kbps = (bw % 1000000)/1000; 114 mbps = bw/1000000; 115 if ((mbps == 0) && (kbps != 0)) 116 mdb_snprintf(buf, len, "0.%03u", kbps); 117 else 118 mdb_snprintf(buf, len, "%5u", mbps); 119 return (buf); 120 } 121 122 static void 123 mac_flow_print_header(uint_t args) 124 { 125 switch (args) { 126 case MAC_FLOW_NONE: 127 mdb_printf("%<u>%?s %-32s %-6s %?s %?s %-20s%</u>\n", 128 "ADDR", "FLOW NAME", "LINKID", "MCIP", "MIP", 129 "MIP NAME"); 130 break; 131 case MAC_FLOW_ATTR: 132 mdb_printf("%<u>%?s %-32s %-7s %6s " 133 "%-9s %s%</u>\n", 134 "ADDR", "FLOW NAME", "PROTO", "PORT", 135 "DSFLD:MSK", "IPADDR"); 136 break; 137 case MAC_FLOW_PROP: 138 mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n", 139 "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY"); 140 break; 141 case MAC_FLOW_MISC: 142 mdb_printf("%<u>%?s %-32s %10s %10s " 143 "%32s %s%</u>\n", 144 "ADDR", "FLOW NAME", "TYPE", "FLAGS", 145 "MATCH_FN", "ZONE"); 146 break; 147 case MAC_FLOW_RX: 148 mdb_printf("%<u>%?s %-24s %7s %s%</u>\n", 149 "ADDR", "FLOW NAME", "SRS_CNT", "RX_SRS"); 150 break; 151 case MAC_FLOW_TX: 152 mdb_printf("%<u>%?s %-32s %?s %</u>\n", 153 "ADDR", "FLOW NAME", "TX_SRS"); 154 break; 155 case MAC_FLOW_STATS: 156 mdb_printf("%<u>%?s %-32s %?s %?s%</u>\n", 157 "ADDR", "FLOW NAME", "RBYTES", "OBYTES"); 158 break; 159 } 160 } 161 162 /* 163 * Display selected fields of the flow_entry_t structure 164 */ 165 static int 166 mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args) 167 { 168 static const mdb_bitmask_t flow_type_bits[] = { 169 {"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC}, 170 {"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC}, 171 {"M", FLOW_MCAST, FLOW_MCAST}, 172 {"O", FLOW_OTHER, FLOW_OTHER}, 173 {"U", FLOW_USER, FLOW_USER}, 174 {"V", FLOW_VNIC, FLOW_VNIC}, 175 {"NS", FLOW_NO_STATS, FLOW_NO_STATS}, 176 { NULL, 0, 0 } 177 }; 178 #define FLOW_MAX_TYPE (sizeof (flow_type_bits) / sizeof (mdb_bitmask_t)) 179 180 static const mdb_bitmask_t flow_flag_bits[] = { 181 {"Q", FE_QUIESCE, FE_QUIESCE}, 182 {"W", FE_WAITER, FE_WAITER}, 183 {"T", FE_FLOW_TAB, FE_FLOW_TAB}, 184 {"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH}, 185 {"I", FE_INCIPIENT, FE_INCIPIENT}, 186 {"C", FE_CONDEMNED, FE_CONDEMNED}, 187 {"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH}, 188 {"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH}, 189 { NULL, 0, 0 } 190 }; 191 #define FLOW_MAX_FLAGS (sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t)) 192 flow_entry_t fe; 193 mac_client_impl_t mcip; 194 mac_impl_t mip; 195 196 if (mdb_vread(&fe, sizeof (fe), addr) == -1) { 197 mdb_warn("failed to read struct flow_entry_s at %p", addr); 198 return (DCMD_ERR); 199 } 200 if (args & MAC_FLOW_USER) { 201 args &= ~MAC_FLOW_USER; 202 if (fe.fe_type & FLOW_MCAST) { 203 if (DCMD_HDRSPEC(flags)) 204 mac_flow_print_header(args); 205 return (DCMD_OK); 206 } 207 } 208 if (DCMD_HDRSPEC(flags)) 209 mac_flow_print_header(args); 210 bzero(&mcip, sizeof (mcip)); 211 bzero(&mip, sizeof (mip)); 212 if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip), 213 (uintptr_t)fe.fe_mcip) == sizeof (mcip)) { 214 (void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip); 215 } 216 switch (args) { 217 case MAC_FLOW_NONE: { 218 mdb_printf("%?p %-32s %6d %?p " 219 "%?p %-20s\n", 220 addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip, 221 mcip.mci_mip, mip.mi_name); 222 break; 223 } 224 case MAC_FLOW_ATTR: { 225 struct in_addr in4; 226 uintptr_t desc_addr; 227 flow_desc_t fdesc; 228 229 desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc); 230 if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) { 231 mdb_warn("failed to read struct flow_description at %p", 232 desc_addr); 233 return (DCMD_ERR); 234 } 235 mdb_printf("%?p %-32s " 236 "%-7s %6d" 237 "%4d:%-4d ", 238 addr, fe.fe_flow_name, 239 mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port, 240 fdesc.fd_dsfield, fdesc.fd_dsfield_mask); 241 if (fdesc.fd_ipversion == IPV4_VERSION) { 242 IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4); 243 mdb_printf("%I", in4.s_addr); 244 } else if (fdesc.fd_ipversion == IPV6_VERSION) { 245 mdb_printf("%N", &fdesc.fd_local_addr); 246 } else { 247 mdb_printf("%s", "--"); 248 } 249 mdb_printf("\n"); 250 break; 251 } 252 case MAC_FLOW_PROP: { 253 uintptr_t prop_addr; 254 char bwstr[STRSIZE]; 255 mac_resource_props_t fprop; 256 257 prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props); 258 if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) { 259 mdb_warn("failed to read struct mac_resoource_props " 260 "at %p", prop_addr); 261 return (DCMD_ERR); 262 } 263 mdb_printf("%?p %-32s " 264 "%8s %9s\n", 265 addr, fe.fe_flow_name, 266 mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE), 267 mac_flow_priority2str(fprop.mrp_priority)); 268 break; 269 } 270 case MAC_FLOW_MISC: { 271 char flow_flags[2 * FLOW_MAX_FLAGS]; 272 char flow_type[2 * FLOW_MAX_TYPE]; 273 GElf_Sym sym; 274 char func_name[MDB_SYM_NAMLEN] = ""; 275 uintptr_t func, match_addr; 276 277 match_addr = addr + OFFSETOF(flow_entry_t, fe_match); 278 (void) mdb_vread(&func, sizeof (func), match_addr); 279 (void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name, 280 MDB_SYM_NAMLEN, &sym); 281 mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb", 282 fe.fe_flags, flow_flag_bits); 283 mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb", 284 fe.fe_type, flow_type_bits); 285 mdb_printf("%?p %-32s %10s %10s " 286 "%32s %-d\n", 287 addr, fe.fe_flow_name, flow_type, flow_flags, 288 func_name, fe.fe_zoneid); 289 break; 290 } 291 case MAC_FLOW_RX: { 292 uintptr_t rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0}; 293 int i; 294 295 rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs); 296 (void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr); 297 mdb_printf("%?p %-24s %7d ", 298 addr, fe.fe_flow_name, fe.fe_rx_srs_cnt); 299 for (i = 0; i < MAX_RINGS_PER_GROUP; i++) { 300 if (rx_srs[i] == 0) 301 continue; 302 mdb_printf("%p ", rx_srs[i]); 303 } 304 mdb_printf("\n"); 305 break; 306 } 307 case MAC_FLOW_TX: { 308 uintptr_t tx_srs = 0, txaddr; 309 310 txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs); 311 (void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr); 312 mdb_printf("%?p %-32s %?p\n", 313 addr, fe.fe_flow_name, fe.fe_tx_srs); 314 break; 315 } 316 case MAC_FLOW_STATS: { 317 mdb_printf("%?p %-32s %16llu %16llu\n", 318 addr, fe.fe_flow_name, fe.fe_flowstats.fs_rbytes, 319 fe.fe_flowstats.fs_obytes); 320 break; 321 } 322 } 323 return (DCMD_OK); 324 } 325 326 /* 327 * Parse the arguments passed to the dcmd and print all or one flow_entry_t 328 * structures 329 */ 330 static int 331 mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 332 { 333 uint_t args = 0; 334 335 if (!(flags & DCMD_ADDRSPEC)) { 336 if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) { 337 mdb_warn("failed to walk 'mac_flow'"); 338 return (DCMD_ERR); 339 } 340 return (DCMD_OK); 341 } 342 if ((mdb_getopts(argc, argv, 343 'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args, 344 'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args, 345 'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args, 346 'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args, 347 't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args, 348 's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args, 349 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args) != argc)) { 350 return (DCMD_USAGE); 351 } 352 if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER))) 353 return (DCMD_USAGE); 354 /* 355 * If no arguments was specified or just "-u" was specified then 356 * we default to printing basic information of flows. 357 */ 358 if (args == 0 || args == MAC_FLOW_USER) 359 args |= MAC_FLOW_NONE; 360 361 return (mac_flow_dcmd_output(addr, flags, args)); 362 } 363 364 static void 365 mac_flow_help(void) 366 { 367 mdb_printf("If an address is specified, then flow_entry structure at " 368 "that address is printed. Otherwise all the flows in the system " 369 "are printed.\n"); 370 mdb_printf("Options:\n" 371 "\t-u\tdisplay user defined link & vnic flows.\n" 372 "\t-a\tdisplay flow attributes\n" 373 "\t-p\tdisplay flow properties\n" 374 "\t-r\tdisplay rx side information\n" 375 "\t-t\tdisplay tx side information\n" 376 "\t-s\tdisplay flow statistics\n" 377 "\t-m\tdisplay miscellaneous flow information\n\n"); 378 mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n"); 379 mdb_printf("Flow Types:\n"); 380 mdb_printf("\t P --> FLOW_PRIMARY_MAC\n"); 381 mdb_printf("\t V --> FLOW_VNIC_MAC\n"); 382 mdb_printf("\t M --> FLOW_MCAST\n"); 383 mdb_printf("\t O --> FLOW_OTHER\n"); 384 mdb_printf("\t U --> FLOW_USER\n"); 385 mdb_printf("\t NS --> FLOW_NO_STATS\n\n"); 386 mdb_printf("Flow Flags:\n"); 387 mdb_printf("\t Q --> FE_QUIESCE\n"); 388 mdb_printf("\t W --> FE_WAITER\n"); 389 mdb_printf("\t T --> FE_FLOW_TAB\n"); 390 mdb_printf("\t G --> FE_G_FLOW_HASH\n"); 391 mdb_printf("\t I --> FE_INCIPIENT\n"); 392 mdb_printf("\t C --> FE_CONDEMNED\n"); 393 mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n"); 394 mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n"); 395 } 396 397 /* 398 * called once by the debugger when the mac_flow walk begins. 399 */ 400 static int 401 mac_flow_walk_init(mdb_walk_state_t *wsp) 402 { 403 if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) { 404 mdb_warn("failed to walk 'mac_flow'"); 405 return (WALK_ERR); 406 } 407 return (WALK_NEXT); 408 } 409 410 /* 411 * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and 412 * mac_ring_t. 413 * 414 * Steps through each flow_entry_t and calls the callback function. If the 415 * user executed ::walk mac_flow, it just prints the address or if the user 416 * executed ::mac_flow it displays selected fields of flow_entry_t structure 417 * by calling "mac_flow_dcmd" 418 */ 419 static int 420 mac_common_walk_step(mdb_walk_state_t *wsp) 421 { 422 int status; 423 424 if (wsp->walk_addr == NULL) 425 return (WALK_DONE); 426 427 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 428 wsp->walk_cbdata); 429 430 return (status); 431 } 432 433 static char * 434 mac_srs_txmode2str(mac_tx_srs_mode_t mode) 435 { 436 switch (mode) { 437 case SRS_TX_DEFAULT: 438 return ("DEF"); 439 case SRS_TX_SERIALIZE: 440 return ("SER"); 441 case SRS_TX_FANOUT: 442 return ("FO"); 443 case SRS_TX_BW: 444 return ("BW"); 445 case SRS_TX_BW_FANOUT: 446 return ("BWFO"); 447 } 448 return ("--"); 449 } 450 451 static void 452 mac_srs_help(void) 453 { 454 mdb_printf("If an address is specified, then mac_soft_ring_set " 455 "structure at that address is printed. Otherwise all the " 456 "SRS in the system are printed.\n"); 457 mdb_printf("Options:\n" 458 "\t-r\tdisplay recieve side SRS structures\n" 459 "\t-t\tdisplay transmit side SRS structures\n" 460 "\t-s\tdisplay statistics for RX or TX side\n" 461 "\t-c\tdisplay CPU binding for RX or TX side\n" 462 "\t-v\tverbose flag for CPU binding to list cpus\n" 463 "Note: use -r or -t (to specify RX or TX side respectively) along " 464 "with -c or -s\n"); 465 mdb_printf("\n%<u>Interpreting TX Modes%</u>\n"); 466 mdb_printf("\t DEF --> Default\n"); 467 mdb_printf("\t SER --> Serialize\n"); 468 mdb_printf("\t FO --> Fanout\n"); 469 mdb_printf("\t BW --> Bandwidth\n"); 470 mdb_printf("\tBWFO --> Bandwidth Fanout\n"); 471 } 472 473 /* 474 * In verbose mode "::mac_srs -rcv or ::mac_srs -tcv", we print the CPUs 475 * assigned to a link and CPUS assigned to the soft rings. 476 * 'len' is used for formatting the output and represents the number of 477 * spaces between CPU list and Fanout CPU list in the output. 478 */ 479 static boolean_t 480 mac_srs_print_cpu(int *i, uint32_t cnt, uint32_t *cpu_list, int *len) 481 { 482 int num = 0; 483 484 if (*i == 0) 485 mdb_printf("("); 486 else 487 mdb_printf(" "); 488 while (*i < cnt) { 489 /* We print 6 CPU's at a time to keep display within 80 cols */ 490 if (((num + 1) % 7) == 0) { 491 if (len != NULL) 492 *len = 2; 493 return (B_FALSE); 494 } 495 mdb_printf("%02x%c", cpu_list[*i], ((*i == cnt - 1)?')':',')); 496 ++*i; 497 ++num; 498 } 499 if (len != NULL) 500 *len = (7 - num) * 3; 501 return (B_TRUE); 502 } 503 504 static int 505 mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 506 { 507 uint_t args = MAC_SRS_NONE; 508 mac_soft_ring_set_t srs; 509 mac_client_impl_t mci; 510 511 if (!(flags & DCMD_ADDRSPEC)) { 512 if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) { 513 mdb_warn("failed to walk 'mac_srs'"); 514 return (DCMD_ERR); 515 } 516 return (DCMD_OK); 517 } 518 if (mdb_getopts(argc, argv, 519 'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args, 520 't', MDB_OPT_SETBITS, MAC_SRS_TX, &args, 521 'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args, 522 'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args, 523 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args) != argc) { 524 return (DCMD_USAGE); 525 } 526 527 if (argc > 2) 528 return (DCMD_USAGE); 529 530 if (mdb_vread(&srs, sizeof (srs), addr) == -1) { 531 mdb_warn("failed to read struct mac_soft_ring_set_s at %p", 532 addr); 533 return (DCMD_ERR); 534 } 535 if (mdb_vread(&mci, sizeof (mci), (uintptr_t)srs.srs_mcip) == -1) { 536 mdb_warn("failed to read struct mac_client_impl_t at %p " 537 "for SRS %p", srs.srs_mcip, addr); 538 return (DCMD_ERR); 539 } 540 541 switch (args) { 542 case MAC_SRS_RX: { 543 if (DCMD_HDRSPEC(flags)) { 544 mdb_printf("%?s %-20s %-8s %-8s %-8s " 545 "%-8s %-3s\n", 546 "", "", "", "", "MBLK", 547 "Q", "SR"); 548 mdb_printf("%<u>%?s %-20s %-8s %-8s %-8s " 549 "%-8s %-3s%</u>\n", 550 "ADDR", "LINK_NAME", "STATE", "TYPE", "CNT", 551 "BYTES", "CNT"); 552 } 553 if (srs.srs_type & SRST_TX) 554 return (DCMD_OK); 555 mdb_printf("%?p %-20s %08x %08x " 556 "%-8d %-8d %-3d\n", 557 addr, mci.mci_name, srs.srs_state, srs.srs_type, 558 srs.srs_count, srs.srs_size, srs.srs_soft_ring_count); 559 break; 560 } 561 case MAC_SRS_TX: { 562 if (DCMD_HDRSPEC(flags)) { 563 mdb_printf("%?s %-16s %-4s %-8s " 564 "%-8s %-8s %-8s %-3s\n", 565 "", "", "TX", "", 566 "", "MBLK", "Q", "SR"); 567 mdb_printf("%<u>%?s %-16s %-4s %-8s " 568 "%-8s %-8s %-8s %-3s%</u>\n", 569 "ADDR", "LINK_NAME", "MODE", "STATE", 570 "TYPE", "CNT", "BYTES", "CNT"); 571 } 572 if (!(srs.srs_type & SRST_TX)) 573 return (DCMD_OK); 574 575 mdb_printf("%?p %-16s %-4s " 576 "%08x %08x %-8d %-8d %-3d\n", 577 addr, mci.mci_name, mac_srs_txmode2str(srs.srs_tx.st_mode), 578 srs.srs_state, srs.srs_type, srs.srs_count, srs.srs_size, 579 srs.srs_oth_ring_count); 580 break; 581 } 582 case MAC_SRS_RXCPU: { 583 mac_cpus_t mc = srs.srs_cpu; 584 585 if (DCMD_HDRSPEC(flags)) { 586 mdb_printf("%?s %-20s %-4s %-4s " 587 "%-6s %-4s %-7s\n", 588 "", "", "NUM", "POLL", 589 "WORKER", "INTR", "FANOUT"); 590 mdb_printf("%<u>%?s %-20s %-4s %-4s " 591 "%-6s %-4s %-7s%</u>\n", 592 "ADDR", "LINK_NAME", "CPUS", "CPU", 593 "CPU", "CPU", "CPU_CNT"); 594 } 595 if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)) 596 return (DCMD_OK); 597 mdb_printf("%?p %-20s %-4d %-4d " 598 "%-6d %-4d %-7d\n", 599 addr, mci.mci_name, mc.mc_ncpus, mc.mc_pollid, 600 mc.mc_workerid, mc.mc_intr_cpu, mc.mc_fanout_cnt); 601 break; 602 603 } 604 case MAC_SRS_TXCPU: { 605 mac_cpus_t mc = srs.srs_cpu; 606 607 if (DCMD_HDRSPEC(flags)) { 608 mdb_printf("%?s %-20s %-4s %-6s " 609 "%-4s %-7s\n", 610 "", "", "NUM", "WORKER", 611 "INTR", "FANOUT"); 612 mdb_printf("%<u>%?s %-20s %-4s %-6s " 613 "%-4s %-7s%</u>\n", 614 "ADDR", "LINK_NAME", "CPUS", "CPU", 615 "CPU", "CPU_CNT"); 616 } 617 if ((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) 618 return (DCMD_OK); 619 mdb_printf("%?p %-20s %-4d " 620 "%-6d %-4d %-7d\n", 621 addr, mci.mci_name, mc.mc_ncpus, 622 mc.mc_workerid, mc.mc_intr_cpu, mc.mc_fanout_cnt); 623 break; 624 } 625 case MAC_SRS_RXCPUVERBOSE: 626 case MAC_SRS_TXCPUVERBOSE: { 627 mac_cpus_t mc = srs.srs_cpu; 628 int cpu_index = 0, fanout_index = 0, len = 0; 629 boolean_t cpu_done = B_FALSE, fanout_done = B_FALSE; 630 631 if (DCMD_HDRSPEC(flags)) { 632 mdb_printf("%?s %-20s %-20s %-20s\n", 633 "", "", "CPU_COUNT", "FANOUT_CPU_COUNT"); 634 mdb_printf("%<u>%?s %-20s " 635 "%-20s %-20s%</u>\n", 636 "ADDR", "LINK_NAME", 637 "(CPU_LIST)", "(CPU_LIST)"); 638 } 639 if (((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) || 640 ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))) 641 return (DCMD_OK); 642 mdb_printf("%?p %-20s %-20d %-20d\n", addr, mci.mci_name, 643 mc.mc_ncpus, mc.mc_fanout_cnt); 644 if (mc.mc_ncpus == 0 && mc.mc_fanout_cnt == 0) 645 break; 646 /* print all cpus and cpus for soft rings */ 647 while (!cpu_done || !fanout_done) { 648 boolean_t old_value = cpu_done; 649 650 if (!cpu_done) { 651 mdb_printf("%?s %20s ", "", ""); 652 cpu_done = mac_srs_print_cpu(&cpu_index, 653 mc.mc_ncpus, mc.mc_cpus, &len); 654 } 655 if (!fanout_done) { 656 if (old_value) 657 mdb_printf("%?s %-40s", "", ""); 658 else 659 mdb_printf("%*s", len, ""); 660 fanout_done = mac_srs_print_cpu(&fanout_index, 661 mc.mc_fanout_cnt, mc.mc_fanout_cpus, NULL); 662 } 663 mdb_printf("\n"); 664 } 665 break; 666 } 667 case MAC_SRS_RXSTAT: { 668 mac_srs_rx_t srs_rx = srs.srs_rx; 669 670 if (DCMD_HDRSPEC(flags)) { 671 mdb_printf("%?s %-16s %-8s %-8s " 672 "%-8s %-8s %-8s\n", 673 "", "", "INTR", "POLL", 674 "CHAIN", "CHAIN", "CHAIN"); 675 mdb_printf("%<u>%?s %-16s %-8s %-8s " 676 "%-8s %-8s %-8s%</u>\n", 677 "ADDR", "LINK_NAME", "COUNT", "COUNT", 678 "<10", "10-50", ">50"); 679 } 680 if (srs.srs_type & SRST_TX) 681 return (DCMD_OK); 682 mdb_printf("%?p %-16s %-8d " 683 "%-8d %-8d " 684 "%-8d %-8d\n", 685 addr, mci.mci_name, srs_rx.sr_intr_count, 686 srs_rx.sr_poll_count, srs_rx.sr_chain_cnt_undr10, 687 srs_rx.sr_chain_cnt_10to50, srs_rx.sr_chain_cnt_over50); 688 break; 689 } 690 case MAC_SRS_TXSTAT: { 691 mac_srs_tx_t srs_tx = srs.srs_tx; 692 693 if (DCMD_HDRSPEC(flags)) { 694 mdb_printf("%?s %-20s %-5s %-8s " 695 "%-8s %-8s %-8s\n", 696 "", "", "WOKEN", "MAX", 697 "DROP", "BLOCK", "UNBLOCK"); 698 mdb_printf("%<u>%?s %-20s %-5s %-8s " 699 "%-8s %-8s %-8s%</u>\n", 700 "ADDR", "LINK_NAME", "UP", "Q_COUNT", 701 "COUNT", "COUNT", "COUNT"); 702 } 703 if (!(srs.srs_type & SRST_TX)) 704 return (DCMD_OK); 705 706 mdb_printf("%?p %-20s %-5d " 707 "%-8d %-8d " 708 "%-8d %-8d\n", 709 addr, mci.mci_name, srs.srs_tx.st_woken_up, 710 srs_tx.st_max_q_cnt, srs_tx.st_drop_count, 711 srs_tx.st_blocked_cnt, srs_tx.st_unblocked_cnt); 712 break; 713 } 714 case MAC_SRS_NONE: { 715 if (DCMD_HDRSPEC(flags)) { 716 mdb_printf("%<u>%?s %-20s %?s %?s %-3s%</u>\n", 717 "ADDR", "LINK_NAME", "FLENT", "HW RING", "DIR"); 718 } 719 mdb_printf("%?p %-20s %?p %?p " 720 "%-3s ", 721 addr, mci.mci_name, srs.srs_flent, srs.srs_ring, 722 (srs.srs_type & SRST_TX ? "TX" : "RX")); 723 break; 724 } 725 default: 726 return (DCMD_USAGE); 727 } 728 return (DCMD_OK); 729 } 730 731 static int 732 mac_srs_walk_init(mdb_walk_state_t *wsp) 733 { 734 if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) { 735 mdb_warn("failed to walk 'mac_srs'"); 736 return (WALK_ERR); 737 } 738 return (WALK_NEXT); 739 } 740 741 static char * 742 mac_ring_state2str(mac_ring_state_t state) 743 { 744 switch (state) { 745 case MR_FREE: 746 return ("free"); 747 case MR_NEWLY_ADDED: 748 return ("new"); 749 case MR_INUSE: 750 return ("inuse"); 751 } 752 return ("--"); 753 } 754 755 static char * 756 mac_ring_classify2str(mac_classify_type_t classify) 757 { 758 switch (classify) { 759 case MAC_NO_CLASSIFIER: 760 return ("no"); 761 case MAC_SW_CLASSIFIER: 762 return ("sw"); 763 case MAC_HW_CLASSIFIER: 764 return ("hw"); 765 } 766 return ("--"); 767 } 768 769 static int 770 mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 771 { 772 mac_ring_t ring; 773 mac_group_t group; 774 flow_entry_t flent; 775 mac_soft_ring_set_t srs; 776 777 if (!(flags & DCMD_ADDRSPEC)) { 778 if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) { 779 mdb_warn("failed to walk 'mac_ring'"); 780 return (DCMD_ERR); 781 } 782 return (DCMD_OK); 783 } 784 if (mdb_vread(&ring, sizeof (ring), addr) == -1) { 785 mdb_warn("failed to read struct mac_ring_s at %p", addr); 786 return (DCMD_ERR); 787 } 788 bzero(&flent, sizeof (flent)); 789 if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) { 790 (void) mdb_vread(&flent, sizeof (flent), 791 (uintptr_t)srs.srs_flent); 792 } 793 (void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh); 794 if (DCMD_HDRSPEC(flags)) { 795 mdb_printf("%<u>%?s %4s %5s %4s %?s " 796 "%5s %?s %?s %s %</u>\n", 797 "ADDR", "TYPE", "STATE", "FLAG", "GROUP", 798 "CLASS", "MIP", "SRS", "FLOW NAME"); 799 } 800 mdb_printf("%?p %-4s " 801 "%5s %04x " 802 "%?p %-5s " 803 "%?p %?p %s\n", 804 addr, ((ring.mr_type == 1)? "RX" : "TX"), 805 mac_ring_state2str(ring.mr_state), ring.mr_flag, 806 ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type), 807 group.mrg_mh, ring.mr_srs, flent.fe_flow_name); 808 return (DCMD_OK); 809 } 810 811 static int 812 mac_ring_walk_init(mdb_walk_state_t *wsp) 813 { 814 if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) { 815 mdb_warn("failed to walk `mac_ring`"); 816 return (WALK_ERR); 817 } 818 return (WALK_NEXT); 819 } 820 821 static void 822 mac_ring_help(void) 823 { 824 mdb_printf("If an address is specified, then mac_ring_t " 825 "structure at that address is printed. Otherwise all the " 826 "hardware rings in the system are printed.\n"); 827 } 828 829 /* Supported dee-commands */ 830 static const mdb_dcmd_t dcmds[] = { 831 {"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures", 832 mac_flow_dcmd, mac_flow_help}, 833 {"mac_srs", "?[ -r[s|c[v]] | -t[s|c[v]] ]", "display MAC Soft Ring Set" 834 " structures", mac_srs_dcmd, mac_srs_help}, 835 {"mac_ring", "?", "display MAC ring (hardware) structures", 836 mac_ring_dcmd, mac_ring_help}, 837 { NULL } 838 }; 839 840 /* Supported walkers */ 841 static const mdb_walker_t walkers[] = { 842 {"mac_flow", "walk list of flow entry structures", mac_flow_walk_init, 843 mac_common_walk_step, NULL, NULL}, 844 {"mac_srs", "walk list of mac soft ring set structures", 845 mac_srs_walk_init, mac_common_walk_step, NULL, NULL}, 846 {"mac_ring", "walk list of mac ring structures", mac_ring_walk_init, 847 mac_common_walk_step, NULL, NULL}, 848 { NULL } 849 }; 850 851 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 852 853 const mdb_modinfo_t * 854 _mdb_init(void) 855 { 856 return (&modinfo); 857 } 858