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, 0x000FC000, 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, 0x000FF800, 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, 0x03F00000, 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, 0x7FE00000, 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, 0x00410000, 0x10842000, 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, 0x00820000, 0x21084000, 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, 0x42108000, 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 /* Packet types for pppoe */
349 static const u32 ice_ptypes_pppoe[] = {
350 0x00000000, 0x00000000, 0x00000000, 0x00000000,
351 0x00000000, 0x00000000, 0x00000000, 0x00000000,
352 0x00000000, 0x03FFF000, 0x00000000, 0x00000000,
353 0x00000000, 0x00000000, 0x00000000, 0x00000000,
354 0x00000000, 0x00000000, 0x00000000, 0x00000000,
355 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 /* Manage parameters and info. used during the creation of a flow profile */
361 struct ice_flow_prof_params {
363 u16 entry_length; /* # of bytes formatted entry will require */
365 struct ice_flow_prof *prof;
367 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
368 * This will give us the direction flags.
370 struct ice_fv_word es[ICE_MAX_FV_WORDS];
371 u16 mask[ICE_MAX_FV_WORDS];
372 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
375 #define ICE_FLOW_SEG_HDRS_L2_MASK \
376 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
377 #define ICE_FLOW_SEG_HDRS_L3_MASK \
378 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
379 ICE_FLOW_SEG_HDR_ARP | ICE_FLOW_SEG_HDR_PPPOE)
380 #define ICE_FLOW_SEG_HDRS_L4_MASK \
381 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
382 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC | \
383 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU)
386 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
387 * @segs: array of one or more packet segments that describe the flow
388 * @segs_cnt: number of packet segments provided
390 static enum ice_status
391 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
395 for (i = 0; i < segs_cnt; i++) {
396 /* Multiple L3 headers */
397 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
398 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
399 return ICE_ERR_PARAM;
401 /* Multiple L4 headers */
402 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
403 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
404 return ICE_ERR_PARAM;
410 /* Sizes of fixed known protocol headers without header options */
411 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
412 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
413 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
414 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
415 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
416 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
417 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
418 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
419 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
422 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
423 * @params: information about the flow to be processed
424 * @seg: index of packet segment whose header size is to be determined
426 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
431 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
432 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
435 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
436 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
437 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
438 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
439 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
440 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
441 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
442 /* A L3 header is required if L4 is specified */
446 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
447 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
448 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
449 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
450 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
451 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
452 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
453 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
459 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
460 * @params: information about the flow to be processed
462 * This function identifies the packet types associated with the protocol
463 * headers being present in packet segments of the specified flow profile.
465 static enum ice_status
466 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
468 struct ice_flow_prof *prof;
471 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
476 for (i = 0; i < params->prof->segs_cnt; i++) {
477 const ice_bitmap_t *src;
480 hdrs = prof->segs[i].hdrs;
482 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
483 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
484 (const ice_bitmap_t *)ice_ptypes_mac_il;
485 ice_and_bitmap(params->ptypes, params->ptypes, src,
489 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
490 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
491 ice_and_bitmap(params->ptypes, params->ptypes, src,
495 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
496 ice_and_bitmap(params->ptypes, params->ptypes,
497 (const ice_bitmap_t *)ice_ptypes_arp_of,
501 if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
502 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
503 ice_and_bitmap(params->ptypes, params->ptypes, src,
507 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
508 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
509 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
510 ice_and_bitmap(params->ptypes, params->ptypes, src,
512 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
513 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
514 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
515 ice_and_bitmap(params->ptypes, params->ptypes, src,
519 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
520 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
521 (const ice_bitmap_t *)ice_ptypes_icmp_il;
522 ice_and_bitmap(params->ptypes, params->ptypes, src,
524 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
525 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
526 ice_and_bitmap(params->ptypes, params->ptypes, src,
528 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
529 ice_and_bitmap(params->ptypes, params->ptypes,
530 (const ice_bitmap_t *)ice_ptypes_tcp_il,
532 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
533 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
534 ice_and_bitmap(params->ptypes, params->ptypes, src,
536 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
538 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
539 ice_and_bitmap(params->ptypes, params->ptypes,
540 src, ICE_FLOW_PTYPE_MAX);
542 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
544 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
545 ice_and_bitmap(params->ptypes, params->ptypes,
546 src, ICE_FLOW_PTYPE_MAX);
548 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
550 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
551 ice_and_bitmap(params->ptypes, params->ptypes,
552 src, ICE_FLOW_PTYPE_MAX);
554 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
556 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
557 ice_and_bitmap(params->ptypes, params->ptypes,
558 src, ICE_FLOW_PTYPE_MAX);
567 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
568 * @hw: pointer to the HW struct
569 * @params: information about the flow to be processed
570 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
572 * This function will allocate an extraction sequence entries for a DWORD size
573 * chunk of the packet flags.
575 static enum ice_status
576 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
577 struct ice_flow_prof_params *params,
578 enum ice_flex_mdid_pkt_flags flags)
580 u8 fv_words = hw->blk[params->blk].es.fvw;
583 /* Make sure the number of extraction sequence entries required does not
584 * exceed the block's capacity.
586 if (params->es_cnt >= fv_words)
587 return ICE_ERR_MAX_LIMIT;
589 /* some blocks require a reversed field vector layout */
590 if (hw->blk[params->blk].es.reverse)
591 idx = fv_words - params->es_cnt - 1;
593 idx = params->es_cnt;
595 params->es[idx].prot_id = ICE_PROT_META_ID;
596 params->es[idx].off = flags;
603 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
604 * @hw: pointer to the HW struct
605 * @params: information about the flow to be processed
606 * @seg: packet segment index of the field to be extracted
607 * @fld: ID of field to be extracted
609 * This function determines the protocol ID, offset, and size of the given
610 * field. It then allocates one or more extraction sequence entries for the
611 * given field, and fill the entries with protocol ID and offset information.
613 static enum ice_status
614 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
615 u8 seg, enum ice_flow_field fld)
617 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
618 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
619 u8 fv_words = hw->blk[params->blk].es.fvw;
620 struct ice_flow_fld_info *flds;
621 u16 cnt, ese_bits, i;
626 flds = params->prof->segs[seg].fields;
629 case ICE_FLOW_FIELD_IDX_ETH_DA:
630 case ICE_FLOW_FIELD_IDX_ETH_SA:
631 case ICE_FLOW_FIELD_IDX_S_VLAN:
632 case ICE_FLOW_FIELD_IDX_C_VLAN:
633 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
635 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
636 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
638 case ICE_FLOW_FIELD_IDX_IP_DSCP:
639 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
640 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
642 case ICE_FLOW_FIELD_IDX_IP_TTL:
643 case ICE_FLOW_FIELD_IDX_IP_PROT:
644 /* Some fields are located at different offsets in IPv4 and
647 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
648 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
650 /* TTL and PROT share the same extraction seq. entry.
651 * Each is considered a sibling to the other in term
652 * sharing the same extraction sequence entry.
654 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
655 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
656 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
657 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
658 } else if (params->prof->segs[seg].hdrs &
659 ICE_FLOW_SEG_HDR_IPV6) {
660 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
662 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
663 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
664 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
665 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
668 case ICE_FLOW_FIELD_IDX_IPV4_SA:
669 case ICE_FLOW_FIELD_IDX_IPV4_DA:
670 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
672 case ICE_FLOW_FIELD_IDX_IPV6_SA:
673 case ICE_FLOW_FIELD_IDX_IPV6_DA:
674 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
676 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
677 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
678 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
679 prot_id = ICE_PROT_TCP_IL;
681 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
682 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
683 prot_id = ICE_PROT_UDP_IL_OR_S;
685 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
686 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
687 prot_id = ICE_PROT_SCTP_IL;
689 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
690 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
691 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
692 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
693 /* GTP is accessed through UDP OF protocol */
694 prot_id = ICE_PROT_UDP_OF;
696 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
697 prot_id = ICE_PROT_PPPOE;
699 case ICE_FLOW_FIELD_IDX_ARP_SIP:
700 case ICE_FLOW_FIELD_IDX_ARP_DIP:
701 case ICE_FLOW_FIELD_IDX_ARP_SHA:
702 case ICE_FLOW_FIELD_IDX_ARP_DHA:
703 case ICE_FLOW_FIELD_IDX_ARP_OP:
704 prot_id = ICE_PROT_ARP_OF;
706 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
707 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
708 /* ICMP type and code share the same extraction seq. entry */
709 prot_id = (params->prof->segs[seg].hdrs &
710 ICE_FLOW_SEG_HDR_IPV4) ?
711 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
712 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
713 ICE_FLOW_FIELD_IDX_ICMP_CODE :
714 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
716 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
717 prot_id = ICE_PROT_GRE_OF;
720 return ICE_ERR_NOT_IMPL;
723 /* Each extraction sequence entry is a word in size, and extracts a
724 * word-aligned offset from a protocol header.
726 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
728 flds[fld].xtrct.prot_id = prot_id;
729 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
730 ICE_FLOW_FV_EXTRACT_SZ;
731 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
732 flds[fld].xtrct.idx = params->es_cnt;
734 /* Adjust the next field-entry index after accommodating the number of
735 * entries this field consumes
737 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
738 ice_flds_info[fld].size, ese_bits);
740 /* Fill in the extraction sequence entries needed for this field */
741 off = flds[fld].xtrct.off;
742 mask = ice_flds_info[fld].mask;
743 for (i = 0; i < cnt; i++) {
744 /* Only consume an extraction sequence entry if there is no
745 * sibling field associated with this field or the sibling entry
746 * already extracts the word shared with this field.
748 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
749 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
750 flds[sib].xtrct.off != off) {
753 /* Make sure the number of extraction sequence required
754 * does not exceed the block's capability
756 if (params->es_cnt >= fv_words)
757 return ICE_ERR_MAX_LIMIT;
759 /* some blocks require a reversed field vector layout */
760 if (hw->blk[params->blk].es.reverse)
761 idx = fv_words - params->es_cnt - 1;
763 idx = params->es_cnt;
765 params->es[idx].prot_id = prot_id;
766 params->es[idx].off = off;
767 params->mask[idx] = mask;
771 off += ICE_FLOW_FV_EXTRACT_SZ;
778 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
779 * @hw: pointer to the HW struct
780 * @params: information about the flow to be processed
781 * @seg: index of packet segment whose raw fields are to be be extracted
783 static enum ice_status
784 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
790 if (!params->prof->segs[seg].raws_cnt)
793 if (params->prof->segs[seg].raws_cnt >
794 ARRAY_SIZE(params->prof->segs[seg].raws))
795 return ICE_ERR_MAX_LIMIT;
797 /* Offsets within the segment headers are not supported */
798 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
800 return ICE_ERR_PARAM;
802 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
803 struct ice_flow_seg_fld_raw *raw;
806 raw = ¶ms->prof->segs[seg].raws[i];
808 /* Only support matching raw fields in the payload */
809 if (raw->off < hdrs_sz)
810 return ICE_ERR_PARAM;
812 /* Convert the segment-relative offset into payload-relative
815 off = raw->off - hdrs_sz;
817 /* Storing extraction information */
818 raw->info.xtrct.prot_id = ICE_PROT_PAY;
819 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
820 ICE_FLOW_FV_EXTRACT_SZ;
821 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
823 raw->info.xtrct.idx = params->es_cnt;
825 /* Determine the number of field vector entries this raw field
828 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
829 (raw->info.src.last * BITS_PER_BYTE),
830 (ICE_FLOW_FV_EXTRACT_SZ *
832 off = raw->info.xtrct.off;
833 for (j = 0; j < cnt; j++) {
834 /* Make sure the number of extraction sequence required
835 * does not exceed the block's capability
837 if (params->es_cnt >= hw->blk[params->blk].es.count ||
838 params->es_cnt >= ICE_MAX_FV_WORDS)
839 return ICE_ERR_MAX_LIMIT;
841 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
842 params->es[params->es_cnt].off = off;
844 off += ICE_FLOW_FV_EXTRACT_SZ;
852 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
853 * @hw: pointer to the HW struct
854 * @params: information about the flow to be processed
856 * This function iterates through all matched fields in the given segments, and
857 * creates an extraction sequence for the fields.
859 static enum ice_status
860 ice_flow_create_xtrct_seq(struct ice_hw *hw,
861 struct ice_flow_prof_params *params)
863 enum ice_status status = ICE_SUCCESS;
866 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
869 if (params->blk == ICE_BLK_ACL)
870 ice_flow_xtract_pkt_flags(hw, params,
871 ICE_RX_MDID_PKT_FLAGS_15_0);
873 for (i = 0; i < params->prof->segs_cnt; i++) {
874 u64 match = params->prof->segs[i].match;
877 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
878 const u64 bit = BIT_ULL(j);
881 status = ice_flow_xtract_fld
882 (hw, params, i, (enum ice_flow_field)j);
889 /* Process raw matching bytes */
890 status = ice_flow_xtract_raws(hw, params, i);
899 * ice_flow_proc_segs - process all packet segments associated with a profile
900 * @hw: pointer to the HW struct
901 * @params: information about the flow to be processed
903 static enum ice_status
904 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
906 enum ice_status status;
908 status = ice_flow_proc_seg_hdrs(params);
912 status = ice_flow_create_xtrct_seq(hw, params);
916 switch (params->blk) {
918 /* Only header information is provided for RSS configuration.
919 * No further processing is needed.
921 status = ICE_SUCCESS;
924 status = ICE_SUCCESS;
928 return ICE_ERR_NOT_IMPL;
934 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
935 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
936 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
939 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
940 * @hw: pointer to the HW struct
941 * @blk: classification stage
942 * @dir: flow direction
943 * @segs: array of one or more packet segments that describe the flow
944 * @segs_cnt: number of packet segments provided
945 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
946 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
948 static struct ice_flow_prof *
949 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
950 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
951 u8 segs_cnt, u16 vsi_handle, u32 conds)
953 struct ice_flow_prof *p, *prof = NULL;
955 ice_acquire_lock(&hw->fl_profs_locks[blk]);
956 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
957 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
958 segs_cnt && segs_cnt == p->segs_cnt) {
961 /* Check for profile-VSI association if specified */
962 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
963 ice_is_vsi_valid(hw, vsi_handle) &&
964 !ice_is_bit_set(p->vsis, vsi_handle))
967 /* Protocol headers must be checked. Matched fields are
968 * checked if specified.
970 for (i = 0; i < segs_cnt; i++)
971 if (segs[i].hdrs != p->segs[i].hdrs ||
972 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
973 segs[i].match != p->segs[i].match))
976 /* A match is found if all segments are matched */
983 ice_release_lock(&hw->fl_profs_locks[blk]);
989 * ice_flow_find_prof - Look up a profile matching headers and matched fields
990 * @hw: pointer to the HW struct
991 * @blk: classification stage
992 * @dir: flow direction
993 * @segs: array of one or more packet segments that describe the flow
994 * @segs_cnt: number of packet segments provided
997 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
998 struct ice_flow_seg_info *segs, u8 segs_cnt)
1000 struct ice_flow_prof *p;
1002 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1003 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1005 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1009 * ice_flow_find_prof_id - Look up a profile with given profile ID
1010 * @hw: pointer to the HW struct
1011 * @blk: classification stage
1012 * @prof_id: unique ID to identify this flow profile
1014 static struct ice_flow_prof *
1015 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1017 struct ice_flow_prof *p;
1019 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1020 if (p->id == prof_id)
1028 * ice_dealloc_flow_entry - Deallocate flow entry memory
1029 * @hw: pointer to the HW struct
1030 * @entry: flow entry to be removed
1033 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1039 ice_free(hw, entry->entry);
1042 ice_free(hw, entry->acts);
1044 entry->acts_cnt = 0;
1047 ice_free(hw, entry);
1051 * ice_flow_rem_entry_sync - Remove a flow entry
1052 * @hw: pointer to the HW struct
1053 * @entry: flow entry to be removed
1055 static enum ice_status
1056 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1059 return ICE_ERR_BAD_PTR;
1061 LIST_DEL(&entry->l_entry);
1063 ice_dealloc_flow_entry(hw, entry);
1069 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1070 * @hw: pointer to the HW struct
1071 * @blk: classification stage
1072 * @dir: flow direction
1073 * @prof_id: unique ID to identify this flow profile
1074 * @segs: array of one or more packet segments that describe the flow
1075 * @segs_cnt: number of packet segments provided
1076 * @acts: array of default actions
1077 * @acts_cnt: number of default actions
1078 * @prof: stores the returned flow profile added
1080 * Assumption: the caller has acquired the lock to the profile list
1082 static enum ice_status
1083 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1084 enum ice_flow_dir dir, u64 prof_id,
1085 struct ice_flow_seg_info *segs, u8 segs_cnt,
1086 struct ice_flow_action *acts, u8 acts_cnt,
1087 struct ice_flow_prof **prof)
1089 struct ice_flow_prof_params params;
1090 enum ice_status status = ICE_SUCCESS;
1093 if (!prof || (acts_cnt && !acts))
1094 return ICE_ERR_BAD_PTR;
1096 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1097 params.prof = (struct ice_flow_prof *)
1098 ice_malloc(hw, sizeof(*params.prof));
1100 return ICE_ERR_NO_MEMORY;
1102 /* initialize extraction sequence to all invalid (0xff) */
1103 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1104 params.es[i].prot_id = ICE_PROT_INVALID;
1105 params.es[i].off = ICE_FV_OFFSET_INVAL;
1109 params.prof->id = prof_id;
1110 params.prof->dir = dir;
1111 params.prof->segs_cnt = segs_cnt;
1113 /* Make a copy of the segments that need to be persistent in the flow
1116 for (i = 0; i < segs_cnt; i++)
1117 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1118 ICE_NONDMA_TO_NONDMA);
1120 /* Make a copy of the actions that need to be persistent in the flow
1124 params.prof->acts = (struct ice_flow_action *)
1125 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1126 ICE_NONDMA_TO_NONDMA);
1128 if (!params.prof->acts) {
1129 status = ICE_ERR_NO_MEMORY;
1134 status = ice_flow_proc_segs(hw, ¶ms);
1136 ice_debug(hw, ICE_DBG_FLOW,
1137 "Error processing a flow's packet segments\n");
1141 /* Add a HW profile for this flow profile */
1142 status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1143 params.es, params.mask);
1145 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1149 INIT_LIST_HEAD(¶ms.prof->entries);
1150 ice_init_lock(¶ms.prof->entries_lock);
1151 *prof = params.prof;
1155 if (params.prof->acts)
1156 ice_free(hw, params.prof->acts);
1157 ice_free(hw, params.prof);
1164 * ice_flow_rem_prof_sync - remove a flow profile
1165 * @hw: pointer to the hardware structure
1166 * @blk: classification stage
1167 * @prof: pointer to flow profile to remove
1169 * Assumption: the caller has acquired the lock to the profile list
1171 static enum ice_status
1172 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1173 struct ice_flow_prof *prof)
1175 enum ice_status status = ICE_SUCCESS;
1177 /* Remove all remaining flow entries before removing the flow profile */
1178 if (!LIST_EMPTY(&prof->entries)) {
1179 struct ice_flow_entry *e, *t;
1181 ice_acquire_lock(&prof->entries_lock);
1183 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1185 status = ice_flow_rem_entry_sync(hw, e);
1190 ice_release_lock(&prof->entries_lock);
1193 /* Remove all hardware profiles associated with this flow profile */
1194 status = ice_rem_prof(hw, blk, prof->id);
1196 LIST_DEL(&prof->l_entry);
1197 ice_destroy_lock(&prof->entries_lock);
1199 ice_free(hw, prof->acts);
1207 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1208 * @hw: pointer to the hardware structure
1209 * @blk: classification stage
1210 * @vsi_handle: software VSI handle
1211 * @vsig: target VSI group
1213 * Assumption: the caller has already verified that the VSI to
1214 * be added has the same characteristics as the VSIG and will
1215 * thereby have access to all resources added to that VSIG.
1218 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1221 enum ice_status status;
1223 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1224 return ICE_ERR_PARAM;
1226 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1227 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1229 ice_release_lock(&hw->fl_profs_locks[blk]);
1235 * ice_flow_assoc_prof - associate a VSI with a flow profile
1236 * @hw: pointer to the hardware structure
1237 * @blk: classification stage
1238 * @prof: pointer to flow profile
1239 * @vsi_handle: software VSI handle
1241 * Assumption: the caller has acquired the lock to the profile list
1242 * and the software VSI handle has been validated
1244 static enum ice_status
1245 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1246 struct ice_flow_prof *prof, u16 vsi_handle)
1248 enum ice_status status = ICE_SUCCESS;
1250 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1251 status = ice_add_prof_id_flow(hw, blk,
1252 ice_get_hw_vsi_num(hw,
1256 ice_set_bit(vsi_handle, prof->vsis);
1258 ice_debug(hw, ICE_DBG_FLOW,
1259 "HW profile add failed, %d\n",
1267 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1268 * @hw: pointer to the hardware structure
1269 * @blk: classification stage
1270 * @prof: pointer to flow profile
1271 * @vsi_handle: software VSI handle
1273 * Assumption: the caller has acquired the lock to the profile list
1274 * and the software VSI handle has been validated
1276 static enum ice_status
1277 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1278 struct ice_flow_prof *prof, u16 vsi_handle)
1280 enum ice_status status = ICE_SUCCESS;
1282 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1283 status = ice_rem_prof_id_flow(hw, blk,
1284 ice_get_hw_vsi_num(hw,
1288 ice_clear_bit(vsi_handle, prof->vsis);
1290 ice_debug(hw, ICE_DBG_FLOW,
1291 "HW profile remove failed, %d\n",
1299 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1300 * @hw: pointer to the HW struct
1301 * @blk: classification stage
1302 * @dir: flow direction
1303 * @prof_id: unique ID to identify this flow profile
1304 * @segs: array of one or more packet segments that describe the flow
1305 * @segs_cnt: number of packet segments provided
1306 * @acts: array of default actions
1307 * @acts_cnt: number of default actions
1308 * @prof: stores the returned flow profile added
1311 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1312 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1313 struct ice_flow_action *acts, u8 acts_cnt,
1314 struct ice_flow_prof **prof)
1316 enum ice_status status;
1318 if (segs_cnt > ICE_FLOW_SEG_MAX)
1319 return ICE_ERR_MAX_LIMIT;
1322 return ICE_ERR_PARAM;
1325 return ICE_ERR_BAD_PTR;
1327 status = ice_flow_val_hdrs(segs, segs_cnt);
1331 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1333 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1334 acts, acts_cnt, prof);
1336 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1338 ice_release_lock(&hw->fl_profs_locks[blk]);
1344 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1345 * @hw: pointer to the HW struct
1346 * @blk: the block for which the flow profile is to be removed
1347 * @prof_id: unique ID of the flow profile to be removed
1350 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1352 struct ice_flow_prof *prof;
1353 enum ice_status status;
1355 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1357 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1359 status = ICE_ERR_DOES_NOT_EXIST;
1363 /* prof becomes invalid after the call */
1364 status = ice_flow_rem_prof_sync(hw, blk, prof);
1367 ice_release_lock(&hw->fl_profs_locks[blk]);
1373 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1374 * @hw: pointer to the HW struct
1375 * @blk: classification stage
1376 * @prof_id: the profile ID handle
1377 * @hw_prof_id: pointer to variable to receive the HW profile ID
1380 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1383 struct ice_prof_map *map;
1385 map = ice_search_prof_id(hw, blk, prof_id);
1387 *hw_prof_id = map->prof_id;
1391 return ICE_ERR_DOES_NOT_EXIST;
1395 * ice_flow_find_entry - look for a flow entry using its unique ID
1396 * @hw: pointer to the HW struct
1397 * @blk: classification stage
1398 * @entry_id: unique ID to identify this flow entry
1400 * This function looks for the flow entry with the specified unique ID in all
1401 * flow profiles of the specified classification stage. If the entry is found,
1402 * and it returns the handle to the flow entry. Otherwise, it returns
1403 * ICE_FLOW_ENTRY_ID_INVAL.
1405 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1407 struct ice_flow_entry *found = NULL;
1408 struct ice_flow_prof *p;
1410 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1412 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1413 struct ice_flow_entry *e;
1415 ice_acquire_lock(&p->entries_lock);
1416 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1417 if (e->id == entry_id) {
1421 ice_release_lock(&p->entries_lock);
1427 ice_release_lock(&hw->fl_profs_locks[blk]);
1429 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1433 * ice_flow_add_entry - Add a flow entry
1434 * @hw: pointer to the HW struct
1435 * @blk: classification stage
1436 * @prof_id: ID of the profile to add a new flow entry to
1437 * @entry_id: unique ID to identify this flow entry
1438 * @vsi_handle: software VSI handle for the flow entry
1439 * @prio: priority of the flow entry
1440 * @data: pointer to a data buffer containing flow entry's match values/masks
1441 * @acts: arrays of actions to be performed on a match
1442 * @acts_cnt: number of actions
1443 * @entry_h: pointer to buffer that receives the new flow entry's handle
1446 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1447 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1448 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1451 struct ice_flow_prof *prof = NULL;
1452 struct ice_flow_entry *e = NULL;
1453 enum ice_status status = ICE_SUCCESS;
1455 if (acts_cnt && !acts)
1456 return ICE_ERR_PARAM;
1458 /* No flow entry data is expected for RSS */
1459 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1460 return ICE_ERR_BAD_PTR;
1462 if (!ice_is_vsi_valid(hw, vsi_handle))
1463 return ICE_ERR_PARAM;
1465 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1467 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1469 status = ICE_ERR_DOES_NOT_EXIST;
1471 /* Allocate memory for the entry being added and associate
1472 * the VSI to the found flow profile
1474 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1476 status = ICE_ERR_NO_MEMORY;
1478 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1481 ice_release_lock(&hw->fl_profs_locks[blk]);
1486 e->vsi_handle = vsi_handle;
1492 /* RSS will add only one entry per VSI per profile */
1499 status = ICE_ERR_NOT_IMPL;
1503 if (blk != ICE_BLK_ACL) {
1504 /* ACL will handle the entry management */
1505 ice_acquire_lock(&prof->entries_lock);
1506 LIST_ADD(&e->l_entry, &prof->entries);
1507 ice_release_lock(&prof->entries_lock);
1510 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1515 ice_free(hw, e->entry);
1523 * ice_flow_rem_entry - Remove a flow entry
1524 * @hw: pointer to the HW struct
1525 * @entry_h: handle to the flow entry to be removed
1527 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1529 struct ice_flow_entry *entry;
1530 struct ice_flow_prof *prof;
1531 enum ice_status status;
1533 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1534 return ICE_ERR_PARAM;
1536 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1538 /* Retain the pointer to the flow profile as the entry will be freed */
1541 ice_acquire_lock(&prof->entries_lock);
1542 status = ice_flow_rem_entry_sync(hw, entry);
1543 ice_release_lock(&prof->entries_lock);
1549 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1550 * @seg: packet segment the field being set belongs to
1551 * @fld: field to be set
1552 * @type: type of the field
1553 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1554 * entry's input buffer
1555 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1557 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1558 * entry's input buffer
1560 * This helper function stores information of a field being matched, including
1561 * the type of the field and the locations of the value to match, the mask, and
1562 * and the upper-bound value in the start of the input buffer for a flow entry.
1563 * This function should only be used for fixed-size data structures.
1565 * This function also opportunistically determines the protocol headers to be
1566 * present based on the fields being set. Some fields cannot be used alone to
1567 * determine the protocol headers present. Sometimes, fields for particular
1568 * protocol headers are not matched. In those cases, the protocol headers
1569 * must be explicitly set.
1572 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1573 enum ice_flow_fld_match_type type, u16 val_loc,
1574 u16 mask_loc, u16 last_loc)
1576 u64 bit = BIT_ULL(fld);
1579 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1582 seg->fields[fld].type = type;
1583 seg->fields[fld].src.val = val_loc;
1584 seg->fields[fld].src.mask = mask_loc;
1585 seg->fields[fld].src.last = last_loc;
1587 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1591 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1592 * @seg: packet segment the field being set belongs to
1593 * @fld: field to be set
1594 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1595 * entry's input buffer
1596 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1598 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1599 * entry's input buffer
1600 * @range: indicate if field being matched is to be in a range
1602 * This function specifies the locations, in the form of byte offsets from the
1603 * start of the input buffer for a flow entry, from where the value to match,
1604 * the mask value, and upper value can be extracted. These locations are then
1605 * stored in the flow profile. When adding a flow entry associated with the
1606 * flow profile, these locations will be used to quickly extract the values and
1607 * create the content of a match entry. This function should only be used for
1608 * fixed-size data structures.
1611 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1612 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1614 enum ice_flow_fld_match_type t = range ?
1615 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1617 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1621 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1622 * @seg: packet segment the field being set belongs to
1623 * @fld: field to be set
1624 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1625 * entry's input buffer
1626 * @pref_loc: location of prefix value from entry's input buffer
1627 * @pref_sz: size of the location holding the prefix value
1629 * This function specifies the locations, in the form of byte offsets from the
1630 * start of the input buffer for a flow entry, from where the value to match
1631 * and the IPv4 prefix value can be extracted. These locations are then stored
1632 * in the flow profile. When adding flow entries to the associated flow profile,
1633 * these locations can be used to quickly extract the values to create the
1634 * content of a match entry. This function should only be used for fixed-size
1638 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1639 u16 val_loc, u16 pref_loc, u8 pref_sz)
1641 /* For this type of field, the "mask" location is for the prefix value's
1642 * location and the "last" location is for the size of the location of
1645 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1646 pref_loc, (u16)pref_sz);
1650 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1651 * @seg: packet segment the field being set belongs to
1652 * @off: offset of the raw field from the beginning of the segment in bytes
1653 * @len: length of the raw pattern to be matched
1654 * @val_loc: location of the value to match from entry's input buffer
1655 * @mask_loc: location of mask value from entry's input buffer
1657 * This function specifies the offset of the raw field to be match from the
1658 * beginning of the specified packet segment, and the locations, in the form of
1659 * byte offsets from the start of the input buffer for a flow entry, from where
1660 * the value to match and the mask value to be extracted. These locations are
1661 * then stored in the flow profile. When adding flow entries to the associated
1662 * flow profile, these locations can be used to quickly extract the values to
1663 * create the content of a match entry. This function should only be used for
1664 * fixed-size data structures.
1667 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1668 u16 val_loc, u16 mask_loc)
1670 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1671 seg->raws[seg->raws_cnt].off = off;
1672 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1673 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1674 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1675 /* The "last" field is used to store the length of the field */
1676 seg->raws[seg->raws_cnt].info.src.last = len;
1679 /* Overflows of "raws" will be handled as an error condition later in
1680 * the flow when this information is processed.
1685 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1686 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE)
1688 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1689 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1690 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC_TEID | \
1691 ICE_FLOW_SEG_HDR_GTPU)
1694 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1695 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1696 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1699 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1700 * @segs: pointer to the flow field segment(s)
1701 * @hash_fields: fields to be hashed on for the segment(s)
1702 * @flow_hdr: protocol header fields within a packet segment
1704 * Helper function to extract fields from hash bitmap and use flow
1705 * header value to set flow field segment for further use in flow
1706 * profile entry or removal.
1708 static enum ice_status
1709 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1712 u64 val = hash_fields;
1715 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1716 u64 bit = BIT_ULL(i);
1719 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1720 ICE_FLOW_FLD_OFF_INVAL,
1721 ICE_FLOW_FLD_OFF_INVAL,
1722 ICE_FLOW_FLD_OFF_INVAL, false);
1726 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1728 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1729 return ICE_ERR_PARAM;
1731 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1732 if (!ice_is_pow2(val))
1735 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1736 if (val && !ice_is_pow2(val))
1743 * ice_rem_vsi_rss_list - remove VSI from RSS list
1744 * @hw: pointer to the hardware structure
1745 * @vsi_handle: software VSI handle
1747 * Remove the VSI from all RSS configurations in the list.
1749 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1751 struct ice_rss_cfg *r, *tmp;
1753 if (LIST_EMPTY(&hw->rss_list_head))
1756 ice_acquire_lock(&hw->rss_locks);
1757 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1758 ice_rss_cfg, l_entry) {
1759 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1760 ice_clear_bit(vsi_handle, r->vsis);
1762 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1763 LIST_DEL(&r->l_entry);
1768 ice_release_lock(&hw->rss_locks);
1772 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1773 * @hw: pointer to the hardware structure
1774 * @vsi_handle: software VSI handle
1776 * This function will iterate through all flow profiles and disassociate
1777 * the VSI from that profile. If the flow profile has no VSIs it will
1780 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1782 const enum ice_block blk = ICE_BLK_RSS;
1783 struct ice_flow_prof *p, *t;
1784 enum ice_status status = ICE_SUCCESS;
1786 if (!ice_is_vsi_valid(hw, vsi_handle))
1787 return ICE_ERR_PARAM;
1789 if (LIST_EMPTY(&hw->fl_profs[blk]))
1792 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1793 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1795 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1796 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1800 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1801 status = ice_flow_rem_prof_sync(hw, blk, p);
1807 ice_release_lock(&hw->fl_profs_locks[blk]);
1813 * ice_rem_rss_list - remove RSS configuration from list
1814 * @hw: pointer to the hardware structure
1815 * @vsi_handle: software VSI handle
1816 * @prof: pointer to flow profile
1818 * Assumption: lock has already been acquired for RSS list
1821 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1823 struct ice_rss_cfg *r, *tmp;
1825 /* Search for RSS hash fields associated to the VSI that match the
1826 * hash configurations associated to the flow profile. If found
1827 * remove from the RSS entry list of the VSI context and delete entry.
1829 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1830 ice_rss_cfg, l_entry) {
1831 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1832 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1833 ice_clear_bit(vsi_handle, r->vsis);
1834 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1835 LIST_DEL(&r->l_entry);
1844 * ice_add_rss_list - add RSS configuration to list
1845 * @hw: pointer to the hardware structure
1846 * @vsi_handle: software VSI handle
1847 * @prof: pointer to flow profile
1849 * Assumption: lock has already been acquired for RSS list
1851 static enum ice_status
1852 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1854 struct ice_rss_cfg *r, *rss_cfg;
1856 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1857 ice_rss_cfg, l_entry)
1858 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1859 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1860 ice_set_bit(vsi_handle, r->vsis);
1864 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1866 return ICE_ERR_NO_MEMORY;
1868 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1869 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1870 ice_set_bit(vsi_handle, rss_cfg->vsis);
1872 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1877 #define ICE_FLOW_PROF_HASH_S 0
1878 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1879 #define ICE_FLOW_PROF_HDR_S 32
1880 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1881 #define ICE_FLOW_PROF_ENCAP_S 63
1882 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1884 #define ICE_RSS_OUTER_HEADERS 1
1885 #define ICE_RSS_INNER_HEADERS 2
1887 /* Flow profile ID format:
1888 * [0:31] - Packet match fields
1889 * [32:62] - Protocol header
1890 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1892 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1893 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1894 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1895 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1898 * ice_add_rss_cfg_sync - add an RSS configuration
1899 * @hw: pointer to the hardware structure
1900 * @vsi_handle: software VSI handle
1901 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1902 * @addl_hdrs: protocol header fields
1903 * @segs_cnt: packet segment count
1905 * Assumption: lock has already been acquired for RSS list
1907 static enum ice_status
1908 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1909 u32 addl_hdrs, u8 segs_cnt)
1911 const enum ice_block blk = ICE_BLK_RSS;
1912 struct ice_flow_prof *prof = NULL;
1913 struct ice_flow_seg_info *segs;
1914 enum ice_status status = ICE_SUCCESS;
1916 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1917 return ICE_ERR_PARAM;
1919 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1922 return ICE_ERR_NO_MEMORY;
1924 /* Construct the packet segment info from the hashed fields */
1925 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1930 /* Search for a flow profile that has matching headers, hash fields
1931 * and has the input VSI associated to it. If found, no further
1932 * operations required and exit.
1934 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1936 ICE_FLOW_FIND_PROF_CHK_FLDS |
1937 ICE_FLOW_FIND_PROF_CHK_VSI);
1941 /* Check if a flow profile exists with the same protocol headers and
1942 * associated with the input VSI. If so disasscociate the VSI from
1943 * this profile. The VSI will be added to a new profile created with
1944 * the protocol header and new hash field configuration.
1946 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1947 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1949 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1951 ice_rem_rss_list(hw, vsi_handle, prof);
1955 /* Remove profile if it has no VSIs associated */
1956 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1957 status = ice_flow_rem_prof(hw, blk, prof->id);
1963 /* Search for a profile that has same match fields only. If this
1964 * exists then associate the VSI to this profile.
1966 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1968 ICE_FLOW_FIND_PROF_CHK_FLDS);
1970 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1972 status = ice_add_rss_list(hw, vsi_handle, prof);
1976 /* Create a new flow profile with generated profile and packet
1977 * segment information.
1979 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1980 ICE_FLOW_GEN_PROFID(hashed_flds,
1981 segs[segs_cnt - 1].hdrs,
1983 segs, segs_cnt, NULL, 0, &prof);
1987 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1988 /* If association to a new flow profile failed then this profile can
1992 ice_flow_rem_prof(hw, blk, prof->id);
1996 status = ice_add_rss_list(hw, vsi_handle, prof);
2004 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2005 * @hw: pointer to the hardware structure
2006 * @vsi_handle: software VSI handle
2007 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2008 * @addl_hdrs: protocol header fields
2010 * This function will generate a flow profile based on fields associated with
2011 * the input fields to hash on, the flow type and use the VSI number to add
2012 * a flow entry to the profile.
2015 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2018 enum ice_status status;
2020 if (hashed_flds == ICE_HASH_INVALID ||
2021 !ice_is_vsi_valid(hw, vsi_handle))
2022 return ICE_ERR_PARAM;
2024 ice_acquire_lock(&hw->rss_locks);
2025 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2026 ICE_RSS_OUTER_HEADERS);
2028 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2029 addl_hdrs, ICE_RSS_INNER_HEADERS);
2030 ice_release_lock(&hw->rss_locks);
2036 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2037 * @hw: pointer to the hardware structure
2038 * @vsi_handle: software VSI handle
2039 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2040 * @addl_hdrs: Protocol header fields within a packet segment
2041 * @segs_cnt: packet segment count
2043 * Assumption: lock has already been acquired for RSS list
2045 static enum ice_status
2046 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2047 u32 addl_hdrs, u8 segs_cnt)
2049 const enum ice_block blk = ICE_BLK_RSS;
2050 struct ice_flow_seg_info *segs;
2051 struct ice_flow_prof *prof;
2052 enum ice_status status;
2054 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
2056 return ICE_ERR_NO_MEMORY;
2058 /* Construct the packet segment info from the hashed fields */
2059 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
2063 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2065 ICE_FLOW_FIND_PROF_CHK_FLDS);
2067 status = ICE_ERR_DOES_NOT_EXIST;
2071 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2075 /* Remove RSS configuration from VSI context before deleting
2078 ice_rem_rss_list(hw, vsi_handle, prof);
2080 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2081 status = ice_flow_rem_prof(hw, blk, prof->id);
2089 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2090 * @hw: pointer to the hardware structure
2091 * @vsi_handle: software VSI handle
2092 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2093 * @addl_hdrs: Protocol header fields within a packet segment
2095 * This function will lookup the flow profile based on the input
2096 * hash field bitmap, iterate through the profile entry list of
2097 * that profile and find entry associated with input VSI to be
2098 * removed. Calls are made to underlying flow apis which will in
2099 * turn build or update buffers for RSS XLT1 section.
2102 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2105 enum ice_status status;
2107 if (hashed_flds == ICE_HASH_INVALID ||
2108 !ice_is_vsi_valid(hw, vsi_handle))
2109 return ICE_ERR_PARAM;
2111 ice_acquire_lock(&hw->rss_locks);
2112 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2113 ICE_RSS_OUTER_HEADERS);
2115 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2116 addl_hdrs, ICE_RSS_INNER_HEADERS);
2117 ice_release_lock(&hw->rss_locks);
2122 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2123 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2124 * convert its values to their appropriate flow L3, L4 values.
2126 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2127 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2128 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2129 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2130 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2131 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2132 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2133 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2134 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2135 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2136 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2137 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2138 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2140 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2141 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2142 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2143 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2144 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2145 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2146 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2147 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2148 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2149 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2150 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2151 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2152 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2154 #define ICE_FLOW_MAX_CFG 10
2157 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2158 * @hw: pointer to the hardware structure
2159 * @vsi_handle: software VSI handle
2160 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2162 * This function will take the hash bitmap provided by the AVF driver via a
2163 * message, convert it to ICE-compatible values, and configure RSS flow
2167 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2169 enum ice_status status = ICE_SUCCESS;
2172 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2173 !ice_is_vsi_valid(hw, vsi_handle))
2174 return ICE_ERR_PARAM;
2176 /* Make sure no unsupported bits are specified */
2177 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2178 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2181 hash_flds = avf_hash;
2183 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2184 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2185 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2187 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2188 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2190 /* Create the corresponding RSS configuration for each valid hash bit */
2192 u64 rss_hash = ICE_HASH_INVALID;
2194 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2195 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2196 rss_hash = ICE_FLOW_HASH_IPV4;
2197 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2198 } else if (hash_flds &
2199 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2200 rss_hash = ICE_FLOW_HASH_IPV4 |
2201 ICE_FLOW_HASH_TCP_PORT;
2202 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2203 } else if (hash_flds &
2204 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2205 rss_hash = ICE_FLOW_HASH_IPV4 |
2206 ICE_FLOW_HASH_UDP_PORT;
2207 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2208 } else if (hash_flds &
2209 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2210 rss_hash = ICE_FLOW_HASH_IPV4 |
2211 ICE_FLOW_HASH_SCTP_PORT;
2213 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2215 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2216 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2217 rss_hash = ICE_FLOW_HASH_IPV6;
2218 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2219 } else if (hash_flds &
2220 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2221 rss_hash = ICE_FLOW_HASH_IPV6 |
2222 ICE_FLOW_HASH_TCP_PORT;
2223 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2224 } else if (hash_flds &
2225 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2226 rss_hash = ICE_FLOW_HASH_IPV6 |
2227 ICE_FLOW_HASH_UDP_PORT;
2228 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2229 } else if (hash_flds &
2230 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2231 rss_hash = ICE_FLOW_HASH_IPV6 |
2232 ICE_FLOW_HASH_SCTP_PORT;
2234 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2238 if (rss_hash == ICE_HASH_INVALID)
2239 return ICE_ERR_OUT_OF_RANGE;
2241 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2242 ICE_FLOW_SEG_HDR_NONE);
2251 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2252 * @hw: pointer to the hardware structure
2253 * @vsi_handle: software VSI handle
2255 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2257 enum ice_status status = ICE_SUCCESS;
2258 struct ice_rss_cfg *r;
2260 if (!ice_is_vsi_valid(hw, vsi_handle))
2261 return ICE_ERR_PARAM;
2263 ice_acquire_lock(&hw->rss_locks);
2264 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2265 ice_rss_cfg, l_entry) {
2266 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2267 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2270 ICE_RSS_OUTER_HEADERS);
2273 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2276 ICE_RSS_INNER_HEADERS);
2281 ice_release_lock(&hw->rss_locks);
2287 * ice_get_rss_cfg - returns hashed fields for the given header types
2288 * @hw: pointer to the hardware structure
2289 * @vsi_handle: software VSI handle
2290 * @hdrs: protocol header type
2292 * This function will return the match fields of the first instance of flow
2293 * profile having the given header types and containing input VSI
2295 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2297 struct ice_rss_cfg *r, *rss_cfg = NULL;
2299 /* verify if the protocol header is non zero and VSI is valid */
2300 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2301 return ICE_HASH_INVALID;
2303 ice_acquire_lock(&hw->rss_locks);
2304 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2305 ice_rss_cfg, l_entry)
2306 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2307 r->packet_hdr == hdrs) {
2311 ice_release_lock(&hw->rss_locks);
2313 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;