Author: jhb
Date: Sun Oct  7 18:57:52 2012
New Revision: 241328
URL: http://svn.freebsd.org/changeset/base/241328

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/8/sys/net/if_vlan.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/net/   (props changed)

Modified: stable/8/sys/net/if_vlan.c
==============================================================================
--- stable/8/sys/net/if_vlan.c  Sun Oct  7 18:57:29 2012        (r241327)
+++ stable/8/sys/net/if_vlan.c  Sun Oct  7 18:57:52 2012        (r241328)
@@ -188,7 +188,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, int link);
 static void vlan_capabilities(struct ifvlan *ifv);
@@ -543,7 +543,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;
                }
@@ -551,7 +551,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
@@ -821,7 +821,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.
                         */
@@ -1163,17 +1163,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();
 
@@ -1204,13 +1205,21 @@ vlan_unconfig_locked(struct ifnet *ifp)
                            ETHER_ADDR_LEN);
 
                        /*
-                        * 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 *)&sdl);
+                       if (!departing) {
+                               error = if_delmulti(parent,
+                                   (struct sockaddr *)&sdl);
+                               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);
                }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to