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