examples/ipsec-secgw: replace strncpy with strlcpy
[dpdk.git] / drivers / net / i40e / i40e_flow.c
index db66883..057e4f9 100644 (file)
@@ -10,6 +10,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 
+#include <rte_debug.h>
 #include <rte_ether.h>
 #include <rte_ethdev_driver.h>
 #include <rte_log.h>
@@ -53,6 +54,7 @@ static int i40e_flow_parse_ethertype_action(struct rte_eth_dev *dev,
                                    struct rte_flow_error *error,
                                    struct rte_eth_ethertype_filter *filter);
 static int i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
+                                       const struct rte_flow_attr *attr,
                                        const struct rte_flow_item *pattern,
                                        struct rte_flow_error *error,
                                        struct i40e_fdir_filter_conf *filter);
@@ -2420,6 +2422,7 @@ i40e_flow_fdir_get_pctype_value(struct i40e_pf *pf,
  */
 static int
 i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
+                            const struct rte_flow_attr *attr,
                             const struct rte_flow_item *pattern,
                             struct rte_flow_error *error,
                             struct i40e_fdir_filter_conf *filter)
@@ -2491,16 +2494,22 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                                      "Invalid MAC_addr mask.");
                                        return -rte_errno;
                                }
+                       }
+                       if (eth_spec && eth_mask && eth_mask->type) {
+                               enum rte_flow_item_type next = (item + 1)->type;
 
-                               if ((eth_mask->type & UINT16_MAX) ==
-                                   UINT16_MAX) {
-                                       input_set |= I40E_INSET_LAST_ETHER_TYPE;
-                                       filter->input.flow.l2_flow.ether_type =
-                                               eth_spec->type;
+                               if (eth_mask->type != RTE_BE16(0xffff)) {
+                                       rte_flow_error_set(error, EINVAL,
+                                                     RTE_FLOW_ERROR_TYPE_ITEM,
+                                                     item,
+                                                     "Invalid type mask.");
+                                       return -rte_errno;
                                }
 
                                ether_type = rte_be_to_cpu_16(eth_spec->type);
-                               if (ether_type == ETHER_TYPE_IPv4 ||
+
+                               if (next == RTE_FLOW_ITEM_TYPE_VLAN ||
+                                   ether_type == ETHER_TYPE_IPv4 ||
                                    ether_type == ETHER_TYPE_IPv6 ||
                                    ether_type == ETHER_TYPE_ARP ||
                                    ether_type == outer_tpid) {
@@ -2510,6 +2519,9 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                                     "Unsupported ether_type.");
                                        return -rte_errno;
                                }
+                               input_set |= I40E_INSET_LAST_ETHER_TYPE;
+                               filter->input.flow.l2_flow.ether_type =
+                                       eth_spec->type;
                        }
 
                        pctype = I40E_FILTER_PCTYPE_L2_PAYLOAD;
@@ -2519,6 +2531,8 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                case RTE_FLOW_ITEM_TYPE_VLAN:
                        vlan_spec = item->spec;
                        vlan_mask = item->mask;
+
+                       RTE_ASSERT(!(input_set & I40E_INSET_LAST_ETHER_TYPE));
                        if (vlan_spec && vlan_mask) {
                                if (vlan_mask->tci ==
                                    rte_cpu_to_be_16(I40E_TCI_MASK)) {
@@ -2527,6 +2541,33 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                                vlan_spec->tci;
                                }
                        }
+                       if (vlan_spec && vlan_mask && vlan_mask->inner_type) {
+                               if (vlan_mask->inner_type != RTE_BE16(0xffff)) {
+                                       rte_flow_error_set(error, EINVAL,
+                                                     RTE_FLOW_ERROR_TYPE_ITEM,
+                                                     item,
+                                                     "Invalid inner_type"
+                                                     " mask.");
+                                       return -rte_errno;
+                               }
+
+                               ether_type =
+                                       rte_be_to_cpu_16(vlan_spec->inner_type);
+
+                               if (ether_type == ETHER_TYPE_IPv4 ||
+                                   ether_type == ETHER_TYPE_IPv6 ||
+                                   ether_type == ETHER_TYPE_ARP ||
+                                   ether_type == outer_tpid) {
+                                       rte_flow_error_set(error, EINVAL,
+                                                    RTE_FLOW_ERROR_TYPE_ITEM,
+                                                    item,
+                                                    "Unsupported inner_type.");
+                                       return -rte_errno;
+                               }
+                               input_set |= I40E_INSET_LAST_ETHER_TYPE;
+                               filter->input.flow.l2_flow.ether_type =
+                                       vlan_spec->inner_type;
+                       }
 
                        pctype = I40E_FILTER_PCTYPE_L2_PAYLOAD;
                        layer_idx = I40E_FLXPLD_L2_IDX;
@@ -2919,6 +2960,16 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                        break;
                case RTE_FLOW_ITEM_TYPE_VF:
                        vf_spec = item->spec;
+                       if (!attr->transfer) {
+                               rte_flow_error_set(error, ENOTSUP,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM,
+                                                  item,
+                                                  "Matching VF traffic"
+                                                  " without affecting it"
+                                                  " (transfer attribute)"
+                                                  " is unsupported");
+                               return -rte_errno;
+                       }
                        filter->input.flow_ext.is_vf = 1;
                        filter->input.flow_ext.dst_id = vf_spec->id;
                        if (filter->input.flow_ext.is_vf &&
@@ -3081,7 +3132,8 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
                &filter->fdir_filter;
        int ret;
 
-       ret = i40e_flow_parse_fdir_pattern(dev, pattern, error, fdir_filter);
+       ret = i40e_flow_parse_fdir_pattern(dev, attr, pattern, error,
+                                          fdir_filter);
        if (ret)
                return ret;
 
@@ -3285,7 +3337,8 @@ i40e_flow_parse_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
                case RTE_FLOW_ITEM_TYPE_VLAN:
                        vlan_spec = item->spec;
                        vlan_mask = item->mask;
-                       if (!(vlan_spec && vlan_mask)) {
+                       if (!(vlan_spec && vlan_mask) ||
+                           vlan_mask->inner_type) {
                                rte_flow_error_set(error, EINVAL,
                                                   RTE_FLOW_ERROR_TYPE_ITEM,
                                                   item,
@@ -3515,7 +3568,8 @@ i40e_flow_parse_nvgre_pattern(__rte_unused struct rte_eth_dev *dev,
                case RTE_FLOW_ITEM_TYPE_VLAN:
                        vlan_spec = item->spec;
                        vlan_mask = item->mask;
-                       if (!(vlan_spec && vlan_mask)) {
+                       if (!(vlan_spec && vlan_mask) ||
+                           vlan_mask->inner_type) {
                                rte_flow_error_set(error, EINVAL,
                                                   RTE_FLOW_ERROR_TYPE_ITEM,
                                                   item,
@@ -4023,7 +4077,8 @@ i40e_flow_parse_qinq_pattern(__rte_unused struct rte_eth_dev *dev,
                        vlan_spec = item->spec;
                        vlan_mask = item->mask;
 
-                       if (!(vlan_spec && vlan_mask)) {
+                       if (!(vlan_spec && vlan_mask) ||
+                           vlan_mask->inner_type) {
                                rte_flow_error_set(error, EINVAL,
                                           RTE_FLOW_ERROR_TYPE_ITEM,
                                           item,