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