1271651Skargl/* SPDX-License-Identifier: BSD-3-Clause */ 2271651Skargl/* Copyright (c) 2024, Intel Corporation 3271651Skargl * All rights reserved. 4271651Skargl * 5271651Skargl * Redistribution and use in source and binary forms, with or without 6271651Skargl * modification, are permitted provided that the following conditions are met: 7271651Skargl * 8271651Skargl * 1. Redistributions of source code must retain the above copyright notice, 9271651Skargl * this list of conditions and the following disclaimer. 10271651Skargl * 11271651Skargl * 2. Redistributions in binary form must reproduce the above copyright 12271651Skargl * notice, this list of conditions and the following disclaimer in the 13271651Skargl * documentation and/or other materials provided with the distribution. 14271651Skargl * 15271651Skargl * 3. Neither the name of the Intel Corporation nor the names of its 16271651Skargl * contributors may be used to endorse or promote products derived from 17284810Stijl * this software without specific prior written permission. 18271651Skargl * 19271651Skargl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20271651Skargl * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21271651Skargl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22271651Skargl * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23271651Skargl * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24271651Skargl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25271651Skargl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26271651Skargl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27271651Skargl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28271651Skargl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29271651Skargl * POSSIBILITY OF SUCH DAMAGE. 30271651Skargl */ 31271651Skargl 32271651Skargl#include "ice_common.h" 33271651Skargl#include "ice_flow.h" 34271651Skargl 35271651Skargl/* Size of known protocol header fields */ 36271651Skargl#define ICE_FLOW_FLD_SZ_ETH_TYPE 2 37271651Skargl#define ICE_FLOW_FLD_SZ_VLAN 2 38271651Skargl#define ICE_FLOW_FLD_SZ_IPV4_ADDR 4 39271651Skargl#define ICE_FLOW_FLD_SZ_IPV6_ADDR 16 40271651Skargl#define ICE_FLOW_FLD_SZ_IP_DSCP 1 41271651Skargl#define ICE_FLOW_FLD_SZ_IP_TTL 1 42271651Skargl#define ICE_FLOW_FLD_SZ_IP_PROT 1 43271651Skargl#define ICE_FLOW_FLD_SZ_PORT 2 44271651Skargl#define ICE_FLOW_FLD_SZ_TCP_FLAGS 1 45271651Skargl#define ICE_FLOW_FLD_SZ_ICMP_TYPE 1 46271651Skargl#define ICE_FLOW_FLD_SZ_ICMP_CODE 1 47271651Skargl#define ICE_FLOW_FLD_SZ_ARP_OPER 2 48271651Skargl#define ICE_FLOW_FLD_SZ_GRE_KEYID 4 49271651Skargl 50271651Skargl/* Describe properties of a protocol header field */ 51271651Skarglstruct ice_flow_field_info { 52271651Skargl enum ice_flow_seg_hdr hdr; 53271651Skargl s16 off; /* Offset from start of a protocol header, in bits */ 54271651Skargl u16 size; /* Size of fields in bits */ 55271651Skargl}; 56271651Skargl 57271651Skargl#define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 58271651Skargl .hdr = _hdr, \ 59271651Skargl .off = (_offset_bytes) * BITS_PER_BYTE, \ 60271651Skargl .size = (_size_bytes) * BITS_PER_BYTE, \ 61271651Skargl} 62271651Skargl 63271651Skargl/* Table containing properties of supported protocol header fields */ 64271651Skarglstatic const 65271651Skarglstruct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 66271651Skargl /* Ether */ 67271651Skargl /* ICE_FLOW_FIELD_IDX_ETH_DA */ 68271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), 69271651Skargl /* ICE_FLOW_FIELD_IDX_ETH_SA */ 70271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), 71271651Skargl /* ICE_FLOW_FIELD_IDX_S_VLAN */ 72271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN), 73271651Skargl /* ICE_FLOW_FIELD_IDX_C_VLAN */ 74271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN), 75271651Skargl /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 76271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE), 77271651Skargl /* IPv4 / IPv6 */ 78271651Skargl /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ 79271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, ICE_FLOW_FLD_SZ_IP_DSCP), 80271651Skargl /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ 81271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP), 82271651Skargl /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ 83271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, ICE_FLOW_FLD_SZ_IP_TTL), 84271651Skargl /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 85271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT), 86271651Skargl /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ 87271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 7, ICE_FLOW_FLD_SZ_IP_TTL), 88271651Skargl /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 89271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 6, ICE_FLOW_FLD_SZ_IP_PROT), 90271651Skargl /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 91271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR), 92271651Skargl /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 93271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR), 94271651Skargl /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 95271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR), 96271651Skargl /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 97271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR), 98271651Skargl /* Transport */ 99271651Skargl /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 100271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT), 101271651Skargl /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 102271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT), 103271651Skargl /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 104271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT), 105271651Skargl /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 106271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT), 107271651Skargl /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 108271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT), 109271651Skargl /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 110271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT), 111271651Skargl /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 112271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS), 113271651Skargl /* ARP */ 114271651Skargl /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 115271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR), 116271651Skargl /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 117271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR), 118271651Skargl /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 119271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), 120271651Skargl /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 121271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), 122271651Skargl /* ICE_FLOW_FIELD_IDX_ARP_OP */ 123271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER), 124271651Skargl /* ICMP */ 125271651Skargl /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 126271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE), 127271651Skargl /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 128271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE), 129271651Skargl /* GRE */ 130271651Skargl /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 131271651Skargl ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID), 132271651Skargl}; 133271651Skargl 134271651Skargl/* Bitmaps indicating relevant packet types for a particular protocol header 135271651Skargl * 136271651Skargl * Packet types for packets with an Outer/First/Single MAC header 137271651Skargl */ 138271651Skarglstatic const u32 ice_ptypes_mac_ofos[] = { 139271651Skargl 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, 140271651Skargl 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 141271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 142271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 143271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 144271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 145271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 146271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 147271651Skargl}; 148271651Skargl 149271651Skargl/* Packet types for packets with an Innermost/Last MAC VLAN header */ 150271651Skarglstatic const u32 ice_ptypes_macvlan_il[] = { 151271651Skargl 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 152271651Skargl 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 153271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 154271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 155271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 156271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 157271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 158271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 159271651Skargl}; 160271651Skargl 161271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv4 header, 162271651Skargl * does NOT include IPV4 other PTYPEs 163271651Skargl */ 164271651Skarglstatic const u32 ice_ptypes_ipv4_ofos[] = { 165271651Skargl 0x1D800000, 0x04000800, 0x00000000, 0x00000000, 166271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 167271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 168271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 169271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 170271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 171271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 172271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 173271651Skargl}; 174271651Skargl 175271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv4 header, 176271651Skargl * includes IPV4 other PTYPEs 177271651Skargl */ 178271651Skarglstatic const u32 ice_ptypes_ipv4_ofos_all[] = { 179271651Skargl 0x1D800000, 0x04000800, 0x00000000, 0x00000000, 180271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 181271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 182271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 183271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 184271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 185271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 186271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 187271651Skargl}; 188271651Skargl 189271651Skargl/* Packet types for packets with an Innermost/Last IPv4 header */ 190271651Skarglstatic const u32 ice_ptypes_ipv4_il[] = { 191271651Skargl 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 192271651Skargl 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 193271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 194271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 195271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 196271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 197271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 198271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 199271651Skargl}; 200271651Skargl 201271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv6 header, 202271651Skargl * does NOT include IVP6 other PTYPEs 203271651Skargl */ 204271651Skarglstatic const u32 ice_ptypes_ipv6_ofos[] = { 205271651Skargl 0x00000000, 0x00000000, 0x76000000, 0x10002000, 206271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 207271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 208271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 209271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 210271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 211271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 212271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 213271651Skargl}; 214271651Skargl 215271651Skargl/* Packet types for packets with an Outer/First/Single non-frag IPv6 header, 216271651Skargl * includes IPV6 other PTYPEs 217271651Skargl */ 218271651Skarglstatic const u32 ice_ptypes_ipv6_ofos_all[] = { 219271651Skargl 0x00000000, 0x00000000, 0x76000000, 0x10002000, 220271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 221284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 222284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 223271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 224271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 225271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 226271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 227271651Skargl}; 228271651Skargl 229271651Skargl/* Packet types for packets with an Innermost/Last IPv6 header */ 230271651Skarglstatic const u32 ice_ptypes_ipv6_il[] = { 231271651Skargl 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 232271651Skargl 0x00000770, 0x00000000, 0x00000000, 0x00000000, 233271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 234271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 235271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 236271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 237271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 238271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 239271651Skargl}; 240271651Skargl 241271651Skargl/* Packet types for packets with an Outer/First/Single 242271651Skargl * non-frag IPv4 header - no L4 243271651Skargl */ 244271651Skarglstatic const u32 ice_ptypes_ipv4_ofos_no_l4[] = { 245284810Stijl 0x10800000, 0x04000800, 0x00000000, 0x00000000, 246271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 247271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 248271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 249271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 250271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 251271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 252271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 253271651Skargl}; 254271651Skargl 255284810Stijl/* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ 256271651Skarglstatic const u32 ice_ptypes_ipv4_il_no_l4[] = { 257271651Skargl 0x60000000, 0x18043008, 0x80000002, 0x6010c021, 258271651Skargl 0x00000008, 0x00000000, 0x00000000, 0x00000000, 259284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 260271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 261284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 262284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 263271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 264271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 265271651Skargl}; 266284810Stijl 267284810Stijl/* Packet types for packets with an Outer/First/Single 268284810Stijl * non-frag IPv6 header - no L4 269284810Stijl */ 270284810Stijlstatic const u32 ice_ptypes_ipv6_ofos_no_l4[] = { 271284810Stijl 0x00000000, 0x00000000, 0x42000000, 0x10002000, 272271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 273284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 274284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 275271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 276284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 277284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 278271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 279271651Skargl}; 280271651Skargl 281271651Skargl/* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ 282271651Skarglstatic const u32 ice_ptypes_ipv6_il_no_l4[] = { 283271651Skargl 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, 284271651Skargl 0x00000430, 0x00000000, 0x00000000, 0x00000000, 285271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 286284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 287284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 288271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 289284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 290284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 291284810Stijl}; 292284810Stijl 293284810Stijl/* Packet types for packets with an Outermost/First ARP header */ 294284810Stijlstatic const u32 ice_ptypes_arp_of[] = { 295284810Stijl 0x00000800, 0x00000000, 0x00000000, 0x00000000, 296284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 297284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 298284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 299284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 300284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 301284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 302284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 303284810Stijl}; 304284810Stijl 305284810Stijl/* UDP Packet types for non-tunneled packets or tunneled 306271651Skargl * packets with inner UDP. 307271651Skargl */ 308284810Stijlstatic const u32 ice_ptypes_udp_il[] = { 309284810Stijl 0x81000000, 0x20204040, 0x04000010, 0x80810102, 310271651Skargl 0x00000040, 0x00000000, 0x00000000, 0x00000000, 311271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 312271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 313271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 314271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 315271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 316271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 317271651Skargl}; 318284810Stijl 319271651Skargl/* Packet types for packets with an Innermost/Last TCP header */ 320271651Skarglstatic const u32 ice_ptypes_tcp_il[] = { 321271651Skargl 0x04000000, 0x80810102, 0x10000040, 0x02040408, 322271651Skargl 0x00000102, 0x00000000, 0x00000000, 0x00000000, 323284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 324271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 325271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 326271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 327284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 328271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 329271651Skargl}; 330284810Stijl 331284810Stijl/* Packet types for packets with an Innermost/Last SCTP header */ 332271651Skarglstatic const u32 ice_ptypes_sctp_il[] = { 333271651Skargl 0x08000000, 0x01020204, 0x20000081, 0x04080810, 334271651Skargl 0x00000204, 0x00000000, 0x00000000, 0x00000000, 335271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 336271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 337271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 338271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 339271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 340271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 341271651Skargl}; 342271651Skargl 343271651Skargl/* Packet types for packets with an Outermost/First ICMP header */ 344271651Skarglstatic const u32 ice_ptypes_icmp_of[] = { 345271651Skargl 0x10000000, 0x00000000, 0x00000000, 0x00000000, 346284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 347284810Stijl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 348271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 349271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 350271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 351271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 352271651Skargl 0x00000000, 0x00000000, 0x00000000, 0x00000000, 353284810Stijl}; 354271651Skargl 355271651Skargl/* Packet types for packets with an Innermost/Last ICMP header */ 356271651Skarglstatic const u32 ice_ptypes_icmp_il[] = { 357271651Skargl 0x00000000, 0x02040408, 0x40000102, 0x08101020, 358271651Skargl 0x00000408, 0x00000000, 0x00000000, 0x00000000, 359 0x00000000, 0x00000000, 0x00000000, 0x00000000, 360 0x00000000, 0x00000000, 0x00000000, 0x00000000, 361 0x00000000, 0x00000000, 0x00000000, 0x00000000, 362 0x00000000, 0x00000000, 0x00000000, 0x00000000, 363 0x00000000, 0x00000000, 0x00000000, 0x00000000, 364 0x00000000, 0x00000000, 0x00000000, 0x00000000, 365}; 366 367/* Packet types for packets with an Outermost/First GRE header */ 368static const u32 ice_ptypes_gre_of[] = { 369 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000, 370 0x0000017E, 0x00000000, 0x00000000, 0x00000000, 371 0x00000000, 0x00000000, 0x00000000, 0x00000000, 372 0x00000000, 0x00000000, 0x00000000, 0x00000000, 373 0x00000000, 0x00000000, 0x00000000, 0x00000000, 374 0x00000000, 0x00000000, 0x00000000, 0x00000000, 375 0x00000000, 0x00000000, 0x00000000, 0x00000000, 376 0x00000000, 0x00000000, 0x00000000, 0x00000000, 377}; 378 379/* Packet types for packets with an Innermost/Last MAC header */ 380static const u32 ice_ptypes_mac_il[] = { 381 0x00000000, 0x00000000, 0x00000000, 0x00000000, 382 0x00000000, 0x00000000, 0x00000000, 0x00000000, 383 0x00000000, 0x00000000, 0x00000000, 0x00000000, 384 0x00000000, 0x00000000, 0x00000000, 0x00000000, 385 0x00000000, 0x00000000, 0x00000000, 0x00000000, 386 0x00000000, 0x00000000, 0x00000000, 0x00000000, 387 0x00000000, 0x00000000, 0x00000000, 0x00000000, 388 0x00000000, 0x00000000, 0x00000000, 0x00000000, 389}; 390 391/* Manage parameters and info. used during the creation of a flow profile */ 392struct ice_flow_prof_params { 393 enum ice_block blk; 394 u16 entry_length; /* # of bytes formatted entry will require */ 395 u8 es_cnt; 396 struct ice_flow_prof *prof; 397 398 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 399 * This will give us the direction flags. 400 */ 401 struct ice_fv_word es[ICE_MAX_FV_WORDS]; 402 403 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX); 404}; 405 406#define ICE_FLOW_SEG_HDRS_L3_MASK \ 407 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP) 408#define ICE_FLOW_SEG_HDRS_L4_MASK \ 409 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \ 410 ICE_FLOW_SEG_HDR_SCTP) 411/* mask for L4 protocols that are NOT part of IPv4/6 OTHER PTYPE groups */ 412#define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \ 413 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 414 415/** 416 * ice_flow_val_hdrs - validates packet segments for valid protocol headers 417 * @segs: array of one or more packet segments that describe the flow 418 * @segs_cnt: number of packet segments provided 419 */ 420static enum ice_status 421ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 422{ 423 u8 i; 424 425 for (i = 0; i < segs_cnt; i++) { 426 /* Multiple L3 headers */ 427 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 428 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 429 return ICE_ERR_PARAM; 430 431 /* Multiple L4 headers */ 432 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 433 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 434 return ICE_ERR_PARAM; 435 } 436 437 return ICE_SUCCESS; 438} 439 440/** 441 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 442 * @params: information about the flow to be processed 443 * 444 * This function identifies the packet types associated with the protocol 445 * headers being present in packet segments of the specified flow profile. 446 */ 447static enum ice_status 448ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 449{ 450 struct ice_flow_prof *prof; 451 u8 i; 452 453 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes), 454 ICE_NONDMA_MEM); 455 456 prof = params->prof; 457 458 for (i = 0; i < params->prof->segs_cnt; i++) { 459 const ice_bitmap_t *src; 460 u32 hdrs; 461 462 hdrs = prof->segs[i].hdrs; 463 464 if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 465 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos : 466 (const ice_bitmap_t *)ice_ptypes_mac_il; 467 ice_and_bitmap(params->ptypes, params->ptypes, src, 468 ICE_FLOW_PTYPE_MAX); 469 } 470 471 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 472 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il; 473 ice_and_bitmap(params->ptypes, params->ptypes, src, 474 ICE_FLOW_PTYPE_MAX); 475 } 476 477 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 478 ice_and_bitmap(params->ptypes, params->ptypes, 479 (const ice_bitmap_t *)ice_ptypes_arp_of, 480 ICE_FLOW_PTYPE_MAX); 481 } 482 483 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 484 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 485 src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il : 486 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all; 487 ice_and_bitmap(params->ptypes, params->ptypes, src, 488 ICE_FLOW_PTYPE_MAX); 489 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 490 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 491 src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il : 492 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all; 493 ice_and_bitmap(params->ptypes, params->ptypes, src, 494 ICE_FLOW_PTYPE_MAX); 495 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 496 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 497 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 : 498 (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4; 499 ice_and_bitmap(params->ptypes, params->ptypes, src, 500 ICE_FLOW_PTYPE_MAX); 501 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 502 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos : 503 (const ice_bitmap_t *)ice_ptypes_ipv4_il; 504 ice_and_bitmap(params->ptypes, params->ptypes, src, 505 ICE_FLOW_PTYPE_MAX); 506 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 507 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 508 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 : 509 (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4; 510 ice_and_bitmap(params->ptypes, params->ptypes, src, 511 ICE_FLOW_PTYPE_MAX); 512 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 513 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos : 514 (const ice_bitmap_t *)ice_ptypes_ipv6_il; 515 ice_and_bitmap(params->ptypes, params->ptypes, src, 516 ICE_FLOW_PTYPE_MAX); 517 } 518 519 if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 520 src = (const ice_bitmap_t *)ice_ptypes_udp_il; 521 ice_and_bitmap(params->ptypes, params->ptypes, src, 522 ICE_FLOW_PTYPE_MAX); 523 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 524 ice_and_bitmap(params->ptypes, params->ptypes, 525 (const ice_bitmap_t *)ice_ptypes_tcp_il, 526 ICE_FLOW_PTYPE_MAX); 527 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 528 src = (const ice_bitmap_t *)ice_ptypes_sctp_il; 529 ice_and_bitmap(params->ptypes, params->ptypes, src, 530 ICE_FLOW_PTYPE_MAX); 531 } 532 533 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 534 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of : 535 (const ice_bitmap_t *)ice_ptypes_icmp_il; 536 ice_and_bitmap(params->ptypes, params->ptypes, src, 537 ICE_FLOW_PTYPE_MAX); 538 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 539 if (!i) { 540 src = (const ice_bitmap_t *)ice_ptypes_gre_of; 541 ice_and_bitmap(params->ptypes, params->ptypes, 542 src, ICE_FLOW_PTYPE_MAX); 543 } 544 } 545 } 546 547 return ICE_SUCCESS; 548} 549 550/** 551 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 552 * @hw: pointer to the HW struct 553 * @params: information about the flow to be processed 554 * @seg: packet segment index of the field to be extracted 555 * @fld: ID of field to be extracted 556 * 557 * This function determines the protocol ID, offset, and size of the given 558 * field. It then allocates one or more extraction sequence entries for the 559 * given field, and fill the entries with protocol ID and offset information. 560 */ 561static enum ice_status 562ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 563 u8 seg, enum ice_flow_field fld) 564{ 565 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 566 u8 fv_words = (u8)hw->blk[params->blk].es.fvw; 567 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 568 struct ice_flow_fld_info *flds; 569 u16 cnt, ese_bits, i; 570 u16 off; 571 572 flds = params->prof->segs[seg].fields; 573 574 switch (fld) { 575 case ICE_FLOW_FIELD_IDX_ETH_DA: 576 case ICE_FLOW_FIELD_IDX_ETH_SA: 577 case ICE_FLOW_FIELD_IDX_S_VLAN: 578 case ICE_FLOW_FIELD_IDX_C_VLAN: 579 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 580 break; 581 case ICE_FLOW_FIELD_IDX_ETH_TYPE: 582 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 583 break; 584 case ICE_FLOW_FIELD_IDX_IPV4_DSCP: 585 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 586 break; 587 case ICE_FLOW_FIELD_IDX_IPV6_DSCP: 588 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 589 break; 590 case ICE_FLOW_FIELD_IDX_IPV4_TTL: 591 case ICE_FLOW_FIELD_IDX_IPV4_PROT: 592 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 593 /* TTL and PROT share the same extraction seq. entry. 594 * Each is considered a sibling to the other in terms of sharing 595 * the same extraction sequence entry. 596 */ 597 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) 598 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; 599 else 600 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; 601 break; 602 case ICE_FLOW_FIELD_IDX_IPV6_TTL: 603 case ICE_FLOW_FIELD_IDX_IPV6_PROT: 604 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 605 /* TTL and PROT share the same extraction seq. entry. 606 * Each is considered a sibling to the other in terms of sharing 607 * the same extraction sequence entry. 608 */ 609 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) 610 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; 611 else 612 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; 613 break; 614 case ICE_FLOW_FIELD_IDX_IPV4_SA: 615 case ICE_FLOW_FIELD_IDX_IPV4_DA: 616 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 617 break; 618 case ICE_FLOW_FIELD_IDX_IPV6_SA: 619 case ICE_FLOW_FIELD_IDX_IPV6_DA: 620 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 621 break; 622 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 623 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 624 case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 625 prot_id = ICE_PROT_TCP_IL; 626 break; 627 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 628 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 629 prot_id = ICE_PROT_UDP_IL_OR_S; 630 break; 631 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 632 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 633 prot_id = ICE_PROT_SCTP_IL; 634 break; 635 case ICE_FLOW_FIELD_IDX_ARP_SIP: 636 case ICE_FLOW_FIELD_IDX_ARP_DIP: 637 case ICE_FLOW_FIELD_IDX_ARP_SHA: 638 case ICE_FLOW_FIELD_IDX_ARP_DHA: 639 case ICE_FLOW_FIELD_IDX_ARP_OP: 640 prot_id = ICE_PROT_ARP_OF; 641 break; 642 case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 643 case ICE_FLOW_FIELD_IDX_ICMP_CODE: 644 /* ICMP type and code share the same extraction seq. entry */ 645 prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ? 646 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 647 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 648 ICE_FLOW_FIELD_IDX_ICMP_CODE : 649 ICE_FLOW_FIELD_IDX_ICMP_TYPE; 650 break; 651 case ICE_FLOW_FIELD_IDX_GRE_KEYID: 652 prot_id = ICE_PROT_GRE_OF; 653 break; 654 default: 655 return ICE_ERR_NOT_IMPL; 656 } 657 658 /* Each extraction sequence entry is a word in size, and extracts a 659 * word-aligned offset from a protocol header. 660 */ 661 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 662 663 flds[fld].xtrct.prot_id = (u8)prot_id; 664 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 665 ICE_FLOW_FV_EXTRACT_SZ; 666 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 667 flds[fld].xtrct.idx = params->es_cnt; 668 669 /* Adjust the next field-entry index after accommodating the number of 670 * entries this field consumes 671 */ 672 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp + 673 ice_flds_info[fld].size, ese_bits); 674 675 /* Fill in the extraction sequence entries needed for this field */ 676 off = flds[fld].xtrct.off; 677 for (i = 0; i < cnt; i++) { 678 /* Only consume an extraction sequence entry if there is no 679 * sibling field associated with this field or the sibling entry 680 * already extracts the word shared with this field. 681 */ 682 if (sib == ICE_FLOW_FIELD_IDX_MAX || 683 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 684 flds[sib].xtrct.off != off) { 685 u8 idx; 686 687 /* Make sure the number of extraction sequence required 688 * does not exceed the block's capability 689 */ 690 if (params->es_cnt >= fv_words) 691 return ICE_ERR_MAX_LIMIT; 692 693 /* some blocks require a reversed field vector layout */ 694 if (hw->blk[params->blk].es.reverse) 695 idx = fv_words - params->es_cnt - 1; 696 else 697 idx = params->es_cnt; 698 699 params->es[idx].prot_id = (u8)prot_id; 700 params->es[idx].off = off; 701 params->es_cnt++; 702 } 703 704 off += ICE_FLOW_FV_EXTRACT_SZ; 705 } 706 707 return ICE_SUCCESS; 708} 709 710/** 711 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 712 * @hw: pointer to the HW struct 713 * @params: information about the flow to be processed 714 * 715 * This function iterates through all matched fields in the given segments, and 716 * creates an extraction sequence for the fields. 717 */ 718static enum ice_status 719ice_flow_create_xtrct_seq(struct ice_hw *hw, 720 struct ice_flow_prof_params *params) 721{ 722 enum ice_status status = ICE_SUCCESS; 723 u8 i; 724 725 for (i = 0; i < params->prof->segs_cnt; i++) { 726 ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX); 727 enum ice_flow_field j; 728 729 ice_cp_bitmap(match, params->prof->segs[i].match, 730 ICE_FLOW_FIELD_IDX_MAX); 731 ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) { 732 status = ice_flow_xtract_fld(hw, params, i, j); 733 if (status) 734 return status; 735 ice_clear_bit(j, match); 736 } 737 } 738 739 return status; 740} 741 742/** 743 * ice_flow_proc_segs - process all packet segments associated with a profile 744 * @hw: pointer to the HW struct 745 * @params: information about the flow to be processed 746 */ 747static enum ice_status 748ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 749{ 750 enum ice_status status; 751 752 status = ice_flow_proc_seg_hdrs(params); 753 if (status) 754 return status; 755 756 status = ice_flow_create_xtrct_seq(hw, params); 757 if (status) 758 return status; 759 760 switch (params->blk) { 761 case ICE_BLK_RSS: 762 status = ICE_SUCCESS; 763 break; 764 default: 765 return ICE_ERR_NOT_IMPL; 766 } 767 768 return status; 769} 770 771#define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 772#define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 773#define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 774 775/** 776 * ice_flow_find_prof_conds - Find a profile matching headers and conditions 777 * @hw: pointer to the HW struct 778 * @blk: classification stage 779 * @dir: flow direction 780 * @segs: array of one or more packet segments that describe the flow 781 * @segs_cnt: number of packet segments provided 782 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 783 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 784 */ 785static struct ice_flow_prof * 786ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 787 enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 788 u8 segs_cnt, u16 vsi_handle, u32 conds) 789{ 790 struct ice_flow_prof *p, *prof = NULL; 791 792 ice_acquire_lock(&hw->fl_profs_locks[blk]); 793 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 794 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 795 segs_cnt && segs_cnt == p->segs_cnt) { 796 u8 i; 797 798 /* Check for profile-VSI association if specified */ 799 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 800 ice_is_vsi_valid(hw, vsi_handle) && 801 !ice_is_bit_set(p->vsis, vsi_handle)) 802 continue; 803 804 /* Protocol headers must be checked. Matched fields are 805 * checked if specified. 806 */ 807 for (i = 0; i < segs_cnt; i++) 808 if (segs[i].hdrs != p->segs[i].hdrs || 809 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 810 (ice_cmp_bitmap(segs[i].match, 811 p->segs[i].match, 812 ICE_FLOW_FIELD_IDX_MAX) == 813 false))) 814 break; 815 816 /* A match is found if all segments are matched */ 817 if (i == segs_cnt) { 818 prof = p; 819 break; 820 } 821 } 822 ice_release_lock(&hw->fl_profs_locks[blk]); 823 824 return prof; 825} 826 827/** 828 * ice_flow_find_prof - Look up a profile matching headers and matched fields 829 * @hw: pointer to the HW struct 830 * @blk: classification stage 831 * @dir: flow direction 832 * @segs: array of one or more packet segments that describe the flow 833 * @segs_cnt: number of packet segments provided 834 */ 835u64 836ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 837 struct ice_flow_seg_info *segs, u8 segs_cnt) 838{ 839 struct ice_flow_prof *p; 840 841 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt, 842 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS); 843 844 return p ? p->id : ICE_FLOW_PROF_ID_INVAL; 845} 846 847/** 848 * ice_flow_find_prof_id - Look up a profile with given profile ID 849 * @hw: pointer to the HW struct 850 * @blk: classification stage 851 * @prof_id: unique ID to identify this flow profile 852 */ 853static struct ice_flow_prof * 854ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 855{ 856 struct ice_flow_prof *p; 857 858 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 859 if (p->id == prof_id) 860 return p; 861 862 return NULL; 863} 864 865/** 866 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle 867 * @hw: pointer to the HW struct 868 * @blk: classification stage 869 * @prof_id: the profile ID handle 870 * @hw_prof_id: pointer to variable to receive the HW profile ID 871 */ 872enum ice_status 873ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 874 u8 *hw_prof_id) 875{ 876 enum ice_status status = ICE_ERR_DOES_NOT_EXIST; 877 struct ice_prof_map *map; 878 879 ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 880 map = ice_search_prof_id(hw, blk, prof_id); 881 if (map) { 882 *hw_prof_id = map->prof_id; 883 status = ICE_SUCCESS; 884 } 885 ice_release_lock(&hw->blk[blk].es.prof_map_lock); 886 return status; 887} 888 889/** 890 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 891 * @hw: pointer to the HW struct 892 * @blk: classification stage 893 * @dir: flow direction 894 * @prof_id: unique ID to identify this flow profile 895 * @segs: array of one or more packet segments that describe the flow 896 * @segs_cnt: number of packet segments provided 897 * @acts: array of default actions 898 * @acts_cnt: number of default actions 899 * @prof: stores the returned flow profile added 900 * 901 * Assumption: the caller has acquired the lock to the profile list 902 */ 903static enum ice_status 904ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 905 enum ice_flow_dir dir, u64 prof_id, 906 struct ice_flow_seg_info *segs, u8 segs_cnt, 907 struct ice_flow_action *acts, u8 acts_cnt, 908 struct ice_flow_prof **prof) 909{ 910 struct ice_flow_prof_params *params; 911 enum ice_status status; 912 u8 i; 913 914 if (!prof || (acts_cnt && !acts)) 915 return ICE_ERR_BAD_PTR; 916 917 params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params)); 918 if (!params) 919 return ICE_ERR_NO_MEMORY; 920 921 params->prof = (struct ice_flow_prof *) 922 ice_malloc(hw, sizeof(*params->prof)); 923 if (!params->prof) { 924 status = ICE_ERR_NO_MEMORY; 925 goto free_params; 926 } 927 928 /* initialize extraction sequence to all invalid (0xff) */ 929 for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 930 params->es[i].prot_id = ICE_PROT_INVALID; 931 params->es[i].off = ICE_FV_OFFSET_INVAL; 932 } 933 934 params->blk = blk; 935 params->prof->id = prof_id; 936 params->prof->dir = dir; 937 params->prof->segs_cnt = segs_cnt; 938 939 /* Make a copy of the segments that need to be persistent in the flow 940 * profile instance 941 */ 942 for (i = 0; i < segs_cnt; i++) 943 ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs), 944 ICE_NONDMA_TO_NONDMA); 945 946 status = ice_flow_proc_segs(hw, params); 947 if (status) { 948 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 949 goto out; 950 } 951 952 /* Add a HW profile for this flow profile */ 953 status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es); 954 if (status) { 955 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 956 goto out; 957 } 958 959 *prof = params->prof; 960 961out: 962 if (status) { 963 ice_free(hw, params->prof); 964 } 965free_params: 966 ice_free(hw, params); 967 968 return status; 969} 970 971/** 972 * ice_flow_rem_prof_sync - remove a flow profile 973 * @hw: pointer to the hardware structure 974 * @blk: classification stage 975 * @prof: pointer to flow profile to remove 976 * 977 * Assumption: the caller has acquired the lock to the profile list 978 */ 979static enum ice_status 980ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 981 struct ice_flow_prof *prof) 982{ 983 enum ice_status status; 984 985 /* Remove all hardware profiles associated with this flow profile */ 986 status = ice_rem_prof(hw, blk, prof->id); 987 if (!status) { 988 LIST_DEL(&prof->l_entry); 989 ice_free(hw, prof); 990 } 991 992 return status; 993} 994 995/** 996 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG 997 * @hw: pointer to the hardware structure 998 * @blk: classification stage 999 * @vsi_handle: software VSI handle 1000 * @vsig: target VSI group 1001 * 1002 * Assumption: the caller has already verified that the VSI to 1003 * be added has the same characteristics as the VSIG and will 1004 * thereby have access to all resources added to that VSIG. 1005 */ 1006enum ice_status 1007ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle, 1008 u16 vsig) 1009{ 1010 enum ice_status status; 1011 1012 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT) 1013 return ICE_ERR_PARAM; 1014 1015 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1016 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle), 1017 vsig); 1018 ice_release_lock(&hw->fl_profs_locks[blk]); 1019 1020 return status; 1021} 1022 1023/** 1024 * ice_flow_assoc_prof - associate a VSI with a flow profile 1025 * @hw: pointer to the hardware structure 1026 * @blk: classification stage 1027 * @prof: pointer to flow profile 1028 * @vsi_handle: software VSI handle 1029 * 1030 * Assumption: the caller has acquired the lock to the profile list 1031 * and the software VSI handle has been validated 1032 */ 1033static enum ice_status 1034ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 1035 struct ice_flow_prof *prof, u16 vsi_handle) 1036{ 1037 enum ice_status status = ICE_SUCCESS; 1038 1039 if (!ice_is_bit_set(prof->vsis, vsi_handle)) { 1040 status = ice_add_prof_id_flow(hw, blk, 1041 ice_get_hw_vsi_num(hw, 1042 vsi_handle), 1043 prof->id); 1044 if (!status) 1045 ice_set_bit(vsi_handle, prof->vsis); 1046 else 1047 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 1048 status); 1049 } 1050 1051 return status; 1052} 1053 1054/** 1055 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 1056 * @hw: pointer to the hardware structure 1057 * @blk: classification stage 1058 * @prof: pointer to flow profile 1059 * @vsi_handle: software VSI handle 1060 * 1061 * Assumption: the caller has acquired the lock to the profile list 1062 * and the software VSI handle has been validated 1063 */ 1064static enum ice_status 1065ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 1066 struct ice_flow_prof *prof, u16 vsi_handle) 1067{ 1068 enum ice_status status = ICE_SUCCESS; 1069 1070 if (ice_is_bit_set(prof->vsis, vsi_handle)) { 1071 status = ice_rem_prof_id_flow(hw, blk, 1072 ice_get_hw_vsi_num(hw, 1073 vsi_handle), 1074 prof->id); 1075 if (!status) 1076 ice_clear_bit(vsi_handle, prof->vsis); 1077 else 1078 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 1079 status); 1080 } 1081 1082 return status; 1083} 1084 1085/** 1086 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 1087 * @hw: pointer to the HW struct 1088 * @blk: classification stage 1089 * @dir: flow direction 1090 * @prof_id: unique ID to identify this flow profile 1091 * @segs: array of one or more packet segments that describe the flow 1092 * @segs_cnt: number of packet segments provided 1093 * @acts: array of default actions 1094 * @acts_cnt: number of default actions 1095 * @prof: stores the returned flow profile added 1096 */ 1097static enum ice_status 1098ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 1099 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 1100 struct ice_flow_action *acts, u8 acts_cnt, 1101 struct ice_flow_prof **prof) 1102{ 1103 enum ice_status status; 1104 1105 if (segs_cnt > ICE_FLOW_SEG_MAX) 1106 return ICE_ERR_MAX_LIMIT; 1107 1108 if (!segs_cnt) 1109 return ICE_ERR_PARAM; 1110 1111 if (!segs) 1112 return ICE_ERR_BAD_PTR; 1113 1114 status = ice_flow_val_hdrs(segs, segs_cnt); 1115 if (status) 1116 return status; 1117 1118 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1119 1120 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 1121 acts, acts_cnt, prof); 1122 if (!status) 1123 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]); 1124 1125 ice_release_lock(&hw->fl_profs_locks[blk]); 1126 1127 return status; 1128} 1129 1130/** 1131 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 1132 * @hw: pointer to the HW struct 1133 * @blk: the block for which the flow profile is to be removed 1134 * @prof_id: unique ID of the flow profile to be removed 1135 */ 1136static enum ice_status 1137ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 1138{ 1139 struct ice_flow_prof *prof; 1140 enum ice_status status; 1141 1142 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1143 1144 prof = ice_flow_find_prof_id(hw, blk, prof_id); 1145 if (!prof) { 1146 status = ICE_ERR_DOES_NOT_EXIST; 1147 goto out; 1148 } 1149 1150 /* prof becomes invalid after the call */ 1151 status = ice_flow_rem_prof_sync(hw, blk, prof); 1152 1153out: 1154 ice_release_lock(&hw->fl_profs_locks[blk]); 1155 1156 return status; 1157} 1158 1159/** 1160 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 1161 * @seg: packet segment the field being set belongs to 1162 * @fld: field to be set 1163 * @field_type: type of the field 1164 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1165 * entry's input buffer 1166 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1167 * input buffer 1168 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1169 * entry's input buffer 1170 * 1171 * This helper function stores information of a field being matched, including 1172 * the type of the field and the locations of the value to match, the mask, and 1173 * the upper-bound value in the start of the input buffer for a flow entry. 1174 * This function should only be used for fixed-size data structures. 1175 * 1176 * This function also opportunistically determines the protocol headers to be 1177 * present based on the fields being set. Some fields cannot be used alone to 1178 * determine the protocol headers present. Sometimes, fields for particular 1179 * protocol headers are not matched. In those cases, the protocol headers 1180 * must be explicitly set. 1181 */ 1182static void 1183ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1184 enum ice_flow_fld_match_type field_type, u16 val_loc, 1185 u16 mask_loc, u16 last_loc) 1186{ 1187 ice_set_bit(fld, seg->match); 1188 if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 1189 ice_set_bit(fld, seg->range); 1190 1191 seg->fields[fld].type = field_type; 1192 seg->fields[fld].src.val = val_loc; 1193 seg->fields[fld].src.mask = mask_loc; 1194 seg->fields[fld].src.last = last_loc; 1195 1196 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 1197} 1198 1199/** 1200 * ice_flow_set_fld - specifies locations of field from entry's input buffer 1201 * @seg: packet segment the field being set belongs to 1202 * @fld: field to be set 1203 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1204 * entry's input buffer 1205 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1206 * input buffer 1207 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1208 * entry's input buffer 1209 * @range: indicate if field being matched is to be in a range 1210 * 1211 * This function specifies the locations, in the form of byte offsets from the 1212 * start of the input buffer for a flow entry, from where the value to match, 1213 * the mask value, and upper value can be extracted. These locations are then 1214 * stored in the flow profile. When adding a flow entry associated with the 1215 * flow profile, these locations will be used to quickly extract the values and 1216 * create the content of a match entry. This function should only be used for 1217 * fixed-size data structures. 1218 */ 1219static void 1220ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1221 u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 1222{ 1223 enum ice_flow_fld_match_type t = range ? 1224 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 1225 1226 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 1227} 1228 1229/** 1230 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf 1231 * @seg: packet segment the field being set belongs to 1232 * @fld: field to be set 1233 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1234 * entry's input buffer 1235 * @pref_loc: location of prefix value from entry's input buffer 1236 * @pref_sz: size of the location holding the prefix value 1237 * 1238 * This function specifies the locations, in the form of byte offsets from the 1239 * start of the input buffer for a flow entry, from where the value to match 1240 * and the IPv4 prefix value can be extracted. These locations are then stored 1241 * in the flow profile. When adding flow entries to the associated flow profile, 1242 * these locations can be used to quickly extract the values to create the 1243 * content of a match entry. This function should only be used for fixed-size 1244 * data structures. 1245 */ 1246void 1247ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1248 u16 val_loc, u16 pref_loc, u8 pref_sz) 1249{ 1250 /* For this type of field, the "mask" location is for the prefix value's 1251 * location and the "last" location is for the size of the location of 1252 * the prefix value. 1253 */ 1254 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc, 1255 pref_loc, (u16)pref_sz); 1256} 1257 1258#define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 1259 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 1260 1261#define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 1262 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 1263 1264#define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 1265 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 1266 ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 1267 1268/** 1269 * ice_flow_set_rss_seg_info - setup packet segments for RSS 1270 * @segs: pointer to the flow field segment(s) 1271 * @seg_cnt: segment count 1272 * @cfg: configure parameters 1273 * 1274 * Helper function to extract fields from hash bitmap and use flow 1275 * header value to set flow field segment for further use in flow 1276 * profile entry or removal. 1277 */ 1278static enum ice_status 1279ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt, 1280 const struct ice_rss_hash_cfg *cfg) 1281{ 1282 struct ice_flow_seg_info *seg; 1283 u64 val; 1284 u16 i; 1285 1286 /* set inner most segment */ 1287 seg = &segs[seg_cnt - 1]; 1288 1289 ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds, 1290 (u16)ICE_FLOW_FIELD_IDX_MAX) 1291 ice_flow_set_fld(seg, (enum ice_flow_field)i, 1292 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 1293 ICE_FLOW_FLD_OFF_INVAL, false); 1294 1295 ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); 1296 1297 /* set outer most header */ 1298 if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) 1299 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 1300 ICE_FLOW_SEG_HDR_IPV_FRAG | 1301 ICE_FLOW_SEG_HDR_IPV_OTHER; 1302 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) 1303 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 1304 ICE_FLOW_SEG_HDR_IPV_FRAG | 1305 ICE_FLOW_SEG_HDR_IPV_OTHER; 1306 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE) 1307 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 1308 ICE_FLOW_SEG_HDR_GRE | 1309 ICE_FLOW_SEG_HDR_IPV_OTHER; 1310 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE) 1311 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 1312 ICE_FLOW_SEG_HDR_GRE | 1313 ICE_FLOW_SEG_HDR_IPV_OTHER; 1314 1315 if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS) 1316 return ICE_ERR_PARAM; 1317 1318 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 1319 if (val && !ice_is_pow2(val)) 1320 return ICE_ERR_CFG; 1321 1322 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 1323 if (val && !ice_is_pow2(val)) 1324 return ICE_ERR_CFG; 1325 1326 return ICE_SUCCESS; 1327} 1328 1329/** 1330 * ice_rem_vsi_rss_list - remove VSI from RSS list 1331 * @hw: pointer to the hardware structure 1332 * @vsi_handle: software VSI handle 1333 * 1334 * Remove the VSI from all RSS configurations in the list. 1335 */ 1336void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 1337{ 1338 struct ice_rss_cfg *r, *tmp; 1339 1340 if (LIST_EMPTY(&hw->rss_list_head)) 1341 return; 1342 1343 ice_acquire_lock(&hw->rss_locks); 1344 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 1345 ice_rss_cfg, l_entry) 1346 if (ice_test_and_clear_bit(vsi_handle, r->vsis)) 1347 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 1348 LIST_DEL(&r->l_entry); 1349 ice_free(hw, r); 1350 } 1351 ice_release_lock(&hw->rss_locks); 1352} 1353 1354/** 1355 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 1356 * @hw: pointer to the hardware structure 1357 * @vsi_handle: software VSI handle 1358 * 1359 * This function will iterate through all flow profiles and disassociate 1360 * the VSI from that profile. If the flow profile has no VSIs it will 1361 * be removed. 1362 */ 1363enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1364{ 1365 const enum ice_block blk = ICE_BLK_RSS; 1366 struct ice_flow_prof *p, *t; 1367 enum ice_status status = ICE_SUCCESS; 1368 u16 vsig; 1369 1370 if (!ice_is_vsi_valid(hw, vsi_handle)) 1371 return ICE_ERR_PARAM; 1372 1373 if (LIST_EMPTY(&hw->fl_profs[blk])) 1374 return ICE_SUCCESS; 1375 1376 ice_acquire_lock(&hw->rss_locks); 1377 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, 1378 l_entry) { 1379 int ret; 1380 1381 /* check if vsig is already removed */ 1382 ret = ice_vsig_find_vsi(hw, blk, 1383 ice_get_hw_vsi_num(hw, vsi_handle), 1384 &vsig); 1385 if (!ret && !vsig) 1386 break; 1387 1388 if (ice_is_bit_set(p->vsis, vsi_handle)) { 1389 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 1390 if (status) 1391 break; 1392 1393 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) { 1394 status = ice_flow_rem_prof(hw, blk, p->id); 1395 if (status) 1396 break; 1397 } 1398 } 1399 } 1400 ice_release_lock(&hw->rss_locks); 1401 1402 return status; 1403} 1404 1405/** 1406 * ice_get_rss_hdr_type - get a RSS profile's header type 1407 * @prof: RSS flow profile 1408 */ 1409static enum ice_rss_cfg_hdr_type 1410ice_get_rss_hdr_type(struct ice_flow_prof *prof) 1411{ 1412 enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS; 1413 1414 if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { 1415 hdr_type = ICE_RSS_OUTER_HEADERS; 1416 } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { 1417 const struct ice_flow_seg_info *s; 1418 1419 s = &prof->segs[ICE_RSS_OUTER_HEADERS]; 1420 if (s->hdrs == ICE_FLOW_SEG_HDR_NONE) 1421 hdr_type = ICE_RSS_INNER_HEADERS; 1422 if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4) 1423 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; 1424 if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6) 1425 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; 1426 } 1427 1428 return hdr_type; 1429} 1430 1431/** 1432 * ice_rem_rss_list - remove RSS configuration from list 1433 * @hw: pointer to the hardware structure 1434 * @vsi_handle: software VSI handle 1435 * @prof: pointer to flow profile 1436 * 1437 * Assumption: lock has already been acquired for RSS list 1438 */ 1439static void 1440ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 1441{ 1442 enum ice_rss_cfg_hdr_type hdr_type; 1443 struct ice_rss_cfg *r, *tmp; 1444 u64 seg_match = 0; 1445 u16 i; 1446 1447 /* convert match bitmap to u64 for hash field comparison */ 1448 ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match, 1449 ICE_FLOW_FIELD_IDX_MAX) { 1450 seg_match |= 1ULL << i; 1451 } 1452 1453 /* Search for RSS hash fields associated to the VSI that match the 1454 * hash configurations associated to the flow profile. If found 1455 * remove from the RSS entry list of the VSI context and delete entry. 1456 */ 1457 hdr_type = ice_get_rss_hdr_type(prof); 1458 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 1459 ice_rss_cfg, l_entry) 1460 if (r->hash.hash_flds == seg_match && 1461 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 1462 r->hash.hdr_type == hdr_type) { 1463 ice_clear_bit(vsi_handle, r->vsis); 1464 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 1465 LIST_DEL(&r->l_entry); 1466 ice_free(hw, r); 1467 } 1468 return; 1469 } 1470} 1471 1472/** 1473 * ice_add_rss_list - add RSS configuration to list 1474 * @hw: pointer to the hardware structure 1475 * @vsi_handle: software VSI handle 1476 * @prof: pointer to flow profile 1477 * 1478 * Assumption: lock has already been acquired for RSS list 1479 */ 1480static enum ice_status 1481ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 1482{ 1483 enum ice_rss_cfg_hdr_type hdr_type; 1484 struct ice_rss_cfg *r, *rss_cfg; 1485 u64 seg_match = 0; 1486 u16 i; 1487 1488 ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match, 1489 ICE_FLOW_FIELD_IDX_MAX) { 1490 seg_match |= 1ULL << i; 1491 } 1492 1493 hdr_type = ice_get_rss_hdr_type(prof); 1494 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 1495 ice_rss_cfg, l_entry) 1496 if (r->hash.hash_flds == seg_match && 1497 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 1498 r->hash.hdr_type == hdr_type) { 1499 ice_set_bit(vsi_handle, r->vsis); 1500 return ICE_SUCCESS; 1501 } 1502 1503 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); 1504 if (!rss_cfg) 1505 return ICE_ERR_NO_MEMORY; 1506 1507 rss_cfg->hash.hash_flds = seg_match; 1508 rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; 1509 rss_cfg->hash.hdr_type = hdr_type; 1510 rss_cfg->hash.symm = prof->cfg.symm; 1511 ice_set_bit(vsi_handle, rss_cfg->vsis); 1512 1513 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head); 1514 1515 return ICE_SUCCESS; 1516} 1517 1518#define ICE_FLOW_PROF_HASH_S 0 1519#define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 1520#define ICE_FLOW_PROF_HDR_S 32 1521#define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 1522#define ICE_FLOW_PROF_ENCAP_S 62 1523#define ICE_FLOW_PROF_ENCAP_M (0x3ULL << ICE_FLOW_PROF_ENCAP_S) 1524 1525/* Flow profile ID format: 1526 * [0:31] - Packet match fields 1527 * [32:61] - Protocol header 1528 * [62:63] - Encapsulation flag: 1529 * 0 if non-tunneled 1530 * 1 if tunneled 1531 * 2 for tunneled with outer IPv4 1532 * 3 for tunneled with outer IPv6 1533 */ 1534#define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ 1535 ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 1536 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 1537 (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & \ 1538 ICE_FLOW_PROF_ENCAP_M))) 1539 1540/** 1541 * ice_add_rss_cfg_sync - add an RSS configuration 1542 * @hw: pointer to the hardware structure 1543 * @vsi_handle: software VSI handle 1544 * @cfg: configure parameters 1545 * 1546 * Assumption: lock has already been acquired for RSS list 1547 */ 1548static enum ice_status 1549ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 1550 const struct ice_rss_hash_cfg *cfg) 1551{ 1552 const enum ice_block blk = ICE_BLK_RSS; 1553 struct ice_flow_prof *prof = NULL; 1554 struct ice_flow_seg_info *segs; 1555 enum ice_status status; 1556 u8 segs_cnt; 1557 1558 if (cfg->symm) 1559 return ICE_ERR_PARAM; 1560 1561 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 1562 ICE_FLOW_SEG_SINGLE : 1563 ICE_FLOW_SEG_MAX; 1564 1565 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 1566 sizeof(*segs)); 1567 if (!segs) 1568 return ICE_ERR_NO_MEMORY; 1569 1570 /* Construct the packet segment info from the hashed fields */ 1571 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 1572 if (status) 1573 goto exit; 1574 1575 /* Search for a flow profile that has matching headers, hash fields 1576 * and has the input VSI associated to it. If found, no further 1577 * operations required and exit. 1578 */ 1579 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1580 vsi_handle, 1581 ICE_FLOW_FIND_PROF_CHK_FLDS | 1582 ICE_FLOW_FIND_PROF_CHK_VSI); 1583 if (prof) 1584 goto exit; 1585 1586 /* Check if a flow profile exists with the same protocol headers and 1587 * associated with the input VSI. If so disassociate the VSI from 1588 * this profile. The VSI will be added to a new profile created with 1589 * the protocol header and new hash field configuration. 1590 */ 1591 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1592 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 1593 if (prof) { 1594 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1595 if (!status) 1596 ice_rem_rss_list(hw, vsi_handle, prof); 1597 else 1598 goto exit; 1599 1600 /* Remove profile if it has no VSIs associated */ 1601 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { 1602 status = ice_flow_rem_prof(hw, blk, prof->id); 1603 if (status) 1604 goto exit; 1605 } 1606 } 1607 1608 /* Search for a profile that has same match fields only. If this 1609 * exists then associate the VSI to this profile. 1610 */ 1611 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1612 vsi_handle, 1613 ICE_FLOW_FIND_PROF_CHK_FLDS); 1614 if (prof) { 1615 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1616 if (!status) 1617 status = ice_add_rss_list(hw, vsi_handle, prof); 1618 goto exit; 1619 } 1620 1621 /* Create a new flow profile with generated profile and packet 1622 * segment information. 1623 */ 1624 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 1625 ICE_FLOW_GEN_PROFID(cfg->hash_flds, 1626 segs[segs_cnt - 1].hdrs, 1627 cfg->hdr_type), 1628 segs, segs_cnt, NULL, 0, &prof); 1629 if (status) 1630 goto exit; 1631 1632 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1633 /* If association to a new flow profile failed then this profile can 1634 * be removed. 1635 */ 1636 if (status) { 1637 ice_flow_rem_prof(hw, blk, prof->id); 1638 goto exit; 1639 } 1640 1641 status = ice_add_rss_list(hw, vsi_handle, prof); 1642 1643 prof->cfg.symm = cfg->symm; 1644 1645exit: 1646 ice_free(hw, segs); 1647 return status; 1648} 1649 1650/** 1651 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 1652 * @hw: pointer to the hardware structure 1653 * @vsi_handle: software VSI handle 1654 * @cfg: configure parameters 1655 * 1656 * This function will generate a flow profile based on fields associated with 1657 * the input fields to hash on, the flow type and use the VSI number to add 1658 * a flow entry to the profile. 1659 */ 1660enum ice_status 1661ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 1662 const struct ice_rss_hash_cfg *cfg) 1663{ 1664 struct ice_rss_hash_cfg local_cfg; 1665 enum ice_status status; 1666 1667 if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || 1668 cfg->hdr_type > ICE_RSS_ANY_HEADERS || 1669 cfg->hash_flds == ICE_HASH_INVALID) 1670 return ICE_ERR_PARAM; 1671 1672 ice_acquire_lock(&hw->rss_locks); 1673 local_cfg = *cfg; 1674 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 1675 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1676 } else { 1677 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 1678 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1679 if (!status) { 1680 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 1681 status = ice_add_rss_cfg_sync(hw, vsi_handle, 1682 &local_cfg); 1683 } 1684 } 1685 ice_release_lock(&hw->rss_locks); 1686 1687 return status; 1688} 1689 1690/** 1691 * ice_rem_rss_cfg_sync - remove an existing RSS configuration 1692 * @hw: pointer to the hardware structure 1693 * @vsi_handle: software VSI handle 1694 * @cfg: configure parameters 1695 * 1696 * Assumption: lock has already been acquired for RSS list 1697 */ 1698static enum ice_status 1699ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 1700 const struct ice_rss_hash_cfg *cfg) 1701{ 1702 const enum ice_block blk = ICE_BLK_RSS; 1703 struct ice_flow_seg_info *segs; 1704 struct ice_flow_prof *prof; 1705 enum ice_status status; 1706 u8 segs_cnt; 1707 1708 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 1709 ICE_FLOW_SEG_SINGLE : 1710 ICE_FLOW_SEG_MAX; 1711 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 1712 sizeof(*segs)); 1713 if (!segs) 1714 return ICE_ERR_NO_MEMORY; 1715 1716 /* Construct the packet segment info from the hashed fields */ 1717 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 1718 if (status) 1719 goto out; 1720 1721 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1722 vsi_handle, 1723 ICE_FLOW_FIND_PROF_CHK_FLDS); 1724 if (!prof) { 1725 status = ICE_ERR_DOES_NOT_EXIST; 1726 goto out; 1727 } 1728 1729 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1730 if (status) 1731 goto out; 1732 1733 /* Remove RSS configuration from VSI context before deleting 1734 * the flow profile. 1735 */ 1736 ice_rem_rss_list(hw, vsi_handle, prof); 1737 1738 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) 1739 status = ice_flow_rem_prof(hw, blk, prof->id); 1740 1741out: 1742 ice_free(hw, segs); 1743 return status; 1744} 1745 1746/** 1747 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 1748 * @hw: pointer to the hardware structure 1749 * @vsi_handle: software VSI handle 1750 * @cfg: configure parameters 1751 * 1752 * This function will lookup the flow profile based on the input 1753 * hash field bitmap, iterate through the profile entry list of 1754 * that profile and find entry associated with input VSI to be 1755 * removed. Calls are made to underlying flow apis which will in 1756 * turn build or update buffers for RSS XLT1 section. 1757 */ 1758enum ice_status 1759ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 1760 const struct ice_rss_hash_cfg *cfg) 1761{ 1762 struct ice_rss_hash_cfg local_cfg; 1763 enum ice_status status; 1764 1765 if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || 1766 cfg->hdr_type > ICE_RSS_ANY_HEADERS || 1767 cfg->hash_flds == ICE_HASH_INVALID) 1768 return ICE_ERR_PARAM; 1769 1770 ice_acquire_lock(&hw->rss_locks); 1771 local_cfg = *cfg; 1772 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 1773 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1774 } else { 1775 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 1776 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1777 if (!status) { 1778 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 1779 status = ice_rem_rss_cfg_sync(hw, vsi_handle, 1780 &local_cfg); 1781 } 1782 } 1783 ice_release_lock(&hw->rss_locks); 1784 1785 return status; 1786} 1787 1788/* Mapping of AVF hash bit fields to an L3-L4 hash combination. 1789 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, 1790 * convert its values to their appropriate flow L3, L4 values. 1791 */ 1792#define ICE_FLOW_AVF_RSS_IPV4_MASKS \ 1793 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ 1794 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) 1795#define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ 1796 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ 1797 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) 1798#define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ 1799 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ 1800 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ 1801 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) 1802#define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ 1803 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ 1804 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) 1805 1806#define ICE_FLOW_AVF_RSS_IPV6_MASKS \ 1807 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ 1808 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) 1809#define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ 1810 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ 1811 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ 1812 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) 1813#define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ 1814 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ 1815 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) 1816#define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ 1817 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ 1818 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) 1819 1820/** 1821 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver 1822 * @hw: pointer to the hardware structure 1823 * @vsi_handle: software VSI handle 1824 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure 1825 * 1826 * This function will take the hash bitmap provided by the AVF driver via a 1827 * message, convert it to ICE-compatible values, and configure RSS flow 1828 * profiles. 1829 */ 1830enum ice_status 1831ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) 1832{ 1833 enum ice_status status = ICE_SUCCESS; 1834 struct ice_rss_hash_cfg hcfg; 1835 u64 hash_flds; 1836 1837 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || 1838 !ice_is_vsi_valid(hw, vsi_handle)) 1839 return ICE_ERR_PARAM; 1840 1841 /* Make sure no unsupported bits are specified */ 1842 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | 1843 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) 1844 return ICE_ERR_CFG; 1845 1846 hash_flds = avf_hash; 1847 1848 /* Always create an L3 RSS configuration for any L4 RSS configuration */ 1849 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) 1850 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; 1851 1852 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) 1853 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; 1854 1855 /* Create the corresponding RSS configuration for each valid hash bit */ 1856 while (hash_flds) { 1857 u64 rss_hash = ICE_HASH_INVALID; 1858 1859 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { 1860 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { 1861 rss_hash = ICE_FLOW_HASH_IPV4; 1862 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; 1863 } else if (hash_flds & 1864 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { 1865 rss_hash = ICE_FLOW_HASH_IPV4 | 1866 ICE_FLOW_HASH_TCP_PORT; 1867 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; 1868 } else if (hash_flds & 1869 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { 1870 rss_hash = ICE_FLOW_HASH_IPV4 | 1871 ICE_FLOW_HASH_UDP_PORT; 1872 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; 1873 } else if (hash_flds & 1874 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { 1875 rss_hash = ICE_FLOW_HASH_IPV4 | 1876 ICE_FLOW_HASH_SCTP_PORT; 1877 hash_flds &= 1878 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); 1879 } 1880 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { 1881 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { 1882 rss_hash = ICE_FLOW_HASH_IPV6; 1883 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; 1884 } else if (hash_flds & 1885 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { 1886 rss_hash = ICE_FLOW_HASH_IPV6 | 1887 ICE_FLOW_HASH_TCP_PORT; 1888 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; 1889 } else if (hash_flds & 1890 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { 1891 rss_hash = ICE_FLOW_HASH_IPV6 | 1892 ICE_FLOW_HASH_UDP_PORT; 1893 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; 1894 } else if (hash_flds & 1895 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { 1896 rss_hash = ICE_FLOW_HASH_IPV6 | 1897 ICE_FLOW_HASH_SCTP_PORT; 1898 hash_flds &= 1899 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); 1900 } 1901 } 1902 1903 if (rss_hash == ICE_HASH_INVALID) 1904 return ICE_ERR_OUT_OF_RANGE; 1905 1906 hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; 1907 hcfg.hash_flds = rss_hash; 1908 hcfg.symm = false; 1909 hcfg.hdr_type = ICE_RSS_ANY_HEADERS; 1910 status = ice_add_rss_cfg(hw, vsi_handle, &hcfg); 1911 if (status) 1912 break; 1913 } 1914 1915 return status; 1916} 1917 1918/** 1919 * ice_replay_rss_cfg - replay RSS configurations associated with VSI 1920 * @hw: pointer to the hardware structure 1921 * @vsi_handle: software VSI handle 1922 */ 1923enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1924{ 1925 enum ice_status status = ICE_SUCCESS; 1926 struct ice_rss_cfg *r; 1927 1928 if (!ice_is_vsi_valid(hw, vsi_handle)) 1929 return ICE_ERR_PARAM; 1930 1931 ice_acquire_lock(&hw->rss_locks); 1932 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 1933 ice_rss_cfg, l_entry) { 1934 if (ice_is_bit_set(r->vsis, vsi_handle)) { 1935 status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash); 1936 if (status) 1937 break; 1938 } 1939 } 1940 ice_release_lock(&hw->rss_locks); 1941 1942 return status; 1943} 1944 1945/** 1946 * ice_get_rss_cfg - returns hashed fields for the given header types 1947 * @hw: pointer to the hardware structure 1948 * @vsi_handle: software VSI handle 1949 * @hdrs: protocol header type 1950 * 1951 * This function will return the match fields of the first instance of flow 1952 * profile having the given header types and containing input VSI 1953 */ 1954u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 1955{ 1956 u64 rss_hash = ICE_HASH_INVALID; 1957 struct ice_rss_cfg *r; 1958 1959 /* verify if the protocol header is non zero and VSI is valid */ 1960 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 1961 return ICE_HASH_INVALID; 1962 1963 ice_acquire_lock(&hw->rss_locks); 1964 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 1965 ice_rss_cfg, l_entry) 1966 if (ice_is_bit_set(r->vsis, vsi_handle) && 1967 r->hash.addl_hdrs == hdrs) { 1968 rss_hash = r->hash.hash_flds; 1969 break; 1970 } 1971 ice_release_lock(&hw->rss_locks); 1972 1973 return rss_hash; 1974} 1975