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