Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 May 2010 19:36:56 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r208212 - head/sys/net
Message-ID:  <201005171936.o4HJauI8018586@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon May 17 19:36:56 2010
New Revision: 208212
URL: http://svn.freebsd.org/changeset/base/208212

Log:
  Ignore failures from removing multicast addresses from the parent (trunk)
  interface when tearing down a vlan interface.  If a trunk interface is
  detached, all of its multicast addresses are removed before the ifnet
  departure eventhandlers are invoked.  This means that all of the multicast
  addresses are removed before the vlan interfaces are removed which causes
  the if_delmulti() calls in the vlan teardown to fail.
  
  In the VLAN_ARRAY case, this left vlan interfaces referencing a no longer
  valid parent interface.  In the !VLAN_ARRAY case, the eventhandler gets
  stuck in an infinite loop retrying vlan_unconfig_locked() forever.  In
  general the callers of vlan_unconfig_locked() do not expect nor handle
  failure, so I believe it is safer to ignore the errors and tear down as
  much of the vlan state as possible.
  
  Silence from:	net@
  MFC after:	4 days

Modified:
  head/sys/net/if_vlan.c

Modified: head/sys/net/if_vlan.c
==============================================================================
--- head/sys/net/if_vlan.c	Mon May 17 19:19:48 2010	(r208211)
+++ head/sys/net/if_vlan.c	Mon May 17 19:36:56 2010	(r208212)
@@ -187,8 +187,8 @@ static	int vlan_setflag(struct ifnet *if
     int (*func)(struct ifnet *, int));
 static	int vlan_setflags(struct ifnet *ifp, int status);
 static	int vlan_setmulti(struct ifnet *ifp);
-static	int vlan_unconfig(struct ifnet *ifp);
-static	int vlan_unconfig_locked(struct ifnet *ifp);
+static	void vlan_unconfig(struct ifnet *ifp);
+static	void vlan_unconfig_locked(struct ifnet *ifp);
 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);
@@ -1128,25 +1128,22 @@ done:
 	return (error);
 }
 
-static int
+static void
 vlan_unconfig(struct ifnet *ifp)
 {
-	int ret;
 
 	VLAN_LOCK();
-	ret = vlan_unconfig_locked(ifp);
+	vlan_unconfig_locked(ifp);
 	VLAN_UNLOCK();
-	return (ret);
 }
 
-static int
+static void
 vlan_unconfig_locked(struct ifnet *ifp)
 {
 	struct ifvlantrunk *trunk;
 	struct vlan_mc_entry *mc;
 	struct ifvlan *ifv;
 	struct ifnet  *parent;
-	int error;
 
 	VLAN_LOCK_ASSERT();
 
@@ -1175,9 +1172,15 @@ vlan_unconfig_locked(struct ifnet *ifp)
 		while ((mc = SLIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
 			bcopy((char *)&mc->mc_addr, LLADDR(&sdl),
 			    ETHER_ADDR_LEN);
-			error = if_delmulti(parent, (struct sockaddr *)&sdl);
-			if (error)
-				return (error);
+
+			/*
+			 * 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.
+			 */
+			(void)if_delmulti(parent, (struct sockaddr *)&sdl);
 			SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries);
 			free(mc, M_VLAN);
 		}
@@ -1223,8 +1226,6 @@ vlan_unconfig_locked(struct ifnet *ifp)
 	 */
 	if (parent != NULL)
 		EVENTHANDLER_INVOKE(vlan_unconfig, parent, ifv->ifv_tag);
-
-	return (0);
 }
 
 /* Handle a reference counted flag that should be set on the parent as well */



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