]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: hns3: support two more actions for tc flow
authorJijie Shao <shaojijie@huawei.com>
Wed, 10 Jun 2026 06:06:15 +0000 (14:06 +0800)
committerJakub Kicinski <kuba@kernel.org>
Sun, 14 Jun 2026 00:56:18 +0000 (17:56 -0700)
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@huawei.com>
Link: https://patch.msgid.link/20260610060618.834987-4-shaojijie@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

index 176ea5aac8aa4247cfd399e3182677d7e2a54c4e..ed7cd0a0d2670126db166ed32982f7f2f8cf1710 100644 (file)
@@ -7344,19 +7344,49 @@ 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 netlink_ext_ack *extack = cls_flower->common.extack;
        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) {
-               NL_SET_ERR_MSG_FMT_MOD(extack, "invalid traffic class: %d", 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) {
+                       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;
        }
 
-       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) {
+                       NL_SET_ERR_MSG_FMT_MOD(extack,
+                                              "queue id (%u) should be less than %u",
+                                              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:
+               NL_SET_ERR_MSG_FMT_MOD(extack,
+                                      "unsupported action(%d)", act->id);
+               return -EOPNOTSUPP;
+       }
 }
 
 static int hclge_parse_cls_flower(struct hclge_dev *hdev,
@@ -7420,6 +7450,25 @@ 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)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "cannot specify both classid and action");
+               return -EOPNOTSUPP;
+       }
+
+       if (!flow_action_has_entries(&flow->action) && !cls_flower->classid) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "must specify either classid or action");
+               return -EINVAL;
+       }
+
+       if (flow_action_has_entries(&flow->action) &&
+           !flow_offload_has_one_action(&flow->action)) {
+               NL_SET_ERR_MSG_MOD(extack, "unsupported multiple actions");
+               return -EOPNOTSUPP;
+       }
+
        return 0;
 }