2 * Copyright (c) 1996-1999 Whistle Communications, Inc.
5 * Subject to the following obligations and disclaimer of warranty, use and
6 * redistribution of this software, in source or object code forms, with or
7 * without modifications are expressly permitted by Whistle Communications;
8 * provided, however, that:
9 * 1. Any and all reproductions of the source or object code must include the
10 * copyright notice above and the following disclaimer of warranties; and
11 * 2. No rights are granted, in any manner or form, to use Whistle
12 * Communications, Inc. trademarks, including the mark "WHISTLE
13 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as
14 * such appears in the above copyright notice or in the software.
16 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
17 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
18 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
19 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
21 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
22 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
23 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
24 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
25 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
26 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
27 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
34 * Authors: Julian Elischer <julian@freebsd.org>
35 * Archie Cobbs <archie@freebsd.org>
37 * $FreeBSD: src/sys/netgraph/ng_base.c,v 1.159 2008/04/19 05:30:49 mav Exp $
38 * $Whistle: ng_base.c,v 1.39 1999/01/28 23:54:53 julian Exp $
42 * This file implements the base netgraph code.
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/ctype.h>
48 #include <sys/errno.h>
50 /*#include <sys/kdb.h>*/
51 #include <sys/kernel.h>
52 #include <sys/limits.h>
53 #include <sys/malloc.h>
55 #include <sys/msgport2.h>
56 #include <sys/mutex2.h>
57 #include <sys/objcache.h>
59 #include <sys/queue.h>
60 #include <sys/refcount.h>
61 #include <sys/sysctl.h>
62 #include <sys/syslog.h>
63 #include <machine/cpu.h>
65 #include <netgraph7/netgraph.h>
66 #include <netgraph7/netgraph2.h>
67 #include <netgraph7/ng_parse.h>
69 MODULE_VERSION(netgraph, NG_ABI_VERSION);
71 /* Token to protect topology events. */
72 static struct lwkt_token ng_topo_token;
73 #define TOPOLOGY_RLOCK() lwkt_gettoken_shared(&ng_topo_token)
74 #define TOPOLOGY_RUNLOCK() lwkt_reltoken(&ng_topo_token)
75 #define TOPOLOGY_WLOCK() lwkt_gettoken(&ng_topo_token)
76 #define TOPOLOGY_WUNLOCK() lwkt_reltoken(&ng_topo_token)
77 #define TOPOLOGY_NOTOWNED() KKASSERT(!LWKT_TOKEN_HELD_ANY(&ng_topo_token))
80 static struct mtx ng_nodelist_mtx; /* protects global node/hook lists */
81 static struct mtx ngq_mtx; /* protects the queue item list */
83 static SLIST_HEAD(, ng_node) ng_allnodes;
84 static LIST_HEAD(, ng_node) ng_freenodes; /* in debug, we never free() them */
85 static SLIST_HEAD(, ng_hook) ng_allhooks;
86 static LIST_HEAD(, ng_hook) ng_freehooks; /* in debug, we never free() them */
88 static void ng_dumpitems(void);
89 static void ng_dumpnodes(void);
90 static void ng_dumphooks(void);
92 #endif /* NETGRAPH_DEBUG */
94 * DEAD versions of the structures.
95 * In order to avoid races, it is sometimes necessary to point
96 * at SOMETHING even though theoretically, the current entity is
97 * INVALID. Use these to avoid these races.
99 struct ng_type ng_deadtype = {
103 NULL, /* constructor */
110 NULL, /* disconnect */
114 struct ng_node ng_deadnode = {
121 LIST_HEAD_INITIALIZER(ng_deadnode.hooks),
122 {}, /* all_nodes list entry */
123 {}, /* id hashtable list entry */
131 #ifdef NETGRAPH_DEBUG
136 #endif /* NETGRAPH_DEBUG */
139 struct ng_hook ng_deadhook = {
142 HK_INVALID | HK_DEAD,
143 0, /* undefined data link type */
144 &ng_deadhook, /* Peer is self */
145 &ng_deadnode, /* attached to deadnode */
147 NULL, /* override rcvmsg() */
148 NULL, /* override rcvdata() */
149 1, /* refs always >= 1 */
150 #ifdef NETGRAPH_DEBUG
155 #endif /* NETGRAPH_DEBUG */
159 * END DEAD STRUCTURES
162 /* We don't want our messages to be replied. This is our panic reply port. */
163 static struct lwkt_port ng_panic_reply_port;
165 /* Array of per-CPU target ports */
166 struct lwkt_port *ng_msgport[MAXCPU];
168 /* List of installed types */
169 static LIST_HEAD(, ng_type) ng_typelist;
170 static struct lwkt_token ng_typelist_token;
171 #define TYPELIST_RLOCK() lwkt_gettoken_shared(&ng_typelist_token)
172 #define TYPELIST_RUNLOCK() lwkt_reltoken(&ng_typelist_token)
173 #define TYPELIST_WLOCK() lwkt_gettoken(&ng_typelist_token)
174 #define TYPELIST_WUNLOCK() lwkt_reltoken(&ng_typelist_token)
176 /* Hash related definitions */
177 LIST_HEAD(nodehash, ng_node);
178 static struct nodehash *ng_ID_hash;
179 static u_long ng_ID_hmask;
180 static u_long ng_nodes;
181 static struct nodehash *ng_name_hash;
182 static u_long ng_name_hmask;
183 static u_long ng_named_nodes;
184 static struct lwkt_token ng_idhash_token;
185 #define IDHASH_RLOCK() lwkt_gettoken_shared(&ng_idhash_token)
186 #define IDHASH_RUNLOCK() lwkt_reltoken(&ng_idhash_token)
187 #define IDHASH_WLOCK() lwkt_gettoken(&ng_idhash_token)
188 #define IDHASH_WUNLOCK() lwkt_reltoken(&ng_idhash_token)
189 #define IDHASH_ASSERT_LOCKED() KKASSERT(LWKT_TOKEN_HELD_ANY(&ng_idhash_token));
190 /* Method to find a node.. used twice so do it here */
191 #define NG_IDHASH_FN(ID) ((ID) % (ng_ID_hmask + 1))
192 #define NG_IDHASH_FIND(ID, node) \
194 IDHASH_ASSERT_LOCKED(); \
195 LIST_FOREACH(node, &ng_ID_hash[NG_IDHASH_FN(ID)], \
197 if (NG_NODE_IS_VALID(node) \
198 && (NG_NODE_ID(node) == ID)) { \
204 static struct lwkt_token ng_namehash_token;
205 #define NAMEHASH_RLOCK() lwkt_gettoken_shared(&ng_namehash_token)
206 #define NAMEHASH_RUNLOCK() lwkt_reltoken(&ng_namehash_token)
207 #define NAMEHASH_WLOCK() lwkt_gettoken(&ng_namehash_token)
208 #define NAMEHASH_WUNLOCK() lwkt_reltoken(&ng_namehash_token)
209 #define NAMEHASH_ASSERT_LOCKED() KKASSERT(LWKT_TOKEN_HELD_ANY(&ng_namehash_token));
211 /* Internal functions */
212 static int ng_add_hook(node_p node, const char *name, hook_p * hookp);
213 static int ng_generic_msg(node_p here, item_p item, hook_p lasthook);
214 static ng_ID_t ng_decodeidname(const char *name);
215 static int ngb_mod_event(module_t mod, int event, void *data);
216 static void ngthread(void *dummy);
217 static int ng_apply_item(item_p item);
218 static node_p ng_ID2noderef(ng_ID_t ID);
219 static int ng_con_nodes(item_p item, node_p node, const char *name,
220 node_p node2, const char *name2);
221 static int ng_con_part2(node_p node, item_p item, hook_p hook);
222 static int ng_con_part3(node_p node, item_p item, hook_p hook);
223 static int ng_mkpeer(node_p node, const char *name, const char *name2,
225 static void ng_name_rehash(void);
226 static void ng_ID_rehash(void);
227 static void ng_check_apply(item_p item, int error);
228 static boolean_t bzero_ctor(void *obj, void *private, int ocflags);
230 /* Imported, these used to be externally visible, some may go back. */
231 void ng_destroy_hook(hook_p hook);
232 node_p ng_name2noderef(node_p node, const char *name);
233 int ng_path2noderef(node_p here, const char *path,
234 node_p *dest, hook_p *lasthook);
235 int ng_make_node(const char *type, node_p *nodepp);
236 int ng_path_parse(char *addr, char **node, char **path, char **hook);
237 void ng_rmnode(node_p node, hook_p dummy1, void *dummy2, int dummy3);
238 void ng_unname(node_p node);
241 /* Our own netgraph malloc type */
242 MALLOC_DEFINE(M_NETGRAPH, "netgraph", "netgraph structures and ctrl messages");
243 MALLOC_DEFINE(M_NETGRAPH_HOOK, "netgraph_hook", "netgraph hook structures");
244 MALLOC_DEFINE(M_NETGRAPH_NODE, "netgraph_node", "netgraph node structures");
245 MALLOC_DEFINE(M_NETGRAPH_MSG, "netgraph_msg", "netgraph name storage");
246 MALLOC_DEFINE(M_NETGRAPH_APPLY, "netgraph_apply", "netgraph apply_info structures");
248 /* Should not be visible outside this file */
250 #define _NG_ALLOC_HOOK(hook) \
251 hook = kmalloc(sizeof(*hook), M_NETGRAPH_HOOK, \
252 M_WAITOK | M_NULLOK | M_ZERO)
253 #define _NG_ALLOC_NODE(node) \
254 node = kmalloc(sizeof(*node), M_NETGRAPH_NODE, \
255 M_WAITOK | M_NULLOK | M_ZERO)
257 #ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
260 * In an attempt to help track reference count screwups
261 * we do not free objects back to the malloc system, but keep them
262 * in a local cache where we can examine them and keep information safely
263 * after they have been freed.
264 * We use this scheme for nodes and hooks, and to some extent for items.
266 static __inline hook_p
270 SLIST_ENTRY(ng_hook) temp;
271 mtx_lock(&ng_nodelist_mtx);
272 hook = LIST_FIRST(&ng_freehooks);
274 LIST_REMOVE(hook, hk_hooks);
275 bcopy(&hook->hk_all, &temp, sizeof(temp));
276 bzero(hook, sizeof(struct ng_hook));
277 bcopy(&temp, &hook->hk_all, sizeof(temp));
278 mtx_unlock(&ng_nodelist_mtx);
279 hook->hk_magic = HK_MAGIC;
281 mtx_unlock(&ng_nodelist_mtx);
282 _NG_ALLOC_HOOK(hook);
284 hook->hk_magic = HK_MAGIC;
285 mtx_lock(&ng_nodelist_mtx);
286 SLIST_INSERT_HEAD(&ng_allhooks, hook, hk_all);
287 mtx_unlock(&ng_nodelist_mtx);
293 static __inline node_p
297 SLIST_ENTRY(ng_node) temp;
298 mtx_lock(&ng_nodelist_mtx);
299 node = LIST_FIRST(&ng_freenodes);
301 LIST_REMOVE(node, nd_nodes);
302 bcopy(&node->nd_all, &temp, sizeof(temp));
303 bzero(node, sizeof(struct ng_node));
304 bcopy(&temp, &node->nd_all, sizeof(temp));
305 mtx_unlock(&ng_nodelist_mtx);
306 node->nd_magic = ND_MAGIC;
308 mtx_unlock(&ng_nodelist_mtx);
309 _NG_ALLOC_NODE(node);
311 node->nd_magic = ND_MAGIC;
312 mtx_lock(&ng_nodelist_mtx);
313 SLIST_INSERT_HEAD(&ng_allnodes, node, nd_all);
314 mtx_unlock(&ng_nodelist_mtx);
320 #define NG_ALLOC_HOOK(hook) do { (hook) = ng_alloc_hook(); } while (0)
321 #define NG_ALLOC_NODE(node) do { (node) = ng_alloc_node(); } while (0)
324 #define NG_FREE_HOOK(hook) \
326 mtx_lock(&ng_nodelist_mtx); \
327 LIST_INSERT_HEAD(&ng_freehooks, hook, hk_hooks); \
328 hook->hk_magic = 0; \
329 mtx_unlock(&ng_nodelist_mtx); \
332 #define NG_FREE_NODE(node) \
334 mtx_lock(&ng_nodelist_mtx); \
335 LIST_INSERT_HEAD(&ng_freenodes, node, nd_nodes); \
336 node->nd_magic = 0; \
337 mtx_unlock(&ng_nodelist_mtx); \
340 #else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
342 #define NG_ALLOC_HOOK(hook) _NG_ALLOC_HOOK(hook)
343 #define NG_ALLOC_NODE(node) _NG_ALLOC_NODE(node)
345 #define NG_FREE_HOOK(hook) do { kfree((hook), M_NETGRAPH_HOOK); } while (0)
346 #define NG_FREE_NODE(node) do { kfree((node), M_NETGRAPH_NODE); } while (0)
348 #endif /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
350 /* Set this to kdb_enter("X") to catch all errors as they occur */
355 static ng_ID_t nextID = 1;
358 #define CHECK_DATA_MBUF(m) do { \
363 for (total = 0, n = (m); n != NULL; n = n->m_next) { \
365 if (n->m_nextpkt != NULL) \
366 panic("%s: m_nextpkt", __func__); \
369 if ((m)->m_pkthdr.len != total) { \
370 panic("%s: %d != %d", \
371 __func__, (m)->m_pkthdr.len, total); \
375 #define CHECK_DATA_MBUF(m)
378 #define ERROUT(x) do { error = (x); goto done; } while (0)
380 /************************************************************************
381 Parse type definitions for generic messages
382 ************************************************************************/
384 /* Handy structure parse type defining macro */
385 #define DEFINE_PARSE_STRUCT_TYPE(lo, up, args) \
386 static const struct ng_parse_struct_field \
387 ng_ ## lo ## _type_fields[] = NG_GENERIC_ ## up ## _INFO args; \
388 static const struct ng_parse_type ng_generic_ ## lo ## _type = { \
389 &ng_parse_struct_type, \
390 &ng_ ## lo ## _type_fields \
393 DEFINE_PARSE_STRUCT_TYPE(mkpeer, MKPEER, ());
394 DEFINE_PARSE_STRUCT_TYPE(connect, CONNECT, ());
395 DEFINE_PARSE_STRUCT_TYPE(name, NAME, ());
396 DEFINE_PARSE_STRUCT_TYPE(rmhook, RMHOOK, ());
397 DEFINE_PARSE_STRUCT_TYPE(nodeinfo, NODEINFO, ());
398 DEFINE_PARSE_STRUCT_TYPE(typeinfo, TYPEINFO, ());
399 DEFINE_PARSE_STRUCT_TYPE(linkinfo, LINKINFO, (&ng_generic_nodeinfo_type));
401 /* Get length of an array when the length is stored as a 32 bit
402 value immediately preceding the array -- as with struct namelist
403 and struct typelist. */
405 ng_generic_list_getLength(const struct ng_parse_type *type,
406 const u_char *start, const u_char *buf)
408 return *((const u_int32_t *)(buf - 4));
411 /* Get length of the array of struct linkinfo inside a struct hooklist */
413 ng_generic_linkinfo_getLength(const struct ng_parse_type *type,
414 const u_char *start, const u_char *buf)
416 const struct hooklist *hl = (const struct hooklist *)start;
418 return hl->nodeinfo.hooks;
421 /* Array type for a variable length array of struct namelist */
422 static const struct ng_parse_array_info ng_nodeinfoarray_type_info = {
423 &ng_generic_nodeinfo_type,
424 &ng_generic_list_getLength
426 static const struct ng_parse_type ng_generic_nodeinfoarray_type = {
427 &ng_parse_array_type,
428 &ng_nodeinfoarray_type_info
431 /* Array type for a variable length array of struct typelist */
432 static const struct ng_parse_array_info ng_typeinfoarray_type_info = {
433 &ng_generic_typeinfo_type,
434 &ng_generic_list_getLength
436 static const struct ng_parse_type ng_generic_typeinfoarray_type = {
437 &ng_parse_array_type,
438 &ng_typeinfoarray_type_info
441 /* Array type for array of struct linkinfo in struct hooklist */
442 static const struct ng_parse_array_info ng_generic_linkinfo_array_type_info = {
443 &ng_generic_linkinfo_type,
444 &ng_generic_linkinfo_getLength
446 static const struct ng_parse_type ng_generic_linkinfo_array_type = {
447 &ng_parse_array_type,
448 &ng_generic_linkinfo_array_type_info
451 DEFINE_PARSE_STRUCT_TYPE(typelist, TYPELIST, (&ng_generic_typeinfoarray_type));
452 DEFINE_PARSE_STRUCT_TYPE(hooklist, HOOKLIST,
453 (&ng_generic_nodeinfo_type, &ng_generic_linkinfo_array_type));
454 DEFINE_PARSE_STRUCT_TYPE(listnodes, LISTNODES,
455 (&ng_generic_nodeinfoarray_type));
457 /* List of commands and how to convert arguments to/from ASCII */
458 static const struct ng_cmdlist ng_generic_cmds[] = {
470 &ng_generic_mkpeer_type,
477 &ng_generic_connect_type,
484 &ng_generic_name_type,
491 &ng_generic_rmhook_type,
499 &ng_generic_nodeinfo_type
506 &ng_generic_hooklist_type
513 &ng_generic_listnodes_type /* same as NGM_LISTNODES */
520 &ng_generic_listnodes_type
527 &ng_generic_typeinfo_type
534 &ng_parse_string_type
541 &ng_parse_string_type
547 &ng_parse_ng_mesg_type,
548 &ng_parse_ng_mesg_type
554 &ng_parse_ng_mesg_type,
555 &ng_parse_ng_mesg_type
560 /************************************************************************
562 ************************************************************************/
565 * Instantiate a node of the requested type
568 ng_make_node(const char *typename, node_p *nodepp)
570 struct ng_type *type;
573 /* Check that the type makes sense */
574 if (typename == NULL) {
579 /* Locate the node type. If we fail we return. Do not try to load
582 if ((type = ng_findtype(typename)) == NULL)
586 * If we have a constructor, then make the node and
587 * call the constructor to do type specific initialisation.
589 if (type->constructor != NULL) {
590 if ((error = ng_make_node_common(type, nodepp)) == 0) {
591 if ((error = ((*type->constructor)(*nodepp)) != 0)) {
592 NG_NODE_UNREF(*nodepp);
597 * Node has no constructor. We cannot ask for one
598 * to be made. It must be brought into existence by
599 * some external agency. The external agency should
600 * call ng_make_node_common() directly to get the
601 * netgraph part initialised.
610 * Generic node creation. Called by node initialisation for externally
611 * instantiated nodes (e.g. hardware, sockets, etc ).
612 * The returned node has a reference count of 1.
615 ng_make_node_common(struct ng_type *type, node_p *nodepp)
619 /* Require the node type to have been already installed */
620 if (ng_findtype(type->name) == NULL) {
625 /* Make a node and try attach it to the type */
631 node->nd_type = type;
632 NG_NODE_REF(node); /* note reference */
635 /* Initialize the reader/writer shared token */
636 lwkt_token_init(&node->nd_token, type->name);
638 /* Initialize hook list for new node */
639 LIST_INIT(&node->nd_hooks);
641 /* Get an ID and put us in the hash chain. */
643 for (;;) { /* wrap protection, even if silly */
645 node->nd_ID = nextID++; /* 137/second for 1 year before wrap */
647 /* Is there a problem with the new number? */
648 NG_IDHASH_FIND(node->nd_ID, node2); /* already taken? */
649 if ((node->nd_ID != 0) && (node2 == NULL)) {
654 if (ng_nodes * 2 > ng_ID_hmask)
656 LIST_INSERT_HEAD(&ng_ID_hash[NG_IDHASH_FN(node->nd_ID)], node,
666 * Forceably start the shutdown process on a node. Either call
667 * its shutdown method, or do the default shutdown if there is
668 * no type-specific method.
670 * We can only be called from a shutdown message, so we know we have
671 * a writer lock, and therefore exclusive access.
673 * Persistent node types must have a type-specific method which
674 * allocates a new node in which case, this one is irretrievably going away,
675 * or cleans up anything it needs, and just makes the node valid again,
676 * in which case we allow the node to survive.
678 * XXX We need to think of how to tell a persistent node that we
679 * REALLY need to go away because the hardware has gone or we
680 * are rebooting.... etc.
683 ng_rmnode(node_p node, hook_p dummy1, void *dummy2, int dummy3)
687 /* Check if it's already shutting down */
688 if ((node->nd_flags & NGF_CLOSING) != 0)
691 if (node == &ng_deadnode) {
692 printf ("shutdown called on deadnode\n");
696 /* Add an extra reference so it doesn't go away during this */
700 * Mark it invalid so any newcomers know not to try use it
701 * Also add our own mark so we can't recurse
702 * note that NGF_INVALID does not do this as it's also set during
705 node->nd_flags |= NGF_INVALID|NGF_CLOSING;
707 /* If node has its pre-shutdown method, then call it first*/
708 if (node->nd_type && node->nd_type->close)
709 (*node->nd_type->close)(node);
711 /* Notify all remaining connected nodes to disconnect */
712 while ((hook = LIST_FIRST(&node->nd_hooks)) != NULL)
713 ng_destroy_hook(hook);
715 /* Ask the type if it has anything to do in this case */
716 if (node->nd_type && node->nd_type->shutdown) {
717 (*node->nd_type->shutdown)(node);
718 if (NG_NODE_IS_VALID(node)) {
720 * Well, blow me down if the node code hasn't declared
721 * that it doesn't want to die.
722 * Presumably it is a persistant node.
723 * If we REALLY want it to go away,
724 * e.g. hardware going away,
725 * Our caller should set NGF_REALLY_DIE in nd_flags.
727 node->nd_flags &= ~(NGF_INVALID|NGF_CLOSING);
728 NG_NODE_UNREF(node); /* Assume they still have theirs */
731 } else { /* do the default thing */
735 ng_unname(node); /* basically a NOP these days */
738 * Remove extra reference, possibly the last
739 * Possible other holders of references may include
740 * timeout callouts, but theoretically the node's supposed to
741 * have cancelled them. Possibly hardware dependencies may
742 * force a driver to 'linger' with a reference.
748 * Remove a reference to the node, possibly the last.
749 * deadnode always acts as it it were the last.
752 ng_unref_node(node_p node)
755 if (node == &ng_deadnode)
759 if (refcount_release(&node->nd_refs)) { /* we were the last */
761 node->nd_type->refs--; /* XXX maybe should get types lock? */
763 if (NG_NODE_HAS_NAME(node)) {
765 LIST_REMOVE(node, nd_nodes);
771 LIST_REMOVE(node, nd_idnodes);
778 /************************************************************************
780 ************************************************************************/
782 ng_ID2noderef(ng_ID_t ID)
787 NG_IDHASH_FIND(ID, node);
795 ng_node2ID(node_p node)
797 return (node ? NG_NODE_ID(node) : 0);
800 /************************************************************************
802 ************************************************************************/
805 * Assign a node a name.
808 ng_name_node(node_p node, const char *name)
814 /* Check the name is valid */
815 for (i = 0; i < NG_NODESIZ; i++) {
816 if (name[i] == '\0' || name[i] == '.' || name[i] == ':')
819 if (i == 0 || name[i] != '\0') {
823 if (ng_decodeidname(name) != 0) { /* valid IDs not allowed here */
829 if (ng_named_nodes * 2 > ng_name_hmask)
832 hash = hash32_str(name, HASHINIT) & ng_name_hmask;
833 /* Check the name isn't already being used. */
834 LIST_FOREACH(node2, &ng_name_hash[hash], nd_nodes)
835 if (NG_NODE_IS_VALID(node2) &&
836 (strcmp(NG_NODE_NAME(node2), name) == 0)) {
841 if (NG_NODE_HAS_NAME(node))
842 LIST_REMOVE(node, nd_nodes);
846 strlcpy(NG_NODE_NAME(node), name, NG_NODESIZ);
848 /* Update name hash. */
849 LIST_INSERT_HEAD(&ng_name_hash[hash], node, nd_nodes);
856 * Find a node by absolute name. The name should NOT end with ':'
857 * The name "." means "this node" and "[xxx]" means "the node
858 * with ID (ie, at address) xxx".
860 * Returns the node if found, else NULL.
861 * Eventually should add something faster than a sequential search.
862 * Note it acquires a reference on the node so you can be sure it's still
866 ng_name2noderef(node_p here, const char *name)
872 /* "." means "this node" */
873 if (strcmp(name, ".") == 0) {
878 /* Check for name-by-ID */
879 if ((temp = ng_decodeidname(name)) != 0) {
880 return (ng_ID2noderef(temp));
883 /* Find node by name. */
884 hash = hash32_str(name, HASHINIT) & ng_name_hmask;
886 LIST_FOREACH(node, &ng_name_hash[hash], nd_nodes)
887 if (NG_NODE_IS_VALID(node) &&
888 (strcmp(NG_NODE_NAME(node), name) == 0)) {
898 * Decode an ID name, eg. "[f03034de]". Returns 0 if the
899 * string is not valid, otherwise returns the value.
902 ng_decodeidname(const char *name)
904 const int len = strlen(name);
908 /* Check for proper length, brackets, no leading junk */
911 || (name[len - 1] != ']')
912 || (!isxdigit(name[1]))) {
917 val = strtoul(name + 1, &eptr, 16);
918 if ((eptr - name != len - 1)
919 || (val == ULONG_MAX)
927 * Remove a name from a node. This should only be called
928 * when shutting down and removing the node.
931 ng_unname(node_p node)
936 * Allocate a bigger name hash.
941 struct nodehash *new;
947 NAMEHASH_ASSERT_LOCKED();
948 new = hashinit((ng_name_hmask + 1) * 2, M_NETGRAPH_NODE, &hmask);
952 for (i = 0; i <= ng_name_hmask; i++) {
953 LIST_FOREACH_MUTABLE(node, &ng_name_hash[i], nd_nodes, node2) {
955 LIST_REMOVE(node, nd_nodes);
957 hash = hash32_str(NG_NODE_NAME(node), HASHINIT) & hmask;
958 LIST_INSERT_HEAD(&new[hash], node, nd_nodes);
962 hashdestroy(ng_name_hash, M_NETGRAPH_NODE, ng_name_hmask);
964 ng_name_hmask = hmask;
968 * Allocate a bigger ID hash.
973 struct nodehash *new;
979 IDHASH_ASSERT_LOCKED();
980 new = hashinit((ng_ID_hmask + 1) * 2, M_NETGRAPH_NODE, &hmask);
984 for (i = 0; i <= ng_ID_hmask; i++) {
985 LIST_FOREACH_MUTABLE(node, &ng_ID_hash[i], nd_idnodes, node2) {
987 LIST_REMOVE(node, nd_idnodes);
989 hash = (node->nd_ID % (hmask + 1));
990 LIST_INSERT_HEAD(&new[hash], node, nd_idnodes);
994 hashdestroy(ng_ID_hash, M_NETGRAPH_NODE, ng_name_hmask);
999 /************************************************************************
1001 Names are not optional. Hooks are always connected, except for a
1002 brief moment within these routines. On invalidation or during creation
1003 they are connected to the 'dead' hook.
1004 ************************************************************************/
1007 * Remove a hook reference
1010 ng_unref_hook(hook_p hook)
1014 if (hook == &ng_deadhook) {
1018 v = atomic_fetchadd_int(&hook->hk_refs, -1);
1020 if (v == 1) { /* we were the last */
1021 if (_NG_HOOK_NODE(hook)) /* it'll probably be ng_deadnode */
1022 _NG_NODE_UNREF((_NG_HOOK_NODE(hook)));
1028 * Add an unconnected hook to a node. Only used internally.
1029 * Assumes node is locked. (XXX not yet true )
1032 ng_add_hook(node_p node, const char *name, hook_p *hookp)
1037 /* Check that the given name is good */
1042 if (ng_findhook(node, name) != NULL) {
1047 /* Allocate the hook and link it up */
1048 NG_ALLOC_HOOK(hook);
1053 hook->hk_refs = 1; /* add a reference for us to return */
1054 hook->hk_flags = HK_INVALID;
1055 hook->hk_peer = &ng_deadhook; /* start off this way */
1056 hook->hk_node = node;
1057 NG_NODE_REF(node); /* each hook counts as a reference */
1060 strlcpy(NG_HOOK_NAME(hook), name, NG_HOOKSIZ);
1063 * Check if the node type code has something to say about it
1064 * If it fails, the unref of the hook will also unref the node.
1066 if (node->nd_type->newhook != NULL) {
1067 if ((error = (*node->nd_type->newhook)(node, hook, name))) {
1068 NG_HOOK_UNREF(hook); /* this frees the hook */
1073 * The 'type' agrees so far, so go ahead and link it in.
1074 * We'll ask again later when we actually connect the hooks.
1076 LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
1077 node->nd_numhooks++;
1078 NG_HOOK_REF(hook); /* one for the node */
1088 * Node types may supply their own optimized routines for finding
1089 * hooks. If none is supplied, we just do a linear search.
1090 * XXX Possibly we should add a reference to the hook?
1093 ng_findhook(node_p node, const char *name)
1097 if (node->nd_type->findhook != NULL)
1098 return (*node->nd_type->findhook)(node, name);
1099 LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
1100 if (NG_HOOK_IS_VALID(hook)
1101 && (strcmp(NG_HOOK_NAME(hook), name) == 0))
1110 * As hooks are always attached, this really destroys two hooks.
1111 * The one given, and the one attached to it. Disconnect the hooks
1112 * from each other first. We reconnect the peer hook to the 'dead'
1113 * hook so that it can still exist after we depart. We then
1114 * send the peer its own destroy message. This ensures that we only
1115 * interact with the peer's structures when it is locked processing that
1116 * message. We hold a reference to the peer hook so we are guaranteed that
1117 * the peer hook and node are still going to exist until
1118 * we are finished there as the hook holds a ref on the node.
1119 * We run this same code again on the peer hook, but that time it is already
1120 * attached to the 'dead' hook.
1122 * This routine is called at all stages of hook creation
1123 * on error detection and must be able to handle any such stage.
1126 ng_destroy_hook(hook_p hook)
1131 if (hook == &ng_deadhook) { /* better safe than sorry */
1132 printf("ng_destroy_hook called on deadhook\n");
1137 * Protect divorce process with mutex, to avoid races on
1138 * simultaneous disconnect.
1142 hook->hk_flags |= HK_INVALID;
1144 peer = NG_HOOK_PEER(hook);
1145 node = NG_HOOK_NODE(hook);
1147 if (peer && (peer != &ng_deadhook)) {
1149 * Set the peer to point to ng_deadhook
1150 * from this moment on we are effectively independent it.
1151 * send it an rmhook message of it's own.
1153 peer->hk_peer = &ng_deadhook; /* They no longer know us */
1154 hook->hk_peer = &ng_deadhook; /* Nor us, them */
1155 if (NG_HOOK_NODE(peer) == &ng_deadnode) {
1157 * If it's already divorced from a node,
1163 ng_rmhook_self(peer); /* Send it a surprise */
1165 NG_HOOK_UNREF(peer); /* account for peer link */
1166 NG_HOOK_UNREF(hook); /* account for peer link */
1170 TOPOLOGY_NOTOWNED();
1173 * Remove the hook from the node's list to avoid possible recursion
1174 * in case the disconnection results in node shutdown.
1176 if (node == &ng_deadnode) { /* happens if called from ng_con_nodes() */
1179 LIST_REMOVE(hook, hk_hooks);
1180 node->nd_numhooks--;
1181 if (node->nd_type->disconnect) {
1183 * The type handler may elect to destroy the node so don't
1184 * trust its existence after this point. (except
1185 * that we still hold a reference on it. (which we
1186 * inherrited from the hook we are destroying)
1188 (*node->nd_type->disconnect) (hook);
1192 * Note that because we will point to ng_deadnode, the original node
1193 * is not decremented automatically so we do that manually.
1195 _NG_HOOK_NODE(hook) = &ng_deadnode;
1196 NG_NODE_UNREF(node); /* We no longer point to it so adjust count */
1197 NG_HOOK_UNREF(hook); /* Account for linkage (in list) to node */
1201 * Take two hooks on a node and merge the connection so that the given node
1202 * is effectively bypassed.
1205 ng_bypass(hook_p hook1, hook_p hook2)
1207 if (hook1->hk_node != hook2->hk_node) {
1211 hook1->hk_peer->hk_peer = hook2->hk_peer;
1212 hook2->hk_peer->hk_peer = hook1->hk_peer;
1214 hook1->hk_peer = &ng_deadhook;
1215 hook2->hk_peer = &ng_deadhook;
1217 NG_HOOK_UNREF(hook1);
1218 NG_HOOK_UNREF(hook2);
1220 /* XXX If we ever cache methods on hooks update them as well */
1221 ng_destroy_hook(hook1);
1222 ng_destroy_hook(hook2);
1227 * Install a new netgraph type
1230 ng_newtype(struct ng_type *tp)
1232 const size_t namelen = strlen(tp->name);
1234 /* Check version and type name fields */
1235 if ((tp->version != NG_ABI_VERSION)
1237 || (namelen >= NG_TYPESIZ)) {
1239 if (tp->version != NG_ABI_VERSION) {
1240 printf("Netgraph: Node type rejected. ABI mismatch. Suggest recompile\n");
1245 /* Check for name collision */
1246 if (ng_findtype(tp->name) != NULL) {
1251 /* Link in new type */
1253 LIST_INSERT_HEAD(&ng_typelist, tp, types);
1254 tp->refs = 1; /* first ref is linked list */
1260 * unlink a netgraph type
1261 * If no examples exist
1264 ng_rmtype(struct ng_type *tp)
1266 /* Check for name collision */
1267 if (tp->refs != 1) {
1274 LIST_REMOVE(tp, types);
1280 * Look for a type of the name given
1283 ng_findtype(const char *typename)
1285 struct ng_type *type;
1288 LIST_FOREACH(type, &ng_typelist, types) {
1289 if (strcmp(type->name, typename) == 0)
1296 /************************************************************************
1298 ************************************************************************/
1300 * Connect two nodes using the specified hooks, using queued functions.
1303 ng_con_part3(node_p node, item_p item, hook_p hook)
1308 * When we run, we know that the node 'node' is locked for us.
1309 * Our caller has a reference on the hook.
1310 * Our caller has a reference on the node.
1311 * (In this case our caller is ng_apply_item() ).
1312 * The peer hook has a reference on the hook.
1313 * We are all set up except for the final call to the node, and
1314 * the clearing of the INVALID flag.
1316 if (NG_HOOK_NODE(hook) == &ng_deadnode) {
1318 * The node must have been freed again since we last visited
1319 * here. ng_destry_hook() has this effect but nothing else does.
1320 * We should just release our references and
1321 * free anything we can think of.
1322 * Since we know it's been destroyed, and it's our caller
1323 * that holds the references, just return.
1327 if (hook->hk_node->nd_type->connect) {
1328 if ((error = (*hook->hk_node->nd_type->connect) (hook))) {
1329 ng_destroy_hook(hook); /* also zaps peer */
1330 printf("failed in ng_con_part3()\n");
1335 * XXX this is wrong for SMP. Possibly we need
1336 * to separate out 'create' and 'invalid' flags.
1337 * should only set flags on hooks we have locked under our node.
1339 hook->hk_flags &= ~HK_INVALID;
1346 ng_con_part2(node_p node, item_p item, hook_p hook)
1352 * When we run, we know that the node 'node' is locked for us.
1353 * Our caller has a reference on the hook.
1354 * Our caller has a reference on the node.
1355 * (In this case our caller is ng_apply_item() ).
1356 * The peer hook has a reference on the hook.
1357 * our node pointer points to the 'dead' node.
1358 * First check the hook name is unique.
1359 * Should not happen because we checked before queueing this.
1361 if (ng_findhook(node, NG_HOOK_NAME(hook)) != NULL) {
1363 ng_destroy_hook(hook); /* should destroy peer too */
1364 printf("failed in ng_con_part2()\n");
1368 * Check if the node type code has something to say about it
1369 * If it fails, the unref of the hook will also unref the attached node,
1370 * however since that node is 'ng_deadnode' this will do nothing.
1371 * The peer hook will also be destroyed.
1373 if (node->nd_type->newhook != NULL) {
1374 if ((error = (*node->nd_type->newhook)(node, hook,
1376 ng_destroy_hook(hook); /* should destroy peer too */
1377 printf("failed in ng_con_part2()\n");
1383 * The 'type' agrees so far, so go ahead and link it in.
1384 * We'll ask again later when we actually connect the hooks.
1386 hook->hk_node = node; /* just overwrite ng_deadnode */
1387 NG_NODE_REF(node); /* each hook counts as a reference */
1388 LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
1389 node->nd_numhooks++;
1390 NG_HOOK_REF(hook); /* one for the node */
1393 * We now have a symmetrical situation, where both hooks have been
1394 * linked to their nodes, the newhook methods have been called
1395 * And the references are all correct. The hooks are still marked
1396 * as invalid, as we have not called the 'connect' methods
1398 * We can call the local one immediately as we have the
1399 * node locked, but we need to queue the remote one.
1401 if (hook->hk_node->nd_type->connect) {
1402 if ((error = (*hook->hk_node->nd_type->connect) (hook))) {
1403 ng_destroy_hook(hook); /* also zaps peer */
1404 printf("failed in ng_con_part2(A)\n");
1410 * Acquire topo token to avoid race with ng_destroy_hook().
1413 peer = hook->hk_peer;
1414 if (peer == &ng_deadhook) {
1416 printf("failed in ng_con_part2(B)\n");
1417 ng_destroy_hook(hook);
1422 if ((error = ng_send_fn2(peer->hk_node, peer, item, &ng_con_part3,
1423 NULL, 0, NG_REUSE_ITEM))) {
1424 printf("failed in ng_con_part2(C)\n");
1425 ng_destroy_hook(hook); /* also zaps peer */
1426 return (error); /* item was consumed. */
1428 hook->hk_flags &= ~HK_INVALID; /* need both to be able to work */
1429 return (0); /* item was consumed. */
1436 * Connect this node with another node. We assume that this node is
1437 * currently locked, as we are only called from an NGM_CONNECT message.
1440 ng_con_nodes(item_p item, node_p node, const char *name,
1441 node_p node2, const char *name2)
1447 if (ng_findhook(node2, name2) != NULL) {
1450 if ((error = ng_add_hook(node, name, &hook))) /* gives us a ref */
1452 /* Allocate the other hook and link it up */
1453 NG_ALLOC_HOOK(hook2);
1454 if (hook2 == NULL) {
1456 ng_destroy_hook(hook); /* XXX check ref counts so far */
1457 NG_HOOK_UNREF(hook); /* including our ref */
1460 hook2->hk_refs = 1; /* start with a reference for us. */
1461 hook2->hk_flags = HK_INVALID;
1462 hook2->hk_peer = hook; /* Link the two together */
1463 hook->hk_peer = hook2;
1464 NG_HOOK_REF(hook); /* Add a ref for the peer to each*/
1466 hook2->hk_node = &ng_deadnode;
1467 strlcpy(NG_HOOK_NAME(hook2), name2, NG_HOOKSIZ);
1470 * Queue the function above.
1471 * Procesing continues in that function in the lock context of
1474 if ((error = ng_send_fn2(node2, hook2, item, &ng_con_part2, NULL, 0,
1476 printf("failed in ng_con_nodes(): %d\n", error);
1477 ng_destroy_hook(hook); /* also zaps peer */
1480 NG_HOOK_UNREF(hook); /* Let each hook go if it wants to */
1481 NG_HOOK_UNREF(hook2);
1486 * Make a peer and connect.
1487 * We assume that the local node is locked.
1488 * The new node probably doesn't need a lock until
1489 * it has a hook, because it cannot really have any work until then,
1490 * but we should think about it a bit more.
1492 * The problem may come if the other node also fires up
1493 * some hardware or a timer or some other source of activation,
1494 * also it may already get a command msg via it's ID.
1496 * We could use the same method as ng_con_nodes() but we'd have
1497 * to add ability to remove the node when failing. (Not hard, just
1498 * make arg1 point to the node to remove).
1499 * Unless of course we just ignore failure to connect and leave
1500 * an unconnected node?
1503 ng_mkpeer(node_p node, const char *name, const char *name2, char *type)
1506 hook_p hook1, hook2;
1509 if ((error = ng_make_node(type, &node2))) {
1513 if ((error = ng_add_hook(node, name, &hook1))) { /* gives us a ref */
1514 ng_rmnode(node2, NULL, NULL, 0);
1518 if ((error = ng_add_hook(node2, name2, &hook2))) {
1519 ng_rmnode(node2, NULL, NULL, 0);
1520 ng_destroy_hook(hook1);
1521 NG_HOOK_UNREF(hook1);
1526 * Actually link the two hooks together.
1528 hook1->hk_peer = hook2;
1529 hook2->hk_peer = hook1;
1531 /* Each hook is referenced by the other */
1535 /* Give each node the opportunity to veto the pending connection */
1536 if (hook1->hk_node->nd_type->connect) {
1537 error = (*hook1->hk_node->nd_type->connect) (hook1);
1540 if ((error == 0) && hook2->hk_node->nd_type->connect) {
1541 error = (*hook2->hk_node->nd_type->connect) (hook2);
1546 * drop the references we were holding on the two hooks.
1549 ng_destroy_hook(hook2); /* also zaps hook1 */
1550 ng_rmnode(node2, NULL, NULL, 0);
1552 /* As a last act, allow the hooks to be used */
1553 hook1->hk_flags &= ~HK_INVALID;
1554 hook2->hk_flags &= ~HK_INVALID;
1556 NG_HOOK_UNREF(hook1);
1557 NG_HOOK_UNREF(hook2);
1561 /************************************************************************
1562 Utility routines to send self messages
1563 ************************************************************************/
1565 /* Shut this node down as soon as everyone is clear of it */
1566 /* Should add arg "immediately" to jump the queue */
1568 ng_rmnode_self(node_p node)
1572 if (node == &ng_deadnode)
1574 node->nd_flags |= NGF_INVALID;
1575 if (node->nd_flags & NGF_CLOSING)
1578 error = ng_send_fn(node, NULL, &ng_rmnode, NULL, 0);
1583 ng_rmhook_part2(node_p node, hook_p hook, void *arg1, int arg2)
1585 ng_destroy_hook(hook);
1590 ng_rmhook_self(hook_p hook)
1593 node_p node = NG_HOOK_NODE(hook);
1595 if (node == &ng_deadnode)
1598 error = ng_send_fn(node, hook, &ng_rmhook_part2, NULL, 0);
1602 /***********************************************************************
1603 * Parse and verify a string of the form: <NODE:><PATH>
1605 * Such a string can refer to a specific node or a specific hook
1606 * on a specific node, depending on how you look at it. In the
1607 * latter case, the PATH component must not end in a dot.
1609 * Both <NODE:> and <PATH> are optional. The <PATH> is a string
1610 * of hook names separated by dots. This breaks out the original
1611 * string, setting *nodep to "NODE" (or NULL if none) and *pathp
1612 * to "PATH" (or NULL if degenerate). Also, *hookp will point to
1613 * the final hook component of <PATH>, if any, otherwise NULL.
1615 * This returns -1 if the path is malformed. The char ** are optional.
1616 ***********************************************************************/
1618 ng_path_parse(char *addr, char **nodep, char **pathp, char **hookp)
1620 char *node, *path, *hook;
1624 * Extract absolute NODE, if any
1626 for (path = addr; *path && *path != ':'; path++);
1628 node = addr; /* Here's the NODE */
1629 *path++ = '\0'; /* Here's the PATH */
1631 /* Node name must not be empty */
1635 /* A name of "." is OK; otherwise '.' not allowed */
1636 if (strcmp(node, ".") != 0) {
1637 for (k = 0; node[k]; k++)
1642 node = NULL; /* No absolute NODE */
1643 path = addr; /* Here's the PATH */
1646 /* Snoop for illegal characters in PATH */
1647 for (k = 0; path[k]; k++)
1651 /* Check for no repeated dots in PATH */
1652 for (k = 0; path[k]; k++)
1653 if (path[k] == '.' && path[k + 1] == '.')
1656 /* Remove extra (degenerate) dots from beginning or end of PATH */
1659 if (*path && path[strlen(path) - 1] == '.')
1660 path[strlen(path) - 1] = 0;
1662 /* If PATH has a dot, then we're not talking about a hook */
1664 for (hook = path, k = 0; path[k]; k++)
1665 if (path[k] == '.') {
1683 * Given a path, which may be absolute or relative, and a starting node,
1684 * return the destination node.
1687 ng_path2noderef(node_p here, const char *address,
1688 node_p *destp, hook_p *lasthook)
1690 char fullpath[NG_PATHSIZ];
1691 char *nodename, *path, pbuf[2];
1692 node_p node, oldnode;
1697 if (destp == NULL) {
1703 /* Make a writable copy of address for ng_path_parse() */
1704 strncpy(fullpath, address, sizeof(fullpath) - 1);
1705 fullpath[sizeof(fullpath) - 1] = '\0';
1707 /* Parse out node and sequence of hooks */
1708 if (ng_path_parse(fullpath, &nodename, &path, NULL) < 0) {
1713 pbuf[0] = '.'; /* Needs to be writable */
1719 * For an absolute address, jump to the starting node.
1720 * Note that this holds a reference on the node for us.
1721 * Don't forget to drop the reference if we don't need it.
1724 node = ng_name2noderef(here, nodename);
1739 * Now follow the sequence of hooks
1741 * We actually cannot guarantee that the sequence
1742 * is not being demolished as we crawl along it
1743 * without extra-ordinary locking etc.
1744 * So this is a bit dodgy to say the least.
1745 * We can probably hold up some things by holding
1746 * the nodelist mutex for the time of this
1747 * crawl if we wanted.. At least that way we wouldn't have to
1748 * worry about the nodes disappearing, but the hooks would still
1751 for (cp = path; node != NULL && *cp != '\0'; ) {
1755 * Break out the next path segment. Replace the dot we just
1756 * found with a NUL; "cp" points to the next segment (or the
1759 for (segment = cp; *cp != '\0'; cp++) {
1767 if (*segment == '\0')
1770 /* We have a segment, so look for a hook by that name */
1771 hook = ng_findhook(node, segment);
1773 /* Can't get there from here... */
1775 || NG_HOOK_PEER(hook) == NULL
1776 || NG_HOOK_NOT_VALID(hook)
1777 || NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) {
1779 NG_NODE_UNREF(node);
1781 printf("hooknotvalid %s %s %d %d %d %d ",
1785 NG_HOOK_PEER(hook) == NULL,
1786 NG_HOOK_NOT_VALID(hook),
1787 NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook)));
1793 * Hop on over to the next node
1795 * Big race conditions here as hooks and nodes go away
1796 * *** Idea.. store an ng_ID_t in each hook and use that
1797 * instead of the direct hook in this crawl?
1800 if ((node = NG_PEER_NODE(hook)))
1801 NG_NODE_REF(node); /* XXX RACE */
1802 NG_NODE_UNREF(oldnode); /* XXX another race */
1803 if (NG_NODE_NOT_VALID(node)) {
1804 NG_NODE_UNREF(node); /* XXX more races */
1809 /* If node somehow missing, fail here (probably this is not needed) */
1817 if (lasthook != NULL)
1818 *lasthook = (hook ? NG_HOOK_PEER(hook) : NULL);
1822 /*********************************************************************\
1823 * Inter-CPU node synchronization
1825 * All activities are submitted to one of the netgraph per-CPU threads.
1826 * There is one item input queue per CPU, not one per node as in
1827 * FreeBSD. If the item is entering netgraph for the first time, it is
1828 * queued to the thread's msgport. Otherwise it is applied directly.
1829 * From start to finish, the item is processed on the same CPU. Items
1830 * are distributed based on the ingress node, to keep item ordering.
1831 \***************************************************************/
1833 static __inline void ng_acquire_read(node_p node);
1834 static __inline void ng_acquire_write(node_p node);
1835 static __inline void ng_leave_readwrite(node_p node);
1837 static __inline void
1838 ng_acquire_read(node_p node)
1840 KASSERT(node != &ng_deadnode,
1841 ("%s: working on deadnode", __func__));
1843 lwkt_gettoken_shared(&node->nd_token);
1846 /* Acquire writer lock on node. If node is busy, sleep. */
1847 static __inline void
1848 ng_acquire_write(node_p node)
1850 KASSERT(node != &ng_deadnode,
1851 ("%s: working on deadnode", __func__));
1853 lwkt_gettoken(&node->nd_token);
1856 /* Release reader or writer lock. */
1857 static __inline void
1858 ng_leave_readwrite(node_p node)
1860 lwkt_reltoken(&node->nd_token);
1863 /***********************************************************************
1865 **********************************************************************/
1866 /* NETGRAPH thread routine
1868 * Pick an item from our thread's queue and apply it.
1871 ngthread(void *dummy __unused)
1875 while ((msg = lwkt_waitport(&curthread->td_msgport, 0)) != NULL) {
1876 item_p item = (void *)msg;
1878 ng_apply_item(item);
1879 /* Do not reply to the message */
1883 /***********************************************************************
1884 * Externally visible method for sending or queueing messages or data.
1885 ***********************************************************************/
1888 * The module code should have filled out the item correctly by this stage:
1890 * reference to destination node.
1891 * Reference to destination rcv hook if relevant.
1892 * apply pointer must be or NULL or reference valid struct ng_apply_info.
1897 * ID of original sender node. (return address)
1903 * The nodes have several routines and macros to help with this task:
1907 ng_snd_item(item_p item, int flags)
1913 /* We are sending item, so it must be present! */
1914 KASSERT(item != NULL, ("ng_snd_item: item is NULL"));
1916 #ifdef NETGRAPH_DEBUG
1917 _ngi_check(item, __FILE__, __LINE__);
1921 * Every time an item is sent or forwarded we hold a reference on it
1922 * to postone the callback (if there is one) and item freedom.
1924 refcount_acquire(&item->depth);
1927 * Node is never optional.
1929 node = NGI_NODE(item);
1930 KASSERT(node != NULL, ("ng_snd_item: node is NULL"));
1933 * Valid hook and mbuf are mandatory for data.
1935 hook = NGI_HOOK(item);
1936 if ((item->el_flags & NGQF_TYPE) == NGQF_DATA) {
1937 KASSERT(hook != NULL, ("ng_snd_item: hook for data is NULL"));
1938 if (NGI_M(item) == NULL)
1940 CHECK_DATA_MBUF(NGI_M(item));
1944 * Always queue items entering netgraph for the first time.
1946 if (item->depth == 1) {
1947 struct lwkt_msg *msg = &item->el_lmsg;
1949 lwkt_initmsg(msg, &ng_panic_reply_port, 0);
1950 /* Always send to cpu0 for now */
1951 lwkt_sendmsg(ng_cpuport(0), msg);
1953 return ((flags & NG_PROGRESS) ? EINPROGRESS : 0);
1957 * The item wasn't queued. Process it synchronously.
1959 error = ng_apply_item(item);
1966 * We have an item that was possibly queued somewhere.
1967 * It should contain all the information needed
1968 * to run it on the appropriate node/hook.
1969 * If there is apply pointer and we own the last reference, call apply().
1972 ng_apply_item(item_p item)
1976 ng_rcvdata_t *rcvdata;
1977 ng_rcvmsg_t *rcvmsg;
1980 /* Node and item are never optional. */
1981 KASSERT(item != NULL, ("ng_apply_item: item is NULL"));
1982 NGI_GET_NODE(item, node); /* zaps stored node */
1983 KASSERT(node != NULL, ("ng_apply_item: node is NULL"));
1984 NGI_GET_HOOK(item, hook); /* clears stored hook */
1987 * If the item or the node specifies single threading, force
1988 * writer semantics. Similarly, the node may say one hook always
1989 * produces writers. These are overrides.
1991 if (((item->el_flags & NGQF_RW) == NGQF_WRITER) ||
1992 (node->nd_flags & NGF_FORCE_WRITER) ||
1993 (hook && (hook->hk_flags & HK_FORCE_WRITER))) {
1994 ng_acquire_write(node);
1996 ng_acquire_read(node);
1999 #ifdef NETGRAPH_DEBUG
2000 _ngi_check(item, __FILE__, __LINE__);
2003 switch (item->el_flags & NGQF_TYPE) {
2006 * Check things are still ok as when we were queued.
2008 KASSERT(hook != NULL, ("ng_apply_item: hook for data is NULL"));
2009 if (NG_HOOK_NOT_VALID(hook) ||
2010 NG_NODE_NOT_VALID(node)) {
2016 * If no receive method, just silently drop it.
2017 * Give preference to the hook over-ride method
2019 if ((!(rcvdata = hook->hk_rcvdata))
2020 && (!(rcvdata = NG_HOOK_NODE(hook)->nd_type->rcvdata))) {
2025 error = (*rcvdata)(hook, item);
2028 if (hook && NG_HOOK_NOT_VALID(hook)) {
2030 * The hook has been zapped then we can't use it.
2031 * Immediately drop its reference.
2032 * The message may not need it.
2034 NG_HOOK_UNREF(hook);
2038 * Similarly, if the node is a zombie there is
2039 * nothing we can do with it, drop everything.
2041 if (NG_NODE_NOT_VALID(node)) {
2048 * Call the appropriate message handler for the object.
2049 * It is up to the message handler to free the message.
2050 * If it's a generic message, handle it generically,
2051 * otherwise call the type's message handler (if it exists).
2052 * XXX (race). Remember that a queued message may
2053 * reference a node or hook that has just been
2054 * invalidated. It will exist as the queue code
2055 * is holding a reference, but..
2057 if ((NGI_MSG(item)->header.typecookie == NGM_GENERIC_COOKIE) &&
2058 ((NGI_MSG(item)->header.flags & NGF_RESP) == 0)) {
2059 error = ng_generic_msg(node, item, hook);
2062 if (((!hook) || (!(rcvmsg = hook->hk_rcvmsg))) &&
2063 (!(rcvmsg = node->nd_type->rcvmsg))) {
2069 error = (*rcvmsg)(node, item, hook);
2074 * We have to implicitly trust the hook,
2075 * as some of these are used for system purposes
2076 * where the hook is invalid. In the case of
2077 * the shutdown message we allow it to hit
2078 * even if the node is invalid.
2080 if ((NG_NODE_NOT_VALID(node))
2081 && (NGI_FN(item) != &ng_rmnode)) {
2087 if ((item->el_flags & NGQF_TYPE) == NGQF_FN) {
2088 (*NGI_FN(item))(node, hook, NGI_ARG1(item),
2091 } else /* it is NGQF_FN2 */
2092 error = (*NGI_FN2(item))(node, item, hook);
2096 * We held references on some of the resources
2097 * that we took from the item. Now that we have
2098 * finished doing everything, drop those references.
2101 NG_HOOK_UNREF(hook);
2103 /* Release our node's token */
2104 ng_leave_readwrite(node);
2106 /* Free the item if we own the last reference to it. */
2107 if (refcount_release(&item->depth)) {
2108 ng_check_apply(item, error);
2111 NG_NODE_UNREF(node);
2116 /***********************************************************************
2117 * Implement the 'generic' control messages
2118 ***********************************************************************/
2120 ng_generic_msg(node_p here, item_p item, hook_p lasthook)
2123 struct ng_mesg *msg;
2124 struct ng_mesg *resp = NULL;
2126 NGI_GET_MSG(item, msg);
2127 if (msg->header.typecookie != NGM_GENERIC_COOKIE) {
2132 switch (msg->header.cmd) {
2134 ng_rmnode(here, NULL, NULL, 0);
2138 struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
2140 if (msg->header.arglen != sizeof(*mkp)) {
2145 mkp->type[sizeof(mkp->type) - 1] = '\0';
2146 mkp->ourhook[sizeof(mkp->ourhook) - 1] = '\0';
2147 mkp->peerhook[sizeof(mkp->peerhook) - 1] = '\0';
2148 error = ng_mkpeer(here, mkp->ourhook, mkp->peerhook, mkp->type);
2153 struct ngm_connect *const con =
2154 (struct ngm_connect *) msg->data;
2157 if (msg->header.arglen != sizeof(*con)) {
2162 con->path[sizeof(con->path) - 1] = '\0';
2163 con->ourhook[sizeof(con->ourhook) - 1] = '\0';
2164 con->peerhook[sizeof(con->peerhook) - 1] = '\0';
2165 /* Don't forget we get a reference.. */
2166 error = ng_path2noderef(here, con->path, &node2, NULL);
2169 error = ng_con_nodes(item, here, con->ourhook,
2170 node2, con->peerhook);
2171 NG_NODE_UNREF(node2);
2176 struct ngm_name *const nam = (struct ngm_name *) msg->data;
2178 if (msg->header.arglen != sizeof(*nam)) {
2183 nam->name[sizeof(nam->name) - 1] = '\0';
2184 error = ng_name_node(here, nam->name);
2189 struct ngm_rmhook *const rmh = (struct ngm_rmhook *) msg->data;
2192 if (msg->header.arglen != sizeof(*rmh)) {
2197 rmh->ourhook[sizeof(rmh->ourhook) - 1] = '\0';
2198 if ((hook = ng_findhook(here, rmh->ourhook)) != NULL)
2199 ng_destroy_hook(hook);
2204 struct nodeinfo *ni;
2206 NG_MKRESPONSE(resp, msg, sizeof(*ni), M_WAITOK | M_NULLOK);
2212 /* Fill in node info */
2213 ni = (struct nodeinfo *) resp->data;
2214 if (NG_NODE_HAS_NAME(here))
2215 strcpy(ni->name, NG_NODE_NAME(here));
2216 strcpy(ni->type, here->nd_type->name);
2217 ni->id = ng_node2ID(here);
2218 ni->hooks = here->nd_numhooks;
2223 const int nhooks = here->nd_numhooks;
2224 struct hooklist *hl;
2225 struct nodeinfo *ni;
2228 /* Get response struct */
2229 NG_MKRESPONSE(resp, msg, sizeof(*hl)
2230 + (nhooks * sizeof(struct linkinfo)), M_WAITOK | M_NULLOK);
2235 hl = (struct hooklist *) resp->data;
2238 /* Fill in node info */
2239 if (NG_NODE_HAS_NAME(here))
2240 strcpy(ni->name, NG_NODE_NAME(here));
2241 strcpy(ni->type, here->nd_type->name);
2242 ni->id = ng_node2ID(here);
2244 /* Cycle through the linked list of hooks */
2246 LIST_FOREACH(hook, &here->nd_hooks, hk_hooks) {
2247 struct linkinfo *const link = &hl->link[ni->hooks];
2249 if (ni->hooks >= nhooks) {
2250 log(LOG_ERR, "%s: number of %s changed\n",
2254 if (NG_HOOK_NOT_VALID(hook))
2256 strcpy(link->ourhook, NG_HOOK_NAME(hook));
2257 strcpy(link->peerhook, NG_PEER_HOOK_NAME(hook));
2258 if (NG_PEER_NODE_NAME(hook)[0] != '\0')
2259 strcpy(link->nodeinfo.name,
2260 NG_PEER_NODE_NAME(hook));
2261 strcpy(link->nodeinfo.type,
2262 NG_PEER_NODE(hook)->nd_type->name);
2263 link->nodeinfo.id = ng_node2ID(NG_PEER_NODE(hook));
2264 link->nodeinfo.hooks = NG_PEER_NODE(hook)->nd_numhooks;
2272 struct namelist *nl;
2277 /* Get response struct. */
2278 NG_MKRESPONSE(resp, msg, sizeof(*nl) +
2279 (ng_nodes * sizeof(struct nodeinfo)), M_NOWAIT | M_ZERO);
2285 nl = (struct namelist *) resp->data;
2287 /* Cycle through the lists of nodes. */
2289 for (i = 0; i <= ng_ID_hmask; i++) {
2290 LIST_FOREACH(node, &ng_ID_hash[i], nd_idnodes) {
2291 struct nodeinfo *const np =
2292 &nl->nodeinfo[nl->numnames];
2294 if (NG_NODE_NOT_VALID(node))
2296 if (NG_NODE_HAS_NAME(node))
2297 strcpy(np->name, NG_NODE_NAME(node));
2298 strcpy(np->type, node->nd_type->name);
2299 np->id = ng_node2ID(node);
2300 np->hooks = node->nd_numhooks;
2301 KASSERT(nl->numnames < ng_nodes,
2302 ("%s: no space", __func__));
2311 struct namelist *nl;
2316 /* Get response struct. */
2317 NG_MKRESPONSE(resp, msg, sizeof(*nl) +
2318 (ng_named_nodes * sizeof(struct nodeinfo)), M_NOWAIT);
2324 nl = (struct namelist *) resp->data;
2326 /* Cycle through the lists of nodes. */
2328 for (i = 0; i <= ng_name_hmask; i++) {
2329 LIST_FOREACH(node, &ng_name_hash[i], nd_nodes) {
2330 struct nodeinfo *const np =
2331 &nl->nodeinfo[nl->numnames];
2333 if (NG_NODE_NOT_VALID(node))
2335 strcpy(np->name, NG_NODE_NAME(node));
2336 strcpy(np->type, node->nd_type->name);
2337 np->id = ng_node2ID(node);
2338 np->hooks = node->nd_numhooks;
2339 KASSERT(nl->numnames < ng_named_nodes,
2340 ("%s: no space", __func__));
2350 struct typelist *tl;
2351 struct ng_type *type;
2355 /* Count number of types */
2356 LIST_FOREACH(type, &ng_typelist, types)
2359 /* Get response struct */
2360 NG_MKRESPONSE(resp, msg, sizeof(*tl)
2361 + (num * sizeof(struct typeinfo)), M_WAITOK | M_NULLOK);
2367 tl = (struct typelist *) resp->data;
2369 /* Cycle through the linked list of types */
2371 LIST_FOREACH(type, &ng_typelist, types) {
2372 struct typeinfo *const tp = &tl->typeinfo[tl->numtypes];
2374 strcpy(tp->type_name, type->name);
2375 tp->numnodes = type->refs - 1; /* don't count list */
2376 KASSERT(tl->numtypes < num, ("%s: no space", __func__));
2383 case NGM_BINARY2ASCII:
2385 int bufSize = 20 * 1024; /* XXX hard coded constant */
2386 const struct ng_parse_type *argstype;
2387 const struct ng_cmdlist *c;
2388 struct ng_mesg *binary, *ascii;
2390 /* Data area must contain a valid netgraph message */
2391 binary = (struct ng_mesg *)msg->data;
2392 if (msg->header.arglen < sizeof(struct ng_mesg) ||
2393 (msg->header.arglen - sizeof(struct ng_mesg) <
2394 binary->header.arglen)) {
2400 /* Get a response message with lots of room */
2401 NG_MKRESPONSE(resp, msg, sizeof(*ascii) + bufSize, M_WAITOK | M_NULLOK);
2406 ascii = (struct ng_mesg *)resp->data;
2408 /* Copy binary message header to response message payload */
2409 bcopy(binary, ascii, sizeof(*binary));
2411 /* Find command by matching typecookie and command number */
2412 for (c = here->nd_type->cmdlist;
2413 c != NULL && c->name != NULL; c++) {
2414 if (binary->header.typecookie == c->cookie
2415 && binary->header.cmd == c->cmd)
2418 if (c == NULL || c->name == NULL) {
2419 for (c = ng_generic_cmds; c->name != NULL; c++) {
2420 if (binary->header.typecookie == c->cookie
2421 && binary->header.cmd == c->cmd)
2424 if (c->name == NULL) {
2431 /* Convert command name to ASCII */
2432 snprintf(ascii->header.cmdstr, sizeof(ascii->header.cmdstr),
2435 /* Convert command arguments to ASCII */
2436 argstype = (binary->header.flags & NGF_RESP) ?
2437 c->respType : c->mesgType;
2438 if (argstype == NULL) {
2439 *ascii->data = '\0';
2441 if ((error = ng_unparse(argstype,
2442 (u_char *)binary->data,
2443 ascii->data, bufSize)) != 0) {
2449 /* Return the result as struct ng_mesg plus ASCII string */
2450 bufSize = strlen(ascii->data) + 1;
2451 ascii->header.arglen = bufSize;
2452 resp->header.arglen = sizeof(*ascii) + bufSize;
2456 case NGM_ASCII2BINARY:
2458 int bufSize = 2000; /* XXX hard coded constant */
2459 const struct ng_cmdlist *c;
2460 const struct ng_parse_type *argstype;
2461 struct ng_mesg *ascii, *binary;
2464 /* Data area must contain at least a struct ng_mesg + '\0' */
2465 ascii = (struct ng_mesg *)msg->data;
2466 if ((msg->header.arglen < sizeof(*ascii) + 1) ||
2467 (ascii->header.arglen < 1) ||
2468 (msg->header.arglen < sizeof(*ascii) +
2469 ascii->header.arglen)) {
2474 ascii->data[ascii->header.arglen - 1] = '\0';
2476 /* Get a response message with lots of room */
2477 NG_MKRESPONSE(resp, msg, sizeof(*binary) + bufSize, M_WAITOK | M_NULLOK);
2482 binary = (struct ng_mesg *)resp->data;
2484 /* Copy ASCII message header to response message payload */
2485 bcopy(ascii, binary, sizeof(*ascii));
2487 /* Find command by matching ASCII command string */
2488 for (c = here->nd_type->cmdlist;
2489 c != NULL && c->name != NULL; c++) {
2490 if (strcmp(ascii->header.cmdstr, c->name) == 0)
2493 if (c == NULL || c->name == NULL) {
2494 for (c = ng_generic_cmds; c->name != NULL; c++) {
2495 if (strcmp(ascii->header.cmdstr, c->name) == 0)
2498 if (c->name == NULL) {
2505 /* Convert command name to binary */
2506 binary->header.cmd = c->cmd;
2507 binary->header.typecookie = c->cookie;
2509 /* Convert command arguments to binary */
2510 argstype = (binary->header.flags & NGF_RESP) ?
2511 c->respType : c->mesgType;
2512 if (argstype == NULL) {
2515 if ((error = ng_parse(argstype, ascii->data,
2516 &off, (u_char *)binary->data, &bufSize)) != 0) {
2522 /* Return the result */
2523 binary->header.arglen = bufSize;
2524 resp->header.arglen = sizeof(*binary) + bufSize;
2528 case NGM_TEXT_CONFIG:
2529 case NGM_TEXT_STATUS:
2531 * This one is tricky as it passes the command down to the
2532 * actual node, even though it is a generic type command.
2533 * This means we must assume that the item/msg is already freed
2534 * when control passes back to us.
2536 if (here->nd_type->rcvmsg != NULL) {
2537 NGI_MSG(item) = msg; /* put it back as we found it */
2538 return((*here->nd_type->rcvmsg)(here, item, lasthook));
2540 /* Fall through if rcvmsg not supported */
2546 * Sometimes a generic message may be statically allocated
2547 * to avoid problems with allocating when in tight memeory situations.
2548 * Don't free it if it is so.
2549 * I break them appart here, because erros may cause a free if the item
2550 * in which case we'd be doing it twice.
2551 * they are kept together above, to simplify freeing.
2554 NG_RESPOND_MSG(error, here, item, resp);
2560 /************************************************************************
2561 Queue element get/free routines
2562 ************************************************************************/
2564 static struct objcache *ng_oc;
2565 static struct objcache *ng_apply_oc;
2566 static int maxalloc = 4096; /* limit the damage of a leak */
2568 TUNABLE_INT("net.graph.maxalloc", &maxalloc);
2569 SYSCTL_INT(_net_graph, OID_AUTO, maxalloc, CTLFLAG_RD, &maxalloc,
2570 0, "Maximum number of queue items to allocate");
2572 #ifdef NETGRAPH_DEBUG
2573 static TAILQ_HEAD(, ng_item) ng_itemlist = TAILQ_HEAD_INITIALIZER(ng_itemlist);
2574 static int allocated; /* number of items malloc'd */
2578 * Get a queue entry.
2579 * This is usually called when a packet first enters netgraph.
2580 * By definition, this is usually from an interrupt, or from a user.
2581 * Users are not so important, but try be quick for the times that it's
2584 static __inline item_p
2585 ng_alloc_item(int type, int flags)
2589 KASSERT(((type & ~NGQF_TYPE) == 0),
2590 ("%s: incorrect item type: %d", __func__, type));
2592 item = objcache_get(ng_oc,
2593 (flags & NG_WAITOK) ? M_WAITOK : M_NOWAIT );
2596 item->el_flags = type;
2597 #ifdef NETGRAPH_DEBUG
2599 TAILQ_INSERT_TAIL(&ng_itemlist, item, all);
2601 mtx_unlock(&ngq_mtx);
2609 * Release a queue entry
2612 ng_free_item(item_p item)
2615 * If the item still has an apply callback registered, it is
2616 * being freed too early.
2618 KASSERT(item->apply == NULL, ("freeing item with registered callback"));
2621 * The item may hold resources on it's own. We need to free
2622 * these before we can free the item. What they are depends upon
2623 * what kind of item it is. it is important that nodes zero
2624 * out pointers to resources that they remove from the item
2625 * or we release them again here.
2627 switch (item->el_flags & NGQF_TYPE) {
2629 /* If we have an mbuf still attached.. */
2630 NG_FREE_M(_NGI_M(item));
2633 _NGI_RETADDR(item) = 0;
2634 NG_FREE_MSG(_NGI_MSG(item));
2638 /* nothing to free really, */
2639 _NGI_FN(item) = NULL;
2640 _NGI_ARG1(item) = NULL;
2641 _NGI_ARG2(item) = 0;
2644 /* If we still have a node or hook referenced... */
2645 _NGI_CLR_NODE(item);
2646 _NGI_CLR_HOOK(item);
2648 #ifdef NETGRAPH_DEBUG
2650 TAILQ_REMOVE(&ng_itemlist, item, all);
2652 mtx_unlock(&ngq_mtx);
2654 /* Object must be initialized before returning to objcache */
2655 bzero(item, sizeof(struct ng_item));
2656 objcache_put(ng_oc, item);
2660 * Change type of the queue entry.
2662 static __inline item_p
2663 ng_realloc_item(item_p item, int type, int flags)
2666 KASSERT((item != NULL), ("%s: can't reallocate NULL", __func__));
2667 KASSERT(((type & ~NGQF_TYPE) == 0),
2668 ("%s: incorrect item type: %d", __func__, type));
2670 item->el_flags = (item->el_flags & ~NGQF_TYPE) | type;
2676 ng_alloc_apply(void)
2678 return (objcache_get(ng_apply_oc, M_WAITOK));
2682 ng_free_apply(apply_p apply)
2684 objcache_put(ng_apply_oc, apply);
2688 ng_check_apply(item_p item, int error)
2690 if (item->apply == NULL)
2693 KKASSERT(item->apply->apply != NULL);
2694 (*item->apply->apply)(item->apply->context, error);
2695 ng_free_apply(item->apply);
2699 /************************************************************************
2701 ************************************************************************/
2704 * Handle the loading/unloading of a netgraph node type module
2707 ng_mod_event(module_t mod, int event, void *data)
2709 struct ng_type *const type = data;
2715 /* Register new netgraph node type */
2716 if ((error = ng_newtype(type)) != 0) {
2720 /* Call type specific code */
2721 if (type->mod_event != NULL)
2722 if ((error = (*type->mod_event)(mod, event, data))) {
2724 type->refs--; /* undo it */
2725 LIST_REMOVE(type, types);
2731 if (type->refs > 1) { /* make sure no nodes exist! */
2734 if (type->refs == 0) {
2735 /* failed load, nothing to undo */
2738 if (type->mod_event != NULL) { /* check with type */
2739 error = (*type->mod_event)(mod, event, data);
2740 if (error != 0) { /* type refuses.. */
2745 LIST_REMOVE(type, types);
2751 if (type->mod_event != NULL)
2752 error = (*type->mod_event)(mod, event, data);
2754 error = EOPNOTSUPP; /* XXX ? */
2761 * Handle loading and unloading for this code.
2764 ngb_mod_event(module_t mod, int event, void *data)
2770 /* Initialize everything. */
2771 lwkt_token_init(&ng_typelist_token, "ng typelist");
2772 lwkt_token_init(&ng_idhash_token, "ng idhash");
2773 lwkt_token_init(&ng_namehash_token, "ng namehash");
2774 lwkt_token_init(&ng_topo_token, "ng topology");
2775 #ifdef NETGRAPH_DEBUG
2776 mtx_init(&ng_nodelist_mtx);
2779 ng_oc = objcache_create_mbacked(M_NETGRAPH,
2780 sizeof(struct ng_item), maxalloc, 0, bzero_ctor,
2782 ng_apply_oc = objcache_create_mbacked(M_NETGRAPH_APPLY,
2783 sizeof(struct ng_apply_info), 0, 0, bzero_ctor,
2786 /* We start with small hashes, but they can grow. */
2787 ng_ID_hash = hashinit(16, M_NETGRAPH_NODE, &ng_ID_hmask);
2788 ng_name_hash = hashinit(16, M_NETGRAPH_NODE, &ng_name_hmask);
2790 lwkt_initport_panic(&ng_panic_reply_port);
2791 for (i = 0; i < ncpus; ++i) {
2794 lwkt_create(ngthread, NULL, &td,
2795 NULL, 0, i, "netgraph %d", i);
2796 ng_msgport[i] = &td->td_msgport;
2801 hashdestroy(V_ng_name_hash, M_NETGRAPH_NODE, V_ng_name_hmask);
2802 hashdestroy(V_ng_ID_hash, M_NETGRAPH_NODE, V_ng_ID_hmask);
2804 /* Destroy the lwkt threads too */
2806 objcache_destroy(ng_apply_oc);
2807 objcache_destroy(ng_oc);
2809 /* You can't unload it because an interface may be using it. */
2819 static moduledata_t netgraph_mod = {
2824 DECLARE_MODULE(netgraph, netgraph_mod, SI_SUB_NETGRAPH, SI_ORDER_MIDDLE);
2825 SYSCTL_NODE(_net, OID_AUTO, graph, CTLFLAG_RW, 0, "netgraph Family");
2826 SYSCTL_INT(_net_graph, OID_AUTO, abi_version, CTLFLAG_RD, 0, NG_ABI_VERSION,"");
2827 SYSCTL_INT(_net_graph, OID_AUTO, msg_version, CTLFLAG_RD, 0, NG_VERSION, "");
2829 #ifdef NETGRAPH_DEBUG
2831 dumphook (hook_p hook, char *file, int line)
2833 printf("hook: name %s, %d refs, Last touched:\n",
2834 _NG_HOOK_NAME(hook), hook->hk_refs);
2835 printf(" Last active @ %s, line %d\n",
2836 hook->lastfile, hook->lastline);
2838 printf(" problem discovered at file %s, line %d\n", file, line);
2843 dumpnode(node_p node, char *file, int line)
2845 printf("node: ID [%x]: type '%s', %d hooks, flags 0x%x, %d refs, %s:\n",
2846 _NG_NODE_ID(node), node->nd_type->name,
2847 node->nd_numhooks, node->nd_flags,
2848 node->nd_refs, node->nd_name);
2849 printf(" Last active @ %s, line %d\n",
2850 node->lastfile, node->lastline);
2852 printf(" problem discovered at file %s, line %d\n", file, line);
2857 dumpitem(item_p item, char *file, int line)
2859 printf(" ACTIVE item, last used at %s, line %d",
2860 item->lastfile, item->lastline);
2861 switch(item->el_flags & NGQF_TYPE) {
2863 printf(" - [data]\n");
2866 printf(" - retaddr[%d]:\n", _NGI_RETADDR(item));
2869 printf(" - fn@%p (%p, %p, %p, %d (%x))\n",
2873 item->body.fn.fn_arg1,
2874 item->body.fn.fn_arg2,
2875 item->body.fn.fn_arg2);
2878 printf(" - fn2@%p (%p, %p, %p, %d (%x))\n",
2882 item->body.fn.fn_arg1,
2883 item->body.fn.fn_arg2,
2884 item->body.fn.fn_arg2);
2888 printf(" problem discovered at file %s, line %d\n", file, line);
2889 if (_NGI_NODE(item)) {
2890 printf("node %p ([%x])\n",
2891 _NGI_NODE(item), ng_node2ID(_NGI_NODE(item)));
2901 TAILQ_FOREACH(item, &ng_itemlist, all) {
2902 printf("[%d] ", i++);
2903 dumpitem(item, NULL, 0);
2912 mtx_lock(&ng_nodelist_mtx);
2913 SLIST_FOREACH(node, &ng_allnodes, nd_all) {
2914 printf("[%d] ", i++);
2915 dumpnode(node, NULL, 0);
2917 mtx_unlock(&ng_nodelist_mtx);
2925 mtx_lock(&ng_nodelist_mtx);
2926 SLIST_FOREACH(hook, &ng_allhooks, hk_all) {
2927 printf("[%d] ", i++);
2928 dumphook(hook, NULL, 0);
2930 mtx_unlock(&ng_nodelist_mtx);
2934 sysctl_debug_ng_dump_items(SYSCTL_HANDLER_ARGS)
2940 error = sysctl_handle_int(oidp, &val, 0, req);
2941 if (error != 0 || req->newptr == NULL)
2951 SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RW,
2952 0, sizeof(int), sysctl_debug_ng_dump_items, "I", "Number of allocated items");
2953 #endif /* NETGRAPH_DEBUG */
2956 /***********************************************************************
2957 * Externally useable functions to set up a queue item ready for sending
2958 ***********************************************************************/
2960 #ifdef NETGRAPH_DEBUG
2961 #define ITEM_DEBUG_CHECKS \
2963 if (NGI_NODE(item) ) { \
2964 printf("item already has node"); \
2965 kdb_enter(KDB_WHY_NETGRAPH, "has node"); \
2966 NGI_CLR_NODE(item); \
2968 if (NGI_HOOK(item) ) { \
2969 printf("item already has hook"); \
2970 kdb_enter(KDB_WHY_NETGRAPH, "has hook"); \
2971 NGI_CLR_HOOK(item); \
2975 #define ITEM_DEBUG_CHECKS
2979 * Put mbuf into the item.
2980 * Hook and node references will be removed when the item is dequeued.
2982 * (XXX) Unsafe because no reference held by peer on remote node.
2983 * remote node might go away in this timescale.
2984 * We know the hooks can't go away because that would require getting
2985 * a writer item on both nodes and we must have at least a reader
2986 * here to be able to do this.
2987 * Note that the hook loaded is the REMOTE hook.
2989 * This is possibly in the critical path for new data.
2992 ng_package_data(struct mbuf *m, int flags)
2996 if ((item = ng_alloc_item(NGQF_DATA, flags)) == NULL) {
3001 item->el_flags |= NGQF_READER;
3007 * Allocate a queue item and put items into it..
3008 * Evaluate the address as this will be needed to queue it and
3009 * to work out what some of the fields should be.
3010 * Hook and node references will be removed when the item is dequeued.
3014 ng_package_msg(struct ng_mesg *msg, int flags)
3018 if ((item = ng_alloc_item(NGQF_MESG, flags)) == NULL) {
3023 /* Messages items count as writers unless explicitly exempted. */
3024 if (msg->header.cmd & NGM_READONLY)
3025 item->el_flags |= NGQF_READER;
3027 item->el_flags |= NGQF_WRITER;
3029 * Set the current lasthook into the queue item
3031 NGI_MSG(item) = msg;
3032 NGI_RETADDR(item) = 0;
3038 #define SET_RETADDR(item, here, retaddr) \
3039 do { /* Data or fn items don't have retaddrs */ \
3040 if ((item->el_flags & NGQF_TYPE) == NGQF_MESG) { \
3042 NGI_RETADDR(item) = retaddr; \
3045 * The old return address should be ok. \
3046 * If there isn't one, use the address \
3049 if (NGI_RETADDR(item) == 0) { \
3051 = ng_node2ID(here); \
3058 ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
3064 * Quick sanity check..
3065 * Since a hook holds a reference on it's node, once we know
3066 * that the peer is still connected (even if invalid,) we know
3067 * that the peer node is present, though maybe invalid.
3069 if ((hook == NULL) ||
3070 NG_HOOK_NOT_VALID(hook) ||
3071 NG_HOOK_NOT_VALID(peer = NG_HOOK_PEER(hook)) ||
3072 NG_NODE_NOT_VALID(peernode = NG_PEER_NODE(hook))) {
3079 * Transfer our interest to the other (peer) end.
3082 NG_NODE_REF(peernode);
3083 NGI_SET_HOOK(item, peer);
3084 NGI_SET_NODE(item, peernode);
3085 SET_RETADDR(item, here, retaddr);
3090 ng_address_path(node_p here, item_p item, char *address, ng_ID_t retaddr)
3098 * Note that ng_path2noderef increments the reference count
3099 * on the node for us if it finds one. So we don't have to.
3101 error = ng_path2noderef(here, address, &dest, &hook);
3106 NGI_SET_NODE(item, dest);
3108 NG_HOOK_REF(hook); /* don't let it go while on the queue */
3109 NGI_SET_HOOK(item, hook);
3111 SET_RETADDR(item, here, retaddr);
3116 ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr)
3122 * Find the target node.
3124 dest = ng_ID2noderef(ID); /* GETS REFERENCE! */
3130 /* Fill out the contents */
3131 NGI_SET_NODE(item, dest);
3133 SET_RETADDR(item, here, retaddr);
3138 * special case to send a message to self (e.g. destroy node)
3139 * Possibly indicate an arrival hook too.
3140 * Useful for removing that hook :-)
3143 ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
3148 * Find the target node.
3149 * If there is a HOOK argument, then use that in preference
3152 if ((item = ng_alloc_item(NGQF_MESG, NG_NOFLAGS)) == NULL) {
3157 /* Fill out the contents */
3158 item->el_flags |= NGQF_WRITER;
3160 NGI_SET_NODE(item, here);
3163 NGI_SET_HOOK(item, hook);
3165 NGI_MSG(item) = msg;
3166 NGI_RETADDR(item) = ng_node2ID(here);
3171 * Send ng_item_fn function call to the specified node.
3175 ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, void * arg1, int arg2)
3177 return ng_send_fn1(node, hook, fn, arg1, arg2, NG_NOFLAGS);
3181 ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void * arg1, int arg2,
3186 if ((item = ng_alloc_item(NGQF_FN, flags)) == NULL) {
3189 item->el_flags |= NGQF_WRITER;
3190 NG_NODE_REF(node); /* and one for the item */
3191 NGI_SET_NODE(item, node);
3194 NGI_SET_HOOK(item, hook);
3197 NGI_ARG1(item) = arg1;
3198 NGI_ARG2(item) = arg2;
3199 return(ng_snd_item(item, flags));
3203 * Send ng_item_fn2 function call to the specified node.
3205 * If NG_REUSE_ITEM flag is set, no new item will be allocated,
3206 * pitem will be used instead.
3209 ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn, void *arg1,
3210 int arg2, int flags)
3214 KASSERT((pitem != NULL || (flags & NG_REUSE_ITEM) == 0),
3215 ("%s: NG_REUSE_ITEM but no pitem", __func__));
3218 * Allocate a new item if no supplied or
3219 * if we can't use supplied one.
3221 if (pitem == NULL || (flags & NG_REUSE_ITEM) == 0) {
3222 if ((item = ng_alloc_item(NGQF_FN2, flags)) == NULL)
3225 if ((item = ng_realloc_item(pitem, NGQF_FN2, flags)) == NULL)
3229 item->el_flags = (item->el_flags & ~NGQF_RW) | NGQF_WRITER;
3230 NG_NODE_REF(node); /* and one for the item */
3231 NGI_SET_NODE(item, node);
3234 NGI_SET_HOOK(item, hook);
3237 NGI_ARG1(item) = arg1;
3238 NGI_ARG2(item) = arg2;
3239 return(ng_snd_item(item, flags));
3243 * Official timeout routines for Netgraph nodes.
3246 ng_callout_trampoline(void *arg)
3250 ng_snd_item(item, 0);
3255 ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
3256 ng_item_fn *fn, void * arg1, int arg2)
3260 if ((item = ng_alloc_item(NGQF_FN, NG_NOFLAGS)) == NULL)
3263 item->el_flags |= NGQF_WRITER;
3264 NG_NODE_REF(node); /* and one for the item */
3265 NGI_SET_NODE(item, node);
3268 NGI_SET_HOOK(item, hook);
3271 NGI_ARG1(item) = arg1;
3272 NGI_ARG2(item) = arg2;
3274 callout_reset(c, ticks, &ng_callout_trampoline, item);
3278 /* A special modified version of untimeout() */
3280 ng_uncallout(struct callout *c, node_p node)
3285 KASSERT(c != NULL, ("ng_uncallout: NULL callout"));
3286 KASSERT(node != NULL, ("ng_uncallout: NULL node"));
3288 rval = callout_stop(c);
3290 /* Do an extra check */
3291 if ((rval > 0) && (c->c_func == &ng_callout_trampoline) &&
3292 (NGI_NODE(item) == node)) {
3294 * We successfully removed it from the queue before it ran
3295 * So now we need to unreference everything that was
3296 * given extra references. (NG_FREE_ITEM does this).
3306 * Set the address, if none given, give the node here.
3309 ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr)
3312 NGI_RETADDR(item) = retaddr;
3315 * The old return address should be ok.
3316 * If there isn't one, use the address here.
3318 NGI_RETADDR(item) = ng_node2ID(here);
3323 bzero_ctor(void *obj, void *private, int ocflags)
3325 struct ng_item *i = obj;
3327 bzero(i, sizeof(struct ng_item));
3333 /* just test all the macros */
3335 ng_macro_test(item_p item);
3337 ng_macro_test(item_p item)
3342 struct ng_mesg *msg;
3347 NGI_GET_MSG(item, msg);
3348 retaddr = NGI_RETADDR(item);
3349 NG_SEND_DATA(error, hook, m, NULL);
3350 NG_SEND_DATA_ONLY(error, hook, m);
3351 NG_FWD_NEW_DATA(error, item, hook, m);
3352 NG_FWD_ITEM_HOOK(error, item, hook);
3353 NG_SEND_MSG_HOOK(error, node, msg, hook, retaddr);
3354 NG_SEND_MSG_ID(error, node, msg, retaddr, retaddr);
3355 NG_SEND_MSG_PATH(error, node, msg, ".:", retaddr);
3356 NG_FWD_MSG_HOOK(error, node, item, hook, retaddr);
3358 #endif /* TESTING */