1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2024, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "ice_common.h" 33 #include "ice_flow.h" 34 35 /* Size of known protocol header fields */ 36 #define ICE_FLOW_FLD_SZ_ETH_TYPE 2 37 #define ICE_FLOW_FLD_SZ_VLAN 2 38 #define ICE_FLOW_FLD_SZ_IPV4_ADDR 4 39 #define ICE_FLOW_FLD_SZ_IPV6_ADDR 16 40 #define ICE_FLOW_FLD_SZ_IP_DSCP 1 41 #define ICE_FLOW_FLD_SZ_IP_TTL 1 42 #define ICE_FLOW_FLD_SZ_IP_PROT 1 43 #define ICE_FLOW_FLD_SZ_PORT 2 44 #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1 45 #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1 46 #define ICE_FLOW_FLD_SZ_ICMP_CODE 1 47 #define ICE_FLOW_FLD_SZ_ARP_OPER 2 48 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4 49 50 /* Describe properties of a protocol header field */ 51 struct ice_flow_field_info { 52 enum ice_flow_seg_hdr hdr; 53 s16 off; /* Offset from start of a protocol header, in bits */ 54 u16 size; /* Size of fields in bits */ 55 }; 56 57 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \ 58 .hdr = _hdr, \ 59 .off = (_offset_bytes) * BITS_PER_BYTE, \ 60 .size = (_size_bytes) * BITS_PER_BYTE, \ 61 } 62 63 /* Table containing properties of supported protocol header fields */ 64 static const 65 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = { 66 /* Ether */ 67 /* ICE_FLOW_FIELD_IDX_ETH_DA */ 68 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN), 69 /* ICE_FLOW_FIELD_IDX_ETH_SA */ 70 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN), 71 /* ICE_FLOW_FIELD_IDX_S_VLAN */ 72 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN), 73 /* ICE_FLOW_FIELD_IDX_C_VLAN */ 74 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN), 75 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */ 76 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE), 77 /* IPv4 / IPv6 */ 78 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */ 79 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, ICE_FLOW_FLD_SZ_IP_DSCP), 80 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */ 81 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP), 82 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */ 83 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, ICE_FLOW_FLD_SZ_IP_TTL), 84 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 85 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT), 86 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */ 87 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 7, ICE_FLOW_FLD_SZ_IP_TTL), 88 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */ 89 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 6, ICE_FLOW_FLD_SZ_IP_PROT), 90 /* ICE_FLOW_FIELD_IDX_IPV4_SA */ 91 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR), 92 /* ICE_FLOW_FIELD_IDX_IPV4_DA */ 93 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR), 94 /* ICE_FLOW_FIELD_IDX_IPV6_SA */ 95 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR), 96 /* ICE_FLOW_FIELD_IDX_IPV6_DA */ 97 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR), 98 /* Transport */ 99 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */ 100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT), 101 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */ 102 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT), 103 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */ 104 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT), 105 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */ 106 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT), 107 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */ 108 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT), 109 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */ 110 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT), 111 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */ 112 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS), 113 /* ARP */ 114 /* ICE_FLOW_FIELD_IDX_ARP_SIP */ 115 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR), 116 /* ICE_FLOW_FIELD_IDX_ARP_DIP */ 117 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR), 118 /* ICE_FLOW_FIELD_IDX_ARP_SHA */ 119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN), 120 /* ICE_FLOW_FIELD_IDX_ARP_DHA */ 121 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN), 122 /* ICE_FLOW_FIELD_IDX_ARP_OP */ 123 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER), 124 /* ICMP */ 125 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */ 126 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE), 127 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */ 128 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE), 129 /* GRE */ 130 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */ 131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID), 132 }; 133 134 /* Bitmaps indicating relevant packet types for a particular protocol header 135 * 136 * Packet types for packets with an Outer/First/Single MAC header 137 */ 138 static const u32 ice_ptypes_mac_ofos[] = { 139 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB, 140 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 141 0x00000000, 0x00000000, 0x00000000, 0x00000000, 142 0x00000000, 0x00000000, 0x00000000, 0x00000000, 143 0x00000000, 0x00000000, 0x00000000, 0x00000000, 144 0x00000000, 0x00000000, 0x00000000, 0x00000000, 145 0x00000000, 0x00000000, 0x00000000, 0x00000000, 146 0x00000000, 0x00000000, 0x00000000, 0x00000000, 147 }; 148 149 /* Packet types for packets with an Innermost/Last MAC VLAN header */ 150 static const u32 ice_ptypes_macvlan_il[] = { 151 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000, 152 0x0000077E, 0x00000000, 0x00000000, 0x00000000, 153 0x00000000, 0x00000000, 0x00000000, 0x00000000, 154 0x00000000, 0x00000000, 0x00000000, 0x00000000, 155 0x00000000, 0x00000000, 0x00000000, 0x00000000, 156 0x00000000, 0x00000000, 0x00000000, 0x00000000, 157 0x00000000, 0x00000000, 0x00000000, 0x00000000, 158 0x00000000, 0x00000000, 0x00000000, 0x00000000, 159 }; 160 161 /* Packet types for packets with an Outer/First/Single non-frag IPv4 header, 162 * does NOT include IPV4 other PTYPEs 163 */ 164 static const u32 ice_ptypes_ipv4_ofos[] = { 165 0x1D800000, 0x04000800, 0x00000000, 0x00000000, 166 0x00000000, 0x00000000, 0x00000000, 0x00000000, 167 0x00000000, 0x00000000, 0x00000000, 0x00000000, 168 0x00000000, 0x00000000, 0x00000000, 0x00000000, 169 0x00000000, 0x00000000, 0x00000000, 0x00000000, 170 0x00000000, 0x00000000, 0x00000000, 0x00000000, 171 0x00000000, 0x00000000, 0x00000000, 0x00000000, 172 0x00000000, 0x00000000, 0x00000000, 0x00000000, 173 }; 174 175 /* Packet types for packets with an Outer/First/Single non-frag IPv4 header, 176 * includes IPV4 other PTYPEs 177 */ 178 static const u32 ice_ptypes_ipv4_ofos_all[] = { 179 0x1D800000, 0x04000800, 0x00000000, 0x00000000, 180 0x00000000, 0x00000000, 0x00000000, 0x00000000, 181 0x00000000, 0x00000000, 0x00000000, 0x00000000, 182 0x00000000, 0x00000000, 0x00000000, 0x00000000, 183 0x00000000, 0x00000000, 0x00000000, 0x00000000, 184 0x00000000, 0x00000000, 0x00000000, 0x00000000, 185 0x00000000, 0x00000000, 0x00000000, 0x00000000, 186 0x00000000, 0x00000000, 0x00000000, 0x00000000, 187 }; 188 189 /* Packet types for packets with an Innermost/Last IPv4 header */ 190 static const u32 ice_ptypes_ipv4_il[] = { 191 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 192 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 193 0x00000000, 0x00000000, 0x00000000, 0x00000000, 194 0x00000000, 0x00000000, 0x00000000, 0x00000000, 195 0x00000000, 0x00000000, 0x00000000, 0x00000000, 196 0x00000000, 0x00000000, 0x00000000, 0x00000000, 197 0x00000000, 0x00000000, 0x00000000, 0x00000000, 198 0x00000000, 0x00000000, 0x00000000, 0x00000000, 199 }; 200 201 /* Packet types for packets with an Outer/First/Single non-frag IPv6 header, 202 * does NOT include IVP6 other PTYPEs 203 */ 204 static const u32 ice_ptypes_ipv6_ofos[] = { 205 0x00000000, 0x00000000, 0x76000000, 0x10002000, 206 0x00000000, 0x00000000, 0x00000000, 0x00000000, 207 0x00000000, 0x00000000, 0x00000000, 0x00000000, 208 0x00000000, 0x00000000, 0x00000000, 0x00000000, 209 0x00000000, 0x00000000, 0x00000000, 0x00000000, 210 0x00000000, 0x00000000, 0x00000000, 0x00000000, 211 0x00000000, 0x00000000, 0x00000000, 0x00000000, 212 0x00000000, 0x00000000, 0x00000000, 0x00000000, 213 }; 214 215 /* Packet types for packets with an Outer/First/Single non-frag IPv6 header, 216 * includes IPV6 other PTYPEs 217 */ 218 static const u32 ice_ptypes_ipv6_ofos_all[] = { 219 0x00000000, 0x00000000, 0x76000000, 0x10002000, 220 0x00000000, 0x00000000, 0x00000000, 0x00000000, 221 0x00000000, 0x00000000, 0x00000000, 0x00000000, 222 0x00000000, 0x00000000, 0x00000000, 0x00000000, 223 0x00000000, 0x00000000, 0x00000000, 0x00000000, 224 0x00000000, 0x00000000, 0x00000000, 0x00000000, 225 0x00000000, 0x00000000, 0x00000000, 0x00000000, 226 0x00000000, 0x00000000, 0x00000000, 0x00000000, 227 }; 228 229 /* Packet types for packets with an Innermost/Last IPv6 header */ 230 static const u32 ice_ptypes_ipv6_il[] = { 231 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 232 0x00000770, 0x00000000, 0x00000000, 0x00000000, 233 0x00000000, 0x00000000, 0x00000000, 0x00000000, 234 0x00000000, 0x00000000, 0x00000000, 0x00000000, 235 0x00000000, 0x00000000, 0x00000000, 0x00000000, 236 0x00000000, 0x00000000, 0x00000000, 0x00000000, 237 0x00000000, 0x00000000, 0x00000000, 0x00000000, 238 0x00000000, 0x00000000, 0x00000000, 0x00000000, 239 }; 240 241 /* Packet types for packets with an Outer/First/Single 242 * non-frag IPv4 header - no L4 243 */ 244 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = { 245 0x10800000, 0x04000800, 0x00000000, 0x00000000, 246 0x00000000, 0x00000000, 0x00000000, 0x00000000, 247 0x00000000, 0x00000000, 0x00000000, 0x00000000, 248 0x00000000, 0x00000000, 0x00000000, 0x00000000, 249 0x00000000, 0x00000000, 0x00000000, 0x00000000, 250 0x00000000, 0x00000000, 0x00000000, 0x00000000, 251 0x00000000, 0x00000000, 0x00000000, 0x00000000, 252 0x00000000, 0x00000000, 0x00000000, 0x00000000, 253 }; 254 255 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */ 256 static const u32 ice_ptypes_ipv4_il_no_l4[] = { 257 0x60000000, 0x18043008, 0x80000002, 0x6010c021, 258 0x00000008, 0x00000000, 0x00000000, 0x00000000, 259 0x00000000, 0x00000000, 0x00000000, 0x00000000, 260 0x00000000, 0x00000000, 0x00000000, 0x00000000, 261 0x00000000, 0x00000000, 0x00000000, 0x00000000, 262 0x00000000, 0x00000000, 0x00000000, 0x00000000, 263 0x00000000, 0x00000000, 0x00000000, 0x00000000, 264 0x00000000, 0x00000000, 0x00000000, 0x00000000, 265 }; 266 267 /* Packet types for packets with an Outer/First/Single 268 * non-frag IPv6 header - no L4 269 */ 270 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = { 271 0x00000000, 0x00000000, 0x42000000, 0x10002000, 272 0x00000000, 0x00000000, 0x00000000, 0x00000000, 273 0x00000000, 0x00000000, 0x00000000, 0x00000000, 274 0x00000000, 0x00000000, 0x00000000, 0x00000000, 275 0x00000000, 0x00000000, 0x00000000, 0x00000000, 276 0x00000000, 0x00000000, 0x00000000, 0x00000000, 277 0x00000000, 0x00000000, 0x00000000, 0x00000000, 278 0x00000000, 0x00000000, 0x00000000, 0x00000000, 279 }; 280 281 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */ 282 static const u32 ice_ptypes_ipv6_il_no_l4[] = { 283 0x00000000, 0x02180430, 0x0000010c, 0x086010c0, 284 0x00000430, 0x00000000, 0x00000000, 0x00000000, 285 0x00000000, 0x00000000, 0x00000000, 0x00000000, 286 0x00000000, 0x00000000, 0x00000000, 0x00000000, 287 0x00000000, 0x00000000, 0x00000000, 0x00000000, 288 0x00000000, 0x00000000, 0x00000000, 0x00000000, 289 0x00000000, 0x00000000, 0x00000000, 0x00000000, 290 0x00000000, 0x00000000, 0x00000000, 0x00000000, 291 }; 292 293 /* Packet types for packets with an Outermost/First ARP header */ 294 static const u32 ice_ptypes_arp_of[] = { 295 0x00000800, 0x00000000, 0x00000000, 0x00000000, 296 0x00000000, 0x00000000, 0x00000000, 0x00000000, 297 0x00000000, 0x00000000, 0x00000000, 0x00000000, 298 0x00000000, 0x00000000, 0x00000000, 0x00000000, 299 0x00000000, 0x00000000, 0x00000000, 0x00000000, 300 0x00000000, 0x00000000, 0x00000000, 0x00000000, 301 0x00000000, 0x00000000, 0x00000000, 0x00000000, 302 0x00000000, 0x00000000, 0x00000000, 0x00000000, 303 }; 304 305 /* UDP Packet types for non-tunneled packets or tunneled 306 * packets with inner UDP. 307 */ 308 static const u32 ice_ptypes_udp_il[] = { 309 0x81000000, 0x20204040, 0x04000010, 0x80810102, 310 0x00000040, 0x00000000, 0x00000000, 0x00000000, 311 0x00000000, 0x00000000, 0x00000000, 0x00000000, 312 0x00000000, 0x00000000, 0x00000000, 0x00000000, 313 0x00000000, 0x00000000, 0x00000000, 0x00000000, 314 0x00000000, 0x00000000, 0x00000000, 0x00000000, 315 0x00000000, 0x00000000, 0x00000000, 0x00000000, 316 0x00000000, 0x00000000, 0x00000000, 0x00000000, 317 }; 318 319 /* Packet types for packets with an Innermost/Last TCP header */ 320 static const u32 ice_ptypes_tcp_il[] = { 321 0x04000000, 0x80810102, 0x10000040, 0x02040408, 322 0x00000102, 0x00000000, 0x00000000, 0x00000000, 323 0x00000000, 0x00000000, 0x00000000, 0x00000000, 324 0x00000000, 0x00000000, 0x00000000, 0x00000000, 325 0x00000000, 0x00000000, 0x00000000, 0x00000000, 326 0x00000000, 0x00000000, 0x00000000, 0x00000000, 327 0x00000000, 0x00000000, 0x00000000, 0x00000000, 328 0x00000000, 0x00000000, 0x00000000, 0x00000000, 329 }; 330 331 /* Packet types for packets with an Innermost/Last SCTP header */ 332 static const u32 ice_ptypes_sctp_il[] = { 333 0x08000000, 0x01020204, 0x20000081, 0x04080810, 334 0x00000204, 0x00000000, 0x00000000, 0x00000000, 335 0x00000000, 0x00000000, 0x00000000, 0x00000000, 336 0x00000000, 0x00000000, 0x00000000, 0x00000000, 337 0x00000000, 0x00000000, 0x00000000, 0x00000000, 338 0x00000000, 0x00000000, 0x00000000, 0x00000000, 339 0x00000000, 0x00000000, 0x00000000, 0x00000000, 340 0x00000000, 0x00000000, 0x00000000, 0x00000000, 341 }; 342 343 /* Packet types for packets with an Outermost/First ICMP header */ 344 static const u32 ice_ptypes_icmp_of[] = { 345 0x10000000, 0x00000000, 0x00000000, 0x00000000, 346 0x00000000, 0x00000000, 0x00000000, 0x00000000, 347 0x00000000, 0x00000000, 0x00000000, 0x00000000, 348 0x00000000, 0x00000000, 0x00000000, 0x00000000, 349 0x00000000, 0x00000000, 0x00000000, 0x00000000, 350 0x00000000, 0x00000000, 0x00000000, 0x00000000, 351 0x00000000, 0x00000000, 0x00000000, 0x00000000, 352 0x00000000, 0x00000000, 0x00000000, 0x00000000, 353 }; 354 355 /* Packet types for packets with an Innermost/Last ICMP header */ 356 static const u32 ice_ptypes_icmp_il[] = { 357 0x00000000, 0x02040408, 0x40000102, 0x08101020, 358 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 */ 368 static 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 */ 380 static 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 */ 392 struct 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 */ 420 static int ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 421 { 422 u8 i; 423 424 for (i = 0; i < segs_cnt; i++) { 425 /* Multiple L3 headers */ 426 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 427 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 428 return ICE_ERR_PARAM; 429 430 /* Multiple L4 headers */ 431 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 432 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 433 return ICE_ERR_PARAM; 434 } 435 436 return 0; 437 } 438 439 /** 440 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 441 * @params: information about the flow to be processed 442 * 443 * This function identifies the packet types associated with the protocol 444 * headers being present in packet segments of the specified flow profile. 445 */ 446 static int 447 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 448 { 449 struct ice_flow_prof *prof; 450 u8 i; 451 452 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes), 453 ICE_NONDMA_MEM); 454 455 prof = params->prof; 456 457 for (i = 0; i < params->prof->segs_cnt; i++) { 458 const ice_bitmap_t *src; 459 u32 hdrs; 460 461 hdrs = prof->segs[i].hdrs; 462 463 if (hdrs & ICE_FLOW_SEG_HDR_ETH) { 464 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos : 465 (const ice_bitmap_t *)ice_ptypes_mac_il; 466 ice_and_bitmap(params->ptypes, params->ptypes, src, 467 ICE_FLOW_PTYPE_MAX); 468 } 469 470 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) { 471 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il; 472 ice_and_bitmap(params->ptypes, params->ptypes, src, 473 ICE_FLOW_PTYPE_MAX); 474 } 475 476 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) { 477 ice_and_bitmap(params->ptypes, params->ptypes, 478 (const ice_bitmap_t *)ice_ptypes_arp_of, 479 ICE_FLOW_PTYPE_MAX); 480 } 481 482 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 483 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 484 src = i ? (const ice_bitmap_t *)ice_ptypes_ipv4_il : 485 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all; 486 ice_and_bitmap(params->ptypes, params->ptypes, src, 487 ICE_FLOW_PTYPE_MAX); 488 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 489 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) { 490 src = i ? (const ice_bitmap_t *)ice_ptypes_ipv6_il : 491 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all; 492 ice_and_bitmap(params->ptypes, params->ptypes, src, 493 ICE_FLOW_PTYPE_MAX); 494 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) && 495 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 496 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 : 497 (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4; 498 ice_and_bitmap(params->ptypes, params->ptypes, src, 499 ICE_FLOW_PTYPE_MAX); 500 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 501 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos : 502 (const ice_bitmap_t *)ice_ptypes_ipv4_il; 503 ice_and_bitmap(params->ptypes, params->ptypes, src, 504 ICE_FLOW_PTYPE_MAX); 505 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) && 506 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) { 507 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 : 508 (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4; 509 ice_and_bitmap(params->ptypes, params->ptypes, src, 510 ICE_FLOW_PTYPE_MAX); 511 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 512 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos : 513 (const ice_bitmap_t *)ice_ptypes_ipv6_il; 514 ice_and_bitmap(params->ptypes, params->ptypes, src, 515 ICE_FLOW_PTYPE_MAX); 516 } 517 518 if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 519 src = (const ice_bitmap_t *)ice_ptypes_udp_il; 520 ice_and_bitmap(params->ptypes, params->ptypes, src, 521 ICE_FLOW_PTYPE_MAX); 522 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 523 ice_and_bitmap(params->ptypes, params->ptypes, 524 (const ice_bitmap_t *)ice_ptypes_tcp_il, 525 ICE_FLOW_PTYPE_MAX); 526 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 527 src = (const ice_bitmap_t *)ice_ptypes_sctp_il; 528 ice_and_bitmap(params->ptypes, params->ptypes, src, 529 ICE_FLOW_PTYPE_MAX); 530 } 531 532 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) { 533 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of : 534 (const ice_bitmap_t *)ice_ptypes_icmp_il; 535 ice_and_bitmap(params->ptypes, params->ptypes, src, 536 ICE_FLOW_PTYPE_MAX); 537 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) { 538 if (!i) { 539 src = (const ice_bitmap_t *)ice_ptypes_gre_of; 540 ice_and_bitmap(params->ptypes, params->ptypes, 541 src, ICE_FLOW_PTYPE_MAX); 542 } 543 } 544 } 545 546 return 0; 547 } 548 549 /* 550 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 551 * @hw: pointer to the HW struct 552 * @params: information about the flow to be processed 553 * @seg: packet segment index of the field to be extracted 554 * @fld: ID of field to be extracted 555 * 556 * This function determines the protocol ID, offset, and size of the given 557 * field. It then allocates one or more extraction sequence entries for the 558 * given field, and fill the entries with protocol ID and offset information. 559 */ 560 static int 561 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 562 u8 seg, enum ice_flow_field fld) 563 { 564 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX; 565 u8 fv_words = (u8)hw->blk[params->blk].es.fvw; 566 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 567 struct ice_flow_fld_info *flds; 568 u16 cnt, ese_bits, i; 569 u16 off; 570 571 flds = params->prof->segs[seg].fields; 572 573 switch (fld) { 574 case ICE_FLOW_FIELD_IDX_ETH_DA: 575 case ICE_FLOW_FIELD_IDX_ETH_SA: 576 case ICE_FLOW_FIELD_IDX_S_VLAN: 577 case ICE_FLOW_FIELD_IDX_C_VLAN: 578 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL; 579 break; 580 case ICE_FLOW_FIELD_IDX_ETH_TYPE: 581 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL; 582 break; 583 case ICE_FLOW_FIELD_IDX_IPV4_DSCP: 584 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 585 break; 586 case ICE_FLOW_FIELD_IDX_IPV6_DSCP: 587 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 588 break; 589 case ICE_FLOW_FIELD_IDX_IPV4_TTL: 590 case ICE_FLOW_FIELD_IDX_IPV4_PROT: 591 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 592 /* TTL and PROT share the same extraction seq. entry. 593 * Each is considered a sibling to the other in terms of sharing 594 * the same extraction sequence entry. 595 */ 596 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL) 597 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT; 598 else 599 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL; 600 break; 601 case ICE_FLOW_FIELD_IDX_IPV6_TTL: 602 case ICE_FLOW_FIELD_IDX_IPV6_PROT: 603 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 604 /* TTL and PROT share the same extraction seq. entry. 605 * Each is considered a sibling to the other in terms of sharing 606 * the same extraction sequence entry. 607 */ 608 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL) 609 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT; 610 else 611 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL; 612 break; 613 case ICE_FLOW_FIELD_IDX_IPV4_SA: 614 case ICE_FLOW_FIELD_IDX_IPV4_DA: 615 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 616 break; 617 case ICE_FLOW_FIELD_IDX_IPV6_SA: 618 case ICE_FLOW_FIELD_IDX_IPV6_DA: 619 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 620 break; 621 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 622 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 623 case ICE_FLOW_FIELD_IDX_TCP_FLAGS: 624 prot_id = ICE_PROT_TCP_IL; 625 break; 626 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 627 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 628 prot_id = ICE_PROT_UDP_IL_OR_S; 629 break; 630 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT: 631 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT: 632 prot_id = ICE_PROT_SCTP_IL; 633 break; 634 case ICE_FLOW_FIELD_IDX_ARP_SIP: 635 case ICE_FLOW_FIELD_IDX_ARP_DIP: 636 case ICE_FLOW_FIELD_IDX_ARP_SHA: 637 case ICE_FLOW_FIELD_IDX_ARP_DHA: 638 case ICE_FLOW_FIELD_IDX_ARP_OP: 639 prot_id = ICE_PROT_ARP_OF; 640 break; 641 case ICE_FLOW_FIELD_IDX_ICMP_TYPE: 642 case ICE_FLOW_FIELD_IDX_ICMP_CODE: 643 /* ICMP type and code share the same extraction seq. entry */ 644 prot_id = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) ? 645 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL; 646 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ? 647 ICE_FLOW_FIELD_IDX_ICMP_CODE : 648 ICE_FLOW_FIELD_IDX_ICMP_TYPE; 649 break; 650 case ICE_FLOW_FIELD_IDX_GRE_KEYID: 651 prot_id = ICE_PROT_GRE_OF; 652 break; 653 default: 654 return ICE_ERR_NOT_IMPL; 655 } 656 657 /* Each extraction sequence entry is a word in size, and extracts a 658 * word-aligned offset from a protocol header. 659 */ 660 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 661 662 flds[fld].xtrct.prot_id = (u8)prot_id; 663 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 664 ICE_FLOW_FV_EXTRACT_SZ; 665 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 666 flds[fld].xtrct.idx = params->es_cnt; 667 668 /* Adjust the next field-entry index after accommodating the number of 669 * entries this field consumes 670 */ 671 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp + 672 ice_flds_info[fld].size, ese_bits); 673 674 /* Fill in the extraction sequence entries needed for this field */ 675 off = flds[fld].xtrct.off; 676 for (i = 0; i < cnt; i++) { 677 /* Only consume an extraction sequence entry if there is no 678 * sibling field associated with this field or the sibling entry 679 * already extracts the word shared with this field. 680 */ 681 if (sib == ICE_FLOW_FIELD_IDX_MAX || 682 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL || 683 flds[sib].xtrct.off != off) { 684 u8 idx; 685 686 /* Make sure the number of extraction sequence required 687 * does not exceed the block's capability 688 */ 689 if (params->es_cnt >= fv_words) 690 return ICE_ERR_MAX_LIMIT; 691 692 /* some blocks require a reversed field vector layout */ 693 if (hw->blk[params->blk].es.reverse) 694 idx = fv_words - params->es_cnt - 1; 695 else 696 idx = params->es_cnt; 697 698 params->es[idx].prot_id = (u8)prot_id; 699 params->es[idx].off = off; 700 params->es_cnt++; 701 } 702 703 off += ICE_FLOW_FV_EXTRACT_SZ; 704 } 705 706 return 0; 707 } 708 709 /** 710 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 711 * @hw: pointer to the HW struct 712 * @params: information about the flow to be processed 713 * 714 * This function iterates through all matched fields in the given segments, and 715 * creates an extraction sequence for the fields. 716 */ 717 static int 718 ice_flow_create_xtrct_seq(struct ice_hw *hw, 719 struct ice_flow_prof_params *params) 720 { 721 int status = 0; 722 u8 i; 723 724 for (i = 0; i < params->prof->segs_cnt; i++) { 725 ice_declare_bitmap(match, ICE_FLOW_FIELD_IDX_MAX); 726 enum ice_flow_field j; 727 728 ice_cp_bitmap(match, params->prof->segs[i].match, 729 ICE_FLOW_FIELD_IDX_MAX); 730 ice_for_each_set_bit(j, match, ICE_FLOW_FIELD_IDX_MAX) { 731 status = ice_flow_xtract_fld(hw, params, i, j); 732 if (status) 733 return status; 734 ice_clear_bit(j, match); 735 } 736 } 737 738 return status; 739 } 740 741 /** 742 * ice_flow_proc_segs - process all packet segments associated with a profile 743 * @hw: pointer to the HW struct 744 * @params: information about the flow to be processed 745 */ 746 static int 747 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 748 { 749 int status; 750 751 status = ice_flow_proc_seg_hdrs(params); 752 if (status) 753 return status; 754 755 status = ice_flow_create_xtrct_seq(hw, params); 756 if (status) 757 return status; 758 759 switch (params->blk) { 760 case ICE_BLK_RSS: 761 status = 0; 762 break; 763 default: 764 return ICE_ERR_NOT_IMPL; 765 } 766 767 return status; 768 } 769 770 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001 771 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002 772 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004 773 774 /** 775 * ice_flow_find_prof_conds - Find a profile matching headers and conditions 776 * @hw: pointer to the HW struct 777 * @blk: classification stage 778 * @dir: flow direction 779 * @segs: array of one or more packet segments that describe the flow 780 * @segs_cnt: number of packet segments provided 781 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI) 782 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*) 783 */ 784 static struct ice_flow_prof * 785 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk, 786 enum ice_flow_dir dir, struct ice_flow_seg_info *segs, 787 u8 segs_cnt, u16 vsi_handle, u32 conds) 788 { 789 struct ice_flow_prof *p, *prof = NULL; 790 791 ice_acquire_lock(&hw->fl_profs_locks[blk]); 792 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 793 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) && 794 segs_cnt && segs_cnt == p->segs_cnt) { 795 u8 i; 796 797 /* Check for profile-VSI association if specified */ 798 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) && 799 ice_is_vsi_valid(hw, vsi_handle) && 800 !ice_is_bit_set(p->vsis, vsi_handle)) 801 continue; 802 803 /* Protocol headers must be checked. Matched fields are 804 * checked if specified. 805 */ 806 for (i = 0; i < segs_cnt; i++) 807 if (segs[i].hdrs != p->segs[i].hdrs || 808 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) && 809 (ice_cmp_bitmap(segs[i].match, 810 p->segs[i].match, 811 ICE_FLOW_FIELD_IDX_MAX) == 812 false))) 813 break; 814 815 /* A match is found if all segments are matched */ 816 if (i == segs_cnt) { 817 prof = p; 818 break; 819 } 820 } 821 ice_release_lock(&hw->fl_profs_locks[blk]); 822 823 return prof; 824 } 825 826 /** 827 * ice_flow_find_prof - Look up a profile matching headers and matched fields 828 * @hw: pointer to the HW struct 829 * @blk: classification stage 830 * @dir: flow direction 831 * @segs: array of one or more packet segments that describe the flow 832 * @segs_cnt: number of packet segments provided 833 */ 834 u64 835 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 836 struct ice_flow_seg_info *segs, u8 segs_cnt) 837 { 838 struct ice_flow_prof *p; 839 840 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt, 841 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS); 842 843 return p ? p->id : ICE_FLOW_PROF_ID_INVAL; 844 } 845 846 /** 847 * ice_flow_find_prof_id - Look up a profile with given profile ID 848 * @hw: pointer to the HW struct 849 * @blk: classification stage 850 * @prof_id: unique ID to identify this flow profile 851 */ 852 static struct ice_flow_prof * 853 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 854 { 855 struct ice_flow_prof *p; 856 857 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) 858 if (p->id == prof_id) 859 return p; 860 861 return NULL; 862 } 863 864 /** 865 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle 866 * @hw: pointer to the HW struct 867 * @blk: classification stage 868 * @prof_id: the profile ID handle 869 * @hw_prof_id: pointer to variable to receive the HW profile ID 870 */ 871 int 872 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id, 873 u8 *hw_prof_id) 874 { 875 struct ice_prof_map *map; 876 int status = ICE_ERR_DOES_NOT_EXIST; 877 878 ice_acquire_lock(&hw->blk[blk].es.prof_map_lock); 879 map = ice_search_prof_id(hw, blk, prof_id); 880 if (map) { 881 *hw_prof_id = map->prof_id; 882 status = 0; 883 } 884 ice_release_lock(&hw->blk[blk].es.prof_map_lock); 885 return status; 886 } 887 888 /** 889 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 890 * @hw: pointer to the HW struct 891 * @blk: classification stage 892 * @dir: flow direction 893 * @prof_id: unique ID to identify this flow profile 894 * @segs: array of one or more packet segments that describe the flow 895 * @segs_cnt: number of packet segments provided 896 * @acts: array of default actions 897 * @acts_cnt: number of default actions 898 * @prof: stores the returned flow profile added 899 * 900 * Assumption: the caller has acquired the lock to the profile list 901 */ 902 static int 903 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 904 enum ice_flow_dir dir, u64 prof_id, 905 struct ice_flow_seg_info *segs, u8 segs_cnt, 906 struct ice_flow_action *acts, u8 acts_cnt, 907 struct ice_flow_prof **prof) 908 { 909 struct ice_flow_prof_params *params; 910 int status; 911 u8 i; 912 913 if (!prof || (acts_cnt && !acts)) 914 return ICE_ERR_BAD_PTR; 915 916 params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params)); 917 if (!params) 918 return ICE_ERR_NO_MEMORY; 919 920 params->prof = (struct ice_flow_prof *) 921 ice_malloc(hw, sizeof(*params->prof)); 922 if (!params->prof) { 923 status = ICE_ERR_NO_MEMORY; 924 goto free_params; 925 } 926 927 /* initialize extraction sequence to all invalid (0xff) */ 928 for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 929 params->es[i].prot_id = ICE_PROT_INVALID; 930 params->es[i].off = ICE_FV_OFFSET_INVAL; 931 } 932 933 params->blk = blk; 934 params->prof->id = prof_id; 935 params->prof->dir = dir; 936 params->prof->segs_cnt = segs_cnt; 937 938 /* Make a copy of the segments that need to be persistent in the flow 939 * profile instance 940 */ 941 for (i = 0; i < segs_cnt; i++) 942 ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs), 943 ICE_NONDMA_TO_NONDMA); 944 945 status = ice_flow_proc_segs(hw, params); 946 if (status) { 947 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n"); 948 goto out; 949 } 950 951 /* Add a HW profile for this flow profile */ 952 status = ice_add_prof(hw, blk, prof_id, params->ptypes, params->es); 953 if (status) { 954 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 955 goto out; 956 } 957 958 *prof = params->prof; 959 960 out: 961 if (status) { 962 ice_free(hw, params->prof); 963 } 964 free_params: 965 ice_free(hw, params); 966 967 return status; 968 } 969 970 /** 971 * ice_flow_rem_prof_sync - remove a flow profile 972 * @hw: pointer to the hardware structure 973 * @blk: classification stage 974 * @prof: pointer to flow profile to remove 975 * 976 * Assumption: the caller has acquired the lock to the profile list 977 */ 978 static int 979 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk, 980 struct ice_flow_prof *prof) 981 { 982 int status; 983 984 /* Remove all hardware profiles associated with this flow profile */ 985 status = ice_rem_prof(hw, blk, prof->id); 986 if (!status) { 987 LIST_DEL(&prof->l_entry); 988 ice_free(hw, prof); 989 } 990 991 return status; 992 } 993 994 /** 995 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG 996 * @hw: pointer to the hardware structure 997 * @blk: classification stage 998 * @vsi_handle: software VSI handle 999 * @vsig: target VSI group 1000 * 1001 * Assumption: the caller has already verified that the VSI to 1002 * be added has the same characteristics as the VSIG and will 1003 * thereby have access to all resources added to that VSIG. 1004 */ 1005 int 1006 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle, 1007 u16 vsig) 1008 { 1009 int status; 1010 1011 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT) 1012 return ICE_ERR_PARAM; 1013 1014 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1015 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle), 1016 vsig); 1017 ice_release_lock(&hw->fl_profs_locks[blk]); 1018 1019 return status; 1020 } 1021 1022 /** 1023 * ice_flow_assoc_prof - associate a VSI with a flow profile 1024 * @hw: pointer to the hardware structure 1025 * @blk: classification stage 1026 * @prof: pointer to flow profile 1027 * @vsi_handle: software VSI handle 1028 * 1029 * Assumption: the caller has acquired the lock to the profile list 1030 * and the software VSI handle has been validated 1031 */ 1032 static int 1033 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk, 1034 struct ice_flow_prof *prof, u16 vsi_handle) 1035 { 1036 int status = 0; 1037 1038 if (!ice_is_bit_set(prof->vsis, vsi_handle)) { 1039 status = ice_add_prof_id_flow(hw, blk, 1040 ice_get_hw_vsi_num(hw, 1041 vsi_handle), 1042 prof->id); 1043 if (!status) 1044 ice_set_bit(vsi_handle, prof->vsis); 1045 else 1046 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n", 1047 status); 1048 } 1049 1050 return status; 1051 } 1052 1053 /** 1054 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile 1055 * @hw: pointer to the hardware structure 1056 * @blk: classification stage 1057 * @prof: pointer to flow profile 1058 * @vsi_handle: software VSI handle 1059 * 1060 * Assumption: the caller has acquired the lock to the profile list 1061 * and the software VSI handle has been validated 1062 */ 1063 static int 1064 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk, 1065 struct ice_flow_prof *prof, u16 vsi_handle) 1066 { 1067 int status = 0; 1068 1069 if (ice_is_bit_set(prof->vsis, vsi_handle)) { 1070 status = ice_rem_prof_id_flow(hw, blk, 1071 ice_get_hw_vsi_num(hw, 1072 vsi_handle), 1073 prof->id); 1074 if (!status) 1075 ice_clear_bit(vsi_handle, prof->vsis); 1076 else 1077 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n", 1078 status); 1079 } 1080 1081 return status; 1082 } 1083 1084 /** 1085 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 1086 * @hw: pointer to the HW struct 1087 * @blk: classification stage 1088 * @dir: flow direction 1089 * @prof_id: unique ID to identify this flow profile 1090 * @segs: array of one or more packet segments that describe the flow 1091 * @segs_cnt: number of packet segments provided 1092 * @acts: array of default actions 1093 * @acts_cnt: number of default actions 1094 * @prof: stores the returned flow profile added 1095 */ 1096 static int 1097 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 1098 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt, 1099 struct ice_flow_action *acts, u8 acts_cnt, 1100 struct ice_flow_prof **prof) 1101 { 1102 int status; 1103 1104 if (segs_cnt > ICE_FLOW_SEG_MAX) 1105 return ICE_ERR_MAX_LIMIT; 1106 1107 if (!segs_cnt) 1108 return ICE_ERR_PARAM; 1109 1110 if (!segs) 1111 return ICE_ERR_BAD_PTR; 1112 1113 status = ice_flow_val_hdrs(segs, segs_cnt); 1114 if (status) 1115 return status; 1116 1117 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1118 1119 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 1120 acts, acts_cnt, prof); 1121 if (!status) 1122 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]); 1123 1124 ice_release_lock(&hw->fl_profs_locks[blk]); 1125 1126 return status; 1127 } 1128 1129 /** 1130 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it 1131 * @hw: pointer to the HW struct 1132 * @blk: the block for which the flow profile is to be removed 1133 * @prof_id: unique ID of the flow profile to be removed 1134 */ 1135 static int 1136 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id) 1137 { 1138 struct ice_flow_prof *prof; 1139 int status; 1140 1141 ice_acquire_lock(&hw->fl_profs_locks[blk]); 1142 1143 prof = ice_flow_find_prof_id(hw, blk, prof_id); 1144 if (!prof) { 1145 status = ICE_ERR_DOES_NOT_EXIST; 1146 goto out; 1147 } 1148 1149 /* prof becomes invalid after the call */ 1150 status = ice_flow_rem_prof_sync(hw, blk, prof); 1151 1152 out: 1153 ice_release_lock(&hw->fl_profs_locks[blk]); 1154 1155 return status; 1156 } 1157 1158 /** 1159 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 1160 * @seg: packet segment the field being set belongs to 1161 * @fld: field to be set 1162 * @field_type: type of the field 1163 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1164 * entry's input buffer 1165 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1166 * input buffer 1167 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1168 * entry's input buffer 1169 * 1170 * This helper function stores information of a field being matched, including 1171 * the type of the field and the locations of the value to match, the mask, and 1172 * the upper-bound value in the start of the input buffer for a flow entry. 1173 * This function should only be used for fixed-size data structures. 1174 * 1175 * This function also opportunistically determines the protocol headers to be 1176 * present based on the fields being set. Some fields cannot be used alone to 1177 * determine the protocol headers present. Sometimes, fields for particular 1178 * protocol headers are not matched. In those cases, the protocol headers 1179 * must be explicitly set. 1180 */ 1181 static void 1182 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1183 enum ice_flow_fld_match_type field_type, u16 val_loc, 1184 u16 mask_loc, u16 last_loc) 1185 { 1186 ice_set_bit(fld, seg->match); 1187 if (field_type == ICE_FLOW_FLD_TYPE_RANGE) 1188 ice_set_bit(fld, seg->range); 1189 1190 seg->fields[fld].type = field_type; 1191 seg->fields[fld].src.val = val_loc; 1192 seg->fields[fld].src.mask = mask_loc; 1193 seg->fields[fld].src.last = last_loc; 1194 1195 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr); 1196 } 1197 1198 /** 1199 * ice_flow_set_fld - specifies locations of field from entry's input buffer 1200 * @seg: packet segment the field being set belongs to 1201 * @fld: field to be set 1202 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1203 * entry's input buffer 1204 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's 1205 * input buffer 1206 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from 1207 * entry's input buffer 1208 * @range: indicate if field being matched is to be in a range 1209 * 1210 * This function specifies the locations, in the form of byte offsets from the 1211 * start of the input buffer for a flow entry, from where the value to match, 1212 * the mask value, and upper value can be extracted. These locations are then 1213 * stored in the flow profile. When adding a flow entry associated with the 1214 * flow profile, these locations will be used to quickly extract the values and 1215 * create the content of a match entry. This function should only be used for 1216 * fixed-size data structures. 1217 */ 1218 static void 1219 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1220 u16 val_loc, u16 mask_loc, u16 last_loc, bool range) 1221 { 1222 enum ice_flow_fld_match_type t = range ? 1223 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG; 1224 1225 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc); 1226 } 1227 1228 /** 1229 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf 1230 * @seg: packet segment the field being set belongs to 1231 * @fld: field to be set 1232 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from 1233 * entry's input buffer 1234 * @pref_loc: location of prefix value from entry's input buffer 1235 * @pref_sz: size of the location holding the prefix value 1236 * 1237 * This function specifies the locations, in the form of byte offsets from the 1238 * start of the input buffer for a flow entry, from where the value to match 1239 * and the IPv4 prefix value can be extracted. These locations are then stored 1240 * in the flow profile. When adding flow entries to the associated flow profile, 1241 * these locations can be used to quickly extract the values to create the 1242 * content of a match entry. This function should only be used for fixed-size 1243 * data structures. 1244 */ 1245 void 1246 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld, 1247 u16 val_loc, u16 pref_loc, u8 pref_sz) 1248 { 1249 /* For this type of field, the "mask" location is for the prefix value's 1250 * location and the "last" location is for the size of the location of 1251 * the prefix value. 1252 */ 1253 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc, 1254 pref_loc, (u16)pref_sz); 1255 } 1256 1257 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \ 1258 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 1259 1260 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \ 1261 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 1262 1263 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \ 1264 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \ 1265 ICE_FLOW_RSS_SEG_HDR_L4_MASKS) 1266 1267 /** 1268 * ice_flow_set_rss_seg_info - setup packet segments for RSS 1269 * @segs: pointer to the flow field segment(s) 1270 * @seg_cnt: segment count 1271 * @cfg: configure parameters 1272 * 1273 * Helper function to extract fields from hash bitmap and use flow 1274 * header value to set flow field segment for further use in flow 1275 * profile entry or removal. 1276 */ 1277 static int 1278 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt, 1279 const struct ice_rss_hash_cfg *cfg) 1280 { 1281 struct ice_flow_seg_info *seg; 1282 u64 val; 1283 u16 i; 1284 1285 /* set inner most segment */ 1286 seg = &segs[seg_cnt - 1]; 1287 1288 ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds, 1289 (u16)ICE_FLOW_FIELD_IDX_MAX) 1290 ice_flow_set_fld(seg, (enum ice_flow_field)i, 1291 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL, 1292 ICE_FLOW_FLD_OFF_INVAL, false); 1293 1294 ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs); 1295 1296 /* set outer most header */ 1297 if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4) 1298 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 1299 ICE_FLOW_SEG_HDR_IPV_FRAG | 1300 ICE_FLOW_SEG_HDR_IPV_OTHER; 1301 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6) 1302 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 1303 ICE_FLOW_SEG_HDR_IPV_FRAG | 1304 ICE_FLOW_SEG_HDR_IPV_OTHER; 1305 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4_GRE) 1306 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 | 1307 ICE_FLOW_SEG_HDR_GRE | 1308 ICE_FLOW_SEG_HDR_IPV_OTHER; 1309 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6_GRE) 1310 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 | 1311 ICE_FLOW_SEG_HDR_GRE | 1312 ICE_FLOW_SEG_HDR_IPV_OTHER; 1313 1314 if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS) 1315 return ICE_ERR_PARAM; 1316 1317 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS); 1318 if (val && !ice_is_pow2(val)) 1319 return ICE_ERR_CFG; 1320 1321 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS); 1322 if (val && !ice_is_pow2(val)) 1323 return ICE_ERR_CFG; 1324 1325 return 0; 1326 } 1327 1328 /** 1329 * ice_rem_vsi_rss_list - remove VSI from RSS list 1330 * @hw: pointer to the hardware structure 1331 * @vsi_handle: software VSI handle 1332 * 1333 * Remove the VSI from all RSS configurations in the list. 1334 */ 1335 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle) 1336 { 1337 struct ice_rss_cfg *r, *tmp; 1338 1339 if (LIST_EMPTY(&hw->rss_list_head)) 1340 return; 1341 1342 ice_acquire_lock(&hw->rss_locks); 1343 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 1344 ice_rss_cfg, l_entry) 1345 if (ice_test_and_clear_bit(vsi_handle, r->vsis)) 1346 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 1347 LIST_DEL(&r->l_entry); 1348 ice_free(hw, r); 1349 } 1350 ice_release_lock(&hw->rss_locks); 1351 } 1352 1353 /** 1354 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI 1355 * @hw: pointer to the hardware structure 1356 * @vsi_handle: software VSI handle 1357 * 1358 * This function will iterate through all flow profiles and disassociate 1359 * the VSI from that profile. If the flow profile has no VSIs it will 1360 * be removed. 1361 */ 1362 int ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1363 { 1364 const enum ice_block blk = ICE_BLK_RSS; 1365 struct ice_flow_prof *p, *t; 1366 int status = 0; 1367 u16 vsig; 1368 1369 if (!ice_is_vsi_valid(hw, vsi_handle)) 1370 return ICE_ERR_PARAM; 1371 1372 if (LIST_EMPTY(&hw->fl_profs[blk])) 1373 return 0; 1374 1375 ice_acquire_lock(&hw->rss_locks); 1376 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof, 1377 l_entry) { 1378 int ret; 1379 1380 /* check if vsig is already removed */ 1381 ret = ice_vsig_find_vsi(hw, blk, 1382 ice_get_hw_vsi_num(hw, vsi_handle), 1383 &vsig); 1384 if (!ret && !vsig) 1385 break; 1386 1387 if (ice_is_bit_set(p->vsis, vsi_handle)) { 1388 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle); 1389 if (status) 1390 break; 1391 1392 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) { 1393 status = ice_flow_rem_prof(hw, blk, p->id); 1394 if (status) 1395 break; 1396 } 1397 } 1398 } 1399 ice_release_lock(&hw->rss_locks); 1400 1401 return status; 1402 } 1403 1404 /** 1405 * ice_get_rss_hdr_type - get a RSS profile's header type 1406 * @prof: RSS flow profile 1407 */ 1408 static enum ice_rss_cfg_hdr_type 1409 ice_get_rss_hdr_type(struct ice_flow_prof *prof) 1410 { 1411 enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS; 1412 1413 if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) { 1414 hdr_type = ICE_RSS_OUTER_HEADERS; 1415 } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) { 1416 const struct ice_flow_seg_info *s; 1417 1418 s = &prof->segs[ICE_RSS_OUTER_HEADERS]; 1419 if (s->hdrs == ICE_FLOW_SEG_HDR_NONE) 1420 hdr_type = ICE_RSS_INNER_HEADERS; 1421 if (s->hdrs & ICE_FLOW_SEG_HDR_IPV4) 1422 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4; 1423 if (s->hdrs & ICE_FLOW_SEG_HDR_IPV6) 1424 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6; 1425 } 1426 1427 return hdr_type; 1428 } 1429 1430 /** 1431 * ice_rem_rss_list - remove RSS configuration from list 1432 * @hw: pointer to the hardware structure 1433 * @vsi_handle: software VSI handle 1434 * @prof: pointer to flow profile 1435 * 1436 * Assumption: lock has already been acquired for RSS list 1437 */ 1438 static void 1439 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 1440 { 1441 enum ice_rss_cfg_hdr_type hdr_type; 1442 struct ice_rss_cfg *r, *tmp; 1443 u64 seg_match = 0; 1444 u16 i; 1445 1446 /* convert match bitmap to u64 for hash field comparison */ 1447 ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match, 1448 ICE_FLOW_FIELD_IDX_MAX) { 1449 seg_match |= 1ULL << i; 1450 } 1451 1452 /* Search for RSS hash fields associated to the VSI that match the 1453 * hash configurations associated to the flow profile. If found 1454 * remove from the RSS entry list of the VSI context and delete entry. 1455 */ 1456 hdr_type = ice_get_rss_hdr_type(prof); 1457 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head, 1458 ice_rss_cfg, l_entry) 1459 if (r->hash.hash_flds == seg_match && 1460 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 1461 r->hash.hdr_type == hdr_type) { 1462 ice_clear_bit(vsi_handle, r->vsis); 1463 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) { 1464 LIST_DEL(&r->l_entry); 1465 ice_free(hw, r); 1466 } 1467 return; 1468 } 1469 } 1470 1471 /** 1472 * ice_add_rss_list - add RSS configuration to list 1473 * @hw: pointer to the hardware structure 1474 * @vsi_handle: software VSI handle 1475 * @prof: pointer to flow profile 1476 * 1477 * Assumption: lock has already been acquired for RSS list 1478 */ 1479 static int 1480 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof) 1481 { 1482 enum ice_rss_cfg_hdr_type hdr_type; 1483 struct ice_rss_cfg *r, *rss_cfg; 1484 u64 seg_match = 0; 1485 u16 i; 1486 1487 ice_for_each_set_bit(i, prof->segs[prof->segs_cnt - 1].match, 1488 ICE_FLOW_FIELD_IDX_MAX) { 1489 seg_match |= 1ULL << i; 1490 } 1491 1492 hdr_type = ice_get_rss_hdr_type(prof); 1493 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 1494 ice_rss_cfg, l_entry) 1495 if (r->hash.hash_flds == seg_match && 1496 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs && 1497 r->hash.hdr_type == hdr_type) { 1498 ice_set_bit(vsi_handle, r->vsis); 1499 return 0; 1500 } 1501 1502 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg)); 1503 if (!rss_cfg) 1504 return ICE_ERR_NO_MEMORY; 1505 1506 rss_cfg->hash.hash_flds = seg_match; 1507 rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs; 1508 rss_cfg->hash.hdr_type = hdr_type; 1509 rss_cfg->hash.symm = prof->cfg.symm; 1510 ice_set_bit(vsi_handle, rss_cfg->vsis); 1511 1512 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head); 1513 1514 return 0; 1515 } 1516 1517 #define ICE_FLOW_PROF_HASH_S 0 1518 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 1519 #define ICE_FLOW_PROF_HDR_S 32 1520 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 1521 #define ICE_FLOW_PROF_ENCAP_S 62 1522 #define ICE_FLOW_PROF_ENCAP_M (0x3ULL << ICE_FLOW_PROF_ENCAP_S) 1523 1524 /* Flow profile ID format: 1525 * [0:31] - Packet match fields 1526 * [32:61] - Protocol header 1527 * [62:63] - Encapsulation flag: 1528 * 0 if non-tunneled 1529 * 1 if tunneled 1530 * 2 for tunneled with outer IPv4 1531 * 3 for tunneled with outer IPv6 1532 */ 1533 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \ 1534 ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 1535 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 1536 (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & \ 1537 ICE_FLOW_PROF_ENCAP_M))) 1538 1539 /** 1540 * ice_add_rss_cfg_sync - add an RSS configuration 1541 * @hw: pointer to the hardware structure 1542 * @vsi_handle: software VSI handle 1543 * @cfg: configure parameters 1544 * 1545 * Assumption: lock has already been acquired for RSS list 1546 */ 1547 static int 1548 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 1549 const struct ice_rss_hash_cfg *cfg) 1550 { 1551 const enum ice_block blk = ICE_BLK_RSS; 1552 struct ice_flow_prof *prof = NULL; 1553 struct ice_flow_seg_info *segs; 1554 u8 segs_cnt; 1555 int status; 1556 1557 if (cfg->symm) 1558 return ICE_ERR_PARAM; 1559 1560 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 1561 ICE_FLOW_SEG_SINGLE : 1562 ICE_FLOW_SEG_MAX; 1563 1564 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 1565 sizeof(*segs)); 1566 if (!segs) 1567 return ICE_ERR_NO_MEMORY; 1568 1569 /* Construct the packet segment info from the hashed fields */ 1570 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 1571 if (status) 1572 goto exit; 1573 1574 /* Search for a flow profile that has matching headers, hash fields 1575 * and has the input VSI associated to it. If found, no further 1576 * operations required and exit. 1577 */ 1578 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1579 vsi_handle, 1580 ICE_FLOW_FIND_PROF_CHK_FLDS | 1581 ICE_FLOW_FIND_PROF_CHK_VSI); 1582 if (prof) 1583 goto exit; 1584 1585 /* Check if a flow profile exists with the same protocol headers and 1586 * associated with the input VSI. If so disassociate the VSI from 1587 * this profile. The VSI will be added to a new profile created with 1588 * the protocol header and new hash field configuration. 1589 */ 1590 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1591 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI); 1592 if (prof) { 1593 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1594 if (!status) 1595 ice_rem_rss_list(hw, vsi_handle, prof); 1596 else 1597 goto exit; 1598 1599 /* Remove profile if it has no VSIs associated */ 1600 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) { 1601 status = ice_flow_rem_prof(hw, blk, prof->id); 1602 if (status) 1603 goto exit; 1604 } 1605 } 1606 1607 /* Search for a profile that has same match fields only. If this 1608 * exists then associate the VSI to this profile. 1609 */ 1610 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1611 vsi_handle, 1612 ICE_FLOW_FIND_PROF_CHK_FLDS); 1613 if (prof) { 1614 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1615 if (!status) 1616 status = ice_add_rss_list(hw, vsi_handle, prof); 1617 goto exit; 1618 } 1619 1620 /* Create a new flow profile with generated profile and packet 1621 * segment information. 1622 */ 1623 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX, 1624 ICE_FLOW_GEN_PROFID(cfg->hash_flds, 1625 segs[segs_cnt - 1].hdrs, 1626 cfg->hdr_type), 1627 segs, segs_cnt, NULL, 0, &prof); 1628 if (status) 1629 goto exit; 1630 1631 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle); 1632 /* If association to a new flow profile failed then this profile can 1633 * be removed. 1634 */ 1635 if (status) { 1636 ice_flow_rem_prof(hw, blk, prof->id); 1637 goto exit; 1638 } 1639 1640 status = ice_add_rss_list(hw, vsi_handle, prof); 1641 1642 prof->cfg.symm = cfg->symm; 1643 1644 exit: 1645 ice_free(hw, segs); 1646 return status; 1647 } 1648 1649 /** 1650 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields 1651 * @hw: pointer to the hardware structure 1652 * @vsi_handle: software VSI handle 1653 * @cfg: configure parameters 1654 * 1655 * This function will generate a flow profile based on fields associated with 1656 * the input fields to hash on, the flow type and use the VSI number to add 1657 * a flow entry to the profile. 1658 */ 1659 int 1660 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 1661 const struct ice_rss_hash_cfg *cfg) 1662 { 1663 struct ice_rss_hash_cfg local_cfg; 1664 int status; 1665 1666 if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || 1667 cfg->hdr_type > ICE_RSS_ANY_HEADERS || 1668 cfg->hash_flds == ICE_HASH_INVALID) 1669 return ICE_ERR_PARAM; 1670 1671 ice_acquire_lock(&hw->rss_locks); 1672 local_cfg = *cfg; 1673 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 1674 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1675 } else { 1676 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 1677 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1678 if (!status) { 1679 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 1680 status = ice_add_rss_cfg_sync(hw, vsi_handle, 1681 &local_cfg); 1682 } 1683 } 1684 ice_release_lock(&hw->rss_locks); 1685 1686 return status; 1687 } 1688 1689 /** 1690 * ice_rem_rss_cfg_sync - remove an existing RSS configuration 1691 * @hw: pointer to the hardware structure 1692 * @vsi_handle: software VSI handle 1693 * @cfg: configure parameters 1694 * 1695 * Assumption: lock has already been acquired for RSS list 1696 */ 1697 static int 1698 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, 1699 const struct ice_rss_hash_cfg *cfg) 1700 { 1701 const enum ice_block blk = ICE_BLK_RSS; 1702 struct ice_flow_seg_info *segs; 1703 struct ice_flow_prof *prof; 1704 u8 segs_cnt; 1705 int status; 1706 1707 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ? 1708 ICE_FLOW_SEG_SINGLE : 1709 ICE_FLOW_SEG_MAX; 1710 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt, 1711 sizeof(*segs)); 1712 if (!segs) 1713 return ICE_ERR_NO_MEMORY; 1714 1715 /* Construct the packet segment info from the hashed fields */ 1716 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg); 1717 if (status) 1718 goto out; 1719 1720 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt, 1721 vsi_handle, 1722 ICE_FLOW_FIND_PROF_CHK_FLDS); 1723 if (!prof) { 1724 status = ICE_ERR_DOES_NOT_EXIST; 1725 goto out; 1726 } 1727 1728 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle); 1729 if (status) 1730 goto out; 1731 1732 /* Remove RSS configuration from VSI context before deleting 1733 * the flow profile. 1734 */ 1735 ice_rem_rss_list(hw, vsi_handle, prof); 1736 1737 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) 1738 status = ice_flow_rem_prof(hw, blk, prof->id); 1739 1740 out: 1741 ice_free(hw, segs); 1742 return status; 1743 } 1744 1745 /** 1746 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields 1747 * @hw: pointer to the hardware structure 1748 * @vsi_handle: software VSI handle 1749 * @cfg: configure parameters 1750 * 1751 * This function will lookup the flow profile based on the input 1752 * hash field bitmap, iterate through the profile entry list of 1753 * that profile and find entry associated with input VSI to be 1754 * removed. Calls are made to underlying flow apis which will in 1755 * turn build or update buffers for RSS XLT1 section. 1756 */ 1757 int 1758 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, 1759 const struct ice_rss_hash_cfg *cfg) 1760 { 1761 struct ice_rss_hash_cfg local_cfg; 1762 int status; 1763 1764 if (!ice_is_vsi_valid(hw, vsi_handle) || !cfg || 1765 cfg->hdr_type > ICE_RSS_ANY_HEADERS || 1766 cfg->hash_flds == ICE_HASH_INVALID) 1767 return ICE_ERR_PARAM; 1768 1769 ice_acquire_lock(&hw->rss_locks); 1770 local_cfg = *cfg; 1771 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) { 1772 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1773 } else { 1774 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS; 1775 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg); 1776 if (!status) { 1777 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS; 1778 status = ice_rem_rss_cfg_sync(hw, vsi_handle, 1779 &local_cfg); 1780 } 1781 } 1782 ice_release_lock(&hw->rss_locks); 1783 1784 return status; 1785 } 1786 1787 /* Mapping of AVF hash bit fields to an L3-L4 hash combination. 1788 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash, 1789 * convert its values to their appropriate flow L3, L4 values. 1790 */ 1791 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \ 1792 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \ 1793 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4)) 1794 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \ 1795 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \ 1796 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP)) 1797 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \ 1798 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \ 1799 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \ 1800 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP)) 1801 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \ 1802 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \ 1803 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) 1804 1805 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \ 1806 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \ 1807 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6)) 1808 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \ 1809 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \ 1810 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \ 1811 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP)) 1812 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \ 1813 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \ 1814 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP)) 1815 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \ 1816 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \ 1817 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) 1818 1819 /** 1820 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver 1821 * @hw: pointer to the hardware structure 1822 * @vsi_handle: software VSI handle 1823 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure 1824 * 1825 * This function will take the hash bitmap provided by the AVF driver via a 1826 * message, convert it to ICE-compatible values, and configure RSS flow 1827 * profiles. 1828 */ 1829 int ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash) 1830 { 1831 struct ice_rss_hash_cfg hcfg; 1832 int status = 0; 1833 u64 hash_flds; 1834 1835 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID || 1836 !ice_is_vsi_valid(hw, vsi_handle)) 1837 return ICE_ERR_PARAM; 1838 1839 /* Make sure no unsupported bits are specified */ 1840 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS | 1841 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)) 1842 return ICE_ERR_CFG; 1843 1844 hash_flds = avf_hash; 1845 1846 /* Always create an L3 RSS configuration for any L4 RSS configuration */ 1847 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) 1848 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS; 1849 1850 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) 1851 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS; 1852 1853 /* Create the corresponding RSS configuration for each valid hash bit */ 1854 while (hash_flds) { 1855 u64 rss_hash = ICE_HASH_INVALID; 1856 1857 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) { 1858 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) { 1859 rss_hash = ICE_FLOW_HASH_IPV4; 1860 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS; 1861 } else if (hash_flds & 1862 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) { 1863 rss_hash = ICE_FLOW_HASH_IPV4 | 1864 ICE_FLOW_HASH_TCP_PORT; 1865 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS; 1866 } else if (hash_flds & 1867 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) { 1868 rss_hash = ICE_FLOW_HASH_IPV4 | 1869 ICE_FLOW_HASH_UDP_PORT; 1870 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS; 1871 } else if (hash_flds & 1872 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) { 1873 rss_hash = ICE_FLOW_HASH_IPV4 | 1874 ICE_FLOW_HASH_SCTP_PORT; 1875 hash_flds &= 1876 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP); 1877 } 1878 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) { 1879 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) { 1880 rss_hash = ICE_FLOW_HASH_IPV6; 1881 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS; 1882 } else if (hash_flds & 1883 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) { 1884 rss_hash = ICE_FLOW_HASH_IPV6 | 1885 ICE_FLOW_HASH_TCP_PORT; 1886 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS; 1887 } else if (hash_flds & 1888 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) { 1889 rss_hash = ICE_FLOW_HASH_IPV6 | 1890 ICE_FLOW_HASH_UDP_PORT; 1891 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS; 1892 } else if (hash_flds & 1893 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) { 1894 rss_hash = ICE_FLOW_HASH_IPV6 | 1895 ICE_FLOW_HASH_SCTP_PORT; 1896 hash_flds &= 1897 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP); 1898 } 1899 } 1900 1901 if (rss_hash == ICE_HASH_INVALID) 1902 return ICE_ERR_OUT_OF_RANGE; 1903 1904 hcfg.addl_hdrs = ICE_FLOW_SEG_HDR_NONE; 1905 hcfg.hash_flds = rss_hash; 1906 hcfg.symm = false; 1907 hcfg.hdr_type = ICE_RSS_ANY_HEADERS; 1908 status = ice_add_rss_cfg(hw, vsi_handle, &hcfg); 1909 if (status) 1910 break; 1911 } 1912 1913 return status; 1914 } 1915 1916 /** 1917 * ice_replay_rss_cfg - replay RSS configurations associated with VSI 1918 * @hw: pointer to the hardware structure 1919 * @vsi_handle: software VSI handle 1920 */ 1921 int ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle) 1922 { 1923 struct ice_rss_cfg *r; 1924 int status = 0; 1925 1926 if (!ice_is_vsi_valid(hw, vsi_handle)) 1927 return ICE_ERR_PARAM; 1928 1929 ice_acquire_lock(&hw->rss_locks); 1930 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 1931 ice_rss_cfg, l_entry) { 1932 if (ice_is_bit_set(r->vsis, vsi_handle)) { 1933 status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash); 1934 if (status) 1935 break; 1936 } 1937 } 1938 ice_release_lock(&hw->rss_locks); 1939 1940 return status; 1941 } 1942 1943 /** 1944 * ice_get_rss_cfg - returns hashed fields for the given header types 1945 * @hw: pointer to the hardware structure 1946 * @vsi_handle: software VSI handle 1947 * @hdrs: protocol header type 1948 * 1949 * This function will return the match fields of the first instance of flow 1950 * profile having the given header types and containing input VSI 1951 */ 1952 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs) 1953 { 1954 u64 rss_hash = ICE_HASH_INVALID; 1955 struct ice_rss_cfg *r; 1956 1957 /* verify if the protocol header is non zero and VSI is valid */ 1958 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle)) 1959 return ICE_HASH_INVALID; 1960 1961 ice_acquire_lock(&hw->rss_locks); 1962 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head, 1963 ice_rss_cfg, l_entry) 1964 if (ice_is_bit_set(r->vsis, vsi_handle) && 1965 r->hash.addl_hdrs == hdrs) { 1966 rss_hash = r->hash.hash_flds; 1967 break; 1968 } 1969 ice_release_lock(&hw->rss_locks); 1970 1971 return rss_hash; 1972 } 1973