1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2019
5 #include "ice_common.h"
8 /* Size of known protocol header fields */
9 #define ICE_FLOW_FLD_SZ_ETH_TYPE 2
10 #define ICE_FLOW_FLD_SZ_VLAN 2
11 #define ICE_FLOW_FLD_SZ_IPV4_ADDR 4
12 #define ICE_FLOW_FLD_SZ_IPV6_ADDR 16
13 #define ICE_FLOW_FLD_SZ_IP_DSCP 1
14 #define ICE_FLOW_FLD_SZ_IP_TTL 1
15 #define ICE_FLOW_FLD_SZ_IP_PROT 1
16 #define ICE_FLOW_FLD_SZ_PORT 2
17 #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1
18 #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1
19 #define ICE_FLOW_FLD_SZ_ICMP_CODE 1
20 #define ICE_FLOW_FLD_SZ_ARP_OPER 2
21 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4
23 /* Protocol header fields are extracted at the word boundaries as word-sized
24 * values. Specify the displacement value of some non-word-aligned fields needed
25 * to compute the offset of words containing the fields in the corresponding
26 * protocol headers. Displacement values are expressed in number of bits.
28 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP (-4)
29 #define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * 8)
30 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * 8)
32 /* Describe properties of a protocol header field */
33 struct ice_flow_field_info {
34 enum ice_flow_seg_hdr hdr;
35 s16 off; /* Offset from start of a protocol header, in bits */
36 u16 size; /* Size of fields in bits */
39 /* Table containing properties of supported protocol header fields */
41 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
43 /* ICE_FLOW_FIELD_IDX_ETH_DA */
44 { ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN * 8 },
45 /* ICE_FLOW_FIELD_IDX_ETH_SA */
46 { ICE_FLOW_SEG_HDR_ETH, ETH_ALEN * 8, ETH_ALEN * 8 },
47 /* ICE_FLOW_FIELD_IDX_S_VLAN */
48 { ICE_FLOW_SEG_HDR_VLAN, 12 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
49 /* ICE_FLOW_FIELD_IDX_C_VLAN */
50 { ICE_FLOW_SEG_HDR_VLAN, 14 * 8, ICE_FLOW_FLD_SZ_VLAN * 8 },
51 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
52 { ICE_FLOW_SEG_HDR_ETH, 12 * 8, ICE_FLOW_FLD_SZ_ETH_TYPE * 8 },
54 /* ICE_FLOW_FIELD_IDX_IP_DSCP */
55 { ICE_FLOW_SEG_HDR_IPV4, 1 * 8, 1 * 8 },
56 /* ICE_FLOW_FIELD_IDX_IP_TTL */
57 { ICE_FLOW_SEG_HDR_NONE, 8 * 8, 1 * 8 },
58 /* ICE_FLOW_FIELD_IDX_IP_PROT */
59 { ICE_FLOW_SEG_HDR_NONE, 9 * 8, ICE_FLOW_FLD_SZ_IP_PROT * 8 },
60 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
61 { ICE_FLOW_SEG_HDR_IPV4, 12 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
62 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
63 { ICE_FLOW_SEG_HDR_IPV4, 16 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
65 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
66 { ICE_FLOW_SEG_HDR_IPV6, 8 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
67 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
68 { ICE_FLOW_SEG_HDR_IPV6, 24 * 8, ICE_FLOW_FLD_SZ_IPV6_ADDR * 8 },
70 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
71 { ICE_FLOW_SEG_HDR_TCP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
72 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
73 { ICE_FLOW_SEG_HDR_TCP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
74 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
75 { ICE_FLOW_SEG_HDR_UDP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
76 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
77 { ICE_FLOW_SEG_HDR_UDP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
78 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
79 { ICE_FLOW_SEG_HDR_SCTP, 0 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
80 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
81 { ICE_FLOW_SEG_HDR_SCTP, 2 * 8, ICE_FLOW_FLD_SZ_PORT * 8 },
82 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
83 { ICE_FLOW_SEG_HDR_TCP, 13 * 8, ICE_FLOW_FLD_SZ_TCP_FLAGS * 8 },
85 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
86 { ICE_FLOW_SEG_HDR_ARP, 14 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
87 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
88 { ICE_FLOW_SEG_HDR_ARP, 24 * 8, ICE_FLOW_FLD_SZ_IPV4_ADDR * 8 },
89 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
90 { ICE_FLOW_SEG_HDR_ARP, 8 * 8, ETH_ALEN * 8 },
91 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
92 { ICE_FLOW_SEG_HDR_ARP, 18 * 8, ETH_ALEN * 8 },
93 /* ICE_FLOW_FIELD_IDX_ARP_OP */
94 { ICE_FLOW_SEG_HDR_ARP, 6 * 8, ICE_FLOW_FLD_SZ_ARP_OPER * 8 },
96 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
97 { ICE_FLOW_SEG_HDR_ICMP, 0 * 8, ICE_FLOW_FLD_SZ_ICMP_TYPE * 8 },
98 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
99 { ICE_FLOW_SEG_HDR_ICMP, 1 * 8, ICE_FLOW_FLD_SZ_ICMP_CODE * 8 },
101 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
102 { ICE_FLOW_SEG_HDR_GRE, 12 * 8, ICE_FLOW_FLD_SZ_GRE_KEYID * 8 },
105 /* Bitmaps indicating relevant packet types for a particular protocol header
107 * Packet types for packets with an Outer/First/Single MAC header
109 static const u32 ice_ptypes_mac_ofos[] = {
110 0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
111 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
112 0x000B0F0F, 0x00000000, 0x00000000, 0x00000000,
113 0x00000000, 0x00000000, 0x00000000, 0x00000000,
114 0x00000000, 0x00000000, 0x00000000, 0x00000000,
115 0x00000000, 0x00000000, 0x00000000, 0x00000000,
116 0x00000000, 0x00000000, 0x00000000, 0x00000000,
117 0x00000000, 0x00000000, 0x00000000, 0x00000000,
120 /* Packet types for packets with an Innermost/Last MAC VLAN header */
121 static const u32 ice_ptypes_macvlan_il[] = {
122 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
123 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
124 0x00000000, 0x00000000, 0x00000000, 0x00000000,
125 0x00000000, 0x00000000, 0x00000000, 0x00000000,
126 0x00000000, 0x00000000, 0x00000000, 0x00000000,
127 0x00000000, 0x00000000, 0x00000000, 0x00000000,
128 0x00000000, 0x00000000, 0x00000000, 0x00000000,
129 0x00000000, 0x00000000, 0x00000000, 0x00000000,
132 /* Packet types for packets with an Outer/First/Single IPv4 header */
133 static const u32 ice_ptypes_ipv4_ofos[] = {
134 0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
135 0x00000000, 0x00000000, 0x00000000, 0x00000000,
136 0x0003000F, 0x00000000, 0x00000000, 0x00000000,
137 0x00000000, 0x00000000, 0x00000000, 0x00000000,
138 0x00000000, 0x00000000, 0x00000000, 0x00000000,
139 0x00000000, 0x00000000, 0x00000000, 0x00000000,
140 0x00000000, 0x00000000, 0x00000000, 0x00000000,
141 0x00000000, 0x00000000, 0x00000000, 0x00000000,
144 /* Packet types for packets with an Innermost/Last IPv4 header */
145 static const u32 ice_ptypes_ipv4_il[] = {
146 0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
147 0x0007700E, 0x00000000, 0x00000000, 0x00000000,
148 0x00000000, 0x00000000, 0x00000000, 0x00000000,
149 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 0x00000000, 0x00000000, 0x00000000, 0x00000000,
151 0x00000000, 0x00000000, 0x00000000, 0x00000000,
152 0x00000000, 0x00000000, 0x00000000, 0x00000000,
153 0x00000000, 0x00000000, 0x00000000, 0x00000000,
156 /* Packet types for packets with an Outer/First/Single IPv6 header */
157 static const u32 ice_ptypes_ipv6_ofos[] = {
158 0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
159 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
160 0x00080F00, 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 0x00000000, 0x00000000, 0x00000000, 0x00000000,
163 0x00000000, 0x00000000, 0x00000000, 0x00000000,
164 0x00000000, 0x00000000, 0x00000000, 0x00000000,
165 0x00000000, 0x00000000, 0x00000000, 0x00000000,
168 /* Packet types for packets with an Innermost/Last IPv6 header */
169 static const u32 ice_ptypes_ipv6_il[] = {
170 0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
171 0x03B80770, 0x00000000, 0x00000000, 0x00000000,
172 0x00000000, 0x00000000, 0x00000000, 0x00000000,
173 0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 0x00000000, 0x00000000, 0x00000000, 0x00000000,
176 0x00000000, 0x00000000, 0x00000000, 0x00000000,
177 0x00000000, 0x00000000, 0x00000000, 0x00000000,
180 /* Packet types for packets with an Outermost/First ARP header */
181 static const u32 ice_ptypes_arp_of[] = {
182 0x00000800, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 0x00000000, 0x00000000, 0x00000000, 0x00000000,
187 0x00000000, 0x00000000, 0x00000000, 0x00000000,
188 0x00000000, 0x00000000, 0x00000000, 0x00000000,
189 0x00000000, 0x00000000, 0x00000000, 0x00000000,
192 /* Packet types for packets with an Outermost/First UDP header */
193 static const u32 ice_ptypes_udp_of[] = {
194 0x81000000, 0x00000000, 0x04000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 0x00000000, 0x00000000, 0x00000000, 0x00000000,
199 0x00000000, 0x00000000, 0x00000000, 0x00000000,
200 0x00000000, 0x00000000, 0x00000000, 0x00000000,
201 0x00000000, 0x00000000, 0x00000000, 0x00000000,
204 /* Packet types for packets with an Innermost/Last UDP header */
205 static const u32 ice_ptypes_udp_il[] = {
206 0x80000000, 0x20204040, 0x00081010, 0x80810102,
207 0x00204040, 0x00000000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 0x00000000, 0x00000000, 0x00000000, 0x00000000,
212 0x00000000, 0x00000000, 0x00000000, 0x00000000,
213 0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 /* Packet types for packets with an Innermost/Last TCP header */
217 static const u32 ice_ptypes_tcp_il[] = {
218 0x04000000, 0x80810102, 0x10204040, 0x42040408,
219 0x00810002, 0x00000000, 0x00000000, 0x00000000,
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,
228 /* Packet types for packets with an Innermost/Last SCTP header */
229 static const u32 ice_ptypes_sctp_il[] = {
230 0x08000000, 0x01020204, 0x20408081, 0x04080810,
231 0x01020204, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 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,
240 /* Packet types for packets with an Outermost/First ICMP header */
241 static const u32 ice_ptypes_icmp_of[] = {
242 0x10000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 0x00000000, 0x00000000, 0x00000000, 0x00000000,
247 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 0x00000000, 0x00000000, 0x00000000, 0x00000000,
252 /* Packet types for packets with an Innermost/Last ICMP header */
253 static const u32 ice_ptypes_icmp_il[] = {
254 0x00000000, 0x02040408, 0x40810102, 0x08101020,
255 0x02040408, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 0x00000000, 0x00000000, 0x00000000, 0x00000000,
264 /* Packet types for packets with an Outermost/First GRE header */
265 static const u32 ice_ptypes_gre_of[] = {
266 0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
267 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 0x00000000, 0x00000000, 0x00000000, 0x00000000,
273 0x00000000, 0x00000000, 0x00000000, 0x00000000,
276 /* Packet types for packets with an Innermost/Last MAC header */
277 static const u32 ice_ptypes_mac_il[] = {
278 0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
279 0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
280 0x00000000, 0x00000000, 0x00000000, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000,
288 /* Manage parameters and info. used during the creation of a flow profile */
289 struct ice_flow_prof_params {
291 struct ice_flow_prof *prof;
293 u16 entry_length; /* # of bytes formatted entry will require */
295 struct ice_fv_word es[ICE_MAX_FV_WORDS];
297 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
301 * ice_is_pow2 - check if integer value is a power of 2
302 * @val: unsigned integer to be validated
304 static bool ice_is_pow2(u64 val)
306 return (val && !(val & (val - 1)));
309 #define ICE_FLOW_SEG_HDRS_L2_MASK \
310 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
311 #define ICE_FLOW_SEG_HDRS_L3_MASK \
312 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
313 #define ICE_FLOW_SEG_HDRS_L4_MASK \
314 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
315 ICE_FLOW_SEG_HDR_SCTP)
318 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
319 * @segs: array of one or more packet segments that describe the flow
320 * @segs_cnt: number of packet segments provided
322 static enum ice_status
323 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
325 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
326 ICE_FLOW_SEG_HDRS_L3_MASK |
327 ICE_FLOW_SEG_HDRS_L4_MASK);
330 for (i = 0; i < segs_cnt; i++) {
331 /* No header specified */
332 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
333 return ICE_ERR_PARAM;
335 /* Multiple L3 headers */
336 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
337 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
338 return ICE_ERR_PARAM;
340 /* Multiple L4 headers */
341 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
342 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
343 return ICE_ERR_PARAM;
349 /* Sizes of fixed known protocol headers without header options */
350 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
351 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
352 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
353 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
354 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
355 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
356 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
357 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
358 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
361 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
362 * @params: information about the flow to be processed
363 * @seg: index of packet segment whose header size is to be determined
365 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
370 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
371 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
374 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
375 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
376 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
377 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
378 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
379 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
380 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
381 /* A L3 header is required if L4 is specified */
385 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
386 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
387 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
388 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
389 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
390 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
391 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
392 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
398 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
399 * @params: information about the flow to be processed
401 * This function identifies the packet types associated with the protocol
402 * headers being present in packet segments of the specified flow profile.
404 static enum ice_status
405 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
407 struct ice_flow_prof *prof;
410 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
415 for (i = 0; i < params->prof->segs_cnt; i++) {
416 const ice_bitmap_t *src;
419 if (i > 0 && (i + 1) < prof->segs_cnt)
422 hdrs = prof->segs[i].hdrs;
424 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
425 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
426 (const ice_bitmap_t *)ice_ptypes_mac_il;
427 ice_and_bitmap(params->ptypes, params->ptypes, src,
429 hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
432 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
433 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
434 ice_and_bitmap(params->ptypes, params->ptypes, src,
436 hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
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,
443 hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
446 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
447 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
448 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
449 ice_and_bitmap(params->ptypes, params->ptypes, src,
451 hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
452 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
453 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
454 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
455 ice_and_bitmap(params->ptypes, params->ptypes, src,
457 hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
460 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
461 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
462 (const ice_bitmap_t *)ice_ptypes_icmp_il;
463 ice_and_bitmap(params->ptypes, params->ptypes, src,
465 hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
466 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
467 src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of :
468 (const ice_bitmap_t *)ice_ptypes_udp_il;
469 ice_and_bitmap(params->ptypes, params->ptypes, src,
471 hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
472 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
473 ice_and_bitmap(params->ptypes, params->ptypes,
474 (const ice_bitmap_t *)ice_ptypes_tcp_il,
476 hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
477 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
478 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
479 ice_and_bitmap(params->ptypes, params->ptypes, src,
481 hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
482 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
484 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
485 ice_and_bitmap(params->ptypes, params->ptypes,
486 src, ICE_FLOW_PTYPE_MAX);
488 hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
496 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
497 * @hw: pointer to the hw struct
498 * @params: information about the flow to be processed
499 * @seg: packet segment index of the field to be extracted
500 * @fld: ID of field to be extracted
502 * This function determines the protocol ID, offset, and size of the given
503 * field. It then allocates one or more extraction sequence entries for the
504 * given field, and fill the entries with protocol ID and offset information.
506 static enum ice_status
507 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
508 u8 seg, enum ice_flow_field fld)
510 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
511 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
512 u8 fv_words = hw->blk[params->blk].es.fvw;
513 struct ice_flow_fld_info *flds;
514 u16 cnt, ese_bits, i;
518 flds = params->prof->segs[seg].fields;
521 case ICE_FLOW_FIELD_IDX_ETH_DA:
522 case ICE_FLOW_FIELD_IDX_ETH_SA:
523 case ICE_FLOW_FIELD_IDX_S_VLAN:
524 case ICE_FLOW_FIELD_IDX_C_VLAN:
525 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
527 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
528 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
530 case ICE_FLOW_FIELD_IDX_IP_DSCP:
531 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
532 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
534 case ICE_FLOW_FIELD_IDX_IP_TTL:
535 case ICE_FLOW_FIELD_IDX_IP_PROT:
536 /* Some fields are located at different offsets in IPv4 and
539 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
540 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
542 /* TTL and PROT share the same extraction seq. entry.
543 * Each is considered a sibling to the other in term
544 * sharing the same extraction sequence entry.
546 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
547 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
548 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
549 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
550 } else if (params->prof->segs[seg].hdrs &
551 ICE_FLOW_SEG_HDR_IPV6) {
552 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
554 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
555 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
556 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
557 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
560 case ICE_FLOW_FIELD_IDX_IPV4_SA:
561 case ICE_FLOW_FIELD_IDX_IPV4_DA:
562 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
564 case ICE_FLOW_FIELD_IDX_IPV6_SA:
565 case ICE_FLOW_FIELD_IDX_IPV6_DA:
566 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
568 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
569 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
570 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
571 prot_id = ICE_PROT_TCP_IL;
573 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
574 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
575 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
577 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
578 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
579 prot_id = ICE_PROT_SCTP_IL;
581 case ICE_FLOW_FIELD_IDX_ARP_SIP:
582 case ICE_FLOW_FIELD_IDX_ARP_DIP:
583 case ICE_FLOW_FIELD_IDX_ARP_SHA:
584 case ICE_FLOW_FIELD_IDX_ARP_DHA:
585 case ICE_FLOW_FIELD_IDX_ARP_OP:
586 prot_id = ICE_PROT_ARP_OF;
588 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
589 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
590 /* ICMP type and code share the same extraction seq. entry */
591 prot_id = (params->prof->segs[seg].hdrs &
592 ICE_FLOW_SEG_HDR_IPV4) ?
593 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
594 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
595 ICE_FLOW_FIELD_IDX_ICMP_CODE :
596 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
598 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
599 prot_id = ICE_PROT_GRE_OF;
602 return ICE_ERR_NOT_IMPL;
605 /* Each extraction sequence entry is a word in size, and extracts a
606 * word-aligned offset from a protocol header.
608 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
610 flds[fld].xtrct.prot_id = prot_id;
611 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
612 ICE_FLOW_FV_EXTRACT_SZ;
613 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
614 flds[fld].xtrct.idx = params->es_cnt;
616 /* Adjust the next field-entry index after accommodating the number of
617 * entries this field consumes
619 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
620 ice_flds_info[fld].size, ese_bits);
622 /* Fill in the extraction sequence entries needed for this field */
623 off = flds[fld].xtrct.off;
624 for (i = 0; i < cnt; i++) {
625 /* Only consume an extraction sequence entry if there is no
626 * sibling field associated with this field or the sibling entry
627 * already extracts the word shared with this field.
629 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
630 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
631 flds[sib].xtrct.off != off) {
634 /* Make sure the number of extraction sequence required
635 * does not exceed the block's capability
637 if (params->es_cnt >= fv_words)
638 return ICE_ERR_MAX_LIMIT;
640 /* some blocks require a reversed field vector layout */
641 if (hw->blk[params->blk].es.reverse)
642 idx = fv_words - params->es_cnt - 1;
644 idx = params->es_cnt;
646 params->es[idx].prot_id = prot_id;
647 params->es[idx].off = off;
651 off += ICE_FLOW_FV_EXTRACT_SZ;
658 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
659 * @hw: pointer to the hw struct
660 * @params: information about the flow to be processed
661 * @seg: index of packet segment whose raw fields are to be be extracted
663 static enum ice_status
664 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
670 if (!params->prof->segs[seg].raws_cnt)
673 if (params->prof->segs[seg].raws_cnt >
674 ARRAY_SIZE(params->prof->segs[seg].raws))
675 return ICE_ERR_MAX_LIMIT;
677 /* Offsets within the segment headers are not supported */
678 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
680 return ICE_ERR_PARAM;
682 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
683 struct ice_flow_seg_fld_raw *raw;
686 raw = ¶ms->prof->segs[seg].raws[i];
688 /* Only support matching raw fields in the payload */
689 if (raw->off < hdrs_sz)
690 return ICE_ERR_PARAM;
692 /* Convert the segment-relative offset into payload-relative
695 off = raw->off - hdrs_sz;
697 /* Storing extraction information */
698 raw->info.xtrct.prot_id = ICE_PROT_PAY;
699 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
700 ICE_FLOW_FV_EXTRACT_SZ;
701 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
702 raw->info.xtrct.idx = params->es_cnt;
704 /* Determine the number of field vector entries this raw field
707 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
708 (raw->info.src.last * 8),
709 ICE_FLOW_FV_EXTRACT_SZ * 8);
710 off = raw->info.xtrct.off;
711 for (j = 0; j < cnt; j++) {
712 /* Make sure the number of extraction sequence required
713 * does not exceed the block's capability
715 if (params->es_cnt >= hw->blk[params->blk].es.count ||
716 params->es_cnt >= ICE_MAX_FV_WORDS)
717 return ICE_ERR_MAX_LIMIT;
719 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
720 params->es[params->es_cnt].off = off;
722 off += ICE_FLOW_FV_EXTRACT_SZ;
730 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
731 * @hw: pointer to the hw struct
732 * @params: information about the flow to be processed
734 * This function iterates through all matched fields in the given segments, and
735 * creates an extraction sequence for the fields.
737 static enum ice_status
738 ice_flow_create_xtrct_seq(struct ice_hw *hw,
739 struct ice_flow_prof_params *params)
741 enum ice_status status = ICE_SUCCESS;
744 for (i = 0; i < params->prof->segs_cnt; i++) {
745 u64 match = params->prof->segs[i].match;
748 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
749 const u64 bit = BIT_ULL(j);
752 status = ice_flow_xtract_fld
753 (hw, params, i, (enum ice_flow_field)j);
760 /* Process raw matching bytes */
761 status = ice_flow_xtract_raws(hw, params, i);
770 * ice_flow_proc_segs - process all packet segments associated with a profile
771 * @hw: pointer to the hw struct
772 * @params: information about the flow to be processed
774 static enum ice_status
775 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
777 enum ice_status status;
779 status = ice_flow_proc_seg_hdrs(params);
783 status = ice_flow_create_xtrct_seq(hw, params);
787 switch (params->blk) {
789 /* Only header information is provided for RSS configuration.
790 * No further processing is needed.
792 status = ICE_SUCCESS;
795 status = ICE_SUCCESS;
799 return ICE_ERR_NOT_IMPL;
805 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
806 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
809 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
810 * @hw: pointer to the hw struct
811 * @blk: classification stage
812 * @dir: flow direction
813 * @segs: array of one or more packet segments that describe the flow
814 * @segs_cnt: number of packet segments provided
815 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
816 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
818 static struct ice_flow_prof *
819 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
820 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
821 u8 segs_cnt, u16 vsi_handle, u32 conds)
823 struct ice_flow_prof *p;
825 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
826 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
829 /* Check for profile-VSI association if specified */
830 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
831 ice_is_vsi_valid(hw, vsi_handle) &&
832 !ice_is_bit_set(p->vsis, vsi_handle))
835 /* Protocol headers must be checked. Matched fields are
836 * checked if specified.
838 for (i = 0; i < segs_cnt; i++)
839 if (segs[i].hdrs != p->segs[i].hdrs ||
840 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
841 segs[i].match != p->segs[i].match))
844 /* A match is found if all segments are matched */
854 * ice_flow_find_prof - Look up a profile matching headers and matched fields
855 * @hw: pointer to the hw struct
856 * @blk: classification stage
857 * @dir: flow direction
858 * @segs: array of one or more packet segments that describe the flow
859 * @segs_cnt: number of packet segments provided
862 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
863 struct ice_flow_seg_info *segs, u8 segs_cnt)
865 struct ice_flow_prof *p;
867 ice_acquire_lock(&hw->fl_profs_locks[blk]);
868 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
869 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
870 ice_release_lock(&hw->fl_profs_locks[blk]);
872 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
876 * ice_flow_find_prof_id - Look up a profile with given profile ID
877 * @hw: pointer to the hw struct
878 * @blk: classification stage
879 * @prof_id: unique ID to identify this flow profile
881 static struct ice_flow_prof *
882 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
884 struct ice_flow_prof *p;
886 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
887 if (p->id == prof_id)
895 * ice_flow_rem_entry_sync - Remove a flow entry
896 * @hw: pointer to the hw struct
897 * @entry: flow entry to be removed
899 static enum ice_status
900 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
903 return ICE_ERR_BAD_PTR;
905 LIST_DEL(&entry->l_entry);
908 ice_free(hw, entry->entry);
911 ice_free(hw, entry->acts);
919 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
920 * @hw: pointer to the hw struct
921 * @blk: classification stage
922 * @dir: flow direction
923 * @prof_id: unique ID to identify this flow profile
924 * @segs: array of one or more packet segments that describe the flow
925 * @segs_cnt: number of packet segments provided
926 * @acts: array of default actions
927 * @acts_cnt: number of default actions
928 * @prof: stores the returned flow profile added
930 * Assumption: the caller has acquired the lock to the profile list
932 static enum ice_status
933 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
934 enum ice_flow_dir dir, u64 prof_id,
935 struct ice_flow_seg_info *segs, u8 segs_cnt,
936 struct ice_flow_action *acts, u8 acts_cnt,
937 struct ice_flow_prof **prof)
939 struct ice_flow_prof_params params;
940 enum ice_status status = ICE_SUCCESS;
943 if (!prof || (acts_cnt && !acts))
944 return ICE_ERR_BAD_PTR;
946 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
947 params.prof = (struct ice_flow_prof *)
948 ice_malloc(hw, sizeof(*params.prof));
950 return ICE_ERR_NO_MEMORY;
952 /* initialize extraction sequence to all invalid (0xff) */
953 ice_memset(params.es, 0xff, sizeof(params.es), ICE_NONDMA_MEM);
956 params.prof->id = prof_id;
957 params.prof->dir = dir;
958 params.prof->segs_cnt = segs_cnt;
960 /* Make a copy of the segments that need to be persistent in the flow
963 for (i = 0; i < segs_cnt; i++)
964 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
965 ICE_NONDMA_TO_NONDMA);
967 /* Make a copy of the actions that need to be persistent in the flow
971 params.prof->acts = (struct ice_flow_action *)
972 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
973 ICE_NONDMA_TO_NONDMA);
975 if (!params.prof->acts) {
976 status = ICE_ERR_NO_MEMORY;
981 status = ice_flow_proc_segs(hw, ¶ms);
983 ice_debug(hw, ICE_DBG_FLOW,
984 "Error processing a flow's packet segments\n");
988 /* Add a HW profile for this flow profile */
989 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
991 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
995 INIT_LIST_HEAD(¶ms.prof->entries);
996 ice_init_lock(¶ms.prof->entries_lock);
1001 if (params.prof->acts)
1002 ice_free(hw, params.prof->acts);
1003 ice_free(hw, params.prof);
1010 * ice_flow_rem_prof_sync - remove a flow profile
1011 * @hw: pointer to the hardware structure
1012 * @blk: classification stage
1013 * @prof: pointer to flow profile to remove
1015 * Assumption: the caller has acquired the lock to the profile list
1017 static enum ice_status
1018 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1019 struct ice_flow_prof *prof)
1021 enum ice_status status = ICE_SUCCESS;
1023 /* Remove all remaining flow entries before removing the flow profile */
1024 if (!LIST_EMPTY(&prof->entries)) {
1025 struct ice_flow_entry *e, *t;
1027 ice_acquire_lock(&prof->entries_lock);
1029 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1031 status = ice_flow_rem_entry_sync(hw, e);
1036 ice_release_lock(&prof->entries_lock);
1039 /* Remove all hardware profiles associated with this flow profile */
1040 status = ice_rem_prof(hw, blk, prof->id);
1042 LIST_DEL(&prof->l_entry);
1043 ice_destroy_lock(&prof->entries_lock);
1045 ice_free(hw, prof->acts);
1053 * ice_flow_assoc_prof - associate a VSI with a flow profile
1054 * @hw: pointer to the hardware structure
1055 * @blk: classification stage
1056 * @prof: pointer to flow profile
1057 * @vsi_handle: software VSI handle
1059 * Assumption: the caller has acquired the lock to the profile list
1060 * and the software vsi handle has been validated
1062 static enum ice_status
1063 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1064 struct ice_flow_prof *prof, u16 vsi_handle)
1066 enum ice_status status = ICE_SUCCESS;
1068 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1069 status = ice_add_prof_id_flow(hw, blk,
1070 ice_get_hw_vsi_num(hw,
1074 ice_set_bit(vsi_handle, prof->vsis);
1076 ice_debug(hw, ICE_DBG_FLOW,
1077 "HW profile add failed, %d\n",
1085 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1086 * @hw: pointer to the hardware structure
1087 * @blk: classification stage
1088 * @prof: pointer to flow profile
1089 * @vsi_handle: software VSI handle
1091 * Assumption: the caller has acquired the lock to the profile list
1092 * and the software vsi handle has been validated
1094 static enum ice_status
1095 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1096 struct ice_flow_prof *prof, u16 vsi_handle)
1098 enum ice_status status = ICE_SUCCESS;
1100 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1101 status = ice_rem_prof_id_flow(hw, blk,
1102 ice_get_hw_vsi_num(hw,
1106 ice_clear_bit(vsi_handle, prof->vsis);
1108 ice_debug(hw, ICE_DBG_FLOW,
1109 "HW profile remove failed, %d\n",
1117 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1118 * @hw: pointer to the hw struct
1119 * @blk: classification stage
1120 * @dir: flow direction
1121 * @prof_id: unique ID to identify this flow profile
1122 * @segs: array of one or more packet segments that describe the flow
1123 * @segs_cnt: number of packet segments provided
1124 * @acts: array of default actions
1125 * @acts_cnt: number of default actions
1126 * @prof: stores the returned flow profile added
1129 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1130 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1131 struct ice_flow_action *acts, u8 acts_cnt,
1132 struct ice_flow_prof **prof)
1134 enum ice_status status;
1136 if (segs_cnt > ICE_FLOW_SEG_MAX)
1137 return ICE_ERR_MAX_LIMIT;
1140 return ICE_ERR_PARAM;
1143 return ICE_ERR_BAD_PTR;
1145 status = ice_flow_val_hdrs(segs, segs_cnt);
1149 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1151 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1152 acts, acts_cnt, prof);
1154 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1156 ice_release_lock(&hw->fl_profs_locks[blk]);
1162 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1163 * @hw: pointer to the hw struct
1164 * @blk: the block for which the flow profile is to be removed
1165 * @prof_id: unique ID of the flow profile to be removed
1168 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1170 struct ice_flow_prof *prof;
1171 enum ice_status status;
1173 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1175 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1177 status = ICE_ERR_DOES_NOT_EXIST;
1181 /* prof becomes invalid after the call */
1182 status = ice_flow_rem_prof_sync(hw, blk, prof);
1185 ice_release_lock(&hw->fl_profs_locks[blk]);
1191 * ice_flow_get_hw_prof - return the hw profile for a specific profile id handle
1192 * @hw: pointer to the hw struct
1193 * @blk: classification stage
1194 * @prof_id: the profile id handle
1195 * @hw_prof_id: pointer to variable to receive the hw profile id
1198 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1201 struct ice_prof_map *map;
1203 map = ice_search_prof_id(hw, blk, prof_id);
1205 *hw_prof_id = map->prof_id;
1209 return ICE_ERR_DOES_NOT_EXIST;
1213 * ice_flow_find_entry - look for a flow entry using its unique ID
1214 * @hw: pointer to the hw struct
1215 * @blk: classification stage
1216 * @entry_id: unique ID to identify this flow entry
1218 * This function looks for the flow entry with the specified unique ID in all
1219 * flow profiles of the specified classification stage. If the entry is found,
1220 * and it returns the handle to the flow entry. Otherwise, it returns
1221 * ICE_FLOW_ENTRY_ID_INVAL.
1223 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1225 struct ice_flow_entry *found = NULL;
1226 struct ice_flow_prof *p;
1228 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1230 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1231 struct ice_flow_entry *e;
1233 ice_acquire_lock(&p->entries_lock);
1234 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1235 if (e->id == entry_id) {
1239 ice_release_lock(&p->entries_lock);
1245 ice_release_lock(&hw->fl_profs_locks[blk]);
1247 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1251 * ice_flow_add_entry - Add a flow entry
1252 * @hw: pointer to the hw struct
1253 * @blk: classification stage
1254 * @prof_id: ID of the profile to add a new flow entry to
1255 * @entry_id: unique ID to identify this flow entry
1256 * @vsi_handle: software VSI handle for the flow entry
1257 * @prio: priority of the flow entry
1258 * @data: pointer to a data buffer containing flow entry's match values/masks
1259 * @acts: arrays of actions to be performed on a match
1260 * @acts_cnt: number of actions
1261 * @entry_h: pointer to buffer that receives the new flow entry's handle
1264 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1265 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1266 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1269 struct ice_flow_prof *prof = NULL;
1270 struct ice_flow_entry *e = NULL;
1271 enum ice_status status = ICE_SUCCESS;
1273 if (acts_cnt && !acts)
1274 return ICE_ERR_PARAM;
1276 /* No flow entry data is expected for RSS */
1277 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1278 return ICE_ERR_BAD_PTR;
1280 if (!ice_is_vsi_valid(hw, vsi_handle))
1281 return ICE_ERR_PARAM;
1283 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1285 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1287 status = ICE_ERR_DOES_NOT_EXIST;
1289 /* Allocate memory for the entry being added and associate
1290 * the VSI to the found flow profile
1292 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1294 status = ICE_ERR_NO_MEMORY;
1296 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1299 ice_release_lock(&hw->fl_profs_locks[blk]);
1304 e->vsi_handle = vsi_handle;
1309 /* RSS will add only one entry per VSI per profile */
1316 status = ICE_ERR_NOT_IMPL;
1320 ice_acquire_lock(&prof->entries_lock);
1321 LIST_ADD(&e->l_entry, &prof->entries);
1322 ice_release_lock(&prof->entries_lock);
1324 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1329 ice_free(hw, e->entry);
1337 * ice_flow_rem_entry - Remove a flow entry
1338 * @hw: pointer to the hw struct
1339 * @entry_h: handle to the flow entry to be removed
1341 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1343 struct ice_flow_entry *entry;
1344 struct ice_flow_prof *prof;
1345 enum ice_status status;
1347 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1348 return ICE_ERR_PARAM;
1350 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1352 /* Retain the pointer to the flow profile as the entry will be freed */
1355 ice_acquire_lock(&prof->entries_lock);
1356 status = ice_flow_rem_entry_sync(hw, entry);
1357 ice_release_lock(&prof->entries_lock);
1363 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1364 * @seg: packet segment the field being set belongs to
1365 * @fld: field to be set
1366 * @type: type of the field
1367 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1368 * entry's input buffer
1369 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1371 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1372 * entry's input buffer
1374 * This helper function stores information of a field being matched, including
1375 * the type of the field and the locations of the value to match, the mask, and
1376 * and the upper-bound value in the start of the input buffer for a flow entry.
1377 * This function should only be used for fixed-size data structures.
1379 * This function also opportunistically determines the protocol headers to be
1380 * present based on the fields being set. Some fields cannot be used alone to
1381 * determine the protocol headers present. Sometimes, fields for particular
1382 * protocol headers are not matched. In those cases, the protocol headers
1383 * must be explicitly set.
1386 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1387 enum ice_flow_fld_match_type type, u16 val_loc,
1388 u16 mask_loc, u16 last_loc)
1390 u64 bit = BIT_ULL(fld);
1393 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1396 seg->fields[fld].type = type;
1397 seg->fields[fld].src.val = val_loc;
1398 seg->fields[fld].src.mask = mask_loc;
1399 seg->fields[fld].src.last = last_loc;
1401 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1405 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1406 * @seg: packet segment the field being set belongs to
1407 * @fld: field to be set
1408 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1409 * entry's input buffer
1410 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1412 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1413 * entry's input buffer
1414 * @range: indicate if field being matched is to be in a range
1416 * This function specifies the locations, in the form of byte offsets from the
1417 * start of the input buffer for a flow entry, from where the value to match,
1418 * the mask value, and upper value can be extracted. These locations are then
1419 * stored in the flow profile. When adding a flow entry associated with the
1420 * flow profile, these locations will be used to quickly extract the values and
1421 * create the content of a match entry. This function should only be used for
1422 * fixed-size data structures.
1425 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1426 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1428 enum ice_flow_fld_match_type t = range ?
1429 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1431 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1435 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1436 * @seg: packet segment the field being set belongs to
1437 * @fld: field to be set
1438 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1439 * entry's input buffer
1440 * @pref_loc: location of prefix value from entry's input buffer
1441 * @pref_sz: size of the location holding the prefix value
1443 * This function specifies the locations, in the form of byte offsets from the
1444 * start of the input buffer for a flow entry, from where the value to match
1445 * and the IPv4 prefix value can be extracted. These locations are then stored
1446 * in the flow profile. When adding flow entries to the associated flow profile,
1447 * these locations can be used to quickly extract the values to create the
1448 * content of a match entry. This function should only be used for fixed-size
1452 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1453 u16 val_loc, u16 pref_loc, u8 pref_sz)
1455 /* For this type of field, the "mask" location is for the prefix value's
1456 * location and the "last" location is for the size of the location of
1459 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1460 pref_loc, (u16)pref_sz);
1464 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1465 * @seg: packet segment the field being set belongs to
1466 * @off: offset of the raw field from the beginning of the segment in bytes
1467 * @len: length of the raw pattern to be matched
1468 * @val_loc: location of the value to match from entry's input buffer
1469 * @mask_loc: location of mask value from entry's input buffer
1471 * This function specifies the offset of the raw field to be match from the
1472 * beginning of the specified packet segment, and the locations, in the form of
1473 * byte offsets from the start of the input buffer for a flow entry, from where
1474 * the value to match and the mask value to be extracted. These locations are
1475 * then stored in the flow profile. When adding flow entries to the associated
1476 * flow profile, these locations can be used to quickly extract the values to
1477 * create the content of a match entry. This function should only be used for
1478 * fixed-size data structures.
1481 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1482 u16 val_loc, u16 mask_loc)
1484 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1485 seg->raws[seg->raws_cnt].off = off;
1486 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1487 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1488 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1489 /* The "last" field is used to store the length of the field */
1490 seg->raws[seg->raws_cnt].info.src.last = len;
1493 /* Overflows of "raws" will be handled as an error condition later in
1494 * the flow when this information is processed.
1499 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1500 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1502 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1503 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1504 ICE_FLOW_SEG_HDR_SCTP)
1506 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1507 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1508 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1511 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1512 * @segs: pointer to the flow field segment(s)
1513 * @hash_fields: fields to be hashed on for the segment(s)
1514 * @flow_hdr: protocol header fields within a packet segment
1516 * Helper function to extract fields from hash bitmap and use flow
1517 * header value to set flow field segment for further use in flow
1518 * profile entry or removal.
1520 static enum ice_status
1521 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1524 u64 val = hash_fields;
1527 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1528 u64 bit = BIT_ULL(i);
1531 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1532 ICE_FLOW_FLD_OFF_INVAL,
1533 ICE_FLOW_FLD_OFF_INVAL,
1534 ICE_FLOW_FLD_OFF_INVAL, false);
1538 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1540 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1541 return ICE_ERR_PARAM;
1543 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1544 if (!ice_is_pow2(val))
1547 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1548 if (val && !ice_is_pow2(val))
1554 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1555 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1556 * convert its values to their appropriate flow L3, L4 values.
1558 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1559 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1560 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1561 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1562 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1563 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1564 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1565 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1566 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1567 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1568 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1569 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1570 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1572 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1573 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1574 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1575 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1576 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1577 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1578 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1579 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1580 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1581 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1582 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1583 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1584 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1586 #define ICE_FLOW_MAX_CFG 10
1589 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1590 * @hw: pointer to the hardware structure
1591 * @vsi_handle: software VSI handle
1592 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1594 * This function will take the hash bitmap provided by the AVF driver via a
1595 * message, convert it to ICE-compatible values, and configure RSS flow
1599 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1601 u64 added_cfg[ICE_FLOW_MAX_CFG], hash_flds;
1602 enum ice_status status = ICE_SUCCESS;
1605 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1606 !ice_is_vsi_valid(hw, vsi_handle))
1607 return ICE_ERR_PARAM;
1609 /* Make sure no unsupported bits are specified */
1610 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1611 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1614 hash_flds = avf_hash;
1616 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1617 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1618 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1620 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1621 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1623 /* Create the corresponding RSS configuration for each valid hash bit */
1625 u64 rss_hash = ICE_HASH_INVALID;
1627 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1628 if (hash_flds & ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1629 rss_hash = ICE_FLOW_HASH_IPV4 |
1630 ICE_FLOW_HASH_TCP_PORT;
1631 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1632 } else if (hash_flds &
1633 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1634 rss_hash = ICE_FLOW_HASH_IPV4 |
1635 ICE_FLOW_HASH_UDP_PORT;
1636 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1637 } else if (hash_flds &
1638 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1639 rss_hash = ICE_FLOW_HASH_IPV4 |
1640 ICE_FLOW_HASH_SCTP_PORT;
1642 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1643 } else if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1644 rss_hash = ICE_FLOW_HASH_IPV4;
1645 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1647 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1648 if (hash_flds & ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1649 rss_hash = ICE_FLOW_HASH_IPV6 |
1650 ICE_FLOW_HASH_TCP_PORT;
1651 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1652 } else if (hash_flds &
1653 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1654 rss_hash = ICE_FLOW_HASH_IPV6 |
1655 ICE_FLOW_HASH_UDP_PORT;
1656 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1657 } else if (hash_flds &
1658 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1659 rss_hash = ICE_FLOW_HASH_IPV6 |
1660 ICE_FLOW_HASH_SCTP_PORT;
1662 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1663 } else if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1664 rss_hash = ICE_FLOW_HASH_IPV6;
1665 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1669 if (rss_hash == ICE_HASH_INVALID)
1670 return ICE_ERR_OUT_OF_RANGE;
1672 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
1673 ICE_FLOW_SEG_HDR_NONE);
1676 added_cfg[idx++] = rss_hash;
1679 /* If status is not success, we must remove all hash configurations
1680 * that were successfully added previously in this call for the vsi
1683 for (i = 0; i < idx; i++)
1684 ice_rem_rss_cfg(hw, vsi_handle, added_cfg[i],
1685 ICE_FLOW_SEG_HDR_NONE);
1691 * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context
1692 * @hw: pointer to the hardware structure
1693 * @vsi_handle: software VSI handle
1696 void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
1698 struct ice_rss_cfg *r, *tmp;
1700 if (!ice_is_vsi_valid(hw, vsi_handle) ||
1701 LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head))
1704 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1705 LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1706 &hw->vsi_ctx[vsi_handle]->rss_list_head,
1707 ice_rss_cfg, l_entry) {
1708 LIST_DEL(&r->l_entry);
1711 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1715 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with vsi
1716 * @hw: pointer to the hardware structure
1717 * @vsi_handle: software VSI handle
1719 * This function will iterate through all flow profiles and disassociate
1720 * the vsi from that profile. If the flow profile has no vsis it will
1723 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1725 const enum ice_block blk = ICE_BLK_RSS;
1726 struct ice_flow_prof *p, *t;
1727 enum ice_status status = ICE_SUCCESS;
1729 if (!ice_is_vsi_valid(hw, vsi_handle))
1730 return ICE_ERR_PARAM;
1732 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1733 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1735 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1736 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1740 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1741 status = ice_flow_rem_prof_sync(hw, blk, p);
1747 ice_release_lock(&hw->fl_profs_locks[blk]);
1753 * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context
1754 * @hw: pointer to the hardware structure
1755 * @vsi_handle: software VSI handle
1756 * @prof: pointer to flow profile
1758 * Assumption: lock has already been acquired for RSS list
1761 ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1762 struct ice_flow_prof *prof)
1764 struct ice_rss_cfg *r, *tmp;
1766 /* Search for RSS hash fields associated to the VSI that match the
1767 * hash configurations associated to the flow profile. If found
1768 * remove from the RSS entry list of the VSI context and delete entry.
1770 LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1771 &hw->vsi_ctx[vsi_handle]->rss_list_head,
1772 ice_rss_cfg, l_entry) {
1773 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1774 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1775 LIST_DEL(&r->l_entry);
1783 * ice_add_rss_vsi_ctx - add RSS configuration to VSI context
1784 * @hw: pointer to the hardware structure
1785 * @vsi_handle: software VSI handle
1786 * @prof: pointer to flow profile
1788 * Assumption: lock has already been acquired for RSS list
1790 static enum ice_status
1791 ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1792 struct ice_flow_prof *prof)
1794 struct ice_rss_cfg *r, *rss_cfg;
1796 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1797 ice_rss_cfg, l_entry)
1798 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1799 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs)
1802 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1804 return ICE_ERR_NO_MEMORY;
1806 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1807 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1808 LIST_ADD(&rss_cfg->l_entry, &hw->vsi_ctx[vsi_handle]->rss_list_head);
1813 #define ICE_FLOW_PROF_HASH_S 0
1814 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1815 #define ICE_FLOW_PROF_HDR_S 32
1816 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1818 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1819 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1820 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1823 * ice_add_rss_cfg_sync - add an RSS configuration
1824 * @hw: pointer to the hardware structure
1825 * @vsi_handle: software VSI handle
1826 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1827 * @addl_hdrs: protocol header fields
1829 * Assumption: lock has already been acquired for RSS list
1831 static enum ice_status
1832 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1835 const enum ice_block blk = ICE_BLK_RSS;
1836 struct ice_flow_prof *prof = NULL;
1837 struct ice_flow_seg_info *segs;
1838 enum ice_status status = ICE_SUCCESS;
1840 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1842 return ICE_ERR_NO_MEMORY;
1844 /* Construct the packet segment info from the hashed fields */
1845 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1849 /* Search for a flow profile that has matching headers, hash fields
1850 * and has the input vsi associated to it. If found, no further
1851 * operations required and exit.
1853 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1855 ICE_FLOW_FIND_PROF_CHK_FLDS |
1856 ICE_FLOW_FIND_PROF_CHK_VSI);
1860 /* Check if a flow profile exists with the same protocol headers and
1861 * associated with the input vsi. If so disasscociate the vsi from
1862 * this profile. The vsi will be added to a new profile created with
1863 * the protocol header and new hash field configuration.
1865 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1866 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1868 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1870 ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1874 /* Remove profile if it has no vsis associated */
1875 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1876 status = ice_flow_rem_prof_sync(hw, blk, prof);
1882 /* Search for a profile that has same match fields only. If this
1883 * exists then associate the vsi to this profile.
1885 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1887 ICE_FLOW_FIND_PROF_CHK_FLDS);
1889 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1891 status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1895 /* Create a new flow profile with generated profile and packet
1896 * segment information.
1898 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1899 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1900 segs, 1, NULL, 0, &prof);
1904 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1905 /* If association to a new flow profile failed then this profile can
1909 ice_flow_rem_prof_sync(hw, blk, prof);
1913 status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1921 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1922 * @hw: pointer to the hardware structure
1923 * @vsi_handle: software VSI handle
1924 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1925 * @addl_hdrs: protocol header fields
1927 * This function will generate a flow profile based on fields associated with
1928 * the input fields to hash on, the flow type and use the VSI number to add
1929 * a flow entry to the profile.
1932 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1935 enum ice_status status;
1937 if (hashed_flds == ICE_HASH_INVALID ||
1938 !ice_is_vsi_valid(hw, vsi_handle))
1939 return ICE_ERR_PARAM;
1941 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1942 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1943 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1949 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1950 * @hw: pointer to the hardware structure
1951 * @vsi_handle: software VSI handle
1952 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1953 * @addl_hdrs: Protocol header fields within a packet segment
1955 * Assumption: lock has already been acquired for RSS list
1957 static enum ice_status
1958 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1961 const enum ice_block blk = ICE_BLK_RSS;
1962 struct ice_flow_seg_info *segs;
1963 struct ice_flow_prof *prof;
1964 enum ice_status status;
1966 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1968 return ICE_ERR_NO_MEMORY;
1970 /* Construct the packet segment info from the hashed fields */
1971 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1975 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1977 ICE_FLOW_FIND_PROF_CHK_FLDS);
1979 status = ICE_ERR_DOES_NOT_EXIST;
1983 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1987 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1988 status = ice_flow_rem_prof_sync(hw, blk, prof);
1990 ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1998 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
1999 * @hw: pointer to the hardware structure
2000 * @vsi_handle: software VSI handle
2001 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2002 * @addl_hdrs: Protocol header fields within a packet segment
2004 * This function will lookup the flow profile based on the input
2005 * hash field bitmap, iterate through the profile entry list of
2006 * that profile and find entry associated with input vsi to be
2007 * removed. Calls are made to underlying flow apis which will in
2008 * turn build or update buffers for RSS XLT1 section.
2011 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2014 enum ice_status status;
2016 if (hashed_flds == ICE_HASH_INVALID ||
2017 !ice_is_vsi_valid(hw, vsi_handle))
2018 return ICE_ERR_PARAM;
2020 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2021 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2022 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2028 * ice_replay_rss_cfg - remove RSS configurations associated with vsi
2029 * @hw: pointer to the hardware structure
2030 * @vsi_handle: software VSI handle
2032 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2034 enum ice_status status = ICE_SUCCESS;
2035 struct ice_rss_cfg *r;
2037 if (!ice_is_vsi_valid(hw, vsi_handle))
2038 return ICE_ERR_PARAM;
2040 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2041 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
2042 ice_rss_cfg, l_entry) {
2043 status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds,
2048 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2054 * ice_get_rss_cfg - returns hashed fields for the given header types
2055 * @hw: pointer to the hardware structure
2056 * @vsi_handle: software VSI handle
2057 * @hdrs: protocol header type
2059 * This function will return the match fields of the first instance of flow
2060 * profile having the given header types and containing input vsi
2062 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2064 struct ice_rss_cfg *r, *rss_cfg = NULL;
2066 /* verify if the protocol header is non zero and vsi is valid */
2067 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2068 return ICE_HASH_INVALID;
2070 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2071 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
2072 ice_rss_cfg, l_entry)
2073 if (r->packet_hdr == hdrs) {
2077 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2079 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;