1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2016 6WIND S.A. 3 * Copyright 2016 Mellanox Technologies, Ltd 4 */ 5 6 #include <netinet/in.h> 7 #include <sys/queue.h> 8 #include <stdalign.h> 9 #include <stdint.h> 10 #include <string.h> 11 12 /* Verbs header. */ 13 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 14 #ifdef PEDANTIC 15 #pragma GCC diagnostic ignored "-Wpedantic" 16 #endif 17 #include <infiniband/verbs.h> 18 #ifdef PEDANTIC 19 #pragma GCC diagnostic error "-Wpedantic" 20 #endif 21 22 #include <rte_common.h> 23 #include <rte_ether.h> 24 #include <rte_ethdev_driver.h> 25 #include <rte_flow.h> 26 #include <rte_flow_driver.h> 27 #include <rte_malloc.h> 28 #include <rte_ip.h> 29 30 #include <mlx5_glue.h> 31 #include <mlx5_devx_cmds.h> 32 #include <mlx5_prm.h> 33 34 #include "mlx5_defs.h" 35 #include "mlx5.h" 36 #include "mlx5_flow.h" 37 #include "mlx5_rxtx.h" 38 39 /* Dev ops structure defined in mlx5.c */ 40 extern const struct eth_dev_ops mlx5_dev_ops; 41 extern const struct eth_dev_ops mlx5_dev_ops_isolate; 42 43 /** Device flow drivers. */ 44 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 45 extern const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops; 46 #endif 47 extern const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops; 48 49 const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops; 50 51 const struct mlx5_flow_driver_ops *flow_drv_ops[] = { 52 [MLX5_FLOW_TYPE_MIN] = &mlx5_flow_null_drv_ops, 53 #ifdef HAVE_IBV_FLOW_DV_SUPPORT 54 [MLX5_FLOW_TYPE_DV] = &mlx5_flow_dv_drv_ops, 55 #endif 56 [MLX5_FLOW_TYPE_VERBS] = &mlx5_flow_verbs_drv_ops, 57 [MLX5_FLOW_TYPE_MAX] = &mlx5_flow_null_drv_ops 58 }; 59 60 enum mlx5_expansion { 61 MLX5_EXPANSION_ROOT, 62 MLX5_EXPANSION_ROOT_OUTER, 63 MLX5_EXPANSION_ROOT_ETH_VLAN, 64 MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN, 65 MLX5_EXPANSION_OUTER_ETH, 66 MLX5_EXPANSION_OUTER_ETH_VLAN, 67 MLX5_EXPANSION_OUTER_VLAN, 68 MLX5_EXPANSION_OUTER_IPV4, 69 MLX5_EXPANSION_OUTER_IPV4_UDP, 70 MLX5_EXPANSION_OUTER_IPV4_TCP, 71 MLX5_EXPANSION_OUTER_IPV6, 72 MLX5_EXPANSION_OUTER_IPV6_UDP, 73 MLX5_EXPANSION_OUTER_IPV6_TCP, 74 MLX5_EXPANSION_VXLAN, 75 MLX5_EXPANSION_VXLAN_GPE, 76 MLX5_EXPANSION_GRE, 77 MLX5_EXPANSION_MPLS, 78 MLX5_EXPANSION_ETH, 79 MLX5_EXPANSION_ETH_VLAN, 80 MLX5_EXPANSION_VLAN, 81 MLX5_EXPANSION_IPV4, 82 MLX5_EXPANSION_IPV4_UDP, 83 MLX5_EXPANSION_IPV4_TCP, 84 MLX5_EXPANSION_IPV6, 85 MLX5_EXPANSION_IPV6_UDP, 86 MLX5_EXPANSION_IPV6_TCP, 87 }; 88 89 /** Supported expansion of items. */ 90 static const struct rte_flow_expand_node mlx5_support_expansion[] = { 91 [MLX5_EXPANSION_ROOT] = { 92 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 93 MLX5_EXPANSION_IPV4, 94 MLX5_EXPANSION_IPV6), 95 .type = RTE_FLOW_ITEM_TYPE_END, 96 }, 97 [MLX5_EXPANSION_ROOT_OUTER] = { 98 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_ETH, 99 MLX5_EXPANSION_OUTER_IPV4, 100 MLX5_EXPANSION_OUTER_IPV6), 101 .type = RTE_FLOW_ITEM_TYPE_END, 102 }, 103 [MLX5_EXPANSION_ROOT_ETH_VLAN] = { 104 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH_VLAN), 105 .type = RTE_FLOW_ITEM_TYPE_END, 106 }, 107 [MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN] = { 108 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_ETH_VLAN), 109 .type = RTE_FLOW_ITEM_TYPE_END, 110 }, 111 [MLX5_EXPANSION_OUTER_ETH] = { 112 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4, 113 MLX5_EXPANSION_OUTER_IPV6, 114 MLX5_EXPANSION_MPLS), 115 .type = RTE_FLOW_ITEM_TYPE_ETH, 116 .rss_types = 0, 117 }, 118 [MLX5_EXPANSION_OUTER_ETH_VLAN] = { 119 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_VLAN), 120 .type = RTE_FLOW_ITEM_TYPE_ETH, 121 .rss_types = 0, 122 }, 123 [MLX5_EXPANSION_OUTER_VLAN] = { 124 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_OUTER_IPV4, 125 MLX5_EXPANSION_OUTER_IPV6), 126 .type = RTE_FLOW_ITEM_TYPE_VLAN, 127 }, 128 [MLX5_EXPANSION_OUTER_IPV4] = { 129 .next = RTE_FLOW_EXPAND_RSS_NEXT 130 (MLX5_EXPANSION_OUTER_IPV4_UDP, 131 MLX5_EXPANSION_OUTER_IPV4_TCP, 132 MLX5_EXPANSION_GRE, 133 MLX5_EXPANSION_IPV4, 134 MLX5_EXPANSION_IPV6), 135 .type = RTE_FLOW_ITEM_TYPE_IPV4, 136 .rss_types = ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 | 137 ETH_RSS_NONFRAG_IPV4_OTHER, 138 }, 139 [MLX5_EXPANSION_OUTER_IPV4_UDP] = { 140 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN, 141 MLX5_EXPANSION_VXLAN_GPE), 142 .type = RTE_FLOW_ITEM_TYPE_UDP, 143 .rss_types = ETH_RSS_NONFRAG_IPV4_UDP, 144 }, 145 [MLX5_EXPANSION_OUTER_IPV4_TCP] = { 146 .type = RTE_FLOW_ITEM_TYPE_TCP, 147 .rss_types = ETH_RSS_NONFRAG_IPV4_TCP, 148 }, 149 [MLX5_EXPANSION_OUTER_IPV6] = { 150 .next = RTE_FLOW_EXPAND_RSS_NEXT 151 (MLX5_EXPANSION_OUTER_IPV6_UDP, 152 MLX5_EXPANSION_OUTER_IPV6_TCP, 153 MLX5_EXPANSION_IPV4, 154 MLX5_EXPANSION_IPV6), 155 .type = RTE_FLOW_ITEM_TYPE_IPV6, 156 .rss_types = ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 | 157 ETH_RSS_NONFRAG_IPV6_OTHER, 158 }, 159 [MLX5_EXPANSION_OUTER_IPV6_UDP] = { 160 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VXLAN, 161 MLX5_EXPANSION_VXLAN_GPE), 162 .type = RTE_FLOW_ITEM_TYPE_UDP, 163 .rss_types = ETH_RSS_NONFRAG_IPV6_UDP, 164 }, 165 [MLX5_EXPANSION_OUTER_IPV6_TCP] = { 166 .type = RTE_FLOW_ITEM_TYPE_TCP, 167 .rss_types = ETH_RSS_NONFRAG_IPV6_TCP, 168 }, 169 [MLX5_EXPANSION_VXLAN] = { 170 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 171 MLX5_EXPANSION_IPV4, 172 MLX5_EXPANSION_IPV6), 173 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 174 }, 175 [MLX5_EXPANSION_VXLAN_GPE] = { 176 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH, 177 MLX5_EXPANSION_IPV4, 178 MLX5_EXPANSION_IPV6), 179 .type = RTE_FLOW_ITEM_TYPE_VXLAN_GPE, 180 }, 181 [MLX5_EXPANSION_GRE] = { 182 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4), 183 .type = RTE_FLOW_ITEM_TYPE_GRE, 184 }, 185 [MLX5_EXPANSION_MPLS] = { 186 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 187 MLX5_EXPANSION_IPV6), 188 .type = RTE_FLOW_ITEM_TYPE_MPLS, 189 }, 190 [MLX5_EXPANSION_ETH] = { 191 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 192 MLX5_EXPANSION_IPV6), 193 .type = RTE_FLOW_ITEM_TYPE_ETH, 194 }, 195 [MLX5_EXPANSION_ETH_VLAN] = { 196 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_VLAN), 197 .type = RTE_FLOW_ITEM_TYPE_ETH, 198 }, 199 [MLX5_EXPANSION_VLAN] = { 200 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4, 201 MLX5_EXPANSION_IPV6), 202 .type = RTE_FLOW_ITEM_TYPE_VLAN, 203 }, 204 [MLX5_EXPANSION_IPV4] = { 205 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV4_UDP, 206 MLX5_EXPANSION_IPV4_TCP), 207 .type = RTE_FLOW_ITEM_TYPE_IPV4, 208 .rss_types = ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 | 209 ETH_RSS_NONFRAG_IPV4_OTHER, 210 }, 211 [MLX5_EXPANSION_IPV4_UDP] = { 212 .type = RTE_FLOW_ITEM_TYPE_UDP, 213 .rss_types = ETH_RSS_NONFRAG_IPV4_UDP, 214 }, 215 [MLX5_EXPANSION_IPV4_TCP] = { 216 .type = RTE_FLOW_ITEM_TYPE_TCP, 217 .rss_types = ETH_RSS_NONFRAG_IPV4_TCP, 218 }, 219 [MLX5_EXPANSION_IPV6] = { 220 .next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_IPV6_UDP, 221 MLX5_EXPANSION_IPV6_TCP), 222 .type = RTE_FLOW_ITEM_TYPE_IPV6, 223 .rss_types = ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 | 224 ETH_RSS_NONFRAG_IPV6_OTHER, 225 }, 226 [MLX5_EXPANSION_IPV6_UDP] = { 227 .type = RTE_FLOW_ITEM_TYPE_UDP, 228 .rss_types = ETH_RSS_NONFRAG_IPV6_UDP, 229 }, 230 [MLX5_EXPANSION_IPV6_TCP] = { 231 .type = RTE_FLOW_ITEM_TYPE_TCP, 232 .rss_types = ETH_RSS_NONFRAG_IPV6_TCP, 233 }, 234 }; 235 236 static const struct rte_flow_ops mlx5_flow_ops = { 237 .validate = mlx5_flow_validate, 238 .create = mlx5_flow_create, 239 .destroy = mlx5_flow_destroy, 240 .flush = mlx5_flow_flush, 241 .isolate = mlx5_flow_isolate, 242 .query = mlx5_flow_query, 243 .dev_dump = mlx5_flow_dev_dump, 244 }; 245 246 /* Convert FDIR request to Generic flow. */ 247 struct mlx5_fdir { 248 struct rte_flow_attr attr; 249 struct rte_flow_item items[4]; 250 struct rte_flow_item_eth l2; 251 struct rte_flow_item_eth l2_mask; 252 union { 253 struct rte_flow_item_ipv4 ipv4; 254 struct rte_flow_item_ipv6 ipv6; 255 } l3; 256 union { 257 struct rte_flow_item_ipv4 ipv4; 258 struct rte_flow_item_ipv6 ipv6; 259 } l3_mask; 260 union { 261 struct rte_flow_item_udp udp; 262 struct rte_flow_item_tcp tcp; 263 } l4; 264 union { 265 struct rte_flow_item_udp udp; 266 struct rte_flow_item_tcp tcp; 267 } l4_mask; 268 struct rte_flow_action actions[2]; 269 struct rte_flow_action_queue queue; 270 }; 271 272 /* Map of Verbs to Flow priority with 8 Verbs priorities. */ 273 static const uint32_t priority_map_3[][MLX5_PRIORITY_MAP_MAX] = { 274 { 0, 1, 2 }, { 2, 3, 4 }, { 5, 6, 7 }, 275 }; 276 277 /* Map of Verbs to Flow priority with 16 Verbs priorities. */ 278 static const uint32_t priority_map_5[][MLX5_PRIORITY_MAP_MAX] = { 279 { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, 280 { 9, 10, 11 }, { 12, 13, 14 }, 281 }; 282 283 /* Tunnel information. */ 284 struct mlx5_flow_tunnel_info { 285 uint64_t tunnel; /**< Tunnel bit (see MLX5_FLOW_*). */ 286 uint32_t ptype; /**< Tunnel Ptype (see RTE_PTYPE_*). */ 287 }; 288 289 static struct mlx5_flow_tunnel_info tunnels_info[] = { 290 { 291 .tunnel = MLX5_FLOW_LAYER_VXLAN, 292 .ptype = RTE_PTYPE_TUNNEL_VXLAN | RTE_PTYPE_L4_UDP, 293 }, 294 { 295 .tunnel = MLX5_FLOW_LAYER_GENEVE, 296 .ptype = RTE_PTYPE_TUNNEL_GENEVE | RTE_PTYPE_L4_UDP, 297 }, 298 { 299 .tunnel = MLX5_FLOW_LAYER_VXLAN_GPE, 300 .ptype = RTE_PTYPE_TUNNEL_VXLAN_GPE | RTE_PTYPE_L4_UDP, 301 }, 302 { 303 .tunnel = MLX5_FLOW_LAYER_GRE, 304 .ptype = RTE_PTYPE_TUNNEL_GRE, 305 }, 306 { 307 .tunnel = MLX5_FLOW_LAYER_MPLS | MLX5_FLOW_LAYER_OUTER_L4_UDP, 308 .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_UDP | RTE_PTYPE_L4_UDP, 309 }, 310 { 311 .tunnel = MLX5_FLOW_LAYER_MPLS, 312 .ptype = RTE_PTYPE_TUNNEL_MPLS_IN_GRE, 313 }, 314 { 315 .tunnel = MLX5_FLOW_LAYER_NVGRE, 316 .ptype = RTE_PTYPE_TUNNEL_NVGRE, 317 }, 318 { 319 .tunnel = MLX5_FLOW_LAYER_IPIP, 320 .ptype = RTE_PTYPE_TUNNEL_IP, 321 }, 322 { 323 .tunnel = MLX5_FLOW_LAYER_IPV6_ENCAP, 324 .ptype = RTE_PTYPE_TUNNEL_IP, 325 }, 326 { 327 .tunnel = MLX5_FLOW_LAYER_GTP, 328 .ptype = RTE_PTYPE_TUNNEL_GTPU, 329 }, 330 }; 331 332 /** 333 * Translate tag ID to register. 334 * 335 * @param[in] dev 336 * Pointer to the Ethernet device structure. 337 * @param[in] feature 338 * The feature that request the register. 339 * @param[in] id 340 * The request register ID. 341 * @param[out] error 342 * Error description in case of any. 343 * 344 * @return 345 * The request register on success, a negative errno 346 * value otherwise and rte_errno is set. 347 */ 348 int 349 mlx5_flow_get_reg_id(struct rte_eth_dev *dev, 350 enum mlx5_feature_name feature, 351 uint32_t id, 352 struct rte_flow_error *error) 353 { 354 struct mlx5_priv *priv = dev->data->dev_private; 355 struct mlx5_dev_config *config = &priv->config; 356 enum modify_reg start_reg; 357 bool skip_mtr_reg = false; 358 359 switch (feature) { 360 case MLX5_HAIRPIN_RX: 361 return REG_B; 362 case MLX5_HAIRPIN_TX: 363 return REG_A; 364 case MLX5_METADATA_RX: 365 switch (config->dv_xmeta_en) { 366 case MLX5_XMETA_MODE_LEGACY: 367 return REG_B; 368 case MLX5_XMETA_MODE_META16: 369 return REG_C_0; 370 case MLX5_XMETA_MODE_META32: 371 return REG_C_1; 372 } 373 break; 374 case MLX5_METADATA_TX: 375 return REG_A; 376 case MLX5_METADATA_FDB: 377 switch (config->dv_xmeta_en) { 378 case MLX5_XMETA_MODE_LEGACY: 379 return REG_NONE; 380 case MLX5_XMETA_MODE_META16: 381 return REG_C_0; 382 case MLX5_XMETA_MODE_META32: 383 return REG_C_1; 384 } 385 break; 386 case MLX5_FLOW_MARK: 387 switch (config->dv_xmeta_en) { 388 case MLX5_XMETA_MODE_LEGACY: 389 return REG_NONE; 390 case MLX5_XMETA_MODE_META16: 391 return REG_C_1; 392 case MLX5_XMETA_MODE_META32: 393 return REG_C_0; 394 } 395 break; 396 case MLX5_MTR_SFX: 397 /* 398 * If meter color and flow match share one register, flow match 399 * should use the meter color register for match. 400 */ 401 if (priv->mtr_reg_share) 402 return priv->mtr_color_reg; 403 else 404 return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : 405 REG_C_3; 406 case MLX5_MTR_COLOR: 407 MLX5_ASSERT(priv->mtr_color_reg != REG_NONE); 408 return priv->mtr_color_reg; 409 case MLX5_COPY_MARK: 410 /* 411 * Metadata COPY_MARK register using is in meter suffix sub 412 * flow while with meter. It's safe to share the same register. 413 */ 414 return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3; 415 case MLX5_APP_TAG: 416 /* 417 * If meter is enable, it will engage the register for color 418 * match and flow match. If meter color match is not using the 419 * REG_C_2, need to skip the REG_C_x be used by meter color 420 * match. 421 * If meter is disable, free to use all available registers. 422 */ 423 start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_2 : 424 (priv->mtr_reg_share ? REG_C_3 : REG_C_4); 425 skip_mtr_reg = !!(priv->mtr_en && start_reg == REG_C_2); 426 if (id > (REG_C_7 - start_reg)) 427 return rte_flow_error_set(error, EINVAL, 428 RTE_FLOW_ERROR_TYPE_ITEM, 429 NULL, "invalid tag id"); 430 if (config->flow_mreg_c[id + start_reg - REG_C_0] == REG_NONE) 431 return rte_flow_error_set(error, ENOTSUP, 432 RTE_FLOW_ERROR_TYPE_ITEM, 433 NULL, "unsupported tag id"); 434 /* 435 * This case means meter is using the REG_C_x great than 2. 436 * Take care not to conflict with meter color REG_C_x. 437 * If the available index REG_C_y >= REG_C_x, skip the 438 * color register. 439 */ 440 if (skip_mtr_reg && config->flow_mreg_c 441 [id + start_reg - REG_C_0] >= priv->mtr_color_reg) { 442 if (config->flow_mreg_c 443 [id + 1 + start_reg - REG_C_0] != REG_NONE) 444 return config->flow_mreg_c 445 [id + 1 + start_reg - REG_C_0]; 446 return rte_flow_error_set(error, ENOTSUP, 447 RTE_FLOW_ERROR_TYPE_ITEM, 448 NULL, "unsupported tag id"); 449 } 450 return config->flow_mreg_c[id + start_reg - REG_C_0]; 451 } 452 MLX5_ASSERT(false); 453 return rte_flow_error_set(error, EINVAL, 454 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 455 NULL, "invalid feature name"); 456 } 457 458 /** 459 * Check extensive flow metadata register support. 460 * 461 * @param dev 462 * Pointer to rte_eth_dev structure. 463 * 464 * @return 465 * True if device supports extensive flow metadata register, otherwise false. 466 */ 467 bool 468 mlx5_flow_ext_mreg_supported(struct rte_eth_dev *dev) 469 { 470 struct mlx5_priv *priv = dev->data->dev_private; 471 struct mlx5_dev_config *config = &priv->config; 472 473 /* 474 * Having available reg_c can be regarded inclusively as supporting 475 * extensive flow metadata register, which could mean, 476 * - metadata register copy action by modify header. 477 * - 16 modify header actions is supported. 478 * - reg_c's are preserved across different domain (FDB and NIC) on 479 * packet loopback by flow lookup miss. 480 */ 481 return config->flow_mreg_c[2] != REG_NONE; 482 } 483 484 /** 485 * Discover the maximum number of priority available. 486 * 487 * @param[in] dev 488 * Pointer to the Ethernet device structure. 489 * 490 * @return 491 * number of supported flow priority on success, a negative errno 492 * value otherwise and rte_errno is set. 493 */ 494 int 495 mlx5_flow_discover_priorities(struct rte_eth_dev *dev) 496 { 497 struct mlx5_priv *priv = dev->data->dev_private; 498 struct { 499 struct ibv_flow_attr attr; 500 struct ibv_flow_spec_eth eth; 501 struct ibv_flow_spec_action_drop drop; 502 } flow_attr = { 503 .attr = { 504 .num_of_specs = 2, 505 .port = (uint8_t)priv->ibv_port, 506 }, 507 .eth = { 508 .type = IBV_FLOW_SPEC_ETH, 509 .size = sizeof(struct ibv_flow_spec_eth), 510 }, 511 .drop = { 512 .size = sizeof(struct ibv_flow_spec_action_drop), 513 .type = IBV_FLOW_SPEC_ACTION_DROP, 514 }, 515 }; 516 struct ibv_flow *flow; 517 struct mlx5_hrxq *drop = mlx5_hrxq_drop_new(dev); 518 uint16_t vprio[] = { 8, 16 }; 519 int i; 520 int priority = 0; 521 522 if (!drop) { 523 rte_errno = ENOTSUP; 524 return -rte_errno; 525 } 526 for (i = 0; i != RTE_DIM(vprio); i++) { 527 flow_attr.attr.priority = vprio[i] - 1; 528 flow = mlx5_glue->create_flow(drop->qp, &flow_attr.attr); 529 if (!flow) 530 break; 531 claim_zero(mlx5_glue->destroy_flow(flow)); 532 priority = vprio[i]; 533 } 534 mlx5_hrxq_drop_release(dev); 535 switch (priority) { 536 case 8: 537 priority = RTE_DIM(priority_map_3); 538 break; 539 case 16: 540 priority = RTE_DIM(priority_map_5); 541 break; 542 default: 543 rte_errno = ENOTSUP; 544 DRV_LOG(ERR, 545 "port %u verbs maximum priority: %d expected 8/16", 546 dev->data->port_id, priority); 547 return -rte_errno; 548 } 549 DRV_LOG(INFO, "port %u flow maximum priority: %d", 550 dev->data->port_id, priority); 551 return priority; 552 } 553 554 /** 555 * Adjust flow priority based on the highest layer and the request priority. 556 * 557 * @param[in] dev 558 * Pointer to the Ethernet device structure. 559 * @param[in] priority 560 * The rule base priority. 561 * @param[in] subpriority 562 * The priority based on the items. 563 * 564 * @return 565 * The new priority. 566 */ 567 uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority, 568 uint32_t subpriority) 569 { 570 uint32_t res = 0; 571 struct mlx5_priv *priv = dev->data->dev_private; 572 573 switch (priv->config.flow_prio) { 574 case RTE_DIM(priority_map_3): 575 res = priority_map_3[priority][subpriority]; 576 break; 577 case RTE_DIM(priority_map_5): 578 res = priority_map_5[priority][subpriority]; 579 break; 580 } 581 return res; 582 } 583 584 /** 585 * Verify the @p item specifications (spec, last, mask) are compatible with the 586 * NIC capabilities. 587 * 588 * @param[in] item 589 * Item specification. 590 * @param[in] mask 591 * @p item->mask or flow default bit-masks. 592 * @param[in] nic_mask 593 * Bit-masks covering supported fields by the NIC to compare with user mask. 594 * @param[in] size 595 * Bit-masks size in bytes. 596 * @param[out] error 597 * Pointer to error structure. 598 * 599 * @return 600 * 0 on success, a negative errno value otherwise and rte_errno is set. 601 */ 602 int 603 mlx5_flow_item_acceptable(const struct rte_flow_item *item, 604 const uint8_t *mask, 605 const uint8_t *nic_mask, 606 unsigned int size, 607 struct rte_flow_error *error) 608 { 609 unsigned int i; 610 611 MLX5_ASSERT(nic_mask); 612 for (i = 0; i < size; ++i) 613 if ((nic_mask[i] | mask[i]) != nic_mask[i]) 614 return rte_flow_error_set(error, ENOTSUP, 615 RTE_FLOW_ERROR_TYPE_ITEM, 616 item, 617 "mask enables non supported" 618 " bits"); 619 if (!item->spec && (item->mask || item->last)) 620 return rte_flow_error_set(error, EINVAL, 621 RTE_FLOW_ERROR_TYPE_ITEM, item, 622 "mask/last without a spec is not" 623 " supported"); 624 if (item->spec && item->last) { 625 uint8_t spec[size]; 626 uint8_t last[size]; 627 unsigned int i; 628 int ret; 629 630 for (i = 0; i < size; ++i) { 631 spec[i] = ((const uint8_t *)item->spec)[i] & mask[i]; 632 last[i] = ((const uint8_t *)item->last)[i] & mask[i]; 633 } 634 ret = memcmp(spec, last, size); 635 if (ret != 0) 636 return rte_flow_error_set(error, EINVAL, 637 RTE_FLOW_ERROR_TYPE_ITEM, 638 item, 639 "range is not valid"); 640 } 641 return 0; 642 } 643 644 /** 645 * Adjust the hash fields according to the @p flow information. 646 * 647 * @param[in] dev_flow. 648 * Pointer to the mlx5_flow. 649 * @param[in] tunnel 650 * 1 when the hash field is for a tunnel item. 651 * @param[in] layer_types 652 * ETH_RSS_* types. 653 * @param[in] hash_fields 654 * Item hash fields. 655 * 656 * @return 657 * The hash fields that should be used. 658 */ 659 uint64_t 660 mlx5_flow_hashfields_adjust(struct mlx5_flow *dev_flow, 661 int tunnel __rte_unused, uint64_t layer_types, 662 uint64_t hash_fields) 663 { 664 struct rte_flow *flow = dev_flow->flow; 665 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 666 int rss_request_inner = flow->rss.level >= 2; 667 668 /* Check RSS hash level for tunnel. */ 669 if (tunnel && rss_request_inner) 670 hash_fields |= IBV_RX_HASH_INNER; 671 else if (tunnel || rss_request_inner) 672 return 0; 673 #endif 674 /* Check if requested layer matches RSS hash fields. */ 675 if (!(flow->rss.types & layer_types)) 676 return 0; 677 return hash_fields; 678 } 679 680 /** 681 * Lookup and set the ptype in the data Rx part. A single Ptype can be used, 682 * if several tunnel rules are used on this queue, the tunnel ptype will be 683 * cleared. 684 * 685 * @param rxq_ctrl 686 * Rx queue to update. 687 */ 688 static void 689 flow_rxq_tunnel_ptype_update(struct mlx5_rxq_ctrl *rxq_ctrl) 690 { 691 unsigned int i; 692 uint32_t tunnel_ptype = 0; 693 694 /* Look up for the ptype to use. */ 695 for (i = 0; i != MLX5_FLOW_TUNNEL; ++i) { 696 if (!rxq_ctrl->flow_tunnels_n[i]) 697 continue; 698 if (!tunnel_ptype) { 699 tunnel_ptype = tunnels_info[i].ptype; 700 } else { 701 tunnel_ptype = 0; 702 break; 703 } 704 } 705 rxq_ctrl->rxq.tunnel = tunnel_ptype; 706 } 707 708 /** 709 * Set the Rx queue flags (Mark/Flag and Tunnel Ptypes) according to the devive 710 * flow. 711 * 712 * @param[in] dev 713 * Pointer to the Ethernet device structure. 714 * @param[in] dev_flow 715 * Pointer to device flow structure. 716 */ 717 static void 718 flow_drv_rxq_flags_set(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow) 719 { 720 struct mlx5_priv *priv = dev->data->dev_private; 721 struct rte_flow *flow = dev_flow->flow; 722 const int mark = !!(dev_flow->actions & 723 (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK)); 724 const int tunnel = !!(dev_flow->layers & MLX5_FLOW_LAYER_TUNNEL); 725 unsigned int i; 726 727 for (i = 0; i != flow->rss.queue_num; ++i) { 728 int idx = (*flow->rss.queue)[i]; 729 struct mlx5_rxq_ctrl *rxq_ctrl = 730 container_of((*priv->rxqs)[idx], 731 struct mlx5_rxq_ctrl, rxq); 732 733 /* 734 * To support metadata register copy on Tx loopback, 735 * this must be always enabled (metadata may arive 736 * from other port - not from local flows only. 737 */ 738 if (priv->config.dv_flow_en && 739 priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 740 mlx5_flow_ext_mreg_supported(dev)) { 741 rxq_ctrl->rxq.mark = 1; 742 rxq_ctrl->flow_mark_n = 1; 743 } else if (mark) { 744 rxq_ctrl->rxq.mark = 1; 745 rxq_ctrl->flow_mark_n++; 746 } 747 if (tunnel) { 748 unsigned int j; 749 750 /* Increase the counter matching the flow. */ 751 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) { 752 if ((tunnels_info[j].tunnel & 753 dev_flow->layers) == 754 tunnels_info[j].tunnel) { 755 rxq_ctrl->flow_tunnels_n[j]++; 756 break; 757 } 758 } 759 flow_rxq_tunnel_ptype_update(rxq_ctrl); 760 } 761 } 762 } 763 764 /** 765 * Set the Rx queue flags (Mark/Flag and Tunnel Ptypes) for a flow 766 * 767 * @param[in] dev 768 * Pointer to the Ethernet device structure. 769 * @param[in] flow 770 * Pointer to flow structure. 771 */ 772 static void 773 flow_rxq_flags_set(struct rte_eth_dev *dev, struct rte_flow *flow) 774 { 775 struct mlx5_flow *dev_flow; 776 777 LIST_FOREACH(dev_flow, &flow->dev_flows, next) 778 flow_drv_rxq_flags_set(dev, dev_flow); 779 } 780 781 /** 782 * Clear the Rx queue flags (Mark/Flag and Tunnel Ptype) associated with the 783 * device flow if no other flow uses it with the same kind of request. 784 * 785 * @param dev 786 * Pointer to Ethernet device. 787 * @param[in] dev_flow 788 * Pointer to the device flow. 789 */ 790 static void 791 flow_drv_rxq_flags_trim(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow) 792 { 793 struct mlx5_priv *priv = dev->data->dev_private; 794 struct rte_flow *flow = dev_flow->flow; 795 const int mark = !!(dev_flow->actions & 796 (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK)); 797 const int tunnel = !!(dev_flow->layers & MLX5_FLOW_LAYER_TUNNEL); 798 unsigned int i; 799 800 MLX5_ASSERT(dev->data->dev_started); 801 for (i = 0; i != flow->rss.queue_num; ++i) { 802 int idx = (*flow->rss.queue)[i]; 803 struct mlx5_rxq_ctrl *rxq_ctrl = 804 container_of((*priv->rxqs)[idx], 805 struct mlx5_rxq_ctrl, rxq); 806 807 if (priv->config.dv_flow_en && 808 priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY && 809 mlx5_flow_ext_mreg_supported(dev)) { 810 rxq_ctrl->rxq.mark = 1; 811 rxq_ctrl->flow_mark_n = 1; 812 } else if (mark) { 813 rxq_ctrl->flow_mark_n--; 814 rxq_ctrl->rxq.mark = !!rxq_ctrl->flow_mark_n; 815 } 816 if (tunnel) { 817 unsigned int j; 818 819 /* Decrease the counter matching the flow. */ 820 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) { 821 if ((tunnels_info[j].tunnel & 822 dev_flow->layers) == 823 tunnels_info[j].tunnel) { 824 rxq_ctrl->flow_tunnels_n[j]--; 825 break; 826 } 827 } 828 flow_rxq_tunnel_ptype_update(rxq_ctrl); 829 } 830 } 831 } 832 833 /** 834 * Clear the Rx queue flags (Mark/Flag and Tunnel Ptype) associated with the 835 * @p flow if no other flow uses it with the same kind of request. 836 * 837 * @param dev 838 * Pointer to Ethernet device. 839 * @param[in] flow 840 * Pointer to the flow. 841 */ 842 static void 843 flow_rxq_flags_trim(struct rte_eth_dev *dev, struct rte_flow *flow) 844 { 845 struct mlx5_flow *dev_flow; 846 847 LIST_FOREACH(dev_flow, &flow->dev_flows, next) 848 flow_drv_rxq_flags_trim(dev, dev_flow); 849 } 850 851 /** 852 * Clear the Mark/Flag and Tunnel ptype information in all Rx queues. 853 * 854 * @param dev 855 * Pointer to Ethernet device. 856 */ 857 static void 858 flow_rxq_flags_clear(struct rte_eth_dev *dev) 859 { 860 struct mlx5_priv *priv = dev->data->dev_private; 861 unsigned int i; 862 863 for (i = 0; i != priv->rxqs_n; ++i) { 864 struct mlx5_rxq_ctrl *rxq_ctrl; 865 unsigned int j; 866 867 if (!(*priv->rxqs)[i]) 868 continue; 869 rxq_ctrl = container_of((*priv->rxqs)[i], 870 struct mlx5_rxq_ctrl, rxq); 871 rxq_ctrl->flow_mark_n = 0; 872 rxq_ctrl->rxq.mark = 0; 873 for (j = 0; j != MLX5_FLOW_TUNNEL; ++j) 874 rxq_ctrl->flow_tunnels_n[j] = 0; 875 rxq_ctrl->rxq.tunnel = 0; 876 } 877 } 878 879 /* 880 * return a pointer to the desired action in the list of actions. 881 * 882 * @param[in] actions 883 * The list of actions to search the action in. 884 * @param[in] action 885 * The action to find. 886 * 887 * @return 888 * Pointer to the action in the list, if found. NULL otherwise. 889 */ 890 const struct rte_flow_action * 891 mlx5_flow_find_action(const struct rte_flow_action *actions, 892 enum rte_flow_action_type action) 893 { 894 if (actions == NULL) 895 return NULL; 896 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) 897 if (actions->type == action) 898 return actions; 899 return NULL; 900 } 901 902 /* 903 * Validate the flag action. 904 * 905 * @param[in] action_flags 906 * Bit-fields that holds the actions detected until now. 907 * @param[in] attr 908 * Attributes of flow that includes this action. 909 * @param[out] error 910 * Pointer to error structure. 911 * 912 * @return 913 * 0 on success, a negative errno value otherwise and rte_errno is set. 914 */ 915 int 916 mlx5_flow_validate_action_flag(uint64_t action_flags, 917 const struct rte_flow_attr *attr, 918 struct rte_flow_error *error) 919 { 920 if (action_flags & MLX5_FLOW_ACTION_MARK) 921 return rte_flow_error_set(error, EINVAL, 922 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 923 "can't mark and flag in same flow"); 924 if (action_flags & MLX5_FLOW_ACTION_FLAG) 925 return rte_flow_error_set(error, EINVAL, 926 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 927 "can't have 2 flag" 928 " actions in same flow"); 929 if (attr->egress) 930 return rte_flow_error_set(error, ENOTSUP, 931 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 932 "flag action not supported for " 933 "egress"); 934 return 0; 935 } 936 937 /* 938 * Validate the mark action. 939 * 940 * @param[in] action 941 * Pointer to the queue action. 942 * @param[in] action_flags 943 * Bit-fields that holds the actions detected until now. 944 * @param[in] attr 945 * Attributes of flow that includes this action. 946 * @param[out] error 947 * Pointer to error structure. 948 * 949 * @return 950 * 0 on success, a negative errno value otherwise and rte_errno is set. 951 */ 952 int 953 mlx5_flow_validate_action_mark(const struct rte_flow_action *action, 954 uint64_t action_flags, 955 const struct rte_flow_attr *attr, 956 struct rte_flow_error *error) 957 { 958 const struct rte_flow_action_mark *mark = action->conf; 959 960 if (!mark) 961 return rte_flow_error_set(error, EINVAL, 962 RTE_FLOW_ERROR_TYPE_ACTION, 963 action, 964 "configuration cannot be null"); 965 if (mark->id >= MLX5_FLOW_MARK_MAX) 966 return rte_flow_error_set(error, EINVAL, 967 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 968 &mark->id, 969 "mark id must in 0 <= id < " 970 RTE_STR(MLX5_FLOW_MARK_MAX)); 971 if (action_flags & MLX5_FLOW_ACTION_FLAG) 972 return rte_flow_error_set(error, EINVAL, 973 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 974 "can't flag and mark in same flow"); 975 if (action_flags & MLX5_FLOW_ACTION_MARK) 976 return rte_flow_error_set(error, EINVAL, 977 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 978 "can't have 2 mark actions in same" 979 " flow"); 980 if (attr->egress) 981 return rte_flow_error_set(error, ENOTSUP, 982 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 983 "mark action not supported for " 984 "egress"); 985 return 0; 986 } 987 988 /* 989 * Validate the drop action. 990 * 991 * @param[in] action_flags 992 * Bit-fields that holds the actions detected until now. 993 * @param[in] attr 994 * Attributes of flow that includes this action. 995 * @param[out] error 996 * Pointer to error structure. 997 * 998 * @return 999 * 0 on success, a negative errno value otherwise and rte_errno is set. 1000 */ 1001 int 1002 mlx5_flow_validate_action_drop(uint64_t action_flags __rte_unused, 1003 const struct rte_flow_attr *attr, 1004 struct rte_flow_error *error) 1005 { 1006 if (attr->egress) 1007 return rte_flow_error_set(error, ENOTSUP, 1008 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1009 "drop action not supported for " 1010 "egress"); 1011 return 0; 1012 } 1013 1014 /* 1015 * Validate the queue action. 1016 * 1017 * @param[in] action 1018 * Pointer to the queue action. 1019 * @param[in] action_flags 1020 * Bit-fields that holds the actions detected until now. 1021 * @param[in] dev 1022 * Pointer to the Ethernet device structure. 1023 * @param[in] attr 1024 * Attributes of flow that includes this action. 1025 * @param[out] error 1026 * Pointer to error structure. 1027 * 1028 * @return 1029 * 0 on success, a negative errno value otherwise and rte_errno is set. 1030 */ 1031 int 1032 mlx5_flow_validate_action_queue(const struct rte_flow_action *action, 1033 uint64_t action_flags, 1034 struct rte_eth_dev *dev, 1035 const struct rte_flow_attr *attr, 1036 struct rte_flow_error *error) 1037 { 1038 struct mlx5_priv *priv = dev->data->dev_private; 1039 const struct rte_flow_action_queue *queue = action->conf; 1040 1041 if (action_flags & MLX5_FLOW_FATE_ACTIONS) 1042 return rte_flow_error_set(error, EINVAL, 1043 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1044 "can't have 2 fate actions in" 1045 " same flow"); 1046 if (!priv->rxqs_n) 1047 return rte_flow_error_set(error, EINVAL, 1048 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1049 NULL, "No Rx queues configured"); 1050 if (queue->index >= priv->rxqs_n) 1051 return rte_flow_error_set(error, EINVAL, 1052 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1053 &queue->index, 1054 "queue index out of range"); 1055 if (!(*priv->rxqs)[queue->index]) 1056 return rte_flow_error_set(error, EINVAL, 1057 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1058 &queue->index, 1059 "queue is not configured"); 1060 if (attr->egress) 1061 return rte_flow_error_set(error, ENOTSUP, 1062 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1063 "queue action not supported for " 1064 "egress"); 1065 return 0; 1066 } 1067 1068 /* 1069 * Validate the rss action. 1070 * 1071 * @param[in] action 1072 * Pointer to the queue action. 1073 * @param[in] action_flags 1074 * Bit-fields that holds the actions detected until now. 1075 * @param[in] dev 1076 * Pointer to the Ethernet device structure. 1077 * @param[in] attr 1078 * Attributes of flow that includes this action. 1079 * @param[in] item_flags 1080 * Items that were detected. 1081 * @param[out] error 1082 * Pointer to error structure. 1083 * 1084 * @return 1085 * 0 on success, a negative errno value otherwise and rte_errno is set. 1086 */ 1087 int 1088 mlx5_flow_validate_action_rss(const struct rte_flow_action *action, 1089 uint64_t action_flags, 1090 struct rte_eth_dev *dev, 1091 const struct rte_flow_attr *attr, 1092 uint64_t item_flags, 1093 struct rte_flow_error *error) 1094 { 1095 struct mlx5_priv *priv = dev->data->dev_private; 1096 const struct rte_flow_action_rss *rss = action->conf; 1097 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1098 unsigned int i; 1099 1100 if (action_flags & MLX5_FLOW_FATE_ACTIONS) 1101 return rte_flow_error_set(error, EINVAL, 1102 RTE_FLOW_ERROR_TYPE_ACTION, NULL, 1103 "can't have 2 fate actions" 1104 " in same flow"); 1105 if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT && 1106 rss->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ) 1107 return rte_flow_error_set(error, ENOTSUP, 1108 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1109 &rss->func, 1110 "RSS hash function not supported"); 1111 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT 1112 if (rss->level > 2) 1113 #else 1114 if (rss->level > 1) 1115 #endif 1116 return rte_flow_error_set(error, ENOTSUP, 1117 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1118 &rss->level, 1119 "tunnel RSS is not supported"); 1120 /* allow RSS key_len 0 in case of NULL (default) RSS key. */ 1121 if (rss->key_len == 0 && rss->key != NULL) 1122 return rte_flow_error_set(error, ENOTSUP, 1123 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1124 &rss->key_len, 1125 "RSS hash key length 0"); 1126 if (rss->key_len > 0 && rss->key_len < MLX5_RSS_HASH_KEY_LEN) 1127 return rte_flow_error_set(error, ENOTSUP, 1128 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1129 &rss->key_len, 1130 "RSS hash key too small"); 1131 if (rss->key_len > MLX5_RSS_HASH_KEY_LEN) 1132 return rte_flow_error_set(error, ENOTSUP, 1133 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1134 &rss->key_len, 1135 "RSS hash key too large"); 1136 if (rss->queue_num > priv->config.ind_table_max_size) 1137 return rte_flow_error_set(error, ENOTSUP, 1138 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1139 &rss->queue_num, 1140 "number of queues too large"); 1141 if (rss->types & MLX5_RSS_HF_MASK) 1142 return rte_flow_error_set(error, ENOTSUP, 1143 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1144 &rss->types, 1145 "some RSS protocols are not" 1146 " supported"); 1147 if ((rss->types & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY)) && 1148 !(rss->types & ETH_RSS_IP)) 1149 return rte_flow_error_set(error, EINVAL, 1150 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 1151 "L3 partial RSS requested but L3 RSS" 1152 " type not specified"); 1153 if ((rss->types & (ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY)) && 1154 !(rss->types & (ETH_RSS_UDP | ETH_RSS_TCP))) 1155 return rte_flow_error_set(error, EINVAL, 1156 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 1157 "L4 partial RSS requested but L4 RSS" 1158 " type not specified"); 1159 if (!priv->rxqs_n) 1160 return rte_flow_error_set(error, EINVAL, 1161 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1162 NULL, "No Rx queues configured"); 1163 if (!rss->queue_num) 1164 return rte_flow_error_set(error, EINVAL, 1165 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1166 NULL, "No queues configured"); 1167 for (i = 0; i != rss->queue_num; ++i) { 1168 if (rss->queue[i] >= priv->rxqs_n) 1169 return rte_flow_error_set 1170 (error, EINVAL, 1171 RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1172 &rss->queue[i], "queue index out of range"); 1173 if (!(*priv->rxqs)[rss->queue[i]]) 1174 return rte_flow_error_set 1175 (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF, 1176 &rss->queue[i], "queue is not configured"); 1177 } 1178 if (attr->egress) 1179 return rte_flow_error_set(error, ENOTSUP, 1180 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1181 "rss action not supported for " 1182 "egress"); 1183 if (rss->level > 1 && !tunnel) 1184 return rte_flow_error_set(error, EINVAL, 1185 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL, 1186 "inner RSS is not supported for " 1187 "non-tunnel flows"); 1188 return 0; 1189 } 1190 1191 /* 1192 * Validate the count action. 1193 * 1194 * @param[in] dev 1195 * Pointer to the Ethernet device structure. 1196 * @param[in] attr 1197 * Attributes of flow that includes this action. 1198 * @param[out] error 1199 * Pointer to error structure. 1200 * 1201 * @return 1202 * 0 on success, a negative errno value otherwise and rte_errno is set. 1203 */ 1204 int 1205 mlx5_flow_validate_action_count(struct rte_eth_dev *dev __rte_unused, 1206 const struct rte_flow_attr *attr, 1207 struct rte_flow_error *error) 1208 { 1209 if (attr->egress) 1210 return rte_flow_error_set(error, ENOTSUP, 1211 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1212 "count action not supported for " 1213 "egress"); 1214 return 0; 1215 } 1216 1217 /** 1218 * Verify the @p attributes will be correctly understood by the NIC and store 1219 * them in the @p flow if everything is correct. 1220 * 1221 * @param[in] dev 1222 * Pointer to the Ethernet device structure. 1223 * @param[in] attributes 1224 * Pointer to flow attributes 1225 * @param[out] error 1226 * Pointer to error structure. 1227 * 1228 * @return 1229 * 0 on success, a negative errno value otherwise and rte_errno is set. 1230 */ 1231 int 1232 mlx5_flow_validate_attributes(struct rte_eth_dev *dev, 1233 const struct rte_flow_attr *attributes, 1234 struct rte_flow_error *error) 1235 { 1236 struct mlx5_priv *priv = dev->data->dev_private; 1237 uint32_t priority_max = priv->config.flow_prio - 1; 1238 1239 if (attributes->group) 1240 return rte_flow_error_set(error, ENOTSUP, 1241 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 1242 NULL, "groups is not supported"); 1243 if (attributes->priority != MLX5_FLOW_PRIO_RSVD && 1244 attributes->priority >= priority_max) 1245 return rte_flow_error_set(error, ENOTSUP, 1246 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, 1247 NULL, "priority out of range"); 1248 if (attributes->egress) 1249 return rte_flow_error_set(error, ENOTSUP, 1250 RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL, 1251 "egress is not supported"); 1252 if (attributes->transfer && !priv->config.dv_esw_en) 1253 return rte_flow_error_set(error, ENOTSUP, 1254 RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, 1255 NULL, "transfer is not supported"); 1256 if (!attributes->ingress) 1257 return rte_flow_error_set(error, EINVAL, 1258 RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, 1259 NULL, 1260 "ingress attribute is mandatory"); 1261 return 0; 1262 } 1263 1264 /** 1265 * Validate ICMP6 item. 1266 * 1267 * @param[in] item 1268 * Item specification. 1269 * @param[in] item_flags 1270 * Bit-fields that holds the items detected until now. 1271 * @param[out] error 1272 * Pointer to error structure. 1273 * 1274 * @return 1275 * 0 on success, a negative errno value otherwise and rte_errno is set. 1276 */ 1277 int 1278 mlx5_flow_validate_item_icmp6(const struct rte_flow_item *item, 1279 uint64_t item_flags, 1280 uint8_t target_protocol, 1281 struct rte_flow_error *error) 1282 { 1283 const struct rte_flow_item_icmp6 *mask = item->mask; 1284 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1285 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : 1286 MLX5_FLOW_LAYER_OUTER_L3_IPV6; 1287 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 1288 MLX5_FLOW_LAYER_OUTER_L4; 1289 int ret; 1290 1291 if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMPV6) 1292 return rte_flow_error_set(error, EINVAL, 1293 RTE_FLOW_ERROR_TYPE_ITEM, item, 1294 "protocol filtering not compatible" 1295 " with ICMP6 layer"); 1296 if (!(item_flags & l3m)) 1297 return rte_flow_error_set(error, EINVAL, 1298 RTE_FLOW_ERROR_TYPE_ITEM, item, 1299 "IPv6 is mandatory to filter on" 1300 " ICMP6"); 1301 if (item_flags & l4m) 1302 return rte_flow_error_set(error, EINVAL, 1303 RTE_FLOW_ERROR_TYPE_ITEM, item, 1304 "multiple L4 layers not supported"); 1305 if (!mask) 1306 mask = &rte_flow_item_icmp6_mask; 1307 ret = mlx5_flow_item_acceptable 1308 (item, (const uint8_t *)mask, 1309 (const uint8_t *)&rte_flow_item_icmp6_mask, 1310 sizeof(struct rte_flow_item_icmp6), error); 1311 if (ret < 0) 1312 return ret; 1313 return 0; 1314 } 1315 1316 /** 1317 * Validate ICMP item. 1318 * 1319 * @param[in] item 1320 * Item specification. 1321 * @param[in] item_flags 1322 * Bit-fields that holds the items detected until now. 1323 * @param[out] error 1324 * Pointer to error structure. 1325 * 1326 * @return 1327 * 0 on success, a negative errno value otherwise and rte_errno is set. 1328 */ 1329 int 1330 mlx5_flow_validate_item_icmp(const struct rte_flow_item *item, 1331 uint64_t item_flags, 1332 uint8_t target_protocol, 1333 struct rte_flow_error *error) 1334 { 1335 const struct rte_flow_item_icmp *mask = item->mask; 1336 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1337 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : 1338 MLX5_FLOW_LAYER_OUTER_L3_IPV4; 1339 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 1340 MLX5_FLOW_LAYER_OUTER_L4; 1341 int ret; 1342 1343 if (target_protocol != 0xFF && target_protocol != IPPROTO_ICMP) 1344 return rte_flow_error_set(error, EINVAL, 1345 RTE_FLOW_ERROR_TYPE_ITEM, item, 1346 "protocol filtering not compatible" 1347 " with ICMP layer"); 1348 if (!(item_flags & l3m)) 1349 return rte_flow_error_set(error, EINVAL, 1350 RTE_FLOW_ERROR_TYPE_ITEM, item, 1351 "IPv4 is mandatory to filter" 1352 " on ICMP"); 1353 if (item_flags & l4m) 1354 return rte_flow_error_set(error, EINVAL, 1355 RTE_FLOW_ERROR_TYPE_ITEM, item, 1356 "multiple L4 layers not supported"); 1357 if (!mask) 1358 mask = &rte_flow_item_icmp_mask; 1359 ret = mlx5_flow_item_acceptable 1360 (item, (const uint8_t *)mask, 1361 (const uint8_t *)&rte_flow_item_icmp_mask, 1362 sizeof(struct rte_flow_item_icmp), error); 1363 if (ret < 0) 1364 return ret; 1365 return 0; 1366 } 1367 1368 /** 1369 * Validate Ethernet item. 1370 * 1371 * @param[in] item 1372 * Item specification. 1373 * @param[in] item_flags 1374 * Bit-fields that holds the items detected until now. 1375 * @param[out] error 1376 * Pointer to error structure. 1377 * 1378 * @return 1379 * 0 on success, a negative errno value otherwise and rte_errno is set. 1380 */ 1381 int 1382 mlx5_flow_validate_item_eth(const struct rte_flow_item *item, 1383 uint64_t item_flags, 1384 struct rte_flow_error *error) 1385 { 1386 const struct rte_flow_item_eth *mask = item->mask; 1387 const struct rte_flow_item_eth nic_mask = { 1388 .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", 1389 .src.addr_bytes = "\xff\xff\xff\xff\xff\xff", 1390 .type = RTE_BE16(0xffff), 1391 }; 1392 int ret; 1393 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1394 const uint64_t ethm = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : 1395 MLX5_FLOW_LAYER_OUTER_L2; 1396 1397 if (item_flags & ethm) 1398 return rte_flow_error_set(error, ENOTSUP, 1399 RTE_FLOW_ERROR_TYPE_ITEM, item, 1400 "multiple L2 layers not supported"); 1401 if ((!tunnel && (item_flags & MLX5_FLOW_LAYER_OUTER_L3)) || 1402 (tunnel && (item_flags & MLX5_FLOW_LAYER_INNER_L3))) 1403 return rte_flow_error_set(error, EINVAL, 1404 RTE_FLOW_ERROR_TYPE_ITEM, item, 1405 "L2 layer should not follow " 1406 "L3 layers"); 1407 if ((!tunnel && (item_flags & MLX5_FLOW_LAYER_OUTER_VLAN)) || 1408 (tunnel && (item_flags & MLX5_FLOW_LAYER_INNER_VLAN))) 1409 return rte_flow_error_set(error, EINVAL, 1410 RTE_FLOW_ERROR_TYPE_ITEM, item, 1411 "L2 layer should not follow VLAN"); 1412 if (!mask) 1413 mask = &rte_flow_item_eth_mask; 1414 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 1415 (const uint8_t *)&nic_mask, 1416 sizeof(struct rte_flow_item_eth), 1417 error); 1418 return ret; 1419 } 1420 1421 /** 1422 * Validate VLAN item. 1423 * 1424 * @param[in] item 1425 * Item specification. 1426 * @param[in] item_flags 1427 * Bit-fields that holds the items detected until now. 1428 * @param[in] dev 1429 * Ethernet device flow is being created on. 1430 * @param[out] error 1431 * Pointer to error structure. 1432 * 1433 * @return 1434 * 0 on success, a negative errno value otherwise and rte_errno is set. 1435 */ 1436 int 1437 mlx5_flow_validate_item_vlan(const struct rte_flow_item *item, 1438 uint64_t item_flags, 1439 struct rte_eth_dev *dev, 1440 struct rte_flow_error *error) 1441 { 1442 const struct rte_flow_item_vlan *spec = item->spec; 1443 const struct rte_flow_item_vlan *mask = item->mask; 1444 const struct rte_flow_item_vlan nic_mask = { 1445 .tci = RTE_BE16(UINT16_MAX), 1446 .inner_type = RTE_BE16(UINT16_MAX), 1447 }; 1448 uint16_t vlan_tag = 0; 1449 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1450 int ret; 1451 const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 | 1452 MLX5_FLOW_LAYER_INNER_L4) : 1453 (MLX5_FLOW_LAYER_OUTER_L3 | 1454 MLX5_FLOW_LAYER_OUTER_L4); 1455 const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN : 1456 MLX5_FLOW_LAYER_OUTER_VLAN; 1457 1458 if (item_flags & vlanm) 1459 return rte_flow_error_set(error, EINVAL, 1460 RTE_FLOW_ERROR_TYPE_ITEM, item, 1461 "multiple VLAN layers not supported"); 1462 else if ((item_flags & l34m) != 0) 1463 return rte_flow_error_set(error, EINVAL, 1464 RTE_FLOW_ERROR_TYPE_ITEM, item, 1465 "VLAN cannot follow L3/L4 layer"); 1466 if (!mask) 1467 mask = &rte_flow_item_vlan_mask; 1468 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 1469 (const uint8_t *)&nic_mask, 1470 sizeof(struct rte_flow_item_vlan), 1471 error); 1472 if (ret) 1473 return ret; 1474 if (!tunnel && mask->tci != RTE_BE16(0x0fff)) { 1475 struct mlx5_priv *priv = dev->data->dev_private; 1476 1477 if (priv->vmwa_context) { 1478 /* 1479 * Non-NULL context means we have a virtual machine 1480 * and SR-IOV enabled, we have to create VLAN interface 1481 * to make hypervisor to setup E-Switch vport 1482 * context correctly. We avoid creating the multiple 1483 * VLAN interfaces, so we cannot support VLAN tag mask. 1484 */ 1485 return rte_flow_error_set(error, EINVAL, 1486 RTE_FLOW_ERROR_TYPE_ITEM, 1487 item, 1488 "VLAN tag mask is not" 1489 " supported in virtual" 1490 " environment"); 1491 } 1492 } 1493 if (spec) { 1494 vlan_tag = spec->tci; 1495 vlan_tag &= mask->tci; 1496 } 1497 /* 1498 * From verbs perspective an empty VLAN is equivalent 1499 * to a packet without VLAN layer. 1500 */ 1501 if (!vlan_tag) 1502 return rte_flow_error_set(error, EINVAL, 1503 RTE_FLOW_ERROR_TYPE_ITEM_SPEC, 1504 item->spec, 1505 "VLAN cannot be empty"); 1506 return 0; 1507 } 1508 1509 /** 1510 * Validate IPV4 item. 1511 * 1512 * @param[in] item 1513 * Item specification. 1514 * @param[in] item_flags 1515 * Bit-fields that holds the items detected until now. 1516 * @param[in] acc_mask 1517 * Acceptable mask, if NULL default internal default mask 1518 * will be used to check whether item fields are supported. 1519 * @param[out] error 1520 * Pointer to error structure. 1521 * 1522 * @return 1523 * 0 on success, a negative errno value otherwise and rte_errno is set. 1524 */ 1525 int 1526 mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, 1527 uint64_t item_flags, 1528 uint64_t last_item, 1529 uint16_t ether_type, 1530 const struct rte_flow_item_ipv4 *acc_mask, 1531 struct rte_flow_error *error) 1532 { 1533 const struct rte_flow_item_ipv4 *mask = item->mask; 1534 const struct rte_flow_item_ipv4 *spec = item->spec; 1535 const struct rte_flow_item_ipv4 nic_mask = { 1536 .hdr = { 1537 .src_addr = RTE_BE32(0xffffffff), 1538 .dst_addr = RTE_BE32(0xffffffff), 1539 .type_of_service = 0xff, 1540 .next_proto_id = 0xff, 1541 }, 1542 }; 1543 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1544 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 1545 MLX5_FLOW_LAYER_OUTER_L3; 1546 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 1547 MLX5_FLOW_LAYER_OUTER_L4; 1548 int ret; 1549 uint8_t next_proto = 0xFF; 1550 const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 | 1551 MLX5_FLOW_LAYER_OUTER_VLAN | 1552 MLX5_FLOW_LAYER_INNER_VLAN); 1553 1554 if ((last_item & l2_vlan) && ether_type && 1555 ether_type != RTE_ETHER_TYPE_IPV4) 1556 return rte_flow_error_set(error, EINVAL, 1557 RTE_FLOW_ERROR_TYPE_ITEM, item, 1558 "IPv4 cannot follow L2/VLAN layer " 1559 "which ether type is not IPv4"); 1560 if (item_flags & MLX5_FLOW_LAYER_IPIP) { 1561 if (mask && spec) 1562 next_proto = mask->hdr.next_proto_id & 1563 spec->hdr.next_proto_id; 1564 if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6) 1565 return rte_flow_error_set(error, EINVAL, 1566 RTE_FLOW_ERROR_TYPE_ITEM, 1567 item, 1568 "multiple tunnel " 1569 "not supported"); 1570 } 1571 if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP) 1572 return rte_flow_error_set(error, EINVAL, 1573 RTE_FLOW_ERROR_TYPE_ITEM, item, 1574 "wrong tunnel type - IPv6 specified " 1575 "but IPv4 item provided"); 1576 if (item_flags & l3m) 1577 return rte_flow_error_set(error, ENOTSUP, 1578 RTE_FLOW_ERROR_TYPE_ITEM, item, 1579 "multiple L3 layers not supported"); 1580 else if (item_flags & l4m) 1581 return rte_flow_error_set(error, EINVAL, 1582 RTE_FLOW_ERROR_TYPE_ITEM, item, 1583 "L3 cannot follow an L4 layer."); 1584 else if ((item_flags & MLX5_FLOW_LAYER_NVGRE) && 1585 !(item_flags & MLX5_FLOW_LAYER_INNER_L2)) 1586 return rte_flow_error_set(error, EINVAL, 1587 RTE_FLOW_ERROR_TYPE_ITEM, item, 1588 "L3 cannot follow an NVGRE layer."); 1589 if (!mask) 1590 mask = &rte_flow_item_ipv4_mask; 1591 else if (mask->hdr.next_proto_id != 0 && 1592 mask->hdr.next_proto_id != 0xff) 1593 return rte_flow_error_set(error, EINVAL, 1594 RTE_FLOW_ERROR_TYPE_ITEM_MASK, mask, 1595 "partial mask is not supported" 1596 " for protocol"); 1597 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 1598 acc_mask ? (const uint8_t *)acc_mask 1599 : (const uint8_t *)&nic_mask, 1600 sizeof(struct rte_flow_item_ipv4), 1601 error); 1602 if (ret < 0) 1603 return ret; 1604 return 0; 1605 } 1606 1607 /** 1608 * Validate IPV6 item. 1609 * 1610 * @param[in] item 1611 * Item specification. 1612 * @param[in] item_flags 1613 * Bit-fields that holds the items detected until now. 1614 * @param[in] acc_mask 1615 * Acceptable mask, if NULL default internal default mask 1616 * will be used to check whether item fields are supported. 1617 * @param[out] error 1618 * Pointer to error structure. 1619 * 1620 * @return 1621 * 0 on success, a negative errno value otherwise and rte_errno is set. 1622 */ 1623 int 1624 mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, 1625 uint64_t item_flags, 1626 uint64_t last_item, 1627 uint16_t ether_type, 1628 const struct rte_flow_item_ipv6 *acc_mask, 1629 struct rte_flow_error *error) 1630 { 1631 const struct rte_flow_item_ipv6 *mask = item->mask; 1632 const struct rte_flow_item_ipv6 *spec = item->spec; 1633 const struct rte_flow_item_ipv6 nic_mask = { 1634 .hdr = { 1635 .src_addr = 1636 "\xff\xff\xff\xff\xff\xff\xff\xff" 1637 "\xff\xff\xff\xff\xff\xff\xff\xff", 1638 .dst_addr = 1639 "\xff\xff\xff\xff\xff\xff\xff\xff" 1640 "\xff\xff\xff\xff\xff\xff\xff\xff", 1641 .vtc_flow = RTE_BE32(0xffffffff), 1642 .proto = 0xff, 1643 .hop_limits = 0xff, 1644 }, 1645 }; 1646 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1647 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 1648 MLX5_FLOW_LAYER_OUTER_L3; 1649 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 1650 MLX5_FLOW_LAYER_OUTER_L4; 1651 int ret; 1652 uint8_t next_proto = 0xFF; 1653 const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 | 1654 MLX5_FLOW_LAYER_OUTER_VLAN | 1655 MLX5_FLOW_LAYER_INNER_VLAN); 1656 1657 if ((last_item & l2_vlan) && ether_type && 1658 ether_type != RTE_ETHER_TYPE_IPV6) 1659 return rte_flow_error_set(error, EINVAL, 1660 RTE_FLOW_ERROR_TYPE_ITEM, item, 1661 "IPv6 cannot follow L2/VLAN layer " 1662 "which ether type is not IPv6"); 1663 if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP) { 1664 if (mask && spec) 1665 next_proto = mask->hdr.proto & spec->hdr.proto; 1666 if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6) 1667 return rte_flow_error_set(error, EINVAL, 1668 RTE_FLOW_ERROR_TYPE_ITEM, 1669 item, 1670 "multiple tunnel " 1671 "not supported"); 1672 } 1673 if (item_flags & MLX5_FLOW_LAYER_IPIP) 1674 return rte_flow_error_set(error, EINVAL, 1675 RTE_FLOW_ERROR_TYPE_ITEM, item, 1676 "wrong tunnel type - IPv4 specified " 1677 "but IPv6 item provided"); 1678 if (item_flags & l3m) 1679 return rte_flow_error_set(error, ENOTSUP, 1680 RTE_FLOW_ERROR_TYPE_ITEM, item, 1681 "multiple L3 layers not supported"); 1682 else if (item_flags & l4m) 1683 return rte_flow_error_set(error, EINVAL, 1684 RTE_FLOW_ERROR_TYPE_ITEM, item, 1685 "L3 cannot follow an L4 layer."); 1686 else if ((item_flags & MLX5_FLOW_LAYER_NVGRE) && 1687 !(item_flags & MLX5_FLOW_LAYER_INNER_L2)) 1688 return rte_flow_error_set(error, EINVAL, 1689 RTE_FLOW_ERROR_TYPE_ITEM, item, 1690 "L3 cannot follow an NVGRE layer."); 1691 if (!mask) 1692 mask = &rte_flow_item_ipv6_mask; 1693 ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask, 1694 acc_mask ? (const uint8_t *)acc_mask 1695 : (const uint8_t *)&nic_mask, 1696 sizeof(struct rte_flow_item_ipv6), 1697 error); 1698 if (ret < 0) 1699 return ret; 1700 return 0; 1701 } 1702 1703 /** 1704 * Validate UDP item. 1705 * 1706 * @param[in] item 1707 * Item specification. 1708 * @param[in] item_flags 1709 * Bit-fields that holds the items detected until now. 1710 * @param[in] target_protocol 1711 * The next protocol in the previous item. 1712 * @param[in] flow_mask 1713 * mlx5 flow-specific (DV, verbs, etc.) supported header fields mask. 1714 * @param[out] error 1715 * Pointer to error structure. 1716 * 1717 * @return 1718 * 0 on success, a negative errno value otherwise and rte_errno is set. 1719 */ 1720 int 1721 mlx5_flow_validate_item_udp(const struct rte_flow_item *item, 1722 uint64_t item_flags, 1723 uint8_t target_protocol, 1724 struct rte_flow_error *error) 1725 { 1726 const struct rte_flow_item_udp *mask = item->mask; 1727 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1728 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 1729 MLX5_FLOW_LAYER_OUTER_L3; 1730 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 1731 MLX5_FLOW_LAYER_OUTER_L4; 1732 int ret; 1733 1734 if (target_protocol != 0xff && target_protocol != IPPROTO_UDP) 1735 return rte_flow_error_set(error, EINVAL, 1736 RTE_FLOW_ERROR_TYPE_ITEM, item, 1737 "protocol filtering not compatible" 1738 " with UDP layer"); 1739 if (!(item_flags & l3m)) 1740 return rte_flow_error_set(error, EINVAL, 1741 RTE_FLOW_ERROR_TYPE_ITEM, item, 1742 "L3 is mandatory to filter on L4"); 1743 if (item_flags & l4m) 1744 return rte_flow_error_set(error, EINVAL, 1745 RTE_FLOW_ERROR_TYPE_ITEM, item, 1746 "multiple L4 layers not supported"); 1747 if (!mask) 1748 mask = &rte_flow_item_udp_mask; 1749 ret = mlx5_flow_item_acceptable 1750 (item, (const uint8_t *)mask, 1751 (const uint8_t *)&rte_flow_item_udp_mask, 1752 sizeof(struct rte_flow_item_udp), error); 1753 if (ret < 0) 1754 return ret; 1755 return 0; 1756 } 1757 1758 /** 1759 * Validate TCP item. 1760 * 1761 * @param[in] item 1762 * Item specification. 1763 * @param[in] item_flags 1764 * Bit-fields that holds the items detected until now. 1765 * @param[in] target_protocol 1766 * The next protocol in the previous item. 1767 * @param[out] error 1768 * Pointer to error structure. 1769 * 1770 * @return 1771 * 0 on success, a negative errno value otherwise and rte_errno is set. 1772 */ 1773 int 1774 mlx5_flow_validate_item_tcp(const struct rte_flow_item *item, 1775 uint64_t item_flags, 1776 uint8_t target_protocol, 1777 const struct rte_flow_item_tcp *flow_mask, 1778 struct rte_flow_error *error) 1779 { 1780 const struct rte_flow_item_tcp *mask = item->mask; 1781 const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL); 1782 const uint64_t l3m = tunnel ? MLX5_FLOW_LAYER_INNER_L3 : 1783 MLX5_FLOW_LAYER_OUTER_L3; 1784 const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : 1785 MLX5_FLOW_LAYER_OUTER_L4; 1786 int ret; 1787 1788 MLX5_ASSERT(flow_mask); 1789 if (target_protocol != 0xff && target_protocol != IPPROTO_TCP) 1790 return rte_flow_error_set(error, EINVAL, 1791 RTE_FLOW_ERROR_TYPE_ITEM, item, 1792 "protocol filtering not compatible" 1793 " with TCP layer"); 1794 if (!(item_flags & l3m)) 1795 return rte_flow_error_set(error, EINVAL, 1796 RTE_FLOW_ERROR_TYPE_ITEM, item, 1797 "L3 is mandatory to filter on L4"); 1798 if (item_flags & l4m) 1799 return rte_flow_error_set(error, EINVAL, 1800 RTE_FLOW_ERROR_TYPE_ITEM, item, 1801 "multiple L4 layers not supported"); 1802 if (!mask) 1803 mask = &rte_flow_item_tcp_mask; 1804 ret = mlx5_flow_item_acceptable 1805 (item, (const uint8_t *)mask, 1806 (const uint8_t *)flow_mask, 1807 sizeof(struct rte_flow_item_tcp), error); 1808 if (ret < 0) 1809 return ret; 1810 return 0; 1811 } 1812 1813 /** 1814 * Validate VXLAN item. 1815 * 1816 * @param[in] item 1817 * Item specification. 1818 * @param[in] item_flags 1819 * Bit-fields that holds the items detected until now. 1820 * @param[in] target_protocol 1821 * The next protocol in the previous item. 1822 * @param[out] error 1823 * Pointer to error structure. 1824 * 1825 * @return 1826 * 0 on success, a negative errno value otherwise and rte_errno is set. 1827 */ 1828 int 1829 mlx5_flow_validate_item_vxlan(const struct rte_flow_item *item, 1830 uint64_t item_flags, 1831 struct rte_flow_error *error) 1832 { 1833 const struct rte_flow_item_vxlan *spec = item->spec; 1834 const struct rte_flow_item_vxlan *mask = item->mask; 1835 int ret; 1836 union vni { 1837 uint32_t vlan_id; 1838 uint8_t vni[4]; 1839 } id = { .vlan_id = 0, }; 1840 uint32_t vlan_id = 0; 1841 1842 1843 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 1844 return rte_flow_error_set(error, ENOTSUP, 1845 RTE_FLOW_ERROR_TYPE_ITEM, item, 1846 "multiple tunnel layers not" 1847 " supported"); 1848 /* 1849 * Verify only UDPv4 is present as defined in 1850 * https://tools.ietf.org/html/rfc7348 1851 */ 1852 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 1853 return rte_flow_error_set(error, EINVAL, 1854 RTE_FLOW_ERROR_TYPE_ITEM, item, 1855 "no outer UDP layer found"); 1856 if (!mask) 1857 mask = &rte_flow_item_vxlan_mask; 1858 ret = mlx5_flow_item_acceptable 1859 (item, (const uint8_t *)mask, 1860 (const uint8_t *)&rte_flow_item_vxlan_mask, 1861 sizeof(struct rte_flow_item_vxlan), 1862 error); 1863 if (ret < 0) 1864 return ret; 1865 if (spec) { 1866 memcpy(&id.vni[1], spec->vni, 3); 1867 vlan_id = id.vlan_id; 1868 memcpy(&id.vni[1], mask->vni, 3); 1869 vlan_id &= id.vlan_id; 1870 } 1871 /* 1872 * Tunnel id 0 is equivalent as not adding a VXLAN layer, if 1873 * only this layer is defined in the Verbs specification it is 1874 * interpreted as wildcard and all packets will match this 1875 * rule, if it follows a full stack layer (ex: eth / ipv4 / 1876 * udp), all packets matching the layers before will also 1877 * match this rule. To avoid such situation, VNI 0 is 1878 * currently refused. 1879 */ 1880 if (!vlan_id) 1881 return rte_flow_error_set(error, ENOTSUP, 1882 RTE_FLOW_ERROR_TYPE_ITEM, item, 1883 "VXLAN vni cannot be 0"); 1884 if (!(item_flags & MLX5_FLOW_LAYER_OUTER)) 1885 return rte_flow_error_set(error, ENOTSUP, 1886 RTE_FLOW_ERROR_TYPE_ITEM, item, 1887 "VXLAN tunnel must be fully defined"); 1888 return 0; 1889 } 1890 1891 /** 1892 * Validate VXLAN_GPE item. 1893 * 1894 * @param[in] item 1895 * Item specification. 1896 * @param[in] item_flags 1897 * Bit-fields that holds the items detected until now. 1898 * @param[in] priv 1899 * Pointer to the private data structure. 1900 * @param[in] target_protocol 1901 * The next protocol in the previous item. 1902 * @param[out] error 1903 * Pointer to error structure. 1904 * 1905 * @return 1906 * 0 on success, a negative errno value otherwise and rte_errno is set. 1907 */ 1908 int 1909 mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item, 1910 uint64_t item_flags, 1911 struct rte_eth_dev *dev, 1912 struct rte_flow_error *error) 1913 { 1914 struct mlx5_priv *priv = dev->data->dev_private; 1915 const struct rte_flow_item_vxlan_gpe *spec = item->spec; 1916 const struct rte_flow_item_vxlan_gpe *mask = item->mask; 1917 int ret; 1918 union vni { 1919 uint32_t vlan_id; 1920 uint8_t vni[4]; 1921 } id = { .vlan_id = 0, }; 1922 uint32_t vlan_id = 0; 1923 1924 if (!priv->config.l3_vxlan_en) 1925 return rte_flow_error_set(error, ENOTSUP, 1926 RTE_FLOW_ERROR_TYPE_ITEM, item, 1927 "L3 VXLAN is not enabled by device" 1928 " parameter and/or not configured in" 1929 " firmware"); 1930 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 1931 return rte_flow_error_set(error, ENOTSUP, 1932 RTE_FLOW_ERROR_TYPE_ITEM, item, 1933 "multiple tunnel layers not" 1934 " supported"); 1935 /* 1936 * Verify only UDPv4 is present as defined in 1937 * https://tools.ietf.org/html/rfc7348 1938 */ 1939 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 1940 return rte_flow_error_set(error, EINVAL, 1941 RTE_FLOW_ERROR_TYPE_ITEM, item, 1942 "no outer UDP layer found"); 1943 if (!mask) 1944 mask = &rte_flow_item_vxlan_gpe_mask; 1945 ret = mlx5_flow_item_acceptable 1946 (item, (const uint8_t *)mask, 1947 (const uint8_t *)&rte_flow_item_vxlan_gpe_mask, 1948 sizeof(struct rte_flow_item_vxlan_gpe), 1949 error); 1950 if (ret < 0) 1951 return ret; 1952 if (spec) { 1953 if (spec->protocol) 1954 return rte_flow_error_set(error, ENOTSUP, 1955 RTE_FLOW_ERROR_TYPE_ITEM, 1956 item, 1957 "VxLAN-GPE protocol" 1958 " not supported"); 1959 memcpy(&id.vni[1], spec->vni, 3); 1960 vlan_id = id.vlan_id; 1961 memcpy(&id.vni[1], mask->vni, 3); 1962 vlan_id &= id.vlan_id; 1963 } 1964 /* 1965 * Tunnel id 0 is equivalent as not adding a VXLAN layer, if only this 1966 * layer is defined in the Verbs specification it is interpreted as 1967 * wildcard and all packets will match this rule, if it follows a full 1968 * stack layer (ex: eth / ipv4 / udp), all packets matching the layers 1969 * before will also match this rule. To avoid such situation, VNI 0 1970 * is currently refused. 1971 */ 1972 if (!vlan_id) 1973 return rte_flow_error_set(error, ENOTSUP, 1974 RTE_FLOW_ERROR_TYPE_ITEM, item, 1975 "VXLAN-GPE vni cannot be 0"); 1976 if (!(item_flags & MLX5_FLOW_LAYER_OUTER)) 1977 return rte_flow_error_set(error, ENOTSUP, 1978 RTE_FLOW_ERROR_TYPE_ITEM, item, 1979 "VXLAN-GPE tunnel must be fully" 1980 " defined"); 1981 return 0; 1982 } 1983 /** 1984 * Validate GRE Key item. 1985 * 1986 * @param[in] item 1987 * Item specification. 1988 * @param[in] item_flags 1989 * Bit flags to mark detected items. 1990 * @param[in] gre_item 1991 * Pointer to gre_item 1992 * @param[out] error 1993 * Pointer to error structure. 1994 * 1995 * @return 1996 * 0 on success, a negative errno value otherwise and rte_errno is set. 1997 */ 1998 int 1999 mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item, 2000 uint64_t item_flags, 2001 const struct rte_flow_item *gre_item, 2002 struct rte_flow_error *error) 2003 { 2004 const rte_be32_t *mask = item->mask; 2005 int ret = 0; 2006 rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 2007 const struct rte_flow_item_gre *gre_spec; 2008 const struct rte_flow_item_gre *gre_mask; 2009 2010 if (item_flags & MLX5_FLOW_LAYER_GRE_KEY) 2011 return rte_flow_error_set(error, ENOTSUP, 2012 RTE_FLOW_ERROR_TYPE_ITEM, item, 2013 "Multiple GRE key not support"); 2014 if (!(item_flags & MLX5_FLOW_LAYER_GRE)) 2015 return rte_flow_error_set(error, ENOTSUP, 2016 RTE_FLOW_ERROR_TYPE_ITEM, item, 2017 "No preceding GRE header"); 2018 if (item_flags & MLX5_FLOW_LAYER_INNER) 2019 return rte_flow_error_set(error, ENOTSUP, 2020 RTE_FLOW_ERROR_TYPE_ITEM, item, 2021 "GRE key following a wrong item"); 2022 gre_mask = gre_item->mask; 2023 if (!gre_mask) 2024 gre_mask = &rte_flow_item_gre_mask; 2025 gre_spec = gre_item->spec; 2026 if (gre_spec && (gre_mask->c_rsvd0_ver & RTE_BE16(0x2000)) && 2027 !(gre_spec->c_rsvd0_ver & RTE_BE16(0x2000))) 2028 return rte_flow_error_set(error, EINVAL, 2029 RTE_FLOW_ERROR_TYPE_ITEM, item, 2030 "Key bit must be on"); 2031 2032 if (!mask) 2033 mask = &gre_key_default_mask; 2034 ret = mlx5_flow_item_acceptable 2035 (item, (const uint8_t *)mask, 2036 (const uint8_t *)&gre_key_default_mask, 2037 sizeof(rte_be32_t), error); 2038 return ret; 2039 } 2040 2041 /** 2042 * Validate GRE item. 2043 * 2044 * @param[in] item 2045 * Item specification. 2046 * @param[in] item_flags 2047 * Bit flags to mark detected items. 2048 * @param[in] target_protocol 2049 * The next protocol in the previous item. 2050 * @param[out] error 2051 * Pointer to error structure. 2052 * 2053 * @return 2054 * 0 on success, a negative errno value otherwise and rte_errno is set. 2055 */ 2056 int 2057 mlx5_flow_validate_item_gre(const struct rte_flow_item *item, 2058 uint64_t item_flags, 2059 uint8_t target_protocol, 2060 struct rte_flow_error *error) 2061 { 2062 const struct rte_flow_item_gre *spec __rte_unused = item->spec; 2063 const struct rte_flow_item_gre *mask = item->mask; 2064 int ret; 2065 const struct rte_flow_item_gre nic_mask = { 2066 .c_rsvd0_ver = RTE_BE16(0xB000), 2067 .protocol = RTE_BE16(UINT16_MAX), 2068 }; 2069 2070 if (target_protocol != 0xff && target_protocol != IPPROTO_GRE) 2071 return rte_flow_error_set(error, EINVAL, 2072 RTE_FLOW_ERROR_TYPE_ITEM, item, 2073 "protocol filtering not compatible" 2074 " with this GRE layer"); 2075 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 2076 return rte_flow_error_set(error, ENOTSUP, 2077 RTE_FLOW_ERROR_TYPE_ITEM, item, 2078 "multiple tunnel layers not" 2079 " supported"); 2080 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3)) 2081 return rte_flow_error_set(error, ENOTSUP, 2082 RTE_FLOW_ERROR_TYPE_ITEM, item, 2083 "L3 Layer is missing"); 2084 if (!mask) 2085 mask = &rte_flow_item_gre_mask; 2086 ret = mlx5_flow_item_acceptable 2087 (item, (const uint8_t *)mask, 2088 (const uint8_t *)&nic_mask, 2089 sizeof(struct rte_flow_item_gre), error); 2090 if (ret < 0) 2091 return ret; 2092 #ifndef HAVE_MLX5DV_DR 2093 #ifndef HAVE_IBV_DEVICE_MPLS_SUPPORT 2094 if (spec && (spec->protocol & mask->protocol)) 2095 return rte_flow_error_set(error, ENOTSUP, 2096 RTE_FLOW_ERROR_TYPE_ITEM, item, 2097 "without MPLS support the" 2098 " specification cannot be used for" 2099 " filtering"); 2100 #endif 2101 #endif 2102 return 0; 2103 } 2104 2105 /** 2106 * Validate Geneve item. 2107 * 2108 * @param[in] item 2109 * Item specification. 2110 * @param[in] itemFlags 2111 * Bit-fields that holds the items detected until now. 2112 * @param[in] enPriv 2113 * Pointer to the private data structure. 2114 * @param[out] error 2115 * Pointer to error structure. 2116 * 2117 * @return 2118 * 0 on success, a negative errno value otherwise and rte_errno is set. 2119 */ 2120 2121 int 2122 mlx5_flow_validate_item_geneve(const struct rte_flow_item *item, 2123 uint64_t item_flags, 2124 struct rte_eth_dev *dev, 2125 struct rte_flow_error *error) 2126 { 2127 struct mlx5_priv *priv = dev->data->dev_private; 2128 const struct rte_flow_item_geneve *spec = item->spec; 2129 const struct rte_flow_item_geneve *mask = item->mask; 2130 int ret; 2131 uint16_t gbhdr; 2132 uint8_t opt_len = priv->config.hca_attr.geneve_max_opt_len ? 2133 MLX5_GENEVE_OPT_LEN_1 : MLX5_GENEVE_OPT_LEN_0; 2134 const struct rte_flow_item_geneve nic_mask = { 2135 .ver_opt_len_o_c_rsvd0 = RTE_BE16(0x3f80), 2136 .vni = "\xff\xff\xff", 2137 .protocol = RTE_BE16(UINT16_MAX), 2138 }; 2139 2140 if (!priv->config.hca_attr.tunnel_stateless_geneve_rx) 2141 return rte_flow_error_set(error, ENOTSUP, 2142 RTE_FLOW_ERROR_TYPE_ITEM, item, 2143 "L3 Geneve is not enabled by device" 2144 " parameter and/or not configured in" 2145 " firmware"); 2146 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 2147 return rte_flow_error_set(error, ENOTSUP, 2148 RTE_FLOW_ERROR_TYPE_ITEM, item, 2149 "multiple tunnel layers not" 2150 " supported"); 2151 /* 2152 * Verify only UDPv4 is present as defined in 2153 * https://tools.ietf.org/html/rfc7348 2154 */ 2155 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_UDP)) 2156 return rte_flow_error_set(error, EINVAL, 2157 RTE_FLOW_ERROR_TYPE_ITEM, item, 2158 "no outer UDP layer found"); 2159 if (!mask) 2160 mask = &rte_flow_item_geneve_mask; 2161 ret = mlx5_flow_item_acceptable 2162 (item, (const uint8_t *)mask, 2163 (const uint8_t *)&nic_mask, 2164 sizeof(struct rte_flow_item_geneve), error); 2165 if (ret) 2166 return ret; 2167 if (spec) { 2168 gbhdr = rte_be_to_cpu_16(spec->ver_opt_len_o_c_rsvd0); 2169 if (MLX5_GENEVE_VER_VAL(gbhdr) || 2170 MLX5_GENEVE_CRITO_VAL(gbhdr) || 2171 MLX5_GENEVE_RSVD_VAL(gbhdr) || spec->rsvd1) 2172 return rte_flow_error_set(error, ENOTSUP, 2173 RTE_FLOW_ERROR_TYPE_ITEM, 2174 item, 2175 "Geneve protocol unsupported" 2176 " fields are being used"); 2177 if (MLX5_GENEVE_OPTLEN_VAL(gbhdr) > opt_len) 2178 return rte_flow_error_set 2179 (error, ENOTSUP, 2180 RTE_FLOW_ERROR_TYPE_ITEM, 2181 item, 2182 "Unsupported Geneve options length"); 2183 } 2184 if (!(item_flags & MLX5_FLOW_LAYER_OUTER)) 2185 return rte_flow_error_set 2186 (error, ENOTSUP, 2187 RTE_FLOW_ERROR_TYPE_ITEM, item, 2188 "Geneve tunnel must be fully defined"); 2189 return 0; 2190 } 2191 2192 /** 2193 * Validate MPLS item. 2194 * 2195 * @param[in] dev 2196 * Pointer to the rte_eth_dev structure. 2197 * @param[in] item 2198 * Item specification. 2199 * @param[in] item_flags 2200 * Bit-fields that holds the items detected until now. 2201 * @param[in] prev_layer 2202 * The protocol layer indicated in previous item. 2203 * @param[out] error 2204 * Pointer to error structure. 2205 * 2206 * @return 2207 * 0 on success, a negative errno value otherwise and rte_errno is set. 2208 */ 2209 int 2210 mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev __rte_unused, 2211 const struct rte_flow_item *item __rte_unused, 2212 uint64_t item_flags __rte_unused, 2213 uint64_t prev_layer __rte_unused, 2214 struct rte_flow_error *error) 2215 { 2216 #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT 2217 const struct rte_flow_item_mpls *mask = item->mask; 2218 struct mlx5_priv *priv = dev->data->dev_private; 2219 int ret; 2220 2221 if (!priv->config.mpls_en) 2222 return rte_flow_error_set(error, ENOTSUP, 2223 RTE_FLOW_ERROR_TYPE_ITEM, item, 2224 "MPLS not supported or" 2225 " disabled in firmware" 2226 " configuration."); 2227 /* MPLS over IP, UDP, GRE is allowed */ 2228 if (!(prev_layer & (MLX5_FLOW_LAYER_OUTER_L3 | 2229 MLX5_FLOW_LAYER_OUTER_L4_UDP | 2230 MLX5_FLOW_LAYER_GRE))) 2231 return rte_flow_error_set(error, EINVAL, 2232 RTE_FLOW_ERROR_TYPE_ITEM, item, 2233 "protocol filtering not compatible" 2234 " with MPLS layer"); 2235 /* Multi-tunnel isn't allowed but MPLS over GRE is an exception. */ 2236 if ((item_flags & MLX5_FLOW_LAYER_TUNNEL) && 2237 !(item_flags & MLX5_FLOW_LAYER_GRE)) 2238 return rte_flow_error_set(error, ENOTSUP, 2239 RTE_FLOW_ERROR_TYPE_ITEM, item, 2240 "multiple tunnel layers not" 2241 " supported"); 2242 if (!mask) 2243 mask = &rte_flow_item_mpls_mask; 2244 ret = mlx5_flow_item_acceptable 2245 (item, (const uint8_t *)mask, 2246 (const uint8_t *)&rte_flow_item_mpls_mask, 2247 sizeof(struct rte_flow_item_mpls), error); 2248 if (ret < 0) 2249 return ret; 2250 return 0; 2251 #endif 2252 return rte_flow_error_set(error, ENOTSUP, 2253 RTE_FLOW_ERROR_TYPE_ITEM, item, 2254 "MPLS is not supported by Verbs, please" 2255 " update."); 2256 } 2257 2258 /** 2259 * Validate NVGRE item. 2260 * 2261 * @param[in] item 2262 * Item specification. 2263 * @param[in] item_flags 2264 * Bit flags to mark detected items. 2265 * @param[in] target_protocol 2266 * The next protocol in the previous item. 2267 * @param[out] error 2268 * Pointer to error structure. 2269 * 2270 * @return 2271 * 0 on success, a negative errno value otherwise and rte_errno is set. 2272 */ 2273 int 2274 mlx5_flow_validate_item_nvgre(const struct rte_flow_item *item, 2275 uint64_t item_flags, 2276 uint8_t target_protocol, 2277 struct rte_flow_error *error) 2278 { 2279 const struct rte_flow_item_nvgre *mask = item->mask; 2280 int ret; 2281 2282 if (target_protocol != 0xff && target_protocol != IPPROTO_GRE) 2283 return rte_flow_error_set(error, EINVAL, 2284 RTE_FLOW_ERROR_TYPE_ITEM, item, 2285 "protocol filtering not compatible" 2286 " with this GRE layer"); 2287 if (item_flags & MLX5_FLOW_LAYER_TUNNEL) 2288 return rte_flow_error_set(error, ENOTSUP, 2289 RTE_FLOW_ERROR_TYPE_ITEM, item, 2290 "multiple tunnel layers not" 2291 " supported"); 2292 if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L3)) 2293 return rte_flow_error_set(error, ENOTSUP, 2294 RTE_FLOW_ERROR_TYPE_ITEM, item, 2295 "L3 Layer is missing"); 2296 if (!mask) 2297 mask = &rte_flow_item_nvgre_mask; 2298 ret = mlx5_flow_item_acceptable 2299 (item, (const uint8_t *)mask, 2300 (const uint8_t *)&rte_flow_item_nvgre_mask, 2301 sizeof(struct rte_flow_item_nvgre), error); 2302 if (ret < 0) 2303 return ret; 2304 return 0; 2305 } 2306 2307 /* Allocate unique ID for the split Q/RSS subflows. */ 2308 static uint32_t 2309 flow_qrss_get_id(struct rte_eth_dev *dev) 2310 { 2311 struct mlx5_priv *priv = dev->data->dev_private; 2312 uint32_t qrss_id, ret; 2313 2314 ret = mlx5_flow_id_get(priv->qrss_id_pool, &qrss_id); 2315 if (ret) 2316 return 0; 2317 MLX5_ASSERT(qrss_id); 2318 return qrss_id; 2319 } 2320 2321 /* Free unique ID for the split Q/RSS subflows. */ 2322 static void 2323 flow_qrss_free_id(struct rte_eth_dev *dev, uint32_t qrss_id) 2324 { 2325 struct mlx5_priv *priv = dev->data->dev_private; 2326 2327 if (qrss_id) 2328 mlx5_flow_id_release(priv->qrss_id_pool, qrss_id); 2329 } 2330 2331 /** 2332 * Release resource related QUEUE/RSS action split. 2333 * 2334 * @param dev 2335 * Pointer to Ethernet device. 2336 * @param flow 2337 * Flow to release id's from. 2338 */ 2339 static void 2340 flow_mreg_split_qrss_release(struct rte_eth_dev *dev, 2341 struct rte_flow *flow) 2342 { 2343 struct mlx5_flow *dev_flow; 2344 2345 LIST_FOREACH(dev_flow, &flow->dev_flows, next) 2346 if (dev_flow->qrss_id) 2347 flow_qrss_free_id(dev, dev_flow->qrss_id); 2348 } 2349 2350 static int 2351 flow_null_validate(struct rte_eth_dev *dev __rte_unused, 2352 const struct rte_flow_attr *attr __rte_unused, 2353 const struct rte_flow_item items[] __rte_unused, 2354 const struct rte_flow_action actions[] __rte_unused, 2355 bool external __rte_unused, 2356 struct rte_flow_error *error) 2357 { 2358 return rte_flow_error_set(error, ENOTSUP, 2359 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 2360 } 2361 2362 static struct mlx5_flow * 2363 flow_null_prepare(const struct rte_flow_attr *attr __rte_unused, 2364 const struct rte_flow_item items[] __rte_unused, 2365 const struct rte_flow_action actions[] __rte_unused, 2366 struct rte_flow_error *error) 2367 { 2368 rte_flow_error_set(error, ENOTSUP, 2369 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 2370 return NULL; 2371 } 2372 2373 static int 2374 flow_null_translate(struct rte_eth_dev *dev __rte_unused, 2375 struct mlx5_flow *dev_flow __rte_unused, 2376 const struct rte_flow_attr *attr __rte_unused, 2377 const struct rte_flow_item items[] __rte_unused, 2378 const struct rte_flow_action actions[] __rte_unused, 2379 struct rte_flow_error *error) 2380 { 2381 return rte_flow_error_set(error, ENOTSUP, 2382 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 2383 } 2384 2385 static int 2386 flow_null_apply(struct rte_eth_dev *dev __rte_unused, 2387 struct rte_flow *flow __rte_unused, 2388 struct rte_flow_error *error) 2389 { 2390 return rte_flow_error_set(error, ENOTSUP, 2391 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 2392 } 2393 2394 static void 2395 flow_null_remove(struct rte_eth_dev *dev __rte_unused, 2396 struct rte_flow *flow __rte_unused) 2397 { 2398 } 2399 2400 static void 2401 flow_null_destroy(struct rte_eth_dev *dev __rte_unused, 2402 struct rte_flow *flow __rte_unused) 2403 { 2404 } 2405 2406 static int 2407 flow_null_query(struct rte_eth_dev *dev __rte_unused, 2408 struct rte_flow *flow __rte_unused, 2409 const struct rte_flow_action *actions __rte_unused, 2410 void *data __rte_unused, 2411 struct rte_flow_error *error) 2412 { 2413 return rte_flow_error_set(error, ENOTSUP, 2414 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, NULL); 2415 } 2416 2417 /* Void driver to protect from null pointer reference. */ 2418 const struct mlx5_flow_driver_ops mlx5_flow_null_drv_ops = { 2419 .validate = flow_null_validate, 2420 .prepare = flow_null_prepare, 2421 .translate = flow_null_translate, 2422 .apply = flow_null_apply, 2423 .remove = flow_null_remove, 2424 .destroy = flow_null_destroy, 2425 .query = flow_null_query, 2426 }; 2427 2428 /** 2429 * Select flow driver type according to flow attributes and device 2430 * configuration. 2431 * 2432 * @param[in] dev 2433 * Pointer to the dev structure. 2434 * @param[in] attr 2435 * Pointer to the flow attributes. 2436 * 2437 * @return 2438 * flow driver type, MLX5_FLOW_TYPE_MAX otherwise. 2439 */ 2440 static enum mlx5_flow_drv_type 2441 flow_get_drv_type(struct rte_eth_dev *dev, const struct rte_flow_attr *attr) 2442 { 2443 struct mlx5_priv *priv = dev->data->dev_private; 2444 enum mlx5_flow_drv_type type = MLX5_FLOW_TYPE_MAX; 2445 2446 if (attr->transfer && priv->config.dv_esw_en) 2447 type = MLX5_FLOW_TYPE_DV; 2448 if (!attr->transfer) 2449 type = priv->config.dv_flow_en ? MLX5_FLOW_TYPE_DV : 2450 MLX5_FLOW_TYPE_VERBS; 2451 return type; 2452 } 2453 2454 #define flow_get_drv_ops(type) flow_drv_ops[type] 2455 2456 /** 2457 * Flow driver validation API. This abstracts calling driver specific functions. 2458 * The type of flow driver is determined according to flow attributes. 2459 * 2460 * @param[in] dev 2461 * Pointer to the dev structure. 2462 * @param[in] attr 2463 * Pointer to the flow attributes. 2464 * @param[in] items 2465 * Pointer to the list of items. 2466 * @param[in] actions 2467 * Pointer to the list of actions. 2468 * @param[in] external 2469 * This flow rule is created by request external to PMD. 2470 * @param[out] error 2471 * Pointer to the error structure. 2472 * 2473 * @return 2474 * 0 on success, a negative errno value otherwise and rte_errno is set. 2475 */ 2476 static inline int 2477 flow_drv_validate(struct rte_eth_dev *dev, 2478 const struct rte_flow_attr *attr, 2479 const struct rte_flow_item items[], 2480 const struct rte_flow_action actions[], 2481 bool external, struct rte_flow_error *error) 2482 { 2483 const struct mlx5_flow_driver_ops *fops; 2484 enum mlx5_flow_drv_type type = flow_get_drv_type(dev, attr); 2485 2486 fops = flow_get_drv_ops(type); 2487 return fops->validate(dev, attr, items, actions, external, error); 2488 } 2489 2490 /** 2491 * Flow driver preparation API. This abstracts calling driver specific 2492 * functions. Parent flow (rte_flow) should have driver type (drv_type). It 2493 * calculates the size of memory required for device flow, allocates the memory, 2494 * initializes the device flow and returns the pointer. 2495 * 2496 * @note 2497 * This function initializes device flow structure such as dv or verbs in 2498 * struct mlx5_flow. However, it is caller's responsibility to initialize the 2499 * rest. For example, adding returning device flow to flow->dev_flow list and 2500 * setting backward reference to the flow should be done out of this function. 2501 * layers field is not filled either. 2502 * 2503 * @param[in] attr 2504 * Pointer to the flow attributes. 2505 * @param[in] items 2506 * Pointer to the list of items. 2507 * @param[in] actions 2508 * Pointer to the list of actions. 2509 * @param[out] error 2510 * Pointer to the error structure. 2511 * 2512 * @return 2513 * Pointer to device flow on success, otherwise NULL and rte_errno is set. 2514 */ 2515 static inline struct mlx5_flow * 2516 flow_drv_prepare(const struct rte_flow *flow, 2517 const struct rte_flow_attr *attr, 2518 const struct rte_flow_item items[], 2519 const struct rte_flow_action actions[], 2520 struct rte_flow_error *error) 2521 { 2522 const struct mlx5_flow_driver_ops *fops; 2523 enum mlx5_flow_drv_type type = flow->drv_type; 2524 2525 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 2526 fops = flow_get_drv_ops(type); 2527 return fops->prepare(attr, items, actions, error); 2528 } 2529 2530 /** 2531 * Flow driver translation API. This abstracts calling driver specific 2532 * functions. Parent flow (rte_flow) should have driver type (drv_type). It 2533 * translates a generic flow into a driver flow. flow_drv_prepare() must 2534 * precede. 2535 * 2536 * @note 2537 * dev_flow->layers could be filled as a result of parsing during translation 2538 * if needed by flow_drv_apply(). dev_flow->flow->actions can also be filled 2539 * if necessary. As a flow can have multiple dev_flows by RSS flow expansion, 2540 * flow->actions could be overwritten even though all the expanded dev_flows 2541 * have the same actions. 2542 * 2543 * @param[in] dev 2544 * Pointer to the rte dev structure. 2545 * @param[in, out] dev_flow 2546 * Pointer to the mlx5 flow. 2547 * @param[in] attr 2548 * Pointer to the flow attributes. 2549 * @param[in] items 2550 * Pointer to the list of items. 2551 * @param[in] actions 2552 * Pointer to the list of actions. 2553 * @param[out] error 2554 * Pointer to the error structure. 2555 * 2556 * @return 2557 * 0 on success, a negative errno value otherwise and rte_errno is set. 2558 */ 2559 static inline int 2560 flow_drv_translate(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow, 2561 const struct rte_flow_attr *attr, 2562 const struct rte_flow_item items[], 2563 const struct rte_flow_action actions[], 2564 struct rte_flow_error *error) 2565 { 2566 const struct mlx5_flow_driver_ops *fops; 2567 enum mlx5_flow_drv_type type = dev_flow->flow->drv_type; 2568 2569 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 2570 fops = flow_get_drv_ops(type); 2571 return fops->translate(dev, dev_flow, attr, items, actions, error); 2572 } 2573 2574 /** 2575 * Flow driver apply API. This abstracts calling driver specific functions. 2576 * Parent flow (rte_flow) should have driver type (drv_type). It applies 2577 * translated driver flows on to device. flow_drv_translate() must precede. 2578 * 2579 * @param[in] dev 2580 * Pointer to Ethernet device structure. 2581 * @param[in, out] flow 2582 * Pointer to flow structure. 2583 * @param[out] error 2584 * Pointer to error structure. 2585 * 2586 * @return 2587 * 0 on success, a negative errno value otherwise and rte_errno is set. 2588 */ 2589 static inline int 2590 flow_drv_apply(struct rte_eth_dev *dev, struct rte_flow *flow, 2591 struct rte_flow_error *error) 2592 { 2593 const struct mlx5_flow_driver_ops *fops; 2594 enum mlx5_flow_drv_type type = flow->drv_type; 2595 2596 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 2597 fops = flow_get_drv_ops(type); 2598 return fops->apply(dev, flow, error); 2599 } 2600 2601 /** 2602 * Flow driver remove API. This abstracts calling driver specific functions. 2603 * Parent flow (rte_flow) should have driver type (drv_type). It removes a flow 2604 * on device. All the resources of the flow should be freed by calling 2605 * flow_drv_destroy(). 2606 * 2607 * @param[in] dev 2608 * Pointer to Ethernet device. 2609 * @param[in, out] flow 2610 * Pointer to flow structure. 2611 */ 2612 static inline void 2613 flow_drv_remove(struct rte_eth_dev *dev, struct rte_flow *flow) 2614 { 2615 const struct mlx5_flow_driver_ops *fops; 2616 enum mlx5_flow_drv_type type = flow->drv_type; 2617 2618 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 2619 fops = flow_get_drv_ops(type); 2620 fops->remove(dev, flow); 2621 } 2622 2623 /** 2624 * Flow driver destroy API. This abstracts calling driver specific functions. 2625 * Parent flow (rte_flow) should have driver type (drv_type). It removes a flow 2626 * on device and releases resources of the flow. 2627 * 2628 * @param[in] dev 2629 * Pointer to Ethernet device. 2630 * @param[in, out] flow 2631 * Pointer to flow structure. 2632 */ 2633 static inline void 2634 flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) 2635 { 2636 const struct mlx5_flow_driver_ops *fops; 2637 enum mlx5_flow_drv_type type = flow->drv_type; 2638 2639 flow_mreg_split_qrss_release(dev, flow); 2640 MLX5_ASSERT(type > MLX5_FLOW_TYPE_MIN && type < MLX5_FLOW_TYPE_MAX); 2641 fops = flow_get_drv_ops(type); 2642 fops->destroy(dev, flow); 2643 } 2644 2645 /** 2646 * Validate a flow supported by the NIC. 2647 * 2648 * @see rte_flow_validate() 2649 * @see rte_flow_ops 2650 */ 2651 int 2652 mlx5_flow_validate(struct rte_eth_dev *dev, 2653 const struct rte_flow_attr *attr, 2654 const struct rte_flow_item items[], 2655 const struct rte_flow_action actions[], 2656 struct rte_flow_error *error) 2657 { 2658 int ret; 2659 2660 ret = flow_drv_validate(dev, attr, items, actions, true, error); 2661 if (ret < 0) 2662 return ret; 2663 return 0; 2664 } 2665 2666 /** 2667 * Get RSS action from the action list. 2668 * 2669 * @param[in] actions 2670 * Pointer to the list of actions. 2671 * 2672 * @return 2673 * Pointer to the RSS action if exist, else return NULL. 2674 */ 2675 static const struct rte_flow_action_rss* 2676 flow_get_rss_action(const struct rte_flow_action actions[]) 2677 { 2678 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2679 switch (actions->type) { 2680 case RTE_FLOW_ACTION_TYPE_RSS: 2681 return (const struct rte_flow_action_rss *) 2682 actions->conf; 2683 default: 2684 break; 2685 } 2686 } 2687 return NULL; 2688 } 2689 2690 static unsigned int 2691 find_graph_root(const struct rte_flow_item pattern[], uint32_t rss_level) 2692 { 2693 const struct rte_flow_item *item; 2694 unsigned int has_vlan = 0; 2695 2696 for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { 2697 if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) { 2698 has_vlan = 1; 2699 break; 2700 } 2701 } 2702 if (has_vlan) 2703 return rss_level < 2 ? MLX5_EXPANSION_ROOT_ETH_VLAN : 2704 MLX5_EXPANSION_ROOT_OUTER_ETH_VLAN; 2705 return rss_level < 2 ? MLX5_EXPANSION_ROOT : 2706 MLX5_EXPANSION_ROOT_OUTER; 2707 } 2708 2709 /** 2710 * Get layer flags from the prefix flow. 2711 * 2712 * Some flows may be split to several subflows, the prefix subflow gets the 2713 * match items and the suffix sub flow gets the actions. 2714 * Some actions need the user defined match item flags to get the detail for 2715 * the action. 2716 * This function helps the suffix flow to get the item layer flags from prefix 2717 * subflow. 2718 * 2719 * @param[in] dev_flow 2720 * Pointer the created preifx subflow. 2721 * 2722 * @return 2723 * The layers get from prefix subflow. 2724 */ 2725 static inline uint64_t 2726 flow_get_prefix_layer_flags(struct mlx5_flow *dev_flow) 2727 { 2728 uint64_t layers = 0; 2729 2730 /* If no decap actions, use the layers directly. */ 2731 if (!(dev_flow->actions & MLX5_FLOW_ACTION_DECAP)) 2732 return dev_flow->layers; 2733 /* Convert L3 layers with decap action. */ 2734 if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L3_IPV4) 2735 layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV4; 2736 else if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L3_IPV6) 2737 layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV6; 2738 /* Convert L4 layers with decap action. */ 2739 if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L4_TCP) 2740 layers |= MLX5_FLOW_LAYER_OUTER_L4_TCP; 2741 else if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L4_UDP) 2742 layers |= MLX5_FLOW_LAYER_OUTER_L4_UDP; 2743 return layers; 2744 } 2745 2746 /** 2747 * Get metadata split action information. 2748 * 2749 * @param[in] actions 2750 * Pointer to the list of actions. 2751 * @param[out] qrss 2752 * Pointer to the return pointer. 2753 * @param[out] qrss_type 2754 * Pointer to the action type to return. RTE_FLOW_ACTION_TYPE_END is returned 2755 * if no QUEUE/RSS is found. 2756 * @param[out] encap_idx 2757 * Pointer to the index of the encap action if exists, otherwise the last 2758 * action index. 2759 * 2760 * @return 2761 * Total number of actions. 2762 */ 2763 static int 2764 flow_parse_metadata_split_actions_info(const struct rte_flow_action actions[], 2765 const struct rte_flow_action **qrss, 2766 int *encap_idx) 2767 { 2768 const struct rte_flow_action_raw_encap *raw_encap; 2769 int actions_n = 0; 2770 int raw_decap_idx = -1; 2771 2772 *encap_idx = -1; 2773 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2774 switch (actions->type) { 2775 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 2776 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 2777 *encap_idx = actions_n; 2778 break; 2779 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 2780 raw_decap_idx = actions_n; 2781 break; 2782 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 2783 raw_encap = actions->conf; 2784 if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE) 2785 *encap_idx = raw_decap_idx != -1 ? 2786 raw_decap_idx : actions_n; 2787 break; 2788 case RTE_FLOW_ACTION_TYPE_QUEUE: 2789 case RTE_FLOW_ACTION_TYPE_RSS: 2790 *qrss = actions; 2791 break; 2792 default: 2793 break; 2794 } 2795 actions_n++; 2796 } 2797 if (*encap_idx == -1) 2798 *encap_idx = actions_n; 2799 /* Count RTE_FLOW_ACTION_TYPE_END. */ 2800 return actions_n + 1; 2801 } 2802 2803 /** 2804 * Check meter action from the action list. 2805 * 2806 * @param[in] actions 2807 * Pointer to the list of actions. 2808 * @param[out] mtr 2809 * Pointer to the meter exist flag. 2810 * 2811 * @return 2812 * Total number of actions. 2813 */ 2814 static int 2815 flow_check_meter_action(const struct rte_flow_action actions[], uint32_t *mtr) 2816 { 2817 int actions_n = 0; 2818 2819 MLX5_ASSERT(mtr); 2820 *mtr = 0; 2821 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2822 switch (actions->type) { 2823 case RTE_FLOW_ACTION_TYPE_METER: 2824 *mtr = 1; 2825 break; 2826 default: 2827 break; 2828 } 2829 actions_n++; 2830 } 2831 /* Count RTE_FLOW_ACTION_TYPE_END. */ 2832 return actions_n + 1; 2833 } 2834 2835 /** 2836 * Check if the flow should be splited due to hairpin. 2837 * The reason for the split is that in current HW we can't 2838 * support encap on Rx, so if a flow have encap we move it 2839 * to Tx. 2840 * 2841 * @param dev 2842 * Pointer to Ethernet device. 2843 * @param[in] attr 2844 * Flow rule attributes. 2845 * @param[in] actions 2846 * Associated actions (list terminated by the END action). 2847 * 2848 * @return 2849 * > 0 the number of actions and the flow should be split, 2850 * 0 when no split required. 2851 */ 2852 static int 2853 flow_check_hairpin_split(struct rte_eth_dev *dev, 2854 const struct rte_flow_attr *attr, 2855 const struct rte_flow_action actions[]) 2856 { 2857 int queue_action = 0; 2858 int action_n = 0; 2859 int encap = 0; 2860 const struct rte_flow_action_queue *queue; 2861 const struct rte_flow_action_rss *rss; 2862 const struct rte_flow_action_raw_encap *raw_encap; 2863 2864 if (!attr->ingress) 2865 return 0; 2866 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 2867 switch (actions->type) { 2868 case RTE_FLOW_ACTION_TYPE_QUEUE: 2869 queue = actions->conf; 2870 if (queue == NULL) 2871 return 0; 2872 if (mlx5_rxq_get_type(dev, queue->index) != 2873 MLX5_RXQ_TYPE_HAIRPIN) 2874 return 0; 2875 queue_action = 1; 2876 action_n++; 2877 break; 2878 case RTE_FLOW_ACTION_TYPE_RSS: 2879 rss = actions->conf; 2880 if (rss == NULL || rss->queue_num == 0) 2881 return 0; 2882 if (mlx5_rxq_get_type(dev, rss->queue[0]) != 2883 MLX5_RXQ_TYPE_HAIRPIN) 2884 return 0; 2885 queue_action = 1; 2886 action_n++; 2887 break; 2888 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 2889 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 2890 encap = 1; 2891 action_n++; 2892 break; 2893 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 2894 raw_encap = actions->conf; 2895 if (raw_encap->size > 2896 (sizeof(struct rte_flow_item_eth) + 2897 sizeof(struct rte_flow_item_ipv4))) 2898 encap = 1; 2899 action_n++; 2900 break; 2901 default: 2902 action_n++; 2903 break; 2904 } 2905 } 2906 if (encap == 1 && queue_action) 2907 return action_n; 2908 return 0; 2909 } 2910 2911 /* Declare flow create/destroy prototype in advance. */ 2912 static struct rte_flow * 2913 flow_list_create(struct rte_eth_dev *dev, struct mlx5_flows *list, 2914 const struct rte_flow_attr *attr, 2915 const struct rte_flow_item items[], 2916 const struct rte_flow_action actions[], 2917 bool external, struct rte_flow_error *error); 2918 2919 static void 2920 flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list, 2921 struct rte_flow *flow); 2922 2923 /** 2924 * Add a flow of copying flow metadata registers in RX_CP_TBL. 2925 * 2926 * As mark_id is unique, if there's already a registered flow for the mark_id, 2927 * return by increasing the reference counter of the resource. Otherwise, create 2928 * the resource (mcp_res) and flow. 2929 * 2930 * Flow looks like, 2931 * - If ingress port is ANY and reg_c[1] is mark_id, 2932 * flow_tag := mark_id, reg_b := reg_c[0] and jump to RX_ACT_TBL. 2933 * 2934 * For default flow (zero mark_id), flow is like, 2935 * - If ingress port is ANY, 2936 * reg_b := reg_c[0] and jump to RX_ACT_TBL. 2937 * 2938 * @param dev 2939 * Pointer to Ethernet device. 2940 * @param mark_id 2941 * ID of MARK action, zero means default flow for META. 2942 * @param[out] error 2943 * Perform verbose error reporting if not NULL. 2944 * 2945 * @return 2946 * Associated resource on success, NULL otherwise and rte_errno is set. 2947 */ 2948 static struct mlx5_flow_mreg_copy_resource * 2949 flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id, 2950 struct rte_flow_error *error) 2951 { 2952 struct mlx5_priv *priv = dev->data->dev_private; 2953 struct rte_flow_attr attr = { 2954 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP, 2955 .ingress = 1, 2956 }; 2957 struct mlx5_rte_flow_item_tag tag_spec = { 2958 .data = mark_id, 2959 }; 2960 struct rte_flow_item items[] = { 2961 [1] = { .type = RTE_FLOW_ITEM_TYPE_END, }, 2962 }; 2963 struct rte_flow_action_mark ftag = { 2964 .id = mark_id, 2965 }; 2966 struct mlx5_flow_action_copy_mreg cp_mreg = { 2967 .dst = REG_B, 2968 .src = 0, 2969 }; 2970 struct rte_flow_action_jump jump = { 2971 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP, 2972 }; 2973 struct rte_flow_action actions[] = { 2974 [3] = { .type = RTE_FLOW_ACTION_TYPE_END, }, 2975 }; 2976 struct mlx5_flow_mreg_copy_resource *mcp_res; 2977 int ret; 2978 2979 /* Fill the register fileds in the flow. */ 2980 ret = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, error); 2981 if (ret < 0) 2982 return NULL; 2983 tag_spec.id = ret; 2984 ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_RX, 0, error); 2985 if (ret < 0) 2986 return NULL; 2987 cp_mreg.src = ret; 2988 /* Check if already registered. */ 2989 MLX5_ASSERT(priv->mreg_cp_tbl); 2990 mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl, mark_id); 2991 if (mcp_res) { 2992 /* For non-default rule. */ 2993 if (mark_id != MLX5_DEFAULT_COPY_ID) 2994 mcp_res->refcnt++; 2995 MLX5_ASSERT(mark_id != MLX5_DEFAULT_COPY_ID || 2996 mcp_res->refcnt == 1); 2997 return mcp_res; 2998 } 2999 /* Provide the full width of FLAG specific value. */ 3000 if (mark_id == (priv->sh->dv_regc0_mask & MLX5_FLOW_MARK_DEFAULT)) 3001 tag_spec.data = MLX5_FLOW_MARK_DEFAULT; 3002 /* Build a new flow. */ 3003 if (mark_id != MLX5_DEFAULT_COPY_ID) { 3004 items[0] = (struct rte_flow_item){ 3005 .type = MLX5_RTE_FLOW_ITEM_TYPE_TAG, 3006 .spec = &tag_spec, 3007 }; 3008 items[1] = (struct rte_flow_item){ 3009 .type = RTE_FLOW_ITEM_TYPE_END, 3010 }; 3011 actions[0] = (struct rte_flow_action){ 3012 .type = MLX5_RTE_FLOW_ACTION_TYPE_MARK, 3013 .conf = &ftag, 3014 }; 3015 actions[1] = (struct rte_flow_action){ 3016 .type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 3017 .conf = &cp_mreg, 3018 }; 3019 actions[2] = (struct rte_flow_action){ 3020 .type = RTE_FLOW_ACTION_TYPE_JUMP, 3021 .conf = &jump, 3022 }; 3023 actions[3] = (struct rte_flow_action){ 3024 .type = RTE_FLOW_ACTION_TYPE_END, 3025 }; 3026 } else { 3027 /* Default rule, wildcard match. */ 3028 attr.priority = MLX5_FLOW_PRIO_RSVD; 3029 items[0] = (struct rte_flow_item){ 3030 .type = RTE_FLOW_ITEM_TYPE_END, 3031 }; 3032 actions[0] = (struct rte_flow_action){ 3033 .type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 3034 .conf = &cp_mreg, 3035 }; 3036 actions[1] = (struct rte_flow_action){ 3037 .type = RTE_FLOW_ACTION_TYPE_JUMP, 3038 .conf = &jump, 3039 }; 3040 actions[2] = (struct rte_flow_action){ 3041 .type = RTE_FLOW_ACTION_TYPE_END, 3042 }; 3043 } 3044 /* Build a new entry. */ 3045 mcp_res = rte_zmalloc(__func__, sizeof(*mcp_res), 0); 3046 if (!mcp_res) { 3047 rte_errno = ENOMEM; 3048 return NULL; 3049 } 3050 /* 3051 * The copy Flows are not included in any list. There 3052 * ones are referenced from other Flows and can not 3053 * be applied, removed, deleted in ardbitrary order 3054 * by list traversing. 3055 */ 3056 mcp_res->flow = flow_list_create(dev, NULL, &attr, items, 3057 actions, false, error); 3058 if (!mcp_res->flow) 3059 goto error; 3060 mcp_res->refcnt++; 3061 mcp_res->hlist_ent.key = mark_id; 3062 ret = mlx5_hlist_insert(priv->mreg_cp_tbl, 3063 &mcp_res->hlist_ent); 3064 MLX5_ASSERT(!ret); 3065 if (ret) 3066 goto error; 3067 return mcp_res; 3068 error: 3069 if (mcp_res->flow) 3070 flow_list_destroy(dev, NULL, mcp_res->flow); 3071 rte_free(mcp_res); 3072 return NULL; 3073 } 3074 3075 /** 3076 * Release flow in RX_CP_TBL. 3077 * 3078 * @param dev 3079 * Pointer to Ethernet device. 3080 * @flow 3081 * Parent flow for wich copying is provided. 3082 */ 3083 static void 3084 flow_mreg_del_copy_action(struct rte_eth_dev *dev, 3085 struct rte_flow *flow) 3086 { 3087 struct mlx5_flow_mreg_copy_resource *mcp_res = flow->mreg_copy; 3088 struct mlx5_priv *priv = dev->data->dev_private; 3089 3090 if (!mcp_res || !priv->mreg_cp_tbl) 3091 return; 3092 if (flow->copy_applied) { 3093 MLX5_ASSERT(mcp_res->appcnt); 3094 flow->copy_applied = 0; 3095 --mcp_res->appcnt; 3096 if (!mcp_res->appcnt) 3097 flow_drv_remove(dev, mcp_res->flow); 3098 } 3099 /* 3100 * We do not check availability of metadata registers here, 3101 * because copy resources are not allocated in this case. 3102 */ 3103 if (--mcp_res->refcnt) 3104 return; 3105 MLX5_ASSERT(mcp_res->flow); 3106 flow_list_destroy(dev, NULL, mcp_res->flow); 3107 mlx5_hlist_remove(priv->mreg_cp_tbl, &mcp_res->hlist_ent); 3108 rte_free(mcp_res); 3109 flow->mreg_copy = NULL; 3110 } 3111 3112 /** 3113 * Start flow in RX_CP_TBL. 3114 * 3115 * @param dev 3116 * Pointer to Ethernet device. 3117 * @flow 3118 * Parent flow for wich copying is provided. 3119 * 3120 * @return 3121 * 0 on success, a negative errno value otherwise and rte_errno is set. 3122 */ 3123 static int 3124 flow_mreg_start_copy_action(struct rte_eth_dev *dev, 3125 struct rte_flow *flow) 3126 { 3127 struct mlx5_flow_mreg_copy_resource *mcp_res = flow->mreg_copy; 3128 int ret; 3129 3130 if (!mcp_res || flow->copy_applied) 3131 return 0; 3132 if (!mcp_res->appcnt) { 3133 ret = flow_drv_apply(dev, mcp_res->flow, NULL); 3134 if (ret) 3135 return ret; 3136 } 3137 ++mcp_res->appcnt; 3138 flow->copy_applied = 1; 3139 return 0; 3140 } 3141 3142 /** 3143 * Stop flow in RX_CP_TBL. 3144 * 3145 * @param dev 3146 * Pointer to Ethernet device. 3147 * @flow 3148 * Parent flow for wich copying is provided. 3149 */ 3150 static void 3151 flow_mreg_stop_copy_action(struct rte_eth_dev *dev, 3152 struct rte_flow *flow) 3153 { 3154 struct mlx5_flow_mreg_copy_resource *mcp_res = flow->mreg_copy; 3155 3156 if (!mcp_res || !flow->copy_applied) 3157 return; 3158 MLX5_ASSERT(mcp_res->appcnt); 3159 --mcp_res->appcnt; 3160 flow->copy_applied = 0; 3161 if (!mcp_res->appcnt) 3162 flow_drv_remove(dev, mcp_res->flow); 3163 } 3164 3165 /** 3166 * Remove the default copy action from RX_CP_TBL. 3167 * 3168 * @param dev 3169 * Pointer to Ethernet device. 3170 */ 3171 static void 3172 flow_mreg_del_default_copy_action(struct rte_eth_dev *dev) 3173 { 3174 struct mlx5_flow_mreg_copy_resource *mcp_res; 3175 struct mlx5_priv *priv = dev->data->dev_private; 3176 3177 /* Check if default flow is registered. */ 3178 if (!priv->mreg_cp_tbl) 3179 return; 3180 mcp_res = (void *)mlx5_hlist_lookup(priv->mreg_cp_tbl, 3181 MLX5_DEFAULT_COPY_ID); 3182 if (!mcp_res) 3183 return; 3184 MLX5_ASSERT(mcp_res->flow); 3185 flow_list_destroy(dev, NULL, mcp_res->flow); 3186 mlx5_hlist_remove(priv->mreg_cp_tbl, &mcp_res->hlist_ent); 3187 rte_free(mcp_res); 3188 } 3189 3190 /** 3191 * Add the default copy action in in RX_CP_TBL. 3192 * 3193 * @param dev 3194 * Pointer to Ethernet device. 3195 * @param[out] error 3196 * Perform verbose error reporting if not NULL. 3197 * 3198 * @return 3199 * 0 for success, negative value otherwise and rte_errno is set. 3200 */ 3201 static int 3202 flow_mreg_add_default_copy_action(struct rte_eth_dev *dev, 3203 struct rte_flow_error *error) 3204 { 3205 struct mlx5_priv *priv = dev->data->dev_private; 3206 struct mlx5_flow_mreg_copy_resource *mcp_res; 3207 3208 /* Check whether extensive metadata feature is engaged. */ 3209 if (!priv->config.dv_flow_en || 3210 priv->config.dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || 3211 !mlx5_flow_ext_mreg_supported(dev) || 3212 !priv->sh->dv_regc0_mask) 3213 return 0; 3214 mcp_res = flow_mreg_add_copy_action(dev, MLX5_DEFAULT_COPY_ID, error); 3215 if (!mcp_res) 3216 return -rte_errno; 3217 return 0; 3218 } 3219 3220 /** 3221 * Add a flow of copying flow metadata registers in RX_CP_TBL. 3222 * 3223 * All the flow having Q/RSS action should be split by 3224 * flow_mreg_split_qrss_prep() to pass by RX_CP_TBL. A flow in the RX_CP_TBL 3225 * performs the following, 3226 * - CQE->flow_tag := reg_c[1] (MARK) 3227 * - CQE->flow_table_metadata (reg_b) := reg_c[0] (META) 3228 * As CQE's flow_tag is not a register, it can't be simply copied from reg_c[1] 3229 * but there should be a flow per each MARK ID set by MARK action. 3230 * 3231 * For the aforementioned reason, if there's a MARK action in flow's action 3232 * list, a corresponding flow should be added to the RX_CP_TBL in order to copy 3233 * the MARK ID to CQE's flow_tag like, 3234 * - If reg_c[1] is mark_id, 3235 * flow_tag := mark_id, reg_b := reg_c[0] and jump to RX_ACT_TBL. 3236 * 3237 * For SET_META action which stores value in reg_c[0], as the destination is 3238 * also a flow metadata register (reg_b), adding a default flow is enough. Zero 3239 * MARK ID means the default flow. The default flow looks like, 3240 * - For all flow, reg_b := reg_c[0] and jump to RX_ACT_TBL. 3241 * 3242 * @param dev 3243 * Pointer to Ethernet device. 3244 * @param flow 3245 * Pointer to flow structure. 3246 * @param[in] actions 3247 * Pointer to the list of actions. 3248 * @param[out] error 3249 * Perform verbose error reporting if not NULL. 3250 * 3251 * @return 3252 * 0 on success, negative value otherwise and rte_errno is set. 3253 */ 3254 static int 3255 flow_mreg_update_copy_table(struct rte_eth_dev *dev, 3256 struct rte_flow *flow, 3257 const struct rte_flow_action *actions, 3258 struct rte_flow_error *error) 3259 { 3260 struct mlx5_priv *priv = dev->data->dev_private; 3261 struct mlx5_dev_config *config = &priv->config; 3262 struct mlx5_flow_mreg_copy_resource *mcp_res; 3263 const struct rte_flow_action_mark *mark; 3264 3265 /* Check whether extensive metadata feature is engaged. */ 3266 if (!config->dv_flow_en || 3267 config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || 3268 !mlx5_flow_ext_mreg_supported(dev) || 3269 !priv->sh->dv_regc0_mask) 3270 return 0; 3271 /* Find MARK action. */ 3272 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 3273 switch (actions->type) { 3274 case RTE_FLOW_ACTION_TYPE_FLAG: 3275 mcp_res = flow_mreg_add_copy_action 3276 (dev, MLX5_FLOW_MARK_DEFAULT, error); 3277 if (!mcp_res) 3278 return -rte_errno; 3279 flow->mreg_copy = mcp_res; 3280 if (dev->data->dev_started) { 3281 mcp_res->appcnt++; 3282 flow->copy_applied = 1; 3283 } 3284 return 0; 3285 case RTE_FLOW_ACTION_TYPE_MARK: 3286 mark = (const struct rte_flow_action_mark *) 3287 actions->conf; 3288 mcp_res = 3289 flow_mreg_add_copy_action(dev, mark->id, error); 3290 if (!mcp_res) 3291 return -rte_errno; 3292 flow->mreg_copy = mcp_res; 3293 if (dev->data->dev_started) { 3294 mcp_res->appcnt++; 3295 flow->copy_applied = 1; 3296 } 3297 return 0; 3298 default: 3299 break; 3300 } 3301 } 3302 return 0; 3303 } 3304 3305 #define MLX5_MAX_SPLIT_ACTIONS 24 3306 #define MLX5_MAX_SPLIT_ITEMS 24 3307 3308 /** 3309 * Split the hairpin flow. 3310 * Since HW can't support encap on Rx we move the encap to Tx. 3311 * If the count action is after the encap then we also 3312 * move the count action. in this case the count will also measure 3313 * the outer bytes. 3314 * 3315 * @param dev 3316 * Pointer to Ethernet device. 3317 * @param[in] actions 3318 * Associated actions (list terminated by the END action). 3319 * @param[out] actions_rx 3320 * Rx flow actions. 3321 * @param[out] actions_tx 3322 * Tx flow actions.. 3323 * @param[out] pattern_tx 3324 * The pattern items for the Tx flow. 3325 * @param[out] flow_id 3326 * The flow ID connected to this flow. 3327 * 3328 * @return 3329 * 0 on success. 3330 */ 3331 static int 3332 flow_hairpin_split(struct rte_eth_dev *dev, 3333 const struct rte_flow_action actions[], 3334 struct rte_flow_action actions_rx[], 3335 struct rte_flow_action actions_tx[], 3336 struct rte_flow_item pattern_tx[], 3337 uint32_t *flow_id) 3338 { 3339 struct mlx5_priv *priv = dev->data->dev_private; 3340 const struct rte_flow_action_raw_encap *raw_encap; 3341 const struct rte_flow_action_raw_decap *raw_decap; 3342 struct mlx5_rte_flow_action_set_tag *set_tag; 3343 struct rte_flow_action *tag_action; 3344 struct mlx5_rte_flow_item_tag *tag_item; 3345 struct rte_flow_item *item; 3346 char *addr; 3347 int encap = 0; 3348 3349 mlx5_flow_id_get(priv->sh->flow_id_pool, flow_id); 3350 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 3351 switch (actions->type) { 3352 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 3353 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 3354 rte_memcpy(actions_tx, actions, 3355 sizeof(struct rte_flow_action)); 3356 actions_tx++; 3357 break; 3358 case RTE_FLOW_ACTION_TYPE_COUNT: 3359 if (encap) { 3360 rte_memcpy(actions_tx, actions, 3361 sizeof(struct rte_flow_action)); 3362 actions_tx++; 3363 } else { 3364 rte_memcpy(actions_rx, actions, 3365 sizeof(struct rte_flow_action)); 3366 actions_rx++; 3367 } 3368 break; 3369 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 3370 raw_encap = actions->conf; 3371 if (raw_encap->size > 3372 (sizeof(struct rte_flow_item_eth) + 3373 sizeof(struct rte_flow_item_ipv4))) { 3374 memcpy(actions_tx, actions, 3375 sizeof(struct rte_flow_action)); 3376 actions_tx++; 3377 encap = 1; 3378 } else { 3379 rte_memcpy(actions_rx, actions, 3380 sizeof(struct rte_flow_action)); 3381 actions_rx++; 3382 } 3383 break; 3384 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 3385 raw_decap = actions->conf; 3386 if (raw_decap->size < 3387 (sizeof(struct rte_flow_item_eth) + 3388 sizeof(struct rte_flow_item_ipv4))) { 3389 memcpy(actions_tx, actions, 3390 sizeof(struct rte_flow_action)); 3391 actions_tx++; 3392 } else { 3393 rte_memcpy(actions_rx, actions, 3394 sizeof(struct rte_flow_action)); 3395 actions_rx++; 3396 } 3397 break; 3398 default: 3399 rte_memcpy(actions_rx, actions, 3400 sizeof(struct rte_flow_action)); 3401 actions_rx++; 3402 break; 3403 } 3404 } 3405 /* Add set meta action and end action for the Rx flow. */ 3406 tag_action = actions_rx; 3407 tag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG; 3408 actions_rx++; 3409 rte_memcpy(actions_rx, actions, sizeof(struct rte_flow_action)); 3410 actions_rx++; 3411 set_tag = (void *)actions_rx; 3412 set_tag->id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_RX, 0, NULL); 3413 MLX5_ASSERT(set_tag->id > REG_NONE); 3414 set_tag->data = *flow_id; 3415 tag_action->conf = set_tag; 3416 /* Create Tx item list. */ 3417 rte_memcpy(actions_tx, actions, sizeof(struct rte_flow_action)); 3418 addr = (void *)&pattern_tx[2]; 3419 item = pattern_tx; 3420 item->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG; 3421 tag_item = (void *)addr; 3422 tag_item->data = *flow_id; 3423 tag_item->id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_TX, 0, NULL); 3424 MLX5_ASSERT(set_tag->id > REG_NONE); 3425 item->spec = tag_item; 3426 addr += sizeof(struct mlx5_rte_flow_item_tag); 3427 tag_item = (void *)addr; 3428 tag_item->data = UINT32_MAX; 3429 tag_item->id = UINT16_MAX; 3430 item->mask = tag_item; 3431 addr += sizeof(struct mlx5_rte_flow_item_tag); 3432 item->last = NULL; 3433 item++; 3434 item->type = RTE_FLOW_ITEM_TYPE_END; 3435 return 0; 3436 } 3437 3438 /** 3439 * The last stage of splitting chain, just creates the subflow 3440 * without any modification. 3441 * 3442 * @param dev 3443 * Pointer to Ethernet device. 3444 * @param[in] flow 3445 * Parent flow structure pointer. 3446 * @param[in, out] sub_flow 3447 * Pointer to return the created subflow, may be NULL. 3448 * @param[in] prefix_layers 3449 * Prefix subflow layers, may be 0. 3450 * @param[in] attr 3451 * Flow rule attributes. 3452 * @param[in] items 3453 * Pattern specification (list terminated by the END pattern item). 3454 * @param[in] actions 3455 * Associated actions (list terminated by the END action). 3456 * @param[in] external 3457 * This flow rule is created by request external to PMD. 3458 * @param[out] error 3459 * Perform verbose error reporting if not NULL. 3460 * @return 3461 * 0 on success, negative value otherwise 3462 */ 3463 static int 3464 flow_create_split_inner(struct rte_eth_dev *dev, 3465 struct rte_flow *flow, 3466 struct mlx5_flow **sub_flow, 3467 uint64_t prefix_layers, 3468 const struct rte_flow_attr *attr, 3469 const struct rte_flow_item items[], 3470 const struct rte_flow_action actions[], 3471 bool external, struct rte_flow_error *error) 3472 { 3473 struct mlx5_flow *dev_flow; 3474 3475 dev_flow = flow_drv_prepare(flow, attr, items, actions, error); 3476 if (!dev_flow) 3477 return -rte_errno; 3478 dev_flow->flow = flow; 3479 dev_flow->external = external; 3480 /* Subflow object was created, we must include one in the list. */ 3481 LIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next); 3482 /* 3483 * If dev_flow is as one of the suffix flow, some actions in suffix 3484 * flow may need some user defined item layer flags. 3485 */ 3486 if (prefix_layers) 3487 dev_flow->layers = prefix_layers; 3488 if (sub_flow) 3489 *sub_flow = dev_flow; 3490 return flow_drv_translate(dev, dev_flow, attr, items, actions, error); 3491 } 3492 3493 /** 3494 * Split the meter flow. 3495 * 3496 * As meter flow will split to three sub flow, other than meter 3497 * action, the other actions make sense to only meter accepts 3498 * the packet. If it need to be dropped, no other additional 3499 * actions should be take. 3500 * 3501 * One kind of special action which decapsulates the L3 tunnel 3502 * header will be in the prefix sub flow, as not to take the 3503 * L3 tunnel header into account. 3504 * 3505 * @param dev 3506 * Pointer to Ethernet device. 3507 * @param[in] items 3508 * Pattern specification (list terminated by the END pattern item). 3509 * @param[out] sfx_items 3510 * Suffix flow match items (list terminated by the END pattern item). 3511 * @param[in] actions 3512 * Associated actions (list terminated by the END action). 3513 * @param[out] actions_sfx 3514 * Suffix flow actions. 3515 * @param[out] actions_pre 3516 * Prefix flow actions. 3517 * @param[out] pattern_sfx 3518 * The pattern items for the suffix flow. 3519 * @param[out] tag_sfx 3520 * Pointer to suffix flow tag. 3521 * 3522 * @return 3523 * 0 on success. 3524 */ 3525 static int 3526 flow_meter_split_prep(struct rte_eth_dev *dev, 3527 const struct rte_flow_item items[], 3528 struct rte_flow_item sfx_items[], 3529 const struct rte_flow_action actions[], 3530 struct rte_flow_action actions_sfx[], 3531 struct rte_flow_action actions_pre[]) 3532 { 3533 struct rte_flow_action *tag_action = NULL; 3534 struct rte_flow_item *tag_item; 3535 struct mlx5_rte_flow_action_set_tag *set_tag; 3536 struct rte_flow_error error; 3537 const struct rte_flow_action_raw_encap *raw_encap; 3538 const struct rte_flow_action_raw_decap *raw_decap; 3539 struct mlx5_rte_flow_item_tag *tag_spec; 3540 struct mlx5_rte_flow_item_tag *tag_mask; 3541 uint32_t tag_id; 3542 bool copy_vlan = false; 3543 3544 /* Prepare the actions for prefix and suffix flow. */ 3545 for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { 3546 struct rte_flow_action **action_cur = NULL; 3547 3548 switch (actions->type) { 3549 case RTE_FLOW_ACTION_TYPE_METER: 3550 /* Add the extra tag action first. */ 3551 tag_action = actions_pre; 3552 tag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG; 3553 actions_pre++; 3554 action_cur = &actions_pre; 3555 break; 3556 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: 3557 case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: 3558 action_cur = &actions_pre; 3559 break; 3560 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 3561 raw_encap = actions->conf; 3562 if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE) 3563 action_cur = &actions_pre; 3564 break; 3565 case RTE_FLOW_ACTION_TYPE_RAW_DECAP: 3566 raw_decap = actions->conf; 3567 if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE) 3568 action_cur = &actions_pre; 3569 break; 3570 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: 3571 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: 3572 copy_vlan = true; 3573 break; 3574 default: 3575 break; 3576 } 3577 if (!action_cur) 3578 action_cur = &actions_sfx; 3579 memcpy(*action_cur, actions, sizeof(struct rte_flow_action)); 3580 (*action_cur)++; 3581 } 3582 /* Add end action to the actions. */ 3583 actions_sfx->type = RTE_FLOW_ACTION_TYPE_END; 3584 actions_pre->type = RTE_FLOW_ACTION_TYPE_END; 3585 actions_pre++; 3586 /* Set the tag. */ 3587 set_tag = (void *)actions_pre; 3588 set_tag->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error); 3589 /* 3590 * Get the id from the qrss_pool to make qrss share the id with meter. 3591 */ 3592 tag_id = flow_qrss_get_id(dev); 3593 set_tag->data = tag_id << MLX5_MTR_COLOR_BITS; 3594 assert(tag_action); 3595 tag_action->conf = set_tag; 3596 /* Prepare the suffix subflow items. */ 3597 tag_item = sfx_items++; 3598 for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { 3599 int item_type = items->type; 3600 3601 switch (item_type) { 3602 case RTE_FLOW_ITEM_TYPE_PORT_ID: 3603 memcpy(sfx_items, items, sizeof(*sfx_items)); 3604 sfx_items++; 3605 break; 3606 case RTE_FLOW_ITEM_TYPE_VLAN: 3607 if (copy_vlan) { 3608 memcpy(sfx_items, items, sizeof(*sfx_items)); 3609 /* 3610 * Convert to internal match item, it is used 3611 * for vlan push and set vid. 3612 */ 3613 sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_VLAN; 3614 sfx_items++; 3615 } 3616 break; 3617 default: 3618 break; 3619 } 3620 } 3621 sfx_items->type = RTE_FLOW_ITEM_TYPE_END; 3622 sfx_items++; 3623 tag_spec = (struct mlx5_rte_flow_item_tag *)sfx_items; 3624 tag_spec->data = tag_id << MLX5_MTR_COLOR_BITS; 3625 tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error); 3626 tag_mask = tag_spec + 1; 3627 tag_mask->data = 0xffffff00; 3628 tag_item->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG; 3629 tag_item->spec = tag_spec; 3630 tag_item->last = NULL; 3631 tag_item->mask = tag_mask; 3632 return tag_id; 3633 } 3634 3635 /** 3636 * Split action list having QUEUE/RSS for metadata register copy. 3637 * 3638 * Once Q/RSS action is detected in user's action list, the flow action 3639 * should be split in order to copy metadata registers, which will happen in 3640 * RX_CP_TBL like, 3641 * - CQE->flow_tag := reg_c[1] (MARK) 3642 * - CQE->flow_table_metadata (reg_b) := reg_c[0] (META) 3643 * The Q/RSS action will be performed on RX_ACT_TBL after passing by RX_CP_TBL. 3644 * This is because the last action of each flow must be a terminal action 3645 * (QUEUE, RSS or DROP). 3646 * 3647 * Flow ID must be allocated to identify actions in the RX_ACT_TBL and it is 3648 * stored and kept in the mlx5_flow structure per each sub_flow. 3649 * 3650 * The Q/RSS action is replaced with, 3651 * - SET_TAG, setting the allocated flow ID to reg_c[2]. 3652 * And the following JUMP action is added at the end, 3653 * - JUMP, to RX_CP_TBL. 3654 * 3655 * A flow to perform remained Q/RSS action will be created in RX_ACT_TBL by 3656 * flow_create_split_metadata() routine. The flow will look like, 3657 * - If flow ID matches (reg_c[2]), perform Q/RSS. 3658 * 3659 * @param dev 3660 * Pointer to Ethernet device. 3661 * @param[out] split_actions 3662 * Pointer to store split actions to jump to CP_TBL. 3663 * @param[in] actions 3664 * Pointer to the list of original flow actions. 3665 * @param[in] qrss 3666 * Pointer to the Q/RSS action. 3667 * @param[in] actions_n 3668 * Number of original actions. 3669 * @param[out] error 3670 * Perform verbose error reporting if not NULL. 3671 * 3672 * @return 3673 * non-zero unique flow_id on success, otherwise 0 and 3674 * error/rte_error are set. 3675 */ 3676 static uint32_t 3677 flow_mreg_split_qrss_prep(struct rte_eth_dev *dev, 3678 struct rte_flow_action *split_actions, 3679 const struct rte_flow_action *actions, 3680 const struct rte_flow_action *qrss, 3681 int actions_n, struct rte_flow_error *error) 3682 { 3683 struct mlx5_rte_flow_action_set_tag *set_tag; 3684 struct rte_flow_action_jump *jump; 3685 const int qrss_idx = qrss - actions; 3686 uint32_t flow_id = 0; 3687 int ret = 0; 3688 3689 /* 3690 * Given actions will be split 3691 * - Replace QUEUE/RSS action with SET_TAG to set flow ID. 3692 * - Add jump to mreg CP_TBL. 3693 * As a result, there will be one more action. 3694 */ 3695 ++actions_n; 3696 memcpy(split_actions, actions, sizeof(*split_actions) * actions_n); 3697 set_tag = (void *)(split_actions + actions_n); 3698 /* 3699 * If tag action is not set to void(it means we are not the meter 3700 * suffix flow), add the tag action. Since meter suffix flow already 3701 * has the tag added. 3702 */ 3703 if (split_actions[qrss_idx].type != RTE_FLOW_ACTION_TYPE_VOID) { 3704 /* 3705 * Allocate the new subflow ID. This one is unique within 3706 * device and not shared with representors. Otherwise, 3707 * we would have to resolve multi-thread access synch 3708 * issue. Each flow on the shared device is appended 3709 * with source vport identifier, so the resulting 3710 * flows will be unique in the shared (by master and 3711 * representors) domain even if they have coinciding 3712 * IDs. 3713 */ 3714 flow_id = flow_qrss_get_id(dev); 3715 if (!flow_id) 3716 return rte_flow_error_set(error, ENOMEM, 3717 RTE_FLOW_ERROR_TYPE_ACTION, 3718 NULL, "can't allocate id " 3719 "for split Q/RSS subflow"); 3720 /* Internal SET_TAG action to set flow ID. */ 3721 *set_tag = (struct mlx5_rte_flow_action_set_tag){ 3722 .data = flow_id, 3723 }; 3724 ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, error); 3725 if (ret < 0) 3726 return ret; 3727 set_tag->id = ret; 3728 /* Construct new actions array. */ 3729 /* Replace QUEUE/RSS action. */ 3730 split_actions[qrss_idx] = (struct rte_flow_action){ 3731 .type = MLX5_RTE_FLOW_ACTION_TYPE_TAG, 3732 .conf = set_tag, 3733 }; 3734 } 3735 /* JUMP action to jump to mreg copy table (CP_TBL). */ 3736 jump = (void *)(set_tag + 1); 3737 *jump = (struct rte_flow_action_jump){ 3738 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP, 3739 }; 3740 split_actions[actions_n - 2] = (struct rte_flow_action){ 3741 .type = RTE_FLOW_ACTION_TYPE_JUMP, 3742 .conf = jump, 3743 }; 3744 split_actions[actions_n - 1] = (struct rte_flow_action){ 3745 .type = RTE_FLOW_ACTION_TYPE_END, 3746 }; 3747 return flow_id; 3748 } 3749 3750 /** 3751 * Extend the given action list for Tx metadata copy. 3752 * 3753 * Copy the given action list to the ext_actions and add flow metadata register 3754 * copy action in order to copy reg_a set by WQE to reg_c[0]. 3755 * 3756 * @param[out] ext_actions 3757 * Pointer to the extended action list. 3758 * @param[in] actions 3759 * Pointer to the list of actions. 3760 * @param[in] actions_n 3761 * Number of actions in the list. 3762 * @param[out] error 3763 * Perform verbose error reporting if not NULL. 3764 * @param[in] encap_idx 3765 * The encap action inndex. 3766 * 3767 * @return 3768 * 0 on success, negative value otherwise 3769 */ 3770 static int 3771 flow_mreg_tx_copy_prep(struct rte_eth_dev *dev, 3772 struct rte_flow_action *ext_actions, 3773 const struct rte_flow_action *actions, 3774 int actions_n, struct rte_flow_error *error, 3775 int encap_idx) 3776 { 3777 struct mlx5_flow_action_copy_mreg *cp_mreg = 3778 (struct mlx5_flow_action_copy_mreg *) 3779 (ext_actions + actions_n + 1); 3780 int ret; 3781 3782 ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_RX, 0, error); 3783 if (ret < 0) 3784 return ret; 3785 cp_mreg->dst = ret; 3786 ret = mlx5_flow_get_reg_id(dev, MLX5_METADATA_TX, 0, error); 3787 if (ret < 0) 3788 return ret; 3789 cp_mreg->src = ret; 3790 if (encap_idx != 0) 3791 memcpy(ext_actions, actions, sizeof(*ext_actions) * encap_idx); 3792 if (encap_idx == actions_n - 1) { 3793 ext_actions[actions_n - 1] = (struct rte_flow_action){ 3794 .type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 3795 .conf = cp_mreg, 3796 }; 3797 ext_actions[actions_n] = (struct rte_flow_action){ 3798 .type = RTE_FLOW_ACTION_TYPE_END, 3799 }; 3800 } else { 3801 ext_actions[encap_idx] = (struct rte_flow_action){ 3802 .type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 3803 .conf = cp_mreg, 3804 }; 3805 memcpy(ext_actions + encap_idx + 1, actions + encap_idx, 3806 sizeof(*ext_actions) * (actions_n - encap_idx)); 3807 } 3808 return 0; 3809 } 3810 3811 /** 3812 * The splitting for metadata feature. 3813 * 3814 * - Q/RSS action on NIC Rx should be split in order to pass by 3815 * the mreg copy table (RX_CP_TBL) and then it jumps to the 3816 * action table (RX_ACT_TBL) which has the split Q/RSS action. 3817 * 3818 * - All the actions on NIC Tx should have a mreg copy action to 3819 * copy reg_a from WQE to reg_c[0]. 3820 * 3821 * @param dev 3822 * Pointer to Ethernet device. 3823 * @param[in] flow 3824 * Parent flow structure pointer. 3825 * @param[in] prefix_layers 3826 * Prefix flow layer flags. 3827 * @param[in] attr 3828 * Flow rule attributes. 3829 * @param[in] items 3830 * Pattern specification (list terminated by the END pattern item). 3831 * @param[in] actions 3832 * Associated actions (list terminated by the END action). 3833 * @param[in] external 3834 * This flow rule is created by request external to PMD. 3835 * @param[out] error 3836 * Perform verbose error reporting if not NULL. 3837 * @return 3838 * 0 on success, negative value otherwise 3839 */ 3840 static int 3841 flow_create_split_metadata(struct rte_eth_dev *dev, 3842 struct rte_flow *flow, 3843 uint64_t prefix_layers, 3844 const struct rte_flow_attr *attr, 3845 const struct rte_flow_item items[], 3846 const struct rte_flow_action actions[], 3847 bool external, struct rte_flow_error *error) 3848 { 3849 struct mlx5_priv *priv = dev->data->dev_private; 3850 struct mlx5_dev_config *config = &priv->config; 3851 const struct rte_flow_action *qrss = NULL; 3852 struct rte_flow_action *ext_actions = NULL; 3853 struct mlx5_flow *dev_flow = NULL; 3854 uint32_t qrss_id = 0; 3855 int mtr_sfx = 0; 3856 size_t act_size; 3857 int actions_n; 3858 int encap_idx; 3859 int ret; 3860 3861 /* Check whether extensive metadata feature is engaged. */ 3862 if (!config->dv_flow_en || 3863 config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY || 3864 !mlx5_flow_ext_mreg_supported(dev)) 3865 return flow_create_split_inner(dev, flow, NULL, prefix_layers, 3866 attr, items, actions, external, 3867 error); 3868 actions_n = flow_parse_metadata_split_actions_info(actions, &qrss, 3869 &encap_idx); 3870 if (qrss) { 3871 /* Exclude hairpin flows from splitting. */ 3872 if (qrss->type == RTE_FLOW_ACTION_TYPE_QUEUE) { 3873 const struct rte_flow_action_queue *queue; 3874 3875 queue = qrss->conf; 3876 if (mlx5_rxq_get_type(dev, queue->index) == 3877 MLX5_RXQ_TYPE_HAIRPIN) 3878 qrss = NULL; 3879 } else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) { 3880 const struct rte_flow_action_rss *rss; 3881 3882 rss = qrss->conf; 3883 if (mlx5_rxq_get_type(dev, rss->queue[0]) == 3884 MLX5_RXQ_TYPE_HAIRPIN) 3885 qrss = NULL; 3886 } 3887 } 3888 if (qrss) { 3889 /* Check if it is in meter suffix table. */ 3890 mtr_sfx = attr->group == (attr->transfer ? 3891 (MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) : 3892 MLX5_FLOW_TABLE_LEVEL_SUFFIX); 3893 /* 3894 * Q/RSS action on NIC Rx should be split in order to pass by 3895 * the mreg copy table (RX_CP_TBL) and then it jumps to the 3896 * action table (RX_ACT_TBL) which has the split Q/RSS action. 3897 */ 3898 act_size = sizeof(struct rte_flow_action) * (actions_n + 1) + 3899 sizeof(struct rte_flow_action_set_tag) + 3900 sizeof(struct rte_flow_action_jump); 3901 ext_actions = rte_zmalloc(__func__, act_size, 0); 3902 if (!ext_actions) 3903 return rte_flow_error_set(error, ENOMEM, 3904 RTE_FLOW_ERROR_TYPE_ACTION, 3905 NULL, "no memory to split " 3906 "metadata flow"); 3907 /* 3908 * If we are the suffix flow of meter, tag already exist. 3909 * Set the tag action to void. 3910 */ 3911 if (mtr_sfx) 3912 ext_actions[qrss - actions].type = 3913 RTE_FLOW_ACTION_TYPE_VOID; 3914 else 3915 ext_actions[qrss - actions].type = 3916 MLX5_RTE_FLOW_ACTION_TYPE_TAG; 3917 /* 3918 * Create the new actions list with removed Q/RSS action 3919 * and appended set tag and jump to register copy table 3920 * (RX_CP_TBL). We should preallocate unique tag ID here 3921 * in advance, because it is needed for set tag action. 3922 */ 3923 qrss_id = flow_mreg_split_qrss_prep(dev, ext_actions, actions, 3924 qrss, actions_n, error); 3925 if (!mtr_sfx && !qrss_id) { 3926 ret = -rte_errno; 3927 goto exit; 3928 } 3929 } else if (attr->egress && !attr->transfer) { 3930 /* 3931 * All the actions on NIC Tx should have a metadata register 3932 * copy action to copy reg_a from WQE to reg_c[meta] 3933 */ 3934 act_size = sizeof(struct rte_flow_action) * (actions_n + 1) + 3935 sizeof(struct mlx5_flow_action_copy_mreg); 3936 ext_actions = rte_zmalloc(__func__, act_size, 0); 3937 if (!ext_actions) 3938 return rte_flow_error_set(error, ENOMEM, 3939 RTE_FLOW_ERROR_TYPE_ACTION, 3940 NULL, "no memory to split " 3941 "metadata flow"); 3942 /* Create the action list appended with copy register. */ 3943 ret = flow_mreg_tx_copy_prep(dev, ext_actions, actions, 3944 actions_n, error, encap_idx); 3945 if (ret < 0) 3946 goto exit; 3947 } 3948 /* Add the unmodified original or prefix subflow. */ 3949 ret = flow_create_split_inner(dev, flow, &dev_flow, prefix_layers, attr, 3950 items, ext_actions ? ext_actions : 3951 actions, external, error); 3952 if (ret < 0) 3953 goto exit; 3954 MLX5_ASSERT(dev_flow); 3955 if (qrss) { 3956 const struct rte_flow_attr q_attr = { 3957 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP, 3958 .ingress = 1, 3959 }; 3960 /* Internal PMD action to set register. */ 3961 struct mlx5_rte_flow_item_tag q_tag_spec = { 3962 .data = qrss_id, 3963 .id = 0, 3964 }; 3965 struct rte_flow_item q_items[] = { 3966 { 3967 .type = MLX5_RTE_FLOW_ITEM_TYPE_TAG, 3968 .spec = &q_tag_spec, 3969 .last = NULL, 3970 .mask = NULL, 3971 }, 3972 { 3973 .type = RTE_FLOW_ITEM_TYPE_END, 3974 }, 3975 }; 3976 struct rte_flow_action q_actions[] = { 3977 { 3978 .type = qrss->type, 3979 .conf = qrss->conf, 3980 }, 3981 { 3982 .type = RTE_FLOW_ACTION_TYPE_END, 3983 }, 3984 }; 3985 uint64_t layers = flow_get_prefix_layer_flags(dev_flow); 3986 3987 /* 3988 * Configure the tag item only if there is no meter subflow. 3989 * Since tag is already marked in the meter suffix subflow 3990 * we can just use the meter suffix items as is. 3991 */ 3992 if (qrss_id) { 3993 /* Not meter subflow. */ 3994 MLX5_ASSERT(!mtr_sfx); 3995 /* 3996 * Put unique id in prefix flow due to it is destroyed 3997 * after suffix flow and id will be freed after there 3998 * is no actual flows with this id and identifier 3999 * reallocation becomes possible (for example, for 4000 * other flows in other threads). 4001 */ 4002 dev_flow->qrss_id = qrss_id; 4003 qrss_id = 0; 4004 ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0, 4005 error); 4006 if (ret < 0) 4007 goto exit; 4008 q_tag_spec.id = ret; 4009 } 4010 dev_flow = NULL; 4011 /* Add suffix subflow to execute Q/RSS. */ 4012 ret = flow_create_split_inner(dev, flow, &dev_flow, layers, 4013 &q_attr, mtr_sfx ? items : 4014 q_items, q_actions, 4015 external, error); 4016 if (ret < 0) 4017 goto exit; 4018 MLX5_ASSERT(dev_flow); 4019 } 4020 4021 exit: 4022 /* 4023 * We do not destroy the partially created sub_flows in case of error. 4024 * These ones are included into parent flow list and will be destroyed 4025 * by flow_drv_destroy. 4026 */ 4027 flow_qrss_free_id(dev, qrss_id); 4028 rte_free(ext_actions); 4029 return ret; 4030 } 4031 4032 /** 4033 * The splitting for meter feature. 4034 * 4035 * - The meter flow will be split to two flows as prefix and 4036 * suffix flow. The packets make sense only it pass the prefix 4037 * meter action. 4038 * 4039 * - Reg_C_5 is used for the packet to match betweend prefix and 4040 * suffix flow. 4041 * 4042 * @param dev 4043 * Pointer to Ethernet device. 4044 * @param[in] flow 4045 * Parent flow structure pointer. 4046 * @param[in] attr 4047 * Flow rule attributes. 4048 * @param[in] items 4049 * Pattern specification (list terminated by the END pattern item). 4050 * @param[in] actions 4051 * Associated actions (list terminated by the END action). 4052 * @param[in] external 4053 * This flow rule is created by request external to PMD. 4054 * @param[out] error 4055 * Perform verbose error reporting if not NULL. 4056 * @return 4057 * 0 on success, negative value otherwise 4058 */ 4059 static int 4060 flow_create_split_meter(struct rte_eth_dev *dev, 4061 struct rte_flow *flow, 4062 const struct rte_flow_attr *attr, 4063 const struct rte_flow_item items[], 4064 const struct rte_flow_action actions[], 4065 bool external, struct rte_flow_error *error) 4066 { 4067 struct mlx5_priv *priv = dev->data->dev_private; 4068 struct rte_flow_action *sfx_actions = NULL; 4069 struct rte_flow_action *pre_actions = NULL; 4070 struct rte_flow_item *sfx_items = NULL; 4071 struct mlx5_flow *dev_flow = NULL; 4072 struct rte_flow_attr sfx_attr = *attr; 4073 uint32_t mtr = 0; 4074 uint32_t mtr_tag_id = 0; 4075 size_t act_size; 4076 size_t item_size; 4077 int actions_n = 0; 4078 int ret; 4079 4080 if (priv->mtr_en) 4081 actions_n = flow_check_meter_action(actions, &mtr); 4082 if (mtr) { 4083 /* The five prefix actions: meter, decap, encap, tag, end. */ 4084 act_size = sizeof(struct rte_flow_action) * (actions_n + 5) + 4085 sizeof(struct mlx5_rte_flow_action_set_tag); 4086 /* tag, vlan, port id, end. */ 4087 #define METER_SUFFIX_ITEM 4 4088 item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM + 4089 sizeof(struct mlx5_rte_flow_item_tag) * 2; 4090 sfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0); 4091 if (!sfx_actions) 4092 return rte_flow_error_set(error, ENOMEM, 4093 RTE_FLOW_ERROR_TYPE_ACTION, 4094 NULL, "no memory to split " 4095 "meter flow"); 4096 sfx_items = (struct rte_flow_item *)((char *)sfx_actions + 4097 act_size); 4098 pre_actions = sfx_actions + actions_n; 4099 mtr_tag_id = flow_meter_split_prep(dev, items, sfx_items, 4100 actions, sfx_actions, 4101 pre_actions); 4102 if (!mtr_tag_id) { 4103 ret = -rte_errno; 4104 goto exit; 4105 } 4106 /* Add the prefix subflow. */ 4107 ret = flow_create_split_inner(dev, flow, &dev_flow, 0, attr, 4108 items, pre_actions, external, 4109 error); 4110 if (ret) { 4111 ret = -rte_errno; 4112 goto exit; 4113 } 4114 dev_flow->mtr_flow_id = mtr_tag_id; 4115 /* Setting the sfx group atrr. */ 4116 sfx_attr.group = sfx_attr.transfer ? 4117 (MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) : 4118 MLX5_FLOW_TABLE_LEVEL_SUFFIX; 4119 } 4120 /* Add the prefix subflow. */ 4121 ret = flow_create_split_metadata(dev, flow, dev_flow ? 4122 flow_get_prefix_layer_flags(dev_flow) : 4123 0, &sfx_attr, 4124 sfx_items ? sfx_items : items, 4125 sfx_actions ? sfx_actions : actions, 4126 external, error); 4127 exit: 4128 if (sfx_actions) 4129 rte_free(sfx_actions); 4130 return ret; 4131 } 4132 4133 /** 4134 * Split the flow to subflow set. The splitters might be linked 4135 * in the chain, like this: 4136 * flow_create_split_outer() calls: 4137 * flow_create_split_meter() calls: 4138 * flow_create_split_metadata(meter_subflow_0) calls: 4139 * flow_create_split_inner(metadata_subflow_0) 4140 * flow_create_split_inner(metadata_subflow_1) 4141 * flow_create_split_inner(metadata_subflow_2) 4142 * flow_create_split_metadata(meter_subflow_1) calls: 4143 * flow_create_split_inner(metadata_subflow_0) 4144 * flow_create_split_inner(metadata_subflow_1) 4145 * flow_create_split_inner(metadata_subflow_2) 4146 * 4147 * This provide flexible way to add new levels of flow splitting. 4148 * The all of successfully created subflows are included to the 4149 * parent flow dev_flow list. 4150 * 4151 * @param dev 4152 * Pointer to Ethernet device. 4153 * @param[in] flow 4154 * Parent flow structure pointer. 4155 * @param[in] attr 4156 * Flow rule attributes. 4157 * @param[in] items 4158 * Pattern specification (list terminated by the END pattern item). 4159 * @param[in] actions 4160 * Associated actions (list terminated by the END action). 4161 * @param[in] external 4162 * This flow rule is created by request external to PMD. 4163 * @param[out] error 4164 * Perform verbose error reporting if not NULL. 4165 * @return 4166 * 0 on success, negative value otherwise 4167 */ 4168 static int 4169 flow_create_split_outer(struct rte_eth_dev *dev, 4170 struct rte_flow *flow, 4171 const struct rte_flow_attr *attr, 4172 const struct rte_flow_item items[], 4173 const struct rte_flow_action actions[], 4174 bool external, struct rte_flow_error *error) 4175 { 4176 int ret; 4177 4178 ret = flow_create_split_meter(dev, flow, attr, items, 4179 actions, external, error); 4180 MLX5_ASSERT(ret <= 0); 4181 return ret; 4182 } 4183 4184 /** 4185 * Create a flow and add it to @p list. 4186 * 4187 * @param dev 4188 * Pointer to Ethernet device. 4189 * @param list 4190 * Pointer to a TAILQ flow list. If this parameter NULL, 4191 * no list insertion occurred, flow is just created, 4192 * this is caller's responsibility to track the 4193 * created flow. 4194 * @param[in] attr 4195 * Flow rule attributes. 4196 * @param[in] items 4197 * Pattern specification (list terminated by the END pattern item). 4198 * @param[in] actions 4199 * Associated actions (list terminated by the END action). 4200 * @param[in] external 4201 * This flow rule is created by request external to PMD. 4202 * @param[out] error 4203 * Perform verbose error reporting if not NULL. 4204 * 4205 * @return 4206 * A flow on success, NULL otherwise and rte_errno is set. 4207 */ 4208 static struct rte_flow * 4209 flow_list_create(struct rte_eth_dev *dev, struct mlx5_flows *list, 4210 const struct rte_flow_attr *attr, 4211 const struct rte_flow_item items[], 4212 const struct rte_flow_action actions[], 4213 bool external, struct rte_flow_error *error) 4214 { 4215 struct mlx5_priv *priv = dev->data->dev_private; 4216 struct rte_flow *flow = NULL; 4217 struct mlx5_flow *dev_flow; 4218 const struct rte_flow_action_rss *rss; 4219 union { 4220 struct rte_flow_expand_rss buf; 4221 uint8_t buffer[2048]; 4222 } expand_buffer; 4223 union { 4224 struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS]; 4225 uint8_t buffer[2048]; 4226 } actions_rx; 4227 union { 4228 struct rte_flow_action actions[MLX5_MAX_SPLIT_ACTIONS]; 4229 uint8_t buffer[2048]; 4230 } actions_hairpin_tx; 4231 union { 4232 struct rte_flow_item items[MLX5_MAX_SPLIT_ITEMS]; 4233 uint8_t buffer[2048]; 4234 } items_tx; 4235 struct rte_flow_expand_rss *buf = &expand_buffer.buf; 4236 const struct rte_flow_action *p_actions_rx = actions; 4237 uint32_t i; 4238 uint32_t flow_size; 4239 int hairpin_flow = 0; 4240 uint32_t hairpin_id = 0; 4241 struct rte_flow_attr attr_tx = { .priority = 0 }; 4242 int ret = flow_drv_validate(dev, attr, items, p_actions_rx, external, 4243 error); 4244 4245 if (ret < 0) 4246 return NULL; 4247 hairpin_flow = flow_check_hairpin_split(dev, attr, actions); 4248 if (hairpin_flow > 0) { 4249 if (hairpin_flow > MLX5_MAX_SPLIT_ACTIONS) { 4250 rte_errno = EINVAL; 4251 return NULL; 4252 } 4253 flow_hairpin_split(dev, actions, actions_rx.actions, 4254 actions_hairpin_tx.actions, items_tx.items, 4255 &hairpin_id); 4256 p_actions_rx = actions_rx.actions; 4257 } 4258 flow_size = sizeof(struct rte_flow); 4259 rss = flow_get_rss_action(p_actions_rx); 4260 if (rss) 4261 flow_size += RTE_ALIGN_CEIL(rss->queue_num * sizeof(uint16_t), 4262 sizeof(void *)); 4263 else 4264 flow_size += RTE_ALIGN_CEIL(sizeof(uint16_t), sizeof(void *)); 4265 flow = rte_calloc(__func__, 1, flow_size, 0); 4266 if (!flow) { 4267 rte_errno = ENOMEM; 4268 goto error_before_flow; 4269 } 4270 flow->drv_type = flow_get_drv_type(dev, attr); 4271 if (hairpin_id != 0) 4272 flow->hairpin_flow_id = hairpin_id; 4273 MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN && 4274 flow->drv_type < MLX5_FLOW_TYPE_MAX); 4275 flow->rss.queue = (void *)(flow + 1); 4276 if (rss) { 4277 /* 4278 * The following information is required by 4279 * mlx5_flow_hashfields_adjust() in advance. 4280 */ 4281 flow->rss.level = rss->level; 4282 /* RSS type 0 indicates default RSS type (ETH_RSS_IP). */ 4283 flow->rss.types = !rss->types ? ETH_RSS_IP : rss->types; 4284 } 4285 LIST_INIT(&flow->dev_flows); 4286 if (rss && rss->types) { 4287 unsigned int graph_root; 4288 4289 graph_root = find_graph_root(items, rss->level); 4290 ret = rte_flow_expand_rss(buf, sizeof(expand_buffer.buffer), 4291 items, rss->types, 4292 mlx5_support_expansion, 4293 graph_root); 4294 MLX5_ASSERT(ret > 0 && 4295 (unsigned int)ret < sizeof(expand_buffer.buffer)); 4296 } else { 4297 buf->entries = 1; 4298 buf->entry[0].pattern = (void *)(uintptr_t)items; 4299 } 4300 for (i = 0; i < buf->entries; ++i) { 4301 /* 4302 * The splitter may create multiple dev_flows, 4303 * depending on configuration. In the simplest 4304 * case it just creates unmodified original flow. 4305 */ 4306 ret = flow_create_split_outer(dev, flow, attr, 4307 buf->entry[i].pattern, 4308 p_actions_rx, external, 4309 error); 4310 if (ret < 0) 4311 goto error; 4312 } 4313 /* Create the tx flow. */ 4314 if (hairpin_flow) { 4315 attr_tx.group = MLX5_HAIRPIN_TX_TABLE; 4316 attr_tx.ingress = 0; 4317 attr_tx.egress = 1; 4318 dev_flow = flow_drv_prepare(flow, &attr_tx, items_tx.items, 4319 actions_hairpin_tx.actions, error); 4320 if (!dev_flow) 4321 goto error; 4322 dev_flow->flow = flow; 4323 dev_flow->external = 0; 4324 LIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next); 4325 ret = flow_drv_translate(dev, dev_flow, &attr_tx, 4326 items_tx.items, 4327 actions_hairpin_tx.actions, error); 4328 if (ret < 0) 4329 goto error; 4330 } 4331 /* 4332 * Update the metadata register copy table. If extensive 4333 * metadata feature is enabled and registers are supported 4334 * we might create the extra rte_flow for each unique 4335 * MARK/FLAG action ID. 4336 * 4337 * The table is updated for ingress Flows only, because 4338 * the egress Flows belong to the different device and 4339 * copy table should be updated in peer NIC Rx domain. 4340 */ 4341 if (attr->ingress && 4342 (external || attr->group != MLX5_FLOW_MREG_CP_TABLE_GROUP)) { 4343 ret = flow_mreg_update_copy_table(dev, flow, actions, error); 4344 if (ret) 4345 goto error; 4346 } 4347 if (dev->data->dev_started) { 4348 ret = flow_drv_apply(dev, flow, error); 4349 if (ret < 0) 4350 goto error; 4351 } 4352 if (list) 4353 TAILQ_INSERT_TAIL(list, flow, next); 4354 flow_rxq_flags_set(dev, flow); 4355 return flow; 4356 error_before_flow: 4357 if (hairpin_id) 4358 mlx5_flow_id_release(priv->sh->flow_id_pool, 4359 hairpin_id); 4360 return NULL; 4361 error: 4362 MLX5_ASSERT(flow); 4363 flow_mreg_del_copy_action(dev, flow); 4364 ret = rte_errno; /* Save rte_errno before cleanup. */ 4365 if (flow->hairpin_flow_id) 4366 mlx5_flow_id_release(priv->sh->flow_id_pool, 4367 flow->hairpin_flow_id); 4368 MLX5_ASSERT(flow); 4369 flow_drv_destroy(dev, flow); 4370 rte_free(flow); 4371 rte_errno = ret; /* Restore rte_errno. */ 4372 return NULL; 4373 } 4374 4375 /** 4376 * Create a dedicated flow rule on e-switch table 0 (root table), to direct all 4377 * incoming packets to table 1. 4378 * 4379 * Other flow rules, requested for group n, will be created in 4380 * e-switch table n+1. 4381 * Jump action to e-switch group n will be created to group n+1. 4382 * 4383 * Used when working in switchdev mode, to utilise advantages of table 1 4384 * and above. 4385 * 4386 * @param dev 4387 * Pointer to Ethernet device. 4388 * 4389 * @return 4390 * Pointer to flow on success, NULL otherwise and rte_errno is set. 4391 */ 4392 struct rte_flow * 4393 mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev) 4394 { 4395 const struct rte_flow_attr attr = { 4396 .group = 0, 4397 .priority = 0, 4398 .ingress = 1, 4399 .egress = 0, 4400 .transfer = 1, 4401 }; 4402 const struct rte_flow_item pattern = { 4403 .type = RTE_FLOW_ITEM_TYPE_END, 4404 }; 4405 struct rte_flow_action_jump jump = { 4406 .group = 1, 4407 }; 4408 const struct rte_flow_action actions[] = { 4409 { 4410 .type = RTE_FLOW_ACTION_TYPE_JUMP, 4411 .conf = &jump, 4412 }, 4413 { 4414 .type = RTE_FLOW_ACTION_TYPE_END, 4415 }, 4416 }; 4417 struct mlx5_priv *priv = dev->data->dev_private; 4418 struct rte_flow_error error; 4419 4420 return flow_list_create(dev, &priv->ctrl_flows, &attr, &pattern, 4421 actions, false, &error); 4422 } 4423 4424 /** 4425 * Create a flow. 4426 * 4427 * @see rte_flow_create() 4428 * @see rte_flow_ops 4429 */ 4430 struct rte_flow * 4431 mlx5_flow_create(struct rte_eth_dev *dev, 4432 const struct rte_flow_attr *attr, 4433 const struct rte_flow_item items[], 4434 const struct rte_flow_action actions[], 4435 struct rte_flow_error *error) 4436 { 4437 struct mlx5_priv *priv = dev->data->dev_private; 4438 4439 return flow_list_create(dev, &priv->flows, 4440 attr, items, actions, true, error); 4441 } 4442 4443 /** 4444 * Destroy a flow in a list. 4445 * 4446 * @param dev 4447 * Pointer to Ethernet device. 4448 * @param list 4449 * Pointer to a TAILQ flow list. If this parameter NULL, 4450 * there is no flow removal from the list. 4451 * @param[in] flow 4452 * Flow to destroy. 4453 */ 4454 static void 4455 flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list, 4456 struct rte_flow *flow) 4457 { 4458 struct mlx5_priv *priv = dev->data->dev_private; 4459 4460 /* 4461 * Update RX queue flags only if port is started, otherwise it is 4462 * already clean. 4463 */ 4464 if (dev->data->dev_started) 4465 flow_rxq_flags_trim(dev, flow); 4466 if (flow->hairpin_flow_id) 4467 mlx5_flow_id_release(priv->sh->flow_id_pool, 4468 flow->hairpin_flow_id); 4469 flow_drv_destroy(dev, flow); 4470 if (list) 4471 TAILQ_REMOVE(list, flow, next); 4472 flow_mreg_del_copy_action(dev, flow); 4473 rte_free(flow->fdir); 4474 rte_free(flow); 4475 } 4476 4477 /** 4478 * Destroy all flows. 4479 * 4480 * @param dev 4481 * Pointer to Ethernet device. 4482 * @param list 4483 * Pointer to a TAILQ flow list. 4484 */ 4485 void 4486 mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list) 4487 { 4488 while (!TAILQ_EMPTY(list)) { 4489 struct rte_flow *flow; 4490 4491 flow = TAILQ_FIRST(list); 4492 flow_list_destroy(dev, list, flow); 4493 } 4494 } 4495 4496 /** 4497 * Remove all flows. 4498 * 4499 * @param dev 4500 * Pointer to Ethernet device. 4501 * @param list 4502 * Pointer to a TAILQ flow list. 4503 */ 4504 void 4505 mlx5_flow_stop(struct rte_eth_dev *dev, struct mlx5_flows *list) 4506 { 4507 struct rte_flow *flow; 4508 4509 TAILQ_FOREACH_REVERSE(flow, list, mlx5_flows, next) { 4510 flow_drv_remove(dev, flow); 4511 flow_mreg_stop_copy_action(dev, flow); 4512 } 4513 flow_mreg_del_default_copy_action(dev); 4514 flow_rxq_flags_clear(dev); 4515 } 4516 4517 /** 4518 * Add all flows. 4519 * 4520 * @param dev 4521 * Pointer to Ethernet device. 4522 * @param list 4523 * Pointer to a TAILQ flow list. 4524 * 4525 * @return 4526 * 0 on success, a negative errno value otherwise and rte_errno is set. 4527 */ 4528 int 4529 mlx5_flow_start(struct rte_eth_dev *dev, struct mlx5_flows *list) 4530 { 4531 struct rte_flow *flow; 4532 struct rte_flow_error error; 4533 int ret = 0; 4534 4535 /* Make sure default copy action (reg_c[0] -> reg_b) is created. */ 4536 ret = flow_mreg_add_default_copy_action(dev, &error); 4537 if (ret < 0) 4538 return -rte_errno; 4539 /* Apply Flows created by application. */ 4540 TAILQ_FOREACH(flow, list, next) { 4541 ret = flow_mreg_start_copy_action(dev, flow); 4542 if (ret < 0) 4543 goto error; 4544 ret = flow_drv_apply(dev, flow, &error); 4545 if (ret < 0) 4546 goto error; 4547 flow_rxq_flags_set(dev, flow); 4548 } 4549 return 0; 4550 error: 4551 ret = rte_errno; /* Save rte_errno before cleanup. */ 4552 mlx5_flow_stop(dev, list); 4553 rte_errno = ret; /* Restore rte_errno. */ 4554 return -rte_errno; 4555 } 4556 4557 /** 4558 * Verify the flow list is empty 4559 * 4560 * @param dev 4561 * Pointer to Ethernet device. 4562 * 4563 * @return the number of flows not released. 4564 */ 4565 int 4566 mlx5_flow_verify(struct rte_eth_dev *dev) 4567 { 4568 struct mlx5_priv *priv = dev->data->dev_private; 4569 struct rte_flow *flow; 4570 int ret = 0; 4571 4572 TAILQ_FOREACH(flow, &priv->flows, next) { 4573 DRV_LOG(DEBUG, "port %u flow %p still referenced", 4574 dev->data->port_id, (void *)flow); 4575 ++ret; 4576 } 4577 return ret; 4578 } 4579 4580 /** 4581 * Enable default hairpin egress flow. 4582 * 4583 * @param dev 4584 * Pointer to Ethernet device. 4585 * @param queue 4586 * The queue index. 4587 * 4588 * @return 4589 * 0 on success, a negative errno value otherwise and rte_errno is set. 4590 */ 4591 int 4592 mlx5_ctrl_flow_source_queue(struct rte_eth_dev *dev, 4593 uint32_t queue) 4594 { 4595 struct mlx5_priv *priv = dev->data->dev_private; 4596 const struct rte_flow_attr attr = { 4597 .egress = 1, 4598 .priority = 0, 4599 }; 4600 struct mlx5_rte_flow_item_tx_queue queue_spec = { 4601 .queue = queue, 4602 }; 4603 struct mlx5_rte_flow_item_tx_queue queue_mask = { 4604 .queue = UINT32_MAX, 4605 }; 4606 struct rte_flow_item items[] = { 4607 { 4608 .type = MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE, 4609 .spec = &queue_spec, 4610 .last = NULL, 4611 .mask = &queue_mask, 4612 }, 4613 { 4614 .type = RTE_FLOW_ITEM_TYPE_END, 4615 }, 4616 }; 4617 struct rte_flow_action_jump jump = { 4618 .group = MLX5_HAIRPIN_TX_TABLE, 4619 }; 4620 struct rte_flow_action actions[2]; 4621 struct rte_flow *flow; 4622 struct rte_flow_error error; 4623 4624 actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP; 4625 actions[0].conf = &jump; 4626 actions[1].type = RTE_FLOW_ACTION_TYPE_END; 4627 flow = flow_list_create(dev, &priv->ctrl_flows, 4628 &attr, items, actions, false, &error); 4629 if (!flow) { 4630 DRV_LOG(DEBUG, 4631 "Failed to create ctrl flow: rte_errno(%d)," 4632 " type(%d), message(%s)", 4633 rte_errno, error.type, 4634 error.message ? error.message : " (no stated reason)"); 4635 return -rte_errno; 4636 } 4637 return 0; 4638 } 4639 4640 /** 4641 * Enable a control flow configured from the control plane. 4642 * 4643 * @param dev 4644 * Pointer to Ethernet device. 4645 * @param eth_spec 4646 * An Ethernet flow spec to apply. 4647 * @param eth_mask 4648 * An Ethernet flow mask to apply. 4649 * @param vlan_spec 4650 * A VLAN flow spec to apply. 4651 * @param vlan_mask 4652 * A VLAN flow mask to apply. 4653 * 4654 * @return 4655 * 0 on success, a negative errno value otherwise and rte_errno is set. 4656 */ 4657 int 4658 mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev, 4659 struct rte_flow_item_eth *eth_spec, 4660 struct rte_flow_item_eth *eth_mask, 4661 struct rte_flow_item_vlan *vlan_spec, 4662 struct rte_flow_item_vlan *vlan_mask) 4663 { 4664 struct mlx5_priv *priv = dev->data->dev_private; 4665 const struct rte_flow_attr attr = { 4666 .ingress = 1, 4667 .priority = MLX5_FLOW_PRIO_RSVD, 4668 }; 4669 struct rte_flow_item items[] = { 4670 { 4671 .type = RTE_FLOW_ITEM_TYPE_ETH, 4672 .spec = eth_spec, 4673 .last = NULL, 4674 .mask = eth_mask, 4675 }, 4676 { 4677 .type = (vlan_spec) ? RTE_FLOW_ITEM_TYPE_VLAN : 4678 RTE_FLOW_ITEM_TYPE_END, 4679 .spec = vlan_spec, 4680 .last = NULL, 4681 .mask = vlan_mask, 4682 }, 4683 { 4684 .type = RTE_FLOW_ITEM_TYPE_END, 4685 }, 4686 }; 4687 uint16_t queue[priv->reta_idx_n]; 4688 struct rte_flow_action_rss action_rss = { 4689 .func = RTE_ETH_HASH_FUNCTION_DEFAULT, 4690 .level = 0, 4691 .types = priv->rss_conf.rss_hf, 4692 .key_len = priv->rss_conf.rss_key_len, 4693 .queue_num = priv->reta_idx_n, 4694 .key = priv->rss_conf.rss_key, 4695 .queue = queue, 4696 }; 4697 struct rte_flow_action actions[] = { 4698 { 4699 .type = RTE_FLOW_ACTION_TYPE_RSS, 4700 .conf = &action_rss, 4701 }, 4702 { 4703 .type = RTE_FLOW_ACTION_TYPE_END, 4704 }, 4705 }; 4706 struct rte_flow *flow; 4707 struct rte_flow_error error; 4708 unsigned int i; 4709 4710 if (!priv->reta_idx_n || !priv->rxqs_n) { 4711 return 0; 4712 } 4713 for (i = 0; i != priv->reta_idx_n; ++i) 4714 queue[i] = (*priv->reta_idx)[i]; 4715 flow = flow_list_create(dev, &priv->ctrl_flows, 4716 &attr, items, actions, false, &error); 4717 if (!flow) 4718 return -rte_errno; 4719 return 0; 4720 } 4721 4722 /** 4723 * Enable a flow control configured from the control plane. 4724 * 4725 * @param dev 4726 * Pointer to Ethernet device. 4727 * @param eth_spec 4728 * An Ethernet flow spec to apply. 4729 * @param eth_mask 4730 * An Ethernet flow mask to apply. 4731 * 4732 * @return 4733 * 0 on success, a negative errno value otherwise and rte_errno is set. 4734 */ 4735 int 4736 mlx5_ctrl_flow(struct rte_eth_dev *dev, 4737 struct rte_flow_item_eth *eth_spec, 4738 struct rte_flow_item_eth *eth_mask) 4739 { 4740 return mlx5_ctrl_flow_vlan(dev, eth_spec, eth_mask, NULL, NULL); 4741 } 4742 4743 /** 4744 * Destroy a flow. 4745 * 4746 * @see rte_flow_destroy() 4747 * @see rte_flow_ops 4748 */ 4749 int 4750 mlx5_flow_destroy(struct rte_eth_dev *dev, 4751 struct rte_flow *flow, 4752 struct rte_flow_error *error __rte_unused) 4753 { 4754 struct mlx5_priv *priv = dev->data->dev_private; 4755 4756 flow_list_destroy(dev, &priv->flows, flow); 4757 return 0; 4758 } 4759 4760 /** 4761 * Destroy all flows. 4762 * 4763 * @see rte_flow_flush() 4764 * @see rte_flow_ops 4765 */ 4766 int 4767 mlx5_flow_flush(struct rte_eth_dev *dev, 4768 struct rte_flow_error *error __rte_unused) 4769 { 4770 struct mlx5_priv *priv = dev->data->dev_private; 4771 4772 mlx5_flow_list_flush(dev, &priv->flows); 4773 return 0; 4774 } 4775 4776 /** 4777 * Isolated mode. 4778 * 4779 * @see rte_flow_isolate() 4780 * @see rte_flow_ops 4781 */ 4782 int 4783 mlx5_flow_isolate(struct rte_eth_dev *dev, 4784 int enable, 4785 struct rte_flow_error *error) 4786 { 4787 struct mlx5_priv *priv = dev->data->dev_private; 4788 4789 if (dev->data->dev_started) { 4790 rte_flow_error_set(error, EBUSY, 4791 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 4792 NULL, 4793 "port must be stopped first"); 4794 return -rte_errno; 4795 } 4796 priv->isolated = !!enable; 4797 if (enable) 4798 dev->dev_ops = &mlx5_dev_ops_isolate; 4799 else 4800 dev->dev_ops = &mlx5_dev_ops; 4801 return 0; 4802 } 4803 4804 /** 4805 * Query a flow. 4806 * 4807 * @see rte_flow_query() 4808 * @see rte_flow_ops 4809 */ 4810 static int 4811 flow_drv_query(struct rte_eth_dev *dev, 4812 struct rte_flow *flow, 4813 const struct rte_flow_action *actions, 4814 void *data, 4815 struct rte_flow_error *error) 4816 { 4817 const struct mlx5_flow_driver_ops *fops; 4818 enum mlx5_flow_drv_type ftype = flow->drv_type; 4819 4820 MLX5_ASSERT(ftype > MLX5_FLOW_TYPE_MIN && ftype < MLX5_FLOW_TYPE_MAX); 4821 fops = flow_get_drv_ops(ftype); 4822 4823 return fops->query(dev, flow, actions, data, error); 4824 } 4825 4826 /** 4827 * Query a flow. 4828 * 4829 * @see rte_flow_query() 4830 * @see rte_flow_ops 4831 */ 4832 int 4833 mlx5_flow_query(struct rte_eth_dev *dev, 4834 struct rte_flow *flow, 4835 const struct rte_flow_action *actions, 4836 void *data, 4837 struct rte_flow_error *error) 4838 { 4839 int ret; 4840 4841 ret = flow_drv_query(dev, flow, actions, data, error); 4842 if (ret < 0) 4843 return ret; 4844 return 0; 4845 } 4846 4847 /** 4848 * Convert a flow director filter to a generic flow. 4849 * 4850 * @param dev 4851 * Pointer to Ethernet device. 4852 * @param fdir_filter 4853 * Flow director filter to add. 4854 * @param attributes 4855 * Generic flow parameters structure. 4856 * 4857 * @return 4858 * 0 on success, a negative errno value otherwise and rte_errno is set. 4859 */ 4860 static int 4861 flow_fdir_filter_convert(struct rte_eth_dev *dev, 4862 const struct rte_eth_fdir_filter *fdir_filter, 4863 struct mlx5_fdir *attributes) 4864 { 4865 struct mlx5_priv *priv = dev->data->dev_private; 4866 const struct rte_eth_fdir_input *input = &fdir_filter->input; 4867 const struct rte_eth_fdir_masks *mask = 4868 &dev->data->dev_conf.fdir_conf.mask; 4869 4870 /* Validate queue number. */ 4871 if (fdir_filter->action.rx_queue >= priv->rxqs_n) { 4872 DRV_LOG(ERR, "port %u invalid queue number %d", 4873 dev->data->port_id, fdir_filter->action.rx_queue); 4874 rte_errno = EINVAL; 4875 return -rte_errno; 4876 } 4877 attributes->attr.ingress = 1; 4878 attributes->items[0] = (struct rte_flow_item) { 4879 .type = RTE_FLOW_ITEM_TYPE_ETH, 4880 .spec = &attributes->l2, 4881 .mask = &attributes->l2_mask, 4882 }; 4883 switch (fdir_filter->action.behavior) { 4884 case RTE_ETH_FDIR_ACCEPT: 4885 attributes->actions[0] = (struct rte_flow_action){ 4886 .type = RTE_FLOW_ACTION_TYPE_QUEUE, 4887 .conf = &attributes->queue, 4888 }; 4889 break; 4890 case RTE_ETH_FDIR_REJECT: 4891 attributes->actions[0] = (struct rte_flow_action){ 4892 .type = RTE_FLOW_ACTION_TYPE_DROP, 4893 }; 4894 break; 4895 default: 4896 DRV_LOG(ERR, "port %u invalid behavior %d", 4897 dev->data->port_id, 4898 fdir_filter->action.behavior); 4899 rte_errno = ENOTSUP; 4900 return -rte_errno; 4901 } 4902 attributes->queue.index = fdir_filter->action.rx_queue; 4903 /* Handle L3. */ 4904 switch (fdir_filter->input.flow_type) { 4905 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 4906 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 4907 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 4908 attributes->l3.ipv4.hdr = (struct rte_ipv4_hdr){ 4909 .src_addr = input->flow.ip4_flow.src_ip, 4910 .dst_addr = input->flow.ip4_flow.dst_ip, 4911 .time_to_live = input->flow.ip4_flow.ttl, 4912 .type_of_service = input->flow.ip4_flow.tos, 4913 }; 4914 attributes->l3_mask.ipv4.hdr = (struct rte_ipv4_hdr){ 4915 .src_addr = mask->ipv4_mask.src_ip, 4916 .dst_addr = mask->ipv4_mask.dst_ip, 4917 .time_to_live = mask->ipv4_mask.ttl, 4918 .type_of_service = mask->ipv4_mask.tos, 4919 .next_proto_id = mask->ipv4_mask.proto, 4920 }; 4921 attributes->items[1] = (struct rte_flow_item){ 4922 .type = RTE_FLOW_ITEM_TYPE_IPV4, 4923 .spec = &attributes->l3, 4924 .mask = &attributes->l3_mask, 4925 }; 4926 break; 4927 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 4928 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 4929 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 4930 attributes->l3.ipv6.hdr = (struct rte_ipv6_hdr){ 4931 .hop_limits = input->flow.ipv6_flow.hop_limits, 4932 .proto = input->flow.ipv6_flow.proto, 4933 }; 4934 4935 memcpy(attributes->l3.ipv6.hdr.src_addr, 4936 input->flow.ipv6_flow.src_ip, 4937 RTE_DIM(attributes->l3.ipv6.hdr.src_addr)); 4938 memcpy(attributes->l3.ipv6.hdr.dst_addr, 4939 input->flow.ipv6_flow.dst_ip, 4940 RTE_DIM(attributes->l3.ipv6.hdr.src_addr)); 4941 memcpy(attributes->l3_mask.ipv6.hdr.src_addr, 4942 mask->ipv6_mask.src_ip, 4943 RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr)); 4944 memcpy(attributes->l3_mask.ipv6.hdr.dst_addr, 4945 mask->ipv6_mask.dst_ip, 4946 RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr)); 4947 attributes->items[1] = (struct rte_flow_item){ 4948 .type = RTE_FLOW_ITEM_TYPE_IPV6, 4949 .spec = &attributes->l3, 4950 .mask = &attributes->l3_mask, 4951 }; 4952 break; 4953 default: 4954 DRV_LOG(ERR, "port %u invalid flow type%d", 4955 dev->data->port_id, fdir_filter->input.flow_type); 4956 rte_errno = ENOTSUP; 4957 return -rte_errno; 4958 } 4959 /* Handle L4. */ 4960 switch (fdir_filter->input.flow_type) { 4961 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 4962 attributes->l4.udp.hdr = (struct rte_udp_hdr){ 4963 .src_port = input->flow.udp4_flow.src_port, 4964 .dst_port = input->flow.udp4_flow.dst_port, 4965 }; 4966 attributes->l4_mask.udp.hdr = (struct rte_udp_hdr){ 4967 .src_port = mask->src_port_mask, 4968 .dst_port = mask->dst_port_mask, 4969 }; 4970 attributes->items[2] = (struct rte_flow_item){ 4971 .type = RTE_FLOW_ITEM_TYPE_UDP, 4972 .spec = &attributes->l4, 4973 .mask = &attributes->l4_mask, 4974 }; 4975 break; 4976 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 4977 attributes->l4.tcp.hdr = (struct rte_tcp_hdr){ 4978 .src_port = input->flow.tcp4_flow.src_port, 4979 .dst_port = input->flow.tcp4_flow.dst_port, 4980 }; 4981 attributes->l4_mask.tcp.hdr = (struct rte_tcp_hdr){ 4982 .src_port = mask->src_port_mask, 4983 .dst_port = mask->dst_port_mask, 4984 }; 4985 attributes->items[2] = (struct rte_flow_item){ 4986 .type = RTE_FLOW_ITEM_TYPE_TCP, 4987 .spec = &attributes->l4, 4988 .mask = &attributes->l4_mask, 4989 }; 4990 break; 4991 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 4992 attributes->l4.udp.hdr = (struct rte_udp_hdr){ 4993 .src_port = input->flow.udp6_flow.src_port, 4994 .dst_port = input->flow.udp6_flow.dst_port, 4995 }; 4996 attributes->l4_mask.udp.hdr = (struct rte_udp_hdr){ 4997 .src_port = mask->src_port_mask, 4998 .dst_port = mask->dst_port_mask, 4999 }; 5000 attributes->items[2] = (struct rte_flow_item){ 5001 .type = RTE_FLOW_ITEM_TYPE_UDP, 5002 .spec = &attributes->l4, 5003 .mask = &attributes->l4_mask, 5004 }; 5005 break; 5006 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 5007 attributes->l4.tcp.hdr = (struct rte_tcp_hdr){ 5008 .src_port = input->flow.tcp6_flow.src_port, 5009 .dst_port = input->flow.tcp6_flow.dst_port, 5010 }; 5011 attributes->l4_mask.tcp.hdr = (struct rte_tcp_hdr){ 5012 .src_port = mask->src_port_mask, 5013 .dst_port = mask->dst_port_mask, 5014 }; 5015 attributes->items[2] = (struct rte_flow_item){ 5016 .type = RTE_FLOW_ITEM_TYPE_TCP, 5017 .spec = &attributes->l4, 5018 .mask = &attributes->l4_mask, 5019 }; 5020 break; 5021 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 5022 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 5023 break; 5024 default: 5025 DRV_LOG(ERR, "port %u invalid flow type%d", 5026 dev->data->port_id, fdir_filter->input.flow_type); 5027 rte_errno = ENOTSUP; 5028 return -rte_errno; 5029 } 5030 return 0; 5031 } 5032 5033 #define FLOW_FDIR_CMP(f1, f2, fld) \ 5034 memcmp(&(f1)->fld, &(f2)->fld, sizeof(f1->fld)) 5035 5036 /** 5037 * Compare two FDIR flows. If items and actions are identical, the two flows are 5038 * regarded as same. 5039 * 5040 * @param dev 5041 * Pointer to Ethernet device. 5042 * @param f1 5043 * FDIR flow to compare. 5044 * @param f2 5045 * FDIR flow to compare. 5046 * 5047 * @return 5048 * Zero on match, 1 otherwise. 5049 */ 5050 static int 5051 flow_fdir_cmp(const struct mlx5_fdir *f1, const struct mlx5_fdir *f2) 5052 { 5053 if (FLOW_FDIR_CMP(f1, f2, attr) || 5054 FLOW_FDIR_CMP(f1, f2, l2) || 5055 FLOW_FDIR_CMP(f1, f2, l2_mask) || 5056 FLOW_FDIR_CMP(f1, f2, l3) || 5057 FLOW_FDIR_CMP(f1, f2, l3_mask) || 5058 FLOW_FDIR_CMP(f1, f2, l4) || 5059 FLOW_FDIR_CMP(f1, f2, l4_mask) || 5060 FLOW_FDIR_CMP(f1, f2, actions[0].type)) 5061 return 1; 5062 if (f1->actions[0].type == RTE_FLOW_ACTION_TYPE_QUEUE && 5063 FLOW_FDIR_CMP(f1, f2, queue)) 5064 return 1; 5065 return 0; 5066 } 5067 5068 /** 5069 * Search device flow list to find out a matched FDIR flow. 5070 * 5071 * @param dev 5072 * Pointer to Ethernet device. 5073 * @param fdir_flow 5074 * FDIR flow to lookup. 5075 * 5076 * @return 5077 * Pointer of flow if found, NULL otherwise. 5078 */ 5079 static struct rte_flow * 5080 flow_fdir_filter_lookup(struct rte_eth_dev *dev, struct mlx5_fdir *fdir_flow) 5081 { 5082 struct mlx5_priv *priv = dev->data->dev_private; 5083 struct rte_flow *flow = NULL; 5084 5085 MLX5_ASSERT(fdir_flow); 5086 TAILQ_FOREACH(flow, &priv->flows, next) { 5087 if (flow->fdir && !flow_fdir_cmp(flow->fdir, fdir_flow)) { 5088 DRV_LOG(DEBUG, "port %u found FDIR flow %p", 5089 dev->data->port_id, (void *)flow); 5090 break; 5091 } 5092 } 5093 return flow; 5094 } 5095 5096 /** 5097 * Add new flow director filter and store it in list. 5098 * 5099 * @param dev 5100 * Pointer to Ethernet device. 5101 * @param fdir_filter 5102 * Flow director filter to add. 5103 * 5104 * @return 5105 * 0 on success, a negative errno value otherwise and rte_errno is set. 5106 */ 5107 static int 5108 flow_fdir_filter_add(struct rte_eth_dev *dev, 5109 const struct rte_eth_fdir_filter *fdir_filter) 5110 { 5111 struct mlx5_priv *priv = dev->data->dev_private; 5112 struct mlx5_fdir *fdir_flow; 5113 struct rte_flow *flow; 5114 int ret; 5115 5116 fdir_flow = rte_zmalloc(__func__, sizeof(*fdir_flow), 0); 5117 if (!fdir_flow) { 5118 rte_errno = ENOMEM; 5119 return -rte_errno; 5120 } 5121 ret = flow_fdir_filter_convert(dev, fdir_filter, fdir_flow); 5122 if (ret) 5123 goto error; 5124 flow = flow_fdir_filter_lookup(dev, fdir_flow); 5125 if (flow) { 5126 rte_errno = EEXIST; 5127 goto error; 5128 } 5129 flow = flow_list_create(dev, &priv->flows, &fdir_flow->attr, 5130 fdir_flow->items, fdir_flow->actions, true, 5131 NULL); 5132 if (!flow) 5133 goto error; 5134 MLX5_ASSERT(!flow->fdir); 5135 flow->fdir = fdir_flow; 5136 DRV_LOG(DEBUG, "port %u created FDIR flow %p", 5137 dev->data->port_id, (void *)flow); 5138 return 0; 5139 error: 5140 rte_free(fdir_flow); 5141 return -rte_errno; 5142 } 5143 5144 /** 5145 * Delete specific filter. 5146 * 5147 * @param dev 5148 * Pointer to Ethernet device. 5149 * @param fdir_filter 5150 * Filter to be deleted. 5151 * 5152 * @return 5153 * 0 on success, a negative errno value otherwise and rte_errno is set. 5154 */ 5155 static int 5156 flow_fdir_filter_delete(struct rte_eth_dev *dev, 5157 const struct rte_eth_fdir_filter *fdir_filter) 5158 { 5159 struct mlx5_priv *priv = dev->data->dev_private; 5160 struct rte_flow *flow; 5161 struct mlx5_fdir fdir_flow = { 5162 .attr.group = 0, 5163 }; 5164 int ret; 5165 5166 ret = flow_fdir_filter_convert(dev, fdir_filter, &fdir_flow); 5167 if (ret) 5168 return -rte_errno; 5169 flow = flow_fdir_filter_lookup(dev, &fdir_flow); 5170 if (!flow) { 5171 rte_errno = ENOENT; 5172 return -rte_errno; 5173 } 5174 flow_list_destroy(dev, &priv->flows, flow); 5175 DRV_LOG(DEBUG, "port %u deleted FDIR flow %p", 5176 dev->data->port_id, (void *)flow); 5177 return 0; 5178 } 5179 5180 /** 5181 * Update queue for specific filter. 5182 * 5183 * @param dev 5184 * Pointer to Ethernet device. 5185 * @param fdir_filter 5186 * Filter to be updated. 5187 * 5188 * @return 5189 * 0 on success, a negative errno value otherwise and rte_errno is set. 5190 */ 5191 static int 5192 flow_fdir_filter_update(struct rte_eth_dev *dev, 5193 const struct rte_eth_fdir_filter *fdir_filter) 5194 { 5195 int ret; 5196 5197 ret = flow_fdir_filter_delete(dev, fdir_filter); 5198 if (ret) 5199 return ret; 5200 return flow_fdir_filter_add(dev, fdir_filter); 5201 } 5202 5203 /** 5204 * Flush all filters. 5205 * 5206 * @param dev 5207 * Pointer to Ethernet device. 5208 */ 5209 static void 5210 flow_fdir_filter_flush(struct rte_eth_dev *dev) 5211 { 5212 struct mlx5_priv *priv = dev->data->dev_private; 5213 5214 mlx5_flow_list_flush(dev, &priv->flows); 5215 } 5216 5217 /** 5218 * Get flow director information. 5219 * 5220 * @param dev 5221 * Pointer to Ethernet device. 5222 * @param[out] fdir_info 5223 * Resulting flow director information. 5224 */ 5225 static void 5226 flow_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info) 5227 { 5228 struct rte_eth_fdir_masks *mask = 5229 &dev->data->dev_conf.fdir_conf.mask; 5230 5231 fdir_info->mode = dev->data->dev_conf.fdir_conf.mode; 5232 fdir_info->guarant_spc = 0; 5233 rte_memcpy(&fdir_info->mask, mask, sizeof(fdir_info->mask)); 5234 fdir_info->max_flexpayload = 0; 5235 fdir_info->flow_types_mask[0] = 0; 5236 fdir_info->flex_payload_unit = 0; 5237 fdir_info->max_flex_payload_segment_num = 0; 5238 fdir_info->flex_payload_limit = 0; 5239 memset(&fdir_info->flex_conf, 0, sizeof(fdir_info->flex_conf)); 5240 } 5241 5242 /** 5243 * Deal with flow director operations. 5244 * 5245 * @param dev 5246 * Pointer to Ethernet device. 5247 * @param filter_op 5248 * Operation to perform. 5249 * @param arg 5250 * Pointer to operation-specific structure. 5251 * 5252 * @return 5253 * 0 on success, a negative errno value otherwise and rte_errno is set. 5254 */ 5255 static int 5256 flow_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, 5257 void *arg) 5258 { 5259 enum rte_fdir_mode fdir_mode = 5260 dev->data->dev_conf.fdir_conf.mode; 5261 5262 if (filter_op == RTE_ETH_FILTER_NOP) 5263 return 0; 5264 if (fdir_mode != RTE_FDIR_MODE_PERFECT && 5265 fdir_mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) { 5266 DRV_LOG(ERR, "port %u flow director mode %d not supported", 5267 dev->data->port_id, fdir_mode); 5268 rte_errno = EINVAL; 5269 return -rte_errno; 5270 } 5271 switch (filter_op) { 5272 case RTE_ETH_FILTER_ADD: 5273 return flow_fdir_filter_add(dev, arg); 5274 case RTE_ETH_FILTER_UPDATE: 5275 return flow_fdir_filter_update(dev, arg); 5276 case RTE_ETH_FILTER_DELETE: 5277 return flow_fdir_filter_delete(dev, arg); 5278 case RTE_ETH_FILTER_FLUSH: 5279 flow_fdir_filter_flush(dev); 5280 break; 5281 case RTE_ETH_FILTER_INFO: 5282 flow_fdir_info_get(dev, arg); 5283 break; 5284 default: 5285 DRV_LOG(DEBUG, "port %u unknown operation %u", 5286 dev->data->port_id, filter_op); 5287 rte_errno = EINVAL; 5288 return -rte_errno; 5289 } 5290 return 0; 5291 } 5292 5293 /** 5294 * Manage filter operations. 5295 * 5296 * @param dev 5297 * Pointer to Ethernet device structure. 5298 * @param filter_type 5299 * Filter type. 5300 * @param filter_op 5301 * Operation to perform. 5302 * @param arg 5303 * Pointer to operation-specific structure. 5304 * 5305 * @return 5306 * 0 on success, a negative errno value otherwise and rte_errno is set. 5307 */ 5308 int 5309 mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, 5310 enum rte_filter_type filter_type, 5311 enum rte_filter_op filter_op, 5312 void *arg) 5313 { 5314 switch (filter_type) { 5315 case RTE_ETH_FILTER_GENERIC: 5316 if (filter_op != RTE_ETH_FILTER_GET) { 5317 rte_errno = EINVAL; 5318 return -rte_errno; 5319 } 5320 *(const void **)arg = &mlx5_flow_ops; 5321 return 0; 5322 case RTE_ETH_FILTER_FDIR: 5323 return flow_fdir_ctrl_func(dev, filter_op, arg); 5324 default: 5325 DRV_LOG(ERR, "port %u filter type (%d) not supported", 5326 dev->data->port_id, filter_type); 5327 rte_errno = ENOTSUP; 5328 return -rte_errno; 5329 } 5330 return 0; 5331 } 5332 5333 /** 5334 * Create the needed meter and suffix tables. 5335 * 5336 * @param[in] dev 5337 * Pointer to Ethernet device. 5338 * @param[in] fm 5339 * Pointer to the flow meter. 5340 * 5341 * @return 5342 * Pointer to table set on success, NULL otherwise. 5343 */ 5344 struct mlx5_meter_domains_infos * 5345 mlx5_flow_create_mtr_tbls(struct rte_eth_dev *dev, 5346 const struct mlx5_flow_meter *fm) 5347 { 5348 const struct mlx5_flow_driver_ops *fops; 5349 5350 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5351 return fops->create_mtr_tbls(dev, fm); 5352 } 5353 5354 /** 5355 * Destroy the meter table set. 5356 * 5357 * @param[in] dev 5358 * Pointer to Ethernet device. 5359 * @param[in] tbl 5360 * Pointer to the meter table set. 5361 * 5362 * @return 5363 * 0 on success. 5364 */ 5365 int 5366 mlx5_flow_destroy_mtr_tbls(struct rte_eth_dev *dev, 5367 struct mlx5_meter_domains_infos *tbls) 5368 { 5369 const struct mlx5_flow_driver_ops *fops; 5370 5371 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5372 return fops->destroy_mtr_tbls(dev, tbls); 5373 } 5374 5375 /** 5376 * Create policer rules. 5377 * 5378 * @param[in] dev 5379 * Pointer to Ethernet device. 5380 * @param[in] fm 5381 * Pointer to flow meter structure. 5382 * @param[in] attr 5383 * Pointer to flow attributes. 5384 * 5385 * @return 5386 * 0 on success, -1 otherwise. 5387 */ 5388 int 5389 mlx5_flow_create_policer_rules(struct rte_eth_dev *dev, 5390 struct mlx5_flow_meter *fm, 5391 const struct rte_flow_attr *attr) 5392 { 5393 const struct mlx5_flow_driver_ops *fops; 5394 5395 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5396 return fops->create_policer_rules(dev, fm, attr); 5397 } 5398 5399 /** 5400 * Destroy policer rules. 5401 * 5402 * @param[in] fm 5403 * Pointer to flow meter structure. 5404 * @param[in] attr 5405 * Pointer to flow attributes. 5406 * 5407 * @return 5408 * 0 on success, -1 otherwise. 5409 */ 5410 int 5411 mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev, 5412 struct mlx5_flow_meter *fm, 5413 const struct rte_flow_attr *attr) 5414 { 5415 const struct mlx5_flow_driver_ops *fops; 5416 5417 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5418 return fops->destroy_policer_rules(dev, fm, attr); 5419 } 5420 5421 /** 5422 * Allocate a counter. 5423 * 5424 * @param[in] dev 5425 * Pointer to Ethernet device structure. 5426 * 5427 * @return 5428 * Pointer to allocated counter on success, NULL otherwise. 5429 */ 5430 struct mlx5_flow_counter * 5431 mlx5_counter_alloc(struct rte_eth_dev *dev) 5432 { 5433 const struct mlx5_flow_driver_ops *fops; 5434 struct rte_flow_attr attr = { .transfer = 0 }; 5435 5436 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 5437 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5438 return fops->counter_alloc(dev); 5439 } 5440 DRV_LOG(ERR, 5441 "port %u counter allocate is not supported.", 5442 dev->data->port_id); 5443 return NULL; 5444 } 5445 5446 /** 5447 * Free a counter. 5448 * 5449 * @param[in] dev 5450 * Pointer to Ethernet device structure. 5451 * @param[in] cnt 5452 * Pointer to counter to be free. 5453 */ 5454 void 5455 mlx5_counter_free(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt) 5456 { 5457 const struct mlx5_flow_driver_ops *fops; 5458 struct rte_flow_attr attr = { .transfer = 0 }; 5459 5460 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 5461 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5462 fops->counter_free(dev, cnt); 5463 return; 5464 } 5465 DRV_LOG(ERR, 5466 "port %u counter free is not supported.", 5467 dev->data->port_id); 5468 } 5469 5470 /** 5471 * Query counter statistics. 5472 * 5473 * @param[in] dev 5474 * Pointer to Ethernet device structure. 5475 * @param[in] cnt 5476 * Pointer to counter to query. 5477 * @param[in] clear 5478 * Set to clear counter statistics. 5479 * @param[out] pkts 5480 * The counter hits packets number to save. 5481 * @param[out] bytes 5482 * The counter hits bytes number to save. 5483 * 5484 * @return 5485 * 0 on success, a negative errno value otherwise. 5486 */ 5487 int 5488 mlx5_counter_query(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt, 5489 bool clear, uint64_t *pkts, uint64_t *bytes) 5490 { 5491 const struct mlx5_flow_driver_ops *fops; 5492 struct rte_flow_attr attr = { .transfer = 0 }; 5493 5494 if (flow_get_drv_type(dev, &attr) == MLX5_FLOW_TYPE_DV) { 5495 fops = flow_get_drv_ops(MLX5_FLOW_TYPE_DV); 5496 return fops->counter_query(dev, cnt, clear, pkts, bytes); 5497 } 5498 DRV_LOG(ERR, 5499 "port %u counter query is not supported.", 5500 dev->data->port_id); 5501 return -ENOTSUP; 5502 } 5503 5504 #define MLX5_POOL_QUERY_FREQ_US 1000000 5505 5506 /** 5507 * Set the periodic procedure for triggering asynchronous batch queries for all 5508 * the counter pools. 5509 * 5510 * @param[in] sh 5511 * Pointer to mlx5_ibv_shared object. 5512 */ 5513 void 5514 mlx5_set_query_alarm(struct mlx5_ibv_shared *sh) 5515 { 5516 struct mlx5_pools_container *cont = MLX5_CNT_CONTAINER(sh, 0, 0); 5517 uint32_t pools_n = rte_atomic16_read(&cont->n_valid); 5518 uint32_t us; 5519 5520 cont = MLX5_CNT_CONTAINER(sh, 1, 0); 5521 pools_n += rte_atomic16_read(&cont->n_valid); 5522 us = MLX5_POOL_QUERY_FREQ_US / pools_n; 5523 DRV_LOG(DEBUG, "Set alarm for %u pools each %u us", pools_n, us); 5524 if (rte_eal_alarm_set(us, mlx5_flow_query_alarm, sh)) { 5525 sh->cmng.query_thread_on = 0; 5526 DRV_LOG(ERR, "Cannot reinitialize query alarm"); 5527 } else { 5528 sh->cmng.query_thread_on = 1; 5529 } 5530 } 5531 5532 /** 5533 * The periodic procedure for triggering asynchronous batch queries for all the 5534 * counter pools. This function is probably called by the host thread. 5535 * 5536 * @param[in] arg 5537 * The parameter for the alarm process. 5538 */ 5539 void 5540 mlx5_flow_query_alarm(void *arg) 5541 { 5542 struct mlx5_ibv_shared *sh = arg; 5543 struct mlx5_devx_obj *dcs; 5544 uint16_t offset; 5545 int ret; 5546 uint8_t batch = sh->cmng.batch; 5547 uint16_t pool_index = sh->cmng.pool_index; 5548 struct mlx5_pools_container *cont; 5549 struct mlx5_pools_container *mcont; 5550 struct mlx5_flow_counter_pool *pool; 5551 5552 if (sh->cmng.pending_queries >= MLX5_MAX_PENDING_QUERIES) 5553 goto set_alarm; 5554 next_container: 5555 cont = MLX5_CNT_CONTAINER(sh, batch, 1); 5556 mcont = MLX5_CNT_CONTAINER(sh, batch, 0); 5557 /* Check if resize was done and need to flip a container. */ 5558 if (cont != mcont) { 5559 if (cont->pools) { 5560 /* Clean the old container. */ 5561 rte_free(cont->pools); 5562 memset(cont, 0, sizeof(*cont)); 5563 } 5564 rte_cio_wmb(); 5565 /* Flip the host container. */ 5566 sh->cmng.mhi[batch] ^= (uint8_t)2; 5567 cont = mcont; 5568 } 5569 if (!cont->pools) { 5570 /* 2 empty containers case is unexpected. */ 5571 if (unlikely(batch != sh->cmng.batch)) 5572 goto set_alarm; 5573 batch ^= 0x1; 5574 pool_index = 0; 5575 goto next_container; 5576 } 5577 pool = cont->pools[pool_index]; 5578 if (pool->raw_hw) 5579 /* There is a pool query in progress. */ 5580 goto set_alarm; 5581 pool->raw_hw = 5582 LIST_FIRST(&sh->cmng.free_stat_raws); 5583 if (!pool->raw_hw) 5584 /* No free counter statistics raw memory. */ 5585 goto set_alarm; 5586 dcs = (struct mlx5_devx_obj *)(uintptr_t)rte_atomic64_read 5587 (&pool->a64_dcs); 5588 offset = batch ? 0 : dcs->id % MLX5_COUNTERS_PER_POOL; 5589 ret = mlx5_devx_cmd_flow_counter_query(dcs, 0, MLX5_COUNTERS_PER_POOL - 5590 offset, NULL, NULL, 5591 pool->raw_hw->mem_mng->dm->id, 5592 (void *)(uintptr_t) 5593 (pool->raw_hw->data + offset), 5594 sh->devx_comp, 5595 (uint64_t)(uintptr_t)pool); 5596 if (ret) { 5597 DRV_LOG(ERR, "Failed to trigger asynchronous query for dcs ID" 5598 " %d", pool->min_dcs->id); 5599 pool->raw_hw = NULL; 5600 goto set_alarm; 5601 } 5602 pool->raw_hw->min_dcs_id = dcs->id; 5603 LIST_REMOVE(pool->raw_hw, next); 5604 sh->cmng.pending_queries++; 5605 pool_index++; 5606 if (pool_index >= rte_atomic16_read(&cont->n_valid)) { 5607 batch ^= 0x1; 5608 pool_index = 0; 5609 } 5610 set_alarm: 5611 sh->cmng.batch = batch; 5612 sh->cmng.pool_index = pool_index; 5613 mlx5_set_query_alarm(sh); 5614 } 5615 5616 /** 5617 * Handler for the HW respond about ready values from an asynchronous batch 5618 * query. This function is probably called by the host thread. 5619 * 5620 * @param[in] sh 5621 * The pointer to the shared IB device context. 5622 * @param[in] async_id 5623 * The Devx async ID. 5624 * @param[in] status 5625 * The status of the completion. 5626 */ 5627 void 5628 mlx5_flow_async_pool_query_handle(struct mlx5_ibv_shared *sh, 5629 uint64_t async_id, int status) 5630 { 5631 struct mlx5_flow_counter_pool *pool = 5632 (struct mlx5_flow_counter_pool *)(uintptr_t)async_id; 5633 struct mlx5_counter_stats_raw *raw_to_free; 5634 5635 if (unlikely(status)) { 5636 raw_to_free = pool->raw_hw; 5637 } else { 5638 raw_to_free = pool->raw; 5639 rte_spinlock_lock(&pool->sl); 5640 pool->raw = pool->raw_hw; 5641 rte_spinlock_unlock(&pool->sl); 5642 rte_atomic64_add(&pool->query_gen, 1); 5643 /* Be sure the new raw counters data is updated in memory. */ 5644 rte_cio_wmb(); 5645 } 5646 LIST_INSERT_HEAD(&sh->cmng.free_stat_raws, raw_to_free, next); 5647 pool->raw_hw = NULL; 5648 sh->cmng.pending_queries--; 5649 } 5650 5651 /** 5652 * Translate the rte_flow group index to HW table value. 5653 * 5654 * @param[in] attributes 5655 * Pointer to flow attributes 5656 * @param[in] external 5657 * Value is part of flow rule created by request external to PMD. 5658 * @param[in] group 5659 * rte_flow group index value. 5660 * @param[out] fdb_def_rule 5661 * Whether fdb jump to table 1 is configured. 5662 * @param[out] table 5663 * HW table value. 5664 * @param[out] error 5665 * Pointer to error structure. 5666 * 5667 * @return 5668 * 0 on success, a negative errno value otherwise and rte_errno is set. 5669 */ 5670 int 5671 mlx5_flow_group_to_table(const struct rte_flow_attr *attributes, bool external, 5672 uint32_t group, bool fdb_def_rule, uint32_t *table, 5673 struct rte_flow_error *error) 5674 { 5675 if (attributes->transfer && external && fdb_def_rule) { 5676 if (group == UINT32_MAX) 5677 return rte_flow_error_set 5678 (error, EINVAL, 5679 RTE_FLOW_ERROR_TYPE_ATTR_GROUP, 5680 NULL, 5681 "group index not supported"); 5682 *table = group + 1; 5683 } else { 5684 *table = group; 5685 } 5686 return 0; 5687 } 5688 5689 /** 5690 * Discover availability of metadata reg_c's. 5691 * 5692 * Iteratively use test flows to check availability. 5693 * 5694 * @param[in] dev 5695 * Pointer to the Ethernet device structure. 5696 * 5697 * @return 5698 * 0 on success, a negative errno value otherwise and rte_errno is set. 5699 */ 5700 int 5701 mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev) 5702 { 5703 struct mlx5_priv *priv = dev->data->dev_private; 5704 struct mlx5_dev_config *config = &priv->config; 5705 enum modify_reg idx; 5706 int n = 0; 5707 5708 /* reg_c[0] and reg_c[1] are reserved. */ 5709 config->flow_mreg_c[n++] = REG_C_0; 5710 config->flow_mreg_c[n++] = REG_C_1; 5711 /* Discover availability of other reg_c's. */ 5712 for (idx = REG_C_2; idx <= REG_C_7; ++idx) { 5713 struct rte_flow_attr attr = { 5714 .group = MLX5_FLOW_MREG_CP_TABLE_GROUP, 5715 .priority = MLX5_FLOW_PRIO_RSVD, 5716 .ingress = 1, 5717 }; 5718 struct rte_flow_item items[] = { 5719 [0] = { 5720 .type = RTE_FLOW_ITEM_TYPE_END, 5721 }, 5722 }; 5723 struct rte_flow_action actions[] = { 5724 [0] = { 5725 .type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG, 5726 .conf = &(struct mlx5_flow_action_copy_mreg){ 5727 .src = REG_C_1, 5728 .dst = idx, 5729 }, 5730 }, 5731 [1] = { 5732 .type = RTE_FLOW_ACTION_TYPE_JUMP, 5733 .conf = &(struct rte_flow_action_jump){ 5734 .group = MLX5_FLOW_MREG_ACT_TABLE_GROUP, 5735 }, 5736 }, 5737 [2] = { 5738 .type = RTE_FLOW_ACTION_TYPE_END, 5739 }, 5740 }; 5741 struct rte_flow *flow; 5742 struct rte_flow_error error; 5743 5744 if (!config->dv_flow_en) 5745 break; 5746 /* Create internal flow, validation skips copy action. */ 5747 flow = flow_list_create(dev, NULL, &attr, items, 5748 actions, false, &error); 5749 if (!flow) 5750 continue; 5751 if (dev->data->dev_started || !flow_drv_apply(dev, flow, NULL)) 5752 config->flow_mreg_c[n++] = idx; 5753 flow_list_destroy(dev, NULL, flow); 5754 } 5755 for (; n < MLX5_MREG_C_NUM; ++n) 5756 config->flow_mreg_c[n] = REG_NONE; 5757 return 0; 5758 } 5759 5760 /** 5761 * Dump flow raw hw data to file 5762 * 5763 * @param[in] dev 5764 * The pointer to Ethernet device. 5765 * @param[in] file 5766 * A pointer to a file for output. 5767 * @param[out] error 5768 * Perform verbose error reporting if not NULL. PMDs initialize this 5769 * structure in case of error only. 5770 * @return 5771 * 0 on success, a nagative value otherwise. 5772 */ 5773 int 5774 mlx5_flow_dev_dump(struct rte_eth_dev *dev, 5775 FILE *file, 5776 struct rte_flow_error *error __rte_unused) 5777 { 5778 struct mlx5_priv *priv = dev->data->dev_private; 5779 struct mlx5_ibv_shared *sh = priv->sh; 5780 5781 return mlx5_devx_cmd_flow_dump(sh->fdb_domain, sh->rx_domain, 5782 sh->tx_domain, file); 5783 } 5784