kern/63317: [patch] make ng_ether(4) support "lower" and "orphans" simultaneously

Gleb Smirnoff glebius at cell.sick.ru
Tue Feb 24 11:50:13 PST 2004


>Number:         63317
>Category:       kern
>Synopsis:       [patch] make ng_ether(4) support "lower" and "orphans" simultaneously
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Feb 24 11:50:12 PST 2004
>Closed-Date:
>Last-Modified:
>Originator:     Gleb Smirnoff
>Release:        FreeBSD 4.9-PRERELEASE i386
>Organization:
Oilspace, Inc.
>Environment:
System: FreeBSD cell.sick.ru 4.9-PRERELEASE FreeBSD 4.9-PRERELEASE #0: Fri Sep 19 10:22:46 MSD 2003 root at fade.bestcom.ru:/usr/obj/usr/src/sys/NUCLEUS i386
>Description:
	
	It is mentioned in manpage ng_ether.4, that ng_ether node has
	a limitation:

     The orphans hook is equivalent to lower, except that only unrecognized
     packets (that would otherwise be discarded) are written to the hook, and
     normal incoming traffic is unaffected.  At most one of orphans and lower
     may be connected at any time.

	In some cases it is necessary to use both hooks. Examining code
	haven't revealed any obstacles for me, so I still can't guess
	what was the purpose of such a limitation. May be developers
	will point me at some underwater stone.

>How-To-Repeat:

	Try to connect both "lower" and "orphans" at one time.

>Fix:

	A patch for CURRENT follows. A patch for STABLE
	can be found here:

	http://cell.sick.ru/~glebius/patches/netgraph/ng_ether_lowerorphan/ng_ether.c.diff.STABLE

	The patch for STABLE was successfully used at production
	router for ~ 2 weeks.

--- ng_ether.c.orig	Mon Feb 23 15:18:14 2004
+++ ng_ether.c	Mon Feb 23 15:26:20 2004
@@ -71,8 +71,8 @@
 struct private {
 	struct ifnet	*ifp;		/* associated interface */
 	hook_p		upper;		/* upper hook connection */
-	hook_p		lower;		/* lower OR orphan hook connection */
-	u_char		lowerOrphan;	/* whether lower is lower or orphan */
+	hook_p		lower;		/* lower hook connection */
+	hook_p		orphan;		/* orphan hook connection */
 	u_char		autoSrcAddr;	/* always overwrite source address */
 	u_char		promisc;	/* promiscuous mode enabled */
 	u_long		hwassist;	/* hardware checksum capabilities */
@@ -95,7 +95,7 @@
 static void	ng_ether_detach(struct ifnet *ifp); 
 
 /* Other functions */
-static void	ng_ether_input2(node_p node, struct mbuf **mp);
+static void	ng_ether_input2(hook_p hook, struct mbuf **mp);
 static int	ng_ether_rcv_lower(node_p node, struct mbuf *m, meta_p meta);
 static int	ng_ether_rcv_upper(node_p node, struct mbuf *m, meta_p meta);
 
@@ -204,9 +204,9 @@
 	const priv_p priv = NG_NODE_PRIVATE(node);
 
 	/* If "lower" hook not connected, let packet continue */
-	if (priv->lower == NULL || priv->lowerOrphan)
+	if (priv->lower == NULL)
 		return;
-	ng_ether_input2(node, mp);
+	ng_ether_input2(priv->lower, mp);
 }
 
 /*
@@ -222,11 +222,11 @@
 	const priv_p priv = NG_NODE_PRIVATE(node);
 
 	/* If "orphan" hook not connected, let packet continue */
-	if (priv->lower == NULL || !priv->lowerOrphan) {
+	if (priv->orphan == NULL ) {
 		m_freem(m);
 		return;
 	}
-	ng_ether_input2(node, &m);
+	ng_ether_input2(priv->orphan, &m);
 	if (m != NULL)
 		m_freem(m);
 }
@@ -239,13 +239,12 @@
  * NOTE: this function will get called at splimp()
  */
 static void
-ng_ether_input2(node_p node, struct mbuf **mp)
+ng_ether_input2(hook_p hook, struct mbuf **mp)
 {
-	const priv_p priv = NG_NODE_PRIVATE(node);
 	int error;
 
 	/* Send out lower/orphan hook */
-	NG_SEND_DATA_ONLY(error, priv->lower, *mp);
+	NG_SEND_DATA_ONLY(error, hook, *mp);
 	*mp = NULL;
 }
 
@@ -353,7 +352,6 @@
 ng_ether_newhook(node_p node, hook_p hook, const char *name)
 {
 	const priv_p priv = NG_NODE_PRIVATE(node);
-	u_char orphan = priv->lowerOrphan;
 	hook_p *hookptr;
 
 	/* Divert hook is an alias for lower */
@@ -365,10 +363,8 @@
 		hookptr = &priv->upper;
 	else if (strcmp(name, NG_ETHER_HOOK_LOWER) == 0) {
 		hookptr = &priv->lower;
-		orphan = 0;
 	} else if (strcmp(name, NG_ETHER_HOOK_ORPHAN) == 0) {
-		hookptr = &priv->lower;
-		orphan = 1;
+		hookptr = &priv->orphan;
 	} else
 		return (EINVAL);
 
@@ -382,7 +378,6 @@
 
 	/* OK */
 	*hookptr = hook;
-	priv->lowerOrphan = orphan;
 	return (0);
 }
 
@@ -515,7 +510,7 @@
 	NGI_GET_M(item, m);
 	NGI_GET_META(item, meta);
 	NG_FREE_ITEM(item);
-	if (hook == priv->lower)
+	if (hook == priv->lower || hook == priv->orphan)
 		return ng_ether_rcv_lower(node, m, meta);
 	if (hook == priv->upper)
 		return ng_ether_rcv_upper(node, m, meta);
@@ -632,7 +627,8 @@
 			priv->ifp->if_hwassist = priv->hwassist;
 	} else if (hook == priv->lower) {
 		priv->lower = NULL;
-		priv->lowerOrphan = 0;
+	} else if (hook == priv->orphan) {
+		priv->orphan = NULL;
 	} else
 		panic("%s: weird hook", __func__);
 	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list