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