1da14cebeSEric Cheng /* 2da14cebeSEric Cheng * CDDL HEADER START 3da14cebeSEric Cheng * 4da14cebeSEric Cheng * The contents of this file are subject to the terms of the 5da14cebeSEric Cheng * Common Development and Distribution License (the "License"). 6da14cebeSEric Cheng * You may not use this file except in compliance with the License. 7da14cebeSEric Cheng * 8da14cebeSEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da14cebeSEric Cheng * or http://www.opensolaris.org/os/licensing. 10da14cebeSEric Cheng * See the License for the specific language governing permissions 11da14cebeSEric Cheng * and limitations under the License. 12da14cebeSEric Cheng * 13da14cebeSEric Cheng * When distributing Covered Code, include this CDDL HEADER in each 14da14cebeSEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da14cebeSEric Cheng * If applicable, add the following below this CDDL HEADER, with the 16da14cebeSEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying 17da14cebeSEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner] 18da14cebeSEric Cheng * 19da14cebeSEric Cheng * CDDL HEADER END 20da14cebeSEric Cheng */ 21da14cebeSEric Cheng /* 220dc2366fSVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23da14cebeSEric Cheng * Use is subject to license terms. 24da14cebeSEric Cheng */ 25da14cebeSEric Cheng 26da14cebeSEric Cheng #include <sys/mdb_modapi.h> 27da14cebeSEric Cheng #include <sys/types.h> 28da14cebeSEric Cheng #include <inet/ip.h> 29da14cebeSEric Cheng #include <inet/ip6.h> 30da14cebeSEric Cheng 31da14cebeSEric Cheng #include <sys/mac.h> 32da14cebeSEric Cheng #include <sys/mac_provider.h> 33da14cebeSEric Cheng #include <sys/mac_client.h> 34da14cebeSEric Cheng #include <sys/mac_client_impl.h> 35da14cebeSEric Cheng #include <sys/mac_flow_impl.h> 36da14cebeSEric Cheng #include <sys/mac_soft_ring.h> 370dc2366fSVenugopal Iyer #include <sys/mac_stat.h> 38da14cebeSEric Cheng 39da14cebeSEric Cheng #define STRSIZE 64 40da14cebeSEric Cheng #define MAC_RX_SRS_SIZE (MAX_RINGS_PER_GROUP * sizeof (uintptr_t)) 41da14cebeSEric Cheng 42da14cebeSEric Cheng #define LAYERED_WALKER_FOR_FLOW "flow_entry_cache" 43da14cebeSEric Cheng #define LAYERED_WALKER_FOR_SRS "mac_srs_cache" 44da14cebeSEric Cheng #define LAYERED_WALKER_FOR_RING "mac_ring_cache" 45d47ced1fSRobert Mustacchi #define LAYERED_WALKER_FOR_GROUP "mac_impl_cache" 46da14cebeSEric Cheng 47da14cebeSEric Cheng /* arguments passed to mac_flow dee-command */ 48da14cebeSEric Cheng #define MAC_FLOW_NONE 0x01 49da14cebeSEric Cheng #define MAC_FLOW_ATTR 0x02 50da14cebeSEric Cheng #define MAC_FLOW_PROP 0x04 51da14cebeSEric Cheng #define MAC_FLOW_RX 0x08 52da14cebeSEric Cheng #define MAC_FLOW_TX 0x10 53da14cebeSEric Cheng #define MAC_FLOW_USER 0x20 54da14cebeSEric Cheng #define MAC_FLOW_STATS 0x40 55da14cebeSEric Cheng #define MAC_FLOW_MISC 0x80 56da14cebeSEric Cheng 57da14cebeSEric Cheng /* arguments passed to mac_srs dee-command */ 582ae51e79SGirish Moodalbail #define MAC_SRS_NONE 0x00 59da14cebeSEric Cheng #define MAC_SRS_RX 0x01 60da14cebeSEric Cheng #define MAC_SRS_TX 0x02 612ae51e79SGirish Moodalbail #define MAC_SRS_STAT 0x04 622ae51e79SGirish Moodalbail #define MAC_SRS_CPU 0x08 632ae51e79SGirish Moodalbail #define MAC_SRS_VERBOSE 0x10 640dc2366fSVenugopal Iyer #define MAC_SRS_INTR 0x20 652ae51e79SGirish Moodalbail #define MAC_SRS_RXSTAT (MAC_SRS_RX|MAC_SRS_STAT) 662ae51e79SGirish Moodalbail #define MAC_SRS_TXSTAT (MAC_SRS_TX|MAC_SRS_STAT) 672ae51e79SGirish Moodalbail #define MAC_SRS_RXCPU (MAC_SRS_RX|MAC_SRS_CPU) 682ae51e79SGirish Moodalbail #define MAC_SRS_TXCPU (MAC_SRS_TX|MAC_SRS_CPU) 692ae51e79SGirish Moodalbail #define MAC_SRS_RXCPUVERBOSE (MAC_SRS_RXCPU|MAC_SRS_VERBOSE) 702ae51e79SGirish Moodalbail #define MAC_SRS_TXCPUVERBOSE (MAC_SRS_TXCPU|MAC_SRS_VERBOSE) 710dc2366fSVenugopal Iyer #define MAC_SRS_RXINTR (MAC_SRS_RX|MAC_SRS_INTR) 720dc2366fSVenugopal Iyer #define MAC_SRS_TXINTR (MAC_SRS_TX|MAC_SRS_INTR) 73da14cebeSEric Cheng 74d47ced1fSRobert Mustacchi /* arguments passed to mac_group dcmd */ 75d47ced1fSRobert Mustacchi #define MAC_GROUP_NONE 0x00 76d47ced1fSRobert Mustacchi #define MAC_GROUP_RX 0x01 77d47ced1fSRobert Mustacchi #define MAC_GROUP_TX 0x02 78d47ced1fSRobert Mustacchi #define MAC_GROUP_UNINIT 0x04 79d47ced1fSRobert Mustacchi 80da14cebeSEric Cheng static char * 81da14cebeSEric Cheng mac_flow_proto2str(uint8_t protocol) 82da14cebeSEric Cheng { 83da14cebeSEric Cheng switch (protocol) { 84da14cebeSEric Cheng case IPPROTO_TCP: 85da14cebeSEric Cheng return ("tcp"); 86da14cebeSEric Cheng case IPPROTO_UDP: 87da14cebeSEric Cheng return ("udp"); 88da14cebeSEric Cheng case IPPROTO_SCTP: 89da14cebeSEric Cheng return ("sctp"); 90da14cebeSEric Cheng case IPPROTO_ICMP: 91da14cebeSEric Cheng return ("icmp"); 92da14cebeSEric Cheng case IPPROTO_ICMPV6: 93da14cebeSEric Cheng return ("icmpv6"); 94da14cebeSEric Cheng default: 95da14cebeSEric Cheng return ("--"); 96da14cebeSEric Cheng } 97da14cebeSEric Cheng } 98da14cebeSEric Cheng 99da14cebeSEric Cheng static char * 100da14cebeSEric Cheng mac_flow_priority2str(mac_priority_level_t prio) 101da14cebeSEric Cheng { 102da14cebeSEric Cheng switch (prio) { 103da14cebeSEric Cheng case MPL_LOW: 104da14cebeSEric Cheng return ("low"); 105da14cebeSEric Cheng case MPL_MEDIUM: 106da14cebeSEric Cheng return ("medium"); 107da14cebeSEric Cheng case MPL_HIGH: 108da14cebeSEric Cheng return ("high"); 109da14cebeSEric Cheng case MPL_RESET: 110da14cebeSEric Cheng return ("reset"); 111da14cebeSEric Cheng default: 112da14cebeSEric Cheng return ("--"); 113da14cebeSEric Cheng } 114da14cebeSEric Cheng } 115da14cebeSEric Cheng 116da14cebeSEric Cheng /* 1174a3b1d5bSBart Coddens * Convert bandwidth in bps to a string in Mbps. 118da14cebeSEric Cheng */ 119da14cebeSEric Cheng static char * 120da14cebeSEric Cheng mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len) 121da14cebeSEric Cheng { 122da14cebeSEric Cheng int kbps, mbps; 123da14cebeSEric Cheng 124da14cebeSEric Cheng kbps = (bw % 1000000)/1000; 125da14cebeSEric Cheng mbps = bw/1000000; 126da14cebeSEric Cheng if ((mbps == 0) && (kbps != 0)) 127da14cebeSEric Cheng mdb_snprintf(buf, len, "0.%03u", kbps); 128da14cebeSEric Cheng else 129da14cebeSEric Cheng mdb_snprintf(buf, len, "%5u", mbps); 130da14cebeSEric Cheng return (buf); 131da14cebeSEric Cheng } 132da14cebeSEric Cheng 133da14cebeSEric Cheng static void 134da14cebeSEric Cheng mac_flow_print_header(uint_t args) 135da14cebeSEric Cheng { 136da14cebeSEric Cheng switch (args) { 137da14cebeSEric Cheng case MAC_FLOW_NONE: 138fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %4s %?s %?s %-16s\n", 139fcff38ebSGirish Moodalbail "", "", "LINK", "", "", "MIP"); 140fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %4s %?s %?s %-16s%</u>\n", 141fcff38ebSGirish Moodalbail "ADDR", "FLOW NAME", "ID", "MCIP", "MIP", "NAME"); 142da14cebeSEric Cheng break; 143da14cebeSEric Cheng case MAC_FLOW_ATTR: 144da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %-7s %6s " 145da14cebeSEric Cheng "%-9s %s%</u>\n", 146da14cebeSEric Cheng "ADDR", "FLOW NAME", "PROTO", "PORT", 147da14cebeSEric Cheng "DSFLD:MSK", "IPADDR"); 148da14cebeSEric Cheng break; 149da14cebeSEric Cheng case MAC_FLOW_PROP: 150da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n", 151da14cebeSEric Cheng "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY"); 152da14cebeSEric Cheng break; 153da14cebeSEric Cheng case MAC_FLOW_MISC: 154fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-24s %10s %10s " 155fcff38ebSGirish Moodalbail "%20s %4s%</u>\n", 156da14cebeSEric Cheng "ADDR", "FLOW NAME", "TYPE", "FLAGS", 157da14cebeSEric Cheng "MATCH_FN", "ZONE"); 158da14cebeSEric Cheng break; 159da14cebeSEric Cheng case MAC_FLOW_RX: 160fcff38ebSGirish Moodalbail mdb_printf("%?s %-24s %3s %s\n", "", "", "SRS", "RX"); 161fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-24s %3s %s%</u>\n", 162fcff38ebSGirish Moodalbail "ADDR", "FLOW NAME", "CNT", "SRS"); 163da14cebeSEric Cheng break; 164da14cebeSEric Cheng case MAC_FLOW_TX: 165da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %?s %</u>\n", 166da14cebeSEric Cheng "ADDR", "FLOW NAME", "TX_SRS"); 167da14cebeSEric Cheng break; 168da14cebeSEric Cheng case MAC_FLOW_STATS: 169fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-32s %16s %16s%</u>\n", 170da14cebeSEric Cheng "ADDR", "FLOW NAME", "RBYTES", "OBYTES"); 171da14cebeSEric Cheng break; 172da14cebeSEric Cheng } 173da14cebeSEric Cheng } 174da14cebeSEric Cheng 175da14cebeSEric Cheng /* 176da14cebeSEric Cheng * Display selected fields of the flow_entry_t structure 177da14cebeSEric Cheng */ 178da14cebeSEric Cheng static int 179da14cebeSEric Cheng mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args) 180da14cebeSEric Cheng { 181da14cebeSEric Cheng static const mdb_bitmask_t flow_type_bits[] = { 182da14cebeSEric Cheng {"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC}, 183da14cebeSEric Cheng {"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC}, 184da14cebeSEric Cheng {"M", FLOW_MCAST, FLOW_MCAST}, 185da14cebeSEric Cheng {"O", FLOW_OTHER, FLOW_OTHER}, 186da14cebeSEric Cheng {"U", FLOW_USER, FLOW_USER}, 187da14cebeSEric Cheng {"V", FLOW_VNIC, FLOW_VNIC}, 188da14cebeSEric Cheng {"NS", FLOW_NO_STATS, FLOW_NO_STATS}, 189da14cebeSEric Cheng { NULL, 0, 0 } 190da14cebeSEric Cheng }; 191da14cebeSEric Cheng #define FLOW_MAX_TYPE (sizeof (flow_type_bits) / sizeof (mdb_bitmask_t)) 192da14cebeSEric Cheng 193da14cebeSEric Cheng static const mdb_bitmask_t flow_flag_bits[] = { 194da14cebeSEric Cheng {"Q", FE_QUIESCE, FE_QUIESCE}, 195da14cebeSEric Cheng {"W", FE_WAITER, FE_WAITER}, 196da14cebeSEric Cheng {"T", FE_FLOW_TAB, FE_FLOW_TAB}, 197da14cebeSEric Cheng {"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH}, 198da14cebeSEric Cheng {"I", FE_INCIPIENT, FE_INCIPIENT}, 199da14cebeSEric Cheng {"C", FE_CONDEMNED, FE_CONDEMNED}, 200da14cebeSEric Cheng {"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH}, 201da14cebeSEric Cheng {"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH}, 202da14cebeSEric Cheng { NULL, 0, 0 } 203da14cebeSEric Cheng }; 204da14cebeSEric Cheng #define FLOW_MAX_FLAGS (sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t)) 205da14cebeSEric Cheng flow_entry_t fe; 206da14cebeSEric Cheng mac_client_impl_t mcip; 207da14cebeSEric Cheng mac_impl_t mip; 208da14cebeSEric Cheng 209da14cebeSEric Cheng if (mdb_vread(&fe, sizeof (fe), addr) == -1) { 210da14cebeSEric Cheng mdb_warn("failed to read struct flow_entry_s at %p", addr); 211da14cebeSEric Cheng return (DCMD_ERR); 212da14cebeSEric Cheng } 213da14cebeSEric Cheng if (args & MAC_FLOW_USER) { 214da14cebeSEric Cheng args &= ~MAC_FLOW_USER; 215da14cebeSEric Cheng if (fe.fe_type & FLOW_MCAST) { 216da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) 217da14cebeSEric Cheng mac_flow_print_header(args); 218da14cebeSEric Cheng return (DCMD_OK); 219da14cebeSEric Cheng } 220da14cebeSEric Cheng } 221da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) 222da14cebeSEric Cheng mac_flow_print_header(args); 223da14cebeSEric Cheng bzero(&mcip, sizeof (mcip)); 224da14cebeSEric Cheng bzero(&mip, sizeof (mip)); 225da14cebeSEric Cheng if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip), 226da14cebeSEric Cheng (uintptr_t)fe.fe_mcip) == sizeof (mcip)) { 227da14cebeSEric Cheng (void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip); 228da14cebeSEric Cheng } 229da14cebeSEric Cheng switch (args) { 230da14cebeSEric Cheng case MAC_FLOW_NONE: { 231fcff38ebSGirish Moodalbail mdb_printf("%?p %-20s %4d %?p " 232fcff38ebSGirish Moodalbail "%?p %-16s\n", 233da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip, 234da14cebeSEric Cheng mcip.mci_mip, mip.mi_name); 235da14cebeSEric Cheng break; 236da14cebeSEric Cheng } 237da14cebeSEric Cheng case MAC_FLOW_ATTR: { 238da14cebeSEric Cheng struct in_addr in4; 239da14cebeSEric Cheng uintptr_t desc_addr; 240da14cebeSEric Cheng flow_desc_t fdesc; 241da14cebeSEric Cheng 242da14cebeSEric Cheng desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc); 243da14cebeSEric Cheng if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) { 244da14cebeSEric Cheng mdb_warn("failed to read struct flow_description at %p", 245da14cebeSEric Cheng desc_addr); 246da14cebeSEric Cheng return (DCMD_ERR); 247da14cebeSEric Cheng } 248da14cebeSEric Cheng mdb_printf("%?p %-32s " 249da14cebeSEric Cheng "%-7s %6d " 250da14cebeSEric Cheng "%4d:%-4d ", 251da14cebeSEric Cheng addr, fe.fe_flow_name, 252da14cebeSEric Cheng mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port, 253da14cebeSEric Cheng fdesc.fd_dsfield, fdesc.fd_dsfield_mask); 254da14cebeSEric Cheng if (fdesc.fd_ipversion == IPV4_VERSION) { 255da14cebeSEric Cheng IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4); 256da14cebeSEric Cheng mdb_printf("%I", in4.s_addr); 257da14cebeSEric Cheng } else if (fdesc.fd_ipversion == IPV6_VERSION) { 258da14cebeSEric Cheng mdb_printf("%N", &fdesc.fd_local_addr); 259da14cebeSEric Cheng } else { 260da14cebeSEric Cheng mdb_printf("%s", "--"); 261da14cebeSEric Cheng } 262da14cebeSEric Cheng mdb_printf("\n"); 263da14cebeSEric Cheng break; 264da14cebeSEric Cheng } 265da14cebeSEric Cheng case MAC_FLOW_PROP: { 266da14cebeSEric Cheng uintptr_t prop_addr; 267da14cebeSEric Cheng char bwstr[STRSIZE]; 268da14cebeSEric Cheng mac_resource_props_t fprop; 269da14cebeSEric Cheng 270da14cebeSEric Cheng prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props); 271da14cebeSEric Cheng if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) { 272da14cebeSEric Cheng mdb_warn("failed to read struct mac_resoource_props " 273da14cebeSEric Cheng "at %p", prop_addr); 274da14cebeSEric Cheng return (DCMD_ERR); 275da14cebeSEric Cheng } 276da14cebeSEric Cheng mdb_printf("%?p %-32s " 277da14cebeSEric Cheng "%8s %9s\n", 278da14cebeSEric Cheng addr, fe.fe_flow_name, 279da14cebeSEric Cheng mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE), 280da14cebeSEric Cheng mac_flow_priority2str(fprop.mrp_priority)); 281da14cebeSEric Cheng break; 282da14cebeSEric Cheng } 283da14cebeSEric Cheng case MAC_FLOW_MISC: { 284da14cebeSEric Cheng char flow_flags[2 * FLOW_MAX_FLAGS]; 285da14cebeSEric Cheng char flow_type[2 * FLOW_MAX_TYPE]; 286da14cebeSEric Cheng GElf_Sym sym; 287da14cebeSEric Cheng char func_name[MDB_SYM_NAMLEN] = ""; 288da14cebeSEric Cheng uintptr_t func, match_addr; 289da14cebeSEric Cheng 290da14cebeSEric Cheng match_addr = addr + OFFSETOF(flow_entry_t, fe_match); 291da14cebeSEric Cheng (void) mdb_vread(&func, sizeof (func), match_addr); 292da14cebeSEric Cheng (void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name, 293da14cebeSEric Cheng MDB_SYM_NAMLEN, &sym); 294da14cebeSEric Cheng mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb", 295da14cebeSEric Cheng fe.fe_flags, flow_flag_bits); 296da14cebeSEric Cheng mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb", 297da14cebeSEric Cheng fe.fe_type, flow_type_bits); 2982b24ab6bSSebastien Roy mdb_printf("%?p %-24s %10s %10s %20s\n", 2992b24ab6bSSebastien Roy addr, fe.fe_flow_name, flow_type, flow_flags, func_name); 300da14cebeSEric Cheng break; 301da14cebeSEric Cheng } 302da14cebeSEric Cheng case MAC_FLOW_RX: { 3032ae51e79SGirish Moodalbail uintptr_t rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0}; 304da14cebeSEric Cheng int i; 305da14cebeSEric Cheng 306da14cebeSEric Cheng rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs); 307da14cebeSEric Cheng (void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr); 308fcff38ebSGirish Moodalbail mdb_printf("%?p %-24s %3d ", 3092ae51e79SGirish Moodalbail addr, fe.fe_flow_name, fe.fe_rx_srs_cnt); 310da14cebeSEric Cheng for (i = 0; i < MAX_RINGS_PER_GROUP; i++) { 311da14cebeSEric Cheng if (rx_srs[i] == 0) 312da14cebeSEric Cheng continue; 313da14cebeSEric Cheng mdb_printf("%p ", rx_srs[i]); 314da14cebeSEric Cheng } 315da14cebeSEric Cheng mdb_printf("\n"); 316da14cebeSEric Cheng break; 317da14cebeSEric Cheng } 318da14cebeSEric Cheng case MAC_FLOW_TX: { 319da14cebeSEric Cheng uintptr_t tx_srs = 0, txaddr; 320da14cebeSEric Cheng 321da14cebeSEric Cheng txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs); 322da14cebeSEric Cheng (void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr); 323da14cebeSEric Cheng mdb_printf("%?p %-32s %?p\n", 324da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_tx_srs); 325da14cebeSEric Cheng break; 326da14cebeSEric Cheng } 327da14cebeSEric Cheng case MAC_FLOW_STATS: { 3280dc2366fSVenugopal Iyer uint64_t totibytes = 0; 3290dc2366fSVenugopal Iyer uint64_t totobytes = 0; 3300dc2366fSVenugopal Iyer mac_soft_ring_set_t *mac_srs; 33178b013d7SRyan Zezeski mac_rx_stats_t mac_rx_stat; 33278b013d7SRyan Zezeski mac_tx_stats_t mac_tx_stat; 3330dc2366fSVenugopal Iyer int i; 3340dc2366fSVenugopal Iyer 33578b013d7SRyan Zezeski /* 33678b013d7SRyan Zezeski * Sum bytes for all Rx SRS. 33778b013d7SRyan Zezeski */ 3380dc2366fSVenugopal Iyer for (i = 0; i < fe.fe_rx_srs_cnt; i++) { 3390dc2366fSVenugopal Iyer mac_srs = (mac_soft_ring_set_t *)(fe.fe_rx_srs[i]); 34078b013d7SRyan Zezeski if (mdb_vread(&mac_rx_stat, sizeof (mac_rx_stats_t), 34178b013d7SRyan Zezeski (uintptr_t)&mac_srs->srs_rx.sr_stat) == -1) { 34278b013d7SRyan Zezeski mdb_warn("failed to read mac_rx_stats_t at %p", 34378b013d7SRyan Zezeski &mac_srs->srs_rx.sr_stat); 34478b013d7SRyan Zezeski return (DCMD_ERR); 3450dc2366fSVenugopal Iyer } 34678b013d7SRyan Zezeski 34778b013d7SRyan Zezeski totibytes += mac_rx_stat.mrs_intrbytes + 34878b013d7SRyan Zezeski mac_rx_stat.mrs_pollbytes + 34978b013d7SRyan Zezeski mac_rx_stat.mrs_lclbytes; 35078b013d7SRyan Zezeski } 35178b013d7SRyan Zezeski 35278b013d7SRyan Zezeski /* 35378b013d7SRyan Zezeski * Sum bytes for Tx SRS. 35478b013d7SRyan Zezeski */ 3550dc2366fSVenugopal Iyer mac_srs = (mac_soft_ring_set_t *)(fe.fe_tx_srs); 3560dc2366fSVenugopal Iyer if (mac_srs != NULL) { 35778b013d7SRyan Zezeski if (mdb_vread(&mac_tx_stat, sizeof (mac_tx_stats_t), 35878b013d7SRyan Zezeski (uintptr_t)&mac_srs->srs_tx.st_stat) == -1) { 35978b013d7SRyan Zezeski mdb_warn("failed to read max_tx_stats_t at %p", 36078b013d7SRyan Zezeski &mac_srs->srs_tx.st_stat); 36178b013d7SRyan Zezeski return (DCMD_ERR); 3620dc2366fSVenugopal Iyer } 36378b013d7SRyan Zezeski 36478b013d7SRyan Zezeski totobytes = mac_tx_stat.mts_obytes; 36578b013d7SRyan Zezeski } 36678b013d7SRyan Zezeski 367da14cebeSEric Cheng mdb_printf("%?p %-32s %16llu %16llu\n", 3680dc2366fSVenugopal Iyer addr, fe.fe_flow_name, totibytes, totobytes); 3690dc2366fSVenugopal Iyer 370da14cebeSEric Cheng break; 371da14cebeSEric Cheng } 372da14cebeSEric Cheng } 373da14cebeSEric Cheng return (DCMD_OK); 374da14cebeSEric Cheng } 375da14cebeSEric Cheng 376da14cebeSEric Cheng /* 377da14cebeSEric Cheng * Parse the arguments passed to the dcmd and print all or one flow_entry_t 378da14cebeSEric Cheng * structures 379da14cebeSEric Cheng */ 380da14cebeSEric Cheng static int 381da14cebeSEric Cheng mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 382da14cebeSEric Cheng { 383da14cebeSEric Cheng uint_t args = 0; 384da14cebeSEric Cheng 385da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) { 386da14cebeSEric Cheng if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) { 387da14cebeSEric Cheng mdb_warn("failed to walk 'mac_flow'"); 388da14cebeSEric Cheng return (DCMD_ERR); 389da14cebeSEric Cheng } 390da14cebeSEric Cheng return (DCMD_OK); 391da14cebeSEric Cheng } 392da14cebeSEric Cheng if ((mdb_getopts(argc, argv, 393da14cebeSEric Cheng 'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args, 394da14cebeSEric Cheng 'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args, 395da14cebeSEric Cheng 'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args, 396da14cebeSEric Cheng 'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args, 397da14cebeSEric Cheng 't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args, 398da14cebeSEric Cheng 's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args, 399d47ced1fSRobert Mustacchi 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args, 400d47ced1fSRobert Mustacchi NULL) != argc)) { 401da14cebeSEric Cheng return (DCMD_USAGE); 402da14cebeSEric Cheng } 403da14cebeSEric Cheng if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER))) 404da14cebeSEric Cheng return (DCMD_USAGE); 405da14cebeSEric Cheng /* 406da14cebeSEric Cheng * If no arguments was specified or just "-u" was specified then 407da14cebeSEric Cheng * we default to printing basic information of flows. 408da14cebeSEric Cheng */ 409da14cebeSEric Cheng if (args == 0 || args == MAC_FLOW_USER) 410da14cebeSEric Cheng args |= MAC_FLOW_NONE; 411da14cebeSEric Cheng 412da14cebeSEric Cheng return (mac_flow_dcmd_output(addr, flags, args)); 413da14cebeSEric Cheng } 414da14cebeSEric Cheng 415da14cebeSEric Cheng static void 416da14cebeSEric Cheng mac_flow_help(void) 417da14cebeSEric Cheng { 418da14cebeSEric Cheng mdb_printf("If an address is specified, then flow_entry structure at " 419da14cebeSEric Cheng "that address is printed. Otherwise all the flows in the system " 420da14cebeSEric Cheng "are printed.\n"); 421da14cebeSEric Cheng mdb_printf("Options:\n" 422da14cebeSEric Cheng "\t-u\tdisplay user defined link & vnic flows.\n" 423da14cebeSEric Cheng "\t-a\tdisplay flow attributes\n" 424da14cebeSEric Cheng "\t-p\tdisplay flow properties\n" 425da14cebeSEric Cheng "\t-r\tdisplay rx side information\n" 426da14cebeSEric Cheng "\t-t\tdisplay tx side information\n" 427da14cebeSEric Cheng "\t-s\tdisplay flow statistics\n" 428da14cebeSEric Cheng "\t-m\tdisplay miscellaneous flow information\n\n"); 429da14cebeSEric Cheng mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n"); 430da14cebeSEric Cheng mdb_printf("Flow Types:\n"); 431da14cebeSEric Cheng mdb_printf("\t P --> FLOW_PRIMARY_MAC\n"); 432da14cebeSEric Cheng mdb_printf("\t V --> FLOW_VNIC_MAC\n"); 433da14cebeSEric Cheng mdb_printf("\t M --> FLOW_MCAST\n"); 434da14cebeSEric Cheng mdb_printf("\t O --> FLOW_OTHER\n"); 435da14cebeSEric Cheng mdb_printf("\t U --> FLOW_USER\n"); 436da14cebeSEric Cheng mdb_printf("\t NS --> FLOW_NO_STATS\n\n"); 437da14cebeSEric Cheng mdb_printf("Flow Flags:\n"); 438da14cebeSEric Cheng mdb_printf("\t Q --> FE_QUIESCE\n"); 439da14cebeSEric Cheng mdb_printf("\t W --> FE_WAITER\n"); 440da14cebeSEric Cheng mdb_printf("\t T --> FE_FLOW_TAB\n"); 441da14cebeSEric Cheng mdb_printf("\t G --> FE_G_FLOW_HASH\n"); 442da14cebeSEric Cheng mdb_printf("\t I --> FE_INCIPIENT\n"); 443da14cebeSEric Cheng mdb_printf("\t C --> FE_CONDEMNED\n"); 444da14cebeSEric Cheng mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n"); 445da14cebeSEric Cheng mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n"); 446da14cebeSEric Cheng } 447da14cebeSEric Cheng 448da14cebeSEric Cheng /* 449da14cebeSEric Cheng * called once by the debugger when the mac_flow walk begins. 450da14cebeSEric Cheng */ 451da14cebeSEric Cheng static int 452da14cebeSEric Cheng mac_flow_walk_init(mdb_walk_state_t *wsp) 453da14cebeSEric Cheng { 454da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) { 455da14cebeSEric Cheng mdb_warn("failed to walk 'mac_flow'"); 456da14cebeSEric Cheng return (WALK_ERR); 457da14cebeSEric Cheng } 458da14cebeSEric Cheng return (WALK_NEXT); 459da14cebeSEric Cheng } 460da14cebeSEric Cheng 461da14cebeSEric Cheng /* 462da14cebeSEric Cheng * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and 463da14cebeSEric Cheng * mac_ring_t. 464da14cebeSEric Cheng * 465da14cebeSEric Cheng * Steps through each flow_entry_t and calls the callback function. If the 466da14cebeSEric Cheng * user executed ::walk mac_flow, it just prints the address or if the user 467da14cebeSEric Cheng * executed ::mac_flow it displays selected fields of flow_entry_t structure 468da14cebeSEric Cheng * by calling "mac_flow_dcmd" 469da14cebeSEric Cheng */ 470da14cebeSEric Cheng static int 471da14cebeSEric Cheng mac_common_walk_step(mdb_walk_state_t *wsp) 472da14cebeSEric Cheng { 473da14cebeSEric Cheng int status; 474da14cebeSEric Cheng 475*892ad162SToomas Soome if (wsp->walk_addr == 0) 476da14cebeSEric Cheng return (WALK_DONE); 477da14cebeSEric Cheng 478da14cebeSEric Cheng status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 479da14cebeSEric Cheng wsp->walk_cbdata); 480da14cebeSEric Cheng 481da14cebeSEric Cheng return (status); 482da14cebeSEric Cheng } 483da14cebeSEric Cheng 484da14cebeSEric Cheng static char * 485da14cebeSEric Cheng mac_srs_txmode2str(mac_tx_srs_mode_t mode) 486da14cebeSEric Cheng { 487da14cebeSEric Cheng switch (mode) { 488da14cebeSEric Cheng case SRS_TX_DEFAULT: 4892ae51e79SGirish Moodalbail return ("DEF"); 490da14cebeSEric Cheng case SRS_TX_SERIALIZE: 4912ae51e79SGirish Moodalbail return ("SER"); 492da14cebeSEric Cheng case SRS_TX_FANOUT: 4932ae51e79SGirish Moodalbail return ("FO"); 494da14cebeSEric Cheng case SRS_TX_BW: 4952ae51e79SGirish Moodalbail return ("BW"); 496da14cebeSEric Cheng case SRS_TX_BW_FANOUT: 4972ae51e79SGirish Moodalbail return ("BWFO"); 4980dc2366fSVenugopal Iyer case SRS_TX_AGGR: 4990dc2366fSVenugopal Iyer return ("AG"); 5000dc2366fSVenugopal Iyer case SRS_TX_BW_AGGR: 5010dc2366fSVenugopal Iyer return ("BWAG"); 502da14cebeSEric Cheng } 503da14cebeSEric Cheng return ("--"); 504da14cebeSEric Cheng } 505da14cebeSEric Cheng 506da14cebeSEric Cheng static void 507da14cebeSEric Cheng mac_srs_help(void) 508da14cebeSEric Cheng { 509da14cebeSEric Cheng mdb_printf("If an address is specified, then mac_soft_ring_set " 510da14cebeSEric Cheng "structure at that address is printed. Otherwise all the " 511da14cebeSEric Cheng "SRS in the system are printed.\n"); 512da14cebeSEric Cheng mdb_printf("Options:\n" 513da14cebeSEric Cheng "\t-r\tdisplay recieve side SRS structures\n" 5142ae51e79SGirish Moodalbail "\t-t\tdisplay transmit side SRS structures\n" 5152ae51e79SGirish Moodalbail "\t-s\tdisplay statistics for RX or TX side\n" 5162ae51e79SGirish Moodalbail "\t-c\tdisplay CPU binding for RX or TX side\n" 5172ae51e79SGirish Moodalbail "\t-v\tverbose flag for CPU binding to list cpus\n" 5180dc2366fSVenugopal Iyer "\t-i\tdisplay mac_ring_t and interrupt information\n" 5192ae51e79SGirish Moodalbail "Note: use -r or -t (to specify RX or TX side respectively) along " 5202ae51e79SGirish Moodalbail "with -c or -s\n"); 5212ae51e79SGirish Moodalbail mdb_printf("\n%<u>Interpreting TX Modes%</u>\n"); 5222ae51e79SGirish Moodalbail mdb_printf("\t DEF --> Default\n"); 5232ae51e79SGirish Moodalbail mdb_printf("\t SER --> Serialize\n"); 5242ae51e79SGirish Moodalbail mdb_printf("\t FO --> Fanout\n"); 5252ae51e79SGirish Moodalbail mdb_printf("\t BW --> Bandwidth\n"); 5262ae51e79SGirish Moodalbail mdb_printf("\tBWFO --> Bandwidth Fanout\n"); 5270dc2366fSVenugopal Iyer mdb_printf("\t AG --> Aggr\n"); 5280dc2366fSVenugopal Iyer mdb_printf("\tBWAG --> Bandwidth Aggr\n"); 5292ae51e79SGirish Moodalbail } 5302ae51e79SGirish Moodalbail 5312ae51e79SGirish Moodalbail /* 5322ae51e79SGirish Moodalbail * In verbose mode "::mac_srs -rcv or ::mac_srs -tcv", we print the CPUs 5332ae51e79SGirish Moodalbail * assigned to a link and CPUS assigned to the soft rings. 5342ae51e79SGirish Moodalbail * 'len' is used for formatting the output and represents the number of 5352ae51e79SGirish Moodalbail * spaces between CPU list and Fanout CPU list in the output. 5362ae51e79SGirish Moodalbail */ 5372ae51e79SGirish Moodalbail static boolean_t 5382ae51e79SGirish Moodalbail mac_srs_print_cpu(int *i, uint32_t cnt, uint32_t *cpu_list, int *len) 5392ae51e79SGirish Moodalbail { 5402ae51e79SGirish Moodalbail int num = 0; 5412ae51e79SGirish Moodalbail 5422ae51e79SGirish Moodalbail if (*i == 0) 5432ae51e79SGirish Moodalbail mdb_printf("("); 5442ae51e79SGirish Moodalbail else 5452ae51e79SGirish Moodalbail mdb_printf(" "); 5462ae51e79SGirish Moodalbail while (*i < cnt) { 5472ae51e79SGirish Moodalbail /* We print 6 CPU's at a time to keep display within 80 cols */ 5482ae51e79SGirish Moodalbail if (((num + 1) % 7) == 0) { 5492ae51e79SGirish Moodalbail if (len != NULL) 5502ae51e79SGirish Moodalbail *len = 2; 5512ae51e79SGirish Moodalbail return (B_FALSE); 5522ae51e79SGirish Moodalbail } 5532ae51e79SGirish Moodalbail mdb_printf("%02x%c", cpu_list[*i], ((*i == cnt - 1)?')':',')); 5542ae51e79SGirish Moodalbail ++*i; 5552ae51e79SGirish Moodalbail ++num; 5562ae51e79SGirish Moodalbail } 5572ae51e79SGirish Moodalbail if (len != NULL) 5582ae51e79SGirish Moodalbail *len = (7 - num) * 3; 5592ae51e79SGirish Moodalbail return (B_TRUE); 560da14cebeSEric Cheng } 561da14cebeSEric Cheng 562da14cebeSEric Cheng static int 563da14cebeSEric Cheng mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 564da14cebeSEric Cheng { 5652ae51e79SGirish Moodalbail uint_t args = MAC_SRS_NONE; 566da14cebeSEric Cheng mac_soft_ring_set_t srs; 5672ae51e79SGirish Moodalbail mac_client_impl_t mci; 568da14cebeSEric Cheng 569da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) { 570da14cebeSEric Cheng if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) { 571da14cebeSEric Cheng mdb_warn("failed to walk 'mac_srs'"); 572da14cebeSEric Cheng return (DCMD_ERR); 573da14cebeSEric Cheng } 574da14cebeSEric Cheng return (DCMD_OK); 575da14cebeSEric Cheng } 5762ae51e79SGirish Moodalbail if (mdb_getopts(argc, argv, 577da14cebeSEric Cheng 'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args, 5782ae51e79SGirish Moodalbail 't', MDB_OPT_SETBITS, MAC_SRS_TX, &args, 5792ae51e79SGirish Moodalbail 'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args, 5802ae51e79SGirish Moodalbail 'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args, 5810dc2366fSVenugopal Iyer 'i', MDB_OPT_SETBITS, MAC_SRS_INTR, &args, 582d47ced1fSRobert Mustacchi 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args, 583d47ced1fSRobert Mustacchi NULL) != argc) { 584da14cebeSEric Cheng return (DCMD_USAGE); 585da14cebeSEric Cheng } 5862ae51e79SGirish Moodalbail 5872ae51e79SGirish Moodalbail if (argc > 2) 588da14cebeSEric Cheng return (DCMD_USAGE); 589da14cebeSEric Cheng 590da14cebeSEric Cheng if (mdb_vread(&srs, sizeof (srs), addr) == -1) { 591da14cebeSEric Cheng mdb_warn("failed to read struct mac_soft_ring_set_s at %p", 592da14cebeSEric Cheng addr); 593da14cebeSEric Cheng return (DCMD_ERR); 594da14cebeSEric Cheng } 5952ae51e79SGirish Moodalbail if (mdb_vread(&mci, sizeof (mci), (uintptr_t)srs.srs_mcip) == -1) { 5962ae51e79SGirish Moodalbail mdb_warn("failed to read struct mac_client_impl_t at %p " 5972ae51e79SGirish Moodalbail "for SRS %p", srs.srs_mcip, addr); 5982ae51e79SGirish Moodalbail return (DCMD_ERR); 5992ae51e79SGirish Moodalbail } 600da14cebeSEric Cheng 601da14cebeSEric Cheng switch (args) { 602da14cebeSEric Cheng case MAC_SRS_RX: { 603da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 604fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %-8s %-8s %8s " 605fcff38ebSGirish Moodalbail "%8s %3s\n", 6062ae51e79SGirish Moodalbail "", "", "", "", "MBLK", 6072ae51e79SGirish Moodalbail "Q", "SR"); 608fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %-8s %-8s %8s " 609fcff38ebSGirish Moodalbail "%8s %3s%</u>\n", 6102ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "STATE", "TYPE", "CNT", 6112ae51e79SGirish Moodalbail "BYTES", "CNT"); 612da14cebeSEric Cheng } 613da14cebeSEric Cheng if (srs.srs_type & SRST_TX) 614da14cebeSEric Cheng return (DCMD_OK); 6152ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %08x %08x " 616fcff38ebSGirish Moodalbail "%8d %8d %3d\n", 6172ae51e79SGirish Moodalbail addr, mci.mci_name, srs.srs_state, srs.srs_type, 6182ae51e79SGirish Moodalbail srs.srs_count, srs.srs_size, srs.srs_soft_ring_count); 619da14cebeSEric Cheng break; 620da14cebeSEric Cheng } 621da14cebeSEric Cheng case MAC_SRS_TX: { 622da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 6232ae51e79SGirish Moodalbail mdb_printf("%?s %-16s %-4s %-8s " 624fcff38ebSGirish Moodalbail "%-8s %8s %8s %3s\n", 6252ae51e79SGirish Moodalbail "", "", "TX", "", 6262ae51e79SGirish Moodalbail "", "MBLK", "Q", "SR"); 6272ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-16s %-4s %-8s " 628fcff38ebSGirish Moodalbail "%-8s %8s %8s %3s%</u>\n", 6292ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "MODE", "STATE", 6302ae51e79SGirish Moodalbail "TYPE", "CNT", "BYTES", "CNT"); 631da14cebeSEric Cheng } 632da14cebeSEric Cheng if (!(srs.srs_type & SRST_TX)) 633da14cebeSEric Cheng return (DCMD_OK); 634da14cebeSEric Cheng 6352ae51e79SGirish Moodalbail mdb_printf("%?p %-16s %-4s " 636fcff38ebSGirish Moodalbail "%08x %08x %8d %8d %3d\n", 6372ae51e79SGirish Moodalbail addr, mci.mci_name, mac_srs_txmode2str(srs.srs_tx.st_mode), 6382ae51e79SGirish Moodalbail srs.srs_state, srs.srs_type, srs.srs_count, srs.srs_size, 6390dc2366fSVenugopal Iyer srs.srs_tx_ring_count); 640da14cebeSEric Cheng break; 641da14cebeSEric Cheng } 6422ae51e79SGirish Moodalbail case MAC_SRS_RXCPU: { 6432ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu; 6442ae51e79SGirish Moodalbail 645da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 6462ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-4s %-4s " 6472ae51e79SGirish Moodalbail "%-6s %-4s %-7s\n", 6482ae51e79SGirish Moodalbail "", "", "NUM", "POLL", 6492ae51e79SGirish Moodalbail "WORKER", "INTR", "FANOUT"); 6502ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %-4s %-4s " 6512ae51e79SGirish Moodalbail "%-6s %-4s %-7s%</u>\n", 6522ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "CPUS", "CPU", 6532ae51e79SGirish Moodalbail "CPU", "CPU", "CPU_CNT"); 654da14cebeSEric Cheng } 6552ae51e79SGirish Moodalbail if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)) 6562ae51e79SGirish Moodalbail return (DCMD_OK); 6572ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-4d %-4d " 6582ae51e79SGirish Moodalbail "%-6d %-4d %-7d\n", 6590dc2366fSVenugopal Iyer addr, mci.mci_name, mc.mc_ncpus, mc.mc_rx_pollid, 6600dc2366fSVenugopal Iyer mc.mc_rx_workerid, mc.mc_rx_intr_cpu, mc.mc_rx_fanout_cnt); 6612ae51e79SGirish Moodalbail break; 6622ae51e79SGirish Moodalbail 6632ae51e79SGirish Moodalbail } 6642ae51e79SGirish Moodalbail case MAC_SRS_TXCPU: { 6652ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu; 6660dc2366fSVenugopal Iyer mac_soft_ring_t *s_ringp, s_ring; 6670dc2366fSVenugopal Iyer boolean_t first = B_TRUE; 6680dc2366fSVenugopal Iyer int i; 6692ae51e79SGirish Moodalbail 6702ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 6710dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?s %8s %8s %8s\n", 6720dc2366fSVenugopal Iyer "", "", "SOFT", "WORKER", "INTR", "RETARGETED"); 6730dc2366fSVenugopal Iyer mdb_printf("%<u>%?s %-12s %?s %8s %8s %8s%</u>\n", 6740dc2366fSVenugopal Iyer "ADDR", "LINK_NAME", "RING", "CPU", "CPU", "CPU"); 6752ae51e79SGirish Moodalbail } 6760dc2366fSVenugopal Iyer if (!(srs.srs_type & SRST_TX)) 6772ae51e79SGirish Moodalbail return (DCMD_OK); 6780dc2366fSVenugopal Iyer 6790dc2366fSVenugopal Iyer mdb_printf("%?p %-12s ", addr, mci.mci_name); 6800dc2366fSVenugopal Iyer 6810dc2366fSVenugopal Iyer /* 6820dc2366fSVenugopal Iyer * Case of no soft rings, print the info from 6830dc2366fSVenugopal Iyer * mac_srs_tx_t. 6840dc2366fSVenugopal Iyer */ 6850dc2366fSVenugopal Iyer if (srs.srs_tx_ring_count == 0) { 6860dc2366fSVenugopal Iyer mdb_printf("%?p %8d %8d %8d\n", 6870dc2366fSVenugopal Iyer 0, mc.mc_tx_fanout_cpus[0], 6880dc2366fSVenugopal Iyer mc.mc_tx_intr_cpu[0], 6890dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[0]); 6900dc2366fSVenugopal Iyer break; 6910dc2366fSVenugopal Iyer } 6920dc2366fSVenugopal Iyer 6930dc2366fSVenugopal Iyer for (s_ringp = srs.srs_soft_ring_head, i = 0; s_ringp != NULL; 6940dc2366fSVenugopal Iyer s_ringp = s_ring.s_ring_next, i++) { 6950dc2366fSVenugopal Iyer (void) mdb_vread(&s_ring, sizeof (s_ring), 6960dc2366fSVenugopal Iyer (uintptr_t)s_ringp); 6970dc2366fSVenugopal Iyer if (first) { 6980dc2366fSVenugopal Iyer mdb_printf("%?p %8d %8d %8d\n", 6990dc2366fSVenugopal Iyer s_ringp, mc.mc_tx_fanout_cpus[i], 7000dc2366fSVenugopal Iyer mc.mc_tx_intr_cpu[i], 7010dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[i]); 7020dc2366fSVenugopal Iyer first = B_FALSE; 7030dc2366fSVenugopal Iyer continue; 7040dc2366fSVenugopal Iyer } 7050dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?p %8d %8d %8d\n", 7060dc2366fSVenugopal Iyer "", "", s_ringp, mc.mc_tx_fanout_cpus[i], 7070dc2366fSVenugopal Iyer mc.mc_tx_intr_cpu[i], mc.mc_tx_retargeted_cpu[i]); 7080dc2366fSVenugopal Iyer } 7090dc2366fSVenugopal Iyer break; 7100dc2366fSVenugopal Iyer } 7110dc2366fSVenugopal Iyer case MAC_SRS_TXINTR: { 7120dc2366fSVenugopal Iyer mac_cpus_t mc = srs.srs_cpu; 7130dc2366fSVenugopal Iyer mac_soft_ring_t *s_ringp, s_ring; 7140dc2366fSVenugopal Iyer mac_ring_t *m_ringp, m_ring; 7150dc2366fSVenugopal Iyer boolean_t first = B_TRUE; 7160dc2366fSVenugopal Iyer int i; 7170dc2366fSVenugopal Iyer 7180dc2366fSVenugopal Iyer if (DCMD_HDRSPEC(flags)) { 7190dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?s %8s %?s %6s %6s\n", 7200dc2366fSVenugopal Iyer "", "", "SOFT", "WORKER", "MAC", "", "INTR"); 7210dc2366fSVenugopal Iyer mdb_printf("%<u>%?s %-12s %?s %8s %?s %6s %6s%</u>\n", 7220dc2366fSVenugopal Iyer "ADDR", "LINK_NAME", "RING", "CPU", "RING", 7230dc2366fSVenugopal Iyer "SHARED", "CPU"); 7240dc2366fSVenugopal Iyer } 7250dc2366fSVenugopal Iyer if (!(srs.srs_type & SRST_TX)) 7260dc2366fSVenugopal Iyer return (DCMD_OK); 7270dc2366fSVenugopal Iyer 7280dc2366fSVenugopal Iyer mdb_printf("%?p %-12s ", addr, mci.mci_name); 7290dc2366fSVenugopal Iyer 7300dc2366fSVenugopal Iyer /* 7310dc2366fSVenugopal Iyer * Case of no soft rings, print the info from 7320dc2366fSVenugopal Iyer * mac_srs_tx_t. 7330dc2366fSVenugopal Iyer */ 7340dc2366fSVenugopal Iyer if (srs.srs_tx_ring_count == 0) { 7350dc2366fSVenugopal Iyer m_ringp = srs.srs_tx.st_arg2; 7360dc2366fSVenugopal Iyer if (m_ringp != NULL) { 7370dc2366fSVenugopal Iyer (void) mdb_vread(&m_ring, sizeof (m_ring), 7380dc2366fSVenugopal Iyer (uintptr_t)m_ringp); 7390dc2366fSVenugopal Iyer mdb_printf("%?p %8d %?p %6d %6d\n", 7400dc2366fSVenugopal Iyer 0, mc.mc_tx_fanout_cpus[0], m_ringp, 7410dc2366fSVenugopal Iyer m_ring.mr_info.mri_intr.mi_ddi_shared, 7420dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[0]); 7430dc2366fSVenugopal Iyer } else { 7440dc2366fSVenugopal Iyer mdb_printf("%?p %8d %?p %6d %6d\n", 7450dc2366fSVenugopal Iyer 0, mc.mc_tx_fanout_cpus[0], 0, 7460dc2366fSVenugopal Iyer 0, mc.mc_tx_retargeted_cpu[0]); 7470dc2366fSVenugopal Iyer } 7480dc2366fSVenugopal Iyer break; 7490dc2366fSVenugopal Iyer } 7500dc2366fSVenugopal Iyer 7510dc2366fSVenugopal Iyer for (s_ringp = srs.srs_soft_ring_head, i = 0; s_ringp != NULL; 7520dc2366fSVenugopal Iyer s_ringp = s_ring.s_ring_next, i++) { 7530dc2366fSVenugopal Iyer (void) mdb_vread(&s_ring, sizeof (s_ring), 7540dc2366fSVenugopal Iyer (uintptr_t)s_ringp); 7550dc2366fSVenugopal Iyer m_ringp = s_ring.s_ring_tx_arg2; 7560dc2366fSVenugopal Iyer (void) mdb_vread(&m_ring, sizeof (m_ring), 7570dc2366fSVenugopal Iyer (uintptr_t)m_ringp); 7580dc2366fSVenugopal Iyer if (first) { 7590dc2366fSVenugopal Iyer mdb_printf("%?p %8d %?p %6d %6d\n", 7600dc2366fSVenugopal Iyer s_ringp, mc.mc_tx_fanout_cpus[i], 7610dc2366fSVenugopal Iyer m_ringp, 7620dc2366fSVenugopal Iyer m_ring.mr_info.mri_intr.mi_ddi_shared, 7630dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[i]); 7640dc2366fSVenugopal Iyer first = B_FALSE; 7650dc2366fSVenugopal Iyer continue; 7660dc2366fSVenugopal Iyer } 7670dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?p %8d %?p %6d %6d\n", 7680dc2366fSVenugopal Iyer "", "", s_ringp, mc.mc_tx_fanout_cpus[i], 7690dc2366fSVenugopal Iyer m_ringp, m_ring.mr_info.mri_intr.mi_ddi_shared, 7700dc2366fSVenugopal Iyer mc.mc_tx_retargeted_cpu[i]); 7710dc2366fSVenugopal Iyer } 7720dc2366fSVenugopal Iyer break; 7730dc2366fSVenugopal Iyer } 7740dc2366fSVenugopal Iyer case MAC_SRS_RXINTR: { 7750dc2366fSVenugopal Iyer mac_cpus_t mc = srs.srs_cpu; 7760dc2366fSVenugopal Iyer mac_ring_t *m_ringp, m_ring; 7770dc2366fSVenugopal Iyer 7780dc2366fSVenugopal Iyer if (DCMD_HDRSPEC(flags)) { 7790dc2366fSVenugopal Iyer mdb_printf("%?s %-12s %?s %8s %6s %6s\n", 7800dc2366fSVenugopal Iyer "", "", "MAC", "", "POLL", "INTR"); 7810dc2366fSVenugopal Iyer mdb_printf("%<u>%?s %-12s %?s %8s %6s %6s%</u>\n", 7820dc2366fSVenugopal Iyer "ADDR", "LINK_NAME", "RING", "SHARED", "CPU", 7830dc2366fSVenugopal Iyer "CPU"); 7840dc2366fSVenugopal Iyer } 7850dc2366fSVenugopal Iyer if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)) 7860dc2366fSVenugopal Iyer return (DCMD_OK); 7870dc2366fSVenugopal Iyer 7880dc2366fSVenugopal Iyer mdb_printf("%?p %-12s ", addr, mci.mci_name); 7890dc2366fSVenugopal Iyer 7900dc2366fSVenugopal Iyer m_ringp = srs.srs_ring; 7910dc2366fSVenugopal Iyer if (m_ringp != NULL) { 7920dc2366fSVenugopal Iyer (void) mdb_vread(&m_ring, sizeof (m_ring), 7930dc2366fSVenugopal Iyer (uintptr_t)m_ringp); 7940dc2366fSVenugopal Iyer mdb_printf("%?p %8d %6d %6d\n", 7950dc2366fSVenugopal Iyer m_ringp, m_ring.mr_info.mri_intr.mi_ddi_shared, 7960dc2366fSVenugopal Iyer mc.mc_rx_pollid, mc.mc_rx_intr_cpu); 7970dc2366fSVenugopal Iyer } else { 7980dc2366fSVenugopal Iyer mdb_printf("%?p %8d %6d %6d\n", 7990dc2366fSVenugopal Iyer 0, 0, mc.mc_rx_pollid, mc.mc_rx_intr_cpu); 8000dc2366fSVenugopal Iyer } 801da14cebeSEric Cheng break; 802da14cebeSEric Cheng } 8032ae51e79SGirish Moodalbail case MAC_SRS_RXCPUVERBOSE: 8042ae51e79SGirish Moodalbail case MAC_SRS_TXCPUVERBOSE: { 8052ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu; 8062ae51e79SGirish Moodalbail int cpu_index = 0, fanout_index = 0, len = 0; 8072ae51e79SGirish Moodalbail boolean_t cpu_done = B_FALSE, fanout_done = B_FALSE; 8082ae51e79SGirish Moodalbail 8092ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 8102ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-20s %-20s\n", 8112ae51e79SGirish Moodalbail "", "", "CPU_COUNT", "FANOUT_CPU_COUNT"); 8122ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s " 8132ae51e79SGirish Moodalbail "%-20s %-20s%</u>\n", 8142ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", 8152ae51e79SGirish Moodalbail "(CPU_LIST)", "(CPU_LIST)"); 8162ae51e79SGirish Moodalbail } 8172ae51e79SGirish Moodalbail if (((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) || 8182ae51e79SGirish Moodalbail ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))) 8192ae51e79SGirish Moodalbail return (DCMD_OK); 8202ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-20d %-20d\n", addr, mci.mci_name, 8210dc2366fSVenugopal Iyer mc.mc_ncpus, mc.mc_rx_fanout_cnt); 8220dc2366fSVenugopal Iyer if (mc.mc_ncpus == 0 && mc.mc_rx_fanout_cnt == 0) 8232ae51e79SGirish Moodalbail break; 8242ae51e79SGirish Moodalbail /* print all cpus and cpus for soft rings */ 8252ae51e79SGirish Moodalbail while (!cpu_done || !fanout_done) { 8262ae51e79SGirish Moodalbail boolean_t old_value = cpu_done; 8272ae51e79SGirish Moodalbail 8282ae51e79SGirish Moodalbail if (!cpu_done) { 8292ae51e79SGirish Moodalbail mdb_printf("%?s %20s ", "", ""); 8302ae51e79SGirish Moodalbail cpu_done = mac_srs_print_cpu(&cpu_index, 8312ae51e79SGirish Moodalbail mc.mc_ncpus, mc.mc_cpus, &len); 8322ae51e79SGirish Moodalbail } 8332ae51e79SGirish Moodalbail if (!fanout_done) { 8342ae51e79SGirish Moodalbail if (old_value) 8352ae51e79SGirish Moodalbail mdb_printf("%?s %-40s", "", ""); 8362ae51e79SGirish Moodalbail else 8372ae51e79SGirish Moodalbail mdb_printf("%*s", len, ""); 8382ae51e79SGirish Moodalbail fanout_done = mac_srs_print_cpu(&fanout_index, 8390dc2366fSVenugopal Iyer mc.mc_rx_fanout_cnt, 8400dc2366fSVenugopal Iyer mc.mc_rx_fanout_cpus, NULL); 8412ae51e79SGirish Moodalbail } 8422ae51e79SGirish Moodalbail mdb_printf("\n"); 8432ae51e79SGirish Moodalbail } 8442ae51e79SGirish Moodalbail break; 8452ae51e79SGirish Moodalbail } 8462ae51e79SGirish Moodalbail case MAC_SRS_RXSTAT: { 8470dc2366fSVenugopal Iyer mac_rx_stats_t *mac_rx_stat = &srs.srs_rx.sr_stat; 8482ae51e79SGirish Moodalbail 8492ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 850fcff38ebSGirish Moodalbail mdb_printf("%?s %-16s %8s %8s " 851fcff38ebSGirish Moodalbail "%8s %8s %8s\n", 8522ae51e79SGirish Moodalbail "", "", "INTR", "POLL", 8532ae51e79SGirish Moodalbail "CHAIN", "CHAIN", "CHAIN"); 854fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-16s %8s %8s " 855fcff38ebSGirish Moodalbail "%8s %8s %8s%</u>\n", 8562ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "COUNT", "COUNT", 8572ae51e79SGirish Moodalbail "<10", "10-50", ">50"); 8582ae51e79SGirish Moodalbail } 8592ae51e79SGirish Moodalbail if (srs.srs_type & SRST_TX) 8602ae51e79SGirish Moodalbail return (DCMD_OK); 861fcff38ebSGirish Moodalbail mdb_printf("%?p %-16s %8d " 862fcff38ebSGirish Moodalbail "%8d %8d " 863fcff38ebSGirish Moodalbail "%8d %8d\n", 8640dc2366fSVenugopal Iyer addr, mci.mci_name, mac_rx_stat->mrs_intrcnt, 8650dc2366fSVenugopal Iyer mac_rx_stat->mrs_pollcnt, mac_rx_stat->mrs_chaincntundr10, 8660dc2366fSVenugopal Iyer mac_rx_stat->mrs_chaincnt10to50, 8670dc2366fSVenugopal Iyer mac_rx_stat->mrs_chaincntover50); 8682ae51e79SGirish Moodalbail break; 8692ae51e79SGirish Moodalbail } 8702ae51e79SGirish Moodalbail case MAC_SRS_TXSTAT: { 8710dc2366fSVenugopal Iyer mac_tx_stats_t *mac_tx_stat = &srs.srs_tx.st_stat; 872fcff38ebSGirish Moodalbail mac_soft_ring_t *s_ringp, s_ring; 873fcff38ebSGirish Moodalbail boolean_t first = B_TRUE; 8742ae51e79SGirish Moodalbail 8752ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 876fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %?s %8s %8s %8s\n", 877fcff38ebSGirish Moodalbail "", "", "SOFT", "DROP", "BLOCK", "UNBLOCK"); 878fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %?s %8s %8s %8s%</u>\n", 879fcff38ebSGirish Moodalbail "ADDR", "LINK_NAME", "RING", "COUNT", "COUNT", 880fcff38ebSGirish Moodalbail "COUNT"); 8812ae51e79SGirish Moodalbail } 8822ae51e79SGirish Moodalbail if (!(srs.srs_type & SRST_TX)) 8832ae51e79SGirish Moodalbail return (DCMD_OK); 8842ae51e79SGirish Moodalbail 885fcff38ebSGirish Moodalbail mdb_printf("%?p %-20s ", addr, mci.mci_name); 886fcff38ebSGirish Moodalbail 887fcff38ebSGirish Moodalbail /* 888fcff38ebSGirish Moodalbail * Case of no soft rings, print the info from 889fcff38ebSGirish Moodalbail * mac_srs_tx_t. 890fcff38ebSGirish Moodalbail */ 8910dc2366fSVenugopal Iyer if (srs.srs_tx_ring_count == 0) { 892fcff38ebSGirish Moodalbail mdb_printf("%?p %8d %8d %8d\n", 8930dc2366fSVenugopal Iyer 0, mac_tx_stat->mts_sdrops, 8940dc2366fSVenugopal Iyer mac_tx_stat->mts_blockcnt, 8950dc2366fSVenugopal Iyer mac_tx_stat->mts_unblockcnt); 896fcff38ebSGirish Moodalbail break; 897fcff38ebSGirish Moodalbail } 898fcff38ebSGirish Moodalbail 899fcff38ebSGirish Moodalbail for (s_ringp = srs.srs_soft_ring_head; s_ringp != NULL; 900fcff38ebSGirish Moodalbail s_ringp = s_ring.s_ring_next) { 901fcff38ebSGirish Moodalbail (void) mdb_vread(&s_ring, sizeof (s_ring), 902fcff38ebSGirish Moodalbail (uintptr_t)s_ringp); 9030dc2366fSVenugopal Iyer mac_tx_stat = &s_ring.s_st_stat; 904fcff38ebSGirish Moodalbail if (first) { 905fcff38ebSGirish Moodalbail mdb_printf("%?p %8d %8d %8d\n", 9060dc2366fSVenugopal Iyer s_ringp, mac_tx_stat->mts_sdrops, 9070dc2366fSVenugopal Iyer mac_tx_stat->mts_blockcnt, 9080dc2366fSVenugopal Iyer mac_tx_stat->mts_unblockcnt); 909fcff38ebSGirish Moodalbail first = B_FALSE; 910fcff38ebSGirish Moodalbail continue; 911fcff38ebSGirish Moodalbail } 912fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %?p %8d %8d %8d\n", 9130dc2366fSVenugopal Iyer "", "", s_ringp, mac_tx_stat->mts_sdrops, 9140dc2366fSVenugopal Iyer mac_tx_stat->mts_blockcnt, 9150dc2366fSVenugopal Iyer mac_tx_stat->mts_unblockcnt); 916fcff38ebSGirish Moodalbail } 9172ae51e79SGirish Moodalbail break; 9182ae51e79SGirish Moodalbail } 9192ae51e79SGirish Moodalbail case MAC_SRS_NONE: { 9202ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 9212ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %?s %?s %-3s%</u>\n", 9222ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "FLENT", "HW RING", "DIR"); 9232ae51e79SGirish Moodalbail } 9242ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %?p %?p " 9252ae51e79SGirish Moodalbail "%-3s ", 9262ae51e79SGirish Moodalbail addr, mci.mci_name, srs.srs_flent, srs.srs_ring, 9272ae51e79SGirish Moodalbail (srs.srs_type & SRST_TX ? "TX" : "RX")); 9282ae51e79SGirish Moodalbail break; 9292ae51e79SGirish Moodalbail } 9302ae51e79SGirish Moodalbail default: 9312ae51e79SGirish Moodalbail return (DCMD_USAGE); 932da14cebeSEric Cheng } 933da14cebeSEric Cheng return (DCMD_OK); 934da14cebeSEric Cheng } 935da14cebeSEric Cheng 936da14cebeSEric Cheng static int 937da14cebeSEric Cheng mac_srs_walk_init(mdb_walk_state_t *wsp) 938da14cebeSEric Cheng { 939da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) { 940da14cebeSEric Cheng mdb_warn("failed to walk 'mac_srs'"); 941da14cebeSEric Cheng return (WALK_ERR); 942da14cebeSEric Cheng } 943da14cebeSEric Cheng return (WALK_NEXT); 944da14cebeSEric Cheng } 945da14cebeSEric Cheng 946da14cebeSEric Cheng static char * 947da14cebeSEric Cheng mac_ring_state2str(mac_ring_state_t state) 948da14cebeSEric Cheng { 949da14cebeSEric Cheng switch (state) { 950da14cebeSEric Cheng case MR_FREE: 951da14cebeSEric Cheng return ("free"); 952da14cebeSEric Cheng case MR_NEWLY_ADDED: 953da14cebeSEric Cheng return ("new"); 954da14cebeSEric Cheng case MR_INUSE: 955da14cebeSEric Cheng return ("inuse"); 956da14cebeSEric Cheng } 957da14cebeSEric Cheng return ("--"); 958da14cebeSEric Cheng } 959da14cebeSEric Cheng 960da14cebeSEric Cheng static char * 961da14cebeSEric Cheng mac_ring_classify2str(mac_classify_type_t classify) 962da14cebeSEric Cheng { 963da14cebeSEric Cheng switch (classify) { 964da14cebeSEric Cheng case MAC_NO_CLASSIFIER: 965da14cebeSEric Cheng return ("no"); 966da14cebeSEric Cheng case MAC_SW_CLASSIFIER: 967da14cebeSEric Cheng return ("sw"); 968da14cebeSEric Cheng case MAC_HW_CLASSIFIER: 969da14cebeSEric Cheng return ("hw"); 970da14cebeSEric Cheng } 971da14cebeSEric Cheng return ("--"); 972da14cebeSEric Cheng } 973da14cebeSEric Cheng 974da14cebeSEric Cheng static int 975da14cebeSEric Cheng mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 976da14cebeSEric Cheng { 977da14cebeSEric Cheng mac_ring_t ring; 978da14cebeSEric Cheng mac_group_t group; 979da14cebeSEric Cheng flow_entry_t flent; 980da14cebeSEric Cheng mac_soft_ring_set_t srs; 981da14cebeSEric Cheng 982da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) { 983da14cebeSEric Cheng if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) { 984da14cebeSEric Cheng mdb_warn("failed to walk 'mac_ring'"); 985da14cebeSEric Cheng return (DCMD_ERR); 986da14cebeSEric Cheng } 987da14cebeSEric Cheng return (DCMD_OK); 988da14cebeSEric Cheng } 989da14cebeSEric Cheng if (mdb_vread(&ring, sizeof (ring), addr) == -1) { 990da14cebeSEric Cheng mdb_warn("failed to read struct mac_ring_s at %p", addr); 991da14cebeSEric Cheng return (DCMD_ERR); 992da14cebeSEric Cheng } 993da14cebeSEric Cheng bzero(&flent, sizeof (flent)); 994da14cebeSEric Cheng if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) { 995da14cebeSEric Cheng (void) mdb_vread(&flent, sizeof (flent), 996da14cebeSEric Cheng (uintptr_t)srs.srs_flent); 997da14cebeSEric Cheng } 998da14cebeSEric Cheng (void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh); 999da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 1000da14cebeSEric Cheng mdb_printf("%<u>%?s %4s %5s %4s %?s " 1001da14cebeSEric Cheng "%5s %?s %?s %s %</u>\n", 1002da14cebeSEric Cheng "ADDR", "TYPE", "STATE", "FLAG", "GROUP", 1003da14cebeSEric Cheng "CLASS", "MIP", "SRS", "FLOW NAME"); 1004da14cebeSEric Cheng } 1005da14cebeSEric Cheng mdb_printf("%?p %-4s " 1006da14cebeSEric Cheng "%5s %04x " 1007da14cebeSEric Cheng "%?p %-5s " 1008da14cebeSEric Cheng "%?p %?p %s\n", 1009da14cebeSEric Cheng addr, ((ring.mr_type == 1)? "RX" : "TX"), 1010da14cebeSEric Cheng mac_ring_state2str(ring.mr_state), ring.mr_flag, 1011da14cebeSEric Cheng ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type), 1012da14cebeSEric Cheng group.mrg_mh, ring.mr_srs, flent.fe_flow_name); 1013da14cebeSEric Cheng return (DCMD_OK); 1014da14cebeSEric Cheng } 1015da14cebeSEric Cheng 1016da14cebeSEric Cheng static int 1017da14cebeSEric Cheng mac_ring_walk_init(mdb_walk_state_t *wsp) 1018da14cebeSEric Cheng { 1019da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) { 1020da14cebeSEric Cheng mdb_warn("failed to walk `mac_ring`"); 1021da14cebeSEric Cheng return (WALK_ERR); 1022da14cebeSEric Cheng } 1023da14cebeSEric Cheng return (WALK_NEXT); 1024da14cebeSEric Cheng } 1025da14cebeSEric Cheng 1026da14cebeSEric Cheng static void 1027da14cebeSEric Cheng mac_ring_help(void) 1028da14cebeSEric Cheng { 1029da14cebeSEric Cheng mdb_printf("If an address is specified, then mac_ring_t " 1030da14cebeSEric Cheng "structure at that address is printed. Otherwise all the " 1031da14cebeSEric Cheng "hardware rings in the system are printed.\n"); 1032da14cebeSEric Cheng } 1033da14cebeSEric Cheng 1034d47ced1fSRobert Mustacchi /* 1035d47ced1fSRobert Mustacchi * To walk groups we have to have our own somewhat-complicated state machine. We 1036d47ced1fSRobert Mustacchi * basically start by walking the mac_impl_t walker as all groups are stored off 1037d47ced1fSRobert Mustacchi * of the various mac_impl_t in the system. The tx and rx rings are kept 1038d47ced1fSRobert Mustacchi * separately. So we'll need to walk through all the rx rings and then all of 1039d47ced1fSRobert Mustacchi * the tx rings. 1040d47ced1fSRobert Mustacchi */ 1041d47ced1fSRobert Mustacchi static int 1042d47ced1fSRobert Mustacchi mac_group_walk_init(mdb_walk_state_t *wsp) 1043d47ced1fSRobert Mustacchi { 1044d47ced1fSRobert Mustacchi int ret; 1045d47ced1fSRobert Mustacchi 1046*892ad162SToomas Soome if (wsp->walk_addr != 0) { 1047d47ced1fSRobert Mustacchi mdb_warn("non-global walks are not supported\n"); 1048d47ced1fSRobert Mustacchi return (WALK_ERR); 1049d47ced1fSRobert Mustacchi } 1050d47ced1fSRobert Mustacchi 1051d47ced1fSRobert Mustacchi if ((ret = mdb_layered_walk(LAYERED_WALKER_FOR_GROUP, wsp)) == -1) { 1052d47ced1fSRobert Mustacchi mdb_warn("couldn't walk '%s'", LAYERED_WALKER_FOR_GROUP); 1053d47ced1fSRobert Mustacchi return (ret); 1054d47ced1fSRobert Mustacchi } 1055d47ced1fSRobert Mustacchi 1056d47ced1fSRobert Mustacchi return (WALK_NEXT); 1057d47ced1fSRobert Mustacchi } 1058d47ced1fSRobert Mustacchi 1059d47ced1fSRobert Mustacchi static int 1060d47ced1fSRobert Mustacchi mac_group_walk_step(mdb_walk_state_t *wsp) 1061d47ced1fSRobert Mustacchi { 1062d47ced1fSRobert Mustacchi int ret; 1063d47ced1fSRobert Mustacchi mac_impl_t mi; 1064d47ced1fSRobert Mustacchi mac_group_t mg; 1065d47ced1fSRobert Mustacchi uintptr_t mgp; 1066d47ced1fSRobert Mustacchi 1067d47ced1fSRobert Mustacchi /* 1068d47ced1fSRobert Mustacchi * Nothing to do if we can't find the layer above us. But the kmem 1069d47ced1fSRobert Mustacchi * walkers are a bit unsporting, they don't actually read in the data 1070d47ced1fSRobert Mustacchi * for us. 1071d47ced1fSRobert Mustacchi */ 1072*892ad162SToomas Soome if (wsp->walk_addr == 0) 1073d47ced1fSRobert Mustacchi return (WALK_DONE); 1074d47ced1fSRobert Mustacchi 1075d47ced1fSRobert Mustacchi if (mdb_vread(&mi, sizeof (mac_impl_t), wsp->walk_addr) == -1) { 1076d47ced1fSRobert Mustacchi mdb_warn("failed to read mac_impl_t at %p", wsp->walk_addr); 1077d47ced1fSRobert Mustacchi return (DCMD_ERR); 1078d47ced1fSRobert Mustacchi } 1079d47ced1fSRobert Mustacchi 1080d47ced1fSRobert Mustacchi /* 1081d47ced1fSRobert Mustacchi * First go for rx groups, then tx groups. 1082d47ced1fSRobert Mustacchi */ 1083d47ced1fSRobert Mustacchi mgp = (uintptr_t)mi.mi_rx_groups; 1084*892ad162SToomas Soome while (mgp != 0) { 1085d47ced1fSRobert Mustacchi if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) { 1086d47ced1fSRobert Mustacchi mdb_warn("failed to read mac_group_t at %p", mgp); 1087d47ced1fSRobert Mustacchi return (WALK_ERR); 1088d47ced1fSRobert Mustacchi } 1089d47ced1fSRobert Mustacchi 1090d47ced1fSRobert Mustacchi ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata); 1091d47ced1fSRobert Mustacchi if (ret != WALK_NEXT) 1092d47ced1fSRobert Mustacchi return (ret); 1093d47ced1fSRobert Mustacchi mgp = (uintptr_t)mg.mrg_next; 1094d47ced1fSRobert Mustacchi } 1095d47ced1fSRobert Mustacchi 1096d47ced1fSRobert Mustacchi mgp = (uintptr_t)mi.mi_tx_groups; 1097*892ad162SToomas Soome while (mgp != 0) { 1098d47ced1fSRobert Mustacchi if (mdb_vread(&mg, sizeof (mac_group_t), mgp) == -1) { 1099d47ced1fSRobert Mustacchi mdb_warn("failed to read mac_group_t at %p", mgp); 1100d47ced1fSRobert Mustacchi return (WALK_ERR); 1101d47ced1fSRobert Mustacchi } 1102d47ced1fSRobert Mustacchi 1103d47ced1fSRobert Mustacchi ret = wsp->walk_callback(mgp, &mg, wsp->walk_cbdata); 1104d47ced1fSRobert Mustacchi if (ret != WALK_NEXT) 1105d47ced1fSRobert Mustacchi return (ret); 1106d47ced1fSRobert Mustacchi mgp = (uintptr_t)mg.mrg_next; 1107d47ced1fSRobert Mustacchi } 1108d47ced1fSRobert Mustacchi 1109d47ced1fSRobert Mustacchi return (WALK_NEXT); 1110d47ced1fSRobert Mustacchi } 1111d47ced1fSRobert Mustacchi 1112d47ced1fSRobert Mustacchi static int 1113d47ced1fSRobert Mustacchi mac_group_count_clients(mac_group_t *mgp) 1114d47ced1fSRobert Mustacchi { 1115d47ced1fSRobert Mustacchi int clients = 0; 1116d47ced1fSRobert Mustacchi uintptr_t mcp = (uintptr_t)mgp->mrg_clients; 1117d47ced1fSRobert Mustacchi 1118*892ad162SToomas Soome while (mcp != 0) { 1119d47ced1fSRobert Mustacchi mac_grp_client_t c; 1120d47ced1fSRobert Mustacchi 1121d47ced1fSRobert Mustacchi if (mdb_vread(&c, sizeof (c), mcp) == -1) { 1122d47ced1fSRobert Mustacchi mdb_warn("failed to read mac_grp_client_t at %p", mcp); 1123d47ced1fSRobert Mustacchi return (-1); 1124d47ced1fSRobert Mustacchi } 1125d47ced1fSRobert Mustacchi clients++; 1126d47ced1fSRobert Mustacchi mcp = (uintptr_t)c.mgc_next; 1127d47ced1fSRobert Mustacchi } 1128d47ced1fSRobert Mustacchi 1129d47ced1fSRobert Mustacchi return (clients); 1130d47ced1fSRobert Mustacchi } 1131d47ced1fSRobert Mustacchi 1132d47ced1fSRobert Mustacchi static const char * 1133d47ced1fSRobert Mustacchi mac_group_type(mac_group_t *mgp) 1134d47ced1fSRobert Mustacchi { 1135d47ced1fSRobert Mustacchi const char *ret; 1136d47ced1fSRobert Mustacchi 1137d47ced1fSRobert Mustacchi switch (mgp->mrg_type) { 1138d47ced1fSRobert Mustacchi case MAC_RING_TYPE_RX: 1139d47ced1fSRobert Mustacchi ret = "RECEIVE"; 1140d47ced1fSRobert Mustacchi break; 1141d47ced1fSRobert Mustacchi case MAC_RING_TYPE_TX: 1142d47ced1fSRobert Mustacchi ret = "TRANSMIT"; 1143d47ced1fSRobert Mustacchi break; 1144d47ced1fSRobert Mustacchi default: 1145d47ced1fSRobert Mustacchi ret = "UNKNOWN"; 1146d47ced1fSRobert Mustacchi break; 1147d47ced1fSRobert Mustacchi } 1148d47ced1fSRobert Mustacchi 1149d47ced1fSRobert Mustacchi return (ret); 1150d47ced1fSRobert Mustacchi } 1151d47ced1fSRobert Mustacchi 1152d47ced1fSRobert Mustacchi static const char * 1153d47ced1fSRobert Mustacchi mac_group_state(mac_group_t *mgp) 1154d47ced1fSRobert Mustacchi { 1155d47ced1fSRobert Mustacchi const char *ret; 1156d47ced1fSRobert Mustacchi 1157d47ced1fSRobert Mustacchi switch (mgp->mrg_state) { 1158d47ced1fSRobert Mustacchi case MAC_GROUP_STATE_UNINIT: 1159d47ced1fSRobert Mustacchi ret = "UNINT"; 1160d47ced1fSRobert Mustacchi break; 1161d47ced1fSRobert Mustacchi case MAC_GROUP_STATE_REGISTERED: 1162d47ced1fSRobert Mustacchi ret = "REGISTERED"; 1163d47ced1fSRobert Mustacchi break; 1164d47ced1fSRobert Mustacchi case MAC_GROUP_STATE_RESERVED: 1165d47ced1fSRobert Mustacchi ret = "RESERVED"; 1166d47ced1fSRobert Mustacchi break; 1167d47ced1fSRobert Mustacchi case MAC_GROUP_STATE_SHARED: 1168d47ced1fSRobert Mustacchi ret = "SHARED"; 1169d47ced1fSRobert Mustacchi break; 1170d47ced1fSRobert Mustacchi default: 1171d47ced1fSRobert Mustacchi ret = "UNKNOWN"; 1172d47ced1fSRobert Mustacchi break; 1173d47ced1fSRobert Mustacchi } 1174d47ced1fSRobert Mustacchi 1175d47ced1fSRobert Mustacchi return (ret); 1176d47ced1fSRobert Mustacchi } 1177d47ced1fSRobert Mustacchi 1178d47ced1fSRobert Mustacchi static int 1179d47ced1fSRobert Mustacchi mac_group_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1180d47ced1fSRobert Mustacchi { 1181d47ced1fSRobert Mustacchi uint_t args = MAC_SRS_NONE; 1182d47ced1fSRobert Mustacchi mac_group_t mg; 1183d47ced1fSRobert Mustacchi int clients; 1184d47ced1fSRobert Mustacchi 1185d47ced1fSRobert Mustacchi if (!(flags & DCMD_ADDRSPEC)) { 1186d47ced1fSRobert Mustacchi if (mdb_walk_dcmd("mac_group", "mac_group", argc, argv) == -1) { 1187d47ced1fSRobert Mustacchi mdb_warn("failed to walk 'mac_group'"); 1188d47ced1fSRobert Mustacchi return (DCMD_ERR); 1189d47ced1fSRobert Mustacchi } 1190d47ced1fSRobert Mustacchi 1191d47ced1fSRobert Mustacchi return (DCMD_OK); 1192d47ced1fSRobert Mustacchi } 1193d47ced1fSRobert Mustacchi 1194d47ced1fSRobert Mustacchi if (mdb_getopts(argc, argv, 1195d47ced1fSRobert Mustacchi 'r', MDB_OPT_SETBITS, MAC_GROUP_RX, &args, 1196d47ced1fSRobert Mustacchi 't', MDB_OPT_SETBITS, MAC_GROUP_TX, &args, 1197d47ced1fSRobert Mustacchi 'u', MDB_OPT_SETBITS, MAC_GROUP_UNINIT, &args, 1198d47ced1fSRobert Mustacchi NULL) != argc) 1199d47ced1fSRobert Mustacchi return (DCMD_USAGE); 1200d47ced1fSRobert Mustacchi 1201d47ced1fSRobert Mustacchi if (mdb_vread(&mg, sizeof (mac_group_t), addr) == -1) { 1202d47ced1fSRobert Mustacchi mdb_warn("failed to read mac_group_t at %p", addr); 1203d47ced1fSRobert Mustacchi return (DCMD_ERR); 1204d47ced1fSRobert Mustacchi } 1205d47ced1fSRobert Mustacchi 1206d47ced1fSRobert Mustacchi if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) { 1207d47ced1fSRobert Mustacchi mdb_printf("%<u>%-?s %-8s %-10s %6s %8s %-?s%</u>\n", 1208d47ced1fSRobert Mustacchi "ADDR", "TYPE", "STATE", "NRINGS", "NCLIENTS", "RINGS"); 1209d47ced1fSRobert Mustacchi } 1210d47ced1fSRobert Mustacchi 1211d47ced1fSRobert Mustacchi if ((args & MAC_GROUP_RX) != 0 && mg.mrg_type != MAC_RING_TYPE_RX) 1212d47ced1fSRobert Mustacchi return (DCMD_OK); 1213d47ced1fSRobert Mustacchi if ((args & MAC_GROUP_TX) != 0 && mg.mrg_type != MAC_RING_TYPE_TX) 1214d47ced1fSRobert Mustacchi return (DCMD_OK); 1215d47ced1fSRobert Mustacchi 1216d47ced1fSRobert Mustacchi /* 1217d47ced1fSRobert Mustacchi * By default, don't show uninitialized groups. They're not very 1218d47ced1fSRobert Mustacchi * interesting. They have no rings and no clients. 1219d47ced1fSRobert Mustacchi */ 1220d47ced1fSRobert Mustacchi if (mg.mrg_state == MAC_GROUP_STATE_UNINIT && 1221d47ced1fSRobert Mustacchi (args & MAC_GROUP_UNINIT) == 0) 1222d47ced1fSRobert Mustacchi return (DCMD_OK); 1223d47ced1fSRobert Mustacchi 1224d47ced1fSRobert Mustacchi if (flags & DCMD_PIPE_OUT) { 1225d47ced1fSRobert Mustacchi mdb_printf("%lr\n", addr); 1226d47ced1fSRobert Mustacchi return (DCMD_OK); 1227d47ced1fSRobert Mustacchi } 1228d47ced1fSRobert Mustacchi 1229d47ced1fSRobert Mustacchi clients = mac_group_count_clients(&mg); 1230d47ced1fSRobert Mustacchi mdb_printf("%?p %-8s %-10s %6d %8d %?p\n", addr, mac_group_type(&mg), 1231d47ced1fSRobert Mustacchi mac_group_state(&mg), mg.mrg_cur_count, clients, mg.mrg_rings); 1232d47ced1fSRobert Mustacchi 1233d47ced1fSRobert Mustacchi return (DCMD_OK); 1234d47ced1fSRobert Mustacchi } 1235d47ced1fSRobert Mustacchi 1236da14cebeSEric Cheng /* Supported dee-commands */ 1237da14cebeSEric Cheng static const mdb_dcmd_t dcmds[] = { 1238da14cebeSEric Cheng {"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures", 1239da14cebeSEric Cheng mac_flow_dcmd, mac_flow_help}, 1240d47ced1fSRobert Mustacchi {"mac_group", "?[-rtu]", "display MAC Ring Groups", mac_group_dcmd, 1241d47ced1fSRobert Mustacchi NULL }, 12420dc2366fSVenugopal Iyer {"mac_srs", "?[ -r[i|s|c[v]] | -t[i|s|c[v]] ]", 12430dc2366fSVenugopal Iyer "display MAC Soft Ring Set" " structures", mac_srs_dcmd, 12440dc2366fSVenugopal Iyer mac_srs_help}, 1245da14cebeSEric Cheng {"mac_ring", "?", "display MAC ring (hardware) structures", 1246da14cebeSEric Cheng mac_ring_dcmd, mac_ring_help}, 1247da14cebeSEric Cheng { NULL } 1248da14cebeSEric Cheng }; 1249da14cebeSEric Cheng 1250da14cebeSEric Cheng /* Supported walkers */ 1251da14cebeSEric Cheng static const mdb_walker_t walkers[] = { 1252da14cebeSEric Cheng {"mac_flow", "walk list of flow entry structures", mac_flow_walk_init, 1253da14cebeSEric Cheng mac_common_walk_step, NULL, NULL}, 1254d47ced1fSRobert Mustacchi {"mac_group", "walk list of ring group structures", mac_group_walk_init, 1255d47ced1fSRobert Mustacchi mac_group_walk_step, NULL, NULL}, 1256da14cebeSEric Cheng {"mac_srs", "walk list of mac soft ring set structures", 1257da14cebeSEric Cheng mac_srs_walk_init, mac_common_walk_step, NULL, NULL}, 1258da14cebeSEric Cheng {"mac_ring", "walk list of mac ring structures", mac_ring_walk_init, 1259da14cebeSEric Cheng mac_common_walk_step, NULL, NULL}, 1260da14cebeSEric Cheng { NULL } 1261da14cebeSEric Cheng }; 1262da14cebeSEric Cheng 1263da14cebeSEric Cheng static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1264da14cebeSEric Cheng 1265da14cebeSEric Cheng const mdb_modinfo_t * 1266da14cebeSEric Cheng _mdb_init(void) 1267da14cebeSEric Cheng { 1268da14cebeSEric Cheng return (&modinfo); 1269da14cebeSEric Cheng } 1270