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