From: Chengchang Tang Date: Fri, 10 Apr 2020 11:09:30 +0000 (+0800) Subject: net/hns3: fix VLAN filter when setting promisucous mode X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=40b5448d045573d4d99c866665cd1a9350390f6c;p=dpdk.git net/hns3: fix VLAN filter when setting promisucous mode Currently, when upper level application call the API function named rte_eth_dev_set_vlan_offload to configure the hardware vlan filter offload and call the rte_eth_promiscuous_enable API to enable promiscuous mode based on hns3 PF device, driver can't receive the packets with a vlan tag which has not been added by calling the API function named rte_eth_dev_vlan_filter. This patch fixes it by disabling the vlan filter when setting the promiscuous mode and enabling the vlan filter again after the promiscuous mode are disabled. Fixes: 19a3ca4c99cf ("net/hns3: add start/stop and configure operations") Cc: stable@dpdk.org Signed-off-by: Chengchang Tang Signed-off-by: Wei Hu (Xavier) --- diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index bab4312b39..3e3a8c5f4e 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -607,16 +607,19 @@ hns3_vlan_offload_set(struct rte_eth_dev *dev, int mask) rxmode = &dev->data->dev_conf.rxmode; tmp_mask = (unsigned int)mask; if (tmp_mask & ETH_VLAN_FILTER_MASK) { - /* Enable or disable VLAN filter */ - enable = rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER ? - true : false; + /* ignore vlan filter configuration during promiscuous mode */ + if (!dev->data->promiscuous) { + /* Enable or disable VLAN filter */ + enable = rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER ? + true : false; - ret = hns3_enable_vlan_filter(hns, enable); - if (ret) { - rte_spinlock_unlock(&hw->lock); - hns3_err(hw, "failed to %s rx filter, ret = %d", - enable ? "enable" : "disable", ret); - return ret; + ret = hns3_enable_vlan_filter(hns, enable); + if (ret) { + rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "failed to %s rx filter, ret = %d", + enable ? "enable" : "disable", ret); + return ret; + } } } @@ -1002,14 +1005,16 @@ hns3_restore_vlan_conf(struct hns3_adapter *hns) bool enable; int ret; - /* restore vlan filter states */ - offloads = hw->data->dev_conf.rxmode.offloads; - enable = offloads & DEV_RX_OFFLOAD_VLAN_FILTER ? true : false; - ret = hns3_enable_vlan_filter(hns, enable); - if (ret) { - hns3_err(hw, "failed to restore vlan rx filter conf, ret = %d", - ret); - return ret; + if (!hw->data->promiscuous) { + /* restore vlan filter states */ + offloads = hw->data->dev_conf.rxmode.offloads; + enable = offloads & DEV_RX_OFFLOAD_VLAN_FILTER ? true : false; + ret = hns3_enable_vlan_filter(hns, enable); + if (ret) { + hns3_err(hw, "failed to restore vlan rx filter conf, " + "ret = %d", ret); + return ret; + } } ret = hns3_set_vlan_rx_offload_cfg(hns, &pf->vtag_config.rx_vcfg); @@ -3830,16 +3835,43 @@ hns3_clear_all_vfs_promisc_mode(struct hns3_hw *hw) static int hns3_dev_promiscuous_enable(struct rte_eth_dev *dev) { + bool allmulti = dev->data->all_multicast ? true : false; struct hns3_adapter *hns = dev->data->dev_private; struct hns3_hw *hw = &hns->hw; + uint64_t offloads; + int err; int ret; rte_spinlock_lock(&hw->lock); ret = hns3_set_promisc_mode(hw, true, true); - rte_spinlock_unlock(&hw->lock); - if (ret) - hns3_err(hw, "Failed to enable promiscuous mode, ret = %d", + if (ret) { + rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "failed to enable promiscuous mode, ret = %d", ret); + return ret; + } + + /* + * When promiscuous mode was enabled, disable the vlan filter to let + * all packets coming in in the receiving direction. + */ + offloads = dev->data->dev_conf.rxmode.offloads; + if (offloads & DEV_RX_OFFLOAD_VLAN_FILTER) { + ret = hns3_enable_vlan_filter(hns, false); + if (ret) { + hns3_err(hw, "failed to enable promiscuous mode due to " + "failure to disable vlan filter, ret = %d", + ret); + err = hns3_set_promisc_mode(hw, false, allmulti); + if (err) + hns3_err(hw, "failed to restore promiscuous " + "status after disable vlan filter " + "failed during enabling promiscuous " + "mode, ret = %d", ret); + } + } + + rte_spinlock_unlock(&hw->lock); return ret; } @@ -3850,15 +3882,36 @@ hns3_dev_promiscuous_disable(struct rte_eth_dev *dev) bool allmulti = dev->data->all_multicast ? true : false; struct hns3_adapter *hns = dev->data->dev_private; struct hns3_hw *hw = &hns->hw; + uint64_t offloads; + int err; int ret; /* If now in all_multicast mode, must remain in all_multicast mode. */ rte_spinlock_lock(&hw->lock); ret = hns3_set_promisc_mode(hw, false, allmulti); - rte_spinlock_unlock(&hw->lock); - if (ret) - hns3_err(hw, "Failed to disable promiscuous mode, ret = %d", + if (ret) { + rte_spinlock_unlock(&hw->lock); + hns3_err(hw, "failed to disable promiscuous mode, ret = %d", ret); + return ret; + } + /* when promiscuous mode was disabled, restore the vlan filter status */ + offloads = dev->data->dev_conf.rxmode.offloads; + if (offloads & DEV_RX_OFFLOAD_VLAN_FILTER) { + ret = hns3_enable_vlan_filter(hns, true); + if (ret) { + hns3_err(hw, "failed to disable promiscuous mode due to" + " failure to restore vlan filter, ret = %d", + ret); + err = hns3_set_promisc_mode(hw, true, true); + if (err) + hns3_err(hw, "failed to restore promiscuous " + "status after enabling vlan filter " + "failed during disabling promiscuous " + "mode, ret = %d", ret); + } + } + rte_spinlock_unlock(&hw->lock); return ret; } @@ -3877,7 +3930,7 @@ hns3_dev_allmulticast_enable(struct rte_eth_dev *dev) ret = hns3_set_promisc_mode(hw, false, true); rte_spinlock_unlock(&hw->lock); if (ret) - hns3_err(hw, "Failed to enable allmulticast mode, ret = %d", + hns3_err(hw, "failed to enable allmulticast mode, ret = %d", ret); return ret; @@ -3898,7 +3951,7 @@ hns3_dev_allmulticast_disable(struct rte_eth_dev *dev) ret = hns3_set_promisc_mode(hw, false, false); rte_spinlock_unlock(&hw->lock); if (ret) - hns3_err(hw, "Failed to disable allmulticast mode, ret = %d", + hns3_err(hw, "failed to disable allmulticast mode, ret = %d", ret); return ret; @@ -3909,11 +3962,21 @@ hns3_dev_promisc_restore(struct hns3_adapter *hns) { struct hns3_hw *hw = &hns->hw; bool allmulti = hw->data->all_multicast ? true : false; + int ret; - if (hw->data->promiscuous) - return hns3_set_promisc_mode(hw, true, true); + if (hw->data->promiscuous) { + ret = hns3_set_promisc_mode(hw, true, true); + if (ret) + hns3_err(hw, "failed to restore promiscuous mode, " + "ret = %d", ret); + return ret; + } - return hns3_set_promisc_mode(hw, false, allmulti); + ret = hns3_set_promisc_mode(hw, false, allmulti); + if (ret) + hns3_err(hw, "failed to restore allmulticast mode, ret = %d", + ret); + return ret; } static int