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