Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 7 Oct 2012 18:57:29 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r241327 - stable/9/sys/net
Message-ID:  <201210071857.q97IvTNO052576@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Sun Oct  7 18:57:29 2012
New Revision: 241327
URL: http://svn.freebsd.org/changeset/base/241327

Log:
  MFC 239440,239519:
  Refine the changes made in r208212 to avoid bogus failures from
  if_delmulti() when clearing the configuration for a subinterface when
  the parent interface is being detached.  The current code was still
  triggering an assertion in if_delmulti() due to the parent interface being
  partially detached.  Fix this by not calling if_delmulti() at all if the
  parent interface is being detached.  Warn if if_delmulti() fails when the
  parent is not being detached (but similar to 208212, still proceed with
  tearing down the vlan state).

Modified:
  stable/9/sys/net/if_vlan.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/net/if_vlan.c
==============================================================================
--- stable/9/sys/net/if_vlan.c	Sun Oct  7 18:47:53 2012	(r241326)
+++ stable/9/sys/net/if_vlan.c	Sun Oct  7 18:57:29 2012	(r241327)
@@ -190,7 +190,7 @@ static	int vlan_setflags(struct ifnet *i
 static	int vlan_setmulti(struct ifnet *ifp);
 static	int vlan_transmit(struct ifnet *ifp, struct mbuf *m);
 static	void vlan_unconfig(struct ifnet *ifp);
-static	void vlan_unconfig_locked(struct ifnet *ifp);
+static	void vlan_unconfig_locked(struct ifnet *ifp, int departing);
 static	int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag);
 static	void vlan_link_state(struct ifnet *ifp);
 static	void vlan_capabilities(struct ifvlan *ifv);
@@ -575,7 +575,7 @@ vlan_ifdetach(void *arg __unused, struct
 #ifdef VLAN_ARRAY
 	for (i = 0; i < VLAN_ARRAY_SIZE; i++)
 		if ((ifv = ifp->if_vlantrunk->vlans[i])) {
-			vlan_unconfig_locked(ifv->ifv_ifp);
+			vlan_unconfig_locked(ifv->ifv_ifp, 1);
 			if (ifp->if_vlantrunk == NULL)
 				break;
 		}
@@ -583,7 +583,7 @@ vlan_ifdetach(void *arg __unused, struct
 restart:
 	for (i = 0; i < (1 << ifp->if_vlantrunk->hwidth); i++)
 		if ((ifv = LIST_FIRST(&ifp->if_vlantrunk->hash[i]))) {
-			vlan_unconfig_locked(ifv->ifv_ifp);
+			vlan_unconfig_locked(ifv->ifv_ifp, 1);
 			if (ifp->if_vlantrunk)
 				goto restart;	/* trunk->hwidth can change */
 			else
@@ -959,7 +959,7 @@ vlan_clone_create(struct if_clone *ifc, 
 		error = vlan_config(ifv, p, tag);
 		if (error != 0) {
 			/*
-			 * Since we've partialy failed, we need to back
+			 * Since we've partially failed, we need to back
 			 * out all the way, otherwise userland could get
 			 * confused.  Thus, we destroy the interface.
 			 */
@@ -1298,17 +1298,18 @@ vlan_unconfig(struct ifnet *ifp)
 {
 
 	VLAN_LOCK();
-	vlan_unconfig_locked(ifp);
+	vlan_unconfig_locked(ifp, 0);
 	VLAN_UNLOCK();
 }
 
 static void
-vlan_unconfig_locked(struct ifnet *ifp)
+vlan_unconfig_locked(struct ifnet *ifp, int departing)
 {
 	struct ifvlantrunk *trunk;
 	struct vlan_mc_entry *mc;
 	struct ifvlan *ifv;
 	struct ifnet  *parent;
+	int error;
 
 	VLAN_LOCK_ASSERT();
 
@@ -1328,14 +1329,21 @@ vlan_unconfig_locked(struct ifnet *ifp)
 		 */
 		while ((mc = SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
 			/*
-			 * This may fail if the parent interface is
-			 * being detached.  Regardless, we should do a
-			 * best effort to free this interface as much
-			 * as possible as all callers expect vlan
-			 * destruction to succeed.
+			 * If the parent interface is being detached,
+			 * all its multicast addresses have already
+			 * been removed.  Warn about errors if
+			 * if_delmulti() does fail, but don't abort as
+			 * all callers expect vlan destruction to
+			 * succeed.
 			 */
-			(void)if_delmulti(parent,
-			    (struct sockaddr *)&mc->mc_addr);
+			if (!departing) {
+				error = if_delmulti(parent,
+				    (struct sockaddr *)&mc->mc_addr);
+				if (error)
+					if_printf(ifp,
+		    "Failed to delete multicast address from parent: %d\n",
+					    error);
+			}
 			SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries);
 			free(mc, M_VLAN);
 		}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210071857.q97IvTNO052576>