X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fice%2Fbase%2Fice_flow.c;h=17fd2423eff91984cb7465ddad8197d1d0dbebcd;hb=486d29fda54c362ec3a96ab13327064458de0b03;hp=769fd2da705cb3debafe0861a32e9f797896d44f;hpb=c5adb3c448835c43a3f12ae435ae040febb5e0a4;p=dpdk.git diff --git a/drivers/net/ice/base/ice_flow.c b/drivers/net/ice/base/ice_flow.c index 769fd2da70..17fd2423ef 100644 --- a/drivers/net/ice/base/ice_flow.c +++ b/drivers/net/ice/base/ice_flow.c @@ -20,17 +20,9 @@ #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,9 +260,9 @@ 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, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x08000000, 0x01020204, 0x20000081, 0x04080810, + 0x00000204, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x01040000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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,19 +446,26 @@ 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); }; +#define ICE_FLOW_RSS_HDRS_INNER_MASK \ + (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \ + ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU) + #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_PPPOE) + ICE_FLOW_SEG_HDR_ARP) #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_GTPC | \ - ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU) + ICE_FLOW_SEG_HDR_SCTP) /** * ice_flow_val_hdrs - validates packet segments for valid protocol headers @@ -540,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); } } @@ -605,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 @@ -612,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; @@ -635,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 (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_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 (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: @@ -690,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; @@ -730,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 @@ -739,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 @@ -764,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++; } @@ -784,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; @@ -799,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 = ¶ms->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; @@ -831,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 */ @@ -838,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; } @@ -866,20 +991,23 @@ ice_flow_create_xtrct_seq(struct ice_hw *hw, /* For ACL, we also need to extract the direction bit (Rx,Tx) data from * packet flags */ - if (params->blk == ICE_BLK_ACL) - ice_flow_xtract_pkt_flags(hw, params, - ICE_RX_MDID_PKT_FLAGS_15_0); + if (params->blk == ICE_BLK_ACL) { + status = ice_flow_xtract_pkt_flags(hw, params, + ICE_RX_MDID_PKT_FLAGS_15_0); + if (status) + return status; + } 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; @@ -1087,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)) @@ -1139,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; @@ -1172,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)) { @@ -1549,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 @@ -1570,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; @@ -1686,13 +1815,11 @@ ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ - (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE) + (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) #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_GTPC_TEID | \ - ICE_FLOW_SEG_HDR_GTPU) - + ICE_FLOW_SEG_HDR_SCTP) #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \ @@ -1729,11 +1856,12 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, } ICE_FLOW_SET_HDRS(segs, flow_hdr); - if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS) + if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS & + ~ICE_FLOW_RSS_HDRS_INNER_MASK) return ICE_ERR_PARAM; val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); - if (!ice_is_pow2(val)) + if (val && !ice_is_pow2(val)) return ICE_ERR_CFG; val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); @@ -1760,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); } @@ -1871,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); @@ -1898,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 @@ -1905,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; @@ -1939,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 @@ -1971,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; } @@ -1999,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; @@ -2010,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 @@ -2017,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; @@ -2027,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; @@ -2055,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; @@ -2123,134 +2373,6 @@ ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, return status; } -/* Mapping of AVF hash bit fields to an L3-L4 hash combination. - * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, - * convert its values to their appropriate flow L3, L4 values. - */ -#define ICE_FLOW_AVF_RSS_IPV4_MASKS \ - (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) -#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ - (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) -#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ - (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) -#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ - (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ - ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) - -#define ICE_FLOW_AVF_RSS_IPV6_MASKS \ - (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) -#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ - (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) -#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ - (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ - BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) -#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ - (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ - ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) - -#define ICE_FLOW_MAX_CFG 10 - -/** - * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver - * @hw: pointer to the hardware structure - * @vsi_handle: software VSI handle - * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure - * - * This function will take the hash bitmap provided by the AVF driver via a - * message, convert it to ICE-compatible values, and configure RSS flow - * profiles. - */ -enum ice_status -ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) -{ - enum ice_status status = ICE_SUCCESS; - u64 hash_flds; - - if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || - !ice_is_vsi_valid(hw, vsi_handle)) - return ICE_ERR_PARAM; - - /* Make sure no unsupported bits are specified */ - if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | - ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) - return ICE_ERR_CFG; - - hash_flds = avf_hash; - - /* Always create an L3 RSS configuration for any L4 RSS configuration */ - if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) - hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; - - if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) - hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; - - /* Create the corresponding RSS configuration for each valid hash bit */ - while (hash_flds) { - u64 rss_hash = ICE_HASH_INVALID; - - if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { - if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { - rss_hash = ICE_FLOW_HASH_IPV4; - hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; - } else if (hash_flds & - ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { - rss_hash = ICE_FLOW_HASH_IPV4 | - ICE_FLOW_HASH_TCP_PORT; - hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; - } else if (hash_flds & - ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { - rss_hash = ICE_FLOW_HASH_IPV4 | - ICE_FLOW_HASH_UDP_PORT; - hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; - } else if (hash_flds & - BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { - rss_hash = ICE_FLOW_HASH_IPV4 | - ICE_FLOW_HASH_SCTP_PORT; - hash_flds &= - ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); - } - } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { - if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { - rss_hash = ICE_FLOW_HASH_IPV6; - hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; - } else if (hash_flds & - ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { - rss_hash = ICE_FLOW_HASH_IPV6 | - ICE_FLOW_HASH_TCP_PORT; - hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; - } else if (hash_flds & - ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { - rss_hash = ICE_FLOW_HASH_IPV6 | - ICE_FLOW_HASH_UDP_PORT; - hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; - } else if (hash_flds & - BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { - rss_hash = ICE_FLOW_HASH_IPV6 | - ICE_FLOW_HASH_SCTP_PORT; - hash_flds &= - ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); - } - } - - if (rss_hash == ICE_HASH_INVALID) - return ICE_ERR_OUT_OF_RANGE; - - status = ice_add_rss_cfg(hw, vsi_handle, rss_hash, - ICE_FLOW_SEG_HDR_NONE); - if (status) - break; - } - - return status; -} - /** * ice_replay_rss_cfg - replay RSS configurations associated with VSI * @hw: pointer to the hardware structure @@ -2271,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; }