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