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_pkt_flags - Create an extr sequence entry for packet flags
500 * @hw: pointer to the HW struct
501 * @params: information about the flow to be processed
502 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
504 * This function will allocate an extraction sequence entries for a DWORD size
505 * chunk of the packet flags.
507 static enum ice_status
508 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
509 struct ice_flow_prof_params *params,
510 enum ice_flex_mdid_pkt_flags flags)
512 u8 fv_words = hw->blk[params->blk].es.fvw;
515 /* Make sure the number of extraction sequence entries required does not
516 * exceed the block's capacity.
518 if (params->es_cnt >= fv_words)
519 return ICE_ERR_MAX_LIMIT;
521 /* some blocks require a reversed field vector layout */
522 if (hw->blk[params->blk].es.reverse)
523 idx = fv_words - params->es_cnt - 1;
525 idx = params->es_cnt;
527 params->es[idx].prot_id = ICE_PROT_META_ID;
528 params->es[idx].off = flags;
535 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
536 * @hw: pointer to the HW struct
537 * @params: information about the flow to be processed
538 * @seg: packet segment index of the field to be extracted
539 * @fld: ID of field to be extracted
541 * This function determines the protocol ID, offset, and size of the given
542 * field. It then allocates one or more extraction sequence entries for the
543 * given field, and fill the entries with protocol ID and offset information.
545 static enum ice_status
546 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
547 u8 seg, enum ice_flow_field fld)
549 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
550 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
551 u8 fv_words = hw->blk[params->blk].es.fvw;
552 struct ice_flow_fld_info *flds;
553 u16 cnt, ese_bits, i;
557 flds = params->prof->segs[seg].fields;
560 case ICE_FLOW_FIELD_IDX_ETH_DA:
561 case ICE_FLOW_FIELD_IDX_ETH_SA:
562 case ICE_FLOW_FIELD_IDX_S_VLAN:
563 case ICE_FLOW_FIELD_IDX_C_VLAN:
564 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
566 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
567 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
569 case ICE_FLOW_FIELD_IDX_IP_DSCP:
570 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
571 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
573 case ICE_FLOW_FIELD_IDX_IP_TTL:
574 case ICE_FLOW_FIELD_IDX_IP_PROT:
575 /* Some fields are located at different offsets in IPv4 and
578 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
579 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
581 /* TTL and PROT share the same extraction seq. entry.
582 * Each is considered a sibling to the other in term
583 * sharing the same extraction sequence entry.
585 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
586 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
587 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
588 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
589 } else if (params->prof->segs[seg].hdrs &
590 ICE_FLOW_SEG_HDR_IPV6) {
591 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
593 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
594 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
595 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
596 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
599 case ICE_FLOW_FIELD_IDX_IPV4_SA:
600 case ICE_FLOW_FIELD_IDX_IPV4_DA:
601 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
603 case ICE_FLOW_FIELD_IDX_IPV6_SA:
604 case ICE_FLOW_FIELD_IDX_IPV6_DA:
605 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
607 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
608 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
609 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
610 prot_id = ICE_PROT_TCP_IL;
612 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
613 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
614 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
616 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
617 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
618 prot_id = ICE_PROT_SCTP_IL;
620 case ICE_FLOW_FIELD_IDX_ARP_SIP:
621 case ICE_FLOW_FIELD_IDX_ARP_DIP:
622 case ICE_FLOW_FIELD_IDX_ARP_SHA:
623 case ICE_FLOW_FIELD_IDX_ARP_DHA:
624 case ICE_FLOW_FIELD_IDX_ARP_OP:
625 prot_id = ICE_PROT_ARP_OF;
627 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
628 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
629 /* ICMP type and code share the same extraction seq. entry */
630 prot_id = (params->prof->segs[seg].hdrs &
631 ICE_FLOW_SEG_HDR_IPV4) ?
632 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
633 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
634 ICE_FLOW_FIELD_IDX_ICMP_CODE :
635 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
637 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
638 prot_id = ICE_PROT_GRE_OF;
641 return ICE_ERR_NOT_IMPL;
644 /* Each extraction sequence entry is a word in size, and extracts a
645 * word-aligned offset from a protocol header.
647 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * 8;
649 flds[fld].xtrct.prot_id = prot_id;
650 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
651 ICE_FLOW_FV_EXTRACT_SZ;
652 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
653 flds[fld].xtrct.idx = params->es_cnt;
655 /* Adjust the next field-entry index after accommodating the number of
656 * entries this field consumes
658 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
659 ice_flds_info[fld].size, ese_bits);
661 /* Fill in the extraction sequence entries needed for this field */
662 off = flds[fld].xtrct.off;
663 for (i = 0; i < cnt; i++) {
664 /* Only consume an extraction sequence entry if there is no
665 * sibling field associated with this field or the sibling entry
666 * already extracts the word shared with this field.
668 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
669 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
670 flds[sib].xtrct.off != off) {
673 /* Make sure the number of extraction sequence required
674 * does not exceed the block's capability
676 if (params->es_cnt >= fv_words)
677 return ICE_ERR_MAX_LIMIT;
679 /* some blocks require a reversed field vector layout */
680 if (hw->blk[params->blk].es.reverse)
681 idx = fv_words - params->es_cnt - 1;
683 idx = params->es_cnt;
685 params->es[idx].prot_id = prot_id;
686 params->es[idx].off = off;
690 off += ICE_FLOW_FV_EXTRACT_SZ;
697 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
698 * @hw: pointer to the HW struct
699 * @params: information about the flow to be processed
700 * @seg: index of packet segment whose raw fields are to be be extracted
702 static enum ice_status
703 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
709 if (!params->prof->segs[seg].raws_cnt)
712 if (params->prof->segs[seg].raws_cnt >
713 ARRAY_SIZE(params->prof->segs[seg].raws))
714 return ICE_ERR_MAX_LIMIT;
716 /* Offsets within the segment headers are not supported */
717 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
719 return ICE_ERR_PARAM;
721 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
722 struct ice_flow_seg_fld_raw *raw;
725 raw = ¶ms->prof->segs[seg].raws[i];
727 /* Only support matching raw fields in the payload */
728 if (raw->off < hdrs_sz)
729 return ICE_ERR_PARAM;
731 /* Convert the segment-relative offset into payload-relative
734 off = raw->off - hdrs_sz;
736 /* Storing extraction information */
737 raw->info.xtrct.prot_id = ICE_PROT_PAY;
738 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
739 ICE_FLOW_FV_EXTRACT_SZ;
740 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) * 8;
741 raw->info.xtrct.idx = params->es_cnt;
743 /* Determine the number of field vector entries this raw field
746 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
747 (raw->info.src.last * 8),
748 ICE_FLOW_FV_EXTRACT_SZ * 8);
749 off = raw->info.xtrct.off;
750 for (j = 0; j < cnt; j++) {
751 /* Make sure the number of extraction sequence required
752 * does not exceed the block's capability
754 if (params->es_cnt >= hw->blk[params->blk].es.count ||
755 params->es_cnt >= ICE_MAX_FV_WORDS)
756 return ICE_ERR_MAX_LIMIT;
758 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
759 params->es[params->es_cnt].off = off;
761 off += ICE_FLOW_FV_EXTRACT_SZ;
769 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
770 * @hw: pointer to the HW struct
771 * @params: information about the flow to be processed
773 * This function iterates through all matched fields in the given segments, and
774 * creates an extraction sequence for the fields.
776 static enum ice_status
777 ice_flow_create_xtrct_seq(struct ice_hw *hw,
778 struct ice_flow_prof_params *params)
780 enum ice_status status = ICE_SUCCESS;
783 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
786 if (params->blk == ICE_BLK_ACL)
787 ice_flow_xtract_pkt_flags(hw, params,
788 ICE_RX_MDID_PKT_FLAGS_15_0);
790 for (i = 0; i < params->prof->segs_cnt; i++) {
791 u64 match = params->prof->segs[i].match;
794 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
795 const u64 bit = BIT_ULL(j);
798 status = ice_flow_xtract_fld
799 (hw, params, i, (enum ice_flow_field)j);
806 /* Process raw matching bytes */
807 status = ice_flow_xtract_raws(hw, params, i);
816 * ice_flow_proc_segs - process all packet segments associated with a profile
817 * @hw: pointer to the HW struct
818 * @params: information about the flow to be processed
820 static enum ice_status
821 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
823 enum ice_status status;
825 status = ice_flow_proc_seg_hdrs(params);
829 status = ice_flow_create_xtrct_seq(hw, params);
833 switch (params->blk) {
835 /* Only header information is provided for RSS configuration.
836 * No further processing is needed.
838 status = ICE_SUCCESS;
841 status = ICE_SUCCESS;
845 return ICE_ERR_NOT_IMPL;
851 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
852 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
855 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
856 * @hw: pointer to the HW struct
857 * @blk: classification stage
858 * @dir: flow direction
859 * @segs: array of one or more packet segments that describe the flow
860 * @segs_cnt: number of packet segments provided
861 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
862 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
864 static struct ice_flow_prof *
865 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
866 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
867 u8 segs_cnt, u16 vsi_handle, u32 conds)
869 struct ice_flow_prof *p;
871 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
872 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
875 /* Check for profile-VSI association if specified */
876 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
877 ice_is_vsi_valid(hw, vsi_handle) &&
878 !ice_is_bit_set(p->vsis, vsi_handle))
881 /* Protocol headers must be checked. Matched fields are
882 * checked if specified.
884 for (i = 0; i < segs_cnt; i++)
885 if (segs[i].hdrs != p->segs[i].hdrs ||
886 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
887 segs[i].match != p->segs[i].match))
890 /* A match is found if all segments are matched */
900 * ice_flow_find_prof - Look up a profile matching headers and matched fields
901 * @hw: pointer to the HW struct
902 * @blk: classification stage
903 * @dir: flow direction
904 * @segs: array of one or more packet segments that describe the flow
905 * @segs_cnt: number of packet segments provided
908 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
909 struct ice_flow_seg_info *segs, u8 segs_cnt)
911 struct ice_flow_prof *p;
913 ice_acquire_lock(&hw->fl_profs_locks[blk]);
914 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
915 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
916 ice_release_lock(&hw->fl_profs_locks[blk]);
918 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
922 * ice_flow_find_prof_id - Look up a profile with given profile ID
923 * @hw: pointer to the HW struct
924 * @blk: classification stage
925 * @prof_id: unique ID to identify this flow profile
927 static struct ice_flow_prof *
928 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
930 struct ice_flow_prof *p;
932 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
933 if (p->id == prof_id)
941 * ice_flow_rem_entry_sync - Remove a flow entry
942 * @hw: pointer to the HW struct
943 * @entry: flow entry to be removed
945 static enum ice_status
946 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
949 return ICE_ERR_BAD_PTR;
951 LIST_DEL(&entry->l_entry);
954 ice_free(hw, entry->entry);
957 ice_free(hw, entry->acts);
968 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
969 * @hw: pointer to the HW struct
970 * @blk: classification stage
971 * @dir: flow direction
972 * @prof_id: unique ID to identify this flow profile
973 * @segs: array of one or more packet segments that describe the flow
974 * @segs_cnt: number of packet segments provided
975 * @acts: array of default actions
976 * @acts_cnt: number of default actions
977 * @prof: stores the returned flow profile added
979 * Assumption: the caller has acquired the lock to the profile list
981 static enum ice_status
982 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
983 enum ice_flow_dir dir, u64 prof_id,
984 struct ice_flow_seg_info *segs, u8 segs_cnt,
985 struct ice_flow_action *acts, u8 acts_cnt,
986 struct ice_flow_prof **prof)
988 struct ice_flow_prof_params params;
989 enum ice_status status = ICE_SUCCESS;
992 if (!prof || (acts_cnt && !acts))
993 return ICE_ERR_BAD_PTR;
995 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
996 params.prof = (struct ice_flow_prof *)
997 ice_malloc(hw, sizeof(*params.prof));
999 return ICE_ERR_NO_MEMORY;
1001 /* initialize extraction sequence to all invalid (0xff) */
1002 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1003 params.es[i].prot_id = ICE_PROT_INVALID;
1004 params.es[i].off = ICE_FV_OFFSET_INVAL;
1008 params.prof->id = prof_id;
1009 params.prof->dir = dir;
1010 params.prof->segs_cnt = segs_cnt;
1012 /* Make a copy of the segments that need to be persistent in the flow
1015 for (i = 0; i < segs_cnt; i++)
1016 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1017 ICE_NONDMA_TO_NONDMA);
1019 /* Make a copy of the actions that need to be persistent in the flow
1023 params.prof->acts = (struct ice_flow_action *)
1024 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1025 ICE_NONDMA_TO_NONDMA);
1027 if (!params.prof->acts) {
1028 status = ICE_ERR_NO_MEMORY;
1033 status = ice_flow_proc_segs(hw, ¶ms);
1035 ice_debug(hw, ICE_DBG_FLOW,
1036 "Error processing a flow's packet segments\n");
1040 /* Add a HW profile for this flow profile */
1041 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
1043 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1047 INIT_LIST_HEAD(¶ms.prof->entries);
1048 ice_init_lock(¶ms.prof->entries_lock);
1049 *prof = params.prof;
1053 if (params.prof->acts)
1054 ice_free(hw, params.prof->acts);
1055 ice_free(hw, params.prof);
1062 * ice_flow_rem_prof_sync - remove a flow profile
1063 * @hw: pointer to the hardware structure
1064 * @blk: classification stage
1065 * @prof: pointer to flow profile to remove
1067 * Assumption: the caller has acquired the lock to the profile list
1069 static enum ice_status
1070 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1071 struct ice_flow_prof *prof)
1073 enum ice_status status = ICE_SUCCESS;
1075 /* Remove all remaining flow entries before removing the flow profile */
1076 if (!LIST_EMPTY(&prof->entries)) {
1077 struct ice_flow_entry *e, *t;
1079 ice_acquire_lock(&prof->entries_lock);
1081 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1083 status = ice_flow_rem_entry_sync(hw, e);
1088 ice_release_lock(&prof->entries_lock);
1091 /* Remove all hardware profiles associated with this flow profile */
1092 status = ice_rem_prof(hw, blk, prof->id);
1094 LIST_DEL(&prof->l_entry);
1095 ice_destroy_lock(&prof->entries_lock);
1097 ice_free(hw, prof->acts);
1105 * ice_flow_assoc_prof - associate a VSI with a flow profile
1106 * @hw: pointer to the hardware structure
1107 * @blk: classification stage
1108 * @prof: pointer to flow profile
1109 * @vsi_handle: software VSI handle
1111 * Assumption: the caller has acquired the lock to the profile list
1112 * and the software VSI handle has been validated
1114 static enum ice_status
1115 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1116 struct ice_flow_prof *prof, u16 vsi_handle)
1118 enum ice_status status = ICE_SUCCESS;
1120 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1121 status = ice_add_prof_id_flow(hw, blk,
1122 ice_get_hw_vsi_num(hw,
1126 ice_set_bit(vsi_handle, prof->vsis);
1128 ice_debug(hw, ICE_DBG_FLOW,
1129 "HW profile add failed, %d\n",
1137 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1138 * @hw: pointer to the hardware structure
1139 * @blk: classification stage
1140 * @prof: pointer to flow profile
1141 * @vsi_handle: software VSI handle
1143 * Assumption: the caller has acquired the lock to the profile list
1144 * and the software VSI handle has been validated
1146 static enum ice_status
1147 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1148 struct ice_flow_prof *prof, u16 vsi_handle)
1150 enum ice_status status = ICE_SUCCESS;
1152 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1153 status = ice_rem_prof_id_flow(hw, blk,
1154 ice_get_hw_vsi_num(hw,
1158 ice_clear_bit(vsi_handle, prof->vsis);
1160 ice_debug(hw, ICE_DBG_FLOW,
1161 "HW profile remove failed, %d\n",
1169 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1170 * @hw: pointer to the HW struct
1171 * @blk: classification stage
1172 * @dir: flow direction
1173 * @prof_id: unique ID to identify this flow profile
1174 * @segs: array of one or more packet segments that describe the flow
1175 * @segs_cnt: number of packet segments provided
1176 * @acts: array of default actions
1177 * @acts_cnt: number of default actions
1178 * @prof: stores the returned flow profile added
1181 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1182 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1183 struct ice_flow_action *acts, u8 acts_cnt,
1184 struct ice_flow_prof **prof)
1186 enum ice_status status;
1188 if (segs_cnt > ICE_FLOW_SEG_MAX)
1189 return ICE_ERR_MAX_LIMIT;
1192 return ICE_ERR_PARAM;
1195 return ICE_ERR_BAD_PTR;
1197 status = ice_flow_val_hdrs(segs, segs_cnt);
1201 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1203 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1204 acts, acts_cnt, prof);
1206 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1208 ice_release_lock(&hw->fl_profs_locks[blk]);
1214 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1215 * @hw: pointer to the HW struct
1216 * @blk: the block for which the flow profile is to be removed
1217 * @prof_id: unique ID of the flow profile to be removed
1220 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1222 struct ice_flow_prof *prof;
1223 enum ice_status status;
1225 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1227 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1229 status = ICE_ERR_DOES_NOT_EXIST;
1233 /* prof becomes invalid after the call */
1234 status = ice_flow_rem_prof_sync(hw, blk, prof);
1237 ice_release_lock(&hw->fl_profs_locks[blk]);
1243 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1244 * @hw: pointer to the HW struct
1245 * @blk: classification stage
1246 * @prof_id: the profile ID handle
1247 * @hw_prof_id: pointer to variable to receive the HW profile ID
1250 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1253 struct ice_prof_map *map;
1255 map = ice_search_prof_id(hw, blk, prof_id);
1257 *hw_prof_id = map->prof_id;
1261 return ICE_ERR_DOES_NOT_EXIST;
1265 * ice_flow_find_entry - look for a flow entry using its unique ID
1266 * @hw: pointer to the HW struct
1267 * @blk: classification stage
1268 * @entry_id: unique ID to identify this flow entry
1270 * This function looks for the flow entry with the specified unique ID in all
1271 * flow profiles of the specified classification stage. If the entry is found,
1272 * and it returns the handle to the flow entry. Otherwise, it returns
1273 * ICE_FLOW_ENTRY_ID_INVAL.
1275 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1277 struct ice_flow_entry *found = NULL;
1278 struct ice_flow_prof *p;
1280 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1282 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1283 struct ice_flow_entry *e;
1285 ice_acquire_lock(&p->entries_lock);
1286 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1287 if (e->id == entry_id) {
1291 ice_release_lock(&p->entries_lock);
1297 ice_release_lock(&hw->fl_profs_locks[blk]);
1299 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1303 * ice_flow_add_entry - Add a flow entry
1304 * @hw: pointer to the HW struct
1305 * @blk: classification stage
1306 * @prof_id: ID of the profile to add a new flow entry to
1307 * @entry_id: unique ID to identify this flow entry
1308 * @vsi_handle: software VSI handle for the flow entry
1309 * @prio: priority of the flow entry
1310 * @data: pointer to a data buffer containing flow entry's match values/masks
1311 * @acts: arrays of actions to be performed on a match
1312 * @acts_cnt: number of actions
1313 * @entry_h: pointer to buffer that receives the new flow entry's handle
1316 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1317 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1318 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1321 struct ice_flow_prof *prof = NULL;
1322 struct ice_flow_entry *e = NULL;
1323 enum ice_status status = ICE_SUCCESS;
1325 if (acts_cnt && !acts)
1326 return ICE_ERR_PARAM;
1328 /* No flow entry data is expected for RSS */
1329 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1330 return ICE_ERR_BAD_PTR;
1332 if (!ice_is_vsi_valid(hw, vsi_handle))
1333 return ICE_ERR_PARAM;
1335 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1337 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1339 status = ICE_ERR_DOES_NOT_EXIST;
1341 /* Allocate memory for the entry being added and associate
1342 * the VSI to the found flow profile
1344 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1346 status = ICE_ERR_NO_MEMORY;
1348 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1351 ice_release_lock(&hw->fl_profs_locks[blk]);
1356 e->vsi_handle = vsi_handle;
1362 /* RSS will add only one entry per VSI per profile */
1369 status = ICE_ERR_NOT_IMPL;
1373 ice_acquire_lock(&prof->entries_lock);
1374 LIST_ADD(&e->l_entry, &prof->entries);
1375 ice_release_lock(&prof->entries_lock);
1377 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1382 ice_free(hw, e->entry);
1390 * ice_flow_rem_entry - Remove a flow entry
1391 * @hw: pointer to the HW struct
1392 * @entry_h: handle to the flow entry to be removed
1394 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1396 struct ice_flow_entry *entry;
1397 struct ice_flow_prof *prof;
1398 enum ice_status status;
1400 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1401 return ICE_ERR_PARAM;
1403 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1405 /* Retain the pointer to the flow profile as the entry will be freed */
1408 ice_acquire_lock(&prof->entries_lock);
1409 status = ice_flow_rem_entry_sync(hw, entry);
1410 ice_release_lock(&prof->entries_lock);
1416 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1417 * @seg: packet segment the field being set belongs to
1418 * @fld: field to be set
1419 * @type: type of the field
1420 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1421 * entry's input buffer
1422 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1424 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1425 * entry's input buffer
1427 * This helper function stores information of a field being matched, including
1428 * the type of the field and the locations of the value to match, the mask, and
1429 * and the upper-bound value in the start of the input buffer for a flow entry.
1430 * This function should only be used for fixed-size data structures.
1432 * This function also opportunistically determines the protocol headers to be
1433 * present based on the fields being set. Some fields cannot be used alone to
1434 * determine the protocol headers present. Sometimes, fields for particular
1435 * protocol headers are not matched. In those cases, the protocol headers
1436 * must be explicitly set.
1439 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1440 enum ice_flow_fld_match_type type, u16 val_loc,
1441 u16 mask_loc, u16 last_loc)
1443 u64 bit = BIT_ULL(fld);
1446 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1449 seg->fields[fld].type = type;
1450 seg->fields[fld].src.val = val_loc;
1451 seg->fields[fld].src.mask = mask_loc;
1452 seg->fields[fld].src.last = last_loc;
1454 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1458 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1459 * @seg: packet segment the field being set belongs to
1460 * @fld: field to be set
1461 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1462 * entry's input buffer
1463 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1465 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1466 * entry's input buffer
1467 * @range: indicate if field being matched is to be in a range
1469 * This function specifies the locations, in the form of byte offsets from the
1470 * start of the input buffer for a flow entry, from where the value to match,
1471 * the mask value, and upper value can be extracted. These locations are then
1472 * stored in the flow profile. When adding a flow entry associated with the
1473 * flow profile, these locations will be used to quickly extract the values and
1474 * create the content of a match entry. This function should only be used for
1475 * fixed-size data structures.
1478 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1479 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1481 enum ice_flow_fld_match_type t = range ?
1482 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1484 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1488 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1489 * @seg: packet segment the field being set belongs to
1490 * @fld: field to be set
1491 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1492 * entry's input buffer
1493 * @pref_loc: location of prefix value from entry's input buffer
1494 * @pref_sz: size of the location holding the prefix value
1496 * This function specifies the locations, in the form of byte offsets from the
1497 * start of the input buffer for a flow entry, from where the value to match
1498 * and the IPv4 prefix value can be extracted. These locations are then stored
1499 * in the flow profile. When adding flow entries to the associated flow profile,
1500 * these locations can be used to quickly extract the values to create the
1501 * content of a match entry. This function should only be used for fixed-size
1505 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1506 u16 val_loc, u16 pref_loc, u8 pref_sz)
1508 /* For this type of field, the "mask" location is for the prefix value's
1509 * location and the "last" location is for the size of the location of
1512 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1513 pref_loc, (u16)pref_sz);
1517 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1518 * @seg: packet segment the field being set belongs to
1519 * @off: offset of the raw field from the beginning of the segment in bytes
1520 * @len: length of the raw pattern to be matched
1521 * @val_loc: location of the value to match from entry's input buffer
1522 * @mask_loc: location of mask value from entry's input buffer
1524 * This function specifies the offset of the raw field to be match from the
1525 * beginning of the specified packet segment, and the locations, in the form of
1526 * byte offsets from the start of the input buffer for a flow entry, from where
1527 * the value to match and the mask value to be extracted. These locations are
1528 * then stored in the flow profile. When adding flow entries to the associated
1529 * flow profile, these locations can be used to quickly extract the values to
1530 * create the content of a match entry. This function should only be used for
1531 * fixed-size data structures.
1534 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1535 u16 val_loc, u16 mask_loc)
1537 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1538 seg->raws[seg->raws_cnt].off = off;
1539 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1540 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1541 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1542 /* The "last" field is used to store the length of the field */
1543 seg->raws[seg->raws_cnt].info.src.last = len;
1546 /* Overflows of "raws" will be handled as an error condition later in
1547 * the flow when this information is processed.
1552 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1553 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1555 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1556 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1557 ICE_FLOW_SEG_HDR_SCTP)
1559 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1560 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1561 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1564 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1565 * @segs: pointer to the flow field segment(s)
1566 * @hash_fields: fields to be hashed on for the segment(s)
1567 * @flow_hdr: protocol header fields within a packet segment
1569 * Helper function to extract fields from hash bitmap and use flow
1570 * header value to set flow field segment for further use in flow
1571 * profile entry or removal.
1573 static enum ice_status
1574 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1577 u64 val = hash_fields;
1580 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1581 u64 bit = BIT_ULL(i);
1584 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1585 ICE_FLOW_FLD_OFF_INVAL,
1586 ICE_FLOW_FLD_OFF_INVAL,
1587 ICE_FLOW_FLD_OFF_INVAL, false);
1591 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1593 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1594 return ICE_ERR_PARAM;
1596 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1597 if (!ice_is_pow2(val))
1600 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1601 if (val && !ice_is_pow2(val))
1608 * ice_rem_vsi_rss_list - remove VSI from RSS list
1609 * @hw: pointer to the hardware structure
1610 * @vsi_handle: software VSI handle
1612 * Remove the VSI from all RSS configurations in the list.
1614 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1616 struct ice_rss_cfg *r, *tmp;
1618 if (LIST_EMPTY(&hw->rss_list_head))
1621 ice_acquire_lock(&hw->rss_locks);
1622 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1623 ice_rss_cfg, l_entry) {
1624 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1625 ice_clear_bit(vsi_handle, r->vsis);
1627 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1628 LIST_DEL(&r->l_entry);
1633 ice_release_lock(&hw->rss_locks);
1637 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1638 * @hw: pointer to the hardware structure
1639 * @vsi_handle: software VSI handle
1641 * This function will iterate through all flow profiles and disassociate
1642 * the VSI from that profile. If the flow profile has no VSIs it will
1645 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1647 const enum ice_block blk = ICE_BLK_RSS;
1648 struct ice_flow_prof *p, *t;
1649 enum ice_status status = ICE_SUCCESS;
1651 if (!ice_is_vsi_valid(hw, vsi_handle))
1652 return ICE_ERR_PARAM;
1654 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1655 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1657 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1658 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1662 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1663 status = ice_flow_rem_prof_sync(hw, blk, p);
1669 ice_release_lock(&hw->fl_profs_locks[blk]);
1675 * ice_rem_rss_list - remove RSS configuration from list
1676 * @hw: pointer to the hardware structure
1677 * @vsi_handle: software VSI handle
1678 * @prof: pointer to flow profile
1680 * Assumption: lock has already been acquired for RSS list
1683 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1685 struct ice_rss_cfg *r, *tmp;
1687 /* Search for RSS hash fields associated to the VSI that match the
1688 * hash configurations associated to the flow profile. If found
1689 * remove from the RSS entry list of the VSI context and delete entry.
1691 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1692 ice_rss_cfg, l_entry) {
1693 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1694 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1695 ice_clear_bit(vsi_handle, r->vsis);
1696 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1697 LIST_DEL(&r->l_entry);
1706 * ice_add_rss_list - add RSS configuration to list
1707 * @hw: pointer to the hardware structure
1708 * @vsi_handle: software VSI handle
1709 * @prof: pointer to flow profile
1711 * Assumption: lock has already been acquired for RSS list
1713 static enum ice_status
1714 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1716 struct ice_rss_cfg *r, *rss_cfg;
1718 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1719 ice_rss_cfg, l_entry)
1720 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1721 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1722 ice_set_bit(vsi_handle, r->vsis);
1726 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1728 return ICE_ERR_NO_MEMORY;
1730 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1731 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1732 ice_set_bit(vsi_handle, rss_cfg->vsis);
1734 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1739 #define ICE_FLOW_PROF_HASH_S 0
1740 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1741 #define ICE_FLOW_PROF_HDR_S 32
1742 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1744 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1745 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1746 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1749 * ice_add_rss_cfg_sync - add an RSS configuration
1750 * @hw: pointer to the hardware structure
1751 * @vsi_handle: software VSI handle
1752 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1753 * @addl_hdrs: protocol header fields
1755 * Assumption: lock has already been acquired for RSS list
1757 static enum ice_status
1758 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1761 const enum ice_block blk = ICE_BLK_RSS;
1762 struct ice_flow_prof *prof = NULL;
1763 struct ice_flow_seg_info *segs;
1764 enum ice_status status = ICE_SUCCESS;
1766 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1768 return ICE_ERR_NO_MEMORY;
1770 /* Construct the packet segment info from the hashed fields */
1771 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1775 /* Search for a flow profile that has matching headers, hash fields
1776 * and has the input VSI associated to it. If found, no further
1777 * operations required and exit.
1779 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1781 ICE_FLOW_FIND_PROF_CHK_FLDS |
1782 ICE_FLOW_FIND_PROF_CHK_VSI);
1786 /* Check if a flow profile exists with the same protocol headers and
1787 * associated with the input VSI. If so disasscociate the VSI from
1788 * this profile. The VSI will be added to a new profile created with
1789 * the protocol header and new hash field configuration.
1791 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1792 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1794 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1796 ice_rem_rss_list(hw, vsi_handle, prof);
1800 /* Remove profile if it has no VSIs associated */
1801 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1802 status = ice_flow_rem_prof_sync(hw, blk, prof);
1808 /* Search for a profile that has same match fields only. If this
1809 * exists then associate the VSI to this profile.
1811 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1813 ICE_FLOW_FIND_PROF_CHK_FLDS);
1815 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1817 status = ice_add_rss_list(hw, vsi_handle, prof);
1821 /* Create a new flow profile with generated profile and packet
1822 * segment information.
1824 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1825 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1826 segs, 1, NULL, 0, &prof);
1830 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1831 /* If association to a new flow profile failed then this profile can
1835 ice_flow_rem_prof_sync(hw, blk, prof);
1839 status = ice_add_rss_list(hw, vsi_handle, prof);
1847 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1848 * @hw: pointer to the hardware structure
1849 * @vsi_handle: software VSI handle
1850 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1851 * @addl_hdrs: protocol header fields
1853 * This function will generate a flow profile based on fields associated with
1854 * the input fields to hash on, the flow type and use the VSI number to add
1855 * a flow entry to the profile.
1858 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1861 enum ice_status status;
1863 if (hashed_flds == ICE_HASH_INVALID ||
1864 !ice_is_vsi_valid(hw, vsi_handle))
1865 return ICE_ERR_PARAM;
1867 ice_acquire_lock(&hw->rss_locks);
1868 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1869 ice_release_lock(&hw->rss_locks);
1875 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1876 * @hw: pointer to the hardware structure
1877 * @vsi_handle: software VSI handle
1878 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1879 * @addl_hdrs: Protocol header fields within a packet segment
1881 * Assumption: lock has already been acquired for RSS list
1883 static enum ice_status
1884 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1887 const enum ice_block blk = ICE_BLK_RSS;
1888 struct ice_flow_seg_info *segs;
1889 struct ice_flow_prof *prof;
1890 enum ice_status status;
1892 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1894 return ICE_ERR_NO_MEMORY;
1896 /* Construct the packet segment info from the hashed fields */
1897 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1901 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1903 ICE_FLOW_FIND_PROF_CHK_FLDS);
1905 status = ICE_ERR_DOES_NOT_EXIST;
1909 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1913 /* Remove RSS configuration from VSI context before deleting
1916 ice_rem_rss_list(hw, vsi_handle, prof);
1918 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1919 status = ice_flow_rem_prof_sync(hw, blk, prof);
1926 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1927 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1928 * convert its values to their appropriate flow L3, L4 values.
1930 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1931 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1932 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1933 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1934 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1935 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1936 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1937 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1938 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1939 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1940 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1941 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1942 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1944 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1945 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1946 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1947 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1948 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1949 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1950 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1951 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1952 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1953 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1954 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1955 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1956 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1958 #define ICE_FLOW_MAX_CFG 10
1961 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1962 * @hw: pointer to the hardware structure
1963 * @vsi_handle: software VSI handle
1964 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1966 * This function will take the hash bitmap provided by the AVF driver via a
1967 * message, convert it to ICE-compatible values, and configure RSS flow
1971 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1973 enum ice_status status = ICE_SUCCESS;
1976 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1977 !ice_is_vsi_valid(hw, vsi_handle))
1978 return ICE_ERR_PARAM;
1980 /* Make sure no unsupported bits are specified */
1981 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1982 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1985 hash_flds = avf_hash;
1987 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1988 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1989 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1991 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1992 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1994 /* Create the corresponding RSS configuration for each valid hash bit */
1996 u64 rss_hash = ICE_HASH_INVALID;
1998 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1999 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2000 rss_hash = ICE_FLOW_HASH_IPV4;
2001 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2002 } else if (hash_flds &
2003 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2004 rss_hash = ICE_FLOW_HASH_IPV4 |
2005 ICE_FLOW_HASH_TCP_PORT;
2006 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2007 } else if (hash_flds &
2008 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2009 rss_hash = ICE_FLOW_HASH_IPV4 |
2010 ICE_FLOW_HASH_UDP_PORT;
2011 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2012 } else if (hash_flds &
2013 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2014 rss_hash = ICE_FLOW_HASH_IPV4 |
2015 ICE_FLOW_HASH_SCTP_PORT;
2017 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2019 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2020 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2021 rss_hash = ICE_FLOW_HASH_IPV6;
2022 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2023 } else if (hash_flds &
2024 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2025 rss_hash = ICE_FLOW_HASH_IPV6 |
2026 ICE_FLOW_HASH_TCP_PORT;
2027 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2028 } else if (hash_flds &
2029 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2030 rss_hash = ICE_FLOW_HASH_IPV6 |
2031 ICE_FLOW_HASH_UDP_PORT;
2032 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2033 } else if (hash_flds &
2034 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2035 rss_hash = ICE_FLOW_HASH_IPV6 |
2036 ICE_FLOW_HASH_SCTP_PORT;
2038 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2042 if (rss_hash == ICE_HASH_INVALID)
2043 return ICE_ERR_OUT_OF_RANGE;
2045 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2046 ICE_FLOW_SEG_HDR_NONE);
2055 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2056 * @hw: pointer to the hardware structure
2057 * @vsi_handle: software VSI handle
2058 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2059 * @addl_hdrs: Protocol header fields within a packet segment
2061 * This function will lookup the flow profile based on the input
2062 * hash field bitmap, iterate through the profile entry list of
2063 * that profile and find entry associated with input VSI to be
2064 * removed. Calls are made to underlying flow apis which will in
2065 * turn build or update buffers for RSS XLT1 section.
2068 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2071 enum ice_status status;
2073 if (hashed_flds == ICE_HASH_INVALID ||
2074 !ice_is_vsi_valid(hw, vsi_handle))
2075 return ICE_ERR_PARAM;
2077 ice_acquire_lock(&hw->rss_locks);
2078 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2079 ice_release_lock(&hw->rss_locks);
2085 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2086 * @hw: pointer to the hardware structure
2087 * @vsi_handle: software VSI handle
2089 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2091 enum ice_status status = ICE_SUCCESS;
2092 struct ice_rss_cfg *r;
2094 if (!ice_is_vsi_valid(hw, vsi_handle))
2095 return ICE_ERR_PARAM;
2097 ice_acquire_lock(&hw->rss_locks);
2098 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2099 ice_rss_cfg, l_entry) {
2100 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2101 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2108 ice_release_lock(&hw->rss_locks);
2114 * ice_get_rss_cfg - returns hashed fields for the given header types
2115 * @hw: pointer to the hardware structure
2116 * @vsi_handle: software VSI handle
2117 * @hdrs: protocol header type
2119 * This function will return the match fields of the first instance of flow
2120 * profile having the given header types and containing input VSI
2122 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2124 struct ice_rss_cfg *r, *rss_cfg = NULL;
2126 /* verify if the protocol header is non zero and VSI is valid */
2127 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2128 return ICE_HASH_INVALID;
2130 ice_acquire_lock(&hw->rss_locks);
2131 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2132 ice_rss_cfg, l_entry)
2133 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2134 r->packet_hdr == hdrs) {
2138 ice_release_lock(&hw->rss_locks);
2140 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;