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