1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright 2016 6WIND S.A. 3 * Copyright 2016 Mellanox Technologies, Ltd 4 */ 5 6 #include <sys/queue.h> 7 #include <stdint.h> 8 #include <string.h> 9 10 /* Verbs header. */ 11 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */ 12 #ifdef PEDANTIC 13 #pragma GCC diagnostic ignored "-Wpedantic" 14 #endif 15 #include <infiniband/verbs.h> 16 #ifdef PEDANTIC 17 #pragma GCC diagnostic error "-Wpedantic" 18 #endif 19 20 #include <rte_common.h> 21 #include <rte_ether.h> 22 #include <rte_eth_ctrl.h> 23 #include <rte_ethdev_driver.h> 24 #include <rte_flow.h> 25 #include <rte_flow_driver.h> 26 #include <rte_malloc.h> 27 #include <rte_ip.h> 28 29 #include "mlx5.h" 30 #include "mlx5_defs.h" 31 #include "mlx5_prm.h" 32 #include "mlx5_glue.h" 33 34 /* Dev ops structure defined in mlx5.c */ 35 extern const struct eth_dev_ops mlx5_dev_ops; 36 extern const struct eth_dev_ops mlx5_dev_ops_isolate; 37 38 struct rte_flow { 39 TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */ 40 }; 41 42 static const struct rte_flow_ops mlx5_flow_ops = { 43 .isolate = mlx5_flow_isolate, 44 }; 45 46 /* Convert FDIR request to Generic flow. */ 47 struct mlx5_fdir { 48 struct rte_flow_attr attr; 49 struct rte_flow_action actions[2]; 50 struct rte_flow_item items[4]; 51 struct rte_flow_item_eth l2; 52 struct rte_flow_item_eth l2_mask; 53 union { 54 struct rte_flow_item_ipv4 ipv4; 55 struct rte_flow_item_ipv6 ipv6; 56 } l3; 57 union { 58 struct rte_flow_item_ipv4 ipv4; 59 struct rte_flow_item_ipv6 ipv6; 60 } l3_mask; 61 union { 62 struct rte_flow_item_udp udp; 63 struct rte_flow_item_tcp tcp; 64 } l4; 65 union { 66 struct rte_flow_item_udp udp; 67 struct rte_flow_item_tcp tcp; 68 } l4_mask; 69 struct rte_flow_action_queue queue; 70 }; 71 72 /* Verbs specification header. */ 73 struct ibv_spec_header { 74 enum ibv_flow_spec_type type; 75 uint16_t size; 76 }; 77 78 /** 79 * Convert a flow. 80 * 81 * @param dev 82 * Pointer to Ethernet device. 83 * @param list 84 * Pointer to a TAILQ flow list. 85 * @param[in] attr 86 * Flow rule attributes. 87 * @param[in] pattern 88 * Pattern specification (list terminated by the END pattern item). 89 * @param[in] actions 90 * Associated actions (list terminated by the END action). 91 * @param[out] error 92 * Perform verbose error reporting if not NULL. 93 * 94 * @return 95 * A flow on success, NULL otherwise and rte_errno is set. 96 */ 97 static struct rte_flow * 98 mlx5_flow_list_create(struct rte_eth_dev *dev __rte_unused, 99 struct mlx5_flows *list __rte_unused, 100 const struct rte_flow_attr *attr __rte_unused, 101 const struct rte_flow_item items[] __rte_unused, 102 const struct rte_flow_action actions[] __rte_unused, 103 struct rte_flow_error *error) 104 { 105 rte_flow_error_set(error, ENOTSUP, 106 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 107 NULL, 108 "action not supported"); 109 return NULL; 110 } 111 112 /** 113 * Validate a flow supported by the NIC. 114 * 115 * @see rte_flow_validate() 116 * @see rte_flow_ops 117 */ 118 int 119 mlx5_flow_validate(struct rte_eth_dev *dev __rte_unused, 120 const struct rte_flow_attr *attr __rte_unused, 121 const struct rte_flow_item items[] __rte_unused, 122 const struct rte_flow_action actions[] __rte_unused, 123 struct rte_flow_error *error) 124 { 125 return rte_flow_error_set(error, ENOTSUP, 126 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 127 NULL, 128 "action not supported"); 129 } 130 131 /** 132 * Create a flow. 133 * 134 * @see rte_flow_create() 135 * @see rte_flow_ops 136 */ 137 struct rte_flow * 138 mlx5_flow_create(struct rte_eth_dev *dev __rte_unused, 139 const struct rte_flow_attr *attr __rte_unused, 140 const struct rte_flow_item items[] __rte_unused, 141 const struct rte_flow_action actions[] __rte_unused, 142 struct rte_flow_error *error) 143 { 144 rte_flow_error_set(error, ENOTSUP, 145 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 146 NULL, 147 "action not supported"); 148 return NULL; 149 } 150 151 /** 152 * Destroy a flow in a list. 153 * 154 * @param dev 155 * Pointer to Ethernet device. 156 * @param list 157 * Pointer to a TAILQ flow list. 158 * @param[in] flow 159 * Flow to destroy. 160 */ 161 static void 162 mlx5_flow_list_destroy(struct rte_eth_dev *dev __rte_unused, 163 struct mlx5_flows *list __rte_unused, 164 struct rte_flow *flow __rte_unused) 165 { 166 } 167 168 /** 169 * Destroy all flows. 170 * 171 * @param dev 172 * Pointer to Ethernet device. 173 * @param list 174 * Pointer to a TAILQ flow list. 175 */ 176 void 177 mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list) 178 { 179 while (!TAILQ_EMPTY(list)) { 180 struct rte_flow *flow; 181 182 flow = TAILQ_FIRST(list); 183 mlx5_flow_list_destroy(dev, list, flow); 184 } 185 } 186 187 /** 188 * Create drop queue. 189 * 190 * @param dev 191 * Pointer to Ethernet device. 192 * 193 * @return 194 * 0 on success, a negative errno value otherwise and rte_errno is set. 195 */ 196 int 197 mlx5_flow_create_drop_queue(struct rte_eth_dev *dev __rte_unused) 198 { 199 return 0; 200 } 201 202 /** 203 * Delete drop queue. 204 * 205 * @param dev 206 * Pointer to Ethernet device. 207 */ 208 void 209 mlx5_flow_delete_drop_queue(struct rte_eth_dev *dev __rte_unused) 210 { 211 } 212 213 /** 214 * Remove all flows. 215 * 216 * @param dev 217 * Pointer to Ethernet device. 218 * @param list 219 * Pointer to a TAILQ flow list. 220 */ 221 void 222 mlx5_flow_stop(struct rte_eth_dev *dev __rte_unused, 223 struct mlx5_flows *list __rte_unused) 224 { 225 } 226 227 /** 228 * Add all flows. 229 * 230 * @param dev 231 * Pointer to Ethernet device. 232 * @param list 233 * Pointer to a TAILQ flow list. 234 * 235 * @return 236 * 0 on success, a negative errno value otherwise and rte_errno is set. 237 */ 238 int 239 mlx5_flow_start(struct rte_eth_dev *dev __rte_unused, 240 struct mlx5_flows *list __rte_unused) 241 { 242 return 0; 243 } 244 245 /** 246 * Verify the flow list is empty 247 * 248 * @param dev 249 * Pointer to Ethernet device. 250 * 251 * @return the number of flows not released. 252 */ 253 int 254 mlx5_flow_verify(struct rte_eth_dev *dev) 255 { 256 struct priv *priv = dev->data->dev_private; 257 struct rte_flow *flow; 258 int ret = 0; 259 260 TAILQ_FOREACH(flow, &priv->flows, next) { 261 DRV_LOG(DEBUG, "port %u flow %p still referenced", 262 dev->data->port_id, (void *)flow); 263 ++ret; 264 } 265 return ret; 266 } 267 268 /** 269 * Enable a control flow configured from the control plane. 270 * 271 * @param dev 272 * Pointer to Ethernet device. 273 * @param eth_spec 274 * An Ethernet flow spec to apply. 275 * @param eth_mask 276 * An Ethernet flow mask to apply. 277 * @param vlan_spec 278 * A VLAN flow spec to apply. 279 * @param vlan_mask 280 * A VLAN flow mask to apply. 281 * 282 * @return 283 * 0 on success, a negative errno value otherwise and rte_errno is set. 284 */ 285 int 286 mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev, 287 struct rte_flow_item_eth *eth_spec, 288 struct rte_flow_item_eth *eth_mask, 289 struct rte_flow_item_vlan *vlan_spec, 290 struct rte_flow_item_vlan *vlan_mask) 291 { 292 struct priv *priv = dev->data->dev_private; 293 const struct rte_flow_attr attr = { 294 .ingress = 1, 295 }; 296 struct rte_flow_item items[] = { 297 { 298 .type = RTE_FLOW_ITEM_TYPE_ETH, 299 .spec = eth_spec, 300 .last = NULL, 301 .mask = eth_mask, 302 }, 303 { 304 .type = (vlan_spec) ? RTE_FLOW_ITEM_TYPE_VLAN : 305 RTE_FLOW_ITEM_TYPE_END, 306 .spec = vlan_spec, 307 .last = NULL, 308 .mask = vlan_mask, 309 }, 310 { 311 .type = RTE_FLOW_ITEM_TYPE_END, 312 }, 313 }; 314 uint16_t queue[priv->reta_idx_n]; 315 struct rte_flow_action_rss action_rss = { 316 .func = RTE_ETH_HASH_FUNCTION_DEFAULT, 317 .level = 0, 318 .types = priv->rss_conf.rss_hf, 319 .key_len = priv->rss_conf.rss_key_len, 320 .queue_num = priv->reta_idx_n, 321 .key = priv->rss_conf.rss_key, 322 .queue = queue, 323 }; 324 struct rte_flow_action actions[] = { 325 { 326 .type = RTE_FLOW_ACTION_TYPE_RSS, 327 .conf = &action_rss, 328 }, 329 { 330 .type = RTE_FLOW_ACTION_TYPE_END, 331 }, 332 }; 333 struct rte_flow *flow; 334 struct rte_flow_error error; 335 unsigned int i; 336 337 if (!priv->reta_idx_n) { 338 rte_errno = EINVAL; 339 return -rte_errno; 340 } 341 for (i = 0; i != priv->reta_idx_n; ++i) 342 queue[i] = (*priv->reta_idx)[i]; 343 flow = mlx5_flow_list_create(dev, &priv->ctrl_flows, &attr, items, 344 actions, &error); 345 if (!flow) 346 return -rte_errno; 347 return 0; 348 } 349 350 /** 351 * Enable a flow control configured from the control plane. 352 * 353 * @param dev 354 * Pointer to Ethernet device. 355 * @param eth_spec 356 * An Ethernet flow spec to apply. 357 * @param eth_mask 358 * An Ethernet flow mask to apply. 359 * 360 * @return 361 * 0 on success, a negative errno value otherwise and rte_errno is set. 362 */ 363 int 364 mlx5_ctrl_flow(struct rte_eth_dev *dev, 365 struct rte_flow_item_eth *eth_spec, 366 struct rte_flow_item_eth *eth_mask) 367 { 368 return mlx5_ctrl_flow_vlan(dev, eth_spec, eth_mask, NULL, NULL); 369 } 370 371 /** 372 * Destroy a flow. 373 * 374 * @see rte_flow_destroy() 375 * @see rte_flow_ops 376 */ 377 int 378 mlx5_flow_destroy(struct rte_eth_dev *dev, 379 struct rte_flow *flow, 380 struct rte_flow_error *error __rte_unused) 381 { 382 struct priv *priv = dev->data->dev_private; 383 384 mlx5_flow_list_destroy(dev, &priv->flows, flow); 385 return 0; 386 } 387 388 /** 389 * Destroy all flows. 390 * 391 * @see rte_flow_flush() 392 * @see rte_flow_ops 393 */ 394 int 395 mlx5_flow_flush(struct rte_eth_dev *dev, 396 struct rte_flow_error *error __rte_unused) 397 { 398 struct priv *priv = dev->data->dev_private; 399 400 mlx5_flow_list_flush(dev, &priv->flows); 401 return 0; 402 } 403 404 /** 405 * Isolated mode. 406 * 407 * @see rte_flow_isolate() 408 * @see rte_flow_ops 409 */ 410 int 411 mlx5_flow_isolate(struct rte_eth_dev *dev, 412 int enable, 413 struct rte_flow_error *error) 414 { 415 struct priv *priv = dev->data->dev_private; 416 417 if (dev->data->dev_started) { 418 rte_flow_error_set(error, EBUSY, 419 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, 420 NULL, 421 "port must be stopped first"); 422 return -rte_errno; 423 } 424 priv->isolated = !!enable; 425 if (enable) 426 dev->dev_ops = &mlx5_dev_ops_isolate; 427 else 428 dev->dev_ops = &mlx5_dev_ops; 429 return 0; 430 } 431 432 /** 433 * Convert a flow director filter to a generic flow. 434 * 435 * @param dev 436 * Pointer to Ethernet device. 437 * @param fdir_filter 438 * Flow director filter to add. 439 * @param attributes 440 * Generic flow parameters structure. 441 * 442 * @return 443 * 0 on success, a negative errno value otherwise and rte_errno is set. 444 */ 445 static int 446 mlx5_fdir_filter_convert(struct rte_eth_dev *dev, 447 const struct rte_eth_fdir_filter *fdir_filter, 448 struct mlx5_fdir *attributes) 449 { 450 struct priv *priv = dev->data->dev_private; 451 const struct rte_eth_fdir_input *input = &fdir_filter->input; 452 const struct rte_eth_fdir_masks *mask = 453 &dev->data->dev_conf.fdir_conf.mask; 454 455 /* Validate queue number. */ 456 if (fdir_filter->action.rx_queue >= priv->rxqs_n) { 457 DRV_LOG(ERR, "port %u invalid queue number %d", 458 dev->data->port_id, fdir_filter->action.rx_queue); 459 rte_errno = EINVAL; 460 return -rte_errno; 461 } 462 attributes->attr.ingress = 1; 463 attributes->items[0] = (struct rte_flow_item) { 464 .type = RTE_FLOW_ITEM_TYPE_ETH, 465 .spec = &attributes->l2, 466 .mask = &attributes->l2_mask, 467 }; 468 switch (fdir_filter->action.behavior) { 469 case RTE_ETH_FDIR_ACCEPT: 470 attributes->actions[0] = (struct rte_flow_action){ 471 .type = RTE_FLOW_ACTION_TYPE_QUEUE, 472 .conf = &attributes->queue, 473 }; 474 break; 475 case RTE_ETH_FDIR_REJECT: 476 attributes->actions[0] = (struct rte_flow_action){ 477 .type = RTE_FLOW_ACTION_TYPE_DROP, 478 }; 479 break; 480 default: 481 DRV_LOG(ERR, "port %u invalid behavior %d", 482 dev->data->port_id, 483 fdir_filter->action.behavior); 484 rte_errno = ENOTSUP; 485 return -rte_errno; 486 } 487 attributes->queue.index = fdir_filter->action.rx_queue; 488 /* Handle L3. */ 489 switch (fdir_filter->input.flow_type) { 490 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 491 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 492 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 493 attributes->l3.ipv4.hdr = (struct ipv4_hdr){ 494 .src_addr = input->flow.ip4_flow.src_ip, 495 .dst_addr = input->flow.ip4_flow.dst_ip, 496 .time_to_live = input->flow.ip4_flow.ttl, 497 .type_of_service = input->flow.ip4_flow.tos, 498 .next_proto_id = input->flow.ip4_flow.proto, 499 }; 500 attributes->l3_mask.ipv4.hdr = (struct ipv4_hdr){ 501 .src_addr = mask->ipv4_mask.src_ip, 502 .dst_addr = mask->ipv4_mask.dst_ip, 503 .time_to_live = mask->ipv4_mask.ttl, 504 .type_of_service = mask->ipv4_mask.tos, 505 .next_proto_id = mask->ipv4_mask.proto, 506 }; 507 attributes->items[1] = (struct rte_flow_item){ 508 .type = RTE_FLOW_ITEM_TYPE_IPV4, 509 .spec = &attributes->l3, 510 .mask = &attributes->l3_mask, 511 }; 512 break; 513 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 514 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 515 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 516 attributes->l3.ipv6.hdr = (struct ipv6_hdr){ 517 .hop_limits = input->flow.ipv6_flow.hop_limits, 518 .proto = input->flow.ipv6_flow.proto, 519 }; 520 521 memcpy(attributes->l3.ipv6.hdr.src_addr, 522 input->flow.ipv6_flow.src_ip, 523 RTE_DIM(attributes->l3.ipv6.hdr.src_addr)); 524 memcpy(attributes->l3.ipv6.hdr.dst_addr, 525 input->flow.ipv6_flow.dst_ip, 526 RTE_DIM(attributes->l3.ipv6.hdr.src_addr)); 527 memcpy(attributes->l3_mask.ipv6.hdr.src_addr, 528 mask->ipv6_mask.src_ip, 529 RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr)); 530 memcpy(attributes->l3_mask.ipv6.hdr.dst_addr, 531 mask->ipv6_mask.dst_ip, 532 RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr)); 533 attributes->items[1] = (struct rte_flow_item){ 534 .type = RTE_FLOW_ITEM_TYPE_IPV6, 535 .spec = &attributes->l3, 536 .mask = &attributes->l3_mask, 537 }; 538 break; 539 default: 540 DRV_LOG(ERR, "port %u invalid flow type%d", 541 dev->data->port_id, fdir_filter->input.flow_type); 542 rte_errno = ENOTSUP; 543 return -rte_errno; 544 } 545 /* Handle L4. */ 546 switch (fdir_filter->input.flow_type) { 547 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 548 attributes->l4.udp.hdr = (struct udp_hdr){ 549 .src_port = input->flow.udp4_flow.src_port, 550 .dst_port = input->flow.udp4_flow.dst_port, 551 }; 552 attributes->l4_mask.udp.hdr = (struct udp_hdr){ 553 .src_port = mask->src_port_mask, 554 .dst_port = mask->dst_port_mask, 555 }; 556 attributes->items[2] = (struct rte_flow_item){ 557 .type = RTE_FLOW_ITEM_TYPE_UDP, 558 .spec = &attributes->l4, 559 .mask = &attributes->l4_mask, 560 }; 561 break; 562 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 563 attributes->l4.tcp.hdr = (struct tcp_hdr){ 564 .src_port = input->flow.tcp4_flow.src_port, 565 .dst_port = input->flow.tcp4_flow.dst_port, 566 }; 567 attributes->l4_mask.tcp.hdr = (struct tcp_hdr){ 568 .src_port = mask->src_port_mask, 569 .dst_port = mask->dst_port_mask, 570 }; 571 attributes->items[2] = (struct rte_flow_item){ 572 .type = RTE_FLOW_ITEM_TYPE_TCP, 573 .spec = &attributes->l4, 574 .mask = &attributes->l4_mask, 575 }; 576 break; 577 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 578 attributes->l4.udp.hdr = (struct udp_hdr){ 579 .src_port = input->flow.udp6_flow.src_port, 580 .dst_port = input->flow.udp6_flow.dst_port, 581 }; 582 attributes->l4_mask.udp.hdr = (struct udp_hdr){ 583 .src_port = mask->src_port_mask, 584 .dst_port = mask->dst_port_mask, 585 }; 586 attributes->items[2] = (struct rte_flow_item){ 587 .type = RTE_FLOW_ITEM_TYPE_UDP, 588 .spec = &attributes->l4, 589 .mask = &attributes->l4_mask, 590 }; 591 break; 592 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 593 attributes->l4.tcp.hdr = (struct tcp_hdr){ 594 .src_port = input->flow.tcp6_flow.src_port, 595 .dst_port = input->flow.tcp6_flow.dst_port, 596 }; 597 attributes->l4_mask.tcp.hdr = (struct tcp_hdr){ 598 .src_port = mask->src_port_mask, 599 .dst_port = mask->dst_port_mask, 600 }; 601 attributes->items[2] = (struct rte_flow_item){ 602 .type = RTE_FLOW_ITEM_TYPE_TCP, 603 .spec = &attributes->l4, 604 .mask = &attributes->l4_mask, 605 }; 606 break; 607 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 608 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 609 break; 610 default: 611 DRV_LOG(ERR, "port %u invalid flow type%d", 612 dev->data->port_id, fdir_filter->input.flow_type); 613 rte_errno = ENOTSUP; 614 return -rte_errno; 615 } 616 return 0; 617 } 618 619 /** 620 * Add new flow director filter and store it in list. 621 * 622 * @param dev 623 * Pointer to Ethernet device. 624 * @param fdir_filter 625 * Flow director filter to add. 626 * 627 * @return 628 * 0 on success, a negative errno value otherwise and rte_errno is set. 629 */ 630 static int 631 mlx5_fdir_filter_add(struct rte_eth_dev *dev, 632 const struct rte_eth_fdir_filter *fdir_filter) 633 { 634 struct priv *priv = dev->data->dev_private; 635 struct mlx5_fdir attributes = { 636 .attr.group = 0, 637 .l2_mask = { 638 .dst.addr_bytes = "\x00\x00\x00\x00\x00\x00", 639 .src.addr_bytes = "\x00\x00\x00\x00\x00\x00", 640 .type = 0, 641 }, 642 }; 643 struct rte_flow_error error; 644 struct rte_flow *flow; 645 int ret; 646 647 ret = mlx5_fdir_filter_convert(dev, fdir_filter, &attributes); 648 if (ret) 649 return ret; 650 flow = mlx5_flow_list_create(dev, &priv->flows, &attributes.attr, 651 attributes.items, attributes.actions, 652 &error); 653 if (flow) { 654 DRV_LOG(DEBUG, "port %u FDIR created %p", dev->data->port_id, 655 (void *)flow); 656 return 0; 657 } 658 return -rte_errno; 659 } 660 661 /** 662 * Delete specific filter. 663 * 664 * @param dev 665 * Pointer to Ethernet device. 666 * @param fdir_filter 667 * Filter to be deleted. 668 * 669 * @return 670 * 0 on success, a negative errno value otherwise and rte_errno is set. 671 */ 672 static int 673 mlx5_fdir_filter_delete(struct rte_eth_dev *dev __rte_unused, 674 const struct rte_eth_fdir_filter *fdir_filter 675 __rte_unused) 676 { 677 rte_errno = ENOTSUP; 678 return -rte_errno; 679 } 680 681 /** 682 * Update queue for specific filter. 683 * 684 * @param dev 685 * Pointer to Ethernet device. 686 * @param fdir_filter 687 * Filter to be updated. 688 * 689 * @return 690 * 0 on success, a negative errno value otherwise and rte_errno is set. 691 */ 692 static int 693 mlx5_fdir_filter_update(struct rte_eth_dev *dev, 694 const struct rte_eth_fdir_filter *fdir_filter) 695 { 696 int ret; 697 698 ret = mlx5_fdir_filter_delete(dev, fdir_filter); 699 if (ret) 700 return ret; 701 return mlx5_fdir_filter_add(dev, fdir_filter); 702 } 703 704 /** 705 * Flush all filters. 706 * 707 * @param dev 708 * Pointer to Ethernet device. 709 */ 710 static void 711 mlx5_fdir_filter_flush(struct rte_eth_dev *dev) 712 { 713 struct priv *priv = dev->data->dev_private; 714 715 mlx5_flow_list_flush(dev, &priv->flows); 716 } 717 718 /** 719 * Get flow director information. 720 * 721 * @param dev 722 * Pointer to Ethernet device. 723 * @param[out] fdir_info 724 * Resulting flow director information. 725 */ 726 static void 727 mlx5_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info) 728 { 729 struct rte_eth_fdir_masks *mask = 730 &dev->data->dev_conf.fdir_conf.mask; 731 732 fdir_info->mode = dev->data->dev_conf.fdir_conf.mode; 733 fdir_info->guarant_spc = 0; 734 rte_memcpy(&fdir_info->mask, mask, sizeof(fdir_info->mask)); 735 fdir_info->max_flexpayload = 0; 736 fdir_info->flow_types_mask[0] = 0; 737 fdir_info->flex_payload_unit = 0; 738 fdir_info->max_flex_payload_segment_num = 0; 739 fdir_info->flex_payload_limit = 0; 740 memset(&fdir_info->flex_conf, 0, sizeof(fdir_info->flex_conf)); 741 } 742 743 /** 744 * Deal with flow director operations. 745 * 746 * @param dev 747 * Pointer to Ethernet device. 748 * @param filter_op 749 * Operation to perform. 750 * @param arg 751 * Pointer to operation-specific structure. 752 * 753 * @return 754 * 0 on success, a negative errno value otherwise and rte_errno is set. 755 */ 756 static int 757 mlx5_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op, 758 void *arg) 759 { 760 enum rte_fdir_mode fdir_mode = 761 dev->data->dev_conf.fdir_conf.mode; 762 763 if (filter_op == RTE_ETH_FILTER_NOP) 764 return 0; 765 if (fdir_mode != RTE_FDIR_MODE_PERFECT && 766 fdir_mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) { 767 DRV_LOG(ERR, "port %u flow director mode %d not supported", 768 dev->data->port_id, fdir_mode); 769 rte_errno = EINVAL; 770 return -rte_errno; 771 } 772 switch (filter_op) { 773 case RTE_ETH_FILTER_ADD: 774 return mlx5_fdir_filter_add(dev, arg); 775 case RTE_ETH_FILTER_UPDATE: 776 return mlx5_fdir_filter_update(dev, arg); 777 case RTE_ETH_FILTER_DELETE: 778 return mlx5_fdir_filter_delete(dev, arg); 779 case RTE_ETH_FILTER_FLUSH: 780 mlx5_fdir_filter_flush(dev); 781 break; 782 case RTE_ETH_FILTER_INFO: 783 mlx5_fdir_info_get(dev, arg); 784 break; 785 default: 786 DRV_LOG(DEBUG, "port %u unknown operation %u", 787 dev->data->port_id, filter_op); 788 rte_errno = EINVAL; 789 return -rte_errno; 790 } 791 return 0; 792 } 793 794 /** 795 * Manage filter operations. 796 * 797 * @param dev 798 * Pointer to Ethernet device structure. 799 * @param filter_type 800 * Filter type. 801 * @param filter_op 802 * Operation to perform. 803 * @param arg 804 * Pointer to operation-specific structure. 805 * 806 * @return 807 * 0 on success, a negative errno value otherwise and rte_errno is set. 808 */ 809 int 810 mlx5_dev_filter_ctrl(struct rte_eth_dev *dev, 811 enum rte_filter_type filter_type, 812 enum rte_filter_op filter_op, 813 void *arg) 814 { 815 switch (filter_type) { 816 case RTE_ETH_FILTER_GENERIC: 817 if (filter_op != RTE_ETH_FILTER_GET) { 818 rte_errno = EINVAL; 819 return -rte_errno; 820 } 821 *(const void **)arg = &mlx5_flow_ops; 822 return 0; 823 case RTE_ETH_FILTER_FDIR: 824 return mlx5_fdir_ctrl_func(dev, filter_op, arg); 825 default: 826 DRV_LOG(ERR, "port %u filter type (%d) not supported", 827 dev->data->port_id, filter_type); 828 rte_errno = ENOTSUP; 829 return -rte_errno; 830 } 831 return 0; 832 } 833 834 /** 835 * Detect number of Verbs flow priorities supported. 836 * 837 * @param dev 838 * Pointer to Ethernet device. 839 * 840 * @return 841 * number of supported Verbs flow priority. 842 */ 843 unsigned int 844 mlx5_get_max_verbs_prio(struct rte_eth_dev *dev __rte_unused) 845 { 846 return 8; 847 } 848