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
22 #define ICE_FLOW_FLD_SZ_GTP_TEID 4
23 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2
25 /* Protocol header fields are extracted at the word boundaries as word-sized
26 * values. Specify the displacement value of some non-word-aligned fields needed
27 * to compute the offset of words containing the fields in the corresponding
28 * protocol headers. Displacement values are expressed in number of bits.
30 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP (-4)
31 #define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * BITS_PER_BYTE)
32 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
34 /* Describe properties of a protocol header field */
35 struct ice_flow_field_info {
36 enum ice_flow_seg_hdr hdr;
37 s16 off; /* Offset from start of a protocol header, in bits */
38 u16 size; /* Size of fields in bits */
39 u16 mask; /* 16-bit mask for field */
42 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
44 .off = (_offset_bytes) * BITS_PER_BYTE, \
45 .size = (_size_bytes) * BITS_PER_BYTE, \
49 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
51 .off = (_offset_bytes) * BITS_PER_BYTE, \
52 .size = (_size_bytes) * BITS_PER_BYTE, \
56 /* Table containing properties of supported protocol header fields */
58 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
60 /* ICE_FLOW_FIELD_IDX_ETH_DA */
61 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
62 /* ICE_FLOW_FIELD_IDX_ETH_SA */
63 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
64 /* ICE_FLOW_FIELD_IDX_S_VLAN */
65 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
66 /* ICE_FLOW_FIELD_IDX_C_VLAN */
67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
68 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
71 /* ICE_FLOW_FIELD_IDX_IP_DSCP */
72 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
73 /* ICE_FLOW_FIELD_IDX_IP_TTL */
74 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
75 /* ICE_FLOW_FIELD_IDX_IP_PROT */
76 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
77 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
78 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
79 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
80 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
82 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
83 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
84 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
85 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
87 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
88 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
89 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
90 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
91 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
93 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
95 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
97 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
99 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
102 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
104 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
105 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
106 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
107 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
108 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
109 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
110 /* ICE_FLOW_FIELD_IDX_ARP_OP */
111 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
113 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
114 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
115 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
116 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
118 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
121 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
122 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
123 ICE_FLOW_FLD_SZ_GTP_TEID),
124 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
126 ICE_FLOW_FLD_SZ_GTP_TEID),
127 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
128 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
129 ICE_FLOW_FLD_SZ_GTP_TEID),
130 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
132 ICE_FLOW_FLD_SZ_GTP_TEID),
134 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
135 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
136 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
139 /* Bitmaps indicating relevant packet types for a particular protocol header
141 * Packet types for packets with an Outer/First/Single MAC header
143 static const u32 ice_ptypes_mac_ofos[] = {
144 0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
145 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
146 0x000B0F0F, 0x00000000, 0x00000000, 0x00000000,
147 0x00000000, 0x00000000, 0x00000000, 0x00000000,
148 0x00000000, 0x00000000, 0x00000000, 0x00000000,
149 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 0x00000000, 0x00000000, 0x00000000, 0x00000000,
151 0x00000000, 0x00000000, 0x00000000, 0x00000000,
154 /* Packet types for packets with an Innermost/Last MAC VLAN header */
155 static const u32 ice_ptypes_macvlan_il[] = {
156 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
157 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 0x00000000, 0x00000000, 0x00000000, 0x00000000,
163 0x00000000, 0x00000000, 0x00000000, 0x00000000,
166 /* Packet types for packets with an Outer/First/Single IPv4 header */
167 static const u32 ice_ptypes_ipv4_ofos[] = {
168 0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
169 0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 0x0003000F, 0x00000000, 0x00000000, 0x00000000,
171 0x00000000, 0x00000000, 0x00000000, 0x00000000,
172 0x00000000, 0x00000000, 0x00000000, 0x00000000,
173 0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 0x00000000, 0x00000000, 0x00000000, 0x00000000,
178 /* Packet types for packets with an Innermost/Last IPv4 header */
179 static const u32 ice_ptypes_ipv4_il[] = {
180 0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
181 0x0007700E, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 0x00000000, 0x00000000, 0x00000000, 0x00000000,
187 0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 /* Packet types for packets with an Outer/First/Single IPv6 header */
191 static const u32 ice_ptypes_ipv6_ofos[] = {
192 0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
193 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
194 0x00080F00, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 0x00000000, 0x00000000, 0x00000000, 0x00000000,
199 0x00000000, 0x00000000, 0x00000000, 0x00000000,
202 /* Packet types for packets with an Innermost/Last IPv6 header */
203 static const u32 ice_ptypes_ipv6_il[] = {
204 0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
205 0x03B80770, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x00000000, 0x00000000,
207 0x00000000, 0x00000000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 0x00000000, 0x00000000, 0x00000000, 0x00000000,
214 /* Packet types for packets with an Outermost/First ARP header */
215 static const u32 ice_ptypes_arp_of[] = {
216 0x00000800, 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,
222 0x00000000, 0x00000000, 0x00000000, 0x00000000,
223 0x00000000, 0x00000000, 0x00000000, 0x00000000,
226 /* UDP Packet types for non-tunneled packets or tunneled
227 * packets with inner UDP.
229 static const u32 ice_ptypes_udp_il[] = {
230 0x81000000, 0x20204040, 0x04081010, 0x80810102,
231 0x00204040, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 0x00000000, 0x00000000, 0x00000000,
233 0x00000000, 0x00000000, 0x00000000, 0x00000000,
234 0x00000000, 0x00000000, 0x00000000, 0x00000000,
235 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 0x00000000, 0x00000000, 0x00000000, 0x00000000,
237 0x00000000, 0x00000000, 0x00000000, 0x00000000,
240 /* Packet types for packets with an Innermost/Last TCP header */
241 static const u32 ice_ptypes_tcp_il[] = {
242 0x04000000, 0x80810102, 0x10204040, 0x42040408,
243 0x00810102, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 0x00000000, 0x00000000, 0x00000000, 0x00000000,
247 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 0x00000000, 0x00000000, 0x00000000, 0x00000000,
252 /* Packet types for packets with an Innermost/Last SCTP header */
253 static const u32 ice_ptypes_sctp_il[] = {
254 0x08000000, 0x01020204, 0x20408081, 0x04080810,
255 0x01020204, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 0x00000000, 0x00000000, 0x00000000, 0x00000000,
264 /* Packet types for packets with an Outermost/First ICMP header */
265 static const u32 ice_ptypes_icmp_of[] = {
266 0x10000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 0x00000000, 0x00000000, 0x00000000, 0x00000000,
273 0x00000000, 0x00000000, 0x00000000, 0x00000000,
276 /* Packet types for packets with an Innermost/Last ICMP header */
277 static const u32 ice_ptypes_icmp_il[] = {
278 0x00000000, 0x02040408, 0x40810102, 0x08101020,
279 0x02040408, 0x00000000, 0x00000000, 0x00000000,
280 0x00000000, 0x00000000, 0x00000000, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000,
288 /* Packet types for packets with an Outermost/First GRE header */
289 static const u32 ice_ptypes_gre_of[] = {
290 0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
291 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
292 0x00000000, 0x00000000, 0x00000000, 0x00000000,
293 0x00000000, 0x00000000, 0x00000000, 0x00000000,
294 0x00000000, 0x00000000, 0x00000000, 0x00000000,
295 0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 /* Packet types for packets with an Innermost/Last MAC header */
301 static const u32 ice_ptypes_mac_il[] = {
302 0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
303 0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
304 0x00000000, 0x00000000, 0x00000000, 0x00000000,
305 0x00000000, 0x00000000, 0x00000000, 0x00000000,
306 0x00000000, 0x00000000, 0x00000000, 0x00000000,
307 0x00000000, 0x00000000, 0x00000000, 0x00000000,
308 0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 /* Packet types for GTPC */
313 static const u32 ice_ptypes_gtpc[] = {
314 0x00000000, 0x00000000, 0x00000000, 0x00000000,
315 0x00000000, 0x00000000, 0x00000000, 0x00000000,
316 0x00000000, 0x00000000, 0x00000180, 0x00000000,
317 0x00000000, 0x00000000, 0x00000000, 0x00000000,
318 0x00000000, 0x00000000, 0x00000000, 0x00000000,
319 0x00000000, 0x00000000, 0x00000000, 0x00000000,
320 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 /* Packet types for GTPC with TEID */
325 static const u32 ice_ptypes_gtpc_tid[] = {
326 0x00000000, 0x00000000, 0x00000000, 0x00000000,
327 0x00000000, 0x00000000, 0x00000000, 0x00000000,
328 0x00000000, 0x00000000, 0x00000060, 0x00000000,
329 0x00000000, 0x00000000, 0x00000000, 0x00000000,
330 0x00000000, 0x00000000, 0x00000000, 0x00000000,
331 0x00000000, 0x00000000, 0x00000000, 0x00000000,
332 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 /* Packet types for GTPU */
337 static const u32 ice_ptypes_gtpu[] = {
338 0x00000000, 0x00000000, 0x00000000, 0x00000000,
339 0x00000000, 0x00000000, 0x00000000, 0x00000000,
340 0x00000000, 0x00000000, 0x7FFFF800, 0x00000000,
341 0x00000000, 0x00000000, 0x00000000, 0x00000000,
342 0x00000000, 0x00000000, 0x00000000, 0x00000000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 0x00000000, 0x00000000, 0x00000000, 0x00000000,
348 /* Manage parameters and info. used during the creation of a flow profile */
349 struct ice_flow_prof_params {
351 u16 entry_length; /* # of bytes formatted entry will require */
353 struct ice_flow_prof *prof;
355 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
356 * This will give us the direction flags.
358 struct ice_fv_word es[ICE_MAX_FV_WORDS];
359 u16 mask[ICE_MAX_FV_WORDS];
360 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
363 #define ICE_FLOW_SEG_HDRS_L2_MASK \
364 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
365 #define ICE_FLOW_SEG_HDRS_L3_MASK \
366 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
367 ICE_FLOW_SEG_HDR_ARP | ICE_FLOW_SEG_HDR_PPPOE)
368 #define ICE_FLOW_SEG_HDRS_L4_MASK \
369 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
370 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC | \
371 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU_IP | \
372 ICE_FLOW_SEG_HDR_GTPU_UP | ICE_FLOW_SEG_HDR_GTPU_DWN)
375 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
376 * @segs: array of one or more packet segments that describe the flow
377 * @segs_cnt: number of packet segments provided
379 static enum ice_status
380 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
382 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
383 ICE_FLOW_SEG_HDRS_L3_MASK |
384 ICE_FLOW_SEG_HDRS_L4_MASK);
387 for (i = 0; i < segs_cnt; i++) {
388 /* No header specified */
389 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
390 return ICE_ERR_PARAM;
392 /* Multiple L3 headers */
393 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
394 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
395 return ICE_ERR_PARAM;
397 /* Multiple L4 headers */
398 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
399 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
400 return ICE_ERR_PARAM;
406 /* Sizes of fixed known protocol headers without header options */
407 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
408 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
409 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
410 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
411 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
412 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
413 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
414 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
415 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
418 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
419 * @params: information about the flow to be processed
420 * @seg: index of packet segment whose header size is to be determined
422 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
427 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
428 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
431 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
432 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
433 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
434 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
435 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
436 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
437 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
438 /* A L3 header is required if L4 is specified */
442 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
443 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
444 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
445 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
446 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
447 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
448 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
449 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
455 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
456 * @params: information about the flow to be processed
458 * This function identifies the packet types associated with the protocol
459 * headers being present in packet segments of the specified flow profile.
461 static enum ice_status
462 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
464 struct ice_flow_prof *prof;
467 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
472 for (i = 0; i < params->prof->segs_cnt; i++) {
473 const ice_bitmap_t *src;
476 hdrs = prof->segs[i].hdrs;
478 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
479 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
480 (const ice_bitmap_t *)ice_ptypes_mac_il;
481 ice_and_bitmap(params->ptypes, params->ptypes, src,
485 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
486 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
487 ice_and_bitmap(params->ptypes, params->ptypes, src,
491 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
492 ice_and_bitmap(params->ptypes, params->ptypes,
493 (const ice_bitmap_t *)ice_ptypes_arp_of,
497 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
498 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
499 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
500 ice_and_bitmap(params->ptypes, params->ptypes, src,
502 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
503 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
504 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
505 ice_and_bitmap(params->ptypes, params->ptypes, src,
509 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
510 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
511 (const ice_bitmap_t *)ice_ptypes_icmp_il;
512 ice_and_bitmap(params->ptypes, params->ptypes, src,
514 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
515 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
516 ice_and_bitmap(params->ptypes, params->ptypes, src,
518 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
519 ice_and_bitmap(params->ptypes, params->ptypes,
520 (const ice_bitmap_t *)ice_ptypes_tcp_il,
522 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
523 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
524 ice_and_bitmap(params->ptypes, params->ptypes, src,
526 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
528 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
529 ice_and_bitmap(params->ptypes, params->ptypes,
530 src, ICE_FLOW_PTYPE_MAX);
532 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
534 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
535 ice_and_bitmap(params->ptypes, params->ptypes,
536 src, ICE_FLOW_PTYPE_MAX);
538 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
540 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
541 ice_and_bitmap(params->ptypes, params->ptypes,
542 src, ICE_FLOW_PTYPE_MAX);
544 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
546 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
547 ice_and_bitmap(params->ptypes, params->ptypes,
548 src, ICE_FLOW_PTYPE_MAX);
557 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
558 * @hw: pointer to the HW struct
559 * @params: information about the flow to be processed
560 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
562 * This function will allocate an extraction sequence entries for a DWORD size
563 * chunk of the packet flags.
565 static enum ice_status
566 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
567 struct ice_flow_prof_params *params,
568 enum ice_flex_mdid_pkt_flags flags)
570 u8 fv_words = hw->blk[params->blk].es.fvw;
573 /* Make sure the number of extraction sequence entries required does not
574 * exceed the block's capacity.
576 if (params->es_cnt >= fv_words)
577 return ICE_ERR_MAX_LIMIT;
579 /* some blocks require a reversed field vector layout */
580 if (hw->blk[params->blk].es.reverse)
581 idx = fv_words - params->es_cnt - 1;
583 idx = params->es_cnt;
585 params->es[idx].prot_id = ICE_PROT_META_ID;
586 params->es[idx].off = flags;
593 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
594 * @hw: pointer to the HW struct
595 * @params: information about the flow to be processed
596 * @seg: packet segment index of the field to be extracted
597 * @fld: ID of field to be extracted
599 * This function determines the protocol ID, offset, and size of the given
600 * field. It then allocates one or more extraction sequence entries for the
601 * given field, and fill the entries with protocol ID and offset information.
603 static enum ice_status
604 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
605 u8 seg, enum ice_flow_field fld)
607 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
608 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
609 u8 fv_words = hw->blk[params->blk].es.fvw;
610 struct ice_flow_fld_info *flds;
611 u16 cnt, ese_bits, i;
616 flds = params->prof->segs[seg].fields;
619 case ICE_FLOW_FIELD_IDX_ETH_DA:
620 case ICE_FLOW_FIELD_IDX_ETH_SA:
621 case ICE_FLOW_FIELD_IDX_S_VLAN:
622 case ICE_FLOW_FIELD_IDX_C_VLAN:
623 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
625 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
626 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
628 case ICE_FLOW_FIELD_IDX_IP_DSCP:
629 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
630 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
632 case ICE_FLOW_FIELD_IDX_IP_TTL:
633 case ICE_FLOW_FIELD_IDX_IP_PROT:
634 /* Some fields are located at different offsets in IPv4 and
637 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
638 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
640 /* TTL and PROT share the same extraction seq. entry.
641 * Each is considered a sibling to the other in term
642 * sharing the same extraction sequence entry.
644 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
645 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
646 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
647 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
648 } else if (params->prof->segs[seg].hdrs &
649 ICE_FLOW_SEG_HDR_IPV6) {
650 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
652 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
653 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
654 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
655 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
658 case ICE_FLOW_FIELD_IDX_IPV4_SA:
659 case ICE_FLOW_FIELD_IDX_IPV4_DA:
660 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
662 case ICE_FLOW_FIELD_IDX_IPV6_SA:
663 case ICE_FLOW_FIELD_IDX_IPV6_DA:
664 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
666 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
667 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
668 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
669 prot_id = ICE_PROT_TCP_IL;
671 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
672 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
673 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
675 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
676 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
677 prot_id = ICE_PROT_SCTP_IL;
679 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
680 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
681 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
682 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
683 /* GTP is accessed through UDP OF protocol */
684 prot_id = ICE_PROT_UDP_OF;
686 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
687 prot_id = ICE_PROT_PPPOE;
689 case ICE_FLOW_FIELD_IDX_ARP_SIP:
690 case ICE_FLOW_FIELD_IDX_ARP_DIP:
691 case ICE_FLOW_FIELD_IDX_ARP_SHA:
692 case ICE_FLOW_FIELD_IDX_ARP_DHA:
693 case ICE_FLOW_FIELD_IDX_ARP_OP:
694 prot_id = ICE_PROT_ARP_OF;
696 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
697 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
698 /* ICMP type and code share the same extraction seq. entry */
699 prot_id = (params->prof->segs[seg].hdrs &
700 ICE_FLOW_SEG_HDR_IPV4) ?
701 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
702 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
703 ICE_FLOW_FIELD_IDX_ICMP_CODE :
704 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
706 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
707 prot_id = ICE_PROT_GRE_OF;
710 return ICE_ERR_NOT_IMPL;
713 /* Each extraction sequence entry is a word in size, and extracts a
714 * word-aligned offset from a protocol header.
716 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
718 flds[fld].xtrct.prot_id = prot_id;
719 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
720 ICE_FLOW_FV_EXTRACT_SZ;
721 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
722 flds[fld].xtrct.idx = params->es_cnt;
724 /* Adjust the next field-entry index after accommodating the number of
725 * entries this field consumes
727 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
728 ice_flds_info[fld].size, ese_bits);
730 /* Fill in the extraction sequence entries needed for this field */
731 off = flds[fld].xtrct.off;
732 mask = ice_flds_info[fld].mask;
733 for (i = 0; i < cnt; i++) {
734 /* Only consume an extraction sequence entry if there is no
735 * sibling field associated with this field or the sibling entry
736 * already extracts the word shared with this field.
738 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
739 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
740 flds[sib].xtrct.off != off) {
743 /* Make sure the number of extraction sequence required
744 * does not exceed the block's capability
746 if (params->es_cnt >= fv_words)
747 return ICE_ERR_MAX_LIMIT;
749 /* some blocks require a reversed field vector layout */
750 if (hw->blk[params->blk].es.reverse)
751 idx = fv_words - params->es_cnt - 1;
753 idx = params->es_cnt;
755 params->es[idx].prot_id = prot_id;
756 params->es[idx].off = off;
757 params->mask[idx] = mask;
761 off += ICE_FLOW_FV_EXTRACT_SZ;
768 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
769 * @hw: pointer to the HW struct
770 * @params: information about the flow to be processed
771 * @seg: index of packet segment whose raw fields are to be be extracted
773 static enum ice_status
774 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
780 if (!params->prof->segs[seg].raws_cnt)
783 if (params->prof->segs[seg].raws_cnt >
784 ARRAY_SIZE(params->prof->segs[seg].raws))
785 return ICE_ERR_MAX_LIMIT;
787 /* Offsets within the segment headers are not supported */
788 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
790 return ICE_ERR_PARAM;
792 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
793 struct ice_flow_seg_fld_raw *raw;
796 raw = ¶ms->prof->segs[seg].raws[i];
798 /* Only support matching raw fields in the payload */
799 if (raw->off < hdrs_sz)
800 return ICE_ERR_PARAM;
802 /* Convert the segment-relative offset into payload-relative
805 off = raw->off - hdrs_sz;
807 /* Storing extraction information */
808 raw->info.xtrct.prot_id = ICE_PROT_PAY;
809 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
810 ICE_FLOW_FV_EXTRACT_SZ;
811 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
813 raw->info.xtrct.idx = params->es_cnt;
815 /* Determine the number of field vector entries this raw field
818 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
819 (raw->info.src.last * BITS_PER_BYTE),
820 (ICE_FLOW_FV_EXTRACT_SZ *
822 off = raw->info.xtrct.off;
823 for (j = 0; j < cnt; j++) {
824 /* Make sure the number of extraction sequence required
825 * does not exceed the block's capability
827 if (params->es_cnt >= hw->blk[params->blk].es.count ||
828 params->es_cnt >= ICE_MAX_FV_WORDS)
829 return ICE_ERR_MAX_LIMIT;
831 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
832 params->es[params->es_cnt].off = off;
834 off += ICE_FLOW_FV_EXTRACT_SZ;
842 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
843 * @hw: pointer to the HW struct
844 * @params: information about the flow to be processed
846 * This function iterates through all matched fields in the given segments, and
847 * creates an extraction sequence for the fields.
849 static enum ice_status
850 ice_flow_create_xtrct_seq(struct ice_hw *hw,
851 struct ice_flow_prof_params *params)
853 enum ice_status status = ICE_SUCCESS;
856 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
859 if (params->blk == ICE_BLK_ACL)
860 ice_flow_xtract_pkt_flags(hw, params,
861 ICE_RX_MDID_PKT_FLAGS_15_0);
863 for (i = 0; i < params->prof->segs_cnt; i++) {
864 u64 match = params->prof->segs[i].match;
867 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
868 const u64 bit = BIT_ULL(j);
871 status = ice_flow_xtract_fld
872 (hw, params, i, (enum ice_flow_field)j);
879 /* Process raw matching bytes */
880 status = ice_flow_xtract_raws(hw, params, i);
889 * ice_flow_proc_segs - process all packet segments associated with a profile
890 * @hw: pointer to the HW struct
891 * @params: information about the flow to be processed
893 static enum ice_status
894 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
896 enum ice_status status;
898 status = ice_flow_proc_seg_hdrs(params);
902 status = ice_flow_create_xtrct_seq(hw, params);
906 switch (params->blk) {
908 /* Only header information is provided for RSS configuration.
909 * No further processing is needed.
911 status = ICE_SUCCESS;
914 status = ICE_SUCCESS;
918 return ICE_ERR_NOT_IMPL;
924 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
925 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
926 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
929 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
930 * @hw: pointer to the HW struct
931 * @blk: classification stage
932 * @dir: flow direction
933 * @segs: array of one or more packet segments that describe the flow
934 * @segs_cnt: number of packet segments provided
935 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
936 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
938 static struct ice_flow_prof *
939 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
940 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
941 u8 segs_cnt, u16 vsi_handle, u32 conds)
943 struct ice_flow_prof *p, *prof = NULL;
945 ice_acquire_lock(&hw->fl_profs_locks[blk]);
946 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
947 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
948 segs_cnt && segs_cnt == p->segs_cnt) {
951 /* Check for profile-VSI association if specified */
952 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
953 ice_is_vsi_valid(hw, vsi_handle) &&
954 !ice_is_bit_set(p->vsis, vsi_handle))
957 /* Protocol headers must be checked. Matched fields are
958 * checked if specified.
960 for (i = 0; i < segs_cnt; i++)
961 if (segs[i].hdrs != p->segs[i].hdrs ||
962 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
963 segs[i].match != p->segs[i].match))
966 /* A match is found if all segments are matched */
973 ice_release_lock(&hw->fl_profs_locks[blk]);
979 * ice_flow_find_prof - Look up a profile matching headers and matched fields
980 * @hw: pointer to the HW struct
981 * @blk: classification stage
982 * @dir: flow direction
983 * @segs: array of one or more packet segments that describe the flow
984 * @segs_cnt: number of packet segments provided
987 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
988 struct ice_flow_seg_info *segs, u8 segs_cnt)
990 struct ice_flow_prof *p;
992 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
993 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
995 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
999 * ice_flow_find_prof_id - Look up a profile with given profile ID
1000 * @hw: pointer to the HW struct
1001 * @blk: classification stage
1002 * @prof_id: unique ID to identify this flow profile
1004 static struct ice_flow_prof *
1005 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1007 struct ice_flow_prof *p;
1009 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1010 if (p->id == prof_id)
1018 * ice_dealloc_flow_entry - Deallocate flow entry memory
1019 * @hw: pointer to the HW struct
1020 * @entry: flow entry to be removed
1023 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1029 ice_free(hw, entry->entry);
1032 ice_free(hw, entry->acts);
1034 entry->acts_cnt = 0;
1037 ice_free(hw, entry);
1041 * ice_flow_rem_entry_sync - Remove a flow entry
1042 * @hw: pointer to the HW struct
1043 * @entry: flow entry to be removed
1045 static enum ice_status
1046 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1049 return ICE_ERR_BAD_PTR;
1051 LIST_DEL(&entry->l_entry);
1053 ice_dealloc_flow_entry(hw, entry);
1059 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1060 * @hw: pointer to the HW struct
1061 * @blk: classification stage
1062 * @dir: flow direction
1063 * @prof_id: unique ID to identify this flow profile
1064 * @segs: array of one or more packet segments that describe the flow
1065 * @segs_cnt: number of packet segments provided
1066 * @acts: array of default actions
1067 * @acts_cnt: number of default actions
1068 * @prof: stores the returned flow profile added
1070 * Assumption: the caller has acquired the lock to the profile list
1072 static enum ice_status
1073 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1074 enum ice_flow_dir dir, u64 prof_id,
1075 struct ice_flow_seg_info *segs, u8 segs_cnt,
1076 struct ice_flow_action *acts, u8 acts_cnt,
1077 struct ice_flow_prof **prof)
1079 struct ice_flow_prof_params params;
1080 enum ice_status status = ICE_SUCCESS;
1083 if (!prof || (acts_cnt && !acts))
1084 return ICE_ERR_BAD_PTR;
1086 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1087 params.prof = (struct ice_flow_prof *)
1088 ice_malloc(hw, sizeof(*params.prof));
1090 return ICE_ERR_NO_MEMORY;
1092 /* initialize extraction sequence to all invalid (0xff) */
1093 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1094 params.es[i].prot_id = ICE_PROT_INVALID;
1095 params.es[i].off = ICE_FV_OFFSET_INVAL;
1099 params.prof->id = prof_id;
1100 params.prof->dir = dir;
1101 params.prof->segs_cnt = segs_cnt;
1103 /* Make a copy of the segments that need to be persistent in the flow
1106 for (i = 0; i < segs_cnt; i++)
1107 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1108 ICE_NONDMA_TO_NONDMA);
1110 /* Make a copy of the actions that need to be persistent in the flow
1114 params.prof->acts = (struct ice_flow_action *)
1115 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1116 ICE_NONDMA_TO_NONDMA);
1118 if (!params.prof->acts) {
1119 status = ICE_ERR_NO_MEMORY;
1124 status = ice_flow_proc_segs(hw, ¶ms);
1126 ice_debug(hw, ICE_DBG_FLOW,
1127 "Error processing a flow's packet segments\n");
1131 /* Add a HW profile for this flow profile */
1132 status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1133 params.es, params.mask);
1135 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1139 INIT_LIST_HEAD(¶ms.prof->entries);
1140 ice_init_lock(¶ms.prof->entries_lock);
1141 *prof = params.prof;
1145 if (params.prof->acts)
1146 ice_free(hw, params.prof->acts);
1147 ice_free(hw, params.prof);
1154 * ice_flow_rem_prof_sync - remove a flow profile
1155 * @hw: pointer to the hardware structure
1156 * @blk: classification stage
1157 * @prof: pointer to flow profile to remove
1159 * Assumption: the caller has acquired the lock to the profile list
1161 static enum ice_status
1162 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1163 struct ice_flow_prof *prof)
1165 enum ice_status status = ICE_SUCCESS;
1167 /* Remove all remaining flow entries before removing the flow profile */
1168 if (!LIST_EMPTY(&prof->entries)) {
1169 struct ice_flow_entry *e, *t;
1171 ice_acquire_lock(&prof->entries_lock);
1173 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1175 status = ice_flow_rem_entry_sync(hw, e);
1180 ice_release_lock(&prof->entries_lock);
1183 /* Remove all hardware profiles associated with this flow profile */
1184 status = ice_rem_prof(hw, blk, prof->id);
1186 LIST_DEL(&prof->l_entry);
1187 ice_destroy_lock(&prof->entries_lock);
1189 ice_free(hw, prof->acts);
1197 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1198 * @hw: pointer to the hardware structure
1199 * @blk: classification stage
1200 * @vsi_handle: software VSI handle
1201 * @vsig: target VSI group
1203 * Assumption: the caller has already verified that the VSI to
1204 * be added has the same characteristics as the VSIG and will
1205 * thereby have access to all resources added to that VSIG.
1208 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1211 enum ice_status status;
1213 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1214 return ICE_ERR_PARAM;
1216 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1217 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1219 ice_release_lock(&hw->fl_profs_locks[blk]);
1225 * ice_flow_assoc_prof - associate a VSI with a flow profile
1226 * @hw: pointer to the hardware structure
1227 * @blk: classification stage
1228 * @prof: pointer to flow profile
1229 * @vsi_handle: software VSI handle
1231 * Assumption: the caller has acquired the lock to the profile list
1232 * and the software VSI handle has been validated
1234 static enum ice_status
1235 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1236 struct ice_flow_prof *prof, u16 vsi_handle)
1238 enum ice_status status = ICE_SUCCESS;
1240 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1241 status = ice_add_prof_id_flow(hw, blk,
1242 ice_get_hw_vsi_num(hw,
1246 ice_set_bit(vsi_handle, prof->vsis);
1248 ice_debug(hw, ICE_DBG_FLOW,
1249 "HW profile add failed, %d\n",
1257 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1258 * @hw: pointer to the hardware structure
1259 * @blk: classification stage
1260 * @prof: pointer to flow profile
1261 * @vsi_handle: software VSI handle
1263 * Assumption: the caller has acquired the lock to the profile list
1264 * and the software VSI handle has been validated
1266 static enum ice_status
1267 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1268 struct ice_flow_prof *prof, u16 vsi_handle)
1270 enum ice_status status = ICE_SUCCESS;
1272 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1273 status = ice_rem_prof_id_flow(hw, blk,
1274 ice_get_hw_vsi_num(hw,
1278 ice_clear_bit(vsi_handle, prof->vsis);
1280 ice_debug(hw, ICE_DBG_FLOW,
1281 "HW profile remove failed, %d\n",
1289 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1290 * @hw: pointer to the HW struct
1291 * @blk: classification stage
1292 * @dir: flow direction
1293 * @prof_id: unique ID to identify this flow profile
1294 * @segs: array of one or more packet segments that describe the flow
1295 * @segs_cnt: number of packet segments provided
1296 * @acts: array of default actions
1297 * @acts_cnt: number of default actions
1298 * @prof: stores the returned flow profile added
1301 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1302 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1303 struct ice_flow_action *acts, u8 acts_cnt,
1304 struct ice_flow_prof **prof)
1306 enum ice_status status;
1308 if (segs_cnt > ICE_FLOW_SEG_MAX)
1309 return ICE_ERR_MAX_LIMIT;
1312 return ICE_ERR_PARAM;
1315 return ICE_ERR_BAD_PTR;
1317 status = ice_flow_val_hdrs(segs, segs_cnt);
1321 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1323 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1324 acts, acts_cnt, prof);
1326 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1328 ice_release_lock(&hw->fl_profs_locks[blk]);
1334 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1335 * @hw: pointer to the HW struct
1336 * @blk: the block for which the flow profile is to be removed
1337 * @prof_id: unique ID of the flow profile to be removed
1340 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1342 struct ice_flow_prof *prof;
1343 enum ice_status status;
1345 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1347 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1349 status = ICE_ERR_DOES_NOT_EXIST;
1353 /* prof becomes invalid after the call */
1354 status = ice_flow_rem_prof_sync(hw, blk, prof);
1357 ice_release_lock(&hw->fl_profs_locks[blk]);
1363 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1364 * @hw: pointer to the HW struct
1365 * @blk: classification stage
1366 * @prof_id: the profile ID handle
1367 * @hw_prof_id: pointer to variable to receive the HW profile ID
1370 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1373 struct ice_prof_map *map;
1375 map = ice_search_prof_id(hw, blk, prof_id);
1377 *hw_prof_id = map->prof_id;
1381 return ICE_ERR_DOES_NOT_EXIST;
1385 * ice_flow_find_entry - look for a flow entry using its unique ID
1386 * @hw: pointer to the HW struct
1387 * @blk: classification stage
1388 * @entry_id: unique ID to identify this flow entry
1390 * This function looks for the flow entry with the specified unique ID in all
1391 * flow profiles of the specified classification stage. If the entry is found,
1392 * and it returns the handle to the flow entry. Otherwise, it returns
1393 * ICE_FLOW_ENTRY_ID_INVAL.
1395 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1397 struct ice_flow_entry *found = NULL;
1398 struct ice_flow_prof *p;
1400 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1402 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1403 struct ice_flow_entry *e;
1405 ice_acquire_lock(&p->entries_lock);
1406 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1407 if (e->id == entry_id) {
1411 ice_release_lock(&p->entries_lock);
1417 ice_release_lock(&hw->fl_profs_locks[blk]);
1419 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1423 * ice_flow_add_entry - Add a flow entry
1424 * @hw: pointer to the HW struct
1425 * @blk: classification stage
1426 * @prof_id: ID of the profile to add a new flow entry to
1427 * @entry_id: unique ID to identify this flow entry
1428 * @vsi_handle: software VSI handle for the flow entry
1429 * @prio: priority of the flow entry
1430 * @data: pointer to a data buffer containing flow entry's match values/masks
1431 * @acts: arrays of actions to be performed on a match
1432 * @acts_cnt: number of actions
1433 * @entry_h: pointer to buffer that receives the new flow entry's handle
1436 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1437 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1438 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1441 struct ice_flow_prof *prof = NULL;
1442 struct ice_flow_entry *e = NULL;
1443 enum ice_status status = ICE_SUCCESS;
1445 if (acts_cnt && !acts)
1446 return ICE_ERR_PARAM;
1448 /* No flow entry data is expected for RSS */
1449 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1450 return ICE_ERR_BAD_PTR;
1452 if (!ice_is_vsi_valid(hw, vsi_handle))
1453 return ICE_ERR_PARAM;
1455 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1457 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1459 status = ICE_ERR_DOES_NOT_EXIST;
1461 /* Allocate memory for the entry being added and associate
1462 * the VSI to the found flow profile
1464 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1466 status = ICE_ERR_NO_MEMORY;
1468 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1471 ice_release_lock(&hw->fl_profs_locks[blk]);
1476 e->vsi_handle = vsi_handle;
1482 /* RSS will add only one entry per VSI per profile */
1489 status = ICE_ERR_NOT_IMPL;
1493 if (blk != ICE_BLK_ACL) {
1494 /* ACL will handle the entry management */
1495 ice_acquire_lock(&prof->entries_lock);
1496 LIST_ADD(&e->l_entry, &prof->entries);
1497 ice_release_lock(&prof->entries_lock);
1500 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1505 ice_free(hw, e->entry);
1513 * ice_flow_rem_entry - Remove a flow entry
1514 * @hw: pointer to the HW struct
1515 * @entry_h: handle to the flow entry to be removed
1517 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1519 struct ice_flow_entry *entry;
1520 struct ice_flow_prof *prof;
1521 enum ice_status status;
1523 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1524 return ICE_ERR_PARAM;
1526 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1528 /* Retain the pointer to the flow profile as the entry will be freed */
1531 ice_acquire_lock(&prof->entries_lock);
1532 status = ice_flow_rem_entry_sync(hw, entry);
1533 ice_release_lock(&prof->entries_lock);
1539 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1540 * @seg: packet segment the field being set belongs to
1541 * @fld: field to be set
1542 * @type: type of the field
1543 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1544 * entry's input buffer
1545 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1547 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1548 * entry's input buffer
1550 * This helper function stores information of a field being matched, including
1551 * the type of the field and the locations of the value to match, the mask, and
1552 * and the upper-bound value in the start of the input buffer for a flow entry.
1553 * This function should only be used for fixed-size data structures.
1555 * This function also opportunistically determines the protocol headers to be
1556 * present based on the fields being set. Some fields cannot be used alone to
1557 * determine the protocol headers present. Sometimes, fields for particular
1558 * protocol headers are not matched. In those cases, the protocol headers
1559 * must be explicitly set.
1562 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1563 enum ice_flow_fld_match_type type, u16 val_loc,
1564 u16 mask_loc, u16 last_loc)
1566 u64 bit = BIT_ULL(fld);
1569 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1572 seg->fields[fld].type = type;
1573 seg->fields[fld].src.val = val_loc;
1574 seg->fields[fld].src.mask = mask_loc;
1575 seg->fields[fld].src.last = last_loc;
1577 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1581 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1582 * @seg: packet segment the field being set belongs to
1583 * @fld: field to be set
1584 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1585 * entry's input buffer
1586 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1588 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1589 * entry's input buffer
1590 * @range: indicate if field being matched is to be in a range
1592 * This function specifies the locations, in the form of byte offsets from the
1593 * start of the input buffer for a flow entry, from where the value to match,
1594 * the mask value, and upper value can be extracted. These locations are then
1595 * stored in the flow profile. When adding a flow entry associated with the
1596 * flow profile, these locations will be used to quickly extract the values and
1597 * create the content of a match entry. This function should only be used for
1598 * fixed-size data structures.
1601 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1602 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1604 enum ice_flow_fld_match_type t = range ?
1605 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1607 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1611 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1612 * @seg: packet segment the field being set belongs to
1613 * @fld: field to be set
1614 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1615 * entry's input buffer
1616 * @pref_loc: location of prefix value from entry's input buffer
1617 * @pref_sz: size of the location holding the prefix value
1619 * This function specifies the locations, in the form of byte offsets from the
1620 * start of the input buffer for a flow entry, from where the value to match
1621 * and the IPv4 prefix value can be extracted. These locations are then stored
1622 * in the flow profile. When adding flow entries to the associated flow profile,
1623 * these locations can be used to quickly extract the values to create the
1624 * content of a match entry. This function should only be used for fixed-size
1628 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1629 u16 val_loc, u16 pref_loc, u8 pref_sz)
1631 /* For this type of field, the "mask" location is for the prefix value's
1632 * location and the "last" location is for the size of the location of
1635 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1636 pref_loc, (u16)pref_sz);
1640 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1641 * @seg: packet segment the field being set belongs to
1642 * @off: offset of the raw field from the beginning of the segment in bytes
1643 * @len: length of the raw pattern to be matched
1644 * @val_loc: location of the value to match from entry's input buffer
1645 * @mask_loc: location of mask value from entry's input buffer
1647 * This function specifies the offset of the raw field to be match from the
1648 * beginning of the specified packet segment, and the locations, in the form of
1649 * byte offsets from the start of the input buffer for a flow entry, from where
1650 * the value to match and the mask value to be extracted. These locations are
1651 * then stored in the flow profile. When adding flow entries to the associated
1652 * flow profile, these locations can be used to quickly extract the values to
1653 * create the content of a match entry. This function should only be used for
1654 * fixed-size data structures.
1657 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1658 u16 val_loc, u16 mask_loc)
1660 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1661 seg->raws[seg->raws_cnt].off = off;
1662 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1663 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1664 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1665 /* The "last" field is used to store the length of the field */
1666 seg->raws[seg->raws_cnt].info.src.last = len;
1669 /* Overflows of "raws" will be handled as an error condition later in
1670 * the flow when this information is processed.
1675 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1676 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE)
1678 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1679 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1680 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC_TEID)
1683 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1684 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1685 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1688 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1689 * @segs: pointer to the flow field segment(s)
1690 * @hash_fields: fields to be hashed on for the segment(s)
1691 * @flow_hdr: protocol header fields within a packet segment
1693 * Helper function to extract fields from hash bitmap and use flow
1694 * header value to set flow field segment for further use in flow
1695 * profile entry or removal.
1697 static enum ice_status
1698 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1701 u64 val = hash_fields;
1704 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1705 u64 bit = BIT_ULL(i);
1708 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1709 ICE_FLOW_FLD_OFF_INVAL,
1710 ICE_FLOW_FLD_OFF_INVAL,
1711 ICE_FLOW_FLD_OFF_INVAL, false);
1715 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1717 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1718 return ICE_ERR_PARAM;
1720 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1721 if (!ice_is_pow2(val))
1724 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1725 if (val && !ice_is_pow2(val))
1732 * ice_rem_vsi_rss_list - remove VSI from RSS list
1733 * @hw: pointer to the hardware structure
1734 * @vsi_handle: software VSI handle
1736 * Remove the VSI from all RSS configurations in the list.
1738 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1740 struct ice_rss_cfg *r, *tmp;
1742 if (LIST_EMPTY(&hw->rss_list_head))
1745 ice_acquire_lock(&hw->rss_locks);
1746 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1747 ice_rss_cfg, l_entry) {
1748 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1749 ice_clear_bit(vsi_handle, r->vsis);
1751 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1752 LIST_DEL(&r->l_entry);
1757 ice_release_lock(&hw->rss_locks);
1761 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1762 * @hw: pointer to the hardware structure
1763 * @vsi_handle: software VSI handle
1765 * This function will iterate through all flow profiles and disassociate
1766 * the VSI from that profile. If the flow profile has no VSIs it will
1769 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1771 const enum ice_block blk = ICE_BLK_RSS;
1772 struct ice_flow_prof *p, *t;
1773 enum ice_status status = ICE_SUCCESS;
1775 if (!ice_is_vsi_valid(hw, vsi_handle))
1776 return ICE_ERR_PARAM;
1778 if (LIST_EMPTY(&hw->fl_profs[blk]))
1781 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1782 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1784 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1785 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1789 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1790 status = ice_flow_rem_prof_sync(hw, blk, p);
1796 ice_release_lock(&hw->fl_profs_locks[blk]);
1802 * ice_rem_rss_list - remove RSS configuration from list
1803 * @hw: pointer to the hardware structure
1804 * @vsi_handle: software VSI handle
1805 * @prof: pointer to flow profile
1807 * Assumption: lock has already been acquired for RSS list
1810 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1812 struct ice_rss_cfg *r, *tmp;
1814 /* Search for RSS hash fields associated to the VSI that match the
1815 * hash configurations associated to the flow profile. If found
1816 * remove from the RSS entry list of the VSI context and delete entry.
1818 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1819 ice_rss_cfg, l_entry) {
1820 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1821 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1822 ice_clear_bit(vsi_handle, r->vsis);
1823 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1824 LIST_DEL(&r->l_entry);
1833 * ice_add_rss_list - add RSS configuration to list
1834 * @hw: pointer to the hardware structure
1835 * @vsi_handle: software VSI handle
1836 * @prof: pointer to flow profile
1838 * Assumption: lock has already been acquired for RSS list
1840 static enum ice_status
1841 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1843 struct ice_rss_cfg *r, *rss_cfg;
1845 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1846 ice_rss_cfg, l_entry)
1847 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1848 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1849 ice_set_bit(vsi_handle, r->vsis);
1853 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1855 return ICE_ERR_NO_MEMORY;
1857 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1858 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1859 ice_set_bit(vsi_handle, rss_cfg->vsis);
1861 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1866 #define ICE_FLOW_PROF_HASH_S 0
1867 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1868 #define ICE_FLOW_PROF_HDR_S 32
1869 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1871 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1872 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1873 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1876 * ice_add_rss_cfg_sync - add an RSS configuration
1877 * @hw: pointer to the hardware structure
1878 * @vsi_handle: software VSI handle
1879 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1880 * @addl_hdrs: protocol header fields
1882 * Assumption: lock has already been acquired for RSS list
1884 static enum ice_status
1885 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1888 const enum ice_block blk = ICE_BLK_RSS;
1889 struct ice_flow_prof *prof = NULL;
1890 struct ice_flow_seg_info *segs;
1891 enum ice_status status = ICE_SUCCESS;
1893 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1895 return ICE_ERR_NO_MEMORY;
1897 /* Construct the packet segment info from the hashed fields */
1898 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1902 /* Search for a flow profile that has matching headers, hash fields
1903 * and has the input VSI associated to it. If found, no further
1904 * operations required and exit.
1906 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1908 ICE_FLOW_FIND_PROF_CHK_FLDS |
1909 ICE_FLOW_FIND_PROF_CHK_VSI);
1913 /* Check if a flow profile exists with the same protocol headers and
1914 * associated with the input VSI. If so disasscociate the VSI from
1915 * this profile. The VSI will be added to a new profile created with
1916 * the protocol header and new hash field configuration.
1918 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1919 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1921 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1923 ice_rem_rss_list(hw, vsi_handle, prof);
1927 /* Remove profile if it has no VSIs associated */
1928 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1929 status = ice_flow_rem_prof(hw, blk, prof->id);
1935 /* Search for a profile that has same match fields only. If this
1936 * exists then associate the VSI to this profile.
1938 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1940 ICE_FLOW_FIND_PROF_CHK_FLDS);
1942 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1944 status = ice_add_rss_list(hw, vsi_handle, prof);
1948 /* Create a new flow profile with generated profile and packet
1949 * segment information.
1951 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1952 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1953 segs, 1, NULL, 0, &prof);
1957 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1958 /* If association to a new flow profile failed then this profile can
1962 ice_flow_rem_prof(hw, blk, prof->id);
1966 status = ice_add_rss_list(hw, vsi_handle, prof);
1974 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1975 * @hw: pointer to the hardware structure
1976 * @vsi_handle: software VSI handle
1977 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1978 * @addl_hdrs: protocol header fields
1980 * This function will generate a flow profile based on fields associated with
1981 * the input fields to hash on, the flow type and use the VSI number to add
1982 * a flow entry to the profile.
1985 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1988 enum ice_status status;
1990 if (hashed_flds == ICE_HASH_INVALID ||
1991 !ice_is_vsi_valid(hw, vsi_handle))
1992 return ICE_ERR_PARAM;
1994 ice_acquire_lock(&hw->rss_locks);
1995 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1996 ice_release_lock(&hw->rss_locks);
2002 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2003 * @hw: pointer to the hardware structure
2004 * @vsi_handle: software VSI handle
2005 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2006 * @addl_hdrs: Protocol header fields within a packet segment
2008 * Assumption: lock has already been acquired for RSS list
2010 static enum ice_status
2011 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2014 const enum ice_block blk = ICE_BLK_RSS;
2015 struct ice_flow_seg_info *segs;
2016 struct ice_flow_prof *prof;
2017 enum ice_status status;
2019 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
2021 return ICE_ERR_NO_MEMORY;
2023 /* Construct the packet segment info from the hashed fields */
2024 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
2028 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
2030 ICE_FLOW_FIND_PROF_CHK_FLDS);
2032 status = ICE_ERR_DOES_NOT_EXIST;
2036 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2040 /* Remove RSS configuration from VSI context before deleting
2043 ice_rem_rss_list(hw, vsi_handle, prof);
2045 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2046 status = ice_flow_rem_prof(hw, blk, prof->id);
2053 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2054 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2055 * convert its values to their appropriate flow L3, L4 values.
2057 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2058 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2059 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2060 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2061 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2062 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2063 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2064 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2065 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2066 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2067 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2068 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2069 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2071 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2072 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2073 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2074 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2075 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2076 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2077 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2078 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2079 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2080 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2081 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2082 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2083 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2085 #define ICE_FLOW_MAX_CFG 10
2088 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2089 * @hw: pointer to the hardware structure
2090 * @vsi_handle: software VSI handle
2091 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2093 * This function will take the hash bitmap provided by the AVF driver via a
2094 * message, convert it to ICE-compatible values, and configure RSS flow
2098 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2100 enum ice_status status = ICE_SUCCESS;
2103 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2104 !ice_is_vsi_valid(hw, vsi_handle))
2105 return ICE_ERR_PARAM;
2107 /* Make sure no unsupported bits are specified */
2108 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2109 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2112 hash_flds = avf_hash;
2114 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2115 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2116 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2118 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2119 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2121 /* Create the corresponding RSS configuration for each valid hash bit */
2123 u64 rss_hash = ICE_HASH_INVALID;
2125 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2126 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2127 rss_hash = ICE_FLOW_HASH_IPV4;
2128 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2129 } else if (hash_flds &
2130 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2131 rss_hash = ICE_FLOW_HASH_IPV4 |
2132 ICE_FLOW_HASH_TCP_PORT;
2133 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2134 } else if (hash_flds &
2135 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2136 rss_hash = ICE_FLOW_HASH_IPV4 |
2137 ICE_FLOW_HASH_UDP_PORT;
2138 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2139 } else if (hash_flds &
2140 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2141 rss_hash = ICE_FLOW_HASH_IPV4 |
2142 ICE_FLOW_HASH_SCTP_PORT;
2144 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2146 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2147 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2148 rss_hash = ICE_FLOW_HASH_IPV6;
2149 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2150 } else if (hash_flds &
2151 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2152 rss_hash = ICE_FLOW_HASH_IPV6 |
2153 ICE_FLOW_HASH_TCP_PORT;
2154 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2155 } else if (hash_flds &
2156 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2157 rss_hash = ICE_FLOW_HASH_IPV6 |
2158 ICE_FLOW_HASH_UDP_PORT;
2159 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2160 } else if (hash_flds &
2161 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2162 rss_hash = ICE_FLOW_HASH_IPV6 |
2163 ICE_FLOW_HASH_SCTP_PORT;
2165 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2169 if (rss_hash == ICE_HASH_INVALID)
2170 return ICE_ERR_OUT_OF_RANGE;
2172 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2173 ICE_FLOW_SEG_HDR_NONE);
2182 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2183 * @hw: pointer to the hardware structure
2184 * @vsi_handle: software VSI handle
2185 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2186 * @addl_hdrs: Protocol header fields within a packet segment
2188 * This function will lookup the flow profile based on the input
2189 * hash field bitmap, iterate through the profile entry list of
2190 * that profile and find entry associated with input VSI to be
2191 * removed. Calls are made to underlying flow apis which will in
2192 * turn build or update buffers for RSS XLT1 section.
2195 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2198 enum ice_status status;
2200 if (hashed_flds == ICE_HASH_INVALID ||
2201 !ice_is_vsi_valid(hw, vsi_handle))
2202 return ICE_ERR_PARAM;
2204 ice_acquire_lock(&hw->rss_locks);
2205 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2206 ice_release_lock(&hw->rss_locks);
2212 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2213 * @hw: pointer to the hardware structure
2214 * @vsi_handle: software VSI handle
2216 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2218 enum ice_status status = ICE_SUCCESS;
2219 struct ice_rss_cfg *r;
2221 if (!ice_is_vsi_valid(hw, vsi_handle))
2222 return ICE_ERR_PARAM;
2224 ice_acquire_lock(&hw->rss_locks);
2225 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2226 ice_rss_cfg, l_entry) {
2227 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2228 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2235 ice_release_lock(&hw->rss_locks);
2241 * ice_get_rss_cfg - returns hashed fields for the given header types
2242 * @hw: pointer to the hardware structure
2243 * @vsi_handle: software VSI handle
2244 * @hdrs: protocol header type
2246 * This function will return the match fields of the first instance of flow
2247 * profile having the given header types and containing input VSI
2249 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2251 struct ice_rss_cfg *r, *rss_cfg = NULL;
2253 /* verify if the protocol header is non zero and VSI is valid */
2254 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2255 return ICE_HASH_INVALID;
2257 ice_acquire_lock(&hw->rss_locks);
2258 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2259 ice_rss_cfg, l_entry)
2260 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2261 r->packet_hdr == hdrs) {
2265 ice_release_lock(&hw->rss_locks);
2267 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;