50#include <sys/kernel.h>
51#include <sys/kthread.h>
53#include <sys/limits.h>
55#include <sys/malloc.h>
60#include <sys/refcount.h>
61#include <sys/rwlock.h>
63#include <sys/sysctl.h>
64#include <sys/syslog.h>
65#include <sys/unistd.h>
66#include <machine/cpu.h>
69#include <net/netisr.h>
80#define TOPOLOGY_RLOCK() rw_rlock(&ng_topo_lock)
81#define TOPOLOGY_RUNLOCK() rw_runlock(&ng_topo_lock)
82#define TOPOLOGY_WLOCK() rw_wlock(&ng_topo_lock)
83#define TOPOLOGY_WUNLOCK() rw_wunlock(&ng_topo_lock)
84#define TOPOLOGY_NOTOWNED() rw_assert(&ng_topo_lock, RA_UNLOCKED)
87static struct mtx ng_nodelist_mtx;
88static struct mtx ngq_mtx;
95static void ng_dumpitems(
void);
96static void ng_dumpnodes(
void);
97static void ng_dumphooks(
void);
171static struct mtx ng_worklist_mtx;
175static struct rwlock ng_typelist_lock;
176#define TYPELIST_RLOCK() rw_rlock(&ng_typelist_lock)
177#define TYPELIST_RUNLOCK() rw_runlock(&ng_typelist_lock)
178#define TYPELIST_WLOCK() rw_wlock(&ng_typelist_lock)
179#define TYPELIST_WUNLOCK() rw_wunlock(&ng_typelist_lock)
189#define V_ng_ID_hash VNET(ng_ID_hash)
190#define V_ng_ID_hmask VNET(ng_ID_hmask)
191#define V_ng_nodes VNET(ng_nodes)
192#define V_ng_name_hash VNET(ng_name_hash)
193#define V_ng_name_hmask VNET(ng_name_hmask)
194#define V_ng_named_nodes VNET(ng_named_nodes)
196static struct rwlock ng_idhash_lock;
197#define IDHASH_RLOCK() rw_rlock(&ng_idhash_lock)
198#define IDHASH_RUNLOCK() rw_runlock(&ng_idhash_lock)
199#define IDHASH_WLOCK() rw_wlock(&ng_idhash_lock)
200#define IDHASH_WUNLOCK() rw_wunlock(&ng_idhash_lock)
203#define NG_IDHASH_FN(ID) ((ID) % (V_ng_ID_hmask + 1))
204#define NG_IDHASH_FIND(ID, node) \
206 rw_assert(&ng_idhash_lock, RA_LOCKED); \
207 LIST_FOREACH(node, &V_ng_ID_hash[NG_IDHASH_FN(ID)], \
209 if (NG_NODE_IS_VALID(node) \
210 && (NG_NODE_ID(node) == ID)) { \
216static struct rwlock ng_namehash_lock;
217#define NAMEHASH_RLOCK() rw_rlock(&ng_namehash_lock)
218#define NAMEHASH_RUNLOCK() rw_runlock(&ng_namehash_lock)
219#define NAMEHASH_WLOCK() rw_wlock(&ng_namehash_lock)
220#define NAMEHASH_WUNLOCK() rw_wunlock(&ng_namehash_lock)
233 node_p node2,
const char *name2);
246int ng_path_parse(
char *addr,
char **node,
char **path,
char **hook);
251MALLOC_DEFINE(M_NETGRAPH,
"netgraph",
"netgraph structures and ctrl messages");
252MALLOC_DEFINE(M_NETGRAPH_MSG,
"netgraph_msg",
"netgraph name storage");
254 "netgraph hook structures");
256 "netgraph node structures");
258 "netgraph item structures");
262#define _NG_ALLOC_HOOK(hook) \
263 hook = malloc(sizeof(*hook), M_NETGRAPH_HOOK, M_NOWAIT | M_ZERO)
264#define _NG_ALLOC_NODE(node) \
265 node = malloc(sizeof(*node), M_NETGRAPH_NODE, M_NOWAIT | M_ZERO)
267#define NG_QUEUE_LOCK_INIT(n) \
268 mtx_init(&(n)->q_mtx, "ng_node", NULL, MTX_DEF)
269#define NG_QUEUE_LOCK(n) \
270 mtx_lock(&(n)->q_mtx)
271#define NG_QUEUE_UNLOCK(n) \
272 mtx_unlock(&(n)->q_mtx)
273#define NG_WORKLIST_LOCK_INIT() \
274 mtx_init(&ng_worklist_mtx, "ng_worklist", NULL, MTX_DEF)
275#define NG_WORKLIST_LOCK() \
276 mtx_lock(&ng_worklist_mtx)
277#define NG_WORKLIST_UNLOCK() \
278 mtx_unlock(&ng_worklist_mtx)
279#define NG_WORKLIST_SLEEP() \
280 mtx_sleep(&ng_worklist, &ng_worklist_mtx, PI_NET, "sleep", 0)
281#define NG_WORKLIST_WAKEUP() \
282 wakeup_one(&ng_worklist)
298 mtx_lock(&ng_nodelist_mtx);
299 hook = LIST_FIRST(&ng_freehooks);
301 LIST_REMOVE(hook, hk_hooks);
302 bcopy(&hook->hk_all, &temp,
sizeof(temp));
303 bzero(hook,
sizeof(
struct ng_hook));
304 bcopy(&temp, &hook->hk_all,
sizeof(temp));
305 mtx_unlock(&ng_nodelist_mtx);
306 hook->hk_magic = HK_MAGIC;
308 mtx_unlock(&ng_nodelist_mtx);
311 hook->hk_magic = HK_MAGIC;
312 mtx_lock(&ng_nodelist_mtx);
313 SLIST_INSERT_HEAD(&ng_allhooks, hook, hk_all);
314 mtx_unlock(&ng_nodelist_mtx);
325 mtx_lock(&ng_nodelist_mtx);
326 node = LIST_FIRST(&ng_freenodes);
328 LIST_REMOVE(node, nd_nodes);
329 bcopy(&node->nd_all, &temp,
sizeof(temp));
330 bzero(node,
sizeof(
struct ng_node));
331 bcopy(&temp, &node->nd_all,
sizeof(temp));
332 mtx_unlock(&ng_nodelist_mtx);
333 node->nd_magic = ND_MAGIC;
335 mtx_unlock(&ng_nodelist_mtx);
338 node->nd_magic = ND_MAGIC;
339 mtx_lock(&ng_nodelist_mtx);
340 SLIST_INSERT_HEAD(&ng_allnodes, node, nd_all);
341 mtx_unlock(&ng_nodelist_mtx);
347#define NG_ALLOC_HOOK(hook) do { (hook) = ng_alloc_hook(); } while (0)
348#define NG_ALLOC_NODE(node) do { (node) = ng_alloc_node(); } while (0)
350#define NG_FREE_HOOK(hook) \
352 mtx_lock(&ng_nodelist_mtx); \
353 LIST_INSERT_HEAD(&ng_freehooks, hook, hk_hooks); \
354 hook->hk_magic = 0; \
355 mtx_unlock(&ng_nodelist_mtx); \
358#define NG_FREE_NODE(node) \
360 mtx_lock(&ng_nodelist_mtx); \
361 LIST_INSERT_HEAD(&ng_freenodes, node, nd_nodes); \
362 node->nd_magic = 0; \
363 mtx_unlock(&ng_nodelist_mtx); \
368#define NG_ALLOC_HOOK(hook) _NG_ALLOC_HOOK(hook)
369#define NG_ALLOC_NODE(node) _NG_ALLOC_NODE(node)
371#define NG_FREE_HOOK(hook) do { free((hook), M_NETGRAPH_HOOK); } while (0)
372#define NG_FREE_NODE(node) do { free((node), M_NETGRAPH_NODE); } while (0)
382#define V_nextID VNET(nextID)
385#define CHECK_DATA_MBUF(m) do { \
390 for (total = 0, n = (m); n != NULL; n = n->m_next) { \
392 if (n->m_nextpkt != NULL) \
393 panic("%s: m_nextpkt", __func__); \
396 if ((m)->m_pkthdr.len != total) { \
397 panic("%s: %d != %d", \
398 __func__, (m)->m_pkthdr.len, total); \
402#define CHECK_DATA_MBUF(m)
405#define ERROUT(x) do { error = (x); goto done; } while (0)
412#define DEFINE_PARSE_STRUCT_TYPE(lo, up, args) \
413static const struct ng_parse_struct_field \
414 ng_ ## lo ## _type_fields[] = NG_GENERIC_ ## up ## _INFO args; \
415static const struct ng_parse_type ng_generic_ ## lo ## _type = { \
416 &ng_parse_struct_type, \
417 &ng_ ## lo ## _type_fields \
433 const u_char *start,
const u_char *buf)
435 return *((
const u_int32_t *)(buf - 4));
441 const u_char *start,
const u_char *buf)
450 &ng_generic_nodeinfo_type,
451 &ng_generic_list_getLength
460 &ng_generic_typeinfo_type,
461 &ng_generic_list_getLength
470 &ng_generic_linkinfo_type,
497 &ng_generic_mkpeer_type,
504 &ng_generic_connect_type,
511 &ng_generic_name_type,
518 &ng_generic_rmhook_type,
526 &ng_generic_nodeinfo_type
533 &ng_generic_hooklist_type
540 &ng_generic_listnodes_type
547 &ng_generic_listnodes_type
554 &ng_generic_typelist_type
601 if (
typename == NULL) {
616 if (
type->constructor != NULL) {
618 if ((error = ((*
type->constructor)(*nodepp))) != 0) {
670 LIST_INIT(&node->nd_hooks);
680 if ((node->
nd_ID != 0) && (node2 == NULL)) {
724 printf (
"shutdown called on deadnode\n");
744 while ((hook = LIST_FIRST(&node->nd_hooks)) != NULL)
801 if (refcount_release(&node->
nd_refs)) {
807 LIST_REMOVE(node, nd_nodes);
813 LIST_REMOVE(node, nd_idnodes);
864 if (
name[i] ==
'\0' ||
name[i] ==
'.' ||
name[i] ==
':')
867 if (i == 0 ||
name[i] !=
'\0') {
890 LIST_REMOVE(node, nd_nodes);
920 if (strcmp(
name,
".") == 0) {
951 const int len = strlen(
name);
956 if ((len < 3) || (
name[0] !=
'[') || (
name[len - 1] !=
']') ||
957 (!isxdigit(
name[1])))
961 val = strtoul(
name + 1, &eptr, 16);
962 if ((eptr -
name != len - 1) || (val == ULONG_MAX) || (val == 0))
983 struct nodehash *
new;
989 new = hashinit_flags((
V_ng_name_hmask + 1) * 2, M_NETGRAPH_NODE, &hmask,
997 LIST_REMOVE(node, nd_nodes);
999 hash = hash32_str(
NG_NODE_NAME(node), HASHINIT) & hmask;
1000 LIST_INSERT_HEAD(&
new[hash], node, nd_nodes);
1014 struct nodehash *
new;
1020 new = hashinit_flags((
V_ng_ID_hmask + 1) * 2, M_NETGRAPH_NODE, &hmask,
1026 LIST_FOREACH_SAFE(node, &
V_ng_ID_hash[i], nd_idnodes, node2) {
1028 LIST_REMOVE(node, nd_idnodes);
1030 hash = (node->
nd_ID % (hmask + 1));
1031 LIST_INSERT_HEAD(&
new[hash], node, nd_idnodes);
1056 if (refcount_release(&hook->
hk_refs)) {
1112 LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
1135 LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
1168 printf(
"ng_destroy_hook called on deadhook\n");
1215 LIST_REMOVE(hook, hk_hooks);
1274 const size_t namelen = strlen(tp->
name);
1281 printf(
"Netgraph: Node type rejected. ABI mismatch. "
1282 "Suggest recompile\n");
1295 LIST_INSERT_HEAD(&ng_typelist, tp, types);
1309 if (tp->
refs != 1) {
1316 LIST_REMOVE(tp, types);
1330 LIST_FOREACH(
type, &ng_typelist, types) {
1331 if (strcmp(
type->name,
typename) == 0)
1372 printf(
"failed in ng_con_part3()\n");
1406 printf(
"failed in ng_con_part2()\n");
1419 printf(
"failed in ng_con_part2()\n");
1430 LIST_INSERT_HEAD(&node->nd_hooks, hook, hk_hooks);
1446 printf(
"failed in ng_con_part2(A)\n");
1458 printf(
"failed in ng_con_part2(B)\n");
1466 printf(
"failed in ng_con_part2(C)\n");
1483 node_p node2,
const char *name2)
1496 if (hook2 == NULL) {
1518 printf(
"failed in ng_con_nodes(): %d\n", error);
1560 if ((error =
ng_add_hook(node2, name2, &hook2))) {
1661 char *node, *path, *hook;
1667 for (path = addr; *path && *path !=
':'; path++);
1677 if (strcmp(node,
".") != 0) {
1678 for (k = 0; node[k]; k++)
1688 for (k = 0; path[k]; k++)
1693 for (k = 0; path[k]; k++)
1694 if (path[k] ==
'.' && path[k + 1] ==
'.')
1700 if (*path && path[strlen(path) - 1] ==
'.')
1701 path[strlen(path) - 1] = 0;
1705 for (hook = path, k = 0; path[k]; k++)
1706 if (path[k] ==
'.') {
1732 char *nodename, *path;
1736 if (destp == NULL) {
1743 strncpy(fullpath,
address,
sizeof(fullpath) - 1);
1744 fullpath[
sizeof(fullpath) - 1] =
'\0';
1773 if (lasthook != NULL)
1796 for (
segment = path; *path !=
'\0'; path++) {
1835 if (*path ==
'\0') {
1836 if (lasthook != NULL) {
1904#define WRITER_ACTIVE 0x00000001
1905#define OP_PENDING 0x00000002
1906#define READER_INCREMENT 0x00000004
1907#define READER_MASK 0xfffffffc
1908#define SAFETY_BARRIER 0x00100000
1912#define NGQ_RMASK (WRITER_ACTIVE|OP_PENDING)
1915#define NGQ_WMASK (NGQ_RMASK|READER_MASK)
1918#define QUEUE_ACTIVE(QP) ((QP)->q_flags & OP_PENDING)
1921#define HEAD_IS_READER(QP) NGI_QUEUED_READER(STAILQ_FIRST(&(QP)->queue))
1922#define HEAD_IS_WRITER(QP) NGI_QUEUED_WRITER(STAILQ_FIRST(&(QP)->queue))
1925#define QUEUED_READER_CAN_PROCEED(QP) \
1926 (((QP)->q_flags & (NGQ_RMASK & ~OP_PENDING)) == 0)
1927#define QUEUED_WRITER_CAN_PROCEED(QP) \
1928 (((QP)->q_flags & (NGQ_WMASK & ~OP_PENDING)) == 0)
1931#define NEXT_QUEUED_ITEM_CAN_PROCEED(QP) \
1932 ((HEAD_IS_READER(QP)) ? QUEUED_READER_CAN_PROCEED(QP) : \
1933 QUEUED_WRITER_CAN_PROCEED(QP))
1938#define NGQ2_WORKQ 0x00000001
1954 mtx_assert(&ngq->
q_mtx, MA_OWNED);
1958 CTR4(KTR_NET,
"%20s: node [%x] (%p) queue empty; "
1959 "queue flags 0x%lx", __func__,
1974 CTR4(KTR_NET,
"%20s: node [%x] (%p) queued "
1975 "reader can't proceed; queue flags 0x%lx",
1976 __func__, node->
nd_ID, node, t);
1979 if (atomic_cmpset_acq_int(&ngq->
q_flags, t,
1992 CTR4(KTR_NET,
"%20s: node [%x] (%p) queued writer can't "
1993 "proceed; queue flags 0x%lx", __func__, node->
nd_ID, node,
2002 item = STAILQ_FIRST(&ngq->queue);
2003 STAILQ_REMOVE_HEAD(&ngq->queue, el_next);
2004 if (STAILQ_EMPTY(&ngq->queue))
2006 CTR6(KTR_NET,
"%20s: node [%x] (%p) returning item %p as %s; queue "
2007 "flags 0x%lx", __func__, node->
nd_ID, node, item, *rw ?
"WRITER" :
2029 STAILQ_INSERT_TAIL(&ngq->queue, item, el_next);
2031 CTR5(KTR_NET,
"%20s: node [%x] (%p) queued item %p as %s", __func__,
2032 node->
nd_ID, node, item, rw ?
"WRITER" :
"READER" );
2048 (
"%s: working on deadnode", __func__));
2058 CTR4(KTR_NET,
"%20s: node [%x] (%p) acquired item %p",
2059 __func__, node->
nd_ID, node, item);
2076 (
"%s: working on deadnode", __func__));
2082 CTR4(KTR_NET,
"%20s: node [%x] (%p) acquired item %p",
2083 __func__, node->
nd_ID, node, item);
2099 (
"%s: working on deadnode", __func__));
2139 if (STAILQ_EMPTY(&ngq->queue)) {
2143 CTR3(KTR_NET,
"%20s: node [%x] (%p) set OP_PENDING", __func__,
2146 STAILQ_INSERT_HEAD(&ngq->queue, item, el_next);
2147 CTR4(KTR_NET,
"%20s: node [%x] (%p) requeued item %p as WRITER",
2148 __func__, node->
nd_ID, node, item );
2182 while ((item = STAILQ_FIRST(&ngq->queue)) != NULL) {
2183 STAILQ_REMOVE_HEAD(&ngq->queue, el_next);
2184 if (STAILQ_EMPTY(&ngq->queue))
2189 if (item->
apply != NULL) {
2190 if (item->
depth == 1)
2192 if (refcount_release(&item->
apply->
refs)) {
2236 KASSERT(item != NULL, (
"ng_snd_item: item is NULL"));
2238#ifdef NETGRAPH_DEBUG
2239 _ngi_check(item, __FILE__, __LINE__);
2248 KASSERT(node != NULL, (
"ng_snd_item: node is NULL"));
2253 KASSERT(hook != NULL, (
"ng_snd_item: hook for data is NULL"));
2254 if (
NGI_M(item) == NULL)
2280 curthread->td_ng_outbound) {
2293 GET_STACK_USAGE(st, su);
2295 if ((sl * 4 < st) || ((sl * 2 < st) &&
2344 if (item->
apply != NULL) {
2345 if (item->
depth == 0 && error != 0)
2347 if (refcount_release(&item->
apply->
refs)) {
2370 int error = 0, depth;
2373 KASSERT(node != NULL, (
"ng_apply_item: node is NULL"));
2374 KASSERT(item != NULL, (
"ng_apply_item: item is NULL"));
2377#ifdef NETGRAPH_DEBUG
2378 _ngi_check(item, __FILE__, __LINE__);
2382 depth = item->
depth;
2389 KASSERT(hook != NULL, (
"ng_apply_item: hook for data is NULL"));
2406 error = (*rcvdata)(hook, item);
2443 if (((!hook) || (!(rcvmsg = hook->hk_rcvmsg))) &&
2450 error = (*rcvmsg)(node, item, hook);
2498 if (
apply != NULL) {
2499 if (depth == 1 &&
error != 0)
2501 if (refcount_release(&
apply->refs))
2537 mkp->
type[
sizeof(mkp->
type) - 1] =
'\0';
2554 con->
path[
sizeof(con->
path) - 1] =
'\0';
2575 nam->
name[
sizeof(nam->
name) - 1] =
'\0';
2622 (nhooks *
sizeof(
struct linkinfo)), M_NOWAIT);
2638 LIST_FOREACH(hook, &here->nd_hooks, hk_hooks) {
2641 if (ni->
hooks >= nhooks) {
2642 log(LOG_ERR,
"%s: number of %s changed\n",
2694 (
"%s: no space", __func__));
2732 (
"%s: no space", __func__));
2748 LIST_FOREACH(
type, &ng_typelist, types)
2753 (num *
sizeof(
struct typeinfo)), M_NOWAIT);
2763 LIST_FOREACH(
type, &ng_typelist, types) {
2768 KASSERT(tl->
numtypes < num, (
"%s: no space", __func__));
2780 struct ng_mesg *binary, *ascii;
2786 binary->
header.arglen)) {
2793 NG_MKRESPONSE(resp, msg,
sizeof(*ascii) + bufSize, M_NOWAIT);
2801 bcopy(binary, ascii,
sizeof(*binary));
2810 if (c == NULL || c->
name == NULL) {
2816 if (c->
name == NULL) {
2830 if (argstype == NULL) {
2831 *ascii->
data =
'\0';
2834 ascii->
data, bufSize);
2835 if (error == ERANGE) {
2846 bufSize = strlen(ascii->
data) + 1;
2854 int bufSize = 20 * 1024;
2857 struct ng_mesg *ascii, *binary;
2873 NG_MKRESPONSE(resp, msg,
sizeof(*binary) + bufSize, M_NOWAIT);
2881 bcopy(ascii, binary,
sizeof(*ascii));
2885 c != NULL && c->
name != NULL; c++) {
2889 if (c == NULL || c->
name == NULL) {
2894 if (c->
name == NULL) {
2908 if (argstype == NULL) {
2912 (u_char *)binary->
data, &bufSize)) != 0) {
2966 0,
"Number of queue processing threads");
2968 0,
"Maximum number of non-data queue items to allocate");
2970 0,
"Maximum number of data queue items to allocate");
2972#ifdef NETGRAPH_DEBUG
2974static int allocated;
2990 (
"%s: incorrect item type: %d", __func__,
type));
2997#ifdef NETGRAPH_DEBUG
2999 TAILQ_INSERT_TAIL(&ng_itemlist, item, all);
3001 mtx_unlock(&ngq_mtx);
3042#ifdef NETGRAPH_DEBUG
3044 TAILQ_REMOVE(&ng_itemlist, item, all);
3046 mtx_unlock(&ngq_mtx);
3062 KASSERT((pitem != NULL), (
"%s: can't reallocate NULL", __func__));
3064 (
"%s: incorrect item type: %d", __func__,
type));
3104 if (
type->mod_event != NULL)
3108 LIST_REMOVE(
type, types);
3114 if (
type->refs > 1) {
3117 if (
type->refs == 0)
3119 if (
type->mod_event != NULL) {
3125 LIST_REMOVE(
type, types);
3131 if (
type->mod_event != NULL)
3153vnet_netgraph_uninit(
const void *unused __unused)
3155 node_p node = NULL, last_killed = NULL;
3175 if (node == last_killed) {
3177 panic(
"ng node %s won't die",
3186 }
while (node != NULL);
3191VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_NETGRAPH, SI_ORDER_FIRST,
3192 vnet_netgraph_uninit, NULL);
3210 rw_init(&ng_typelist_lock,
"netgraph types");
3211 rw_init(&ng_idhash_lock,
"netgraph idhash");
3212 rw_init(&ng_namehash_lock,
"netgraph namehash");
3214#ifdef NETGRAPH_DEBUG
3215 mtx_init(&ng_nodelist_mtx,
"netgraph nodelist mutex", NULL,
3217 mtx_init(&ngq_mtx,
"netgraph item list mutex", NULL,
3221 NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
3223 ng_qdzone = uma_zcreate(
"NetGraph data items",
3224 sizeof(
struct ng_item), NULL, NULL, NULL, NULL,
3225 UMA_ALIGN_CACHE, 0);
3233 if (kproc_kthread_add(
ngthread, NULL, &p, &td,
3234 RFHIGHPID, 0,
"ng_queue",
"ng_queue%d", i)) {
3262#ifdef NETGRAPH_DEBUG
3264dumphook (
hook_p hook,
char *file,
int line)
3266 printf(
"hook: name %s, %d refs, Last touched:\n",
3268 printf(
" Last active @ %s, line %d\n",
3269 hook->lastfile, hook->lastline);
3271 printf(
" problem discovered at file %s, line %d\n", file, line);
3279dumpnode(
node_p node,
char *file,
int line)
3281 printf(
"node: ID [%x]: type '%s', %d hooks, flags 0x%x, %d refs, %s:\n",
3285 printf(
" Last active @ %s, line %d\n",
3286 node->lastfile, node->lastline);
3288 printf(
" problem discovered at file %s, line %d\n", file, line);
3296dumpitem(
item_p item,
char *file,
int line)
3298 printf(
" ACTIVE item, last used at %s, line %d",
3299 item->lastfile, item->lastline);
3302 printf(
" - [data]\n");
3308 printf(
" - fn@%p (%p, %p, %p, %d (%x))\n",
3317 printf(
" - fn2@%p (%p, %p, %p, %d (%x))\n",
3327 printf(
" problem discovered at file %s, line %d\n", file, line);
3329 printf(
"node %p ([%x])\n",
3340 TAILQ_FOREACH(item, &ng_itemlist, all) {
3341 printf(
"[%d] ", i++);
3342 dumpitem(item, NULL, 0);
3351 mtx_lock(&ng_nodelist_mtx);
3352 SLIST_FOREACH(node, &ng_allnodes, nd_all) {
3353 printf(
"[%d] ", i++);
3354 dumpnode(node, NULL, 0);
3356 mtx_unlock(&ng_nodelist_mtx);
3364 mtx_lock(&ng_nodelist_mtx);
3365 SLIST_FOREACH(hook, &ng_allhooks, hk_all) {
3366 printf(
"[%d] ", i++);
3367 dumphook(hook, NULL, 0);
3369 mtx_unlock(&ng_nodelist_mtx);
3373sysctl_debug_ng_dump_items(SYSCTL_HANDLER_ARGS)
3381 error = sysctl_handle_int(oidp, &val, 0, req);
3382 if (error != 0 || req->newptr == NULL)
3393 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
sizeof(
int),
3394 sysctl_debug_ng_dump_items,
"I",
3395 "Number of allocated items");
3409 struct epoch_tracker et;
3414 while ((node = STAILQ_FIRST(&ng_worklist)) == NULL)
3416 STAILQ_REMOVE_HEAD(&ng_worklist, nd_input_queue.q_work);
3418 CURVNET_SET(node->nd_vnet);
3419 CTR3(KTR_NET,
"%20s: node [%x] (%p) taken off worklist",
3420 __func__, node->nd_ID, node);
3430 NET_EPOCH_ENTER(et);
3438 node->nd_input_queue.q_flags2 &= ~NGQ2_WORKQ;
3473 STAILQ_INSERT_TAIL(&ng_worklist, node, nd_input_queue.q_work);
3475 CTR3(KTR_NET,
"%20s: node [%x] (%p) put on worklist", __func__,
3479 CTR3(KTR_NET,
"%20s: node [%x] (%p) already on worklist",
3480 __func__, node->
nd_ID, node);
3488#ifdef NETGRAPH_DEBUG
3489#define ITEM_DEBUG_CHECKS \
3491 if (NGI_NODE(item) ) { \
3492 printf("item already has node"); \
3493 kdb_enter(KDB_WHY_NETGRAPH, "has node"); \
3494 NGI_CLR_NODE(item); \
3496 if (NGI_HOOK(item) ) { \
3497 printf("item already has hook"); \
3498 kdb_enter(KDB_WHY_NETGRAPH, "has hook"); \
3499 NGI_CLR_HOOK(item); \
3503#define ITEM_DEBUG_CHECKS
3564#define SET_RETADDR(item, here, retaddr) \
3566 if ((item->el_flags & NGQF_TYPE) == NGQF_MESG) { \
3568 NGI_RETADDR(item) = retaddr; \
3575 if (NGI_RETADDR(item) == 0) { \
3577 = ng_node2ID(here); \
3742 int arg2,
int flags)
3747 (
"%s: NG_REUSE_ITEM but no pitem", __func__));
3782 struct epoch_tracker et;
3785 NET_EPOCH_ENTER(et);
3786 CURVNET_SET(
NGI_NODE(item)->nd_vnet);
3830 (item != NULL) && (
NGI_NODE(item) == node)) {
3848 rval = callout_stop(c);
3868 rval = callout_drain(c);
#define NGI_SET_HOOK(i, h)
#define NGI_SET_NODE(i, n)
int ng_item_fn2(node_p node, struct ng_item *item, hook_p hook)
#define NGI_GET_NODE(i, n)
#define NGI_SET_WRITER(i)
#define NG_HOOK_NODE(hook)
#define NGI_GET_HOOK(i, h)
#define NG_PEER_NODE(hook)
#define NG_HOOK_UNREF(hook)
#define NG_PEER_HOOK_NAME(hook)
#define NG_HOOK_NOT_VALID(hook)
#define _NG_HOOK_NAME(hook)
#define NG_NODE_NOT_VALID(node)
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
#define NG_RESPOND_MSG(error, here, item, resp)
#define _NG_HOOK_NODE(hook)
#define NG_NODE_IS_VALID(node)
#define NGI_SET_READER(i)
struct ng_node const * node_cp
void ng_item_fn(node_p node, hook_p hook, void *arg1, int arg2)
#define NG_NODE_HAS_NAME(node)
#define NG_HOOK_PEER(hook)
#define NG_NODE_UNREF(node)
#define NG_NODE_NAME(node)
#define NG_PEER_NODE_NAME(hook)
#define _NG_NODE_ID(node)
#define NG_HOOK_REF(hook)
int ng_rcvdata_t(hook_p hook, item_p item)
#define NG_HOOK_NAME(hook)
#define NG_FREE_ITEM(item)
#define _NG_NODE_UNREF(node)
#define NG_HOOK_IS_VALID(hook)
#define NGI_GET_MSG(i, m)
#define NG_NODE_REF(node)
static int ng_con_part2(node_p node, item_p item, hook_p hook)
#define NG_WORKLIST_LOCK_INIT()
void ng_unref_hook(hook_p hook)
static __inline void ng_queue_rw(node_p node, item_p item, int rw)
struct ng_type * ng_findtype(const char *typename)
#define TOPOLOGY_NOTOWNED()
static __inline void ng_leave_read(node_p node)
void ng_unref_node(node_p node)
static void vnet_netgraph_init(const void *unused __unused)
int ng_uncallout_drain(struct callout *c, node_p node)
void ng_free_item(item_p item)
static __inline item_p ng_acquire_read(node_p node, item_p item)
static __inline item_p ng_dequeue(node_p node, int *rw)
#define NG_QUEUE_UNLOCK(n)
#define _NG_ALLOC_HOOK(hook)
static int ngb_mod_event(module_t mod, int event, void *data)
item_p ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg)
void ng_unname(node_p node)
int ng_mod_event(module_t mod, int event, void *data)
int ng_make_node(const char *typename, node_p *nodepp)
static const struct ng_parse_type ng_generic_linkinfo_array_type
#define NG_ALLOC_HOOK(hook)
int ng_path2noderef(node_p here, const char *address, node_p *destp, hook_p *lasthook)
static __inline item_p ng_acquire_write(node_p node, item_p item)
#define DEFINE_PARSE_STRUCT_TYPE(lo, up, args)
static const struct ng_parse_array_info ng_generic_linkinfo_array_type_info
static const struct ng_parse_type ng_generic_nodeinfoarray_type
static int ng_con_nodes(item_p item, node_p node, const char *name, node_p node2, const char *name2)
void ng_destroy_hook(hook_p hook)
static void ng_callout_trampoline(void *arg)
int ng_rmnode_self(node_p node)
static void ng_ID_rehash()
#define SET_RETADDR(item, here, retaddr)
#define NAMEHASH_RUNLOCK()
static __inline item_p ng_realloc_item(item_p pitem, int type, int flags)
int ng_newtype(struct ng_type *tp)
static const struct ng_parse_array_info ng_typeinfoarray_type_info
#define TOPOLOGY_WUNLOCK()
struct ng_node ng_deadnode
static STAILQ_HEAD(ng_node)
MODULE_VERSION(netgraph, NG_ABI_VERSION)
int ng_rmhook_self(hook_p hook)
static moduledata_t netgraph_mod
#define TYPELIST_RUNLOCK()
#define HEAD_IS_READER(QP)
static int ng_con_part3(node_p node, item_p item, hook_p hook)
struct ng_hook ng_deadhook
static void ngthread(void *arg)
static const struct ng_cmdlist ng_generic_cmds[]
#define NG_FREE_HOOK(hook)
int ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void *arg1, int arg2, int flags)
#define NEXT_QUEUED_ITEM_CAN_PROCEED(QP)
int ng_path_parse(char *addr, char **nodep, char **pathp, char **hookp)
int ng_snd_item(item_p item, int flags)
item_p ng_package_data(struct mbuf *m, int flags)
#define TYPELIST_WUNLOCK()
static ng_ID_t ng_decodeidname(const char *name)
int ng_address_ID(node_p here, item_p item, ng_ID_t ID, ng_ID_t retaddr)
SYSCTL_INT(_net_graph, OID_AUTO, threads, CTLFLAG_RDTUN, &numthreads, 0, "Number of queue processing threads")
static void ng_worklist_add(node_p node)
static void ng_rmhook_part2(node_p node, hook_p hook, void *arg1, int arg2)
int ng_address_path(node_p here, item_p item, const char *address, ng_ID_t retaddr)
static struct rwlock ng_topo_lock
#define NG_WORKLIST_LOCK()
void ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr)
static __inline void ng_leave_write(node_p node)
static int ng_generic_linkinfo_getLength(const struct ng_parse_type *type, const u_char *start, const u_char *buf)
int ng_uncallout(struct callout *c, node_p node)
#define NAMEHASH_WUNLOCK()
#define NG_WORKLIST_UNLOCK()
static void ng_uncallout_internal(struct callout *c, node_p node)
DECLARE_MODULE(netgraph, netgraph_mod, SI_SUB_NETGRAPH, SI_ORDER_FIRST)
static node_p ng_ID2noderef(ng_ID_t ID)
static int ng_apply_item(node_p node, item_p item, int rw)
int ng_rmtype(struct ng_type *tp)
void ng_rmnode(node_p node, hook_p dummy1, void *dummy2, int dummy3)
VNET_SYSINIT(vnet_netgraph_init, SI_SUB_NETGRAPH, SI_ORDER_FIRST, vnet_netgraph_init, NULL)
#define NG_ALLOC_NODE(node)
int ng_make_node_common(struct ng_type *type, node_p *nodepp)
int ng_name_node(node_p node, const char *name)
int ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, void *arg1, int arg2)
static const struct ng_parse_type ng_generic_typeinfoarray_type
static void ng_flush_input_queue(node_p node)
#define NG_WORKLIST_WAKEUP()
item_p ng_package_msg(struct ng_mesg *msg, int flags)
#define TOPOLOGY_RUNLOCK()
#define _NG_ALLOC_NODE(node)
ng_ID_t ng_node2ID(node_cp node)
static int ng_add_hook(node_p node, const char *name, hook_p *hookp)
static const struct ng_parse_array_info ng_nodeinfoarray_type_info
int ng_bypass(hook_p hook1, hook_p hook2)
int ng_address_hook(node_p here, item_p item, hook_p hook, ng_ID_t retaddr)
struct ng_type ng_deadtype
#define NG_QUEUE_LOCK_INIT(n)
static int ng_generic_msg(node_p here, item_p item, hook_p lasthook)
#define CHECK_DATA_MBUF(m)
static int ng_mkpeer(node_p node, const char *name, const char *name2, char *type)
#define NG_IDHASH_FIND(ID, node)
int ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn, void *arg1, int arg2, int flags)
static void ng_name_rehash()
#define NG_WORKLIST_SLEEP()
static __inline item_p ng_alloc_item(int type, int flags)
int ng_callout(struct callout *c, node_p node, hook_p hook, int ticks, ng_item_fn *fn, void *arg1, int arg2)
SYSCTL_NODE(_net, OID_AUTO, graph, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "netgraph Family")
node_p ng_name2noderef(node_p here, const char *name)
#define NG_FREE_NODE(node)
#define ITEM_DEBUG_CHECKS
hook_p ng_findhook(node_p node, const char *name)
SYSCTL_PROC(_net_bluetooth_hci, OID_AUTO, command_timeout, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_NEEDGIANT, &bluetooth_hci_command_timeout_value, 5, bluetooth_set_hci_command_timeout_value, "I", "HCI command timeout (sec)")
SLIST_HEAD(ng_bridge_bucket, ng_bridge_host)
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
VNET_DEFINE_STATIC(struct unrhdr *, ng_eiface_unit)
VNET_SYSUNINIT(vnet_ng_eiface_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_ng_eiface_uninit, NULL)
#define NG_MKRESPONSE(rsp, msg, len, how)
#define NGM_GENERIC_COOKIE
const struct ng_parse_type ng_parse_ng_mesg_type
int ng_unparse(const struct ng_parse_type *type, const u_char *data, char *cbuf, int cbuflen)
const struct ng_parse_type ng_parse_array_type
const struct ng_parse_type ng_parse_string_type
int ng_parse(const struct ng_parse_type *type, const char *string, int *off, u_char *buf, int *buflen)
typedef TAILQ_HEAD(sscfu_sigq, sscfu_sig) sscfu_sigq_head_t
struct ubt_hci_evhdr header
static LIST_HEAD(ngatm_msg)
char peerhook[NG_HOOKSIZ]
struct nodeinfo nodeinfo[]
const struct ng_parse_type * respType
const struct ng_parse_type * mesgType
ng_rcvdata_t * hk_rcvdata
struct ng_apply_info * apply
struct ng_item::@23::@25 fn
u_char cmdstr[NG_CMDSTRSIZ]
struct ng_mesg::ng_msghdr header
struct ng_queue nd_input_queue
ng_disconnect_t * disconnect
const struct ng_cmdlist * cmdlist
char peerhook[NG_HOOKSIZ]
char peerhook[NG_HOOKSIZ]
char type_name[NG_TYPESIZ]
struct typeinfo typeinfo[]