1*3b2bd0f6Slogwang /*
2*3b2bd0f6Slogwang  * netgraph.h
3*3b2bd0f6Slogwang  */
4*3b2bd0f6Slogwang 
5*3b2bd0f6Slogwang /*-
6*3b2bd0f6Slogwang  * Copyright (c) 1996-1999 Whistle Communications, Inc.
7*3b2bd0f6Slogwang  * All rights reserved.
8*3b2bd0f6Slogwang  *
9*3b2bd0f6Slogwang  * Subject to the following obligations and disclaimer of warranty, use and
10*3b2bd0f6Slogwang  * redistribution of this software, in source or object code forms, with or
11*3b2bd0f6Slogwang  * without modifications are expressly permitted by Whistle Communications;
12*3b2bd0f6Slogwang  * provided, however, that:
13*3b2bd0f6Slogwang  * 1. Any and all reproductions of the source or object code must include the
14*3b2bd0f6Slogwang  *    copyright notice above and the following disclaimer of warranties; and
15*3b2bd0f6Slogwang  * 2. No rights are granted, in any manner or form, to use Whistle
16*3b2bd0f6Slogwang  *    Communications, Inc. trademarks, including the mark "WHISTLE
17*3b2bd0f6Slogwang  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18*3b2bd0f6Slogwang  *    such appears in the above copyright notice or in the software.
19*3b2bd0f6Slogwang  *
20*3b2bd0f6Slogwang  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
21*3b2bd0f6Slogwang  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22*3b2bd0f6Slogwang  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23*3b2bd0f6Slogwang  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
24*3b2bd0f6Slogwang  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
25*3b2bd0f6Slogwang  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
26*3b2bd0f6Slogwang  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
27*3b2bd0f6Slogwang  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
28*3b2bd0f6Slogwang  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29*3b2bd0f6Slogwang  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30*3b2bd0f6Slogwang  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31*3b2bd0f6Slogwang  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32*3b2bd0f6Slogwang  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33*3b2bd0f6Slogwang  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34*3b2bd0f6Slogwang  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35*3b2bd0f6Slogwang  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36*3b2bd0f6Slogwang  * OF SUCH DAMAGE.
37*3b2bd0f6Slogwang  *
38*3b2bd0f6Slogwang  * Author: Julian Elischer <[email protected]>
39*3b2bd0f6Slogwang  *
40*3b2bd0f6Slogwang  * $FreeBSD$
41*3b2bd0f6Slogwang  * $Whistle: netgraph.h,v 1.29 1999/11/01 07:56:13 julian Exp $
42*3b2bd0f6Slogwang  */
43*3b2bd0f6Slogwang 
44*3b2bd0f6Slogwang #ifndef _NETGRAPH_NETGRAPH_H_
45*3b2bd0f6Slogwang #define _NETGRAPH_NETGRAPH_H_
46*3b2bd0f6Slogwang 
47*3b2bd0f6Slogwang #ifndef _KERNEL
48*3b2bd0f6Slogwang #error "This file should not be included in user level programs"
49*3b2bd0f6Slogwang #endif
50*3b2bd0f6Slogwang 
51*3b2bd0f6Slogwang #include <sys/queue.h>
52*3b2bd0f6Slogwang #include <sys/lock.h>
53*3b2bd0f6Slogwang #include <sys/malloc.h>
54*3b2bd0f6Slogwang #include <sys/module.h>
55*3b2bd0f6Slogwang #include <sys/mutex.h>
56*3b2bd0f6Slogwang #include <sys/refcount.h>
57*3b2bd0f6Slogwang 
58*3b2bd0f6Slogwang #ifdef HAVE_KERNEL_OPTION_HEADERS
59*3b2bd0f6Slogwang #include "opt_netgraph.h"
60*3b2bd0f6Slogwang #include "opt_kdb.h"
61*3b2bd0f6Slogwang #endif
62*3b2bd0f6Slogwang 
63*3b2bd0f6Slogwang /* debugging options */
64*3b2bd0f6Slogwang #define NG_SEPARATE_MALLOC	/* make modules use their own malloc types */
65*3b2bd0f6Slogwang 
66*3b2bd0f6Slogwang /*
67*3b2bd0f6Slogwang  * This defines the in-kernel binary interface version.
68*3b2bd0f6Slogwang  * It is possible to change this but leave the external message
69*3b2bd0f6Slogwang  * API the same. Each type also has it's own cookies for versioning as well.
70*3b2bd0f6Slogwang  * Change it for NETGRAPH_DEBUG version so we cannot mix debug and non debug
71*3b2bd0f6Slogwang  * modules.
72*3b2bd0f6Slogwang  */
73*3b2bd0f6Slogwang #define _NG_ABI_VERSION 12
74*3b2bd0f6Slogwang #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
75*3b2bd0f6Slogwang #define NG_ABI_VERSION	(_NG_ABI_VERSION + 0x10000)
76*3b2bd0f6Slogwang #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
77*3b2bd0f6Slogwang #define NG_ABI_VERSION	_NG_ABI_VERSION
78*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
79*3b2bd0f6Slogwang 
80*3b2bd0f6Slogwang 
81*3b2bd0f6Slogwang /*
82*3b2bd0f6Slogwang  * Forward references for the basic structures so we can
83*3b2bd0f6Slogwang  * define the typedefs and use them in the structures themselves.
84*3b2bd0f6Slogwang  */
85*3b2bd0f6Slogwang struct ng_hook ;
86*3b2bd0f6Slogwang struct ng_node ;
87*3b2bd0f6Slogwang struct ng_item ;
88*3b2bd0f6Slogwang typedef	struct ng_item *item_p;
89*3b2bd0f6Slogwang typedef struct ng_node *node_p;
90*3b2bd0f6Slogwang typedef struct ng_hook *hook_p;
91*3b2bd0f6Slogwang 
92*3b2bd0f6Slogwang /* node method definitions */
93*3b2bd0f6Slogwang typedef	int	ng_constructor_t(node_p node);
94*3b2bd0f6Slogwang typedef	int	ng_close_t(node_p node);
95*3b2bd0f6Slogwang typedef	int	ng_shutdown_t(node_p node);
96*3b2bd0f6Slogwang typedef	int	ng_newhook_t(node_p node, hook_p hook, const char *name);
97*3b2bd0f6Slogwang typedef	hook_p	ng_findhook_t(node_p node, const char *name);
98*3b2bd0f6Slogwang typedef	int	ng_connect_t(hook_p hook);
99*3b2bd0f6Slogwang typedef	int	ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook);
100*3b2bd0f6Slogwang typedef	int	ng_rcvdata_t(hook_p hook, item_p item);
101*3b2bd0f6Slogwang typedef	int	ng_disconnect_t(hook_p hook);
102*3b2bd0f6Slogwang typedef	int	ng_rcvitem (node_p node, hook_p hook, item_p item);
103*3b2bd0f6Slogwang 
104*3b2bd0f6Slogwang /***********************************************************************
105*3b2bd0f6Slogwang  ***************** Hook Structure and Methods **************************
106*3b2bd0f6Slogwang  ***********************************************************************
107*3b2bd0f6Slogwang  *
108*3b2bd0f6Slogwang  * Structure of a hook
109*3b2bd0f6Slogwang  */
110*3b2bd0f6Slogwang struct ng_hook {
111*3b2bd0f6Slogwang 	char	hk_name[NG_HOOKSIZ];	/* what this node knows this link as */
112*3b2bd0f6Slogwang 	void   *hk_private;		/* node dependent ID for this hook */
113*3b2bd0f6Slogwang 	int	hk_flags;		/* info about this hook/link */
114*3b2bd0f6Slogwang 	int	hk_type;		/* tbd: hook data link type */
115*3b2bd0f6Slogwang 	struct	ng_hook *hk_peer;	/* the other end of this link */
116*3b2bd0f6Slogwang 	struct	ng_node *hk_node;	/* The node this hook is attached to */
117*3b2bd0f6Slogwang 	LIST_ENTRY(ng_hook) hk_hooks;	/* linked list of all hooks on node */
118*3b2bd0f6Slogwang 	ng_rcvmsg_t	*hk_rcvmsg;	/* control messages come here */
119*3b2bd0f6Slogwang 	ng_rcvdata_t	*hk_rcvdata;	/* data comes here */
120*3b2bd0f6Slogwang 	int	hk_refs;		/* dont actually free this till 0 */
121*3b2bd0f6Slogwang #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
122*3b2bd0f6Slogwang #define HK_MAGIC 0x78573011
123*3b2bd0f6Slogwang 	int	hk_magic;
124*3b2bd0f6Slogwang 	char	*lastfile;
125*3b2bd0f6Slogwang 	int	lastline;
126*3b2bd0f6Slogwang 	SLIST_ENTRY(ng_hook)	  hk_all;		/* all existing items */
127*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
128*3b2bd0f6Slogwang };
129*3b2bd0f6Slogwang /* Flags for a hook */
130*3b2bd0f6Slogwang #define HK_INVALID		0x0001	/* don't trust it! */
131*3b2bd0f6Slogwang #define HK_QUEUE		0x0002	/* queue for later delivery */
132*3b2bd0f6Slogwang #define HK_FORCE_WRITER		0x0004	/* Incoming data queued as a writer */
133*3b2bd0f6Slogwang #define HK_DEAD			0x0008	/* This is the dead hook.. don't free */
134*3b2bd0f6Slogwang #define HK_HI_STACK		0x0010	/* Hook has hi stack usage */
135*3b2bd0f6Slogwang #define HK_TO_INBOUND		0x0020	/* Hook on ntw. stack inbound path. */
136*3b2bd0f6Slogwang 
137*3b2bd0f6Slogwang /*
138*3b2bd0f6Slogwang  * Public Methods for hook
139*3b2bd0f6Slogwang  * If you can't do it with these you probably shouldn;t be doing it.
140*3b2bd0f6Slogwang  */
141*3b2bd0f6Slogwang void ng_unref_hook(hook_p hook); /* don't move this */
142*3b2bd0f6Slogwang #define	_NG_HOOK_REF(hook)	refcount_acquire(&(hook)->hk_refs)
143*3b2bd0f6Slogwang #define _NG_HOOK_NAME(hook)	((hook)->hk_name)
144*3b2bd0f6Slogwang #define _NG_HOOK_UNREF(hook)	ng_unref_hook(hook)
145*3b2bd0f6Slogwang #define	_NG_HOOK_SET_PRIVATE(hook, val)	do {(hook)->hk_private = val;} while (0)
146*3b2bd0f6Slogwang #define	_NG_HOOK_SET_RCVMSG(hook, val)	do {(hook)->hk_rcvmsg = val;} while (0)
147*3b2bd0f6Slogwang #define	_NG_HOOK_SET_RCVDATA(hook, val)	do {(hook)->hk_rcvdata = val;} while (0)
148*3b2bd0f6Slogwang #define	_NG_HOOK_PRIVATE(hook)	((hook)->hk_private)
149*3b2bd0f6Slogwang #define _NG_HOOK_NOT_VALID(hook)	((hook)->hk_flags & HK_INVALID)
150*3b2bd0f6Slogwang #define _NG_HOOK_IS_VALID(hook)	(!((hook)->hk_flags & HK_INVALID))
151*3b2bd0f6Slogwang #define _NG_HOOK_NODE(hook)	((hook)->hk_node) /* only rvalue! */
152*3b2bd0f6Slogwang #define _NG_HOOK_PEER(hook)	((hook)->hk_peer) /* only rvalue! */
153*3b2bd0f6Slogwang #define _NG_HOOK_FORCE_WRITER(hook)				\
154*3b2bd0f6Slogwang 		do { hook->hk_flags |= HK_FORCE_WRITER; } while (0)
155*3b2bd0f6Slogwang #define _NG_HOOK_FORCE_QUEUE(hook) do { hook->hk_flags |= HK_QUEUE; } while (0)
156*3b2bd0f6Slogwang #define _NG_HOOK_SET_TO_INBOUND(hook)				\
157*3b2bd0f6Slogwang 		do { hook->hk_flags |= HK_TO_INBOUND; } while (0)
158*3b2bd0f6Slogwang #define _NG_HOOK_HI_STACK(hook) do { hook->hk_flags |= HK_HI_STACK; } while (0)
159*3b2bd0f6Slogwang 
160*3b2bd0f6Slogwang /* Some shortcuts */
161*3b2bd0f6Slogwang #define NG_PEER_NODE(hook)	NG_HOOK_NODE(NG_HOOK_PEER(hook))
162*3b2bd0f6Slogwang #define NG_PEER_HOOK_NAME(hook)	NG_HOOK_NAME(NG_HOOK_PEER(hook))
163*3b2bd0f6Slogwang #define NG_PEER_NODE_NAME(hook)	NG_NODE_NAME(NG_PEER_NODE(hook))
164*3b2bd0f6Slogwang 
165*3b2bd0f6Slogwang #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
166*3b2bd0f6Slogwang #define _NN_ __FILE__,__LINE__
167*3b2bd0f6Slogwang void	dumphook (hook_p hook, char *file, int line);
168*3b2bd0f6Slogwang static __inline void	_chkhook(hook_p hook, char *file, int line);
169*3b2bd0f6Slogwang static __inline void	_ng_hook_ref(hook_p hook, char * file, int line);
170*3b2bd0f6Slogwang static __inline char *	_ng_hook_name(hook_p hook, char * file, int line);
171*3b2bd0f6Slogwang static __inline void	_ng_hook_unref(hook_p hook, char * file, int line);
172*3b2bd0f6Slogwang static __inline void	_ng_hook_set_private(hook_p hook,
173*3b2bd0f6Slogwang 				void * val, char * file, int line);
174*3b2bd0f6Slogwang static __inline void	_ng_hook_set_rcvmsg(hook_p hook,
175*3b2bd0f6Slogwang 				ng_rcvmsg_t *val, char * file, int line);
176*3b2bd0f6Slogwang static __inline void	_ng_hook_set_rcvdata(hook_p hook,
177*3b2bd0f6Slogwang 				ng_rcvdata_t *val, char * file, int line);
178*3b2bd0f6Slogwang static __inline void *	_ng_hook_private(hook_p hook, char * file, int line);
179*3b2bd0f6Slogwang static __inline int	_ng_hook_not_valid(hook_p hook, char * file, int line);
180*3b2bd0f6Slogwang static __inline int	_ng_hook_is_valid(hook_p hook, char * file, int line);
181*3b2bd0f6Slogwang static __inline node_p	_ng_hook_node(hook_p hook, char * file, int line);
182*3b2bd0f6Slogwang static __inline hook_p	_ng_hook_peer(hook_p hook, char * file, int line);
183*3b2bd0f6Slogwang static __inline void	_ng_hook_force_writer(hook_p hook, char * file,
184*3b2bd0f6Slogwang 				int line);
185*3b2bd0f6Slogwang static __inline void	_ng_hook_force_queue(hook_p hook, char * file,
186*3b2bd0f6Slogwang 				int line);
187*3b2bd0f6Slogwang static __inline void	_ng_hook_set_to_inbound(hook_p hook, char * file,
188*3b2bd0f6Slogwang 				int line);
189*3b2bd0f6Slogwang 
190*3b2bd0f6Slogwang static __inline void
_chkhook(hook_p hook,char * file,int line)191*3b2bd0f6Slogwang _chkhook(hook_p hook, char *file, int line)
192*3b2bd0f6Slogwang {
193*3b2bd0f6Slogwang 	if (hook->hk_magic != HK_MAGIC) {
194*3b2bd0f6Slogwang 		printf("Accessing freed ");
195*3b2bd0f6Slogwang 		dumphook(hook, file, line);
196*3b2bd0f6Slogwang 	}
197*3b2bd0f6Slogwang 	hook->lastline = line;
198*3b2bd0f6Slogwang 	hook->lastfile = file;
199*3b2bd0f6Slogwang }
200*3b2bd0f6Slogwang 
201*3b2bd0f6Slogwang static __inline void
_ng_hook_ref(hook_p hook,char * file,int line)202*3b2bd0f6Slogwang _ng_hook_ref(hook_p hook, char * file, int line)
203*3b2bd0f6Slogwang {
204*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
205*3b2bd0f6Slogwang 	_NG_HOOK_REF(hook);
206*3b2bd0f6Slogwang }
207*3b2bd0f6Slogwang 
208*3b2bd0f6Slogwang static __inline char *
_ng_hook_name(hook_p hook,char * file,int line)209*3b2bd0f6Slogwang _ng_hook_name(hook_p hook, char * file, int line)
210*3b2bd0f6Slogwang {
211*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
212*3b2bd0f6Slogwang 	return (_NG_HOOK_NAME(hook));
213*3b2bd0f6Slogwang }
214*3b2bd0f6Slogwang 
215*3b2bd0f6Slogwang static __inline void
_ng_hook_unref(hook_p hook,char * file,int line)216*3b2bd0f6Slogwang _ng_hook_unref(hook_p hook, char * file, int line)
217*3b2bd0f6Slogwang {
218*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
219*3b2bd0f6Slogwang 	_NG_HOOK_UNREF(hook);
220*3b2bd0f6Slogwang }
221*3b2bd0f6Slogwang 
222*3b2bd0f6Slogwang static __inline void
_ng_hook_set_private(hook_p hook,void * val,char * file,int line)223*3b2bd0f6Slogwang _ng_hook_set_private(hook_p hook, void *val, char * file, int line)
224*3b2bd0f6Slogwang {
225*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
226*3b2bd0f6Slogwang 	_NG_HOOK_SET_PRIVATE(hook, val);
227*3b2bd0f6Slogwang }
228*3b2bd0f6Slogwang 
229*3b2bd0f6Slogwang static __inline void
_ng_hook_set_rcvmsg(hook_p hook,ng_rcvmsg_t * val,char * file,int line)230*3b2bd0f6Slogwang _ng_hook_set_rcvmsg(hook_p hook, ng_rcvmsg_t *val, char * file, int line)
231*3b2bd0f6Slogwang {
232*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
233*3b2bd0f6Slogwang 	_NG_HOOK_SET_RCVMSG(hook, val);
234*3b2bd0f6Slogwang }
235*3b2bd0f6Slogwang 
236*3b2bd0f6Slogwang static __inline void
_ng_hook_set_rcvdata(hook_p hook,ng_rcvdata_t * val,char * file,int line)237*3b2bd0f6Slogwang _ng_hook_set_rcvdata(hook_p hook, ng_rcvdata_t *val, char * file, int line)
238*3b2bd0f6Slogwang {
239*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
240*3b2bd0f6Slogwang 	_NG_HOOK_SET_RCVDATA(hook, val);
241*3b2bd0f6Slogwang }
242*3b2bd0f6Slogwang 
243*3b2bd0f6Slogwang static __inline void *
_ng_hook_private(hook_p hook,char * file,int line)244*3b2bd0f6Slogwang _ng_hook_private(hook_p hook, char * file, int line)
245*3b2bd0f6Slogwang {
246*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
247*3b2bd0f6Slogwang 	return (_NG_HOOK_PRIVATE(hook));
248*3b2bd0f6Slogwang }
249*3b2bd0f6Slogwang 
250*3b2bd0f6Slogwang static __inline int
_ng_hook_not_valid(hook_p hook,char * file,int line)251*3b2bd0f6Slogwang _ng_hook_not_valid(hook_p hook, char * file, int line)
252*3b2bd0f6Slogwang {
253*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
254*3b2bd0f6Slogwang 	return (_NG_HOOK_NOT_VALID(hook));
255*3b2bd0f6Slogwang }
256*3b2bd0f6Slogwang 
257*3b2bd0f6Slogwang static __inline int
_ng_hook_is_valid(hook_p hook,char * file,int line)258*3b2bd0f6Slogwang _ng_hook_is_valid(hook_p hook, char * file, int line)
259*3b2bd0f6Slogwang {
260*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
261*3b2bd0f6Slogwang 	return (_NG_HOOK_IS_VALID(hook));
262*3b2bd0f6Slogwang }
263*3b2bd0f6Slogwang 
264*3b2bd0f6Slogwang static __inline node_p
_ng_hook_node(hook_p hook,char * file,int line)265*3b2bd0f6Slogwang _ng_hook_node(hook_p hook, char * file, int line)
266*3b2bd0f6Slogwang {
267*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
268*3b2bd0f6Slogwang 	return (_NG_HOOK_NODE(hook));
269*3b2bd0f6Slogwang }
270*3b2bd0f6Slogwang 
271*3b2bd0f6Slogwang static __inline hook_p
_ng_hook_peer(hook_p hook,char * file,int line)272*3b2bd0f6Slogwang _ng_hook_peer(hook_p hook, char * file, int line)
273*3b2bd0f6Slogwang {
274*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
275*3b2bd0f6Slogwang 	return (_NG_HOOK_PEER(hook));
276*3b2bd0f6Slogwang }
277*3b2bd0f6Slogwang 
278*3b2bd0f6Slogwang static __inline void
_ng_hook_force_writer(hook_p hook,char * file,int line)279*3b2bd0f6Slogwang _ng_hook_force_writer(hook_p hook, char * file, int line)
280*3b2bd0f6Slogwang {
281*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
282*3b2bd0f6Slogwang 	_NG_HOOK_FORCE_WRITER(hook);
283*3b2bd0f6Slogwang }
284*3b2bd0f6Slogwang 
285*3b2bd0f6Slogwang static __inline void
_ng_hook_force_queue(hook_p hook,char * file,int line)286*3b2bd0f6Slogwang _ng_hook_force_queue(hook_p hook, char * file, int line)
287*3b2bd0f6Slogwang {
288*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
289*3b2bd0f6Slogwang 	_NG_HOOK_FORCE_QUEUE(hook);
290*3b2bd0f6Slogwang }
291*3b2bd0f6Slogwang 
292*3b2bd0f6Slogwang static __inline void
_ng_hook_set_to_inbound(hook_p hook,char * file,int line)293*3b2bd0f6Slogwang _ng_hook_set_to_inbound(hook_p hook, char * file, int line)
294*3b2bd0f6Slogwang {
295*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
296*3b2bd0f6Slogwang 	_NG_HOOK_SET_TO_INBOUND(hook);
297*3b2bd0f6Slogwang }
298*3b2bd0f6Slogwang 
299*3b2bd0f6Slogwang static __inline void
_ng_hook_hi_stack(hook_p hook,char * file,int line)300*3b2bd0f6Slogwang _ng_hook_hi_stack(hook_p hook, char * file, int line)
301*3b2bd0f6Slogwang {
302*3b2bd0f6Slogwang 	_chkhook(hook, file, line);
303*3b2bd0f6Slogwang 	_NG_HOOK_HI_STACK(hook);
304*3b2bd0f6Slogwang }
305*3b2bd0f6Slogwang 
306*3b2bd0f6Slogwang 
307*3b2bd0f6Slogwang #define	NG_HOOK_REF(hook)		_ng_hook_ref(hook, _NN_)
308*3b2bd0f6Slogwang #define NG_HOOK_NAME(hook)		_ng_hook_name(hook, _NN_)
309*3b2bd0f6Slogwang #define NG_HOOK_UNREF(hook)		_ng_hook_unref(hook, _NN_)
310*3b2bd0f6Slogwang #define	NG_HOOK_SET_PRIVATE(hook, val)	_ng_hook_set_private(hook, val, _NN_)
311*3b2bd0f6Slogwang #define	NG_HOOK_SET_RCVMSG(hook, val)	_ng_hook_set_rcvmsg(hook, val, _NN_)
312*3b2bd0f6Slogwang #define	NG_HOOK_SET_RCVDATA(hook, val)	_ng_hook_set_rcvdata(hook, val, _NN_)
313*3b2bd0f6Slogwang #define	NG_HOOK_PRIVATE(hook)		_ng_hook_private(hook, _NN_)
314*3b2bd0f6Slogwang #define NG_HOOK_NOT_VALID(hook)		_ng_hook_not_valid(hook, _NN_)
315*3b2bd0f6Slogwang #define NG_HOOK_IS_VALID(hook)		_ng_hook_is_valid(hook, _NN_)
316*3b2bd0f6Slogwang #define NG_HOOK_NODE(hook)		_ng_hook_node(hook, _NN_)
317*3b2bd0f6Slogwang #define NG_HOOK_PEER(hook)		_ng_hook_peer(hook, _NN_)
318*3b2bd0f6Slogwang #define NG_HOOK_FORCE_WRITER(hook)	_ng_hook_force_writer(hook, _NN_)
319*3b2bd0f6Slogwang #define NG_HOOK_FORCE_QUEUE(hook)	_ng_hook_force_queue(hook, _NN_)
320*3b2bd0f6Slogwang #define NG_HOOK_SET_TO_INBOUND(hook)	_ng_hook_set_to_inbound(hook, _NN_)
321*3b2bd0f6Slogwang #define NG_HOOK_HI_STACK(hook)		_ng_hook_hi_stack(hook, _NN_)
322*3b2bd0f6Slogwang 
323*3b2bd0f6Slogwang #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
324*3b2bd0f6Slogwang 
325*3b2bd0f6Slogwang #define	NG_HOOK_REF(hook)		_NG_HOOK_REF(hook)
326*3b2bd0f6Slogwang #define NG_HOOK_NAME(hook)		_NG_HOOK_NAME(hook)
327*3b2bd0f6Slogwang #define NG_HOOK_UNREF(hook)		_NG_HOOK_UNREF(hook)
328*3b2bd0f6Slogwang #define	NG_HOOK_SET_PRIVATE(hook, val)	_NG_HOOK_SET_PRIVATE(hook, val)
329*3b2bd0f6Slogwang #define	NG_HOOK_SET_RCVMSG(hook, val)	_NG_HOOK_SET_RCVMSG(hook, val)
330*3b2bd0f6Slogwang #define	NG_HOOK_SET_RCVDATA(hook, val)	_NG_HOOK_SET_RCVDATA(hook, val)
331*3b2bd0f6Slogwang #define	NG_HOOK_PRIVATE(hook)		_NG_HOOK_PRIVATE(hook)
332*3b2bd0f6Slogwang #define NG_HOOK_NOT_VALID(hook)		_NG_HOOK_NOT_VALID(hook)
333*3b2bd0f6Slogwang #define NG_HOOK_IS_VALID(hook)		_NG_HOOK_IS_VALID(hook)
334*3b2bd0f6Slogwang #define NG_HOOK_NODE(hook)		_NG_HOOK_NODE(hook)
335*3b2bd0f6Slogwang #define NG_HOOK_PEER(hook)		_NG_HOOK_PEER(hook)
336*3b2bd0f6Slogwang #define NG_HOOK_FORCE_WRITER(hook)	_NG_HOOK_FORCE_WRITER(hook)
337*3b2bd0f6Slogwang #define NG_HOOK_FORCE_QUEUE(hook)	_NG_HOOK_FORCE_QUEUE(hook)
338*3b2bd0f6Slogwang #define NG_HOOK_SET_TO_INBOUND(hook)	_NG_HOOK_SET_TO_INBOUND(hook)
339*3b2bd0f6Slogwang #define NG_HOOK_HI_STACK(hook)		_NG_HOOK_HI_STACK(hook)
340*3b2bd0f6Slogwang 
341*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
342*3b2bd0f6Slogwang 
343*3b2bd0f6Slogwang /***********************************************************************
344*3b2bd0f6Slogwang  ***************** Node Structure and Methods **************************
345*3b2bd0f6Slogwang  ***********************************************************************
346*3b2bd0f6Slogwang  * Structure of a node
347*3b2bd0f6Slogwang  * including the eembedded queue structure.
348*3b2bd0f6Slogwang  *
349*3b2bd0f6Slogwang  * The structure for queueing Netgraph request items
350*3b2bd0f6Slogwang  * embedded in the node structure
351*3b2bd0f6Slogwang  */
352*3b2bd0f6Slogwang struct ng_queue {
353*3b2bd0f6Slogwang 	u_int		q_flags;	/* Current r/w/q lock flags */
354*3b2bd0f6Slogwang 	u_int		q_flags2;	/* Other queue flags */
355*3b2bd0f6Slogwang 	struct mtx	q_mtx;
356*3b2bd0f6Slogwang 	STAILQ_ENTRY(ng_node)	q_work;	/* nodes with work to do */
357*3b2bd0f6Slogwang 	STAILQ_HEAD(, ng_item)	queue;	/* actually items queue */
358*3b2bd0f6Slogwang };
359*3b2bd0f6Slogwang 
360*3b2bd0f6Slogwang struct ng_node {
361*3b2bd0f6Slogwang 	char	nd_name[NG_NODESIZ];	/* optional globally unique name */
362*3b2bd0f6Slogwang 	struct	ng_type *nd_type;	/* the installed 'type' */
363*3b2bd0f6Slogwang 	int	nd_flags;		/* see below for bit definitions */
364*3b2bd0f6Slogwang 	int	nd_numhooks;		/* number of hooks */
365*3b2bd0f6Slogwang 	void   *nd_private;		/* node type dependent node ID */
366*3b2bd0f6Slogwang 	ng_ID_t	nd_ID;			/* Unique per node */
367*3b2bd0f6Slogwang 	LIST_HEAD(hooks, ng_hook) nd_hooks;	/* linked list of node hooks */
368*3b2bd0f6Slogwang 	LIST_ENTRY(ng_node)	  nd_nodes;	/* name hash collision list */
369*3b2bd0f6Slogwang 	LIST_ENTRY(ng_node)	  nd_idnodes;	/* ID hash collision list */
370*3b2bd0f6Slogwang 	struct	ng_queue	  nd_input_queue; /* input queue for locking */
371*3b2bd0f6Slogwang 	int	nd_refs;		/* # of references to this node */
372*3b2bd0f6Slogwang 	struct	vnet		 *nd_vnet;	/* network stack instance */
373*3b2bd0f6Slogwang #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
374*3b2bd0f6Slogwang #define ND_MAGIC 0x59264837
375*3b2bd0f6Slogwang 	int	nd_magic;
376*3b2bd0f6Slogwang 	char	*lastfile;
377*3b2bd0f6Slogwang 	int	lastline;
378*3b2bd0f6Slogwang 	SLIST_ENTRY(ng_node)	  nd_all;	/* all existing nodes */
379*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
380*3b2bd0f6Slogwang };
381*3b2bd0f6Slogwang 
382*3b2bd0f6Slogwang /* Flags for a node */
383*3b2bd0f6Slogwang #define NGF_INVALID	0x00000001	/* free when refs go to 0 */
384*3b2bd0f6Slogwang #define NG_INVALID	NGF_INVALID	/* compat for old code */
385*3b2bd0f6Slogwang #define NGF_FORCE_WRITER	0x00000004	/* Never multithread this node */
386*3b2bd0f6Slogwang #define NG_FORCE_WRITER	NGF_FORCE_WRITER /* compat for old code */
387*3b2bd0f6Slogwang #define NGF_CLOSING	0x00000008	/* ng_rmnode() at work */
388*3b2bd0f6Slogwang #define NG_CLOSING	NGF_CLOSING	/* compat for old code */
389*3b2bd0f6Slogwang #define NGF_REALLY_DIE	0x00000010	/* "persistent" node is unloading */
390*3b2bd0f6Slogwang #define NG_REALLY_DIE	NGF_REALLY_DIE	/* compat for old code */
391*3b2bd0f6Slogwang #define NGF_HI_STACK	0x00000020	/* node has hi stack usage */
392*3b2bd0f6Slogwang #define NGF_TYPE1	0x10000000	/* reserved for type specific storage */
393*3b2bd0f6Slogwang #define NGF_TYPE2	0x20000000	/* reserved for type specific storage */
394*3b2bd0f6Slogwang #define NGF_TYPE3	0x40000000	/* reserved for type specific storage */
395*3b2bd0f6Slogwang #define NGF_TYPE4	0x80000000	/* reserved for type specific storage */
396*3b2bd0f6Slogwang 
397*3b2bd0f6Slogwang /*
398*3b2bd0f6Slogwang  * Public methods for nodes.
399*3b2bd0f6Slogwang  * If you can't do it with these you probably shouldn't be doing it.
400*3b2bd0f6Slogwang  */
401*3b2bd0f6Slogwang void	ng_unref_node(node_p node); /* don't move this */
402*3b2bd0f6Slogwang #define _NG_NODE_NAME(node)	((node)->nd_name + 0)
403*3b2bd0f6Slogwang #define _NG_NODE_HAS_NAME(node)	((node)->nd_name[0] + 0)
404*3b2bd0f6Slogwang #define _NG_NODE_ID(node)	((node)->nd_ID + 0)
405*3b2bd0f6Slogwang #define	_NG_NODE_REF(node)	refcount_acquire(&(node)->nd_refs)
406*3b2bd0f6Slogwang #define	_NG_NODE_UNREF(node)	ng_unref_node(node)
407*3b2bd0f6Slogwang #define	_NG_NODE_SET_PRIVATE(node, val)	do {(node)->nd_private = val;} while (0)
408*3b2bd0f6Slogwang #define	_NG_NODE_PRIVATE(node)	((node)->nd_private)
409*3b2bd0f6Slogwang #define _NG_NODE_IS_VALID(node)	(!((node)->nd_flags & NGF_INVALID))
410*3b2bd0f6Slogwang #define _NG_NODE_NOT_VALID(node)	((node)->nd_flags & NGF_INVALID)
411*3b2bd0f6Slogwang #define _NG_NODE_NUMHOOKS(node)	((node)->nd_numhooks + 0) /* rvalue */
412*3b2bd0f6Slogwang #define _NG_NODE_FORCE_WRITER(node)					\
413*3b2bd0f6Slogwang 	do{ node->nd_flags |= NGF_FORCE_WRITER; }while (0)
414*3b2bd0f6Slogwang #define _NG_NODE_HI_STACK(node)						\
415*3b2bd0f6Slogwang 	do{ node->nd_flags |= NGF_HI_STACK; }while (0)
416*3b2bd0f6Slogwang #define _NG_NODE_REALLY_DIE(node)					\
417*3b2bd0f6Slogwang 	do{ node->nd_flags |= (NGF_REALLY_DIE|NGF_INVALID); }while (0)
418*3b2bd0f6Slogwang #define _NG_NODE_REVIVE(node) \
419*3b2bd0f6Slogwang 	do { node->nd_flags &= ~NGF_INVALID; } while (0)
420*3b2bd0f6Slogwang /*
421*3b2bd0f6Slogwang  * The hook iterator.
422*3b2bd0f6Slogwang  * This macro will call a function of type ng_fn_eachhook for each
423*3b2bd0f6Slogwang  * hook attached to the node. If the function returns 0, then the
424*3b2bd0f6Slogwang  * iterator will stop and return a pointer to the hook that returned 0.
425*3b2bd0f6Slogwang  */
426*3b2bd0f6Slogwang typedef	int	ng_fn_eachhook(hook_p hook, void* arg);
427*3b2bd0f6Slogwang #define _NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			\
428*3b2bd0f6Slogwang 	do {								\
429*3b2bd0f6Slogwang 		hook_p _hook;						\
430*3b2bd0f6Slogwang 		(rethook) = NULL;					\
431*3b2bd0f6Slogwang 		LIST_FOREACH(_hook, &((node)->nd_hooks), hk_hooks) {	\
432*3b2bd0f6Slogwang 			if ((fn)(_hook, arg) == 0) {			\
433*3b2bd0f6Slogwang 				(rethook) = _hook;			\
434*3b2bd0f6Slogwang 				break;					\
435*3b2bd0f6Slogwang 			}						\
436*3b2bd0f6Slogwang 		}							\
437*3b2bd0f6Slogwang 	} while (0)
438*3b2bd0f6Slogwang 
439*3b2bd0f6Slogwang #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
440*3b2bd0f6Slogwang void	dumpnode(node_p node, char *file, int line);
441*3b2bd0f6Slogwang static __inline void _chknode(node_p node, char *file, int line);
442*3b2bd0f6Slogwang static __inline char * _ng_node_name(node_p node, char *file, int line);
443*3b2bd0f6Slogwang static __inline int _ng_node_has_name(node_p node, char *file, int line);
444*3b2bd0f6Slogwang static __inline ng_ID_t _ng_node_id(node_p node, char *file, int line);
445*3b2bd0f6Slogwang static __inline void _ng_node_ref(node_p node, char *file, int line);
446*3b2bd0f6Slogwang static __inline void _ng_node_unref(node_p node, char *file, int line);
447*3b2bd0f6Slogwang static __inline void _ng_node_set_private(node_p node, void * val,
448*3b2bd0f6Slogwang 							char *file, int line);
449*3b2bd0f6Slogwang static __inline void * _ng_node_private(node_p node, char *file, int line);
450*3b2bd0f6Slogwang static __inline int _ng_node_is_valid(node_p node, char *file, int line);
451*3b2bd0f6Slogwang static __inline int _ng_node_not_valid(node_p node, char *file, int line);
452*3b2bd0f6Slogwang static __inline int _ng_node_numhooks(node_p node, char *file, int line);
453*3b2bd0f6Slogwang static __inline void _ng_node_force_writer(node_p node, char *file, int line);
454*3b2bd0f6Slogwang static __inline hook_p _ng_node_foreach_hook(node_p node,
455*3b2bd0f6Slogwang 			ng_fn_eachhook *fn, void *arg, char *file, int line);
456*3b2bd0f6Slogwang static __inline void _ng_node_revive(node_p node, char *file, int line);
457*3b2bd0f6Slogwang 
458*3b2bd0f6Slogwang static __inline void
_chknode(node_p node,char * file,int line)459*3b2bd0f6Slogwang _chknode(node_p node, char *file, int line)
460*3b2bd0f6Slogwang {
461*3b2bd0f6Slogwang 	if (node->nd_magic != ND_MAGIC) {
462*3b2bd0f6Slogwang 		printf("Accessing freed ");
463*3b2bd0f6Slogwang 		dumpnode(node, file, line);
464*3b2bd0f6Slogwang 	}
465*3b2bd0f6Slogwang 	node->lastline = line;
466*3b2bd0f6Slogwang 	node->lastfile = file;
467*3b2bd0f6Slogwang }
468*3b2bd0f6Slogwang 
469*3b2bd0f6Slogwang static __inline char *
_ng_node_name(node_p node,char * file,int line)470*3b2bd0f6Slogwang _ng_node_name(node_p node, char *file, int line)
471*3b2bd0f6Slogwang {
472*3b2bd0f6Slogwang 	_chknode(node, file, line);
473*3b2bd0f6Slogwang 	return(_NG_NODE_NAME(node));
474*3b2bd0f6Slogwang }
475*3b2bd0f6Slogwang 
476*3b2bd0f6Slogwang static __inline int
_ng_node_has_name(node_p node,char * file,int line)477*3b2bd0f6Slogwang _ng_node_has_name(node_p node, char *file, int line)
478*3b2bd0f6Slogwang {
479*3b2bd0f6Slogwang 	_chknode(node, file, line);
480*3b2bd0f6Slogwang 	return(_NG_NODE_HAS_NAME(node));
481*3b2bd0f6Slogwang }
482*3b2bd0f6Slogwang 
483*3b2bd0f6Slogwang static __inline ng_ID_t
_ng_node_id(node_p node,char * file,int line)484*3b2bd0f6Slogwang _ng_node_id(node_p node, char *file, int line)
485*3b2bd0f6Slogwang {
486*3b2bd0f6Slogwang 	_chknode(node, file, line);
487*3b2bd0f6Slogwang 	return(_NG_NODE_ID(node));
488*3b2bd0f6Slogwang }
489*3b2bd0f6Slogwang 
490*3b2bd0f6Slogwang static __inline void
_ng_node_ref(node_p node,char * file,int line)491*3b2bd0f6Slogwang _ng_node_ref(node_p node, char *file, int line)
492*3b2bd0f6Slogwang {
493*3b2bd0f6Slogwang 	_chknode(node, file, line);
494*3b2bd0f6Slogwang 	_NG_NODE_REF(node);
495*3b2bd0f6Slogwang }
496*3b2bd0f6Slogwang 
497*3b2bd0f6Slogwang static __inline void
_ng_node_unref(node_p node,char * file,int line)498*3b2bd0f6Slogwang _ng_node_unref(node_p node, char *file, int line)
499*3b2bd0f6Slogwang {
500*3b2bd0f6Slogwang 	_chknode(node, file, line);
501*3b2bd0f6Slogwang 	_NG_NODE_UNREF(node);
502*3b2bd0f6Slogwang }
503*3b2bd0f6Slogwang 
504*3b2bd0f6Slogwang static __inline void
_ng_node_set_private(node_p node,void * val,char * file,int line)505*3b2bd0f6Slogwang _ng_node_set_private(node_p node, void * val, char *file, int line)
506*3b2bd0f6Slogwang {
507*3b2bd0f6Slogwang 	_chknode(node, file, line);
508*3b2bd0f6Slogwang 	_NG_NODE_SET_PRIVATE(node, val);
509*3b2bd0f6Slogwang }
510*3b2bd0f6Slogwang 
511*3b2bd0f6Slogwang static __inline void *
_ng_node_private(node_p node,char * file,int line)512*3b2bd0f6Slogwang _ng_node_private(node_p node, char *file, int line)
513*3b2bd0f6Slogwang {
514*3b2bd0f6Slogwang 	_chknode(node, file, line);
515*3b2bd0f6Slogwang 	return (_NG_NODE_PRIVATE(node));
516*3b2bd0f6Slogwang }
517*3b2bd0f6Slogwang 
518*3b2bd0f6Slogwang static __inline int
_ng_node_is_valid(node_p node,char * file,int line)519*3b2bd0f6Slogwang _ng_node_is_valid(node_p node, char *file, int line)
520*3b2bd0f6Slogwang {
521*3b2bd0f6Slogwang 	_chknode(node, file, line);
522*3b2bd0f6Slogwang 	return(_NG_NODE_IS_VALID(node));
523*3b2bd0f6Slogwang }
524*3b2bd0f6Slogwang 
525*3b2bd0f6Slogwang static __inline int
_ng_node_not_valid(node_p node,char * file,int line)526*3b2bd0f6Slogwang _ng_node_not_valid(node_p node, char *file, int line)
527*3b2bd0f6Slogwang {
528*3b2bd0f6Slogwang 	_chknode(node, file, line);
529*3b2bd0f6Slogwang 	return(_NG_NODE_NOT_VALID(node));
530*3b2bd0f6Slogwang }
531*3b2bd0f6Slogwang 
532*3b2bd0f6Slogwang static __inline int
_ng_node_numhooks(node_p node,char * file,int line)533*3b2bd0f6Slogwang _ng_node_numhooks(node_p node, char *file, int line)
534*3b2bd0f6Slogwang {
535*3b2bd0f6Slogwang 	_chknode(node, file, line);
536*3b2bd0f6Slogwang 	return(_NG_NODE_NUMHOOKS(node));
537*3b2bd0f6Slogwang }
538*3b2bd0f6Slogwang 
539*3b2bd0f6Slogwang static __inline void
_ng_node_force_writer(node_p node,char * file,int line)540*3b2bd0f6Slogwang _ng_node_force_writer(node_p node, char *file, int line)
541*3b2bd0f6Slogwang {
542*3b2bd0f6Slogwang 	_chknode(node, file, line);
543*3b2bd0f6Slogwang 	_NG_NODE_FORCE_WRITER(node);
544*3b2bd0f6Slogwang }
545*3b2bd0f6Slogwang 
546*3b2bd0f6Slogwang static __inline void
_ng_node_hi_stack(node_p node,char * file,int line)547*3b2bd0f6Slogwang _ng_node_hi_stack(node_p node, char *file, int line)
548*3b2bd0f6Slogwang {
549*3b2bd0f6Slogwang 	_chknode(node, file, line);
550*3b2bd0f6Slogwang 	_NG_NODE_HI_STACK(node);
551*3b2bd0f6Slogwang }
552*3b2bd0f6Slogwang 
553*3b2bd0f6Slogwang static __inline void
_ng_node_really_die(node_p node,char * file,int line)554*3b2bd0f6Slogwang _ng_node_really_die(node_p node, char *file, int line)
555*3b2bd0f6Slogwang {
556*3b2bd0f6Slogwang 	_chknode(node, file, line);
557*3b2bd0f6Slogwang 	_NG_NODE_REALLY_DIE(node);
558*3b2bd0f6Slogwang }
559*3b2bd0f6Slogwang 
560*3b2bd0f6Slogwang static __inline void
_ng_node_revive(node_p node,char * file,int line)561*3b2bd0f6Slogwang _ng_node_revive(node_p node, char *file, int line)
562*3b2bd0f6Slogwang {
563*3b2bd0f6Slogwang 	_chknode(node, file, line);
564*3b2bd0f6Slogwang 	_NG_NODE_REVIVE(node);
565*3b2bd0f6Slogwang }
566*3b2bd0f6Slogwang 
567*3b2bd0f6Slogwang static __inline hook_p
_ng_node_foreach_hook(node_p node,ng_fn_eachhook * fn,void * arg,char * file,int line)568*3b2bd0f6Slogwang _ng_node_foreach_hook(node_p node, ng_fn_eachhook *fn, void *arg,
569*3b2bd0f6Slogwang 						char *file, int line)
570*3b2bd0f6Slogwang {
571*3b2bd0f6Slogwang 	hook_p hook;
572*3b2bd0f6Slogwang 	_chknode(node, file, line);
573*3b2bd0f6Slogwang 	_NG_NODE_FOREACH_HOOK(node, fn, arg, hook);
574*3b2bd0f6Slogwang 	return (hook);
575*3b2bd0f6Slogwang }
576*3b2bd0f6Slogwang 
577*3b2bd0f6Slogwang #define NG_NODE_NAME(node)		_ng_node_name(node, _NN_)
578*3b2bd0f6Slogwang #define NG_NODE_HAS_NAME(node)		_ng_node_has_name(node, _NN_)
579*3b2bd0f6Slogwang #define NG_NODE_ID(node)		_ng_node_id(node, _NN_)
580*3b2bd0f6Slogwang #define NG_NODE_REF(node)		_ng_node_ref(node, _NN_)
581*3b2bd0f6Slogwang #define	NG_NODE_UNREF(node)		_ng_node_unref(node, _NN_)
582*3b2bd0f6Slogwang #define	NG_NODE_SET_PRIVATE(node, val)	_ng_node_set_private(node, val, _NN_)
583*3b2bd0f6Slogwang #define	NG_NODE_PRIVATE(node)		_ng_node_private(node, _NN_)
584*3b2bd0f6Slogwang #define NG_NODE_IS_VALID(node)		_ng_node_is_valid(node, _NN_)
585*3b2bd0f6Slogwang #define NG_NODE_NOT_VALID(node)		_ng_node_not_valid(node, _NN_)
586*3b2bd0f6Slogwang #define NG_NODE_FORCE_WRITER(node) 	_ng_node_force_writer(node, _NN_)
587*3b2bd0f6Slogwang #define NG_NODE_HI_STACK(node) 		_ng_node_hi_stack(node, _NN_)
588*3b2bd0f6Slogwang #define NG_NODE_REALLY_DIE(node) 	_ng_node_really_die(node, _NN_)
589*3b2bd0f6Slogwang #define NG_NODE_NUMHOOKS(node)		_ng_node_numhooks(node, _NN_)
590*3b2bd0f6Slogwang #define NG_NODE_REVIVE(node)		_ng_node_revive(node, _NN_)
591*3b2bd0f6Slogwang #define NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			      \
592*3b2bd0f6Slogwang 	do {								      \
593*3b2bd0f6Slogwang 		rethook = _ng_node_foreach_hook(node, fn, (void *)arg, _NN_); \
594*3b2bd0f6Slogwang 	} while (0)
595*3b2bd0f6Slogwang 
596*3b2bd0f6Slogwang #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
597*3b2bd0f6Slogwang 
598*3b2bd0f6Slogwang #define NG_NODE_NAME(node)		_NG_NODE_NAME(node)
599*3b2bd0f6Slogwang #define NG_NODE_HAS_NAME(node)		_NG_NODE_HAS_NAME(node)
600*3b2bd0f6Slogwang #define NG_NODE_ID(node)		_NG_NODE_ID(node)
601*3b2bd0f6Slogwang #define	NG_NODE_REF(node)		_NG_NODE_REF(node)
602*3b2bd0f6Slogwang #define	NG_NODE_UNREF(node)		_NG_NODE_UNREF(node)
603*3b2bd0f6Slogwang #define	NG_NODE_SET_PRIVATE(node, val)	_NG_NODE_SET_PRIVATE(node, val)
604*3b2bd0f6Slogwang #define	NG_NODE_PRIVATE(node)		_NG_NODE_PRIVATE(node)
605*3b2bd0f6Slogwang #define NG_NODE_IS_VALID(node)		_NG_NODE_IS_VALID(node)
606*3b2bd0f6Slogwang #define NG_NODE_NOT_VALID(node)		_NG_NODE_NOT_VALID(node)
607*3b2bd0f6Slogwang #define NG_NODE_FORCE_WRITER(node) 	_NG_NODE_FORCE_WRITER(node)
608*3b2bd0f6Slogwang #define NG_NODE_HI_STACK(node) 		_NG_NODE_HI_STACK(node)
609*3b2bd0f6Slogwang #define NG_NODE_REALLY_DIE(node) 	_NG_NODE_REALLY_DIE(node)
610*3b2bd0f6Slogwang #define NG_NODE_NUMHOOKS(node)		_NG_NODE_NUMHOOKS(node)
611*3b2bd0f6Slogwang #define NG_NODE_REVIVE(node)		_NG_NODE_REVIVE(node)
612*3b2bd0f6Slogwang #define NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			\
613*3b2bd0f6Slogwang 		_NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)
614*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
615*3b2bd0f6Slogwang 
616*3b2bd0f6Slogwang /***********************************************************************
617*3b2bd0f6Slogwang  ************* Node Queue and Item Structures and Methods **************
618*3b2bd0f6Slogwang  ***********************************************************************
619*3b2bd0f6Slogwang  *
620*3b2bd0f6Slogwang  */
621*3b2bd0f6Slogwang typedef	void	ng_item_fn(node_p node, hook_p hook, void *arg1, int arg2);
622*3b2bd0f6Slogwang typedef	int	ng_item_fn2(node_p node, struct ng_item *item, hook_p hook);
623*3b2bd0f6Slogwang typedef	void	ng_apply_t(void *context, int error);
624*3b2bd0f6Slogwang struct ng_apply_info {
625*3b2bd0f6Slogwang 	ng_apply_t	*apply;
626*3b2bd0f6Slogwang 	void		*context;
627*3b2bd0f6Slogwang 	int		refs;
628*3b2bd0f6Slogwang 	int		error;
629*3b2bd0f6Slogwang };
630*3b2bd0f6Slogwang struct ng_item {
631*3b2bd0f6Slogwang 	u_long	el_flags;
632*3b2bd0f6Slogwang 	STAILQ_ENTRY(ng_item)	el_next;
633*3b2bd0f6Slogwang 	node_p	el_dest; /* The node it will be applied against (or NULL) */
634*3b2bd0f6Slogwang 	hook_p	el_hook; /* Entering hook. Optional in Control messages */
635*3b2bd0f6Slogwang 	union {
636*3b2bd0f6Slogwang 		struct mbuf	*da_m;
637*3b2bd0f6Slogwang 		struct {
638*3b2bd0f6Slogwang 			struct ng_mesg	*msg_msg;
639*3b2bd0f6Slogwang 			ng_ID_t		msg_retaddr;
640*3b2bd0f6Slogwang 		} msg;
641*3b2bd0f6Slogwang 		struct {
642*3b2bd0f6Slogwang 			union {
643*3b2bd0f6Slogwang 				ng_item_fn	*fn_fn;
644*3b2bd0f6Slogwang 				ng_item_fn2	*fn_fn2;
645*3b2bd0f6Slogwang 			} fn_fn;
646*3b2bd0f6Slogwang 			void 		*fn_arg1;
647*3b2bd0f6Slogwang 			int		fn_arg2;
648*3b2bd0f6Slogwang 		} fn;
649*3b2bd0f6Slogwang 	} body;
650*3b2bd0f6Slogwang 	/*
651*3b2bd0f6Slogwang 	 * Optional callback called when item is being applied,
652*3b2bd0f6Slogwang 	 * and its context.
653*3b2bd0f6Slogwang 	 */
654*3b2bd0f6Slogwang 	struct ng_apply_info	*apply;
655*3b2bd0f6Slogwang 	u_int	depth;
656*3b2bd0f6Slogwang #ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
657*3b2bd0f6Slogwang 	char *lastfile;
658*3b2bd0f6Slogwang 	int  lastline;
659*3b2bd0f6Slogwang 	TAILQ_ENTRY(ng_item)	  all;		/* all existing items */
660*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
661*3b2bd0f6Slogwang };
662*3b2bd0f6Slogwang 
663*3b2bd0f6Slogwang #define NGQF_TYPE	0x03		/* MASK of content definition */
664*3b2bd0f6Slogwang #define NGQF_MESG	0x00		/* the queue element is a message */
665*3b2bd0f6Slogwang #define NGQF_DATA	0x01		/* the queue element is data */
666*3b2bd0f6Slogwang #define NGQF_FN		0x02		/* the queue element is a function */
667*3b2bd0f6Slogwang #define NGQF_FN2	0x03		/* the queue element is a new function */
668*3b2bd0f6Slogwang 
669*3b2bd0f6Slogwang #define NGQF_RW		0x04		/* MASK for wanted queue mode */
670*3b2bd0f6Slogwang #define NGQF_READER	0x04		/* wants to be a reader */
671*3b2bd0f6Slogwang #define NGQF_WRITER	0x00		/* wants to be a writer */
672*3b2bd0f6Slogwang 
673*3b2bd0f6Slogwang #define NGQF_QMODE	0x08		/* MASK for how it was queued */
674*3b2bd0f6Slogwang #define NGQF_QREADER	0x08		/* was queued as a reader */
675*3b2bd0f6Slogwang #define NGQF_QWRITER	0x00		/* was queued as a writer */
676*3b2bd0f6Slogwang 
677*3b2bd0f6Slogwang /*
678*3b2bd0f6Slogwang  * Get the mbuf (etc) out of an item.
679*3b2bd0f6Slogwang  * Sets the value in the item to NULL in case we need to call NG_FREE_ITEM()
680*3b2bd0f6Slogwang  * with it, (to avoid freeing the things twice).
681*3b2bd0f6Slogwang  * If you don't want to zero out the item then realise that the
682*3b2bd0f6Slogwang  * item still owns it.
683*3b2bd0f6Slogwang  * Retaddr is different. There are no references on that. It's just a number.
684*3b2bd0f6Slogwang  * The debug versions must be either all used everywhere or not at all.
685*3b2bd0f6Slogwang  */
686*3b2bd0f6Slogwang 
687*3b2bd0f6Slogwang #define _NGI_M(i) ((i)->body.da_m)
688*3b2bd0f6Slogwang #define _NGI_MSG(i) ((i)->body.msg.msg_msg)
689*3b2bd0f6Slogwang #define _NGI_RETADDR(i) ((i)->body.msg.msg_retaddr)
690*3b2bd0f6Slogwang #define	_NGI_FN(i) ((i)->body.fn.fn_fn.fn_fn)
691*3b2bd0f6Slogwang #define	_NGI_FN2(i) ((i)->body.fn.fn_fn.fn_fn2)
692*3b2bd0f6Slogwang #define	_NGI_ARG1(i) ((i)->body.fn.fn_arg1)
693*3b2bd0f6Slogwang #define	_NGI_ARG2(i) ((i)->body.fn.fn_arg2)
694*3b2bd0f6Slogwang #define	_NGI_NODE(i) ((i)->el_dest)
695*3b2bd0f6Slogwang #define	_NGI_HOOK(i) ((i)->el_hook)
696*3b2bd0f6Slogwang #define	_NGI_SET_HOOK(i,h) do { _NGI_HOOK(i) = h; h = NULL;} while (0)
697*3b2bd0f6Slogwang #define	_NGI_CLR_HOOK(i)   do {						\
698*3b2bd0f6Slogwang 		hook_p _hook = _NGI_HOOK(i);				\
699*3b2bd0f6Slogwang 		if (_hook) {						\
700*3b2bd0f6Slogwang 			_NG_HOOK_UNREF(_hook);				\
701*3b2bd0f6Slogwang 			_NGI_HOOK(i) = NULL;				\
702*3b2bd0f6Slogwang 		}							\
703*3b2bd0f6Slogwang 	} while (0)
704*3b2bd0f6Slogwang #define	_NGI_SET_NODE(i,n) do { _NGI_NODE(i) = n; n = NULL;} while (0)
705*3b2bd0f6Slogwang #define	_NGI_CLR_NODE(i)   do {						\
706*3b2bd0f6Slogwang 		node_p _node = _NGI_NODE(i);				\
707*3b2bd0f6Slogwang 		if (_node) {						\
708*3b2bd0f6Slogwang 			_NG_NODE_UNREF(_node);				\
709*3b2bd0f6Slogwang 			_NGI_NODE(i) = NULL;				\
710*3b2bd0f6Slogwang 		}							\
711*3b2bd0f6Slogwang 	} while (0)
712*3b2bd0f6Slogwang 
713*3b2bd0f6Slogwang #ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
714*3b2bd0f6Slogwang void				dumpitem(item_p item, char *file, int line);
715*3b2bd0f6Slogwang static __inline void		_ngi_check(item_p item, char *file, int line) ;
716*3b2bd0f6Slogwang static __inline struct mbuf **	_ngi_m(item_p item, char *file, int line) ;
717*3b2bd0f6Slogwang static __inline ng_ID_t *	_ngi_retaddr(item_p item, char *file, int line);
718*3b2bd0f6Slogwang static __inline struct ng_mesg ** _ngi_msg(item_p item, char *file, int line) ;
719*3b2bd0f6Slogwang static __inline ng_item_fn **	_ngi_fn(item_p item, char *file, int line) ;
720*3b2bd0f6Slogwang static __inline ng_item_fn2 **	_ngi_fn2(item_p item, char *file, int line) ;
721*3b2bd0f6Slogwang static __inline void **		_ngi_arg1(item_p item, char *file, int line) ;
722*3b2bd0f6Slogwang static __inline int *		_ngi_arg2(item_p item, char *file, int line) ;
723*3b2bd0f6Slogwang static __inline node_p		_ngi_node(item_p item, char *file, int line);
724*3b2bd0f6Slogwang static __inline hook_p		_ngi_hook(item_p item, char *file, int line);
725*3b2bd0f6Slogwang 
726*3b2bd0f6Slogwang static __inline void
_ngi_check(item_p item,char * file,int line)727*3b2bd0f6Slogwang _ngi_check(item_p item, char *file, int line)
728*3b2bd0f6Slogwang {
729*3b2bd0f6Slogwang 	(item)->lastline = line;
730*3b2bd0f6Slogwang 	(item)->lastfile = file;
731*3b2bd0f6Slogwang }
732*3b2bd0f6Slogwang 
733*3b2bd0f6Slogwang static __inline struct mbuf **
_ngi_m(item_p item,char * file,int line)734*3b2bd0f6Slogwang _ngi_m(item_p item, char *file, int line)
735*3b2bd0f6Slogwang {
736*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
737*3b2bd0f6Slogwang 	return (&_NGI_M(item));
738*3b2bd0f6Slogwang }
739*3b2bd0f6Slogwang 
740*3b2bd0f6Slogwang static __inline struct ng_mesg **
_ngi_msg(item_p item,char * file,int line)741*3b2bd0f6Slogwang _ngi_msg(item_p item, char *file, int line)
742*3b2bd0f6Slogwang {
743*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
744*3b2bd0f6Slogwang 	return (&_NGI_MSG(item));
745*3b2bd0f6Slogwang }
746*3b2bd0f6Slogwang 
747*3b2bd0f6Slogwang static __inline ng_ID_t *
_ngi_retaddr(item_p item,char * file,int line)748*3b2bd0f6Slogwang _ngi_retaddr(item_p item, char *file, int line)
749*3b2bd0f6Slogwang {
750*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
751*3b2bd0f6Slogwang 	return (&_NGI_RETADDR(item));
752*3b2bd0f6Slogwang }
753*3b2bd0f6Slogwang 
754*3b2bd0f6Slogwang static __inline ng_item_fn **
_ngi_fn(item_p item,char * file,int line)755*3b2bd0f6Slogwang _ngi_fn(item_p item, char *file, int line)
756*3b2bd0f6Slogwang {
757*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
758*3b2bd0f6Slogwang 	return (&_NGI_FN(item));
759*3b2bd0f6Slogwang }
760*3b2bd0f6Slogwang 
761*3b2bd0f6Slogwang static __inline ng_item_fn2 **
_ngi_fn2(item_p item,char * file,int line)762*3b2bd0f6Slogwang _ngi_fn2(item_p item, char *file, int line)
763*3b2bd0f6Slogwang {
764*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
765*3b2bd0f6Slogwang 	return (&_NGI_FN2(item));
766*3b2bd0f6Slogwang }
767*3b2bd0f6Slogwang 
768*3b2bd0f6Slogwang static __inline void **
_ngi_arg1(item_p item,char * file,int line)769*3b2bd0f6Slogwang _ngi_arg1(item_p item, char *file, int line)
770*3b2bd0f6Slogwang {
771*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
772*3b2bd0f6Slogwang 	return (&_NGI_ARG1(item));
773*3b2bd0f6Slogwang }
774*3b2bd0f6Slogwang 
775*3b2bd0f6Slogwang static __inline int *
_ngi_arg2(item_p item,char * file,int line)776*3b2bd0f6Slogwang _ngi_arg2(item_p item, char *file, int line)
777*3b2bd0f6Slogwang {
778*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
779*3b2bd0f6Slogwang 	return (&_NGI_ARG2(item));
780*3b2bd0f6Slogwang }
781*3b2bd0f6Slogwang 
782*3b2bd0f6Slogwang static __inline node_p
_ngi_node(item_p item,char * file,int line)783*3b2bd0f6Slogwang _ngi_node(item_p item, char *file, int line)
784*3b2bd0f6Slogwang {
785*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
786*3b2bd0f6Slogwang 	return (_NGI_NODE(item));
787*3b2bd0f6Slogwang }
788*3b2bd0f6Slogwang 
789*3b2bd0f6Slogwang static __inline hook_p
_ngi_hook(item_p item,char * file,int line)790*3b2bd0f6Slogwang _ngi_hook(item_p item, char *file, int line)
791*3b2bd0f6Slogwang {
792*3b2bd0f6Slogwang 	_ngi_check(item, file, line);
793*3b2bd0f6Slogwang 	return (_NGI_HOOK(item));
794*3b2bd0f6Slogwang }
795*3b2bd0f6Slogwang 
796*3b2bd0f6Slogwang #define NGI_M(i)	(*_ngi_m(i, _NN_))
797*3b2bd0f6Slogwang #define NGI_MSG(i)	(*_ngi_msg(i, _NN_))
798*3b2bd0f6Slogwang #define NGI_RETADDR(i)	(*_ngi_retaddr(i, _NN_))
799*3b2bd0f6Slogwang #define NGI_FN(i)	(*_ngi_fn(i, _NN_))
800*3b2bd0f6Slogwang #define NGI_FN2(i)	(*_ngi_fn2(i, _NN_))
801*3b2bd0f6Slogwang #define NGI_ARG1(i)	(*_ngi_arg1(i, _NN_))
802*3b2bd0f6Slogwang #define NGI_ARG2(i)	(*_ngi_arg2(i, _NN_))
803*3b2bd0f6Slogwang #define NGI_HOOK(i)	_ngi_hook(i, _NN_)
804*3b2bd0f6Slogwang #define NGI_NODE(i)	_ngi_node(i, _NN_)
805*3b2bd0f6Slogwang #define	NGI_SET_HOOK(i,h)						\
806*3b2bd0f6Slogwang 	do { _ngi_check(i, _NN_); _NGI_SET_HOOK(i, h); } while (0)
807*3b2bd0f6Slogwang #define	NGI_CLR_HOOK(i)							\
808*3b2bd0f6Slogwang 	do { _ngi_check(i, _NN_); _NGI_CLR_HOOK(i); } while (0)
809*3b2bd0f6Slogwang #define	NGI_SET_NODE(i,n)						\
810*3b2bd0f6Slogwang 	do { _ngi_check(i, _NN_); _NGI_SET_NODE(i, n); } while (0)
811*3b2bd0f6Slogwang #define	NGI_CLR_NODE(i)							\
812*3b2bd0f6Slogwang 	do { _ngi_check(i, _NN_); _NGI_CLR_NODE(i); } while (0)
813*3b2bd0f6Slogwang 
814*3b2bd0f6Slogwang #define NG_FREE_ITEM(item)						\
815*3b2bd0f6Slogwang 	do {								\
816*3b2bd0f6Slogwang 		_ngi_check(item, _NN_);					\
817*3b2bd0f6Slogwang 		ng_free_item((item));					\
818*3b2bd0f6Slogwang 	} while (0)
819*3b2bd0f6Slogwang 
820*3b2bd0f6Slogwang #define	SAVE_LINE(item)							\
821*3b2bd0f6Slogwang 	do {								\
822*3b2bd0f6Slogwang 		(item)->lastline = __LINE__;				\
823*3b2bd0f6Slogwang 		(item)->lastfile = __FILE__;				\
824*3b2bd0f6Slogwang 	} while (0)
825*3b2bd0f6Slogwang 
826*3b2bd0f6Slogwang #else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
827*3b2bd0f6Slogwang 
828*3b2bd0f6Slogwang #define NGI_M(i)	_NGI_M(i)
829*3b2bd0f6Slogwang #define NGI_MSG(i)	_NGI_MSG(i)
830*3b2bd0f6Slogwang #define NGI_RETADDR(i)	_NGI_RETADDR(i)
831*3b2bd0f6Slogwang #define NGI_FN(i)	_NGI_FN(i)
832*3b2bd0f6Slogwang #define NGI_FN2(i)	_NGI_FN2(i)
833*3b2bd0f6Slogwang #define NGI_ARG1(i)	_NGI_ARG1(i)
834*3b2bd0f6Slogwang #define NGI_ARG2(i)	_NGI_ARG2(i)
835*3b2bd0f6Slogwang #define	NGI_NODE(i)	_NGI_NODE(i)
836*3b2bd0f6Slogwang #define	NGI_HOOK(i)	_NGI_HOOK(i)
837*3b2bd0f6Slogwang #define	NGI_SET_HOOK(i,h) _NGI_SET_HOOK(i,h)
838*3b2bd0f6Slogwang #define	NGI_CLR_HOOK(i)	  _NGI_CLR_HOOK(i)
839*3b2bd0f6Slogwang #define	NGI_SET_NODE(i,n) _NGI_SET_NODE(i,n)
840*3b2bd0f6Slogwang #define	NGI_CLR_NODE(i)	  _NGI_CLR_NODE(i)
841*3b2bd0f6Slogwang 
842*3b2bd0f6Slogwang #define	NG_FREE_ITEM(item)	ng_free_item((item))
843*3b2bd0f6Slogwang #define	SAVE_LINE(item)		do {} while (0)
844*3b2bd0f6Slogwang 
845*3b2bd0f6Slogwang #endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
846*3b2bd0f6Slogwang 
847*3b2bd0f6Slogwang #define NGI_GET_M(i,m)							\
848*3b2bd0f6Slogwang 	do {								\
849*3b2bd0f6Slogwang 		(m) = NGI_M(i);						\
850*3b2bd0f6Slogwang 		_NGI_M(i) = NULL;					\
851*3b2bd0f6Slogwang 	} while (0)
852*3b2bd0f6Slogwang 
853*3b2bd0f6Slogwang #define NGI_GET_MSG(i,m)						\
854*3b2bd0f6Slogwang 	do {								\
855*3b2bd0f6Slogwang 		(m) = NGI_MSG(i);					\
856*3b2bd0f6Slogwang 		_NGI_MSG(i) = NULL;					\
857*3b2bd0f6Slogwang 	} while (0)
858*3b2bd0f6Slogwang 
859*3b2bd0f6Slogwang #define NGI_GET_NODE(i,n)	/* YOU NOW HAVE THE REFERENCE */	\
860*3b2bd0f6Slogwang 	do {								\
861*3b2bd0f6Slogwang 		(n) = NGI_NODE(i);					\
862*3b2bd0f6Slogwang 		_NGI_NODE(i) = NULL;					\
863*3b2bd0f6Slogwang 	} while (0)
864*3b2bd0f6Slogwang 
865*3b2bd0f6Slogwang #define NGI_GET_HOOK(i,h)						\
866*3b2bd0f6Slogwang 	do {								\
867*3b2bd0f6Slogwang 		(h) = NGI_HOOK(i);					\
868*3b2bd0f6Slogwang 		_NGI_HOOK(i) = NULL;					\
869*3b2bd0f6Slogwang 	} while (0)
870*3b2bd0f6Slogwang 
871*3b2bd0f6Slogwang #define NGI_SET_WRITER(i)	((i)->el_flags &= ~NGQF_QMODE)
872*3b2bd0f6Slogwang #define NGI_SET_READER(i)	((i)->el_flags |= NGQF_QREADER)
873*3b2bd0f6Slogwang 
874*3b2bd0f6Slogwang #define NGI_QUEUED_READER(i)	((i)->el_flags & NGQF_QREADER)
875*3b2bd0f6Slogwang #define NGI_QUEUED_WRITER(i)	(((i)->el_flags & NGQF_QMODE) == NGQF_QWRITER)
876*3b2bd0f6Slogwang 
877*3b2bd0f6Slogwang /**********************************************************************
878*3b2bd0f6Slogwang * Data macros.  Send, manipulate and free.
879*3b2bd0f6Slogwang **********************************************************************/
880*3b2bd0f6Slogwang /*
881*3b2bd0f6Slogwang  * Assuming the data is already ok, just set the new address and send
882*3b2bd0f6Slogwang  */
883*3b2bd0f6Slogwang #define NG_FWD_ITEM_HOOK_FLAGS(error, item, hook, flags)		\
884*3b2bd0f6Slogwang 	do {								\
885*3b2bd0f6Slogwang 		(error) =						\
886*3b2bd0f6Slogwang 		    ng_address_hook(NULL, (item), (hook), NG_NOFLAGS);	\
887*3b2bd0f6Slogwang 		if (error == 0) {					\
888*3b2bd0f6Slogwang 			SAVE_LINE(item);				\
889*3b2bd0f6Slogwang 			(error) = ng_snd_item((item), (flags));		\
890*3b2bd0f6Slogwang 		}							\
891*3b2bd0f6Slogwang 		(item) = NULL;						\
892*3b2bd0f6Slogwang 	} while (0)
893*3b2bd0f6Slogwang #define	NG_FWD_ITEM_HOOK(error, item, hook)	\
894*3b2bd0f6Slogwang 		NG_FWD_ITEM_HOOK_FLAGS(error, item, hook, NG_NOFLAGS)
895*3b2bd0f6Slogwang 
896*3b2bd0f6Slogwang /*
897*3b2bd0f6Slogwang  * Forward a data packet. Mbuf pointer is updated to new value. We
898*3b2bd0f6Slogwang  * presume you dealt with the old one when you update it to the new one
899*3b2bd0f6Slogwang  * (or it maybe the old one). We got a packet and possibly had to modify
900*3b2bd0f6Slogwang  * the mbuf. You should probably use NGI_GET_M() if you are going to use
901*3b2bd0f6Slogwang  * this too.
902*3b2bd0f6Slogwang  */
903*3b2bd0f6Slogwang #define NG_FWD_NEW_DATA_FLAGS(error, item, hook, m, flags)		\
904*3b2bd0f6Slogwang 	do {								\
905*3b2bd0f6Slogwang 		NGI_M(item) = (m);					\
906*3b2bd0f6Slogwang 		(m) = NULL;						\
907*3b2bd0f6Slogwang 		NG_FWD_ITEM_HOOK_FLAGS(error, item, hook, flags);	\
908*3b2bd0f6Slogwang 	} while (0)
909*3b2bd0f6Slogwang #define	NG_FWD_NEW_DATA(error, item, hook, m)	\
910*3b2bd0f6Slogwang 		NG_FWD_NEW_DATA_FLAGS(error, item, hook, m, NG_NOFLAGS)
911*3b2bd0f6Slogwang 
912*3b2bd0f6Slogwang /* Send a previously unpackaged mbuf. XXX: This should be called
913*3b2bd0f6Slogwang  * NG_SEND_DATA in future, but this name is kept for compatibility
914*3b2bd0f6Slogwang  * reasons.
915*3b2bd0f6Slogwang  */
916*3b2bd0f6Slogwang #define NG_SEND_DATA_FLAGS(error, hook, m, flags)			\
917*3b2bd0f6Slogwang 	do {								\
918*3b2bd0f6Slogwang 		item_p _item;						\
919*3b2bd0f6Slogwang 		if ((_item = ng_package_data((m), flags))) {		\
920*3b2bd0f6Slogwang 			NG_FWD_ITEM_HOOK_FLAGS(error, _item, hook, flags);\
921*3b2bd0f6Slogwang 		} else {						\
922*3b2bd0f6Slogwang 			(error) = ENOMEM;				\
923*3b2bd0f6Slogwang 		}							\
924*3b2bd0f6Slogwang 		(m) = NULL;						\
925*3b2bd0f6Slogwang 	} while (0)
926*3b2bd0f6Slogwang 
927*3b2bd0f6Slogwang #define NG_SEND_DATA_ONLY(error, hook, m)	\
928*3b2bd0f6Slogwang 		NG_SEND_DATA_FLAGS(error, hook, m, NG_NOFLAGS)
929*3b2bd0f6Slogwang /* NG_SEND_DATA() compat for meta-data times */
930*3b2bd0f6Slogwang #define	NG_SEND_DATA(error, hook, m, x)	\
931*3b2bd0f6Slogwang 		NG_SEND_DATA_FLAGS(error, hook, m, NG_NOFLAGS)
932*3b2bd0f6Slogwang 
933*3b2bd0f6Slogwang #define NG_FREE_MSG(msg)						\
934*3b2bd0f6Slogwang 	do {								\
935*3b2bd0f6Slogwang 		if ((msg)) {						\
936*3b2bd0f6Slogwang 			free((msg), M_NETGRAPH_MSG);			\
937*3b2bd0f6Slogwang 			(msg) = NULL;					\
938*3b2bd0f6Slogwang 		}	 						\
939*3b2bd0f6Slogwang 	} while (0)
940*3b2bd0f6Slogwang 
941*3b2bd0f6Slogwang #define NG_FREE_M(m)							\
942*3b2bd0f6Slogwang 	do {								\
943*3b2bd0f6Slogwang 		if ((m)) {						\
944*3b2bd0f6Slogwang 			m_freem((m));					\
945*3b2bd0f6Slogwang 			(m) = NULL;					\
946*3b2bd0f6Slogwang 		}							\
947*3b2bd0f6Slogwang 	} while (0)
948*3b2bd0f6Slogwang 
949*3b2bd0f6Slogwang /*****************************************
950*3b2bd0f6Slogwang * Message macros
951*3b2bd0f6Slogwang *****************************************/
952*3b2bd0f6Slogwang 
953*3b2bd0f6Slogwang #define NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr)		\
954*3b2bd0f6Slogwang 	do {								\
955*3b2bd0f6Slogwang 		item_p _item;						\
956*3b2bd0f6Slogwang 		if ((_item = ng_package_msg(msg, NG_NOFLAGS)) == NULL) {\
957*3b2bd0f6Slogwang 			(msg) = NULL;					\
958*3b2bd0f6Slogwang 			(error) = ENOMEM;				\
959*3b2bd0f6Slogwang 			break;						\
960*3b2bd0f6Slogwang 		}							\
961*3b2bd0f6Slogwang 		if (((error) = ng_address_hook((here), (_item),		\
962*3b2bd0f6Slogwang 					(hook), (retaddr))) == 0) {	\
963*3b2bd0f6Slogwang 			SAVE_LINE(_item);				\
964*3b2bd0f6Slogwang 			(error) = ng_snd_item((_item), 0);		\
965*3b2bd0f6Slogwang 		}							\
966*3b2bd0f6Slogwang 		(msg) = NULL;						\
967*3b2bd0f6Slogwang 	} while (0)
968*3b2bd0f6Slogwang 
969*3b2bd0f6Slogwang #define NG_SEND_MSG_PATH(error, here, msg, path, retaddr)		\
970*3b2bd0f6Slogwang 	do {								\
971*3b2bd0f6Slogwang 		item_p _item;						\
972*3b2bd0f6Slogwang 		if ((_item = ng_package_msg(msg, NG_NOFLAGS)) == NULL) {\
973*3b2bd0f6Slogwang 			(msg) = NULL;					\
974*3b2bd0f6Slogwang 			(error) = ENOMEM;				\
975*3b2bd0f6Slogwang 			break;						\
976*3b2bd0f6Slogwang 		}							\
977*3b2bd0f6Slogwang 		if (((error) = ng_address_path((here), (_item),		\
978*3b2bd0f6Slogwang 					(path), (retaddr))) == 0) {	\
979*3b2bd0f6Slogwang 			SAVE_LINE(_item);				\
980*3b2bd0f6Slogwang 			(error) = ng_snd_item((_item), 0);		\
981*3b2bd0f6Slogwang 		}							\
982*3b2bd0f6Slogwang 		(msg) = NULL;						\
983*3b2bd0f6Slogwang 	} while (0)
984*3b2bd0f6Slogwang 
985*3b2bd0f6Slogwang #define NG_SEND_MSG_ID(error, here, msg, ID, retaddr)			\
986*3b2bd0f6Slogwang 	do {								\
987*3b2bd0f6Slogwang 		item_p _item;						\
988*3b2bd0f6Slogwang 		if ((_item = ng_package_msg(msg, NG_NOFLAGS)) == NULL) {\
989*3b2bd0f6Slogwang 			(msg) = NULL;					\
990*3b2bd0f6Slogwang 			(error) = ENOMEM;				\
991*3b2bd0f6Slogwang 			break;						\
992*3b2bd0f6Slogwang 		}							\
993*3b2bd0f6Slogwang 		if (((error) = ng_address_ID((here), (_item),		\
994*3b2bd0f6Slogwang 					(ID), (retaddr))) == 0) {	\
995*3b2bd0f6Slogwang 			SAVE_LINE(_item);				\
996*3b2bd0f6Slogwang 			(error) = ng_snd_item((_item), 0);		\
997*3b2bd0f6Slogwang 		}							\
998*3b2bd0f6Slogwang 		(msg) = NULL;						\
999*3b2bd0f6Slogwang 	} while (0)
1000*3b2bd0f6Slogwang 
1001*3b2bd0f6Slogwang /*
1002*3b2bd0f6Slogwang  * Redirect the message to the next hop using the given hook.
1003*3b2bd0f6Slogwang  * ng_retarget_msg() frees the item if there is an error
1004*3b2bd0f6Slogwang  * and returns an error code.  It returns 0 on success.
1005*3b2bd0f6Slogwang  */
1006*3b2bd0f6Slogwang #define NG_FWD_MSG_HOOK(error, here, item, hook, retaddr)		\
1007*3b2bd0f6Slogwang 	do {								\
1008*3b2bd0f6Slogwang 		if (((error) = ng_address_hook((here), (item),		\
1009*3b2bd0f6Slogwang 					(hook), (retaddr))) == 0) {	\
1010*3b2bd0f6Slogwang 			SAVE_LINE(item);				\
1011*3b2bd0f6Slogwang 			(error) = ng_snd_item((item), 0);		\
1012*3b2bd0f6Slogwang 		}							\
1013*3b2bd0f6Slogwang 		(item) = NULL;						\
1014*3b2bd0f6Slogwang 	} while (0)
1015*3b2bd0f6Slogwang 
1016*3b2bd0f6Slogwang /*
1017*3b2bd0f6Slogwang  * Send a queue item back to it's originator with a response message.
1018*3b2bd0f6Slogwang  * Assume original message was removed and freed separatly.
1019*3b2bd0f6Slogwang  */
1020*3b2bd0f6Slogwang #define NG_RESPOND_MSG(error, here, item, resp)				\
1021*3b2bd0f6Slogwang 	do {								\
1022*3b2bd0f6Slogwang 		if (resp) {						\
1023*3b2bd0f6Slogwang 			ng_ID_t _dest = NGI_RETADDR(item);		\
1024*3b2bd0f6Slogwang 			NGI_RETADDR(item) = 0;				\
1025*3b2bd0f6Slogwang 			NGI_MSG(item) = resp;				\
1026*3b2bd0f6Slogwang 			if ((error = ng_address_ID((here), (item),	\
1027*3b2bd0f6Slogwang 					_dest, 0)) == 0) {		\
1028*3b2bd0f6Slogwang 				SAVE_LINE(item);			\
1029*3b2bd0f6Slogwang 				(error) = ng_snd_item((item), NG_QUEUE);\
1030*3b2bd0f6Slogwang 			}						\
1031*3b2bd0f6Slogwang 		} else							\
1032*3b2bd0f6Slogwang 			NG_FREE_ITEM(item);				\
1033*3b2bd0f6Slogwang 		(item) = NULL;						\
1034*3b2bd0f6Slogwang 	} while (0)
1035*3b2bd0f6Slogwang 
1036*3b2bd0f6Slogwang 
1037*3b2bd0f6Slogwang /***********************************************************************
1038*3b2bd0f6Slogwang  ******** Structures Definitions and Macros for defining a node  *******
1039*3b2bd0f6Slogwang  ***********************************************************************
1040*3b2bd0f6Slogwang  *
1041*3b2bd0f6Slogwang  * Here we define the structures needed to actually define a new node
1042*3b2bd0f6Slogwang  * type.
1043*3b2bd0f6Slogwang  */
1044*3b2bd0f6Slogwang 
1045*3b2bd0f6Slogwang /*
1046*3b2bd0f6Slogwang  * Command list -- each node type specifies the command that it knows
1047*3b2bd0f6Slogwang  * how to convert between ASCII and binary using an array of these.
1048*3b2bd0f6Slogwang  * The last element in the array must be a terminator with cookie=0.
1049*3b2bd0f6Slogwang  */
1050*3b2bd0f6Slogwang 
1051*3b2bd0f6Slogwang struct ng_cmdlist {
1052*3b2bd0f6Slogwang 	u_int32_t			cookie;		/* command typecookie */
1053*3b2bd0f6Slogwang 	int				cmd;		/* command number */
1054*3b2bd0f6Slogwang 	const char			*name;		/* command name */
1055*3b2bd0f6Slogwang 	const struct ng_parse_type	*mesgType;	/* args if !NGF_RESP */
1056*3b2bd0f6Slogwang 	const struct ng_parse_type	*respType;	/* args if NGF_RESP */
1057*3b2bd0f6Slogwang };
1058*3b2bd0f6Slogwang 
1059*3b2bd0f6Slogwang /*
1060*3b2bd0f6Slogwang  * Structure of a node type
1061*3b2bd0f6Slogwang  * If data is sent to the "rcvdata()" entrypoint then the system
1062*3b2bd0f6Slogwang  * may decide to defer it until later by queing it with the normal netgraph
1063*3b2bd0f6Slogwang  * input queuing system.  This is decidde by the HK_QUEUE flag being set in
1064*3b2bd0f6Slogwang  * the flags word of the peer (receiving) hook. The dequeuing mechanism will
1065*3b2bd0f6Slogwang  * ensure it is not requeued again.
1066*3b2bd0f6Slogwang  * Note the input queueing system is to allow modules
1067*3b2bd0f6Slogwang  * to 'release the stack' or to pass data across spl layers.
1068*3b2bd0f6Slogwang  * The data will be redelivered as soon as the NETISR code runs
1069*3b2bd0f6Slogwang  * which may be almost immediately.  A node may also do it's own queueing
1070*3b2bd0f6Slogwang  * for other reasons (e.g. device output queuing).
1071*3b2bd0f6Slogwang  */
1072*3b2bd0f6Slogwang struct ng_type {
1073*3b2bd0f6Slogwang 
1074*3b2bd0f6Slogwang 	u_int32_t	version; 	/* must equal NG_API_VERSION */
1075*3b2bd0f6Slogwang 	const char	*name;		/* Unique type name */
1076*3b2bd0f6Slogwang 	modeventhand_t	mod_event;	/* Module event handler (optional) */
1077*3b2bd0f6Slogwang 	ng_constructor_t *constructor;	/* Node constructor */
1078*3b2bd0f6Slogwang 	ng_rcvmsg_t	*rcvmsg;	/* control messages come here */
1079*3b2bd0f6Slogwang 	ng_close_t	*close;		/* warn about forthcoming shutdown */
1080*3b2bd0f6Slogwang 	ng_shutdown_t	*shutdown;	/* reset, and free resources */
1081*3b2bd0f6Slogwang 	ng_newhook_t	*newhook;	/* first notification of new hook */
1082*3b2bd0f6Slogwang 	ng_findhook_t	*findhook;	/* only if you have lots of hooks */
1083*3b2bd0f6Slogwang 	ng_connect_t	*connect;	/* final notification of new hook */
1084*3b2bd0f6Slogwang 	ng_rcvdata_t	*rcvdata;	/* data comes here */
1085*3b2bd0f6Slogwang 	ng_disconnect_t	*disconnect;	/* notify on disconnect */
1086*3b2bd0f6Slogwang 
1087*3b2bd0f6Slogwang 	const struct	ng_cmdlist *cmdlist;	/* commands we can convert */
1088*3b2bd0f6Slogwang 
1089*3b2bd0f6Slogwang 	/* R/W data private to the base netgraph code DON'T TOUCH! */
1090*3b2bd0f6Slogwang 	LIST_ENTRY(ng_type) types;		/* linked list of all types */
1091*3b2bd0f6Slogwang 	int		    refs;		/* number of instances */
1092*3b2bd0f6Slogwang };
1093*3b2bd0f6Slogwang 
1094*3b2bd0f6Slogwang /*
1095*3b2bd0f6Slogwang  * Use the NETGRAPH_INIT() macro to link a node type into the
1096*3b2bd0f6Slogwang  * netgraph system. This works for types compiled into the kernel
1097*3b2bd0f6Slogwang  * as well as KLD modules. The first argument should be the type
1098*3b2bd0f6Slogwang  * name (eg, echo) and the second a pointer to the type struct.
1099*3b2bd0f6Slogwang  *
1100*3b2bd0f6Slogwang  * If a different link time is desired, e.g., a device driver that
1101*3b2bd0f6Slogwang  * needs to install its netgraph type before probing, use the
1102*3b2bd0f6Slogwang  * NETGRAPH_INIT_ORDERED() macro instead.  Device drivers probably
1103*3b2bd0f6Slogwang  * want to use SI_SUB_DRIVERS/SI_ORDER_FIRST.
1104*3b2bd0f6Slogwang  */
1105*3b2bd0f6Slogwang 
1106*3b2bd0f6Slogwang #define NETGRAPH_INIT_ORDERED(typename, typestructp, sub, order)	\
1107*3b2bd0f6Slogwang static moduledata_t ng_##typename##_mod = {				\
1108*3b2bd0f6Slogwang 	"ng_" #typename,						\
1109*3b2bd0f6Slogwang 	ng_mod_event,							\
1110*3b2bd0f6Slogwang 	(typestructp)							\
1111*3b2bd0f6Slogwang };									\
1112*3b2bd0f6Slogwang DECLARE_MODULE(ng_##typename, ng_##typename##_mod, sub, order);		\
1113*3b2bd0f6Slogwang MODULE_DEPEND(ng_##typename, netgraph,	NG_ABI_VERSION,			\
1114*3b2bd0f6Slogwang 					NG_ABI_VERSION,			\
1115*3b2bd0f6Slogwang 					NG_ABI_VERSION)
1116*3b2bd0f6Slogwang 
1117*3b2bd0f6Slogwang #define NETGRAPH_INIT(tn, tp)						\
1118*3b2bd0f6Slogwang 	NETGRAPH_INIT_ORDERED(tn, tp, SI_SUB_PSEUDO, SI_ORDER_MIDDLE)
1119*3b2bd0f6Slogwang 
1120*3b2bd0f6Slogwang /* Special malloc() type for netgraph structs and ctrl messages */
1121*3b2bd0f6Slogwang /* Only these two types should be visible to nodes */
1122*3b2bd0f6Slogwang MALLOC_DECLARE(M_NETGRAPH);
1123*3b2bd0f6Slogwang MALLOC_DECLARE(M_NETGRAPH_MSG);
1124*3b2bd0f6Slogwang 
1125*3b2bd0f6Slogwang /* declare the base of the netgraph sysclt hierarchy */
1126*3b2bd0f6Slogwang /* but only if this file cares about sysctls */
1127*3b2bd0f6Slogwang #ifdef	SYSCTL_DECL
1128*3b2bd0f6Slogwang SYSCTL_DECL(_net_graph);
1129*3b2bd0f6Slogwang #endif
1130*3b2bd0f6Slogwang 
1131*3b2bd0f6Slogwang /*
1132*3b2bd0f6Slogwang  * Methods that the nodes can use.
1133*3b2bd0f6Slogwang  * Many of these methods should usually NOT be used directly but via
1134*3b2bd0f6Slogwang  * Macros above.
1135*3b2bd0f6Slogwang  */
1136*3b2bd0f6Slogwang int	ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr);
1137*3b2bd0f6Slogwang int	ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr);
1138*3b2bd0f6Slogwang int	ng_address_path(node_p here, item_p item, const char *address, ng_ID_t raddr);
1139*3b2bd0f6Slogwang int	ng_bypass(hook_p hook1, hook_p hook2);
1140*3b2bd0f6Slogwang hook_p	ng_findhook(node_p node, const char *name);
1141*3b2bd0f6Slogwang struct	ng_type *ng_findtype(const char *type);
1142*3b2bd0f6Slogwang int	ng_make_node_common(struct ng_type *typep, node_p *nodep);
1143*3b2bd0f6Slogwang int	ng_name_node(node_p node, const char *name);
1144*3b2bd0f6Slogwang node_p	ng_name2noderef(node_p node, const char *name);
1145*3b2bd0f6Slogwang int	ng_newtype(struct ng_type *tp);
1146*3b2bd0f6Slogwang ng_ID_t ng_node2ID(node_p node);
1147*3b2bd0f6Slogwang item_p	ng_package_data(struct mbuf *m, int flags);
1148*3b2bd0f6Slogwang item_p	ng_package_msg(struct ng_mesg *msg, int flags);
1149*3b2bd0f6Slogwang item_p	ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg);
1150*3b2bd0f6Slogwang void	ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr);
1151*3b2bd0f6Slogwang int	ng_rmhook_self(hook_p hook);	/* if a node wants to kill a hook */
1152*3b2bd0f6Slogwang int	ng_rmnode_self(node_p here);	/* if a node wants to suicide */
1153*3b2bd0f6Slogwang int	ng_rmtype(struct ng_type *tp);
1154*3b2bd0f6Slogwang int	ng_snd_item(item_p item, int queue);
1155*3b2bd0f6Slogwang int 	ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, void *arg1,
1156*3b2bd0f6Slogwang 	int arg2);
1157*3b2bd0f6Slogwang int 	ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void *arg1,
1158*3b2bd0f6Slogwang 	int arg2, int flags);
1159*3b2bd0f6Slogwang int 	ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn,
1160*3b2bd0f6Slogwang 	void *arg1, int arg2, int flags);
1161*3b2bd0f6Slogwang int	ng_uncallout(struct callout *c, node_p node);
1162*3b2bd0f6Slogwang int	ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
1163*3b2bd0f6Slogwang 	    ng_item_fn *fn, void * arg1, int arg2);
1164*3b2bd0f6Slogwang #define	ng_callout_init(c)	callout_init(c, 1)
1165*3b2bd0f6Slogwang 
1166*3b2bd0f6Slogwang /* Flags for netgraph functions. */
1167*3b2bd0f6Slogwang #define	NG_NOFLAGS	0x00000000	/* no special options */
1168*3b2bd0f6Slogwang #define	NG_QUEUE	0x00000001	/* enqueue item, don't dispatch */
1169*3b2bd0f6Slogwang #define	NG_WAITOK	0x00000002	/* use M_WAITOK, etc. */
1170*3b2bd0f6Slogwang /* XXXGL: NG_PROGRESS unused since ng_base.c rev. 1.136. Should be deleted? */
1171*3b2bd0f6Slogwang #define	NG_PROGRESS	0x00000004	/* return EINPROGRESS if queued */
1172*3b2bd0f6Slogwang #define	NG_REUSE_ITEM	0x00000008	/* supplied item should be reused */
1173*3b2bd0f6Slogwang 
1174*3b2bd0f6Slogwang /*
1175*3b2bd0f6Slogwang  * prototypes the user should DEFINITELY not use directly
1176*3b2bd0f6Slogwang  */
1177*3b2bd0f6Slogwang void	ng_free_item(item_p item); /* Use NG_FREE_ITEM instead */
1178*3b2bd0f6Slogwang int	ng_mod_event(module_t mod, int what, void *arg);
1179*3b2bd0f6Slogwang 
1180*3b2bd0f6Slogwang /*
1181*3b2bd0f6Slogwang  * Tag definitions and constants
1182*3b2bd0f6Slogwang  */
1183*3b2bd0f6Slogwang 
1184*3b2bd0f6Slogwang #define	NG_TAG_PRIO	1
1185*3b2bd0f6Slogwang 
1186*3b2bd0f6Slogwang struct ng_tag_prio {
1187*3b2bd0f6Slogwang 	struct m_tag	tag;
1188*3b2bd0f6Slogwang 	char	priority;
1189*3b2bd0f6Slogwang 	char	discardability;
1190*3b2bd0f6Slogwang };
1191*3b2bd0f6Slogwang 
1192*3b2bd0f6Slogwang #define	NG_PRIO_CUTOFF		32
1193*3b2bd0f6Slogwang #define	NG_PRIO_LINKSTATE	64
1194*3b2bd0f6Slogwang 
1195*3b2bd0f6Slogwang /* Macros and declarations to keep compatibility with metadata, which
1196*3b2bd0f6Slogwang  * is obsoleted now. To be deleted.
1197*3b2bd0f6Slogwang  */
1198*3b2bd0f6Slogwang typedef void *meta_p;
1199*3b2bd0f6Slogwang #define _NGI_META(i)	NULL
1200*3b2bd0f6Slogwang #define NGI_META(i)	NULL
1201*3b2bd0f6Slogwang #define NG_FREE_META(meta)
1202*3b2bd0f6Slogwang #define NGI_GET_META(i,m)
1203*3b2bd0f6Slogwang #define	ng_copy_meta(meta) NULL
1204*3b2bd0f6Slogwang 
1205*3b2bd0f6Slogwang /*
1206*3b2bd0f6Slogwang  * Mark the current thread when called from the outbound path of the
1207*3b2bd0f6Slogwang  * network stack, in order to enforce queuing on ng nodes calling into
1208*3b2bd0f6Slogwang  * the inbound network stack path.
1209*3b2bd0f6Slogwang  */
1210*3b2bd0f6Slogwang #define NG_OUTBOUND_THREAD_REF()					\
1211*3b2bd0f6Slogwang 	curthread->td_ng_outbound++
1212*3b2bd0f6Slogwang #define NG_OUTBOUND_THREAD_UNREF()					\
1213*3b2bd0f6Slogwang 	do {								\
1214*3b2bd0f6Slogwang 		curthread->td_ng_outbound--;				\
1215*3b2bd0f6Slogwang 		KASSERT(curthread->td_ng_outbound >= 0,			\
1216*3b2bd0f6Slogwang 		    ("%s: negative td_ng_outbound", __func__));		\
1217*3b2bd0f6Slogwang 	} while (0)
1218*3b2bd0f6Slogwang 
1219*3b2bd0f6Slogwang #endif /* _NETGRAPH_NETGRAPH_H_ */
1220