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