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