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 /* Describe properties of a protocol header field */
26 struct ice_flow_field_info {
27 enum ice_flow_seg_hdr hdr;
28 s16 off; /* Offset from start of a protocol header, in bits */
29 u16 size; /* Size of fields in bits */
30 u16 mask; /* 16-bit mask for field */
33 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
35 .off = (_offset_bytes) * BITS_PER_BYTE, \
36 .size = (_size_bytes) * BITS_PER_BYTE, \
40 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
42 .off = (_offset_bytes) * BITS_PER_BYTE, \
43 .size = (_size_bytes) * BITS_PER_BYTE, \
47 /* Table containing properties of supported protocol header fields */
49 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
51 /* ICE_FLOW_FIELD_IDX_ETH_DA */
52 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
53 /* ICE_FLOW_FIELD_IDX_ETH_SA */
54 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
55 /* ICE_FLOW_FIELD_IDX_S_VLAN */
56 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
57 /* ICE_FLOW_FIELD_IDX_C_VLAN */
58 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
59 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
60 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
62 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
63 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
65 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
66 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
68 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
69 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
70 ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
71 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
72 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
73 ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
74 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
75 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
76 ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
77 /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
78 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
79 ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
80 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
81 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
82 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
83 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
84 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
85 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
86 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
87 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
89 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
90 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
91 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
93 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
95 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
97 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
99 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
101 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
102 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
104 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
105 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
106 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
107 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
108 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
109 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
110 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
111 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
112 /* ICE_FLOW_FIELD_IDX_ARP_OP */
113 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
115 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
116 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
117 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
118 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
120 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
121 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
123 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
124 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
125 ICE_FLOW_FLD_SZ_GTP_TEID),
126 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
127 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
128 ICE_FLOW_FLD_SZ_GTP_TEID),
129 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
130 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
131 ICE_FLOW_FLD_SZ_GTP_TEID),
132 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
133 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
134 ICE_FLOW_FLD_SZ_GTP_TEID),
136 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
137 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
138 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
141 /* Bitmaps indicating relevant packet types for a particular protocol header
143 * Packet types for packets with an Outer/First/Single MAC header
145 static const u32 ice_ptypes_mac_ofos[] = {
146 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
147 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
148 0x00000000, 0x00003000, 0x00000000, 0x00000000,
149 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 0x00000000, 0x00000000, 0x00000000, 0x00000000,
151 0x00000000, 0x00000000, 0x00000000, 0x00000000,
152 0x00000000, 0x00000000, 0x00000000, 0x00000000,
153 0x00000000, 0x00000000, 0x00000000, 0x00000000,
156 /* Packet types for packets with an Innermost/Last MAC VLAN header */
157 static const u32 ice_ptypes_macvlan_il[] = {
158 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
159 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 0x00000000, 0x00000000, 0x00000000, 0x00000000,
163 0x00000000, 0x00000000, 0x00000000, 0x00000000,
164 0x00000000, 0x00000000, 0x00000000, 0x00000000,
165 0x00000000, 0x00000000, 0x00000000, 0x00000000,
168 /* Packet types for packets with an Outer/First/Single IPv4 header */
169 static const u32 ice_ptypes_ipv4_ofos[] = {
170 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
171 0x00000000, 0x00000000, 0x00000000, 0x00000000,
172 0x00000000, 0x000FC000, 0x00000000, 0x00000000,
173 0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 0x00000000, 0x00000000, 0x00000000, 0x00000000,
176 0x00000000, 0x00000000, 0x00000000, 0x00000000,
177 0x00000000, 0x00000000, 0x00000000, 0x00000000,
180 /* Packet types for packets with an Innermost/Last IPv4 header */
181 static const u32 ice_ptypes_ipv4_il[] = {
182 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
183 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x001FF800, 0x00000000,
185 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 0x00000000, 0x00000000, 0x00000000, 0x00000000,
187 0x00000000, 0x00000000, 0x00000000, 0x00000000,
188 0x00000000, 0x00000000, 0x00000000, 0x00000000,
189 0x00000000, 0x00000000, 0x00000000, 0x00000000,
192 /* Packet types for packets with an Outer/First/Single IPv6 header */
193 static const u32 ice_ptypes_ipv6_ofos[] = {
194 0x00000000, 0x00000000, 0x77000000, 0x10002000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x03F00000, 0x00000000, 0x00000000,
197 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 0x00000000, 0x00000000, 0x00000000, 0x00000000,
199 0x00000000, 0x00000000, 0x00000000, 0x00000000,
200 0x00000000, 0x00000000, 0x00000000, 0x00000000,
201 0x00000000, 0x00000000, 0x00000000, 0x00000000,
204 /* Packet types for packets with an Innermost/Last IPv6 header */
205 static const u32 ice_ptypes_ipv6_il[] = {
206 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
207 0x00000770, 0x00000000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
209 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 0x00000000, 0x00000000, 0x00000000, 0x00000000,
212 0x00000000, 0x00000000, 0x00000000, 0x00000000,
213 0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 /* Packet types for packets with an Outermost/First ARP header */
217 static const u32 ice_ptypes_arp_of[] = {
218 0x00000800, 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,
224 0x00000000, 0x00000000, 0x00000000, 0x00000000,
225 0x00000000, 0x00000000, 0x00000000, 0x00000000,
228 /* UDP Packet types for non-tunneled packets or tunneled
229 * packets with inner UDP.
231 static const u32 ice_ptypes_udp_il[] = {
232 0x81000000, 0x20204040, 0x04000010, 0x80810102,
233 0x00000040, 0x00000000, 0x00000000, 0x00000000,
234 0x00000000, 0x00410000, 0x10842000, 0x00000000,
235 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 0x00000000, 0x00000000, 0x00000000, 0x00000000,
237 0x00000000, 0x00000000, 0x00000000, 0x00000000,
238 0x00000000, 0x00000000, 0x00000000, 0x00000000,
239 0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 /* Packet types for packets with an Innermost/Last TCP header */
243 static const u32 ice_ptypes_tcp_il[] = {
244 0x04000000, 0x80810102, 0x10000040, 0x02040408,
245 0x00000102, 0x00000000, 0x00000000, 0x00000000,
246 0x00000000, 0x00820000, 0x21084000, 0x00000000,
247 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 0x00000000, 0x00000000, 0x00000000, 0x00000000,
250 0x00000000, 0x00000000, 0x00000000, 0x00000000,
251 0x00000000, 0x00000000, 0x00000000, 0x00000000,
254 /* Packet types for packets with an Innermost/Last SCTP header */
255 static const u32 ice_ptypes_sctp_il[] = {
256 0x08000000, 0x01020204, 0x20000081, 0x04080810,
257 0x00000204, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x01040000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 0x00000000, 0x00000000, 0x00000000, 0x00000000,
262 0x00000000, 0x00000000, 0x00000000, 0x00000000,
263 0x00000000, 0x00000000, 0x00000000, 0x00000000,
266 /* Packet types for packets with an Outermost/First ICMP header */
267 static const u32 ice_ptypes_icmp_of[] = {
268 0x10000000, 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,
274 0x00000000, 0x00000000, 0x00000000, 0x00000000,
275 0x00000000, 0x00000000, 0x00000000, 0x00000000,
278 /* Packet types for packets with an Innermost/Last ICMP header */
279 static const u32 ice_ptypes_icmp_il[] = {
280 0x00000000, 0x02040408, 0x40000102, 0x08101020,
281 0x00000408, 0x00000000, 0x00000000, 0x00000000,
282 0x00000000, 0x00000000, 0x42108000, 0x00000000,
283 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 0x00000000, 0x00000000, 0x00000000, 0x00000000,
287 0x00000000, 0x00000000, 0x00000000, 0x00000000,
290 /* Packet types for packets with an Outermost/First GRE header */
291 static const u32 ice_ptypes_gre_of[] = {
292 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
293 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
294 0x00000000, 0x00000000, 0x00000000, 0x00000000,
295 0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 0x00000000, 0x00000000, 0x00000000, 0x00000000,
298 0x00000000, 0x00000000, 0x00000000, 0x00000000,
299 0x00000000, 0x00000000, 0x00000000, 0x00000000,
302 /* Packet types for packets with an Innermost/Last MAC header */
303 static const u32 ice_ptypes_mac_il[] = {
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,
310 0x00000000, 0x00000000, 0x00000000, 0x00000000,
311 0x00000000, 0x00000000, 0x00000000, 0x00000000,
314 /* Packet types for GTPC */
315 static const u32 ice_ptypes_gtpc[] = {
316 0x00000000, 0x00000000, 0x00000000, 0x00000000,
317 0x00000000, 0x00000000, 0x00000000, 0x00000000,
318 0x00000000, 0x00000000, 0x00000180, 0x00000000,
319 0x00000000, 0x00000000, 0x00000000, 0x00000000,
320 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 0x00000000, 0x00000000, 0x00000000, 0x00000000,
322 0x00000000, 0x00000000, 0x00000000, 0x00000000,
323 0x00000000, 0x00000000, 0x00000000, 0x00000000,
326 /* Packet types for GTPC with TEID */
327 static const u32 ice_ptypes_gtpc_tid[] = {
328 0x00000000, 0x00000000, 0x00000000, 0x00000000,
329 0x00000000, 0x00000000, 0x00000000, 0x00000000,
330 0x00000000, 0x00000000, 0x00000060, 0x00000000,
331 0x00000000, 0x00000000, 0x00000000, 0x00000000,
332 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 0x00000000, 0x00000000, 0x00000000, 0x00000000,
334 0x00000000, 0x00000000, 0x00000000, 0x00000000,
335 0x00000000, 0x00000000, 0x00000000, 0x00000000,
338 /* Packet types for GTPU */
339 static const u32 ice_ptypes_gtpu[] = {
340 0x00000000, 0x00000000, 0x00000000, 0x00000000,
341 0x00000000, 0x00000000, 0x00000000, 0x00000000,
342 0x00000000, 0x00000000, 0x7FFFF800, 0x00000000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 0x00000000, 0x00000000, 0x00000000, 0x00000000,
346 0x00000000, 0x00000000, 0x00000000, 0x00000000,
347 0x00000000, 0x00000000, 0x00000000, 0x00000000,
350 /* Packet types for pppoe */
351 static const u32 ice_ptypes_pppoe[] = {
352 0x00000000, 0x00000000, 0x00000000, 0x00000000,
353 0x00000000, 0x00000000, 0x00000000, 0x00000000,
354 0x00000000, 0x03FFF000, 0x00000000, 0x00000000,
355 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 0x00000000, 0x00000000, 0x00000000, 0x00000000,
359 0x00000000, 0x00000000, 0x00000000, 0x00000000,
362 /* Manage parameters and info. used during the creation of a flow profile */
363 struct ice_flow_prof_params {
365 u16 entry_length; /* # of bytes formatted entry will require */
367 struct ice_flow_prof *prof;
369 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
370 * This will give us the direction flags.
372 struct ice_fv_word es[ICE_MAX_FV_WORDS];
373 u16 mask[ICE_MAX_FV_WORDS];
374 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
377 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
378 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
379 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU)
381 #define ICE_FLOW_SEG_HDRS_L2_MASK \
382 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
383 #define ICE_FLOW_SEG_HDRS_L3_MASK \
384 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
385 ICE_FLOW_SEG_HDR_ARP)
386 #define ICE_FLOW_SEG_HDRS_L4_MASK \
387 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
388 ICE_FLOW_SEG_HDR_SCTP)
391 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
392 * @segs: array of one or more packet segments that describe the flow
393 * @segs_cnt: number of packet segments provided
395 static enum ice_status
396 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
400 for (i = 0; i < segs_cnt; i++) {
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_PPPOE) {
507 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
508 ice_and_bitmap(params->ptypes, params->ptypes, src,
512 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
513 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
514 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
515 ice_and_bitmap(params->ptypes, params->ptypes, src,
517 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
518 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
519 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
520 ice_and_bitmap(params->ptypes, params->ptypes, src,
524 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
525 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
526 (const ice_bitmap_t *)ice_ptypes_icmp_il;
527 ice_and_bitmap(params->ptypes, params->ptypes, src,
529 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
530 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
531 ice_and_bitmap(params->ptypes, params->ptypes, src,
533 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
534 ice_and_bitmap(params->ptypes, params->ptypes,
535 (const ice_bitmap_t *)ice_ptypes_tcp_il,
537 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
538 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
539 ice_and_bitmap(params->ptypes, params->ptypes, src,
541 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
543 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
544 ice_and_bitmap(params->ptypes, params->ptypes,
545 src, ICE_FLOW_PTYPE_MAX);
547 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
549 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
550 ice_and_bitmap(params->ptypes, params->ptypes,
551 src, ICE_FLOW_PTYPE_MAX);
553 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
555 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
556 ice_and_bitmap(params->ptypes, params->ptypes,
557 src, ICE_FLOW_PTYPE_MAX);
559 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
561 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
562 ice_and_bitmap(params->ptypes, params->ptypes,
563 src, ICE_FLOW_PTYPE_MAX);
572 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
573 * @hw: pointer to the HW struct
574 * @params: information about the flow to be processed
575 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
577 * This function will allocate an extraction sequence entries for a DWORD size
578 * chunk of the packet flags.
580 static enum ice_status
581 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
582 struct ice_flow_prof_params *params,
583 enum ice_flex_mdid_pkt_flags flags)
585 u8 fv_words = hw->blk[params->blk].es.fvw;
588 /* Make sure the number of extraction sequence entries required does not
589 * exceed the block's capacity.
591 if (params->es_cnt >= fv_words)
592 return ICE_ERR_MAX_LIMIT;
594 /* some blocks require a reversed field vector layout */
595 if (hw->blk[params->blk].es.reverse)
596 idx = fv_words - params->es_cnt - 1;
598 idx = params->es_cnt;
600 params->es[idx].prot_id = ICE_PROT_META_ID;
601 params->es[idx].off = flags;
608 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
609 * @hw: pointer to the HW struct
610 * @params: information about the flow to be processed
611 * @seg: packet segment index of the field to be extracted
612 * @fld: ID of field to be extracted
613 * @match: bitfield of all fields
615 * This function determines the protocol ID, offset, and size of the given
616 * field. It then allocates one or more extraction sequence entries for the
617 * given field, and fill the entries with protocol ID and offset information.
619 static enum ice_status
620 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
621 u8 seg, enum ice_flow_field fld, u64 match)
623 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
624 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
625 u8 fv_words = hw->blk[params->blk].es.fvw;
626 struct ice_flow_fld_info *flds;
627 u16 cnt, ese_bits, i;
633 flds = params->prof->segs[seg].fields;
636 case ICE_FLOW_FIELD_IDX_ETH_DA:
637 case ICE_FLOW_FIELD_IDX_ETH_SA:
638 case ICE_FLOW_FIELD_IDX_S_VLAN:
639 case ICE_FLOW_FIELD_IDX_C_VLAN:
640 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
642 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
643 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
645 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
646 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
648 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
649 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
651 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
652 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
653 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
655 /* TTL and PROT share the same extraction seq. entry.
656 * Each is considered a sibling to the other in terms of sharing
657 * the same extraction sequence entry.
659 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
660 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
661 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
662 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
664 /* If the sibling field is also included, that field's
665 * mask needs to be included.
667 if (match & BIT(sib))
668 sib_mask = ice_flds_info[sib].mask;
670 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
671 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
672 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
674 /* TTL and PROT share the same extraction seq. entry.
675 * Each is considered a sibling to the other in terms of sharing
676 * the same extraction sequence entry.
678 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
679 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
680 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
681 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
683 /* If the sibling field is also included, that field's
684 * mask needs to be included.
686 if (match & BIT(sib))
687 sib_mask = ice_flds_info[sib].mask;
689 case ICE_FLOW_FIELD_IDX_IPV4_SA:
690 case ICE_FLOW_FIELD_IDX_IPV4_DA:
691 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
693 case ICE_FLOW_FIELD_IDX_IPV6_SA:
694 case ICE_FLOW_FIELD_IDX_IPV6_DA:
695 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
697 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
698 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
699 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
700 prot_id = ICE_PROT_TCP_IL;
702 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
703 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
704 prot_id = ICE_PROT_UDP_IL_OR_S;
706 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
707 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
708 prot_id = ICE_PROT_SCTP_IL;
710 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
711 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
712 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
713 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
714 /* GTP is accessed through UDP OF protocol */
715 prot_id = ICE_PROT_UDP_OF;
717 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
718 prot_id = ICE_PROT_PPPOE;
720 case ICE_FLOW_FIELD_IDX_ARP_SIP:
721 case ICE_FLOW_FIELD_IDX_ARP_DIP:
722 case ICE_FLOW_FIELD_IDX_ARP_SHA:
723 case ICE_FLOW_FIELD_IDX_ARP_DHA:
724 case ICE_FLOW_FIELD_IDX_ARP_OP:
725 prot_id = ICE_PROT_ARP_OF;
727 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
728 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
729 /* ICMP type and code share the same extraction seq. entry */
730 prot_id = (params->prof->segs[seg].hdrs &
731 ICE_FLOW_SEG_HDR_IPV4) ?
732 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
733 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
734 ICE_FLOW_FIELD_IDX_ICMP_CODE :
735 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
737 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
738 prot_id = ICE_PROT_GRE_OF;
741 return ICE_ERR_NOT_IMPL;
744 /* Each extraction sequence entry is a word in size, and extracts a
745 * word-aligned offset from a protocol header.
747 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
749 flds[fld].xtrct.prot_id = prot_id;
750 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
751 ICE_FLOW_FV_EXTRACT_SZ;
752 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
753 flds[fld].xtrct.idx = params->es_cnt;
754 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
756 /* Adjust the next field-entry index after accommodating the number of
757 * entries this field consumes
759 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
760 ice_flds_info[fld].size, ese_bits);
762 /* Fill in the extraction sequence entries needed for this field */
763 off = flds[fld].xtrct.off;
764 mask = flds[fld].xtrct.mask;
765 for (i = 0; i < cnt; i++) {
766 /* Only consume an extraction sequence entry if there is no
767 * sibling field associated with this field or the sibling entry
768 * already extracts the word shared with this field.
770 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
771 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
772 flds[sib].xtrct.off != off) {
775 /* Make sure the number of extraction sequence required
776 * does not exceed the block's capability
778 if (params->es_cnt >= fv_words)
779 return ICE_ERR_MAX_LIMIT;
781 /* some blocks require a reversed field vector layout */
782 if (hw->blk[params->blk].es.reverse)
783 idx = fv_words - params->es_cnt - 1;
785 idx = params->es_cnt;
787 params->es[idx].prot_id = prot_id;
788 params->es[idx].off = off;
789 params->mask[idx] = mask | sib_mask;
793 off += ICE_FLOW_FV_EXTRACT_SZ;
800 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
801 * @hw: pointer to the HW struct
802 * @params: information about the flow to be processed
803 * @seg: index of packet segment whose raw fields are to be be extracted
805 static enum ice_status
806 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
813 if (!params->prof->segs[seg].raws_cnt)
816 if (params->prof->segs[seg].raws_cnt >
817 ARRAY_SIZE(params->prof->segs[seg].raws))
818 return ICE_ERR_MAX_LIMIT;
820 /* Offsets within the segment headers are not supported */
821 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
823 return ICE_ERR_PARAM;
825 fv_words = hw->blk[params->blk].es.fvw;
827 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
828 struct ice_flow_seg_fld_raw *raw;
831 raw = ¶ms->prof->segs[seg].raws[i];
833 /* Only support matching raw fields in the payload */
834 if (raw->off < hdrs_sz)
835 return ICE_ERR_PARAM;
837 /* Convert the segment-relative offset into payload-relative
840 off = raw->off - hdrs_sz;
842 /* Storing extraction information */
843 raw->info.xtrct.prot_id = ICE_PROT_PAY;
844 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
845 ICE_FLOW_FV_EXTRACT_SZ;
846 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
848 raw->info.xtrct.idx = params->es_cnt;
850 /* Determine the number of field vector entries this raw field
853 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
854 (raw->info.src.last * BITS_PER_BYTE),
855 (ICE_FLOW_FV_EXTRACT_SZ *
857 off = raw->info.xtrct.off;
858 for (j = 0; j < cnt; j++) {
861 /* Make sure the number of extraction sequence required
862 * does not exceed the block's capability
864 if (params->es_cnt >= hw->blk[params->blk].es.count ||
865 params->es_cnt >= ICE_MAX_FV_WORDS)
866 return ICE_ERR_MAX_LIMIT;
868 /* some blocks require a reversed field vector layout */
869 if (hw->blk[params->blk].es.reverse)
870 idx = fv_words - params->es_cnt - 1;
872 idx = params->es_cnt;
874 params->es[idx].prot_id = ICE_PROT_PAY;
875 params->es[idx].off = off;
877 off += ICE_FLOW_FV_EXTRACT_SZ;
885 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
886 * @hw: pointer to the HW struct
887 * @params: information about the flow to be processed
889 * This function iterates through all matched fields in the given segments, and
890 * creates an extraction sequence for the fields.
892 static enum ice_status
893 ice_flow_create_xtrct_seq(struct ice_hw *hw,
894 struct ice_flow_prof_params *params)
896 enum ice_status status = ICE_SUCCESS;
899 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
902 if (params->blk == ICE_BLK_ACL) {
903 status = ice_flow_xtract_pkt_flags(hw, params,
904 ICE_RX_MDID_PKT_FLAGS_15_0);
909 for (i = 0; i < params->prof->segs_cnt; i++) {
910 u64 match = params->prof->segs[i].match;
913 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
914 const u64 bit = BIT_ULL(j);
917 status = ice_flow_xtract_fld
918 (hw, params, i, (enum ice_flow_field)j,
926 /* Process raw matching bytes */
927 status = ice_flow_xtract_raws(hw, params, i);
936 * ice_flow_proc_segs - process all packet segments associated with a profile
937 * @hw: pointer to the HW struct
938 * @params: information about the flow to be processed
940 static enum ice_status
941 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
943 enum ice_status status;
945 status = ice_flow_proc_seg_hdrs(params);
949 status = ice_flow_create_xtrct_seq(hw, params);
953 switch (params->blk) {
955 /* Only header information is provided for RSS configuration.
956 * No further processing is needed.
958 status = ICE_SUCCESS;
961 status = ICE_SUCCESS;
965 return ICE_ERR_NOT_IMPL;
971 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
972 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
973 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
976 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
977 * @hw: pointer to the HW struct
978 * @blk: classification stage
979 * @dir: flow direction
980 * @segs: array of one or more packet segments that describe the flow
981 * @segs_cnt: number of packet segments provided
982 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
983 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
985 static struct ice_flow_prof *
986 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
987 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
988 u8 segs_cnt, u16 vsi_handle, u32 conds)
990 struct ice_flow_prof *p, *prof = NULL;
992 ice_acquire_lock(&hw->fl_profs_locks[blk]);
993 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
994 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
995 segs_cnt && segs_cnt == p->segs_cnt) {
998 /* Check for profile-VSI association if specified */
999 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1000 ice_is_vsi_valid(hw, vsi_handle) &&
1001 !ice_is_bit_set(p->vsis, vsi_handle))
1004 /* Protocol headers must be checked. Matched fields are
1005 * checked if specified.
1007 for (i = 0; i < segs_cnt; i++)
1008 if (segs[i].hdrs != p->segs[i].hdrs ||
1009 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1010 segs[i].match != p->segs[i].match))
1013 /* A match is found if all segments are matched */
1014 if (i == segs_cnt) {
1020 ice_release_lock(&hw->fl_profs_locks[blk]);
1026 * ice_flow_find_prof - Look up a profile matching headers and matched fields
1027 * @hw: pointer to the HW struct
1028 * @blk: classification stage
1029 * @dir: flow direction
1030 * @segs: array of one or more packet segments that describe the flow
1031 * @segs_cnt: number of packet segments provided
1034 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1035 struct ice_flow_seg_info *segs, u8 segs_cnt)
1037 struct ice_flow_prof *p;
1039 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1040 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1042 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1046 * ice_flow_find_prof_id - Look up a profile with given profile ID
1047 * @hw: pointer to the HW struct
1048 * @blk: classification stage
1049 * @prof_id: unique ID to identify this flow profile
1051 static struct ice_flow_prof *
1052 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1054 struct ice_flow_prof *p;
1056 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1057 if (p->id == prof_id)
1065 * ice_dealloc_flow_entry - Deallocate flow entry memory
1066 * @hw: pointer to the HW struct
1067 * @entry: flow entry to be removed
1070 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1076 ice_free(hw, entry->entry);
1079 ice_free(hw, entry->acts);
1081 entry->acts_cnt = 0;
1084 ice_free(hw, entry);
1088 * ice_flow_rem_entry_sync - Remove a flow entry
1089 * @hw: pointer to the HW struct
1090 * @entry: flow entry to be removed
1092 static enum ice_status
1093 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1096 return ICE_ERR_BAD_PTR;
1098 LIST_DEL(&entry->l_entry);
1100 ice_dealloc_flow_entry(hw, entry);
1106 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1107 * @hw: pointer to the HW struct
1108 * @blk: classification stage
1109 * @dir: flow direction
1110 * @prof_id: unique ID to identify this flow profile
1111 * @segs: array of one or more packet segments that describe the flow
1112 * @segs_cnt: number of packet segments provided
1113 * @acts: array of default actions
1114 * @acts_cnt: number of default actions
1115 * @prof: stores the returned flow profile added
1117 * Assumption: the caller has acquired the lock to the profile list
1119 static enum ice_status
1120 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1121 enum ice_flow_dir dir, u64 prof_id,
1122 struct ice_flow_seg_info *segs, u8 segs_cnt,
1123 struct ice_flow_action *acts, u8 acts_cnt,
1124 struct ice_flow_prof **prof)
1126 struct ice_flow_prof_params params;
1127 enum ice_status status = ICE_SUCCESS;
1130 if (!prof || (acts_cnt && !acts))
1131 return ICE_ERR_BAD_PTR;
1133 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1134 params.prof = (struct ice_flow_prof *)
1135 ice_malloc(hw, sizeof(*params.prof));
1137 return ICE_ERR_NO_MEMORY;
1139 /* initialize extraction sequence to all invalid (0xff) */
1140 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1141 params.es[i].prot_id = ICE_PROT_INVALID;
1142 params.es[i].off = ICE_FV_OFFSET_INVAL;
1146 params.prof->id = prof_id;
1147 params.prof->dir = dir;
1148 params.prof->segs_cnt = segs_cnt;
1150 /* Make a copy of the segments that need to be persistent in the flow
1153 for (i = 0; i < segs_cnt; i++)
1154 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1155 ICE_NONDMA_TO_NONDMA);
1157 /* Make a copy of the actions that need to be persistent in the flow
1161 params.prof->acts = (struct ice_flow_action *)
1162 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1163 ICE_NONDMA_TO_NONDMA);
1165 if (!params.prof->acts) {
1166 status = ICE_ERR_NO_MEMORY;
1171 status = ice_flow_proc_segs(hw, ¶ms);
1173 ice_debug(hw, ICE_DBG_FLOW,
1174 "Error processing a flow's packet segments\n");
1178 /* Add a HW profile for this flow profile */
1179 status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1180 params.es, params.mask);
1182 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1186 INIT_LIST_HEAD(¶ms.prof->entries);
1187 ice_init_lock(¶ms.prof->entries_lock);
1188 *prof = params.prof;
1192 if (params.prof->acts)
1193 ice_free(hw, params.prof->acts);
1194 ice_free(hw, params.prof);
1201 * ice_flow_rem_prof_sync - remove a flow profile
1202 * @hw: pointer to the hardware structure
1203 * @blk: classification stage
1204 * @prof: pointer to flow profile to remove
1206 * Assumption: the caller has acquired the lock to the profile list
1208 static enum ice_status
1209 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1210 struct ice_flow_prof *prof)
1212 enum ice_status status = ICE_SUCCESS;
1214 /* Remove all remaining flow entries before removing the flow profile */
1215 if (!LIST_EMPTY(&prof->entries)) {
1216 struct ice_flow_entry *e, *t;
1218 ice_acquire_lock(&prof->entries_lock);
1220 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1222 status = ice_flow_rem_entry_sync(hw, e);
1227 ice_release_lock(&prof->entries_lock);
1230 /* Remove all hardware profiles associated with this flow profile */
1231 status = ice_rem_prof(hw, blk, prof->id);
1233 LIST_DEL(&prof->l_entry);
1234 ice_destroy_lock(&prof->entries_lock);
1236 ice_free(hw, prof->acts);
1244 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1245 * @hw: pointer to the hardware structure
1246 * @blk: classification stage
1247 * @vsi_handle: software VSI handle
1248 * @vsig: target VSI group
1250 * Assumption: the caller has already verified that the VSI to
1251 * be added has the same characteristics as the VSIG and will
1252 * thereby have access to all resources added to that VSIG.
1255 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1258 enum ice_status status;
1260 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1261 return ICE_ERR_PARAM;
1263 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1264 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1266 ice_release_lock(&hw->fl_profs_locks[blk]);
1272 * ice_flow_assoc_prof - associate a VSI with a flow profile
1273 * @hw: pointer to the hardware structure
1274 * @blk: classification stage
1275 * @prof: pointer to flow profile
1276 * @vsi_handle: software VSI handle
1278 * Assumption: the caller has acquired the lock to the profile list
1279 * and the software VSI handle has been validated
1281 static enum ice_status
1282 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1283 struct ice_flow_prof *prof, u16 vsi_handle)
1285 enum ice_status status = ICE_SUCCESS;
1287 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1288 status = ice_add_prof_id_flow(hw, blk,
1289 ice_get_hw_vsi_num(hw,
1293 ice_set_bit(vsi_handle, prof->vsis);
1295 ice_debug(hw, ICE_DBG_FLOW,
1296 "HW profile add failed, %d\n",
1304 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1305 * @hw: pointer to the hardware structure
1306 * @blk: classification stage
1307 * @prof: pointer to flow profile
1308 * @vsi_handle: software VSI handle
1310 * Assumption: the caller has acquired the lock to the profile list
1311 * and the software VSI handle has been validated
1313 static enum ice_status
1314 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1315 struct ice_flow_prof *prof, u16 vsi_handle)
1317 enum ice_status status = ICE_SUCCESS;
1319 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1320 status = ice_rem_prof_id_flow(hw, blk,
1321 ice_get_hw_vsi_num(hw,
1325 ice_clear_bit(vsi_handle, prof->vsis);
1327 ice_debug(hw, ICE_DBG_FLOW,
1328 "HW profile remove failed, %d\n",
1336 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1337 * @hw: pointer to the HW struct
1338 * @blk: classification stage
1339 * @dir: flow direction
1340 * @prof_id: unique ID to identify this flow profile
1341 * @segs: array of one or more packet segments that describe the flow
1342 * @segs_cnt: number of packet segments provided
1343 * @acts: array of default actions
1344 * @acts_cnt: number of default actions
1345 * @prof: stores the returned flow profile added
1348 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1349 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1350 struct ice_flow_action *acts, u8 acts_cnt,
1351 struct ice_flow_prof **prof)
1353 enum ice_status status;
1355 if (segs_cnt > ICE_FLOW_SEG_MAX)
1356 return ICE_ERR_MAX_LIMIT;
1359 return ICE_ERR_PARAM;
1362 return ICE_ERR_BAD_PTR;
1364 status = ice_flow_val_hdrs(segs, segs_cnt);
1368 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1370 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1371 acts, acts_cnt, prof);
1373 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1375 ice_release_lock(&hw->fl_profs_locks[blk]);
1381 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1382 * @hw: pointer to the HW struct
1383 * @blk: the block for which the flow profile is to be removed
1384 * @prof_id: unique ID of the flow profile to be removed
1387 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1389 struct ice_flow_prof *prof;
1390 enum ice_status status;
1392 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1394 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1396 status = ICE_ERR_DOES_NOT_EXIST;
1400 /* prof becomes invalid after the call */
1401 status = ice_flow_rem_prof_sync(hw, blk, prof);
1404 ice_release_lock(&hw->fl_profs_locks[blk]);
1410 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1411 * @hw: pointer to the HW struct
1412 * @blk: classification stage
1413 * @prof_id: the profile ID handle
1414 * @hw_prof_id: pointer to variable to receive the HW profile ID
1417 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1420 struct ice_prof_map *map;
1422 map = ice_search_prof_id(hw, blk, prof_id);
1424 *hw_prof_id = map->prof_id;
1428 return ICE_ERR_DOES_NOT_EXIST;
1432 * ice_flow_find_entry - look for a flow entry using its unique ID
1433 * @hw: pointer to the HW struct
1434 * @blk: classification stage
1435 * @entry_id: unique ID to identify this flow entry
1437 * This function looks for the flow entry with the specified unique ID in all
1438 * flow profiles of the specified classification stage. If the entry is found,
1439 * and it returns the handle to the flow entry. Otherwise, it returns
1440 * ICE_FLOW_ENTRY_ID_INVAL.
1442 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1444 struct ice_flow_entry *found = NULL;
1445 struct ice_flow_prof *p;
1447 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1449 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1450 struct ice_flow_entry *e;
1452 ice_acquire_lock(&p->entries_lock);
1453 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1454 if (e->id == entry_id) {
1458 ice_release_lock(&p->entries_lock);
1464 ice_release_lock(&hw->fl_profs_locks[blk]);
1466 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1470 * ice_flow_add_entry - Add a flow entry
1471 * @hw: pointer to the HW struct
1472 * @blk: classification stage
1473 * @prof_id: ID of the profile to add a new flow entry to
1474 * @entry_id: unique ID to identify this flow entry
1475 * @vsi_handle: software VSI handle for the flow entry
1476 * @prio: priority of the flow entry
1477 * @data: pointer to a data buffer containing flow entry's match values/masks
1478 * @acts: arrays of actions to be performed on a match
1479 * @acts_cnt: number of actions
1480 * @entry_h: pointer to buffer that receives the new flow entry's handle
1483 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1484 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1485 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1488 struct ice_flow_prof *prof = NULL;
1489 struct ice_flow_entry *e = NULL;
1490 enum ice_status status = ICE_SUCCESS;
1492 if (acts_cnt && !acts)
1493 return ICE_ERR_PARAM;
1495 /* No flow entry data is expected for RSS */
1496 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1497 return ICE_ERR_BAD_PTR;
1499 if (!ice_is_vsi_valid(hw, vsi_handle))
1500 return ICE_ERR_PARAM;
1502 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1504 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1506 status = ICE_ERR_DOES_NOT_EXIST;
1508 /* Allocate memory for the entry being added and associate
1509 * the VSI to the found flow profile
1511 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1513 status = ICE_ERR_NO_MEMORY;
1515 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1518 ice_release_lock(&hw->fl_profs_locks[blk]);
1523 e->vsi_handle = vsi_handle;
1529 /* RSS will add only one entry per VSI per profile */
1536 status = ICE_ERR_NOT_IMPL;
1540 if (blk != ICE_BLK_ACL) {
1541 /* ACL will handle the entry management */
1542 ice_acquire_lock(&prof->entries_lock);
1543 LIST_ADD(&e->l_entry, &prof->entries);
1544 ice_release_lock(&prof->entries_lock);
1547 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1552 ice_free(hw, e->entry);
1560 * ice_flow_rem_entry - Remove a flow entry
1561 * @hw: pointer to the HW struct
1562 * @entry_h: handle to the flow entry to be removed
1564 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1566 struct ice_flow_entry *entry;
1567 struct ice_flow_prof *prof;
1568 enum ice_status status;
1570 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1571 return ICE_ERR_PARAM;
1573 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1575 /* Retain the pointer to the flow profile as the entry will be freed */
1578 ice_acquire_lock(&prof->entries_lock);
1579 status = ice_flow_rem_entry_sync(hw, entry);
1580 ice_release_lock(&prof->entries_lock);
1586 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1587 * @seg: packet segment the field being set belongs to
1588 * @fld: field to be set
1589 * @type: type of the field
1590 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1591 * entry's input buffer
1592 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1594 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1595 * entry's input buffer
1597 * This helper function stores information of a field being matched, including
1598 * the type of the field and the locations of the value to match, the mask, and
1599 * and the upper-bound value in the start of the input buffer for a flow entry.
1600 * This function should only be used for fixed-size data structures.
1602 * This function also opportunistically determines the protocol headers to be
1603 * present based on the fields being set. Some fields cannot be used alone to
1604 * determine the protocol headers present. Sometimes, fields for particular
1605 * protocol headers are not matched. In those cases, the protocol headers
1606 * must be explicitly set.
1609 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1610 enum ice_flow_fld_match_type type, u16 val_loc,
1611 u16 mask_loc, u16 last_loc)
1613 u64 bit = BIT_ULL(fld);
1616 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1619 seg->fields[fld].type = type;
1620 seg->fields[fld].src.val = val_loc;
1621 seg->fields[fld].src.mask = mask_loc;
1622 seg->fields[fld].src.last = last_loc;
1624 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1628 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1629 * @seg: packet segment the field being set belongs to
1630 * @fld: field to be set
1631 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1632 * entry's input buffer
1633 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1635 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1636 * entry's input buffer
1637 * @range: indicate if field being matched is to be in a range
1639 * This function specifies the locations, in the form of byte offsets from the
1640 * start of the input buffer for a flow entry, from where the value to match,
1641 * the mask value, and upper value can be extracted. These locations are then
1642 * stored in the flow profile. When adding a flow entry associated with the
1643 * flow profile, these locations will be used to quickly extract the values and
1644 * create the content of a match entry. This function should only be used for
1645 * fixed-size data structures.
1648 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1649 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1651 enum ice_flow_fld_match_type t = range ?
1652 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1654 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1658 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1659 * @seg: packet segment the field being set belongs to
1660 * @fld: field to be set
1661 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1662 * entry's input buffer
1663 * @pref_loc: location of prefix value from entry's input buffer
1664 * @pref_sz: size of the location holding the prefix value
1666 * This function specifies the locations, in the form of byte offsets from the
1667 * start of the input buffer for a flow entry, from where the value to match
1668 * and the IPv4 prefix value can be extracted. These locations are then stored
1669 * in the flow profile. When adding flow entries to the associated flow profile,
1670 * these locations can be used to quickly extract the values to create the
1671 * content of a match entry. This function should only be used for fixed-size
1675 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1676 u16 val_loc, u16 pref_loc, u8 pref_sz)
1678 /* For this type of field, the "mask" location is for the prefix value's
1679 * location and the "last" location is for the size of the location of
1682 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1683 pref_loc, (u16)pref_sz);
1687 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1688 * @seg: packet segment the field being set belongs to
1689 * @off: offset of the raw field from the beginning of the segment in bytes
1690 * @len: length of the raw pattern to be matched
1691 * @val_loc: location of the value to match from entry's input buffer
1692 * @mask_loc: location of mask value from entry's input buffer
1694 * This function specifies the offset of the raw field to be match from the
1695 * beginning of the specified packet segment, and the locations, in the form of
1696 * byte offsets from the start of the input buffer for a flow entry, from where
1697 * the value to match and the mask value to be extracted. These locations are
1698 * then stored in the flow profile. When adding flow entries to the associated
1699 * flow profile, these locations can be used to quickly extract the values to
1700 * create the content of a match entry. This function should only be used for
1701 * fixed-size data structures.
1704 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1705 u16 val_loc, u16 mask_loc)
1707 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1708 seg->raws[seg->raws_cnt].off = off;
1709 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1710 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1711 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1712 /* The "last" field is used to store the length of the field */
1713 seg->raws[seg->raws_cnt].info.src.last = len;
1716 /* Overflows of "raws" will be handled as an error condition later in
1717 * the flow when this information is processed.
1722 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1723 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1725 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1726 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1728 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1729 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1730 ICE_FLOW_SEG_HDR_SCTP)
1732 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1733 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1734 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1735 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1738 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1739 * @segs: pointer to the flow field segment(s)
1740 * @hash_fields: fields to be hashed on for the segment(s)
1741 * @flow_hdr: protocol header fields within a packet segment
1743 * Helper function to extract fields from hash bitmap and use flow
1744 * header value to set flow field segment for further use in flow
1745 * profile entry or removal.
1747 static enum ice_status
1748 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1751 u64 val = hash_fields;
1754 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1755 u64 bit = BIT_ULL(i);
1758 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1759 ICE_FLOW_FLD_OFF_INVAL,
1760 ICE_FLOW_FLD_OFF_INVAL,
1761 ICE_FLOW_FLD_OFF_INVAL, false);
1765 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1767 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1768 ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1769 return ICE_ERR_PARAM;
1771 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1772 if (val && !ice_is_pow2(val))
1775 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1776 if (val && !ice_is_pow2(val))
1783 * ice_rem_vsi_rss_list - remove VSI from RSS list
1784 * @hw: pointer to the hardware structure
1785 * @vsi_handle: software VSI handle
1787 * Remove the VSI from all RSS configurations in the list.
1789 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1791 struct ice_rss_cfg *r, *tmp;
1793 if (LIST_EMPTY(&hw->rss_list_head))
1796 ice_acquire_lock(&hw->rss_locks);
1797 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1798 ice_rss_cfg, l_entry) {
1799 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1800 ice_clear_bit(vsi_handle, r->vsis);
1802 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1803 LIST_DEL(&r->l_entry);
1808 ice_release_lock(&hw->rss_locks);
1812 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1813 * @hw: pointer to the hardware structure
1814 * @vsi_handle: software VSI handle
1816 * This function will iterate through all flow profiles and disassociate
1817 * the VSI from that profile. If the flow profile has no VSIs it will
1820 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1822 const enum ice_block blk = ICE_BLK_RSS;
1823 struct ice_flow_prof *p, *t;
1824 enum ice_status status = ICE_SUCCESS;
1826 if (!ice_is_vsi_valid(hw, vsi_handle))
1827 return ICE_ERR_PARAM;
1829 if (LIST_EMPTY(&hw->fl_profs[blk]))
1832 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1833 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1835 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1836 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1840 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1841 status = ice_flow_rem_prof_sync(hw, blk, p);
1847 ice_release_lock(&hw->fl_profs_locks[blk]);
1853 * ice_rem_rss_list - remove RSS configuration from list
1854 * @hw: pointer to the hardware structure
1855 * @vsi_handle: software VSI handle
1856 * @prof: pointer to flow profile
1858 * Assumption: lock has already been acquired for RSS list
1861 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1863 struct ice_rss_cfg *r, *tmp;
1865 /* Search for RSS hash fields associated to the VSI that match the
1866 * hash configurations associated to the flow profile. If found
1867 * remove from the RSS entry list of the VSI context and delete entry.
1869 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1870 ice_rss_cfg, l_entry) {
1871 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1872 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1873 ice_clear_bit(vsi_handle, r->vsis);
1874 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1875 LIST_DEL(&r->l_entry);
1884 * ice_add_rss_list - add RSS configuration to list
1885 * @hw: pointer to the hardware structure
1886 * @vsi_handle: software VSI handle
1887 * @prof: pointer to flow profile
1889 * Assumption: lock has already been acquired for RSS list
1891 static enum ice_status
1892 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1894 struct ice_rss_cfg *r, *rss_cfg;
1896 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1897 ice_rss_cfg, l_entry)
1898 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1899 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1900 ice_set_bit(vsi_handle, r->vsis);
1904 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1906 return ICE_ERR_NO_MEMORY;
1908 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1909 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1910 rss_cfg->symm = prof->cfg.symm;
1911 ice_set_bit(vsi_handle, rss_cfg->vsis);
1913 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1918 #define ICE_FLOW_PROF_HASH_S 0
1919 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1920 #define ICE_FLOW_PROF_HDR_S 32
1921 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1922 #define ICE_FLOW_PROF_ENCAP_S 63
1923 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1925 #define ICE_RSS_OUTER_HEADERS 1
1926 #define ICE_RSS_INNER_HEADERS 2
1928 /* Flow profile ID format:
1929 * [0:31] - Packet match fields
1930 * [32:62] - Protocol header
1931 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1933 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1934 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1935 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1936 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1939 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
1941 u32 s = ((src % 4) << 3); /* byte shift */
1942 u32 v = dst | 0x80; /* value to program */
1943 u8 i = src / 4; /* register index */
1946 reg = rd32(hw, GLQF_HSYMM(prof_id, i));
1947 reg = (reg & ~(0xff << s)) | (v << s);
1948 wr32(hw, GLQF_HSYMM(prof_id, i), reg);
1952 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
1955 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
1958 for (i = 0; i < len; i++) {
1959 ice_rss_config_xor_word(hw, prof_id,
1960 /* Yes, field vector in GLQF_HSYMM and
1961 * GLQF_HINSET is inversed!
1963 fv_last_word - (src + i),
1964 fv_last_word - (dst + i));
1965 ice_rss_config_xor_word(hw, prof_id,
1966 fv_last_word - (dst + i),
1967 fv_last_word - (src + i));
1972 ice_rss_update_symm(struct ice_hw *hw,
1973 struct ice_flow_prof *prof)
1975 struct ice_prof_map *map;
1978 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
1979 prof_id = map->prof_id;
1981 /* clear to default */
1982 for (m = 0; m < 6; m++)
1983 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
1984 if (prof->cfg.symm) {
1985 struct ice_flow_seg_info *seg =
1986 &prof->segs[prof->segs_cnt - 1];
1988 struct ice_flow_seg_xtrct *ipv4_src =
1989 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
1990 struct ice_flow_seg_xtrct *ipv4_dst =
1991 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
1992 struct ice_flow_seg_xtrct *ipv6_src =
1993 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
1994 struct ice_flow_seg_xtrct *ipv6_dst =
1995 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
1997 struct ice_flow_seg_xtrct *tcp_src =
1998 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
1999 struct ice_flow_seg_xtrct *tcp_dst =
2000 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2002 struct ice_flow_seg_xtrct *udp_src =
2003 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2004 struct ice_flow_seg_xtrct *udp_dst =
2005 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2007 struct ice_flow_seg_xtrct *sctp_src =
2008 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2009 struct ice_flow_seg_xtrct *sctp_dst =
2010 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2013 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2014 ice_rss_config_xor(hw, prof_id,
2015 ipv4_src->idx, ipv4_dst->idx, 2);
2018 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2019 ice_rss_config_xor(hw, prof_id,
2020 ipv6_src->idx, ipv6_dst->idx, 8);
2023 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2024 ice_rss_config_xor(hw, prof_id,
2025 tcp_src->idx, tcp_dst->idx, 1);
2028 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2029 ice_rss_config_xor(hw, prof_id,
2030 udp_src->idx, udp_dst->idx, 1);
2033 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2034 ice_rss_config_xor(hw, prof_id,
2035 sctp_src->idx, sctp_dst->idx, 1);
2040 * ice_add_rss_cfg_sync - add an RSS configuration
2041 * @hw: pointer to the hardware structure
2042 * @vsi_handle: software VSI handle
2043 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2044 * @addl_hdrs: protocol header fields
2045 * @segs_cnt: packet segment count
2046 * @symm: symmetric hash enable/disable
2048 * Assumption: lock has already been acquired for RSS list
2050 static enum ice_status
2051 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2052 u32 addl_hdrs, u8 segs_cnt, bool symm)
2054 const enum ice_block blk = ICE_BLK_RSS;
2055 struct ice_flow_prof *prof = NULL;
2056 struct ice_flow_seg_info *segs;
2057 enum ice_status status = ICE_SUCCESS;
2059 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2060 return ICE_ERR_PARAM;
2062 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2065 return ICE_ERR_NO_MEMORY;
2067 /* Construct the packet segment info from the hashed fields */
2068 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2073 /* Search for a flow profile that has matching headers, hash fields
2074 * and has the input VSI associated to it. If found, no further
2075 * operations required and exit.
2077 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2079 ICE_FLOW_FIND_PROF_CHK_FLDS |
2080 ICE_FLOW_FIND_PROF_CHK_VSI);
2082 if (prof->cfg.symm == symm)
2084 prof->cfg.symm = symm;
2088 /* Check if a flow profile exists with the same protocol headers and
2089 * associated with the input VSI. If so disasscociate the VSI from
2090 * this profile. The VSI will be added to a new profile created with
2091 * the protocol header and new hash field configuration.
2093 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2094 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
2096 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2098 ice_rem_rss_list(hw, vsi_handle, prof);
2102 /* Remove profile if it has no VSIs associated */
2103 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
2104 status = ice_flow_rem_prof(hw, blk, prof->id);
2110 /* Search for a profile that has same match fields only. If this
2111 * exists then associate the VSI to this profile.
2113 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2115 ICE_FLOW_FIND_PROF_CHK_FLDS);
2117 if (prof->cfg.symm == symm) {
2118 status = ice_flow_assoc_prof(hw, blk, prof,
2121 status = ice_add_rss_list(hw, vsi_handle,
2124 /* if a profile exist but with different symmetric
2125 * requirement, just return error.
2127 status = ICE_ERR_NOT_SUPPORTED;
2132 /* Create a new flow profile with generated profile and packet
2133 * segment information.
2135 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2136 ICE_FLOW_GEN_PROFID(hashed_flds,
2137 segs[segs_cnt - 1].hdrs,
2139 segs, segs_cnt, NULL, 0, &prof);
2143 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2144 /* If association to a new flow profile failed then this profile can
2148 ice_flow_rem_prof(hw, blk, prof->id);
2152 status = ice_add_rss_list(hw, vsi_handle, prof);
2154 prof->cfg.symm = symm;
2159 ice_rss_update_symm(hw, prof);
2167 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2168 * @hw: pointer to the hardware structure
2169 * @vsi_handle: software VSI handle
2170 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2171 * @addl_hdrs: protocol header fields
2172 * @symm: symmetric hash enable/disable
2174 * This function will generate a flow profile based on fields associated with
2175 * the input fields to hash on, the flow type and use the VSI number to add
2176 * a flow entry to the profile.
2179 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2180 u32 addl_hdrs, bool symm)
2182 enum ice_status status;
2184 if (hashed_flds == ICE_HASH_INVALID ||
2185 !ice_is_vsi_valid(hw, vsi_handle))
2186 return ICE_ERR_PARAM;
2188 ice_acquire_lock(&hw->rss_locks);
2189 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2190 ICE_RSS_OUTER_HEADERS, symm);
2192 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2193 addl_hdrs, ICE_RSS_INNER_HEADERS,
2195 ice_release_lock(&hw->rss_locks);
2201 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2202 * @hw: pointer to the hardware structure
2203 * @vsi_handle: software VSI handle
2204 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2205 * @addl_hdrs: Protocol header fields within a packet segment
2206 * @segs_cnt: packet segment count
2208 * Assumption: lock has already been acquired for RSS list
2210 static enum ice_status
2211 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2212 u32 addl_hdrs, u8 segs_cnt)
2214 const enum ice_block blk = ICE_BLK_RSS;
2215 struct ice_flow_seg_info *segs;
2216 struct ice_flow_prof *prof;
2217 enum ice_status status;
2219 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2222 return ICE_ERR_NO_MEMORY;
2224 /* Construct the packet segment info from the hashed fields */
2225 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2230 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2232 ICE_FLOW_FIND_PROF_CHK_FLDS);
2234 status = ICE_ERR_DOES_NOT_EXIST;
2238 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2242 /* Remove RSS configuration from VSI context before deleting
2245 ice_rem_rss_list(hw, vsi_handle, prof);
2247 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2248 status = ice_flow_rem_prof(hw, blk, prof->id);
2256 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2257 * @hw: pointer to the hardware structure
2258 * @vsi_handle: software VSI handle
2259 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2260 * @addl_hdrs: Protocol header fields within a packet segment
2262 * This function will lookup the flow profile based on the input
2263 * hash field bitmap, iterate through the profile entry list of
2264 * that profile and find entry associated with input VSI to be
2265 * removed. Calls are made to underlying flow apis which will in
2266 * turn build or update buffers for RSS XLT1 section.
2269 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2272 enum ice_status status;
2274 if (hashed_flds == ICE_HASH_INVALID ||
2275 !ice_is_vsi_valid(hw, vsi_handle))
2276 return ICE_ERR_PARAM;
2278 ice_acquire_lock(&hw->rss_locks);
2279 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2280 ICE_RSS_OUTER_HEADERS);
2282 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2283 addl_hdrs, ICE_RSS_INNER_HEADERS);
2284 ice_release_lock(&hw->rss_locks);
2290 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2291 * @hw: pointer to the hardware structure
2292 * @vsi_handle: software VSI handle
2294 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2296 enum ice_status status = ICE_SUCCESS;
2297 struct ice_rss_cfg *r;
2299 if (!ice_is_vsi_valid(hw, vsi_handle))
2300 return ICE_ERR_PARAM;
2302 ice_acquire_lock(&hw->rss_locks);
2303 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2304 ice_rss_cfg, l_entry) {
2305 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2306 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2309 ICE_RSS_OUTER_HEADERS,
2313 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2316 ICE_RSS_INNER_HEADERS,
2322 ice_release_lock(&hw->rss_locks);
2328 * ice_get_rss_cfg - returns hashed fields for the given header types
2329 * @hw: pointer to the hardware structure
2330 * @vsi_handle: software VSI handle
2331 * @hdrs: protocol header type
2333 * This function will return the match fields of the first instance of flow
2334 * profile having the given header types and containing input VSI
2336 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2338 struct ice_rss_cfg *r, *rss_cfg = NULL;
2340 /* verify if the protocol header is non zero and VSI is valid */
2341 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2342 return ICE_HASH_INVALID;
2344 ice_acquire_lock(&hw->rss_locks);
2345 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2346 ice_rss_cfg, l_entry)
2347 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2348 r->packet_hdr == hdrs) {
2352 ice_release_lock(&hw->rss_locks);
2354 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;