This patch supports mirroring by adding an dest_array action. The action
accecpts a list containing multiple destination actions, and can duplicate
packet and forward to each destination in the list.

Signed-off-by: Shun Hao <sh...@nvidia.com>
Acked-by: Alex Vesker <va...@nvidia.com>
---
 drivers/common/mlx5/mlx5_prm.h       |  23 ++++-
 drivers/net/mlx5/hws/mlx5dr.h        |  34 +++++++
 drivers/net/mlx5/hws/mlx5dr_action.c | 132 ++++++++++++++++++++++++++-
 drivers/net/mlx5/hws/mlx5dr_action.h |   3 +
 drivers/net/mlx5/hws/mlx5dr_cmd.c    |  63 +++++++++++--
 drivers/net/mlx5/hws/mlx5dr_cmd.h    |  19 +++-
 drivers/net/mlx5/hws/mlx5dr_debug.c  |   1 +
 drivers/net/mlx5/hws/mlx5dr_table.c  |   7 +-
 8 files changed, 264 insertions(+), 18 deletions(-)

diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 6749f2c037..5d62dd8e84 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -2310,7 +2310,11 @@ struct mlx5_ifc_cmd_hca_cap_2_bits {
 };
 
 struct mlx5_ifc_esw_cap_bits {
-       u8 reserved_at_0[0x60];
+       u8 reserved_at_0[0x1d];
+       u8 merged_eswitch[0x1];
+       u8 reserved_at_1e[0x2];
+
+       u8 reserved_at_20[0x40];
 
        u8 esw_manager_vport_number_valid[0x1];
        u8 reserved_at_61[0xf];
@@ -5034,6 +5038,7 @@ struct mlx5_ifc_query_flow_table_out_bits {
 enum mlx5_flow_destination_type {
        MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0,
        MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1,
+       MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2,
 };
 
 enum mlx5_flow_context_action {
@@ -5073,6 +5078,19 @@ union mlx5_ifc_dest_format_flow_counter_list_auto_bits {
        u8 reserved_at_0[0x40];
 };
 
+struct mlx5_ifc_extended_dest_format_bits {
+       struct mlx5_ifc_dest_format_bits destination_entry;
+
+       u8 packet_reformat_id[0x20];
+
+       u8 reserved_at_60[0x20];
+};
+
+#define MLX5_IFC_MULTI_PATH_FT_MAX_LEVEL 64
+
+#ifdef PEDANTIC
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
 struct mlx5_ifc_flow_context_bits {
        u8 reserved_at_00[0x20];
        u8 group_id[0x20];
@@ -5091,8 +5109,7 @@ struct mlx5_ifc_flow_context_bits {
        u8 reserved_at_e0[0x40];
        u8 encrypt_decrypt_obj_id[0x20];
        u8 reserved_at_140[0x16c0];
-       /* Currently only one destnation */
-       union mlx5_ifc_dest_format_flow_counter_list_auto_bits destination[1];
+       union mlx5_ifc_dest_format_flow_counter_list_auto_bits destination[0];
 };
 
 struct mlx5_ifc_set_fte_in_bits {
diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index 184de8feaf..5eabbc34a4 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -46,6 +46,7 @@ enum mlx5dr_action_type {
        MLX5DR_ACTION_TYP_ASO_METER,
        MLX5DR_ACTION_TYP_ASO_CT,
        MLX5DR_ACTION_TYP_DEST_ROOT,
+       MLX5DR_ACTION_TYP_DEST_ARRAY,
        MLX5DR_ACTION_TYP_MAX,
 };
 
@@ -213,6 +214,20 @@ struct mlx5dr_rule_action {
        };
 };
 
+struct mlx5dr_action_dest_attr {
+       /* Required action combination */
+       enum mlx5dr_action_type *action_type;
+
+       /* Required destination action to forward the packet */
+       struct mlx5dr_action *dest;
+
+       /* Optional reformat data */
+       struct {
+               size_t reformat_data_sz;
+               void *reformat_data;
+       } reformat;
+};
+
 /* Open a context used for direct rule insertion using hardware steering.
  * Each context can contain multiple tables of different types.
  *
@@ -604,6 +619,25 @@ mlx5dr_action_create_pop_vlan(struct mlx5dr_context *ctx, 
uint32_t flags);
 struct mlx5dr_action *
 mlx5dr_action_create_push_vlan(struct mlx5dr_context *ctx, uint32_t flags);
 
+/* Create a dest array action, this action can duplicate packets and forward to
+ * multiple destinations in the destination list.
+ * @param[in] ctx
+ *     The context in which the new action will be created.
+ * @param[in] num_dest
+ *     The number of dests attributes.
+ * @param[in] dests
+ *     The destination array. Each contains a destination action and can have
+ *     additional actions.
+ * @param[in] flags
+ *     Action creation flags. (enum mlx5dr_action_flags)
+ * @return pointer to mlx5dr_action on success NULL otherwise.
+ */
+struct mlx5dr_action *
+mlx5dr_action_create_dest_array(struct mlx5dr_context *ctx,
+                               size_t num_dest,
+                               struct mlx5dr_action_dest_attr *dests,
+                               uint32_t flags);
+
 /* Create dest root table, this action will jump to root table according
  * the given priority.
  * @param[in] ctx
diff --git a/drivers/net/mlx5/hws/mlx5dr_action.c 
b/drivers/net/mlx5/hws/mlx5dr_action.c
index ba17d97517..e890ebb481 100644
--- a/drivers/net/mlx5/hws/mlx5dr_action.c
+++ b/drivers/net/mlx5/hws/mlx5dr_action.c
@@ -34,7 +34,8 @@ static const uint32_t 
action_order_arr[MLX5DR_TABLE_TYPE_MAX][MLX5DR_ACTION_TYP_
                BIT(MLX5DR_ACTION_TYP_MISS) |
                BIT(MLX5DR_ACTION_TYP_TIR) |
                BIT(MLX5DR_ACTION_TYP_DROP) |
-               BIT(MLX5DR_ACTION_TYP_DEST_ROOT),
+               BIT(MLX5DR_ACTION_TYP_DEST_ROOT) |
+               BIT(MLX5DR_ACTION_TYP_DEST_ARRAY),
                BIT(MLX5DR_ACTION_TYP_LAST),
        },
        [MLX5DR_TABLE_TYPE_NIC_TX] = {
@@ -71,7 +72,8 @@ static const uint32_t 
action_order_arr[MLX5DR_TABLE_TYPE_MAX][MLX5DR_ACTION_TYP_
                BIT(MLX5DR_ACTION_TYP_MISS) |
                BIT(MLX5DR_ACTION_TYP_VPORT) |
                BIT(MLX5DR_ACTION_TYP_DROP) |
-               BIT(MLX5DR_ACTION_TYP_DEST_ROOT),
+               BIT(MLX5DR_ACTION_TYP_DEST_ROOT) |
+               BIT(MLX5DR_ACTION_TYP_DEST_ARRAY),
                BIT(MLX5DR_ACTION_TYP_LAST),
        },
 };
@@ -533,6 +535,7 @@ static void mlx5dr_action_fill_stc_attr(struct 
mlx5dr_action *action,
                }
                break;
        case MLX5DR_ACTION_TYP_TBL:
+       case MLX5DR_ACTION_TYP_DEST_ARRAY:
                attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT;
                attr->action_offset = MLX5DR_ACTION_OFFSET_HIT;
                attr->dest_table_id = obj->id;
@@ -864,6 +867,8 @@ mlx5dr_action_create_dest_tir(struct mlx5dr_context *ctx,
                ret = mlx5dr_action_create_stcs(action, cur_obj);
                if (ret)
                        goto clean_obj;
+
+               action->devx_dest.devx_obj = cur_obj;
        }
 
        return action;
@@ -1696,6 +1701,124 @@ mlx5dr_action_create_modify_header(struct 
mlx5dr_context *ctx,
        return NULL;
 }
 
+struct mlx5dr_action *
+mlx5dr_action_create_dest_array(struct mlx5dr_context *ctx,
+                               size_t num_dest,
+                               struct mlx5dr_action_dest_attr *dests,
+                               uint32_t flags)
+{
+       struct mlx5dr_cmd_set_fte_dest *dest_list = NULL;
+       struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
+       struct mlx5dr_cmd_set_fte_attr fte_attr = {0};
+       struct mlx5dr_cmd_forward_tbl *fw_island;
+       enum mlx5dr_table_type table_type;
+       struct mlx5dr_action *action;
+       uint32_t i;
+       int ret;
+
+       if (num_dest <= 1) {
+               rte_errno = EINVAL;
+               DR_LOG(ERR, "Action must have multiple dests");
+               return NULL;
+       }
+
+       if (flags == (MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_SHARED)) {
+               ft_attr.type = FS_FT_NIC_RX;
+               ft_attr.level = MLX5_IFC_MULTI_PATH_FT_MAX_LEVEL - 1;
+               table_type = MLX5DR_TABLE_TYPE_NIC_RX;
+       } else if (flags == (MLX5DR_ACTION_FLAG_HWS_FDB | 
MLX5DR_ACTION_FLAG_SHARED)) {
+               ft_attr.type = FS_FT_FDB;
+               ft_attr.level = ctx->caps->fdb_ft.max_level - 1;
+               table_type = MLX5DR_TABLE_TYPE_FDB;
+       } else {
+               DR_LOG(ERR, "Action flags not supported");
+               rte_errno = ENOTSUP;
+               return NULL;
+       }
+
+       if (mlx5dr_context_shared_gvmi_used(ctx)) {
+               DR_LOG(ERR, "Cannot use this action in shared GVMI context");
+               rte_errno = ENOTSUP;
+               return NULL;
+       }
+
+       dest_list = simple_calloc(num_dest, sizeof(*dest_list));
+       if (!dest_list) {
+               DR_LOG(ERR, "Failed to allocate memory for destinations");
+               rte_errno = ENOMEM;
+               return NULL;
+       }
+
+       for (i = 0; i < num_dest; i++) {
+               enum mlx5dr_action_type *action_type = dests[i].action_type;
+
+               if (!mlx5dr_action_check_combo(dests[i].action_type, 
table_type)) {
+                       DR_LOG(ERR, "Invalid combination of actions");
+                       rte_errno = EINVAL;
+                       goto free_dest_list;
+               }
+
+               for (; *action_type != MLX5DR_ACTION_TYP_LAST; action_type++) {
+                       switch (*action_type) {
+                       case MLX5DR_ACTION_TYP_TBL:
+                               dest_list[i].destination_type =
+                                       MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
+                               dest_list[i].destination_id = 
dests[i].dest->devx_dest.devx_obj->id;
+                               fte_attr.action_flags |= 
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+                               fte_attr.ignore_flow_level = 1;
+                               break;
+                       case MLX5DR_ACTION_TYP_VPORT:
+                               dest_list[i].destination_type = 
MLX5_FLOW_DESTINATION_TYPE_VPORT;
+                               dest_list[i].destination_id = 
dests[i].dest->vport.vport_num;
+                               fte_attr.action_flags |= 
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+                               if (ctx->caps->merged_eswitch) {
+                                       dest_list[i].ext_flags |=
+                                               
MLX5DR_CMD_EXT_DEST_ESW_OWNER_VHCA_ID;
+                                       dest_list[i].esw_owner_vhca_id =
+                                               
dests[i].dest->vport.esw_owner_vhca_id;
+                               }
+                               break;
+                       case MLX5DR_ACTION_TYP_TIR:
+                               dest_list[i].destination_type = 
MLX5_FLOW_DESTINATION_TYPE_TIR;
+                               dest_list[i].destination_id = 
dests[i].dest->devx_dest.devx_obj->id;
+                               fte_attr.action_flags |= 
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+                               break;
+                       default:
+                               DR_LOG(ERR, "Unsupported action in dest_array");
+                               rte_errno = ENOTSUP;
+                               goto free_dest_list;
+                       }
+               }
+       }
+       fte_attr.dests_num = num_dest;
+       fte_attr.dests = dest_list;
+
+       fw_island = mlx5dr_cmd_forward_tbl_create(ctx->ibv_ctx, &ft_attr, 
&fte_attr);
+       if (!fw_island)
+               goto free_dest_list;
+
+       action = mlx5dr_action_create_generic(ctx, flags, 
MLX5DR_ACTION_TYP_DEST_ARRAY);
+       if (!action)
+               goto destroy_fw_island;
+
+       ret = mlx5dr_action_create_stcs(action, fw_island->ft);
+       if (ret)
+               goto free_action;
+
+       action->dest_array.fw_island = fw_island;
+
+       simple_free(dest_list);
+       return action;
+
+free_action:
+       simple_free(action);
+destroy_fw_island:
+       mlx5dr_cmd_forward_tbl_destroy(fw_island);
+free_dest_list:
+       simple_free(dest_list);
+       return NULL;
+}
+
 struct mlx5dr_action *
 mlx5dr_action_create_dest_root(struct mlx5dr_context *ctx,
                               uint16_t priority,
@@ -1778,6 +1901,10 @@ static void mlx5dr_action_destroy_hws(struct 
mlx5dr_action *action)
                mlx5dr_action_destroy_stcs(action);
                mlx5dr_action_put_shared_stc(action, 
MLX5DR_CONTEXT_SHARED_STC_POP);
                break;
+       case MLX5DR_ACTION_TYP_DEST_ARRAY:
+               mlx5dr_action_destroy_stcs(action);
+               mlx5dr_cmd_forward_tbl_destroy(action->dest_array.fw_island);
+               break;
        case MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
        case MLX5DR_ACTION_TYP_MODIFY_HDR:
                for (i = 0; i < action->modify_header.num_of_patterns; i++) {
@@ -2285,6 +2412,7 @@ int mlx5dr_action_template_process(struct 
mlx5dr_action_template *at)
                case MLX5DR_ACTION_TYP_TIR:
                case MLX5DR_ACTION_TYP_TBL:
                case MLX5DR_ACTION_TYP_DEST_ROOT:
+               case MLX5DR_ACTION_TYP_DEST_ARRAY:
                case MLX5DR_ACTION_TYP_VPORT:
                case MLX5DR_ACTION_TYP_MISS:
                        /* Hit action */
diff --git a/drivers/net/mlx5/hws/mlx5dr_action.h 
b/drivers/net/mlx5/hws/mlx5dr_action.h
index 104c6880c1..efe07c9d47 100644
--- a/drivers/net/mlx5/hws/mlx5dr_action.h
+++ b/drivers/net/mlx5/hws/mlx5dr_action.h
@@ -151,6 +151,9 @@ struct mlx5dr_action {
                                struct {
                                        struct mlx5dr_devx_obj *devx_obj;
                                } devx_dest;
+                               struct {
+                                       struct mlx5dr_cmd_forward_tbl 
*fw_island;
+                               } dest_array;
                        };
                };
 
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.c 
b/drivers/net/mlx5/hws/mlx5dr_cmd.c
index d20ec7f0c4..3b4545324e 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.c
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.c
@@ -157,18 +157,31 @@ mlx5dr_cmd_set_fte(struct ibv_context *ctx,
                   uint32_t group_id,
                   struct mlx5dr_cmd_set_fte_attr *fte_attr)
 {
-       uint32_t in[MLX5_ST_SZ_DW(set_fte_in) + MLX5_ST_SZ_DW(dest_format)] = 
{0};
        uint32_t out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
        struct mlx5dr_devx_obj *devx_obj;
+       uint32_t dest_entry_sz;
+       uint32_t total_dest_sz;
        void *in_flow_context;
        uint32_t action_flags;
-       void *in_dests;
+       uint8_t *in_dests;
+       uint32_t inlen;
+       uint32_t *in;
+       uint32_t i;
+
+       dest_entry_sz = MLX5_ST_SZ_BYTES(dest_format);
+       total_dest_sz = dest_entry_sz * fte_attr->dests_num;
+       inlen = align((MLX5_ST_SZ_BYTES(set_fte_in) + total_dest_sz), DW_SIZE);
+       in = simple_calloc(1, inlen);
+       if (!in) {
+               rte_errno = ENOMEM;
+               return NULL;
+       }
 
        devx_obj = simple_malloc(sizeof(*devx_obj));
        if (!devx_obj) {
                DR_LOG(ERR, "Failed to allocate memory for fte object");
                rte_errno = ENOMEM;
-               return NULL;
+               goto free_in;
        }
 
        MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
@@ -178,19 +191,45 @@ mlx5dr_cmd_set_fte(struct ibv_context *ctx,
        in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
        MLX5_SET(flow_context, in_flow_context, group_id, group_id);
        MLX5_SET(flow_context, in_flow_context, flow_source, 
fte_attr->flow_source);
+       MLX5_SET(set_fte_in, in, ignore_flow_level, 
fte_attr->ignore_flow_level);
 
        action_flags = fte_attr->action_flags;
        MLX5_SET(flow_context, in_flow_context, action, action_flags);
 
        if (action_flags & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
-               /* Only destination_list_size of size 1 is supported */
-               MLX5_SET(flow_context, in_flow_context, destination_list_size, 
1);
-               in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, 
destination);
-               MLX5_SET(dest_format, in_dests, destination_type, 
fte_attr->destination_type);
-               MLX5_SET(dest_format, in_dests, destination_id, 
fte_attr->destination_id);
+               in_dests = (uint8_t *)MLX5_ADDR_OF(flow_context, 
in_flow_context, destination);
+
+               for (i = 0; i < fte_attr->dests_num; i++) {
+                       struct mlx5dr_cmd_set_fte_dest *dest = 
&fte_attr->dests[i];
+
+                       switch (dest->destination_type) {
+                       case MLX5_FLOW_DESTINATION_TYPE_VPORT:
+                               if (dest->ext_flags & 
MLX5DR_CMD_EXT_DEST_ESW_OWNER_VHCA_ID) {
+                                       MLX5_SET(dest_format, in_dests,
+                                                
destination_eswitch_owner_vhca_id_valid, 1);
+                                       MLX5_SET(dest_format, in_dests,
+                                                
destination_eswitch_owner_vhca_id,
+                                                dest->esw_owner_vhca_id);
+                               }
+                               /* Fall through */
+                       case MLX5_FLOW_DESTINATION_TYPE_TIR:
+                       case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
+                               MLX5_SET(dest_format, in_dests, 
destination_type,
+                                        dest->destination_type);
+                               MLX5_SET(dest_format, in_dests, destination_id,
+                                        dest->destination_id);
+                               break;
+                       default:
+                               rte_errno = EOPNOTSUPP;
+                               goto free_devx;
+                       }
+
+                       in_dests = in_dests + dest_entry_sz;
+               }
+               MLX5_SET(flow_context, in_flow_context, destination_list_size, 
fte_attr->dests_num);
        }
 
-       devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, sizeof(in), out, 
sizeof(out));
+       devx_obj->obj = mlx5_glue->devx_obj_create(ctx, in, inlen, out, 
sizeof(out));
        if (!devx_obj->obj) {
                DR_LOG(ERR, "Failed to create FTE (syndrome: %#x)",
                       mlx5dr_cmd_get_syndrome(out));
@@ -198,10 +237,13 @@ mlx5dr_cmd_set_fte(struct ibv_context *ctx,
                goto free_devx;
        }
 
+       simple_free(in);
        return devx_obj;
 
 free_devx:
        simple_free(devx_obj);
+free_in:
+       simple_free(in);
        return NULL;
 }
 
@@ -1224,6 +1266,9 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
                        caps->eswitch_manager_vport_number =
                        MLX5_GET(query_hca_cap_out, out,
                                 capability.esw_cap.esw_manager_vport_number);
+
+               caps->merged_eswitch = MLX5_GET(query_hca_cap_out, out,
+                                               
capability.esw_cap.merged_eswitch);
        }
 
        ret = mlx5_glue->query_device_ex(ctx, NULL, &attr_ex);
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.h 
b/drivers/net/mlx5/hws/mlx5dr_cmd.h
index ee427c1829..37cb501c98 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.h
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.h
@@ -5,11 +5,25 @@
 #ifndef MLX5DR_CMD_H_
 #define MLX5DR_CMD_H_
 
-struct mlx5dr_cmd_set_fte_attr {
-       uint32_t action_flags;
+enum mlx5dr_cmd_ext_dest_flags {
+       MLX5DR_CMD_EXT_DEST_REFORMAT = 1 << 0,
+       MLX5DR_CMD_EXT_DEST_ESW_OWNER_VHCA_ID = 1 << 1,
+};
+
+struct mlx5dr_cmd_set_fte_dest {
        uint8_t destination_type;
        uint32_t destination_id;
+       enum mlx5dr_cmd_ext_dest_flags ext_flags;
+       uint16_t esw_owner_vhca_id;
+};
+
+struct mlx5dr_cmd_set_fte_attr {
+       uint32_t action_flags;
+       uint8_t ignore_flow_level;
        uint8_t flow_source;
+       uint32_t packet_reformat_id;
+       uint32_t dests_num;
+       struct mlx5dr_cmd_set_fte_dest *dests;
 };
 
 struct mlx5dr_cmd_ft_create_attr {
@@ -210,6 +224,7 @@ struct mlx5dr_cmd_query_caps {
        struct mlx5dr_cmd_query_ft_caps nic_ft;
        struct mlx5dr_cmd_query_ft_caps fdb_ft;
        bool eswitch_manager;
+       uint8_t merged_eswitch;
        uint32_t eswitch_manager_vport_number;
        uint8_t log_header_modify_argument_granularity;
        uint8_t log_header_modify_argument_max_alloc;
diff --git a/drivers/net/mlx5/hws/mlx5dr_debug.c 
b/drivers/net/mlx5/hws/mlx5dr_debug.c
index 48810142a0..7ede8ec43f 100644
--- a/drivers/net/mlx5/hws/mlx5dr_debug.c
+++ b/drivers/net/mlx5/hws/mlx5dr_debug.c
@@ -23,6 +23,7 @@ const char *mlx5dr_debug_action_type_str[] = {
        [MLX5DR_ACTION_TYP_ASO_METER] = "ASO_METER",
        [MLX5DR_ACTION_TYP_ASO_CT] = "ASO_CT",
        [MLX5DR_ACTION_TYP_DEST_ROOT] = "DEST_ROOT",
+       [MLX5DR_ACTION_TYP_DEST_ARRAY] = "DEST_ARRAY",
 };
 
 static_assert(ARRAY_SIZE(mlx5dr_debug_action_type_str) == 
MLX5DR_ACTION_TYP_MAX,
diff --git a/drivers/net/mlx5/hws/mlx5dr_table.c 
b/drivers/net/mlx5/hws/mlx5dr_table.c
index c26b22c248..c8d60e68f3 100644
--- a/drivers/net/mlx5/hws/mlx5dr_table.c
+++ b/drivers/net/mlx5/hws/mlx5dr_table.c
@@ -22,6 +22,7 @@ mlx5dr_table_up_default_fdb_miss_tbl(struct mlx5dr_table *tbl)
        struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
        struct mlx5dr_cmd_set_fte_attr fte_attr = {0};
        struct mlx5dr_cmd_forward_tbl *default_miss;
+       struct mlx5dr_cmd_set_fte_dest dest = {0};
        struct mlx5dr_context *ctx = tbl->ctx;
        uint8_t tbl_type = tbl->type;
 
@@ -37,9 +38,11 @@ mlx5dr_table_up_default_fdb_miss_tbl(struct mlx5dr_table 
*tbl)
        ft_attr.level = tbl->ctx->caps->fdb_ft.max_level; /* The last level */
        ft_attr.rtc_valid = false;
 
+       dest.destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
+       dest.destination_id = ctx->caps->eswitch_manager_vport_number;
        fte_attr.action_flags = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-       fte_attr.destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
-       fte_attr.destination_id = ctx->caps->eswitch_manager_vport_number;
+       fte_attr.dests_num = 1;
+       fte_attr.dests = &dest;
 
        default_miss = 
mlx5dr_cmd_forward_tbl_create(mlx5dr_context_get_local_ibv(ctx),
                                                     &ft_attr, &fte_attr);
-- 
2.20.0

Reply via email to