Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/if_lagg.c
Show First 20 Lines • Show All 627 Lines • ▼ Show 20 Lines | lagg_capabilities(struct lagg_softc *sc) | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) | lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) | ||||
{ | { | ||||
struct lagg_softc *sc_ptr; | struct lagg_softc *sc_ptr; | ||||
struct lagg_port *lp, *tlp; | struct lagg_port *lp, *tlp; | ||||
int error, i; | struct ifreq ifr; | ||||
int error, i, oldmtu; | |||||
uint64_t *pval; | uint64_t *pval; | ||||
LAGG_XLOCK_ASSERT(sc); | LAGG_XLOCK_ASSERT(sc); | ||||
if (sc->sc_ifp == ifp) { | |||||
if_printf(sc->sc_ifp, | |||||
"cannot add a lagg to itself as a port\n"); | |||||
return (EINVAL); | |||||
} | |||||
/* Limit the maximal number of lagg ports */ | /* Limit the maximal number of lagg ports */ | ||||
if (sc->sc_count >= LAGG_MAX_PORTS) | if (sc->sc_count >= LAGG_MAX_PORTS) | ||||
return (ENOSPC); | return (ENOSPC); | ||||
/* Check if port has already been associated to a lagg */ | /* Check if port has already been associated to a lagg */ | ||||
if (ifp->if_lagg != NULL) { | if (ifp->if_lagg != NULL) { | ||||
/* Port is already in the current lagg? */ | /* Port is already in the current lagg? */ | ||||
lp = (struct lagg_port *)ifp->if_lagg; | lp = (struct lagg_port *)ifp->if_lagg; | ||||
if (lp->lp_softc == sc) | if (lp->lp_softc == sc) | ||||
return (EEXIST); | return (EEXIST); | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
/* XXX Disallow non-ethernet interfaces (this should be any of 802) */ | /* XXX Disallow non-ethernet interfaces (this should be any of 802) */ | ||||
if (ifp->if_type != IFT_ETHER && ifp->if_type != IFT_L2VLAN) | if (ifp->if_type != IFT_ETHER && ifp->if_type != IFT_L2VLAN) | ||||
return (EPROTONOSUPPORT); | return (EPROTONOSUPPORT); | ||||
/* Allow the first Ethernet member to define the MTU */ | /* Allow the first Ethernet member to define the MTU */ | ||||
if (CK_SLIST_EMPTY(&sc->sc_ports)) | oldmtu = -1; | ||||
if (CK_SLIST_EMPTY(&sc->sc_ports)) { | |||||
sc->sc_ifp->if_mtu = ifp->if_mtu; | sc->sc_ifp->if_mtu = ifp->if_mtu; | ||||
else if (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", | if (ifp->if_ioctl == NULL) { | ||||
if_printf(sc->sc_ifp, "cannot change MTU for %s\n", | |||||
ifp->if_xname); | ifp->if_xname); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
oldmtu = ifp->if_mtu; | |||||
strlcpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); | |||||
ifr.ifr_mtu = sc->sc_ifp->if_mtu; | |||||
error = (*ifp->if_ioctl)(ifp, SIOCSIFMTU, (caddr_t)&ifr); | |||||
if (error != 0) { | |||||
if_printf(sc->sc_ifp, "invalid MTU for %s\n", | |||||
ifp->if_xname); | |||||
return (error); | |||||
} | |||||
ifr.ifr_mtu = oldmtu; | |||||
} | |||||
lp = malloc(sizeof(struct lagg_port), M_DEVBUF, M_WAITOK|M_ZERO); | lp = malloc(sizeof(struct lagg_port), M_DEVBUF, M_WAITOK|M_ZERO); | ||||
lp->lp_softc = sc; | lp->lp_softc = sc; | ||||
/* Check if port is a stacked lagg */ | /* Check if port is a stacked lagg */ | ||||
LAGG_LIST_LOCK(); | LAGG_LIST_LOCK(); | ||||
SLIST_FOREACH(sc_ptr, &V_lagg_list, sc_entries) { | SLIST_FOREACH(sc_ptr, &V_lagg_list, sc_entries) { | ||||
if (ifp == sc_ptr->sc_ifp) { | if (ifp == sc_ptr->sc_ifp) { | ||||
LAGG_LIST_UNLOCK(); | LAGG_LIST_UNLOCK(); | ||||
free(lp, M_DEVBUF); | free(lp, M_DEVBUF); | ||||
if (oldmtu != -1) | |||||
(*ifp->if_ioctl)(ifp, SIOCSIFMTU, | |||||
(caddr_t)&ifr); | |||||
return (EINVAL); | return (EINVAL); | ||||
/* XXX disable stacking for the moment, its untested */ | /* XXX disable stacking for the moment, its untested */ | ||||
#ifdef LAGG_PORT_STACKING | #ifdef LAGG_PORT_STACKING | ||||
lp->lp_flags |= LAGG_PORT_STACK; | lp->lp_flags |= LAGG_PORT_STACK; | ||||
if (lagg_port_checkstacking(sc_ptr) >= | if (lagg_port_checkstacking(sc_ptr) >= | ||||
LAGG_MAX_STACKING) { | LAGG_MAX_STACKING) { | ||||
LAGG_LIST_UNLOCK(); | LAGG_LIST_UNLOCK(); | ||||
free(lp, M_DEVBUF); | free(lp, M_DEVBUF); | ||||
if (oldmtu != -1) | |||||
(*ifp->if_ioctl)(ifp, SIOCSIFMTU, | |||||
(caddr_t)&ifr); | |||||
return (E2BIG); | return (E2BIG); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
LAGG_LIST_UNLOCK(); | LAGG_LIST_UNLOCK(); | ||||
if_ref(ifp); | if_ref(ifp); | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | #endif | ||||
sc->sc_count++; | sc->sc_count++; | ||||
lagg_setmulti(lp); | lagg_setmulti(lp); | ||||
if ((error = lagg_proto_addport(sc, lp)) != 0) { | if ((error = lagg_proto_addport(sc, lp)) != 0) { | ||||
/* Remove the port, without calling pr_delport. */ | /* Remove the port, without calling pr_delport. */ | ||||
lagg_port_destroy(lp, 0); | lagg_port_destroy(lp, 0); | ||||
if (oldmtu != -1) | |||||
(*ifp->if_ioctl)(ifp, SIOCSIFMTU, (caddr_t)&ifr); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* Update lagg capabilities */ | /* Update lagg capabilities */ | ||||
lagg_capabilities(sc); | lagg_capabilities(sc); | ||||
lagg_linkstate(sc); | lagg_linkstate(sc); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 702 Lines • ▼ Show 20 Lines | case SIOCSIFCAP: | ||||
} | } | ||||
lagg_capabilities(sc); | lagg_capabilities(sc); | ||||
LAGG_XUNLOCK(sc); | LAGG_XUNLOCK(sc); | ||||
VLAN_CAPABILITIES(ifp); | VLAN_CAPABILITIES(ifp); | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
case SIOCSIFMTU: | case SIOCSIFMTU: | ||||
/* Do not allow the MTU to be directly changed */ | LAGG_XLOCK(sc); | ||||
CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { | |||||
if (lp->lp_ioctl != NULL) | |||||
error = (*lp->lp_ioctl)(lp->lp_ifp, cmd, data); | |||||
else | |||||
error = EINVAL; | error = EINVAL; | ||||
if (error != 0) { | |||||
if_printf(ifp, | |||||
"failed to change MTU to %d on port %s, " | |||||
"reverting all ports to original MTU (%d)\n", | |||||
ifr->ifr_mtu, lp->lp_ifp->if_xname, ifp->if_mtu); | |||||
break; | |||||
} | |||||
} | |||||
if (error == 0) { | |||||
ifp->if_mtu = ifr->ifr_mtu; | |||||
} else { | |||||
/* set every port back to the original MTU */ | |||||
ifr->ifr_mtu = ifp->if_mtu; | |||||
CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { | |||||
if (lp->lp_ioctl != NULL) | |||||
(*lp->lp_ioctl)(lp->lp_ifp, cmd, data); | |||||
} | |||||
} | |||||
LAGG_XUNLOCK(sc); | |||||
break; | break; | ||||
default: | default: | ||||
error = ether_ioctl(ifp, cmd, data); | error = ether_ioctl(ifp, cmd, data); | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 724 Lines • Show Last 20 Lines |