From owner-svn-src-head@FreeBSD.ORG Thu Jun 11 16:56:42 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6D7C5106566B; Thu, 11 Jun 2009 16:56:42 +0000 (UTC) (envelope-from zec@freebsd.org) Received: from xaqua.tel.fer.hr (xaqua.tel.fer.hr [161.53.19.25]) by mx1.freebsd.org (Postfix) with ESMTP id 944AA8FC0A; Thu, 11 Jun 2009 16:56:41 +0000 (UTC) (envelope-from zec@freebsd.org) Received: by xaqua.tel.fer.hr (Postfix, from userid 20006) id 2CADE9B647; Thu, 11 Jun 2009 18:56:40 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.1.7 (2006-10-05) on xaqua.tel.fer.hr X-Spam-Level: X-Spam-Status: No, score=-1.6 required=5.0 tests=AWL autolearn=unavailable version=3.1.7 Received: from localhost (imunes.tel.fer.hr [161.53.19.8]) by xaqua.tel.fer.hr (Postfix) with ESMTP id A63149B645; Thu, 11 Jun 2009 18:56:16 +0200 (CEST) From: Marko Zec To: src-committers@freebsd.org Date: Thu, 11 Jun 2009 18:56:07 +0200 User-Agent: KMail/1.9.10 References: <200906111650.n5BGonnn053446@svn.freebsd.org> In-Reply-To: <200906111650.n5BGonnn053446@svn.freebsd.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200906111856.07618.zec@freebsd.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org Subject: Re: svn commit: r194012 - in head: . sys/netgraph sys/sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Jun 2009 16:56:42 -0000 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 > #include > #include > +#include > #include > #include > #include > @@ -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