svn commit: r194012 - in head: . sys/netgraph sys/sys
Marko Zec
zec at freebsd.org
Thu Jun 11 16:56:42 UTC 2009
On Thursday 11 June 2009 18:50:49 Marko Zec wrote:
> Author: zec
> Date: Thu Jun 11 16:50:49 2009
> New Revision: 194012
> URL: http://svn.freebsd.org/changeset/base/194012
>
> Log:
> Introduce a mechanism for detecting calls from outbound path of the
> network stack when reentering the inbound path from netgraph, and
> force queueing of mbufs at the outbound netgraph node.
^^^^^^^^
s/outbound/inbound/ -> the framework prevents direct call dispatching at the
egress netgraph node, i.e. the one reentering the network stack from below,
not on the output path.
Sorry for the typo...
Marko
>
> The mechanism relies on two components. First, in netgraph nodes
> where outbound path of the network stack calls into netgraph, the
> current thread has to be appropriately marked using the new
> NG_OUTBOUND_THREAD_REF() macro before proceeding to call further
> into the netgraph topology, and unmarked using the
> NG_OUTBOUND_THREAD_UNREF() macro before returning to the caller.
> Second, netgraph nodes which can potentially reenter the network
> stack in the inbound path have to mark their inbound hooks using
> NG_HOOK_SET_TO_INBOUND() macro. The netgraph framework will then
> detect when there is a danger of a call graph looping back from
> outbound to inbound path via netgraph, and defer handing off the
> mbufs to the "inbound" node to a worker thread with a clean stack.
>
> In this first pass only the most obvious netgraph nodes have been
> updated to ensure no outbound to inbound calls can occur. Nodes
> such as ng_ipfw, ng_gif etc. should be further examined whether a
> potential for outbound to inbound call looping exists.
>
> This commit changes the layout of struct thread, but due to
> __FreeBSD_version number shortage a version bump has been omitted
> at this time, nevertheless kernel and modules have to be rebuilt.
>
> Reviewed by: julian, rwatson, bz
> Approved by: julian (mentor)
>
> Modified:
> head/UPDATING
> head/sys/netgraph/netgraph.h
> head/sys/netgraph/ng_base.c
> head/sys/netgraph/ng_eiface.c
> head/sys/netgraph/ng_ether.c
> head/sys/netgraph/ng_iface.c
> head/sys/netgraph/ng_ip_input.c
> head/sys/sys/proc.h
>
> Modified: head/UPDATING
> ===========================================================================
>=== --- head/UPDATING Thu Jun 11 16:48:59 2009 (r194011)
> +++ head/UPDATING Thu Jun 11 16:50:49 2009 (r194012)
> @@ -22,6 +22,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.
> 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.
>
> Modified: head/sys/netgraph/netgraph.h
> ===========================================================================
>=== --- head/sys/netgraph/netgraph.h Thu Jun 11 16:48:59 2009 (r194011) +++
> head/sys/netgraph/netgraph.h Thu Jun 11 16:50:49 2009 (r194012) @@ -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'
> #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(ho
> 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 *
> }
>
> 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 * fi
> #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 * fi
> #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, \
>
> Modified: head/sys/netgraph/ng_base.c
> ===========================================================================
>=== --- head/sys/netgraph/ng_base.c Thu Jun 11 16:48:59 2009 (r194011) +++
> head/sys/netgraph/ng_base.c Thu Jun 11 16:50:49 2009 (r194012) @@ -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
>
> Modified: head/sys/netgraph/ng_eiface.c
> ===========================================================================
>=== --- head/sys/netgraph/ng_eiface.c Thu Jun 11 16:48:59 2009 (r194011) +++
> head/sys/netgraph/ng_eiface.c Thu Jun 11 16:50:49 2009 (r194012) @@ -261,7
> +261,9 @@ ng_eiface_start2(node_p node, hook_p hoo
> * 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 ho
> 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);
>
>
> Modified: head/sys/netgraph/ng_ether.c
> ===========================================================================
>=== --- head/sys/netgraph/ng_ether.c Thu Jun 11 16:48:59 2009 (r194011) +++
> head/sys/netgraph/ng_ether.c Thu Jun 11 16:50:49 2009 (r194012) @@ -282,7
> +282,9 @@ ng_ether_output(struct ifnet *ifp, struc
> 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 hoo
> 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);
>
> Modified: head/sys/netgraph/ng_iface.c
> ===========================================================================
>=== --- head/sys/netgraph/ng_iface.c Thu Jun 11 16:48:59 2009 (r194011) +++
> head/sys/netgraph/ng_iface.c Thu Jun 11 16:50:49 2009 (r194012) @@ -482,9
> +482,10 @@ ng_iface_send(struct ifnet *ifp, struct
> /* 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 hoo
> return (EISCONN);
> *hookptr = hook;
> NG_HOOK_HI_STACK(hook);
> + NG_HOOK_SET_TO_INBOUND(hook);
> return (0);
> }
>
>
> Modified: head/sys/netgraph/ng_ip_input.c
> ===========================================================================
>=== --- head/sys/netgraph/ng_ip_input.c Thu Jun 11 16:48:59 2009 (r194011)
> +++ head/sys/netgraph/ng_ip_input.c Thu Jun 11 16:50:49 2009 (r194012) @@
> -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;
> }
>
>
> Modified: head/sys/sys/proc.h
> ===========================================================================
>=== --- head/sys/sys/proc.h Thu Jun 11 16:48:59 2009 (r194011)
> +++ head/sys/sys/proc.h Thu Jun 11 16:50:49 2009 (r194012)
> @@ -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
More information about the svn-src-all
mailing list