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 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
296 * This will give us the direction flags.
298 struct ice_fv_word es[ICE_MAX_FV_WORDS];
300 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
304 * ice_is_pow2 - check if integer value is a power of 2
305 * @val: unsigned integer to be validated
307 static bool ice_is_pow2(u64 val)
309 return (val && !(val & (val - 1)));
312 #define ICE_FLOW_SEG_HDRS_L2_MASK \
313 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
314 #define ICE_FLOW_SEG_HDRS_L3_MASK \
315 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
316 #define ICE_FLOW_SEG_HDRS_L4_MASK \
317 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
318 ICE_FLOW_SEG_HDR_SCTP)
321 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
322 * @segs: array of one or more packet segments that describe the flow
323 * @segs_cnt: number of packet segments provided
325 static enum ice_status
326 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
328 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
329 ICE_FLOW_SEG_HDRS_L3_MASK |
330 ICE_FLOW_SEG_HDRS_L4_MASK);
333 for (i = 0; i < segs_cnt; i++) {
334 /* No header specified */
335 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
336 return ICE_ERR_PARAM;
338 /* Multiple L3 headers */
339 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
340 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
341 return ICE_ERR_PARAM;
343 /* Multiple L4 headers */
344 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
345 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
346 return ICE_ERR_PARAM;
352 /* Sizes of fixed known protocol headers without header options */
353 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
354 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
355 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
356 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
357 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
358 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
359 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
360 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
361 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
364 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
365 * @params: information about the flow to be processed
366 * @seg: index of packet segment whose header size is to be determined
368 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
373 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
374 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
377 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
378 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
379 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
380 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
381 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
382 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
383 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
384 /* A L3 header is required if L4 is specified */
388 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
389 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
390 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
391 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
392 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
393 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
394 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
395 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
401 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
402 * @params: information about the flow to be processed
404 * This function identifies the packet types associated with the protocol
405 * headers being present in packet segments of the specified flow profile.
407 static enum ice_status
408 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
410 struct ice_flow_prof *prof;
413 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
418 for (i = 0; i < params->prof->segs_cnt; i++) {
419 const ice_bitmap_t *src;
422 if (i > 0 && (i + 1) < prof->segs_cnt)
425 hdrs = prof->segs[i].hdrs;
427 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
428 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
429 (const ice_bitmap_t *)ice_ptypes_mac_il;
430 ice_and_bitmap(params->ptypes, params->ptypes, src,
432 hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
435 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
436 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
437 ice_and_bitmap(params->ptypes, params->ptypes, src,
439 hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
442 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
443 ice_and_bitmap(params->ptypes, params->ptypes,
444 (const ice_bitmap_t *)ice_ptypes_arp_of,
446 hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
449 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
450 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
451 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
452 ice_and_bitmap(params->ptypes, params->ptypes, src,
454 hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
455 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
456 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
457 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
458 ice_and_bitmap(params->ptypes, params->ptypes, src,
460 hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
463 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
464 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
465 (const ice_bitmap_t *)ice_ptypes_icmp_il;
466 ice_and_bitmap(params->ptypes, params->ptypes, src,
468 hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
469 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
470 src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of :
471 (const ice_bitmap_t *)ice_ptypes_udp_il;
472 ice_and_bitmap(params->ptypes, params->ptypes, src,
474 hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
475 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
476 ice_and_bitmap(params->ptypes, params->ptypes,
477 (const ice_bitmap_t *)ice_ptypes_tcp_il,
479 hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
480 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
481 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
482 ice_and_bitmap(params->ptypes, params->ptypes, src,
484 hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
485 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
487 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
488 ice_and_bitmap(params->ptypes, params->ptypes,
489 src, ICE_FLOW_PTYPE_MAX);
491 hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
499 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
500 * @hw: pointer to the HW struct
501 * @params: information about the flow to be processed
502 * @seg: packet segment index of the field to be extracted
503 * @fld: ID of field to be extracted
505 * This function determines the protocol ID, offset, and size of the given
506 * field. It then allocates one or more extraction sequence entries for the
507 * given field, and fill the entries with protocol ID and offset information.
509 static enum ice_status
510 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
511 u8 seg, enum ice_flow_field fld)
513 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
514 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
515 u8 fv_words = hw->blk[params->blk].es.fvw;
516 struct ice_flow_fld_info *flds;
517 u16 cnt, ese_bits, i;
521 flds = params->prof->segs[seg].fields;
524 case ICE_FLOW_FIELD_IDX_ETH_DA:
525 case ICE_FLOW_FIELD_IDX_ETH_SA:
526 case ICE_FLOW_FIELD_IDX_S_VLAN:
527 case ICE_FLOW_FIELD_IDX_C_VLAN:
528 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
530 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
531 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
533 case ICE_FLOW_FIELD_IDX_IP_DSCP:
534 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
535 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
537 case ICE_FLOW_FIELD_IDX_IP_TTL:
538 case ICE_FLOW_FIELD_IDX_IP_PROT:
539 /* Some fields are located at different offsets in IPv4 and
542 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
543 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
545 /* TTL and PROT share the same extraction seq. entry.
546 * Each is considered a sibling to the other in term
547 * sharing the same extraction sequence entry.
549 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
550 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
551 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
552 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
553 } else if (params->prof->segs[seg].hdrs &
554 ICE_FLOW_SEG_HDR_IPV6) {
555 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
557 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
558 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
559 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
560 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
563 case ICE_FLOW_FIELD_IDX_IPV4_SA:
564 case ICE_FLOW_FIELD_IDX_IPV4_DA:
565 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
567 case ICE_FLOW_FIELD_IDX_IPV6_SA:
568 case ICE_FLOW_FIELD_IDX_IPV6_DA:
569 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
571 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
572 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
573 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
574 prot_id = ICE_PROT_TCP_IL;
576 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
577 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
578 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
580 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
581 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
582 prot_id = ICE_PROT_SCTP_IL;
584 case ICE_FLOW_FIELD_IDX_ARP_SIP:
585 case ICE_FLOW_FIELD_IDX_ARP_DIP:
586 case ICE_FLOW_FIELD_IDX_ARP_SHA:
587 case ICE_FLOW_FIELD_IDX_ARP_DHA:
588 case ICE_FLOW_FIELD_IDX_ARP_OP:
589 prot_id = ICE_PROT_ARP_OF;
591 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
592 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
593 /* ICMP type and code share the same extraction seq. entry */
594 prot_id = (params->prof->segs[seg].hdrs &
595 ICE_FLOW_SEG_HDR_IPV4) ?
596 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
597 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
598 ICE_FLOW_FIELD_IDX_ICMP_CODE :
599 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
601 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
602 prot_id = ICE_PROT_GRE_OF;
605 return ICE_ERR_NOT_IMPL;
608 /* Each extraction sequence entry is a word in size, and extracts a
609 * word-aligned offset from a protocol header.
611 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
613 flds[fld].xtrct.prot_id = prot_id;
614 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
615 ICE_FLOW_FV_EXTRACT_SZ;
616 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
617 flds[fld].xtrct.idx = params->es_cnt;
619 /* Adjust the next field-entry index after accommodating the number of
620 * entries this field consumes
622 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
623 ice_flds_info[fld].size, ese_bits);
625 /* Fill in the extraction sequence entries needed for this field */
626 off = flds[fld].xtrct.off;
627 for (i = 0; i < cnt; i++) {
628 /* Only consume an extraction sequence entry if there is no
629 * sibling field associated with this field or the sibling entry
630 * already extracts the word shared with this field.
632 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
633 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
634 flds[sib].xtrct.off != off) {
637 /* Make sure the number of extraction sequence required
638 * does not exceed the block's capability
640 if (params->es_cnt >= fv_words)
641 return ICE_ERR_MAX_LIMIT;
643 /* some blocks require a reversed field vector layout */
644 if (hw->blk[params->blk].es.reverse)
645 idx = fv_words - params->es_cnt - 1;
647 idx = params->es_cnt;
649 params->es[idx].prot_id = prot_id;
650 params->es[idx].off = off;
654 off += ICE_FLOW_FV_EXTRACT_SZ;
661 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
662 * @hw: pointer to the HW struct
663 * @params: information about the flow to be processed
664 * @seg: index of packet segment whose raw fields are to be be extracted
666 static enum ice_status
667 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
673 if (!params->prof->segs[seg].raws_cnt)
676 if (params->prof->segs[seg].raws_cnt >
677 ARRAY_SIZE(params->prof->segs[seg].raws))
678 return ICE_ERR_MAX_LIMIT;
680 /* Offsets within the segment headers are not supported */
681 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
683 return ICE_ERR_PARAM;
685 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
686 struct ice_flow_seg_fld_raw *raw;
689 raw = ¶ms->prof->segs[seg].raws[i];
691 /* Only support matching raw fields in the payload */
692 if (raw->off < hdrs_sz)
693 return ICE_ERR_PARAM;
695 /* Convert the segment-relative offset into payload-relative
698 off = raw->off - hdrs_sz;
700 /* Storing extraction information */
701 raw->info.xtrct.prot_id = ICE_PROT_PAY;
702 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
703 ICE_FLOW_FV_EXTRACT_SZ;
704 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
705 raw->info.xtrct.idx = params->es_cnt;
707 /* Determine the number of field vector entries this raw field
710 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
711 (raw->info.src.last * 8),
712 ICE_FLOW_FV_EXTRACT_SZ * 8);
713 off = raw->info.xtrct.off;
714 for (j = 0; j < cnt; j++) {
715 /* Make sure the number of extraction sequence required
716 * does not exceed the block's capability
718 if (params->es_cnt >= hw->blk[params->blk].es.count ||
719 params->es_cnt >= ICE_MAX_FV_WORDS)
720 return ICE_ERR_MAX_LIMIT;
722 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
723 params->es[params->es_cnt].off = off;
725 off += ICE_FLOW_FV_EXTRACT_SZ;
733 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
734 * @hw: pointer to the HW struct
735 * @params: information about the flow to be processed
737 * This function iterates through all matched fields in the given segments, and
738 * creates an extraction sequence for the fields.
740 static enum ice_status
741 ice_flow_create_xtrct_seq(struct ice_hw *hw,
742 struct ice_flow_prof_params *params)
744 enum ice_status status = ICE_SUCCESS;
747 for (i = 0; i < params->prof->segs_cnt; i++) {
748 u64 match = params->prof->segs[i].match;
751 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
752 const u64 bit = BIT_ULL(j);
755 status = ice_flow_xtract_fld
756 (hw, params, i, (enum ice_flow_field)j);
763 /* Process raw matching bytes */
764 status = ice_flow_xtract_raws(hw, params, i);
773 * ice_flow_proc_segs - process all packet segments associated with a profile
774 * @hw: pointer to the HW struct
775 * @params: information about the flow to be processed
777 static enum ice_status
778 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
780 enum ice_status status;
782 status = ice_flow_proc_seg_hdrs(params);
786 status = ice_flow_create_xtrct_seq(hw, params);
790 switch (params->blk) {
792 /* Only header information is provided for RSS configuration.
793 * No further processing is needed.
795 status = ICE_SUCCESS;
798 status = ICE_SUCCESS;
802 return ICE_ERR_NOT_IMPL;
808 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
809 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
812 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
813 * @hw: pointer to the HW struct
814 * @blk: classification stage
815 * @dir: flow direction
816 * @segs: array of one or more packet segments that describe the flow
817 * @segs_cnt: number of packet segments provided
818 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
819 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
821 static struct ice_flow_prof *
822 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
823 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
824 u8 segs_cnt, u16 vsi_handle, u32 conds)
826 struct ice_flow_prof *p;
828 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
829 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
832 /* Check for profile-VSI association if specified */
833 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
834 ice_is_vsi_valid(hw, vsi_handle) &&
835 !ice_is_bit_set(p->vsis, vsi_handle))
838 /* Protocol headers must be checked. Matched fields are
839 * checked if specified.
841 for (i = 0; i < segs_cnt; i++)
842 if (segs[i].hdrs != p->segs[i].hdrs ||
843 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
844 segs[i].match != p->segs[i].match))
847 /* A match is found if all segments are matched */
857 * ice_flow_find_prof - Look up a profile matching headers and matched fields
858 * @hw: pointer to the HW struct
859 * @blk: classification stage
860 * @dir: flow direction
861 * @segs: array of one or more packet segments that describe the flow
862 * @segs_cnt: number of packet segments provided
865 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
866 struct ice_flow_seg_info *segs, u8 segs_cnt)
868 struct ice_flow_prof *p;
870 ice_acquire_lock(&hw->fl_profs_locks[blk]);
871 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
872 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
873 ice_release_lock(&hw->fl_profs_locks[blk]);
875 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
879 * ice_flow_find_prof_id - Look up a profile with given profile ID
880 * @hw: pointer to the HW struct
881 * @blk: classification stage
882 * @prof_id: unique ID to identify this flow profile
884 static struct ice_flow_prof *
885 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
887 struct ice_flow_prof *p;
889 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
890 if (p->id == prof_id)
898 * ice_flow_rem_entry_sync - Remove a flow entry
899 * @hw: pointer to the HW struct
900 * @entry: flow entry to be removed
902 static enum ice_status
903 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
906 return ICE_ERR_BAD_PTR;
908 LIST_DEL(&entry->l_entry);
911 ice_free(hw, entry->entry);
914 ice_free(hw, entry->acts);
922 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
923 * @hw: pointer to the HW struct
924 * @blk: classification stage
925 * @dir: flow direction
926 * @prof_id: unique ID to identify this flow profile
927 * @segs: array of one or more packet segments that describe the flow
928 * @segs_cnt: number of packet segments provided
929 * @acts: array of default actions
930 * @acts_cnt: number of default actions
931 * @prof: stores the returned flow profile added
933 * Assumption: the caller has acquired the lock to the profile list
935 static enum ice_status
936 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
937 enum ice_flow_dir dir, u64 prof_id,
938 struct ice_flow_seg_info *segs, u8 segs_cnt,
939 struct ice_flow_action *acts, u8 acts_cnt,
940 struct ice_flow_prof **prof)
942 struct ice_flow_prof_params params;
943 enum ice_status status = ICE_SUCCESS;
946 if (!prof || (acts_cnt && !acts))
947 return ICE_ERR_BAD_PTR;
949 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
950 params.prof = (struct ice_flow_prof *)
951 ice_malloc(hw, sizeof(*params.prof));
953 return ICE_ERR_NO_MEMORY;
955 /* initialize extraction sequence to all invalid (0xff) */
956 ice_memset(params.es, 0xff, sizeof(params.es), ICE_NONDMA_MEM);
959 params.prof->id = prof_id;
960 params.prof->dir = dir;
961 params.prof->segs_cnt = segs_cnt;
963 /* Make a copy of the segments that need to be persistent in the flow
966 for (i = 0; i < segs_cnt; i++)
967 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
968 ICE_NONDMA_TO_NONDMA);
970 /* Make a copy of the actions that need to be persistent in the flow
974 params.prof->acts = (struct ice_flow_action *)
975 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
976 ICE_NONDMA_TO_NONDMA);
978 if (!params.prof->acts) {
979 status = ICE_ERR_NO_MEMORY;
984 status = ice_flow_proc_segs(hw, ¶ms);
986 ice_debug(hw, ICE_DBG_FLOW,
987 "Error processing a flow's packet segments\n");
991 /* Add a HW profile for this flow profile */
992 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
994 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
998 INIT_LIST_HEAD(¶ms.prof->entries);
999 ice_init_lock(¶ms.prof->entries_lock);
1000 *prof = params.prof;
1004 if (params.prof->acts)
1005 ice_free(hw, params.prof->acts);
1006 ice_free(hw, params.prof);
1013 * ice_flow_rem_prof_sync - remove a flow profile
1014 * @hw: pointer to the hardware structure
1015 * @blk: classification stage
1016 * @prof: pointer to flow profile to remove
1018 * Assumption: the caller has acquired the lock to the profile list
1020 static enum ice_status
1021 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1022 struct ice_flow_prof *prof)
1024 enum ice_status status = ICE_SUCCESS;
1026 /* Remove all remaining flow entries before removing the flow profile */
1027 if (!LIST_EMPTY(&prof->entries)) {
1028 struct ice_flow_entry *e, *t;
1030 ice_acquire_lock(&prof->entries_lock);
1032 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1034 status = ice_flow_rem_entry_sync(hw, e);
1039 ice_release_lock(&prof->entries_lock);
1042 /* Remove all hardware profiles associated with this flow profile */
1043 status = ice_rem_prof(hw, blk, prof->id);
1045 LIST_DEL(&prof->l_entry);
1046 ice_destroy_lock(&prof->entries_lock);
1048 ice_free(hw, prof->acts);
1056 * ice_flow_assoc_prof - associate a VSI with a flow profile
1057 * @hw: pointer to the hardware structure
1058 * @blk: classification stage
1059 * @prof: pointer to flow profile
1060 * @vsi_handle: software VSI handle
1062 * Assumption: the caller has acquired the lock to the profile list
1063 * and the software VSI handle has been validated
1065 static enum ice_status
1066 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1067 struct ice_flow_prof *prof, u16 vsi_handle)
1069 enum ice_status status = ICE_SUCCESS;
1071 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1072 status = ice_add_prof_id_flow(hw, blk,
1073 ice_get_hw_vsi_num(hw,
1077 ice_set_bit(vsi_handle, prof->vsis);
1079 ice_debug(hw, ICE_DBG_FLOW,
1080 "HW profile add failed, %d\n",
1088 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1089 * @hw: pointer to the hardware structure
1090 * @blk: classification stage
1091 * @prof: pointer to flow profile
1092 * @vsi_handle: software VSI handle
1094 * Assumption: the caller has acquired the lock to the profile list
1095 * and the software VSI handle has been validated
1097 static enum ice_status
1098 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1099 struct ice_flow_prof *prof, u16 vsi_handle)
1101 enum ice_status status = ICE_SUCCESS;
1103 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1104 status = ice_rem_prof_id_flow(hw, blk,
1105 ice_get_hw_vsi_num(hw,
1109 ice_clear_bit(vsi_handle, prof->vsis);
1111 ice_debug(hw, ICE_DBG_FLOW,
1112 "HW profile remove failed, %d\n",
1120 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1121 * @hw: pointer to the HW struct
1122 * @blk: classification stage
1123 * @dir: flow direction
1124 * @prof_id: unique ID to identify this flow profile
1125 * @segs: array of one or more packet segments that describe the flow
1126 * @segs_cnt: number of packet segments provided
1127 * @acts: array of default actions
1128 * @acts_cnt: number of default actions
1129 * @prof: stores the returned flow profile added
1132 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1133 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1134 struct ice_flow_action *acts, u8 acts_cnt,
1135 struct ice_flow_prof **prof)
1137 enum ice_status status;
1139 if (segs_cnt > ICE_FLOW_SEG_MAX)
1140 return ICE_ERR_MAX_LIMIT;
1143 return ICE_ERR_PARAM;
1146 return ICE_ERR_BAD_PTR;
1148 status = ice_flow_val_hdrs(segs, segs_cnt);
1152 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1154 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1155 acts, acts_cnt, prof);
1157 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1159 ice_release_lock(&hw->fl_profs_locks[blk]);
1165 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1166 * @hw: pointer to the HW struct
1167 * @blk: the block for which the flow profile is to be removed
1168 * @prof_id: unique ID of the flow profile to be removed
1171 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1173 struct ice_flow_prof *prof;
1174 enum ice_status status;
1176 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1178 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1180 status = ICE_ERR_DOES_NOT_EXIST;
1184 /* prof becomes invalid after the call */
1185 status = ice_flow_rem_prof_sync(hw, blk, prof);
1188 ice_release_lock(&hw->fl_profs_locks[blk]);
1194 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1195 * @hw: pointer to the HW struct
1196 * @blk: classification stage
1197 * @prof_id: the profile ID handle
1198 * @hw_prof_id: pointer to variable to receive the HW profile ID
1201 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1204 struct ice_prof_map *map;
1206 map = ice_search_prof_id(hw, blk, prof_id);
1208 *hw_prof_id = map->prof_id;
1212 return ICE_ERR_DOES_NOT_EXIST;
1216 * ice_flow_find_entry - look for a flow entry using its unique ID
1217 * @hw: pointer to the HW struct
1218 * @blk: classification stage
1219 * @entry_id: unique ID to identify this flow entry
1221 * This function looks for the flow entry with the specified unique ID in all
1222 * flow profiles of the specified classification stage. If the entry is found,
1223 * and it returns the handle to the flow entry. Otherwise, it returns
1224 * ICE_FLOW_ENTRY_ID_INVAL.
1226 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1228 struct ice_flow_entry *found = NULL;
1229 struct ice_flow_prof *p;
1231 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1233 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1234 struct ice_flow_entry *e;
1236 ice_acquire_lock(&p->entries_lock);
1237 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1238 if (e->id == entry_id) {
1242 ice_release_lock(&p->entries_lock);
1248 ice_release_lock(&hw->fl_profs_locks[blk]);
1250 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1254 * ice_flow_add_entry - Add a flow entry
1255 * @hw: pointer to the HW struct
1256 * @blk: classification stage
1257 * @prof_id: ID of the profile to add a new flow entry to
1258 * @entry_id: unique ID to identify this flow entry
1259 * @vsi_handle: software VSI handle for the flow entry
1260 * @prio: priority of the flow entry
1261 * @data: pointer to a data buffer containing flow entry's match values/masks
1262 * @acts: arrays of actions to be performed on a match
1263 * @acts_cnt: number of actions
1264 * @entry_h: pointer to buffer that receives the new flow entry's handle
1267 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1268 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1269 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1272 struct ice_flow_prof *prof = NULL;
1273 struct ice_flow_entry *e = NULL;
1274 enum ice_status status = ICE_SUCCESS;
1276 if (acts_cnt && !acts)
1277 return ICE_ERR_PARAM;
1279 /* No flow entry data is expected for RSS */
1280 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1281 return ICE_ERR_BAD_PTR;
1283 if (!ice_is_vsi_valid(hw, vsi_handle))
1284 return ICE_ERR_PARAM;
1286 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1288 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1290 status = ICE_ERR_DOES_NOT_EXIST;
1292 /* Allocate memory for the entry being added and associate
1293 * the VSI to the found flow profile
1295 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1297 status = ICE_ERR_NO_MEMORY;
1299 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1302 ice_release_lock(&hw->fl_profs_locks[blk]);
1307 e->vsi_handle = vsi_handle;
1312 /* RSS will add only one entry per VSI per profile */
1319 status = ICE_ERR_NOT_IMPL;
1323 ice_acquire_lock(&prof->entries_lock);
1324 LIST_ADD(&e->l_entry, &prof->entries);
1325 ice_release_lock(&prof->entries_lock);
1327 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1332 ice_free(hw, e->entry);
1340 * ice_flow_rem_entry - Remove a flow entry
1341 * @hw: pointer to the HW struct
1342 * @entry_h: handle to the flow entry to be removed
1344 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1346 struct ice_flow_entry *entry;
1347 struct ice_flow_prof *prof;
1348 enum ice_status status;
1350 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1351 return ICE_ERR_PARAM;
1353 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1355 /* Retain the pointer to the flow profile as the entry will be freed */
1358 ice_acquire_lock(&prof->entries_lock);
1359 status = ice_flow_rem_entry_sync(hw, entry);
1360 ice_release_lock(&prof->entries_lock);
1366 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1367 * @seg: packet segment the field being set belongs to
1368 * @fld: field to be set
1369 * @type: type of the field
1370 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1371 * entry's input buffer
1372 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1374 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1375 * entry's input buffer
1377 * This helper function stores information of a field being matched, including
1378 * the type of the field and the locations of the value to match, the mask, and
1379 * and the upper-bound value in the start of the input buffer for a flow entry.
1380 * This function should only be used for fixed-size data structures.
1382 * This function also opportunistically determines the protocol headers to be
1383 * present based on the fields being set. Some fields cannot be used alone to
1384 * determine the protocol headers present. Sometimes, fields for particular
1385 * protocol headers are not matched. In those cases, the protocol headers
1386 * must be explicitly set.
1389 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1390 enum ice_flow_fld_match_type type, u16 val_loc,
1391 u16 mask_loc, u16 last_loc)
1393 u64 bit = BIT_ULL(fld);
1396 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1399 seg->fields[fld].type = type;
1400 seg->fields[fld].src.val = val_loc;
1401 seg->fields[fld].src.mask = mask_loc;
1402 seg->fields[fld].src.last = last_loc;
1404 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1408 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1409 * @seg: packet segment the field being set belongs to
1410 * @fld: field to be set
1411 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1412 * entry's input buffer
1413 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1415 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1416 * entry's input buffer
1417 * @range: indicate if field being matched is to be in a range
1419 * This function specifies the locations, in the form of byte offsets from the
1420 * start of the input buffer for a flow entry, from where the value to match,
1421 * the mask value, and upper value can be extracted. These locations are then
1422 * stored in the flow profile. When adding a flow entry associated with the
1423 * flow profile, these locations will be used to quickly extract the values and
1424 * create the content of a match entry. This function should only be used for
1425 * fixed-size data structures.
1428 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1429 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1431 enum ice_flow_fld_match_type t = range ?
1432 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1434 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1438 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1439 * @seg: packet segment the field being set belongs to
1440 * @fld: field to be set
1441 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1442 * entry's input buffer
1443 * @pref_loc: location of prefix value from entry's input buffer
1444 * @pref_sz: size of the location holding the prefix value
1446 * This function specifies the locations, in the form of byte offsets from the
1447 * start of the input buffer for a flow entry, from where the value to match
1448 * and the IPv4 prefix value can be extracted. These locations are then stored
1449 * in the flow profile. When adding flow entries to the associated flow profile,
1450 * these locations can be used to quickly extract the values to create the
1451 * content of a match entry. This function should only be used for fixed-size
1455 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1456 u16 val_loc, u16 pref_loc, u8 pref_sz)
1458 /* For this type of field, the "mask" location is for the prefix value's
1459 * location and the "last" location is for the size of the location of
1462 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1463 pref_loc, (u16)pref_sz);
1467 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1468 * @seg: packet segment the field being set belongs to
1469 * @off: offset of the raw field from the beginning of the segment in bytes
1470 * @len: length of the raw pattern to be matched
1471 * @val_loc: location of the value to match from entry's input buffer
1472 * @mask_loc: location of mask value from entry's input buffer
1474 * This function specifies the offset of the raw field to be match from the
1475 * beginning of the specified packet segment, and the locations, in the form of
1476 * byte offsets from the start of the input buffer for a flow entry, from where
1477 * the value to match and the mask value to be extracted. These locations are
1478 * then stored in the flow profile. When adding flow entries to the associated
1479 * flow profile, these locations can be used to quickly extract the values to
1480 * create the content of a match entry. This function should only be used for
1481 * fixed-size data structures.
1484 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1485 u16 val_loc, u16 mask_loc)
1487 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1488 seg->raws[seg->raws_cnt].off = off;
1489 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1490 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1491 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1492 /* The "last" field is used to store the length of the field */
1493 seg->raws[seg->raws_cnt].info.src.last = len;
1496 /* Overflows of "raws" will be handled as an error condition later in
1497 * the flow when this information is processed.
1502 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1503 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1505 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1506 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1507 ICE_FLOW_SEG_HDR_SCTP)
1509 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1510 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1511 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1514 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1515 * @segs: pointer to the flow field segment(s)
1516 * @hash_fields: fields to be hashed on for the segment(s)
1517 * @flow_hdr: protocol header fields within a packet segment
1519 * Helper function to extract fields from hash bitmap and use flow
1520 * header value to set flow field segment for further use in flow
1521 * profile entry or removal.
1523 static enum ice_status
1524 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1527 u64 val = hash_fields;
1530 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1531 u64 bit = BIT_ULL(i);
1534 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1535 ICE_FLOW_FLD_OFF_INVAL,
1536 ICE_FLOW_FLD_OFF_INVAL,
1537 ICE_FLOW_FLD_OFF_INVAL, false);
1541 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1543 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1544 return ICE_ERR_PARAM;
1546 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1547 if (!ice_is_pow2(val))
1550 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1551 if (val && !ice_is_pow2(val))
1557 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1558 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1559 * convert its values to their appropriate flow L3, L4 values.
1561 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1562 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1563 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1564 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1565 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1566 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1567 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1568 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1569 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1570 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1571 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1572 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1573 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1575 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1576 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1577 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1578 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1579 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1580 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1581 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1582 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1583 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1584 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1585 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1586 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1587 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1589 #define ICE_FLOW_MAX_CFG 10
1592 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1593 * @hw: pointer to the hardware structure
1594 * @vsi_handle: software VSI handle
1595 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1597 * This function will take the hash bitmap provided by the AVF driver via a
1598 * message, convert it to ICE-compatible values, and configure RSS flow
1602 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1604 u64 added_cfg[ICE_FLOW_MAX_CFG], hash_flds;
1605 enum ice_status status = ICE_SUCCESS;
1608 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1609 !ice_is_vsi_valid(hw, vsi_handle))
1610 return ICE_ERR_PARAM;
1612 /* Make sure no unsupported bits are specified */
1613 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1614 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1617 hash_flds = avf_hash;
1619 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1620 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1621 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1623 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1624 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1626 /* Create the corresponding RSS configuration for each valid hash bit */
1628 u64 rss_hash = ICE_HASH_INVALID;
1630 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1631 if (hash_flds & ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
1632 rss_hash = ICE_FLOW_HASH_IPV4 |
1633 ICE_FLOW_HASH_TCP_PORT;
1634 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
1635 } else if (hash_flds &
1636 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
1637 rss_hash = ICE_FLOW_HASH_IPV4 |
1638 ICE_FLOW_HASH_UDP_PORT;
1639 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
1640 } else if (hash_flds &
1641 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
1642 rss_hash = ICE_FLOW_HASH_IPV4 |
1643 ICE_FLOW_HASH_SCTP_PORT;
1645 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
1646 } else if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1647 rss_hash = ICE_FLOW_HASH_IPV4;
1648 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1650 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
1651 if (hash_flds & ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
1652 rss_hash = ICE_FLOW_HASH_IPV6 |
1653 ICE_FLOW_HASH_TCP_PORT;
1654 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
1655 } else if (hash_flds &
1656 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
1657 rss_hash = ICE_FLOW_HASH_IPV6 |
1658 ICE_FLOW_HASH_UDP_PORT;
1659 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
1660 } else if (hash_flds &
1661 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
1662 rss_hash = ICE_FLOW_HASH_IPV6 |
1663 ICE_FLOW_HASH_SCTP_PORT;
1665 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
1666 } else if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
1667 rss_hash = ICE_FLOW_HASH_IPV6;
1668 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
1672 if (rss_hash == ICE_HASH_INVALID)
1673 return ICE_ERR_OUT_OF_RANGE;
1675 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
1676 ICE_FLOW_SEG_HDR_NONE);
1679 added_cfg[idx++] = rss_hash;
1682 /* If status is not success, we must remove all hash configurations
1683 * that were successfully added previously in this call for the vsi
1686 for (i = 0; i < idx; i++)
1687 ice_rem_rss_cfg(hw, vsi_handle, added_cfg[i],
1688 ICE_FLOW_SEG_HDR_NONE);
1694 * ice_rem_all_rss_vsi_ctx - remove all RSS configurations from VSI context
1695 * @hw: pointer to the hardware structure
1696 * @vsi_handle: software VSI handle
1699 void ice_rem_all_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
1701 struct ice_rss_cfg *r, *tmp;
1703 if (!ice_is_vsi_valid(hw, vsi_handle) ||
1704 LIST_EMPTY(&hw->vsi_ctx[vsi_handle]->rss_list_head))
1707 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1708 LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1709 &hw->vsi_ctx[vsi_handle]->rss_list_head,
1710 ice_rss_cfg, l_entry) {
1711 LIST_DEL(&r->l_entry);
1714 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1718 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1719 * @hw: pointer to the hardware structure
1720 * @vsi_handle: software VSI handle
1722 * This function will iterate through all flow profiles and disassociate
1723 * the VSI from that profile. If the flow profile has no VSIs it will
1726 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1728 const enum ice_block blk = ICE_BLK_RSS;
1729 struct ice_flow_prof *p, *t;
1730 enum ice_status status = ICE_SUCCESS;
1732 if (!ice_is_vsi_valid(hw, vsi_handle))
1733 return ICE_ERR_PARAM;
1735 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1736 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1738 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1739 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1743 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1744 status = ice_flow_rem_prof_sync(hw, blk, p);
1750 ice_release_lock(&hw->fl_profs_locks[blk]);
1756 * ice_rem_rss_cfg_vsi_ctx - remove RSS configuration from VSI context
1757 * @hw: pointer to the hardware structure
1758 * @vsi_handle: software VSI handle
1759 * @prof: pointer to flow profile
1761 * Assumption: lock has already been acquired for RSS list
1764 ice_rem_rss_cfg_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1765 struct ice_flow_prof *prof)
1767 struct ice_rss_cfg *r, *tmp;
1769 /* Search for RSS hash fields associated to the VSI that match the
1770 * hash configurations associated to the flow profile. If found
1771 * remove from the RSS entry list of the VSI context and delete entry.
1773 LIST_FOR_EACH_ENTRY_SAFE(r, tmp,
1774 &hw->vsi_ctx[vsi_handle]->rss_list_head,
1775 ice_rss_cfg, l_entry) {
1776 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1777 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1778 LIST_DEL(&r->l_entry);
1786 * ice_add_rss_vsi_ctx - add RSS configuration to VSI context
1787 * @hw: pointer to the hardware structure
1788 * @vsi_handle: software VSI handle
1789 * @prof: pointer to flow profile
1791 * Assumption: lock has already been acquired for RSS list
1793 static enum ice_status
1794 ice_add_rss_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
1795 struct ice_flow_prof *prof)
1797 struct ice_rss_cfg *r, *rss_cfg;
1799 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
1800 ice_rss_cfg, l_entry)
1801 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1802 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs)
1805 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1807 return ICE_ERR_NO_MEMORY;
1809 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1810 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1811 LIST_ADD(&rss_cfg->l_entry, &hw->vsi_ctx[vsi_handle]->rss_list_head);
1816 #define ICE_FLOW_PROF_HASH_S 0
1817 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1818 #define ICE_FLOW_PROF_HDR_S 32
1819 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1821 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1822 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1823 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1826 * ice_add_rss_cfg_sync - add an RSS configuration
1827 * @hw: pointer to the hardware structure
1828 * @vsi_handle: software VSI handle
1829 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1830 * @addl_hdrs: protocol header fields
1832 * Assumption: lock has already been acquired for RSS list
1834 static enum ice_status
1835 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1838 const enum ice_block blk = ICE_BLK_RSS;
1839 struct ice_flow_prof *prof = NULL;
1840 struct ice_flow_seg_info *segs;
1841 enum ice_status status = ICE_SUCCESS;
1843 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1845 return ICE_ERR_NO_MEMORY;
1847 /* Construct the packet segment info from the hashed fields */
1848 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1852 /* Search for a flow profile that has matching headers, hash fields
1853 * and has the input VSI associated to it. If found, no further
1854 * operations required and exit.
1856 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1858 ICE_FLOW_FIND_PROF_CHK_FLDS |
1859 ICE_FLOW_FIND_PROF_CHK_VSI);
1863 /* Check if a flow profile exists with the same protocol headers and
1864 * associated with the input VSI. If so disasscociate the VSI from
1865 * this profile. The VSI will be added to a new profile created with
1866 * the protocol header and new hash field configuration.
1868 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1869 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1871 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1873 ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
1877 /* Remove profile if it has no VSIs associated */
1878 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1879 status = ice_flow_rem_prof_sync(hw, blk, prof);
1885 /* Search for a profile that has same match fields only. If this
1886 * exists then associate the VSI to this profile.
1888 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1890 ICE_FLOW_FIND_PROF_CHK_FLDS);
1892 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1894 status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1898 /* Create a new flow profile with generated profile and packet
1899 * segment information.
1901 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1902 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1903 segs, 1, NULL, 0, &prof);
1907 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1908 /* If association to a new flow profile failed then this profile can
1912 ice_flow_rem_prof_sync(hw, blk, prof);
1916 status = ice_add_rss_vsi_ctx(hw, vsi_handle, prof);
1924 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1925 * @hw: pointer to the hardware structure
1926 * @vsi_handle: software VSI handle
1927 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1928 * @addl_hdrs: protocol header fields
1930 * This function will generate a flow profile based on fields associated with
1931 * the input fields to hash on, the flow type and use the VSI number to add
1932 * a flow entry to the profile.
1935 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1938 enum ice_status status;
1940 if (hashed_flds == ICE_HASH_INVALID ||
1941 !ice_is_vsi_valid(hw, vsi_handle))
1942 return ICE_ERR_PARAM;
1944 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1945 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1946 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
1952 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1953 * @hw: pointer to the hardware structure
1954 * @vsi_handle: software VSI handle
1955 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1956 * @addl_hdrs: Protocol header fields within a packet segment
1958 * Assumption: lock has already been acquired for RSS list
1960 static enum ice_status
1961 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1964 const enum ice_block blk = ICE_BLK_RSS;
1965 struct ice_flow_seg_info *segs;
1966 struct ice_flow_prof *prof;
1967 enum ice_status status;
1969 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
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, hashed_flds, addl_hdrs);
1978 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1980 ICE_FLOW_FIND_PROF_CHK_FLDS);
1982 status = ICE_ERR_DOES_NOT_EXIST;
1986 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1990 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1991 status = ice_flow_rem_prof_sync(hw, blk, prof);
1993 ice_rem_rss_cfg_vsi_ctx(hw, vsi_handle, prof);
2001 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2002 * @hw: pointer to the hardware structure
2003 * @vsi_handle: software VSI handle
2004 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2005 * @addl_hdrs: Protocol header fields within a packet segment
2007 * This function will lookup the flow profile based on the input
2008 * hash field bitmap, iterate through the profile entry list of
2009 * that profile and find entry associated with input VSI to be
2010 * removed. Calls are made to underlying flow apis which will in
2011 * turn build or update buffers for RSS XLT1 section.
2014 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2017 enum ice_status status;
2019 if (hashed_flds == ICE_HASH_INVALID ||
2020 !ice_is_vsi_valid(hw, vsi_handle))
2021 return ICE_ERR_PARAM;
2023 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2024 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2025 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2031 * ice_replay_rss_cfg - remove RSS configurations associated with VSI
2032 * @hw: pointer to the hardware structure
2033 * @vsi_handle: software VSI handle
2035 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2037 enum ice_status status = ICE_SUCCESS;
2038 struct ice_rss_cfg *r;
2040 if (!ice_is_vsi_valid(hw, vsi_handle))
2041 return ICE_ERR_PARAM;
2043 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2044 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
2045 ice_rss_cfg, l_entry) {
2046 status = ice_add_rss_cfg_sync(hw, vsi_handle, r->hashed_flds,
2051 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2057 * ice_get_rss_cfg - returns hashed fields for the given header types
2058 * @hw: pointer to the hardware structure
2059 * @vsi_handle: software VSI handle
2060 * @hdrs: protocol header type
2062 * This function will return the match fields of the first instance of flow
2063 * profile having the given header types and containing input VSI
2065 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2067 struct ice_rss_cfg *r, *rss_cfg = NULL;
2069 /* verify if the protocol header is non zero and VSI is valid */
2070 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2071 return ICE_HASH_INVALID;
2073 ice_acquire_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2074 LIST_FOR_EACH_ENTRY(r, &hw->vsi_ctx[vsi_handle]->rss_list_head,
2075 ice_rss_cfg, l_entry)
2076 if (r->packet_hdr == hdrs) {
2080 ice_release_lock(&hw->vsi_ctx[vsi_handle]->rss_locks);
2082 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;