Subject: Re: [PATCH V3 net-next 3/6] net: hns3: support two more actions for tc flow

From: Jakub Kicinski <[email-masked]>
Date: Fri, 5 Jun 2026 17:40:21 -0700

On Tue, 2 Jun 2026 21:33:34 +0800 Jijie Shao wrote:
> 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 <[email-masked]>
> ---
>  .../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;

Please use struct flow_cls_offload::common:extack and
NL_SET_ERR_MSG_MOD() to return these to the caller instead of dumping
them into the system logs.
-- 
pw-bot: cr