summaryrefslogtreecommitdiffstats
path: root/sys/net/if_vlan.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-05-16 00:33:46 +0000
committermav <mav@FreeBSD.org>2017-05-16 00:33:46 +0000
commit7c19a4dff2b7a28c75aee39c669426dce3a37eee (patch)
tree74aa606a39962a1f458f2f3629f3e9b91cadd83e /sys/net/if_vlan.c
parent1943c4762afacb8897b851c84fea47b557e8de9f (diff)
downloadFreeBSD-src-7c19a4dff2b7a28c75aee39c669426dce3a37eee.zip
FreeBSD-src-7c19a4dff2b7a28c75aee39c669426dce3a37eee.tar.gz
MFC r317547: Allow some control over enabled capabilities for if_vlan.
It improves interoperability with if_bridge, which may need to disable some capabilities not supported by other members. IMHO there is still open question about LRO capability, which may need to be disabled on physical interface.
Diffstat (limited to 'sys/net/if_vlan.c')
-rw-r--r--sys/net/if_vlan.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 223b823..1d3e827 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -112,6 +112,7 @@ struct ifvlan {
#define PARENT(ifv) ((ifv)->ifv_trunk->parent)
void *ifv_cookie;
int ifv_pflags; /* special flags we have set on parent */
+ int ifv_capenable;
struct ifv_linkmib {
int ifvm_encaplen; /* encapsulation length */
int ifvm_mtufudge; /* MTU fudged by this much */
@@ -1286,6 +1287,7 @@ exists:
ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
ifv->ifv_mintu = ETHERMIN;
ifv->ifv_pflags = 0;
+ ifv->ifv_capenable = -1;
/*
* If the parent supports the VLAN_MTU capability,
@@ -1537,9 +1539,14 @@ vlan_capabilities(struct ifvlan *ifv)
struct ifnet *p = PARENT(ifv);
struct ifnet *ifp = ifv->ifv_ifp;
struct ifnet_hw_tsomax hw_tsomax;
+ int cap = 0, ena = 0, mena;
+ u_long hwa = 0;
TRUNK_LOCK_ASSERT(TRUNK(ifv));
+ /* Mask parent interface enabled capabilities disabled by user. */
+ mena = p->if_capenable & ifv->ifv_capenable;
+
/*
* If the parent interface can do checksum offloading
* on VLANs, then propagate its hardware-assisted
@@ -1547,20 +1554,18 @@ vlan_capabilities(struct ifvlan *ifv)
* offloading requires hardware VLAN tagging.
*/
if (p->if_capabilities & IFCAP_VLAN_HWCSUM)
- ifp->if_capabilities =
- p->if_capabilities & (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
-
+ cap |= p->if_capabilities & (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
if (p->if_capenable & IFCAP_VLAN_HWCSUM &&
p->if_capenable & IFCAP_VLAN_HWTAGGING) {
- ifp->if_capenable =
- p->if_capenable & (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
- ifp->if_hwassist = p->if_hwassist & (CSUM_IP | CSUM_TCP |
- CSUM_UDP | CSUM_SCTP | CSUM_TCP_IPV6 | CSUM_UDP_IPV6 |
- CSUM_SCTP_IPV6);
- } else {
- ifp->if_capenable = 0;
- ifp->if_hwassist = 0;
+ ena |= mena & (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6);
+ if (ena & IFCAP_TXCSUM)
+ hwa |= p->if_hwassist & (CSUM_IP | CSUM_TCP |
+ CSUM_UDP | CSUM_SCTP);
+ if (ena & IFCAP_TXCSUM_IPV6)
+ hwa |= p->if_hwassist & (CSUM_TCP_IPV6 |
+ CSUM_UDP_IPV6 | CSUM_SCTP_IPV6);
}
+
/*
* If the parent interface can do TSO on VLANs then
* propagate the hardware-assisted flag. TSO on VLANs
@@ -1570,13 +1575,11 @@ vlan_capabilities(struct ifvlan *ifv)
if_hw_tsomax_common(p, &hw_tsomax);
if_hw_tsomax_update(ifp, &hw_tsomax);
if (p->if_capabilities & IFCAP_VLAN_HWTSO)
- ifp->if_capabilities |= p->if_capabilities & IFCAP_TSO;
+ cap |= p->if_capabilities & IFCAP_TSO;
if (p->if_capenable & IFCAP_VLAN_HWTSO) {
- ifp->if_capenable |= p->if_capenable & IFCAP_TSO;
- ifp->if_hwassist |= p->if_hwassist & CSUM_TSO;
- } else {
- ifp->if_capenable &= ~(p->if_capenable & IFCAP_TSO);
- ifp->if_hwassist &= ~(p->if_hwassist & CSUM_TSO);
+ ena |= mena & IFCAP_TSO;
+ if (ena & IFCAP_TSO)
+ hwa |= p->if_hwassist & CSUM_TSO;
}
/*
@@ -1589,11 +1592,22 @@ vlan_capabilities(struct ifvlan *ifv)
*/
#define IFCAP_VLAN_TOE IFCAP_TOE
if (p->if_capabilities & IFCAP_VLAN_TOE)
- ifp->if_capabilities |= p->if_capabilities & IFCAP_TOE;
+ cap |= p->if_capabilities & IFCAP_TOE;
if (p->if_capenable & IFCAP_VLAN_TOE) {
TOEDEV(ifp) = TOEDEV(p);
- ifp->if_capenable |= p->if_capenable & IFCAP_TOE;
+ ena |= mena & IFCAP_TOE;
}
+
+ /*
+ * If the parent interface supports dynamic link state, so does the
+ * VLAN interface.
+ */
+ cap |= (p->if_capabilities & IFCAP_LINKSTATE);
+ ena |= (mena & IFCAP_LINKSTATE);
+
+ ifp->if_capabilities = cap;
+ ifp->if_capenable = ena;
+ ifp->if_hwassist = hwa;
}
static void
@@ -1797,6 +1811,18 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
vlan_tag_recalculate(ifv);
break;
+ case SIOCSIFCAP:
+ VLAN_LOCK();
+ ifv->ifv_capenable = ifr->ifr_reqcap;
+ trunk = TRUNK(ifv);
+ if (trunk != NULL) {
+ TRUNK_LOCK(trunk);
+ vlan_capabilities(ifv);
+ TRUNK_UNLOCK(trunk);
+ }
+ VLAN_UNLOCK();
+ break;
+
default:
error = EINVAL;
break;
OpenPOWER on IntegriCloud