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);
364 * ice_is_pow2 - check if integer value is a power of 2
365 * @val: unsigned integer to be validated
367 static bool ice_is_pow2(u64 val)
369 return (val && !(val & (val - 1)));
372 #define ICE_FLOW_SEG_HDRS_L2_MASK \
373 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
374 #define ICE_FLOW_SEG_HDRS_L3_MASK \
375 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
376 ICE_FLOW_SEG_HDR_ARP | ICE_FLOW_SEG_HDR_PPPOE)
377 #define ICE_FLOW_SEG_HDRS_L4_MASK \
378 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
379 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC | \
380 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU_IP | \
381 ICE_FLOW_SEG_HDR_GTPU_UP | ICE_FLOW_SEG_HDR_GTPU_DWN)
384 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
385 * @segs: array of one or more packet segments that describe the flow
386 * @segs_cnt: number of packet segments provided
388 static enum ice_status
389 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
391 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
392 ICE_FLOW_SEG_HDRS_L3_MASK |
393 ICE_FLOW_SEG_HDRS_L4_MASK);
396 for (i = 0; i < segs_cnt; i++) {
397 /* No header specified */
398 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
399 return ICE_ERR_PARAM;
401 /* Multiple L3 headers */
402 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
403 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
404 return ICE_ERR_PARAM;
406 /* Multiple L4 headers */
407 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
408 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
409 return ICE_ERR_PARAM;
415 /* Sizes of fixed known protocol headers without header options */
416 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
417 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
418 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
419 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
420 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
421 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
422 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
423 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
424 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
427 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
428 * @params: information about the flow to be processed
429 * @seg: index of packet segment whose header size is to be determined
431 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
436 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
437 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
440 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
441 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
442 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
443 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
444 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
445 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
446 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
447 /* A L3 header is required if L4 is specified */
451 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
452 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
453 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
454 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
455 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
456 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
457 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
458 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
464 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
465 * @params: information about the flow to be processed
467 * This function identifies the packet types associated with the protocol
468 * headers being present in packet segments of the specified flow profile.
470 static enum ice_status
471 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
473 struct ice_flow_prof *prof;
476 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
481 for (i = 0; i < params->prof->segs_cnt; i++) {
482 const ice_bitmap_t *src;
485 hdrs = prof->segs[i].hdrs;
487 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
488 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
489 (const ice_bitmap_t *)ice_ptypes_mac_il;
490 ice_and_bitmap(params->ptypes, params->ptypes, src,
494 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
495 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
496 ice_and_bitmap(params->ptypes, params->ptypes, src,
500 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
501 ice_and_bitmap(params->ptypes, params->ptypes,
502 (const ice_bitmap_t *)ice_ptypes_arp_of,
506 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
507 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
508 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
509 ice_and_bitmap(params->ptypes, params->ptypes, src,
511 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
512 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
513 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
514 ice_and_bitmap(params->ptypes, params->ptypes, src,
518 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
519 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
520 (const ice_bitmap_t *)ice_ptypes_icmp_il;
521 ice_and_bitmap(params->ptypes, params->ptypes, src,
523 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
524 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
525 ice_and_bitmap(params->ptypes, params->ptypes, src,
527 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
528 ice_and_bitmap(params->ptypes, params->ptypes,
529 (const ice_bitmap_t *)ice_ptypes_tcp_il,
531 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
532 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
533 ice_and_bitmap(params->ptypes, params->ptypes, src,
535 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
537 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
538 ice_and_bitmap(params->ptypes, params->ptypes,
539 src, ICE_FLOW_PTYPE_MAX);
541 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
543 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
544 ice_and_bitmap(params->ptypes, params->ptypes,
545 src, ICE_FLOW_PTYPE_MAX);
547 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
549 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
550 ice_and_bitmap(params->ptypes, params->ptypes,
551 src, ICE_FLOW_PTYPE_MAX);
553 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
555 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
556 ice_and_bitmap(params->ptypes, params->ptypes,
557 src, ICE_FLOW_PTYPE_MAX);
566 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
567 * @hw: pointer to the HW struct
568 * @params: information about the flow to be processed
569 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
571 * This function will allocate an extraction sequence entries for a DWORD size
572 * chunk of the packet flags.
574 static enum ice_status
575 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
576 struct ice_flow_prof_params *params,
577 enum ice_flex_mdid_pkt_flags flags)
579 u8 fv_words = hw->blk[params->blk].es.fvw;
582 /* Make sure the number of extraction sequence entries required does not
583 * exceed the block's capacity.
585 if (params->es_cnt >= fv_words)
586 return ICE_ERR_MAX_LIMIT;
588 /* some blocks require a reversed field vector layout */
589 if (hw->blk[params->blk].es.reverse)
590 idx = fv_words - params->es_cnt - 1;
592 idx = params->es_cnt;
594 params->es[idx].prot_id = ICE_PROT_META_ID;
595 params->es[idx].off = flags;
602 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
603 * @hw: pointer to the HW struct
604 * @params: information about the flow to be processed
605 * @seg: packet segment index of the field to be extracted
606 * @fld: ID of field to be extracted
608 * This function determines the protocol ID, offset, and size of the given
609 * field. It then allocates one or more extraction sequence entries for the
610 * given field, and fill the entries with protocol ID and offset information.
612 static enum ice_status
613 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
614 u8 seg, enum ice_flow_field fld)
616 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
617 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
618 u8 fv_words = hw->blk[params->blk].es.fvw;
619 struct ice_flow_fld_info *flds;
620 u16 cnt, ese_bits, i;
625 flds = params->prof->segs[seg].fields;
628 case ICE_FLOW_FIELD_IDX_ETH_DA:
629 case ICE_FLOW_FIELD_IDX_ETH_SA:
630 case ICE_FLOW_FIELD_IDX_S_VLAN:
631 case ICE_FLOW_FIELD_IDX_C_VLAN:
632 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
634 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
635 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
637 case ICE_FLOW_FIELD_IDX_IP_DSCP:
638 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
639 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
641 case ICE_FLOW_FIELD_IDX_IP_TTL:
642 case ICE_FLOW_FIELD_IDX_IP_PROT:
643 /* Some fields are located at different offsets in IPv4 and
646 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
647 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
649 /* TTL and PROT share the same extraction seq. entry.
650 * Each is considered a sibling to the other in term
651 * sharing the same extraction sequence entry.
653 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
654 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
655 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
656 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
657 } else if (params->prof->segs[seg].hdrs &
658 ICE_FLOW_SEG_HDR_IPV6) {
659 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
661 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
662 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
663 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
664 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
667 case ICE_FLOW_FIELD_IDX_IPV4_SA:
668 case ICE_FLOW_FIELD_IDX_IPV4_DA:
669 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
671 case ICE_FLOW_FIELD_IDX_IPV6_SA:
672 case ICE_FLOW_FIELD_IDX_IPV6_DA:
673 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
675 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
676 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
677 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
678 prot_id = ICE_PROT_TCP_IL;
680 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
681 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
682 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
684 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
685 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
686 prot_id = ICE_PROT_SCTP_IL;
688 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
689 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
690 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
691 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
692 /* GTP is accessed through UDP OF protocol */
693 prot_id = ICE_PROT_UDP_OF;
695 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
696 prot_id = ICE_PROT_PPPOE;
698 case ICE_FLOW_FIELD_IDX_ARP_SIP:
699 case ICE_FLOW_FIELD_IDX_ARP_DIP:
700 case ICE_FLOW_FIELD_IDX_ARP_SHA:
701 case ICE_FLOW_FIELD_IDX_ARP_DHA:
702 case ICE_FLOW_FIELD_IDX_ARP_OP:
703 prot_id = ICE_PROT_ARP_OF;
705 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
706 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
707 /* ICMP type and code share the same extraction seq. entry */
708 prot_id = (params->prof->segs[seg].hdrs &
709 ICE_FLOW_SEG_HDR_IPV4) ?
710 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
711 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
712 ICE_FLOW_FIELD_IDX_ICMP_CODE :
713 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
715 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
716 prot_id = ICE_PROT_GRE_OF;
719 return ICE_ERR_NOT_IMPL;
722 /* Each extraction sequence entry is a word in size, and extracts a
723 * word-aligned offset from a protocol header.
725 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
727 flds[fld].xtrct.prot_id = prot_id;
728 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
729 ICE_FLOW_FV_EXTRACT_SZ;
730 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
731 flds[fld].xtrct.idx = params->es_cnt;
733 /* Adjust the next field-entry index after accommodating the number of
734 * entries this field consumes
736 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
737 ice_flds_info[fld].size, ese_bits);
739 /* Fill in the extraction sequence entries needed for this field */
740 off = flds[fld].xtrct.off;
741 mask = ice_flds_info[fld].mask;
742 for (i = 0; i < cnt; i++) {
743 /* Only consume an extraction sequence entry if there is no
744 * sibling field associated with this field or the sibling entry
745 * already extracts the word shared with this field.
747 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
748 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
749 flds[sib].xtrct.off != off) {
752 /* Make sure the number of extraction sequence required
753 * does not exceed the block's capability
755 if (params->es_cnt >= fv_words)
756 return ICE_ERR_MAX_LIMIT;
758 /* some blocks require a reversed field vector layout */
759 if (hw->blk[params->blk].es.reverse)
760 idx = fv_words - params->es_cnt - 1;
762 idx = params->es_cnt;
764 params->es[idx].prot_id = prot_id;
765 params->es[idx].off = off;
766 params->mask[idx] = mask;
770 off += ICE_FLOW_FV_EXTRACT_SZ;
777 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
778 * @hw: pointer to the HW struct
779 * @params: information about the flow to be processed
780 * @seg: index of packet segment whose raw fields are to be be extracted
782 static enum ice_status
783 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
789 if (!params->prof->segs[seg].raws_cnt)
792 if (params->prof->segs[seg].raws_cnt >
793 ARRAY_SIZE(params->prof->segs[seg].raws))
794 return ICE_ERR_MAX_LIMIT;
796 /* Offsets within the segment headers are not supported */
797 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
799 return ICE_ERR_PARAM;
801 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
802 struct ice_flow_seg_fld_raw *raw;
805 raw = ¶ms->prof->segs[seg].raws[i];
807 /* Only support matching raw fields in the payload */
808 if (raw->off < hdrs_sz)
809 return ICE_ERR_PARAM;
811 /* Convert the segment-relative offset into payload-relative
814 off = raw->off - hdrs_sz;
816 /* Storing extraction information */
817 raw->info.xtrct.prot_id = ICE_PROT_PAY;
818 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
819 ICE_FLOW_FV_EXTRACT_SZ;
820 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
822 raw->info.xtrct.idx = params->es_cnt;
824 /* Determine the number of field vector entries this raw field
827 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
828 (raw->info.src.last * BITS_PER_BYTE),
829 (ICE_FLOW_FV_EXTRACT_SZ *
831 off = raw->info.xtrct.off;
832 for (j = 0; j < cnt; j++) {
833 /* Make sure the number of extraction sequence required
834 * does not exceed the block's capability
836 if (params->es_cnt >= hw->blk[params->blk].es.count ||
837 params->es_cnt >= ICE_MAX_FV_WORDS)
838 return ICE_ERR_MAX_LIMIT;
840 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
841 params->es[params->es_cnt].off = off;
843 off += ICE_FLOW_FV_EXTRACT_SZ;
851 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
852 * @hw: pointer to the HW struct
853 * @params: information about the flow to be processed
855 * This function iterates through all matched fields in the given segments, and
856 * creates an extraction sequence for the fields.
858 static enum ice_status
859 ice_flow_create_xtrct_seq(struct ice_hw *hw,
860 struct ice_flow_prof_params *params)
862 enum ice_status status = ICE_SUCCESS;
865 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
868 if (params->blk == ICE_BLK_ACL)
869 ice_flow_xtract_pkt_flags(hw, params,
870 ICE_RX_MDID_PKT_FLAGS_15_0);
872 for (i = 0; i < params->prof->segs_cnt; i++) {
873 u64 match = params->prof->segs[i].match;
876 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
877 const u64 bit = BIT_ULL(j);
880 status = ice_flow_xtract_fld
881 (hw, params, i, (enum ice_flow_field)j);
888 /* Process raw matching bytes */
889 status = ice_flow_xtract_raws(hw, params, i);
898 * ice_flow_proc_segs - process all packet segments associated with a profile
899 * @hw: pointer to the HW struct
900 * @params: information about the flow to be processed
902 static enum ice_status
903 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
905 enum ice_status status;
907 status = ice_flow_proc_seg_hdrs(params);
911 status = ice_flow_create_xtrct_seq(hw, params);
915 switch (params->blk) {
917 /* Only header information is provided for RSS configuration.
918 * No further processing is needed.
920 status = ICE_SUCCESS;
923 status = ICE_SUCCESS;
927 return ICE_ERR_NOT_IMPL;
933 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
934 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
935 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
938 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
939 * @hw: pointer to the HW struct
940 * @blk: classification stage
941 * @dir: flow direction
942 * @segs: array of one or more packet segments that describe the flow
943 * @segs_cnt: number of packet segments provided
944 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
945 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
947 static struct ice_flow_prof *
948 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
949 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
950 u8 segs_cnt, u16 vsi_handle, u32 conds)
952 struct ice_flow_prof *p, *prof = NULL;
954 ice_acquire_lock(&hw->fl_profs_locks[blk]);
955 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
956 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
957 segs_cnt && segs_cnt == p->segs_cnt) {
960 /* Check for profile-VSI association if specified */
961 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
962 ice_is_vsi_valid(hw, vsi_handle) &&
963 !ice_is_bit_set(p->vsis, vsi_handle))
966 /* Protocol headers must be checked. Matched fields are
967 * checked if specified.
969 for (i = 0; i < segs_cnt; i++)
970 if (segs[i].hdrs != p->segs[i].hdrs ||
971 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
972 segs[i].match != p->segs[i].match))
975 /* A match is found if all segments are matched */
982 ice_release_lock(&hw->fl_profs_locks[blk]);
988 * ice_flow_find_prof - Look up a profile matching headers and matched fields
989 * @hw: pointer to the HW struct
990 * @blk: classification stage
991 * @dir: flow direction
992 * @segs: array of one or more packet segments that describe the flow
993 * @segs_cnt: number of packet segments provided
996 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
997 struct ice_flow_seg_info *segs, u8 segs_cnt)
999 struct ice_flow_prof *p;
1001 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1002 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1004 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1008 * ice_flow_find_prof_id - Look up a profile with given profile ID
1009 * @hw: pointer to the HW struct
1010 * @blk: classification stage
1011 * @prof_id: unique ID to identify this flow profile
1013 static struct ice_flow_prof *
1014 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1016 struct ice_flow_prof *p;
1018 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1019 if (p->id == prof_id)
1027 * ice_dealloc_flow_entry - Deallocate flow entry memory
1028 * @hw: pointer to the HW struct
1029 * @entry: flow entry to be removed
1032 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1038 ice_free(hw, entry->entry);
1041 ice_free(hw, entry->acts);
1043 entry->acts_cnt = 0;
1046 ice_free(hw, entry);
1050 * ice_flow_rem_entry_sync - Remove a flow entry
1051 * @hw: pointer to the HW struct
1052 * @entry: flow entry to be removed
1054 static enum ice_status
1055 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1058 return ICE_ERR_BAD_PTR;
1060 LIST_DEL(&entry->l_entry);
1062 ice_dealloc_flow_entry(hw, entry);
1068 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1069 * @hw: pointer to the HW struct
1070 * @blk: classification stage
1071 * @dir: flow direction
1072 * @prof_id: unique ID to identify this flow profile
1073 * @segs: array of one or more packet segments that describe the flow
1074 * @segs_cnt: number of packet segments provided
1075 * @acts: array of default actions
1076 * @acts_cnt: number of default actions
1077 * @prof: stores the returned flow profile added
1079 * Assumption: the caller has acquired the lock to the profile list
1081 static enum ice_status
1082 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1083 enum ice_flow_dir dir, u64 prof_id,
1084 struct ice_flow_seg_info *segs, u8 segs_cnt,
1085 struct ice_flow_action *acts, u8 acts_cnt,
1086 struct ice_flow_prof **prof)
1088 struct ice_flow_prof_params params;
1089 enum ice_status status = ICE_SUCCESS;
1092 if (!prof || (acts_cnt && !acts))
1093 return ICE_ERR_BAD_PTR;
1095 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1096 params.prof = (struct ice_flow_prof *)
1097 ice_malloc(hw, sizeof(*params.prof));
1099 return ICE_ERR_NO_MEMORY;
1101 /* initialize extraction sequence to all invalid (0xff) */
1102 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1103 params.es[i].prot_id = ICE_PROT_INVALID;
1104 params.es[i].off = ICE_FV_OFFSET_INVAL;
1108 params.prof->id = prof_id;
1109 params.prof->dir = dir;
1110 params.prof->segs_cnt = segs_cnt;
1112 /* Make a copy of the segments that need to be persistent in the flow
1115 for (i = 0; i < segs_cnt; i++)
1116 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1117 ICE_NONDMA_TO_NONDMA);
1119 /* Make a copy of the actions that need to be persistent in the flow
1123 params.prof->acts = (struct ice_flow_action *)
1124 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1125 ICE_NONDMA_TO_NONDMA);
1127 if (!params.prof->acts) {
1128 status = ICE_ERR_NO_MEMORY;
1133 status = ice_flow_proc_segs(hw, ¶ms);
1135 ice_debug(hw, ICE_DBG_FLOW,
1136 "Error processing a flow's packet segments\n");
1140 /* Add a HW profile for this flow profile */
1141 status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1142 params.es, params.mask);
1144 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1148 INIT_LIST_HEAD(¶ms.prof->entries);
1149 ice_init_lock(¶ms.prof->entries_lock);
1150 *prof = params.prof;
1154 if (params.prof->acts)
1155 ice_free(hw, params.prof->acts);
1156 ice_free(hw, params.prof);
1163 * ice_flow_rem_prof_sync - remove a flow profile
1164 * @hw: pointer to the hardware structure
1165 * @blk: classification stage
1166 * @prof: pointer to flow profile to remove
1168 * Assumption: the caller has acquired the lock to the profile list
1170 static enum ice_status
1171 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1172 struct ice_flow_prof *prof)
1174 enum ice_status status = ICE_SUCCESS;
1176 /* Remove all remaining flow entries before removing the flow profile */
1177 if (!LIST_EMPTY(&prof->entries)) {
1178 struct ice_flow_entry *e, *t;
1180 ice_acquire_lock(&prof->entries_lock);
1182 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1184 status = ice_flow_rem_entry_sync(hw, e);
1189 ice_release_lock(&prof->entries_lock);
1192 /* Remove all hardware profiles associated with this flow profile */
1193 status = ice_rem_prof(hw, blk, prof->id);
1195 LIST_DEL(&prof->l_entry);
1196 ice_destroy_lock(&prof->entries_lock);
1198 ice_free(hw, prof->acts);
1206 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1207 * @hw: pointer to the hardware structure
1208 * @blk: classification stage
1209 * @vsi_handle: software VSI handle
1210 * @vsig: target VSI group
1212 * Assumption: the caller has already verified that the VSI to
1213 * be added has the same characteristics as the VSIG and will
1214 * thereby have access to all resources added to that VSIG.
1217 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1220 enum ice_status status;
1222 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1223 return ICE_ERR_PARAM;
1225 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1226 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1228 ice_release_lock(&hw->fl_profs_locks[blk]);
1234 * ice_flow_assoc_prof - associate a VSI with a flow profile
1235 * @hw: pointer to the hardware structure
1236 * @blk: classification stage
1237 * @prof: pointer to flow profile
1238 * @vsi_handle: software VSI handle
1240 * Assumption: the caller has acquired the lock to the profile list
1241 * and the software VSI handle has been validated
1243 static enum ice_status
1244 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1245 struct ice_flow_prof *prof, u16 vsi_handle)
1247 enum ice_status status = ICE_SUCCESS;
1249 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1250 status = ice_add_prof_id_flow(hw, blk,
1251 ice_get_hw_vsi_num(hw,
1255 ice_set_bit(vsi_handle, prof->vsis);
1257 ice_debug(hw, ICE_DBG_FLOW,
1258 "HW profile add failed, %d\n",
1266 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1267 * @hw: pointer to the hardware structure
1268 * @blk: classification stage
1269 * @prof: pointer to flow profile
1270 * @vsi_handle: software VSI handle
1272 * Assumption: the caller has acquired the lock to the profile list
1273 * and the software VSI handle has been validated
1275 static enum ice_status
1276 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1277 struct ice_flow_prof *prof, u16 vsi_handle)
1279 enum ice_status status = ICE_SUCCESS;
1281 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1282 status = ice_rem_prof_id_flow(hw, blk,
1283 ice_get_hw_vsi_num(hw,
1287 ice_clear_bit(vsi_handle, prof->vsis);
1289 ice_debug(hw, ICE_DBG_FLOW,
1290 "HW profile remove failed, %d\n",
1298 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1299 * @hw: pointer to the HW struct
1300 * @blk: classification stage
1301 * @dir: flow direction
1302 * @prof_id: unique ID to identify this flow profile
1303 * @segs: array of one or more packet segments that describe the flow
1304 * @segs_cnt: number of packet segments provided
1305 * @acts: array of default actions
1306 * @acts_cnt: number of default actions
1307 * @prof: stores the returned flow profile added
1310 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1311 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1312 struct ice_flow_action *acts, u8 acts_cnt,
1313 struct ice_flow_prof **prof)
1315 enum ice_status status;
1317 if (segs_cnt > ICE_FLOW_SEG_MAX)
1318 return ICE_ERR_MAX_LIMIT;
1321 return ICE_ERR_PARAM;
1324 return ICE_ERR_BAD_PTR;
1326 status = ice_flow_val_hdrs(segs, segs_cnt);
1330 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1332 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1333 acts, acts_cnt, prof);
1335 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1337 ice_release_lock(&hw->fl_profs_locks[blk]);
1343 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1344 * @hw: pointer to the HW struct
1345 * @blk: the block for which the flow profile is to be removed
1346 * @prof_id: unique ID of the flow profile to be removed
1349 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1351 struct ice_flow_prof *prof;
1352 enum ice_status status;
1354 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1356 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1358 status = ICE_ERR_DOES_NOT_EXIST;
1362 /* prof becomes invalid after the call */
1363 status = ice_flow_rem_prof_sync(hw, blk, prof);
1366 ice_release_lock(&hw->fl_profs_locks[blk]);
1372 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1373 * @hw: pointer to the HW struct
1374 * @blk: classification stage
1375 * @prof_id: the profile ID handle
1376 * @hw_prof_id: pointer to variable to receive the HW profile ID
1379 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1382 struct ice_prof_map *map;
1384 map = ice_search_prof_id(hw, blk, prof_id);
1386 *hw_prof_id = map->prof_id;
1390 return ICE_ERR_DOES_NOT_EXIST;
1394 * ice_flow_find_entry - look for a flow entry using its unique ID
1395 * @hw: pointer to the HW struct
1396 * @blk: classification stage
1397 * @entry_id: unique ID to identify this flow entry
1399 * This function looks for the flow entry with the specified unique ID in all
1400 * flow profiles of the specified classification stage. If the entry is found,
1401 * and it returns the handle to the flow entry. Otherwise, it returns
1402 * ICE_FLOW_ENTRY_ID_INVAL.
1404 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1406 struct ice_flow_entry *found = NULL;
1407 struct ice_flow_prof *p;
1409 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1411 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1412 struct ice_flow_entry *e;
1414 ice_acquire_lock(&p->entries_lock);
1415 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1416 if (e->id == entry_id) {
1420 ice_release_lock(&p->entries_lock);
1426 ice_release_lock(&hw->fl_profs_locks[blk]);
1428 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1432 * ice_flow_add_entry - Add a flow entry
1433 * @hw: pointer to the HW struct
1434 * @blk: classification stage
1435 * @prof_id: ID of the profile to add a new flow entry to
1436 * @entry_id: unique ID to identify this flow entry
1437 * @vsi_handle: software VSI handle for the flow entry
1438 * @prio: priority of the flow entry
1439 * @data: pointer to a data buffer containing flow entry's match values/masks
1440 * @acts: arrays of actions to be performed on a match
1441 * @acts_cnt: number of actions
1442 * @entry_h: pointer to buffer that receives the new flow entry's handle
1445 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1446 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1447 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1450 struct ice_flow_prof *prof = NULL;
1451 struct ice_flow_entry *e = NULL;
1452 enum ice_status status = ICE_SUCCESS;
1454 if (acts_cnt && !acts)
1455 return ICE_ERR_PARAM;
1457 /* No flow entry data is expected for RSS */
1458 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1459 return ICE_ERR_BAD_PTR;
1461 if (!ice_is_vsi_valid(hw, vsi_handle))
1462 return ICE_ERR_PARAM;
1464 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1466 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1468 status = ICE_ERR_DOES_NOT_EXIST;
1470 /* Allocate memory for the entry being added and associate
1471 * the VSI to the found flow profile
1473 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1475 status = ICE_ERR_NO_MEMORY;
1477 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1480 ice_release_lock(&hw->fl_profs_locks[blk]);
1485 e->vsi_handle = vsi_handle;
1491 /* RSS will add only one entry per VSI per profile */
1498 status = ICE_ERR_NOT_IMPL;
1502 if (blk != ICE_BLK_ACL) {
1503 /* ACL will handle the entry management */
1504 ice_acquire_lock(&prof->entries_lock);
1505 LIST_ADD(&e->l_entry, &prof->entries);
1506 ice_release_lock(&prof->entries_lock);
1509 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1514 ice_free(hw, e->entry);
1522 * ice_flow_rem_entry - Remove a flow entry
1523 * @hw: pointer to the HW struct
1524 * @entry_h: handle to the flow entry to be removed
1526 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1528 struct ice_flow_entry *entry;
1529 struct ice_flow_prof *prof;
1530 enum ice_status status;
1532 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1533 return ICE_ERR_PARAM;
1535 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1537 /* Retain the pointer to the flow profile as the entry will be freed */
1540 ice_acquire_lock(&prof->entries_lock);
1541 status = ice_flow_rem_entry_sync(hw, entry);
1542 ice_release_lock(&prof->entries_lock);
1548 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1549 * @seg: packet segment the field being set belongs to
1550 * @fld: field to be set
1551 * @type: type of the field
1552 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1553 * entry's input buffer
1554 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1556 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1557 * entry's input buffer
1559 * This helper function stores information of a field being matched, including
1560 * the type of the field and the locations of the value to match, the mask, and
1561 * and the upper-bound value in the start of the input buffer for a flow entry.
1562 * This function should only be used for fixed-size data structures.
1564 * This function also opportunistically determines the protocol headers to be
1565 * present based on the fields being set. Some fields cannot be used alone to
1566 * determine the protocol headers present. Sometimes, fields for particular
1567 * protocol headers are not matched. In those cases, the protocol headers
1568 * must be explicitly set.
1571 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1572 enum ice_flow_fld_match_type type, u16 val_loc,
1573 u16 mask_loc, u16 last_loc)
1575 u64 bit = BIT_ULL(fld);
1578 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1581 seg->fields[fld].type = type;
1582 seg->fields[fld].src.val = val_loc;
1583 seg->fields[fld].src.mask = mask_loc;
1584 seg->fields[fld].src.last = last_loc;
1586 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1590 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1591 * @seg: packet segment the field being set belongs to
1592 * @fld: field to be set
1593 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1594 * entry's input buffer
1595 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1597 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1598 * entry's input buffer
1599 * @range: indicate if field being matched is to be in a range
1601 * This function specifies the locations, in the form of byte offsets from the
1602 * start of the input buffer for a flow entry, from where the value to match,
1603 * the mask value, and upper value can be extracted. These locations are then
1604 * stored in the flow profile. When adding a flow entry associated with the
1605 * flow profile, these locations will be used to quickly extract the values and
1606 * create the content of a match entry. This function should only be used for
1607 * fixed-size data structures.
1610 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1611 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1613 enum ice_flow_fld_match_type t = range ?
1614 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1616 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1620 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1621 * @seg: packet segment the field being set belongs to
1622 * @fld: field to be set
1623 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1624 * entry's input buffer
1625 * @pref_loc: location of prefix value from entry's input buffer
1626 * @pref_sz: size of the location holding the prefix value
1628 * This function specifies the locations, in the form of byte offsets from the
1629 * start of the input buffer for a flow entry, from where the value to match
1630 * and the IPv4 prefix value can be extracted. These locations are then stored
1631 * in the flow profile. When adding flow entries to the associated flow profile,
1632 * these locations can be used to quickly extract the values to create the
1633 * content of a match entry. This function should only be used for fixed-size
1637 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1638 u16 val_loc, u16 pref_loc, u8 pref_sz)
1640 /* For this type of field, the "mask" location is for the prefix value's
1641 * location and the "last" location is for the size of the location of
1644 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1645 pref_loc, (u16)pref_sz);
1649 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1650 * @seg: packet segment the field being set belongs to
1651 * @off: offset of the raw field from the beginning of the segment in bytes
1652 * @len: length of the raw pattern to be matched
1653 * @val_loc: location of the value to match from entry's input buffer
1654 * @mask_loc: location of mask value from entry's input buffer
1656 * This function specifies the offset of the raw field to be match from the
1657 * beginning of the specified packet segment, and the locations, in the form of
1658 * byte offsets from the start of the input buffer for a flow entry, from where
1659 * the value to match and the mask value to be extracted. These locations are
1660 * then stored in the flow profile. When adding flow entries to the associated
1661 * flow profile, these locations can be used to quickly extract the values to
1662 * create the content of a match entry. This function should only be used for
1663 * fixed-size data structures.
1666 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1667 u16 val_loc, u16 mask_loc)
1669 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1670 seg->raws[seg->raws_cnt].off = off;
1671 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1672 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1673 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1674 /* The "last" field is used to store the length of the field */
1675 seg->raws[seg->raws_cnt].info.src.last = len;
1678 /* Overflows of "raws" will be handled as an error condition later in
1679 * the flow when this information is processed.
1684 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1685 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_PPPOE)
1687 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1688 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1689 ICE_FLOW_SEG_HDR_SCTP | ICE_FLOW_SEG_HDR_GTPC_TEID)
1692 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1693 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1694 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1697 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1698 * @segs: pointer to the flow field segment(s)
1699 * @hash_fields: fields to be hashed on for the segment(s)
1700 * @flow_hdr: protocol header fields within a packet segment
1702 * Helper function to extract fields from hash bitmap and use flow
1703 * header value to set flow field segment for further use in flow
1704 * profile entry or removal.
1706 static enum ice_status
1707 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1710 u64 val = hash_fields;
1713 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1714 u64 bit = BIT_ULL(i);
1717 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1718 ICE_FLOW_FLD_OFF_INVAL,
1719 ICE_FLOW_FLD_OFF_INVAL,
1720 ICE_FLOW_FLD_OFF_INVAL, false);
1724 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1726 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1727 return ICE_ERR_PARAM;
1729 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1730 if (!ice_is_pow2(val))
1733 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1734 if (val && !ice_is_pow2(val))
1741 * ice_rem_vsi_rss_list - remove VSI from RSS list
1742 * @hw: pointer to the hardware structure
1743 * @vsi_handle: software VSI handle
1745 * Remove the VSI from all RSS configurations in the list.
1747 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1749 struct ice_rss_cfg *r, *tmp;
1751 if (LIST_EMPTY(&hw->rss_list_head))
1754 ice_acquire_lock(&hw->rss_locks);
1755 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1756 ice_rss_cfg, l_entry) {
1757 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1758 ice_clear_bit(vsi_handle, r->vsis);
1760 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1761 LIST_DEL(&r->l_entry);
1766 ice_release_lock(&hw->rss_locks);
1770 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1771 * @hw: pointer to the hardware structure
1772 * @vsi_handle: software VSI handle
1774 * This function will iterate through all flow profiles and disassociate
1775 * the VSI from that profile. If the flow profile has no VSIs it will
1778 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1780 const enum ice_block blk = ICE_BLK_RSS;
1781 struct ice_flow_prof *p, *t;
1782 enum ice_status status = ICE_SUCCESS;
1784 if (!ice_is_vsi_valid(hw, vsi_handle))
1785 return ICE_ERR_PARAM;
1787 if (LIST_EMPTY(&hw->fl_profs[blk]))
1790 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1791 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1793 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1794 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1798 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1799 status = ice_flow_rem_prof_sync(hw, blk, p);
1805 ice_release_lock(&hw->fl_profs_locks[blk]);
1811 * ice_rem_rss_list - remove RSS configuration from list
1812 * @hw: pointer to the hardware structure
1813 * @vsi_handle: software VSI handle
1814 * @prof: pointer to flow profile
1816 * Assumption: lock has already been acquired for RSS list
1819 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1821 struct ice_rss_cfg *r, *tmp;
1823 /* Search for RSS hash fields associated to the VSI that match the
1824 * hash configurations associated to the flow profile. If found
1825 * remove from the RSS entry list of the VSI context and delete entry.
1827 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1828 ice_rss_cfg, l_entry) {
1829 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1830 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1831 ice_clear_bit(vsi_handle, r->vsis);
1832 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1833 LIST_DEL(&r->l_entry);
1842 * ice_add_rss_list - add RSS configuration to list
1843 * @hw: pointer to the hardware structure
1844 * @vsi_handle: software VSI handle
1845 * @prof: pointer to flow profile
1847 * Assumption: lock has already been acquired for RSS list
1849 static enum ice_status
1850 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1852 struct ice_rss_cfg *r, *rss_cfg;
1854 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1855 ice_rss_cfg, l_entry)
1856 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1857 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1858 ice_set_bit(vsi_handle, r->vsis);
1862 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1864 return ICE_ERR_NO_MEMORY;
1866 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1867 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1868 ice_set_bit(vsi_handle, rss_cfg->vsis);
1870 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1875 #define ICE_FLOW_PROF_HASH_S 0
1876 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1877 #define ICE_FLOW_PROF_HDR_S 32
1878 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1880 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1881 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1882 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1885 * ice_add_rss_cfg_sync - add an RSS configuration
1886 * @hw: pointer to the hardware structure
1887 * @vsi_handle: software VSI handle
1888 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1889 * @addl_hdrs: protocol header fields
1891 * Assumption: lock has already been acquired for RSS list
1893 static enum ice_status
1894 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1897 const enum ice_block blk = ICE_BLK_RSS;
1898 struct ice_flow_prof *prof = NULL;
1899 struct ice_flow_seg_info *segs;
1900 enum ice_status status = ICE_SUCCESS;
1902 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
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, hashed_flds, addl_hdrs);
1911 /* Search for a flow profile that has matching headers, hash fields
1912 * and has the input VSI associated to it. If found, no further
1913 * operations required and exit.
1915 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1917 ICE_FLOW_FIND_PROF_CHK_FLDS |
1918 ICE_FLOW_FIND_PROF_CHK_VSI);
1922 /* Check if a flow profile exists with the same protocol headers and
1923 * associated with the input VSI. If so disasscociate the VSI from
1924 * this profile. The VSI will be added to a new profile created with
1925 * the protocol header and new hash field configuration.
1927 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1928 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1930 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1932 ice_rem_rss_list(hw, vsi_handle, prof);
1936 /* Remove profile if it has no VSIs associated */
1937 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1938 status = ice_flow_rem_prof(hw, blk, prof->id);
1944 /* Search for a profile that has same match fields only. If this
1945 * exists then associate the VSI to this profile.
1947 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1949 ICE_FLOW_FIND_PROF_CHK_FLDS);
1951 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1953 status = ice_add_rss_list(hw, vsi_handle, prof);
1957 /* Create a new flow profile with generated profile and packet
1958 * segment information.
1960 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1961 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1962 segs, 1, NULL, 0, &prof);
1966 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1967 /* If association to a new flow profile failed then this profile can
1971 ice_flow_rem_prof(hw, blk, prof->id);
1975 status = ice_add_rss_list(hw, vsi_handle, prof);
1983 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1984 * @hw: pointer to the hardware structure
1985 * @vsi_handle: software VSI handle
1986 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1987 * @addl_hdrs: protocol header fields
1989 * This function will generate a flow profile based on fields associated with
1990 * the input fields to hash on, the flow type and use the VSI number to add
1991 * a flow entry to the profile.
1994 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1997 enum ice_status status;
1999 if (hashed_flds == ICE_HASH_INVALID ||
2000 !ice_is_vsi_valid(hw, vsi_handle))
2001 return ICE_ERR_PARAM;
2003 ice_acquire_lock(&hw->rss_locks);
2004 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2005 ice_release_lock(&hw->rss_locks);
2011 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2012 * @hw: pointer to the hardware structure
2013 * @vsi_handle: software VSI handle
2014 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2015 * @addl_hdrs: Protocol header fields within a packet segment
2017 * Assumption: lock has already been acquired for RSS list
2019 static enum ice_status
2020 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2023 const enum ice_block blk = ICE_BLK_RSS;
2024 struct ice_flow_seg_info *segs;
2025 struct ice_flow_prof *prof;
2026 enum ice_status status;
2028 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
2030 return ICE_ERR_NO_MEMORY;
2032 /* Construct the packet segment info from the hashed fields */
2033 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
2037 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
2039 ICE_FLOW_FIND_PROF_CHK_FLDS);
2041 status = ICE_ERR_DOES_NOT_EXIST;
2045 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2049 /* Remove RSS configuration from VSI context before deleting
2052 ice_rem_rss_list(hw, vsi_handle, prof);
2054 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2055 status = ice_flow_rem_prof(hw, blk, prof->id);
2062 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2063 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2064 * convert its values to their appropriate flow L3, L4 values.
2066 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2067 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2068 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2069 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2070 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2071 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2072 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2073 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2074 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2075 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2076 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2077 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2078 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2080 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2081 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2082 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2083 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2084 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2085 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2086 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2087 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2088 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2089 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2090 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2091 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2092 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2094 #define ICE_FLOW_MAX_CFG 10
2097 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2098 * @hw: pointer to the hardware structure
2099 * @vsi_handle: software VSI handle
2100 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2102 * This function will take the hash bitmap provided by the AVF driver via a
2103 * message, convert it to ICE-compatible values, and configure RSS flow
2107 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2109 enum ice_status status = ICE_SUCCESS;
2112 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2113 !ice_is_vsi_valid(hw, vsi_handle))
2114 return ICE_ERR_PARAM;
2116 /* Make sure no unsupported bits are specified */
2117 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2118 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2121 hash_flds = avf_hash;
2123 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2124 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2125 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2127 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2128 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2130 /* Create the corresponding RSS configuration for each valid hash bit */
2132 u64 rss_hash = ICE_HASH_INVALID;
2134 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2135 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2136 rss_hash = ICE_FLOW_HASH_IPV4;
2137 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2138 } else if (hash_flds &
2139 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2140 rss_hash = ICE_FLOW_HASH_IPV4 |
2141 ICE_FLOW_HASH_TCP_PORT;
2142 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2143 } else if (hash_flds &
2144 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2145 rss_hash = ICE_FLOW_HASH_IPV4 |
2146 ICE_FLOW_HASH_UDP_PORT;
2147 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2148 } else if (hash_flds &
2149 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2150 rss_hash = ICE_FLOW_HASH_IPV4 |
2151 ICE_FLOW_HASH_SCTP_PORT;
2153 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2155 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2156 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2157 rss_hash = ICE_FLOW_HASH_IPV6;
2158 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2159 } else if (hash_flds &
2160 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2161 rss_hash = ICE_FLOW_HASH_IPV6 |
2162 ICE_FLOW_HASH_TCP_PORT;
2163 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2164 } else if (hash_flds &
2165 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2166 rss_hash = ICE_FLOW_HASH_IPV6 |
2167 ICE_FLOW_HASH_UDP_PORT;
2168 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2169 } else if (hash_flds &
2170 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2171 rss_hash = ICE_FLOW_HASH_IPV6 |
2172 ICE_FLOW_HASH_SCTP_PORT;
2174 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2178 if (rss_hash == ICE_HASH_INVALID)
2179 return ICE_ERR_OUT_OF_RANGE;
2181 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2182 ICE_FLOW_SEG_HDR_NONE);
2191 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2192 * @hw: pointer to the hardware structure
2193 * @vsi_handle: software VSI handle
2194 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2195 * @addl_hdrs: Protocol header fields within a packet segment
2197 * This function will lookup the flow profile based on the input
2198 * hash field bitmap, iterate through the profile entry list of
2199 * that profile and find entry associated with input VSI to be
2200 * removed. Calls are made to underlying flow apis which will in
2201 * turn build or update buffers for RSS XLT1 section.
2204 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2207 enum ice_status status;
2209 if (hashed_flds == ICE_HASH_INVALID ||
2210 !ice_is_vsi_valid(hw, vsi_handle))
2211 return ICE_ERR_PARAM;
2213 ice_acquire_lock(&hw->rss_locks);
2214 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2215 ice_release_lock(&hw->rss_locks);
2221 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2222 * @hw: pointer to the hardware structure
2223 * @vsi_handle: software VSI handle
2225 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2227 enum ice_status status = ICE_SUCCESS;
2228 struct ice_rss_cfg *r;
2230 if (!ice_is_vsi_valid(hw, vsi_handle))
2231 return ICE_ERR_PARAM;
2233 ice_acquire_lock(&hw->rss_locks);
2234 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2235 ice_rss_cfg, l_entry) {
2236 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2237 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2244 ice_release_lock(&hw->rss_locks);
2250 * ice_get_rss_cfg - returns hashed fields for the given header types
2251 * @hw: pointer to the hardware structure
2252 * @vsi_handle: software VSI handle
2253 * @hdrs: protocol header type
2255 * This function will return the match fields of the first instance of flow
2256 * profile having the given header types and containing input VSI
2258 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2260 struct ice_rss_cfg *r, *rss_cfg = NULL;
2262 /* verify if the protocol header is non zero and VSI is valid */
2263 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2264 return ICE_HASH_INVALID;
2266 ice_acquire_lock(&hw->rss_locks);
2267 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2268 ice_rss_cfg, l_entry)
2269 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2270 r->packet_hdr == hdrs) {
2274 ice_release_lock(&hw->rss_locks);
2276 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;