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 /* 222ae51e79SGirish Moodalbail * Copyright 2009 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> 37da14cebeSEric Cheng 38da14cebeSEric Cheng #define STRSIZE 64 39da14cebeSEric Cheng #define MAC_RX_SRS_SIZE (MAX_RINGS_PER_GROUP * sizeof (uintptr_t)) 40da14cebeSEric Cheng 41da14cebeSEric Cheng #define LAYERED_WALKER_FOR_FLOW "flow_entry_cache" 42da14cebeSEric Cheng #define LAYERED_WALKER_FOR_SRS "mac_srs_cache" 43da14cebeSEric Cheng #define LAYERED_WALKER_FOR_RING "mac_ring_cache" 44da14cebeSEric Cheng 45da14cebeSEric Cheng /* arguments passed to mac_flow dee-command */ 46da14cebeSEric Cheng #define MAC_FLOW_NONE 0x01 47da14cebeSEric Cheng #define MAC_FLOW_ATTR 0x02 48da14cebeSEric Cheng #define MAC_FLOW_PROP 0x04 49da14cebeSEric Cheng #define MAC_FLOW_RX 0x08 50da14cebeSEric Cheng #define MAC_FLOW_TX 0x10 51da14cebeSEric Cheng #define MAC_FLOW_USER 0x20 52da14cebeSEric Cheng #define MAC_FLOW_STATS 0x40 53da14cebeSEric Cheng #define MAC_FLOW_MISC 0x80 54da14cebeSEric Cheng 55da14cebeSEric Cheng /* arguments passed to mac_srs dee-command */ 562ae51e79SGirish Moodalbail #define MAC_SRS_NONE 0x00 572ae51e79SGirish Moodalbail #define MAC_SRS_RX 0x01 582ae51e79SGirish Moodalbail #define MAC_SRS_TX 0x02 592ae51e79SGirish Moodalbail #define MAC_SRS_STAT 0x04 602ae51e79SGirish Moodalbail #define MAC_SRS_CPU 0x08 612ae51e79SGirish Moodalbail #define MAC_SRS_VERBOSE 0x10 622ae51e79SGirish Moodalbail #define MAC_SRS_RXSTAT (MAC_SRS_RX|MAC_SRS_STAT) 632ae51e79SGirish Moodalbail #define MAC_SRS_TXSTAT (MAC_SRS_TX|MAC_SRS_STAT) 642ae51e79SGirish Moodalbail #define MAC_SRS_RXCPU (MAC_SRS_RX|MAC_SRS_CPU) 652ae51e79SGirish Moodalbail #define MAC_SRS_TXCPU (MAC_SRS_TX|MAC_SRS_CPU) 662ae51e79SGirish Moodalbail #define MAC_SRS_RXCPUVERBOSE (MAC_SRS_RXCPU|MAC_SRS_VERBOSE) 672ae51e79SGirish Moodalbail #define MAC_SRS_TXCPUVERBOSE (MAC_SRS_TXCPU|MAC_SRS_VERBOSE) 68da14cebeSEric Cheng 69da14cebeSEric Cheng static char * 70da14cebeSEric Cheng mac_flow_proto2str(uint8_t protocol) 71da14cebeSEric Cheng { 72da14cebeSEric Cheng switch (protocol) { 73da14cebeSEric Cheng case IPPROTO_TCP: 74da14cebeSEric Cheng return ("tcp"); 75da14cebeSEric Cheng case IPPROTO_UDP: 76da14cebeSEric Cheng return ("udp"); 77da14cebeSEric Cheng case IPPROTO_SCTP: 78da14cebeSEric Cheng return ("sctp"); 79da14cebeSEric Cheng case IPPROTO_ICMP: 80da14cebeSEric Cheng return ("icmp"); 81da14cebeSEric Cheng case IPPROTO_ICMPV6: 82da14cebeSEric Cheng return ("icmpv6"); 83da14cebeSEric Cheng default: 84da14cebeSEric Cheng return ("--"); 85da14cebeSEric Cheng } 86da14cebeSEric Cheng } 87da14cebeSEric Cheng 88da14cebeSEric Cheng static char * 89da14cebeSEric Cheng mac_flow_priority2str(mac_priority_level_t prio) 90da14cebeSEric Cheng { 91da14cebeSEric Cheng switch (prio) { 92da14cebeSEric Cheng case MPL_LOW: 93da14cebeSEric Cheng return ("low"); 94da14cebeSEric Cheng case MPL_MEDIUM: 95da14cebeSEric Cheng return ("medium"); 96da14cebeSEric Cheng case MPL_HIGH: 97da14cebeSEric Cheng return ("high"); 98da14cebeSEric Cheng case MPL_RESET: 99da14cebeSEric Cheng return ("reset"); 100da14cebeSEric Cheng default: 101da14cebeSEric Cheng return ("--"); 102da14cebeSEric Cheng } 103da14cebeSEric Cheng } 104da14cebeSEric Cheng 105da14cebeSEric Cheng /* 106da14cebeSEric Cheng * Convert bandwidth in bps to a string in mpbs. 107da14cebeSEric Cheng */ 108da14cebeSEric Cheng static char * 109da14cebeSEric Cheng mac_flow_bw2str(uint64_t bw, char *buf, ssize_t len) 110da14cebeSEric Cheng { 111da14cebeSEric Cheng int kbps, mbps; 112da14cebeSEric Cheng 113da14cebeSEric Cheng kbps = (bw % 1000000)/1000; 114da14cebeSEric Cheng mbps = bw/1000000; 115da14cebeSEric Cheng if ((mbps == 0) && (kbps != 0)) 116da14cebeSEric Cheng mdb_snprintf(buf, len, "0.%03u", kbps); 117da14cebeSEric Cheng else 118da14cebeSEric Cheng mdb_snprintf(buf, len, "%5u", mbps); 119da14cebeSEric Cheng return (buf); 120da14cebeSEric Cheng } 121da14cebeSEric Cheng 122da14cebeSEric Cheng static void 123da14cebeSEric Cheng mac_flow_print_header(uint_t args) 124da14cebeSEric Cheng { 125da14cebeSEric Cheng switch (args) { 126da14cebeSEric Cheng case MAC_FLOW_NONE: 127*fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %4s %?s %?s %-16s\n", 128*fcff38ebSGirish Moodalbail "", "", "LINK", "", "", "MIP"); 129*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %4s %?s %?s %-16s%</u>\n", 130*fcff38ebSGirish Moodalbail "ADDR", "FLOW NAME", "ID", "MCIP", "MIP", "NAME"); 131da14cebeSEric Cheng break; 132da14cebeSEric Cheng case MAC_FLOW_ATTR: 133da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %-7s %6s " 134da14cebeSEric Cheng "%-9s %s%</u>\n", 135da14cebeSEric Cheng "ADDR", "FLOW NAME", "PROTO", "PORT", 136da14cebeSEric Cheng "DSFLD:MSK", "IPADDR"); 137da14cebeSEric Cheng break; 138da14cebeSEric Cheng case MAC_FLOW_PROP: 139da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %8s %9s%</u>\n", 140da14cebeSEric Cheng "ADDR", "FLOW NAME", "MAXBW(M)", "PRIORITY"); 141da14cebeSEric Cheng break; 142da14cebeSEric Cheng case MAC_FLOW_MISC: 143*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-24s %10s %10s " 144*fcff38ebSGirish Moodalbail "%20s %4s%</u>\n", 145da14cebeSEric Cheng "ADDR", "FLOW NAME", "TYPE", "FLAGS", 146da14cebeSEric Cheng "MATCH_FN", "ZONE"); 147da14cebeSEric Cheng break; 148da14cebeSEric Cheng case MAC_FLOW_RX: 149*fcff38ebSGirish Moodalbail mdb_printf("%?s %-24s %3s %s\n", "", "", "SRS", "RX"); 150*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-24s %3s %s%</u>\n", 151*fcff38ebSGirish Moodalbail "ADDR", "FLOW NAME", "CNT", "SRS"); 152da14cebeSEric Cheng break; 153da14cebeSEric Cheng case MAC_FLOW_TX: 154da14cebeSEric Cheng mdb_printf("%<u>%?s %-32s %?s %</u>\n", 155da14cebeSEric Cheng "ADDR", "FLOW NAME", "TX_SRS"); 156da14cebeSEric Cheng break; 157da14cebeSEric Cheng case MAC_FLOW_STATS: 158*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-32s %16s %16s%</u>\n", 159da14cebeSEric Cheng "ADDR", "FLOW NAME", "RBYTES", "OBYTES"); 160da14cebeSEric Cheng break; 161da14cebeSEric Cheng } 162da14cebeSEric Cheng } 163da14cebeSEric Cheng 164da14cebeSEric Cheng /* 165da14cebeSEric Cheng * Display selected fields of the flow_entry_t structure 166da14cebeSEric Cheng */ 167da14cebeSEric Cheng static int 168da14cebeSEric Cheng mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args) 169da14cebeSEric Cheng { 170da14cebeSEric Cheng static const mdb_bitmask_t flow_type_bits[] = { 171da14cebeSEric Cheng {"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC}, 172da14cebeSEric Cheng {"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC}, 173da14cebeSEric Cheng {"M", FLOW_MCAST, FLOW_MCAST}, 174da14cebeSEric Cheng {"O", FLOW_OTHER, FLOW_OTHER}, 175da14cebeSEric Cheng {"U", FLOW_USER, FLOW_USER}, 176da14cebeSEric Cheng {"V", FLOW_VNIC, FLOW_VNIC}, 177da14cebeSEric Cheng {"NS", FLOW_NO_STATS, FLOW_NO_STATS}, 178da14cebeSEric Cheng { NULL, 0, 0 } 179da14cebeSEric Cheng }; 180da14cebeSEric Cheng #define FLOW_MAX_TYPE (sizeof (flow_type_bits) / sizeof (mdb_bitmask_t)) 181da14cebeSEric Cheng 182da14cebeSEric Cheng static const mdb_bitmask_t flow_flag_bits[] = { 183da14cebeSEric Cheng {"Q", FE_QUIESCE, FE_QUIESCE}, 184da14cebeSEric Cheng {"W", FE_WAITER, FE_WAITER}, 185da14cebeSEric Cheng {"T", FE_FLOW_TAB, FE_FLOW_TAB}, 186da14cebeSEric Cheng {"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH}, 187da14cebeSEric Cheng {"I", FE_INCIPIENT, FE_INCIPIENT}, 188da14cebeSEric Cheng {"C", FE_CONDEMNED, FE_CONDEMNED}, 189da14cebeSEric Cheng {"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH}, 190da14cebeSEric Cheng {"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH}, 191da14cebeSEric Cheng { NULL, 0, 0 } 192da14cebeSEric Cheng }; 193da14cebeSEric Cheng #define FLOW_MAX_FLAGS (sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t)) 194da14cebeSEric Cheng flow_entry_t fe; 195da14cebeSEric Cheng mac_client_impl_t mcip; 196da14cebeSEric Cheng mac_impl_t mip; 197da14cebeSEric Cheng 198da14cebeSEric Cheng if (mdb_vread(&fe, sizeof (fe), addr) == -1) { 199da14cebeSEric Cheng mdb_warn("failed to read struct flow_entry_s at %p", addr); 200da14cebeSEric Cheng return (DCMD_ERR); 201da14cebeSEric Cheng } 202da14cebeSEric Cheng if (args & MAC_FLOW_USER) { 203da14cebeSEric Cheng args &= ~MAC_FLOW_USER; 204da14cebeSEric Cheng if (fe.fe_type & FLOW_MCAST) { 205da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) 206da14cebeSEric Cheng mac_flow_print_header(args); 207da14cebeSEric Cheng return (DCMD_OK); 208da14cebeSEric Cheng } 209da14cebeSEric Cheng } 210da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) 211da14cebeSEric Cheng mac_flow_print_header(args); 212da14cebeSEric Cheng bzero(&mcip, sizeof (mcip)); 213da14cebeSEric Cheng bzero(&mip, sizeof (mip)); 214da14cebeSEric Cheng if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip), 215da14cebeSEric Cheng (uintptr_t)fe.fe_mcip) == sizeof (mcip)) { 216da14cebeSEric Cheng (void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip); 217da14cebeSEric Cheng } 218da14cebeSEric Cheng switch (args) { 219da14cebeSEric Cheng case MAC_FLOW_NONE: { 220*fcff38ebSGirish Moodalbail mdb_printf("%?p %-20s %4d %?p " 221*fcff38ebSGirish Moodalbail "%?p %-16s\n", 222da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip, 223da14cebeSEric Cheng mcip.mci_mip, mip.mi_name); 224da14cebeSEric Cheng break; 225da14cebeSEric Cheng } 226da14cebeSEric Cheng case MAC_FLOW_ATTR: { 227da14cebeSEric Cheng struct in_addr in4; 228da14cebeSEric Cheng uintptr_t desc_addr; 229da14cebeSEric Cheng flow_desc_t fdesc; 230da14cebeSEric Cheng 231da14cebeSEric Cheng desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc); 232da14cebeSEric Cheng if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) { 233da14cebeSEric Cheng mdb_warn("failed to read struct flow_description at %p", 234da14cebeSEric Cheng desc_addr); 235da14cebeSEric Cheng return (DCMD_ERR); 236da14cebeSEric Cheng } 237da14cebeSEric Cheng mdb_printf("%?p %-32s " 238*fcff38ebSGirish Moodalbail "%-7s %6d " 239da14cebeSEric Cheng "%4d:%-4d ", 240da14cebeSEric Cheng addr, fe.fe_flow_name, 241da14cebeSEric Cheng mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port, 242da14cebeSEric Cheng fdesc.fd_dsfield, fdesc.fd_dsfield_mask); 243da14cebeSEric Cheng if (fdesc.fd_ipversion == IPV4_VERSION) { 244da14cebeSEric Cheng IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4); 245da14cebeSEric Cheng mdb_printf("%I", in4.s_addr); 246da14cebeSEric Cheng } else if (fdesc.fd_ipversion == IPV6_VERSION) { 247da14cebeSEric Cheng mdb_printf("%N", &fdesc.fd_local_addr); 248da14cebeSEric Cheng } else { 249da14cebeSEric Cheng mdb_printf("%s", "--"); 250da14cebeSEric Cheng } 251da14cebeSEric Cheng mdb_printf("\n"); 252da14cebeSEric Cheng break; 253da14cebeSEric Cheng } 254da14cebeSEric Cheng case MAC_FLOW_PROP: { 255da14cebeSEric Cheng uintptr_t prop_addr; 256da14cebeSEric Cheng char bwstr[STRSIZE]; 257da14cebeSEric Cheng mac_resource_props_t fprop; 258da14cebeSEric Cheng 259da14cebeSEric Cheng prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props); 260da14cebeSEric Cheng if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) { 261da14cebeSEric Cheng mdb_warn("failed to read struct mac_resoource_props " 262da14cebeSEric Cheng "at %p", prop_addr); 263da14cebeSEric Cheng return (DCMD_ERR); 264da14cebeSEric Cheng } 265da14cebeSEric Cheng mdb_printf("%?p %-32s " 266da14cebeSEric Cheng "%8s %9s\n", 267da14cebeSEric Cheng addr, fe.fe_flow_name, 268da14cebeSEric Cheng mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE), 269da14cebeSEric Cheng mac_flow_priority2str(fprop.mrp_priority)); 270da14cebeSEric Cheng break; 271da14cebeSEric Cheng } 272da14cebeSEric Cheng case MAC_FLOW_MISC: { 273da14cebeSEric Cheng char flow_flags[2 * FLOW_MAX_FLAGS]; 274da14cebeSEric Cheng char flow_type[2 * FLOW_MAX_TYPE]; 275da14cebeSEric Cheng GElf_Sym sym; 276da14cebeSEric Cheng char func_name[MDB_SYM_NAMLEN] = ""; 277da14cebeSEric Cheng uintptr_t func, match_addr; 278da14cebeSEric Cheng 279da14cebeSEric Cheng match_addr = addr + OFFSETOF(flow_entry_t, fe_match); 280da14cebeSEric Cheng (void) mdb_vread(&func, sizeof (func), match_addr); 281da14cebeSEric Cheng (void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name, 282da14cebeSEric Cheng MDB_SYM_NAMLEN, &sym); 283da14cebeSEric Cheng mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb", 284da14cebeSEric Cheng fe.fe_flags, flow_flag_bits); 285da14cebeSEric Cheng mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb", 286da14cebeSEric Cheng fe.fe_type, flow_type_bits); 287*fcff38ebSGirish Moodalbail mdb_printf("%?p %-24s %10s %10s " 288*fcff38ebSGirish Moodalbail "%20s %4d\n", 289da14cebeSEric Cheng addr, fe.fe_flow_name, flow_type, flow_flags, 290da14cebeSEric Cheng func_name, fe.fe_zoneid); 291da14cebeSEric Cheng break; 292da14cebeSEric Cheng } 293da14cebeSEric Cheng case MAC_FLOW_RX: { 2942ae51e79SGirish Moodalbail uintptr_t rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0}; 295da14cebeSEric Cheng int i; 296da14cebeSEric Cheng 297da14cebeSEric Cheng rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs); 298da14cebeSEric Cheng (void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr); 299*fcff38ebSGirish Moodalbail mdb_printf("%?p %-24s %3d ", 3002ae51e79SGirish Moodalbail addr, fe.fe_flow_name, fe.fe_rx_srs_cnt); 301da14cebeSEric Cheng for (i = 0; i < MAX_RINGS_PER_GROUP; i++) { 302da14cebeSEric Cheng if (rx_srs[i] == 0) 303da14cebeSEric Cheng continue; 304da14cebeSEric Cheng mdb_printf("%p ", rx_srs[i]); 305da14cebeSEric Cheng } 306da14cebeSEric Cheng mdb_printf("\n"); 307da14cebeSEric Cheng break; 308da14cebeSEric Cheng } 309da14cebeSEric Cheng case MAC_FLOW_TX: { 310da14cebeSEric Cheng uintptr_t tx_srs = 0, txaddr; 311da14cebeSEric Cheng 312da14cebeSEric Cheng txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs); 313da14cebeSEric Cheng (void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr); 314da14cebeSEric Cheng mdb_printf("%?p %-32s %?p\n", 315da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_tx_srs); 316da14cebeSEric Cheng break; 317da14cebeSEric Cheng } 318da14cebeSEric Cheng case MAC_FLOW_STATS: { 319da14cebeSEric Cheng mdb_printf("%?p %-32s %16llu %16llu\n", 320da14cebeSEric Cheng addr, fe.fe_flow_name, fe.fe_flowstats.fs_rbytes, 321da14cebeSEric Cheng fe.fe_flowstats.fs_obytes); 322da14cebeSEric Cheng break; 323da14cebeSEric Cheng } 324da14cebeSEric Cheng } 325da14cebeSEric Cheng return (DCMD_OK); 326da14cebeSEric Cheng } 327da14cebeSEric Cheng 328da14cebeSEric Cheng /* 329da14cebeSEric Cheng * Parse the arguments passed to the dcmd and print all or one flow_entry_t 330da14cebeSEric Cheng * structures 331da14cebeSEric Cheng */ 332da14cebeSEric Cheng static int 333da14cebeSEric Cheng mac_flow_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 334da14cebeSEric Cheng { 335da14cebeSEric Cheng uint_t args = 0; 336da14cebeSEric Cheng 337da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) { 338da14cebeSEric Cheng if (mdb_walk_dcmd("mac_flow", "mac_flow", argc, argv) == -1) { 339da14cebeSEric Cheng mdb_warn("failed to walk 'mac_flow'"); 340da14cebeSEric Cheng return (DCMD_ERR); 341da14cebeSEric Cheng } 342da14cebeSEric Cheng return (DCMD_OK); 343da14cebeSEric Cheng } 344da14cebeSEric Cheng if ((mdb_getopts(argc, argv, 345da14cebeSEric Cheng 'a', MDB_OPT_SETBITS, MAC_FLOW_ATTR, &args, 346da14cebeSEric Cheng 'p', MDB_OPT_SETBITS, MAC_FLOW_PROP, &args, 347da14cebeSEric Cheng 'm', MDB_OPT_SETBITS, MAC_FLOW_MISC, &args, 348da14cebeSEric Cheng 'r', MDB_OPT_SETBITS, MAC_FLOW_RX, &args, 349da14cebeSEric Cheng 't', MDB_OPT_SETBITS, MAC_FLOW_TX, &args, 350da14cebeSEric Cheng 's', MDB_OPT_SETBITS, MAC_FLOW_STATS, &args, 351da14cebeSEric Cheng 'u', MDB_OPT_SETBITS, MAC_FLOW_USER, &args) != argc)) { 352da14cebeSEric Cheng return (DCMD_USAGE); 353da14cebeSEric Cheng } 354da14cebeSEric Cheng if (argc > 2 || (argc == 2 && !(args & MAC_FLOW_USER))) 355da14cebeSEric Cheng return (DCMD_USAGE); 356da14cebeSEric Cheng /* 357da14cebeSEric Cheng * If no arguments was specified or just "-u" was specified then 358da14cebeSEric Cheng * we default to printing basic information of flows. 359da14cebeSEric Cheng */ 360da14cebeSEric Cheng if (args == 0 || args == MAC_FLOW_USER) 361da14cebeSEric Cheng args |= MAC_FLOW_NONE; 362da14cebeSEric Cheng 363da14cebeSEric Cheng return (mac_flow_dcmd_output(addr, flags, args)); 364da14cebeSEric Cheng } 365da14cebeSEric Cheng 366da14cebeSEric Cheng static void 367da14cebeSEric Cheng mac_flow_help(void) 368da14cebeSEric Cheng { 369da14cebeSEric Cheng mdb_printf("If an address is specified, then flow_entry structure at " 370da14cebeSEric Cheng "that address is printed. Otherwise all the flows in the system " 371da14cebeSEric Cheng "are printed.\n"); 372da14cebeSEric Cheng mdb_printf("Options:\n" 373da14cebeSEric Cheng "\t-u\tdisplay user defined link & vnic flows.\n" 374da14cebeSEric Cheng "\t-a\tdisplay flow attributes\n" 375da14cebeSEric Cheng "\t-p\tdisplay flow properties\n" 376da14cebeSEric Cheng "\t-r\tdisplay rx side information\n" 377da14cebeSEric Cheng "\t-t\tdisplay tx side information\n" 378da14cebeSEric Cheng "\t-s\tdisplay flow statistics\n" 379da14cebeSEric Cheng "\t-m\tdisplay miscellaneous flow information\n\n"); 380da14cebeSEric Cheng mdb_printf("%<u>Interpreting Flow type and Flow flags output.%</u>\n"); 381da14cebeSEric Cheng mdb_printf("Flow Types:\n"); 382da14cebeSEric Cheng mdb_printf("\t P --> FLOW_PRIMARY_MAC\n"); 383da14cebeSEric Cheng mdb_printf("\t V --> FLOW_VNIC_MAC\n"); 384da14cebeSEric Cheng mdb_printf("\t M --> FLOW_MCAST\n"); 385da14cebeSEric Cheng mdb_printf("\t O --> FLOW_OTHER\n"); 386da14cebeSEric Cheng mdb_printf("\t U --> FLOW_USER\n"); 387da14cebeSEric Cheng mdb_printf("\t NS --> FLOW_NO_STATS\n\n"); 388da14cebeSEric Cheng mdb_printf("Flow Flags:\n"); 389da14cebeSEric Cheng mdb_printf("\t Q --> FE_QUIESCE\n"); 390da14cebeSEric Cheng mdb_printf("\t W --> FE_WAITER\n"); 391da14cebeSEric Cheng mdb_printf("\t T --> FE_FLOW_TAB\n"); 392da14cebeSEric Cheng mdb_printf("\t G --> FE_G_FLOW_HASH\n"); 393da14cebeSEric Cheng mdb_printf("\t I --> FE_INCIPIENT\n"); 394da14cebeSEric Cheng mdb_printf("\t C --> FE_CONDEMNED\n"); 395da14cebeSEric Cheng mdb_printf("\t NU --> FE_UF_NO_DATAPATH\n"); 396da14cebeSEric Cheng mdb_printf("\t NC --> FE_MC_NO_DATAPATH\n"); 397da14cebeSEric Cheng } 398da14cebeSEric Cheng 399da14cebeSEric Cheng /* 400da14cebeSEric Cheng * called once by the debugger when the mac_flow walk begins. 401da14cebeSEric Cheng */ 402da14cebeSEric Cheng static int 403da14cebeSEric Cheng mac_flow_walk_init(mdb_walk_state_t *wsp) 404da14cebeSEric Cheng { 405da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_FLOW, wsp) == -1) { 406da14cebeSEric Cheng mdb_warn("failed to walk 'mac_flow'"); 407da14cebeSEric Cheng return (WALK_ERR); 408da14cebeSEric Cheng } 409da14cebeSEric Cheng return (WALK_NEXT); 410da14cebeSEric Cheng } 411da14cebeSEric Cheng 412da14cebeSEric Cheng /* 413da14cebeSEric Cheng * Common walker step funciton for flow_entry_t, mac_soft_ring_set_t and 414da14cebeSEric Cheng * mac_ring_t. 415da14cebeSEric Cheng * 416da14cebeSEric Cheng * Steps through each flow_entry_t and calls the callback function. If the 417da14cebeSEric Cheng * user executed ::walk mac_flow, it just prints the address or if the user 418da14cebeSEric Cheng * executed ::mac_flow it displays selected fields of flow_entry_t structure 419da14cebeSEric Cheng * by calling "mac_flow_dcmd" 420da14cebeSEric Cheng */ 421da14cebeSEric Cheng static int 422da14cebeSEric Cheng mac_common_walk_step(mdb_walk_state_t *wsp) 423da14cebeSEric Cheng { 424da14cebeSEric Cheng int status; 425da14cebeSEric Cheng 426da14cebeSEric Cheng if (wsp->walk_addr == NULL) 427da14cebeSEric Cheng return (WALK_DONE); 428da14cebeSEric Cheng 429da14cebeSEric Cheng status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 430da14cebeSEric Cheng wsp->walk_cbdata); 431da14cebeSEric Cheng 432da14cebeSEric Cheng return (status); 433da14cebeSEric Cheng } 434da14cebeSEric Cheng 435da14cebeSEric Cheng static char * 436da14cebeSEric Cheng mac_srs_txmode2str(mac_tx_srs_mode_t mode) 437da14cebeSEric Cheng { 438da14cebeSEric Cheng switch (mode) { 439da14cebeSEric Cheng case SRS_TX_DEFAULT: 4402ae51e79SGirish Moodalbail return ("DEF"); 441da14cebeSEric Cheng case SRS_TX_SERIALIZE: 4422ae51e79SGirish Moodalbail return ("SER"); 443da14cebeSEric Cheng case SRS_TX_FANOUT: 4442ae51e79SGirish Moodalbail return ("FO"); 445da14cebeSEric Cheng case SRS_TX_BW: 4462ae51e79SGirish Moodalbail return ("BW"); 447da14cebeSEric Cheng case SRS_TX_BW_FANOUT: 4482ae51e79SGirish Moodalbail return ("BWFO"); 449da14cebeSEric Cheng } 450da14cebeSEric Cheng return ("--"); 451da14cebeSEric Cheng } 452da14cebeSEric Cheng 453da14cebeSEric Cheng static void 454da14cebeSEric Cheng mac_srs_help(void) 455da14cebeSEric Cheng { 456da14cebeSEric Cheng mdb_printf("If an address is specified, then mac_soft_ring_set " 457da14cebeSEric Cheng "structure at that address is printed. Otherwise all the " 458da14cebeSEric Cheng "SRS in the system are printed.\n"); 459da14cebeSEric Cheng mdb_printf("Options:\n" 460da14cebeSEric Cheng "\t-r\tdisplay recieve side SRS structures\n" 4612ae51e79SGirish Moodalbail "\t-t\tdisplay transmit side SRS structures\n" 4622ae51e79SGirish Moodalbail "\t-s\tdisplay statistics for RX or TX side\n" 4632ae51e79SGirish Moodalbail "\t-c\tdisplay CPU binding for RX or TX side\n" 4642ae51e79SGirish Moodalbail "\t-v\tverbose flag for CPU binding to list cpus\n" 4652ae51e79SGirish Moodalbail "Note: use -r or -t (to specify RX or TX side respectively) along " 4662ae51e79SGirish Moodalbail "with -c or -s\n"); 4672ae51e79SGirish Moodalbail mdb_printf("\n%<u>Interpreting TX Modes%</u>\n"); 4682ae51e79SGirish Moodalbail mdb_printf("\t DEF --> Default\n"); 4692ae51e79SGirish Moodalbail mdb_printf("\t SER --> Serialize\n"); 4702ae51e79SGirish Moodalbail mdb_printf("\t FO --> Fanout\n"); 4712ae51e79SGirish Moodalbail mdb_printf("\t BW --> Bandwidth\n"); 4722ae51e79SGirish Moodalbail mdb_printf("\tBWFO --> Bandwidth Fanout\n"); 4732ae51e79SGirish Moodalbail } 4742ae51e79SGirish Moodalbail 4752ae51e79SGirish Moodalbail /* 4762ae51e79SGirish Moodalbail * In verbose mode "::mac_srs -rcv or ::mac_srs -tcv", we print the CPUs 4772ae51e79SGirish Moodalbail * assigned to a link and CPUS assigned to the soft rings. 4782ae51e79SGirish Moodalbail * 'len' is used for formatting the output and represents the number of 4792ae51e79SGirish Moodalbail * spaces between CPU list and Fanout CPU list in the output. 4802ae51e79SGirish Moodalbail */ 4812ae51e79SGirish Moodalbail static boolean_t 4822ae51e79SGirish Moodalbail mac_srs_print_cpu(int *i, uint32_t cnt, uint32_t *cpu_list, int *len) 4832ae51e79SGirish Moodalbail { 4842ae51e79SGirish Moodalbail int num = 0; 4852ae51e79SGirish Moodalbail 4862ae51e79SGirish Moodalbail if (*i == 0) 4872ae51e79SGirish Moodalbail mdb_printf("("); 4882ae51e79SGirish Moodalbail else 4892ae51e79SGirish Moodalbail mdb_printf(" "); 4902ae51e79SGirish Moodalbail while (*i < cnt) { 4912ae51e79SGirish Moodalbail /* We print 6 CPU's at a time to keep display within 80 cols */ 4922ae51e79SGirish Moodalbail if (((num + 1) % 7) == 0) { 4932ae51e79SGirish Moodalbail if (len != NULL) 4942ae51e79SGirish Moodalbail *len = 2; 4952ae51e79SGirish Moodalbail return (B_FALSE); 4962ae51e79SGirish Moodalbail } 4972ae51e79SGirish Moodalbail mdb_printf("%02x%c", cpu_list[*i], ((*i == cnt - 1)?')':',')); 4982ae51e79SGirish Moodalbail ++*i; 4992ae51e79SGirish Moodalbail ++num; 5002ae51e79SGirish Moodalbail } 5012ae51e79SGirish Moodalbail if (len != NULL) 5022ae51e79SGirish Moodalbail *len = (7 - num) * 3; 5032ae51e79SGirish Moodalbail return (B_TRUE); 504da14cebeSEric Cheng } 505da14cebeSEric Cheng 506da14cebeSEric Cheng static int 507da14cebeSEric Cheng mac_srs_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 508da14cebeSEric Cheng { 5092ae51e79SGirish Moodalbail uint_t args = MAC_SRS_NONE; 510da14cebeSEric Cheng mac_soft_ring_set_t srs; 5112ae51e79SGirish Moodalbail mac_client_impl_t mci; 512da14cebeSEric Cheng 513da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) { 514da14cebeSEric Cheng if (mdb_walk_dcmd("mac_srs", "mac_srs", argc, argv) == -1) { 515da14cebeSEric Cheng mdb_warn("failed to walk 'mac_srs'"); 516da14cebeSEric Cheng return (DCMD_ERR); 517da14cebeSEric Cheng } 518da14cebeSEric Cheng return (DCMD_OK); 519da14cebeSEric Cheng } 5202ae51e79SGirish Moodalbail if (mdb_getopts(argc, argv, 521da14cebeSEric Cheng 'r', MDB_OPT_SETBITS, MAC_SRS_RX, &args, 5222ae51e79SGirish Moodalbail 't', MDB_OPT_SETBITS, MAC_SRS_TX, &args, 5232ae51e79SGirish Moodalbail 'c', MDB_OPT_SETBITS, MAC_SRS_CPU, &args, 5242ae51e79SGirish Moodalbail 'v', MDB_OPT_SETBITS, MAC_SRS_VERBOSE, &args, 5252ae51e79SGirish Moodalbail 's', MDB_OPT_SETBITS, MAC_SRS_STAT, &args) != argc) { 526da14cebeSEric Cheng return (DCMD_USAGE); 527da14cebeSEric Cheng } 5282ae51e79SGirish Moodalbail 5292ae51e79SGirish Moodalbail if (argc > 2) 530da14cebeSEric Cheng return (DCMD_USAGE); 531da14cebeSEric Cheng 532da14cebeSEric Cheng if (mdb_vread(&srs, sizeof (srs), addr) == -1) { 533da14cebeSEric Cheng mdb_warn("failed to read struct mac_soft_ring_set_s at %p", 534da14cebeSEric Cheng addr); 535da14cebeSEric Cheng return (DCMD_ERR); 536da14cebeSEric Cheng } 5372ae51e79SGirish Moodalbail if (mdb_vread(&mci, sizeof (mci), (uintptr_t)srs.srs_mcip) == -1) { 5382ae51e79SGirish Moodalbail mdb_warn("failed to read struct mac_client_impl_t at %p " 5392ae51e79SGirish Moodalbail "for SRS %p", srs.srs_mcip, addr); 5402ae51e79SGirish Moodalbail return (DCMD_ERR); 5412ae51e79SGirish Moodalbail } 542da14cebeSEric Cheng 543da14cebeSEric Cheng switch (args) { 544da14cebeSEric Cheng case MAC_SRS_RX: { 545da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 546*fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %-8s %-8s %8s " 547*fcff38ebSGirish Moodalbail "%8s %3s\n", 5482ae51e79SGirish Moodalbail "", "", "", "", "MBLK", 5492ae51e79SGirish Moodalbail "Q", "SR"); 550*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %-8s %-8s %8s " 551*fcff38ebSGirish Moodalbail "%8s %3s%</u>\n", 5522ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "STATE", "TYPE", "CNT", 5532ae51e79SGirish Moodalbail "BYTES", "CNT"); 554da14cebeSEric Cheng } 555da14cebeSEric Cheng if (srs.srs_type & SRST_TX) 556da14cebeSEric Cheng return (DCMD_OK); 5572ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %08x %08x " 558*fcff38ebSGirish Moodalbail "%8d %8d %3d\n", 5592ae51e79SGirish Moodalbail addr, mci.mci_name, srs.srs_state, srs.srs_type, 5602ae51e79SGirish Moodalbail srs.srs_count, srs.srs_size, srs.srs_soft_ring_count); 561da14cebeSEric Cheng break; 562da14cebeSEric Cheng } 563da14cebeSEric Cheng case MAC_SRS_TX: { 564da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 5652ae51e79SGirish Moodalbail mdb_printf("%?s %-16s %-4s %-8s " 566*fcff38ebSGirish Moodalbail "%-8s %8s %8s %3s\n", 5672ae51e79SGirish Moodalbail "", "", "TX", "", 5682ae51e79SGirish Moodalbail "", "MBLK", "Q", "SR"); 5692ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-16s %-4s %-8s " 570*fcff38ebSGirish Moodalbail "%-8s %8s %8s %3s%</u>\n", 5712ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "MODE", "STATE", 5722ae51e79SGirish Moodalbail "TYPE", "CNT", "BYTES", "CNT"); 5732ae51e79SGirish Moodalbail } 5742ae51e79SGirish Moodalbail if (!(srs.srs_type & SRST_TX)) 5752ae51e79SGirish Moodalbail return (DCMD_OK); 5762ae51e79SGirish Moodalbail 5772ae51e79SGirish Moodalbail mdb_printf("%?p %-16s %-4s " 578*fcff38ebSGirish Moodalbail "%08x %08x %8d %8d %3d\n", 5792ae51e79SGirish Moodalbail addr, mci.mci_name, mac_srs_txmode2str(srs.srs_tx.st_mode), 5802ae51e79SGirish Moodalbail srs.srs_state, srs.srs_type, srs.srs_count, srs.srs_size, 5812ae51e79SGirish Moodalbail srs.srs_oth_ring_count); 5822ae51e79SGirish Moodalbail break; 5832ae51e79SGirish Moodalbail } 5842ae51e79SGirish Moodalbail case MAC_SRS_RXCPU: { 5852ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu; 5862ae51e79SGirish Moodalbail 5872ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 5882ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-4s %-4s " 5892ae51e79SGirish Moodalbail "%-6s %-4s %-7s\n", 5902ae51e79SGirish Moodalbail "", "", "NUM", "POLL", 5912ae51e79SGirish Moodalbail "WORKER", "INTR", "FANOUT"); 5922ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %-4s %-4s " 5932ae51e79SGirish Moodalbail "%-6s %-4s %-7s%</u>\n", 5942ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "CPUS", "CPU", 5952ae51e79SGirish Moodalbail "CPU", "CPU", "CPU_CNT"); 5962ae51e79SGirish Moodalbail } 5972ae51e79SGirish Moodalbail if ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX)) 5982ae51e79SGirish Moodalbail return (DCMD_OK); 5992ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-4d %-4d " 6002ae51e79SGirish Moodalbail "%-6d %-4d %-7d\n", 6012ae51e79SGirish Moodalbail addr, mci.mci_name, mc.mc_ncpus, mc.mc_pollid, 6022ae51e79SGirish Moodalbail mc.mc_workerid, mc.mc_intr_cpu, mc.mc_fanout_cnt); 6032ae51e79SGirish Moodalbail break; 6042ae51e79SGirish Moodalbail 6052ae51e79SGirish Moodalbail } 6062ae51e79SGirish Moodalbail case MAC_SRS_TXCPU: { 6072ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu; 6082ae51e79SGirish Moodalbail 6092ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 6102ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-4s %-6s " 6112ae51e79SGirish Moodalbail "%-4s %-7s\n", 6122ae51e79SGirish Moodalbail "", "", "NUM", "WORKER", 6132ae51e79SGirish Moodalbail "INTR", "FANOUT"); 6142ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %-4s %-6s " 6152ae51e79SGirish Moodalbail "%-4s %-7s%</u>\n", 6162ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "CPUS", "CPU", 6172ae51e79SGirish Moodalbail "CPU", "CPU_CNT"); 6182ae51e79SGirish Moodalbail } 6192ae51e79SGirish Moodalbail if ((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) 6202ae51e79SGirish Moodalbail return (DCMD_OK); 6212ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-4d " 6222ae51e79SGirish Moodalbail "%-6d %-4d %-7d\n", 6232ae51e79SGirish Moodalbail addr, mci.mci_name, mc.mc_ncpus, 6242ae51e79SGirish Moodalbail mc.mc_workerid, mc.mc_intr_cpu, mc.mc_fanout_cnt); 6252ae51e79SGirish Moodalbail break; 6262ae51e79SGirish Moodalbail } 6272ae51e79SGirish Moodalbail case MAC_SRS_RXCPUVERBOSE: 6282ae51e79SGirish Moodalbail case MAC_SRS_TXCPUVERBOSE: { 6292ae51e79SGirish Moodalbail mac_cpus_t mc = srs.srs_cpu; 6302ae51e79SGirish Moodalbail int cpu_index = 0, fanout_index = 0, len = 0; 6312ae51e79SGirish Moodalbail boolean_t cpu_done = B_FALSE, fanout_done = B_FALSE; 6322ae51e79SGirish Moodalbail 6332ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 6342ae51e79SGirish Moodalbail mdb_printf("%?s %-20s %-20s %-20s\n", 6352ae51e79SGirish Moodalbail "", "", "CPU_COUNT", "FANOUT_CPU_COUNT"); 6362ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s " 6372ae51e79SGirish Moodalbail "%-20s %-20s%</u>\n", 6382ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", 6392ae51e79SGirish Moodalbail "(CPU_LIST)", "(CPU_LIST)"); 6402ae51e79SGirish Moodalbail } 6412ae51e79SGirish Moodalbail if (((args & MAC_SRS_TX) && !(srs.srs_type & SRST_TX)) || 6422ae51e79SGirish Moodalbail ((args & MAC_SRS_RX) && (srs.srs_type & SRST_TX))) 6432ae51e79SGirish Moodalbail return (DCMD_OK); 6442ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %-20d %-20d\n", addr, mci.mci_name, 6452ae51e79SGirish Moodalbail mc.mc_ncpus, mc.mc_fanout_cnt); 6462ae51e79SGirish Moodalbail if (mc.mc_ncpus == 0 && mc.mc_fanout_cnt == 0) 6472ae51e79SGirish Moodalbail break; 6482ae51e79SGirish Moodalbail /* print all cpus and cpus for soft rings */ 6492ae51e79SGirish Moodalbail while (!cpu_done || !fanout_done) { 6502ae51e79SGirish Moodalbail boolean_t old_value = cpu_done; 6512ae51e79SGirish Moodalbail 6522ae51e79SGirish Moodalbail if (!cpu_done) { 6532ae51e79SGirish Moodalbail mdb_printf("%?s %20s ", "", ""); 6542ae51e79SGirish Moodalbail cpu_done = mac_srs_print_cpu(&cpu_index, 6552ae51e79SGirish Moodalbail mc.mc_ncpus, mc.mc_cpus, &len); 6562ae51e79SGirish Moodalbail } 6572ae51e79SGirish Moodalbail if (!fanout_done) { 6582ae51e79SGirish Moodalbail if (old_value) 6592ae51e79SGirish Moodalbail mdb_printf("%?s %-40s", "", ""); 6602ae51e79SGirish Moodalbail else 6612ae51e79SGirish Moodalbail mdb_printf("%*s", len, ""); 6622ae51e79SGirish Moodalbail fanout_done = mac_srs_print_cpu(&fanout_index, 6632ae51e79SGirish Moodalbail mc.mc_fanout_cnt, mc.mc_fanout_cpus, NULL); 6642ae51e79SGirish Moodalbail } 6652ae51e79SGirish Moodalbail mdb_printf("\n"); 6662ae51e79SGirish Moodalbail } 6672ae51e79SGirish Moodalbail break; 6682ae51e79SGirish Moodalbail } 6692ae51e79SGirish Moodalbail case MAC_SRS_RXSTAT: { 6702ae51e79SGirish Moodalbail mac_srs_rx_t srs_rx = srs.srs_rx; 6712ae51e79SGirish Moodalbail 6722ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 673*fcff38ebSGirish Moodalbail mdb_printf("%?s %-16s %8s %8s " 674*fcff38ebSGirish Moodalbail "%8s %8s %8s\n", 6752ae51e79SGirish Moodalbail "", "", "INTR", "POLL", 6762ae51e79SGirish Moodalbail "CHAIN", "CHAIN", "CHAIN"); 677*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-16s %8s %8s " 678*fcff38ebSGirish Moodalbail "%8s %8s %8s%</u>\n", 6792ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "COUNT", "COUNT", 6802ae51e79SGirish Moodalbail "<10", "10-50", ">50"); 6812ae51e79SGirish Moodalbail } 6822ae51e79SGirish Moodalbail if (srs.srs_type & SRST_TX) 6832ae51e79SGirish Moodalbail return (DCMD_OK); 684*fcff38ebSGirish Moodalbail mdb_printf("%?p %-16s %8d " 685*fcff38ebSGirish Moodalbail "%8d %8d " 686*fcff38ebSGirish Moodalbail "%8d %8d\n", 6872ae51e79SGirish Moodalbail addr, mci.mci_name, srs_rx.sr_intr_count, 6882ae51e79SGirish Moodalbail srs_rx.sr_poll_count, srs_rx.sr_chain_cnt_undr10, 6892ae51e79SGirish Moodalbail srs_rx.sr_chain_cnt_10to50, srs_rx.sr_chain_cnt_over50); 6902ae51e79SGirish Moodalbail break; 6912ae51e79SGirish Moodalbail } 6922ae51e79SGirish Moodalbail case MAC_SRS_TXSTAT: { 6932ae51e79SGirish Moodalbail mac_srs_tx_t srs_tx = srs.srs_tx; 694*fcff38ebSGirish Moodalbail mac_soft_ring_t *s_ringp, s_ring; 695*fcff38ebSGirish Moodalbail boolean_t first = B_TRUE; 6962ae51e79SGirish Moodalbail 6972ae51e79SGirish Moodalbail if (DCMD_HDRSPEC(flags)) { 698*fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %?s %8s %8s %8s\n", 699*fcff38ebSGirish Moodalbail "", "", "SOFT", "DROP", "BLOCK", "UNBLOCK"); 700*fcff38ebSGirish Moodalbail mdb_printf("%<u>%?s %-20s %?s %8s %8s %8s%</u>\n", 701*fcff38ebSGirish Moodalbail "ADDR", "LINK_NAME", "RING", "COUNT", "COUNT", 702*fcff38ebSGirish Moodalbail "COUNT"); 703da14cebeSEric Cheng } 704da14cebeSEric Cheng if (!(srs.srs_type & SRST_TX)) 705da14cebeSEric Cheng return (DCMD_OK); 706da14cebeSEric Cheng 707*fcff38ebSGirish Moodalbail mdb_printf("%?p %-20s ", addr, mci.mci_name); 708*fcff38ebSGirish Moodalbail 709*fcff38ebSGirish Moodalbail /* 710*fcff38ebSGirish Moodalbail * Case of no soft rings, print the info from 711*fcff38ebSGirish Moodalbail * mac_srs_tx_t. 712*fcff38ebSGirish Moodalbail */ 713*fcff38ebSGirish Moodalbail if (srs.srs_oth_ring_count == 0) { 714*fcff38ebSGirish Moodalbail mdb_printf("%?p %8d %8d %8d\n", 715*fcff38ebSGirish Moodalbail 0, srs_tx.st_drop_count, srs_tx.st_blocked_cnt, 716*fcff38ebSGirish Moodalbail srs_tx.st_unblocked_cnt); 717*fcff38ebSGirish Moodalbail break; 718*fcff38ebSGirish Moodalbail } 719*fcff38ebSGirish Moodalbail 720*fcff38ebSGirish Moodalbail for (s_ringp = srs.srs_soft_ring_head; s_ringp != NULL; 721*fcff38ebSGirish Moodalbail s_ringp = s_ring.s_ring_next) { 722*fcff38ebSGirish Moodalbail (void) mdb_vread(&s_ring, sizeof (s_ring), 723*fcff38ebSGirish Moodalbail (uintptr_t)s_ringp); 724*fcff38ebSGirish Moodalbail if (first) { 725*fcff38ebSGirish Moodalbail mdb_printf("%?p %8d %8d %8d\n", 726*fcff38ebSGirish Moodalbail s_ringp, s_ring.s_ring_drops, 727*fcff38ebSGirish Moodalbail s_ring.s_ring_blocked_cnt, 728*fcff38ebSGirish Moodalbail s_ring.s_ring_unblocked_cnt); 729*fcff38ebSGirish Moodalbail first = B_FALSE; 730*fcff38ebSGirish Moodalbail continue; 731*fcff38ebSGirish Moodalbail } 732*fcff38ebSGirish Moodalbail mdb_printf("%?s %-20s %?p %8d %8d %8d\n", 733*fcff38ebSGirish Moodalbail "", "", s_ringp, s_ring.s_ring_drops, 734*fcff38ebSGirish Moodalbail s_ring.s_ring_blocked_cnt, 735*fcff38ebSGirish Moodalbail s_ring.s_ring_unblocked_cnt); 736*fcff38ebSGirish Moodalbail } 737da14cebeSEric Cheng break; 738da14cebeSEric Cheng } 7392ae51e79SGirish Moodalbail case MAC_SRS_NONE: { 740da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 7412ae51e79SGirish Moodalbail mdb_printf("%<u>%?s %-20s %?s %?s %-3s%</u>\n", 7422ae51e79SGirish Moodalbail "ADDR", "LINK_NAME", "FLENT", "HW RING", "DIR"); 743da14cebeSEric Cheng } 7442ae51e79SGirish Moodalbail mdb_printf("%?p %-20s %?p %?p " 7452ae51e79SGirish Moodalbail "%-3s ", 7462ae51e79SGirish Moodalbail addr, mci.mci_name, srs.srs_flent, srs.srs_ring, 7472ae51e79SGirish Moodalbail (srs.srs_type & SRST_TX ? "TX" : "RX")); 748da14cebeSEric Cheng break; 749da14cebeSEric Cheng } 7502ae51e79SGirish Moodalbail default: 7512ae51e79SGirish Moodalbail return (DCMD_USAGE); 752da14cebeSEric Cheng } 753da14cebeSEric Cheng return (DCMD_OK); 754da14cebeSEric Cheng } 755da14cebeSEric Cheng 756da14cebeSEric Cheng static int 757da14cebeSEric Cheng mac_srs_walk_init(mdb_walk_state_t *wsp) 758da14cebeSEric Cheng { 759da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_SRS, wsp) == -1) { 760da14cebeSEric Cheng mdb_warn("failed to walk 'mac_srs'"); 761da14cebeSEric Cheng return (WALK_ERR); 762da14cebeSEric Cheng } 763da14cebeSEric Cheng return (WALK_NEXT); 764da14cebeSEric Cheng } 765da14cebeSEric Cheng 766da14cebeSEric Cheng static char * 767da14cebeSEric Cheng mac_ring_state2str(mac_ring_state_t state) 768da14cebeSEric Cheng { 769da14cebeSEric Cheng switch (state) { 770da14cebeSEric Cheng case MR_FREE: 771da14cebeSEric Cheng return ("free"); 772da14cebeSEric Cheng case MR_NEWLY_ADDED: 773da14cebeSEric Cheng return ("new"); 774da14cebeSEric Cheng case MR_INUSE: 775da14cebeSEric Cheng return ("inuse"); 776da14cebeSEric Cheng } 777da14cebeSEric Cheng return ("--"); 778da14cebeSEric Cheng } 779da14cebeSEric Cheng 780da14cebeSEric Cheng static char * 781da14cebeSEric Cheng mac_ring_classify2str(mac_classify_type_t classify) 782da14cebeSEric Cheng { 783da14cebeSEric Cheng switch (classify) { 784da14cebeSEric Cheng case MAC_NO_CLASSIFIER: 785da14cebeSEric Cheng return ("no"); 786da14cebeSEric Cheng case MAC_SW_CLASSIFIER: 787da14cebeSEric Cheng return ("sw"); 788da14cebeSEric Cheng case MAC_HW_CLASSIFIER: 789da14cebeSEric Cheng return ("hw"); 790da14cebeSEric Cheng } 791da14cebeSEric Cheng return ("--"); 792da14cebeSEric Cheng } 793da14cebeSEric Cheng 794da14cebeSEric Cheng static int 795da14cebeSEric Cheng mac_ring_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 796da14cebeSEric Cheng { 797da14cebeSEric Cheng mac_ring_t ring; 798da14cebeSEric Cheng mac_group_t group; 799da14cebeSEric Cheng flow_entry_t flent; 800da14cebeSEric Cheng mac_soft_ring_set_t srs; 801da14cebeSEric Cheng 802da14cebeSEric Cheng if (!(flags & DCMD_ADDRSPEC)) { 803da14cebeSEric Cheng if (mdb_walk_dcmd("mac_ring", "mac_ring", argc, argv) == -1) { 804da14cebeSEric Cheng mdb_warn("failed to walk 'mac_ring'"); 805da14cebeSEric Cheng return (DCMD_ERR); 806da14cebeSEric Cheng } 807da14cebeSEric Cheng return (DCMD_OK); 808da14cebeSEric Cheng } 809da14cebeSEric Cheng if (mdb_vread(&ring, sizeof (ring), addr) == -1) { 810da14cebeSEric Cheng mdb_warn("failed to read struct mac_ring_s at %p", addr); 811da14cebeSEric Cheng return (DCMD_ERR); 812da14cebeSEric Cheng } 813da14cebeSEric Cheng bzero(&flent, sizeof (flent)); 814da14cebeSEric Cheng if (mdb_vread(&srs, sizeof (srs), (uintptr_t)ring.mr_srs) != -1) { 815da14cebeSEric Cheng (void) mdb_vread(&flent, sizeof (flent), 816da14cebeSEric Cheng (uintptr_t)srs.srs_flent); 817da14cebeSEric Cheng } 818da14cebeSEric Cheng (void) mdb_vread(&group, sizeof (group), (uintptr_t)ring.mr_gh); 819da14cebeSEric Cheng if (DCMD_HDRSPEC(flags)) { 820da14cebeSEric Cheng mdb_printf("%<u>%?s %4s %5s %4s %?s " 821da14cebeSEric Cheng "%5s %?s %?s %s %</u>\n", 822da14cebeSEric Cheng "ADDR", "TYPE", "STATE", "FLAG", "GROUP", 823da14cebeSEric Cheng "CLASS", "MIP", "SRS", "FLOW NAME"); 824da14cebeSEric Cheng } 825da14cebeSEric Cheng mdb_printf("%?p %-4s " 826da14cebeSEric Cheng "%5s %04x " 827da14cebeSEric Cheng "%?p %-5s " 828da14cebeSEric Cheng "%?p %?p %s\n", 829da14cebeSEric Cheng addr, ((ring.mr_type == 1)? "RX" : "TX"), 830da14cebeSEric Cheng mac_ring_state2str(ring.mr_state), ring.mr_flag, 831da14cebeSEric Cheng ring.mr_gh, mac_ring_classify2str(ring.mr_classify_type), 832da14cebeSEric Cheng group.mrg_mh, ring.mr_srs, flent.fe_flow_name); 833da14cebeSEric Cheng return (DCMD_OK); 834da14cebeSEric Cheng } 835da14cebeSEric Cheng 836da14cebeSEric Cheng static int 837da14cebeSEric Cheng mac_ring_walk_init(mdb_walk_state_t *wsp) 838da14cebeSEric Cheng { 839da14cebeSEric Cheng if (mdb_layered_walk(LAYERED_WALKER_FOR_RING, wsp) == -1) { 840da14cebeSEric Cheng mdb_warn("failed to walk `mac_ring`"); 841da14cebeSEric Cheng return (WALK_ERR); 842da14cebeSEric Cheng } 843da14cebeSEric Cheng return (WALK_NEXT); 844da14cebeSEric Cheng } 845da14cebeSEric Cheng 846da14cebeSEric Cheng static void 847da14cebeSEric Cheng mac_ring_help(void) 848da14cebeSEric Cheng { 849da14cebeSEric Cheng mdb_printf("If an address is specified, then mac_ring_t " 850da14cebeSEric Cheng "structure at that address is printed. Otherwise all the " 851da14cebeSEric Cheng "hardware rings in the system are printed.\n"); 852da14cebeSEric Cheng } 853da14cebeSEric Cheng 854da14cebeSEric Cheng /* Supported dee-commands */ 855da14cebeSEric Cheng static const mdb_dcmd_t dcmds[] = { 856da14cebeSEric Cheng {"mac_flow", "?[-u] [-aprtsm]", "display Flow Entry structures", 857da14cebeSEric Cheng mac_flow_dcmd, mac_flow_help}, 8582ae51e79SGirish Moodalbail {"mac_srs", "?[ -r[s|c[v]] | -t[s|c[v]] ]", "display MAC Soft Ring Set" 8592ae51e79SGirish Moodalbail " structures", mac_srs_dcmd, mac_srs_help}, 860da14cebeSEric Cheng {"mac_ring", "?", "display MAC ring (hardware) structures", 861da14cebeSEric Cheng mac_ring_dcmd, mac_ring_help}, 862da14cebeSEric Cheng { NULL } 863da14cebeSEric Cheng }; 864da14cebeSEric Cheng 865da14cebeSEric Cheng /* Supported walkers */ 866da14cebeSEric Cheng static const mdb_walker_t walkers[] = { 867da14cebeSEric Cheng {"mac_flow", "walk list of flow entry structures", mac_flow_walk_init, 868da14cebeSEric Cheng mac_common_walk_step, NULL, NULL}, 869da14cebeSEric Cheng {"mac_srs", "walk list of mac soft ring set structures", 870da14cebeSEric Cheng mac_srs_walk_init, mac_common_walk_step, NULL, NULL}, 871da14cebeSEric Cheng {"mac_ring", "walk list of mac ring structures", mac_ring_walk_init, 872da14cebeSEric Cheng mac_common_walk_step, NULL, NULL}, 873da14cebeSEric Cheng { NULL } 874da14cebeSEric Cheng }; 875da14cebeSEric Cheng 876da14cebeSEric Cheng static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 877da14cebeSEric Cheng 878da14cebeSEric Cheng const mdb_modinfo_t * 879da14cebeSEric Cheng _mdb_init(void) 880da14cebeSEric Cheng { 881da14cebeSEric Cheng return (&modinfo); 882da14cebeSEric Cheng } 883