Author: hrs
Date: Fri Oct 17 09:08:44 2014
New Revision: 273210
URL: https://svnweb.freebsd.org/changeset/base/273210

Log:
  - Fix lladdr configuration which could prevent LACP mode from working.
  - Fix LORs when a laggport interface has an IPv6 LLA.
  
  PR:   194321

Modified:
  head/sys/net/if_lagg.c

Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c      Fri Oct 17 07:58:51 2014        (r273209)
+++ head/sys/net/if_lagg.c      Fri Oct 17 09:08:44 2014        (r273210)
@@ -569,9 +569,22 @@ 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);
+       /*
+        * Set the link layer address on the lagg interface.
+        * lagg_proto_lladdr() notifies the MAC change to
+        * the aggregation protocol.  iflladdr_event handler which
+        * may trigger gratuitous ARPs for INET will be handled in
+        * a taskqueue.
+        */
+       bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
+       lagg_proto_lladdr(sc);
 
        bzero(&lp, sizeof(lp));
        lp.lp_ifp = sc->sc_ifp;
@@ -625,11 +638,13 @@ lagg_port_lladdr(struct lagg_port *lp, u
        struct ifnet *ifp = lp->lp_ifp;
        struct lagg_llq *llq;
        int pending = 0;
+       int primary;
 
        LAGG_WLOCK_ASSERT(sc);
 
-       if (lp->lp_detaching ||
-           memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0)
+       primary = (sc->sc_primary->lp_ifp == ifp) ? 1 : 0;
+       if (primary == 0 && (lp->lp_detaching ||
+           memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0))
                return;
 
        /* Check to make sure its not already queued to be changed */
@@ -648,7 +663,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;
+       llq->llq_primary = primary;
        bcopy(lladdr, llq->llq_lladdr, ETHER_ADDR_LEN);
 
        if (!pending)
@@ -692,23 +707,8 @@ lagg_port_setlladdr(void *arg, int pendi
                        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);
-                       }
-               }
+               } else
+                       EVENTHANDLER_INVOKE(iflladdr_event, ifp);
                CURVNET_RESTORE();
                head = SLIST_NEXT(llq, llq_entries);
                free(llq, M_DEVBUF);
@@ -742,34 +742,6 @@ lagg_port_create(struct lagg_softc *sc, 
        if (ifp->if_type != IFT_ETHER)
                return (EPROTONOSUPPORT);
 
-#ifdef INET6
-       /*
-        * The member interface should not have inet6 address because
-        * two interfaces with a valid link-local scope zone must not be
-        * merged in any form.  This restriction is needed to
-        * prevent violation of link-local scope zone.  Attempts to
-        * add a member interface which has inet6 addresses triggers
-        * removal of all inet6 addresses on the member interface.
-        */
-       SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
-               if (in6ifa_llaonifp(lp->lp_ifp)) {
-                       in6_ifdetach(lp->lp_ifp);
-                       if_printf(sc->sc_ifp,
-                           "IPv6 addresses on %s have been removed "
-                           "before adding it as a member to prevent "
-                           "IPv6 address scope violation.\n",
-                           lp->lp_ifp->if_xname);
-               }
-       }
-       if (in6ifa_llaonifp(ifp)) {
-               in6_ifdetach(ifp);
-               if_printf(sc->sc_ifp,
-                   "IPv6 addresses on %s have been removed "
-                   "before adding it as a member to prevent "
-                   "IPv6 address scope violation.\n",
-                   ifp->if_xname);
-       }
-#endif
        /* Allow the first Ethernet member to define the MTU */
        if (SLIST_EMPTY(&sc->sc_ports))
                sc->sc_ifp->if_mtu = ifp->if_mtu;
@@ -1414,6 +1386,26 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd
                        error = EINVAL;
                        break;
                }
+#ifdef INET6
+               /*
+                * A laggport interface should not have inet6 address
+                * because two interfaces with a valid link-local
+                * scope zone must not be merged in any form.  This
+                * restriction is needed to prevent violation of
+                * link-local scope zone.  Attempts to add a laggport
+                * interface which has inet6 addresses triggers
+                * removal of all inet6 addresses on the member
+                * interface.
+                */
+               if (in6ifa_llaonifp(tpif)) {
+                       in6_ifdetach(tpif);
+                               if_printf(sc->sc_ifp,
+                                   "IPv6 addresses on %s have been removed "
+                                   "before adding it as a member to prevent "
+                                   "IPv6 address scope violation.\n",
+                                   tpif->if_xname);
+               }
+#endif
                LAGG_WLOCK(sc);
                error = lagg_port_create(sc, tpif);
                LAGG_WUNLOCK(sc);
_______________________________________________
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