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