1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2019 Mellanox Technologies. */ 3 4 #include <linux/types.h> 5 #include <linux/crc32.h> 6 #include "dr_ste.h" 7 8 struct dr_hw_ste_format { 9 u8 ctrl[DR_STE_SIZE_CTRL]; 10 u8 tag[DR_STE_SIZE_TAG]; 11 u8 mask[DR_STE_SIZE_MASK]; 12 }; 13 14 static u32 dr_ste_crc32_calc(const void *input_data, size_t length) 15 { 16 u32 crc = crc32(0, input_data, length); 17 18 return (__force u32)htonl(crc); 19 } 20 21 bool mlx5dr_ste_supp_ttl_cs_recalc(struct mlx5dr_cmd_caps *caps) 22 { 23 return caps->sw_format_ver > MLX5_STEERING_FORMAT_CONNECTX_5; 24 } 25 26 u32 mlx5dr_ste_calc_hash_index(u8 *hw_ste_p, struct mlx5dr_ste_htbl *htbl) 27 { 28 struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 29 u8 masked[DR_STE_SIZE_TAG] = {}; 30 u32 crc32, index; 31 u16 bit; 32 int i; 33 34 /* Don't calculate CRC if the result is predicted */ 35 if (htbl->chunk->num_of_entries == 1 || htbl->byte_mask == 0) 36 return 0; 37 38 /* Mask tag using byte mask, bit per byte */ 39 bit = 1 << (DR_STE_SIZE_TAG - 1); 40 for (i = 0; i < DR_STE_SIZE_TAG; i++) { 41 if (htbl->byte_mask & bit) 42 masked[i] = hw_ste->tag[i]; 43 44 bit = bit >> 1; 45 } 46 47 crc32 = dr_ste_crc32_calc(masked, DR_STE_SIZE_TAG); 48 index = crc32 & (htbl->chunk->num_of_entries - 1); 49 50 return index; 51 } 52 53 u16 mlx5dr_ste_conv_bit_to_byte_mask(u8 *bit_mask) 54 { 55 u16 byte_mask = 0; 56 int i; 57 58 for (i = 0; i < DR_STE_SIZE_MASK; i++) { 59 byte_mask = byte_mask << 1; 60 if (bit_mask[i] == 0xff) 61 byte_mask |= 1; 62 } 63 return byte_mask; 64 } 65 66 static u8 *dr_ste_get_tag(u8 *hw_ste_p) 67 { 68 struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 69 70 return hw_ste->tag; 71 } 72 73 void mlx5dr_ste_set_bit_mask(u8 *hw_ste_p, u8 *bit_mask) 74 { 75 struct dr_hw_ste_format *hw_ste = (struct dr_hw_ste_format *)hw_ste_p; 76 77 memcpy(hw_ste->mask, bit_mask, DR_STE_SIZE_MASK); 78 } 79 80 static void dr_ste_set_always_hit(struct dr_hw_ste_format *hw_ste) 81 { 82 memset(&hw_ste->tag, 0, sizeof(hw_ste->tag)); 83 memset(&hw_ste->mask, 0, sizeof(hw_ste->mask)); 84 } 85 86 static void dr_ste_set_always_miss(struct dr_hw_ste_format *hw_ste) 87 { 88 hw_ste->tag[0] = 0xdc; 89 hw_ste->mask[0] = 0; 90 } 91 92 void mlx5dr_ste_set_miss_addr(struct mlx5dr_ste_ctx *ste_ctx, 93 u8 *hw_ste_p, u64 miss_addr) 94 { 95 ste_ctx->set_miss_addr(hw_ste_p, miss_addr); 96 } 97 98 static void dr_ste_always_miss_addr(struct mlx5dr_ste_ctx *ste_ctx, 99 struct mlx5dr_ste *ste, u64 miss_addr) 100 { 101 u8 *hw_ste_p = ste->hw_ste; 102 103 ste_ctx->set_next_lu_type(hw_ste_p, MLX5DR_STE_LU_TYPE_DONT_CARE); 104 ste_ctx->set_miss_addr(hw_ste_p, miss_addr); 105 dr_ste_set_always_miss((struct dr_hw_ste_format *)ste->hw_ste); 106 } 107 108 void mlx5dr_ste_set_hit_addr(struct mlx5dr_ste_ctx *ste_ctx, 109 u8 *hw_ste, u64 icm_addr, u32 ht_size) 110 { 111 ste_ctx->set_hit_addr(hw_ste, icm_addr, ht_size); 112 } 113 114 u64 mlx5dr_ste_get_icm_addr(struct mlx5dr_ste *ste) 115 { 116 u32 index = ste - ste->htbl->ste_arr; 117 118 return ste->htbl->chunk->icm_addr + DR_STE_SIZE * index; 119 } 120 121 u64 mlx5dr_ste_get_mr_addr(struct mlx5dr_ste *ste) 122 { 123 u32 index = ste - ste->htbl->ste_arr; 124 125 return ste->htbl->chunk->mr_addr + DR_STE_SIZE * index; 126 } 127 128 struct list_head *mlx5dr_ste_get_miss_list(struct mlx5dr_ste *ste) 129 { 130 u32 index = ste - ste->htbl->ste_arr; 131 132 return &ste->htbl->miss_list[index]; 133 } 134 135 static void dr_ste_always_hit_htbl(struct mlx5dr_ste_ctx *ste_ctx, 136 struct mlx5dr_ste *ste, 137 struct mlx5dr_ste_htbl *next_htbl) 138 { 139 struct mlx5dr_icm_chunk *chunk = next_htbl->chunk; 140 u8 *hw_ste = ste->hw_ste; 141 142 ste_ctx->set_byte_mask(hw_ste, next_htbl->byte_mask); 143 ste_ctx->set_next_lu_type(hw_ste, next_htbl->lu_type); 144 ste_ctx->set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries); 145 146 dr_ste_set_always_hit((struct dr_hw_ste_format *)ste->hw_ste); 147 } 148 149 bool mlx5dr_ste_is_last_in_rule(struct mlx5dr_matcher_rx_tx *nic_matcher, 150 u8 ste_location) 151 { 152 return ste_location == nic_matcher->num_of_builders; 153 } 154 155 /* Replace relevant fields, except of: 156 * htbl - keep the origin htbl 157 * miss_list + list - already took the src from the list. 158 * icm_addr/mr_addr - depends on the hosting table. 159 * 160 * Before: 161 * | a | -> | b | -> | c | -> 162 * 163 * After: 164 * | a | -> | c | -> 165 * While the data that was in b copied to a. 166 */ 167 static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src) 168 { 169 memcpy(dst->hw_ste, src->hw_ste, DR_STE_SIZE_REDUCED); 170 dst->next_htbl = src->next_htbl; 171 if (dst->next_htbl) 172 dst->next_htbl->pointing_ste = dst; 173 174 dst->refcount = src->refcount; 175 } 176 177 /* Free ste which is the head and the only one in miss_list */ 178 static void 179 dr_ste_remove_head_ste(struct mlx5dr_ste_ctx *ste_ctx, 180 struct mlx5dr_ste *ste, 181 struct mlx5dr_matcher_rx_tx *nic_matcher, 182 struct mlx5dr_ste_send_info *ste_info_head, 183 struct list_head *send_ste_list, 184 struct mlx5dr_ste_htbl *stats_tbl) 185 { 186 u8 tmp_data_ste[DR_STE_SIZE] = {}; 187 struct mlx5dr_ste tmp_ste = {}; 188 u64 miss_addr; 189 190 tmp_ste.hw_ste = tmp_data_ste; 191 192 /* Use temp ste because dr_ste_always_miss_addr 193 * touches bit_mask area which doesn't exist at ste->hw_ste. 194 */ 195 memcpy(tmp_ste.hw_ste, ste->hw_ste, DR_STE_SIZE_REDUCED); 196 miss_addr = nic_matcher->e_anchor->chunk->icm_addr; 197 dr_ste_always_miss_addr(ste_ctx, &tmp_ste, miss_addr); 198 memcpy(ste->hw_ste, tmp_ste.hw_ste, DR_STE_SIZE_REDUCED); 199 200 list_del_init(&ste->miss_list_node); 201 202 /* Write full STE size in order to have "always_miss" */ 203 mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE, 204 0, tmp_data_ste, 205 ste_info_head, 206 send_ste_list, 207 true /* Copy data */); 208 209 stats_tbl->ctrl.num_of_valid_entries--; 210 } 211 212 /* Free ste which is the head but NOT the only one in miss_list: 213 * |_ste_| --> |_next_ste_| -->|__| -->|__| -->/0 214 */ 215 static void 216 dr_ste_replace_head_ste(struct mlx5dr_matcher_rx_tx *nic_matcher, 217 struct mlx5dr_ste *ste, 218 struct mlx5dr_ste *next_ste, 219 struct mlx5dr_ste_send_info *ste_info_head, 220 struct list_head *send_ste_list, 221 struct mlx5dr_ste_htbl *stats_tbl) 222 223 { 224 struct mlx5dr_ste_htbl *next_miss_htbl; 225 u8 hw_ste[DR_STE_SIZE] = {}; 226 int sb_idx; 227 228 next_miss_htbl = next_ste->htbl; 229 230 /* Remove from the miss_list the next_ste before copy */ 231 list_del_init(&next_ste->miss_list_node); 232 233 /* Move data from next into ste */ 234 dr_ste_replace(ste, next_ste); 235 236 /* Update the rule on STE change */ 237 mlx5dr_rule_set_last_member(next_ste->rule_rx_tx, ste, false); 238 239 /* Copy all 64 hw_ste bytes */ 240 memcpy(hw_ste, ste->hw_ste, DR_STE_SIZE_REDUCED); 241 sb_idx = ste->ste_chain_location - 1; 242 mlx5dr_ste_set_bit_mask(hw_ste, 243 nic_matcher->ste_builder[sb_idx].bit_mask); 244 245 /* Del the htbl that contains the next_ste. 246 * The origin htbl stay with the same number of entries. 247 */ 248 mlx5dr_htbl_put(next_miss_htbl); 249 250 mlx5dr_send_fill_and_append_ste_send_info(ste, DR_STE_SIZE, 251 0, hw_ste, 252 ste_info_head, 253 send_ste_list, 254 true /* Copy data */); 255 256 stats_tbl->ctrl.num_of_collisions--; 257 stats_tbl->ctrl.num_of_valid_entries--; 258 } 259 260 /* Free ste that is located in the middle of the miss list: 261 * |__| -->|_prev_ste_|->|_ste_|-->|_next_ste_| 262 */ 263 static void dr_ste_remove_middle_ste(struct mlx5dr_ste_ctx *ste_ctx, 264 struct mlx5dr_ste *ste, 265 struct mlx5dr_ste_send_info *ste_info, 266 struct list_head *send_ste_list, 267 struct mlx5dr_ste_htbl *stats_tbl) 268 { 269 struct mlx5dr_ste *prev_ste; 270 u64 miss_addr; 271 272 prev_ste = list_prev_entry(ste, miss_list_node); 273 if (WARN_ON(!prev_ste)) 274 return; 275 276 miss_addr = ste_ctx->get_miss_addr(ste->hw_ste); 277 ste_ctx->set_miss_addr(prev_ste->hw_ste, miss_addr); 278 279 mlx5dr_send_fill_and_append_ste_send_info(prev_ste, DR_STE_SIZE_CTRL, 0, 280 prev_ste->hw_ste, ste_info, 281 send_ste_list, true /* Copy data*/); 282 283 list_del_init(&ste->miss_list_node); 284 285 stats_tbl->ctrl.num_of_valid_entries--; 286 stats_tbl->ctrl.num_of_collisions--; 287 } 288 289 void mlx5dr_ste_free(struct mlx5dr_ste *ste, 290 struct mlx5dr_matcher *matcher, 291 struct mlx5dr_matcher_rx_tx *nic_matcher) 292 { 293 struct mlx5dr_ste_send_info *cur_ste_info, *tmp_ste_info; 294 struct mlx5dr_domain *dmn = matcher->tbl->dmn; 295 struct mlx5dr_ste_ctx *ste_ctx = dmn->ste_ctx; 296 struct mlx5dr_ste_send_info ste_info_head; 297 struct mlx5dr_ste *next_ste, *first_ste; 298 bool put_on_origin_table = true; 299 struct mlx5dr_ste_htbl *stats_tbl; 300 LIST_HEAD(send_ste_list); 301 302 first_ste = list_first_entry(mlx5dr_ste_get_miss_list(ste), 303 struct mlx5dr_ste, miss_list_node); 304 stats_tbl = first_ste->htbl; 305 306 /* Two options: 307 * 1. ste is head: 308 * a. head ste is the only ste in the miss list 309 * b. head ste is not the only ste in the miss-list 310 * 2. ste is not head 311 */ 312 if (first_ste == ste) { /* Ste is the head */ 313 struct mlx5dr_ste *last_ste; 314 315 last_ste = list_last_entry(mlx5dr_ste_get_miss_list(ste), 316 struct mlx5dr_ste, miss_list_node); 317 if (last_ste == first_ste) 318 next_ste = NULL; 319 else 320 next_ste = list_next_entry(ste, miss_list_node); 321 322 if (!next_ste) { 323 /* One and only entry in the list */ 324 dr_ste_remove_head_ste(ste_ctx, ste, 325 nic_matcher, 326 &ste_info_head, 327 &send_ste_list, 328 stats_tbl); 329 } else { 330 /* First but not only entry in the list */ 331 dr_ste_replace_head_ste(nic_matcher, ste, 332 next_ste, &ste_info_head, 333 &send_ste_list, stats_tbl); 334 put_on_origin_table = false; 335 } 336 } else { /* Ste in the middle of the list */ 337 dr_ste_remove_middle_ste(ste_ctx, ste, 338 &ste_info_head, &send_ste_list, 339 stats_tbl); 340 } 341 342 /* Update HW */ 343 list_for_each_entry_safe(cur_ste_info, tmp_ste_info, 344 &send_ste_list, send_list) { 345 list_del(&cur_ste_info->send_list); 346 mlx5dr_send_postsend_ste(dmn, cur_ste_info->ste, 347 cur_ste_info->data, cur_ste_info->size, 348 cur_ste_info->offset); 349 } 350 351 if (put_on_origin_table) 352 mlx5dr_htbl_put(ste->htbl); 353 } 354 355 bool mlx5dr_ste_equal_tag(void *src, void *dst) 356 { 357 struct dr_hw_ste_format *s_hw_ste = (struct dr_hw_ste_format *)src; 358 struct dr_hw_ste_format *d_hw_ste = (struct dr_hw_ste_format *)dst; 359 360 return !memcmp(s_hw_ste->tag, d_hw_ste->tag, DR_STE_SIZE_TAG); 361 } 362 363 void mlx5dr_ste_set_hit_addr_by_next_htbl(struct mlx5dr_ste_ctx *ste_ctx, 364 u8 *hw_ste, 365 struct mlx5dr_ste_htbl *next_htbl) 366 { 367 struct mlx5dr_icm_chunk *chunk = next_htbl->chunk; 368 369 ste_ctx->set_hit_addr(hw_ste, chunk->icm_addr, chunk->num_of_entries); 370 } 371 372 void mlx5dr_ste_prepare_for_postsend(struct mlx5dr_ste_ctx *ste_ctx, 373 u8 *hw_ste_p, u32 ste_size) 374 { 375 if (ste_ctx->prepare_for_postsend) 376 ste_ctx->prepare_for_postsend(hw_ste_p, ste_size); 377 } 378 379 /* Init one ste as a pattern for ste data array */ 380 void mlx5dr_ste_set_formatted_ste(struct mlx5dr_ste_ctx *ste_ctx, 381 u16 gvmi, 382 enum mlx5dr_domain_nic_type nic_type, 383 struct mlx5dr_ste_htbl *htbl, 384 u8 *formatted_ste, 385 struct mlx5dr_htbl_connect_info *connect_info) 386 { 387 bool is_rx = nic_type == DR_DOMAIN_NIC_TYPE_RX; 388 struct mlx5dr_ste ste = {}; 389 390 ste_ctx->ste_init(formatted_ste, htbl->lu_type, is_rx, gvmi); 391 ste.hw_ste = formatted_ste; 392 393 if (connect_info->type == CONNECT_HIT) 394 dr_ste_always_hit_htbl(ste_ctx, &ste, connect_info->hit_next_htbl); 395 else 396 dr_ste_always_miss_addr(ste_ctx, &ste, connect_info->miss_icm_addr); 397 } 398 399 int mlx5dr_ste_htbl_init_and_postsend(struct mlx5dr_domain *dmn, 400 struct mlx5dr_domain_rx_tx *nic_dmn, 401 struct mlx5dr_ste_htbl *htbl, 402 struct mlx5dr_htbl_connect_info *connect_info, 403 bool update_hw_ste) 404 { 405 u8 formatted_ste[DR_STE_SIZE] = {}; 406 407 mlx5dr_ste_set_formatted_ste(dmn->ste_ctx, 408 dmn->info.caps.gvmi, 409 nic_dmn->type, 410 htbl, 411 formatted_ste, 412 connect_info); 413 414 return mlx5dr_send_postsend_formatted_htbl(dmn, htbl, formatted_ste, update_hw_ste); 415 } 416 417 int mlx5dr_ste_create_next_htbl(struct mlx5dr_matcher *matcher, 418 struct mlx5dr_matcher_rx_tx *nic_matcher, 419 struct mlx5dr_ste *ste, 420 u8 *cur_hw_ste, 421 enum mlx5dr_icm_chunk_size log_table_size) 422 { 423 struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn; 424 struct mlx5dr_domain *dmn = matcher->tbl->dmn; 425 struct mlx5dr_ste_ctx *ste_ctx = dmn->ste_ctx; 426 struct mlx5dr_htbl_connect_info info; 427 struct mlx5dr_ste_htbl *next_htbl; 428 429 if (!mlx5dr_ste_is_last_in_rule(nic_matcher, ste->ste_chain_location)) { 430 u16 next_lu_type; 431 u16 byte_mask; 432 433 next_lu_type = ste_ctx->get_next_lu_type(cur_hw_ste); 434 byte_mask = ste_ctx->get_byte_mask(cur_hw_ste); 435 436 next_htbl = mlx5dr_ste_htbl_alloc(dmn->ste_icm_pool, 437 log_table_size, 438 next_lu_type, 439 byte_mask); 440 if (!next_htbl) { 441 mlx5dr_dbg(dmn, "Failed allocating table\n"); 442 return -ENOMEM; 443 } 444 445 /* Write new table to HW */ 446 info.type = CONNECT_MISS; 447 info.miss_icm_addr = nic_matcher->e_anchor->chunk->icm_addr; 448 if (mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, next_htbl, 449 &info, false)) { 450 mlx5dr_info(dmn, "Failed writing table to HW\n"); 451 goto free_table; 452 } 453 454 mlx5dr_ste_set_hit_addr_by_next_htbl(ste_ctx, 455 cur_hw_ste, next_htbl); 456 ste->next_htbl = next_htbl; 457 next_htbl->pointing_ste = ste; 458 } 459 460 return 0; 461 462 free_table: 463 mlx5dr_ste_htbl_free(next_htbl); 464 return -ENOENT; 465 } 466 467 struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool, 468 enum mlx5dr_icm_chunk_size chunk_size, 469 u16 lu_type, u16 byte_mask) 470 { 471 struct mlx5dr_icm_chunk *chunk; 472 struct mlx5dr_ste_htbl *htbl; 473 int i; 474 475 htbl = kzalloc(sizeof(*htbl), GFP_KERNEL); 476 if (!htbl) 477 return NULL; 478 479 chunk = mlx5dr_icm_alloc_chunk(pool, chunk_size); 480 if (!chunk) 481 goto out_free_htbl; 482 483 htbl->chunk = chunk; 484 htbl->lu_type = lu_type; 485 htbl->byte_mask = byte_mask; 486 htbl->ste_arr = chunk->ste_arr; 487 htbl->hw_ste_arr = chunk->hw_ste_arr; 488 htbl->miss_list = chunk->miss_list; 489 htbl->refcount = 0; 490 491 for (i = 0; i < chunk->num_of_entries; i++) { 492 struct mlx5dr_ste *ste = &htbl->ste_arr[i]; 493 494 ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED; 495 ste->htbl = htbl; 496 ste->refcount = 0; 497 INIT_LIST_HEAD(&ste->miss_list_node); 498 INIT_LIST_HEAD(&htbl->miss_list[i]); 499 } 500 501 htbl->chunk_size = chunk_size; 502 return htbl; 503 504 out_free_htbl: 505 kfree(htbl); 506 return NULL; 507 } 508 509 int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl) 510 { 511 if (htbl->refcount) 512 return -EBUSY; 513 514 mlx5dr_icm_free_chunk(htbl->chunk); 515 kfree(htbl); 516 return 0; 517 } 518 519 void mlx5dr_ste_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx, 520 struct mlx5dr_domain *dmn, 521 u8 *action_type_set, 522 u8 *hw_ste_arr, 523 struct mlx5dr_ste_actions_attr *attr, 524 u32 *added_stes) 525 { 526 ste_ctx->set_actions_tx(dmn, action_type_set, hw_ste_arr, 527 attr, added_stes); 528 } 529 530 void mlx5dr_ste_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx, 531 struct mlx5dr_domain *dmn, 532 u8 *action_type_set, 533 u8 *hw_ste_arr, 534 struct mlx5dr_ste_actions_attr *attr, 535 u32 *added_stes) 536 { 537 ste_ctx->set_actions_rx(dmn, action_type_set, hw_ste_arr, 538 attr, added_stes); 539 } 540 541 const struct mlx5dr_ste_action_modify_field * 542 mlx5dr_ste_conv_modify_hdr_sw_field(struct mlx5dr_ste_ctx *ste_ctx, u16 sw_field) 543 { 544 const struct mlx5dr_ste_action_modify_field *hw_field; 545 546 if (sw_field >= ste_ctx->modify_field_arr_sz) 547 return NULL; 548 549 hw_field = &ste_ctx->modify_field_arr[sw_field]; 550 if (!hw_field->end && !hw_field->start) 551 return NULL; 552 553 return hw_field; 554 } 555 556 void mlx5dr_ste_set_action_set(struct mlx5dr_ste_ctx *ste_ctx, 557 __be64 *hw_action, 558 u8 hw_field, 559 u8 shifter, 560 u8 length, 561 u32 data) 562 { 563 ste_ctx->set_action_set((u8 *)hw_action, 564 hw_field, shifter, length, data); 565 } 566 567 void mlx5dr_ste_set_action_add(struct mlx5dr_ste_ctx *ste_ctx, 568 __be64 *hw_action, 569 u8 hw_field, 570 u8 shifter, 571 u8 length, 572 u32 data) 573 { 574 ste_ctx->set_action_add((u8 *)hw_action, 575 hw_field, shifter, length, data); 576 } 577 578 void mlx5dr_ste_set_action_copy(struct mlx5dr_ste_ctx *ste_ctx, 579 __be64 *hw_action, 580 u8 dst_hw_field, 581 u8 dst_shifter, 582 u8 dst_len, 583 u8 src_hw_field, 584 u8 src_shifter) 585 { 586 ste_ctx->set_action_copy((u8 *)hw_action, 587 dst_hw_field, dst_shifter, dst_len, 588 src_hw_field, src_shifter); 589 } 590 591 int mlx5dr_ste_set_action_decap_l3_list(struct mlx5dr_ste_ctx *ste_ctx, 592 void *data, u32 data_sz, 593 u8 *hw_action, u32 hw_action_sz, 594 u16 *used_hw_action_num) 595 { 596 /* Only Ethernet frame is supported, with VLAN (18) or without (14) */ 597 if (data_sz != HDR_LEN_L2 && data_sz != HDR_LEN_L2_W_VLAN) 598 return -EINVAL; 599 600 return ste_ctx->set_action_decap_l3_list(data, data_sz, 601 hw_action, hw_action_sz, 602 used_hw_action_num); 603 } 604 605 int mlx5dr_ste_build_pre_check(struct mlx5dr_domain *dmn, 606 u8 match_criteria, 607 struct mlx5dr_match_param *mask, 608 struct mlx5dr_match_param *value) 609 { 610 if (!value && (match_criteria & DR_MATCHER_CRITERIA_MISC)) { 611 if (mask->misc.source_port && mask->misc.source_port != 0xffff) { 612 mlx5dr_err(dmn, 613 "Partial mask source_port is not supported\n"); 614 return -EINVAL; 615 } 616 if (mask->misc.source_eswitch_owner_vhca_id && 617 mask->misc.source_eswitch_owner_vhca_id != 0xffff) { 618 mlx5dr_err(dmn, 619 "Partial mask source_eswitch_owner_vhca_id is not supported\n"); 620 return -EINVAL; 621 } 622 } 623 624 return 0; 625 } 626 627 int mlx5dr_ste_build_ste_arr(struct mlx5dr_matcher *matcher, 628 struct mlx5dr_matcher_rx_tx *nic_matcher, 629 struct mlx5dr_match_param *value, 630 u8 *ste_arr) 631 { 632 struct mlx5dr_domain_rx_tx *nic_dmn = nic_matcher->nic_tbl->nic_dmn; 633 bool is_rx = nic_dmn->type == DR_DOMAIN_NIC_TYPE_RX; 634 struct mlx5dr_domain *dmn = matcher->tbl->dmn; 635 struct mlx5dr_ste_ctx *ste_ctx = dmn->ste_ctx; 636 struct mlx5dr_ste_build *sb; 637 int ret, i; 638 639 ret = mlx5dr_ste_build_pre_check(dmn, matcher->match_criteria, 640 &matcher->mask, value); 641 if (ret) 642 return ret; 643 644 sb = nic_matcher->ste_builder; 645 for (i = 0; i < nic_matcher->num_of_builders; i++) { 646 ste_ctx->ste_init(ste_arr, 647 sb->lu_type, 648 is_rx, 649 dmn->info.caps.gvmi); 650 651 mlx5dr_ste_set_bit_mask(ste_arr, sb->bit_mask); 652 653 ret = sb->ste_build_tag_func(value, sb, dr_ste_get_tag(ste_arr)); 654 if (ret) 655 return ret; 656 657 /* Connect the STEs */ 658 if (i < (nic_matcher->num_of_builders - 1)) { 659 /* Need the next builder for these fields, 660 * not relevant for the last ste in the chain. 661 */ 662 sb++; 663 ste_ctx->set_next_lu_type(ste_arr, sb->lu_type); 664 ste_ctx->set_byte_mask(ste_arr, sb->byte_mask); 665 } 666 ste_arr += DR_STE_SIZE; 667 } 668 return 0; 669 } 670 671 static void dr_ste_copy_mask_misc(char *mask, struct mlx5dr_match_misc *spec) 672 { 673 spec->gre_c_present = MLX5_GET(fte_match_set_misc, mask, gre_c_present); 674 spec->gre_k_present = MLX5_GET(fte_match_set_misc, mask, gre_k_present); 675 spec->gre_s_present = MLX5_GET(fte_match_set_misc, mask, gre_s_present); 676 spec->source_vhca_port = MLX5_GET(fte_match_set_misc, mask, source_vhca_port); 677 spec->source_sqn = MLX5_GET(fte_match_set_misc, mask, source_sqn); 678 679 spec->source_port = MLX5_GET(fte_match_set_misc, mask, source_port); 680 spec->source_eswitch_owner_vhca_id = MLX5_GET(fte_match_set_misc, mask, 681 source_eswitch_owner_vhca_id); 682 683 spec->outer_second_prio = MLX5_GET(fte_match_set_misc, mask, outer_second_prio); 684 spec->outer_second_cfi = MLX5_GET(fte_match_set_misc, mask, outer_second_cfi); 685 spec->outer_second_vid = MLX5_GET(fte_match_set_misc, mask, outer_second_vid); 686 spec->inner_second_prio = MLX5_GET(fte_match_set_misc, mask, inner_second_prio); 687 spec->inner_second_cfi = MLX5_GET(fte_match_set_misc, mask, inner_second_cfi); 688 spec->inner_second_vid = MLX5_GET(fte_match_set_misc, mask, inner_second_vid); 689 690 spec->outer_second_cvlan_tag = 691 MLX5_GET(fte_match_set_misc, mask, outer_second_cvlan_tag); 692 spec->inner_second_cvlan_tag = 693 MLX5_GET(fte_match_set_misc, mask, inner_second_cvlan_tag); 694 spec->outer_second_svlan_tag = 695 MLX5_GET(fte_match_set_misc, mask, outer_second_svlan_tag); 696 spec->inner_second_svlan_tag = 697 MLX5_GET(fte_match_set_misc, mask, inner_second_svlan_tag); 698 699 spec->gre_protocol = MLX5_GET(fte_match_set_misc, mask, gre_protocol); 700 701 spec->gre_key_h = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.hi); 702 spec->gre_key_l = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.lo); 703 704 spec->vxlan_vni = MLX5_GET(fte_match_set_misc, mask, vxlan_vni); 705 706 spec->geneve_vni = MLX5_GET(fte_match_set_misc, mask, geneve_vni); 707 spec->geneve_oam = MLX5_GET(fte_match_set_misc, mask, geneve_oam); 708 709 spec->outer_ipv6_flow_label = 710 MLX5_GET(fte_match_set_misc, mask, outer_ipv6_flow_label); 711 712 spec->inner_ipv6_flow_label = 713 MLX5_GET(fte_match_set_misc, mask, inner_ipv6_flow_label); 714 715 spec->geneve_opt_len = MLX5_GET(fte_match_set_misc, mask, geneve_opt_len); 716 spec->geneve_protocol_type = 717 MLX5_GET(fte_match_set_misc, mask, geneve_protocol_type); 718 719 spec->bth_dst_qp = MLX5_GET(fte_match_set_misc, mask, bth_dst_qp); 720 } 721 722 static void dr_ste_copy_mask_spec(char *mask, struct mlx5dr_match_spec *spec) 723 { 724 __be32 raw_ip[4]; 725 726 spec->smac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_47_16); 727 728 spec->smac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_15_0); 729 spec->ethertype = MLX5_GET(fte_match_set_lyr_2_4, mask, ethertype); 730 731 spec->dmac_47_16 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_47_16); 732 733 spec->dmac_15_0 = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_15_0); 734 spec->first_prio = MLX5_GET(fte_match_set_lyr_2_4, mask, first_prio); 735 spec->first_cfi = MLX5_GET(fte_match_set_lyr_2_4, mask, first_cfi); 736 spec->first_vid = MLX5_GET(fte_match_set_lyr_2_4, mask, first_vid); 737 738 spec->ip_protocol = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_protocol); 739 spec->ip_dscp = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_dscp); 740 spec->ip_ecn = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_ecn); 741 spec->cvlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, cvlan_tag); 742 spec->svlan_tag = MLX5_GET(fte_match_set_lyr_2_4, mask, svlan_tag); 743 spec->frag = MLX5_GET(fte_match_set_lyr_2_4, mask, frag); 744 spec->ip_version = MLX5_GET(fte_match_set_lyr_2_4, mask, ip_version); 745 spec->tcp_flags = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_flags); 746 spec->tcp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_sport); 747 spec->tcp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, tcp_dport); 748 749 spec->ttl_hoplimit = MLX5_GET(fte_match_set_lyr_2_4, mask, ttl_hoplimit); 750 751 spec->udp_sport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_sport); 752 spec->udp_dport = MLX5_GET(fte_match_set_lyr_2_4, mask, udp_dport); 753 754 memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask, 755 src_ipv4_src_ipv6.ipv6_layout.ipv6), 756 sizeof(raw_ip)); 757 758 spec->src_ip_127_96 = be32_to_cpu(raw_ip[0]); 759 spec->src_ip_95_64 = be32_to_cpu(raw_ip[1]); 760 spec->src_ip_63_32 = be32_to_cpu(raw_ip[2]); 761 spec->src_ip_31_0 = be32_to_cpu(raw_ip[3]); 762 763 memcpy(raw_ip, MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask, 764 dst_ipv4_dst_ipv6.ipv6_layout.ipv6), 765 sizeof(raw_ip)); 766 767 spec->dst_ip_127_96 = be32_to_cpu(raw_ip[0]); 768 spec->dst_ip_95_64 = be32_to_cpu(raw_ip[1]); 769 spec->dst_ip_63_32 = be32_to_cpu(raw_ip[2]); 770 spec->dst_ip_31_0 = be32_to_cpu(raw_ip[3]); 771 } 772 773 static void dr_ste_copy_mask_misc2(char *mask, struct mlx5dr_match_misc2 *spec) 774 { 775 spec->outer_first_mpls_label = 776 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_label); 777 spec->outer_first_mpls_exp = 778 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_exp); 779 spec->outer_first_mpls_s_bos = 780 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_s_bos); 781 spec->outer_first_mpls_ttl = 782 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls.mpls_ttl); 783 spec->inner_first_mpls_label = 784 MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_label); 785 spec->inner_first_mpls_exp = 786 MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_exp); 787 spec->inner_first_mpls_s_bos = 788 MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_s_bos); 789 spec->inner_first_mpls_ttl = 790 MLX5_GET(fte_match_set_misc2, mask, inner_first_mpls.mpls_ttl); 791 spec->outer_first_mpls_over_gre_label = 792 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_label); 793 spec->outer_first_mpls_over_gre_exp = 794 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_exp); 795 spec->outer_first_mpls_over_gre_s_bos = 796 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_s_bos); 797 spec->outer_first_mpls_over_gre_ttl = 798 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_gre.mpls_ttl); 799 spec->outer_first_mpls_over_udp_label = 800 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_label); 801 spec->outer_first_mpls_over_udp_exp = 802 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_exp); 803 spec->outer_first_mpls_over_udp_s_bos = 804 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_s_bos); 805 spec->outer_first_mpls_over_udp_ttl = 806 MLX5_GET(fte_match_set_misc2, mask, outer_first_mpls_over_udp.mpls_ttl); 807 spec->metadata_reg_c_7 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_7); 808 spec->metadata_reg_c_6 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_6); 809 spec->metadata_reg_c_5 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_5); 810 spec->metadata_reg_c_4 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_4); 811 spec->metadata_reg_c_3 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_3); 812 spec->metadata_reg_c_2 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_2); 813 spec->metadata_reg_c_1 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_1); 814 spec->metadata_reg_c_0 = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_c_0); 815 spec->metadata_reg_a = MLX5_GET(fte_match_set_misc2, mask, metadata_reg_a); 816 } 817 818 static void dr_ste_copy_mask_misc3(char *mask, struct mlx5dr_match_misc3 *spec) 819 { 820 spec->inner_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_seq_num); 821 spec->outer_tcp_seq_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_seq_num); 822 spec->inner_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, inner_tcp_ack_num); 823 spec->outer_tcp_ack_num = MLX5_GET(fte_match_set_misc3, mask, outer_tcp_ack_num); 824 spec->outer_vxlan_gpe_vni = 825 MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_vni); 826 spec->outer_vxlan_gpe_next_protocol = 827 MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_next_protocol); 828 spec->outer_vxlan_gpe_flags = 829 MLX5_GET(fte_match_set_misc3, mask, outer_vxlan_gpe_flags); 830 spec->icmpv4_header_data = MLX5_GET(fte_match_set_misc3, mask, icmp_header_data); 831 spec->icmpv6_header_data = 832 MLX5_GET(fte_match_set_misc3, mask, icmpv6_header_data); 833 spec->icmpv4_type = MLX5_GET(fte_match_set_misc3, mask, icmp_type); 834 spec->icmpv4_code = MLX5_GET(fte_match_set_misc3, mask, icmp_code); 835 spec->icmpv6_type = MLX5_GET(fte_match_set_misc3, mask, icmpv6_type); 836 spec->icmpv6_code = MLX5_GET(fte_match_set_misc3, mask, icmpv6_code); 837 spec->geneve_tlv_option_0_data = 838 MLX5_GET(fte_match_set_misc3, mask, geneve_tlv_option_0_data); 839 spec->gtpu_msg_flags = MLX5_GET(fte_match_set_misc3, mask, gtpu_msg_flags); 840 spec->gtpu_msg_type = MLX5_GET(fte_match_set_misc3, mask, gtpu_msg_type); 841 spec->gtpu_teid = MLX5_GET(fte_match_set_misc3, mask, gtpu_teid); 842 spec->gtpu_dw_0 = MLX5_GET(fte_match_set_misc3, mask, gtpu_dw_0); 843 spec->gtpu_dw_2 = MLX5_GET(fte_match_set_misc3, mask, gtpu_dw_2); 844 spec->gtpu_first_ext_dw_0 = 845 MLX5_GET(fte_match_set_misc3, mask, gtpu_first_ext_dw_0); 846 } 847 848 static void dr_ste_copy_mask_misc4(char *mask, struct mlx5dr_match_misc4 *spec) 849 { 850 spec->prog_sample_field_id_0 = 851 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_id_0); 852 spec->prog_sample_field_value_0 = 853 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_value_0); 854 spec->prog_sample_field_id_1 = 855 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_id_1); 856 spec->prog_sample_field_value_1 = 857 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_value_1); 858 spec->prog_sample_field_id_2 = 859 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_id_2); 860 spec->prog_sample_field_value_2 = 861 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_value_2); 862 spec->prog_sample_field_id_3 = 863 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_id_3); 864 spec->prog_sample_field_value_3 = 865 MLX5_GET(fte_match_set_misc4, mask, prog_sample_field_value_3); 866 } 867 868 void mlx5dr_ste_copy_param(u8 match_criteria, 869 struct mlx5dr_match_param *set_param, 870 struct mlx5dr_match_parameters *mask) 871 { 872 u8 tail_param[MLX5_ST_SZ_BYTES(fte_match_set_lyr_2_4)] = {}; 873 u8 *data = (u8 *)mask->match_buf; 874 size_t param_location; 875 void *buff; 876 877 if (match_criteria & DR_MATCHER_CRITERIA_OUTER) { 878 if (mask->match_sz < sizeof(struct mlx5dr_match_spec)) { 879 memcpy(tail_param, data, mask->match_sz); 880 buff = tail_param; 881 } else { 882 buff = mask->match_buf; 883 } 884 dr_ste_copy_mask_spec(buff, &set_param->outer); 885 } 886 param_location = sizeof(struct mlx5dr_match_spec); 887 888 if (match_criteria & DR_MATCHER_CRITERIA_MISC) { 889 if (mask->match_sz < param_location + 890 sizeof(struct mlx5dr_match_misc)) { 891 memcpy(tail_param, data + param_location, 892 mask->match_sz - param_location); 893 buff = tail_param; 894 } else { 895 buff = data + param_location; 896 } 897 dr_ste_copy_mask_misc(buff, &set_param->misc); 898 } 899 param_location += sizeof(struct mlx5dr_match_misc); 900 901 if (match_criteria & DR_MATCHER_CRITERIA_INNER) { 902 if (mask->match_sz < param_location + 903 sizeof(struct mlx5dr_match_spec)) { 904 memcpy(tail_param, data + param_location, 905 mask->match_sz - param_location); 906 buff = tail_param; 907 } else { 908 buff = data + param_location; 909 } 910 dr_ste_copy_mask_spec(buff, &set_param->inner); 911 } 912 param_location += sizeof(struct mlx5dr_match_spec); 913 914 if (match_criteria & DR_MATCHER_CRITERIA_MISC2) { 915 if (mask->match_sz < param_location + 916 sizeof(struct mlx5dr_match_misc2)) { 917 memcpy(tail_param, data + param_location, 918 mask->match_sz - param_location); 919 buff = tail_param; 920 } else { 921 buff = data + param_location; 922 } 923 dr_ste_copy_mask_misc2(buff, &set_param->misc2); 924 } 925 926 param_location += sizeof(struct mlx5dr_match_misc2); 927 928 if (match_criteria & DR_MATCHER_CRITERIA_MISC3) { 929 if (mask->match_sz < param_location + 930 sizeof(struct mlx5dr_match_misc3)) { 931 memcpy(tail_param, data + param_location, 932 mask->match_sz - param_location); 933 buff = tail_param; 934 } else { 935 buff = data + param_location; 936 } 937 dr_ste_copy_mask_misc3(buff, &set_param->misc3); 938 } 939 940 param_location += sizeof(struct mlx5dr_match_misc3); 941 942 if (match_criteria & DR_MATCHER_CRITERIA_MISC4) { 943 if (mask->match_sz < param_location + 944 sizeof(struct mlx5dr_match_misc4)) { 945 memcpy(tail_param, data + param_location, 946 mask->match_sz - param_location); 947 buff = tail_param; 948 } else { 949 buff = data + param_location; 950 } 951 dr_ste_copy_mask_misc4(buff, &set_param->misc4); 952 } 953 } 954 955 void mlx5dr_ste_build_eth_l2_src_dst(struct mlx5dr_ste_ctx *ste_ctx, 956 struct mlx5dr_ste_build *sb, 957 struct mlx5dr_match_param *mask, 958 bool inner, bool rx) 959 { 960 sb->rx = rx; 961 sb->inner = inner; 962 ste_ctx->build_eth_l2_src_dst_init(sb, mask); 963 } 964 965 void mlx5dr_ste_build_eth_l3_ipv6_dst(struct mlx5dr_ste_ctx *ste_ctx, 966 struct mlx5dr_ste_build *sb, 967 struct mlx5dr_match_param *mask, 968 bool inner, bool rx) 969 { 970 sb->rx = rx; 971 sb->inner = inner; 972 ste_ctx->build_eth_l3_ipv6_dst_init(sb, mask); 973 } 974 975 void mlx5dr_ste_build_eth_l3_ipv6_src(struct mlx5dr_ste_ctx *ste_ctx, 976 struct mlx5dr_ste_build *sb, 977 struct mlx5dr_match_param *mask, 978 bool inner, bool rx) 979 { 980 sb->rx = rx; 981 sb->inner = inner; 982 ste_ctx->build_eth_l3_ipv6_src_init(sb, mask); 983 } 984 985 void mlx5dr_ste_build_eth_l3_ipv4_5_tuple(struct mlx5dr_ste_ctx *ste_ctx, 986 struct mlx5dr_ste_build *sb, 987 struct mlx5dr_match_param *mask, 988 bool inner, bool rx) 989 { 990 sb->rx = rx; 991 sb->inner = inner; 992 ste_ctx->build_eth_l3_ipv4_5_tuple_init(sb, mask); 993 } 994 995 void mlx5dr_ste_build_eth_l2_src(struct mlx5dr_ste_ctx *ste_ctx, 996 struct mlx5dr_ste_build *sb, 997 struct mlx5dr_match_param *mask, 998 bool inner, bool rx) 999 { 1000 sb->rx = rx; 1001 sb->inner = inner; 1002 ste_ctx->build_eth_l2_src_init(sb, mask); 1003 } 1004 1005 void mlx5dr_ste_build_eth_l2_dst(struct mlx5dr_ste_ctx *ste_ctx, 1006 struct mlx5dr_ste_build *sb, 1007 struct mlx5dr_match_param *mask, 1008 bool inner, bool rx) 1009 { 1010 sb->rx = rx; 1011 sb->inner = inner; 1012 ste_ctx->build_eth_l2_dst_init(sb, mask); 1013 } 1014 1015 void mlx5dr_ste_build_eth_l2_tnl(struct mlx5dr_ste_ctx *ste_ctx, 1016 struct mlx5dr_ste_build *sb, 1017 struct mlx5dr_match_param *mask, bool inner, bool rx) 1018 { 1019 sb->rx = rx; 1020 sb->inner = inner; 1021 ste_ctx->build_eth_l2_tnl_init(sb, mask); 1022 } 1023 1024 void mlx5dr_ste_build_eth_l3_ipv4_misc(struct mlx5dr_ste_ctx *ste_ctx, 1025 struct mlx5dr_ste_build *sb, 1026 struct mlx5dr_match_param *mask, 1027 bool inner, bool rx) 1028 { 1029 sb->rx = rx; 1030 sb->inner = inner; 1031 ste_ctx->build_eth_l3_ipv4_misc_init(sb, mask); 1032 } 1033 1034 void mlx5dr_ste_build_eth_ipv6_l3_l4(struct mlx5dr_ste_ctx *ste_ctx, 1035 struct mlx5dr_ste_build *sb, 1036 struct mlx5dr_match_param *mask, 1037 bool inner, bool rx) 1038 { 1039 sb->rx = rx; 1040 sb->inner = inner; 1041 ste_ctx->build_eth_ipv6_l3_l4_init(sb, mask); 1042 } 1043 1044 static int dr_ste_build_empty_always_hit_tag(struct mlx5dr_match_param *value, 1045 struct mlx5dr_ste_build *sb, 1046 u8 *tag) 1047 { 1048 return 0; 1049 } 1050 1051 void mlx5dr_ste_build_empty_always_hit(struct mlx5dr_ste_build *sb, bool rx) 1052 { 1053 sb->rx = rx; 1054 sb->lu_type = MLX5DR_STE_LU_TYPE_DONT_CARE; 1055 sb->byte_mask = 0; 1056 sb->ste_build_tag_func = &dr_ste_build_empty_always_hit_tag; 1057 } 1058 1059 void mlx5dr_ste_build_mpls(struct mlx5dr_ste_ctx *ste_ctx, 1060 struct mlx5dr_ste_build *sb, 1061 struct mlx5dr_match_param *mask, 1062 bool inner, bool rx) 1063 { 1064 sb->rx = rx; 1065 sb->inner = inner; 1066 ste_ctx->build_mpls_init(sb, mask); 1067 } 1068 1069 void mlx5dr_ste_build_tnl_gre(struct mlx5dr_ste_ctx *ste_ctx, 1070 struct mlx5dr_ste_build *sb, 1071 struct mlx5dr_match_param *mask, 1072 bool inner, bool rx) 1073 { 1074 sb->rx = rx; 1075 sb->inner = inner; 1076 ste_ctx->build_tnl_gre_init(sb, mask); 1077 } 1078 1079 void mlx5dr_ste_build_tnl_mpls_over_gre(struct mlx5dr_ste_ctx *ste_ctx, 1080 struct mlx5dr_ste_build *sb, 1081 struct mlx5dr_match_param *mask, 1082 struct mlx5dr_cmd_caps *caps, 1083 bool inner, bool rx) 1084 { 1085 sb->rx = rx; 1086 sb->inner = inner; 1087 sb->caps = caps; 1088 return ste_ctx->build_tnl_mpls_over_gre_init(sb, mask); 1089 } 1090 1091 void mlx5dr_ste_build_tnl_mpls_over_udp(struct mlx5dr_ste_ctx *ste_ctx, 1092 struct mlx5dr_ste_build *sb, 1093 struct mlx5dr_match_param *mask, 1094 struct mlx5dr_cmd_caps *caps, 1095 bool inner, bool rx) 1096 { 1097 sb->rx = rx; 1098 sb->inner = inner; 1099 sb->caps = caps; 1100 return ste_ctx->build_tnl_mpls_over_udp_init(sb, mask); 1101 } 1102 1103 void mlx5dr_ste_build_icmp(struct mlx5dr_ste_ctx *ste_ctx, 1104 struct mlx5dr_ste_build *sb, 1105 struct mlx5dr_match_param *mask, 1106 struct mlx5dr_cmd_caps *caps, 1107 bool inner, bool rx) 1108 { 1109 sb->rx = rx; 1110 sb->inner = inner; 1111 sb->caps = caps; 1112 ste_ctx->build_icmp_init(sb, mask); 1113 } 1114 1115 void mlx5dr_ste_build_general_purpose(struct mlx5dr_ste_ctx *ste_ctx, 1116 struct mlx5dr_ste_build *sb, 1117 struct mlx5dr_match_param *mask, 1118 bool inner, bool rx) 1119 { 1120 sb->rx = rx; 1121 sb->inner = inner; 1122 ste_ctx->build_general_purpose_init(sb, mask); 1123 } 1124 1125 void mlx5dr_ste_build_eth_l4_misc(struct mlx5dr_ste_ctx *ste_ctx, 1126 struct mlx5dr_ste_build *sb, 1127 struct mlx5dr_match_param *mask, 1128 bool inner, bool rx) 1129 { 1130 sb->rx = rx; 1131 sb->inner = inner; 1132 ste_ctx->build_eth_l4_misc_init(sb, mask); 1133 } 1134 1135 void mlx5dr_ste_build_tnl_vxlan_gpe(struct mlx5dr_ste_ctx *ste_ctx, 1136 struct mlx5dr_ste_build *sb, 1137 struct mlx5dr_match_param *mask, 1138 bool inner, bool rx) 1139 { 1140 sb->rx = rx; 1141 sb->inner = inner; 1142 ste_ctx->build_tnl_vxlan_gpe_init(sb, mask); 1143 } 1144 1145 void mlx5dr_ste_build_tnl_geneve(struct mlx5dr_ste_ctx *ste_ctx, 1146 struct mlx5dr_ste_build *sb, 1147 struct mlx5dr_match_param *mask, 1148 bool inner, bool rx) 1149 { 1150 sb->rx = rx; 1151 sb->inner = inner; 1152 ste_ctx->build_tnl_geneve_init(sb, mask); 1153 } 1154 1155 void mlx5dr_ste_build_tnl_geneve_tlv_opt(struct mlx5dr_ste_ctx *ste_ctx, 1156 struct mlx5dr_ste_build *sb, 1157 struct mlx5dr_match_param *mask, 1158 struct mlx5dr_cmd_caps *caps, 1159 bool inner, bool rx) 1160 { 1161 sb->rx = rx; 1162 sb->caps = caps; 1163 sb->inner = inner; 1164 ste_ctx->build_tnl_geneve_tlv_opt_init(sb, mask); 1165 } 1166 1167 void mlx5dr_ste_build_tnl_gtpu(struct mlx5dr_ste_ctx *ste_ctx, 1168 struct mlx5dr_ste_build *sb, 1169 struct mlx5dr_match_param *mask, 1170 bool inner, bool rx) 1171 { 1172 sb->rx = rx; 1173 sb->inner = inner; 1174 ste_ctx->build_tnl_gtpu_init(sb, mask); 1175 } 1176 1177 void mlx5dr_ste_build_tnl_gtpu_flex_parser_0(struct mlx5dr_ste_ctx *ste_ctx, 1178 struct mlx5dr_ste_build *sb, 1179 struct mlx5dr_match_param *mask, 1180 struct mlx5dr_cmd_caps *caps, 1181 bool inner, bool rx) 1182 { 1183 sb->rx = rx; 1184 sb->caps = caps; 1185 sb->inner = inner; 1186 ste_ctx->build_tnl_gtpu_flex_parser_0_init(sb, mask); 1187 } 1188 1189 void mlx5dr_ste_build_tnl_gtpu_flex_parser_1(struct mlx5dr_ste_ctx *ste_ctx, 1190 struct mlx5dr_ste_build *sb, 1191 struct mlx5dr_match_param *mask, 1192 struct mlx5dr_cmd_caps *caps, 1193 bool inner, bool rx) 1194 { 1195 sb->rx = rx; 1196 sb->caps = caps; 1197 sb->inner = inner; 1198 ste_ctx->build_tnl_gtpu_flex_parser_1_init(sb, mask); 1199 } 1200 1201 void mlx5dr_ste_build_register_0(struct mlx5dr_ste_ctx *ste_ctx, 1202 struct mlx5dr_ste_build *sb, 1203 struct mlx5dr_match_param *mask, 1204 bool inner, bool rx) 1205 { 1206 sb->rx = rx; 1207 sb->inner = inner; 1208 ste_ctx->build_register_0_init(sb, mask); 1209 } 1210 1211 void mlx5dr_ste_build_register_1(struct mlx5dr_ste_ctx *ste_ctx, 1212 struct mlx5dr_ste_build *sb, 1213 struct mlx5dr_match_param *mask, 1214 bool inner, bool rx) 1215 { 1216 sb->rx = rx; 1217 sb->inner = inner; 1218 ste_ctx->build_register_1_init(sb, mask); 1219 } 1220 1221 void mlx5dr_ste_build_src_gvmi_qpn(struct mlx5dr_ste_ctx *ste_ctx, 1222 struct mlx5dr_ste_build *sb, 1223 struct mlx5dr_match_param *mask, 1224 struct mlx5dr_domain *dmn, 1225 bool inner, bool rx) 1226 { 1227 /* Set vhca_id_valid before we reset source_eswitch_owner_vhca_id */ 1228 sb->vhca_id_valid = mask->misc.source_eswitch_owner_vhca_id; 1229 1230 sb->rx = rx; 1231 sb->dmn = dmn; 1232 sb->inner = inner; 1233 ste_ctx->build_src_gvmi_qpn_init(sb, mask); 1234 } 1235 1236 void mlx5dr_ste_build_flex_parser_0(struct mlx5dr_ste_ctx *ste_ctx, 1237 struct mlx5dr_ste_build *sb, 1238 struct mlx5dr_match_param *mask, 1239 bool inner, bool rx) 1240 { 1241 sb->rx = rx; 1242 sb->inner = inner; 1243 ste_ctx->build_flex_parser_0_init(sb, mask); 1244 } 1245 1246 void mlx5dr_ste_build_flex_parser_1(struct mlx5dr_ste_ctx *ste_ctx, 1247 struct mlx5dr_ste_build *sb, 1248 struct mlx5dr_match_param *mask, 1249 bool inner, bool rx) 1250 { 1251 sb->rx = rx; 1252 sb->inner = inner; 1253 ste_ctx->build_flex_parser_1_init(sb, mask); 1254 } 1255 1256 static struct mlx5dr_ste_ctx *mlx5dr_ste_ctx_arr[] = { 1257 [MLX5_STEERING_FORMAT_CONNECTX_5] = &ste_ctx_v0, 1258 [MLX5_STEERING_FORMAT_CONNECTX_6DX] = &ste_ctx_v1, 1259 }; 1260 1261 struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx(u8 version) 1262 { 1263 if (version > MLX5_STEERING_FORMAT_CONNECTX_6DX) 1264 return NULL; 1265 1266 return mlx5dr_ste_ctx_arr[version]; 1267 } 1268