Date: Fri, 17 Oct 2014 09:08:45 +0000 (UTC) From: Hiroki Sato <hrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r273210 - head/sys/net Message-ID: <201410170908.s9H98j0c019310@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201410170908.s9H98j0c019310>