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