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