net/mlx5: HWS, make sure the uplink is the last destination
authorVlad Dogaru <vdogaru@nvidia.com>
Tue, 10 Jun 2025 15:15:11 +0000 (18:15 +0300)
committerJakub Kicinski <kuba@kernel.org>
Wed, 11 Jun 2025 21:41:09 +0000 (14:41 -0700)
When there are more than one destinations, we create a FW flow
table and provide it with all the destinations. FW requires to
have wire as the last destination in the list (if it exists),
otherwise the operation fails with FW syndrome.

This patch fixes the destination array action creation: if it
contains a wire destination, it is moved to the end.

Fixes: 504e536d9010 ("net/mlx5: HWS, added actions handling")
Signed-off-by: Vlad Dogaru <vdogaru@nvidia.com>
Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20250610151514.1094735-7-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h

index fb62f3bc4bd4f67a5fcea014fa7a18546d92a4f1..447ea3f8722ce4202b77cdb46c8052a4c1862d7c 100644 (file)
@@ -1370,8 +1370,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
        struct mlx5hws_cmd_set_fte_attr fte_attr = {0};
        struct mlx5hws_cmd_forward_tbl *fw_island;
        struct mlx5hws_action *action;
-       u32 i /*, packet_reformat_id*/;
-       int ret;
+       int ret, last_dest_idx = -1;
+       u32 i;
 
        if (num_dest <= 1) {
                mlx5hws_err(ctx, "Action must have multiple dests\n");
@@ -1401,11 +1401,8 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
                        dest_list[i].destination_id = dests[i].dest->dest_obj.obj_id;
                        fte_attr.action_flags |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
                        fte_attr.ignore_flow_level = ignore_flow_level;
-                       /* ToDo: In SW steering we have a handling of 'go to WIRE'
-                        * destination here by upper layer setting 'is_wire_ft' flag
-                        * if the destination is wire.
-                        * This is because uplink should be last dest in the list.
-                        */
+                       if (dests[i].is_wire_ft)
+                               last_dest_idx = i;
                        break;
                case MLX5HWS_ACTION_TYP_VPORT:
                        dest_list[i].destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
@@ -1429,6 +1426,9 @@ mlx5hws_action_create_dest_array(struct mlx5hws_context *ctx,
                }
        }
 
+       if (last_dest_idx != -1)
+               swap(dest_list[last_dest_idx], dest_list[num_dest - 1]);
+
        fte_attr.dests_num = num_dest;
        fte_attr.dests = dest_list;
 
index 372e2be907067e3bd3246477609d0b3e4b64247c..bf4643d0ce17900a9a46832013b59e62dda50ef2 100644 (file)
@@ -966,6 +966,9 @@ static int mlx5_fs_fte_get_hws_actions(struct mlx5_flow_root_namespace *ns,
                        switch (attr->type) {
                        case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
                                dest_action = mlx5_fs_get_dest_action_ft(fs_ctx, dst);
+                               if (dst->dest_attr.ft->flags &
+                                   MLX5_FLOW_TABLE_UPLINK_VPORT)
+                                       dest_actions[num_dest_actions].is_wire_ft = true;
                                break;
                        case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
                                dest_action = mlx5_fs_get_dest_action_table_num(fs_ctx,
index 9bbadc4d8a0b680f4974220b281c993f14330ef1..d8ac6c196211c9e782c5ab609e0aea15d6528085 100644 (file)
@@ -213,6 +213,7 @@ struct mlx5hws_action_dest_attr {
        struct mlx5hws_action *dest;
        /* Optional reformat action */
        struct mlx5hws_action *reformat;
+       bool is_wire_ft;
 };
 
 /**