Author: hrs
Date: Sun Oct  5 02:34:21 2014
New Revision: 272547
URL: https://svnweb.freebsd.org/changeset/base/272547

Log:
  - Move L2 addr configuration for the primary port to a taskqueue.  This fixes
    LOR of softc rmlock in iflladdr_event handlers.
  
  - Call if_delmulti_ifma() after LACP_UNLOCK().  This fixes another LOR.
  
  - Fix a panic in lacp_transit_expire().
  
  - Fix a panic in lagg_input() upon shutting down a port.

Modified:
  head/sys/net/ieee8023ad_lacp.c
  head/sys/net/if_lagg.c
  head/sys/net/if_lagg.h

Modified: head/sys/net/ieee8023ad_lacp.c
==============================================================================
--- head/sys/net/ieee8023ad_lacp.c      Sun Oct  5 02:16:53 2014        
(r272546)
+++ head/sys/net/ieee8023ad_lacp.c      Sun Oct  5 02:34:21 2014        
(r272547)
@@ -579,12 +579,13 @@ lacp_port_destroy(struct lagg_port *lgp)
        lacp_disable_distributing(lp);
        lacp_unselect(lp);
 
+       LIST_REMOVE(lp, lp_next);
+       LACP_UNLOCK(lsc);
+
        /* The address may have already been removed by if_purgemaddrs() */
        if (!lgp->lp_detaching)
                if_delmulti_ifma(lp->lp_ifma);
 
-       LIST_REMOVE(lp, lp_next);
-       LACP_UNLOCK(lsc);
        free(lp, M_DEVBUF);
 }
 
@@ -745,7 +746,9 @@ lacp_transit_expire(void *vp)
 
        LACP_LOCK_ASSERT(lsc);
 
+       CURVNET_SET(lsc->lsc_softc->sc_ifp->if_vnet);
        LACP_TRACE(NULL);
+       CURVNET_RESTORE();
 
        lsc->lsc_suppress_distributing = FALSE;
 }

Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c      Sun Oct  5 02:16:53 2014        (r272546)
+++ head/sys/net/if_lagg.c      Sun Oct  5 02:34:21 2014        (r272547)
@@ -569,15 +569,15 @@ lagg_clone_destroy(struct ifnet *ifp)
 static void
 lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr)
 {
-       struct ifnet *ifp = sc->sc_ifp;
+       struct lagg_port lp;
 
-       if (memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0)
-               return;
+       LAGG_WLOCK_ASSERT(sc);
+
+       bzero(&lp, sizeof(lp));
+       lp.lp_ifp = sc->sc_ifp;
+       lp.lp_softc = sc;
 
-       bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
-       /* Let the protocol know the MAC has changed */
-       lagg_proto_lladdr(sc);
-       EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+       lagg_port_lladdr(&lp, lladdr);
 }
 
 static void
@@ -648,6 +648,7 @@ lagg_port_lladdr(struct lagg_port *lp, u
 
        /* Update the lladdr even if pending, it may have changed */
        llq->llq_ifp = ifp;
+       llq->llq_primary = (sc->sc_primary->lp_ifp == ifp) ? 1 : 0;
        bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN);
 
        if (!pending)
@@ -680,14 +681,35 @@ lagg_port_setlladdr(void *arg, int pendi
        for (llq = head; llq != NULL; llq = head) {
                ifp = llq->llq_ifp;
 
-               /* Set the link layer address */
                CURVNET_SET(ifp->if_vnet);
-               error = if_setlladdr(ifp, llq->llq_lladdr, ETHER_ADDR_LEN);
+               if (llq->llq_primary == 0) {
+                       /*
+                        * Set the link layer address on the laggport interface.
+                        * if_setlladdr() triggers gratuitous ARPs for INET.
+                        */
+                       error = if_setlladdr(ifp, llq->llq_lladdr,
+                           ETHER_ADDR_LEN);
+                       if (error)
+                               printf("%s: setlladdr failed on %s\n", __func__,
+                                   ifp->if_xname);
+               } else {
+                       /*
+                        * Set the link layer address on the lagg interface.
+                        * lagg_proto_lladdr() notifies the MAC change to
+                        * the aggregation protocol.  iflladdr_event handler
+                        * may trigger gratuitous ARPs for INET.
+                        */
+                       if (memcmp(llq->llq_lladdr, IF_LLADDR(ifp),
+                           ETHER_ADDR_LEN) != 0) {
+                               bcopy(llq->llq_lladdr, IF_LLADDR(ifp),
+                                   ETHER_ADDR_LEN);
+                               LAGG_WLOCK(sc);
+                               lagg_proto_lladdr(sc);
+                               LAGG_WUNLOCK(sc);
+                               EVENTHANDLER_INVOKE(iflladdr_event, ifp);
+                       }
+               }
                CURVNET_RESTORE();
-               if (error)
-                       printf("%s: setlladdr failed on %s\n", __func__,
-                           ifp->if_xname);
-
                head = SLIST_NEXT(llq, llq_entries);
                free(llq, M_DEVBUF);
        }
@@ -1639,7 +1661,7 @@ lagg_input(struct ifnet *ifp, struct mbu
 
        ETHER_BPF_MTAP(scifp, m);
 
-       m = lagg_proto_input(sc, lp, m);
+       m = (lp->lp_detaching == 0) ? lagg_proto_input(sc, lp, m) : NULL;
 
        if (m != NULL) {
                if (scifp->if_flags & IFF_MONITOR) {

Modified: head/sys/net/if_lagg.h
==============================================================================
--- head/sys/net/if_lagg.h      Sun Oct  5 02:16:53 2014        (r272546)
+++ head/sys/net/if_lagg.h      Sun Oct  5 02:34:21 2014        (r272547)
@@ -159,6 +159,9 @@ struct lagg_reqopts {
 #define        SIOCGLAGGOPTS           _IOWR('i', 152, struct lagg_reqopts)
 #define        SIOCSLAGGOPTS            _IOW('i', 153, struct lagg_reqopts)
 
+#define        LAGG_OPT_BITS           "\020\001USE_FLOWID\005LACP_STRICT" \
+                               "\006LACP_TXTEST\007LACP_RXTEST"
+
 #ifdef _KERNEL
 
 /*
@@ -203,6 +206,7 @@ struct lagg_mc {
 struct lagg_llq {
        struct ifnet            *llq_ifp;
        uint8_t                 llq_lladdr[ETHER_ADDR_LEN];
+       uint8_t                 llq_primary;
        SLIST_ENTRY(lagg_llq)   llq_entries;
 };
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to