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