1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright (c) 2020, Intel Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
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.
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.
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.
33 #include "ice_common.h"
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
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 */
58 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
60 .off = (_offset_bytes) * BITS_PER_BYTE, \
61 .size = (_size_bytes) * BITS_PER_BYTE, \
64 /* Table containing properties of supported protocol header fields */
66 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
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, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
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),
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),
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),
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),
131 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
132 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
135 /* Bitmaps indicating relevant packet types for a particular protocol header
137 * Packet types for packets with an Outer/First/Single MAC header
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,
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,
162 /* Packet types for packets with an Outer/First/Single IPv4 header */
163 static const u32 ice_ptypes_ipv4_ofos[] = {
164 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
165 0x00000000, 0x00000000, 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,
174 /* Packet types for packets with an Innermost/Last IPv4 header */
175 static const u32 ice_ptypes_ipv4_il[] = {
176 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
177 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
178 0x00000000, 0x00000000, 0x00000000, 0x00000000,
179 0x00000000, 0x00000000, 0x00000000, 0x00000000,
180 0x00000000, 0x00000000, 0x00000000, 0x00000000,
181 0x00000000, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 /* Packet types for packets with an Outer/First/Single IPv6 header */
187 static const u32 ice_ptypes_ipv6_ofos[] = {
188 0x00000000, 0x00000000, 0x77000000, 0x10002000,
189 0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 0x00000000, 0x00000000, 0x00000000, 0x00000000,
191 0x00000000, 0x00000000, 0x00000000, 0x00000000,
192 0x00000000, 0x00000000, 0x00000000, 0x00000000,
193 0x00000000, 0x00000000, 0x00000000, 0x00000000,
194 0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 /* Packet types for packets with an Innermost/Last IPv6 header */
199 static const u32 ice_ptypes_ipv6_il[] = {
200 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
201 0x00000770, 0x00000000, 0x00000000, 0x00000000,
202 0x00000000, 0x00000000, 0x00000000, 0x00000000,
203 0x00000000, 0x00000000, 0x00000000, 0x00000000,
204 0x00000000, 0x00000000, 0x00000000, 0x00000000,
205 0x00000000, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x00000000, 0x00000000,
207 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 /* Packet types for packets with an Outermost/First ARP header */
211 static const u32 ice_ptypes_arp_of[] = {
212 0x00000800, 0x00000000, 0x00000000, 0x00000000,
213 0x00000000, 0x00000000, 0x00000000, 0x00000000,
214 0x00000000, 0x00000000, 0x00000000, 0x00000000,
215 0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
222 /* UDP Packet types for non-tunneled packets or tunneled
223 * packets with inner UDP.
225 static const u32 ice_ptypes_udp_il[] = {
226 0x81000000, 0x20204040, 0x04000010, 0x80810102,
227 0x00000040, 0x00000000, 0x00000000, 0x00000000,
228 0x00000000, 0x00000000, 0x00000000, 0x00000000,
229 0x00000000, 0x00000000, 0x00000000, 0x00000000,
230 0x00000000, 0x00000000, 0x00000000, 0x00000000,
231 0x00000000, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 0x00000000, 0x00000000, 0x00000000,
233 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 /* Packet types for packets with an Innermost/Last TCP header */
237 static const u32 ice_ptypes_tcp_il[] = {
238 0x04000000, 0x80810102, 0x10000040, 0x02040408,
239 0x00000102, 0x00000000, 0x00000000, 0x00000000,
240 0x00000000, 0x00000000, 0x00000000, 0x00000000,
241 0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 /* Packet types for packets with an Innermost/Last SCTP header */
249 static const u32 ice_ptypes_sctp_il[] = {
250 0x08000000, 0x01020204, 0x20000081, 0x04080810,
251 0x00000204, 0x00000000, 0x00000000, 0x00000000,
252 0x00000000, 0x00000000, 0x00000000, 0x00000000,
253 0x00000000, 0x00000000, 0x00000000, 0x00000000,
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 /* Packet types for packets with an Outermost/First ICMP header */
261 static const u32 ice_ptypes_icmp_of[] = {
262 0x10000000, 0x00000000, 0x00000000, 0x00000000,
263 0x00000000, 0x00000000, 0x00000000, 0x00000000,
264 0x00000000, 0x00000000, 0x00000000, 0x00000000,
265 0x00000000, 0x00000000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 /* Packet types for packets with an Innermost/Last ICMP header */
273 static const u32 ice_ptypes_icmp_il[] = {
274 0x00000000, 0x02040408, 0x40000102, 0x08101020,
275 0x00000408, 0x00000000, 0x00000000, 0x00000000,
276 0x00000000, 0x00000000, 0x00000000, 0x00000000,
277 0x00000000, 0x00000000, 0x00000000, 0x00000000,
278 0x00000000, 0x00000000, 0x00000000, 0x00000000,
279 0x00000000, 0x00000000, 0x00000000, 0x00000000,
280 0x00000000, 0x00000000, 0x00000000, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 /* Packet types for packets with an Outermost/First GRE header */
285 static const u32 ice_ptypes_gre_of[] = {
286 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
287 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
288 0x00000000, 0x00000000, 0x00000000, 0x00000000,
289 0x00000000, 0x00000000, 0x00000000, 0x00000000,
290 0x00000000, 0x00000000, 0x00000000, 0x00000000,
291 0x00000000, 0x00000000, 0x00000000, 0x00000000,
292 0x00000000, 0x00000000, 0x00000000, 0x00000000,
293 0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 /* Packet types for packets with an Innermost/Last MAC header */
297 static const u32 ice_ptypes_mac_il[] = {
298 0x00000000, 0x00000000, 0x00000000, 0x00000000,
299 0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 0x00000000, 0x00000000, 0x00000000, 0x00000000,
301 0x00000000, 0x00000000, 0x00000000, 0x00000000,
302 0x00000000, 0x00000000, 0x00000000, 0x00000000,
303 0x00000000, 0x00000000, 0x00000000, 0x00000000,
304 0x00000000, 0x00000000, 0x00000000, 0x00000000,
305 0x00000000, 0x00000000, 0x00000000, 0x00000000,
308 /* Manage parameters and info. used during the creation of a flow profile */
309 struct ice_flow_prof_params {
311 u16 entry_length; /* # of bytes formatted entry will require */
313 struct ice_flow_prof *prof;
315 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
316 * This will give us the direction flags.
318 struct ice_fv_word es[ICE_MAX_FV_WORDS];
319 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
322 #define ICE_FLOW_SEG_HDRS_L3_MASK \
323 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
324 ICE_FLOW_SEG_HDR_ARP)
325 #define ICE_FLOW_SEG_HDRS_L4_MASK \
326 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
327 ICE_FLOW_SEG_HDR_SCTP)
330 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
331 * @segs: array of one or more packet segments that describe the flow
332 * @segs_cnt: number of packet segments provided
334 static enum ice_status
335 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
339 for (i = 0; i < segs_cnt; i++) {
340 /* Multiple L3 headers */
341 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
342 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
343 return ICE_ERR_PARAM;
345 /* Multiple L4 headers */
346 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
347 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
348 return ICE_ERR_PARAM;
354 /* Sizes of fixed known protocol headers without header options */
355 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
356 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
357 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
358 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
359 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
360 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
361 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
362 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
363 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
366 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
367 * @params: information about the flow to be processed
368 * @seg: index of packet segment whose header size is to be determined
370 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
375 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
376 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
379 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
380 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
381 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
382 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
383 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
384 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
385 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
386 /* A L3 header is required if L4 is specified */
390 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
391 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
392 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
393 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
394 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
395 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
396 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
397 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
403 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
404 * @params: information about the flow to be processed
406 * This function identifies the packet types associated with the protocol
407 * headers being present in packet segments of the specified flow profile.
409 static enum ice_status
410 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
412 struct ice_flow_prof *prof;
415 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
420 for (i = 0; i < params->prof->segs_cnt; i++) {
421 const ice_bitmap_t *src;
424 hdrs = prof->segs[i].hdrs;
426 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
427 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
428 (const ice_bitmap_t *)ice_ptypes_mac_il;
429 ice_and_bitmap(params->ptypes, params->ptypes, src,
433 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
434 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
435 ice_and_bitmap(params->ptypes, params->ptypes, src,
439 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
440 ice_and_bitmap(params->ptypes, params->ptypes,
441 (const ice_bitmap_t *)ice_ptypes_arp_of,
445 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
446 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
447 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
448 ice_and_bitmap(params->ptypes, params->ptypes, src,
450 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
451 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
452 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
453 ice_and_bitmap(params->ptypes, params->ptypes, src,
457 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
458 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
459 (const ice_bitmap_t *)ice_ptypes_icmp_il;
460 ice_and_bitmap(params->ptypes, params->ptypes, src,
462 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
463 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
464 ice_and_bitmap(params->ptypes, params->ptypes, src,
466 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
467 ice_and_bitmap(params->ptypes, params->ptypes,
468 (const ice_bitmap_t *)ice_ptypes_tcp_il,
470 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
471 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
472 ice_and_bitmap(params->ptypes, params->ptypes, src,
474 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
476 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
477 ice_and_bitmap(params->ptypes, params->ptypes,
478 src, ICE_FLOW_PTYPE_MAX);
487 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
488 * @hw: pointer to the HW struct
489 * @params: information about the flow to be processed
490 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
492 * This function will allocate an extraction sequence entries for a DWORD size
493 * chunk of the packet flags.
495 static enum ice_status
496 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
497 struct ice_flow_prof_params *params,
498 enum ice_flex_mdid_pkt_flags flags)
500 u8 fv_words = hw->blk[params->blk].es.fvw;
503 /* Make sure the number of extraction sequence entries required does not
504 * exceed the block's capacity.
506 if (params->es_cnt >= fv_words)
507 return ICE_ERR_MAX_LIMIT;
509 /* some blocks require a reversed field vector layout */
510 if (hw->blk[params->blk].es.reverse)
511 idx = fv_words - params->es_cnt - 1;
513 idx = params->es_cnt;
515 params->es[idx].prot_id = ICE_PROT_META_ID;
516 params->es[idx].off = flags;
523 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
524 * @hw: pointer to the HW struct
525 * @params: information about the flow to be processed
526 * @seg: packet segment index of the field to be extracted
527 * @fld: ID of field to be extracted
529 * This function determines the protocol ID, offset, and size of the given
530 * field. It then allocates one or more extraction sequence entries for the
531 * given field, and fill the entries with protocol ID and offset information.
533 static enum ice_status
534 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
535 u8 seg, enum ice_flow_field fld)
537 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
538 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
539 u8 fv_words = hw->blk[params->blk].es.fvw;
540 struct ice_flow_fld_info *flds;
541 u16 cnt, ese_bits, i;
545 flds = params->prof->segs[seg].fields;
548 case ICE_FLOW_FIELD_IDX_ETH_DA:
549 case ICE_FLOW_FIELD_IDX_ETH_SA:
550 case ICE_FLOW_FIELD_IDX_S_VLAN:
551 case ICE_FLOW_FIELD_IDX_C_VLAN:
552 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
554 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
555 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
557 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
558 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
560 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
561 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
563 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
564 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
565 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
567 /* TTL and PROT share the same extraction seq. entry.
568 * Each is considered a sibling to the other in terms of sharing
569 * the same extraction sequence entry.
571 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
572 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
573 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
574 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
576 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
577 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
578 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
580 /* TTL and PROT share the same extraction seq. entry.
581 * Each is considered a sibling to the other in terms of sharing
582 * the same extraction sequence entry.
584 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
585 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
586 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
587 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
589 case ICE_FLOW_FIELD_IDX_IPV4_SA:
590 case ICE_FLOW_FIELD_IDX_IPV4_DA:
591 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
593 case ICE_FLOW_FIELD_IDX_IPV6_SA:
594 case ICE_FLOW_FIELD_IDX_IPV6_DA:
595 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
597 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
598 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
599 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
600 prot_id = ICE_PROT_TCP_IL;
602 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
603 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
604 prot_id = ICE_PROT_UDP_IL_OR_S;
606 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
607 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
608 prot_id = ICE_PROT_SCTP_IL;
610 case ICE_FLOW_FIELD_IDX_ARP_SIP:
611 case ICE_FLOW_FIELD_IDX_ARP_DIP:
612 case ICE_FLOW_FIELD_IDX_ARP_SHA:
613 case ICE_FLOW_FIELD_IDX_ARP_DHA:
614 case ICE_FLOW_FIELD_IDX_ARP_OP:
615 prot_id = ICE_PROT_ARP_OF;
617 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
618 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
619 /* ICMP type and code share the same extraction seq. entry */
620 prot_id = (params->prof->segs[seg].hdrs &
621 ICE_FLOW_SEG_HDR_IPV4) ?
622 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
623 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
624 ICE_FLOW_FIELD_IDX_ICMP_CODE :
625 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
627 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
628 prot_id = ICE_PROT_GRE_OF;
631 return ICE_ERR_NOT_IMPL;
634 /* Each extraction sequence entry is a word in size, and extracts a
635 * word-aligned offset from a protocol header.
637 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
639 flds[fld].xtrct.prot_id = prot_id;
640 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
641 ICE_FLOW_FV_EXTRACT_SZ;
642 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
643 flds[fld].xtrct.idx = params->es_cnt;
645 /* Adjust the next field-entry index after accommodating the number of
646 * entries this field consumes
648 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
649 ice_flds_info[fld].size, ese_bits);
651 /* Fill in the extraction sequence entries needed for this field */
652 off = flds[fld].xtrct.off;
653 for (i = 0; i < cnt; i++) {
654 /* Only consume an extraction sequence entry if there is no
655 * sibling field associated with this field or the sibling entry
656 * already extracts the word shared with this field.
658 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
659 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
660 flds[sib].xtrct.off != off) {
663 /* Make sure the number of extraction sequence required
664 * does not exceed the block's capability
666 if (params->es_cnt >= fv_words)
667 return ICE_ERR_MAX_LIMIT;
669 /* some blocks require a reversed field vector layout */
670 if (hw->blk[params->blk].es.reverse)
671 idx = fv_words - params->es_cnt - 1;
673 idx = params->es_cnt;
675 params->es[idx].prot_id = prot_id;
676 params->es[idx].off = off;
680 off += ICE_FLOW_FV_EXTRACT_SZ;
687 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
688 * @hw: pointer to the HW struct
689 * @params: information about the flow to be processed
690 * @seg: index of packet segment whose raw fields are to be be extracted
692 static enum ice_status
693 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
700 if (!params->prof->segs[seg].raws_cnt)
703 if (params->prof->segs[seg].raws_cnt >
704 ARRAY_SIZE(params->prof->segs[seg].raws))
705 return ICE_ERR_MAX_LIMIT;
707 /* Offsets within the segment headers are not supported */
708 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
710 return ICE_ERR_PARAM;
712 fv_words = hw->blk[params->blk].es.fvw;
714 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
715 struct ice_flow_seg_fld_raw *raw;
718 raw = ¶ms->prof->segs[seg].raws[i];
720 /* Storing extraction information */
721 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
722 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
723 ICE_FLOW_FV_EXTRACT_SZ;
724 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
726 raw->info.xtrct.idx = params->es_cnt;
728 /* Determine the number of field vector entries this raw field
731 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
732 (raw->info.src.last * BITS_PER_BYTE),
733 (ICE_FLOW_FV_EXTRACT_SZ *
735 off = raw->info.xtrct.off;
736 for (j = 0; j < cnt; j++) {
739 /* Make sure the number of extraction sequence required
740 * does not exceed the block's capability
742 if (params->es_cnt >= hw->blk[params->blk].es.count ||
743 params->es_cnt >= ICE_MAX_FV_WORDS)
744 return ICE_ERR_MAX_LIMIT;
746 /* some blocks require a reversed field vector layout */
747 if (hw->blk[params->blk].es.reverse)
748 idx = fv_words - params->es_cnt - 1;
750 idx = params->es_cnt;
752 params->es[idx].prot_id = raw->info.xtrct.prot_id;
753 params->es[idx].off = off;
755 off += ICE_FLOW_FV_EXTRACT_SZ;
763 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
764 * @hw: pointer to the HW struct
765 * @params: information about the flow to be processed
767 * This function iterates through all matched fields in the given segments, and
768 * creates an extraction sequence for the fields.
770 static enum ice_status
771 ice_flow_create_xtrct_seq(struct ice_hw *hw,
772 struct ice_flow_prof_params *params)
774 enum ice_status status = ICE_SUCCESS;
777 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
780 if (params->blk == ICE_BLK_ACL) {
781 status = ice_flow_xtract_pkt_flags(hw, params,
782 ICE_RX_MDID_PKT_FLAGS_15_0);
787 for (i = 0; i < params->prof->segs_cnt; i++) {
788 u64 match = params->prof->segs[i].match;
789 enum ice_flow_field j;
791 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
792 const u64 bit = BIT_ULL(j);
795 status = ice_flow_xtract_fld(hw, params, i, j);
802 /* Process raw matching bytes */
803 status = ice_flow_xtract_raws(hw, params, i);
812 * ice_flow_proc_segs - process all packet segments associated with a profile
813 * @hw: pointer to the HW struct
814 * @params: information about the flow to be processed
816 static enum ice_status
817 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
819 enum ice_status status;
821 status = ice_flow_proc_seg_hdrs(params);
825 status = ice_flow_create_xtrct_seq(hw, params);
829 switch (params->blk) {
831 /* Only header information is provided for RSS configuration.
832 * No further processing is needed.
834 status = ICE_SUCCESS;
837 status = ICE_SUCCESS;
841 return ICE_ERR_NOT_IMPL;
847 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
848 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
849 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
852 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
853 * @hw: pointer to the HW struct
854 * @blk: classification stage
855 * @dir: flow direction
856 * @segs: array of one or more packet segments that describe the flow
857 * @segs_cnt: number of packet segments provided
858 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
859 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
861 static struct ice_flow_prof *
862 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
863 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
864 u8 segs_cnt, u16 vsi_handle, u32 conds)
866 struct ice_flow_prof *p, *prof = NULL;
868 ice_acquire_lock(&hw->fl_profs_locks[blk]);
869 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
870 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
871 segs_cnt && segs_cnt == p->segs_cnt) {
874 /* Check for profile-VSI association if specified */
875 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
876 ice_is_vsi_valid(hw, vsi_handle) &&
877 !ice_is_bit_set(p->vsis, vsi_handle))
880 /* Protocol headers must be checked. Matched fields are
881 * checked if specified.
883 for (i = 0; i < segs_cnt; i++)
884 if (segs[i].hdrs != p->segs[i].hdrs ||
885 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
886 segs[i].match != p->segs[i].match))
889 /* A match is found if all segments are matched */
896 ice_release_lock(&hw->fl_profs_locks[blk]);
902 * ice_flow_find_prof - Look up a profile matching headers and matched fields
903 * @hw: pointer to the HW struct
904 * @blk: classification stage
905 * @dir: flow direction
906 * @segs: array of one or more packet segments that describe the flow
907 * @segs_cnt: number of packet segments provided
910 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
911 struct ice_flow_seg_info *segs, u8 segs_cnt)
913 struct ice_flow_prof *p;
915 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
916 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
918 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
922 * ice_flow_find_prof_id - Look up a profile with given profile ID
923 * @hw: pointer to the HW struct
924 * @blk: classification stage
925 * @prof_id: unique ID to identify this flow profile
927 static struct ice_flow_prof *
928 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
930 struct ice_flow_prof *p;
932 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
933 if (p->id == prof_id)
941 * ice_dealloc_flow_entry - Deallocate flow entry memory
942 * @hw: pointer to the HW struct
943 * @entry: flow entry to be removed
946 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
952 ice_free(hw, entry->entry);
955 ice_free(hw, entry->acts);
964 * ice_flow_rem_entry_sync - Remove a flow entry
965 * @hw: pointer to the HW struct
966 * @blk: classification stage
967 * @entry: flow entry to be removed
969 static enum ice_status
970 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block __ALWAYS_UNUSED blk,
971 struct ice_flow_entry *entry)
974 return ICE_ERR_BAD_PTR;
976 LIST_DEL(&entry->l_entry);
978 ice_dealloc_flow_entry(hw, entry);
984 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
985 * @hw: pointer to the HW struct
986 * @blk: classification stage
987 * @dir: flow direction
988 * @prof_id: unique ID to identify this flow profile
989 * @segs: array of one or more packet segments that describe the flow
990 * @segs_cnt: number of packet segments provided
991 * @acts: array of default actions
992 * @acts_cnt: number of default actions
993 * @prof: stores the returned flow profile added
995 * Assumption: the caller has acquired the lock to the profile list
997 static enum ice_status
998 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
999 enum ice_flow_dir dir, u64 prof_id,
1000 struct ice_flow_seg_info *segs, u8 segs_cnt,
1001 struct ice_flow_action *acts, u8 acts_cnt,
1002 struct ice_flow_prof **prof)
1004 struct ice_flow_prof_params params;
1005 enum ice_status status;
1008 if (!prof || (acts_cnt && !acts))
1009 return ICE_ERR_BAD_PTR;
1011 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1012 params.prof = (struct ice_flow_prof *)
1013 ice_malloc(hw, sizeof(*params.prof));
1015 return ICE_ERR_NO_MEMORY;
1017 /* initialize extraction sequence to all invalid (0xff) */
1018 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1019 params.es[i].prot_id = ICE_PROT_INVALID;
1020 params.es[i].off = ICE_FV_OFFSET_INVAL;
1024 params.prof->id = prof_id;
1025 params.prof->dir = dir;
1026 params.prof->segs_cnt = segs_cnt;
1028 /* Make a copy of the segments that need to be persistent in the flow
1031 for (i = 0; i < segs_cnt; i++)
1032 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1033 ICE_NONDMA_TO_NONDMA);
1035 /* Make a copy of the actions that need to be persistent in the flow
1039 params.prof->acts = (struct ice_flow_action *)
1040 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1041 ICE_NONDMA_TO_NONDMA);
1043 if (!params.prof->acts) {
1044 status = ICE_ERR_NO_MEMORY;
1049 status = ice_flow_proc_segs(hw, ¶ms);
1051 ice_debug(hw, ICE_DBG_FLOW,
1052 "Error processing a flow's packet segments\n");
1056 /* Add a HW profile for this flow profile */
1057 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
1059 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1063 INIT_LIST_HEAD(¶ms.prof->entries);
1064 ice_init_lock(¶ms.prof->entries_lock);
1065 *prof = params.prof;
1069 if (params.prof->acts)
1070 ice_free(hw, params.prof->acts);
1071 ice_free(hw, params.prof);
1078 * ice_flow_rem_prof_sync - remove a flow profile
1079 * @hw: pointer to the hardware structure
1080 * @blk: classification stage
1081 * @prof: pointer to flow profile to remove
1083 * Assumption: the caller has acquired the lock to the profile list
1085 static enum ice_status
1086 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1087 struct ice_flow_prof *prof)
1089 enum ice_status status;
1091 /* Remove all remaining flow entries before removing the flow profile */
1092 if (!LIST_EMPTY(&prof->entries)) {
1093 struct ice_flow_entry *e, *t;
1095 ice_acquire_lock(&prof->entries_lock);
1097 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1099 status = ice_flow_rem_entry_sync(hw, blk, e);
1104 ice_release_lock(&prof->entries_lock);
1107 /* Remove all hardware profiles associated with this flow profile */
1108 status = ice_rem_prof(hw, blk, prof->id);
1110 LIST_DEL(&prof->l_entry);
1111 ice_destroy_lock(&prof->entries_lock);
1113 ice_free(hw, prof->acts);
1121 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1122 * @hw: pointer to the hardware structure
1123 * @blk: classification stage
1124 * @vsi_handle: software VSI handle
1125 * @vsig: target VSI group
1127 * Assumption: the caller has already verified that the VSI to
1128 * be added has the same characteristics as the VSIG and will
1129 * thereby have access to all resources added to that VSIG.
1132 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1135 enum ice_status status;
1137 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1138 return ICE_ERR_PARAM;
1140 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1141 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1143 ice_release_lock(&hw->fl_profs_locks[blk]);
1149 * ice_flow_assoc_prof - associate a VSI with a flow profile
1150 * @hw: pointer to the hardware structure
1151 * @blk: classification stage
1152 * @prof: pointer to flow profile
1153 * @vsi_handle: software VSI handle
1155 * Assumption: the caller has acquired the lock to the profile list
1156 * and the software VSI handle has been validated
1158 static enum ice_status
1159 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1160 struct ice_flow_prof *prof, u16 vsi_handle)
1162 enum ice_status status = ICE_SUCCESS;
1164 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1165 status = ice_add_prof_id_flow(hw, blk,
1166 ice_get_hw_vsi_num(hw,
1170 ice_set_bit(vsi_handle, prof->vsis);
1172 ice_debug(hw, ICE_DBG_FLOW,
1173 "HW profile add failed, %d\n",
1181 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1182 * @hw: pointer to the hardware structure
1183 * @blk: classification stage
1184 * @prof: pointer to flow profile
1185 * @vsi_handle: software VSI handle
1187 * Assumption: the caller has acquired the lock to the profile list
1188 * and the software VSI handle has been validated
1190 static enum ice_status
1191 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1192 struct ice_flow_prof *prof, u16 vsi_handle)
1194 enum ice_status status = ICE_SUCCESS;
1196 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1197 status = ice_rem_prof_id_flow(hw, blk,
1198 ice_get_hw_vsi_num(hw,
1202 ice_clear_bit(vsi_handle, prof->vsis);
1204 ice_debug(hw, ICE_DBG_FLOW,
1205 "HW profile remove failed, %d\n",
1213 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1214 * @hw: pointer to the HW struct
1215 * @blk: classification stage
1216 * @dir: flow direction
1217 * @prof_id: unique ID to identify this flow profile
1218 * @segs: array of one or more packet segments that describe the flow
1219 * @segs_cnt: number of packet segments provided
1220 * @acts: array of default actions
1221 * @acts_cnt: number of default actions
1222 * @prof: stores the returned flow profile added
1225 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1226 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1227 struct ice_flow_action *acts, u8 acts_cnt,
1228 struct ice_flow_prof **prof)
1230 enum ice_status status;
1232 if (segs_cnt > ICE_FLOW_SEG_MAX)
1233 return ICE_ERR_MAX_LIMIT;
1236 return ICE_ERR_PARAM;
1239 return ICE_ERR_BAD_PTR;
1241 status = ice_flow_val_hdrs(segs, segs_cnt);
1245 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1247 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1248 acts, acts_cnt, prof);
1250 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1252 ice_release_lock(&hw->fl_profs_locks[blk]);
1258 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1259 * @hw: pointer to the HW struct
1260 * @blk: the block for which the flow profile is to be removed
1261 * @prof_id: unique ID of the flow profile to be removed
1264 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1266 struct ice_flow_prof *prof;
1267 enum ice_status status;
1269 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1271 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1273 status = ICE_ERR_DOES_NOT_EXIST;
1277 /* prof becomes invalid after the call */
1278 status = ice_flow_rem_prof_sync(hw, blk, prof);
1281 ice_release_lock(&hw->fl_profs_locks[blk]);
1287 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1288 * @hw: pointer to the HW struct
1289 * @blk: classification stage
1290 * @prof_id: the profile ID handle
1291 * @hw_prof_id: pointer to variable to receive the HW profile ID
1294 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1297 struct ice_prof_map *map;
1299 map = ice_search_prof_id(hw, blk, prof_id);
1301 *hw_prof_id = map->prof_id;
1305 return ICE_ERR_DOES_NOT_EXIST;
1309 * ice_flow_find_entry - look for a flow entry using its unique ID
1310 * @hw: pointer to the HW struct
1311 * @blk: classification stage
1312 * @entry_id: unique ID to identify this flow entry
1314 * This function looks for the flow entry with the specified unique ID in all
1315 * flow profiles of the specified classification stage. If the entry is found,
1316 * and it returns the handle to the flow entry. Otherwise, it returns
1317 * ICE_FLOW_ENTRY_ID_INVAL.
1319 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1321 struct ice_flow_entry *found = NULL;
1322 struct ice_flow_prof *p;
1324 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1326 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1327 struct ice_flow_entry *e;
1329 ice_acquire_lock(&p->entries_lock);
1330 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1331 if (e->id == entry_id) {
1335 ice_release_lock(&p->entries_lock);
1341 ice_release_lock(&hw->fl_profs_locks[blk]);
1343 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1347 * ice_flow_add_entry - Add a flow entry
1348 * @hw: pointer to the HW struct
1349 * @blk: classification stage
1350 * @prof_id: ID of the profile to add a new flow entry to
1351 * @entry_id: unique ID to identify this flow entry
1352 * @vsi_handle: software VSI handle for the flow entry
1353 * @prio: priority of the flow entry
1354 * @data: pointer to a data buffer containing flow entry's match values/masks
1355 * @acts: arrays of actions to be performed on a match
1356 * @acts_cnt: number of actions
1357 * @entry_h: pointer to buffer that receives the new flow entry's handle
1360 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1361 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1362 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1365 struct ice_flow_entry *e = NULL;
1366 struct ice_flow_prof *prof;
1367 enum ice_status status = ICE_SUCCESS;
1369 /* ACL entries must indicate an action */
1370 if (blk == ICE_BLK_ACL && (!acts || !acts_cnt))
1371 return ICE_ERR_PARAM;
1373 /* No flow entry data is expected for RSS */
1374 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1375 return ICE_ERR_BAD_PTR;
1377 if (!ice_is_vsi_valid(hw, vsi_handle))
1378 return ICE_ERR_PARAM;
1380 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1382 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1384 status = ICE_ERR_DOES_NOT_EXIST;
1386 /* Allocate memory for the entry being added and associate
1387 * the VSI to the found flow profile
1389 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1391 status = ICE_ERR_NO_MEMORY;
1393 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1396 ice_release_lock(&hw->fl_profs_locks[blk]);
1401 e->vsi_handle = vsi_handle;
1407 /* RSS will add only one entry per VSI per profile */
1414 status = ICE_ERR_NOT_IMPL;
1418 if (blk != ICE_BLK_ACL) {
1419 /* ACL will handle the entry management */
1420 ice_acquire_lock(&prof->entries_lock);
1421 LIST_ADD(&e->l_entry, &prof->entries);
1422 ice_release_lock(&prof->entries_lock);
1425 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1430 ice_free(hw, e->entry);
1438 * ice_flow_rem_entry - Remove a flow entry
1439 * @hw: pointer to the HW struct
1440 * @blk: classification stage
1441 * @entry_h: handle to the flow entry to be removed
1443 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
1446 struct ice_flow_entry *entry;
1447 struct ice_flow_prof *prof;
1448 enum ice_status status = ICE_SUCCESS;
1450 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1451 return ICE_ERR_PARAM;
1453 entry = ICE_FLOW_ENTRY_PTR(entry_h);
1455 /* Retain the pointer to the flow profile as the entry will be freed */
1459 ice_acquire_lock(&prof->entries_lock);
1460 status = ice_flow_rem_entry_sync(hw, blk, entry);
1461 ice_release_lock(&prof->entries_lock);
1468 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1469 * @seg: packet segment the field being set belongs to
1470 * @fld: field to be set
1471 * @field_type: type of the field
1472 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1473 * entry's input buffer
1474 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1476 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1477 * entry's input buffer
1479 * This helper function stores information of a field being matched, including
1480 * the type of the field and the locations of the value to match, the mask, and
1481 * and the upper-bound value in the start of the input buffer for a flow entry.
1482 * This function should only be used for fixed-size data structures.
1484 * This function also opportunistically determines the protocol headers to be
1485 * present based on the fields being set. Some fields cannot be used alone to
1486 * determine the protocol headers present. Sometimes, fields for particular
1487 * protocol headers are not matched. In those cases, the protocol headers
1488 * must be explicitly set.
1491 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1492 enum ice_flow_fld_match_type field_type, u16 val_loc,
1493 u16 mask_loc, u16 last_loc)
1495 u64 bit = BIT_ULL(fld);
1498 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1501 seg->fields[fld].type = field_type;
1502 seg->fields[fld].src.val = val_loc;
1503 seg->fields[fld].src.mask = mask_loc;
1504 seg->fields[fld].src.last = last_loc;
1506 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1510 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1511 * @seg: packet segment the field being set belongs to
1512 * @fld: field to be set
1513 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1514 * entry's input buffer
1515 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1517 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1518 * entry's input buffer
1519 * @range: indicate if field being matched is to be in a range
1521 * This function specifies the locations, in the form of byte offsets from the
1522 * start of the input buffer for a flow entry, from where the value to match,
1523 * the mask value, and upper value can be extracted. These locations are then
1524 * stored in the flow profile. When adding a flow entry associated with the
1525 * flow profile, these locations will be used to quickly extract the values and
1526 * create the content of a match entry. This function should only be used for
1527 * fixed-size data structures.
1530 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1531 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1533 enum ice_flow_fld_match_type t = range ?
1534 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1536 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1540 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1541 * @seg: packet segment the field being set belongs to
1542 * @fld: field to be set
1543 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1544 * entry's input buffer
1545 * @pref_loc: location of prefix value from entry's input buffer
1546 * @pref_sz: size of the location holding the prefix value
1548 * This function specifies the locations, in the form of byte offsets from the
1549 * start of the input buffer for a flow entry, from where the value to match
1550 * and the IPv4 prefix value can be extracted. These locations are then stored
1551 * in the flow profile. When adding flow entries to the associated flow profile,
1552 * these locations can be used to quickly extract the values to create the
1553 * content of a match entry. This function should only be used for fixed-size
1557 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1558 u16 val_loc, u16 pref_loc, u8 pref_sz)
1560 /* For this type of field, the "mask" location is for the prefix value's
1561 * location and the "last" location is for the size of the location of
1564 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1565 pref_loc, (u16)pref_sz);
1569 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1570 * @seg: packet segment the field being set belongs to
1571 * @off: offset of the raw field from the beginning of the segment in bytes
1572 * @len: length of the raw pattern to be matched
1573 * @val_loc: location of the value to match from entry's input buffer
1574 * @mask_loc: location of mask value from entry's input buffer
1576 * This function specifies the offset of the raw field to be match from the
1577 * beginning of the specified packet segment, and the locations, in the form of
1578 * byte offsets from the start of the input buffer for a flow entry, from where
1579 * the value to match and the mask value to be extracted. These locations are
1580 * then stored in the flow profile. When adding flow entries to the associated
1581 * flow profile, these locations can be used to quickly extract the values to
1582 * create the content of a match entry. This function should only be used for
1583 * fixed-size data structures.
1586 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1587 u16 val_loc, u16 mask_loc)
1589 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1590 seg->raws[seg->raws_cnt].off = off;
1591 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1592 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1593 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1594 /* The "last" field is used to store the length of the field */
1595 seg->raws[seg->raws_cnt].info.src.last = len;
1598 /* Overflows of "raws" will be handled as an error condition later in
1599 * the flow when this information is processed.
1604 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1605 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1607 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1608 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1609 ICE_FLOW_SEG_HDR_SCTP)
1611 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1612 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1613 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1616 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1617 * @segs: pointer to the flow field segment(s)
1618 * @hash_fields: fields to be hashed on for the segment(s)
1619 * @flow_hdr: protocol header fields within a packet segment
1621 * Helper function to extract fields from hash bitmap and use flow
1622 * header value to set flow field segment for further use in flow
1623 * profile entry or removal.
1625 static enum ice_status
1626 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1629 u64 val = hash_fields;
1632 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1633 u64 bit = BIT_ULL(i);
1636 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1637 ICE_FLOW_FLD_OFF_INVAL,
1638 ICE_FLOW_FLD_OFF_INVAL,
1639 ICE_FLOW_FLD_OFF_INVAL, false);
1643 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1645 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1646 return ICE_ERR_PARAM;
1648 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1649 if (val && !ice_is_pow2(val))
1652 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1653 if (val && !ice_is_pow2(val))
1660 * ice_rem_vsi_rss_list - remove VSI from RSS list
1661 * @hw: pointer to the hardware structure
1662 * @vsi_handle: software VSI handle
1664 * Remove the VSI from all RSS configurations in the list.
1666 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1668 struct ice_rss_cfg *r, *tmp;
1670 if (LIST_EMPTY(&hw->rss_list_head))
1673 ice_acquire_lock(&hw->rss_locks);
1674 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1675 ice_rss_cfg, l_entry) {
1676 if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1677 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1678 LIST_DEL(&r->l_entry);
1682 ice_release_lock(&hw->rss_locks);
1686 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1687 * @hw: pointer to the hardware structure
1688 * @vsi_handle: software VSI handle
1690 * This function will iterate through all flow profiles and disassociate
1691 * the VSI from that profile. If the flow profile has no VSIs it will
1694 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1696 const enum ice_block blk = ICE_BLK_RSS;
1697 struct ice_flow_prof *p, *t;
1698 enum ice_status status = ICE_SUCCESS;
1700 if (!ice_is_vsi_valid(hw, vsi_handle))
1701 return ICE_ERR_PARAM;
1703 if (LIST_EMPTY(&hw->fl_profs[blk]))
1706 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1707 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1709 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1710 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1714 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1715 status = ice_flow_rem_prof_sync(hw, blk, p);
1721 ice_release_lock(&hw->fl_profs_locks[blk]);
1727 * ice_rem_rss_list - remove RSS configuration from list
1728 * @hw: pointer to the hardware structure
1729 * @vsi_handle: software VSI handle
1730 * @prof: pointer to flow profile
1732 * Assumption: lock has already been acquired for RSS list
1735 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1737 struct ice_rss_cfg *r, *tmp;
1739 /* Search for RSS hash fields associated to the VSI that match the
1740 * hash configurations associated to the flow profile. If found
1741 * remove from the RSS entry list of the VSI context and delete entry.
1743 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1744 ice_rss_cfg, l_entry) {
1745 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1746 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1747 ice_clear_bit(vsi_handle, r->vsis);
1748 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1749 LIST_DEL(&r->l_entry);
1758 * ice_add_rss_list - add RSS configuration to list
1759 * @hw: pointer to the hardware structure
1760 * @vsi_handle: software VSI handle
1761 * @prof: pointer to flow profile
1763 * Assumption: lock has already been acquired for RSS list
1765 static enum ice_status
1766 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1768 struct ice_rss_cfg *r, *rss_cfg;
1770 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1771 ice_rss_cfg, l_entry)
1772 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1773 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1774 ice_set_bit(vsi_handle, r->vsis);
1778 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1780 return ICE_ERR_NO_MEMORY;
1782 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1783 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1784 ice_set_bit(vsi_handle, rss_cfg->vsis);
1786 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1791 #define ICE_FLOW_PROF_HASH_S 0
1792 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1793 #define ICE_FLOW_PROF_HDR_S 32
1794 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1795 #define ICE_FLOW_PROF_ENCAP_S 63
1796 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1798 #define ICE_RSS_OUTER_HEADERS 1
1799 #define ICE_RSS_INNER_HEADERS 2
1801 /* Flow profile ID format:
1802 * [0:31] - Packet match fields
1803 * [32:62] - Protocol header
1804 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1806 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1807 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1808 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1809 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1812 * ice_add_rss_cfg_sync - add an RSS configuration
1813 * @hw: pointer to the hardware structure
1814 * @vsi_handle: software VSI handle
1815 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1816 * @addl_hdrs: protocol header fields
1817 * @segs_cnt: packet segment count
1819 * Assumption: lock has already been acquired for RSS list
1821 static enum ice_status
1822 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1823 u32 addl_hdrs, u8 segs_cnt)
1825 const enum ice_block blk = ICE_BLK_RSS;
1826 struct ice_flow_prof *prof = NULL;
1827 struct ice_flow_seg_info *segs;
1828 enum ice_status status;
1830 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1831 return ICE_ERR_PARAM;
1833 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1836 return ICE_ERR_NO_MEMORY;
1838 /* Construct the packet segment info from the hashed fields */
1839 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1844 /* Search for a flow profile that has matching headers, hash fields
1845 * and has the input VSI associated to it. If found, no further
1846 * operations required and exit.
1848 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1850 ICE_FLOW_FIND_PROF_CHK_FLDS |
1851 ICE_FLOW_FIND_PROF_CHK_VSI);
1855 /* Check if a flow profile exists with the same protocol headers and
1856 * associated with the input VSI. If so disasscociate the VSI from
1857 * this profile. The VSI will be added to a new profile created with
1858 * the protocol header and new hash field configuration.
1860 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1861 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1863 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1865 ice_rem_rss_list(hw, vsi_handle, prof);
1869 /* Remove profile if it has no VSIs associated */
1870 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1871 status = ice_flow_rem_prof(hw, blk, prof->id);
1877 /* Search for a profile that has same match fields only. If this
1878 * exists then associate the VSI to this profile.
1880 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1882 ICE_FLOW_FIND_PROF_CHK_FLDS);
1884 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1886 status = ice_add_rss_list(hw, vsi_handle, prof);
1890 /* Create a new flow profile with generated profile and packet
1891 * segment information.
1893 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1894 ICE_FLOW_GEN_PROFID(hashed_flds,
1895 segs[segs_cnt - 1].hdrs,
1897 segs, segs_cnt, NULL, 0, &prof);
1901 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1902 /* If association to a new flow profile failed then this profile can
1906 ice_flow_rem_prof(hw, blk, prof->id);
1910 status = ice_add_rss_list(hw, vsi_handle, prof);
1918 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1919 * @hw: pointer to the hardware structure
1920 * @vsi_handle: software VSI handle
1921 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1922 * @addl_hdrs: protocol header fields
1924 * This function will generate a flow profile based on fields associated with
1925 * the input fields to hash on, the flow type and use the VSI number to add
1926 * a flow entry to the profile.
1929 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1932 enum ice_status status;
1934 if (hashed_flds == ICE_HASH_INVALID ||
1935 !ice_is_vsi_valid(hw, vsi_handle))
1936 return ICE_ERR_PARAM;
1938 ice_acquire_lock(&hw->rss_locks);
1939 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
1940 ICE_RSS_OUTER_HEADERS);
1942 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
1943 addl_hdrs, ICE_RSS_INNER_HEADERS);
1944 ice_release_lock(&hw->rss_locks);
1950 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1951 * @hw: pointer to the hardware structure
1952 * @vsi_handle: software VSI handle
1953 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1954 * @addl_hdrs: Protocol header fields within a packet segment
1955 * @segs_cnt: packet segment count
1957 * Assumption: lock has already been acquired for RSS list
1959 static enum ice_status
1960 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1961 u32 addl_hdrs, u8 segs_cnt)
1963 const enum ice_block blk = ICE_BLK_RSS;
1964 struct ice_flow_seg_info *segs;
1965 struct ice_flow_prof *prof;
1966 enum ice_status status;
1968 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1971 return ICE_ERR_NO_MEMORY;
1973 /* Construct the packet segment info from the hashed fields */
1974 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1979 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1981 ICE_FLOW_FIND_PROF_CHK_FLDS);
1983 status = ICE_ERR_DOES_NOT_EXIST;
1987 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1991 /* Remove RSS configuration from VSI context before deleting
1994 ice_rem_rss_list(hw, vsi_handle, prof);
1996 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1997 status = ice_flow_rem_prof(hw, blk, prof->id);
2005 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2006 * @hw: pointer to the hardware structure
2007 * @vsi_handle: software VSI handle
2008 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2009 * @addl_hdrs: Protocol header fields within a packet segment
2011 * This function will lookup the flow profile based on the input
2012 * hash field bitmap, iterate through the profile entry list of
2013 * that profile and find entry associated with input VSI to be
2014 * removed. Calls are made to underlying flow apis which will in
2015 * turn build or update buffers for RSS XLT1 section.
2018 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2021 enum ice_status status;
2023 if (hashed_flds == ICE_HASH_INVALID ||
2024 !ice_is_vsi_valid(hw, vsi_handle))
2025 return ICE_ERR_PARAM;
2027 ice_acquire_lock(&hw->rss_locks);
2028 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2029 ICE_RSS_OUTER_HEADERS);
2031 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2032 addl_hdrs, ICE_RSS_INNER_HEADERS);
2033 ice_release_lock(&hw->rss_locks);
2038 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2039 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2040 * convert its values to their appropriate flow L3, L4 values.
2042 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2043 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2044 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2045 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2046 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2047 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2048 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2049 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2050 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2051 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2052 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2053 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2054 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2056 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2057 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2058 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2059 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2060 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2061 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2062 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2063 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2064 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2065 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2066 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2067 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2068 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2071 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2072 * @hw: pointer to the hardware structure
2073 * @vsi_handle: software VSI handle
2074 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2076 * This function will take the hash bitmap provided by the AVF driver via a
2077 * message, convert it to ICE-compatible values, and configure RSS flow
2081 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2083 enum ice_status status = ICE_SUCCESS;
2086 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2087 !ice_is_vsi_valid(hw, vsi_handle))
2088 return ICE_ERR_PARAM;
2090 /* Make sure no unsupported bits are specified */
2091 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2092 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2095 hash_flds = avf_hash;
2097 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2098 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2099 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2101 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2102 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2104 /* Create the corresponding RSS configuration for each valid hash bit */
2106 u64 rss_hash = ICE_HASH_INVALID;
2108 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2109 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2110 rss_hash = ICE_FLOW_HASH_IPV4;
2111 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2112 } else if (hash_flds &
2113 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2114 rss_hash = ICE_FLOW_HASH_IPV4 |
2115 ICE_FLOW_HASH_TCP_PORT;
2116 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2117 } else if (hash_flds &
2118 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2119 rss_hash = ICE_FLOW_HASH_IPV4 |
2120 ICE_FLOW_HASH_UDP_PORT;
2121 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2122 } else if (hash_flds &
2123 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2124 rss_hash = ICE_FLOW_HASH_IPV4 |
2125 ICE_FLOW_HASH_SCTP_PORT;
2127 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2129 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2130 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2131 rss_hash = ICE_FLOW_HASH_IPV6;
2132 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2133 } else if (hash_flds &
2134 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2135 rss_hash = ICE_FLOW_HASH_IPV6 |
2136 ICE_FLOW_HASH_TCP_PORT;
2137 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2138 } else if (hash_flds &
2139 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2140 rss_hash = ICE_FLOW_HASH_IPV6 |
2141 ICE_FLOW_HASH_UDP_PORT;
2142 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2143 } else if (hash_flds &
2144 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2145 rss_hash = ICE_FLOW_HASH_IPV6 |
2146 ICE_FLOW_HASH_SCTP_PORT;
2148 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2152 if (rss_hash == ICE_HASH_INVALID)
2153 return ICE_ERR_OUT_OF_RANGE;
2155 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2156 ICE_FLOW_SEG_HDR_NONE);
2165 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2166 * @hw: pointer to the hardware structure
2167 * @vsi_handle: software VSI handle
2169 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2171 enum ice_status status = ICE_SUCCESS;
2172 struct ice_rss_cfg *r;
2174 if (!ice_is_vsi_valid(hw, vsi_handle))
2175 return ICE_ERR_PARAM;
2177 ice_acquire_lock(&hw->rss_locks);
2178 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2179 ice_rss_cfg, l_entry) {
2180 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2181 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2184 ICE_RSS_OUTER_HEADERS);
2187 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2190 ICE_RSS_INNER_HEADERS);
2195 ice_release_lock(&hw->rss_locks);
2201 * ice_get_rss_cfg - returns hashed fields for the given header types
2202 * @hw: pointer to the hardware structure
2203 * @vsi_handle: software VSI handle
2204 * @hdrs: protocol header type
2206 * This function will return the match fields of the first instance of flow
2207 * profile having the given header types and containing input VSI
2209 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2211 struct ice_rss_cfg *r, *rss_cfg = NULL;
2213 /* verify if the protocol header is non zero and VSI is valid */
2214 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2215 return ICE_HASH_INVALID;
2217 ice_acquire_lock(&hw->rss_locks);
2218 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2219 ice_rss_cfg, l_entry)
2220 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2221 r->packet_hdr == hdrs) {
2225 ice_release_lock(&hw->rss_locks);
2227 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;