summaryrefslogtreecommitdiffstats
path: root/sys/net/if_lagg.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2007-07-30 20:17:22 +0000
committerthompsa <thompsa@FreeBSD.org>2007-07-30 20:17:22 +0000
commit35be05311259522727bb84611255f4c49d569cda (patch)
treeae91130db18901f01b04283579a31b2650bca3ff /sys/net/if_lagg.c
parentdc9f653549ec5c7bb7102c3c72f780250d3f72d0 (diff)
downloadFreeBSD-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/if_lagg.c')
-rw-r--r--sys/net/if_lagg.c72
1 files changed, 57 insertions, 15 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;
OpenPOWER on IntegriCloud