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