Re: [Intel-wired-lan] [PATCH iwl-net] iavf: fix VLAN filter lost on add/delete race
From: Petr Oros
Date: Wed Feb 25 2026 - 09:57:59 EST
On 2/25/26 12:17, Michal Schmidt wrote:
On Wed, Feb 25, 2026 at 11:02 AM Petr Oros <poros@xxxxxxxxxx> wrote:
When iavf_add_vlan() finds an existing filter in IAVF_VLAN_REMOVEI don't get it. If, as the diagram shows, iavf_del_vlans() skipped it,
state, it transitions the filter to IAVF_VLAN_ACTIVE assuming the
pending delete can simply be cancelled. However, there is no guarantee
that iavf_del_vlans() has not already processed the delete AQ request
and removed the filter from the PF. In that case the filter remains in
the driver's list as IAVF_VLAN_ACTIVE but is no longer programmed on
the NIC. Since iavf_add_vlans() only picks up filters in
IAVF_VLAN_ADD state, the filter is never re-added, and spoof checking
drops all traffic for that VLAN.
CPU0 CPU1 Workqueue
---- ---- ---------
iavf_del_vlan(vlan 100)
f->state = REMOVE
schedule AQ_DEL_VLAN
iavf_add_vlan(vlan 100)
f->state = ACTIVE
iavf_del_vlans()
f is ACTIVE, skip
iavf_add_vlans()
f is ACTIVE, skip
Filter is ACTIVE in driver but absent from NIC.
then how does the filter become absent from NIC?
VLAN teardown Workqueue VLAN setup
------------- --------- ----------
iavf_del_vlan(100)
f->state = REMOVE
schedule AQ_DEL_VLAN
iavf_open()
restore_filters()
f is REMOVE, skip
iavf_add_vlan(100)
f->state = ACTIVE
iavf_del_vlans()
f is ACTIVE, skip
iavf_add_vlans()
f is ACTIVE, skip
Is it clear like this?
Michal
Transition to IAVF_VLAN_ADD instead and schedule
IAVF_FLAG_AQ_ADD_VLAN_FILTER so iavf_add_vlans() re-programs the
filter. A duplicate add is idempotent on the PF.
Fixes: 0c0da0e95105 ("iavf: refactor VLAN filter states")
Signed-off-by: Petr Oros <poros@xxxxxxxxxx>
---
drivers/net/ethernet/intel/iavf/iavf_main.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 4b0fc8f354bc90..6046b93c7f3472 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -782,10 +782,13 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,
adapter->num_vlan_filters++;
iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER);
} else if (f->state == IAVF_VLAN_REMOVE) {
- /* IAVF_VLAN_REMOVE means that VLAN wasn't yet removed.
- * We can safely only change the state here.
+ /* Re-add the filter since we cannot tell whether the
+ * pending delete has already been processed by the PF.
+ * A duplicate add is harmless.
*/
- f->state = IAVF_VLAN_ACTIVE;
+ f->state = IAVF_VLAN_ADD;
+ iavf_schedule_aq_request(adapter,
+ IAVF_FLAG_AQ_ADD_VLAN_FILTER);
}
clearout:
--
2.52.0