1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <mdb/mdb_modapi.h>
29 #include <mdb/mdb_ks.h>
30 #include <mdb/mdb_ctf.h>
31 #include <sys/types.h>
32 #include <sys/netstack.h>
33
34 int
netstack_walk_init(mdb_walk_state_t * wsp)35 netstack_walk_init(mdb_walk_state_t *wsp)
36 {
37 GElf_Sym sym;
38 uintptr_t addr;
39
40 if (mdb_lookup_by_name("netstack_head", &sym) == -1) {
41 mdb_warn("couldn't find netstack_head");
42 return (WALK_ERR);
43 }
44 addr = (uintptr_t)sym.st_value;
45
46 if (mdb_vread(&wsp->walk_addr, sizeof (wsp->walk_addr), addr) == -1) {
47 mdb_warn("failed to read address of initial netstack "
48 "at %p", addr);
49 return (WALK_ERR);
50 }
51 return (WALK_NEXT);
52 }
53
54 int
netstack_walk_step(mdb_walk_state_t * wsp)55 netstack_walk_step(mdb_walk_state_t *wsp)
56 {
57 int status;
58 netstack_t nss;
59
60 if (wsp->walk_addr == NULL)
61 return (WALK_DONE);
62
63 if (mdb_vread(&nss, sizeof (netstack_t), wsp->walk_addr) == -1) {
64 mdb_warn("failed to read netstack at %p", wsp->walk_addr);
65 return (WALK_ERR);
66 }
67
68 status = wsp->walk_callback(wsp->walk_addr, &nss,
69 wsp->walk_cbdata);
70
71 if (status != WALK_NEXT)
72 return (status);
73
74 wsp->walk_addr = (uintptr_t)nss.netstack_next;
75 return (status);
76 }
77
78 /*ARGSUSED*/
79 int
netstack(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)80 netstack(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
81 {
82 netstack_t nss;
83 uint_t quiet = FALSE;
84 uint_t verbose = FALSE;
85
86 if (!(flags & DCMD_ADDRSPEC)) {
87 if (mdb_walk_dcmd("genunix`netstack", "genunix`netstack",
88 argc, argv) == -1) {
89 mdb_warn("failed to walk netstack");
90 return (DCMD_ERR);
91 }
92 return (DCMD_OK);
93 }
94 if (mdb_getopts(argc, argv,
95 'v', MDB_OPT_SETBITS, TRUE, &verbose,
96 'q', MDB_OPT_SETBITS, TRUE, &quiet,
97 NULL) != argc)
98 return (DCMD_USAGE);
99
100 if (DCMD_HDRSPEC(flags) && !quiet) {
101 mdb_printf("%?s %-7s %6s\n",
102 "ADDR", "STACKID", "FLAGS");
103 }
104
105 if (mdb_vread(&nss, sizeof (nss), addr) == -1) {
106 mdb_warn("couldn't read netstack at %p", addr);
107 return (DCMD_ERR);
108 }
109
110 /*
111 * Options are specified for filtering, so If any option is specified on
112 * the command line, just print address and exit.
113 */
114 if (quiet) {
115 mdb_printf("%0?p\n", addr);
116 return (DCMD_OK);
117 }
118
119 mdb_printf("%0?p %6d %06x\n",
120 addr, nss.netstack_stackid, nss.netstack_flags);
121
122 return (DCMD_OK);
123 }
124