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