#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;
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 */
/* 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),
* 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,
/* 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,
/* 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,
/* 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,
/* 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,
* 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,
/* 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,
/* 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,
/* 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,
/* 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,
/* 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,
};
/* 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,
* 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);
};
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);
}
}
* @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
*/
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;
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:
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;
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
/* 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
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++;
}
ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
u8 seg)
{
+ u16 fv_words;
u16 hdrs_sz;
u8 i;
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;
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
*/
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;
}
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;
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))
}
/* 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;
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)) {
* 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
*/
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;
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);
}
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);
(((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
* @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;
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
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;
}
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;
* @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
*/
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;
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;
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;
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;
}