1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2016 6WIND S.A. 3 * Copyright 2016 Mellanox Technologies, Ltd 4 */ 5 6 #include <stdalign.h> 7 #include <stdint.h> 8 #include <string.h> 9 #include <stdbool.h> 10 #include <sys/queue.h> 11 12 #include <rte_common.h> 13 #include <rte_ether.h> 14 #include <ethdev_driver.h> 15 #include <rte_eal_paging.h> 16 #include <rte_flow.h> 17 #include <rte_cycles.h> 18 #include <rte_flow_driver.h> 19 #include <rte_malloc.h> 20 #include <rte_ip.h> 21 22 #include <mlx5_glue.h> 23 #include <mlx5_devx_cmds.h> 24 #include <mlx5_prm.h> 25 #include <mlx5_malloc.h> 26 27 #include "mlx5_defs.h" 28 #include "mlx5.h" 29 #include "mlx5_flow.h" 30 #include "mlx5_flow_os.h" 31 #include "mlx5_rx.h" 32 #include "mlx5_tx.h" 33 #include "mlx5_common_os.h" 34 #include "rte_pmd_mlx5.h" 35 36 /* 37 * Shared array for quick translation between port_id and vport mask/values 38 * used for HWS rules. 39 */ 40 struct flow_hw_port_info mlx5_flow_hw_port_infos[RTE_MAX_ETHPORTS]; 41 42 /* 43 * A global structure to save the available REG_C_x for tags usage. 44 * The Meter color REG (ASO) and the last available one will be reserved 45 * for PMD internal usage. 46 * Since there is no "port" concept in the driver, it is assumed that the 47 * available tags set will be the minimum intersection. 48 * 3 - in FDB mode / 5 - in legacy mode 49 */ 50 uint32_t mlx5_flow_hw_avl_tags_init_cnt; 51 enum modify_reg mlx5_flow_hw_avl_tags[MLX5_FLOW_HW_TAGS_MAX] = {REG_NON}; 52 53 struct tunnel_default_miss_ctx { 54 uint16_t *queue; 55 __extension__ 56 union { 57 struct rte_flow_action_rss action_rss; 58 struct rte_flow_action_queue miss_queue; 59 struct rte_flow_action_jump miss_jump; 60 uint8_t raw[0]; 61 }; 62 }; 63 64 static int 65 flow_tunnel_add_default_miss(struct rte_eth_dev *dev, 66 struct rte_flow *flow, 67 const struct rte_flow_attr *attr, 68 const struct rte_flow_action *app_actions, 69 uint32_t flow_idx, 70 const struct mlx5_flow_tunnel *tunnel, 71 struct tunnel_default_miss_ctx *ctx, 72 struct rte_flow_error *error); 73 static struct mlx5_flow_tunnel * 74 mlx5_find_tunnel_id(struct rte_eth_dev *dev, uint32_t id); 75 static void 76 mlx5_flow_tunnel_free(struct rte_eth_dev *dev, struct mlx5_flow_tunnel *tunnel); 77 static uint32_t 78 tunnel_flow_group_to_flow_table(struct rte_eth_dev *dev, 79 const struct mlx5_flow_tunnel *tunnel, 80 uint32_t group, uint32_t *table, 81 struct rte_flow_error *error); 82 83 /** Device flow drivers. */ 84 extern const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops; 85 86 const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops; 87 88 const struct mlx5_flow_driver_ops *flow_drv_ops[] = { 89 [MLX5_FLOW_TYPE_MIN] = &mlx5_flow_null_drv_ops, 90 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H) 91 [MLX5_FLOW_TYPE_DV] = &mlx5_flow_dv_drv_ops, 92 #endif 93 #ifdef HAVE_MLX5_HWS_SUPPORT 94 [MLX5_FLOW_TYPE_HW] = &mlx5_flow_hw_drv_ops, 95 #endif 96 [MLX5_FLOW_TYPE_VERBS] = &mlx5_flow_verbs_drv_ops, 97 [MLX5_FLOW_TYPE_MAX] = &mlx5_flow_null_drv_ops 98 }; 99 100 /** Helper macro to build input graph for mlx5_flow_expand_rss(). */ 101 #define MLX5_FLOW_EXPAND_RSS_NEXT(...) \ 102 (const int []){ \ 103 __VA_ARGS__, 0, \ 104 } 105 106 /** Node object of input graph for mlx5_flow_expand_rss(). */ 107 struct mlx5_flow_expand_node { 108 const int *const next; 109 /**< 110 * List of next node indexes. Index 0 is interpreted as a terminator. 111 */ 112 const enum rte_flow_item_type type; 113 /**< Pattern item type of current node. */ 114 uint64_t rss_types; 115 /**< 116 * RSS types bit-field associated with this node 117 * (see RTE_ETH_RSS_* definitions). 118 */ 119 uint64_t node_flags; 120 /**< 121 * Bit-fields that define how the node is used in the expansion. 122 * (see MLX5_EXPANSION_NODE_* definitions). 123 */ 124 }; 125 126 /* Optional expand field. The expansion alg will not go deeper. */ 127 #define MLX5_EXPANSION_NODE_OPTIONAL (UINT64_C(1) << 0) 128 129 /* The node is not added implicitly as expansion to the flow pattern. 130 * If the node type does not match the flow pattern item type, the 131 * expansion alg will go deeper to its next items. 132 * In the current implementation, the list of next nodes indexes can 133 * have up to one node with this flag set and it has to be the last 134 * node index (before the list terminator). 135 */ 136 #define MLX5_EXPANSION_NODE_EXPLICIT (UINT64_C(1) << 1) 137 138 /** Object returned by mlx5_flow_expand_rss(). */ 139 struct mlx5_flow_expand_rss { 140 uint32_t entries; 141 /**< Number of entries @p patterns and @p priorities. */ 142 struct { 143 struct rte_flow_item *pattern; /**< Expanded pattern array. */ 144 uint32_t priority; /**< Priority offset for each expansion. */ 145 } entry[]; 146 }; 147 148 static void 149 mlx5_dbg__print_pattern(const struct rte_flow_item *item); 150 151 static const struct mlx5_flow_expand_node * 152 mlx5_flow_expand_rss_adjust_node(const struct rte_flow_item *pattern, 153 unsigned int item_idx, 154 const struct mlx5_flow_expand_node graph[], 155 const struct mlx5_flow_expand_node *node); 156 157 static bool 158 mlx5_flow_is_rss_expandable_item(const struct rte_flow_item *item) 159 { 160 switch (item->type) { 161 case RTE_FLOW_ITEM_TYPE_ETH: 162 case RTE_FLOW_ITEM_TYPE_VLAN: 163 case RTE_FLOW_ITEM_TYPE_IPV4: 164 case RTE_FLOW_ITEM_TYPE_IPV6: 165 case RTE_FLOW_ITEM_TYPE_UDP: 166 case RTE_FLOW_ITEM_TYPE_TCP: 167 case RTE_FLOW_ITEM_TYPE_ESP: 168 case RTE_FLOW_ITEM_TYPE_ICMP: 169 case RTE_FLOW_ITEM_TYPE_ICMP6: 170 case RTE_FLOW_ITEM_TYPE_VXLAN: 171 case RTE_FLOW_ITEM_TYPE_NVGRE: 172 case RTE_FLOW_ITEM_TYPE_GRE: 173 case RTE_FLOW_ITEM_TYPE_GENEVE: 174 case RTE_FLOW_ITEM_TYPE_MPLS: 175 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 176 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 177 case RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT: 178 case RTE_FLOW_ITEM_TYPE_GTP: 179 return true; 180 default: 181 break; 182 } 183 return false; 184 } 185 186 /** 187 * Network Service Header (NSH) and its next protocol values 188 * are described in RFC-8393. 189 */ 190 static enum rte_flow_item_type 191 mlx5_nsh_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask) 192 { 193 enum rte_flow_item_type type; 194 195 switch (proto_mask & proto_spec) { 196 case 0: 197 type = RTE_FLOW_ITEM_TYPE_VOID; 198 break; 199 case RTE_VXLAN_GPE_TYPE_IPV4: 200 type = RTE_FLOW_ITEM_TYPE_IPV4; 201 break; 202 case RTE_VXLAN_GPE_TYPE_IPV6: 203 type = RTE_VXLAN_GPE_TYPE_IPV6; 204 break; 205 case RTE_VXLAN_GPE_TYPE_ETH: 206 type = RTE_FLOW_ITEM_TYPE_ETH; 207 break; 208 default: 209 type = RTE_FLOW_ITEM_TYPE_END; 210 } 211 return type; 212 } 213 214 static enum rte_flow_item_type 215 mlx5_inet_proto_to_item_type(uint8_t proto_spec, uint8_t proto_mask) 216 { 217 enum rte_flow_item_type type; 218 219 switch (proto_mask & proto_spec) { 220 case 0: 221 type = RTE_FLOW_ITEM_TYPE_VOID; 222 break; 223 case IPPROTO_UDP: 224 type = RTE_FLOW_ITEM_TYPE_UDP; 225 break; 226 case IPPROTO_TCP: 227 type = RTE_FLOW_ITEM_TYPE_TCP; 228 break; 229 case IPPROTO_IPIP: 230 type = RTE_FLOW_ITEM_TYPE_IPV4; 231 break; 232 case IPPROTO_IPV6: 233 type = RTE_FLOW_ITEM_TYPE_IPV6; 234 break; 235 case IPPROTO_ESP: 236 type = RTE_FLOW_ITEM_TYPE_ESP; 237 break; 238 default: 239 type = RTE_FLOW_ITEM_TYPE_END; 240 } 241 return type; 242 } 243 244 static enum rte_flow_item_type 245 mlx5_ethertype_to_item_type(rte_be16_t type_spec, 246 rte_be16_t type_mask, bool is_tunnel) 247 { 248 enum rte_flow_item_type type; 249 250 switch (rte_be_to_cpu_16(type_spec & type_mask)) { 251 case 0: 252 type = RTE_FLOW_ITEM_TYPE_VOID; 253 break; 254 case RTE_ETHER_TYPE_TEB: 255 type = is_tunnel ? 256 RTE_FLOW_ITEM_TYPE_ETH : RTE_FLOW_ITEM_TYPE_END; 257 break; 258 case RTE_ETHER_TYPE_VLAN: 259 type = !is_tunnel ? 260 RTE_FLOW_ITEM_TYPE_VLAN : RTE_FLOW_ITEM_TYPE_END; 261 break; 262 case RTE_ETHER_TYPE_IPV4: 263 type = RTE_FLOW_ITEM_TYPE_IPV4; 264 break; 265 case RTE_ETHER_TYPE_IPV6: 266 type = RTE_FLOW_ITEM_TYPE_IPV6; 267 break; 268 default: 269 type = RTE_FLOW_ITEM_TYPE_END; 270 } 271 return type; 272 } 273 274 static enum rte_flow_item_type 275 mlx5_flow_expand_rss_item_complete(const struct rte_flow_item *item) 276 { 277 #define MLX5_XSET_ITEM_MASK_SPEC(type, fld) \ 278 do { \ 279 const void *m = item->mask; \ 280 const void *s = item->spec; \ 281 mask = m ? \ 282 ((const struct rte_flow_item_##type *)m)->fld : \ 283 rte_flow_item_##type##_mask.fld; \ 284 spec = ((const struct rte_flow_item_##type *)s)->fld; \ 285 } while (0) 286 287 enum rte_flow_item_type ret; 288 uint16_t spec, mask; 289 290 if (item == NULL || item->spec == NULL) 291 return RTE_FLOW_ITEM_TYPE_VOID; 292 switch (item->type) { 293 case RTE_FLOW_ITEM_TYPE_ETH: 294 MLX5_XSET_ITEM_MASK_SPEC(eth, type); 295 if (!mask) 296 return RTE_FLOW_ITEM_TYPE_VOID; 297 ret = mlx5_ethertype_to_item_type(spec, mask, false); 298 break; 299 case RTE_FLOW_ITEM_TYPE_VLAN: 300 MLX5_XSET_ITEM_MASK_SPEC(vlan, inner_type); 301 if (!mask) 302 return RTE_FLOW_ITEM_TYPE_VOID; 303 ret = mlx5_ethertype_to_item_type(spec, mask, false); 304 break; 305 case RTE_FLOW_ITEM_TYPE_IPV4: 306 MLX5_XSET_ITEM_MASK_SPEC(ipv4, hdr.next_proto_id); 307 if (!mask) 308 return RTE_FLOW_ITEM_TYPE_VOID; 309 ret = mlx5_inet_proto_to_item_type(spec, mask); 310 break; 311 case RTE_FLOW_ITEM_TYPE_IPV6: 312 MLX5_XSET_ITEM_MASK_SPEC(ipv6, hdr.proto); 313 if (!mask) 314 return RTE_FLOW_ITEM_TYPE_VOID; 315 ret = mlx5_inet_proto_to_item_type(spec, mask); 316 break; 317 case RTE_FLOW_ITEM_TYPE_GENEVE: 318 MLX5_XSET_ITEM_MASK_SPEC(geneve, protocol); 319 ret = mlx5_ethertype_to_item_type(spec, mask, true); 320 break; 321 case RTE_FLOW_ITEM_TYPE_GRE: 322 MLX5_XSET_ITEM_MASK_SPEC(gre, protocol); 323 ret = mlx5_ethertype_to_item_type(spec, mask, true); 324 break; 325 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 326 MLX5_XSET_ITEM_MASK_SPEC(vxlan_gpe, protocol); 327 ret = mlx5_nsh_proto_to_item_type(spec, mask); 328 break; 329 default: 330 ret = RTE_FLOW_ITEM_TYPE_VOID; 331 break; 332 } 333 return ret; 334 #undef MLX5_XSET_ITEM_MASK_SPEC 335 } 336 337 static const int * 338 mlx5_flow_expand_rss_skip_explicit(const struct mlx5_flow_expand_node graph[], 339 const int *next_node) 340 { 341 const struct mlx5_flow_expand_node *node = NULL; 342 const int *next = next_node; 343 344 while (next && *next) { 345 /* 346 * Skip the nodes with the MLX5_EXPANSION_NODE_EXPLICIT 347 * flag set, because they were not found in the flow pattern. 348 */ 349 node = &graph[*next]; 350 if (!(node->node_flags & MLX5_EXPANSION_NODE_EXPLICIT)) 351 break; 352 next = node->next; 353 } 354 return next; 355 } 356 357 #define MLX5_RSS_EXP_ELT_N 16 358 359 /** 360 * Expand RSS flows into several possible flows according to the RSS hash 361 * fields requested and the driver capabilities. 362 * 363 * @param[out] buf 364 * Buffer to store the result expansion. 365 * @param[in] size 366 * Buffer size in bytes. If 0, @p buf can be NULL. 367 * @param[in] pattern 368 * User flow pattern. 369 * @param[in] types 370 * RSS types to expand (see RTE_ETH_RSS_* definitions). 371 * @param[in] graph 372 * Input graph to expand @p pattern according to @p types. 373 * @param[in] graph_root_index 374 * Index of root node in @p graph, typically 0. 375 * 376 * @return 377 * A positive value representing the size of @p buf in bytes regardless of 378 * @p size on success, a negative errno value otherwise and rte_errno is 379 * set, the following errors are defined: 380 * 381 * -E2BIG: graph-depth @p graph is too deep. 382 * -EINVAL: @p size has not enough space for expanded pattern. 383 */ 384 static int 385 mlx5_flow_expand_rss(struct mlx5_flow_expand_rss *buf, size_t size, 386 const struct rte_flow_item *pattern, uint64_t types, 387 const struct mlx5_flow_expand_node graph[], 388 int graph_root_index) 389 { 390 const struct rte_flow_item *item; 391 const struct mlx5_flow_expand_node *node = &graph[graph_root_index]; 392 const int *next_node; 393 const int *stack[MLX5_RSS_EXP_ELT_N]; 394 int stack_pos = 0; 395 struct rte_flow_item flow_items[MLX5_RSS_EXP_ELT_N]; 396 unsigned int i, item_idx, last_expand_item_idx = 0; 397 size_t lsize; 398 size_t user_pattern_size = 0; 399 void *addr = NULL; 400 const struct mlx5_flow_expand_node *next = NULL; 401 struct rte_flow_item missed_item; 402 int missed = 0; 403 int elt = 0; 404 const struct rte_flow_item *last_expand_item = NULL; 405 406 memset(&missed_item, 0, sizeof(missed_item)); 407 lsize = offsetof(struct mlx5_flow_expand_rss, entry) + 408 MLX5_RSS_EXP_ELT_N * sizeof(buf->entry[0]); 409 if (lsize > size) 410 return -EINVAL; 411 buf->entry[0].priority = 0; 412 buf->entry[0].pattern = (void *)&buf->entry[MLX5_RSS_EXP_ELT_N]; 413 buf->entries = 0; 414 addr = buf->entry[0].pattern; 415 for (item = pattern, item_idx = 0; 416 item->type != RTE_FLOW_ITEM_TYPE_END; 417 item++, item_idx++) { 418 if (!mlx5_flow_is_rss_expandable_item(item)) { 419 user_pattern_size += sizeof(*item); 420 continue; 421 } 422 last_expand_item = item; 423 last_expand_item_idx = item_idx; 424 i = 0; 425 while (node->next && node->next[i]) { 426 next = &graph[node->next[i]]; 427 if (next->type == item->type) 428 break; 429 if (next->node_flags & MLX5_EXPANSION_NODE_EXPLICIT) { 430 node = next; 431 i = 0; 432 } else { 433 ++i; 434 } 435 } 436 if (next) 437 node = next; 438 user_pattern_size += sizeof(*item); 439 } 440 user_pattern_size += sizeof(*item); /* Handle END item. */ 441 lsize += user_pattern_size; 442 if (lsize > size) 443 return -EINVAL; 444 /* Copy the user pattern in the first entry of the buffer. */ 445 rte_memcpy(addr, pattern, user_pattern_size); 446 addr = (void *)(((uintptr_t)addr) + user_pattern_size); 447 buf->entries = 1; 448 /* Start expanding. */ 449 memset(flow_items, 0, sizeof(flow_items)); 450 user_pattern_size -= sizeof(*item); 451 /* 452 * Check if the last valid item has spec set, need complete pattern, 453 * and the pattern can be used for expansion. 454 */ 455 missed_item.type = mlx5_flow_expand_rss_item_complete(last_expand_item); 456 if (missed_item.type == RTE_FLOW_ITEM_TYPE_END) { 457 /* Item type END indicates expansion is not required. */ 458 return lsize; 459 } 460 if (missed_item.type != RTE_FLOW_ITEM_TYPE_VOID) { 461 next = NULL; 462 missed = 1; 463 i = 0; 464 while (node->next && node->next[i]) { 465 next = &graph[node->next[i]]; 466 if (next->type == missed_item.type) { 467 flow_items[0].type = missed_item.type; 468 flow_items[1].type = RTE_FLOW_ITEM_TYPE_END; 469 break; 470 } 471 if (next->node_flags & MLX5_EXPANSION_NODE_EXPLICIT) { 472 node = next; 473 i = 0; 474 } else { 475 ++i; 476 } 477 next = NULL; 478 } 479 } 480 if (next && missed) { 481 elt = 2; /* missed item + item end. */ 482 node = next; 483 lsize += elt * sizeof(*item) + user_pattern_size; 484 if (lsize > size) 485 return -EINVAL; 486 if (node->rss_types & types) { 487 buf->entry[buf->entries].priority = 1; 488 buf->entry[buf->entries].pattern = addr; 489 buf->entries++; 490 rte_memcpy(addr, buf->entry[0].pattern, 491 user_pattern_size); 492 addr = (void *)(((uintptr_t)addr) + user_pattern_size); 493 rte_memcpy(addr, flow_items, elt * sizeof(*item)); 494 addr = (void *)(((uintptr_t)addr) + 495 elt * sizeof(*item)); 496 } 497 } else if (last_expand_item != NULL) { 498 node = mlx5_flow_expand_rss_adjust_node(pattern, 499 last_expand_item_idx, graph, node); 500 } 501 memset(flow_items, 0, sizeof(flow_items)); 502 next_node = mlx5_flow_expand_rss_skip_explicit(graph, 503 node->next); 504 stack[stack_pos] = next_node; 505 node = next_node ? &graph[*next_node] : NULL; 506 while (node) { 507 flow_items[stack_pos].type = node->type; 508 if (node->rss_types & types) { 509 size_t n; 510 /* 511 * compute the number of items to copy from the 512 * expansion and copy it. 513 * When the stack_pos is 0, there are 1 element in it, 514 * plus the addition END item. 515 */ 516 elt = stack_pos + 2; 517 flow_items[stack_pos + 1].type = RTE_FLOW_ITEM_TYPE_END; 518 lsize += elt * sizeof(*item) + user_pattern_size; 519 if (lsize > size) 520 return -EINVAL; 521 n = elt * sizeof(*item); 522 buf->entry[buf->entries].priority = 523 stack_pos + 1 + missed; 524 buf->entry[buf->entries].pattern = addr; 525 buf->entries++; 526 rte_memcpy(addr, buf->entry[0].pattern, 527 user_pattern_size); 528 addr = (void *)(((uintptr_t)addr) + 529 user_pattern_size); 530 rte_memcpy(addr, &missed_item, 531 missed * sizeof(*item)); 532 addr = (void *)(((uintptr_t)addr) + 533 missed * sizeof(*item)); 534 rte_memcpy(addr, flow_items, n); 535 addr = (void *)(((uintptr_t)addr) + n); 536 } 537 /* Go deeper. */ 538 if (!(node->node_flags & MLX5_EXPANSION_NODE_OPTIONAL) && 539 node->next) { 540 next_node = mlx5_flow_expand_rss_skip_explicit(graph, 541 node->next); 542 if (stack_pos++ == MLX5_RSS_EXP_ELT_N) { 543 rte_errno = E2BIG; 544 return -rte_errno; 545 } 546 stack[stack_pos] = next_node; 547 } else if (*(next_node + 1)) { 548 /* Follow up with the next possibility. */ 549 next_node = mlx5_flow_expand_rss_skip_explicit(graph, 550 ++next_node); 551 } else if (!stack_pos) { 552 /* 553 * Completing the traverse over the different paths. 554 * The next_node is advanced to the terminator. 555 */ 556 ++next_node; 557 } else { 558 /* Move to the next path. */ 559 while (stack_pos) { 560 next_node = stack[--stack_pos]; 561 next_node++; 562 if (*next_node) 563 break; 564 } 565 next_node = mlx5_flow_expand_rss_skip_explicit(graph, 566 next_node); 567 stack[stack_pos] = next_node; 568 } 569 node = next_node && *next_node ? &graph[*next_node] : NULL; 570 }; 571 return lsize; 572 } 573 574 enum mlx5_expansion { 575 MLX5_EXPANSION_ROOT, 576 MLX5_EXPANSION_ROOT_OUTER, 577 MLX5_EXPANSION_OUTER_ETH, 578 MLX5_EXPANSION_OUTER_VLAN, 579 MLX5_EXPANSION_OUTER_IPV4, 580 MLX5_EXPANSION_OUTER_IPV4_UDP, 581 MLX5_EXPANSION_OUTER_IPV4_TCP, 582 MLX5_EXPANSION_OUTER_IPV4_ESP, 583 MLX5_EXPANSION_OUTER_IPV4_ICMP, 584 MLX5_EXPANSION_OUTER_IPV6, 585 MLX5_EXPANSION_OUTER_IPV6_UDP, 586 MLX5_EXPANSION_OUTER_IPV6_TCP, 587 MLX5_EXPANSION_OUTER_IPV6_ESP, 588 MLX5_EXPANSION_OUTER_IPV6_ICMP6, 589 MLX5_EXPANSION_VXLAN, 590 MLX5_EXPANSION_STD_VXLAN, 591 MLX5_EXPANSION_L3_VXLAN, 592 MLX5_EXPANSION_VXLAN_GPE, 593 MLX5_EXPANSION_GRE, 594 MLX5_EXPANSION_NVGRE, 595 MLX5_EXPANSION_GRE_KEY, 596 MLX5_EXPANSION_MPLS, 597 MLX5_EXPANSION_ETH, 598 MLX5_EXPANSION_VLAN, 599 MLX5_EXPANSION_IPV4, 600 MLX5_EXPANSION_IPV4_UDP, 601 MLX5_EXPANSION_IPV4_TCP, 602 MLX5_EXPANSION_IPV4_ESP, 603 MLX5_EXPANSION_IPV4_ICMP, 604 MLX5_EXPANSION_IPV6, 605 MLX5_EXPANSION_IPV6_UDP, 606 MLX5_EXPANSION_IPV6_TCP, 607 MLX5_EXPANSION_IPV6_ESP, 608 MLX5_EXPANSION_IPV6_ICMP6, 609 MLX5_EXPANSION_IPV6_FRAG_EXT, 610 MLX5_EXPANSION_GTP, 611 MLX5_EXPANSION_GENEVE, 612 }; 613 614 /** Supported expansion of items. */ 615 static const struct mlx5_flow_expand_node mlx5_support_expansion[] = { 616 [MLX5_EXPANSION_ROOT] = { 617 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 618 MLX5_EXPANSION_IPV4, 619 MLX5_EXPANSION_IPV6), 620 .type = RTE_FLOW_ITEM_TYPE_END, 621 }, 622 [MLX5_EXPANSION_ROOT_OUTER] = { 623 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_ETH, 624 MLX5_EXPANSION_OUTER_IPV4, 625 MLX5_EXPANSION_OUTER_IPV6), 626 .type = RTE_FLOW_ITEM_TYPE_END, 627 }, 628 [MLX5_EXPANSION_OUTER_ETH] = { 629 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_VLAN), 630 .type = RTE_FLOW_ITEM_TYPE_ETH, 631 .rss_types = 0, 632 }, 633 [MLX5_EXPANSION_OUTER_VLAN] = { 634 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4, 635 MLX5_EXPANSION_OUTER_IPV6), 636 .type = RTE_FLOW_ITEM_TYPE_VLAN, 637 .node_flags = MLX5_EXPANSION_NODE_EXPLICIT, 638 }, 639 [MLX5_EXPANSION_OUTER_IPV4] = { 640 .next = MLX5_FLOW_EXPAND_RSS_NEXT 641 (MLX5_EXPANSION_OUTER_IPV4_UDP, 642 MLX5_EXPANSION_OUTER_IPV4_TCP, 643 MLX5_EXPANSION_OUTER_IPV4_ESP, 644 MLX5_EXPANSION_OUTER_IPV4_ICMP, 645 MLX5_EXPANSION_GRE, 646 MLX5_EXPANSION_NVGRE, 647 MLX5_EXPANSION_IPV4, 648 MLX5_EXPANSION_IPV6), 649 .type = RTE_FLOW_ITEM_TYPE_IPV4, 650 .rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | 651 RTE_ETH_RSS_NONFRAG_IPV4_OTHER, 652 }, 653 [MLX5_EXPANSION_OUTER_IPV4_UDP] = { 654 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN, 655 MLX5_EXPANSION_VXLAN_GPE, 656 MLX5_EXPANSION_MPLS, 657 MLX5_EXPANSION_GENEVE, 658 MLX5_EXPANSION_GTP), 659 .type = RTE_FLOW_ITEM_TYPE_UDP, 660 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_UDP, 661 }, 662 [MLX5_EXPANSION_OUTER_IPV4_TCP] = { 663 .type = RTE_FLOW_ITEM_TYPE_TCP, 664 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP, 665 }, 666 [MLX5_EXPANSION_OUTER_IPV4_ESP] = { 667 .type = RTE_FLOW_ITEM_TYPE_ESP, 668 .rss_types = RTE_ETH_RSS_ESP, 669 }, 670 [MLX5_EXPANSION_OUTER_IPV4_ICMP] = { 671 .type = RTE_FLOW_ITEM_TYPE_ICMP, 672 }, 673 [MLX5_EXPANSION_OUTER_IPV6] = { 674 .next = MLX5_FLOW_EXPAND_RSS_NEXT 675 (MLX5_EXPANSION_OUTER_IPV6_UDP, 676 MLX5_EXPANSION_OUTER_IPV6_TCP, 677 MLX5_EXPANSION_OUTER_IPV6_ESP, 678 MLX5_EXPANSION_OUTER_IPV6_ICMP6, 679 MLX5_EXPANSION_IPV4, 680 MLX5_EXPANSION_IPV6, 681 MLX5_EXPANSION_GRE, 682 MLX5_EXPANSION_NVGRE), 683 .type = RTE_FLOW_ITEM_TYPE_IPV6, 684 .rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | 685 RTE_ETH_RSS_NONFRAG_IPV6_OTHER, 686 }, 687 [MLX5_EXPANSION_OUTER_IPV6_UDP] = { 688 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN, 689 MLX5_EXPANSION_VXLAN_GPE, 690 MLX5_EXPANSION_MPLS, 691 MLX5_EXPANSION_GENEVE, 692 MLX5_EXPANSION_GTP), 693 .type = RTE_FLOW_ITEM_TYPE_UDP, 694 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_UDP, 695 }, 696 [MLX5_EXPANSION_OUTER_IPV6_TCP] = { 697 .type = RTE_FLOW_ITEM_TYPE_TCP, 698 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP, 699 }, 700 [MLX5_EXPANSION_OUTER_IPV6_ESP] = { 701 .type = RTE_FLOW_ITEM_TYPE_ESP, 702 .rss_types = RTE_ETH_RSS_ESP, 703 }, 704 [MLX5_EXPANSION_OUTER_IPV6_ICMP6] = { 705 .type = RTE_FLOW_ITEM_TYPE_ICMP6, 706 }, 707 [MLX5_EXPANSION_VXLAN] = { 708 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 709 MLX5_EXPANSION_IPV4, 710 MLX5_EXPANSION_IPV6), 711 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 712 }, 713 [MLX5_EXPANSION_STD_VXLAN] = { 714 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH), 715 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 716 }, 717 [MLX5_EXPANSION_L3_VXLAN] = { 718 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 719 MLX5_EXPANSION_IPV6), 720 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 721 }, 722 [MLX5_EXPANSION_VXLAN_GPE] = { 723 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 724 MLX5_EXPANSION_IPV4, 725 MLX5_EXPANSION_IPV6), 726 .type = RTE_FLOW_ITEM_TYPE_VXLAN_GPE, 727 }, 728 [MLX5_EXPANSION_GRE] = { 729 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 730 MLX5_EXPANSION_IPV4, 731 MLX5_EXPANSION_IPV6, 732 MLX5_EXPANSION_GRE_KEY, 733 MLX5_EXPANSION_MPLS), 734 .type = RTE_FLOW_ITEM_TYPE_GRE, 735 }, 736 [MLX5_EXPANSION_GRE_KEY] = { 737 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 738 MLX5_EXPANSION_IPV6, 739 MLX5_EXPANSION_MPLS), 740 .type = RTE_FLOW_ITEM_TYPE_GRE_KEY, 741 .node_flags = MLX5_EXPANSION_NODE_OPTIONAL, 742 }, 743 [MLX5_EXPANSION_NVGRE] = { 744 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH), 745 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 746 }, 747 [MLX5_EXPANSION_MPLS] = { 748 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 749 MLX5_EXPANSION_IPV6, 750 MLX5_EXPANSION_ETH), 751 .type = RTE_FLOW_ITEM_TYPE_MPLS, 752 .node_flags = MLX5_EXPANSION_NODE_OPTIONAL, 753 }, 754 [MLX5_EXPANSION_ETH] = { 755 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VLAN), 756 .type = RTE_FLOW_ITEM_TYPE_ETH, 757 }, 758 [MLX5_EXPANSION_VLAN] = { 759 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 760 MLX5_EXPANSION_IPV6), 761 .type = RTE_FLOW_ITEM_TYPE_VLAN, 762 .node_flags = MLX5_EXPANSION_NODE_EXPLICIT, 763 }, 764 [MLX5_EXPANSION_IPV4] = { 765 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP, 766 MLX5_EXPANSION_IPV4_TCP, 767 MLX5_EXPANSION_IPV4_ESP, 768 MLX5_EXPANSION_IPV4_ICMP), 769 .type = RTE_FLOW_ITEM_TYPE_IPV4, 770 .rss_types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 | 771 RTE_ETH_RSS_NONFRAG_IPV4_OTHER, 772 }, 773 [MLX5_EXPANSION_IPV4_UDP] = { 774 .type = RTE_FLOW_ITEM_TYPE_UDP, 775 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_UDP, 776 }, 777 [MLX5_EXPANSION_IPV4_TCP] = { 778 .type = RTE_FLOW_ITEM_TYPE_TCP, 779 .rss_types = RTE_ETH_RSS_NONFRAG_IPV4_TCP, 780 }, 781 [MLX5_EXPANSION_IPV4_ESP] = { 782 .type = RTE_FLOW_ITEM_TYPE_ESP, 783 .rss_types = RTE_ETH_RSS_ESP, 784 }, 785 [MLX5_EXPANSION_IPV4_ICMP] = { 786 .type = RTE_FLOW_ITEM_TYPE_ICMP, 787 }, 788 [MLX5_EXPANSION_IPV6] = { 789 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP, 790 MLX5_EXPANSION_IPV6_TCP, 791 MLX5_EXPANSION_IPV6_ESP, 792 MLX5_EXPANSION_IPV6_ICMP6, 793 MLX5_EXPANSION_IPV6_FRAG_EXT), 794 .type = RTE_FLOW_ITEM_TYPE_IPV6, 795 .rss_types = RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6 | 796 RTE_ETH_RSS_NONFRAG_IPV6_OTHER, 797 }, 798 [MLX5_EXPANSION_IPV6_UDP] = { 799 .type = RTE_FLOW_ITEM_TYPE_UDP, 800 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_UDP, 801 }, 802 [MLX5_EXPANSION_IPV6_TCP] = { 803 .type = RTE_FLOW_ITEM_TYPE_TCP, 804 .rss_types = RTE_ETH_RSS_NONFRAG_IPV6_TCP, 805 }, 806 [MLX5_EXPANSION_IPV6_ESP] = { 807 .type = RTE_FLOW_ITEM_TYPE_ESP, 808 .rss_types = RTE_ETH_RSS_ESP, 809 }, 810 [MLX5_EXPANSION_IPV6_FRAG_EXT] = { 811 .type = RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT, 812 }, 813 [MLX5_EXPANSION_IPV6_ICMP6] = { 814 .type = RTE_FLOW_ITEM_TYPE_ICMP6, 815 }, 816 [MLX5_EXPANSION_GTP] = { 817 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 818 MLX5_EXPANSION_IPV6), 819 .type = RTE_FLOW_ITEM_TYPE_GTP, 820 }, 821 [MLX5_EXPANSION_GENEVE] = { 822 .next = MLX5_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 823 MLX5_EXPANSION_IPV4, 824 MLX5_EXPANSION_IPV6), 825 .type = RTE_FLOW_ITEM_TYPE_GENEVE, 826 }, 827 }; 828 829 static struct rte_flow_action_handle * 830 mlx5_action_handle_create(struct rte_eth_dev *dev, 831 const struct rte_flow_indir_action_conf *conf, 832 const struct rte_flow_action *action, 833 struct rte_flow_error *error); 834 static int mlx5_action_handle_destroy 835 (struct rte_eth_dev *dev, 836 struct rte_flow_action_handle *handle, 837 struct rte_flow_error *error); 838 static int mlx5_action_handle_update 839 (struct rte_eth_dev *dev, 840 struct rte_flow_action_handle *handle, 841 const void *update, 842 struct rte_flow_error *error); 843 static int mlx5_action_handle_query 844 (struct rte_eth_dev *dev, 845 const struct rte_flow_action_handle *handle, 846 void *data, 847 struct rte_flow_error *error); 848 static int 849 mlx5_flow_tunnel_decap_set(struct rte_eth_dev *dev, 850 struct rte_flow_tunnel *app_tunnel, 851 struct rte_flow_action **actions, 852 uint32_t *num_of_actions, 853 struct rte_flow_error *error); 854 static int 855 mlx5_flow_tunnel_match(struct rte_eth_dev *dev, 856 struct rte_flow_tunnel *app_tunnel, 857 struct rte_flow_item **items, 858 uint32_t *num_of_items, 859 struct rte_flow_error *error); 860 static int 861 mlx5_flow_tunnel_item_release(struct rte_eth_dev *dev, 862 struct rte_flow_item *pmd_items, 863 uint32_t num_items, struct rte_flow_error *err); 864 static int 865 mlx5_flow_tunnel_action_release(struct rte_eth_dev *dev, 866 struct rte_flow_action *pmd_actions, 867 uint32_t num_actions, 868 struct rte_flow_error *err); 869 static int 870 mlx5_flow_tunnel_get_restore_info(struct rte_eth_dev *dev, 871 struct rte_mbuf *m, 872 struct rte_flow_restore_info *info, 873 struct rte_flow_error *err); 874 static struct rte_flow_item_flex_handle * 875 mlx5_flow_flex_item_create(struct rte_eth_dev *dev, 876 const struct rte_flow_item_flex_conf *conf, 877 struct rte_flow_error *error); 878 static int 879 mlx5_flow_flex_item_release(struct rte_eth_dev *dev, 880 const struct rte_flow_item_flex_handle *handle, 881 struct rte_flow_error *error); 882 static int 883 mlx5_flow_info_get(struct rte_eth_dev *dev, 884 struct rte_flow_port_info *port_info, 885 struct rte_flow_queue_info *queue_info, 886 struct rte_flow_error *error); 887 static int 888 mlx5_flow_port_configure(struct rte_eth_dev *dev, 889 const struct rte_flow_port_attr *port_attr, 890 uint16_t nb_queue, 891 const struct rte_flow_queue_attr *queue_attr[], 892 struct rte_flow_error *err); 893 894 static struct rte_flow_pattern_template * 895 mlx5_flow_pattern_template_create(struct rte_eth_dev *dev, 896 const struct rte_flow_pattern_template_attr *attr, 897 const struct rte_flow_item items[], 898 struct rte_flow_error *error); 899 900 static int 901 mlx5_flow_pattern_template_destroy(struct rte_eth_dev *dev, 902 struct rte_flow_pattern_template *template, 903 struct rte_flow_error *error); 904 static struct rte_flow_actions_template * 905 mlx5_flow_actions_template_create(struct rte_eth_dev *dev, 906 const struct rte_flow_actions_template_attr *attr, 907 const struct rte_flow_action actions[], 908 const struct rte_flow_action masks[], 909 struct rte_flow_error *error); 910 static int 911 mlx5_flow_actions_template_destroy(struct rte_eth_dev *dev, 912 struct rte_flow_actions_template *template, 913 struct rte_flow_error *error); 914 915 static struct rte_flow_template_table * 916 mlx5_flow_table_create(struct rte_eth_dev *dev, 917 const struct rte_flow_template_table_attr *attr, 918 struct rte_flow_pattern_template *item_templates[], 919 uint8_t nb_item_templates, 920 struct rte_flow_actions_template *action_templates[], 921 uint8_t nb_action_templates, 922 struct rte_flow_error *error); 923 static int 924 mlx5_flow_table_destroy(struct rte_eth_dev *dev, 925 struct rte_flow_template_table *table, 926 struct rte_flow_error *error); 927 static struct rte_flow * 928 mlx5_flow_async_flow_create(struct rte_eth_dev *dev, 929 uint32_t queue, 930 const struct rte_flow_op_attr *attr, 931 struct rte_flow_template_table *table, 932 const struct rte_flow_item items[], 933 uint8_t pattern_template_index, 934 const struct rte_flow_action actions[], 935 uint8_t action_template_index, 936 void *user_data, 937 struct rte_flow_error *error); 938 static int 939 mlx5_flow_async_flow_destroy(struct rte_eth_dev *dev, 940 uint32_t queue, 941 const struct rte_flow_op_attr *attr, 942 struct rte_flow *flow, 943 void *user_data, 944 struct rte_flow_error *error); 945 static int 946 mlx5_flow_pull(struct rte_eth_dev *dev, 947 uint32_t queue, 948 struct rte_flow_op_result res[], 949 uint16_t n_res, 950 struct rte_flow_error *error); 951 static int 952 mlx5_flow_push(struct rte_eth_dev *dev, 953 uint32_t queue, 954 struct rte_flow_error *error); 955 956 static struct rte_flow_action_handle * 957 mlx5_flow_async_action_handle_create(struct rte_eth_dev *dev, uint32_t queue, 958 const struct rte_flow_op_attr *attr, 959 const struct rte_flow_indir_action_conf *conf, 960 const struct rte_flow_action *action, 961 void *user_data, 962 struct rte_flow_error *error); 963 964 static int 965 mlx5_flow_async_action_handle_update(struct rte_eth_dev *dev, uint32_t queue, 966 const struct rte_flow_op_attr *attr, 967 struct rte_flow_action_handle *handle, 968 const void *update, 969 void *user_data, 970 struct rte_flow_error *error); 971 972 static int 973 mlx5_flow_async_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue, 974 const struct rte_flow_op_attr *attr, 975 struct rte_flow_action_handle *handle, 976 void *user_data, 977 struct rte_flow_error *error); 978 979 static const struct rte_flow_ops mlx5_flow_ops = { 980 .validate = mlx5_flow_validate, 981 .create = mlx5_flow_create, 982 .destroy = mlx5_flow_destroy, 983 .flush = mlx5_flow_flush, 984 .isolate = mlx5_flow_isolate, 985 .query = mlx5_flow_query, 986 .dev_dump = mlx5_flow_dev_dump, 987 .get_aged_flows = mlx5_flow_get_aged_flows, 988 .action_handle_create = mlx5_action_handle_create, 989 .action_handle_destroy = mlx5_action_handle_destroy, 990 .action_handle_update = mlx5_action_handle_update, 991 .action_handle_query = mlx5_action_handle_query, 992 .tunnel_decap_set = mlx5_flow_tunnel_decap_set, 993 .tunnel_match = mlx5_flow_tunnel_match, 994 .tunnel_action_decap_release = mlx5_flow_tunnel_action_release, 995 .tunnel_item_release = mlx5_flow_tunnel_item_release, 996 .get_restore_info = mlx5_flow_tunnel_get_restore_info, 997 .flex_item_create = mlx5_flow_flex_item_create, 998 .flex_item_release = mlx5_flow_flex_item_release, 999 .info_get = mlx5_flow_info_get, 1000 .configure = mlx5_flow_port_configure, 1001 .pattern_template_create = mlx5_flow_pattern_template_create, 1002 .pattern_template_destroy = mlx5_flow_pattern_template_destroy, 1003 .actions_template_create = mlx5_flow_actions_template_create, 1004 .actions_template_destroy = mlx5_flow_actions_template_destroy, 1005 .template_table_create = mlx5_flow_table_create, 1006 .template_table_destroy = mlx5_flow_table_destroy, 1007 .async_create = mlx5_flow_async_flow_create, 1008 .async_destroy = mlx5_flow_async_flow_destroy, 1009 .pull = mlx5_flow_pull, 1010 .push = mlx5_flow_push, 1011 .async_action_handle_create = mlx5_flow_async_action_handle_create, 1012 .async_action_handle_update = mlx5_flow_async_action_handle_update, 1013 .async_action_handle_destroy = mlx5_flow_async_action_handle_destroy, 1014 }; 1015 1016 /* Tunnel information. */ 1017 struct mlx5_flow_tunnel_info { 1018 uint64_t tunnel; /**< Tunnel bit (see MLX5_FLOW_*). */ 1019 uint32_t ptype; /**< Tunnel Ptype (see RTE_PTYPE_*). */ 1020 }; 1021 1022 static struct mlx5_flow_tunnel_info tunnels_info[] = { 1023 { 1024 .tunnel = MLX5_FLOW_LAYER_VXLAN, 1025 .ptype = RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_L4_UDP, 1026 }, 1027 { 1028 .tunnel = MLX5_FLOW_LAYER_GENEVE, 1029 .ptype = RTE_PTYPE_TUNNEL_GENEVE | RTE_PTYPE_L4_UDP, 1030 }, 1031 { 1032 .tunnel = MLX5_FLOW_LAYER_VXLAN_GPE, 1033 .ptype = RTE_PTYPE_TUNNEL_VXLAN_GPE | RTE_PTYPE_L4_UDP, 1034 }, 1035 { 1036 .tunnel = MLX5_FLOW_LAYER_GRE, 1037 .ptype = RTE_PTYPE_TUNNEL_GRE, 1038 }, 1039 { 1040 .tunnel = MLX5_FLOW_LAYER_MPLS | MLX5_FLOW_LAYER_OUTER_L4_UDP, 1041 .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_UDP | RTE_PTYPE_L4_UDP, 1042 }, 1043 { 1044 .tunnel = MLX5_FLOW_LAYER_MPLS, 1045 .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_GRE, 1046 }, 1047 { 1048 .tunnel = MLX5_FLOW_LAYER_NVGRE, 1049 .ptype = RTE_PTYPE_TUNNEL_NVGRE, 1050 }, 1051 { 1052 .tunnel = MLX5_FLOW_LAYER_IPIP, 1053 .ptype = RTE_PTYPE_TUNNEL_IP, 1054 }, 1055 { 1056 .tunnel = MLX5_FLOW_LAYER_IPV6_ENCAP, 1057 .ptype = RTE_PTYPE_TUNNEL_IP, 1058 }, 1059 { 1060 .tunnel = MLX5_FLOW_LAYER_GTP, 1061 .ptype = RTE_PTYPE_TUNNEL_GTPU, 1062 }, 1063 }; 1064 1065 1066 1067 /** 1068 * Translate tag ID to register. 1069 * 1070 * @param[in] dev 1071 * Pointer to the Ethernet device structure. 1072 * @param[in] feature 1073 * The feature that request the register. 1074 * @param[in] id 1075 * The request register ID. 1076 * @param[out] error 1077 * Error description in case of any. 1078 * 1079 * @return 1080 * The request register on success, a negative errno 1081 * value otherwise and rte_errno is set. 1082 */ 1083 int 1084 mlx5_flow_get_reg_id(struct rte_eth_dev *dev, 1085 enum mlx5_feature_name feature, 1086 uint32_t id, 1087 struct rte_flow_error *error) 1088 { 1089 struct mlx5_priv *priv = dev->data->dev_private; 1090 struct mlx5_sh_config *config = &priv->sh->config; 1091 enum modify_reg start_reg; 1092 bool skip_mtr_reg = false; 1093 1094 switch (feature) { 1095 case MLX5_HAIRPIN_RX: 1096 return REG_B; 1097 case MLX5_HAIRPIN_TX: 1098 return REG_A; 1099 case MLX5_METADATA_RX: 1100 switch (config->dv_xmeta_en) { 1101 case MLX5_XMETA_MODE_LEGACY: 1102 return REG_B; 1103 case MLX5_XMETA_MODE_META16: 1104 return REG_C_0; 1105 case MLX5_XMETA_MODE_META32: 1106 return REG_C_1; 1107 } 1108 break; 1109 case MLX5_METADATA_TX: 1110 return REG_A; 1111 case MLX5_METADATA_FDB: 1112 switch (config->dv_xmeta_en) { 1113 case MLX5_XMETA_MODE_LEGACY: 1114 return REG_NON; 1115 case MLX5_XMETA_MODE_META16: 1116 return REG_C_0; 1117 case MLX5_XMETA_MODE_META32: 1118 return REG_C_1; 1119 } 1120 break; 1121 case MLX5_FLOW_MARK: 1122 switch (config->dv_xmeta_en) { 1123 case MLX5_XMETA_MODE_LEGACY: 1124 return REG_NON; 1125 case MLX5_XMETA_MODE_META16: 1126 return REG_C_1; 1127 case MLX5_XMETA_MODE_META32: 1128 return REG_C_0; 1129 } 1130 break; 1131 case MLX5_MTR_ID: 1132 /* 1133 * If meter color and meter id share one register, flow match 1134 * should use the meter color register for match. 1135 */ 1136 if (priv->mtr_reg_share) 1137 return priv->mtr_color_reg; 1138 else 1139 return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : 1140 REG_C_3; 1141 case MLX5_MTR_COLOR: 1142 case MLX5_ASO_FLOW_HIT: 1143 case MLX5_ASO_CONNTRACK: 1144 case MLX5_SAMPLE_ID: 1145 /* All features use the same REG_C. */ 1146 MLX5_ASSERT(priv->mtr_color_reg != REG_NON); 1147 return priv->mtr_color_reg; 1148 case MLX5_COPY_MARK: 1149 /* 1150 * Metadata COPY_MARK register using is in meter suffix sub 1151 * flow while with meter. It's safe to share the same register. 1152 */ 1153 return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3; 1154 case MLX5_APP_TAG: 1155 /* 1156 * If meter is enable, it will engage the register for color 1157 * match and flow match. If meter color match is not using the 1158 * REG_C_2, need to skip the REG_C_x be used by meter color 1159 * match. 1160 * If meter is disable, free to use all available registers. 1161 */ 1162 start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_2 : 1163 (priv->mtr_reg_share ? REG_C_3 : REG_C_4); 1164 skip_mtr_reg = !!(priv->mtr_en && start_reg == REG_C_2); 1165 if (id > (uint32_t)(REG_C_7 - start_reg)) 1166 return rte_flow_error_set(error, EINVAL, 1167 RTE_FLOW_ERROR_TYPE_ITEM, 1168 NULL, "invalid tag id"); 1169 if (priv->sh->flow_mreg_c[id + start_reg - REG_C_0] == REG_NON) 1170 return rte_flow_error_set(error, ENOTSUP, 1171 RTE_FLOW_ERROR_TYPE_ITEM, 1172 NULL, "unsupported tag id"); 1173 /* 1174 * This case means meter is using the REG_C_x great than 2. 1175 * Take care not to conflict with meter color REG_C_x. 1176 * If the available index REG_C_y >= REG_C_x, skip the 1177 * color register. 1178 */ 1179 if (skip_mtr_reg && priv->sh->flow_mreg_c 1180 [id + start_reg - REG_C_0] >= priv->mtr_color_reg) { 1181 if (id >= (uint32_t)(REG_C_7 - start_reg)) 1182 return rte_flow_error_set(error, EINVAL, 1183 RTE_FLOW_ERROR_TYPE_ITEM, 1184 NULL, "invalid tag id"); 1185 if (priv->sh->flow_mreg_c 1186 [id + 1 + start_reg - REG_C_0] != REG_NON) 1187 return priv->sh->flow_mreg_c 1188 [id + 1 + start_reg - REG_C_0]; 1189 return rte_flow_error_set(error, ENOTSUP, 1190 RTE_FLOW_ERROR_TYPE_ITEM, 1191 NULL, "unsupported tag id"); 1192 } 1193 return priv->sh->flow_mreg_c[id + start_reg - REG_C_0]; 1194 } 1195 MLX5_ASSERT(false); 1196 return rte_flow_error_set(error, EINVAL, 1197 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 1198 NULL, "invalid feature name"); 1199 } 1200 1201 /** 1202 * Check extensive flow metadata register support. 1203 * 1204 * @param dev 1205 * Pointer to rte_eth_dev structure. 1206 * 1207 * @return 1208 * True if device supports extensive flow metadata register, otherwise false. 1209 */ 1210 bool 1211 mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev) 1212 { 1213 struct mlx5_priv *priv = dev->data->dev_private; 1214 1215 /* 1216 * Having available reg_c can be regarded inclusively as supporting 1217 * extensive flow metadata register, which could mean, 1218 * - metadata register copy action by modify header. 1219 * - 16 modify header actions is supported. 1220 * - reg_c's are preserved across different domain (FDB and NIC) on 1221 * packet loopback by flow lookup miss. 1222 */ 1223 return priv->sh->flow_mreg_c[2] != REG_NON; 1224 } 1225 1226 /** 1227 * Get the lowest priority. 1228 * 1229 * @param[in] dev 1230 * Pointer to the Ethernet device structure. 1231 * @param[in] attributes 1232 * Pointer to device flow rule attributes. 1233 * 1234 * @return 1235 * The value of lowest priority of flow. 1236 */ 1237 uint32_t 1238 mlx5_get_lowest_priority(struct rte_eth_dev *dev, 1239 const struct rte_flow_attr *attr) 1240 { 1241 struct mlx5_priv *priv = dev->data->dev_private; 1242 1243 if (!attr->group && !attr->transfer) 1244 return priv->sh->flow_max_priority - 2; 1245 return MLX5_NON_ROOT_FLOW_MAX_PRIO - 1; 1246 } 1247 1248 /** 1249 * Calculate matcher priority of the flow. 1250 * 1251 * @param[in] dev 1252 * Pointer to the Ethernet device structure. 1253 * @param[in] attr 1254 * Pointer to device flow rule attributes. 1255 * @param[in] subpriority 1256 * The priority based on the items. 1257 * @param[in] external 1258 * Flow is user flow. 1259 * @return 1260 * The matcher priority of the flow. 1261 */ 1262 uint16_t 1263 mlx5_get_matcher_priority(struct rte_eth_dev *dev, 1264 const struct rte_flow_attr *attr, 1265 uint32_t subpriority, bool external) 1266 { 1267 uint16_t priority = (uint16_t)attr->priority; 1268 struct mlx5_priv *priv = dev->data->dev_private; 1269 1270 if (!attr->group && !attr->transfer) { 1271 if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) 1272 priority = priv->sh->flow_max_priority - 1; 1273 return mlx5_os_flow_adjust_priority(dev, priority, subpriority); 1274 } else if (!external && attr->transfer && attr->group == 0 && 1275 attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) { 1276 return (priv->sh->flow_max_priority - 1) * 3; 1277 } 1278 if (attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR) 1279 priority = MLX5_NON_ROOT_FLOW_MAX_PRIO; 1280 return priority * 3 + subpriority; 1281 } 1282 1283 /** 1284 * Verify the @p item specifications (spec, last, mask) are compatible with the 1285 * NIC capabilities. 1286 * 1287 * @param[in] item 1288 * Item specification. 1289 * @param[in] mask 1290 * @p item->mask or flow default bit-masks. 1291 * @param[in] nic_mask 1292 * Bit-masks covering supported fields by the NIC to compare with user mask. 1293 * @param[in] size 1294 * Bit-masks size in bytes. 1295 * @param[in] range_accepted 1296 * True if range of values is accepted for specific fields, false otherwise. 1297 * @param[out] error 1298 * Pointer to error structure. 1299 * 1300 * @return 1301 * 0 on success, a negative errno value otherwise and rte_errno is set. 1302 */ 1303 int 1304 mlx5_flow_item_acceptable(const struct rte_flow_item *item, 1305 const uint8_t *mask, 1306 const uint8_t *nic_mask, 1307 unsigned int size, 1308 bool range_accepted, 1309 struct rte_flow_error *error) 1310 { 1311 unsigned int i; 1312 1313 MLX5_ASSERT(nic_mask); 1314 for (i = 0; i < size; ++i) 1315 if ((nic_mask[i] | mask[i]) != nic_mask[i]) 1316 return rte_flow_error_set(error, ENOTSUP, 1317 RTE_FLOW_ERROR_TYPE_ITEM, 1318 item, 1319 "mask enables non supported" 1320 " bits"); 1321 if (!item->spec && (item->mask || item->last)) 1322 return rte_flow_error_set(error, EINVAL, 1323 RTE_FLOW_ERROR_TYPE_ITEM, item, 1324 "mask/last without a spec is not" 1325 " supported"); 1326 if (item->spec && item->last && !range_accepted) { 1327 uint8_t spec[size]; 1328 uint8_t last[size]; 1329 unsigned int i; 1330 int ret; 1331 1332 for (i = 0; i < size; ++i) { 1333 spec[i] = ((const uint8_t *)item->spec)[i] & mask[i]; 1334 last[i] = ((const uint8_t *)item->last)[i] & mask[i]; 1335 } 1336 ret = memcmp(spec, last, size); 1337 if (ret != 0) 1338 return rte_flow_error_set(error, EINVAL, 1339 RTE_FLOW_ERROR_TYPE_ITEM, 1340 item, 1341 "range is not valid"); 1342 } 1343 return 0; 1344 } 1345 1346 /** 1347 * Adjust the hash fields according to the @p flow information. 1348 * 1349 * @param[in] dev_flow. 1350 * Pointer to the mlx5_flow. 1351 * @param[in] tunnel 1352 * 1 when the hash field is for a tunnel item. 1353 * @param[in] layer_types 1354 * RTE_ETH_RSS_* types. 1355 * @param[in] hash_fields 1356 * Item hash fields. 1357 * 1358 * @return 1359 * The hash fields that should be used. 1360 */ 1361 uint64_t 1362 mlx5_flow_hashfields_adjust(struct mlx5_flow_rss_desc *rss_desc, 1363 int tunnel __rte_unused, uint64_t layer_types, 1364 uint64_t hash_fields) 1365 { 1366 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 1367 int rss_request_inner = rss_desc->level >= 2; 1368 1369 /* Check RSS hash level for tunnel. */ 1370 if (tunnel && rss_request_inner) 1371 hash_fields |= IBV_RX_HASH_INNER; 1372 else if (tunnel || rss_request_inner) 1373 return 0; 1374 #endif 1375 /* Check if requested layer matches RSS hash fields. */ 1376 if (!(rss_desc->types & layer_types)) 1377 return 0; 1378 return hash_fields; 1379 } 1380 1381 /** 1382 * Lookup and set the ptype in the data Rx part. A single Ptype can be used, 1383 * if several tunnel rules are used on this queue, the tunnel ptype will be 1384 * cleared. 1385 * 1386 * @param rxq_ctrl 1387 * Rx queue to update. 1388 */ 1389 static void 1390 flow_rxq_tunnel_ptype_update(struct mlx5_rxq_ctrl *rxq_ctrl) 1391 { 1392 unsigned int i; 1393 uint32_t tunnel_ptype = 0; 1394 1395 /* Look up for the ptype to use. */ 1396 for (i = 0; i != MLX5_FLOW_TUNNEL; ++i) { 1397 if (!rxq_ctrl->flow_tunnels_n[i]) 1398 continue; 1399 if (!tunnel_ptype) { 1400 tunnel_ptype = tunnels_info[i].ptype; 1401 } else { 1402 tunnel_ptype = 0; 1403 break; 1404 } 1405 } 1406 rxq_ctrl->rxq.tunnel = tunnel_ptype; 1407 } 1408 1409 /** 1410 * Set the Rx queue flags (Mark/Flag and Tunnel Ptypes) according to the device 1411 * flow. 1412 * 1413 * @param[in] dev 1414 * Pointer to the Ethernet device structure. 1415 * @param[in] dev_handle 1416 * Pointer to device flow handle structure. 1417 */ 1418 void 1419 flow_drv_rxq_flags_set(struct rte_eth_dev *dev, 1420 struct mlx5_flow_handle *dev_handle) 1421 { 1422 struct mlx5_priv *priv = dev->data->dev_private; 1423 const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL); 1424 struct mlx5_ind_table_obj *ind_tbl = NULL; 1425 unsigned int i; 1426 1427 if (dev_handle->fate_action == MLX5_FLOW_FATE_QUEUE) { 1428 struct mlx5_hrxq *hrxq; 1429 1430 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], 1431 dev_handle->rix_hrxq); 1432 if (hrxq) 1433 ind_tbl = hrxq->ind_table; 1434 } else if (dev_handle->fate_action == MLX5_FLOW_FATE_SHARED_RSS) { 1435 struct mlx5_shared_action_rss *shared_rss; 1436 1437 shared_rss = mlx5_ipool_get 1438 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 1439 dev_handle->rix_srss); 1440 if (shared_rss) 1441 ind_tbl = shared_rss->ind_tbl; 1442 } 1443 if (!ind_tbl) 1444 return; 1445 for (i = 0; i != ind_tbl->queues_n; ++i) { 1446 int idx = ind_tbl->queues[i]; 1447 struct mlx5_rxq_ctrl *rxq_ctrl; 1448 1449 if (mlx5_is_external_rxq(dev, idx)) 1450 continue; 1451 rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx); 1452 MLX5_ASSERT(rxq_ctrl != NULL); 1453 if (rxq_ctrl == NULL) 1454 continue; 1455 /* 1456 * To support metadata register copy on Tx loopback, 1457 * this must be always enabled (metadata may arive 1458 * from other port - not from local flows only. 1459 */ 1460 if (tunnel) { 1461 unsigned int j; 1462 1463 /* Increase the counter matching the flow. */ 1464 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) { 1465 if ((tunnels_info[j].tunnel & 1466 dev_handle->layers) == 1467 tunnels_info[j].tunnel) { 1468 rxq_ctrl->flow_tunnels_n[j]++; 1469 break; 1470 } 1471 } 1472 flow_rxq_tunnel_ptype_update(rxq_ctrl); 1473 } 1474 } 1475 } 1476 1477 static void 1478 flow_rxq_mark_flag_set(struct rte_eth_dev *dev) 1479 { 1480 struct mlx5_priv *priv = dev->data->dev_private; 1481 struct mlx5_rxq_ctrl *rxq_ctrl; 1482 1483 if (priv->mark_enabled) 1484 return; 1485 LIST_FOREACH(rxq_ctrl, &priv->rxqsctrl, next) { 1486 rxq_ctrl->rxq.mark = 1; 1487 } 1488 priv->mark_enabled = 1; 1489 } 1490 1491 /** 1492 * Set the Rx queue flags (Mark/Flag and Tunnel Ptypes) for a flow 1493 * 1494 * @param[in] dev 1495 * Pointer to the Ethernet device structure. 1496 * @param[in] flow 1497 * Pointer to flow structure. 1498 */ 1499 static void 1500 flow_rxq_flags_set(struct rte_eth_dev *dev, struct rte_flow *flow) 1501 { 1502 struct mlx5_priv *priv = dev->data->dev_private; 1503 uint32_t handle_idx; 1504 struct mlx5_flow_handle *dev_handle; 1505 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 1506 1507 MLX5_ASSERT(wks); 1508 if (wks->mark) 1509 flow_rxq_mark_flag_set(dev); 1510 SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 1511 handle_idx, dev_handle, next) 1512 flow_drv_rxq_flags_set(dev, dev_handle); 1513 } 1514 1515 /** 1516 * Clear the Rx queue flags (Mark/Flag and Tunnel Ptype) associated with the 1517 * device flow if no other flow uses it with the same kind of request. 1518 * 1519 * @param dev 1520 * Pointer to Ethernet device. 1521 * @param[in] dev_handle 1522 * Pointer to the device flow handle structure. 1523 */ 1524 static void 1525 flow_drv_rxq_flags_trim(struct rte_eth_dev *dev, 1526 struct mlx5_flow_handle *dev_handle) 1527 { 1528 struct mlx5_priv *priv = dev->data->dev_private; 1529 const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL); 1530 struct mlx5_ind_table_obj *ind_tbl = NULL; 1531 unsigned int i; 1532 1533 if (dev_handle->fate_action == MLX5_FLOW_FATE_QUEUE) { 1534 struct mlx5_hrxq *hrxq; 1535 1536 hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], 1537 dev_handle->rix_hrxq); 1538 if (hrxq) 1539 ind_tbl = hrxq->ind_table; 1540 } else if (dev_handle->fate_action == MLX5_FLOW_FATE_SHARED_RSS) { 1541 struct mlx5_shared_action_rss *shared_rss; 1542 1543 shared_rss = mlx5_ipool_get 1544 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 1545 dev_handle->rix_srss); 1546 if (shared_rss) 1547 ind_tbl = shared_rss->ind_tbl; 1548 } 1549 if (!ind_tbl) 1550 return; 1551 MLX5_ASSERT(dev->data->dev_started); 1552 for (i = 0; i != ind_tbl->queues_n; ++i) { 1553 int idx = ind_tbl->queues[i]; 1554 struct mlx5_rxq_ctrl *rxq_ctrl; 1555 1556 if (mlx5_is_external_rxq(dev, idx)) 1557 continue; 1558 rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx); 1559 MLX5_ASSERT(rxq_ctrl != NULL); 1560 if (rxq_ctrl == NULL) 1561 continue; 1562 if (tunnel) { 1563 unsigned int j; 1564 1565 /* Decrease the counter matching the flow. */ 1566 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) { 1567 if ((tunnels_info[j].tunnel & 1568 dev_handle->layers) == 1569 tunnels_info[j].tunnel) { 1570 rxq_ctrl->flow_tunnels_n[j]--; 1571 break; 1572 } 1573 } 1574 flow_rxq_tunnel_ptype_update(rxq_ctrl); 1575 } 1576 } 1577 } 1578 1579 /** 1580 * Clear the Rx queue flags (Mark/Flag and Tunnel Ptype) associated with the 1581 * @p flow if no other flow uses it with the same kind of request. 1582 * 1583 * @param dev 1584 * Pointer to Ethernet device. 1585 * @param[in] flow 1586 * Pointer to the flow. 1587 */ 1588 static void 1589 flow_rxq_flags_trim(struct rte_eth_dev *dev, struct rte_flow *flow) 1590 { 1591 struct mlx5_priv *priv = dev->data->dev_private; 1592 uint32_t handle_idx; 1593 struct mlx5_flow_handle *dev_handle; 1594 1595 SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles, 1596 handle_idx, dev_handle, next) 1597 flow_drv_rxq_flags_trim(dev, dev_handle); 1598 } 1599 1600 /** 1601 * Clear the Mark/Flag and Tunnel ptype information in all Rx queues. 1602 * 1603 * @param dev 1604 * Pointer to Ethernet device. 1605 */ 1606 static void 1607 flow_rxq_flags_clear(struct rte_eth_dev *dev) 1608 { 1609 struct mlx5_priv *priv = dev->data->dev_private; 1610 unsigned int i; 1611 1612 for (i = 0; i != priv->rxqs_n; ++i) { 1613 struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, i); 1614 unsigned int j; 1615 1616 if (rxq == NULL || rxq->ctrl == NULL) 1617 continue; 1618 rxq->ctrl->rxq.mark = 0; 1619 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) 1620 rxq->ctrl->flow_tunnels_n[j] = 0; 1621 rxq->ctrl->rxq.tunnel = 0; 1622 } 1623 priv->mark_enabled = 0; 1624 } 1625 1626 /** 1627 * Set the Rx queue dynamic metadata (mask and offset) for a flow 1628 * 1629 * @param[in] dev 1630 * Pointer to the Ethernet device structure. 1631 */ 1632 void 1633 mlx5_flow_rxq_dynf_metadata_set(struct rte_eth_dev *dev) 1634 { 1635 struct mlx5_priv *priv = dev->data->dev_private; 1636 unsigned int i; 1637 1638 for (i = 0; i != priv->rxqs_n; ++i) { 1639 struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, i); 1640 struct mlx5_rxq_data *data; 1641 1642 if (rxq == NULL || rxq->ctrl == NULL) 1643 continue; 1644 data = &rxq->ctrl->rxq; 1645 if (!rte_flow_dynf_metadata_avail()) { 1646 data->dynf_meta = 0; 1647 data->flow_meta_mask = 0; 1648 data->flow_meta_offset = -1; 1649 data->flow_meta_port_mask = 0; 1650 } else { 1651 data->dynf_meta = 1; 1652 data->flow_meta_mask = rte_flow_dynf_metadata_mask; 1653 data->flow_meta_offset = rte_flow_dynf_metadata_offs; 1654 data->flow_meta_port_mask = priv->sh->dv_meta_mask; 1655 } 1656 } 1657 } 1658 1659 /* 1660 * return a pointer to the desired action in the list of actions. 1661 * 1662 * @param[in] actions 1663 * The list of actions to search the action in. 1664 * @param[in] action 1665 * The action to find. 1666 * 1667 * @return 1668 * Pointer to the action in the list, if found. NULL otherwise. 1669 */ 1670 const struct rte_flow_action * 1671 mlx5_flow_find_action(const struct rte_flow_action *actions, 1672 enum rte_flow_action_type action) 1673 { 1674 if (actions == NULL) 1675 return NULL; 1676 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) 1677 if (actions->type == action) 1678 return actions; 1679 return NULL; 1680 } 1681 1682 /* 1683 * Validate the flag action. 1684 * 1685 * @param[in] action_flags 1686 * Bit-fields that holds the actions detected until now. 1687 * @param[in] attr 1688 * Attributes of flow that includes this action. 1689 * @param[out] error 1690 * Pointer to error structure. 1691 * 1692 * @return 1693 * 0 on success, a negative errno value otherwise and rte_errno is set. 1694 */ 1695 int 1696 mlx5_flow_validate_action_flag(uint64_t action_flags, 1697 const struct rte_flow_attr *attr, 1698 struct rte_flow_error *error) 1699 { 1700 if (action_flags & MLX5_FLOW_ACTION_MARK) 1701 return rte_flow_error_set(error, EINVAL, 1702 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1703 "can't mark and flag in same flow"); 1704 if (action_flags & MLX5_FLOW_ACTION_FLAG) 1705 return rte_flow_error_set(error, EINVAL, 1706 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1707 "can't have 2 flag" 1708 " actions in same flow"); 1709 if (attr->egress) 1710 return rte_flow_error_set(error, ENOTSUP, 1711 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1712 "flag action not supported for " 1713 "egress"); 1714 return 0; 1715 } 1716 1717 /* 1718 * Validate the mark action. 1719 * 1720 * @param[in] action 1721 * Pointer to the queue action. 1722 * @param[in] action_flags 1723 * Bit-fields that holds the actions detected until now. 1724 * @param[in] attr 1725 * Attributes of flow that includes this action. 1726 * @param[out] error 1727 * Pointer to error structure. 1728 * 1729 * @return 1730 * 0 on success, a negative errno value otherwise and rte_errno is set. 1731 */ 1732 int 1733 mlx5_flow_validate_action_mark(const struct rte_flow_action *action, 1734 uint64_t action_flags, 1735 const struct rte_flow_attr *attr, 1736 struct rte_flow_error *error) 1737 { 1738 const struct rte_flow_action_mark *mark = action->conf; 1739 1740 if (!mark) 1741 return rte_flow_error_set(error, EINVAL, 1742 RTE_FLOW_ERROR_TYPE_ACTION, 1743 action, 1744 "configuration cannot be null"); 1745 if (mark->id >= MLX5_FLOW_MARK_MAX) 1746 return rte_flow_error_set(error, EINVAL, 1747 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1748 &mark->id, 1749 "mark id must in 0 <= id < " 1750 RTE_STR(MLX5_FLOW_MARK_MAX)); 1751 if (action_flags & MLX5_FLOW_ACTION_FLAG) 1752 return rte_flow_error_set(error, EINVAL, 1753 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1754 "can't flag and mark in same flow"); 1755 if (action_flags & MLX5_FLOW_ACTION_MARK) 1756 return rte_flow_error_set(error, EINVAL, 1757 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1758 "can't have 2 mark actions in same" 1759 " flow"); 1760 if (attr->egress) 1761 return rte_flow_error_set(error, ENOTSUP, 1762 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1763 "mark action not supported for " 1764 "egress"); 1765 return 0; 1766 } 1767 1768 /* 1769 * Validate the drop action. 1770 * 1771 * @param[in] action_flags 1772 * Bit-fields that holds the actions detected until now. 1773 * @param[in] attr 1774 * Attributes of flow that includes this action. 1775 * @param[out] error 1776 * Pointer to error structure. 1777 * 1778 * @return 1779 * 0 on success, a negative errno value otherwise and rte_errno is set. 1780 */ 1781 int 1782 mlx5_flow_validate_action_drop(uint64_t action_flags __rte_unused, 1783 const struct rte_flow_attr *attr, 1784 struct rte_flow_error *error) 1785 { 1786 if (attr->egress) 1787 return rte_flow_error_set(error, ENOTSUP, 1788 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1789 "drop action not supported for " 1790 "egress"); 1791 return 0; 1792 } 1793 1794 /* 1795 * Validate the queue action. 1796 * 1797 * @param[in] action 1798 * Pointer to the queue action. 1799 * @param[in] action_flags 1800 * Bit-fields that holds the actions detected until now. 1801 * @param[in] dev 1802 * Pointer to the Ethernet device structure. 1803 * @param[in] attr 1804 * Attributes of flow that includes this action. 1805 * @param[out] error 1806 * Pointer to error structure. 1807 * 1808 * @return 1809 * 0 on success, a negative errno value otherwise and rte_errno is set. 1810 */ 1811 int 1812 mlx5_flow_validate_action_queue(const struct rte_flow_action *action, 1813 uint64_t action_flags, 1814 struct rte_eth_dev *dev, 1815 const struct rte_flow_attr *attr, 1816 struct rte_flow_error *error) 1817 { 1818 struct mlx5_priv *priv = dev->data->dev_private; 1819 const struct rte_flow_action_queue *queue = action->conf; 1820 1821 if (action_flags & MLX5_FLOW_FATE_ACTIONS) 1822 return rte_flow_error_set(error, EINVAL, 1823 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1824 "can't have 2 fate actions in" 1825 " same flow"); 1826 if (attr->egress) 1827 return rte_flow_error_set(error, ENOTSUP, 1828 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1829 "queue action not supported for egress."); 1830 if (mlx5_is_external_rxq(dev, queue->index)) 1831 return 0; 1832 if (!priv->rxqs_n) 1833 return rte_flow_error_set(error, EINVAL, 1834 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1835 NULL, "No Rx queues configured"); 1836 if (queue->index >= priv->rxqs_n) 1837 return rte_flow_error_set(error, EINVAL, 1838 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1839 &queue->index, 1840 "queue index out of range"); 1841 if (mlx5_rxq_get(dev, queue->index) == NULL) 1842 return rte_flow_error_set(error, EINVAL, 1843 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1844 &queue->index, 1845 "queue is not configured"); 1846 return 0; 1847 } 1848 1849 /** 1850 * Validate queue numbers for device RSS. 1851 * 1852 * @param[in] dev 1853 * Configured device. 1854 * @param[in] queues 1855 * Array of queue numbers. 1856 * @param[in] queues_n 1857 * Size of the @p queues array. 1858 * @param[out] error 1859 * On error, filled with a textual error description. 1860 * @param[out] queue_idx 1861 * On error, filled with an offending queue index in @p queues array. 1862 * 1863 * @return 1864 * 0 on success, a negative errno code on error. 1865 */ 1866 static int 1867 mlx5_validate_rss_queues(struct rte_eth_dev *dev, 1868 const uint16_t *queues, uint32_t queues_n, 1869 const char **error, uint32_t *queue_idx) 1870 { 1871 const struct mlx5_priv *priv = dev->data->dev_private; 1872 bool is_hairpin = false; 1873 bool is_ext_rss = false; 1874 uint32_t i; 1875 1876 for (i = 0; i != queues_n; ++i) { 1877 struct mlx5_rxq_ctrl *rxq_ctrl; 1878 1879 if (mlx5_is_external_rxq(dev, queues[0])) { 1880 is_ext_rss = true; 1881 continue; 1882 } 1883 if (is_ext_rss) { 1884 *error = "Combining external and regular RSS queues is not supported"; 1885 *queue_idx = i; 1886 return -ENOTSUP; 1887 } 1888 if (queues[i] >= priv->rxqs_n) { 1889 *error = "queue index out of range"; 1890 *queue_idx = i; 1891 return -EINVAL; 1892 } 1893 rxq_ctrl = mlx5_rxq_ctrl_get(dev, queues[i]); 1894 if (rxq_ctrl == NULL) { 1895 *error = "queue is not configured"; 1896 *queue_idx = i; 1897 return -EINVAL; 1898 } 1899 if (i == 0 && rxq_ctrl->is_hairpin) 1900 is_hairpin = true; 1901 if (is_hairpin != rxq_ctrl->is_hairpin) { 1902 *error = "combining hairpin and regular RSS queues is not supported"; 1903 *queue_idx = i; 1904 return -ENOTSUP; 1905 } 1906 } 1907 return 0; 1908 } 1909 1910 /* 1911 * Validate the rss action. 1912 * 1913 * @param[in] dev 1914 * Pointer to the Ethernet device structure. 1915 * @param[in] action 1916 * Pointer to the queue action. 1917 * @param[out] error 1918 * Pointer to error structure. 1919 * 1920 * @return 1921 * 0 on success, a negative errno value otherwise and rte_errno is set. 1922 */ 1923 int 1924 mlx5_validate_action_rss(struct rte_eth_dev *dev, 1925 const struct rte_flow_action *action, 1926 struct rte_flow_error *error) 1927 { 1928 struct mlx5_priv *priv = dev->data->dev_private; 1929 const struct rte_flow_action_rss *rss = action->conf; 1930 int ret; 1931 const char *message; 1932 uint32_t queue_idx; 1933 1934 if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT && 1935 rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ) 1936 return rte_flow_error_set(error, ENOTSUP, 1937 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1938 &rss->func, 1939 "RSS hash function not supported"); 1940 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 1941 if (rss->level > 2) 1942 #else 1943 if (rss->level > 1) 1944 #endif 1945 return rte_flow_error_set(error, ENOTSUP, 1946 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1947 &rss->level, 1948 "tunnel RSS is not supported"); 1949 /* allow RSS key_len 0 in case of NULL (default) RSS key. */ 1950 if (rss->key_len == 0 && rss->key != NULL) 1951 return rte_flow_error_set(error, ENOTSUP, 1952 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1953 &rss->key_len, 1954 "RSS hash key length 0"); 1955 if (rss->key_len > 0 && rss->key_len < MLX5_RSS_HASH_KEY_LEN) 1956 return rte_flow_error_set(error, ENOTSUP, 1957 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1958 &rss->key_len, 1959 "RSS hash key too small"); 1960 if (rss->key_len > MLX5_RSS_HASH_KEY_LEN) 1961 return rte_flow_error_set(error, ENOTSUP, 1962 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1963 &rss->key_len, 1964 "RSS hash key too large"); 1965 if (rss->queue_num > priv->sh->dev_cap.ind_table_max_size) 1966 return rte_flow_error_set(error, ENOTSUP, 1967 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1968 &rss->queue_num, 1969 "number of queues too large"); 1970 if (rss->types & MLX5_RSS_HF_MASK) 1971 return rte_flow_error_set(error, ENOTSUP, 1972 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1973 &rss->types, 1974 "some RSS protocols are not" 1975 " supported"); 1976 if ((rss->types & (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY)) && 1977 !(rss->types & RTE_ETH_RSS_IP)) 1978 return rte_flow_error_set(error, EINVAL, 1979 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 1980 "L3 partial RSS requested but L3 RSS" 1981 " type not specified"); 1982 if ((rss->types & (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY)) && 1983 !(rss->types & (RTE_ETH_RSS_UDP | RTE_ETH_RSS_TCP))) 1984 return rte_flow_error_set(error, EINVAL, 1985 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 1986 "L4 partial RSS requested but L4 RSS" 1987 " type not specified"); 1988 if (!priv->rxqs_n && priv->ext_rxqs == NULL) 1989 return rte_flow_error_set(error, EINVAL, 1990 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1991 NULL, "No Rx queues configured"); 1992 if (!rss->queue_num) 1993 return rte_flow_error_set(error, EINVAL, 1994 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1995 NULL, "No queues configured"); 1996 ret = mlx5_validate_rss_queues(dev, rss->queue, rss->queue_num, 1997 &message, &queue_idx); 1998 if (ret != 0) { 1999 return rte_flow_error_set(error, -ret, 2000 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 2001 &rss->queue[queue_idx], message); 2002 } 2003 return 0; 2004 } 2005 2006 /* 2007 * Validate the rss action. 2008 * 2009 * @param[in] action 2010 * Pointer to the queue action. 2011 * @param[in] action_flags 2012 * Bit-fields that holds the actions detected until now. 2013 * @param[in] dev 2014 * Pointer to the Ethernet device structure. 2015 * @param[in] attr 2016 * Attributes of flow that includes this action. 2017 * @param[in] item_flags 2018 * Items that were detected. 2019 * @param[out] error 2020 * Pointer to error structure. 2021 * 2022 * @return 2023 * 0 on success, a negative errno value otherwise and rte_errno is set. 2024 */ 2025 int 2026 mlx5_flow_validate_action_rss(const struct rte_flow_action *action, 2027 uint64_t action_flags, 2028 struct rte_eth_dev *dev, 2029 const struct rte_flow_attr *attr, 2030 uint64_t item_flags, 2031 struct rte_flow_error *error) 2032 { 2033 const struct rte_flow_action_rss *rss = action->conf; 2034 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2035 int ret; 2036 2037 if (action_flags & MLX5_FLOW_FATE_ACTIONS) 2038 return rte_flow_error_set(error, EINVAL, 2039 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2040 "can't have 2 fate actions" 2041 " in same flow"); 2042 ret = mlx5_validate_action_rss(dev, action, error); 2043 if (ret) 2044 return ret; 2045 if (attr->egress) 2046 return rte_flow_error_set(error, ENOTSUP, 2047 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 2048 "rss action not supported for " 2049 "egress"); 2050 if (rss->level > 1 && !tunnel) 2051 return rte_flow_error_set(error, EINVAL, 2052 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2053 "inner RSS is not supported for " 2054 "non-tunnel flows"); 2055 if ((item_flags & MLX5_FLOW_LAYER_ECPRI) && 2056 !(item_flags & MLX5_FLOW_LAYER_INNER_L4_UDP)) { 2057 return rte_flow_error_set(error, EINVAL, 2058 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 2059 "RSS on eCPRI is not supported now"); 2060 } 2061 if ((item_flags & MLX5_FLOW_LAYER_MPLS) && 2062 !(item_flags & 2063 (MLX5_FLOW_LAYER_INNER_L2 | MLX5_FLOW_LAYER_INNER_L3)) && 2064 rss->level > 1) 2065 return rte_flow_error_set(error, EINVAL, 2066 RTE_FLOW_ERROR_TYPE_ITEM, NULL, 2067 "MPLS inner RSS needs to specify inner L2/L3 items after MPLS in pattern"); 2068 return 0; 2069 } 2070 2071 /* 2072 * Validate the default miss action. 2073 * 2074 * @param[in] action_flags 2075 * Bit-fields that holds the actions detected until now. 2076 * @param[out] error 2077 * Pointer to error structure. 2078 * 2079 * @return 2080 * 0 on success, a negative errno value otherwise and rte_errno is set. 2081 */ 2082 int 2083 mlx5_flow_validate_action_default_miss(uint64_t action_flags, 2084 const struct rte_flow_attr *attr, 2085 struct rte_flow_error *error) 2086 { 2087 if (action_flags & MLX5_FLOW_FATE_ACTIONS) 2088 return rte_flow_error_set(error, EINVAL, 2089 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2090 "can't have 2 fate actions in" 2091 " same flow"); 2092 if (attr->egress) 2093 return rte_flow_error_set(error, ENOTSUP, 2094 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 2095 "default miss action not supported " 2096 "for egress"); 2097 if (attr->group) 2098 return rte_flow_error_set(error, ENOTSUP, 2099 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL, 2100 "only group 0 is supported"); 2101 if (attr->transfer) 2102 return rte_flow_error_set(error, ENOTSUP, 2103 RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, 2104 NULL, "transfer is not supported"); 2105 return 0; 2106 } 2107 2108 /* 2109 * Validate the count action. 2110 * 2111 * @param[in] dev 2112 * Pointer to the Ethernet device structure. 2113 * @param[in] attr 2114 * Attributes of flow that includes this action. 2115 * @param[out] error 2116 * Pointer to error structure. 2117 * 2118 * @return 2119 * 0 on success, a negative errno value otherwise and rte_errno is set. 2120 */ 2121 int 2122 mlx5_flow_validate_action_count(struct rte_eth_dev *dev __rte_unused, 2123 const struct rte_flow_attr *attr, 2124 struct rte_flow_error *error) 2125 { 2126 if (attr->egress) 2127 return rte_flow_error_set(error, ENOTSUP, 2128 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 2129 "count action not supported for " 2130 "egress"); 2131 return 0; 2132 } 2133 2134 /* 2135 * Validate the ASO CT action. 2136 * 2137 * @param[in] dev 2138 * Pointer to the Ethernet device structure. 2139 * @param[in] conntrack 2140 * Pointer to the CT action profile. 2141 * @param[out] error 2142 * Pointer to error structure. 2143 * 2144 * @return 2145 * 0 on success, a negative errno value otherwise and rte_errno is set. 2146 */ 2147 int 2148 mlx5_validate_action_ct(struct rte_eth_dev *dev, 2149 const struct rte_flow_action_conntrack *conntrack, 2150 struct rte_flow_error *error) 2151 { 2152 RTE_SET_USED(dev); 2153 2154 if (conntrack->state > RTE_FLOW_CONNTRACK_STATE_TIME_WAIT) 2155 return rte_flow_error_set(error, EINVAL, 2156 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2157 "Invalid CT state"); 2158 if (conntrack->last_index > RTE_FLOW_CONNTRACK_FLAG_RST) 2159 return rte_flow_error_set(error, EINVAL, 2160 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 2161 "Invalid last TCP packet flag"); 2162 return 0; 2163 } 2164 2165 /** 2166 * Verify the @p attributes will be correctly understood by the NIC and store 2167 * them in the @p flow if everything is correct. 2168 * 2169 * @param[in] dev 2170 * Pointer to the Ethernet device structure. 2171 * @param[in] attributes 2172 * Pointer to flow attributes 2173 * @param[out] error 2174 * Pointer to error structure. 2175 * 2176 * @return 2177 * 0 on success, a negative errno value otherwise and rte_errno is set. 2178 */ 2179 int 2180 mlx5_flow_validate_attributes(struct rte_eth_dev *dev, 2181 const struct rte_flow_attr *attributes, 2182 struct rte_flow_error *error) 2183 { 2184 struct mlx5_priv *priv = dev->data->dev_private; 2185 uint32_t priority_max = priv->sh->flow_max_priority - 1; 2186 2187 if (attributes->group) 2188 return rte_flow_error_set(error, ENOTSUP, 2189 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 2190 NULL, "groups is not supported"); 2191 if (attributes->priority != MLX5_FLOW_LOWEST_PRIO_INDICATOR && 2192 attributes->priority >= priority_max) 2193 return rte_flow_error_set(error, ENOTSUP, 2194 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 2195 NULL, "priority out of range"); 2196 if (attributes->egress) 2197 return rte_flow_error_set(error, ENOTSUP, 2198 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 2199 "egress is not supported"); 2200 if (attributes->transfer && !priv->sh->config.dv_esw_en) 2201 return rte_flow_error_set(error, ENOTSUP, 2202 RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, 2203 NULL, "transfer is not supported"); 2204 if (!attributes->ingress) 2205 return rte_flow_error_set(error, EINVAL, 2206 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 2207 NULL, 2208 "ingress attribute is mandatory"); 2209 return 0; 2210 } 2211 2212 /** 2213 * Validate ICMP6 item. 2214 * 2215 * @param[in] item 2216 * Item specification. 2217 * @param[in] item_flags 2218 * Bit-fields that holds the items detected until now. 2219 * @param[in] ext_vlan_sup 2220 * Whether extended VLAN features are supported or not. 2221 * @param[out] error 2222 * Pointer to error structure. 2223 * 2224 * @return 2225 * 0 on success, a negative errno value otherwise and rte_errno is set. 2226 */ 2227 int 2228 mlx5_flow_validate_item_icmp6(const struct rte_flow_item *item, 2229 uint64_t item_flags, 2230 uint8_t target_protocol, 2231 struct rte_flow_error *error) 2232 { 2233 const struct rte_flow_item_icmp6 *mask = item->mask; 2234 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2235 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 2236 MLX5_FLOW_LAYER_OUTER_L3_IPV6; 2237 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2238 MLX5_FLOW_LAYER_OUTER_L4; 2239 int ret; 2240 2241 if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMPV6) 2242 return rte_flow_error_set(error, EINVAL, 2243 RTE_FLOW_ERROR_TYPE_ITEM, item, 2244 "protocol filtering not compatible" 2245 " with ICMP6 layer"); 2246 if (!(item_flags & l3m)) 2247 return rte_flow_error_set(error, EINVAL, 2248 RTE_FLOW_ERROR_TYPE_ITEM, item, 2249 "IPv6 is mandatory to filter on" 2250 " ICMP6"); 2251 if (item_flags & l4m) 2252 return rte_flow_error_set(error, EINVAL, 2253 RTE_FLOW_ERROR_TYPE_ITEM, item, 2254 "multiple L4 layers not supported"); 2255 if (!mask) 2256 mask = &rte_flow_item_icmp6_mask; 2257 ret = mlx5_flow_item_acceptable 2258 (item, (const uint8_t *)mask, 2259 (const uint8_t *)&rte_flow_item_icmp6_mask, 2260 sizeof(struct rte_flow_item_icmp6), 2261 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2262 if (ret < 0) 2263 return ret; 2264 return 0; 2265 } 2266 2267 /** 2268 * Validate ICMP item. 2269 * 2270 * @param[in] item 2271 * Item specification. 2272 * @param[in] item_flags 2273 * Bit-fields that holds the items detected until now. 2274 * @param[out] error 2275 * Pointer to error structure. 2276 * 2277 * @return 2278 * 0 on success, a negative errno value otherwise and rte_errno is set. 2279 */ 2280 int 2281 mlx5_flow_validate_item_icmp(const struct rte_flow_item *item, 2282 uint64_t item_flags, 2283 uint8_t target_protocol, 2284 struct rte_flow_error *error) 2285 { 2286 const struct rte_flow_item_icmp *mask = item->mask; 2287 const struct rte_flow_item_icmp nic_mask = { 2288 .hdr.icmp_type = 0xff, 2289 .hdr.icmp_code = 0xff, 2290 .hdr.icmp_ident = RTE_BE16(0xffff), 2291 .hdr.icmp_seq_nb = RTE_BE16(0xffff), 2292 }; 2293 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2294 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 2295 MLX5_FLOW_LAYER_OUTER_L3_IPV4; 2296 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2297 MLX5_FLOW_LAYER_OUTER_L4; 2298 int ret; 2299 2300 if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMP) 2301 return rte_flow_error_set(error, EINVAL, 2302 RTE_FLOW_ERROR_TYPE_ITEM, item, 2303 "protocol filtering not compatible" 2304 " with ICMP layer"); 2305 if (!(item_flags & l3m)) 2306 return rte_flow_error_set(error, EINVAL, 2307 RTE_FLOW_ERROR_TYPE_ITEM, item, 2308 "IPv4 is mandatory to filter" 2309 " on ICMP"); 2310 if (item_flags & l4m) 2311 return rte_flow_error_set(error, EINVAL, 2312 RTE_FLOW_ERROR_TYPE_ITEM, item, 2313 "multiple L4 layers not supported"); 2314 if (!mask) 2315 mask = &nic_mask; 2316 ret = mlx5_flow_item_acceptable 2317 (item, (const uint8_t *)mask, 2318 (const uint8_t *)&nic_mask, 2319 sizeof(struct rte_flow_item_icmp), 2320 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2321 if (ret < 0) 2322 return ret; 2323 return 0; 2324 } 2325 2326 /** 2327 * Validate Ethernet item. 2328 * 2329 * @param[in] item 2330 * Item specification. 2331 * @param[in] item_flags 2332 * Bit-fields that holds the items detected until now. 2333 * @param[out] error 2334 * Pointer to error structure. 2335 * 2336 * @return 2337 * 0 on success, a negative errno value otherwise and rte_errno is set. 2338 */ 2339 int 2340 mlx5_flow_validate_item_eth(const struct rte_flow_item *item, 2341 uint64_t item_flags, bool ext_vlan_sup, 2342 struct rte_flow_error *error) 2343 { 2344 const struct rte_flow_item_eth *mask = item->mask; 2345 const struct rte_flow_item_eth nic_mask = { 2346 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 2347 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", 2348 .type = RTE_BE16(0xffff), 2349 .has_vlan = ext_vlan_sup ? 1 : 0, 2350 }; 2351 int ret; 2352 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2353 const uint64_t ethm = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 2354 MLX5_FLOW_LAYER_OUTER_L2; 2355 2356 if (item_flags & ethm) 2357 return rte_flow_error_set(error, ENOTSUP, 2358 RTE_FLOW_ERROR_TYPE_ITEM, item, 2359 "multiple L2 layers not supported"); 2360 if ((!tunnel && (item_flags & MLX5_FLOW_LAYER_OUTER_L3)) || 2361 (tunnel && (item_flags & MLX5_FLOW_LAYER_INNER_L3))) 2362 return rte_flow_error_set(error, EINVAL, 2363 RTE_FLOW_ERROR_TYPE_ITEM, item, 2364 "L2 layer should not follow " 2365 "L3 layers"); 2366 if ((!tunnel && (item_flags & MLX5_FLOW_LAYER_OUTER_VLAN)) || 2367 (tunnel && (item_flags & MLX5_FLOW_LAYER_INNER_VLAN))) 2368 return rte_flow_error_set(error, EINVAL, 2369 RTE_FLOW_ERROR_TYPE_ITEM, item, 2370 "L2 layer should not follow VLAN"); 2371 if (item_flags & MLX5_FLOW_LAYER_GTP) 2372 return rte_flow_error_set(error, EINVAL, 2373 RTE_FLOW_ERROR_TYPE_ITEM, item, 2374 "L2 layer should not follow GTP"); 2375 if (!mask) 2376 mask = &rte_flow_item_eth_mask; 2377 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2378 (const uint8_t *)&nic_mask, 2379 sizeof(struct rte_flow_item_eth), 2380 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2381 return ret; 2382 } 2383 2384 /** 2385 * Validate VLAN item. 2386 * 2387 * @param[in] item 2388 * Item specification. 2389 * @param[in] item_flags 2390 * Bit-fields that holds the items detected until now. 2391 * @param[in] dev 2392 * Ethernet device flow is being created on. 2393 * @param[out] error 2394 * Pointer to error structure. 2395 * 2396 * @return 2397 * 0 on success, a negative errno value otherwise and rte_errno is set. 2398 */ 2399 int 2400 mlx5_flow_validate_item_vlan(const struct rte_flow_item *item, 2401 uint64_t item_flags, 2402 struct rte_eth_dev *dev, 2403 struct rte_flow_error *error) 2404 { 2405 const struct rte_flow_item_vlan *spec = item->spec; 2406 const struct rte_flow_item_vlan *mask = item->mask; 2407 const struct rte_flow_item_vlan nic_mask = { 2408 .tci = RTE_BE16(UINT16_MAX), 2409 .inner_type = RTE_BE16(UINT16_MAX), 2410 }; 2411 uint16_t vlan_tag = 0; 2412 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2413 int ret; 2414 const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 | 2415 MLX5_FLOW_LAYER_INNER_L4) : 2416 (MLX5_FLOW_LAYER_OUTER_L3 | 2417 MLX5_FLOW_LAYER_OUTER_L4); 2418 const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN : 2419 MLX5_FLOW_LAYER_OUTER_VLAN; 2420 2421 if (item_flags & vlanm) 2422 return rte_flow_error_set(error, EINVAL, 2423 RTE_FLOW_ERROR_TYPE_ITEM, item, 2424 "multiple VLAN layers not supported"); 2425 else if ((item_flags & l34m) != 0) 2426 return rte_flow_error_set(error, EINVAL, 2427 RTE_FLOW_ERROR_TYPE_ITEM, item, 2428 "VLAN cannot follow L3/L4 layer"); 2429 if (!mask) 2430 mask = &rte_flow_item_vlan_mask; 2431 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2432 (const uint8_t *)&nic_mask, 2433 sizeof(struct rte_flow_item_vlan), 2434 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2435 if (ret) 2436 return ret; 2437 if (!tunnel && mask->tci != RTE_BE16(0x0fff)) { 2438 struct mlx5_priv *priv = dev->data->dev_private; 2439 2440 if (priv->vmwa_context) { 2441 /* 2442 * Non-NULL context means we have a virtual machine 2443 * and SR-IOV enabled, we have to create VLAN interface 2444 * to make hypervisor to setup E-Switch vport 2445 * context correctly. We avoid creating the multiple 2446 * VLAN interfaces, so we cannot support VLAN tag mask. 2447 */ 2448 return rte_flow_error_set(error, EINVAL, 2449 RTE_FLOW_ERROR_TYPE_ITEM, 2450 item, 2451 "VLAN tag mask is not" 2452 " supported in virtual" 2453 " environment"); 2454 } 2455 } 2456 if (spec) { 2457 vlan_tag = spec->tci; 2458 vlan_tag &= mask->tci; 2459 } 2460 /* 2461 * From verbs perspective an empty VLAN is equivalent 2462 * to a packet without VLAN layer. 2463 */ 2464 if (!vlan_tag) 2465 return rte_flow_error_set(error, EINVAL, 2466 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 2467 item->spec, 2468 "VLAN cannot be empty"); 2469 return 0; 2470 } 2471 2472 /** 2473 * Validate IPV4 item. 2474 * 2475 * @param[in] item 2476 * Item specification. 2477 * @param[in] item_flags 2478 * Bit-fields that holds the items detected until now. 2479 * @param[in] last_item 2480 * Previous validated item in the pattern items. 2481 * @param[in] ether_type 2482 * Type in the ethernet layer header (including dot1q). 2483 * @param[in] acc_mask 2484 * Acceptable mask, if NULL default internal default mask 2485 * will be used to check whether item fields are supported. 2486 * @param[in] range_accepted 2487 * True if range of values is accepted for specific fields, false otherwise. 2488 * @param[out] error 2489 * Pointer to error structure. 2490 * 2491 * @return 2492 * 0 on success, a negative errno value otherwise and rte_errno is set. 2493 */ 2494 int 2495 mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, 2496 uint64_t item_flags, 2497 uint64_t last_item, 2498 uint16_t ether_type, 2499 const struct rte_flow_item_ipv4 *acc_mask, 2500 bool range_accepted, 2501 struct rte_flow_error *error) 2502 { 2503 const struct rte_flow_item_ipv4 *mask = item->mask; 2504 const struct rte_flow_item_ipv4 *spec = item->spec; 2505 const struct rte_flow_item_ipv4 nic_mask = { 2506 .hdr = { 2507 .src_addr = RTE_BE32(0xffffffff), 2508 .dst_addr = RTE_BE32(0xffffffff), 2509 .type_of_service = 0xff, 2510 .next_proto_id = 0xff, 2511 }, 2512 }; 2513 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2514 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 2515 MLX5_FLOW_LAYER_OUTER_L3; 2516 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2517 MLX5_FLOW_LAYER_OUTER_L4; 2518 int ret; 2519 uint8_t next_proto = 0xFF; 2520 const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 | 2521 MLX5_FLOW_LAYER_OUTER_VLAN | 2522 MLX5_FLOW_LAYER_INNER_VLAN); 2523 2524 if ((last_item & l2_vlan) && ether_type && 2525 ether_type != RTE_ETHER_TYPE_IPV4) 2526 return rte_flow_error_set(error, EINVAL, 2527 RTE_FLOW_ERROR_TYPE_ITEM, item, 2528 "IPv4 cannot follow L2/VLAN layer " 2529 "which ether type is not IPv4"); 2530 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) { 2531 if (mask && spec) 2532 next_proto = mask->hdr.next_proto_id & 2533 spec->hdr.next_proto_id; 2534 if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6) 2535 return rte_flow_error_set(error, EINVAL, 2536 RTE_FLOW_ERROR_TYPE_ITEM, 2537 item, 2538 "multiple tunnel " 2539 "not supported"); 2540 } 2541 if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP) 2542 return rte_flow_error_set(error, EINVAL, 2543 RTE_FLOW_ERROR_TYPE_ITEM, item, 2544 "wrong tunnel type - IPv6 specified " 2545 "but IPv4 item provided"); 2546 if (item_flags & l3m) 2547 return rte_flow_error_set(error, ENOTSUP, 2548 RTE_FLOW_ERROR_TYPE_ITEM, item, 2549 "multiple L3 layers not supported"); 2550 else if (item_flags & l4m) 2551 return rte_flow_error_set(error, EINVAL, 2552 RTE_FLOW_ERROR_TYPE_ITEM, item, 2553 "L3 cannot follow an L4 layer."); 2554 else if ((item_flags & MLX5_FLOW_LAYER_NVGRE) && 2555 !(item_flags & MLX5_FLOW_LAYER_INNER_L2)) 2556 return rte_flow_error_set(error, EINVAL, 2557 RTE_FLOW_ERROR_TYPE_ITEM, item, 2558 "L3 cannot follow an NVGRE layer."); 2559 if (!mask) 2560 mask = &rte_flow_item_ipv4_mask; 2561 else if (mask->hdr.next_proto_id != 0 && 2562 mask->hdr.next_proto_id != 0xff) 2563 return rte_flow_error_set(error, EINVAL, 2564 RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, 2565 "partial mask is not supported" 2566 " for protocol"); 2567 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2568 acc_mask ? (const uint8_t *)acc_mask 2569 : (const uint8_t *)&nic_mask, 2570 sizeof(struct rte_flow_item_ipv4), 2571 range_accepted, error); 2572 if (ret < 0) 2573 return ret; 2574 return 0; 2575 } 2576 2577 /** 2578 * Validate IPV6 item. 2579 * 2580 * @param[in] item 2581 * Item specification. 2582 * @param[in] item_flags 2583 * Bit-fields that holds the items detected until now. 2584 * @param[in] last_item 2585 * Previous validated item in the pattern items. 2586 * @param[in] ether_type 2587 * Type in the ethernet layer header (including dot1q). 2588 * @param[in] acc_mask 2589 * Acceptable mask, if NULL default internal default mask 2590 * will be used to check whether item fields are supported. 2591 * @param[out] error 2592 * Pointer to error structure. 2593 * 2594 * @return 2595 * 0 on success, a negative errno value otherwise and rte_errno is set. 2596 */ 2597 int 2598 mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, 2599 uint64_t item_flags, 2600 uint64_t last_item, 2601 uint16_t ether_type, 2602 const struct rte_flow_item_ipv6 *acc_mask, 2603 struct rte_flow_error *error) 2604 { 2605 const struct rte_flow_item_ipv6 *mask = item->mask; 2606 const struct rte_flow_item_ipv6 *spec = item->spec; 2607 const struct rte_flow_item_ipv6 nic_mask = { 2608 .hdr = { 2609 .src_addr = 2610 "\xff\xff\xff\xff\xff\xff\xff\xff" 2611 "\xff\xff\xff\xff\xff\xff\xff\xff", 2612 .dst_addr = 2613 "\xff\xff\xff\xff\xff\xff\xff\xff" 2614 "\xff\xff\xff\xff\xff\xff\xff\xff", 2615 .vtc_flow = RTE_BE32(0xffffffff), 2616 .proto = 0xff, 2617 }, 2618 }; 2619 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2620 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 2621 MLX5_FLOW_LAYER_OUTER_L3; 2622 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2623 MLX5_FLOW_LAYER_OUTER_L4; 2624 int ret; 2625 uint8_t next_proto = 0xFF; 2626 const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 | 2627 MLX5_FLOW_LAYER_OUTER_VLAN | 2628 MLX5_FLOW_LAYER_INNER_VLAN); 2629 2630 if ((last_item & l2_vlan) && ether_type && 2631 ether_type != RTE_ETHER_TYPE_IPV6) 2632 return rte_flow_error_set(error, EINVAL, 2633 RTE_FLOW_ERROR_TYPE_ITEM, item, 2634 "IPv6 cannot follow L2/VLAN layer " 2635 "which ether type is not IPv6"); 2636 if (mask && mask->hdr.proto == UINT8_MAX && spec) 2637 next_proto = spec->hdr.proto; 2638 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) { 2639 if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6) 2640 return rte_flow_error_set(error, EINVAL, 2641 RTE_FLOW_ERROR_TYPE_ITEM, 2642 item, 2643 "multiple tunnel " 2644 "not supported"); 2645 } 2646 if (next_proto == IPPROTO_HOPOPTS || 2647 next_proto == IPPROTO_ROUTING || 2648 next_proto == IPPROTO_FRAGMENT || 2649 next_proto == IPPROTO_ESP || 2650 next_proto == IPPROTO_AH || 2651 next_proto == IPPROTO_DSTOPTS) 2652 return rte_flow_error_set(error, EINVAL, 2653 RTE_FLOW_ERROR_TYPE_ITEM, item, 2654 "IPv6 proto (next header) should " 2655 "not be set as extension header"); 2656 if (item_flags & MLX5_FLOW_LAYER_IPIP) 2657 return rte_flow_error_set(error, EINVAL, 2658 RTE_FLOW_ERROR_TYPE_ITEM, item, 2659 "wrong tunnel type - IPv4 specified " 2660 "but IPv6 item provided"); 2661 if (item_flags & l3m) 2662 return rte_flow_error_set(error, ENOTSUP, 2663 RTE_FLOW_ERROR_TYPE_ITEM, item, 2664 "multiple L3 layers not supported"); 2665 else if (item_flags & l4m) 2666 return rte_flow_error_set(error, EINVAL, 2667 RTE_FLOW_ERROR_TYPE_ITEM, item, 2668 "L3 cannot follow an L4 layer."); 2669 else if ((item_flags & MLX5_FLOW_LAYER_NVGRE) && 2670 !(item_flags & MLX5_FLOW_LAYER_INNER_L2)) 2671 return rte_flow_error_set(error, EINVAL, 2672 RTE_FLOW_ERROR_TYPE_ITEM, item, 2673 "L3 cannot follow an NVGRE layer."); 2674 if (!mask) 2675 mask = &rte_flow_item_ipv6_mask; 2676 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 2677 acc_mask ? (const uint8_t *)acc_mask 2678 : (const uint8_t *)&nic_mask, 2679 sizeof(struct rte_flow_item_ipv6), 2680 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2681 if (ret < 0) 2682 return ret; 2683 return 0; 2684 } 2685 2686 /** 2687 * Validate UDP item. 2688 * 2689 * @param[in] item 2690 * Item specification. 2691 * @param[in] item_flags 2692 * Bit-fields that holds the items detected until now. 2693 * @param[in] target_protocol 2694 * The next protocol in the previous item. 2695 * @param[in] flow_mask 2696 * mlx5 flow-specific (DV, verbs, etc.) supported header fields mask. 2697 * @param[out] error 2698 * Pointer to error structure. 2699 * 2700 * @return 2701 * 0 on success, a negative errno value otherwise and rte_errno is set. 2702 */ 2703 int 2704 mlx5_flow_validate_item_udp(const struct rte_flow_item *item, 2705 uint64_t item_flags, 2706 uint8_t target_protocol, 2707 struct rte_flow_error *error) 2708 { 2709 const struct rte_flow_item_udp *mask = item->mask; 2710 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2711 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 2712 MLX5_FLOW_LAYER_OUTER_L3; 2713 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2714 MLX5_FLOW_LAYER_OUTER_L4; 2715 int ret; 2716 2717 if (target_protocol != 0xff && target_protocol != IPPROTO_UDP) 2718 return rte_flow_error_set(error, EINVAL, 2719 RTE_FLOW_ERROR_TYPE_ITEM, item, 2720 "protocol filtering not compatible" 2721 " with UDP layer"); 2722 if (!(item_flags & l3m)) 2723 return rte_flow_error_set(error, EINVAL, 2724 RTE_FLOW_ERROR_TYPE_ITEM, item, 2725 "L3 is mandatory to filter on L4"); 2726 if (item_flags & l4m) 2727 return rte_flow_error_set(error, EINVAL, 2728 RTE_FLOW_ERROR_TYPE_ITEM, item, 2729 "multiple L4 layers not supported"); 2730 if (!mask) 2731 mask = &rte_flow_item_udp_mask; 2732 ret = mlx5_flow_item_acceptable 2733 (item, (const uint8_t *)mask, 2734 (const uint8_t *)&rte_flow_item_udp_mask, 2735 sizeof(struct rte_flow_item_udp), MLX5_ITEM_RANGE_NOT_ACCEPTED, 2736 error); 2737 if (ret < 0) 2738 return ret; 2739 return 0; 2740 } 2741 2742 /** 2743 * Validate TCP item. 2744 * 2745 * @param[in] item 2746 * Item specification. 2747 * @param[in] item_flags 2748 * Bit-fields that holds the items detected until now. 2749 * @param[in] target_protocol 2750 * The next protocol in the previous item. 2751 * @param[out] error 2752 * Pointer to error structure. 2753 * 2754 * @return 2755 * 0 on success, a negative errno value otherwise and rte_errno is set. 2756 */ 2757 int 2758 mlx5_flow_validate_item_tcp(const struct rte_flow_item *item, 2759 uint64_t item_flags, 2760 uint8_t target_protocol, 2761 const struct rte_flow_item_tcp *flow_mask, 2762 struct rte_flow_error *error) 2763 { 2764 const struct rte_flow_item_tcp *mask = item->mask; 2765 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 2766 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 2767 MLX5_FLOW_LAYER_OUTER_L3; 2768 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 2769 MLX5_FLOW_LAYER_OUTER_L4; 2770 int ret; 2771 2772 MLX5_ASSERT(flow_mask); 2773 if (target_protocol != 0xff && target_protocol != IPPROTO_TCP) 2774 return rte_flow_error_set(error, EINVAL, 2775 RTE_FLOW_ERROR_TYPE_ITEM, item, 2776 "protocol filtering not compatible" 2777 " with TCP layer"); 2778 if (!(item_flags & l3m)) 2779 return rte_flow_error_set(error, EINVAL, 2780 RTE_FLOW_ERROR_TYPE_ITEM, item, 2781 "L3 is mandatory to filter on L4"); 2782 if (item_flags & l4m) 2783 return rte_flow_error_set(error, EINVAL, 2784 RTE_FLOW_ERROR_TYPE_ITEM, item, 2785 "multiple L4 layers not supported"); 2786 if (!mask) 2787 mask = &rte_flow_item_tcp_mask; 2788 ret = mlx5_flow_item_acceptable 2789 (item, (const uint8_t *)mask, 2790 (const uint8_t *)flow_mask, 2791 sizeof(struct rte_flow_item_tcp), MLX5_ITEM_RANGE_NOT_ACCEPTED, 2792 error); 2793 if (ret < 0) 2794 return ret; 2795 return 0; 2796 } 2797 2798 /** 2799 * Validate VXLAN item. 2800 * 2801 * @param[in] dev 2802 * Pointer to the Ethernet device structure. 2803 * @param[in] udp_dport 2804 * UDP destination port 2805 * @param[in] item 2806 * Item specification. 2807 * @param[in] item_flags 2808 * Bit-fields that holds the items detected until now. 2809 * @param[in] attr 2810 * Flow rule attributes. 2811 * @param[out] error 2812 * Pointer to error structure. 2813 * 2814 * @return 2815 * 0 on success, a negative errno value otherwise and rte_errno is set. 2816 */ 2817 int 2818 mlx5_flow_validate_item_vxlan(struct rte_eth_dev *dev, 2819 uint16_t udp_dport, 2820 const struct rte_flow_item *item, 2821 uint64_t item_flags, 2822 const struct rte_flow_attr *attr, 2823 struct rte_flow_error *error) 2824 { 2825 const struct rte_flow_item_vxlan *spec = item->spec; 2826 const struct rte_flow_item_vxlan *mask = item->mask; 2827 int ret; 2828 struct mlx5_priv *priv = dev->data->dev_private; 2829 union vni { 2830 uint32_t vlan_id; 2831 uint8_t vni[4]; 2832 } id = { .vlan_id = 0, }; 2833 const struct rte_flow_item_vxlan nic_mask = { 2834 .vni = "\xff\xff\xff", 2835 .rsvd1 = 0xff, 2836 }; 2837 const struct rte_flow_item_vxlan *valid_mask; 2838 2839 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 2840 return rte_flow_error_set(error, ENOTSUP, 2841 RTE_FLOW_ERROR_TYPE_ITEM, item, 2842 "multiple tunnel layers not" 2843 " supported"); 2844 valid_mask = &rte_flow_item_vxlan_mask; 2845 /* 2846 * Verify only UDPv4 is present as defined in 2847 * https://tools.ietf.org/html/rfc7348 2848 */ 2849 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 2850 return rte_flow_error_set(error, EINVAL, 2851 RTE_FLOW_ERROR_TYPE_ITEM, item, 2852 "no outer UDP layer found"); 2853 if (!mask) 2854 mask = &rte_flow_item_vxlan_mask; 2855 2856 if (priv->sh->steering_format_version != 2857 MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 || 2858 !udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN) { 2859 /* FDB domain & NIC domain non-zero group */ 2860 if ((attr->transfer || attr->group) && priv->sh->misc5_cap) 2861 valid_mask = &nic_mask; 2862 /* Group zero in NIC domain */ 2863 if (!attr->group && !attr->transfer && 2864 priv->sh->tunnel_header_0_1) 2865 valid_mask = &nic_mask; 2866 } 2867 ret = mlx5_flow_item_acceptable 2868 (item, (const uint8_t *)mask, 2869 (const uint8_t *)valid_mask, 2870 sizeof(struct rte_flow_item_vxlan), 2871 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2872 if (ret < 0) 2873 return ret; 2874 if (spec) { 2875 memcpy(&id.vni[1], spec->vni, 3); 2876 memcpy(&id.vni[1], mask->vni, 3); 2877 } 2878 if (!(item_flags & MLX5_FLOW_LAYER_OUTER)) 2879 return rte_flow_error_set(error, ENOTSUP, 2880 RTE_FLOW_ERROR_TYPE_ITEM, item, 2881 "VXLAN tunnel must be fully defined"); 2882 return 0; 2883 } 2884 2885 /** 2886 * Validate VXLAN_GPE item. 2887 * 2888 * @param[in] item 2889 * Item specification. 2890 * @param[in] item_flags 2891 * Bit-fields that holds the items detected until now. 2892 * @param[in] priv 2893 * Pointer to the private data structure. 2894 * @param[in] target_protocol 2895 * The next protocol in the previous item. 2896 * @param[out] error 2897 * Pointer to error structure. 2898 * 2899 * @return 2900 * 0 on success, a negative errno value otherwise and rte_errno is set. 2901 */ 2902 int 2903 mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item, 2904 uint64_t item_flags, 2905 struct rte_eth_dev *dev, 2906 struct rte_flow_error *error) 2907 { 2908 struct mlx5_priv *priv = dev->data->dev_private; 2909 const struct rte_flow_item_vxlan_gpe *spec = item->spec; 2910 const struct rte_flow_item_vxlan_gpe *mask = item->mask; 2911 int ret; 2912 union vni { 2913 uint32_t vlan_id; 2914 uint8_t vni[4]; 2915 } id = { .vlan_id = 0, }; 2916 2917 if (!priv->sh->config.l3_vxlan_en) 2918 return rte_flow_error_set(error, ENOTSUP, 2919 RTE_FLOW_ERROR_TYPE_ITEM, item, 2920 "L3 VXLAN is not enabled by device" 2921 " parameter and/or not configured in" 2922 " firmware"); 2923 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 2924 return rte_flow_error_set(error, ENOTSUP, 2925 RTE_FLOW_ERROR_TYPE_ITEM, item, 2926 "multiple tunnel layers not" 2927 " supported"); 2928 /* 2929 * Verify only UDPv4 is present as defined in 2930 * https://tools.ietf.org/html/rfc7348 2931 */ 2932 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 2933 return rte_flow_error_set(error, EINVAL, 2934 RTE_FLOW_ERROR_TYPE_ITEM, item, 2935 "no outer UDP layer found"); 2936 if (!mask) 2937 mask = &rte_flow_item_vxlan_gpe_mask; 2938 ret = mlx5_flow_item_acceptable 2939 (item, (const uint8_t *)mask, 2940 (const uint8_t *)&rte_flow_item_vxlan_gpe_mask, 2941 sizeof(struct rte_flow_item_vxlan_gpe), 2942 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 2943 if (ret < 0) 2944 return ret; 2945 if (spec) { 2946 if (spec->protocol) 2947 return rte_flow_error_set(error, ENOTSUP, 2948 RTE_FLOW_ERROR_TYPE_ITEM, 2949 item, 2950 "VxLAN-GPE protocol" 2951 " not supported"); 2952 memcpy(&id.vni[1], spec->vni, 3); 2953 memcpy(&id.vni[1], mask->vni, 3); 2954 } 2955 if (!(item_flags & MLX5_FLOW_LAYER_OUTER)) 2956 return rte_flow_error_set(error, ENOTSUP, 2957 RTE_FLOW_ERROR_TYPE_ITEM, item, 2958 "VXLAN-GPE tunnel must be fully" 2959 " defined"); 2960 return 0; 2961 } 2962 /** 2963 * Validate GRE Key item. 2964 * 2965 * @param[in] item 2966 * Item specification. 2967 * @param[in] item_flags 2968 * Bit flags to mark detected items. 2969 * @param[in] gre_item 2970 * Pointer to gre_item 2971 * @param[out] error 2972 * Pointer to error structure. 2973 * 2974 * @return 2975 * 0 on success, a negative errno value otherwise and rte_errno is set. 2976 */ 2977 int 2978 mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item, 2979 uint64_t item_flags, 2980 const struct rte_flow_item *gre_item, 2981 struct rte_flow_error *error) 2982 { 2983 const rte_be32_t *mask = item->mask; 2984 int ret = 0; 2985 rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 2986 const struct rte_flow_item_gre *gre_spec; 2987 const struct rte_flow_item_gre *gre_mask; 2988 2989 if (item_flags & MLX5_FLOW_LAYER_GRE_KEY) 2990 return rte_flow_error_set(error, ENOTSUP, 2991 RTE_FLOW_ERROR_TYPE_ITEM, item, 2992 "Multiple GRE key not support"); 2993 if (!(item_flags & MLX5_FLOW_LAYER_GRE)) 2994 return rte_flow_error_set(error, ENOTSUP, 2995 RTE_FLOW_ERROR_TYPE_ITEM, item, 2996 "No preceding GRE header"); 2997 if (item_flags & MLX5_FLOW_LAYER_INNER) 2998 return rte_flow_error_set(error, ENOTSUP, 2999 RTE_FLOW_ERROR_TYPE_ITEM, item, 3000 "GRE key following a wrong item"); 3001 gre_mask = gre_item->mask; 3002 if (!gre_mask) 3003 gre_mask = &rte_flow_item_gre_mask; 3004 gre_spec = gre_item->spec; 3005 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) && 3006 !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000))) 3007 return rte_flow_error_set(error, EINVAL, 3008 RTE_FLOW_ERROR_TYPE_ITEM, item, 3009 "Key bit must be on"); 3010 3011 if (!mask) 3012 mask = &gre_key_default_mask; 3013 ret = mlx5_flow_item_acceptable 3014 (item, (const uint8_t *)mask, 3015 (const uint8_t *)&gre_key_default_mask, 3016 sizeof(rte_be32_t), MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 3017 return ret; 3018 } 3019 3020 /** 3021 * Validate GRE optional item. 3022 * 3023 * @param[in] dev 3024 * Pointer to the Ethernet device structure. 3025 * @param[in] item 3026 * Item specification. 3027 * @param[in] item_flags 3028 * Bit flags to mark detected items. 3029 * @param[in] attr 3030 * Flow rule attributes. 3031 * @param[in] gre_item 3032 * Pointer to gre_item 3033 * @param[out] error 3034 * Pointer to error structure. 3035 * 3036 * @return 3037 * 0 on success, a negative errno value otherwise and rte_errno is set. 3038 */ 3039 int 3040 mlx5_flow_validate_item_gre_option(struct rte_eth_dev *dev, 3041 const struct rte_flow_item *item, 3042 uint64_t item_flags, 3043 const struct rte_flow_attr *attr, 3044 const struct rte_flow_item *gre_item, 3045 struct rte_flow_error *error) 3046 { 3047 const struct rte_flow_item_gre *gre_spec = gre_item->spec; 3048 const struct rte_flow_item_gre *gre_mask = gre_item->mask; 3049 const struct rte_flow_item_gre_opt *spec = item->spec; 3050 const struct rte_flow_item_gre_opt *mask = item->mask; 3051 struct mlx5_priv *priv = dev->data->dev_private; 3052 int ret = 0; 3053 struct rte_flow_item_gre_opt nic_mask = { 3054 .checksum_rsvd = { 3055 .checksum = RTE_BE16(UINT16_MAX), 3056 .reserved1 = 0x0, 3057 }, 3058 .key = { 3059 .key = RTE_BE32(UINT32_MAX), 3060 }, 3061 .sequence = { 3062 .sequence = RTE_BE32(UINT32_MAX), 3063 }, 3064 }; 3065 3066 if (!(item_flags & MLX5_FLOW_LAYER_GRE)) 3067 return rte_flow_error_set(error, ENOTSUP, 3068 RTE_FLOW_ERROR_TYPE_ITEM, item, 3069 "No preceding GRE header"); 3070 if (item_flags & MLX5_FLOW_LAYER_INNER) 3071 return rte_flow_error_set(error, ENOTSUP, 3072 RTE_FLOW_ERROR_TYPE_ITEM, item, 3073 "GRE option following a wrong item"); 3074 if (!spec || !mask) 3075 return rte_flow_error_set(error, EINVAL, 3076 RTE_FLOW_ERROR_TYPE_ITEM, item, 3077 "At least one field gre_option(checksum/key/sequence) must be specified"); 3078 if (!gre_mask) 3079 gre_mask = &rte_flow_item_gre_mask; 3080 if (mask->checksum_rsvd.checksum) 3081 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x8000)) && 3082 !(gre_spec->c_rsvd0_ver & RTE_BE16(0x8000))) 3083 return rte_flow_error_set(error, EINVAL, 3084 RTE_FLOW_ERROR_TYPE_ITEM, 3085 item, 3086 "Checksum bit must be on"); 3087 if (mask->key.key) 3088 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) && 3089 !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000))) 3090 return rte_flow_error_set(error, EINVAL, 3091 RTE_FLOW_ERROR_TYPE_ITEM, 3092 item, "Key bit must be on"); 3093 if (mask->sequence.sequence) 3094 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x1000)) && 3095 !(gre_spec->c_rsvd0_ver & RTE_BE16(0x1000))) 3096 return rte_flow_error_set(error, EINVAL, 3097 RTE_FLOW_ERROR_TYPE_ITEM, 3098 item, 3099 "Sequence bit must be on"); 3100 if (mask->checksum_rsvd.checksum || mask->sequence.sequence) { 3101 if (priv->sh->steering_format_version == 3102 MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 || 3103 ((attr->group || attr->transfer) && 3104 !priv->sh->misc5_cap) || 3105 (!(priv->sh->tunnel_header_0_1 && 3106 priv->sh->tunnel_header_2_3) && 3107 !attr->group && !attr->transfer)) 3108 return rte_flow_error_set(error, EINVAL, 3109 RTE_FLOW_ERROR_TYPE_ITEM, 3110 item, 3111 "Checksum/Sequence not supported"); 3112 } 3113 ret = mlx5_flow_item_acceptable 3114 (item, (const uint8_t *)mask, 3115 (const uint8_t *)&nic_mask, 3116 sizeof(struct rte_flow_item_gre_opt), 3117 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 3118 return ret; 3119 } 3120 3121 /** 3122 * Validate GRE item. 3123 * 3124 * @param[in] item 3125 * Item specification. 3126 * @param[in] item_flags 3127 * Bit flags to mark detected items. 3128 * @param[in] target_protocol 3129 * The next protocol in the previous item. 3130 * @param[out] error 3131 * Pointer to error structure. 3132 * 3133 * @return 3134 * 0 on success, a negative errno value otherwise and rte_errno is set. 3135 */ 3136 int 3137 mlx5_flow_validate_item_gre(const struct rte_flow_item *item, 3138 uint64_t item_flags, 3139 uint8_t target_protocol, 3140 struct rte_flow_error *error) 3141 { 3142 const struct rte_flow_item_gre *spec __rte_unused = item->spec; 3143 const struct rte_flow_item_gre *mask = item->mask; 3144 int ret; 3145 const struct rte_flow_item_gre nic_mask = { 3146 .c_rsvd0_ver = RTE_BE16(0xB000), 3147 .protocol = RTE_BE16(UINT16_MAX), 3148 }; 3149 3150 if (target_protocol != 0xff && target_protocol != IPPROTO_GRE) 3151 return rte_flow_error_set(error, EINVAL, 3152 RTE_FLOW_ERROR_TYPE_ITEM, item, 3153 "protocol filtering not compatible" 3154 " with this GRE layer"); 3155 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 3156 return rte_flow_error_set(error, ENOTSUP, 3157 RTE_FLOW_ERROR_TYPE_ITEM, item, 3158 "multiple tunnel layers not" 3159 " supported"); 3160 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3)) 3161 return rte_flow_error_set(error, ENOTSUP, 3162 RTE_FLOW_ERROR_TYPE_ITEM, item, 3163 "L3 Layer is missing"); 3164 if (!mask) 3165 mask = &rte_flow_item_gre_mask; 3166 ret = mlx5_flow_item_acceptable 3167 (item, (const uint8_t *)mask, 3168 (const uint8_t *)&nic_mask, 3169 sizeof(struct rte_flow_item_gre), MLX5_ITEM_RANGE_NOT_ACCEPTED, 3170 error); 3171 if (ret < 0) 3172 return ret; 3173 #ifndef HAVE_MLX5DV_DR 3174 #ifndef HAVE_IBV_DEVICE_MPLS_SUPPORT 3175 if (spec && (spec->protocol & mask->protocol)) 3176 return rte_flow_error_set(error, ENOTSUP, 3177 RTE_FLOW_ERROR_TYPE_ITEM, item, 3178 "without MPLS support the" 3179 " specification cannot be used for" 3180 " filtering"); 3181 #endif 3182 #endif 3183 return 0; 3184 } 3185 3186 /** 3187 * Validate Geneve item. 3188 * 3189 * @param[in] item 3190 * Item specification. 3191 * @param[in] itemFlags 3192 * Bit-fields that holds the items detected until now. 3193 * @param[in] enPriv 3194 * Pointer to the private data structure. 3195 * @param[out] error 3196 * Pointer to error structure. 3197 * 3198 * @return 3199 * 0 on success, a negative errno value otherwise and rte_errno is set. 3200 */ 3201 3202 int 3203 mlx5_flow_validate_item_geneve(const struct rte_flow_item *item, 3204 uint64_t item_flags, 3205 struct rte_eth_dev *dev, 3206 struct rte_flow_error *error) 3207 { 3208 struct mlx5_priv *priv = dev->data->dev_private; 3209 const struct rte_flow_item_geneve *spec = item->spec; 3210 const struct rte_flow_item_geneve *mask = item->mask; 3211 int ret; 3212 uint16_t gbhdr; 3213 uint8_t opt_len = priv->sh->cdev->config.hca_attr.geneve_max_opt_len ? 3214 MLX5_GENEVE_OPT_LEN_1 : MLX5_GENEVE_OPT_LEN_0; 3215 const struct rte_flow_item_geneve nic_mask = { 3216 .ver_opt_len_o_c_rsvd0 = RTE_BE16(0x3f80), 3217 .vni = "\xff\xff\xff", 3218 .protocol = RTE_BE16(UINT16_MAX), 3219 }; 3220 3221 if (!priv->sh->cdev->config.hca_attr.tunnel_stateless_geneve_rx) 3222 return rte_flow_error_set(error, ENOTSUP, 3223 RTE_FLOW_ERROR_TYPE_ITEM, item, 3224 "L3 Geneve is not enabled by device" 3225 " parameter and/or not configured in" 3226 " firmware"); 3227 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 3228 return rte_flow_error_set(error, ENOTSUP, 3229 RTE_FLOW_ERROR_TYPE_ITEM, item, 3230 "multiple tunnel layers not" 3231 " supported"); 3232 /* 3233 * Verify only UDPv4 is present as defined in 3234 * https://tools.ietf.org/html/rfc7348 3235 */ 3236 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 3237 return rte_flow_error_set(error, EINVAL, 3238 RTE_FLOW_ERROR_TYPE_ITEM, item, 3239 "no outer UDP layer found"); 3240 if (!mask) 3241 mask = &rte_flow_item_geneve_mask; 3242 ret = mlx5_flow_item_acceptable 3243 (item, (const uint8_t *)mask, 3244 (const uint8_t *)&nic_mask, 3245 sizeof(struct rte_flow_item_geneve), 3246 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 3247 if (ret) 3248 return ret; 3249 if (spec) { 3250 gbhdr = rte_be_to_cpu_16(spec->ver_opt_len_o_c_rsvd0); 3251 if (MLX5_GENEVE_VER_VAL(gbhdr) || 3252 MLX5_GENEVE_CRITO_VAL(gbhdr) || 3253 MLX5_GENEVE_RSVD_VAL(gbhdr) || spec->rsvd1) 3254 return rte_flow_error_set(error, ENOTSUP, 3255 RTE_FLOW_ERROR_TYPE_ITEM, 3256 item, 3257 "Geneve protocol unsupported" 3258 " fields are being used"); 3259 if (MLX5_GENEVE_OPTLEN_VAL(gbhdr) > opt_len) 3260 return rte_flow_error_set 3261 (error, ENOTSUP, 3262 RTE_FLOW_ERROR_TYPE_ITEM, 3263 item, 3264 "Unsupported Geneve options length"); 3265 } 3266 if (!(item_flags & MLX5_FLOW_LAYER_OUTER)) 3267 return rte_flow_error_set 3268 (error, ENOTSUP, 3269 RTE_FLOW_ERROR_TYPE_ITEM, item, 3270 "Geneve tunnel must be fully defined"); 3271 return 0; 3272 } 3273 3274 /** 3275 * Validate Geneve TLV option item. 3276 * 3277 * @param[in] item 3278 * Item specification. 3279 * @param[in] last_item 3280 * Previous validated item in the pattern items. 3281 * @param[in] geneve_item 3282 * Previous GENEVE item specification. 3283 * @param[in] dev 3284 * Pointer to the rte_eth_dev structure. 3285 * @param[out] error 3286 * Pointer to error structure. 3287 * 3288 * @return 3289 * 0 on success, a negative errno value otherwise and rte_errno is set. 3290 */ 3291 int 3292 mlx5_flow_validate_item_geneve_opt(const struct rte_flow_item *item, 3293 uint64_t last_item, 3294 const struct rte_flow_item *geneve_item, 3295 struct rte_eth_dev *dev, 3296 struct rte_flow_error *error) 3297 { 3298 struct mlx5_priv *priv = dev->data->dev_private; 3299 struct mlx5_dev_ctx_shared *sh = priv->sh; 3300 struct mlx5_geneve_tlv_option_resource *geneve_opt_resource; 3301 struct mlx5_hca_attr *hca_attr = &sh->cdev->config.hca_attr; 3302 uint8_t data_max_supported = 3303 hca_attr->max_geneve_tlv_option_data_len * 4; 3304 const struct rte_flow_item_geneve *geneve_spec; 3305 const struct rte_flow_item_geneve *geneve_mask; 3306 const struct rte_flow_item_geneve_opt *spec = item->spec; 3307 const struct rte_flow_item_geneve_opt *mask = item->mask; 3308 unsigned int i; 3309 unsigned int data_len; 3310 uint8_t tlv_option_len; 3311 uint16_t optlen_m, optlen_v; 3312 const struct rte_flow_item_geneve_opt full_mask = { 3313 .option_class = RTE_BE16(0xffff), 3314 .option_type = 0xff, 3315 .option_len = 0x1f, 3316 }; 3317 3318 if (!mask) 3319 mask = &rte_flow_item_geneve_opt_mask; 3320 if (!spec) 3321 return rte_flow_error_set 3322 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3323 "Geneve TLV opt class/type/length must be specified"); 3324 if ((uint32_t)spec->option_len > MLX5_GENEVE_OPTLEN_MASK) 3325 return rte_flow_error_set 3326 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3327 "Geneve TLV opt length exceeds the limit (31)"); 3328 /* Check if class type and length masks are full. */ 3329 if (full_mask.option_class != mask->option_class || 3330 full_mask.option_type != mask->option_type || 3331 full_mask.option_len != (mask->option_len & full_mask.option_len)) 3332 return rte_flow_error_set 3333 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3334 "Geneve TLV opt class/type/length masks must be full"); 3335 /* Check if length is supported */ 3336 if ((uint32_t)spec->option_len > 3337 hca_attr->max_geneve_tlv_option_data_len) 3338 return rte_flow_error_set 3339 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3340 "Geneve TLV opt length not supported"); 3341 if (hca_attr->max_geneve_tlv_options > 1) 3342 DRV_LOG(DEBUG, 3343 "max_geneve_tlv_options supports more than 1 option"); 3344 /* Check GENEVE item preceding. */ 3345 if (!geneve_item || !(last_item & MLX5_FLOW_LAYER_GENEVE)) 3346 return rte_flow_error_set 3347 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3348 "Geneve opt item must be preceded with Geneve item"); 3349 geneve_spec = geneve_item->spec; 3350 geneve_mask = geneve_item->mask ? geneve_item->mask : 3351 &rte_flow_item_geneve_mask; 3352 /* Check if GENEVE TLV option size doesn't exceed option length */ 3353 if (geneve_spec && (geneve_mask->ver_opt_len_o_c_rsvd0 || 3354 geneve_spec->ver_opt_len_o_c_rsvd0)) { 3355 tlv_option_len = spec->option_len & mask->option_len; 3356 optlen_v = rte_be_to_cpu_16(geneve_spec->ver_opt_len_o_c_rsvd0); 3357 optlen_v = MLX5_GENEVE_OPTLEN_VAL(optlen_v); 3358 optlen_m = rte_be_to_cpu_16(geneve_mask->ver_opt_len_o_c_rsvd0); 3359 optlen_m = MLX5_GENEVE_OPTLEN_VAL(optlen_m); 3360 if ((optlen_v & optlen_m) <= tlv_option_len) 3361 return rte_flow_error_set 3362 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3363 "GENEVE TLV option length exceeds optlen"); 3364 } 3365 /* Check if length is 0 or data is 0. */ 3366 if (spec->data == NULL || spec->option_len == 0) 3367 return rte_flow_error_set 3368 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3369 "Geneve TLV opt with zero data/length not supported"); 3370 /* Check not all data & mask are 0. */ 3371 data_len = spec->option_len * 4; 3372 if (mask->data == NULL) { 3373 for (i = 0; i < data_len; i++) 3374 if (spec->data[i]) 3375 break; 3376 if (i == data_len) 3377 return rte_flow_error_set(error, ENOTSUP, 3378 RTE_FLOW_ERROR_TYPE_ITEM, item, 3379 "Can't match on Geneve option data 0"); 3380 } else { 3381 for (i = 0; i < data_len; i++) 3382 if (spec->data[i] & mask->data[i]) 3383 break; 3384 if (i == data_len) 3385 return rte_flow_error_set(error, ENOTSUP, 3386 RTE_FLOW_ERROR_TYPE_ITEM, item, 3387 "Can't match on Geneve option data and mask 0"); 3388 /* Check data mask supported. */ 3389 for (i = data_max_supported; i < data_len ; i++) 3390 if (mask->data[i]) 3391 return rte_flow_error_set(error, ENOTSUP, 3392 RTE_FLOW_ERROR_TYPE_ITEM, item, 3393 "Data mask is of unsupported size"); 3394 } 3395 /* Check GENEVE option is supported in NIC. */ 3396 if (!hca_attr->geneve_tlv_opt) 3397 return rte_flow_error_set 3398 (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, 3399 "Geneve TLV opt not supported"); 3400 /* Check if we already have geneve option with different type/class. */ 3401 rte_spinlock_lock(&sh->geneve_tlv_opt_sl); 3402 geneve_opt_resource = sh->geneve_tlv_option_resource; 3403 if (geneve_opt_resource != NULL) 3404 if (geneve_opt_resource->option_class != spec->option_class || 3405 geneve_opt_resource->option_type != spec->option_type || 3406 geneve_opt_resource->length != spec->option_len) { 3407 rte_spinlock_unlock(&sh->geneve_tlv_opt_sl); 3408 return rte_flow_error_set(error, ENOTSUP, 3409 RTE_FLOW_ERROR_TYPE_ITEM, item, 3410 "Only one Geneve TLV option supported"); 3411 } 3412 rte_spinlock_unlock(&sh->geneve_tlv_opt_sl); 3413 return 0; 3414 } 3415 3416 /** 3417 * Validate MPLS item. 3418 * 3419 * @param[in] dev 3420 * Pointer to the rte_eth_dev structure. 3421 * @param[in] item 3422 * Item specification. 3423 * @param[in] item_flags 3424 * Bit-fields that holds the items detected until now. 3425 * @param[in] prev_layer 3426 * The protocol layer indicated in previous item. 3427 * @param[out] error 3428 * Pointer to error structure. 3429 * 3430 * @return 3431 * 0 on success, a negative errno value otherwise and rte_errno is set. 3432 */ 3433 int 3434 mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev __rte_unused, 3435 const struct rte_flow_item *item __rte_unused, 3436 uint64_t item_flags __rte_unused, 3437 uint64_t prev_layer __rte_unused, 3438 struct rte_flow_error *error) 3439 { 3440 #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 3441 const struct rte_flow_item_mpls *mask = item->mask; 3442 struct mlx5_priv *priv = dev->data->dev_private; 3443 int ret; 3444 3445 if (!priv->sh->dev_cap.mpls_en) 3446 return rte_flow_error_set(error, ENOTSUP, 3447 RTE_FLOW_ERROR_TYPE_ITEM, item, 3448 "MPLS not supported or" 3449 " disabled in firmware" 3450 " configuration."); 3451 /* MPLS over UDP, GRE is allowed */ 3452 if (!(prev_layer & (MLX5_FLOW_LAYER_OUTER_L4_UDP | 3453 MLX5_FLOW_LAYER_GRE | 3454 MLX5_FLOW_LAYER_GRE_KEY))) 3455 return rte_flow_error_set(error, EINVAL, 3456 RTE_FLOW_ERROR_TYPE_ITEM, item, 3457 "protocol filtering not compatible" 3458 " with MPLS layer"); 3459 /* Multi-tunnel isn't allowed but MPLS over GRE is an exception. */ 3460 if ((item_flags & MLX5_FLOW_LAYER_TUNNEL) && 3461 !(item_flags & MLX5_FLOW_LAYER_GRE)) 3462 return rte_flow_error_set(error, ENOTSUP, 3463 RTE_FLOW_ERROR_TYPE_ITEM, item, 3464 "multiple tunnel layers not" 3465 " supported"); 3466 if (!mask) 3467 mask = &rte_flow_item_mpls_mask; 3468 ret = mlx5_flow_item_acceptable 3469 (item, (const uint8_t *)mask, 3470 (const uint8_t *)&rte_flow_item_mpls_mask, 3471 sizeof(struct rte_flow_item_mpls), 3472 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 3473 if (ret < 0) 3474 return ret; 3475 return 0; 3476 #else 3477 return rte_flow_error_set(error, ENOTSUP, 3478 RTE_FLOW_ERROR_TYPE_ITEM, item, 3479 "MPLS is not supported by Verbs, please" 3480 " update."); 3481 #endif 3482 } 3483 3484 /** 3485 * Validate NVGRE item. 3486 * 3487 * @param[in] item 3488 * Item specification. 3489 * @param[in] item_flags 3490 * Bit flags to mark detected items. 3491 * @param[in] target_protocol 3492 * The next protocol in the previous item. 3493 * @param[out] error 3494 * Pointer to error structure. 3495 * 3496 * @return 3497 * 0 on success, a negative errno value otherwise and rte_errno is set. 3498 */ 3499 int 3500 mlx5_flow_validate_item_nvgre(const struct rte_flow_item *item, 3501 uint64_t item_flags, 3502 uint8_t target_protocol, 3503 struct rte_flow_error *error) 3504 { 3505 const struct rte_flow_item_nvgre *mask = item->mask; 3506 int ret; 3507 3508 if (target_protocol != 0xff && target_protocol != IPPROTO_GRE) 3509 return rte_flow_error_set(error, EINVAL, 3510 RTE_FLOW_ERROR_TYPE_ITEM, item, 3511 "protocol filtering not compatible" 3512 " with this GRE layer"); 3513 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 3514 return rte_flow_error_set(error, ENOTSUP, 3515 RTE_FLOW_ERROR_TYPE_ITEM, item, 3516 "multiple tunnel layers not" 3517 " supported"); 3518 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3)) 3519 return rte_flow_error_set(error, ENOTSUP, 3520 RTE_FLOW_ERROR_TYPE_ITEM, item, 3521 "L3 Layer is missing"); 3522 if (!mask) 3523 mask = &rte_flow_item_nvgre_mask; 3524 ret = mlx5_flow_item_acceptable 3525 (item, (const uint8_t *)mask, 3526 (const uint8_t *)&rte_flow_item_nvgre_mask, 3527 sizeof(struct rte_flow_item_nvgre), 3528 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 3529 if (ret < 0) 3530 return ret; 3531 return 0; 3532 } 3533 3534 /** 3535 * Validate eCPRI item. 3536 * 3537 * @param[in] item 3538 * Item specification. 3539 * @param[in] item_flags 3540 * Bit-fields that holds the items detected until now. 3541 * @param[in] last_item 3542 * Previous validated item in the pattern items. 3543 * @param[in] ether_type 3544 * Type in the ethernet layer header (including dot1q). 3545 * @param[in] acc_mask 3546 * Acceptable mask, if NULL default internal default mask 3547 * will be used to check whether item fields are supported. 3548 * @param[out] error 3549 * Pointer to error structure. 3550 * 3551 * @return 3552 * 0 on success, a negative errno value otherwise and rte_errno is set. 3553 */ 3554 int 3555 mlx5_flow_validate_item_ecpri(const struct rte_flow_item *item, 3556 uint64_t item_flags, 3557 uint64_t last_item, 3558 uint16_t ether_type, 3559 const struct rte_flow_item_ecpri *acc_mask, 3560 struct rte_flow_error *error) 3561 { 3562 const struct rte_flow_item_ecpri *mask = item->mask; 3563 const struct rte_flow_item_ecpri nic_mask = { 3564 .hdr = { 3565 .common = { 3566 .u32 = 3567 RTE_BE32(((const struct rte_ecpri_common_hdr) { 3568 .type = 0xFF, 3569 }).u32), 3570 }, 3571 .dummy[0] = 0xFFFFFFFF, 3572 }, 3573 }; 3574 const uint64_t outer_l2_vlan = (MLX5_FLOW_LAYER_OUTER_L2 | 3575 MLX5_FLOW_LAYER_OUTER_VLAN); 3576 struct rte_flow_item_ecpri mask_lo; 3577 3578 if (!(last_item & outer_l2_vlan) && 3579 last_item != MLX5_FLOW_LAYER_OUTER_L4_UDP) 3580 return rte_flow_error_set(error, EINVAL, 3581 RTE_FLOW_ERROR_TYPE_ITEM, item, 3582 "eCPRI can only follow L2/VLAN layer or UDP layer"); 3583 if ((last_item & outer_l2_vlan) && ether_type && 3584 ether_type != RTE_ETHER_TYPE_ECPRI) 3585 return rte_flow_error_set(error, EINVAL, 3586 RTE_FLOW_ERROR_TYPE_ITEM, item, 3587 "eCPRI cannot follow L2/VLAN layer which ether type is not 0xAEFE"); 3588 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 3589 return rte_flow_error_set(error, EINVAL, 3590 RTE_FLOW_ERROR_TYPE_ITEM, item, 3591 "eCPRI with tunnel is not supported right now"); 3592 if (item_flags & MLX5_FLOW_LAYER_OUTER_L3) 3593 return rte_flow_error_set(error, ENOTSUP, 3594 RTE_FLOW_ERROR_TYPE_ITEM, item, 3595 "multiple L3 layers not supported"); 3596 else if (item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP) 3597 return rte_flow_error_set(error, EINVAL, 3598 RTE_FLOW_ERROR_TYPE_ITEM, item, 3599 "eCPRI cannot coexist with a TCP layer"); 3600 /* In specification, eCPRI could be over UDP layer. */ 3601 else if (item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP) 3602 return rte_flow_error_set(error, EINVAL, 3603 RTE_FLOW_ERROR_TYPE_ITEM, item, 3604 "eCPRI over UDP layer is not yet supported right now"); 3605 /* Mask for type field in common header could be zero. */ 3606 if (!mask) 3607 mask = &rte_flow_item_ecpri_mask; 3608 mask_lo.hdr.common.u32 = rte_be_to_cpu_32(mask->hdr.common.u32); 3609 /* Input mask is in big-endian format. */ 3610 if (mask_lo.hdr.common.type != 0 && mask_lo.hdr.common.type != 0xff) 3611 return rte_flow_error_set(error, EINVAL, 3612 RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, 3613 "partial mask is not supported for protocol"); 3614 else if (mask_lo.hdr.common.type == 0 && mask->hdr.dummy[0] != 0) 3615 return rte_flow_error_set(error, EINVAL, 3616 RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, 3617 "message header mask must be after a type mask"); 3618 return mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 3619 acc_mask ? (const uint8_t *)acc_mask 3620 : (const uint8_t *)&nic_mask, 3621 sizeof(struct rte_flow_item_ecpri), 3622 MLX5_ITEM_RANGE_NOT_ACCEPTED, error); 3623 } 3624 3625 static int 3626 flow_null_validate(struct rte_eth_dev *dev __rte_unused, 3627 const struct rte_flow_attr *attr __rte_unused, 3628 const struct rte_flow_item items[] __rte_unused, 3629 const struct rte_flow_action actions[] __rte_unused, 3630 bool external __rte_unused, 3631 int hairpin __rte_unused, 3632 struct rte_flow_error *error) 3633 { 3634 return rte_flow_error_set(error, ENOTSUP, 3635 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 3636 } 3637 3638 static struct mlx5_flow * 3639 flow_null_prepare(struct rte_eth_dev *dev __rte_unused, 3640 const struct rte_flow_attr *attr __rte_unused, 3641 const struct rte_flow_item items[] __rte_unused, 3642 const struct rte_flow_action actions[] __rte_unused, 3643 struct rte_flow_error *error) 3644 { 3645 rte_flow_error_set(error, ENOTSUP, 3646 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 3647 return NULL; 3648 } 3649 3650 static int 3651 flow_null_translate(struct rte_eth_dev *dev __rte_unused, 3652 struct mlx5_flow *dev_flow __rte_unused, 3653 const struct rte_flow_attr *attr __rte_unused, 3654 const struct rte_flow_item items[] __rte_unused, 3655 const struct rte_flow_action actions[] __rte_unused, 3656 struct rte_flow_error *error) 3657 { 3658 return rte_flow_error_set(error, ENOTSUP, 3659 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 3660 } 3661 3662 static int 3663 flow_null_apply(struct rte_eth_dev *dev __rte_unused, 3664 struct rte_flow *flow __rte_unused, 3665 struct rte_flow_error *error) 3666 { 3667 return rte_flow_error_set(error, ENOTSUP, 3668 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 3669 } 3670 3671 static void 3672 flow_null_remove(struct rte_eth_dev *dev __rte_unused, 3673 struct rte_flow *flow __rte_unused) 3674 { 3675 } 3676 3677 static void 3678 flow_null_destroy(struct rte_eth_dev *dev __rte_unused, 3679 struct rte_flow *flow __rte_unused) 3680 { 3681 } 3682 3683 static int 3684 flow_null_query(struct rte_eth_dev *dev __rte_unused, 3685 struct rte_flow *flow __rte_unused, 3686 const struct rte_flow_action *actions __rte_unused, 3687 void *data __rte_unused, 3688 struct rte_flow_error *error) 3689 { 3690 return rte_flow_error_set(error, ENOTSUP, 3691 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 3692 } 3693 3694 static int 3695 flow_null_sync_domain(struct rte_eth_dev *dev __rte_unused, 3696 uint32_t domains __rte_unused, 3697 uint32_t flags __rte_unused) 3698 { 3699 return 0; 3700 } 3701 3702 /* Void driver to protect from null pointer reference. */ 3703 const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops = { 3704 .validate = flow_null_validate, 3705 .prepare = flow_null_prepare, 3706 .translate = flow_null_translate, 3707 .apply = flow_null_apply, 3708 .remove = flow_null_remove, 3709 .destroy = flow_null_destroy, 3710 .query = flow_null_query, 3711 .sync_domain = flow_null_sync_domain, 3712 }; 3713 3714 /** 3715 * Select flow driver type according to flow attributes and device 3716 * configuration. 3717 * 3718 * @param[in] dev 3719 * Pointer to the dev structure. 3720 * @param[in] attr 3721 * Pointer to the flow attributes. 3722 * 3723 * @return 3724 * flow driver type, MLX5_FLOW_TYPE_MAX otherwise. 3725 */ 3726 static enum mlx5_flow_drv_type 3727 flow_get_drv_type(struct rte_eth_dev *dev, const struct rte_flow_attr *attr) 3728 { 3729 struct mlx5_priv *priv = dev->data->dev_private; 3730 /* The OS can determine first a specific flow type (DV, VERBS) */ 3731 enum mlx5_flow_drv_type type = mlx5_flow_os_get_type(); 3732 3733 if (type != MLX5_FLOW_TYPE_MAX) 3734 return type; 3735 /* 3736 * Currently when dv_flow_en == 2, only HW steering engine is 3737 * supported. New engines can also be chosen here if ready. 3738 */ 3739 if (priv->sh->config.dv_flow_en == 2) 3740 return MLX5_FLOW_TYPE_HW; 3741 if (!attr) 3742 return MLX5_FLOW_TYPE_MIN; 3743 /* If no OS specific type - continue with DV/VERBS selection */ 3744 if (attr->transfer && priv->sh->config.dv_esw_en) 3745 type = MLX5_FLOW_TYPE_DV; 3746 if (!attr->transfer) 3747 type = priv->sh->config.dv_flow_en ? MLX5_FLOW_TYPE_DV : 3748 MLX5_FLOW_TYPE_VERBS; 3749 return type; 3750 } 3751 3752 #define flow_get_drv_ops(type) flow_drv_ops[type] 3753 3754 /** 3755 * Flow driver validation API. This abstracts calling driver specific functions. 3756 * The type of flow driver is determined according to flow attributes. 3757 * 3758 * @param[in] dev 3759 * Pointer to the dev structure. 3760 * @param[in] attr 3761 * Pointer to the flow attributes. 3762 * @param[in] items 3763 * Pointer to the list of items. 3764 * @param[in] actions 3765 * Pointer to the list of actions. 3766 * @param[in] external 3767 * This flow rule is created by request external to PMD. 3768 * @param[in] hairpin 3769 * Number of hairpin TX actions, 0 means classic flow. 3770 * @param[out] error 3771 * Pointer to the error structure. 3772 * 3773 * @return 3774 * 0 on success, a negative errno value otherwise and rte_errno is set. 3775 */ 3776 static inline int 3777 flow_drv_validate(struct rte_eth_dev *dev, 3778 const struct rte_flow_attr *attr, 3779 const struct rte_flow_item items[], 3780 const struct rte_flow_action actions[], 3781 bool external, int hairpin, struct rte_flow_error *error) 3782 { 3783 const struct mlx5_flow_driver_ops *fops; 3784 enum mlx5_flow_drv_type type = flow_get_drv_type(dev, attr); 3785 3786 fops = flow_get_drv_ops(type); 3787 return fops->validate(dev, attr, items, actions, external, 3788 hairpin, error); 3789 } 3790 3791 /** 3792 * Flow driver preparation API. This abstracts calling driver specific 3793 * functions. Parent flow (rte_flow) should have driver type (drv_type). It 3794 * calculates the size of memory required for device flow, allocates the memory, 3795 * initializes the device flow and returns the pointer. 3796 * 3797 * @note 3798 * This function initializes device flow structure such as dv or verbs in 3799 * struct mlx5_flow. However, it is caller's responsibility to initialize the 3800 * rest. For example, adding returning device flow to flow->dev_flow list and 3801 * setting backward reference to the flow should be done out of this function. 3802 * layers field is not filled either. 3803 * 3804 * @param[in] dev 3805 * Pointer to the dev structure. 3806 * @param[in] attr 3807 * Pointer to the flow attributes. 3808 * @param[in] items 3809 * Pointer to the list of items. 3810 * @param[in] actions 3811 * Pointer to the list of actions. 3812 * @param[in] flow_idx 3813 * This memory pool index to the flow. 3814 * @param[out] error 3815 * Pointer to the error structure. 3816 * 3817 * @return 3818 * Pointer to device flow on success, otherwise NULL and rte_errno is set. 3819 */ 3820 static inline struct mlx5_flow * 3821 flow_drv_prepare(struct rte_eth_dev *dev, 3822 const struct rte_flow *flow, 3823 const struct rte_flow_attr *attr, 3824 const struct rte_flow_item items[], 3825 const struct rte_flow_action actions[], 3826 uint32_t flow_idx, 3827 struct rte_flow_error *error) 3828 { 3829 const struct mlx5_flow_driver_ops *fops; 3830 enum mlx5_flow_drv_type type = flow->drv_type; 3831 struct mlx5_flow *mlx5_flow = NULL; 3832 3833 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 3834 fops = flow_get_drv_ops(type); 3835 mlx5_flow = fops->prepare(dev, attr, items, actions, error); 3836 if (mlx5_flow) 3837 mlx5_flow->flow_idx = flow_idx; 3838 return mlx5_flow; 3839 } 3840 3841 /** 3842 * Flow driver translation API. This abstracts calling driver specific 3843 * functions. Parent flow (rte_flow) should have driver type (drv_type). It 3844 * translates a generic flow into a driver flow. flow_drv_prepare() must 3845 * precede. 3846 * 3847 * @note 3848 * dev_flow->layers could be filled as a result of parsing during translation 3849 * if needed by flow_drv_apply(). dev_flow->flow->actions can also be filled 3850 * if necessary. As a flow can have multiple dev_flows by RSS flow expansion, 3851 * flow->actions could be overwritten even though all the expanded dev_flows 3852 * have the same actions. 3853 * 3854 * @param[in] dev 3855 * Pointer to the rte dev structure. 3856 * @param[in, out] dev_flow 3857 * Pointer to the mlx5 flow. 3858 * @param[in] attr 3859 * Pointer to the flow attributes. 3860 * @param[in] items 3861 * Pointer to the list of items. 3862 * @param[in] actions 3863 * Pointer to the list of actions. 3864 * @param[out] error 3865 * Pointer to the error structure. 3866 * 3867 * @return 3868 * 0 on success, a negative errno value otherwise and rte_errno is set. 3869 */ 3870 static inline int 3871 flow_drv_translate(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow, 3872 const struct rte_flow_attr *attr, 3873 const struct rte_flow_item items[], 3874 const struct rte_flow_action actions[], 3875 struct rte_flow_error *error) 3876 { 3877 const struct mlx5_flow_driver_ops *fops; 3878 enum mlx5_flow_drv_type type = dev_flow->flow->drv_type; 3879 3880 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 3881 fops = flow_get_drv_ops(type); 3882 return fops->translate(dev, dev_flow, attr, items, actions, error); 3883 } 3884 3885 /** 3886 * Flow driver apply API. This abstracts calling driver specific functions. 3887 * Parent flow (rte_flow) should have driver type (drv_type). It applies 3888 * translated driver flows on to device. flow_drv_translate() must precede. 3889 * 3890 * @param[in] dev 3891 * Pointer to Ethernet device structure. 3892 * @param[in, out] flow 3893 * Pointer to flow structure. 3894 * @param[out] error 3895 * Pointer to error structure. 3896 * 3897 * @return 3898 * 0 on success, a negative errno value otherwise and rte_errno is set. 3899 */ 3900 static inline int 3901 flow_drv_apply(struct rte_eth_dev *dev, struct rte_flow *flow, 3902 struct rte_flow_error *error) 3903 { 3904 const struct mlx5_flow_driver_ops *fops; 3905 enum mlx5_flow_drv_type type = flow->drv_type; 3906 3907 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 3908 fops = flow_get_drv_ops(type); 3909 return fops->apply(dev, flow, error); 3910 } 3911 3912 /** 3913 * Flow driver destroy API. This abstracts calling driver specific functions. 3914 * Parent flow (rte_flow) should have driver type (drv_type). It removes a flow 3915 * on device and releases resources of the flow. 3916 * 3917 * @param[in] dev 3918 * Pointer to Ethernet device. 3919 * @param[in, out] flow 3920 * Pointer to flow structure. 3921 */ 3922 static inline void 3923 flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) 3924 { 3925 const struct mlx5_flow_driver_ops *fops; 3926 enum mlx5_flow_drv_type type = flow->drv_type; 3927 3928 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 3929 fops = flow_get_drv_ops(type); 3930 fops->destroy(dev, flow); 3931 } 3932 3933 /** 3934 * Flow driver find RSS policy tbl API. This abstracts calling driver 3935 * specific functions. Parent flow (rte_flow) should have driver 3936 * type (drv_type). It will find the RSS policy table that has the rss_desc. 3937 * 3938 * @param[in] dev 3939 * Pointer to Ethernet device. 3940 * @param[in, out] flow 3941 * Pointer to flow structure. 3942 * @param[in] policy 3943 * Pointer to meter policy table. 3944 * @param[in] rss_desc 3945 * Pointer to rss_desc 3946 */ 3947 static struct mlx5_flow_meter_sub_policy * 3948 flow_drv_meter_sub_policy_rss_prepare(struct rte_eth_dev *dev, 3949 struct rte_flow *flow, 3950 struct mlx5_flow_meter_policy *policy, 3951 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS]) 3952 { 3953 const struct mlx5_flow_driver_ops *fops; 3954 enum mlx5_flow_drv_type type = flow->drv_type; 3955 3956 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 3957 fops = flow_get_drv_ops(type); 3958 return fops->meter_sub_policy_rss_prepare(dev, policy, rss_desc); 3959 } 3960 3961 /** 3962 * Flow driver color tag rule API. This abstracts calling driver 3963 * specific functions. Parent flow (rte_flow) should have driver 3964 * type (drv_type). It will create the color tag rules in hierarchy meter. 3965 * 3966 * @param[in] dev 3967 * Pointer to Ethernet device. 3968 * @param[in, out] flow 3969 * Pointer to flow structure. 3970 * @param[in] fm 3971 * Pointer to flow meter structure. 3972 * @param[in] src_port 3973 * The src port this extra rule should use. 3974 * @param[in] item 3975 * The src port id match item. 3976 * @param[out] error 3977 * Pointer to error structure. 3978 */ 3979 static int 3980 flow_drv_mtr_hierarchy_rule_create(struct rte_eth_dev *dev, 3981 struct rte_flow *flow, 3982 struct mlx5_flow_meter_info *fm, 3983 int32_t src_port, 3984 const struct rte_flow_item *item, 3985 struct rte_flow_error *error) 3986 { 3987 const struct mlx5_flow_driver_ops *fops; 3988 enum mlx5_flow_drv_type type = flow->drv_type; 3989 3990 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 3991 fops = flow_get_drv_ops(type); 3992 return fops->meter_hierarchy_rule_create(dev, fm, 3993 src_port, item, error); 3994 } 3995 3996 /** 3997 * Get RSS action from the action list. 3998 * 3999 * @param[in] dev 4000 * Pointer to Ethernet device. 4001 * @param[in] actions 4002 * Pointer to the list of actions. 4003 * @param[in] flow 4004 * Parent flow structure pointer. 4005 * 4006 * @return 4007 * Pointer to the RSS action if exist, else return NULL. 4008 */ 4009 static const struct rte_flow_action_rss* 4010 flow_get_rss_action(struct rte_eth_dev *dev, 4011 const struct rte_flow_action actions[]) 4012 { 4013 struct mlx5_priv *priv = dev->data->dev_private; 4014 const struct rte_flow_action_rss *rss = NULL; 4015 struct mlx5_meter_policy_action_container *acg; 4016 struct mlx5_meter_policy_action_container *acy; 4017 4018 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 4019 switch (actions->type) { 4020 case RTE_FLOW_ACTION_TYPE_RSS: 4021 rss = actions->conf; 4022 break; 4023 case RTE_FLOW_ACTION_TYPE_SAMPLE: 4024 { 4025 const struct rte_flow_action_sample *sample = 4026 actions->conf; 4027 const struct rte_flow_action *act = sample->actions; 4028 for (; act->type != RTE_FLOW_ACTION_TYPE_END; act++) 4029 if (act->type == RTE_FLOW_ACTION_TYPE_RSS) 4030 rss = act->conf; 4031 break; 4032 } 4033 case RTE_FLOW_ACTION_TYPE_METER: 4034 { 4035 uint32_t mtr_idx; 4036 struct mlx5_flow_meter_info *fm; 4037 struct mlx5_flow_meter_policy *policy; 4038 const struct rte_flow_action_meter *mtr = actions->conf; 4039 4040 fm = mlx5_flow_meter_find(priv, mtr->mtr_id, &mtr_idx); 4041 if (fm && !fm->def_policy) { 4042 policy = mlx5_flow_meter_policy_find(dev, 4043 fm->policy_id, NULL); 4044 MLX5_ASSERT(policy); 4045 if (policy->is_hierarchy) { 4046 policy = 4047 mlx5_flow_meter_hierarchy_get_final_policy(dev, 4048 policy); 4049 if (!policy) 4050 return NULL; 4051 } 4052 if (policy->is_rss) { 4053 acg = 4054 &policy->act_cnt[RTE_COLOR_GREEN]; 4055 acy = 4056 &policy->act_cnt[RTE_COLOR_YELLOW]; 4057 if (acg->fate_action == 4058 MLX5_FLOW_FATE_SHARED_RSS) 4059 rss = acg->rss->conf; 4060 else if (acy->fate_action == 4061 MLX5_FLOW_FATE_SHARED_RSS) 4062 rss = acy->rss->conf; 4063 } 4064 } 4065 break; 4066 } 4067 default: 4068 break; 4069 } 4070 } 4071 return rss; 4072 } 4073 4074 /** 4075 * Get ASO age action by index. 4076 * 4077 * @param[in] dev 4078 * Pointer to the Ethernet device structure. 4079 * @param[in] age_idx 4080 * Index to the ASO age action. 4081 * 4082 * @return 4083 * The specified ASO age action. 4084 */ 4085 struct mlx5_aso_age_action* 4086 flow_aso_age_get_by_idx(struct rte_eth_dev *dev, uint32_t age_idx) 4087 { 4088 uint16_t pool_idx = age_idx & UINT16_MAX; 4089 uint16_t offset = (age_idx >> 16) & UINT16_MAX; 4090 struct mlx5_priv *priv = dev->data->dev_private; 4091 struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; 4092 struct mlx5_aso_age_pool *pool; 4093 4094 rte_rwlock_read_lock(&mng->resize_rwl); 4095 pool = mng->pools[pool_idx]; 4096 rte_rwlock_read_unlock(&mng->resize_rwl); 4097 return &pool->actions[offset - 1]; 4098 } 4099 4100 /* maps indirect action to translated direct in some actions array */ 4101 struct mlx5_translated_action_handle { 4102 struct rte_flow_action_handle *action; /**< Indirect action handle. */ 4103 int index; /**< Index in related array of rte_flow_action. */ 4104 }; 4105 4106 /** 4107 * Translates actions of type RTE_FLOW_ACTION_TYPE_INDIRECT to related 4108 * direct action if translation possible. 4109 * This functionality used to run same execution path for both direct and 4110 * indirect actions on flow create. All necessary preparations for indirect 4111 * action handling should be performed on *handle* actions list returned 4112 * from this call. 4113 * 4114 * @param[in] dev 4115 * Pointer to Ethernet device. 4116 * @param[in] actions 4117 * List of actions to translate. 4118 * @param[out] handle 4119 * List to store translated indirect action object handles. 4120 * @param[in, out] indir_n 4121 * Size of *handle* array. On return should be updated with number of 4122 * indirect actions retrieved from the *actions* list. 4123 * @param[out] translated_actions 4124 * List of actions where all indirect actions were translated to direct 4125 * if possible. NULL if no translation took place. 4126 * @param[out] error 4127 * Pointer to the error structure. 4128 * 4129 * @return 4130 * 0 on success, a negative errno value otherwise and rte_errno is set. 4131 */ 4132 static int 4133 flow_action_handles_translate(struct rte_eth_dev *dev, 4134 const struct rte_flow_action actions[], 4135 struct mlx5_translated_action_handle *handle, 4136 int *indir_n, 4137 struct rte_flow_action **translated_actions, 4138 struct rte_flow_error *error) 4139 { 4140 struct mlx5_priv *priv = dev->data->dev_private; 4141 struct rte_flow_action *translated = NULL; 4142 size_t actions_size; 4143 int n; 4144 int copied_n = 0; 4145 struct mlx5_translated_action_handle *handle_end = NULL; 4146 4147 for (n = 0; actions[n].type != RTE_FLOW_ACTION_TYPE_END; n++) { 4148 if (actions[n].type != RTE_FLOW_ACTION_TYPE_INDIRECT) 4149 continue; 4150 if (copied_n == *indir_n) { 4151 return rte_flow_error_set 4152 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_NUM, 4153 NULL, "too many shared actions"); 4154 } 4155 rte_memcpy(&handle[copied_n].action, &actions[n].conf, 4156 sizeof(actions[n].conf)); 4157 handle[copied_n].index = n; 4158 copied_n++; 4159 } 4160 n++; 4161 *indir_n = copied_n; 4162 if (!copied_n) 4163 return 0; 4164 actions_size = sizeof(struct rte_flow_action) * n; 4165 translated = mlx5_malloc(MLX5_MEM_ZERO, actions_size, 0, SOCKET_ID_ANY); 4166 if (!translated) { 4167 rte_errno = ENOMEM; 4168 return -ENOMEM; 4169 } 4170 memcpy(translated, actions, actions_size); 4171 for (handle_end = handle + copied_n; handle < handle_end; handle++) { 4172 struct mlx5_shared_action_rss *shared_rss; 4173 uint32_t act_idx = (uint32_t)(uintptr_t)handle->action; 4174 uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET; 4175 uint32_t idx = act_idx & 4176 ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1); 4177 4178 switch (type) { 4179 case MLX5_INDIRECT_ACTION_TYPE_RSS: 4180 shared_rss = mlx5_ipool_get 4181 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx); 4182 translated[handle->index].type = 4183 RTE_FLOW_ACTION_TYPE_RSS; 4184 translated[handle->index].conf = 4185 &shared_rss->origin; 4186 break; 4187 case MLX5_INDIRECT_ACTION_TYPE_COUNT: 4188 translated[handle->index].type = 4189 (enum rte_flow_action_type) 4190 MLX5_RTE_FLOW_ACTION_TYPE_COUNT; 4191 translated[handle->index].conf = (void *)(uintptr_t)idx; 4192 break; 4193 case MLX5_INDIRECT_ACTION_TYPE_AGE: 4194 if (priv->sh->flow_hit_aso_en) { 4195 translated[handle->index].type = 4196 (enum rte_flow_action_type) 4197 MLX5_RTE_FLOW_ACTION_TYPE_AGE; 4198 translated[handle->index].conf = 4199 (void *)(uintptr_t)idx; 4200 break; 4201 } 4202 /* Fall-through */ 4203 case MLX5_INDIRECT_ACTION_TYPE_CT: 4204 if (priv->sh->ct_aso_en) { 4205 translated[handle->index].type = 4206 RTE_FLOW_ACTION_TYPE_CONNTRACK; 4207 translated[handle->index].conf = 4208 (void *)(uintptr_t)idx; 4209 break; 4210 } 4211 /* Fall-through */ 4212 default: 4213 mlx5_free(translated); 4214 return rte_flow_error_set 4215 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, 4216 NULL, "invalid indirect action type"); 4217 } 4218 } 4219 *translated_actions = translated; 4220 return 0; 4221 } 4222 4223 /** 4224 * Get Shared RSS action from the action list. 4225 * 4226 * @param[in] dev 4227 * Pointer to Ethernet device. 4228 * @param[in] shared 4229 * Pointer to the list of actions. 4230 * @param[in] shared_n 4231 * Actions list length. 4232 * 4233 * @return 4234 * The MLX5 RSS action ID if exists, otherwise return 0. 4235 */ 4236 static uint32_t 4237 flow_get_shared_rss_action(struct rte_eth_dev *dev, 4238 struct mlx5_translated_action_handle *handle, 4239 int shared_n) 4240 { 4241 struct mlx5_translated_action_handle *handle_end; 4242 struct mlx5_priv *priv = dev->data->dev_private; 4243 struct mlx5_shared_action_rss *shared_rss; 4244 4245 4246 for (handle_end = handle + shared_n; handle < handle_end; handle++) { 4247 uint32_t act_idx = (uint32_t)(uintptr_t)handle->action; 4248 uint32_t type = act_idx >> MLX5_INDIRECT_ACTION_TYPE_OFFSET; 4249 uint32_t idx = act_idx & 4250 ((1u << MLX5_INDIRECT_ACTION_TYPE_OFFSET) - 1); 4251 switch (type) { 4252 case MLX5_INDIRECT_ACTION_TYPE_RSS: 4253 shared_rss = mlx5_ipool_get 4254 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 4255 idx); 4256 __atomic_add_fetch(&shared_rss->refcnt, 1, 4257 __ATOMIC_RELAXED); 4258 return idx; 4259 default: 4260 break; 4261 } 4262 } 4263 return 0; 4264 } 4265 4266 static unsigned int 4267 find_graph_root(uint32_t rss_level) 4268 { 4269 return rss_level < 2 ? MLX5_EXPANSION_ROOT : 4270 MLX5_EXPANSION_ROOT_OUTER; 4271 } 4272 4273 /** 4274 * Get layer flags from the prefix flow. 4275 * 4276 * Some flows may be split to several subflows, the prefix subflow gets the 4277 * match items and the suffix sub flow gets the actions. 4278 * Some actions need the user defined match item flags to get the detail for 4279 * the action. 4280 * This function helps the suffix flow to get the item layer flags from prefix 4281 * subflow. 4282 * 4283 * @param[in] dev_flow 4284 * Pointer the created prefix subflow. 4285 * 4286 * @return 4287 * The layers get from prefix subflow. 4288 */ 4289 static inline uint64_t 4290 flow_get_prefix_layer_flags(struct mlx5_flow *dev_flow) 4291 { 4292 uint64_t layers = 0; 4293 4294 /* 4295 * Layers bits could be localization, but usually the compiler will 4296 * help to do the optimization work for source code. 4297 * If no decap actions, use the layers directly. 4298 */ 4299 if (!(dev_flow->act_flags & MLX5_FLOW_ACTION_DECAP)) 4300 return dev_flow->handle->layers; 4301 /* Convert L3 layers with decap action. */ 4302 if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L3_IPV4) 4303 layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV4; 4304 else if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L3_IPV6) 4305 layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV6; 4306 /* Convert L4 layers with decap action. */ 4307 if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L4_TCP) 4308 layers |= MLX5_FLOW_LAYER_OUTER_L4_TCP; 4309 else if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L4_UDP) 4310 layers |= MLX5_FLOW_LAYER_OUTER_L4_UDP; 4311 return layers; 4312 } 4313 4314 /** 4315 * Get metadata split action information. 4316 * 4317 * @param[in] actions 4318 * Pointer to the list of actions. 4319 * @param[out] qrss 4320 * Pointer to the return pointer. 4321 * @param[out] qrss_type 4322 * Pointer to the action type to return. RTE_FLOW_ACTION_TYPE_END is returned 4323 * if no QUEUE/RSS is found. 4324 * @param[out] encap_idx 4325 * Pointer to the index of the encap action if exists, otherwise the last 4326 * action index. 4327 * 4328 * @return 4329 * Total number of actions. 4330 */ 4331 static int 4332 flow_parse_metadata_split_actions_info(const struct rte_flow_action actions[], 4333 const struct rte_flow_action **qrss, 4334 int *encap_idx) 4335 { 4336 const struct rte_flow_action_raw_encap *raw_encap; 4337 int actions_n = 0; 4338 int raw_decap_idx = -1; 4339 4340 *encap_idx = -1; 4341 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 4342 switch (actions->type) { 4343 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 4344 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 4345 *encap_idx = actions_n; 4346 break; 4347 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 4348 raw_decap_idx = actions_n; 4349 break; 4350 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 4351 raw_encap = actions->conf; 4352 if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE) 4353 *encap_idx = raw_decap_idx != -1 ? 4354 raw_decap_idx : actions_n; 4355 break; 4356 case RTE_FLOW_ACTION_TYPE_QUEUE: 4357 case RTE_FLOW_ACTION_TYPE_RSS: 4358 *qrss = actions; 4359 break; 4360 default: 4361 break; 4362 } 4363 actions_n++; 4364 } 4365 if (*encap_idx == -1) 4366 *encap_idx = actions_n; 4367 /* Count RTE_FLOW_ACTION_TYPE_END. */ 4368 return actions_n + 1; 4369 } 4370 4371 /** 4372 * Check if the action will change packet. 4373 * 4374 * @param dev 4375 * Pointer to Ethernet device. 4376 * @param[in] type 4377 * action type. 4378 * 4379 * @return 4380 * true if action will change packet, false otherwise. 4381 */ 4382 static bool flow_check_modify_action_type(struct rte_eth_dev *dev, 4383 enum rte_flow_action_type type) 4384 { 4385 struct mlx5_priv *priv = dev->data->dev_private; 4386 4387 switch (type) { 4388 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: 4389 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: 4390 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: 4391 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: 4392 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: 4393 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: 4394 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: 4395 case RTE_FLOW_ACTION_TYPE_SET_TP_DST: 4396 case RTE_FLOW_ACTION_TYPE_DEC_TTL: 4397 case RTE_FLOW_ACTION_TYPE_SET_TTL: 4398 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ: 4399 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ: 4400 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK: 4401 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK: 4402 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: 4403 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP: 4404 case RTE_FLOW_ACTION_TYPE_SET_META: 4405 case RTE_FLOW_ACTION_TYPE_SET_TAG: 4406 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: 4407 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 4408 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 4409 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 4410 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 4411 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 4412 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 4413 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: 4414 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 4415 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 4416 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD: 4417 return true; 4418 case RTE_FLOW_ACTION_TYPE_FLAG: 4419 case RTE_FLOW_ACTION_TYPE_MARK: 4420 if (priv->sh->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) 4421 return true; 4422 else 4423 return false; 4424 default: 4425 return false; 4426 } 4427 } 4428 4429 /** 4430 * Check meter action from the action list. 4431 * 4432 * @param dev 4433 * Pointer to Ethernet device. 4434 * @param[in] actions 4435 * Pointer to the list of actions. 4436 * @param[out] has_mtr 4437 * Pointer to the meter exist flag. 4438 * @param[out] has_modify 4439 * Pointer to the flag showing there's packet change action. 4440 * @param[out] meter_id 4441 * Pointer to the meter id. 4442 * 4443 * @return 4444 * Total number of actions. 4445 */ 4446 static int 4447 flow_check_meter_action(struct rte_eth_dev *dev, 4448 const struct rte_flow_action actions[], 4449 bool *has_mtr, bool *has_modify, uint32_t *meter_id) 4450 { 4451 const struct rte_flow_action_meter *mtr = NULL; 4452 int actions_n = 0; 4453 4454 MLX5_ASSERT(has_mtr); 4455 *has_mtr = false; 4456 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 4457 switch (actions->type) { 4458 case RTE_FLOW_ACTION_TYPE_METER: 4459 mtr = actions->conf; 4460 *meter_id = mtr->mtr_id; 4461 *has_mtr = true; 4462 break; 4463 default: 4464 break; 4465 } 4466 if (!*has_mtr) 4467 *has_modify |= flow_check_modify_action_type(dev, 4468 actions->type); 4469 actions_n++; 4470 } 4471 /* Count RTE_FLOW_ACTION_TYPE_END. */ 4472 return actions_n + 1; 4473 } 4474 4475 /** 4476 * Check if the flow should be split due to hairpin. 4477 * The reason for the split is that in current HW we can't 4478 * support encap and push-vlan on Rx, so if a flow contains 4479 * these actions we move it to Tx. 4480 * 4481 * @param dev 4482 * Pointer to Ethernet device. 4483 * @param[in] attr 4484 * Flow rule attributes. 4485 * @param[in] actions 4486 * Associated actions (list terminated by the END action). 4487 * 4488 * @return 4489 * > 0 the number of actions and the flow should be split, 4490 * 0 when no split required. 4491 */ 4492 static int 4493 flow_check_hairpin_split(struct rte_eth_dev *dev, 4494 const struct rte_flow_attr *attr, 4495 const struct rte_flow_action actions[]) 4496 { 4497 int queue_action = 0; 4498 int action_n = 0; 4499 int split = 0; 4500 const struct rte_flow_action_queue *queue; 4501 const struct rte_flow_action_rss *rss; 4502 const struct rte_flow_action_raw_encap *raw_encap; 4503 const struct rte_eth_hairpin_conf *conf; 4504 4505 if (!attr->ingress) 4506 return 0; 4507 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 4508 switch (actions->type) { 4509 case RTE_FLOW_ACTION_TYPE_QUEUE: 4510 queue = actions->conf; 4511 if (queue == NULL) 4512 return 0; 4513 conf = mlx5_rxq_get_hairpin_conf(dev, queue->index); 4514 if (conf == NULL || conf->tx_explicit != 0) 4515 return 0; 4516 queue_action = 1; 4517 action_n++; 4518 break; 4519 case RTE_FLOW_ACTION_TYPE_RSS: 4520 rss = actions->conf; 4521 if (rss == NULL || rss->queue_num == 0) 4522 return 0; 4523 conf = mlx5_rxq_get_hairpin_conf(dev, rss->queue[0]); 4524 if (conf == NULL || conf->tx_explicit != 0) 4525 return 0; 4526 queue_action = 1; 4527 action_n++; 4528 break; 4529 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 4530 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 4531 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 4532 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 4533 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 4534 split++; 4535 action_n++; 4536 break; 4537 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 4538 raw_encap = actions->conf; 4539 if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE) 4540 split++; 4541 action_n++; 4542 break; 4543 default: 4544 action_n++; 4545 break; 4546 } 4547 } 4548 if (split && queue_action) 4549 return action_n; 4550 return 0; 4551 } 4552 4553 /* Declare flow create/destroy prototype in advance. */ 4554 static uint32_t 4555 flow_list_create(struct rte_eth_dev *dev, enum mlx5_flow_type type, 4556 const struct rte_flow_attr *attr, 4557 const struct rte_flow_item items[], 4558 const struct rte_flow_action actions[], 4559 bool external, struct rte_flow_error *error); 4560 4561 static void 4562 flow_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type, 4563 uint32_t flow_idx); 4564 4565 int 4566 flow_dv_mreg_match_cb(void *tool_ctx __rte_unused, 4567 struct mlx5_list_entry *entry, void *cb_ctx) 4568 { 4569 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 4570 struct mlx5_flow_mreg_copy_resource *mcp_res = 4571 container_of(entry, typeof(*mcp_res), hlist_ent); 4572 4573 return mcp_res->mark_id != *(uint32_t *)(ctx->data); 4574 } 4575 4576 struct mlx5_list_entry * 4577 flow_dv_mreg_create_cb(void *tool_ctx, void *cb_ctx) 4578 { 4579 struct rte_eth_dev *dev = tool_ctx; 4580 struct mlx5_priv *priv = dev->data->dev_private; 4581 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 4582 struct mlx5_flow_mreg_copy_resource *mcp_res; 4583 struct rte_flow_error *error = ctx->error; 4584 uint32_t idx = 0; 4585 int ret; 4586 uint32_t mark_id = *(uint32_t *)(ctx->data); 4587 struct rte_flow_attr attr = { 4588 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP, 4589 .ingress = 1, 4590 }; 4591 struct mlx5_rte_flow_item_tag tag_spec = { 4592 .data = mark_id, 4593 }; 4594 struct rte_flow_item items[] = { 4595 [1] = { .type = RTE_FLOW_ITEM_TYPE_END, }, 4596 }; 4597 struct rte_flow_action_mark ftag = { 4598 .id = mark_id, 4599 }; 4600 struct mlx5_flow_action_copy_mreg cp_mreg = { 4601 .dst = REG_B, 4602 .src = REG_NON, 4603 }; 4604 struct rte_flow_action_jump jump = { 4605 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP, 4606 }; 4607 struct rte_flow_action actions[] = { 4608 [3] = { .type = RTE_FLOW_ACTION_TYPE_END, }, 4609 }; 4610 4611 /* Fill the register fields in the flow. */ 4612 ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error); 4613 if (ret < 0) 4614 return NULL; 4615 tag_spec.id = ret; 4616 ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_RX, 0, error); 4617 if (ret < 0) 4618 return NULL; 4619 cp_mreg.src = ret; 4620 /* Provide the full width of FLAG specific value. */ 4621 if (mark_id == (priv->sh->dv_regc0_mask & MLX5_FLOW_MARK_DEFAULT)) 4622 tag_spec.data = MLX5_FLOW_MARK_DEFAULT; 4623 /* Build a new flow. */ 4624 if (mark_id != MLX5_DEFAULT_COPY_ID) { 4625 items[0] = (struct rte_flow_item){ 4626 .type = (enum rte_flow_item_type) 4627 MLX5_RTE_FLOW_ITEM_TYPE_TAG, 4628 .spec = &tag_spec, 4629 }; 4630 items[1] = (struct rte_flow_item){ 4631 .type = RTE_FLOW_ITEM_TYPE_END, 4632 }; 4633 actions[0] = (struct rte_flow_action){ 4634 .type = (enum rte_flow_action_type) 4635 MLX5_RTE_FLOW_ACTION_TYPE_MARK, 4636 .conf = &ftag, 4637 }; 4638 actions[1] = (struct rte_flow_action){ 4639 .type = (enum rte_flow_action_type) 4640 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 4641 .conf = &cp_mreg, 4642 }; 4643 actions[2] = (struct rte_flow_action){ 4644 .type = RTE_FLOW_ACTION_TYPE_JUMP, 4645 .conf = &jump, 4646 }; 4647 actions[3] = (struct rte_flow_action){ 4648 .type = RTE_FLOW_ACTION_TYPE_END, 4649 }; 4650 } else { 4651 /* Default rule, wildcard match. */ 4652 attr.priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR; 4653 items[0] = (struct rte_flow_item){ 4654 .type = RTE_FLOW_ITEM_TYPE_END, 4655 }; 4656 actions[0] = (struct rte_flow_action){ 4657 .type = (enum rte_flow_action_type) 4658 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 4659 .conf = &cp_mreg, 4660 }; 4661 actions[1] = (struct rte_flow_action){ 4662 .type = RTE_FLOW_ACTION_TYPE_JUMP, 4663 .conf = &jump, 4664 }; 4665 actions[2] = (struct rte_flow_action){ 4666 .type = RTE_FLOW_ACTION_TYPE_END, 4667 }; 4668 } 4669 /* Build a new entry. */ 4670 mcp_res = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx); 4671 if (!mcp_res) { 4672 rte_errno = ENOMEM; 4673 return NULL; 4674 } 4675 mcp_res->idx = idx; 4676 mcp_res->mark_id = mark_id; 4677 /* 4678 * The copy Flows are not included in any list. There 4679 * ones are referenced from other Flows and can not 4680 * be applied, removed, deleted in arbitrary order 4681 * by list traversing. 4682 */ 4683 mcp_res->rix_flow = flow_list_create(dev, MLX5_FLOW_TYPE_MCP, 4684 &attr, items, actions, false, error); 4685 if (!mcp_res->rix_flow) { 4686 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], idx); 4687 return NULL; 4688 } 4689 return &mcp_res->hlist_ent; 4690 } 4691 4692 struct mlx5_list_entry * 4693 flow_dv_mreg_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry, 4694 void *cb_ctx __rte_unused) 4695 { 4696 struct rte_eth_dev *dev = tool_ctx; 4697 struct mlx5_priv *priv = dev->data->dev_private; 4698 struct mlx5_flow_mreg_copy_resource *mcp_res; 4699 uint32_t idx = 0; 4700 4701 mcp_res = mlx5_ipool_malloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx); 4702 if (!mcp_res) { 4703 rte_errno = ENOMEM; 4704 return NULL; 4705 } 4706 memcpy(mcp_res, oentry, sizeof(*mcp_res)); 4707 mcp_res->idx = idx; 4708 return &mcp_res->hlist_ent; 4709 } 4710 4711 void 4712 flow_dv_mreg_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry) 4713 { 4714 struct mlx5_flow_mreg_copy_resource *mcp_res = 4715 container_of(entry, typeof(*mcp_res), hlist_ent); 4716 struct rte_eth_dev *dev = tool_ctx; 4717 struct mlx5_priv *priv = dev->data->dev_private; 4718 4719 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx); 4720 } 4721 4722 /** 4723 * Add a flow of copying flow metadata registers in RX_CP_TBL. 4724 * 4725 * As mark_id is unique, if there's already a registered flow for the mark_id, 4726 * return by increasing the reference counter of the resource. Otherwise, create 4727 * the resource (mcp_res) and flow. 4728 * 4729 * Flow looks like, 4730 * - If ingress port is ANY and reg_c[1] is mark_id, 4731 * flow_tag := mark_id, reg_b := reg_c[0] and jump to RX_ACT_TBL. 4732 * 4733 * For default flow (zero mark_id), flow is like, 4734 * - If ingress port is ANY, 4735 * reg_b := reg_c[0] and jump to RX_ACT_TBL. 4736 * 4737 * @param dev 4738 * Pointer to Ethernet device. 4739 * @param mark_id 4740 * ID of MARK action, zero means default flow for META. 4741 * @param[out] error 4742 * Perform verbose error reporting if not NULL. 4743 * 4744 * @return 4745 * Associated resource on success, NULL otherwise and rte_errno is set. 4746 */ 4747 static struct mlx5_flow_mreg_copy_resource * 4748 flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id, 4749 struct rte_flow_error *error) 4750 { 4751 struct mlx5_priv *priv = dev->data->dev_private; 4752 struct mlx5_list_entry *entry; 4753 struct mlx5_flow_cb_ctx ctx = { 4754 .dev = dev, 4755 .error = error, 4756 .data = &mark_id, 4757 }; 4758 4759 /* Check if already registered. */ 4760 MLX5_ASSERT(priv->mreg_cp_tbl); 4761 entry = mlx5_hlist_register(priv->mreg_cp_tbl, mark_id, &ctx); 4762 if (!entry) 4763 return NULL; 4764 return container_of(entry, struct mlx5_flow_mreg_copy_resource, 4765 hlist_ent); 4766 } 4767 4768 void 4769 flow_dv_mreg_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry) 4770 { 4771 struct mlx5_flow_mreg_copy_resource *mcp_res = 4772 container_of(entry, typeof(*mcp_res), hlist_ent); 4773 struct rte_eth_dev *dev = tool_ctx; 4774 struct mlx5_priv *priv = dev->data->dev_private; 4775 4776 MLX5_ASSERT(mcp_res->rix_flow); 4777 flow_list_destroy(dev, MLX5_FLOW_TYPE_MCP, mcp_res->rix_flow); 4778 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx); 4779 } 4780 4781 /** 4782 * Release flow in RX_CP_TBL. 4783 * 4784 * @param dev 4785 * Pointer to Ethernet device. 4786 * @flow 4787 * Parent flow for wich copying is provided. 4788 */ 4789 static void 4790 flow_mreg_del_copy_action(struct rte_eth_dev *dev, 4791 struct rte_flow *flow) 4792 { 4793 struct mlx5_flow_mreg_copy_resource *mcp_res; 4794 struct mlx5_priv *priv = dev->data->dev_private; 4795 4796 if (!flow->rix_mreg_copy) 4797 return; 4798 mcp_res = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MCP], 4799 flow->rix_mreg_copy); 4800 if (!mcp_res || !priv->mreg_cp_tbl) 4801 return; 4802 MLX5_ASSERT(mcp_res->rix_flow); 4803 mlx5_hlist_unregister(priv->mreg_cp_tbl, &mcp_res->hlist_ent); 4804 flow->rix_mreg_copy = 0; 4805 } 4806 4807 /** 4808 * Remove the default copy action from RX_CP_TBL. 4809 * 4810 * This functions is called in the mlx5_dev_start(). No thread safe 4811 * is guaranteed. 4812 * 4813 * @param dev 4814 * Pointer to Ethernet device. 4815 */ 4816 static void 4817 flow_mreg_del_default_copy_action(struct rte_eth_dev *dev) 4818 { 4819 struct mlx5_list_entry *entry; 4820 struct mlx5_priv *priv = dev->data->dev_private; 4821 struct mlx5_flow_cb_ctx ctx; 4822 uint32_t mark_id; 4823 4824 /* Check if default flow is registered. */ 4825 if (!priv->mreg_cp_tbl) 4826 return; 4827 mark_id = MLX5_DEFAULT_COPY_ID; 4828 ctx.data = &mark_id; 4829 entry = mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id, &ctx); 4830 if (!entry) 4831 return; 4832 mlx5_hlist_unregister(priv->mreg_cp_tbl, entry); 4833 } 4834 4835 /** 4836 * Add the default copy action in in RX_CP_TBL. 4837 * 4838 * This functions is called in the mlx5_dev_start(). No thread safe 4839 * is guaranteed. 4840 * 4841 * @param dev 4842 * Pointer to Ethernet device. 4843 * @param[out] error 4844 * Perform verbose error reporting if not NULL. 4845 * 4846 * @return 4847 * 0 for success, negative value otherwise and rte_errno is set. 4848 */ 4849 static int 4850 flow_mreg_add_default_copy_action(struct rte_eth_dev *dev, 4851 struct rte_flow_error *error) 4852 { 4853 struct mlx5_priv *priv = dev->data->dev_private; 4854 struct mlx5_flow_mreg_copy_resource *mcp_res; 4855 struct mlx5_flow_cb_ctx ctx; 4856 uint32_t mark_id; 4857 4858 /* Check whether extensive metadata feature is engaged. */ 4859 if (!priv->sh->config.dv_flow_en || 4860 priv->sh->config.dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || 4861 !mlx5_flow_ext_mreg_supported(dev) || 4862 !priv->sh->dv_regc0_mask) 4863 return 0; 4864 /* 4865 * Add default mreg copy flow may be called multiple time, but 4866 * only be called once in stop. Avoid register it twice. 4867 */ 4868 mark_id = MLX5_DEFAULT_COPY_ID; 4869 ctx.data = &mark_id; 4870 if (mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id, &ctx)) 4871 return 0; 4872 mcp_res = flow_mreg_add_copy_action(dev, mark_id, error); 4873 if (!mcp_res) 4874 return -rte_errno; 4875 return 0; 4876 } 4877 4878 /** 4879 * Add a flow of copying flow metadata registers in RX_CP_TBL. 4880 * 4881 * All the flow having Q/RSS action should be split by 4882 * flow_mreg_split_qrss_prep() to pass by RX_CP_TBL. A flow in the RX_CP_TBL 4883 * performs the following, 4884 * - CQE->flow_tag := reg_c[1] (MARK) 4885 * - CQE->flow_table_metadata (reg_b) := reg_c[0] (META) 4886 * As CQE's flow_tag is not a register, it can't be simply copied from reg_c[1] 4887 * but there should be a flow per each MARK ID set by MARK action. 4888 * 4889 * For the aforementioned reason, if there's a MARK action in flow's action 4890 * list, a corresponding flow should be added to the RX_CP_TBL in order to copy 4891 * the MARK ID to CQE's flow_tag like, 4892 * - If reg_c[1] is mark_id, 4893 * flow_tag := mark_id, reg_b := reg_c[0] and jump to RX_ACT_TBL. 4894 * 4895 * For SET_META action which stores value in reg_c[0], as the destination is 4896 * also a flow metadata register (reg_b), adding a default flow is enough. Zero 4897 * MARK ID means the default flow. The default flow looks like, 4898 * - For all flow, reg_b := reg_c[0] and jump to RX_ACT_TBL. 4899 * 4900 * @param dev 4901 * Pointer to Ethernet device. 4902 * @param flow 4903 * Pointer to flow structure. 4904 * @param[in] actions 4905 * Pointer to the list of actions. 4906 * @param[out] error 4907 * Perform verbose error reporting if not NULL. 4908 * 4909 * @return 4910 * 0 on success, negative value otherwise and rte_errno is set. 4911 */ 4912 static int 4913 flow_mreg_update_copy_table(struct rte_eth_dev *dev, 4914 struct rte_flow *flow, 4915 const struct rte_flow_action *actions, 4916 struct rte_flow_error *error) 4917 { 4918 struct mlx5_priv *priv = dev->data->dev_private; 4919 struct mlx5_sh_config *config = &priv->sh->config; 4920 struct mlx5_flow_mreg_copy_resource *mcp_res; 4921 const struct rte_flow_action_mark *mark; 4922 4923 /* Check whether extensive metadata feature is engaged. */ 4924 if (!config->dv_flow_en || 4925 config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || 4926 !mlx5_flow_ext_mreg_supported(dev) || 4927 !priv->sh->dv_regc0_mask) 4928 return 0; 4929 /* Find MARK action. */ 4930 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 4931 switch (actions->type) { 4932 case RTE_FLOW_ACTION_TYPE_FLAG: 4933 mcp_res = flow_mreg_add_copy_action 4934 (dev, MLX5_FLOW_MARK_DEFAULT, error); 4935 if (!mcp_res) 4936 return -rte_errno; 4937 flow->rix_mreg_copy = mcp_res->idx; 4938 return 0; 4939 case RTE_FLOW_ACTION_TYPE_MARK: 4940 mark = (const struct rte_flow_action_mark *) 4941 actions->conf; 4942 mcp_res = 4943 flow_mreg_add_copy_action(dev, mark->id, error); 4944 if (!mcp_res) 4945 return -rte_errno; 4946 flow->rix_mreg_copy = mcp_res->idx; 4947 return 0; 4948 default: 4949 break; 4950 } 4951 } 4952 return 0; 4953 } 4954 4955 #define MLX5_MAX_SPLIT_ACTIONS 24 4956 #define MLX5_MAX_SPLIT_ITEMS 24 4957 4958 /** 4959 * Split the hairpin flow. 4960 * Since HW can't support encap and push-vlan on Rx, we move these 4961 * actions to Tx. 4962 * If the count action is after the encap then we also 4963 * move the count action. in this case the count will also measure 4964 * the outer bytes. 4965 * 4966 * @param dev 4967 * Pointer to Ethernet device. 4968 * @param[in] actions 4969 * Associated actions (list terminated by the END action). 4970 * @param[out] actions_rx 4971 * Rx flow actions. 4972 * @param[out] actions_tx 4973 * Tx flow actions.. 4974 * @param[out] pattern_tx 4975 * The pattern items for the Tx flow. 4976 * @param[out] flow_id 4977 * The flow ID connected to this flow. 4978 * 4979 * @return 4980 * 0 on success. 4981 */ 4982 static int 4983 flow_hairpin_split(struct rte_eth_dev *dev, 4984 const struct rte_flow_action actions[], 4985 struct rte_flow_action actions_rx[], 4986 struct rte_flow_action actions_tx[], 4987 struct rte_flow_item pattern_tx[], 4988 uint32_t flow_id) 4989 { 4990 const struct rte_flow_action_raw_encap *raw_encap; 4991 const struct rte_flow_action_raw_decap *raw_decap; 4992 struct mlx5_rte_flow_action_set_tag *set_tag; 4993 struct rte_flow_action *tag_action; 4994 struct mlx5_rte_flow_item_tag *tag_item; 4995 struct rte_flow_item *item; 4996 char *addr; 4997 int encap = 0; 4998 4999 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 5000 switch (actions->type) { 5001 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 5002 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 5003 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 5004 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 5005 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 5006 rte_memcpy(actions_tx, actions, 5007 sizeof(struct rte_flow_action)); 5008 actions_tx++; 5009 break; 5010 case RTE_FLOW_ACTION_TYPE_COUNT: 5011 if (encap) { 5012 rte_memcpy(actions_tx, actions, 5013 sizeof(struct rte_flow_action)); 5014 actions_tx++; 5015 } else { 5016 rte_memcpy(actions_rx, actions, 5017 sizeof(struct rte_flow_action)); 5018 actions_rx++; 5019 } 5020 break; 5021 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 5022 raw_encap = actions->conf; 5023 if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE) { 5024 memcpy(actions_tx, actions, 5025 sizeof(struct rte_flow_action)); 5026 actions_tx++; 5027 encap = 1; 5028 } else { 5029 rte_memcpy(actions_rx, actions, 5030 sizeof(struct rte_flow_action)); 5031 actions_rx++; 5032 } 5033 break; 5034 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 5035 raw_decap = actions->conf; 5036 if (raw_decap->size < MLX5_ENCAPSULATION_DECISION_SIZE) { 5037 memcpy(actions_tx, actions, 5038 sizeof(struct rte_flow_action)); 5039 actions_tx++; 5040 } else { 5041 rte_memcpy(actions_rx, actions, 5042 sizeof(struct rte_flow_action)); 5043 actions_rx++; 5044 } 5045 break; 5046 default: 5047 rte_memcpy(actions_rx, actions, 5048 sizeof(struct rte_flow_action)); 5049 actions_rx++; 5050 break; 5051 } 5052 } 5053 /* Add set meta action and end action for the Rx flow. */ 5054 tag_action = actions_rx; 5055 tag_action->type = (enum rte_flow_action_type) 5056 MLX5_RTE_FLOW_ACTION_TYPE_TAG; 5057 actions_rx++; 5058 rte_memcpy(actions_rx, actions, sizeof(struct rte_flow_action)); 5059 actions_rx++; 5060 set_tag = (void *)actions_rx; 5061 *set_tag = (struct mlx5_rte_flow_action_set_tag) { 5062 .id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_RX, 0, NULL), 5063 .data = flow_id, 5064 }; 5065 MLX5_ASSERT(set_tag->id > REG_NON); 5066 tag_action->conf = set_tag; 5067 /* Create Tx item list. */ 5068 rte_memcpy(actions_tx, actions, sizeof(struct rte_flow_action)); 5069 addr = (void *)&pattern_tx[2]; 5070 item = pattern_tx; 5071 item->type = (enum rte_flow_item_type) 5072 MLX5_RTE_FLOW_ITEM_TYPE_TAG; 5073 tag_item = (void *)addr; 5074 tag_item->data = flow_id; 5075 tag_item->id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_TX, 0, NULL); 5076 MLX5_ASSERT(set_tag->id > REG_NON); 5077 item->spec = tag_item; 5078 addr += sizeof(struct mlx5_rte_flow_item_tag); 5079 tag_item = (void *)addr; 5080 tag_item->data = UINT32_MAX; 5081 tag_item->id = UINT16_MAX; 5082 item->mask = tag_item; 5083 item->last = NULL; 5084 item++; 5085 item->type = RTE_FLOW_ITEM_TYPE_END; 5086 return 0; 5087 } 5088 5089 /** 5090 * The last stage of splitting chain, just creates the subflow 5091 * without any modification. 5092 * 5093 * @param[in] dev 5094 * Pointer to Ethernet device. 5095 * @param[in] flow 5096 * Parent flow structure pointer. 5097 * @param[in, out] sub_flow 5098 * Pointer to return the created subflow, may be NULL. 5099 * @param[in] attr 5100 * Flow rule attributes. 5101 * @param[in] items 5102 * Pattern specification (list terminated by the END pattern item). 5103 * @param[in] actions 5104 * Associated actions (list terminated by the END action). 5105 * @param[in] flow_split_info 5106 * Pointer to flow split info structure. 5107 * @param[out] error 5108 * Perform verbose error reporting if not NULL. 5109 * @return 5110 * 0 on success, negative value otherwise 5111 */ 5112 static int 5113 flow_create_split_inner(struct rte_eth_dev *dev, 5114 struct rte_flow *flow, 5115 struct mlx5_flow **sub_flow, 5116 const struct rte_flow_attr *attr, 5117 const struct rte_flow_item items[], 5118 const struct rte_flow_action actions[], 5119 struct mlx5_flow_split_info *flow_split_info, 5120 struct rte_flow_error *error) 5121 { 5122 struct mlx5_flow *dev_flow; 5123 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 5124 5125 dev_flow = flow_drv_prepare(dev, flow, attr, items, actions, 5126 flow_split_info->flow_idx, error); 5127 if (!dev_flow) 5128 return -rte_errno; 5129 dev_flow->flow = flow; 5130 dev_flow->external = flow_split_info->external; 5131 dev_flow->skip_scale = flow_split_info->skip_scale; 5132 /* Subflow object was created, we must include one in the list. */ 5133 SILIST_INSERT(&flow->dev_handles, dev_flow->handle_idx, 5134 dev_flow->handle, next); 5135 /* 5136 * If dev_flow is as one of the suffix flow, some actions in suffix 5137 * flow may need some user defined item layer flags, and pass the 5138 * Metadata rxq mark flag to suffix flow as well. 5139 */ 5140 if (flow_split_info->prefix_layers) 5141 dev_flow->handle->layers = flow_split_info->prefix_layers; 5142 if (flow_split_info->prefix_mark) { 5143 MLX5_ASSERT(wks); 5144 wks->mark = 1; 5145 } 5146 if (sub_flow) 5147 *sub_flow = dev_flow; 5148 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 5149 dev_flow->dv.table_id = flow_split_info->table_id; 5150 #endif 5151 return flow_drv_translate(dev, dev_flow, attr, items, actions, error); 5152 } 5153 5154 /** 5155 * Get the sub policy of a meter. 5156 * 5157 * @param[in] dev 5158 * Pointer to Ethernet device. 5159 * @param[in] flow 5160 * Parent flow structure pointer. 5161 * @param wks 5162 * Pointer to thread flow work space. 5163 * @param[in] attr 5164 * Flow rule attributes. 5165 * @param[in] items 5166 * Pattern specification (list terminated by the END pattern item). 5167 * @param[out] error 5168 * Perform verbose error reporting if not NULL. 5169 * 5170 * @return 5171 * Pointer to the meter sub policy, NULL otherwise and rte_errno is set. 5172 */ 5173 static struct mlx5_flow_meter_sub_policy * 5174 get_meter_sub_policy(struct rte_eth_dev *dev, 5175 struct rte_flow *flow, 5176 struct mlx5_flow_workspace *wks, 5177 const struct rte_flow_attr *attr, 5178 const struct rte_flow_item items[], 5179 struct rte_flow_error *error) 5180 { 5181 struct mlx5_flow_meter_policy *policy; 5182 struct mlx5_flow_meter_policy *final_policy; 5183 struct mlx5_flow_meter_sub_policy *sub_policy = NULL; 5184 5185 policy = wks->policy; 5186 final_policy = policy->is_hierarchy ? wks->final_policy : policy; 5187 if (final_policy->is_rss || final_policy->is_queue) { 5188 struct mlx5_flow_rss_desc rss_desc_v[MLX5_MTR_RTE_COLORS]; 5189 struct mlx5_flow_rss_desc *rss_desc[MLX5_MTR_RTE_COLORS] = {0}; 5190 uint32_t i; 5191 5192 /* 5193 * This is a tmp dev_flow, 5194 * no need to register any matcher for it in translate. 5195 */ 5196 wks->skip_matcher_reg = 1; 5197 for (i = 0; i < MLX5_MTR_RTE_COLORS; i++) { 5198 struct mlx5_flow dev_flow = {0}; 5199 struct mlx5_flow_handle dev_handle = { {0} }; 5200 uint8_t fate = final_policy->act_cnt[i].fate_action; 5201 5202 if (fate == MLX5_FLOW_FATE_SHARED_RSS) { 5203 const struct rte_flow_action_rss *rss_act = 5204 final_policy->act_cnt[i].rss->conf; 5205 struct rte_flow_action rss_actions[2] = { 5206 [0] = { 5207 .type = RTE_FLOW_ACTION_TYPE_RSS, 5208 .conf = rss_act, 5209 }, 5210 [1] = { 5211 .type = RTE_FLOW_ACTION_TYPE_END, 5212 .conf = NULL, 5213 } 5214 }; 5215 5216 dev_flow.handle = &dev_handle; 5217 dev_flow.ingress = attr->ingress; 5218 dev_flow.flow = flow; 5219 dev_flow.external = 0; 5220 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 5221 dev_flow.dv.transfer = attr->transfer; 5222 #endif 5223 /** 5224 * Translate RSS action to get rss hash fields. 5225 */ 5226 if (flow_drv_translate(dev, &dev_flow, attr, 5227 items, rss_actions, error)) 5228 goto exit; 5229 rss_desc_v[i] = wks->rss_desc; 5230 rss_desc_v[i].key_len = MLX5_RSS_HASH_KEY_LEN; 5231 rss_desc_v[i].hash_fields = 5232 dev_flow.hash_fields; 5233 rss_desc_v[i].queue_num = 5234 rss_desc_v[i].hash_fields ? 5235 rss_desc_v[i].queue_num : 1; 5236 rss_desc_v[i].tunnel = 5237 !!(dev_flow.handle->layers & 5238 MLX5_FLOW_LAYER_TUNNEL); 5239 /* Use the RSS queues in the containers. */ 5240 rss_desc_v[i].queue = 5241 (uint16_t *)(uintptr_t)rss_act->queue; 5242 rss_desc[i] = &rss_desc_v[i]; 5243 } else if (fate == MLX5_FLOW_FATE_QUEUE) { 5244 /* This is queue action. */ 5245 rss_desc_v[i] = wks->rss_desc; 5246 rss_desc_v[i].key_len = 0; 5247 rss_desc_v[i].hash_fields = 0; 5248 rss_desc_v[i].queue = 5249 &final_policy->act_cnt[i].queue; 5250 rss_desc_v[i].queue_num = 1; 5251 rss_desc[i] = &rss_desc_v[i]; 5252 } else { 5253 rss_desc[i] = NULL; 5254 } 5255 } 5256 sub_policy = flow_drv_meter_sub_policy_rss_prepare(dev, 5257 flow, policy, rss_desc); 5258 } else { 5259 enum mlx5_meter_domain mtr_domain = 5260 attr->transfer ? MLX5_MTR_DOMAIN_TRANSFER : 5261 (attr->egress ? MLX5_MTR_DOMAIN_EGRESS : 5262 MLX5_MTR_DOMAIN_INGRESS); 5263 sub_policy = policy->sub_policys[mtr_domain][0]; 5264 } 5265 if (!sub_policy) 5266 rte_flow_error_set(error, EINVAL, 5267 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 5268 "Failed to get meter sub-policy."); 5269 exit: 5270 return sub_policy; 5271 } 5272 5273 /** 5274 * Split the meter flow. 5275 * 5276 * As meter flow will split to three sub flow, other than meter 5277 * action, the other actions make sense to only meter accepts 5278 * the packet. If it need to be dropped, no other additional 5279 * actions should be take. 5280 * 5281 * One kind of special action which decapsulates the L3 tunnel 5282 * header will be in the prefix sub flow, as not to take the 5283 * L3 tunnel header into account. 5284 * 5285 * @param[in] dev 5286 * Pointer to Ethernet device. 5287 * @param[in] flow 5288 * Parent flow structure pointer. 5289 * @param wks 5290 * Pointer to thread flow work space. 5291 * @param[in] attr 5292 * Flow rule attributes. 5293 * @param[in] items 5294 * Pattern specification (list terminated by the END pattern item). 5295 * @param[out] sfx_items 5296 * Suffix flow match items (list terminated by the END pattern item). 5297 * @param[in] actions 5298 * Associated actions (list terminated by the END action). 5299 * @param[out] actions_sfx 5300 * Suffix flow actions. 5301 * @param[out] actions_pre 5302 * Prefix flow actions. 5303 * @param[out] mtr_flow_id 5304 * Pointer to meter flow id. 5305 * @param[out] error 5306 * Perform verbose error reporting if not NULL. 5307 * 5308 * @return 5309 * 0 on success, a negative errno value otherwise and rte_errno is set. 5310 */ 5311 static int 5312 flow_meter_split_prep(struct rte_eth_dev *dev, 5313 struct rte_flow *flow, 5314 struct mlx5_flow_workspace *wks, 5315 const struct rte_flow_attr *attr, 5316 const struct rte_flow_item items[], 5317 struct rte_flow_item sfx_items[], 5318 const struct rte_flow_action actions[], 5319 struct rte_flow_action actions_sfx[], 5320 struct rte_flow_action actions_pre[], 5321 uint32_t *mtr_flow_id, 5322 struct rte_flow_error *error) 5323 { 5324 struct mlx5_priv *priv = dev->data->dev_private; 5325 struct mlx5_flow_meter_info *fm = wks->fm; 5326 struct rte_flow_action *tag_action = NULL; 5327 struct rte_flow_item *tag_item; 5328 struct mlx5_rte_flow_action_set_tag *set_tag; 5329 const struct rte_flow_action_raw_encap *raw_encap; 5330 const struct rte_flow_action_raw_decap *raw_decap; 5331 struct mlx5_rte_flow_item_tag *tag_item_spec; 5332 struct mlx5_rte_flow_item_tag *tag_item_mask; 5333 uint32_t tag_id = 0; 5334 struct rte_flow_item *vlan_item_dst = NULL; 5335 const struct rte_flow_item *vlan_item_src = NULL; 5336 const struct rte_flow_item *orig_items = items; 5337 struct rte_flow_action *hw_mtr_action; 5338 struct rte_flow_action *action_pre_head = NULL; 5339 uint16_t flow_src_port = priv->representor_id; 5340 bool mtr_first; 5341 uint8_t mtr_id_offset = priv->mtr_reg_share ? MLX5_MTR_COLOR_BITS : 0; 5342 uint8_t mtr_reg_bits = priv->mtr_reg_share ? 5343 MLX5_MTR_IDLE_BITS_IN_COLOR_REG : MLX5_REG_BITS; 5344 uint32_t flow_id = 0; 5345 uint32_t flow_id_reversed = 0; 5346 uint8_t flow_id_bits = 0; 5347 bool after_meter = false; 5348 int shift; 5349 5350 /* Prepare the suffix subflow items. */ 5351 tag_item = sfx_items++; 5352 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 5353 int item_type = items->type; 5354 5355 switch (item_type) { 5356 case RTE_FLOW_ITEM_TYPE_PORT_ID: 5357 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT: 5358 if (mlx5_flow_get_item_vport_id(dev, items, &flow_src_port, NULL, error)) 5359 return -rte_errno; 5360 if (!fm->def_policy && wks->policy->is_hierarchy && 5361 flow_src_port != priv->representor_id) { 5362 if (flow_drv_mtr_hierarchy_rule_create(dev, 5363 flow, fm, 5364 flow_src_port, 5365 items, 5366 error)) 5367 return -rte_errno; 5368 } 5369 memcpy(sfx_items, items, sizeof(*sfx_items)); 5370 sfx_items++; 5371 break; 5372 case RTE_FLOW_ITEM_TYPE_VLAN: 5373 /* Determine if copy vlan item below. */ 5374 vlan_item_src = items; 5375 vlan_item_dst = sfx_items++; 5376 vlan_item_dst->type = RTE_FLOW_ITEM_TYPE_VOID; 5377 break; 5378 default: 5379 break; 5380 } 5381 } 5382 sfx_items->type = RTE_FLOW_ITEM_TYPE_END; 5383 sfx_items++; 5384 mtr_first = priv->sh->meter_aso_en && 5385 (attr->egress || (attr->transfer && flow_src_port != UINT16_MAX)); 5386 /* For ASO meter, meter must be before tag in TX direction. */ 5387 if (mtr_first) { 5388 action_pre_head = actions_pre++; 5389 /* Leave space for tag action. */ 5390 tag_action = actions_pre++; 5391 } 5392 /* Prepare the actions for prefix and suffix flow. */ 5393 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 5394 struct rte_flow_action *action_cur = NULL; 5395 5396 switch (actions->type) { 5397 case RTE_FLOW_ACTION_TYPE_METER: 5398 if (mtr_first) { 5399 action_cur = action_pre_head; 5400 } else { 5401 /* Leave space for tag action. */ 5402 tag_action = actions_pre++; 5403 action_cur = actions_pre++; 5404 } 5405 after_meter = true; 5406 break; 5407 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 5408 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: 5409 action_cur = actions_pre++; 5410 break; 5411 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 5412 raw_encap = actions->conf; 5413 if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE) 5414 action_cur = actions_pre++; 5415 break; 5416 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 5417 raw_decap = actions->conf; 5418 if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE) 5419 action_cur = actions_pre++; 5420 break; 5421 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 5422 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 5423 if (vlan_item_dst && vlan_item_src) { 5424 memcpy(vlan_item_dst, vlan_item_src, 5425 sizeof(*vlan_item_dst)); 5426 /* 5427 * Convert to internal match item, it is used 5428 * for vlan push and set vid. 5429 */ 5430 vlan_item_dst->type = (enum rte_flow_item_type) 5431 MLX5_RTE_FLOW_ITEM_TYPE_VLAN; 5432 } 5433 break; 5434 case RTE_FLOW_ACTION_TYPE_COUNT: 5435 if (fm->def_policy) 5436 action_cur = after_meter ? 5437 actions_sfx++ : actions_pre++; 5438 break; 5439 default: 5440 break; 5441 } 5442 if (!action_cur) 5443 action_cur = (fm->def_policy) ? 5444 actions_sfx++ : actions_pre++; 5445 memcpy(action_cur, actions, sizeof(struct rte_flow_action)); 5446 } 5447 /* Add end action to the actions. */ 5448 actions_sfx->type = RTE_FLOW_ACTION_TYPE_END; 5449 if (priv->sh->meter_aso_en) { 5450 /** 5451 * For ASO meter, need to add an extra jump action explicitly, 5452 * to jump from meter to policer table. 5453 */ 5454 struct mlx5_flow_meter_sub_policy *sub_policy; 5455 struct mlx5_flow_tbl_data_entry *tbl_data; 5456 5457 if (!fm->def_policy) { 5458 sub_policy = get_meter_sub_policy(dev, flow, wks, 5459 attr, orig_items, 5460 error); 5461 if (!sub_policy) 5462 return -rte_errno; 5463 } else { 5464 enum mlx5_meter_domain mtr_domain = 5465 attr->transfer ? MLX5_MTR_DOMAIN_TRANSFER : 5466 (attr->egress ? MLX5_MTR_DOMAIN_EGRESS : 5467 MLX5_MTR_DOMAIN_INGRESS); 5468 5469 sub_policy = 5470 &priv->sh->mtrmng->def_policy[mtr_domain]->sub_policy; 5471 } 5472 tbl_data = container_of(sub_policy->tbl_rsc, 5473 struct mlx5_flow_tbl_data_entry, tbl); 5474 hw_mtr_action = actions_pre++; 5475 hw_mtr_action->type = (enum rte_flow_action_type) 5476 MLX5_RTE_FLOW_ACTION_TYPE_JUMP; 5477 hw_mtr_action->conf = tbl_data->jump.action; 5478 } 5479 actions_pre->type = RTE_FLOW_ACTION_TYPE_END; 5480 actions_pre++; 5481 if (!tag_action) 5482 return rte_flow_error_set(error, ENOMEM, 5483 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 5484 NULL, "No tag action space."); 5485 if (!mtr_flow_id) { 5486 tag_action->type = RTE_FLOW_ACTION_TYPE_VOID; 5487 goto exit; 5488 } 5489 /* Only default-policy Meter creates mtr flow id. */ 5490 if (fm->def_policy) { 5491 mlx5_ipool_malloc(fm->flow_ipool, &tag_id); 5492 if (!tag_id) 5493 return rte_flow_error_set(error, ENOMEM, 5494 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 5495 "Failed to allocate meter flow id."); 5496 flow_id = tag_id - 1; 5497 flow_id_bits = (!flow_id) ? 1 : 5498 (MLX5_REG_BITS - __builtin_clz(flow_id)); 5499 if ((flow_id_bits + priv->sh->mtrmng->max_mtr_bits) > 5500 mtr_reg_bits) { 5501 mlx5_ipool_free(fm->flow_ipool, tag_id); 5502 return rte_flow_error_set(error, EINVAL, 5503 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 5504 "Meter flow id exceeds max limit."); 5505 } 5506 if (flow_id_bits > priv->sh->mtrmng->max_mtr_flow_bits) 5507 priv->sh->mtrmng->max_mtr_flow_bits = flow_id_bits; 5508 } 5509 /* Build tag actions and items for meter_id/meter flow_id. */ 5510 set_tag = (struct mlx5_rte_flow_action_set_tag *)actions_pre; 5511 tag_item_spec = (struct mlx5_rte_flow_item_tag *)sfx_items; 5512 tag_item_mask = tag_item_spec + 1; 5513 /* Both flow_id and meter_id share the same register. */ 5514 *set_tag = (struct mlx5_rte_flow_action_set_tag) { 5515 .id = (enum modify_reg)mlx5_flow_get_reg_id(dev, MLX5_MTR_ID, 5516 0, error), 5517 .offset = mtr_id_offset, 5518 .length = mtr_reg_bits, 5519 .data = flow->meter, 5520 }; 5521 /* 5522 * The color Reg bits used by flow_id are growing from 5523 * msb to lsb, so must do bit reverse for flow_id val in RegC. 5524 */ 5525 for (shift = 0; shift < flow_id_bits; shift++) 5526 flow_id_reversed = (flow_id_reversed << 1) | 5527 ((flow_id >> shift) & 0x1); 5528 set_tag->data |= 5529 flow_id_reversed << (mtr_reg_bits - flow_id_bits); 5530 tag_item_spec->id = set_tag->id; 5531 tag_item_spec->data = set_tag->data << mtr_id_offset; 5532 tag_item_mask->data = UINT32_MAX << mtr_id_offset; 5533 tag_action->type = (enum rte_flow_action_type) 5534 MLX5_RTE_FLOW_ACTION_TYPE_TAG; 5535 tag_action->conf = set_tag; 5536 tag_item->type = (enum rte_flow_item_type) 5537 MLX5_RTE_FLOW_ITEM_TYPE_TAG; 5538 tag_item->spec = tag_item_spec; 5539 tag_item->last = NULL; 5540 tag_item->mask = tag_item_mask; 5541 exit: 5542 if (mtr_flow_id) 5543 *mtr_flow_id = tag_id; 5544 return 0; 5545 } 5546 5547 /** 5548 * Split action list having QUEUE/RSS for metadata register copy. 5549 * 5550 * Once Q/RSS action is detected in user's action list, the flow action 5551 * should be split in order to copy metadata registers, which will happen in 5552 * RX_CP_TBL like, 5553 * - CQE->flow_tag := reg_c[1] (MARK) 5554 * - CQE->flow_table_metadata (reg_b) := reg_c[0] (META) 5555 * The Q/RSS action will be performed on RX_ACT_TBL after passing by RX_CP_TBL. 5556 * This is because the last action of each flow must be a terminal action 5557 * (QUEUE, RSS or DROP). 5558 * 5559 * Flow ID must be allocated to identify actions in the RX_ACT_TBL and it is 5560 * stored and kept in the mlx5_flow structure per each sub_flow. 5561 * 5562 * The Q/RSS action is replaced with, 5563 * - SET_TAG, setting the allocated flow ID to reg_c[2]. 5564 * And the following JUMP action is added at the end, 5565 * - JUMP, to RX_CP_TBL. 5566 * 5567 * A flow to perform remained Q/RSS action will be created in RX_ACT_TBL by 5568 * flow_create_split_metadata() routine. The flow will look like, 5569 * - If flow ID matches (reg_c[2]), perform Q/RSS. 5570 * 5571 * @param dev 5572 * Pointer to Ethernet device. 5573 * @param[out] split_actions 5574 * Pointer to store split actions to jump to CP_TBL. 5575 * @param[in] actions 5576 * Pointer to the list of original flow actions. 5577 * @param[in] qrss 5578 * Pointer to the Q/RSS action. 5579 * @param[in] actions_n 5580 * Number of original actions. 5581 * @param[in] mtr_sfx 5582 * Check if it is in meter suffix table. 5583 * @param[out] error 5584 * Perform verbose error reporting if not NULL. 5585 * 5586 * @return 5587 * non-zero unique flow_id on success, otherwise 0 and 5588 * error/rte_error are set. 5589 */ 5590 static uint32_t 5591 flow_mreg_split_qrss_prep(struct rte_eth_dev *dev, 5592 struct rte_flow_action *split_actions, 5593 const struct rte_flow_action *actions, 5594 const struct rte_flow_action *qrss, 5595 int actions_n, int mtr_sfx, 5596 struct rte_flow_error *error) 5597 { 5598 struct mlx5_priv *priv = dev->data->dev_private; 5599 struct mlx5_rte_flow_action_set_tag *set_tag; 5600 struct rte_flow_action_jump *jump; 5601 const int qrss_idx = qrss - actions; 5602 uint32_t flow_id = 0; 5603 int ret = 0; 5604 5605 /* 5606 * Given actions will be split 5607 * - Replace QUEUE/RSS action with SET_TAG to set flow ID. 5608 * - Add jump to mreg CP_TBL. 5609 * As a result, there will be one more action. 5610 */ 5611 memcpy(split_actions, actions, sizeof(*split_actions) * actions_n); 5612 /* Count MLX5_RTE_FLOW_ACTION_TYPE_TAG. */ 5613 ++actions_n; 5614 set_tag = (void *)(split_actions + actions_n); 5615 /* 5616 * If we are not the meter suffix flow, add the tag action. 5617 * Since meter suffix flow already has the tag added. 5618 */ 5619 if (!mtr_sfx) { 5620 /* 5621 * Allocate the new subflow ID. This one is unique within 5622 * device and not shared with representors. Otherwise, 5623 * we would have to resolve multi-thread access synch 5624 * issue. Each flow on the shared device is appended 5625 * with source vport identifier, so the resulting 5626 * flows will be unique in the shared (by master and 5627 * representors) domain even if they have coinciding 5628 * IDs. 5629 */ 5630 mlx5_ipool_malloc(priv->sh->ipool 5631 [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], &flow_id); 5632 if (!flow_id) 5633 return rte_flow_error_set(error, ENOMEM, 5634 RTE_FLOW_ERROR_TYPE_ACTION, 5635 NULL, "can't allocate id " 5636 "for split Q/RSS subflow"); 5637 /* Internal SET_TAG action to set flow ID. */ 5638 *set_tag = (struct mlx5_rte_flow_action_set_tag){ 5639 .data = flow_id, 5640 }; 5641 ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, error); 5642 if (ret < 0) 5643 return ret; 5644 set_tag->id = ret; 5645 /* Construct new actions array. */ 5646 /* Replace QUEUE/RSS action. */ 5647 split_actions[qrss_idx] = (struct rte_flow_action){ 5648 .type = (enum rte_flow_action_type) 5649 MLX5_RTE_FLOW_ACTION_TYPE_TAG, 5650 .conf = set_tag, 5651 }; 5652 } else { 5653 /* 5654 * If we are the suffix flow of meter, tag already exist. 5655 * Set the QUEUE/RSS action to void. 5656 */ 5657 split_actions[qrss_idx].type = RTE_FLOW_ACTION_TYPE_VOID; 5658 } 5659 /* JUMP action to jump to mreg copy table (CP_TBL). */ 5660 jump = (void *)(set_tag + 1); 5661 *jump = (struct rte_flow_action_jump){ 5662 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP, 5663 }; 5664 split_actions[actions_n - 2] = (struct rte_flow_action){ 5665 .type = RTE_FLOW_ACTION_TYPE_JUMP, 5666 .conf = jump, 5667 }; 5668 split_actions[actions_n - 1] = (struct rte_flow_action){ 5669 .type = RTE_FLOW_ACTION_TYPE_END, 5670 }; 5671 return flow_id; 5672 } 5673 5674 /** 5675 * Extend the given action list for Tx metadata copy. 5676 * 5677 * Copy the given action list to the ext_actions and add flow metadata register 5678 * copy action in order to copy reg_a set by WQE to reg_c[0]. 5679 * 5680 * @param[out] ext_actions 5681 * Pointer to the extended action list. 5682 * @param[in] actions 5683 * Pointer to the list of actions. 5684 * @param[in] actions_n 5685 * Number of actions in the list. 5686 * @param[out] error 5687 * Perform verbose error reporting if not NULL. 5688 * @param[in] encap_idx 5689 * The encap action index. 5690 * 5691 * @return 5692 * 0 on success, negative value otherwise 5693 */ 5694 static int 5695 flow_mreg_tx_copy_prep(struct rte_eth_dev *dev, 5696 struct rte_flow_action *ext_actions, 5697 const struct rte_flow_action *actions, 5698 int actions_n, struct rte_flow_error *error, 5699 int encap_idx) 5700 { 5701 struct mlx5_flow_action_copy_mreg *cp_mreg = 5702 (struct mlx5_flow_action_copy_mreg *) 5703 (ext_actions + actions_n + 1); 5704 int ret; 5705 5706 ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_RX, 0, error); 5707 if (ret < 0) 5708 return ret; 5709 cp_mreg->dst = ret; 5710 ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_TX, 0, error); 5711 if (ret < 0) 5712 return ret; 5713 cp_mreg->src = ret; 5714 if (encap_idx != 0) 5715 memcpy(ext_actions, actions, sizeof(*ext_actions) * encap_idx); 5716 if (encap_idx == actions_n - 1) { 5717 ext_actions[actions_n - 1] = (struct rte_flow_action){ 5718 .type = (enum rte_flow_action_type) 5719 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 5720 .conf = cp_mreg, 5721 }; 5722 ext_actions[actions_n] = (struct rte_flow_action){ 5723 .type = RTE_FLOW_ACTION_TYPE_END, 5724 }; 5725 } else { 5726 ext_actions[encap_idx] = (struct rte_flow_action){ 5727 .type = (enum rte_flow_action_type) 5728 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 5729 .conf = cp_mreg, 5730 }; 5731 memcpy(ext_actions + encap_idx + 1, actions + encap_idx, 5732 sizeof(*ext_actions) * (actions_n - encap_idx)); 5733 } 5734 return 0; 5735 } 5736 5737 /** 5738 * Check the match action from the action list. 5739 * 5740 * @param[in] actions 5741 * Pointer to the list of actions. 5742 * @param[in] attr 5743 * Flow rule attributes. 5744 * @param[in] action 5745 * The action to be check if exist. 5746 * @param[out] match_action_pos 5747 * Pointer to the position of the matched action if exists, otherwise is -1. 5748 * @param[out] qrss_action_pos 5749 * Pointer to the position of the Queue/RSS action if exists, otherwise is -1. 5750 * @param[out] modify_after_mirror 5751 * Pointer to the flag of modify action after FDB mirroring. 5752 * 5753 * @return 5754 * > 0 the total number of actions. 5755 * 0 if not found match action in action list. 5756 */ 5757 static int 5758 flow_check_match_action(const struct rte_flow_action actions[], 5759 const struct rte_flow_attr *attr, 5760 enum rte_flow_action_type action, 5761 int *match_action_pos, int *qrss_action_pos, 5762 int *modify_after_mirror) 5763 { 5764 const struct rte_flow_action_sample *sample; 5765 const struct rte_flow_action_raw_decap *decap; 5766 int actions_n = 0; 5767 uint32_t ratio = 0; 5768 int sub_type = 0; 5769 int flag = 0; 5770 int fdb_mirror = 0; 5771 5772 *match_action_pos = -1; 5773 *qrss_action_pos = -1; 5774 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 5775 if (actions->type == action) { 5776 flag = 1; 5777 *match_action_pos = actions_n; 5778 } 5779 switch (actions->type) { 5780 case RTE_FLOW_ACTION_TYPE_QUEUE: 5781 case RTE_FLOW_ACTION_TYPE_RSS: 5782 *qrss_action_pos = actions_n; 5783 break; 5784 case RTE_FLOW_ACTION_TYPE_SAMPLE: 5785 sample = actions->conf; 5786 ratio = sample->ratio; 5787 sub_type = ((const struct rte_flow_action *) 5788 (sample->actions))->type; 5789 if (ratio == 1 && attr->transfer) 5790 fdb_mirror = 1; 5791 break; 5792 case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC: 5793 case RTE_FLOW_ACTION_TYPE_SET_MAC_DST: 5794 case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC: 5795 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST: 5796 case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC: 5797 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST: 5798 case RTE_FLOW_ACTION_TYPE_SET_TP_SRC: 5799 case RTE_FLOW_ACTION_TYPE_SET_TP_DST: 5800 case RTE_FLOW_ACTION_TYPE_DEC_TTL: 5801 case RTE_FLOW_ACTION_TYPE_SET_TTL: 5802 case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ: 5803 case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ: 5804 case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK: 5805 case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK: 5806 case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP: 5807 case RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP: 5808 case RTE_FLOW_ACTION_TYPE_FLAG: 5809 case RTE_FLOW_ACTION_TYPE_MARK: 5810 case RTE_FLOW_ACTION_TYPE_SET_META: 5811 case RTE_FLOW_ACTION_TYPE_SET_TAG: 5812 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: 5813 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 5814 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 5815 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: 5816 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 5817 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: 5818 case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD: 5819 case RTE_FLOW_ACTION_TYPE_METER: 5820 if (fdb_mirror) 5821 *modify_after_mirror = 1; 5822 break; 5823 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 5824 decap = actions->conf; 5825 while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID) 5826 ; 5827 actions_n++; 5828 if (actions->type == RTE_FLOW_ACTION_TYPE_RAW_ENCAP) { 5829 const struct rte_flow_action_raw_encap *encap = 5830 actions->conf; 5831 if (decap->size <= 5832 MLX5_ENCAPSULATION_DECISION_SIZE && 5833 encap->size > 5834 MLX5_ENCAPSULATION_DECISION_SIZE) 5835 /* L3 encap. */ 5836 break; 5837 } 5838 if (fdb_mirror) 5839 *modify_after_mirror = 1; 5840 break; 5841 default: 5842 break; 5843 } 5844 actions_n++; 5845 } 5846 if (flag && fdb_mirror && !*modify_after_mirror) { 5847 /* FDB mirroring uses the destination array to implement 5848 * instead of FLOW_SAMPLER object. 5849 */ 5850 if (sub_type != RTE_FLOW_ACTION_TYPE_END) 5851 flag = 0; 5852 } 5853 /* Count RTE_FLOW_ACTION_TYPE_END. */ 5854 return flag ? actions_n + 1 : 0; 5855 } 5856 5857 #define SAMPLE_SUFFIX_ITEM 3 5858 5859 /** 5860 * Split the sample flow. 5861 * 5862 * As sample flow will split to two sub flow, sample flow with 5863 * sample action, the other actions will move to new suffix flow. 5864 * 5865 * Also add unique tag id with tag action in the sample flow, 5866 * the same tag id will be as match in the suffix flow. 5867 * 5868 * @param dev 5869 * Pointer to Ethernet device. 5870 * @param[in] add_tag 5871 * Add extra tag action flag. 5872 * @param[out] sfx_items 5873 * Suffix flow match items (list terminated by the END pattern item). 5874 * @param[in] actions 5875 * Associated actions (list terminated by the END action). 5876 * @param[out] actions_sfx 5877 * Suffix flow actions. 5878 * @param[out] actions_pre 5879 * Prefix flow actions. 5880 * @param[in] actions_n 5881 * The total number of actions. 5882 * @param[in] sample_action_pos 5883 * The sample action position. 5884 * @param[in] qrss_action_pos 5885 * The Queue/RSS action position. 5886 * @param[in] jump_table 5887 * Add extra jump action flag. 5888 * @param[out] error 5889 * Perform verbose error reporting if not NULL. 5890 * 5891 * @return 5892 * 0 on success, or unique flow_id, a negative errno value 5893 * otherwise and rte_errno is set. 5894 */ 5895 static int 5896 flow_sample_split_prep(struct rte_eth_dev *dev, 5897 int add_tag, 5898 const struct rte_flow_item items[], 5899 struct rte_flow_item sfx_items[], 5900 const struct rte_flow_action actions[], 5901 struct rte_flow_action actions_sfx[], 5902 struct rte_flow_action actions_pre[], 5903 int actions_n, 5904 int sample_action_pos, 5905 int qrss_action_pos, 5906 int jump_table, 5907 struct rte_flow_error *error) 5908 { 5909 struct mlx5_priv *priv = dev->data->dev_private; 5910 struct mlx5_rte_flow_action_set_tag *set_tag; 5911 struct mlx5_rte_flow_item_tag *tag_spec; 5912 struct mlx5_rte_flow_item_tag *tag_mask; 5913 struct rte_flow_action_jump *jump_action; 5914 uint32_t tag_id = 0; 5915 int append_index = 0; 5916 int set_tag_idx = -1; 5917 int index; 5918 int ret; 5919 5920 if (sample_action_pos < 0) 5921 return rte_flow_error_set(error, EINVAL, 5922 RTE_FLOW_ERROR_TYPE_ACTION, 5923 NULL, "invalid position of sample " 5924 "action in list"); 5925 /* Prepare the actions for prefix and suffix flow. */ 5926 if (add_tag) { 5927 /* Update the new added tag action index preceding 5928 * the PUSH_VLAN or ENCAP action. 5929 */ 5930 const struct rte_flow_action_raw_encap *raw_encap; 5931 const struct rte_flow_action *action = actions; 5932 int encap_idx; 5933 int action_idx = 0; 5934 int raw_decap_idx = -1; 5935 int push_vlan_idx = -1; 5936 for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) { 5937 switch (action->type) { 5938 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 5939 raw_decap_idx = action_idx; 5940 break; 5941 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 5942 raw_encap = action->conf; 5943 if (raw_encap->size > 5944 MLX5_ENCAPSULATION_DECISION_SIZE) { 5945 encap_idx = raw_decap_idx != -1 ? 5946 raw_decap_idx : action_idx; 5947 if (encap_idx < sample_action_pos && 5948 push_vlan_idx == -1) 5949 set_tag_idx = encap_idx; 5950 } 5951 break; 5952 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 5953 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 5954 encap_idx = action_idx; 5955 if (encap_idx < sample_action_pos && 5956 push_vlan_idx == -1) 5957 set_tag_idx = encap_idx; 5958 break; 5959 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 5960 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 5961 push_vlan_idx = action_idx; 5962 if (push_vlan_idx < sample_action_pos) 5963 set_tag_idx = action_idx; 5964 break; 5965 default: 5966 break; 5967 } 5968 action_idx++; 5969 } 5970 } 5971 /* Prepare the actions for prefix and suffix flow. */ 5972 if (qrss_action_pos >= 0 && qrss_action_pos < sample_action_pos) { 5973 index = qrss_action_pos; 5974 /* Put the preceding the Queue/RSS action into prefix flow. */ 5975 if (index != 0) 5976 memcpy(actions_pre, actions, 5977 sizeof(struct rte_flow_action) * index); 5978 /* Put others preceding the sample action into prefix flow. */ 5979 if (sample_action_pos > index + 1) 5980 memcpy(actions_pre + index, actions + index + 1, 5981 sizeof(struct rte_flow_action) * 5982 (sample_action_pos - index - 1)); 5983 index = sample_action_pos - 1; 5984 /* Put Queue/RSS action into Suffix flow. */ 5985 memcpy(actions_sfx, actions + qrss_action_pos, 5986 sizeof(struct rte_flow_action)); 5987 actions_sfx++; 5988 } else if (add_tag && set_tag_idx >= 0) { 5989 if (set_tag_idx > 0) 5990 memcpy(actions_pre, actions, 5991 sizeof(struct rte_flow_action) * set_tag_idx); 5992 memcpy(actions_pre + set_tag_idx + 1, actions + set_tag_idx, 5993 sizeof(struct rte_flow_action) * 5994 (sample_action_pos - set_tag_idx)); 5995 index = sample_action_pos; 5996 } else { 5997 index = sample_action_pos; 5998 if (index != 0) 5999 memcpy(actions_pre, actions, 6000 sizeof(struct rte_flow_action) * index); 6001 } 6002 /* For CX5, add an extra tag action for NIC-RX and E-Switch ingress. 6003 * For CX6DX and above, metadata registers Cx preserve their value, 6004 * add an extra tag action for NIC-RX and E-Switch Domain. 6005 */ 6006 if (add_tag) { 6007 /* Prepare the prefix tag action. */ 6008 append_index++; 6009 set_tag = (void *)(actions_pre + actions_n + append_index); 6010 ret = mlx5_flow_get_reg_id(dev, MLX5_SAMPLE_ID, 0, error); 6011 /* Trust VF/SF on CX5 not supported meter so that the reserved 6012 * metadata regC is REG_NON, back to use application tag 6013 * index 0. 6014 */ 6015 if (unlikely(ret == REG_NON)) 6016 ret = mlx5_flow_get_reg_id(dev, MLX5_APP_TAG, 0, error); 6017 if (ret < 0) 6018 return ret; 6019 mlx5_ipool_malloc(priv->sh->ipool 6020 [MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], &tag_id); 6021 *set_tag = (struct mlx5_rte_flow_action_set_tag) { 6022 .id = ret, 6023 .data = tag_id, 6024 }; 6025 /* Prepare the suffix subflow items. */ 6026 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 6027 if (items->type == RTE_FLOW_ITEM_TYPE_PORT_ID) { 6028 memcpy(sfx_items, items, sizeof(*sfx_items)); 6029 sfx_items++; 6030 } 6031 } 6032 tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM); 6033 tag_spec->data = tag_id; 6034 tag_spec->id = set_tag->id; 6035 tag_mask = tag_spec + 1; 6036 tag_mask->data = UINT32_MAX; 6037 sfx_items[0] = (struct rte_flow_item){ 6038 .type = (enum rte_flow_item_type) 6039 MLX5_RTE_FLOW_ITEM_TYPE_TAG, 6040 .spec = tag_spec, 6041 .last = NULL, 6042 .mask = tag_mask, 6043 }; 6044 sfx_items[1] = (struct rte_flow_item){ 6045 .type = (enum rte_flow_item_type) 6046 RTE_FLOW_ITEM_TYPE_END, 6047 }; 6048 /* Prepare the tag action in prefix subflow. */ 6049 set_tag_idx = (set_tag_idx == -1) ? index : set_tag_idx; 6050 actions_pre[set_tag_idx] = 6051 (struct rte_flow_action){ 6052 .type = (enum rte_flow_action_type) 6053 MLX5_RTE_FLOW_ACTION_TYPE_TAG, 6054 .conf = set_tag, 6055 }; 6056 /* Update next sample position due to add one tag action */ 6057 index += 1; 6058 } 6059 /* Copy the sample action into prefix flow. */ 6060 memcpy(actions_pre + index, actions + sample_action_pos, 6061 sizeof(struct rte_flow_action)); 6062 index += 1; 6063 /* For the modify action after the sample action in E-Switch mirroring, 6064 * Add the extra jump action in prefix subflow and jump into the next 6065 * table, then do the modify action in the new table. 6066 */ 6067 if (jump_table) { 6068 /* Prepare the prefix jump action. */ 6069 append_index++; 6070 jump_action = (void *)(actions_pre + actions_n + append_index); 6071 jump_action->group = jump_table; 6072 actions_pre[index++] = 6073 (struct rte_flow_action){ 6074 .type = (enum rte_flow_action_type) 6075 RTE_FLOW_ACTION_TYPE_JUMP, 6076 .conf = jump_action, 6077 }; 6078 } 6079 actions_pre[index] = (struct rte_flow_action){ 6080 .type = (enum rte_flow_action_type) 6081 RTE_FLOW_ACTION_TYPE_END, 6082 }; 6083 /* Put the actions after sample into Suffix flow. */ 6084 memcpy(actions_sfx, actions + sample_action_pos + 1, 6085 sizeof(struct rte_flow_action) * 6086 (actions_n - sample_action_pos - 1)); 6087 return tag_id; 6088 } 6089 6090 /** 6091 * The splitting for metadata feature. 6092 * 6093 * - Q/RSS action on NIC Rx should be split in order to pass by 6094 * the mreg copy table (RX_CP_TBL) and then it jumps to the 6095 * action table (RX_ACT_TBL) which has the split Q/RSS action. 6096 * 6097 * - All the actions on NIC Tx should have a mreg copy action to 6098 * copy reg_a from WQE to reg_c[0]. 6099 * 6100 * @param dev 6101 * Pointer to Ethernet device. 6102 * @param[in] flow 6103 * Parent flow structure pointer. 6104 * @param[in] attr 6105 * Flow rule attributes. 6106 * @param[in] items 6107 * Pattern specification (list terminated by the END pattern item). 6108 * @param[in] actions 6109 * Associated actions (list terminated by the END action). 6110 * @param[in] flow_split_info 6111 * Pointer to flow split info structure. 6112 * @param[out] error 6113 * Perform verbose error reporting if not NULL. 6114 * @return 6115 * 0 on success, negative value otherwise 6116 */ 6117 static int 6118 flow_create_split_metadata(struct rte_eth_dev *dev, 6119 struct rte_flow *flow, 6120 const struct rte_flow_attr *attr, 6121 const struct rte_flow_item items[], 6122 const struct rte_flow_action actions[], 6123 struct mlx5_flow_split_info *flow_split_info, 6124 struct rte_flow_error *error) 6125 { 6126 struct mlx5_priv *priv = dev->data->dev_private; 6127 struct mlx5_sh_config *config = &priv->sh->config; 6128 const struct rte_flow_action *qrss = NULL; 6129 struct rte_flow_action *ext_actions = NULL; 6130 struct mlx5_flow *dev_flow = NULL; 6131 uint32_t qrss_id = 0; 6132 int mtr_sfx = 0; 6133 size_t act_size; 6134 int actions_n; 6135 int encap_idx; 6136 int ret; 6137 6138 /* Check whether extensive metadata feature is engaged. */ 6139 if (!config->dv_flow_en || 6140 config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || 6141 !mlx5_flow_ext_mreg_supported(dev)) 6142 return flow_create_split_inner(dev, flow, NULL, attr, items, 6143 actions, flow_split_info, error); 6144 actions_n = flow_parse_metadata_split_actions_info(actions, &qrss, 6145 &encap_idx); 6146 if (qrss) { 6147 /* Exclude hairpin flows from splitting. */ 6148 if (qrss->type == RTE_FLOW_ACTION_TYPE_QUEUE) { 6149 const struct rte_flow_action_queue *queue; 6150 6151 queue = qrss->conf; 6152 if (mlx5_rxq_is_hairpin(dev, queue->index)) 6153 qrss = NULL; 6154 } else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) { 6155 const struct rte_flow_action_rss *rss; 6156 6157 rss = qrss->conf; 6158 if (mlx5_rxq_is_hairpin(dev, rss->queue[0])) 6159 qrss = NULL; 6160 } 6161 } 6162 if (qrss) { 6163 /* Check if it is in meter suffix table. */ 6164 mtr_sfx = attr->group == (attr->transfer ? 6165 (MLX5_FLOW_TABLE_LEVEL_METER - 1) : 6166 MLX5_FLOW_TABLE_LEVEL_METER); 6167 /* 6168 * Q/RSS action on NIC Rx should be split in order to pass by 6169 * the mreg copy table (RX_CP_TBL) and then it jumps to the 6170 * action table (RX_ACT_TBL) which has the split Q/RSS action. 6171 */ 6172 act_size = sizeof(struct rte_flow_action) * (actions_n + 1) + 6173 sizeof(struct rte_flow_action_set_tag) + 6174 sizeof(struct rte_flow_action_jump); 6175 ext_actions = mlx5_malloc(MLX5_MEM_ZERO, act_size, 0, 6176 SOCKET_ID_ANY); 6177 if (!ext_actions) 6178 return rte_flow_error_set(error, ENOMEM, 6179 RTE_FLOW_ERROR_TYPE_ACTION, 6180 NULL, "no memory to split " 6181 "metadata flow"); 6182 /* 6183 * Create the new actions list with removed Q/RSS action 6184 * and appended set tag and jump to register copy table 6185 * (RX_CP_TBL). We should preallocate unique tag ID here 6186 * in advance, because it is needed for set tag action. 6187 */ 6188 qrss_id = flow_mreg_split_qrss_prep(dev, ext_actions, actions, 6189 qrss, actions_n, 6190 mtr_sfx, error); 6191 if (!mtr_sfx && !qrss_id) { 6192 ret = -rte_errno; 6193 goto exit; 6194 } 6195 } else if (attr->egress && !attr->transfer) { 6196 /* 6197 * All the actions on NIC Tx should have a metadata register 6198 * copy action to copy reg_a from WQE to reg_c[meta] 6199 */ 6200 act_size = sizeof(struct rte_flow_action) * (actions_n + 1) + 6201 sizeof(struct mlx5_flow_action_copy_mreg); 6202 ext_actions = mlx5_malloc(MLX5_MEM_ZERO, act_size, 0, 6203 SOCKET_ID_ANY); 6204 if (!ext_actions) 6205 return rte_flow_error_set(error, ENOMEM, 6206 RTE_FLOW_ERROR_TYPE_ACTION, 6207 NULL, "no memory to split " 6208 "metadata flow"); 6209 /* Create the action list appended with copy register. */ 6210 ret = flow_mreg_tx_copy_prep(dev, ext_actions, actions, 6211 actions_n, error, encap_idx); 6212 if (ret < 0) 6213 goto exit; 6214 } 6215 /* Add the unmodified original or prefix subflow. */ 6216 ret = flow_create_split_inner(dev, flow, &dev_flow, attr, 6217 items, ext_actions ? ext_actions : 6218 actions, flow_split_info, error); 6219 if (ret < 0) 6220 goto exit; 6221 MLX5_ASSERT(dev_flow); 6222 if (qrss) { 6223 const struct rte_flow_attr q_attr = { 6224 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP, 6225 .ingress = 1, 6226 }; 6227 /* Internal PMD action to set register. */ 6228 struct mlx5_rte_flow_item_tag q_tag_spec = { 6229 .data = qrss_id, 6230 .id = REG_NON, 6231 }; 6232 struct rte_flow_item q_items[] = { 6233 { 6234 .type = (enum rte_flow_item_type) 6235 MLX5_RTE_FLOW_ITEM_TYPE_TAG, 6236 .spec = &q_tag_spec, 6237 .last = NULL, 6238 .mask = NULL, 6239 }, 6240 { 6241 .type = RTE_FLOW_ITEM_TYPE_END, 6242 }, 6243 }; 6244 struct rte_flow_action q_actions[] = { 6245 { 6246 .type = qrss->type, 6247 .conf = qrss->conf, 6248 }, 6249 { 6250 .type = RTE_FLOW_ACTION_TYPE_END, 6251 }, 6252 }; 6253 uint64_t layers = flow_get_prefix_layer_flags(dev_flow); 6254 6255 /* 6256 * Configure the tag item only if there is no meter subflow. 6257 * Since tag is already marked in the meter suffix subflow 6258 * we can just use the meter suffix items as is. 6259 */ 6260 if (qrss_id) { 6261 /* Not meter subflow. */ 6262 MLX5_ASSERT(!mtr_sfx); 6263 /* 6264 * Put unique id in prefix flow due to it is destroyed 6265 * after suffix flow and id will be freed after there 6266 * is no actual flows with this id and identifier 6267 * reallocation becomes possible (for example, for 6268 * other flows in other threads). 6269 */ 6270 dev_flow->handle->split_flow_id = qrss_id; 6271 ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, 6272 error); 6273 if (ret < 0) 6274 goto exit; 6275 q_tag_spec.id = ret; 6276 } 6277 dev_flow = NULL; 6278 /* Add suffix subflow to execute Q/RSS. */ 6279 flow_split_info->prefix_layers = layers; 6280 flow_split_info->prefix_mark = 0; 6281 flow_split_info->table_id = 0; 6282 ret = flow_create_split_inner(dev, flow, &dev_flow, 6283 &q_attr, mtr_sfx ? items : 6284 q_items, q_actions, 6285 flow_split_info, error); 6286 if (ret < 0) 6287 goto exit; 6288 /* qrss ID should be freed if failed. */ 6289 qrss_id = 0; 6290 MLX5_ASSERT(dev_flow); 6291 } 6292 6293 exit: 6294 /* 6295 * We do not destroy the partially created sub_flows in case of error. 6296 * These ones are included into parent flow list and will be destroyed 6297 * by flow_drv_destroy. 6298 */ 6299 mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_EXPANTION_FLOW_ID], 6300 qrss_id); 6301 mlx5_free(ext_actions); 6302 return ret; 6303 } 6304 6305 /** 6306 * Create meter internal drop flow with the original pattern. 6307 * 6308 * @param dev 6309 * Pointer to Ethernet device. 6310 * @param[in] flow 6311 * Parent flow structure pointer. 6312 * @param[in] attr 6313 * Flow rule attributes. 6314 * @param[in] items 6315 * Pattern specification (list terminated by the END pattern item). 6316 * @param[in] flow_split_info 6317 * Pointer to flow split info structure. 6318 * @param[in] fm 6319 * Pointer to flow meter structure. 6320 * @param[out] error 6321 * Perform verbose error reporting if not NULL. 6322 * @return 6323 * 0 on success, negative value otherwise 6324 */ 6325 static uint32_t 6326 flow_meter_create_drop_flow_with_org_pattern(struct rte_eth_dev *dev, 6327 struct rte_flow *flow, 6328 const struct rte_flow_attr *attr, 6329 const struct rte_flow_item items[], 6330 struct mlx5_flow_split_info *flow_split_info, 6331 struct mlx5_flow_meter_info *fm, 6332 struct rte_flow_error *error) 6333 { 6334 struct mlx5_flow *dev_flow = NULL; 6335 struct rte_flow_attr drop_attr = *attr; 6336 struct rte_flow_action drop_actions[3]; 6337 struct mlx5_flow_split_info drop_split_info = *flow_split_info; 6338 6339 MLX5_ASSERT(fm->drop_cnt); 6340 drop_actions[0].type = 6341 (enum rte_flow_action_type)MLX5_RTE_FLOW_ACTION_TYPE_COUNT; 6342 drop_actions[0].conf = (void *)(uintptr_t)fm->drop_cnt; 6343 drop_actions[1].type = RTE_FLOW_ACTION_TYPE_DROP; 6344 drop_actions[1].conf = NULL; 6345 drop_actions[2].type = RTE_FLOW_ACTION_TYPE_END; 6346 drop_actions[2].conf = NULL; 6347 drop_split_info.external = false; 6348 drop_split_info.skip_scale |= 1 << MLX5_SCALE_FLOW_GROUP_BIT; 6349 drop_split_info.table_id = MLX5_MTR_TABLE_ID_DROP; 6350 drop_attr.group = MLX5_FLOW_TABLE_LEVEL_METER; 6351 return flow_create_split_inner(dev, flow, &dev_flow, 6352 &drop_attr, items, drop_actions, 6353 &drop_split_info, error); 6354 } 6355 6356 /** 6357 * The splitting for meter feature. 6358 * 6359 * - The meter flow will be split to two flows as prefix and 6360 * suffix flow. The packets make sense only it pass the prefix 6361 * meter action. 6362 * 6363 * - Reg_C_5 is used for the packet to match betweend prefix and 6364 * suffix flow. 6365 * 6366 * @param dev 6367 * Pointer to Ethernet device. 6368 * @param[in] flow 6369 * Parent flow structure pointer. 6370 * @param[in] attr 6371 * Flow rule attributes. 6372 * @param[in] items 6373 * Pattern specification (list terminated by the END pattern item). 6374 * @param[in] actions 6375 * Associated actions (list terminated by the END action). 6376 * @param[in] flow_split_info 6377 * Pointer to flow split info structure. 6378 * @param[out] error 6379 * Perform verbose error reporting if not NULL. 6380 * @return 6381 * 0 on success, negative value otherwise 6382 */ 6383 static int 6384 flow_create_split_meter(struct rte_eth_dev *dev, 6385 struct rte_flow *flow, 6386 const struct rte_flow_attr *attr, 6387 const struct rte_flow_item items[], 6388 const struct rte_flow_action actions[], 6389 struct mlx5_flow_split_info *flow_split_info, 6390 struct rte_flow_error *error) 6391 { 6392 struct mlx5_priv *priv = dev->data->dev_private; 6393 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 6394 struct rte_flow_action *sfx_actions = NULL; 6395 struct rte_flow_action *pre_actions = NULL; 6396 struct rte_flow_item *sfx_items = NULL; 6397 struct mlx5_flow *dev_flow = NULL; 6398 struct rte_flow_attr sfx_attr = *attr; 6399 struct mlx5_flow_meter_info *fm = NULL; 6400 uint8_t skip_scale_restore; 6401 bool has_mtr = false; 6402 bool has_modify = false; 6403 bool set_mtr_reg = true; 6404 bool is_mtr_hierarchy = false; 6405 uint32_t meter_id = 0; 6406 uint32_t mtr_idx = 0; 6407 uint32_t mtr_flow_id = 0; 6408 size_t act_size; 6409 size_t item_size; 6410 int actions_n = 0; 6411 int ret = 0; 6412 6413 if (priv->mtr_en) 6414 actions_n = flow_check_meter_action(dev, actions, &has_mtr, 6415 &has_modify, &meter_id); 6416 if (has_mtr) { 6417 if (flow->meter) { 6418 fm = flow_dv_meter_find_by_idx(priv, flow->meter); 6419 if (!fm) 6420 return rte_flow_error_set(error, EINVAL, 6421 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 6422 NULL, "Meter not found."); 6423 } else { 6424 fm = mlx5_flow_meter_find(priv, meter_id, &mtr_idx); 6425 if (!fm) 6426 return rte_flow_error_set(error, EINVAL, 6427 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 6428 NULL, "Meter not found."); 6429 ret = mlx5_flow_meter_attach(priv, fm, 6430 &sfx_attr, error); 6431 if (ret) 6432 return -rte_errno; 6433 flow->meter = mtr_idx; 6434 } 6435 MLX5_ASSERT(wks); 6436 wks->fm = fm; 6437 if (!fm->def_policy) { 6438 wks->policy = mlx5_flow_meter_policy_find(dev, 6439 fm->policy_id, 6440 NULL); 6441 MLX5_ASSERT(wks->policy); 6442 if (wks->policy->mark) 6443 wks->mark = 1; 6444 if (wks->policy->is_hierarchy) { 6445 wks->final_policy = 6446 mlx5_flow_meter_hierarchy_get_final_policy(dev, 6447 wks->policy); 6448 if (!wks->final_policy) 6449 return rte_flow_error_set(error, 6450 EINVAL, 6451 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 6452 "Failed to find terminal policy of hierarchy."); 6453 is_mtr_hierarchy = true; 6454 } 6455 } 6456 /* 6457 * If it isn't default-policy Meter, and 6458 * 1. Not meter hierarchy and there's no action in flow to change 6459 * packet (modify/encap/decap etc.), OR 6460 * 2. No drop count needed for this meter. 6461 * Then no need to use regC to save meter id anymore. 6462 */ 6463 if (!fm->def_policy && ((!has_modify && !is_mtr_hierarchy) || !fm->drop_cnt)) 6464 set_mtr_reg = false; 6465 /* Prefix actions: meter, decap, encap, tag, jump, end, cnt. */ 6466 #define METER_PREFIX_ACTION 7 6467 act_size = (sizeof(struct rte_flow_action) * 6468 (actions_n + METER_PREFIX_ACTION)) + 6469 sizeof(struct mlx5_rte_flow_action_set_tag); 6470 /* Suffix items: tag, vlan, port id, end. */ 6471 #define METER_SUFFIX_ITEM 4 6472 item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM + 6473 sizeof(struct mlx5_rte_flow_item_tag) * 2; 6474 sfx_actions = mlx5_malloc(MLX5_MEM_ZERO, (act_size + item_size), 6475 0, SOCKET_ID_ANY); 6476 if (!sfx_actions) 6477 return rte_flow_error_set(error, ENOMEM, 6478 RTE_FLOW_ERROR_TYPE_ACTION, 6479 NULL, "no memory to split " 6480 "meter flow"); 6481 sfx_items = (struct rte_flow_item *)((char *)sfx_actions + 6482 act_size); 6483 /* There's no suffix flow for meter of non-default policy. */ 6484 if (!fm->def_policy) 6485 pre_actions = sfx_actions + 1; 6486 else 6487 pre_actions = sfx_actions + actions_n; 6488 ret = flow_meter_split_prep(dev, flow, wks, &sfx_attr, 6489 items, sfx_items, actions, 6490 sfx_actions, pre_actions, 6491 (set_mtr_reg ? &mtr_flow_id : NULL), 6492 error); 6493 if (ret) { 6494 ret = -rte_errno; 6495 goto exit; 6496 } 6497 /* Add the prefix subflow. */ 6498 skip_scale_restore = flow_split_info->skip_scale; 6499 flow_split_info->skip_scale |= 6500 1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT; 6501 ret = flow_create_split_inner(dev, flow, &dev_flow, 6502 attr, items, pre_actions, 6503 flow_split_info, error); 6504 flow_split_info->skip_scale = skip_scale_restore; 6505 if (ret) { 6506 if (mtr_flow_id) 6507 mlx5_ipool_free(fm->flow_ipool, mtr_flow_id); 6508 ret = -rte_errno; 6509 goto exit; 6510 } 6511 if (mtr_flow_id) { 6512 dev_flow->handle->split_flow_id = mtr_flow_id; 6513 dev_flow->handle->is_meter_flow_id = 1; 6514 } 6515 if (!fm->def_policy) { 6516 if (!set_mtr_reg && fm->drop_cnt) 6517 ret = 6518 flow_meter_create_drop_flow_with_org_pattern(dev, flow, 6519 &sfx_attr, items, 6520 flow_split_info, 6521 fm, error); 6522 goto exit; 6523 } 6524 /* Setting the sfx group atrr. */ 6525 sfx_attr.group = sfx_attr.transfer ? 6526 (MLX5_FLOW_TABLE_LEVEL_METER - 1) : 6527 MLX5_FLOW_TABLE_LEVEL_METER; 6528 flow_split_info->prefix_layers = 6529 flow_get_prefix_layer_flags(dev_flow); 6530 flow_split_info->prefix_mark |= wks->mark; 6531 flow_split_info->table_id = MLX5_MTR_TABLE_ID_SUFFIX; 6532 } 6533 /* Add the prefix subflow. */ 6534 ret = flow_create_split_metadata(dev, flow, 6535 &sfx_attr, sfx_items ? 6536 sfx_items : items, 6537 sfx_actions ? sfx_actions : actions, 6538 flow_split_info, error); 6539 exit: 6540 if (sfx_actions) 6541 mlx5_free(sfx_actions); 6542 return ret; 6543 } 6544 6545 /** 6546 * The splitting for sample feature. 6547 * 6548 * Once Sample action is detected in the action list, the flow actions should 6549 * be split into prefix sub flow and suffix sub flow. 6550 * 6551 * The original items remain in the prefix sub flow, all actions preceding the 6552 * sample action and the sample action itself will be copied to the prefix 6553 * sub flow, the actions following the sample action will be copied to the 6554 * suffix sub flow, Queue action always be located in the suffix sub flow. 6555 * 6556 * In order to make the packet from prefix sub flow matches with suffix sub 6557 * flow, an extra tag action be added into prefix sub flow, and the suffix sub 6558 * flow uses tag item with the unique flow id. 6559 * 6560 * @param dev 6561 * Pointer to Ethernet device. 6562 * @param[in] flow 6563 * Parent flow structure pointer. 6564 * @param[in] attr 6565 * Flow rule attributes. 6566 * @param[in] items 6567 * Pattern specification (list terminated by the END pattern item). 6568 * @param[in] actions 6569 * Associated actions (list terminated by the END action). 6570 * @param[in] flow_split_info 6571 * Pointer to flow split info structure. 6572 * @param[out] error 6573 * Perform verbose error reporting if not NULL. 6574 * @return 6575 * 0 on success, negative value otherwise 6576 */ 6577 static int 6578 flow_create_split_sample(struct rte_eth_dev *dev, 6579 struct rte_flow *flow, 6580 const struct rte_flow_attr *attr, 6581 const struct rte_flow_item items[], 6582 const struct rte_flow_action actions[], 6583 struct mlx5_flow_split_info *flow_split_info, 6584 struct rte_flow_error *error) 6585 { 6586 struct mlx5_priv *priv = dev->data->dev_private; 6587 struct rte_flow_action *sfx_actions = NULL; 6588 struct rte_flow_action *pre_actions = NULL; 6589 struct rte_flow_item *sfx_items = NULL; 6590 struct mlx5_flow *dev_flow = NULL; 6591 struct rte_flow_attr sfx_attr = *attr; 6592 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 6593 struct mlx5_flow_dv_sample_resource *sample_res; 6594 struct mlx5_flow_tbl_data_entry *sfx_tbl_data; 6595 struct mlx5_flow_tbl_resource *sfx_tbl; 6596 struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); 6597 #endif 6598 size_t act_size; 6599 size_t item_size; 6600 uint32_t fdb_tx = 0; 6601 int32_t tag_id = 0; 6602 int actions_n = 0; 6603 int sample_action_pos; 6604 int qrss_action_pos; 6605 int add_tag = 0; 6606 int modify_after_mirror = 0; 6607 uint16_t jump_table = 0; 6608 const uint32_t next_ft_step = 1; 6609 int ret = 0; 6610 6611 if (priv->sampler_en) 6612 actions_n = flow_check_match_action(actions, attr, 6613 RTE_FLOW_ACTION_TYPE_SAMPLE, 6614 &sample_action_pos, &qrss_action_pos, 6615 &modify_after_mirror); 6616 if (actions_n) { 6617 /* The prefix actions must includes sample, tag, end. */ 6618 act_size = sizeof(struct rte_flow_action) * (actions_n * 2 + 1) 6619 + sizeof(struct mlx5_rte_flow_action_set_tag); 6620 item_size = sizeof(struct rte_flow_item) * SAMPLE_SUFFIX_ITEM + 6621 sizeof(struct mlx5_rte_flow_item_tag) * 2; 6622 sfx_actions = mlx5_malloc(MLX5_MEM_ZERO, (act_size + 6623 item_size), 0, SOCKET_ID_ANY); 6624 if (!sfx_actions) 6625 return rte_flow_error_set(error, ENOMEM, 6626 RTE_FLOW_ERROR_TYPE_ACTION, 6627 NULL, "no memory to split " 6628 "sample flow"); 6629 /* The representor_id is UINT16_MAX for uplink. */ 6630 fdb_tx = (attr->transfer && priv->representor_id != UINT16_MAX); 6631 /* 6632 * When reg_c_preserve is set, metadata registers Cx preserve 6633 * their value even through packet duplication. 6634 */ 6635 add_tag = (!fdb_tx || 6636 priv->sh->cdev->config.hca_attr.reg_c_preserve); 6637 if (add_tag) 6638 sfx_items = (struct rte_flow_item *)((char *)sfx_actions 6639 + act_size); 6640 if (modify_after_mirror) 6641 jump_table = attr->group * MLX5_FLOW_TABLE_FACTOR + 6642 next_ft_step; 6643 pre_actions = sfx_actions + actions_n; 6644 tag_id = flow_sample_split_prep(dev, add_tag, items, sfx_items, 6645 actions, sfx_actions, 6646 pre_actions, actions_n, 6647 sample_action_pos, 6648 qrss_action_pos, jump_table, 6649 error); 6650 if (tag_id < 0 || (add_tag && !tag_id)) { 6651 ret = -rte_errno; 6652 goto exit; 6653 } 6654 if (modify_after_mirror) 6655 flow_split_info->skip_scale = 6656 1 << MLX5_SCALE_JUMP_FLOW_GROUP_BIT; 6657 /* Add the prefix subflow. */ 6658 ret = flow_create_split_inner(dev, flow, &dev_flow, attr, 6659 items, pre_actions, 6660 flow_split_info, error); 6661 if (ret) { 6662 ret = -rte_errno; 6663 goto exit; 6664 } 6665 dev_flow->handle->split_flow_id = tag_id; 6666 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 6667 if (!modify_after_mirror) { 6668 /* Set the sfx group attr. */ 6669 sample_res = (struct mlx5_flow_dv_sample_resource *) 6670 dev_flow->dv.sample_res; 6671 sfx_tbl = (struct mlx5_flow_tbl_resource *) 6672 sample_res->normal_path_tbl; 6673 sfx_tbl_data = container_of(sfx_tbl, 6674 struct mlx5_flow_tbl_data_entry, 6675 tbl); 6676 sfx_attr.group = sfx_attr.transfer ? 6677 (sfx_tbl_data->level - 1) : sfx_tbl_data->level; 6678 } else { 6679 MLX5_ASSERT(attr->transfer); 6680 sfx_attr.group = jump_table; 6681 } 6682 flow_split_info->prefix_layers = 6683 flow_get_prefix_layer_flags(dev_flow); 6684 MLX5_ASSERT(wks); 6685 flow_split_info->prefix_mark |= wks->mark; 6686 /* Suffix group level already be scaled with factor, set 6687 * MLX5_SCALE_FLOW_GROUP_BIT of skip_scale to 1 to avoid scale 6688 * again in translation. 6689 */ 6690 flow_split_info->skip_scale = 1 << MLX5_SCALE_FLOW_GROUP_BIT; 6691 #endif 6692 } 6693 /* Add the suffix subflow. */ 6694 ret = flow_create_split_meter(dev, flow, &sfx_attr, 6695 sfx_items ? sfx_items : items, 6696 sfx_actions ? sfx_actions : actions, 6697 flow_split_info, error); 6698 exit: 6699 if (sfx_actions) 6700 mlx5_free(sfx_actions); 6701 return ret; 6702 } 6703 6704 /** 6705 * Split the flow to subflow set. The splitters might be linked 6706 * in the chain, like this: 6707 * flow_create_split_outer() calls: 6708 * flow_create_split_meter() calls: 6709 * flow_create_split_metadata(meter_subflow_0) calls: 6710 * flow_create_split_inner(metadata_subflow_0) 6711 * flow_create_split_inner(metadata_subflow_1) 6712 * flow_create_split_inner(metadata_subflow_2) 6713 * flow_create_split_metadata(meter_subflow_1) calls: 6714 * flow_create_split_inner(metadata_subflow_0) 6715 * flow_create_split_inner(metadata_subflow_1) 6716 * flow_create_split_inner(metadata_subflow_2) 6717 * 6718 * This provide flexible way to add new levels of flow splitting. 6719 * The all of successfully created subflows are included to the 6720 * parent flow dev_flow list. 6721 * 6722 * @param dev 6723 * Pointer to Ethernet device. 6724 * @param[in] flow 6725 * Parent flow structure pointer. 6726 * @param[in] attr 6727 * Flow rule attributes. 6728 * @param[in] items 6729 * Pattern specification (list terminated by the END pattern item). 6730 * @param[in] actions 6731 * Associated actions (list terminated by the END action). 6732 * @param[in] flow_split_info 6733 * Pointer to flow split info structure. 6734 * @param[out] error 6735 * Perform verbose error reporting if not NULL. 6736 * @return 6737 * 0 on success, negative value otherwise 6738 */ 6739 static int 6740 flow_create_split_outer(struct rte_eth_dev *dev, 6741 struct rte_flow *flow, 6742 const struct rte_flow_attr *attr, 6743 const struct rte_flow_item items[], 6744 const struct rte_flow_action actions[], 6745 struct mlx5_flow_split_info *flow_split_info, 6746 struct rte_flow_error *error) 6747 { 6748 int ret; 6749 6750 ret = flow_create_split_sample(dev, flow, attr, items, 6751 actions, flow_split_info, error); 6752 MLX5_ASSERT(ret <= 0); 6753 return ret; 6754 } 6755 6756 static inline struct mlx5_flow_tunnel * 6757 flow_tunnel_from_rule(const struct mlx5_flow *flow) 6758 { 6759 struct mlx5_flow_tunnel *tunnel; 6760 6761 #pragma GCC diagnostic push 6762 #pragma GCC diagnostic ignored "-Wcast-qual" 6763 tunnel = (typeof(tunnel))flow->tunnel; 6764 #pragma GCC diagnostic pop 6765 6766 return tunnel; 6767 } 6768 6769 /** 6770 * Adjust flow RSS workspace if needed. 6771 * 6772 * @param wks 6773 * Pointer to thread flow work space. 6774 * @param rss_desc 6775 * Pointer to RSS descriptor. 6776 * @param[in] nrssq_num 6777 * New RSS queue number. 6778 * 6779 * @return 6780 * 0 on success, -1 otherwise and rte_errno is set. 6781 */ 6782 static int 6783 flow_rss_workspace_adjust(struct mlx5_flow_workspace *wks, 6784 struct mlx5_flow_rss_desc *rss_desc, 6785 uint32_t nrssq_num) 6786 { 6787 if (likely(nrssq_num <= wks->rssq_num)) 6788 return 0; 6789 rss_desc->queue = realloc(rss_desc->queue, 6790 sizeof(*rss_desc->queue) * RTE_ALIGN(nrssq_num, 2)); 6791 if (!rss_desc->queue) { 6792 rte_errno = ENOMEM; 6793 return -1; 6794 } 6795 wks->rssq_num = RTE_ALIGN(nrssq_num, 2); 6796 return 0; 6797 } 6798 6799 /** 6800 * Create a flow and add it to @p list. 6801 * 6802 * @param dev 6803 * Pointer to Ethernet device. 6804 * @param list 6805 * Pointer to a TAILQ flow list. If this parameter NULL, 6806 * no list insertion occurred, flow is just created, 6807 * this is caller's responsibility to track the 6808 * created flow. 6809 * @param[in] attr 6810 * Flow rule attributes. 6811 * @param[in] items 6812 * Pattern specification (list terminated by the END pattern item). 6813 * @param[in] actions 6814 * Associated actions (list terminated by the END action). 6815 * @param[in] external 6816 * This flow rule is created by request external to PMD. 6817 * @param[out] error 6818 * Perform verbose error reporting if not NULL. 6819 * 6820 * @return 6821 * A flow index on success, 0 otherwise and rte_errno is set. 6822 */ 6823 static uint32_t 6824 flow_list_create(struct rte_eth_dev *dev, enum mlx5_flow_type type, 6825 const struct rte_flow_attr *attr, 6826 const struct rte_flow_item items[], 6827 const struct rte_flow_action original_actions[], 6828 bool external, struct rte_flow_error *error) 6829 { 6830 struct mlx5_priv *priv = dev->data->dev_private; 6831 struct rte_flow *flow = NULL; 6832 struct mlx5_flow *dev_flow; 6833 const struct rte_flow_action_rss *rss = NULL; 6834 struct mlx5_translated_action_handle 6835 indir_actions[MLX5_MAX_INDIRECT_ACTIONS]; 6836 int indir_actions_n = MLX5_MAX_INDIRECT_ACTIONS; 6837 union { 6838 struct mlx5_flow_expand_rss buf; 6839 uint8_t buffer[4096]; 6840 } expand_buffer; 6841 union { 6842 struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS]; 6843 uint8_t buffer[2048]; 6844 } actions_rx; 6845 union { 6846 struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS]; 6847 uint8_t buffer[2048]; 6848 } actions_hairpin_tx; 6849 union { 6850 struct rte_flow_item items[MLX5_MAX_SPLIT_ITEMS]; 6851 uint8_t buffer[2048]; 6852 } items_tx; 6853 struct mlx5_flow_expand_rss *buf = &expand_buffer.buf; 6854 struct mlx5_flow_rss_desc *rss_desc; 6855 const struct rte_flow_action *p_actions_rx; 6856 uint32_t i; 6857 uint32_t idx = 0; 6858 int hairpin_flow; 6859 struct rte_flow_attr attr_tx = { .priority = 0 }; 6860 const struct rte_flow_action *actions; 6861 struct rte_flow_action *translated_actions = NULL; 6862 struct mlx5_flow_tunnel *tunnel; 6863 struct tunnel_default_miss_ctx default_miss_ctx = { 0, }; 6864 struct mlx5_flow_workspace *wks = mlx5_flow_push_thread_workspace(); 6865 struct mlx5_flow_split_info flow_split_info = { 6866 .external = !!external, 6867 .skip_scale = 0, 6868 .flow_idx = 0, 6869 .prefix_mark = 0, 6870 .prefix_layers = 0, 6871 .table_id = 0 6872 }; 6873 int ret; 6874 6875 MLX5_ASSERT(wks); 6876 rss_desc = &wks->rss_desc; 6877 ret = flow_action_handles_translate(dev, original_actions, 6878 indir_actions, 6879 &indir_actions_n, 6880 &translated_actions, error); 6881 if (ret < 0) { 6882 MLX5_ASSERT(translated_actions == NULL); 6883 return 0; 6884 } 6885 actions = translated_actions ? translated_actions : original_actions; 6886 p_actions_rx = actions; 6887 hairpin_flow = flow_check_hairpin_split(dev, attr, actions); 6888 ret = flow_drv_validate(dev, attr, items, p_actions_rx, 6889 external, hairpin_flow, error); 6890 if (ret < 0) 6891 goto error_before_hairpin_split; 6892 flow = mlx5_ipool_zmalloc(priv->flows[type], &idx); 6893 if (!flow) { 6894 rte_errno = ENOMEM; 6895 goto error_before_hairpin_split; 6896 } 6897 if (hairpin_flow > 0) { 6898 if (hairpin_flow > MLX5_MAX_SPLIT_ACTIONS) { 6899 rte_errno = EINVAL; 6900 goto error_before_hairpin_split; 6901 } 6902 flow_hairpin_split(dev, actions, actions_rx.actions, 6903 actions_hairpin_tx.actions, items_tx.items, 6904 idx); 6905 p_actions_rx = actions_rx.actions; 6906 } 6907 flow_split_info.flow_idx = idx; 6908 flow->drv_type = flow_get_drv_type(dev, attr); 6909 MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN && 6910 flow->drv_type < MLX5_FLOW_TYPE_MAX); 6911 memset(rss_desc, 0, offsetof(struct mlx5_flow_rss_desc, queue)); 6912 /* RSS Action only works on NIC RX domain */ 6913 if (attr->ingress && !attr->transfer) 6914 rss = flow_get_rss_action(dev, p_actions_rx); 6915 if (rss) { 6916 if (flow_rss_workspace_adjust(wks, rss_desc, rss->queue_num)) 6917 return 0; 6918 /* 6919 * The following information is required by 6920 * mlx5_flow_hashfields_adjust() in advance. 6921 */ 6922 rss_desc->level = rss->level; 6923 /* RSS type 0 indicates default RSS type (RTE_ETH_RSS_IP). */ 6924 rss_desc->types = !rss->types ? RTE_ETH_RSS_IP : rss->types; 6925 } 6926 flow->dev_handles = 0; 6927 if (rss && rss->types) { 6928 unsigned int graph_root; 6929 6930 graph_root = find_graph_root(rss->level); 6931 ret = mlx5_flow_expand_rss(buf, sizeof(expand_buffer.buffer), 6932 items, rss->types, 6933 mlx5_support_expansion, graph_root); 6934 MLX5_ASSERT(ret > 0 && 6935 (unsigned int)ret < sizeof(expand_buffer.buffer)); 6936 if (rte_log_can_log(mlx5_logtype, RTE_LOG_DEBUG)) { 6937 for (i = 0; i < buf->entries; ++i) 6938 mlx5_dbg__print_pattern(buf->entry[i].pattern); 6939 } 6940 } else { 6941 buf->entries = 1; 6942 buf->entry[0].pattern = (void *)(uintptr_t)items; 6943 } 6944 rss_desc->shared_rss = flow_get_shared_rss_action(dev, indir_actions, 6945 indir_actions_n); 6946 for (i = 0; i < buf->entries; ++i) { 6947 /* Initialize flow split data. */ 6948 flow_split_info.prefix_layers = 0; 6949 flow_split_info.prefix_mark = 0; 6950 flow_split_info.skip_scale = 0; 6951 /* 6952 * The splitter may create multiple dev_flows, 6953 * depending on configuration. In the simplest 6954 * case it just creates unmodified original flow. 6955 */ 6956 ret = flow_create_split_outer(dev, flow, attr, 6957 buf->entry[i].pattern, 6958 p_actions_rx, &flow_split_info, 6959 error); 6960 if (ret < 0) 6961 goto error; 6962 if (is_flow_tunnel_steer_rule(wks->flows[0].tof_type)) { 6963 ret = flow_tunnel_add_default_miss(dev, flow, attr, 6964 p_actions_rx, 6965 idx, 6966 wks->flows[0].tunnel, 6967 &default_miss_ctx, 6968 error); 6969 if (ret < 0) { 6970 mlx5_free(default_miss_ctx.queue); 6971 goto error; 6972 } 6973 } 6974 } 6975 /* Create the tx flow. */ 6976 if (hairpin_flow) { 6977 attr_tx.group = MLX5_HAIRPIN_TX_TABLE; 6978 attr_tx.ingress = 0; 6979 attr_tx.egress = 1; 6980 dev_flow = flow_drv_prepare(dev, flow, &attr_tx, items_tx.items, 6981 actions_hairpin_tx.actions, 6982 idx, error); 6983 if (!dev_flow) 6984 goto error; 6985 dev_flow->flow = flow; 6986 dev_flow->external = 0; 6987 SILIST_INSERT(&flow->dev_handles, dev_flow->handle_idx, 6988 dev_flow->handle, next); 6989 ret = flow_drv_translate(dev, dev_flow, &attr_tx, 6990 items_tx.items, 6991 actions_hairpin_tx.actions, error); 6992 if (ret < 0) 6993 goto error; 6994 } 6995 /* 6996 * Update the metadata register copy table. If extensive 6997 * metadata feature is enabled and registers are supported 6998 * we might create the extra rte_flow for each unique 6999 * MARK/FLAG action ID. 7000 * 7001 * The table is updated for ingress Flows only, because 7002 * the egress Flows belong to the different device and 7003 * copy table should be updated in peer NIC Rx domain. 7004 */ 7005 if (attr->ingress && 7006 (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) { 7007 ret = flow_mreg_update_copy_table(dev, flow, actions, error); 7008 if (ret) 7009 goto error; 7010 } 7011 /* 7012 * If the flow is external (from application) OR device is started, 7013 * OR mreg discover, then apply immediately. 7014 */ 7015 if (external || dev->data->dev_started || 7016 (attr->group == MLX5_FLOW_MREG_CP_TABLE_GROUP && 7017 attr->priority == MLX5_FLOW_LOWEST_PRIO_INDICATOR)) { 7018 ret = flow_drv_apply(dev, flow, error); 7019 if (ret < 0) 7020 goto error; 7021 } 7022 flow->type = type; 7023 flow_rxq_flags_set(dev, flow); 7024 rte_free(translated_actions); 7025 tunnel = flow_tunnel_from_rule(wks->flows); 7026 if (tunnel) { 7027 flow->tunnel = 1; 7028 flow->tunnel_id = tunnel->tunnel_id; 7029 __atomic_add_fetch(&tunnel->refctn, 1, __ATOMIC_RELAXED); 7030 mlx5_free(default_miss_ctx.queue); 7031 } 7032 mlx5_flow_pop_thread_workspace(); 7033 return idx; 7034 error: 7035 MLX5_ASSERT(flow); 7036 ret = rte_errno; /* Save rte_errno before cleanup. */ 7037 flow_mreg_del_copy_action(dev, flow); 7038 flow_drv_destroy(dev, flow); 7039 if (rss_desc->shared_rss) 7040 __atomic_sub_fetch(&((struct mlx5_shared_action_rss *) 7041 mlx5_ipool_get 7042 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 7043 rss_desc->shared_rss))->refcnt, 1, __ATOMIC_RELAXED); 7044 mlx5_ipool_free(priv->flows[type], idx); 7045 rte_errno = ret; /* Restore rte_errno. */ 7046 ret = rte_errno; 7047 rte_errno = ret; 7048 error_before_hairpin_split: 7049 mlx5_flow_pop_thread_workspace(); 7050 rte_free(translated_actions); 7051 return 0; 7052 } 7053 7054 /** 7055 * Create a dedicated flow rule on e-switch table 0 (root table), to direct all 7056 * incoming packets to table 1. 7057 * 7058 * Other flow rules, requested for group n, will be created in 7059 * e-switch table n+1. 7060 * Jump action to e-switch group n will be created to group n+1. 7061 * 7062 * Used when working in switchdev mode, to utilise advantages of table 1 7063 * and above. 7064 * 7065 * @param dev 7066 * Pointer to Ethernet device. 7067 * 7068 * @return 7069 * Pointer to flow on success, NULL otherwise and rte_errno is set. 7070 */ 7071 struct rte_flow * 7072 mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev) 7073 { 7074 const struct rte_flow_attr attr = { 7075 .group = 0, 7076 .priority = 0, 7077 .ingress = 1, 7078 .egress = 0, 7079 .transfer = 1, 7080 }; 7081 const struct rte_flow_item pattern = { 7082 .type = RTE_FLOW_ITEM_TYPE_END, 7083 }; 7084 struct rte_flow_action_jump jump = { 7085 .group = 1, 7086 }; 7087 const struct rte_flow_action actions[] = { 7088 { 7089 .type = RTE_FLOW_ACTION_TYPE_JUMP, 7090 .conf = &jump, 7091 }, 7092 { 7093 .type = RTE_FLOW_ACTION_TYPE_END, 7094 }, 7095 }; 7096 struct rte_flow_error error; 7097 7098 return (void *)(uintptr_t)flow_list_create(dev, MLX5_FLOW_TYPE_CTL, 7099 &attr, &pattern, 7100 actions, false, &error); 7101 } 7102 7103 /** 7104 * Create a dedicated flow rule on e-switch table 1, matches ESW manager 7105 * and sq number, directs all packets to peer vport. 7106 * 7107 * @param dev 7108 * Pointer to Ethernet device. 7109 * @param txq 7110 * Txq index. 7111 * 7112 * @return 7113 * Flow ID on success, 0 otherwise and rte_errno is set. 7114 */ 7115 uint32_t 7116 mlx5_flow_create_devx_sq_miss_flow(struct rte_eth_dev *dev, uint32_t txq) 7117 { 7118 struct rte_flow_attr attr = { 7119 .group = 0, 7120 .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR, 7121 .ingress = 1, 7122 .egress = 0, 7123 .transfer = 1, 7124 }; 7125 struct rte_flow_item_port_id port_spec = { 7126 .id = MLX5_PORT_ESW_MGR, 7127 }; 7128 struct mlx5_rte_flow_item_sq txq_spec = { 7129 .queue = txq, 7130 }; 7131 struct rte_flow_item pattern[] = { 7132 { 7133 .type = RTE_FLOW_ITEM_TYPE_PORT_ID, 7134 .spec = &port_spec, 7135 }, 7136 { 7137 .type = (enum rte_flow_item_type) 7138 MLX5_RTE_FLOW_ITEM_TYPE_SQ, 7139 .spec = &txq_spec, 7140 }, 7141 { 7142 .type = RTE_FLOW_ITEM_TYPE_END, 7143 }, 7144 }; 7145 struct rte_flow_action_jump jump = { 7146 .group = 1, 7147 }; 7148 struct rte_flow_action_port_id port = { 7149 .id = dev->data->port_id, 7150 }; 7151 struct rte_flow_action actions[] = { 7152 { 7153 .type = RTE_FLOW_ACTION_TYPE_JUMP, 7154 .conf = &jump, 7155 }, 7156 { 7157 .type = RTE_FLOW_ACTION_TYPE_END, 7158 }, 7159 }; 7160 struct rte_flow_error error; 7161 7162 /* 7163 * Creates group 0, highest priority jump flow. 7164 * Matches txq to bypass kernel packets. 7165 */ 7166 if (flow_list_create(dev, MLX5_FLOW_TYPE_CTL, &attr, pattern, actions, 7167 false, &error) == 0) 7168 return 0; 7169 /* Create group 1, lowest priority redirect flow for txq. */ 7170 attr.group = 1; 7171 actions[0].conf = &port; 7172 actions[0].type = RTE_FLOW_ACTION_TYPE_PORT_ID; 7173 return flow_list_create(dev, MLX5_FLOW_TYPE_CTL, &attr, pattern, 7174 actions, false, &error); 7175 } 7176 7177 /** 7178 * Validate a flow supported by the NIC. 7179 * 7180 * @see rte_flow_validate() 7181 * @see rte_flow_ops 7182 */ 7183 int 7184 mlx5_flow_validate(struct rte_eth_dev *dev, 7185 const struct rte_flow_attr *attr, 7186 const struct rte_flow_item items[], 7187 const struct rte_flow_action original_actions[], 7188 struct rte_flow_error *error) 7189 { 7190 int hairpin_flow; 7191 struct mlx5_translated_action_handle 7192 indir_actions[MLX5_MAX_INDIRECT_ACTIONS]; 7193 int indir_actions_n = MLX5_MAX_INDIRECT_ACTIONS; 7194 const struct rte_flow_action *actions; 7195 struct rte_flow_action *translated_actions = NULL; 7196 int ret = flow_action_handles_translate(dev, original_actions, 7197 indir_actions, 7198 &indir_actions_n, 7199 &translated_actions, error); 7200 7201 if (ret) 7202 return ret; 7203 actions = translated_actions ? translated_actions : original_actions; 7204 hairpin_flow = flow_check_hairpin_split(dev, attr, actions); 7205 ret = flow_drv_validate(dev, attr, items, actions, 7206 true, hairpin_flow, error); 7207 rte_free(translated_actions); 7208 return ret; 7209 } 7210 7211 /** 7212 * Create a flow. 7213 * 7214 * @see rte_flow_create() 7215 * @see rte_flow_ops 7216 */ 7217 struct rte_flow * 7218 mlx5_flow_create(struct rte_eth_dev *dev, 7219 const struct rte_flow_attr *attr, 7220 const struct rte_flow_item items[], 7221 const struct rte_flow_action actions[], 7222 struct rte_flow_error *error) 7223 { 7224 struct mlx5_priv *priv = dev->data->dev_private; 7225 7226 if (priv->sh->config.dv_flow_en == 2) { 7227 rte_flow_error_set(error, ENOTSUP, 7228 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 7229 NULL, 7230 "Flow non-Q creation not supported"); 7231 return NULL; 7232 } 7233 /* 7234 * If the device is not started yet, it is not allowed to created a 7235 * flow from application. PMD default flows and traffic control flows 7236 * are not affected. 7237 */ 7238 if (unlikely(!dev->data->dev_started)) { 7239 DRV_LOG(DEBUG, "port %u is not started when " 7240 "inserting a flow", dev->data->port_id); 7241 rte_flow_error_set(error, ENODEV, 7242 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 7243 NULL, 7244 "port not started"); 7245 return NULL; 7246 } 7247 7248 return (void *)(uintptr_t)flow_list_create(dev, MLX5_FLOW_TYPE_GEN, 7249 attr, items, actions, 7250 true, error); 7251 } 7252 7253 /** 7254 * Destroy a flow in a list. 7255 * 7256 * @param dev 7257 * Pointer to Ethernet device. 7258 * @param[in] flow_idx 7259 * Index of flow to destroy. 7260 */ 7261 static void 7262 flow_list_destroy(struct rte_eth_dev *dev, enum mlx5_flow_type type, 7263 uint32_t flow_idx) 7264 { 7265 struct mlx5_priv *priv = dev->data->dev_private; 7266 struct rte_flow *flow = mlx5_ipool_get(priv->flows[type], flow_idx); 7267 7268 if (!flow) 7269 return; 7270 MLX5_ASSERT(flow->type == type); 7271 /* 7272 * Update RX queue flags only if port is started, otherwise it is 7273 * already clean. 7274 */ 7275 if (dev->data->dev_started) 7276 flow_rxq_flags_trim(dev, flow); 7277 flow_drv_destroy(dev, flow); 7278 if (flow->tunnel) { 7279 struct mlx5_flow_tunnel *tunnel; 7280 7281 tunnel = mlx5_find_tunnel_id(dev, flow->tunnel_id); 7282 RTE_VERIFY(tunnel); 7283 if (!__atomic_sub_fetch(&tunnel->refctn, 1, __ATOMIC_RELAXED)) 7284 mlx5_flow_tunnel_free(dev, tunnel); 7285 } 7286 flow_mreg_del_copy_action(dev, flow); 7287 mlx5_ipool_free(priv->flows[type], flow_idx); 7288 } 7289 7290 /** 7291 * Destroy all flows. 7292 * 7293 * @param dev 7294 * Pointer to Ethernet device. 7295 * @param type 7296 * Flow type to be flushed. 7297 * @param active 7298 * If flushing is called actively. 7299 */ 7300 void 7301 mlx5_flow_list_flush(struct rte_eth_dev *dev, enum mlx5_flow_type type, 7302 bool active) 7303 { 7304 struct mlx5_priv *priv = dev->data->dev_private; 7305 uint32_t num_flushed = 0, fidx = 1; 7306 struct rte_flow *flow; 7307 7308 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 7309 if (priv->sh->config.dv_flow_en == 2 && 7310 type == MLX5_FLOW_TYPE_GEN) { 7311 flow_hw_q_flow_flush(dev, NULL); 7312 return; 7313 } 7314 #endif 7315 7316 MLX5_IPOOL_FOREACH(priv->flows[type], fidx, flow) { 7317 flow_list_destroy(dev, type, fidx); 7318 num_flushed++; 7319 } 7320 if (active) { 7321 DRV_LOG(INFO, "port %u: %u flows flushed before stopping", 7322 dev->data->port_id, num_flushed); 7323 } 7324 } 7325 7326 /** 7327 * Stop all default actions for flows. 7328 * 7329 * @param dev 7330 * Pointer to Ethernet device. 7331 */ 7332 void 7333 mlx5_flow_stop_default(struct rte_eth_dev *dev) 7334 { 7335 flow_mreg_del_default_copy_action(dev); 7336 flow_rxq_flags_clear(dev); 7337 } 7338 7339 /** 7340 * Start all default actions for flows. 7341 * 7342 * @param dev 7343 * Pointer to Ethernet device. 7344 * @return 7345 * 0 on success, a negative errno value otherwise and rte_errno is set. 7346 */ 7347 int 7348 mlx5_flow_start_default(struct rte_eth_dev *dev) 7349 { 7350 struct rte_flow_error error; 7351 7352 /* Make sure default copy action (reg_c[0] -> reg_b) is created. */ 7353 return flow_mreg_add_default_copy_action(dev, &error); 7354 } 7355 7356 /** 7357 * Release key of thread specific flow workspace data. 7358 */ 7359 void 7360 flow_release_workspace(void *data) 7361 { 7362 struct mlx5_flow_workspace *wks = data; 7363 struct mlx5_flow_workspace *next; 7364 7365 while (wks) { 7366 next = wks->next; 7367 free(wks->rss_desc.queue); 7368 free(wks); 7369 wks = next; 7370 } 7371 } 7372 7373 /** 7374 * Get thread specific current flow workspace. 7375 * 7376 * @return pointer to thread specific flow workspace data, NULL on error. 7377 */ 7378 struct mlx5_flow_workspace* 7379 mlx5_flow_get_thread_workspace(void) 7380 { 7381 struct mlx5_flow_workspace *data; 7382 7383 data = mlx5_flow_os_get_specific_workspace(); 7384 MLX5_ASSERT(data && data->inuse); 7385 if (!data || !data->inuse) 7386 DRV_LOG(ERR, "flow workspace not initialized."); 7387 return data; 7388 } 7389 7390 /** 7391 * Allocate and init new flow workspace. 7392 * 7393 * @return pointer to flow workspace data, NULL on error. 7394 */ 7395 static struct mlx5_flow_workspace* 7396 flow_alloc_thread_workspace(void) 7397 { 7398 struct mlx5_flow_workspace *data = calloc(1, sizeof(*data)); 7399 7400 if (!data) { 7401 DRV_LOG(ERR, "Failed to allocate flow workspace " 7402 "memory."); 7403 return NULL; 7404 } 7405 data->rss_desc.queue = calloc(1, 7406 sizeof(uint16_t) * MLX5_RSSQ_DEFAULT_NUM); 7407 if (!data->rss_desc.queue) 7408 goto err; 7409 data->rssq_num = MLX5_RSSQ_DEFAULT_NUM; 7410 return data; 7411 err: 7412 free(data->rss_desc.queue); 7413 free(data); 7414 return NULL; 7415 } 7416 7417 /** 7418 * Get new thread specific flow workspace. 7419 * 7420 * If current workspace inuse, create new one and set as current. 7421 * 7422 * @return pointer to thread specific flow workspace data, NULL on error. 7423 */ 7424 struct mlx5_flow_workspace* 7425 mlx5_flow_push_thread_workspace(void) 7426 { 7427 struct mlx5_flow_workspace *curr; 7428 struct mlx5_flow_workspace *data; 7429 7430 curr = mlx5_flow_os_get_specific_workspace(); 7431 if (!curr) { 7432 data = flow_alloc_thread_workspace(); 7433 if (!data) 7434 return NULL; 7435 } else if (!curr->inuse) { 7436 data = curr; 7437 } else if (curr->next) { 7438 data = curr->next; 7439 } else { 7440 data = flow_alloc_thread_workspace(); 7441 if (!data) 7442 return NULL; 7443 curr->next = data; 7444 data->prev = curr; 7445 } 7446 data->inuse = 1; 7447 data->flow_idx = 0; 7448 /* Set as current workspace */ 7449 if (mlx5_flow_os_set_specific_workspace(data)) 7450 DRV_LOG(ERR, "Failed to set flow workspace to thread."); 7451 return data; 7452 } 7453 7454 /** 7455 * Close current thread specific flow workspace. 7456 * 7457 * If previous workspace available, set it as current. 7458 * 7459 * @return pointer to thread specific flow workspace data, NULL on error. 7460 */ 7461 void 7462 mlx5_flow_pop_thread_workspace(void) 7463 { 7464 struct mlx5_flow_workspace *data = mlx5_flow_get_thread_workspace(); 7465 7466 if (!data) 7467 return; 7468 if (!data->inuse) { 7469 DRV_LOG(ERR, "Failed to close unused flow workspace."); 7470 return; 7471 } 7472 data->inuse = 0; 7473 if (!data->prev) 7474 return; 7475 if (mlx5_flow_os_set_specific_workspace(data->prev)) 7476 DRV_LOG(ERR, "Failed to set flow workspace to thread."); 7477 } 7478 7479 /** 7480 * Verify the flow list is empty 7481 * 7482 * @param dev 7483 * Pointer to Ethernet device. 7484 * 7485 * @return the number of flows not released. 7486 */ 7487 int 7488 mlx5_flow_verify(struct rte_eth_dev *dev __rte_unused) 7489 { 7490 struct mlx5_priv *priv = dev->data->dev_private; 7491 struct rte_flow *flow; 7492 uint32_t idx = 0; 7493 int ret = 0, i; 7494 7495 for (i = 0; i < MLX5_FLOW_TYPE_MAXI; i++) { 7496 MLX5_IPOOL_FOREACH(priv->flows[i], idx, flow) { 7497 DRV_LOG(DEBUG, "port %u flow %p still referenced", 7498 dev->data->port_id, (void *)flow); 7499 ret++; 7500 } 7501 } 7502 return ret; 7503 } 7504 7505 /** 7506 * Enable default hairpin egress flow. 7507 * 7508 * @param dev 7509 * Pointer to Ethernet device. 7510 * @param queue 7511 * The queue index. 7512 * 7513 * @return 7514 * 0 on success, a negative errno value otherwise and rte_errno is set. 7515 */ 7516 int 7517 mlx5_ctrl_flow_source_queue(struct rte_eth_dev *dev, 7518 uint32_t queue) 7519 { 7520 const struct rte_flow_attr attr = { 7521 .egress = 1, 7522 .priority = 0, 7523 }; 7524 struct mlx5_rte_flow_item_sq queue_spec = { 7525 .queue = queue, 7526 }; 7527 struct mlx5_rte_flow_item_sq queue_mask = { 7528 .queue = UINT32_MAX, 7529 }; 7530 struct rte_flow_item items[] = { 7531 { 7532 .type = (enum rte_flow_item_type) 7533 MLX5_RTE_FLOW_ITEM_TYPE_SQ, 7534 .spec = &queue_spec, 7535 .last = NULL, 7536 .mask = &queue_mask, 7537 }, 7538 { 7539 .type = RTE_FLOW_ITEM_TYPE_END, 7540 }, 7541 }; 7542 struct rte_flow_action_jump jump = { 7543 .group = MLX5_HAIRPIN_TX_TABLE, 7544 }; 7545 struct rte_flow_action actions[2]; 7546 uint32_t flow_idx; 7547 struct rte_flow_error error; 7548 7549 actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; 7550 actions[0].conf = &jump; 7551 actions[1].type = RTE_FLOW_ACTION_TYPE_END; 7552 flow_idx = flow_list_create(dev, MLX5_FLOW_TYPE_CTL, 7553 &attr, items, actions, false, &error); 7554 if (!flow_idx) { 7555 DRV_LOG(DEBUG, 7556 "Failed to create ctrl flow: rte_errno(%d)," 7557 " type(%d), message(%s)", 7558 rte_errno, error.type, 7559 error.message ? error.message : " (no stated reason)"); 7560 return -rte_errno; 7561 } 7562 return 0; 7563 } 7564 7565 /** 7566 * Enable a control flow configured from the control plane. 7567 * 7568 * @param dev 7569 * Pointer to Ethernet device. 7570 * @param eth_spec 7571 * An Ethernet flow spec to apply. 7572 * @param eth_mask 7573 * An Ethernet flow mask to apply. 7574 * @param vlan_spec 7575 * A VLAN flow spec to apply. 7576 * @param vlan_mask 7577 * A VLAN flow mask to apply. 7578 * 7579 * @return 7580 * 0 on success, a negative errno value otherwise and rte_errno is set. 7581 */ 7582 int 7583 mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev, 7584 struct rte_flow_item_eth *eth_spec, 7585 struct rte_flow_item_eth *eth_mask, 7586 struct rte_flow_item_vlan *vlan_spec, 7587 struct rte_flow_item_vlan *vlan_mask) 7588 { 7589 struct mlx5_priv *priv = dev->data->dev_private; 7590 const struct rte_flow_attr attr = { 7591 .ingress = 1, 7592 .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR, 7593 }; 7594 struct rte_flow_item items[] = { 7595 { 7596 .type = RTE_FLOW_ITEM_TYPE_ETH, 7597 .spec = eth_spec, 7598 .last = NULL, 7599 .mask = eth_mask, 7600 }, 7601 { 7602 .type = (vlan_spec) ? RTE_FLOW_ITEM_TYPE_VLAN : 7603 RTE_FLOW_ITEM_TYPE_END, 7604 .spec = vlan_spec, 7605 .last = NULL, 7606 .mask = vlan_mask, 7607 }, 7608 { 7609 .type = RTE_FLOW_ITEM_TYPE_END, 7610 }, 7611 }; 7612 uint16_t queue[priv->reta_idx_n]; 7613 struct rte_flow_action_rss action_rss = { 7614 .func = RTE_ETH_HASH_FUNCTION_DEFAULT, 7615 .level = 0, 7616 .types = priv->rss_conf.rss_hf, 7617 .key_len = priv->rss_conf.rss_key_len, 7618 .queue_num = priv->reta_idx_n, 7619 .key = priv->rss_conf.rss_key, 7620 .queue = queue, 7621 }; 7622 struct rte_flow_action actions[] = { 7623 { 7624 .type = RTE_FLOW_ACTION_TYPE_RSS, 7625 .conf = &action_rss, 7626 }, 7627 { 7628 .type = RTE_FLOW_ACTION_TYPE_END, 7629 }, 7630 }; 7631 uint32_t flow_idx; 7632 struct rte_flow_error error; 7633 unsigned int i; 7634 7635 if (!priv->reta_idx_n || !priv->rxqs_n) { 7636 return 0; 7637 } 7638 if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)) 7639 action_rss.types = 0; 7640 for (i = 0; i != priv->reta_idx_n; ++i) 7641 queue[i] = (*priv->reta_idx)[i]; 7642 flow_idx = flow_list_create(dev, MLX5_FLOW_TYPE_CTL, 7643 &attr, items, actions, false, &error); 7644 if (!flow_idx) 7645 return -rte_errno; 7646 return 0; 7647 } 7648 7649 /** 7650 * Enable a flow control configured from the control plane. 7651 * 7652 * @param dev 7653 * Pointer to Ethernet device. 7654 * @param eth_spec 7655 * An Ethernet flow spec to apply. 7656 * @param eth_mask 7657 * An Ethernet flow mask to apply. 7658 * 7659 * @return 7660 * 0 on success, a negative errno value otherwise and rte_errno is set. 7661 */ 7662 int 7663 mlx5_ctrl_flow(struct rte_eth_dev *dev, 7664 struct rte_flow_item_eth *eth_spec, 7665 struct rte_flow_item_eth *eth_mask) 7666 { 7667 return mlx5_ctrl_flow_vlan(dev, eth_spec, eth_mask, NULL, NULL); 7668 } 7669 7670 /** 7671 * Create default miss flow rule matching lacp traffic 7672 * 7673 * @param dev 7674 * Pointer to Ethernet device. 7675 * @param eth_spec 7676 * An Ethernet flow spec to apply. 7677 * 7678 * @return 7679 * 0 on success, a negative errno value otherwise and rte_errno is set. 7680 */ 7681 int 7682 mlx5_flow_lacp_miss(struct rte_eth_dev *dev) 7683 { 7684 /* 7685 * The LACP matching is done by only using ether type since using 7686 * a multicast dst mac causes kernel to give low priority to this flow. 7687 */ 7688 static const struct rte_flow_item_eth lacp_spec = { 7689 .type = RTE_BE16(0x8809), 7690 }; 7691 static const struct rte_flow_item_eth lacp_mask = { 7692 .type = 0xffff, 7693 }; 7694 const struct rte_flow_attr attr = { 7695 .ingress = 1, 7696 }; 7697 struct rte_flow_item items[] = { 7698 { 7699 .type = RTE_FLOW_ITEM_TYPE_ETH, 7700 .spec = &lacp_spec, 7701 .mask = &lacp_mask, 7702 }, 7703 { 7704 .type = RTE_FLOW_ITEM_TYPE_END, 7705 }, 7706 }; 7707 struct rte_flow_action actions[] = { 7708 { 7709 .type = (enum rte_flow_action_type) 7710 MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS, 7711 }, 7712 { 7713 .type = RTE_FLOW_ACTION_TYPE_END, 7714 }, 7715 }; 7716 struct rte_flow_error error; 7717 uint32_t flow_idx = flow_list_create(dev, MLX5_FLOW_TYPE_CTL, 7718 &attr, items, actions, 7719 false, &error); 7720 7721 if (!flow_idx) 7722 return -rte_errno; 7723 return 0; 7724 } 7725 7726 /** 7727 * Destroy a flow. 7728 * 7729 * @see rte_flow_destroy() 7730 * @see rte_flow_ops 7731 */ 7732 int 7733 mlx5_flow_destroy(struct rte_eth_dev *dev, 7734 struct rte_flow *flow, 7735 struct rte_flow_error *error __rte_unused) 7736 { 7737 struct mlx5_priv *priv = dev->data->dev_private; 7738 7739 if (priv->sh->config.dv_flow_en == 2) 7740 return rte_flow_error_set(error, ENOTSUP, 7741 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 7742 NULL, 7743 "Flow non-Q destruction not supported"); 7744 flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN, 7745 (uintptr_t)(void *)flow); 7746 return 0; 7747 } 7748 7749 /** 7750 * Destroy all flows. 7751 * 7752 * @see rte_flow_flush() 7753 * @see rte_flow_ops 7754 */ 7755 int 7756 mlx5_flow_flush(struct rte_eth_dev *dev, 7757 struct rte_flow_error *error __rte_unused) 7758 { 7759 mlx5_flow_list_flush(dev, MLX5_FLOW_TYPE_GEN, false); 7760 return 0; 7761 } 7762 7763 /** 7764 * Isolated mode. 7765 * 7766 * @see rte_flow_isolate() 7767 * @see rte_flow_ops 7768 */ 7769 int 7770 mlx5_flow_isolate(struct rte_eth_dev *dev, 7771 int enable, 7772 struct rte_flow_error *error) 7773 { 7774 struct mlx5_priv *priv = dev->data->dev_private; 7775 7776 if (dev->data->dev_started) { 7777 rte_flow_error_set(error, EBUSY, 7778 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 7779 NULL, 7780 "port must be stopped first"); 7781 return -rte_errno; 7782 } 7783 priv->isolated = !!enable; 7784 if (enable) 7785 dev->dev_ops = &mlx5_dev_ops_isolate; 7786 else 7787 dev->dev_ops = &mlx5_dev_ops; 7788 7789 dev->rx_descriptor_status = mlx5_rx_descriptor_status; 7790 dev->tx_descriptor_status = mlx5_tx_descriptor_status; 7791 7792 return 0; 7793 } 7794 7795 /** 7796 * Query a flow. 7797 * 7798 * @see rte_flow_query() 7799 * @see rte_flow_ops 7800 */ 7801 static int 7802 flow_drv_query(struct rte_eth_dev *dev, 7803 uint32_t flow_idx, 7804 const struct rte_flow_action *actions, 7805 void *data, 7806 struct rte_flow_error *error) 7807 { 7808 struct mlx5_priv *priv = dev->data->dev_private; 7809 const struct mlx5_flow_driver_ops *fops; 7810 struct rte_flow *flow = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN], 7811 flow_idx); 7812 enum mlx5_flow_drv_type ftype; 7813 7814 if (!flow) { 7815 return rte_flow_error_set(error, ENOENT, 7816 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 7817 NULL, 7818 "invalid flow handle"); 7819 } 7820 ftype = flow->drv_type; 7821 MLX5_ASSERT(ftype > MLX5_FLOW_TYPE_MIN && ftype < MLX5_FLOW_TYPE_MAX); 7822 fops = flow_get_drv_ops(ftype); 7823 7824 return fops->query(dev, flow, actions, data, error); 7825 } 7826 7827 /** 7828 * Query a flow. 7829 * 7830 * @see rte_flow_query() 7831 * @see rte_flow_ops 7832 */ 7833 int 7834 mlx5_flow_query(struct rte_eth_dev *dev, 7835 struct rte_flow *flow, 7836 const struct rte_flow_action *actions, 7837 void *data, 7838 struct rte_flow_error *error) 7839 { 7840 int ret; 7841 struct mlx5_priv *priv = dev->data->dev_private; 7842 7843 if (priv->sh->config.dv_flow_en == 2) 7844 return rte_flow_error_set(error, ENOTSUP, 7845 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 7846 NULL, 7847 "Flow non-Q query not supported"); 7848 ret = flow_drv_query(dev, (uintptr_t)(void *)flow, actions, data, 7849 error); 7850 if (ret < 0) 7851 return ret; 7852 return 0; 7853 } 7854 7855 /** 7856 * Get rte_flow callbacks. 7857 * 7858 * @param dev 7859 * Pointer to Ethernet device structure. 7860 * @param ops 7861 * Pointer to operation-specific structure. 7862 * 7863 * @return 0 7864 */ 7865 int 7866 mlx5_flow_ops_get(struct rte_eth_dev *dev __rte_unused, 7867 const struct rte_flow_ops **ops) 7868 { 7869 *ops = &mlx5_flow_ops; 7870 return 0; 7871 } 7872 7873 /** 7874 * Validate meter policy actions. 7875 * Dispatcher for action type specific validation. 7876 * 7877 * @param[in] dev 7878 * Pointer to the Ethernet device structure. 7879 * @param[in] action 7880 * The meter policy action object to validate. 7881 * @param[in] attr 7882 * Attributes of flow to determine steering domain. 7883 * @param[out] is_rss 7884 * Is RSS or not. 7885 * @param[out] domain_bitmap 7886 * Domain bitmap. 7887 * @param[out] is_def_policy 7888 * Is default policy or not. 7889 * @param[out] error 7890 * Perform verbose error reporting if not NULL. Initialized in case of 7891 * error only. 7892 * 7893 * @return 7894 * 0 on success, otherwise negative errno value. 7895 */ 7896 int 7897 mlx5_flow_validate_mtr_acts(struct rte_eth_dev *dev, 7898 const struct rte_flow_action *actions[RTE_COLORS], 7899 struct rte_flow_attr *attr, 7900 bool *is_rss, 7901 uint8_t *domain_bitmap, 7902 uint8_t *policy_mode, 7903 struct rte_mtr_error *error) 7904 { 7905 const struct mlx5_flow_driver_ops *fops; 7906 7907 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 7908 return fops->validate_mtr_acts(dev, actions, attr, is_rss, 7909 domain_bitmap, policy_mode, error); 7910 } 7911 7912 /** 7913 * Destroy the meter table set. 7914 * 7915 * @param[in] dev 7916 * Pointer to Ethernet device. 7917 * @param[in] mtr_policy 7918 * Meter policy struct. 7919 */ 7920 void 7921 mlx5_flow_destroy_mtr_acts(struct rte_eth_dev *dev, 7922 struct mlx5_flow_meter_policy *mtr_policy) 7923 { 7924 const struct mlx5_flow_driver_ops *fops; 7925 7926 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 7927 fops->destroy_mtr_acts(dev, mtr_policy); 7928 } 7929 7930 /** 7931 * Create policy action, lock free, 7932 * (mutex should be acquired by caller). 7933 * Dispatcher for action type specific call. 7934 * 7935 * @param[in] dev 7936 * Pointer to the Ethernet device structure. 7937 * @param[in] mtr_policy 7938 * Meter policy struct. 7939 * @param[in] action 7940 * Action specification used to create meter actions. 7941 * @param[in] attr 7942 * Flow rule attributes. 7943 * @param[out] error 7944 * Perform verbose error reporting if not NULL. Initialized in case of 7945 * error only. 7946 * 7947 * @return 7948 * 0 on success, otherwise negative errno value. 7949 */ 7950 int 7951 mlx5_flow_create_mtr_acts(struct rte_eth_dev *dev, 7952 struct mlx5_flow_meter_policy *mtr_policy, 7953 const struct rte_flow_action *actions[RTE_COLORS], 7954 struct rte_flow_attr *attr, 7955 struct rte_mtr_error *error) 7956 { 7957 const struct mlx5_flow_driver_ops *fops; 7958 7959 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 7960 return fops->create_mtr_acts(dev, mtr_policy, actions, attr, error); 7961 } 7962 7963 /** 7964 * Create policy rules, lock free, 7965 * (mutex should be acquired by caller). 7966 * Dispatcher for action type specific call. 7967 * 7968 * @param[in] dev 7969 * Pointer to the Ethernet device structure. 7970 * @param[in] mtr_policy 7971 * Meter policy struct. 7972 * 7973 * @return 7974 * 0 on success, -1 otherwise. 7975 */ 7976 int 7977 mlx5_flow_create_policy_rules(struct rte_eth_dev *dev, 7978 struct mlx5_flow_meter_policy *mtr_policy) 7979 { 7980 const struct mlx5_flow_driver_ops *fops; 7981 7982 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 7983 return fops->create_policy_rules(dev, mtr_policy); 7984 } 7985 7986 /** 7987 * Destroy policy rules, lock free, 7988 * (mutex should be acquired by caller). 7989 * Dispatcher for action type specific call. 7990 * 7991 * @param[in] dev 7992 * Pointer to the Ethernet device structure. 7993 * @param[in] mtr_policy 7994 * Meter policy struct. 7995 */ 7996 void 7997 mlx5_flow_destroy_policy_rules(struct rte_eth_dev *dev, 7998 struct mlx5_flow_meter_policy *mtr_policy) 7999 { 8000 const struct mlx5_flow_driver_ops *fops; 8001 8002 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8003 fops->destroy_policy_rules(dev, mtr_policy); 8004 } 8005 8006 /** 8007 * Destroy the default policy table set. 8008 * 8009 * @param[in] dev 8010 * Pointer to Ethernet device. 8011 */ 8012 void 8013 mlx5_flow_destroy_def_policy(struct rte_eth_dev *dev) 8014 { 8015 const struct mlx5_flow_driver_ops *fops; 8016 8017 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8018 fops->destroy_def_policy(dev); 8019 } 8020 8021 /** 8022 * Destroy the default policy table set. 8023 * 8024 * @param[in] dev 8025 * Pointer to Ethernet device. 8026 * 8027 * @return 8028 * 0 on success, -1 otherwise. 8029 */ 8030 int 8031 mlx5_flow_create_def_policy(struct rte_eth_dev *dev) 8032 { 8033 const struct mlx5_flow_driver_ops *fops; 8034 8035 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8036 return fops->create_def_policy(dev); 8037 } 8038 8039 /** 8040 * Create the needed meter and suffix tables. 8041 * 8042 * @param[in] dev 8043 * Pointer to Ethernet device. 8044 * 8045 * @return 8046 * 0 on success, -1 otherwise. 8047 */ 8048 int 8049 mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev, 8050 struct mlx5_flow_meter_info *fm, 8051 uint32_t mtr_idx, 8052 uint8_t domain_bitmap) 8053 { 8054 const struct mlx5_flow_driver_ops *fops; 8055 8056 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8057 return fops->create_mtr_tbls(dev, fm, mtr_idx, domain_bitmap); 8058 } 8059 8060 /** 8061 * Destroy the meter table set. 8062 * 8063 * @param[in] dev 8064 * Pointer to Ethernet device. 8065 * @param[in] tbl 8066 * Pointer to the meter table set. 8067 */ 8068 void 8069 mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev, 8070 struct mlx5_flow_meter_info *fm) 8071 { 8072 const struct mlx5_flow_driver_ops *fops; 8073 8074 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8075 fops->destroy_mtr_tbls(dev, fm); 8076 } 8077 8078 /** 8079 * Destroy the global meter drop table. 8080 * 8081 * @param[in] dev 8082 * Pointer to Ethernet device. 8083 */ 8084 void 8085 mlx5_flow_destroy_mtr_drop_tbls(struct rte_eth_dev *dev) 8086 { 8087 const struct mlx5_flow_driver_ops *fops; 8088 8089 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8090 fops->destroy_mtr_drop_tbls(dev); 8091 } 8092 8093 /** 8094 * Destroy the sub policy table with RX queue. 8095 * 8096 * @param[in] dev 8097 * Pointer to Ethernet device. 8098 * @param[in] mtr_policy 8099 * Pointer to meter policy table. 8100 */ 8101 void 8102 mlx5_flow_destroy_sub_policy_with_rxq(struct rte_eth_dev *dev, 8103 struct mlx5_flow_meter_policy *mtr_policy) 8104 { 8105 const struct mlx5_flow_driver_ops *fops; 8106 8107 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8108 fops->destroy_sub_policy_with_rxq(dev, mtr_policy); 8109 } 8110 8111 /** 8112 * Allocate the needed aso flow meter id. 8113 * 8114 * @param[in] dev 8115 * Pointer to Ethernet device. 8116 * 8117 * @return 8118 * Index to aso flow meter on success, NULL otherwise. 8119 */ 8120 uint32_t 8121 mlx5_flow_mtr_alloc(struct rte_eth_dev *dev) 8122 { 8123 const struct mlx5_flow_driver_ops *fops; 8124 8125 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8126 return fops->create_meter(dev); 8127 } 8128 8129 /** 8130 * Free the aso flow meter id. 8131 * 8132 * @param[in] dev 8133 * Pointer to Ethernet device. 8134 * @param[in] mtr_idx 8135 * Index to aso flow meter to be free. 8136 * 8137 * @return 8138 * 0 on success. 8139 */ 8140 void 8141 mlx5_flow_mtr_free(struct rte_eth_dev *dev, uint32_t mtr_idx) 8142 { 8143 const struct mlx5_flow_driver_ops *fops; 8144 8145 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8146 fops->free_meter(dev, mtr_idx); 8147 } 8148 8149 /** 8150 * Allocate a counter. 8151 * 8152 * @param[in] dev 8153 * Pointer to Ethernet device structure. 8154 * 8155 * @return 8156 * Index to allocated counter on success, 0 otherwise. 8157 */ 8158 uint32_t 8159 mlx5_counter_alloc(struct rte_eth_dev *dev) 8160 { 8161 const struct mlx5_flow_driver_ops *fops; 8162 struct rte_flow_attr attr = { .transfer = 0 }; 8163 8164 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 8165 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8166 return fops->counter_alloc(dev); 8167 } 8168 DRV_LOG(ERR, 8169 "port %u counter allocate is not supported.", 8170 dev->data->port_id); 8171 return 0; 8172 } 8173 8174 /** 8175 * Free a counter. 8176 * 8177 * @param[in] dev 8178 * Pointer to Ethernet device structure. 8179 * @param[in] cnt 8180 * Index to counter to be free. 8181 */ 8182 void 8183 mlx5_counter_free(struct rte_eth_dev *dev, uint32_t cnt) 8184 { 8185 const struct mlx5_flow_driver_ops *fops; 8186 struct rte_flow_attr attr = { .transfer = 0 }; 8187 8188 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 8189 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8190 fops->counter_free(dev, cnt); 8191 return; 8192 } 8193 DRV_LOG(ERR, 8194 "port %u counter free is not supported.", 8195 dev->data->port_id); 8196 } 8197 8198 /** 8199 * Query counter statistics. 8200 * 8201 * @param[in] dev 8202 * Pointer to Ethernet device structure. 8203 * @param[in] cnt 8204 * Index to counter to query. 8205 * @param[in] clear 8206 * Set to clear counter statistics. 8207 * @param[out] pkts 8208 * The counter hits packets number to save. 8209 * @param[out] bytes 8210 * The counter hits bytes number to save. 8211 * 8212 * @return 8213 * 0 on success, a negative errno value otherwise. 8214 */ 8215 int 8216 mlx5_counter_query(struct rte_eth_dev *dev, uint32_t cnt, 8217 bool clear, uint64_t *pkts, uint64_t *bytes, void **action) 8218 { 8219 const struct mlx5_flow_driver_ops *fops; 8220 struct rte_flow_attr attr = { .transfer = 0 }; 8221 8222 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 8223 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 8224 return fops->counter_query(dev, cnt, clear, pkts, 8225 bytes, action); 8226 } 8227 DRV_LOG(ERR, 8228 "port %u counter query is not supported.", 8229 dev->data->port_id); 8230 return -ENOTSUP; 8231 } 8232 8233 /** 8234 * Get information about HWS pre-configurable resources. 8235 * 8236 * @param[in] dev 8237 * Pointer to the rte_eth_dev structure. 8238 * @param[out] port_info 8239 * Pointer to port information. 8240 * @param[out] queue_info 8241 * Pointer to queue information. 8242 * @param[out] error 8243 * Pointer to error structure. 8244 * 8245 * @return 8246 * 0 on success, a negative errno value otherwise and rte_errno is set. 8247 */ 8248 static int 8249 mlx5_flow_info_get(struct rte_eth_dev *dev, 8250 struct rte_flow_port_info *port_info, 8251 struct rte_flow_queue_info *queue_info, 8252 struct rte_flow_error *error) 8253 { 8254 const struct mlx5_flow_driver_ops *fops; 8255 struct rte_flow_attr attr = {0}; 8256 8257 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8258 return rte_flow_error_set(error, ENOTSUP, 8259 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8260 NULL, 8261 "info get with incorrect steering mode"); 8262 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8263 return fops->info_get(dev, port_info, queue_info, error); 8264 } 8265 8266 /** 8267 * Configure port HWS resources. 8268 * 8269 * @param[in] dev 8270 * Pointer to the rte_eth_dev structure. 8271 * @param[in] port_attr 8272 * Port configuration attributes. 8273 * @param[in] nb_queue 8274 * Number of queue. 8275 * @param[in] queue_attr 8276 * Array that holds attributes for each flow queue. 8277 * @param[out] error 8278 * Pointer to error structure. 8279 * 8280 * @return 8281 * 0 on success, a negative errno value otherwise and rte_errno is set. 8282 */ 8283 static int 8284 mlx5_flow_port_configure(struct rte_eth_dev *dev, 8285 const struct rte_flow_port_attr *port_attr, 8286 uint16_t nb_queue, 8287 const struct rte_flow_queue_attr *queue_attr[], 8288 struct rte_flow_error *error) 8289 { 8290 const struct mlx5_flow_driver_ops *fops; 8291 struct rte_flow_attr attr = {0}; 8292 8293 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8294 return rte_flow_error_set(error, ENOTSUP, 8295 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8296 NULL, 8297 "port configure with incorrect steering mode"); 8298 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8299 return fops->configure(dev, port_attr, nb_queue, queue_attr, error); 8300 } 8301 8302 /** 8303 * Create flow item template. 8304 * 8305 * @param[in] dev 8306 * Pointer to the rte_eth_dev structure. 8307 * @param[in] attr 8308 * Pointer to the item template attributes. 8309 * @param[in] items 8310 * The template item pattern. 8311 * @param[out] error 8312 * Pointer to error structure. 8313 * 8314 * @return 8315 * 0 on success, a negative errno value otherwise and rte_errno is set. 8316 */ 8317 static struct rte_flow_pattern_template * 8318 mlx5_flow_pattern_template_create(struct rte_eth_dev *dev, 8319 const struct rte_flow_pattern_template_attr *attr, 8320 const struct rte_flow_item items[], 8321 struct rte_flow_error *error) 8322 { 8323 const struct mlx5_flow_driver_ops *fops; 8324 struct rte_flow_attr fattr = {0}; 8325 8326 if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) { 8327 rte_flow_error_set(error, ENOTSUP, 8328 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8329 NULL, 8330 "pattern create with incorrect steering mode"); 8331 return NULL; 8332 } 8333 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8334 return fops->pattern_template_create(dev, attr, items, error); 8335 } 8336 8337 /** 8338 * Destroy flow item template. 8339 * 8340 * @param[in] dev 8341 * Pointer to the rte_eth_dev structure. 8342 * @param[in] template 8343 * Pointer to the item template to be destroyed. 8344 * @param[out] error 8345 * Pointer to error structure. 8346 * 8347 * @return 8348 * 0 on success, a negative errno value otherwise and rte_errno is set. 8349 */ 8350 static int 8351 mlx5_flow_pattern_template_destroy(struct rte_eth_dev *dev, 8352 struct rte_flow_pattern_template *template, 8353 struct rte_flow_error *error) 8354 { 8355 const struct mlx5_flow_driver_ops *fops; 8356 struct rte_flow_attr attr = {0}; 8357 8358 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8359 return rte_flow_error_set(error, ENOTSUP, 8360 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8361 NULL, 8362 "pattern destroy with incorrect steering mode"); 8363 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8364 return fops->pattern_template_destroy(dev, template, error); 8365 } 8366 8367 /** 8368 * Create flow item template. 8369 * 8370 * @param[in] dev 8371 * Pointer to the rte_eth_dev structure. 8372 * @param[in] attr 8373 * Pointer to the action template attributes. 8374 * @param[in] actions 8375 * Associated actions (list terminated by the END action). 8376 * @param[in] masks 8377 * List of actions that marks which of the action's member is constant. 8378 * @param[out] error 8379 * Pointer to error structure. 8380 * 8381 * @return 8382 * 0 on success, a negative errno value otherwise and rte_errno is set. 8383 */ 8384 static struct rte_flow_actions_template * 8385 mlx5_flow_actions_template_create(struct rte_eth_dev *dev, 8386 const struct rte_flow_actions_template_attr *attr, 8387 const struct rte_flow_action actions[], 8388 const struct rte_flow_action masks[], 8389 struct rte_flow_error *error) 8390 { 8391 const struct mlx5_flow_driver_ops *fops; 8392 struct rte_flow_attr fattr = {0}; 8393 8394 if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) { 8395 rte_flow_error_set(error, ENOTSUP, 8396 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8397 NULL, 8398 "action create with incorrect steering mode"); 8399 return NULL; 8400 } 8401 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8402 return fops->actions_template_create(dev, attr, actions, masks, error); 8403 } 8404 8405 /** 8406 * Destroy flow action template. 8407 * 8408 * @param[in] dev 8409 * Pointer to the rte_eth_dev structure. 8410 * @param[in] template 8411 * Pointer to the action template to be destroyed. 8412 * @param[out] error 8413 * Pointer to error structure. 8414 * 8415 * @return 8416 * 0 on success, a negative errno value otherwise and rte_errno is set. 8417 */ 8418 static int 8419 mlx5_flow_actions_template_destroy(struct rte_eth_dev *dev, 8420 struct rte_flow_actions_template *template, 8421 struct rte_flow_error *error) 8422 { 8423 const struct mlx5_flow_driver_ops *fops; 8424 struct rte_flow_attr attr = {0}; 8425 8426 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8427 return rte_flow_error_set(error, ENOTSUP, 8428 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8429 NULL, 8430 "action destroy with incorrect steering mode"); 8431 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8432 return fops->actions_template_destroy(dev, template, error); 8433 } 8434 8435 /** 8436 * Create flow table. 8437 * 8438 * @param[in] dev 8439 * Pointer to the rte_eth_dev structure. 8440 * @param[in] attr 8441 * Pointer to the table attributes. 8442 * @param[in] item_templates 8443 * Item template array to be binded to the table. 8444 * @param[in] nb_item_templates 8445 * Number of item template. 8446 * @param[in] action_templates 8447 * Action template array to be binded to the table. 8448 * @param[in] nb_action_templates 8449 * Number of action template. 8450 * @param[out] error 8451 * Pointer to error structure. 8452 * 8453 * @return 8454 * Table on success, NULL otherwise and rte_errno is set. 8455 */ 8456 static struct rte_flow_template_table * 8457 mlx5_flow_table_create(struct rte_eth_dev *dev, 8458 const struct rte_flow_template_table_attr *attr, 8459 struct rte_flow_pattern_template *item_templates[], 8460 uint8_t nb_item_templates, 8461 struct rte_flow_actions_template *action_templates[], 8462 uint8_t nb_action_templates, 8463 struct rte_flow_error *error) 8464 { 8465 const struct mlx5_flow_driver_ops *fops; 8466 struct rte_flow_attr fattr = {0}; 8467 8468 if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) { 8469 rte_flow_error_set(error, ENOTSUP, 8470 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8471 NULL, 8472 "table create with incorrect steering mode"); 8473 return NULL; 8474 } 8475 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8476 return fops->template_table_create(dev, 8477 attr, 8478 item_templates, 8479 nb_item_templates, 8480 action_templates, 8481 nb_action_templates, 8482 error); 8483 } 8484 8485 /** 8486 * PMD destroy flow table. 8487 * 8488 * @param[in] dev 8489 * Pointer to the rte_eth_dev structure. 8490 * @param[in] table 8491 * Pointer to the table to be destroyed. 8492 * @param[out] error 8493 * Pointer to error structure. 8494 * 8495 * @return 8496 * 0 on success, a negative errno value otherwise and rte_errno is set. 8497 */ 8498 static int 8499 mlx5_flow_table_destroy(struct rte_eth_dev *dev, 8500 struct rte_flow_template_table *table, 8501 struct rte_flow_error *error) 8502 { 8503 const struct mlx5_flow_driver_ops *fops; 8504 struct rte_flow_attr attr = {0}; 8505 8506 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8507 return rte_flow_error_set(error, ENOTSUP, 8508 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8509 NULL, 8510 "table destroy with incorrect steering mode"); 8511 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8512 return fops->template_table_destroy(dev, table, error); 8513 } 8514 8515 /** 8516 * Enqueue flow creation. 8517 * 8518 * @param[in] dev 8519 * Pointer to the rte_eth_dev structure. 8520 * @param[in] queue_id 8521 * The queue to create the flow. 8522 * @param[in] attr 8523 * Pointer to the flow operation attributes. 8524 * @param[in] items 8525 * Items with flow spec value. 8526 * @param[in] pattern_template_index 8527 * The item pattern flow follows from the table. 8528 * @param[in] actions 8529 * Action with flow spec value. 8530 * @param[in] action_template_index 8531 * The action pattern flow follows from the table. 8532 * @param[in] user_data 8533 * Pointer to the user_data. 8534 * @param[out] error 8535 * Pointer to error structure. 8536 * 8537 * @return 8538 * Flow pointer on success, NULL otherwise and rte_errno is set. 8539 */ 8540 static struct rte_flow * 8541 mlx5_flow_async_flow_create(struct rte_eth_dev *dev, 8542 uint32_t queue_id, 8543 const struct rte_flow_op_attr *attr, 8544 struct rte_flow_template_table *table, 8545 const struct rte_flow_item items[], 8546 uint8_t pattern_template_index, 8547 const struct rte_flow_action actions[], 8548 uint8_t action_template_index, 8549 void *user_data, 8550 struct rte_flow_error *error) 8551 { 8552 const struct mlx5_flow_driver_ops *fops; 8553 struct rte_flow_attr fattr = {0}; 8554 8555 if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) { 8556 rte_flow_error_set(error, ENOTSUP, 8557 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8558 NULL, 8559 "flow_q create with incorrect steering mode"); 8560 return NULL; 8561 } 8562 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8563 return fops->async_flow_create(dev, queue_id, attr, table, 8564 items, pattern_template_index, 8565 actions, action_template_index, 8566 user_data, error); 8567 } 8568 8569 /** 8570 * Enqueue flow destruction. 8571 * 8572 * @param[in] dev 8573 * Pointer to the rte_eth_dev structure. 8574 * @param[in] queue 8575 * The queue to destroy the flow. 8576 * @param[in] attr 8577 * Pointer to the flow operation attributes. 8578 * @param[in] flow 8579 * Pointer to the flow to be destroyed. 8580 * @param[in] user_data 8581 * Pointer to the user_data. 8582 * @param[out] error 8583 * Pointer to error structure. 8584 * 8585 * @return 8586 * 0 on success, negative value otherwise and rte_errno is set. 8587 */ 8588 static int 8589 mlx5_flow_async_flow_destroy(struct rte_eth_dev *dev, 8590 uint32_t queue, 8591 const struct rte_flow_op_attr *attr, 8592 struct rte_flow *flow, 8593 void *user_data, 8594 struct rte_flow_error *error) 8595 { 8596 const struct mlx5_flow_driver_ops *fops; 8597 struct rte_flow_attr fattr = {0}; 8598 8599 if (flow_get_drv_type(dev, &fattr) != MLX5_FLOW_TYPE_HW) 8600 return rte_flow_error_set(error, ENOTSUP, 8601 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8602 NULL, 8603 "flow_q destroy with incorrect steering mode"); 8604 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8605 return fops->async_flow_destroy(dev, queue, attr, flow, 8606 user_data, error); 8607 } 8608 8609 /** 8610 * Pull the enqueued flows. 8611 * 8612 * @param[in] dev 8613 * Pointer to the rte_eth_dev structure. 8614 * @param[in] queue 8615 * The queue to pull the result. 8616 * @param[in/out] res 8617 * Array to save the results. 8618 * @param[in] n_res 8619 * Available result with the array. 8620 * @param[out] error 8621 * Pointer to error structure. 8622 * 8623 * @return 8624 * Result number on success, negative value otherwise and rte_errno is set. 8625 */ 8626 static int 8627 mlx5_flow_pull(struct rte_eth_dev *dev, 8628 uint32_t queue, 8629 struct rte_flow_op_result res[], 8630 uint16_t n_res, 8631 struct rte_flow_error *error) 8632 { 8633 const struct mlx5_flow_driver_ops *fops; 8634 struct rte_flow_attr attr = {0}; 8635 8636 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8637 return rte_flow_error_set(error, ENOTSUP, 8638 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8639 NULL, 8640 "flow_q pull with incorrect steering mode"); 8641 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8642 return fops->pull(dev, queue, res, n_res, error); 8643 } 8644 8645 /** 8646 * Push the enqueued flows. 8647 * 8648 * @param[in] dev 8649 * Pointer to the rte_eth_dev structure. 8650 * @param[in] queue 8651 * The queue to push the flows. 8652 * @param[out] error 8653 * Pointer to error structure. 8654 * 8655 * @return 8656 * 0 on success, negative value otherwise and rte_errno is set. 8657 */ 8658 static int 8659 mlx5_flow_push(struct rte_eth_dev *dev, 8660 uint32_t queue, 8661 struct rte_flow_error *error) 8662 { 8663 const struct mlx5_flow_driver_ops *fops; 8664 struct rte_flow_attr attr = {0}; 8665 8666 if (flow_get_drv_type(dev, &attr) != MLX5_FLOW_TYPE_HW) 8667 return rte_flow_error_set(error, ENOTSUP, 8668 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 8669 NULL, 8670 "flow_q push with incorrect steering mode"); 8671 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8672 return fops->push(dev, queue, error); 8673 } 8674 8675 /** 8676 * Create shared action. 8677 * 8678 * @param[in] dev 8679 * Pointer to the rte_eth_dev structure. 8680 * @param[in] queue 8681 * Which queue to be used.. 8682 * @param[in] attr 8683 * Operation attribute. 8684 * @param[in] conf 8685 * Indirect action configuration. 8686 * @param[in] action 8687 * rte_flow action detail. 8688 * @param[in] user_data 8689 * Pointer to the user_data. 8690 * @param[out] error 8691 * Pointer to error structure. 8692 * 8693 * @return 8694 * Action handle on success, NULL otherwise and rte_errno is set. 8695 */ 8696 static struct rte_flow_action_handle * 8697 mlx5_flow_async_action_handle_create(struct rte_eth_dev *dev, uint32_t queue, 8698 const struct rte_flow_op_attr *attr, 8699 const struct rte_flow_indir_action_conf *conf, 8700 const struct rte_flow_action *action, 8701 void *user_data, 8702 struct rte_flow_error *error) 8703 { 8704 const struct mlx5_flow_driver_ops *fops = 8705 flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8706 8707 return fops->async_action_create(dev, queue, attr, conf, action, 8708 user_data, error); 8709 } 8710 8711 /** 8712 * Update shared action. 8713 * 8714 * @param[in] dev 8715 * Pointer to the rte_eth_dev structure. 8716 * @param[in] queue 8717 * Which queue to be used.. 8718 * @param[in] attr 8719 * Operation attribute. 8720 * @param[in] handle 8721 * Action handle to be updated. 8722 * @param[in] update 8723 * Update value. 8724 * @param[in] user_data 8725 * Pointer to the user_data. 8726 * @param[out] error 8727 * Pointer to error structure. 8728 * 8729 * @return 8730 * 0 on success, negative value otherwise and rte_errno is set. 8731 */ 8732 static int 8733 mlx5_flow_async_action_handle_update(struct rte_eth_dev *dev, uint32_t queue, 8734 const struct rte_flow_op_attr *attr, 8735 struct rte_flow_action_handle *handle, 8736 const void *update, 8737 void *user_data, 8738 struct rte_flow_error *error) 8739 { 8740 const struct mlx5_flow_driver_ops *fops = 8741 flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8742 8743 return fops->async_action_update(dev, queue, attr, handle, 8744 update, user_data, error); 8745 } 8746 8747 /** 8748 * Destroy shared action. 8749 * 8750 * @param[in] dev 8751 * Pointer to the rte_eth_dev structure. 8752 * @param[in] queue 8753 * Which queue to be used.. 8754 * @param[in] attr 8755 * Operation attribute. 8756 * @param[in] handle 8757 * Action handle to be destroyed. 8758 * @param[in] user_data 8759 * Pointer to the user_data. 8760 * @param[out] error 8761 * Pointer to error structure. 8762 * 8763 * @return 8764 * 0 on success, negative value otherwise and rte_errno is set. 8765 */ 8766 static int 8767 mlx5_flow_async_action_handle_destroy(struct rte_eth_dev *dev, uint32_t queue, 8768 const struct rte_flow_op_attr *attr, 8769 struct rte_flow_action_handle *handle, 8770 void *user_data, 8771 struct rte_flow_error *error) 8772 { 8773 const struct mlx5_flow_driver_ops *fops = 8774 flow_get_drv_ops(MLX5_FLOW_TYPE_HW); 8775 8776 return fops->async_action_destroy(dev, queue, attr, handle, 8777 user_data, error); 8778 } 8779 8780 /** 8781 * Allocate a new memory for the counter values wrapped by all the needed 8782 * management. 8783 * 8784 * @param[in] sh 8785 * Pointer to mlx5_dev_ctx_shared object. 8786 * 8787 * @return 8788 * 0 on success, a negative errno value otherwise. 8789 */ 8790 static int 8791 mlx5_flow_create_counter_stat_mem_mng(struct mlx5_dev_ctx_shared *sh) 8792 { 8793 struct mlx5_counter_stats_mem_mng *mem_mng; 8794 volatile struct flow_counter_stats *raw_data; 8795 int raws_n = MLX5_CNT_CONTAINER_RESIZE + MLX5_MAX_PENDING_QUERIES; 8796 int size = (sizeof(struct flow_counter_stats) * 8797 MLX5_COUNTERS_PER_POOL + 8798 sizeof(struct mlx5_counter_stats_raw)) * raws_n + 8799 sizeof(struct mlx5_counter_stats_mem_mng); 8800 size_t pgsize = rte_mem_page_size(); 8801 uint8_t *mem; 8802 int ret; 8803 int i; 8804 8805 if (pgsize == (size_t)-1) { 8806 DRV_LOG(ERR, "Failed to get mem page size"); 8807 rte_errno = ENOMEM; 8808 return -ENOMEM; 8809 } 8810 mem = mlx5_malloc(MLX5_MEM_ZERO, size, pgsize, SOCKET_ID_ANY); 8811 if (!mem) { 8812 rte_errno = ENOMEM; 8813 return -ENOMEM; 8814 } 8815 mem_mng = (struct mlx5_counter_stats_mem_mng *)(mem + size) - 1; 8816 size = sizeof(*raw_data) * MLX5_COUNTERS_PER_POOL * raws_n; 8817 ret = mlx5_os_wrapped_mkey_create(sh->cdev->ctx, sh->cdev->pd, 8818 sh->cdev->pdn, mem, size, 8819 &mem_mng->wm); 8820 if (ret) { 8821 rte_errno = errno; 8822 mlx5_free(mem); 8823 return -rte_errno; 8824 } 8825 mem_mng->raws = (struct mlx5_counter_stats_raw *)(mem + size); 8826 raw_data = (volatile struct flow_counter_stats *)mem; 8827 for (i = 0; i < raws_n; ++i) { 8828 mem_mng->raws[i].mem_mng = mem_mng; 8829 mem_mng->raws[i].data = raw_data + i * MLX5_COUNTERS_PER_POOL; 8830 } 8831 for (i = 0; i < MLX5_MAX_PENDING_QUERIES; ++i) 8832 LIST_INSERT_HEAD(&sh->cmng.free_stat_raws, 8833 mem_mng->raws + MLX5_CNT_CONTAINER_RESIZE + i, 8834 next); 8835 LIST_INSERT_HEAD(&sh->cmng.mem_mngs, mem_mng, next); 8836 sh->cmng.mem_mng = mem_mng; 8837 return 0; 8838 } 8839 8840 /** 8841 * Set the statistic memory to the new counter pool. 8842 * 8843 * @param[in] sh 8844 * Pointer to mlx5_dev_ctx_shared object. 8845 * @param[in] pool 8846 * Pointer to the pool to set the statistic memory. 8847 * 8848 * @return 8849 * 0 on success, a negative errno value otherwise. 8850 */ 8851 static int 8852 mlx5_flow_set_counter_stat_mem(struct mlx5_dev_ctx_shared *sh, 8853 struct mlx5_flow_counter_pool *pool) 8854 { 8855 struct mlx5_flow_counter_mng *cmng = &sh->cmng; 8856 /* Resize statistic memory once used out. */ 8857 if (!(pool->index % MLX5_CNT_CONTAINER_RESIZE) && 8858 mlx5_flow_create_counter_stat_mem_mng(sh)) { 8859 DRV_LOG(ERR, "Cannot resize counter stat mem."); 8860 return -1; 8861 } 8862 rte_spinlock_lock(&pool->sl); 8863 pool->raw = cmng->mem_mng->raws + pool->index % 8864 MLX5_CNT_CONTAINER_RESIZE; 8865 rte_spinlock_unlock(&pool->sl); 8866 pool->raw_hw = NULL; 8867 return 0; 8868 } 8869 8870 #define MLX5_POOL_QUERY_FREQ_US 1000000 8871 8872 /** 8873 * Set the periodic procedure for triggering asynchronous batch queries for all 8874 * the counter pools. 8875 * 8876 * @param[in] sh 8877 * Pointer to mlx5_dev_ctx_shared object. 8878 */ 8879 void 8880 mlx5_set_query_alarm(struct mlx5_dev_ctx_shared *sh) 8881 { 8882 uint32_t pools_n, us; 8883 8884 pools_n = __atomic_load_n(&sh->cmng.n_valid, __ATOMIC_RELAXED); 8885 us = MLX5_POOL_QUERY_FREQ_US / pools_n; 8886 DRV_LOG(DEBUG, "Set alarm for %u pools each %u us", pools_n, us); 8887 if (rte_eal_alarm_set(us, mlx5_flow_query_alarm, sh)) { 8888 sh->cmng.query_thread_on = 0; 8889 DRV_LOG(ERR, "Cannot reinitialize query alarm"); 8890 } else { 8891 sh->cmng.query_thread_on = 1; 8892 } 8893 } 8894 8895 /** 8896 * The periodic procedure for triggering asynchronous batch queries for all the 8897 * counter pools. This function is probably called by the host thread. 8898 * 8899 * @param[in] arg 8900 * The parameter for the alarm process. 8901 */ 8902 void 8903 mlx5_flow_query_alarm(void *arg) 8904 { 8905 struct mlx5_dev_ctx_shared *sh = arg; 8906 int ret; 8907 uint16_t pool_index = sh->cmng.pool_index; 8908 struct mlx5_flow_counter_mng *cmng = &sh->cmng; 8909 struct mlx5_flow_counter_pool *pool; 8910 uint16_t n_valid; 8911 8912 if (sh->cmng.pending_queries >= MLX5_MAX_PENDING_QUERIES) 8913 goto set_alarm; 8914 rte_spinlock_lock(&cmng->pool_update_sl); 8915 pool = cmng->pools[pool_index]; 8916 n_valid = cmng->n_valid; 8917 rte_spinlock_unlock(&cmng->pool_update_sl); 8918 /* Set the statistic memory to the new created pool. */ 8919 if ((!pool->raw && mlx5_flow_set_counter_stat_mem(sh, pool))) 8920 goto set_alarm; 8921 if (pool->raw_hw) 8922 /* There is a pool query in progress. */ 8923 goto set_alarm; 8924 pool->raw_hw = 8925 LIST_FIRST(&sh->cmng.free_stat_raws); 8926 if (!pool->raw_hw) 8927 /* No free counter statistics raw memory. */ 8928 goto set_alarm; 8929 /* 8930 * Identify the counters released between query trigger and query 8931 * handle more efficiently. The counter released in this gap period 8932 * should wait for a new round of query as the new arrived packets 8933 * will not be taken into account. 8934 */ 8935 pool->query_gen++; 8936 ret = mlx5_devx_cmd_flow_counter_query(pool->min_dcs, 0, 8937 MLX5_COUNTERS_PER_POOL, 8938 NULL, NULL, 8939 pool->raw_hw->mem_mng->wm.lkey, 8940 (void *)(uintptr_t) 8941 pool->raw_hw->data, 8942 sh->devx_comp, 8943 (uint64_t)(uintptr_t)pool); 8944 if (ret) { 8945 DRV_LOG(ERR, "Failed to trigger asynchronous query for dcs ID" 8946 " %d", pool->min_dcs->id); 8947 pool->raw_hw = NULL; 8948 goto set_alarm; 8949 } 8950 LIST_REMOVE(pool->raw_hw, next); 8951 sh->cmng.pending_queries++; 8952 pool_index++; 8953 if (pool_index >= n_valid) 8954 pool_index = 0; 8955 set_alarm: 8956 sh->cmng.pool_index = pool_index; 8957 mlx5_set_query_alarm(sh); 8958 } 8959 8960 /** 8961 * Check and callback event for new aged flow in the counter pool 8962 * 8963 * @param[in] sh 8964 * Pointer to mlx5_dev_ctx_shared object. 8965 * @param[in] pool 8966 * Pointer to Current counter pool. 8967 */ 8968 static void 8969 mlx5_flow_aging_check(struct mlx5_dev_ctx_shared *sh, 8970 struct mlx5_flow_counter_pool *pool) 8971 { 8972 struct mlx5_priv *priv; 8973 struct mlx5_flow_counter *cnt; 8974 struct mlx5_age_info *age_info; 8975 struct mlx5_age_param *age_param; 8976 struct mlx5_counter_stats_raw *cur = pool->raw_hw; 8977 struct mlx5_counter_stats_raw *prev = pool->raw; 8978 const uint64_t curr_time = MLX5_CURR_TIME_SEC; 8979 const uint32_t time_delta = curr_time - pool->time_of_last_age_check; 8980 uint16_t expected = AGE_CANDIDATE; 8981 uint32_t i; 8982 8983 pool->time_of_last_age_check = curr_time; 8984 for (i = 0; i < MLX5_COUNTERS_PER_POOL; ++i) { 8985 cnt = MLX5_POOL_GET_CNT(pool, i); 8986 age_param = MLX5_CNT_TO_AGE(cnt); 8987 if (__atomic_load_n(&age_param->state, 8988 __ATOMIC_RELAXED) != AGE_CANDIDATE) 8989 continue; 8990 if (cur->data[i].hits != prev->data[i].hits) { 8991 __atomic_store_n(&age_param->sec_since_last_hit, 0, 8992 __ATOMIC_RELAXED); 8993 continue; 8994 } 8995 if (__atomic_add_fetch(&age_param->sec_since_last_hit, 8996 time_delta, 8997 __ATOMIC_RELAXED) <= age_param->timeout) 8998 continue; 8999 /** 9000 * Hold the lock first, or if between the 9001 * state AGE_TMOUT and tailq operation the 9002 * release happened, the release procedure 9003 * may delete a non-existent tailq node. 9004 */ 9005 priv = rte_eth_devices[age_param->port_id].data->dev_private; 9006 age_info = GET_PORT_AGE_INFO(priv); 9007 rte_spinlock_lock(&age_info->aged_sl); 9008 if (__atomic_compare_exchange_n(&age_param->state, &expected, 9009 AGE_TMOUT, false, 9010 __ATOMIC_RELAXED, 9011 __ATOMIC_RELAXED)) { 9012 TAILQ_INSERT_TAIL(&age_info->aged_counters, cnt, next); 9013 MLX5_AGE_SET(age_info, MLX5_AGE_EVENT_NEW); 9014 } 9015 rte_spinlock_unlock(&age_info->aged_sl); 9016 } 9017 mlx5_age_event_prepare(sh); 9018 } 9019 9020 /** 9021 * Handler for the HW respond about ready values from an asynchronous batch 9022 * query. This function is probably called by the host thread. 9023 * 9024 * @param[in] sh 9025 * The pointer to the shared device context. 9026 * @param[in] async_id 9027 * The Devx async ID. 9028 * @param[in] status 9029 * The status of the completion. 9030 */ 9031 void 9032 mlx5_flow_async_pool_query_handle(struct mlx5_dev_ctx_shared *sh, 9033 uint64_t async_id, int status) 9034 { 9035 struct mlx5_flow_counter_pool *pool = 9036 (struct mlx5_flow_counter_pool *)(uintptr_t)async_id; 9037 struct mlx5_counter_stats_raw *raw_to_free; 9038 uint8_t query_gen = pool->query_gen ^ 1; 9039 struct mlx5_flow_counter_mng *cmng = &sh->cmng; 9040 enum mlx5_counter_type cnt_type = 9041 pool->is_aged ? MLX5_COUNTER_TYPE_AGE : 9042 MLX5_COUNTER_TYPE_ORIGIN; 9043 9044 if (unlikely(status)) { 9045 raw_to_free = pool->raw_hw; 9046 } else { 9047 raw_to_free = pool->raw; 9048 if (pool->is_aged) 9049 mlx5_flow_aging_check(sh, pool); 9050 rte_spinlock_lock(&pool->sl); 9051 pool->raw = pool->raw_hw; 9052 rte_spinlock_unlock(&pool->sl); 9053 /* Be sure the new raw counters data is updated in memory. */ 9054 rte_io_wmb(); 9055 if (!TAILQ_EMPTY(&pool->counters[query_gen])) { 9056 rte_spinlock_lock(&cmng->csl[cnt_type]); 9057 TAILQ_CONCAT(&cmng->counters[cnt_type], 9058 &pool->counters[query_gen], next); 9059 rte_spinlock_unlock(&cmng->csl[cnt_type]); 9060 } 9061 } 9062 LIST_INSERT_HEAD(&sh->cmng.free_stat_raws, raw_to_free, next); 9063 pool->raw_hw = NULL; 9064 sh->cmng.pending_queries--; 9065 } 9066 9067 static int 9068 flow_group_to_table(uint32_t port_id, uint32_t group, uint32_t *table, 9069 const struct flow_grp_info *grp_info, 9070 struct rte_flow_error *error) 9071 { 9072 if (grp_info->transfer && grp_info->external && 9073 grp_info->fdb_def_rule) { 9074 if (group == UINT32_MAX) 9075 return rte_flow_error_set 9076 (error, EINVAL, 9077 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 9078 NULL, 9079 "group index not supported"); 9080 *table = group + 1; 9081 } else { 9082 *table = group; 9083 } 9084 DRV_LOG(DEBUG, "port %u group=%#x table=%#x", port_id, group, *table); 9085 return 0; 9086 } 9087 9088 /** 9089 * Translate the rte_flow group index to HW table value. 9090 * 9091 * If tunnel offload is disabled, all group ids converted to flow table 9092 * id using the standard method. 9093 * If tunnel offload is enabled, group id can be converted using the 9094 * standard or tunnel conversion method. Group conversion method 9095 * selection depends on flags in `grp_info` parameter: 9096 * - Internal (grp_info.external == 0) groups conversion uses the 9097 * standard method. 9098 * - Group ids in JUMP action converted with the tunnel conversion. 9099 * - Group id in rule attribute conversion depends on a rule type and 9100 * group id value: 9101 * ** non zero group attributes converted with the tunnel method 9102 * ** zero group attribute in non-tunnel rule is converted using the 9103 * standard method - there's only one root table 9104 * ** zero group attribute in steer tunnel rule is converted with the 9105 * standard method - single root table 9106 * ** zero group attribute in match tunnel rule is a special OvS 9107 * case: that value is used for portability reasons. That group 9108 * id is converted with the tunnel conversion method. 9109 * 9110 * @param[in] dev 9111 * Port device 9112 * @param[in] tunnel 9113 * PMD tunnel offload object 9114 * @param[in] group 9115 * rte_flow group index value. 9116 * @param[out] table 9117 * HW table value. 9118 * @param[in] grp_info 9119 * flags used for conversion 9120 * @param[out] error 9121 * Pointer to error structure. 9122 * 9123 * @return 9124 * 0 on success, a negative errno value otherwise and rte_errno is set. 9125 */ 9126 int 9127 mlx5_flow_group_to_table(struct rte_eth_dev *dev, 9128 const struct mlx5_flow_tunnel *tunnel, 9129 uint32_t group, uint32_t *table, 9130 const struct flow_grp_info *grp_info, 9131 struct rte_flow_error *error) 9132 { 9133 int ret; 9134 bool standard_translation; 9135 9136 if (!grp_info->skip_scale && grp_info->external && 9137 group < MLX5_MAX_TABLES_EXTERNAL) 9138 group *= MLX5_FLOW_TABLE_FACTOR; 9139 if (is_tunnel_offload_active(dev)) { 9140 standard_translation = !grp_info->external || 9141 grp_info->std_tbl_fix; 9142 } else { 9143 standard_translation = true; 9144 } 9145 DRV_LOG(DEBUG, 9146 "port %u group=%u transfer=%d external=%d fdb_def_rule=%d translate=%s", 9147 dev->data->port_id, group, grp_info->transfer, 9148 grp_info->external, grp_info->fdb_def_rule, 9149 standard_translation ? "STANDARD" : "TUNNEL"); 9150 if (standard_translation) 9151 ret = flow_group_to_table(dev->data->port_id, group, table, 9152 grp_info, error); 9153 else 9154 ret = tunnel_flow_group_to_flow_table(dev, tunnel, group, 9155 table, error); 9156 9157 return ret; 9158 } 9159 9160 /** 9161 * Discover availability of metadata reg_c's. 9162 * 9163 * Iteratively use test flows to check availability. 9164 * 9165 * @param[in] dev 9166 * Pointer to the Ethernet device structure. 9167 * 9168 * @return 9169 * 0 on success, a negative errno value otherwise and rte_errno is set. 9170 */ 9171 int 9172 mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev) 9173 { 9174 struct mlx5_priv *priv = dev->data->dev_private; 9175 enum modify_reg idx; 9176 int n = 0; 9177 9178 /* reg_c[0] and reg_c[1] are reserved. */ 9179 priv->sh->flow_mreg_c[n++] = REG_C_0; 9180 priv->sh->flow_mreg_c[n++] = REG_C_1; 9181 /* Discover availability of other reg_c's. */ 9182 for (idx = REG_C_2; idx <= REG_C_7; ++idx) { 9183 struct rte_flow_attr attr = { 9184 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP, 9185 .priority = MLX5_FLOW_LOWEST_PRIO_INDICATOR, 9186 .ingress = 1, 9187 }; 9188 struct rte_flow_item items[] = { 9189 [0] = { 9190 .type = RTE_FLOW_ITEM_TYPE_END, 9191 }, 9192 }; 9193 struct rte_flow_action actions[] = { 9194 [0] = { 9195 .type = (enum rte_flow_action_type) 9196 MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 9197 .conf = &(struct mlx5_flow_action_copy_mreg){ 9198 .src = REG_C_1, 9199 .dst = idx, 9200 }, 9201 }, 9202 [1] = { 9203 .type = RTE_FLOW_ACTION_TYPE_JUMP, 9204 .conf = &(struct rte_flow_action_jump){ 9205 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP, 9206 }, 9207 }, 9208 [2] = { 9209 .type = RTE_FLOW_ACTION_TYPE_END, 9210 }, 9211 }; 9212 uint32_t flow_idx; 9213 struct rte_flow *flow; 9214 struct rte_flow_error error; 9215 9216 if (!priv->sh->config.dv_flow_en) 9217 break; 9218 /* Create internal flow, validation skips copy action. */ 9219 flow_idx = flow_list_create(dev, MLX5_FLOW_TYPE_GEN, &attr, 9220 items, actions, false, &error); 9221 flow = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN], 9222 flow_idx); 9223 if (!flow) 9224 continue; 9225 priv->sh->flow_mreg_c[n++] = idx; 9226 flow_list_destroy(dev, MLX5_FLOW_TYPE_GEN, flow_idx); 9227 } 9228 for (; n < MLX5_MREG_C_NUM; ++n) 9229 priv->sh->flow_mreg_c[n] = REG_NON; 9230 priv->sh->metadata_regc_check_flag = 1; 9231 return 0; 9232 } 9233 9234 int 9235 save_dump_file(const uint8_t *data, uint32_t size, 9236 uint32_t type, uint64_t id, void *arg, FILE *file) 9237 { 9238 char line[BUF_SIZE]; 9239 uint32_t out = 0; 9240 uint32_t k; 9241 uint32_t actions_num; 9242 struct rte_flow_query_count *count; 9243 9244 memset(line, 0, BUF_SIZE); 9245 switch (type) { 9246 case DR_DUMP_REC_TYPE_PMD_MODIFY_HDR: 9247 actions_num = *(uint32_t *)(arg); 9248 out += snprintf(line + out, BUF_SIZE - out, "%d,0x%" PRIx64 ",%d,", 9249 type, id, actions_num); 9250 break; 9251 case DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT: 9252 out += snprintf(line + out, BUF_SIZE - out, "%d,0x%" PRIx64 ",", 9253 type, id); 9254 break; 9255 case DR_DUMP_REC_TYPE_PMD_COUNTER: 9256 count = (struct rte_flow_query_count *)arg; 9257 fprintf(file, 9258 "%d,0x%" PRIx64 ",%" PRIu64 ",%" PRIu64 "\n", 9259 type, id, count->hits, count->bytes); 9260 return 0; 9261 default: 9262 return -1; 9263 } 9264 9265 for (k = 0; k < size; k++) { 9266 /* Make sure we do not overrun the line buffer length. */ 9267 if (out >= BUF_SIZE - 4) { 9268 line[out] = '\0'; 9269 break; 9270 } 9271 out += snprintf(line + out, BUF_SIZE - out, "%02x", 9272 (data[k]) & 0xff); 9273 } 9274 fprintf(file, "%s\n", line); 9275 return 0; 9276 } 9277 9278 int 9279 mlx5_flow_query_counter(struct rte_eth_dev *dev, struct rte_flow *flow, 9280 struct rte_flow_query_count *count, struct rte_flow_error *error) 9281 { 9282 struct rte_flow_action action[2]; 9283 enum mlx5_flow_drv_type ftype; 9284 const struct mlx5_flow_driver_ops *fops; 9285 9286 if (!flow) { 9287 return rte_flow_error_set(error, ENOENT, 9288 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9289 NULL, 9290 "invalid flow handle"); 9291 } 9292 action[0].type = RTE_FLOW_ACTION_TYPE_COUNT; 9293 action[1].type = RTE_FLOW_ACTION_TYPE_END; 9294 if (flow->counter) { 9295 memset(count, 0, sizeof(struct rte_flow_query_count)); 9296 ftype = (enum mlx5_flow_drv_type)(flow->drv_type); 9297 MLX5_ASSERT(ftype > MLX5_FLOW_TYPE_MIN && 9298 ftype < MLX5_FLOW_TYPE_MAX); 9299 fops = flow_get_drv_ops(ftype); 9300 return fops->query(dev, flow, action, count, error); 9301 } 9302 return -1; 9303 } 9304 9305 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 9306 /** 9307 * Dump flow ipool data to file 9308 * 9309 * @param[in] dev 9310 * The pointer to Ethernet device. 9311 * @param[in] file 9312 * A pointer to a file for output. 9313 * @param[out] error 9314 * Perform verbose error reporting if not NULL. PMDs initialize this 9315 * structure in case of error only. 9316 * @return 9317 * 0 on success, a negative value otherwise. 9318 */ 9319 int 9320 mlx5_flow_dev_dump_ipool(struct rte_eth_dev *dev, 9321 struct rte_flow *flow, FILE *file, 9322 struct rte_flow_error *error) 9323 { 9324 struct mlx5_priv *priv = dev->data->dev_private; 9325 struct mlx5_flow_dv_modify_hdr_resource *modify_hdr; 9326 struct mlx5_flow_dv_encap_decap_resource *encap_decap; 9327 uint32_t handle_idx; 9328 struct mlx5_flow_handle *dh; 9329 struct rte_flow_query_count count; 9330 uint32_t actions_num; 9331 const uint8_t *data; 9332 size_t size; 9333 uint64_t id; 9334 uint32_t type; 9335 void *action = NULL; 9336 9337 if (!flow) { 9338 return rte_flow_error_set(error, ENOENT, 9339 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 9340 NULL, 9341 "invalid flow handle"); 9342 } 9343 handle_idx = flow->dev_handles; 9344 /* query counter */ 9345 if (flow->counter && 9346 (!mlx5_counter_query(dev, flow->counter, false, 9347 &count.hits, &count.bytes, &action)) && action) { 9348 id = (uint64_t)(uintptr_t)action; 9349 type = DR_DUMP_REC_TYPE_PMD_COUNTER; 9350 save_dump_file(NULL, 0, type, 9351 id, (void *)&count, file); 9352 } 9353 9354 while (handle_idx) { 9355 dh = mlx5_ipool_get(priv->sh->ipool 9356 [MLX5_IPOOL_MLX5_FLOW], handle_idx); 9357 if (!dh) 9358 continue; 9359 handle_idx = dh->next.next; 9360 9361 /* Get modify_hdr and encap_decap buf from ipools. */ 9362 encap_decap = NULL; 9363 modify_hdr = dh->dvh.modify_hdr; 9364 9365 if (dh->dvh.rix_encap_decap) { 9366 encap_decap = mlx5_ipool_get(priv->sh->ipool 9367 [MLX5_IPOOL_DECAP_ENCAP], 9368 dh->dvh.rix_encap_decap); 9369 } 9370 if (modify_hdr) { 9371 data = (const uint8_t *)modify_hdr->actions; 9372 size = (size_t)(modify_hdr->actions_num) * 8; 9373 id = (uint64_t)(uintptr_t)modify_hdr->action; 9374 actions_num = modify_hdr->actions_num; 9375 type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR; 9376 save_dump_file(data, size, type, id, 9377 (void *)(&actions_num), file); 9378 } 9379 if (encap_decap) { 9380 data = encap_decap->buf; 9381 size = encap_decap->size; 9382 id = (uint64_t)(uintptr_t)encap_decap->action; 9383 type = DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT; 9384 save_dump_file(data, size, type, 9385 id, NULL, file); 9386 } 9387 } 9388 return 0; 9389 } 9390 9391 /** 9392 * Dump all flow's encap_decap/modify_hdr/counter data to file 9393 * 9394 * @param[in] dev 9395 * The pointer to Ethernet device. 9396 * @param[in] file 9397 * A pointer to a file for output. 9398 * @param[out] error 9399 * Perform verbose error reporting if not NULL. PMDs initialize this 9400 * structure in case of error only. 9401 * @return 9402 * 0 on success, a negative value otherwise. 9403 */ 9404 static int 9405 mlx5_flow_dev_dump_sh_all(struct rte_eth_dev *dev, 9406 FILE *file, struct rte_flow_error *error __rte_unused) 9407 { 9408 struct mlx5_priv *priv = dev->data->dev_private; 9409 struct mlx5_dev_ctx_shared *sh = priv->sh; 9410 struct mlx5_hlist *h; 9411 struct mlx5_flow_dv_modify_hdr_resource *modify_hdr; 9412 struct mlx5_flow_dv_encap_decap_resource *encap_decap; 9413 struct rte_flow_query_count count; 9414 uint32_t actions_num; 9415 const uint8_t *data; 9416 size_t size; 9417 uint64_t id; 9418 uint32_t type; 9419 uint32_t i; 9420 uint32_t j; 9421 struct mlx5_list_inconst *l_inconst; 9422 struct mlx5_list_entry *e; 9423 int lcore_index; 9424 struct mlx5_flow_counter_mng *cmng = &priv->sh->cmng; 9425 uint32_t max; 9426 void *action; 9427 9428 /* encap_decap hlist is lcore_share, get global core cache. */ 9429 i = MLX5_LIST_GLOBAL; 9430 h = sh->encaps_decaps; 9431 if (h) { 9432 for (j = 0; j <= h->mask; j++) { 9433 l_inconst = &h->buckets[j].l; 9434 if (!l_inconst || !l_inconst->cache[i]) 9435 continue; 9436 9437 e = LIST_FIRST(&l_inconst->cache[i]->h); 9438 while (e) { 9439 encap_decap = 9440 (struct mlx5_flow_dv_encap_decap_resource *)e; 9441 data = encap_decap->buf; 9442 size = encap_decap->size; 9443 id = (uint64_t)(uintptr_t)encap_decap->action; 9444 type = DR_DUMP_REC_TYPE_PMD_PKT_REFORMAT; 9445 save_dump_file(data, size, type, 9446 id, NULL, file); 9447 e = LIST_NEXT(e, next); 9448 } 9449 } 9450 } 9451 9452 /* get modify_hdr */ 9453 h = sh->modify_cmds; 9454 if (h) { 9455 lcore_index = rte_lcore_index(rte_lcore_id()); 9456 if (unlikely(lcore_index == -1)) { 9457 lcore_index = MLX5_LIST_NLCORE; 9458 rte_spinlock_lock(&h->l_const.lcore_lock); 9459 } 9460 i = lcore_index; 9461 9462 for (j = 0; j <= h->mask; j++) { 9463 l_inconst = &h->buckets[j].l; 9464 if (!l_inconst || !l_inconst->cache[i]) 9465 continue; 9466 9467 e = LIST_FIRST(&l_inconst->cache[i]->h); 9468 while (e) { 9469 modify_hdr = 9470 (struct mlx5_flow_dv_modify_hdr_resource *)e; 9471 data = (const uint8_t *)modify_hdr->actions; 9472 size = (size_t)(modify_hdr->actions_num) * 8; 9473 actions_num = modify_hdr->actions_num; 9474 id = (uint64_t)(uintptr_t)modify_hdr->action; 9475 type = DR_DUMP_REC_TYPE_PMD_MODIFY_HDR; 9476 save_dump_file(data, size, type, id, 9477 (void *)(&actions_num), file); 9478 e = LIST_NEXT(e, next); 9479 } 9480 } 9481 9482 if (unlikely(lcore_index == MLX5_LIST_NLCORE)) 9483 rte_spinlock_unlock(&h->l_const.lcore_lock); 9484 } 9485 9486 /* get counter */ 9487 MLX5_ASSERT(cmng->n_valid <= cmng->n); 9488 max = MLX5_COUNTERS_PER_POOL * cmng->n_valid; 9489 for (j = 1; j <= max; j++) { 9490 action = NULL; 9491 if ((!mlx5_counter_query(dev, j, false, &count.hits, 9492 &count.bytes, &action)) && action) { 9493 id = (uint64_t)(uintptr_t)action; 9494 type = DR_DUMP_REC_TYPE_PMD_COUNTER; 9495 save_dump_file(NULL, 0, type, 9496 id, (void *)&count, file); 9497 } 9498 } 9499 return 0; 9500 } 9501 #endif 9502 9503 /** 9504 * Dump flow raw hw data to file 9505 * 9506 * @param[in] dev 9507 * The pointer to Ethernet device. 9508 * @param[in] file 9509 * A pointer to a file for output. 9510 * @param[out] error 9511 * Perform verbose error reporting if not NULL. PMDs initialize this 9512 * structure in case of error only. 9513 * @return 9514 * 0 on success, a negative value otherwise. 9515 */ 9516 int 9517 mlx5_flow_dev_dump(struct rte_eth_dev *dev, struct rte_flow *flow_idx, 9518 FILE *file, 9519 struct rte_flow_error *error __rte_unused) 9520 { 9521 struct mlx5_priv *priv = dev->data->dev_private; 9522 struct mlx5_dev_ctx_shared *sh = priv->sh; 9523 uint32_t handle_idx; 9524 int ret; 9525 struct mlx5_flow_handle *dh; 9526 struct rte_flow *flow; 9527 9528 if (!sh->config.dv_flow_en) { 9529 if (fputs("device dv flow disabled\n", file) <= 0) 9530 return -errno; 9531 return -ENOTSUP; 9532 } 9533 9534 /* dump all */ 9535 if (!flow_idx) { 9536 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 9537 if (mlx5_flow_dev_dump_sh_all(dev, file, error)) 9538 return -EINVAL; 9539 #endif 9540 return mlx5_devx_cmd_flow_dump(sh->fdb_domain, 9541 sh->rx_domain, 9542 sh->tx_domain, file); 9543 } 9544 /* dump one */ 9545 flow = mlx5_ipool_get(priv->flows[MLX5_FLOW_TYPE_GEN], 9546 (uintptr_t)(void *)flow_idx); 9547 if (!flow) 9548 return -EINVAL; 9549 9550 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 9551 mlx5_flow_dev_dump_ipool(dev, flow, file, error); 9552 #endif 9553 handle_idx = flow->dev_handles; 9554 while (handle_idx) { 9555 dh = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], 9556 handle_idx); 9557 if (!dh) 9558 return -ENOENT; 9559 if (dh->drv_flow) { 9560 ret = mlx5_devx_cmd_flow_single_dump(dh->drv_flow, 9561 file); 9562 if (ret) 9563 return -ENOENT; 9564 } 9565 handle_idx = dh->next.next; 9566 } 9567 return 0; 9568 } 9569 9570 /** 9571 * Get aged-out flows. 9572 * 9573 * @param[in] dev 9574 * Pointer to the Ethernet device structure. 9575 * @param[in] context 9576 * The address of an array of pointers to the aged-out flows contexts. 9577 * @param[in] nb_countexts 9578 * The length of context array pointers. 9579 * @param[out] error 9580 * Perform verbose error reporting if not NULL. Initialized in case of 9581 * error only. 9582 * 9583 * @return 9584 * how many contexts get in success, otherwise negative errno value. 9585 * if nb_contexts is 0, return the amount of all aged contexts. 9586 * if nb_contexts is not 0 , return the amount of aged flows reported 9587 * in the context array. 9588 */ 9589 int 9590 mlx5_flow_get_aged_flows(struct rte_eth_dev *dev, void **contexts, 9591 uint32_t nb_contexts, struct rte_flow_error *error) 9592 { 9593 const struct mlx5_flow_driver_ops *fops; 9594 struct rte_flow_attr attr = { .transfer = 0 }; 9595 9596 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 9597 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 9598 return fops->get_aged_flows(dev, contexts, nb_contexts, 9599 error); 9600 } 9601 DRV_LOG(ERR, 9602 "port %u get aged flows is not supported.", 9603 dev->data->port_id); 9604 return -ENOTSUP; 9605 } 9606 9607 /* Wrapper for driver action_validate op callback */ 9608 static int 9609 flow_drv_action_validate(struct rte_eth_dev *dev, 9610 const struct rte_flow_indir_action_conf *conf, 9611 const struct rte_flow_action *action, 9612 const struct mlx5_flow_driver_ops *fops, 9613 struct rte_flow_error *error) 9614 { 9615 static const char err_msg[] = "indirect action validation unsupported"; 9616 9617 if (!fops->action_validate) { 9618 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 9619 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 9620 NULL, err_msg); 9621 return -rte_errno; 9622 } 9623 return fops->action_validate(dev, conf, action, error); 9624 } 9625 9626 /** 9627 * Destroys the shared action by handle. 9628 * 9629 * @param dev 9630 * Pointer to Ethernet device structure. 9631 * @param[in] handle 9632 * Handle for the indirect action object to be destroyed. 9633 * @param[out] error 9634 * Perform verbose error reporting if not NULL. PMDs initialize this 9635 * structure in case of error only. 9636 * 9637 * @return 9638 * 0 on success, a negative errno value otherwise and rte_errno is set. 9639 * 9640 * @note: wrapper for driver action_create op callback. 9641 */ 9642 static int 9643 mlx5_action_handle_destroy(struct rte_eth_dev *dev, 9644 struct rte_flow_action_handle *handle, 9645 struct rte_flow_error *error) 9646 { 9647 static const char err_msg[] = "indirect action destruction unsupported"; 9648 struct rte_flow_attr attr = { .transfer = 0 }; 9649 const struct mlx5_flow_driver_ops *fops = 9650 flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 9651 9652 if (!fops->action_destroy) { 9653 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 9654 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 9655 NULL, err_msg); 9656 return -rte_errno; 9657 } 9658 return fops->action_destroy(dev, handle, error); 9659 } 9660 9661 /* Wrapper for driver action_destroy op callback */ 9662 static int 9663 flow_drv_action_update(struct rte_eth_dev *dev, 9664 struct rte_flow_action_handle *handle, 9665 const void *update, 9666 const struct mlx5_flow_driver_ops *fops, 9667 struct rte_flow_error *error) 9668 { 9669 static const char err_msg[] = "indirect action update unsupported"; 9670 9671 if (!fops->action_update) { 9672 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 9673 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 9674 NULL, err_msg); 9675 return -rte_errno; 9676 } 9677 return fops->action_update(dev, handle, update, error); 9678 } 9679 9680 /* Wrapper for driver action_destroy op callback */ 9681 static int 9682 flow_drv_action_query(struct rte_eth_dev *dev, 9683 const struct rte_flow_action_handle *handle, 9684 void *data, 9685 const struct mlx5_flow_driver_ops *fops, 9686 struct rte_flow_error *error) 9687 { 9688 static const char err_msg[] = "indirect action query unsupported"; 9689 9690 if (!fops->action_query) { 9691 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 9692 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 9693 NULL, err_msg); 9694 return -rte_errno; 9695 } 9696 return fops->action_query(dev, handle, data, error); 9697 } 9698 9699 /** 9700 * Create indirect action for reuse in multiple flow rules. 9701 * 9702 * @param dev 9703 * Pointer to Ethernet device structure. 9704 * @param conf 9705 * Pointer to indirect action object configuration. 9706 * @param[in] action 9707 * Action configuration for indirect action object creation. 9708 * @param[out] error 9709 * Perform verbose error reporting if not NULL. PMDs initialize this 9710 * structure in case of error only. 9711 * @return 9712 * A valid handle in case of success, NULL otherwise and rte_errno is set. 9713 */ 9714 static struct rte_flow_action_handle * 9715 mlx5_action_handle_create(struct rte_eth_dev *dev, 9716 const struct rte_flow_indir_action_conf *conf, 9717 const struct rte_flow_action *action, 9718 struct rte_flow_error *error) 9719 { 9720 static const char err_msg[] = "indirect action creation unsupported"; 9721 struct rte_flow_attr attr = { .transfer = 0 }; 9722 const struct mlx5_flow_driver_ops *fops = 9723 flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 9724 9725 if (flow_drv_action_validate(dev, conf, action, fops, error)) 9726 return NULL; 9727 if (!fops->action_create) { 9728 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 9729 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 9730 NULL, err_msg); 9731 return NULL; 9732 } 9733 return fops->action_create(dev, conf, action, error); 9734 } 9735 9736 /** 9737 * Updates inplace the indirect action configuration pointed by *handle* 9738 * with the configuration provided as *update* argument. 9739 * The update of the indirect action configuration effects all flow rules 9740 * reusing the action via handle. 9741 * 9742 * @param dev 9743 * Pointer to Ethernet device structure. 9744 * @param[in] handle 9745 * Handle for the indirect action to be updated. 9746 * @param[in] update 9747 * Action specification used to modify the action pointed by handle. 9748 * *update* could be of same type with the action pointed by the *handle* 9749 * handle argument, or some other structures like a wrapper, depending on 9750 * the indirect action type. 9751 * @param[out] error 9752 * Perform verbose error reporting if not NULL. PMDs initialize this 9753 * structure in case of error only. 9754 * 9755 * @return 9756 * 0 on success, a negative errno value otherwise and rte_errno is set. 9757 */ 9758 static int 9759 mlx5_action_handle_update(struct rte_eth_dev *dev, 9760 struct rte_flow_action_handle *handle, 9761 const void *update, 9762 struct rte_flow_error *error) 9763 { 9764 struct rte_flow_attr attr = { .transfer = 0 }; 9765 const struct mlx5_flow_driver_ops *fops = 9766 flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 9767 int ret; 9768 9769 ret = flow_drv_action_validate(dev, NULL, 9770 (const struct rte_flow_action *)update, fops, error); 9771 if (ret) 9772 return ret; 9773 return flow_drv_action_update(dev, handle, update, fops, 9774 error); 9775 } 9776 9777 /** 9778 * Query the indirect action by handle. 9779 * 9780 * This function allows retrieving action-specific data such as counters. 9781 * Data is gathered by special action which may be present/referenced in 9782 * more than one flow rule definition. 9783 * 9784 * see @RTE_FLOW_ACTION_TYPE_COUNT 9785 * 9786 * @param dev 9787 * Pointer to Ethernet device structure. 9788 * @param[in] handle 9789 * Handle for the indirect action to query. 9790 * @param[in, out] data 9791 * Pointer to storage for the associated query data type. 9792 * @param[out] error 9793 * Perform verbose error reporting if not NULL. PMDs initialize this 9794 * structure in case of error only. 9795 * 9796 * @return 9797 * 0 on success, a negative errno value otherwise and rte_errno is set. 9798 */ 9799 static int 9800 mlx5_action_handle_query(struct rte_eth_dev *dev, 9801 const struct rte_flow_action_handle *handle, 9802 void *data, 9803 struct rte_flow_error *error) 9804 { 9805 struct rte_flow_attr attr = { .transfer = 0 }; 9806 const struct mlx5_flow_driver_ops *fops = 9807 flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 9808 9809 return flow_drv_action_query(dev, handle, data, fops, error); 9810 } 9811 9812 /** 9813 * Destroy all indirect actions (shared RSS). 9814 * 9815 * @param dev 9816 * Pointer to Ethernet device. 9817 * 9818 * @return 9819 * 0 on success, a negative errno value otherwise and rte_errno is set. 9820 */ 9821 int 9822 mlx5_action_handle_flush(struct rte_eth_dev *dev) 9823 { 9824 struct rte_flow_error error; 9825 struct mlx5_priv *priv = dev->data->dev_private; 9826 struct mlx5_shared_action_rss *shared_rss; 9827 int ret = 0; 9828 uint32_t idx; 9829 9830 ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], 9831 priv->rss_shared_actions, idx, shared_rss, next) { 9832 ret |= mlx5_action_handle_destroy(dev, 9833 (struct rte_flow_action_handle *)(uintptr_t)idx, &error); 9834 } 9835 return ret; 9836 } 9837 9838 /** 9839 * Validate existing indirect actions against current device configuration 9840 * and attach them to device resources. 9841 * 9842 * @param dev 9843 * Pointer to Ethernet device. 9844 * 9845 * @return 9846 * 0 on success, a negative errno value otherwise and rte_errno is set. 9847 */ 9848 int 9849 mlx5_action_handle_attach(struct rte_eth_dev *dev) 9850 { 9851 struct mlx5_priv *priv = dev->data->dev_private; 9852 int ret = 0; 9853 struct mlx5_ind_table_obj *ind_tbl, *ind_tbl_last; 9854 9855 LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { 9856 const char *message; 9857 uint32_t queue_idx; 9858 9859 ret = mlx5_validate_rss_queues(dev, ind_tbl->queues, 9860 ind_tbl->queues_n, 9861 &message, &queue_idx); 9862 if (ret != 0) { 9863 DRV_LOG(ERR, "Port %u cannot use queue %u in RSS: %s", 9864 dev->data->port_id, ind_tbl->queues[queue_idx], 9865 message); 9866 break; 9867 } 9868 } 9869 if (ret != 0) 9870 return ret; 9871 LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { 9872 ret = mlx5_ind_table_obj_attach(dev, ind_tbl); 9873 if (ret != 0) { 9874 DRV_LOG(ERR, "Port %u could not attach " 9875 "indirection table obj %p", 9876 dev->data->port_id, (void *)ind_tbl); 9877 goto error; 9878 } 9879 } 9880 9881 return 0; 9882 error: 9883 ind_tbl_last = ind_tbl; 9884 LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { 9885 if (ind_tbl == ind_tbl_last) 9886 break; 9887 if (mlx5_ind_table_obj_detach(dev, ind_tbl) != 0) 9888 DRV_LOG(CRIT, "Port %u could not detach " 9889 "indirection table obj %p on rollback", 9890 dev->data->port_id, (void *)ind_tbl); 9891 } 9892 return ret; 9893 } 9894 9895 /** 9896 * Detach indirect actions of the device from its resources. 9897 * 9898 * @param dev 9899 * Pointer to Ethernet device. 9900 * 9901 * @return 9902 * 0 on success, a negative errno value otherwise and rte_errno is set. 9903 */ 9904 int 9905 mlx5_action_handle_detach(struct rte_eth_dev *dev) 9906 { 9907 struct mlx5_priv *priv = dev->data->dev_private; 9908 int ret = 0; 9909 struct mlx5_ind_table_obj *ind_tbl, *ind_tbl_last; 9910 9911 LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { 9912 ret = mlx5_ind_table_obj_detach(dev, ind_tbl); 9913 if (ret != 0) { 9914 DRV_LOG(ERR, "Port %u could not detach " 9915 "indirection table obj %p", 9916 dev->data->port_id, (void *)ind_tbl); 9917 goto error; 9918 } 9919 } 9920 return 0; 9921 error: 9922 ind_tbl_last = ind_tbl; 9923 LIST_FOREACH(ind_tbl, &priv->standalone_ind_tbls, next) { 9924 if (ind_tbl == ind_tbl_last) 9925 break; 9926 if (mlx5_ind_table_obj_attach(dev, ind_tbl) != 0) 9927 DRV_LOG(CRIT, "Port %u could not attach " 9928 "indirection table obj %p on rollback", 9929 dev->data->port_id, (void *)ind_tbl); 9930 } 9931 return ret; 9932 } 9933 9934 #ifndef HAVE_MLX5DV_DR 9935 #define MLX5_DOMAIN_SYNC_FLOW ((1 << 0) | (1 << 1)) 9936 #else 9937 #define MLX5_DOMAIN_SYNC_FLOW \ 9938 (MLX5DV_DR_DOMAIN_SYNC_FLAGS_SW | MLX5DV_DR_DOMAIN_SYNC_FLAGS_HW) 9939 #endif 9940 9941 int rte_pmd_mlx5_sync_flow(uint16_t port_id, uint32_t domains) 9942 { 9943 struct rte_eth_dev *dev = &rte_eth_devices[port_id]; 9944 const struct mlx5_flow_driver_ops *fops; 9945 int ret; 9946 struct rte_flow_attr attr = { .transfer = 0 }; 9947 9948 fops = flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 9949 ret = fops->sync_domain(dev, domains, MLX5_DOMAIN_SYNC_FLOW); 9950 if (ret > 0) 9951 ret = -ret; 9952 return ret; 9953 } 9954 9955 const struct mlx5_flow_tunnel * 9956 mlx5_get_tof(const struct rte_flow_item *item, 9957 const struct rte_flow_action *action, 9958 enum mlx5_tof_rule_type *rule_type) 9959 { 9960 for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 9961 if (item->type == (typeof(item->type)) 9962 MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL) { 9963 *rule_type = MLX5_TUNNEL_OFFLOAD_MATCH_RULE; 9964 return flow_items_to_tunnel(item); 9965 } 9966 } 9967 for (; action->conf != RTE_FLOW_ACTION_TYPE_END; action++) { 9968 if (action->type == (typeof(action->type)) 9969 MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET) { 9970 *rule_type = MLX5_TUNNEL_OFFLOAD_SET_RULE; 9971 return flow_actions_to_tunnel(action); 9972 } 9973 } 9974 return NULL; 9975 } 9976 9977 /** 9978 * tunnel offload functionality is defined for DV environment only 9979 */ 9980 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 9981 __extension__ 9982 union tunnel_offload_mark { 9983 uint32_t val; 9984 struct { 9985 uint32_t app_reserve:8; 9986 uint32_t table_id:15; 9987 uint32_t transfer:1; 9988 uint32_t _unused_:8; 9989 }; 9990 }; 9991 9992 static bool 9993 mlx5_access_tunnel_offload_db 9994 (struct rte_eth_dev *dev, 9995 bool (*match)(struct rte_eth_dev *, 9996 struct mlx5_flow_tunnel *, const void *), 9997 void (*hit)(struct rte_eth_dev *, struct mlx5_flow_tunnel *, void *), 9998 void (*miss)(struct rte_eth_dev *, void *), 9999 void *ctx, bool lock_op); 10000 10001 static int 10002 flow_tunnel_add_default_miss(struct rte_eth_dev *dev, 10003 struct rte_flow *flow, 10004 const struct rte_flow_attr *attr, 10005 const struct rte_flow_action *app_actions, 10006 uint32_t flow_idx, 10007 const struct mlx5_flow_tunnel *tunnel, 10008 struct tunnel_default_miss_ctx *ctx, 10009 struct rte_flow_error *error) 10010 { 10011 struct mlx5_priv *priv = dev->data->dev_private; 10012 struct mlx5_flow *dev_flow; 10013 struct rte_flow_attr miss_attr = *attr; 10014 const struct rte_flow_item miss_items[2] = { 10015 { 10016 .type = RTE_FLOW_ITEM_TYPE_ETH, 10017 .spec = NULL, 10018 .last = NULL, 10019 .mask = NULL 10020 }, 10021 { 10022 .type = RTE_FLOW_ITEM_TYPE_END, 10023 .spec = NULL, 10024 .last = NULL, 10025 .mask = NULL 10026 } 10027 }; 10028 union tunnel_offload_mark mark_id; 10029 struct rte_flow_action_mark miss_mark; 10030 struct rte_flow_action miss_actions[3] = { 10031 [0] = { .type = RTE_FLOW_ACTION_TYPE_MARK, .conf = &miss_mark }, 10032 [2] = { .type = RTE_FLOW_ACTION_TYPE_END, .conf = NULL } 10033 }; 10034 const struct rte_flow_action_jump *jump_data; 10035 uint32_t i, flow_table = 0; /* prevent compilation warning */ 10036 struct flow_grp_info grp_info = { 10037 .external = 1, 10038 .transfer = attr->transfer, 10039 .fdb_def_rule = !!priv->fdb_def_rule, 10040 .std_tbl_fix = 0, 10041 }; 10042 int ret; 10043 10044 if (!attr->transfer) { 10045 uint32_t q_size; 10046 10047 miss_actions[1].type = RTE_FLOW_ACTION_TYPE_RSS; 10048 q_size = priv->reta_idx_n * sizeof(ctx->queue[0]); 10049 ctx->queue = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO, q_size, 10050 0, SOCKET_ID_ANY); 10051 if (!ctx->queue) 10052 return rte_flow_error_set 10053 (error, ENOMEM, 10054 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 10055 NULL, "invalid default miss RSS"); 10056 ctx->action_rss.func = RTE_ETH_HASH_FUNCTION_DEFAULT, 10057 ctx->action_rss.level = 0, 10058 ctx->action_rss.types = priv->rss_conf.rss_hf, 10059 ctx->action_rss.key_len = priv->rss_conf.rss_key_len, 10060 ctx->action_rss.queue_num = priv->reta_idx_n, 10061 ctx->action_rss.key = priv->rss_conf.rss_key, 10062 ctx->action_rss.queue = ctx->queue; 10063 if (!priv->reta_idx_n || !priv->rxqs_n) 10064 return rte_flow_error_set 10065 (error, EINVAL, 10066 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 10067 NULL, "invalid port configuration"); 10068 if (!(dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)) 10069 ctx->action_rss.types = 0; 10070 for (i = 0; i != priv->reta_idx_n; ++i) 10071 ctx->queue[i] = (*priv->reta_idx)[i]; 10072 } else { 10073 miss_actions[1].type = RTE_FLOW_ACTION_TYPE_JUMP; 10074 ctx->miss_jump.group = MLX5_TNL_MISS_FDB_JUMP_GRP; 10075 } 10076 miss_actions[1].conf = (typeof(miss_actions[1].conf))ctx->raw; 10077 for (; app_actions->type != RTE_FLOW_ACTION_TYPE_JUMP; app_actions++); 10078 jump_data = app_actions->conf; 10079 miss_attr.priority = MLX5_TNL_MISS_RULE_PRIORITY; 10080 miss_attr.group = jump_data->group; 10081 ret = mlx5_flow_group_to_table(dev, tunnel, jump_data->group, 10082 &flow_table, &grp_info, error); 10083 if (ret) 10084 return rte_flow_error_set(error, EINVAL, 10085 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 10086 NULL, "invalid tunnel id"); 10087 mark_id.app_reserve = 0; 10088 mark_id.table_id = tunnel_flow_tbl_to_id(flow_table); 10089 mark_id.transfer = !!attr->transfer; 10090 mark_id._unused_ = 0; 10091 miss_mark.id = mark_id.val; 10092 dev_flow = flow_drv_prepare(dev, flow, &miss_attr, 10093 miss_items, miss_actions, flow_idx, error); 10094 if (!dev_flow) 10095 return -rte_errno; 10096 dev_flow->flow = flow; 10097 dev_flow->external = true; 10098 dev_flow->tunnel = tunnel; 10099 dev_flow->tof_type = MLX5_TUNNEL_OFFLOAD_MISS_RULE; 10100 /* Subflow object was created, we must include one in the list. */ 10101 SILIST_INSERT(&flow->dev_handles, dev_flow->handle_idx, 10102 dev_flow->handle, next); 10103 DRV_LOG(DEBUG, 10104 "port %u tunnel type=%d id=%u miss rule priority=%u group=%u", 10105 dev->data->port_id, tunnel->app_tunnel.type, 10106 tunnel->tunnel_id, miss_attr.priority, miss_attr.group); 10107 ret = flow_drv_translate(dev, dev_flow, &miss_attr, miss_items, 10108 miss_actions, error); 10109 if (!ret) 10110 ret = flow_mreg_update_copy_table(dev, flow, miss_actions, 10111 error); 10112 10113 return ret; 10114 } 10115 10116 static const struct mlx5_flow_tbl_data_entry * 10117 tunnel_mark_decode(struct rte_eth_dev *dev, uint32_t mark) 10118 { 10119 struct mlx5_priv *priv = dev->data->dev_private; 10120 struct mlx5_dev_ctx_shared *sh = priv->sh; 10121 struct mlx5_list_entry *he; 10122 union tunnel_offload_mark mbits = { .val = mark }; 10123 union mlx5_flow_tbl_key table_key = { 10124 { 10125 .level = tunnel_id_to_flow_tbl(mbits.table_id), 10126 .id = 0, 10127 .reserved = 0, 10128 .dummy = 0, 10129 .is_fdb = !!mbits.transfer, 10130 .is_egress = 0, 10131 } 10132 }; 10133 struct mlx5_flow_cb_ctx ctx = { 10134 .data = &table_key.v64, 10135 }; 10136 10137 he = mlx5_hlist_lookup(sh->flow_tbls, table_key.v64, &ctx); 10138 return he ? 10139 container_of(he, struct mlx5_flow_tbl_data_entry, entry) : NULL; 10140 } 10141 10142 static void 10143 mlx5_flow_tunnel_grp2tbl_remove_cb(void *tool_ctx, 10144 struct mlx5_list_entry *entry) 10145 { 10146 struct mlx5_dev_ctx_shared *sh = tool_ctx; 10147 struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash); 10148 10149 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TNL_TBL_ID], 10150 tunnel_flow_tbl_to_id(tte->flow_table)); 10151 mlx5_free(tte); 10152 } 10153 10154 static int 10155 mlx5_flow_tunnel_grp2tbl_match_cb(void *tool_ctx __rte_unused, 10156 struct mlx5_list_entry *entry, void *cb_ctx) 10157 { 10158 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 10159 union tunnel_tbl_key tbl = { 10160 .val = *(uint64_t *)(ctx->data), 10161 }; 10162 struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash); 10163 10164 return tbl.tunnel_id != tte->tunnel_id || tbl.group != tte->group; 10165 } 10166 10167 static struct mlx5_list_entry * 10168 mlx5_flow_tunnel_grp2tbl_create_cb(void *tool_ctx, void *cb_ctx) 10169 { 10170 struct mlx5_dev_ctx_shared *sh = tool_ctx; 10171 struct mlx5_flow_cb_ctx *ctx = cb_ctx; 10172 struct tunnel_tbl_entry *tte; 10173 union tunnel_tbl_key tbl = { 10174 .val = *(uint64_t *)(ctx->data), 10175 }; 10176 10177 tte = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO, 10178 sizeof(*tte), 0, 10179 SOCKET_ID_ANY); 10180 if (!tte) 10181 goto err; 10182 mlx5_ipool_malloc(sh->ipool[MLX5_IPOOL_TNL_TBL_ID], 10183 &tte->flow_table); 10184 if (tte->flow_table >= MLX5_MAX_TABLES) { 10185 DRV_LOG(ERR, "Tunnel TBL ID %d exceed max limit.", 10186 tte->flow_table); 10187 mlx5_ipool_free(sh->ipool[MLX5_IPOOL_TNL_TBL_ID], 10188 tte->flow_table); 10189 goto err; 10190 } else if (!tte->flow_table) { 10191 goto err; 10192 } 10193 tte->flow_table = tunnel_id_to_flow_tbl(tte->flow_table); 10194 tte->tunnel_id = tbl.tunnel_id; 10195 tte->group = tbl.group; 10196 return &tte->hash; 10197 err: 10198 if (tte) 10199 mlx5_free(tte); 10200 return NULL; 10201 } 10202 10203 static struct mlx5_list_entry * 10204 mlx5_flow_tunnel_grp2tbl_clone_cb(void *tool_ctx __rte_unused, 10205 struct mlx5_list_entry *oentry, 10206 void *cb_ctx __rte_unused) 10207 { 10208 struct tunnel_tbl_entry *tte = mlx5_malloc(MLX5_MEM_SYS, sizeof(*tte), 10209 0, SOCKET_ID_ANY); 10210 10211 if (!tte) 10212 return NULL; 10213 memcpy(tte, oentry, sizeof(*tte)); 10214 return &tte->hash; 10215 } 10216 10217 static void 10218 mlx5_flow_tunnel_grp2tbl_clone_free_cb(void *tool_ctx __rte_unused, 10219 struct mlx5_list_entry *entry) 10220 { 10221 struct tunnel_tbl_entry *tte = container_of(entry, typeof(*tte), hash); 10222 10223 mlx5_free(tte); 10224 } 10225 10226 static uint32_t 10227 tunnel_flow_group_to_flow_table(struct rte_eth_dev *dev, 10228 const struct mlx5_flow_tunnel *tunnel, 10229 uint32_t group, uint32_t *table, 10230 struct rte_flow_error *error) 10231 { 10232 struct mlx5_list_entry *he; 10233 struct tunnel_tbl_entry *tte; 10234 union tunnel_tbl_key key = { 10235 .tunnel_id = tunnel ? tunnel->tunnel_id : 0, 10236 .group = group 10237 }; 10238 struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev); 10239 struct mlx5_hlist *group_hash; 10240 struct mlx5_flow_cb_ctx ctx = { 10241 .data = &key.val, 10242 }; 10243 10244 group_hash = tunnel ? tunnel->groups : thub->groups; 10245 he = mlx5_hlist_register(group_hash, key.val, &ctx); 10246 if (!he) 10247 return rte_flow_error_set(error, EINVAL, 10248 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 10249 NULL, 10250 "tunnel group index not supported"); 10251 tte = container_of(he, typeof(*tte), hash); 10252 *table = tte->flow_table; 10253 DRV_LOG(DEBUG, "port %u tunnel %u group=%#x table=%#x", 10254 dev->data->port_id, key.tunnel_id, group, *table); 10255 return 0; 10256 } 10257 10258 static void 10259 mlx5_flow_tunnel_free(struct rte_eth_dev *dev, 10260 struct mlx5_flow_tunnel *tunnel) 10261 { 10262 struct mlx5_priv *priv = dev->data->dev_private; 10263 struct mlx5_indexed_pool *ipool; 10264 10265 DRV_LOG(DEBUG, "port %u release pmd tunnel id=0x%x", 10266 dev->data->port_id, tunnel->tunnel_id); 10267 LIST_REMOVE(tunnel, chain); 10268 mlx5_hlist_destroy(tunnel->groups); 10269 ipool = priv->sh->ipool[MLX5_IPOOL_TUNNEL_ID]; 10270 mlx5_ipool_free(ipool, tunnel->tunnel_id); 10271 } 10272 10273 static bool 10274 mlx5_access_tunnel_offload_db 10275 (struct rte_eth_dev *dev, 10276 bool (*match)(struct rte_eth_dev *, 10277 struct mlx5_flow_tunnel *, const void *), 10278 void (*hit)(struct rte_eth_dev *, struct mlx5_flow_tunnel *, void *), 10279 void (*miss)(struct rte_eth_dev *, void *), 10280 void *ctx, bool lock_op) 10281 { 10282 bool verdict = false; 10283 struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev); 10284 struct mlx5_flow_tunnel *tunnel; 10285 10286 rte_spinlock_lock(&thub->sl); 10287 LIST_FOREACH(tunnel, &thub->tunnels, chain) { 10288 verdict = match(dev, tunnel, (const void *)ctx); 10289 if (verdict) 10290 break; 10291 } 10292 if (!lock_op) 10293 rte_spinlock_unlock(&thub->sl); 10294 if (verdict && hit) 10295 hit(dev, tunnel, ctx); 10296 if (!verdict && miss) 10297 miss(dev, ctx); 10298 if (lock_op) 10299 rte_spinlock_unlock(&thub->sl); 10300 10301 return verdict; 10302 } 10303 10304 struct tunnel_db_find_tunnel_id_ctx { 10305 uint32_t tunnel_id; 10306 struct mlx5_flow_tunnel *tunnel; 10307 }; 10308 10309 static bool 10310 find_tunnel_id_match(struct rte_eth_dev *dev, 10311 struct mlx5_flow_tunnel *tunnel, const void *x) 10312 { 10313 const struct tunnel_db_find_tunnel_id_ctx *ctx = x; 10314 10315 RTE_SET_USED(dev); 10316 return tunnel->tunnel_id == ctx->tunnel_id; 10317 } 10318 10319 static void 10320 find_tunnel_id_hit(struct rte_eth_dev *dev, 10321 struct mlx5_flow_tunnel *tunnel, void *x) 10322 { 10323 struct tunnel_db_find_tunnel_id_ctx *ctx = x; 10324 RTE_SET_USED(dev); 10325 ctx->tunnel = tunnel; 10326 } 10327 10328 static struct mlx5_flow_tunnel * 10329 mlx5_find_tunnel_id(struct rte_eth_dev *dev, uint32_t id) 10330 { 10331 struct tunnel_db_find_tunnel_id_ctx ctx = { 10332 .tunnel_id = id, 10333 }; 10334 10335 mlx5_access_tunnel_offload_db(dev, find_tunnel_id_match, 10336 find_tunnel_id_hit, NULL, &ctx, true); 10337 10338 return ctx.tunnel; 10339 } 10340 10341 static struct mlx5_flow_tunnel * 10342 mlx5_flow_tunnel_allocate(struct rte_eth_dev *dev, 10343 const struct rte_flow_tunnel *app_tunnel) 10344 { 10345 struct mlx5_priv *priv = dev->data->dev_private; 10346 struct mlx5_indexed_pool *ipool; 10347 struct mlx5_flow_tunnel *tunnel; 10348 uint32_t id; 10349 10350 ipool = priv->sh->ipool[MLX5_IPOOL_TUNNEL_ID]; 10351 tunnel = mlx5_ipool_zmalloc(ipool, &id); 10352 if (!tunnel) 10353 return NULL; 10354 if (id >= MLX5_MAX_TUNNELS) { 10355 mlx5_ipool_free(ipool, id); 10356 DRV_LOG(ERR, "Tunnel ID %d exceed max limit.", id); 10357 return NULL; 10358 } 10359 tunnel->groups = mlx5_hlist_create("tunnel groups", 64, false, true, 10360 priv->sh, 10361 mlx5_flow_tunnel_grp2tbl_create_cb, 10362 mlx5_flow_tunnel_grp2tbl_match_cb, 10363 mlx5_flow_tunnel_grp2tbl_remove_cb, 10364 mlx5_flow_tunnel_grp2tbl_clone_cb, 10365 mlx5_flow_tunnel_grp2tbl_clone_free_cb); 10366 if (!tunnel->groups) { 10367 mlx5_ipool_free(ipool, id); 10368 return NULL; 10369 } 10370 /* initiate new PMD tunnel */ 10371 memcpy(&tunnel->app_tunnel, app_tunnel, sizeof(*app_tunnel)); 10372 tunnel->tunnel_id = id; 10373 tunnel->action.type = (typeof(tunnel->action.type)) 10374 MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET; 10375 tunnel->action.conf = tunnel; 10376 tunnel->item.type = (typeof(tunnel->item.type)) 10377 MLX5_RTE_FLOW_ITEM_TYPE_TUNNEL; 10378 tunnel->item.spec = tunnel; 10379 tunnel->item.last = NULL; 10380 tunnel->item.mask = NULL; 10381 10382 DRV_LOG(DEBUG, "port %u new pmd tunnel id=0x%x", 10383 dev->data->port_id, tunnel->tunnel_id); 10384 10385 return tunnel; 10386 } 10387 10388 struct tunnel_db_get_tunnel_ctx { 10389 const struct rte_flow_tunnel *app_tunnel; 10390 struct mlx5_flow_tunnel *tunnel; 10391 }; 10392 10393 static bool get_tunnel_match(struct rte_eth_dev *dev, 10394 struct mlx5_flow_tunnel *tunnel, const void *x) 10395 { 10396 const struct tunnel_db_get_tunnel_ctx *ctx = x; 10397 10398 RTE_SET_USED(dev); 10399 return !memcmp(ctx->app_tunnel, &tunnel->app_tunnel, 10400 sizeof(*ctx->app_tunnel)); 10401 } 10402 10403 static void get_tunnel_hit(struct rte_eth_dev *dev, 10404 struct mlx5_flow_tunnel *tunnel, void *x) 10405 { 10406 /* called under tunnel spinlock protection */ 10407 struct tunnel_db_get_tunnel_ctx *ctx = x; 10408 10409 RTE_SET_USED(dev); 10410 tunnel->refctn++; 10411 ctx->tunnel = tunnel; 10412 } 10413 10414 static void get_tunnel_miss(struct rte_eth_dev *dev, void *x) 10415 { 10416 /* called under tunnel spinlock protection */ 10417 struct mlx5_flow_tunnel_hub *thub = mlx5_tunnel_hub(dev); 10418 struct tunnel_db_get_tunnel_ctx *ctx = x; 10419 10420 rte_spinlock_unlock(&thub->sl); 10421 ctx->tunnel = mlx5_flow_tunnel_allocate(dev, ctx->app_tunnel); 10422 rte_spinlock_lock(&thub->sl); 10423 if (ctx->tunnel) { 10424 ctx->tunnel->refctn = 1; 10425 LIST_INSERT_HEAD(&thub->tunnels, ctx->tunnel, chain); 10426 } 10427 } 10428 10429 10430 static int 10431 mlx5_get_flow_tunnel(struct rte_eth_dev *dev, 10432 const struct rte_flow_tunnel *app_tunnel, 10433 struct mlx5_flow_tunnel **tunnel) 10434 { 10435 struct tunnel_db_get_tunnel_ctx ctx = { 10436 .app_tunnel = app_tunnel, 10437 }; 10438 10439 mlx5_access_tunnel_offload_db(dev, get_tunnel_match, get_tunnel_hit, 10440 get_tunnel_miss, &ctx, true); 10441 *tunnel = ctx.tunnel; 10442 return ctx.tunnel ? 0 : -ENOMEM; 10443 } 10444 10445 void mlx5_release_tunnel_hub(struct mlx5_dev_ctx_shared *sh, uint16_t port_id) 10446 { 10447 struct mlx5_flow_tunnel_hub *thub = sh->tunnel_hub; 10448 10449 if (!thub) 10450 return; 10451 if (!LIST_EMPTY(&thub->tunnels)) 10452 DRV_LOG(WARNING, "port %u tunnels present", port_id); 10453 mlx5_hlist_destroy(thub->groups); 10454 mlx5_free(thub); 10455 } 10456 10457 int mlx5_alloc_tunnel_hub(struct mlx5_dev_ctx_shared *sh) 10458 { 10459 int err; 10460 struct mlx5_flow_tunnel_hub *thub; 10461 10462 thub = mlx5_malloc(MLX5_MEM_SYS | MLX5_MEM_ZERO, sizeof(*thub), 10463 0, SOCKET_ID_ANY); 10464 if (!thub) 10465 return -ENOMEM; 10466 LIST_INIT(&thub->tunnels); 10467 rte_spinlock_init(&thub->sl); 10468 thub->groups = mlx5_hlist_create("flow groups", 64, 10469 false, true, sh, 10470 mlx5_flow_tunnel_grp2tbl_create_cb, 10471 mlx5_flow_tunnel_grp2tbl_match_cb, 10472 mlx5_flow_tunnel_grp2tbl_remove_cb, 10473 mlx5_flow_tunnel_grp2tbl_clone_cb, 10474 mlx5_flow_tunnel_grp2tbl_clone_free_cb); 10475 if (!thub->groups) { 10476 err = -rte_errno; 10477 goto err; 10478 } 10479 sh->tunnel_hub = thub; 10480 10481 return 0; 10482 10483 err: 10484 if (thub->groups) 10485 mlx5_hlist_destroy(thub->groups); 10486 if (thub) 10487 mlx5_free(thub); 10488 return err; 10489 } 10490 10491 static inline int 10492 mlx5_flow_tunnel_validate(struct rte_eth_dev *dev, 10493 struct rte_flow_tunnel *tunnel, 10494 struct rte_flow_error *error) 10495 { 10496 struct mlx5_priv *priv = dev->data->dev_private; 10497 10498 if (!priv->sh->config.dv_flow_en) 10499 return rte_flow_error_set(error, ENOTSUP, 10500 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 10501 "flow DV interface is off"); 10502 if (!is_tunnel_offload_active(dev)) 10503 return rte_flow_error_set(error, ENOTSUP, 10504 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 10505 "tunnel offload was not activated"); 10506 if (!tunnel) 10507 return rte_flow_error_set(error, EINVAL, 10508 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 10509 "no application tunnel"); 10510 switch (tunnel->type) { 10511 default: 10512 return rte_flow_error_set(error, EINVAL, 10513 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 10514 "unsupported tunnel type"); 10515 case RTE_FLOW_ITEM_TYPE_VXLAN: 10516 case RTE_FLOW_ITEM_TYPE_GRE: 10517 case RTE_FLOW_ITEM_TYPE_NVGRE: 10518 case RTE_FLOW_ITEM_TYPE_GENEVE: 10519 break; 10520 } 10521 return 0; 10522 } 10523 10524 static int 10525 mlx5_flow_tunnel_decap_set(struct rte_eth_dev *dev, 10526 struct rte_flow_tunnel *app_tunnel, 10527 struct rte_flow_action **actions, 10528 uint32_t *num_of_actions, 10529 struct rte_flow_error *error) 10530 { 10531 struct mlx5_flow_tunnel *tunnel; 10532 int ret = mlx5_flow_tunnel_validate(dev, app_tunnel, error); 10533 10534 if (ret) 10535 return ret; 10536 ret = mlx5_get_flow_tunnel(dev, app_tunnel, &tunnel); 10537 if (ret < 0) { 10538 return rte_flow_error_set(error, ret, 10539 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 10540 "failed to initialize pmd tunnel"); 10541 } 10542 *actions = &tunnel->action; 10543 *num_of_actions = 1; 10544 return 0; 10545 } 10546 10547 static int 10548 mlx5_flow_tunnel_match(struct rte_eth_dev *dev, 10549 struct rte_flow_tunnel *app_tunnel, 10550 struct rte_flow_item **items, 10551 uint32_t *num_of_items, 10552 struct rte_flow_error *error) 10553 { 10554 struct mlx5_flow_tunnel *tunnel; 10555 int ret = mlx5_flow_tunnel_validate(dev, app_tunnel, error); 10556 10557 if (ret) 10558 return ret; 10559 ret = mlx5_get_flow_tunnel(dev, app_tunnel, &tunnel); 10560 if (ret < 0) { 10561 return rte_flow_error_set(error, ret, 10562 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 10563 "failed to initialize pmd tunnel"); 10564 } 10565 *items = &tunnel->item; 10566 *num_of_items = 1; 10567 return 0; 10568 } 10569 10570 struct tunnel_db_element_release_ctx { 10571 struct rte_flow_item *items; 10572 struct rte_flow_action *actions; 10573 uint32_t num_elements; 10574 struct rte_flow_error *error; 10575 int ret; 10576 }; 10577 10578 static bool 10579 tunnel_element_release_match(struct rte_eth_dev *dev, 10580 struct mlx5_flow_tunnel *tunnel, const void *x) 10581 { 10582 const struct tunnel_db_element_release_ctx *ctx = x; 10583 10584 RTE_SET_USED(dev); 10585 if (ctx->num_elements != 1) 10586 return false; 10587 else if (ctx->items) 10588 return ctx->items == &tunnel->item; 10589 else if (ctx->actions) 10590 return ctx->actions == &tunnel->action; 10591 10592 return false; 10593 } 10594 10595 static void 10596 tunnel_element_release_hit(struct rte_eth_dev *dev, 10597 struct mlx5_flow_tunnel *tunnel, void *x) 10598 { 10599 struct tunnel_db_element_release_ctx *ctx = x; 10600 ctx->ret = 0; 10601 if (!__atomic_sub_fetch(&tunnel->refctn, 1, __ATOMIC_RELAXED)) 10602 mlx5_flow_tunnel_free(dev, tunnel); 10603 } 10604 10605 static void 10606 tunnel_element_release_miss(struct rte_eth_dev *dev, void *x) 10607 { 10608 struct tunnel_db_element_release_ctx *ctx = x; 10609 RTE_SET_USED(dev); 10610 ctx->ret = rte_flow_error_set(ctx->error, EINVAL, 10611 RTE_FLOW_ERROR_TYPE_HANDLE, NULL, 10612 "invalid argument"); 10613 } 10614 10615 static int 10616 mlx5_flow_tunnel_item_release(struct rte_eth_dev *dev, 10617 struct rte_flow_item *pmd_items, 10618 uint32_t num_items, struct rte_flow_error *err) 10619 { 10620 struct tunnel_db_element_release_ctx ctx = { 10621 .items = pmd_items, 10622 .actions = NULL, 10623 .num_elements = num_items, 10624 .error = err, 10625 }; 10626 10627 mlx5_access_tunnel_offload_db(dev, tunnel_element_release_match, 10628 tunnel_element_release_hit, 10629 tunnel_element_release_miss, &ctx, false); 10630 10631 return ctx.ret; 10632 } 10633 10634 static int 10635 mlx5_flow_tunnel_action_release(struct rte_eth_dev *dev, 10636 struct rte_flow_action *pmd_actions, 10637 uint32_t num_actions, struct rte_flow_error *err) 10638 { 10639 struct tunnel_db_element_release_ctx ctx = { 10640 .items = NULL, 10641 .actions = pmd_actions, 10642 .num_elements = num_actions, 10643 .error = err, 10644 }; 10645 10646 mlx5_access_tunnel_offload_db(dev, tunnel_element_release_match, 10647 tunnel_element_release_hit, 10648 tunnel_element_release_miss, &ctx, false); 10649 10650 return ctx.ret; 10651 } 10652 10653 static int 10654 mlx5_flow_tunnel_get_restore_info(struct rte_eth_dev *dev, 10655 struct rte_mbuf *m, 10656 struct rte_flow_restore_info *info, 10657 struct rte_flow_error *err) 10658 { 10659 uint64_t ol_flags = m->ol_flags; 10660 const struct mlx5_flow_tbl_data_entry *tble; 10661 const uint64_t mask = RTE_MBUF_F_RX_FDIR | RTE_MBUF_F_RX_FDIR_ID; 10662 10663 if (!is_tunnel_offload_active(dev)) { 10664 info->flags = 0; 10665 return 0; 10666 } 10667 10668 if ((ol_flags & mask) != mask) 10669 goto err; 10670 tble = tunnel_mark_decode(dev, m->hash.fdir.hi); 10671 if (!tble) { 10672 DRV_LOG(DEBUG, "port %u invalid miss tunnel mark %#x", 10673 dev->data->port_id, m->hash.fdir.hi); 10674 goto err; 10675 } 10676 MLX5_ASSERT(tble->tunnel); 10677 memcpy(&info->tunnel, &tble->tunnel->app_tunnel, sizeof(info->tunnel)); 10678 info->group_id = tble->group_id; 10679 info->flags = RTE_FLOW_RESTORE_INFO_TUNNEL | 10680 RTE_FLOW_RESTORE_INFO_GROUP_ID | 10681 RTE_FLOW_RESTORE_INFO_ENCAPSULATED; 10682 10683 return 0; 10684 10685 err: 10686 return rte_flow_error_set(err, EINVAL, 10687 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 10688 "failed to get restore info"); 10689 } 10690 10691 #else /* HAVE_IBV_FLOW_DV_SUPPORT */ 10692 static int 10693 mlx5_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev, 10694 __rte_unused struct rte_flow_tunnel *app_tunnel, 10695 __rte_unused struct rte_flow_action **actions, 10696 __rte_unused uint32_t *num_of_actions, 10697 __rte_unused struct rte_flow_error *error) 10698 { 10699 return -ENOTSUP; 10700 } 10701 10702 static int 10703 mlx5_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev, 10704 __rte_unused struct rte_flow_tunnel *app_tunnel, 10705 __rte_unused struct rte_flow_item **items, 10706 __rte_unused uint32_t *num_of_items, 10707 __rte_unused struct rte_flow_error *error) 10708 { 10709 return -ENOTSUP; 10710 } 10711 10712 static int 10713 mlx5_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev, 10714 __rte_unused struct rte_flow_item *pmd_items, 10715 __rte_unused uint32_t num_items, 10716 __rte_unused struct rte_flow_error *err) 10717 { 10718 return -ENOTSUP; 10719 } 10720 10721 static int 10722 mlx5_flow_tunnel_action_release(__rte_unused struct rte_eth_dev *dev, 10723 __rte_unused struct rte_flow_action *pmd_action, 10724 __rte_unused uint32_t num_actions, 10725 __rte_unused struct rte_flow_error *err) 10726 { 10727 return -ENOTSUP; 10728 } 10729 10730 static int 10731 mlx5_flow_tunnel_get_restore_info(__rte_unused struct rte_eth_dev *dev, 10732 __rte_unused struct rte_mbuf *m, 10733 __rte_unused struct rte_flow_restore_info *i, 10734 __rte_unused struct rte_flow_error *err) 10735 { 10736 return -ENOTSUP; 10737 } 10738 10739 static int 10740 flow_tunnel_add_default_miss(__rte_unused struct rte_eth_dev *dev, 10741 __rte_unused struct rte_flow *flow, 10742 __rte_unused const struct rte_flow_attr *attr, 10743 __rte_unused const struct rte_flow_action *actions, 10744 __rte_unused uint32_t flow_idx, 10745 __rte_unused const struct mlx5_flow_tunnel *tunnel, 10746 __rte_unused struct tunnel_default_miss_ctx *ctx, 10747 __rte_unused struct rte_flow_error *error) 10748 { 10749 return -ENOTSUP; 10750 } 10751 10752 static struct mlx5_flow_tunnel * 10753 mlx5_find_tunnel_id(__rte_unused struct rte_eth_dev *dev, 10754 __rte_unused uint32_t id) 10755 { 10756 return NULL; 10757 } 10758 10759 static void 10760 mlx5_flow_tunnel_free(__rte_unused struct rte_eth_dev *dev, 10761 __rte_unused struct mlx5_flow_tunnel *tunnel) 10762 { 10763 } 10764 10765 static uint32_t 10766 tunnel_flow_group_to_flow_table(__rte_unused struct rte_eth_dev *dev, 10767 __rte_unused const struct mlx5_flow_tunnel *t, 10768 __rte_unused uint32_t group, 10769 __rte_unused uint32_t *table, 10770 struct rte_flow_error *error) 10771 { 10772 return rte_flow_error_set(error, ENOTSUP, 10773 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 10774 "tunnel offload requires DV support"); 10775 } 10776 10777 void 10778 mlx5_release_tunnel_hub(__rte_unused struct mlx5_dev_ctx_shared *sh, 10779 __rte_unused uint16_t port_id) 10780 { 10781 } 10782 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */ 10783 10784 /* Flex flow item API */ 10785 static struct rte_flow_item_flex_handle * 10786 mlx5_flow_flex_item_create(struct rte_eth_dev *dev, 10787 const struct rte_flow_item_flex_conf *conf, 10788 struct rte_flow_error *error) 10789 { 10790 static const char err_msg[] = "flex item creation unsupported"; 10791 struct mlx5_priv *priv = dev->data->dev_private; 10792 struct rte_flow_attr attr = { .transfer = 0 }; 10793 const struct mlx5_flow_driver_ops *fops = 10794 flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 10795 10796 if (!priv->pci_dev) { 10797 rte_flow_error_set(error, ENOTSUP, 10798 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 10799 "create flex item on PF only"); 10800 return NULL; 10801 } 10802 switch (priv->pci_dev->id.device_id) { 10803 case PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF: 10804 case PCI_DEVICE_ID_MELLANOX_CONNECTX7BF: 10805 break; 10806 default: 10807 rte_flow_error_set(error, ENOTSUP, 10808 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, 10809 "flex item available on BlueField ports only"); 10810 return NULL; 10811 } 10812 if (!fops->item_create) { 10813 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 10814 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 10815 NULL, err_msg); 10816 return NULL; 10817 } 10818 return fops->item_create(dev, conf, error); 10819 } 10820 10821 static int 10822 mlx5_flow_flex_item_release(struct rte_eth_dev *dev, 10823 const struct rte_flow_item_flex_handle *handle, 10824 struct rte_flow_error *error) 10825 { 10826 static const char err_msg[] = "flex item release unsupported"; 10827 struct rte_flow_attr attr = { .transfer = 0 }; 10828 const struct mlx5_flow_driver_ops *fops = 10829 flow_get_drv_ops(flow_get_drv_type(dev, &attr)); 10830 10831 if (!fops->item_release) { 10832 DRV_LOG(ERR, "port %u %s.", dev->data->port_id, err_msg); 10833 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, 10834 NULL, err_msg); 10835 return -rte_errno; 10836 } 10837 return fops->item_release(dev, handle, error); 10838 } 10839 10840 static void 10841 mlx5_dbg__print_pattern(const struct rte_flow_item *item) 10842 { 10843 int ret; 10844 struct rte_flow_error error; 10845 10846 for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 10847 char *item_name; 10848 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR, &item_name, 10849 sizeof(item_name), 10850 (void *)(uintptr_t)item->type, &error); 10851 if (ret > 0) 10852 printf("%s ", item_name); 10853 else 10854 printf("%d\n", (int)item->type); 10855 } 10856 printf("END\n"); 10857 } 10858 10859 static int 10860 mlx5_flow_is_std_vxlan_port(const struct rte_flow_item *udp_item) 10861 { 10862 const struct rte_flow_item_udp *spec = udp_item->spec; 10863 const struct rte_flow_item_udp *mask = udp_item->mask; 10864 uint16_t udp_dport = 0; 10865 10866 if (spec != NULL) { 10867 if (!mask) 10868 mask = &rte_flow_item_udp_mask; 10869 udp_dport = rte_be_to_cpu_16(spec->hdr.dst_port & 10870 mask->hdr.dst_port); 10871 } 10872 return (!udp_dport || udp_dport == MLX5_UDP_PORT_VXLAN); 10873 } 10874 10875 static const struct mlx5_flow_expand_node * 10876 mlx5_flow_expand_rss_adjust_node(const struct rte_flow_item *pattern, 10877 unsigned int item_idx, 10878 const struct mlx5_flow_expand_node graph[], 10879 const struct mlx5_flow_expand_node *node) 10880 { 10881 const struct rte_flow_item *item = pattern + item_idx, *prev_item; 10882 10883 if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN && 10884 node != NULL && 10885 node->type == RTE_FLOW_ITEM_TYPE_VXLAN) { 10886 /* 10887 * The expansion node is VXLAN and it is also the last 10888 * expandable item in the pattern, so need to continue 10889 * expansion of the inner tunnel. 10890 */ 10891 MLX5_ASSERT(item_idx > 0); 10892 prev_item = pattern + item_idx - 1; 10893 MLX5_ASSERT(prev_item->type == RTE_FLOW_ITEM_TYPE_UDP); 10894 if (mlx5_flow_is_std_vxlan_port(prev_item)) 10895 return &graph[MLX5_EXPANSION_STD_VXLAN]; 10896 return &graph[MLX5_EXPANSION_L3_VXLAN]; 10897 } 10898 return node; 10899 } 10900 10901 /* Map of Verbs to Flow priority with 8 Verbs priorities. */ 10902 static const uint32_t priority_map_3[][MLX5_PRIORITY_MAP_MAX] = { 10903 { 0, 1, 2 }, { 2, 3, 4 }, { 5, 6, 7 }, 10904 }; 10905 10906 /* Map of Verbs to Flow priority with 16 Verbs priorities. */ 10907 static const uint32_t priority_map_5[][MLX5_PRIORITY_MAP_MAX] = { 10908 { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, 10909 { 9, 10, 11 }, { 12, 13, 14 }, 10910 }; 10911 10912 /** 10913 * Discover the number of available flow priorities. 10914 * 10915 * @param dev 10916 * Ethernet device. 10917 * 10918 * @return 10919 * On success, number of available flow priorities. 10920 * On failure, a negative errno-style code and rte_errno is set. 10921 */ 10922 int 10923 mlx5_flow_discover_priorities(struct rte_eth_dev *dev) 10924 { 10925 static const uint16_t vprio[] = {8, 16}; 10926 const struct mlx5_priv *priv = dev->data->dev_private; 10927 const struct mlx5_flow_driver_ops *fops; 10928 enum mlx5_flow_drv_type type; 10929 int ret; 10930 10931 type = mlx5_flow_os_get_type(); 10932 if (type == MLX5_FLOW_TYPE_MAX) { 10933 type = MLX5_FLOW_TYPE_VERBS; 10934 if (priv->sh->cdev->config.devx && priv->sh->config.dv_flow_en) 10935 type = MLX5_FLOW_TYPE_DV; 10936 } 10937 fops = flow_get_drv_ops(type); 10938 if (fops->discover_priorities == NULL) { 10939 DRV_LOG(ERR, "Priority discovery not supported"); 10940 rte_errno = ENOTSUP; 10941 return -rte_errno; 10942 } 10943 ret = fops->discover_priorities(dev, vprio, RTE_DIM(vprio)); 10944 if (ret < 0) 10945 return ret; 10946 switch (ret) { 10947 case 8: 10948 ret = RTE_DIM(priority_map_3); 10949 break; 10950 case 16: 10951 ret = RTE_DIM(priority_map_5); 10952 break; 10953 default: 10954 rte_errno = ENOTSUP; 10955 DRV_LOG(ERR, 10956 "port %u maximum priority: %d expected 8/16", 10957 dev->data->port_id, ret); 10958 return -rte_errno; 10959 } 10960 DRV_LOG(INFO, "port %u supported flow priorities:" 10961 " 0-%d for ingress or egress root table," 10962 " 0-%d for non-root table or transfer root table.", 10963 dev->data->port_id, ret - 2, 10964 MLX5_NON_ROOT_FLOW_MAX_PRIO - 1); 10965 return ret; 10966 } 10967 10968 /** 10969 * Adjust flow priority based on the highest layer and the request priority. 10970 * 10971 * @param[in] dev 10972 * Pointer to the Ethernet device structure. 10973 * @param[in] priority 10974 * The rule base priority. 10975 * @param[in] subpriority 10976 * The priority based on the items. 10977 * 10978 * @return 10979 * The new priority. 10980 */ 10981 uint32_t 10982 mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority, 10983 uint32_t subpriority) 10984 { 10985 uint32_t res = 0; 10986 struct mlx5_priv *priv = dev->data->dev_private; 10987 10988 switch (priv->sh->flow_max_priority) { 10989 case RTE_DIM(priority_map_3): 10990 res = priority_map_3[priority][subpriority]; 10991 break; 10992 case RTE_DIM(priority_map_5): 10993 res = priority_map_5[priority][subpriority]; 10994 break; 10995 } 10996 return res; 10997 } 10998 10999 /** 11000 * Get the priority for sending traffic to kernel table. 11001 * 11002 * @param[in] dev 11003 * Pointer to the Ethernet device structure. 11004 * 11005 * @return 11006 * On success: the value of priority for sending traffic to kernel table 11007 * On failure: -1 11008 */ 11009 uint32_t 11010 mlx5_get_send_to_kernel_priority(struct rte_eth_dev *dev) 11011 { 11012 struct mlx5_priv *priv = dev->data->dev_private; 11013 uint32_t res; 11014 11015 switch (priv->sh->flow_max_priority) { 11016 case RTE_DIM(priority_map_5): 11017 res = 15; 11018 break; 11019 case RTE_DIM(priority_map_3): 11020 res = 7; 11021 break; 11022 default: 11023 DRV_LOG(ERR, 11024 "port %u maximum priority: %d expected 8/16", 11025 dev->data->port_id, priv->sh->flow_max_priority); 11026 res = (uint32_t)-1; 11027 } 11028 return res; 11029 } 11030 11031 /** 11032 * Get the E-Switch Manager vport id. 11033 * 11034 * @param[in] dev 11035 * Pointer to the Ethernet device structure. 11036 * 11037 * @return 11038 * The vport id. 11039 */ 11040 int16_t mlx5_flow_get_esw_manager_vport_id(struct rte_eth_dev *dev) 11041 { 11042 struct mlx5_priv *priv = dev->data->dev_private; 11043 struct mlx5_common_device *cdev = priv->sh->cdev; 11044 11045 /* New FW exposes E-Switch Manager vport ID, can use it directly. */ 11046 if (cdev->config.hca_attr.esw_mgr_vport_id_valid) 11047 return (int16_t)cdev->config.hca_attr.esw_mgr_vport_id; 11048 11049 if (priv->pci_dev == NULL) 11050 return 0; 11051 switch (priv->pci_dev->id.device_id) { 11052 case PCI_DEVICE_ID_MELLANOX_CONNECTX5BF: 11053 case PCI_DEVICE_ID_MELLANOX_CONNECTX6DXBF: 11054 case PCI_DEVICE_ID_MELLANOX_CONNECTX7BF: 11055 /* 11056 * In old FW which doesn't expose the E-Switch Manager vport ID in the capability, 11057 * only the BF embedded CPUs control the E-Switch Manager port. Hence, 11058 * ECPF vport ID is selected and not the host port (0) in any BF case. 11059 */ 11060 return (int16_t)MLX5_ECPF_VPORT_ID; 11061 default: 11062 return MLX5_PF_VPORT_ID; 11063 } 11064 } 11065 11066 /** 11067 * Parse item to get the vport id. 11068 * 11069 * @param[in] dev 11070 * Pointer to the Ethernet device structure. 11071 * @param[in] item 11072 * The src port id match item. 11073 * @param[out] vport_id 11074 * Pointer to put the vport id. 11075 * @param[out] all_ports 11076 * Indicate if the item matches all ports. 11077 * @param[out] error 11078 * Pointer to error structure. 11079 * 11080 * @return 11081 * 0 on success, a negative errno value otherwise and rte_errno is set. 11082 */ 11083 int mlx5_flow_get_item_vport_id(struct rte_eth_dev *dev, 11084 const struct rte_flow_item *item, 11085 uint16_t *vport_id, 11086 bool *all_ports, 11087 struct rte_flow_error *error) 11088 { 11089 struct mlx5_priv *port_priv; 11090 const struct rte_flow_item_port_id *pid_v; 11091 uint32_t esw_mgr_port; 11092 11093 if (item->type != RTE_FLOW_ITEM_TYPE_PORT_ID && 11094 item->type != RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) 11095 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 11096 NULL, "Incorrect item type."); 11097 pid_v = item->spec; 11098 if (!pid_v) { 11099 if (all_ports) 11100 *all_ports = (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT); 11101 return 0; 11102 } 11103 if (all_ports) 11104 *all_ports = false; 11105 esw_mgr_port = (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) ? 11106 MLX5_REPRESENTED_PORT_ESW_MGR : MLX5_PORT_ESW_MGR; 11107 if (pid_v->id == esw_mgr_port) { 11108 *vport_id = mlx5_flow_get_esw_manager_vport_id(dev); 11109 } else { 11110 port_priv = mlx5_port_to_eswitch_info(pid_v->id, false); 11111 if (!port_priv) 11112 return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 11113 NULL, "Failed to get port info."); 11114 *vport_id = port_priv->representor_id; 11115 } 11116 11117 return 0; 11118 } 11119