net: hns3: refactor add_cls_flower to prepare for multiple actions

Remove the tc parameter from the add_cls_flower() ops callback and
refactor action parsing to support future extensions for SELECT_QUEUE
and DROP_PACKET actions.

Changes:
* Remove the tc parameter from the add_cls_flower() callback signature.
* Extract TC-based action parsing into hclge_get_tc_flower_action().
* Move the dissector->used_keys check from hclge_parse_cls_flower() to
  hclge_check_cls_flower(), and restrict ETH_ADDRS to
  HCLGE_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1 mode since hardware only
  supports MAC matching there.
* Migrate error reporting from dev_err() to netlink extended ACK (extack).

Signed-off-by: Jijie Shao <shaojijie@huawei.com>
Link: https://patch.msgid.link/20260610060618.834987-2-shaojijie@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jijie Shao 2026-06-10 14:06:13 +08:00 committed by Jakub Kicinski
parent a6ee1ca955
commit d7db57e3b4
3 changed files with 60 additions and 38 deletions

View File

@ -778,7 +778,7 @@ struct hnae3_ae_ops {
u32 len, u8 *data);
bool (*get_cmdq_stat)(struct hnae3_handle *handle);
int (*add_cls_flower)(struct hnae3_handle *handle,
struct flow_cls_offload *cls_flower, int tc);
struct flow_cls_offload *cls_flower);
int (*del_cls_flower)(struct hnae3_handle *handle,
struct flow_cls_offload *cls_flower);
bool (*cls_flower_active)(struct hnae3_handle *handle);

View File

@ -2678,13 +2678,12 @@ static int hns3_setup_tc(struct net_device *netdev, void *type_data)
static int hns3_setup_tc_cls_flower(struct hns3_nic_priv *priv,
struct flow_cls_offload *flow)
{
int tc = tc_classid_to_hwtc(priv->netdev, flow->classid);
struct hnae3_handle *h = hns3_get_handle(priv->netdev);
switch (flow->command) {
case FLOW_CLS_REPLACE:
if (h->ae_algo->ops->add_cls_flower)
return h->ae_algo->ops->add_cls_flower(h, flow, tc);
return h->ae_algo->ops->add_cls_flower(h, flow);
break;
case FLOW_CLS_DESTROY:
if (h->ae_algo->ops->del_cls_flower)

View File

@ -7328,28 +7328,33 @@ static void hclge_get_cls_key_port(const struct flow_rule *flow,
}
}
static int hclge_get_tc_flower_action(struct hclge_dev *hdev,
struct flow_cls_offload *cls_flower,
struct hclge_fd_rule *rule)
{
struct netlink_ext_ack *extack = cls_flower->common.extack;
struct hnae3_handle *handle = &hdev->vport[0].nic;
int tc;
tc = tc_classid_to_hwtc(handle->netdev, cls_flower->classid);
if (tc < 0 || tc > hdev->tc_max) {
NL_SET_ERR_MSG_FMT_MOD(extack, "invalid traffic class: %d", tc);
return -EINVAL;
}
rule->action = HCLGE_FD_ACTION_SELECT_TC;
rule->cls_flower.tc = tc;
return 0;
}
static int hclge_parse_cls_flower(struct hclge_dev *hdev,
struct flow_cls_offload *cls_flower,
struct hclge_fd_rule *rule)
{
struct flow_rule *flow = flow_cls_offload_flow_rule(cls_flower);
struct netlink_ext_ack *extack = cls_flower->common.extack;
struct flow_dissector *dissector = flow->match.dissector;
int ret;
if (dissector->used_keys &
~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_PORTS))) {
dev_err(&hdev->pdev->dev, "unsupported key set: %#llx\n",
dissector->used_keys);
return -EOPNOTSUPP;
}
hclge_get_cls_key_basic(flow, rule);
hclge_get_cls_key_mac(flow, rule);
hclge_get_cls_key_vlan(flow, rule);
@ -7364,51 +7369,65 @@ static int hclge_parse_cls_flower(struct hclge_dev *hdev,
}
static int hclge_check_cls_flower(struct hclge_dev *hdev,
struct flow_cls_offload *cls_flower, int tc)
struct flow_cls_offload *cls_flower)
{
struct flow_rule *flow = flow_cls_offload_flow_rule(cls_flower);
struct netlink_ext_ack *extack = cls_flower->common.extack;
struct flow_dissector *dissector = flow->match.dissector;
u32 prio = cls_flower->common.prio;
if (tc < 0 || tc > hdev->tc_max) {
dev_err(&hdev->pdev->dev, "invalid traffic class\n");
return -EINVAL;
}
u64 support_keys;
if (prio == 0 ||
prio > hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]) {
dev_err(&hdev->pdev->dev,
"prio %u should be in range[1, %u]\n",
prio, hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]);
NL_SET_ERR_MSG_FMT_MOD(extack,
"prio %u should be in range[1, %u]",
prio,
hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]);
return -EINVAL;
}
if (test_bit(prio - 1, hdev->fd_bmap)) {
dev_err(&hdev->pdev->dev, "prio %u is already used\n", prio);
NL_SET_ERR_MSG_FMT_MOD(extack,
"prio %u is already used", prio);
return -EINVAL;
}
support_keys = BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT_ULL(FLOW_DISSECTOR_KEY_PORTS);
if (hdev->fd_cfg.fd_mode == HCLGE_FD_MODE_DEPTH_2K_WIDTH_400B_STAGE_1)
support_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS);
if (dissector->used_keys & ~support_keys) {
NL_SET_ERR_MSG_FMT_MOD(extack, "unsupported key set: %#llx",
dissector->used_keys);
return -EOPNOTSUPP;
}
return 0;
}
static int hclge_add_cls_flower(struct hnae3_handle *handle,
struct flow_cls_offload *cls_flower,
int tc)
struct flow_cls_offload *cls_flower)
{
struct netlink_ext_ack *extack = cls_flower->common.extack;
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
struct hclge_fd_rule *rule;
int ret;
if (!hnae3_ae_dev_fd_supported(hdev->ae_dev)) {
dev_err(&hdev->pdev->dev,
"cls flower is not supported\n");
NL_SET_ERR_MSG_MOD(extack, "cls flower is not supported");
return -EOPNOTSUPP;
}
ret = hclge_check_cls_flower(hdev, cls_flower, tc);
if (ret) {
dev_err(&hdev->pdev->dev,
"failed to check cls flower params, ret = %d\n", ret);
ret = hclge_check_cls_flower(hdev, cls_flower);
if (ret)
return ret;
}
rule = kzalloc_obj(*rule);
if (!rule)
@ -7420,8 +7439,12 @@ static int hclge_add_cls_flower(struct hnae3_handle *handle,
return ret;
}
rule->action = HCLGE_FD_ACTION_SELECT_TC;
rule->cls_flower.tc = tc;
ret = hclge_get_tc_flower_action(hdev, cls_flower, rule);
if (ret) {
kfree(rule);
return ret;
}
rule->location = cls_flower->common.prio - 1;
rule->vf_id = 0;
rule->cls_flower.cookie = cls_flower->cookie;