From f977280daca812cfe096811558436ddd515c5a9b Mon Sep 17 00:00:00 2001 From: Yufeng Mo Date: Fri, 26 Jul 2019 17:03:37 +0800 Subject: [PATCH] net: hns3: not allow SSU loopback while execute ethtool -t dev driver inclusion category: bugfix bugzilla: NA CVE: NA The current loopback mode is to add 0x1F to the SMAC address as the DMAC address and enable the promiscuous mode. However, if the VF address is the same as the DMAC address, the loopback test fails. Loopback can be enabled in three places: SSU, MAC, and serdes. By default, SSU loopback is enabled, so if the SMAC and the DMAC are the same, the packets are looped back in the SSU. If SSU loopback is disabled, packets can reach MAC even if SMAC is the same as DMAC. Therefore, this patch disable the SSU loopback before the loopback test. In this way, the SMAC and DMAC can be the same, and the promiscuous mode does not need to be enabled. And this is not valid in version 0x20. This patch also modifies a spelling mistake in a macro definition. Feature or Bugfix:Bugfix Signed-off-by: Yufeng Mo Reviewed-by: lipeng Reviewed-by: Yunsheng Lin Reviewed-by: Yang Yingliang Signed-off-by: Yang Yingliang --- .../ethernet/hisilicon/hns3/hns3_ethtool.c | 7 ++- .../hisilicon/hns3/hns3pf/hclge_cmd.h | 16 +++++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 47 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c index 06bb5531a47c..a54f140bb608 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c @@ -97,7 +97,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) break; } - if (ret) + if (ret || h->pdev->revision >= 0x21) return ret; if (en) { @@ -146,6 +146,7 @@ static void hns3_lp_setup_skb(struct sk_buff *skb) { #define HNS3_NIC_LB_DST_MAC_ADDR 0x1f struct net_device *ndev = skb->dev; + struct hnae3_handle *handle; unsigned char *packet; struct ethhdr *ethh; unsigned int i; @@ -166,7 +167,9 @@ static void hns3_lp_setup_skb(struct sk_buff *skb) * before the packet reaches mac or serdes, which will defect * the purpose of mac or serdes selftest. */ - ethh->h_dest[5] += HNS3_NIC_LB_DST_MAC_ADDR; + handle = hns3_get_handle(ndev); + if (handle->pdev->revision == 0x20) + ethh->h_dest[5] += HNS3_NIC_LB_DST_MAC_ADDR; eth_zero_addr(ethh->h_source); ethh->h_proto = htons(ETH_P_ARP); skb_reset_mac_header(skb); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h index db5e92151ecd..4cd3dbd32800 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h @@ -228,6 +228,9 @@ enum hclge_opcode_type { HCLGE_OPC_MAC_ETHTYPE_ADD = 0x1010, HCLGE_OPC_MAC_ETHTYPE_REMOVE = 0x1011, + /* MAC VLAN commands */ + HCLGE_OPC_MAC_VLAN_SWITCH_PARAM = 0x1033, + /* VLAN commands */ HCLGE_OPC_VLAN_FILTER_CTRL = 0x1100, HCLGE_OPC_VLAN_FILTER_PF_CFG = 0x1101, @@ -812,6 +815,19 @@ struct hclge_vlan_filter_vf_cfg_cmd { u8 vf_bitmap[HCLGE_MAX_VF_BYTES]; }; +struct hclge_mac_vlan_switch_cmd { + u8 roce_sel; + u8 rsv1[3]; + __le32 func_id; + u8 swich_param; + u8 rsv2[15]; +}; + +enum hclge_mac_vlan_cfg_sel { + HCLGE_MAC_VLAN_NIC_SEL = 0, + HCLGE_MAC_VLAN_ROCE_SEL, +}; + #define HCLGE_ACCEPT_TAG1_B 0 #define HCLGE_ACCEPT_UNTAG1_B 1 #define HCLGE_PORT_INS_TAG1_EN_B 2 diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index e3f76be19f33..c1c7e7fec6d1 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3712,6 +3712,42 @@ void hclge_handle_imp_error(struct hnae3_handle *handle) } } +static int hclge_config_ssu_loopback(struct hnae3_handle *handle, + bool enable) +{ +#define HCLGE_ALLOW_LOOPBACK_PKTS 0x2 + + struct hclge_vport *vport = hclge_get_vport(handle); + struct hclge_mac_vlan_switch_cmd *req; + struct hclge_dev *hdev = vport->back; + struct hclge_desc desc; + int ret; + + req = (struct hclge_mac_vlan_switch_cmd *)desc.data; + hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_VLAN_SWITCH_PARAM, + true); + req->roce_sel = HCLGE_MAC_VLAN_NIC_SEL; + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) { + dev_err(&hdev->pdev->dev, + "query mac vlan switch parameter fail, ret = %d\n", + ret); + return ret; + } + + hclge_cmd_reuse_desc(&desc, false); + if (enable) + req->swich_param |= HCLGE_ALLOW_LOOPBACK_PKTS; + else + req->swich_param &= (~HCLGE_ALLOW_LOOPBACK_PKTS); + + ret = hclge_cmd_send(&hdev->hw, &desc, 1); + if (ret) + dev_err(&hdev->pdev->dev, + "set mac vlan switch parameter fail, ret = %d\n", ret); + return ret; +} + static void hclge_reset_subtask(struct hclge_dev *hdev) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); @@ -6495,6 +6531,17 @@ static int hclge_set_loopback(struct hnae3_handle *handle, int ret = 0; int i; + /* Loopback can be enabled in three places: SSU, MAC, and serdes. By + * default, SSU loopback is enabled, so if the SMAC and the DMAC are + * the same, the packets are looped back in the SSU. If SSU loopback + * is disabled, packets can reach MAC even if SMAC is the same as DMAC. + */ + if (hdev->pdev->revision >= 0x21) { + ret = hclge_config_ssu_loopback(handle, !en); + if (ret) + return ret; + } + switch (loop_mode) { case HNAE3_LOOP_APP: ret = hclge_set_app_loopback(hdev, en); -- GitLab