- 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
This commit is contained in:
thompsa 2007-07-30 20:17:22 +00:00
parent dc9f653549
commit 35be053112
3 changed files with 60 additions and 16 deletions

View File

@ -122,6 +122,9 @@ command or using the
.Va cloned_interfaces
variable in
.Xr rc.conf 5 .
.Pp
The MTU of the first interface to be added is used as the lagg MTU.
All additional interfaces are required to have exactly the same value.
.Sh EXAMPLES
Create a 802.3ad link aggregation using LACP with two
.Xr bge 4

View File

@ -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);
return (cap == ~0 ? priv : (cap | priv));
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);
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;

View File

@ -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) && \