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 if (mlx5dr_context_shared_gvmi_used(ctx)) 748 action->devx_obj = tbl->local_ft->obj; 749 else 750 action->devx_obj = tbl->ft->obj; 751 } else { 752 ret = mlx5dr_action_create_stcs(action, tbl->ft); 753 if (ret) 754 goto free_action; 755 } 756 757 return action; 758 759 free_action: 760 simple_free(action); 761 return NULL; 762 } 763 764 static int mlx5dr_action_get_dest_tir_obj(struct mlx5dr_context *ctx, 765 struct mlx5dr_action *action, 766 struct mlx5dr_devx_obj *obj, 767 struct mlx5dr_devx_obj **ret_obj) 768 { 769 int ret; 770 771 if (mlx5dr_context_shared_gvmi_used(ctx)) { 772 ret = mlx5dr_matcher_create_aliased_obj(ctx, 773 ctx->local_ibv_ctx, 774 ctx->ibv_ctx, 775 ctx->caps->vhca_id, 776 obj->id, 777 MLX5_GENERAL_OBJ_TYPE_TIR_ALIAS, 778 &action->alias.devx_obj); 779 if (ret) { 780 DR_LOG(ERR, "Failed to create tir alias"); 781 return rte_errno; 782 } 783 *ret_obj = action->alias.devx_obj; 784 } else { 785 *ret_obj = obj; 786 } 787 788 return 0; 789 } 790 791 struct mlx5dr_action * 792 mlx5dr_action_create_dest_tir(struct mlx5dr_context *ctx, 793 struct mlx5dr_devx_obj *obj, 794 uint32_t flags, 795 bool is_local) 796 { 797 struct mlx5dr_action *action; 798 int ret; 799 800 if (mlx5dr_action_is_hws_flags(flags) && 801 mlx5dr_action_is_root_flags(flags)) { 802 DR_LOG(ERR, "Same action cannot be used for root and non root"); 803 rte_errno = ENOTSUP; 804 return NULL; 805 } 806 807 if (!is_local) { 808 DR_LOG(ERR, "TIR should be created on local ibv_device, flags: 0x%x", 809 flags); 810 rte_errno = ENOTSUP; 811 return NULL; 812 } 813 814 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_TIR); 815 if (!action) 816 return NULL; 817 818 if (mlx5dr_action_is_root_flags(flags)) { 819 action->devx_obj = obj->obj; 820 } else { 821 struct mlx5dr_devx_obj *cur_obj = NULL; /*compilation warn*/ 822 823 ret = mlx5dr_action_get_dest_tir_obj(ctx, action, obj, &cur_obj); 824 if (ret) { 825 DR_LOG(ERR, "Failed to create tir alias (flags: %d)", flags); 826 goto free_action; 827 } 828 829 ret = mlx5dr_action_create_stcs(action, cur_obj); 830 if (ret) 831 goto clean_obj; 832 } 833 834 return action; 835 836 clean_obj: 837 mlx5dr_cmd_destroy_obj(action->alias.devx_obj); 838 free_action: 839 simple_free(action); 840 return NULL; 841 } 842 843 struct mlx5dr_action * 844 mlx5dr_action_create_dest_drop(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_DROP); 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 struct mlx5dr_action * 868 mlx5dr_action_create_default_miss(struct mlx5dr_context *ctx, 869 uint32_t flags) 870 { 871 struct mlx5dr_action *action; 872 int ret; 873 874 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_MISS); 875 if (!action) 876 return NULL; 877 878 if (mlx5dr_action_is_hws_flags(flags)) { 879 ret = mlx5dr_action_create_stcs(action, NULL); 880 if (ret) 881 goto free_action; 882 } 883 884 return action; 885 886 free_action: 887 simple_free(action); 888 return NULL; 889 } 890 891 struct mlx5dr_action * 892 mlx5dr_action_create_tag(struct mlx5dr_context *ctx, 893 uint32_t flags) 894 { 895 struct mlx5dr_action *action; 896 int ret; 897 898 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_TAG); 899 if (!action) 900 return NULL; 901 902 if (mlx5dr_action_is_hws_flags(flags)) { 903 ret = mlx5dr_action_create_stcs(action, NULL); 904 if (ret) 905 goto free_action; 906 } 907 908 return action; 909 910 free_action: 911 simple_free(action); 912 return NULL; 913 } 914 915 static struct mlx5dr_action * 916 mlx5dr_action_create_aso(struct mlx5dr_context *ctx, 917 enum mlx5dr_action_type action_type, 918 struct mlx5dr_devx_obj *devx_obj, 919 uint8_t return_reg_id, 920 uint32_t flags) 921 { 922 struct mlx5dr_action *action; 923 int ret; 924 925 if (mlx5dr_action_is_root_flags(flags)) { 926 DR_LOG(ERR, "ASO action cannot be used over root table"); 927 rte_errno = ENOTSUP; 928 return NULL; 929 } 930 931 action = mlx5dr_action_create_generic(ctx, flags, action_type); 932 if (!action) 933 return NULL; 934 935 action->aso.devx_obj = devx_obj; 936 action->aso.return_reg_id = return_reg_id; 937 938 ret = mlx5dr_action_create_stcs(action, devx_obj); 939 if (ret) 940 goto free_action; 941 942 return action; 943 944 free_action: 945 simple_free(action); 946 return NULL; 947 } 948 949 struct mlx5dr_action * 950 mlx5dr_action_create_aso_meter(struct mlx5dr_context *ctx, 951 struct mlx5dr_devx_obj *devx_obj, 952 uint8_t return_reg_id, 953 uint32_t flags) 954 { 955 return mlx5dr_action_create_aso(ctx, MLX5DR_ACTION_TYP_ASO_METER, 956 devx_obj, return_reg_id, flags); 957 } 958 959 struct mlx5dr_action * 960 mlx5dr_action_create_aso_ct(struct mlx5dr_context *ctx, 961 struct mlx5dr_devx_obj *devx_obj, 962 uint8_t return_reg_id, 963 uint32_t flags) 964 { 965 return mlx5dr_action_create_aso(ctx, MLX5DR_ACTION_TYP_ASO_CT, 966 devx_obj, return_reg_id, flags); 967 } 968 969 struct mlx5dr_action * 970 mlx5dr_action_create_counter(struct mlx5dr_context *ctx, 971 struct mlx5dr_devx_obj *obj, 972 uint32_t flags) 973 { 974 struct mlx5dr_action *action; 975 int ret; 976 977 if (mlx5dr_action_is_hws_flags(flags) && 978 mlx5dr_action_is_root_flags(flags)) { 979 DR_LOG(ERR, "Same action cannot be used for root and non root"); 980 rte_errno = ENOTSUP; 981 return NULL; 982 } 983 984 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_CTR); 985 if (!action) 986 return NULL; 987 988 if (mlx5dr_action_is_root_flags(flags)) { 989 action->devx_obj = obj->obj; 990 } else { 991 ret = mlx5dr_action_create_stcs(action, obj); 992 if (ret) 993 goto free_action; 994 } 995 996 return action; 997 998 free_action: 999 simple_free(action); 1000 return NULL; 1001 } 1002 1003 static int mlx5dr_action_create_dest_vport_hws(struct mlx5dr_context *ctx, 1004 struct mlx5dr_action *action, 1005 uint32_t ib_port_num) 1006 { 1007 struct mlx5dr_cmd_query_vport_caps vport_caps = {0}; 1008 int ret; 1009 1010 ret = mlx5dr_cmd_query_ib_port(ctx->ibv_ctx, &vport_caps, ib_port_num); 1011 if (ret) { 1012 DR_LOG(ERR, "Failed querying port %d\n", ib_port_num); 1013 return ret; 1014 } 1015 action->vport.vport_num = vport_caps.vport_num; 1016 action->vport.esw_owner_vhca_id = vport_caps.esw_owner_vhca_id; 1017 1018 ret = mlx5dr_action_create_stcs(action, NULL); 1019 if (ret) { 1020 DR_LOG(ERR, "Failed creating stc for port %d\n", ib_port_num); 1021 return ret; 1022 } 1023 1024 return 0; 1025 } 1026 1027 struct mlx5dr_action * 1028 mlx5dr_action_create_dest_vport(struct mlx5dr_context *ctx, 1029 uint32_t ib_port_num, 1030 uint32_t flags) 1031 { 1032 struct mlx5dr_action *action; 1033 int ret; 1034 1035 if (!(flags & MLX5DR_ACTION_FLAG_HWS_FDB)) { 1036 DR_LOG(ERR, "Vport action is supported for FDB only\n"); 1037 rte_errno = EINVAL; 1038 return NULL; 1039 } 1040 1041 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_VPORT); 1042 if (!action) 1043 return NULL; 1044 1045 ret = mlx5dr_action_create_dest_vport_hws(ctx, action, ib_port_num); 1046 if (ret) { 1047 DR_LOG(ERR, "Failed to create vport action HWS\n"); 1048 goto free_action; 1049 } 1050 1051 return action; 1052 1053 free_action: 1054 simple_free(action); 1055 return NULL; 1056 } 1057 1058 struct mlx5dr_action * 1059 mlx5dr_action_create_push_vlan(struct mlx5dr_context *ctx, uint32_t flags) 1060 { 1061 struct mlx5dr_action *action; 1062 int ret; 1063 1064 if (mlx5dr_action_is_root_flags(flags)) { 1065 DR_LOG(ERR, "Push vlan action not supported for root"); 1066 rte_errno = ENOTSUP; 1067 return NULL; 1068 } 1069 1070 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_PUSH_VLAN); 1071 if (!action) 1072 return NULL; 1073 1074 ret = mlx5dr_action_create_stcs(action, NULL); 1075 if (ret) { 1076 DR_LOG(ERR, "Failed creating stc for push vlan\n"); 1077 goto free_action; 1078 } 1079 1080 return action; 1081 1082 free_action: 1083 simple_free(action); 1084 return NULL; 1085 } 1086 1087 struct mlx5dr_action * 1088 mlx5dr_action_create_pop_vlan(struct mlx5dr_context *ctx, uint32_t flags) 1089 { 1090 struct mlx5dr_action *action; 1091 int ret; 1092 1093 if (mlx5dr_action_is_root_flags(flags)) { 1094 DR_LOG(ERR, "Pop vlan action not supported for root"); 1095 rte_errno = ENOTSUP; 1096 return NULL; 1097 } 1098 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_POP_VLAN); 1099 if (!action) 1100 return NULL; 1101 1102 ret = mlx5dr_action_get_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_POP); 1103 if (ret) { 1104 DR_LOG(ERR, "Failed to create remove stc for reformat"); 1105 goto free_action; 1106 } 1107 1108 ret = mlx5dr_action_create_stcs(action, NULL); 1109 if (ret) { 1110 DR_LOG(ERR, "Failed creating stc for pop vlan\n"); 1111 goto free_shared; 1112 } 1113 1114 return action; 1115 1116 free_shared: 1117 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_POP); 1118 free_action: 1119 simple_free(action); 1120 return NULL; 1121 } 1122 1123 static int 1124 mlx5dr_action_conv_reformat_type_to_action(uint32_t reformat_type, 1125 enum mlx5dr_action_type *action_type) 1126 { 1127 switch (reformat_type) { 1128 case MLX5DR_ACTION_REFORMAT_TYPE_TNL_L2_TO_L2: 1129 *action_type = MLX5DR_ACTION_TYP_TNL_L2_TO_L2; 1130 break; 1131 case MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2: 1132 *action_type = MLX5DR_ACTION_TYP_L2_TO_TNL_L2; 1133 break; 1134 case MLX5DR_ACTION_REFORMAT_TYPE_TNL_L3_TO_L2: 1135 *action_type = MLX5DR_ACTION_TYP_TNL_L3_TO_L2; 1136 break; 1137 case MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L3: 1138 *action_type = MLX5DR_ACTION_TYP_L2_TO_TNL_L3; 1139 break; 1140 default: 1141 DR_LOG(ERR, "Invalid reformat type requested"); 1142 rte_errno = ENOTSUP; 1143 return rte_errno; 1144 } 1145 return 0; 1146 } 1147 1148 static void 1149 mlx5dr_action_conv_reformat_to_verbs(uint32_t action_type, 1150 uint32_t *verb_reformat_type) 1151 { 1152 switch (action_type) { 1153 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1154 *verb_reformat_type = 1155 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2; 1156 break; 1157 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1158 *verb_reformat_type = 1159 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL; 1160 break; 1161 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1162 *verb_reformat_type = 1163 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2; 1164 break; 1165 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1166 *verb_reformat_type = 1167 MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL; 1168 break; 1169 } 1170 } 1171 1172 static int 1173 mlx5dr_action_conv_flags_to_ft_type(uint32_t flags, enum mlx5dv_flow_table_type *ft_type) 1174 { 1175 if (flags & MLX5DR_ACTION_FLAG_ROOT_RX) { 1176 *ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX; 1177 } else if (flags & MLX5DR_ACTION_FLAG_ROOT_TX) { 1178 *ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_TX; 1179 #ifdef HAVE_MLX5DV_FLOW_MATCHER_FT_TYPE 1180 } else if (flags & MLX5DR_ACTION_FLAG_ROOT_FDB) { 1181 *ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB; 1182 #endif 1183 } else { 1184 rte_errno = ENOTSUP; 1185 return 1; 1186 } 1187 1188 return 0; 1189 } 1190 1191 static int 1192 mlx5dr_action_create_reformat_root(struct mlx5dr_action *action, 1193 size_t data_sz, 1194 void *data) 1195 { 1196 enum mlx5dv_flow_table_type ft_type = 0; /*fix compilation warn*/ 1197 uint32_t verb_reformat_type = 0; 1198 struct ibv_context *ibv_ctx; 1199 int ret; 1200 1201 /* Convert action to FT type and verbs reformat type */ 1202 ret = mlx5dr_action_conv_flags_to_ft_type(action->flags, &ft_type); 1203 if (ret) 1204 return rte_errno; 1205 1206 mlx5dr_action_conv_reformat_to_verbs(action->type, &verb_reformat_type); 1207 1208 /* Create the reformat type for root table */ 1209 ibv_ctx = mlx5dr_context_get_local_ibv(action->ctx); 1210 action->flow_action = 1211 mlx5_glue->dv_create_flow_action_packet_reformat_root(ibv_ctx, 1212 data_sz, 1213 data, 1214 verb_reformat_type, 1215 ft_type); 1216 if (!action->flow_action) { 1217 rte_errno = errno; 1218 return rte_errno; 1219 } 1220 1221 return 0; 1222 } 1223 1224 static int mlx5dr_action_handle_reformat_args(struct mlx5dr_context *ctx, 1225 size_t data_sz, 1226 void *data, 1227 uint32_t bulk_size, 1228 struct mlx5dr_action *action) 1229 { 1230 uint32_t args_log_size; 1231 int ret; 1232 1233 if (data_sz % 2 != 0) { 1234 DR_LOG(ERR, "Data size should be multiply of 2"); 1235 rte_errno = EINVAL; 1236 return rte_errno; 1237 } 1238 action->reformat.header_size = data_sz; 1239 1240 args_log_size = mlx5dr_arg_data_size_to_arg_log_size(data_sz); 1241 if (args_log_size >= MLX5DR_ARG_CHUNK_SIZE_MAX) { 1242 DR_LOG(ERR, "Data size is bigger than supported"); 1243 rte_errno = EINVAL; 1244 return rte_errno; 1245 } 1246 args_log_size += bulk_size; 1247 1248 if (!mlx5dr_arg_is_valid_arg_request_size(ctx, args_log_size)) { 1249 DR_LOG(ERR, "Arg size %d does not fit FW requests", 1250 args_log_size); 1251 rte_errno = EINVAL; 1252 return rte_errno; 1253 } 1254 1255 action->reformat.arg_obj = mlx5dr_cmd_arg_create(ctx->ibv_ctx, 1256 args_log_size, 1257 ctx->pd_num); 1258 if (!action->reformat.arg_obj) { 1259 DR_LOG(ERR, "Failed to create arg for reformat"); 1260 return rte_errno; 1261 } 1262 1263 /* When INLINE need to write the arg data */ 1264 if (action->flags & MLX5DR_ACTION_FLAG_SHARED) { 1265 ret = mlx5dr_arg_write_inline_arg_data(ctx, 1266 action->reformat.arg_obj->id, 1267 data, 1268 data_sz); 1269 if (ret) { 1270 DR_LOG(ERR, "Failed to write inline arg for reformat"); 1271 goto free_arg; 1272 } 1273 } 1274 1275 return 0; 1276 1277 free_arg: 1278 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1279 return ret; 1280 } 1281 1282 static int mlx5dr_action_handle_l2_to_tunnel_l2(struct mlx5dr_context *ctx, 1283 size_t data_sz, 1284 void *data, 1285 uint32_t bulk_size, 1286 struct mlx5dr_action *action) 1287 { 1288 int ret; 1289 1290 ret = mlx5dr_action_handle_reformat_args(ctx, data_sz, data, bulk_size, 1291 action); 1292 if (ret) { 1293 DR_LOG(ERR, "Failed to create args for reformat"); 1294 return ret; 1295 } 1296 1297 ret = mlx5dr_action_create_stcs(action, NULL); 1298 if (ret) { 1299 DR_LOG(ERR, "Failed to create stc for reformat"); 1300 goto free_arg; 1301 } 1302 1303 return 0; 1304 1305 free_arg: 1306 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1307 return ret; 1308 } 1309 1310 static int mlx5dr_action_get_shared_stc_offset(struct mlx5dr_context_common_res *common_res, 1311 enum mlx5dr_context_shared_stc_type stc_type) 1312 { 1313 return common_res->shared_stc[stc_type]->remove_header.offset; 1314 } 1315 1316 static int mlx5dr_action_handle_l2_to_tunnel_l3(struct mlx5dr_context *ctx, 1317 size_t data_sz, 1318 void *data, 1319 uint32_t bulk_size, 1320 struct mlx5dr_action *action) 1321 { 1322 int ret; 1323 1324 ret = mlx5dr_action_handle_reformat_args(ctx, data_sz, data, bulk_size, 1325 action); 1326 if (ret) { 1327 DR_LOG(ERR, "Failed to create args for reformat"); 1328 return ret; 1329 } 1330 1331 /* The action is remove-l2-header + insert-l3-header */ 1332 ret = mlx5dr_action_get_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_DECAP); 1333 if (ret) { 1334 DR_LOG(ERR, "Failed to create remove stc for reformat"); 1335 goto free_arg; 1336 } 1337 1338 ret = mlx5dr_action_create_stcs(action, NULL); 1339 if (ret) { 1340 DR_LOG(ERR, "Failed to create insert stc for reformat"); 1341 goto down_shared; 1342 } 1343 1344 return 0; 1345 1346 down_shared: 1347 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_DECAP); 1348 free_arg: 1349 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1350 return ret; 1351 } 1352 1353 static void mlx5dr_action_prepare_decap_l3_actions(size_t data_sz, 1354 uint8_t *mh_data, 1355 int *num_of_actions) 1356 { 1357 int actions; 1358 uint32_t i; 1359 1360 /* Remove L2L3 outer headers */ 1361 MLX5_SET(stc_ste_param_remove, mh_data, action_type, 1362 MLX5_MODIFICATION_TYPE_REMOVE); 1363 MLX5_SET(stc_ste_param_remove, mh_data, decap, 0x1); 1364 MLX5_SET(stc_ste_param_remove, mh_data, remove_start_anchor, 1365 MLX5_HEADER_ANCHOR_PACKET_START); 1366 MLX5_SET(stc_ste_param_remove, mh_data, remove_end_anchor, 1367 MLX5_HEADER_ANCHOR_INNER_IPV6_IPV4); 1368 mh_data += MLX5DR_ACTION_DOUBLE_SIZE; /* Assume every action is 2 dw */ 1369 actions = 1; 1370 1371 /* Add the new header using inline action 4Byte at a time, the header 1372 * is added in reversed order to the beginning of the packet to avoid 1373 * incorrect parsing by the HW. Since header is 14B or 18B an extra 1374 * two bytes are padded and later removed. 1375 */ 1376 for (i = 0; i < data_sz / MLX5DR_ACTION_INLINE_DATA_SIZE + 1; i++) { 1377 MLX5_SET(stc_ste_param_insert, mh_data, action_type, 1378 MLX5_MODIFICATION_TYPE_INSERT); 1379 MLX5_SET(stc_ste_param_insert, mh_data, inline_data, 0x1); 1380 MLX5_SET(stc_ste_param_insert, mh_data, insert_anchor, 1381 MLX5_HEADER_ANCHOR_PACKET_START); 1382 MLX5_SET(stc_ste_param_insert, mh_data, insert_size, 2); 1383 mh_data += MLX5DR_ACTION_DOUBLE_SIZE; 1384 actions++; 1385 } 1386 1387 /* Remove first 2 extra bytes */ 1388 MLX5_SET(stc_ste_param_remove_words, mh_data, action_type, 1389 MLX5_MODIFICATION_TYPE_REMOVE_WORDS); 1390 MLX5_SET(stc_ste_param_remove_words, mh_data, remove_start_anchor, 1391 MLX5_HEADER_ANCHOR_PACKET_START); 1392 /* The hardware expects here size in words (2 bytes) */ 1393 MLX5_SET(stc_ste_param_remove_words, mh_data, remove_size, 1); 1394 actions++; 1395 1396 *num_of_actions = actions; 1397 } 1398 1399 static int 1400 mlx5dr_action_handle_tunnel_l3_to_l2(struct mlx5dr_context *ctx, 1401 size_t data_sz, 1402 void *data, 1403 uint32_t bulk_size, 1404 struct mlx5dr_action *action) 1405 { 1406 uint8_t mh_data[MLX5DR_ACTION_REFORMAT_DATA_SIZE] = {0}; 1407 int num_of_actions; 1408 int mh_data_size; 1409 int ret; 1410 1411 if (data_sz != MLX5DR_ACTION_HDR_LEN_L2 && 1412 data_sz != MLX5DR_ACTION_HDR_LEN_L2_W_VLAN) { 1413 DR_LOG(ERR, "Data size is not supported for decap-l3\n"); 1414 rte_errno = EINVAL; 1415 return rte_errno; 1416 } 1417 1418 mlx5dr_action_prepare_decap_l3_actions(data_sz, mh_data, &num_of_actions); 1419 1420 mh_data_size = num_of_actions * MLX5DR_MODIFY_ACTION_SIZE; 1421 1422 ret = mlx5dr_pat_arg_create_modify_header(ctx, action, mh_data_size, 1423 (__be64 *)mh_data, bulk_size); 1424 if (ret) { 1425 DR_LOG(ERR, "Failed allocating modify-header for decap-l3\n"); 1426 return ret; 1427 } 1428 1429 ret = mlx5dr_action_create_stcs(action, NULL); 1430 if (ret) 1431 goto free_mh_obj; 1432 1433 if (action->flags & MLX5DR_ACTION_FLAG_SHARED) { 1434 mlx5dr_action_prepare_decap_l3_data(data, mh_data, num_of_actions); 1435 ret = mlx5dr_arg_write_inline_arg_data(ctx, 1436 action->modify_header.arg_obj->id, 1437 (uint8_t *)mh_data, 1438 num_of_actions * 1439 MLX5DR_MODIFY_ACTION_SIZE); 1440 if (ret) { 1441 DR_LOG(ERR, "Failed writing INLINE arg decap_l3"); 1442 goto clean_stc; 1443 } 1444 } 1445 1446 return 0; 1447 1448 clean_stc: 1449 mlx5dr_action_destroy_stcs(action); 1450 free_mh_obj: 1451 mlx5dr_pat_arg_destroy_modify_header(ctx, action); 1452 return ret; 1453 } 1454 1455 static int 1456 mlx5dr_action_create_reformat_hws(struct mlx5dr_context *ctx, 1457 size_t data_sz, 1458 void *data, 1459 uint32_t bulk_size, 1460 struct mlx5dr_action *action) 1461 { 1462 int ret; 1463 1464 switch (action->type) { 1465 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1466 ret = mlx5dr_action_create_stcs(action, NULL); 1467 break; 1468 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1469 ret = mlx5dr_action_handle_l2_to_tunnel_l2(ctx, data_sz, data, bulk_size, action); 1470 break; 1471 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1472 ret = mlx5dr_action_handle_l2_to_tunnel_l3(ctx, data_sz, data, bulk_size, action); 1473 break; 1474 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1475 ret = mlx5dr_action_handle_tunnel_l3_to_l2(ctx, data_sz, data, bulk_size, action); 1476 break; 1477 1478 default: 1479 assert(false); 1480 rte_errno = ENOTSUP; 1481 return rte_errno; 1482 } 1483 1484 return ret; 1485 } 1486 1487 struct mlx5dr_action * 1488 mlx5dr_action_create_reformat(struct mlx5dr_context *ctx, 1489 enum mlx5dr_action_reformat_type reformat_type, 1490 size_t data_sz, 1491 void *inline_data, 1492 uint32_t log_bulk_size, 1493 uint32_t flags) 1494 { 1495 enum mlx5dr_action_type action_type; 1496 struct mlx5dr_action *action; 1497 int ret; 1498 1499 ret = mlx5dr_action_conv_reformat_type_to_action(reformat_type, &action_type); 1500 if (ret) 1501 return NULL; 1502 1503 action = mlx5dr_action_create_generic(ctx, flags, action_type); 1504 if (!action) 1505 return NULL; 1506 1507 if (mlx5dr_action_is_root_flags(flags)) { 1508 if (log_bulk_size) { 1509 DR_LOG(ERR, "Bulk reformat not supported over root"); 1510 rte_errno = ENOTSUP; 1511 goto free_action; 1512 } 1513 1514 ret = mlx5dr_action_create_reformat_root(action, data_sz, inline_data); 1515 if (ret) 1516 goto free_action; 1517 1518 return action; 1519 } 1520 1521 if (!mlx5dr_action_is_hws_flags(flags) || 1522 ((flags & MLX5DR_ACTION_FLAG_SHARED) && log_bulk_size)) { 1523 DR_LOG(ERR, "Reformat flags don't fit HWS (flags: %x0x)\n", 1524 flags); 1525 rte_errno = EINVAL; 1526 goto free_action; 1527 } 1528 1529 ret = mlx5dr_action_create_reformat_hws(ctx, data_sz, inline_data, log_bulk_size, action); 1530 if (ret) { 1531 DR_LOG(ERR, "Failed to create reformat.\n"); 1532 rte_errno = EINVAL; 1533 goto free_action; 1534 } 1535 1536 return action; 1537 1538 free_action: 1539 simple_free(action); 1540 return NULL; 1541 } 1542 1543 static int 1544 mlx5dr_action_create_modify_header_root(struct mlx5dr_action *action, 1545 size_t actions_sz, 1546 __be64 *actions) 1547 { 1548 enum mlx5dv_flow_table_type ft_type = 0; 1549 struct ibv_context *local_ibv_ctx; 1550 int ret; 1551 1552 ret = mlx5dr_action_conv_flags_to_ft_type(action->flags, &ft_type); 1553 if (ret) 1554 return rte_errno; 1555 1556 local_ibv_ctx = mlx5dr_context_get_local_ibv(action->ctx); 1557 1558 action->flow_action = 1559 mlx5_glue->dv_create_flow_action_modify_header_root(local_ibv_ctx, 1560 actions_sz, 1561 (uint64_t *)actions, 1562 ft_type); 1563 if (!action->flow_action) { 1564 rte_errno = errno; 1565 return rte_errno; 1566 } 1567 1568 return 0; 1569 } 1570 1571 struct mlx5dr_action * 1572 mlx5dr_action_create_modify_header(struct mlx5dr_context *ctx, 1573 size_t pattern_sz, 1574 __be64 pattern[], 1575 uint32_t log_bulk_size, 1576 uint32_t flags) 1577 { 1578 struct mlx5dr_action *action; 1579 int ret; 1580 1581 action = mlx5dr_action_create_generic(ctx, flags, MLX5DR_ACTION_TYP_MODIFY_HDR); 1582 if (!action) 1583 return NULL; 1584 1585 if (mlx5dr_action_is_root_flags(flags)) { 1586 if (log_bulk_size) { 1587 DR_LOG(ERR, "Bulk modify-header not supported over root"); 1588 rte_errno = ENOTSUP; 1589 goto free_action; 1590 } 1591 ret = mlx5dr_action_create_modify_header_root(action, pattern_sz, pattern); 1592 if (ret) 1593 goto free_action; 1594 1595 return action; 1596 } 1597 1598 if (!mlx5dr_action_is_hws_flags(flags) || 1599 ((flags & MLX5DR_ACTION_FLAG_SHARED) && log_bulk_size)) { 1600 DR_LOG(ERR, "Flags don't fit hws (flags: %x0x, log_bulk_size: %d)\n", 1601 flags, log_bulk_size); 1602 rte_errno = EINVAL; 1603 goto free_action; 1604 } 1605 1606 if (pattern_sz / MLX5DR_MODIFY_ACTION_SIZE == 1) { 1607 /* Optimize single modiy action to be used inline */ 1608 action->modify_header.single_action = pattern[0]; 1609 action->modify_header.num_of_actions = 1; 1610 action->modify_header.single_action_type = 1611 MLX5_GET(set_action_in, pattern, action_type); 1612 } else { 1613 /* Use multi action pattern and argument */ 1614 ret = mlx5dr_pat_arg_create_modify_header(ctx, action, pattern_sz, 1615 pattern, log_bulk_size); 1616 if (ret) { 1617 DR_LOG(ERR, "Failed allocating modify-header\n"); 1618 goto free_action; 1619 } 1620 } 1621 1622 ret = mlx5dr_action_create_stcs(action, NULL); 1623 if (ret) 1624 goto free_mh_obj; 1625 1626 return action; 1627 1628 free_mh_obj: 1629 if (action->modify_header.num_of_actions > 1) 1630 mlx5dr_pat_arg_destroy_modify_header(ctx, action); 1631 free_action: 1632 simple_free(action); 1633 return NULL; 1634 } 1635 1636 static void mlx5dr_action_destroy_hws(struct mlx5dr_action *action) 1637 { 1638 switch (action->type) { 1639 case MLX5DR_ACTION_TYP_TIR: 1640 mlx5dr_action_destroy_stcs(action); 1641 if (mlx5dr_context_shared_gvmi_used(action->ctx)) 1642 mlx5dr_cmd_destroy_obj(action->alias.devx_obj); 1643 break; 1644 case MLX5DR_ACTION_TYP_MISS: 1645 case MLX5DR_ACTION_TYP_TAG: 1646 case MLX5DR_ACTION_TYP_DROP: 1647 case MLX5DR_ACTION_TYP_CTR: 1648 case MLX5DR_ACTION_TYP_FT: 1649 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1650 case MLX5DR_ACTION_TYP_ASO_METER: 1651 case MLX5DR_ACTION_TYP_ASO_CT: 1652 case MLX5DR_ACTION_TYP_PUSH_VLAN: 1653 mlx5dr_action_destroy_stcs(action); 1654 break; 1655 case MLX5DR_ACTION_TYP_POP_VLAN: 1656 mlx5dr_action_destroy_stcs(action); 1657 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_POP); 1658 break; 1659 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1660 case MLX5DR_ACTION_TYP_MODIFY_HDR: 1661 mlx5dr_action_destroy_stcs(action); 1662 if (action->modify_header.num_of_actions > 1) 1663 mlx5dr_pat_arg_destroy_modify_header(action->ctx, action); 1664 break; 1665 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1666 mlx5dr_action_destroy_stcs(action); 1667 mlx5dr_action_put_shared_stc(action, MLX5DR_CONTEXT_SHARED_STC_DECAP); 1668 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1669 break; 1670 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1671 mlx5dr_action_destroy_stcs(action); 1672 mlx5dr_cmd_destroy_obj(action->reformat.arg_obj); 1673 break; 1674 } 1675 } 1676 1677 static void mlx5dr_action_destroy_root(struct mlx5dr_action *action) 1678 { 1679 switch (action->type) { 1680 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 1681 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 1682 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 1683 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 1684 case MLX5DR_ACTION_TYP_MODIFY_HDR: 1685 ibv_destroy_flow_action(action->flow_action); 1686 break; 1687 } 1688 } 1689 1690 int mlx5dr_action_destroy(struct mlx5dr_action *action) 1691 { 1692 if (mlx5dr_action_is_root_flags(action->flags)) 1693 mlx5dr_action_destroy_root(action); 1694 else 1695 mlx5dr_action_destroy_hws(action); 1696 1697 simple_free(action); 1698 return 0; 1699 } 1700 1701 /* Called under pthread_spin_lock(&ctx->ctrl_lock) */ 1702 int mlx5dr_action_get_default_stc(struct mlx5dr_context *ctx, 1703 uint8_t tbl_type) 1704 { 1705 struct mlx5dr_cmd_stc_modify_attr stc_attr = {0}; 1706 struct mlx5dr_action_default_stc *default_stc; 1707 int ret; 1708 1709 if (ctx->common_res[tbl_type].default_stc) { 1710 ctx->common_res[tbl_type].default_stc->refcount++; 1711 return 0; 1712 } 1713 1714 default_stc = simple_calloc(1, sizeof(*default_stc)); 1715 if (!default_stc) { 1716 DR_LOG(ERR, "Failed to allocate memory for default STCs"); 1717 rte_errno = ENOMEM; 1718 return rte_errno; 1719 } 1720 1721 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_NOP; 1722 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW0; 1723 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1724 &default_stc->nop_ctr); 1725 if (ret) { 1726 DR_LOG(ERR, "Failed to allocate default counter STC"); 1727 goto free_default_stc; 1728 } 1729 1730 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW5; 1731 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1732 &default_stc->nop_dw5); 1733 if (ret) { 1734 DR_LOG(ERR, "Failed to allocate default NOP DW5 STC"); 1735 goto free_nop_ctr; 1736 } 1737 1738 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW6; 1739 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1740 &default_stc->nop_dw6); 1741 if (ret) { 1742 DR_LOG(ERR, "Failed to allocate default NOP DW6 STC"); 1743 goto free_nop_dw5; 1744 } 1745 1746 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_DW7; 1747 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1748 &default_stc->nop_dw7); 1749 if (ret) { 1750 DR_LOG(ERR, "Failed to allocate default NOP DW7 STC"); 1751 goto free_nop_dw6; 1752 } 1753 1754 stc_attr.action_type = MLX5_IFC_STC_ACTION_TYPE_ALLOW; 1755 stc_attr.action_offset = MLX5DR_ACTION_OFFSET_HIT; 1756 ret = mlx5dr_action_alloc_single_stc(ctx, &stc_attr, tbl_type, 1757 &default_stc->default_hit); 1758 if (ret) { 1759 DR_LOG(ERR, "Failed to allocate default allow STC"); 1760 goto free_nop_dw7; 1761 } 1762 1763 ctx->common_res[tbl_type].default_stc = default_stc; 1764 ctx->common_res[tbl_type].default_stc->refcount++; 1765 1766 return 0; 1767 1768 free_nop_dw7: 1769 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw7); 1770 free_nop_dw6: 1771 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw6); 1772 free_nop_dw5: 1773 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw5); 1774 free_nop_ctr: 1775 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_ctr); 1776 free_default_stc: 1777 simple_free(default_stc); 1778 return rte_errno; 1779 } 1780 1781 void mlx5dr_action_put_default_stc(struct mlx5dr_context *ctx, 1782 uint8_t tbl_type) 1783 { 1784 struct mlx5dr_action_default_stc *default_stc; 1785 1786 default_stc = ctx->common_res[tbl_type].default_stc; 1787 1788 default_stc = ctx->common_res[tbl_type].default_stc; 1789 if (--default_stc->refcount) 1790 return; 1791 1792 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->default_hit); 1793 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw7); 1794 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw6); 1795 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw5); 1796 mlx5dr_action_free_single_stc(ctx, tbl_type, &default_stc->nop_ctr); 1797 simple_free(default_stc); 1798 ctx->common_res[tbl_type].default_stc = NULL; 1799 } 1800 1801 static void mlx5dr_action_modify_write(struct mlx5dr_send_engine *queue, 1802 uint32_t arg_idx, 1803 uint8_t *arg_data, 1804 uint16_t num_of_actions) 1805 { 1806 mlx5dr_arg_write(queue, NULL, arg_idx, arg_data, 1807 num_of_actions * MLX5DR_MODIFY_ACTION_SIZE); 1808 } 1809 1810 void 1811 mlx5dr_action_prepare_decap_l3_data(uint8_t *src, uint8_t *dst, 1812 uint16_t num_of_actions) 1813 { 1814 uint8_t *e_src; 1815 int i; 1816 1817 /* num_of_actions = remove l3l2 + 4/5 inserts + remove extra 2 bytes 1818 * copy from end of src to the start of dst. 1819 * move to the end, 2 is the leftover from 14B or 18B 1820 */ 1821 if (num_of_actions == DECAP_L3_NUM_ACTIONS_W_NO_VLAN) 1822 e_src = src + MLX5DR_ACTION_HDR_LEN_L2; 1823 else 1824 e_src = src + MLX5DR_ACTION_HDR_LEN_L2_W_VLAN; 1825 1826 /* Move dst over the first remove action + zero data */ 1827 dst += MLX5DR_ACTION_DOUBLE_SIZE; 1828 /* Move dst over the first insert ctrl action */ 1829 dst += MLX5DR_ACTION_DOUBLE_SIZE / 2; 1830 /* Actions: 1831 * no vlan: r_h-insert_4b-insert_4b-insert_4b-insert_4b-remove_2b. 1832 * with vlan: r_h-insert_4b-insert_4b-insert_4b-insert_4b-insert_4b-remove_2b. 1833 * the loop is without the last insertion. 1834 */ 1835 for (i = 0; i < num_of_actions - 3; i++) { 1836 e_src -= MLX5DR_ACTION_INLINE_DATA_SIZE; 1837 memcpy(dst, e_src, MLX5DR_ACTION_INLINE_DATA_SIZE); /* data */ 1838 dst += MLX5DR_ACTION_DOUBLE_SIZE; 1839 } 1840 /* Copy the last 2 bytes after a gap of 2 bytes which will be removed */ 1841 e_src -= MLX5DR_ACTION_INLINE_DATA_SIZE / 2; 1842 dst += MLX5DR_ACTION_INLINE_DATA_SIZE / 2; 1843 memcpy(dst, e_src, 2); 1844 } 1845 1846 static struct mlx5dr_actions_wqe_setter * 1847 mlx5dr_action_setter_find_first(struct mlx5dr_actions_wqe_setter *setter, 1848 uint8_t req_flags) 1849 { 1850 /* Use a new setter if requested flags are taken */ 1851 while (setter->flags & req_flags) 1852 setter++; 1853 1854 /* Use current setter in required flags are not used */ 1855 return setter; 1856 } 1857 1858 static void 1859 mlx5dr_action_apply_stc(struct mlx5dr_actions_apply_data *apply, 1860 enum mlx5dr_action_stc_idx stc_idx, 1861 uint8_t action_idx) 1862 { 1863 struct mlx5dr_action *action = apply->rule_action[action_idx].action; 1864 1865 apply->wqe_ctrl->stc_ix[stc_idx] = 1866 htobe32(action->stc[apply->tbl_type].offset); 1867 } 1868 1869 static void 1870 mlx5dr_action_setter_push_vlan(struct mlx5dr_actions_apply_data *apply, 1871 struct mlx5dr_actions_wqe_setter *setter) 1872 { 1873 struct mlx5dr_rule_action *rule_action; 1874 1875 rule_action = &apply->rule_action[setter->idx_double]; 1876 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1877 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = rule_action->push_vlan.vlan_hdr; 1878 1879 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1880 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1881 } 1882 1883 static void 1884 mlx5dr_action_setter_modify_header(struct mlx5dr_actions_apply_data *apply, 1885 struct mlx5dr_actions_wqe_setter *setter) 1886 { 1887 struct mlx5dr_rule_action *rule_action; 1888 struct mlx5dr_action *action; 1889 uint32_t arg_sz, arg_idx; 1890 uint8_t *single_action; 1891 1892 rule_action = &apply->rule_action[setter->idx_double]; 1893 action = rule_action->action; 1894 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1895 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1896 1897 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1898 1899 if (action->modify_header.num_of_actions == 1) { 1900 if (action->modify_header.single_action_type == 1901 MLX5_MODIFICATION_TYPE_COPY) { 1902 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = 0; 1903 return; 1904 } 1905 1906 if (action->flags & MLX5DR_ACTION_FLAG_SHARED) 1907 single_action = (uint8_t *)&action->modify_header.single_action; 1908 else 1909 single_action = rule_action->modify_header.data; 1910 1911 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = 1912 *(__be32 *)MLX5_ADDR_OF(set_action_in, single_action, data); 1913 } else { 1914 /* Argument offset multiple with number of args per these actions */ 1915 arg_sz = mlx5dr_arg_get_arg_size(action->modify_header.num_of_actions); 1916 arg_idx = rule_action->modify_header.offset * arg_sz; 1917 1918 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(arg_idx); 1919 1920 if (!(action->flags & MLX5DR_ACTION_FLAG_SHARED)) { 1921 apply->require_dep = 1; 1922 mlx5dr_action_modify_write(apply->queue, 1923 action->modify_header.arg_obj->id + arg_idx, 1924 rule_action->modify_header.data, 1925 action->modify_header.num_of_actions); 1926 } 1927 } 1928 } 1929 1930 static void 1931 mlx5dr_action_setter_insert_ptr(struct mlx5dr_actions_apply_data *apply, 1932 struct mlx5dr_actions_wqe_setter *setter) 1933 { 1934 struct mlx5dr_rule_action *rule_action; 1935 uint32_t arg_idx, arg_sz; 1936 1937 rule_action = &apply->rule_action[setter->idx_double]; 1938 1939 /* Argument offset multiple on args required for header size */ 1940 arg_sz = mlx5dr_arg_data_size_to_arg_size(rule_action->action->reformat.header_size); 1941 arg_idx = rule_action->reformat.offset * arg_sz; 1942 1943 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1944 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(arg_idx); 1945 1946 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1947 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1948 1949 if (!(rule_action->action->flags & MLX5DR_ACTION_FLAG_SHARED)) { 1950 apply->require_dep = 1; 1951 mlx5dr_arg_write(apply->queue, NULL, 1952 rule_action->action->reformat.arg_obj->id + arg_idx, 1953 rule_action->reformat.data, 1954 rule_action->action->reformat.header_size); 1955 } 1956 } 1957 1958 static void 1959 mlx5dr_action_setter_tnl_l3_to_l2(struct mlx5dr_actions_apply_data *apply, 1960 struct mlx5dr_actions_wqe_setter *setter) 1961 { 1962 struct mlx5dr_rule_action *rule_action; 1963 struct mlx5dr_action *action; 1964 uint32_t arg_sz, arg_idx; 1965 1966 rule_action = &apply->rule_action[setter->idx_double]; 1967 action = rule_action->action; 1968 1969 /* Argument offset multiple on args required for num of actions */ 1970 arg_sz = mlx5dr_arg_get_arg_size(action->modify_header.num_of_actions); 1971 arg_idx = rule_action->reformat.offset * arg_sz; 1972 1973 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = 0; 1974 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(arg_idx); 1975 1976 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 1977 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 1978 1979 if (!(action->flags & MLX5DR_ACTION_FLAG_SHARED)) { 1980 apply->require_dep = 1; 1981 mlx5dr_arg_decapl3_write(apply->queue, 1982 action->modify_header.arg_obj->id + arg_idx, 1983 rule_action->reformat.data, 1984 action->modify_header.num_of_actions); 1985 } 1986 } 1987 1988 static void 1989 mlx5dr_action_setter_aso(struct mlx5dr_actions_apply_data *apply, 1990 struct mlx5dr_actions_wqe_setter *setter) 1991 { 1992 struct mlx5dr_rule_action *rule_action; 1993 uint32_t exe_aso_ctrl; 1994 uint32_t offset; 1995 1996 rule_action = &apply->rule_action[setter->idx_double]; 1997 1998 switch (rule_action->action->type) { 1999 case MLX5DR_ACTION_TYP_ASO_METER: 2000 /* exe_aso_ctrl format: 2001 * [STC only and reserved bits 29b][init_color 2b][meter_id 1b] 2002 */ 2003 offset = rule_action->aso_meter.offset / MLX5_ASO_METER_NUM_PER_OBJ; 2004 exe_aso_ctrl = rule_action->aso_meter.offset % MLX5_ASO_METER_NUM_PER_OBJ; 2005 exe_aso_ctrl |= rule_action->aso_meter.init_color << 2006 MLX5DR_ACTION_METER_INIT_COLOR_OFFSET; 2007 break; 2008 case MLX5DR_ACTION_TYP_ASO_CT: 2009 /* exe_aso_ctrl CT format: 2010 * [STC only and reserved bits 31b][direction 1b] 2011 */ 2012 offset = rule_action->aso_ct.offset / MLX5_ASO_CT_NUM_PER_OBJ; 2013 exe_aso_ctrl = rule_action->aso_ct.direction; 2014 break; 2015 default: 2016 DR_LOG(ERR, "Unsupported ASO action type: %d", rule_action->action->type); 2017 rte_errno = ENOTSUP; 2018 return; 2019 } 2020 2021 /* aso_object_offset format: [24B] */ 2022 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW6] = htobe32(offset); 2023 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW7] = htobe32(exe_aso_ctrl); 2024 2025 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW6, setter->idx_double); 2026 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW7] = 0; 2027 } 2028 2029 static void 2030 mlx5dr_action_setter_tag(struct mlx5dr_actions_apply_data *apply, 2031 struct mlx5dr_actions_wqe_setter *setter) 2032 { 2033 struct mlx5dr_rule_action *rule_action; 2034 2035 rule_action = &apply->rule_action[setter->idx_single]; 2036 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = htobe32(rule_action->tag.value); 2037 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW5, setter->idx_single); 2038 } 2039 2040 static void 2041 mlx5dr_action_setter_ctrl_ctr(struct mlx5dr_actions_apply_data *apply, 2042 struct mlx5dr_actions_wqe_setter *setter) 2043 { 2044 struct mlx5dr_rule_action *rule_action; 2045 2046 rule_action = &apply->rule_action[setter->idx_ctr]; 2047 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW0] = htobe32(rule_action->counter.offset); 2048 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_CTRL, setter->idx_ctr); 2049 } 2050 2051 static void 2052 mlx5dr_action_setter_single(struct mlx5dr_actions_apply_data *apply, 2053 struct mlx5dr_actions_wqe_setter *setter) 2054 { 2055 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = 0; 2056 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_DW5, setter->idx_single); 2057 } 2058 2059 static void 2060 mlx5dr_action_setter_single_double_pop(struct mlx5dr_actions_apply_data *apply, 2061 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2062 { 2063 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = 0; 2064 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW5] = 2065 htobe32(mlx5dr_action_get_shared_stc_offset(apply->common_res, 2066 MLX5DR_CONTEXT_SHARED_STC_POP)); 2067 } 2068 2069 static void 2070 mlx5dr_action_setter_hit(struct mlx5dr_actions_apply_data *apply, 2071 struct mlx5dr_actions_wqe_setter *setter) 2072 { 2073 apply->wqe_data[MLX5DR_ACTION_OFFSET_HIT_LSB] = 0; 2074 mlx5dr_action_apply_stc(apply, MLX5DR_ACTION_STC_IDX_HIT, setter->idx_hit); 2075 } 2076 2077 static void 2078 mlx5dr_action_setter_default_hit(struct mlx5dr_actions_apply_data *apply, 2079 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2080 { 2081 apply->wqe_data[MLX5DR_ACTION_OFFSET_HIT_LSB] = 0; 2082 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_HIT] = 2083 htobe32(apply->common_res->default_stc->default_hit.offset); 2084 } 2085 2086 static void 2087 mlx5dr_action_setter_hit_next_action(struct mlx5dr_actions_apply_data *apply, 2088 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2089 { 2090 apply->wqe_data[MLX5DR_ACTION_OFFSET_HIT_LSB] = htobe32(apply->next_direct_idx << 6); 2091 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_HIT] = htobe32(apply->jump_to_action_stc); 2092 } 2093 2094 static void 2095 mlx5dr_action_setter_common_decap(struct mlx5dr_actions_apply_data *apply, 2096 __rte_unused struct mlx5dr_actions_wqe_setter *setter) 2097 { 2098 apply->wqe_data[MLX5DR_ACTION_OFFSET_DW5] = 0; 2099 apply->wqe_ctrl->stc_ix[MLX5DR_ACTION_STC_IDX_DW5] = 2100 htobe32(mlx5dr_action_get_shared_stc_offset(apply->common_res, 2101 MLX5DR_CONTEXT_SHARED_STC_DECAP)); 2102 } 2103 2104 int mlx5dr_action_template_process(struct mlx5dr_action_template *at) 2105 { 2106 struct mlx5dr_actions_wqe_setter *start_setter = at->setters + 1; 2107 enum mlx5dr_action_type *action_type = at->action_type_arr; 2108 struct mlx5dr_actions_wqe_setter *setter = at->setters; 2109 struct mlx5dr_actions_wqe_setter *pop_setter = NULL; 2110 struct mlx5dr_actions_wqe_setter *last_setter; 2111 int i; 2112 2113 /* Note: Given action combination must be valid */ 2114 2115 /* Check if action were already processed */ 2116 if (at->num_of_action_stes) 2117 return 0; 2118 2119 for (i = 0; i < MLX5DR_ACTION_MAX_STE; i++) 2120 setter[i].set_hit = &mlx5dr_action_setter_hit_next_action; 2121 2122 /* The same action template setters can be used with jumbo or match 2123 * STE, to support both cases we reseve the first setter for cases 2124 * with jumbo STE to allow jump to the first action STE. 2125 * This extra setter can be reduced in some cases on rule creation. 2126 */ 2127 setter = start_setter; 2128 last_setter = start_setter; 2129 2130 for (i = 0; i < at->num_actions; i++) { 2131 switch (action_type[i]) { 2132 case MLX5DR_ACTION_TYP_DROP: 2133 case MLX5DR_ACTION_TYP_TIR: 2134 case MLX5DR_ACTION_TYP_FT: 2135 case MLX5DR_ACTION_TYP_VPORT: 2136 case MLX5DR_ACTION_TYP_MISS: 2137 /* Hit action */ 2138 last_setter->flags |= ASF_HIT; 2139 last_setter->set_hit = &mlx5dr_action_setter_hit; 2140 last_setter->idx_hit = i; 2141 break; 2142 2143 case MLX5DR_ACTION_TYP_POP_VLAN: 2144 /* Single remove header to header */ 2145 if (pop_setter) { 2146 /* We have 2 pops, use the shared */ 2147 pop_setter->set_single = &mlx5dr_action_setter_single_double_pop; 2148 break; 2149 } 2150 setter = mlx5dr_action_setter_find_first(last_setter, ASF_SINGLE1 | ASF_MODIFY); 2151 setter->flags |= ASF_SINGLE1 | ASF_REPARSE | ASF_REMOVE; 2152 setter->set_single = &mlx5dr_action_setter_single; 2153 setter->idx_single = i; 2154 pop_setter = setter; 2155 break; 2156 2157 case MLX5DR_ACTION_TYP_PUSH_VLAN: 2158 /* Double insert inline */ 2159 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE | ASF_REMOVE); 2160 setter->flags |= ASF_DOUBLE | ASF_REPARSE | ASF_MODIFY; 2161 setter->set_double = &mlx5dr_action_setter_push_vlan; 2162 setter->idx_double = i; 2163 break; 2164 2165 case MLX5DR_ACTION_TYP_MODIFY_HDR: 2166 /* Double modify header list */ 2167 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE | ASF_REMOVE); 2168 setter->flags |= ASF_DOUBLE | ASF_MODIFY | ASF_REPARSE; 2169 setter->set_double = &mlx5dr_action_setter_modify_header; 2170 setter->idx_double = i; 2171 break; 2172 2173 case MLX5DR_ACTION_TYP_ASO_METER: 2174 case MLX5DR_ACTION_TYP_ASO_CT: 2175 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE); 2176 setter->flags |= ASF_DOUBLE; 2177 setter->set_double = &mlx5dr_action_setter_aso; 2178 setter->idx_double = i; 2179 break; 2180 2181 case MLX5DR_ACTION_TYP_TNL_L2_TO_L2: 2182 /* Single remove header to header */ 2183 setter = mlx5dr_action_setter_find_first(last_setter, ASF_SINGLE1 | ASF_MODIFY); 2184 setter->flags |= ASF_SINGLE1 | ASF_REMOVE | ASF_REPARSE; 2185 setter->set_single = &mlx5dr_action_setter_single; 2186 setter->idx_single = i; 2187 break; 2188 2189 case MLX5DR_ACTION_TYP_L2_TO_TNL_L2: 2190 /* Double insert header with pointer */ 2191 setter = mlx5dr_action_setter_find_first(last_setter, ASF_DOUBLE); 2192 setter->flags |= ASF_DOUBLE | ASF_REPARSE; 2193 setter->set_double = &mlx5dr_action_setter_insert_ptr; 2194 setter->idx_double = i; 2195 break; 2196 2197 case MLX5DR_ACTION_TYP_L2_TO_TNL_L3: 2198 /* Single remove + Double insert header with pointer */ 2199 setter = mlx5dr_action_setter_find_first(last_setter, ASF_SINGLE1 | ASF_DOUBLE); 2200 setter->flags |= ASF_SINGLE1 | ASF_DOUBLE | ASF_REPARSE | ASF_REMOVE; 2201 setter->set_double = &mlx5dr_action_setter_insert_ptr; 2202 setter->idx_double = i; 2203 setter->set_single = &mlx5dr_action_setter_common_decap; 2204 setter->idx_single = i; 2205 break; 2206 2207 case MLX5DR_ACTION_TYP_TNL_L3_TO_L2: 2208 /* Double modify header list with remove and push inline */ 2209 setter = mlx5dr_action_setter_find_first(last_setter, 2210 ASF_DOUBLE | ASF_REMOVE); 2211 setter->flags |= ASF_DOUBLE | ASF_MODIFY | ASF_REPARSE; 2212 setter->set_double = &mlx5dr_action_setter_tnl_l3_to_l2; 2213 setter->idx_double = i; 2214 break; 2215 2216 case MLX5DR_ACTION_TYP_TAG: 2217 /* Single TAG action, search for any room from the start */ 2218 setter = mlx5dr_action_setter_find_first(start_setter, ASF_SINGLE1); 2219 setter->flags |= ASF_SINGLE1; 2220 setter->set_single = &mlx5dr_action_setter_tag; 2221 setter->idx_single = i; 2222 break; 2223 2224 case MLX5DR_ACTION_TYP_CTR: 2225 /* Control counter action 2226 * TODO: Current counter executed first. Support is needed 2227 * for single ation counter action which is done last. 2228 * Example: Decap + CTR 2229 */ 2230 setter = mlx5dr_action_setter_find_first(start_setter, ASF_CTR); 2231 setter->flags |= ASF_CTR; 2232 setter->set_ctr = &mlx5dr_action_setter_ctrl_ctr; 2233 setter->idx_ctr = i; 2234 break; 2235 2236 default: 2237 DR_LOG(ERR, "Unsupported action type: %d", action_type[i]); 2238 rte_errno = ENOTSUP; 2239 assert(false); 2240 return rte_errno; 2241 } 2242 2243 last_setter = RTE_MAX(setter, last_setter); 2244 } 2245 2246 /* Set default hit on the last STE if no hit action provided */ 2247 if (!(last_setter->flags & ASF_HIT)) 2248 last_setter->set_hit = &mlx5dr_action_setter_default_hit; 2249 2250 at->num_of_action_stes = last_setter - start_setter + 1; 2251 2252 /* Check if action template doesn't require any action DWs */ 2253 at->only_term = (at->num_of_action_stes == 1) && 2254 !(last_setter->flags & ~(ASF_CTR | ASF_HIT)); 2255 2256 return 0; 2257 } 2258 2259 struct mlx5dr_action_template * 2260 mlx5dr_action_template_create(const enum mlx5dr_action_type action_type[]) 2261 { 2262 struct mlx5dr_action_template *at; 2263 uint8_t num_actions = 0; 2264 int i; 2265 2266 at = simple_calloc(1, sizeof(*at)); 2267 if (!at) { 2268 DR_LOG(ERR, "Failed to allocate action template"); 2269 rte_errno = ENOMEM; 2270 return NULL; 2271 } 2272 2273 while (action_type[num_actions++] != MLX5DR_ACTION_TYP_LAST) 2274 ; 2275 2276 at->num_actions = num_actions - 1; 2277 at->action_type_arr = simple_calloc(num_actions, sizeof(*action_type)); 2278 if (!at->action_type_arr) { 2279 DR_LOG(ERR, "Failed to allocate action type array"); 2280 rte_errno = ENOMEM; 2281 goto free_at; 2282 } 2283 2284 for (i = 0; i < num_actions; i++) 2285 at->action_type_arr[i] = action_type[i]; 2286 2287 return at; 2288 2289 free_at: 2290 simple_free(at); 2291 return NULL; 2292 } 2293 2294 int mlx5dr_action_template_destroy(struct mlx5dr_action_template *at) 2295 { 2296 simple_free(at->action_type_arr); 2297 simple_free(at); 2298 return 0; 2299 } 2300