10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2546Scarlsonj * Common Development and Distribution License (the "License"). 6*2546Scarlsonj * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2546Scarlsonj * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/stropts.h> 300Sstevel@tonic-gate #include <sys/stream.h> 310Sstevel@tonic-gate #include <sys/socket.h> 320Sstevel@tonic-gate #include <sys/avl_impl.h> 330Sstevel@tonic-gate #include <net/if.h> 340Sstevel@tonic-gate #include <net/route.h> 350Sstevel@tonic-gate #include <netinet/in.h> 360Sstevel@tonic-gate #include <netinet/ip6.h> 370Sstevel@tonic-gate #include <netinet/udp.h> 380Sstevel@tonic-gate #include <netinet/sctp.h> 390Sstevel@tonic-gate #include <inet/mib2.h> 400Sstevel@tonic-gate #include <inet/common.h> 410Sstevel@tonic-gate #include <inet/ip.h> 420Sstevel@tonic-gate #include <inet/ip_ire.h> 430Sstevel@tonic-gate #include <inet/ip6.h> 440Sstevel@tonic-gate #include <inet/ipclassifier.h> 450Sstevel@tonic-gate #include <inet/mi.h> 460Sstevel@tonic-gate #include <sys/squeue_impl.h> 470Sstevel@tonic-gate 480Sstevel@tonic-gate #include <mdb/mdb_modapi.h> 490Sstevel@tonic-gate #include <mdb/mdb_ks.h> 500Sstevel@tonic-gate 510Sstevel@tonic-gate #define ADDR_WIDTH 11 520Sstevel@tonic-gate 530Sstevel@tonic-gate typedef struct { 540Sstevel@tonic-gate const char *bit_name; /* name of bit */ 550Sstevel@tonic-gate const char *bit_descr; /* description of bit's purpose */ 560Sstevel@tonic-gate } bitname_t; 570Sstevel@tonic-gate 580Sstevel@tonic-gate static const bitname_t squeue_states[] = { 590Sstevel@tonic-gate { "SQS_PROC", "being processed" }, 600Sstevel@tonic-gate { "SQS_WORKER", "... by a worker thread" }, 610Sstevel@tonic-gate { "SQS_ENTER", "... by an squeue_enter() thread" }, 620Sstevel@tonic-gate { "SQS_FAST", "... in fast-path mode" }, 630Sstevel@tonic-gate { "SQS_USER", "A non interrupt user" }, 640Sstevel@tonic-gate { "SQS_BOUND", "worker thread bound to CPU" }, 650Sstevel@tonic-gate { "SQS_PROFILE", "profiling enabled" }, 660Sstevel@tonic-gate { "SQS_REENTER", "re-entered thred" }, 670Sstevel@tonic-gate { NULL } 680Sstevel@tonic-gate }; 690Sstevel@tonic-gate 700Sstevel@tonic-gate typedef struct illif_walk_data { 710Sstevel@tonic-gate ill_g_head_t ill_g_heads[MAX_G_HEADS]; 720Sstevel@tonic-gate int ill_list; 730Sstevel@tonic-gate ill_if_t ill_if; 740Sstevel@tonic-gate } illif_walk_data_t; 750Sstevel@tonic-gate 760Sstevel@tonic-gate static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *); 770Sstevel@tonic-gate static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *); 780Sstevel@tonic-gate 790Sstevel@tonic-gate int 800Sstevel@tonic-gate illif_walk_init(mdb_walk_state_t *wsp) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate illif_walk_data_t *iw; 830Sstevel@tonic-gate 840Sstevel@tonic-gate if (wsp->walk_addr != NULL) { 850Sstevel@tonic-gate mdb_warn("illif supports only global walks\n"); 860Sstevel@tonic-gate return (WALK_ERR); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP); 900Sstevel@tonic-gate 910Sstevel@tonic-gate if (mdb_readsym(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t), 920Sstevel@tonic-gate "ill_g_heads") == -1) { 930Sstevel@tonic-gate mdb_warn("failed to read 'ill_g_heads'"); 940Sstevel@tonic-gate mdb_free(iw, sizeof (illif_walk_data_t)); 950Sstevel@tonic-gate return (WALK_ERR); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate iw->ill_list = 0; 990Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->IP_VX_ILL_G_LIST(0); 1000Sstevel@tonic-gate wsp->walk_data = iw; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate return (WALK_NEXT); 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate int 1060Sstevel@tonic-gate illif_walk_step(mdb_walk_state_t *wsp) 1070Sstevel@tonic-gate { 1080Sstevel@tonic-gate uintptr_t addr = wsp->walk_addr; 1090Sstevel@tonic-gate illif_walk_data_t *iw = wsp->walk_data; 1100Sstevel@tonic-gate int list = iw->ill_list; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) { 1130Sstevel@tonic-gate mdb_warn("failed to read ill_if_t at %p", addr); 1140Sstevel@tonic-gate return (WALK_ERR); 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next; 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate if (wsp->walk_addr == (uintptr_t)iw->IP_VX_ILL_G_LIST(list)) { 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate if (++list >= MAX_G_HEADS) 1220Sstevel@tonic-gate return (WALK_DONE); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate iw->ill_list = list; 1250Sstevel@tonic-gate wsp->walk_addr = (uintptr_t)iw->IP_VX_ILL_G_LIST(list); 1260Sstevel@tonic-gate return (WALK_NEXT); 1270Sstevel@tonic-gate } 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate void 1330Sstevel@tonic-gate illif_walk_fini(mdb_walk_state_t *wsp) 1340Sstevel@tonic-gate { 1350Sstevel@tonic-gate mdb_free(wsp->walk_data, sizeof (illif_walk_data_t)); 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate typedef struct illif_cbdata { 1390Sstevel@tonic-gate uint_t ill_flags; 1400Sstevel@tonic-gate uintptr_t ill_addr; 1410Sstevel@tonic-gate int ill_printlist; /* list to be printed (MAX_G_HEADS for all) */ 1420Sstevel@tonic-gate boolean_t ill_printed; 1430Sstevel@tonic-gate } illif_cbdata_t; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate static int 1460Sstevel@tonic-gate illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id) 1470Sstevel@tonic-gate { 1480Sstevel@tonic-gate const char *version; 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate if (id->ill_printlist < MAX_G_HEADS && 1510Sstevel@tonic-gate id->ill_printlist != iw->ill_list) 1520Sstevel@tonic-gate return (WALK_NEXT); 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr) 1550Sstevel@tonic-gate return (WALK_NEXT); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if (id->ill_flags & DCMD_PIPE_OUT) { 1580Sstevel@tonic-gate mdb_printf("%p\n", addr); 1590Sstevel@tonic-gate return (WALK_NEXT); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate switch (iw->ill_list) { 1630Sstevel@tonic-gate case IP_V4_G_HEAD: version = "v4"; break; 1640Sstevel@tonic-gate case IP_V6_G_HEAD: version = "v6"; break; 1650Sstevel@tonic-gate default: version = "??"; break; 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate mdb_printf("%?p %2s %?p %10d %?p %s\n", 1690Sstevel@tonic-gate addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa), 1700Sstevel@tonic-gate iw->ill_if.illif_avl_by_ppa.avl_numnodes, 1710Sstevel@tonic-gate iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate id->ill_printed = TRUE; 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate return (WALK_NEXT); 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate int 1790Sstevel@tonic-gate illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1800Sstevel@tonic-gate { 1810Sstevel@tonic-gate illif_cbdata_t id; 1820Sstevel@tonic-gate ill_if_t ill_if; 1830Sstevel@tonic-gate const char *opt_P = NULL; 1840Sstevel@tonic-gate int printlist = MAX_G_HEADS; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate if (mdb_getopts(argc, argv, 1870Sstevel@tonic-gate 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 1880Sstevel@tonic-gate return (DCMD_USAGE); 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate if (opt_P != NULL) { 1910Sstevel@tonic-gate if (strcmp("v4", opt_P) == 0) { 1920Sstevel@tonic-gate printlist = IP_V4_G_HEAD; 1930Sstevel@tonic-gate } else if (strcmp("v6", opt_P) == 0) { 1940Sstevel@tonic-gate printlist = IP_V6_G_HEAD; 1950Sstevel@tonic-gate } else { 1960Sstevel@tonic-gate mdb_warn("invalid protocol '%s'\n", opt_P); 1970Sstevel@tonic-gate return (DCMD_USAGE); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) { 2020Sstevel@tonic-gate mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n", 2030Sstevel@tonic-gate "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME"); 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate id.ill_flags = flags; 2070Sstevel@tonic-gate id.ill_addr = addr; 2080Sstevel@tonic-gate id.ill_printlist = printlist; 2090Sstevel@tonic-gate id.ill_printed = FALSE; 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) { 2120Sstevel@tonic-gate mdb_warn("can't walk ill_if_t structures"); 2130Sstevel@tonic-gate return (DCMD_ERR); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed) 2170Sstevel@tonic-gate return (DCMD_OK); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate /* 2200Sstevel@tonic-gate * If an address is specified and the walk doesn't find it, 2210Sstevel@tonic-gate * print it anyway. 2220Sstevel@tonic-gate */ 2230Sstevel@tonic-gate if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) { 2240Sstevel@tonic-gate mdb_warn("failed to read ill_if_t at %p", addr); 2250Sstevel@tonic-gate return (DCMD_ERR); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate mdb_printf("%?p %2s %?p %10d %?p %s\n", 2290Sstevel@tonic-gate addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa), 2300Sstevel@tonic-gate ill_if.illif_avl_by_ppa.avl_numnodes, 2310Sstevel@tonic-gate ill_if.illif_ppa_arena, ill_if.illif_name); 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate return (DCMD_OK); 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate static void 2370Sstevel@tonic-gate illif_help(void) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate mdb_printf("Options:\n"); 2400Sstevel@tonic-gate mdb_printf("\t-P v4 | v6" 2410Sstevel@tonic-gate "\tfilter interface structures for the specified protocol\n"); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate int 2450Sstevel@tonic-gate ire_walk_init(mdb_walk_state_t *wsp) 2460Sstevel@tonic-gate { 2470Sstevel@tonic-gate if (mdb_layered_walk("ire_cache", wsp) == -1) { 2480Sstevel@tonic-gate mdb_warn("can't walk 'ire_cache'"); 2490Sstevel@tonic-gate return (WALK_ERR); 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate return (WALK_NEXT); 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate int 2560Sstevel@tonic-gate ire_walk_step(mdb_walk_state_t *wsp) 2570Sstevel@tonic-gate { 2580Sstevel@tonic-gate ire_t ire; 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) { 2610Sstevel@tonic-gate mdb_warn("can't read ire at %p", wsp->walk_addr); 2620Sstevel@tonic-gate return (WALK_ERR); 2630Sstevel@tonic-gate } 2640Sstevel@tonic-gate 2650Sstevel@tonic-gate return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata)); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate static int 2690Sstevel@tonic-gate ire_format(uintptr_t addr, const ire_t *irep, uint_t *verbose) 2700Sstevel@tonic-gate { 2710Sstevel@tonic-gate static const mdb_bitmask_t tmasks[] = { 2720Sstevel@tonic-gate { "BROADCAST", IRE_BROADCAST, IRE_BROADCAST }, 2730Sstevel@tonic-gate { "DEFAULT", IRE_DEFAULT, IRE_DEFAULT }, 2740Sstevel@tonic-gate { "LOCAL", IRE_LOCAL, IRE_LOCAL }, 2750Sstevel@tonic-gate { "LOOPBACK", IRE_LOOPBACK, IRE_LOOPBACK }, 2760Sstevel@tonic-gate { "PREFIX", IRE_PREFIX, IRE_PREFIX }, 2770Sstevel@tonic-gate { "CACHE", IRE_CACHE, IRE_CACHE }, 2780Sstevel@tonic-gate { "IF_NORESOLVER", IRE_IF_NORESOLVER, IRE_IF_NORESOLVER }, 2790Sstevel@tonic-gate { "IF_RESOLVER", IRE_IF_RESOLVER, IRE_IF_RESOLVER }, 2800Sstevel@tonic-gate { "HOST", IRE_HOST, IRE_HOST }, 2810Sstevel@tonic-gate { "HOST_REDIRECT", IRE_HOST_REDIRECT, IRE_HOST_REDIRECT }, 2820Sstevel@tonic-gate { "MIPRTUN", IRE_MIPRTUN, IRE_MIPRTUN }, 2830Sstevel@tonic-gate { NULL, 0, 0 } 2840Sstevel@tonic-gate }; 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate static const mdb_bitmask_t mmasks[] = { 2870Sstevel@tonic-gate { "CONDEMNED", IRE_MARK_CONDEMNED, IRE_MARK_CONDEMNED }, 2880Sstevel@tonic-gate { "NORECV", IRE_MARK_NORECV, IRE_MARK_NORECV }, 2890Sstevel@tonic-gate { "HIDDEN", IRE_MARK_HIDDEN, IRE_MARK_HIDDEN }, 2900Sstevel@tonic-gate { "NOADD", IRE_MARK_NOADD, IRE_MARK_NOADD }, 2910Sstevel@tonic-gate { "TEMPORARY", IRE_MARK_TEMPORARY, IRE_MARK_TEMPORARY }, 2920Sstevel@tonic-gate { NULL, 0, 0 } 2930Sstevel@tonic-gate }; 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate static const mdb_bitmask_t fmasks[] = { 2960Sstevel@tonic-gate { "UP", RTF_UP, RTF_UP }, 2970Sstevel@tonic-gate { "GATEWAY", RTF_GATEWAY, RTF_GATEWAY }, 2980Sstevel@tonic-gate { "HOST", RTF_HOST, RTF_HOST }, 2990Sstevel@tonic-gate { "REJECT", RTF_REJECT, RTF_REJECT }, 3000Sstevel@tonic-gate { "DYNAMIC", RTF_DYNAMIC, RTF_DYNAMIC }, 3010Sstevel@tonic-gate { "MODIFIED", RTF_MODIFIED, RTF_MODIFIED }, 3020Sstevel@tonic-gate { "DONE", RTF_DONE, RTF_DONE }, 3030Sstevel@tonic-gate { "MASK", RTF_MASK, RTF_MASK }, 3040Sstevel@tonic-gate { "CLONING", RTF_CLONING, RTF_CLONING }, 3050Sstevel@tonic-gate { "XRESOLVE", RTF_XRESOLVE, RTF_XRESOLVE }, 3060Sstevel@tonic-gate { "LLINFO", RTF_LLINFO, RTF_LLINFO }, 3070Sstevel@tonic-gate { "STATIC", RTF_STATIC, RTF_STATIC }, 3080Sstevel@tonic-gate { "BLACKHOLE", RTF_BLACKHOLE, RTF_BLACKHOLE }, 3090Sstevel@tonic-gate { "PRIVATE", RTF_PRIVATE, RTF_PRIVATE }, 3100Sstevel@tonic-gate { "PROTO2", RTF_PROTO2, RTF_PROTO2 }, 3110Sstevel@tonic-gate { "PROTO1", RTF_PROTO1, RTF_PROTO1 }, 3120Sstevel@tonic-gate { "MULTIRT", RTF_MULTIRT, RTF_MULTIRT }, 3130Sstevel@tonic-gate { "SETSRC", RTF_SETSRC, RTF_SETSRC }, 3140Sstevel@tonic-gate { NULL, 0, 0 } 3150Sstevel@tonic-gate }; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate if (irep->ire_ipversion == 6 && *verbose) { 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate mdb_printf("%<b>%?p%</b> %40N <%hb>\n" 3200Sstevel@tonic-gate "%?s %40N <%hb>\n" 3210Sstevel@tonic-gate "%?s %40d <%hb>\n", 3220Sstevel@tonic-gate addr, &irep->ire_src_addr_v6, irep->ire_type, tmasks, 3230Sstevel@tonic-gate "", &irep->ire_addr_v6, (ushort_t)irep->ire_marks, mmasks, 3240Sstevel@tonic-gate "", irep->ire_zoneid, irep->ire_flags, fmasks); 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate } else if (irep->ire_ipversion == 6) { 3270Sstevel@tonic-gate 3280Sstevel@tonic-gate mdb_printf("%?p %30N %30N %4d\n", addr, &irep->ire_src_addr_v6, 3290Sstevel@tonic-gate &irep->ire_addr_v6, irep->ire_zoneid); 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate } else if (*verbose) { 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate mdb_printf("%<b>%?p%</b> %40I <%hb>\n" 3340Sstevel@tonic-gate "%?s %40I <%hb>\n" 3350Sstevel@tonic-gate "%?s %40d <%hb>\n", 3360Sstevel@tonic-gate addr, irep->ire_src_addr, irep->ire_type, tmasks, 3370Sstevel@tonic-gate "", irep->ire_addr, (ushort_t)irep->ire_marks, mmasks, 3380Sstevel@tonic-gate "", irep->ire_zoneid, irep->ire_flags, fmasks); 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate } else { 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate mdb_printf("%?p %30I %30I %4d\n", addr, irep->ire_src_addr, 3430Sstevel@tonic-gate irep->ire_addr, irep->ire_zoneid); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate return (WALK_NEXT); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate /* 3500Sstevel@tonic-gate * There are faster ways to do this. Given the interactive nature of this 3510Sstevel@tonic-gate * use I don't think its worth much effort. 3520Sstevel@tonic-gate */ 3530Sstevel@tonic-gate static unsigned short 3540Sstevel@tonic-gate ipcksum(void *p, int len) 3550Sstevel@tonic-gate { 3560Sstevel@tonic-gate int32_t sum = 0; 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate while (len > 1) { 3590Sstevel@tonic-gate /* alignment */ 3600Sstevel@tonic-gate sum += *(uint16_t *)p; 3610Sstevel@tonic-gate p = (char *)p + sizeof (uint16_t); 3620Sstevel@tonic-gate if (sum & 0x80000000) 3630Sstevel@tonic-gate sum = (sum & 0xFFFF) + (sum >> 16); 3640Sstevel@tonic-gate len -= 2; 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if (len) 3680Sstevel@tonic-gate sum += (uint16_t)*(unsigned char *)p; 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate while (sum >> 16) 3710Sstevel@tonic-gate sum = (sum & 0xFFFF) + (sum >> 16); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate return (~sum); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate static const mdb_bitmask_t tcp_flags[] = { 3770Sstevel@tonic-gate { "SYN", TH_SYN, TH_SYN }, 3780Sstevel@tonic-gate { "ACK", TH_ACK, TH_ACK }, 3790Sstevel@tonic-gate { "FIN", TH_FIN, TH_FIN }, 3800Sstevel@tonic-gate { "RST", TH_RST, TH_RST }, 3810Sstevel@tonic-gate { "PSH", TH_PUSH, TH_PUSH }, 3820Sstevel@tonic-gate { "ECE", TH_ECE, TH_ECE }, 3830Sstevel@tonic-gate { "CWR", TH_CWR, TH_CWR }, 3840Sstevel@tonic-gate { NULL, 0, 0 } 3850Sstevel@tonic-gate }; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate static void 3880Sstevel@tonic-gate tcphdr_print(struct tcphdr *tcph) 3890Sstevel@tonic-gate { 3900Sstevel@tonic-gate in_port_t sport, dport; 3910Sstevel@tonic-gate tcp_seq seq, ack; 3920Sstevel@tonic-gate uint16_t win, urp; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate mdb_printf("%<b>TCP header%</b>\n"); 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport)); 3970Sstevel@tonic-gate mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport)); 3980Sstevel@tonic-gate mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq)); 3990Sstevel@tonic-gate mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack)); 4000Sstevel@tonic-gate mdb_nhconvert(&win, &tcph->th_win, sizeof (win)); 4010Sstevel@tonic-gate mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp)); 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n", 4040Sstevel@tonic-gate "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP", 4050Sstevel@tonic-gate "FLAGS"); 4060Sstevel@tonic-gate mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n", 4070Sstevel@tonic-gate sport, dport, seq, ack, tcph->th_off << 2, win, 4080Sstevel@tonic-gate tcph->th_sum, urp, tcph->th_flags, tcp_flags); 4090Sstevel@tonic-gate mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n", 4100Sstevel@tonic-gate sport, dport, seq, ack); 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* ARGSUSED */ 4140Sstevel@tonic-gate static int 4150Sstevel@tonic-gate tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 4160Sstevel@tonic-gate { 4170Sstevel@tonic-gate struct tcphdr tcph; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 4200Sstevel@tonic-gate return (DCMD_USAGE); 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 4230Sstevel@tonic-gate mdb_warn("failed to read TCP header at %p", addr); 4240Sstevel@tonic-gate return (DCMD_ERR); 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate tcphdr_print(&tcph); 4270Sstevel@tonic-gate return (DCMD_OK); 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate 4300Sstevel@tonic-gate static void 4310Sstevel@tonic-gate udphdr_print(struct udphdr *udph) 4320Sstevel@tonic-gate { 4330Sstevel@tonic-gate in_port_t sport, dport; 4340Sstevel@tonic-gate uint16_t hlen; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate mdb_printf("%<b>UDP header%</b>\n"); 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport)); 4390Sstevel@tonic-gate mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport)); 4400Sstevel@tonic-gate mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen)); 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate mdb_printf("%<u>%14s %14s %5s %6s%</u>\n", 4430Sstevel@tonic-gate "SPORT", "DPORT", "LEN", "CSUM"); 4440Sstevel@tonic-gate mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport, 4450Sstevel@tonic-gate dport, dport, hlen, udph->uh_sum); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate /* ARGSUSED */ 4490Sstevel@tonic-gate static int 4500Sstevel@tonic-gate udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 4510Sstevel@tonic-gate { 4520Sstevel@tonic-gate struct udphdr udph; 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 4550Sstevel@tonic-gate return (DCMD_USAGE); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 4580Sstevel@tonic-gate mdb_warn("failed to read UDP header at %p", addr); 4590Sstevel@tonic-gate return (DCMD_ERR); 4600Sstevel@tonic-gate } 4610Sstevel@tonic-gate udphdr_print(&udph); 4620Sstevel@tonic-gate return (DCMD_OK); 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4650Sstevel@tonic-gate static void 4660Sstevel@tonic-gate sctphdr_print(sctp_hdr_t *sctph) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate in_port_t sport, dport; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate mdb_printf("%<b>SCTP header%</b>\n"); 4710Sstevel@tonic-gate mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport)); 4720Sstevel@tonic-gate mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport)); 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate mdb_printf("%<u>%14s %14s %10s %10s%</u>\n", 4750Sstevel@tonic-gate "SPORT", "DPORT", "VTAG", "CHKSUM"); 4760Sstevel@tonic-gate mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport, 4770Sstevel@tonic-gate dport, dport, sctph->sh_verf, sctph->sh_chksum); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate /* ARGSUSED */ 4810Sstevel@tonic-gate static int 4820Sstevel@tonic-gate sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 4830Sstevel@tonic-gate { 4840Sstevel@tonic-gate sctp_hdr_t sctph; 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) 4870Sstevel@tonic-gate return (DCMD_USAGE); 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 4900Sstevel@tonic-gate mdb_warn("failed to read SCTP header at %p", addr); 4910Sstevel@tonic-gate return (DCMD_ERR); 4920Sstevel@tonic-gate } 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate sctphdr_print(&sctph); 4950Sstevel@tonic-gate return (DCMD_OK); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate static int 4990Sstevel@tonic-gate transport_hdr(int proto, uintptr_t addr) 5000Sstevel@tonic-gate { 5010Sstevel@tonic-gate mdb_printf("\n"); 5020Sstevel@tonic-gate switch (proto) { 5030Sstevel@tonic-gate case IPPROTO_TCP: { 5040Sstevel@tonic-gate struct tcphdr tcph; 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 5070Sstevel@tonic-gate mdb_warn("failed to read TCP header at %p", addr); 5080Sstevel@tonic-gate return (DCMD_ERR); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate tcphdr_print(&tcph); 5110Sstevel@tonic-gate break; 5120Sstevel@tonic-gate } 5130Sstevel@tonic-gate case IPPROTO_UDP: { 5140Sstevel@tonic-gate struct udphdr udph; 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 5170Sstevel@tonic-gate mdb_warn("failed to read UDP header at %p", addr); 5180Sstevel@tonic-gate return (DCMD_ERR); 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate udphdr_print(&udph); 5210Sstevel@tonic-gate break; 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate case IPPROTO_SCTP: { 5240Sstevel@tonic-gate sctp_hdr_t sctph; 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 5270Sstevel@tonic-gate mdb_warn("failed to read SCTP header at %p", addr); 5280Sstevel@tonic-gate return (DCMD_ERR); 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate sctphdr_print(&sctph); 5310Sstevel@tonic-gate break; 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate default: 5340Sstevel@tonic-gate break; 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate return (DCMD_OK); 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate static const mdb_bitmask_t ip_flags[] = { 5410Sstevel@tonic-gate { "DF", IPH_DF, IPH_DF }, 5420Sstevel@tonic-gate { "MF", IPH_MF, IPH_MF }, 5430Sstevel@tonic-gate { NULL, 0, 0 } 5440Sstevel@tonic-gate }; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate /* ARGSUSED */ 5470Sstevel@tonic-gate static int 5480Sstevel@tonic-gate iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 5490Sstevel@tonic-gate { 5500Sstevel@tonic-gate uint_t verbose = FALSE, force = FALSE; 5510Sstevel@tonic-gate ipha_t iph[1]; 5520Sstevel@tonic-gate uint16_t ver, totlen, hdrlen, ipid, off, csum; 5530Sstevel@tonic-gate uintptr_t nxt_proto; 5540Sstevel@tonic-gate char exp_csum[8]; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate if (mdb_getopts(argc, argv, 5570Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, 5580Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 5590Sstevel@tonic-gate return (DCMD_USAGE); 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 5620Sstevel@tonic-gate mdb_warn("failed to read IPv4 header at %p", addr); 5630Sstevel@tonic-gate return (DCMD_ERR); 5640Sstevel@tonic-gate } 5650Sstevel@tonic-gate 5660Sstevel@tonic-gate ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4; 5670Sstevel@tonic-gate if (ver != IPV4_VERSION) { 5680Sstevel@tonic-gate if (ver == IPV6_VERSION) { 5690Sstevel@tonic-gate return (ip6hdr(addr, flags, argc, argv)); 5700Sstevel@tonic-gate } else if (!force) { 5710Sstevel@tonic-gate mdb_warn("unknown IP version: %d\n", ver); 5720Sstevel@tonic-gate return (DCMD_ERR); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate } 5750Sstevel@tonic-gate 5760Sstevel@tonic-gate mdb_printf("%<b>IPv4 header%</b>\n"); 5770Sstevel@tonic-gate mdb_printf("%-34s %-34s\n" 5780Sstevel@tonic-gate "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n", 5790Sstevel@tonic-gate "SRC", "DST", 5800Sstevel@tonic-gate "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM", 5810Sstevel@tonic-gate "EXP-CSUM", "FLGS"); 5820Sstevel@tonic-gate 5830Sstevel@tonic-gate hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2; 5840Sstevel@tonic-gate mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen)); 5850Sstevel@tonic-gate mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid)); 5860Sstevel@tonic-gate mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off)); 5870Sstevel@tonic-gate if (hdrlen == IP_SIMPLE_HDR_LENGTH) { 5880Sstevel@tonic-gate if ((csum = ipcksum(iph, sizeof (*iph))) != 0) 5890Sstevel@tonic-gate csum = ~(~csum + ~iph->ipha_hdr_checksum); 5900Sstevel@tonic-gate else 5910Sstevel@tonic-gate csum = iph->ipha_hdr_checksum; 5920Sstevel@tonic-gate mdb_snprintf(exp_csum, 8, "%u", csum); 5930Sstevel@tonic-gate } else { 5940Sstevel@tonic-gate mdb_snprintf(exp_csum, 8, "<n/a>"); 5950Sstevel@tonic-gate } 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate mdb_printf("%-34I %-34I%\n" 5980Sstevel@tonic-gate "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n", 5990Sstevel@tonic-gate iph->ipha_src, iph->ipha_dst, 6000Sstevel@tonic-gate hdrlen, iph->ipha_type_of_service, totlen, ipid, 6010Sstevel@tonic-gate (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol, 6020Sstevel@tonic-gate iph->ipha_hdr_checksum, exp_csum, off, ip_flags); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate if (verbose) { 6050Sstevel@tonic-gate nxt_proto = addr + hdrlen; 6060Sstevel@tonic-gate return (transport_hdr(iph->ipha_protocol, nxt_proto)); 6070Sstevel@tonic-gate } else { 6080Sstevel@tonic-gate return (DCMD_OK); 6090Sstevel@tonic-gate } 6100Sstevel@tonic-gate } 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate /* ARGSUSED */ 6130Sstevel@tonic-gate static int 6140Sstevel@tonic-gate ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 6150Sstevel@tonic-gate { 6160Sstevel@tonic-gate uint_t verbose = FALSE, force = FALSE; 6170Sstevel@tonic-gate ip6_t iph[1]; 6180Sstevel@tonic-gate int ver, class, flow; 6190Sstevel@tonic-gate uint16_t plen; 6200Sstevel@tonic-gate uintptr_t nxt_proto; 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate if (mdb_getopts(argc, argv, 6230Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, 6240Sstevel@tonic-gate 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 6250Sstevel@tonic-gate return (DCMD_USAGE); 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 6280Sstevel@tonic-gate mdb_warn("failed to read IPv6 header at %p", addr); 6290Sstevel@tonic-gate return (DCMD_ERR); 6300Sstevel@tonic-gate } 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate ver = (iph->ip6_vfc & 0xf0) >> 4; 6330Sstevel@tonic-gate if (ver != IPV6_VERSION) { 6340Sstevel@tonic-gate if (ver == IPV4_VERSION) { 6350Sstevel@tonic-gate return (iphdr(addr, flags, argc, argv)); 6360Sstevel@tonic-gate } else if (!force) { 6370Sstevel@tonic-gate mdb_warn("unknown IP version: %d\n", ver); 6380Sstevel@tonic-gate return (DCMD_ERR); 6390Sstevel@tonic-gate } 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate mdb_printf("%<b>IPv6 header%</b>\n"); 6430Sstevel@tonic-gate mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n", 6440Sstevel@tonic-gate "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP"); 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20; 6470Sstevel@tonic-gate mdb_nhconvert(&class, &class, sizeof (class)); 6480Sstevel@tonic-gate flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL; 6490Sstevel@tonic-gate mdb_nhconvert(&flow, &flow, sizeof (flow)); 6500Sstevel@tonic-gate mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen)); 6510Sstevel@tonic-gate 6520Sstevel@tonic-gate mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n", 6530Sstevel@tonic-gate &iph->ip6_src, &iph->ip6_dst, 6540Sstevel@tonic-gate class, flow, plen, iph->ip6_nxt, iph->ip6_hlim); 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate if (verbose) { 6570Sstevel@tonic-gate nxt_proto = addr + sizeof (ip6_t); 6580Sstevel@tonic-gate return (transport_hdr(iph->ip6_nxt, nxt_proto)); 6590Sstevel@tonic-gate } else { 6600Sstevel@tonic-gate return (DCMD_OK); 6610Sstevel@tonic-gate } 6620Sstevel@tonic-gate } 6630Sstevel@tonic-gate 6640Sstevel@tonic-gate int 6650Sstevel@tonic-gate ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 6660Sstevel@tonic-gate { 6670Sstevel@tonic-gate uint_t verbose = FALSE; 6680Sstevel@tonic-gate ire_t ire; 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate if (mdb_getopts(argc, argv, 6710Sstevel@tonic-gate 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 6720Sstevel@tonic-gate return (DCMD_USAGE); 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate if (verbose) { 6770Sstevel@tonic-gate mdb_printf("%?s %40s %-20s%\n" 6780Sstevel@tonic-gate "%?s %40s %-20s%\n" 6790Sstevel@tonic-gate "%<u>%?s %40s %-20s%</u>\n", 6800Sstevel@tonic-gate "ADDR", "SRC", "TYPE", 6810Sstevel@tonic-gate "", "DST", "MARKS", 6820Sstevel@tonic-gate "", "ZONE", "FLAGS"); 6830Sstevel@tonic-gate } else { 6840Sstevel@tonic-gate mdb_printf("%<u>%?s %30s %30s %4s%</u>\n", 6850Sstevel@tonic-gate "ADDR", "SRC", "DST", "ZONE"); 6860Sstevel@tonic-gate } 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if (flags & DCMD_ADDRSPEC) { 6900Sstevel@tonic-gate (void) mdb_vread(&ire, sizeof (ire_t), addr); 6910Sstevel@tonic-gate (void) ire_format(addr, &ire, &verbose); 6920Sstevel@tonic-gate } else if (mdb_walk("ire", (mdb_walk_cb_t)ire_format, &verbose) == -1) { 6930Sstevel@tonic-gate mdb_warn("failed to walk ire table"); 6940Sstevel@tonic-gate return (DCMD_ERR); 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate return (DCMD_OK); 6980Sstevel@tonic-gate } 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate static size_t 7010Sstevel@tonic-gate mi_osize(const queue_t *q) 7020Sstevel@tonic-gate { 7030Sstevel@tonic-gate /* 7040Sstevel@tonic-gate * The code in common/inet/mi.c allocates an extra word to store the 7050Sstevel@tonic-gate * size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s. 7060Sstevel@tonic-gate */ 7070Sstevel@tonic-gate struct mi_block { 7080Sstevel@tonic-gate size_t mi_nbytes; 7090Sstevel@tonic-gate struct mi_o_s mi_o; 7100Sstevel@tonic-gate } m; 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr - 7130Sstevel@tonic-gate sizeof (m)) == sizeof (m)) 7140Sstevel@tonic-gate return (m.mi_nbytes - sizeof (m)); 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate return (0); 7170Sstevel@tonic-gate } 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate static void 7200Sstevel@tonic-gate ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes) 7210Sstevel@tonic-gate { 7220Sstevel@tonic-gate char name[32]; 7230Sstevel@tonic-gate ill_t ill; 7240Sstevel@tonic-gate 7250Sstevel@tonic-gate if (mdb_vread(&ill, sizeof (ill), 7260Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill) && 7270Sstevel@tonic-gate mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0) 7280Sstevel@tonic-gate (void) mdb_snprintf(buf, nbytes, "if: %s", name); 7290Sstevel@tonic-gate } 7300Sstevel@tonic-gate 7310Sstevel@tonic-gate void 7320Sstevel@tonic-gate ip_qinfo(const queue_t *q, char *buf, size_t nbytes) 7330Sstevel@tonic-gate { 7340Sstevel@tonic-gate size_t size = mi_osize(q); 7350Sstevel@tonic-gate 7360Sstevel@tonic-gate if (size == sizeof (ill_t)) 7370Sstevel@tonic-gate ip_ill_qinfo(q, buf, nbytes); 7380Sstevel@tonic-gate } 7390Sstevel@tonic-gate 7400Sstevel@tonic-gate uintptr_t 7410Sstevel@tonic-gate ip_rnext(const queue_t *q) 7420Sstevel@tonic-gate { 7430Sstevel@tonic-gate size_t size = mi_osize(q); 7440Sstevel@tonic-gate ill_t ill; 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 7470Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill)) 7480Sstevel@tonic-gate return ((uintptr_t)ill.ill_rq); 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate return (NULL); 7510Sstevel@tonic-gate } 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate uintptr_t 7540Sstevel@tonic-gate ip_wnext(const queue_t *q) 7550Sstevel@tonic-gate { 7560Sstevel@tonic-gate size_t size = mi_osize(q); 7570Sstevel@tonic-gate ill_t ill; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 7600Sstevel@tonic-gate (uintptr_t)q->q_ptr) == sizeof (ill)) 7610Sstevel@tonic-gate return ((uintptr_t)ill.ill_wq); 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate return (NULL); 7640Sstevel@tonic-gate } 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate /* 7670Sstevel@tonic-gate * Print the core fields in an squeue_t. With the "-v" argument, 7680Sstevel@tonic-gate * provide more verbose output. 7690Sstevel@tonic-gate */ 7700Sstevel@tonic-gate static int 7710Sstevel@tonic-gate squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 7720Sstevel@tonic-gate { 7730Sstevel@tonic-gate unsigned int i; 7740Sstevel@tonic-gate unsigned int verbose = FALSE; 7750Sstevel@tonic-gate const int SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9); 7760Sstevel@tonic-gate boolean_t arm; 7770Sstevel@tonic-gate squeue_t squeue; 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate if (!(flags & DCMD_ADDRSPEC)) { 7800Sstevel@tonic-gate if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue", 7810Sstevel@tonic-gate argc, argv) == -1) { 7820Sstevel@tonic-gate mdb_warn("failed to walk squeue cache"); 7830Sstevel@tonic-gate return (DCMD_ERR); 7840Sstevel@tonic-gate } 7850Sstevel@tonic-gate return (DCMD_OK); 7860Sstevel@tonic-gate } 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 7890Sstevel@tonic-gate != argc) 7900Sstevel@tonic-gate return (DCMD_USAGE); 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate if (!DCMD_HDRSPEC(flags) && verbose) 7930Sstevel@tonic-gate mdb_printf("\n\n"); 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate if (DCMD_HDRSPEC(flags) || verbose) { 7960Sstevel@tonic-gate mdb_printf("%?s %-5s %-3s %?s %?s %?s\n", 7970Sstevel@tonic-gate "ADDR", "STATE", "CPU", 7980Sstevel@tonic-gate "FIRST", "LAST", "WORKER"); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) { 8020Sstevel@tonic-gate mdb_warn("cannot read squeue_t at %p", addr); 8030Sstevel@tonic-gate return (DCMD_ERR); 8040Sstevel@tonic-gate } 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n", 8070Sstevel@tonic-gate addr, squeue.sq_state, squeue.sq_bind, 8080Sstevel@tonic-gate squeue.sq_first, squeue.sq_last, squeue.sq_worker); 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate if (!verbose) 8110Sstevel@tonic-gate return (DCMD_OK); 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate arm = B_TRUE; 8140Sstevel@tonic-gate for (i = 0; squeue_states[i].bit_name != NULL; i++) { 8150Sstevel@tonic-gate if (((squeue.sq_state) & (1 << i)) == 0) 8160Sstevel@tonic-gate continue; 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate if (arm) { 8190Sstevel@tonic-gate mdb_printf("%*s|\n", SQUEUE_STATEDELT, ""); 8200Sstevel@tonic-gate mdb_printf("%*s+--> ", SQUEUE_STATEDELT, ""); 8210Sstevel@tonic-gate arm = B_FALSE; 8220Sstevel@tonic-gate } else 8230Sstevel@tonic-gate mdb_printf("%*s ", SQUEUE_STATEDELT, ""); 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate mdb_printf("%-12s %s\n", squeue_states[i].bit_name, 8260Sstevel@tonic-gate squeue_states[i].bit_descr); 8270Sstevel@tonic-gate } 8280Sstevel@tonic-gate 8290Sstevel@tonic-gate return (DCMD_OK); 8300Sstevel@tonic-gate } 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate static void 8330Sstevel@tonic-gate ip_squeue_help(void) 8340Sstevel@tonic-gate { 8350Sstevel@tonic-gate mdb_printf("Print the core information for a given NCA squeue_t.\n\n"); 8360Sstevel@tonic-gate mdb_printf("Options:\n"); 8370Sstevel@tonic-gate mdb_printf("\t-v\tbe verbose (more descriptive)\n"); 8380Sstevel@tonic-gate } 8390Sstevel@tonic-gate 8400Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = { 8410Sstevel@tonic-gate { "illif", "?[-P v4 | v6]", 8420Sstevel@tonic-gate "display or filter IP Lower Level InterFace structures", illif, 8430Sstevel@tonic-gate illif_help }, 8440Sstevel@tonic-gate { "iphdr", ":[-vf]", "display an IPv4 header", iphdr }, 8450Sstevel@tonic-gate { "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr }, 8460Sstevel@tonic-gate { "ire", "?[-v]", "display Internet Route Entry structures", ire }, 8470Sstevel@tonic-gate { "squeue", ":[-v]", "print core squeue_t info", squeue, 8480Sstevel@tonic-gate ip_squeue_help }, 8490Sstevel@tonic-gate { "tcphdr", ":", "display a TCP header", tcphdr }, 8500Sstevel@tonic-gate { "udphdr", ":", "display an UDP header", udphdr }, 8510Sstevel@tonic-gate { "sctphdr", ":", "display an SCTP header", sctphdr }, 8520Sstevel@tonic-gate { NULL } 8530Sstevel@tonic-gate }; 8540Sstevel@tonic-gate 8550Sstevel@tonic-gate static const mdb_walker_t walkers[] = { 8560Sstevel@tonic-gate { "illif", "walk list of ill interface types", 8570Sstevel@tonic-gate illif_walk_init, illif_walk_step, illif_walk_fini }, 8580Sstevel@tonic-gate { "ire", "walk active ire_t structures", 8590Sstevel@tonic-gate ire_walk_init, ire_walk_step, NULL }, 8600Sstevel@tonic-gate { NULL } 8610Sstevel@tonic-gate }; 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext }; 8640Sstevel@tonic-gate static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 8650Sstevel@tonic-gate 8660Sstevel@tonic-gate const mdb_modinfo_t * 8670Sstevel@tonic-gate _mdb_init(void) 8680Sstevel@tonic-gate { 8690Sstevel@tonic-gate GElf_Sym sym; 8700Sstevel@tonic-gate 871*2546Scarlsonj if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 8720Sstevel@tonic-gate mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value); 8730Sstevel@tonic-gate 8740Sstevel@tonic-gate return (&modinfo); 8750Sstevel@tonic-gate } 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate void 8780Sstevel@tonic-gate _mdb_fini(void) 8790Sstevel@tonic-gate { 8800Sstevel@tonic-gate GElf_Sym sym; 8810Sstevel@tonic-gate 882*2546Scarlsonj if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 8830Sstevel@tonic-gate mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value); 8840Sstevel@tonic-gate } 885