git: 3bdc281f5df0 - main - ice: Enforce VF MAC anti-spoof policy

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Thu, 17 Sep 2026 17:02:21 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=3bdc281f5df0003d745b4e911f5d583bf5938317

commit 3bdc281f5df0003d745b4e911f5d583bf5938317
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-19 03:28:59 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-17 17:01:41 +0000

    ice: Enforce VF MAC anti-spoof policy
    
    The SR-IOV schema enables MAC anti-spoofing by default, but the driver
    never programs the VSI security section.  A VF can therefore transmit
    with an arbitrary source address despite the configured policy.
    
    Program ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF when the VF VSI is
    created, and replay the policy when the VSI is rebuilt after a PF or
    device reset.  Fail VF creation or rebuild when firmware cannot install
    the security policy so an unprotected VF is never published as active.
    
    Validated on E810 hardware with host-attached and Linux passthrough
    VFs.  Traffic using the assigned source MAC passed while otherwise
    identical forged-source frames were dropped.  After a PF reset, assigned
    traffic resumed and zero of ten forged frames reached the peer.
    
    An injected MAC anti-spoof update failure left the VF inactive.
    Destroying and recreating the SR-IOV configuration restored the policy
    and traffic.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
    Differential Revision:  https://reviews.freebsd.org/D59022
---
 share/man/man4/ice.4  |  8 ++++++--
 sys/dev/ice/ice_iov.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/share/man/man4/ice.4 b/share/man/man4/ice.4
index 31b61136e36b..d1fa58c8c94c 100644
--- a/share/man/man4/ice.4
+++ b/share/man/man4/ice.4
@@ -1107,9 +1107,13 @@ If unspecified, the VF will use a randomly generated MAC address and
 .Dq allow-set-mac
 will be set to true.
 .It mac-anti-spoof Pq bool
-Prevent the VF from sending Ethernet frames with a source address
-that does not match its own.
+Prevent the VF from sending Ethernet frames whose source address does not
+match a MAC address installed for that VF.
 Enabled by default.
+The policy is enforced in hardware and replayed after PF and device resets.
+If firmware cannot install it during VF creation, the SR-IOV configuration
+request fails.
+If replay fails during reconstruction, the configured VF remains inactive.
 .It allow-set-mac Pq bool
 Allow the VF to set its own Ethernet MAC address.
 Disallowed by default.
diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c
index 0c5d49ebf5b1..57362d8f5a89 100644
--- a/sys/dev/ice/ice_iov.c
+++ b/sys/dev/ice/ice_iov.c
@@ -54,6 +54,8 @@ SYSCTL_INT(_debug_fail_point_ice_iov, OID_AUTO, vf,
     "VF eligible for ice SR-IOV fail points (-1 selects every VF)");
 #endif /* DRIVER_FAILPOINTS */
 static struct ice_vf *ice_iov_get_vf(struct ice_softc *sc, int vf_num);
+static int ice_iov_configure_mac_anti_spoof(struct ice_softc *sc,
+    struct ice_vf *vf);
 static void ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf);
 static void ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf,
 			 bool trigger_vflr);
@@ -242,6 +244,47 @@ ice_iov_get_vf(struct ice_softc *sc, int vf_num)
 	return &sc->vfs[vf_num];
 }
 
+/**
+ * ice_iov_configure_mac_anti_spoof - Apply a VF's source-MAC policy
+ * @sc: device softc structure
+ * @vf: VF whose VSI security policy should be configured
+ *
+ * PF and device resets discard the hardware VSI context, so callers must
+ * replay this policy after creating or rebuilding the VF's VSI.
+ */
+static int
+ice_iov_configure_mac_anti_spoof(struct ice_softc *sc, struct ice_vf *vf)
+{
+	struct ice_vsi_ctx ctx = { 0 };
+	struct ice_vsi *vsi = vf->vsi;
+	struct ice_hw *hw = &sc->hw;
+	bool enable;
+	int status;
+
+	enable = (atomic_load_acq_32(&vf->vf_flags) &
+	    VF_FLAG_MAC_ANTI_SPOOF) != 0;
+	ctx.info.sec_flags = vsi->info.sec_flags;
+	ctx.info.valid_sections =
+	    CPU_TO_LE16(ICE_AQ_VSI_PROP_SECURITY_VALID);
+	if (enable)
+		ctx.info.sec_flags |= ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
+	else
+		ctx.info.sec_flags &= ~ICE_AQ_VSI_SEC_FLAG_ENA_MAC_ANTI_SPOOF;
+
+	status = ice_update_vsi(hw, vsi->idx, &ctx, NULL);
+	if (status != 0) {
+		device_printf(sc->dev,
+		    "Unable to configure VF %u MAC anti-spoof %s, "
+		    "err %s aq_err %s\n", vf->vf_num,
+		    enable ? "on" : "off", ice_status_str(status),
+		    ice_aq_str(hw->adminq.sq_last_status));
+		return (EIO);
+	}
+
+	vsi->info.sec_flags = ctx.info.sec_flags;
+	return (0);
+}
+
 /**
  * ice_iov_add_vf - Called by the OS for each VF to create
  * @sc: device softc structure
@@ -436,6 +479,9 @@ ice_iov_add_vf(struct ice_softc *sc, uint16_t vfnum, const nvlist_t *params)
 	}
 	ICE_IOV_FAIL_POINT(sc, vfnum, add_after_vsi_init, error,
 	    release_imap);
+	error = ice_iov_configure_mac_anti_spoof(sc, vf);
+	if (error != 0)
+		goto release_imap;
 
 	/* Add the broadcast address */
 	error = ice_add_vsi_mac_filter(vsi, broadcastaddr);
@@ -675,6 +721,9 @@ ice_iov_rebuild_vf(struct ice_softc *sc, struct ice_vsi *vsi)
 		return (error);
 	}
 	vsi->hw_stats.cur = accumulated_stats;
+	error = ice_iov_configure_mac_anti_spoof(sc, vf);
+	if (error != 0)
+		return (error);
 
 	status = ice_replay_vsi(hw, vsi->idx);
 	if (status != 0) {