summaryrefslogtreecommitdiffstats
path: root/sys/net/if_vlan.c
diff options
context:
space:
mode:
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