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