netgraph.h revision 314667
1339631Sphilip/*
2339631Sphilip * netgraph.h
3192886Sedwin */
4192886Sedwin
564499Swollman/*-
6273719Sedwin * Copyright (c) 1996-1999 Whistle Communications, Inc.
72742Swollman * All rights reserved.
8273719Sedwin *
9273719Sedwin * Subject to the following obligations and disclaimer of warranty, use and
102742Swollman * redistribution of this software, in source or object code forms, with or
11339631Sphilip * without modifications are expressly permitted by Whistle Communications;
122742Swollman * provided, however, that:
13274563Sedwin * 1. Any and all reproductions of the source or object code must include the
14158421Swollman *    copyright notice above and the following disclaimer of warranties; and
15158421Swollman * 2. No rights are granted, in any manner or form, to use Whistle
16274563Sedwin *    Communications, Inc. trademarks, including the mark "WHISTLE
172742Swollman *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18316350Sbapt *    such appears in the above copyright notice or in the software.
19316350Sbapt *
2020094Swollman * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
2120094Swollman * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22274563Sedwin * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23274563Sedwin * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
2420094Swollman * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
252742Swollman * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
262742Swollman * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
272742Swollman * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
282742Swollman * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29248307Sedwin * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30273719Sedwin * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31325160Sphilip * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32248307Sedwin * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33273719Sedwin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34273719Sedwin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35273719Sedwin * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36273719Sedwin * OF SUCH DAMAGE.
372742Swollman *
3858787Sru * Author: Julian Elischer <julian@freebsd.org>
392742Swollman *
40339631Sphilip * $FreeBSD: stable/10/sys/netgraph/netgraph.h 314667 2017-03-04 13:03:31Z avg $
41339631Sphilip * $Whistle: netgraph.h,v 1.29 1999/11/01 07:56:13 julian Exp $
42114173Swollman */
43114173Swollman
44114173Swollman#ifndef _NETGRAPH_NETGRAPH_H_
45114173Swollman#define _NETGRAPH_NETGRAPH_H_
46114173Swollman
47257697Sedwin#ifndef _KERNEL
48257697Sedwin#error "This file should not be included in user level programs"
49114173Swollman#endif
50339631Sphilip
51316350Sbapt#include <sys/queue.h>
52257697Sedwin#include <sys/lock.h>
53149590Swollman#include <sys/malloc.h>
54286751Sedwin#include <sys/module.h>
55270817Spluknet#include <sys/mutex.h>
56339631Sphilip#include <sys/refcount.h>
57316350Sbapt
58328476Sphilip#ifdef HAVE_KERNEL_OPTION_HEADERS
59316350Sbapt#include "opt_netgraph.h"
60316350Sbapt#include "opt_kdb.h"
612742Swollman#endif
62270817Spluknet
632742Swollman/* debugging options */
642742Swollman#define NG_SEPARATE_MALLOC	/* make modules use their own malloc types */
652742Swollman
662742Swollman/*
672742Swollman * This defines the in-kernel binary interface version.
68316350Sbapt * It is possible to change this but leave the external message
692742Swollman * API the same. Each type also has it's own cookies for versioning as well.
702742Swollman * Change it for NETGRAPH_DEBUG version so we cannot mix debug and non debug
712742Swollman * modules.
72270817Spluknet */
732742Swollman#define _NG_ABI_VERSION 12
7420094Swollman#ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
75158421Swollman#define NG_ABI_VERSION	(_NG_ABI_VERSION + 0x10000)
7620094Swollman#else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
77331663Sphilip#define NG_ABI_VERSION	_NG_ABI_VERSION
7820094Swollman#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
7920094Swollman
80331663Sphilip
8120094Swollman/*
82307362Sbapt * Forward references for the basic structures so we can
83331663Sphilip * define the typedefs and use them in the structures themselves.
84325160Sphilip */
852742Swollmanstruct ng_hook ;
862742Swollmanstruct ng_node ;
872742Swollmanstruct ng_item ;
882742Swollmantypedef	struct ng_item *item_p;
89316350Sbapttypedef struct ng_node *node_p;
90316350Sbapttypedef struct ng_hook *hook_p;
912742Swollman
922742Swollman/* node method definitions */
93158421Swollmantypedef	int	ng_constructor_t(node_p node);
94158421Swollmantypedef	int	ng_close_t(node_p node);
95158421Swollmantypedef	int	ng_shutdown_t(node_p node);
96158421Swollmantypedef	int	ng_newhook_t(node_p node, hook_p hook, const char *name);
97158421Swollmantypedef	hook_p	ng_findhook_t(node_p node, const char *name);
98153670Swollmantypedef	int	ng_connect_t(hook_p hook);
9943014Swollmantypedef	int	ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook);
10043014Swollmantypedef	int	ng_rcvdata_t(hook_p hook, item_p item);
10143014Swollmantypedef	int	ng_disconnect_t(hook_p hook);
102233445Sedwintypedef	int	ng_rcvitem (node_p node, hook_p hook, item_p item);
103233445Sedwin
104233445Sedwin/***********************************************************************
105233445Sedwin ***************** Hook Structure and Methods **************************
106233445Sedwin ***********************************************************************
107233445Sedwin *
108233445Sedwin * Structure of a hook
109233445Sedwin */
110240457Sedwinstruct ng_hook {
111233445Sedwin	char	hk_name[NG_HOOKSIZ];	/* what this node knows this link as */
112233445Sedwin	void   *hk_private;		/* node dependant ID for this hook */
113233445Sedwin	int	hk_flags;		/* info about this hook/link */
114233445Sedwin	int	hk_type;		/* tbd: hook data link type */
115233445Sedwin	struct	ng_hook *hk_peer;	/* the other end of this link */
116233445Sedwin	struct	ng_node *hk_node;	/* The node this hook is attached to */
117325160Sphilip	LIST_ENTRY(ng_hook) hk_hooks;	/* linked list of all hooks on node */
118331663Sphilip	ng_rcvmsg_t	*hk_rcvmsg;	/* control messages come here */
119325160Sphilip	ng_rcvdata_t	*hk_rcvdata;	/* data comes here */
1202742Swollman	int	hk_refs;		/* dont actually free this till 0 */
1212742Swollman#ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
122307362Sbapt#define HK_MAGIC 0x78573011
123307362Sbapt	int	hk_magic;
124307362Sbapt	char	*lastfile;
125307362Sbapt	int	lastline;
126325160Sphilip	SLIST_ENTRY(ng_hook)	  hk_all;		/* all existing items */
127325160Sphilip#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
1282742Swollman};
1292742Swollman/* Flags for a hook */
130307362Sbapt#define HK_INVALID		0x0001	/* don't trust it! */
131153670Swollman#define HK_QUEUE		0x0002	/* queue for later delivery */
132153670Swollman#define HK_FORCE_WRITER		0x0004	/* Incoming data queued as a writer */
133290698Sedwin#define HK_DEAD			0x0008	/* This is the dead hook.. don't free */
134290698Sedwin#define HK_HI_STACK		0x0010	/* Hook has hi stack usage */
135307362Sbapt#define HK_TO_INBOUND		0x0020	/* Hook on ntw. stack inbound path. */
136307362Sbapt
137307362Sbapt/*
138307362Sbapt * Public Methods for hook
139325160Sphilip * If you can't do it with these you probably shouldn;t be doing it.
140307362Sbapt */
141307362Sbaptvoid ng_unref_hook(hook_p hook); /* don't move this */
142307362Sbapt#define	_NG_HOOK_REF(hook)	refcount_acquire(&(hook)->hk_refs)
14343014Swollman#define _NG_HOOK_NAME(hook)	((hook)->hk_name)
144331663Sphilip#define _NG_HOOK_UNREF(hook)	ng_unref_hook(hook)
145307362Sbapt#define	_NG_HOOK_SET_PRIVATE(hook, val)	do {(hook)->hk_private = val;} while (0)
1462742Swollman#define	_NG_HOOK_SET_RCVMSG(hook, val)	do {(hook)->hk_rcvmsg = val;} while (0)
1472742Swollman#define	_NG_HOOK_SET_RCVDATA(hook, val)	do {(hook)->hk_rcvdata = val;} while (0)
148307362Sbapt#define	_NG_HOOK_PRIVATE(hook)	((hook)->hk_private)
149307362Sbapt#define _NG_HOOK_NOT_VALID(hook)	((hook)->hk_flags & HK_INVALID)
150307362Sbapt#define _NG_HOOK_IS_VALID(hook)	(!((hook)->hk_flags & HK_INVALID))
151307362Sbapt#define _NG_HOOK_NODE(hook)	((hook)->hk_node) /* only rvalue! */
152307362Sbapt#define _NG_HOOK_PEER(hook)	((hook)->hk_peer) /* only rvalue! */
153307362Sbapt#define _NG_HOOK_FORCE_WRITER(hook)				\
1542742Swollman		do { hook->hk_flags |= HK_FORCE_WRITER; } while (0)
1552742Swollman#define _NG_HOOK_FORCE_QUEUE(hook) do { hook->hk_flags |= HK_QUEUE; } while (0)
156279707Sedwin#define _NG_HOOK_SET_TO_INBOUND(hook)				\
1572742Swollman		do { hook->hk_flags |= HK_TO_INBOUND; } while (0)
1582742Swollman#define _NG_HOOK_HI_STACK(hook) do { hook->hk_flags |= HK_HI_STACK; } while (0)
159193785Sedwin
160193785Sedwin/* Some shortcuts */
161193785Sedwin#define NG_PEER_NODE(hook)	NG_HOOK_NODE(NG_HOOK_PEER(hook))
162193785Sedwin#define NG_PEER_HOOK_NAME(hook)	NG_HOOK_NAME(NG_HOOK_PEER(hook))
163193785Sedwin#define NG_PEER_NODE_NAME(hook)	NG_NODE_NAME(NG_PEER_NODE(hook))
164193785Sedwin
165193785Sedwin#ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
166193785Sedwin#define _NN_ __FILE__,__LINE__
167193785Sedwinvoid	dumphook (hook_p hook, char *file, int line);
168193785Sedwinstatic __inline void	_chkhook(hook_p hook, char *file, int line);
169193785Sedwinstatic __inline void	_ng_hook_ref(hook_p hook, char * file, int line);
170193785Sedwinstatic __inline char *	_ng_hook_name(hook_p hook, char * file, int line);
171193785Sedwinstatic __inline void	_ng_hook_unref(hook_p hook, char * file, int line);
172193785Sedwinstatic __inline void	_ng_hook_set_private(hook_p hook,
173193785Sedwin				void * val, char * file, int line);
174193785Sedwinstatic __inline void	_ng_hook_set_rcvmsg(hook_p hook,
175193785Sedwin				ng_rcvmsg_t *val, char * file, int line);
176193785Sedwinstatic __inline void	_ng_hook_set_rcvdata(hook_p hook,
177193785Sedwin				ng_rcvdata_t *val, char * file, int line);
178193785Sedwinstatic __inline void *	_ng_hook_private(hook_p hook, char * file, int line);
179193785Sedwinstatic __inline int	_ng_hook_not_valid(hook_p hook, char * file, int line);
180325160Sphilipstatic __inline int	_ng_hook_is_valid(hook_p hook, char * file, int line);
181193785Sedwinstatic __inline node_p	_ng_hook_node(hook_p hook, char * file, int line);
182193785Sedwinstatic __inline hook_p	_ng_hook_peer(hook_p hook, char * file, int line);
183193785Sedwinstatic __inline void	_ng_hook_force_writer(hook_p hook, char * file,
184325160Sphilip				int line);
185193785Sedwinstatic __inline void	_ng_hook_force_queue(hook_p hook, char * file,
186194485Sedwin				int line);
187240457Sedwinstatic __inline void	_ng_hook_set_to_inbound(hook_p hook, char * file,
188240457Sedwin				int line);
189240457Sedwin
190194485Sedwinstatic __inline void
191194485Sedwin_chkhook(hook_p hook, char *file, int line)
192193785Sedwin{
193198270Sedwin	if (hook->hk_magic != HK_MAGIC) {
194240457Sedwin		printf("Accessing freed ");
195240457Sedwin		dumphook(hook, file, line);
196198270Sedwin	}
197198270Sedwin	hook->lastline = line;
198198270Sedwin	hook->lastfile = file;
199198270Sedwin}
200198270Sedwin
201196581Sedwinstatic __inline void
202198270Sedwin_ng_hook_ref(hook_p hook, char * file, int line)
203198270Sedwin{
204240457Sedwin	_chkhook(hook, file, line);
205240457Sedwin	_NG_HOOK_REF(hook);
206198270Sedwin}
207198270Sedwin
208198270Sedwinstatic __inline char *
209198270Sedwin_ng_hook_name(hook_p hook, char * file, int line)
210198270Sedwin{
211201189Sedwin	_chkhook(hook, file, line);
212201189Sedwin	return (_NG_HOOK_NAME(hook));
213201189Sedwin}
214201189Sedwin
215201189Sedwinstatic __inline void
216201189Sedwin_ng_hook_unref(hook_p hook, char * file, int line)
217201189Sedwin{
218201189Sedwin	_chkhook(hook, file, line);
219201189Sedwin	_NG_HOOK_UNREF(hook);
220201189Sedwin}
221201189Sedwin
222201189Sedwinstatic __inline void
223201189Sedwin_ng_hook_set_private(hook_p hook, void *val, char * file, int line)
224206219Sedwin{
225206219Sedwin	_chkhook(hook, file, line);
226240457Sedwin	_NG_HOOK_SET_PRIVATE(hook, val);
227206219Sedwin}
228206219Sedwin
229204887Sedwinstatic __inline void
230201189Sedwin_ng_hook_set_rcvmsg(hook_p hook, ng_rcvmsg_t *val, char * file, int line)
231331663Sphilip{
232273719Sedwin	_chkhook(hook, file, line);
233201189Sedwin	_NG_HOOK_SET_RCVMSG(hook, val);
2342742Swollman}
23575267Swollman
23619878Swollmanstatic __inline void
237316350Sbapt_ng_hook_set_rcvdata(hook_p hook, ng_rcvdata_t *val, char * file, int line)
238316350Sbapt{
239316350Sbapt	_chkhook(hook, file, line);
240316350Sbapt	_NG_HOOK_SET_RCVDATA(hook, val);
241316350Sbapt}
2422742Swollman
2432742Swollmanstatic __inline void *
2442742Swollman_ng_hook_private(hook_p hook, char * file, int line)
24567578Swollman{
246316350Sbapt	_chkhook(hook, file, line);
247316350Sbapt	return (_NG_HOOK_PRIVATE(hook));
2482742Swollman}
2492742Swollman
25086222Swollmanstatic __inline int
25186222Swollman_ng_hook_not_valid(hook_p hook, char * file, int line)
252149514Swollman{
253149514Swollman	_chkhook(hook, file, line);
254149514Swollman	return (_NG_HOOK_NOT_VALID(hook));
2552742Swollman}
256149514Swollman
257316350Sbaptstatic __inline int
258316350Sbapt_ng_hook_is_valid(hook_p hook, char * file, int line)
2592742Swollman{
2602742Swollman	_chkhook(hook, file, line);
2612742Swollman	return (_NG_HOOK_IS_VALID(hook));
262273719Sedwin}
263316350Sbapt
264316350Sbaptstatic __inline node_p
2652742Swollman_ng_hook_node(hook_p hook, char * file, int line)
26614343Swollman{
267248307Sedwin	_chkhook(hook, file, line);
268248307Sedwin	return (_NG_HOOK_NODE(hook));
269248307Sedwin}
270325160Sphilip
271325160Sphilipstatic __inline hook_p
272325160Sphilip_ng_hook_peer(hook_p hook, char * file, int line)
273325160Sphilip{
274325160Sphilip	_chkhook(hook, file, line);
275325160Sphilip	return (_NG_HOOK_PEER(hook));
2762742Swollman}
277325160Sphilip
278325160Sphilipstatic __inline void
279316350Sbapt_ng_hook_force_writer(hook_p hook, char * file, int line)
280316350Sbapt{
281316350Sbapt	_chkhook(hook, file, line);
2822742Swollman	_NG_HOOK_FORCE_WRITER(hook);
2832742Swollman}
284273719Sedwin
2852742Swollmanstatic __inline void
286273719Sedwin_ng_hook_force_queue(hook_p hook, char * file, int line)
28743014Swollman{
2882742Swollman	_chkhook(hook, file, line);
289339631Sphilip	_NG_HOOK_FORCE_QUEUE(hook);
290339631Sphilip}
291339631Sphilip
292339631Sphilipstatic __inline void
293339631Sphilip_ng_hook_set_to_inbound(hook_p hook, char * file, int line)
294339631Sphilip{
295339631Sphilip	_chkhook(hook, file, line);
296339631Sphilip	_NG_HOOK_SET_TO_INBOUND(hook);
297339631Sphilip}
298339631Sphilip
299339631Sphilipstatic __inline void
300339631Sphilip_ng_hook_hi_stack(hook_p hook, char * file, int line)
301339631Sphilip{
302339631Sphilip	_chkhook(hook, file, line);
303339631Sphilip	_NG_HOOK_HI_STACK(hook);
304339631Sphilip}
305339631Sphilip
306339631Sphilip
307339631Sphilip#define	NG_HOOK_REF(hook)		_ng_hook_ref(hook, _NN_)
308339631Sphilip#define NG_HOOK_NAME(hook)		_ng_hook_name(hook, _NN_)
309339631Sphilip#define NG_HOOK_UNREF(hook)		_ng_hook_unref(hook, _NN_)
310339631Sphilip#define	NG_HOOK_SET_PRIVATE(hook, val)	_ng_hook_set_private(hook, val, _NN_)
311339631Sphilip#define	NG_HOOK_SET_RCVMSG(hook, val)	_ng_hook_set_rcvmsg(hook, val, _NN_)
3122742Swollman#define	NG_HOOK_SET_RCVDATA(hook, val)	_ng_hook_set_rcvdata(hook, val, _NN_)
3132742Swollman#define	NG_HOOK_PRIVATE(hook)		_ng_hook_private(hook, _NN_)
3142742Swollman#define NG_HOOK_NOT_VALID(hook)		_ng_hook_not_valid(hook, _NN_)
31519878Swollman#define NG_HOOK_IS_VALID(hook)		_ng_hook_is_valid(hook, _NN_)
31619878Swollman#define NG_HOOK_NODE(hook)		_ng_hook_node(hook, _NN_)
3172742Swollman#define NG_HOOK_PEER(hook)		_ng_hook_peer(hook, _NN_)
318270817Spluknet#define NG_HOOK_FORCE_WRITER(hook)	_ng_hook_force_writer(hook, _NN_)
319270817Spluknet#define NG_HOOK_FORCE_QUEUE(hook)	_ng_hook_force_queue(hook, _NN_)
32093799Swollman#define NG_HOOK_SET_TO_INBOUND(hook)	_ng_hook_set_to_inbound(hook, _NN_)
3212742Swollman#define NG_HOOK_HI_STACK(hook)		_ng_hook_hi_stack(hook, _NN_)
3222742Swollman
323270817Spluknet#else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
3242742Swollman
3252742Swollman#define	NG_HOOK_REF(hook)		_NG_HOOK_REF(hook)
3262742Swollman#define NG_HOOK_NAME(hook)		_NG_HOOK_NAME(hook)
3272742Swollman#define NG_HOOK_UNREF(hook)		_NG_HOOK_UNREF(hook)
3282742Swollman#define	NG_HOOK_SET_PRIVATE(hook, val)	_NG_HOOK_SET_PRIVATE(hook, val)
32919878Swollman#define	NG_HOOK_SET_RCVMSG(hook, val)	_NG_HOOK_SET_RCVMSG(hook, val)
3302742Swollman#define	NG_HOOK_SET_RCVDATA(hook, val)	_NG_HOOK_SET_RCVDATA(hook, val)
3312742Swollman#define	NG_HOOK_PRIVATE(hook)		_NG_HOOK_PRIVATE(hook)
3322742Swollman#define NG_HOOK_NOT_VALID(hook)		_NG_HOOK_NOT_VALID(hook)
333270817Spluknet#define NG_HOOK_IS_VALID(hook)		_NG_HOOK_IS_VALID(hook)
334270817Spluknet#define NG_HOOK_NODE(hook)		_NG_HOOK_NODE(hook)
335270817Spluknet#define NG_HOOK_PEER(hook)		_NG_HOOK_PEER(hook)
336270817Spluknet#define NG_HOOK_FORCE_WRITER(hook)	_NG_HOOK_FORCE_WRITER(hook)
3372742Swollman#define NG_HOOK_FORCE_QUEUE(hook)	_NG_HOOK_FORCE_QUEUE(hook)
338339631Sphilip#define NG_HOOK_SET_TO_INBOUND(hook)	_NG_HOOK_SET_TO_INBOUND(hook)
339339631Sphilip#define NG_HOOK_HI_STACK(hook)		_NG_HOOK_HI_STACK(hook)
340339631Sphilip
341339631Sphilip#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
342339631Sphilip
343339631Sphilip/***********************************************************************
344339631Sphilip ***************** Node Structure and Methods **************************
345339631Sphilip ***********************************************************************
346339631Sphilip * Structure of a node
347339631Sphilip * including the eembedded queue structure.
348339631Sphilip *
349339631Sphilip * The structure for queueing Netgraph request items
350339631Sphilip * embedded in the node structure
351339631Sphilip */
352339631Sphilipstruct ng_queue {
353339631Sphilip	u_int		q_flags;	/* Current r/w/q lock flags */
354339631Sphilip	u_int		q_flags2;	/* Other queue flags */
355339631Sphilip	struct mtx	q_mtx;
356339631Sphilip	STAILQ_ENTRY(ng_node)	q_work;	/* nodes with work to do */
357339631Sphilip	STAILQ_HEAD(, ng_item)	queue;	/* actually items queue */
358339631Sphilip};
359339631Sphilip
360339631Sphilipstruct ng_node {
3612742Swollman	char	nd_name[NG_NODESIZ];	/* optional globally unique name */
362339631Sphilip	struct	ng_type *nd_type;	/* the installed 'type' */
363339631Sphilip	int	nd_flags;		/* see below for bit definitions */
364339631Sphilip	int	nd_numhooks;		/* number of hooks */
365163302Sru	void   *nd_private;		/* node type dependant node ID */
36693799Swollman	ng_ID_t	nd_ID;			/* Unique per node */
36793799Swollman	LIST_HEAD(hooks, ng_hook) nd_hooks;	/* linked list of node hooks */
36893799Swollman	LIST_ENTRY(ng_node)	  nd_nodes;	/* name hash collision list */
369163302Sru	LIST_ENTRY(ng_node)	  nd_idnodes;	/* ID hash collision list */
370169811Swollman	struct	ng_queue	  nd_input_queue; /* input queue for locking */
371270817Spluknet	int	nd_refs;		/* # of references to this node */
372163302Sru	struct	vnet		 *nd_vnet;	/* network stack instance */
373325160Sphilip#ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
374163302Sru#define ND_MAGIC 0x59264837
375163302Sru	int	nd_magic;
376163302Sru	char	*lastfile;
377163302Sru	int	lastline;
378163302Sru	SLIST_ENTRY(ng_node)	  nd_all;	/* all existing nodes */
379163302Sru#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
380163302Sru};
381163302Sru
382316350Sbapt/* Flags for a node */
383270817Spluknet#define NGF_INVALID	0x00000001	/* free when refs go to 0 */
384181421Sedwin#define NG_INVALID	NGF_INVALID	/* compat for old code */
385270817Spluknet#define NGF_FORCE_WRITER	0x00000004	/* Never multithread this node */
386339631Sphilip#define NG_FORCE_WRITER	NGF_FORCE_WRITER /* compat for old code */
387270817Spluknet#define NGF_CLOSING	0x00000008	/* ng_rmnode() at work */
388270817Spluknet#define NG_CLOSING	NGF_CLOSING	/* compat for old code */
389339631Sphilip#define NGF_REALLY_DIE	0x00000010	/* "persistent" node is unloading */
390339631Sphilip#define NG_REALLY_DIE	NGF_REALLY_DIE	/* compat for old code */
391270817Spluknet#define NGF_HI_STACK	0x00000020	/* node has hi stack usage */
392270817Spluknet#define NGF_TYPE1	0x10000000	/* reserved for type specific storage */
393270817Spluknet#define NGF_TYPE2	0x20000000	/* reserved for type specific storage */
394270817Spluknet#define NGF_TYPE3	0x40000000	/* reserved for type specific storage */
395270817Spluknet#define NGF_TYPE4	0x80000000	/* reserved for type specific storage */
396270817Spluknet
397270817Spluknet/*
398270817Spluknet * Public methods for nodes.
399181421Sedwin * If you can't do it with these you probably shouldn't be doing it.
400270817Spluknet */
401270817Spluknetvoid	ng_unref_node(node_p node); /* don't move this */
402270817Spluknet#define _NG_NODE_NAME(node)	((node)->nd_name + 0)
403270817Spluknet#define _NG_NODE_HAS_NAME(node)	((node)->nd_name[0] + 0)
404270817Spluknet#define _NG_NODE_ID(node)	((node)->nd_ID + 0)
405270817Spluknet#define	_NG_NODE_REF(node)	refcount_acquire(&(node)->nd_refs)
406270817Spluknet#define	_NG_NODE_UNREF(node)	ng_unref_node(node)
407270817Spluknet#define	_NG_NODE_SET_PRIVATE(node, val)	do {(node)->nd_private = val;} while (0)
408270817Spluknet#define	_NG_NODE_PRIVATE(node)	((node)->nd_private)
409273719Sedwin#define _NG_NODE_IS_VALID(node)	(!((node)->nd_flags & NGF_INVALID))
410273719Sedwin#define _NG_NODE_NOT_VALID(node)	((node)->nd_flags & NGF_INVALID)
411270817Spluknet#define _NG_NODE_NUMHOOKS(node)	((node)->nd_numhooks + 0) /* rvalue */
412270817Spluknet#define _NG_NODE_FORCE_WRITER(node)					\
413270817Spluknet	do{ node->nd_flags |= NGF_FORCE_WRITER; }while (0)
414270817Spluknet#define _NG_NODE_HI_STACK(node)						\
415270817Spluknet	do{ node->nd_flags |= NGF_HI_STACK; }while (0)
416270817Spluknet#define _NG_NODE_REALLY_DIE(node)					\
417270817Spluknet	do{ node->nd_flags |= (NGF_REALLY_DIE|NGF_INVALID); }while (0)
418270817Spluknet#define _NG_NODE_REVIVE(node) \
419270817Spluknet	do { node->nd_flags &= ~NGF_INVALID; } while (0)
420270817Spluknet/*
421270817Spluknet * The hook iterator.
422270817Spluknet * This macro will call a function of type ng_fn_eachhook for each
423270817Spluknet * hook attached to the node. If the function returns 0, then the
424270817Spluknet * iterator will stop and return a pointer to the hook that returned 0.
425270817Spluknet */
426270817Spluknettypedef	int	ng_fn_eachhook(hook_p hook, void* arg);
427270817Spluknet#define _NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			\
428270817Spluknet	do {								\
429270817Spluknet		hook_p _hook;						\
430270817Spluknet		(rethook) = NULL;					\
431307362Sbapt		LIST_FOREACH(_hook, &((node)->nd_hooks), hk_hooks) {	\
432270817Spluknet			if ((fn)(_hook, arg) == 0) {			\
433270817Spluknet				(rethook) = _hook;			\
434273719Sedwin				break;					\
435270817Spluknet			}						\
436270817Spluknet		}							\
437270817Spluknet	} while (0)
438270817Spluknet
439270817Spluknet#ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
440307362Sbaptvoid	dumpnode(node_p node, char *file, int line);
441316350Sbaptstatic __inline void _chknode(node_p node, char *file, int line);
442163302Srustatic __inline char * _ng_node_name(node_p node, char *file, int line);
443270817Spluknetstatic __inline int _ng_node_has_name(node_p node, char *file, int line);
444307362Sbaptstatic __inline ng_ID_t _ng_node_id(node_p node, char *file, int line);
445316350Sbaptstatic __inline void _ng_node_ref(node_p node, char *file, int line);
446163302Srustatic __inline void _ng_node_unref(node_p node, char *file, int line);
447270817Spluknetstatic __inline void _ng_node_set_private(node_p node, void * val,
448307362Sbapt							char *file, int line);
449270817Spluknetstatic __inline void * _ng_node_private(node_p node, char *file, int line);
450316350Sbaptstatic __inline int _ng_node_is_valid(node_p node, char *file, int line);
451316350Sbaptstatic __inline int _ng_node_not_valid(node_p node, char *file, int line);
452163302Srustatic __inline int _ng_node_numhooks(node_p node, char *file, int line);
453316350Sbaptstatic __inline void _ng_node_force_writer(node_p node, char *file, int line);
454163302Srustatic __inline hook_p _ng_node_foreach_hook(node_p node,
455163302Sru			ng_fn_eachhook *fn, void *arg, char *file, int line);
456270817Spluknetstatic __inline void _ng_node_revive(node_p node, char *file, int line);
457307362Sbapt
458316350Sbaptstatic __inline void
459316350Sbapt_chknode(node_p node, char *file, int line)
460316350Sbapt{
461163302Sru	if (node->nd_magic != ND_MAGIC) {
462163302Sru		printf("Accessing freed ");
463163302Sru		dumpnode(node, file, line);
464163302Sru	}
465270817Spluknet	node->lastline = line;
466163302Sru	node->lastfile = file;
467163302Sru}
468163302Sru
469270817Spluknetstatic __inline char *
470307362Sbapt_ng_node_name(node_p node, char *file, int line)
471316350Sbapt{
472163302Sru	_chknode(node, file, line);
473163302Sru	return(_NG_NODE_NAME(node));
474163302Sru}
475163302Sru
476200835Sedwinstatic __inline int
477200835Sedwin_ng_node_has_name(node_p node, char *file, int line)
478200835Sedwin{
479200835Sedwin	_chknode(node, file, line);
480200835Sedwin	return(_NG_NODE_HAS_NAME(node));
481200835Sedwin}
482200835Sedwin
483200835Sedwinstatic __inline ng_ID_t
484200835Sedwin_ng_node_id(node_p node, char *file, int line)
485200835Sedwin{
486307362Sbapt	_chknode(node, file, line);
487200835Sedwin	return(_NG_NODE_ID(node));
488270817Spluknet}
489200835Sedwin
490270817Spluknetstatic __inline void
491200835Sedwin_ng_node_ref(node_p node, char *file, int line)
492200835Sedwin{
493200835Sedwin	_chknode(node, file, line);
494200835Sedwin	_NG_NODE_REF(node);
495200835Sedwin}
496200835Sedwin
497200835Sedwinstatic __inline void
498200835Sedwin_ng_node_unref(node_p node, char *file, int line)
499200835Sedwin{
500200835Sedwin	_chknode(node, file, line);
501200835Sedwin	_NG_NODE_UNREF(node);
502200835Sedwin}
503200835Sedwin
504200835Sedwinstatic __inline void
505200835Sedwin_ng_node_set_private(node_p node, void * val, char *file, int line)
506200835Sedwin{
507200835Sedwin	_chknode(node, file, line);
508200835Sedwin	_NG_NODE_SET_PRIVATE(node, val);
509200835Sedwin}
510200835Sedwin
511200835Sedwinstatic __inline void *
512270817Spluknet_ng_node_private(node_p node, char *file, int line)
513200835Sedwin{
514200835Sedwin	_chknode(node, file, line);
515200835Sedwin	return (_NG_NODE_PRIVATE(node));
516200835Sedwin}
517200835Sedwin
518200835Sedwinstatic __inline int
519200835Sedwin_ng_node_is_valid(node_p node, char *file, int line)
520200835Sedwin{
521200835Sedwin	_chknode(node, file, line);
522200835Sedwin	return(_NG_NODE_IS_VALID(node));
523200835Sedwin}
524270817Spluknet
525270817Spluknetstatic __inline int
526325160Sphilip_ng_node_not_valid(node_p node, char *file, int line)
527270817Spluknet{
528270817Spluknet	_chknode(node, file, line);
529270817Spluknet	return(_NG_NODE_NOT_VALID(node));
530270817Spluknet}
531270817Spluknet
532270817Spluknetstatic __inline int
533270817Spluknet_ng_node_numhooks(node_p node, char *file, int line)
534270817Spluknet{
535270817Spluknet	_chknode(node, file, line);
536270817Spluknet	return(_NG_NODE_NUMHOOKS(node));
537270817Spluknet}
538270817Spluknet
539270817Spluknetstatic __inline void
540270817Spluknet_ng_node_force_writer(node_p node, char *file, int line)
541270817Spluknet{
542307362Sbapt	_chknode(node, file, line);
543307362Sbapt	_NG_NODE_FORCE_WRITER(node);
544270817Spluknet}
545270817Spluknet
546270817Spluknetstatic __inline void
547270817Spluknet_ng_node_hi_stack(node_p node, char *file, int line)
548270817Spluknet{
549270817Spluknet	_chknode(node, file, line);
550270817Spluknet	_NG_NODE_HI_STACK(node);
551270817Spluknet}
552273719Sedwin
553270817Spluknetstatic __inline void
554270817Spluknet_ng_node_really_die(node_p node, char *file, int line)
555270817Spluknet{
556270817Spluknet	_chknode(node, file, line);
557307362Sbapt	_NG_NODE_REALLY_DIE(node);
558270817Spluknet}
559307362Sbapt
560307362Sbaptstatic __inline void
561270817Spluknet_ng_node_revive(node_p node, char *file, int line)
562307362Sbapt{
563270817Spluknet	_chknode(node, file, line);
564270817Spluknet	_NG_NODE_REVIVE(node);
565270817Spluknet}
566270817Spluknet
567339631Sphilipstatic __inline hook_p
56814343Swollman_ng_node_foreach_hook(node_p node, ng_fn_eachhook *fn, void *arg,
569270817Spluknet						char *file, int line)
570270817Spluknet{
571270817Spluknet	hook_p hook;
572316350Sbapt	_chknode(node, file, line);
57393799Swollman	_NG_NODE_FOREACH_HOOK(node, fn, arg, hook);
574198825Sedwin	return (hook);
575248307Sedwin}
576248307Sedwin
577248307Sedwin#define NG_NODE_NAME(node)		_ng_node_name(node, _NN_)
578248307Sedwin#define NG_NODE_HAS_NAME(node)		_ng_node_has_name(node, _NN_)
579198825Sedwin#define NG_NODE_ID(node)		_ng_node_id(node, _NN_)
580200835Sedwin#define NG_NODE_REF(node)		_ng_node_ref(node, _NN_)
581200835Sedwin#define	NG_NODE_UNREF(node)		_ng_node_unref(node, _NN_)
582198825Sedwin#define	NG_NODE_SET_PRIVATE(node, val)	_ng_node_set_private(node, val, _NN_)
583198825Sedwin#define	NG_NODE_PRIVATE(node)		_ng_node_private(node, _NN_)
584198825Sedwin#define NG_NODE_IS_VALID(node)		_ng_node_is_valid(node, _NN_)
585198825Sedwin#define NG_NODE_NOT_VALID(node)		_ng_node_not_valid(node, _NN_)
586198825Sedwin#define NG_NODE_FORCE_WRITER(node) 	_ng_node_force_writer(node, _NN_)
587198825Sedwin#define NG_NODE_HI_STACK(node) 		_ng_node_hi_stack(node, _NN_)
588198825Sedwin#define NG_NODE_REALLY_DIE(node) 	_ng_node_really_die(node, _NN_)
589342669Sphilip#define NG_NODE_NUMHOOKS(node)		_ng_node_numhooks(node, _NN_)
590342669Sphilip#define NG_NODE_REVIVE(node)		_ng_node_revive(node, _NN_)
591342669Sphilip#define NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			      \
592342669Sphilip	do {								      \
593342669Sphilip		rethook = _ng_node_foreach_hook(node, fn, (void *)arg, _NN_); \
594342669Sphilip	} while (0)
595342669Sphilip
596342669Sphilip#else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
597342669Sphilip
598342669Sphilip#define NG_NODE_NAME(node)		_NG_NODE_NAME(node)
599342669Sphilip#define NG_NODE_HAS_NAME(node)		_NG_NODE_HAS_NAME(node)
600342669Sphilip#define NG_NODE_ID(node)		_NG_NODE_ID(node)
601342669Sphilip#define	NG_NODE_REF(node)		_NG_NODE_REF(node)
602342669Sphilip#define	NG_NODE_UNREF(node)		_NG_NODE_UNREF(node)
603342669Sphilip#define	NG_NODE_SET_PRIVATE(node, val)	_NG_NODE_SET_PRIVATE(node, val)
604342669Sphilip#define	NG_NODE_PRIVATE(node)		_NG_NODE_PRIVATE(node)
605342669Sphilip#define NG_NODE_IS_VALID(node)		_NG_NODE_IS_VALID(node)
606342669Sphilip#define NG_NODE_NOT_VALID(node)		_NG_NODE_NOT_VALID(node)
607342669Sphilip#define NG_NODE_FORCE_WRITER(node) 	_NG_NODE_FORCE_WRITER(node)
608342669Sphilip#define NG_NODE_HI_STACK(node) 		_NG_NODE_HI_STACK(node)
609342669Sphilip#define NG_NODE_REALLY_DIE(node) 	_NG_NODE_REALLY_DIE(node)
610342669Sphilip#define NG_NODE_NUMHOOKS(node)		_NG_NODE_NUMHOOKS(node)
611342669Sphilip#define NG_NODE_REVIVE(node)		_NG_NODE_REVIVE(node)
612342669Sphilip#define NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)			\
613342669Sphilip		_NG_NODE_FOREACH_HOOK(node, fn, arg, rethook)
614342669Sphilip#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
615342669Sphilip
616342669Sphilip/***********************************************************************
617342669Sphilip ************* Node Queue and Item Structures and Methods **************
618342669Sphilip ***********************************************************************
619342669Sphilip *
620342669Sphilip */
621342669Sphiliptypedef	void	ng_item_fn(node_p node, hook_p hook, void *arg1, int arg2);
622342669Sphiliptypedef	int	ng_item_fn2(node_p node, struct ng_item *item, hook_p hook);
623342669Sphiliptypedef	void	ng_apply_t(void *context, int error);
624342669Sphilipstruct ng_apply_info {
625342669Sphilip	ng_apply_t	*apply;
626342669Sphilip	void		*context;
627342669Sphilip	int		refs;
628342669Sphilip	int		error;
629342669Sphilip};
630342669Sphilipstruct ng_item {
631342669Sphilip	u_long	el_flags;
632342669Sphilip	STAILQ_ENTRY(ng_item)	el_next;
633342669Sphilip	node_p	el_dest; /* The node it will be applied against (or NULL) */
634342669Sphilip	hook_p	el_hook; /* Entering hook. Optional in Control messages */
635342669Sphilip	union {
636342669Sphilip		struct mbuf	*da_m;
637342669Sphilip		struct {
638342669Sphilip			struct ng_mesg	*msg_msg;
639342669Sphilip			ng_ID_t		msg_retaddr;
640342669Sphilip		} msg;
641342669Sphilip		struct {
642342669Sphilip			union {
643342669Sphilip				ng_item_fn	*fn_fn;
644342669Sphilip				ng_item_fn2	*fn_fn2;
645342669Sphilip			} fn_fn;
646342669Sphilip			void 		*fn_arg1;
647342669Sphilip			int		fn_arg2;
648342669Sphilip		} fn;
649342669Sphilip	} body;
650342669Sphilip	/*
651342669Sphilip	 * Optional callback called when item is being applied,
652342669Sphilip	 * and its context.
653342669Sphilip	 */
654342669Sphilip	struct ng_apply_info	*apply;
655342669Sphilip	u_int	depth;
656342669Sphilip#ifdef	NETGRAPH_DEBUG /*----------------------------------------------*/
657342669Sphilip	char *lastfile;
658342669Sphilip	int  lastline;
659342669Sphilip	TAILQ_ENTRY(ng_item)	  all;		/* all existing items */
660198825Sedwin#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
661342669Sphilip};
662342669Sphilip
663198825Sedwin#define NGQF_TYPE	0x03		/* MASK of content definition */
664342669Sphilip#define NGQF_MESG	0x00		/* the queue element is a message */
665240457Sedwin#define NGQF_DATA	0x01		/* the queue element is data */
666198825Sedwin#define NGQF_FN		0x02		/* the queue element is a function */
667198825Sedwin#define NGQF_FN2	0x03		/* the queue element is a new function */
668198825Sedwin
669198825Sedwin#define NGQF_RW		0x04		/* MASK for wanted queue mode */
670198825Sedwin#define NGQF_READER	0x04		/* wants to be a reader */
671198825Sedwin#define NGQF_WRITER	0x00		/* wants to be a writer */
672198825Sedwin
673198825Sedwin#define NGQF_QMODE	0x08		/* MASK for how it was queued */
674198825Sedwin#define NGQF_QREADER	0x08		/* was queued as a reader */
675342669Sphilip#define NGQF_QWRITER	0x00		/* was queued as a writer */
676198825Sedwin
677198825Sedwin/*
678198825Sedwin * Get the mbuf (etc) out of an item.
679198825Sedwin * Sets the value in the item to NULL in case we need to call NG_FREE_ITEM()
680198825Sedwin * with it, (to avoid freeing the things twice).
681198825Sedwin * If you don't want to zero out the item then realise that the
682198825Sedwin * item still owns it.
683198825Sedwin * Retaddr is different. There are no references on that. It's just a number.
684198825Sedwin * The debug versions must be either all used everywhere or not at all.
685198825Sedwin */
686198825Sedwin
687198825Sedwin#define _NGI_M(i) ((i)->body.da_m)
688198825Sedwin#define _NGI_MSG(i) ((i)->body.msg.msg_msg)
689198825Sedwin#define _NGI_RETADDR(i) ((i)->body.msg.msg_retaddr)
690198825Sedwin#define	_NGI_FN(i) ((i)->body.fn.fn_fn.fn_fn)
691198825Sedwin#define	_NGI_FN2(i) ((i)->body.fn.fn_fn.fn_fn2)
692198825Sedwin#define	_NGI_ARG1(i) ((i)->body.fn.fn_arg1)
693198825Sedwin#define	_NGI_ARG2(i) ((i)->body.fn.fn_arg2)
694198825Sedwin#define	_NGI_NODE(i) ((i)->el_dest)
695198825Sedwin#define	_NGI_HOOK(i) ((i)->el_hook)
696198825Sedwin#define	_NGI_SET_HOOK(i,h) do { _NGI_HOOK(i) = h; h = NULL;} while (0)
697198825Sedwin#define	_NGI_CLR_HOOK(i)   do {						\
698198825Sedwin		hook_p _hook = _NGI_HOOK(i);				\
699198825Sedwin		if (_hook) {						\
700198825Sedwin			_NG_HOOK_UNREF(_hook);				\
701198825Sedwin			_NGI_HOOK(i) = NULL;				\
702198825Sedwin		}							\
703198825Sedwin	} while (0)
704342669Sphilip#define	_NGI_SET_NODE(i,n) do { _NGI_NODE(i) = n; n = NULL;} while (0)
705342669Sphilip#define	_NGI_CLR_NODE(i)   do {						\
706342669Sphilip		node_p _node = _NGI_NODE(i);				\
707342669Sphilip		if (_node) {						\
708342669Sphilip			_NG_NODE_UNREF(_node);				\
709342669Sphilip			_NGI_NODE(i) = NULL;				\
710342669Sphilip		}							\
711342669Sphilip	} while (0)
712342669Sphilip
713198825Sedwin#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
7142742Swollmanvoid				dumpitem(item_p item, char *file, int line);
7152742Swollmanstatic __inline void		_ngi_check(item_p item, char *file, int line) ;
7162742Swollmanstatic __inline struct mbuf **	_ngi_m(item_p item, char *file, int line) ;
7172742Swollmanstatic __inline ng_ID_t *	_ngi_retaddr(item_p item, char *file, int line);
7182742Swollmanstatic __inline struct ng_mesg ** _ngi_msg(item_p item, char *file, int line) ;
7192742Swollmanstatic __inline ng_item_fn **	_ngi_fn(item_p item, char *file, int line) ;
720198825Sedwinstatic __inline ng_item_fn2 **	_ngi_fn2(item_p item, char *file, int line) ;
721342669Sphilipstatic __inline void **		_ngi_arg1(item_p item, char *file, int line) ;
7222742Swollmanstatic __inline int *		_ngi_arg2(item_p item, char *file, int line) ;
7232742Swollmanstatic __inline node_p		_ngi_node(item_p item, char *file, int line);
7242742Swollmanstatic __inline hook_p		_ngi_hook(item_p item, char *file, int line);
7252742Swollman
726213312Sedwinstatic __inline void
727213312Sedwin_ngi_check(item_p item, char *file, int line)
728198825Sedwin{
729198825Sedwin	(item)->lastline = line;
730198825Sedwin	(item)->lastfile = file;
7312742Swollman}
732342669Sphilip
733342669Sphilipstatic __inline struct mbuf **
734342669Sphilip_ngi_m(item_p item, char *file, int line)
735342669Sphilip{
736342669Sphilip	_ngi_check(item, file, line);
73758787Sru	return (&_NGI_M(item));
7382742Swollman}
73930711Swollman
74030711Swollmanstatic __inline struct ng_mesg **
74143014Swollman_ngi_msg(item_p item, char *file, int line)
74230711Swollman{
743206868Sedwin	_ngi_check(item, file, line);
744270817Spluknet	return (&_NGI_MSG(item));
745206868Sedwin}
746206868Sedwin
747206868Sedwinstatic __inline ng_ID_t *
748270817Spluknet_ngi_retaddr(item_p item, char *file, int line)
749270817Spluknet{
750270817Spluknet	_ngi_check(item, file, line);
751270817Spluknet	return (&_NGI_RETADDR(item));
752270817Spluknet}
753270817Spluknet
754270817Spluknetstatic __inline ng_item_fn **
755325160Sphilip_ngi_fn(item_p item, char *file, int line)
756270817Spluknet{
757270817Spluknet	_ngi_check(item, file, line);
758270817Spluknet	return (&_NGI_FN(item));
759270817Spluknet}
760270817Spluknet
761270817Spluknetstatic __inline ng_item_fn2 **
762270817Spluknet_ngi_fn2(item_p item, char *file, int line)
763270817Spluknet{
764270817Spluknet	_ngi_check(item, file, line);
765270817Spluknet	return (&_NGI_FN2(item));
766328476Sphilip}
767270817Spluknet
768325160Sphilipstatic __inline void **
769270817Spluknet_ngi_arg1(item_p item, char *file, int line)
770328476Sphilip{
771206868Sedwin	_ngi_check(item, file, line);
772270817Spluknet	return (&_NGI_ARG1(item));
773328476Sphilip}
774328476Sphilip
775270817Spluknetstatic __inline int *
776328476Sphilip_ngi_arg2(item_p item, char *file, int line)
777270817Spluknet{
778270817Spluknet	_ngi_check(item, file, line);
779270817Spluknet	return (&_NGI_ARG2(item));
780270817Spluknet}
781270817Spluknet
782270817Spluknetstatic __inline node_p
783270817Spluknet_ngi_node(item_p item, char *file, int line)
784270817Spluknet{
785270817Spluknet	_ngi_check(item, file, line);
786270817Spluknet	return (_NGI_NODE(item));
787270817Spluknet}
788270817Spluknet
789270817Spluknetstatic __inline hook_p
790270817Spluknet_ngi_hook(item_p item, char *file, int line)
791270817Spluknet{
792270817Spluknet	_ngi_check(item, file, line);
793270817Spluknet	return (_NGI_HOOK(item));
794270817Spluknet}
795270817Spluknet
796270817Spluknet#define NGI_M(i)	(*_ngi_m(i, _NN_))
797270817Spluknet#define NGI_MSG(i)	(*_ngi_msg(i, _NN_))
798270817Spluknet#define NGI_RETADDR(i)	(*_ngi_retaddr(i, _NN_))
799270817Spluknet#define NGI_FN(i)	(*_ngi_fn(i, _NN_))
800270817Spluknet#define NGI_FN2(i)	(*_ngi_fn2(i, _NN_))
801270817Spluknet#define NGI_ARG1(i)	(*_ngi_arg1(i, _NN_))
802270817Spluknet#define NGI_ARG2(i)	(*_ngi_arg2(i, _NN_))
803270817Spluknet#define NGI_HOOK(i)	_ngi_hook(i, _NN_)
804270817Spluknet#define NGI_NODE(i)	_ngi_node(i, _NN_)
805270817Spluknet#define	NGI_SET_HOOK(i,h)						\
806270817Spluknet	do { _ngi_check(i, _NN_); _NGI_SET_HOOK(i, h); } while (0)
807270817Spluknet#define	NGI_CLR_HOOK(i)							\
808270817Spluknet	do { _ngi_check(i, _NN_); _NGI_CLR_HOOK(i); } while (0)
809270817Spluknet#define	NGI_SET_NODE(i,n)						\
810270817Spluknet	do { _ngi_check(i, _NN_); _NGI_SET_NODE(i, n); } while (0)
811270817Spluknet#define	NGI_CLR_NODE(i)							\
812270817Spluknet	do { _ngi_check(i, _NN_); _NGI_CLR_NODE(i); } while (0)
813270817Spluknet
814270817Spluknet#define NG_FREE_ITEM(item)						\
815270817Spluknet	do {								\
816270817Spluknet		_ngi_check(item, _NN_);					\
817270817Spluknet		ng_free_item((item));					\
818270817Spluknet	} while (0)
819270817Spluknet
820270817Spluknet#define	SAVE_LINE(item)							\
821273719Sedwin	do {								\
822273719Sedwin		(item)->lastline = __LINE__;				\
823270817Spluknet		(item)->lastfile = __FILE__;				\
824270817Spluknet	} while (0)
825270817Spluknet
826270817Spluknet#else	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
827273719Sedwin
828270817Spluknet#define NGI_M(i)	_NGI_M(i)
829270817Spluknet#define NGI_MSG(i)	_NGI_MSG(i)
830270817Spluknet#define NGI_RETADDR(i)	_NGI_RETADDR(i)
831270817Spluknet#define NGI_FN(i)	_NGI_FN(i)
832270817Spluknet#define NGI_FN2(i)	_NGI_FN2(i)
833273719Sedwin#define NGI_ARG1(i)	_NGI_ARG1(i)
834270817Spluknet#define NGI_ARG2(i)	_NGI_ARG2(i)
835270817Spluknet#define	NGI_NODE(i)	_NGI_NODE(i)
836270817Spluknet#define	NGI_HOOK(i)	_NGI_HOOK(i)
837270817Spluknet#define	NGI_SET_HOOK(i,h) _NGI_SET_HOOK(i,h)
838270817Spluknet#define	NGI_CLR_HOOK(i)	  _NGI_CLR_HOOK(i)
839307362Sbapt#define	NGI_SET_NODE(i,n) _NGI_SET_NODE(i,n)
840270817Spluknet#define	NGI_CLR_NODE(i)	  _NGI_CLR_NODE(i)
841270817Spluknet
842270817Spluknet#define	NG_FREE_ITEM(item)	ng_free_item((item))
84330711Swollman#define	SAVE_LINE(item)		do {} while (0)
844270817Spluknet
845270817Spluknet#endif	/* NETGRAPH_DEBUG */ /*----------------------------------------------*/
846270817Spluknet
847270817Spluknet#define NGI_GET_M(i,m)							\
848270817Spluknet	do {								\
849270817Spluknet		(m) = NGI_M(i);						\
85030711Swollman		_NGI_M(i) = NULL;					\
85130711Swollman	} while (0)
85230711Swollman
85330711Swollman#define NGI_GET_MSG(i,m)						\
85430711Swollman	do {								\
85530711Swollman		(m) = NGI_MSG(i);					\
85630711Swollman		_NGI_MSG(i) = NULL;					\
857270817Spluknet	} while (0)
858270817Spluknet
859206868Sedwin#define NGI_GET_NODE(i,n)	/* YOU NOW HAVE THE REFERENCE */	\
86030711Swollman	do {								\
861270817Spluknet		(n) = NGI_NODE(i);					\
862270817Spluknet		_NGI_NODE(i) = NULL;					\
863316350Sbapt	} while (0)
864273719Sedwin
86530711Swollman#define NGI_GET_HOOK(i,h)						\
86630711Swollman	do {								\
86793799Swollman		(h) = NGI_HOOK(i);					\
868339631Sphilip		_NGI_HOOK(i) = NULL;					\
869339631Sphilip	} while (0)
870339631Sphilip
871339631Sphilip#define NGI_SET_WRITER(i)	((i)->el_flags &= ~NGQF_QMODE)
872339631Sphilip#define NGI_SET_READER(i)	((i)->el_flags |= NGQF_QREADER)
873339631Sphilip
874339631Sphilip#define NGI_QUEUED_READER(i)	((i)->el_flags & NGQF_QREADER)
875339631Sphilip#define NGI_QUEUED_WRITER(i)	(((i)->el_flags & NGQF_QMODE) == NGQF_QWRITER)
876339631Sphilip
877339631Sphilip/**********************************************************************
878339631Sphilip* Data macros.  Send, manipulate and free.
879339631Sphilip**********************************************************************/
880339631Sphilip/*
881339631Sphilip * Assuming the data is already ok, just set the new address and send
882339631Sphilip */
883339631Sphilip#define NG_FWD_ITEM_HOOK_FLAGS(error, item, hook, flags)		\
884339631Sphilip	do {								\
885339631Sphilip		(error) =						\
886339631Sphilip		    ng_address_hook(NULL, (item), (hook), NG_NOFLAGS);	\
887339631Sphilip		if (error == 0) {					\
888339631Sphilip			SAVE_LINE(item);				\
889339631Sphilip			(error) = ng_snd_item((item), (flags));		\
890339631Sphilip		}							\
891339631Sphilip		(item) = NULL;						\
892339631Sphilip	} while (0)
893339631Sphilip#define	NG_FWD_ITEM_HOOK(error, item, hook)	\
894339631Sphilip		NG_FWD_ITEM_HOOK_FLAGS(error, item, hook, NG_NOFLAGS)
895339631Sphilip
896339631Sphilip/*
897339631Sphilip * Forward a data packet. Mbuf pointer is updated to new value. We
898339631Sphilip * presume you dealt with the old one when you update it to the new one
899339631Sphilip * (or it maybe the old one). We got a packet and possibly had to modify
900339631Sphilip * the mbuf. You should probably use NGI_GET_M() if you are going to use
901339631Sphilip * this too.
902339631Sphilip */
903339631Sphilip#define NG_FWD_NEW_DATA_FLAGS(error, item, hook, m, flags)		\
904339631Sphilip	do {								\
905339631Sphilip		NGI_M(item) = (m);					\
906339631Sphilip		(m) = NULL;						\
907339631Sphilip		NG_FWD_ITEM_HOOK_FLAGS(error, item, hook, flags);	\
908339631Sphilip	} while (0)
909339631Sphilip#define	NG_FWD_NEW_DATA(error, item, hook, m)	\
910339631Sphilip		NG_FWD_NEW_DATA_FLAGS(error, item, hook, m, NG_NOFLAGS)
911339631Sphilip
912339631Sphilip/* Send a previously unpackaged mbuf. XXX: This should be called
913339631Sphilip * NG_SEND_DATA in future, but this name is kept for compatibility
914339631Sphilip * reasons.
915339631Sphilip */
916339631Sphilip#define NG_SEND_DATA_FLAGS(error, hook, m, flags)			\
917339631Sphilip	do {								\
918339631Sphilip		item_p _item;						\
919339631Sphilip		if ((_item = ng_package_data((m), flags))) {		\
920339631Sphilip			NG_FWD_ITEM_HOOK_FLAGS(error, _item, hook, flags);\
921339631Sphilip		} else {						\
922339631Sphilip			(error) = ENOMEM;				\
923339631Sphilip		}							\
924339631Sphilip		(m) = NULL;						\
925339631Sphilip	} while (0)
926339631Sphilip
927339631Sphilip#define NG_SEND_DATA_ONLY(error, hook, m)	\
928339631Sphilip		NG_SEND_DATA_FLAGS(error, hook, m, NG_NOFLAGS)
929339631Sphilip/* NG_SEND_DATA() compat for meta-data times */
930339631Sphilip#define	NG_SEND_DATA(error, hook, m, x)	\
931339631Sphilip		NG_SEND_DATA_FLAGS(error, hook, m, NG_NOFLAGS)
932339631Sphilip
933339631Sphilip#define NG_FREE_MSG(msg)						\
934339631Sphilip	do {								\
935339631Sphilip		if ((msg)) {						\
936339631Sphilip			free((msg), M_NETGRAPH_MSG);			\
937339631Sphilip			(msg) = NULL;					\
938339631Sphilip		}	 						\
939339631Sphilip	} while (0)
940339631Sphilip
941339631Sphilip#define NG_FREE_M(m)							\
942339631Sphilip	do {								\
943339631Sphilip		if ((m)) {						\
944339631Sphilip			m_freem((m));					\
945339631Sphilip			(m) = NULL;					\
946339631Sphilip		}							\
947339631Sphilip	} while (0)
948339631Sphilip
949339631Sphilip/*****************************************
950339631Sphilip* Message macros
951339631Sphilip*****************************************/
952339631Sphilip
953339631Sphilip#define NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr)		\
954339631Sphilip	do {								\
955339631Sphilip		item_p _item;						\
956339631Sphilip		if ((_item = ng_package_msg(msg, NG_NOFLAGS)) == NULL) {\
957339631Sphilip			(msg) = NULL;					\
958339631Sphilip			(error) = ENOMEM;				\
959339631Sphilip			break;						\
960339631Sphilip		}							\
961339631Sphilip		if (((error) = ng_address_hook((here), (_item),		\
962339631Sphilip					(hook), (retaddr))) == 0) {	\
963339631Sphilip			SAVE_LINE(_item);				\
964339631Sphilip			(error) = ng_snd_item((_item), 0);		\
965339631Sphilip		}							\
966339631Sphilip		(msg) = NULL;						\
967339631Sphilip	} while (0)
968339631Sphilip
9692742Swollman#define NG_SEND_MSG_PATH(error, here, msg, path, retaddr)		\
970339631Sphilip	do {								\
971339631Sphilip		item_p _item;						\
972339631Sphilip		if ((_item = ng_package_msg(msg, NG_NOFLAGS)) == NULL) {\
973339631Sphilip			(msg) = NULL;					\
974339631Sphilip			(error) = ENOMEM;				\
975339631Sphilip			break;						\
976339631Sphilip		}							\
977339631Sphilip		if (((error) = ng_address_path((here), (_item),		\
978339631Sphilip					(path), (retaddr))) == 0) {	\
979339631Sphilip			SAVE_LINE(_item);				\
980339631Sphilip			(error) = ng_snd_item((_item), 0);		\
981339631Sphilip		}							\
982339631Sphilip		(msg) = NULL;						\
983339631Sphilip	} while (0)
984339631Sphilip
985339631Sphilip#define NG_SEND_MSG_ID(error, here, msg, ID, retaddr)			\
986339631Sphilip	do {								\
987339631Sphilip		item_p _item;						\
988339631Sphilip		if ((_item = ng_package_msg(msg, NG_NOFLAGS)) == NULL) {\
989339631Sphilip			(msg) = NULL;					\
990339631Sphilip			(error) = ENOMEM;				\
991339631Sphilip			break;						\
992339631Sphilip		}							\
993339631Sphilip		if (((error) = ng_address_ID((here), (_item),		\
994339631Sphilip					(ID), (retaddr))) == 0) {	\
995339631Sphilip			SAVE_LINE(_item);				\
996339631Sphilip			(error) = ng_snd_item((_item), 0);		\
997339631Sphilip		}							\
9982742Swollman		(msg) = NULL;						\
999339631Sphilip	} while (0)
1000339631Sphilip
1001339631Sphilip/*
1002316350Sbapt * Redirect the message to the next hop using the given hook.
10032742Swollman * ng_retarget_msg() frees the item if there is an error
10042742Swollman * and returns an error code.  It returns 0 on success.
10052742Swollman */
10062742Swollman#define NG_FWD_MSG_HOOK(error, here, item, hook, retaddr)		\
10072742Swollman	do {								\
1008308302Sgjb		if (((error) = ng_address_hook((here), (item),		\
1009248307Sedwin					(hook), (retaddr))) == 0) {	\
1010308302Sgjb			SAVE_LINE(item);				\
1011308302Sgjb			(error) = ng_snd_item((item), 0);		\
1012308302Sgjb		}							\
1013308302Sgjb		(item) = NULL;						\
1014308302Sgjb	} while (0)
1015308302Sgjb
1016248307Sedwin/*
1017308302Sgjb * Send a queue item back to it's originator with a response message.
1018308302Sgjb * Assume original message was removed and freed separatly.
1019308302Sgjb */
1020308302Sgjb#define NG_RESPOND_MSG(error, here, item, resp)				\
1021325160Sphilip	do {								\
1022325160Sphilip		if (resp) {						\
1023325160Sphilip			ng_ID_t _dest = NGI_RETADDR(item);		\
1024325160Sphilip			NGI_RETADDR(item) = 0;				\
1025325160Sphilip			NGI_MSG(item) = resp;				\
1026325160Sphilip			if ((error = ng_address_ID((here), (item),	\
10272742Swollman					_dest, 0)) == 0) {		\
102819878Swollman				SAVE_LINE(item);			\
10292742Swollman				(error) = ng_snd_item((item), NG_QUEUE);\
103019878Swollman			}						\
10312742Swollman		} else							\
103219878Swollman			NG_FREE_ITEM(item);				\
10332742Swollman		(item) = NULL;						\
10342742Swollman	} while (0)
103543543Swollman
103643543Swollman
10372742Swollman/***********************************************************************
10382742Swollman ******** Structures Definitions and Macros for defining a node  *******
103943543Swollman ***********************************************************************
104058787Sru *
1041308302Sgjb * Here we define the structures needed to actually define a new node
1042308302Sgjb * type.
1043308302Sgjb */
1044325160Sphilip
1045325160Sphilip/*
10462742Swollman * Command list -- each node type specifies the command that it knows
104767578Swollman * how to convert between ASCII and binary using an array of these.
104867578Swollman * The last element in the array must be a terminator with cookie=0.
104967578Swollman */
105067578Swollman
10512742Swollmanstruct ng_cmdlist {
1052149514Swollman	u_int32_t			cookie;		/* command typecookie */
10539908Swollman	int				cmd;		/* command number */
10549908Swollman	const char			*name;		/* command name */
10559908Swollman	const struct ng_parse_type	*mesgType;	/* args if !NGF_RESP */
105614343Swollman	const struct ng_parse_type	*respType;	/* args if NGF_RESP */
105714343Swollman};
1058149514Swollman
105920094Swollman/*
106020094Swollman * Structure of a node type
106120094Swollman * If data is sent to the "rcvdata()" entrypoint then the system
1062136638Swollman * may decide to defer it until later by queing it with the normal netgraph
1063136638Swollman * input queuing system.  This is decidde by the HK_QUEUE flag being set in
1064149514Swollman * the flags word of the peer (receiving) hook. The dequeuing mechanism will
1065136638Swollman * ensure it is not requeued again.
1066136638Swollman * Note the input queueing system is to allow modules
1067136638Swollman * to 'release the stack' or to pass data across spl layers.
1068136638Swollman * The data will be redelivered as soon as the NETISR code runs
1069270817Spluknet * which may be almost immediatly.  A node may also do it's own queueing
1070136638Swollman * for other reasons (e.g. device output queuing).
1071136638Swollman */
1072153670Swollmanstruct ng_type {
1073153670Swollman
1074153670Swollman	u_int32_t	version; 	/* must equal NG_API_VERSION */
1075153670Swollman	const char	*name;		/* Unique type name */
1076153670Swollman	modeventhand_t	mod_event;	/* Module event handler (optional) */
1077153670Swollman	ng_constructor_t *constructor;	/* Node constructor */
1078153670Swollman	ng_rcvmsg_t	*rcvmsg;	/* control messages come here */
1079153670Swollman	ng_close_t	*close;		/* warn about forthcoming shutdown */
1080153670Swollman	ng_shutdown_t	*shutdown;	/* reset, and free resources */
1081153670Swollman	ng_newhook_t	*newhook;	/* first notification of new hook */
1082273719Sedwin	ng_findhook_t	*findhook;	/* only if you have lots of hooks */
1083273719Sedwin	ng_connect_t	*connect;	/* final notification of new hook */
1084273719Sedwin	ng_rcvdata_t	*rcvdata;	/* data comes here */
1085153670Swollman	ng_disconnect_t	*disconnect;	/* notify on disconnect */
10862742Swollman
1087273719Sedwin	const struct	ng_cmdlist *cmdlist;	/* commands we can convert */
1088273719Sedwin
1089307362Sbapt	/* R/W data private to the base netgraph code DON'T TOUCH! */
1090307362Sbapt	LIST_ENTRY(ng_type) types;		/* linked list of all types */
1091307362Sbapt	int		    refs;		/* number of instances */
1092307362Sbapt};
1093307362Sbapt
1094307362Sbapt/*
1095307362Sbapt * Use the NETGRAPH_INIT() macro to link a node type into the
1096307362Sbapt * netgraph system. This works for types compiled into the kernel
1097307362Sbapt * as well as KLD modules. The first argument should be the type
10982742Swollman * name (eg, echo) and the second a pointer to the type struct.
109958787Sru *
110075267Swollman * If a different link time is desired, e.g., a device driver that
1101169811Swollman * needs to install its netgraph type before probing, use the
1102169811Swollman * NETGRAPH_INIT_ORDERED() macro instead.  Device drivers probably
1103270817Spluknet * want to use SI_SUB_DRIVERS/SI_ORDER_FIRST.
110475267Swollman */
1105325160Sphilip
110675267Swollman#define NETGRAPH_INIT_ORDERED(typename, typestructp, sub, order)	\
110775267Swollmanstatic moduledata_t ng_##typename##_mod = {				\
110875267Swollman	"ng_" #typename,						\
110975267Swollman	ng_mod_event,							\
111075267Swollman	(typestructp)							\
111175267Swollman};									\
111275267SwollmanDECLARE_MODULE(ng_##typename, ng_##typename##_mod, sub, order);		\
111375267SwollmanMODULE_DEPEND(ng_##typename, netgraph,	NG_ABI_VERSION,			\
111475267Swollman					NG_ABI_VERSION,			\
111575267Swollman					NG_ABI_VERSION)
1116270817Spluknet
1117270817Spluknet#define NETGRAPH_INIT(tn, tp)						\
111875267Swollman	NETGRAPH_INIT_ORDERED(tn, tp, SI_SUB_PSEUDO, SI_ORDER_MIDDLE)
111975267Swollman
112075267Swollman/* Special malloc() type for netgraph structs and ctrl messages */
112175267Swollman/* Only these two types should be visible to nodes */
112275267SwollmanMALLOC_DECLARE(M_NETGRAPH);
112358787SruMALLOC_DECLARE(M_NETGRAPH_MSG);
1124273719Sedwin
1125316350Sbapt/* declare the base of the netgraph sysclt hierarchy */
1126316350Sbapt/* but only if this file cares about sysctls */
1127316350Sbapt#ifdef	SYSCTL_DECL
1128316350SbaptSYSCTL_DECL(_net_graph);
112958787Sru#endif
11302742Swollman
1131307362Sbapt/*
1132342669Sphilip * Methods that the nodes can use.
1133342669Sphilip * Many of these methods should usually NOT be used directly but via
1134342669Sphilip * Macros above.
1135342669Sphilip */
1136342669Sphilipint	ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr);
1137342669Sphilipint	ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr);
1138342669Sphilipint	ng_address_path(node_p here, item_p item, const char *address, ng_ID_t raddr);
1139342669Sphilipint	ng_bypass(hook_p hook1, hook_p hook2);
1140342669Sphiliphook_p	ng_findhook(node_p node, const char *name);
1141342669Sphilipstruct	ng_type *ng_findtype(const char *type);
1142307362Sbaptint	ng_make_node_common(struct ng_type *typep, node_p *nodep);
1143325160Sphilipint	ng_name_node(node_p node, const char *name);
1144307362Sbaptnode_p	ng_name2noderef(node_p node, const char *name);
1145307362Sbaptint	ng_newtype(struct ng_type *tp);
1146307362Sbaptng_ID_t ng_node2ID(node_p node);
1147307362Sbaptitem_p	ng_package_data(struct mbuf *m, int flags);
1148307362Sbaptitem_p	ng_package_msg(struct ng_mesg *msg, int flags);
1149307362Sbaptitem_p	ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg);
1150325160Sphilipvoid	ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr);
1151325160Sphilipint	ng_rmhook_self(hook_p hook);	/* if a node wants to kill a hook */
1152325160Sphilipint	ng_rmnode_self(node_p here);	/* if a node wants to suicide */
1153325160Sphilipint	ng_rmtype(struct ng_type *tp);
1154325160Sphilipint	ng_snd_item(item_p item, int queue);
1155325160Sphilipint 	ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, void *arg1,
1156325160Sphilip	int arg2);
1157325160Sphilipint 	ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void *arg1,
1158325160Sphilip	int arg2, int flags);
1159325160Sphilipint 	ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn,
1160325160Sphilip	void *arg1, int arg2, int flags);
1161325160Sphilipint	ng_uncallout(struct callout *c, node_p node);
1162325160Sphilipint	ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
1163325160Sphilip	    ng_item_fn *fn, void * arg1, int arg2);
1164325160Sphilip#define	ng_callout_init(c)	callout_init(c, 1)
1165325160Sphilip
1166325160Sphilip/* Flags for netgraph functions. */
1167325160Sphilip#define	NG_NOFLAGS	0x00000000	/* no special options */
1168325160Sphilip#define	NG_QUEUE	0x00000001	/* enqueue item, don't dispatch */
1169325160Sphilip#define	NG_WAITOK	0x00000002	/* use M_WAITOK, etc. */
1170325160Sphilip/* XXXGL: NG_PROGRESS unused since ng_base.c rev. 1.136. Should be deleted? */
1171325160Sphilip#define	NG_PROGRESS	0x00000004	/* return EINPROGRESS if queued */
1172325160Sphilip#define	NG_REUSE_ITEM	0x00000008	/* supplied item should be reused */
1173325160Sphilip
1174325160Sphilip/*
1175325160Sphilip * prototypes the user should DEFINITELY not use directly
1176325160Sphilip */
1177325160Sphilipvoid	ng_free_item(item_p item); /* Use NG_FREE_ITEM instead */
1178325160Sphilipint	ng_mod_event(module_t mod, int what, void *arg);
1179325160Sphilip
1180325160Sphilip/*
1181325160Sphilip * Tag definitions and constants
1182325160Sphilip */
1183325160Sphilip
1184325160Sphilip#define	NG_TAG_PRIO	1
1185325160Sphilip
1186325160Sphilipstruct ng_tag_prio {
1187325160Sphilip	struct m_tag	tag;
1188325160Sphilip	char	priority;
11892742Swollman	char	discardability;
1190325160Sphilip};
1191325160Sphilip
1192325160Sphilip#define	NG_PRIO_CUTOFF		32
1193325160Sphilip#define	NG_PRIO_LINKSTATE	64
1194325160Sphilip
11952742Swollman/* Macros and declarations to keep compatibility with metadata, which
1196316350Sbapt * is obsoleted now. To be deleted.
11972742Swollman */
1198325160Sphiliptypedef void *meta_p;
11992742Swollman#define _NGI_META(i)	NULL
12002742Swollman#define NGI_META(i)	NULL
12012742Swollman#define NG_FREE_META(meta)
12022742Swollman#define NGI_GET_META(i,m)
12032742Swollman#define	ng_copy_meta(meta) NULL
120486222Swollman
1205273719Sedwin/*
1206273719Sedwin * Mark the current thread when called from the outbound path of the
1207273719Sedwin * network stack, in order to enforce queuing on ng nodes calling into
1208273719Sedwin * the inbound network stack path.
1209158421Swollman */
1210273719Sedwin#define NG_OUTBOUND_THREAD_REF()					\
121186222Swollman	curthread->td_ng_outbound++
121286222Swollman#define NG_OUTBOUND_THREAD_UNREF()					\
121386222Swollman	do {								\
121486222Swollman		curthread->td_ng_outbound--;				\
1215169811Swollman		KASSERT(curthread->td_ng_outbound >= 0,			\
1216169811Swollman		    ("%s: negative td_ng_outbound", __func__));		\
1217169811Swollman	} while (0)
1218169811Swollman
1219169811Swollman#endif /* _NETGRAPH_NETGRAPH_H_ */
1220169811Swollman