1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2020 Intel Corporation
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_IPV6_PRE32_ADDR 4
14 #define ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR 6
15 #define ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR 8
16 #define ICE_FLOW_FLD_SZ_IP_DSCP 1
17 #define ICE_FLOW_FLD_SZ_IP_TTL 1
18 #define ICE_FLOW_FLD_SZ_IP_PROT 1
19 #define ICE_FLOW_FLD_SZ_PORT 2
20 #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1
21 #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1
22 #define ICE_FLOW_FLD_SZ_ICMP_CODE 1
23 #define ICE_FLOW_FLD_SZ_ARP_OPER 2
24 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4
25 #define ICE_FLOW_FLD_SZ_GTP_TEID 4
26 #define ICE_FLOW_FLD_SZ_GTP_QFI 2
27 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2
28 #define ICE_FLOW_FLD_SZ_PFCP_SEID 8
29 #define ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID 4
30 #define ICE_FLOW_FLD_SZ_ESP_SPI 4
31 #define ICE_FLOW_FLD_SZ_AH_SPI 4
32 #define ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI 4
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, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
71 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
72 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
74 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
75 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
77 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
78 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
79 ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
80 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
81 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
82 ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
83 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
84 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
85 ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
86 /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
87 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
88 ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
89 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
90 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
91 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
93 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
95 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
97 /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
99 ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
100 /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA */
101 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
102 ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
103 /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA */
104 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
105 ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
106 /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA */
107 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
108 ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
109 /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA */
110 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
111 ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
112 /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA */
113 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
114 ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
116 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
117 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
118 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
120 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
121 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
122 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
123 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
124 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
126 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
127 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
128 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
129 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
131 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
132 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
133 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
134 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
135 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
136 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
137 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
138 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
139 /* ICE_FLOW_FIELD_IDX_ARP_OP */
140 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
142 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
143 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
144 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
145 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
147 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
148 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
150 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
151 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
152 ICE_FLOW_FLD_SZ_GTP_TEID),
153 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
154 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
155 ICE_FLOW_FLD_SZ_GTP_TEID),
156 /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
157 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12,
158 ICE_FLOW_FLD_SZ_GTP_TEID),
159 /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
160 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22,
161 ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
162 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
163 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
164 ICE_FLOW_FLD_SZ_GTP_TEID),
165 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
166 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
167 ICE_FLOW_FLD_SZ_GTP_TEID),
169 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
170 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
171 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
173 /* ICE_FLOW_FIELD_IDX_PFCP_SEID */
174 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12,
175 ICE_FLOW_FLD_SZ_PFCP_SEID),
177 /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
178 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0,
179 ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID),
181 /* ICE_FLOW_FIELD_IDX_ESP_SPI */
182 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0,
183 ICE_FLOW_FLD_SZ_ESP_SPI),
185 /* ICE_FLOW_FIELD_IDX_AH_SPI */
186 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4,
187 ICE_FLOW_FLD_SZ_AH_SPI),
189 /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
190 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8,
191 ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI),
194 /* Bitmaps indicating relevant packet types for a particular protocol header
196 * Packet types for packets with an Outer/First/Single MAC header
198 static const u32 ice_ptypes_mac_ofos[] = {
199 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
200 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
201 0x00400000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
202 0x00000000, 0x00000000, 0x00000000, 0x00000000,
203 0x00000000, 0x00000000, 0x00000000, 0x00000000,
204 0x00000000, 0x00000000, 0x00000000, 0x00000000,
205 0x00000000, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 /* Packet types for packets with an Innermost/Last MAC VLAN header */
210 static const u32 ice_ptypes_macvlan_il[] = {
211 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
212 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
213 0x00000000, 0x00000000, 0x00000000, 0x00000000,
214 0x00000000, 0x00000000, 0x00000000, 0x00000000,
215 0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
221 /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
222 * include IPV4 other PTYPEs
224 static const u32 ice_ptypes_ipv4_ofos[] = {
225 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
226 0x00000000, 0x00000155, 0x00000000, 0x00000000,
227 0x00000000, 0x000FC000, 0x000002A0, 0x00000000,
228 0x00000000, 0x00000000, 0x00000000, 0x00000000,
229 0x00000000, 0x00000000, 0x00000000, 0x00000000,
230 0x00000000, 0x00000000, 0x00000000, 0x00000000,
231 0x00000000, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 0x00000000, 0x00000000, 0x00000000,
235 /* Packet types for packets with an Outer/First/Single IPv4 header, includes
238 static const u32 ice_ptypes_ipv4_ofos_all[] = {
239 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
240 0x00000000, 0x00000155, 0x00000000, 0x00000000,
241 0x00000000, 0x000FC000, 0x83E0FAA0, 0x00000101,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 /* Packet types for packets with an Innermost/Last IPv4 header */
250 static const u32 ice_ptypes_ipv4_il[] = {
251 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
252 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
253 0x00000000, 0x00000000, 0x001FF800, 0x00000000,
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
262 * include IVP6 other PTYPEs
264 static const u32 ice_ptypes_ipv6_ofos[] = {
265 0x00000000, 0x00000000, 0x77000000, 0x10002000,
266 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
267 0x00000000, 0x03F00000, 0x00000540, 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,
275 /* Packet types for packets with an Outer/First/Single IPv6 header, includes
278 static const u32 ice_ptypes_ipv6_ofos_all[] = {
279 0x00000000, 0x00000000, 0x77000000, 0x10002000,
280 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
281 0x00000000, 0x03F00000, 0x7C1F0540, 0x00000206,
282 0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000,
286 0x00000000, 0x00000000, 0x00000000, 0x00000000,
289 /* Packet types for packets with an Innermost/Last IPv6 header */
290 static const u32 ice_ptypes_ipv6_il[] = {
291 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
292 0x00000770, 0x00000000, 0x00000000, 0x00000000,
293 0x00000000, 0x00000000, 0x7FE00000, 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,
301 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
302 static const u32 ice_ipv4_ofos_no_l4[] = {
303 0x10C00000, 0x04000800, 0x00000000, 0x00000000,
304 0x00000000, 0x00000000, 0x00000000, 0x00000000,
305 0x00000000, 0x000cc000, 0x000002A0, 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,
313 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
314 static const u32 ice_ipv4_il_no_l4[] = {
315 0x60000000, 0x18043008, 0x80000002, 0x6010c021,
316 0x00000008, 0x00000000, 0x00000000, 0x00000000,
317 0x00000000, 0x00000000, 0x00139800, 0x00000000,
318 0x00000000, 0x00000000, 0x00000000, 0x00000000,
319 0x00000000, 0x00000000, 0x00000000, 0x00000000,
320 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 0x00000000, 0x00000000, 0x00000000, 0x00000000,
322 0x00000000, 0x00000000, 0x00000000, 0x00000000,
325 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
326 static const u32 ice_ipv6_ofos_no_l4[] = {
327 0x00000000, 0x00000000, 0x43000000, 0x10002000,
328 0x00000000, 0x00000000, 0x00000000, 0x00000000,
329 0x00000000, 0x02300000, 0x00000540, 0x00000000,
330 0x00000000, 0x00000000, 0x00000000, 0x00000000,
331 0x00000000, 0x00000000, 0x00000000, 0x00000000,
332 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 0x00000000, 0x00000000, 0x00000000, 0x00000000,
334 0x00000000, 0x00000000, 0x00000000, 0x00000000,
337 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
338 static const u32 ice_ipv6_il_no_l4[] = {
339 0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
340 0x00000430, 0x00000000, 0x00000000, 0x00000000,
341 0x00000000, 0x00000000, 0x4e600000, 0x00000000,
342 0x00000000, 0x00000000, 0x00000000, 0x00000000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 0x00000000, 0x00000000, 0x00000000, 0x00000000,
346 0x00000000, 0x00000000, 0x00000000, 0x00000000,
349 /* Packet types for packets with an Outermost/First ARP header */
350 static const u32 ice_ptypes_arp_of[] = {
351 0x00000800, 0x00000000, 0x00000000, 0x00000000,
352 0x00000000, 0x00000000, 0x00000000, 0x00000000,
353 0x00000000, 0x00000000, 0x00000000, 0x00000000,
354 0x00000000, 0x00000000, 0x00000000, 0x00000000,
355 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 0x00000000, 0x00000000, 0x00000000, 0x00000000,
361 /* UDP Packet types for non-tunneled packets or tunneled
362 * packets with inner UDP.
364 static const u32 ice_ptypes_udp_il[] = {
365 0x81000000, 0x20204040, 0x04000010, 0x80810102,
366 0x00000040, 0x00000000, 0x00000000, 0x00000000,
367 0x00000000, 0x00410000, 0x90842000, 0x00000007,
368 0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 0x00000000, 0x00000000, 0x00000000, 0x00000000,
375 /* Packet types for packets with an Innermost/Last TCP header */
376 static const u32 ice_ptypes_tcp_il[] = {
377 0x04000000, 0x80810102, 0x10000040, 0x02040408,
378 0x00000102, 0x00000000, 0x00000000, 0x00000000,
379 0x00000000, 0x00820000, 0x21084000, 0x00000000,
380 0x00000000, 0x00000000, 0x00000000, 0x00000000,
381 0x00000000, 0x00000000, 0x00000000, 0x00000000,
382 0x00000000, 0x00000000, 0x00000000, 0x00000000,
383 0x00000000, 0x00000000, 0x00000000, 0x00000000,
384 0x00000000, 0x00000000, 0x00000000, 0x00000000,
387 /* Packet types for packets with an Innermost/Last SCTP header */
388 static const u32 ice_ptypes_sctp_il[] = {
389 0x08000000, 0x01020204, 0x20000081, 0x04080810,
390 0x00000204, 0x00000000, 0x00000000, 0x00000000,
391 0x00000000, 0x01040000, 0x00000000, 0x00000000,
392 0x00000000, 0x00000000, 0x00000000, 0x00000000,
393 0x00000000, 0x00000000, 0x00000000, 0x00000000,
394 0x00000000, 0x00000000, 0x00000000, 0x00000000,
395 0x00000000, 0x00000000, 0x00000000, 0x00000000,
396 0x00000000, 0x00000000, 0x00000000, 0x00000000,
399 /* Packet types for packets with an Outermost/First ICMP header */
400 static const u32 ice_ptypes_icmp_of[] = {
401 0x10000000, 0x00000000, 0x00000000, 0x00000000,
402 0x00000000, 0x00000000, 0x00000000, 0x00000000,
403 0x00000000, 0x00000000, 0x00000000, 0x00000000,
404 0x00000000, 0x00000000, 0x00000000, 0x00000000,
405 0x00000000, 0x00000000, 0x00000000, 0x00000000,
406 0x00000000, 0x00000000, 0x00000000, 0x00000000,
407 0x00000000, 0x00000000, 0x00000000, 0x00000000,
408 0x00000000, 0x00000000, 0x00000000, 0x00000000,
411 /* Packet types for packets with an Innermost/Last ICMP header */
412 static const u32 ice_ptypes_icmp_il[] = {
413 0x00000000, 0x02040408, 0x40000102, 0x08101020,
414 0x00000408, 0x00000000, 0x00000000, 0x00000000,
415 0x00000000, 0x00000000, 0x42108000, 0x00000000,
416 0x00000000, 0x00000000, 0x00000000, 0x00000000,
417 0x00000000, 0x00000000, 0x00000000, 0x00000000,
418 0x00000000, 0x00000000, 0x00000000, 0x00000000,
419 0x00000000, 0x00000000, 0x00000000, 0x00000000,
420 0x00000000, 0x00000000, 0x00000000, 0x00000000,
423 /* Packet types for packets with an Outermost/First GRE header */
424 static const u32 ice_ptypes_gre_of[] = {
425 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
426 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
427 0x00000000, 0x00000000, 0x00000000, 0x00000000,
428 0x00000000, 0x00000000, 0x00000000, 0x00000000,
429 0x00000000, 0x00000000, 0x00000000, 0x00000000,
430 0x00000000, 0x00000000, 0x00000000, 0x00000000,
431 0x00000000, 0x00000000, 0x00000000, 0x00000000,
432 0x00000000, 0x00000000, 0x00000000, 0x00000000,
435 /* Packet types for packets with an Innermost/Last MAC header */
436 static const u32 ice_ptypes_mac_il[] = {
437 0x00000000, 0x00000000, 0x00000000, 0x00000000,
438 0x00000000, 0x00000000, 0x00000000, 0x00000000,
439 0x00000000, 0x00000000, 0x00000000, 0x00000000,
440 0x00000000, 0x00000000, 0x00000000, 0x00000000,
441 0x00000000, 0x00000000, 0x00000000, 0x00000000,
442 0x00000000, 0x00000000, 0x00000000, 0x00000000,
443 0x00000000, 0x00000000, 0x00000000, 0x00000000,
444 0x00000000, 0x00000000, 0x00000000, 0x00000000,
447 /* Packet types for GTPC */
448 static const u32 ice_ptypes_gtpc[] = {
449 0x00000000, 0x00000000, 0x00000000, 0x00000000,
450 0x00000000, 0x00000000, 0x00000000, 0x00000000,
451 0x00000000, 0x00000000, 0x000001E0, 0x00000000,
452 0x00000000, 0x00000000, 0x00000000, 0x00000000,
453 0x00000000, 0x00000000, 0x00000000, 0x00000000,
454 0x00000000, 0x00000000, 0x00000000, 0x00000000,
455 0x00000000, 0x00000000, 0x00000000, 0x00000000,
456 0x00000000, 0x00000000, 0x00000000, 0x00000000,
459 /* Packet types for GTPC with TEID */
460 static const u32 ice_ptypes_gtpc_tid[] = {
461 0x00000000, 0x00000000, 0x00000000, 0x00000000,
462 0x00000000, 0x00000000, 0x00000000, 0x00000000,
463 0x00000000, 0x00000000, 0x00000060, 0x00000000,
464 0x00000000, 0x00000000, 0x00000000, 0x00000000,
465 0x00000000, 0x00000000, 0x00000000, 0x00000000,
466 0x00000000, 0x00000000, 0x00000000, 0x00000000,
467 0x00000000, 0x00000000, 0x00000000, 0x00000000,
468 0x00000000, 0x00000000, 0x00000000, 0x00000000,
471 /* Packet types for GTPU */
472 static const struct ice_ptype_attributes ice_attr_gtpu_session[] = {
473 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
474 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
475 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
476 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
477 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION },
478 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
479 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
480 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
481 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
482 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION },
483 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
484 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
485 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
486 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
487 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION },
488 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
489 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
490 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
491 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
492 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION },
495 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
496 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
497 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
498 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
499 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
500 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
501 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
502 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
503 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
504 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
505 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
506 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
507 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
508 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
509 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
510 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
511 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
512 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
513 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
514 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
515 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
518 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
519 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
520 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
521 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
522 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
523 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
524 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
525 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
526 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
527 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
528 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
529 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
530 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
531 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
532 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
533 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
534 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
535 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
536 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
537 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
538 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
541 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
542 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
543 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
544 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
545 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
546 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
547 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
548 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
549 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
550 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
551 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
552 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
553 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
554 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
555 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
556 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
557 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
558 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
559 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
560 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
561 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
564 static const u32 ice_ptypes_gtpu[] = {
565 0x00000000, 0x00000000, 0x00000000, 0x00000000,
566 0x00000000, 0x00000000, 0x00000000, 0x00000000,
567 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
568 0x00000000, 0x00000000, 0x00000000, 0x00000000,
569 0x00000000, 0x00000000, 0x00000000, 0x00000000,
570 0x00000000, 0x00000000, 0x00000000, 0x00000000,
571 0x00000000, 0x00000000, 0x00000000, 0x00000000,
572 0x00000000, 0x00000000, 0x00000000, 0x00000000,
575 /* Packet types for pppoe */
576 static const u32 ice_ptypes_pppoe[] = {
577 0x00000000, 0x00000000, 0x00000000, 0x00000000,
578 0x00000000, 0x00000000, 0x00000000, 0x00000000,
579 0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
580 0x00000000, 0x00000000, 0x00000000, 0x00000000,
581 0x00000000, 0x00000000, 0x00000000, 0x00000000,
582 0x00000000, 0x00000000, 0x00000000, 0x00000000,
583 0x00000000, 0x00000000, 0x00000000, 0x00000000,
584 0x00000000, 0x00000000, 0x00000000, 0x00000000,
587 /* Packet types for packets with PFCP NODE header */
588 static const u32 ice_ptypes_pfcp_node[] = {
589 0x00000000, 0x00000000, 0x00000000, 0x00000000,
590 0x00000000, 0x00000000, 0x00000000, 0x00000000,
591 0x00000000, 0x00000000, 0x80000000, 0x00000002,
592 0x00000000, 0x00000000, 0x00000000, 0x00000000,
593 0x00000000, 0x00000000, 0x00000000, 0x00000000,
594 0x00000000, 0x00000000, 0x00000000, 0x00000000,
595 0x00000000, 0x00000000, 0x00000000, 0x00000000,
596 0x00000000, 0x00000000, 0x00000000, 0x00000000,
599 /* Packet types for packets with PFCP SESSION header */
600 static const u32 ice_ptypes_pfcp_session[] = {
601 0x00000000, 0x00000000, 0x00000000, 0x00000000,
602 0x00000000, 0x00000000, 0x00000000, 0x00000000,
603 0x00000000, 0x00000000, 0x00000000, 0x00000005,
604 0x00000000, 0x00000000, 0x00000000, 0x00000000,
605 0x00000000, 0x00000000, 0x00000000, 0x00000000,
606 0x00000000, 0x00000000, 0x00000000, 0x00000000,
607 0x00000000, 0x00000000, 0x00000000, 0x00000000,
608 0x00000000, 0x00000000, 0x00000000, 0x00000000,
611 /* Packet types for l2tpv3 */
612 static const u32 ice_ptypes_l2tpv3[] = {
613 0x00000000, 0x00000000, 0x00000000, 0x00000000,
614 0x00000000, 0x00000000, 0x00000000, 0x00000000,
615 0x00000000, 0x00000000, 0x00000000, 0x00000300,
616 0x00000000, 0x00000000, 0x00000000, 0x00000000,
617 0x00000000, 0x00000000, 0x00000000, 0x00000000,
618 0x00000000, 0x00000000, 0x00000000, 0x00000000,
619 0x00000000, 0x00000000, 0x00000000, 0x00000000,
620 0x00000000, 0x00000000, 0x00000000, 0x00000000,
623 /* Packet types for esp */
624 static const u32 ice_ptypes_esp[] = {
625 0x00000000, 0x00000000, 0x00000000, 0x00000000,
626 0x00000000, 0x00000003, 0x00000000, 0x00000000,
627 0x00000000, 0x00000000, 0x00000000, 0x00000000,
628 0x00000000, 0x00000000, 0x00000000, 0x00000000,
629 0x00000000, 0x00000000, 0x00000000, 0x00000000,
630 0x00000000, 0x00000000, 0x00000000, 0x00000000,
631 0x00000000, 0x00000000, 0x00000000, 0x00000000,
632 0x00000000, 0x00000000, 0x00000000, 0x00000000,
635 /* Packet types for ah */
636 static const u32 ice_ptypes_ah[] = {
637 0x00000000, 0x00000000, 0x00000000, 0x00000000,
638 0x00000000, 0x0000000C, 0x00000000, 0x00000000,
639 0x00000000, 0x00000000, 0x00000000, 0x00000000,
640 0x00000000, 0x00000000, 0x00000000, 0x00000000,
641 0x00000000, 0x00000000, 0x00000000, 0x00000000,
642 0x00000000, 0x00000000, 0x00000000, 0x00000000,
643 0x00000000, 0x00000000, 0x00000000, 0x00000000,
644 0x00000000, 0x00000000, 0x00000000, 0x00000000,
647 /* Packet types for packets with NAT_T ESP header */
648 static const u32 ice_ptypes_nat_t_esp[] = {
649 0x00000000, 0x00000000, 0x00000000, 0x00000000,
650 0x00000000, 0x00000030, 0x00000000, 0x00000000,
651 0x00000000, 0x00000000, 0x00000000, 0x00000000,
652 0x00000000, 0x00000000, 0x00000000, 0x00000000,
653 0x00000000, 0x00000000, 0x00000000, 0x00000000,
654 0x00000000, 0x00000000, 0x00000000, 0x00000000,
655 0x00000000, 0x00000000, 0x00000000, 0x00000000,
656 0x00000000, 0x00000000, 0x00000000, 0x00000000,
659 static const u32 ice_ptypes_mac_non_ip_ofos[] = {
660 0x00000846, 0x00000000, 0x00000000, 0x00000000,
661 0x00000000, 0x00000000, 0x00000000, 0x00000000,
662 0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
663 0x00000000, 0x00000000, 0x00000000, 0x00000000,
664 0x00000000, 0x00000000, 0x00000000, 0x00000000,
665 0x00000000, 0x00000000, 0x00000000, 0x00000000,
666 0x00000000, 0x00000000, 0x00000000, 0x00000000,
667 0x00000000, 0x00000000, 0x00000000, 0x00000000,
670 static const u32 ice_ptypes_gtpu_no_ip[] = {
671 0x00000000, 0x00000000, 0x00000000, 0x00000000,
672 0x00000000, 0x00000000, 0x00000000, 0x00000000,
673 0x00000000, 0x00000000, 0x00000600, 0x00000000,
674 0x00000000, 0x00000000, 0x00000000, 0x00000000,
675 0x00000000, 0x00000000, 0x00000000, 0x00000000,
676 0x00000000, 0x00000000, 0x00000000, 0x00000000,
677 0x00000000, 0x00000000, 0x00000000, 0x00000000,
678 0x00000000, 0x00000000, 0x00000000, 0x00000000,
681 /* Manage parameters and info. used during the creation of a flow profile */
682 struct ice_flow_prof_params {
684 u16 entry_length; /* # of bytes formatted entry will require */
686 struct ice_flow_prof *prof;
688 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
689 * This will give us the direction flags.
691 struct ice_fv_word es[ICE_MAX_FV_WORDS];
692 /* attributes can be used to add attributes to a particular PTYPE */
693 const struct ice_ptype_attributes *attr;
696 u16 mask[ICE_MAX_FV_WORDS];
697 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
700 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
701 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
702 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
703 ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
704 ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
705 ICE_FLOW_SEG_HDR_NAT_T_ESP | ICE_FLOW_SEG_HDR_GTPU_NON_IP)
707 #define ICE_FLOW_SEG_HDRS_L2_MASK \
708 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
709 #define ICE_FLOW_SEG_HDRS_L3_MASK \
710 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
711 ICE_FLOW_SEG_HDR_ARP)
712 #define ICE_FLOW_SEG_HDRS_L4_MASK \
713 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
714 ICE_FLOW_SEG_HDR_SCTP)
715 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */
716 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \
717 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
720 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
721 * @segs: array of one or more packet segments that describe the flow
722 * @segs_cnt: number of packet segments provided
724 static enum ice_status
725 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
729 for (i = 0; i < segs_cnt; i++) {
730 /* Multiple L3 headers */
731 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
732 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
733 return ICE_ERR_PARAM;
735 /* Multiple L4 headers */
736 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
737 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
738 return ICE_ERR_PARAM;
744 /* Sizes of fixed known protocol headers without header options */
745 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
746 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
747 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
748 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
749 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
750 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
751 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
752 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
753 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
756 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
757 * @params: information about the flow to be processed
758 * @seg: index of packet segment whose header size is to be determined
760 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
765 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
766 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
769 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
770 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
771 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
772 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
773 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
774 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
775 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
776 /* A L3 header is required if L4 is specified */
780 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
781 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
782 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
783 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
784 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
785 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
786 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
787 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
793 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
794 * @params: information about the flow to be processed
796 * This function identifies the packet types associated with the protocol
797 * headers being present in packet segments of the specified flow profile.
799 static enum ice_status
800 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
802 struct ice_flow_prof *prof;
805 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
810 for (i = 0; i < params->prof->segs_cnt; i++) {
811 const ice_bitmap_t *src;
814 hdrs = prof->segs[i].hdrs;
816 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
817 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
818 (const ice_bitmap_t *)ice_ptypes_mac_il;
819 ice_and_bitmap(params->ptypes, params->ptypes, src,
823 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
824 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
825 ice_and_bitmap(params->ptypes, params->ptypes, src,
829 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
830 ice_and_bitmap(params->ptypes, params->ptypes,
831 (const ice_bitmap_t *)ice_ptypes_arp_of,
835 if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
836 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
837 ice_and_bitmap(params->ptypes, params->ptypes, src,
840 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
841 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
843 (const ice_bitmap_t *)ice_ptypes_ipv4_il :
844 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
845 ice_and_bitmap(params->ptypes, params->ptypes, src,
847 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
848 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
850 (const ice_bitmap_t *)ice_ptypes_ipv6_il :
851 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
852 ice_and_bitmap(params->ptypes, params->ptypes, src,
854 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
855 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
856 src = !i ? (const ice_bitmap_t *)ice_ipv4_ofos_no_l4 :
857 (const ice_bitmap_t *)ice_ipv4_il_no_l4;
858 ice_and_bitmap(params->ptypes, params->ptypes, src,
860 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
861 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
862 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
863 ice_and_bitmap(params->ptypes, params->ptypes, src,
865 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
866 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
867 src = !i ? (const ice_bitmap_t *)ice_ipv6_ofos_no_l4 :
868 (const ice_bitmap_t *)ice_ipv6_il_no_l4;
869 ice_and_bitmap(params->ptypes, params->ptypes, src,
871 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
872 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
873 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
874 ice_and_bitmap(params->ptypes, params->ptypes, src,
878 if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
879 src = (const ice_bitmap_t *)ice_ptypes_mac_non_ip_ofos;
880 ice_and_bitmap(params->ptypes, params->ptypes,
881 src, ICE_FLOW_PTYPE_MAX);
882 } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
883 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
884 ice_and_bitmap(params->ptypes, params->ptypes, src,
887 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
888 ice_andnot_bitmap(params->ptypes, params->ptypes, src,
892 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
893 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
894 ice_and_bitmap(params->ptypes, params->ptypes, src,
896 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
897 ice_and_bitmap(params->ptypes, params->ptypes,
898 (const ice_bitmap_t *)ice_ptypes_tcp_il,
900 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
901 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
902 ice_and_bitmap(params->ptypes, params->ptypes, src,
906 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
907 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
908 (const ice_bitmap_t *)ice_ptypes_icmp_il;
909 ice_and_bitmap(params->ptypes, params->ptypes, src,
911 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
913 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
914 ice_and_bitmap(params->ptypes, params->ptypes,
915 src, ICE_FLOW_PTYPE_MAX);
917 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
918 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
919 ice_and_bitmap(params->ptypes, params->ptypes,
920 src, ICE_FLOW_PTYPE_MAX);
921 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
922 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
923 ice_and_bitmap(params->ptypes, params->ptypes,
924 src, ICE_FLOW_PTYPE_MAX);
925 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_NON_IP) {
926 src = (const ice_bitmap_t *)ice_ptypes_gtpu_no_ip;
927 ice_and_bitmap(params->ptypes, params->ptypes,
928 src, ICE_FLOW_PTYPE_MAX);
929 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
930 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
931 ice_and_bitmap(params->ptypes, params->ptypes,
932 src, ICE_FLOW_PTYPE_MAX);
934 /* Attributes for GTP packet with downlink */
935 params->attr = ice_attr_gtpu_down;
936 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
937 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
938 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
939 ice_and_bitmap(params->ptypes, params->ptypes,
940 src, ICE_FLOW_PTYPE_MAX);
942 /* Attributes for GTP packet with uplink */
943 params->attr = ice_attr_gtpu_up;
944 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
945 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
946 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
947 ice_and_bitmap(params->ptypes, params->ptypes,
948 src, ICE_FLOW_PTYPE_MAX);
950 /* Attributes for GTP packet with Extension Header */
951 params->attr = ice_attr_gtpu_eh;
952 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
953 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
954 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
955 ice_and_bitmap(params->ptypes, params->ptypes,
956 src, ICE_FLOW_PTYPE_MAX);
958 /* Attributes for GTP packet without Extension Header */
959 params->attr = ice_attr_gtpu_session;
960 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session);
961 } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
962 src = (const ice_bitmap_t *)ice_ptypes_l2tpv3;
963 ice_and_bitmap(params->ptypes, params->ptypes,
964 src, ICE_FLOW_PTYPE_MAX);
965 } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
966 src = (const ice_bitmap_t *)ice_ptypes_esp;
967 ice_and_bitmap(params->ptypes, params->ptypes,
968 src, ICE_FLOW_PTYPE_MAX);
969 } else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
970 src = (const ice_bitmap_t *)ice_ptypes_ah;
971 ice_and_bitmap(params->ptypes, params->ptypes,
972 src, ICE_FLOW_PTYPE_MAX);
973 } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
974 src = (const ice_bitmap_t *)ice_ptypes_nat_t_esp;
975 ice_and_bitmap(params->ptypes, params->ptypes,
976 src, ICE_FLOW_PTYPE_MAX);
979 if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
980 if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
982 (const ice_bitmap_t *)ice_ptypes_pfcp_node;
985 (const ice_bitmap_t *)ice_ptypes_pfcp_session;
987 ice_and_bitmap(params->ptypes, params->ptypes,
988 src, ICE_FLOW_PTYPE_MAX);
990 src = (const ice_bitmap_t *)ice_ptypes_pfcp_node;
991 ice_andnot_bitmap(params->ptypes, params->ptypes,
992 src, ICE_FLOW_PTYPE_MAX);
994 src = (const ice_bitmap_t *)ice_ptypes_pfcp_session;
995 ice_andnot_bitmap(params->ptypes, params->ptypes,
996 src, ICE_FLOW_PTYPE_MAX);
1004 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
1005 * @hw: pointer to the HW struct
1006 * @params: information about the flow to be processed
1007 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
1009 * This function will allocate an extraction sequence entries for a DWORD size
1010 * chunk of the packet flags.
1012 static enum ice_status
1013 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
1014 struct ice_flow_prof_params *params,
1015 enum ice_flex_mdid_pkt_flags flags)
1017 u8 fv_words = hw->blk[params->blk].es.fvw;
1020 /* Make sure the number of extraction sequence entries required does not
1021 * exceed the block's capacity.
1023 if (params->es_cnt >= fv_words)
1024 return ICE_ERR_MAX_LIMIT;
1026 /* some blocks require a reversed field vector layout */
1027 if (hw->blk[params->blk].es.reverse)
1028 idx = fv_words - params->es_cnt - 1;
1030 idx = params->es_cnt;
1032 params->es[idx].prot_id = ICE_PROT_META_ID;
1033 params->es[idx].off = flags;
1040 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
1041 * @hw: pointer to the HW struct
1042 * @params: information about the flow to be processed
1043 * @seg: packet segment index of the field to be extracted
1044 * @fld: ID of field to be extracted
1045 * @match: bitfield of all fields
1047 * This function determines the protocol ID, offset, and size of the given
1048 * field. It then allocates one or more extraction sequence entries for the
1049 * given field, and fill the entries with protocol ID and offset information.
1051 static enum ice_status
1052 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
1053 u8 seg, enum ice_flow_field fld, u64 match)
1055 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
1056 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
1057 u8 fv_words = hw->blk[params->blk].es.fvw;
1058 struct ice_flow_fld_info *flds;
1059 u16 cnt, ese_bits, i;
1064 flds = params->prof->segs[seg].fields;
1067 case ICE_FLOW_FIELD_IDX_ETH_DA:
1068 case ICE_FLOW_FIELD_IDX_ETH_SA:
1069 case ICE_FLOW_FIELD_IDX_S_VLAN:
1070 case ICE_FLOW_FIELD_IDX_C_VLAN:
1071 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
1073 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
1074 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
1076 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
1077 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1079 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
1080 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1082 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
1083 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
1084 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1086 /* TTL and PROT share the same extraction seq. entry.
1087 * Each is considered a sibling to the other in terms of sharing
1088 * the same extraction sequence entry.
1090 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
1091 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
1092 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
1093 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
1095 /* If the sibling field is also included, that field's
1096 * mask needs to be included.
1098 if (match & BIT(sib))
1099 sib_mask = ice_flds_info[sib].mask;
1101 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
1102 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
1103 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1105 /* TTL and PROT share the same extraction seq. entry.
1106 * Each is considered a sibling to the other in terms of sharing
1107 * the same extraction sequence entry.
1109 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
1110 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
1111 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
1112 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
1114 /* If the sibling field is also included, that field's
1115 * mask needs to be included.
1117 if (match & BIT(sib))
1118 sib_mask = ice_flds_info[sib].mask;
1120 case ICE_FLOW_FIELD_IDX_IPV4_SA:
1121 case ICE_FLOW_FIELD_IDX_IPV4_DA:
1122 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1124 case ICE_FLOW_FIELD_IDX_IPV6_SA:
1125 case ICE_FLOW_FIELD_IDX_IPV6_DA:
1126 case ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA:
1127 case ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA:
1128 case ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA:
1129 case ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA:
1130 case ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA:
1131 case ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA:
1132 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1134 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
1135 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
1136 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
1137 prot_id = ICE_PROT_TCP_IL;
1139 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
1140 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
1141 prot_id = ICE_PROT_UDP_IL_OR_S;
1143 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
1144 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
1145 prot_id = ICE_PROT_SCTP_IL;
1147 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
1148 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
1149 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
1150 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
1151 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
1152 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
1153 /* GTP is accessed through UDP OF protocol */
1154 prot_id = ICE_PROT_UDP_OF;
1156 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
1157 prot_id = ICE_PROT_PPPOE;
1159 case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1160 prot_id = ICE_PROT_UDP_IL_OR_S;
1162 case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1163 prot_id = ICE_PROT_L2TPV3;
1165 case ICE_FLOW_FIELD_IDX_ESP_SPI:
1166 prot_id = ICE_PROT_ESP_F;
1168 case ICE_FLOW_FIELD_IDX_AH_SPI:
1169 prot_id = ICE_PROT_ESP_2;
1171 case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1172 prot_id = ICE_PROT_UDP_IL_OR_S;
1174 case ICE_FLOW_FIELD_IDX_ARP_SIP:
1175 case ICE_FLOW_FIELD_IDX_ARP_DIP:
1176 case ICE_FLOW_FIELD_IDX_ARP_SHA:
1177 case ICE_FLOW_FIELD_IDX_ARP_DHA:
1178 case ICE_FLOW_FIELD_IDX_ARP_OP:
1179 prot_id = ICE_PROT_ARP_OF;
1181 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1182 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1183 /* ICMP type and code share the same extraction seq. entry */
1184 prot_id = (params->prof->segs[seg].hdrs &
1185 ICE_FLOW_SEG_HDR_IPV4) ?
1186 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1187 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1188 ICE_FLOW_FIELD_IDX_ICMP_CODE :
1189 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1191 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1192 prot_id = ICE_PROT_GRE_OF;
1195 return ICE_ERR_NOT_IMPL;
1198 /* Each extraction sequence entry is a word in size, and extracts a
1199 * word-aligned offset from a protocol header.
1201 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1203 flds[fld].xtrct.prot_id = prot_id;
1204 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1205 ICE_FLOW_FV_EXTRACT_SZ;
1206 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1207 flds[fld].xtrct.idx = params->es_cnt;
1208 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1210 /* Adjust the next field-entry index after accommodating the number of
1211 * entries this field consumes
1213 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
1214 ice_flds_info[fld].size, ese_bits);
1216 /* Fill in the extraction sequence entries needed for this field */
1217 off = flds[fld].xtrct.off;
1218 mask = flds[fld].xtrct.mask;
1219 for (i = 0; i < cnt; i++) {
1220 /* Only consume an extraction sequence entry if there is no
1221 * sibling field associated with this field or the sibling entry
1222 * already extracts the word shared with this field.
1224 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1225 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1226 flds[sib].xtrct.off != off) {
1229 /* Make sure the number of extraction sequence required
1230 * does not exceed the block's capability
1232 if (params->es_cnt >= fv_words)
1233 return ICE_ERR_MAX_LIMIT;
1235 /* some blocks require a reversed field vector layout */
1236 if (hw->blk[params->blk].es.reverse)
1237 idx = fv_words - params->es_cnt - 1;
1239 idx = params->es_cnt;
1241 params->es[idx].prot_id = prot_id;
1242 params->es[idx].off = off;
1243 params->mask[idx] = mask | sib_mask;
1247 off += ICE_FLOW_FV_EXTRACT_SZ;
1254 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1255 * @hw: pointer to the HW struct
1256 * @params: information about the flow to be processed
1257 * @seg: index of packet segment whose raw fields are to be be extracted
1259 static enum ice_status
1260 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1267 if (!params->prof->segs[seg].raws_cnt)
1270 if (params->prof->segs[seg].raws_cnt >
1271 ARRAY_SIZE(params->prof->segs[seg].raws))
1272 return ICE_ERR_MAX_LIMIT;
1274 /* Offsets within the segment headers are not supported */
1275 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1277 return ICE_ERR_PARAM;
1279 fv_words = hw->blk[params->blk].es.fvw;
1281 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1282 struct ice_flow_seg_fld_raw *raw;
1285 raw = ¶ms->prof->segs[seg].raws[i];
1287 /* Storing extraction information */
1288 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1289 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1290 ICE_FLOW_FV_EXTRACT_SZ;
1291 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1293 raw->info.xtrct.idx = params->es_cnt;
1295 /* Determine the number of field vector entries this raw field
1298 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
1299 (raw->info.src.last * BITS_PER_BYTE),
1300 (ICE_FLOW_FV_EXTRACT_SZ *
1302 off = raw->info.xtrct.off;
1303 for (j = 0; j < cnt; j++) {
1306 /* Make sure the number of extraction sequence required
1307 * does not exceed the block's capability
1309 if (params->es_cnt >= hw->blk[params->blk].es.count ||
1310 params->es_cnt >= ICE_MAX_FV_WORDS)
1311 return ICE_ERR_MAX_LIMIT;
1313 /* some blocks require a reversed field vector layout */
1314 if (hw->blk[params->blk].es.reverse)
1315 idx = fv_words - params->es_cnt - 1;
1317 idx = params->es_cnt;
1319 params->es[idx].prot_id = raw->info.xtrct.prot_id;
1320 params->es[idx].off = off;
1322 off += ICE_FLOW_FV_EXTRACT_SZ;
1330 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1331 * @hw: pointer to the HW struct
1332 * @params: information about the flow to be processed
1334 * This function iterates through all matched fields in the given segments, and
1335 * creates an extraction sequence for the fields.
1337 static enum ice_status
1338 ice_flow_create_xtrct_seq(struct ice_hw *hw,
1339 struct ice_flow_prof_params *params)
1341 enum ice_status status = ICE_SUCCESS;
1344 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
1347 if (params->blk == ICE_BLK_ACL) {
1348 status = ice_flow_xtract_pkt_flags(hw, params,
1349 ICE_RX_MDID_PKT_FLAGS_15_0);
1354 for (i = 0; i < params->prof->segs_cnt; i++) {
1355 u64 match = params->prof->segs[i].match;
1356 enum ice_flow_field j;
1358 ice_for_each_set_bit(j, (ice_bitmap_t *)&match,
1359 ICE_FLOW_FIELD_IDX_MAX) {
1360 status = ice_flow_xtract_fld(hw, params, i, j, match);
1363 ice_clear_bit(j, (ice_bitmap_t *)&match);
1366 /* Process raw matching bytes */
1367 status = ice_flow_xtract_raws(hw, params, i);
1376 * ice_flow_sel_acl_scen - returns the specific scenario
1377 * @hw: pointer to the hardware structure
1378 * @params: information about the flow to be processed
1380 * This function will return the specific scenario based on the
1381 * params passed to it
1383 static enum ice_status
1384 ice_flow_sel_acl_scen(struct ice_hw *hw, struct ice_flow_prof_params *params)
1386 /* Find the best-fit scenario for the provided match width */
1387 struct ice_acl_scen *cand_scen = NULL, *scen;
1390 return ICE_ERR_DOES_NOT_EXIST;
1392 /* Loop through each scenario and match against the scenario width
1393 * to select the specific scenario
1395 LIST_FOR_EACH_ENTRY(scen, &hw->acl_tbl->scens, ice_acl_scen, list_entry)
1396 if (scen->eff_width >= params->entry_length &&
1397 (!cand_scen || cand_scen->eff_width > scen->eff_width))
1400 return ICE_ERR_DOES_NOT_EXIST;
1402 params->prof->cfg.scen = cand_scen;
1408 * ice_flow_acl_def_entry_frmt - Determine the layout of flow entries
1409 * @params: information about the flow to be processed
1411 static enum ice_status
1412 ice_flow_acl_def_entry_frmt(struct ice_flow_prof_params *params)
1414 u16 index, i, range_idx = 0;
1416 index = ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1418 for (i = 0; i < params->prof->segs_cnt; i++) {
1419 struct ice_flow_seg_info *seg = ¶ms->prof->segs[i];
1422 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
1423 ICE_FLOW_FIELD_IDX_MAX) {
1424 struct ice_flow_fld_info *fld = &seg->fields[j];
1426 fld->entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1428 if (fld->type == ICE_FLOW_FLD_TYPE_RANGE) {
1429 fld->entry.last = ICE_FLOW_FLD_OFF_INVAL;
1431 /* Range checking only supported for single
1434 if (DIVIDE_AND_ROUND_UP(ice_flds_info[j].size +
1436 BITS_PER_BYTE * 2) > 1)
1437 return ICE_ERR_PARAM;
1439 /* Ranges must define low and high values */
1440 if (fld->src.val == ICE_FLOW_FLD_OFF_INVAL ||
1441 fld->src.last == ICE_FLOW_FLD_OFF_INVAL)
1442 return ICE_ERR_PARAM;
1444 fld->entry.val = range_idx++;
1446 /* Store adjusted byte-length of field for later
1447 * use, taking into account potential
1448 * non-byte-aligned displacement
1450 fld->entry.last = DIVIDE_AND_ROUND_UP
1451 (ice_flds_info[j].size +
1452 (fld->xtrct.disp % BITS_PER_BYTE),
1454 fld->entry.val = index;
1455 index += fld->entry.last;
1459 for (j = 0; j < seg->raws_cnt; j++) {
1460 struct ice_flow_seg_fld_raw *raw = &seg->raws[j];
1462 raw->info.entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1463 raw->info.entry.val = index;
1464 raw->info.entry.last = raw->info.src.last;
1465 index += raw->info.entry.last;
1469 /* Currently only support using the byte selection base, which only
1470 * allows for an effective entry size of 30 bytes. Reject anything
1473 if (index > ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS)
1474 return ICE_ERR_PARAM;
1476 /* Only 8 range checkers per profile, reject anything trying to use
1479 if (range_idx > ICE_AQC_ACL_PROF_RANGES_NUM_CFG)
1480 return ICE_ERR_PARAM;
1482 /* Store # bytes required for entry for later use */
1483 params->entry_length = index - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1489 * ice_flow_proc_segs - process all packet segments associated with a profile
1490 * @hw: pointer to the HW struct
1491 * @params: information about the flow to be processed
1493 static enum ice_status
1494 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1496 enum ice_status status;
1498 status = ice_flow_proc_seg_hdrs(params);
1502 status = ice_flow_create_xtrct_seq(hw, params);
1506 switch (params->blk) {
1509 status = ICE_SUCCESS;
1512 status = ice_flow_acl_def_entry_frmt(params);
1515 status = ice_flow_sel_acl_scen(hw, params);
1520 return ICE_ERR_NOT_IMPL;
1526 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1527 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
1528 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
1531 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1532 * @hw: pointer to the HW struct
1533 * @blk: classification stage
1534 * @dir: flow direction
1535 * @segs: array of one or more packet segments that describe the flow
1536 * @segs_cnt: number of packet segments provided
1537 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1538 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1540 static struct ice_flow_prof *
1541 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1542 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1543 u8 segs_cnt, u16 vsi_handle, u32 conds)
1545 struct ice_flow_prof *p, *prof = NULL;
1547 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1548 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1549 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1550 segs_cnt && segs_cnt == p->segs_cnt) {
1553 /* Check for profile-VSI association if specified */
1554 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1555 ice_is_vsi_valid(hw, vsi_handle) &&
1556 !ice_is_bit_set(p->vsis, vsi_handle))
1559 /* Protocol headers must be checked. Matched fields are
1560 * checked if specified.
1562 for (i = 0; i < segs_cnt; i++)
1563 if (segs[i].hdrs != p->segs[i].hdrs ||
1564 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1565 segs[i].match != p->segs[i].match))
1568 /* A match is found if all segments are matched */
1569 if (i == segs_cnt) {
1574 ice_release_lock(&hw->fl_profs_locks[blk]);
1580 * ice_flow_find_prof - Look up a profile matching headers and matched fields
1581 * @hw: pointer to the HW struct
1582 * @blk: classification stage
1583 * @dir: flow direction
1584 * @segs: array of one or more packet segments that describe the flow
1585 * @segs_cnt: number of packet segments provided
1588 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1589 struct ice_flow_seg_info *segs, u8 segs_cnt)
1591 struct ice_flow_prof *p;
1593 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1594 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1596 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1600 * ice_flow_find_prof_id - Look up a profile with given profile ID
1601 * @hw: pointer to the HW struct
1602 * @blk: classification stage
1603 * @prof_id: unique ID to identify this flow profile
1605 static struct ice_flow_prof *
1606 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1608 struct ice_flow_prof *p;
1610 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1611 if (p->id == prof_id)
1618 * ice_dealloc_flow_entry - Deallocate flow entry memory
1619 * @hw: pointer to the HW struct
1620 * @entry: flow entry to be removed
1623 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1629 ice_free(hw, entry->entry);
1631 if (entry->range_buf) {
1632 ice_free(hw, entry->range_buf);
1633 entry->range_buf = NULL;
1637 ice_free(hw, entry->acts);
1639 entry->acts_cnt = 0;
1642 ice_free(hw, entry);
1646 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1647 * @hw: pointer to the HW struct
1648 * @blk: classification stage
1649 * @prof_id: the profile ID handle
1650 * @hw_prof_id: pointer to variable to receive the HW profile ID
1653 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1656 enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
1657 struct ice_prof_map *map;
1659 ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
1660 map = ice_search_prof_id(hw, blk, prof_id);
1662 *hw_prof_id = map->prof_id;
1663 status = ICE_SUCCESS;
1665 ice_release_lock(&hw->blk[blk].es.prof_map_lock);
1669 #define ICE_ACL_INVALID_SCEN 0x3f
1672 * ice_flow_acl_is_prof_in_use - Verify if the profile is associated to any PF
1673 * @hw: pointer to the hardware structure
1674 * @prof: pointer to flow profile
1675 * @buf: destination buffer function writes partial extraction sequence to
1677 * returns ICE_SUCCESS if no PF is associated to the given profile
1678 * returns ICE_ERR_IN_USE if at least one PF is associated to the given profile
1679 * returns other error code for real error
1681 static enum ice_status
1682 ice_flow_acl_is_prof_in_use(struct ice_hw *hw, struct ice_flow_prof *prof,
1683 struct ice_aqc_acl_prof_generic_frmt *buf)
1685 enum ice_status status;
1688 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1692 status = ice_query_acl_prof(hw, prof_id, buf, NULL);
1696 /* If all PF's associated scenarios are all 0 or all
1697 * ICE_ACL_INVALID_SCEN (63) for the given profile then the latter has
1698 * not been configured yet.
1700 if (buf->pf_scenario_num[0] == 0 && buf->pf_scenario_num[1] == 0 &&
1701 buf->pf_scenario_num[2] == 0 && buf->pf_scenario_num[3] == 0 &&
1702 buf->pf_scenario_num[4] == 0 && buf->pf_scenario_num[5] == 0 &&
1703 buf->pf_scenario_num[6] == 0 && buf->pf_scenario_num[7] == 0)
1706 if (buf->pf_scenario_num[0] == ICE_ACL_INVALID_SCEN &&
1707 buf->pf_scenario_num[1] == ICE_ACL_INVALID_SCEN &&
1708 buf->pf_scenario_num[2] == ICE_ACL_INVALID_SCEN &&
1709 buf->pf_scenario_num[3] == ICE_ACL_INVALID_SCEN &&
1710 buf->pf_scenario_num[4] == ICE_ACL_INVALID_SCEN &&
1711 buf->pf_scenario_num[5] == ICE_ACL_INVALID_SCEN &&
1712 buf->pf_scenario_num[6] == ICE_ACL_INVALID_SCEN &&
1713 buf->pf_scenario_num[7] == ICE_ACL_INVALID_SCEN)
1716 return ICE_ERR_IN_USE;
1720 * ice_flow_acl_free_act_cntr - Free the ACL rule's actions
1721 * @hw: pointer to the hardware structure
1722 * @acts: array of actions to be performed on a match
1723 * @acts_cnt: number of actions
1725 static enum ice_status
1726 ice_flow_acl_free_act_cntr(struct ice_hw *hw, struct ice_flow_action *acts,
1731 for (i = 0; i < acts_cnt; i++) {
1732 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
1733 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
1734 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
1735 struct ice_acl_cntrs cntrs;
1736 enum ice_status status;
1738 cntrs.bank = 0; /* Only bank0 for the moment */
1740 LE16_TO_CPU(acts[i].data.acl_act.value);
1742 LE16_TO_CPU(acts[i].data.acl_act.value);
1744 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
1745 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
1747 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
1749 status = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL);
1758 * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile
1759 * @hw: pointer to the hardware structure
1760 * @prof: pointer to flow profile
1762 * Disassociate the scenario from the profile for the PF of the VSI.
1764 static enum ice_status
1765 ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof)
1767 struct ice_aqc_acl_prof_generic_frmt buf;
1768 enum ice_status status = ICE_SUCCESS;
1771 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
1773 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1777 status = ice_query_acl_prof(hw, prof_id, &buf, NULL);
1781 /* Clear scenario for this PF */
1782 buf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN;
1783 status = ice_prgm_acl_prof_extrt(hw, prof_id, &buf, NULL);
1789 * ice_flow_rem_entry_sync - Remove a flow entry
1790 * @hw: pointer to the HW struct
1791 * @blk: classification stage
1792 * @entry: flow entry to be removed
1794 static enum ice_status
1795 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk,
1796 struct ice_flow_entry *entry)
1799 return ICE_ERR_BAD_PTR;
1801 if (blk == ICE_BLK_ACL) {
1802 enum ice_status status;
1805 return ICE_ERR_BAD_PTR;
1807 status = ice_acl_rem_entry(hw, entry->prof->cfg.scen,
1808 entry->scen_entry_idx);
1812 /* Checks if we need to release an ACL counter. */
1813 if (entry->acts_cnt && entry->acts)
1814 ice_flow_acl_free_act_cntr(hw, entry->acts,
1818 LIST_DEL(&entry->l_entry);
1820 ice_dealloc_flow_entry(hw, entry);
1826 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1827 * @hw: pointer to the HW struct
1828 * @blk: classification stage
1829 * @dir: flow direction
1830 * @prof_id: unique ID to identify this flow profile
1831 * @segs: array of one or more packet segments that describe the flow
1832 * @segs_cnt: number of packet segments provided
1833 * @acts: array of default actions
1834 * @acts_cnt: number of default actions
1835 * @prof: stores the returned flow profile added
1837 * Assumption: the caller has acquired the lock to the profile list
1839 static enum ice_status
1840 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1841 enum ice_flow_dir dir, u64 prof_id,
1842 struct ice_flow_seg_info *segs, u8 segs_cnt,
1843 struct ice_flow_action *acts, u8 acts_cnt,
1844 struct ice_flow_prof **prof)
1846 struct ice_flow_prof_params *params;
1847 enum ice_status status;
1850 if (!prof || (acts_cnt && !acts))
1851 return ICE_ERR_BAD_PTR;
1853 params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
1855 return ICE_ERR_NO_MEMORY;
1857 params->prof = (struct ice_flow_prof *)
1858 ice_malloc(hw, sizeof(*params->prof));
1859 if (!params->prof) {
1860 status = ICE_ERR_NO_MEMORY;
1864 /* initialize extraction sequence to all invalid (0xff) */
1865 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1866 params->es[i].prot_id = ICE_PROT_INVALID;
1867 params->es[i].off = ICE_FV_OFFSET_INVAL;
1871 params->prof->id = prof_id;
1872 params->prof->dir = dir;
1873 params->prof->segs_cnt = segs_cnt;
1875 /* Make a copy of the segments that need to be persistent in the flow
1878 for (i = 0; i < segs_cnt; i++)
1879 ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs),
1880 ICE_NONDMA_TO_NONDMA);
1882 /* Make a copy of the actions that need to be persistent in the flow
1886 params->prof->acts = (struct ice_flow_action *)
1887 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1888 ICE_NONDMA_TO_NONDMA);
1890 if (!params->prof->acts) {
1891 status = ICE_ERR_NO_MEMORY;
1896 status = ice_flow_proc_segs(hw, params);
1898 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1902 /* Add a HW profile for this flow profile */
1903 status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1904 params->attr, params->attr_cnt, params->es,
1907 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1911 INIT_LIST_HEAD(¶ms->prof->entries);
1912 ice_init_lock(¶ms->prof->entries_lock);
1913 *prof = params->prof;
1917 if (params->prof->acts)
1918 ice_free(hw, params->prof->acts);
1919 ice_free(hw, params->prof);
1922 ice_free(hw, params);
1928 * ice_flow_rem_prof_sync - remove a flow profile
1929 * @hw: pointer to the hardware structure
1930 * @blk: classification stage
1931 * @prof: pointer to flow profile to remove
1933 * Assumption: the caller has acquired the lock to the profile list
1935 static enum ice_status
1936 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1937 struct ice_flow_prof *prof)
1939 enum ice_status status;
1941 /* Remove all remaining flow entries before removing the flow profile */
1942 if (!LIST_EMPTY(&prof->entries)) {
1943 struct ice_flow_entry *e, *t;
1945 ice_acquire_lock(&prof->entries_lock);
1947 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1949 status = ice_flow_rem_entry_sync(hw, blk, e);
1954 ice_release_lock(&prof->entries_lock);
1957 if (blk == ICE_BLK_ACL) {
1958 struct ice_aqc_acl_profile_ranges query_rng_buf;
1959 struct ice_aqc_acl_prof_generic_frmt buf;
1962 /* Disassociate the scenario from the profile for the PF */
1963 status = ice_flow_acl_disassoc_scen(hw, prof);
1967 /* Clear the range-checker if the profile ID is no longer
1970 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
1971 if (status && status != ICE_ERR_IN_USE) {
1973 } else if (!status) {
1974 /* Clear the range-checker value for profile ID */
1975 ice_memset(&query_rng_buf, 0,
1976 sizeof(struct ice_aqc_acl_profile_ranges),
1979 status = ice_flow_get_hw_prof(hw, blk, prof->id,
1984 status = ice_prog_acl_prof_ranges(hw, prof_id,
1985 &query_rng_buf, NULL);
1991 /* Remove all hardware profiles associated with this flow profile */
1992 status = ice_rem_prof(hw, blk, prof->id);
1994 LIST_DEL(&prof->l_entry);
1995 ice_destroy_lock(&prof->entries_lock);
1997 ice_free(hw, prof->acts);
2005 * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field
2006 * @buf: Destination buffer function writes partial xtrct sequence to
2007 * @info: Info about field
2010 ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf,
2011 struct ice_flow_fld_info *info)
2016 src = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ +
2017 info->xtrct.disp / BITS_PER_BYTE;
2018 dst = info->entry.val;
2019 for (i = 0; i < info->entry.last; i++)
2020 /* HW stores field vector words in LE, convert words back to BE
2021 * so constructed entries will end up in network order
2023 buf->byte_selection[dst++] = src++ ^ 1;
2027 * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence
2028 * @hw: pointer to the hardware structure
2029 * @prof: pointer to flow profile
2031 static enum ice_status
2032 ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof)
2034 struct ice_aqc_acl_prof_generic_frmt buf;
2035 struct ice_flow_fld_info *info;
2036 enum ice_status status;
2040 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2042 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2046 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2047 if (status && status != ICE_ERR_IN_USE)
2051 /* Program the profile dependent configuration. This is done
2052 * only once regardless of the number of PFs using that profile
2054 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2056 for (i = 0; i < prof->segs_cnt; i++) {
2057 struct ice_flow_seg_info *seg = &prof->segs[i];
2060 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2061 ICE_FLOW_FIELD_IDX_MAX) {
2062 info = &seg->fields[j];
2064 if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2065 buf.word_selection[info->entry.val] =
2068 ice_flow_acl_set_xtrct_seq_fld(&buf,
2072 for (j = 0; j < seg->raws_cnt; j++) {
2073 info = &seg->raws[j].info;
2074 ice_flow_acl_set_xtrct_seq_fld(&buf, info);
2078 ice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN,
2079 ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS,
2083 /* Update the current PF */
2084 buf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id;
2085 status = ice_prgm_acl_prof_extrt(hw, prof_id, &buf, NULL);
2091 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
2092 * @hw: pointer to the hardware structure
2093 * @blk: classification stage
2094 * @vsi_handle: software VSI handle
2095 * @vsig: target VSI group
2097 * Assumption: the caller has already verified that the VSI to
2098 * be added has the same characteristics as the VSIG and will
2099 * thereby have access to all resources added to that VSIG.
2102 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
2105 enum ice_status status;
2107 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
2108 return ICE_ERR_PARAM;
2110 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2111 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
2113 ice_release_lock(&hw->fl_profs_locks[blk]);
2119 * ice_flow_assoc_prof - associate a VSI with a flow profile
2120 * @hw: pointer to the hardware structure
2121 * @blk: classification stage
2122 * @prof: pointer to flow profile
2123 * @vsi_handle: software VSI handle
2125 * Assumption: the caller has acquired the lock to the profile list
2126 * and the software VSI handle has been validated
2128 static enum ice_status
2129 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
2130 struct ice_flow_prof *prof, u16 vsi_handle)
2132 enum ice_status status = ICE_SUCCESS;
2134 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
2135 if (blk == ICE_BLK_ACL) {
2136 status = ice_flow_acl_set_xtrct_seq(hw, prof);
2140 status = ice_add_prof_id_flow(hw, blk,
2141 ice_get_hw_vsi_num(hw,
2145 ice_set_bit(vsi_handle, prof->vsis);
2147 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
2155 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
2156 * @hw: pointer to the hardware structure
2157 * @blk: classification stage
2158 * @prof: pointer to flow profile
2159 * @vsi_handle: software VSI handle
2161 * Assumption: the caller has acquired the lock to the profile list
2162 * and the software VSI handle has been validated
2164 static enum ice_status
2165 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
2166 struct ice_flow_prof *prof, u16 vsi_handle)
2168 enum ice_status status = ICE_SUCCESS;
2170 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
2171 status = ice_rem_prof_id_flow(hw, blk,
2172 ice_get_hw_vsi_num(hw,
2176 ice_clear_bit(vsi_handle, prof->vsis);
2178 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
2186 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
2187 * @hw: pointer to the HW struct
2188 * @blk: classification stage
2189 * @dir: flow direction
2190 * @prof_id: unique ID to identify this flow profile
2191 * @segs: array of one or more packet segments that describe the flow
2192 * @segs_cnt: number of packet segments provided
2193 * @acts: array of default actions
2194 * @acts_cnt: number of default actions
2195 * @prof: stores the returned flow profile added
2198 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
2199 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
2200 struct ice_flow_action *acts, u8 acts_cnt,
2201 struct ice_flow_prof **prof)
2203 enum ice_status status;
2205 if (segs_cnt > ICE_FLOW_SEG_MAX)
2206 return ICE_ERR_MAX_LIMIT;
2209 return ICE_ERR_PARAM;
2212 return ICE_ERR_BAD_PTR;
2214 status = ice_flow_val_hdrs(segs, segs_cnt);
2218 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2220 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
2221 acts, acts_cnt, prof);
2223 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
2225 ice_release_lock(&hw->fl_profs_locks[blk]);
2231 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
2232 * @hw: pointer to the HW struct
2233 * @blk: the block for which the flow profile is to be removed
2234 * @prof_id: unique ID of the flow profile to be removed
2237 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
2239 struct ice_flow_prof *prof;
2240 enum ice_status status;
2242 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2244 prof = ice_flow_find_prof_id(hw, blk, prof_id);
2246 status = ICE_ERR_DOES_NOT_EXIST;
2250 /* prof becomes invalid after the call */
2251 status = ice_flow_rem_prof_sync(hw, blk, prof);
2254 ice_release_lock(&hw->fl_profs_locks[blk]);
2260 * ice_flow_find_entry - look for a flow entry using its unique ID
2261 * @hw: pointer to the HW struct
2262 * @blk: classification stage
2263 * @entry_id: unique ID to identify this flow entry
2265 * This function looks for the flow entry with the specified unique ID in all
2266 * flow profiles of the specified classification stage. If the entry is found,
2267 * and it returns the handle to the flow entry. Otherwise, it returns
2268 * ICE_FLOW_ENTRY_ID_INVAL.
2270 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
2272 struct ice_flow_entry *found = NULL;
2273 struct ice_flow_prof *p;
2275 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2277 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
2278 struct ice_flow_entry *e;
2280 ice_acquire_lock(&p->entries_lock);
2281 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
2282 if (e->id == entry_id) {
2286 ice_release_lock(&p->entries_lock);
2292 ice_release_lock(&hw->fl_profs_locks[blk]);
2294 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
2298 * ice_flow_acl_check_actions - Checks the ACL rule's actions
2299 * @hw: pointer to the hardware structure
2300 * @acts: array of actions to be performed on a match
2301 * @acts_cnt: number of actions
2302 * @cnt_alloc: indicates if an ACL counter has been allocated.
2304 static enum ice_status
2305 ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts,
2306 u8 acts_cnt, bool *cnt_alloc)
2308 ice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2311 ice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2314 if (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT)
2315 return ICE_ERR_OUT_OF_RANGE;
2317 for (i = 0; i < acts_cnt; i++) {
2318 if (acts[i].type != ICE_FLOW_ACT_NOP &&
2319 acts[i].type != ICE_FLOW_ACT_DROP &&
2320 acts[i].type != ICE_FLOW_ACT_CNTR_PKT &&
2321 acts[i].type != ICE_FLOW_ACT_FWD_QUEUE)
2324 /* If the caller want to add two actions of the same type, then
2325 * it is considered invalid configuration.
2327 if (ice_test_and_set_bit(acts[i].type, dup_check))
2328 return ICE_ERR_PARAM;
2331 /* Checks if ACL counters are needed. */
2332 for (i = 0; i < acts_cnt; i++) {
2333 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
2334 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
2335 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
2336 struct ice_acl_cntrs cntrs;
2337 enum ice_status status;
2340 cntrs.bank = 0; /* Only bank0 for the moment */
2342 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
2343 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
2345 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
2347 status = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL);
2350 /* Counter index within the bank */
2351 acts[i].data.acl_act.value =
2352 CPU_TO_LE16(cntrs.first_cntr);
2361 * ice_flow_acl_frmt_entry_range - Format an ACL range checker for a given field
2362 * @fld: number of the given field
2363 * @info: info about field
2364 * @range_buf: range checker configuration buffer
2365 * @data: pointer to a data buffer containing flow entry's match values/masks
2366 * @range: Input/output param indicating which range checkers are being used
2369 ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info,
2370 struct ice_aqc_acl_profile_ranges *range_buf,
2371 u8 *data, u8 *range)
2375 /* If not specified, default mask is all bits in field */
2376 new_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ?
2377 BIT(ice_flds_info[fld].size) - 1 :
2378 (*(u16 *)(data + info->src.mask))) << info->xtrct.disp;
2380 /* If the mask is 0, then we don't need to worry about this input
2381 * range checker value.
2385 (*(u16 *)(data + info->src.last)) << info->xtrct.disp;
2387 (*(u16 *)(data + info->src.val)) << info->xtrct.disp;
2388 u8 range_idx = info->entry.val;
2390 range_buf->checker_cfg[range_idx].low_boundary =
2391 CPU_TO_BE16(new_low);
2392 range_buf->checker_cfg[range_idx].high_boundary =
2393 CPU_TO_BE16(new_high);
2394 range_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask);
2396 /* Indicate which range checker is being used */
2397 *range |= BIT(range_idx);
2402 * ice_flow_acl_frmt_entry_fld - Partially format ACL entry for a given field
2403 * @fld: number of the given field
2404 * @info: info about the field
2405 * @buf: buffer containing the entry
2406 * @dontcare: buffer containing don't care mask for entry
2407 * @data: pointer to a data buffer containing flow entry's match values/masks
2410 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf,
2411 u8 *dontcare, u8 *data)
2413 u16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0;
2414 bool use_mask = false;
2417 src = info->src.val;
2418 mask = info->src.mask;
2419 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2420 disp = info->xtrct.disp % BITS_PER_BYTE;
2422 if (mask != ICE_FLOW_FLD_OFF_INVAL)
2425 for (k = 0; k < info->entry.last; k++, dst++) {
2426 /* Add overflow bits from previous byte */
2427 buf[dst] = (tmp_s & 0xff00) >> 8;
2429 /* If mask is not valid, tmp_m is always zero, so just setting
2430 * dontcare to 0 (no masked bits). If mask is valid, pulls in
2431 * overflow bits of mask from prev byte
2433 dontcare[dst] = (tmp_m & 0xff00) >> 8;
2435 /* If there is displacement, last byte will only contain
2436 * displaced data, but there is no more data to read from user
2437 * buffer, so skip so as not to potentially read beyond end of
2440 if (!disp || k < info->entry.last - 1) {
2441 /* Store shifted data to use in next byte */
2442 tmp_s = data[src++] << disp;
2444 /* Add current (shifted) byte */
2445 buf[dst] |= tmp_s & 0xff;
2447 /* Handle mask if valid */
2449 tmp_m = (~data[mask++] & 0xff) << disp;
2450 dontcare[dst] |= tmp_m & 0xff;
2455 /* Fill in don't care bits at beginning of field */
2457 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2458 for (k = 0; k < disp; k++)
2459 dontcare[dst] |= BIT(k);
2462 end_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE;
2464 /* Fill in don't care bits at end of field */
2466 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX +
2467 info->entry.last - 1;
2468 for (k = end_disp; k < BITS_PER_BYTE; k++)
2469 dontcare[dst] |= BIT(k);
2474 * ice_flow_acl_frmt_entry - Format ACL entry
2475 * @hw: pointer to the hardware structure
2476 * @prof: pointer to flow profile
2477 * @e: pointer to the flow entry
2478 * @data: pointer to a data buffer containing flow entry's match values/masks
2479 * @acts: array of actions to be performed on a match
2480 * @acts_cnt: number of actions
2482 * Formats the key (and key_inverse) to be matched from the data passed in,
2483 * along with data from the flow profile. This key/key_inverse pair makes up
2484 * the 'entry' for an ACL flow entry.
2486 static enum ice_status
2487 ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
2488 struct ice_flow_entry *e, u8 *data,
2489 struct ice_flow_action *acts, u8 acts_cnt)
2491 u8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk;
2492 struct ice_aqc_acl_profile_ranges *range_buf = NULL;
2493 enum ice_status status;
2498 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2502 /* Format the result action */
2504 status = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc);
2508 status = ICE_ERR_NO_MEMORY;
2510 e->acts = (struct ice_flow_action *)
2511 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
2512 ICE_NONDMA_TO_NONDMA);
2517 e->acts_cnt = acts_cnt;
2519 /* Format the matching data */
2520 buf_sz = prof->cfg.scen->width;
2521 buf = (u8 *)ice_malloc(hw, buf_sz);
2525 dontcare = (u8 *)ice_malloc(hw, buf_sz);
2529 /* 'key' buffer will store both key and key_inverse, so must be twice
2532 key = (u8 *)ice_malloc(hw, buf_sz * 2);
2536 range_buf = (struct ice_aqc_acl_profile_ranges *)
2537 ice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges));
2541 /* Set don't care mask to all 1's to start, will zero out used bytes */
2542 ice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM);
2544 for (i = 0; i < prof->segs_cnt; i++) {
2545 struct ice_flow_seg_info *seg = &prof->segs[i];
2548 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2549 ICE_FLOW_FIELD_IDX_MAX) {
2550 struct ice_flow_fld_info *info = &seg->fields[j];
2552 if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2553 ice_flow_acl_frmt_entry_range(j, info,
2557 ice_flow_acl_frmt_entry_fld(j, info, buf,
2561 for (j = 0; j < seg->raws_cnt; j++) {
2562 struct ice_flow_fld_info *info = &seg->raws[j].info;
2563 u16 dst, src, mask, k;
2564 bool use_mask = false;
2566 src = info->src.val;
2567 dst = info->entry.val -
2568 ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2569 mask = info->src.mask;
2571 if (mask != ICE_FLOW_FLD_OFF_INVAL)
2574 for (k = 0; k < info->entry.last; k++, dst++) {
2575 buf[dst] = data[src++];
2577 dontcare[dst] = ~data[mask++];
2584 buf[prof->cfg.scen->pid_idx] = (u8)prof_id;
2585 dontcare[prof->cfg.scen->pid_idx] = 0;
2587 /* Format the buffer for direction flags */
2588 dir_flag_msk = BIT(ICE_FLG_PKT_DIR);
2590 if (prof->dir == ICE_FLOW_RX)
2591 buf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk;
2594 buf[prof->cfg.scen->rng_chk_idx] = range;
2595 /* Mark any unused range checkers as don't care */
2596 dontcare[prof->cfg.scen->rng_chk_idx] = ~range;
2597 e->range_buf = range_buf;
2599 ice_free(hw, range_buf);
2602 status = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0,
2608 e->entry_sz = buf_sz * 2;
2615 ice_free(hw, dontcare);
2620 if (status && range_buf) {
2621 ice_free(hw, range_buf);
2622 e->range_buf = NULL;
2625 if (status && e->acts) {
2626 ice_free(hw, e->acts);
2631 if (status && cnt_alloc)
2632 ice_flow_acl_free_act_cntr(hw, acts, acts_cnt);
2638 * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches
2639 * the compared data.
2640 * @prof: pointer to flow profile
2641 * @e: pointer to the comparing flow entry
2642 * @do_chg_action: decide if we want to change the ACL action
2643 * @do_add_entry: decide if we want to add the new ACL entry
2644 * @do_rem_entry: decide if we want to remove the current ACL entry
2646 * Find an ACL scenario entry that matches the compared data. In the same time,
2647 * this function also figure out:
2648 * a/ If we want to change the ACL action
2649 * b/ If we want to add the new ACL entry
2650 * c/ If we want to remove the current ACL entry
2652 static struct ice_flow_entry *
2653 ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof,
2654 struct ice_flow_entry *e, bool *do_chg_action,
2655 bool *do_add_entry, bool *do_rem_entry)
2657 struct ice_flow_entry *p, *return_entry = NULL;
2661 * a/ There exists an entry with same matching data, but different
2662 * priority, then we remove this existing ACL entry. Then, we
2663 * will add the new entry to the ACL scenario.
2664 * b/ There exists an entry with same matching data, priority, and
2665 * result action, then we do nothing
2666 * c/ There exists an entry with same matching data, priority, but
2667 * different, action, then do only change the action's entry.
2668 * d/ Else, we add this new entry to the ACL scenario.
2670 *do_chg_action = false;
2671 *do_add_entry = true;
2672 *do_rem_entry = false;
2673 LIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) {
2674 if (memcmp(p->entry, e->entry, p->entry_sz))
2677 /* From this point, we have the same matching_data. */
2678 *do_add_entry = false;
2681 if (p->priority != e->priority) {
2682 /* matching data && !priority */
2683 *do_add_entry = true;
2684 *do_rem_entry = true;
2688 /* From this point, we will have matching_data && priority */
2689 if (p->acts_cnt != e->acts_cnt)
2690 *do_chg_action = true;
2691 for (i = 0; i < p->acts_cnt; i++) {
2692 bool found_not_match = false;
2694 for (j = 0; j < e->acts_cnt; j++)
2695 if (memcmp(&p->acts[i], &e->acts[j],
2696 sizeof(struct ice_flow_action))) {
2697 found_not_match = true;
2701 if (found_not_match) {
2702 *do_chg_action = true;
2707 /* (do_chg_action = true) means :
2708 * matching_data && priority && !result_action
2709 * (do_chg_action = false) means :
2710 * matching_data && priority && result_action
2715 return return_entry;
2719 * ice_flow_acl_convert_to_acl_prior - Convert to ACL priority
2722 static enum ice_acl_entry_prior
2723 ice_flow_acl_convert_to_acl_prior(enum ice_flow_priority p)
2725 enum ice_acl_entry_prior acl_prior;
2728 case ICE_FLOW_PRIO_LOW:
2729 acl_prior = ICE_LOW;
2731 case ICE_FLOW_PRIO_NORMAL:
2732 acl_prior = ICE_NORMAL;
2734 case ICE_FLOW_PRIO_HIGH:
2735 acl_prior = ICE_HIGH;
2738 acl_prior = ICE_NORMAL;
2746 * ice_flow_acl_union_rng_chk - Perform union operation between two
2747 * range-range checker buffers
2748 * @dst_buf: pointer to destination range checker buffer
2749 * @src_buf: pointer to source range checker buffer
2751 * For this function, we do the union between dst_buf and src_buf
2752 * range checker buffer, and we will save the result back to dst_buf
2754 static enum ice_status
2755 ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf,
2756 struct ice_aqc_acl_profile_ranges *src_buf)
2760 if (!dst_buf || !src_buf)
2761 return ICE_ERR_BAD_PTR;
2763 for (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) {
2764 struct ice_acl_rng_data *cfg_data = NULL, *in_data;
2765 bool will_populate = false;
2767 in_data = &src_buf->checker_cfg[i];
2772 for (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) {
2773 cfg_data = &dst_buf->checker_cfg[j];
2775 if (!cfg_data->mask ||
2776 !memcmp(cfg_data, in_data,
2777 sizeof(struct ice_acl_rng_data))) {
2778 will_populate = true;
2783 if (will_populate) {
2784 ice_memcpy(cfg_data, in_data,
2785 sizeof(struct ice_acl_rng_data),
2786 ICE_NONDMA_TO_NONDMA);
2788 /* No available slot left to program range checker */
2789 return ICE_ERR_MAX_LIMIT;
2797 * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync
2798 * @hw: pointer to the hardware structure
2799 * @prof: pointer to flow profile
2800 * @entry: double pointer to the flow entry
2802 * For this function, we will look at the current added entries in the
2803 * corresponding ACL scenario. Then, we will perform matching logic to
2804 * see if we want to add/modify/do nothing with this new entry.
2806 static enum ice_status
2807 ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof,
2808 struct ice_flow_entry **entry)
2810 bool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk;
2811 struct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf;
2812 struct ice_acl_act_entry *acts = NULL;
2813 struct ice_flow_entry *exist;
2814 enum ice_status status = ICE_SUCCESS;
2815 struct ice_flow_entry *e;
2818 if (!entry || !(*entry) || !prof)
2819 return ICE_ERR_BAD_PTR;
2823 do_chg_rng_chk = false;
2827 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id,
2832 /* Query the current range-checker value in FW */
2833 status = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf,
2837 ice_memcpy(&cfg_rng_buf, &query_rng_buf,
2838 sizeof(struct ice_aqc_acl_profile_ranges),
2839 ICE_NONDMA_TO_NONDMA);
2841 /* Generate the new range-checker value */
2842 status = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf);
2846 /* Reconfigure the range check if the buffer is changed. */
2847 do_chg_rng_chk = false;
2848 if (memcmp(&query_rng_buf, &cfg_rng_buf,
2849 sizeof(struct ice_aqc_acl_profile_ranges))) {
2850 status = ice_prog_acl_prof_ranges(hw, prof_id,
2851 &cfg_rng_buf, NULL);
2855 do_chg_rng_chk = true;
2859 /* Figure out if we want to (change the ACL action) and/or
2860 * (Add the new ACL entry) and/or (Remove the current ACL entry)
2862 exist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action,
2863 &do_add_entry, &do_rem_entry);
2865 status = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist);
2870 /* Prepare the result action buffer */
2871 acts = (struct ice_acl_act_entry *)
2872 ice_calloc(hw, e->entry_sz, sizeof(struct ice_acl_act_entry));
2874 return ICE_ERR_NO_MEMORY;
2876 for (i = 0; i < e->acts_cnt; i++)
2877 ice_memcpy(&acts[i], &e->acts[i].data.acl_act,
2878 sizeof(struct ice_acl_act_entry),
2879 ICE_NONDMA_TO_NONDMA);
2882 enum ice_acl_entry_prior prior;
2886 keys = (u8 *)e->entry;
2887 inverts = keys + (e->entry_sz / 2);
2888 prior = ice_flow_acl_convert_to_acl_prior(e->priority);
2890 status = ice_acl_add_entry(hw, prof->cfg.scen, prior, keys,
2891 inverts, acts, e->acts_cnt,
2896 e->scen_entry_idx = entry_idx;
2897 LIST_ADD(&e->l_entry, &prof->entries);
2899 if (do_chg_action) {
2900 /* For the action memory info, update the SW's copy of
2901 * exist entry with e's action memory info
2903 ice_free(hw, exist->acts);
2904 exist->acts_cnt = e->acts_cnt;
2905 exist->acts = (struct ice_flow_action *)
2906 ice_calloc(hw, exist->acts_cnt,
2907 sizeof(struct ice_flow_action));
2910 status = ICE_ERR_NO_MEMORY;
2914 ice_memcpy(exist->acts, e->acts,
2915 sizeof(struct ice_flow_action) * e->acts_cnt,
2916 ICE_NONDMA_TO_NONDMA);
2918 status = ice_acl_prog_act(hw, prof->cfg.scen, acts,
2920 exist->scen_entry_idx);
2925 if (do_chg_rng_chk) {
2926 /* In this case, we want to update the range checker
2927 * information of the exist entry
2929 status = ice_flow_acl_union_rng_chk(exist->range_buf,
2935 /* As we don't add the new entry to our SW DB, deallocate its
2936 * memories, and return the exist entry to the caller
2938 ice_dealloc_flow_entry(hw, e);
2948 * ice_flow_acl_add_scen_entry - Add entry to ACL scenario
2949 * @hw: pointer to the hardware structure
2950 * @prof: pointer to flow profile
2951 * @e: double pointer to the flow entry
2953 static enum ice_status
2954 ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
2955 struct ice_flow_entry **e)
2957 enum ice_status status;
2959 ice_acquire_lock(&prof->entries_lock);
2960 status = ice_flow_acl_add_scen_entry_sync(hw, prof, e);
2961 ice_release_lock(&prof->entries_lock);
2967 * ice_flow_add_entry - Add a flow entry
2968 * @hw: pointer to the HW struct
2969 * @blk: classification stage
2970 * @prof_id: ID of the profile to add a new flow entry to
2971 * @entry_id: unique ID to identify this flow entry
2972 * @vsi_handle: software VSI handle for the flow entry
2973 * @prio: priority of the flow entry
2974 * @data: pointer to a data buffer containing flow entry's match values/masks
2975 * @acts: arrays of actions to be performed on a match
2976 * @acts_cnt: number of actions
2977 * @entry_h: pointer to buffer that receives the new flow entry's handle
2980 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
2981 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
2982 void *data, struct ice_flow_action *acts, u8 acts_cnt,
2985 struct ice_flow_entry *e = NULL;
2986 struct ice_flow_prof *prof;
2987 enum ice_status status = ICE_SUCCESS;
2989 /* ACL entries must indicate an action */
2990 if (blk == ICE_BLK_ACL && (!acts || !acts_cnt))
2991 return ICE_ERR_PARAM;
2993 /* No flow entry data is expected for RSS */
2994 if (!entry_h || (!data && blk != ICE_BLK_RSS))
2995 return ICE_ERR_BAD_PTR;
2997 if (!ice_is_vsi_valid(hw, vsi_handle))
2998 return ICE_ERR_PARAM;
3000 ice_acquire_lock(&hw->fl_profs_locks[blk]);
3002 prof = ice_flow_find_prof_id(hw, blk, prof_id);
3004 status = ICE_ERR_DOES_NOT_EXIST;
3006 /* Allocate memory for the entry being added and associate
3007 * the VSI to the found flow profile
3009 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
3011 status = ICE_ERR_NO_MEMORY;
3013 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3016 ice_release_lock(&hw->fl_profs_locks[blk]);
3021 e->vsi_handle = vsi_handle;
3030 /* ACL will handle the entry management */
3031 status = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts,
3036 status = ice_flow_acl_add_scen_entry(hw, prof, &e);
3042 status = ICE_ERR_NOT_IMPL;
3046 if (blk != ICE_BLK_ACL) {
3047 /* ACL will handle the entry management */
3048 ice_acquire_lock(&prof->entries_lock);
3049 LIST_ADD(&e->l_entry, &prof->entries);
3050 ice_release_lock(&prof->entries_lock);
3053 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
3058 ice_free(hw, e->entry);
3066 * ice_flow_rem_entry - Remove a flow entry
3067 * @hw: pointer to the HW struct
3068 * @blk: classification stage
3069 * @entry_h: handle to the flow entry to be removed
3071 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
3074 struct ice_flow_entry *entry;
3075 struct ice_flow_prof *prof;
3076 enum ice_status status = ICE_SUCCESS;
3078 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
3079 return ICE_ERR_PARAM;
3081 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
3083 /* Retain the pointer to the flow profile as the entry will be freed */
3087 ice_acquire_lock(&prof->entries_lock);
3088 status = ice_flow_rem_entry_sync(hw, blk, entry);
3089 ice_release_lock(&prof->entries_lock);
3096 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
3097 * @seg: packet segment the field being set belongs to
3098 * @fld: field to be set
3099 * @field_type: type of the field
3100 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3101 * entry's input buffer
3102 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3104 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3105 * entry's input buffer
3107 * This helper function stores information of a field being matched, including
3108 * the type of the field and the locations of the value to match, the mask, and
3109 * and the upper-bound value in the start of the input buffer for a flow entry.
3110 * This function should only be used for fixed-size data structures.
3112 * This function also opportunistically determines the protocol headers to be
3113 * present based on the fields being set. Some fields cannot be used alone to
3114 * determine the protocol headers present. Sometimes, fields for particular
3115 * protocol headers are not matched. In those cases, the protocol headers
3116 * must be explicitly set.
3119 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3120 enum ice_flow_fld_match_type field_type, u16 val_loc,
3121 u16 mask_loc, u16 last_loc)
3123 u64 bit = BIT_ULL(fld);
3126 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
3129 seg->fields[fld].type = field_type;
3130 seg->fields[fld].src.val = val_loc;
3131 seg->fields[fld].src.mask = mask_loc;
3132 seg->fields[fld].src.last = last_loc;
3134 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
3138 * ice_flow_set_fld - specifies locations of field from entry's input buffer
3139 * @seg: packet segment the field being set belongs to
3140 * @fld: field to be set
3141 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3142 * entry's input buffer
3143 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3145 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3146 * entry's input buffer
3147 * @range: indicate if field being matched is to be in a range
3149 * This function specifies the locations, in the form of byte offsets from the
3150 * start of the input buffer for a flow entry, from where the value to match,
3151 * the mask value, and upper value can be extracted. These locations are then
3152 * stored in the flow profile. When adding a flow entry associated with the
3153 * flow profile, these locations will be used to quickly extract the values and
3154 * create the content of a match entry. This function should only be used for
3155 * fixed-size data structures.
3158 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3159 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
3161 enum ice_flow_fld_match_type t = range ?
3162 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
3164 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
3168 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
3169 * @seg: packet segment the field being set belongs to
3170 * @fld: field to be set
3171 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3172 * entry's input buffer
3173 * @pref_loc: location of prefix value from entry's input buffer
3174 * @pref_sz: size of the location holding the prefix value
3176 * This function specifies the locations, in the form of byte offsets from the
3177 * start of the input buffer for a flow entry, from where the value to match
3178 * and the IPv4 prefix value can be extracted. These locations are then stored
3179 * in the flow profile. When adding flow entries to the associated flow profile,
3180 * these locations can be used to quickly extract the values to create the
3181 * content of a match entry. This function should only be used for fixed-size
3185 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3186 u16 val_loc, u16 pref_loc, u8 pref_sz)
3188 /* For this type of field, the "mask" location is for the prefix value's
3189 * location and the "last" location is for the size of the location of
3192 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
3193 pref_loc, (u16)pref_sz);
3197 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
3198 * @seg: packet segment the field being set belongs to
3199 * @off: offset of the raw field from the beginning of the segment in bytes
3200 * @len: length of the raw pattern to be matched
3201 * @val_loc: location of the value to match from entry's input buffer
3202 * @mask_loc: location of mask value from entry's input buffer
3204 * This function specifies the offset of the raw field to be match from the
3205 * beginning of the specified packet segment, and the locations, in the form of
3206 * byte offsets from the start of the input buffer for a flow entry, from where
3207 * the value to match and the mask value to be extracted. These locations are
3208 * then stored in the flow profile. When adding flow entries to the associated
3209 * flow profile, these locations can be used to quickly extract the values to
3210 * create the content of a match entry. This function should only be used for
3211 * fixed-size data structures.
3214 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
3215 u16 val_loc, u16 mask_loc)
3217 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
3218 seg->raws[seg->raws_cnt].off = off;
3219 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
3220 seg->raws[seg->raws_cnt].info.src.val = val_loc;
3221 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
3222 /* The "last" field is used to store the length of the field */
3223 seg->raws[seg->raws_cnt].info.src.last = len;
3226 /* Overflows of "raws" will be handled as an error condition later in
3227 * the flow when this information is processed.
3232 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
3233 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
3235 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
3236 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
3238 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
3239 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
3240 ICE_FLOW_SEG_HDR_SCTP)
3242 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
3243 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
3244 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
3245 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
3248 * ice_flow_set_rss_seg_info - setup packet segments for RSS
3249 * @segs: pointer to the flow field segment(s)
3250 * @hash_fields: fields to be hashed on for the segment(s)
3251 * @flow_hdr: protocol header fields within a packet segment
3253 * Helper function to extract fields from hash bitmap and use flow
3254 * header value to set flow field segment for further use in flow
3255 * profile entry or removal.
3257 static enum ice_status
3258 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
3264 ice_for_each_set_bit(i, (ice_bitmap_t *)&hash_fields,
3265 ICE_FLOW_FIELD_IDX_MAX)
3266 ice_flow_set_fld(segs, (enum ice_flow_field)i,
3267 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
3268 ICE_FLOW_FLD_OFF_INVAL, false);
3270 ICE_FLOW_SET_HDRS(segs, flow_hdr);
3272 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
3273 ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
3274 return ICE_ERR_PARAM;
3276 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
3277 if (val && !ice_is_pow2(val))
3280 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
3281 if (val && !ice_is_pow2(val))
3288 * ice_rem_vsi_rss_list - remove VSI from RSS list
3289 * @hw: pointer to the hardware structure
3290 * @vsi_handle: software VSI handle
3292 * Remove the VSI from all RSS configurations in the list.
3294 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
3296 struct ice_rss_cfg *r, *tmp;
3298 if (LIST_EMPTY(&hw->rss_list_head))
3301 ice_acquire_lock(&hw->rss_locks);
3302 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3303 ice_rss_cfg, l_entry)
3304 if (ice_test_and_clear_bit(vsi_handle, r->vsis))
3305 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3306 LIST_DEL(&r->l_entry);
3309 ice_release_lock(&hw->rss_locks);
3313 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
3314 * @hw: pointer to the hardware structure
3315 * @vsi_handle: software VSI handle
3317 * This function will iterate through all flow profiles and disassociate
3318 * the VSI from that profile. If the flow profile has no VSIs it will
3321 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3323 const enum ice_block blk = ICE_BLK_RSS;
3324 struct ice_flow_prof *p, *t;
3325 enum ice_status status = ICE_SUCCESS;
3327 if (!ice_is_vsi_valid(hw, vsi_handle))
3328 return ICE_ERR_PARAM;
3330 if (LIST_EMPTY(&hw->fl_profs[blk]))
3333 ice_acquire_lock(&hw->rss_locks);
3334 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
3336 if (ice_is_bit_set(p->vsis, vsi_handle)) {
3337 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
3341 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
3342 status = ice_flow_rem_prof(hw, blk, p->id);
3347 ice_release_lock(&hw->rss_locks);
3353 * ice_rem_rss_list - remove RSS configuration from list
3354 * @hw: pointer to the hardware structure
3355 * @vsi_handle: software VSI handle
3356 * @prof: pointer to flow profile
3358 * Assumption: lock has already been acquired for RSS list
3361 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3363 struct ice_rss_cfg *r, *tmp;
3365 /* Search for RSS hash fields associated to the VSI that match the
3366 * hash configurations associated to the flow profile. If found
3367 * remove from the RSS entry list of the VSI context and delete entry.
3369 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3370 ice_rss_cfg, l_entry)
3371 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
3372 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
3373 ice_clear_bit(vsi_handle, r->vsis);
3374 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3375 LIST_DEL(&r->l_entry);
3383 * ice_add_rss_list - add RSS configuration to list
3384 * @hw: pointer to the hardware structure
3385 * @vsi_handle: software VSI handle
3386 * @prof: pointer to flow profile
3388 * Assumption: lock has already been acquired for RSS list
3390 static enum ice_status
3391 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3393 struct ice_rss_cfg *r, *rss_cfg;
3395 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3396 ice_rss_cfg, l_entry)
3397 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
3398 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
3399 ice_set_bit(vsi_handle, r->vsis);
3403 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
3405 return ICE_ERR_NO_MEMORY;
3407 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
3408 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
3409 rss_cfg->symm = prof->cfg.symm;
3410 ice_set_bit(vsi_handle, rss_cfg->vsis);
3412 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
3417 #define ICE_FLOW_PROF_HASH_S 0
3418 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
3419 #define ICE_FLOW_PROF_HDR_S 32
3420 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
3421 #define ICE_FLOW_PROF_ENCAP_S 63
3422 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
3424 #define ICE_RSS_OUTER_HEADERS 1
3425 #define ICE_RSS_INNER_HEADERS 2
3427 /* Flow profile ID format:
3428 * [0:31] - Packet match fields
3429 * [32:62] - Protocol header
3430 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
3432 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
3433 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
3434 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
3435 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
3438 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
3440 u32 s = ((src % 4) << 3); /* byte shift */
3441 u32 v = dst | 0x80; /* value to program */
3442 u8 i = src / 4; /* register index */
3445 reg = rd32(hw, GLQF_HSYMM(prof_id, i));
3446 reg = (reg & ~(0xff << s)) | (v << s);
3447 wr32(hw, GLQF_HSYMM(prof_id, i), reg);
3451 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
3454 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
3457 for (i = 0; i < len; i++) {
3458 ice_rss_config_xor_word(hw, prof_id,
3459 /* Yes, field vector in GLQF_HSYMM and
3460 * GLQF_HINSET is inversed!
3462 fv_last_word - (src + i),
3463 fv_last_word - (dst + i));
3464 ice_rss_config_xor_word(hw, prof_id,
3465 fv_last_word - (dst + i),
3466 fv_last_word - (src + i));
3471 ice_rss_update_symm(struct ice_hw *hw,
3472 struct ice_flow_prof *prof)
3474 struct ice_prof_map *map;
3477 ice_acquire_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3478 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
3480 prof_id = map->prof_id;
3481 ice_release_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3484 /* clear to default */
3485 for (m = 0; m < 6; m++)
3486 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
3487 if (prof->cfg.symm) {
3488 struct ice_flow_seg_info *seg =
3489 &prof->segs[prof->segs_cnt - 1];
3491 struct ice_flow_seg_xtrct *ipv4_src =
3492 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
3493 struct ice_flow_seg_xtrct *ipv4_dst =
3494 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
3495 struct ice_flow_seg_xtrct *ipv6_src =
3496 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
3497 struct ice_flow_seg_xtrct *ipv6_dst =
3498 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
3500 struct ice_flow_seg_xtrct *tcp_src =
3501 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
3502 struct ice_flow_seg_xtrct *tcp_dst =
3503 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
3505 struct ice_flow_seg_xtrct *udp_src =
3506 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
3507 struct ice_flow_seg_xtrct *udp_dst =
3508 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
3510 struct ice_flow_seg_xtrct *sctp_src =
3511 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
3512 struct ice_flow_seg_xtrct *sctp_dst =
3513 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
3516 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
3517 ice_rss_config_xor(hw, prof_id,
3518 ipv4_src->idx, ipv4_dst->idx, 2);
3521 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
3522 ice_rss_config_xor(hw, prof_id,
3523 ipv6_src->idx, ipv6_dst->idx, 8);
3526 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
3527 ice_rss_config_xor(hw, prof_id,
3528 tcp_src->idx, tcp_dst->idx, 1);
3531 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
3532 ice_rss_config_xor(hw, prof_id,
3533 udp_src->idx, udp_dst->idx, 1);
3536 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
3537 ice_rss_config_xor(hw, prof_id,
3538 sctp_src->idx, sctp_dst->idx, 1);
3543 * ice_add_rss_cfg_sync - add an RSS configuration
3544 * @hw: pointer to the hardware structure
3545 * @vsi_handle: software VSI handle
3546 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
3547 * @addl_hdrs: protocol header fields
3548 * @segs_cnt: packet segment count
3549 * @symm: symmetric hash enable/disable
3551 * Assumption: lock has already been acquired for RSS list
3553 static enum ice_status
3554 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
3555 u32 addl_hdrs, u8 segs_cnt, bool symm)
3557 const enum ice_block blk = ICE_BLK_RSS;
3558 struct ice_flow_prof *prof = NULL;
3559 struct ice_flow_seg_info *segs;
3560 enum ice_status status;
3562 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
3563 return ICE_ERR_PARAM;
3565 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3568 return ICE_ERR_NO_MEMORY;
3570 /* Construct the packet segment info from the hashed fields */
3571 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
3576 /* don't do RSS for GTPU outer */
3577 if (segs_cnt == ICE_RSS_OUTER_HEADERS &&
3578 segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3579 status = ICE_SUCCESS;
3583 /* Search for a flow profile that has matching headers, hash fields
3584 * and has the input VSI associated to it. If found, no further
3585 * operations required and exit.
3587 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3589 ICE_FLOW_FIND_PROF_CHK_FLDS |
3590 ICE_FLOW_FIND_PROF_CHK_VSI);
3592 if (prof->cfg.symm == symm)
3594 prof->cfg.symm = symm;
3598 /* Check if a flow profile exists with the same protocol headers and
3599 * associated with the input VSI. If so disassociate the VSI from
3600 * this profile. The VSI will be added to a new profile created with
3601 * the protocol header and new hash field configuration.
3603 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3604 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
3606 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3608 ice_rem_rss_list(hw, vsi_handle, prof);
3612 /* Remove profile if it has no VSIs associated */
3613 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
3614 status = ice_flow_rem_prof(hw, blk, prof->id);
3620 /* Search for a profile that has same match fields only. If this
3621 * exists then associate the VSI to this profile.
3623 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3625 ICE_FLOW_FIND_PROF_CHK_FLDS);
3627 if (prof->cfg.symm == symm) {
3628 status = ice_flow_assoc_prof(hw, blk, prof,
3631 status = ice_add_rss_list(hw, vsi_handle,
3634 /* if a profile exist but with different symmetric
3635 * requirement, just return error.
3637 status = ICE_ERR_NOT_SUPPORTED;
3642 /* Create a new flow profile with generated profile and packet
3643 * segment information.
3645 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
3646 ICE_FLOW_GEN_PROFID(hashed_flds,
3647 segs[segs_cnt - 1].hdrs,
3649 segs, segs_cnt, NULL, 0, &prof);
3653 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3654 /* If association to a new flow profile failed then this profile can
3658 ice_flow_rem_prof(hw, blk, prof->id);
3662 status = ice_add_rss_list(hw, vsi_handle, prof);
3664 prof->cfg.symm = symm;
3667 ice_rss_update_symm(hw, prof);
3675 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
3676 * @hw: pointer to the hardware structure
3677 * @vsi_handle: software VSI handle
3678 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
3679 * @addl_hdrs: protocol header fields
3680 * @symm: symmetric hash enable/disable
3682 * This function will generate a flow profile based on fields associated with
3683 * the input fields to hash on, the flow type and use the VSI number to add
3684 * a flow entry to the profile.
3687 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
3688 u32 addl_hdrs, bool symm)
3690 enum ice_status status;
3692 if (hashed_flds == ICE_HASH_INVALID ||
3693 !ice_is_vsi_valid(hw, vsi_handle))
3694 return ICE_ERR_PARAM;
3696 ice_acquire_lock(&hw->rss_locks);
3697 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
3698 ICE_RSS_OUTER_HEADERS, symm);
3701 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
3702 addl_hdrs, ICE_RSS_INNER_HEADERS,
3704 ice_release_lock(&hw->rss_locks);
3710 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
3711 * @hw: pointer to the hardware structure
3712 * @vsi_handle: software VSI handle
3713 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
3714 * @addl_hdrs: Protocol header fields within a packet segment
3715 * @segs_cnt: packet segment count
3717 * Assumption: lock has already been acquired for RSS list
3719 static enum ice_status
3720 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
3721 u32 addl_hdrs, u8 segs_cnt)
3723 const enum ice_block blk = ICE_BLK_RSS;
3724 struct ice_flow_seg_info *segs;
3725 struct ice_flow_prof *prof;
3726 enum ice_status status;
3728 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3731 return ICE_ERR_NO_MEMORY;
3733 /* Construct the packet segment info from the hashed fields */
3734 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
3739 if (segs_cnt == ICE_RSS_OUTER_HEADERS &&
3740 segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3741 status = ICE_SUCCESS;
3745 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3747 ICE_FLOW_FIND_PROF_CHK_FLDS);
3749 status = ICE_ERR_DOES_NOT_EXIST;
3753 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3757 /* Remove RSS configuration from VSI context before deleting
3760 ice_rem_rss_list(hw, vsi_handle, prof);
3762 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
3763 status = ice_flow_rem_prof(hw, blk, prof->id);
3771 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
3772 * @hw: pointer to the hardware structure
3773 * @vsi_handle: software VSI handle
3774 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
3775 * @addl_hdrs: Protocol header fields within a packet segment
3777 * This function will lookup the flow profile based on the input
3778 * hash field bitmap, iterate through the profile entry list of
3779 * that profile and find entry associated with input VSI to be
3780 * removed. Calls are made to underlying flow apis which will in
3781 * turn build or update buffers for RSS XLT1 section.
3784 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
3787 enum ice_status status;
3789 if (hashed_flds == ICE_HASH_INVALID ||
3790 !ice_is_vsi_valid(hw, vsi_handle))
3791 return ICE_ERR_PARAM;
3793 ice_acquire_lock(&hw->rss_locks);
3794 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
3795 ICE_RSS_OUTER_HEADERS);
3797 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
3798 addl_hdrs, ICE_RSS_INNER_HEADERS);
3799 ice_release_lock(&hw->rss_locks);
3805 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
3806 * @hw: pointer to the hardware structure
3807 * @vsi_handle: software VSI handle
3809 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3811 enum ice_status status = ICE_SUCCESS;
3812 struct ice_rss_cfg *r;
3814 if (!ice_is_vsi_valid(hw, vsi_handle))
3815 return ICE_ERR_PARAM;
3817 ice_acquire_lock(&hw->rss_locks);
3818 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3819 ice_rss_cfg, l_entry) {
3820 if (ice_is_bit_set(r->vsis, vsi_handle)) {
3821 status = ice_add_rss_cfg_sync(hw, vsi_handle,
3824 ICE_RSS_OUTER_HEADERS,
3828 status = ice_add_rss_cfg_sync(hw, vsi_handle,
3831 ICE_RSS_INNER_HEADERS,
3837 ice_release_lock(&hw->rss_locks);
3843 * ice_get_rss_cfg - returns hashed fields for the given header types
3844 * @hw: pointer to the hardware structure
3845 * @vsi_handle: software VSI handle
3846 * @hdrs: protocol header type
3848 * This function will return the match fields of the first instance of flow
3849 * profile having the given header types and containing input VSI
3851 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
3853 u64 rss_hash = ICE_HASH_INVALID;
3854 struct ice_rss_cfg *r;
3856 /* verify if the protocol header is non zero and VSI is valid */
3857 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
3858 return ICE_HASH_INVALID;
3860 ice_acquire_lock(&hw->rss_locks);
3861 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3862 ice_rss_cfg, l_entry)
3863 if (ice_is_bit_set(r->vsis, vsi_handle) &&
3864 r->packet_hdr == hdrs) {
3865 rss_hash = r->hashed_flds;
3868 ice_release_lock(&hw->rss_locks);