bus/fslmc: support multi VFIO group
[dpdk.git] / drivers / net / ice / ice_generic_flow.c
index e6a2c4b..1c0adc7 100644 (file)
@@ -13,6 +13,7 @@
 #include <rte_ether.h>
 #include <rte_ethdev_driver.h>
 #include <rte_malloc.h>
+#include <rte_tailq.h>
 
 #include "ice_ethdev.h"
 #include "ice_generic_flow.h"
@@ -209,8 +210,7 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
        uint64_t input_set = ICE_INSET_NONE;
-       bool outer_ip = true;
-       bool outer_l4 = true;
+       bool is_tunnel = false;
 
        for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
                if (item->last) {
@@ -239,13 +239,8 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                        ipv4_spec = item->spec;
                        ipv4_mask = item->mask;
 
-                       if (!(ipv4_spec && ipv4_mask)) {
-                               rte_flow_error_set(error, EINVAL,
-                                          RTE_FLOW_ERROR_TYPE_ITEM,
-                                          item,
-                                          "Invalid IPv4 spec or mask.");
-                               return 0;
-                       }
+                       if (!(ipv4_spec && ipv4_mask))
+                               break;
 
                        /* Check IPv4 mask and update input set */
                        if (ipv4_mask->hdr.version_ihl ||
@@ -259,42 +254,36 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                return 0;
                        }
 
-                       if (outer_ip) {
+                       if (is_tunnel) {
                                if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-                                       input_set |= ICE_INSET_IPV4_SRC;
+                                       input_set |= ICE_INSET_TUN_IPV4_SRC;
                                if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-                                       input_set |= ICE_INSET_IPV4_DST;
-                               if (ipv4_mask->hdr.type_of_service == UINT8_MAX)
-                                       input_set |= ICE_INSET_IPV4_TOS;
+                                       input_set |= ICE_INSET_TUN_IPV4_DST;
                                if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
-                                       input_set |= ICE_INSET_IPV4_TTL;
+                                       input_set |= ICE_INSET_TUN_IPV4_TTL;
                                if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
-                                       input_set |= ICE_INSET_IPV4_PROTO;
-                               outer_ip = false;
+                                       input_set |= ICE_INSET_TUN_IPV4_PROTO;
                        } else {
                                if (ipv4_mask->hdr.src_addr == UINT32_MAX)
-                                       input_set |= ICE_INSET_TUN_IPV4_SRC;
+                                       input_set |= ICE_INSET_IPV4_SRC;
                                if (ipv4_mask->hdr.dst_addr == UINT32_MAX)
-                                       input_set |= ICE_INSET_TUN_IPV4_DST;
+                                       input_set |= ICE_INSET_IPV4_DST;
                                if (ipv4_mask->hdr.time_to_live == UINT8_MAX)
-                                       input_set |= ICE_INSET_TUN_IPV4_TTL;
+                                       input_set |= ICE_INSET_IPV4_TTL;
                                if (ipv4_mask->hdr.next_proto_id == UINT8_MAX)
-                                       input_set |= ICE_INSET_TUN_IPV4_PROTO;
+                                       input_set |= ICE_INSET_IPV4_PROTO;
+                               if (ipv4_mask->hdr.type_of_service == UINT8_MAX)
+                                       input_set |= ICE_INSET_IPV4_TOS;
                        }
                        break;
                case RTE_FLOW_ITEM_TYPE_IPV6:
                        ipv6_spec = item->spec;
                        ipv6_mask = item->mask;
 
-                       if (!(ipv6_spec && ipv6_mask)) {
-                               rte_flow_error_set(error, EINVAL,
-                                       RTE_FLOW_ERROR_TYPE_ITEM,
-                                       item, "Invalid IPv6 spec or mask");
-                               return 0;
-                       }
+                       if (!(ipv6_spec && ipv6_mask))
+                               break;
 
-                       if (ipv6_mask->hdr.payload_len ||
-                           ipv6_mask->hdr.vtc_flow) {
+                       if (ipv6_mask->hdr.payload_len) {
                                rte_flow_error_set(error, EINVAL,
                                           RTE_FLOW_ERROR_TYPE_ITEM,
                                           item,
@@ -302,33 +291,37 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                return 0;
                        }
 
-                       if (outer_ip) {
+                       if (is_tunnel) {
                                if (!memcmp(ipv6_mask->hdr.src_addr,
                                            ipv6_addr_mask,
                                            RTE_DIM(ipv6_mask->hdr.src_addr)))
-                                       input_set |= ICE_INSET_IPV6_SRC;
+                                       input_set |= ICE_INSET_TUN_IPV6_SRC;
                                if (!memcmp(ipv6_mask->hdr.dst_addr,
                                            ipv6_addr_mask,
                                            RTE_DIM(ipv6_mask->hdr.dst_addr)))
-                                       input_set |= ICE_INSET_IPV6_DST;
+                                       input_set |= ICE_INSET_TUN_IPV6_DST;
                                if (ipv6_mask->hdr.proto == UINT8_MAX)
-                                       input_set |= ICE_INSET_IPV6_PROTO;
+                                       input_set |= ICE_INSET_TUN_IPV6_PROTO;
                                if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
-                                       input_set |= ICE_INSET_IPV6_HOP_LIMIT;
-                               outer_ip = false;
+                                       input_set |= ICE_INSET_TUN_IPV6_TTL;
                        } else {
                                if (!memcmp(ipv6_mask->hdr.src_addr,
                                            ipv6_addr_mask,
                                            RTE_DIM(ipv6_mask->hdr.src_addr)))
-                                       input_set |= ICE_INSET_TUN_IPV6_SRC;
+                                       input_set |= ICE_INSET_IPV6_SRC;
                                if (!memcmp(ipv6_mask->hdr.dst_addr,
                                            ipv6_addr_mask,
                                            RTE_DIM(ipv6_mask->hdr.dst_addr)))
-                                       input_set |= ICE_INSET_TUN_IPV6_DST;
+                                       input_set |= ICE_INSET_IPV6_DST;
                                if (ipv6_mask->hdr.proto == UINT8_MAX)
-                                       input_set |= ICE_INSET_TUN_IPV6_PROTO;
+                                       input_set |= ICE_INSET_IPV6_PROTO;
                                if (ipv6_mask->hdr.hop_limits == UINT8_MAX)
-                                       input_set |= ICE_INSET_TUN_IPV6_TTL;
+                                       input_set |= ICE_INSET_IPV6_HOP_LIMIT;
+                               if ((ipv6_mask->hdr.vtc_flow &
+                                       rte_cpu_to_be_32(RTE_IPV6_HDR_TC_MASK))
+                                               == rte_cpu_to_be_32
+                                               (RTE_IPV6_HDR_TC_MASK))
+                                       input_set |= ICE_INSET_IPV6_TOS;
                        }
 
                        break;
@@ -336,12 +329,8 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                        udp_spec = item->spec;
                        udp_mask = item->mask;
 
-                       if (!(udp_spec && udp_mask)) {
-                               rte_flow_error_set(error, EINVAL,
-                                                  RTE_FLOW_ERROR_TYPE_ITEM,
-                                                  item, "Invalid UDP mask");
-                               return 0;
-                       }
+                       if (!(udp_spec && udp_mask))
+                               break;
 
                        /* Check UDP mask and update input set*/
                        if (udp_mask->hdr.dgram_len ||
@@ -353,17 +342,16 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                return 0;
                        }
 
-                       if (outer_l4) {
+                       if (is_tunnel) {
                                if (udp_mask->hdr.src_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_SRC_PORT;
+                                       input_set |= ICE_INSET_TUN_SRC_PORT;
                                if (udp_mask->hdr.dst_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_DST_PORT;
-                               outer_l4 = false;
+                                       input_set |= ICE_INSET_TUN_DST_PORT;
                        } else {
                                if (udp_mask->hdr.src_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_TUN_SRC_PORT;
+                                       input_set |= ICE_INSET_SRC_PORT;
                                if (udp_mask->hdr.dst_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_TUN_DST_PORT;
+                                       input_set |= ICE_INSET_DST_PORT;
                        }
 
                        break;
@@ -371,12 +359,8 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                        tcp_spec = item->spec;
                        tcp_mask = item->mask;
 
-                       if (!(tcp_spec && tcp_mask)) {
-                               rte_flow_error_set(error, EINVAL,
-                                                  RTE_FLOW_ERROR_TYPE_ITEM,
-                                                  item, "Invalid TCP mask");
-                               return 0;
-                       }
+                       if (!(tcp_spec && tcp_mask))
+                               break;
 
                        /* Check TCP mask and update input set */
                        if (tcp_mask->hdr.sent_seq ||
@@ -393,17 +377,16 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                return 0;
                        }
 
-                       if (outer_l4) {
+                       if (is_tunnel) {
                                if (tcp_mask->hdr.src_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_SRC_PORT;
+                                       input_set |= ICE_INSET_TUN_SRC_PORT;
                                if (tcp_mask->hdr.dst_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_DST_PORT;
-                               outer_l4 = false;
+                                       input_set |= ICE_INSET_TUN_DST_PORT;
                        } else {
                                if (tcp_mask->hdr.src_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_TUN_SRC_PORT;
+                                       input_set |= ICE_INSET_SRC_PORT;
                                if (tcp_mask->hdr.dst_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_TUN_DST_PORT;
+                                       input_set |= ICE_INSET_DST_PORT;
                        }
 
                        break;
@@ -411,12 +394,8 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                        sctp_spec = item->spec;
                        sctp_mask = item->mask;
 
-                       if (!(sctp_spec && sctp_mask)) {
-                               rte_flow_error_set(error, EINVAL,
-                                                  RTE_FLOW_ERROR_TYPE_ITEM,
-                                                  item, "Invalid SCTP mask");
-                               return 0;
-                       }
+                       if (!(sctp_spec && sctp_mask))
+                               break;
 
                        /* Check SCTP mask and update input set */
                        if (sctp_mask->hdr.cksum) {
@@ -427,17 +406,16 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                return 0;
                        }
 
-                       if (outer_l4) {
+                       if (is_tunnel) {
                                if (sctp_mask->hdr.src_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_SRC_PORT;
+                                       input_set |= ICE_INSET_TUN_SRC_PORT;
                                if (sctp_mask->hdr.dst_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_DST_PORT;
-                               outer_l4 = false;
+                                       input_set |= ICE_INSET_TUN_DST_PORT;
                        } else {
                                if (sctp_mask->hdr.src_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_TUN_SRC_PORT;
+                                       input_set |= ICE_INSET_SRC_PORT;
                                if (sctp_mask->hdr.dst_port == UINT16_MAX)
-                                       input_set |= ICE_INSET_TUN_DST_PORT;
+                                       input_set |= ICE_INSET_DST_PORT;
                        }
 
                        break;
@@ -486,12 +464,17 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                           "Invalid VXLAN item");
                                return 0;
                        }
+                       if (vxlan_mask && vxlan_mask->vni[0] == UINT8_MAX &&
+                                       vxlan_mask->vni[1] == UINT8_MAX &&
+                                       vxlan_mask->vni[2] == UINT8_MAX)
+                               input_set |= ICE_INSET_TUN_ID;
+                       is_tunnel = 1;
 
                        break;
                case RTE_FLOW_ITEM_TYPE_NVGRE:
                        nvgre_spec = item->spec;
                        nvgre_mask = item->mask;
-                       /* Check if VXLAN item is used to describe protocol.
+                       /* Check if NVGRE item is used to describe protocol.
                         * If yes, both spec and mask should be NULL.
                         * If no, both spec and mask shouldn't be NULL.
                         */
@@ -503,13 +486,20 @@ static uint64_t ice_get_flow_field(const struct rte_flow_item pattern[],
                                           "Invalid NVGRE item");
                                return 0;
                        }
+                       if (nvgre_mask && nvgre_mask->tni[0] == UINT8_MAX &&
+                                       nvgre_mask->tni[1] == UINT8_MAX &&
+                                       nvgre_mask->tni[2] == UINT8_MAX)
+                               input_set |= ICE_INSET_TUN_ID;
+                       is_tunnel = 1;
 
+                       break;
+               case RTE_FLOW_ITEM_TYPE_VOID:
                        break;
                default:
                        rte_flow_error_set(error, EINVAL,
                                           RTE_FLOW_ERROR_TYPE_ITEM,
                                           item,
-                                          "Invalid mask no exist");
+                                          "Invalid pattern");
                        break;
                }
        }
@@ -540,28 +530,31 @@ static int ice_flow_valid_action(struct rte_eth_dev *dev,
 {
        const struct rte_flow_action_queue *act_q;
        uint16_t queue;
-
-       switch (actions->type) {
-       case RTE_FLOW_ACTION_TYPE_QUEUE:
-               act_q = actions->conf;
-               queue = act_q->index;
-               if (queue >= dev->data->nb_rx_queues) {
+       const struct rte_flow_action *action;
+       for (action = actions; action->type !=
+                       RTE_FLOW_ACTION_TYPE_END; action++) {
+               switch (action->type) {
+               case RTE_FLOW_ACTION_TYPE_QUEUE:
+                       act_q = action->conf;
+                       queue = act_q->index;
+                       if (queue >= dev->data->nb_rx_queues) {
+                               rte_flow_error_set(error, EINVAL,
+                                               RTE_FLOW_ERROR_TYPE_ACTION,
+                                               actions, "Invalid queue ID for"
+                                               " switch filter.");
+                               return -rte_errno;
+                       }
+                       break;
+               case RTE_FLOW_ACTION_TYPE_DROP:
+               case RTE_FLOW_ACTION_TYPE_VOID:
+                       break;
+               default:
                        rte_flow_error_set(error, EINVAL,
-                                          RTE_FLOW_ERROR_TYPE_ACTION,
-                                          actions, "Invalid queue ID for"
-                                          " switch filter.");
+                                          RTE_FLOW_ERROR_TYPE_ACTION, actions,
+                                          "Invalid action.");
                        return -rte_errno;
                }
-               break;
-       case RTE_FLOW_ACTION_TYPE_DROP:
-               break;
-       default:
-               rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_ACTION, actions,
-                                  "Invalid action.");
-               return -rte_errno;
        }
-
        return 0;
 }
 
@@ -680,9 +673,10 @@ ice_flow_flush(struct rte_eth_dev *dev,
 {
        struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
        struct rte_flow *p_flow;
+       void *temp;
        int ret = 0;
 
-       TAILQ_FOREACH(p_flow, &pf->flow_list, node) {
+       TAILQ_FOREACH_SAFE(p_flow, &pf->flow_list, node, temp) {
                ret = ice_flow_destroy(dev, p_flow, error);
                if (ret) {
                        rte_flow_error_set(error, -ret,