X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fice%2Fbase%2Fice_flow.c;h=9a35a11d5cd949a3b6550e98a8408c9e37484235;hb=12f6ea93f060e87c8cf211486d44fdb4cc4235f5;hp=98727cfeb7be6c293214c129b276bba3297d4d0c;hpb=182dda1e8812a9f57984b7f0186487c494e24cbf;p=dpdk.git diff --git a/drivers/net/ice/base/ice_flow.c b/drivers/net/ice/base/ice_flow.c index 98727cfeb7..9a35a11d5c 100644 --- a/drivers/net/ice/base/ice_flow.c +++ b/drivers/net/ice/base/ice_flow.c @@ -19,6 +19,8 @@ #define ICE_FLOW_FLD_SZ_ICMP_CODE 1 #define ICE_FLOW_FLD_SZ_ARP_OPER 2 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4 +#define ICE_FLOW_FLD_SZ_GTP_TEID 4 +#define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2 /* Protocol header fields are extracted at the word boundaries as word-sized * values. Specify the displacement value of some non-word-aligned fields needed @@ -26,80 +28,112 @@ * protocol headers. Displacement values are expressed in number of bits. */ #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP (-4) -#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * 8) -#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * 8) +#define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * BITS_PER_BYTE) +#define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE) /* Describe properties of a protocol header field */ struct ice_flow_field_info { enum ice_flow_seg_hdr hdr; s16 off; /* Offset from start of a protocol header, in bits */ u16 size; /* Size of fields in bits */ + u16 mask; /* 16-bit mask for field */ }; +#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ + .hdr = _hdr, \ + .off = (_offset_bytes) * BITS_PER_BYTE, \ + .size = (_size_bytes) * BITS_PER_BYTE, \ + .mask = 0, \ +} + +#define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \ + .hdr = _hdr, \ + .off = (_offset_bytes) * BITS_PER_BYTE, \ + .size = (_size_bytes) * BITS_PER_BYTE, \ + .mask = _mask, \ +} + /* Table containing properties of supported protocol header fields */ static const struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { /* Ether */ /* ICE_FLOW_FIELD_IDX_ETH_DA */ - { ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), /* ICE_FLOW_FIELD_IDX_ETH_SA */ - { ICE_FLOW_SEG_HDR_ETH, ETH_ALEN * 8, ETH_ALEN * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), /* ICE_FLOW_FIELD_IDX_S_VLAN */ - { ICE_FLOW_SEG_HDR_VLAN, 12 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN), /* ICE_FLOW_FIELD_IDX_C_VLAN */ - { ICE_FLOW_SEG_HDR_VLAN, 14 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN), /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ - { ICE_FLOW_SEG_HDR_ETH, 12 * 8, ICE_FLOW_FLD_SZ_ETH_TYPE * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE), /* IPv4 */ /* ICE_FLOW_FIELD_IDX_IP_DSCP */ - { ICE_FLOW_SEG_HDR_IPV4, 1 * 8, 1 * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1), /* ICE_FLOW_FIELD_IDX_IP_TTL */ - { ICE_FLOW_SEG_HDR_NONE, 8 * 8, 1 * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1), /* ICE_FLOW_FIELD_IDX_IP_PROT */ - { ICE_FLOW_SEG_HDR_NONE, 9 * 8, ICE_FLOW_FLD_SZ_IP_PROT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT), /* ICE_FLOW_FIELD_IDX_IPV4_SA */ - { ICE_FLOW_SEG_HDR_IPV4, 12 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR), /* ICE_FLOW_FIELD_IDX_IPV4_DA */ - { ICE_FLOW_SEG_HDR_IPV4, 16 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR), /* IPv6 */ /* ICE_FLOW_FIELD_IDX_IPV6_SA */ - { ICE_FLOW_SEG_HDR_IPV6, 8 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR), /* ICE_FLOW_FIELD_IDX_IPV6_DA */ - { ICE_FLOW_SEG_HDR_IPV6, 24 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR), /* Transport */ /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ - { ICE_FLOW_SEG_HDR_TCP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT), /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ - { ICE_FLOW_SEG_HDR_TCP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT), /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ - { ICE_FLOW_SEG_HDR_UDP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT), /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ - { ICE_FLOW_SEG_HDR_UDP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT), /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ - { ICE_FLOW_SEG_HDR_SCTP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT), /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ - { ICE_FLOW_SEG_HDR_SCTP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT), /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ - { ICE_FLOW_SEG_HDR_TCP, 13 * 8, ICE_FLOW_FLD_SZ_TCP_FLAGS * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS), /* ARP */ /* ICE_FLOW_FIELD_IDX_ARP_SIP */ - { ICE_FLOW_SEG_HDR_ARP, 14 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR), /* ICE_FLOW_FIELD_IDX_ARP_DIP */ - { ICE_FLOW_SEG_HDR_ARP, 24 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR), /* ICE_FLOW_FIELD_IDX_ARP_SHA */ - { ICE_FLOW_SEG_HDR_ARP, 8 * 8, ETH_ALEN * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), /* ICE_FLOW_FIELD_IDX_ARP_DHA */ - { ICE_FLOW_SEG_HDR_ARP, 18 * 8, ETH_ALEN * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), /* ICE_FLOW_FIELD_IDX_ARP_OP */ - { ICE_FLOW_SEG_HDR_ARP, 6 * 8, ICE_FLOW_FLD_SZ_ARP_OPER * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER), /* ICMP */ /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ - { ICE_FLOW_SEG_HDR_ICMP, 0 * 8, ICE_FLOW_FLD_SZ_ICMP_TYPE * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE), /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ - { ICE_FLOW_SEG_HDR_ICMP, 1 * 8, ICE_FLOW_FLD_SZ_ICMP_CODE * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE), /* GRE */ /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ - { ICE_FLOW_SEG_HDR_GRE, 12 * 8, ICE_FLOW_FLD_SZ_GRE_KEYID * 8 }, + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID), + /* GTP */ + /* ICE_FLOW_FIELD_IDX_GTPC_TEID */ + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12, + ICE_FLOW_FLD_SZ_GTP_TEID), + /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */ + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12, + ICE_FLOW_FLD_SZ_GTP_TEID), + /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */ + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12, + ICE_FLOW_FLD_SZ_GTP_TEID), + /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */ + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12, + ICE_FLOW_FLD_SZ_GTP_TEID), + /* PPPOE */ + /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */ + ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2, + ICE_FLOW_FLD_SZ_PPPOE_SESS_ID), }; /* Bitmaps indicating relevant packet types for a particular protocol header @@ -189,21 +223,11 @@ static const u32 ice_ptypes_arp_of[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; -/* Packet types for packets with an Outermost/First UDP header */ -static const u32 ice_ptypes_udp_of[] = { - 0x81000000, 0x00000000, 0x04000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; - -/* Packet types for packets with an Innermost/Last UDP header */ +/* UDP Packet types for non-tunneled packets or tunneled + * packets with inner UDP. + */ static const u32 ice_ptypes_udp_il[] = { - 0x80000000, 0x20204040, 0x00081010, 0x80810102, + 0x81000000, 0x20204040, 0x04081010, 0x80810102, 0x00204040, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -216,7 +240,7 @@ static const u32 ice_ptypes_udp_il[] = { /* Packet types for packets with an Innermost/Last TCP header */ static const u32 ice_ptypes_tcp_il[] = { 0x04000000, 0x80810102, 0x10204040, 0x42040408, - 0x00810002, 0x00000000, 0x00000000, 0x00000000, + 0x00810102, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -285,37 +309,67 @@ static const u32 ice_ptypes_mac_il[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; +/* Packet types for GTPC */ +static const u32 ice_ptypes_gtpc[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000180, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +/* Packet types for GTPC with TEID */ +static const u32 ice_ptypes_gtpc_tid[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000060, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +/* Packet types for GTPU */ +static const u32 ice_ptypes_gtpu[] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x7FFFF800, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + /* Manage parameters and info. used during the creation of a flow profile */ struct ice_flow_prof_params { enum ice_block blk; - struct ice_flow_prof *prof; - u16 entry_length; /* # of bytes formatted entry will require */ u8 es_cnt; + struct ice_flow_prof *prof; + /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 * This will give us the direction flags. */ struct ice_fv_word es[ICE_MAX_FV_WORDS]; - + u16 mask[ICE_MAX_FV_WORDS]; ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX); }; -/** - * ice_is_pow2 - check if integer value is a power of 2 - * @val: unsigned integer to be validated - */ -static bool ice_is_pow2(u64 val) -{ - return (val && !(val & (val - 1))); -} - #define ICE_FLOW_SEG_HDRS_L2_MASK \ (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN) #define ICE_FLOW_SEG_HDRS_L3_MASK \ - (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) + (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \ + ICE_FLOW_SEG_HDR_ARP | ICE_FLOW_SEG_HDR_PPPOE) #define ICE_FLOW_SEG_HDRS_L4_MASK \ (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ - ICE_FLOW_SEG_HDR_SCTP) + ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC | \ + ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU_IP | \ + ICE_FLOW_SEG_HDR_GTPU_UP | ICE_FLOW_SEG_HDR_GTPU_DWN) /** * ice_flow_val_hdrs - validates packet segments for valid protocol headers @@ -419,9 +473,6 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) const ice_bitmap_t *src; u32 hdrs; - if (i > 0 && (i + 1) < prof->segs_cnt) - continue; - hdrs = prof->segs[i].hdrs; if (hdrs & ICE_FLOW_SEG_HDR_ETH) { @@ -429,21 +480,18 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) (const ice_bitmap_t *)ice_ptypes_mac_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_ETH; } if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { src = (const ice_bitmap_t *)ice_ptypes_macvlan_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_VLAN; } if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { ice_and_bitmap(params->ptypes, params->ptypes, (const ice_bitmap_t *)ice_ptypes_arp_of, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_ARP; } if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { @@ -451,13 +499,11 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) (const ice_bitmap_t *)ice_ptypes_ipv4_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_IPV4; } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos : (const ice_bitmap_t *)ice_ptypes_ipv6_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_IPV6; } if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { @@ -465,36 +511,84 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) (const ice_bitmap_t *)ice_ptypes_icmp_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_ICMP; } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) { - src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of : - (const ice_bitmap_t *)ice_ptypes_udp_il; + src = (const ice_bitmap_t *)ice_ptypes_udp_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_UDP; } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { ice_and_bitmap(params->ptypes, params->ptypes, (const ice_bitmap_t *)ice_ptypes_tcp_il, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_TCP; } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { src = (const ice_bitmap_t *)ice_ptypes_sctp_il; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); - hdrs &= ~ICE_FLOW_SEG_HDR_SCTP; } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { if (!i) { src = (const ice_bitmap_t *)ice_ptypes_gre_of; ice_and_bitmap(params->ptypes, params->ptypes, src, ICE_FLOW_PTYPE_MAX); } - hdrs &= ~ICE_FLOW_SEG_HDR_GRE; + } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) { + if (!i) { + src = (const ice_bitmap_t *)ice_ptypes_gtpc; + ice_and_bitmap(params->ptypes, params->ptypes, + src, ICE_FLOW_PTYPE_MAX); + } + } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) { + if (!i) { + src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid; + ice_and_bitmap(params->ptypes, params->ptypes, + src, ICE_FLOW_PTYPE_MAX); + } + } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) { + if (!i) { + src = (const ice_bitmap_t *)ice_ptypes_gtpu; + ice_and_bitmap(params->ptypes, params->ptypes, + src, ICE_FLOW_PTYPE_MAX); + } } } return ICE_SUCCESS; } +/** + * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags + * @hw: pointer to the HW struct + * @params: information about the flow to be processed + * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata. + * + * This function will allocate an extraction sequence entries for a DWORD size + * chunk of the packet flags. + */ +static enum ice_status +ice_flow_xtract_pkt_flags(struct ice_hw *hw, + struct ice_flow_prof_params *params, + enum ice_flex_mdid_pkt_flags flags) +{ + u8 fv_words = hw->blk[params->blk].es.fvw; + u8 idx; + + /* Make sure the number of extraction sequence entries required does not + * exceed the block's capacity. + */ + if (params->es_cnt >= fv_words) + return ICE_ERR_MAX_LIMIT; + + /* 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 = ICE_PROT_META_ID; + params->es[idx].off = flags; + params->es_cnt++; + + return ICE_SUCCESS; +} + /** * ice_flow_xtract_fld - Create an extraction sequence entry for the given field * @hw: pointer to the HW struct @@ -516,7 +610,8 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, struct ice_flow_fld_info *flds; u16 cnt, ese_bits, i; s16 adj = 0; - u8 off; + u16 mask; + u16 off; flds = params->prof->segs[seg].fields; @@ -575,12 +670,22 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, break; case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: - prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF; + prot_id = ICE_PROT_UDP_IL_OR_S; break; case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: prot_id = ICE_PROT_SCTP_IL; break; + case ICE_FLOW_FIELD_IDX_GTPC_TEID: + case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID: + case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID: + case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID: + /* GTP is accessed through UDP OF protocol */ + prot_id = ICE_PROT_UDP_OF; + break; + case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID: + prot_id = ICE_PROT_PPPOE; + break; case ICE_FLOW_FIELD_IDX_ARP_SIP: case ICE_FLOW_FIELD_IDX_ARP_DIP: case ICE_FLOW_FIELD_IDX_ARP_SHA: @@ -608,7 +713,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, /* Each extraction sequence entry is a word in size, and extracts a * word-aligned offset from a protocol header. */ - ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8; + ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; flds[fld].xtrct.prot_id = prot_id; flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * @@ -624,6 +729,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, /* Fill in the extraction sequence entries needed for this field */ off = flds[fld].xtrct.off; + mask = ice_flds_info[fld].mask; for (i = 0; i < cnt; i++) { /* Only consume an extraction sequence entry if there is no * sibling field associated with this field or the sibling entry @@ -648,6 +754,7 @@ ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, params->es[idx].prot_id = prot_id; params->es[idx].off = off; + params->mask[idx] = mask; params->es_cnt++; } @@ -701,15 +808,17 @@ ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params, raw->info.xtrct.prot_id = ICE_PROT_PAY; raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) * ICE_FLOW_FV_EXTRACT_SZ; - raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8; + raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * + BITS_PER_BYTE; raw->info.xtrct.idx = params->es_cnt; /* Determine the number of field vector entries this raw field * consumes. */ cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp + - (raw->info.src.last * 8), - ICE_FLOW_FV_EXTRACT_SZ * 8); + (raw->info.src.last * BITS_PER_BYTE), + (ICE_FLOW_FV_EXTRACT_SZ * + BITS_PER_BYTE)); off = raw->info.xtrct.off; for (j = 0; j < cnt; j++) { /* Make sure the number of extraction sequence required @@ -744,6 +853,13 @@ ice_flow_create_xtrct_seq(struct ice_hw *hw, enum ice_status status = ICE_SUCCESS; u8 i; + /* 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); + for (i = 0; i < params->prof->segs_cnt; i++) { u64 match = params->prof->segs[i].match; u16 j; @@ -807,6 +923,7 @@ ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 +#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 /** * ice_flow_find_prof_conds - Find a profile matching headers and conditions @@ -823,10 +940,12 @@ ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, struct ice_flow_seg_info *segs, u8 segs_cnt, u16 vsi_handle, u32 conds) { - struct ice_flow_prof *p; + struct ice_flow_prof *p, *prof = NULL; + ice_acquire_lock(&hw->fl_profs_locks[blk]); LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) { - if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) { + if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && + segs_cnt && segs_cnt == p->segs_cnt) { u8 i; /* Check for profile-VSI association if specified */ @@ -845,12 +964,15 @@ ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, break; /* A match is found if all segments are matched */ - if (i == segs_cnt) - return p; + if (i == segs_cnt) { + prof = p; + break; + } } } + ice_release_lock(&hw->fl_profs_locks[blk]); - return NULL; + return prof; } /** @@ -867,10 +989,8 @@ ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, { struct ice_flow_prof *p; - ice_acquire_lock(&hw->fl_profs_locks[blk]); p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt, ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS); - ice_release_lock(&hw->fl_profs_locks[blk]); return p ? p->id : ICE_FLOW_PROF_ID_INVAL; } @@ -895,17 +1015,15 @@ ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) } /** - * ice_flow_rem_entry_sync - Remove a flow entry + * ice_dealloc_flow_entry - Deallocate flow entry memory * @hw: pointer to the HW struct * @entry: flow entry to be removed */ -static enum ice_status -ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry) +static void +ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry) { if (!entry) - return ICE_ERR_BAD_PTR; - - LIST_DEL(&entry->l_entry); + return; if (entry->entry) ice_free(hw, entry->entry); @@ -917,6 +1035,22 @@ ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry) } ice_free(hw, entry); +} + +/** + * ice_flow_rem_entry_sync - Remove a flow entry + * @hw: pointer to the HW struct + * @entry: flow entry to be removed + */ +static enum ice_status +ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry) +{ + if (!entry) + return ICE_ERR_BAD_PTR; + + LIST_DEL(&entry->l_entry); + + ice_dealloc_flow_entry(hw, entry); return ICE_SUCCESS; } @@ -956,7 +1090,10 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, return ICE_ERR_NO_MEMORY; /* initialize extraction sequence to all invalid (0xff) */ - ice_memset(params.es, 0xff, sizeof(params.es), ICE_NONDMA_MEM); + for (i = 0; i < ICE_MAX_FV_WORDS; i++) { + params.es[i].prot_id = ICE_PROT_INVALID; + params.es[i].off = ICE_FV_OFFSET_INVAL; + } params.blk = blk; params.prof->id = prof_id; @@ -992,7 +1129,8 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, } /* Add a HW profile for this flow profile */ - status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es); + status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes, + params.es, params.mask); if (status) { ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); goto out; @@ -1055,6 +1193,34 @@ ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, return status; } +/** + * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG + * @hw: pointer to the hardware structure + * @blk: classification stage + * @vsi_handle: software VSI handle + * @vsig: target VSI group + * + * Assumption: the caller has already verified that the VSI to + * be added has the same characteristics as the VSIG and will + * thereby have access to all resources added to that VSIG. + */ +enum ice_status +ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle, + u16 vsig) +{ + enum ice_status status; + + if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT) + return ICE_ERR_PARAM; + + ice_acquire_lock(&hw->fl_profs_locks[blk]); + status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle), + vsig); + ice_release_lock(&hw->fl_profs_locks[blk]); + + return status; +} + /** * ice_flow_assoc_prof - associate a VSI with a flow profile * @hw: pointer to the hardware structure @@ -1324,9 +1490,12 @@ ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id, goto out; } - ice_acquire_lock(&prof->entries_lock); - LIST_ADD(&e->l_entry, &prof->entries); - ice_release_lock(&prof->entries_lock); + if (blk != ICE_BLK_ACL) { + /* ACL will handle the entry management */ + ice_acquire_lock(&prof->entries_lock); + LIST_ADD(&e->l_entry, &prof->entries); + ice_release_lock(&prof->entries_lock); + } *entry_h = ICE_FLOW_ENTRY_HNDL(e); @@ -1504,11 +1673,12 @@ ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len, } #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ - (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) + (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE) #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ - ICE_FLOW_SEG_HDR_SCTP) + ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC_TEID) + #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ @@ -1559,27 +1729,32 @@ ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields, } /** - * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context + * ice_rem_vsi_rss_list - remove VSI from RSS list * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle * + * Remove the VSI from all RSS configurations in the list. */ -void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) +void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) { struct ice_rss_cfg *r, *tmp; - if (!ice_is_vsi_valid(hw, vsi_handle) || - LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head)) + if (LIST_EMPTY(&hw->rss_list_head)) return; - ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); - LIST_FOR_EACH_ENTRY_SAFE(r, tmp, - &hw->vsi_ctx[vsi_handle]->rss_list_head, + ice_acquire_lock(&hw->rss_locks); + LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, ice_rss_cfg, l_entry) { - LIST_DEL(&r->l_entry); - ice_free(hw, r); + if (ice_is_bit_set(r->vsis, vsi_handle)) { + ice_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->vsi_ctx[vsi_handle]->rss_locks); + ice_release_lock(&hw->rss_locks); } /** @@ -1600,6 +1775,9 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) if (!ice_is_vsi_valid(hw, vsi_handle)) return ICE_ERR_PARAM; + if (LIST_EMPTY(&hw->fl_profs[blk])) + return ICE_SUCCESS; + ice_acquire_lock(&hw->fl_profs_locks[blk]); LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, l_entry) { @@ -1621,7 +1799,7 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) } /** - * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context + * ice_rem_rss_list - remove RSS configuration from list * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle * @prof: pointer to flow profile @@ -1629,8 +1807,7 @@ enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) * Assumption: lock has already been acquired for RSS list */ static void -ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, - struct ice_flow_prof *prof) +ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) { struct ice_rss_cfg *r, *tmp; @@ -1638,20 +1815,22 @@ ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, * hash configurations associated to the flow profile. If found * remove from the RSS entry list of the VSI context and delete entry. */ - LIST_FOR_EACH_ENTRY_SAFE(r, tmp, - &hw->vsi_ctx[vsi_handle]->rss_list_head, + LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, ice_rss_cfg, l_entry) { if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { - LIST_DEL(&r->l_entry); - ice_free(hw, r); + ice_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); + } return; } } } /** - * ice_add_rss_vsi_ctx - add RSS configuration to VSI context + * ice_add_rss_list - add RSS configuration to list * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle * @prof: pointer to flow profile @@ -1659,16 +1838,17 @@ ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, * Assumption: lock has already been acquired for RSS list */ static enum ice_status -ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, - struct ice_flow_prof *prof) +ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) { struct ice_rss_cfg *r, *rss_cfg; - LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head, + LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, ice_rss_cfg, l_entry) if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match && - r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) + r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) { + ice_set_bit(vsi_handle, r->vsis); return ICE_SUCCESS; + } rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); if (!rss_cfg) @@ -1676,8 +1856,9 @@ ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match; rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs; - LIST_ADD_TAIL(&rss_cfg->l_entry, - &hw->vsi_ctx[vsi_handle]->rss_list_head); + ice_set_bit(vsi_handle, rss_cfg->vsis); + + LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head); return ICE_SUCCESS; } @@ -1739,13 +1920,13 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, if (prof) { status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); if (!status) - ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof); + ice_rem_rss_list(hw, vsi_handle, prof); else goto exit; /* Remove profile if it has no VSIs associated */ if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { - status = ice_flow_rem_prof_sync(hw, blk, prof); + status = ice_flow_rem_prof(hw, blk, prof->id); if (status) goto exit; } @@ -1760,7 +1941,7 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, if (prof) { status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); if (!status) - status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof); + status = ice_add_rss_list(hw, vsi_handle, prof); goto exit; } @@ -1778,11 +1959,11 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, * be removed. */ if (status) { - ice_flow_rem_prof_sync(hw, blk, prof); + ice_flow_rem_prof(hw, blk, prof->id); goto exit; } - status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof); + status = ice_add_rss_list(hw, vsi_handle, prof); exit: ice_free(hw, segs); @@ -1810,9 +1991,9 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, !ice_is_vsi_valid(hw, vsi_handle)) return ICE_ERR_PARAM; - ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); + ice_acquire_lock(&hw->rss_locks); status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs); - ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); + ice_release_lock(&hw->rss_locks); return status; } @@ -1859,16 +2040,144 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, /* Remove RSS configuration from VSI context before deleting * the flow profile. */ - ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof); + ice_rem_rss_list(hw, vsi_handle, prof); if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) - status = ice_flow_rem_prof_sync(hw, blk, prof); + status = ice_flow_rem_prof(hw, blk, prof->id); out: ice_free(hw, segs); 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_rem_rss_cfg - remove an existing RSS config with matching hashed fields * @hw: pointer to the hardware structure @@ -1892,15 +2201,15 @@ ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds, !ice_is_vsi_valid(hw, vsi_handle)) return ICE_ERR_PARAM; - ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); + ice_acquire_lock(&hw->rss_locks); status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs); - ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); + ice_release_lock(&hw->rss_locks); return status; } /** - * ice_replay_rss_cfg - remove RSS configurations associated with VSI + * ice_replay_rss_cfg - replay RSS configurations associated with VSI * @hw: pointer to the hardware structure * @vsi_handle: software VSI handle */ @@ -1912,15 +2221,18 @@ enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) if (!ice_is_vsi_valid(hw, vsi_handle)) return ICE_ERR_PARAM; - ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); - LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head, + ice_acquire_lock(&hw->rss_locks); + LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, ice_rss_cfg, l_entry) { - status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds, - r->packet_hdr); - if (status) - break; + if (ice_is_bit_set(r->vsis, vsi_handle)) { + status = ice_add_rss_cfg_sync(hw, vsi_handle, + r->hashed_flds, + r->packet_hdr); + if (status) + break; + } } - ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); + ice_release_lock(&hw->rss_locks); return status; } @@ -1942,14 +2254,15 @@ u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) return ICE_HASH_INVALID; - ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); - LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head, + ice_acquire_lock(&hw->rss_locks); + LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, ice_rss_cfg, l_entry) - if (r->packet_hdr == hdrs) { + if (ice_is_bit_set(r->vsis, vsi_handle) && + r->packet_hdr == hdrs) { rss_cfg = r; break; } - ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks); + ice_release_lock(&hw->rss_locks); return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID; }