1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022 NVIDIA Corporation & Affiliates 3 */ 4 5 #include "mlx5dr_internal.h" 6 7 const char *mlx5dr_debug_action_type_str[] = { 8 [MLX5DR_ACTION_TYP_LAST] = "LAST", 9 [MLX5DR_ACTION_TYP_REFORMAT_TNL_L2_TO_L2] = "TNL_L2_TO_L2", 10 [MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L2] = "L2_TO_TNL_L2", 11 [MLX5DR_ACTION_TYP_REFORMAT_TNL_L3_TO_L2] = "TNL_L3_TO_L2", 12 [MLX5DR_ACTION_TYP_REFORMAT_L2_TO_TNL_L3] = "L2_TO_TNL_L3", 13 [MLX5DR_ACTION_TYP_DROP] = "DROP", 14 [MLX5DR_ACTION_TYP_TIR] = "TIR", 15 [MLX5DR_ACTION_TYP_TBL] = "TBL", 16 [MLX5DR_ACTION_TYP_CTR] = "CTR", 17 [MLX5DR_ACTION_TYP_TAG] = "TAG", 18 [MLX5DR_ACTION_TYP_MODIFY_HDR] = "MODIFY_HDR", 19 [MLX5DR_ACTION_TYP_VPORT] = "VPORT", 20 [MLX5DR_ACTION_TYP_MISS] = "DEFAULT_MISS", 21 [MLX5DR_ACTION_TYP_POP_VLAN] = "POP_VLAN", 22 [MLX5DR_ACTION_TYP_PUSH_VLAN] = "PUSH_VLAN", 23 [MLX5DR_ACTION_TYP_ASO_METER] = "ASO_METER", 24 [MLX5DR_ACTION_TYP_ASO_CT] = "ASO_CT", 25 [MLX5DR_ACTION_TYP_DEST_ROOT] = "DEST_ROOT", 26 }; 27 28 static_assert(ARRAY_SIZE(mlx5dr_debug_action_type_str) == MLX5DR_ACTION_TYP_MAX, 29 "Missing mlx5dr_debug_action_type_str"); 30 31 const char *mlx5dr_debug_action_type_to_str(enum mlx5dr_action_type action_type) 32 { 33 return mlx5dr_debug_action_type_str[action_type]; 34 } 35 36 static int 37 mlx5dr_debug_dump_matcher_template_definer(FILE *f, 38 void *parent_obj, 39 struct mlx5dr_definer *definer, 40 enum mlx5dr_debug_res_type type) 41 { 42 int i, ret; 43 44 if (!definer) 45 return 0; 46 47 ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,", 48 type, 49 (uint64_t)(uintptr_t)definer, 50 (uint64_t)(uintptr_t)parent_obj, 51 definer->obj->id, 52 definer->type); 53 if (ret < 0) { 54 rte_errno = EINVAL; 55 return rte_errno; 56 } 57 58 for (i = 0; i < DW_SELECTORS; i++) { 59 ret = fprintf(f, "0x%x%s", definer->dw_selector[i], 60 (i == DW_SELECTORS - 1) ? "," : "-"); 61 if (ret < 0) { 62 rte_errno = EINVAL; 63 return rte_errno; 64 } 65 } 66 67 for (i = 0; i < BYTE_SELECTORS; i++) { 68 ret = fprintf(f, "0x%x%s", definer->byte_selector[i], 69 (i == BYTE_SELECTORS - 1) ? "," : "-"); 70 if (ret < 0) { 71 rte_errno = EINVAL; 72 return rte_errno; 73 } 74 } 75 76 for (i = 0; i < MLX5DR_JUMBO_TAG_SZ; i++) { 77 ret = fprintf(f, "%02x", definer->mask.jumbo[i]); 78 if (ret < 0) { 79 rte_errno = EINVAL; 80 return rte_errno; 81 } 82 } 83 84 ret = fprintf(f, "\n"); 85 if (ret < 0) { 86 rte_errno = EINVAL; 87 return rte_errno; 88 } 89 90 return 0; 91 } 92 93 static int 94 mlx5dr_debug_dump_matcher_match_template(FILE *f, struct mlx5dr_matcher *matcher) 95 { 96 bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL; 97 enum mlx5dr_debug_res_type type; 98 int i, ret; 99 100 for (i = 0; i < matcher->num_of_mt; i++) { 101 struct mlx5dr_match_template *mt = &matcher->mt[i]; 102 103 ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,%d\n", 104 MLX5DR_DEBUG_RES_TYPE_MATCHER_MATCH_TEMPLATE, 105 (uint64_t)(uintptr_t)mt, 106 (uint64_t)(uintptr_t)matcher, 107 is_root ? 0 : mt->fc_sz, 108 mt->flags, 109 is_root ? 0 : mt->fcr_sz); 110 if (ret < 0) { 111 rte_errno = EINVAL; 112 return rte_errno; 113 } 114 115 type = MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_MATCH_DEFINER; 116 ret = mlx5dr_debug_dump_matcher_template_definer(f, mt, mt->definer, type); 117 if (ret) 118 return ret; 119 120 type = MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_RANGE_DEFINER; 121 ret = mlx5dr_debug_dump_matcher_template_definer(f, mt, mt->range_definer, type); 122 if (ret) 123 return ret; 124 } 125 126 type = MLX5DR_DEBUG_RES_TYPE_MATCHER_TEMPLATE_HASH_DEFINER; 127 ret = mlx5dr_debug_dump_matcher_template_definer(f, matcher, matcher->hash_definer, type); 128 if (ret) 129 return ret; 130 131 return 0; 132 } 133 134 static int 135 mlx5dr_debug_dump_matcher_action_template(FILE *f, struct mlx5dr_matcher *matcher) 136 { 137 bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL; 138 enum mlx5dr_action_type action_type; 139 int i, j, ret; 140 141 for (i = 0; i < matcher->num_of_at; i++) { 142 struct mlx5dr_action_template *at = &matcher->at[i]; 143 144 ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,%d", 145 MLX5DR_DEBUG_RES_TYPE_MATCHER_ACTION_TEMPLATE, 146 (uint64_t)(uintptr_t)at, 147 (uint64_t)(uintptr_t)matcher, 148 at->only_term ? 0 : 1, 149 is_root ? 0 : at->num_of_action_stes, 150 at->num_actions); 151 if (ret < 0) { 152 rte_errno = EINVAL; 153 return rte_errno; 154 } 155 156 for (j = 0; j < at->num_actions; j++) { 157 action_type = at->action_type_arr[j]; 158 ret = fprintf(f, ",%s", mlx5dr_debug_action_type_to_str(action_type)); 159 if (ret < 0) { 160 rte_errno = EINVAL; 161 return rte_errno; 162 } 163 } 164 165 fprintf(f, "\n"); 166 } 167 168 return 0; 169 } 170 171 static int 172 mlx5dr_debug_dump_matcher_attr(FILE *f, struct mlx5dr_matcher *matcher) 173 { 174 struct mlx5dr_matcher_attr *attr = &matcher->attr; 175 int ret; 176 177 ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d\n", 178 MLX5DR_DEBUG_RES_TYPE_MATCHER_ATTR, 179 (uint64_t)(uintptr_t)matcher, 180 attr->priority, 181 attr->mode, 182 attr->table.sz_row_log, 183 attr->table.sz_col_log, 184 attr->optimize_using_rule_idx, 185 attr->optimize_flow_src, 186 attr->insert_mode, 187 attr->distribute_mode); 188 if (ret < 0) { 189 rte_errno = EINVAL; 190 return rte_errno; 191 } 192 193 return 0; 194 } 195 196 static int mlx5dr_debug_dump_matcher(FILE *f, struct mlx5dr_matcher *matcher) 197 { 198 bool is_shared = mlx5dr_context_shared_gvmi_used(matcher->tbl->ctx); 199 bool is_root = matcher->tbl->level == MLX5DR_ROOT_LEVEL; 200 enum mlx5dr_table_type tbl_type = matcher->tbl->type; 201 struct mlx5dr_cmd_ft_query_attr ft_attr = {0}; 202 struct mlx5dr_devx_obj *ste_0, *ste_1 = NULL; 203 struct mlx5dr_pool_chunk *ste; 204 struct mlx5dr_pool *ste_pool; 205 uint64_t icm_addr_0 = 0; 206 uint64_t icm_addr_1 = 0; 207 int ret; 208 209 ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,0x%" PRIx64, 210 MLX5DR_DEBUG_RES_TYPE_MATCHER, 211 (uint64_t)(uintptr_t)matcher, 212 (uint64_t)(uintptr_t)matcher->tbl, 213 matcher->num_of_mt, 214 is_root ? 0 : matcher->end_ft->id, 215 matcher->col_matcher ? (uint64_t)(uintptr_t)matcher->col_matcher : 0); 216 if (ret < 0) 217 goto out_err; 218 219 ste = &matcher->match_ste.ste; 220 ste_pool = matcher->match_ste.pool; 221 if (ste_pool) { 222 ste_0 = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste); 223 if (tbl_type == MLX5DR_TABLE_TYPE_FDB) 224 ste_1 = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste); 225 } else { 226 ste_0 = NULL; 227 ste_1 = NULL; 228 } 229 230 ret = fprintf(f, ",%d,%d,%d,%d", 231 matcher->match_ste.rtc_0 ? matcher->match_ste.rtc_0->id : 0, 232 ste_0 ? (int)ste_0->id : -1, 233 matcher->match_ste.rtc_1 ? matcher->match_ste.rtc_1->id : 0, 234 ste_1 ? (int)ste_1->id : -1); 235 if (ret < 0) 236 goto out_err; 237 238 ste = &matcher->action_ste.ste; 239 ste_pool = matcher->action_ste.pool; 240 if (ste_pool) { 241 ste_0 = mlx5dr_pool_chunk_get_base_devx_obj(ste_pool, ste); 242 if (tbl_type == MLX5DR_TABLE_TYPE_FDB) 243 ste_1 = mlx5dr_pool_chunk_get_base_devx_obj_mirror(ste_pool, ste); 244 } else { 245 ste_0 = NULL; 246 ste_1 = NULL; 247 } 248 249 if (!is_root) { 250 ft_attr.type = matcher->tbl->fw_ft_type; 251 ret = mlx5dr_cmd_flow_table_query(matcher->end_ft, 252 &ft_attr, 253 &icm_addr_0, 254 &icm_addr_1); 255 if (ret) 256 return ret; 257 } 258 259 ret = fprintf(f, ",%d,%d,%d,%d,%d,0x%" PRIx64 ",0x%" PRIx64 "\n", 260 matcher->action_ste.rtc_0 ? matcher->action_ste.rtc_0->id : 0, 261 ste_0 ? (int)ste_0->id : -1, 262 matcher->action_ste.rtc_1 ? matcher->action_ste.rtc_1->id : 0, 263 ste_1 ? (int)ste_1->id : -1, 264 is_shared && !is_root ? 265 matcher->match_ste.aliased_rtc_0->id : 0, 266 mlx5dr_debug_icm_to_idx(icm_addr_0), 267 mlx5dr_debug_icm_to_idx(icm_addr_1)); 268 if (ret < 0) 269 goto out_err; 270 271 ret = mlx5dr_debug_dump_matcher_attr(f, matcher); 272 if (ret) 273 return ret; 274 275 ret = mlx5dr_debug_dump_matcher_match_template(f, matcher); 276 if (ret) 277 return ret; 278 279 ret = mlx5dr_debug_dump_matcher_action_template(f, matcher); 280 if (ret) 281 return ret; 282 283 return 0; 284 285 out_err: 286 rte_errno = EINVAL; 287 return rte_errno; 288 } 289 290 static int mlx5dr_debug_dump_table(FILE *f, struct mlx5dr_table *tbl) 291 { 292 bool is_shared = mlx5dr_context_shared_gvmi_used(tbl->ctx); 293 bool is_root = tbl->level == MLX5DR_ROOT_LEVEL; 294 struct mlx5dr_cmd_ft_query_attr ft_attr = {0}; 295 struct mlx5dr_matcher *matcher; 296 uint64_t local_icm_addr_0 = 0; 297 uint64_t local_icm_addr_1 = 0; 298 uint64_t icm_addr_0 = 0; 299 uint64_t icm_addr_1 = 0; 300 int ret; 301 302 ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d,%d,%d,%d", 303 MLX5DR_DEBUG_RES_TYPE_TABLE, 304 (uint64_t)(uintptr_t)tbl, 305 (uint64_t)(uintptr_t)tbl->ctx, 306 is_root ? 0 : tbl->ft->id, 307 tbl->type, 308 is_root ? 0 : tbl->fw_ft_type, 309 tbl->level, 310 is_shared && !is_root ? tbl->local_ft->id : 0); 311 if (ret < 0) 312 goto out_err; 313 314 if (!is_root) { 315 ft_attr.type = tbl->fw_ft_type; 316 ret = mlx5dr_cmd_flow_table_query(tbl->ft, 317 &ft_attr, 318 &icm_addr_0, 319 &icm_addr_1); 320 if (ret) 321 return ret; 322 323 if (is_shared) { 324 ft_attr.type = tbl->fw_ft_type; 325 ret = mlx5dr_cmd_flow_table_query(tbl->local_ft, 326 &ft_attr, 327 &local_icm_addr_0, 328 &local_icm_addr_1); 329 if (ret) 330 return ret; 331 } 332 } 333 334 ret = fprintf(f, ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 "\n", 335 mlx5dr_debug_icm_to_idx(icm_addr_0), 336 mlx5dr_debug_icm_to_idx(icm_addr_1), 337 mlx5dr_debug_icm_to_idx(local_icm_addr_0), 338 mlx5dr_debug_icm_to_idx(local_icm_addr_1), 339 (uint64_t)(uintptr_t)tbl->default_miss.miss_tbl); 340 if (ret < 0) 341 goto out_err; 342 343 LIST_FOREACH(matcher, &tbl->head, next) { 344 ret = mlx5dr_debug_dump_matcher(f, matcher); 345 if (ret) 346 return ret; 347 } 348 349 return 0; 350 351 out_err: 352 rte_errno = EINVAL; 353 return rte_errno; 354 } 355 356 static int 357 mlx5dr_debug_dump_context_send_engine(FILE *f, struct mlx5dr_context *ctx) 358 { 359 struct mlx5dr_send_engine *send_queue; 360 int ret, i, j; 361 362 for (i = 0; i < (int)ctx->queues; i++) { 363 send_queue = &ctx->send_queue[i]; 364 ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d\n", 365 MLX5DR_DEBUG_RES_TYPE_CONTEXT_SEND_ENGINE, 366 (uint64_t)(uintptr_t)ctx, 367 i, 368 send_queue->used_entries, 369 send_queue->th_entries, 370 send_queue->rings, 371 send_queue->num_entries, 372 send_queue->err, 373 send_queue->completed.ci, 374 send_queue->completed.pi, 375 send_queue->completed.mask); 376 if (ret < 0) { 377 rte_errno = EINVAL; 378 return rte_errno; 379 } 380 381 for (j = 0; j < MLX5DR_NUM_SEND_RINGS; j++) { 382 struct mlx5dr_send_ring *send_ring = &send_queue->send_ring[j]; 383 struct mlx5dr_send_ring_cq *cq = &send_ring->send_cq; 384 struct mlx5dr_send_ring_sq *sq = &send_ring->send_sq; 385 386 ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", 387 MLX5DR_DEBUG_RES_TYPE_CONTEXT_SEND_RING, 388 (uint64_t)(uintptr_t)ctx, 389 j, 390 i, 391 cq->cqn, 392 cq->cons_index, 393 cq->ncqe_mask, 394 cq->buf_sz, 395 cq->ncqe, 396 cq->cqe_log_sz, 397 cq->poll_wqe, 398 cq->cqe_sz, 399 sq->sqn, 400 sq->obj->id, 401 sq->cur_post, 402 sq->buf_mask); 403 if (ret < 0) { 404 rte_errno = EINVAL; 405 return rte_errno; 406 } 407 } 408 } 409 410 return 0; 411 } 412 413 static int mlx5dr_debug_dump_context_caps(FILE *f, struct mlx5dr_context *ctx) 414 { 415 struct mlx5dr_cmd_query_caps *caps = ctx->caps; 416 int ret; 417 418 ret = fprintf(f, "%d,0x%" PRIx64 ",%s,%d,%d,%d,%d,", 419 MLX5DR_DEBUG_RES_TYPE_CONTEXT_CAPS, 420 (uint64_t)(uintptr_t)ctx, 421 caps->fw_ver, 422 caps->wqe_based_update, 423 caps->ste_format, 424 caps->ste_alloc_log_max, 425 caps->log_header_modify_argument_max_alloc); 426 if (ret < 0) { 427 rte_errno = EINVAL; 428 return rte_errno; 429 } 430 431 ret = fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", 432 caps->flex_protocols, 433 caps->rtc_reparse_mode, 434 caps->rtc_index_mode, 435 caps->ste_alloc_log_gran, 436 caps->stc_alloc_log_max, 437 caps->stc_alloc_log_gran, 438 caps->rtc_log_depth_max, 439 caps->format_select_gtpu_dw_0, 440 caps->format_select_gtpu_dw_1, 441 caps->format_select_gtpu_dw_2, 442 caps->format_select_gtpu_ext_dw_0, 443 caps->nic_ft.max_level, 444 caps->nic_ft.reparse, 445 caps->fdb_ft.max_level, 446 caps->fdb_ft.reparse, 447 caps->log_header_modify_argument_granularity); 448 if (ret < 0) { 449 rte_errno = EINVAL; 450 return rte_errno; 451 } 452 453 return 0; 454 } 455 456 static int mlx5dr_debug_dump_context_attr(FILE *f, struct mlx5dr_context *ctx) 457 { 458 int ret; 459 460 ret = fprintf(f, "%u,0x%" PRIx64 ",%d,%zu,%d,%s,%d,%d\n", 461 MLX5DR_DEBUG_RES_TYPE_CONTEXT_ATTR, 462 (uint64_t)(uintptr_t)ctx, 463 ctx->pd_num, 464 ctx->queues, 465 ctx->send_queue->num_entries, 466 mlx5dr_context_shared_gvmi_used(ctx) ? 467 mlx5_glue->get_device_name(ctx->ibv_ctx->device) : "None", 468 ctx->caps->vhca_id, 469 mlx5dr_context_shared_gvmi_used(ctx) ? 470 ctx->caps->shared_vhca_id : 0xffff); 471 if (ret < 0) { 472 rte_errno = EINVAL; 473 return rte_errno; 474 } 475 476 return 0; 477 } 478 479 static int mlx5dr_debug_dump_context_info(FILE *f, struct mlx5dr_context *ctx) 480 { 481 int ret; 482 483 ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%s,%s\n", 484 MLX5DR_DEBUG_RES_TYPE_CONTEXT, 485 (uint64_t)(uintptr_t)ctx, 486 ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT, 487 mlx5_glue->get_device_name(mlx5dr_context_get_local_ibv(ctx)->device), 488 DEBUG_VERSION); 489 if (ret < 0) { 490 rte_errno = EINVAL; 491 return rte_errno; 492 } 493 494 ret = mlx5dr_debug_dump_context_attr(f, ctx); 495 if (ret) 496 return ret; 497 498 ret = mlx5dr_debug_dump_context_caps(f, ctx); 499 if (ret) 500 return ret; 501 502 return 0; 503 } 504 505 static int 506 mlx5dr_debug_dump_context_stc_resource(FILE *f, 507 struct mlx5dr_context *ctx, 508 uint32_t tbl_type, 509 struct mlx5dr_pool_resource *resource) 510 { 511 int ret; 512 513 ret = fprintf(f, "%d,0x%" PRIx64 ",%u,%u\n", 514 MLX5DR_DEBUG_RES_TYPE_CONTEXT_STC, 515 (uint64_t)(uintptr_t)ctx, 516 tbl_type, 517 resource->base_id); 518 if (ret < 0) { 519 rte_errno = EINVAL; 520 return rte_errno; 521 } 522 523 return 0; 524 } 525 526 static int mlx5dr_debug_dump_context_stc(FILE *f, struct mlx5dr_context *ctx) 527 { 528 struct mlx5dr_pool *stc_pool; 529 int ret; 530 int i; 531 532 for (i = 0; i < MLX5DR_TABLE_TYPE_MAX; i++) { 533 stc_pool = ctx->stc_pool[i]; 534 535 if (!stc_pool) 536 continue; 537 538 if (stc_pool->resource[0] != NULL) { 539 ret = mlx5dr_debug_dump_context_stc_resource(f, ctx, i, 540 stc_pool->resource[0]); 541 if (ret) 542 return ret; 543 } 544 545 if (i == MLX5DR_TABLE_TYPE_FDB && stc_pool->mirror_resource[0] != NULL) { 546 ret = mlx5dr_debug_dump_context_stc_resource(f, ctx, i, 547 stc_pool->mirror_resource[0]); 548 if (ret) 549 return ret; 550 } 551 } 552 553 return 0; 554 } 555 556 static int mlx5dr_debug_dump_context(FILE *f, struct mlx5dr_context *ctx) 557 { 558 struct mlx5dr_table *tbl; 559 int ret; 560 561 ret = mlx5dr_debug_dump_context_info(f, ctx); 562 if (ret) 563 return ret; 564 565 ret = mlx5dr_debug_dump_context_send_engine(f, ctx); 566 if (ret) 567 return ret; 568 569 ret = mlx5dr_debug_dump_context_stc(f, ctx); 570 if (ret) 571 return ret; 572 573 LIST_FOREACH(tbl, &ctx->head, next) { 574 ret = mlx5dr_debug_dump_table(f, tbl); 575 if (ret) 576 return ret; 577 } 578 579 return 0; 580 } 581 582 int mlx5dr_debug_dump(struct mlx5dr_context *ctx, FILE *f) 583 { 584 int ret; 585 586 if (!f || !ctx) { 587 rte_errno = EINVAL; 588 return -rte_errno; 589 } 590 591 pthread_spin_lock(&ctx->ctrl_lock); 592 ret = mlx5dr_debug_dump_context(f, ctx); 593 pthread_spin_unlock(&ctx->ctrl_lock); 594 595 return -ret; 596 } 597