1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
11 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
13 #pragma GCC diagnostic ignored "-Wpedantic"
15 #include <infiniband/verbs.h>
17 #pragma GCC diagnostic error "-Wpedantic"
20 #include <rte_common.h>
21 #include <rte_ether.h>
22 #include <rte_eth_ctrl.h>
23 #include <rte_ethdev_driver.h>
25 #include <rte_flow_driver.h>
26 #include <rte_malloc.h>
30 #include "mlx5_defs.h"
32 #include "mlx5_glue.h"
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;
39 TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
42 static const struct rte_flow_ops mlx5_flow_ops = {
43 .isolate = mlx5_flow_isolate,
46 /* Convert FDIR request to Generic flow. */
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;
54 struct rte_flow_item_ipv4 ipv4;
55 struct rte_flow_item_ipv6 ipv6;
58 struct rte_flow_item_ipv4 ipv4;
59 struct rte_flow_item_ipv6 ipv6;
62 struct rte_flow_item_udp udp;
63 struct rte_flow_item_tcp tcp;
66 struct rte_flow_item_udp udp;
67 struct rte_flow_item_tcp tcp;
69 struct rte_flow_action_queue queue;
72 /* Verbs specification header. */
73 struct ibv_spec_header {
74 enum ibv_flow_spec_type type;
79 * Discover the maximum number of priority available.
82 * Pointer to Ethernet device.
85 * number of supported flow priority on success, a negative errno value
86 * otherwise and rte_errno is set.
89 mlx5_flow_discover_priorities(struct rte_eth_dev *dev)
92 struct ibv_flow_attr attr;
93 struct ibv_flow_spec_eth eth;
94 struct ibv_flow_spec_action_drop drop;
100 .type = IBV_FLOW_SPEC_ETH,
101 .size = sizeof(struct ibv_flow_spec_eth),
104 .size = sizeof(struct ibv_flow_spec_action_drop),
105 .type = IBV_FLOW_SPEC_ACTION_DROP,
108 struct ibv_flow *flow;
109 struct mlx5_hrxq *drop = mlx5_hrxq_drop_new(dev);
110 uint16_t vprio[] = { 8, 16 };
117 for (i = 0; i != RTE_DIM(vprio); i++) {
118 flow_attr.attr.priority = vprio[i] - 1;
119 flow = mlx5_glue->create_flow(drop->qp, &flow_attr.attr);
122 claim_zero(mlx5_glue->destroy_flow(flow));
124 mlx5_hrxq_drop_release(dev);
125 DRV_LOG(INFO, "port %u flow maximum priority: %d",
126 dev->data->port_id, vprio[i - 1]);
134 * Pointer to Ethernet device.
136 * Pointer to a TAILQ flow list.
138 * Flow rule attributes.
140 * Pattern specification (list terminated by the END pattern item).
142 * Associated actions (list terminated by the END action).
144 * Perform verbose error reporting if not NULL.
147 * A flow on success, NULL otherwise and rte_errno is set.
149 static struct rte_flow *
150 mlx5_flow_list_create(struct rte_eth_dev *dev __rte_unused,
151 struct mlx5_flows *list __rte_unused,
152 const struct rte_flow_attr *attr __rte_unused,
153 const struct rte_flow_item items[] __rte_unused,
154 const struct rte_flow_action actions[] __rte_unused,
155 struct rte_flow_error *error)
157 rte_flow_error_set(error, ENOTSUP,
158 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
160 "action not supported");
165 * Validate a flow supported by the NIC.
167 * @see rte_flow_validate()
171 mlx5_flow_validate(struct rte_eth_dev *dev __rte_unused,
172 const struct rte_flow_attr *attr __rte_unused,
173 const struct rte_flow_item items[] __rte_unused,
174 const struct rte_flow_action actions[] __rte_unused,
175 struct rte_flow_error *error)
177 return rte_flow_error_set(error, ENOTSUP,
178 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
180 "action not supported");
186 * @see rte_flow_create()
190 mlx5_flow_create(struct rte_eth_dev *dev __rte_unused,
191 const struct rte_flow_attr *attr __rte_unused,
192 const struct rte_flow_item items[] __rte_unused,
193 const struct rte_flow_action actions[] __rte_unused,
194 struct rte_flow_error *error)
196 rte_flow_error_set(error, ENOTSUP,
197 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
199 "action not supported");
204 * Destroy a flow in a list.
207 * Pointer to Ethernet device.
209 * Pointer to a TAILQ flow list.
214 mlx5_flow_list_destroy(struct rte_eth_dev *dev __rte_unused,
215 struct mlx5_flows *list __rte_unused,
216 struct rte_flow *flow __rte_unused)
224 * Pointer to Ethernet device.
226 * Pointer to a TAILQ flow list.
229 mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list)
231 while (!TAILQ_EMPTY(list)) {
232 struct rte_flow *flow;
234 flow = TAILQ_FIRST(list);
235 mlx5_flow_list_destroy(dev, list, flow);
243 * Pointer to Ethernet device.
245 * Pointer to a TAILQ flow list.
248 mlx5_flow_stop(struct rte_eth_dev *dev __rte_unused,
249 struct mlx5_flows *list __rte_unused)
257 * Pointer to Ethernet device.
259 * Pointer to a TAILQ flow list.
262 * 0 on success, a negative errno value otherwise and rte_errno is set.
265 mlx5_flow_start(struct rte_eth_dev *dev __rte_unused,
266 struct mlx5_flows *list __rte_unused)
272 * Verify the flow list is empty
275 * Pointer to Ethernet device.
277 * @return the number of flows not released.
280 mlx5_flow_verify(struct rte_eth_dev *dev)
282 struct priv *priv = dev->data->dev_private;
283 struct rte_flow *flow;
286 TAILQ_FOREACH(flow, &priv->flows, next) {
287 DRV_LOG(DEBUG, "port %u flow %p still referenced",
288 dev->data->port_id, (void *)flow);
295 * Enable a control flow configured from the control plane.
298 * Pointer to Ethernet device.
300 * An Ethernet flow spec to apply.
302 * An Ethernet flow mask to apply.
304 * A VLAN flow spec to apply.
306 * A VLAN flow mask to apply.
309 * 0 on success, a negative errno value otherwise and rte_errno is set.
312 mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev,
313 struct rte_flow_item_eth *eth_spec,
314 struct rte_flow_item_eth *eth_mask,
315 struct rte_flow_item_vlan *vlan_spec,
316 struct rte_flow_item_vlan *vlan_mask)
318 struct priv *priv = dev->data->dev_private;
319 const struct rte_flow_attr attr = {
321 .priority = priv->config.flow_prio - 1,
323 struct rte_flow_item items[] = {
325 .type = RTE_FLOW_ITEM_TYPE_ETH,
331 .type = (vlan_spec) ? RTE_FLOW_ITEM_TYPE_VLAN :
332 RTE_FLOW_ITEM_TYPE_END,
338 .type = RTE_FLOW_ITEM_TYPE_END,
341 uint16_t queue[priv->reta_idx_n];
342 struct rte_flow_action_rss action_rss = {
343 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
345 .types = priv->rss_conf.rss_hf,
346 .key_len = priv->rss_conf.rss_key_len,
347 .queue_num = priv->reta_idx_n,
348 .key = priv->rss_conf.rss_key,
351 struct rte_flow_action actions[] = {
353 .type = RTE_FLOW_ACTION_TYPE_RSS,
357 .type = RTE_FLOW_ACTION_TYPE_END,
360 struct rte_flow *flow;
361 struct rte_flow_error error;
364 if (!priv->reta_idx_n) {
368 for (i = 0; i != priv->reta_idx_n; ++i)
369 queue[i] = (*priv->reta_idx)[i];
370 flow = mlx5_flow_list_create(dev, &priv->ctrl_flows, &attr, items,
378 * Enable a flow control configured from the control plane.
381 * Pointer to Ethernet device.
383 * An Ethernet flow spec to apply.
385 * An Ethernet flow mask to apply.
388 * 0 on success, a negative errno value otherwise and rte_errno is set.
391 mlx5_ctrl_flow(struct rte_eth_dev *dev,
392 struct rte_flow_item_eth *eth_spec,
393 struct rte_flow_item_eth *eth_mask)
395 return mlx5_ctrl_flow_vlan(dev, eth_spec, eth_mask, NULL, NULL);
401 * @see rte_flow_destroy()
405 mlx5_flow_destroy(struct rte_eth_dev *dev,
406 struct rte_flow *flow,
407 struct rte_flow_error *error __rte_unused)
409 struct priv *priv = dev->data->dev_private;
411 mlx5_flow_list_destroy(dev, &priv->flows, flow);
418 * @see rte_flow_flush()
422 mlx5_flow_flush(struct rte_eth_dev *dev,
423 struct rte_flow_error *error __rte_unused)
425 struct priv *priv = dev->data->dev_private;
427 mlx5_flow_list_flush(dev, &priv->flows);
434 * @see rte_flow_isolate()
438 mlx5_flow_isolate(struct rte_eth_dev *dev,
440 struct rte_flow_error *error)
442 struct priv *priv = dev->data->dev_private;
444 if (dev->data->dev_started) {
445 rte_flow_error_set(error, EBUSY,
446 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
448 "port must be stopped first");
451 priv->isolated = !!enable;
453 dev->dev_ops = &mlx5_dev_ops_isolate;
455 dev->dev_ops = &mlx5_dev_ops;
460 * Convert a flow director filter to a generic flow.
463 * Pointer to Ethernet device.
465 * Flow director filter to add.
467 * Generic flow parameters structure.
470 * 0 on success, a negative errno value otherwise and rte_errno is set.
473 mlx5_fdir_filter_convert(struct rte_eth_dev *dev,
474 const struct rte_eth_fdir_filter *fdir_filter,
475 struct mlx5_fdir *attributes)
477 struct priv *priv = dev->data->dev_private;
478 const struct rte_eth_fdir_input *input = &fdir_filter->input;
479 const struct rte_eth_fdir_masks *mask =
480 &dev->data->dev_conf.fdir_conf.mask;
482 /* Validate queue number. */
483 if (fdir_filter->action.rx_queue >= priv->rxqs_n) {
484 DRV_LOG(ERR, "port %u invalid queue number %d",
485 dev->data->port_id, fdir_filter->action.rx_queue);
489 attributes->attr.ingress = 1;
490 attributes->items[0] = (struct rte_flow_item) {
491 .type = RTE_FLOW_ITEM_TYPE_ETH,
492 .spec = &attributes->l2,
493 .mask = &attributes->l2_mask,
495 switch (fdir_filter->action.behavior) {
496 case RTE_ETH_FDIR_ACCEPT:
497 attributes->actions[0] = (struct rte_flow_action){
498 .type = RTE_FLOW_ACTION_TYPE_QUEUE,
499 .conf = &attributes->queue,
502 case RTE_ETH_FDIR_REJECT:
503 attributes->actions[0] = (struct rte_flow_action){
504 .type = RTE_FLOW_ACTION_TYPE_DROP,
508 DRV_LOG(ERR, "port %u invalid behavior %d",
510 fdir_filter->action.behavior);
514 attributes->queue.index = fdir_filter->action.rx_queue;
516 switch (fdir_filter->input.flow_type) {
517 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
518 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
519 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
520 attributes->l3.ipv4.hdr = (struct ipv4_hdr){
521 .src_addr = input->flow.ip4_flow.src_ip,
522 .dst_addr = input->flow.ip4_flow.dst_ip,
523 .time_to_live = input->flow.ip4_flow.ttl,
524 .type_of_service = input->flow.ip4_flow.tos,
525 .next_proto_id = input->flow.ip4_flow.proto,
527 attributes->l3_mask.ipv4.hdr = (struct ipv4_hdr){
528 .src_addr = mask->ipv4_mask.src_ip,
529 .dst_addr = mask->ipv4_mask.dst_ip,
530 .time_to_live = mask->ipv4_mask.ttl,
531 .type_of_service = mask->ipv4_mask.tos,
532 .next_proto_id = mask->ipv4_mask.proto,
534 attributes->items[1] = (struct rte_flow_item){
535 .type = RTE_FLOW_ITEM_TYPE_IPV4,
536 .spec = &attributes->l3,
537 .mask = &attributes->l3_mask,
540 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
541 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
542 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
543 attributes->l3.ipv6.hdr = (struct ipv6_hdr){
544 .hop_limits = input->flow.ipv6_flow.hop_limits,
545 .proto = input->flow.ipv6_flow.proto,
548 memcpy(attributes->l3.ipv6.hdr.src_addr,
549 input->flow.ipv6_flow.src_ip,
550 RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
551 memcpy(attributes->l3.ipv6.hdr.dst_addr,
552 input->flow.ipv6_flow.dst_ip,
553 RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
554 memcpy(attributes->l3_mask.ipv6.hdr.src_addr,
555 mask->ipv6_mask.src_ip,
556 RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr));
557 memcpy(attributes->l3_mask.ipv6.hdr.dst_addr,
558 mask->ipv6_mask.dst_ip,
559 RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr));
560 attributes->items[1] = (struct rte_flow_item){
561 .type = RTE_FLOW_ITEM_TYPE_IPV6,
562 .spec = &attributes->l3,
563 .mask = &attributes->l3_mask,
567 DRV_LOG(ERR, "port %u invalid flow type%d",
568 dev->data->port_id, fdir_filter->input.flow_type);
573 switch (fdir_filter->input.flow_type) {
574 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
575 attributes->l4.udp.hdr = (struct udp_hdr){
576 .src_port = input->flow.udp4_flow.src_port,
577 .dst_port = input->flow.udp4_flow.dst_port,
579 attributes->l4_mask.udp.hdr = (struct udp_hdr){
580 .src_port = mask->src_port_mask,
581 .dst_port = mask->dst_port_mask,
583 attributes->items[2] = (struct rte_flow_item){
584 .type = RTE_FLOW_ITEM_TYPE_UDP,
585 .spec = &attributes->l4,
586 .mask = &attributes->l4_mask,
589 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
590 attributes->l4.tcp.hdr = (struct tcp_hdr){
591 .src_port = input->flow.tcp4_flow.src_port,
592 .dst_port = input->flow.tcp4_flow.dst_port,
594 attributes->l4_mask.tcp.hdr = (struct tcp_hdr){
595 .src_port = mask->src_port_mask,
596 .dst_port = mask->dst_port_mask,
598 attributes->items[2] = (struct rte_flow_item){
599 .type = RTE_FLOW_ITEM_TYPE_TCP,
600 .spec = &attributes->l4,
601 .mask = &attributes->l4_mask,
604 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
605 attributes->l4.udp.hdr = (struct udp_hdr){
606 .src_port = input->flow.udp6_flow.src_port,
607 .dst_port = input->flow.udp6_flow.dst_port,
609 attributes->l4_mask.udp.hdr = (struct udp_hdr){
610 .src_port = mask->src_port_mask,
611 .dst_port = mask->dst_port_mask,
613 attributes->items[2] = (struct rte_flow_item){
614 .type = RTE_FLOW_ITEM_TYPE_UDP,
615 .spec = &attributes->l4,
616 .mask = &attributes->l4_mask,
619 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
620 attributes->l4.tcp.hdr = (struct tcp_hdr){
621 .src_port = input->flow.tcp6_flow.src_port,
622 .dst_port = input->flow.tcp6_flow.dst_port,
624 attributes->l4_mask.tcp.hdr = (struct tcp_hdr){
625 .src_port = mask->src_port_mask,
626 .dst_port = mask->dst_port_mask,
628 attributes->items[2] = (struct rte_flow_item){
629 .type = RTE_FLOW_ITEM_TYPE_TCP,
630 .spec = &attributes->l4,
631 .mask = &attributes->l4_mask,
634 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
635 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
638 DRV_LOG(ERR, "port %u invalid flow type%d",
639 dev->data->port_id, fdir_filter->input.flow_type);
647 * Add new flow director filter and store it in list.
650 * Pointer to Ethernet device.
652 * Flow director filter to add.
655 * 0 on success, a negative errno value otherwise and rte_errno is set.
658 mlx5_fdir_filter_add(struct rte_eth_dev *dev,
659 const struct rte_eth_fdir_filter *fdir_filter)
661 struct priv *priv = dev->data->dev_private;
662 struct mlx5_fdir attributes = {
665 .dst.addr_bytes = "\x00\x00\x00\x00\x00\x00",
666 .src.addr_bytes = "\x00\x00\x00\x00\x00\x00",
670 struct rte_flow_error error;
671 struct rte_flow *flow;
674 ret = mlx5_fdir_filter_convert(dev, fdir_filter, &attributes);
677 flow = mlx5_flow_list_create(dev, &priv->flows, &attributes.attr,
678 attributes.items, attributes.actions,
681 DRV_LOG(DEBUG, "port %u FDIR created %p", dev->data->port_id,
689 * Delete specific filter.
692 * Pointer to Ethernet device.
694 * Filter to be deleted.
697 * 0 on success, a negative errno value otherwise and rte_errno is set.
700 mlx5_fdir_filter_delete(struct rte_eth_dev *dev __rte_unused,
701 const struct rte_eth_fdir_filter *fdir_filter
709 * Update queue for specific filter.
712 * Pointer to Ethernet device.
714 * Filter to be updated.
717 * 0 on success, a negative errno value otherwise and rte_errno is set.
720 mlx5_fdir_filter_update(struct rte_eth_dev *dev,
721 const struct rte_eth_fdir_filter *fdir_filter)
725 ret = mlx5_fdir_filter_delete(dev, fdir_filter);
728 return mlx5_fdir_filter_add(dev, fdir_filter);
735 * Pointer to Ethernet device.
738 mlx5_fdir_filter_flush(struct rte_eth_dev *dev)
740 struct priv *priv = dev->data->dev_private;
742 mlx5_flow_list_flush(dev, &priv->flows);
746 * Get flow director information.
749 * Pointer to Ethernet device.
750 * @param[out] fdir_info
751 * Resulting flow director information.
754 mlx5_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info)
756 struct rte_eth_fdir_masks *mask =
757 &dev->data->dev_conf.fdir_conf.mask;
759 fdir_info->mode = dev->data->dev_conf.fdir_conf.mode;
760 fdir_info->guarant_spc = 0;
761 rte_memcpy(&fdir_info->mask, mask, sizeof(fdir_info->mask));
762 fdir_info->max_flexpayload = 0;
763 fdir_info->flow_types_mask[0] = 0;
764 fdir_info->flex_payload_unit = 0;
765 fdir_info->max_flex_payload_segment_num = 0;
766 fdir_info->flex_payload_limit = 0;
767 memset(&fdir_info->flex_conf, 0, sizeof(fdir_info->flex_conf));
771 * Deal with flow director operations.
774 * Pointer to Ethernet device.
776 * Operation to perform.
778 * Pointer to operation-specific structure.
781 * 0 on success, a negative errno value otherwise and rte_errno is set.
784 mlx5_fdir_ctrl_func(struct rte_eth_dev *dev, enum rte_filter_op filter_op,
787 enum rte_fdir_mode fdir_mode =
788 dev->data->dev_conf.fdir_conf.mode;
790 if (filter_op == RTE_ETH_FILTER_NOP)
792 if (fdir_mode != RTE_FDIR_MODE_PERFECT &&
793 fdir_mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
794 DRV_LOG(ERR, "port %u flow director mode %d not supported",
795 dev->data->port_id, fdir_mode);
800 case RTE_ETH_FILTER_ADD:
801 return mlx5_fdir_filter_add(dev, arg);
802 case RTE_ETH_FILTER_UPDATE:
803 return mlx5_fdir_filter_update(dev, arg);
804 case RTE_ETH_FILTER_DELETE:
805 return mlx5_fdir_filter_delete(dev, arg);
806 case RTE_ETH_FILTER_FLUSH:
807 mlx5_fdir_filter_flush(dev);
809 case RTE_ETH_FILTER_INFO:
810 mlx5_fdir_info_get(dev, arg);
813 DRV_LOG(DEBUG, "port %u unknown operation %u",
814 dev->data->port_id, filter_op);
822 * Manage filter operations.
825 * Pointer to Ethernet device structure.
829 * Operation to perform.
831 * Pointer to operation-specific structure.
834 * 0 on success, a negative errno value otherwise and rte_errno is set.
837 mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
838 enum rte_filter_type filter_type,
839 enum rte_filter_op filter_op,
842 switch (filter_type) {
843 case RTE_ETH_FILTER_GENERIC:
844 if (filter_op != RTE_ETH_FILTER_GET) {
848 *(const void **)arg = &mlx5_flow_ops;
850 case RTE_ETH_FILTER_FDIR:
851 return mlx5_fdir_ctrl_func(dev, filter_op, arg);
853 DRV_LOG(ERR, "port %u filter type (%d) not supported",
854 dev->data->port_id, filter_type);