Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Dec 2018 23:22:37 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r342206 - stable/11/sys/net
Message-ID:  <201812182322.wBINMbPn033919@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Dec 18 23:22:37 2018
New Revision: 342206
URL: https://svnweb.freebsd.org/changeset/base/342206

Log:
  MFC r339909: Allow changing lagg(4) MTU.
  
  Previously, changing the MTU would require destroying the lagg and
  creating a new one. Now it is allowed to change the MTU of
  the lagg interface and the MTU of the ports will be set to match.
  
  If any port cannot set the new MTU, all ports are reverted to the original
  MTU of the lagg. Additionally, when adding ports, the MTU of a port will be
  automatically set to the MTU of the lagg. As always, the MTU of the lagg is
  initially determined by the MTU of the first port added. If adding an
  interface as a port for some reason fails, that interface is reverted to its
  original MTU.
  
  Submitted by: Ryan Moeller <ryan@freqlabs.com>
  Relnotes: Yes
  Sponsored by: iXsystems Inc.

Modified:
  stable/11/sys/net/if_lagg.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/net/if_lagg.c
==============================================================================
--- stable/11/sys/net/if_lagg.c	Tue Dec 18 22:56:24 2018	(r342205)
+++ stable/11/sys/net/if_lagg.c	Tue Dec 18 23:22:37 2018	(r342206)
@@ -617,11 +617,18 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *
 {
 	struct lagg_softc *sc_ptr;
 	struct lagg_port *lp, *tlp;
-	int error, i;
+	struct ifreq ifr;
+	int error, i, oldmtu;
 	uint64_t *pval;
 
 	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 */
 	if (sc->sc_count >= LAGG_MAX_PORTS)
 		return (ENOSPC);
@@ -640,12 +647,25 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *
 		return (EPROTONOSUPPORT);
 
 	/* Allow the first Ethernet member to define the MTU */
-	if (SLIST_EMPTY(&sc->sc_ports))
+	oldmtu = -1;
+	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);
+	} else if (sc->sc_ifp->if_mtu != ifp->if_mtu) {
+		if (ifp->if_ioctl == NULL) {
+			if_printf(sc->sc_ifp, "cannot change MTU for %s\n",
+			    ifp->if_xname);
+			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);
@@ -657,6 +677,9 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *
 		if (ifp == sc_ptr->sc_ifp) {
 			LAGG_LIST_UNLOCK();
 			free(lp, M_DEVBUF);
+			if (oldmtu != -1)
+				(*ifp->if_ioctl)(ifp, SIOCSIFMTU,
+				    (caddr_t)&ifr);
 			return (EINVAL);
 			/* XXX disable stacking for the moment, its untested */
 #ifdef LAGG_PORT_STACKING
@@ -665,6 +688,9 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *
 			    LAGG_MAX_STACKING) {
 				LAGG_LIST_UNLOCK();
 				free(lp, M_DEVBUF);
+				if (oldmtu != -1)
+					(*ifp->if_ioctl)(ifp, SIOCSIFMTU,
+					    (caddr_t)&ifr);
 				return (E2BIG);
 			}
 #endif
@@ -730,6 +756,8 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *
 	if ((error = lagg_proto_addport(sc, lp)) != 0) {
 		/* Remove the port, without calling pr_delport. */
 		lagg_port_destroy(lp, 0);
+		if (oldmtu != -1)
+			(*ifp->if_ioctl)(ifp, SIOCSIFMTU, (caddr_t)&ifr);
 		LAGG_UNLOCK_ASSERT(sc);
 		return (error);
 	}
@@ -1444,8 +1472,31 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data
 		break;
 
 	case SIOCSIFMTU:
-		/* Do not allow the MTU to be directly changed */
-		error = EINVAL;
+		LAGG_XLOCK(sc);
+		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;
+			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;
+			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;
 
 	default:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812182322.wBINMbPn033919>