1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022 NVIDIA Corporation & Affiliates 3 */ 4 5 #include "mlx5dr_internal.h" 6 7 #define WIRE_PORT 0xFFFF 8 9 #define MLX5DR_ACTION_METER_INIT_COLOR_OFFSET 1 10 11 /* This is the maximum allowed action order for each table type: 12 * TX: POP_VLAN, CTR, ASO_METER, AS_CT, PUSH_VLAN, MODIFY, ENCAP, Term 13 * RX: TAG, DECAP, POP_VLAN, CTR, ASO_METER, ASO_CT, PUSH_VLAN, MODIFY, 14 * ENCAP, Term 15 * FDB: DECAP, POP_VLAN, CTR, ASO_METER, ASO_CT, PUSH_VLAN, MODIFY, 16 * ENCAP, Term 17 */ 18 static const uint32_t action_order_arr[MLX5DR_TABLE_TYPE_MAX][MLX5DR_ACTION_TYP_MAX] = { 19 [MLX5DR_TABLE_TYPE_NIC_RX] = { 20 BIT(MLX5DR_ACTION_TYP_TAG), 21 BIT(MLX5DR_ACTION_TYP_TNL_L2_TO_L2) | 22 BIT(MLX5DR_ACTION_TYP_TNL_L3_TO_L2), 23 BIT(MLX5DR_ACTION_TYP_POP_VLAN), 24 BIT(MLX5DR_ACTION_TYP_POP_VLAN), 25 BIT(MLX5DR_ACTION_TYP_CTR), 26 BIT(MLX5DR_ACTION_TYP_ASO_METER), 27 BIT(MLX5DR_ACTION_TYP_ASO_CT), 28 BIT(MLX5DR_ACTION_TYP_PUSH_VLAN), 29 BIT(MLX5DR_ACTION_TYP_PUSH_VLAN), 30 BIT(MLX5DR_ACTION_TYP_MODIFY_HDR), 31 BIT(MLX5DR_ACTION_TYP_L2_TO_TNL_L2) | 32 BIT(MLX5DR_ACTION_TYP_L2_TO_TNL_L3), 33 BIT(MLX5DR_ACTION_TYP_FT) | 34 BIT(MLX5DR_ACTION_TYP_MISS) | 35 BIT(MLX5DR_ACTION_TYP_TIR) | 36 BIT(MLX5DR_ACTION_TYP_DROP), 37 BIT(MLX5DR_ACTION_TYP_LAST), 38 }, 39 [MLX5DR_TABLE_TYPE_NIC_TX] = { 40 BIT(MLX5DR_ACTION_TYP_POP_VLAN), 41 BIT(MLX5DR_ACTION_TYP_POP_VLAN), 42 BIT(MLX5DR_ACTION_TYP_CTR), 43 BIT(MLX5DR_ACTION_TYP_ASO_METER), 44 BIT(MLX5DR_ACTION_TYP_ASO_CT), 45 BIT(MLX5DR_ACTION_TYP_PUSH_VLAN), 46 BIT(MLX5DR_ACTION_TYP_PUSH_VLAN), 47 BIT(MLX5DR_ACTION_TYP_MODIFY_HDR), 48 BIT(MLX5DR_ACTION_TYP_L2_TO_TNL_L2) | 49 BIT(MLX5DR_ACTION_TYP_L2_TO_TNL_L3), 50 BIT(MLX5DR_ACTION_TYP_FT) | 51 BIT(MLX5DR_ACTION_TYP_MISS) | 52 BIT(MLX5DR_ACTION_TYP_DROP), 53 BIT(MLX5DR_ACTION_TYP_LAST), 54 }, 55 [MLX5DR_TABLE_TYPE_FDB] = { 56 BIT(MLX5DR_ACTION_TYP_TNL_L2_TO_L2) | 57 BIT(MLX5DR_ACTION_TYP_TNL_L3_TO_L2), 58 BIT(MLX5DR_ACTION_TYP_POP_VLAN), 59 BIT(MLX5DR_ACTION_TYP_POP_VLAN), 60 BIT(MLX5DR_ACTION_TYP_CTR), 61 BIT(MLX5DR_ACTION_TYP_ASO_METER), 62 BIT(MLX5DR_ACTION_TYP_ASO_CT), 63 BIT(MLX5DR_ACTION_TYP_PUSH_VLAN), 64 BIT(MLX5DR_ACTION_TYP_PUSH_VLAN), 65 BIT(MLX5DR_ACTION_TYP_MODIFY_HDR), 66 BIT(MLX5DR_ACTION_TYP_L2_TO_TNL_L2) | 67 BIT(MLX5DR_ACTION_TYP_L2_TO_TNL_L3), 68 BIT(MLX5DR_ACTION_TYP_FT) | 69 BIT(MLX5DR_ACTION_TYP_MISS) | 70 BIT(MLX5DR_ACTION_TYP_VPORT) | 71 BIT(MLX5DR_ACTION_TYP_DROP), 72 BIT(MLX5DR_ACTION_TYP_LAST), 73 }, 74 }; 75 76 static int mlx5dr_action_get_shared_stc_nic(struct mlx5dr_context *ctx, 77 enum mlx5dr_context_shared_stc_type stc_type, 78 uint8_t tbl_type) 79 { 80 struct mlx5dr_cmd_stc_modify_attr stc_attr = {0}; 81 struct mlx5dr_action_shared_stc *shared_stc; 82 int ret; 83 84 pthread_spin_lock(&ctx->ctrl_lock); 85 if (ctx->common_res[tbl_type].shared_stc[stc_type]) { 86 ctx->common_res[tbl_type].shared_stc[stc_type]->refcount++; 87 pthread_spin_unlock(&ctx->ctrl_lock); 88 return 0; 89 } 90 91 shared_stc = simple_calloc(1, sizeof(*shared_stc)); 92 if (!shared_stc) { 93 DR_LOG(ERR, "Failed to allocate memory for shared STCs"); 94 rte_errno = ENOMEM; 95 goto unlock_and_out; 96 } 97 switch (stc_type) { 98 case MLX5DR_CONTEXT_SHARED_STC_DECAP: 99 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE; 100 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW5; 101 stc_attr.remove_header.decap = 0; 102 stc_attr.remove_header.start_anchor = MLX5_HEADER_ANCHOR_PACKET_START; 103 stc_attr.remove_header.end_anchor = MLX5_HEADER_ANCHOR_IPV6_IPV4; 104 break; 105 case MLX5DR_CONTEXT_SHARED_STC_POP: 106 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS; 107 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW5; 108 stc_attr.remove_words.start_anchor = MLX5_HEADER_ANCHOR_FIRST_VLAN_START; 109 stc_attr.remove_words.num_of_words = MLX5DR_ACTION_HDR_LEN_L2_VLAN; 110 break; 111 default: 112 DR_LOG(ERR, "No such type : stc_type\n"); 113 assert(false); 114 rte_errno = EINVAL; 115 goto unlock_and_out; 116 } 117 118 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 119 &shared_stc->remove_header); 120 if (ret) { 121 DR_LOG(ERR, "Failed to allocate shared decap l2 STC"); 122 goto free_shared_stc; 123 } 124 125 ctx->common_res[tbl_type].shared_stc[stc_type] = shared_stc; 126 ctx->common_res[tbl_type].shared_stc[stc_type]->refcount = 1; 127 128 pthread_spin_unlock(&ctx->ctrl_lock); 129 130 return 0; 131 132 free_shared_stc: 133 simple_free(shared_stc); 134 unlock_and_out: 135 pthread_spin_unlock(&ctx->ctrl_lock); 136 return rte_errno; 137 } 138 139 static void mlx5dr_action_put_shared_stc_nic(struct mlx5dr_context *ctx, 140 enum mlx5dr_context_shared_stc_type stc_type, 141 uint8_t tbl_type) 142 { 143 struct mlx5dr_action_shared_stc *shared_stc; 144 145 pthread_spin_lock(&ctx->ctrl_lock); 146 if (--ctx->common_res[tbl_type].shared_stc[stc_type]->refcount) { 147 pthread_spin_unlock(&ctx->ctrl_lock); 148 return; 149 } 150 151 shared_stc = ctx->common_res[tbl_type].shared_stc[stc_type]; 152 153 mlx5dr_action_free_single_stc(ctx, tbl_type, &shared_stc->remove_header); 154 simple_free(shared_stc); 155 ctx->common_res[tbl_type].shared_stc[stc_type] = NULL; 156 pthread_spin_unlock(&ctx->ctrl_lock); 157 } 158 159 static int mlx5dr_action_get_shared_stc(struct mlx5dr_action *action, 160 enum mlx5dr_context_shared_stc_type stc_type) 161 { 162 struct mlx5dr_context *ctx = action->ctx; 163 int ret; 164 165 if (stc_type >= MLX5DR_CONTEXT_SHARED_STC_MAX) { 166 assert(false); 167 rte_errno = EINVAL; 168 return rte_errno; 169 } 170 171 if (action->flags & MLX5DR_ACTION_FLAG_HWS_RX) { 172 ret = mlx5dr_action_get_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_NIC_RX); 173 if (ret) { 174 DR_LOG(ERR, "Failed to allocate memory for RX shared STCs (type: %d)", 175 stc_type); 176 return ret; 177 } 178 } 179 180 if (action->flags & MLX5DR_ACTION_FLAG_HWS_TX) { 181 ret = mlx5dr_action_get_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_NIC_TX); 182 if (ret) { 183 DR_LOG(ERR, "Failed to allocate memory for TX shared STCs(type: %d)", 184 stc_type); 185 goto clean_nic_rx_stc; 186 } 187 } 188 189 if (action->flags & MLX5DR_ACTION_FLAG_HWS_FDB) { 190 ret = mlx5dr_action_get_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_FDB); 191 if (ret) { 192 DR_LOG(ERR, "Failed to allocate memory for FDB shared STCs (type: %d)", 193 stc_type); 194 goto clean_nic_tx_stc; 195 } 196 } 197 198 return 0; 199 200 clean_nic_tx_stc: 201 if (action->flags & MLX5DR_ACTION_FLAG_HWS_TX) 202 mlx5dr_action_put_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_NIC_TX); 203 clean_nic_rx_stc: 204 if (action->flags & MLX5DR_ACTION_FLAG_HWS_RX) 205 mlx5dr_action_put_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_NIC_RX); 206 207 return ret; 208 } 209 210 static void mlx5dr_action_put_shared_stc(struct mlx5dr_action *action, 211 enum mlx5dr_context_shared_stc_type stc_type) 212 { 213 struct mlx5dr_context *ctx = action->ctx; 214 215 if (stc_type >= MLX5DR_CONTEXT_SHARED_STC_MAX) { 216 assert(false); 217 return; 218 } 219 220 if (action->flags & MLX5DR_ACTION_FLAG_HWS_RX) 221 mlx5dr_action_put_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_NIC_RX); 222 223 if (action->flags & MLX5DR_ACTION_FLAG_HWS_TX) 224 mlx5dr_action_put_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_NIC_TX); 225 226 if (action->flags & MLX5DR_ACTION_FLAG_HWS_FDB) 227 mlx5dr_action_put_shared_stc_nic(ctx, stc_type, MLX5DR_TABLE_TYPE_FDB); 228 } 229 230 static void mlx5dr_action_print_combo(enum mlx5dr_action_type *user_actions) 231 { 232 DR_LOG(ERR, "Invalid action_type sequence"); 233 while (*user_actions != MLX5DR_ACTION_TYP_LAST) { 234 DR_LOG(ERR, "%s", mlx5dr_debug_action_type_to_str(*user_actions)); 235 user_actions++; 236 } 237 } 238 239 bool mlx5dr_action_check_combo(enum mlx5dr_action_type *user_actions, 240 enum mlx5dr_table_type table_type) 241 { 242 const uint32_t *order_arr = action_order_arr[table_type]; 243 uint8_t order_idx = 0; 244 uint8_t user_idx = 0; 245 bool valid_combo; 246 247 while (order_arr[order_idx] != BIT(MLX5DR_ACTION_TYP_LAST)) { 248 /* User action order validated move to next user action */ 249 if (BIT(user_actions[user_idx]) & order_arr[order_idx]) 250 user_idx++; 251 252 /* Iterate to the next supported action in the order */ 253 order_idx++; 254 } 255 256 /* Combination is valid if all user action were processed */ 257 valid_combo = user_actions[user_idx] == MLX5DR_ACTION_TYP_LAST; 258 if (!valid_combo) 259 mlx5dr_action_print_combo(user_actions); 260 261 return valid_combo; 262 } 263 264 int mlx5dr_action_root_build_attr(struct mlx5dr_rule_action rule_actions[], 265 uint32_t num_actions, 266 struct mlx5dv_flow_action_attr *attr) 267 { 268 struct mlx5dr_action *action; 269 uint32_t i; 270 271 for (i = 0; i < num_actions; i++) { 272 action = rule_actions[i].action; 273 274 switch (action->type) { 275 case MLX5DR_ACTION_TYP_FT: 276 case MLX5DR_ACTION_TYP_TIR: 277 attr[i].type = MLX5DV_FLOW_ACTION_DEST_DEVX; 278 attr[i].obj = action->devx_obj; 279 break; 280 case MLX5DR_ACTION_TYP_TAG: 281 attr[i].type = MLX5DV_FLOW_ACTION_TAG; 282 attr[i].tag_value = rule_actions[i].tag.value; 283 break; 284 #ifdef HAVE_MLX5_DR_CREATE_ACTION_DEFAULT_MISS 285 case MLX5DR_ACTION_TYP_MISS: 286 attr[i].type = MLX5DV_FLOW_ACTION_DEFAULT_MISS; 287 break; 288 #endif 289 case MLX5DR_ACTION_TYP_DROP: 290 attr[i].type = MLX5DV_FLOW_ACTION_DROP; 291 break; 292 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 293 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 294 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 295 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 296 case MLX5DR_ACTION_TYP_MODIFY_HDR: 297 attr[i].type = MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION; 298 attr[i].action = action->flow_action; 299 break; 300 #ifdef HAVE_IBV_FLOW_DEVX_COUNTERS 301 case MLX5DR_ACTION_TYP_CTR: 302 attr[i].type = MLX5DV_FLOW_ACTION_COUNTERS_DEVX; 303 attr[i].obj = action->devx_obj; 304 305 if (rule_actions[i].counter.offset) { 306 DR_LOG(ERR, "Counter offset not supported over root"); 307 rte_errno = ENOTSUP; 308 return rte_errno; 309 } 310 break; 311 #endif 312 default: 313 DR_LOG(ERR, "Found unsupported action type: %d", action->type); 314 rte_errno = ENOTSUP; 315 return rte_errno; 316 } 317 } 318 319 return 0; 320 } 321 322 static bool mlx5dr_action_fixup_stc_attr(struct mlx5dr_cmd_stc_modify_attr *stc_attr, 323 struct mlx5dr_cmd_stc_modify_attr *fixup_stc_attr, 324 enum mlx5dr_table_type table_type, 325 bool is_mirror) 326 { 327 struct mlx5dr_devx_obj *devx_obj; 328 bool use_fixup = false; 329 uint32_t fw_tbl_type; 330 331 fw_tbl_type = mlx5dr_table_get_res_fw_ft_type(table_type, is_mirror); 332 333 switch (stc_attr->action_type) { 334 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_STE_TABLE: 335 if (!is_mirror) 336 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(stc_attr->ste_table.ste_pool, 337 &stc_attr->ste_table.ste); 338 else 339 devx_obj = 340 mlx5dr_pool_chunk_get_base_devx_obj_mirror(stc_attr->ste_table.ste_pool, 341 &stc_attr->ste_table.ste); 342 343 *fixup_stc_attr = *stc_attr; 344 fixup_stc_attr->ste_table.ste_obj_id = devx_obj->id; 345 use_fixup = true; 346 break; 347 348 case MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT: 349 if (stc_attr->vport.vport_num != WIRE_PORT) 350 break; 351 352 if (fw_tbl_type == FS_FT_FDB_RX) { 353 /* The FW doesn't allow to go back to wire in RX, so change it to DROP */ 354 fixup_stc_attr->action_type = MLX5_IFC_STC_ACTION_TYPE_DROP; 355 fixup_stc_attr->action_offset = MLX5DR_ACTION_OFFSET_HIT; 356 fixup_stc_attr->stc_offset = stc_attr->stc_offset; 357 } else if (fw_tbl_type == FS_FT_FDB_TX) { 358 /*The FW doesn't allow to go to wire in the TX by JUMP_TO_VPORT*/ 359 fixup_stc_attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_UPLINK; 360 fixup_stc_attr->action_offset = stc_attr->action_offset; 361 fixup_stc_attr->stc_offset = stc_attr->stc_offset; 362 fixup_stc_attr->vport.vport_num = 0; 363 fixup_stc_attr->vport.esw_owner_vhca_id = stc_attr->vport.esw_owner_vhca_id; 364 } 365 use_fixup = true; 366 break; 367 368 default: 369 break; 370 } 371 372 return use_fixup; 373 } 374 375 int mlx5dr_action_alloc_single_stc(struct mlx5dr_context *ctx, 376 struct mlx5dr_cmd_stc_modify_attr *stc_attr, 377 uint32_t table_type, 378 struct mlx5dr_pool_chunk *stc) 379 { 380 struct mlx5dr_cmd_stc_modify_attr cleanup_stc_attr = {0}; 381 struct mlx5dr_pool *stc_pool = ctx->stc_pool[table_type]; 382 struct mlx5dr_cmd_stc_modify_attr fixup_stc_attr = {0}; 383 struct mlx5dr_devx_obj *devx_obj_0; 384 bool use_fixup; 385 int ret; 386 387 ret = mlx5dr_pool_chunk_alloc(stc_pool, stc); 388 if (ret) { 389 DR_LOG(ERR, "Failed to allocate single action STC"); 390 return ret; 391 } 392 393 stc_attr->stc_offset = stc->offset; 394 devx_obj_0 = mlx5dr_pool_chunk_get_base_devx_obj(stc_pool, stc); 395 396 /* According to table/action limitation change the stc_attr */ 397 use_fixup = mlx5dr_action_fixup_stc_attr(stc_attr, &fixup_stc_attr, table_type, false); 398 ret = mlx5dr_cmd_stc_modify(devx_obj_0, use_fixup ? &fixup_stc_attr : stc_attr); 399 if (ret) { 400 DR_LOG(ERR, "Failed to modify STC action_type %d tbl_type %d", 401 stc_attr->action_type, table_type); 402 goto free_chunk; 403 } 404 405 /* Modify the FDB peer */ 406 if (table_type == MLX5DR_TABLE_TYPE_FDB) { 407 struct mlx5dr_devx_obj *devx_obj_1; 408 409 devx_obj_1 = mlx5dr_pool_chunk_get_base_devx_obj_mirror(stc_pool, stc); 410 411 use_fixup = mlx5dr_action_fixup_stc_attr(stc_attr, &fixup_stc_attr, 412 table_type, true); 413 ret = mlx5dr_cmd_stc_modify(devx_obj_1, use_fixup ? &fixup_stc_attr : stc_attr); 414 if (ret) { 415 DR_LOG(ERR, "Failed to modify peer STC action_type %d tbl_type %d", 416 stc_attr->action_type, table_type); 417 goto clean_devx_obj_0; 418 } 419 } 420 421 return 0; 422 423 clean_devx_obj_0: 424 cleanup_stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_DROP; 425 cleanup_stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT; 426 cleanup_stc_attr.stc_offset = stc->offset; 427 mlx5dr_cmd_stc_modify(devx_obj_0, &cleanup_stc_attr); 428 free_chunk: 429 mlx5dr_pool_chunk_free(stc_pool, stc); 430 return rte_errno; 431 } 432 433 void mlx5dr_action_free_single_stc(struct mlx5dr_context *ctx, 434 uint32_t table_type, 435 struct mlx5dr_pool_chunk *stc) 436 { 437 struct mlx5dr_pool *stc_pool = ctx->stc_pool[table_type]; 438 struct mlx5dr_cmd_stc_modify_attr stc_attr = {0}; 439 struct mlx5dr_devx_obj *devx_obj; 440 441 /* Modify the STC not to point to an object */ 442 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_DROP; 443 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT; 444 stc_attr.stc_offset = stc->offset; 445 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj(stc_pool, stc); 446 mlx5dr_cmd_stc_modify(devx_obj, &stc_attr); 447 448 if (table_type == MLX5DR_TABLE_TYPE_FDB) { 449 devx_obj = mlx5dr_pool_chunk_get_base_devx_obj_mirror(stc_pool, stc); 450 mlx5dr_cmd_stc_modify(devx_obj, &stc_attr); 451 } 452 453 mlx5dr_pool_chunk_free(stc_pool, stc); 454 } 455 456 static uint32_t mlx5dr_action_get_mh_stc_type(__be64 pattern) 457 { 458 uint8_t action_type = MLX5_GET(set_action_in, &pattern, action_type); 459 460 switch (action_type) { 461 case MLX5_MODIFICATION_TYPE_SET: 462 return MLX5_IFC_STC_ACTION_TYPE_SET; 463 case MLX5_MODIFICATION_TYPE_ADD: 464 return MLX5_IFC_STC_ACTION_TYPE_ADD; 465 case MLX5_MODIFICATION_TYPE_COPY: 466 return MLX5_IFC_STC_ACTION_TYPE_COPY; 467 default: 468 assert(false); 469 DR_LOG(ERR, "Unsupported action type: 0x%x\n", action_type); 470 rte_errno = ENOTSUP; 471 return MLX5_IFC_STC_ACTION_TYPE_NOP; 472 } 473 } 474 475 static void mlx5dr_action_fill_stc_attr(struct mlx5dr_action *action, 476 struct mlx5dr_devx_obj *obj, 477 struct mlx5dr_cmd_stc_modify_attr *attr) 478 { 479 switch (action->type) { 480 case MLX5DR_ACTION_TYP_TAG: 481 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_TAG; 482 attr->action_offset = MLX5DR_ACTION_OFFSET_DW5; 483 break; 484 case MLX5DR_ACTION_TYP_DROP: 485 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_DROP; 486 attr->action_offset = MLX5DR_ACTION_OFFSET_HIT; 487 break; 488 case MLX5DR_ACTION_TYP_MISS: 489 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_ALLOW; 490 attr->action_offset = MLX5DR_ACTION_OFFSET_HIT; 491 /* TODO Need to support default miss for FDB */ 492 break; 493 case MLX5DR_ACTION_TYP_CTR: 494 attr->id = obj->id; 495 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_COUNTER; 496 attr->action_offset = MLX5DR_ACTION_OFFSET_DW0; 497 break; 498 case MLX5DR_ACTION_TYP_TIR: 499 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_TIR; 500 attr->action_offset = MLX5DR_ACTION_OFFSET_HIT; 501 attr->dest_tir_num = obj->id; 502 break; 503 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 504 case MLX5DR_ACTION_TYP_MODIFY_HDR: 505 attr->action_offset = MLX5DR_ACTION_OFFSET_DW6; 506 if (action->modify_header.num_of_actions == 1) { 507 attr->modify_action.data = action->modify_header.single_action; 508 attr->action_type = mlx5dr_action_get_mh_stc_type(attr->modify_action.data); 509 510 if (attr->action_type == MLX5_IFC_STC_ACTION_TYPE_ADD || 511 attr->action_type == MLX5_IFC_STC_ACTION_TYPE_SET) 512 MLX5_SET(set_action_in, &attr->modify_action.data, data, 0); 513 } else { 514 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_ACC_MODIFY_LIST; 515 attr->modify_header.arg_id = action->modify_header.arg_obj->id; 516 attr->modify_header.pattern_id = action->modify_header.pattern_obj->id; 517 } 518 break; 519 case MLX5DR_ACTION_TYP_FT: 520 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT; 521 attr->action_offset = MLX5DR_ACTION_OFFSET_HIT; 522 attr->dest_table_id = obj->id; 523 break; 524 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 525 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_HEADER_REMOVE; 526 attr->action_offset = MLX5DR_ACTION_OFFSET_DW5; 527 attr->remove_header.decap = 1; 528 attr->remove_header.start_anchor = MLX5_HEADER_ANCHOR_PACKET_START; 529 attr->remove_header.end_anchor = MLX5_HEADER_ANCHOR_INNER_MAC; 530 break; 531 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 532 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT; 533 attr->action_offset = MLX5DR_ACTION_OFFSET_DW6; 534 attr->insert_header.encap = 1; 535 attr->insert_header.insert_anchor = MLX5_HEADER_ANCHOR_PACKET_START; 536 attr->insert_header.arg_id = action->reformat.arg_obj->id; 537 attr->insert_header.header_size = action->reformat.header_size; 538 break; 539 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 540 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT; 541 attr->action_offset = MLX5DR_ACTION_OFFSET_DW6; 542 attr->insert_header.encap = 1; 543 attr->insert_header.insert_anchor = MLX5_HEADER_ANCHOR_PACKET_START; 544 attr->insert_header.arg_id = action->reformat.arg_obj->id; 545 attr->insert_header.header_size = action->reformat.header_size; 546 break; 547 case MLX5DR_ACTION_TYP_ASO_METER: 548 attr->action_offset = MLX5DR_ACTION_OFFSET_DW6; 549 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_ASO; 550 attr->aso.aso_type = ASO_OPC_MOD_POLICER; 551 attr->aso.devx_obj_id = obj->id; 552 attr->aso.return_reg_id = action->aso.return_reg_id; 553 break; 554 case MLX5DR_ACTION_TYP_ASO_CT: 555 attr->action_offset = MLX5DR_ACTION_OFFSET_DW6; 556 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_ASO; 557 attr->aso.aso_type = ASO_OPC_MOD_CONNECTION_TRACKING; 558 attr->aso.devx_obj_id = obj->id; 559 attr->aso.return_reg_id = action->aso.return_reg_id; 560 break; 561 case MLX5DR_ACTION_TYP_VPORT: 562 attr->action_offset = MLX5DR_ACTION_OFFSET_HIT; 563 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_VPORT; 564 attr->vport.vport_num = action->vport.vport_num; 565 attr->vport.esw_owner_vhca_id = action->vport.esw_owner_vhca_id; 566 break; 567 case MLX5DR_ACTION_TYP_POP_VLAN: 568 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_REMOVE_WORDS; 569 attr->action_offset = MLX5DR_ACTION_OFFSET_DW5; 570 attr->remove_words.start_anchor = MLX5_HEADER_ANCHOR_FIRST_VLAN_START; 571 attr->remove_words.num_of_words = MLX5DR_ACTION_HDR_LEN_L2_VLAN / 2; 572 break; 573 case MLX5DR_ACTION_TYP_PUSH_VLAN: 574 attr->action_type = MLX5_IFC_STC_ACTION_TYPE_HEADER_INSERT; 575 attr->action_offset = MLX5DR_ACTION_OFFSET_DW6; 576 attr->insert_header.encap = 0; 577 attr->insert_header.is_inline = 1; 578 attr->insert_header.insert_anchor = MLX5_HEADER_ANCHOR_PACKET_START; 579 attr->insert_header.insert_offset = MLX5DR_ACTION_HDR_LEN_L2_MACS; 580 attr->insert_header.header_size = MLX5DR_ACTION_HDR_LEN_L2_VLAN; 581 break; 582 default: 583 DR_LOG(ERR, "Invalid action type %d", action->type); 584 assert(false); 585 } 586 } 587 588 static int 589 mlx5dr_action_create_stcs(struct mlx5dr_action *action, 590 struct mlx5dr_devx_obj *obj) 591 { 592 struct mlx5dr_cmd_stc_modify_attr stc_attr = {0}; 593 struct mlx5dr_context *ctx = action->ctx; 594 int ret; 595 596 mlx5dr_action_fill_stc_attr(action, obj, &stc_attr); 597 598 /* Block unsupported parallel devx obj modify over the same base */ 599 pthread_spin_lock(&ctx->ctrl_lock); 600 601 /* Allocate STC for RX */ 602 if (action->flags & MLX5DR_ACTION_FLAG_HWS_RX) { 603 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, 604 MLX5DR_TABLE_TYPE_NIC_RX, 605 &action->stc[MLX5DR_TABLE_TYPE_NIC_RX]); 606 if (ret) 607 goto out_err; 608 } 609 610 /* Allocate STC for TX */ 611 if (action->flags & MLX5DR_ACTION_FLAG_HWS_TX) { 612 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, 613 MLX5DR_TABLE_TYPE_NIC_TX, 614 &action->stc[MLX5DR_TABLE_TYPE_NIC_TX]); 615 if (ret) 616 goto free_nic_rx_stc; 617 } 618 619 /* Allocate STC for FDB */ 620 if (action->flags & MLX5DR_ACTION_FLAG_HWS_FDB) { 621 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, 622 MLX5DR_TABLE_TYPE_FDB, 623 &action->stc[MLX5DR_TABLE_TYPE_FDB]); 624 if (ret) 625 goto free_nic_tx_stc; 626 } 627 628 pthread_spin_unlock(&ctx->ctrl_lock); 629 630 return 0; 631 632 free_nic_tx_stc: 633 if (action->flags & MLX5DR_ACTION_FLAG_HWS_TX) 634 mlx5dr_action_free_single_stc(ctx, 635 MLX5DR_TABLE_TYPE_NIC_TX, 636 &action->stc[MLX5DR_TABLE_TYPE_NIC_TX]); 637 free_nic_rx_stc: 638 if (action->flags & MLX5DR_ACTION_FLAG_HWS_RX) 639 mlx5dr_action_free_single_stc(ctx, 640 MLX5DR_TABLE_TYPE_NIC_RX, 641 &action->stc[MLX5DR_TABLE_TYPE_NIC_RX]); 642 out_err: 643 pthread_spin_unlock(&ctx->ctrl_lock); 644 return rte_errno; 645 } 646 647 static void 648 mlx5dr_action_destroy_stcs(struct mlx5dr_action *action) 649 { 650 struct mlx5dr_context *ctx = action->ctx; 651 652 /* Block unsupported parallel devx obj modify over the same base */ 653 pthread_spin_lock(&ctx->ctrl_lock); 654 655 if (action->flags & MLX5DR_ACTION_FLAG_HWS_RX) 656 mlx5dr_action_free_single_stc(ctx, MLX5DR_TABLE_TYPE_NIC_RX, 657 &action->stc[MLX5DR_TABLE_TYPE_NIC_RX]); 658 659 if (action->flags & MLX5DR_ACTION_FLAG_HWS_TX) 660 mlx5dr_action_free_single_stc(ctx, MLX5DR_TABLE_TYPE_NIC_TX, 661 &action->stc[MLX5DR_TABLE_TYPE_NIC_TX]); 662 663 if (action->flags & MLX5DR_ACTION_FLAG_HWS_FDB) 664 mlx5dr_action_free_single_stc(ctx, MLX5DR_TABLE_TYPE_FDB, 665 &action->stc[MLX5DR_TABLE_TYPE_FDB]); 666 667 pthread_spin_unlock(&ctx->ctrl_lock); 668 } 669 670 static bool 671 mlx5dr_action_is_root_flags(uint32_t flags) 672 { 673 return flags & (MLX5DR_ACTION_FLAG_ROOT_RX | 674 MLX5DR_ACTION_FLAG_ROOT_TX | 675 MLX5DR_ACTION_FLAG_ROOT_FDB); 676 } 677 678 static bool 679 mlx5dr_action_is_hws_flags(uint32_t flags) 680 { 681 return flags & (MLX5DR_ACTION_FLAG_HWS_RX | 682 MLX5DR_ACTION_FLAG_HWS_TX | 683 MLX5DR_ACTION_FLAG_HWS_FDB); 684 } 685 686 static struct mlx5dr_action * 687 mlx5dr_action_create_generic(struct mlx5dr_context *ctx, 688 uint32_t flags, 689 enum mlx5dr_action_type action_type) 690 { 691 struct mlx5dr_action *action; 692 693 if (!mlx5dr_action_is_root_flags(flags) && 694 !mlx5dr_action_is_hws_flags(flags)) { 695 DR_LOG(ERR, "Action flags must specify root or non root (HWS)"); 696 rte_errno = ENOTSUP; 697 return NULL; 698 } 699 700 if (mlx5dr_action_is_hws_flags(flags) && 701 !(ctx->flags & MLX5DR_CONTEXT_FLAG_HWS_SUPPORT)) { 702 DR_LOG(ERR, "Cannot create HWS action since HWS is not supported"); 703 rte_errno = ENOTSUP; 704 return NULL; 705 } 706 707 action = simple_calloc(1, sizeof(*action)); 708 if (!action) { 709 DR_LOG(ERR, "Failed to allocate memory for action [%d]", action_type); 710 rte_errno = ENOMEM; 711 return NULL; 712 } 713 714 action->ctx = ctx; 715 action->flags = flags; 716 action->type = action_type; 717 718 return action; 719 } 720 721 struct mlx5dr_action * 722 mlx5dr_action_create_dest_table(struct mlx5dr_context *ctx, 723 struct mlx5dr_table *tbl, 724 uint32_t flags) 725 { 726 struct mlx5dr_action *action; 727 int ret; 728 729 if (mlx5dr_table_is_root(tbl)) { 730 DR_LOG(ERR, "Root table cannot be set as destination"); 731 rte_errno = ENOTSUP; 732 return NULL; 733 } 734 735 if (mlx5dr_action_is_hws_flags(flags) && 736 mlx5dr_action_is_root_flags(flags)) { 737 DR_LOG(ERR, "Same action cannot be used for root and non root"); 738 rte_errno = ENOTSUP; 739 return NULL; 740 } 741 742 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_FT); 743 if (!action) 744 return NULL; 745 746 if (mlx5dr_action_is_root_flags(flags)) { 747 action->devx_obj = tbl->ft->obj; 748 } else { 749 ret = mlx5dr_action_create_stcs(action, tbl->ft); 750 if (ret) 751 goto free_action; 752 } 753 754 return action; 755 756 free_action: 757 simple_free(action); 758 return NULL; 759 } 760 761 struct mlx5dr_action * 762 mlx5dr_action_create_dest_tir(struct mlx5dr_context *ctx, 763 struct mlx5dr_devx_obj *obj, 764 uint32_t flags) 765 { 766 struct mlx5dr_action *action; 767 int ret; 768 769 if (mlx5dr_action_is_hws_flags(flags) && 770 mlx5dr_action_is_root_flags(flags)) { 771 DR_LOG(ERR, "Same action cannot be used for root and non root"); 772 rte_errno = ENOTSUP; 773 return NULL; 774 } 775 776 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_TIR); 777 if (!action) 778 return NULL; 779 780 if (mlx5dr_action_is_root_flags(flags)) { 781 action->devx_obj = obj->obj; 782 } else { 783 ret = mlx5dr_action_create_stcs(action, obj); 784 if (ret) 785 goto free_action; 786 } 787 788 return action; 789 790 free_action: 791 simple_free(action); 792 return NULL; 793 } 794 795 struct mlx5dr_action * 796 mlx5dr_action_create_dest_drop(struct mlx5dr_context *ctx, 797 uint32_t flags) 798 { 799 struct mlx5dr_action *action; 800 int ret; 801 802 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_DROP); 803 if (!action) 804 return NULL; 805 806 if (mlx5dr_action_is_hws_flags(flags)) { 807 ret = mlx5dr_action_create_stcs(action, NULL); 808 if (ret) 809 goto free_action; 810 } 811 812 return action; 813 814 free_action: 815 simple_free(action); 816 return NULL; 817 } 818 819 struct mlx5dr_action * 820 mlx5dr_action_create_default_miss(struct mlx5dr_context *ctx, 821 uint32_t flags) 822 { 823 struct mlx5dr_action *action; 824 int ret; 825 826 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_MISS); 827 if (!action) 828 return NULL; 829 830 if (mlx5dr_action_is_hws_flags(flags)) { 831 ret = mlx5dr_action_create_stcs(action, NULL); 832 if (ret) 833 goto free_action; 834 } 835 836 return action; 837 838 free_action: 839 simple_free(action); 840 return NULL; 841 } 842 843 struct mlx5dr_action * 844 mlx5dr_action_create_tag(struct mlx5dr_context *ctx, 845 uint32_t flags) 846 { 847 struct mlx5dr_action *action; 848 int ret; 849 850 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_TAG); 851 if (!action) 852 return NULL; 853 854 if (mlx5dr_action_is_hws_flags(flags)) { 855 ret = mlx5dr_action_create_stcs(action, NULL); 856 if (ret) 857 goto free_action; 858 } 859 860 return action; 861 862 free_action: 863 simple_free(action); 864 return NULL; 865 } 866 867 static struct mlx5dr_action * 868 mlx5dr_action_create_aso(struct mlx5dr_context *ctx, 869 enum mlx5dr_action_type action_type, 870 struct mlx5dr_devx_obj *devx_obj, 871 uint8_t return_reg_id, 872 uint32_t flags) 873 { 874 struct mlx5dr_action *action; 875 int ret; 876 877 if (mlx5dr_action_is_root_flags(flags)) { 878 DR_LOG(ERR, "ASO action cannot be used over root table"); 879 rte_errno = ENOTSUP; 880 return NULL; 881 } 882 883 action = mlx5dr_action_create_generic(ctx, flags, action_type); 884 if (!action) 885 return NULL; 886 887 action->aso.devx_obj = devx_obj; 888 action->aso.return_reg_id = return_reg_id; 889 890 ret = mlx5dr_action_create_stcs(action, devx_obj); 891 if (ret) 892 goto free_action; 893 894 return action; 895 896 free_action: 897 simple_free(action); 898 return NULL; 899 } 900 901 struct mlx5dr_action * 902 mlx5dr_action_create_aso_meter(struct mlx5dr_context *ctx, 903 struct mlx5dr_devx_obj *devx_obj, 904 uint8_t return_reg_id, 905 uint32_t flags) 906 { 907 return mlx5dr_action_create_aso(ctx, MLX5DR_ACTION_TYP_ASO_METER, 908 devx_obj, return_reg_id, flags); 909 } 910 911 struct mlx5dr_action * 912 mlx5dr_action_create_aso_ct(struct mlx5dr_context *ctx, 913 struct mlx5dr_devx_obj *devx_obj, 914 uint8_t return_reg_id, 915 uint32_t flags) 916 { 917 return mlx5dr_action_create_aso(ctx, MLX5DR_ACTION_TYP_ASO_CT, 918 devx_obj, return_reg_id, flags); 919 } 920 921 struct mlx5dr_action * 922 mlx5dr_action_create_counter(struct mlx5dr_context *ctx, 923 struct mlx5dr_devx_obj *obj, 924 uint32_t flags) 925 { 926 struct mlx5dr_action *action; 927 int ret; 928 929 if (mlx5dr_action_is_hws_flags(flags) && 930 mlx5dr_action_is_root_flags(flags)) { 931 DR_LOG(ERR, "Same action cannot be used for root and non root"); 932 rte_errno = ENOTSUP; 933 return NULL; 934 } 935 936 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_CTR); 937 if (!action) 938 return NULL; 939 940 if (mlx5dr_action_is_root_flags(flags)) { 941 action->devx_obj = obj->obj; 942 } else { 943 ret = mlx5dr_action_create_stcs(action, obj); 944 if (ret) 945 goto free_action; 946 } 947 948 return action; 949 950 free_action: 951 simple_free(action); 952 return NULL; 953 } 954 955 static int mlx5dr_action_create_dest_vport_hws(struct mlx5dr_context *ctx, 956 struct mlx5dr_action *action, 957 uint32_t ib_port_num) 958 { 959 struct mlx5dr_cmd_query_vport_caps vport_caps = {0}; 960 int ret; 961 962 ret = mlx5dr_cmd_query_ib_port(ctx->ibv_ctx, &vport_caps, ib_port_num); 963 if (ret) { 964 DR_LOG(ERR, "Failed querying port %d\n", ib_port_num); 965 return ret; 966 } 967 action->vport.vport_num = vport_caps.vport_num; 968 action->vport.esw_owner_vhca_id = vport_caps.esw_owner_vhca_id; 969 970 ret = mlx5dr_action_create_stcs(action, NULL); 971 if (ret) { 972 DR_LOG(ERR, "Failed creating stc for port %d\n", ib_port_num); 973 return ret; 974 } 975 976 return 0; 977 } 978 979 struct mlx5dr_action * 980 mlx5dr_action_create_dest_vport(struct mlx5dr_context *ctx, 981 uint32_t ib_port_num, 982 uint32_t flags) 983 { 984 struct mlx5dr_action *action; 985 int ret; 986 987 if (!(flags & MLX5DR_ACTION_FLAG_HWS_FDB)) { 988 DR_LOG(ERR, "Vport action is supported for FDB only\n"); 989 rte_errno = EINVAL; 990 return NULL; 991 } 992 993 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_VPORT); 994 if (!action) 995 return NULL; 996 997 ret = mlx5dr_action_create_dest_vport_hws(ctx, action, ib_port_num); 998 if (ret) { 999 DR_LOG(ERR, "Failed to create vport action HWS\n"); 1000 goto free_action; 1001 } 1002 1003 return action; 1004 1005 free_action: 1006 simple_free(action); 1007 return NULL; 1008 } 1009 1010 struct mlx5dr_action * 1011 mlx5dr_action_create_push_vlan(struct mlx5dr_context *ctx, uint32_t flags) 1012 { 1013 struct mlx5dr_action *action; 1014 int ret; 1015 1016 if (mlx5dr_action_is_root_flags(flags)) { 1017 DR_LOG(ERR, "Push vlan action not supported for root"); 1018 rte_errno = ENOTSUP; 1019 return NULL; 1020 } 1021 1022 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_PUSH_VLAN); 1023 if (!action) 1024 return NULL; 1025 1026 ret = mlx5dr_action_create_stcs(action, NULL); 1027 if (ret) { 1028 DR_LOG(ERR, "Failed creating stc for push vlan\n"); 1029 goto free_action; 1030 } 1031 1032 return action; 1033 1034 free_action: 1035 simple_free(action); 1036 return NULL; 1037 } 1038 1039 struct mlx5dr_action * 1040 mlx5dr_action_create_pop_vlan(struct mlx5dr_context *ctx, uint32_t flags) 1041 { 1042 struct mlx5dr_action *action; 1043 int ret; 1044 1045 if (mlx5dr_action_is_root_flags(flags)) { 1046 DR_LOG(ERR, "Pop vlan action not supported for root"); 1047 rte_errno = ENOTSUP; 1048 return NULL; 1049 } 1050 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_POP_VLAN); 1051 if (!action) 1052 return NULL; 1053 1054 ret = mlx5dr_action_get_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_POP); 1055 if (ret) { 1056 DR_LOG(ERR, "Failed to create remove stc for reformat"); 1057 goto free_action; 1058 } 1059 1060 ret = mlx5dr_action_create_stcs(action, NULL); 1061 if (ret) { 1062 DR_LOG(ERR, "Failed creating stc for pop vlan\n"); 1063 goto free_shared; 1064 } 1065 1066 return action; 1067 1068 free_shared: 1069 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_POP); 1070 free_action: 1071 simple_free(action); 1072 return NULL; 1073 } 1074 1075 static int 1076 mlx5dr_action_conv_reformat_type_to_action(uint32_t reformat_type, 1077 enum mlx5dr_action_type *action_type) 1078 { 1079 switch (reformat_type) { 1080 case MLX5DR_ACTION_REFORMAT_TYPE_TNL_L2_TO_L2: 1081 *action_type = MLX5DR_ACTION_TYP_TNL_L2_TO_L2; 1082 break; 1083 case MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2: 1084 *action_type = MLX5DR_ACTION_TYP_L2_TO_TNL_L2; 1085 break; 1086 case MLX5DR_ACTION_REFORMAT_TYPE_TNL_L3_TO_L2: 1087 *action_type = MLX5DR_ACTION_TYP_TNL_L3_TO_L2; 1088 break; 1089 case MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L3: 1090 *action_type = MLX5DR_ACTION_TYP_L2_TO_TNL_L3; 1091 break; 1092 default: 1093 DR_LOG(ERR, "Invalid reformat type requested"); 1094 rte_errno = ENOTSUP; 1095 return rte_errno; 1096 } 1097 return 0; 1098 } 1099 1100 static void 1101 mlx5dr_action_conv_reformat_to_verbs(uint32_t action_type, 1102 uint32_t *verb_reformat_type) 1103 { 1104 switch (action_type) { 1105 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1106 *verb_reformat_type = 1107 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2; 1108 break; 1109 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1110 *verb_reformat_type = 1111 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL; 1112 break; 1113 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1114 *verb_reformat_type = 1115 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2; 1116 break; 1117 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1118 *verb_reformat_type = 1119 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL; 1120 break; 1121 } 1122 } 1123 1124 static int 1125 mlx5dr_action_conv_flags_to_ft_type(uint32_t flags, enum mlx5dv_flow_table_type *ft_type) 1126 { 1127 if (flags & MLX5DR_ACTION_FLAG_ROOT_RX) { 1128 *ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 1129 } else if (flags & MLX5DR_ACTION_FLAG_ROOT_TX) { 1130 *ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX; 1131 #ifdef HAVE_MLX5DV_FLOW_MATCHER_FT_TYPE 1132 } else if (flags & MLX5DR_ACTION_FLAG_ROOT_FDB) { 1133 *ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 1134 #endif 1135 } else { 1136 rte_errno = ENOTSUP; 1137 return 1; 1138 } 1139 1140 return 0; 1141 } 1142 1143 static int 1144 mlx5dr_action_create_reformat_root(struct mlx5dr_action *action, 1145 size_t data_sz, 1146 void *data) 1147 { 1148 enum mlx5dv_flow_table_type ft_type = 0; /*fix compilation warn*/ 1149 uint32_t verb_reformat_type = 0; 1150 int ret; 1151 1152 /* Convert action to FT type and verbs reformat type */ 1153 ret = mlx5dr_action_conv_flags_to_ft_type(action->flags, &ft_type); 1154 if (ret) 1155 return rte_errno; 1156 1157 mlx5dr_action_conv_reformat_to_verbs(action->type, &verb_reformat_type); 1158 1159 /* Create the reformat type for root table */ 1160 action->flow_action = 1161 mlx5_glue->dv_create_flow_action_packet_reformat_root(action->ctx->ibv_ctx, 1162 data_sz, 1163 data, 1164 verb_reformat_type, 1165 ft_type); 1166 if (!action->flow_action) { 1167 rte_errno = errno; 1168 return rte_errno; 1169 } 1170 1171 return 0; 1172 } 1173 1174 static int mlx5dr_action_handle_reformat_args(struct mlx5dr_context *ctx, 1175 size_t data_sz, 1176 void *data, 1177 uint32_t bulk_size, 1178 struct mlx5dr_action *action) 1179 { 1180 uint32_t args_log_size; 1181 int ret; 1182 1183 if (data_sz % 2 != 0) { 1184 DR_LOG(ERR, "Data size should be multiply of 2"); 1185 rte_errno = EINVAL; 1186 return rte_errno; 1187 } 1188 action->reformat.header_size = data_sz; 1189 1190 args_log_size = mlx5dr_arg_data_size_to_arg_log_size(data_sz); 1191 if (args_log_size >= MLX5DR_ARG_CHUNK_SIZE_MAX) { 1192 DR_LOG(ERR, "Data size is bigger than supported"); 1193 rte_errno = EINVAL; 1194 return rte_errno; 1195 } 1196 args_log_size += bulk_size; 1197 1198 if (!mlx5dr_arg_is_valid_arg_request_size(ctx, args_log_size)) { 1199 DR_LOG(ERR, "Arg size %d does not fit FW requests", 1200 args_log_size); 1201 rte_errno = EINVAL; 1202 return rte_errno; 1203 } 1204 1205 action->reformat.arg_obj = mlx5dr_cmd_arg_create(ctx->ibv_ctx, 1206 args_log_size, 1207 ctx->pd_num); 1208 if (!action->reformat.arg_obj) { 1209 DR_LOG(ERR, "Failed to create arg for reformat"); 1210 return rte_errno; 1211 } 1212 1213 /* When INLINE need to write the arg data */ 1214 if (action->flags & MLX5DR_ACTION_FLAG_SHARED) { 1215 ret = mlx5dr_arg_write_inline_arg_data(ctx, 1216 action->reformat.arg_obj->id, 1217 data, 1218 data_sz); 1219 if (ret) { 1220 DR_LOG(ERR, "Failed to write inline arg for reformat"); 1221 goto free_arg; 1222 } 1223 } 1224 1225 return 0; 1226 1227 free_arg: 1228 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1229 return ret; 1230 } 1231 1232 static int mlx5dr_action_handle_l2_to_tunnel_l2(struct mlx5dr_context *ctx, 1233 size_t data_sz, 1234 void *data, 1235 uint32_t bulk_size, 1236 struct mlx5dr_action *action) 1237 { 1238 int ret; 1239 1240 ret = mlx5dr_action_handle_reformat_args(ctx, data_sz, data, bulk_size, 1241 action); 1242 if (ret) { 1243 DR_LOG(ERR, "Failed to create args for reformat"); 1244 return ret; 1245 } 1246 1247 ret = mlx5dr_action_create_stcs(action, NULL); 1248 if (ret) { 1249 DR_LOG(ERR, "Failed to create stc for reformat"); 1250 goto free_arg; 1251 } 1252 1253 return 0; 1254 1255 free_arg: 1256 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1257 return ret; 1258 } 1259 1260 static int mlx5dr_action_get_shared_stc_offset(struct mlx5dr_context_common_res *common_res, 1261 enum mlx5dr_context_shared_stc_type stc_type) 1262 { 1263 return common_res->shared_stc[stc_type]->remove_header.offset; 1264 } 1265 1266 static int mlx5dr_action_handle_l2_to_tunnel_l3(struct mlx5dr_context *ctx, 1267 size_t data_sz, 1268 void *data, 1269 uint32_t bulk_size, 1270 struct mlx5dr_action *action) 1271 { 1272 int ret; 1273 1274 ret = mlx5dr_action_handle_reformat_args(ctx, data_sz, data, bulk_size, 1275 action); 1276 if (ret) { 1277 DR_LOG(ERR, "Failed to create args for reformat"); 1278 return ret; 1279 } 1280 1281 /* The action is remove-l2-header + insert-l3-header */ 1282 ret = mlx5dr_action_get_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_DECAP); 1283 if (ret) { 1284 DR_LOG(ERR, "Failed to create remove stc for reformat"); 1285 goto free_arg; 1286 } 1287 1288 ret = mlx5dr_action_create_stcs(action, NULL); 1289 if (ret) { 1290 DR_LOG(ERR, "Failed to create insert stc for reformat"); 1291 goto down_shared; 1292 } 1293 1294 return 0; 1295 1296 down_shared: 1297 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_DECAP); 1298 free_arg: 1299 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1300 return ret; 1301 } 1302 1303 static void mlx5dr_action_prepare_decap_l3_actions(size_t data_sz, 1304 uint8_t *mh_data, 1305 int *num_of_actions) 1306 { 1307 int actions; 1308 uint32_t i; 1309 1310 /* Remove L2L3 outer headers */ 1311 MLX5_SET(stc_ste_param_remove, mh_data, action_type, 1312 MLX5_MODIFICATION_TYPE_REMOVE); 1313 MLX5_SET(stc_ste_param_remove, mh_data, decap, 0x1); 1314 MLX5_SET(stc_ste_param_remove, mh_data, remove_start_anchor, 1315 MLX5_HEADER_ANCHOR_PACKET_START); 1316 MLX5_SET(stc_ste_param_remove, mh_data, remove_end_anchor, 1317 MLX5_HEADER_ANCHOR_INNER_IPV6_IPV4); 1318 mh_data += MLX5DR_ACTION_DOUBLE_SIZE; /* Assume every action is 2 dw */ 1319 actions = 1; 1320 1321 /* Add the new header using inline action 4Byte at a time, the header 1322 * is added in reversed order to the beginning of the packet to avoid 1323 * incorrect parsing by the HW. Since header is 14B or 18B an extra 1324 * two bytes are padded and later removed. 1325 */ 1326 for (i = 0; i < data_sz / MLX5DR_ACTION_INLINE_DATA_SIZE + 1; i++) { 1327 MLX5_SET(stc_ste_param_insert, mh_data, action_type, 1328 MLX5_MODIFICATION_TYPE_INSERT); 1329 MLX5_SET(stc_ste_param_insert, mh_data, inline_data, 0x1); 1330 MLX5_SET(stc_ste_param_insert, mh_data, insert_anchor, 1331 MLX5_HEADER_ANCHOR_PACKET_START); 1332 MLX5_SET(stc_ste_param_insert, mh_data, insert_size, 2); 1333 mh_data += MLX5DR_ACTION_DOUBLE_SIZE; 1334 actions++; 1335 } 1336 1337 /* Remove first 2 extra bytes */ 1338 MLX5_SET(stc_ste_param_remove_words, mh_data, action_type, 1339 MLX5_MODIFICATION_TYPE_REMOVE_WORDS); 1340 MLX5_SET(stc_ste_param_remove_words, mh_data, remove_start_anchor, 1341 MLX5_HEADER_ANCHOR_PACKET_START); 1342 /* The hardware expects here size in words (2 bytes) */ 1343 MLX5_SET(stc_ste_param_remove_words, mh_data, remove_size, 1); 1344 actions++; 1345 1346 *num_of_actions = actions; 1347 } 1348 1349 static int 1350 mlx5dr_action_handle_tunnel_l3_to_l2(struct mlx5dr_context *ctx, 1351 size_t data_sz, 1352 void *data, 1353 uint32_t bulk_size, 1354 struct mlx5dr_action *action) 1355 { 1356 uint8_t mh_data[MLX5DR_ACTION_REFORMAT_DATA_SIZE] = {0}; 1357 int num_of_actions; 1358 int mh_data_size; 1359 int ret; 1360 1361 if (data_sz != MLX5DR_ACTION_HDR_LEN_L2 && 1362 data_sz != MLX5DR_ACTION_HDR_LEN_L2_W_VLAN) { 1363 DR_LOG(ERR, "Data size is not supported for decap-l3\n"); 1364 rte_errno = EINVAL; 1365 return rte_errno; 1366 } 1367 1368 mlx5dr_action_prepare_decap_l3_actions(data_sz, mh_data, &num_of_actions); 1369 1370 mh_data_size = num_of_actions * MLX5DR_MODIFY_ACTION_SIZE; 1371 1372 ret = mlx5dr_pat_arg_create_modify_header(ctx, action, mh_data_size, 1373 (__be64 *)mh_data, bulk_size); 1374 if (ret) { 1375 DR_LOG(ERR, "Failed allocating modify-header for decap-l3\n"); 1376 return ret; 1377 } 1378 1379 ret = mlx5dr_action_create_stcs(action, NULL); 1380 if (ret) 1381 goto free_mh_obj; 1382 1383 if (action->flags & MLX5DR_ACTION_FLAG_SHARED) { 1384 mlx5dr_action_prepare_decap_l3_data(data, mh_data, num_of_actions); 1385 ret = mlx5dr_arg_write_inline_arg_data(ctx, 1386 action->modify_header.arg_obj->id, 1387 (uint8_t *)mh_data, 1388 num_of_actions * 1389 MLX5DR_MODIFY_ACTION_SIZE); 1390 if (ret) { 1391 DR_LOG(ERR, "Failed writing INLINE arg decap_l3"); 1392 goto clean_stc; 1393 } 1394 } 1395 1396 return 0; 1397 1398 clean_stc: 1399 mlx5dr_action_destroy_stcs(action); 1400 free_mh_obj: 1401 mlx5dr_pat_arg_destroy_modify_header(ctx, action); 1402 return ret; 1403 } 1404 1405 static int 1406 mlx5dr_action_create_reformat_hws(struct mlx5dr_context *ctx, 1407 size_t data_sz, 1408 void *data, 1409 uint32_t bulk_size, 1410 struct mlx5dr_action *action) 1411 { 1412 int ret; 1413 1414 switch (action->type) { 1415 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1416 ret = mlx5dr_action_create_stcs(action, NULL); 1417 break; 1418 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1419 ret = mlx5dr_action_handle_l2_to_tunnel_l2(ctx, data_sz, data, bulk_size, action); 1420 break; 1421 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1422 ret = mlx5dr_action_handle_l2_to_tunnel_l3(ctx, data_sz, data, bulk_size, action); 1423 break; 1424 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1425 ret = mlx5dr_action_handle_tunnel_l3_to_l2(ctx, data_sz, data, bulk_size, action); 1426 break; 1427 1428 default: 1429 assert(false); 1430 rte_errno = ENOTSUP; 1431 return rte_errno; 1432 } 1433 1434 return ret; 1435 } 1436 1437 struct mlx5dr_action * 1438 mlx5dr_action_create_reformat(struct mlx5dr_context *ctx, 1439 enum mlx5dr_action_reformat_type reformat_type, 1440 size_t data_sz, 1441 void *inline_data, 1442 uint32_t log_bulk_size, 1443 uint32_t flags) 1444 { 1445 enum mlx5dr_action_type action_type; 1446 struct mlx5dr_action *action; 1447 int ret; 1448 1449 ret = mlx5dr_action_conv_reformat_type_to_action(reformat_type, &action_type); 1450 if (ret) 1451 return NULL; 1452 1453 action = mlx5dr_action_create_generic(ctx, flags, action_type); 1454 if (!action) 1455 return NULL; 1456 1457 if (mlx5dr_action_is_root_flags(flags)) { 1458 if (log_bulk_size) { 1459 DR_LOG(ERR, "Bulk reformat not supported over root"); 1460 rte_errno = ENOTSUP; 1461 goto free_action; 1462 } 1463 1464 ret = mlx5dr_action_create_reformat_root(action, data_sz, inline_data); 1465 if (ret) 1466 goto free_action; 1467 1468 return action; 1469 } 1470 1471 if (!mlx5dr_action_is_hws_flags(flags) || 1472 ((flags & MLX5DR_ACTION_FLAG_SHARED) && log_bulk_size)) { 1473 DR_LOG(ERR, "Reformat flags don't fit HWS (flags: %x0x)\n", 1474 flags); 1475 rte_errno = EINVAL; 1476 goto free_action; 1477 } 1478 1479 ret = mlx5dr_action_create_reformat_hws(ctx, data_sz, inline_data, log_bulk_size, action); 1480 if (ret) { 1481 DR_LOG(ERR, "Failed to create reformat.\n"); 1482 rte_errno = EINVAL; 1483 goto free_action; 1484 } 1485 1486 return action; 1487 1488 free_action: 1489 simple_free(action); 1490 return NULL; 1491 } 1492 1493 static int 1494 mlx5dr_action_create_modify_header_root(struct mlx5dr_action *action, 1495 size_t actions_sz, 1496 __be64 *actions) 1497 { 1498 enum mlx5dv_flow_table_type ft_type = 0; 1499 int ret; 1500 1501 ret = mlx5dr_action_conv_flags_to_ft_type(action->flags, &ft_type); 1502 if (ret) 1503 return rte_errno; 1504 1505 action->flow_action = 1506 mlx5_glue->dv_create_flow_action_modify_header_root(action->ctx->ibv_ctx, 1507 actions_sz, 1508 (uint64_t *)actions, 1509 ft_type); 1510 if (!action->flow_action) { 1511 rte_errno = errno; 1512 return rte_errno; 1513 } 1514 1515 return 0; 1516 } 1517 1518 struct mlx5dr_action * 1519 mlx5dr_action_create_modify_header(struct mlx5dr_context *ctx, 1520 size_t pattern_sz, 1521 __be64 pattern[], 1522 uint32_t log_bulk_size, 1523 uint32_t flags) 1524 { 1525 struct mlx5dr_action *action; 1526 int ret; 1527 1528 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_MODIFY_HDR); 1529 if (!action) 1530 return NULL; 1531 1532 if (mlx5dr_action_is_root_flags(flags)) { 1533 if (log_bulk_size) { 1534 DR_LOG(ERR, "Bulk modify-header not supported over root"); 1535 rte_errno = ENOTSUP; 1536 goto free_action; 1537 } 1538 ret = mlx5dr_action_create_modify_header_root(action, pattern_sz, pattern); 1539 if (ret) 1540 goto free_action; 1541 1542 return action; 1543 } 1544 1545 if (!mlx5dr_action_is_hws_flags(flags) || 1546 ((flags & MLX5DR_ACTION_FLAG_SHARED) && log_bulk_size)) { 1547 DR_LOG(ERR, "Flags don't fit hws (flags: %x0x, log_bulk_size: %d)\n", 1548 flags, log_bulk_size); 1549 rte_errno = EINVAL; 1550 goto free_action; 1551 } 1552 1553 if (pattern_sz / MLX5DR_MODIFY_ACTION_SIZE == 1) { 1554 /* Optimize single modiy action to be used inline */ 1555 action->modify_header.single_action = pattern[0]; 1556 action->modify_header.num_of_actions = 1; 1557 action->modify_header.single_action_type = 1558 MLX5_GET(set_action_in, pattern, action_type); 1559 } else { 1560 /* Use multi action pattern and argument */ 1561 ret = mlx5dr_pat_arg_create_modify_header(ctx, action, pattern_sz, 1562 pattern, log_bulk_size); 1563 if (ret) { 1564 DR_LOG(ERR, "Failed allocating modify-header\n"); 1565 goto free_action; 1566 } 1567 } 1568 1569 ret = mlx5dr_action_create_stcs(action, NULL); 1570 if (ret) 1571 goto free_mh_obj; 1572 1573 return action; 1574 1575 free_mh_obj: 1576 if (action->modify_header.num_of_actions > 1) 1577 mlx5dr_pat_arg_destroy_modify_header(ctx, action); 1578 free_action: 1579 simple_free(action); 1580 return NULL; 1581 } 1582 1583 static void mlx5dr_action_destroy_hws(struct mlx5dr_action *action) 1584 { 1585 switch (action->type) { 1586 case MLX5DR_ACTION_TYP_TIR: 1587 case MLX5DR_ACTION_TYP_MISS: 1588 case MLX5DR_ACTION_TYP_TAG: 1589 case MLX5DR_ACTION_TYP_DROP: 1590 case MLX5DR_ACTION_TYP_CTR: 1591 case MLX5DR_ACTION_TYP_FT: 1592 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1593 case MLX5DR_ACTION_TYP_ASO_METER: 1594 case MLX5DR_ACTION_TYP_ASO_CT: 1595 case MLX5DR_ACTION_TYP_PUSH_VLAN: 1596 mlx5dr_action_destroy_stcs(action); 1597 break; 1598 case MLX5DR_ACTION_TYP_POP_VLAN: 1599 mlx5dr_action_destroy_stcs(action); 1600 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_POP); 1601 break; 1602 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1603 case MLX5DR_ACTION_TYP_MODIFY_HDR: 1604 mlx5dr_action_destroy_stcs(action); 1605 if (action->modify_header.num_of_actions > 1) 1606 mlx5dr_pat_arg_destroy_modify_header(action->ctx, action); 1607 break; 1608 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1609 mlx5dr_action_destroy_stcs(action); 1610 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_DECAP); 1611 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1612 break; 1613 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1614 mlx5dr_action_destroy_stcs(action); 1615 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1616 break; 1617 } 1618 } 1619 1620 static void mlx5dr_action_destroy_root(struct mlx5dr_action *action) 1621 { 1622 switch (action->type) { 1623 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1624 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1625 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1626 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1627 case MLX5DR_ACTION_TYP_MODIFY_HDR: 1628 ibv_destroy_flow_action(action->flow_action); 1629 break; 1630 } 1631 } 1632 1633 int mlx5dr_action_destroy(struct mlx5dr_action *action) 1634 { 1635 if (mlx5dr_action_is_root_flags(action->flags)) 1636 mlx5dr_action_destroy_root(action); 1637 else 1638 mlx5dr_action_destroy_hws(action); 1639 1640 simple_free(action); 1641 return 0; 1642 } 1643 1644 /* Called under pthread_spin_lock(&ctx->ctrl_lock) */ 1645 int mlx5dr_action_get_default_stc(struct mlx5dr_context *ctx, 1646 uint8_t tbl_type) 1647 { 1648 struct mlx5dr_cmd_stc_modify_attr stc_attr = {0}; 1649 struct mlx5dr_action_default_stc *default_stc; 1650 int ret; 1651 1652 if (ctx->common_res[tbl_type].default_stc) { 1653 ctx->common_res[tbl_type].default_stc->refcount++; 1654 return 0; 1655 } 1656 1657 default_stc = simple_calloc(1, sizeof(*default_stc)); 1658 if (!default_stc) { 1659 DR_LOG(ERR, "Failed to allocate memory for default STCs"); 1660 rte_errno = ENOMEM; 1661 return rte_errno; 1662 } 1663 1664 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_NOP; 1665 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW0; 1666 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1667 &default_stc->nop_ctr); 1668 if (ret) { 1669 DR_LOG(ERR, "Failed to allocate default counter STC"); 1670 goto free_default_stc; 1671 } 1672 1673 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW5; 1674 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1675 &default_stc->nop_dw5); 1676 if (ret) { 1677 DR_LOG(ERR, "Failed to allocate default NOP DW5 STC"); 1678 goto free_nop_ctr; 1679 } 1680 1681 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW6; 1682 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1683 &default_stc->nop_dw6); 1684 if (ret) { 1685 DR_LOG(ERR, "Failed to allocate default NOP DW6 STC"); 1686 goto free_nop_dw5; 1687 } 1688 1689 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW7; 1690 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1691 &default_stc->nop_dw7); 1692 if (ret) { 1693 DR_LOG(ERR, "Failed to allocate default NOP DW7 STC"); 1694 goto free_nop_dw6; 1695 } 1696 1697 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_ALLOW; 1698 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT; 1699 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1700 &default_stc->default_hit); 1701 if (ret) { 1702 DR_LOG(ERR, "Failed to allocate default allow STC"); 1703 goto free_nop_dw7; 1704 } 1705 1706 ctx->common_res[tbl_type].default_stc = default_stc; 1707 ctx->common_res[tbl_type].default_stc->refcount++; 1708 1709 return 0; 1710 1711 free_nop_dw7: 1712 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw7); 1713 free_nop_dw6: 1714 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw6); 1715 free_nop_dw5: 1716 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw5); 1717 free_nop_ctr: 1718 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_ctr); 1719 free_default_stc: 1720 simple_free(default_stc); 1721 return rte_errno; 1722 } 1723 1724 void mlx5dr_action_put_default_stc(struct mlx5dr_context *ctx, 1725 uint8_t tbl_type) 1726 { 1727 struct mlx5dr_action_default_stc *default_stc; 1728 1729 default_stc = ctx->common_res[tbl_type].default_stc; 1730 1731 default_stc = ctx->common_res[tbl_type].default_stc; 1732 if (--default_stc->refcount) 1733 return; 1734 1735 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->default_hit); 1736 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw7); 1737 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw6); 1738 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw5); 1739 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_ctr); 1740 simple_free(default_stc); 1741 ctx->common_res[tbl_type].default_stc = NULL; 1742 } 1743 1744 static void mlx5dr_action_modify_write(struct mlx5dr_send_engine *queue, 1745 uint32_t arg_idx, 1746 uint8_t *arg_data, 1747 uint16_t num_of_actions) 1748 { 1749 mlx5dr_arg_write(queue, NULL, arg_idx, arg_data, 1750 num_of_actions * MLX5DR_MODIFY_ACTION_SIZE); 1751 } 1752 1753 void 1754 mlx5dr_action_prepare_decap_l3_data(uint8_t *src, uint8_t *dst, 1755 uint16_t num_of_actions) 1756 { 1757 uint8_t *e_src; 1758 int i; 1759 1760 /* num_of_actions = remove l3l2 + 4/5 inserts + remove extra 2 bytes 1761 * copy from end of src to the start of dst. 1762 * move to the end, 2 is the leftover from 14B or 18B 1763 */ 1764 if (num_of_actions == DECAP_L3_NUM_ACTIONS_W_NO_VLAN) 1765 e_src = src + MLX5DR_ACTION_HDR_LEN_L2; 1766 else 1767 e_src = src + MLX5DR_ACTION_HDR_LEN_L2_W_VLAN; 1768 1769 /* Move dst over the first remove action + zero data */ 1770 dst += MLX5DR_ACTION_DOUBLE_SIZE; 1771 /* Move dst over the first insert ctrl action */ 1772 dst += MLX5DR_ACTION_DOUBLE_SIZE / 2; 1773 /* Actions: 1774 * no vlan: r_h-insert_4b-insert_4b-insert_4b-insert_4b-remove_2b. 1775 * with vlan: r_h-insert_4b-insert_4b-insert_4b-insert_4b-insert_4b-remove_2b. 1776 * the loop is without the last insertion. 1777 */ 1778 for (i = 0; i < num_of_actions - 3; i++) { 1779 e_src -= MLX5DR_ACTION_INLINE_DATA_SIZE; 1780 memcpy(dst, e_src, MLX5DR_ACTION_INLINE_DATA_SIZE); /* data */ 1781 dst += MLX5DR_ACTION_DOUBLE_SIZE; 1782 } 1783 /* Copy the last 2 bytes after a gap of 2 bytes which will be removed */ 1784 e_src -= MLX5DR_ACTION_INLINE_DATA_SIZE / 2; 1785 dst += MLX5DR_ACTION_INLINE_DATA_SIZE / 2; 1786 memcpy(dst, e_src, 2); 1787 } 1788 1789 static struct mlx5dr_actions_wqe_setter * 1790 mlx5dr_action_setter_find_first(struct mlx5dr_actions_wqe_setter *setter, 1791 uint8_t req_flags) 1792 { 1793 /* Use a new setter if requested flags are taken */ 1794 while (setter->flags & req_flags) 1795 setter++; 1796 1797 /* Use current setter in required flags are not used */ 1798 return setter; 1799 } 1800 1801 static void 1802 mlx5dr_action_apply_stc(struct mlx5dr_actions_apply_data *apply, 1803 enum mlx5dr_action_stc_idx stc_idx, 1804 uint8_t action_idx) 1805 { 1806 struct mlx5dr_action *action = apply->rule_action[action_idx].action; 1807 1808 apply->wqe_ctrl->stc_ix[stc_idx] = 1809 htobe32(action->stc[apply->tbl_type].offset); 1810 } 1811 1812 static void 1813 mlx5dr_action_setter_push_vlan(struct mlx5dr_actions_apply_data *apply, 1814 struct mlx5dr_actions_wqe_setter *setter) 1815 { 1816 struct mlx5dr_rule_action *rule_action; 1817 1818 rule_action = &apply->rule_action[setter->idx_double]; 1819 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1820 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = rule_action->push_vlan.vlan_hdr; 1821 1822 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1823 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1824 } 1825 1826 static void 1827 mlx5dr_action_setter_modify_header(struct mlx5dr_actions_apply_data *apply, 1828 struct mlx5dr_actions_wqe_setter *setter) 1829 { 1830 struct mlx5dr_rule_action *rule_action; 1831 struct mlx5dr_action *action; 1832 uint32_t arg_sz, arg_idx; 1833 uint8_t *single_action; 1834 1835 rule_action = &apply->rule_action[setter->idx_double]; 1836 action = rule_action->action; 1837 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1838 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1839 1840 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1841 1842 if (action->modify_header.num_of_actions == 1) { 1843 if (action->modify_header.single_action_type == 1844 MLX5_MODIFICATION_TYPE_COPY) { 1845 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = 0; 1846 return; 1847 } 1848 1849 if (action->flags & MLX5DR_ACTION_FLAG_SHARED) 1850 single_action = (uint8_t *)&action->modify_header.single_action; 1851 else 1852 single_action = rule_action->modify_header.data; 1853 1854 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = 1855 *(__be32 *)MLX5_ADDR_OF(set_action_in, single_action, data); 1856 } else { 1857 /* Argument offset multiple with number of args per these actions */ 1858 arg_sz = mlx5dr_arg_get_arg_size(action->modify_header.num_of_actions); 1859 arg_idx = rule_action->modify_header.offset * arg_sz; 1860 1861 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(arg_idx); 1862 1863 if (!(action->flags & MLX5DR_ACTION_FLAG_SHARED)) { 1864 apply->require_dep = 1; 1865 mlx5dr_action_modify_write(apply->queue, 1866 action->modify_header.arg_obj->id + arg_idx, 1867 rule_action->modify_header.data, 1868 action->modify_header.num_of_actions); 1869 } 1870 } 1871 } 1872 1873 static void 1874 mlx5dr_action_setter_insert_ptr(struct mlx5dr_actions_apply_data *apply, 1875 struct mlx5dr_actions_wqe_setter *setter) 1876 { 1877 struct mlx5dr_rule_action *rule_action; 1878 uint32_t arg_idx, arg_sz; 1879 1880 rule_action = &apply->rule_action[setter->idx_double]; 1881 1882 /* Argument offset multiple on args required for header size */ 1883 arg_sz = mlx5dr_arg_data_size_to_arg_size(rule_action->action->reformat.header_size); 1884 arg_idx = rule_action->reformat.offset * arg_sz; 1885 1886 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1887 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(arg_idx); 1888 1889 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1890 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1891 1892 if (!(rule_action->action->flags & MLX5DR_ACTION_FLAG_SHARED)) { 1893 apply->require_dep = 1; 1894 mlx5dr_arg_write(apply->queue, NULL, 1895 rule_action->action->reformat.arg_obj->id + arg_idx, 1896 rule_action->reformat.data, 1897 rule_action->action->reformat.header_size); 1898 } 1899 } 1900 1901 static void 1902 mlx5dr_action_setter_tnl_l3_to_l2(struct mlx5dr_actions_apply_data *apply, 1903 struct mlx5dr_actions_wqe_setter *setter) 1904 { 1905 struct mlx5dr_rule_action *rule_action; 1906 struct mlx5dr_action *action; 1907 uint32_t arg_sz, arg_idx; 1908 1909 rule_action = &apply->rule_action[setter->idx_double]; 1910 action = rule_action->action; 1911 1912 /* Argument offset multiple on args required for num of actions */ 1913 arg_sz = mlx5dr_arg_get_arg_size(action->modify_header.num_of_actions); 1914 arg_idx = rule_action->reformat.offset * arg_sz; 1915 1916 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1917 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(arg_idx); 1918 1919 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1920 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1921 1922 if (!(action->flags & MLX5DR_ACTION_FLAG_SHARED)) { 1923 apply->require_dep = 1; 1924 mlx5dr_arg_decapl3_write(apply->queue, 1925 action->modify_header.arg_obj->id + arg_idx, 1926 rule_action->reformat.data, 1927 action->modify_header.num_of_actions); 1928 } 1929 } 1930 1931 static void 1932 mlx5dr_action_setter_aso(struct mlx5dr_actions_apply_data *apply, 1933 struct mlx5dr_actions_wqe_setter *setter) 1934 { 1935 struct mlx5dr_rule_action *rule_action; 1936 uint32_t exe_aso_ctrl; 1937 uint32_t offset; 1938 1939 rule_action = &apply->rule_action[setter->idx_double]; 1940 1941 switch (rule_action->action->type) { 1942 case MLX5DR_ACTION_TYP_ASO_METER: 1943 /* exe_aso_ctrl format: 1944 * [STC only and reserved bits 29b][init_color 2b][meter_id 1b] 1945 */ 1946 offset = rule_action->aso_meter.offset / MLX5_ASO_METER_NUM_PER_OBJ; 1947 exe_aso_ctrl = rule_action->aso_meter.offset % MLX5_ASO_METER_NUM_PER_OBJ; 1948 exe_aso_ctrl |= rule_action->aso_meter.init_color << 1949 MLX5DR_ACTION_METER_INIT_COLOR_OFFSET; 1950 break; 1951 case MLX5DR_ACTION_TYP_ASO_CT: 1952 /* exe_aso_ctrl CT format: 1953 * [STC only and reserved bits 31b][direction 1b] 1954 */ 1955 offset = rule_action->aso_ct.offset / MLX5_ASO_CT_NUM_PER_OBJ; 1956 exe_aso_ctrl = rule_action->aso_ct.direction; 1957 break; 1958 default: 1959 DR_LOG(ERR, "Unsupported ASO action type: %d", rule_action->action->type); 1960 rte_errno = ENOTSUP; 1961 return; 1962 } 1963 1964 /* aso_object_offset format: [24B] */ 1965 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = htobe32(offset); 1966 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(exe_aso_ctrl); 1967 1968 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1969 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1970 } 1971 1972 static void 1973 mlx5dr_action_setter_tag(struct mlx5dr_actions_apply_data *apply, 1974 struct mlx5dr_actions_wqe_setter *setter) 1975 { 1976 struct mlx5dr_rule_action *rule_action; 1977 1978 rule_action = &apply->rule_action[setter->idx_single]; 1979 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = htobe32(rule_action->tag.value); 1980 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW5, setter->idx_single); 1981 } 1982 1983 static void 1984 mlx5dr_action_setter_ctrl_ctr(struct mlx5dr_actions_apply_data *apply, 1985 struct mlx5dr_actions_wqe_setter *setter) 1986 { 1987 struct mlx5dr_rule_action *rule_action; 1988 1989 rule_action = &apply->rule_action[setter->idx_ctr]; 1990 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW0] = htobe32(rule_action->counter.offset); 1991 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_CTRL, setter->idx_ctr); 1992 } 1993 1994 static void 1995 mlx5dr_action_setter_single(struct mlx5dr_actions_apply_data *apply, 1996 struct mlx5dr_actions_wqe_setter *setter) 1997 { 1998 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = 0; 1999 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW5, setter->idx_single); 2000 } 2001 2002 static void 2003 mlx5dr_action_setter_single_double_pop(struct mlx5dr_actions_apply_data *apply, 2004 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2005 { 2006 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = 0; 2007 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW5] = 2008 htobe32(mlx5dr_action_get_shared_stc_offset(apply->common_res, 2009 MLX5DR_CONTEXT_SHARED_STC_POP)); 2010 } 2011 2012 static void 2013 mlx5dr_action_setter_hit(struct mlx5dr_actions_apply_data *apply, 2014 struct mlx5dr_actions_wqe_setter *setter) 2015 { 2016 apply->wqe_data[MLX5DR_ACTION_OFFSET_HIT_LSB] = 0; 2017 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_HIT, setter->idx_hit); 2018 } 2019 2020 static void 2021 mlx5dr_action_setter_default_hit(struct mlx5dr_actions_apply_data *apply, 2022 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2023 { 2024 apply->wqe_data[MLX5DR_ACTION_OFFSET_HIT_LSB] = 0; 2025 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_HIT] = 2026 htobe32(apply->common_res->default_stc->default_hit.offset); 2027 } 2028 2029 static void 2030 mlx5dr_action_setter_hit_next_action(struct mlx5dr_actions_apply_data *apply, 2031 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2032 { 2033 apply->wqe_data[MLX5DR_ACTION_OFFSET_HIT_LSB] = htobe32(apply->next_direct_idx << 6); 2034 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_HIT] = htobe32(apply->jump_to_action_stc); 2035 } 2036 2037 static void 2038 mlx5dr_action_setter_common_decap(struct mlx5dr_actions_apply_data *apply, 2039 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2040 { 2041 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = 0; 2042 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW5] = 2043 htobe32(mlx5dr_action_get_shared_stc_offset(apply->common_res, 2044 MLX5DR_CONTEXT_SHARED_STC_DECAP)); 2045 } 2046 2047 int mlx5dr_action_template_process(struct mlx5dr_action_template *at) 2048 { 2049 struct mlx5dr_actions_wqe_setter *start_setter = at->setters + 1; 2050 enum mlx5dr_action_type *action_type = at->action_type_arr; 2051 struct mlx5dr_actions_wqe_setter *setter = at->setters; 2052 struct mlx5dr_actions_wqe_setter *pop_setter = NULL; 2053 struct mlx5dr_actions_wqe_setter *last_setter; 2054 int i; 2055 2056 /* Note: Given action combination must be valid */ 2057 2058 /* Check if action were already processed */ 2059 if (at->num_of_action_stes) 2060 return 0; 2061 2062 for (i = 0; i < MLX5DR_ACTION_MAX_STE; i++) 2063 setter[i].set_hit = &mlx5dr_action_setter_hit_next_action; 2064 2065 /* The same action template setters can be used with jumbo or match 2066 * STE, to support both cases we reseve the first setter for cases 2067 * with jumbo STE to allow jump to the first action STE. 2068 * This extra setter can be reduced in some cases on rule creation. 2069 */ 2070 setter = start_setter; 2071 last_setter = start_setter; 2072 2073 for (i = 0; i < at->num_actions; i++) { 2074 switch (action_type[i]) { 2075 case MLX5DR_ACTION_TYP_DROP: 2076 case MLX5DR_ACTION_TYP_TIR: 2077 case MLX5DR_ACTION_TYP_FT: 2078 case MLX5DR_ACTION_TYP_VPORT: 2079 case MLX5DR_ACTION_TYP_MISS: 2080 /* Hit action */ 2081 last_setter->flags |= ASF_HIT; 2082 last_setter->set_hit = &mlx5dr_action_setter_hit; 2083 last_setter->idx_hit = i; 2084 break; 2085 2086 case MLX5DR_ACTION_TYP_POP_VLAN: 2087 /* Single remove header to header */ 2088 if (pop_setter) { 2089 /* We have 2 pops, use the shared */ 2090 pop_setter->set_single = &mlx5dr_action_setter_single_double_pop; 2091 break; 2092 } 2093 setter = mlx5dr_action_setter_find_first(last_setter, ASF_SINGLE1 | ASF_MODIFY); 2094 setter->flags |= ASF_SINGLE1 | ASF_REPARSE | ASF_REMOVE; 2095 setter->set_single = &mlx5dr_action_setter_single; 2096 setter->idx_single = i; 2097 pop_setter = setter; 2098 break; 2099 2100 case MLX5DR_ACTION_TYP_PUSH_VLAN: 2101 /* Double insert inline */ 2102 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE | ASF_REMOVE); 2103 setter->flags |= ASF_DOUBLE | ASF_REPARSE | ASF_MODIFY; 2104 setter->set_double = &mlx5dr_action_setter_push_vlan; 2105 setter->idx_double = i; 2106 break; 2107 2108 case MLX5DR_ACTION_TYP_MODIFY_HDR: 2109 /* Double modify header list */ 2110 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE | ASF_REMOVE); 2111 setter->flags |= ASF_DOUBLE | ASF_MODIFY | ASF_REPARSE; 2112 setter->set_double = &mlx5dr_action_setter_modify_header; 2113 setter->idx_double = i; 2114 break; 2115 2116 case MLX5DR_ACTION_TYP_ASO_METER: 2117 case MLX5DR_ACTION_TYP_ASO_CT: 2118 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE); 2119 setter->flags |= ASF_DOUBLE; 2120 setter->set_double = &mlx5dr_action_setter_aso; 2121 setter->idx_double = i; 2122 break; 2123 2124 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 2125 /* Single remove header to header */ 2126 setter = mlx5dr_action_setter_find_first(last_setter, ASF_SINGLE1 | ASF_MODIFY); 2127 setter->flags |= ASF_SINGLE1 | ASF_REMOVE | ASF_REPARSE; 2128 setter->set_single = &mlx5dr_action_setter_single; 2129 setter->idx_single = i; 2130 break; 2131 2132 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 2133 /* Double insert header with pointer */ 2134 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE); 2135 setter->flags |= ASF_DOUBLE | ASF_REPARSE; 2136 setter->set_double = &mlx5dr_action_setter_insert_ptr; 2137 setter->idx_double = i; 2138 break; 2139 2140 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 2141 /* Single remove + Double insert header with pointer */ 2142 setter = mlx5dr_action_setter_find_first(last_setter, ASF_SINGLE1 | ASF_DOUBLE); 2143 setter->flags |= ASF_SINGLE1 | ASF_DOUBLE | ASF_REPARSE | ASF_REMOVE; 2144 setter->set_double = &mlx5dr_action_setter_insert_ptr; 2145 setter->idx_double = i; 2146 setter->set_single = &mlx5dr_action_setter_common_decap; 2147 setter->idx_single = i; 2148 break; 2149 2150 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 2151 /* Double modify header list with remove and push inline */ 2152 setter = mlx5dr_action_setter_find_first(last_setter, 2153 ASF_DOUBLE | ASF_REMOVE); 2154 setter->flags |= ASF_DOUBLE | ASF_MODIFY | ASF_REPARSE; 2155 setter->set_double = &mlx5dr_action_setter_tnl_l3_to_l2; 2156 setter->idx_double = i; 2157 break; 2158 2159 case MLX5DR_ACTION_TYP_TAG: 2160 /* Single TAG action, search for any room from the start */ 2161 setter = mlx5dr_action_setter_find_first(start_setter, ASF_SINGLE1); 2162 setter->flags |= ASF_SINGLE1; 2163 setter->set_single = &mlx5dr_action_setter_tag; 2164 setter->idx_single = i; 2165 break; 2166 2167 case MLX5DR_ACTION_TYP_CTR: 2168 /* Control counter action 2169 * TODO: Current counter executed first. Support is needed 2170 * for single ation counter action which is done last. 2171 * Example: Decap + CTR 2172 */ 2173 setter = mlx5dr_action_setter_find_first(start_setter, ASF_CTR); 2174 setter->flags |= ASF_CTR; 2175 setter->set_ctr = &mlx5dr_action_setter_ctrl_ctr; 2176 setter->idx_ctr = i; 2177 break; 2178 2179 default: 2180 DR_LOG(ERR, "Unsupported action type: %d", action_type[i]); 2181 rte_errno = ENOTSUP; 2182 assert(false); 2183 return rte_errno; 2184 } 2185 2186 last_setter = RTE_MAX(setter, last_setter); 2187 } 2188 2189 /* Set default hit on the last STE if no hit action provided */ 2190 if (!(last_setter->flags & ASF_HIT)) 2191 last_setter->set_hit = &mlx5dr_action_setter_default_hit; 2192 2193 at->num_of_action_stes = last_setter - start_setter + 1; 2194 2195 /* Check if action template doesn't require any action DWs */ 2196 at->only_term = (at->num_of_action_stes == 1) && 2197 !(last_setter->flags & ~(ASF_CTR | ASF_HIT)); 2198 2199 return 0; 2200 } 2201 2202 struct mlx5dr_action_template * 2203 mlx5dr_action_template_create(const enum mlx5dr_action_type action_type[]) 2204 { 2205 struct mlx5dr_action_template *at; 2206 uint8_t num_actions = 0; 2207 int i; 2208 2209 at = simple_calloc(1, sizeof(*at)); 2210 if (!at) { 2211 DR_LOG(ERR, "Failed to allocate action template"); 2212 rte_errno = ENOMEM; 2213 return NULL; 2214 } 2215 2216 while (action_type[num_actions++] != MLX5DR_ACTION_TYP_LAST) 2217 ; 2218 2219 at->num_actions = num_actions - 1; 2220 at->action_type_arr = simple_calloc(num_actions, sizeof(*action_type)); 2221 if (!at->action_type_arr) { 2222 DR_LOG(ERR, "Failed to allocate action type array"); 2223 rte_errno = ENOMEM; 2224 goto free_at; 2225 } 2226 2227 for (i = 0; i < num_actions; i++) 2228 at->action_type_arr[i] = action_type[i]; 2229 2230 return at; 2231 2232 free_at: 2233 simple_free(at); 2234 return NULL; 2235 } 2236 2237 int mlx5dr_action_template_destroy(struct mlx5dr_action_template *at) 2238 { 2239 simple_free(at->action_type_arr); 2240 simple_free(at); 2241 return 0; 2242 } 2243