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