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