ip.c revision 0870f17b1158eef95a9cbc509c015c6467c7cdec
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <sys/avl_impl.h>
#include <net/if_types.h>
#include <inet/ipclassifier.h>
#include <sys/squeue_impl.h>
#include <sys/modhash_impl.h>
#include <ilb.h>
#include <ilb/ilb_impl.h>
#include <ilb/ilb_stack.h>
#include <ilb/ilb_conn.h>
#include <mdb/mdb_modapi.h>
#define ADDR_WIDTH 11
#define L2MAXADDRSTRLEN 255
#define MAX_SAP_LEN 255
#define DEFCOLS 80
typedef struct {
const char *bit_name; /* name of bit */
const char *bit_descr; /* description of bit's purpose */
} bitname_t;
static const bitname_t squeue_states[] = {
{ "SQS_PROC", "being processed" },
{ "SQS_WORKER", "... by a worker thread" },
{ "SQS_ENTER", "... by an squeue_enter() thread" },
{ "SQS_FAST", "... in fast-path mode" },
{ "SQS_USER", "A non interrupt user" },
{ "SQS_BOUND", "worker thread bound to CPU" },
{ "SQS_PROFILE", "profiling enabled" },
{ "SQS_REENTER", "re-entered thred" },
{ NULL }
};
typedef struct illif_walk_data {
int ill_list;
typedef struct ncec_walk_data_s {
struct ndp_g_s ncec_ip_ndp;
int ncec_hash_tbl_index;
typedef struct ncec_cbdata_s {
int ncec_ipversion;
typedef struct nce_cbdata_s {
int nce_ipversion;
char nce_ill_name[LIFNAMSIZ];
} nce_cbdata_t;
typedef struct ire_cbdata_s {
int ire_ipversion;
} ire_cbdata_t;
typedef struct zi_cbdata_s {
const char *zone_name;
} zi_cbdata_t;
typedef struct th_walk_data {
typedef struct ipcl_hash_walk_data_s {
int connf_tbl_index;
int hash_tbl_size;
typedef struct ill_walk_data_s {
typedef struct ill_cbdata_s {
int ill_ipversion;
} ill_cbdata_t;
typedef struct ipif_walk_data_s {
typedef struct ipif_cbdata_s {
int ipif_ipversion;
typedef struct hash_walk_arg_s {
static hash_walk_arg_t udp_hash_arg = {
};
static hash_walk_arg_t conn_hash_arg = {
};
static hash_walk_arg_t bind_hash_arg = {
};
static hash_walk_arg_t proto_hash_arg = {
0
};
static hash_walk_arg_t proto_v6_hash_arg = {
0
};
typedef struct ip_list_walk_data_s {
typedef struct ip_list_walk_arg_s {
static ip_list_walk_arg_t ipif_walk_arg = {
sizeof (ipif_t),
};
static ip_list_walk_arg_t srcid_walk_arg = {
sizeof (srcid_map_t),
};
static void ill_help(void);
static int ill_walk_init(mdb_walk_state_t *);
static int ill_walk_step(mdb_walk_state_t *);
static int ill_format(uintptr_t, const void *, void *);
static void ill_header(boolean_t);
static void ipif_help(void);
static int ipif_walk_init(mdb_walk_state_t *);
static int ipif_walk_step(mdb_walk_state_t *);
static int ipif_format(uintptr_t, const void *, void *);
static void ipif_header(boolean_t);
static int ip_list_walk_init(mdb_walk_state_t *);
static int ip_list_walk_step(mdb_walk_state_t *);
static void ip_list_walk_fini(mdb_walk_state_t *);
static int srcid_walk_step(mdb_walk_state_t *);
ncec_cbdata_t *id);
static int ipcl_hash_walk_init(mdb_walk_state_t *);
static int ipcl_hash_walk_step(mdb_walk_state_t *);
static void ipcl_hash_walk_fini(mdb_walk_state_t *);
static int conn_status_walk_step(mdb_walk_state_t *);
static void conn_status_help(void);
static int ilb_stacks_walk_step(mdb_walk_state_t *);
static int ilb_rules_walk_init(mdb_walk_state_t *);
static int ilb_rules_walk_step(mdb_walk_state_t *);
static int ilb_servers_walk_init(mdb_walk_state_t *);
static int ilb_servers_walk_step(mdb_walk_state_t *);
static int ilb_nat_src_walk_init(mdb_walk_state_t *);
static int ilb_nat_src_walk_step(mdb_walk_state_t *);
static int ilb_conn_walk_init(mdb_walk_state_t *);
static int ilb_conn_walk_step(mdb_walk_state_t *);
static int ilb_sticky_walk_init(mdb_walk_state_t *);
static int ilb_sticky_walk_step(mdb_walk_state_t *);
static void ilb_common_walk_fini(mdb_walk_state_t *);
/*
* Given the kernel address of an ip_stack_t, return the stackid
*/
static int
{
return (0);
}
return (0);
}
return (nss.netstack_stackid);
}
/* ARGSUSED */
static int
{
char zone_name[ZONENAME_MAX];
return (WALK_ERR);
}
return (WALK_NEXT);
== -1) {
return (WALK_ERR);
}
return (WALK_DONE);
}
static ip_stack_t *
zone_to_ips(const char *zone_name)
{
return (NULL);
mdb_warn("failed to walk zone");
return (NULL);
}
if (zi_cb.shared_ip_zone) {
mdb_warn("%s is a Shared-IP zone, try '-s global' instead\n",
return (NULL);
}
return (NULL);
}
}
/*
* Generic network stack walker initialization function. It is used by all
* other netwrok stack walkers.
*/
int
{
mdb_warn("can't walk 'netstack'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
/*
* Generic network stack walker stepping function. It is used by all other
* network stack walkers. The which parameter differentiates the different
* walkers.
*/
int
{
return (WALK_ERR);
}
}
/*
* IP network stack walker stepping function.
*/
int
{
}
/*
* TCP network stack walker stepping function.
*/
int
{
}
/*
* SCTP network stack walker stepping function.
*/
int
{
}
/*
* UDP network stack walker stepping function.
*/
int
{
}
/*
* Initialization function for the per CPU TCP stats counter walker of a given
* TCP stack.
*/
int
{
return (WALK_ERR);
return (WALK_ERR);
}
if (tcps.tcps_sc_cnt == 0)
return (WALK_DONE);
/*
* Store the tcp_stack_t pointer in walk_data. The stepping function
* used it to calculate if the end of the counter has reached.
*/
return (WALK_NEXT);
}
/*
* Stepping function for the per CPU TCP stats counterwalker.
*/
int
{
int status;
return (WALK_ERR);
}
mdb_warn("failed ot read tcp_stats_cpu_t at %p",
return (WALK_ERR);
}
return (status);
sizeof (tcp_stats_cpu_t *);
return (WALK_DONE);
return (WALK_NEXT);
}
int
{
} else {
mdb_warn("unable to locate ip_thread_list\n");
return (WALK_ERR);
}
}
mdb_warn("non-DEBUG image; cannot walk th_hash list\n");
return (WALK_ERR);
}
mdb_warn("can't walk 'list'");
return (WALK_ERR);
} else {
return (WALK_NEXT);
}
}
int
{
wsp->walk_cbdata));
}
/*
* Called with walk_addr being the address of ips_ill_g_heads
*/
int
{
mdb_warn("illif_stack supports only local walks\n");
return (WALK_ERR);
}
mdb_warn("failed to read 'ips_ill_g_heads' at %p",
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
return (WALK_ERR);
}
if (++list >= MAX_G_HEADS)
return (WALK_DONE);
return (WALK_NEXT);
}
}
void
{
}
typedef struct illif_cbdata {
int ill_printlist; /* list to be printed (MAX_G_HEADS for all) */
static int
{
const char *version;
return (WALK_NEXT);
return (WALK_NEXT);
return (WALK_NEXT);
}
default: version = "??"; break;
}
mdb_printf("%?p %2s %?p %10d %?p %s\n",
return (WALK_NEXT);
}
int
{
mdb_warn("can't walk 'ip_stacks'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
return (WALK_ERR);
}
mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p",
kaddr);
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
int printlist = MAX_G_HEADS;
return (DCMD_USAGE);
} else {
return (DCMD_USAGE);
}
}
mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n",
"ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME");
}
mdb_warn("can't walk ill_if_t structures");
return (DCMD_ERR);
}
return (DCMD_OK);
/*
* If an address is specified and the walk doesn't find it,
* print it anyway.
*/
return (DCMD_ERR);
}
mdb_printf("%?p %2s %?p %10d %?p %s\n",
return (DCMD_OK);
}
static void
illif_help(void)
{
mdb_printf("Options:\n");
mdb_printf("\t-P v4 | v6"
"\tfilter interface structures for the specified protocol\n");
}
int
{
mdb_warn("can't walk 'nce_cache'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
return (WALK_ERR);
}
}
static int
{
return (WALK_NEXT);
}
if (nce_cb->nce_ipversion != 0 &&
return (WALK_NEXT);
} else {
(void) mdb_readstr(ill_name,
}
return (WALK_NEXT);
mdb_printf("%?p %5s %-18s %?p %6d %N\n",
} else {
mdb_printf("%?p %5s %-18s %?p %6d %I\n",
}
return (WALK_NEXT);
}
int
{
mdb_warn("can't walk 'dce_cache'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
return (WALK_ERR);
}
/* If ip_stack_t is specified, skip DCEs that don't belong to it. */
return (WALK_NEXT);
}
int
{
mdb_warn("can't walk 'ire_cache'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
int
{
return (WALK_ERR);
}
/* If ip_stack_t is specified, skip IREs that don't belong to it. */
return (WALK_NEXT);
}
/* ARGSUSED */
int
{
return (WALK_NEXT);
}
int
{
int status;
return (WALK_DONE);
return (WALK_ERR);
}
wsp->walk_cbdata);
return (status);
return (status);
}
static int
{
static const mdb_bitmask_t tmasks[] = {
{ NULL, 0, 0 }
};
static const mdb_bitmask_t fmasks[] = {
{ NULL, 0, 0 }
};
if (ire_cb->ire_ipversion != 0 &&
return (WALK_NEXT);
} else {
(void) mdb_readstr(ill_name,
}
mdb_printf("%<b>%?p%</b>%3s %40N <%hb%s>\n"
"%?s %40N\n"
"%?s %40d %4d <%hb> %s\n",
mdb_printf("%?p%3s %30N %30N %5d %4d %s\n",
&irep->ire_addr_v6,
} else if (verbose) {
mdb_printf("%<b>%?p%</b>%3s %40I <%hb%s>\n"
"%?s %40I\n"
"%?s %40d %4d <%hb> %s\n",
} else {
}
return (WALK_NEXT);
}
/*
* There are faster ways to do this. Given the interactive nature of this
* use I don't think its worth much effort.
*/
static unsigned short
{
while (len > 1) {
/* alignment */
p = (char *)p + sizeof (uint16_t);
if (sum & 0x80000000)
len -= 2;
}
if (len)
while (sum >> 16)
return (~sum);
}
static const mdb_bitmask_t tcp_flags[] = {
{ NULL, 0, 0 }
};
/* TCP option length */
#define TCPOPT_HEADER_LEN 2
#define TCPOPT_MAXSEG_LEN 4
#define TCPOPT_WS_LEN 3
#define TCPOPT_TSTAMP_LEN 10
#define TCPOPT_SACK_OK_LEN 2
static void
{
mdb_printf("%<b>Options:%</b>");
switch (*opts) {
case TCPOPT_EOL:
mdb_printf(" EOL");
opts++;
break;
case TCPOPT_NOP:
mdb_printf(" NOP");
opts++;
break;
case TCPOPT_MAXSEG: {
if (len < TCPOPT_MAXSEG_LEN ||
mdb_printf(" <Truncated MSS>\n");
return;
}
sizeof (mss));
break;
}
case TCPOPT_WSCALE:
mdb_printf(" <Truncated WS>\n");
return;
}
opts += TCPOPT_WS_LEN;
break;
case TCPOPT_TSTAMP: {
if (len < TCPOPT_TSTAMP_LEN ||
mdb_printf(" <Truncated TS>\n");
return;
}
break;
}
case TCPOPT_SACK_PERMITTED:
if (len < TCPOPT_SACK_OK_LEN ||
mdb_printf(" <Truncated SACK_OK>\n");
return;
}
mdb_printf(" SACK_OK");
break;
case TCPOPT_SACK: {
mdb_printf(" <Truncated SACK>\n");
return;
}
mdb_printf(" SACK=");
while (sack_len > 0) {
mdb_printf("<Truncated SACK>\n");
break;
}
}
break;
}
default:
opts[1]);
break;
}
}
mdb_printf("\n");
}
static void
{
mdb_printf("%<b>TCP header%</b>\n");
mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n",
"SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP",
"FLAGS");
mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n",
mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n",
}
/* ARGSUSED */
static int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
tcphdr_print(&tcph);
/* If there are options, print them out also. */
if (opt_len > 0) {
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static void
{
mdb_printf("%<b>UDP header%</b>\n");
mdb_printf("%<u>%14s %14s %5s %6s%</u>\n",
"SPORT", "DPORT", "LEN", "CSUM");
}
/* ARGSUSED */
static int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
udphdr_print(&udph);
return (DCMD_OK);
}
static void
{
mdb_printf("%<b>SCTP header%</b>\n");
mdb_printf("%<u>%14s %14s %10s %10s%</u>\n",
"SPORT", "DPORT", "VTAG", "CHKSUM");
}
/* ARGSUSED */
static int
{
if (!(flags & DCMD_ADDRSPEC))
return (DCMD_USAGE);
return (DCMD_ERR);
}
return (DCMD_OK);
}
static int
{
mdb_printf("\n");
switch (proto) {
case IPPROTO_TCP: {
return (DCMD_ERR);
}
tcphdr_print(&tcph);
break;
}
case IPPROTO_UDP: {
return (DCMD_ERR);
}
udphdr_print(&udph);
break;
}
case IPPROTO_SCTP: {
return (DCMD_ERR);
}
break;
}
default:
break;
}
return (DCMD_OK);
}
static const mdb_bitmask_t ip_flags[] = {
{ NULL, 0, 0 }
};
/* ARGSUSED */
static int
{
char exp_csum[8];
return (DCMD_USAGE);
return (DCMD_ERR);
}
if (ver != IPV4_VERSION) {
if (ver == IPV6_VERSION) {
} else if (!force) {
return (DCMD_ERR);
}
}
mdb_printf("%<b>IPv4 header%</b>\n");
mdb_printf("%-34s %-34s\n"
"%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n",
"SRC", "DST",
"HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM",
"EXP-CSUM", "FLGS");
if (hdrlen == IP_SIMPLE_HDR_LENGTH) {
else
} else {
}
mdb_printf("%-34I %-34I%\n"
"%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n",
if (verbose) {
} else {
return (DCMD_OK);
}
}
/* ARGSUSED */
static int
{
return (DCMD_USAGE);
return (DCMD_ERR);
}
if (ver != IPV6_VERSION) {
if (ver == IPV4_VERSION) {
} else if (!force) {
return (DCMD_ERR);
}
}
mdb_printf("%<b>IPv6 header%</b>\n");
mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n",
"SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP");
mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n",
if (verbose) {
} else {
return (DCMD_OK);
}
}
int
{
int ipversion = 0;
return (DCMD_USAGE);
} else {
return (DCMD_USAGE);
}
}
mdb_printf("%<u>%?s %5s %18s %?s %s %s %</u>\n",
"ADDR", "INTF", "LLADDR", "FP_MP", "REFCNT",
"NCE_ADDR");
}
}
if (flags & DCMD_ADDRSPEC) {
mdb_warn("failed to walk ire table");
return (DCMD_ERR);
}
return (DCMD_OK);
}
/* ARGSUSED */
static int
{
static const mdb_bitmask_t dmasks[] = {
{ NULL, 0, 0 }
};
int ipversion = *(int *)dce_cb_arg;
return (WALK_NEXT);
dmasks);
switch (dcep->dce_ipversion) {
case IPV4_VERSION:
break;
case IPV6_VERSION:
break;
default:
}
return (WALK_NEXT);
}
int
{
int ipversion = 0;
return (DCMD_USAGE);
/* Follow the specified zone name to find a ip_stack_t*. */
return (DCMD_USAGE);
}
} else {
return (DCMD_USAGE);
}
}
mdb_printf("%<u>%?s%3s %8s %8s %30s %</u>\n",
"ADDR", "", "FLAGS", "PMTU", "DST_ADDR");
}
if (flags & DCMD_ADDRSPEC) {
mdb_warn("failed to walk dce cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
int
{
int ipversion = 0;
return (DCMD_USAGE);
/* Follow the specified zone name to find a ip_stack_t*. */
return (DCMD_USAGE);
}
} else {
return (DCMD_USAGE);
}
}
if (verbose) {
mdb_printf("%?s %40s %-20s%\n"
"%?s %40s %-20s%\n"
"%<u>%?s %40s %4s %-20s %s%</u>\n",
"ADDR", "SRC", "TYPE",
"", "DST", "MARKS",
"", "STACK", "ZONE", "FLAGS", "INTF");
} else {
mdb_printf("%<u>%?s %30s %30s %5s %4s %s%</u>\n",
"ADDR", "SRC", "DST", "STACK", "ZONE", "INTF");
}
}
if (flags & DCMD_ADDRSPEC) {
mdb_warn("failed to walk ire table");
return (DCMD_ERR);
}
return (DCMD_OK);
}
static size_t
{
/*
* size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s.
*/
struct mi_block {
} m;
sizeof (m)) == sizeof (m))
return (m.mi_nbytes - sizeof (m));
return (0);
}
static void
{
char name[32];
}
void
{
}
{
return (NULL);
}
{
return (NULL);
}
/*
* Print the core fields in an squeue_t. With the "-v" argument,
* provide more verbose output.
*/
static int
{
unsigned int i;
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("failed to walk squeue cache");
return (DCMD_ERR);
}
return (DCMD_OK);
}
!= argc)
return (DCMD_USAGE);
mdb_printf("\n\n");
mdb_printf("%?s %-5s %-3s %?s %?s %?s\n",
"ADDR", "STATE", "CPU",
"FIRST", "LAST", "WORKER");
}
return (DCMD_ERR);
}
mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n",
if (!verbose)
return (DCMD_OK);
continue;
if (arm) {
} else
squeue_states[i].bit_descr);
}
return (DCMD_OK);
}
static void
ip_squeue_help(void)
{
mdb_printf("Print the core information for a given NCA squeue_t.\n\n");
mdb_printf("Options:\n");
mdb_printf("\t-v\tbe verbose (more descriptive)\n");
}
/*
* This is called by ::th_trace (via a callback) when walking the th_hash
* list. It calls modent to find the entries.
*/
/* ARGSUSED */
static int
{
return (WALK_ERR);
}
return (WALK_NEXT);
int i, j, k;
i = th.th_trace_lastref;
for (j = TR_BUF_MAX; j > 0; j--) {
break;
if (--i < 0)
i = TR_BUF_MAX - 1;
}
}
return (WALK_NEXT);
}
/*
* This is called by ::th_trace (via a callback) when walking the th_hash
* list. It calls modent to find the entries.
*/
/* ARGSUSED */
static int
{
}
/*
* Print or summarize the th_trace_t structures.
*/
static int
{
return (DCMD_USAGE);
if (!(flags & DCMD_ADDRSPEC)) {
/*
* No address specified. Walk all of the th_hash_t in the
* system, and summarize the th_trace_t entries in each.
*/
mdb_printf("%?s %?s %?s %8s %?s\n",
"IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD");
} else {
mdb_warn("failed to read lbolt");
return (DCMD_ERR);
}
}
mdb_warn("can't walk th_hash entries");
return (DCMD_ERR);
}
return (DCMD_OK);
}
static void
th_trace_help(void)
{
mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or ncec_t, "
"print the\n"
"corresponding th_trace_t structure in detail. Otherwise, if no "
"address is\n"
"given, then summarize all th_trace_t structures.\n\n");
mdb_printf("Options:\n"
"\t-n\tdisplay only entries with non-zero th_refcnt\n");
}
static const mdb_dcmd_t dcmds[] = {
{ "conn_status", ":",
"display connection structures from ipcl hash tables",
{ "srcid_status", ":",
"display connection structures from ipcl hash tables",
srcid_status },
{ "ill", "?[-v] [-P v4 | v6] [-s exclusive-ip-zone-name]",
{ "illif", "?[-P v4 | v6]",
"display or filter IP Lower Level InterFace structures", illif,
illif_help },
{ "ipif", "?[-v] [-P v4 | v6]", "display ipif structures",
{ "ire", "?[-v] [-P v4|v6] [-s exclusive-ip-zone-name]",
"display Internet Route Entry structures", ire },
{ "nce", "?[-P v4|v6] [-i <interface>]",
"display interface-specific Neighbor Cache structures", nce },
{ "ncec", "?[-P v4 | v6]", "display Neighbor Cache Entry structures",
ncec },
{ "dce", "?[-P v4|v6] [-s exclusive-ip-zone-name]",
"display Destination Cache Entry structures", dce },
{ NULL }
};
static const mdb_walker_t walkers[] = {
{ "conn_status", "walk list of conn_t structures",
{ "illif", "walk list of ill interface types for all stacks",
{ "illif_stack", "walk list of ill interface types",
{ "ill", "walk active ill_t structures for all stacks",
{ "ipif", "walk list of ipif structures for all stacks",
{ "ipif_list", "walk the linked list of ipif structures "
"for a given ill",
{ "srcid", "walk list of srcid_map structures for all stacks",
{ "srcid_list", "walk list of srcid_map structures for a stack",
&srcid_walk_arg },
{ "ire", "walk active ire_t structures",
{ "ire_next", "walk ire_t structures in the ctable",
{ "nce", "walk active nce_t structures",
{ "dce", "walk active dce_t structures",
{ "ip_stacks", "walk all the ip_stack_t",
{ "tcp_stacks", "walk all the tcp_stack_t",
{ "sctp_stacks", "walk all the sctp_stack_t",
{ "udp_stacks", "walk all the udp_stack_t",
{ "th_hash", "walk all the th_hash_t entries",
{ "ncec", "walk list of ncec structures for all stacks",
{ "ncec_stack", "walk list of ncec structures",
{ "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout",
{ "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout",
{ "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout",
{ "proto_hash", "walk list of conn_t structures in "
"ips_ipcl_proto_fanout",
{ "proto_v6_hash", "walk list of conn_t structures in "
"ips_ipcl_proto_fanout_v6",
{ "ilb_stacks", "walk all ilb_stack_t",
{ "ilb_rules", "walk ilb rules in a given ilb_stack_t",
{ "ilb_servers", "walk server in a given ilb_rule_t",
{ "ilb_nat_src", "walk NAT source table of a given ilb_stack_t",
{ "ilb_conns", "walk NAT table of a given ilb_stack_t",
{ "ilb_stickys", "walk sticky table of a given ilb_stack_t",
{ "tcps_sc", "walk all the per CPU stats counters of a tcp_stack_t",
{ NULL }
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&modinfo);
}
void
_mdb_fini(void)
{
}
static char *
ncec_state(int ncec_state)
{
switch (ncec_state) {
case ND_UNCHANGED:
return ("unchanged");
case ND_INCOMPLETE:
return ("incomplete");
case ND_REACHABLE:
return ("reachable");
case ND_STALE:
return ("stale");
case ND_DELAY:
return ("delay");
case ND_PROBE:
return ("probe");
case ND_UNREACHABLE:
return ("unreach");
case ND_INITIAL:
return ("initial");
default:
return ("??");
}
}
static char *
{
uchar_t *h;
static char addr_buf[L2MAXADDRSTRLEN];
return ("None");
}
if (ill->ill_phys_addr_length == 0)
return ("None");
mdb_warn("failed to read hwaddr at %p",
ncec->ncec_lladdr);
return ("Unknown");
}
} else {
return ("None");
}
return (addr_buf);
}
static char *
{
uchar_t *h;
static char addr_buf[L2MAXADDRSTRLEN];
return ("None");
mdb_warn("failed to read nce_dlur_mp at %p",
nce->nce_dlur_mp);
return ("None");
}
if (ill->ill_phys_addr_length == 0)
return ("None");
return ("Unknown");
}
mdb_warn("failed to read hwaddr at %p",
return ("Unknown");
}
} else {
return ("None");
}
return (addr_buf);
}
static void
{
mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n",
"ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR");
}
}
int
{
int ipversion = 0;
return (DCMD_USAGE);
} else {
return (DCMD_USAGE);
}
}
if (flags & DCMD_ADDRSPEC) {
return (DCMD_ERR);
}
mdb_printf("IP Version mismatch\n");
return (DCMD_ERR);
}
} else {
mdb_warn("failed to walk ncec table\n");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static int
{
static const mdb_bitmask_t ncec_flags[] = {
{ NULL, 0, 0 }
};
char flagsbuf[NCE_MAX_FLAGS];
mdb_warn("failed to read ncec_ill at %p",
return (DCMD_ERR);
}
return (DCMD_OK);
mdb_printf("%?p %-20s %-10s "
"%-8s "
"%-5s %I\n",
} else {
mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n",
}
return (DCMD_OK);
}
static uintptr_t
{
int i = *index;
if (++i >= NCE_TABLE_SIZE)
break;
}
*index = i;
return (addr);
}
static int
{
return (WALK_ERR);
}
return (WALK_ERR);
}
kaddr4) == -1) {
mdb_warn("couldn't walk 'ncec_stack' for ips_ndp4 %p",
kaddr4);
return (WALK_ERR);
}
mdb_warn("couldn't walk 'ncec_stack' for ips_ndp6 %p",
kaddr6);
return (WALK_ERR);
}
return (WALK_NEXT);
}
static uintptr_t
{
do {
break;
}
return (NULL);
}
return (addr);
}
static int
{
return (WALK_ERR);
}
} else {
sizeaddr) == -1) {
mdb_warn("can't read fanout table size addr at %p",
sizeaddr);
return (WALK_ERR);
}
}
iw->connf_tbl_index = 0;
return (WALK_NEXT);
else
return (WALK_DONE);
}
static int
{
return (WALK_ERR);
}
break;
}
return (WALK_NEXT);
else
return (WALK_DONE);
}
return (ret);
}
static void
{
}
/*
* Called with walk_addr being the address of ips_ndp{4,6}
*/
static int
{
mdb_warn("ncec_stack requires ndp_g_s address\n");
return (WALK_ERR);
}
mdb_warn("failed to read 'ip_ndp' at %p",
return (WALK_ERR);
}
/*
* ncec_get_next_hash_tbl() starts at ++i , so initialize index to -1
*/
return (WALK_NEXT);
}
static int
{
return (WALK_DONE);
return (WALK_ERR);
}
}
static void
{
}
/* ARGSUSED */
static int
{
return (WALK_NEXT);
}
return (WALK_NEXT);
}
static int
{
mdb_warn("can't walk 'illif'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
return (WALK_ERR);
}
mdb_warn("can't walk 'avl'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
/* ARGSUSED */
static int
{
return (WALK_NEXT);
}
/* If ip_stack_t is specified, skip ILLs that don't belong to it. */
return (WALK_NEXT);
}
static void
{
if (verbose) {
mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n",
"ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS");
mdb_printf("%-?s %4s%4s %-?s\n",
"PHYINT", "CNT", "", "GROUP");
} else {
mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n",
"ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS");
}
}
static int
{
static const mdb_bitmask_t fmasks[] = {
{ NULL, 0, 0 }
};
static const mdb_bitmask_t v_fmasks[] = {
{ NULL, 0, 0 }
};
int cnt;
char *typebuf;
if (ipver != 0) {
return (WALK_NEXT);
}
}
mdb_warn("failed to read ill_phyint at %p",
return (WALK_NEXT);
}
case 0:
typebuf = "LOOPBACK";
break;
case IFT_ETHER:
typebuf = "ETHER";
break;
case IFT_OTHER:
typebuf = "OTHER";
break;
default:
break;
}
mdb_printf("%-?p %-8s %-3s ",
else
if (verbose) {
mdb_printf("%-?p %-?p %-llb\n",
mdb_printf("%-?p %4d%4s %-?p\n",
mdb_printf("%s|\n%s+--> %3d %-18s "
"references from active threads\n",
mdb_printf("%*s %7d %-18s ires referencing this ill\n",
mdb_printf("%*s %7d %-18s nces referencing this ill\n",
mdb_printf("%*s %7d %-18s ncecs referencing this ill\n",
mdb_printf("%*s %7d %-18s ilms referencing this ill\n",
} else {
mdb_printf("%4d %-?p %-llb\n",
}
return (WALK_NEXT);
}
static int
{
int ipversion = 0;
return (DCMD_USAGE);
/* Follow the specified zone name to find a ip_stack_t*. */
return (DCMD_USAGE);
}
} else {
return (DCMD_USAGE);
}
}
if (flags & DCMD_ADDRSPEC) {
return (DCMD_ERR);
}
} else {
mdb_warn("failed to walk ills\n");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static void
ill_help(void)
{
mdb_printf("Prints the following fields: ill ptr, name, "
"IP version, count, ill type and ill flags.\n"
"The count field is a sum of individual refcnts and is expanded "
"with the -v option.\n\n");
mdb_printf("Options:\n");
mdb_printf("\t-P v4 | v6"
"\tfilter ill structures for the specified protocol\n");
}
static int
{
mdb_warn("only local walks supported\n");
return (WALK_ERR);
}
addr) == -1) {
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
return (WALK_DONE);
return (WALK_ERR);
}
}
static void
{
}
static int
{
mdb_warn("can't walk 'ills'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
mdb_warn("can't walk 'ipif_list'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
/* ARGSUSED */
static int
{
return (WALK_NEXT);
}
return (WALK_NEXT);
}
return (WALK_NEXT);
}
static void
{
if (verbose) {
mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n",
"ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
mdb_printf("%s\n%s\n",
"LCLADDR", "BROADCAST");
} else {
mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n",
"ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS");
}
}
#ifdef _BIG_ENDIAN
#define ip_ntohl_32(x) ((x) & 0xffffffff)
#else
((uint32_t)(x) >> 24))
#endif
int
{
int len = 0;
int i;
for (i = 0; i < 4; i++) {
len += 32;
} else {
break;
}
}
} else {
}
if (mask > 0)
return (len);
}
static int
{
int cnt;
static const mdb_bitmask_t sfmasks[] = {
{ NULL, 0, 0 }
};
static const mdb_bitmask_t fmasks[] = {
{ NULL, 0, 0 }
};
int af;
if (ipver != 0) {
return (WALK_NEXT);
}
}
return (WALK_NEXT);
}
} else {
}
&ipif->ipif_v6lcl_addr);
} else {
}
if (verbose) {
mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n",
mdb_printf("%s |\n%s +---> %4d %-15s "
"Active consistent reader cnt\n",
mdb_printf("%-s/%d\n",
} else {
mdb_printf("%-I\n",
}
} else {
mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n",
mdb_printf("%-s/%d\n",
}
return (WALK_NEXT);
}
static int
{
int ipversion = 0;
return (DCMD_USAGE);
} else {
return (DCMD_USAGE);
}
}
if (flags & DCMD_ADDRSPEC) {
return (DCMD_ERR);
}
return (WALK_NEXT);
}
} else {
mdb_warn("failed to walk ipifs\n");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static void
ipif_help(void)
{
mdb_printf("Prints the following fields: ipif ptr, name, "
"count, ill ptr, state flags and ipif flags.\n"
"The count field is a sum of individual refcnts and is expanded "
"with the -v option.\n"
"The flags field shows the following:"
"\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, "
"\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, "
"\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, "
"\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, "
"\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, "
"\n\tWU -> ipif_was_up, WD -> ipif_was_dup, "
"JA -> ipif_joined_allhosts.\n\n");
mdb_printf("Options:\n");
mdb_printf("\t-P v4 | v6"
"\tfilter ipif structures on ills for the specified protocol\n");
}
static int
const char *walkname)
{
addr) == -1) {
return (WALK_ERR);
}
return (WALK_NEXT);
}
static int
{
return (WALK_NEXT);
}
/* ARGSUSED */
static int
void *private)
{
char src_addrstr[INET6_ADDRSTRLEN];
char rem_addrstr[INET6_ADDRSTRLEN];
return (WALK_ERR);
}
mdb_warn("failed to read netstack_t %p",
return (WALK_ERR);
}
&conn->conn_laddr_v6);
&conn->conn_faddr_v6);
} else {
}
mdb_printf("%s:%-5d\n%s:%-5d\n",
return (WALK_NEXT);
}
static void
conn_header(void)
{
mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n",
"ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT");
}
/*ARGSUSED*/
static int
{
conn_header();
if (flags & DCMD_ADDRSPEC) {
} else {
NULL) == -1) {
mdb_warn("failed to walk conn_fanout");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static void
conn_status_help(void)
{
mdb_printf("Prints conn_t structures from the following hash tables: "
"\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout"
"\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout_v4"
"\n\tips_ipcl_proto_fanout_v6\n");
}
static int
{
mdb_warn("can't walk 'srcid_list'");
return (WALK_ERR);
}
return (WALK_NEXT);
}
/* ARGSUSED */
static int
void *private)
{
return (WALK_ERR);
}
mdb_printf("%-?p %3d %4d %6d %N\n",
return (WALK_NEXT);
}
static void
srcid_header(void)
{
mdb_printf("%-?s %3s %4s %6s %s\n",
"ADDR", "ID", "ZONE", "REFCNT", "IPADDR");
}
/*ARGSUSED*/
static int
{
srcid_header();
if (flags & DCMD_ADDRSPEC) {
} else {
NULL) == -1) {
mdb_warn("failed to walk srcid_map");
return (DCMD_ERR);
}
}
return (DCMD_OK);
}
static int
{
}
static int
{
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_NEXT);
else
return (WALK_DONE);
}
static int
{
int status;
return (WALK_ERR);
}
return (status);
return (WALK_DONE);
else
return (WALK_NEXT);
}
static int
{
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_NEXT);
else
return (WALK_DONE);
}
static int
{
int status;
return (WALK_ERR);
}
return (status);
return (WALK_DONE);
else
return (WALK_NEXT);
}
/*
* Helper structure for ilb_nat_src walker. It stores the current index of the
* nat src table.
*/
typedef struct {
int idx;
} ilb_walk_t;
/* Copy from list.c */
static int
{
int i;
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_DONE);
}
char *khead;
/* Read in the nsh_head in the i-th element of the array. */
sizeof (ilb_nat_src_hash_t);
return (WALK_ERR);
}
/*
* Note that list_next points to a kernel address and we need
* to compare list_next with the kernel address of the list
* head. So we need to calculate the address manually.
*/
break;
}
}
return (WALK_DONE);
return (WALK_NEXT);
}
static int
{
int status;
char *khead;
int i;
mdb_warn("failed to read ilb_nat_src_entry_t at %p",
return (WALK_ERR);
}
return (status);
/* Read in the nsh_head in the i-th element of the array. */
return (WALK_ERR);
}
/*
* Check if there is still entry in the current list.
*
* Note that list_next points to a kernel address and we need to
* compare list_next with the kernel address of the list head.
* So we need to calculate the address manually.
*/
list_head)) {
return (WALK_NEXT);
}
/* Start with the next bucket in the array. */
next_entry = NULL;
for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) {
sizeof (ilb_nat_src_hash_t);
return (WALK_ERR);
}
break;
}
}
if (next_entry == NULL)
return (WALK_DONE);
return (WALK_NEXT);
}
static void
{
return;
}
static int
{
int i;
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_DONE);
}
char *khead;
/* Read in the nsh_head in the i-th element of the array. */
sizeof (ilb_conn_hash_t);
mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n",
khead);
return (WALK_ERR);
}
break;
}
return (WALK_DONE);
return (WALK_NEXT);
}
static int
{
int status;
char *khead;
int i;
return (WALK_ERR);
}
return (status);
/* Check if there is still entry in the current list. */
return (WALK_NEXT);
}
/* Start with the next bucket in the array. */
for (i++; i < ilbs->ilbs_conn_hash_size; i++) {
sizeof (ilb_conn_hash_t);
mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n",
khead);
return (WALK_ERR);
}
break;
}
return (WALK_DONE);
return (WALK_NEXT);
}
static int
{
int i;
return (WALK_ERR);
return (WALK_ERR);
}
return (WALK_DONE);
}
char *khead;
/* Read in the nsh_head in the i-th element of the array. */
sizeof (ilb_sticky_hash_t);
mdb_warn("failed to read ilbs_sticky_hash at %p\n",
khead);
return (WALK_ERR);
}
/*
* Note that list_next points to a kernel address and we need
* to compare list_next with the kernel address of the list
* head. So we need to calculate the address manually.
*/
break;
}
}
return (WALK_DONE);
sticky_walk->idx = i;
return (WALK_NEXT);
}
static int
{
int status;
char *khead;
int i;
return (WALK_ERR);
}
return (status);
i = sticky_walk->idx;
/* Read in the nsh_head in the i-th element of the array. */
return (WALK_ERR);
}
/*
* Check if there is still entry in the current list.
*
* Note that list_next points to a kernel address and we need to
* compare list_next with the kernel address of the list head.
* So we need to calculate the address manually.
*/
list_head)) {
return (WALK_NEXT);
}
/* Start with the next bucket in the array. */
for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) {
sizeof (ilb_sticky_hash_t);
mdb_warn("failed to read ilbs_sticky_hash at %p\n",
khead);
return (WALK_ERR);
}
break;
}
}
return (WALK_DONE);
sticky_walk->idx = i;
return (WALK_NEXT);
}