171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 371d10453SEric Joyner * All rights reserved. 471d10453SEric Joyner * 571d10453SEric Joyner * Redistribution and use in source and binary forms, with or without 671d10453SEric Joyner * modification, are permitted provided that the following conditions are met: 771d10453SEric Joyner * 871d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 971d10453SEric Joyner * this list of conditions and the following disclaimer. 1071d10453SEric Joyner * 1171d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 1271d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the 1371d10453SEric Joyner * documentation and/or other materials provided with the distribution. 1471d10453SEric Joyner * 1571d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 1671d10453SEric Joyner * contributors may be used to endorse or promote products derived from 1771d10453SEric Joyner * this software without specific prior written permission. 1871d10453SEric Joyner * 1971d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2071d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2171d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2271d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2371d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2471d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2571d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2671d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2771d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2871d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2971d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE. 3071d10453SEric Joyner */ 3171d10453SEric Joyner 3271d10453SEric Joyner #include "ice_common.h" 3371d10453SEric Joyner #include "ice_flow.h" 3471d10453SEric Joyner 3571d10453SEric Joyner /* Size of known protocol header fields */ 3671d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ETH_TYPE 2 3771d10453SEric Joyner #define ICE_FLOW_FLD_SZ_VLAN 2 3871d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IPV4_ADDR 4 3971d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IPV6_ADDR 16 4071d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IP_DSCP 1 4171d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IP_TTL 1 4271d10453SEric Joyner #define ICE_FLOW_FLD_SZ_IP_PROT 1 4371d10453SEric Joyner #define ICE_FLOW_FLD_SZ_PORT 2 4471d10453SEric Joyner #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1 4571d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1 4671d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ICMP_CODE 1 4771d10453SEric Joyner #define ICE_FLOW_FLD_SZ_ARP_OPER 2 4871d10453SEric Joyner #define ICE_FLOW_FLD_SZ_GRE_KEYID 4 4971d10453SEric Joyner 5071d10453SEric Joyner /* Describe properties of a protocol header field */ 5171d10453SEric Joyner struct ice_flow_field_info { 5271d10453SEric Joyner enum ice_flow_seg_hdr hdr; 5371d10453SEric Joyner s16 off; /* Offset from start of a protocol header, in bits */ 5471d10453SEric Joyner u16 size; /* Size of fields in bits */ 5571d10453SEric Joyner }; 5671d10453SEric Joyner 5771d10453SEric Joyner #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 5871d10453SEric Joyner .hdr = _hdr, \ 5971d10453SEric Joyner .off = (_offset_bytes) * BITS_PER_BYTE, \ 6071d10453SEric Joyner .size = (_size_bytes) * BITS_PER_BYTE, \ 6171d10453SEric Joyner } 6271d10453SEric Joyner 6371d10453SEric Joyner /* Table containing properties of supported protocol header fields */ 6471d10453SEric Joyner static const 6571d10453SEric Joyner struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 6671d10453SEric Joyner /* Ether */ 6771d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ETH_DA */ 6871d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), 6971d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ETH_SA */ 7071d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), 7171d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_S_VLAN */ 7271d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN), 7371d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_C_VLAN */ 7471d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN), 7571d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 767d7af7f8SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE), 7771d10453SEric Joyner /* IPv4 / IPv6 */ 7871d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ 7971d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, ICE_FLOW_FLD_SZ_IP_DSCP), 8071d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ 8171d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP), 8271d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ 8371d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, ICE_FLOW_FLD_SZ_IP_TTL), 8471d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 8571d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT), 8671d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ 8771d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 7, ICE_FLOW_FLD_SZ_IP_TTL), 8871d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 8971d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 6, ICE_FLOW_FLD_SZ_IP_PROT), 9071d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 9171d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR), 9271d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 9371d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR), 9471d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 9571d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR), 9671d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 9771d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR), 9871d10453SEric Joyner /* Transport */ 9971d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 10071d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT), 10171d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 10271d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT), 10371d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 10471d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT), 10571d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 10671d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT), 10771d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 10871d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT), 10971d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 11071d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT), 11171d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 11271d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS), 11371d10453SEric Joyner /* ARP */ 11471d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 11571d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR), 11671d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 11771d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR), 11871d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 11971d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), 12071d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 12171d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), 12271d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ARP_OP */ 12371d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER), 12471d10453SEric Joyner /* ICMP */ 12571d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 12671d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE), 12771d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 12871d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE), 12971d10453SEric Joyner /* GRE */ 13071d10453SEric Joyner /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 13171d10453SEric Joyner ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID), 13271d10453SEric Joyner }; 13371d10453SEric Joyner 13471d10453SEric Joyner /* Bitmaps indicating relevant packet types for a particular protocol header 13571d10453SEric Joyner * 13671d10453SEric Joyner * Packet types for packets with an Outer/First/Single MAC header 13771d10453SEric Joyner */ 13871d10453SEric Joyner static const u32 ice_ptypes_mac_ofos[] = { 13971d10453SEric Joyner 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, 14071d10453SEric Joyner 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 14171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 14771d10453SEric Joyner }; 14871d10453SEric Joyner 14971d10453SEric Joyner /* Packet types for packets with an Innermost/Last MAC VLAN header */ 15071d10453SEric Joyner static const u32 ice_ptypes_macvlan_il[] = { 15171d10453SEric Joyner 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 15271d10453SEric Joyner 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 15371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 15971d10453SEric Joyner }; 16071d10453SEric Joyner 16156429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv4 header, 16256429daeSEric Joyner * does NOT include IPV4 other PTYPEs 1637d7af7f8SEric Joyner */ 16471d10453SEric Joyner static const u32 ice_ptypes_ipv4_ofos[] = { 16556429daeSEric Joyner 0x1D800000, 0x04000800, 0x00000000, 0x00000000, 16671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 16971d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17071d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 17371d10453SEric Joyner }; 17471d10453SEric Joyner 17556429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv4 header, 17656429daeSEric Joyner * includes IPV4 other PTYPEs 1777d7af7f8SEric Joyner */ 1787d7af7f8SEric Joyner static const u32 ice_ptypes_ipv4_ofos_all[] = { 17956429daeSEric Joyner 0x1D800000, 0x04000800, 0x00000000, 0x00000000, 1807d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1817d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1827d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1837d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1847d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1857d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1867d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1877d7af7f8SEric Joyner }; 1887d7af7f8SEric Joyner 18971d10453SEric Joyner /* Packet types for packets with an Innermost/Last IPv4 header */ 19071d10453SEric Joyner static const u32 ice_ptypes_ipv4_il[] = { 19171d10453SEric Joyner 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 19271d10453SEric Joyner 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 19371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 19971d10453SEric Joyner }; 20071d10453SEric Joyner 20156429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv6 header, 20256429daeSEric Joyner * does NOT include IVP6 other PTYPEs 2037d7af7f8SEric Joyner */ 20471d10453SEric Joyner static const u32 ice_ptypes_ipv6_ofos[] = { 20556429daeSEric Joyner 0x00000000, 0x00000000, 0x76000000, 0x10002000, 20671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 20971d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21071d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 21371d10453SEric Joyner }; 21471d10453SEric Joyner 21556429daeSEric Joyner /* Packet types for packets with an Outer/First/Single non-frag IPv6 header, 21656429daeSEric Joyner * includes IPV6 other PTYPEs 2177d7af7f8SEric Joyner */ 2187d7af7f8SEric Joyner static const u32 ice_ptypes_ipv6_ofos_all[] = { 21956429daeSEric Joyner 0x00000000, 0x00000000, 0x76000000, 0x10002000, 2207d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2217d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2227d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2237d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2247d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2257d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2267d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2277d7af7f8SEric Joyner }; 2287d7af7f8SEric Joyner 22971d10453SEric Joyner /* Packet types for packets with an Innermost/Last IPv6 header */ 23071d10453SEric Joyner static const u32 ice_ptypes_ipv6_il[] = { 23171d10453SEric Joyner 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 23271d10453SEric Joyner 0x00000770, 0x00000000, 0x00000000, 0x00000000, 23371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 23971d10453SEric Joyner }; 24071d10453SEric Joyner 24156429daeSEric Joyner /* Packet types for packets with an Outer/First/Single 24256429daeSEric Joyner * non-frag IPv4 header - no L4 24356429daeSEric Joyner */ 244d08b8680SEric Joyner static const u32 ice_ptypes_ipv4_ofos_no_l4[] = { 24556429daeSEric Joyner 0x10800000, 0x04000800, 0x00000000, 0x00000000, 2467d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2477d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2487d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2497d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2507d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2517d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2527d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2537d7af7f8SEric Joyner }; 2547d7af7f8SEric Joyner 2557d7af7f8SEric Joyner /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ 256d08b8680SEric Joyner static const u32 ice_ptypes_ipv4_il_no_l4[] = { 2577d7af7f8SEric Joyner 0x60000000, 0x18043008, 0x80000002, 0x6010c021, 2587d7af7f8SEric Joyner 0x00000008, 0x00000000, 0x00000000, 0x00000000, 2597d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2607d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2617d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2627d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2637d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2647d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2657d7af7f8SEric Joyner }; 2667d7af7f8SEric Joyner 26756429daeSEric Joyner /* Packet types for packets with an Outer/First/Single 26856429daeSEric Joyner * non-frag IPv6 header - no L4 26956429daeSEric Joyner */ 270d08b8680SEric Joyner static const u32 ice_ptypes_ipv6_ofos_no_l4[] = { 27156429daeSEric Joyner 0x00000000, 0x00000000, 0x42000000, 0x10002000, 2727d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2737d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2747d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2757d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2767d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2777d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2787d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2797d7af7f8SEric Joyner }; 2807d7af7f8SEric Joyner 2817d7af7f8SEric Joyner /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ 282d08b8680SEric Joyner static const u32 ice_ptypes_ipv6_il_no_l4[] = { 2837d7af7f8SEric Joyner 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, 2847d7af7f8SEric Joyner 0x00000430, 0x00000000, 0x00000000, 0x00000000, 2857d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2867d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2877d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2887d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2897d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2907d7af7f8SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 2917d7af7f8SEric Joyner }; 2927d7af7f8SEric Joyner 29371d10453SEric Joyner /* Packet types for packets with an Outermost/First ARP header */ 29471d10453SEric Joyner static const u32 ice_ptypes_arp_of[] = { 29571d10453SEric Joyner 0x00000800, 0x00000000, 0x00000000, 0x00000000, 29671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 29971d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30071d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 30371d10453SEric Joyner }; 30471d10453SEric Joyner 30571d10453SEric Joyner /* UDP Packet types for non-tunneled packets or tunneled 30671d10453SEric Joyner * packets with inner UDP. 30771d10453SEric Joyner */ 30871d10453SEric Joyner static const u32 ice_ptypes_udp_il[] = { 30971d10453SEric Joyner 0x81000000, 0x20204040, 0x04000010, 0x80810102, 31071d10453SEric Joyner 0x00000040, 0x00000000, 0x00000000, 0x00000000, 31171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 31771d10453SEric Joyner }; 31871d10453SEric Joyner 31971d10453SEric Joyner /* Packet types for packets with an Innermost/Last TCP header */ 32071d10453SEric Joyner static const u32 ice_ptypes_tcp_il[] = { 32171d10453SEric Joyner 0x04000000, 0x80810102, 0x10000040, 0x02040408, 32271d10453SEric Joyner 0x00000102, 0x00000000, 0x00000000, 0x00000000, 32371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 32971d10453SEric Joyner }; 33071d10453SEric Joyner 33171d10453SEric Joyner /* Packet types for packets with an Innermost/Last SCTP header */ 33271d10453SEric Joyner static const u32 ice_ptypes_sctp_il[] = { 33371d10453SEric Joyner 0x08000000, 0x01020204, 0x20000081, 0x04080810, 33471d10453SEric Joyner 0x00000204, 0x00000000, 0x00000000, 0x00000000, 33571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 33971d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34071d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34171d10453SEric Joyner }; 34271d10453SEric Joyner 34371d10453SEric Joyner /* Packet types for packets with an Outermost/First ICMP header */ 34471d10453SEric Joyner static const u32 ice_ptypes_icmp_of[] = { 34571d10453SEric Joyner 0x10000000, 0x00000000, 0x00000000, 0x00000000, 34671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 34971d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35071d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 35371d10453SEric Joyner }; 35471d10453SEric Joyner 35571d10453SEric Joyner /* Packet types for packets with an Innermost/Last ICMP header */ 35671d10453SEric Joyner static const u32 ice_ptypes_icmp_il[] = { 35771d10453SEric Joyner 0x00000000, 0x02040408, 0x40000102, 0x08101020, 35871d10453SEric Joyner 0x00000408, 0x00000000, 0x00000000, 0x00000000, 35971d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36071d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 36571d10453SEric Joyner }; 36671d10453SEric Joyner 36771d10453SEric Joyner /* Packet types for packets with an Outermost/First GRE header */ 36871d10453SEric Joyner static const u32 ice_ptypes_gre_of[] = { 36971d10453SEric Joyner 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000, 37071d10453SEric Joyner 0x0000017E, 0x00000000, 0x00000000, 0x00000000, 37171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 37771d10453SEric Joyner }; 37871d10453SEric Joyner 37971d10453SEric Joyner /* Packet types for packets with an Innermost/Last MAC header */ 38071d10453SEric Joyner static const u32 ice_ptypes_mac_il[] = { 38171d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38271d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38371d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38471d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38571d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38671d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38771d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38871d10453SEric Joyner 0x00000000, 0x00000000, 0x00000000, 0x00000000, 38971d10453SEric Joyner }; 39071d10453SEric Joyner 39171d10453SEric Joyner /* Manage parameters and info. used during the creation of a flow profile */ 39271d10453SEric Joyner struct ice_flow_prof_params { 39371d10453SEric Joyner enum ice_block blk; 39471d10453SEric Joyner u16 entry_length; /* # of bytes formatted entry will require */ 39571d10453SEric Joyner u8 es_cnt; 39671d10453SEric Joyner struct ice_flow_prof *prof; 39771d10453SEric Joyner 39871d10453SEric Joyner /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 39971d10453SEric Joyner * This will give us the direction flags. 40071d10453SEric Joyner */ 40171d10453SEric Joyner struct ice_fv_word es[ICE_MAX_FV_WORDS]; 4028923de59SPiotr Kubaj 40371d10453SEric Joyner ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX); 40471d10453SEric Joyner }; 40571d10453SEric Joyner 40671d10453SEric Joyner #define ICE_FLOW_SEG_HDRS_L3_MASK \ 4079e54973fSEric Joyner (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) 40871d10453SEric Joyner #define ICE_FLOW_SEG_HDRS_L4_MASK \ 40971d10453SEric Joyner (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 41071d10453SEric Joyner ICE_FLOW_SEG_HDR_SCTP) 4119e54973fSEric Joyner /* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */ 4127d7af7f8SEric Joyner #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \ 4137d7af7f8SEric Joyner (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 41471d10453SEric Joyner 41571d10453SEric Joyner /** 41671d10453SEric Joyner * ice_flow_val_hdrs - validates packet segments for valid protocol headers 41771d10453SEric Joyner * @segs: array of one or more packet segments that describe the flow 41871d10453SEric Joyner * @segs_cnt: number of packet segments provided 41971d10453SEric Joyner */ 420*f2635e84SEric Joyner static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 42171d10453SEric Joyner { 42271d10453SEric Joyner u8 i; 42371d10453SEric Joyner 42471d10453SEric Joyner for (i = 0; i < segs_cnt; i++) { 42571d10453SEric Joyner /* Multiple L3 headers */ 42671d10453SEric Joyner if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 42771d10453SEric Joyner !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 42871d10453SEric Joyner return ICE_ERR_PARAM; 42971d10453SEric Joyner 43071d10453SEric Joyner /* Multiple L4 headers */ 43171d10453SEric Joyner if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 43271d10453SEric Joyner !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 43371d10453SEric Joyner return ICE_ERR_PARAM; 43471d10453SEric Joyner } 43571d10453SEric Joyner 436*f2635e84SEric Joyner return 0; 43771d10453SEric Joyner } 43871d10453SEric Joyner 43971d10453SEric Joyner /** 44071d10453SEric Joyner * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 44171d10453SEric Joyner * @params: information about the flow to be processed 44271d10453SEric Joyner * 44371d10453SEric Joyner * This function identifies the packet types associated with the protocol 44471d10453SEric Joyner * headers being present in packet segments of the specified flow profile. 44571d10453SEric Joyner */ 446*f2635e84SEric Joyner static int 44771d10453SEric Joyner ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 44871d10453SEric Joyner { 44971d10453SEric Joyner struct ice_flow_prof *prof; 45071d10453SEric Joyner u8 i; 45171d10453SEric Joyner 45271d10453SEric Joyner ice_memset(params->ptypes, 0xff, sizeof(params->ptypes), 45371d10453SEric Joyner ICE_NONDMA_MEM); 45471d10453SEric Joyner 45571d10453SEric Joyner prof = params->prof; 45671d10453SEric Joyner 45771d10453SEric Joyner for (i = 0; i < params->prof->segs_cnt; i++) { 45871d10453SEric Joyner const ice_bitmap_t *src; 45971d10453SEric Joyner u32 hdrs; 46071d10453SEric Joyner 46171d10453SEric Joyner hdrs = prof->segs[i].hdrs; 46271d10453SEric Joyner 46371d10453SEric Joyner if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 46471d10453SEric Joyner src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos : 46571d10453SEric Joyner (const ice_bitmap_t *)ice_ptypes_mac_il; 46671d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 46771d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 46871d10453SEric Joyner } 46971d10453SEric Joyner 47071d10453SEric Joyner if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 47171d10453SEric Joyner src = (const ice_bitmap_t *)ice_ptypes_macvlan_il; 47271d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 47371d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 47471d10453SEric Joyner } 47571d10453SEric Joyner 47671d10453SEric Joyner if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 47771d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, 47871d10453SEric Joyner (const ice_bitmap_t *)ice_ptypes_arp_of, 47971d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 48071d10453SEric Joyner } 48171d10453SEric Joyner 4827d7af7f8SEric Joyner if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 4837d7af7f8SEric Joyner (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 4849e54973fSEric Joyner src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il : 4857d7af7f8SEric Joyner (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all; 4867d7af7f8SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 4877d7af7f8SEric Joyner ICE_FLOW_PTYPE_MAX); 4887d7af7f8SEric Joyner } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 4897d7af7f8SEric Joyner (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 4909e54973fSEric Joyner src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il : 4917d7af7f8SEric Joyner (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all; 4927d7af7f8SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 4937d7af7f8SEric Joyner ICE_FLOW_PTYPE_MAX); 4947d7af7f8SEric Joyner } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 4957d7af7f8SEric Joyner !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 496d08b8680SEric Joyner src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 : 497d08b8680SEric Joyner (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4; 4987d7af7f8SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 4997d7af7f8SEric Joyner ICE_FLOW_PTYPE_MAX); 5007d7af7f8SEric Joyner } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 50171d10453SEric Joyner src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos : 50271d10453SEric Joyner (const ice_bitmap_t *)ice_ptypes_ipv4_il; 50371d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 50471d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 5057d7af7f8SEric Joyner } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 5067d7af7f8SEric Joyner !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 507d08b8680SEric Joyner src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 : 508d08b8680SEric Joyner (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4; 5097d7af7f8SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 5107d7af7f8SEric Joyner ICE_FLOW_PTYPE_MAX); 51171d10453SEric Joyner } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 51271d10453SEric Joyner src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos : 51371d10453SEric Joyner (const ice_bitmap_t *)ice_ptypes_ipv6_il; 51471d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 51571d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 51671d10453SEric Joyner } 51771d10453SEric Joyner 5187d7af7f8SEric Joyner if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 51971d10453SEric Joyner src = (const ice_bitmap_t *)ice_ptypes_udp_il; 52071d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 52171d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 52271d10453SEric Joyner } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 52371d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, 52471d10453SEric Joyner (const ice_bitmap_t *)ice_ptypes_tcp_il, 52571d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 52671d10453SEric Joyner } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 52771d10453SEric Joyner src = (const ice_bitmap_t *)ice_ptypes_sctp_il; 52871d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 52971d10453SEric Joyner ICE_FLOW_PTYPE_MAX); 5307d7af7f8SEric Joyner } 5317d7af7f8SEric Joyner 5327d7af7f8SEric Joyner if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 5337d7af7f8SEric Joyner src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of : 5347d7af7f8SEric Joyner (const ice_bitmap_t *)ice_ptypes_icmp_il; 5357d7af7f8SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, src, 5367d7af7f8SEric Joyner ICE_FLOW_PTYPE_MAX); 53771d10453SEric Joyner } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 53871d10453SEric Joyner if (!i) { 53971d10453SEric Joyner src = (const ice_bitmap_t *)ice_ptypes_gre_of; 54071d10453SEric Joyner ice_and_bitmap(params->ptypes, params->ptypes, 54171d10453SEric Joyner src, ICE_FLOW_PTYPE_MAX); 54271d10453SEric Joyner } 54371d10453SEric Joyner } 54471d10453SEric Joyner } 54571d10453SEric Joyner 546*f2635e84SEric Joyner return 0; 54771d10453SEric Joyner } 54871d10453SEric Joyner 549*f2635e84SEric Joyner /* 55071d10453SEric Joyner * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 55171d10453SEric Joyner * @hw: pointer to the HW struct 55271d10453SEric Joyner * @params: information about the flow to be processed 55371d10453SEric Joyner * @seg: packet segment index of the field to be extracted 55471d10453SEric Joyner * @fld: ID of field to be extracted 55571d10453SEric Joyner * 55671d10453SEric Joyner * This function determines the protocol ID, offset, and size of the given 55771d10453SEric Joyner * field. It then allocates one or more extraction sequence entries for the 55871d10453SEric Joyner * given field, and fill the entries with protocol ID and offset information. 55971d10453SEric Joyner */ 560*f2635e84SEric Joyner static int 56171d10453SEric Joyner ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 56271d10453SEric Joyner u8 seg, enum ice_flow_field fld) 56371d10453SEric Joyner { 56471d10453SEric Joyner enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 5658923de59SPiotr Kubaj u8 fv_words = (u8)hw->blk[params->blk].es.fvw; 56671d10453SEric Joyner enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 56771d10453SEric Joyner struct ice_flow_fld_info *flds; 56871d10453SEric Joyner u16 cnt, ese_bits, i; 56971d10453SEric Joyner u16 off; 57071d10453SEric Joyner 57171d10453SEric Joyner flds = params->prof->segs[seg].fields; 57271d10453SEric Joyner 57371d10453SEric Joyner switch (fld) { 57471d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ETH_DA: 57571d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ETH_SA: 57671d10453SEric Joyner case ICE_FLOW_FIELD_IDX_S_VLAN: 57771d10453SEric Joyner case ICE_FLOW_FIELD_IDX_C_VLAN: 57871d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 57971d10453SEric Joyner break; 58071d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ETH_TYPE: 58171d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 58271d10453SEric Joyner break; 58371d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV4_DSCP: 58471d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 58571d10453SEric Joyner break; 58671d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV6_DSCP: 58771d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 58871d10453SEric Joyner break; 58971d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV4_TTL: 59071d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV4_PROT: 59171d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 59271d10453SEric Joyner /* TTL and PROT share the same extraction seq. entry. 59371d10453SEric Joyner * Each is considered a sibling to the other in terms of sharing 59471d10453SEric Joyner * the same extraction sequence entry. 59571d10453SEric Joyner */ 59671d10453SEric Joyner if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) 59771d10453SEric Joyner sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; 598d08b8680SEric Joyner else 59971d10453SEric Joyner sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; 60071d10453SEric Joyner break; 60171d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV6_TTL: 60271d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV6_PROT: 60371d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 60471d10453SEric Joyner /* TTL and PROT share the same extraction seq. entry. 60571d10453SEric Joyner * Each is considered a sibling to the other in terms of sharing 60671d10453SEric Joyner * the same extraction sequence entry. 60771d10453SEric Joyner */ 60871d10453SEric Joyner if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) 60971d10453SEric Joyner sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; 610d08b8680SEric Joyner else 61171d10453SEric Joyner sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; 61271d10453SEric Joyner break; 61371d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV4_SA: 61471d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV4_DA: 61571d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 61671d10453SEric Joyner break; 61771d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV6_SA: 61871d10453SEric Joyner case ICE_FLOW_FIELD_IDX_IPV6_DA: 61971d10453SEric Joyner prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 62071d10453SEric Joyner break; 62171d10453SEric Joyner case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 62271d10453SEric Joyner case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 62371d10453SEric Joyner case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 62471d10453SEric Joyner prot_id = ICE_PROT_TCP_IL; 62571d10453SEric Joyner break; 62671d10453SEric Joyner case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 62771d10453SEric Joyner case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 62871d10453SEric Joyner prot_id = ICE_PROT_UDP_IL_OR_S; 62971d10453SEric Joyner break; 63071d10453SEric Joyner case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 63171d10453SEric Joyner case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 63271d10453SEric Joyner prot_id = ICE_PROT_SCTP_IL; 63371d10453SEric Joyner break; 63471d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ARP_SIP: 63571d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ARP_DIP: 63671d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ARP_SHA: 63771d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ARP_DHA: 63871d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ARP_OP: 63971d10453SEric Joyner prot_id = ICE_PROT_ARP_OF; 64071d10453SEric Joyner break; 64171d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 64271d10453SEric Joyner case ICE_FLOW_FIELD_IDX_ICMP_CODE: 64371d10453SEric Joyner /* ICMP type and code share the same extraction seq. entry */ 6449e54973fSEric Joyner prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ? 64571d10453SEric Joyner ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 64671d10453SEric Joyner sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 64771d10453SEric Joyner ICE_FLOW_FIELD_IDX_ICMP_CODE : 64871d10453SEric Joyner ICE_FLOW_FIELD_IDX_ICMP_TYPE; 64971d10453SEric Joyner break; 65071d10453SEric Joyner case ICE_FLOW_FIELD_IDX_GRE_KEYID: 65171d10453SEric Joyner prot_id = ICE_PROT_GRE_OF; 65271d10453SEric Joyner break; 65371d10453SEric Joyner default: 65471d10453SEric Joyner return ICE_ERR_NOT_IMPL; 65571d10453SEric Joyner } 65671d10453SEric Joyner 65771d10453SEric Joyner /* Each extraction sequence entry is a word in size, and extracts a 65871d10453SEric Joyner * word-aligned offset from a protocol header. 65971d10453SEric Joyner */ 66071d10453SEric Joyner ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 66171d10453SEric Joyner 6628923de59SPiotr Kubaj flds[fld].xtrct.prot_id = (u8)prot_id; 66371d10453SEric Joyner flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 66471d10453SEric Joyner ICE_FLOW_FV_EXTRACT_SZ; 6657d7af7f8SEric Joyner flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 66671d10453SEric Joyner flds[fld].xtrct.idx = params->es_cnt; 66771d10453SEric Joyner 66871d10453SEric Joyner /* Adjust the next field-entry index after accommodating the number of 66971d10453SEric Joyner * entries this field consumes 67071d10453SEric Joyner */ 67171d10453SEric Joyner cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp + 67271d10453SEric Joyner ice_flds_info[fld].size, ese_bits); 67371d10453SEric Joyner 67471d10453SEric Joyner /* Fill in the extraction sequence entries needed for this field */ 67571d10453SEric Joyner off = flds[fld].xtrct.off; 67671d10453SEric Joyner for (i = 0; i < cnt; i++) { 67771d10453SEric Joyner /* Only consume an extraction sequence entry if there is no 67871d10453SEric Joyner * sibling field associated with this field or the sibling entry 67971d10453SEric Joyner * already extracts the word shared with this field. 68071d10453SEric Joyner */ 68171d10453SEric Joyner if (sib == ICE_FLOW_FIELD_IDX_MAX || 68271d10453SEric Joyner flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 68371d10453SEric Joyner flds[sib].xtrct.off != off) { 68471d10453SEric Joyner u8 idx; 68571d10453SEric Joyner 68671d10453SEric Joyner /* Make sure the number of extraction sequence required 68771d10453SEric Joyner * does not exceed the block's capability 68871d10453SEric Joyner */ 68971d10453SEric Joyner if (params->es_cnt >= fv_words) 69071d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 69171d10453SEric Joyner 69271d10453SEric Joyner /* some blocks require a reversed field vector layout */ 69371d10453SEric Joyner if (hw->blk[params->blk].es.reverse) 69471d10453SEric Joyner idx = fv_words - params->es_cnt - 1; 69571d10453SEric Joyner else 69671d10453SEric Joyner idx = params->es_cnt; 69771d10453SEric Joyner 6988923de59SPiotr Kubaj params->es[idx].prot_id = (u8)prot_id; 69971d10453SEric Joyner params->es[idx].off = off; 70071d10453SEric Joyner params->es_cnt++; 70171d10453SEric Joyner } 70271d10453SEric Joyner 70371d10453SEric Joyner off += ICE_FLOW_FV_EXTRACT_SZ; 70471d10453SEric Joyner } 70571d10453SEric Joyner 706*f2635e84SEric Joyner return 0; 70771d10453SEric Joyner } 70871d10453SEric Joyner 70971d10453SEric Joyner /** 71071d10453SEric Joyner * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 71171d10453SEric Joyner * @hw: pointer to the HW struct 71271d10453SEric Joyner * @params: information about the flow to be processed 71371d10453SEric Joyner * 71471d10453SEric Joyner * This function iterates through all matched fields in the given segments, and 71571d10453SEric Joyner * creates an extraction sequence for the fields. 71671d10453SEric Joyner */ 717*f2635e84SEric Joyner static int 71871d10453SEric Joyner ice_flow_create_xtrct_seq(struct ice_hw *hw, 71971d10453SEric Joyner struct ice_flow_prof_params *params) 72071d10453SEric Joyner { 721*f2635e84SEric Joyner int status = 0; 72271d10453SEric Joyner u8 i; 72371d10453SEric Joyner 72471d10453SEric Joyner for (i = 0; i < params->prof->segs_cnt; i++) { 7259c30461dSEric Joyner ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX); 72671d10453SEric Joyner enum ice_flow_field j; 72771d10453SEric Joyner 7289c30461dSEric Joyner ice_cp_bitmap(match, params->prof->segs[i].match, 7299c30461dSEric Joyner ICE_FLOW_FIELD_IDX_MAX); 7309c30461dSEric Joyner ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) { 73171d10453SEric Joyner status = ice_flow_xtract_fld(hw, params, i, j); 73271d10453SEric Joyner if (status) 73371d10453SEric Joyner return status; 7349c30461dSEric Joyner ice_clear_bit(j, match); 73571d10453SEric Joyner } 73671d10453SEric Joyner } 73771d10453SEric Joyner 73871d10453SEric Joyner return status; 73971d10453SEric Joyner } 74071d10453SEric Joyner 74171d10453SEric Joyner /** 74271d10453SEric Joyner * ice_flow_proc_segs - process all packet segments associated with a profile 74371d10453SEric Joyner * @hw: pointer to the HW struct 74471d10453SEric Joyner * @params: information about the flow to be processed 74571d10453SEric Joyner */ 746*f2635e84SEric Joyner static int 74771d10453SEric Joyner ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 74871d10453SEric Joyner { 749*f2635e84SEric Joyner int status; 75071d10453SEric Joyner 75171d10453SEric Joyner status = ice_flow_proc_seg_hdrs(params); 75271d10453SEric Joyner if (status) 75371d10453SEric Joyner return status; 75471d10453SEric Joyner 75571d10453SEric Joyner status = ice_flow_create_xtrct_seq(hw, params); 75671d10453SEric Joyner if (status) 75771d10453SEric Joyner return status; 75871d10453SEric Joyner 75971d10453SEric Joyner switch (params->blk) { 76071d10453SEric Joyner case ICE_BLK_RSS: 761*f2635e84SEric Joyner status = 0; 76271d10453SEric Joyner break; 76371d10453SEric Joyner default: 76471d10453SEric Joyner return ICE_ERR_NOT_IMPL; 76571d10453SEric Joyner } 76671d10453SEric Joyner 76771d10453SEric Joyner return status; 76871d10453SEric Joyner } 76971d10453SEric Joyner 77071d10453SEric Joyner #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 77171d10453SEric Joyner #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 77271d10453SEric Joyner #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 77371d10453SEric Joyner 77471d10453SEric Joyner /** 77571d10453SEric Joyner * ice_flow_find_prof_conds - Find a profile matching headers and conditions 77671d10453SEric Joyner * @hw: pointer to the HW struct 77771d10453SEric Joyner * @blk: classification stage 77871d10453SEric Joyner * @dir: flow direction 77971d10453SEric Joyner * @segs: array of one or more packet segments that describe the flow 78071d10453SEric Joyner * @segs_cnt: number of packet segments provided 78171d10453SEric Joyner * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 78271d10453SEric Joyner * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 78371d10453SEric Joyner */ 78471d10453SEric Joyner static struct ice_flow_prof * 78571d10453SEric Joyner ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 78671d10453SEric Joyner enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 78771d10453SEric Joyner u8 segs_cnt, u16 vsi_handle, u32 conds) 78871d10453SEric Joyner { 78971d10453SEric Joyner struct ice_flow_prof *p, *prof = NULL; 79071d10453SEric Joyner 79171d10453SEric Joyner ice_acquire_lock(&hw->fl_profs_locks[blk]); 7927d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 79371d10453SEric Joyner if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 79471d10453SEric Joyner segs_cnt && segs_cnt == p->segs_cnt) { 79571d10453SEric Joyner u8 i; 79671d10453SEric Joyner 79771d10453SEric Joyner /* Check for profile-VSI association if specified */ 79871d10453SEric Joyner if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 79971d10453SEric Joyner ice_is_vsi_valid(hw, vsi_handle) && 80071d10453SEric Joyner !ice_is_bit_set(p->vsis, vsi_handle)) 80171d10453SEric Joyner continue; 80271d10453SEric Joyner 80371d10453SEric Joyner /* Protocol headers must be checked. Matched fields are 80471d10453SEric Joyner * checked if specified. 80571d10453SEric Joyner */ 80671d10453SEric Joyner for (i = 0; i < segs_cnt; i++) 80771d10453SEric Joyner if (segs[i].hdrs != p->segs[i].hdrs || 80871d10453SEric Joyner ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 8099c30461dSEric Joyner (ice_cmp_bitmap(segs[i].match, 8109c30461dSEric Joyner p->segs[i].match, 8119c30461dSEric Joyner ICE_FLOW_FIELD_IDX_MAX) == 8129c30461dSEric Joyner false))) 81371d10453SEric Joyner break; 81471d10453SEric Joyner 81571d10453SEric Joyner /* A match is found if all segments are matched */ 81671d10453SEric Joyner if (i == segs_cnt) { 81771d10453SEric Joyner prof = p; 81871d10453SEric Joyner break; 81971d10453SEric Joyner } 82071d10453SEric Joyner } 82171d10453SEric Joyner ice_release_lock(&hw->fl_profs_locks[blk]); 82271d10453SEric Joyner 82371d10453SEric Joyner return prof; 82471d10453SEric Joyner } 82571d10453SEric Joyner 82671d10453SEric Joyner /** 82771d10453SEric Joyner * ice_flow_find_prof - Look up a profile matching headers and matched fields 82871d10453SEric Joyner * @hw: pointer to the HW struct 82971d10453SEric Joyner * @blk: classification stage 83071d10453SEric Joyner * @dir: flow direction 83171d10453SEric Joyner * @segs: array of one or more packet segments that describe the flow 83271d10453SEric Joyner * @segs_cnt: number of packet segments provided 83371d10453SEric Joyner */ 83471d10453SEric Joyner u64 83571d10453SEric Joyner ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 83671d10453SEric Joyner struct ice_flow_seg_info *segs, u8 segs_cnt) 83771d10453SEric Joyner { 83871d10453SEric Joyner struct ice_flow_prof *p; 83971d10453SEric Joyner 84071d10453SEric Joyner p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt, 84171d10453SEric Joyner ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS); 84271d10453SEric Joyner 84371d10453SEric Joyner return p ? p->id : ICE_FLOW_PROF_ID_INVAL; 84471d10453SEric Joyner } 84571d10453SEric Joyner 84671d10453SEric Joyner /** 84771d10453SEric Joyner * ice_flow_find_prof_id - Look up a profile with given profile ID 84871d10453SEric Joyner * @hw: pointer to the HW struct 84971d10453SEric Joyner * @blk: classification stage 85071d10453SEric Joyner * @prof_id: unique ID to identify this flow profile 85171d10453SEric Joyner */ 85271d10453SEric Joyner static struct ice_flow_prof * 85371d10453SEric Joyner ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 85471d10453SEric Joyner { 85571d10453SEric Joyner struct ice_flow_prof *p; 85671d10453SEric Joyner 8577d7af7f8SEric Joyner LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 85871d10453SEric Joyner if (p->id == prof_id) 85971d10453SEric Joyner return p; 86071d10453SEric Joyner 86171d10453SEric Joyner return NULL; 86271d10453SEric Joyner } 86371d10453SEric Joyner 86471d10453SEric Joyner /** 8657d7af7f8SEric Joyner * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle 86671d10453SEric Joyner * @hw: pointer to the HW struct 86771d10453SEric Joyner * @blk: classification stage 8687d7af7f8SEric Joyner * @prof_id: the profile ID handle 8697d7af7f8SEric Joyner * @hw_prof_id: pointer to variable to receive the HW profile ID 87071d10453SEric Joyner */ 871*f2635e84SEric Joyner int 8727d7af7f8SEric Joyner ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 8737d7af7f8SEric Joyner u8 *hw_prof_id) 87471d10453SEric Joyner { 8757d7af7f8SEric Joyner struct ice_prof_map *map; 876*f2635e84SEric Joyner int status = ICE_ERR_DOES_NOT_EXIST; 87771d10453SEric Joyner 8787d7af7f8SEric Joyner ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 8797d7af7f8SEric Joyner map = ice_search_prof_id(hw, blk, prof_id); 8807d7af7f8SEric Joyner if (map) { 8817d7af7f8SEric Joyner *hw_prof_id = map->prof_id; 882*f2635e84SEric Joyner status = 0; 8837d7af7f8SEric Joyner } 8847d7af7f8SEric Joyner ice_release_lock(&hw->blk[blk].es.prof_map_lock); 8857d7af7f8SEric Joyner return status; 88671d10453SEric Joyner } 88771d10453SEric Joyner 88871d10453SEric Joyner /** 88971d10453SEric Joyner * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 89071d10453SEric Joyner * @hw: pointer to the HW struct 89171d10453SEric Joyner * @blk: classification stage 89271d10453SEric Joyner * @dir: flow direction 89371d10453SEric Joyner * @prof_id: unique ID to identify this flow profile 89471d10453SEric Joyner * @segs: array of one or more packet segments that describe the flow 89571d10453SEric Joyner * @segs_cnt: number of packet segments provided 89671d10453SEric Joyner * @acts: array of default actions 89771d10453SEric Joyner * @acts_cnt: number of default actions 89871d10453SEric Joyner * @prof: stores the returned flow profile added 89971d10453SEric Joyner * 90071d10453SEric Joyner * Assumption: the caller has acquired the lock to the profile list 90171d10453SEric Joyner */ 902*f2635e84SEric Joyner static int 90371d10453SEric Joyner ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 90471d10453SEric Joyner enum ice_flow_dir dir, u64 prof_id, 90571d10453SEric Joyner struct ice_flow_seg_info *segs, u8 segs_cnt, 90671d10453SEric Joyner struct ice_flow_action *acts, u8 acts_cnt, 90771d10453SEric Joyner struct ice_flow_prof **prof) 90871d10453SEric Joyner { 9097d7af7f8SEric Joyner struct ice_flow_prof_params *params; 910*f2635e84SEric Joyner int status; 91171d10453SEric Joyner u8 i; 91271d10453SEric Joyner 91371d10453SEric Joyner if (!prof || (acts_cnt && !acts)) 91471d10453SEric Joyner return ICE_ERR_BAD_PTR; 91571d10453SEric Joyner 9167d7af7f8SEric Joyner params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params)); 9177d7af7f8SEric Joyner if (!params) 91871d10453SEric Joyner return ICE_ERR_NO_MEMORY; 91971d10453SEric Joyner 9207d7af7f8SEric Joyner params->prof = (struct ice_flow_prof *) 9217d7af7f8SEric Joyner ice_malloc(hw, sizeof(*params->prof)); 9227d7af7f8SEric Joyner if (!params->prof) { 9237d7af7f8SEric Joyner status = ICE_ERR_NO_MEMORY; 9247d7af7f8SEric Joyner goto free_params; 9257d7af7f8SEric Joyner } 9267d7af7f8SEric Joyner 92771d10453SEric Joyner /* initialize extraction sequence to all invalid (0xff) */ 92871d10453SEric Joyner for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 9297d7af7f8SEric Joyner params->es[i].prot_id = ICE_PROT_INVALID; 9307d7af7f8SEric Joyner params->es[i].off = ICE_FV_OFFSET_INVAL; 93171d10453SEric Joyner } 93271d10453SEric Joyner 9337d7af7f8SEric Joyner params->blk = blk; 9347d7af7f8SEric Joyner params->prof->id = prof_id; 9357d7af7f8SEric Joyner params->prof->dir = dir; 9367d7af7f8SEric Joyner params->prof->segs_cnt = segs_cnt; 93771d10453SEric Joyner 93871d10453SEric Joyner /* Make a copy of the segments that need to be persistent in the flow 93971d10453SEric Joyner * profile instance 94071d10453SEric Joyner */ 94171d10453SEric Joyner for (i = 0; i < segs_cnt; i++) 9427d7af7f8SEric Joyner ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs), 94371d10453SEric Joyner ICE_NONDMA_TO_NONDMA); 94471d10453SEric Joyner 9457d7af7f8SEric Joyner status = ice_flow_proc_segs(hw, params); 94671d10453SEric Joyner if (status) { 9477d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 94871d10453SEric Joyner goto out; 94971d10453SEric Joyner } 95071d10453SEric Joyner 95171d10453SEric Joyner /* Add a HW profile for this flow profile */ 9528923de59SPiotr Kubaj status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es); 95371d10453SEric Joyner if (status) { 95471d10453SEric Joyner ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 95571d10453SEric Joyner goto out; 95671d10453SEric Joyner } 95771d10453SEric Joyner 9587d7af7f8SEric Joyner *prof = params->prof; 95971d10453SEric Joyner 96071d10453SEric Joyner out: 96171d10453SEric Joyner if (status) { 9627d7af7f8SEric Joyner ice_free(hw, params->prof); 96371d10453SEric Joyner } 9647d7af7f8SEric Joyner free_params: 9657d7af7f8SEric Joyner ice_free(hw, params); 96671d10453SEric Joyner 96771d10453SEric Joyner return status; 96871d10453SEric Joyner } 96971d10453SEric Joyner 97071d10453SEric Joyner /** 97171d10453SEric Joyner * ice_flow_rem_prof_sync - remove a flow profile 97271d10453SEric Joyner * @hw: pointer to the hardware structure 97371d10453SEric Joyner * @blk: classification stage 97471d10453SEric Joyner * @prof: pointer to flow profile to remove 97571d10453SEric Joyner * 97671d10453SEric Joyner * Assumption: the caller has acquired the lock to the profile list 97771d10453SEric Joyner */ 978*f2635e84SEric Joyner static int 97971d10453SEric Joyner ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 98071d10453SEric Joyner struct ice_flow_prof *prof) 98171d10453SEric Joyner { 982*f2635e84SEric Joyner int status; 98371d10453SEric Joyner 98471d10453SEric Joyner /* Remove all hardware profiles associated with this flow profile */ 98571d10453SEric Joyner status = ice_rem_prof(hw, blk, prof->id); 98671d10453SEric Joyner if (!status) { 98771d10453SEric Joyner LIST_DEL(&prof->l_entry); 98871d10453SEric Joyner ice_free(hw, prof); 98971d10453SEric Joyner } 99071d10453SEric Joyner 99171d10453SEric Joyner return status; 99271d10453SEric Joyner } 99371d10453SEric Joyner 99471d10453SEric Joyner /** 99571d10453SEric Joyner * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG 99671d10453SEric Joyner * @hw: pointer to the hardware structure 99771d10453SEric Joyner * @blk: classification stage 99871d10453SEric Joyner * @vsi_handle: software VSI handle 99971d10453SEric Joyner * @vsig: target VSI group 100071d10453SEric Joyner * 100171d10453SEric Joyner * Assumption: the caller has already verified that the VSI to 100271d10453SEric Joyner * be added has the same characteristics as the VSIG and will 100371d10453SEric Joyner * thereby have access to all resources added to that VSIG. 100471d10453SEric Joyner */ 1005*f2635e84SEric Joyner int 100671d10453SEric Joyner ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle, 100771d10453SEric Joyner u16 vsig) 100871d10453SEric Joyner { 1009*f2635e84SEric Joyner int status; 101071d10453SEric Joyner 101171d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT) 101271d10453SEric Joyner return ICE_ERR_PARAM; 101371d10453SEric Joyner 101471d10453SEric Joyner ice_acquire_lock(&hw->fl_profs_locks[blk]); 101571d10453SEric Joyner status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle), 101671d10453SEric Joyner vsig); 101771d10453SEric Joyner ice_release_lock(&hw->fl_profs_locks[blk]); 101871d10453SEric Joyner 101971d10453SEric Joyner return status; 102071d10453SEric Joyner } 102171d10453SEric Joyner 102271d10453SEric Joyner /** 102371d10453SEric Joyner * ice_flow_assoc_prof - associate a VSI with a flow profile 102471d10453SEric Joyner * @hw: pointer to the hardware structure 102571d10453SEric Joyner * @blk: classification stage 102671d10453SEric Joyner * @prof: pointer to flow profile 102771d10453SEric Joyner * @vsi_handle: software VSI handle 102871d10453SEric Joyner * 102971d10453SEric Joyner * Assumption: the caller has acquired the lock to the profile list 103071d10453SEric Joyner * and the software VSI handle has been validated 103171d10453SEric Joyner */ 1032*f2635e84SEric Joyner static int 103371d10453SEric Joyner ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 103471d10453SEric Joyner struct ice_flow_prof *prof, u16 vsi_handle) 103571d10453SEric Joyner { 1036*f2635e84SEric Joyner int status = 0; 103771d10453SEric Joyner 103871d10453SEric Joyner if (!ice_is_bit_set(prof->vsis, vsi_handle)) { 103971d10453SEric Joyner status = ice_add_prof_id_flow(hw, blk, 104071d10453SEric Joyner ice_get_hw_vsi_num(hw, 104171d10453SEric Joyner vsi_handle), 104271d10453SEric Joyner prof->id); 104371d10453SEric Joyner if (!status) 104471d10453SEric Joyner ice_set_bit(vsi_handle, prof->vsis); 104571d10453SEric Joyner else 10467d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 104771d10453SEric Joyner status); 104871d10453SEric Joyner } 104971d10453SEric Joyner 105071d10453SEric Joyner return status; 105171d10453SEric Joyner } 105271d10453SEric Joyner 105371d10453SEric Joyner /** 105471d10453SEric Joyner * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 105571d10453SEric Joyner * @hw: pointer to the hardware structure 105671d10453SEric Joyner * @blk: classification stage 105771d10453SEric Joyner * @prof: pointer to flow profile 105871d10453SEric Joyner * @vsi_handle: software VSI handle 105971d10453SEric Joyner * 106071d10453SEric Joyner * Assumption: the caller has acquired the lock to the profile list 106171d10453SEric Joyner * and the software VSI handle has been validated 106271d10453SEric Joyner */ 1063*f2635e84SEric Joyner static int 106471d10453SEric Joyner ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 106571d10453SEric Joyner struct ice_flow_prof *prof, u16 vsi_handle) 106671d10453SEric Joyner { 1067*f2635e84SEric Joyner int status = 0; 106871d10453SEric Joyner 106971d10453SEric Joyner if (ice_is_bit_set(prof->vsis, vsi_handle)) { 107071d10453SEric Joyner status = ice_rem_prof_id_flow(hw, blk, 107171d10453SEric Joyner ice_get_hw_vsi_num(hw, 107271d10453SEric Joyner vsi_handle), 107371d10453SEric Joyner prof->id); 107471d10453SEric Joyner if (!status) 107571d10453SEric Joyner ice_clear_bit(vsi_handle, prof->vsis); 107671d10453SEric Joyner else 10777d7af7f8SEric Joyner ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 107871d10453SEric Joyner status); 107971d10453SEric Joyner } 108071d10453SEric Joyner 108171d10453SEric Joyner return status; 108271d10453SEric Joyner } 108371d10453SEric Joyner 108471d10453SEric Joyner /** 108571d10453SEric Joyner * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 108671d10453SEric Joyner * @hw: pointer to the HW struct 108771d10453SEric Joyner * @blk: classification stage 108871d10453SEric Joyner * @dir: flow direction 108971d10453SEric Joyner * @prof_id: unique ID to identify this flow profile 109071d10453SEric Joyner * @segs: array of one or more packet segments that describe the flow 109171d10453SEric Joyner * @segs_cnt: number of packet segments provided 109271d10453SEric Joyner * @acts: array of default actions 109371d10453SEric Joyner * @acts_cnt: number of default actions 109471d10453SEric Joyner * @prof: stores the returned flow profile added 109571d10453SEric Joyner */ 1096*f2635e84SEric Joyner static int 109771d10453SEric Joyner ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 109871d10453SEric Joyner u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 109971d10453SEric Joyner struct ice_flow_action *acts, u8 acts_cnt, 110071d10453SEric Joyner struct ice_flow_prof **prof) 110171d10453SEric Joyner { 1102*f2635e84SEric Joyner int status; 110371d10453SEric Joyner 110471d10453SEric Joyner if (segs_cnt > ICE_FLOW_SEG_MAX) 110571d10453SEric Joyner return ICE_ERR_MAX_LIMIT; 110671d10453SEric Joyner 110771d10453SEric Joyner if (!segs_cnt) 110871d10453SEric Joyner return ICE_ERR_PARAM; 110971d10453SEric Joyner 111071d10453SEric Joyner if (!segs) 111171d10453SEric Joyner return ICE_ERR_BAD_PTR; 111271d10453SEric Joyner 111371d10453SEric Joyner status = ice_flow_val_hdrs(segs, segs_cnt); 111471d10453SEric Joyner if (status) 111571d10453SEric Joyner return status; 111671d10453SEric Joyner 111771d10453SEric Joyner ice_acquire_lock(&hw->fl_profs_locks[blk]); 111871d10453SEric Joyner 111971d10453SEric Joyner status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 112071d10453SEric Joyner acts, acts_cnt, prof); 112171d10453SEric Joyner if (!status) 112271d10453SEric Joyner LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]); 112371d10453SEric Joyner 112471d10453SEric Joyner ice_release_lock(&hw->fl_profs_locks[blk]); 112571d10453SEric Joyner 112671d10453SEric Joyner return status; 112771d10453SEric Joyner } 112871d10453SEric Joyner 112971d10453SEric Joyner /** 113071d10453SEric Joyner * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 113171d10453SEric Joyner * @hw: pointer to the HW struct 113271d10453SEric Joyner * @blk: the block for which the flow profile is to be removed 113371d10453SEric Joyner * @prof_id: unique ID of the flow profile to be removed 113471d10453SEric Joyner */ 1135*f2635e84SEric Joyner static int 113671d10453SEric Joyner ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 113771d10453SEric Joyner { 113871d10453SEric Joyner struct ice_flow_prof *prof; 1139*f2635e84SEric Joyner int status; 114071d10453SEric Joyner 114171d10453SEric Joyner ice_acquire_lock(&hw->fl_profs_locks[blk]); 114271d10453SEric Joyner 114371d10453SEric Joyner prof = ice_flow_find_prof_id(hw, blk, prof_id); 114471d10453SEric Joyner if (!prof) { 114571d10453SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 114671d10453SEric Joyner goto out; 114771d10453SEric Joyner } 114871d10453SEric Joyner 114971d10453SEric Joyner /* prof becomes invalid after the call */ 115071d10453SEric Joyner status = ice_flow_rem_prof_sync(hw, blk, prof); 115171d10453SEric Joyner 115271d10453SEric Joyner out: 115371d10453SEric Joyner ice_release_lock(&hw->fl_profs_locks[blk]); 115471d10453SEric Joyner 115571d10453SEric Joyner return status; 115671d10453SEric Joyner } 115771d10453SEric Joyner 115871d10453SEric Joyner /** 115971d10453SEric Joyner * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 116071d10453SEric Joyner * @seg: packet segment the field being set belongs to 116171d10453SEric Joyner * @fld: field to be set 116271d10453SEric Joyner * @field_type: type of the field 116371d10453SEric Joyner * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 116471d10453SEric Joyner * entry's input buffer 116571d10453SEric Joyner * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 116671d10453SEric Joyner * input buffer 116771d10453SEric Joyner * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 116871d10453SEric Joyner * entry's input buffer 116971d10453SEric Joyner * 117071d10453SEric Joyner * This helper function stores information of a field being matched, including 117171d10453SEric Joyner * the type of the field and the locations of the value to match, the mask, and 11727d7af7f8SEric Joyner * the upper-bound value in the start of the input buffer for a flow entry. 117371d10453SEric Joyner * This function should only be used for fixed-size data structures. 117471d10453SEric Joyner * 117571d10453SEric Joyner * This function also opportunistically determines the protocol headers to be 117671d10453SEric Joyner * present based on the fields being set. Some fields cannot be used alone to 117771d10453SEric Joyner * determine the protocol headers present. Sometimes, fields for particular 117871d10453SEric Joyner * protocol headers are not matched. In those cases, the protocol headers 117971d10453SEric Joyner * must be explicitly set. 118071d10453SEric Joyner */ 118171d10453SEric Joyner static void 118271d10453SEric Joyner ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 118371d10453SEric Joyner enum ice_flow_fld_match_type field_type, u16 val_loc, 118471d10453SEric Joyner u16 mask_loc, u16 last_loc) 118571d10453SEric Joyner { 11869c30461dSEric Joyner ice_set_bit(fld, seg->match); 118771d10453SEric Joyner if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 11889c30461dSEric Joyner ice_set_bit(fld, seg->range); 118971d10453SEric Joyner 119071d10453SEric Joyner seg->fields[fld].type = field_type; 119171d10453SEric Joyner seg->fields[fld].src.val = val_loc; 119271d10453SEric Joyner seg->fields[fld].src.mask = mask_loc; 119371d10453SEric Joyner seg->fields[fld].src.last = last_loc; 119471d10453SEric Joyner 119571d10453SEric Joyner ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 119671d10453SEric Joyner } 119771d10453SEric Joyner 119871d10453SEric Joyner /** 119971d10453SEric Joyner * ice_flow_set_fld - specifies locations of field from entry's input buffer 120071d10453SEric Joyner * @seg: packet segment the field being set belongs to 120171d10453SEric Joyner * @fld: field to be set 120271d10453SEric Joyner * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 120371d10453SEric Joyner * entry's input buffer 120471d10453SEric Joyner * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 120571d10453SEric Joyner * input buffer 120671d10453SEric Joyner * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 120771d10453SEric Joyner * entry's input buffer 120871d10453SEric Joyner * @range: indicate if field being matched is to be in a range 120971d10453SEric Joyner * 121071d10453SEric Joyner * This function specifies the locations, in the form of byte offsets from the 121171d10453SEric Joyner * start of the input buffer for a flow entry, from where the value to match, 121271d10453SEric Joyner * the mask value, and upper value can be extracted. These locations are then 121371d10453SEric Joyner * stored in the flow profile. When adding a flow entry associated with the 121471d10453SEric Joyner * flow profile, these locations will be used to quickly extract the values and 121571d10453SEric Joyner * create the content of a match entry. This function should only be used for 121671d10453SEric Joyner * fixed-size data structures. 121771d10453SEric Joyner */ 12187d7af7f8SEric Joyner static void 121971d10453SEric Joyner ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 122071d10453SEric Joyner u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 122171d10453SEric Joyner { 122271d10453SEric Joyner enum ice_flow_fld_match_type t = range ? 122371d10453SEric Joyner ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 122471d10453SEric Joyner 122571d10453SEric Joyner ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 122671d10453SEric Joyner } 122771d10453SEric Joyner 122871d10453SEric Joyner /** 122971d10453SEric Joyner * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf 123071d10453SEric Joyner * @seg: packet segment the field being set belongs to 123171d10453SEric Joyner * @fld: field to be set 123271d10453SEric Joyner * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 123371d10453SEric Joyner * entry's input buffer 123471d10453SEric Joyner * @pref_loc: location of prefix value from entry's input buffer 123571d10453SEric Joyner * @pref_sz: size of the location holding the prefix value 123671d10453SEric Joyner * 123771d10453SEric Joyner * This function specifies the locations, in the form of byte offsets from the 123871d10453SEric Joyner * start of the input buffer for a flow entry, from where the value to match 123971d10453SEric Joyner * and the IPv4 prefix value can be extracted. These locations are then stored 124071d10453SEric Joyner * in the flow profile. When adding flow entries to the associated flow profile, 124171d10453SEric Joyner * these locations can be used to quickly extract the values to create the 124271d10453SEric Joyner * content of a match entry. This function should only be used for fixed-size 124371d10453SEric Joyner * data structures. 124471d10453SEric Joyner */ 124571d10453SEric Joyner void 124671d10453SEric Joyner ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 124771d10453SEric Joyner u16 val_loc, u16 pref_loc, u8 pref_sz) 124871d10453SEric Joyner { 124971d10453SEric Joyner /* For this type of field, the "mask" location is for the prefix value's 125071d10453SEric Joyner * location and the "last" location is for the size of the location of 125171d10453SEric Joyner * the prefix value. 125271d10453SEric Joyner */ 125371d10453SEric Joyner ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc, 125471d10453SEric Joyner pref_loc, (u16)pref_sz); 125571d10453SEric Joyner } 125671d10453SEric Joyner 125771d10453SEric Joyner #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 125871d10453SEric Joyner (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 125971d10453SEric Joyner 126071d10453SEric Joyner #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 12617d7af7f8SEric Joyner (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 126271d10453SEric Joyner 126371d10453SEric Joyner #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 126471d10453SEric Joyner (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 126571d10453SEric Joyner ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 126671d10453SEric Joyner 126771d10453SEric Joyner /** 126871d10453SEric Joyner * ice_flow_set_rss_seg_info - setup packet segments for RSS 126971d10453SEric Joyner * @segs: pointer to the flow field segment(s) 1270d08b8680SEric Joyner * @seg_cnt: segment count 1271d08b8680SEric Joyner * @cfg: configure parameters 127271d10453SEric Joyner * 127371d10453SEric Joyner * Helper function to extract fields from hash bitmap and use flow 127471d10453SEric Joyner * header value to set flow field segment for further use in flow 127571d10453SEric Joyner * profile entry or removal. 127671d10453SEric Joyner */ 1277*f2635e84SEric Joyner static int 1278d08b8680SEric Joyner ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt, 1279d08b8680SEric Joyner const struct ice_rss_hash_cfg *cfg) 128071d10453SEric Joyner { 1281d08b8680SEric Joyner struct ice_flow_seg_info *seg; 12827d7af7f8SEric Joyner u64 val; 12838923de59SPiotr Kubaj u16 i; 128471d10453SEric Joyner 1285d08b8680SEric Joyner /* set inner most segment */ 1286d08b8680SEric Joyner seg = &segs[seg_cnt - 1]; 1287d08b8680SEric Joyner 1288d08b8680SEric Joyner ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds, 12898923de59SPiotr Kubaj (u16)ICE_FLOW_FIELD_IDX_MAX) 1290d08b8680SEric Joyner ice_flow_set_fld(seg, (enum ice_flow_field)i, 12917d7af7f8SEric Joyner ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 129271d10453SEric Joyner ICE_FLOW_FLD_OFF_INVAL, false); 12937d7af7f8SEric Joyner 1294d08b8680SEric Joyner ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); 129571d10453SEric Joyner 1296d08b8680SEric Joyner /* set outer most header */ 1297d08b8680SEric Joyner if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) 1298d08b8680SEric Joyner segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 129956429daeSEric Joyner ICE_FLOW_SEG_HDR_IPV_FRAG | 1300d08b8680SEric Joyner ICE_FLOW_SEG_HDR_IPV_OTHER; 1301d08b8680SEric Joyner else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) 1302d08b8680SEric Joyner segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 130356429daeSEric Joyner ICE_FLOW_SEG_HDR_IPV_FRAG | 130456429daeSEric Joyner ICE_FLOW_SEG_HDR_IPV_OTHER; 130556429daeSEric Joyner else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE) 130656429daeSEric Joyner segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 130756429daeSEric Joyner ICE_FLOW_SEG_HDR_GRE | 130856429daeSEric Joyner ICE_FLOW_SEG_HDR_IPV_OTHER; 130956429daeSEric Joyner else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE) 131056429daeSEric Joyner segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 131156429daeSEric Joyner ICE_FLOW_SEG_HDR_GRE | 1312d08b8680SEric Joyner ICE_FLOW_SEG_HDR_IPV_OTHER; 1313d08b8680SEric Joyner 1314d08b8680SEric Joyner if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS) 131571d10453SEric Joyner return ICE_ERR_PARAM; 131671d10453SEric Joyner 1317d08b8680SEric Joyner val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 131871d10453SEric Joyner if (val && !ice_is_pow2(val)) 131971d10453SEric Joyner return ICE_ERR_CFG; 132071d10453SEric Joyner 1321d08b8680SEric Joyner val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 132271d10453SEric Joyner if (val && !ice_is_pow2(val)) 132371d10453SEric Joyner return ICE_ERR_CFG; 132471d10453SEric Joyner 1325*f2635e84SEric Joyner return 0; 132671d10453SEric Joyner } 132771d10453SEric Joyner 132871d10453SEric Joyner /** 132971d10453SEric Joyner * ice_rem_vsi_rss_list - remove VSI from RSS list 133071d10453SEric Joyner * @hw: pointer to the hardware structure 133171d10453SEric Joyner * @vsi_handle: software VSI handle 133271d10453SEric Joyner * 133371d10453SEric Joyner * Remove the VSI from all RSS configurations in the list. 133471d10453SEric Joyner */ 133571d10453SEric Joyner void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 133671d10453SEric Joyner { 133771d10453SEric Joyner struct ice_rss_cfg *r, *tmp; 133871d10453SEric Joyner 133971d10453SEric Joyner if (LIST_EMPTY(&hw->rss_list_head)) 134071d10453SEric Joyner return; 134171d10453SEric Joyner 134271d10453SEric Joyner ice_acquire_lock(&hw->rss_locks); 134371d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 13447d7af7f8SEric Joyner ice_rss_cfg, l_entry) 134571d10453SEric Joyner if (ice_test_and_clear_bit(vsi_handle, r->vsis)) 134671d10453SEric Joyner if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 134771d10453SEric Joyner LIST_DEL(&r->l_entry); 134871d10453SEric Joyner ice_free(hw, r); 134971d10453SEric Joyner } 135071d10453SEric Joyner ice_release_lock(&hw->rss_locks); 135171d10453SEric Joyner } 135271d10453SEric Joyner 135371d10453SEric Joyner /** 135471d10453SEric Joyner * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 135571d10453SEric Joyner * @hw: pointer to the hardware structure 135671d10453SEric Joyner * @vsi_handle: software VSI handle 135771d10453SEric Joyner * 135871d10453SEric Joyner * This function will iterate through all flow profiles and disassociate 135971d10453SEric Joyner * the VSI from that profile. If the flow profile has no VSIs it will 136071d10453SEric Joyner * be removed. 136171d10453SEric Joyner */ 1362*f2635e84SEric Joyner int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 136371d10453SEric Joyner { 136471d10453SEric Joyner const enum ice_block blk = ICE_BLK_RSS; 136571d10453SEric Joyner struct ice_flow_prof *p, *t; 1366*f2635e84SEric Joyner int status = 0; 13679dc2f6e2SEric Joyner u16 vsig; 136871d10453SEric Joyner 136971d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle)) 137071d10453SEric Joyner return ICE_ERR_PARAM; 137171d10453SEric Joyner 137271d10453SEric Joyner if (LIST_EMPTY(&hw->fl_profs[blk])) 1373*f2635e84SEric Joyner return 0; 137471d10453SEric Joyner 13757d7af7f8SEric Joyner ice_acquire_lock(&hw->rss_locks); 137671d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, 13779dc2f6e2SEric Joyner l_entry) { 13789dc2f6e2SEric Joyner int ret; 13799dc2f6e2SEric Joyner 13809dc2f6e2SEric Joyner /* check if vsig is already removed */ 13819dc2f6e2SEric Joyner ret = ice_vsig_find_vsi(hw, blk, 13829dc2f6e2SEric Joyner ice_get_hw_vsi_num(hw, vsi_handle), 13839dc2f6e2SEric Joyner &vsig); 13849dc2f6e2SEric Joyner if (!ret && !vsig) 13859dc2f6e2SEric Joyner break; 13869dc2f6e2SEric Joyner 138771d10453SEric Joyner if (ice_is_bit_set(p->vsis, vsi_handle)) { 138871d10453SEric Joyner status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 138971d10453SEric Joyner if (status) 139071d10453SEric Joyner break; 139171d10453SEric Joyner 139271d10453SEric Joyner if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) { 13937d7af7f8SEric Joyner status = ice_flow_rem_prof(hw, blk, p->id); 139471d10453SEric Joyner if (status) 139571d10453SEric Joyner break; 139671d10453SEric Joyner } 139771d10453SEric Joyner } 13989dc2f6e2SEric Joyner } 13997d7af7f8SEric Joyner ice_release_lock(&hw->rss_locks); 140071d10453SEric Joyner 140171d10453SEric Joyner return status; 140271d10453SEric Joyner } 140371d10453SEric Joyner 140471d10453SEric Joyner /** 1405d08b8680SEric Joyner * ice_get_rss_hdr_type - get a RSS profile's header type 1406d08b8680SEric Joyner * @prof: RSS flow profile 1407d08b8680SEric Joyner */ 1408d08b8680SEric Joyner static enum ice_rss_cfg_hdr_type 1409d08b8680SEric Joyner ice_get_rss_hdr_type(struct ice_flow_prof *prof) 1410d08b8680SEric Joyner { 1411d08b8680SEric Joyner enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS; 1412d08b8680SEric Joyner 1413d08b8680SEric Joyner if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { 1414d08b8680SEric Joyner hdr_type = ICE_RSS_OUTER_HEADERS; 1415d08b8680SEric Joyner } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { 14169e54973fSEric Joyner const struct ice_flow_seg_info *s; 14179e54973fSEric Joyner 14189e54973fSEric Joyner s = &prof->segs[ICE_RSS_OUTER_HEADERS]; 14199e54973fSEric Joyner if (s->hdrs == ICE_FLOW_SEG_HDR_NONE) 1420d08b8680SEric Joyner hdr_type = ICE_RSS_INNER_HEADERS; 14219e54973fSEric Joyner if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4) 1422d08b8680SEric Joyner hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; 14239e54973fSEric Joyner if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6) 1424d08b8680SEric Joyner hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; 1425d08b8680SEric Joyner } 1426d08b8680SEric Joyner 1427d08b8680SEric Joyner return hdr_type; 1428d08b8680SEric Joyner } 1429d08b8680SEric Joyner 1430d08b8680SEric Joyner /** 143171d10453SEric Joyner * ice_rem_rss_list - remove RSS configuration from list 143271d10453SEric Joyner * @hw: pointer to the hardware structure 143371d10453SEric Joyner * @vsi_handle: software VSI handle 143471d10453SEric Joyner * @prof: pointer to flow profile 143571d10453SEric Joyner * 143671d10453SEric Joyner * Assumption: lock has already been acquired for RSS list 143771d10453SEric Joyner */ 143871d10453SEric Joyner static void 143971d10453SEric Joyner ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 144071d10453SEric Joyner { 1441d08b8680SEric Joyner enum ice_rss_cfg_hdr_type hdr_type; 144271d10453SEric Joyner struct ice_rss_cfg *r, *tmp; 14439c30461dSEric Joyner u64 seg_match = 0; 14449c30461dSEric Joyner u16 i; 14459c30461dSEric Joyner 14469c30461dSEric Joyner /* convert match bitmap to u64 for hash field comparison */ 14479c30461dSEric Joyner ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match, 14489c30461dSEric Joyner ICE_FLOW_FIELD_IDX_MAX) { 14499c30461dSEric Joyner seg_match |= 1ULL << i; 14509c30461dSEric Joyner } 145171d10453SEric Joyner 145271d10453SEric Joyner /* Search for RSS hash fields associated to the VSI that match the 145371d10453SEric Joyner * hash configurations associated to the flow profile. If found 145471d10453SEric Joyner * remove from the RSS entry list of the VSI context and delete entry. 145571d10453SEric Joyner */ 1456d08b8680SEric Joyner hdr_type = ice_get_rss_hdr_type(prof); 145771d10453SEric Joyner LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 14587d7af7f8SEric Joyner ice_rss_cfg, l_entry) 14599c30461dSEric Joyner if (r->hash.hash_flds == seg_match && 1460d08b8680SEric Joyner r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 1461d08b8680SEric Joyner r->hash.hdr_type == hdr_type) { 146271d10453SEric Joyner ice_clear_bit(vsi_handle, r->vsis); 146371d10453SEric Joyner if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 146471d10453SEric Joyner LIST_DEL(&r->l_entry); 146571d10453SEric Joyner ice_free(hw, r); 146671d10453SEric Joyner } 146771d10453SEric Joyner return; 146871d10453SEric Joyner } 146971d10453SEric Joyner } 147071d10453SEric Joyner 147171d10453SEric Joyner /** 147271d10453SEric Joyner * ice_add_rss_list - add RSS configuration to list 147371d10453SEric Joyner * @hw: pointer to the hardware structure 147471d10453SEric Joyner * @vsi_handle: software VSI handle 147571d10453SEric Joyner * @prof: pointer to flow profile 147671d10453SEric Joyner * 147771d10453SEric Joyner * Assumption: lock has already been acquired for RSS list 147871d10453SEric Joyner */ 1479*f2635e84SEric Joyner static int 148071d10453SEric Joyner ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 148171d10453SEric Joyner { 1482d08b8680SEric Joyner enum ice_rss_cfg_hdr_type hdr_type; 148371d10453SEric Joyner struct ice_rss_cfg *r, *rss_cfg; 14849c30461dSEric Joyner u64 seg_match = 0; 14859c30461dSEric Joyner u16 i; 14869c30461dSEric Joyner 14879c30461dSEric Joyner ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match, 14889c30461dSEric Joyner ICE_FLOW_FIELD_IDX_MAX) { 14899c30461dSEric Joyner seg_match |= 1ULL << i; 14909c30461dSEric Joyner } 149171d10453SEric Joyner 1492d08b8680SEric Joyner hdr_type = ice_get_rss_hdr_type(prof); 149371d10453SEric Joyner LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 149471d10453SEric Joyner ice_rss_cfg, l_entry) 14959c30461dSEric Joyner if (r->hash.hash_flds == seg_match && 1496d08b8680SEric Joyner r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 1497d08b8680SEric Joyner r->hash.hdr_type == hdr_type) { 149871d10453SEric Joyner ice_set_bit(vsi_handle, r->vsis); 1499*f2635e84SEric Joyner return 0; 150071d10453SEric Joyner } 150171d10453SEric Joyner 150271d10453SEric Joyner rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); 150371d10453SEric Joyner if (!rss_cfg) 150471d10453SEric Joyner return ICE_ERR_NO_MEMORY; 150571d10453SEric Joyner 15069c30461dSEric Joyner rss_cfg->hash.hash_flds = seg_match; 1507d08b8680SEric Joyner rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; 1508d08b8680SEric Joyner rss_cfg->hash.hdr_type = hdr_type; 1509d08b8680SEric Joyner rss_cfg->hash.symm = prof->cfg.symm; 151071d10453SEric Joyner ice_set_bit(vsi_handle, rss_cfg->vsis); 151171d10453SEric Joyner 151271d10453SEric Joyner LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head); 151371d10453SEric Joyner 1514*f2635e84SEric Joyner return 0; 151571d10453SEric Joyner } 151671d10453SEric Joyner 151771d10453SEric Joyner #define ICE_FLOW_PROF_HASH_S 0 151871d10453SEric Joyner #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 151971d10453SEric Joyner #define ICE_FLOW_PROF_HDR_S 32 152071d10453SEric Joyner #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 1521d08b8680SEric Joyner #define ICE_FLOW_PROF_ENCAP_S 62 1522d08b8680SEric Joyner #define ICE_FLOW_PROF_ENCAP_M (0x3ULL << ICE_FLOW_PROF_ENCAP_S) 152371d10453SEric Joyner 152471d10453SEric Joyner /* Flow profile ID format: 152571d10453SEric Joyner * [0:31] - Packet match fields 1526d08b8680SEric Joyner * [32:61] - Protocol header 1527d08b8680SEric Joyner * [62:63] - Encapsulation flag: 1528d08b8680SEric Joyner * 0 if non-tunneled 1529d08b8680SEric Joyner * 1 if tunneled 15309e54973fSEric Joyner * 2 for tunneled with outer IPv4 15319e54973fSEric Joyner * 3 for tunneled with outer IPv6 153271d10453SEric Joyner */ 1533d08b8680SEric Joyner #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ 15349cf1841cSEric Joyner ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 153571d10453SEric Joyner (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 15369e54973fSEric Joyner (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & \ 15379e54973fSEric Joyner ICE_FLOW_PROF_ENCAP_M))) 153871d10453SEric Joyner 153971d10453SEric Joyner /** 154071d10453SEric Joyner * ice_add_rss_cfg_sync - add an RSS configuration 154171d10453SEric Joyner * @hw: pointer to the hardware structure 154271d10453SEric Joyner * @vsi_handle: software VSI handle 1543d08b8680SEric Joyner * @cfg: configure parameters 154471d10453SEric Joyner * 154571d10453SEric Joyner * Assumption: lock has already been acquired for RSS list 154671d10453SEric Joyner */ 1547*f2635e84SEric Joyner static int 1548d08b8680SEric Joyner ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 1549d08b8680SEric Joyner const struct ice_rss_hash_cfg *cfg) 155071d10453SEric Joyner { 155171d10453SEric Joyner const enum ice_block blk = ICE_BLK_RSS; 155271d10453SEric Joyner struct ice_flow_prof *prof = NULL; 155371d10453SEric Joyner struct ice_flow_seg_info *segs; 1554d08b8680SEric Joyner u8 segs_cnt; 1555*f2635e84SEric Joyner int status; 155671d10453SEric Joyner 1557d08b8680SEric Joyner if (cfg->symm) 155871d10453SEric Joyner return ICE_ERR_PARAM; 155971d10453SEric Joyner 1560d08b8680SEric Joyner segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 15619e54973fSEric Joyner ICE_FLOW_SEG_SINGLE : 15629e54973fSEric Joyner ICE_FLOW_SEG_MAX; 1563d08b8680SEric Joyner 156471d10453SEric Joyner segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 156571d10453SEric Joyner sizeof(*segs)); 156671d10453SEric Joyner if (!segs) 156771d10453SEric Joyner return ICE_ERR_NO_MEMORY; 156871d10453SEric Joyner 156971d10453SEric Joyner /* Construct the packet segment info from the hashed fields */ 1570d08b8680SEric Joyner status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 157171d10453SEric Joyner if (status) 157271d10453SEric Joyner goto exit; 157371d10453SEric Joyner 157471d10453SEric Joyner /* Search for a flow profile that has matching headers, hash fields 157571d10453SEric Joyner * and has the input VSI associated to it. If found, no further 157671d10453SEric Joyner * operations required and exit. 157771d10453SEric Joyner */ 157871d10453SEric Joyner prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 157971d10453SEric Joyner vsi_handle, 158071d10453SEric Joyner ICE_FLOW_FIND_PROF_CHK_FLDS | 158171d10453SEric Joyner ICE_FLOW_FIND_PROF_CHK_VSI); 158271d10453SEric Joyner if (prof) 158371d10453SEric Joyner goto exit; 158471d10453SEric Joyner 158571d10453SEric Joyner /* Check if a flow profile exists with the same protocol headers and 15867d7af7f8SEric Joyner * associated with the input VSI. If so disassociate the VSI from 158771d10453SEric Joyner * this profile. The VSI will be added to a new profile created with 158871d10453SEric Joyner * the protocol header and new hash field configuration. 158971d10453SEric Joyner */ 159071d10453SEric Joyner prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 159171d10453SEric Joyner vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 159271d10453SEric Joyner if (prof) { 159371d10453SEric Joyner status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 159471d10453SEric Joyner if (!status) 159571d10453SEric Joyner ice_rem_rss_list(hw, vsi_handle, prof); 159671d10453SEric Joyner else 159771d10453SEric Joyner goto exit; 159871d10453SEric Joyner 159971d10453SEric Joyner /* Remove profile if it has no VSIs associated */ 160071d10453SEric Joyner if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { 160171d10453SEric Joyner status = ice_flow_rem_prof(hw, blk, prof->id); 160271d10453SEric Joyner if (status) 160371d10453SEric Joyner goto exit; 160471d10453SEric Joyner } 160571d10453SEric Joyner } 160671d10453SEric Joyner 160771d10453SEric Joyner /* Search for a profile that has same match fields only. If this 160871d10453SEric Joyner * exists then associate the VSI to this profile. 160971d10453SEric Joyner */ 161071d10453SEric Joyner prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 161171d10453SEric Joyner vsi_handle, 161271d10453SEric Joyner ICE_FLOW_FIND_PROF_CHK_FLDS); 161371d10453SEric Joyner if (prof) { 161471d10453SEric Joyner status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 161571d10453SEric Joyner if (!status) 161671d10453SEric Joyner status = ice_add_rss_list(hw, vsi_handle, prof); 161771d10453SEric Joyner goto exit; 161871d10453SEric Joyner } 161971d10453SEric Joyner 162071d10453SEric Joyner /* Create a new flow profile with generated profile and packet 162171d10453SEric Joyner * segment information. 162271d10453SEric Joyner */ 162371d10453SEric Joyner status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 1624d08b8680SEric Joyner ICE_FLOW_GEN_PROFID(cfg->hash_flds, 162571d10453SEric Joyner segs[segs_cnt - 1].hdrs, 1626d08b8680SEric Joyner cfg->hdr_type), 162771d10453SEric Joyner segs, segs_cnt, NULL, 0, &prof); 162871d10453SEric Joyner if (status) 162971d10453SEric Joyner goto exit; 163071d10453SEric Joyner 163171d10453SEric Joyner status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 163271d10453SEric Joyner /* If association to a new flow profile failed then this profile can 163371d10453SEric Joyner * be removed. 163471d10453SEric Joyner */ 163571d10453SEric Joyner if (status) { 163671d10453SEric Joyner ice_flow_rem_prof(hw, blk, prof->id); 163771d10453SEric Joyner goto exit; 163871d10453SEric Joyner } 163971d10453SEric Joyner 164071d10453SEric Joyner status = ice_add_rss_list(hw, vsi_handle, prof); 164171d10453SEric Joyner 1642d08b8680SEric Joyner prof->cfg.symm = cfg->symm; 1643d08b8680SEric Joyner 164471d10453SEric Joyner exit: 164571d10453SEric Joyner ice_free(hw, segs); 164671d10453SEric Joyner return status; 164771d10453SEric Joyner } 164871d10453SEric Joyner 164971d10453SEric Joyner /** 165071d10453SEric Joyner * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 165171d10453SEric Joyner * @hw: pointer to the hardware structure 165271d10453SEric Joyner * @vsi_handle: software VSI handle 1653d08b8680SEric Joyner * @cfg: configure parameters 165471d10453SEric Joyner * 165571d10453SEric Joyner * This function will generate a flow profile based on fields associated with 165671d10453SEric Joyner * the input fields to hash on, the flow type and use the VSI number to add 165771d10453SEric Joyner * a flow entry to the profile. 165871d10453SEric Joyner */ 1659*f2635e84SEric Joyner int 1660d08b8680SEric Joyner ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 1661d08b8680SEric Joyner const struct ice_rss_hash_cfg *cfg) 166271d10453SEric Joyner { 1663d08b8680SEric Joyner struct ice_rss_hash_cfg local_cfg; 1664*f2635e84SEric Joyner int status; 166571d10453SEric Joyner 16669e54973fSEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || 16679e54973fSEric Joyner cfg->hdr_type > ICE_RSS_ANY_HEADERS || 1668d08b8680SEric Joyner cfg->hash_flds == ICE_HASH_INVALID) 166971d10453SEric Joyner return ICE_ERR_PARAM; 167071d10453SEric Joyner 16719e54973fSEric Joyner ice_acquire_lock(&hw->rss_locks); 1672d08b8680SEric Joyner local_cfg = *cfg; 1673d08b8680SEric Joyner if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 1674d08b8680SEric Joyner status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1675d08b8680SEric Joyner } else { 1676d08b8680SEric Joyner local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 1677d08b8680SEric Joyner status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1678d08b8680SEric Joyner if (!status) { 1679d08b8680SEric Joyner local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 1680d08b8680SEric Joyner status = ice_add_rss_cfg_sync(hw, vsi_handle, 1681d08b8680SEric Joyner &local_cfg); 1682d08b8680SEric Joyner } 1683d08b8680SEric Joyner } 16849e54973fSEric Joyner ice_release_lock(&hw->rss_locks); 168571d10453SEric Joyner 168671d10453SEric Joyner return status; 168771d10453SEric Joyner } 168871d10453SEric Joyner 168971d10453SEric Joyner /** 169071d10453SEric Joyner * ice_rem_rss_cfg_sync - remove an existing RSS configuration 169171d10453SEric Joyner * @hw: pointer to the hardware structure 169271d10453SEric Joyner * @vsi_handle: software VSI handle 1693d08b8680SEric Joyner * @cfg: configure parameters 169471d10453SEric Joyner * 169571d10453SEric Joyner * Assumption: lock has already been acquired for RSS list 169671d10453SEric Joyner */ 1697*f2635e84SEric Joyner static int 1698d08b8680SEric Joyner ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 1699d08b8680SEric Joyner const struct ice_rss_hash_cfg *cfg) 170071d10453SEric Joyner { 170171d10453SEric Joyner const enum ice_block blk = ICE_BLK_RSS; 170271d10453SEric Joyner struct ice_flow_seg_info *segs; 170371d10453SEric Joyner struct ice_flow_prof *prof; 1704d08b8680SEric Joyner u8 segs_cnt; 1705*f2635e84SEric Joyner int status; 170671d10453SEric Joyner 1707d08b8680SEric Joyner segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 17089e54973fSEric Joyner ICE_FLOW_SEG_SINGLE : 17099e54973fSEric Joyner ICE_FLOW_SEG_MAX; 171071d10453SEric Joyner segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 171171d10453SEric Joyner sizeof(*segs)); 171271d10453SEric Joyner if (!segs) 171371d10453SEric Joyner return ICE_ERR_NO_MEMORY; 171471d10453SEric Joyner 171571d10453SEric Joyner /* Construct the packet segment info from the hashed fields */ 1716d08b8680SEric Joyner status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 171771d10453SEric Joyner if (status) 171871d10453SEric Joyner goto out; 171971d10453SEric Joyner 172071d10453SEric Joyner prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 172171d10453SEric Joyner vsi_handle, 172271d10453SEric Joyner ICE_FLOW_FIND_PROF_CHK_FLDS); 172371d10453SEric Joyner if (!prof) { 172471d10453SEric Joyner status = ICE_ERR_DOES_NOT_EXIST; 172571d10453SEric Joyner goto out; 172671d10453SEric Joyner } 172771d10453SEric Joyner 172871d10453SEric Joyner status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 172971d10453SEric Joyner if (status) 173071d10453SEric Joyner goto out; 173171d10453SEric Joyner 173271d10453SEric Joyner /* Remove RSS configuration from VSI context before deleting 173371d10453SEric Joyner * the flow profile. 173471d10453SEric Joyner */ 173571d10453SEric Joyner ice_rem_rss_list(hw, vsi_handle, prof); 173671d10453SEric Joyner 173771d10453SEric Joyner if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) 173871d10453SEric Joyner status = ice_flow_rem_prof(hw, blk, prof->id); 173971d10453SEric Joyner 174071d10453SEric Joyner out: 174171d10453SEric Joyner ice_free(hw, segs); 174271d10453SEric Joyner return status; 174371d10453SEric Joyner } 174471d10453SEric Joyner 174571d10453SEric Joyner /** 174671d10453SEric Joyner * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 174771d10453SEric Joyner * @hw: pointer to the hardware structure 174871d10453SEric Joyner * @vsi_handle: software VSI handle 1749d08b8680SEric Joyner * @cfg: configure parameters 175071d10453SEric Joyner * 175171d10453SEric Joyner * This function will lookup the flow profile based on the input 175271d10453SEric Joyner * hash field bitmap, iterate through the profile entry list of 175371d10453SEric Joyner * that profile and find entry associated with input VSI to be 175471d10453SEric Joyner * removed. Calls are made to underlying flow apis which will in 175571d10453SEric Joyner * turn build or update buffers for RSS XLT1 section. 175671d10453SEric Joyner */ 1757*f2635e84SEric Joyner int 1758d08b8680SEric Joyner ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 1759d08b8680SEric Joyner const struct ice_rss_hash_cfg *cfg) 176071d10453SEric Joyner { 1761d08b8680SEric Joyner struct ice_rss_hash_cfg local_cfg; 1762*f2635e84SEric Joyner int status; 176371d10453SEric Joyner 17649e54973fSEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || 17659e54973fSEric Joyner cfg->hdr_type > ICE_RSS_ANY_HEADERS || 1766d08b8680SEric Joyner cfg->hash_flds == ICE_HASH_INVALID) 176771d10453SEric Joyner return ICE_ERR_PARAM; 176871d10453SEric Joyner 176971d10453SEric Joyner ice_acquire_lock(&hw->rss_locks); 1770d08b8680SEric Joyner local_cfg = *cfg; 1771d08b8680SEric Joyner if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 1772d08b8680SEric Joyner status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1773d08b8680SEric Joyner } else { 1774d08b8680SEric Joyner local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 1775d08b8680SEric Joyner status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1776d08b8680SEric Joyner if (!status) { 1777d08b8680SEric Joyner local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 1778d08b8680SEric Joyner status = ice_rem_rss_cfg_sync(hw, vsi_handle, 1779d08b8680SEric Joyner &local_cfg); 1780d08b8680SEric Joyner } 1781d08b8680SEric Joyner } 178271d10453SEric Joyner ice_release_lock(&hw->rss_locks); 178371d10453SEric Joyner 178471d10453SEric Joyner return status; 178571d10453SEric Joyner } 178671d10453SEric Joyner 178771d10453SEric Joyner /* Mapping of AVF hash bit fields to an L3-L4 hash combination. 178871d10453SEric Joyner * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, 178971d10453SEric Joyner * convert its values to their appropriate flow L3, L4 values. 179071d10453SEric Joyner */ 179171d10453SEric Joyner #define ICE_FLOW_AVF_RSS_IPV4_MASKS \ 179271d10453SEric Joyner (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ 179371d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) 179471d10453SEric Joyner #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ 179571d10453SEric Joyner (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ 179671d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) 179771d10453SEric Joyner #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ 179871d10453SEric Joyner (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ 179971d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ 180071d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) 180171d10453SEric Joyner #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ 180271d10453SEric Joyner (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ 180371d10453SEric Joyner ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) 180471d10453SEric Joyner 180571d10453SEric Joyner #define ICE_FLOW_AVF_RSS_IPV6_MASKS \ 180671d10453SEric Joyner (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ 180771d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) 180871d10453SEric Joyner #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ 180971d10453SEric Joyner (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ 181071d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ 181171d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) 181271d10453SEric Joyner #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ 181371d10453SEric Joyner (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ 181471d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) 181571d10453SEric Joyner #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ 181671d10453SEric Joyner (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ 181771d10453SEric Joyner ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) 181871d10453SEric Joyner 181971d10453SEric Joyner /** 182071d10453SEric Joyner * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver 182171d10453SEric Joyner * @hw: pointer to the hardware structure 182271d10453SEric Joyner * @vsi_handle: software VSI handle 182371d10453SEric Joyner * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure 182471d10453SEric Joyner * 182571d10453SEric Joyner * This function will take the hash bitmap provided by the AVF driver via a 182671d10453SEric Joyner * message, convert it to ICE-compatible values, and configure RSS flow 182771d10453SEric Joyner * profiles. 182871d10453SEric Joyner */ 1829*f2635e84SEric Joyner int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) 183071d10453SEric Joyner { 1831d08b8680SEric Joyner struct ice_rss_hash_cfg hcfg; 1832*f2635e84SEric Joyner int status = 0; 183371d10453SEric Joyner u64 hash_flds; 183471d10453SEric Joyner 183571d10453SEric Joyner if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || 183671d10453SEric Joyner !ice_is_vsi_valid(hw, vsi_handle)) 183771d10453SEric Joyner return ICE_ERR_PARAM; 183871d10453SEric Joyner 183971d10453SEric Joyner /* Make sure no unsupported bits are specified */ 184071d10453SEric Joyner if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | 184171d10453SEric Joyner ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) 184271d10453SEric Joyner return ICE_ERR_CFG; 184371d10453SEric Joyner 184471d10453SEric Joyner hash_flds = avf_hash; 184571d10453SEric Joyner 184671d10453SEric Joyner /* Always create an L3 RSS configuration for any L4 RSS configuration */ 184771d10453SEric Joyner if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) 184871d10453SEric Joyner hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; 184971d10453SEric Joyner 185071d10453SEric Joyner if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) 185171d10453SEric Joyner hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; 185271d10453SEric Joyner 185371d10453SEric Joyner /* Create the corresponding RSS configuration for each valid hash bit */ 185471d10453SEric Joyner while (hash_flds) { 185571d10453SEric Joyner u64 rss_hash = ICE_HASH_INVALID; 185671d10453SEric Joyner 185771d10453SEric Joyner if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { 185871d10453SEric Joyner if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { 185971d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV4; 186071d10453SEric Joyner hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; 186171d10453SEric Joyner } else if (hash_flds & 186271d10453SEric Joyner ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { 186371d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV4 | 186471d10453SEric Joyner ICE_FLOW_HASH_TCP_PORT; 186571d10453SEric Joyner hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; 186671d10453SEric Joyner } else if (hash_flds & 186771d10453SEric Joyner ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { 186871d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV4 | 186971d10453SEric Joyner ICE_FLOW_HASH_UDP_PORT; 187071d10453SEric Joyner hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; 187171d10453SEric Joyner } else if (hash_flds & 187271d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { 187371d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV4 | 187471d10453SEric Joyner ICE_FLOW_HASH_SCTP_PORT; 187571d10453SEric Joyner hash_flds &= 187671d10453SEric Joyner ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); 187771d10453SEric Joyner } 187871d10453SEric Joyner } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { 187971d10453SEric Joyner if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { 188071d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV6; 188171d10453SEric Joyner hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; 188271d10453SEric Joyner } else if (hash_flds & 188371d10453SEric Joyner ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { 188471d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV6 | 188571d10453SEric Joyner ICE_FLOW_HASH_TCP_PORT; 188671d10453SEric Joyner hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; 188771d10453SEric Joyner } else if (hash_flds & 188871d10453SEric Joyner ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { 188971d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV6 | 189071d10453SEric Joyner ICE_FLOW_HASH_UDP_PORT; 189171d10453SEric Joyner hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; 189271d10453SEric Joyner } else if (hash_flds & 189371d10453SEric Joyner BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { 189471d10453SEric Joyner rss_hash = ICE_FLOW_HASH_IPV6 | 189571d10453SEric Joyner ICE_FLOW_HASH_SCTP_PORT; 189671d10453SEric Joyner hash_flds &= 189771d10453SEric Joyner ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); 189871d10453SEric Joyner } 189971d10453SEric Joyner } 190071d10453SEric Joyner 190171d10453SEric Joyner if (rss_hash == ICE_HASH_INVALID) 190271d10453SEric Joyner return ICE_ERR_OUT_OF_RANGE; 190371d10453SEric Joyner 1904d08b8680SEric Joyner hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; 1905d08b8680SEric Joyner hcfg.hash_flds = rss_hash; 1906d08b8680SEric Joyner hcfg.symm = false; 1907d08b8680SEric Joyner hcfg.hdr_type = ICE_RSS_ANY_HEADERS; 1908d08b8680SEric Joyner status = ice_add_rss_cfg(hw, vsi_handle, &hcfg); 190971d10453SEric Joyner if (status) 191071d10453SEric Joyner break; 191171d10453SEric Joyner } 191271d10453SEric Joyner 191371d10453SEric Joyner return status; 191471d10453SEric Joyner } 191571d10453SEric Joyner 191671d10453SEric Joyner /** 191771d10453SEric Joyner * ice_replay_rss_cfg - replay RSS configurations associated with VSI 191871d10453SEric Joyner * @hw: pointer to the hardware structure 191971d10453SEric Joyner * @vsi_handle: software VSI handle 192071d10453SEric Joyner */ 1921*f2635e84SEric Joyner int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 192271d10453SEric Joyner { 192371d10453SEric Joyner struct ice_rss_cfg *r; 1924*f2635e84SEric Joyner int status = 0; 192571d10453SEric Joyner 192671d10453SEric Joyner if (!ice_is_vsi_valid(hw, vsi_handle)) 192771d10453SEric Joyner return ICE_ERR_PARAM; 192871d10453SEric Joyner 192971d10453SEric Joyner ice_acquire_lock(&hw->rss_locks); 193071d10453SEric Joyner LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 193171d10453SEric Joyner ice_rss_cfg, l_entry) { 193271d10453SEric Joyner if (ice_is_bit_set(r->vsis, vsi_handle)) { 1933d08b8680SEric Joyner status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash); 193471d10453SEric Joyner if (status) 193571d10453SEric Joyner break; 193671d10453SEric Joyner } 193771d10453SEric Joyner } 193871d10453SEric Joyner ice_release_lock(&hw->rss_locks); 193971d10453SEric Joyner 194071d10453SEric Joyner return status; 194171d10453SEric Joyner } 194271d10453SEric Joyner 194371d10453SEric Joyner /** 194471d10453SEric Joyner * ice_get_rss_cfg - returns hashed fields for the given header types 194571d10453SEric Joyner * @hw: pointer to the hardware structure 194671d10453SEric Joyner * @vsi_handle: software VSI handle 194771d10453SEric Joyner * @hdrs: protocol header type 194871d10453SEric Joyner * 194971d10453SEric Joyner * This function will return the match fields of the first instance of flow 195071d10453SEric Joyner * profile having the given header types and containing input VSI 195171d10453SEric Joyner */ 195271d10453SEric Joyner u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 195371d10453SEric Joyner { 19547d7af7f8SEric Joyner u64 rss_hash = ICE_HASH_INVALID; 19557d7af7f8SEric Joyner struct ice_rss_cfg *r; 195671d10453SEric Joyner 195771d10453SEric Joyner /* verify if the protocol header is non zero and VSI is valid */ 195871d10453SEric Joyner if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 195971d10453SEric Joyner return ICE_HASH_INVALID; 196071d10453SEric Joyner 196171d10453SEric Joyner ice_acquire_lock(&hw->rss_locks); 196271d10453SEric Joyner LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 196371d10453SEric Joyner ice_rss_cfg, l_entry) 196471d10453SEric Joyner if (ice_is_bit_set(r->vsis, vsi_handle) && 1965d08b8680SEric Joyner r->hash.addl_hdrs == hdrs) { 1966d08b8680SEric Joyner rss_hash = r->hash.hash_flds; 196771d10453SEric Joyner break; 196871d10453SEric Joyner } 196971d10453SEric Joyner ice_release_lock(&hw->rss_locks); 197071d10453SEric Joyner 19717d7af7f8SEric Joyner return rss_hash; 197271d10453SEric Joyner } 1973