Hello Dan,
Thanks for your report!
在 2021/3/24 15:01, Dan Carpenter 写道:
> Hello Jian Shen,
>
> The patch 5f2b1238b33c: "net: hns3: refactor out
> hclge_add_fd_entry()" from Mar 22, 2021, leads to the following
> static checker warning:
>
> drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c:6512 hclge_fd_parse_ring_cookie()
> warn: array off by one? 'hdev->vport[vf]'
>
> drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
> 6493 static int hclge_fd_parse_ring_cookie(struct hclge_dev *hdev, u64 ring_cookie,
> 6494 u16 *vport_id, u8 *action, u16 *queue_id)
> 6495 {
> 6496 struct hclge_vport *vport = hdev->vport;
> 6497
> 6498 if (ring_cookie == RX_CLS_FLOW_DISC) {
> 6499 *action = HCLGE_FD_ACTION_DROP_PACKET;
> 6500 } else {
> 6501 u32 ring = ethtool_get_flow_spec_ring(ring_cookie);
> 6502 u8 vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
> 6503 u16 tqps;
> 6504
> 6505 if (vf > hdev->num_req_vfs) {
> ^^^^^^^^^^^^^^^^^^^^^^
>
> The is off by one but checking hdev->num_req_vfs in this context doesn't
> make sense. Should it instead be check hdev->num_alloc_vport? Also
> should we add HCLGE_VF_VPORT_START_NUM?
>
> vf = ethtool_get_flow_spec_ring_vf(ring_cookie);
> vf += HCLGE_VF_VPORT_START_NUM;
> if (vf >= hdev->num_alloc_vport)
> return -EINVAL;
>
> 6506 dev_err(&hdev->pdev->dev,
> 6507 "Error: vf id (%u) > max vf num (%u)\n",
> ^^
> Use >=
>
> 6508 vf, hdev->num_req_vfs);
> 6509 return -EINVAL;
> 6510 }
> 6511
> 6512 *vport_id = vf ? hdev->vport[vf].vport_id : vport->vport_id;
> ^^^^^^^^^
> 6513 tqps = hdev->vport[vf].nic.kinfo.num_tqps;
> ^^^
> The vport array has hdev->num_vmdq_vport + hdev->num_req_vfs + 1;
> elements. ->vport[0] is tqp_main_vport. The next elements are
> hdev->num_vmdq_vport and the last part of the array is hdev->num_req_vfs.
>
> Another possibility is that perhaps this is what was intended?
>
> idx = vf + 1 + hdev->num_vmdq_vport;
>
> *vport_id = vf ? vport[idx].vport_id : vport[0].vport_id;
> tqps = vport[idx].nic.kinfo.num_tqps;
>
> There is related code that offers clues but I'm not sure what to do.
>
> 6514
> 6515 if (ring >= tqps) {
> 6516 dev_err(&hdev->pdev->dev,
> 6517 "Error: queue id (%u) > max tqp num (%u)\n",
> 6518 ring, tqps - 1);
> 6519 return -EINVAL;
> 6520 }
> 6521
> 6522 *action = HCLGE_FD_ACTION_SELECT_QUEUE;
> 6523 *queue_id = ring;
> 6524 }
> 6525
> 6526 return 0;
> 6527 }
>
> [ snip ]
>
> 9111 static bool hclge_check_vf_mac_exist(struct hclge_vport *vport, int vf_idx,
> 9112 u8 *mac_addr)
> 9113 {
> 9114 struct hclge_mac_vlan_tbl_entry_cmd req;
> 9115 struct hclge_dev *hdev = vport->back;
> 9116 struct hclge_desc desc;
> 9117 u16 egress_port = 0;
> 9118 int i;
> 9119
> 9120 if (is_zero_ether_addr(mac_addr))
> 9121 return false;
> 9122
> 9123 memset(&req, 0, sizeof(req));
> 9124 hnae3_set_field(egress_port, HCLGE_MAC_EPORT_VFID_M,
> 9125 HCLGE_MAC_EPORT_VFID_S, vport->vport_id);
> 9126 req.egress_port = cpu_to_le16(egress_port);
> 9127 hclge_prepare_mac_addr(&req, mac_addr, false);
> 9128
> 9129 if (hclge_lookup_mac_vlan_tbl(vport, &req, &desc, false) != -ENOENT)
> 9130 return true;
> 9131
> 9132 vf_idx += HCLGE_VF_VPORT_START_NUM;
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> We're are skipping the first element. Should it instead be?:
>
> vf_idx += hdev->num_vmdq_vport + 1;
>
> 9133 for (i = hdev->num_vmdq_vport + 1; i < hdev->num_alloc_vport; i++)
> ^^^^^^^^^^^^^^^^^^^^^^^^
> We're only checking the last part of the array.
>
> 9134 if (i != vf_idx &&
> 9135 ether_addr_equal(mac_addr, hdev->vport[i].vf_info.mac))
> 9136 return true;
> 9137
> 9138 return false;
> 9139 }
>
> Another thing that's not clear to me is how pci_num_vf() relates to
> this. I suspect that it is the same as hdev->num_vmdq_vport, but I
> can't be sure.
>
> regards,
> dan carpenter
> .
The use for num_vmdq_vport is confusing. At the beginning, the HNS3
driver is planed to support
VMDQ . Whereafter the hardware supports SR-IOV with better performance.
So VMDQ feature is
discarded, but the codes of vmdq is remained. For the value of
num_vmdq_vport is always 0, so the
vport id of VF is actually start from 1. That's why the driver still work.
As the num_vmdq_vport is actually useless and confusing, I will send a
patch to remove it soon.
regards,
Jian Shen