Skip to content

Commit

Permalink
ice: Add support for PF/VF promiscuous mode
Browse files Browse the repository at this point in the history
Implement support for VF promiscuous mode, MAC/VLAN/MAC_VLAN and PF
multicast MAC/VLAN/MAC_VLAN promiscuous mode.

Signed-off-by: Akeem G Abodunrin <akeem.g.abodunrin@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
aabodunrin authored and Jeff Kirsher committed Mar 22, 2019
1 parent e1ca65a commit 5eda8af
Show file tree
Hide file tree
Showing 7 changed files with 527 additions and 31 deletions.
18 changes: 18 additions & 0 deletions drivers/net/ethernet/intel/ice/ice.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ extern const char ice_drv_ver[];
#define ice_for_each_q_vector(vsi, i) \
for ((i) = 0; (i) < (vsi)->num_q_vectors; (i)++)

#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \
ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX)

#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
ICE_PROMISC_MCAST_TX | \
ICE_PROMISC_UCAST_RX | \
ICE_PROMISC_MCAST_RX | \
ICE_PROMISC_VLAN_TX | \
ICE_PROMISC_VLAN_RX)

#define ICE_MCAST_PROMISC_BITS (ICE_PROMISC_MCAST_TX | ICE_PROMISC_MCAST_RX)

#define ICE_MCAST_VLAN_PROMISC_BITS (ICE_PROMISC_MCAST_TX | \
ICE_PROMISC_MCAST_RX | \
ICE_PROMISC_VLAN_TX | \
ICE_PROMISC_VLAN_RX)

struct ice_tc_info {
u16 qoffset;
u16 qcount_tx;
Expand Down Expand Up @@ -258,6 +275,7 @@ struct ice_vsi {
u8 irqs_ready;
u8 current_isup; /* Sync 'link up' logging */
u8 stat_offsets_loaded;
u8 vlan_ena;

/* queue information */
u8 tx_mapping_mode; /* ICE_MAP_MODE_[CONTIG|SCATTER] */
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/ethernet/intel/ice/ice_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2119,10 +2119,11 @@ ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
* ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
* @vsi: VSI to enable or disable VLAN pruning on
* @ena: set to true to enable VLAN pruning and false to disable it
* @vlan_promisc: enable valid security flags if not in VLAN promiscuous mode
*
* returns 0 if VSI is updated, negative otherwise
*/
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc)
{
struct ice_vsi_ctx *ctxt;
struct device *dev;
Expand Down Expand Up @@ -2150,8 +2151,10 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
}

ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
ICE_AQ_VSI_PROP_SW_VALID);
if (!vlan_promisc)
ctxt->info.valid_sections =
cpu_to_le16(ICE_AQ_VSI_PROP_SECURITY_VALID |
ICE_AQ_VSI_PROP_SW_VALID);

status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL);
if (status) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/ice/ice_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int
ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
u16 rel_vmvf_num);

int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena);
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc);

void ice_vsi_delete(struct ice_vsi *vsi);

Expand Down
91 changes: 80 additions & 11 deletions drivers/net/ethernet/intel/ice/ice_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,39 @@ static bool ice_vsi_fltr_changed(struct ice_vsi *vsi)
test_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
}

/**
* ice_cfg_promisc - Enable or disable promiscuous mode for a given PF
* @vsi: the VSI being configured
* @promisc_m: mask of promiscuous config bits
* @set_promisc: enable or disable promisc flag request
*
*/
static int ice_cfg_promisc(struct ice_vsi *vsi, u8 promisc_m, bool set_promisc)
{
struct ice_hw *hw = &vsi->back->hw;
enum ice_status status = 0;

if (vsi->type != ICE_VSI_PF)
return 0;

if (vsi->vlan_ena) {
status = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_m,
set_promisc);
} else {
if (set_promisc)
status = ice_set_vsi_promisc(hw, vsi->idx, promisc_m,
0);
else
status = ice_clear_vsi_promisc(hw, vsi->idx, promisc_m,
0);
}

if (status)
return -EIO;

return 0;
}

/**
* ice_vsi_sync_fltr - Update the VSI filter list to the HW
* @vsi: ptr to the VSI
Expand All @@ -182,6 +215,7 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
struct ice_hw *hw = &pf->hw;
enum ice_status status = 0;
u32 changed_flags = 0;
u8 promisc_m;
int err = 0;

if (!vsi->netdev)
Expand Down Expand Up @@ -245,8 +279,35 @@ static int ice_vsi_sync_fltr(struct ice_vsi *vsi)
}
}
/* check for changes in promiscuous modes */
if (changed_flags & IFF_ALLMULTI)
netdev_warn(netdev, "Unsupported configuration\n");
if (changed_flags & IFF_ALLMULTI) {
if (vsi->current_netdev_flags & IFF_ALLMULTI) {
if (vsi->vlan_ena)
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
else
promisc_m = ICE_MCAST_PROMISC_BITS;

err = ice_cfg_promisc(vsi, promisc_m, true);
if (err) {
netdev_err(netdev, "Error setting Multicast promiscuous mode on VSI %i\n",
vsi->vsi_num);
vsi->current_netdev_flags &= ~IFF_ALLMULTI;
goto out_promisc;
}
} else if (!(vsi->current_netdev_flags & IFF_ALLMULTI)) {
if (vsi->vlan_ena)
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
else
promisc_m = ICE_MCAST_PROMISC_BITS;

err = ice_cfg_promisc(vsi, promisc_m, false);
if (err) {
netdev_err(netdev, "Error clearing Multicast promiscuous mode on VSI %i\n",
vsi->vsi_num);
vsi->current_netdev_flags |= IFF_ALLMULTI;
goto out_promisc;
}
}
}

if (((changed_flags & IFF_PROMISC) || promisc_forced_on) ||
test_bit(ICE_VSI_FLAG_PROMISC_CHANGED, vsi->flags)) {
Expand Down Expand Up @@ -1665,6 +1726,7 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
int ret;

if (vid >= VLAN_N_VID) {
netdev_err(netdev, "VLAN id requested %d is out of range %d\n",
Expand All @@ -1677,8 +1739,7 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,

/* Enable VLAN pruning when VLAN 0 is added */
if (unlikely(!vid)) {
int ret = ice_cfg_vlan_pruning(vsi, true);

ret = ice_cfg_vlan_pruning(vsi, true, false);
if (ret)
return ret;
}
Expand All @@ -1687,7 +1748,13 @@ ice_vlan_rx_add_vid(struct net_device *netdev, __always_unused __be16 proto,
* needed to continue allowing all untagged packets since VLAN prune
* list is applied to all packets by the switch
*/
return ice_vsi_add_vlan(vsi, vid);
ret = ice_vsi_add_vlan(vsi, vid);
if (!ret) {
vsi->vlan_ena = true;
set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
}

return ret;
}

/**
Expand All @@ -1704,23 +1771,25 @@ ice_vlan_rx_kill_vid(struct net_device *netdev, __always_unused __be16 proto,
{
struct ice_netdev_priv *np = netdev_priv(netdev);
struct ice_vsi *vsi = np->vsi;
int status;
int ret;

if (vsi->info.pvid)
return -EINVAL;

/* Make sure ice_vsi_kill_vlan is successful before updating VLAN
* information
*/
status = ice_vsi_kill_vlan(vsi, vid);
if (status)
return status;
ret = ice_vsi_kill_vlan(vsi, vid);
if (ret)
return ret;

/* Disable VLAN pruning when VLAN 0 is removed */
if (unlikely(!vid))
status = ice_cfg_vlan_pruning(vsi, false);
ret = ice_cfg_vlan_pruning(vsi, false, false);

return status;
vsi->vlan_ena = false;
set_bit(ICE_VSI_FLAG_VLAN_FLTR_CHANGED, vsi->flags);
return ret;
}

/**
Expand Down

0 comments on commit 5eda8af

Please sign in to comment.