Skip to content

Commit 494ebb7

Browse files
lczapnikgregkh
authored andcommitted
i40e: improve VF MAC filters accounting
commit b99dd77 upstream. When adding new VM MAC, driver checks only *active* filters in vsi->mac_filter_hash. Each MAC, even in non-active state is using resources. To determine number of MACs VM uses, count VSI filters in *any* state. Add i40e_count_all_filters() to simply count all filters, and rename i40e_count_filters() to i40e_count_active_filters() to avoid ambiguity. Fixes: cfb1d57 ("i40e: Add ensurance of MacVlan resources for every trusted VF") Cc: stable@vger.kernel.org Signed-off-by: Lukasz Czapnik <lukasz.czapnik@intel.com> Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com> Reviewed-by: Simon Horman <horms@kernel.org> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent be4b969 commit 494ebb7

File tree

3 files changed

+50
-44
lines changed

3 files changed

+50
-44
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,8 @@ struct i40e_mac_filter *i40e_add_mac_filter(struct i40e_vsi *vsi,
12771277
const u8 *macaddr);
12781278
int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr);
12791279
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
1280-
int i40e_count_filters(struct i40e_vsi *vsi);
1280+
int i40e_count_all_filters(struct i40e_vsi *vsi);
1281+
int i40e_count_active_filters(struct i40e_vsi *vsi);
12811282
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
12821283
void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
12831284
static inline bool i40e_is_sw_dcb(struct i40e_pf *pf)

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,12 +1241,30 @@ void i40e_update_stats(struct i40e_vsi *vsi)
12411241
}
12421242

12431243
/**
1244-
* i40e_count_filters - counts VSI mac filters
1244+
* i40e_count_all_filters - counts VSI MAC filters
12451245
* @vsi: the VSI to be searched
12461246
*
1247-
* Returns count of mac filters
1248-
**/
1249-
int i40e_count_filters(struct i40e_vsi *vsi)
1247+
* Return: count of MAC filters in any state.
1248+
*/
1249+
int i40e_count_all_filters(struct i40e_vsi *vsi)
1250+
{
1251+
struct i40e_mac_filter *f;
1252+
struct hlist_node *h;
1253+
int bkt, cnt = 0;
1254+
1255+
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist)
1256+
cnt++;
1257+
1258+
return cnt;
1259+
}
1260+
1261+
/**
1262+
* i40e_count_active_filters - counts VSI MAC filters
1263+
* @vsi: the VSI to be searched
1264+
*
1265+
* Return: count of active MAC filters.
1266+
*/
1267+
int i40e_count_active_filters(struct i40e_vsi *vsi)
12501268
{
12511269
struct i40e_mac_filter *f;
12521270
struct hlist_node *h;

drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2865,24 +2865,6 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg)
28652865
(u8 *)&stats, sizeof(stats));
28662866
}
28672867

2868-
/**
2869-
* i40e_can_vf_change_mac
2870-
* @vf: pointer to the VF info
2871-
*
2872-
* Return true if the VF is allowed to change its MAC filters, false otherwise
2873-
*/
2874-
static bool i40e_can_vf_change_mac(struct i40e_vf *vf)
2875-
{
2876-
/* If the VF MAC address has been set administratively (via the
2877-
* ndo_set_vf_mac command), then deny permission to the VF to
2878-
* add/delete unicast MAC addresses, unless the VF is trusted
2879-
*/
2880-
if (vf->pf_set_mac && !vf->trusted)
2881-
return false;
2882-
2883-
return true;
2884-
}
2885-
28862868
#define I40E_MAX_MACVLAN_PER_HW 3072
28872869
#define I40E_MAX_MACVLAN_PER_PF(num_ports) (I40E_MAX_MACVLAN_PER_HW / \
28882870
(num_ports))
@@ -2921,8 +2903,10 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
29212903
struct i40e_pf *pf = vf->pf;
29222904
struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
29232905
struct i40e_hw *hw = &pf->hw;
2924-
int mac2add_cnt = 0;
2925-
int i;
2906+
int i, mac_add_max, mac_add_cnt = 0;
2907+
bool vf_trusted;
2908+
2909+
vf_trusted = test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
29262910

29272911
for (i = 0; i < al->num_elements; i++) {
29282912
struct i40e_mac_filter *f;
@@ -2942,9 +2926,8 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
29422926
* The VF may request to set the MAC address filter already
29432927
* assigned to it so do not return an error in that case.
29442928
*/
2945-
if (!i40e_can_vf_change_mac(vf) &&
2946-
!is_multicast_ether_addr(addr) &&
2947-
!ether_addr_equal(addr, vf->default_lan_addr.addr)) {
2929+
if (!vf_trusted && !is_multicast_ether_addr(addr) &&
2930+
vf->pf_set_mac && !ether_addr_equal(addr, vf->default_lan_addr.addr)) {
29482931
dev_err(&pf->pdev->dev,
29492932
"VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
29502933
return -EPERM;
@@ -2953,29 +2936,33 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf,
29532936
/*count filters that really will be added*/
29542937
f = i40e_find_mac(vsi, addr);
29552938
if (!f)
2956-
++mac2add_cnt;
2939+
++mac_add_cnt;
29572940
}
29582941

29592942
/* If this VF is not privileged, then we can't add more than a limited
2960-
* number of addresses. Check to make sure that the additions do not
2961-
* push us over the limit.
2962-
*/
2963-
if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
2964-
if ((i40e_count_filters(vsi) + mac2add_cnt) >
2965-
I40E_VC_MAX_MAC_ADDR_PER_VF) {
2966-
dev_err(&pf->pdev->dev,
2967-
"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
2968-
return -EPERM;
2969-
}
2970-
/* If this VF is trusted, it can use more resources than untrusted.
2943+
* number of addresses.
2944+
*
2945+
* If this VF is trusted, it can use more resources than untrusted.
29712946
* However to ensure that every trusted VF has appropriate number of
29722947
* resources, divide whole pool of resources per port and then across
29732948
* all VFs.
29742949
*/
2975-
} else {
2976-
if ((i40e_count_filters(vsi) + mac2add_cnt) >
2977-
I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs,
2978-
hw->num_ports)) {
2950+
if (!vf_trusted)
2951+
mac_add_max = I40E_VC_MAX_MAC_ADDR_PER_VF;
2952+
else
2953+
mac_add_max = I40E_VC_MAX_MACVLAN_PER_TRUSTED_VF(pf->num_alloc_vfs, hw->num_ports);
2954+
2955+
/* VF can replace all its filters in one step, in this case mac_add_max
2956+
* will be added as active and another mac_add_max will be in
2957+
* a to-be-removed state. Account for that.
2958+
*/
2959+
if ((i40e_count_active_filters(vsi) + mac_add_cnt) > mac_add_max ||
2960+
(i40e_count_all_filters(vsi) + mac_add_cnt) > 2 * mac_add_max) {
2961+
if (!vf_trusted) {
2962+
dev_err(&pf->pdev->dev,
2963+
"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
2964+
return -EPERM;
2965+
} else {
29792966
dev_err(&pf->pdev->dev,
29802967
"Cannot add more MAC addresses, trusted VF exhausted it's resources\n");
29812968
return -EPERM;

0 commit comments

Comments
 (0)