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