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 if (i > 0 && (i + 1) < prof->segs_cnt)
421 hdrs = prof->segs[i].hdrs;
423 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
424 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
425 (const ice_bitmap_t *)ice_ptypes_mac_il;
426 ice_and_bitmap(params->ptypes, params->ptypes, src,
428 hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
431 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
432 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
433 ice_and_bitmap(params->ptypes, params->ptypes, src,
435 hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
438 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
439 ice_and_bitmap(params->ptypes, params->ptypes,
440 (const ice_bitmap_t *)ice_ptypes_arp_of,
442 hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
445 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
446 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
447 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
448 ice_and_bitmap(params->ptypes, params->ptypes, src,
450 hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
451 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
452 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
453 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
454 ice_and_bitmap(params->ptypes, params->ptypes, src,
456 hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
459 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
460 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
461 (const ice_bitmap_t *)ice_ptypes_icmp_il;
462 ice_and_bitmap(params->ptypes, params->ptypes, src,
464 hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
465 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
466 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
467 ice_and_bitmap(params->ptypes, params->ptypes, src,
469 hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
470 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
471 ice_and_bitmap(params->ptypes, params->ptypes,
472 (const ice_bitmap_t *)ice_ptypes_tcp_il,
474 hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
475 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
476 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
477 ice_and_bitmap(params->ptypes, params->ptypes, src,
479 hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
480 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
482 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
483 ice_and_bitmap(params->ptypes, params->ptypes,
484 src, ICE_FLOW_PTYPE_MAX);
486 hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
494 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
495 * @hw: pointer to the HW struct
496 * @params: information about the flow to be processed
497 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
499 * This function will allocate an extraction sequence entries for a DWORD size
500 * chunk of the packet flags.
502 static enum ice_status
503 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
504 struct ice_flow_prof_params *params,
505 enum ice_flex_mdid_pkt_flags flags)
507 u8 fv_words = hw->blk[params->blk].es.fvw;
510 /* Make sure the number of extraction sequence entries required does not
511 * exceed the block's capacity.
513 if (params->es_cnt >= fv_words)
514 return ICE_ERR_MAX_LIMIT;
516 /* some blocks require a reversed field vector layout */
517 if (hw->blk[params->blk].es.reverse)
518 idx = fv_words - params->es_cnt - 1;
520 idx = params->es_cnt;
522 params->es[idx].prot_id = ICE_PROT_META_ID;
523 params->es[idx].off = flags;
530 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
531 * @hw: pointer to the HW struct
532 * @params: information about the flow to be processed
533 * @seg: packet segment index of the field to be extracted
534 * @fld: ID of field to be extracted
536 * This function determines the protocol ID, offset, and size of the given
537 * field. It then allocates one or more extraction sequence entries for the
538 * given field, and fill the entries with protocol ID and offset information.
540 static enum ice_status
541 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
542 u8 seg, enum ice_flow_field fld)
544 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
545 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
546 u8 fv_words = hw->blk[params->blk].es.fvw;
547 struct ice_flow_fld_info *flds;
548 u16 cnt, ese_bits, i;
552 flds = params->prof->segs[seg].fields;
555 case ICE_FLOW_FIELD_IDX_ETH_DA:
556 case ICE_FLOW_FIELD_IDX_ETH_SA:
557 case ICE_FLOW_FIELD_IDX_S_VLAN:
558 case ICE_FLOW_FIELD_IDX_C_VLAN:
559 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
561 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
562 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
564 case ICE_FLOW_FIELD_IDX_IP_DSCP:
565 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
566 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
568 case ICE_FLOW_FIELD_IDX_IP_TTL:
569 case ICE_FLOW_FIELD_IDX_IP_PROT:
570 /* Some fields are located at different offsets in IPv4 and
573 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
574 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
576 /* TTL and PROT share the same extraction seq. entry.
577 * Each is considered a sibling to the other in term
578 * sharing the same extraction sequence entry.
580 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
581 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
582 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
583 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
584 } else if (params->prof->segs[seg].hdrs &
585 ICE_FLOW_SEG_HDR_IPV6) {
586 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
588 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
589 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
590 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
591 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
594 case ICE_FLOW_FIELD_IDX_IPV4_SA:
595 case ICE_FLOW_FIELD_IDX_IPV4_DA:
596 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
598 case ICE_FLOW_FIELD_IDX_IPV6_SA:
599 case ICE_FLOW_FIELD_IDX_IPV6_DA:
600 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
602 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
603 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
604 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
605 prot_id = ICE_PROT_TCP_IL;
607 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
608 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
609 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
611 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
612 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
613 prot_id = ICE_PROT_SCTP_IL;
615 case ICE_FLOW_FIELD_IDX_ARP_SIP:
616 case ICE_FLOW_FIELD_IDX_ARP_DIP:
617 case ICE_FLOW_FIELD_IDX_ARP_SHA:
618 case ICE_FLOW_FIELD_IDX_ARP_DHA:
619 case ICE_FLOW_FIELD_IDX_ARP_OP:
620 prot_id = ICE_PROT_ARP_OF;
622 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
623 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
624 /* ICMP type and code share the same extraction seq. entry */
625 prot_id = (params->prof->segs[seg].hdrs &
626 ICE_FLOW_SEG_HDR_IPV4) ?
627 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
628 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
629 ICE_FLOW_FIELD_IDX_ICMP_CODE :
630 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
632 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
633 prot_id = ICE_PROT_GRE_OF;
636 return ICE_ERR_NOT_IMPL;
639 /* Each extraction sequence entry is a word in size, and extracts a
640 * word-aligned offset from a protocol header.
642 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
644 flds[fld].xtrct.prot_id = prot_id;
645 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
646 ICE_FLOW_FV_EXTRACT_SZ;
647 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
648 flds[fld].xtrct.idx = params->es_cnt;
650 /* Adjust the next field-entry index after accommodating the number of
651 * entries this field consumes
653 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
654 ice_flds_info[fld].size, ese_bits);
656 /* Fill in the extraction sequence entries needed for this field */
657 off = flds[fld].xtrct.off;
658 for (i = 0; i < cnt; i++) {
659 /* Only consume an extraction sequence entry if there is no
660 * sibling field associated with this field or the sibling entry
661 * already extracts the word shared with this field.
663 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
664 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
665 flds[sib].xtrct.off != off) {
668 /* Make sure the number of extraction sequence required
669 * does not exceed the block's capability
671 if (params->es_cnt >= fv_words)
672 return ICE_ERR_MAX_LIMIT;
674 /* some blocks require a reversed field vector layout */
675 if (hw->blk[params->blk].es.reverse)
676 idx = fv_words - params->es_cnt - 1;
678 idx = params->es_cnt;
680 params->es[idx].prot_id = prot_id;
681 params->es[idx].off = off;
685 off += ICE_FLOW_FV_EXTRACT_SZ;
692 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
693 * @hw: pointer to the HW struct
694 * @params: information about the flow to be processed
695 * @seg: index of packet segment whose raw fields are to be be extracted
697 static enum ice_status
698 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
704 if (!params->prof->segs[seg].raws_cnt)
707 if (params->prof->segs[seg].raws_cnt >
708 ARRAY_SIZE(params->prof->segs[seg].raws))
709 return ICE_ERR_MAX_LIMIT;
711 /* Offsets within the segment headers are not supported */
712 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
714 return ICE_ERR_PARAM;
716 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
717 struct ice_flow_seg_fld_raw *raw;
720 raw = ¶ms->prof->segs[seg].raws[i];
722 /* Only support matching raw fields in the payload */
723 if (raw->off < hdrs_sz)
724 return ICE_ERR_PARAM;
726 /* Convert the segment-relative offset into payload-relative
729 off = raw->off - hdrs_sz;
731 /* Storing extraction information */
732 raw->info.xtrct.prot_id = ICE_PROT_PAY;
733 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
734 ICE_FLOW_FV_EXTRACT_SZ;
735 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
737 raw->info.xtrct.idx = params->es_cnt;
739 /* Determine the number of field vector entries this raw field
742 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
743 (raw->info.src.last * BITS_PER_BYTE),
744 (ICE_FLOW_FV_EXTRACT_SZ *
746 off = raw->info.xtrct.off;
747 for (j = 0; j < cnt; j++) {
748 /* Make sure the number of extraction sequence required
749 * does not exceed the block's capability
751 if (params->es_cnt >= hw->blk[params->blk].es.count ||
752 params->es_cnt >= ICE_MAX_FV_WORDS)
753 return ICE_ERR_MAX_LIMIT;
755 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
756 params->es[params->es_cnt].off = off;
758 off += ICE_FLOW_FV_EXTRACT_SZ;
766 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
767 * @hw: pointer to the HW struct
768 * @params: information about the flow to be processed
770 * This function iterates through all matched fields in the given segments, and
771 * creates an extraction sequence for the fields.
773 static enum ice_status
774 ice_flow_create_xtrct_seq(struct ice_hw *hw,
775 struct ice_flow_prof_params *params)
777 enum ice_status status = ICE_SUCCESS;
780 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
783 if (params->blk == ICE_BLK_ACL)
784 ice_flow_xtract_pkt_flags(hw, params,
785 ICE_RX_MDID_PKT_FLAGS_15_0);
787 for (i = 0; i < params->prof->segs_cnt; i++) {
788 u64 match = params->prof->segs[i].match;
791 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
792 const u64 bit = BIT_ULL(j);
795 status = ice_flow_xtract_fld
796 (hw, params, i, (enum ice_flow_field)j);
803 /* Process raw matching bytes */
804 status = ice_flow_xtract_raws(hw, params, i);
813 * ice_flow_proc_segs - process all packet segments associated with a profile
814 * @hw: pointer to the HW struct
815 * @params: information about the flow to be processed
817 static enum ice_status
818 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
820 enum ice_status status;
822 status = ice_flow_proc_seg_hdrs(params);
826 status = ice_flow_create_xtrct_seq(hw, params);
830 switch (params->blk) {
832 /* Only header information is provided for RSS configuration.
833 * No further processing is needed.
835 status = ICE_SUCCESS;
838 status = ICE_SUCCESS;
842 return ICE_ERR_NOT_IMPL;
848 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
849 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
852 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
853 * @hw: pointer to the HW struct
854 * @blk: classification stage
855 * @dir: flow direction
856 * @segs: array of one or more packet segments that describe the flow
857 * @segs_cnt: number of packet segments provided
858 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
859 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
861 static struct ice_flow_prof *
862 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
863 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
864 u8 segs_cnt, u16 vsi_handle, u32 conds)
866 struct ice_flow_prof *p;
868 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
869 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
872 /* Check for profile-VSI association if specified */
873 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
874 ice_is_vsi_valid(hw, vsi_handle) &&
875 !ice_is_bit_set(p->vsis, vsi_handle))
878 /* Protocol headers must be checked. Matched fields are
879 * checked if specified.
881 for (i = 0; i < segs_cnt; i++)
882 if (segs[i].hdrs != p->segs[i].hdrs ||
883 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
884 segs[i].match != p->segs[i].match))
887 /* A match is found if all segments are matched */
897 * ice_flow_find_prof - Look up a profile matching headers and matched fields
898 * @hw: pointer to the HW struct
899 * @blk: classification stage
900 * @dir: flow direction
901 * @segs: array of one or more packet segments that describe the flow
902 * @segs_cnt: number of packet segments provided
905 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
906 struct ice_flow_seg_info *segs, u8 segs_cnt)
908 struct ice_flow_prof *p;
910 ice_acquire_lock(&hw->fl_profs_locks[blk]);
911 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
912 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
913 ice_release_lock(&hw->fl_profs_locks[blk]);
915 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
919 * ice_flow_find_prof_id - Look up a profile with given profile ID
920 * @hw: pointer to the HW struct
921 * @blk: classification stage
922 * @prof_id: unique ID to identify this flow profile
924 static struct ice_flow_prof *
925 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
927 struct ice_flow_prof *p;
929 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
930 if (p->id == prof_id)
938 * ice_flow_rem_entry_sync - Remove a flow entry
939 * @hw: pointer to the HW struct
940 * @entry: flow entry to be removed
942 static enum ice_status
943 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
946 return ICE_ERR_BAD_PTR;
948 LIST_DEL(&entry->l_entry);
951 ice_free(hw, entry->entry);
954 ice_free(hw, entry->acts);
965 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
966 * @hw: pointer to the HW struct
967 * @blk: classification stage
968 * @dir: flow direction
969 * @prof_id: unique ID to identify this flow profile
970 * @segs: array of one or more packet segments that describe the flow
971 * @segs_cnt: number of packet segments provided
972 * @acts: array of default actions
973 * @acts_cnt: number of default actions
974 * @prof: stores the returned flow profile added
976 * Assumption: the caller has acquired the lock to the profile list
978 static enum ice_status
979 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
980 enum ice_flow_dir dir, u64 prof_id,
981 struct ice_flow_seg_info *segs, u8 segs_cnt,
982 struct ice_flow_action *acts, u8 acts_cnt,
983 struct ice_flow_prof **prof)
985 struct ice_flow_prof_params params;
986 enum ice_status status = ICE_SUCCESS;
989 if (!prof || (acts_cnt && !acts))
990 return ICE_ERR_BAD_PTR;
992 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
993 params.prof = (struct ice_flow_prof *)
994 ice_malloc(hw, sizeof(*params.prof));
996 return ICE_ERR_NO_MEMORY;
998 /* initialize extraction sequence to all invalid (0xff) */
999 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1000 params.es[i].prot_id = ICE_PROT_INVALID;
1001 params.es[i].off = ICE_FV_OFFSET_INVAL;
1005 params.prof->id = prof_id;
1006 params.prof->dir = dir;
1007 params.prof->segs_cnt = segs_cnt;
1009 /* Make a copy of the segments that need to be persistent in the flow
1012 for (i = 0; i < segs_cnt; i++)
1013 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1014 ICE_NONDMA_TO_NONDMA);
1016 /* Make a copy of the actions that need to be persistent in the flow
1020 params.prof->acts = (struct ice_flow_action *)
1021 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1022 ICE_NONDMA_TO_NONDMA);
1024 if (!params.prof->acts) {
1025 status = ICE_ERR_NO_MEMORY;
1030 status = ice_flow_proc_segs(hw, ¶ms);
1032 ice_debug(hw, ICE_DBG_FLOW,
1033 "Error processing a flow's packet segments\n");
1037 /* Add a HW profile for this flow profile */
1038 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
1040 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1044 INIT_LIST_HEAD(¶ms.prof->entries);
1045 ice_init_lock(¶ms.prof->entries_lock);
1046 *prof = params.prof;
1050 if (params.prof->acts)
1051 ice_free(hw, params.prof->acts);
1052 ice_free(hw, params.prof);
1059 * ice_flow_rem_prof_sync - remove a flow profile
1060 * @hw: pointer to the hardware structure
1061 * @blk: classification stage
1062 * @prof: pointer to flow profile to remove
1064 * Assumption: the caller has acquired the lock to the profile list
1066 static enum ice_status
1067 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1068 struct ice_flow_prof *prof)
1070 enum ice_status status = ICE_SUCCESS;
1072 /* Remove all remaining flow entries before removing the flow profile */
1073 if (!LIST_EMPTY(&prof->entries)) {
1074 struct ice_flow_entry *e, *t;
1076 ice_acquire_lock(&prof->entries_lock);
1078 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1080 status = ice_flow_rem_entry_sync(hw, e);
1085 ice_release_lock(&prof->entries_lock);
1088 /* Remove all hardware profiles associated with this flow profile */
1089 status = ice_rem_prof(hw, blk, prof->id);
1091 LIST_DEL(&prof->l_entry);
1092 ice_destroy_lock(&prof->entries_lock);
1094 ice_free(hw, prof->acts);
1102 * ice_flow_assoc_prof - associate a VSI with a flow profile
1103 * @hw: pointer to the hardware structure
1104 * @blk: classification stage
1105 * @prof: pointer to flow profile
1106 * @vsi_handle: software VSI handle
1108 * Assumption: the caller has acquired the lock to the profile list
1109 * and the software VSI handle has been validated
1111 static enum ice_status
1112 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1113 struct ice_flow_prof *prof, u16 vsi_handle)
1115 enum ice_status status = ICE_SUCCESS;
1117 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1118 status = ice_add_prof_id_flow(hw, blk,
1119 ice_get_hw_vsi_num(hw,
1123 ice_set_bit(vsi_handle, prof->vsis);
1125 ice_debug(hw, ICE_DBG_FLOW,
1126 "HW profile add failed, %d\n",
1134 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1135 * @hw: pointer to the hardware structure
1136 * @blk: classification stage
1137 * @prof: pointer to flow profile
1138 * @vsi_handle: software VSI handle
1140 * Assumption: the caller has acquired the lock to the profile list
1141 * and the software VSI handle has been validated
1143 static enum ice_status
1144 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1145 struct ice_flow_prof *prof, u16 vsi_handle)
1147 enum ice_status status = ICE_SUCCESS;
1149 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1150 status = ice_rem_prof_id_flow(hw, blk,
1151 ice_get_hw_vsi_num(hw,
1155 ice_clear_bit(vsi_handle, prof->vsis);
1157 ice_debug(hw, ICE_DBG_FLOW,
1158 "HW profile remove failed, %d\n",
1166 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1167 * @hw: pointer to the HW struct
1168 * @blk: classification stage
1169 * @dir: flow direction
1170 * @prof_id: unique ID to identify this flow profile
1171 * @segs: array of one or more packet segments that describe the flow
1172 * @segs_cnt: number of packet segments provided
1173 * @acts: array of default actions
1174 * @acts_cnt: number of default actions
1175 * @prof: stores the returned flow profile added
1178 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1179 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1180 struct ice_flow_action *acts, u8 acts_cnt,
1181 struct ice_flow_prof **prof)
1183 enum ice_status status;
1185 if (segs_cnt > ICE_FLOW_SEG_MAX)
1186 return ICE_ERR_MAX_LIMIT;
1189 return ICE_ERR_PARAM;
1192 return ICE_ERR_BAD_PTR;
1194 status = ice_flow_val_hdrs(segs, segs_cnt);
1198 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1200 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1201 acts, acts_cnt, prof);
1203 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1205 ice_release_lock(&hw->fl_profs_locks[blk]);
1211 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1212 * @hw: pointer to the HW struct
1213 * @blk: the block for which the flow profile is to be removed
1214 * @prof_id: unique ID of the flow profile to be removed
1217 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1219 struct ice_flow_prof *prof;
1220 enum ice_status status;
1222 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1224 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1226 status = ICE_ERR_DOES_NOT_EXIST;
1230 /* prof becomes invalid after the call */
1231 status = ice_flow_rem_prof_sync(hw, blk, prof);
1234 ice_release_lock(&hw->fl_profs_locks[blk]);
1240 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1241 * @hw: pointer to the HW struct
1242 * @blk: classification stage
1243 * @prof_id: the profile ID handle
1244 * @hw_prof_id: pointer to variable to receive the HW profile ID
1247 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1250 struct ice_prof_map *map;
1252 map = ice_search_prof_id(hw, blk, prof_id);
1254 *hw_prof_id = map->prof_id;
1258 return ICE_ERR_DOES_NOT_EXIST;
1262 * ice_flow_find_entry - look for a flow entry using its unique ID
1263 * @hw: pointer to the HW struct
1264 * @blk: classification stage
1265 * @entry_id: unique ID to identify this flow entry
1267 * This function looks for the flow entry with the specified unique ID in all
1268 * flow profiles of the specified classification stage. If the entry is found,
1269 * and it returns the handle to the flow entry. Otherwise, it returns
1270 * ICE_FLOW_ENTRY_ID_INVAL.
1272 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1274 struct ice_flow_entry *found = NULL;
1275 struct ice_flow_prof *p;
1277 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1279 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1280 struct ice_flow_entry *e;
1282 ice_acquire_lock(&p->entries_lock);
1283 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1284 if (e->id == entry_id) {
1288 ice_release_lock(&p->entries_lock);
1294 ice_release_lock(&hw->fl_profs_locks[blk]);
1296 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1300 * ice_flow_add_entry - Add a flow entry
1301 * @hw: pointer to the HW struct
1302 * @blk: classification stage
1303 * @prof_id: ID of the profile to add a new flow entry to
1304 * @entry_id: unique ID to identify this flow entry
1305 * @vsi_handle: software VSI handle for the flow entry
1306 * @prio: priority of the flow entry
1307 * @data: pointer to a data buffer containing flow entry's match values/masks
1308 * @acts: arrays of actions to be performed on a match
1309 * @acts_cnt: number of actions
1310 * @entry_h: pointer to buffer that receives the new flow entry's handle
1313 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1314 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1315 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1318 struct ice_flow_prof *prof = NULL;
1319 struct ice_flow_entry *e = NULL;
1320 enum ice_status status = ICE_SUCCESS;
1322 if (acts_cnt && !acts)
1323 return ICE_ERR_PARAM;
1325 /* No flow entry data is expected for RSS */
1326 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1327 return ICE_ERR_BAD_PTR;
1329 if (!ice_is_vsi_valid(hw, vsi_handle))
1330 return ICE_ERR_PARAM;
1332 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1334 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1336 status = ICE_ERR_DOES_NOT_EXIST;
1338 /* Allocate memory for the entry being added and associate
1339 * the VSI to the found flow profile
1341 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1343 status = ICE_ERR_NO_MEMORY;
1345 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1348 ice_release_lock(&hw->fl_profs_locks[blk]);
1353 e->vsi_handle = vsi_handle;
1359 /* RSS will add only one entry per VSI per profile */
1366 status = ICE_ERR_NOT_IMPL;
1370 ice_acquire_lock(&prof->entries_lock);
1371 LIST_ADD(&e->l_entry, &prof->entries);
1372 ice_release_lock(&prof->entries_lock);
1374 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1379 ice_free(hw, e->entry);
1387 * ice_flow_rem_entry - Remove a flow entry
1388 * @hw: pointer to the HW struct
1389 * @entry_h: handle to the flow entry to be removed
1391 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1393 struct ice_flow_entry *entry;
1394 struct ice_flow_prof *prof;
1395 enum ice_status status;
1397 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1398 return ICE_ERR_PARAM;
1400 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1402 /* Retain the pointer to the flow profile as the entry will be freed */
1405 ice_acquire_lock(&prof->entries_lock);
1406 status = ice_flow_rem_entry_sync(hw, entry);
1407 ice_release_lock(&prof->entries_lock);
1413 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1414 * @seg: packet segment the field being set belongs to
1415 * @fld: field to be set
1416 * @type: type of the field
1417 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1418 * entry's input buffer
1419 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1421 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1422 * entry's input buffer
1424 * This helper function stores information of a field being matched, including
1425 * the type of the field and the locations of the value to match, the mask, and
1426 * and the upper-bound value in the start of the input buffer for a flow entry.
1427 * This function should only be used for fixed-size data structures.
1429 * This function also opportunistically determines the protocol headers to be
1430 * present based on the fields being set. Some fields cannot be used alone to
1431 * determine the protocol headers present. Sometimes, fields for particular
1432 * protocol headers are not matched. In those cases, the protocol headers
1433 * must be explicitly set.
1436 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1437 enum ice_flow_fld_match_type type, u16 val_loc,
1438 u16 mask_loc, u16 last_loc)
1440 u64 bit = BIT_ULL(fld);
1443 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1446 seg->fields[fld].type = type;
1447 seg->fields[fld].src.val = val_loc;
1448 seg->fields[fld].src.mask = mask_loc;
1449 seg->fields[fld].src.last = last_loc;
1451 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1455 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1456 * @seg: packet segment the field being set belongs to
1457 * @fld: field to be set
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
1464 * @range: indicate if field being matched is to be in a range
1466 * This function specifies the locations, in the form of byte offsets from the
1467 * start of the input buffer for a flow entry, from where the value to match,
1468 * the mask value, and upper value can be extracted. These locations are then
1469 * stored in the flow profile. When adding a flow entry associated with the
1470 * flow profile, these locations will be used to quickly extract the values and
1471 * create the content of a match entry. This function should only be used for
1472 * fixed-size data structures.
1475 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1476 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1478 enum ice_flow_fld_match_type t = range ?
1479 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1481 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1485 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1486 * @seg: packet segment the field being set belongs to
1487 * @fld: field to be set
1488 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1489 * entry's input buffer
1490 * @pref_loc: location of prefix value from entry's input buffer
1491 * @pref_sz: size of the location holding the prefix value
1493 * This function specifies the locations, in the form of byte offsets from the
1494 * start of the input buffer for a flow entry, from where the value to match
1495 * and the IPv4 prefix value can be extracted. These locations are then stored
1496 * in the flow profile. When adding flow entries to the associated flow profile,
1497 * these locations can be used to quickly extract the values to create the
1498 * content of a match entry. This function should only be used for fixed-size
1502 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1503 u16 val_loc, u16 pref_loc, u8 pref_sz)
1505 /* For this type of field, the "mask" location is for the prefix value's
1506 * location and the "last" location is for the size of the location of
1509 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1510 pref_loc, (u16)pref_sz);
1514 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1515 * @seg: packet segment the field being set belongs to
1516 * @off: offset of the raw field from the beginning of the segment in bytes
1517 * @len: length of the raw pattern to be matched
1518 * @val_loc: location of the value to match from entry's input buffer
1519 * @mask_loc: location of mask value from entry's input buffer
1521 * This function specifies the offset of the raw field to be match from the
1522 * beginning of the specified packet segment, and the locations, in the form of
1523 * byte offsets from the start of the input buffer for a flow entry, from where
1524 * the value to match and the mask value to be extracted. These locations are
1525 * then stored in the flow profile. When adding flow entries to the associated
1526 * flow profile, these locations can be used to quickly extract the values to
1527 * create the content of a match entry. This function should only be used for
1528 * fixed-size data structures.
1531 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1532 u16 val_loc, u16 mask_loc)
1534 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1535 seg->raws[seg->raws_cnt].off = off;
1536 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1537 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1538 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1539 /* The "last" field is used to store the length of the field */
1540 seg->raws[seg->raws_cnt].info.src.last = len;
1543 /* Overflows of "raws" will be handled as an error condition later in
1544 * the flow when this information is processed.
1549 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1550 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1552 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1553 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1554 ICE_FLOW_SEG_HDR_SCTP)
1556 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1557 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1558 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1561 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1562 * @segs: pointer to the flow field segment(s)
1563 * @hash_fields: fields to be hashed on for the segment(s)
1564 * @flow_hdr: protocol header fields within a packet segment
1566 * Helper function to extract fields from hash bitmap and use flow
1567 * header value to set flow field segment for further use in flow
1568 * profile entry or removal.
1570 static enum ice_status
1571 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1574 u64 val = hash_fields;
1577 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1578 u64 bit = BIT_ULL(i);
1581 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1582 ICE_FLOW_FLD_OFF_INVAL,
1583 ICE_FLOW_FLD_OFF_INVAL,
1584 ICE_FLOW_FLD_OFF_INVAL, false);
1588 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1590 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1591 return ICE_ERR_PARAM;
1593 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1594 if (!ice_is_pow2(val))
1597 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1598 if (val && !ice_is_pow2(val))
1605 * ice_rem_vsi_rss_list - remove VSI from RSS list
1606 * @hw: pointer to the hardware structure
1607 * @vsi_handle: software VSI handle
1609 * Remove the VSI from all RSS configurations in the list.
1611 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1613 struct ice_rss_cfg *r, *tmp;
1615 if (LIST_EMPTY(&hw->rss_list_head))
1618 ice_acquire_lock(&hw->rss_locks);
1619 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1620 ice_rss_cfg, l_entry) {
1621 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1622 ice_clear_bit(vsi_handle, r->vsis);
1624 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1625 LIST_DEL(&r->l_entry);
1630 ice_release_lock(&hw->rss_locks);
1634 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1635 * @hw: pointer to the hardware structure
1636 * @vsi_handle: software VSI handle
1638 * This function will iterate through all flow profiles and disassociate
1639 * the VSI from that profile. If the flow profile has no VSIs it will
1642 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1644 const enum ice_block blk = ICE_BLK_RSS;
1645 struct ice_flow_prof *p, *t;
1646 enum ice_status status = ICE_SUCCESS;
1648 if (!ice_is_vsi_valid(hw, vsi_handle))
1649 return ICE_ERR_PARAM;
1651 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1652 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1654 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1655 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1659 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1660 status = ice_flow_rem_prof_sync(hw, blk, p);
1666 ice_release_lock(&hw->fl_profs_locks[blk]);
1672 * ice_rem_rss_list - remove RSS configuration from list
1673 * @hw: pointer to the hardware structure
1674 * @vsi_handle: software VSI handle
1675 * @prof: pointer to flow profile
1677 * Assumption: lock has already been acquired for RSS list
1680 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1682 struct ice_rss_cfg *r, *tmp;
1684 /* Search for RSS hash fields associated to the VSI that match the
1685 * hash configurations associated to the flow profile. If found
1686 * remove from the RSS entry list of the VSI context and delete entry.
1688 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1689 ice_rss_cfg, l_entry) {
1690 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1691 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1692 ice_clear_bit(vsi_handle, r->vsis);
1693 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1694 LIST_DEL(&r->l_entry);
1703 * ice_add_rss_list - add RSS configuration to list
1704 * @hw: pointer to the hardware structure
1705 * @vsi_handle: software VSI handle
1706 * @prof: pointer to flow profile
1708 * Assumption: lock has already been acquired for RSS list
1710 static enum ice_status
1711 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1713 struct ice_rss_cfg *r, *rss_cfg;
1715 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1716 ice_rss_cfg, l_entry)
1717 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1718 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1719 ice_set_bit(vsi_handle, r->vsis);
1723 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1725 return ICE_ERR_NO_MEMORY;
1727 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1728 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1729 ice_set_bit(vsi_handle, rss_cfg->vsis);
1731 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1736 #define ICE_FLOW_PROF_HASH_S 0
1737 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1738 #define ICE_FLOW_PROF_HDR_S 32
1739 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1741 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1742 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1743 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1746 * ice_add_rss_cfg_sync - add an RSS configuration
1747 * @hw: pointer to the hardware structure
1748 * @vsi_handle: software VSI handle
1749 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1750 * @addl_hdrs: protocol header fields
1752 * Assumption: lock has already been acquired for RSS list
1754 static enum ice_status
1755 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1758 const enum ice_block blk = ICE_BLK_RSS;
1759 struct ice_flow_prof *prof = NULL;
1760 struct ice_flow_seg_info *segs;
1761 enum ice_status status = ICE_SUCCESS;
1763 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1765 return ICE_ERR_NO_MEMORY;
1767 /* Construct the packet segment info from the hashed fields */
1768 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1772 /* Search for a flow profile that has matching headers, hash fields
1773 * and has the input VSI associated to it. If found, no further
1774 * operations required and exit.
1776 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1778 ICE_FLOW_FIND_PROF_CHK_FLDS |
1779 ICE_FLOW_FIND_PROF_CHK_VSI);
1783 /* Check if a flow profile exists with the same protocol headers and
1784 * associated with the input VSI. If so disasscociate the VSI from
1785 * this profile. The VSI will be added to a new profile created with
1786 * the protocol header and new hash field configuration.
1788 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1789 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1791 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1793 ice_rem_rss_list(hw, vsi_handle, prof);
1797 /* Remove profile if it has no VSIs associated */
1798 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1799 status = ice_flow_rem_prof_sync(hw, blk, prof);
1805 /* Search for a profile that has same match fields only. If this
1806 * exists then associate the VSI to this profile.
1808 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1810 ICE_FLOW_FIND_PROF_CHK_FLDS);
1812 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1814 status = ice_add_rss_list(hw, vsi_handle, prof);
1818 /* Create a new flow profile with generated profile and packet
1819 * segment information.
1821 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1822 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1823 segs, 1, NULL, 0, &prof);
1827 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1828 /* If association to a new flow profile failed then this profile can
1832 ice_flow_rem_prof_sync(hw, blk, prof);
1836 status = ice_add_rss_list(hw, vsi_handle, prof);
1844 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1845 * @hw: pointer to the hardware structure
1846 * @vsi_handle: software VSI handle
1847 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1848 * @addl_hdrs: protocol header fields
1850 * This function will generate a flow profile based on fields associated with
1851 * the input fields to hash on, the flow type and use the VSI number to add
1852 * a flow entry to the profile.
1855 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1858 enum ice_status status;
1860 if (hashed_flds == ICE_HASH_INVALID ||
1861 !ice_is_vsi_valid(hw, vsi_handle))
1862 return ICE_ERR_PARAM;
1864 ice_acquire_lock(&hw->rss_locks);
1865 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1866 ice_release_lock(&hw->rss_locks);
1872 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1873 * @hw: pointer to the hardware structure
1874 * @vsi_handle: software VSI handle
1875 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1876 * @addl_hdrs: Protocol header fields within a packet segment
1878 * Assumption: lock has already been acquired for RSS list
1880 static enum ice_status
1881 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1884 const enum ice_block blk = ICE_BLK_RSS;
1885 struct ice_flow_seg_info *segs;
1886 struct ice_flow_prof *prof;
1887 enum ice_status status;
1889 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1891 return ICE_ERR_NO_MEMORY;
1893 /* Construct the packet segment info from the hashed fields */
1894 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1898 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1900 ICE_FLOW_FIND_PROF_CHK_FLDS);
1902 status = ICE_ERR_DOES_NOT_EXIST;
1906 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1910 /* Remove RSS configuration from VSI context before deleting
1913 ice_rem_rss_list(hw, vsi_handle, prof);
1915 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1916 status = ice_flow_rem_prof_sync(hw, blk, prof);
1923 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1924 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1925 * convert its values to their appropriate flow L3, L4 values.
1927 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1928 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1929 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1930 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1931 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1932 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1933 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1934 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1935 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1936 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1937 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1938 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1939 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1941 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1942 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1943 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1944 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1945 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1946 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1947 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1948 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1949 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1950 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1951 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1952 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1953 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1955 #define ICE_FLOW_MAX_CFG 10
1958 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1959 * @hw: pointer to the hardware structure
1960 * @vsi_handle: software VSI handle
1961 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1963 * This function will take the hash bitmap provided by the AVF driver via a
1964 * message, convert it to ICE-compatible values, and configure RSS flow
1968 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1970 enum ice_status status = ICE_SUCCESS;
1973 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1974 !ice_is_vsi_valid(hw, vsi_handle))
1975 return ICE_ERR_PARAM;
1977 /* Make sure no unsupported bits are specified */
1978 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1979 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1982 hash_flds = avf_hash;
1984 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1985 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1986 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1988 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
1989 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
1991 /* Create the corresponding RSS configuration for each valid hash bit */
1993 u64 rss_hash = ICE_HASH_INVALID;
1995 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
1996 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
1997 rss_hash = ICE_FLOW_HASH_IPV4;
1998 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
1999 } else if (hash_flds &
2000 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2001 rss_hash = ICE_FLOW_HASH_IPV4 |
2002 ICE_FLOW_HASH_TCP_PORT;
2003 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2004 } else if (hash_flds &
2005 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2006 rss_hash = ICE_FLOW_HASH_IPV4 |
2007 ICE_FLOW_HASH_UDP_PORT;
2008 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2009 } else if (hash_flds &
2010 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2011 rss_hash = ICE_FLOW_HASH_IPV4 |
2012 ICE_FLOW_HASH_SCTP_PORT;
2014 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2016 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2017 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2018 rss_hash = ICE_FLOW_HASH_IPV6;
2019 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2020 } else if (hash_flds &
2021 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2022 rss_hash = ICE_FLOW_HASH_IPV6 |
2023 ICE_FLOW_HASH_TCP_PORT;
2024 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2025 } else if (hash_flds &
2026 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2027 rss_hash = ICE_FLOW_HASH_IPV6 |
2028 ICE_FLOW_HASH_UDP_PORT;
2029 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2030 } else if (hash_flds &
2031 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2032 rss_hash = ICE_FLOW_HASH_IPV6 |
2033 ICE_FLOW_HASH_SCTP_PORT;
2035 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2039 if (rss_hash == ICE_HASH_INVALID)
2040 return ICE_ERR_OUT_OF_RANGE;
2042 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2043 ICE_FLOW_SEG_HDR_NONE);
2052 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2053 * @hw: pointer to the hardware structure
2054 * @vsi_handle: software VSI handle
2055 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2056 * @addl_hdrs: Protocol header fields within a packet segment
2058 * This function will lookup the flow profile based on the input
2059 * hash field bitmap, iterate through the profile entry list of
2060 * that profile and find entry associated with input VSI to be
2061 * removed. Calls are made to underlying flow apis which will in
2062 * turn build or update buffers for RSS XLT1 section.
2065 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2068 enum ice_status status;
2070 if (hashed_flds == ICE_HASH_INVALID ||
2071 !ice_is_vsi_valid(hw, vsi_handle))
2072 return ICE_ERR_PARAM;
2074 ice_acquire_lock(&hw->rss_locks);
2075 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2076 ice_release_lock(&hw->rss_locks);
2082 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2083 * @hw: pointer to the hardware structure
2084 * @vsi_handle: software VSI handle
2086 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2088 enum ice_status status = ICE_SUCCESS;
2089 struct ice_rss_cfg *r;
2091 if (!ice_is_vsi_valid(hw, vsi_handle))
2092 return ICE_ERR_PARAM;
2094 ice_acquire_lock(&hw->rss_locks);
2095 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2096 ice_rss_cfg, l_entry) {
2097 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2098 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2105 ice_release_lock(&hw->rss_locks);
2111 * ice_get_rss_cfg - returns hashed fields for the given header types
2112 * @hw: pointer to the hardware structure
2113 * @vsi_handle: software VSI handle
2114 * @hdrs: protocol header type
2116 * This function will return the match fields of the first instance of flow
2117 * profile having the given header types and containing input VSI
2119 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2121 struct ice_rss_cfg *r, *rss_cfg = NULL;
2123 /* verify if the protocol header is non zero and VSI is valid */
2124 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2125 return ICE_HASH_INVALID;
2127 ice_acquire_lock(&hw->rss_locks);
2128 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2129 ice_rss_cfg, l_entry)
2130 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2131 r->packet_hdr == hdrs) {
2135 ice_release_lock(&hw->rss_locks);
2137 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;