git: 933c4f6e06c2 - main - iavf: Honor negotiated VLAN offload capabilities

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Tue, 03 Nov 2026 02:41:55 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=933c4f6e06c276548783247242b75814027159eb

commit 933c4f6e06c276548783247242b75814027159eb
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-11-02 00:40:25 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-11-03 02:41:46 +0000

    iavf: Honor negotiated VLAN offload capabilities
    
    The driver advertised VLAN offload unconditionally, even when the PF
    did not grant it, as observed with an E835 VF under Hyper-V.  This
    tells the stack to rely on hardware tag insertion and sends the PF
    unsupported VLAN filter requests.
    
    Advertise hardware VLAN tagging and filtering only when GET_VF_RESOURCES
    grants the legacy VLAN capability.  Do not allocate filter shadow entries
    or send ADD_VLAN/DEL_VLAN requests without that capability.  Retain VLAN
    MTU and checksum/TSO support for software-tagged packets.
    
    Keep advertised capabilities stable across resets, since existing VLAN
    interfaces may already rely on them.  If resource rediscovery removes
    previously advertised VLAN offload, leave the VF stopped and require
    reattachment rather than resume with a stale offload contract.  A newly
    granted capability is not exposed until reattach.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
---
 sys/dev/iavf/iavf_vc_common.c |  5 +++++
 sys/dev/iavf/if_iavf_iflib.c  | 20 +++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/sys/dev/iavf/iavf_vc_common.c b/sys/dev/iavf/iavf_vc_common.c
index a605ec0901bf..c67f660f9356 100644
--- a/sys/dev/iavf/iavf_vc_common.c
+++ b/sys/dev/iavf/iavf_vc_common.c
@@ -483,6 +483,11 @@ iavf_sync_vlans(struct iavf_sc *sc)
 	int error, first_error;
 
 	sx_assert(iflib_ctx_lock_get(sc->vsi.ctx), SA_XLOCKED);
+	/* Software VLANs need no PF filter configuration. */
+	if ((sc->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) == 0) {
+		atomic_store_rel_32(&sc->vlan_batch_pending, 0);
+		return (0);
+	}
 	if (iavf_test_state(&sc->state, IAVF_STATE_RESET_PENDING) ||
 	    iavf_test_state(&sc->state, IAVF_STATE_RESET_RECOVERY) ||
 	    iavf_test_state(&sc->state, IAVF_STATE_VC_POLLING) ||
diff --git a/sys/dev/iavf/if_iavf_iflib.c b/sys/dev/iavf/if_iavf_iflib.c
index 304347316a75..4fb0237d2d7c 100644
--- a/sys/dev/iavf/if_iavf_iflib.c
+++ b/sys/dev/iavf/if_iavf_iflib.c
@@ -414,7 +414,11 @@ iavf_if_attach_pre(if_ctx_t ctx)
 	if ((sc->vf_res->vf_cap_flags & (VIRTCHNL_VF_OFFLOAD_RSS_REG |
 	    VIRTCHNL_VF_OFFLOAD_RSS_PF)) == VIRTCHNL_VF_OFFLOAD_RSS_PF)
 		scctx->isc_rss_table_size = sc->vf_res->rss_lut_size;
-	scctx->isc_capabilities = scctx->isc_capenable = IAVF_CAPS;
+	scctx->isc_capabilities = IAVF_CAPS;
+	if ((sc->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) == 0)
+		scctx->isc_capabilities &=
+		    ~(IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWFILTER);
+	scctx->isc_capenable = scctx->isc_capabilities;
 	scctx->isc_tx_csum_flags = CSUM_OFFLOAD;
 
 	return (0);
@@ -1123,6 +1127,16 @@ iavf_reestablish_vc(struct iavf_sc *sc)
 	if (error != 0)
 		goto fail;
 
+	/* Do not keep advertising an offload that the PF no longer provides. */
+	if ((vsi->shared->isc_capabilities & IFCAP_VLAN_HWTAGGING) != 0 &&
+	    (sc->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) == 0) {
+		if (iavf_mbx_log_allowed(sc))
+			device_printf(sc->dev,
+			    "PF VLAN offload capabilities changed; reattach the VF\n");
+		error = ENOTSUP;
+		goto fail;
+	}
+
 	if (vsi->num_tx_queues > sc->vsi_res->num_queue_pairs ||
 	    vsi->num_rx_queues > sc->vsi_res->num_queue_pairs ||
 	    vsi->num_rx_queues + 1 > sc->vf_res->max_vectors) {
@@ -2027,6 +2041,8 @@ iavf_if_vlan_register(if_ctx_t ctx, u16 vtag)
 	struct iavf_sc *sc = iavf_sc_from_ctx(ctx);
 	struct iavf_vsi *vsi = &sc->vsi;
 
+	if ((vsi->shared->isc_capabilities & IFCAP_VLAN_HWFILTER) == 0)
+		return;
 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
 		return;
 
@@ -2054,6 +2070,8 @@ iavf_if_vlan_unregister(if_ctx_t ctx, u16 vtag)
 	struct iavf_vsi *vsi = &sc->vsi;
 	int i = 0;
 
+	if ((vsi->shared->isc_capabilities & IFCAP_VLAN_HWFILTER) == 0)
+		return;
 	if ((vtag == 0) || (vtag > 4095) || (vsi->num_vlans == 0))	/* Invalid */
 		return;