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