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) * BITS_PER_BYTE)
30 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
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 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
41 .off = _offset_bytes * BITS_PER_BYTE, \
42 .size = _size_bytes * BITS_PER_BYTE, \
45 /* Table containing properties of supported protocol header fields */
47 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
49 /* ICE_FLOW_FIELD_IDX_ETH_DA */
50 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
51 /* ICE_FLOW_FIELD_IDX_ETH_SA */
52 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
53 /* ICE_FLOW_FIELD_IDX_S_VLAN */
54 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
55 /* ICE_FLOW_FIELD_IDX_C_VLAN */
56 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
57 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
58 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
60 /* ICE_FLOW_FIELD_IDX_IP_DSCP */
61 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
62 /* ICE_FLOW_FIELD_IDX_IP_TTL */
63 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
64 /* ICE_FLOW_FIELD_IDX_IP_PROT */
65 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
66 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
68 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
71 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
72 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
73 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
74 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
76 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
77 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
78 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
79 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
80 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
81 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
82 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
83 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
84 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
85 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
86 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
87 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
88 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
89 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
91 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
93 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
95 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
97 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
99 /* ICE_FLOW_FIELD_IDX_ARP_OP */
100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
102 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
104 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
105 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
107 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
108 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
111 /* Bitmaps indicating relevant packet types for a particular protocol header
113 * Packet types for packets with an Outer/First/Single MAC header
115 static const u32 ice_ptypes_mac_ofos[] = {
116 0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
117 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
118 0x000B0F0F, 0x00000000, 0x00000000, 0x00000000,
119 0x00000000, 0x00000000, 0x00000000, 0x00000000,
120 0x00000000, 0x00000000, 0x00000000, 0x00000000,
121 0x00000000, 0x00000000, 0x00000000, 0x00000000,
122 0x00000000, 0x00000000, 0x00000000, 0x00000000,
123 0x00000000, 0x00000000, 0x00000000, 0x00000000,
126 /* Packet types for packets with an Innermost/Last MAC VLAN header */
127 static const u32 ice_ptypes_macvlan_il[] = {
128 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
129 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
130 0x00000000, 0x00000000, 0x00000000, 0x00000000,
131 0x00000000, 0x00000000, 0x00000000, 0x00000000,
132 0x00000000, 0x00000000, 0x00000000, 0x00000000,
133 0x00000000, 0x00000000, 0x00000000, 0x00000000,
134 0x00000000, 0x00000000, 0x00000000, 0x00000000,
135 0x00000000, 0x00000000, 0x00000000, 0x00000000,
138 /* Packet types for packets with an Outer/First/Single IPv4 header */
139 static const u32 ice_ptypes_ipv4_ofos[] = {
140 0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
141 0x00000000, 0x00000000, 0x00000000, 0x00000000,
142 0x0003000F, 0x00000000, 0x00000000, 0x00000000,
143 0x00000000, 0x00000000, 0x00000000, 0x00000000,
144 0x00000000, 0x00000000, 0x00000000, 0x00000000,
145 0x00000000, 0x00000000, 0x00000000, 0x00000000,
146 0x00000000, 0x00000000, 0x00000000, 0x00000000,
147 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 /* Packet types for packets with an Innermost/Last IPv4 header */
151 static const u32 ice_ptypes_ipv4_il[] = {
152 0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
153 0x0007700E, 0x00000000, 0x00000000, 0x00000000,
154 0x00000000, 0x00000000, 0x00000000, 0x00000000,
155 0x00000000, 0x00000000, 0x00000000, 0x00000000,
156 0x00000000, 0x00000000, 0x00000000, 0x00000000,
157 0x00000000, 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 /* Packet types for packets with an Outer/First/Single IPv6 header */
163 static const u32 ice_ptypes_ipv6_ofos[] = {
164 0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
165 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
166 0x00080F00, 0x00000000, 0x00000000, 0x00000000,
167 0x00000000, 0x00000000, 0x00000000, 0x00000000,
168 0x00000000, 0x00000000, 0x00000000, 0x00000000,
169 0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 0x00000000, 0x00000000, 0x00000000, 0x00000000,
171 0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 /* Packet types for packets with an Innermost/Last IPv6 header */
175 static const u32 ice_ptypes_ipv6_il[] = {
176 0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
177 0x03B80770, 0x00000000, 0x00000000, 0x00000000,
178 0x00000000, 0x00000000, 0x00000000, 0x00000000,
179 0x00000000, 0x00000000, 0x00000000, 0x00000000,
180 0x00000000, 0x00000000, 0x00000000, 0x00000000,
181 0x00000000, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 /* Packet types for packets with an Outermost/First ARP header */
187 static const u32 ice_ptypes_arp_of[] = {
188 0x00000800, 0x00000000, 0x00000000, 0x00000000,
189 0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 0x00000000, 0x00000000, 0x00000000, 0x00000000,
191 0x00000000, 0x00000000, 0x00000000, 0x00000000,
192 0x00000000, 0x00000000, 0x00000000, 0x00000000,
193 0x00000000, 0x00000000, 0x00000000, 0x00000000,
194 0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 /* UDP Packet types for non-tunneled packets or tunneled
199 * packets with inner UDP.
201 static const u32 ice_ptypes_udp_il[] = {
202 0x81000000, 0x20204040, 0x04081010, 0x80810102,
203 0x00204040, 0x00000000, 0x00000000, 0x00000000,
204 0x00000000, 0x00000000, 0x00000000, 0x00000000,
205 0x00000000, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x00000000, 0x00000000,
207 0x00000000, 0x00000000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 0x00000000, 0x00000000, 0x00000000, 0x00000000,
212 /* Packet types for packets with an Innermost/Last TCP header */
213 static const u32 ice_ptypes_tcp_il[] = {
214 0x04000000, 0x80810102, 0x10204040, 0x42040408,
215 0x00810102, 0x00000000, 0x00000000, 0x00000000,
216 0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
220 0x00000000, 0x00000000, 0x00000000, 0x00000000,
221 0x00000000, 0x00000000, 0x00000000, 0x00000000,
224 /* Packet types for packets with an Innermost/Last SCTP header */
225 static const u32 ice_ptypes_sctp_il[] = {
226 0x08000000, 0x01020204, 0x20408081, 0x04080810,
227 0x01020204, 0x00000000, 0x00000000, 0x00000000,
228 0x00000000, 0x00000000, 0x00000000, 0x00000000,
229 0x00000000, 0x00000000, 0x00000000, 0x00000000,
230 0x00000000, 0x00000000, 0x00000000, 0x00000000,
231 0x00000000, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 0x00000000, 0x00000000, 0x00000000,
233 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 /* Packet types for packets with an Outermost/First ICMP header */
237 static const u32 ice_ptypes_icmp_of[] = {
238 0x10000000, 0x00000000, 0x00000000, 0x00000000,
239 0x00000000, 0x00000000, 0x00000000, 0x00000000,
240 0x00000000, 0x00000000, 0x00000000, 0x00000000,
241 0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 /* Packet types for packets with an Innermost/Last ICMP header */
249 static const u32 ice_ptypes_icmp_il[] = {
250 0x00000000, 0x02040408, 0x40810102, 0x08101020,
251 0x02040408, 0x00000000, 0x00000000, 0x00000000,
252 0x00000000, 0x00000000, 0x00000000, 0x00000000,
253 0x00000000, 0x00000000, 0x00000000, 0x00000000,
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 /* Packet types for packets with an Outermost/First GRE header */
261 static const u32 ice_ptypes_gre_of[] = {
262 0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
263 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
264 0x00000000, 0x00000000, 0x00000000, 0x00000000,
265 0x00000000, 0x00000000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 /* Packet types for packets with an Innermost/Last MAC header */
273 static const u32 ice_ptypes_mac_il[] = {
274 0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
275 0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
276 0x00000000, 0x00000000, 0x00000000, 0x00000000,
277 0x00000000, 0x00000000, 0x00000000, 0x00000000,
278 0x00000000, 0x00000000, 0x00000000, 0x00000000,
279 0x00000000, 0x00000000, 0x00000000, 0x00000000,
280 0x00000000, 0x00000000, 0x00000000, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 /* Manage parameters and info. used during the creation of a flow profile */
285 struct ice_flow_prof_params {
287 u16 entry_length; /* # of bytes formatted entry will require */
289 struct ice_flow_prof *prof;
291 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
292 * This will give us the direction flags.
294 struct ice_fv_word es[ICE_MAX_FV_WORDS];
296 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
300 * ice_is_pow2 - check if integer value is a power of 2
301 * @val: unsigned integer to be validated
303 static bool ice_is_pow2(u64 val)
305 return (val && !(val & (val - 1)));
308 #define ICE_FLOW_SEG_HDRS_L2_MASK \
309 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
310 #define ICE_FLOW_SEG_HDRS_L3_MASK \
311 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
312 #define ICE_FLOW_SEG_HDRS_L4_MASK \
313 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
314 ICE_FLOW_SEG_HDR_SCTP)
317 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
318 * @segs: array of one or more packet segments that describe the flow
319 * @segs_cnt: number of packet segments provided
321 static enum ice_status
322 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
324 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
325 ICE_FLOW_SEG_HDRS_L3_MASK |
326 ICE_FLOW_SEG_HDRS_L4_MASK);
329 for (i = 0; i < segs_cnt; i++) {
330 /* No header specified */
331 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
332 return ICE_ERR_PARAM;
334 /* Multiple L3 headers */
335 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
336 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
337 return ICE_ERR_PARAM;
339 /* Multiple L4 headers */
340 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
341 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
342 return ICE_ERR_PARAM;
348 /* Sizes of fixed known protocol headers without header options */
349 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
350 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
351 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
352 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
353 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
354 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
355 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
356 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
357 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
360 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
361 * @params: information about the flow to be processed
362 * @seg: index of packet segment whose header size is to be determined
364 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
369 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
370 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
373 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
374 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
375 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
376 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
377 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
378 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
379 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
380 /* A L3 header is required if L4 is specified */
384 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
385 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
386 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
387 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
388 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
389 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
390 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
391 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
397 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
398 * @params: information about the flow to be processed
400 * This function identifies the packet types associated with the protocol
401 * headers being present in packet segments of the specified flow profile.
403 static enum ice_status
404 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
406 struct ice_flow_prof *prof;
409 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
414 for (i = 0; i < params->prof->segs_cnt; i++) {
415 const ice_bitmap_t *src;
418 hdrs = prof->segs[i].hdrs;
420 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
421 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
422 (const ice_bitmap_t *)ice_ptypes_mac_il;
423 ice_and_bitmap(params->ptypes, params->ptypes, src,
425 hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
428 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
429 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
430 ice_and_bitmap(params->ptypes, params->ptypes, src,
432 hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
435 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
436 ice_and_bitmap(params->ptypes, params->ptypes,
437 (const ice_bitmap_t *)ice_ptypes_arp_of,
439 hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
442 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
443 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
444 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
445 ice_and_bitmap(params->ptypes, params->ptypes, src,
447 hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
448 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
449 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
450 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
451 ice_and_bitmap(params->ptypes, params->ptypes, src,
453 hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
456 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
457 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
458 (const ice_bitmap_t *)ice_ptypes_icmp_il;
459 ice_and_bitmap(params->ptypes, params->ptypes, src,
461 hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
462 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
463 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
464 ice_and_bitmap(params->ptypes, params->ptypes, src,
466 hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
467 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
468 ice_and_bitmap(params->ptypes, params->ptypes,
469 (const ice_bitmap_t *)ice_ptypes_tcp_il,
471 hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
472 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
473 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
474 ice_and_bitmap(params->ptypes, params->ptypes, src,
476 hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
477 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
479 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
480 ice_and_bitmap(params->ptypes, params->ptypes,
481 src, ICE_FLOW_PTYPE_MAX);
483 hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
491 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
492 * @hw: pointer to the HW struct
493 * @params: information about the flow to be processed
494 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
496 * This function will allocate an extraction sequence entries for a DWORD size
497 * chunk of the packet flags.
499 static enum ice_status
500 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
501 struct ice_flow_prof_params *params,
502 enum ice_flex_mdid_pkt_flags flags)
504 u8 fv_words = hw->blk[params->blk].es.fvw;
507 /* Make sure the number of extraction sequence entries required does not
508 * exceed the block's capacity.
510 if (params->es_cnt >= fv_words)
511 return ICE_ERR_MAX_LIMIT;
513 /* some blocks require a reversed field vector layout */
514 if (hw->blk[params->blk].es.reverse)
515 idx = fv_words - params->es_cnt - 1;
517 idx = params->es_cnt;
519 params->es[idx].prot_id = ICE_PROT_META_ID;
520 params->es[idx].off = flags;
527 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
528 * @hw: pointer to the HW struct
529 * @params: information about the flow to be processed
530 * @seg: packet segment index of the field to be extracted
531 * @fld: ID of field to be extracted
533 * This function determines the protocol ID, offset, and size of the given
534 * field. It then allocates one or more extraction sequence entries for the
535 * given field, and fill the entries with protocol ID and offset information.
537 static enum ice_status
538 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
539 u8 seg, enum ice_flow_field fld)
541 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
542 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
543 u8 fv_words = hw->blk[params->blk].es.fvw;
544 struct ice_flow_fld_info *flds;
545 u16 cnt, ese_bits, i;
549 flds = params->prof->segs[seg].fields;
552 case ICE_FLOW_FIELD_IDX_ETH_DA:
553 case ICE_FLOW_FIELD_IDX_ETH_SA:
554 case ICE_FLOW_FIELD_IDX_S_VLAN:
555 case ICE_FLOW_FIELD_IDX_C_VLAN:
556 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
558 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
559 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
561 case ICE_FLOW_FIELD_IDX_IP_DSCP:
562 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
563 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
565 case ICE_FLOW_FIELD_IDX_IP_TTL:
566 case ICE_FLOW_FIELD_IDX_IP_PROT:
567 /* Some fields are located at different offsets in IPv4 and
570 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
571 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
573 /* TTL and PROT share the same extraction seq. entry.
574 * Each is considered a sibling to the other in term
575 * sharing the same extraction sequence entry.
577 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
578 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
579 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
580 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
581 } else if (params->prof->segs[seg].hdrs &
582 ICE_FLOW_SEG_HDR_IPV6) {
583 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
585 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
586 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
587 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
588 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
591 case ICE_FLOW_FIELD_IDX_IPV4_SA:
592 case ICE_FLOW_FIELD_IDX_IPV4_DA:
593 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
595 case ICE_FLOW_FIELD_IDX_IPV6_SA:
596 case ICE_FLOW_FIELD_IDX_IPV6_DA:
597 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
599 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
600 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
601 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
602 prot_id = ICE_PROT_TCP_IL;
604 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
605 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
606 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
608 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
609 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
610 prot_id = ICE_PROT_SCTP_IL;
612 case ICE_FLOW_FIELD_IDX_ARP_SIP:
613 case ICE_FLOW_FIELD_IDX_ARP_DIP:
614 case ICE_FLOW_FIELD_IDX_ARP_SHA:
615 case ICE_FLOW_FIELD_IDX_ARP_DHA:
616 case ICE_FLOW_FIELD_IDX_ARP_OP:
617 prot_id = ICE_PROT_ARP_OF;
619 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
620 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
621 /* ICMP type and code share the same extraction seq. entry */
622 prot_id = (params->prof->segs[seg].hdrs &
623 ICE_FLOW_SEG_HDR_IPV4) ?
624 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
625 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
626 ICE_FLOW_FIELD_IDX_ICMP_CODE :
627 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
629 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
630 prot_id = ICE_PROT_GRE_OF;
633 return ICE_ERR_NOT_IMPL;
636 /* Each extraction sequence entry is a word in size, and extracts a
637 * word-aligned offset from a protocol header.
639 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
641 flds[fld].xtrct.prot_id = prot_id;
642 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
643 ICE_FLOW_FV_EXTRACT_SZ;
644 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
645 flds[fld].xtrct.idx = params->es_cnt;
647 /* Adjust the next field-entry index after accommodating the number of
648 * entries this field consumes
650 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
651 ice_flds_info[fld].size, ese_bits);
653 /* Fill in the extraction sequence entries needed for this field */
654 off = flds[fld].xtrct.off;
655 for (i = 0; i < cnt; i++) {
656 /* Only consume an extraction sequence entry if there is no
657 * sibling field associated with this field or the sibling entry
658 * already extracts the word shared with this field.
660 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
661 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
662 flds[sib].xtrct.off != off) {
665 /* Make sure the number of extraction sequence required
666 * does not exceed the block's capability
668 if (params->es_cnt >= fv_words)
669 return ICE_ERR_MAX_LIMIT;
671 /* some blocks require a reversed field vector layout */
672 if (hw->blk[params->blk].es.reverse)
673 idx = fv_words - params->es_cnt - 1;
675 idx = params->es_cnt;
677 params->es[idx].prot_id = prot_id;
678 params->es[idx].off = off;
682 off += ICE_FLOW_FV_EXTRACT_SZ;
689 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
690 * @hw: pointer to the HW struct
691 * @params: information about the flow to be processed
692 * @seg: index of packet segment whose raw fields are to be be extracted
694 static enum ice_status
695 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
701 if (!params->prof->segs[seg].raws_cnt)
704 if (params->prof->segs[seg].raws_cnt >
705 ARRAY_SIZE(params->prof->segs[seg].raws))
706 return ICE_ERR_MAX_LIMIT;
708 /* Offsets within the segment headers are not supported */
709 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
711 return ICE_ERR_PARAM;
713 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
714 struct ice_flow_seg_fld_raw *raw;
717 raw = ¶ms->prof->segs[seg].raws[i];
719 /* Only support matching raw fields in the payload */
720 if (raw->off < hdrs_sz)
721 return ICE_ERR_PARAM;
723 /* Convert the segment-relative offset into payload-relative
726 off = raw->off - hdrs_sz;
728 /* Storing extraction information */
729 raw->info.xtrct.prot_id = ICE_PROT_PAY;
730 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
731 ICE_FLOW_FV_EXTRACT_SZ;
732 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
734 raw->info.xtrct.idx = params->es_cnt;
736 /* Determine the number of field vector entries this raw field
739 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
740 (raw->info.src.last * BITS_PER_BYTE),
741 (ICE_FLOW_FV_EXTRACT_SZ *
743 off = raw->info.xtrct.off;
744 for (j = 0; j < cnt; j++) {
745 /* Make sure the number of extraction sequence required
746 * does not exceed the block's capability
748 if (params->es_cnt >= hw->blk[params->blk].es.count ||
749 params->es_cnt >= ICE_MAX_FV_WORDS)
750 return ICE_ERR_MAX_LIMIT;
752 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
753 params->es[params->es_cnt].off = off;
755 off += ICE_FLOW_FV_EXTRACT_SZ;
763 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
764 * @hw: pointer to the HW struct
765 * @params: information about the flow to be processed
767 * This function iterates through all matched fields in the given segments, and
768 * creates an extraction sequence for the fields.
770 static enum ice_status
771 ice_flow_create_xtrct_seq(struct ice_hw *hw,
772 struct ice_flow_prof_params *params)
774 enum ice_status status = ICE_SUCCESS;
777 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
780 if (params->blk == ICE_BLK_ACL)
781 ice_flow_xtract_pkt_flags(hw, params,
782 ICE_RX_MDID_PKT_FLAGS_15_0);
784 for (i = 0; i < params->prof->segs_cnt; i++) {
785 u64 match = params->prof->segs[i].match;
788 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
789 const u64 bit = BIT_ULL(j);
792 status = ice_flow_xtract_fld
793 (hw, params, i, (enum ice_flow_field)j);
800 /* Process raw matching bytes */
801 status = ice_flow_xtract_raws(hw, params, i);
810 * ice_flow_proc_segs - process all packet segments associated with a profile
811 * @hw: pointer to the HW struct
812 * @params: information about the flow to be processed
814 static enum ice_status
815 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
817 enum ice_status status;
819 status = ice_flow_proc_seg_hdrs(params);
823 status = ice_flow_create_xtrct_seq(hw, params);
827 switch (params->blk) {
829 /* Only header information is provided for RSS configuration.
830 * No further processing is needed.
832 status = ICE_SUCCESS;
835 status = ICE_SUCCESS;
839 return ICE_ERR_NOT_IMPL;
845 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
846 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
847 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
850 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
851 * @hw: pointer to the HW struct
852 * @blk: classification stage
853 * @dir: flow direction
854 * @segs: array of one or more packet segments that describe the flow
855 * @segs_cnt: number of packet segments provided
856 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
857 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
859 static struct ice_flow_prof *
860 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
861 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
862 u8 segs_cnt, u16 vsi_handle, u32 conds)
864 struct ice_flow_prof *p;
866 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
867 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
868 segs_cnt && segs_cnt == p->segs_cnt) {
871 /* Check for profile-VSI association if specified */
872 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
873 ice_is_vsi_valid(hw, vsi_handle) &&
874 !ice_is_bit_set(p->vsis, vsi_handle))
877 /* Protocol headers must be checked. Matched fields are
878 * checked if specified.
880 for (i = 0; i < segs_cnt; i++)
881 if (segs[i].hdrs != p->segs[i].hdrs ||
882 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
883 segs[i].match != p->segs[i].match))
886 /* A match is found if all segments are matched */
896 * ice_flow_find_prof - Look up a profile matching headers and matched fields
897 * @hw: pointer to the HW struct
898 * @blk: classification stage
899 * @dir: flow direction
900 * @segs: array of one or more packet segments that describe the flow
901 * @segs_cnt: number of packet segments provided
904 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
905 struct ice_flow_seg_info *segs, u8 segs_cnt)
907 struct ice_flow_prof *p;
909 ice_acquire_lock(&hw->fl_profs_locks[blk]);
910 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
911 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
912 ice_release_lock(&hw->fl_profs_locks[blk]);
914 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
918 * ice_flow_find_prof_id - Look up a profile with given profile ID
919 * @hw: pointer to the HW struct
920 * @blk: classification stage
921 * @prof_id: unique ID to identify this flow profile
923 static struct ice_flow_prof *
924 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
926 struct ice_flow_prof *p;
928 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
929 if (p->id == prof_id)
937 * ice_dealloc_flow_entry - Deallocate flow entry memory
938 * @hw: pointer to the HW struct
939 * @entry: flow entry to be removed
942 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
948 ice_free(hw, entry->entry);
951 ice_free(hw, entry->acts);
960 * ice_flow_rem_entry_sync - Remove a flow entry
961 * @hw: pointer to the HW struct
962 * @entry: flow entry to be removed
964 static enum ice_status
965 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
968 return ICE_ERR_BAD_PTR;
970 LIST_DEL(&entry->l_entry);
972 ice_dealloc_flow_entry(hw, entry);
978 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
979 * @hw: pointer to the HW struct
980 * @blk: classification stage
981 * @dir: flow direction
982 * @prof_id: unique ID to identify this flow profile
983 * @segs: array of one or more packet segments that describe the flow
984 * @segs_cnt: number of packet segments provided
985 * @acts: array of default actions
986 * @acts_cnt: number of default actions
987 * @prof: stores the returned flow profile added
989 * Assumption: the caller has acquired the lock to the profile list
991 static enum ice_status
992 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
993 enum ice_flow_dir dir, u64 prof_id,
994 struct ice_flow_seg_info *segs, u8 segs_cnt,
995 struct ice_flow_action *acts, u8 acts_cnt,
996 struct ice_flow_prof **prof)
998 struct ice_flow_prof_params params;
999 enum ice_status status = ICE_SUCCESS;
1002 if (!prof || (acts_cnt && !acts))
1003 return ICE_ERR_BAD_PTR;
1005 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1006 params.prof = (struct ice_flow_prof *)
1007 ice_malloc(hw, sizeof(*params.prof));
1009 return ICE_ERR_NO_MEMORY;
1011 /* initialize extraction sequence to all invalid (0xff) */
1012 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1013 params.es[i].prot_id = ICE_PROT_INVALID;
1014 params.es[i].off = ICE_FV_OFFSET_INVAL;
1018 params.prof->id = prof_id;
1019 params.prof->dir = dir;
1020 params.prof->segs_cnt = segs_cnt;
1022 /* Make a copy of the segments that need to be persistent in the flow
1025 for (i = 0; i < segs_cnt; i++)
1026 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1027 ICE_NONDMA_TO_NONDMA);
1029 /* Make a copy of the actions that need to be persistent in the flow
1033 params.prof->acts = (struct ice_flow_action *)
1034 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1035 ICE_NONDMA_TO_NONDMA);
1037 if (!params.prof->acts) {
1038 status = ICE_ERR_NO_MEMORY;
1043 status = ice_flow_proc_segs(hw, ¶ms);
1045 ice_debug(hw, ICE_DBG_FLOW,
1046 "Error processing a flow's packet segments\n");
1050 /* Add a HW profile for this flow profile */
1051 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
1053 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1057 INIT_LIST_HEAD(¶ms.prof->entries);
1058 ice_init_lock(¶ms.prof->entries_lock);
1059 *prof = params.prof;
1063 if (params.prof->acts)
1064 ice_free(hw, params.prof->acts);
1065 ice_free(hw, params.prof);
1072 * ice_flow_rem_prof_sync - remove a flow profile
1073 * @hw: pointer to the hardware structure
1074 * @blk: classification stage
1075 * @prof: pointer to flow profile to remove
1077 * Assumption: the caller has acquired the lock to the profile list
1079 static enum ice_status
1080 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1081 struct ice_flow_prof *prof)
1083 enum ice_status status = ICE_SUCCESS;
1085 /* Remove all remaining flow entries before removing the flow profile */
1086 if (!LIST_EMPTY(&prof->entries)) {
1087 struct ice_flow_entry *e, *t;
1089 ice_acquire_lock(&prof->entries_lock);
1091 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1093 status = ice_flow_rem_entry_sync(hw, e);
1098 ice_release_lock(&prof->entries_lock);
1101 /* Remove all hardware profiles associated with this flow profile */
1102 status = ice_rem_prof(hw, blk, prof->id);
1104 LIST_DEL(&prof->l_entry);
1105 ice_destroy_lock(&prof->entries_lock);
1107 ice_free(hw, prof->acts);
1115 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1116 * @hw: pointer to the hardware structure
1117 * @blk: classification stage
1118 * @vsi_handle: software VSI handle
1119 * @vsig: target VSI group
1121 * Assumption: the caller has already verified that the VSI to
1122 * be added has the same characteristics as the VSIG and will
1123 * thereby have access to all resources added to that VSIG.
1126 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1129 enum ice_status status;
1131 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1132 return ICE_ERR_PARAM;
1134 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1135 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1137 ice_release_lock(&hw->fl_profs_locks[blk]);
1143 * ice_flow_assoc_prof - associate a VSI with a flow profile
1144 * @hw: pointer to the hardware structure
1145 * @blk: classification stage
1146 * @prof: pointer to flow profile
1147 * @vsi_handle: software VSI handle
1149 * Assumption: the caller has acquired the lock to the profile list
1150 * and the software VSI handle has been validated
1152 static enum ice_status
1153 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1154 struct ice_flow_prof *prof, u16 vsi_handle)
1156 enum ice_status status = ICE_SUCCESS;
1158 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1159 status = ice_add_prof_id_flow(hw, blk,
1160 ice_get_hw_vsi_num(hw,
1164 ice_set_bit(vsi_handle, prof->vsis);
1166 ice_debug(hw, ICE_DBG_FLOW,
1167 "HW profile add failed, %d\n",
1175 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1176 * @hw: pointer to the hardware structure
1177 * @blk: classification stage
1178 * @prof: pointer to flow profile
1179 * @vsi_handle: software VSI handle
1181 * Assumption: the caller has acquired the lock to the profile list
1182 * and the software VSI handle has been validated
1184 static enum ice_status
1185 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1186 struct ice_flow_prof *prof, u16 vsi_handle)
1188 enum ice_status status = ICE_SUCCESS;
1190 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1191 status = ice_rem_prof_id_flow(hw, blk,
1192 ice_get_hw_vsi_num(hw,
1196 ice_clear_bit(vsi_handle, prof->vsis);
1198 ice_debug(hw, ICE_DBG_FLOW,
1199 "HW profile remove failed, %d\n",
1207 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1208 * @hw: pointer to the HW struct
1209 * @blk: classification stage
1210 * @dir: flow direction
1211 * @prof_id: unique ID to identify this flow profile
1212 * @segs: array of one or more packet segments that describe the flow
1213 * @segs_cnt: number of packet segments provided
1214 * @acts: array of default actions
1215 * @acts_cnt: number of default actions
1216 * @prof: stores the returned flow profile added
1219 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1220 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1221 struct ice_flow_action *acts, u8 acts_cnt,
1222 struct ice_flow_prof **prof)
1224 enum ice_status status;
1226 if (segs_cnt > ICE_FLOW_SEG_MAX)
1227 return ICE_ERR_MAX_LIMIT;
1230 return ICE_ERR_PARAM;
1233 return ICE_ERR_BAD_PTR;
1235 status = ice_flow_val_hdrs(segs, segs_cnt);
1239 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1241 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1242 acts, acts_cnt, prof);
1244 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1246 ice_release_lock(&hw->fl_profs_locks[blk]);
1252 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1253 * @hw: pointer to the HW struct
1254 * @blk: the block for which the flow profile is to be removed
1255 * @prof_id: unique ID of the flow profile to be removed
1258 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1260 struct ice_flow_prof *prof;
1261 enum ice_status status;
1263 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1265 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1267 status = ICE_ERR_DOES_NOT_EXIST;
1271 /* prof becomes invalid after the call */
1272 status = ice_flow_rem_prof_sync(hw, blk, prof);
1275 ice_release_lock(&hw->fl_profs_locks[blk]);
1281 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1282 * @hw: pointer to the HW struct
1283 * @blk: classification stage
1284 * @prof_id: the profile ID handle
1285 * @hw_prof_id: pointer to variable to receive the HW profile ID
1288 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1291 struct ice_prof_map *map;
1293 map = ice_search_prof_id(hw, blk, prof_id);
1295 *hw_prof_id = map->prof_id;
1299 return ICE_ERR_DOES_NOT_EXIST;
1303 * ice_flow_find_entry - look for a flow entry using its unique ID
1304 * @hw: pointer to the HW struct
1305 * @blk: classification stage
1306 * @entry_id: unique ID to identify this flow entry
1308 * This function looks for the flow entry with the specified unique ID in all
1309 * flow profiles of the specified classification stage. If the entry is found,
1310 * and it returns the handle to the flow entry. Otherwise, it returns
1311 * ICE_FLOW_ENTRY_ID_INVAL.
1313 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1315 struct ice_flow_entry *found = NULL;
1316 struct ice_flow_prof *p;
1318 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1320 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1321 struct ice_flow_entry *e;
1323 ice_acquire_lock(&p->entries_lock);
1324 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1325 if (e->id == entry_id) {
1329 ice_release_lock(&p->entries_lock);
1335 ice_release_lock(&hw->fl_profs_locks[blk]);
1337 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1341 * ice_flow_add_entry - Add a flow entry
1342 * @hw: pointer to the HW struct
1343 * @blk: classification stage
1344 * @prof_id: ID of the profile to add a new flow entry to
1345 * @entry_id: unique ID to identify this flow entry
1346 * @vsi_handle: software VSI handle for the flow entry
1347 * @prio: priority of the flow entry
1348 * @data: pointer to a data buffer containing flow entry's match values/masks
1349 * @acts: arrays of actions to be performed on a match
1350 * @acts_cnt: number of actions
1351 * @entry_h: pointer to buffer that receives the new flow entry's handle
1354 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1355 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1356 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1359 struct ice_flow_prof *prof = NULL;
1360 struct ice_flow_entry *e = NULL;
1361 enum ice_status status = ICE_SUCCESS;
1363 if (acts_cnt && !acts)
1364 return ICE_ERR_PARAM;
1366 /* No flow entry data is expected for RSS */
1367 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1368 return ICE_ERR_BAD_PTR;
1370 if (!ice_is_vsi_valid(hw, vsi_handle))
1371 return ICE_ERR_PARAM;
1373 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1375 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1377 status = ICE_ERR_DOES_NOT_EXIST;
1379 /* Allocate memory for the entry being added and associate
1380 * the VSI to the found flow profile
1382 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1384 status = ICE_ERR_NO_MEMORY;
1386 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1389 ice_release_lock(&hw->fl_profs_locks[blk]);
1394 e->vsi_handle = vsi_handle;
1400 /* RSS will add only one entry per VSI per profile */
1407 status = ICE_ERR_NOT_IMPL;
1411 ice_acquire_lock(&prof->entries_lock);
1412 LIST_ADD(&e->l_entry, &prof->entries);
1413 ice_release_lock(&prof->entries_lock);
1415 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1420 ice_free(hw, e->entry);
1428 * ice_flow_rem_entry - Remove a flow entry
1429 * @hw: pointer to the HW struct
1430 * @entry_h: handle to the flow entry to be removed
1432 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1434 struct ice_flow_entry *entry;
1435 struct ice_flow_prof *prof;
1436 enum ice_status status;
1438 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1439 return ICE_ERR_PARAM;
1441 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1443 /* Retain the pointer to the flow profile as the entry will be freed */
1446 ice_acquire_lock(&prof->entries_lock);
1447 status = ice_flow_rem_entry_sync(hw, entry);
1448 ice_release_lock(&prof->entries_lock);
1454 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1455 * @seg: packet segment the field being set belongs to
1456 * @fld: field to be set
1457 * @type: type of the field
1458 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1459 * entry's input buffer
1460 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1462 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1463 * entry's input buffer
1465 * This helper function stores information of a field being matched, including
1466 * the type of the field and the locations of the value to match, the mask, and
1467 * and the upper-bound value in the start of the input buffer for a flow entry.
1468 * This function should only be used for fixed-size data structures.
1470 * This function also opportunistically determines the protocol headers to be
1471 * present based on the fields being set. Some fields cannot be used alone to
1472 * determine the protocol headers present. Sometimes, fields for particular
1473 * protocol headers are not matched. In those cases, the protocol headers
1474 * must be explicitly set.
1477 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1478 enum ice_flow_fld_match_type type, u16 val_loc,
1479 u16 mask_loc, u16 last_loc)
1481 u64 bit = BIT_ULL(fld);
1484 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1487 seg->fields[fld].type = type;
1488 seg->fields[fld].src.val = val_loc;
1489 seg->fields[fld].src.mask = mask_loc;
1490 seg->fields[fld].src.last = last_loc;
1492 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1496 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1497 * @seg: packet segment the field being set belongs to
1498 * @fld: field to be set
1499 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1500 * entry's input buffer
1501 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1503 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1504 * entry's input buffer
1505 * @range: indicate if field being matched is to be in a range
1507 * This function specifies the locations, in the form of byte offsets from the
1508 * start of the input buffer for a flow entry, from where the value to match,
1509 * the mask value, and upper value can be extracted. These locations are then
1510 * stored in the flow profile. When adding a flow entry associated with the
1511 * flow profile, these locations will be used to quickly extract the values and
1512 * create the content of a match entry. This function should only be used for
1513 * fixed-size data structures.
1516 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1517 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1519 enum ice_flow_fld_match_type t = range ?
1520 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1522 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1526 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1527 * @seg: packet segment the field being set belongs to
1528 * @fld: field to be set
1529 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1530 * entry's input buffer
1531 * @pref_loc: location of prefix value from entry's input buffer
1532 * @pref_sz: size of the location holding the prefix value
1534 * This function specifies the locations, in the form of byte offsets from the
1535 * start of the input buffer for a flow entry, from where the value to match
1536 * and the IPv4 prefix value can be extracted. These locations are then stored
1537 * in the flow profile. When adding flow entries to the associated flow profile,
1538 * these locations can be used to quickly extract the values to create the
1539 * content of a match entry. This function should only be used for fixed-size
1543 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1544 u16 val_loc, u16 pref_loc, u8 pref_sz)
1546 /* For this type of field, the "mask" location is for the prefix value's
1547 * location and the "last" location is for the size of the location of
1550 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1551 pref_loc, (u16)pref_sz);
1555 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1556 * @seg: packet segment the field being set belongs to
1557 * @off: offset of the raw field from the beginning of the segment in bytes
1558 * @len: length of the raw pattern to be matched
1559 * @val_loc: location of the value to match from entry's input buffer
1560 * @mask_loc: location of mask value from entry's input buffer
1562 * This function specifies the offset of the raw field to be match from the
1563 * beginning of the specified packet segment, and the locations, in the form of
1564 * byte offsets from the start of the input buffer for a flow entry, from where
1565 * the value to match and the mask value to be extracted. These locations are
1566 * then stored in the flow profile. When adding flow entries to the associated
1567 * flow profile, these locations can be used to quickly extract the values to
1568 * create the content of a match entry. This function should only be used for
1569 * fixed-size data structures.
1572 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1573 u16 val_loc, u16 mask_loc)
1575 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1576 seg->raws[seg->raws_cnt].off = off;
1577 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1578 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1579 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1580 /* The "last" field is used to store the length of the field */
1581 seg->raws[seg->raws_cnt].info.src.last = len;
1584 /* Overflows of "raws" will be handled as an error condition later in
1585 * the flow when this information is processed.
1590 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1591 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1593 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1594 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1595 ICE_FLOW_SEG_HDR_SCTP)
1597 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1598 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1599 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1602 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1603 * @segs: pointer to the flow field segment(s)
1604 * @hash_fields: fields to be hashed on for the segment(s)
1605 * @flow_hdr: protocol header fields within a packet segment
1607 * Helper function to extract fields from hash bitmap and use flow
1608 * header value to set flow field segment for further use in flow
1609 * profile entry or removal.
1611 static enum ice_status
1612 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1615 u64 val = hash_fields;
1618 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1619 u64 bit = BIT_ULL(i);
1622 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1623 ICE_FLOW_FLD_OFF_INVAL,
1624 ICE_FLOW_FLD_OFF_INVAL,
1625 ICE_FLOW_FLD_OFF_INVAL, false);
1629 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1631 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1632 return ICE_ERR_PARAM;
1634 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1635 if (!ice_is_pow2(val))
1638 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1639 if (val && !ice_is_pow2(val))
1646 * ice_rem_vsi_rss_list - remove VSI from RSS list
1647 * @hw: pointer to the hardware structure
1648 * @vsi_handle: software VSI handle
1650 * Remove the VSI from all RSS configurations in the list.
1652 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1654 struct ice_rss_cfg *r, *tmp;
1656 if (LIST_EMPTY(&hw->rss_list_head))
1659 ice_acquire_lock(&hw->rss_locks);
1660 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1661 ice_rss_cfg, l_entry) {
1662 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1663 ice_clear_bit(vsi_handle, r->vsis);
1665 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1666 LIST_DEL(&r->l_entry);
1671 ice_release_lock(&hw->rss_locks);
1675 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1676 * @hw: pointer to the hardware structure
1677 * @vsi_handle: software VSI handle
1679 * This function will iterate through all flow profiles and disassociate
1680 * the VSI from that profile. If the flow profile has no VSIs it will
1683 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1685 const enum ice_block blk = ICE_BLK_RSS;
1686 struct ice_flow_prof *p, *t;
1687 enum ice_status status = ICE_SUCCESS;
1689 if (!ice_is_vsi_valid(hw, vsi_handle))
1690 return ICE_ERR_PARAM;
1692 if (LIST_EMPTY(&hw->fl_profs[blk]))
1695 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1696 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1698 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1699 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1703 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1704 status = ice_flow_rem_prof_sync(hw, blk, p);
1710 ice_release_lock(&hw->fl_profs_locks[blk]);
1716 * ice_rem_rss_list - remove RSS configuration from list
1717 * @hw: pointer to the hardware structure
1718 * @vsi_handle: software VSI handle
1719 * @prof: pointer to flow profile
1721 * Assumption: lock has already been acquired for RSS list
1724 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1726 struct ice_rss_cfg *r, *tmp;
1728 /* Search for RSS hash fields associated to the VSI that match the
1729 * hash configurations associated to the flow profile. If found
1730 * remove from the RSS entry list of the VSI context and delete entry.
1732 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1733 ice_rss_cfg, l_entry) {
1734 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1735 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1736 ice_clear_bit(vsi_handle, r->vsis);
1737 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1738 LIST_DEL(&r->l_entry);
1747 * ice_add_rss_list - add RSS configuration to list
1748 * @hw: pointer to the hardware structure
1749 * @vsi_handle: software VSI handle
1750 * @prof: pointer to flow profile
1752 * Assumption: lock has already been acquired for RSS list
1754 static enum ice_status
1755 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1757 struct ice_rss_cfg *r, *rss_cfg;
1759 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1760 ice_rss_cfg, l_entry)
1761 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1762 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1763 ice_set_bit(vsi_handle, r->vsis);
1767 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1769 return ICE_ERR_NO_MEMORY;
1771 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1772 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1773 ice_set_bit(vsi_handle, rss_cfg->vsis);
1775 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1780 #define ICE_FLOW_PROF_HASH_S 0
1781 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1782 #define ICE_FLOW_PROF_HDR_S 32
1783 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1785 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1786 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1787 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1790 * ice_add_rss_cfg_sync - add an RSS configuration
1791 * @hw: pointer to the hardware structure
1792 * @vsi_handle: software VSI handle
1793 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1794 * @addl_hdrs: protocol header fields
1796 * Assumption: lock has already been acquired for RSS list
1798 static enum ice_status
1799 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1802 const enum ice_block blk = ICE_BLK_RSS;
1803 struct ice_flow_prof *prof = NULL;
1804 struct ice_flow_seg_info *segs;
1805 enum ice_status status = ICE_SUCCESS;
1807 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1809 return ICE_ERR_NO_MEMORY;
1811 /* Construct the packet segment info from the hashed fields */
1812 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1816 /* Search for a flow profile that has matching headers, hash fields
1817 * and has the input VSI associated to it. If found, no further
1818 * operations required and exit.
1820 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1822 ICE_FLOW_FIND_PROF_CHK_FLDS |
1823 ICE_FLOW_FIND_PROF_CHK_VSI);
1827 /* Check if a flow profile exists with the same protocol headers and
1828 * associated with the input VSI. If so disasscociate the VSI from
1829 * this profile. The VSI will be added to a new profile created with
1830 * the protocol header and new hash field configuration.
1832 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1833 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1835 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1837 ice_rem_rss_list(hw, vsi_handle, prof);
1841 /* Remove profile if it has no VSIs associated */
1842 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1843 status = ice_flow_rem_prof_sync(hw, blk, prof);
1849 /* Search for a profile that has same match fields only. If this
1850 * exists then associate the VSI to this profile.
1852 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1854 ICE_FLOW_FIND_PROF_CHK_FLDS);
1856 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1858 status = ice_add_rss_list(hw, vsi_handle, prof);
1862 /* Create a new flow profile with generated profile and packet
1863 * segment information.
1865 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1866 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1867 segs, 1, NULL, 0, &prof);
1871 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1872 /* If association to a new flow profile failed then this profile can
1876 ice_flow_rem_prof_sync(hw, blk, prof);
1880 status = ice_add_rss_list(hw, vsi_handle, prof);
1888 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1889 * @hw: pointer to the hardware structure
1890 * @vsi_handle: software VSI handle
1891 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1892 * @addl_hdrs: protocol header fields
1894 * This function will generate a flow profile based on fields associated with
1895 * the input fields to hash on, the flow type and use the VSI number to add
1896 * a flow entry to the profile.
1899 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1902 enum ice_status status;
1904 if (hashed_flds == ICE_HASH_INVALID ||
1905 !ice_is_vsi_valid(hw, vsi_handle))
1906 return ICE_ERR_PARAM;
1908 ice_acquire_lock(&hw->rss_locks);
1909 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1910 ice_release_lock(&hw->rss_locks);
1916 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1917 * @hw: pointer to the hardware structure
1918 * @vsi_handle: software VSI handle
1919 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1920 * @addl_hdrs: Protocol header fields within a packet segment
1922 * Assumption: lock has already been acquired for RSS list
1924 static enum ice_status
1925 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1928 const enum ice_block blk = ICE_BLK_RSS;
1929 struct ice_flow_seg_info *segs;
1930 struct ice_flow_prof *prof;
1931 enum ice_status status;
1933 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1935 return ICE_ERR_NO_MEMORY;
1937 /* Construct the packet segment info from the hashed fields */
1938 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1942 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1944 ICE_FLOW_FIND_PROF_CHK_FLDS);
1946 status = ICE_ERR_DOES_NOT_EXIST;
1950 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1954 /* Remove RSS configuration from VSI context before deleting
1957 ice_rem_rss_list(hw, vsi_handle, prof);
1959 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1960 status = ice_flow_rem_prof_sync(hw, blk, prof);
1967 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1968 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1969 * convert its values to their appropriate flow L3, L4 values.
1971 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1972 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1973 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1974 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1975 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1976 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1977 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1978 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1979 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1980 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1981 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1982 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1983 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1985 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1986 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1987 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1988 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1989 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1990 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1991 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1992 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1993 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1994 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1995 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1996 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1997 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1999 #define ICE_FLOW_MAX_CFG 10
2002 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2003 * @hw: pointer to the hardware structure
2004 * @vsi_handle: software VSI handle
2005 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2007 * This function will take the hash bitmap provided by the AVF driver via a
2008 * message, convert it to ICE-compatible values, and configure RSS flow
2012 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2014 enum ice_status status = ICE_SUCCESS;
2017 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2018 !ice_is_vsi_valid(hw, vsi_handle))
2019 return ICE_ERR_PARAM;
2021 /* Make sure no unsupported bits are specified */
2022 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2023 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2026 hash_flds = avf_hash;
2028 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2029 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2030 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2032 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2033 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2035 /* Create the corresponding RSS configuration for each valid hash bit */
2037 u64 rss_hash = ICE_HASH_INVALID;
2039 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2040 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2041 rss_hash = ICE_FLOW_HASH_IPV4;
2042 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2043 } else if (hash_flds &
2044 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2045 rss_hash = ICE_FLOW_HASH_IPV4 |
2046 ICE_FLOW_HASH_TCP_PORT;
2047 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2048 } else if (hash_flds &
2049 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2050 rss_hash = ICE_FLOW_HASH_IPV4 |
2051 ICE_FLOW_HASH_UDP_PORT;
2052 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2053 } else if (hash_flds &
2054 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2055 rss_hash = ICE_FLOW_HASH_IPV4 |
2056 ICE_FLOW_HASH_SCTP_PORT;
2058 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2060 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2061 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2062 rss_hash = ICE_FLOW_HASH_IPV6;
2063 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2064 } else if (hash_flds &
2065 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2066 rss_hash = ICE_FLOW_HASH_IPV6 |
2067 ICE_FLOW_HASH_TCP_PORT;
2068 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2069 } else if (hash_flds &
2070 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2071 rss_hash = ICE_FLOW_HASH_IPV6 |
2072 ICE_FLOW_HASH_UDP_PORT;
2073 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2074 } else if (hash_flds &
2075 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2076 rss_hash = ICE_FLOW_HASH_IPV6 |
2077 ICE_FLOW_HASH_SCTP_PORT;
2079 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2083 if (rss_hash == ICE_HASH_INVALID)
2084 return ICE_ERR_OUT_OF_RANGE;
2086 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2087 ICE_FLOW_SEG_HDR_NONE);
2096 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2097 * @hw: pointer to the hardware structure
2098 * @vsi_handle: software VSI handle
2099 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2100 * @addl_hdrs: Protocol header fields within a packet segment
2102 * This function will lookup the flow profile based on the input
2103 * hash field bitmap, iterate through the profile entry list of
2104 * that profile and find entry associated with input VSI to be
2105 * removed. Calls are made to underlying flow apis which will in
2106 * turn build or update buffers for RSS XLT1 section.
2109 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2112 enum ice_status status;
2114 if (hashed_flds == ICE_HASH_INVALID ||
2115 !ice_is_vsi_valid(hw, vsi_handle))
2116 return ICE_ERR_PARAM;
2118 ice_acquire_lock(&hw->rss_locks);
2119 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2120 ice_release_lock(&hw->rss_locks);
2126 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2127 * @hw: pointer to the hardware structure
2128 * @vsi_handle: software VSI handle
2130 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2132 enum ice_status status = ICE_SUCCESS;
2133 struct ice_rss_cfg *r;
2135 if (!ice_is_vsi_valid(hw, vsi_handle))
2136 return ICE_ERR_PARAM;
2138 ice_acquire_lock(&hw->rss_locks);
2139 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2140 ice_rss_cfg, l_entry) {
2141 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2142 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2149 ice_release_lock(&hw->rss_locks);
2155 * ice_get_rss_cfg - returns hashed fields for the given header types
2156 * @hw: pointer to the hardware structure
2157 * @vsi_handle: software VSI handle
2158 * @hdrs: protocol header type
2160 * This function will return the match fields of the first instance of flow
2161 * profile having the given header types and containing input VSI
2163 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2165 struct ice_rss_cfg *r, *rss_cfg = NULL;
2167 /* verify if the protocol header is non zero and VSI is valid */
2168 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2169 return ICE_HASH_INVALID;
2171 ice_acquire_lock(&hw->rss_locks);
2172 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2173 ice_rss_cfg, l_entry)
2174 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2175 r->packet_hdr == hdrs) {
2179 ice_release_lock(&hw->rss_locks);
2181 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;