Add support for L2TPv2(include PPP over L2TPv2) protocols FDIR
based on outer MAC src address and L2TPv2 session ID.

Add support for PPPoL2TPv2oUDP protocols FDIR based on inner IP
src/dst address and UDP/TCP src/dst port.

Patterns are listed below:
eth/ipv4(6)/udp/l2tpv2
eth/ipv4(6)/udp/l2tpv2/ppp

eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)
eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)/udp
eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)/tcp

Signed-off-by: Jie Wang <jie1x.w...@intel.com>
---
 doc/guides/rel_notes/release_22_03.rst |   8 +-
 drivers/net/iavf/iavf_fdir.c           | 174 +++++++++++++++++++++----
 drivers/net/iavf/iavf_generic_flow.h   |   4 +
 3 files changed, 156 insertions(+), 30 deletions(-)

diff --git a/doc/guides/rel_notes/release_22_03.rst 
b/doc/guides/rel_notes/release_22_03.rst
index 0d1e4a0b61..5a73ccc14e 100644
--- a/doc/guides/rel_notes/release_22_03.rst
+++ b/doc/guides/rel_notes/release_22_03.rst
@@ -66,8 +66,12 @@ New Features
 
 * **Updated Intel iavf driver.**
 
-  Added L2TPv2(include PPP over L2TPv2) RSS hash distribute packets
-  based on outer MAC src address and L2TPv2 session ID.
+  * Added L2TPv2(include PPP over L2TPv2) RSS hash distribute packets
+    based on outer MAC src address and L2TPv2 session ID.
+  * Added L2TPv2(include PPP over L2TPv2) FDIR distribute packets
+    based on outer MAC src address and L2TPv2 session ID.
+  * Added PPPoL2TPv2oUDP FDIR distribute packets based on inner IP
+    src/dst address and UDP/TCP src/dst port.
 
 
 Removed Items
diff --git a/drivers/net/iavf/iavf_fdir.c b/drivers/net/iavf/iavf_fdir.c
index b63aaca91d..2583b899aa 100644
--- a/drivers/net/iavf/iavf_fdir.c
+++ b/drivers/net/iavf/iavf_fdir.c
@@ -168,6 +168,31 @@
        IAVF_FDIR_INSET_GRE_IPV6 | IAVF_INSET_TUN_UDP_SRC_PORT | \
        IAVF_INSET_TUN_UDP_DST_PORT)
 
+#define IAVF_FDIR_INSET_L2TPV2 (\
+       IAVF_INSET_SMAC | IAVF_INSET_L2TPV2)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV4 (\
+       IAVF_INSET_TUN_IPV4_SRC | IAVF_INSET_TUN_IPV4_DST)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_UDP (\
+       IAVF_FDIR_INSET_L2TPV2_PPP_IPV4 | IAVF_INSET_TUN_UDP_SRC_PORT | \
+       IAVF_INSET_TUN_UDP_DST_PORT)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_TCP (\
+       IAVF_FDIR_INSET_L2TPV2_PPP_IPV4 | IAVF_INSET_TUN_TCP_SRC_PORT | \
+       IAVF_INSET_TUN_TCP_DST_PORT)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV6 (\
+       IAVF_INSET_TUN_IPV6_SRC | IAVF_INSET_TUN_IPV6_DST)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_UDP (\
+       IAVF_FDIR_INSET_L2TPV2_PPP_IPV6 | IAVF_INSET_TUN_UDP_SRC_PORT | \
+       IAVF_INSET_TUN_UDP_DST_PORT)
+
+#define IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_TCP (\
+       IAVF_FDIR_INSET_L2TPV2_PPP_IPV6 | IAVF_INSET_TUN_TCP_SRC_PORT | \
+       IAVF_INSET_TUN_TCP_DST_PORT)
+
 static struct iavf_pattern_match_item iavf_fdir_pattern[] = {
        {iavf_pattern_ethertype,                 IAVF_FDIR_INSET_ETH,           
IAVF_INSET_NONE},
        {iavf_pattern_eth_ipv4,                  IAVF_FDIR_INSET_ETH_IPV4,      
IAVF_INSET_NONE},
@@ -275,6 +300,28 @@ static struct iavf_pattern_match_item iavf_fdir_pattern[] 
= {
        {iavf_pattern_eth_ipv6_gre_ipv6,        IAVF_FDIR_INSET_GRE_IPV6,       
IAVF_INSET_NONE},
        {iavf_pattern_eth_ipv6_gre_ipv6_tcp,    IAVF_FDIR_INSET_GRE_IPV6_TCP,   
IAVF_INSET_NONE},
        {iavf_pattern_eth_ipv6_gre_ipv6_udp,    IAVF_FDIR_INSET_GRE_IPV6_UDP,   
IAVF_INSET_NONE},
+
+       {iavf_pattern_eth_ipv4_udp_l2tpv2,              IAVF_FDIR_INSET_L2TPV2, 
                IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp,          IAVF_FDIR_INSET_L2TPV2, 
                IAVF_INSET_NONE},
+
+       {iavf_pattern_eth_ipv6_udp_l2tpv2,              IAVF_FDIR_INSET_L2TPV2, 
                IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp,          IAVF_FDIR_INSET_L2TPV2, 
                IAVF_INSET_NONE},
+
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4,     
IAVF_FDIR_INSET_L2TPV2_PPP_IPV4,        IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,    IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,    IAVF_INSET_NONE},
+
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4,     
IAVF_FDIR_INSET_L2TPV2_PPP_IPV4,        IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_UDP,    IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV4_TCP,    IAVF_INSET_NONE},
+
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6,     
IAVF_FDIR_INSET_L2TPV2_PPP_IPV6,        IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,    IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,    IAVF_INSET_NONE},
+
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6,     
IAVF_FDIR_INSET_L2TPV2_PPP_IPV6,        IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_UDP,    IAVF_INSET_NONE},
+       {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp, 
IAVF_FDIR_INSET_L2TPV2_PPP_IPV6_TCP,    IAVF_INSET_NONE},
 };
 
 static struct iavf_flow_parser iavf_fdir_parser;
@@ -694,6 +741,8 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter 
*ad,
        const struct rte_flow_item_pfcp *pfcp_spec, *pfcp_mask;
        const struct rte_flow_item_ecpri *ecpri_spec, *ecpri_mask;
        const struct rte_flow_item_gre *gre_spec, *gre_mask;
+       const struct rte_flow_item_l2tpv2 *l2tpv2_spec, *l2tpv2_mask;
+       const struct rte_flow_item_ppp *ppp_spec, *ppp_mask;
        const struct rte_flow_item *item = pattern;
        struct virtchnl_proto_hdr *hdr, *hdr1 = NULL;
        struct rte_ecpri_common_hdr ecpri_common;
@@ -701,7 +750,7 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter 
*ad,
        enum rte_flow_item_type item_type;
        enum rte_flow_item_type next_type;
        uint8_t tun_inner = 0;
-       uint16_t ether_type;
+       uint16_t ether_type, flags_version;
        int layer = 0;
 
        uint8_t  ipv6_addr_mask[16] = {
@@ -739,37 +788,41 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter 
*ad,
                        }
 
                        if (eth_spec && eth_mask) {
-                               if (!rte_is_zero_ether_addr(&eth_mask->src) ||
-                                   !rte_is_zero_ether_addr(&eth_mask->dst)) {
-                                       rte_flow_error_set(error, EINVAL,
-                                               RTE_FLOW_ERROR_TYPE_ITEM, item,
-                                               "Invalid MAC_addr mask.");
-                                       return -rte_errno;
-                               }
-                       }
-
-                       if (eth_spec && eth_mask && eth_mask->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;
+                               if (!rte_is_zero_ether_addr(&eth_mask->dst)) {
+                                       input_set |= IAVF_INSET_DMAC;
+                                       VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1,
+                                                                       ETH,
+                                                                       DST);
+                               } else if 
(!rte_is_zero_ether_addr(&eth_mask->src)) {
+                                       input_set |= IAVF_INSET_SMAC;
+                                       VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1,
+                                                                       ETH,
+                                                                       SRC);
                                }
 
-                               ether_type = rte_be_to_cpu_16(eth_spec->type);
-                               if (ether_type == RTE_ETHER_TYPE_IPV4 ||
-                                       ether_type == RTE_ETHER_TYPE_IPV6) {
-                                       rte_flow_error_set(error, EINVAL,
-                                               RTE_FLOW_ERROR_TYPE_ITEM,
-                                               item,
-                                               "Unsupported ether_type.");
-                                       return -rte_errno;
+                               if (eth_mask->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 == RTE_ETHER_TYPE_IPV4 ||
+                                               ether_type == 
RTE_ETHER_TYPE_IPV6) {
+                                               rte_flow_error_set(error, 
EINVAL,
+                                                       
RTE_FLOW_ERROR_TYPE_ITEM,
+                                                       item,
+                                                       "Unsupported 
ether_type.");
+                                               return -rte_errno;
+                                       }
+
+                                       input_set |= IAVF_INSET_ETHERTYPE;
+                                       VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1, 
ETH,
+                                                                       
ETHERTYPE);
                                }
 
-                               input_set |= IAVF_INSET_ETHERTYPE;
-                               VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr1, ETH,
-                                                                ETHERTYPE);
-
                                rte_memcpy(hdr1->buffer, eth_spec,
                                           sizeof(struct rte_ether_hdr));
                        }
@@ -1319,6 +1372,71 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter 
*ad,
                        hdrs->count = ++layer;
                        break;
 
+               case RTE_FLOW_ITEM_TYPE_L2TPV2:
+                       l2tpv2_spec = item->spec;
+                       l2tpv2_mask = item->mask;
+
+                       hdr = &hdrs->proto_hdr[layer];
+
+                       VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, L2TPV2);
+
+                       if (l2tpv2_spec && l2tpv2_mask) {
+                               flags_version =
+                                       
rte_be_to_cpu_16(l2tpv2_spec->hdr.common.flags_version);
+                               if ((flags_version == 
RTE_L2TPV2_MSG_TYPE_CONTROL &&
+                                    l2tpv2_mask->hdr.type3.session_id == 
UINT16_MAX) ||
+                                   (flags_version == RTE_L2TPV2_MSG_TYPE_DATA 
&&
+                                    l2tpv2_mask->hdr.type7.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_L &&
+                                    l2tpv2_mask->hdr.type6.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_S &&
+                                    l2tpv2_mask->hdr.type5.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_O &&
+                                    l2tpv2_mask->hdr.type4.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_L_S &&
+                                    l2tpv2_mask->hdr.type3.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_L_O &&
+                                    l2tpv2_mask->hdr.type2.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_S_O &&
+                                    l2tpv2_mask->hdr.type1.session_id == 
UINT16_MAX) ||
+                                   (flags_version == 
RTE_L2TPV2_MSG_TYPE_DATA_L_S_O &&
+                                    l2tpv2_mask->hdr.type0.session_id == 
UINT16_MAX)) {
+                                       input_set |= IAVF_L2TPV2_SESSION_ID;
+                                       if (flags_version & 
IAVF_L2TPV2_FLAGS_LEN)
+                                               
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr,
+                                                               L2TPV2,
+                                                               LEN_SESS_ID);
+                                       else
+                                               
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr,
+                                                               L2TPV2,
+                                                               SESS_ID);
+                               }
+
+                               rte_memcpy(hdr->buffer, l2tpv2_spec,
+                                          sizeof(*l2tpv2_spec));
+                       }
+
+                       tun_inner = 1;
+
+                       hdrs->count = ++layer;
+                       break;
+
+               case RTE_FLOW_ITEM_TYPE_PPP:
+                       ppp_spec = item->spec;
+                       ppp_mask = item->mask;
+
+                       hdr = &hdrs->proto_hdr[layer];
+
+                       VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, PPP);
+
+                       if (ppp_spec && ppp_mask) {
+                               rte_memcpy(hdr->buffer, ppp_spec,
+                                          sizeof(*ppp_spec));
+                       }
+
+                       hdrs->count = ++layer;
+                       break;
+
                case RTE_FLOW_ITEM_TYPE_VOID:
                        break;
 
diff --git a/drivers/net/iavf/iavf_generic_flow.h 
b/drivers/net/iavf/iavf_generic_flow.h
index 107bbc1a23..f6af176073 100644
--- a/drivers/net/iavf/iavf_generic_flow.h
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -35,6 +35,7 @@
 #define IAVF_PROT_L2TPV3OIP        (1ULL << 24)
 #define IAVF_PROT_PFCP             (1ULL << 25)
 #define IAVF_PROT_ECPRI                    (1ULL << 26)
+#define IAVF_PROT_L2TPV2           (1ULL << 27)
 
 
 /* field */
@@ -62,6 +63,7 @@
 #define IAVF_PFCP_SEID             (1ULL << 43)
 #define IAVF_ECPRI_PC_RTC_ID       (1ULL << 42)
 #define IAVF_IP_PKID               (1ULL << 41)
+#define IAVF_L2TPV2_SESSION_ID     (1ULL << 40)
 
 /* input set */
 
@@ -175,6 +177,8 @@
        (IAVF_PROT_PFCP | IAVF_PFCP_S_FIELD | IAVF_PFCP_SEID)
 #define IAVF_INSET_ECPRI \
        (IAVF_PROT_ECPRI | IAVF_ECPRI_PC_RTC_ID)
+#define IAVF_INSET_L2TPV2 \
+       (IAVF_PROT_L2TPV2 | IAVF_L2TPV2_SESSION_ID)
 
 /* empty pattern */
 extern enum rte_flow_item_type iavf_pattern_empty[];
-- 
2.25.1

Reply via email to