net/ice/base: fix for RSS hash on inner UDP port
[dpdk.git] / drivers / net / ice / base / ice_flow.c
index dccd7d3..9a35a11 100644 (file)
@@ -19,6 +19,8 @@
 #define ICE_FLOW_FLD_SZ_ICMP_CODE      1
 #define ICE_FLOW_FLD_SZ_ARP_OPER       2
 #define ICE_FLOW_FLD_SZ_GRE_KEYID      4
+#define ICE_FLOW_FLD_SZ_GTP_TEID       4
+#define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID   2
 
 /* Protocol header fields are extracted at the word boundaries as word-sized
  * values. Specify the displacement value of some non-word-aligned fields needed
  * protocol headers. Displacement values are expressed in number of bits.
  */
 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP        (-4)
-#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP        ((-2) * 8)
-#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * 8)
+#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP        ((-2) * BITS_PER_BYTE)
+#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
 
 /* Describe properties of a protocol header field */
 struct ice_flow_field_info {
        enum ice_flow_seg_hdr hdr;
        s16 off;        /* Offset from start of a protocol header, in bits */
        u16 size;       /* Size of fields in bits */
+       u16 mask;       /* 16-bit mask for field */
 };
 
+#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
+       .hdr = _hdr, \
+       .off = (_offset_bytes) * BITS_PER_BYTE, \
+       .size = (_size_bytes) * BITS_PER_BYTE, \
+       .mask = 0, \
+}
+
+#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
+       .hdr = _hdr, \
+       .off = (_offset_bytes) * BITS_PER_BYTE, \
+       .size = (_size_bytes) * BITS_PER_BYTE, \
+       .mask = _mask, \
+}
+
 /* Table containing properties of supported protocol header fields */
 static const
 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
        /* Ether */
        /* ICE_FLOW_FIELD_IDX_ETH_DA */
-       { ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_ETH_SA */
-       { ICE_FLOW_SEG_HDR_ETH, ETH_ALEN * 8, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_S_VLAN */
-       { ICE_FLOW_SEG_HDR_VLAN, 12 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
        /* ICE_FLOW_FIELD_IDX_C_VLAN */
-       { ICE_FLOW_SEG_HDR_VLAN, 14 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
        /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
-       { ICE_FLOW_SEG_HDR_ETH, 12 * 8, ICE_FLOW_FLD_SZ_ETH_TYPE * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
        /* IPv4 */
        /* ICE_FLOW_FIELD_IDX_IP_DSCP */
-       { ICE_FLOW_SEG_HDR_IPV4, 1 * 8, 1 * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
        /* ICE_FLOW_FIELD_IDX_IP_TTL */
-       { ICE_FLOW_SEG_HDR_NONE, 8 * 8, 1 * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
        /* ICE_FLOW_FIELD_IDX_IP_PROT */
-       { ICE_FLOW_SEG_HDR_NONE, 9 * 8, ICE_FLOW_FLD_SZ_IP_PROT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
        /* ICE_FLOW_FIELD_IDX_IPV4_SA */
-       { ICE_FLOW_SEG_HDR_IPV4, 12 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV4_DA */
-       { ICE_FLOW_SEG_HDR_IPV4, 16 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* IPv6 */
        /* ICE_FLOW_FIELD_IDX_IPV6_SA */
-       { ICE_FLOW_SEG_HDR_IPV6, 8 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV6_DA */
-       { ICE_FLOW_SEG_HDR_IPV6, 24 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
        /* Transport */
        /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
-       { ICE_FLOW_SEG_HDR_TCP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
-       { ICE_FLOW_SEG_HDR_TCP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
-       { ICE_FLOW_SEG_HDR_UDP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
-       { ICE_FLOW_SEG_HDR_UDP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
-       { ICE_FLOW_SEG_HDR_SCTP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
-       { ICE_FLOW_SEG_HDR_SCTP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
        /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
-       { ICE_FLOW_SEG_HDR_TCP, 13 * 8, ICE_FLOW_FLD_SZ_TCP_FLAGS * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
        /* ARP */
        /* ICE_FLOW_FIELD_IDX_ARP_SIP */
-       { ICE_FLOW_SEG_HDR_ARP, 14 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_ARP_DIP */
-       { ICE_FLOW_SEG_HDR_ARP, 24 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_ARP_SHA */
-       { ICE_FLOW_SEG_HDR_ARP, 8 * 8, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_ARP_DHA */
-       { ICE_FLOW_SEG_HDR_ARP, 18 * 8, ETH_ALEN * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
        /* ICE_FLOW_FIELD_IDX_ARP_OP */
-       { ICE_FLOW_SEG_HDR_ARP, 6 * 8, ICE_FLOW_FLD_SZ_ARP_OPER * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
        /* ICMP */
        /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
-       { ICE_FLOW_SEG_HDR_ICMP, 0 * 8, ICE_FLOW_FLD_SZ_ICMP_TYPE * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
        /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
-       { ICE_FLOW_SEG_HDR_ICMP, 1 * 8, ICE_FLOW_FLD_SZ_ICMP_CODE * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
        /* GRE */
        /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
-       { ICE_FLOW_SEG_HDR_GRE, 12 * 8, ICE_FLOW_FLD_SZ_GRE_KEYID * 8 },
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
+       /* GTP */
+       /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
+                         ICE_FLOW_FLD_SZ_GTP_TEID),
+       /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
+                         ICE_FLOW_FLD_SZ_GTP_TEID),
+       /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
+                         ICE_FLOW_FLD_SZ_GTP_TEID),
+       /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
+                         ICE_FLOW_FLD_SZ_GTP_TEID),
+       /* PPPOE */
+       /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
+                         ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
 };
 
 /* Bitmaps indicating relevant packet types for a particular protocol header
@@ -189,21 +223,11 @@ static const u32 ice_ptypes_arp_of[] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
 };
 
-/* Packet types for packets with an Outermost/First UDP header */
-static const u32 ice_ptypes_udp_of[] = {
-       0x81000000, 0x00000000, 0x04000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x00000000, 0x00000000,
-};
-
-/* Packet types for packets with an Innermost/Last UDP header */
+/* UDP Packet types for non-tunneled packets or tunneled
+ * packets with inner UDP.
+ */
 static const u32 ice_ptypes_udp_il[] = {
-       0x80000000, 0x20204040, 0x00081010, 0x80810102,
+       0x81000000, 0x20204040, 0x04081010, 0x80810102,
        0x00204040, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -216,7 +240,7 @@ static const u32 ice_ptypes_udp_il[] = {
 /* Packet types for packets with an Innermost/Last TCP header */
 static const u32 ice_ptypes_tcp_il[] = {
        0x04000000, 0x80810102, 0x10204040, 0x42040408,
-       0x00810002, 0x00000000, 0x00000000, 0x00000000,
+       0x00810102, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -285,37 +309,67 @@ static const u32 ice_ptypes_mac_il[] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
 };
 
+/* Packet types for GTPC */
+static const u32 ice_ptypes_gtpc[] = {
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000180, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Packet types for GTPC with TEID */
+static const u32 ice_ptypes_gtpc_tid[] = {
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000060, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+/* Packet types for GTPU */
+static const u32 ice_ptypes_gtpu[] = {
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x7FFFF800, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
 /* Manage parameters and info. used during the creation of a flow profile */
 struct ice_flow_prof_params {
        enum ice_block blk;
-       struct ice_flow_prof *prof;
-
        u16 entry_length; /* # of bytes formatted entry will require */
        u8 es_cnt;
+       struct ice_flow_prof *prof;
+
        /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
         * This will give us the direction flags.
         */
        struct ice_fv_word es[ICE_MAX_FV_WORDS];
-
+       u16 mask[ICE_MAX_FV_WORDS];
        ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
 };
 
-/**
- * ice_is_pow2 - check if integer value is a power of 2
- * @val: unsigned integer to be validated
- */
-static bool ice_is_pow2(u64 val)
-{
-       return (val && !(val & (val - 1)));
-}
-
 #define ICE_FLOW_SEG_HDRS_L2_MASK      \
        (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
 #define ICE_FLOW_SEG_HDRS_L3_MASK      \
-       (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
+       (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
+        ICE_FLOW_SEG_HDR_ARP | ICE_FLOW_SEG_HDR_PPPOE)
 #define ICE_FLOW_SEG_HDRS_L4_MASK      \
        (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
-        ICE_FLOW_SEG_HDR_SCTP)
+        ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC | \
+        ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU_IP | \
+        ICE_FLOW_SEG_HDR_GTPU_UP | ICE_FLOW_SEG_HDR_GTPU_DWN)
 
 /**
  * ice_flow_val_hdrs - validates packet segments for valid protocol headers
@@ -419,9 +473,6 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                const ice_bitmap_t *src;
                u32 hdrs;
 
-               if (i > 0 && (i + 1) < prof->segs_cnt)
-                       continue;
-
                hdrs = prof->segs[i].hdrs;
 
                if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
@@ -429,21 +480,18 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                                (const ice_bitmap_t *)ice_ptypes_mac_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
                }
 
                if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
                        src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
                }
 
                if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
                        ice_and_bitmap(params->ptypes, params->ptypes,
                                       (const ice_bitmap_t *)ice_ptypes_arp_of,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
                }
 
                if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
@@ -451,13 +499,11 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                                (const ice_bitmap_t *)ice_ptypes_ipv4_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
                } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
                        src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
                                (const ice_bitmap_t *)ice_ptypes_ipv6_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
                }
 
                if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
@@ -465,30 +511,42 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                                (const ice_bitmap_t *)ice_ptypes_icmp_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
                } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
-                       src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of :
-                               (const ice_bitmap_t *)ice_ptypes_udp_il;
+                       src = (const ice_bitmap_t *)ice_ptypes_udp_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
                } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
                        ice_and_bitmap(params->ptypes, params->ptypes,
                                       (const ice_bitmap_t *)ice_ptypes_tcp_il,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
                } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
                        src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
                        ice_and_bitmap(params->ptypes, params->ptypes, src,
                                       ICE_FLOW_PTYPE_MAX);
-                       hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
                } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
                        if (!i) {
                                src = (const ice_bitmap_t *)ice_ptypes_gre_of;
                                ice_and_bitmap(params->ptypes, params->ptypes,
                                               src, ICE_FLOW_PTYPE_MAX);
                        }
-                       hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
+               } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
+                       if (!i) {
+                               src = (const ice_bitmap_t *)ice_ptypes_gtpc;
+                               ice_and_bitmap(params->ptypes, params->ptypes,
+                                              src, ICE_FLOW_PTYPE_MAX);
+                       }
+               } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
+                       if (!i) {
+                               src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
+                               ice_and_bitmap(params->ptypes, params->ptypes,
+                                              src, ICE_FLOW_PTYPE_MAX);
+                       }
+               } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
+                       if (!i) {
+                               src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+                               ice_and_bitmap(params->ptypes, params->ptypes,
+                                              src, ICE_FLOW_PTYPE_MAX);
+                       }
                }
        }
 
@@ -552,6 +610,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
        struct ice_flow_fld_info *flds;
        u16 cnt, ese_bits, i;
        s16 adj = 0;
+       u16 mask;
        u16 off;
 
        flds = params->prof->segs[seg].fields;
@@ -611,12 +670,22 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
                break;
        case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
        case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
-               prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
+               prot_id = ICE_PROT_UDP_IL_OR_S;
                break;
        case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
        case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
                prot_id = ICE_PROT_SCTP_IL;
                break;
+       case ICE_FLOW_FIELD_IDX_GTPC_TEID:
+       case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
+       case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
+       case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
+               /* GTP is accessed through UDP OF protocol */
+               prot_id = ICE_PROT_UDP_OF;
+               break;
+       case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
+               prot_id = ICE_PROT_PPPOE;
+               break;
        case ICE_FLOW_FIELD_IDX_ARP_SIP:
        case ICE_FLOW_FIELD_IDX_ARP_DIP:
        case ICE_FLOW_FIELD_IDX_ARP_SHA:
@@ -644,7 +713,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
        /* Each extraction sequence entry is a word in size, and extracts a
         * word-aligned offset from a protocol header.
         */
-       ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
+       ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
 
        flds[fld].xtrct.prot_id = prot_id;
        flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
@@ -660,6 +729,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
 
        /* Fill in the extraction sequence entries needed for this field */
        off = flds[fld].xtrct.off;
+       mask = ice_flds_info[fld].mask;
        for (i = 0; i < cnt; i++) {
                /* Only consume an extraction sequence entry if there is no
                 * sibling field associated with this field or the sibling entry
@@ -684,6 +754,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
 
                        params->es[idx].prot_id = prot_id;
                        params->es[idx].off = off;
+                       params->mask[idx] = mask;
                        params->es_cnt++;
                }
 
@@ -737,15 +808,17 @@ ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
                raw->info.xtrct.prot_id = ICE_PROT_PAY;
                raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
                        ICE_FLOW_FV_EXTRACT_SZ;
-               raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
+               raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
+                       BITS_PER_BYTE;
                raw->info.xtrct.idx = params->es_cnt;
 
                /* Determine the number of field vector entries this raw field
                 * consumes.
                 */
                cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
-                                         (raw->info.src.last * 8),
-                                         ICE_FLOW_FV_EXTRACT_SZ * 8);
+                                         (raw->info.src.last * BITS_PER_BYTE),
+                                         (ICE_FLOW_FV_EXTRACT_SZ *
+                                          BITS_PER_BYTE));
                off = raw->info.xtrct.off;
                for (j = 0; j < cnt; j++) {
                        /* Make sure the number of extraction sequence required
@@ -850,6 +923,7 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
 
 #define ICE_FLOW_FIND_PROF_CHK_FLDS    0x00000001
 #define ICE_FLOW_FIND_PROF_CHK_VSI     0x00000002
+#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
 
 /**
  * ice_flow_find_prof_conds - Find a profile matching headers and conditions
@@ -866,10 +940,12 @@ ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
                         enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
                         u8 segs_cnt, u16 vsi_handle, u32 conds)
 {
-       struct ice_flow_prof *p;
+       struct ice_flow_prof *p, *prof = NULL;
 
+       ice_acquire_lock(&hw->fl_profs_locks[blk]);
        LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
-               if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
+               if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
+                   segs_cnt && segs_cnt == p->segs_cnt) {
                        u8 i;
 
                        /* Check for profile-VSI association if specified */
@@ -888,12 +964,15 @@ ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
                                        break;
 
                        /* A match is found if all segments are matched */
-                       if (i == segs_cnt)
-                               return p;
+                       if (i == segs_cnt) {
+                               prof = p;
+                               break;
+                       }
                }
        }
+       ice_release_lock(&hw->fl_profs_locks[blk]);
 
-       return NULL;
+       return prof;
 }
 
 /**
@@ -910,10 +989,8 @@ ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
 {
        struct ice_flow_prof *p;
 
-       ice_acquire_lock(&hw->fl_profs_locks[blk]);
        p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
                                     ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
-       ice_release_lock(&hw->fl_profs_locks[blk]);
 
        return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
 }
@@ -938,17 +1015,15 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
 }
 
 /**
- * ice_flow_rem_entry_sync - Remove a flow entry
+ * ice_dealloc_flow_entry - Deallocate flow entry memory
  * @hw: pointer to the HW struct
  * @entry: flow entry to be removed
  */
-static enum ice_status
-ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
+static void
+ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
 {
        if (!entry)
-               return ICE_ERR_BAD_PTR;
-
-       LIST_DEL(&entry->l_entry);
+               return;
 
        if (entry->entry)
                ice_free(hw, entry->entry);
@@ -960,6 +1035,22 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
        }
 
        ice_free(hw, entry);
+}
+
+/**
+ * ice_flow_rem_entry_sync - Remove a flow entry
+ * @hw: pointer to the HW struct
+ * @entry: flow entry to be removed
+ */
+static enum ice_status
+ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
+{
+       if (!entry)
+               return ICE_ERR_BAD_PTR;
+
+       LIST_DEL(&entry->l_entry);
+
+       ice_dealloc_flow_entry(hw, entry);
 
        return ICE_SUCCESS;
 }
@@ -1038,7 +1129,8 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
        }
 
        /* Add a HW profile for this flow profile */
-       status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
+       status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
+                                       params.es, params.mask);
        if (status) {
                ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
                goto out;
@@ -1101,6 +1193,34 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
        return status;
 }
 
+/**
+ * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
+ * @hw: pointer to the hardware structure
+ * @blk: classification stage
+ * @vsi_handle: software VSI handle
+ * @vsig: target VSI group
+ *
+ * Assumption: the caller has already verified that the VSI to
+ * be added has the same characteristics as the VSIG and will
+ * thereby have access to all resources added to that VSIG.
+ */
+enum ice_status
+ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
+                       u16 vsig)
+{
+       enum ice_status status;
+
+       if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
+               return ICE_ERR_PARAM;
+
+       ice_acquire_lock(&hw->fl_profs_locks[blk]);
+       status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
+                                 vsig);
+       ice_release_lock(&hw->fl_profs_locks[blk]);
+
+       return status;
+}
+
 /**
  * ice_flow_assoc_prof - associate a VSI with a flow profile
  * @hw: pointer to the hardware structure
@@ -1370,9 +1490,12 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
                goto out;
        }
 
-       ice_acquire_lock(&prof->entries_lock);
-       LIST_ADD(&e->l_entry, &prof->entries);
-       ice_release_lock(&prof->entries_lock);
+       if (blk != ICE_BLK_ACL) {
+               /* ACL will handle the entry management */
+               ice_acquire_lock(&prof->entries_lock);
+               LIST_ADD(&e->l_entry, &prof->entries);
+               ice_release_lock(&prof->entries_lock);
+       }
 
        *entry_h = ICE_FLOW_ENTRY_HNDL(e);
 
@@ -1550,11 +1673,12 @@ ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
 }
 
 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
-       (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
+       (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE)
 
 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
        (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
-        ICE_FLOW_SEG_HDR_SCTP)
+        ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC_TEID)
+
 
 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
        (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
@@ -1651,6 +1775,9 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
        if (!ice_is_vsi_valid(hw, vsi_handle))
                return ICE_ERR_PARAM;
 
+       if (LIST_EMPTY(&hw->fl_profs[blk]))
+               return ICE_SUCCESS;
+
        ice_acquire_lock(&hw->fl_profs_locks[blk]);
        LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
                                 l_entry) {
@@ -1799,7 +1926,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
 
                /* Remove profile if it has no VSIs associated */
                if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
-                       status = ice_flow_rem_prof_sync(hw, blk, prof);
+                       status = ice_flow_rem_prof(hw, blk, prof->id);
                        if (status)
                                goto exit;
                }
@@ -1832,7 +1959,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
         * be removed.
         */
        if (status) {
-               ice_flow_rem_prof_sync(hw, blk, prof);
+               ice_flow_rem_prof(hw, blk, prof->id);
                goto exit;
        }
 
@@ -1916,7 +2043,7 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
        ice_rem_rss_list(hw, vsi_handle, prof);
 
        if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
-               status = ice_flow_rem_prof_sync(hw, blk, prof);
+               status = ice_flow_rem_prof(hw, blk, prof->id);
 
 out:
        ice_free(hw, segs);