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)
384 for (i = 0; i < segs_cnt; i++) {
385 /* Multiple L3 headers */
386 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
387 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
388 return ICE_ERR_PARAM;
390 /* Multiple L4 headers */
391 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
392 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
393 return ICE_ERR_PARAM;
399 /* Sizes of fixed known protocol headers without header options */
400 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
401 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
402 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
403 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
404 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
405 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
406 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
407 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
408 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
411 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
412 * @params: information about the flow to be processed
413 * @seg: index of packet segment whose header size is to be determined
415 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
420 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
421 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
424 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
425 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
426 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
427 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
428 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
429 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
430 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
431 /* A L3 header is required if L4 is specified */
435 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
436 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
437 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
438 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
439 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
440 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
441 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
442 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
448 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
449 * @params: information about the flow to be processed
451 * This function identifies the packet types associated with the protocol
452 * headers being present in packet segments of the specified flow profile.
454 static enum ice_status
455 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
457 struct ice_flow_prof *prof;
460 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
465 for (i = 0; i < params->prof->segs_cnt; i++) {
466 const ice_bitmap_t *src;
469 hdrs = prof->segs[i].hdrs;
471 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
472 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
473 (const ice_bitmap_t *)ice_ptypes_mac_il;
474 ice_and_bitmap(params->ptypes, params->ptypes, src,
478 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
479 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
480 ice_and_bitmap(params->ptypes, params->ptypes, src,
484 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
485 ice_and_bitmap(params->ptypes, params->ptypes,
486 (const ice_bitmap_t *)ice_ptypes_arp_of,
490 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
491 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
492 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
493 ice_and_bitmap(params->ptypes, params->ptypes, src,
495 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
496 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
497 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
498 ice_and_bitmap(params->ptypes, params->ptypes, src,
502 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
503 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
504 (const ice_bitmap_t *)ice_ptypes_icmp_il;
505 ice_and_bitmap(params->ptypes, params->ptypes, src,
507 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
508 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
509 ice_and_bitmap(params->ptypes, params->ptypes, src,
511 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
512 ice_and_bitmap(params->ptypes, params->ptypes,
513 (const ice_bitmap_t *)ice_ptypes_tcp_il,
515 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
516 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
517 ice_and_bitmap(params->ptypes, params->ptypes, src,
519 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
521 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
522 ice_and_bitmap(params->ptypes, params->ptypes,
523 src, ICE_FLOW_PTYPE_MAX);
525 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
527 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
528 ice_and_bitmap(params->ptypes, params->ptypes,
529 src, ICE_FLOW_PTYPE_MAX);
531 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
533 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
534 ice_and_bitmap(params->ptypes, params->ptypes,
535 src, ICE_FLOW_PTYPE_MAX);
537 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
539 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
540 ice_and_bitmap(params->ptypes, params->ptypes,
541 src, ICE_FLOW_PTYPE_MAX);
550 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
551 * @hw: pointer to the HW struct
552 * @params: information about the flow to be processed
553 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
555 * This function will allocate an extraction sequence entries for a DWORD size
556 * chunk of the packet flags.
558 static enum ice_status
559 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
560 struct ice_flow_prof_params *params,
561 enum ice_flex_mdid_pkt_flags flags)
563 u8 fv_words = hw->blk[params->blk].es.fvw;
566 /* Make sure the number of extraction sequence entries required does not
567 * exceed the block's capacity.
569 if (params->es_cnt >= fv_words)
570 return ICE_ERR_MAX_LIMIT;
572 /* some blocks require a reversed field vector layout */
573 if (hw->blk[params->blk].es.reverse)
574 idx = fv_words - params->es_cnt - 1;
576 idx = params->es_cnt;
578 params->es[idx].prot_id = ICE_PROT_META_ID;
579 params->es[idx].off = flags;
586 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
587 * @hw: pointer to the HW struct
588 * @params: information about the flow to be processed
589 * @seg: packet segment index of the field to be extracted
590 * @fld: ID of field to be extracted
592 * This function determines the protocol ID, offset, and size of the given
593 * field. It then allocates one or more extraction sequence entries for the
594 * given field, and fill the entries with protocol ID and offset information.
596 static enum ice_status
597 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
598 u8 seg, enum ice_flow_field fld)
600 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
601 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
602 u8 fv_words = hw->blk[params->blk].es.fvw;
603 struct ice_flow_fld_info *flds;
604 u16 cnt, ese_bits, i;
609 flds = params->prof->segs[seg].fields;
612 case ICE_FLOW_FIELD_IDX_ETH_DA:
613 case ICE_FLOW_FIELD_IDX_ETH_SA:
614 case ICE_FLOW_FIELD_IDX_S_VLAN:
615 case ICE_FLOW_FIELD_IDX_C_VLAN:
616 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
618 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
619 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
621 case ICE_FLOW_FIELD_IDX_IP_DSCP:
622 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
623 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
625 case ICE_FLOW_FIELD_IDX_IP_TTL:
626 case ICE_FLOW_FIELD_IDX_IP_PROT:
627 /* Some fields are located at different offsets in IPv4 and
630 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
631 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
633 /* TTL and PROT share the same extraction seq. entry.
634 * Each is considered a sibling to the other in term
635 * sharing the same extraction sequence entry.
637 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
638 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
639 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
640 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
641 } else if (params->prof->segs[seg].hdrs &
642 ICE_FLOW_SEG_HDR_IPV6) {
643 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
645 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
646 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
647 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
648 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
651 case ICE_FLOW_FIELD_IDX_IPV4_SA:
652 case ICE_FLOW_FIELD_IDX_IPV4_DA:
653 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
655 case ICE_FLOW_FIELD_IDX_IPV6_SA:
656 case ICE_FLOW_FIELD_IDX_IPV6_DA:
657 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
659 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
660 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
661 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
662 prot_id = ICE_PROT_TCP_IL;
664 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
665 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
666 prot_id = ICE_PROT_UDP_IL_OR_S;
668 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
669 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
670 prot_id = ICE_PROT_SCTP_IL;
672 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
673 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
674 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
675 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
676 /* GTP is accessed through UDP OF protocol */
677 prot_id = ICE_PROT_UDP_OF;
679 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
680 prot_id = ICE_PROT_PPPOE;
682 case ICE_FLOW_FIELD_IDX_ARP_SIP:
683 case ICE_FLOW_FIELD_IDX_ARP_DIP:
684 case ICE_FLOW_FIELD_IDX_ARP_SHA:
685 case ICE_FLOW_FIELD_IDX_ARP_DHA:
686 case ICE_FLOW_FIELD_IDX_ARP_OP:
687 prot_id = ICE_PROT_ARP_OF;
689 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
690 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
691 /* ICMP type and code share the same extraction seq. entry */
692 prot_id = (params->prof->segs[seg].hdrs &
693 ICE_FLOW_SEG_HDR_IPV4) ?
694 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
695 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
696 ICE_FLOW_FIELD_IDX_ICMP_CODE :
697 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
699 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
700 prot_id = ICE_PROT_GRE_OF;
703 return ICE_ERR_NOT_IMPL;
706 /* Each extraction sequence entry is a word in size, and extracts a
707 * word-aligned offset from a protocol header.
709 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
711 flds[fld].xtrct.prot_id = prot_id;
712 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
713 ICE_FLOW_FV_EXTRACT_SZ;
714 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
715 flds[fld].xtrct.idx = params->es_cnt;
717 /* Adjust the next field-entry index after accommodating the number of
718 * entries this field consumes
720 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
721 ice_flds_info[fld].size, ese_bits);
723 /* Fill in the extraction sequence entries needed for this field */
724 off = flds[fld].xtrct.off;
725 mask = ice_flds_info[fld].mask;
726 for (i = 0; i < cnt; i++) {
727 /* Only consume an extraction sequence entry if there is no
728 * sibling field associated with this field or the sibling entry
729 * already extracts the word shared with this field.
731 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
732 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
733 flds[sib].xtrct.off != off) {
736 /* Make sure the number of extraction sequence required
737 * does not exceed the block's capability
739 if (params->es_cnt >= fv_words)
740 return ICE_ERR_MAX_LIMIT;
742 /* some blocks require a reversed field vector layout */
743 if (hw->blk[params->blk].es.reverse)
744 idx = fv_words - params->es_cnt - 1;
746 idx = params->es_cnt;
748 params->es[idx].prot_id = prot_id;
749 params->es[idx].off = off;
750 params->mask[idx] = mask;
754 off += ICE_FLOW_FV_EXTRACT_SZ;
761 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
762 * @hw: pointer to the HW struct
763 * @params: information about the flow to be processed
764 * @seg: index of packet segment whose raw fields are to be be extracted
766 static enum ice_status
767 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
773 if (!params->prof->segs[seg].raws_cnt)
776 if (params->prof->segs[seg].raws_cnt >
777 ARRAY_SIZE(params->prof->segs[seg].raws))
778 return ICE_ERR_MAX_LIMIT;
780 /* Offsets within the segment headers are not supported */
781 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
783 return ICE_ERR_PARAM;
785 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
786 struct ice_flow_seg_fld_raw *raw;
789 raw = ¶ms->prof->segs[seg].raws[i];
791 /* Only support matching raw fields in the payload */
792 if (raw->off < hdrs_sz)
793 return ICE_ERR_PARAM;
795 /* Convert the segment-relative offset into payload-relative
798 off = raw->off - hdrs_sz;
800 /* Storing extraction information */
801 raw->info.xtrct.prot_id = ICE_PROT_PAY;
802 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
803 ICE_FLOW_FV_EXTRACT_SZ;
804 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
806 raw->info.xtrct.idx = params->es_cnt;
808 /* Determine the number of field vector entries this raw field
811 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
812 (raw->info.src.last * BITS_PER_BYTE),
813 (ICE_FLOW_FV_EXTRACT_SZ *
815 off = raw->info.xtrct.off;
816 for (j = 0; j < cnt; j++) {
817 /* Make sure the number of extraction sequence required
818 * does not exceed the block's capability
820 if (params->es_cnt >= hw->blk[params->blk].es.count ||
821 params->es_cnt >= ICE_MAX_FV_WORDS)
822 return ICE_ERR_MAX_LIMIT;
824 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
825 params->es[params->es_cnt].off = off;
827 off += ICE_FLOW_FV_EXTRACT_SZ;
835 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
836 * @hw: pointer to the HW struct
837 * @params: information about the flow to be processed
839 * This function iterates through all matched fields in the given segments, and
840 * creates an extraction sequence for the fields.
842 static enum ice_status
843 ice_flow_create_xtrct_seq(struct ice_hw *hw,
844 struct ice_flow_prof_params *params)
846 enum ice_status status = ICE_SUCCESS;
849 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
852 if (params->blk == ICE_BLK_ACL)
853 ice_flow_xtract_pkt_flags(hw, params,
854 ICE_RX_MDID_PKT_FLAGS_15_0);
856 for (i = 0; i < params->prof->segs_cnt; i++) {
857 u64 match = params->prof->segs[i].match;
860 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
861 const u64 bit = BIT_ULL(j);
864 status = ice_flow_xtract_fld
865 (hw, params, i, (enum ice_flow_field)j);
872 /* Process raw matching bytes */
873 status = ice_flow_xtract_raws(hw, params, i);
882 * ice_flow_proc_segs - process all packet segments associated with a profile
883 * @hw: pointer to the HW struct
884 * @params: information about the flow to be processed
886 static enum ice_status
887 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
889 enum ice_status status;
891 status = ice_flow_proc_seg_hdrs(params);
895 status = ice_flow_create_xtrct_seq(hw, params);
899 switch (params->blk) {
901 /* Only header information is provided for RSS configuration.
902 * No further processing is needed.
904 status = ICE_SUCCESS;
907 status = ICE_SUCCESS;
911 return ICE_ERR_NOT_IMPL;
917 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
918 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
919 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
922 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
923 * @hw: pointer to the HW struct
924 * @blk: classification stage
925 * @dir: flow direction
926 * @segs: array of one or more packet segments that describe the flow
927 * @segs_cnt: number of packet segments provided
928 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
929 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
931 static struct ice_flow_prof *
932 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
933 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
934 u8 segs_cnt, u16 vsi_handle, u32 conds)
936 struct ice_flow_prof *p, *prof = NULL;
938 ice_acquire_lock(&hw->fl_profs_locks[blk]);
939 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
940 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
941 segs_cnt && segs_cnt == p->segs_cnt) {
944 /* Check for profile-VSI association if specified */
945 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
946 ice_is_vsi_valid(hw, vsi_handle) &&
947 !ice_is_bit_set(p->vsis, vsi_handle))
950 /* Protocol headers must be checked. Matched fields are
951 * checked if specified.
953 for (i = 0; i < segs_cnt; i++)
954 if (segs[i].hdrs != p->segs[i].hdrs ||
955 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
956 segs[i].match != p->segs[i].match))
959 /* A match is found if all segments are matched */
966 ice_release_lock(&hw->fl_profs_locks[blk]);
972 * ice_flow_find_prof - Look up a profile matching headers and matched fields
973 * @hw: pointer to the HW struct
974 * @blk: classification stage
975 * @dir: flow direction
976 * @segs: array of one or more packet segments that describe the flow
977 * @segs_cnt: number of packet segments provided
980 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
981 struct ice_flow_seg_info *segs, u8 segs_cnt)
983 struct ice_flow_prof *p;
985 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
986 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
988 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
992 * ice_flow_find_prof_id - Look up a profile with given profile ID
993 * @hw: pointer to the HW struct
994 * @blk: classification stage
995 * @prof_id: unique ID to identify this flow profile
997 static struct ice_flow_prof *
998 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1000 struct ice_flow_prof *p;
1002 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1003 if (p->id == prof_id)
1011 * ice_dealloc_flow_entry - Deallocate flow entry memory
1012 * @hw: pointer to the HW struct
1013 * @entry: flow entry to be removed
1016 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1022 ice_free(hw, entry->entry);
1025 ice_free(hw, entry->acts);
1027 entry->acts_cnt = 0;
1030 ice_free(hw, entry);
1034 * ice_flow_rem_entry_sync - Remove a flow entry
1035 * @hw: pointer to the HW struct
1036 * @entry: flow entry to be removed
1038 static enum ice_status
1039 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1042 return ICE_ERR_BAD_PTR;
1044 LIST_DEL(&entry->l_entry);
1046 ice_dealloc_flow_entry(hw, entry);
1052 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1053 * @hw: pointer to the HW struct
1054 * @blk: classification stage
1055 * @dir: flow direction
1056 * @prof_id: unique ID to identify this flow profile
1057 * @segs: array of one or more packet segments that describe the flow
1058 * @segs_cnt: number of packet segments provided
1059 * @acts: array of default actions
1060 * @acts_cnt: number of default actions
1061 * @prof: stores the returned flow profile added
1063 * Assumption: the caller has acquired the lock to the profile list
1065 static enum ice_status
1066 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1067 enum ice_flow_dir dir, u64 prof_id,
1068 struct ice_flow_seg_info *segs, u8 segs_cnt,
1069 struct ice_flow_action *acts, u8 acts_cnt,
1070 struct ice_flow_prof **prof)
1072 struct ice_flow_prof_params params;
1073 enum ice_status status = ICE_SUCCESS;
1076 if (!prof || (acts_cnt && !acts))
1077 return ICE_ERR_BAD_PTR;
1079 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1080 params.prof = (struct ice_flow_prof *)
1081 ice_malloc(hw, sizeof(*params.prof));
1083 return ICE_ERR_NO_MEMORY;
1085 /* initialize extraction sequence to all invalid (0xff) */
1086 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1087 params.es[i].prot_id = ICE_PROT_INVALID;
1088 params.es[i].off = ICE_FV_OFFSET_INVAL;
1092 params.prof->id = prof_id;
1093 params.prof->dir = dir;
1094 params.prof->segs_cnt = segs_cnt;
1096 /* Make a copy of the segments that need to be persistent in the flow
1099 for (i = 0; i < segs_cnt; i++)
1100 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1101 ICE_NONDMA_TO_NONDMA);
1103 /* Make a copy of the actions that need to be persistent in the flow
1107 params.prof->acts = (struct ice_flow_action *)
1108 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1109 ICE_NONDMA_TO_NONDMA);
1111 if (!params.prof->acts) {
1112 status = ICE_ERR_NO_MEMORY;
1117 status = ice_flow_proc_segs(hw, ¶ms);
1119 ice_debug(hw, ICE_DBG_FLOW,
1120 "Error processing a flow's packet segments\n");
1124 /* Add a HW profile for this flow profile */
1125 status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1126 params.es, params.mask);
1128 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1132 INIT_LIST_HEAD(¶ms.prof->entries);
1133 ice_init_lock(¶ms.prof->entries_lock);
1134 *prof = params.prof;
1138 if (params.prof->acts)
1139 ice_free(hw, params.prof->acts);
1140 ice_free(hw, params.prof);
1147 * ice_flow_rem_prof_sync - remove a flow profile
1148 * @hw: pointer to the hardware structure
1149 * @blk: classification stage
1150 * @prof: pointer to flow profile to remove
1152 * Assumption: the caller has acquired the lock to the profile list
1154 static enum ice_status
1155 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1156 struct ice_flow_prof *prof)
1158 enum ice_status status = ICE_SUCCESS;
1160 /* Remove all remaining flow entries before removing the flow profile */
1161 if (!LIST_EMPTY(&prof->entries)) {
1162 struct ice_flow_entry *e, *t;
1164 ice_acquire_lock(&prof->entries_lock);
1166 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1168 status = ice_flow_rem_entry_sync(hw, e);
1173 ice_release_lock(&prof->entries_lock);
1176 /* Remove all hardware profiles associated with this flow profile */
1177 status = ice_rem_prof(hw, blk, prof->id);
1179 LIST_DEL(&prof->l_entry);
1180 ice_destroy_lock(&prof->entries_lock);
1182 ice_free(hw, prof->acts);
1190 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1191 * @hw: pointer to the hardware structure
1192 * @blk: classification stage
1193 * @vsi_handle: software VSI handle
1194 * @vsig: target VSI group
1196 * Assumption: the caller has already verified that the VSI to
1197 * be added has the same characteristics as the VSIG and will
1198 * thereby have access to all resources added to that VSIG.
1201 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1204 enum ice_status status;
1206 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1207 return ICE_ERR_PARAM;
1209 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1210 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1212 ice_release_lock(&hw->fl_profs_locks[blk]);
1218 * ice_flow_assoc_prof - associate a VSI with a flow profile
1219 * @hw: pointer to the hardware structure
1220 * @blk: classification stage
1221 * @prof: pointer to flow profile
1222 * @vsi_handle: software VSI handle
1224 * Assumption: the caller has acquired the lock to the profile list
1225 * and the software VSI handle has been validated
1227 static enum ice_status
1228 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1229 struct ice_flow_prof *prof, u16 vsi_handle)
1231 enum ice_status status = ICE_SUCCESS;
1233 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1234 status = ice_add_prof_id_flow(hw, blk,
1235 ice_get_hw_vsi_num(hw,
1239 ice_set_bit(vsi_handle, prof->vsis);
1241 ice_debug(hw, ICE_DBG_FLOW,
1242 "HW profile add failed, %d\n",
1250 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1251 * @hw: pointer to the hardware structure
1252 * @blk: classification stage
1253 * @prof: pointer to flow profile
1254 * @vsi_handle: software VSI handle
1256 * Assumption: the caller has acquired the lock to the profile list
1257 * and the software VSI handle has been validated
1259 static enum ice_status
1260 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1261 struct ice_flow_prof *prof, u16 vsi_handle)
1263 enum ice_status status = ICE_SUCCESS;
1265 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1266 status = ice_rem_prof_id_flow(hw, blk,
1267 ice_get_hw_vsi_num(hw,
1271 ice_clear_bit(vsi_handle, prof->vsis);
1273 ice_debug(hw, ICE_DBG_FLOW,
1274 "HW profile remove failed, %d\n",
1282 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1283 * @hw: pointer to the HW struct
1284 * @blk: classification stage
1285 * @dir: flow direction
1286 * @prof_id: unique ID to identify this flow profile
1287 * @segs: array of one or more packet segments that describe the flow
1288 * @segs_cnt: number of packet segments provided
1289 * @acts: array of default actions
1290 * @acts_cnt: number of default actions
1291 * @prof: stores the returned flow profile added
1294 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1295 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1296 struct ice_flow_action *acts, u8 acts_cnt,
1297 struct ice_flow_prof **prof)
1299 enum ice_status status;
1301 if (segs_cnt > ICE_FLOW_SEG_MAX)
1302 return ICE_ERR_MAX_LIMIT;
1305 return ICE_ERR_PARAM;
1308 return ICE_ERR_BAD_PTR;
1310 status = ice_flow_val_hdrs(segs, segs_cnt);
1314 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1316 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1317 acts, acts_cnt, prof);
1319 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1321 ice_release_lock(&hw->fl_profs_locks[blk]);
1327 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1328 * @hw: pointer to the HW struct
1329 * @blk: the block for which the flow profile is to be removed
1330 * @prof_id: unique ID of the flow profile to be removed
1333 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1335 struct ice_flow_prof *prof;
1336 enum ice_status status;
1338 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1340 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1342 status = ICE_ERR_DOES_NOT_EXIST;
1346 /* prof becomes invalid after the call */
1347 status = ice_flow_rem_prof_sync(hw, blk, prof);
1350 ice_release_lock(&hw->fl_profs_locks[blk]);
1356 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1357 * @hw: pointer to the HW struct
1358 * @blk: classification stage
1359 * @prof_id: the profile ID handle
1360 * @hw_prof_id: pointer to variable to receive the HW profile ID
1363 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1366 struct ice_prof_map *map;
1368 map = ice_search_prof_id(hw, blk, prof_id);
1370 *hw_prof_id = map->prof_id;
1374 return ICE_ERR_DOES_NOT_EXIST;
1378 * ice_flow_find_entry - look for a flow entry using its unique ID
1379 * @hw: pointer to the HW struct
1380 * @blk: classification stage
1381 * @entry_id: unique ID to identify this flow entry
1383 * This function looks for the flow entry with the specified unique ID in all
1384 * flow profiles of the specified classification stage. If the entry is found,
1385 * and it returns the handle to the flow entry. Otherwise, it returns
1386 * ICE_FLOW_ENTRY_ID_INVAL.
1388 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1390 struct ice_flow_entry *found = NULL;
1391 struct ice_flow_prof *p;
1393 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1395 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1396 struct ice_flow_entry *e;
1398 ice_acquire_lock(&p->entries_lock);
1399 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1400 if (e->id == entry_id) {
1404 ice_release_lock(&p->entries_lock);
1410 ice_release_lock(&hw->fl_profs_locks[blk]);
1412 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1416 * ice_flow_add_entry - Add a flow entry
1417 * @hw: pointer to the HW struct
1418 * @blk: classification stage
1419 * @prof_id: ID of the profile to add a new flow entry to
1420 * @entry_id: unique ID to identify this flow entry
1421 * @vsi_handle: software VSI handle for the flow entry
1422 * @prio: priority of the flow entry
1423 * @data: pointer to a data buffer containing flow entry's match values/masks
1424 * @acts: arrays of actions to be performed on a match
1425 * @acts_cnt: number of actions
1426 * @entry_h: pointer to buffer that receives the new flow entry's handle
1429 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1430 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1431 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1434 struct ice_flow_prof *prof = NULL;
1435 struct ice_flow_entry *e = NULL;
1436 enum ice_status status = ICE_SUCCESS;
1438 if (acts_cnt && !acts)
1439 return ICE_ERR_PARAM;
1441 /* No flow entry data is expected for RSS */
1442 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1443 return ICE_ERR_BAD_PTR;
1445 if (!ice_is_vsi_valid(hw, vsi_handle))
1446 return ICE_ERR_PARAM;
1448 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1450 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1452 status = ICE_ERR_DOES_NOT_EXIST;
1454 /* Allocate memory for the entry being added and associate
1455 * the VSI to the found flow profile
1457 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1459 status = ICE_ERR_NO_MEMORY;
1461 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1464 ice_release_lock(&hw->fl_profs_locks[blk]);
1469 e->vsi_handle = vsi_handle;
1475 /* RSS will add only one entry per VSI per profile */
1482 status = ICE_ERR_NOT_IMPL;
1486 if (blk != ICE_BLK_ACL) {
1487 /* ACL will handle the entry management */
1488 ice_acquire_lock(&prof->entries_lock);
1489 LIST_ADD(&e->l_entry, &prof->entries);
1490 ice_release_lock(&prof->entries_lock);
1493 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1498 ice_free(hw, e->entry);
1506 * ice_flow_rem_entry - Remove a flow entry
1507 * @hw: pointer to the HW struct
1508 * @entry_h: handle to the flow entry to be removed
1510 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1512 struct ice_flow_entry *entry;
1513 struct ice_flow_prof *prof;
1514 enum ice_status status;
1516 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1517 return ICE_ERR_PARAM;
1519 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1521 /* Retain the pointer to the flow profile as the entry will be freed */
1524 ice_acquire_lock(&prof->entries_lock);
1525 status = ice_flow_rem_entry_sync(hw, entry);
1526 ice_release_lock(&prof->entries_lock);
1532 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1533 * @seg: packet segment the field being set belongs to
1534 * @fld: field to be set
1535 * @type: type of the field
1536 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1537 * entry's input buffer
1538 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1540 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1541 * entry's input buffer
1543 * This helper function stores information of a field being matched, including
1544 * the type of the field and the locations of the value to match, the mask, and
1545 * and the upper-bound value in the start of the input buffer for a flow entry.
1546 * This function should only be used for fixed-size data structures.
1548 * This function also opportunistically determines the protocol headers to be
1549 * present based on the fields being set. Some fields cannot be used alone to
1550 * determine the protocol headers present. Sometimes, fields for particular
1551 * protocol headers are not matched. In those cases, the protocol headers
1552 * must be explicitly set.
1555 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1556 enum ice_flow_fld_match_type type, u16 val_loc,
1557 u16 mask_loc, u16 last_loc)
1559 u64 bit = BIT_ULL(fld);
1562 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1565 seg->fields[fld].type = type;
1566 seg->fields[fld].src.val = val_loc;
1567 seg->fields[fld].src.mask = mask_loc;
1568 seg->fields[fld].src.last = last_loc;
1570 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1574 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1575 * @seg: packet segment the field being set belongs to
1576 * @fld: field to be set
1577 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1578 * entry's input buffer
1579 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1581 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1582 * entry's input buffer
1583 * @range: indicate if field being matched is to be in a range
1585 * This function specifies the locations, in the form of byte offsets from the
1586 * start of the input buffer for a flow entry, from where the value to match,
1587 * the mask value, and upper value can be extracted. These locations are then
1588 * stored in the flow profile. When adding a flow entry associated with the
1589 * flow profile, these locations will be used to quickly extract the values and
1590 * create the content of a match entry. This function should only be used for
1591 * fixed-size data structures.
1594 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1595 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1597 enum ice_flow_fld_match_type t = range ?
1598 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1600 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1604 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1605 * @seg: packet segment the field being set belongs to
1606 * @fld: field to be set
1607 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1608 * entry's input buffer
1609 * @pref_loc: location of prefix value from entry's input buffer
1610 * @pref_sz: size of the location holding the prefix value
1612 * This function specifies the locations, in the form of byte offsets from the
1613 * start of the input buffer for a flow entry, from where the value to match
1614 * and the IPv4 prefix value can be extracted. These locations are then stored
1615 * in the flow profile. When adding flow entries to the associated flow profile,
1616 * these locations can be used to quickly extract the values to create the
1617 * content of a match entry. This function should only be used for fixed-size
1621 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1622 u16 val_loc, u16 pref_loc, u8 pref_sz)
1624 /* For this type of field, the "mask" location is for the prefix value's
1625 * location and the "last" location is for the size of the location of
1628 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1629 pref_loc, (u16)pref_sz);
1633 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1634 * @seg: packet segment the field being set belongs to
1635 * @off: offset of the raw field from the beginning of the segment in bytes
1636 * @len: length of the raw pattern to be matched
1637 * @val_loc: location of the value to match from entry's input buffer
1638 * @mask_loc: location of mask value from entry's input buffer
1640 * This function specifies the offset of the raw field to be match from the
1641 * beginning of the specified packet segment, and the locations, in the form of
1642 * byte offsets from the start of the input buffer for a flow entry, from where
1643 * the value to match and the mask value to be extracted. These locations are
1644 * then stored in the flow profile. When adding flow entries to the associated
1645 * flow profile, these locations can be used to quickly extract the values to
1646 * create the content of a match entry. This function should only be used for
1647 * fixed-size data structures.
1650 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1651 u16 val_loc, u16 mask_loc)
1653 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1654 seg->raws[seg->raws_cnt].off = off;
1655 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1656 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1657 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1658 /* The "last" field is used to store the length of the field */
1659 seg->raws[seg->raws_cnt].info.src.last = len;
1662 /* Overflows of "raws" will be handled as an error condition later in
1663 * the flow when this information is processed.
1668 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1669 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE)
1671 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1672 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1673 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC_TEID)
1676 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1677 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1678 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1681 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1682 * @segs: pointer to the flow field segment(s)
1683 * @hash_fields: fields to be hashed on for the segment(s)
1684 * @flow_hdr: protocol header fields within a packet segment
1686 * Helper function to extract fields from hash bitmap and use flow
1687 * header value to set flow field segment for further use in flow
1688 * profile entry or removal.
1690 static enum ice_status
1691 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1694 u64 val = hash_fields;
1697 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1698 u64 bit = BIT_ULL(i);
1701 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1702 ICE_FLOW_FLD_OFF_INVAL,
1703 ICE_FLOW_FLD_OFF_INVAL,
1704 ICE_FLOW_FLD_OFF_INVAL, false);
1708 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1710 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1711 return ICE_ERR_PARAM;
1713 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1714 if (!ice_is_pow2(val))
1717 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1718 if (val && !ice_is_pow2(val))
1725 * ice_rem_vsi_rss_list - remove VSI from RSS list
1726 * @hw: pointer to the hardware structure
1727 * @vsi_handle: software VSI handle
1729 * Remove the VSI from all RSS configurations in the list.
1731 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1733 struct ice_rss_cfg *r, *tmp;
1735 if (LIST_EMPTY(&hw->rss_list_head))
1738 ice_acquire_lock(&hw->rss_locks);
1739 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1740 ice_rss_cfg, l_entry) {
1741 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1742 ice_clear_bit(vsi_handle, r->vsis);
1744 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1745 LIST_DEL(&r->l_entry);
1750 ice_release_lock(&hw->rss_locks);
1754 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1755 * @hw: pointer to the hardware structure
1756 * @vsi_handle: software VSI handle
1758 * This function will iterate through all flow profiles and disassociate
1759 * the VSI from that profile. If the flow profile has no VSIs it will
1762 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1764 const enum ice_block blk = ICE_BLK_RSS;
1765 struct ice_flow_prof *p, *t;
1766 enum ice_status status = ICE_SUCCESS;
1768 if (!ice_is_vsi_valid(hw, vsi_handle))
1769 return ICE_ERR_PARAM;
1771 if (LIST_EMPTY(&hw->fl_profs[blk]))
1774 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1775 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1777 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1778 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1782 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1783 status = ice_flow_rem_prof_sync(hw, blk, p);
1789 ice_release_lock(&hw->fl_profs_locks[blk]);
1795 * ice_rem_rss_list - remove RSS configuration from list
1796 * @hw: pointer to the hardware structure
1797 * @vsi_handle: software VSI handle
1798 * @prof: pointer to flow profile
1800 * Assumption: lock has already been acquired for RSS list
1803 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1805 struct ice_rss_cfg *r, *tmp;
1807 /* Search for RSS hash fields associated to the VSI that match the
1808 * hash configurations associated to the flow profile. If found
1809 * remove from the RSS entry list of the VSI context and delete entry.
1811 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1812 ice_rss_cfg, l_entry) {
1813 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1814 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1815 ice_clear_bit(vsi_handle, r->vsis);
1816 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1817 LIST_DEL(&r->l_entry);
1826 * ice_add_rss_list - add RSS configuration to list
1827 * @hw: pointer to the hardware structure
1828 * @vsi_handle: software VSI handle
1829 * @prof: pointer to flow profile
1831 * Assumption: lock has already been acquired for RSS list
1833 static enum ice_status
1834 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1836 struct ice_rss_cfg *r, *rss_cfg;
1838 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1839 ice_rss_cfg, l_entry)
1840 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1841 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1842 ice_set_bit(vsi_handle, r->vsis);
1846 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1848 return ICE_ERR_NO_MEMORY;
1850 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1851 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1852 ice_set_bit(vsi_handle, rss_cfg->vsis);
1854 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1859 #define ICE_FLOW_PROF_HASH_S 0
1860 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1861 #define ICE_FLOW_PROF_HDR_S 32
1862 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1863 #define ICE_FLOW_PROF_ENCAP_S 63
1864 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1866 #define ICE_RSS_OUTER_HEADERS 1
1867 #define ICE_RSS_INNER_HEADERS 2
1869 /* Flow profile ID format:
1870 * [0:31] - Packet match fields
1871 * [32:62] - Protocol header
1872 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1874 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1875 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1876 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1877 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1880 * ice_add_rss_cfg_sync - add an RSS configuration
1881 * @hw: pointer to the hardware structure
1882 * @vsi_handle: software VSI handle
1883 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1884 * @addl_hdrs: protocol header fields
1885 * @segs_cnt: packet segment count
1887 * Assumption: lock has already been acquired for RSS list
1889 static enum ice_status
1890 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1891 u32 addl_hdrs, u8 segs_cnt)
1893 const enum ice_block blk = ICE_BLK_RSS;
1894 struct ice_flow_prof *prof = NULL;
1895 struct ice_flow_seg_info *segs;
1896 enum ice_status status = ICE_SUCCESS;
1898 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1899 return ICE_ERR_PARAM;
1901 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1904 return ICE_ERR_NO_MEMORY;
1906 /* Construct the packet segment info from the hashed fields */
1907 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1912 /* Search for a flow profile that has matching headers, hash fields
1913 * and has the input VSI associated to it. If found, no further
1914 * operations required and exit.
1916 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1918 ICE_FLOW_FIND_PROF_CHK_FLDS |
1919 ICE_FLOW_FIND_PROF_CHK_VSI);
1923 /* Check if a flow profile exists with the same protocol headers and
1924 * associated with the input VSI. If so disasscociate the VSI from
1925 * this profile. The VSI will be added to a new profile created with
1926 * the protocol header and new hash field configuration.
1928 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1929 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1931 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1933 ice_rem_rss_list(hw, vsi_handle, prof);
1937 /* Remove profile if it has no VSIs associated */
1938 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1939 status = ice_flow_rem_prof(hw, blk, prof->id);
1945 /* Search for a profile that has same match fields only. If this
1946 * exists then associate the VSI to this profile.
1948 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1950 ICE_FLOW_FIND_PROF_CHK_FLDS);
1952 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1954 status = ice_add_rss_list(hw, vsi_handle, prof);
1958 /* Create a new flow profile with generated profile and packet
1959 * segment information.
1961 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1962 ICE_FLOW_GEN_PROFID(hashed_flds,
1963 segs[segs_cnt - 1].hdrs,
1965 segs, segs_cnt, NULL, 0, &prof);
1969 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1970 /* If association to a new flow profile failed then this profile can
1974 ice_flow_rem_prof(hw, blk, prof->id);
1978 status = ice_add_rss_list(hw, vsi_handle, prof);
1986 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1987 * @hw: pointer to the hardware structure
1988 * @vsi_handle: software VSI handle
1989 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1990 * @addl_hdrs: protocol header fields
1992 * This function will generate a flow profile based on fields associated with
1993 * the input fields to hash on, the flow type and use the VSI number to add
1994 * a flow entry to the profile.
1997 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2000 enum ice_status status;
2002 if (hashed_flds == ICE_HASH_INVALID ||
2003 !ice_is_vsi_valid(hw, vsi_handle))
2004 return ICE_ERR_PARAM;
2006 ice_acquire_lock(&hw->rss_locks);
2007 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2008 ICE_RSS_OUTER_HEADERS);
2010 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2011 addl_hdrs, ICE_RSS_INNER_HEADERS);
2012 ice_release_lock(&hw->rss_locks);
2018 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2019 * @hw: pointer to the hardware structure
2020 * @vsi_handle: software VSI handle
2021 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2022 * @addl_hdrs: Protocol header fields within a packet segment
2023 * @segs_cnt: packet segment count
2025 * Assumption: lock has already been acquired for RSS list
2027 static enum ice_status
2028 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2029 u32 addl_hdrs, u8 segs_cnt)
2031 const enum ice_block blk = ICE_BLK_RSS;
2032 struct ice_flow_seg_info *segs;
2033 struct ice_flow_prof *prof;
2034 enum ice_status status;
2036 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
2038 return ICE_ERR_NO_MEMORY;
2040 /* Construct the packet segment info from the hashed fields */
2041 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
2045 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2047 ICE_FLOW_FIND_PROF_CHK_FLDS);
2049 status = ICE_ERR_DOES_NOT_EXIST;
2053 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2057 /* Remove RSS configuration from VSI context before deleting
2060 ice_rem_rss_list(hw, vsi_handle, prof);
2062 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2063 status = ice_flow_rem_prof(hw, blk, prof->id);
2071 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2072 * @hw: pointer to the hardware structure
2073 * @vsi_handle: software VSI handle
2074 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2075 * @addl_hdrs: Protocol header fields within a packet segment
2077 * This function will lookup the flow profile based on the input
2078 * hash field bitmap, iterate through the profile entry list of
2079 * that profile and find entry associated with input VSI to be
2080 * removed. Calls are made to underlying flow apis which will in
2081 * turn build or update buffers for RSS XLT1 section.
2084 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2087 enum ice_status status;
2089 if (hashed_flds == ICE_HASH_INVALID ||
2090 !ice_is_vsi_valid(hw, vsi_handle))
2091 return ICE_ERR_PARAM;
2093 ice_acquire_lock(&hw->rss_locks);
2094 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2095 ICE_RSS_OUTER_HEADERS);
2097 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2098 addl_hdrs, ICE_RSS_INNER_HEADERS);
2099 ice_release_lock(&hw->rss_locks);
2104 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2105 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2106 * convert its values to their appropriate flow L3, L4 values.
2108 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2109 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2110 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2111 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2112 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2113 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2114 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2115 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2116 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2117 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2118 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2119 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2120 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2122 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2123 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2124 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2125 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2126 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2127 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2128 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2129 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2130 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2131 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2132 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2133 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2134 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2136 #define ICE_FLOW_MAX_CFG 10
2139 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2140 * @hw: pointer to the hardware structure
2141 * @vsi_handle: software VSI handle
2142 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2144 * This function will take the hash bitmap provided by the AVF driver via a
2145 * message, convert it to ICE-compatible values, and configure RSS flow
2149 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2151 enum ice_status status = ICE_SUCCESS;
2154 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2155 !ice_is_vsi_valid(hw, vsi_handle))
2156 return ICE_ERR_PARAM;
2158 /* Make sure no unsupported bits are specified */
2159 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2160 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2163 hash_flds = avf_hash;
2165 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2166 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2167 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2169 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2170 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2172 /* Create the corresponding RSS configuration for each valid hash bit */
2174 u64 rss_hash = ICE_HASH_INVALID;
2176 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2177 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2178 rss_hash = ICE_FLOW_HASH_IPV4;
2179 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2180 } else if (hash_flds &
2181 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2182 rss_hash = ICE_FLOW_HASH_IPV4 |
2183 ICE_FLOW_HASH_TCP_PORT;
2184 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2185 } else if (hash_flds &
2186 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2187 rss_hash = ICE_FLOW_HASH_IPV4 |
2188 ICE_FLOW_HASH_UDP_PORT;
2189 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2190 } else if (hash_flds &
2191 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2192 rss_hash = ICE_FLOW_HASH_IPV4 |
2193 ICE_FLOW_HASH_SCTP_PORT;
2195 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2197 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2198 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2199 rss_hash = ICE_FLOW_HASH_IPV6;
2200 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2201 } else if (hash_flds &
2202 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2203 rss_hash = ICE_FLOW_HASH_IPV6 |
2204 ICE_FLOW_HASH_TCP_PORT;
2205 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2206 } else if (hash_flds &
2207 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2208 rss_hash = ICE_FLOW_HASH_IPV6 |
2209 ICE_FLOW_HASH_UDP_PORT;
2210 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2211 } else if (hash_flds &
2212 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2213 rss_hash = ICE_FLOW_HASH_IPV6 |
2214 ICE_FLOW_HASH_SCTP_PORT;
2216 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2220 if (rss_hash == ICE_HASH_INVALID)
2221 return ICE_ERR_OUT_OF_RANGE;
2223 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2224 ICE_FLOW_SEG_HDR_NONE);
2233 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2234 * @hw: pointer to the hardware structure
2235 * @vsi_handle: software VSI handle
2237 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2239 enum ice_status status = ICE_SUCCESS;
2240 struct ice_rss_cfg *r;
2242 if (!ice_is_vsi_valid(hw, vsi_handle))
2243 return ICE_ERR_PARAM;
2245 ice_acquire_lock(&hw->rss_locks);
2246 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2247 ice_rss_cfg, l_entry) {
2248 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2249 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2252 ICE_RSS_OUTER_HEADERS);
2255 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2258 ICE_RSS_INNER_HEADERS);
2263 ice_release_lock(&hw->rss_locks);
2269 * ice_get_rss_cfg - returns hashed fields for the given header types
2270 * @hw: pointer to the hardware structure
2271 * @vsi_handle: software VSI handle
2272 * @hdrs: protocol header type
2274 * This function will return the match fields of the first instance of flow
2275 * profile having the given header types and containing input VSI
2277 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2279 struct ice_rss_cfg *r, *rss_cfg = NULL;
2281 /* verify if the protocol header is non zero and VSI is valid */
2282 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2283 return ICE_HASH_INVALID;
2285 ice_acquire_lock(&hw->rss_locks);
2286 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2287 ice_rss_cfg, l_entry)
2288 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2289 r->packet_hdr == hdrs) {
2293 ice_release_lock(&hw->rss_locks);
2295 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;