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@elam.kais.kyoto-u.ac.jp> Reported by: Shirkdog <mshirk@daemon-security.com> Reviewed by: galladin Approved by: re (gjb) Sponsored by: Limelight Networks Differential Revision: https://reviews.freebsd.org/D17158
This commit is contained in:
parent
c56fc36e4b
commit
bd447b7e63
@ -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 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));
|
||||
|
||||
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);
|
||||
/*
|
||||
* 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:
|
||||
|
Loading…
Reference in New Issue
Block a user