1394cc7baSAlex Vesker /* SPDX-License-Identifier: BSD-3-Clause 2394cc7baSAlex Vesker * Copyright (c) 2022 NVIDIA Corporation & Affiliates 3394cc7baSAlex Vesker */ 4394cc7baSAlex Vesker 5394cc7baSAlex Vesker #include "mlx5dr_internal.h" 6394cc7baSAlex Vesker 7394cc7baSAlex Vesker static void mlx5dr_table_init_next_ft_attr(struct mlx5dr_table *tbl, 8394cc7baSAlex Vesker struct mlx5dr_cmd_ft_create_attr *ft_attr) 9394cc7baSAlex Vesker { 10394cc7baSAlex Vesker ft_attr->type = tbl->fw_ft_type; 11394cc7baSAlex Vesker if (tbl->type == MLX5DR_TABLE_TYPE_FDB) 12394cc7baSAlex Vesker ft_attr->level = tbl->ctx->caps->fdb_ft.max_level - 1; 13394cc7baSAlex Vesker else 14394cc7baSAlex Vesker ft_attr->level = tbl->ctx->caps->nic_ft.max_level - 1; 15394cc7baSAlex Vesker ft_attr->rtc_valid = true; 16394cc7baSAlex Vesker } 17394cc7baSAlex Vesker 18394cc7baSAlex Vesker /* Call this under ctx->ctrl_lock */ 19394cc7baSAlex Vesker static int 20394cc7baSAlex Vesker mlx5dr_table_up_default_fdb_miss_tbl(struct mlx5dr_table *tbl) 21394cc7baSAlex Vesker { 22394cc7baSAlex Vesker struct mlx5dr_cmd_ft_create_attr ft_attr = {0}; 23e1df1578SHamdan Igbaria struct mlx5dr_cmd_set_fte_attr fte_attr = {0}; 24394cc7baSAlex Vesker struct mlx5dr_cmd_forward_tbl *default_miss; 25eefaf43dSShun Hao struct mlx5dr_cmd_set_fte_dest dest = {0}; 26394cc7baSAlex Vesker struct mlx5dr_context *ctx = tbl->ctx; 27394cc7baSAlex Vesker uint8_t tbl_type = tbl->type; 28394cc7baSAlex Vesker 29394cc7baSAlex Vesker if (tbl->type != MLX5DR_TABLE_TYPE_FDB) 30394cc7baSAlex Vesker return 0; 31394cc7baSAlex Vesker 32394cc7baSAlex Vesker if (ctx->common_res[tbl_type].default_miss) { 33394cc7baSAlex Vesker ctx->common_res[tbl_type].default_miss->refcount++; 34394cc7baSAlex Vesker return 0; 35394cc7baSAlex Vesker } 36394cc7baSAlex Vesker 37394cc7baSAlex Vesker ft_attr.type = tbl->fw_ft_type; 38394cc7baSAlex Vesker ft_attr.level = tbl->ctx->caps->fdb_ft.max_level; /* The last level */ 39394cc7baSAlex Vesker ft_attr.rtc_valid = false; 40394cc7baSAlex Vesker 41eefaf43dSShun Hao dest.destination_type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 42eefaf43dSShun Hao dest.destination_id = ctx->caps->eswitch_manager_vport_number; 43e1df1578SHamdan Igbaria fte_attr.action_flags = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 44eefaf43dSShun Hao fte_attr.dests_num = 1; 45eefaf43dSShun Hao fte_attr.dests = &dest; 46e1df1578SHamdan Igbaria 47e1df1578SHamdan Igbaria default_miss = mlx5dr_cmd_forward_tbl_create(mlx5dr_context_get_local_ibv(ctx), 48e1df1578SHamdan Igbaria &ft_attr, &fte_attr); 49394cc7baSAlex Vesker if (!default_miss) { 50394cc7baSAlex Vesker DR_LOG(ERR, "Failed to default miss table type: 0x%x", tbl_type); 51394cc7baSAlex Vesker return rte_errno; 52394cc7baSAlex Vesker } 53394cc7baSAlex Vesker 54394cc7baSAlex Vesker ctx->common_res[tbl_type].default_miss = default_miss; 55394cc7baSAlex Vesker ctx->common_res[tbl_type].default_miss->refcount++; 56394cc7baSAlex Vesker return 0; 57394cc7baSAlex Vesker } 58394cc7baSAlex Vesker 59394cc7baSAlex Vesker /* Called under pthread_spin_lock(&ctx->ctrl_lock) */ 60394cc7baSAlex Vesker static void mlx5dr_table_down_default_fdb_miss_tbl(struct mlx5dr_table *tbl) 61394cc7baSAlex Vesker { 62394cc7baSAlex Vesker struct mlx5dr_cmd_forward_tbl *default_miss; 63394cc7baSAlex Vesker struct mlx5dr_context *ctx = tbl->ctx; 64394cc7baSAlex Vesker uint8_t tbl_type = tbl->type; 65394cc7baSAlex Vesker 66394cc7baSAlex Vesker if (tbl->type != MLX5DR_TABLE_TYPE_FDB) 67394cc7baSAlex Vesker return; 68394cc7baSAlex Vesker 69394cc7baSAlex Vesker default_miss = ctx->common_res[tbl_type].default_miss; 70394cc7baSAlex Vesker if (--default_miss->refcount) 71394cc7baSAlex Vesker return; 72394cc7baSAlex Vesker 73e1df1578SHamdan Igbaria mlx5dr_cmd_forward_tbl_destroy(default_miss); 74394cc7baSAlex Vesker ctx->common_res[tbl_type].default_miss = NULL; 75394cc7baSAlex Vesker } 76394cc7baSAlex Vesker 77394cc7baSAlex Vesker static int 78394cc7baSAlex Vesker mlx5dr_table_connect_to_default_miss_tbl(struct mlx5dr_table *tbl, 79394cc7baSAlex Vesker struct mlx5dr_devx_obj *ft) 80394cc7baSAlex Vesker { 81394cc7baSAlex Vesker struct mlx5dr_cmd_ft_modify_attr ft_attr = {0}; 82394cc7baSAlex Vesker int ret; 83394cc7baSAlex Vesker 84394cc7baSAlex Vesker assert(tbl->type == MLX5DR_TABLE_TYPE_FDB); 85394cc7baSAlex Vesker 86394cc7baSAlex Vesker mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx, 87394cc7baSAlex Vesker tbl->fw_ft_type, 88394cc7baSAlex Vesker tbl->type, 89394cc7baSAlex Vesker &ft_attr); 90394cc7baSAlex Vesker 91394cc7baSAlex Vesker /* Connect to next */ 92394cc7baSAlex Vesker ret = mlx5dr_cmd_flow_table_modify(ft, &ft_attr); 93394cc7baSAlex Vesker if (ret) { 94394cc7baSAlex Vesker DR_LOG(ERR, "Failed to connect FT to default FDB FT"); 95b81f95caSItamar Gozlan return ret; 96394cc7baSAlex Vesker } 97394cc7baSAlex Vesker 98394cc7baSAlex Vesker return 0; 99394cc7baSAlex Vesker } 100394cc7baSAlex Vesker 101394cc7baSAlex Vesker struct mlx5dr_devx_obj * 102ce946c7dSErez Shitrit mlx5dr_table_create_default_ft(struct ibv_context *ibv, 103ce946c7dSErez Shitrit struct mlx5dr_table *tbl) 104394cc7baSAlex Vesker { 105394cc7baSAlex Vesker struct mlx5dr_cmd_ft_create_attr ft_attr = {0}; 106394cc7baSAlex Vesker struct mlx5dr_devx_obj *ft_obj; 107394cc7baSAlex Vesker int ret; 108394cc7baSAlex Vesker 109394cc7baSAlex Vesker mlx5dr_table_init_next_ft_attr(tbl, &ft_attr); 110394cc7baSAlex Vesker 111ce946c7dSErez Shitrit ft_obj = mlx5dr_cmd_flow_table_create(ibv, &ft_attr); 112394cc7baSAlex Vesker if (ft_obj && tbl->type == MLX5DR_TABLE_TYPE_FDB) { 113394cc7baSAlex Vesker /* Take/create ref over the default miss */ 114394cc7baSAlex Vesker ret = mlx5dr_table_up_default_fdb_miss_tbl(tbl); 115394cc7baSAlex Vesker if (ret) { 116394cc7baSAlex Vesker DR_LOG(ERR, "Failed to get default fdb miss"); 117394cc7baSAlex Vesker goto free_ft_obj; 118394cc7baSAlex Vesker } 119394cc7baSAlex Vesker ret = mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj); 120394cc7baSAlex Vesker if (ret) { 121394cc7baSAlex Vesker DR_LOG(ERR, "Failed connecting to default miss tbl"); 122394cc7baSAlex Vesker goto down_miss_tbl; 123394cc7baSAlex Vesker } 124394cc7baSAlex Vesker } 125394cc7baSAlex Vesker 126394cc7baSAlex Vesker return ft_obj; 127394cc7baSAlex Vesker 128394cc7baSAlex Vesker down_miss_tbl: 129394cc7baSAlex Vesker mlx5dr_table_down_default_fdb_miss_tbl(tbl); 130394cc7baSAlex Vesker free_ft_obj: 131394cc7baSAlex Vesker mlx5dr_cmd_destroy_obj(ft_obj); 132394cc7baSAlex Vesker return NULL; 133394cc7baSAlex Vesker } 134394cc7baSAlex Vesker 135ce946c7dSErez Shitrit static int 136ce946c7dSErez Shitrit mlx5dr_table_init_check_hws_support(struct mlx5dr_context *ctx, 137ce946c7dSErez Shitrit struct mlx5dr_table *tbl) 138ce946c7dSErez Shitrit { 139ce946c7dSErez Shitrit if (!(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) { 140ce946c7dSErez Shitrit DR_LOG(ERR, "HWS not supported, cannot create mlx5dr_table"); 141ce946c7dSErez Shitrit rte_errno = EOPNOTSUPP; 142ce946c7dSErez Shitrit return rte_errno; 143ce946c7dSErez Shitrit } 144ce946c7dSErez Shitrit 145ce946c7dSErez Shitrit if (mlx5dr_context_shared_gvmi_used(ctx) && tbl->type == MLX5DR_TABLE_TYPE_FDB) { 146ce946c7dSErez Shitrit DR_LOG(ERR, "FDB with shared port resources is not supported"); 147ce946c7dSErez Shitrit rte_errno = EOPNOTSUPP; 148ce946c7dSErez Shitrit return rte_errno; 149ce946c7dSErez Shitrit } 150ce946c7dSErez Shitrit 151ce946c7dSErez Shitrit return 0; 152ce946c7dSErez Shitrit } 153ce946c7dSErez Shitrit 154ce946c7dSErez Shitrit static int 155ce946c7dSErez Shitrit mlx5dr_table_shared_gvmi_resource_create(struct mlx5dr_context *ctx, 156ce946c7dSErez Shitrit enum mlx5dr_table_type type, 157ce946c7dSErez Shitrit struct mlx5dr_context_shared_gvmi_res *gvmi_res) 158ce946c7dSErez Shitrit { 159ce946c7dSErez Shitrit struct mlx5dr_cmd_ft_create_attr ft_attr = {0}; 160ce946c7dSErez Shitrit uint32_t calculated_ft_id; 161ce946c7dSErez Shitrit int ret; 162ce946c7dSErez Shitrit 163ce946c7dSErez Shitrit if (!mlx5dr_context_shared_gvmi_used(ctx)) 164ce946c7dSErez Shitrit return 0; 165ce946c7dSErez Shitrit 166ce946c7dSErez Shitrit ft_attr.type = mlx5dr_table_get_res_fw_ft_type(type, false); 167ce946c7dSErez Shitrit ft_attr.level = ctx->caps->nic_ft.max_level - 1; 168ce946c7dSErez Shitrit ft_attr.rtc_valid = true; 169ce946c7dSErez Shitrit 170ce946c7dSErez Shitrit gvmi_res->end_ft = 171ce946c7dSErez Shitrit mlx5dr_cmd_flow_table_create(mlx5dr_context_get_local_ibv(ctx), 172ce946c7dSErez Shitrit &ft_attr); 173ce946c7dSErez Shitrit if (!gvmi_res->end_ft) { 174ce946c7dSErez Shitrit DR_LOG(ERR, "Failed to create end-ft"); 175ce946c7dSErez Shitrit return rte_errno; 176ce946c7dSErez Shitrit } 177ce946c7dSErez Shitrit 178ce946c7dSErez Shitrit calculated_ft_id = 179ce946c7dSErez Shitrit mlx5dr_table_get_res_fw_ft_type(type, false) << FT_ID_FT_TYPE_OFFSET; 180ce946c7dSErez Shitrit calculated_ft_id |= gvmi_res->end_ft->id; 181ce946c7dSErez Shitrit 182ce946c7dSErez Shitrit /* create alias to that FT */ 183ce946c7dSErez Shitrit ret = mlx5dr_matcher_create_aliased_obj(ctx, 184ce946c7dSErez Shitrit ctx->local_ibv_ctx, 185ce946c7dSErez Shitrit ctx->ibv_ctx, 186ce946c7dSErez Shitrit ctx->caps->vhca_id, 187ce946c7dSErez Shitrit calculated_ft_id, 188ce946c7dSErez Shitrit MLX5_GENERAL_OBJ_TYPE_FT_ALIAS, 189ce946c7dSErez Shitrit &gvmi_res->aliased_end_ft); 190ce946c7dSErez Shitrit if (ret) { 191ce946c7dSErez Shitrit DR_LOG(ERR, "Failed to create alias end-ft"); 192ce946c7dSErez Shitrit goto free_end_ft; 193ce946c7dSErez Shitrit } 194ce946c7dSErez Shitrit 195ce946c7dSErez Shitrit return 0; 196ce946c7dSErez Shitrit 197ce946c7dSErez Shitrit free_end_ft: 198ce946c7dSErez Shitrit mlx5dr_cmd_destroy_obj(gvmi_res->end_ft); 199ce946c7dSErez Shitrit 200ce946c7dSErez Shitrit return rte_errno; 201ce946c7dSErez Shitrit } 202ce946c7dSErez Shitrit 203ce946c7dSErez Shitrit static void 204ce946c7dSErez Shitrit mlx5dr_table_shared_gvmi_resourse_destroy(struct mlx5dr_context *ctx, 205ce946c7dSErez Shitrit struct mlx5dr_context_shared_gvmi_res *gvmi_res) 206ce946c7dSErez Shitrit { 207ce946c7dSErez Shitrit if (!mlx5dr_context_shared_gvmi_used(ctx)) 208ce946c7dSErez Shitrit return; 209ce946c7dSErez Shitrit 210ce946c7dSErez Shitrit if (gvmi_res->aliased_end_ft) { 211ce946c7dSErez Shitrit mlx5dr_cmd_destroy_obj(gvmi_res->aliased_end_ft); 212ce946c7dSErez Shitrit gvmi_res->aliased_end_ft = NULL; 213ce946c7dSErez Shitrit } 214ce946c7dSErez Shitrit if (gvmi_res->end_ft) { 215ce946c7dSErez Shitrit mlx5dr_cmd_destroy_obj(gvmi_res->end_ft); 216ce946c7dSErez Shitrit gvmi_res->end_ft = NULL; 217ce946c7dSErez Shitrit } 218ce946c7dSErez Shitrit } 219ce946c7dSErez Shitrit 220ce946c7dSErez Shitrit /* called under spinlock ctx->ctrl_lock */ 221ce946c7dSErez Shitrit static struct mlx5dr_context_shared_gvmi_res * 222ce946c7dSErez Shitrit mlx5dr_table_get_shared_gvmi_res(struct mlx5dr_context *ctx, enum mlx5dr_table_type type) 223ce946c7dSErez Shitrit { 224ce946c7dSErez Shitrit int ret; 225ce946c7dSErez Shitrit 226ce946c7dSErez Shitrit if (!mlx5dr_context_shared_gvmi_used(ctx)) 227ce946c7dSErez Shitrit return NULL; 228ce946c7dSErez Shitrit 229ce946c7dSErez Shitrit if (ctx->gvmi_res[type].aliased_end_ft) { 230ce946c7dSErez Shitrit ctx->gvmi_res[type].refcount++; 231ce946c7dSErez Shitrit return &ctx->gvmi_res[type]; 232ce946c7dSErez Shitrit } 233ce946c7dSErez Shitrit 234ce946c7dSErez Shitrit ret = mlx5dr_table_shared_gvmi_resource_create(ctx, type, &ctx->gvmi_res[type]); 235ce946c7dSErez Shitrit if (ret) { 236ce946c7dSErez Shitrit DR_LOG(ERR, "Failed to create shared gvmi res for type: %d", type); 237ce946c7dSErez Shitrit goto out; 238ce946c7dSErez Shitrit } 239ce946c7dSErez Shitrit 240ce946c7dSErez Shitrit ctx->gvmi_res[type].refcount = 1; 241ce946c7dSErez Shitrit 242ce946c7dSErez Shitrit return &ctx->gvmi_res[type]; 243ce946c7dSErez Shitrit 244ce946c7dSErez Shitrit out: 245ce946c7dSErez Shitrit return NULL; 246ce946c7dSErez Shitrit } 247ce946c7dSErez Shitrit 248ce946c7dSErez Shitrit /* called under spinlock ctx->ctrl_lock */ 249ce946c7dSErez Shitrit static void mlx5dr_table_put_shared_gvmi_res(struct mlx5dr_table *tbl) 250ce946c7dSErez Shitrit { 251ce946c7dSErez Shitrit struct mlx5dr_context *ctx = tbl->ctx; 252ce946c7dSErez Shitrit 253ce946c7dSErez Shitrit if (!mlx5dr_context_shared_gvmi_used(ctx)) 254ce946c7dSErez Shitrit return; 255ce946c7dSErez Shitrit 256ce946c7dSErez Shitrit if (--ctx->gvmi_res[tbl->type].refcount) 257ce946c7dSErez Shitrit return; 258ce946c7dSErez Shitrit 259ce946c7dSErez Shitrit mlx5dr_table_shared_gvmi_resourse_destroy(ctx, &ctx->gvmi_res[tbl->type]); 260ce946c7dSErez Shitrit } 261ce946c7dSErez Shitrit 262ce946c7dSErez Shitrit static void mlx5dr_table_uninit_shared_ctx_res(struct mlx5dr_table *tbl) 263ce946c7dSErez Shitrit { 264ce946c7dSErez Shitrit struct mlx5dr_context *ctx = tbl->ctx; 265ce946c7dSErez Shitrit 266ce946c7dSErez Shitrit if (!mlx5dr_context_shared_gvmi_used(ctx)) 267ce946c7dSErez Shitrit return; 268ce946c7dSErez Shitrit 269ce946c7dSErez Shitrit mlx5dr_cmd_destroy_obj(tbl->local_ft); 270ce946c7dSErez Shitrit 271ce946c7dSErez Shitrit mlx5dr_table_put_shared_gvmi_res(tbl); 272ce946c7dSErez Shitrit } 273ce946c7dSErez Shitrit 274ce946c7dSErez Shitrit /* called under spin_lock ctx->ctrl_lock */ 275ce946c7dSErez Shitrit static int mlx5dr_table_init_shared_ctx_res(struct mlx5dr_context *ctx, struct mlx5dr_table *tbl) 276ce946c7dSErez Shitrit { 277a5b44bc2SErez Shitrit struct mlx5dr_cmd_ft_modify_attr ft_attr = {0}; 278a5b44bc2SErez Shitrit int ret; 279a5b44bc2SErez Shitrit 280ce946c7dSErez Shitrit if (!mlx5dr_context_shared_gvmi_used(ctx)) 281ce946c7dSErez Shitrit return 0; 282ce946c7dSErez Shitrit 283ce946c7dSErez Shitrit /* create local-ft for root access */ 284ce946c7dSErez Shitrit tbl->local_ft = 285ce946c7dSErez Shitrit mlx5dr_table_create_default_ft(mlx5dr_context_get_local_ibv(ctx), tbl); 286ce946c7dSErez Shitrit if (!tbl->local_ft) { 287ce946c7dSErez Shitrit DR_LOG(ERR, "Failed to create local-ft"); 288ce946c7dSErez Shitrit return rte_errno; 289ce946c7dSErez Shitrit } 290ce946c7dSErez Shitrit 291ce946c7dSErez Shitrit if (!mlx5dr_table_get_shared_gvmi_res(tbl->ctx, tbl->type)) { 292ce946c7dSErez Shitrit DR_LOG(ERR, "Failed to shared gvmi resources"); 293ce946c7dSErez Shitrit goto clean_local_ft; 294ce946c7dSErez Shitrit } 295ce946c7dSErez Shitrit 296a5b44bc2SErez Shitrit /* On shared gvmi the default behavior is jump to alias end ft */ 297a5b44bc2SErez Shitrit mlx5dr_cmd_set_attr_connect_miss_tbl(tbl->ctx, 298a5b44bc2SErez Shitrit tbl->fw_ft_type, 299a5b44bc2SErez Shitrit tbl->type, 300a5b44bc2SErez Shitrit &ft_attr); 301a5b44bc2SErez Shitrit 302a5b44bc2SErez Shitrit ret = mlx5dr_cmd_flow_table_modify(tbl->ft, &ft_attr); 303a5b44bc2SErez Shitrit if (ret) { 304a5b44bc2SErez Shitrit DR_LOG(ERR, "Failed to point table to its default miss"); 305a5b44bc2SErez Shitrit goto clean_shared_res; 306a5b44bc2SErez Shitrit } 307a5b44bc2SErez Shitrit 308ce946c7dSErez Shitrit return 0; 309ce946c7dSErez Shitrit 310a5b44bc2SErez Shitrit clean_shared_res: 311a5b44bc2SErez Shitrit mlx5dr_table_put_shared_gvmi_res(tbl); 312ce946c7dSErez Shitrit clean_local_ft: 313ce946c7dSErez Shitrit mlx5dr_table_destroy_default_ft(tbl, tbl->local_ft); 314ce946c7dSErez Shitrit return rte_errno; 315ce946c7dSErez Shitrit } 316ce946c7dSErez Shitrit 317394cc7baSAlex Vesker void mlx5dr_table_destroy_default_ft(struct mlx5dr_table *tbl, 318394cc7baSAlex Vesker struct mlx5dr_devx_obj *ft_obj) 319394cc7baSAlex Vesker { 320394cc7baSAlex Vesker mlx5dr_cmd_destroy_obj(ft_obj); 32101895651SErez Shitrit mlx5dr_table_down_default_fdb_miss_tbl(tbl); 322394cc7baSAlex Vesker } 323394cc7baSAlex Vesker 324394cc7baSAlex Vesker static int mlx5dr_table_init(struct mlx5dr_table *tbl) 325394cc7baSAlex Vesker { 326394cc7baSAlex Vesker struct mlx5dr_context *ctx = tbl->ctx; 327394cc7baSAlex Vesker int ret; 328394cc7baSAlex Vesker 329394cc7baSAlex Vesker if (mlx5dr_table_is_root(tbl)) 330394cc7baSAlex Vesker return 0; 331394cc7baSAlex Vesker 332ce946c7dSErez Shitrit ret = mlx5dr_table_init_check_hws_support(ctx, tbl); 333ce946c7dSErez Shitrit if (ret) 334ce946c7dSErez Shitrit return ret; 335394cc7baSAlex Vesker 336394cc7baSAlex Vesker switch (tbl->type) { 337394cc7baSAlex Vesker case MLX5DR_TABLE_TYPE_NIC_RX: 338394cc7baSAlex Vesker tbl->fw_ft_type = FS_FT_NIC_RX; 339394cc7baSAlex Vesker break; 340394cc7baSAlex Vesker case MLX5DR_TABLE_TYPE_NIC_TX: 341394cc7baSAlex Vesker tbl->fw_ft_type = FS_FT_NIC_TX; 342394cc7baSAlex Vesker break; 343394cc7baSAlex Vesker case MLX5DR_TABLE_TYPE_FDB: 344394cc7baSAlex Vesker tbl->fw_ft_type = FS_FT_FDB; 345394cc7baSAlex Vesker break; 346394cc7baSAlex Vesker default: 347394cc7baSAlex Vesker assert(0); 348394cc7baSAlex Vesker break; 349394cc7baSAlex Vesker } 350394cc7baSAlex Vesker 351394cc7baSAlex Vesker pthread_spin_lock(&ctx->ctrl_lock); 352ce946c7dSErez Shitrit tbl->ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl); 353394cc7baSAlex Vesker if (!tbl->ft) { 354394cc7baSAlex Vesker DR_LOG(ERR, "Failed to create flow table devx object"); 355394cc7baSAlex Vesker pthread_spin_unlock(&ctx->ctrl_lock); 356394cc7baSAlex Vesker return rte_errno; 357394cc7baSAlex Vesker } 358394cc7baSAlex Vesker 359a5b44bc2SErez Shitrit ret = mlx5dr_table_init_shared_ctx_res(ctx, tbl); 360394cc7baSAlex Vesker if (ret) 361394cc7baSAlex Vesker goto tbl_destroy; 362ce946c7dSErez Shitrit 363a5b44bc2SErez Shitrit ret = mlx5dr_action_get_default_stc(ctx, tbl->type); 364ce946c7dSErez Shitrit if (ret) 365a5b44bc2SErez Shitrit goto free_shared_ctx; 366ce946c7dSErez Shitrit 367394cc7baSAlex Vesker pthread_spin_unlock(&ctx->ctrl_lock); 368394cc7baSAlex Vesker 369394cc7baSAlex Vesker return 0; 370394cc7baSAlex Vesker 371a5b44bc2SErez Shitrit free_shared_ctx: 372a5b44bc2SErez Shitrit mlx5dr_table_uninit_shared_ctx_res(tbl); 373394cc7baSAlex Vesker tbl_destroy: 374394cc7baSAlex Vesker mlx5dr_table_destroy_default_ft(tbl, tbl->ft); 375394cc7baSAlex Vesker pthread_spin_unlock(&ctx->ctrl_lock); 376394cc7baSAlex Vesker return rte_errno; 377394cc7baSAlex Vesker } 378394cc7baSAlex Vesker 379394cc7baSAlex Vesker static void mlx5dr_table_uninit(struct mlx5dr_table *tbl) 380394cc7baSAlex Vesker { 381394cc7baSAlex Vesker if (mlx5dr_table_is_root(tbl)) 382394cc7baSAlex Vesker return; 383394cc7baSAlex Vesker pthread_spin_lock(&tbl->ctx->ctrl_lock); 384394cc7baSAlex Vesker mlx5dr_action_put_default_stc(tbl->ctx, tbl->type); 385ce946c7dSErez Shitrit mlx5dr_table_uninit_shared_ctx_res(tbl); 386a5b44bc2SErez Shitrit mlx5dr_table_destroy_default_ft(tbl, tbl->ft); 387394cc7baSAlex Vesker pthread_spin_unlock(&tbl->ctx->ctrl_lock); 388394cc7baSAlex Vesker } 389394cc7baSAlex Vesker 390394cc7baSAlex Vesker struct mlx5dr_table *mlx5dr_table_create(struct mlx5dr_context *ctx, 391394cc7baSAlex Vesker struct mlx5dr_table_attr *attr) 392394cc7baSAlex Vesker { 393394cc7baSAlex Vesker struct mlx5dr_table *tbl; 394394cc7baSAlex Vesker int ret; 395394cc7baSAlex Vesker 396394cc7baSAlex Vesker if (attr->type > MLX5DR_TABLE_TYPE_FDB) { 397394cc7baSAlex Vesker DR_LOG(ERR, "Invalid table type %d", attr->type); 398394cc7baSAlex Vesker return NULL; 399394cc7baSAlex Vesker } 400394cc7baSAlex Vesker 401b81f95caSItamar Gozlan tbl = simple_calloc(1, sizeof(*tbl)); 402394cc7baSAlex Vesker if (!tbl) { 403394cc7baSAlex Vesker rte_errno = ENOMEM; 404394cc7baSAlex Vesker return NULL; 405394cc7baSAlex Vesker } 406394cc7baSAlex Vesker 407394cc7baSAlex Vesker tbl->ctx = ctx; 408394cc7baSAlex Vesker tbl->type = attr->type; 409394cc7baSAlex Vesker tbl->level = attr->level; 410394cc7baSAlex Vesker 411394cc7baSAlex Vesker ret = mlx5dr_table_init(tbl); 412394cc7baSAlex Vesker if (ret) { 413394cc7baSAlex Vesker DR_LOG(ERR, "Failed to initialise table"); 414394cc7baSAlex Vesker goto free_tbl; 415394cc7baSAlex Vesker } 416394cc7baSAlex Vesker 417394cc7baSAlex Vesker pthread_spin_lock(&ctx->ctrl_lock); 418394cc7baSAlex Vesker LIST_INSERT_HEAD(&ctx->head, tbl, next); 419394cc7baSAlex Vesker pthread_spin_unlock(&ctx->ctrl_lock); 420394cc7baSAlex Vesker 421394cc7baSAlex Vesker return tbl; 422394cc7baSAlex Vesker 423394cc7baSAlex Vesker free_tbl: 424394cc7baSAlex Vesker simple_free(tbl); 425394cc7baSAlex Vesker return NULL; 426394cc7baSAlex Vesker } 427394cc7baSAlex Vesker 428394cc7baSAlex Vesker int mlx5dr_table_destroy(struct mlx5dr_table *tbl) 429394cc7baSAlex Vesker { 430394cc7baSAlex Vesker struct mlx5dr_context *ctx = tbl->ctx; 431394cc7baSAlex Vesker pthread_spin_lock(&ctx->ctrl_lock); 432*486f9aacSHamdan Igbaria if (!LIST_EMPTY(&tbl->head) || !LIST_EMPTY(&tbl->isolated_matchers)) { 433b81f95caSItamar Gozlan DR_LOG(ERR, "Cannot destroy table containing matchers"); 434b81f95caSItamar Gozlan rte_errno = EBUSY; 435b81f95caSItamar Gozlan goto unlock_err; 436b81f95caSItamar Gozlan } 437b81f95caSItamar Gozlan 438b81f95caSItamar Gozlan if (!LIST_EMPTY(&tbl->default_miss.head)) { 439b81f95caSItamar Gozlan DR_LOG(ERR, "Cannot destroy table pointed by default miss"); 440b81f95caSItamar Gozlan rte_errno = EBUSY; 441b81f95caSItamar Gozlan goto unlock_err; 442b81f95caSItamar Gozlan } 443b81f95caSItamar Gozlan 444394cc7baSAlex Vesker LIST_REMOVE(tbl, next); 445394cc7baSAlex Vesker pthread_spin_unlock(&ctx->ctrl_lock); 446394cc7baSAlex Vesker mlx5dr_table_uninit(tbl); 447394cc7baSAlex Vesker simple_free(tbl); 448394cc7baSAlex Vesker 449394cc7baSAlex Vesker return 0; 450b81f95caSItamar Gozlan 451b81f95caSItamar Gozlan unlock_err: 452b81f95caSItamar Gozlan pthread_spin_unlock(&ctx->ctrl_lock); 453b81f95caSItamar Gozlan return -rte_errno; 454b81f95caSItamar Gozlan } 455b81f95caSItamar Gozlan 456b81f95caSItamar Gozlan static struct mlx5dr_devx_obj * 457b81f95caSItamar Gozlan mlx5dr_table_get_last_ft(struct mlx5dr_table *tbl) 458b81f95caSItamar Gozlan { 459b81f95caSItamar Gozlan struct mlx5dr_devx_obj *last_ft = tbl->ft; 460b81f95caSItamar Gozlan struct mlx5dr_matcher *matcher; 461b81f95caSItamar Gozlan 462b81f95caSItamar Gozlan LIST_FOREACH(matcher, &tbl->head, next) 463b81f95caSItamar Gozlan last_ft = matcher->end_ft; 464b81f95caSItamar Gozlan 465b81f95caSItamar Gozlan return last_ft; 466b81f95caSItamar Gozlan } 467b81f95caSItamar Gozlan 468b81f95caSItamar Gozlan int mlx5dr_table_ft_set_default_next_ft(struct mlx5dr_table *tbl, 469b81f95caSItamar Gozlan struct mlx5dr_devx_obj *ft_obj) 470b81f95caSItamar Gozlan { 471b81f95caSItamar Gozlan struct mlx5dr_cmd_ft_modify_attr ft_attr = {0}; 472b81f95caSItamar Gozlan int ret; 473b81f95caSItamar Gozlan 474b81f95caSItamar Gozlan /* Due to FW limitation, resetting the flow table to default action will 475b81f95caSItamar Gozlan * disconnect RTC when ignore_flow_level_rtc_valid is not supported. 476b81f95caSItamar Gozlan */ 477b81f95caSItamar Gozlan if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid) 478b81f95caSItamar Gozlan return 0; 479b81f95caSItamar Gozlan 480b81f95caSItamar Gozlan if (tbl->type == MLX5DR_TABLE_TYPE_FDB) 481b81f95caSItamar Gozlan return mlx5dr_table_connect_to_default_miss_tbl(tbl, ft_obj); 482b81f95caSItamar Gozlan 483b81f95caSItamar Gozlan ft_attr.type = tbl->fw_ft_type; 484b81f95caSItamar Gozlan ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION; 485b81f95caSItamar Gozlan ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_DEFAULT; 486b81f95caSItamar Gozlan 487b81f95caSItamar Gozlan ret = mlx5dr_cmd_flow_table_modify(ft_obj, &ft_attr); 488b81f95caSItamar Gozlan if (ret) { 489b81f95caSItamar Gozlan DR_LOG(ERR, "Failed to set FT default miss action"); 490b81f95caSItamar Gozlan return ret; 491b81f95caSItamar Gozlan } 492b81f95caSItamar Gozlan 493b81f95caSItamar Gozlan return 0; 494b81f95caSItamar Gozlan } 495b81f95caSItamar Gozlan 496b81f95caSItamar Gozlan int mlx5dr_table_ft_set_next_rtc(struct mlx5dr_devx_obj *ft, 497b81f95caSItamar Gozlan uint32_t fw_ft_type, 498b81f95caSItamar Gozlan struct mlx5dr_devx_obj *rtc_0, 499b81f95caSItamar Gozlan struct mlx5dr_devx_obj *rtc_1) 500b81f95caSItamar Gozlan { 501b81f95caSItamar Gozlan struct mlx5dr_cmd_ft_modify_attr ft_attr = {0}; 502b81f95caSItamar Gozlan 503b81f95caSItamar Gozlan ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID; 504b81f95caSItamar Gozlan ft_attr.type = fw_ft_type; 505b81f95caSItamar Gozlan ft_attr.rtc_id_0 = rtc_0 ? rtc_0->id : 0; 506b81f95caSItamar Gozlan ft_attr.rtc_id_1 = rtc_1 ? rtc_1->id : 0; 507b81f95caSItamar Gozlan 508b81f95caSItamar Gozlan return mlx5dr_cmd_flow_table_modify(ft, &ft_attr); 509b81f95caSItamar Gozlan } 510b81f95caSItamar Gozlan 511b81f95caSItamar Gozlan static int mlx5dr_table_ft_set_next_ft(struct mlx5dr_devx_obj *ft, 512b81f95caSItamar Gozlan uint32_t fw_ft_type, 513b81f95caSItamar Gozlan uint32_t next_ft_id) 514b81f95caSItamar Gozlan { 515b81f95caSItamar Gozlan struct mlx5dr_cmd_ft_modify_attr ft_attr = {0}; 516b81f95caSItamar Gozlan 517b81f95caSItamar Gozlan ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION; 518b81f95caSItamar Gozlan ft_attr.table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL; 519b81f95caSItamar Gozlan ft_attr.type = fw_ft_type; 520b81f95caSItamar Gozlan ft_attr.table_miss_id = next_ft_id; 521b81f95caSItamar Gozlan 522b81f95caSItamar Gozlan return mlx5dr_cmd_flow_table_modify(ft, &ft_attr); 523b81f95caSItamar Gozlan } 524b81f95caSItamar Gozlan 525b81f95caSItamar Gozlan int mlx5dr_table_update_connected_miss_tables(struct mlx5dr_table *dst_tbl) 526b81f95caSItamar Gozlan { 527b81f95caSItamar Gozlan struct mlx5dr_table *src_tbl; 528b81f95caSItamar Gozlan int ret; 529b81f95caSItamar Gozlan 530b81f95caSItamar Gozlan if (LIST_EMPTY(&dst_tbl->default_miss.head)) 531b81f95caSItamar Gozlan return 0; 532b81f95caSItamar Gozlan 533b81f95caSItamar Gozlan LIST_FOREACH(src_tbl, &dst_tbl->default_miss.head, default_miss.next) { 534*486f9aacSHamdan Igbaria ret = mlx5dr_table_connect_to_miss_table(src_tbl, dst_tbl, false); 535b81f95caSItamar Gozlan if (ret) { 536b81f95caSItamar Gozlan DR_LOG(ERR, "Failed to update source miss table, unexpected behavior"); 537b81f95caSItamar Gozlan return ret; 538b81f95caSItamar Gozlan } 539b81f95caSItamar Gozlan } 540b81f95caSItamar Gozlan 541b81f95caSItamar Gozlan return 0; 542b81f95caSItamar Gozlan } 543b81f95caSItamar Gozlan 544*486f9aacSHamdan Igbaria int mlx5dr_table_connect_src_ft_to_miss_table(struct mlx5dr_table *src_tbl, 545*486f9aacSHamdan Igbaria struct mlx5dr_devx_obj *ft, 546b81f95caSItamar Gozlan struct mlx5dr_table *dst_tbl) 547b81f95caSItamar Gozlan { 548b81f95caSItamar Gozlan struct mlx5dr_matcher *matcher; 549b81f95caSItamar Gozlan int ret; 550b81f95caSItamar Gozlan 551b81f95caSItamar Gozlan if (dst_tbl) { 552b81f95caSItamar Gozlan if (LIST_EMPTY(&dst_tbl->head)) { 553*486f9aacSHamdan Igbaria /* Connect src_tbl ft to dst_tbl start anchor */ 554*486f9aacSHamdan Igbaria ret = mlx5dr_table_ft_set_next_ft(ft, 555b81f95caSItamar Gozlan src_tbl->fw_ft_type, 556b81f95caSItamar Gozlan dst_tbl->ft->id); 557b81f95caSItamar Gozlan if (ret) 558b81f95caSItamar Gozlan return ret; 559b81f95caSItamar Gozlan 560*486f9aacSHamdan Igbaria /* Reset ft RTC to default RTC */ 561*486f9aacSHamdan Igbaria ret = mlx5dr_table_ft_set_next_rtc(ft, 562b81f95caSItamar Gozlan src_tbl->fw_ft_type, 563b81f95caSItamar Gozlan NULL, NULL); 564b81f95caSItamar Gozlan if (ret) 565b81f95caSItamar Gozlan return ret; 566b81f95caSItamar Gozlan } else { 567*486f9aacSHamdan Igbaria /* Connect src_tbl ft to first matcher RTC */ 568b81f95caSItamar Gozlan matcher = LIST_FIRST(&dst_tbl->head); 569*486f9aacSHamdan Igbaria ret = mlx5dr_table_ft_set_next_rtc(ft, 570b81f95caSItamar Gozlan src_tbl->fw_ft_type, 571b81f95caSItamar Gozlan matcher->match_ste.rtc_0, 572b81f95caSItamar Gozlan matcher->match_ste.rtc_1); 573b81f95caSItamar Gozlan if (ret) 574b81f95caSItamar Gozlan return ret; 575b81f95caSItamar Gozlan 576b81f95caSItamar Gozlan /* Reset next miss FT to default */ 577*486f9aacSHamdan Igbaria ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft); 578b81f95caSItamar Gozlan if (ret) 579b81f95caSItamar Gozlan return ret; 580b81f95caSItamar Gozlan } 581b81f95caSItamar Gozlan } else { 582b81f95caSItamar Gozlan /* Reset next miss FT to default */ 583*486f9aacSHamdan Igbaria ret = mlx5dr_table_ft_set_default_next_ft(src_tbl, ft); 584b81f95caSItamar Gozlan if (ret) 585b81f95caSItamar Gozlan return ret; 586b81f95caSItamar Gozlan 587*486f9aacSHamdan Igbaria /* Reset ft RTC to default RTC */ 588*486f9aacSHamdan Igbaria ret = mlx5dr_table_ft_set_next_rtc(ft, 589b81f95caSItamar Gozlan src_tbl->fw_ft_type, 590b81f95caSItamar Gozlan NULL, NULL); 591b81f95caSItamar Gozlan if (ret) 592b81f95caSItamar Gozlan return ret; 593b81f95caSItamar Gozlan } 594b81f95caSItamar Gozlan 595*486f9aacSHamdan Igbaria return 0; 596*486f9aacSHamdan Igbaria } 597*486f9aacSHamdan Igbaria 598*486f9aacSHamdan Igbaria int mlx5dr_table_connect_to_miss_table(struct mlx5dr_table *src_tbl, 599*486f9aacSHamdan Igbaria struct mlx5dr_table *dst_tbl, 600*486f9aacSHamdan Igbaria bool only_update_last_ft) 601*486f9aacSHamdan Igbaria { 602*486f9aacSHamdan Igbaria struct mlx5dr_matcher *matcher; 603*486f9aacSHamdan Igbaria struct mlx5dr_devx_obj *ft; 604*486f9aacSHamdan Igbaria int ret; 605*486f9aacSHamdan Igbaria 606*486f9aacSHamdan Igbaria /* Connect last FT in the src_tbl matchers chain */ 607*486f9aacSHamdan Igbaria ft = mlx5dr_table_get_last_ft(src_tbl); 608*486f9aacSHamdan Igbaria ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl); 609*486f9aacSHamdan Igbaria if (ret) 610*486f9aacSHamdan Igbaria return ret; 611*486f9aacSHamdan Igbaria 612*486f9aacSHamdan Igbaria if (!only_update_last_ft) { 613*486f9aacSHamdan Igbaria /* Connect isolated matchers FT */ 614*486f9aacSHamdan Igbaria LIST_FOREACH(matcher, &src_tbl->isolated_matchers, next) { 615*486f9aacSHamdan Igbaria ft = matcher->end_ft; 616*486f9aacSHamdan Igbaria ret = mlx5dr_table_connect_src_ft_to_miss_table(src_tbl, ft, dst_tbl); 617*486f9aacSHamdan Igbaria if (ret) 618*486f9aacSHamdan Igbaria return ret; 619*486f9aacSHamdan Igbaria } 620*486f9aacSHamdan Igbaria } 621*486f9aacSHamdan Igbaria 622b81f95caSItamar Gozlan src_tbl->default_miss.miss_tbl = dst_tbl; 623b81f95caSItamar Gozlan 624b81f95caSItamar Gozlan return 0; 625b81f95caSItamar Gozlan } 626b81f95caSItamar Gozlan 627b81f95caSItamar Gozlan static int mlx5dr_table_set_default_miss_not_valid(struct mlx5dr_table *tbl, 628b81f95caSItamar Gozlan struct mlx5dr_table *miss_tbl) 629b81f95caSItamar Gozlan { 630b81f95caSItamar Gozlan if (!tbl->ctx->caps->nic_ft.ignore_flow_level_rtc_valid || 631b81f95caSItamar Gozlan mlx5dr_context_shared_gvmi_used(tbl->ctx)) { 632b81f95caSItamar Gozlan DR_LOG(ERR, "Default miss table is not supported"); 633b81f95caSItamar Gozlan rte_errno = EOPNOTSUPP; 634b81f95caSItamar Gozlan return -rte_errno; 635b81f95caSItamar Gozlan } 636b81f95caSItamar Gozlan 637b81f95caSItamar Gozlan if (mlx5dr_table_is_root(tbl) || 638b81f95caSItamar Gozlan (miss_tbl && mlx5dr_table_is_root(miss_tbl)) || 6394711950bSItamar Gozlan (miss_tbl && miss_tbl->type != tbl->type)) { 640b81f95caSItamar Gozlan DR_LOG(ERR, "Invalid arguments"); 641b81f95caSItamar Gozlan rte_errno = EINVAL; 642b81f95caSItamar Gozlan return -rte_errno; 643b81f95caSItamar Gozlan } 644b81f95caSItamar Gozlan 645b81f95caSItamar Gozlan return 0; 646b81f95caSItamar Gozlan } 647b81f95caSItamar Gozlan 648b81f95caSItamar Gozlan int mlx5dr_table_set_default_miss(struct mlx5dr_table *tbl, 649b81f95caSItamar Gozlan struct mlx5dr_table *miss_tbl) 650b81f95caSItamar Gozlan { 651b81f95caSItamar Gozlan struct mlx5dr_context *ctx = tbl->ctx; 6524711950bSItamar Gozlan struct mlx5dr_table *old_miss_tbl; 653b81f95caSItamar Gozlan int ret; 654b81f95caSItamar Gozlan 655b81f95caSItamar Gozlan ret = mlx5dr_table_set_default_miss_not_valid(tbl, miss_tbl); 656b81f95caSItamar Gozlan if (ret) 657b81f95caSItamar Gozlan return ret; 658b81f95caSItamar Gozlan 659b81f95caSItamar Gozlan pthread_spin_lock(&ctx->ctrl_lock); 6604711950bSItamar Gozlan old_miss_tbl = tbl->default_miss.miss_tbl; 661*486f9aacSHamdan Igbaria ret = mlx5dr_table_connect_to_miss_table(tbl, miss_tbl, false); 662b81f95caSItamar Gozlan if (ret) 663b81f95caSItamar Gozlan goto out; 664b81f95caSItamar Gozlan 6654711950bSItamar Gozlan if (old_miss_tbl) 6664711950bSItamar Gozlan LIST_REMOVE(tbl, default_miss.next); 6674711950bSItamar Gozlan 668b81f95caSItamar Gozlan if (miss_tbl) 669b81f95caSItamar Gozlan LIST_INSERT_HEAD(&miss_tbl->default_miss.head, tbl, default_miss.next); 670b81f95caSItamar Gozlan 671b81f95caSItamar Gozlan pthread_spin_unlock(&ctx->ctrl_lock); 672b81f95caSItamar Gozlan return 0; 673b81f95caSItamar Gozlan out: 674b81f95caSItamar Gozlan pthread_spin_unlock(&ctx->ctrl_lock); 675b81f95caSItamar Gozlan return -ret; 676394cc7baSAlex Vesker } 677