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