net/dpaa2: fix the ethdev offload checks
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
index e6af324..1807e3f 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2016 6WIND S.A.
- * Copyright 2016 Mellanox.
+ * Copyright 2016 Mellanox Technologies, Ltd
  */
 
 #include <sys/queue.h>
@@ -16,6 +16,7 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include <rte_common.h>
 #include <rte_ethdev_driver.h>
 #include <rte_flow.h>
 #include <rte_flow_driver.h>
@@ -442,10 +443,18 @@ struct mlx5_fdir {
                struct rte_flow_item_ipv4 ipv4;
                struct rte_flow_item_ipv6 ipv6;
        } l3;
+       union {
+               struct rte_flow_item_ipv4 ipv4;
+               struct rte_flow_item_ipv6 ipv6;
+       } l3_mask;
        union {
                struct rte_flow_item_udp udp;
                struct rte_flow_item_tcp tcp;
        } l4;
+       union {
+               struct rte_flow_item_udp udp;
+               struct rte_flow_item_tcp tcp;
+       } l4_mask;
        struct rte_flow_action_queue queue;
 };
 
@@ -713,6 +722,14 @@ mlx5_flow_convert_actions(struct rte_eth_dev *dev,
                                        return -rte_errno;
                                }
                        }
+                       if (rss->num > RTE_DIM(parser->queues)) {
+                               rte_flow_error_set(error, EINVAL,
+                                                  RTE_FLOW_ERROR_TYPE_ACTION,
+                                                  actions,
+                                                  "too many queues for RSS"
+                                                  " context");
+                               return -rte_errno;
+                       }
                        for (n = 0; n < rss->num; ++n) {
                                if (rss->queue[n] >= priv->rxqs_n) {
                                        rte_flow_error_set(error, EINVAL,
@@ -817,8 +834,10 @@ mlx5_flow_convert_items_validate(const struct rte_flow_item items[],
                                break;
                        }
                }
-               if (!token)
+               if (!token) {
+                       ret = -ENOTSUP;
                        goto exit_item_not_supported;
+               }
                cur_item = token;
                ret = mlx5_flow_item_validate(items,
                                              (const uint8_t *)cur_item->mask,
@@ -2661,6 +2680,8 @@ mlx5_fdir_filter_convert(struct rte_eth_dev *dev,
 {
        struct priv *priv = dev->data->dev_private;
        const struct rte_eth_fdir_input *input = &fdir_filter->input;
+       const struct rte_eth_fdir_masks *mask =
+               &dev->data->dev_conf.fdir_conf.mask;
 
        /* Validate queue number. */
        if (fdir_filter->action.rx_queue >= priv->rxqs_n) {
@@ -2695,135 +2716,127 @@ mlx5_fdir_filter_convert(struct rte_eth_dev *dev,
                return -rte_errno;
        }
        attributes->queue.index = fdir_filter->action.rx_queue;
+       /* Handle L3. */
        switch (fdir_filter->input.flow_type) {
        case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
+       case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
                attributes->l3.ipv4.hdr = (struct ipv4_hdr){
-                       .src_addr = input->flow.udp4_flow.ip.src_ip,
-                       .dst_addr = input->flow.udp4_flow.ip.dst_ip,
-                       .time_to_live = input->flow.udp4_flow.ip.ttl,
-                       .type_of_service = input->flow.udp4_flow.ip.tos,
-                       .next_proto_id = input->flow.udp4_flow.ip.proto,
+                       .src_addr = input->flow.ip4_flow.src_ip,
+                       .dst_addr = input->flow.ip4_flow.dst_ip,
+                       .time_to_live = input->flow.ip4_flow.ttl,
+                       .type_of_service = input->flow.ip4_flow.tos,
+                       .next_proto_id = input->flow.ip4_flow.proto,
                };
-               attributes->l4.udp.hdr = (struct udp_hdr){
-                       .src_port = input->flow.udp4_flow.src_port,
-                       .dst_port = input->flow.udp4_flow.dst_port,
+               attributes->l3_mask.ipv4.hdr = (struct ipv4_hdr){
+                       .src_addr = mask->ipv4_mask.src_ip,
+                       .dst_addr = mask->ipv4_mask.dst_ip,
+                       .time_to_live = mask->ipv4_mask.ttl,
+                       .type_of_service = mask->ipv4_mask.tos,
+                       .next_proto_id = mask->ipv4_mask.proto,
                };
                attributes->items[1] = (struct rte_flow_item){
                        .type = RTE_FLOW_ITEM_TYPE_IPV4,
                        .spec = &attributes->l3,
-                       .mask = &attributes->l3,
+                       .mask = &attributes->l3_mask,
+               };
+               break;
+       case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
+       case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
+               attributes->l3.ipv6.hdr = (struct ipv6_hdr){
+                       .hop_limits = input->flow.ipv6_flow.hop_limits,
+                       .proto = input->flow.ipv6_flow.proto,
+               };
+
+               memcpy(attributes->l3.ipv6.hdr.src_addr,
+                      input->flow.ipv6_flow.src_ip,
+                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
+               memcpy(attributes->l3.ipv6.hdr.dst_addr,
+                      input->flow.ipv6_flow.dst_ip,
+                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
+               memcpy(attributes->l3_mask.ipv6.hdr.src_addr,
+                      mask->ipv6_mask.src_ip,
+                      RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr));
+               memcpy(attributes->l3_mask.ipv6.hdr.dst_addr,
+                      mask->ipv6_mask.dst_ip,
+                      RTE_DIM(attributes->l3_mask.ipv6.hdr.src_addr));
+               attributes->items[1] = (struct rte_flow_item){
+                       .type = RTE_FLOW_ITEM_TYPE_IPV6,
+                       .spec = &attributes->l3,
+                       .mask = &attributes->l3_mask,
+               };
+               break;
+       default:
+               DRV_LOG(ERR, "port %u invalid flow type%d",
+                       dev->data->port_id, fdir_filter->input.flow_type);
+               rte_errno = ENOTSUP;
+               return -rte_errno;
+       }
+       /* Handle L4. */
+       switch (fdir_filter->input.flow_type) {
+       case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
+               attributes->l4.udp.hdr = (struct udp_hdr){
+                       .src_port = input->flow.udp4_flow.src_port,
+                       .dst_port = input->flow.udp4_flow.dst_port,
+               };
+               attributes->l4_mask.udp.hdr = (struct udp_hdr){
+                       .src_port = mask->src_port_mask,
+                       .dst_port = mask->dst_port_mask,
                };
                attributes->items[2] = (struct rte_flow_item){
                        .type = RTE_FLOW_ITEM_TYPE_UDP,
                        .spec = &attributes->l4,
-                       .mask = &attributes->l4,
+                       .mask = &attributes->l4_mask,
                };
                break;
        case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
-               attributes->l3.ipv4.hdr = (struct ipv4_hdr){
-                       .src_addr = input->flow.tcp4_flow.ip.src_ip,
-                       .dst_addr = input->flow.tcp4_flow.ip.dst_ip,
-                       .time_to_live = input->flow.tcp4_flow.ip.ttl,
-                       .type_of_service = input->flow.tcp4_flow.ip.tos,
-                       .next_proto_id = input->flow.tcp4_flow.ip.proto,
-               };
                attributes->l4.tcp.hdr = (struct tcp_hdr){
                        .src_port = input->flow.tcp4_flow.src_port,
                        .dst_port = input->flow.tcp4_flow.dst_port,
                };
-               attributes->items[1] = (struct rte_flow_item){
-                       .type = RTE_FLOW_ITEM_TYPE_IPV4,
-                       .spec = &attributes->l3,
-                       .mask = &attributes->l3,
+               attributes->l4_mask.tcp.hdr = (struct tcp_hdr){
+                       .src_port = mask->src_port_mask,
+                       .dst_port = mask->dst_port_mask,
                };
                attributes->items[2] = (struct rte_flow_item){
                        .type = RTE_FLOW_ITEM_TYPE_TCP,
                        .spec = &attributes->l4,
-                       .mask = &attributes->l4,
-               };
-               break;
-       case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
-               attributes->l3.ipv4.hdr = (struct ipv4_hdr){
-                       .src_addr = input->flow.ip4_flow.src_ip,
-                       .dst_addr = input->flow.ip4_flow.dst_ip,
-                       .time_to_live = input->flow.ip4_flow.ttl,
-                       .type_of_service = input->flow.ip4_flow.tos,
-                       .next_proto_id = input->flow.ip4_flow.proto,
-               };
-               attributes->items[1] = (struct rte_flow_item){
-                       .type = RTE_FLOW_ITEM_TYPE_IPV4,
-                       .spec = &attributes->l3,
-                       .mask = &attributes->l3,
+                       .mask = &attributes->l4_mask,
                };
                break;
        case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
-               attributes->l3.ipv6.hdr = (struct ipv6_hdr){
-                       .hop_limits = input->flow.udp6_flow.ip.hop_limits,
-                       .proto = input->flow.udp6_flow.ip.proto,
-               };
-               memcpy(attributes->l3.ipv6.hdr.src_addr,
-                      input->flow.udp6_flow.ip.src_ip,
-                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
-               memcpy(attributes->l3.ipv6.hdr.dst_addr,
-                      input->flow.udp6_flow.ip.dst_ip,
-                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
                attributes->l4.udp.hdr = (struct udp_hdr){
                        .src_port = input->flow.udp6_flow.src_port,
                        .dst_port = input->flow.udp6_flow.dst_port,
                };
-               attributes->items[1] = (struct rte_flow_item){
-                       .type = RTE_FLOW_ITEM_TYPE_IPV6,
-                       .spec = &attributes->l3,
-                       .mask = &attributes->l3,
+               attributes->l4_mask.udp.hdr = (struct udp_hdr){
+                       .src_port = mask->src_port_mask,
+                       .dst_port = mask->dst_port_mask,
                };
                attributes->items[2] = (struct rte_flow_item){
                        .type = RTE_FLOW_ITEM_TYPE_UDP,
                        .spec = &attributes->l4,
-                       .mask = &attributes->l4,
+                       .mask = &attributes->l4_mask,
                };
                break;
        case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
-               attributes->l3.ipv6.hdr = (struct ipv6_hdr){
-                       .hop_limits = input->flow.tcp6_flow.ip.hop_limits,
-                       .proto = input->flow.tcp6_flow.ip.proto,
-               };
-               memcpy(attributes->l3.ipv6.hdr.src_addr,
-                      input->flow.tcp6_flow.ip.src_ip,
-                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
-               memcpy(attributes->l3.ipv6.hdr.dst_addr,
-                      input->flow.tcp6_flow.ip.dst_ip,
-                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
                attributes->l4.tcp.hdr = (struct tcp_hdr){
                        .src_port = input->flow.tcp6_flow.src_port,
                        .dst_port = input->flow.tcp6_flow.dst_port,
                };
-               attributes->items[1] = (struct rte_flow_item){
-                       .type = RTE_FLOW_ITEM_TYPE_IPV6,
-                       .spec = &attributes->l3,
-                       .mask = &attributes->l3,
+               attributes->l4_mask.tcp.hdr = (struct tcp_hdr){
+                       .src_port = mask->src_port_mask,
+                       .dst_port = mask->dst_port_mask,
                };
                attributes->items[2] = (struct rte_flow_item){
                        .type = RTE_FLOW_ITEM_TYPE_TCP,
                        .spec = &attributes->l4,
-                       .mask = &attributes->l4,
+                       .mask = &attributes->l4_mask,
                };
                break;
+       case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
        case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
-               attributes->l3.ipv6.hdr = (struct ipv6_hdr){
-                       .hop_limits = input->flow.ipv6_flow.hop_limits,
-                       .proto = input->flow.ipv6_flow.proto,
-               };
-               memcpy(attributes->l3.ipv6.hdr.src_addr,
-                      input->flow.ipv6_flow.src_ip,
-                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
-               memcpy(attributes->l3.ipv6.hdr.dst_addr,
-                      input->flow.ipv6_flow.dst_ip,
-                      RTE_DIM(attributes->l3.ipv6.hdr.src_addr));
-               attributes->items[1] = (struct rte_flow_item){
-                       .type = RTE_FLOW_ITEM_TYPE_IPV6,
-                       .spec = &attributes->l3,
-                       .mask = &attributes->l3,
-               };
                break;
        default:
                DRV_LOG(ERR, "port %u invalid flow type%d",