svn commit: r338838 - head/sys/net

Stephen Hurd shurd at FreeBSD.org
Thu Sep 20 19:35:36 UTC 2018


Author: shurd
Date: Thu Sep 20 19:35:35 2018
New Revision: 338838
URL: https://svnweb.freebsd.org/changeset/base/338838

Log:
  Fix capabilities handling for iflib drivers
  
  Various capabilities were not being handled correctly in the
  SIOCSIFCAP handler. Specifically:
  
  IFCAP_RXCSUM and IFCAP_RXCSUM_IPV6 could be set even if not supported
  
  It was impossible to disable IFCAP_RXCSUM and/or IFCAP_RXCSUM_IPV6 via
  ifconfig since it does ioctl() per command-line flag rather than combine
  them into a single call.
  
  IFCAP_VLAN_HWCSUM could not be modified via the ioctl()
  
  Setting any combination of the three IFCAP_WOL flags would set only
  IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC. For example, setting only
  IFCAP_WOL_UCAST would result in both IFCAP_WOL_MCAST and IFCAP_WOL_MAGIC
  being enabled, but IFCAP_WOL_UCAST would not be enabled.
  
  Because if_vlancap() was called before if_togglecapenable(), vlan flags
  were sometimes not applied correctly.
  
  Interfaces were being unnecessarily stopped and restarted for WoL
  
  PR:		231151
  Submitted by:	Kaho Toshikazu <kaho at elam.kais.kyoto-u.ac.jp>
  Reported by:	Shirkdog <mshirk at daemon-security.com>
  Reviewed by:	galladin
  Approved by:	re (gjb)
  Sponsored by:	Limelight Networks
  Differential Revision:	https://reviews.freebsd.org/D17158

Modified:
  head/sys/net/iflib.c

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c	Thu Sep 20 18:30:17 2018	(r338837)
+++ head/sys/net/iflib.c	Thu Sep 20 19:35:35 2018	(r338838)
@@ -4100,9 +4100,10 @@ iflib_if_qflush(if_t ifp)
 }
 
 
-#define IFCAP_FLAGS (IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM_IPV6 | IFCAP_HWCSUM | IFCAP_LRO | \
-		     IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTAGGING | IFCAP_HWSTATS | \
-		     IFCAP_VLAN_MTU | IFCAP_VLAN_HWFILTER | IFCAP_VLAN_HWTSO)
+#define IFCAP_FLAGS (IFCAP_HWCSUM_IPV6 | IFCAP_HWCSUM | IFCAP_LRO | \
+		     IFCAP_TSO | IFCAP_VLAN_HWTAGGING | IFCAP_HWSTATS | \
+		     IFCAP_VLAN_MTU | IFCAP_VLAN_HWFILTER | \
+		     IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM)
 
 static int
 iflib_if_ioctl(if_t ifp, u_long command, caddr_t data)
@@ -4223,39 +4224,51 @@ iflib_if_ioctl(if_t ifp, u_long command, caddr_t data)
 	}
 	case SIOCSIFCAP:
 	{
-		int mask, setmask;
+		int mask, setmask, oldmask;
 
-		mask = ifr->ifr_reqcap ^ if_getcapenable(ifp);
+		oldmask = if_getcapenable(ifp);
+		mask = ifr->ifr_reqcap ^ oldmask;
+		mask &= ctx->ifc_softc_ctx.isc_capabilities;
 		setmask = 0;
 #ifdef TCP_OFFLOAD
 		setmask |= mask & (IFCAP_TOE4|IFCAP_TOE6);
 #endif
 		setmask |= (mask & IFCAP_FLAGS);
+		setmask |= (mask & IFCAP_WOL);
 
-		if (setmask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6))
-			setmask |= (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6);
-		if ((mask & IFCAP_WOL) &&
-		    (if_getcapabilities(ifp) & IFCAP_WOL) != 0)
-			setmask |= (mask & (IFCAP_WOL_MCAST|IFCAP_WOL_MAGIC));
-		if_vlancap(ifp);
 		/*
+		 * If we're disabling any RX csum, disable all the ones
+		 * the driver supports.  This assumes all supported are
+		 * enabled.
+		 * 
+		 * Otherwise, if they've changed, enable all of them.
+		 */
+		if ((setmask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) <
+		    (oldmask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)))
+			setmask &= ~(IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6);
+		else if ((setmask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) !=
+		    (oldmask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)))
+			setmask |= (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6));
+
+		/*
 		 * want to ensure that traffic has stopped before we change any of the flags
 		 */
 		if (setmask) {
 			CTX_LOCK(ctx);
 			bits = if_getdrvflags(ifp);
-			if (bits & IFF_DRV_RUNNING)
+			if (bits & IFF_DRV_RUNNING && setmask & ~IFCAP_WOL)
 				iflib_stop(ctx);
 			STATE_LOCK(ctx);
 			if_togglecapenable(ifp, setmask);
 			STATE_UNLOCK(ctx);
-			if (bits & IFF_DRV_RUNNING)
+			if (bits & IFF_DRV_RUNNING && setmask & ~IFCAP_WOL)
 				iflib_init_locked(ctx);
 			STATE_LOCK(ctx);
 			if_setdrvflags(ifp, bits);
 			STATE_UNLOCK(ctx);
 			CTX_UNLOCK(ctx);
 		}
+		if_vlancap(ifp);
 		break;
 	}
 	case SIOCGPRIVATE_0:


More information about the svn-src-head mailing list