diff options
author | thompsa <thompsa@FreeBSD.org> | 2007-07-30 20:17:22 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2007-07-30 20:17:22 +0000 |
commit | 35be05311259522727bb84611255f4c49d569cda (patch) | |
tree | ae91130db18901f01b04283579a31b2650bca3ff /sys/net | |
parent | dc9f653549ec5c7bb7102c3c72f780250d3f72d0 (diff) | |
download | FreeBSD-src-35be05311259522727bb84611255f4c49d569cda.zip FreeBSD-src-35be05311259522727bb84611255f4c49d569cda.tar.gz |
- Propagate the largest set of interface capabilities supported by all lagg
ports to the lagg interface.
- Use the MTU from the first interface as the lagg MTU, all extra interfaces
must be the same.
This fixes using a lagg interface for a vlan or enabling jumbo frames, etc.
Approved by: re (kensmith)
MFC After: 3 days
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_lagg.c | 72 | ||||
-rw-r--r-- | sys/net/if_lagg.h | 1 |
2 files changed, 57 insertions, 16 deletions
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 2e489eb..22462b3 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -82,7 +82,7 @@ eventhandler_tag lagg_detach_cookie = NULL; static int lagg_clone_create(struct if_clone *, int, caddr_t); static void lagg_clone_destroy(struct ifnet *); static void lagg_lladdr(struct lagg_softc *, uint8_t *); -static int lagg_capabilities(struct lagg_softc *); +static void lagg_capabilities(struct lagg_softc *); static void lagg_port_lladdr(struct lagg_port *, uint8_t *); static void lagg_port_setlladdr(void *, int); static int lagg_port_create(struct lagg_softc *, struct ifnet *); @@ -305,27 +305,32 @@ lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr) (*sc->sc_lladdr)(sc); } -static int +static void lagg_capabilities(struct lagg_softc *sc) { struct lagg_port *lp; - int cap = ~0, priv; + int cap = ~0, ena = ~0; LAGG_WLOCK_ASSERT(sc); - /* Preserve private capabilities */ - priv = sc->sc_capabilities & IFCAP_LAGG_MASK; - /* Get capabilities from the lagg ports */ - SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) - cap &= lp->lp_capabilities; - - if (sc->sc_ifflags & IFF_DEBUG) { - printf("%s: capabilities 0x%08x\n", - sc->sc_ifname, cap == ~0 ? priv : (cap | priv)); + SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { + cap &= lp->lp_ifp->if_capabilities; + ena &= lp->lp_ifp->if_capenable; } + cap = (cap == ~0 ? 0 : cap); + ena = (ena == ~0 ? 0 : ena); + + if (sc->sc_ifp->if_capabilities != cap || + sc->sc_ifp->if_capenable != ena) { + sc->sc_ifp->if_capabilities = cap; + sc->sc_ifp->if_capenable = ena; + getmicrotime(&sc->sc_ifp->if_lastchange); - return (cap == ~0 ? priv : (cap | priv)); + if (sc->sc_ifflags & IFF_DEBUG) + if_printf(sc->sc_ifp, + "capabilities 0x%08x enabled 0x%08x\n", cap, ena); + } } static void @@ -426,6 +431,15 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) if (ifp->if_type != IFT_ETHER) return (EPROTONOSUPPORT); + /* Allow the first Ethernet member to define the MTU */ + if (SLIST_EMPTY(&sc->sc_ports)) + sc->sc_ifp->if_mtu = ifp->if_mtu; + else if (sc->sc_ifp->if_mtu != ifp->if_mtu) { + if_printf(sc->sc_ifp, "invalid MTU for %s\n", + ifp->if_xname); + return (EINVAL); + } + if ((lp = malloc(sizeof(struct lagg_port), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) return (ENOMEM); @@ -478,7 +492,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) sc->sc_count++; /* Update lagg capabilities */ - sc->sc_capabilities = lagg_capabilities(sc); + lagg_capabilities(sc); /* Add multicast addresses and interface flags to this port */ lagg_ether_cmdmulti(lp, 1); @@ -583,7 +597,7 @@ lagg_port_destroy(struct lagg_port *lp, int runpd) free(lp, M_DEVBUF); /* Update lagg capabilities */ - sc->sc_capabilities = lagg_capabilities(sc); + lagg_capabilities(sc); return (0); } @@ -619,6 +633,27 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) lagg_port2req(lp, rp); LAGG_RUNLOCK(sc); break; + + case SIOCSIFCAP: + if (lp->lp_ioctl == NULL) { + error = EINVAL; + break; + } + error = (*lp->lp_ioctl)(ifp, cmd, data); + if (error) + break; + + /* Update lagg interface capabilities */ + LAGG_WLOCK(sc); + lagg_capabilities(sc); + LAGG_WUNLOCK(sc); + break; + + case SIOCSIFMTU: + /* Do not allow the MTU to be changed once joined */ + error = EINVAL; + break; + default: goto fallback; } @@ -934,6 +969,13 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCGIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; + + case SIOCSIFCAP: + case SIOCSIFMTU: + /* Do not allow the MTU or caps to be directly changed */ + error = EINVAL; + break; + default: error = ether_ioctl(ifp, cmd, data); break; diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index 1c8072e..ed888e6 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -127,7 +127,6 @@ struct lagg_reqall { #define lp_ifname lp_ifp->if_xname /* interface name */ #define lp_link_state lp_ifp->if_link_state /* link state */ -#define lp_capabilities lp_ifp->if_capabilities /* capabilities */ #define LAGG_PORTACTIVE(_tp) ( \ ((_tp)->lp_link_state == LINK_STATE_UP) && \ |