1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022 NVIDIA Corporation & Affiliates 3 */ 4 5 #include "mlx5dr_internal.h" 6 7 enum mlx5dr_matcher_rtc_type { 8 DR_MATCHER_RTC_TYPE_MATCH, 9 DR_MATCHER_RTC_TYPE_STE_ARRAY, 10 DR_MATCHER_RTC_TYPE_MAX, 11 }; 12 13 static const char * const mlx5dr_matcher_rtc_type_str[] = { 14 [DR_MATCHER_RTC_TYPE_MATCH] = "MATCH", 15 [DR_MATCHER_RTC_TYPE_STE_ARRAY] = "STE_ARRAY", 16 [DR_MATCHER_RTC_TYPE_MAX] = "UNKNOWN", 17 }; 18 19 static const char *mlx5dr_matcher_rtc_type_to_str(enum mlx5dr_matcher_rtc_type rtc_type) 20 { 21 if (rtc_type > DR_MATCHER_RTC_TYPE_MAX) 22 rtc_type = DR_MATCHER_RTC_TYPE_MAX; 23 return mlx5dr_matcher_rtc_type_str[rtc_type]; 24 } 25 26 static bool mlx5dr_matcher_requires_col_tbl(uint8_t log_num_of_rules) 27 { 28 /* Collision table concatenation is done only for large rule tables */ 29 return log_num_of_rules > MLX5DR_MATCHER_ASSURED_RULES_TH; 30 } 31 32 static uint8_t mlx5dr_matcher_rules_to_tbl_depth(uint8_t log_num_of_rules) 33 { 34 if (mlx5dr_matcher_requires_col_tbl(log_num_of_rules)) 35 return MLX5DR_MATCHER_ASSURED_MAIN_TBL_DEPTH; 36 37 /* For small rule tables we use a single deep table to assure insertion */ 38 return RTE_MIN(log_num_of_rules, MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH); 39 } 40 41 static void mlx5dr_matcher_destroy_end_ft(struct mlx5dr_matcher *matcher) 42 { 43 mlx5dr_table_destroy_default_ft(matcher->tbl, matcher->end_ft); 44 } 45 46 int mlx5dr_matcher_free_rtc_pointing(struct mlx5dr_context *ctx, 47 uint32_t fw_ft_type, 48 enum mlx5dr_table_type type, 49 struct mlx5dr_devx_obj *devx_obj) 50 { 51 int ret; 52 53 if (type != MLX5DR_TABLE_TYPE_FDB && !mlx5dr_context_shared_gvmi_used(ctx)) 54 return 0; 55 56 ret = mlx5dr_table_ft_set_next_rtc(devx_obj, fw_ft_type, NULL, NULL); 57 if (ret) 58 DR_LOG(ERR, "Failed to disconnect previous RTC"); 59 60 return ret; 61 } 62 63 static int mlx5dr_matcher_shared_point_end_ft(struct mlx5dr_matcher *matcher) 64 { 65 struct mlx5dr_cmd_ft_modify_attr ft_attr = {0}; 66 int ret; 67 68 mlx5dr_cmd_set_attr_connect_miss_tbl(matcher->tbl->ctx, 69 matcher->tbl->fw_ft_type, 70 matcher->tbl->type, 71 &ft_attr); 72 73 ret = mlx5dr_cmd_flow_table_modify(matcher->end_ft, &ft_attr); 74 if (ret) { 75 DR_LOG(ERR, "Failed to connect new matcher to default miss alias RTC"); 76 return ret; 77 } 78 79 ret = mlx5dr_matcher_free_rtc_pointing(matcher->tbl->ctx, 80 matcher->tbl->fw_ft_type, 81 matcher->tbl->type, 82 matcher->end_ft); 83 84 return ret; 85 } 86 87 static int mlx5dr_matcher_shared_create_alias_rtc(struct mlx5dr_matcher *matcher) 88 { 89 struct mlx5dr_context *ctx = matcher->tbl->ctx; 90 int ret; 91 92 ret = mlx5dr_matcher_create_aliased_obj(ctx, 93 ctx->ibv_ctx, 94 ctx->local_ibv_ctx, 95 ctx->caps->shared_vhca_id, 96 matcher->match_ste.rtc_0->id, 97 MLX5_GENERAL_OBJ_TYPE_RTC, 98 &matcher->match_ste.aliased_rtc_0); 99 if (ret) { 100 DR_LOG(ERR, "Failed to allocate alias RTC"); 101 return ret; 102 } 103 return 0; 104 } 105 106 static int mlx5dr_matcher_create_init_shared(struct mlx5dr_matcher *matcher) 107 { 108 if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx)) 109 return 0; 110 111 if (mlx5dr_matcher_shared_point_end_ft(matcher)) { 112 DR_LOG(ERR, "Failed to point shared matcher end flow table"); 113 return rte_errno; 114 } 115 116 if (mlx5dr_matcher_shared_create_alias_rtc(matcher)) { 117 DR_LOG(ERR, "Failed to create alias RTC"); 118 return rte_errno; 119 } 120 121 return 0; 122 } 123 124 static void mlx5dr_matcher_create_uninit_shared(struct mlx5dr_matcher *matcher) 125 { 126 if (!mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx)) 127 return; 128 129 if (matcher->match_ste.aliased_rtc_0) { 130 mlx5dr_cmd_destroy_obj(matcher->match_ste.aliased_rtc_0); 131 matcher->match_ste.aliased_rtc_0 = NULL; 132 } 133 } 134 135 static int mlx5dr_matcher_create_end_ft(struct mlx5dr_matcher *matcher) 136 { 137 struct mlx5dr_table *tbl = matcher->tbl; 138 139 matcher->end_ft = mlx5dr_table_create_default_ft(tbl->ctx->ibv_ctx, tbl); 140 if (!matcher->end_ft) { 141 DR_LOG(ERR, "Failed to create matcher end flow table"); 142 return rte_errno; 143 } 144 return 0; 145 } 146 147 static uint32_t 148 mlx5dr_matcher_connect_get_rtc0(struct mlx5dr_matcher *matcher) 149 { 150 if (!matcher->match_ste.aliased_rtc_0) 151 return matcher->match_ste.rtc_0->id; 152 else 153 return matcher->match_ste.aliased_rtc_0->id; 154 } 155 156 /* The function updates tbl->local_ft to the first RTC or 0 if no more matchers */ 157 static int mlx5dr_matcher_shared_update_local_ft(struct mlx5dr_table *tbl) 158 { 159 struct mlx5dr_cmd_ft_modify_attr cur_ft_attr = {0}; 160 struct mlx5dr_matcher *first_matcher; 161 int ret; 162 163 if (!mlx5dr_context_shared_gvmi_used(tbl->ctx)) 164 return 0; 165 166 first_matcher = LIST_FIRST(&tbl->head); 167 if (!first_matcher) { 168 /* local ft no longer points to any RTC, drop refcount */ 169 ret = mlx5dr_matcher_free_rtc_pointing(tbl->ctx, 170 tbl->fw_ft_type, 171 tbl->type, 172 tbl->local_ft); 173 if (ret) 174 DR_LOG(ERR, "Failed to clear local FT to prev alias RTC"); 175 176 return ret; 177 } 178 179 /* point local_ft to the first RTC */ 180 cur_ft_attr.modify_fs = MLX5_IFC_MODIFY_FLOW_TABLE_RTC_ID; 181 cur_ft_attr.type = tbl->fw_ft_type; 182 cur_ft_attr.rtc_id_0 = mlx5dr_matcher_connect_get_rtc0(first_matcher); 183 184 ret = mlx5dr_cmd_flow_table_modify(tbl->local_ft, &cur_ft_attr); 185 if (ret) { 186 DR_LOG(ERR, "Failed to point local FT to alias RTC"); 187 return ret; 188 } 189 190 return 0; 191 } 192 193 static int mlx5dr_matcher_connect(struct mlx5dr_matcher *matcher) 194 { 195 struct mlx5dr_table *tbl = matcher->tbl; 196 struct mlx5dr_matcher *prev = NULL; 197 struct mlx5dr_matcher *next = NULL; 198 struct mlx5dr_matcher *tmp_matcher; 199 int ret; 200 201 if (matcher->attr.isolated) { 202 LIST_INSERT_HEAD(&tbl->isolated_matchers, matcher, next); 203 ret = mlx5dr_table_connect_src_ft_to_miss_table(tbl, matcher->end_ft, 204 tbl->default_miss.miss_tbl); 205 if (ret) { 206 DR_LOG(ERR, "Failed to connect the new matcher to the miss_tbl"); 207 goto remove_from_list; 208 } 209 210 return 0; 211 } 212 213 /* Find location in matcher list */ 214 if (LIST_EMPTY(&tbl->head)) { 215 LIST_INSERT_HEAD(&tbl->head, matcher, next); 216 goto connect; 217 } 218 219 LIST_FOREACH(tmp_matcher, &tbl->head, next) { 220 if (tmp_matcher->attr.priority > matcher->attr.priority) { 221 next = tmp_matcher; 222 break; 223 } 224 prev = tmp_matcher; 225 } 226 227 if (next) 228 LIST_INSERT_BEFORE(next, matcher, next); 229 else 230 LIST_INSERT_AFTER(prev, matcher, next); 231 232 connect: 233 if (next) { 234 /* Connect to next RTC */ 235 ret = mlx5dr_table_ft_set_next_rtc(matcher->end_ft, 236 tbl->fw_ft_type, 237 next->match_ste.rtc_0, 238 next->match_ste.rtc_1); 239 if (ret) { 240 DR_LOG(ERR, "Failed to connect new matcher to next RTC"); 241 goto remove_from_list; 242 } 243 } else { 244 /* Connect last matcher to next miss_tbl if exists */ 245 ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true); 246 if (ret) { 247 DR_LOG(ERR, "Failed connect new matcher to miss_tbl"); 248 goto remove_from_list; 249 } 250 } 251 252 /* Connect to previous FT */ 253 ret = mlx5dr_table_ft_set_next_rtc(prev ? prev->end_ft : tbl->ft, 254 tbl->fw_ft_type, 255 matcher->match_ste.rtc_0, 256 matcher->match_ste.rtc_1); 257 if (ret) { 258 DR_LOG(ERR, "Failed to connect new matcher to previous FT"); 259 goto remove_from_list; 260 } 261 262 ret = mlx5dr_matcher_shared_update_local_ft(tbl); 263 if (ret) { 264 DR_LOG(ERR, "Failed to update local_ft anchor in shared table"); 265 goto remove_from_list; 266 } 267 268 /* Reset next miss FT to default (drop refcount) */ 269 ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev ? prev->end_ft : tbl->ft); 270 if (ret) { 271 DR_LOG(ERR, "Failed to reset matcher ft default miss"); 272 goto remove_from_list; 273 } 274 275 if (!prev) { 276 /* Update tables missing to current matcher in the table */ 277 ret = mlx5dr_table_update_connected_miss_tables(tbl); 278 if (ret) { 279 DR_LOG(ERR, "Fatal error, failed to update connected miss table"); 280 goto remove_from_list; 281 } 282 } 283 284 return 0; 285 286 remove_from_list: 287 LIST_REMOVE(matcher, next); 288 return ret; 289 } 290 291 static int mlx5dr_matcher_disconnect(struct mlx5dr_matcher *matcher) 292 { 293 struct mlx5dr_matcher *tmp_matcher, *prev_matcher; 294 struct mlx5dr_table *tbl = matcher->tbl; 295 struct mlx5dr_devx_obj *prev_ft; 296 struct mlx5dr_matcher *next; 297 int ret; 298 299 if (matcher->attr.isolated) { 300 LIST_REMOVE(matcher, next); 301 return 0; 302 } 303 304 prev_ft = tbl->ft; 305 prev_matcher = LIST_FIRST(&tbl->head); 306 LIST_FOREACH(tmp_matcher, &tbl->head, next) { 307 if (tmp_matcher == matcher) 308 break; 309 310 prev_ft = tmp_matcher->end_ft; 311 prev_matcher = tmp_matcher; 312 } 313 314 next = matcher->next.le_next; 315 316 LIST_REMOVE(matcher, next); 317 318 if (next) { 319 /* Connect previous end FT to next RTC */ 320 ret = mlx5dr_table_ft_set_next_rtc(prev_ft, 321 tbl->fw_ft_type, 322 next->match_ste.rtc_0, 323 next->match_ste.rtc_1); 324 if (ret) { 325 DR_LOG(ERR, "Failed to disconnect matcher"); 326 goto matcher_reconnect; 327 } 328 } else { 329 ret = mlx5dr_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl, true); 330 if (ret) { 331 DR_LOG(ERR, "Failed to disconnect last matcher"); 332 goto matcher_reconnect; 333 } 334 } 335 336 ret = mlx5dr_matcher_shared_update_local_ft(tbl); 337 if (ret) { 338 DR_LOG(ERR, "Failed to update local_ft in shared table"); 339 goto matcher_reconnect; 340 } 341 342 /* Removing first matcher, update connected miss tables if exists */ 343 if (prev_ft == tbl->ft) { 344 ret = mlx5dr_table_update_connected_miss_tables(tbl); 345 if (ret) { 346 DR_LOG(ERR, "Fatal error, failed to update connected miss table"); 347 goto matcher_reconnect; 348 } 349 } 350 351 ret = mlx5dr_table_ft_set_default_next_ft(tbl, prev_ft); 352 if (ret) { 353 DR_LOG(ERR, "Fatal error, failed to restore matcher ft default miss"); 354 goto matcher_reconnect; 355 } 356 357 return 0; 358 359 matcher_reconnect: 360 if (LIST_EMPTY(&tbl->head) || prev_matcher == matcher) 361 LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next); 362 else 363 LIST_INSERT_AFTER(prev_matcher, matcher, next); 364 365 return ret; 366 } 367 368 static bool mlx5dr_matcher_supp_fw_wqe(struct mlx5dr_matcher *matcher) 369 { 370 struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps; 371 372 if (matcher->flags & MLX5DR_MATCHER_FLAGS_HASH_DEFINER) { 373 if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_MATCH && 374 !IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_8DW)) { 375 DR_LOG(ERR, "Gen WQE MATCH format not supported"); 376 return false; 377 } 378 379 if (matcher->hash_definer->type == MLX5DR_DEFINER_TYPE_JUMBO) { 380 DR_LOG(ERR, "Gen WQE JUMBO format not supported"); 381 return false; 382 } 383 } 384 385 if (matcher->attr.insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH || 386 matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) { 387 DR_LOG(ERR, "Gen WQE must be inserted and distribute by hash"); 388 return false; 389 } 390 391 if ((matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) && 392 !IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_RANGE)) { 393 DR_LOG(INFO, "Extended match gen wqe RANGE format not supported"); 394 return false; 395 } 396 397 if (!(caps->supp_type_gen_wqe & MLX5_GENERATE_WQE_TYPE_FLOW_UPDATE)) { 398 DR_LOG(ERR, "Gen WQE command not supporting GTA"); 399 return false; 400 } 401 402 if (!caps->rtc_max_hash_def_gen_wqe) { 403 DR_LOG(ERR, "Hash definer not supported"); 404 return false; 405 } 406 407 return true; 408 } 409 410 static void mlx5dr_matcher_set_rtc_attr_sz(struct mlx5dr_matcher *matcher, 411 struct mlx5dr_cmd_rtc_create_attr *rtc_attr, 412 enum mlx5dr_matcher_rtc_type rtc_type, 413 bool is_mirror) 414 { 415 enum mlx5dr_matcher_flow_src flow_src = matcher->attr.optimize_flow_src; 416 bool is_match_rtc = rtc_type == DR_MATCHER_RTC_TYPE_MATCH; 417 struct mlx5dr_pool_chunk *ste = &matcher->action_ste.ste; 418 419 if ((flow_src == MLX5DR_MATCHER_FLOW_SRC_VPORT && !is_mirror) || 420 (flow_src == MLX5DR_MATCHER_FLOW_SRC_WIRE && is_mirror)) { 421 /* Optimize FDB RTC */ 422 rtc_attr->log_size = 0; 423 rtc_attr->log_depth = 0; 424 } else { 425 /* Keep original values */ 426 rtc_attr->log_size = is_match_rtc ? matcher->attr.table.sz_row_log : ste->order; 427 rtc_attr->log_depth = is_match_rtc ? matcher->attr.table.sz_col_log : 0; 428 } 429 } 430 431 int mlx5dr_matcher_create_aliased_obj(struct mlx5dr_context *ctx, 432 struct ibv_context *ibv_owner, 433 struct ibv_context *ibv_allowed, 434 uint16_t vhca_id_to_be_accessed, 435 uint32_t aliased_object_id, 436 uint16_t object_type, 437 struct mlx5dr_devx_obj **obj) 438 { 439 struct mlx5dr_cmd_allow_other_vhca_access_attr allow_attr = {0}; 440 struct mlx5dr_cmd_alias_obj_create_attr alias_attr = {0}; 441 char key[ACCESS_KEY_LEN]; 442 int ret; 443 int i; 444 445 if (!mlx5dr_context_shared_gvmi_used(ctx)) 446 return 0; 447 448 for (i = 0; i < ACCESS_KEY_LEN; i++) 449 key[i] = rte_rand() & 0xFF; 450 451 memcpy(allow_attr.access_key, key, ACCESS_KEY_LEN); 452 allow_attr.obj_type = object_type; 453 allow_attr.obj_id = aliased_object_id; 454 455 ret = mlx5dr_cmd_allow_other_vhca_access(ibv_owner, &allow_attr); 456 if (ret) { 457 DR_LOG(ERR, "Failed to allow RTC to be aliased"); 458 return ret; 459 } 460 461 memcpy(alias_attr.access_key, key, ACCESS_KEY_LEN); 462 alias_attr.obj_id = aliased_object_id; 463 alias_attr.obj_type = object_type; 464 alias_attr.vhca_id = vhca_id_to_be_accessed; 465 *obj = mlx5dr_cmd_alias_obj_create(ibv_allowed, &alias_attr); 466 if (!*obj) { 467 DR_LOG(ERR, "Failed to create alias object"); 468 return rte_errno; 469 } 470 471 return 0; 472 } 473 474 static int mlx5dr_matcher_create_rtc(struct mlx5dr_matcher *matcher, 475 enum mlx5dr_matcher_rtc_type rtc_type) 476 { 477 struct mlx5dr_matcher_attr *attr = &matcher->attr; 478 struct mlx5dr_cmd_rtc_create_attr rtc_attr = {0}; 479 struct mlx5dr_match_template *mt = matcher->mt; 480 struct mlx5dr_context *ctx = matcher->tbl->ctx; 481 struct mlx5dr_action_default_stc *default_stc; 482 struct mlx5dr_table *tbl = matcher->tbl; 483 struct mlx5dr_devx_obj **rtc_0, **rtc_1; 484 struct mlx5dr_pool *ste_pool, *stc_pool; 485 struct mlx5dr_devx_obj *devx_obj; 486 struct mlx5dr_pool_chunk *ste; 487 int ret; 488 489 switch (rtc_type) { 490 case DR_MATCHER_RTC_TYPE_MATCH: 491 rtc_0 = &matcher->match_ste.rtc_0; 492 rtc_1 = &matcher->match_ste.rtc_1; 493 ste_pool = matcher->match_ste.pool; 494 ste = &matcher->match_ste.ste; 495 ste->order = attr->table.sz_col_log + attr->table.sz_row_log; 496 497 /* Add additional rows due to additional range STE */ 498 if (mlx5dr_matcher_mt_is_range(mt)) 499 ste->order++; 500 501 rtc_attr.log_size = attr->table.sz_row_log; 502 rtc_attr.log_depth = attr->table.sz_col_log; 503 rtc_attr.is_frst_jumbo = mlx5dr_matcher_mt_is_jumbo(mt); 504 rtc_attr.is_scnd_range = mlx5dr_matcher_mt_is_range(mt); 505 rtc_attr.is_compare = mlx5dr_matcher_is_compare(matcher); 506 rtc_attr.miss_ft_id = matcher->end_ft->id; 507 508 if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH) { 509 /* The usual Hash Table */ 510 rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_HASH; 511 512 if (matcher->hash_definer) { 513 /* Specify definer_id_0 is used for hashing */ 514 rtc_attr.fw_gen_wqe = true; 515 rtc_attr.num_hash_definer = 1; 516 rtc_attr.match_definer_0 = 517 mlx5dr_definer_get_id(matcher->hash_definer); 518 } else if (mlx5dr_matcher_is_compare(matcher)) { 519 rtc_attr.match_definer_0 = ctx->caps->trivial_match_definer; 520 rtc_attr.fw_gen_wqe = true; 521 rtc_attr.num_hash_definer = 1; 522 } else { 523 /* The first mt is used since all share the same definer */ 524 rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer); 525 526 /* This is tricky, instead of passing two definers for 527 * match and range, we specify that this RTC uses a hash 528 * definer, this will allow us to use any range definer 529 * since only first STE is used for hashing anyways. 530 */ 531 if (matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) { 532 rtc_attr.fw_gen_wqe = true; 533 rtc_attr.num_hash_definer = 1; 534 } 535 } 536 } else if (attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) { 537 rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET; 538 539 if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) { 540 /* Hash Split Table */ 541 if (mlx5dr_matcher_is_always_hit(matcher)) 542 rtc_attr.num_hash_definer = 1; 543 544 rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_BY_HASH; 545 rtc_attr.match_definer_0 = mlx5dr_definer_get_id(mt->definer); 546 } else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) { 547 /* Linear Lookup Table */ 548 rtc_attr.num_hash_definer = 1; 549 rtc_attr.access_index_mode = MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR; 550 rtc_attr.match_definer_0 = ctx->caps->linear_match_definer; 551 } 552 } 553 554 /* Match pool requires implicit allocation */ 555 ret = mlx5dr_pool_chunk_alloc(ste_pool, ste); 556 if (ret) { 557 DR_LOG(ERR, "Failed to allocate STE for %s RTC", 558 mlx5dr_matcher_rtc_type_to_str(rtc_type)); 559 return ret; 560 } 561 break; 562 563 case DR_MATCHER_RTC_TYPE_STE_ARRAY: 564 rtc_0 = &matcher->action_ste.rtc_0; 565 rtc_1 = &matcher->action_ste.rtc_1; 566 ste_pool = matcher->action_ste.pool; 567 ste = &matcher->action_ste.ste; 568 ste->order = rte_log2_u32(matcher->action_ste.max_stes) + 569 attr->table.sz_row_log; 570 rtc_attr.log_size = ste->order; 571 rtc_attr.log_depth = 0; 572 rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET; 573 /* The action STEs use the default always hit definer */ 574 rtc_attr.match_definer_0 = ctx->caps->trivial_match_definer; 575 rtc_attr.is_frst_jumbo = false; 576 rtc_attr.miss_ft_id = 0; 577 break; 578 579 default: 580 DR_LOG(ERR, "HWS Invalid RTC type"); 581 rte_errno = EINVAL; 582 return rte_errno; 583 } 584 585 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste); 586 587 rtc_attr.pd = ctx->pd_num; 588 rtc_attr.ste_base = devx_obj->id; 589 rtc_attr.ste_offset = ste->offset; 590 rtc_attr.reparse_mode = mlx5dr_context_get_reparse_mode(ctx); 591 rtc_attr.table_type = mlx5dr_table_get_res_fw_ft_type(tbl->type, false); 592 mlx5dr_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, false); 593 594 /* STC is a single resource (devx_obj), use any STC for the ID */ 595 stc_pool = ctx->stc_pool[tbl->type]; 596 default_stc = ctx->common_res[tbl->type].default_stc; 597 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(stc_pool, &default_stc->default_hit); 598 rtc_attr.stc_base = devx_obj->id; 599 600 *rtc_0 = mlx5dr_cmd_rtc_create(ctx->ibv_ctx, &rtc_attr); 601 if (!*rtc_0) { 602 DR_LOG(ERR, "Failed to create matcher RTC of type %s", 603 mlx5dr_matcher_rtc_type_to_str(rtc_type)); 604 goto free_ste; 605 } 606 607 if (tbl->type == MLX5DR_TABLE_TYPE_FDB) { 608 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste); 609 rtc_attr.ste_base = devx_obj->id; 610 rtc_attr.table_type = mlx5dr_table_get_res_fw_ft_type(tbl->type, true); 611 612 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(stc_pool, &default_stc->default_hit); 613 rtc_attr.stc_base = devx_obj->id; 614 mlx5dr_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, true); 615 616 *rtc_1 = mlx5dr_cmd_rtc_create(ctx->ibv_ctx, &rtc_attr); 617 if (!*rtc_1) { 618 DR_LOG(ERR, "Failed to create peer matcher RTC of type %s", 619 mlx5dr_matcher_rtc_type_to_str(rtc_type)); 620 goto destroy_rtc_0; 621 } 622 } 623 624 return 0; 625 626 destroy_rtc_0: 627 mlx5dr_cmd_destroy_obj(*rtc_0); 628 free_ste: 629 if (rtc_type == DR_MATCHER_RTC_TYPE_MATCH) 630 mlx5dr_pool_chunk_free(ste_pool, ste); 631 return rte_errno; 632 } 633 634 static void mlx5dr_matcher_destroy_rtc(struct mlx5dr_matcher *matcher, 635 enum mlx5dr_matcher_rtc_type rtc_type) 636 { 637 struct mlx5dr_table *tbl = matcher->tbl; 638 struct mlx5dr_devx_obj *rtc_0, *rtc_1; 639 struct mlx5dr_pool_chunk *ste; 640 struct mlx5dr_pool *ste_pool; 641 642 switch (rtc_type) { 643 case DR_MATCHER_RTC_TYPE_MATCH: 644 rtc_0 = matcher->match_ste.rtc_0; 645 rtc_1 = matcher->match_ste.rtc_1; 646 ste_pool = matcher->match_ste.pool; 647 ste = &matcher->match_ste.ste; 648 break; 649 case DR_MATCHER_RTC_TYPE_STE_ARRAY: 650 rtc_0 = matcher->action_ste.rtc_0; 651 rtc_1 = matcher->action_ste.rtc_1; 652 ste_pool = matcher->action_ste.pool; 653 ste = &matcher->action_ste.ste; 654 break; 655 default: 656 return; 657 } 658 659 if (tbl->type == MLX5DR_TABLE_TYPE_FDB) 660 mlx5dr_cmd_destroy_obj(rtc_1); 661 662 mlx5dr_cmd_destroy_obj(rtc_0); 663 if (rtc_type == DR_MATCHER_RTC_TYPE_MATCH) 664 mlx5dr_pool_chunk_free(ste_pool, ste); 665 } 666 667 static int 668 mlx5dr_matcher_check_attr_sz(struct mlx5dr_cmd_query_caps *caps, 669 struct mlx5dr_matcher_attr *attr) 670 { 671 if (attr->table.sz_col_log > caps->rtc_log_depth_max) { 672 DR_LOG(ERR, "Matcher depth exceeds limit %d", caps->rtc_log_depth_max); 673 goto not_supported; 674 } 675 676 if (attr->table.sz_col_log + attr->table.sz_row_log > caps->ste_alloc_log_max) { 677 DR_LOG(ERR, "Total matcher size exceeds limit %d", caps->ste_alloc_log_max); 678 goto not_supported; 679 } 680 681 if (attr->table.sz_col_log + attr->table.sz_row_log < caps->ste_alloc_log_gran) { 682 DR_LOG(ERR, "Total matcher size below limit %d", caps->ste_alloc_log_gran); 683 goto not_supported; 684 } 685 686 return 0; 687 688 not_supported: 689 rte_errno = EOPNOTSUPP; 690 return rte_errno; 691 } 692 693 static void mlx5dr_matcher_set_pool_attr(struct mlx5dr_pool_attr *attr, 694 struct mlx5dr_matcher *matcher) 695 { 696 switch (matcher->attr.optimize_flow_src) { 697 case MLX5DR_MATCHER_FLOW_SRC_VPORT: 698 attr->opt_type = MLX5DR_POOL_OPTIMIZE_ORIG; 699 break; 700 case MLX5DR_MATCHER_FLOW_SRC_WIRE: 701 attr->opt_type = MLX5DR_POOL_OPTIMIZE_MIRROR; 702 break; 703 default: 704 break; 705 } 706 } 707 708 static int mlx5dr_matcher_check_and_process_at(struct mlx5dr_matcher *matcher, 709 struct mlx5dr_action_template *at) 710 { 711 bool valid; 712 int ret; 713 714 if (!(at->flags & MLX5DR_ACTION_TEMPLATE_FLAG_RELAXED_ORDER)) { 715 /* Check if actions combinabtion is valid, 716 * in the case of not relaxed actions order. 717 */ 718 valid = mlx5dr_action_check_combo(at->action_type_arr, matcher->tbl->type); 719 if (!valid) { 720 DR_LOG(ERR, "Invalid combination in action template"); 721 rte_errno = EINVAL; 722 return rte_errno; 723 } 724 } 725 726 /* Process action template to setters */ 727 ret = mlx5dr_action_template_process(at); 728 if (ret) { 729 DR_LOG(ERR, "Failed to process action template"); 730 return ret; 731 } 732 733 return 0; 734 } 735 736 static int 737 mlx5dr_matcher_resize_init(struct mlx5dr_matcher *src_matcher) 738 { 739 struct mlx5dr_matcher_resize_data *resize_data; 740 741 resize_data = simple_calloc(1, sizeof(*resize_data)); 742 if (!resize_data) { 743 rte_errno = ENOMEM; 744 return rte_errno; 745 } 746 747 resize_data->max_stes = src_matcher->action_ste.max_stes; 748 resize_data->ste = src_matcher->action_ste.ste; 749 resize_data->stc = src_matcher->action_ste.stc; 750 resize_data->action_ste_rtc_0 = src_matcher->action_ste.rtc_0; 751 resize_data->action_ste_rtc_1 = src_matcher->action_ste.rtc_1; 752 resize_data->action_ste_pool = src_matcher->action_ste.max_stes ? 753 src_matcher->action_ste.pool : 754 NULL; 755 756 /* Place the new resized matcher on the dst matcher's list */ 757 LIST_INSERT_HEAD(&src_matcher->resize_dst->resize_data, 758 resize_data, next); 759 760 /* Move all the previous resized matchers to the dst matcher's list */ 761 while (!LIST_EMPTY(&src_matcher->resize_data)) { 762 resize_data = LIST_FIRST(&src_matcher->resize_data); 763 LIST_REMOVE(resize_data, next); 764 LIST_INSERT_HEAD(&src_matcher->resize_dst->resize_data, 765 resize_data, next); 766 } 767 768 return 0; 769 } 770 771 static void 772 mlx5dr_matcher_resize_uninit(struct mlx5dr_matcher *matcher) 773 { 774 struct mlx5dr_matcher_resize_data *resize_data; 775 776 if (!mlx5dr_matcher_is_resizable(matcher)) 777 return; 778 779 while (!LIST_EMPTY(&matcher->resize_data)) { 780 resize_data = LIST_FIRST(&matcher->resize_data); 781 LIST_REMOVE(resize_data, next); 782 783 if (resize_data->max_stes) { 784 mlx5dr_action_free_single_stc(matcher->tbl->ctx, 785 matcher->tbl->type, 786 &resize_data->stc); 787 788 if (matcher->tbl->type == MLX5DR_TABLE_TYPE_FDB) 789 mlx5dr_cmd_destroy_obj(resize_data->action_ste_rtc_1); 790 mlx5dr_cmd_destroy_obj(resize_data->action_ste_rtc_0); 791 if (resize_data->action_ste_pool) 792 mlx5dr_pool_destroy(resize_data->action_ste_pool); 793 } 794 795 simple_free(resize_data); 796 } 797 } 798 799 static int mlx5dr_matcher_bind_at(struct mlx5dr_matcher *matcher) 800 { 801 bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt); 802 struct mlx5dr_cmd_stc_modify_attr stc_attr = {0}; 803 struct mlx5dr_table *tbl = matcher->tbl; 804 struct mlx5dr_pool_attr pool_attr = {0}; 805 struct mlx5dr_context *ctx = tbl->ctx; 806 uint32_t required_stes; 807 int i, ret; 808 809 if (matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION) 810 return 0; 811 812 if (matcher->attr.max_num_of_at_attach && 813 mlx5dr_matcher_req_fw_wqe(matcher)) { 814 DR_LOG(ERR, "FW extended matcher doesn't support additional at"); 815 rte_errno = ENOTSUP; 816 return rte_errno; 817 } 818 819 for (i = 0; i < matcher->num_of_at; i++) { 820 struct mlx5dr_action_template *at = &matcher->at[i]; 821 822 ret = mlx5dr_matcher_check_and_process_at(matcher, at); 823 if (ret) { 824 DR_LOG(ERR, "Invalid at %d", i); 825 return rte_errno; 826 } 827 828 required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term); 829 matcher->action_ste.max_stes = RTE_MAX(matcher->action_ste.max_stes, required_stes); 830 831 /* Future: Optimize reparse */ 832 } 833 834 /* There are no additioanl STEs required for matcher */ 835 if (!matcher->action_ste.max_stes) 836 return 0; 837 838 if (mlx5dr_matcher_req_fw_wqe(matcher)) { 839 DR_LOG(ERR, "FW extended matcher cannot be binded to complex at"); 840 rte_errno = ENOTSUP; 841 return rte_errno; 842 } 843 844 /* Allocate action STE mempool */ 845 pool_attr.table_type = tbl->type; 846 pool_attr.pool_type = MLX5DR_POOL_TYPE_STE; 847 pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_STE_ACTION_POOL; 848 pool_attr.alloc_log_sz = rte_log2_u32(matcher->action_ste.max_stes) + 849 matcher->attr.table.sz_row_log; 850 mlx5dr_matcher_set_pool_attr(&pool_attr, matcher); 851 matcher->action_ste.pool = mlx5dr_pool_create(ctx, &pool_attr); 852 if (!matcher->action_ste.pool) { 853 DR_LOG(ERR, "Failed to create action ste pool"); 854 return rte_errno; 855 } 856 857 /* Allocate action RTC */ 858 ret = mlx5dr_matcher_create_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY); 859 if (ret) { 860 DR_LOG(ERR, "Failed to create action RTC"); 861 goto free_ste_pool; 862 } 863 864 /* Allocate STC for jumps to STE */ 865 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT; 866 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE; 867 stc_attr.reparse_mode = MLX5_IFC_STC_REPARSE_IGNORE; 868 stc_attr.ste_table.ste = matcher->action_ste.ste; 869 stc_attr.ste_table.ste_pool = matcher->action_ste.pool; 870 stc_attr.ste_table.match_definer_id = ctx->caps->trivial_match_definer; 871 872 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl->type, 873 &matcher->action_ste.stc); 874 if (ret) { 875 DR_LOG(ERR, "Failed to create action jump to table STC"); 876 goto free_rtc; 877 } 878 879 return 0; 880 881 free_rtc: 882 mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY); 883 free_ste_pool: 884 mlx5dr_pool_destroy(matcher->action_ste.pool); 885 return rte_errno; 886 } 887 888 static void mlx5dr_matcher_unbind_at(struct mlx5dr_matcher *matcher) 889 { 890 struct mlx5dr_table *tbl = matcher->tbl; 891 892 if (!matcher->action_ste.max_stes || 893 matcher->flags & MLX5DR_MATCHER_FLAGS_COLLISION || 894 mlx5dr_matcher_is_in_resize(matcher)) 895 return; 896 897 mlx5dr_action_free_single_stc(tbl->ctx, tbl->type, &matcher->action_ste.stc); 898 mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_STE_ARRAY); 899 mlx5dr_pool_destroy(matcher->action_ste.pool); 900 } 901 902 static int mlx5dr_matcher_bind_mt(struct mlx5dr_matcher *matcher) 903 { 904 struct mlx5dr_context *ctx = matcher->tbl->ctx; 905 struct mlx5dr_pool_attr pool_attr = {0}; 906 int ret; 907 908 /* Calculate match, range and hash definers */ 909 ret = mlx5dr_definer_matcher_init(ctx, matcher); 910 if (ret) { 911 DR_LOG(DEBUG, "Failed to set matcher templates with match definers"); 912 return ret; 913 } 914 915 if (mlx5dr_matcher_req_fw_wqe(matcher) && 916 !mlx5dr_matcher_supp_fw_wqe(matcher)) { 917 DR_LOG(ERR, "Matcher requires FW WQE which is not supported"); 918 rte_errno = ENOTSUP; 919 ret = rte_errno; 920 goto uninit_match_definer; 921 } 922 923 /* Create an STE pool per matcher*/ 924 pool_attr.table_type = matcher->tbl->type; 925 pool_attr.pool_type = MLX5DR_POOL_TYPE_STE; 926 pool_attr.flags = MLX5DR_POOL_FLAGS_FOR_MATCHER_STE_POOL; 927 pool_attr.alloc_log_sz = matcher->attr.table.sz_col_log + 928 matcher->attr.table.sz_row_log; 929 /* Add additional rows due to additional range STE */ 930 if (matcher->flags & MLX5DR_MATCHER_FLAGS_RANGE_DEFINER) 931 pool_attr.alloc_log_sz++; 932 mlx5dr_matcher_set_pool_attr(&pool_attr, matcher); 933 934 matcher->match_ste.pool = mlx5dr_pool_create(ctx, &pool_attr); 935 if (!matcher->match_ste.pool) { 936 DR_LOG(ERR, "Failed to allocate matcher STE pool"); 937 ret = ENOTSUP; 938 goto uninit_match_definer; 939 } 940 941 return 0; 942 943 uninit_match_definer: 944 mlx5dr_definer_matcher_uninit(matcher); 945 return ret; 946 } 947 948 static void mlx5dr_matcher_unbind_mt(struct mlx5dr_matcher *matcher) 949 { 950 mlx5dr_pool_destroy(matcher->match_ste.pool); 951 mlx5dr_definer_matcher_uninit(matcher); 952 } 953 954 static int 955 mlx5dr_matcher_validate_insert_mode(struct mlx5dr_cmd_query_caps *caps, 956 struct mlx5dr_matcher *matcher, 957 bool is_root) 958 { 959 struct mlx5dr_matcher_attr *attr = &matcher->attr; 960 961 if (is_root) { 962 if (attr->mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE) { 963 DR_LOG(ERR, "Root matcher supports only rule resource mode"); 964 goto not_supported; 965 } 966 if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH) { 967 DR_LOG(ERR, "Root matcher supports only insert by hash mode"); 968 goto not_supported; 969 } 970 if (attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) { 971 DR_LOG(ERR, "Root matcher supports only distribute by hash mode"); 972 goto not_supported; 973 } 974 if (attr->optimize_flow_src) { 975 DR_LOG(ERR, "Root matcher can't specify FDB direction"); 976 goto not_supported; 977 } 978 } 979 980 switch (attr->insert_mode) { 981 case MLX5DR_MATCHER_INSERT_BY_HASH: 982 if (matcher->attr.distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) { 983 DR_LOG(ERR, "Invalid matcher distribute mode"); 984 goto not_supported; 985 } 986 break; 987 988 case MLX5DR_MATCHER_INSERT_BY_INDEX: 989 if (attr->table.sz_col_log) { 990 DR_LOG(ERR, "Matcher with INSERT_BY_INDEX supports only Nx1 table size"); 991 goto not_supported; 992 } 993 994 if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) { 995 /* Hash Split Table */ 996 if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT && 997 !caps->rtc_hash_split_table) { 998 DR_LOG(ERR, "FW doesn't support insert by index and hash distribute"); 999 goto not_supported; 1000 } 1001 1002 if (attr->match_mode == MLX5DR_MATCHER_MATCH_MODE_DEFAULT && 1003 !attr->isolated) { 1004 DR_LOG(ERR, "STE array matcher supported only as an isolated matcher"); 1005 goto not_supported; 1006 } 1007 } else if (attr->distribute_mode == MLX5DR_MATCHER_DISTRIBUTE_BY_LINEAR) { 1008 /* Linear Lookup Table */ 1009 if (!caps->rtc_linear_lookup_table || 1010 !IS_BIT_SET(caps->access_index_mode, 1011 MLX5_IFC_RTC_STE_ACCESS_MODE_LINEAR)) { 1012 DR_LOG(ERR, "FW doesn't support insert by index and linear distribute"); 1013 goto not_supported; 1014 } 1015 1016 if (attr->table.sz_row_log > MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX) { 1017 DR_LOG(ERR, "Matcher with linear distribute: rows exceed limit %d", 1018 MLX5_IFC_RTC_LINEAR_LOOKUP_TBL_LOG_MAX); 1019 goto not_supported; 1020 } 1021 1022 if (attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_ALWAYS_HIT) { 1023 DR_LOG(ERR, "Linear lookup tables will always hit, given match mode is not supported %d\n", 1024 attr->match_mode); 1025 goto not_supported; 1026 } 1027 } else { 1028 DR_LOG(ERR, "Matcher has unsupported distribute mode"); 1029 goto not_supported; 1030 } 1031 break; 1032 1033 default: 1034 DR_LOG(ERR, "Matcher has unsupported insert mode"); 1035 goto not_supported; 1036 } 1037 1038 return 0; 1039 1040 not_supported: 1041 rte_errno = EOPNOTSUPP; 1042 return rte_errno; 1043 } 1044 1045 static int 1046 mlx5dr_matcher_process_attr(struct mlx5dr_cmd_query_caps *caps, 1047 struct mlx5dr_matcher *matcher, 1048 bool is_root) 1049 { 1050 struct mlx5dr_matcher_attr *attr = &matcher->attr; 1051 1052 if (mlx5dr_matcher_validate_insert_mode(caps, matcher, is_root)) 1053 goto not_supported; 1054 1055 if (is_root) { 1056 if (attr->optimize_flow_src) { 1057 DR_LOG(ERR, "Root matcher can't specify FDB direction"); 1058 goto not_supported; 1059 } 1060 if (attr->max_num_of_at_attach) { 1061 DR_LOG(ERR, "Root matcher does not support at attaching"); 1062 goto not_supported; 1063 } 1064 if (attr->resizable) { 1065 DR_LOG(ERR, "Root matcher does not support resizing"); 1066 goto not_supported; 1067 } 1068 if (attr->isolated) { 1069 DR_LOG(ERR, "Root matcher can not be isolated"); 1070 goto not_supported; 1071 } 1072 1073 return 0; 1074 } 1075 1076 if (matcher->tbl->type != MLX5DR_TABLE_TYPE_FDB && attr->optimize_flow_src) { 1077 DR_LOG(ERR, "NIC domain doesn't support flow_src"); 1078 goto not_supported; 1079 } 1080 1081 /* Convert number of rules to the required depth */ 1082 if (attr->mode == MLX5DR_MATCHER_RESOURCE_MODE_RULE && 1083 attr->insert_mode == MLX5DR_MATCHER_INSERT_BY_HASH) 1084 attr->table.sz_col_log = mlx5dr_matcher_rules_to_tbl_depth(attr->rule.num_log); 1085 1086 if (attr->isolated) { 1087 if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_INDEX || 1088 attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH || 1089 attr->match_mode != MLX5DR_MATCHER_MATCH_MODE_DEFAULT) { 1090 DR_LOG(ERR, "Isolated matcher only supported for STE array matcher"); 1091 goto not_supported; 1092 } 1093 1094 /* We reach here only in case of STE array */ 1095 matcher->flags |= MLX5DR_MATCHER_FLAGS_STE_ARRAY; 1096 } 1097 1098 matcher->flags |= attr->resizable ? MLX5DR_MATCHER_FLAGS_RESIZABLE : 0; 1099 1100 return mlx5dr_matcher_check_attr_sz(caps, attr); 1101 1102 not_supported: 1103 rte_errno = EOPNOTSUPP; 1104 return rte_errno; 1105 } 1106 1107 static int mlx5dr_matcher_create_and_connect(struct mlx5dr_matcher *matcher) 1108 { 1109 int ret; 1110 1111 /* Select and create the definers for current matcher */ 1112 ret = mlx5dr_matcher_bind_mt(matcher); 1113 if (ret) 1114 return ret; 1115 1116 /* Calculate and verify action combination */ 1117 ret = mlx5dr_matcher_bind_at(matcher); 1118 if (ret) 1119 goto unbind_mt; 1120 1121 /* Create matcher end flow table anchor */ 1122 ret = mlx5dr_matcher_create_end_ft(matcher); 1123 if (ret) 1124 goto unbind_at; 1125 1126 /* Allocate the RTC for the new matcher */ 1127 ret = mlx5dr_matcher_create_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH); 1128 if (ret) 1129 goto destroy_end_ft; 1130 1131 /* Allocate and set shared resources */ 1132 ret = mlx5dr_matcher_create_init_shared(matcher); 1133 if (ret) 1134 goto destroy_rtc; 1135 1136 /* Connect the matcher to the matcher list */ 1137 ret = mlx5dr_matcher_connect(matcher); 1138 if (ret) 1139 goto destroy_shared; 1140 1141 return 0; 1142 1143 destroy_shared: 1144 mlx5dr_matcher_create_uninit_shared(matcher); 1145 destroy_rtc: 1146 mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH); 1147 destroy_end_ft: 1148 mlx5dr_matcher_destroy_end_ft(matcher); 1149 unbind_at: 1150 mlx5dr_matcher_unbind_at(matcher); 1151 unbind_mt: 1152 mlx5dr_matcher_unbind_mt(matcher); 1153 return ret; 1154 } 1155 1156 static void mlx5dr_matcher_destroy_and_disconnect(struct mlx5dr_matcher *matcher) 1157 { 1158 mlx5dr_matcher_resize_uninit(matcher); 1159 mlx5dr_matcher_disconnect(matcher); 1160 mlx5dr_matcher_create_uninit_shared(matcher); 1161 mlx5dr_matcher_destroy_rtc(matcher, DR_MATCHER_RTC_TYPE_MATCH); 1162 mlx5dr_matcher_destroy_end_ft(matcher); 1163 mlx5dr_matcher_unbind_at(matcher); 1164 mlx5dr_matcher_unbind_mt(matcher); 1165 } 1166 1167 static int 1168 mlx5dr_matcher_create_col_matcher(struct mlx5dr_matcher *matcher) 1169 { 1170 struct mlx5dr_context *ctx = matcher->tbl->ctx; 1171 struct mlx5dr_matcher *col_matcher; 1172 int ret; 1173 1174 if (matcher->attr.mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE || 1175 matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) 1176 return 0; 1177 1178 if (!mlx5dr_matcher_requires_col_tbl(matcher->attr.rule.num_log)) 1179 return 0; 1180 1181 col_matcher = simple_calloc(1, sizeof(*matcher)); 1182 if (!col_matcher) { 1183 rte_errno = ENOMEM; 1184 return rte_errno; 1185 } 1186 1187 col_matcher->tbl = matcher->tbl; 1188 col_matcher->mt = matcher->mt; 1189 col_matcher->at = matcher->at; 1190 col_matcher->num_of_at = matcher->num_of_at; 1191 col_matcher->num_of_mt = matcher->num_of_mt; 1192 col_matcher->hash_definer = matcher->hash_definer; 1193 col_matcher->attr.priority = matcher->attr.priority; 1194 col_matcher->flags = matcher->flags; 1195 col_matcher->flags |= MLX5DR_MATCHER_FLAGS_COLLISION; 1196 col_matcher->attr.mode = MLX5DR_MATCHER_RESOURCE_MODE_HTABLE; 1197 col_matcher->attr.optimize_flow_src = matcher->attr.optimize_flow_src; 1198 col_matcher->attr.table.sz_row_log = matcher->attr.rule.num_log; 1199 col_matcher->attr.table.sz_col_log = MLX5DR_MATCHER_ASSURED_COL_TBL_DEPTH; 1200 if (col_matcher->attr.table.sz_row_log > MLX5DR_MATCHER_ASSURED_ROW_RATIO) 1201 col_matcher->attr.table.sz_row_log -= MLX5DR_MATCHER_ASSURED_ROW_RATIO; 1202 1203 col_matcher->attr.max_num_of_at_attach = matcher->attr.max_num_of_at_attach; 1204 1205 ret = mlx5dr_matcher_process_attr(ctx->caps, col_matcher, false); 1206 if (ret) 1207 goto free_col_matcher; 1208 1209 ret = mlx5dr_matcher_create_and_connect(col_matcher); 1210 if (ret) 1211 goto free_col_matcher; 1212 1213 matcher->col_matcher = col_matcher; 1214 1215 return 0; 1216 1217 free_col_matcher: 1218 simple_free(col_matcher); 1219 DR_LOG(ERR, "Failed to create assured collision matcher"); 1220 return ret; 1221 } 1222 1223 static void 1224 mlx5dr_matcher_destroy_col_matcher(struct mlx5dr_matcher *matcher) 1225 { 1226 if (matcher->attr.mode != MLX5DR_MATCHER_RESOURCE_MODE_RULE || 1227 matcher->attr.insert_mode == MLX5DR_MATCHER_INSERT_BY_INDEX) 1228 return; 1229 1230 if (matcher->col_matcher) { 1231 mlx5dr_matcher_destroy_and_disconnect(matcher->col_matcher); 1232 simple_free(matcher->col_matcher); 1233 } 1234 } 1235 1236 static int mlx5dr_matcher_init(struct mlx5dr_matcher *matcher) 1237 { 1238 struct mlx5dr_context *ctx = matcher->tbl->ctx; 1239 int ret; 1240 1241 pthread_spin_lock(&ctx->ctrl_lock); 1242 1243 /* Allocate matcher resource and connect to the packet pipe */ 1244 ret = mlx5dr_matcher_create_and_connect(matcher); 1245 if (ret) 1246 goto unlock_err; 1247 1248 /* Create additional matcher for collision handling */ 1249 ret = mlx5dr_matcher_create_col_matcher(matcher); 1250 if (ret) 1251 goto destory_and_disconnect; 1252 1253 pthread_spin_unlock(&ctx->ctrl_lock); 1254 1255 return 0; 1256 1257 destory_and_disconnect: 1258 mlx5dr_matcher_destroy_and_disconnect(matcher); 1259 unlock_err: 1260 pthread_spin_unlock(&ctx->ctrl_lock); 1261 return ret; 1262 } 1263 1264 static int mlx5dr_matcher_uninit(struct mlx5dr_matcher *matcher) 1265 { 1266 struct mlx5dr_context *ctx = matcher->tbl->ctx; 1267 1268 pthread_spin_lock(&ctx->ctrl_lock); 1269 mlx5dr_matcher_destroy_col_matcher(matcher); 1270 mlx5dr_matcher_destroy_and_disconnect(matcher); 1271 pthread_spin_unlock(&ctx->ctrl_lock); 1272 1273 return 0; 1274 } 1275 1276 static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher) 1277 { 1278 enum mlx5dr_table_type type = matcher->tbl->type; 1279 struct mlx5dr_context *ctx = matcher->tbl->ctx; 1280 struct mlx5dv_flow_matcher_attr attr = {0}; 1281 struct mlx5dv_flow_match_parameters *mask; 1282 struct mlx5_flow_attr flow_attr = {0}; 1283 struct rte_flow_error rte_error; 1284 uint8_t match_criteria; 1285 int ret; 1286 1287 #ifdef HAVE_MLX5DV_FLOW_MATCHER_FT_TYPE 1288 attr.comp_mask = MLX5DV_FLOW_MATCHER_MASK_FT_TYPE; 1289 1290 switch (type) { 1291 case MLX5DR_TABLE_TYPE_NIC_RX: 1292 attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 1293 break; 1294 case MLX5DR_TABLE_TYPE_NIC_TX: 1295 attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX; 1296 break; 1297 case MLX5DR_TABLE_TYPE_FDB: 1298 attr.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 1299 break; 1300 default: 1301 assert(0); 1302 break; 1303 } 1304 #endif 1305 1306 if (matcher->attr.priority > UINT16_MAX) { 1307 DR_LOG(ERR, "Root matcher priority exceeds allowed limit"); 1308 rte_errno = EINVAL; 1309 return rte_errno; 1310 } 1311 1312 ret = flow_hw_get_port_id_from_ctx(ctx, &flow_attr.port_id); 1313 if (ret) { 1314 DR_LOG(ERR, "Failed to get port id for dev %s", ctx->ibv_ctx->device->name); 1315 rte_errno = EINVAL; 1316 return rte_errno; 1317 } 1318 1319 mask = simple_calloc(1, MLX5_ST_SZ_BYTES(fte_match_param) + 1320 offsetof(struct mlx5dv_flow_match_parameters, match_buf)); 1321 if (!mask) { 1322 rte_errno = ENOMEM; 1323 return rte_errno; 1324 } 1325 1326 flow_attr.tbl_type = type; 1327 1328 /* On root table matcher, only a single match template is supported */ 1329 ret = flow_dv_translate_items_hws(matcher->mt[0].items, 1330 &flow_attr, mask->match_buf, 1331 MLX5_SET_MATCHER_HS_M, NULL, 1332 &match_criteria, 1333 &rte_error); 1334 if (ret) { 1335 DR_LOG(ERR, "Failed to convert items to PRM [%s]", rte_error.message); 1336 goto free_mask; 1337 } 1338 1339 mask->match_sz = MLX5_ST_SZ_BYTES(fte_match_param); 1340 attr.match_mask = mask; 1341 attr.match_criteria_enable = match_criteria; 1342 attr.type = IBV_FLOW_ATTR_NORMAL; 1343 attr.priority = matcher->attr.priority; 1344 1345 matcher->dv_matcher = 1346 mlx5_glue->dv_create_flow_matcher_root(mlx5dr_context_get_local_ibv(ctx), 1347 &attr); 1348 if (!matcher->dv_matcher) { 1349 DR_LOG(ERR, "Failed to create DV flow matcher"); 1350 rte_errno = errno; 1351 goto free_mask; 1352 } 1353 1354 simple_free(mask); 1355 1356 pthread_spin_lock(&ctx->ctrl_lock); 1357 LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next); 1358 pthread_spin_unlock(&ctx->ctrl_lock); 1359 1360 return 0; 1361 1362 free_mask: 1363 simple_free(mask); 1364 return rte_errno; 1365 } 1366 1367 static int mlx5dr_matcher_uninit_root(struct mlx5dr_matcher *matcher) 1368 { 1369 struct mlx5dr_context *ctx = matcher->tbl->ctx; 1370 int ret; 1371 1372 pthread_spin_lock(&ctx->ctrl_lock); 1373 LIST_REMOVE(matcher, next); 1374 pthread_spin_unlock(&ctx->ctrl_lock); 1375 1376 ret = mlx5_glue->dv_destroy_flow_matcher_root(matcher->dv_matcher); 1377 if (ret) { 1378 DR_LOG(ERR, "Failed to Destroy DV flow matcher"); 1379 rte_errno = errno; 1380 } 1381 1382 return ret; 1383 } 1384 1385 int mlx5dr_matcher_attach_at(struct mlx5dr_matcher *matcher, 1386 struct mlx5dr_action_template *at) 1387 { 1388 bool is_jumbo = mlx5dr_matcher_mt_is_jumbo(matcher->mt); 1389 uint32_t required_stes; 1390 int ret; 1391 1392 if (!matcher->attr.max_num_of_at_attach) { 1393 DR_LOG(DEBUG, "Num of current at (%d) exceed allowed value", 1394 matcher->num_of_at); 1395 rte_errno = ENOTSUP; 1396 return -rte_errno; 1397 } 1398 1399 ret = mlx5dr_matcher_check_and_process_at(matcher, at); 1400 if (ret) 1401 return -rte_errno; 1402 1403 required_stes = at->num_of_action_stes - (!is_jumbo || at->only_term); 1404 if (matcher->action_ste.max_stes < required_stes) { 1405 DR_LOG(DEBUG, "Required STEs [%d] exceeds initial action template STE [%d]", 1406 required_stes, matcher->action_ste.max_stes); 1407 rte_errno = ENOMEM; 1408 return -rte_errno; 1409 } 1410 1411 matcher->at[matcher->num_of_at] = *at; 1412 matcher->num_of_at += 1; 1413 matcher->attr.max_num_of_at_attach -= 1; 1414 1415 if (matcher->col_matcher) 1416 matcher->col_matcher->num_of_at = matcher->num_of_at; 1417 1418 return 0; 1419 } 1420 1421 static int 1422 mlx5dr_matcher_set_templates(struct mlx5dr_matcher *matcher, 1423 struct mlx5dr_match_template *mt[], 1424 uint8_t num_of_mt, 1425 struct mlx5dr_action_template *at[], 1426 uint8_t num_of_at) 1427 { 1428 bool is_root = mlx5dr_table_is_root(matcher->tbl); 1429 int i; 1430 1431 if (!num_of_mt || !num_of_at) { 1432 DR_LOG(ERR, "Number of action/match template cannot be zero"); 1433 rte_errno = ENOTSUP; 1434 return rte_errno; 1435 } 1436 1437 if (is_root && num_of_mt > MLX5DR_MATCHER_MAX_MT_ROOT) { 1438 DR_LOG(ERR, "Number of match templates exceeds limit"); 1439 rte_errno = ENOTSUP; 1440 return rte_errno; 1441 } 1442 1443 matcher->mt = simple_calloc(num_of_mt, sizeof(*matcher->mt)); 1444 if (!matcher->mt) { 1445 DR_LOG(ERR, "Failed to allocate match template array"); 1446 rte_errno = ENOMEM; 1447 return rte_errno; 1448 } 1449 1450 matcher->at = simple_calloc(num_of_at + matcher->attr.max_num_of_at_attach, 1451 sizeof(*matcher->at)); 1452 if (!matcher->at) { 1453 DR_LOG(ERR, "Failed to allocate action template array"); 1454 rte_errno = ENOMEM; 1455 goto free_mt; 1456 } 1457 1458 for (i = 0; i < num_of_mt; i++) 1459 matcher->mt[i] = *mt[i]; 1460 1461 for (i = 0; i < num_of_at; i++) 1462 matcher->at[i] = *at[i]; 1463 1464 matcher->num_of_mt = num_of_mt; 1465 matcher->num_of_at = num_of_at; 1466 1467 return 0; 1468 1469 free_mt: 1470 simple_free(matcher->mt); 1471 return rte_errno; 1472 } 1473 1474 static void 1475 mlx5dr_matcher_unset_templates(struct mlx5dr_matcher *matcher) 1476 { 1477 simple_free(matcher->at); 1478 simple_free(matcher->mt); 1479 } 1480 1481 struct mlx5dr_matcher * 1482 mlx5dr_matcher_create(struct mlx5dr_table *tbl, 1483 struct mlx5dr_match_template *mt[], 1484 uint8_t num_of_mt, 1485 struct mlx5dr_action_template *at[], 1486 uint8_t num_of_at, 1487 struct mlx5dr_matcher_attr *attr) 1488 { 1489 bool is_root = mlx5dr_table_is_root(tbl); 1490 struct mlx5dr_matcher *matcher; 1491 int ret; 1492 1493 matcher = simple_calloc(1, sizeof(*matcher)); 1494 if (!matcher) { 1495 rte_errno = ENOMEM; 1496 return NULL; 1497 } 1498 1499 matcher->tbl = tbl; 1500 matcher->attr = *attr; 1501 1502 ret = mlx5dr_matcher_process_attr(tbl->ctx->caps, matcher, is_root); 1503 if (ret) 1504 goto free_matcher; 1505 1506 ret = mlx5dr_matcher_set_templates(matcher, mt, num_of_mt, at, num_of_at); 1507 if (ret) 1508 goto free_matcher; 1509 1510 if (is_root) 1511 ret = mlx5dr_matcher_init_root(matcher); 1512 else 1513 ret = mlx5dr_matcher_init(matcher); 1514 1515 if (ret) { 1516 DR_LOG(ERR, "Failed to initialise matcher: %d", ret); 1517 goto unset_templates; 1518 } 1519 1520 return matcher; 1521 1522 unset_templates: 1523 mlx5dr_matcher_unset_templates(matcher); 1524 free_matcher: 1525 simple_free(matcher); 1526 return NULL; 1527 } 1528 1529 int mlx5dr_matcher_destroy(struct mlx5dr_matcher *matcher) 1530 { 1531 if (mlx5dr_table_is_root(matcher->tbl)) 1532 mlx5dr_matcher_uninit_root(matcher); 1533 else 1534 mlx5dr_matcher_uninit(matcher); 1535 1536 mlx5dr_matcher_unset_templates(matcher); 1537 simple_free(matcher); 1538 return 0; 1539 } 1540 1541 struct mlx5dr_match_template * 1542 mlx5dr_match_template_create(const struct rte_flow_item items[], 1543 enum mlx5dr_match_template_flags flags) 1544 { 1545 struct mlx5dr_match_template *mt; 1546 struct rte_flow_error error; 1547 int ret, len; 1548 1549 if (flags > MLX5DR_MATCH_TEMPLATE_FLAG_RELAXED_MATCH) { 1550 DR_LOG(ERR, "Unsupported match template flag provided"); 1551 rte_errno = EINVAL; 1552 return NULL; 1553 } 1554 1555 mt = simple_calloc(1, sizeof(*mt)); 1556 if (!mt) { 1557 DR_LOG(ERR, "Failed to allocate match template"); 1558 rte_errno = ENOMEM; 1559 return NULL; 1560 } 1561 1562 mt->flags = flags; 1563 1564 /* Duplicate the user given items */ 1565 ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, NULL, 0, items, &error); 1566 if (ret <= 0) { 1567 DR_LOG(ERR, "Unable to process items (%s): %s", 1568 error.message ? error.message : "unspecified", 1569 strerror(rte_errno)); 1570 goto free_template; 1571 } 1572 1573 len = RTE_ALIGN(ret, 16); 1574 mt->items = simple_calloc(1, len); 1575 if (!mt->items) { 1576 DR_LOG(ERR, "Failed to allocate item copy"); 1577 rte_errno = ENOMEM; 1578 goto free_template; 1579 } 1580 1581 ret = rte_flow_conv(RTE_FLOW_CONV_OP_PATTERN, mt->items, ret, items, &error); 1582 if (ret <= 0) 1583 goto free_dst; 1584 1585 return mt; 1586 1587 free_dst: 1588 simple_free(mt->items); 1589 free_template: 1590 simple_free(mt); 1591 return NULL; 1592 } 1593 1594 int mlx5dr_match_template_destroy(struct mlx5dr_match_template *mt) 1595 { 1596 simple_free(mt->items); 1597 simple_free(mt); 1598 return 0; 1599 } 1600 1601 bool mlx5dr_matcher_is_updatable(struct mlx5dr_matcher *matcher) 1602 { 1603 if (mlx5dr_table_is_root(matcher->tbl) || 1604 mlx5dr_matcher_req_fw_wqe(matcher) || 1605 mlx5dr_matcher_is_resizable(matcher) || 1606 (!matcher->attr.optimize_using_rule_idx && 1607 !mlx5dr_matcher_is_insert_by_idx(matcher))) 1608 return false; 1609 1610 return true; 1611 } 1612 1613 bool mlx5dr_matcher_is_dependent(struct mlx5dr_matcher *matcher) 1614 { 1615 int i; 1616 1617 if (matcher->action_ste.max_stes || mlx5dr_matcher_req_fw_wqe(matcher)) 1618 return true; 1619 1620 for (i = 0; i < matcher->num_of_at; i++) { 1621 struct mlx5dr_action_template *at = &matcher->at[i]; 1622 1623 if (at->need_dep_write) 1624 return true; 1625 } 1626 1627 return false; 1628 } 1629 1630 static int mlx5dr_matcher_resize_precheck(struct mlx5dr_matcher *src_matcher, 1631 struct mlx5dr_matcher *dst_matcher) 1632 { 1633 int i; 1634 1635 if (mlx5dr_table_is_root(src_matcher->tbl) || 1636 mlx5dr_table_is_root(dst_matcher->tbl)) { 1637 DR_LOG(ERR, "Src/dst matcher belongs to root table - resize unsupported"); 1638 goto out_einval; 1639 } 1640 1641 if (src_matcher->tbl->type != dst_matcher->tbl->type) { 1642 DR_LOG(ERR, "Table type mismatch for src/dst matchers"); 1643 goto out_einval; 1644 } 1645 1646 if (mlx5dr_matcher_req_fw_wqe(src_matcher) || 1647 mlx5dr_matcher_req_fw_wqe(dst_matcher)) { 1648 DR_LOG(ERR, "Matchers require FW WQE - resize unsupported"); 1649 goto out_einval; 1650 } 1651 1652 if (!mlx5dr_matcher_is_resizable(src_matcher) || 1653 !mlx5dr_matcher_is_resizable(dst_matcher)) { 1654 DR_LOG(ERR, "Src/dst matcher is not resizable"); 1655 goto out_einval; 1656 } 1657 1658 if (mlx5dr_matcher_is_insert_by_idx(src_matcher) != 1659 mlx5dr_matcher_is_insert_by_idx(dst_matcher)) { 1660 DR_LOG(ERR, "Src/dst matchers insert mode mismatch"); 1661 goto out_einval; 1662 } 1663 1664 if (mlx5dr_matcher_is_in_resize(src_matcher) || 1665 mlx5dr_matcher_is_in_resize(dst_matcher)) { 1666 DR_LOG(ERR, "Src/dst matcher is already in resize"); 1667 goto out_einval; 1668 } 1669 1670 /* Compare match templates - make sure the definers are equivalent */ 1671 if (src_matcher->num_of_mt != dst_matcher->num_of_mt) { 1672 DR_LOG(ERR, "Src/dst matcher match templates mismatch"); 1673 goto out_einval; 1674 } 1675 1676 if (src_matcher->action_ste.max_stes > dst_matcher->action_ste.max_stes) { 1677 DR_LOG(ERR, "Src/dst matcher max STEs mismatch"); 1678 goto out_einval; 1679 } 1680 1681 for (i = 0; i < src_matcher->num_of_mt; i++) { 1682 if (mlx5dr_definer_compare(src_matcher->mt[i].definer, 1683 dst_matcher->mt[i].definer)) { 1684 DR_LOG(ERR, "Src/dst matcher definers mismatch"); 1685 goto out_einval; 1686 } 1687 } 1688 1689 return 0; 1690 1691 out_einval: 1692 rte_errno = EINVAL; 1693 return rte_errno; 1694 } 1695 1696 int mlx5dr_matcher_resize_set_target(struct mlx5dr_matcher *src_matcher, 1697 struct mlx5dr_matcher *dst_matcher) 1698 { 1699 int ret = 0; 1700 1701 pthread_spin_lock(&src_matcher->tbl->ctx->ctrl_lock); 1702 1703 if (mlx5dr_matcher_resize_precheck(src_matcher, dst_matcher)) { 1704 ret = -rte_errno; 1705 goto out; 1706 } 1707 1708 src_matcher->resize_dst = dst_matcher; 1709 1710 if (mlx5dr_matcher_resize_init(src_matcher)) { 1711 src_matcher->resize_dst = NULL; 1712 ret = -rte_errno; 1713 } 1714 1715 out: 1716 pthread_spin_unlock(&src_matcher->tbl->ctx->ctrl_lock); 1717 return ret; 1718 } 1719 1720 int mlx5dr_matcher_resize_rule_move(struct mlx5dr_matcher *src_matcher, 1721 struct mlx5dr_rule *rule, 1722 struct mlx5dr_rule_attr *attr) 1723 { 1724 if (unlikely(!mlx5dr_matcher_is_in_resize(src_matcher))) { 1725 DR_LOG(ERR, "Matcher is not resizable or not in resize"); 1726 goto out_einval; 1727 } 1728 1729 if (unlikely(src_matcher != rule->matcher)) { 1730 DR_LOG(ERR, "Rule doesn't belong to src matcher"); 1731 goto out_einval; 1732 } 1733 1734 return mlx5dr_rule_move_hws_add(rule, attr); 1735 1736 out_einval: 1737 rte_errno = EINVAL; 1738 return -rte_errno; 1739 } 1740 1741 int mlx5dr_matcher_validate_compare_attr(struct mlx5dr_matcher *matcher) 1742 { 1743 struct mlx5dr_cmd_query_caps *caps = matcher->tbl->ctx->caps; 1744 struct mlx5dr_matcher_attr *attr = &matcher->attr; 1745 1746 if (mlx5dr_table_is_root(matcher->tbl)) { 1747 DR_LOG(ERR, "Compare matcher is not supported for root tables"); 1748 goto err; 1749 } 1750 1751 if (attr->mode != MLX5DR_MATCHER_RESOURCE_MODE_HTABLE) { 1752 DR_LOG(ERR, "Compare matcher is only supported with pre-defined table size"); 1753 goto err; 1754 } 1755 1756 if (attr->insert_mode != MLX5DR_MATCHER_INSERT_BY_HASH || 1757 attr->distribute_mode != MLX5DR_MATCHER_DISTRIBUTE_BY_HASH) { 1758 DR_LOG(ERR, "Gen WQE for compare matcher must be inserted and distribute by hash"); 1759 goto err; 1760 } 1761 1762 if (matcher->num_of_mt != 1 || matcher->num_of_at != 1) { 1763 DR_LOG(ERR, "Compare matcher match templates and action templates must be 1 for each"); 1764 goto err; 1765 } 1766 1767 if (attr->table.sz_col_log || attr->table.sz_row_log) { 1768 DR_LOG(ERR, "Compare matcher supports only 1x1 table size"); 1769 goto err; 1770 } 1771 1772 if (attr->resizable) { 1773 DR_LOG(ERR, "Compare matcher does not support resizeing"); 1774 goto err; 1775 } 1776 1777 if (!IS_BIT_SET(caps->supp_ste_format_gen_wqe, MLX5_IFC_RTC_STE_FORMAT_4DW_RANGE)) { 1778 DR_LOG(ERR, "Gen WQE Compare match format not supported"); 1779 goto err; 1780 } 1781 1782 return 0; 1783 1784 err: 1785 rte_errno = ENOTSUP; 1786 return rte_errno; 1787 } 1788