1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stropts.h> 28 #include <sys/stream.h> 29 #include <sys/socket.h> 30 #include <sys/avl_impl.h> 31 #include <net/if_types.h> 32 #include <net/if.h> 33 #include <net/route.h> 34 #include <netinet/in.h> 35 #include <netinet/ip6.h> 36 #include <netinet/udp.h> 37 #include <netinet/sctp.h> 38 #include <inet/mib2.h> 39 #include <inet/common.h> 40 #include <inet/ip.h> 41 #include <inet/ip_ire.h> 42 #include <inet/ip6.h> 43 #include <inet/ipclassifier.h> 44 #include <inet/mi.h> 45 #include <sys/squeue_impl.h> 46 #include <sys/modhash_impl.h> 47 #include <inet/ip_ndp.h> 48 #include <inet/ip_if.h> 49 #include <ilb.h> 50 #include <ilb/ilb_impl.h> 51 #include <ilb/ilb_stack.h> 52 #include <ilb/ilb_nat.h> 53 #include <ilb/ilb_conn.h> 54 #include <sys/dlpi.h> 55 56 #include <mdb/mdb_modapi.h> 57 #include <mdb/mdb_ks.h> 58 59 #define ADDR_WIDTH 11 60 #define L2MAXADDRSTRLEN 255 61 #define MAX_SAP_LEN 255 62 #define DEFCOLS 80 63 64 typedef struct { 65 const char *bit_name; /* name of bit */ 66 const char *bit_descr; /* description of bit's purpose */ 67 } bitname_t; 68 69 static const bitname_t squeue_states[] = { 70 { "SQS_PROC", "being processed" }, 71 { "SQS_WORKER", "... by a worker thread" }, 72 { "SQS_ENTER", "... by an squeue_enter() thread" }, 73 { "SQS_FAST", "... in fast-path mode" }, 74 { "SQS_USER", "A non interrupt user" }, 75 { "SQS_BOUND", "worker thread bound to CPU" }, 76 { "SQS_PROFILE", "profiling enabled" }, 77 { "SQS_REENTER", "re-entered thred" }, 78 { NULL } 79 }; 80 81 typedef struct illif_walk_data { 82 ill_g_head_t ill_g_heads[MAX_G_HEADS]; 83 int ill_list; 84 ill_if_t ill_if; 85 } illif_walk_data_t; 86 87 typedef struct nce_walk_data_s { 88 struct ndp_g_s nce_ip_ndp; 89 int nce_hash_tbl_index; 90 nce_t nce; 91 } nce_walk_data_t; 92 93 typedef struct nce_cbdata_s { 94 uintptr_t nce_addr; 95 int nce_ipversion; 96 } nce_cbdata_t; 97 98 typedef struct ire_cbdata_s { 99 int ire_ipversion; 100 boolean_t verbose; 101 } ire_cbdata_t; 102 103 typedef struct th_walk_data { 104 uint_t thw_non_zero_only; 105 boolean_t thw_match; 106 uintptr_t thw_matchkey; 107 uintptr_t thw_ipst; 108 clock_t thw_lbolt; 109 } th_walk_data_t; 110 111 typedef struct ipcl_hash_walk_data_s { 112 conn_t *conn; 113 int connf_tbl_index; 114 uintptr_t hash_tbl; 115 int hash_tbl_size; 116 } ipcl_hash_walk_data_t; 117 118 typedef struct ill_walk_data_s { 119 ill_t ill; 120 } ill_walk_data_t; 121 122 typedef struct ill_cbdata_s { 123 uintptr_t ill_addr; 124 int ill_ipversion; 125 boolean_t verbose; 126 } ill_cbdata_t; 127 128 typedef struct ipif_walk_data_s { 129 ipif_t ipif; 130 } ipif_walk_data_t; 131 132 typedef struct ipif_cbdata_s { 133 ill_t ill; 134 int ipif_ipversion; 135 boolean_t verbose; 136 } ipif_cbdata_t; 137 138 typedef struct hash_walk_arg_s { 139 off_t tbl_off; 140 off_t size_off; 141 } hash_walk_arg_t; 142 143 static hash_walk_arg_t udp_hash_arg = { 144 OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout), 145 OFFSETOF(ip_stack_t, ips_ipcl_udp_fanout_size) 146 }; 147 148 static hash_walk_arg_t conn_hash_arg = { 149 OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout), 150 OFFSETOF(ip_stack_t, ips_ipcl_conn_fanout_size) 151 }; 152 153 static hash_walk_arg_t bind_hash_arg = { 154 OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout), 155 OFFSETOF(ip_stack_t, ips_ipcl_bind_fanout_size) 156 }; 157 158 static hash_walk_arg_t proto_hash_arg = { 159 OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout), 160 0 161 }; 162 163 static hash_walk_arg_t proto_v6_hash_arg = { 164 OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6), 165 0 166 }; 167 168 typedef struct ip_list_walk_data_s { 169 off_t nextoff; 170 } ip_list_walk_data_t; 171 172 typedef struct ip_list_walk_arg_s { 173 off_t off; 174 size_t size; 175 off_t nextp_off; 176 } ip_list_walk_arg_t; 177 178 static ip_list_walk_arg_t ipif_walk_arg = { 179 OFFSETOF(ill_t, ill_ipif), 180 sizeof (ipif_t), 181 OFFSETOF(ipif_t, ipif_next) 182 }; 183 184 static ip_list_walk_arg_t srcid_walk_arg = { 185 OFFSETOF(ip_stack_t, ips_srcid_head), 186 sizeof (srcid_map_t), 187 OFFSETOF(srcid_map_t, sm_next) 188 }; 189 190 static int iphdr(uintptr_t, uint_t, int, const mdb_arg_t *); 191 static int ip6hdr(uintptr_t, uint_t, int, const mdb_arg_t *); 192 193 static int ill(uintptr_t, uint_t, int, const mdb_arg_t *); 194 static void ill_help(void); 195 static int ill_walk_init(mdb_walk_state_t *); 196 static int ill_walk_step(mdb_walk_state_t *); 197 static int ill_format(uintptr_t, const void *, void *); 198 static void ill_header(boolean_t); 199 200 static int ipif(uintptr_t, uint_t, int, const mdb_arg_t *); 201 static void ipif_help(void); 202 static int ipif_walk_init(mdb_walk_state_t *); 203 static int ipif_walk_step(mdb_walk_state_t *); 204 static int ipif_format(uintptr_t, const void *, void *); 205 static void ipif_header(boolean_t); 206 207 static int ip_list_walk_init(mdb_walk_state_t *); 208 static int ip_list_walk_step(mdb_walk_state_t *); 209 static void ip_list_walk_fini(mdb_walk_state_t *); 210 static int srcid_walk_step(mdb_walk_state_t *); 211 212 static int ire_format(uintptr_t addr, const void *, void *); 213 static int nce_format(uintptr_t addr, const nce_t *nce, int ipversion); 214 static int nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv); 215 static int nce_walk_step(mdb_walk_state_t *wsp); 216 static int nce_stack_walk_init(mdb_walk_state_t *wsp); 217 static int nce_stack_walk_step(mdb_walk_state_t *wsp); 218 static void nce_stack_walk_fini(mdb_walk_state_t *wsp); 219 static int nce_cb(uintptr_t addr, const nce_walk_data_t *iw, nce_cbdata_t *id); 220 221 static int ipcl_hash_walk_init(mdb_walk_state_t *); 222 static int ipcl_hash_walk_step(mdb_walk_state_t *); 223 static void ipcl_hash_walk_fini(mdb_walk_state_t *); 224 225 static int conn_status_walk_step(mdb_walk_state_t *); 226 static int conn_status(uintptr_t, uint_t, int, const mdb_arg_t *); 227 static void conn_status_help(void); 228 229 static int srcid_status(uintptr_t, uint_t, int, const mdb_arg_t *); 230 231 static int ilb_stacks_walk_step(mdb_walk_state_t *); 232 static int ilb_rules_walk_init(mdb_walk_state_t *); 233 static int ilb_rules_walk_step(mdb_walk_state_t *); 234 static int ilb_servers_walk_init(mdb_walk_state_t *); 235 static int ilb_servers_walk_step(mdb_walk_state_t *); 236 static int ilb_nat_src_walk_init(mdb_walk_state_t *); 237 static int ilb_nat_src_walk_step(mdb_walk_state_t *); 238 static int ilb_conn_walk_init(mdb_walk_state_t *); 239 static int ilb_conn_walk_step(mdb_walk_state_t *); 240 static int ilb_sticky_walk_init(mdb_walk_state_t *); 241 static int ilb_sticky_walk_step(mdb_walk_state_t *); 242 static void ilb_common_walk_fini(mdb_walk_state_t *); 243 244 /* 245 * Given the kernel address of an ip_stack_t, return the stackid 246 */ 247 static int 248 ips_to_stackid(uintptr_t kaddr) 249 { 250 ip_stack_t ipss; 251 netstack_t nss; 252 253 if (mdb_vread(&ipss, sizeof (ipss), kaddr) == -1) { 254 mdb_warn("failed to read ip_stack_t %p", kaddr); 255 return (0); 256 } 257 kaddr = (uintptr_t)ipss.ips_netstack; 258 if (mdb_vread(&nss, sizeof (nss), kaddr) == -1) { 259 mdb_warn("failed to read netstack_t %p", kaddr); 260 return (0); 261 } 262 return (nss.netstack_stackid); 263 } 264 265 int 266 ip_stacks_walk_init(mdb_walk_state_t *wsp) 267 { 268 if (mdb_layered_walk("netstack", wsp) == -1) { 269 mdb_warn("can't walk 'netstack'"); 270 return (WALK_ERR); 271 } 272 return (WALK_NEXT); 273 } 274 275 int 276 ip_stacks_walk_step(mdb_walk_state_t *wsp) 277 { 278 uintptr_t kaddr; 279 netstack_t nss; 280 281 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 282 mdb_warn("can't read netstack at %p", wsp->walk_addr); 283 return (WALK_ERR); 284 } 285 kaddr = (uintptr_t)nss.netstack_modules[NS_IP]; 286 287 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 288 } 289 290 int 291 th_hash_walk_init(mdb_walk_state_t *wsp) 292 { 293 GElf_Sym sym; 294 list_node_t *next; 295 296 if (wsp->walk_addr == NULL) { 297 if (mdb_lookup_by_obj("ip", "ip_thread_list", &sym) == 0) { 298 wsp->walk_addr = sym.st_value; 299 } else { 300 mdb_warn("unable to locate ip_thread_list\n"); 301 return (WALK_ERR); 302 } 303 } 304 305 if (mdb_vread(&next, sizeof (next), 306 wsp->walk_addr + offsetof(list_t, list_head) + 307 offsetof(list_node_t, list_next)) == -1 || 308 next == NULL) { 309 mdb_warn("non-DEBUG image; cannot walk th_hash list\n"); 310 return (WALK_ERR); 311 } 312 313 if (mdb_layered_walk("list", wsp) == -1) { 314 mdb_warn("can't walk 'list'"); 315 return (WALK_ERR); 316 } else { 317 return (WALK_NEXT); 318 } 319 } 320 321 int 322 th_hash_walk_step(mdb_walk_state_t *wsp) 323 { 324 return (wsp->walk_callback(wsp->walk_addr, wsp->walk_layer, 325 wsp->walk_cbdata)); 326 } 327 328 /* 329 * Called with walk_addr being the address of ips_ill_g_heads 330 */ 331 int 332 illif_stack_walk_init(mdb_walk_state_t *wsp) 333 { 334 illif_walk_data_t *iw; 335 336 if (wsp->walk_addr == NULL) { 337 mdb_warn("illif_stack supports only local walks\n"); 338 return (WALK_ERR); 339 } 340 341 iw = mdb_alloc(sizeof (illif_walk_data_t), UM_SLEEP); 342 343 if (mdb_vread(iw->ill_g_heads, MAX_G_HEADS * sizeof (ill_g_head_t), 344 wsp->walk_addr) == -1) { 345 mdb_warn("failed to read 'ips_ill_g_heads' at %p", 346 wsp->walk_addr); 347 mdb_free(iw, sizeof (illif_walk_data_t)); 348 return (WALK_ERR); 349 } 350 351 iw->ill_list = 0; 352 wsp->walk_addr = (uintptr_t)iw->ill_g_heads[0].ill_g_list_head; 353 wsp->walk_data = iw; 354 355 return (WALK_NEXT); 356 } 357 358 int 359 illif_stack_walk_step(mdb_walk_state_t *wsp) 360 { 361 uintptr_t addr = wsp->walk_addr; 362 illif_walk_data_t *iw = wsp->walk_data; 363 int list = iw->ill_list; 364 365 if (mdb_vread(&iw->ill_if, sizeof (ill_if_t), addr) == -1) { 366 mdb_warn("failed to read ill_if_t at %p", addr); 367 return (WALK_ERR); 368 } 369 370 wsp->walk_addr = (uintptr_t)iw->ill_if.illif_next; 371 372 if (wsp->walk_addr == 373 (uintptr_t)iw->ill_g_heads[list].ill_g_list_head) { 374 375 if (++list >= MAX_G_HEADS) 376 return (WALK_DONE); 377 378 iw->ill_list = list; 379 wsp->walk_addr = 380 (uintptr_t)iw->ill_g_heads[list].ill_g_list_head; 381 return (WALK_NEXT); 382 } 383 384 return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 385 } 386 387 void 388 illif_stack_walk_fini(mdb_walk_state_t *wsp) 389 { 390 mdb_free(wsp->walk_data, sizeof (illif_walk_data_t)); 391 } 392 393 typedef struct illif_cbdata { 394 uint_t ill_flags; 395 uintptr_t ill_addr; 396 int ill_printlist; /* list to be printed (MAX_G_HEADS for all) */ 397 boolean_t ill_printed; 398 } illif_cbdata_t; 399 400 static int 401 illif_cb(uintptr_t addr, const illif_walk_data_t *iw, illif_cbdata_t *id) 402 { 403 const char *version; 404 405 if (id->ill_printlist < MAX_G_HEADS && 406 id->ill_printlist != iw->ill_list) 407 return (WALK_NEXT); 408 409 if (id->ill_flags & DCMD_ADDRSPEC && id->ill_addr != addr) 410 return (WALK_NEXT); 411 412 if (id->ill_flags & DCMD_PIPE_OUT) { 413 mdb_printf("%p\n", addr); 414 return (WALK_NEXT); 415 } 416 417 switch (iw->ill_list) { 418 case IP_V4_G_HEAD: version = "v4"; break; 419 case IP_V6_G_HEAD: version = "v6"; break; 420 default: version = "??"; break; 421 } 422 423 mdb_printf("%?p %2s %?p %10d %?p %s\n", 424 addr, version, addr + offsetof(ill_if_t, illif_avl_by_ppa), 425 iw->ill_if.illif_avl_by_ppa.avl_numnodes, 426 iw->ill_if.illif_ppa_arena, iw->ill_if.illif_name); 427 428 id->ill_printed = TRUE; 429 430 return (WALK_NEXT); 431 } 432 433 int 434 ip_stacks_common_walk_init(mdb_walk_state_t *wsp) 435 { 436 if (mdb_layered_walk("ip_stacks", wsp) == -1) { 437 mdb_warn("can't walk 'ip_stacks'"); 438 return (WALK_ERR); 439 } 440 441 return (WALK_NEXT); 442 } 443 444 int 445 illif_walk_step(mdb_walk_state_t *wsp) 446 { 447 uintptr_t kaddr; 448 449 kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ill_g_heads); 450 451 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 452 mdb_warn("can't read ips_ip_cache_table at %p", kaddr); 453 return (WALK_ERR); 454 } 455 456 if (mdb_pwalk("illif_stack", wsp->walk_callback, 457 wsp->walk_cbdata, kaddr) == -1) { 458 mdb_warn("couldn't walk 'illif_stack' for ips_ill_g_heads %p", 459 kaddr); 460 return (WALK_ERR); 461 } 462 return (WALK_NEXT); 463 } 464 465 int 466 illif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 467 { 468 illif_cbdata_t id; 469 ill_if_t ill_if; 470 const char *opt_P = NULL; 471 int printlist = MAX_G_HEADS; 472 473 if (mdb_getopts(argc, argv, 474 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 475 return (DCMD_USAGE); 476 477 if (opt_P != NULL) { 478 if (strcmp("v4", opt_P) == 0) { 479 printlist = IP_V4_G_HEAD; 480 } else if (strcmp("v6", opt_P) == 0) { 481 printlist = IP_V6_G_HEAD; 482 } else { 483 mdb_warn("invalid protocol '%s'\n", opt_P); 484 return (DCMD_USAGE); 485 } 486 } 487 488 if (DCMD_HDRSPEC(flags) && (flags & DCMD_PIPE_OUT) == 0) { 489 mdb_printf("%<u>%?s %2s %?s %10s %?s %-10s%</u>\n", 490 "ADDR", "IP", "AVLADDR", "NUMNODES", "ARENA", "NAME"); 491 } 492 493 id.ill_flags = flags; 494 id.ill_addr = addr; 495 id.ill_printlist = printlist; 496 id.ill_printed = FALSE; 497 498 if (mdb_walk("illif", (mdb_walk_cb_t)illif_cb, &id) == -1) { 499 mdb_warn("can't walk ill_if_t structures"); 500 return (DCMD_ERR); 501 } 502 503 if (!(flags & DCMD_ADDRSPEC) || opt_P != NULL || id.ill_printed) 504 return (DCMD_OK); 505 506 /* 507 * If an address is specified and the walk doesn't find it, 508 * print it anyway. 509 */ 510 if (mdb_vread(&ill_if, sizeof (ill_if_t), addr) == -1) { 511 mdb_warn("failed to read ill_if_t at %p", addr); 512 return (DCMD_ERR); 513 } 514 515 mdb_printf("%?p %2s %?p %10d %?p %s\n", 516 addr, "??", addr + offsetof(ill_if_t, illif_avl_by_ppa), 517 ill_if.illif_avl_by_ppa.avl_numnodes, 518 ill_if.illif_ppa_arena, ill_if.illif_name); 519 520 return (DCMD_OK); 521 } 522 523 static void 524 illif_help(void) 525 { 526 mdb_printf("Options:\n"); 527 mdb_printf("\t-P v4 | v6" 528 "\tfilter interface structures for the specified protocol\n"); 529 } 530 531 int 532 ire_walk_init(mdb_walk_state_t *wsp) 533 { 534 if (mdb_layered_walk("ire_cache", wsp) == -1) { 535 mdb_warn("can't walk 'ire_cache'"); 536 return (WALK_ERR); 537 } 538 539 return (WALK_NEXT); 540 } 541 542 int 543 ire_walk_step(mdb_walk_state_t *wsp) 544 { 545 ire_t ire; 546 547 if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) { 548 mdb_warn("can't read ire at %p", wsp->walk_addr); 549 return (WALK_ERR); 550 } 551 552 return (wsp->walk_callback(wsp->walk_addr, &ire, wsp->walk_cbdata)); 553 } 554 555 556 int 557 ire_ctable_walk_step(mdb_walk_state_t *wsp) 558 { 559 uintptr_t kaddr; 560 irb_t *irb; 561 uint32_t cache_table_size; 562 int i; 563 ire_cbdata_t ire_cb; 564 565 ire_cb.verbose = B_FALSE; 566 ire_cb.ire_ipversion = 0; 567 568 569 kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table_size); 570 571 if (mdb_vread(&cache_table_size, sizeof (uint32_t), kaddr) == -1) { 572 mdb_warn("can't read ips_ip_cache_table at %p", kaddr); 573 return (WALK_ERR); 574 } 575 576 kaddr = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ip_cache_table); 577 if (mdb_vread(&kaddr, sizeof (kaddr), kaddr) == -1) { 578 mdb_warn("can't read ips_ip_cache_table at %p", kaddr); 579 return (WALK_ERR); 580 } 581 582 irb = mdb_alloc(sizeof (irb_t) * cache_table_size, UM_SLEEP|UM_GC); 583 if (mdb_vread(irb, sizeof (irb_t) * cache_table_size, kaddr) == -1) { 584 mdb_warn("can't read irb at %p", kaddr); 585 return (WALK_ERR); 586 } 587 for (i = 0; i < cache_table_size; i++) { 588 kaddr = (uintptr_t)irb[i].irb_ire; 589 590 if (mdb_pwalk("ire_next", ire_format, &ire_cb, 591 kaddr) == -1) { 592 mdb_warn("can't walk 'ire_next' for ire %p", kaddr); 593 return (WALK_ERR); 594 } 595 } 596 return (WALK_NEXT); 597 } 598 599 /* ARGSUSED */ 600 int 601 ire_next_walk_init(mdb_walk_state_t *wsp) 602 { 603 return (WALK_NEXT); 604 } 605 606 int 607 ire_next_walk_step(mdb_walk_state_t *wsp) 608 { 609 ire_t ire; 610 int status; 611 612 613 if (wsp->walk_addr == NULL) 614 return (WALK_DONE); 615 616 if (mdb_vread(&ire, sizeof (ire), wsp->walk_addr) == -1) { 617 mdb_warn("can't read ire at %p", wsp->walk_addr); 618 return (WALK_ERR); 619 } 620 status = wsp->walk_callback(wsp->walk_addr, &ire, 621 wsp->walk_cbdata); 622 623 if (status != WALK_NEXT) 624 return (status); 625 626 wsp->walk_addr = (uintptr_t)ire.ire_next; 627 return (status); 628 } 629 630 static int 631 ire_format(uintptr_t addr, const void *ire_arg, void *ire_cb_arg) 632 { 633 const ire_t *irep = ire_arg; 634 ire_cbdata_t *ire_cb = ire_cb_arg; 635 boolean_t verbose = ire_cb->verbose; 636 637 static const mdb_bitmask_t tmasks[] = { 638 { "BROADCAST", IRE_BROADCAST, IRE_BROADCAST }, 639 { "DEFAULT", IRE_DEFAULT, IRE_DEFAULT }, 640 { "LOCAL", IRE_LOCAL, IRE_LOCAL }, 641 { "LOOPBACK", IRE_LOOPBACK, IRE_LOOPBACK }, 642 { "PREFIX", IRE_PREFIX, IRE_PREFIX }, 643 { "CACHE", IRE_CACHE, IRE_CACHE }, 644 { "IF_NORESOLVER", IRE_IF_NORESOLVER, IRE_IF_NORESOLVER }, 645 { "IF_RESOLVER", IRE_IF_RESOLVER, IRE_IF_RESOLVER }, 646 { "HOST", IRE_HOST, IRE_HOST }, 647 { "HOST_REDIRECT", IRE_HOST_REDIRECT, IRE_HOST_REDIRECT }, 648 { NULL, 0, 0 } 649 }; 650 651 static const mdb_bitmask_t mmasks[] = { 652 { "CONDEMNED", IRE_MARK_CONDEMNED, IRE_MARK_CONDEMNED }, 653 { "TESTHIDDEN", IRE_MARK_TESTHIDDEN, IRE_MARK_TESTHIDDEN }, 654 { "NOADD", IRE_MARK_NOADD, IRE_MARK_NOADD }, 655 { "TEMPORARY", IRE_MARK_TEMPORARY, IRE_MARK_TEMPORARY }, 656 { "USESRC", IRE_MARK_USESRC_CHECK, IRE_MARK_USESRC_CHECK }, 657 { "PRIVATE", IRE_MARK_PRIVATE_ADDR, IRE_MARK_PRIVATE_ADDR }, 658 { "UNCACHED", IRE_MARK_UNCACHED, IRE_MARK_UNCACHED }, 659 { NULL, 0, 0 } 660 }; 661 662 static const mdb_bitmask_t fmasks[] = { 663 { "UP", RTF_UP, RTF_UP }, 664 { "GATEWAY", RTF_GATEWAY, RTF_GATEWAY }, 665 { "HOST", RTF_HOST, RTF_HOST }, 666 { "REJECT", RTF_REJECT, RTF_REJECT }, 667 { "DYNAMIC", RTF_DYNAMIC, RTF_DYNAMIC }, 668 { "MODIFIED", RTF_MODIFIED, RTF_MODIFIED }, 669 { "DONE", RTF_DONE, RTF_DONE }, 670 { "MASK", RTF_MASK, RTF_MASK }, 671 { "CLONING", RTF_CLONING, RTF_CLONING }, 672 { "XRESOLVE", RTF_XRESOLVE, RTF_XRESOLVE }, 673 { "LLINFO", RTF_LLINFO, RTF_LLINFO }, 674 { "STATIC", RTF_STATIC, RTF_STATIC }, 675 { "BLACKHOLE", RTF_BLACKHOLE, RTF_BLACKHOLE }, 676 { "PRIVATE", RTF_PRIVATE, RTF_PRIVATE }, 677 { "PROTO2", RTF_PROTO2, RTF_PROTO2 }, 678 { "PROTO1", RTF_PROTO1, RTF_PROTO1 }, 679 { "MULTIRT", RTF_MULTIRT, RTF_MULTIRT }, 680 { "SETSRC", RTF_SETSRC, RTF_SETSRC }, 681 { NULL, 0, 0 } 682 }; 683 684 if (ire_cb->ire_ipversion != 0 && 685 irep->ire_ipversion != ire_cb->ire_ipversion) 686 return (WALK_NEXT); 687 688 if (irep->ire_ipversion == IPV6_VERSION && verbose) { 689 690 mdb_printf("%<b>%?p%</b> %40N <%hb>\n" 691 "%?s %40N <%hb>\n" 692 "%?s %40d %4d <%hb>\n", 693 addr, &irep->ire_src_addr_v6, irep->ire_type, tmasks, 694 "", &irep->ire_addr_v6, (ushort_t)irep->ire_marks, mmasks, 695 "", ips_to_stackid((uintptr_t)irep->ire_ipst), 696 irep->ire_zoneid, 697 irep->ire_flags, fmasks); 698 699 } else if (irep->ire_ipversion == IPV6_VERSION) { 700 701 mdb_printf("%?p %30N %30N %5d %4d\n", 702 addr, &irep->ire_src_addr_v6, 703 &irep->ire_addr_v6, 704 ips_to_stackid((uintptr_t)irep->ire_ipst), 705 irep->ire_zoneid); 706 707 } else if (verbose) { 708 709 mdb_printf("%<b>%?p%</b> %40I <%hb>\n" 710 "%?s %40I <%hb>\n" 711 "%?s %40d %4d <%hb>\n", 712 addr, irep->ire_src_addr, irep->ire_type, tmasks, 713 "", irep->ire_addr, (ushort_t)irep->ire_marks, mmasks, 714 "", ips_to_stackid((uintptr_t)irep->ire_ipst), 715 irep->ire_zoneid, irep->ire_flags, fmasks); 716 717 } else { 718 719 mdb_printf("%?p %30I %30I %5d %4d\n", addr, irep->ire_src_addr, 720 irep->ire_addr, ips_to_stackid((uintptr_t)irep->ire_ipst), 721 irep->ire_zoneid); 722 } 723 724 return (WALK_NEXT); 725 } 726 727 /* 728 * There are faster ways to do this. Given the interactive nature of this 729 * use I don't think its worth much effort. 730 */ 731 static unsigned short 732 ipcksum(void *p, int len) 733 { 734 int32_t sum = 0; 735 736 while (len > 1) { 737 /* alignment */ 738 sum += *(uint16_t *)p; 739 p = (char *)p + sizeof (uint16_t); 740 if (sum & 0x80000000) 741 sum = (sum & 0xFFFF) + (sum >> 16); 742 len -= 2; 743 } 744 745 if (len) 746 sum += (uint16_t)*(unsigned char *)p; 747 748 while (sum >> 16) 749 sum = (sum & 0xFFFF) + (sum >> 16); 750 751 return (~sum); 752 } 753 754 static const mdb_bitmask_t tcp_flags[] = { 755 { "SYN", TH_SYN, TH_SYN }, 756 { "ACK", TH_ACK, TH_ACK }, 757 { "FIN", TH_FIN, TH_FIN }, 758 { "RST", TH_RST, TH_RST }, 759 { "PSH", TH_PUSH, TH_PUSH }, 760 { "ECE", TH_ECE, TH_ECE }, 761 { "CWR", TH_CWR, TH_CWR }, 762 { NULL, 0, 0 } 763 }; 764 765 static void 766 tcphdr_print(struct tcphdr *tcph) 767 { 768 in_port_t sport, dport; 769 tcp_seq seq, ack; 770 uint16_t win, urp; 771 772 mdb_printf("%<b>TCP header%</b>\n"); 773 774 mdb_nhconvert(&sport, &tcph->th_sport, sizeof (sport)); 775 mdb_nhconvert(&dport, &tcph->th_dport, sizeof (dport)); 776 mdb_nhconvert(&seq, &tcph->th_seq, sizeof (seq)); 777 mdb_nhconvert(&ack, &tcph->th_ack, sizeof (ack)); 778 mdb_nhconvert(&win, &tcph->th_win, sizeof (win)); 779 mdb_nhconvert(&urp, &tcph->th_urp, sizeof (urp)); 780 781 mdb_printf("%<u>%6s %6s %10s %10s %4s %5s %5s %5s %-15s%</u>\n", 782 "SPORT", "DPORT", "SEQ", "ACK", "HLEN", "WIN", "CSUM", "URP", 783 "FLAGS"); 784 mdb_printf("%6hu %6hu %10u %10u %4d %5hu %5hu %5hu <%b>\n", 785 sport, dport, seq, ack, tcph->th_off << 2, win, 786 tcph->th_sum, urp, tcph->th_flags, tcp_flags); 787 mdb_printf("0x%04x 0x%04x 0x%08x 0x%08x\n\n", 788 sport, dport, seq, ack); 789 } 790 791 /* ARGSUSED */ 792 static int 793 tcphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 794 { 795 struct tcphdr tcph; 796 797 if (!(flags & DCMD_ADDRSPEC)) 798 return (DCMD_USAGE); 799 800 if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 801 mdb_warn("failed to read TCP header at %p", addr); 802 return (DCMD_ERR); 803 } 804 tcphdr_print(&tcph); 805 return (DCMD_OK); 806 } 807 808 static void 809 udphdr_print(struct udphdr *udph) 810 { 811 in_port_t sport, dport; 812 uint16_t hlen; 813 814 mdb_printf("%<b>UDP header%</b>\n"); 815 816 mdb_nhconvert(&sport, &udph->uh_sport, sizeof (sport)); 817 mdb_nhconvert(&dport, &udph->uh_dport, sizeof (dport)); 818 mdb_nhconvert(&hlen, &udph->uh_ulen, sizeof (hlen)); 819 820 mdb_printf("%<u>%14s %14s %5s %6s%</u>\n", 821 "SPORT", "DPORT", "LEN", "CSUM"); 822 mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %5hu 0x%04hx\n\n", sport, sport, 823 dport, dport, hlen, udph->uh_sum); 824 } 825 826 /* ARGSUSED */ 827 static int 828 udphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 829 { 830 struct udphdr udph; 831 832 if (!(flags & DCMD_ADDRSPEC)) 833 return (DCMD_USAGE); 834 835 if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 836 mdb_warn("failed to read UDP header at %p", addr); 837 return (DCMD_ERR); 838 } 839 udphdr_print(&udph); 840 return (DCMD_OK); 841 } 842 843 static void 844 sctphdr_print(sctp_hdr_t *sctph) 845 { 846 in_port_t sport, dport; 847 848 mdb_printf("%<b>SCTP header%</b>\n"); 849 mdb_nhconvert(&sport, &sctph->sh_sport, sizeof (sport)); 850 mdb_nhconvert(&dport, &sctph->sh_dport, sizeof (dport)); 851 852 mdb_printf("%<u>%14s %14s %10s %10s%</u>\n", 853 "SPORT", "DPORT", "VTAG", "CHKSUM"); 854 mdb_printf("%5hu (0x%04x) %5hu (0x%04x) %10u 0x%08x\n\n", sport, sport, 855 dport, dport, sctph->sh_verf, sctph->sh_chksum); 856 } 857 858 /* ARGSUSED */ 859 static int 860 sctphdr(uintptr_t addr, uint_t flags, int ac, const mdb_arg_t *av) 861 { 862 sctp_hdr_t sctph; 863 864 if (!(flags & DCMD_ADDRSPEC)) 865 return (DCMD_USAGE); 866 867 if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 868 mdb_warn("failed to read SCTP header at %p", addr); 869 return (DCMD_ERR); 870 } 871 872 sctphdr_print(&sctph); 873 return (DCMD_OK); 874 } 875 876 static int 877 transport_hdr(int proto, uintptr_t addr) 878 { 879 mdb_printf("\n"); 880 switch (proto) { 881 case IPPROTO_TCP: { 882 struct tcphdr tcph; 883 884 if (mdb_vread(&tcph, sizeof (tcph), addr) == -1) { 885 mdb_warn("failed to read TCP header at %p", addr); 886 return (DCMD_ERR); 887 } 888 tcphdr_print(&tcph); 889 break; 890 } 891 case IPPROTO_UDP: { 892 struct udphdr udph; 893 894 if (mdb_vread(&udph, sizeof (udph), addr) == -1) { 895 mdb_warn("failed to read UDP header at %p", addr); 896 return (DCMD_ERR); 897 } 898 udphdr_print(&udph); 899 break; 900 } 901 case IPPROTO_SCTP: { 902 sctp_hdr_t sctph; 903 904 if (mdb_vread(&sctph, sizeof (sctph), addr) == -1) { 905 mdb_warn("failed to read SCTP header at %p", addr); 906 return (DCMD_ERR); 907 } 908 sctphdr_print(&sctph); 909 break; 910 } 911 default: 912 break; 913 } 914 915 return (DCMD_OK); 916 } 917 918 static const mdb_bitmask_t ip_flags[] = { 919 { "DF", IPH_DF, IPH_DF }, 920 { "MF", IPH_MF, IPH_MF }, 921 { NULL, 0, 0 } 922 }; 923 924 /* ARGSUSED */ 925 static int 926 iphdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 927 { 928 uint_t verbose = FALSE, force = FALSE; 929 ipha_t iph[1]; 930 uint16_t ver, totlen, hdrlen, ipid, off, csum; 931 uintptr_t nxt_proto; 932 char exp_csum[8]; 933 934 if (mdb_getopts(argc, argv, 935 'v', MDB_OPT_SETBITS, TRUE, &verbose, 936 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 937 return (DCMD_USAGE); 938 939 if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 940 mdb_warn("failed to read IPv4 header at %p", addr); 941 return (DCMD_ERR); 942 } 943 944 ver = (iph->ipha_version_and_hdr_length & 0xf0) >> 4; 945 if (ver != IPV4_VERSION) { 946 if (ver == IPV6_VERSION) { 947 return (ip6hdr(addr, flags, argc, argv)); 948 } else if (!force) { 949 mdb_warn("unknown IP version: %d\n", ver); 950 return (DCMD_ERR); 951 } 952 } 953 954 mdb_printf("%<b>IPv4 header%</b>\n"); 955 mdb_printf("%-34s %-34s\n" 956 "%<u>%-4s %-4s %-5s %-5s %-6s %-5s %-5s %-6s %-8s %-6s%</u>\n", 957 "SRC", "DST", 958 "HLEN", "TOS", "LEN", "ID", "OFFSET", "TTL", "PROTO", "CHKSUM", 959 "EXP-CSUM", "FLGS"); 960 961 hdrlen = (iph->ipha_version_and_hdr_length & 0x0f) << 2; 962 mdb_nhconvert(&totlen, &iph->ipha_length, sizeof (totlen)); 963 mdb_nhconvert(&ipid, &iph->ipha_ident, sizeof (ipid)); 964 mdb_nhconvert(&off, &iph->ipha_fragment_offset_and_flags, sizeof (off)); 965 if (hdrlen == IP_SIMPLE_HDR_LENGTH) { 966 if ((csum = ipcksum(iph, sizeof (*iph))) != 0) 967 csum = ~(~csum + ~iph->ipha_hdr_checksum); 968 else 969 csum = iph->ipha_hdr_checksum; 970 mdb_snprintf(exp_csum, 8, "%u", csum); 971 } else { 972 mdb_snprintf(exp_csum, 8, "<n/a>"); 973 } 974 975 mdb_printf("%-34I %-34I%\n" 976 "%-4d %-4d %-5hu %-5hu %-6hu %-5hu %-5hu %-6u %-8s <%5hb>\n", 977 iph->ipha_src, iph->ipha_dst, 978 hdrlen, iph->ipha_type_of_service, totlen, ipid, 979 (off << 3) & 0xffff, iph->ipha_ttl, iph->ipha_protocol, 980 iph->ipha_hdr_checksum, exp_csum, off, ip_flags); 981 982 if (verbose) { 983 nxt_proto = addr + hdrlen; 984 return (transport_hdr(iph->ipha_protocol, nxt_proto)); 985 } else { 986 return (DCMD_OK); 987 } 988 } 989 990 /* ARGSUSED */ 991 static int 992 ip6hdr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 993 { 994 uint_t verbose = FALSE, force = FALSE; 995 ip6_t iph[1]; 996 int ver, class, flow; 997 uint16_t plen; 998 uintptr_t nxt_proto; 999 1000 if (mdb_getopts(argc, argv, 1001 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1002 'f', MDB_OPT_SETBITS, TRUE, &force, NULL) != argc) 1003 return (DCMD_USAGE); 1004 1005 if (mdb_vread(iph, sizeof (*iph), addr) == -1) { 1006 mdb_warn("failed to read IPv6 header at %p", addr); 1007 return (DCMD_ERR); 1008 } 1009 1010 ver = (iph->ip6_vfc & 0xf0) >> 4; 1011 if (ver != IPV6_VERSION) { 1012 if (ver == IPV4_VERSION) { 1013 return (iphdr(addr, flags, argc, argv)); 1014 } else if (!force) { 1015 mdb_warn("unknown IP version: %d\n", ver); 1016 return (DCMD_ERR); 1017 } 1018 } 1019 1020 mdb_printf("%<b>IPv6 header%</b>\n"); 1021 mdb_printf("%<u>%-26s %-26s %4s %7s %5s %3s %3s%</u>\n", 1022 "SRC", "DST", "TCLS", "FLOW-ID", "PLEN", "NXT", "HOP"); 1023 1024 class = (iph->ip6_vcf & IPV6_FLOWINFO_TCLASS) >> 20; 1025 mdb_nhconvert(&class, &class, sizeof (class)); 1026 flow = iph->ip6_vcf & IPV6_FLOWINFO_FLOWLABEL; 1027 mdb_nhconvert(&flow, &flow, sizeof (flow)); 1028 mdb_nhconvert(&plen, &iph->ip6_plen, sizeof (plen)); 1029 1030 mdb_printf("%-26N %-26N %4d %7d %5hu %3d %3d\n", 1031 &iph->ip6_src, &iph->ip6_dst, 1032 class, flow, plen, iph->ip6_nxt, iph->ip6_hlim); 1033 1034 if (verbose) { 1035 nxt_proto = addr + sizeof (ip6_t); 1036 return (transport_hdr(iph->ip6_nxt, nxt_proto)); 1037 } else { 1038 return (DCMD_OK); 1039 } 1040 } 1041 1042 int 1043 ire(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1044 { 1045 uint_t verbose = FALSE; 1046 ire_t ire; 1047 ire_cbdata_t ire_cb; 1048 int ipversion = 0; 1049 const char *opt_P = NULL; 1050 1051 if (mdb_getopts(argc, argv, 1052 'v', MDB_OPT_SETBITS, TRUE, &verbose, 1053 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 1054 return (DCMD_USAGE); 1055 1056 if (opt_P != NULL) { 1057 if (strcmp("v4", opt_P) == 0) { 1058 ipversion = IPV4_VERSION; 1059 } else if (strcmp("v6", opt_P) == 0) { 1060 ipversion = IPV6_VERSION; 1061 } else { 1062 mdb_warn("invalid protocol '%s'\n", opt_P); 1063 return (DCMD_USAGE); 1064 } 1065 } 1066 1067 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 1068 1069 if (verbose) { 1070 mdb_printf("%?s %40s %-20s%\n" 1071 "%?s %40s %-20s%\n" 1072 "%<u>%?s %40s %4s %-20s%</u>\n", 1073 "ADDR", "SRC", "TYPE", 1074 "", "DST", "MARKS", 1075 "", "STACK", "ZONE", "FLAGS"); 1076 } else { 1077 mdb_printf("%<u>%?s %30s %30s %5s %4s%</u>\n", 1078 "ADDR", "SRC", "DST", "STACK", "ZONE"); 1079 } 1080 } 1081 1082 ire_cb.verbose = (verbose == TRUE); 1083 ire_cb.ire_ipversion = ipversion; 1084 1085 if (flags & DCMD_ADDRSPEC) { 1086 (void) mdb_vread(&ire, sizeof (ire_t), addr); 1087 (void) ire_format(addr, &ire, &ire_cb); 1088 } else if (mdb_walk("ire", (mdb_walk_cb_t)ire_format, &ire_cb) == -1) { 1089 mdb_warn("failed to walk ire table"); 1090 return (DCMD_ERR); 1091 } 1092 1093 return (DCMD_OK); 1094 } 1095 1096 static size_t 1097 mi_osize(const queue_t *q) 1098 { 1099 /* 1100 * The code in common/inet/mi.c allocates an extra word to store the 1101 * size of the allocation. An mi_o_s is thus a size_t plus an mi_o_s. 1102 */ 1103 struct mi_block { 1104 size_t mi_nbytes; 1105 struct mi_o_s mi_o; 1106 } m; 1107 1108 if (mdb_vread(&m, sizeof (m), (uintptr_t)q->q_ptr - 1109 sizeof (m)) == sizeof (m)) 1110 return (m.mi_nbytes - sizeof (m)); 1111 1112 return (0); 1113 } 1114 1115 static void 1116 ip_ill_qinfo(const queue_t *q, char *buf, size_t nbytes) 1117 { 1118 char name[32]; 1119 ill_t ill; 1120 1121 if (mdb_vread(&ill, sizeof (ill), 1122 (uintptr_t)q->q_ptr) == sizeof (ill) && 1123 mdb_readstr(name, sizeof (name), (uintptr_t)ill.ill_name) > 0) 1124 (void) mdb_snprintf(buf, nbytes, "if: %s", name); 1125 } 1126 1127 void 1128 ip_qinfo(const queue_t *q, char *buf, size_t nbytes) 1129 { 1130 size_t size = mi_osize(q); 1131 1132 if (size == sizeof (ill_t)) 1133 ip_ill_qinfo(q, buf, nbytes); 1134 } 1135 1136 uintptr_t 1137 ip_rnext(const queue_t *q) 1138 { 1139 size_t size = mi_osize(q); 1140 ill_t ill; 1141 1142 if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 1143 (uintptr_t)q->q_ptr) == sizeof (ill)) 1144 return ((uintptr_t)ill.ill_rq); 1145 1146 return (NULL); 1147 } 1148 1149 uintptr_t 1150 ip_wnext(const queue_t *q) 1151 { 1152 size_t size = mi_osize(q); 1153 ill_t ill; 1154 1155 if (size == sizeof (ill_t) && mdb_vread(&ill, sizeof (ill), 1156 (uintptr_t)q->q_ptr) == sizeof (ill)) 1157 return ((uintptr_t)ill.ill_wq); 1158 1159 return (NULL); 1160 } 1161 1162 /* 1163 * Print the core fields in an squeue_t. With the "-v" argument, 1164 * provide more verbose output. 1165 */ 1166 static int 1167 squeue(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1168 { 1169 unsigned int i; 1170 unsigned int verbose = FALSE; 1171 const int SQUEUE_STATEDELT = (int)(sizeof (uintptr_t) + 9); 1172 boolean_t arm; 1173 squeue_t squeue; 1174 1175 if (!(flags & DCMD_ADDRSPEC)) { 1176 if (mdb_walk_dcmd("genunix`squeue_cache", "ip`squeue", 1177 argc, argv) == -1) { 1178 mdb_warn("failed to walk squeue cache"); 1179 return (DCMD_ERR); 1180 } 1181 return (DCMD_OK); 1182 } 1183 1184 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 1185 != argc) 1186 return (DCMD_USAGE); 1187 1188 if (!DCMD_HDRSPEC(flags) && verbose) 1189 mdb_printf("\n\n"); 1190 1191 if (DCMD_HDRSPEC(flags) || verbose) { 1192 mdb_printf("%?s %-5s %-3s %?s %?s %?s\n", 1193 "ADDR", "STATE", "CPU", 1194 "FIRST", "LAST", "WORKER"); 1195 } 1196 1197 if (mdb_vread(&squeue, sizeof (squeue_t), addr) == -1) { 1198 mdb_warn("cannot read squeue_t at %p", addr); 1199 return (DCMD_ERR); 1200 } 1201 1202 mdb_printf("%0?p %05x %3d %0?p %0?p %0?p\n", 1203 addr, squeue.sq_state, squeue.sq_bind, 1204 squeue.sq_first, squeue.sq_last, squeue.sq_worker); 1205 1206 if (!verbose) 1207 return (DCMD_OK); 1208 1209 arm = B_TRUE; 1210 for (i = 0; squeue_states[i].bit_name != NULL; i++) { 1211 if (((squeue.sq_state) & (1 << i)) == 0) 1212 continue; 1213 1214 if (arm) { 1215 mdb_printf("%*s|\n", SQUEUE_STATEDELT, ""); 1216 mdb_printf("%*s+--> ", SQUEUE_STATEDELT, ""); 1217 arm = B_FALSE; 1218 } else 1219 mdb_printf("%*s ", SQUEUE_STATEDELT, ""); 1220 1221 mdb_printf("%-12s %s\n", squeue_states[i].bit_name, 1222 squeue_states[i].bit_descr); 1223 } 1224 1225 return (DCMD_OK); 1226 } 1227 1228 static void 1229 ip_squeue_help(void) 1230 { 1231 mdb_printf("Print the core information for a given NCA squeue_t.\n\n"); 1232 mdb_printf("Options:\n"); 1233 mdb_printf("\t-v\tbe verbose (more descriptive)\n"); 1234 } 1235 1236 /* 1237 * This is called by ::th_trace (via a callback) when walking the th_hash 1238 * list. It calls modent to find the entries. 1239 */ 1240 /* ARGSUSED */ 1241 static int 1242 modent_summary(uintptr_t addr, const void *data, void *private) 1243 { 1244 th_walk_data_t *thw = private; 1245 const struct mod_hash_entry *mhe = data; 1246 th_trace_t th; 1247 1248 if (mdb_vread(&th, sizeof (th), (uintptr_t)mhe->mhe_val) == -1) { 1249 mdb_warn("failed to read th_trace_t %p", mhe->mhe_val); 1250 return (WALK_ERR); 1251 } 1252 1253 if (th.th_refcnt == 0 && thw->thw_non_zero_only) 1254 return (WALK_NEXT); 1255 1256 if (!thw->thw_match) { 1257 mdb_printf("%?p %?p %?p %8d %?p\n", thw->thw_ipst, mhe->mhe_key, 1258 mhe->mhe_val, th.th_refcnt, th.th_id); 1259 } else if (thw->thw_matchkey == (uintptr_t)mhe->mhe_key) { 1260 int i, j, k; 1261 tr_buf_t *tr; 1262 1263 mdb_printf("Object %p in IP stack %p:\n", mhe->mhe_key, 1264 thw->thw_ipst); 1265 i = th.th_trace_lastref; 1266 mdb_printf("\tThread %p refcnt %d:\n", th.th_id, 1267 th.th_refcnt); 1268 for (j = TR_BUF_MAX; j > 0; j--) { 1269 tr = th.th_trbuf + i; 1270 if (tr->tr_depth == 0 || tr->tr_depth > TR_STACK_DEPTH) 1271 break; 1272 mdb_printf("\t T%+ld:\n", tr->tr_time - 1273 thw->thw_lbolt); 1274 for (k = 0; k < tr->tr_depth; k++) 1275 mdb_printf("\t\t%a\n", tr->tr_stack[k]); 1276 if (--i < 0) 1277 i = TR_BUF_MAX - 1; 1278 } 1279 } 1280 return (WALK_NEXT); 1281 } 1282 1283 /* 1284 * This is called by ::th_trace (via a callback) when walking the th_hash 1285 * list. It calls modent to find the entries. 1286 */ 1287 /* ARGSUSED */ 1288 static int 1289 th_hash_summary(uintptr_t addr, const void *data, void *private) 1290 { 1291 const th_hash_t *thh = data; 1292 th_walk_data_t *thw = private; 1293 1294 thw->thw_ipst = (uintptr_t)thh->thh_ipst; 1295 return (mdb_pwalk("modent", modent_summary, private, 1296 (uintptr_t)thh->thh_hash)); 1297 } 1298 1299 /* 1300 * Print or summarize the th_trace_t structures. 1301 */ 1302 static int 1303 th_trace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1304 { 1305 th_walk_data_t thw; 1306 1307 (void) memset(&thw, 0, sizeof (thw)); 1308 1309 if (mdb_getopts(argc, argv, 1310 'n', MDB_OPT_SETBITS, TRUE, &thw.thw_non_zero_only, 1311 NULL) != argc) 1312 return (DCMD_USAGE); 1313 1314 if (!(flags & DCMD_ADDRSPEC)) { 1315 /* 1316 * No address specified. Walk all of the th_hash_t in the 1317 * system, and summarize the th_trace_t entries in each. 1318 */ 1319 mdb_printf("%?s %?s %?s %8s %?s\n", 1320 "IPSTACK", "OBJECT", "TRACE", "REFCNT", "THREAD"); 1321 thw.thw_match = B_FALSE; 1322 } else { 1323 thw.thw_match = B_TRUE; 1324 thw.thw_matchkey = addr; 1325 if (mdb_readvar(&thw.thw_lbolt, 1326 mdb_prop_postmortem ? "panic_lbolt" : "lbolt") == -1) { 1327 mdb_warn("failed to read lbolt"); 1328 return (DCMD_ERR); 1329 } 1330 } 1331 if (mdb_pwalk("th_hash", th_hash_summary, &thw, NULL) == -1) { 1332 mdb_warn("can't walk th_hash entries"); 1333 return (DCMD_ERR); 1334 } 1335 return (DCMD_OK); 1336 } 1337 1338 static void 1339 th_trace_help(void) 1340 { 1341 mdb_printf("If given an address of an ill_t, ipif_t, ire_t, or nce_t, " 1342 "print the\n" 1343 "corresponding th_trace_t structure in detail. Otherwise, if no " 1344 "address is\n" 1345 "given, then summarize all th_trace_t structures.\n\n"); 1346 mdb_printf("Options:\n" 1347 "\t-n\tdisplay only entries with non-zero th_refcnt\n"); 1348 } 1349 1350 static const mdb_dcmd_t dcmds[] = { 1351 { "conn_status", ":", 1352 "display connection structures from ipcl hash tables", 1353 conn_status, conn_status_help }, 1354 { "srcid_status", ":", 1355 "display connection structures from ipcl hash tables", 1356 srcid_status }, 1357 { "ill", "?[-v] [-P v4 | v6]", "display ill_t structures", 1358 ill, ill_help }, 1359 { "illif", "?[-P v4 | v6]", 1360 "display or filter IP Lower Level InterFace structures", illif, 1361 illif_help }, 1362 { "iphdr", ":[-vf]", "display an IPv4 header", iphdr }, 1363 { "ip6hdr", ":[-vf]", "display an IPv6 header", ip6hdr }, 1364 { "ipif", "?[-v] [-P v4 | v6]", "display ipif structures", 1365 ipif, ipif_help }, 1366 { "ire", "?[-v] [-P v4|v6]", 1367 "display Internet Route Entry structures", ire }, 1368 { "nce", "?[-P v4 | v6]", "display Neighbor Cache Entry structures", 1369 nce }, 1370 { "squeue", ":[-v]", "print core squeue_t info", squeue, 1371 ip_squeue_help }, 1372 { "tcphdr", ":", "display a TCP header", tcphdr }, 1373 { "udphdr", ":", "display an UDP header", udphdr }, 1374 { "sctphdr", ":", "display an SCTP header", sctphdr }, 1375 { "th_trace", "?[-n]", "display th_trace_t structures", th_trace, 1376 th_trace_help }, 1377 { NULL } 1378 }; 1379 1380 static const mdb_walker_t walkers[] = { 1381 { "conn_status", "walk list of conn_t structures", 1382 ip_stacks_common_walk_init, conn_status_walk_step, NULL }, 1383 { "illif", "walk list of ill interface types for all stacks", 1384 ip_stacks_common_walk_init, illif_walk_step, NULL }, 1385 { "illif_stack", "walk list of ill interface types", 1386 illif_stack_walk_init, illif_stack_walk_step, 1387 illif_stack_walk_fini }, 1388 { "ill", "walk list of nce structures for all stacks", 1389 ill_walk_init, ill_walk_step, NULL }, 1390 { "ipif", "walk list of ipif structures for all stacks", 1391 ipif_walk_init, ipif_walk_step, NULL }, 1392 { "ipif_list", "walk the linked list of ipif structures " 1393 "for a given ill", 1394 ip_list_walk_init, ip_list_walk_step, 1395 ip_list_walk_fini, &ipif_walk_arg }, 1396 { "srcid", "walk list of srcid_map structures for all stacks", 1397 ip_stacks_common_walk_init, srcid_walk_step, NULL }, 1398 { "srcid_list", "walk list of srcid_map structures for a stack", 1399 ip_list_walk_init, ip_list_walk_step, ip_list_walk_fini, 1400 &srcid_walk_arg }, 1401 { "ire", "walk active ire_t structures", 1402 ire_walk_init, ire_walk_step, NULL }, 1403 { "ire_ctable", "walk ire_t structures in the ctable", 1404 ip_stacks_common_walk_init, ire_ctable_walk_step, NULL }, 1405 { "ire_next", "walk ire_t structures in the ctable", 1406 ire_next_walk_init, ire_next_walk_step, NULL }, 1407 { "ip_stacks", "walk all the ip_stack_t", 1408 ip_stacks_walk_init, ip_stacks_walk_step, NULL }, 1409 { "th_hash", "walk all the th_hash_t entries", 1410 th_hash_walk_init, th_hash_walk_step, NULL }, 1411 { "nce", "walk list of nce structures for all stacks", 1412 ip_stacks_common_walk_init, nce_walk_step, NULL }, 1413 { "nce_stack", "walk list of nce structures", 1414 nce_stack_walk_init, nce_stack_walk_step, 1415 nce_stack_walk_fini}, 1416 { "udp_hash", "walk list of conn_t structures in ips_ipcl_udp_fanout", 1417 ipcl_hash_walk_init, ipcl_hash_walk_step, 1418 ipcl_hash_walk_fini, &udp_hash_arg}, 1419 { "conn_hash", "walk list of conn_t structures in ips_ipcl_conn_fanout", 1420 ipcl_hash_walk_init, ipcl_hash_walk_step, 1421 ipcl_hash_walk_fini, &conn_hash_arg}, 1422 { "bind_hash", "walk list of conn_t structures in ips_ipcl_bind_fanout", 1423 ipcl_hash_walk_init, ipcl_hash_walk_step, 1424 ipcl_hash_walk_fini, &bind_hash_arg}, 1425 { "proto_hash", "walk list of conn_t structures in " 1426 "ips_ipcl_proto_fanout", 1427 ipcl_hash_walk_init, ipcl_hash_walk_step, 1428 ipcl_hash_walk_fini, &proto_hash_arg}, 1429 { "proto_v6_hash", "walk list of conn_t structures in " 1430 "ips_ipcl_proto_fanout_v6", 1431 ipcl_hash_walk_init, ipcl_hash_walk_step, 1432 ipcl_hash_walk_fini, &proto_v6_hash_arg}, 1433 { "ilb_stacks", "walk ilb_stack_t", 1434 ip_stacks_walk_init, ilb_stacks_walk_step, NULL }, 1435 { "ilb_rules", "walk ilb rules in a given ilb_stack_t", 1436 ilb_rules_walk_init, ilb_rules_walk_step, NULL }, 1437 { "ilb_servers", "walk server in a given ilb_rule_t", 1438 ilb_servers_walk_init, ilb_servers_walk_step, NULL }, 1439 { "ilb_nat_src", "walk NAT source table of a given ilb_stack_t", 1440 ilb_nat_src_walk_init, ilb_nat_src_walk_step, 1441 ilb_common_walk_fini }, 1442 { "ilb_conns", "walk NAT table of a given ilb_stack_t", 1443 ilb_conn_walk_init, ilb_conn_walk_step, ilb_common_walk_fini }, 1444 { "ilb_stickys", "walk sticky table of a given ilb_stack_t", 1445 ilb_sticky_walk_init, ilb_sticky_walk_step, 1446 ilb_common_walk_fini }, 1447 { NULL } 1448 }; 1449 1450 static const mdb_qops_t ip_qops = { ip_qinfo, ip_rnext, ip_wnext }; 1451 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; 1452 1453 const mdb_modinfo_t * 1454 _mdb_init(void) 1455 { 1456 GElf_Sym sym; 1457 1458 if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 1459 mdb_qops_install(&ip_qops, (uintptr_t)sym.st_value); 1460 1461 return (&modinfo); 1462 } 1463 1464 void 1465 _mdb_fini(void) 1466 { 1467 GElf_Sym sym; 1468 1469 if (mdb_lookup_by_obj("ip", "ipwinit", &sym) == 0) 1470 mdb_qops_remove(&ip_qops, (uintptr_t)sym.st_value); 1471 } 1472 1473 static char * 1474 nce_state(int nce_state) 1475 { 1476 switch (nce_state) { 1477 case ND_UNCHANGED: 1478 return ("unchanged"); 1479 case ND_INCOMPLETE: 1480 return ("incomplete"); 1481 case ND_REACHABLE: 1482 return ("reachable"); 1483 case ND_STALE: 1484 return ("stale"); 1485 case ND_DELAY: 1486 return ("delay"); 1487 case ND_PROBE: 1488 return ("probe"); 1489 case ND_UNREACHABLE: 1490 return ("unreach"); 1491 case ND_INITIAL: 1492 return ("initial"); 1493 default: 1494 return ("??"); 1495 } 1496 } 1497 1498 static char * 1499 nce_l2_addr(const nce_t *nce, const ill_t *ill) 1500 { 1501 uchar_t *h; 1502 static char addr_buf[L2MAXADDRSTRLEN]; 1503 mblk_t mp; 1504 size_t mblen; 1505 1506 if (ill->ill_flags & ILLF_XRESOLV) { 1507 return ("XRESOLV"); 1508 } 1509 1510 if (nce->nce_res_mp == NULL) { 1511 return ("None"); 1512 } 1513 1514 if (ill->ill_net_type == IRE_IF_RESOLVER) { 1515 1516 if (mdb_vread(&mp, sizeof (mblk_t), 1517 (uintptr_t)nce->nce_res_mp) == -1) { 1518 mdb_warn("failed to read nce_res_mp at %p", 1519 nce->nce_res_mp); 1520 } 1521 1522 if (ill->ill_nd_lla_len == 0) 1523 return ("None"); 1524 mblen = mp.b_wptr - mp.b_rptr; 1525 if (mblen > (sizeof (dl_unitdata_req_t) + MAX_SAP_LEN) || 1526 ill->ill_nd_lla_len > MAX_SAP_LEN || 1527 NCE_LL_ADDR_OFFSET(ill) + ill->ill_nd_lla_len > mblen) { 1528 return ("Truncated"); 1529 } 1530 h = mdb_zalloc(mblen, UM_SLEEP); 1531 if (mdb_vread(h, mblen, (uintptr_t)(mp.b_rptr)) == -1) { 1532 mdb_warn("failed to read hwaddr at %p", 1533 mp.b_rptr + NCE_LL_ADDR_OFFSET(ill)); 1534 return ("Unknown"); 1535 } 1536 mdb_mac_addr(h + NCE_LL_ADDR_OFFSET(ill), ill->ill_nd_lla_len, 1537 addr_buf, sizeof (addr_buf)); 1538 } else { 1539 return ("None"); 1540 } 1541 mdb_free(h, mblen); 1542 return (addr_buf); 1543 } 1544 1545 static void 1546 nce_header(uint_t flags) 1547 { 1548 if ((flags & DCMD_LOOPFIRST) || !(flags & DCMD_LOOP)) { 1549 1550 mdb_printf("%<u>%?s %-20s %-10s %-8s %-5s %s%</u>\n", 1551 "ADDR", "HW_ADDR", "STATE", "FLAGS", "ILL", "IP ADDR"); 1552 } 1553 } 1554 1555 int 1556 nce(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1557 { 1558 nce_t nce; 1559 nce_cbdata_t id; 1560 int ipversion = 0; 1561 const char *opt_P = NULL; 1562 1563 if (mdb_getopts(argc, argv, 1564 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 1565 return (DCMD_USAGE); 1566 1567 if (opt_P != NULL) { 1568 if (strcmp("v4", opt_P) == 0) { 1569 ipversion = IPV4_VERSION; 1570 } else if (strcmp("v6", opt_P) == 0) { 1571 ipversion = IPV6_VERSION; 1572 } else { 1573 mdb_warn("invalid protocol '%s'\n", opt_P); 1574 return (DCMD_USAGE); 1575 } 1576 } 1577 1578 if (flags & DCMD_ADDRSPEC) { 1579 1580 if (mdb_vread(&nce, sizeof (nce_t), addr) == -1) { 1581 mdb_warn("failed to read nce at %p\n", addr); 1582 return (DCMD_ERR); 1583 } 1584 if (ipversion != 0 && nce.nce_ipversion != ipversion) { 1585 mdb_printf("IP Version mismatch\n"); 1586 return (DCMD_ERR); 1587 } 1588 nce_header(flags); 1589 return (nce_format(addr, &nce, ipversion)); 1590 1591 } else { 1592 id.nce_addr = addr; 1593 id.nce_ipversion = ipversion; 1594 nce_header(flags); 1595 if (mdb_walk("nce", (mdb_walk_cb_t)nce_cb, &id) == -1) { 1596 mdb_warn("failed to walk nce table\n"); 1597 return (DCMD_ERR); 1598 } 1599 } 1600 return (DCMD_OK); 1601 } 1602 1603 static int 1604 nce_format(uintptr_t addr, const nce_t *nce, int ipversion) 1605 { 1606 static const mdb_bitmask_t nce_flags[] = { 1607 { "P", NCE_F_PERMANENT, NCE_F_PERMANENT }, 1608 { "R", NCE_F_ISROUTER, NCE_F_ISROUTER }, 1609 { "N", NCE_F_NONUD, NCE_F_NONUD }, 1610 { "A", NCE_F_ANYCAST, NCE_F_ANYCAST }, 1611 { "C", NCE_F_CONDEMNED, NCE_F_CONDEMNED }, 1612 { "U", NCE_F_UNSOL_ADV, NCE_F_UNSOL_ADV }, 1613 { "B", NCE_F_BCAST, NCE_F_BCAST }, 1614 { NULL, 0, 0 } 1615 }; 1616 #define NCE_MAX_FLAGS (sizeof (nce_flags) / sizeof (mdb_bitmask_t)) 1617 struct in_addr nceaddr; 1618 ill_t ill; 1619 char ill_name[LIFNAMSIZ]; 1620 char flagsbuf[NCE_MAX_FLAGS]; 1621 1622 if (mdb_vread(&ill, sizeof (ill), (uintptr_t)nce->nce_ill) == -1) { 1623 mdb_warn("failed to read nce_ill at %p", 1624 nce->nce_ill); 1625 return (DCMD_ERR); 1626 } 1627 1628 (void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill.ill_name_length), 1629 (uintptr_t)ill.ill_name); 1630 1631 mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%hb", 1632 nce->nce_flags, nce_flags); 1633 1634 if (ipversion != 0 && nce->nce_ipversion != ipversion) 1635 return (DCMD_OK); 1636 1637 if (nce->nce_ipversion == IPV4_VERSION) { 1638 IN6_V4MAPPED_TO_INADDR(&nce->nce_addr, &nceaddr); 1639 mdb_printf("%?p %-20s %-10s " 1640 "%-8s " 1641 "%-5s %I\n", 1642 addr, nce_l2_addr(nce, &ill), 1643 nce_state(nce->nce_state), 1644 flagsbuf, 1645 ill_name, nceaddr.s_addr); 1646 } else { 1647 mdb_printf("%?p %-20s %-10s %-8s %-5s %N\n", 1648 addr, nce_l2_addr(nce, &ill), 1649 nce_state(nce->nce_state), 1650 flagsbuf, 1651 ill_name, &nce->nce_addr); 1652 } 1653 1654 return (DCMD_OK); 1655 } 1656 1657 static uintptr_t 1658 nce_get_next_hash_tbl(uintptr_t start, int *index, struct ndp_g_s ndp) 1659 { 1660 uintptr_t addr = start; 1661 int i = *index; 1662 1663 while (addr == NULL) { 1664 1665 if (++i >= NCE_TABLE_SIZE) 1666 break; 1667 addr = (uintptr_t)ndp.nce_hash_tbl[i]; 1668 } 1669 *index = i; 1670 return (addr); 1671 } 1672 1673 static int 1674 nce_walk_step(mdb_walk_state_t *wsp) 1675 { 1676 uintptr_t kaddr4, kaddr6; 1677 1678 kaddr4 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp4); 1679 kaddr6 = wsp->walk_addr + OFFSETOF(ip_stack_t, ips_ndp6); 1680 1681 if (mdb_vread(&kaddr4, sizeof (kaddr4), kaddr4) == -1) { 1682 mdb_warn("can't read ips_ip_cache_table at %p", kaddr4); 1683 return (WALK_ERR); 1684 } 1685 if (mdb_vread(&kaddr6, sizeof (kaddr6), kaddr6) == -1) { 1686 mdb_warn("can't read ips_ip_cache_table at %p", kaddr6); 1687 return (WALK_ERR); 1688 } 1689 if (mdb_pwalk("nce_stack", wsp->walk_callback, wsp->walk_cbdata, 1690 kaddr4) == -1) { 1691 mdb_warn("couldn't walk 'nce_stack' for ips_ndp4 %p", 1692 kaddr4); 1693 return (WALK_ERR); 1694 } 1695 if (mdb_pwalk("nce_stack", wsp->walk_callback, 1696 wsp->walk_cbdata, kaddr6) == -1) { 1697 mdb_warn("couldn't walk 'nce_stack' for ips_ndp6 %p", 1698 kaddr6); 1699 return (WALK_ERR); 1700 } 1701 return (WALK_NEXT); 1702 } 1703 1704 static uintptr_t 1705 ipcl_hash_get_next_connf_tbl(ipcl_hash_walk_data_t *iw) 1706 { 1707 struct connf_s connf; 1708 uintptr_t addr = NULL, next; 1709 int index = iw->connf_tbl_index; 1710 1711 do { 1712 next = iw->hash_tbl + index * sizeof (struct connf_s); 1713 if (++index >= iw->hash_tbl_size) { 1714 addr = NULL; 1715 break; 1716 } 1717 if (mdb_vread(&connf, sizeof (struct connf_s), next) == -1) { 1718 mdb_warn("failed to read conn_t at %p", next); 1719 return (NULL); 1720 } 1721 addr = (uintptr_t)connf.connf_head; 1722 } while (addr == NULL); 1723 iw->connf_tbl_index = index; 1724 return (addr); 1725 } 1726 1727 static int 1728 ipcl_hash_walk_init(mdb_walk_state_t *wsp) 1729 { 1730 const hash_walk_arg_t *arg = wsp->walk_arg; 1731 ipcl_hash_walk_data_t *iw; 1732 uintptr_t tbladdr; 1733 uintptr_t sizeaddr; 1734 1735 iw = mdb_alloc(sizeof (ipcl_hash_walk_data_t), UM_SLEEP); 1736 iw->conn = mdb_alloc(sizeof (conn_t), UM_SLEEP); 1737 tbladdr = wsp->walk_addr + arg->tbl_off; 1738 sizeaddr = wsp->walk_addr + arg->size_off; 1739 1740 if (mdb_vread(&iw->hash_tbl, sizeof (uintptr_t), tbladdr) == -1) { 1741 mdb_warn("can't read fanout table addr at %p", tbladdr); 1742 mdb_free(iw->conn, sizeof (conn_t)); 1743 mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 1744 return (WALK_ERR); 1745 } 1746 if (arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout) || 1747 arg->tbl_off == OFFSETOF(ip_stack_t, ips_ipcl_proto_fanout_v6)) { 1748 iw->hash_tbl_size = IPPROTO_MAX; 1749 } else { 1750 if (mdb_vread(&iw->hash_tbl_size, sizeof (int), 1751 sizeaddr) == -1) { 1752 mdb_warn("can't read fanout table size addr at %p", 1753 sizeaddr); 1754 mdb_free(iw->conn, sizeof (conn_t)); 1755 mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 1756 return (WALK_ERR); 1757 } 1758 } 1759 iw->connf_tbl_index = 0; 1760 wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw); 1761 wsp->walk_data = iw; 1762 1763 if (wsp->walk_addr != NULL) 1764 return (WALK_NEXT); 1765 else 1766 return (WALK_DONE); 1767 } 1768 1769 static int 1770 ipcl_hash_walk_step(mdb_walk_state_t *wsp) 1771 { 1772 uintptr_t addr = wsp->walk_addr; 1773 ipcl_hash_walk_data_t *iw = wsp->walk_data; 1774 conn_t *conn = iw->conn; 1775 int ret = WALK_DONE; 1776 1777 while (addr != NULL) { 1778 if (mdb_vread(conn, sizeof (conn_t), addr) == -1) { 1779 mdb_warn("failed to read conn_t at %p", addr); 1780 return (WALK_ERR); 1781 } 1782 ret = wsp->walk_callback(addr, iw, wsp->walk_cbdata); 1783 if (ret != WALK_NEXT) 1784 break; 1785 addr = (uintptr_t)conn->conn_next; 1786 } 1787 if (ret == WALK_NEXT) { 1788 wsp->walk_addr = ipcl_hash_get_next_connf_tbl(iw); 1789 1790 if (wsp->walk_addr != NULL) 1791 return (WALK_NEXT); 1792 else 1793 return (WALK_DONE); 1794 } 1795 1796 return (ret); 1797 } 1798 1799 static void 1800 ipcl_hash_walk_fini(mdb_walk_state_t *wsp) 1801 { 1802 ipcl_hash_walk_data_t *iw = wsp->walk_data; 1803 1804 mdb_free(iw->conn, sizeof (conn_t)); 1805 mdb_free(iw, sizeof (ipcl_hash_walk_data_t)); 1806 } 1807 1808 /* 1809 * Called with walk_addr being the address of ips_ndp{4,6} 1810 */ 1811 static int 1812 nce_stack_walk_init(mdb_walk_state_t *wsp) 1813 { 1814 nce_walk_data_t *nw; 1815 1816 if (wsp->walk_addr == NULL) { 1817 mdb_warn("nce_stack requires ndp_g_s address\n"); 1818 return (WALK_ERR); 1819 } 1820 1821 nw = mdb_alloc(sizeof (nce_walk_data_t), UM_SLEEP); 1822 1823 if (mdb_vread(&nw->nce_ip_ndp, sizeof (struct ndp_g_s), 1824 wsp->walk_addr) == -1) { 1825 mdb_warn("failed to read 'ip_ndp' at %p", 1826 wsp->walk_addr); 1827 mdb_free(nw, sizeof (nce_walk_data_t)); 1828 return (WALK_ERR); 1829 } 1830 1831 nw->nce_hash_tbl_index = 0; 1832 wsp->walk_addr = nce_get_next_hash_tbl(NULL, 1833 &nw->nce_hash_tbl_index, nw->nce_ip_ndp); 1834 wsp->walk_data = nw; 1835 1836 return (WALK_NEXT); 1837 } 1838 1839 static int 1840 nce_stack_walk_step(mdb_walk_state_t *wsp) 1841 { 1842 uintptr_t addr = wsp->walk_addr; 1843 nce_walk_data_t *nw = wsp->walk_data; 1844 1845 if (addr == NULL) 1846 return (WALK_DONE); 1847 1848 if (mdb_vread(&nw->nce, sizeof (nce_t), addr) == -1) { 1849 mdb_warn("failed to read nce_t at %p", addr); 1850 return (WALK_ERR); 1851 } 1852 1853 wsp->walk_addr = (uintptr_t)nw->nce.nce_next; 1854 1855 wsp->walk_addr = nce_get_next_hash_tbl(wsp->walk_addr, 1856 &nw->nce_hash_tbl_index, nw->nce_ip_ndp); 1857 1858 return (wsp->walk_callback(addr, nw, wsp->walk_cbdata)); 1859 } 1860 1861 static void 1862 nce_stack_walk_fini(mdb_walk_state_t *wsp) 1863 { 1864 mdb_free(wsp->walk_data, sizeof (nce_walk_data_t)); 1865 } 1866 1867 /* ARGSUSED */ 1868 static int 1869 nce_cb(uintptr_t addr, const nce_walk_data_t *iw, nce_cbdata_t *id) 1870 { 1871 nce_t nce; 1872 1873 if (mdb_vread(&nce, sizeof (nce_t), addr) == -1) { 1874 mdb_warn("failed to read nce at %p", addr); 1875 return (WALK_NEXT); 1876 } 1877 (void) nce_format(addr, &nce, id->nce_ipversion); 1878 return (WALK_NEXT); 1879 } 1880 1881 static int 1882 ill_walk_init(mdb_walk_state_t *wsp) 1883 { 1884 if (mdb_layered_walk("illif", wsp) == -1) { 1885 mdb_warn("can't walk 'illif'"); 1886 return (WALK_ERR); 1887 } 1888 return (WALK_NEXT); 1889 } 1890 1891 static int 1892 ill_walk_step(mdb_walk_state_t *wsp) 1893 { 1894 ill_if_t ill_if; 1895 1896 if (mdb_vread(&ill_if, sizeof (ill_if_t), wsp->walk_addr) == -1) { 1897 mdb_warn("can't read ill_if_t at %p", wsp->walk_addr); 1898 return (WALK_ERR); 1899 } 1900 wsp->walk_addr = (uintptr_t)(wsp->walk_addr + 1901 offsetof(ill_if_t, illif_avl_by_ppa)); 1902 if (mdb_pwalk("avl", wsp->walk_callback, wsp->walk_cbdata, 1903 wsp->walk_addr) == -1) { 1904 mdb_warn("can't walk 'avl'"); 1905 return (WALK_ERR); 1906 } 1907 1908 return (WALK_NEXT); 1909 } 1910 1911 /* ARGSUSED */ 1912 static int 1913 ill_cb(uintptr_t addr, const ill_walk_data_t *iw, ill_cbdata_t *id) 1914 { 1915 ill_t ill; 1916 1917 if (mdb_vread(&ill, sizeof (ill_t), (uintptr_t)addr) == -1) { 1918 mdb_warn("failed to read ill at %p", addr); 1919 return (WALK_NEXT); 1920 } 1921 return (ill_format((uintptr_t)addr, &ill, id)); 1922 } 1923 1924 static void 1925 ill_header(boolean_t verbose) 1926 { 1927 if (verbose) { 1928 mdb_printf("%-?s %-8s %3s %-10s %-?s %-?s %-10s%</u>\n", 1929 "ADDR", "NAME", "VER", "TYPE", "WQ", "IPST", "FLAGS"); 1930 mdb_printf("%-?s %4s%4s %-?s\n", 1931 "PHYINT", "CNT", "", "GROUP"); 1932 mdb_printf("%<u>%80s%</u>\n", ""); 1933 } else { 1934 mdb_printf("%<u>%-?s %-8s %-3s %-10s %4s %-?s %-10s%</u>\n", 1935 "ADDR", "NAME", "VER", "TYPE", "CNT", "WQ", "FLAGS"); 1936 } 1937 } 1938 1939 static int 1940 ill_format(uintptr_t addr, const void *illptr, void *ill_cb_arg) 1941 { 1942 ill_t *ill = (ill_t *)illptr; 1943 ill_cbdata_t *illcb = ill_cb_arg; 1944 boolean_t verbose = illcb->verbose; 1945 phyint_t phyi; 1946 static const mdb_bitmask_t fmasks[] = { 1947 { "R", PHYI_RUNNING, PHYI_RUNNING }, 1948 { "P", PHYI_PROMISC, PHYI_PROMISC }, 1949 { "V", PHYI_VIRTUAL, PHYI_VIRTUAL }, 1950 { "I", PHYI_IPMP, PHYI_IPMP }, 1951 { "f", PHYI_FAILED, PHYI_FAILED }, 1952 { "S", PHYI_STANDBY, PHYI_STANDBY }, 1953 { "i", PHYI_INACTIVE, PHYI_INACTIVE }, 1954 { "O", PHYI_OFFLINE, PHYI_OFFLINE }, 1955 { "T", ILLF_NOTRAILERS, ILLF_NOTRAILERS }, 1956 { "A", ILLF_NOARP, ILLF_NOARP }, 1957 { "M", ILLF_MULTICAST, ILLF_MULTICAST }, 1958 { "F", ILLF_ROUTER, ILLF_ROUTER }, 1959 { "D", ILLF_NONUD, ILLF_NONUD }, 1960 { "X", ILLF_NORTEXCH, ILLF_NORTEXCH }, 1961 { NULL, 0, 0 } 1962 }; 1963 static const mdb_bitmask_t v_fmasks[] = { 1964 { "RUNNING", PHYI_RUNNING, PHYI_RUNNING }, 1965 { "PROMISC", PHYI_PROMISC, PHYI_PROMISC }, 1966 { "VIRTUAL", PHYI_VIRTUAL, PHYI_VIRTUAL }, 1967 { "IPMP", PHYI_IPMP, PHYI_IPMP }, 1968 { "FAILED", PHYI_FAILED, PHYI_FAILED }, 1969 { "STANDBY", PHYI_STANDBY, PHYI_STANDBY }, 1970 { "INACTIVE", PHYI_INACTIVE, PHYI_INACTIVE }, 1971 { "OFFLINE", PHYI_OFFLINE, PHYI_OFFLINE }, 1972 { "NOTRAILER", ILLF_NOTRAILERS, ILLF_NOTRAILERS }, 1973 { "NOARP", ILLF_NOARP, ILLF_NOARP }, 1974 { "MULTICAST", ILLF_MULTICAST, ILLF_MULTICAST }, 1975 { "ROUTER", ILLF_ROUTER, ILLF_ROUTER }, 1976 { "NONUD", ILLF_NONUD, ILLF_NONUD }, 1977 { "NORTEXCH", ILLF_NORTEXCH, ILLF_NORTEXCH }, 1978 { NULL, 0, 0 } 1979 }; 1980 char ill_name[LIFNAMSIZ]; 1981 int cnt; 1982 char *typebuf; 1983 char sbuf[DEFCOLS]; 1984 int ipver = illcb->ill_ipversion; 1985 1986 if (ipver != 0) { 1987 if ((ipver == IPV4_VERSION && ill->ill_isv6) || 1988 (ipver == IPV6_VERSION && !ill->ill_isv6)) { 1989 return (WALK_NEXT); 1990 } 1991 } 1992 if (mdb_vread(&phyi, sizeof (phyint_t), 1993 (uintptr_t)ill->ill_phyint) == -1) { 1994 mdb_warn("failed to read ill_phyint at %p", 1995 (uintptr_t)ill->ill_phyint); 1996 return (WALK_NEXT); 1997 } 1998 (void) mdb_readstr(ill_name, MIN(LIFNAMSIZ, ill->ill_name_length), 1999 (uintptr_t)ill->ill_name); 2000 2001 switch (ill->ill_type) { 2002 case 0: 2003 typebuf = "LOOPBACK"; 2004 break; 2005 case IFT_ETHER: 2006 typebuf = "ETHER"; 2007 break; 2008 case IFT_OTHER: 2009 typebuf = "OTHER"; 2010 break; 2011 default: 2012 typebuf = NULL; 2013 break; 2014 } 2015 cnt = ill->ill_refcnt + ill->ill_ire_cnt + ill->ill_nce_cnt + 2016 ill->ill_ilm_walker_cnt + ill->ill_ilm_cnt; 2017 mdb_printf("%-?p %-8s %-3s ", 2018 addr, ill_name, ill->ill_isv6 ? "v6" : "v4"); 2019 if (typebuf != NULL) 2020 mdb_printf("%-10s ", typebuf); 2021 else 2022 mdb_printf("%-10x ", ill->ill_type); 2023 if (verbose) { 2024 mdb_printf("%-?p %-?p %-llb\n", 2025 ill->ill_wq, ill->ill_ipst, 2026 ill->ill_flags | phyi.phyint_flags, v_fmasks); 2027 mdb_printf("%-?p %4d%4s %-?p\n", 2028 ill->ill_phyint, cnt, "", ill->ill_grp); 2029 mdb_snprintf(sbuf, sizeof (sbuf), "%*s %3s", 2030 sizeof (uintptr_t) * 2, "", ""); 2031 mdb_printf("%s|\n%s+--> %3d %-18s " 2032 "references from active threads\n", 2033 sbuf, sbuf, ill->ill_refcnt, "ill_refcnt"); 2034 mdb_printf("%*s %7d %-18s ires referencing this ill\n", 2035 strlen(sbuf), "", ill->ill_ire_cnt, "ill_ire_cnt"); 2036 mdb_printf("%*s %7d %-18s nces referencing this ill\n", 2037 strlen(sbuf), "", ill->ill_nce_cnt, "ill_nce_cnt"); 2038 mdb_printf("%*s %7d %-18s ilms referencing this ill\n", 2039 strlen(sbuf), "", ill->ill_ilm_cnt, "ill_ilm_cnt"); 2040 mdb_printf("%*s %7d %-18s active ilm walkers\n\n", 2041 strlen(sbuf), "", ill->ill_ilm_walker_cnt, 2042 "ill_ilm_walker_cnt"); 2043 } else { 2044 mdb_printf("%4d %-?p %-llb\n", 2045 cnt, ill->ill_wq, 2046 ill->ill_flags | phyi.phyint_flags, fmasks); 2047 } 2048 return (WALK_NEXT); 2049 } 2050 2051 static int 2052 ill(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2053 { 2054 ill_t ill_data; 2055 ill_cbdata_t id; 2056 int ipversion = 0; 2057 const char *opt_P = NULL; 2058 uint_t verbose = FALSE; 2059 2060 if (mdb_getopts(argc, argv, 2061 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2062 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2063 return (DCMD_USAGE); 2064 2065 if (opt_P != NULL) { 2066 if (strcmp("v4", opt_P) == 0) { 2067 ipversion = IPV4_VERSION; 2068 } else if (strcmp("v6", opt_P) == 0) { 2069 ipversion = IPV6_VERSION; 2070 } else { 2071 mdb_warn("invalid protocol '%s'\n", opt_P); 2072 return (DCMD_USAGE); 2073 } 2074 } 2075 2076 id.verbose = verbose; 2077 id.ill_addr = addr; 2078 id.ill_ipversion = ipversion; 2079 2080 ill_header(verbose); 2081 if (flags & DCMD_ADDRSPEC) { 2082 if (mdb_vread(&ill_data, sizeof (ill_t), addr) == -1) { 2083 mdb_warn("failed to read ill at %p\n", addr); 2084 return (DCMD_ERR); 2085 } 2086 (void) ill_format(addr, &ill_data, &id); 2087 } else { 2088 if (mdb_walk("ill", (mdb_walk_cb_t)ill_cb, &id) == -1) { 2089 mdb_warn("failed to walk ills\n"); 2090 return (DCMD_ERR); 2091 } 2092 } 2093 return (DCMD_OK); 2094 } 2095 2096 static void 2097 ill_help(void) 2098 { 2099 mdb_printf("Prints the following fields: ill ptr, name, " 2100 "IP version, count, ill type and ill flags.\n" 2101 "The count field is a sum of individual refcnts and is expanded " 2102 "with the -v option.\n\n"); 2103 mdb_printf("Options:\n"); 2104 mdb_printf("\t-P v4 | v6" 2105 "\tfilter ill structures for the specified protocol\n"); 2106 } 2107 2108 static int 2109 ip_list_walk_init(mdb_walk_state_t *wsp) 2110 { 2111 const ip_list_walk_arg_t *arg = wsp->walk_arg; 2112 ip_list_walk_data_t *iw; 2113 uintptr_t addr = (uintptr_t)(wsp->walk_addr + arg->off); 2114 2115 if (wsp->walk_addr == NULL) { 2116 mdb_warn("only local walks supported\n"); 2117 return (WALK_ERR); 2118 } 2119 if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), 2120 addr) == -1) { 2121 mdb_warn("failed to read list head at %p", addr); 2122 return (WALK_ERR); 2123 } 2124 iw = mdb_alloc(sizeof (ip_list_walk_data_t), UM_SLEEP); 2125 iw->nextoff = arg->nextp_off; 2126 wsp->walk_data = iw; 2127 2128 return (WALK_NEXT); 2129 } 2130 2131 static int 2132 ip_list_walk_step(mdb_walk_state_t *wsp) 2133 { 2134 ip_list_walk_data_t *iw = wsp->walk_data; 2135 uintptr_t addr = wsp->walk_addr; 2136 2137 if (addr == NULL) 2138 return (WALK_DONE); 2139 wsp->walk_addr = addr + iw->nextoff; 2140 if (mdb_vread(&wsp->walk_addr, sizeof (uintptr_t), 2141 wsp->walk_addr) == -1) { 2142 mdb_warn("failed to read list node at %p", addr); 2143 return (WALK_ERR); 2144 } 2145 return (wsp->walk_callback(addr, iw, wsp->walk_cbdata)); 2146 } 2147 2148 static void 2149 ip_list_walk_fini(mdb_walk_state_t *wsp) 2150 { 2151 mdb_free(wsp->walk_data, sizeof (ip_list_walk_data_t)); 2152 } 2153 2154 static int 2155 ipif_walk_init(mdb_walk_state_t *wsp) 2156 { 2157 if (mdb_layered_walk("ill", wsp) == -1) { 2158 mdb_warn("can't walk 'ills'"); 2159 return (WALK_ERR); 2160 } 2161 return (WALK_NEXT); 2162 } 2163 2164 static int 2165 ipif_walk_step(mdb_walk_state_t *wsp) 2166 { 2167 if (mdb_pwalk("ipif_list", wsp->walk_callback, wsp->walk_cbdata, 2168 wsp->walk_addr) == -1) { 2169 mdb_warn("can't walk 'ipif_list'"); 2170 return (WALK_ERR); 2171 } 2172 2173 return (WALK_NEXT); 2174 } 2175 2176 /* ARGSUSED */ 2177 static int 2178 ipif_cb(uintptr_t addr, const ipif_walk_data_t *iw, ipif_cbdata_t *id) 2179 { 2180 ipif_t ipif; 2181 2182 if (mdb_vread(&ipif, sizeof (ipif_t), (uintptr_t)addr) == -1) { 2183 mdb_warn("failed to read ipif at %p", addr); 2184 return (WALK_NEXT); 2185 } 2186 if (mdb_vread(&id->ill, sizeof (ill_t), 2187 (uintptr_t)ipif.ipif_ill) == -1) { 2188 mdb_warn("failed to read ill at %p", ipif.ipif_ill); 2189 return (WALK_NEXT); 2190 } 2191 (void) ipif_format((uintptr_t)addr, &ipif, id); 2192 return (WALK_NEXT); 2193 } 2194 2195 static void 2196 ipif_header(boolean_t verbose) 2197 { 2198 if (verbose) { 2199 mdb_printf("%-?s %-10s %-3s %-?s %-8s %-30s\n", 2200 "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS"); 2201 mdb_printf("%s\n%s\n", 2202 "LCLADDR", "BROADCAST"); 2203 mdb_printf("%<u>%80s%</u>\n", ""); 2204 } else { 2205 mdb_printf("%-?s %-10s %6s %-?s %-8s %-30s\n", 2206 "ADDR", "NAME", "CNT", "ILL", "STFLAGS", "FLAGS"); 2207 mdb_printf("%s\n%<u>%80s%</u>\n", "LCLADDR", ""); 2208 } 2209 } 2210 2211 #ifdef _BIG_ENDIAN 2212 #define ip_ntohl_32(x) ((x) & 0xffffffff) 2213 #else 2214 #define ip_ntohl_32(x) (((uint32_t)(x) << 24) | \ 2215 (((uint32_t)(x) << 8) & 0xff0000) | \ 2216 (((uint32_t)(x) >> 8) & 0xff00) | \ 2217 ((uint32_t)(x) >> 24)) 2218 #endif 2219 2220 int 2221 mask_to_prefixlen(int af, const in6_addr_t *addr) 2222 { 2223 int len = 0; 2224 int i; 2225 uint_t mask = 0; 2226 2227 if (af == AF_INET6) { 2228 for (i = 0; i < 4; i++) { 2229 if (addr->s6_addr32[i] == 0xffffffff) { 2230 len += 32; 2231 } else { 2232 mask = addr->s6_addr32[i]; 2233 break; 2234 } 2235 } 2236 } else { 2237 mask = V4_PART_OF_V6((*addr)); 2238 } 2239 if (mask > 0) 2240 len += (33 - mdb_ffs(ip_ntohl_32(mask))); 2241 return (len); 2242 } 2243 2244 static int 2245 ipif_format(uintptr_t addr, const void *ipifptr, void *ipif_cb_arg) 2246 { 2247 const ipif_t *ipif = ipifptr; 2248 ipif_cbdata_t *ipifcb = ipif_cb_arg; 2249 boolean_t verbose = ipifcb->verbose; 2250 char ill_name[LIFNAMSIZ]; 2251 char buf[LIFNAMSIZ]; 2252 int cnt; 2253 static const mdb_bitmask_t sfmasks[] = { 2254 { "CO", IPIF_CONDEMNED, IPIF_CONDEMNED}, 2255 { "CH", IPIF_CHANGING, IPIF_CHANGING}, 2256 { "SL", IPIF_SET_LINKLOCAL, IPIF_SET_LINKLOCAL}, 2257 { "ZS", IPIF_ZERO_SOURCE, IPIF_ZERO_SOURCE}, 2258 { NULL, 0, 0 } 2259 }; 2260 static const mdb_bitmask_t fmasks[] = { 2261 { "UP", IPIF_UP, IPIF_UP }, 2262 { "UNN", IPIF_UNNUMBERED, IPIF_UNNUMBERED}, 2263 { "DHCP", IPIF_DHCPRUNNING, IPIF_DHCPRUNNING}, 2264 { "PRIV", IPIF_PRIVATE, IPIF_PRIVATE}, 2265 { "NOXMT", IPIF_NOXMIT, IPIF_NOXMIT}, 2266 { "NOLCL", IPIF_NOLOCAL, IPIF_NOLOCAL}, 2267 { "DEPR", IPIF_DEPRECATED, IPIF_DEPRECATED}, 2268 { "PREF", IPIF_PREFERRED, IPIF_PREFERRED}, 2269 { "TEMP", IPIF_TEMPORARY, IPIF_TEMPORARY}, 2270 { "ACONF", IPIF_ADDRCONF, IPIF_ADDRCONF}, 2271 { "ANY", IPIF_ANYCAST, IPIF_ANYCAST}, 2272 { "NFAIL", IPIF_NOFAILOVER, IPIF_NOFAILOVER}, 2273 { NULL, 0, 0 } 2274 }; 2275 char flagsbuf[2 * A_CNT(fmasks)]; 2276 char bitfields[A_CNT(fmasks)]; 2277 char sflagsbuf[A_CNT(sfmasks)]; 2278 char sbuf[DEFCOLS], addrstr[INET6_ADDRSTRLEN]; 2279 int ipver = ipifcb->ipif_ipversion; 2280 int af; 2281 2282 if (ipver != 0) { 2283 if ((ipver == IPV4_VERSION && ipifcb->ill.ill_isv6) || 2284 (ipver == IPV6_VERSION && !ipifcb->ill.ill_isv6)) { 2285 return (WALK_NEXT); 2286 } 2287 } 2288 if ((mdb_readstr(ill_name, MIN(LIFNAMSIZ, 2289 ipifcb->ill.ill_name_length), 2290 (uintptr_t)ipifcb->ill.ill_name)) == -1) { 2291 mdb_warn("failed to read ill_name of ill %p\n", ipifcb->ill); 2292 return (WALK_NEXT); 2293 } 2294 if (ipif->ipif_id != 0) { 2295 mdb_snprintf(buf, LIFNAMSIZ, "%s:%d", 2296 ill_name, ipif->ipif_id); 2297 } else { 2298 mdb_snprintf(buf, LIFNAMSIZ, "%s", ill_name); 2299 } 2300 mdb_snprintf(bitfields, sizeof (bitfields), "%s", 2301 ipif->ipif_addr_ready ? ",ADR" : "", 2302 ipif->ipif_multicast_up ? ",MU" : "", 2303 ipif->ipif_was_up ? ",WU" : "", 2304 ipif->ipif_was_dup ? ",WD" : "", 2305 ipif->ipif_joined_allhosts ? ",JA" : ""); 2306 mdb_snprintf(flagsbuf, sizeof (flagsbuf), "%llb%s", 2307 ipif->ipif_flags, fmasks, bitfields); 2308 mdb_snprintf(sflagsbuf, sizeof (sflagsbuf), "%b", 2309 ipif->ipif_state_flags, sfmasks); 2310 2311 cnt = ipif->ipif_refcnt + ipif->ipif_ire_cnt + ipif->ipif_ilm_cnt; 2312 2313 if (ipifcb->ill.ill_isv6) { 2314 mdb_snprintf(addrstr, sizeof (addrstr), "%N", 2315 &ipif->ipif_v6lcl_addr); 2316 af = AF_INET6; 2317 } else { 2318 mdb_snprintf(addrstr, sizeof (addrstr), "%I", 2319 V4_PART_OF_V6((ipif->ipif_v6lcl_addr))); 2320 af = AF_INET; 2321 } 2322 2323 if (verbose) { 2324 mdb_printf("%-?p %-10s %3d %-?p %-8s %-30s\n", 2325 addr, buf, cnt, ipif->ipif_ill, 2326 sflagsbuf, flagsbuf); 2327 mdb_snprintf(sbuf, sizeof (sbuf), "%*s %12s", 2328 sizeof (uintptr_t) * 2, "", ""); 2329 mdb_printf("%s |\n%s +---> %4d %-15s " 2330 "Active consistent reader cnt\n", 2331 sbuf, sbuf, ipif->ipif_refcnt, "ipif_refcnt"); 2332 mdb_printf("%*s %10d %-15s " 2333 "Number of ire's referencing this ipif\n", 2334 strlen(sbuf), "", ipif->ipif_ire_cnt, "ipif_ire_cnt"); 2335 mdb_printf("%*s %10d %-15s " 2336 "Number of ilm's referencing this ipif\n\n", 2337 strlen(sbuf), "", ipif->ipif_ilm_cnt, "ipif_ilm_cnt"); 2338 mdb_printf("%-s/%d\n", 2339 addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask)); 2340 if (ipifcb->ill.ill_isv6) { 2341 mdb_printf("%-N\n", &ipif->ipif_v6brd_addr); 2342 } else { 2343 mdb_printf("%-I\n", 2344 V4_PART_OF_V6((ipif->ipif_v6brd_addr))); 2345 } 2346 } else { 2347 mdb_printf("%-?p %-10s %6d %-?p %-8s %-30s\n", 2348 addr, buf, cnt, ipif->ipif_ill, 2349 sflagsbuf, flagsbuf); 2350 mdb_printf("%-s/%d\n", 2351 addrstr, mask_to_prefixlen(af, &ipif->ipif_v6net_mask)); 2352 } 2353 2354 return (WALK_NEXT); 2355 } 2356 2357 static int 2358 ipif(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2359 { 2360 ipif_t ipif; 2361 ipif_cbdata_t id; 2362 int ipversion = 0; 2363 const char *opt_P = NULL; 2364 uint_t verbose = FALSE; 2365 2366 if (mdb_getopts(argc, argv, 2367 'v', MDB_OPT_SETBITS, TRUE, &verbose, 2368 'P', MDB_OPT_STR, &opt_P, NULL) != argc) 2369 return (DCMD_USAGE); 2370 2371 if (opt_P != NULL) { 2372 if (strcmp("v4", opt_P) == 0) { 2373 ipversion = IPV4_VERSION; 2374 } else if (strcmp("v6", opt_P) == 0) { 2375 ipversion = IPV6_VERSION; 2376 } else { 2377 mdb_warn("invalid protocol '%s'\n", opt_P); 2378 return (DCMD_USAGE); 2379 } 2380 } 2381 2382 id.verbose = verbose; 2383 id.ipif_ipversion = ipversion; 2384 2385 if (flags & DCMD_ADDRSPEC) { 2386 if (mdb_vread(&ipif, sizeof (ipif_t), addr) == -1) { 2387 mdb_warn("failed to read ipif at %p\n", addr); 2388 return (DCMD_ERR); 2389 } 2390 ipif_header(verbose); 2391 if (mdb_vread(&id.ill, sizeof (ill_t), 2392 (uintptr_t)ipif.ipif_ill) == -1) { 2393 mdb_warn("failed to read ill at %p", ipif.ipif_ill); 2394 return (WALK_NEXT); 2395 } 2396 return (ipif_format(addr, &ipif, &id)); 2397 } else { 2398 ipif_header(verbose); 2399 if (mdb_walk("ipif", (mdb_walk_cb_t)ipif_cb, &id) == -1) { 2400 mdb_warn("failed to walk ipifs\n"); 2401 return (DCMD_ERR); 2402 } 2403 } 2404 return (DCMD_OK); 2405 } 2406 2407 static void 2408 ipif_help(void) 2409 { 2410 mdb_printf("Prints the following fields: ipif ptr, name, " 2411 "count, ill ptr, state flags and ipif flags.\n" 2412 "The count field is a sum of individual refcnts and is expanded " 2413 "with the -v option.\n" 2414 "The flags field shows the following:" 2415 "\n\tUNN -> UNNUMBERED, DHCP -> DHCPRUNNING, PRIV -> PRIVATE, " 2416 "\n\tNOXMT -> NOXMIT, NOLCL -> NOLOCAL, DEPR -> DEPRECATED, " 2417 "\n\tPREF -> PREFERRED, TEMP -> TEMPORARY, ACONF -> ADDRCONF, " 2418 "\n\tANY -> ANYCAST, NFAIL -> NOFAILOVER, " 2419 "\n\tADR -> ipif_addr_ready, MU -> ipif_multicast_up, " 2420 "\n\tWU -> ipif_was_up, WD -> ipif_was_dup, " 2421 "JA -> ipif_joined_allhosts.\n\n"); 2422 mdb_printf("Options:\n"); 2423 mdb_printf("\t-P v4 | v6" 2424 "\tfilter ipif structures on ills for the specified protocol\n"); 2425 } 2426 2427 static int 2428 conn_status_walk_fanout(uintptr_t addr, mdb_walk_state_t *wsp, 2429 const char *walkname) 2430 { 2431 if (mdb_pwalk(walkname, wsp->walk_callback, wsp->walk_cbdata, 2432 addr) == -1) { 2433 mdb_warn("couldn't walk '%s' at %p", walkname, addr); 2434 return (WALK_ERR); 2435 } 2436 return (WALK_NEXT); 2437 } 2438 2439 static int 2440 conn_status_walk_step(mdb_walk_state_t *wsp) 2441 { 2442 uintptr_t addr = wsp->walk_addr; 2443 2444 (void) conn_status_walk_fanout(addr, wsp, "udp_hash"); 2445 (void) conn_status_walk_fanout(addr, wsp, "conn_hash"); 2446 (void) conn_status_walk_fanout(addr, wsp, "bind_hash"); 2447 (void) conn_status_walk_fanout(addr, wsp, "proto_hash"); 2448 (void) conn_status_walk_fanout(addr, wsp, "proto_v6_hash"); 2449 return (WALK_NEXT); 2450 } 2451 2452 /* ARGSUSED */ 2453 static int 2454 conn_status_cb(uintptr_t addr, const void *walk_data, 2455 void *private) 2456 { 2457 netstack_t nss; 2458 char src_addrstr[INET6_ADDRSTRLEN]; 2459 char rem_addrstr[INET6_ADDRSTRLEN]; 2460 const ipcl_hash_walk_data_t *iw = walk_data; 2461 conn_t *conn = iw->conn; 2462 2463 if (mdb_vread(conn, sizeof (conn_t), addr) == -1) { 2464 mdb_warn("failed to read conn_t at %p", addr); 2465 return (WALK_ERR); 2466 } 2467 if (mdb_vread(&nss, sizeof (nss), 2468 (uintptr_t)conn->conn_netstack) == -1) { 2469 mdb_warn("failed to read netstack_t %p", 2470 conn->conn_netstack); 2471 return (WALK_ERR); 2472 } 2473 mdb_printf("%-?p %-?p %?d %?d\n", addr, conn->conn_wq, 2474 nss.netstack_stackid, conn->conn_zoneid); 2475 2476 if (conn->conn_af_isv6) { 2477 mdb_snprintf(src_addrstr, sizeof (rem_addrstr), "%N", 2478 &conn->conn_srcv6); 2479 mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%N", 2480 &conn->conn_remv6); 2481 } else { 2482 mdb_snprintf(src_addrstr, sizeof (src_addrstr), "%I", 2483 V4_PART_OF_V6((conn->conn_srcv6))); 2484 mdb_snprintf(rem_addrstr, sizeof (rem_addrstr), "%I", 2485 V4_PART_OF_V6((conn->conn_remv6))); 2486 } 2487 mdb_printf("%s:%-5d\n%s:%-5d\n", 2488 src_addrstr, conn->conn_lport, rem_addrstr, conn->conn_fport); 2489 return (WALK_NEXT); 2490 } 2491 2492 static void 2493 conn_header(void) 2494 { 2495 mdb_printf("%-?s %-?s %?s %?s\n%s\n%s\n", 2496 "ADDR", "WQ", "STACK", "ZONE", "SRC:PORT", "DEST:PORT"); 2497 mdb_printf("%<u>%80s%</u>\n", ""); 2498 } 2499 2500 /*ARGSUSED*/ 2501 static int 2502 conn_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2503 { 2504 conn_header(); 2505 if (flags & DCMD_ADDRSPEC) { 2506 (void) conn_status_cb(addr, NULL, NULL); 2507 } else { 2508 if (mdb_walk("conn_status", (mdb_walk_cb_t)conn_status_cb, 2509 NULL) == -1) { 2510 mdb_warn("failed to walk conn_fanout"); 2511 return (DCMD_ERR); 2512 } 2513 } 2514 return (DCMD_OK); 2515 } 2516 2517 static void 2518 conn_status_help(void) 2519 { 2520 mdb_printf("Prints conn_t structures from the following hash tables: " 2521 "\n\tips_ipcl_udp_fanout\n\tips_ipcl_bind_fanout" 2522 "\n\tips_ipcl_conn_fanout\n\tips_ipcl_proto_fanout" 2523 "\n\tips_ipcl_proto_fanout_v6\n"); 2524 } 2525 2526 static int 2527 srcid_walk_step(mdb_walk_state_t *wsp) 2528 { 2529 if (mdb_pwalk("srcid_list", wsp->walk_callback, wsp->walk_cbdata, 2530 wsp->walk_addr) == -1) { 2531 mdb_warn("can't walk 'srcid_list'"); 2532 return (WALK_ERR); 2533 } 2534 return (WALK_NEXT); 2535 } 2536 2537 /* ARGSUSED */ 2538 static int 2539 srcid_status_cb(uintptr_t addr, const void *walk_data, 2540 void *private) 2541 { 2542 srcid_map_t smp; 2543 2544 if (mdb_vread(&smp, sizeof (srcid_map_t), addr) == -1) { 2545 mdb_warn("failed to read srcid_map at %p", addr); 2546 return (WALK_ERR); 2547 } 2548 mdb_printf("%-?p %3d %4d %6d %N\n", 2549 addr, smp.sm_srcid, smp.sm_zoneid, smp.sm_refcnt, 2550 &smp.sm_addr); 2551 return (WALK_NEXT); 2552 } 2553 2554 static void 2555 srcid_header(void) 2556 { 2557 mdb_printf("%-?s %3s %4s %6s %s\n", 2558 "ADDR", "ID", "ZONE", "REFCNT", "IPADDR"); 2559 mdb_printf("%<u>%80s%</u>\n", ""); 2560 } 2561 2562 /*ARGSUSED*/ 2563 static int 2564 srcid_status(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 2565 { 2566 srcid_header(); 2567 if (flags & DCMD_ADDRSPEC) { 2568 (void) srcid_status_cb(addr, NULL, NULL); 2569 } else { 2570 if (mdb_walk("srcid", (mdb_walk_cb_t)srcid_status_cb, 2571 NULL) == -1) { 2572 mdb_warn("failed to walk srcid_map"); 2573 return (DCMD_ERR); 2574 } 2575 } 2576 return (DCMD_OK); 2577 } 2578 2579 static int 2580 ilb_stacks_walk_step(mdb_walk_state_t *wsp) 2581 { 2582 uintptr_t kaddr; 2583 netstack_t nss; 2584 2585 if (mdb_vread(&nss, sizeof (nss), wsp->walk_addr) == -1) { 2586 mdb_warn("can't read netstack at %p", wsp->walk_addr); 2587 return (WALK_ERR); 2588 } 2589 kaddr = (uintptr_t)nss.netstack_modules[NS_ILB]; 2590 2591 return (wsp->walk_callback(kaddr, wsp->walk_layer, wsp->walk_cbdata)); 2592 } 2593 2594 static int 2595 ilb_rules_walk_init(mdb_walk_state_t *wsp) 2596 { 2597 ilb_stack_t ilbs; 2598 2599 if (wsp->walk_addr == NULL) 2600 return (WALK_ERR); 2601 2602 if (mdb_vread(&ilbs, sizeof (ilbs), wsp->walk_addr) == -1) { 2603 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 2604 return (WALK_ERR); 2605 } 2606 if ((wsp->walk_addr = (uintptr_t)ilbs.ilbs_rule_head) != NULL) 2607 return (WALK_NEXT); 2608 else 2609 return (WALK_DONE); 2610 } 2611 2612 static int 2613 ilb_rules_walk_step(mdb_walk_state_t *wsp) 2614 { 2615 ilb_rule_t rule; 2616 int status; 2617 2618 if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) { 2619 mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr); 2620 return (WALK_ERR); 2621 } 2622 status = wsp->walk_callback(wsp->walk_addr, &rule, wsp->walk_cbdata); 2623 if (status != WALK_NEXT) 2624 return (status); 2625 if ((wsp->walk_addr = (uintptr_t)rule.ir_next) == NULL) 2626 return (WALK_DONE); 2627 else 2628 return (WALK_NEXT); 2629 } 2630 2631 static int 2632 ilb_servers_walk_init(mdb_walk_state_t *wsp) 2633 { 2634 ilb_rule_t rule; 2635 2636 if (wsp->walk_addr == NULL) 2637 return (WALK_ERR); 2638 2639 if (mdb_vread(&rule, sizeof (rule), wsp->walk_addr) == -1) { 2640 mdb_warn("failed to read ilb_rule_t at %p", wsp->walk_addr); 2641 return (WALK_ERR); 2642 } 2643 if ((wsp->walk_addr = (uintptr_t)rule.ir_servers) != NULL) 2644 return (WALK_NEXT); 2645 else 2646 return (WALK_DONE); 2647 } 2648 2649 static int 2650 ilb_servers_walk_step(mdb_walk_state_t *wsp) 2651 { 2652 ilb_server_t server; 2653 int status; 2654 2655 if (mdb_vread(&server, sizeof (server), wsp->walk_addr) == -1) { 2656 mdb_warn("failed to read ilb_server_t at %p", wsp->walk_addr); 2657 return (WALK_ERR); 2658 } 2659 status = wsp->walk_callback(wsp->walk_addr, &server, wsp->walk_cbdata); 2660 if (status != WALK_NEXT) 2661 return (status); 2662 if ((wsp->walk_addr = (uintptr_t)server.iser_next) == NULL) 2663 return (WALK_DONE); 2664 else 2665 return (WALK_NEXT); 2666 } 2667 2668 /* 2669 * Helper structure for ilb_nat_src walker. It stores the current index of the 2670 * nat src table. 2671 */ 2672 typedef struct { 2673 ilb_stack_t ilbs; 2674 int idx; 2675 } ilb_walk_t; 2676 2677 /* Copy from list.c */ 2678 #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) 2679 2680 static int 2681 ilb_nat_src_walk_init(mdb_walk_state_t *wsp) 2682 { 2683 int i; 2684 ilb_walk_t *ns_walk; 2685 ilb_nat_src_entry_t *entry = NULL; 2686 2687 if (wsp->walk_addr == NULL) 2688 return (WALK_ERR); 2689 2690 ns_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP); 2691 if (mdb_vread(&ns_walk->ilbs, sizeof (ns_walk->ilbs), 2692 wsp->walk_addr) == -1) { 2693 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 2694 mdb_free(ns_walk, sizeof (ilb_walk_t)); 2695 return (WALK_ERR); 2696 } 2697 2698 if (ns_walk->ilbs.ilbs_nat_src == NULL) { 2699 mdb_free(ns_walk, sizeof (ilb_walk_t)); 2700 return (WALK_DONE); 2701 } 2702 2703 wsp->walk_data = ns_walk; 2704 for (i = 0; i < ns_walk->ilbs.ilbs_nat_src_hash_size; i++) { 2705 list_t head; 2706 char *khead; 2707 2708 /* Read in the nsh_head in the i-th element of the array. */ 2709 khead = (char *)ns_walk->ilbs.ilbs_nat_src + i * 2710 sizeof (ilb_nat_src_hash_t); 2711 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 2712 mdb_warn("failed to read ilbs_nat_src at %p\n", khead); 2713 return (WALK_ERR); 2714 } 2715 2716 /* 2717 * Note that list_next points to a kernel address and we need 2718 * to compare list_next with the kernel address of the list 2719 * head. So we need to calculate the address manually. 2720 */ 2721 if ((char *)head.list_head.list_next != khead + 2722 offsetof(list_t, list_head)) { 2723 entry = list_object(&head, head.list_head.list_next); 2724 break; 2725 } 2726 } 2727 2728 if (entry == NULL) 2729 return (WALK_DONE); 2730 2731 wsp->walk_addr = (uintptr_t)entry; 2732 ns_walk->idx = i; 2733 return (WALK_NEXT); 2734 } 2735 2736 static int 2737 ilb_nat_src_walk_step(mdb_walk_state_t *wsp) 2738 { 2739 int status; 2740 ilb_nat_src_entry_t entry, *next_entry; 2741 ilb_walk_t *ns_walk; 2742 ilb_stack_t *ilbs; 2743 list_t head; 2744 char *khead; 2745 int i; 2746 2747 if (mdb_vread(&entry, sizeof (ilb_nat_src_entry_t), 2748 wsp->walk_addr) == -1) { 2749 mdb_warn("failed to read ilb_nat_src_entry_t at %p", 2750 wsp->walk_addr); 2751 return (WALK_ERR); 2752 } 2753 status = wsp->walk_callback(wsp->walk_addr, &entry, wsp->walk_cbdata); 2754 if (status != WALK_NEXT) 2755 return (status); 2756 2757 ns_walk = (ilb_walk_t *)wsp->walk_data; 2758 ilbs = &ns_walk->ilbs; 2759 i = ns_walk->idx; 2760 2761 /* Read in the nsh_head in the i-th element of the array. */ 2762 khead = (char *)ilbs->ilbs_nat_src + i * sizeof (ilb_nat_src_hash_t); 2763 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 2764 mdb_warn("failed to read ilbs_nat_src at %p\n", khead); 2765 return (WALK_ERR); 2766 } 2767 2768 /* 2769 * Check if there is still entry in the current list. 2770 * 2771 * Note that list_next points to a kernel address and we need to 2772 * compare list_next with the kernel address of the list head. 2773 * So we need to calculate the address manually. 2774 */ 2775 if ((char *)entry.nse_link.list_next != khead + offsetof(list_t, 2776 list_head)) { 2777 wsp->walk_addr = (uintptr_t)list_object(&head, 2778 entry.nse_link.list_next); 2779 return (WALK_NEXT); 2780 } 2781 2782 /* Start with the next bucket in the array. */ 2783 next_entry = NULL; 2784 for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) { 2785 khead = (char *)ilbs->ilbs_nat_src + i * 2786 sizeof (ilb_nat_src_hash_t); 2787 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 2788 mdb_warn("failed to read ilbs_nat_src at %p\n", khead); 2789 return (WALK_ERR); 2790 } 2791 2792 if ((char *)head.list_head.list_next != khead + 2793 offsetof(list_t, list_head)) { 2794 next_entry = list_object(&head, 2795 head.list_head.list_next); 2796 break; 2797 } 2798 } 2799 2800 if (next_entry == NULL) 2801 return (WALK_DONE); 2802 2803 wsp->walk_addr = (uintptr_t)next_entry; 2804 ns_walk->idx = i; 2805 return (WALK_NEXT); 2806 } 2807 2808 static void 2809 ilb_common_walk_fini(mdb_walk_state_t *wsp) 2810 { 2811 ilb_walk_t *walk; 2812 2813 walk = (ilb_walk_t *)wsp->walk_data; 2814 if (walk == NULL) 2815 return; 2816 mdb_free(walk, sizeof (ilb_walk_t *)); 2817 } 2818 2819 static int 2820 ilb_conn_walk_init(mdb_walk_state_t *wsp) 2821 { 2822 int i; 2823 ilb_walk_t *conn_walk; 2824 ilb_conn_hash_t head; 2825 2826 if (wsp->walk_addr == NULL) 2827 return (WALK_ERR); 2828 2829 conn_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP); 2830 if (mdb_vread(&conn_walk->ilbs, sizeof (conn_walk->ilbs), 2831 wsp->walk_addr) == -1) { 2832 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 2833 mdb_free(conn_walk, sizeof (ilb_walk_t)); 2834 return (WALK_ERR); 2835 } 2836 2837 if (conn_walk->ilbs.ilbs_c2s_conn_hash == NULL) { 2838 mdb_free(conn_walk, sizeof (ilb_walk_t)); 2839 return (WALK_DONE); 2840 } 2841 2842 wsp->walk_data = conn_walk; 2843 for (i = 0; i < conn_walk->ilbs.ilbs_conn_hash_size; i++) { 2844 char *khead; 2845 2846 /* Read in the nsh_head in the i-th element of the array. */ 2847 khead = (char *)conn_walk->ilbs.ilbs_c2s_conn_hash + i * 2848 sizeof (ilb_conn_hash_t); 2849 if (mdb_vread(&head, sizeof (ilb_conn_hash_t), 2850 (uintptr_t)khead) == -1) { 2851 mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n", 2852 khead); 2853 return (WALK_ERR); 2854 } 2855 2856 if (head.ilb_connp != NULL) 2857 break; 2858 } 2859 2860 if (head.ilb_connp == NULL) 2861 return (WALK_DONE); 2862 2863 wsp->walk_addr = (uintptr_t)head.ilb_connp; 2864 conn_walk->idx = i; 2865 return (WALK_NEXT); 2866 } 2867 2868 static int 2869 ilb_conn_walk_step(mdb_walk_state_t *wsp) 2870 { 2871 int status; 2872 ilb_conn_t conn; 2873 ilb_walk_t *conn_walk; 2874 ilb_stack_t *ilbs; 2875 ilb_conn_hash_t head; 2876 char *khead; 2877 int i; 2878 2879 if (mdb_vread(&conn, sizeof (ilb_conn_t), wsp->walk_addr) == -1) { 2880 mdb_warn("failed to read ilb_conn_t at %p", wsp->walk_addr); 2881 return (WALK_ERR); 2882 } 2883 2884 status = wsp->walk_callback(wsp->walk_addr, &conn, wsp->walk_cbdata); 2885 if (status != WALK_NEXT) 2886 return (status); 2887 2888 conn_walk = (ilb_walk_t *)wsp->walk_data; 2889 ilbs = &conn_walk->ilbs; 2890 i = conn_walk->idx; 2891 2892 /* Check if there is still entry in the current list. */ 2893 if (conn.conn_c2s_next != NULL) { 2894 wsp->walk_addr = (uintptr_t)conn.conn_c2s_next; 2895 return (WALK_NEXT); 2896 } 2897 2898 /* Start with the next bucket in the array. */ 2899 for (i++; i < ilbs->ilbs_conn_hash_size; i++) { 2900 khead = (char *)ilbs->ilbs_c2s_conn_hash + i * 2901 sizeof (ilb_conn_hash_t); 2902 if (mdb_vread(&head, sizeof (ilb_conn_hash_t), 2903 (uintptr_t)khead) == -1) { 2904 mdb_warn("failed to read ilbs_c2s_conn_hash at %p\n", 2905 khead); 2906 return (WALK_ERR); 2907 } 2908 2909 if (head.ilb_connp != NULL) 2910 break; 2911 } 2912 2913 if (head.ilb_connp == NULL) 2914 return (WALK_DONE); 2915 2916 wsp->walk_addr = (uintptr_t)head.ilb_connp; 2917 conn_walk->idx = i; 2918 return (WALK_NEXT); 2919 } 2920 2921 static int 2922 ilb_sticky_walk_init(mdb_walk_state_t *wsp) 2923 { 2924 int i; 2925 ilb_walk_t *sticky_walk; 2926 ilb_sticky_t *st = NULL; 2927 2928 if (wsp->walk_addr == NULL) 2929 return (WALK_ERR); 2930 2931 sticky_walk = mdb_alloc(sizeof (ilb_walk_t), UM_SLEEP); 2932 if (mdb_vread(&sticky_walk->ilbs, sizeof (sticky_walk->ilbs), 2933 wsp->walk_addr) == -1) { 2934 mdb_warn("failed to read ilb_stack_t at %p", wsp->walk_addr); 2935 mdb_free(sticky_walk, sizeof (ilb_walk_t)); 2936 return (WALK_ERR); 2937 } 2938 2939 if (sticky_walk->ilbs.ilbs_sticky_hash == NULL) { 2940 mdb_free(sticky_walk, sizeof (ilb_walk_t)); 2941 return (WALK_DONE); 2942 } 2943 2944 wsp->walk_data = sticky_walk; 2945 for (i = 0; i < sticky_walk->ilbs.ilbs_sticky_hash_size; i++) { 2946 list_t head; 2947 char *khead; 2948 2949 /* Read in the nsh_head in the i-th element of the array. */ 2950 khead = (char *)sticky_walk->ilbs.ilbs_sticky_hash + i * 2951 sizeof (ilb_sticky_hash_t); 2952 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 2953 mdb_warn("failed to read ilbs_sticky_hash at %p\n", 2954 khead); 2955 return (WALK_ERR); 2956 } 2957 2958 /* 2959 * Note that list_next points to a kernel address and we need 2960 * to compare list_next with the kernel address of the list 2961 * head. So we need to calculate the address manually. 2962 */ 2963 if ((char *)head.list_head.list_next != khead + 2964 offsetof(list_t, list_head)) { 2965 st = list_object(&head, head.list_head.list_next); 2966 break; 2967 } 2968 } 2969 2970 if (st == NULL) 2971 return (WALK_DONE); 2972 2973 wsp->walk_addr = (uintptr_t)st; 2974 sticky_walk->idx = i; 2975 return (WALK_NEXT); 2976 } 2977 2978 static int 2979 ilb_sticky_walk_step(mdb_walk_state_t *wsp) 2980 { 2981 int status; 2982 ilb_sticky_t st, *st_next; 2983 ilb_walk_t *sticky_walk; 2984 ilb_stack_t *ilbs; 2985 list_t head; 2986 char *khead; 2987 int i; 2988 2989 if (mdb_vread(&st, sizeof (ilb_sticky_t), wsp->walk_addr) == -1) { 2990 mdb_warn("failed to read ilb_sticky_t at %p", wsp->walk_addr); 2991 return (WALK_ERR); 2992 } 2993 2994 status = wsp->walk_callback(wsp->walk_addr, &st, wsp->walk_cbdata); 2995 if (status != WALK_NEXT) 2996 return (status); 2997 2998 sticky_walk = (ilb_walk_t *)wsp->walk_data; 2999 ilbs = &sticky_walk->ilbs; 3000 i = sticky_walk->idx; 3001 3002 /* Read in the nsh_head in the i-th element of the array. */ 3003 khead = (char *)ilbs->ilbs_sticky_hash + i * sizeof (ilb_sticky_hash_t); 3004 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3005 mdb_warn("failed to read ilbs_sticky_hash at %p\n", khead); 3006 return (WALK_ERR); 3007 } 3008 3009 /* 3010 * Check if there is still entry in the current list. 3011 * 3012 * Note that list_next points to a kernel address and we need to 3013 * compare list_next with the kernel address of the list head. 3014 * So we need to calculate the address manually. 3015 */ 3016 if ((char *)st.list.list_next != khead + offsetof(list_t, 3017 list_head)) { 3018 wsp->walk_addr = (uintptr_t)list_object(&head, 3019 st.list.list_next); 3020 return (WALK_NEXT); 3021 } 3022 3023 /* Start with the next bucket in the array. */ 3024 st_next = NULL; 3025 for (i++; i < ilbs->ilbs_nat_src_hash_size; i++) { 3026 khead = (char *)ilbs->ilbs_sticky_hash + i * 3027 sizeof (ilb_sticky_hash_t); 3028 if (mdb_vread(&head, sizeof (list_t), (uintptr_t)khead) == -1) { 3029 mdb_warn("failed to read ilbs_sticky_hash at %p\n", 3030 khead); 3031 return (WALK_ERR); 3032 } 3033 3034 if ((char *)head.list_head.list_next != khead + 3035 offsetof(list_t, list_head)) { 3036 st_next = list_object(&head, 3037 head.list_head.list_next); 3038 break; 3039 } 3040 } 3041 3042 if (st_next == NULL) 3043 return (WALK_DONE); 3044 3045 wsp->walk_addr = (uintptr_t)st_next; 3046 sticky_walk->idx = i; 3047 return (WALK_NEXT); 3048 } 3049