[PATCH V3 net-next 3/6] net: hns3: support two more actions for tc flow
From: Jijie Shao
Date: Tue Jun 02 2026 - 09:42:15 EST
Currently, the driver supports only one action:HCLGE_FD_ACTION_SELECT_TC.
This patch adds support for HCLGE_FD_ACTION_SELECT_QUEUE and
HCLGE_FD_ACTION_DROP_PACKET.
A rule can have only one action. Therefore, the driver intercepts rules
that have multiple actions or no action.
Note: The driver considers cls_flower->classid as an action:
HCLGE_FD_ACTION_SELECT_TC.
Signed-off-by: Jijie Shao <shaojijie@xxxxxxxxxx>
---
.../hisilicon/hns3/hns3pf/hclge_main.c | 59 ++++++++++++++++---
1 file changed, 52 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 5e1f76513622..aa85abda2909 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7344,18 +7344,45 @@ static int hclge_get_tc_flower_action(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 hnae3_handle *handle = &hdev->vport[0].nic;
+ struct flow_action *action = &flow->action;
+ struct flow_action_entry *act;
int tc;
- tc = tc_classid_to_hwtc(handle->netdev, cls_flower->classid);
- if (tc < 0 || tc > hdev->tc_max) {
- dev_err(&hdev->pdev->dev, "invalid traffic class: %d\n", tc);
- return -EINVAL;
+ if (!flow_action_has_entries(&flow->action)) {
+ tc = tc_classid_to_hwtc(handle->netdev, cls_flower->classid);
+ if (tc < 0 || tc > hdev->tc_max) {
+ dev_err(&hdev->pdev->dev,
+ "invalid traffic class: %d\n", tc);
+ return -EINVAL;
+ }
+
+ rule->action = HCLGE_FD_ACTION_SELECT_TC;
+ rule->cls_flower.tc = tc;
+ return 0;
}
- rule->action = HCLGE_FD_ACTION_SELECT_TC;
- rule->cls_flower.tc = tc;
- return 0;
+ act = &action->entries[0];
+ switch (act->id) {
+ case FLOW_ACTION_RX_QUEUE_MAPPING:
+ if (act->rx_queue >= handle->kinfo.num_tqps) {
+ dev_err(&hdev->pdev->dev,
+ "queue id (%u) should be less than %u\n",
+ act->rx_queue, handle->kinfo.num_tqps);
+ return -EINVAL;
+ }
+
+ rule->queue_id = act->rx_queue;
+ rule->action = HCLGE_FD_ACTION_SELECT_QUEUE;
+ return 0;
+ case FLOW_ACTION_DROP:
+ rule->action = HCLGE_FD_ACTION_DROP_PACKET;
+ return 0;
+ default:
+ dev_err(&hdev->pdev->dev, "unsupported action(%d)\n", act->id);
+ return -EOPNOTSUPP;
+ }
}
static int hclge_parse_cls_flower(struct hclge_dev *hdev,
@@ -7412,6 +7439,24 @@ static int hclge_check_cls_flower(struct hclge_dev *hdev,
return -EOPNOTSUPP;
}
+ /* driver will parses classid into an action */
+ if (cls_flower->classid && flow_action_has_entries(&flow->action)) {
+ dev_err(&hdev->pdev->dev,
+ "please not set classid and action together\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (!flow_action_has_entries(&flow->action) && !cls_flower->classid) {
+ dev_err(&hdev->pdev->dev, "please set action or classid\n");
+ return -EINVAL;
+ }
+
+ if (flow_action_has_entries(&flow->action) &&
+ !flow_offload_has_one_action(&flow->action)) {
+ dev_err(&hdev->pdev->dev, "unsupported multiple actions\n");
+ return -EOPNOTSUPP;
+ }
+
return 0;
}
--
2.33.0