summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--UPDATING4
-rw-r--r--sys/netgraph/netgraph.h33
-rw-r--r--sys/netgraph/ng_base.c6
-rw-r--r--sys/netgraph/ng_eiface.c3
-rw-r--r--sys/netgraph/ng_ether.c3
-rw-r--r--sys/netgraph/ng_iface.c6
-rw-r--r--sys/netgraph/ng_ip_input.c6
-rw-r--r--sys/sys/proc.h1
8 files changed, 56 insertions, 6 deletions
diff --git a/UPDATING b/UPDATING
index d5e05f9..0d398e8 100644
--- a/UPDATING
+++ b/UPDATING
@@ -22,6 +22,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW:
to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
+20090611:
+ The layout of struct thread has changed. Kernel and modules
+ need to be rebuilt.
+
20090608:
The layout of structs ifnet, domain, protosw and vnet_net has
changed. Kernel modules need to be rebuilt.
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h
index 7276427..5a0418e 100644
--- a/sys/netgraph/netgraph.h
+++ b/sys/netgraph/netgraph.h
@@ -130,6 +130,7 @@ struct ng_hook {
#define HK_FORCE_WRITER 0x0004 /* Incoming data queued as a writer */
#define HK_DEAD 0x0008 /* This is the dead hook.. don't free */
#define HK_HI_STACK 0x0010 /* Hook has hi stack usage */
+#define HK_TO_INBOUND 0x0020 /* Hook on ntw. stack inbound path. */
/*
* Public Methods for hook
@@ -150,6 +151,8 @@ void ng_unref_hook(hook_p hook); /* don't move this */
#define _NG_HOOK_FORCE_WRITER(hook) \
do { hook->hk_flags |= HK_FORCE_WRITER; } while (0)
#define _NG_HOOK_FORCE_QUEUE(hook) do { hook->hk_flags |= HK_QUEUE; } while (0)
+#define _NG_HOOK_SET_TO_INBOUND(hook) \
+ do { hook->hk_flags |= HK_TO_INBOUND; } while (0)
#define _NG_HOOK_HI_STACK(hook) do { hook->hk_flags |= HK_HI_STACK; } while (0)
/* Some shortcuts */
@@ -176,8 +179,11 @@ static __inline int _ng_hook_is_valid(hook_p hook, char * file, int line);
static __inline node_p _ng_hook_node(hook_p hook, char * file, int line);
static __inline hook_p _ng_hook_peer(hook_p hook, char * file, int line);
static __inline void _ng_hook_force_writer(hook_p hook, char * file,
- int line);
-static __inline void _ng_hook_force_queue(hook_p hook, char * file, int line);
+ int line);
+static __inline void _ng_hook_force_queue(hook_p hook, char * file,
+ int line);
+static __inline void _ng_hook_set_to_inbound(hook_p hook, char * file,
+ int line);
static __inline void
_chkhook(hook_p hook, char *file, int line)
@@ -282,6 +288,13 @@ _ng_hook_force_queue(hook_p hook, char * file, int line)
}
static __inline void
+_ng_hook_set_to_inbound(hook_p hook, char * file, int line)
+{
+ _chkhook(hook, file, line);
+ _NG_HOOK_SET_TO_INBOUND(hook);
+}
+
+static __inline void
_ng_hook_hi_stack(hook_p hook, char * file, int line)
{
_chkhook(hook, file, line);
@@ -302,6 +315,7 @@ _ng_hook_hi_stack(hook_p hook, char * file, int line)
#define NG_HOOK_PEER(hook) _ng_hook_peer(hook, _NN_)
#define NG_HOOK_FORCE_WRITER(hook) _ng_hook_force_writer(hook, _NN_)
#define NG_HOOK_FORCE_QUEUE(hook) _ng_hook_force_queue(hook, _NN_)
+#define NG_HOOK_SET_TO_INBOUND(hook) _ng_hook_set_to_inbound(hook, _NN_)
#define NG_HOOK_HI_STACK(hook) _ng_hook_hi_stack(hook, _NN_)
#else /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
@@ -319,6 +333,7 @@ _ng_hook_hi_stack(hook_p hook, char * file, int line)
#define NG_HOOK_PEER(hook) _NG_HOOK_PEER(hook)
#define NG_HOOK_FORCE_WRITER(hook) _NG_HOOK_FORCE_WRITER(hook)
#define NG_HOOK_FORCE_QUEUE(hook) _NG_HOOK_FORCE_QUEUE(hook)
+#define NG_HOOK_SET_TO_INBOUND(hook) _NG_HOOK_SET_TO_INBOUND(hook)
#define NG_HOOK_HI_STACK(hook) _NG_HOOK_HI_STACK(hook)
#endif /* NETGRAPH_DEBUG */ /*----------------------------------------------*/
@@ -1189,6 +1204,20 @@ typedef void *meta_p;
#define NG_ID_HASH_SIZE 128 /* most systems wont need even this many */
#define NG_NAME_HASH_SIZE 128 /* most systems wont need even this many */
+/*
+ * Mark the current thread when called from the outbound path of the
+ * network stack, in order to enforce queuing on ng nodes calling into
+ * the inbound network stack path.
+ */
+#define NG_OUTBOUND_THREAD_REF() \
+ curthread->td_ng_outbound++
+#define NG_OUTBOUND_THREAD_UNREF() \
+ do { \
+ curthread->td_ng_outbound--; \
+ KASSERT(curthread->td_ng_outbound >= 0, \
+ ("%s: negative td_ng_outbound", __func__)); \
+ } while (0)
+
/* Virtualization macros */
#define INIT_VNET_NETGRAPH(vnet) \
INIT_FROM_VNET(vnet, VNET_MOD_NETGRAPH, \
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 39084b5..a495701 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -2213,11 +2213,15 @@ ng_snd_item(item_p item, int flags)
}
/*
- * If sender or receiver requests queued delivery or stack usage
+ * If sender or receiver requests queued delivery, or call graph
+ * loops back from outbound to inbound path, or stack usage
* level is dangerous - enqueue message.
*/
if ((flags & NG_QUEUE) || (hook && (hook->hk_flags & HK_QUEUE))) {
queue = 1;
+ } else if (hook && (hook->hk_flags & HK_TO_INBOUND) &&
+ curthread->td_ng_outbound) {
+ queue = 1;
} else {
queue = 0;
#ifdef GET_STACK_USAGE
diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c
index 615d10d..5474798 100644
--- a/sys/netgraph/ng_eiface.c
+++ b/sys/netgraph/ng_eiface.c
@@ -261,7 +261,9 @@ ng_eiface_start2(node_p node, hook_p hook, void *arg1, int arg2)
* Send packet; if hook is not connected, mbuf will get
* freed.
*/
+ NG_OUTBOUND_THREAD_REF();
NG_SEND_DATA_ONLY(error, priv->ether, m);
+ NG_OUTBOUND_THREAD_UNREF();
/* Update stats */
if (error == 0)
@@ -414,6 +416,7 @@ ng_eiface_newhook(node_p node, hook_p hook, const char *name)
return (EISCONN);
priv->ether = hook;
NG_HOOK_SET_PRIVATE(hook, &priv->ether);
+ NG_HOOK_SET_TO_INBOUND(hook);
if_link_state_change(ifp, LINK_STATE_UP);
diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c
index 679c4e9..d009e00 100644
--- a/sys/netgraph/ng_ether.c
+++ b/sys/netgraph/ng_ether.c
@@ -282,7 +282,9 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
return (0);
/* Send it out "upper" hook */
+ NG_OUTBOUND_THREAD_REF();
NG_SEND_DATA_ONLY(error, priv->upper, *mp);
+ NG_OUTBOUND_THREAD_UNREF();
return (error);
}
@@ -416,6 +418,7 @@ ng_ether_newhook(node_p node, hook_p hook, const char *name)
if (strcmp(name, NG_ETHER_HOOK_UPPER) == 0) {
hookptr = &priv->upper;
NG_HOOK_SET_RCVDATA(hook, ng_ether_rcv_upper);
+ NG_HOOK_SET_TO_INBOUND(hook);
} else if (strcmp(name, NG_ETHER_HOOK_LOWER) == 0) {
hookptr = &priv->lower;
NG_HOOK_SET_RCVDATA(hook, ng_ether_rcv_lower);
diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c
index 385750c..d6e3d64 100644
--- a/sys/netgraph/ng_iface.c
+++ b/sys/netgraph/ng_iface.c
@@ -482,9 +482,10 @@ ng_iface_send(struct ifnet *ifp, struct mbuf *m, sa_family_t sa)
/* Copy length before the mbuf gets invalidated. */
len = m->m_pkthdr.len;
- /* Send packet. If hook is not connected,
- mbuf will get freed. */
+ /* Send packet. If hook is not connected, mbuf will get freed. */
+ NG_OUTBOUND_THREAD_REF();
NG_SEND_DATA_ONLY(error, *get_hook_from_iffam(priv, iffam), m);
+ NG_OUTBOUND_THREAD_UNREF();
/* Update stats. */
if (error == 0) {
@@ -610,6 +611,7 @@ ng_iface_newhook(node_p node, hook_p hook, const char *name)
return (EISCONN);
*hookptr = hook;
NG_HOOK_HI_STACK(hook);
+ NG_HOOK_SET_TO_INBOUND(hook);
return (0);
}
diff --git a/sys/netgraph/ng_ip_input.c b/sys/netgraph/ng_ip_input.c
index 416bc12..af0254b 100644
--- a/sys/netgraph/ng_ip_input.c
+++ b/sys/netgraph/ng_ip_input.c
@@ -77,6 +77,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
+#include <sys/proc.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/if_var.h>
@@ -120,7 +121,10 @@ ngipi_rcvdata(hook_p hook, item_p item)
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
- netisr_dispatch(NETISR_IP, m);
+ if (curthread->td_ng_outbound)
+ netisr_queue(NETISR_IP, m);
+ else
+ netisr_dispatch(NETISR_IP, m);
return 0;
}
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 96f811d..1dd82ed 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -235,6 +235,7 @@ struct thread {
char td_name[MAXCOMLEN + 1]; /* (*) Thread name. */
struct file *td_fpop; /* (k) file referencing cdev under op */
int td_dbgflags; /* (c) Userland debugger flags */
+ int td_ng_outbound; /* (k) Thread entered ng from above. */
struct osd td_osd; /* (k) Object specific data. */
#define td_endzero td_base_pri
OpenPOWER on IntegriCloud