Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iavf: stop removing VLAN filters from PF on interface down

When a VF goes down, the driver currently sends DEL_VLAN to the PF for
every VLAN filter (ACTIVE -> DISABLE -> send DEL -> INACTIVE), then
re-adds them all on UP (INACTIVE -> ADD -> send ADD -> ADDING ->
ACTIVE). This round-trip is unnecessary because:

1. The PF disables the VF's queues via VIRTCHNL_OP_DISABLE_QUEUES,
which already prevents all RX/TX traffic regardless of VLAN filter
state.

2. The VLAN filters remaining in PF HW while the VF is down is
harmless - packets matching those filters have nowhere to go with
queues disabled.

3. The DEL+ADD cycle during down/up creates race windows where the
VLAN filter list is incomplete. With spoofcheck enabled, the PF
enables TX VLAN filtering on the first non-zero VLAN add, blocking
traffic for any VLANs not yet re-added.

Remove the entire DISABLE/INACTIVE state machinery:
- Remove IAVF_VLAN_DISABLE and IAVF_VLAN_INACTIVE enum values
- Remove iavf_restore_filters() and its call from iavf_open()
- Remove VLAN filter handling from iavf_clear_mac_vlan_filters(),
rename it to iavf_clear_mac_filters()
- Remove DEL_VLAN_FILTER scheduling from iavf_down()
- Remove all DISABLE/INACTIVE handling from iavf_del_vlans()

VLAN filters now stay ACTIVE across down/up cycles. Only explicit
user removal (ndo_vlan_rx_kill_vid) or PF/VF reset triggers VLAN
filter deletion/re-addition.

Fixes: ed1f5b58ea01 ("i40evf: remove VLAN filters on close")
Signed-off-by: Petr Oros <poros@redhat.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260427-jk-iwl-net-petr-oros-fixes-v1-2-cdcb48303fd8@intel.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Petr Oros and committed by
Paolo Abeni
f2ce65b9 70d62b66

+12 -66
+2 -4
drivers/net/ethernet/intel/iavf/iavf.h
··· 159 159 IAVF_VLAN_INVALID, 160 160 IAVF_VLAN_ADD, /* filter needs to be added */ 161 161 IAVF_VLAN_ADDING, /* ADD sent to PF, waiting for response */ 162 - IAVF_VLAN_ACTIVE, /* filter is accepted by PF */ 163 - IAVF_VLAN_DISABLE, /* filter needs to be deleted by PF, then marked INACTIVE */ 164 - IAVF_VLAN_INACTIVE, /* filter is inactive, we are in IFF_DOWN */ 165 - IAVF_VLAN_REMOVE, /* filter needs to be removed from list */ 162 + IAVF_VLAN_ACTIVE, /* PF confirmed, filter is in HW */ 163 + IAVF_VLAN_REMOVE, /* filter queued for DEL from PF */ 166 164 }; 167 165 168 166 struct iavf_vlan_filter {
+4 -35
drivers/net/ethernet/intel/iavf/iavf_main.c
··· 801 801 spin_unlock_bh(&adapter->mac_vlan_list_lock); 802 802 } 803 803 804 - /** 805 - * iavf_restore_filters 806 - * @adapter: board private structure 807 - * 808 - * Restore existing non MAC filters when VF netdev comes back up 809 - **/ 810 - static void iavf_restore_filters(struct iavf_adapter *adapter) 811 - { 812 - struct iavf_vlan_filter *f; 813 - 814 - /* re-add all VLAN filters */ 815 - spin_lock_bh(&adapter->mac_vlan_list_lock); 816 - 817 - list_for_each_entry(f, &adapter->vlan_filter_list, list) { 818 - if (f->state == IAVF_VLAN_INACTIVE) 819 - f->state = IAVF_VLAN_ADD; 820 - } 821 - 822 - spin_unlock_bh(&adapter->mac_vlan_list_lock); 823 - adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER; 824 - } 825 804 826 805 /** 827 806 * iavf_get_num_vlans_added - get number of VLANs added ··· 1225 1246 } 1226 1247 1227 1248 /** 1228 - * iavf_clear_mac_vlan_filters - Remove mac and vlan filters not sent to PF 1229 - * yet and mark other to be removed. 1249 + * iavf_clear_mac_filters - Remove MAC filters not sent to PF yet and mark 1250 + * others to be removed. 1230 1251 * @adapter: board private structure 1231 1252 **/ 1232 - static void iavf_clear_mac_vlan_filters(struct iavf_adapter *adapter) 1253 + static void iavf_clear_mac_filters(struct iavf_adapter *adapter) 1233 1254 { 1234 - struct iavf_vlan_filter *vlf, *vlftmp; 1235 1255 struct iavf_mac_filter *f, *ftmp; 1236 1256 1237 1257 spin_lock_bh(&adapter->mac_vlan_list_lock); ··· 1248 1270 f->remove = true; 1249 1271 } 1250 1272 } 1251 - 1252 - /* disable all VLAN filters */ 1253 - list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list, 1254 - list) 1255 - vlf->state = IAVF_VLAN_DISABLE; 1256 1273 1257 1274 spin_unlock_bh(&adapter->mac_vlan_list_lock); 1258 1275 } ··· 1344 1371 iavf_napi_disable_all(adapter); 1345 1372 iavf_irq_disable(adapter); 1346 1373 1347 - iavf_clear_mac_vlan_filters(adapter); 1374 + iavf_clear_mac_filters(adapter); 1348 1375 iavf_clear_cloud_filters(adapter); 1349 1376 iavf_clear_fdir_filters(adapter); 1350 1377 iavf_clear_adv_rss_conf(adapter); ··· 1361 1388 */ 1362 1389 if (!list_empty(&adapter->mac_filter_list)) 1363 1390 adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER; 1364 - if (!list_empty(&adapter->vlan_filter_list)) 1365 - adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER; 1366 1391 if (!list_empty(&adapter->cloud_filter_list)) 1367 1392 adapter->aq_required |= IAVF_FLAG_AQ_DEL_CLOUD_FILTER; 1368 1393 if (!list_empty(&adapter->fdir_list_head)) ··· 4465 4494 iavf_add_filter(adapter, adapter->hw.mac.addr); 4466 4495 spin_unlock_bh(&adapter->mac_vlan_list_lock); 4467 4496 4468 - /* Restore filters that were removed with IFF_DOWN */ 4469 - iavf_restore_filters(adapter); 4470 4497 iavf_restore_fdir_filters(adapter); 4471 4498 4472 4499 iavf_configure(adapter);
+6 -27
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
··· 911 911 spin_lock_bh(&adapter->mac_vlan_list_lock); 912 912 913 913 list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { 914 - /* since VLAN capabilities are not allowed, we dont want to send 915 - * a VLAN delete request because it will most likely fail and 916 - * create unnecessary errors/noise, so just free the VLAN 917 - * filters marked for removal to enable bailing out before 918 - * sending a virtchnl message 919 - */ 920 914 if (f->state == IAVF_VLAN_REMOVE && 921 915 !VLAN_FILTERING_ALLOWED(adapter)) { 922 916 list_del(&f->list); 923 917 kfree(f); 924 918 adapter->num_vlan_filters--; 925 - } else if (f->state == IAVF_VLAN_DISABLE && 926 - !VLAN_FILTERING_ALLOWED(adapter)) { 927 - f->state = IAVF_VLAN_INACTIVE; 928 - } else if (f->state == IAVF_VLAN_REMOVE || 929 - f->state == IAVF_VLAN_DISABLE) { 919 + } else if (f->state == IAVF_VLAN_REMOVE) { 930 920 count++; 931 921 } 932 922 } ··· 949 959 vvfl->vsi_id = adapter->vsi_res->vsi_id; 950 960 vvfl->num_elements = count; 951 961 list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { 952 - if (f->state == IAVF_VLAN_DISABLE) { 953 - vvfl->vlan_id[i] = f->vlan.vid; 954 - f->state = IAVF_VLAN_INACTIVE; 955 - i++; 956 - if (i == count) 957 - break; 958 - } else if (f->state == IAVF_VLAN_REMOVE) { 962 + if (f->state == IAVF_VLAN_REMOVE) { 959 963 vvfl->vlan_id[i] = f->vlan.vid; 960 964 list_del(&f->list); 961 965 kfree(f); ··· 991 1007 vvfl_v2->vport_id = adapter->vsi_res->vsi_id; 992 1008 vvfl_v2->num_elements = count; 993 1009 list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) { 994 - if (f->state == IAVF_VLAN_DISABLE || 995 - f->state == IAVF_VLAN_REMOVE) { 1010 + if (f->state == IAVF_VLAN_REMOVE) { 996 1011 struct virtchnl_vlan_supported_caps *filtering_support = 997 1012 &adapter->vlan_v2_caps.filtering.filtering_support; 998 1013 struct virtchnl_vlan *vlan; ··· 1005 1022 vlan->tci = f->vlan.vid; 1006 1023 vlan->tpid = f->vlan.tpid; 1007 1024 1008 - if (f->state == IAVF_VLAN_DISABLE) { 1009 - f->state = IAVF_VLAN_INACTIVE; 1010 - } else { 1011 - list_del(&f->list); 1012 - kfree(f); 1013 - adapter->num_vlan_filters--; 1014 - } 1025 + list_del(&f->list); 1026 + kfree(f); 1027 + adapter->num_vlan_filters--; 1015 1028 i++; 1016 1029 if (i == count) 1017 1030 break;