| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2006-2009 University of Zagreb |
| 5 | * Copyright (c) 2006-2009 FreeBSD Foundation |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * This software was developed by the University of Zagreb and the |
| 9 | * FreeBSD Foundation under sponsorship by the Stichting NLnet and the |
| 10 | * FreeBSD Foundation. |
| 11 | * |
| 12 | * Copyright (c) 2009 Jeffrey Roberson <jeff@freebsd.org> |
| 13 | * Copyright (c) 2009 Robert N. M. Watson |
| 14 | * All rights reserved. |
| 15 | * |
| 16 | * Redistribution and use in source and binary forms, with or without |
| 17 | * modification, are permitted provided that the following conditions |
| 18 | * are met: |
| 19 | * 1. Redistributions of source code must retain the above copyright |
| 20 | * notice, this list of conditions and the following disclaimer. |
| 21 | * 2. Redistributions in binary form must reproduce the above copyright |
| 22 | * notice, this list of conditions and the following disclaimer in the |
| 23 | * documentation and/or other materials provided with the distribution. |
| 24 | * |
| 25 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 35 | * SUCH DAMAGE. |
| 36 | */ |
| 37 | |
| 38 | /*- |
| 39 | * This header file defines several sets of interfaces supporting virtualized |
| 40 | * network stacks: |
| 41 | * |
| 42 | * - Definition of 'struct vnet' and functions and macros to allocate/free/ |
| 43 | * manipulate it. |
| 44 | * |
| 45 | * - A virtual network stack memory allocator, which provides support for |
| 46 | * virtualized global variables via a special linker set, set_vnet. |
| 47 | * |
| 48 | * - Virtualized sysinits/sysuninits, which allow constructors and |
| 49 | * destructors to be run for each network stack subsystem as virtual |
| 50 | * instances are created and destroyed. |
| 51 | * |
| 52 | * If VIMAGE isn't compiled into the kernel, virtualized global variables |
| 53 | * compile to normal global variables, and virtualized sysinits to regular |
| 54 | * sysinits. |
| 55 | */ |
| 56 | |
| 57 | #ifndef _NET_VNET_H_ |
| 58 | #define	_NET_VNET_H_ |
| 59 | |
| 60 | /* |
| 61 | * struct vnet describes a virtualized network stack, and is primarily a |
| 62 | * pointer to storage for virtualized global variables. Expose to userspace |
| 63 | * as required for libkvm. |
| 64 | */ |
| 65 | #if defined(_KERNEL) || defined(_WANT_VNET) |
| 66 | #include <machine/param.h>	/* for CACHE_LINE_SIZE */ |
| 67 | #include <sys/queue.h> |
| 68 | |
| 69 | struct vnet { |
| 70 | 	LIST_ENTRY(vnet)	 vnet_le;	/* all vnets list */ |
| 71 | 	u_int			 vnet_magic_n; |
| 72 | 	u_int			 vnet_ifcnt; |
| 73 | 	u_int			 vnet_sockcnt; |
| 74 | 	u_int			 vnet_state;	/* SI_SUB_* */ |
| 75 | 	void			*vnet_data_mem; |
| 76 | 	uintptr_t		 vnet_data_base; |
| 77 | 	bool			 vnet_shutdown;	/* Shutdown in progress. */ |
| 78 | } __aligned(CACHE_LINE_SIZE); |
| 79 | #define	VNET_MAGIC_N	0x5e4a6f28 |
| 80 | |
| 81 | /* |
| 82 | * These two virtual network stack allocator definitions are also required |
| 83 | * for libkvm so that it can evaluate virtualized global variables. |
| 84 | */ |
| 85 | #define	VNET_SETNAME		"set_vnet" |
| 86 | #define	VNET_SYMPREFIX		"vnet_entry_" |
| 87 | #endif |
| 88 | |
| 89 | #ifdef _KERNEL |
| 90 | |
| 91 | #define	VNET_PCPUSTAT_DECLARE(type, name)	\ |
| 92 | VNET_DECLARE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)]) |
| 93 | |
| 94 | #define	VNET_PCPUSTAT_DEFINE(type, name)	\ |
| 95 | VNET_DEFINE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)]) |
| 96 | #define	VNET_PCPUSTAT_DEFINE_STATIC(type, name)	\ |
| 97 | VNET_DEFINE_STATIC(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)]) |
| 98 | |
| 99 | #define	VNET_PCPUSTAT_ALLOC(name, wait)	\ |
| 100 | COUNTER_ARRAY_ALLOC(VNET(name), \ |
| 101 | 	sizeof(VNET(name)) / sizeof(counter_u64_t), (wait)) |
| 102 | |
| 103 | #define	VNET_PCPUSTAT_FREE(name)	\ |
| 104 | COUNTER_ARRAY_FREE(VNET(name), sizeof(VNET(name)) / sizeof(counter_u64_t)) |
| 105 | |
| 106 | #define	VNET_PCPUSTAT_ADD(type, name, f, v)	\ |
| 107 | counter_u64_add(VNET(name)[offsetof(type, f) / sizeof(uint64_t)], (v)) |
| 108 | |
| 109 | #define	VNET_PCPUSTAT_FETCH(type, name, f)	\ |
| 110 | counter_u64_fetch(VNET(name)[offsetof(type, f) / sizeof(uint64_t)]) |
| 111 | |
| 112 | #define	VNET_PCPUSTAT_SYSINIT(name)	\ |
| 113 | static void				\ |
| 114 | vnet_##name##_init(const void *unused)	\ |
| 115 | {					\ |
| 116 | 	VNET_PCPUSTAT_ALLOC(name, M_WAITOK);	\ |
| 117 | }					\ |
| 118 | VNET_SYSINIT(vnet_ ## name ## _init, SI_SUB_INIT_IF,			\ |
| 119 | SI_ORDER_FIRST, vnet_ ## name ## _init, NULL) |
| 120 | |
| 121 | #define	VNET_PCPUSTAT_SYSUNINIT(name)					\ |
| 122 | static void								\ |
| 123 | vnet_##name##_uninit(const void *unused)				\ |
| 124 | {									\ |
| 125 | 	VNET_PCPUSTAT_FREE(name);					\ |
| 126 | }									\ |
| 127 | VNET_SYSUNINIT(vnet_ ## name ## _uninit, SI_SUB_INIT_IF,		\ |
| 128 | SI_ORDER_FIRST, vnet_ ## name ## _uninit, NULL) |
| 129 | |
| 130 | #ifdef SYSCTL_OID |
| 131 | #define	SYSCTL_VNET_PCPUSTAT(parent, nbr, name, type, array, desc)	\ |
| 132 | static int								\ |
| 133 | array##_sysctl(SYSCTL_HANDLER_ARGS)					\ |
| 134 | {									\ |
| 135 | 	type s;								\ |
| 136 | 	CTASSERT((sizeof(type) / sizeof(uint64_t)) ==			\ |
| 137 | 	 (sizeof(VNET(array)) / sizeof(counter_u64_t)));		\ |
| 138 | 	COUNTER_ARRAY_COPY(VNET(array), &s, sizeof(type) / sizeof(uint64_t));\ |
| 139 | 	if (req->newptr)						\ |
| 140 | 		COUNTER_ARRAY_ZERO(VNET(array),				\ |
| 141 | 		 sizeof(type) / sizeof(uint64_t));			\ |
| 142 | 	return (SYSCTL_OUT(req, &s, sizeof(type)));			\ |
| 143 | }									\ |
| 144 | SYSCTL_PROC(parent, nbr, name,						\ |
| 145 | CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_NEEDGIANT,	\ |
| 146 | NULL, 0, array ## _sysctl, "I", desc) |
| 147 | #endif /* SYSCTL_OID */ |
| 148 | |
| 149 | #ifdef VIMAGE |
| 150 | #include <sys/lock.h> |
| 151 | #include <sys/proc.h>			/* for struct thread */ |
| 152 | #include <sys/rwlock.h> |
| 153 | #include <sys/sx.h> |
| 154 | |
| 155 | /* |
| 156 | * Location of the kernel's 'set_vnet' linker set. |
| 157 | */ |
| 158 | extern uintptr_t	*__start_set_vnet; |
| 159 | __GLOBL(__start_set_vnet); |
| 160 | extern uintptr_t	*__stop_set_vnet; |
| 161 | __GLOBL(__stop_set_vnet); |
| 162 | |
| 163 | #define	VNET_START	(uintptr_t)&__start_set_vnet |
| 164 | #define	VNET_STOP	(uintptr_t)&__stop_set_vnet |
| 165 | |
| 166 | /* |
| 167 | * Functions to allocate and destroy virtual network stacks. |
| 168 | */ |
| 169 | struct vnet *vnet_alloc(void); |
| 170 | void	vnet_destroy(struct vnet *vnet); |
| 171 | |
| 172 | /* |
| 173 | * The current virtual network stack -- we may wish to move this to struct |
| 174 | * pcpu in the future. |
| 175 | */ |
| 176 | #define	curvnet	curthread->td_vnet |
| 177 | |
| 178 | /* |
| 179 | * Various macros -- get and set the current network stack, but also |
| 180 | * assertions. |
| 181 | */ |
| 182 | #if defined(INVARIANTS) || defined(VNET_DEBUG) |
| 183 | #define	VNET_ASSERT(exp, msg)	do {					\ |
| 184 | 	if (!(exp))							\ |
| 185 | 		panic msg;						\ |
| 186 | } while (0) |
| 187 | #else |
| 188 | #define	VNET_ASSERT(exp, msg)	do {					\ |
| 189 | } while (0) |
| 190 | #endif |
| 191 | |
| 192 | #ifdef VNET_DEBUG |
| 193 | void vnet_log_recursion(struct vnet *, const char *, int); |
| 194 | |
| 195 | #define	CURVNET_SET_QUIET(arg)						\ |
| 196 | 	VNET_ASSERT((arg) != NULL && (arg)->vnet_magic_n == VNET_MAGIC_N, \ |
| 197 | 	 ("CURVNET_SET at %s:%d %s() curvnet=%p vnet=%p",		\ |
| 198 | 	 __FILE__, __LINE__, __func__, curvnet, (arg)));		\ |
| 199 | 	struct vnet *saved_vnet = curvnet;				\ |
| 200 | 	const char *saved_vnet_lpush = curthread->td_vnet_lpush;	\ |
| 201 | 	curvnet = arg;							\ |
| 202 | 	curthread->td_vnet_lpush = __func__; |
| 203 | |
| 204 | #define	CURVNET_SET_VERBOSE(arg)					\ |
| 205 | 	CURVNET_SET_QUIET(arg)						\ |
| 206 | 	if (saved_vnet)							\ |
| 207 | 		vnet_log_recursion(saved_vnet, saved_vnet_lpush, __LINE__); |
| 208 | |
| 209 | #define	CURVNET_SET(arg)	CURVNET_SET_VERBOSE(arg) |
| 210 | |
| 211 | #define	CURVNET_RESTORE()						\ |
| 212 | 	VNET_ASSERT(curvnet != NULL && (saved_vnet == NULL ||		\ |
| 213 | 	 saved_vnet->vnet_magic_n == VNET_MAGIC_N),			\ |
| 214 | 	 ("CURVNET_RESTORE at %s:%d %s() curvnet=%p saved_vnet=%p",	\ |
| 215 | 	 __FILE__, __LINE__, __func__, curvnet, saved_vnet));	\ |
| 216 | 	curvnet = saved_vnet;						\ |
| 217 | 	curthread->td_vnet_lpush = saved_vnet_lpush; |
| 218 | #else /* !VNET_DEBUG */ |
| 219 | |
| 220 | #define	CURVNET_SET_QUIET(arg)						\ |
| 221 | 	VNET_ASSERT((arg) != NULL && (arg)->vnet_magic_n == VNET_MAGIC_N, \ |
| 222 | 	 ("CURVNET_SET at %s:%d %s() curvnet=%p vnet=%p",		\ |
| 223 | 	 __FILE__, __LINE__, __func__, curvnet, (arg)));		\ |
| 224 | 	struct vnet *saved_vnet = curvnet;				\ |
| 225 | 	curvnet = arg;	 |
| 226 | |
| 227 | #define	CURVNET_SET_VERBOSE(arg)					\ |
| 228 | 	CURVNET_SET_QUIET(arg) |
| 229 | |
| 230 | #define	CURVNET_SET(arg)	CURVNET_SET_VERBOSE(arg) |
| 231 | |
| 232 | #define	CURVNET_RESTORE()						\ |
| 233 | 	VNET_ASSERT(curvnet != NULL && (saved_vnet == NULL ||		\ |
| 234 | 	 saved_vnet->vnet_magic_n == VNET_MAGIC_N),			\ |
| 235 | 	 ("CURVNET_RESTORE at %s:%d %s() curvnet=%p saved_vnet=%p",	\ |
| 236 | 	 __FILE__, __LINE__, __func__, curvnet, saved_vnet));	\ |
| 237 | 	curvnet = saved_vnet; |
| 238 | #endif /* VNET_DEBUG */ |
| 239 | |
| 240 | #define	CURVNET_ASSERT_SET()						\ |
| 241 | 	VNET_ASSERT(curvnet != NULL, ("vnet is not set at %s:%d %s()", \ |
| 242 | 	 __FILE__, __LINE__, __func__)) |
| 243 | |
| 244 | extern struct vnet *vnet0; |
| 245 | #define	IS_DEFAULT_VNET(arg)	((arg) == vnet0) |
| 246 | |
| 247 | #define	CRED_TO_VNET(cr)	(cr)->cr_prison->pr_vnet |
| 248 | #define	TD_TO_VNET(td)		CRED_TO_VNET((td)->td_ucred) |
| 249 | #define	P_TO_VNET(p)		CRED_TO_VNET((p)->p_ucred) |
| 250 | |
| 251 | /* |
| 252 | * Global linked list of all virtual network stacks, along with read locks to |
| 253 | * access it. If a caller may sleep while accessing the list, it must use |
| 254 | * the sleepable lock macros. |
| 255 | */ |
| 256 | LIST_HEAD(vnet_list_head, vnet); |
| 257 | extern struct vnet_list_head vnet_head; |
| 258 | extern struct rwlock vnet_rwlock; |
| 259 | extern struct sx vnet_sxlock; |
| 260 | |
| 261 | #define	VNET_LIST_RLOCK()		sx_slock(&vnet_sxlock) |
| 262 | #define	VNET_LIST_RLOCK_NOSLEEP()	rw_rlock(&vnet_rwlock) |
| 263 | #define	VNET_LIST_RUNLOCK()		sx_sunlock(&vnet_sxlock) |
| 264 | #define	VNET_LIST_RUNLOCK_NOSLEEP()	rw_runlock(&vnet_rwlock) |
| 265 | |
| 266 | /* |
| 267 | * Iteration macros to walk the global list of virtual network stacks. |
| 268 | */ |
| 269 | #define	VNET_ITERATOR_DECL(arg)	struct vnet *arg |
| 270 | #define	VNET_FOREACH(arg)	LIST_FOREACH((arg), &vnet_head, vnet_le) |
| 271 | |
| 272 | /* |
| 273 | * Virtual network stack memory allocator, which allows global variables to |
| 274 | * be automatically instantiated for each network stack instance. |
| 275 | */ |
| 276 | #define	VNET_NAME(n)		vnet_entry_##n |
| 277 | #define	VNET_DECLARE(t, n)	extern t VNET_NAME(n) |
| 278 | /* struct _hack is to stop this from being used with static data */ |
| 279 | #define	VNET_DEFINE(t, n)	\ |
| 280 | struct _hack; t VNET_NAME(n) __section(VNET_SETNAME) __used |
| 281 | #if defined(KLD_MODULE) && (defined(__aarch64__) || defined(__riscv) \ |
| 282 | 		|| defined(__powerpc64__) || defined(__i386__)) |
| 283 | /* |
| 284 | * As with DPCPU_DEFINE_STATIC we are unable to mark this data as static |
| 285 | * in modules on some architectures. |
| 286 | */ |
| 287 | #define	VNET_DEFINE_STATIC(t, n) \ |
| 288 | t VNET_NAME(n) __section(VNET_SETNAME) __used |
| 289 | #else |
| 290 | #define	VNET_DEFINE_STATIC(t, n) \ |
| 291 | static t VNET_NAME(n) __section(VNET_SETNAME) __used |
| 292 | #endif |
| 293 | #define	_VNET_PTR(b, n)		(__typeof(VNET_NAME(n))*)		\ |
| 294 | 				 ((b) + (uintptr_t)&VNET_NAME(n)) |
| 295 | |
| 296 | #define	_VNET(b, n)		(*_VNET_PTR(b, n)) |
| 297 | |
| 298 | /* |
| 299 | * Virtualized global variable accessor macros. |
| 300 | */ |
| 301 | #define	VNET_VNET_PTR(vnet, n)		_VNET_PTR((vnet)->vnet_data_base, n) |
| 302 | #define	VNET_VNET(vnet, n)		(*VNET_VNET_PTR((vnet), n)) |
| 303 | |
| 304 | #define	VNET_PTR(n)		VNET_VNET_PTR(curvnet, n) |
| 305 | #define	VNET(n)			VNET_VNET(curvnet, n) |
| 306 | |
| 307 | /* |
| 308 | * Virtual network stack allocator interfaces from the kernel linker. |
| 309 | */ |
| 310 | void	*vnet_data_alloc(int size); |
| 311 | void	 vnet_data_copy(void *start, int size); |
| 312 | void	 vnet_data_free(void *start_arg, int size); |
| 313 | |
| 314 | /* |
| 315 | * Interfaces to manipulate the initial values of virtualized global variables. |
| 316 | */ |
| 317 | void vnet_save_init(void *, size_t); |
| 318 | void vnet_restore_init(void *, size_t); |
| 319 | |
| 320 | /* |
| 321 | * Virtual sysinit mechanism, allowing network stack components to declare |
| 322 | * startup and shutdown methods to be run when virtual network stack |
| 323 | * instances are created and destroyed. |
| 324 | */ |
| 325 | #include <sys/kernel.h> |
| 326 | |
| 327 | /* |
| 328 | * SYSINIT/SYSUNINIT variants that provide per-vnet constructors and |
| 329 | * destructors. |
| 330 | */ |
| 331 | struct vnet_sysinit { |
| 332 | 	enum sysinit_sub_id	subsystem; |
| 333 | 	enum sysinit_elem_order	order; |
| 334 | 	sysinit_cfunc_t		func; |
| 335 | 	const void		*arg; |
| 336 | 	TAILQ_ENTRY(vnet_sysinit) link; |
| 337 | }; |
| 338 | |
| 339 | #define	VNET_SYSINIT(ident, subsystem, order, func, arg)		\ |
| 340 | 	CTASSERT((subsystem) > SI_SUB_VNET &&				\ |
| 341 | 	 (subsystem) <= SI_SUB_VNET_DONE);				\ |
| 342 | 	static struct vnet_sysinit ident ## _vnet_init = {		\ |
| 343 | 		subsystem,						\ |
| 344 | 		order,							\ |
| 345 | 		(sysinit_cfunc_t)(sysinit_nfunc_t)func,			\ |
| 346 | 		(arg)							\ |
| 347 | 	};								\ |
| 348 | 	SYSINIT(vnet_init_ ## ident, subsystem, order,			\ |
| 349 | 	 vnet_register_sysinit, &ident ## _vnet_init);		\ |
| 350 | 	SYSUNINIT(vnet_init_ ## ident, subsystem, order,		\ |
| 351 | 	 vnet_deregister_sysinit, &ident ## _vnet_init) |
| 352 | |
| 353 | #define	VNET_SYSUNINIT(ident, subsystem, order, func, arg)		\ |
| 354 | 	CTASSERT((subsystem) > SI_SUB_VNET &&				\ |
| 355 | 	 (subsystem) <= SI_SUB_VNET_DONE);				\ |
| 356 | 	static struct vnet_sysinit ident ## _vnet_uninit = {		\ |
| 357 | 		subsystem,						\ |
| 358 | 		order,							\ |
| 359 | 		(sysinit_cfunc_t)(sysinit_nfunc_t)func,			\ |
| 360 | 		(arg)							\ |
| 361 | 	};								\ |
| 362 | 	SYSINIT(vnet_uninit_ ## ident, subsystem, order,		\ |
| 363 | 	 vnet_register_sysuninit, &ident ## _vnet_uninit);		\ |
| 364 | 	SYSUNINIT(vnet_uninit_ ## ident, subsystem, order,		\ |
| 365 | 	 vnet_deregister_sysuninit, &ident ## _vnet_uninit) |
| 366 | |
| 367 | /* |
| 368 | * Interfaces for managing per-vnet constructors and destructors. |
| 369 | */ |
| 370 | void	vnet_register_sysinit(void *arg); |
| 371 | void	vnet_register_sysuninit(void *arg); |
| 372 | void	vnet_deregister_sysinit(void *arg); |
| 373 | void	vnet_deregister_sysuninit(void *arg); |
| 374 | |
| 375 | /* |
| 376 | * EVENTHANDLER(9) extensions. |
| 377 | */ |
| 378 | #include <sys/eventhandler.h> |
| 379 | |
| 380 | void	vnet_global_eventhandler_iterator_func(void *, ...); |
| 381 | #define VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG(tag, name, func, arg, priority) \ |
| 382 | do {									\ |
| 383 | 	if (IS_DEFAULT_VNET(curvnet)) {					\ |
| 384 | 		(tag) = vimage_eventhandler_register(NULL, #name, func,	\ |
| 385 | 		 arg, priority,					\ |
| 386 | 		 vnet_global_eventhandler_iterator_func);		\ |
| 387 | 	}								\ |
| 388 | } while(0) |
| 389 | #define VNET_GLOBAL_EVENTHANDLER_REGISTER(name, func, arg, priority)	\ |
| 390 | do {									\ |
| 391 | 	if (IS_DEFAULT_VNET(curvnet)) {					\ |
| 392 | 		vimage_eventhandler_register(NULL, #name, func,		\ |
| 393 | 		 arg, priority,					\ |
| 394 | 		 vnet_global_eventhandler_iterator_func);		\ |
| 395 | 	}								\ |
| 396 | } while(0) |
| 397 | |
| 398 | #else /* !VIMAGE */ |
| 399 | |
| 400 | /* |
| 401 | * Various virtual network stack macros compile to no-ops without VIMAGE. |
| 402 | */ |
| 403 | #define	curvnet			NULL |
| 404 | |
| 405 | #define	VNET_ASSERT(exp, msg) |
| 406 | #define	CURVNET_SET(arg) |
| 407 | #define	CURVNET_SET_QUIET(arg) |
| 408 | #define	CURVNET_RESTORE() |
| 409 | #define	CURVNET_ASSERT_SET() |
| 410 | |
| 411 | #define	VNET_LIST_RLOCK() |
| 412 | #define	VNET_LIST_RLOCK_NOSLEEP() |
| 413 | #define	VNET_LIST_RUNLOCK() |
| 414 | #define	VNET_LIST_RUNLOCK_NOSLEEP() |
| 415 | #define	VNET_ITERATOR_DECL(arg) |
| 416 | #define	VNET_FOREACH(arg)	for (int _vn = 0; _vn == 0; _vn++) |
| 417 | |
| 418 | #define	IS_DEFAULT_VNET(arg)	1 |
| 419 | #define	CRED_TO_VNET(cr)	NULL |
| 420 | #define	TD_TO_VNET(td)		NULL |
| 421 | #define	P_TO_VNET(p)		NULL |
| 422 | |
| 423 | /* |
| 424 | * Versions of the VNET macros that compile to normal global variables and |
| 425 | * standard sysctl definitions. |
| 426 | */ |
| 427 | #define	VNET_NAME(n)		n |
| 428 | #define	VNET_DECLARE(t, n)	extern t n |
| 429 | #define	VNET_DEFINE(t, n)	struct _hack; t n |
| 430 | #define	VNET_DEFINE_STATIC(t, n)	static t n |
| 431 | #define	_VNET_PTR(b, n)		&VNET_NAME(n) |
| 432 | |
| 433 | /* |
| 434 | * Virtualized global variable accessor macros. |
| 435 | */ |
| 436 | #define	VNET_VNET_PTR(vnet, n)		(&(n)) |
| 437 | #define	VNET_VNET(vnet, n)		(n) |
| 438 | |
| 439 | #define	VNET_PTR(n)		(&(n)) |
| 440 | #define	VNET(n)			(n) |
| 441 | |
| 442 | /* |
| 443 | * When VIMAGE isn't compiled into the kernel, VNET_SYSINIT/VNET_SYSUNINIT |
| 444 | * map into normal sysinits, which have the same ordering properties. |
| 445 | */ |
| 446 | #define	VNET_SYSINIT(ident, subsystem, order, func, arg)		\ |
| 447 | 	SYSINIT(ident, subsystem, order, func, arg) |
| 448 | #define	VNET_SYSUNINIT(ident, subsystem, order, func, arg)		\ |
| 449 | 	SYSUNINIT(ident, subsystem, order, func, arg) |
| 450 | |
| 451 | /* |
| 452 | * Without VIMAGE revert to the default implementation. |
| 453 | */ |
| 454 | #define VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG(tag, name, func, arg, priority) \ |
| 455 | 	(tag) = eventhandler_register(NULL, #name, func, arg, priority) |
| 456 | #define VNET_GLOBAL_EVENTHANDLER_REGISTER(name, func, arg, priority)	\ |
| 457 | 	eventhandler_register(NULL, #name, func, arg, priority) |
| 458 | #endif /* VIMAGE */ |
| 459 | #endif /* _KERNEL */ |
| 460 | |
| 461 | #endif /* !_NET_VNET_H_ */ |