@@ -291,6 +291,12 @@
#define MAX_ACTIONS_DATA_IN_HEADER_MODIFY 512
+/* Alias FT id passed to the ALLOW_OTHER_VHCA_ACCESS & CREATE_GENERAL_OBJECT
+ * commands should have the following format:
+ * {table_type: 8bits, table_id: 24bits}.
+ */
+#define FT_ID_FT_TYPE_OFFSET 24
+
/* Completion mode. */
enum mlx5_completion_mode {
MLX5_COMP_ONLY_ERR = 0x0,
@@ -96,6 +96,8 @@ struct mlx5dr_context_attr {
size_t initial_log_ste_memory; /* Currently not in use */
/* Optional PD used for allocating res ources */
struct ibv_pd *pd;
+ /* Optional other ctx for resources allocation, all objects will be created on it */
+ struct ibv_context *shared_ibv_ctx;
};
struct mlx5dr_table_attr {
@@ -1147,6 +1147,7 @@ mlx5dr_action_create_reformat_root(struct mlx5dr_action *action,
{
enum mlx5dv_flow_table_type ft_type = 0; /*fix compilation warn*/
uint32_t verb_reformat_type = 0;
+ struct ibv_context *ibv_ctx;
int ret;
/* Convert action to FT type and verbs reformat type */
@@ -1157,8 +1158,9 @@ mlx5dr_action_create_reformat_root(struct mlx5dr_action *action,
mlx5dr_action_conv_reformat_to_verbs(action->type, &verb_reformat_type);
/* Create the reformat type for root table */
+ ibv_ctx = mlx5dr_context_get_local_ibv(action->ctx);
action->flow_action =
- mlx5_glue->dv_create_flow_action_packet_reformat_root(action->ctx->ibv_ctx,
+ mlx5_glue->dv_create_flow_action_packet_reformat_root(ibv_ctx,
data_sz,
data,
verb_reformat_type,
@@ -1496,14 +1498,17 @@ mlx5dr_action_create_modify_header_root(struct mlx5dr_action *action,
__be64 *actions)
{
enum mlx5dv_flow_table_type ft_type = 0;
+ struct ibv_context *local_ibv_ctx;
int ret;
ret = mlx5dr_action_conv_flags_to_ft_type(action->flags, &ft_type);
if (ret)
return rte_errno;
+ local_ibv_ctx = mlx5dr_context_get_local_ibv(action->ctx);
+
action->flow_action =
- mlx5_glue->dv_create_flow_action_modify_header_root(action->ctx->ibv_ctx,
+ mlx5_glue->dv_create_flow_action_modify_header_root(local_ibv_ctx,
actions_sz,
(uint64_t *)actions,
ft_type);
@@ -217,18 +217,23 @@ void mlx5dr_cmd_set_attr_connect_miss_tbl(struct mlx5dr_context *ctx,
{
struct mlx5dr_devx_obj *default_miss_tbl;
- if (type != MLX5DR_TABLE_TYPE_FDB)
+ if (type != MLX5DR_TABLE_TYPE_FDB && !mlx5dr_context_shared_gvmi_used(ctx))
return;
- default_miss_tbl = ctx->common_res[type].default_miss->ft;
- if (!default_miss_tbl) {
- assert(false);
- return;
- }
ft_attr->modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION;
ft_attr->type = fw_ft_type;
ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
- ft_attr->table_miss_id = default_miss_tbl->id;
+
+ if (type == MLX5DR_TABLE_TYPE_FDB) {
+ default_miss_tbl = ctx->common_res[type].default_miss->ft;
+ if (!default_miss_tbl) {
+ assert(false);
+ return;
+ }
+ ft_attr->table_miss_id = default_miss_tbl->id;
+ } else {
+ ft_attr->table_miss_id = ctx->gvmi_res[type].aliased_end_ft->id;
+ }
}
struct mlx5dr_devx_obj *
@@ -11,6 +11,8 @@ struct mlx5dr_cmd_ft_create_attr {
bool rtc_valid;
};
+#define ACCESS_KEY_LEN 32
+
struct mlx5dr_cmd_ft_modify_attr {
uint8_t type;
uint32_t rtc_id_0;
@@ -50,7 +52,7 @@ struct mlx5dr_cmd_alias_obj_create_attr {
uint32_t obj_id;
uint16_t vhca_id;
uint16_t obj_type;
- uint8_t access_key[32];
+ uint8_t access_key[ACCESS_KEY_LEN];
};
struct mlx5dr_cmd_stc_create_attr {
@@ -134,7 +136,7 @@ struct mlx5dr_cmd_sq_create_attr {
struct mlx5dr_cmd_allow_other_vhca_access_attr {
uint16_t obj_type;
uint32_t obj_id;
- uint8_t access_key[32];
+ uint8_t access_key[ACCESS_KEY_LEN];
};
struct mlx5dr_cmd_query_ft_caps {
@@ -178,6 +180,7 @@ struct mlx5dr_cmd_query_caps {
uint32_t trivial_match_definer;
uint32_t vhca_id;
bool cross_vhca_resources;
+ uint32_t shared_vhca_id;
char fw_ver[64];
};
@@ -178,6 +178,36 @@ static void mlx5dr_context_uninit_hws(struct mlx5dr_context *ctx)
mlx5dr_context_uninit_pd(ctx);
}
+static int mlx5dr_context_init_shared_ctx(struct mlx5dr_context *ctx,
+ struct ibv_context *ibv_ctx,
+ struct mlx5dr_context_attr *attr)
+{
+ struct mlx5dr_cmd_query_caps shared_caps = {0};
+ int ret;
+
+ if (!attr->shared_ibv_ctx) {
+ ctx->ibv_ctx = ibv_ctx;
+ } else {
+ ctx->ibv_ctx = attr->shared_ibv_ctx;
+ ctx->local_ibv_ctx = ibv_ctx;
+ ret = mlx5dr_cmd_query_caps(attr->shared_ibv_ctx, &shared_caps);
+ if (ret || !shared_caps.cross_vhca_resources) {
+ DR_LOG(INFO, "No cross_vhca_resources cap for shared ibv");
+ rte_errno = ENOTSUP;
+ return rte_errno;
+ }
+ ctx->caps->shared_vhca_id = shared_caps.vhca_id;
+ }
+
+ if (ctx->local_ibv_ctx && !ctx->caps->cross_vhca_resources) {
+ DR_LOG(INFO, "No cross_vhca_resources cap for local ibv");
+ rte_errno = ENOTSUP;
+ return rte_errno;
+ }
+
+ return 0;
+}
+
struct mlx5dr_context *mlx5dr_context_open(struct ibv_context *ibv_ctx,
struct mlx5dr_context_attr *attr)
{
@@ -190,7 +220,6 @@ struct mlx5dr_context *mlx5dr_context_open(struct ibv_context *ibv_ctx,
return NULL;
}
- ctx->ibv_ctx = ibv_ctx;
pthread_spin_init(&ctx->ctrl_lock, PTHREAD_PROCESS_PRIVATE);
ctx->caps = simple_calloc(1, sizeof(*ctx->caps));
@@ -201,6 +230,9 @@ struct mlx5dr_context *mlx5dr_context_open(struct ibv_context *ibv_ctx,
if (ret)
goto free_caps;
+ if (mlx5dr_context_init_shared_ctx(ctx, ibv_ctx, attr))
+ goto free_caps;
+
ret = mlx5dr_context_init_hws(ctx, attr);
if (ret)
goto free_caps;
@@ -22,13 +22,22 @@ struct mlx5dr_context_common_res {
struct mlx5dr_cmd_forward_tbl *default_miss;
};
+struct mlx5dr_context_shared_gvmi_res {
+ struct mlx5dr_devx_obj *end_ft;
+ struct mlx5dr_devx_obj *aliased_end_ft;
+ uint32_t refcount;
+};
+
struct mlx5dr_context {
struct ibv_context *ibv_ctx;
+ /* When local_ibv_ctx is not NULL means we are using shared_ibv for resources */
+ struct ibv_context *local_ibv_ctx;
struct mlx5dr_cmd_query_caps *caps;
struct ibv_pd *pd;
uint32_t pd_num;
struct mlx5dr_pool *stc_pool[MLX5DR_TABLE_TYPE_MAX];
struct mlx5dr_context_common_res common_res[MLX5DR_TABLE_TYPE_MAX];
+ struct mlx5dr_context_shared_gvmi_res gvmi_res[MLX5DR_TABLE_TYPE_MAX];
struct mlx5dr_pattern_cache *pattern_cache;
pthread_spinlock_t ctrl_lock;
enum mlx5dr_context_flags flags;
@@ -37,4 +46,17 @@ struct mlx5dr_context {
LIST_HEAD(table_head, mlx5dr_table) head;
};
+static inline bool mlx5dr_context_shared_gvmi_used(struct mlx5dr_context *ctx)
+{
+ return ctx->local_ibv_ctx ? true : false;
+}
+
+static inline struct ibv_context *
+mlx5dr_context_get_local_ibv(struct mlx5dr_context *ctx)
+{
+ if (mlx5dr_context_shared_gvmi_used(ctx))
+ return ctx->local_ibv_ctx;
+
+ return ctx->ibv_ctx;
+}
#endif /* MLX5DR_CONTEXT_H_ */
@@ -405,7 +405,7 @@ static int mlx5dr_debug_dump_context_info(FILE *f, struct mlx5dr_context *ctx)
MLX5DR_DEBUG_RES_TYPE_CONTEXT,
(uint64_t)(uintptr_t)ctx,
ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT,
- mlx5_glue->get_device_name(ctx->ibv_ctx->device),
+ mlx5_glue->get_device_name(mlx5dr_context_get_local_ibv(ctx)->device),
DEBUG_VERSION);
if (ret < 0) {
rte_errno = EINVAL;
@@ -18,6 +18,7 @@
#endif
#include <rte_flow.h>
#include <rte_gtp.h>
+#include <rte_random.h>
#include "mlx5_prm.h"
#include "mlx5_glue.h"
@@ -19,31 +19,20 @@ static uint8_t mlx5dr_matcher_rules_to_tbl_depth(uint8_t log_num_of_rules)
return RTE_MIN(log_num_of_rules, MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH);
}
-static int mlx5dr_matcher_create_end_ft(struct mlx5dr_matcher *matcher)
-{
- struct mlx5dr_table *tbl = matcher->tbl;
-
- matcher->end_ft = mlx5dr_table_create_default_ft(tbl);
- if (!matcher->end_ft) {
- DR_LOG(ERR, "Failed to create matcher end flow table");
- return rte_errno;
- }
- return 0;
-}
-
static void mlx5dr_matcher_destroy_end_ft(struct mlx5dr_matcher *matcher)
{
mlx5dr_table_destroy_default_ft(matcher->tbl, matcher->end_ft);
}
-static int mlx5dr_matcher_free_rtc_pointing(uint32_t fw_ft_type,
+static int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx,
+ uint32_t fw_ft_type,
enum mlx5dr_table_type type,
struct mlx5dr_devx_obj *devx_obj)
{
struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
int ret;
- if (type != MLX5DR_TABLE_TYPE_FDB)
+ if (type != MLX5DR_TABLE_TYPE_FDB && !mlx5dr_context_shared_gvmi_used(ctx))
return 0;
ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
@@ -60,6 +49,136 @@ static int mlx5dr_matcher_free_rtc_pointing(uint32_t fw_ft_type,
return 0;
}
+static int mlx5dr_matcher_shared_point_end_ft(struct mlx5dr_matcher *matcher)
+{
+ struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
+ int ret;
+
+ mlx5dr_cmd_set_attr_connect_miss_tbl(matcher->tbl->ctx,
+ matcher->tbl->fw_ft_type,
+ matcher->tbl->type,
+ &ft_attr);
+
+ ret = mlx5dr_cmd_flow_table_modify(matcher->end_ft, &ft_attr);
+ if (ret) {
+ DR_LOG(ERR, "Failed to connect new matcher to default miss alias RTC");
+ return ret;
+ }
+
+ ret = mlx5dr_matcher_free_rtc_pointing(matcher->tbl->ctx,
+ matcher->tbl->fw_ft_type,
+ matcher->tbl->type,
+ matcher->end_ft);
+
+ return ret;
+}
+
+static int mlx5dr_matcher_shared_create_alias_rtc(struct mlx5dr_matcher *matcher)
+{
+ struct mlx5dr_context *ctx = matcher->tbl->ctx;
+ int ret;
+
+ ret = mlx5dr_matcher_create_aliased_obj(ctx,
+ ctx->ibv_ctx,
+ ctx->local_ibv_ctx,
+ ctx->caps->shared_vhca_id,
+ matcher->match_ste.rtc_0->id,
+ MLX5_GENERAL_OBJ_TYPE_RTC,
+ &matcher->match_ste.aliased_rtc_0);
+ if (ret) {
+ DR_LOG(ERR, "Failed to allocate alias RTC");
+ return ret;
+ }
+ return 0;
+}
+
+static int mlx5dr_matcher_create_init_shared(struct mlx5dr_matcher *matcher)
+{
+ if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx))
+ return 0;
+
+ if (mlx5dr_matcher_shared_point_end_ft(matcher)) {
+ DR_LOG(ERR, "Failed to point shared matcher end flow table");
+ return rte_errno;
+ }
+
+ if (mlx5dr_matcher_shared_create_alias_rtc(matcher)) {
+ DR_LOG(ERR, "Failed to create alias RTC");
+ return rte_errno;
+ }
+
+ return 0;
+}
+
+static void mlx5dr_matcher_create_uninit_shared(struct mlx5dr_matcher *matcher)
+{
+ if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx))
+ return;
+
+ if (matcher->match_ste.aliased_rtc_0) {
+ mlx5dr_cmd_destroy_obj(matcher->match_ste.aliased_rtc_0);
+ matcher->match_ste.aliased_rtc_0 = NULL;
+ }
+}
+
+static int mlx5dr_matcher_create_end_ft(struct mlx5dr_matcher *matcher)
+{
+ struct mlx5dr_table *tbl = matcher->tbl;
+
+ matcher->end_ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl);
+ if (!matcher->end_ft) {
+ DR_LOG(ERR, "Failed to create matcher end flow table");
+ return rte_errno;
+ }
+ return 0;
+}
+
+static uint32_t
+mlx5dr_matcher_connect_get_rtc0(struct mlx5dr_matcher *matcher)
+{
+ if (!matcher->match_ste.aliased_rtc_0)
+ return matcher->match_ste.rtc_0->id;
+ else
+ return matcher->match_ste.aliased_rtc_0->id;
+}
+
+/* The function updates tbl->local_ft to the first RTC or 0 if no more matchers */
+static int mlx5dr_matcher_shared_update_local_ft(struct mlx5dr_table *tbl)
+{
+ struct mlx5dr_cmd_ft_modify_attr cur_ft_attr = {0};
+ struct mlx5dr_matcher *first_matcher;
+ int ret;
+
+ if (!mlx5dr_context_shared_gvmi_used(tbl->ctx))
+ return 0;
+
+ first_matcher = LIST_FIRST(&tbl->head);
+ if (!first_matcher) {
+ /* local ft no longer points to any RTC, drop refcount */
+ ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx,
+ tbl->fw_ft_type,
+ tbl->type,
+ tbl->local_ft);
+ if (ret)
+ DR_LOG(ERR, "Failed to clear local FT to prev alias RTC");
+
+ return ret;
+ }
+
+ /* point local_ft to the first RTC */
+ cur_ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID;
+ cur_ft_attr.type = tbl->fw_ft_type;
+ cur_ft_attr.rtc_id_0 = mlx5dr_matcher_connect_get_rtc0(first_matcher);
+
+ ret = mlx5dr_cmd_flow_table_modify(tbl->local_ft, &cur_ft_attr);
+ if (ret) {
+ DR_LOG(ERR, "Failed to point local FT to alias RTC");
+ return ret;
+ }
+
+ return 0;
+}
+
static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
{
struct mlx5dr_cmd_ft_modify_attr ft_attr = {0};
@@ -121,6 +240,12 @@ static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher)
goto remove_from_list;
}
+ ret = mlx5dr_matcher_shared_update_local_ft(tbl);
+ if (ret) {
+ DR_LOG(ERR, "Failed to update local_ft anchor in shared table");
+ goto remove_from_list;
+ }
+
return 0;
remove_from_list:
@@ -174,7 +299,8 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
if (!next) {
/* ft no longer points to any RTC, drop refcount */
- ret = mlx5dr_matcher_free_rtc_pointing(tbl->fw_ft_type,
+ ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx,
+ tbl->fw_ft_type,
tbl->type,
prev_ft);
if (ret) {
@@ -183,6 +309,12 @@ static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher)
}
}
+ ret = mlx5dr_matcher_shared_update_local_ft(tbl);
+ if (ret) {
+ DR_LOG(ERR, "Failed to update local_ft in shared table");
+ return ret;
+ }
+
return 0;
}
@@ -206,6 +338,49 @@ static void mlx5dr_matcher_set_rtc_attr_sz(struct mlx5dr_matcher *matcher,
}
}
+int mlx5dr_matcher_create_aliased_obj(struct mlx5dr_context *ctx,
+ struct ibv_context *ibv_owner,
+ struct ibv_context *ibv_allowed,
+ uint16_t vhca_id_to_be_accessed,
+ uint32_t aliased_object_id,
+ uint16_t object_type,
+ struct mlx5dr_devx_obj **obj)
+{
+ struct mlx5dr_cmd_allow_other_vhca_access_attr allow_attr = {0};
+ struct mlx5dr_cmd_alias_obj_create_attr alias_attr = {0};
+ char key[ACCESS_KEY_LEN];
+ int ret;
+ int i;
+
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return 0;
+
+ for (i = 0; i < ACCESS_KEY_LEN; i++)
+ key[i] = rte_rand() & 0xFF;
+
+ memcpy(allow_attr.access_key, key, ACCESS_KEY_LEN);
+ allow_attr.obj_type = object_type;
+ allow_attr.obj_id = aliased_object_id;
+
+ ret = mlx5dr_cmd_allow_other_vhca_access(ibv_owner, &allow_attr);
+ if (ret) {
+ DR_LOG(ERR, "Failed to allow RTC to be aliased");
+ return ret;
+ }
+
+ memcpy(alias_attr.access_key, key, ACCESS_KEY_LEN);
+ alias_attr.obj_id = aliased_object_id;
+ alias_attr.obj_type = object_type;
+ alias_attr.vhca_id = vhca_id_to_be_accessed;
+ *obj = mlx5dr_cmd_alias_obj_create(ibv_allowed, &alias_attr);
+ if (!*obj) {
+ DR_LOG(ERR, "Failed to create alias object");
+ return rte_errno;
+ }
+
+ return 0;
+}
+
static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher,
bool is_match_rtc)
{
@@ -573,13 +748,20 @@ static int mlx5dr_matcher_create_and_connect(struct mlx5dr_matcher *matcher)
if (ret)
goto destroy_end_ft;
+ /* Allocate and set shared resources */
+ ret = mlx5dr_matcher_create_init_shared(matcher);
+ if (ret)
+ goto destroy_rtc;
+
/* Connect the matcher to the matcher list */
ret = mlx5dr_matcher_connect(matcher);
if (ret)
- goto destroy_rtc;
+ goto destroy_shared;
return 0;
+destroy_shared:
+ mlx5dr_matcher_create_uninit_shared(matcher);
destroy_rtc:
mlx5dr_matcher_destroy_rtc(matcher, true);
destroy_end_ft:
@@ -594,6 +776,7 @@ static int mlx5dr_matcher_create_and_connect(struct mlx5dr_matcher *matcher)
static void mlx5dr_matcher_destroy_and_disconnect(struct mlx5dr_matcher *matcher)
{
mlx5dr_matcher_disconnect(matcher);
+ mlx5dr_matcher_create_uninit_shared(matcher);
mlx5dr_matcher_destroy_rtc(matcher, true);
mlx5dr_matcher_destroy_end_ft(matcher);
mlx5dr_matcher_unbind_at(matcher);
@@ -766,7 +949,8 @@ static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher)
attr.priority = matcher->attr.priority;
matcher->dv_matcher =
- mlx5_glue->dv_create_flow_matcher_root(ctx->ibv_ctx, &attr);
+ mlx5_glue->dv_create_flow_matcher_root(mlx5dr_context_get_local_ibv(ctx),
+ &attr);
if (!matcher->dv_matcher) {
DR_LOG(ERR, "Failed to create DV flow matcher");
rte_errno = errno;
@@ -42,6 +42,8 @@ struct mlx5dr_matcher_match_ste {
struct mlx5dr_devx_obj *rtc_0;
struct mlx5dr_devx_obj *rtc_1;
struct mlx5dr_pool *pool;
+ /* Currently not support FDB aliased */
+ struct mlx5dr_devx_obj *aliased_rtc_0;
};
struct mlx5dr_matcher_action_ste {
@@ -73,4 +75,11 @@ int mlx5dr_matcher_conv_items_to_prm(uint64_t *match_buf,
uint8_t *match_criteria,
bool is_value);
+int mlx5dr_matcher_create_aliased_obj(struct mlx5dr_context *ctx,
+ struct ibv_context *ibv_owner,
+ struct ibv_context *ibv_allowed,
+ uint16_t vhca_id_to_be_accessed,
+ uint32_t aliased_object_id,
+ uint16_t object_type,
+ struct mlx5dr_devx_obj **obj);
#endif /* MLX5DR_MATCHER_H_ */
@@ -40,7 +40,8 @@ mlx5dr_table_up_default_fdb_miss_tbl(struct mlx5dr_table *tbl)
assert(ctx->caps->eswitch_manager);
vport = ctx->caps->eswitch_manager_vport_number;
- default_miss = mlx5dr_cmd_miss_ft_create(ctx->ibv_ctx, &ft_attr, vport);
+ default_miss = mlx5dr_cmd_miss_ft_create(mlx5dr_context_get_local_ibv(ctx),
+ &ft_attr, vport);
if (!default_miss) {
DR_LOG(ERR, "Failed to default miss table type: 0x%x", tbl_type);
return rte_errno;
@@ -96,7 +97,8 @@ mlx5dr_table_connect_to_default_miss_tbl(struct mlx5dr_table *tbl,
}
struct mlx5dr_devx_obj *
-mlx5dr_table_create_default_ft(struct mlx5dr_table *tbl)
+mlx5dr_table_create_default_ft(struct ibv_context *ibv,
+ struct mlx5dr_table *tbl)
{
struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
struct mlx5dr_devx_obj *ft_obj;
@@ -104,7 +106,7 @@ mlx5dr_table_create_default_ft(struct mlx5dr_table *tbl)
mlx5dr_table_init_next_ft_attr(tbl, &ft_attr);
- ft_obj = mlx5dr_cmd_flow_table_create(tbl->ctx->ibv_ctx, &ft_attr);
+ ft_obj = mlx5dr_cmd_flow_table_create(ibv, &ft_attr);
if (ft_obj && tbl->type == MLX5DR_TABLE_TYPE_FDB) {
/* Take/create ref over the default miss */
ret = mlx5dr_table_up_default_fdb_miss_tbl(tbl);
@@ -128,6 +130,171 @@ mlx5dr_table_create_default_ft(struct mlx5dr_table *tbl)
return NULL;
}
+static int
+mlx5dr_table_init_check_hws_support(struct mlx5dr_context *ctx,
+ struct mlx5dr_table *tbl)
+{
+ if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) {
+ DR_LOG(ERR, "HWS not supported, cannot create mlx5dr_table");
+ rte_errno = EOPNOTSUPP;
+ return rte_errno;
+ }
+
+ if (mlx5dr_context_shared_gvmi_used(ctx) && tbl->type == MLX5DR_TABLE_TYPE_FDB) {
+ DR_LOG(ERR, "FDB with shared port resources is not supported");
+ rte_errno = EOPNOTSUPP;
+ return rte_errno;
+ }
+
+ return 0;
+}
+
+static int
+mlx5dr_table_shared_gvmi_resource_create(struct mlx5dr_context *ctx,
+ enum mlx5dr_table_type type,
+ struct mlx5dr_context_shared_gvmi_res *gvmi_res)
+{
+ struct mlx5dr_cmd_ft_create_attr ft_attr = {0};
+ uint32_t calculated_ft_id;
+ int ret;
+
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return 0;
+
+ ft_attr.type = mlx5dr_table_get_res_fw_ft_type(type, false);
+ ft_attr.level = ctx->caps->nic_ft.max_level - 1;
+ ft_attr.rtc_valid = true;
+
+ gvmi_res->end_ft =
+ mlx5dr_cmd_flow_table_create(mlx5dr_context_get_local_ibv(ctx),
+ &ft_attr);
+ if (!gvmi_res->end_ft) {
+ DR_LOG(ERR, "Failed to create end-ft");
+ return rte_errno;
+ }
+
+ calculated_ft_id =
+ mlx5dr_table_get_res_fw_ft_type(type, false) << FT_ID_FT_TYPE_OFFSET;
+ calculated_ft_id |= gvmi_res->end_ft->id;
+
+ /* create alias to that FT */
+ ret = mlx5dr_matcher_create_aliased_obj(ctx,
+ ctx->local_ibv_ctx,
+ ctx->ibv_ctx,
+ ctx->caps->vhca_id,
+ calculated_ft_id,
+ MLX5_GENERAL_OBJ_TYPE_FT_ALIAS,
+ &gvmi_res->aliased_end_ft);
+ if (ret) {
+ DR_LOG(ERR, "Failed to create alias end-ft");
+ goto free_end_ft;
+ }
+
+ return 0;
+
+free_end_ft:
+ mlx5dr_cmd_destroy_obj(gvmi_res->end_ft);
+
+ return rte_errno;
+}
+
+static void
+mlx5dr_table_shared_gvmi_resourse_destroy(struct mlx5dr_context *ctx,
+ struct mlx5dr_context_shared_gvmi_res *gvmi_res)
+{
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return;
+
+ if (gvmi_res->aliased_end_ft) {
+ mlx5dr_cmd_destroy_obj(gvmi_res->aliased_end_ft);
+ gvmi_res->aliased_end_ft = NULL;
+ }
+ if (gvmi_res->end_ft) {
+ mlx5dr_cmd_destroy_obj(gvmi_res->end_ft);
+ gvmi_res->end_ft = NULL;
+ }
+}
+
+/* called under spinlock ctx->ctrl_lock */
+static struct mlx5dr_context_shared_gvmi_res *
+mlx5dr_table_get_shared_gvmi_res(struct mlx5dr_context *ctx, enum mlx5dr_table_type type)
+{
+ int ret;
+
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return NULL;
+
+ if (ctx->gvmi_res[type].aliased_end_ft) {
+ ctx->gvmi_res[type].refcount++;
+ return &ctx->gvmi_res[type];
+ }
+
+ ret = mlx5dr_table_shared_gvmi_resource_create(ctx, type, &ctx->gvmi_res[type]);
+ if (ret) {
+ DR_LOG(ERR, "Failed to create shared gvmi res for type: %d", type);
+ goto out;
+ }
+
+ ctx->gvmi_res[type].refcount = 1;
+
+ return &ctx->gvmi_res[type];
+
+out:
+ return NULL;
+}
+
+/* called under spinlock ctx->ctrl_lock */
+static void mlx5dr_table_put_shared_gvmi_res(struct mlx5dr_table *tbl)
+{
+ struct mlx5dr_context *ctx = tbl->ctx;
+
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return;
+
+ if (--ctx->gvmi_res[tbl->type].refcount)
+ return;
+
+ mlx5dr_table_shared_gvmi_resourse_destroy(ctx, &ctx->gvmi_res[tbl->type]);
+}
+
+static void mlx5dr_table_uninit_shared_ctx_res(struct mlx5dr_table *tbl)
+{
+ struct mlx5dr_context *ctx = tbl->ctx;
+
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return;
+
+ mlx5dr_cmd_destroy_obj(tbl->local_ft);
+
+ mlx5dr_table_put_shared_gvmi_res(tbl);
+}
+
+/* called under spin_lock ctx->ctrl_lock */
+static int mlx5dr_table_init_shared_ctx_res(struct mlx5dr_context *ctx, struct mlx5dr_table *tbl)
+{
+ if (!mlx5dr_context_shared_gvmi_used(ctx))
+ return 0;
+
+ /* create local-ft for root access */
+ tbl->local_ft =
+ mlx5dr_table_create_default_ft(mlx5dr_context_get_local_ibv(ctx), tbl);
+ if (!tbl->local_ft) {
+ DR_LOG(ERR, "Failed to create local-ft");
+ return rte_errno;
+ }
+
+ if (!mlx5dr_table_get_shared_gvmi_res(tbl->ctx, tbl->type)) {
+ DR_LOG(ERR, "Failed to shared gvmi resources");
+ goto clean_local_ft;
+ }
+
+ return 0;
+
+clean_local_ft:
+ mlx5dr_table_destroy_default_ft(tbl, tbl->local_ft);
+ return rte_errno;
+}
+
void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
struct mlx5dr_devx_obj *ft_obj)
{
@@ -143,11 +310,9 @@ static int mlx5dr_table_init(struct mlx5dr_table *tbl)
if (mlx5dr_table_is_root(tbl))
return 0;
- if (!(tbl->ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) {
- DR_LOG(ERR, "HWS not supported, cannot create mlx5dr_table");
- rte_errno = EOPNOTSUPP;
- return rte_errno;
- }
+ ret = mlx5dr_table_init_check_hws_support(ctx, tbl);
+ if (ret)
+ return ret;
switch (tbl->type) {
case MLX5DR_TABLE_TYPE_NIC_RX:
@@ -165,7 +330,7 @@ static int mlx5dr_table_init(struct mlx5dr_table *tbl)
}
pthread_spin_lock(&ctx->ctrl_lock);
- tbl->ft = mlx5dr_table_create_default_ft(tbl);
+ tbl->ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl);
if (!tbl->ft) {
DR_LOG(ERR, "Failed to create flow table devx object");
pthread_spin_unlock(&ctx->ctrl_lock);
@@ -175,10 +340,17 @@ static int mlx5dr_table_init(struct mlx5dr_table *tbl)
ret = mlx5dr_action_get_default_stc(ctx, tbl->type);
if (ret)
goto tbl_destroy;
+
+ ret = mlx5dr_table_init_shared_ctx_res(ctx, tbl);
+ if (ret)
+ goto put_stc;
+
pthread_spin_unlock(&ctx->ctrl_lock);
return 0;
+put_stc:
+ mlx5dr_action_put_default_stc(ctx, tbl->type);
tbl_destroy:
mlx5dr_table_destroy_default_ft(tbl, tbl->ft);
pthread_spin_unlock(&ctx->ctrl_lock);
@@ -192,6 +364,7 @@ static void mlx5dr_table_uninit(struct mlx5dr_table *tbl)
pthread_spin_lock(&tbl->ctx->ctrl_lock);
mlx5dr_action_put_default_stc(tbl->ctx, tbl->type);
mlx5dr_table_destroy_default_ft(tbl, tbl->ft);
+ mlx5dr_table_uninit_shared_ctx_res(tbl);
pthread_spin_unlock(&tbl->ctx->ctrl_lock);
}
@@ -10,6 +10,7 @@
struct mlx5dr_table {
struct mlx5dr_context *ctx;
struct mlx5dr_devx_obj *ft;
+ struct mlx5dr_devx_obj *local_ft;
enum mlx5dr_table_type type;
uint32_t fw_ft_type;
uint32_t level;
@@ -37,7 +38,8 @@ static inline bool mlx5dr_table_is_root(struct mlx5dr_table *tbl)
return (tbl->level == MLX5DR_ROOT_LEVEL);
}
-struct mlx5dr_devx_obj *mlx5dr_table_create_default_ft(struct mlx5dr_table *tbl);
+struct mlx5dr_devx_obj *mlx5dr_table_create_default_ft(struct ibv_context *ibv,
+ struct mlx5dr_table *tbl);
void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl,
struct mlx5dr_devx_obj *ft_obj);