net/ice/base: add dedicate MAC type for E810
[dpdk.git] / drivers / net / ice / base / ice_flow.c
index d919225..17fd242 100644 (file)
 #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_GTP_QFI                2
 #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
- * to compute the offset of words containing the fields in the corresponding
- * 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) * 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;
@@ -67,18 +59,29 @@ struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
        /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
        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_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
-       /* ICE_FLOW_FIELD_IDX_IP_TTL */
-       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
-       /* ICE_FLOW_FIELD_IDX_IP_PROT */
-       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
+       /* IPv4 / IPv6 */
+       /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
+                             0x00fc),
+       /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
+                             0x0ff0),
+       /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
+                             ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
+       /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
+                             ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
+       /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
+                             ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
+       /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
+                             ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
        /* ICE_FLOW_FIELD_IDX_IPV4_SA */
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV4_DA */
        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_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
        /* ICE_FLOW_FIELD_IDX_IPV6_DA */
@@ -124,6 +127,12 @@ struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
        /* 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_EH_TEID */
+       ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12,
+                         ICE_FLOW_FLD_SZ_GTP_TEID),
+       /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
+       ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22,
+                             ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
        /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
        ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
                          ICE_FLOW_FLD_SZ_GTP_TEID),
@@ -141,9 +150,9 @@ struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
  * Packet types for packets with an Outer/First/Single MAC header
  */
 static const u32 ice_ptypes_mac_ofos[] = {
-       0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
-       0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
-       0x000B0F0F, 0x00003000, 0x00000000, 0x00000000,
+       0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
+       0x0000077E, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -165,9 +174,9 @@ static const u32 ice_ptypes_macvlan_il[] = {
 
 /* Packet types for packets with an Outer/First/Single IPv4 header */
 static const u32 ice_ptypes_ipv4_ofos[] = {
-       0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
+       0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x0003000F, 0x000FC000, 0x00000000, 0x00000000,
+       0x0003000F, 0x000FC000, 0x03E0F800, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -177,9 +186,9 @@ static const u32 ice_ptypes_ipv4_ofos[] = {
 
 /* Packet types for packets with an Innermost/Last IPv4 header */
 static const u32 ice_ptypes_ipv4_il[] = {
-       0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
-       0x0007700E, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x000FF800, 0x00000000,
+       0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
+       0x0000000E, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x001FF800, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -189,9 +198,9 @@ static const u32 ice_ptypes_ipv4_il[] = {
 
 /* Packet types for packets with an Outer/First/Single IPv6 header */
 static const u32 ice_ptypes_ipv6_ofos[] = {
-       0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
-       0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
-       0x00080F00, 0x03F00000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x77000000, 0x10002000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -201,8 +210,8 @@ static const u32 ice_ptypes_ipv6_ofos[] = {
 
 /* Packet types for packets with an Innermost/Last IPv6 header */
 static const u32 ice_ptypes_ipv6_il[] = {
-       0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
-       0x03B80770, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
+       0x00000770, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -227,8 +236,8 @@ static const u32 ice_ptypes_arp_of[] = {
  * packets with inner UDP.
  */
 static const u32 ice_ptypes_udp_il[] = {
-       0x81000000, 0x20204040, 0x04081010, 0x80810102,
-       0x00204040, 0x00000000, 0x00000000, 0x00000000,
+       0x81000000, 0x20204040, 0x04000010, 0x80810102,
+       0x00000040, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00410000, 0x10842000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -239,8 +248,8 @@ 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,
-       0x00810102, 0x00000000, 0x00000000, 0x00000000,
+       0x04000000, 0x80810102, 0x10000040, 0x02040408,
+       0x00000102, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00820000, 0x21084000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -251,8 +260,8 @@ static const u32 ice_ptypes_tcp_il[] = {
 
 /* Packet types for packets with an Innermost/Last SCTP header */
 static const u32 ice_ptypes_sctp_il[] = {
-       0x08000000, 0x01020204, 0x20408081, 0x04080810,
-       0x01020204, 0x00000000, 0x00000000, 0x00000000,
+       0x08000000, 0x01020204, 0x20000081, 0x04080810,
+       0x00000204, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x01040000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -275,8 +284,8 @@ static const u32 ice_ptypes_icmp_of[] = {
 
 /* Packet types for packets with an Innermost/Last ICMP header */
 static const u32 ice_ptypes_icmp_il[] = {
-       0x00000000, 0x02040408, 0x40810102, 0x08101020,
-       0x02040408, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x02040408, 0x40000102, 0x08101020,
+       0x00000408, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x42108000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -287,8 +296,8 @@ static const u32 ice_ptypes_icmp_il[] = {
 
 /* Packet types for packets with an Outermost/First GRE header */
 static const u32 ice_ptypes_gre_of[] = {
-       0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
-       0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
+       0x0000017E, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -299,8 +308,8 @@ static const u32 ice_ptypes_gre_of[] = {
 
 /* Packet types for packets with an Innermost/Last MAC header */
 static const u32 ice_ptypes_mac_il[] = {
-       0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
-       0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -334,10 +343,79 @@ static const u32 ice_ptypes_gtpc_tid[] = {
 };
 
 /* Packet types for GTPU */
+static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
+       { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_PDU_EH },
+       { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_PDU_EH },
+};
+
+static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
+       { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_DOWNLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_DOWNLINK },
+};
+
+static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
+       { ICE_MAC_IPV4_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV4_ICMP,    ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_FRAG,    ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_PAY,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_TCP,     ICE_PTYPE_ATTR_GTP_UPLINK },
+       { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6,  ICE_PTYPE_ATTR_GTP_UPLINK },
+};
+
 static const u32 ice_ptypes_gtpu[] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x00000000, 0x00000000, 0x7FFFF800, 0x00000000,
+       0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -368,6 +446,10 @@ struct ice_flow_prof_params {
         * This will give us the direction flags.
         */
        struct ice_fv_word es[ICE_MAX_FV_WORDS];
+       /* attributes can be used to add attributes to a particular PTYPE */
+       const struct ice_ptype_attributes *attr;
+       u16 attr_cnt;
+
        u16 mask[ICE_MAX_FV_WORDS];
        ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
 };
@@ -543,23 +625,42 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
                                               src, ICE_FLOW_PTYPE_MAX);
                        }
                } 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);
-                       }
+                       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);
-                       }
+                       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_DWN) {
+                       src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+                       ice_and_bitmap(params->ptypes, params->ptypes,
+                                      src, ICE_FLOW_PTYPE_MAX);
+
+                       /* Attributes for GTP packet with downlink */
+                       params->attr = ice_attr_gtpu_down;
+                       params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
+               } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
+                       src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+                       ice_and_bitmap(params->ptypes, params->ptypes,
+                                      src, ICE_FLOW_PTYPE_MAX);
+
+                       /* Attributes for GTP packet with uplink */
+                       params->attr = ice_attr_gtpu_up;
+                       params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
+               } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
+                       src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+                       ice_and_bitmap(params->ptypes, params->ptypes,
+                                      src, ICE_FLOW_PTYPE_MAX);
+
+                       /* Attributes for GTP packet with Extension Header */
+                       params->attr = ice_attr_gtpu_eh;
+                       params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
+               } else if ((hdrs & ICE_FLOW_SEG_HDR_GTPU) ==
+                          ICE_FLOW_SEG_HDR_GTPU) {
+                       src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+                       ice_and_bitmap(params->ptypes, params->ptypes,
+                                      src, ICE_FLOW_PTYPE_MAX);
                }
        }
 
@@ -608,6 +709,7 @@ ice_flow_xtract_pkt_flags(struct ice_hw *hw,
  * @params: information about the flow to be processed
  * @seg: packet segment index of the field to be extracted
  * @fld: ID of field to be extracted
+ * @match: bitfield of all fields
  *
  * This function determines the protocol ID, offset, and size of the given
  * field. It then allocates one or more extraction sequence entries for the
@@ -615,13 +717,14 @@ ice_flow_xtract_pkt_flags(struct ice_hw *hw,
  */
 static enum ice_status
 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
-                   u8 seg, enum ice_flow_field fld)
+                   u8 seg, enum ice_flow_field fld, u64 match)
 {
        enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
        enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
        u8 fv_words = hw->blk[params->blk].es.fvw;
        struct ice_flow_fld_info *flds;
        u16 cnt, ese_bits, i;
+       u16 sib_mask = 0;
        s16 adj = 0;
        u16 mask;
        u16 off;
@@ -638,35 +741,49 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
        case ICE_FLOW_FIELD_IDX_ETH_TYPE:
                prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
                break;
-       case ICE_FLOW_FIELD_IDX_IP_DSCP:
-               if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
-                       adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
-               /* Fall through */
-       case ICE_FLOW_FIELD_IDX_IP_TTL:
-       case ICE_FLOW_FIELD_IDX_IP_PROT:
-               /* Some fields are located at different offsets in IPv4 and
-                * IPv6
+       case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
+               prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
+               break;
+       case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
+               prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
+               break;
+       case ICE_FLOW_FIELD_IDX_IPV4_TTL:
+       case ICE_FLOW_FIELD_IDX_IPV4_PROT:
+               prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
+
+               /* TTL and PROT share the same extraction seq. entry.
+                * Each is considered a sibling to the other in terms of sharing
+                * the same extraction sequence entry.
+                */
+               if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
+                       sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
+               else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
+                       sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
+
+               /* If the sibling field is also included, that field's
+                * mask needs to be included.
+                */
+               if (match & BIT(sib))
+                       sib_mask = ice_flds_info[sib].mask;
+               break;
+       case ICE_FLOW_FIELD_IDX_IPV6_TTL:
+       case ICE_FLOW_FIELD_IDX_IPV6_PROT:
+               prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
+
+               /* TTL and PROT share the same extraction seq. entry.
+                * Each is considered a sibling to the other in terms of sharing
+                * the same extraction sequence entry.
                 */
-               if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
-                       prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
-                               ICE_PROT_IPV4_IL;
-                       /* TTL and PROT share the same extraction seq. entry.
-                        * Each is considered a sibling to the other in term
-                        * sharing the same extraction sequence entry.
-                        */
-                       if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
-                               sib = ICE_FLOW_FIELD_IDX_IP_PROT;
-                       else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
-                               sib = ICE_FLOW_FIELD_IDX_IP_TTL;
-               } else if (params->prof->segs[seg].hdrs &
-                          ICE_FLOW_SEG_HDR_IPV6) {
-                       prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
-                               ICE_PROT_IPV6_IL;
-                       if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
-                               adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
-                       else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
-                               adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
-               }
+               if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
+                       sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
+               else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
+                       sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
+
+               /* If the sibling field is also included, that field's
+                * mask needs to be included.
+                */
+               if (match & BIT(sib))
+                       sib_mask = ice_flds_info[sib].mask;
                break;
        case ICE_FLOW_FIELD_IDX_IPV4_SA:
        case ICE_FLOW_FIELD_IDX_IPV4_DA:
@@ -693,6 +810,8 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
        case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
        case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
        case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
+       case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
+       case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
                /* GTP is accessed through UDP OF protocol */
                prot_id = ICE_PROT_UDP_OF;
                break;
@@ -733,6 +852,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
                ICE_FLOW_FV_EXTRACT_SZ;
        flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
        flds[fld].xtrct.idx = params->es_cnt;
+       flds[fld].xtrct.mask = ice_flds_info[fld].mask;
 
        /* Adjust the next field-entry index after accommodating the number of
         * entries this field consumes
@@ -742,7 +862,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;
+       mask = flds[fld].xtrct.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
@@ -767,7 +887,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->mask[idx] = mask | sib_mask;
                        params->es_cnt++;
                }
 
@@ -787,6 +907,7 @@ static enum ice_status
 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
                     u8 seg)
 {
+       u16 fv_words;
        u16 hdrs_sz;
        u8 i;
 
@@ -802,26 +923,19 @@ ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
        if (!hdrs_sz)
                return ICE_ERR_PARAM;
 
+       fv_words = hw->blk[params->blk].es.fvw;
+
        for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
                struct ice_flow_seg_fld_raw *raw;
                u16 off, cnt, j;
 
                raw = &params->prof->segs[seg].raws[i];
 
-               /* Only support matching raw fields in the payload */
-               if (raw->off < hdrs_sz)
-                       return ICE_ERR_PARAM;
-
-               /* Convert the segment-relative offset into payload-relative
-                * offset.
-                */
-               off = raw->off - hdrs_sz;
-
                /* Storing extraction information */
-               raw->info.xtrct.prot_id = ICE_PROT_PAY;
-               raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
+               raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
+               raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
                        ICE_FLOW_FV_EXTRACT_SZ;
-               raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
+               raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
                        BITS_PER_BYTE;
                raw->info.xtrct.idx = params->es_cnt;
 
@@ -834,6 +948,8 @@ ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
                                           BITS_PER_BYTE));
                off = raw->info.xtrct.off;
                for (j = 0; j < cnt; j++) {
+                       u16 idx;
+
                        /* Make sure the number of extraction sequence required
                         * does not exceed the block's capability
                         */
@@ -841,8 +957,14 @@ ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
                            params->es_cnt >= ICE_MAX_FV_WORDS)
                                return ICE_ERR_MAX_LIMIT;
 
-                       params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
-                       params->es[params->es_cnt].off = off;
+                       /* some blocks require a reversed field vector layout */
+                       if (hw->blk[params->blk].es.reverse)
+                               idx = fv_words - params->es_cnt - 1;
+                       else
+                               idx = params->es_cnt;
+
+                       params->es[idx].prot_id = raw->info.xtrct.prot_id;
+                       params->es[idx].off = off;
                        params->es_cnt++;
                        off += ICE_FLOW_FV_EXTRACT_SZ;
                }
@@ -878,14 +1000,14 @@ ice_flow_create_xtrct_seq(struct ice_hw *hw,
 
        for (i = 0; i < params->prof->segs_cnt; i++) {
                u64 match = params->prof->segs[i].match;
-               u16 j;
+               enum ice_flow_field j;
 
                for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
                        const u64 bit = BIT_ULL(j);
 
                        if (match & bit) {
-                               status = ice_flow_xtract_fld
-                                       (hw, params, i, (enum ice_flow_field)j);
+                               status = ice_flow_xtract_fld(hw, params, i, j,
+                                                            match);
                                if (status)
                                        return status;
                                match &= ~bit;
@@ -1093,7 +1215,7 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
                       struct ice_flow_prof **prof)
 {
        struct ice_flow_prof_params params;
-       enum ice_status status = ICE_SUCCESS;
+       enum ice_status status;
        u8 i;
 
        if (!prof || (acts_cnt && !acts))
@@ -1145,8 +1267,9 @@ 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_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
-                                       params.es, params.mask);
+       status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes,
+                             params.attr, params.attr_cnt, params.es,
+                             params.mask);
        if (status) {
                ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
                goto out;
@@ -1178,7 +1301,7 @@ static enum ice_status
 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
                       struct ice_flow_prof *prof)
 {
-       enum ice_status status = ICE_SUCCESS;
+       enum ice_status status;
 
        /* Remove all remaining flow entries before removing the flow profile */
        if (!LIST_EMPTY(&prof->entries)) {
@@ -1555,7 +1678,7 @@ enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
  * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
  * @seg: packet segment the field being set belongs to
  * @fld: field to be set
- * @type: type of the field
+ * @field_type: type of the field
  * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
  *           entry's input buffer
  * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
@@ -1576,16 +1699,16 @@ enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
  */
 static void
 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
-                    enum ice_flow_fld_match_type type, u16 val_loc,
+                    enum ice_flow_fld_match_type field_type, u16 val_loc,
                     u16 mask_loc, u16 last_loc)
 {
        u64 bit = BIT_ULL(fld);
 
        seg->match |= bit;
-       if (type == ICE_FLOW_FLD_TYPE_RANGE)
+       if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
                seg->range |= bit;
 
-       seg->fields[fld].type = type;
+       seg->fields[fld].type = field_type;
        seg->fields[fld].src.val = val_loc;
        seg->fields[fld].src.mask = mask_loc;
        seg->fields[fld].src.last = last_loc;
@@ -1765,14 +1888,11 @@ void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
        ice_acquire_lock(&hw->rss_locks);
        LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
                                 ice_rss_cfg, l_entry) {
-               if (ice_is_bit_set(r->vsis, vsi_handle)) {
-                       ice_clear_bit(vsi_handle, r->vsis);
-
+               if (ice_test_and_clear_bit(vsi_handle, r->vsis))
                        if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
                                LIST_DEL(&r->l_entry);
                                ice_free(hw, r);
                        }
-               }
        }
        ice_release_lock(&hw->rss_locks);
 }
@@ -1876,6 +1996,7 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
 
        rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
        rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
+       rss_cfg->symm = prof->cfg.symm;
        ice_set_bit(vsi_handle, rss_cfg->vsis);
 
        LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
@@ -1903,6 +2024,107 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
              (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
              ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
 
+static void
+ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
+{
+       u32 s = ((src % 4) << 3); /* byte shift */
+       u32 v = dst | 0x80; /* value to program */
+       u8 i = src / 4; /* register index */
+       u32 reg;
+
+       reg = rd32(hw, GLQF_HSYMM(prof_id, i));
+       reg = (reg & ~(0xff << s)) | (v << s);
+       wr32(hw, GLQF_HSYMM(prof_id, i), reg);
+}
+
+static void
+ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
+{
+       int fv_last_word =
+               ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               ice_rss_config_xor_word(hw, prof_id,
+                                       /* Yes, field vector in GLQF_HSYMM and
+                                        * GLQF_HINSET is inversed!
+                                        */
+                                       fv_last_word - (src + i),
+                                       fv_last_word - (dst + i));
+               ice_rss_config_xor_word(hw, prof_id,
+                                       fv_last_word - (dst + i),
+                                       fv_last_word - (src + i));
+       }
+}
+
+static void
+ice_rss_update_symm(struct ice_hw *hw,
+                   struct ice_flow_prof *prof)
+{
+       struct ice_prof_map *map;
+       u8 prof_id, m;
+
+       map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
+       prof_id = map->prof_id;
+
+       /* clear to default */
+       for (m = 0; m < 6; m++)
+               wr32(hw, GLQF_HSYMM(prof_id, m), 0);
+       if (prof->cfg.symm) {
+               struct ice_flow_seg_info *seg =
+                       &prof->segs[prof->segs_cnt - 1];
+
+               struct ice_flow_seg_xtrct *ipv4_src =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
+               struct ice_flow_seg_xtrct *ipv4_dst =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
+               struct ice_flow_seg_xtrct *ipv6_src =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
+               struct ice_flow_seg_xtrct *ipv6_dst =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
+
+               struct ice_flow_seg_xtrct *tcp_src =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
+               struct ice_flow_seg_xtrct *tcp_dst =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
+
+               struct ice_flow_seg_xtrct *udp_src =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
+               struct ice_flow_seg_xtrct *udp_dst =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
+
+               struct ice_flow_seg_xtrct *sctp_src =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
+               struct ice_flow_seg_xtrct *sctp_dst =
+                       &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
+
+               /* xor IPv4 */
+               if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
+                       ice_rss_config_xor(hw, prof_id,
+                                          ipv4_src->idx, ipv4_dst->idx, 2);
+
+               /* xor IPv6 */
+               if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
+                       ice_rss_config_xor(hw, prof_id,
+                                          ipv6_src->idx, ipv6_dst->idx, 8);
+
+               /* xor TCP */
+               if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
+                       ice_rss_config_xor(hw, prof_id,
+                                          tcp_src->idx, tcp_dst->idx, 1);
+
+               /* xor UDP */
+               if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
+                       ice_rss_config_xor(hw, prof_id,
+                                          udp_src->idx, udp_dst->idx, 1);
+
+               /* xor SCTP */
+               if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
+                       ice_rss_config_xor(hw, prof_id,
+                                          sctp_src->idx, sctp_dst->idx, 1);
+       }
+}
+
 /**
  * ice_add_rss_cfg_sync - add an RSS configuration
  * @hw: pointer to the hardware structure
@@ -1910,17 +2132,18 @@ ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
  * @addl_hdrs: protocol header fields
  * @segs_cnt: packet segment count
+ * @symm: symmetric hash enable/disable
  *
  * Assumption: lock has already been acquired for RSS list
  */
 static enum ice_status
 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
-                    u32 addl_hdrs, u8 segs_cnt)
+                    u32 addl_hdrs, u8 segs_cnt, bool symm)
 {
        const enum ice_block blk = ICE_BLK_RSS;
        struct ice_flow_prof *prof = NULL;
        struct ice_flow_seg_info *segs;
-       enum ice_status status = ICE_SUCCESS;
+       enum ice_status status;
 
        if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
                return ICE_ERR_PARAM;
@@ -1944,8 +2167,12 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
                                        vsi_handle,
                                        ICE_FLOW_FIND_PROF_CHK_FLDS |
                                        ICE_FLOW_FIND_PROF_CHK_VSI);
-       if (prof)
-               goto exit;
+       if (prof) {
+               if (prof->cfg.symm == symm)
+                       goto exit;
+               prof->cfg.symm = symm;
+               goto update_symm;
+       }
 
        /* Check if a flow profile exists with the same protocol headers and
         * associated with the input VSI. If so disasscociate the VSI from
@@ -1976,9 +2203,18 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
                                        vsi_handle,
                                        ICE_FLOW_FIND_PROF_CHK_FLDS);
        if (prof) {
-               status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
-               if (!status)
-                       status = ice_add_rss_list(hw, vsi_handle, prof);
+               if (prof->cfg.symm == symm) {
+                       status = ice_flow_assoc_prof(hw, blk, prof,
+                                                    vsi_handle);
+                       if (!status)
+                               status = ice_add_rss_list(hw, vsi_handle,
+                                                         prof);
+               } else {
+                       /* if a profile exist but with different symmetric
+                        * requirement, just return error.
+                        */
+                       status = ICE_ERR_NOT_SUPPORTED;
+               }
                goto exit;
        }
 
@@ -2004,6 +2240,11 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
 
        status = ice_add_rss_list(hw, vsi_handle, prof);
 
+       prof->cfg.symm = symm;
+
+update_symm:
+       ice_rss_update_symm(hw, prof);
+
 exit:
        ice_free(hw, segs);
        return status;
@@ -2015,6 +2256,7 @@ exit:
  * @vsi_handle: software VSI handle
  * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
  * @addl_hdrs: protocol header fields
+ * @symm: symmetric hash enable/disable
  *
  * This function will generate a flow profile based on fields associated with
  * the input fields to hash on, the flow type and use the VSI number to add
@@ -2022,7 +2264,7 @@ exit:
  */
 enum ice_status
 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
-               u32 addl_hdrs)
+               u32 addl_hdrs, bool symm)
 {
        enum ice_status status;
 
@@ -2032,10 +2274,11 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
 
        ice_acquire_lock(&hw->rss_locks);
        status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
-                                     ICE_RSS_OUTER_HEADERS);
+                                     ICE_RSS_OUTER_HEADERS, symm);
        if (!status)
                status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
-                                             addl_hdrs, ICE_RSS_INNER_HEADERS);
+                                             addl_hdrs, ICE_RSS_INNER_HEADERS,
+                                             symm);
        ice_release_lock(&hw->rss_locks);
 
        return status;
@@ -2060,12 +2303,14 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
        struct ice_flow_prof *prof;
        enum ice_status status;
 
-       segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
+       segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
+                                                     sizeof(*segs));
        if (!segs)
                return ICE_ERR_NO_MEMORY;
 
        /* Construct the packet segment info from the hashed fields */
-       status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
+       status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
+                                          addl_hdrs);
        if (status)
                goto out;
 
@@ -2148,13 +2393,15 @@ enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
                        status = ice_add_rss_cfg_sync(hw, vsi_handle,
                                                      r->hashed_flds,
                                                      r->packet_hdr,
-                                                     ICE_RSS_OUTER_HEADERS);
+                                                     ICE_RSS_OUTER_HEADERS,
+                                                     r->symm);
                        if (status)
                                break;
                        status = ice_add_rss_cfg_sync(hw, vsi_handle,
                                                      r->hashed_flds,
                                                      r->packet_hdr,
-                                                     ICE_RSS_INNER_HEADERS);
+                                                     ICE_RSS_INNER_HEADERS,
+                                                     r->symm);
                        if (status)
                                break;
                }