Skip to content

Commit ef62dd5

Browse files
azaki1Sasha Levin
authored and
Sasha Levin
committed
iavf: remove active_cvlans and active_svlans bitmaps
[ Upstream commit 9c85b7f ] The VLAN filters info is currently being held in a list and 2 bitmaps (active_cvlans and active_svlans). We are experiencing some racing where data is not in sync in the list and bitmaps. For example, the VLAN is initially added to the list but only when the PF replies, it is added to the bitmap. If a user adds many V2 VLANS before the PF responds: while [ $((i++)) ] ip l add l eth0 name eth0.$i type vlan id $i we might end up with more VLAN list entries than the designated limit. Also, The "ip link show" will show more links added than the PF limit. On the other and, the bitmaps are only used to check the number of VLAN filters and to re-enable the filters when the interface goes from DOWN to UP. This patch gets rid of the bitmaps and uses the list only. To do that, the states of the VLAN filter are modified: 1 - IAVF_VLAN_REMOVE: the entry needs to be totally removed after informing the PF. This is the "ip link del eth0.$i" path. 2 - IAVF_VLAN_DISABLE: (new) the netdev went down. The filter needs to be removed from the PF and then marked INACTIVE. 3 - IAVF_VLAN_INACTIVE: (new) no PF filter exists, but the user did not delete the VLAN. Fixes: 48ccc43 ("iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config") Signed-off-by: Ahmed Zaki <[email protected]> Tested-by: Rafal Romanowski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent c83ed12 commit ef62dd5

File tree

3 files changed

+45
-47
lines changed

3 files changed

+45
-47
lines changed

drivers/net/ethernet/intel/iavf/iavf.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ enum iavf_vsi_state_t {
5858
struct iavf_vsi {
5959
struct iavf_adapter *back;
6060
struct net_device *netdev;
61-
unsigned long active_cvlans[BITS_TO_LONGS(VLAN_N_VID)];
62-
unsigned long active_svlans[BITS_TO_LONGS(VLAN_N_VID)];
6361
u16 seid;
6462
u16 id;
6563
DECLARE_BITMAP(state, __IAVF_VSI_STATE_SIZE__);
@@ -162,7 +160,9 @@ enum iavf_vlan_state_t {
162160
IAVF_VLAN_ADD, /* filter needs to be added */
163161
IAVF_VLAN_IS_NEW, /* filter is new, wait for PF answer */
164162
IAVF_VLAN_ACTIVE, /* filter is accepted by PF */
165-
IAVF_VLAN_REMOVE, /* filter needs to be removed */
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 */
166166
};
167167

168168
struct iavf_vlan_filter {
@@ -260,6 +260,7 @@ struct iavf_adapter {
260260
wait_queue_head_t vc_waitqueue;
261261
struct iavf_q_vector *q_vectors;
262262
struct list_head vlan_filter_list;
263+
int num_vlan_filters;
263264
struct list_head mac_filter_list;
264265
struct mutex crit_lock;
265266
struct mutex client_lock;

drivers/net/ethernet/intel/iavf/iavf_main.c

+16-24
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter,
792792

793793
list_add_tail(&f->list, &adapter->vlan_filter_list);
794794
f->state = IAVF_VLAN_ADD;
795+
adapter->num_vlan_filters++;
795796
adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
796797
}
797798

@@ -828,14 +829,18 @@ static void iavf_del_vlan(struct iavf_adapter *adapter, struct iavf_vlan vlan)
828829
**/
829830
static void iavf_restore_filters(struct iavf_adapter *adapter)
830831
{
831-
u16 vid;
832+
struct iavf_vlan_filter *f;
832833

833834
/* re-add all VLAN filters */
834-
for_each_set_bit(vid, adapter->vsi.active_cvlans, VLAN_N_VID)
835-
iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021Q));
835+
spin_lock_bh(&adapter->mac_vlan_list_lock);
836836

837-
for_each_set_bit(vid, adapter->vsi.active_svlans, VLAN_N_VID)
838-
iavf_add_vlan(adapter, IAVF_VLAN(vid, ETH_P_8021AD));
837+
list_for_each_entry(f, &adapter->vlan_filter_list, list) {
838+
if (f->state == IAVF_VLAN_INACTIVE)
839+
f->state = IAVF_VLAN_ADD;
840+
}
841+
842+
spin_unlock_bh(&adapter->mac_vlan_list_lock);
843+
adapter->aq_required |= IAVF_FLAG_AQ_ADD_VLAN_FILTER;
839844
}
840845

841846
/**
@@ -844,8 +849,7 @@ static void iavf_restore_filters(struct iavf_adapter *adapter)
844849
*/
845850
u16 iavf_get_num_vlans_added(struct iavf_adapter *adapter)
846851
{
847-
return bitmap_weight(adapter->vsi.active_cvlans, VLAN_N_VID) +
848-
bitmap_weight(adapter->vsi.active_svlans, VLAN_N_VID);
852+
return adapter->num_vlan_filters;
849853
}
850854

851855
/**
@@ -928,11 +932,6 @@ static int iavf_vlan_rx_kill_vid(struct net_device *netdev,
928932
return 0;
929933

930934
iavf_del_vlan(adapter, IAVF_VLAN(vid, be16_to_cpu(proto)));
931-
if (proto == cpu_to_be16(ETH_P_8021Q))
932-
clear_bit(vid, adapter->vsi.active_cvlans);
933-
else
934-
clear_bit(vid, adapter->vsi.active_svlans);
935-
936935
return 0;
937936
}
938937

@@ -1293,16 +1292,11 @@ static void iavf_clear_mac_vlan_filters(struct iavf_adapter *adapter)
12931292
}
12941293
}
12951294

1296-
/* remove all VLAN filters */
1295+
/* disable all VLAN filters */
12971296
list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list,
1298-
list) {
1299-
if (vlf->state == IAVF_VLAN_ADD) {
1300-
list_del(&vlf->list);
1301-
kfree(vlf);
1302-
} else {
1303-
vlf->state = IAVF_VLAN_REMOVE;
1304-
}
1305-
}
1297+
list)
1298+
vlf->state = IAVF_VLAN_DISABLE;
1299+
13061300
spin_unlock_bh(&adapter->mac_vlan_list_lock);
13071301
}
13081302

@@ -2914,6 +2908,7 @@ static void iavf_disable_vf(struct iavf_adapter *adapter)
29142908
list_del(&fv->list);
29152909
kfree(fv);
29162910
}
2911+
adapter->num_vlan_filters = 0;
29172912

29182913
spin_unlock_bh(&adapter->mac_vlan_list_lock);
29192914

@@ -3131,9 +3126,6 @@ static void iavf_reset_task(struct work_struct *work)
31313126
adapter->aq_required |= IAVF_FLAG_AQ_ADD_CLOUD_FILTER;
31323127
iavf_misc_irq_enable(adapter);
31333128

3134-
bitmap_clear(adapter->vsi.active_cvlans, 0, VLAN_N_VID);
3135-
bitmap_clear(adapter->vsi.active_svlans, 0, VLAN_N_VID);
3136-
31373129
mod_delayed_work(adapter->wq, &adapter->watchdog_task, 2);
31383130

31393131
/* We were running when the reset started, so we need to restore some

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

+25-20
Original file line numberDiff line numberDiff line change
@@ -643,15 +643,9 @@ static void iavf_vlan_add_reject(struct iavf_adapter *adapter)
643643
spin_lock_bh(&adapter->mac_vlan_list_lock);
644644
list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
645645
if (f->state == IAVF_VLAN_IS_NEW) {
646-
if (f->vlan.tpid == ETH_P_8021Q)
647-
clear_bit(f->vlan.vid,
648-
adapter->vsi.active_cvlans);
649-
else
650-
clear_bit(f->vlan.vid,
651-
adapter->vsi.active_svlans);
652-
653646
list_del(&f->list);
654647
kfree(f);
648+
adapter->num_vlan_filters--;
655649
}
656650
}
657651
spin_unlock_bh(&adapter->mac_vlan_list_lock);
@@ -824,7 +818,12 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
824818
!VLAN_FILTERING_ALLOWED(adapter)) {
825819
list_del(&f->list);
826820
kfree(f);
827-
} else if (f->state == IAVF_VLAN_REMOVE) {
821+
adapter->num_vlan_filters--;
822+
} else if (f->state == IAVF_VLAN_DISABLE &&
823+
!VLAN_FILTERING_ALLOWED(adapter)) {
824+
f->state = IAVF_VLAN_INACTIVE;
825+
} else if (f->state == IAVF_VLAN_REMOVE ||
826+
f->state == IAVF_VLAN_DISABLE) {
828827
count++;
829828
}
830829
}
@@ -856,11 +855,18 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
856855
vvfl->vsi_id = adapter->vsi_res->vsi_id;
857856
vvfl->num_elements = count;
858857
list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
859-
if (f->state == IAVF_VLAN_REMOVE) {
858+
if (f->state == IAVF_VLAN_DISABLE) {
860859
vvfl->vlan_id[i] = f->vlan.vid;
860+
f->state = IAVF_VLAN_INACTIVE;
861861
i++;
862+
if (i == count)
863+
break;
864+
} else if (f->state == IAVF_VLAN_REMOVE) {
865+
vvfl->vlan_id[i] = f->vlan.vid;
862866
list_del(&f->list);
863867
kfree(f);
868+
adapter->num_vlan_filters--;
869+
i++;
864870
if (i == count)
865871
break;
866872
}
@@ -900,7 +906,8 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
900906
vvfl_v2->vport_id = adapter->vsi_res->vsi_id;
901907
vvfl_v2->num_elements = count;
902908
list_for_each_entry_safe(f, ftmp, &adapter->vlan_filter_list, list) {
903-
if (f->state == IAVF_VLAN_REMOVE) {
909+
if (f->state == IAVF_VLAN_DISABLE ||
910+
f->state == IAVF_VLAN_REMOVE) {
904911
struct virtchnl_vlan_supported_caps *filtering_support =
905912
&adapter->vlan_v2_caps.filtering.filtering_support;
906913
struct virtchnl_vlan *vlan;
@@ -914,8 +921,13 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
914921
vlan->tci = f->vlan.vid;
915922
vlan->tpid = f->vlan.tpid;
916923

917-
list_del(&f->list);
918-
kfree(f);
924+
if (f->state == IAVF_VLAN_DISABLE) {
925+
f->state = IAVF_VLAN_INACTIVE;
926+
} else {
927+
list_del(&f->list);
928+
kfree(f);
929+
adapter->num_vlan_filters--;
930+
}
919931
i++;
920932
if (i == count)
921933
break;
@@ -2443,15 +2455,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
24432455

24442456
spin_lock_bh(&adapter->mac_vlan_list_lock);
24452457
list_for_each_entry(f, &adapter->vlan_filter_list, list) {
2446-
if (f->state == IAVF_VLAN_IS_NEW) {
2458+
if (f->state == IAVF_VLAN_IS_NEW)
24472459
f->state = IAVF_VLAN_ACTIVE;
2448-
if (f->vlan.tpid == ETH_P_8021Q)
2449-
set_bit(f->vlan.vid,
2450-
adapter->vsi.active_cvlans);
2451-
else
2452-
set_bit(f->vlan.vid,
2453-
adapter->vsi.active_svlans);
2454-
}
24552460
}
24562461
spin_unlock_bh(&adapter->mac_vlan_list_lock);
24572462
}

0 commit comments

Comments
 (0)