net/i40e: support ESP flows
authorBernard Iremonger <bernard.iremonger@intel.com>
Thu, 16 Jan 2020 12:44:54 +0000 (12:44 +0000)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 17 Jan 2020 18:59:18 +0000 (19:59 +0100)
add eth/ipv4/esp and eth/ipv6/esp patterns
add eth/ipv4/udp/esp and eth/ipv6/esp/udp patterns
update i40e_flow_parse_fdir_filter()
add i40e_flow_set_filter_spi()

Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
drivers/net/i40e/i40e_flow.c

index 949ecc8..d877ac2 100644 (file)
@@ -110,8 +110,7 @@ static int i40e_flow_destroy_tunnel_filter(struct i40e_pf *pf,
 static int i40e_flow_flush_fdir_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_ethertype_filter(struct i40e_pf *pf);
 static int i40e_flow_flush_tunnel_filter(struct i40e_pf *pf);
-static int
-i40e_flow_flush_rss_filter(struct rte_eth_dev *dev);
+static int i40e_flow_flush_rss_filter(struct rte_eth_dev *dev);
 static int
 i40e_flow_parse_qinq_filter(struct rte_eth_dev *dev,
                              const struct rte_flow_attr *attr,
@@ -1629,6 +1628,36 @@ static enum rte_flow_item_type pattern_fdir_ipv6_l2tpv3oip[] = {
        RTE_FLOW_ITEM_TYPE_END,
 };
 
+static enum rte_flow_item_type pattern_fdir_ipv4_esp[] = {
+       RTE_FLOW_ITEM_TYPE_ETH,
+       RTE_FLOW_ITEM_TYPE_IPV4,
+       RTE_FLOW_ITEM_TYPE_ESP,
+       RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_esp[] = {
+       RTE_FLOW_ITEM_TYPE_ETH,
+       RTE_FLOW_ITEM_TYPE_IPV6,
+       RTE_FLOW_ITEM_TYPE_ESP,
+       RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv4_udp_esp[] = {
+       RTE_FLOW_ITEM_TYPE_ETH,
+       RTE_FLOW_ITEM_TYPE_IPV4,
+       RTE_FLOW_ITEM_TYPE_UDP,
+       RTE_FLOW_ITEM_TYPE_ESP,
+       RTE_FLOW_ITEM_TYPE_END,
+};
+
+static enum rte_flow_item_type pattern_fdir_ipv6_udp_esp[] = {
+       RTE_FLOW_ITEM_TYPE_ETH,
+       RTE_FLOW_ITEM_TYPE_IPV6,
+       RTE_FLOW_ITEM_TYPE_UDP,
+       RTE_FLOW_ITEM_TYPE_ESP,
+       RTE_FLOW_ITEM_TYPE_END,
+};
+
 static struct i40e_valid_pattern i40e_supported_patterns[] = {
        /* Ethertype */
        { pattern_ethertype, i40e_flow_parse_ethertype_filter },
@@ -1642,6 +1671,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
        { pattern_fdir_ipv4_gtpu, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv4_gtpu_ipv4, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv4_gtpu_ipv6, i40e_flow_parse_fdir_filter },
+       { pattern_fdir_ipv4_esp, i40e_flow_parse_fdir_filter },
+       { pattern_fdir_ipv4_udp_esp, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv6, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv6_udp, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv6_tcp, i40e_flow_parse_fdir_filter },
@@ -1650,6 +1681,8 @@ static struct i40e_valid_pattern i40e_supported_patterns[] = {
        { pattern_fdir_ipv6_gtpu, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv6_gtpu_ipv4, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ipv6_gtpu_ipv6, i40e_flow_parse_fdir_filter },
+       { pattern_fdir_ipv6_esp, i40e_flow_parse_fdir_filter },
+       { pattern_fdir_ipv6_udp_esp, i40e_flow_parse_fdir_filter },
        /* FDIR - support default flow type with flexible payload */
        { pattern_fdir_ethertype_raw_1, i40e_flow_parse_fdir_filter },
        { pattern_fdir_ethertype_raw_2, i40e_flow_parse_fdir_filter },
@@ -2446,6 +2479,28 @@ i40e_flow_fdir_get_pctype_value(struct i40e_pf *pf,
                        cus_pctype = i40e_find_customized_pctype(pf,
                                                I40E_CUSTOMIZED_IPV6_L2TPV3);
                break;
+       case RTE_FLOW_ITEM_TYPE_ESP:
+               if (!filter->input.flow_ext.is_udp) {
+                       if (filter->input.flow_ext.oip_type ==
+                               I40E_FDIR_IPTYPE_IPV4)
+                               cus_pctype = i40e_find_customized_pctype(pf,
+                                               I40E_CUSTOMIZED_ESP_IPV4);
+                       else if (filter->input.flow_ext.oip_type ==
+                               I40E_FDIR_IPTYPE_IPV6)
+                               cus_pctype = i40e_find_customized_pctype(pf,
+                                               I40E_CUSTOMIZED_ESP_IPV6);
+               } else {
+                       if (filter->input.flow_ext.oip_type ==
+                               I40E_FDIR_IPTYPE_IPV4)
+                               cus_pctype = i40e_find_customized_pctype(pf,
+                                               I40E_CUSTOMIZED_ESP_IPV4_UDP);
+                       else if (filter->input.flow_ext.oip_type ==
+                                       I40E_FDIR_IPTYPE_IPV6)
+                               cus_pctype = i40e_find_customized_pctype(pf,
+                                               I40E_CUSTOMIZED_ESP_IPV6_UDP);
+                       filter->input.flow_ext.is_udp = false;
+               }
+               break;
        default:
                PMD_DRV_LOG(ERR, "Unsupported item type");
                break;
@@ -2457,6 +2512,30 @@ i40e_flow_fdir_get_pctype_value(struct i40e_pf *pf,
        return I40E_FILTER_PCTYPE_INVALID;
 }
 
+static void
+i40e_flow_set_filter_spi(struct i40e_fdir_filter_conf *filter,
+       const struct rte_flow_item_esp *esp_spec)
+{
+       if (filter->input.flow_ext.oip_type ==
+               I40E_FDIR_IPTYPE_IPV4) {
+               if (filter->input.flow_ext.is_udp)
+                       filter->input.flow.esp_ipv4_udp_flow.spi =
+                               esp_spec->hdr.spi;
+               else
+                       filter->input.flow.esp_ipv4_flow.spi =
+                               esp_spec->hdr.spi;
+       }
+       if (filter->input.flow_ext.oip_type ==
+               I40E_FDIR_IPTYPE_IPV6) {
+               if (filter->input.flow_ext.is_udp)
+                       filter->input.flow.esp_ipv6_udp_flow.spi =
+                               esp_spec->hdr.spi;
+               else
+                       filter->input.flow.esp_ipv6_flow.spi =
+                               esp_spec->hdr.spi;
+       }
+}
+
 /* 1. Last in item should be NULL as range is not supported.
  * 2. Supported patterns: refer to array i40e_supported_patterns.
  * 3. Default supported flow type and input set: refer to array
@@ -2485,6 +2564,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
        const struct rte_flow_item_udp *udp_spec, *udp_mask;
        const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
        const struct rte_flow_item_gtp *gtp_spec, *gtp_mask;
+       const struct rte_flow_item_esp *esp_spec, *esp_mask;
        const struct rte_flow_item_raw *raw_spec, *raw_mask;
        const struct rte_flow_item_vf *vf_spec;
        const struct rte_flow_item_l2tpv3oip *l2tpv3oip_spec, *l2tpv3oip_mask;
@@ -2681,10 +2761,18 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                        ipv4_spec->hdr.src_addr;
                                filter->input.flow.ip4_flow.dst_ip =
                                        ipv4_spec->hdr.dst_addr;
+
+                               filter->input.flow_ext.inner_ip = false;
+                               filter->input.flow_ext.oip_type =
+                                       I40E_FDIR_IPTYPE_IPV4;
                        } else if (!ipv4_spec && !ipv4_mask && !outer_ip) {
                                filter->input.flow_ext.inner_ip = true;
                                filter->input.flow_ext.iip_type =
                                        I40E_FDIR_IPTYPE_IPV4;
+                       } else if (!ipv4_spec && !ipv4_mask && outer_ip) {
+                               filter->input.flow_ext.inner_ip = false;
+                               filter->input.flow_ext.oip_type =
+                                       I40E_FDIR_IPTYPE_IPV4;
                        } else if ((ipv4_spec || ipv4_mask) && !outer_ip) {
                                rte_flow_error_set(error, EINVAL,
                                                   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2743,6 +2831,10 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                filter->input.flow.ipv6_flow.hop_limits =
                                        ipv6_spec->hdr.hop_limits;
 
+                               filter->input.flow_ext.inner_ip = false;
+                               filter->input.flow_ext.oip_type =
+                                       I40E_FDIR_IPTYPE_IPV6;
+
                                rte_memcpy(filter->input.flow.ipv6_flow.src_ip,
                                           ipv6_spec->hdr.src_addr, 16);
                                rte_memcpy(filter->input.flow.ipv6_flow.dst_ip,
@@ -2756,6 +2848,10 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                filter->input.flow_ext.inner_ip = true;
                                filter->input.flow_ext.iip_type =
                                        I40E_FDIR_IPTYPE_IPV6;
+                       } else if (!ipv6_spec && !ipv6_mask && outer_ip) {
+                               filter->input.flow_ext.inner_ip = false;
+                               filter->input.flow_ext.oip_type =
+                                       I40E_FDIR_IPTYPE_IPV6;
                        } else if ((ipv6_spec || ipv6_mask) && !outer_ip) {
                                rte_flow_error_set(error, EINVAL,
                                                   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2855,7 +2951,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                                udp_spec->hdr.dst_port;
                                }
                        }
-
+                       filter->input.flow_ext.is_udp = true;
                        layer_idx = I40E_FLXPLD_L4_IDX;
 
                        break;
@@ -2890,6 +2986,39 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
                                cus_proto = item_type;
                        }
                        break;
+               case RTE_FLOW_ITEM_TYPE_ESP:
+                       if (!pf->esp_support) {
+                               rte_flow_error_set(error, EINVAL,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM,
+                                                  item,
+                                                  "Unsupported ESP protocol");
+                               return -rte_errno;
+                       }
+
+                       esp_spec = item->spec;
+                       esp_mask = item->mask;
+
+                       if (!esp_spec || !esp_mask) {
+                               rte_flow_error_set(error, EINVAL,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM,
+                                                  item,
+                                                  "Invalid ESP item");
+                               return -rte_errno;
+                       }
+
+                       if (esp_spec && esp_mask) {
+                               if (esp_mask->hdr.spi != UINT32_MAX) {
+                                       rte_flow_error_set(error, EINVAL,
+                                                  RTE_FLOW_ERROR_TYPE_ITEM,
+                                                  item,
+                                                  "Invalid ESP mask");
+                                       return -rte_errno;
+                               }
+                               i40e_flow_set_filter_spi(filter, esp_spec);
+                               filter->input.flow_ext.customized_pctype = true;
+                               cus_proto = item_type;
+                       }
+                       break;
                case RTE_FLOW_ITEM_TYPE_SCTP:
                        sctp_spec = item->spec;
                        sctp_mask = item->mask;