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