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