1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2021 Intel Corporation
5 #include "ice_switch.h"
6 #include "ice_flex_type.h"
9 #define ICE_ETH_DA_OFFSET 0
10 #define ICE_ETH_ETHTYPE_OFFSET 12
11 #define ICE_ETH_VLAN_TCI_OFFSET 14
12 #define ICE_MAX_VLAN_ID 0xFFF
13 #define ICE_IPV4_NVGRE_PROTO_ID 0x002F
14 #define ICE_PPP_IPV6_PROTO_ID 0x0057
15 #define ICE_IPV6_ETHER_ID 0x86DD
16 #define ICE_TCP_PROTO_ID 0x06
17 #define ICE_ETH_P_8021Q 0x8100
19 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
20 * struct to configure any switch filter rules.
21 * {DA (6 bytes), SA(6 bytes),
22 * Ether type (2 bytes for header without VLAN tag) OR
23 * VLAN tag (4 bytes for header with VLAN tag) }
25 * Word on Hardcoded values
26 * byte 0 = 0x2: to identify it as locally administered DA MAC
27 * byte 6 = 0x2: to identify it as locally administered SA MAC
28 * byte 12 = 0x81 & byte 13 = 0x00:
29 * In case of VLAN filter first two bytes defines ether type (0x8100)
30 * and remaining two bytes are placeholder for programming a given VLAN ID
31 * In case of Ether type filter it is treated as header without VLAN tag
32 * and byte 12 and 13 is used to program a given Ether type instead
34 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
38 struct ice_dummy_pkt_offsets {
39 enum ice_protocol_type type;
40 u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */
43 static const struct ice_dummy_pkt_offsets dummy_gre_tcp_packet_offsets[] = {
46 { ICE_IPV4_OFOS, 14 },
51 { ICE_PROTOCOL_LAST, 0 },
54 static const u8 dummy_gre_tcp_packet[] = {
55 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
56 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00,
59 0x08, 0x00, /* ICE_ETYPE_OL 12 */
61 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */
62 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x2F, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00,
67 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
68 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
71 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00,
75 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */
76 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x06, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 76 */
82 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00,
84 0x50, 0x02, 0x20, 0x00,
85 0x00, 0x00, 0x00, 0x00
88 static const struct ice_dummy_pkt_offsets dummy_gre_udp_packet_offsets[] = {
91 { ICE_IPV4_OFOS, 14 },
96 { ICE_PROTOCOL_LAST, 0 },
99 static const u8 dummy_gre_udp_packet[] = {
100 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
101 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00,
104 0x08, 0x00, /* ICE_ETYPE_OL 12 */
106 0x45, 0x00, 0x00, 0x3E, /* ICE_IPV4_OFOS 14 */
107 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x2F, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00,
112 0x80, 0x00, 0x65, 0x58, /* ICE_NVGRE 34 */
113 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 42 */
116 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00,
120 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 56 */
121 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x11, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 76 */
127 0x00, 0x08, 0x00, 0x00,
130 static const struct ice_dummy_pkt_offsets dummy_udp_tun_tcp_packet_offsets[] = {
132 { ICE_ETYPE_OL, 12 },
133 { ICE_IPV4_OFOS, 14 },
137 { ICE_VXLAN_GPE, 42 },
141 { ICE_PROTOCOL_LAST, 0 },
144 static const u8 dummy_udp_tun_tcp_packet[] = {
145 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
146 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00,
149 0x08, 0x00, /* ICE_ETYPE_OL 12 */
151 0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
152 0x00, 0x01, 0x00, 0x00,
153 0x40, 0x11, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
158 0x00, 0x46, 0x00, 0x00,
160 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
161 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
164 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00,
168 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */
169 0x00, 0x01, 0x00, 0x00,
170 0x40, 0x06, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */
175 0x00, 0x00, 0x00, 0x00,
176 0x00, 0x00, 0x00, 0x00,
177 0x50, 0x02, 0x20, 0x00,
178 0x00, 0x00, 0x00, 0x00
181 static const struct ice_dummy_pkt_offsets dummy_udp_tun_udp_packet_offsets[] = {
183 { ICE_ETYPE_OL, 12 },
184 { ICE_IPV4_OFOS, 14 },
188 { ICE_VXLAN_GPE, 42 },
191 { ICE_UDP_ILOS, 84 },
192 { ICE_PROTOCOL_LAST, 0 },
195 static const u8 dummy_udp_tun_udp_packet[] = {
196 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
197 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00,
200 0x08, 0x00, /* ICE_ETYPE_OL 12 */
202 0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */
203 0x00, 0x01, 0x00, 0x00,
204 0x00, 0x11, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
209 0x00, 0x3a, 0x00, 0x00,
211 0x00, 0x00, 0x65, 0x58, /* ICE_VXLAN 42 */
212 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
215 0x00, 0x00, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x00,
219 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */
220 0x00, 0x01, 0x00, 0x00,
221 0x00, 0x11, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */
226 0x00, 0x08, 0x00, 0x00,
229 /* offset info for MAC + IPv4 + UDP dummy packet */
230 static const struct ice_dummy_pkt_offsets dummy_udp_packet_offsets[] = {
232 { ICE_ETYPE_OL, 12 },
233 { ICE_IPV4_OFOS, 14 },
234 { ICE_UDP_ILOS, 34 },
235 { ICE_PROTOCOL_LAST, 0 },
238 /* Dummy packet for MAC + IPv4 + UDP */
239 static const u8 dummy_udp_packet[] = {
240 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
241 0x00, 0x00, 0x00, 0x00,
242 0x00, 0x00, 0x00, 0x00,
244 0x08, 0x00, /* ICE_ETYPE_OL 12 */
246 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */
247 0x00, 0x01, 0x00, 0x00,
248 0x00, 0x11, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */
253 0x00, 0x08, 0x00, 0x00,
255 0x00, 0x00, /* 2 bytes for 4 byte alignment */
258 /* offset info for MAC + VLAN + IPv4 + UDP dummy packet */
259 static const struct ice_dummy_pkt_offsets dummy_vlan_udp_packet_offsets[] = {
261 { ICE_ETYPE_OL, 12 },
262 { ICE_VLAN_OFOS, 14 },
263 { ICE_IPV4_OFOS, 18 },
264 { ICE_UDP_ILOS, 38 },
265 { ICE_PROTOCOL_LAST, 0 },
268 /* C-tag (801.1Q), IPv4:UDP dummy packet */
269 static const u8 dummy_vlan_udp_packet[] = {
270 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
271 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00,
274 0x81, 0x00, /* ICE_ETYPE_OL 12 */
276 0x00, 0x00, 0x08, 0x00, /* ICE_VLAN_OFOS 14 */
278 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 18 */
279 0x00, 0x01, 0x00, 0x00,
280 0x00, 0x11, 0x00, 0x00,
281 0x00, 0x00, 0x00, 0x00,
282 0x00, 0x00, 0x00, 0x00,
284 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 38 */
285 0x00, 0x08, 0x00, 0x00,
287 0x00, 0x00, /* 2 bytes for 4 byte alignment */
290 /* offset info for MAC + IPv4 + TCP dummy packet */
291 static const struct ice_dummy_pkt_offsets dummy_tcp_packet_offsets[] = {
293 { ICE_ETYPE_OL, 12 },
294 { ICE_IPV4_OFOS, 14 },
296 { ICE_PROTOCOL_LAST, 0 },
299 /* Dummy packet for MAC + IPv4 + TCP */
300 static const u8 dummy_tcp_packet[] = {
301 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
302 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00,
305 0x08, 0x00, /* ICE_ETYPE_OL 12 */
307 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */
308 0x00, 0x01, 0x00, 0x00,
309 0x00, 0x06, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */
314 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00,
316 0x50, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, /* 2 bytes for 4 byte alignment */
322 /* offset info for MAC + VLAN (C-tag, 802.1Q) + IPv4 + TCP dummy packet */
323 static const struct ice_dummy_pkt_offsets dummy_vlan_tcp_packet_offsets[] = {
325 { ICE_ETYPE_OL, 12 },
326 { ICE_VLAN_OFOS, 14 },
327 { ICE_IPV4_OFOS, 18 },
329 { ICE_PROTOCOL_LAST, 0 },
332 /* C-tag (801.1Q), IPv4:TCP dummy packet */
333 static const u8 dummy_vlan_tcp_packet[] = {
334 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
335 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00,
338 0x81, 0x00, /* ICE_ETYPE_OL 12 */
340 0x00, 0x00, 0x08, 0x00, /* ICE_VLAN_OFOS 14 */
342 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 18 */
343 0x00, 0x01, 0x00, 0x00,
344 0x00, 0x06, 0x00, 0x00,
345 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00,
348 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 38 */
349 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00,
351 0x50, 0x00, 0x00, 0x00,
352 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, /* 2 bytes for 4 byte alignment */
357 static const struct ice_dummy_pkt_offsets dummy_tcp_ipv6_packet_offsets[] = {
359 { ICE_ETYPE_OL, 12 },
360 { ICE_IPV6_OFOS, 14 },
362 { ICE_PROTOCOL_LAST, 0 },
365 static const u8 dummy_tcp_ipv6_packet[] = {
366 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
367 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00,
370 0x86, 0xDD, /* ICE_ETYPE_OL 12 */
372 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
373 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
374 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */
384 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00,
386 0x50, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, /* 2 bytes for 4 byte alignment */
392 /* C-tag (802.1Q): IPv6 + TCP */
393 static const struct ice_dummy_pkt_offsets
394 dummy_vlan_tcp_ipv6_packet_offsets[] = {
396 { ICE_ETYPE_OL, 12 },
397 { ICE_VLAN_OFOS, 14 },
398 { ICE_IPV6_OFOS, 18 },
400 { ICE_PROTOCOL_LAST, 0 },
403 /* C-tag (802.1Q), IPv6 + TCP dummy packet */
404 static const u8 dummy_vlan_tcp_ipv6_packet[] = {
405 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
406 0x00, 0x00, 0x00, 0x00,
407 0x00, 0x00, 0x00, 0x00,
409 0x81, 0x00, /* ICE_ETYPE_OL 12 */
411 0x00, 0x00, 0x86, 0xDD, /* ICE_VLAN_OFOS 14 */
413 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */
414 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
415 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 58 */
425 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00,
427 0x50, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, /* 2 bytes for 4 byte alignment */
434 static const struct ice_dummy_pkt_offsets dummy_udp_ipv6_packet_offsets[] = {
436 { ICE_ETYPE_OL, 12 },
437 { ICE_IPV6_OFOS, 14 },
438 { ICE_UDP_ILOS, 54 },
439 { ICE_PROTOCOL_LAST, 0 },
442 /* IPv6 + UDP dummy packet */
443 static const u8 dummy_udp_ipv6_packet[] = {
444 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
445 0x00, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00,
448 0x86, 0xDD, /* ICE_ETYPE_OL 12 */
450 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
451 0x00, 0x10, 0x11, 0x00, /* Next header UDP */
452 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00,
454 0x00, 0x00, 0x00, 0x00,
455 0x00, 0x00, 0x00, 0x00,
456 0x00, 0x00, 0x00, 0x00,
457 0x00, 0x00, 0x00, 0x00,
458 0x00, 0x00, 0x00, 0x00,
459 0x00, 0x00, 0x00, 0x00,
461 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */
462 0x00, 0x10, 0x00, 0x00,
464 0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */
465 0x00, 0x00, 0x00, 0x00,
467 0x00, 0x00, /* 2 bytes for 4 byte alignment */
470 /* C-tag (802.1Q): IPv6 + UDP */
471 static const struct ice_dummy_pkt_offsets
472 dummy_vlan_udp_ipv6_packet_offsets[] = {
474 { ICE_ETYPE_OL, 12 },
475 { ICE_VLAN_OFOS, 14 },
476 { ICE_IPV6_OFOS, 18 },
477 { ICE_UDP_ILOS, 58 },
478 { ICE_PROTOCOL_LAST, 0 },
481 /* C-tag (802.1Q), IPv6 + UDP dummy packet */
482 static const u8 dummy_vlan_udp_ipv6_packet[] = {
483 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
484 0x00, 0x00, 0x00, 0x00,
485 0x00, 0x00, 0x00, 0x00,
487 0x81, 0x00, /* ICE_ETYPE_OL 12 */
489 0x00, 0x00, 0x86, 0xDD, /* ICE_VLAN_OFOS 14 */
491 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 18 */
492 0x00, 0x08, 0x11, 0x00, /* Next header UDP */
493 0x00, 0x00, 0x00, 0x00,
494 0x00, 0x00, 0x00, 0x00,
495 0x00, 0x00, 0x00, 0x00,
496 0x00, 0x00, 0x00, 0x00,
497 0x00, 0x00, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00,
500 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 58 */
503 0x00, 0x08, 0x00, 0x00,
505 0x00, 0x00, /* 2 bytes for 4 byte alignment */
508 /* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
509 static const struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_tcp_packet_offsets[] = {
511 { ICE_IPV4_OFOS, 14 },
516 { ICE_PROTOCOL_LAST, 0 },
519 static const u8 dummy_ipv4_gtpu_ipv4_tcp_packet[] = {
520 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
521 0x00, 0x00, 0x00, 0x00,
522 0x00, 0x00, 0x00, 0x00,
525 0x45, 0x00, 0x00, 0x58, /* IP 14 */
526 0x00, 0x00, 0x00, 0x00,
527 0x00, 0x11, 0x00, 0x00,
528 0x00, 0x00, 0x00, 0x00,
529 0x00, 0x00, 0x00, 0x00,
531 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
532 0x00, 0x44, 0x00, 0x00,
534 0x34, 0xff, 0x00, 0x34, /* GTP-U Header 42 */
535 0x00, 0x00, 0x00, 0x00,
536 0x00, 0x00, 0x00, 0x85,
538 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
539 0x00, 0x00, 0x00, 0x00,
541 0x45, 0x00, 0x00, 0x28, /* IP 62 */
542 0x00, 0x00, 0x00, 0x00,
543 0x00, 0x06, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00,
545 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, /* TCP 82 */
548 0x00, 0x00, 0x00, 0x00,
549 0x00, 0x00, 0x00, 0x00,
550 0x50, 0x00, 0x00, 0x00,
551 0x00, 0x00, 0x00, 0x00,
553 0x00, 0x00, /* 2 bytes for 4 byte alignment */
556 /* Outer IPv4 + Outer UDP + GTP + Inner IPv4 + Inner UDP */
557 static const struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_udp_packet_offsets[] = {
559 { ICE_IPV4_OFOS, 14 },
563 { ICE_UDP_ILOS, 82 },
564 { ICE_PROTOCOL_LAST, 0 },
567 static const u8 dummy_ipv4_gtpu_ipv4_udp_packet[] = {
568 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
569 0x00, 0x00, 0x00, 0x00,
570 0x00, 0x00, 0x00, 0x00,
573 0x45, 0x00, 0x00, 0x4c, /* IP 14 */
574 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x11, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
580 0x00, 0x38, 0x00, 0x00,
582 0x34, 0xff, 0x00, 0x28, /* GTP-U Header 42 */
583 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x85,
586 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
587 0x00, 0x00, 0x00, 0x00,
589 0x45, 0x00, 0x00, 0x1c, /* IP 62 */
590 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x11, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, /* UDP 82 */
596 0x00, 0x08, 0x00, 0x00,
598 0x00, 0x00, /* 2 bytes for 4 byte alignment */
601 /* Outer IPv6 + Outer UDP + GTP + Inner IPv4 + Inner TCP */
602 static const struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv6_tcp_packet_offsets[] = {
604 { ICE_IPV4_OFOS, 14 },
609 { ICE_PROTOCOL_LAST, 0 },
612 static const u8 dummy_ipv4_gtpu_ipv6_tcp_packet[] = {
613 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
614 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00,
618 0x45, 0x00, 0x00, 0x6c, /* IP 14 */
619 0x00, 0x00, 0x00, 0x00,
620 0x00, 0x11, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00,
622 0x00, 0x00, 0x00, 0x00,
624 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
625 0x00, 0x58, 0x00, 0x00,
627 0x34, 0xff, 0x00, 0x48, /* GTP-U Header 42 */
628 0x00, 0x00, 0x00, 0x00,
629 0x00, 0x00, 0x00, 0x85,
631 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
632 0x00, 0x00, 0x00, 0x00,
634 0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
635 0x00, 0x14, 0x06, 0x00,
636 0x00, 0x00, 0x00, 0x00,
637 0x00, 0x00, 0x00, 0x00,
638 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00,
640 0x00, 0x00, 0x00, 0x00,
641 0x00, 0x00, 0x00, 0x00,
642 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, /* TCP 102 */
646 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00,
648 0x50, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, /* 2 bytes for 4 byte alignment */
654 static const struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv6_udp_packet_offsets[] = {
656 { ICE_IPV4_OFOS, 14 },
660 { ICE_UDP_ILOS, 102 },
661 { ICE_PROTOCOL_LAST, 0 },
664 static const u8 dummy_ipv4_gtpu_ipv6_udp_packet[] = {
665 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
666 0x00, 0x00, 0x00, 0x00,
667 0x00, 0x00, 0x00, 0x00,
670 0x45, 0x00, 0x00, 0x60, /* IP 14 */
671 0x00, 0x00, 0x00, 0x00,
672 0x00, 0x11, 0x00, 0x00,
673 0x00, 0x00, 0x00, 0x00,
674 0x00, 0x00, 0x00, 0x00,
676 0x00, 0x00, 0x08, 0x68, /* UDP 34 */
677 0x00, 0x4c, 0x00, 0x00,
679 0x34, 0xff, 0x00, 0x3c, /* GTP-U Header 42 */
680 0x00, 0x00, 0x00, 0x00,
681 0x00, 0x00, 0x00, 0x85,
683 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 54 */
684 0x00, 0x00, 0x00, 0x00,
686 0x60, 0x00, 0x00, 0x00, /* IPv6 62 */
687 0x00, 0x08, 0x11, 0x00,
688 0x00, 0x00, 0x00, 0x00,
689 0x00, 0x00, 0x00, 0x00,
690 0x00, 0x00, 0x00, 0x00,
691 0x00, 0x00, 0x00, 0x00,
692 0x00, 0x00, 0x00, 0x00,
693 0x00, 0x00, 0x00, 0x00,
694 0x00, 0x00, 0x00, 0x00,
695 0x00, 0x00, 0x00, 0x00,
697 0x00, 0x00, 0x00, 0x00, /* UDP 102 */
698 0x00, 0x08, 0x00, 0x00,
700 0x00, 0x00, /* 2 bytes for 4 byte alignment */
703 static const struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv4_tcp_packet_offsets[] = {
705 { ICE_IPV6_OFOS, 14 },
710 { ICE_PROTOCOL_LAST, 0 },
713 static const u8 dummy_ipv6_gtpu_ipv4_tcp_packet[] = {
714 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
715 0x00, 0x00, 0x00, 0x00,
716 0x00, 0x00, 0x00, 0x00,
719 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
720 0x00, 0x44, 0x11, 0x00,
721 0x00, 0x00, 0x00, 0x00,
722 0x00, 0x00, 0x00, 0x00,
723 0x00, 0x00, 0x00, 0x00,
724 0x00, 0x00, 0x00, 0x00,
725 0x00, 0x00, 0x00, 0x00,
726 0x00, 0x00, 0x00, 0x00,
727 0x00, 0x00, 0x00, 0x00,
728 0x00, 0x00, 0x00, 0x00,
730 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
731 0x00, 0x44, 0x00, 0x00,
733 0x34, 0xff, 0x00, 0x34, /* GTP-U Header 62 */
734 0x00, 0x00, 0x00, 0x00,
735 0x00, 0x00, 0x00, 0x85,
737 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
738 0x00, 0x00, 0x00, 0x00,
740 0x45, 0x00, 0x00, 0x28, /* IP 82 */
741 0x00, 0x00, 0x00, 0x00,
742 0x00, 0x06, 0x00, 0x00,
743 0x00, 0x00, 0x00, 0x00,
744 0x00, 0x00, 0x00, 0x00,
746 0x00, 0x00, 0x00, 0x00, /* TCP 102 */
747 0x00, 0x00, 0x00, 0x00,
748 0x00, 0x00, 0x00, 0x00,
749 0x50, 0x00, 0x00, 0x00,
750 0x00, 0x00, 0x00, 0x00,
752 0x00, 0x00, /* 2 bytes for 4 byte alignment */
755 static const struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv4_udp_packet_offsets[] = {
757 { ICE_IPV6_OFOS, 14 },
761 { ICE_UDP_ILOS, 102 },
762 { ICE_PROTOCOL_LAST, 0 },
765 static const u8 dummy_ipv6_gtpu_ipv4_udp_packet[] = {
766 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
767 0x00, 0x00, 0x00, 0x00,
768 0x00, 0x00, 0x00, 0x00,
771 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
772 0x00, 0x38, 0x11, 0x00,
773 0x00, 0x00, 0x00, 0x00,
774 0x00, 0x00, 0x00, 0x00,
775 0x00, 0x00, 0x00, 0x00,
776 0x00, 0x00, 0x00, 0x00,
777 0x00, 0x00, 0x00, 0x00,
778 0x00, 0x00, 0x00, 0x00,
779 0x00, 0x00, 0x00, 0x00,
780 0x00, 0x00, 0x00, 0x00,
782 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
783 0x00, 0x38, 0x00, 0x00,
785 0x34, 0xff, 0x00, 0x28, /* GTP-U Header 62 */
786 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x85,
789 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
790 0x00, 0x00, 0x00, 0x00,
792 0x45, 0x00, 0x00, 0x1c, /* IP 82 */
793 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x11, 0x00, 0x00,
795 0x00, 0x00, 0x00, 0x00,
796 0x00, 0x00, 0x00, 0x00,
798 0x00, 0x00, 0x00, 0x00, /* UDP 102 */
799 0x00, 0x08, 0x00, 0x00,
801 0x00, 0x00, /* 2 bytes for 4 byte alignment */
804 static const struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv6_tcp_packet_offsets[] = {
806 { ICE_IPV6_OFOS, 14 },
811 { ICE_PROTOCOL_LAST, 0 },
814 static const u8 dummy_ipv6_gtpu_ipv6_tcp_packet[] = {
815 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
816 0x00, 0x00, 0x00, 0x00,
817 0x00, 0x00, 0x00, 0x00,
820 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
821 0x00, 0x58, 0x11, 0x00,
822 0x00, 0x00, 0x00, 0x00,
823 0x00, 0x00, 0x00, 0x00,
824 0x00, 0x00, 0x00, 0x00,
825 0x00, 0x00, 0x00, 0x00,
826 0x00, 0x00, 0x00, 0x00,
827 0x00, 0x00, 0x00, 0x00,
828 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
832 0x00, 0x58, 0x00, 0x00,
834 0x34, 0xff, 0x00, 0x48, /* GTP-U Header 62 */
835 0x00, 0x00, 0x00, 0x00,
836 0x00, 0x00, 0x00, 0x85,
838 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
839 0x00, 0x00, 0x00, 0x00,
841 0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
842 0x00, 0x14, 0x06, 0x00,
843 0x00, 0x00, 0x00, 0x00,
844 0x00, 0x00, 0x00, 0x00,
845 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x00, 0x00,
848 0x00, 0x00, 0x00, 0x00,
849 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, /* TCP 122 */
853 0x00, 0x00, 0x00, 0x00,
854 0x00, 0x00, 0x00, 0x00,
855 0x50, 0x00, 0x00, 0x00,
856 0x00, 0x00, 0x00, 0x00,
858 0x00, 0x00, /* 2 bytes for 4 byte alignment */
861 static const struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv6_udp_packet_offsets[] = {
863 { ICE_IPV6_OFOS, 14 },
867 { ICE_UDP_ILOS, 102 },
868 { ICE_PROTOCOL_LAST, 0 },
871 static const u8 dummy_ipv6_gtpu_ipv6_udp_packet[] = {
872 0x00, 0x00, 0x00, 0x00, /* Ethernet 0 */
873 0x00, 0x00, 0x00, 0x00,
874 0x00, 0x00, 0x00, 0x00,
877 0x60, 0x00, 0x00, 0x00, /* IPv6 14 */
878 0x00, 0x4c, 0x11, 0x00,
879 0x00, 0x00, 0x00, 0x00,
880 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00,
884 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x00, 0x00, 0x00,
886 0x00, 0x00, 0x00, 0x00,
888 0x00, 0x00, 0x08, 0x68, /* UDP 54 */
889 0x00, 0x4c, 0x00, 0x00,
891 0x34, 0xff, 0x00, 0x3c, /* GTP-U Header 62 */
892 0x00, 0x00, 0x00, 0x00,
893 0x00, 0x00, 0x00, 0x85,
895 0x02, 0x00, 0x00, 0x00, /* GTP_PDUSession_ExtensionHeader 74 */
896 0x00, 0x00, 0x00, 0x00,
898 0x60, 0x00, 0x00, 0x00, /* IPv6 82 */
899 0x00, 0x08, 0x11, 0x00,
900 0x00, 0x00, 0x00, 0x00,
901 0x00, 0x00, 0x00, 0x00,
902 0x00, 0x00, 0x00, 0x00,
903 0x00, 0x00, 0x00, 0x00,
904 0x00, 0x00, 0x00, 0x00,
905 0x00, 0x00, 0x00, 0x00,
906 0x00, 0x00, 0x00, 0x00,
907 0x00, 0x00, 0x00, 0x00,
909 0x00, 0x00, 0x00, 0x00, /* UDP 122 */
910 0x00, 0x08, 0x00, 0x00,
912 0x00, 0x00, /* 2 bytes for 4 byte alignment */
915 static const struct ice_dummy_pkt_offsets dummy_udp_gtp_packet_offsets[] = {
917 { ICE_IPV4_OFOS, 14 },
920 { ICE_PROTOCOL_LAST, 0 },
923 static const u8 dummy_udp_gtp_packet[] = {
924 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
925 0x00, 0x00, 0x00, 0x00,
926 0x00, 0x00, 0x00, 0x00,
929 0x45, 0x00, 0x00, 0x30, /* ICE_IPV4_OFOS 14 */
930 0x00, 0x00, 0x00, 0x00,
931 0x00, 0x11, 0x00, 0x00,
932 0x00, 0x00, 0x00, 0x00,
933 0x00, 0x00, 0x00, 0x00,
935 0x00, 0x00, 0x08, 0x68, /* ICE_UDP_OF 34 */
936 0x00, 0x1c, 0x00, 0x00,
938 0x34, 0xff, 0x00, 0x0c, /* ICE_GTP 42 */
939 0x00, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x85,
942 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
943 0x00, 0x00, 0x00, 0x00,
947 struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv4_packet_offsets[] = {
949 { ICE_IPV4_OFOS, 14 },
953 { ICE_PROTOCOL_LAST, 0 },
956 static const u8 dummy_ipv4_gtpu_ipv4_packet[] = {
957 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
958 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00,
962 0x45, 0x00, 0x00, 0x44, /* ICE_IPV4_OFOS 14 */
963 0x00, 0x00, 0x40, 0x00,
964 0x40, 0x11, 0x00, 0x00,
965 0x00, 0x00, 0x00, 0x00,
966 0x00, 0x00, 0x00, 0x00,
968 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */
969 0x00, 0x00, 0x00, 0x00,
971 0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */
972 0x00, 0x00, 0x00, 0x00,
973 0x00, 0x00, 0x00, 0x85,
975 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
976 0x00, 0x00, 0x00, 0x00,
978 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 62 */
979 0x00, 0x00, 0x40, 0x00,
980 0x40, 0x00, 0x00, 0x00,
981 0x00, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00,
987 struct ice_dummy_pkt_offsets dummy_ipv4_gtpu_ipv6_packet_offsets[] = {
989 { ICE_IPV4_OFOS, 14 },
993 { ICE_PROTOCOL_LAST, 0 },
996 static const u8 dummy_ipv4_gtpu_ipv6_packet[] = {
997 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
998 0x00, 0x00, 0x00, 0x00,
999 0x00, 0x00, 0x00, 0x00,
1002 0x45, 0x00, 0x00, 0x58, /* ICE_IPV4_OFOS 14 */
1003 0x00, 0x00, 0x40, 0x00,
1004 0x40, 0x11, 0x00, 0x00,
1005 0x00, 0x00, 0x00, 0x00,
1006 0x00, 0x00, 0x00, 0x00,
1008 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 34 */
1009 0x00, 0x00, 0x00, 0x00,
1011 0x34, 0xff, 0x00, 0x28, /* ICE_GTP 42 */
1012 0x00, 0x00, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x85,
1015 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
1016 0x00, 0x00, 0x00, 0x00,
1018 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 62 */
1019 0x00, 0x00, 0x3b, 0x00,
1020 0x00, 0x00, 0x00, 0x00,
1021 0x00, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x00, 0x00,
1023 0x00, 0x00, 0x00, 0x00,
1024 0x00, 0x00, 0x00, 0x00,
1025 0x00, 0x00, 0x00, 0x00,
1026 0x00, 0x00, 0x00, 0x00,
1027 0x00, 0x00, 0x00, 0x00,
1033 struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv4_packet_offsets[] = {
1034 { ICE_MAC_OFOS, 0 },
1035 { ICE_IPV6_OFOS, 14 },
1038 { ICE_IPV4_IL, 82 },
1039 { ICE_PROTOCOL_LAST, 0 },
1042 static const u8 dummy_ipv6_gtpu_ipv4_packet[] = {
1043 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1044 0x00, 0x00, 0x00, 0x00,
1045 0x00, 0x00, 0x00, 0x00,
1048 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
1049 0x00, 0x58, 0x11, 0x00, /* Next header UDP*/
1050 0x00, 0x00, 0x00, 0x00,
1051 0x00, 0x00, 0x00, 0x00,
1052 0x00, 0x00, 0x00, 0x00,
1053 0x00, 0x00, 0x00, 0x00,
1054 0x00, 0x00, 0x00, 0x00,
1055 0x00, 0x00, 0x00, 0x00,
1056 0x00, 0x00, 0x00, 0x00,
1057 0x00, 0x00, 0x00, 0x00,
1059 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */
1060 0x00, 0x00, 0x00, 0x00,
1062 0x34, 0xff, 0x00, 0x28, /* ICE_GTP 62 */
1063 0x00, 0x00, 0x00, 0x00,
1064 0x00, 0x00, 0x00, 0x85,
1066 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
1067 0x00, 0x00, 0x00, 0x00,
1069 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 82 */
1070 0x00, 0x00, 0x40, 0x00,
1071 0x40, 0x00, 0x00, 0x00,
1072 0x00, 0x00, 0x00, 0x00,
1073 0x00, 0x00, 0x00, 0x00,
1079 struct ice_dummy_pkt_offsets dummy_ipv6_gtpu_ipv6_packet_offsets[] = {
1080 { ICE_MAC_OFOS, 0 },
1081 { ICE_IPV6_OFOS, 14 },
1084 { ICE_IPV6_IL, 82 },
1085 { ICE_PROTOCOL_LAST, 0 },
1088 static const u8 dummy_ipv6_gtpu_ipv6_packet[] = {
1089 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1090 0x00, 0x00, 0x00, 0x00,
1091 0x00, 0x00, 0x00, 0x00,
1094 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
1095 0x00, 0x6c, 0x11, 0x00, /* Next header UDP*/
1096 0x00, 0x00, 0x00, 0x00,
1097 0x00, 0x00, 0x00, 0x00,
1098 0x00, 0x00, 0x00, 0x00,
1099 0x00, 0x00, 0x00, 0x00,
1100 0x00, 0x00, 0x00, 0x00,
1101 0x00, 0x00, 0x00, 0x00,
1102 0x00, 0x00, 0x00, 0x00,
1103 0x00, 0x00, 0x00, 0x00,
1105 0x08, 0x68, 0x08, 0x68, /* ICE_UDP_OF 54 */
1106 0x00, 0x00, 0x00, 0x00,
1108 0x34, 0xff, 0x00, 0x28, /* ICE_GTP 62 */
1109 0x00, 0x00, 0x00, 0x00,
1110 0x00, 0x00, 0x00, 0x85,
1112 0x02, 0x00, 0x00, 0x00, /* PDU Session extension header */
1113 0x00, 0x00, 0x00, 0x00,
1115 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFIL 82 */
1116 0x00, 0x00, 0x3b, 0x00,
1117 0x00, 0x00, 0x00, 0x00,
1118 0x00, 0x00, 0x00, 0x00,
1119 0x00, 0x00, 0x00, 0x00,
1120 0x00, 0x00, 0x00, 0x00,
1121 0x00, 0x00, 0x00, 0x00,
1122 0x00, 0x00, 0x00, 0x00,
1123 0x00, 0x00, 0x00, 0x00,
1124 0x00, 0x00, 0x00, 0x00,
1130 struct ice_dummy_pkt_offsets dummy_ipv4_gtp_no_pay_packet_offsets[] = {
1131 { ICE_MAC_OFOS, 0 },
1132 { ICE_IPV4_OFOS, 14 },
1134 { ICE_GTP_NO_PAY, 42 },
1135 { ICE_PROTOCOL_LAST, 0 },
1139 struct ice_dummy_pkt_offsets dummy_ipv6_gtp_no_pay_packet_offsets[] = {
1140 { ICE_MAC_OFOS, 0 },
1141 { ICE_IPV6_OFOS, 14 },
1143 { ICE_GTP_NO_PAY, 62 },
1144 { ICE_PROTOCOL_LAST, 0 },
1147 static const struct ice_dummy_pkt_offsets dummy_pppoe_packet_offsets[] = {
1148 { ICE_MAC_OFOS, 0 },
1149 { ICE_ETYPE_OL, 12 },
1150 { ICE_VLAN_OFOS, 14},
1152 { ICE_PROTOCOL_LAST, 0 },
1155 static const struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv4_offsets[] = {
1156 { ICE_MAC_OFOS, 0 },
1157 { ICE_ETYPE_OL, 12 },
1158 { ICE_VLAN_OFOS, 14},
1160 { ICE_IPV4_OFOS, 26 },
1161 { ICE_PROTOCOL_LAST, 0 },
1164 static const u8 dummy_pppoe_ipv4_packet[] = {
1165 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1166 0x00, 0x00, 0x00, 0x00,
1167 0x00, 0x00, 0x00, 0x00,
1169 0x81, 0x00, /* ICE_ETYPE_OL 12 */
1171 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */
1173 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */
1176 0x00, 0x21, /* PPP Link Layer 24 */
1178 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 26 */
1179 0x00, 0x00, 0x00, 0x00,
1180 0x00, 0x00, 0x00, 0x00,
1181 0x00, 0x00, 0x00, 0x00,
1182 0x00, 0x00, 0x00, 0x00,
1184 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1188 struct ice_dummy_pkt_offsets dummy_pppoe_ipv4_tcp_packet_offsets[] = {
1189 { ICE_MAC_OFOS, 0 },
1190 { ICE_ETYPE_OL, 12 },
1191 { ICE_VLAN_OFOS, 14},
1193 { ICE_IPV4_OFOS, 26 },
1195 { ICE_PROTOCOL_LAST, 0 },
1198 static const u8 dummy_pppoe_ipv4_tcp_packet[] = {
1199 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1200 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00,
1203 0x81, 0x00, /* ICE_ETYPE_OL 12 */
1205 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */
1207 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */
1210 0x00, 0x21, /* PPP Link Layer 24 */
1212 0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 26 */
1213 0x00, 0x01, 0x00, 0x00,
1214 0x00, 0x06, 0x00, 0x00,
1215 0x00, 0x00, 0x00, 0x00,
1216 0x00, 0x00, 0x00, 0x00,
1218 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 46 */
1219 0x00, 0x00, 0x00, 0x00,
1220 0x00, 0x00, 0x00, 0x00,
1221 0x50, 0x00, 0x00, 0x00,
1222 0x00, 0x00, 0x00, 0x00,
1224 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1228 struct ice_dummy_pkt_offsets dummy_pppoe_ipv4_udp_packet_offsets[] = {
1229 { ICE_MAC_OFOS, 0 },
1230 { ICE_ETYPE_OL, 12 },
1231 { ICE_VLAN_OFOS, 14},
1233 { ICE_IPV4_OFOS, 26 },
1234 { ICE_UDP_ILOS, 46 },
1235 { ICE_PROTOCOL_LAST, 0 },
1238 static const u8 dummy_pppoe_ipv4_udp_packet[] = {
1239 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1240 0x00, 0x00, 0x00, 0x00,
1241 0x00, 0x00, 0x00, 0x00,
1243 0x81, 0x00, /* ICE_ETYPE_OL 12 */
1245 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */
1247 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */
1250 0x00, 0x21, /* PPP Link Layer 24 */
1252 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 26 */
1253 0x00, 0x01, 0x00, 0x00,
1254 0x00, 0x11, 0x00, 0x00,
1255 0x00, 0x00, 0x00, 0x00,
1256 0x00, 0x00, 0x00, 0x00,
1258 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 46 */
1259 0x00, 0x08, 0x00, 0x00,
1261 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1264 static const struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv6_offsets[] = {
1265 { ICE_MAC_OFOS, 0 },
1266 { ICE_ETYPE_OL, 12 },
1267 { ICE_VLAN_OFOS, 14},
1269 { ICE_IPV6_OFOS, 26 },
1270 { ICE_PROTOCOL_LAST, 0 },
1273 static const u8 dummy_pppoe_ipv6_packet[] = {
1274 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1275 0x00, 0x00, 0x00, 0x00,
1276 0x00, 0x00, 0x00, 0x00,
1278 0x81, 0x00, /* ICE_ETYPE_OL 12 */
1280 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */
1282 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */
1285 0x00, 0x57, /* PPP Link Layer 24 */
1287 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 26 */
1288 0x00, 0x00, 0x3b, 0x00,
1289 0x00, 0x00, 0x00, 0x00,
1290 0x00, 0x00, 0x00, 0x00,
1291 0x00, 0x00, 0x00, 0x00,
1292 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00,
1294 0x00, 0x00, 0x00, 0x00,
1295 0x00, 0x00, 0x00, 0x00,
1296 0x00, 0x00, 0x00, 0x00,
1298 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1302 struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv6_tcp_offsets[] = {
1303 { ICE_MAC_OFOS, 0 },
1304 { ICE_ETYPE_OL, 12 },
1305 { ICE_VLAN_OFOS, 14},
1307 { ICE_IPV6_OFOS, 26 },
1309 { ICE_PROTOCOL_LAST, 0 },
1312 static const u8 dummy_pppoe_ipv6_tcp_packet[] = {
1313 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1314 0x00, 0x00, 0x00, 0x00,
1315 0x00, 0x00, 0x00, 0x00,
1317 0x81, 0x00, /* ICE_ETYPE_OL 12 */
1319 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */
1321 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */
1324 0x00, 0x57, /* PPP Link Layer 24 */
1326 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 26 */
1327 0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
1328 0x00, 0x00, 0x00, 0x00,
1329 0x00, 0x00, 0x00, 0x00,
1330 0x00, 0x00, 0x00, 0x00,
1331 0x00, 0x00, 0x00, 0x00,
1332 0x00, 0x00, 0x00, 0x00,
1333 0x00, 0x00, 0x00, 0x00,
1334 0x00, 0x00, 0x00, 0x00,
1335 0x00, 0x00, 0x00, 0x00,
1337 0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 66 */
1338 0x00, 0x00, 0x00, 0x00,
1339 0x00, 0x00, 0x00, 0x00,
1340 0x50, 0x00, 0x00, 0x00,
1341 0x00, 0x00, 0x00, 0x00,
1343 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1347 struct ice_dummy_pkt_offsets dummy_pppoe_packet_ipv6_udp_offsets[] = {
1348 { ICE_MAC_OFOS, 0 },
1349 { ICE_ETYPE_OL, 12 },
1350 { ICE_VLAN_OFOS, 14},
1352 { ICE_IPV6_OFOS, 26 },
1353 { ICE_UDP_ILOS, 66 },
1354 { ICE_PROTOCOL_LAST, 0 },
1357 static const u8 dummy_pppoe_ipv6_udp_packet[] = {
1358 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1359 0x00, 0x00, 0x00, 0x00,
1360 0x00, 0x00, 0x00, 0x00,
1362 0x81, 0x00, /* ICE_ETYPE_OL 12 */
1364 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 14 */
1366 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 18 */
1369 0x00, 0x57, /* PPP Link Layer 24 */
1371 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 26 */
1372 0x00, 0x08, 0x11, 0x00, /* Next header UDP*/
1373 0x00, 0x00, 0x00, 0x00,
1374 0x00, 0x00, 0x00, 0x00,
1375 0x00, 0x00, 0x00, 0x00,
1376 0x00, 0x00, 0x00, 0x00,
1377 0x00, 0x00, 0x00, 0x00,
1378 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0x00, 0x00,
1380 0x00, 0x00, 0x00, 0x00,
1382 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 66 */
1383 0x00, 0x08, 0x00, 0x00,
1385 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1388 static const struct ice_dummy_pkt_offsets dummy_ipv4_esp_packet_offsets[] = {
1389 { ICE_MAC_OFOS, 0 },
1390 { ICE_IPV4_OFOS, 14 },
1392 { ICE_PROTOCOL_LAST, 0 },
1395 static const u8 dummy_ipv4_esp_pkt[] = {
1396 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1397 0x00, 0x00, 0x00, 0x00,
1398 0x00, 0x00, 0x00, 0x00,
1401 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 14 */
1402 0x00, 0x00, 0x40, 0x00,
1403 0x40, 0x32, 0x00, 0x00,
1404 0x00, 0x00, 0x00, 0x00,
1405 0x00, 0x00, 0x00, 0x00,
1407 0x00, 0x00, 0x00, 0x00, /* ICE_ESP 34 */
1408 0x00, 0x00, 0x00, 0x00,
1409 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1412 static const struct ice_dummy_pkt_offsets dummy_ipv6_esp_packet_offsets[] = {
1413 { ICE_MAC_OFOS, 0 },
1414 { ICE_IPV6_OFOS, 14 },
1416 { ICE_PROTOCOL_LAST, 0 },
1419 static const u8 dummy_ipv6_esp_pkt[] = {
1420 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1421 0x00, 0x00, 0x00, 0x00,
1422 0x00, 0x00, 0x00, 0x00,
1425 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
1426 0x00, 0x08, 0x32, 0x00, /* Next header ESP */
1427 0x00, 0x00, 0x00, 0x00,
1428 0x00, 0x00, 0x00, 0x00,
1429 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x00, 0x00,
1431 0x00, 0x00, 0x00, 0x00,
1432 0x00, 0x00, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x00, 0x00, 0x00,
1436 0x00, 0x00, 0x00, 0x00, /* ICE_ESP 54 */
1437 0x00, 0x00, 0x00, 0x00,
1438 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1441 static const struct ice_dummy_pkt_offsets dummy_ipv4_ah_packet_offsets[] = {
1442 { ICE_MAC_OFOS, 0 },
1443 { ICE_IPV4_OFOS, 14 },
1445 { ICE_PROTOCOL_LAST, 0 },
1448 static const u8 dummy_ipv4_ah_pkt[] = {
1449 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1450 0x00, 0x00, 0x00, 0x00,
1451 0x00, 0x00, 0x00, 0x00,
1454 0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */
1455 0x00, 0x00, 0x40, 0x00,
1456 0x40, 0x33, 0x00, 0x00,
1457 0x00, 0x00, 0x00, 0x00,
1458 0x00, 0x00, 0x00, 0x00,
1460 0x00, 0x00, 0x00, 0x00, /* ICE_AH 34 */
1461 0x00, 0x00, 0x00, 0x00,
1462 0x00, 0x00, 0x00, 0x00,
1463 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1466 static const struct ice_dummy_pkt_offsets dummy_ipv6_ah_packet_offsets[] = {
1467 { ICE_MAC_OFOS, 0 },
1468 { ICE_IPV6_OFOS, 14 },
1470 { ICE_PROTOCOL_LAST, 0 },
1473 static const u8 dummy_ipv6_ah_pkt[] = {
1474 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1475 0x00, 0x00, 0x00, 0x00,
1476 0x00, 0x00, 0x00, 0x00,
1479 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
1480 0x00, 0x0c, 0x33, 0x00, /* Next header AH */
1481 0x00, 0x00, 0x00, 0x00,
1482 0x00, 0x00, 0x00, 0x00,
1483 0x00, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00,
1485 0x00, 0x00, 0x00, 0x00,
1486 0x00, 0x00, 0x00, 0x00,
1487 0x00, 0x00, 0x00, 0x00,
1488 0x00, 0x00, 0x00, 0x00,
1490 0x00, 0x00, 0x00, 0x00, /* ICE_AH 54 */
1491 0x00, 0x00, 0x00, 0x00,
1492 0x00, 0x00, 0x00, 0x00,
1493 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1496 static const struct ice_dummy_pkt_offsets dummy_ipv4_nat_packet_offsets[] = {
1497 { ICE_MAC_OFOS, 0 },
1498 { ICE_IPV4_OFOS, 14 },
1499 { ICE_UDP_ILOS, 34 },
1501 { ICE_PROTOCOL_LAST, 0 },
1504 static const u8 dummy_ipv4_nat_pkt[] = {
1505 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1506 0x00, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00,
1510 0x45, 0x00, 0x00, 0x24, /* ICE_IPV4_IL 14 */
1511 0x00, 0x00, 0x40, 0x00,
1512 0x40, 0x11, 0x00, 0x00,
1513 0x00, 0x00, 0x00, 0x00,
1514 0x00, 0x00, 0x00, 0x00,
1516 0x00, 0x00, 0x11, 0x94, /* ICE_NAT_T 34 */
1517 0x00, 0x00, 0x00, 0x00,
1519 0x00, 0x00, 0x00, 0x00,
1520 0x00, 0x00, 0x00, 0x00,
1521 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1524 static const struct ice_dummy_pkt_offsets dummy_ipv6_nat_packet_offsets[] = {
1525 { ICE_MAC_OFOS, 0 },
1526 { ICE_IPV6_OFOS, 14 },
1527 { ICE_UDP_ILOS, 54 },
1529 { ICE_PROTOCOL_LAST, 0 },
1532 static const u8 dummy_ipv6_nat_pkt[] = {
1533 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1534 0x00, 0x00, 0x00, 0x00,
1535 0x00, 0x00, 0x00, 0x00,
1538 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 14 */
1539 0x00, 0x10, 0x11, 0x00, /* Next header NAT_T */
1540 0x00, 0x00, 0x00, 0x00,
1541 0x00, 0x00, 0x00, 0x00,
1542 0x00, 0x00, 0x00, 0x00,
1543 0x00, 0x00, 0x00, 0x00,
1544 0x00, 0x00, 0x00, 0x00,
1545 0x00, 0x00, 0x00, 0x00,
1546 0x00, 0x00, 0x00, 0x00,
1547 0x00, 0x00, 0x00, 0x00,
1549 0x00, 0x00, 0x11, 0x94, /* ICE_NAT_T 54 */
1550 0x00, 0x00, 0x00, 0x00,
1552 0x00, 0x00, 0x00, 0x00,
1553 0x00, 0x00, 0x00, 0x00,
1554 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1558 static const struct ice_dummy_pkt_offsets dummy_ipv4_l2tpv3_packet_offsets[] = {
1559 { ICE_MAC_OFOS, 0 },
1560 { ICE_IPV4_OFOS, 14 },
1562 { ICE_PROTOCOL_LAST, 0 },
1565 static const u8 dummy_ipv4_l2tpv3_pkt[] = {
1566 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1567 0x00, 0x00, 0x00, 0x00,
1568 0x00, 0x00, 0x00, 0x00,
1571 0x45, 0x00, 0x00, 0x20, /* ICE_IPV4_IL 14 */
1572 0x00, 0x00, 0x40, 0x00,
1573 0x40, 0x73, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00,
1575 0x00, 0x00, 0x00, 0x00,
1577 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 34 */
1578 0x00, 0x00, 0x00, 0x00,
1579 0x00, 0x00, 0x00, 0x00,
1580 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1583 static const struct ice_dummy_pkt_offsets dummy_ipv6_l2tpv3_packet_offsets[] = {
1584 { ICE_MAC_OFOS, 0 },
1585 { ICE_IPV6_OFOS, 14 },
1587 { ICE_PROTOCOL_LAST, 0 },
1590 static const u8 dummy_ipv6_l2tpv3_pkt[] = {
1591 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1592 0x00, 0x00, 0x00, 0x00,
1593 0x00, 0x00, 0x00, 0x00,
1596 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_IL 14 */
1597 0x00, 0x0c, 0x73, 0x40,
1598 0x00, 0x00, 0x00, 0x00,
1599 0x00, 0x00, 0x00, 0x00,
1600 0x00, 0x00, 0x00, 0x00,
1601 0x00, 0x00, 0x00, 0x00,
1602 0x00, 0x00, 0x00, 0x00,
1603 0x00, 0x00, 0x00, 0x00,
1604 0x00, 0x00, 0x00, 0x00,
1605 0x00, 0x00, 0x00, 0x00,
1607 0x00, 0x00, 0x00, 0x00, /* ICE_L2TPV3 54 */
1608 0x00, 0x00, 0x00, 0x00,
1609 0x00, 0x00, 0x00, 0x00,
1610 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1613 static const struct ice_dummy_pkt_offsets dummy_qinq_ipv4_packet_offsets[] = {
1614 { ICE_MAC_OFOS, 0 },
1615 { ICE_VLAN_EX, 14 },
1616 { ICE_VLAN_OFOS, 18 },
1617 { ICE_IPV4_OFOS, 22 },
1618 { ICE_PROTOCOL_LAST, 0 },
1621 static const u8 dummy_qinq_ipv4_pkt[] = {
1622 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1623 0x00, 0x00, 0x00, 0x00,
1624 0x00, 0x00, 0x00, 0x00,
1627 0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
1628 0x00, 0x00, 0x08, 0x00, /* ICE_VLAN_OFOS 18 */
1630 0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 22 */
1631 0x00, 0x01, 0x00, 0x00,
1632 0x00, 0x11, 0x00, 0x00,
1633 0x00, 0x00, 0x00, 0x00,
1634 0x00, 0x00, 0x00, 0x00,
1636 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 42 */
1637 0x00, 0x08, 0x00, 0x00,
1639 0x00, 0x00, /* 2 bytes for 4 byte alignment */
1642 static const struct ice_dummy_pkt_offsets dummy_qinq_ipv6_packet_offsets[] = {
1643 { ICE_MAC_OFOS, 0 },
1644 { ICE_VLAN_EX, 14 },
1645 { ICE_VLAN_OFOS, 18 },
1646 { ICE_IPV6_OFOS, 22 },
1647 { ICE_PROTOCOL_LAST, 0 },
1650 static const u8 dummy_qinq_ipv6_pkt[] = {
1651 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1652 0x00, 0x00, 0x00, 0x00,
1653 0x00, 0x00, 0x00, 0x00,
1656 0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
1657 0x00, 0x00, 0x86, 0xDD, /* ICE_VLAN_OFOS 18 */
1659 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 22 */
1660 0x00, 0x10, 0x11, 0x00, /* Next header UDP */
1661 0x00, 0x00, 0x00, 0x00,
1662 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00,
1665 0x00, 0x00, 0x00, 0x00,
1666 0x00, 0x00, 0x00, 0x00,
1667 0x00, 0x00, 0x00, 0x00,
1668 0x00, 0x00, 0x00, 0x00,
1670 0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 62 */
1671 0x00, 0x10, 0x00, 0x00,
1673 0x00, 0x00, 0x00, 0x00, /* needed for ESP packets */
1674 0x00, 0x00, 0x00, 0x00,
1676 0x00, 0x00, /* 2 bytes for 4 byte alignment */
1679 static const struct ice_dummy_pkt_offsets dummy_qinq_pppoe_packet_offsets[] = {
1680 { ICE_MAC_OFOS, 0 },
1681 { ICE_VLAN_EX, 14 },
1682 { ICE_VLAN_OFOS, 18 },
1684 { ICE_PROTOCOL_LAST, 0 },
1688 struct ice_dummy_pkt_offsets dummy_qinq_pppoe_ipv4_packet_offsets[] = {
1689 { ICE_MAC_OFOS, 0 },
1690 { ICE_VLAN_EX, 14 },
1691 { ICE_VLAN_OFOS, 18 },
1693 { ICE_IPV4_OFOS, 30 },
1694 { ICE_PROTOCOL_LAST, 0 },
1697 static const u8 dummy_qinq_pppoe_ipv4_pkt[] = {
1698 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1699 0x00, 0x00, 0x00, 0x00,
1700 0x00, 0x00, 0x00, 0x00,
1703 0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
1704 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 18 */
1706 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 22 */
1709 0x00, 0x21, /* PPP Link Layer 28 */
1711 0x45, 0x00, 0x00, 0x14, /* ICE_IPV4_IL 30 */
1712 0x00, 0x00, 0x00, 0x00,
1713 0x00, 0x00, 0x00, 0x00,
1714 0x00, 0x00, 0x00, 0x00,
1715 0x00, 0x00, 0x00, 0x00,
1717 0x00, 0x00, /* 2 bytes for 4 byte alignment */
1721 struct ice_dummy_pkt_offsets dummy_qinq_pppoe_packet_ipv6_offsets[] = {
1722 { ICE_MAC_OFOS, 0 },
1723 { ICE_ETYPE_OL, 12 },
1725 { ICE_VLAN_OFOS, 18 },
1727 { ICE_IPV6_OFOS, 30 },
1728 { ICE_PROTOCOL_LAST, 0 },
1731 static const u8 dummy_qinq_pppoe_ipv6_packet[] = {
1732 0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
1733 0x00, 0x00, 0x00, 0x00,
1734 0x00, 0x00, 0x00, 0x00,
1736 0x91, 0x00, /* ICE_ETYPE_OL 12 */
1738 0x00, 0x00, 0x81, 0x00, /* ICE_VLAN_EX 14 */
1739 0x00, 0x00, 0x88, 0x64, /* ICE_VLAN_OFOS 18 */
1741 0x11, 0x00, 0x00, 0x00, /* ICE_PPPOE 22 */
1744 0x00, 0x57, /* PPP Link Layer 28*/
1746 0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 30 */
1747 0x00, 0x00, 0x3b, 0x00,
1748 0x00, 0x00, 0x00, 0x00,
1749 0x00, 0x00, 0x00, 0x00,
1750 0x00, 0x00, 0x00, 0x00,
1751 0x00, 0x00, 0x00, 0x00,
1752 0x00, 0x00, 0x00, 0x00,
1753 0x00, 0x00, 0x00, 0x00,
1754 0x00, 0x00, 0x00, 0x00,
1755 0x00, 0x00, 0x00, 0x00,
1757 0x00, 0x00, /* 2 bytes for 4 bytes alignment */
1760 /* this is a recipe to profile association bitmap */
1761 static ice_declare_bitmap(recipe_to_profile[ICE_MAX_NUM_RECIPES],
1762 ICE_MAX_NUM_PROFILES);
1764 /* this is a profile to recipe association bitmap */
1765 static ice_declare_bitmap(profile_to_recipe[ICE_MAX_NUM_PROFILES],
1766 ICE_MAX_NUM_RECIPES);
1768 static void ice_get_recp_to_prof_map(struct ice_hw *hw);
1771 * ice_collect_result_idx - copy result index values
1772 * @buf: buffer that contains the result index
1773 * @recp: the recipe struct to copy data into
1775 static void ice_collect_result_idx(struct ice_aqc_recipe_data_elem *buf,
1776 struct ice_sw_recipe *recp)
1778 if (buf->content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
1779 ice_set_bit(buf->content.result_indx &
1780 ~ICE_AQ_RECIPE_RESULT_EN, recp->res_idxs);
1784 * ice_get_tun_type_for_recipe - get tunnel type for the recipe
1785 * @rid: recipe ID that we are populating
1787 static enum ice_sw_tunnel_type ice_get_tun_type_for_recipe(u8 rid, bool vlan)
1789 u8 vxlan_profile[12] = {10, 11, 12, 16, 17, 18, 22, 23, 24, 25, 26, 27};
1790 u8 gre_profile[12] = {13, 14, 15, 19, 20, 21, 28, 29, 30, 31, 32, 33};
1791 u8 pppoe_profile[7] = {34, 35, 36, 37, 38, 39, 40};
1792 u8 non_tun_profile[6] = {4, 5, 6, 7, 8, 9};
1793 enum ice_sw_tunnel_type tun_type;
1794 u16 i, j, profile_num = 0;
1795 bool non_tun_valid = false;
1796 bool pppoe_valid = false;
1797 bool vxlan_valid = false;
1798 bool gre_valid = false;
1799 bool gtp_valid = false;
1800 bool flag_valid = false;
1802 for (j = 0; j < ICE_MAX_NUM_PROFILES; j++) {
1803 if (!ice_is_bit_set(recipe_to_profile[rid], j))
1808 for (i = 0; i < 12; i++) {
1809 if (gre_profile[i] == j)
1813 for (i = 0; i < 12; i++) {
1814 if (vxlan_profile[i] == j)
1818 for (i = 0; i < 7; i++) {
1819 if (pppoe_profile[i] == j)
1823 for (i = 0; i < 6; i++) {
1824 if (non_tun_profile[i] == j)
1825 non_tun_valid = true;
1828 if (j >= ICE_PROFID_IPV4_GTPU_EH_IPV4_OTHER &&
1829 j <= ICE_PROFID_IPV6_GTPU_IPV6_TCP)
1832 if ((j >= ICE_PROFID_IPV4_ESP &&
1833 j <= ICE_PROFID_IPV6_PFCP_SESSION) ||
1834 (j >= ICE_PROFID_IPV4_GTPC_TEID &&
1835 j <= ICE_PROFID_IPV6_GTPU_TEID))
1839 if (!non_tun_valid && vxlan_valid)
1840 tun_type = ICE_SW_TUN_VXLAN;
1841 else if (!non_tun_valid && gre_valid)
1842 tun_type = ICE_SW_TUN_NVGRE;
1843 else if (!non_tun_valid && pppoe_valid)
1844 tun_type = ICE_SW_TUN_PPPOE;
1845 else if (!non_tun_valid && gtp_valid)
1846 tun_type = ICE_SW_TUN_GTP;
1847 else if (non_tun_valid &&
1848 (vxlan_valid || gre_valid || gtp_valid || pppoe_valid))
1849 tun_type = ICE_SW_TUN_AND_NON_TUN;
1850 else if (non_tun_valid && !vxlan_valid && !gre_valid && !gtp_valid &&
1852 tun_type = ICE_NON_TUN;
1854 tun_type = ICE_NON_TUN;
1856 if (profile_num > 1 && tun_type == ICE_SW_TUN_PPPOE) {
1857 i = ice_is_bit_set(recipe_to_profile[rid],
1858 ICE_PROFID_PPPOE_IPV4_OTHER);
1859 j = ice_is_bit_set(recipe_to_profile[rid],
1860 ICE_PROFID_PPPOE_IPV6_OTHER);
1862 tun_type = ICE_SW_TUN_PPPOE_IPV4;
1864 tun_type = ICE_SW_TUN_PPPOE_IPV6;
1867 if (tun_type == ICE_SW_TUN_GTP) {
1868 if (ice_is_bit_set(recipe_to_profile[rid],
1869 ICE_PROFID_IPV4_GTPU_IPV4_OTHER))
1870 tun_type = ICE_SW_TUN_IPV4_GTPU_IPV4;
1871 else if (ice_is_bit_set(recipe_to_profile[rid],
1872 ICE_PROFID_IPV4_GTPU_IPV6_OTHER))
1873 tun_type = ICE_SW_TUN_IPV4_GTPU_IPV6;
1874 else if (ice_is_bit_set(recipe_to_profile[rid],
1875 ICE_PROFID_IPV6_GTPU_IPV4_OTHER))
1876 tun_type = ICE_SW_TUN_IPV6_GTPU_IPV4;
1877 else if (ice_is_bit_set(recipe_to_profile[rid],
1878 ICE_PROFID_IPV6_GTPU_IPV6_OTHER))
1879 tun_type = ICE_SW_TUN_IPV6_GTPU_IPV6;
1882 if (profile_num == 1 && (flag_valid || non_tun_valid || pppoe_valid)) {
1883 for (j = 0; j < ICE_MAX_NUM_PROFILES; j++) {
1884 if (ice_is_bit_set(recipe_to_profile[rid], j)) {
1886 case ICE_PROFID_IPV4_TCP:
1887 tun_type = ICE_SW_IPV4_TCP;
1889 case ICE_PROFID_IPV4_UDP:
1890 tun_type = ICE_SW_IPV4_UDP;
1892 case ICE_PROFID_IPV6_TCP:
1893 tun_type = ICE_SW_IPV6_TCP;
1895 case ICE_PROFID_IPV6_UDP:
1896 tun_type = ICE_SW_IPV6_UDP;
1898 case ICE_PROFID_PPPOE_PAY:
1899 tun_type = ICE_SW_TUN_PPPOE_PAY;
1901 case ICE_PROFID_PPPOE_IPV4_TCP:
1902 tun_type = ICE_SW_TUN_PPPOE_IPV4_TCP;
1904 case ICE_PROFID_PPPOE_IPV4_UDP:
1905 tun_type = ICE_SW_TUN_PPPOE_IPV4_UDP;
1907 case ICE_PROFID_PPPOE_IPV4_OTHER:
1908 tun_type = ICE_SW_TUN_PPPOE_IPV4;
1910 case ICE_PROFID_PPPOE_IPV6_TCP:
1911 tun_type = ICE_SW_TUN_PPPOE_IPV6_TCP;
1913 case ICE_PROFID_PPPOE_IPV6_UDP:
1914 tun_type = ICE_SW_TUN_PPPOE_IPV6_UDP;
1916 case ICE_PROFID_PPPOE_IPV6_OTHER:
1917 tun_type = ICE_SW_TUN_PPPOE_IPV6;
1919 case ICE_PROFID_IPV4_ESP:
1920 tun_type = ICE_SW_TUN_IPV4_ESP;
1922 case ICE_PROFID_IPV6_ESP:
1923 tun_type = ICE_SW_TUN_IPV6_ESP;
1925 case ICE_PROFID_IPV4_AH:
1926 tun_type = ICE_SW_TUN_IPV4_AH;
1928 case ICE_PROFID_IPV6_AH:
1929 tun_type = ICE_SW_TUN_IPV6_AH;
1931 case ICE_PROFID_IPV4_NAT_T:
1932 tun_type = ICE_SW_TUN_IPV4_NAT_T;
1934 case ICE_PROFID_IPV6_NAT_T:
1935 tun_type = ICE_SW_TUN_IPV6_NAT_T;
1937 case ICE_PROFID_IPV4_PFCP_NODE:
1939 ICE_SW_TUN_PROFID_IPV4_PFCP_NODE;
1941 case ICE_PROFID_IPV6_PFCP_NODE:
1943 ICE_SW_TUN_PROFID_IPV6_PFCP_NODE;
1945 case ICE_PROFID_IPV4_PFCP_SESSION:
1947 ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION;
1949 case ICE_PROFID_IPV6_PFCP_SESSION:
1951 ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION;
1953 case ICE_PROFID_MAC_IPV4_L2TPV3:
1954 tun_type = ICE_SW_TUN_IPV4_L2TPV3;
1956 case ICE_PROFID_MAC_IPV6_L2TPV3:
1957 tun_type = ICE_SW_TUN_IPV6_L2TPV3;
1959 case ICE_PROFID_IPV4_GTPU_TEID:
1960 tun_type = ICE_SW_TUN_IPV4_GTPU_NO_PAY;
1962 case ICE_PROFID_IPV6_GTPU_TEID:
1963 tun_type = ICE_SW_TUN_IPV6_GTPU_NO_PAY;
1974 if (vlan && tun_type == ICE_SW_TUN_PPPOE)
1975 tun_type = ICE_SW_TUN_PPPOE_QINQ;
1976 else if (vlan && tun_type == ICE_SW_TUN_PPPOE_IPV6)
1977 tun_type = ICE_SW_TUN_PPPOE_IPV6_QINQ;
1978 else if (vlan && tun_type == ICE_SW_TUN_PPPOE_IPV4)
1979 tun_type = ICE_SW_TUN_PPPOE_IPV4_QINQ;
1980 else if (vlan && tun_type == ICE_SW_TUN_PPPOE_PAY)
1981 tun_type = ICE_SW_TUN_PPPOE_PAY_QINQ;
1982 else if (vlan && tun_type == ICE_SW_TUN_AND_NON_TUN)
1983 tun_type = ICE_SW_TUN_AND_NON_TUN_QINQ;
1984 else if (vlan && tun_type == ICE_NON_TUN)
1985 tun_type = ICE_NON_TUN_QINQ;
1991 * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
1992 * @hw: pointer to hardware structure
1993 * @recps: struct that we need to populate
1994 * @rid: recipe ID that we are populating
1995 * @refresh_required: true if we should get recipe to profile mapping from FW
1997 * This function is used to populate all the necessary entries into our
1998 * bookkeeping so that we have a current list of all the recipes that are
1999 * programmed in the firmware.
2001 static enum ice_status
2002 ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
2003 bool *refresh_required)
2005 ice_declare_bitmap(result_bm, ICE_MAX_FV_WORDS);
2006 struct ice_aqc_recipe_data_elem *tmp;
2007 u16 num_recps = ICE_MAX_NUM_RECIPES;
2008 struct ice_prot_lkup_ext *lkup_exts;
2009 enum ice_status status;
2014 ice_zero_bitmap(result_bm, ICE_MAX_FV_WORDS);
2016 /* we need a buffer big enough to accommodate all the recipes */
2017 tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,
2018 ICE_MAX_NUM_RECIPES, sizeof(*tmp));
2020 return ICE_ERR_NO_MEMORY;
2022 tmp[0].recipe_indx = rid;
2023 status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
2024 /* non-zero status meaning recipe doesn't exist */
2028 /* Get recipe to profile map so that we can get the fv from lkups that
2029 * we read for a recipe from FW. Since we want to minimize the number of
2030 * times we make this FW call, just make one call and cache the copy
2031 * until a new recipe is added. This operation is only required the
2032 * first time to get the changes from FW. Then to search existing
2033 * entries we don't need to update the cache again until another recipe
2036 if (*refresh_required) {
2037 ice_get_recp_to_prof_map(hw);
2038 *refresh_required = false;
2041 /* Start populating all the entries for recps[rid] based on lkups from
2042 * firmware. Note that we are only creating the root recipe in our
2045 lkup_exts = &recps[rid].lkup_exts;
2047 for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
2048 struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
2049 struct ice_recp_grp_entry *rg_entry;
2050 u8 i, prof, idx, prot = 0;
2054 rg_entry = (struct ice_recp_grp_entry *)
2055 ice_malloc(hw, sizeof(*rg_entry));
2057 status = ICE_ERR_NO_MEMORY;
2061 idx = root_bufs.recipe_indx;
2062 is_root = root_bufs.content.rid & ICE_AQ_RECIPE_ID_IS_ROOT;
2064 /* Mark all result indices in this chain */
2065 if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
2066 ice_set_bit(root_bufs.content.result_indx &
2067 ~ICE_AQ_RECIPE_RESULT_EN, result_bm);
2069 /* get the first profile that is associated with rid */
2070 prof = ice_find_first_bit(recipe_to_profile[idx],
2071 ICE_MAX_NUM_PROFILES);
2072 for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
2073 u8 lkup_indx = root_bufs.content.lkup_indx[i + 1];
2075 rg_entry->fv_idx[i] = lkup_indx;
2076 rg_entry->fv_mask[i] =
2077 LE16_TO_CPU(root_bufs.content.mask[i + 1]);
2079 /* If the recipe is a chained recipe then all its
2080 * child recipe's result will have a result index.
2081 * To fill fv_words we should not use those result
2082 * index, we only need the protocol ids and offsets.
2083 * We will skip all the fv_idx which stores result
2084 * index in them. We also need to skip any fv_idx which
2085 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
2086 * valid offset value.
2088 if (ice_is_bit_set(hw->switch_info->prof_res_bm[prof],
2089 rg_entry->fv_idx[i]) ||
2090 rg_entry->fv_idx[i] & ICE_AQ_RECIPE_LKUP_IGNORE ||
2091 rg_entry->fv_idx[i] == 0)
2094 ice_find_prot_off(hw, ICE_BLK_SW, prof,
2095 rg_entry->fv_idx[i], &prot, &off);
2096 lkup_exts->fv_words[fv_word_idx].prot_id = prot;
2097 lkup_exts->fv_words[fv_word_idx].off = off;
2098 lkup_exts->field_mask[fv_word_idx] =
2099 rg_entry->fv_mask[i];
2100 if (prot == ICE_META_DATA_ID_HW &&
2101 off == ICE_TUN_FLAG_MDID_OFF)
2105 /* populate rg_list with the data from the child entry of this
2108 LIST_ADD(&rg_entry->l_entry, &recps[rid].rg_list);
2110 /* Propagate some data to the recipe database */
2111 recps[idx].is_root = !!is_root;
2112 recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2113 ice_zero_bitmap(recps[idx].res_idxs, ICE_MAX_FV_WORDS);
2114 if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN) {
2115 recps[idx].chain_idx = root_bufs.content.result_indx &
2116 ~ICE_AQ_RECIPE_RESULT_EN;
2117 ice_set_bit(recps[idx].chain_idx, recps[idx].res_idxs);
2119 recps[idx].chain_idx = ICE_INVAL_CHAIN_IND;
2125 /* Only do the following for root recipes entries */
2126 ice_memcpy(recps[idx].r_bitmap, root_bufs.recipe_bitmap,
2127 sizeof(recps[idx].r_bitmap), ICE_NONDMA_TO_NONDMA);
2128 recps[idx].root_rid = root_bufs.content.rid &
2129 ~ICE_AQ_RECIPE_ID_IS_ROOT;
2130 recps[idx].priority = root_bufs.content.act_ctrl_fwd_priority;
2133 /* Complete initialization of the root recipe entry */
2134 lkup_exts->n_val_words = fv_word_idx;
2135 recps[rid].big_recp = (num_recps > 1);
2136 recps[rid].n_grp_count = (u8)num_recps;
2137 recps[rid].tun_type = ice_get_tun_type_for_recipe(rid, vlan);
2138 recps[rid].root_buf = (struct ice_aqc_recipe_data_elem *)
2139 ice_memdup(hw, tmp, recps[rid].n_grp_count *
2140 sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA);
2141 if (!recps[rid].root_buf)
2144 /* Copy result indexes */
2145 ice_cp_bitmap(recps[rid].res_idxs, result_bm, ICE_MAX_FV_WORDS);
2146 recps[rid].recp_created = true;
2154 * ice_get_recp_to_prof_map - updates recipe to profile mapping
2155 * @hw: pointer to hardware structure
2157 * This function is used to populate recipe_to_profile matrix where index to
2158 * this array is the recipe ID and the element is the mapping of which profiles
2159 * is this recipe mapped to.
2161 static void ice_get_recp_to_prof_map(struct ice_hw *hw)
2163 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
2166 for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
2169 ice_zero_bitmap(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
2170 ice_zero_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
2171 if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
2173 ice_cp_bitmap(profile_to_recipe[i], r_bitmap,
2174 ICE_MAX_NUM_RECIPES);
2175 ice_for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
2176 ice_set_bit(i, recipe_to_profile[j]);
2181 * ice_init_def_sw_recp - initialize the recipe book keeping tables
2182 * @hw: pointer to the HW struct
2183 * @recp_list: pointer to sw recipe list
2185 * Allocate memory for the entire recipe table and initialize the structures/
2186 * entries corresponding to basic recipes.
2189 ice_init_def_sw_recp(struct ice_hw *hw, struct ice_sw_recipe **recp_list)
2191 struct ice_sw_recipe *recps;
2194 recps = (struct ice_sw_recipe *)
2195 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps));
2197 return ICE_ERR_NO_MEMORY;
2199 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
2200 recps[i].root_rid = i;
2201 INIT_LIST_HEAD(&recps[i].filt_rules);
2202 INIT_LIST_HEAD(&recps[i].filt_replay_rules);
2203 INIT_LIST_HEAD(&recps[i].rg_list);
2204 ice_init_lock(&recps[i].filt_rule_lock);
2213 * ice_aq_get_sw_cfg - get switch configuration
2214 * @hw: pointer to the hardware structure
2215 * @buf: pointer to the result buffer
2216 * @buf_size: length of the buffer available for response
2217 * @req_desc: pointer to requested descriptor
2218 * @num_elems: pointer to number of elements
2219 * @cd: pointer to command details structure or NULL
2221 * Get switch configuration (0x0200) to be placed in buf.
2222 * This admin command returns information such as initial VSI/port number
2223 * and switch ID it belongs to.
2225 * NOTE: *req_desc is both an input/output parameter.
2226 * The caller of this function first calls this function with *request_desc set
2227 * to 0. If the response from f/w has *req_desc set to 0, all the switch
2228 * configuration information has been returned; if non-zero (meaning not all
2229 * the information was returned), the caller should call this function again
2230 * with *req_desc set to the previous value returned by f/w to get the
2231 * next block of switch configuration information.
2233 * *num_elems is output only parameter. This reflects the number of elements
2234 * in response buffer. The caller of this function to use *num_elems while
2235 * parsing the response buffer.
2237 static enum ice_status
2238 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
2239 u16 buf_size, u16 *req_desc, u16 *num_elems,
2240 struct ice_sq_cd *cd)
2242 struct ice_aqc_get_sw_cfg *cmd;
2243 struct ice_aq_desc desc;
2244 enum ice_status status;
2246 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
2247 cmd = &desc.params.get_sw_conf;
2248 cmd->element = CPU_TO_LE16(*req_desc);
2250 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2252 *req_desc = LE16_TO_CPU(cmd->element);
2253 *num_elems = LE16_TO_CPU(cmd->num_elems);
2260 * ice_alloc_rss_global_lut - allocate a RSS global LUT
2261 * @hw: pointer to the HW struct
2262 * @shared_res: true to allocate as a shared resource and false to allocate as a dedicated resource
2263 * @global_lut_id: output parameter for the RSS global LUT's ID
2265 enum ice_status ice_alloc_rss_global_lut(struct ice_hw *hw, bool shared_res, u16 *global_lut_id)
2267 struct ice_aqc_alloc_free_res_elem *sw_buf;
2268 enum ice_status status;
2271 buf_len = ice_struct_size(sw_buf, elem, 1);
2272 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
2274 return ICE_ERR_NO_MEMORY;
2276 sw_buf->num_elems = CPU_TO_LE16(1);
2277 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_GLOBAL_RSS_HASH |
2278 (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
2279 ICE_AQC_RES_TYPE_FLAG_DEDICATED));
2281 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, ice_aqc_opc_alloc_res, NULL);
2283 ice_debug(hw, ICE_DBG_RES, "Failed to allocate %s RSS global LUT, status %d\n",
2284 shared_res ? "shared" : "dedicated", status);
2285 goto ice_alloc_global_lut_exit;
2288 *global_lut_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
2290 ice_alloc_global_lut_exit:
2291 ice_free(hw, sw_buf);
2296 * ice_free_global_lut - free a RSS global LUT
2297 * @hw: pointer to the HW struct
2298 * @global_lut_id: ID of the RSS global LUT to free
2300 enum ice_status ice_free_rss_global_lut(struct ice_hw *hw, u16 global_lut_id)
2302 struct ice_aqc_alloc_free_res_elem *sw_buf;
2303 u16 buf_len, num_elems = 1;
2304 enum ice_status status;
2306 buf_len = ice_struct_size(sw_buf, elem, num_elems);
2307 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
2309 return ICE_ERR_NO_MEMORY;
2311 sw_buf->num_elems = CPU_TO_LE16(num_elems);
2312 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_GLOBAL_RSS_HASH);
2313 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(global_lut_id);
2315 status = ice_aq_alloc_free_res(hw, num_elems, sw_buf, buf_len, ice_aqc_opc_free_res, NULL);
2317 ice_debug(hw, ICE_DBG_RES, "Failed to free RSS global LUT %d, status %d\n",
2318 global_lut_id, status);
2320 ice_free(hw, sw_buf);
2325 * ice_alloc_sw - allocate resources specific to switch
2326 * @hw: pointer to the HW struct
2327 * @ena_stats: true to turn on VEB stats
2328 * @shared_res: true for shared resource, false for dedicated resource
2329 * @sw_id: switch ID returned
2330 * @counter_id: VEB counter ID returned
2332 * allocates switch resources (SWID and VEB counter) (0x0208)
2335 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id,
2338 struct ice_aqc_alloc_free_res_elem *sw_buf;
2339 struct ice_aqc_res_elem *sw_ele;
2340 enum ice_status status;
2343 buf_len = ice_struct_size(sw_buf, elem, 1);
2344 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
2346 return ICE_ERR_NO_MEMORY;
2348 /* Prepare buffer for switch ID.
2349 * The number of resource entries in buffer is passed as 1 since only a
2350 * single switch/VEB instance is allocated, and hence a single sw_id
2353 sw_buf->num_elems = CPU_TO_LE16(1);
2355 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID |
2356 (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
2357 ICE_AQC_RES_TYPE_FLAG_DEDICATED));
2359 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
2360 ice_aqc_opc_alloc_res, NULL);
2363 goto ice_alloc_sw_exit;
2365 sw_ele = &sw_buf->elem[0];
2366 *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp);
2369 /* Prepare buffer for VEB Counter */
2370 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res;
2371 struct ice_aqc_alloc_free_res_elem *counter_buf;
2372 struct ice_aqc_res_elem *counter_ele;
2374 counter_buf = (struct ice_aqc_alloc_free_res_elem *)
2375 ice_malloc(hw, buf_len);
2377 status = ICE_ERR_NO_MEMORY;
2378 goto ice_alloc_sw_exit;
2381 /* The number of resource entries in buffer is passed as 1 since
2382 * only a single switch/VEB instance is allocated, and hence a
2383 * single VEB counter is requested.
2385 counter_buf->num_elems = CPU_TO_LE16(1);
2386 counter_buf->res_type =
2387 CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER |
2388 ICE_AQC_RES_TYPE_FLAG_DEDICATED);
2389 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
2393 ice_free(hw, counter_buf);
2394 goto ice_alloc_sw_exit;
2396 counter_ele = &counter_buf->elem[0];
2397 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp);
2398 ice_free(hw, counter_buf);
2402 ice_free(hw, sw_buf);
2407 * ice_free_sw - free resources specific to switch
2408 * @hw: pointer to the HW struct
2409 * @sw_id: switch ID returned
2410 * @counter_id: VEB counter ID returned
2412 * free switch resources (SWID and VEB counter) (0x0209)
2414 * NOTE: This function frees multiple resources. It continues
2415 * releasing other resources even after it encounters error.
2416 * The error code returned is the last error it encountered.
2418 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id)
2420 struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf;
2421 enum ice_status status, ret_status;
2424 buf_len = ice_struct_size(sw_buf, elem, 1);
2425 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
2427 return ICE_ERR_NO_MEMORY;
2429 /* Prepare buffer to free for switch ID res.
2430 * The number of resource entries in buffer is passed as 1 since only a
2431 * single switch/VEB instance is freed, and hence a single sw_id
2434 sw_buf->num_elems = CPU_TO_LE16(1);
2435 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID);
2436 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id);
2438 ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
2439 ice_aqc_opc_free_res, NULL);
2442 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
2444 /* Prepare buffer to free for VEB Counter resource */
2445 counter_buf = (struct ice_aqc_alloc_free_res_elem *)
2446 ice_malloc(hw, buf_len);
2448 ice_free(hw, sw_buf);
2449 return ICE_ERR_NO_MEMORY;
2452 /* The number of resource entries in buffer is passed as 1 since only a
2453 * single switch/VEB instance is freed, and hence a single VEB counter
2456 counter_buf->num_elems = CPU_TO_LE16(1);
2457 counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER);
2458 counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
2460 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
2461 ice_aqc_opc_free_res, NULL);
2463 ice_debug(hw, ICE_DBG_SW, "VEB counter resource could not be freed\n");
2464 ret_status = status;
2467 ice_free(hw, counter_buf);
2468 ice_free(hw, sw_buf);
2474 * @hw: pointer to the HW struct
2475 * @vsi_ctx: pointer to a VSI context struct
2476 * @cd: pointer to command details structure or NULL
2478 * Add a VSI context to the hardware (0x0210)
2481 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
2482 struct ice_sq_cd *cd)
2484 struct ice_aqc_add_update_free_vsi_resp *res;
2485 struct ice_aqc_add_get_update_free_vsi *cmd;
2486 struct ice_aq_desc desc;
2487 enum ice_status status;
2489 cmd = &desc.params.vsi_cmd;
2490 res = &desc.params.add_update_free_vsi_res;
2492 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
2494 if (!vsi_ctx->alloc_from_pool)
2495 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num |
2496 ICE_AQ_VSI_IS_VALID);
2498 cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags);
2500 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
2502 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
2503 sizeof(vsi_ctx->info), cd);
2506 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M;
2507 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used);
2508 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free);
2516 * @hw: pointer to the HW struct
2517 * @vsi_ctx: pointer to a VSI context struct
2518 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
2519 * @cd: pointer to command details structure or NULL
2521 * Free VSI context info from hardware (0x0213)
2524 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
2525 bool keep_vsi_alloc, struct ice_sq_cd *cd)
2527 struct ice_aqc_add_update_free_vsi_resp *resp;
2528 struct ice_aqc_add_get_update_free_vsi *cmd;
2529 struct ice_aq_desc desc;
2530 enum ice_status status;
2532 cmd = &desc.params.vsi_cmd;
2533 resp = &desc.params.add_update_free_vsi_res;
2535 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
2537 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
2539 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC);
2541 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
2543 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
2544 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
2552 * @hw: pointer to the HW struct
2553 * @vsi_ctx: pointer to a VSI context struct
2554 * @cd: pointer to command details structure or NULL
2556 * Update VSI context in the hardware (0x0211)
2559 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
2560 struct ice_sq_cd *cd)
2562 struct ice_aqc_add_update_free_vsi_resp *resp;
2563 struct ice_aqc_add_get_update_free_vsi *cmd;
2564 struct ice_aq_desc desc;
2565 enum ice_status status;
2567 cmd = &desc.params.vsi_cmd;
2568 resp = &desc.params.add_update_free_vsi_res;
2570 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
2572 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
2574 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
2576 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
2577 sizeof(vsi_ctx->info), cd);
2580 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
2581 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
2588 * ice_is_vsi_valid - check whether the VSI is valid or not
2589 * @hw: pointer to the HW struct
2590 * @vsi_handle: VSI handle
2592 * check whether the VSI is valid or not
2594 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
2596 return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
2600 * ice_get_hw_vsi_num - return the HW VSI number
2601 * @hw: pointer to the HW struct
2602 * @vsi_handle: VSI handle
2604 * return the HW VSI number
2605 * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
2607 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
2609 return hw->vsi_ctx[vsi_handle]->vsi_num;
2613 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
2614 * @hw: pointer to the HW struct
2615 * @vsi_handle: VSI handle
2617 * return the VSI context entry for a given VSI handle
2619 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
2621 return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
2625 * ice_save_vsi_ctx - save the VSI context for a given VSI handle
2626 * @hw: pointer to the HW struct
2627 * @vsi_handle: VSI handle
2628 * @vsi: VSI context pointer
2630 * save the VSI context entry for a given VSI handle
2633 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
2635 hw->vsi_ctx[vsi_handle] = vsi;
2639 * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
2640 * @hw: pointer to the HW struct
2641 * @vsi_handle: VSI handle
2643 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
2645 struct ice_vsi_ctx *vsi;
2648 vsi = ice_get_vsi_ctx(hw, vsi_handle);
2651 ice_for_each_traffic_class(i) {
2652 if (vsi->lan_q_ctx[i]) {
2653 ice_free(hw, vsi->lan_q_ctx[i]);
2654 vsi->lan_q_ctx[i] = NULL;
2660 * ice_clear_vsi_ctx - clear the VSI context entry
2661 * @hw: pointer to the HW struct
2662 * @vsi_handle: VSI handle
2664 * clear the VSI context entry
2666 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
2668 struct ice_vsi_ctx *vsi;
2670 vsi = ice_get_vsi_ctx(hw, vsi_handle);
2672 ice_clear_vsi_q_ctx(hw, vsi_handle);
2674 hw->vsi_ctx[vsi_handle] = NULL;
2679 * ice_clear_all_vsi_ctx - clear all the VSI context entries
2680 * @hw: pointer to the HW struct
2682 void ice_clear_all_vsi_ctx(struct ice_hw *hw)
2686 for (i = 0; i < ICE_MAX_VSI; i++)
2687 ice_clear_vsi_ctx(hw, i);
2691 * ice_add_vsi - add VSI context to the hardware and VSI handle list
2692 * @hw: pointer to the HW struct
2693 * @vsi_handle: unique VSI handle provided by drivers
2694 * @vsi_ctx: pointer to a VSI context struct
2695 * @cd: pointer to command details structure or NULL
2697 * Add a VSI context to the hardware also add it into the VSI handle list.
2698 * If this function gets called after reset for existing VSIs then update
2699 * with the new HW VSI number in the corresponding VSI handle list entry.
2702 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
2703 struct ice_sq_cd *cd)
2705 struct ice_vsi_ctx *tmp_vsi_ctx;
2706 enum ice_status status;
2708 if (vsi_handle >= ICE_MAX_VSI)
2709 return ICE_ERR_PARAM;
2710 status = ice_aq_add_vsi(hw, vsi_ctx, cd);
2713 tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
2715 /* Create a new VSI context */
2716 tmp_vsi_ctx = (struct ice_vsi_ctx *)
2717 ice_malloc(hw, sizeof(*tmp_vsi_ctx));
2719 ice_aq_free_vsi(hw, vsi_ctx, false, cd);
2720 return ICE_ERR_NO_MEMORY;
2722 *tmp_vsi_ctx = *vsi_ctx;
2724 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
2726 /* update with new HW VSI num */
2727 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
2734 * ice_free_vsi- free VSI context from hardware and VSI handle list
2735 * @hw: pointer to the HW struct
2736 * @vsi_handle: unique VSI handle
2737 * @vsi_ctx: pointer to a VSI context struct
2738 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
2739 * @cd: pointer to command details structure or NULL
2741 * Free VSI context info from hardware as well as from VSI handle list
2744 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
2745 bool keep_vsi_alloc, struct ice_sq_cd *cd)
2747 enum ice_status status;
2749 if (!ice_is_vsi_valid(hw, vsi_handle))
2750 return ICE_ERR_PARAM;
2751 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
2752 status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
2754 ice_clear_vsi_ctx(hw, vsi_handle);
2760 * @hw: pointer to the HW struct
2761 * @vsi_handle: unique VSI handle
2762 * @vsi_ctx: pointer to a VSI context struct
2763 * @cd: pointer to command details structure or NULL
2765 * Update VSI context in the hardware
2768 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
2769 struct ice_sq_cd *cd)
2771 if (!ice_is_vsi_valid(hw, vsi_handle))
2772 return ICE_ERR_PARAM;
2773 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
2774 return ice_aq_update_vsi(hw, vsi_ctx, cd);
2778 * ice_aq_get_vsi_params
2779 * @hw: pointer to the HW struct
2780 * @vsi_ctx: pointer to a VSI context struct
2781 * @cd: pointer to command details structure or NULL
2783 * Get VSI context info from hardware (0x0212)
2786 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
2787 struct ice_sq_cd *cd)
2789 struct ice_aqc_add_get_update_free_vsi *cmd;
2790 struct ice_aqc_get_vsi_resp *resp;
2791 struct ice_aq_desc desc;
2792 enum ice_status status;
2794 cmd = &desc.params.vsi_cmd;
2795 resp = &desc.params.get_vsi_resp;
2797 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params);
2799 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
2801 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
2802 sizeof(vsi_ctx->info), cd);
2804 vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) &
2806 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
2807 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
2814 * ice_aq_add_update_mir_rule - add/update a mirror rule
2815 * @hw: pointer to the HW struct
2816 * @rule_type: Rule Type
2817 * @dest_vsi: VSI number to which packets will be mirrored
2818 * @count: length of the list
2819 * @mr_buf: buffer for list of mirrored VSI numbers
2820 * @cd: pointer to command details structure or NULL
2823 * Add/Update Mirror Rule (0x260).
2826 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi,
2827 u16 count, struct ice_mir_rule_buf *mr_buf,
2828 struct ice_sq_cd *cd, u16 *rule_id)
2830 struct ice_aqc_add_update_mir_rule *cmd;
2831 struct ice_aq_desc desc;
2832 enum ice_status status;
2833 __le16 *mr_list = NULL;
2836 switch (rule_type) {
2837 case ICE_AQC_RULE_TYPE_VPORT_INGRESS:
2838 case ICE_AQC_RULE_TYPE_VPORT_EGRESS:
2839 /* Make sure count and mr_buf are set for these rule_types */
2840 if (!(count && mr_buf))
2841 return ICE_ERR_PARAM;
2843 buf_size = count * sizeof(__le16);
2844 mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size);
2846 return ICE_ERR_NO_MEMORY;
2848 case ICE_AQC_RULE_TYPE_PPORT_INGRESS:
2849 case ICE_AQC_RULE_TYPE_PPORT_EGRESS:
2850 /* Make sure count and mr_buf are not set for these
2853 if (count || mr_buf)
2854 return ICE_ERR_PARAM;
2857 ice_debug(hw, ICE_DBG_SW, "Error due to unsupported rule_type %u\n", rule_type);
2858 return ICE_ERR_OUT_OF_RANGE;
2861 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule);
2863 /* Pre-process 'mr_buf' items for add/update of virtual port
2864 * ingress/egress mirroring (but not physical port ingress/egress
2870 for (i = 0; i < count; i++) {
2873 id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M;
2875 /* Validate specified VSI number, make sure it is less
2876 * than ICE_MAX_VSI, if not return with error.
2878 if (id >= ICE_MAX_VSI) {
2879 ice_debug(hw, ICE_DBG_SW, "Error VSI index (%u) out-of-range\n",
2881 ice_free(hw, mr_list);
2882 return ICE_ERR_OUT_OF_RANGE;
2885 /* add VSI to mirror rule */
2888 CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M);
2889 else /* remove VSI from mirror rule */
2890 mr_list[i] = CPU_TO_LE16(id);
2894 cmd = &desc.params.add_update_rule;
2895 if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID)
2896 cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) |
2897 ICE_AQC_RULE_ID_VALID_M);
2898 cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M);
2899 cmd->num_entries = CPU_TO_LE16(count);
2900 cmd->dest = CPU_TO_LE16(dest_vsi);
2902 status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd);
2904 *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M;
2906 ice_free(hw, mr_list);
2912 * ice_aq_delete_mir_rule - delete a mirror rule
2913 * @hw: pointer to the HW struct
2914 * @rule_id: Mirror rule ID (to be deleted)
2915 * @keep_allocd: if set, the VSI stays part of the PF allocated res,
2916 * otherwise it is returned to the shared pool
2917 * @cd: pointer to command details structure or NULL
2919 * Delete Mirror Rule (0x261).
2922 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd,
2923 struct ice_sq_cd *cd)
2925 struct ice_aqc_delete_mir_rule *cmd;
2926 struct ice_aq_desc desc;
2928 /* rule_id should be in the range 0...63 */
2929 if (rule_id >= ICE_MAX_NUM_MIRROR_RULES)
2930 return ICE_ERR_OUT_OF_RANGE;
2932 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule);
2934 cmd = &desc.params.del_rule;
2935 rule_id |= ICE_AQC_RULE_ID_VALID_M;
2936 cmd->rule_id = CPU_TO_LE16(rule_id);
2939 cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M);
2941 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
2945 * ice_aq_alloc_free_vsi_list
2946 * @hw: pointer to the HW struct
2947 * @vsi_list_id: VSI list ID returned or used for lookup
2948 * @lkup_type: switch rule filter lookup type
2949 * @opc: switch rules population command type - pass in the command opcode
2951 * allocates or free a VSI list resource
2953 static enum ice_status
2954 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
2955 enum ice_sw_lkup_type lkup_type,
2956 enum ice_adminq_opc opc)
2958 struct ice_aqc_alloc_free_res_elem *sw_buf;
2959 struct ice_aqc_res_elem *vsi_ele;
2960 enum ice_status status;
2963 buf_len = ice_struct_size(sw_buf, elem, 1);
2964 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
2966 return ICE_ERR_NO_MEMORY;
2967 sw_buf->num_elems = CPU_TO_LE16(1);
2969 if (lkup_type == ICE_SW_LKUP_MAC ||
2970 lkup_type == ICE_SW_LKUP_MAC_VLAN ||
2971 lkup_type == ICE_SW_LKUP_ETHERTYPE ||
2972 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
2973 lkup_type == ICE_SW_LKUP_PROMISC ||
2974 lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2975 lkup_type == ICE_SW_LKUP_LAST) {
2976 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
2977 } else if (lkup_type == ICE_SW_LKUP_VLAN) {
2979 CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
2981 status = ICE_ERR_PARAM;
2982 goto ice_aq_alloc_free_vsi_list_exit;
2985 if (opc == ice_aqc_opc_free_res)
2986 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id);
2988 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
2990 goto ice_aq_alloc_free_vsi_list_exit;
2992 if (opc == ice_aqc_opc_alloc_res) {
2993 vsi_ele = &sw_buf->elem[0];
2994 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp);
2997 ice_aq_alloc_free_vsi_list_exit:
2998 ice_free(hw, sw_buf);
3003 * ice_aq_set_storm_ctrl - Sets storm control configuration
3004 * @hw: pointer to the HW struct
3005 * @bcast_thresh: represents the upper threshold for broadcast storm control
3006 * @mcast_thresh: represents the upper threshold for multicast storm control
3007 * @ctl_bitmask: storm control knobs
3009 * Sets the storm control configuration (0x0280)
3012 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh,
3015 struct ice_aqc_storm_cfg *cmd;
3016 struct ice_aq_desc desc;
3018 cmd = &desc.params.storm_conf;
3020 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg);
3022 cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M);
3023 cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M);
3024 cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask);
3026 return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
3030 * ice_aq_get_storm_ctrl - gets storm control configuration
3031 * @hw: pointer to the HW struct
3032 * @bcast_thresh: represents the upper threshold for broadcast storm control
3033 * @mcast_thresh: represents the upper threshold for multicast storm control
3034 * @ctl_bitmask: storm control knobs
3036 * Gets the storm control configuration (0x0281)
3039 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh,
3042 enum ice_status status;
3043 struct ice_aq_desc desc;
3045 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg);
3047 status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
3049 struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf;
3052 *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) &
3055 *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) &
3058 *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl);
3065 * ice_aq_sw_rules - add/update/remove switch rules
3066 * @hw: pointer to the HW struct
3067 * @rule_list: pointer to switch rule population list
3068 * @rule_list_sz: total size of the rule list in bytes
3069 * @num_rules: number of switch rules in the rule_list
3070 * @opc: switch rules population command type - pass in the command opcode
3071 * @cd: pointer to command details structure or NULL
3073 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
3075 static enum ice_status
3076 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
3077 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
3079 struct ice_aq_desc desc;
3080 enum ice_status status;
3082 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3084 if (opc != ice_aqc_opc_add_sw_rules &&
3085 opc != ice_aqc_opc_update_sw_rules &&
3086 opc != ice_aqc_opc_remove_sw_rules)
3087 return ICE_ERR_PARAM;
3089 ice_fill_dflt_direct_cmd_desc(&desc, opc);
3091 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
3092 desc.params.sw_rules.num_rules_fltr_entry_index =
3093 CPU_TO_LE16(num_rules);
3094 status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
3095 if (opc != ice_aqc_opc_add_sw_rules &&
3096 hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
3097 status = ICE_ERR_DOES_NOT_EXIST;
3103 * ice_aq_add_recipe - add switch recipe
3104 * @hw: pointer to the HW struct
3105 * @s_recipe_list: pointer to switch rule population list
3106 * @num_recipes: number of switch recipes in the list
3107 * @cd: pointer to command details structure or NULL
3112 ice_aq_add_recipe(struct ice_hw *hw,
3113 struct ice_aqc_recipe_data_elem *s_recipe_list,
3114 u16 num_recipes, struct ice_sq_cd *cd)
3116 struct ice_aqc_add_get_recipe *cmd;
3117 struct ice_aq_desc desc;
3120 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3121 cmd = &desc.params.add_get_recipe;
3122 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
3124 cmd->num_sub_recipes = CPU_TO_LE16(num_recipes);
3125 desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
3127 buf_size = num_recipes * sizeof(*s_recipe_list);
3129 return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
3133 * ice_aq_get_recipe - get switch recipe
3134 * @hw: pointer to the HW struct
3135 * @s_recipe_list: pointer to switch rule population list
3136 * @num_recipes: pointer to the number of recipes (input and output)
3137 * @recipe_root: root recipe number of recipe(s) to retrieve
3138 * @cd: pointer to command details structure or NULL
3142 * On input, *num_recipes should equal the number of entries in s_recipe_list.
3143 * On output, *num_recipes will equal the number of entries returned in
3146 * The caller must supply enough space in s_recipe_list to hold all possible
3147 * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
3150 ice_aq_get_recipe(struct ice_hw *hw,
3151 struct ice_aqc_recipe_data_elem *s_recipe_list,
3152 u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
3154 struct ice_aqc_add_get_recipe *cmd;
3155 struct ice_aq_desc desc;
3156 enum ice_status status;
3159 if (*num_recipes != ICE_MAX_NUM_RECIPES)
3160 return ICE_ERR_PARAM;
3162 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3163 cmd = &desc.params.add_get_recipe;
3164 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
3166 cmd->return_index = CPU_TO_LE16(recipe_root);
3167 cmd->num_sub_recipes = 0;
3169 buf_size = *num_recipes * sizeof(*s_recipe_list);
3171 status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
3172 /* cppcheck-suppress constArgument */
3173 *num_recipes = LE16_TO_CPU(cmd->num_sub_recipes);
3179 * ice_update_recipe_lkup_idx - update a default recipe based on the lkup_idx
3180 * @hw: pointer to the HW struct
3181 * @params: parameters used to update the default recipe
3183 * This function only supports updating default recipes and it only supports
3184 * updating a single recipe based on the lkup_idx at a time.
3186 * This is done as a read-modify-write operation. First, get the current recipe
3187 * contents based on the recipe's ID. Then modify the field vector index and
3188 * mask if it's valid at the lkup_idx. Finally, use the add recipe AQ to update
3189 * the pre-existing recipe with the modifications.
3192 ice_update_recipe_lkup_idx(struct ice_hw *hw,
3193 struct ice_update_recipe_lkup_idx_params *params)
3195 struct ice_aqc_recipe_data_elem *rcp_list;
3196 u16 num_recps = ICE_MAX_NUM_RECIPES;
3197 enum ice_status status;
3199 rcp_list = (struct ice_aqc_recipe_data_elem *)ice_malloc(hw, num_recps * sizeof(*rcp_list));
3201 return ICE_ERR_NO_MEMORY;
3203 /* read current recipe list from firmware */
3204 rcp_list->recipe_indx = params->rid;
3205 status = ice_aq_get_recipe(hw, rcp_list, &num_recps, params->rid, NULL);
3207 ice_debug(hw, ICE_DBG_SW, "Failed to get recipe %d, status %d\n",
3208 params->rid, status);
3212 /* only modify existing recipe's lkup_idx and mask if valid, while
3213 * leaving all other fields the same, then update the recipe firmware
3215 rcp_list->content.lkup_indx[params->lkup_idx] = params->fv_idx;
3216 if (params->mask_valid)
3217 rcp_list->content.mask[params->lkup_idx] =
3218 CPU_TO_LE16(params->mask);
3220 if (params->ignore_valid)
3221 rcp_list->content.lkup_indx[params->lkup_idx] |=
3222 ICE_AQ_RECIPE_LKUP_IGNORE;
3224 status = ice_aq_add_recipe(hw, &rcp_list[0], 1, NULL);
3226 ice_debug(hw, ICE_DBG_SW, "Failed to update recipe %d lkup_idx %d fv_idx %d mask %d mask_valid %s, status %d\n",
3227 params->rid, params->lkup_idx, params->fv_idx,
3228 params->mask, params->mask_valid ? "true" : "false",
3232 ice_free(hw, rcp_list);
3237 * ice_aq_map_recipe_to_profile - Map recipe to packet profile
3238 * @hw: pointer to the HW struct
3239 * @profile_id: package profile ID to associate the recipe with
3240 * @r_bitmap: Recipe bitmap filled in and need to be returned as response
3241 * @cd: pointer to command details structure or NULL
3242 * Recipe to profile association (0x0291)
3245 ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
3246 struct ice_sq_cd *cd)
3248 struct ice_aqc_recipe_to_profile *cmd;
3249 struct ice_aq_desc desc;
3251 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3252 cmd = &desc.params.recipe_to_profile;
3253 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
3254 cmd->profile_id = CPU_TO_LE16(profile_id);
3255 /* Set the recipe ID bit in the bitmask to let the device know which
3256 * profile we are associating the recipe to
3258 ice_memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc),
3259 ICE_NONDMA_TO_NONDMA);
3261 return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
3265 * ice_aq_get_recipe_to_profile - Map recipe to packet profile
3266 * @hw: pointer to the HW struct
3267 * @profile_id: package profile ID to associate the recipe with
3268 * @r_bitmap: Recipe bitmap filled in and need to be returned as response
3269 * @cd: pointer to command details structure or NULL
3270 * Associate profile ID with given recipe (0x0293)
3273 ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
3274 struct ice_sq_cd *cd)
3276 struct ice_aqc_recipe_to_profile *cmd;
3277 struct ice_aq_desc desc;
3278 enum ice_status status;
3280 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3281 cmd = &desc.params.recipe_to_profile;
3282 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
3283 cmd->profile_id = CPU_TO_LE16(profile_id);
3285 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
3287 ice_memcpy(r_bitmap, cmd->recipe_assoc,
3288 sizeof(cmd->recipe_assoc), ICE_NONDMA_TO_NONDMA);
3294 * ice_alloc_recipe - add recipe resource
3295 * @hw: pointer to the hardware structure
3296 * @rid: recipe ID returned as response to AQ call
3298 enum ice_status ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
3300 struct ice_aqc_alloc_free_res_elem *sw_buf;
3301 enum ice_status status;
3304 buf_len = ice_struct_size(sw_buf, elem, 1);
3305 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
3307 return ICE_ERR_NO_MEMORY;
3309 sw_buf->num_elems = CPU_TO_LE16(1);
3310 sw_buf->res_type = CPU_TO_LE16((ICE_AQC_RES_TYPE_RECIPE <<
3311 ICE_AQC_RES_TYPE_S) |
3312 ICE_AQC_RES_TYPE_FLAG_SHARED);
3313 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
3314 ice_aqc_opc_alloc_res, NULL);
3316 *rid = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
3317 ice_free(hw, sw_buf);
3322 /* ice_init_port_info - Initialize port_info with switch configuration data
3323 * @pi: pointer to port_info
3324 * @vsi_port_num: VSI number or port number
3325 * @type: Type of switch element (port or VSI)
3326 * @swid: switch ID of the switch the element is attached to
3327 * @pf_vf_num: PF or VF number
3328 * @is_vf: true if the element is a VF, false otherwise
3331 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
3332 u16 swid, u16 pf_vf_num, bool is_vf)
3335 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
3336 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
3338 pi->pf_vf_num = pf_vf_num;
3340 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
3341 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
3344 ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
3349 /* ice_get_initial_sw_cfg - Get initial port and default VSI data
3350 * @hw: pointer to the hardware structure
3352 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
3354 struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
3355 enum ice_status status;
3362 num_total_ports = 1;
3364 rbuf = (struct ice_aqc_get_sw_cfg_resp_elem *)
3365 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN);
3368 return ICE_ERR_NO_MEMORY;
3370 /* Multiple calls to ice_aq_get_sw_cfg may be required
3371 * to get all the switch configuration information. The need
3372 * for additional calls is indicated by ice_aq_get_sw_cfg
3373 * writing a non-zero value in req_desc
3376 struct ice_aqc_get_sw_cfg_resp_elem *ele;
3378 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
3379 &req_desc, &num_elems, NULL);
3384 for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
3385 u16 pf_vf_num, swid, vsi_port_num;
3389 vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) &
3390 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
3392 pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) &
3393 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
3395 swid = LE16_TO_CPU(ele->swid);
3397 if (LE16_TO_CPU(ele->pf_vf_num) &
3398 ICE_AQC_GET_SW_CONF_RESP_IS_VF)
3401 res_type = (u8)(LE16_TO_CPU(ele->vsi_port_num) >>
3402 ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
3405 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
3406 case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT:
3407 if (j == num_total_ports) {
3408 ice_debug(hw, ICE_DBG_SW, "more ports than expected\n");
3409 status = ICE_ERR_CFG;
3412 ice_init_port_info(hw->port_info,
3413 vsi_port_num, res_type, swid,
3421 } while (req_desc && !status);
3429 * ice_fill_sw_info - Helper function to populate lb_en and lan_en
3430 * @hw: pointer to the hardware structure
3431 * @fi: filter info structure to fill/update
3433 * This helper function populates the lb_en and lan_en elements of the provided
3434 * ice_fltr_info struct using the switch's type and characteristics of the
3435 * switch rule being configured.
3437 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
3439 if ((fi->flag & ICE_FLTR_RX) &&
3440 (fi->fltr_act == ICE_FWD_TO_VSI ||
3441 fi->fltr_act == ICE_FWD_TO_VSI_LIST) &&
3442 fi->lkup_type == ICE_SW_LKUP_LAST)
3446 if ((fi->flag & ICE_FLTR_TX) &&
3447 (fi->fltr_act == ICE_FWD_TO_VSI ||
3448 fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
3449 fi->fltr_act == ICE_FWD_TO_Q ||
3450 fi->fltr_act == ICE_FWD_TO_QGRP)) {
3451 /* Setting LB for prune actions will result in replicated
3452 * packets to the internal switch that will be dropped.
3454 if (fi->lkup_type != ICE_SW_LKUP_VLAN)
3457 /* Set lan_en to TRUE if
3458 * 1. The switch is a VEB AND
3460 * 2.1 The lookup is a directional lookup like ethertype,
3461 * promiscuous, ethertype-MAC, promiscuous-VLAN
3462 * and default-port OR
3463 * 2.2 The lookup is VLAN, OR
3464 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
3465 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
3469 * The switch is a VEPA.
3471 * In all other cases, the LAN enable has to be set to false.
3474 if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
3475 fi->lkup_type == ICE_SW_LKUP_PROMISC ||
3476 fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
3477 fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
3478 fi->lkup_type == ICE_SW_LKUP_DFLT ||
3479 fi->lkup_type == ICE_SW_LKUP_VLAN ||
3480 (fi->lkup_type == ICE_SW_LKUP_MAC &&
3481 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) ||
3482 (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
3483 !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)))
3492 * ice_fill_sw_rule - Helper function to fill switch rule structure
3493 * @hw: pointer to the hardware structure
3494 * @f_info: entry containing packet forwarding information
3495 * @s_rule: switch rule structure to be filled in based on mac_entry
3496 * @opc: switch rules population command type - pass in the command opcode
3499 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
3500 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
3502 u16 vlan_id = ICE_MAX_VLAN_ID + 1;
3503 u16 vlan_tpid = ICE_ETH_P_8021Q;
3511 if (opc == ice_aqc_opc_remove_sw_rules) {
3512 s_rule->pdata.lkup_tx_rx.act = 0;
3513 s_rule->pdata.lkup_tx_rx.index =
3514 CPU_TO_LE16(f_info->fltr_rule_id);
3515 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
3519 eth_hdr_sz = sizeof(dummy_eth_header);
3520 eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
3522 /* initialize the ether header with a dummy header */
3523 ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA);
3524 ice_fill_sw_info(hw, f_info);
3526 switch (f_info->fltr_act) {
3527 case ICE_FWD_TO_VSI:
3528 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
3529 ICE_SINGLE_ACT_VSI_ID_M;
3530 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
3531 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
3532 ICE_SINGLE_ACT_VALID_BIT;
3534 case ICE_FWD_TO_VSI_LIST:
3535 act |= ICE_SINGLE_ACT_VSI_LIST;
3536 act |= (f_info->fwd_id.vsi_list_id <<
3537 ICE_SINGLE_ACT_VSI_LIST_ID_S) &
3538 ICE_SINGLE_ACT_VSI_LIST_ID_M;
3539 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
3540 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
3541 ICE_SINGLE_ACT_VALID_BIT;
3544 act |= ICE_SINGLE_ACT_TO_Q;
3545 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
3546 ICE_SINGLE_ACT_Q_INDEX_M;
3548 case ICE_DROP_PACKET:
3549 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
3550 ICE_SINGLE_ACT_VALID_BIT;
3552 case ICE_FWD_TO_QGRP:
3553 q_rgn = f_info->qgrp_size > 0 ?
3554 (u8)ice_ilog2(f_info->qgrp_size) : 0;
3555 act |= ICE_SINGLE_ACT_TO_Q;
3556 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
3557 ICE_SINGLE_ACT_Q_INDEX_M;
3558 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
3559 ICE_SINGLE_ACT_Q_REGION_M;
3566 act |= ICE_SINGLE_ACT_LB_ENABLE;
3568 act |= ICE_SINGLE_ACT_LAN_ENABLE;
3570 switch (f_info->lkup_type) {
3571 case ICE_SW_LKUP_MAC:
3572 daddr = f_info->l_data.mac.mac_addr;
3574 case ICE_SW_LKUP_VLAN:
3575 vlan_id = f_info->l_data.vlan.vlan_id;
3576 if (f_info->l_data.vlan.tpid_valid)
3577 vlan_tpid = f_info->l_data.vlan.tpid;
3578 if (f_info->fltr_act == ICE_FWD_TO_VSI ||
3579 f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
3580 act |= ICE_SINGLE_ACT_PRUNE;
3581 act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
3584 case ICE_SW_LKUP_ETHERTYPE_MAC:
3585 daddr = f_info->l_data.ethertype_mac.mac_addr;
3587 case ICE_SW_LKUP_ETHERTYPE:
3588 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
3589 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype);
3591 case ICE_SW_LKUP_MAC_VLAN:
3592 daddr = f_info->l_data.mac_vlan.mac_addr;
3593 vlan_id = f_info->l_data.mac_vlan.vlan_id;
3595 case ICE_SW_LKUP_PROMISC_VLAN:
3596 vlan_id = f_info->l_data.mac_vlan.vlan_id;
3598 case ICE_SW_LKUP_PROMISC:
3599 daddr = f_info->l_data.mac_vlan.mac_addr;
3605 s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
3606 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) :
3607 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
3609 /* Recipe set depending on lookup type */
3610 s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type);
3611 s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src);
3612 s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
3615 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN,
3616 ICE_NONDMA_TO_NONDMA);
3618 if (!(vlan_id > ICE_MAX_VLAN_ID)) {
3619 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
3620 *off = CPU_TO_BE16(vlan_id);
3621 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
3622 *off = CPU_TO_BE16(vlan_tpid);
3625 /* Create the switch rule with the final dummy Ethernet header */
3626 if (opc != ice_aqc_opc_update_sw_rules)
3627 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz);
3631 * ice_add_marker_act
3632 * @hw: pointer to the hardware structure
3633 * @m_ent: the management entry for which sw marker needs to be added
3634 * @sw_marker: sw marker to tag the Rx descriptor with
3635 * @l_id: large action resource ID
3637 * Create a large action to hold software marker and update the switch rule
3638 * entry pointed by m_ent with newly created large action
3640 static enum ice_status
3641 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
3642 u16 sw_marker, u16 l_id)
3644 struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
3645 /* For software marker we need 3 large actions
3646 * 1. FWD action: FWD TO VSI or VSI LIST
3647 * 2. GENERIC VALUE action to hold the profile ID
3648 * 3. GENERIC VALUE action to hold the software marker ID
3650 const u16 num_lg_acts = 3;
3651 enum ice_status status;
3657 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
3658 return ICE_ERR_PARAM;
3660 /* Create two back-to-back switch rules and submit them to the HW using
3661 * one memory buffer:
3665 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
3666 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
3667 lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
3669 return ICE_ERR_NO_MEMORY;
3671 rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
3673 /* Fill in the first switch rule i.e. large action */
3674 lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
3675 lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
3676 lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts);
3678 /* First action VSI forwarding or VSI list forwarding depending on how
3681 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
3682 m_ent->fltr_info.fwd_id.hw_vsi_id;
3684 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
3685 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
3686 if (m_ent->vsi_count > 1)
3687 act |= ICE_LG_ACT_VSI_LIST;
3688 lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
3690 /* Second action descriptor type */
3691 act = ICE_LG_ACT_GENERIC;
3693 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
3694 lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
3696 act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
3697 ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
3699 /* Third action Marker value */
3700 act |= ICE_LG_ACT_GENERIC;
3701 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
3702 ICE_LG_ACT_GENERIC_VALUE_M;
3704 lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act);
3706 /* call the fill switch rule to fill the lookup Tx Rx structure */
3707 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
3708 ice_aqc_opc_update_sw_rules);
3710 /* Update the action to point to the large action ID */
3711 rx_tx->pdata.lkup_tx_rx.act =
3712 CPU_TO_LE32(ICE_SINGLE_ACT_PTR |
3713 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
3714 ICE_SINGLE_ACT_PTR_VAL_M));
3716 /* Use the filter rule ID of the previously created rule with single
3717 * act. Once the update happens, hardware will treat this as large
3720 rx_tx->pdata.lkup_tx_rx.index =
3721 CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id);
3723 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
3724 ice_aqc_opc_update_sw_rules, NULL);
3726 m_ent->lg_act_idx = l_id;
3727 m_ent->sw_marker_id = sw_marker;
3730 ice_free(hw, lg_act);
3735 * ice_add_counter_act - add/update filter rule with counter action
3736 * @hw: pointer to the hardware structure
3737 * @m_ent: the management entry for which counter needs to be added
3738 * @counter_id: VLAN counter ID returned as part of allocate resource
3739 * @l_id: large action resource ID
3741 static enum ice_status
3742 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
3743 u16 counter_id, u16 l_id)
3745 struct ice_aqc_sw_rules_elem *lg_act;
3746 struct ice_aqc_sw_rules_elem *rx_tx;
3747 enum ice_status status;
3748 /* 2 actions will be added while adding a large action counter */
3749 const int num_acts = 2;
3756 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
3757 return ICE_ERR_PARAM;
3759 /* Create two back-to-back switch rules and submit them to the HW using
3760 * one memory buffer:
3764 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_acts);
3765 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
3766 lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
3768 return ICE_ERR_NO_MEMORY;
3770 rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
3772 /* Fill in the first switch rule i.e. large action */
3773 lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
3774 lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
3775 lg_act->pdata.lg_act.size = CPU_TO_LE16(num_acts);
3777 /* First action VSI forwarding or VSI list forwarding depending on how
3780 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
3781 m_ent->fltr_info.fwd_id.hw_vsi_id;
3783 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
3784 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
3785 ICE_LG_ACT_VSI_LIST_ID_M;
3786 if (m_ent->vsi_count > 1)
3787 act |= ICE_LG_ACT_VSI_LIST;
3788 lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
3790 /* Second action counter ID */
3791 act = ICE_LG_ACT_STAT_COUNT;
3792 act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) &
3793 ICE_LG_ACT_STAT_COUNT_M;
3794 lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
3796 /* call the fill switch rule to fill the lookup Tx Rx structure */
3797 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
3798 ice_aqc_opc_update_sw_rules);
3800 act = ICE_SINGLE_ACT_PTR;
3801 act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M;
3802 rx_tx->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
3804 /* Use the filter rule ID of the previously created rule with single
3805 * act. Once the update happens, hardware will treat this as large
3808 f_rule_id = m_ent->fltr_info.fltr_rule_id;
3809 rx_tx->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_rule_id);
3811 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
3812 ice_aqc_opc_update_sw_rules, NULL);
3814 m_ent->lg_act_idx = l_id;
3815 m_ent->counter_index = counter_id;
3818 ice_free(hw, lg_act);
3823 * ice_create_vsi_list_map
3824 * @hw: pointer to the hardware structure
3825 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
3826 * @num_vsi: number of VSI handles in the array
3827 * @vsi_list_id: VSI list ID generated as part of allocate resource
3829 * Helper function to create a new entry of VSI list ID to VSI mapping
3830 * using the given VSI list ID
3832 static struct ice_vsi_list_map_info *
3833 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
3836 struct ice_switch_info *sw = hw->switch_info;
3837 struct ice_vsi_list_map_info *v_map;
3840 v_map = (struct ice_vsi_list_map_info *)ice_malloc(hw, sizeof(*v_map));
3844 v_map->vsi_list_id = vsi_list_id;
3846 for (i = 0; i < num_vsi; i++)
3847 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map);
3849 LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head);
3854 * ice_update_vsi_list_rule
3855 * @hw: pointer to the hardware structure
3856 * @vsi_handle_arr: array of VSI handles to form a VSI list
3857 * @num_vsi: number of VSI handles in the array
3858 * @vsi_list_id: VSI list ID generated as part of allocate resource
3859 * @remove: Boolean value to indicate if this is a remove action
3860 * @opc: switch rules population command type - pass in the command opcode
3861 * @lkup_type: lookup type of the filter
3863 * Call AQ command to add a new switch rule or update existing switch rule
3864 * using the given VSI list ID
3866 static enum ice_status
3867 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
3868 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
3869 enum ice_sw_lkup_type lkup_type)
3871 struct ice_aqc_sw_rules_elem *s_rule;
3872 enum ice_status status;
3878 return ICE_ERR_PARAM;
3880 if (lkup_type == ICE_SW_LKUP_MAC ||
3881 lkup_type == ICE_SW_LKUP_MAC_VLAN ||
3882 lkup_type == ICE_SW_LKUP_ETHERTYPE ||
3883 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
3884 lkup_type == ICE_SW_LKUP_PROMISC ||
3885 lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
3886 lkup_type == ICE_SW_LKUP_LAST)
3887 rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
3888 ICE_AQC_SW_RULES_T_VSI_LIST_SET;
3889 else if (lkup_type == ICE_SW_LKUP_VLAN)
3890 rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
3891 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
3893 return ICE_ERR_PARAM;
3895 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
3896 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
3898 return ICE_ERR_NO_MEMORY;
3899 for (i = 0; i < num_vsi; i++) {
3900 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
3901 status = ICE_ERR_PARAM;
3904 /* AQ call requires hw_vsi_id(s) */
3905 s_rule->pdata.vsi_list.vsi[i] =
3906 CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
3909 s_rule->type = CPU_TO_LE16(rule_type);
3910 s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi);
3911 s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
3913 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
3916 ice_free(hw, s_rule);
3921 * ice_create_vsi_list_rule - Creates and populates a VSI list rule
3922 * @hw: pointer to the HW struct
3923 * @vsi_handle_arr: array of VSI handles to form a VSI list
3924 * @num_vsi: number of VSI handles in the array
3925 * @vsi_list_id: stores the ID of the VSI list to be created
3926 * @lkup_type: switch rule filter's lookup type
3928 static enum ice_status
3929 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
3930 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
3932 enum ice_status status;
3934 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
3935 ice_aqc_opc_alloc_res);
3939 /* Update the newly created VSI list to include the specified VSIs */
3940 return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
3941 *vsi_list_id, false,
3942 ice_aqc_opc_add_sw_rules, lkup_type);
3946 * ice_create_pkt_fwd_rule
3947 * @hw: pointer to the hardware structure
3948 * @recp_list: corresponding filter management list
3949 * @f_entry: entry containing packet forwarding information
3951 * Create switch rule with given filter information and add an entry
3952 * to the corresponding filter management list to track this switch rule
3955 static enum ice_status
3956 ice_create_pkt_fwd_rule(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
3957 struct ice_fltr_list_entry *f_entry)
3959 struct ice_fltr_mgmt_list_entry *fm_entry;
3960 struct ice_aqc_sw_rules_elem *s_rule;
3961 enum ice_status status;
3963 s_rule = (struct ice_aqc_sw_rules_elem *)
3964 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
3966 return ICE_ERR_NO_MEMORY;
3967 fm_entry = (struct ice_fltr_mgmt_list_entry *)
3968 ice_malloc(hw, sizeof(*fm_entry));
3970 status = ICE_ERR_NO_MEMORY;
3971 goto ice_create_pkt_fwd_rule_exit;
3974 fm_entry->fltr_info = f_entry->fltr_info;
3976 /* Initialize all the fields for the management entry */
3977 fm_entry->vsi_count = 1;
3978 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
3979 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
3980 fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
3982 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
3983 ice_aqc_opc_add_sw_rules);
3985 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
3986 ice_aqc_opc_add_sw_rules, NULL);
3988 ice_free(hw, fm_entry);
3989 goto ice_create_pkt_fwd_rule_exit;
3992 f_entry->fltr_info.fltr_rule_id =
3993 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
3994 fm_entry->fltr_info.fltr_rule_id =
3995 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
3997 /* The book keeping entries will get removed when base driver
3998 * calls remove filter AQ command
4000 LIST_ADD(&fm_entry->list_entry, &recp_list->filt_rules);
4002 ice_create_pkt_fwd_rule_exit:
4003 ice_free(hw, s_rule);
4008 * ice_update_pkt_fwd_rule
4009 * @hw: pointer to the hardware structure
4010 * @f_info: filter information for switch rule
4012 * Call AQ command to update a previously created switch rule with a
4015 static enum ice_status
4016 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
4018 struct ice_aqc_sw_rules_elem *s_rule;
4019 enum ice_status status;
4021 s_rule = (struct ice_aqc_sw_rules_elem *)
4022 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
4024 return ICE_ERR_NO_MEMORY;
4026 ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
4028 s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id);
4030 /* Update switch rule with new rule set to forward VSI list */
4031 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
4032 ice_aqc_opc_update_sw_rules, NULL);
4034 ice_free(hw, s_rule);
4039 * ice_update_sw_rule_bridge_mode
4040 * @hw: pointer to the HW struct
4042 * Updates unicast switch filter rules based on VEB/VEPA mode
4044 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
4046 struct ice_switch_info *sw = hw->switch_info;
4047 struct ice_fltr_mgmt_list_entry *fm_entry;
4048 enum ice_status status = ICE_SUCCESS;
4049 struct LIST_HEAD_TYPE *rule_head;
4050 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
4052 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
4053 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
4055 ice_acquire_lock(rule_lock);
4056 LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry,
4058 struct ice_fltr_info *fi = &fm_entry->fltr_info;
4059 u8 *addr = fi->l_data.mac.mac_addr;
4061 /* Update unicast Tx rules to reflect the selected
4064 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) &&
4065 (fi->fltr_act == ICE_FWD_TO_VSI ||
4066 fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
4067 fi->fltr_act == ICE_FWD_TO_Q ||
4068 fi->fltr_act == ICE_FWD_TO_QGRP)) {
4069 status = ice_update_pkt_fwd_rule(hw, fi);
4075 ice_release_lock(rule_lock);
4081 * ice_add_update_vsi_list
4082 * @hw: pointer to the hardware structure
4083 * @m_entry: pointer to current filter management list entry
4084 * @cur_fltr: filter information from the book keeping entry
4085 * @new_fltr: filter information with the new VSI to be added
4087 * Call AQ command to add or update previously created VSI list with new VSI.
4089 * Helper function to do book keeping associated with adding filter information
4090 * The algorithm to do the book keeping is described below :
4091 * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
4092 * if only one VSI has been added till now
4093 * Allocate a new VSI list and add two VSIs
4094 * to this list using switch rule command
4095 * Update the previously created switch rule with the
4096 * newly created VSI list ID
4097 * if a VSI list was previously created
4098 * Add the new VSI to the previously created VSI list set
4099 * using the update switch rule command
4101 static enum ice_status
4102 ice_add_update_vsi_list(struct ice_hw *hw,
4103 struct ice_fltr_mgmt_list_entry *m_entry,
4104 struct ice_fltr_info *cur_fltr,
4105 struct ice_fltr_info *new_fltr)
4107 enum ice_status status = ICE_SUCCESS;
4108 u16 vsi_list_id = 0;
4110 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
4111 cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
4112 return ICE_ERR_NOT_IMPL;
4114 if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
4115 new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
4116 (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
4117 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
4118 return ICE_ERR_NOT_IMPL;
4120 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
4121 /* Only one entry existed in the mapping and it was not already
4122 * a part of a VSI list. So, create a VSI list with the old and
4125 struct ice_fltr_info tmp_fltr;
4126 u16 vsi_handle_arr[2];
4128 /* A rule already exists with the new VSI being added */
4129 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
4130 return ICE_ERR_ALREADY_EXISTS;
4132 vsi_handle_arr[0] = cur_fltr->vsi_handle;
4133 vsi_handle_arr[1] = new_fltr->vsi_handle;
4134 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
4136 new_fltr->lkup_type);
4140 tmp_fltr = *new_fltr;
4141 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
4142 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
4143 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
4144 /* Update the previous switch rule of "MAC forward to VSI" to
4145 * "MAC fwd to VSI list"
4147 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
4151 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
4152 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
4153 m_entry->vsi_list_info =
4154 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
4157 if (!m_entry->vsi_list_info)
4158 return ICE_ERR_NO_MEMORY;
4160 /* If this entry was large action then the large action needs
4161 * to be updated to point to FWD to VSI list
4163 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
4165 ice_add_marker_act(hw, m_entry,
4166 m_entry->sw_marker_id,
4167 m_entry->lg_act_idx);
4169 u16 vsi_handle = new_fltr->vsi_handle;
4170 enum ice_adminq_opc opcode;
4172 if (!m_entry->vsi_list_info)
4175 /* A rule already exists with the new VSI being added */
4176 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
4179 /* Update the previously created VSI list set with
4180 * the new VSI ID passed in
4182 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
4183 opcode = ice_aqc_opc_update_sw_rules;
4185 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
4186 vsi_list_id, false, opcode,
4187 new_fltr->lkup_type);
4188 /* update VSI list mapping info with new VSI ID */
4190 ice_set_bit(vsi_handle,
4191 m_entry->vsi_list_info->vsi_map);
4194 m_entry->vsi_count++;
4199 * ice_find_rule_entry - Search a rule entry
4200 * @list_head: head of rule list
4201 * @f_info: rule information
4203 * Helper function to search for a given rule entry
4204 * Returns pointer to entry storing the rule if found
4206 static struct ice_fltr_mgmt_list_entry *
4207 ice_find_rule_entry(struct LIST_HEAD_TYPE *list_head,
4208 struct ice_fltr_info *f_info)
4210 struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
4212 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
4214 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
4215 sizeof(f_info->l_data)) &&
4216 f_info->flag == list_itr->fltr_info.flag) {
4225 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
4226 * @recp_list: VSI lists needs to be searched
4227 * @vsi_handle: VSI handle to be found in VSI list
4228 * @vsi_list_id: VSI list ID found containing vsi_handle
4230 * Helper function to search a VSI list with single entry containing given VSI
4231 * handle element. This can be extended further to search VSI list with more
4232 * than 1 vsi_count. Returns pointer to VSI list entry if found.
4234 static struct ice_vsi_list_map_info *
4235 ice_find_vsi_list_entry(struct ice_sw_recipe *recp_list, u16 vsi_handle,
4238 struct ice_vsi_list_map_info *map_info = NULL;
4239 struct LIST_HEAD_TYPE *list_head;
4241 list_head = &recp_list->filt_rules;
4242 if (recp_list->adv_rule) {
4243 struct ice_adv_fltr_mgmt_list_entry *list_itr;
4245 LIST_FOR_EACH_ENTRY(list_itr, list_head,
4246 ice_adv_fltr_mgmt_list_entry,
4248 if (list_itr->vsi_list_info) {
4249 map_info = list_itr->vsi_list_info;
4250 if (ice_is_bit_set(map_info->vsi_map,
4252 *vsi_list_id = map_info->vsi_list_id;
4258 struct ice_fltr_mgmt_list_entry *list_itr;
4260 LIST_FOR_EACH_ENTRY(list_itr, list_head,
4261 ice_fltr_mgmt_list_entry,
4263 if (list_itr->vsi_count == 1 &&
4264 list_itr->vsi_list_info) {
4265 map_info = list_itr->vsi_list_info;
4266 if (ice_is_bit_set(map_info->vsi_map,
4268 *vsi_list_id = map_info->vsi_list_id;
4278 * ice_add_rule_internal - add rule for a given lookup type
4279 * @hw: pointer to the hardware structure
4280 * @recp_list: recipe list for which rule has to be added
4281 * @lport: logic port number on which function add rule
4282 * @f_entry: structure containing MAC forwarding information
4284 * Adds or updates the rule lists for a given recipe
4286 static enum ice_status
4287 ice_add_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
4288 u8 lport, struct ice_fltr_list_entry *f_entry)
4290 struct ice_fltr_info *new_fltr, *cur_fltr;
4291 struct ice_fltr_mgmt_list_entry *m_entry;
4292 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
4293 enum ice_status status = ICE_SUCCESS;
4295 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
4296 return ICE_ERR_PARAM;
4298 /* Load the hw_vsi_id only if the fwd action is fwd to VSI */
4299 if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI)
4300 f_entry->fltr_info.fwd_id.hw_vsi_id =
4301 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
4303 rule_lock = &recp_list->filt_rule_lock;
4305 ice_acquire_lock(rule_lock);
4306 new_fltr = &f_entry->fltr_info;
4307 if (new_fltr->flag & ICE_FLTR_RX)
4308 new_fltr->src = lport;
4309 else if (new_fltr->flag & ICE_FLTR_TX)
4311 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
4313 m_entry = ice_find_rule_entry(&recp_list->filt_rules, new_fltr);
4315 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry);
4316 goto exit_add_rule_internal;
4319 cur_fltr = &m_entry->fltr_info;
4320 status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
4322 exit_add_rule_internal:
4323 ice_release_lock(rule_lock);
4328 * ice_remove_vsi_list_rule
4329 * @hw: pointer to the hardware structure
4330 * @vsi_list_id: VSI list ID generated as part of allocate resource
4331 * @lkup_type: switch rule filter lookup type
4333 * The VSI list should be emptied before this function is called to remove the
4336 static enum ice_status
4337 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
4338 enum ice_sw_lkup_type lkup_type)
4340 /* Free the vsi_list resource that we allocated. It is assumed that the
4341 * list is empty at this point.
4343 return ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
4344 ice_aqc_opc_free_res);
4348 * ice_rem_update_vsi_list
4349 * @hw: pointer to the hardware structure
4350 * @vsi_handle: VSI handle of the VSI to remove
4351 * @fm_list: filter management entry for which the VSI list management needs to
4354 static enum ice_status
4355 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
4356 struct ice_fltr_mgmt_list_entry *fm_list)
4358 enum ice_sw_lkup_type lkup_type;
4359 enum ice_status status = ICE_SUCCESS;
4362 if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
4363 fm_list->vsi_count == 0)
4364 return ICE_ERR_PARAM;
4366 /* A rule with the VSI being removed does not exist */
4367 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
4368 return ICE_ERR_DOES_NOT_EXIST;
4370 lkup_type = fm_list->fltr_info.lkup_type;
4371 vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
4372 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
4373 ice_aqc_opc_update_sw_rules,
4378 fm_list->vsi_count--;
4379 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
4381 if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
4382 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
4383 struct ice_vsi_list_map_info *vsi_list_info =
4384 fm_list->vsi_list_info;
4387 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
4389 if (!ice_is_vsi_valid(hw, rem_vsi_handle))
4390 return ICE_ERR_OUT_OF_RANGE;
4392 /* Make sure VSI list is empty before removing it below */
4393 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
4395 ice_aqc_opc_update_sw_rules,
4400 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
4401 tmp_fltr_info.fwd_id.hw_vsi_id =
4402 ice_get_hw_vsi_num(hw, rem_vsi_handle);
4403 tmp_fltr_info.vsi_handle = rem_vsi_handle;
4404 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
4406 ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
4407 tmp_fltr_info.fwd_id.hw_vsi_id, status);
4411 fm_list->fltr_info = tmp_fltr_info;
4414 if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
4415 (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
4416 struct ice_vsi_list_map_info *vsi_list_info =
4417 fm_list->vsi_list_info;
4419 /* Remove the VSI list since it is no longer used */
4420 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
4422 ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
4423 vsi_list_id, status);
4427 LIST_DEL(&vsi_list_info->list_entry);
4428 ice_free(hw, vsi_list_info);
4429 fm_list->vsi_list_info = NULL;
4436 * ice_remove_rule_internal - Remove a filter rule of a given type
4438 * @hw: pointer to the hardware structure
4439 * @recp_list: recipe list for which the rule needs to removed
4440 * @f_entry: rule entry containing filter information
4442 static enum ice_status
4443 ice_remove_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
4444 struct ice_fltr_list_entry *f_entry)
4446 struct ice_fltr_mgmt_list_entry *list_elem;
4447 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
4448 enum ice_status status = ICE_SUCCESS;
4449 bool remove_rule = false;
4452 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
4453 return ICE_ERR_PARAM;
4454 f_entry->fltr_info.fwd_id.hw_vsi_id =
4455 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
4457 rule_lock = &recp_list->filt_rule_lock;
4458 ice_acquire_lock(rule_lock);
4459 list_elem = ice_find_rule_entry(&recp_list->filt_rules,
4460 &f_entry->fltr_info);
4462 status = ICE_ERR_DOES_NOT_EXIST;
4466 if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
4468 } else if (!list_elem->vsi_list_info) {
4469 status = ICE_ERR_DOES_NOT_EXIST;
4471 } else if (list_elem->vsi_list_info->ref_cnt > 1) {
4472 /* a ref_cnt > 1 indicates that the vsi_list is being
4473 * shared by multiple rules. Decrement the ref_cnt and
4474 * remove this rule, but do not modify the list, as it
4475 * is in-use by other rules.
4477 list_elem->vsi_list_info->ref_cnt--;
4480 /* a ref_cnt of 1 indicates the vsi_list is only used
4481 * by one rule. However, the original removal request is only
4482 * for a single VSI. Update the vsi_list first, and only
4483 * remove the rule if there are no further VSIs in this list.
4485 vsi_handle = f_entry->fltr_info.vsi_handle;
4486 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
4489 /* if VSI count goes to zero after updating the VSI list */
4490 if (list_elem->vsi_count == 0)
4495 /* Remove the lookup rule */
4496 struct ice_aqc_sw_rules_elem *s_rule;
4498 s_rule = (struct ice_aqc_sw_rules_elem *)
4499 ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE);
4501 status = ICE_ERR_NO_MEMORY;
4505 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
4506 ice_aqc_opc_remove_sw_rules);
4508 status = ice_aq_sw_rules(hw, s_rule,
4509 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
4510 ice_aqc_opc_remove_sw_rules, NULL);
4512 /* Remove a book keeping from the list */
4513 ice_free(hw, s_rule);
4518 LIST_DEL(&list_elem->list_entry);
4519 ice_free(hw, list_elem);
4522 ice_release_lock(rule_lock);
4527 * ice_aq_get_res_alloc - get allocated resources
4528 * @hw: pointer to the HW struct
4529 * @num_entries: pointer to u16 to store the number of resource entries returned
4530 * @buf: pointer to buffer
4531 * @buf_size: size of buf
4532 * @cd: pointer to command details structure or NULL
4534 * The caller-supplied buffer must be large enough to store the resource
4535 * information for all resource types. Each resource type is an
4536 * ice_aqc_get_res_resp_elem structure.
4539 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries,
4540 struct ice_aqc_get_res_resp_elem *buf, u16 buf_size,
4541 struct ice_sq_cd *cd)
4543 struct ice_aqc_get_res_alloc *resp;
4544 enum ice_status status;
4545 struct ice_aq_desc desc;
4548 return ICE_ERR_BAD_PTR;
4550 if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN)
4551 return ICE_ERR_INVAL_SIZE;
4553 resp = &desc.params.get_res;
4555 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc);
4556 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
4558 if (!status && num_entries)
4559 *num_entries = LE16_TO_CPU(resp->resp_elem_num);
4565 * ice_aq_get_res_descs - get allocated resource descriptors
4566 * @hw: pointer to the hardware structure
4567 * @num_entries: number of resource entries in buffer
4568 * @buf: structure to hold response data buffer
4569 * @buf_size: size of buffer
4570 * @res_type: resource type
4571 * @res_shared: is resource shared
4572 * @desc_id: input - first desc ID to start; output - next desc ID
4573 * @cd: pointer to command details structure or NULL
4576 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,
4577 struct ice_aqc_res_elem *buf, u16 buf_size, u16 res_type,
4578 bool res_shared, u16 *desc_id, struct ice_sq_cd *cd)
4580 struct ice_aqc_get_allocd_res_desc *cmd;
4581 struct ice_aq_desc desc;
4582 enum ice_status status;
4584 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
4586 cmd = &desc.params.get_res_desc;
4589 return ICE_ERR_PARAM;
4591 if (buf_size != (num_entries * sizeof(*buf)))
4592 return ICE_ERR_PARAM;
4594 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc);
4596 cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) &
4597 ICE_AQC_RES_TYPE_M) | (res_shared ?
4598 ICE_AQC_RES_TYPE_FLAG_SHARED : 0));
4599 cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id);
4601 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
4603 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc);
4609 * ice_add_mac_rule - Add a MAC address based filter rule
4610 * @hw: pointer to the hardware structure
4611 * @m_list: list of MAC addresses and forwarding information
4612 * @sw: pointer to switch info struct for which function add rule
4613 * @lport: logic port number on which function add rule
4615 * IMPORTANT: When the ucast_shared flag is set to false and m_list has
4616 * multiple unicast addresses, the function assumes that all the
4617 * addresses are unique in a given add_mac call. It doesn't
4618 * check for duplicates in this case, removing duplicates from a given
4619 * list should be taken care of in the caller of this function.
4621 static enum ice_status
4622 ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
4623 struct ice_switch_info *sw, u8 lport)
4625 struct ice_sw_recipe *recp_list = &sw->recp_list[ICE_SW_LKUP_MAC];
4626 struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
4627 struct ice_fltr_list_entry *m_list_itr;
4628 struct LIST_HEAD_TYPE *rule_head;
4629 u16 total_elem_left, s_rule_size;
4630 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
4631 enum ice_status status = ICE_SUCCESS;
4632 u16 num_unicast = 0;
4636 rule_lock = &recp_list->filt_rule_lock;
4637 rule_head = &recp_list->filt_rules;
4639 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
4641 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
4645 m_list_itr->fltr_info.flag = ICE_FLTR_TX;
4646 vsi_handle = m_list_itr->fltr_info.vsi_handle;
4647 if (!ice_is_vsi_valid(hw, vsi_handle))
4648 return ICE_ERR_PARAM;
4649 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
4650 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
4651 /* update the src in case it is VSI num */
4652 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
4653 return ICE_ERR_PARAM;
4654 m_list_itr->fltr_info.src = hw_vsi_id;
4655 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
4656 IS_ZERO_ETHER_ADDR(add))
4657 return ICE_ERR_PARAM;
4658 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
4659 /* Don't overwrite the unicast address */
4660 ice_acquire_lock(rule_lock);
4661 if (ice_find_rule_entry(rule_head,
4662 &m_list_itr->fltr_info)) {
4663 ice_release_lock(rule_lock);
4664 return ICE_ERR_ALREADY_EXISTS;
4666 ice_release_lock(rule_lock);
4668 } else if (IS_MULTICAST_ETHER_ADDR(add) ||
4669 (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) {
4670 m_list_itr->status =
4671 ice_add_rule_internal(hw, recp_list, lport,
4673 if (m_list_itr->status)
4674 return m_list_itr->status;
4678 ice_acquire_lock(rule_lock);
4679 /* Exit if no suitable entries were found for adding bulk switch rule */
4681 status = ICE_SUCCESS;
4682 goto ice_add_mac_exit;
4685 /* Allocate switch rule buffer for the bulk update for unicast */
4686 s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
4687 s_rule = (struct ice_aqc_sw_rules_elem *)
4688 ice_calloc(hw, num_unicast, s_rule_size);
4690 status = ICE_ERR_NO_MEMORY;
4691 goto ice_add_mac_exit;
4695 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
4697 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
4698 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
4700 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
4701 ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
4702 ice_aqc_opc_add_sw_rules);
4703 r_iter = (struct ice_aqc_sw_rules_elem *)
4704 ((u8 *)r_iter + s_rule_size);
4708 /* Call AQ bulk switch rule update for all unicast addresses */
4710 /* Call AQ switch rule in AQ_MAX chunk */
4711 for (total_elem_left = num_unicast; total_elem_left > 0;
4712 total_elem_left -= elem_sent) {
4713 struct ice_aqc_sw_rules_elem *entry = r_iter;
4715 elem_sent = MIN_T(u8, total_elem_left,
4716 (ICE_AQ_MAX_BUF_LEN / s_rule_size));
4717 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
4718 elem_sent, ice_aqc_opc_add_sw_rules,
4721 goto ice_add_mac_exit;
4722 r_iter = (struct ice_aqc_sw_rules_elem *)
4723 ((u8 *)r_iter + (elem_sent * s_rule_size));
4726 /* Fill up rule ID based on the value returned from FW */
4728 LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
4730 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
4731 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
4732 struct ice_fltr_mgmt_list_entry *fm_entry;
4734 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
4735 f_info->fltr_rule_id =
4736 LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index);
4737 f_info->fltr_act = ICE_FWD_TO_VSI;
4738 /* Create an entry to track this MAC address */
4739 fm_entry = (struct ice_fltr_mgmt_list_entry *)
4740 ice_malloc(hw, sizeof(*fm_entry));
4742 status = ICE_ERR_NO_MEMORY;
4743 goto ice_add_mac_exit;
4745 fm_entry->fltr_info = *f_info;
4746 fm_entry->vsi_count = 1;
4747 /* The book keeping entries will get removed when
4748 * base driver calls remove filter AQ command
4751 LIST_ADD(&fm_entry->list_entry, rule_head);
4752 r_iter = (struct ice_aqc_sw_rules_elem *)
4753 ((u8 *)r_iter + s_rule_size);
4758 ice_release_lock(rule_lock);
4760 ice_free(hw, s_rule);
4765 * ice_add_mac - Add a MAC address based filter rule
4766 * @hw: pointer to the hardware structure
4767 * @m_list: list of MAC addresses and forwarding information
4769 * Function add MAC rule for logical port from HW struct
4771 enum ice_status ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
4774 return ICE_ERR_PARAM;
4776 return ice_add_mac_rule(hw, m_list, hw->switch_info,
4777 hw->port_info->lport);
4781 * ice_add_vlan_internal - Add one VLAN based filter rule
4782 * @hw: pointer to the hardware structure
4783 * @recp_list: recipe list for which rule has to be added
4784 * @f_entry: filter entry containing one VLAN information
4786 static enum ice_status
4787 ice_add_vlan_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
4788 struct ice_fltr_list_entry *f_entry)
4790 struct ice_fltr_mgmt_list_entry *v_list_itr;
4791 struct ice_fltr_info *new_fltr, *cur_fltr;
4792 enum ice_sw_lkup_type lkup_type;
4793 u16 vsi_list_id = 0, vsi_handle;
4794 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
4795 enum ice_status status = ICE_SUCCESS;
4797 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
4798 return ICE_ERR_PARAM;
4800 f_entry->fltr_info.fwd_id.hw_vsi_id =
4801 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
4802 new_fltr = &f_entry->fltr_info;
4804 /* VLAN ID should only be 12 bits */
4805 if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
4806 return ICE_ERR_PARAM;
4808 if (new_fltr->src_id != ICE_SRC_ID_VSI)
4809 return ICE_ERR_PARAM;
4811 new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
4812 lkup_type = new_fltr->lkup_type;
4813 vsi_handle = new_fltr->vsi_handle;
4814 rule_lock = &recp_list->filt_rule_lock;
4815 ice_acquire_lock(rule_lock);
4816 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, new_fltr);
4818 struct ice_vsi_list_map_info *map_info = NULL;
4820 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
4821 /* All VLAN pruning rules use a VSI list. Check if
4822 * there is already a VSI list containing VSI that we
4823 * want to add. If found, use the same vsi_list_id for
4824 * this new VLAN rule or else create a new list.
4826 map_info = ice_find_vsi_list_entry(recp_list,
4830 status = ice_create_vsi_list_rule(hw,
4838 /* Convert the action to forwarding to a VSI list. */
4839 new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
4840 new_fltr->fwd_id.vsi_list_id = vsi_list_id;
4843 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry);
4845 v_list_itr = ice_find_rule_entry(&recp_list->filt_rules,
4848 status = ICE_ERR_DOES_NOT_EXIST;
4851 /* reuse VSI list for new rule and increment ref_cnt */
4853 v_list_itr->vsi_list_info = map_info;
4854 map_info->ref_cnt++;
4856 v_list_itr->vsi_list_info =
4857 ice_create_vsi_list_map(hw, &vsi_handle,
4861 } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
4862 /* Update existing VSI list to add new VSI ID only if it used
4865 cur_fltr = &v_list_itr->fltr_info;
4866 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
4869 /* If VLAN rule exists and VSI list being used by this rule is
4870 * referenced by more than 1 VLAN rule. Then create a new VSI
4871 * list appending previous VSI with new VSI and update existing
4872 * VLAN rule to point to new VSI list ID
4874 struct ice_fltr_info tmp_fltr;
4875 u16 vsi_handle_arr[2];
4878 /* Current implementation only supports reusing VSI list with
4879 * one VSI count. We should never hit below condition
4881 if (v_list_itr->vsi_count > 1 &&
4882 v_list_itr->vsi_list_info->ref_cnt > 1) {
4883 ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
4884 status = ICE_ERR_CFG;
4889 ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map,
4892 /* A rule already exists with the new VSI being added */
4893 if (cur_handle == vsi_handle) {
4894 status = ICE_ERR_ALREADY_EXISTS;
4898 vsi_handle_arr[0] = cur_handle;
4899 vsi_handle_arr[1] = vsi_handle;
4900 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
4901 &vsi_list_id, lkup_type);
4905 tmp_fltr = v_list_itr->fltr_info;
4906 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
4907 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
4908 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
4909 /* Update the previous switch rule to a new VSI list which
4910 * includes current VSI that is requested
4912 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
4916 /* before overriding VSI list map info. decrement ref_cnt of
4919 v_list_itr->vsi_list_info->ref_cnt--;
4921 /* now update to newly created list */
4922 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
4923 v_list_itr->vsi_list_info =
4924 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
4926 v_list_itr->vsi_count++;
4930 ice_release_lock(rule_lock);
4935 * ice_add_vlan_rule - Add VLAN based filter rule
4936 * @hw: pointer to the hardware structure
4937 * @v_list: list of VLAN entries and forwarding information
4938 * @sw: pointer to switch info struct for which function add rule
4940 static enum ice_status
4941 ice_add_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
4942 struct ice_switch_info *sw)
4944 struct ice_fltr_list_entry *v_list_itr;
4945 struct ice_sw_recipe *recp_list;
4947 recp_list = &sw->recp_list[ICE_SW_LKUP_VLAN];
4948 LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry,
4950 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
4951 return ICE_ERR_PARAM;
4952 v_list_itr->fltr_info.flag = ICE_FLTR_TX;
4953 v_list_itr->status = ice_add_vlan_internal(hw, recp_list,
4955 if (v_list_itr->status)
4956 return v_list_itr->status;
4962 * ice_add_vlan - Add a VLAN based filter rule
4963 * @hw: pointer to the hardware structure
4964 * @v_list: list of VLAN and forwarding information
4966 * Function add VLAN rule for logical port from HW struct
4968 enum ice_status ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
4971 return ICE_ERR_PARAM;
4973 return ice_add_vlan_rule(hw, v_list, hw->switch_info);
4977 * ice_add_mac_vlan - Add MAC and VLAN pair based filter rule
4978 * @hw: pointer to the hardware structure
4979 * @mv_list: list of MAC and VLAN filters
4980 * @sw: pointer to switch info struct for which function add rule
4981 * @lport: logic port number on which function add rule
4983 * If the VSI on which the MAC-VLAN pair has to be added has Rx and Tx VLAN
4984 * pruning bits enabled, then it is the responsibility of the caller to make
4985 * sure to add a VLAN only filter on the same VSI. Packets belonging to that
4986 * VLAN won't be received on that VSI otherwise.
4988 static enum ice_status
4989 ice_add_mac_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list,
4990 struct ice_switch_info *sw, u8 lport)
4992 struct ice_fltr_list_entry *mv_list_itr;
4993 struct ice_sw_recipe *recp_list;
4995 if (!mv_list || !hw)
4996 return ICE_ERR_PARAM;
4998 recp_list = &sw->recp_list[ICE_SW_LKUP_MAC_VLAN];
4999 LIST_FOR_EACH_ENTRY(mv_list_itr, mv_list, ice_fltr_list_entry,
5001 enum ice_sw_lkup_type l_type =
5002 mv_list_itr->fltr_info.lkup_type;
5004 if (l_type != ICE_SW_LKUP_MAC_VLAN)
5005 return ICE_ERR_PARAM;
5006 mv_list_itr->fltr_info.flag = ICE_FLTR_TX;
5007 mv_list_itr->status =
5008 ice_add_rule_internal(hw, recp_list, lport,
5010 if (mv_list_itr->status)
5011 return mv_list_itr->status;
5017 * ice_add_mac_vlan - Add a MAC VLAN address based filter rule
5018 * @hw: pointer to the hardware structure
5019 * @mv_list: list of MAC VLAN addresses and forwarding information
5021 * Function add MAC VLAN rule for logical port from HW struct
5024 ice_add_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list)
5026 if (!mv_list || !hw)
5027 return ICE_ERR_PARAM;
5029 return ice_add_mac_vlan_rule(hw, mv_list, hw->switch_info,
5030 hw->port_info->lport);
5034 * ice_add_eth_mac_rule - Add ethertype and MAC based filter rule
5035 * @hw: pointer to the hardware structure
5036 * @em_list: list of ether type MAC filter, MAC is optional
5037 * @sw: pointer to switch info struct for which function add rule
5038 * @lport: logic port number on which function add rule
5040 * This function requires the caller to populate the entries in
5041 * the filter list with the necessary fields (including flags to
5042 * indicate Tx or Rx rules).
5044 static enum ice_status
5045 ice_add_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list,
5046 struct ice_switch_info *sw, u8 lport)
5048 struct ice_fltr_list_entry *em_list_itr;
5050 LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry,
5052 struct ice_sw_recipe *recp_list;
5053 enum ice_sw_lkup_type l_type;
5055 l_type = em_list_itr->fltr_info.lkup_type;
5056 recp_list = &sw->recp_list[l_type];
5058 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
5059 l_type != ICE_SW_LKUP_ETHERTYPE)
5060 return ICE_ERR_PARAM;
5062 em_list_itr->status = ice_add_rule_internal(hw, recp_list,
5065 if (em_list_itr->status)
5066 return em_list_itr->status;
5072 * ice_add_eth_mac - Add a ethertype based filter rule
5073 * @hw: pointer to the hardware structure
5074 * @em_list: list of ethertype and forwarding information
5076 * Function add ethertype rule for logical port from HW struct
5079 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
5081 if (!em_list || !hw)
5082 return ICE_ERR_PARAM;
5084 return ice_add_eth_mac_rule(hw, em_list, hw->switch_info,
5085 hw->port_info->lport);
5089 * ice_remove_eth_mac_rule - Remove an ethertype (or MAC) based filter rule
5090 * @hw: pointer to the hardware structure
5091 * @em_list: list of ethertype or ethertype MAC entries
5092 * @sw: pointer to switch info struct for which function add rule
5094 static enum ice_status
5095 ice_remove_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list,
5096 struct ice_switch_info *sw)
5098 struct ice_fltr_list_entry *em_list_itr, *tmp;
5100 LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry,
5102 struct ice_sw_recipe *recp_list;
5103 enum ice_sw_lkup_type l_type;
5105 l_type = em_list_itr->fltr_info.lkup_type;
5107 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
5108 l_type != ICE_SW_LKUP_ETHERTYPE)
5109 return ICE_ERR_PARAM;
5111 recp_list = &sw->recp_list[l_type];
5112 em_list_itr->status = ice_remove_rule_internal(hw, recp_list,
5114 if (em_list_itr->status)
5115 return em_list_itr->status;
5121 * ice_remove_eth_mac - remove a ethertype based filter rule
5122 * @hw: pointer to the hardware structure
5123 * @em_list: list of ethertype and forwarding information
5127 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
5129 if (!em_list || !hw)
5130 return ICE_ERR_PARAM;
5132 return ice_remove_eth_mac_rule(hw, em_list, hw->switch_info);
5136 * ice_rem_sw_rule_info
5137 * @hw: pointer to the hardware structure
5138 * @rule_head: pointer to the switch list structure that we want to delete
5141 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
5143 if (!LIST_EMPTY(rule_head)) {
5144 struct ice_fltr_mgmt_list_entry *entry;
5145 struct ice_fltr_mgmt_list_entry *tmp;
5147 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head,
5148 ice_fltr_mgmt_list_entry, list_entry) {
5149 LIST_DEL(&entry->list_entry);
5150 ice_free(hw, entry);
5156 * ice_rem_adv_rule_info
5157 * @hw: pointer to the hardware structure
5158 * @rule_head: pointer to the switch list structure that we want to delete
5161 ice_rem_adv_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
5163 struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
5164 struct ice_adv_fltr_mgmt_list_entry *lst_itr;
5166 if (LIST_EMPTY(rule_head))
5169 LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry, rule_head,
5170 ice_adv_fltr_mgmt_list_entry, list_entry) {
5171 LIST_DEL(&lst_itr->list_entry);
5172 ice_free(hw, lst_itr->lkups);
5173 ice_free(hw, lst_itr);
5178 * ice_rem_all_sw_rules_info
5179 * @hw: pointer to the hardware structure
5181 void ice_rem_all_sw_rules_info(struct ice_hw *hw)
5183 struct ice_switch_info *sw = hw->switch_info;
5186 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
5187 struct LIST_HEAD_TYPE *rule_head;
5189 rule_head = &sw->recp_list[i].filt_rules;
5190 if (!sw->recp_list[i].adv_rule)
5191 ice_rem_sw_rule_info(hw, rule_head);
5193 ice_rem_adv_rule_info(hw, rule_head);
5194 if (sw->recp_list[i].adv_rule &&
5195 LIST_EMPTY(&sw->recp_list[i].filt_rules))
5196 sw->recp_list[i].adv_rule = false;
5201 * ice_cfg_dflt_vsi - change state of VSI to set/clear default
5202 * @pi: pointer to the port_info structure
5203 * @vsi_handle: VSI handle to set as default
5204 * @set: true to add the above mentioned switch rule, false to remove it
5205 * @direction: ICE_FLTR_RX or ICE_FLTR_TX
5207 * add filter rule to set/unset given VSI as default VSI for the switch
5208 * (represented by swid)
5211 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
5214 struct ice_aqc_sw_rules_elem *s_rule;
5215 struct ice_fltr_info f_info;
5216 struct ice_hw *hw = pi->hw;
5217 enum ice_adminq_opc opcode;
5218 enum ice_status status;
5222 if (!ice_is_vsi_valid(hw, vsi_handle))
5223 return ICE_ERR_PARAM;
5224 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
5226 s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
5227 ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
5229 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
5231 return ICE_ERR_NO_MEMORY;
5233 ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM);
5235 f_info.lkup_type = ICE_SW_LKUP_DFLT;
5236 f_info.flag = direction;
5237 f_info.fltr_act = ICE_FWD_TO_VSI;
5238 f_info.fwd_id.hw_vsi_id = hw_vsi_id;
5240 if (f_info.flag & ICE_FLTR_RX) {
5241 f_info.src = pi->lport;
5242 f_info.src_id = ICE_SRC_ID_LPORT;
5244 f_info.fltr_rule_id =
5245 pi->dflt_rx_vsi_rule_id;
5246 } else if (f_info.flag & ICE_FLTR_TX) {
5247 f_info.src_id = ICE_SRC_ID_VSI;
5248 f_info.src = hw_vsi_id;
5250 f_info.fltr_rule_id =
5251 pi->dflt_tx_vsi_rule_id;
5255 opcode = ice_aqc_opc_add_sw_rules;
5257 opcode = ice_aqc_opc_remove_sw_rules;
5259 ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
5261 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
5262 if (status || !(f_info.flag & ICE_FLTR_TX_RX))
5265 u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
5267 if (f_info.flag & ICE_FLTR_TX) {
5268 pi->dflt_tx_vsi_num = hw_vsi_id;
5269 pi->dflt_tx_vsi_rule_id = index;
5270 } else if (f_info.flag & ICE_FLTR_RX) {
5271 pi->dflt_rx_vsi_num = hw_vsi_id;
5272 pi->dflt_rx_vsi_rule_id = index;
5275 if (f_info.flag & ICE_FLTR_TX) {
5276 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
5277 pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
5278 } else if (f_info.flag & ICE_FLTR_RX) {
5279 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
5280 pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
5285 ice_free(hw, s_rule);
5290 * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
5291 * @list_head: head of rule list
5292 * @f_info: rule information
5294 * Helper function to search for a unicast rule entry - this is to be used
5295 * to remove unicast MAC filter that is not shared with other VSIs on the
5298 * Returns pointer to entry storing the rule if found
5300 static struct ice_fltr_mgmt_list_entry *
5301 ice_find_ucast_rule_entry(struct LIST_HEAD_TYPE *list_head,
5302 struct ice_fltr_info *f_info)
5304 struct ice_fltr_mgmt_list_entry *list_itr;
5306 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
5308 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
5309 sizeof(f_info->l_data)) &&
5310 f_info->fwd_id.hw_vsi_id ==
5311 list_itr->fltr_info.fwd_id.hw_vsi_id &&
5312 f_info->flag == list_itr->fltr_info.flag)
5319 * ice_remove_mac_rule - remove a MAC based filter rule
5320 * @hw: pointer to the hardware structure
5321 * @m_list: list of MAC addresses and forwarding information
5322 * @recp_list: list from which function remove MAC address
5324 * This function removes either a MAC filter rule or a specific VSI from a
5325 * VSI list for a multicast MAC address.
5327 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
5328 * ice_add_mac. Caller should be aware that this call will only work if all
5329 * the entries passed into m_list were added previously. It will not attempt to
5330 * do a partial remove of entries that were found.
5332 static enum ice_status
5333 ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
5334 struct ice_sw_recipe *recp_list)
5336 struct ice_fltr_list_entry *list_itr, *tmp;
5337 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
5340 return ICE_ERR_PARAM;
5342 rule_lock = &recp_list->filt_rule_lock;
5343 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry,
5345 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
5346 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
5349 if (l_type != ICE_SW_LKUP_MAC)
5350 return ICE_ERR_PARAM;
5352 vsi_handle = list_itr->fltr_info.vsi_handle;
5353 if (!ice_is_vsi_valid(hw, vsi_handle))
5354 return ICE_ERR_PARAM;
5356 list_itr->fltr_info.fwd_id.hw_vsi_id =
5357 ice_get_hw_vsi_num(hw, vsi_handle);
5358 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
5359 /* Don't remove the unicast address that belongs to
5360 * another VSI on the switch, since it is not being
5363 ice_acquire_lock(rule_lock);
5364 if (!ice_find_ucast_rule_entry(&recp_list->filt_rules,
5365 &list_itr->fltr_info)) {
5366 ice_release_lock(rule_lock);
5367 return ICE_ERR_DOES_NOT_EXIST;
5369 ice_release_lock(rule_lock);
5371 list_itr->status = ice_remove_rule_internal(hw, recp_list,
5373 if (list_itr->status)
5374 return list_itr->status;
5380 * ice_remove_mac - remove a MAC address based filter rule
5381 * @hw: pointer to the hardware structure
5382 * @m_list: list of MAC addresses and forwarding information
5385 enum ice_status ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
5387 struct ice_sw_recipe *recp_list;
5389 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
5390 return ice_remove_mac_rule(hw, m_list, recp_list);
5394 * ice_remove_vlan_rule - Remove VLAN based filter rule
5395 * @hw: pointer to the hardware structure
5396 * @v_list: list of VLAN entries and forwarding information
5397 * @recp_list: list from which function remove VLAN
5399 static enum ice_status
5400 ice_remove_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
5401 struct ice_sw_recipe *recp_list)
5403 struct ice_fltr_list_entry *v_list_itr, *tmp;
5405 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
5407 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
5409 if (l_type != ICE_SW_LKUP_VLAN)
5410 return ICE_ERR_PARAM;
5411 v_list_itr->status = ice_remove_rule_internal(hw, recp_list,
5413 if (v_list_itr->status)
5414 return v_list_itr->status;
5420 * ice_remove_vlan - remove a VLAN address based filter rule
5421 * @hw: pointer to the hardware structure
5422 * @v_list: list of VLAN and forwarding information
5426 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
5428 struct ice_sw_recipe *recp_list;
5431 return ICE_ERR_PARAM;
5433 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_VLAN];
5434 return ice_remove_vlan_rule(hw, v_list, recp_list);
5438 * ice_remove_mac_vlan_rule - Remove MAC VLAN based filter rule
5439 * @hw: pointer to the hardware structure
5440 * @v_list: list of MAC VLAN entries and forwarding information
5441 * @recp_list: list from which function remove MAC VLAN
5443 static enum ice_status
5444 ice_remove_mac_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
5445 struct ice_sw_recipe *recp_list)
5447 struct ice_fltr_list_entry *v_list_itr, *tmp;
5449 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC_VLAN];
5450 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
5452 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
5454 if (l_type != ICE_SW_LKUP_MAC_VLAN)
5455 return ICE_ERR_PARAM;
5456 v_list_itr->status =
5457 ice_remove_rule_internal(hw, recp_list,
5459 if (v_list_itr->status)
5460 return v_list_itr->status;
5466 * ice_remove_mac_vlan - remove a MAC VLAN address based filter rule
5467 * @hw: pointer to the hardware structure
5468 * @mv_list: list of MAC VLAN and forwarding information
5471 ice_remove_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list)
5473 struct ice_sw_recipe *recp_list;
5475 if (!mv_list || !hw)
5476 return ICE_ERR_PARAM;
5478 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC_VLAN];
5479 return ice_remove_mac_vlan_rule(hw, mv_list, recp_list);
5483 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
5484 * @fm_entry: filter entry to inspect
5485 * @vsi_handle: VSI handle to compare with filter info
5488 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
5490 return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
5491 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
5492 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
5493 fm_entry->vsi_list_info &&
5494 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
5499 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
5500 * @hw: pointer to the hardware structure
5501 * @vsi_handle: VSI handle to remove filters from
5502 * @vsi_list_head: pointer to the list to add entry to
5503 * @fi: pointer to fltr_info of filter entry to copy & add
5505 * Helper function, used when creating a list of filters to remove from
5506 * a specific VSI. The entry added to vsi_list_head is a COPY of the
5507 * original filter entry, with the exception of fltr_info.fltr_act and
5508 * fltr_info.fwd_id fields. These are set such that later logic can
5509 * extract which VSI to remove the fltr from, and pass on that information.
5511 static enum ice_status
5512 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
5513 struct LIST_HEAD_TYPE *vsi_list_head,
5514 struct ice_fltr_info *fi)
5516 struct ice_fltr_list_entry *tmp;
5518 /* this memory is freed up in the caller function
5519 * once filters for this VSI are removed
5521 tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp));
5523 return ICE_ERR_NO_MEMORY;
5525 tmp->fltr_info = *fi;
5527 /* Overwrite these fields to indicate which VSI to remove filter from,
5528 * so find and remove logic can extract the information from the
5529 * list entries. Note that original entries will still have proper
5532 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
5533 tmp->fltr_info.vsi_handle = vsi_handle;
5534 tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
5536 LIST_ADD(&tmp->list_entry, vsi_list_head);
5542 * ice_add_to_vsi_fltr_list - Add VSI filters to the list
5543 * @hw: pointer to the hardware structure
5544 * @vsi_handle: VSI handle to remove filters from
5545 * @lkup_list_head: pointer to the list that has certain lookup type filters
5546 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
5548 * Locates all filters in lkup_list_head that are used by the given VSI,
5549 * and adds COPIES of those entries to vsi_list_head (intended to be used
5550 * to remove the listed filters).
5551 * Note that this means all entries in vsi_list_head must be explicitly
5552 * deallocated by the caller when done with list.
5554 static enum ice_status
5555 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
5556 struct LIST_HEAD_TYPE *lkup_list_head,
5557 struct LIST_HEAD_TYPE *vsi_list_head)
5559 struct ice_fltr_mgmt_list_entry *fm_entry;
5560 enum ice_status status = ICE_SUCCESS;
5562 /* check to make sure VSI ID is valid and within boundary */
5563 if (!ice_is_vsi_valid(hw, vsi_handle))
5564 return ICE_ERR_PARAM;
5566 LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
5567 ice_fltr_mgmt_list_entry, list_entry) {
5568 if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
5571 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
5573 &fm_entry->fltr_info);
5581 * ice_determine_promisc_mask
5582 * @fi: filter info to parse
5584 * Helper function to determine which ICE_PROMISC_ mask corresponds
5585 * to given filter into.
5587 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
5589 u16 vid = fi->l_data.mac_vlan.vlan_id;
5590 u8 *macaddr = fi->l_data.mac.mac_addr;
5591 bool is_tx_fltr = false;
5592 u8 promisc_mask = 0;
5594 if (fi->flag == ICE_FLTR_TX)
5597 if (IS_BROADCAST_ETHER_ADDR(macaddr))
5598 promisc_mask |= is_tx_fltr ?
5599 ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
5600 else if (IS_MULTICAST_ETHER_ADDR(macaddr))
5601 promisc_mask |= is_tx_fltr ?
5602 ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
5603 else if (IS_UNICAST_ETHER_ADDR(macaddr))
5604 promisc_mask |= is_tx_fltr ?
5605 ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
5607 promisc_mask |= is_tx_fltr ?
5608 ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
5610 return promisc_mask;
5614 * _ice_get_vsi_promisc - get promiscuous mode of given VSI
5615 * @hw: pointer to the hardware structure
5616 * @vsi_handle: VSI handle to retrieve info from
5617 * @promisc_mask: pointer to mask to be filled in
5618 * @vid: VLAN ID of promisc VLAN VSI
5619 * @sw: pointer to switch info struct for which function add rule
5621 static enum ice_status
5622 _ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
5623 u16 *vid, struct ice_switch_info *sw)
5625 struct ice_fltr_mgmt_list_entry *itr;
5626 struct LIST_HEAD_TYPE *rule_head;
5627 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
5629 if (!ice_is_vsi_valid(hw, vsi_handle))
5630 return ICE_ERR_PARAM;
5634 rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rules;
5635 rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rule_lock;
5637 ice_acquire_lock(rule_lock);
5638 LIST_FOR_EACH_ENTRY(itr, rule_head,
5639 ice_fltr_mgmt_list_entry, list_entry) {
5640 /* Continue if this filter doesn't apply to this VSI or the
5641 * VSI ID is not in the VSI map for this filter
5643 if (!ice_vsi_uses_fltr(itr, vsi_handle))
5646 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
5648 ice_release_lock(rule_lock);
5654 * ice_get_vsi_promisc - get promiscuous mode of given VSI
5655 * @hw: pointer to the hardware structure
5656 * @vsi_handle: VSI handle to retrieve info from
5657 * @promisc_mask: pointer to mask to be filled in
5658 * @vid: VLAN ID of promisc VLAN VSI
5661 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
5664 return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask,
5665 vid, hw->switch_info);
5669 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
5670 * @hw: pointer to the hardware structure
5671 * @vsi_handle: VSI handle to retrieve info from
5672 * @promisc_mask: pointer to mask to be filled in
5673 * @vid: VLAN ID of promisc VLAN VSI
5674 * @sw: pointer to switch info struct for which function add rule
5676 static enum ice_status
5677 _ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
5678 u16 *vid, struct ice_switch_info *sw)
5680 struct ice_fltr_mgmt_list_entry *itr;
5681 struct LIST_HEAD_TYPE *rule_head;
5682 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
5684 if (!ice_is_vsi_valid(hw, vsi_handle))
5685 return ICE_ERR_PARAM;
5689 rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rules;
5690 rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rule_lock;
5692 ice_acquire_lock(rule_lock);
5693 LIST_FOR_EACH_ENTRY(itr, rule_head, ice_fltr_mgmt_list_entry,
5695 /* Continue if this filter doesn't apply to this VSI or the
5696 * VSI ID is not in the VSI map for this filter
5698 if (!ice_vsi_uses_fltr(itr, vsi_handle))
5701 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
5703 ice_release_lock(rule_lock);
5709 * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
5710 * @hw: pointer to the hardware structure
5711 * @vsi_handle: VSI handle to retrieve info from
5712 * @promisc_mask: pointer to mask to be filled in
5713 * @vid: VLAN ID of promisc VLAN VSI
5716 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
5719 return _ice_get_vsi_vlan_promisc(hw, vsi_handle, promisc_mask,
5720 vid, hw->switch_info);
5724 * ice_remove_promisc - Remove promisc based filter rules
5725 * @hw: pointer to the hardware structure
5726 * @recp_id: recipe ID for which the rule needs to removed
5727 * @v_list: list of promisc entries
5729 static enum ice_status
5730 ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
5731 struct LIST_HEAD_TYPE *v_list)
5733 struct ice_fltr_list_entry *v_list_itr, *tmp;
5734 struct ice_sw_recipe *recp_list;
5736 recp_list = &hw->switch_info->recp_list[recp_id];
5737 LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
5739 v_list_itr->status =
5740 ice_remove_rule_internal(hw, recp_list, v_list_itr);
5741 if (v_list_itr->status)
5742 return v_list_itr->status;
5748 * _ice_clear_vsi_promisc - clear specified promiscuous mode(s)
5749 * @hw: pointer to the hardware structure
5750 * @vsi_handle: VSI handle to clear mode
5751 * @promisc_mask: mask of promiscuous config bits to clear
5752 * @vid: VLAN ID to clear VLAN promiscuous
5753 * @sw: pointer to switch info struct for which function add rule
5755 static enum ice_status
5756 _ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
5757 u16 vid, struct ice_switch_info *sw)
5759 struct ice_fltr_list_entry *fm_entry, *tmp;
5760 struct LIST_HEAD_TYPE remove_list_head;
5761 struct ice_fltr_mgmt_list_entry *itr;
5762 struct LIST_HEAD_TYPE *rule_head;
5763 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
5764 enum ice_status status = ICE_SUCCESS;
5767 if (!ice_is_vsi_valid(hw, vsi_handle))
5768 return ICE_ERR_PARAM;
5770 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
5771 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
5773 recipe_id = ICE_SW_LKUP_PROMISC;
5775 rule_head = &sw->recp_list[recipe_id].filt_rules;
5776 rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
5778 INIT_LIST_HEAD(&remove_list_head);
5780 ice_acquire_lock(rule_lock);
5781 LIST_FOR_EACH_ENTRY(itr, rule_head,
5782 ice_fltr_mgmt_list_entry, list_entry) {
5783 struct ice_fltr_info *fltr_info;
5784 u8 fltr_promisc_mask = 0;
5786 if (!ice_vsi_uses_fltr(itr, vsi_handle))
5788 fltr_info = &itr->fltr_info;
5790 if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
5791 vid != fltr_info->l_data.mac_vlan.vlan_id)
5794 fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
5796 /* Skip if filter is not completely specified by given mask */
5797 if (fltr_promisc_mask & ~promisc_mask)
5800 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
5804 ice_release_lock(rule_lock);
5805 goto free_fltr_list;
5808 ice_release_lock(rule_lock);
5810 status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
5813 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
5814 ice_fltr_list_entry, list_entry) {
5815 LIST_DEL(&fm_entry->list_entry);
5816 ice_free(hw, fm_entry);
5823 * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
5824 * @hw: pointer to the hardware structure
5825 * @vsi_handle: VSI handle to clear mode
5826 * @promisc_mask: mask of promiscuous config bits to clear
5827 * @vid: VLAN ID to clear VLAN promiscuous
5830 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle,
5831 u8 promisc_mask, u16 vid)
5833 return _ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask,
5834 vid, hw->switch_info);
5838 * _ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
5839 * @hw: pointer to the hardware structure
5840 * @vsi_handle: VSI handle to configure
5841 * @promisc_mask: mask of promiscuous config bits
5842 * @vid: VLAN ID to set VLAN promiscuous
5843 * @lport: logical port number to configure promisc mode
5844 * @sw: pointer to switch info struct for which function add rule
5846 static enum ice_status
5847 _ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
5848 u16 vid, u8 lport, struct ice_switch_info *sw)
5850 enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
5851 struct ice_fltr_list_entry f_list_entry;
5852 struct ice_fltr_info new_fltr;
5853 enum ice_status status = ICE_SUCCESS;
5859 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
5861 if (!ice_is_vsi_valid(hw, vsi_handle))
5862 return ICE_ERR_PARAM;
5863 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
5865 ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM);
5867 if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
5868 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
5869 new_fltr.l_data.mac_vlan.vlan_id = vid;
5870 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
5872 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
5873 recipe_id = ICE_SW_LKUP_PROMISC;
5876 /* Separate filters must be set for each direction/packet type
5877 * combination, so we will loop over the mask value, store the
5878 * individual type, and clear it out in the input mask as it
5881 while (promisc_mask) {
5882 struct ice_sw_recipe *recp_list;
5888 if (promisc_mask & ICE_PROMISC_UCAST_RX) {
5889 promisc_mask &= ~ICE_PROMISC_UCAST_RX;
5890 pkt_type = UCAST_FLTR;
5891 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
5892 promisc_mask &= ~ICE_PROMISC_UCAST_TX;
5893 pkt_type = UCAST_FLTR;
5895 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
5896 promisc_mask &= ~ICE_PROMISC_MCAST_RX;
5897 pkt_type = MCAST_FLTR;
5898 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
5899 promisc_mask &= ~ICE_PROMISC_MCAST_TX;
5900 pkt_type = MCAST_FLTR;
5902 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
5903 promisc_mask &= ~ICE_PROMISC_BCAST_RX;
5904 pkt_type = BCAST_FLTR;
5905 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
5906 promisc_mask &= ~ICE_PROMISC_BCAST_TX;
5907 pkt_type = BCAST_FLTR;
5911 /* Check for VLAN promiscuous flag */
5912 if (promisc_mask & ICE_PROMISC_VLAN_RX) {
5913 promisc_mask &= ~ICE_PROMISC_VLAN_RX;
5914 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
5915 promisc_mask &= ~ICE_PROMISC_VLAN_TX;
5919 /* Set filter DA based on packet type */
5920 mac_addr = new_fltr.l_data.mac.mac_addr;
5921 if (pkt_type == BCAST_FLTR) {
5922 ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM);
5923 } else if (pkt_type == MCAST_FLTR ||
5924 pkt_type == UCAST_FLTR) {
5925 /* Use the dummy ether header DA */
5926 ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN,
5927 ICE_NONDMA_TO_NONDMA);
5928 if (pkt_type == MCAST_FLTR)
5929 mac_addr[0] |= 0x1; /* Set multicast bit */
5932 /* Need to reset this to zero for all iterations */
5935 new_fltr.flag |= ICE_FLTR_TX;
5936 new_fltr.src = hw_vsi_id;
5938 new_fltr.flag |= ICE_FLTR_RX;
5939 new_fltr.src = lport;
5942 new_fltr.fltr_act = ICE_FWD_TO_VSI;
5943 new_fltr.vsi_handle = vsi_handle;
5944 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
5945 f_list_entry.fltr_info = new_fltr;
5946 recp_list = &sw->recp_list[recipe_id];
5948 status = ice_add_rule_internal(hw, recp_list, lport,
5950 if (status != ICE_SUCCESS)
5951 goto set_promisc_exit;
5959 * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
5960 * @hw: pointer to the hardware structure
5961 * @vsi_handle: VSI handle to configure
5962 * @promisc_mask: mask of promiscuous config bits
5963 * @vid: VLAN ID to set VLAN promiscuous
5966 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
5969 return _ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid,
5970 hw->port_info->lport,
5975 * _ice_set_vlan_vsi_promisc
5976 * @hw: pointer to the hardware structure
5977 * @vsi_handle: VSI handle to configure
5978 * @promisc_mask: mask of promiscuous config bits
5979 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
5980 * @lport: logical port number to configure promisc mode
5981 * @sw: pointer to switch info struct for which function add rule
5983 * Configure VSI with all associated VLANs to given promiscuous mode(s)
5985 static enum ice_status
5986 _ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
5987 bool rm_vlan_promisc, u8 lport,
5988 struct ice_switch_info *sw)
5990 struct ice_fltr_list_entry *list_itr, *tmp;
5991 struct LIST_HEAD_TYPE vsi_list_head;
5992 struct LIST_HEAD_TYPE *vlan_head;
5993 struct ice_lock *vlan_lock; /* Lock to protect filter rule list */
5994 enum ice_status status;
5997 INIT_LIST_HEAD(&vsi_list_head);
5998 vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
5999 vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
6000 ice_acquire_lock(vlan_lock);
6001 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
6003 ice_release_lock(vlan_lock);
6005 goto free_fltr_list;
6007 LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry,
6009 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
6010 if (rm_vlan_promisc)
6011 status = _ice_clear_vsi_promisc(hw, vsi_handle,
6015 status = _ice_set_vsi_promisc(hw, vsi_handle,
6016 promisc_mask, vlan_id,
6023 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head,
6024 ice_fltr_list_entry, list_entry) {
6025 LIST_DEL(&list_itr->list_entry);
6026 ice_free(hw, list_itr);
6032 * ice_set_vlan_vsi_promisc
6033 * @hw: pointer to the hardware structure
6034 * @vsi_handle: VSI handle to configure
6035 * @promisc_mask: mask of promiscuous config bits
6036 * @rm_vlan_promisc: Clear VLANs VSI promisc mode
6038 * Configure VSI with all associated VLANs to given promiscuous mode(s)
6041 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
6042 bool rm_vlan_promisc)
6044 return _ice_set_vlan_vsi_promisc(hw, vsi_handle, promisc_mask,
6045 rm_vlan_promisc, hw->port_info->lport,
6050 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
6051 * @hw: pointer to the hardware structure
6052 * @vsi_handle: VSI handle to remove filters from
6053 * @recp_list: recipe list from which function remove fltr
6054 * @lkup: switch rule filter lookup type
6057 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
6058 struct ice_sw_recipe *recp_list,
6059 enum ice_sw_lkup_type lkup)
6061 struct ice_fltr_list_entry *fm_entry;
6062 struct LIST_HEAD_TYPE remove_list_head;
6063 struct LIST_HEAD_TYPE *rule_head;
6064 struct ice_fltr_list_entry *tmp;
6065 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
6066 enum ice_status status;
6068 INIT_LIST_HEAD(&remove_list_head);
6069 rule_lock = &recp_list[lkup].filt_rule_lock;
6070 rule_head = &recp_list[lkup].filt_rules;
6071 ice_acquire_lock(rule_lock);
6072 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
6074 ice_release_lock(rule_lock);
6079 case ICE_SW_LKUP_MAC:
6080 ice_remove_mac_rule(hw, &remove_list_head, &recp_list[lkup]);
6082 case ICE_SW_LKUP_VLAN:
6083 ice_remove_vlan_rule(hw, &remove_list_head, &recp_list[lkup]);
6085 case ICE_SW_LKUP_PROMISC:
6086 case ICE_SW_LKUP_PROMISC_VLAN:
6087 ice_remove_promisc(hw, lkup, &remove_list_head);
6089 case ICE_SW_LKUP_MAC_VLAN:
6090 ice_remove_mac_vlan(hw, &remove_list_head);
6092 case ICE_SW_LKUP_ETHERTYPE:
6093 case ICE_SW_LKUP_ETHERTYPE_MAC:
6094 ice_remove_eth_mac(hw, &remove_list_head);
6096 case ICE_SW_LKUP_DFLT:
6097 ice_debug(hw, ICE_DBG_SW, "Remove filters for this lookup type hasn't been implemented yet\n");
6099 case ICE_SW_LKUP_LAST:
6100 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n");
6104 LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
6105 ice_fltr_list_entry, list_entry) {
6106 LIST_DEL(&fm_entry->list_entry);
6107 ice_free(hw, fm_entry);
6112 * ice_remove_vsi_fltr_rule - Remove all filters for a VSI
6113 * @hw: pointer to the hardware structure
6114 * @vsi_handle: VSI handle to remove filters from
6115 * @sw: pointer to switch info struct
6118 ice_remove_vsi_fltr_rule(struct ice_hw *hw, u16 vsi_handle,
6119 struct ice_switch_info *sw)
6121 ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
6123 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6124 sw->recp_list, ICE_SW_LKUP_MAC);
6125 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6126 sw->recp_list, ICE_SW_LKUP_MAC_VLAN);
6127 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6128 sw->recp_list, ICE_SW_LKUP_PROMISC);
6129 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6130 sw->recp_list, ICE_SW_LKUP_VLAN);
6131 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6132 sw->recp_list, ICE_SW_LKUP_DFLT);
6133 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6134 sw->recp_list, ICE_SW_LKUP_ETHERTYPE);
6135 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6136 sw->recp_list, ICE_SW_LKUP_ETHERTYPE_MAC);
6137 ice_remove_vsi_lkup_fltr(hw, vsi_handle,
6138 sw->recp_list, ICE_SW_LKUP_PROMISC_VLAN);
6142 * ice_remove_vsi_fltr - Remove all filters for a VSI
6143 * @hw: pointer to the hardware structure
6144 * @vsi_handle: VSI handle to remove filters from
6146 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
6148 ice_remove_vsi_fltr_rule(hw, vsi_handle, hw->switch_info);
6152 * ice_alloc_res_cntr - allocating resource counter
6153 * @hw: pointer to the hardware structure
6154 * @type: type of resource
6155 * @alloc_shared: if set it is shared else dedicated
6156 * @num_items: number of entries requested for FD resource type
6157 * @counter_id: counter index returned by AQ call
6160 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
6163 struct ice_aqc_alloc_free_res_elem *buf;
6164 enum ice_status status;
6167 /* Allocate resource */
6168 buf_len = ice_struct_size(buf, elem, 1);
6169 buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
6171 return ICE_ERR_NO_MEMORY;
6173 buf->num_elems = CPU_TO_LE16(num_items);
6174 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
6175 ICE_AQC_RES_TYPE_M) | alloc_shared);
6177 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
6178 ice_aqc_opc_alloc_res, NULL);
6182 *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp);
6190 * ice_free_res_cntr - free resource counter
6191 * @hw: pointer to the hardware structure
6192 * @type: type of resource
6193 * @alloc_shared: if set it is shared else dedicated
6194 * @num_items: number of entries to be freed for FD resource type
6195 * @counter_id: counter ID resource which needs to be freed
6198 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
6201 struct ice_aqc_alloc_free_res_elem *buf;
6202 enum ice_status status;
6206 buf_len = ice_struct_size(buf, elem, 1);
6207 buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
6209 return ICE_ERR_NO_MEMORY;
6211 buf->num_elems = CPU_TO_LE16(num_items);
6212 buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
6213 ICE_AQC_RES_TYPE_M) | alloc_shared);
6214 buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
6216 status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
6217 ice_aqc_opc_free_res, NULL);
6219 ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
6226 * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type
6227 * @hw: pointer to the hardware structure
6228 * @counter_id: returns counter index
6230 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id)
6232 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
6233 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
6238 * ice_free_vlan_res_counter - Free counter resource for VLAN type
6239 * @hw: pointer to the hardware structure
6240 * @counter_id: counter index to be freed
6242 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id)
6244 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
6245 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
6250 * ice_alloc_res_lg_act - add large action resource
6251 * @hw: pointer to the hardware structure
6252 * @l_id: large action ID to fill it in
6253 * @num_acts: number of actions to hold with a large action entry
6255 static enum ice_status
6256 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts)
6258 struct ice_aqc_alloc_free_res_elem *sw_buf;
6259 enum ice_status status;
6262 if (num_acts > ICE_MAX_LG_ACT || num_acts == 0)
6263 return ICE_ERR_PARAM;
6265 /* Allocate resource for large action */
6266 buf_len = ice_struct_size(sw_buf, elem, 1);
6267 sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
6269 return ICE_ERR_NO_MEMORY;
6271 sw_buf->num_elems = CPU_TO_LE16(1);
6273 /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1.
6274 * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3.
6275 * If num_acts is greater than 2, then use
6276 * ICE_AQC_RES_TYPE_WIDE_TABLE_4.
6277 * The num_acts cannot exceed 4. This was ensured at the
6278 * beginning of the function.
6281 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_1);
6282 else if (num_acts == 2)
6283 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_2);
6285 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_4);
6287 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
6288 ice_aqc_opc_alloc_res, NULL);
6290 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
6292 ice_free(hw, sw_buf);
6297 * ice_add_mac_with_sw_marker - add filter with sw marker
6298 * @hw: pointer to the hardware structure
6299 * @f_info: filter info structure containing the MAC filter information
6300 * @sw_marker: sw marker to tag the Rx descriptor with
6303 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info,
6306 struct ice_fltr_mgmt_list_entry *m_entry;
6307 struct ice_fltr_list_entry fl_info;
6308 struct ice_sw_recipe *recp_list;
6309 struct LIST_HEAD_TYPE l_head;
6310 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
6311 enum ice_status ret;
6315 if (f_info->fltr_act != ICE_FWD_TO_VSI)
6316 return ICE_ERR_PARAM;
6318 if (f_info->lkup_type != ICE_SW_LKUP_MAC)
6319 return ICE_ERR_PARAM;
6321 if (sw_marker == ICE_INVAL_SW_MARKER_ID)
6322 return ICE_ERR_PARAM;
6324 if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
6325 return ICE_ERR_PARAM;
6326 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
6328 /* Add filter if it doesn't exist so then the adding of large
6329 * action always results in update
6332 INIT_LIST_HEAD(&l_head);
6333 fl_info.fltr_info = *f_info;
6334 LIST_ADD(&fl_info.list_entry, &l_head);
6336 entry_exists = false;
6337 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info,
6338 hw->port_info->lport);
6339 if (ret == ICE_ERR_ALREADY_EXISTS)
6340 entry_exists = true;
6344 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
6345 rule_lock = &recp_list->filt_rule_lock;
6346 ice_acquire_lock(rule_lock);
6347 /* Get the book keeping entry for the filter */
6348 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info);
6352 /* If counter action was enabled for this rule then don't enable
6353 * sw marker large action
6355 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
6356 ret = ICE_ERR_PARAM;
6360 /* if same marker was added before */
6361 if (m_entry->sw_marker_id == sw_marker) {
6362 ret = ICE_ERR_ALREADY_EXISTS;
6366 /* Allocate a hardware table entry to hold large act. Three actions
6367 * for marker based large action
6369 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3);
6373 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
6376 /* Update the switch rule to add the marker action */
6377 ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id);
6379 ice_release_lock(rule_lock);
6384 ice_release_lock(rule_lock);
6385 /* only remove entry if it did not exist previously */
6387 ret = ice_remove_mac(hw, &l_head);
6393 * ice_add_mac_with_counter - add filter with counter enabled
6394 * @hw: pointer to the hardware structure
6395 * @f_info: pointer to filter info structure containing the MAC filter
6399 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info)
6401 struct ice_fltr_mgmt_list_entry *m_entry;
6402 struct ice_fltr_list_entry fl_info;
6403 struct ice_sw_recipe *recp_list;
6404 struct LIST_HEAD_TYPE l_head;
6405 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
6406 enum ice_status ret;
6411 if (f_info->fltr_act != ICE_FWD_TO_VSI)
6412 return ICE_ERR_PARAM;
6414 if (f_info->lkup_type != ICE_SW_LKUP_MAC)
6415 return ICE_ERR_PARAM;
6417 if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
6418 return ICE_ERR_PARAM;
6419 f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
6420 recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
6422 entry_exist = false;
6424 rule_lock = &recp_list->filt_rule_lock;
6426 /* Add filter if it doesn't exist so then the adding of large
6427 * action always results in update
6429 INIT_LIST_HEAD(&l_head);
6431 fl_info.fltr_info = *f_info;
6432 LIST_ADD(&fl_info.list_entry, &l_head);
6434 ret = ice_add_mac_rule(hw, &l_head, hw->switch_info,
6435 hw->port_info->lport);
6436 if (ret == ICE_ERR_ALREADY_EXISTS)
6441 ice_acquire_lock(rule_lock);
6442 m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info);
6444 ret = ICE_ERR_BAD_PTR;
6448 /* Don't enable counter for a filter for which sw marker was enabled */
6449 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) {
6450 ret = ICE_ERR_PARAM;
6454 /* If a counter was already enabled then don't need to add again */
6455 if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
6456 ret = ICE_ERR_ALREADY_EXISTS;
6460 /* Allocate a hardware table entry to VLAN counter */
6461 ret = ice_alloc_vlan_res_counter(hw, &counter_id);
6465 /* Allocate a hardware table entry to hold large act. Two actions for
6466 * counter based large action
6468 ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2);
6472 if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
6475 /* Update the switch rule to add the counter action */
6476 ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id);
6478 ice_release_lock(rule_lock);
6483 ice_release_lock(rule_lock);
6484 /* only remove entry if it did not exist previously */
6486 ret = ice_remove_mac(hw, &l_head);
6491 /* This is mapping table entry that maps every word within a given protocol
6492 * structure to the real byte offset as per the specification of that
6494 * for example dst address is 3 words in ethertype header and corresponding
6495 * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
6496 * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
6497 * matching entry describing its field. This needs to be updated if new
6498 * structure is added to that union.
6500 static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = {
6501 { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } },
6502 { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } },
6503 { ICE_ETYPE_OL, { 0 } },
6504 { ICE_VLAN_OFOS, { 0, 2 } },
6505 { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
6506 { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
6507 { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
6508 26, 28, 30, 32, 34, 36, 38 } },
6509 { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
6510 26, 28, 30, 32, 34, 36, 38 } },
6511 { ICE_TCP_IL, { 0, 2 } },
6512 { ICE_UDP_OF, { 0, 2 } },
6513 { ICE_UDP_ILOS, { 0, 2 } },
6514 { ICE_SCTP_IL, { 0, 2 } },
6515 { ICE_VXLAN, { 8, 10, 12, 14 } },
6516 { ICE_GENEVE, { 8, 10, 12, 14 } },
6517 { ICE_VXLAN_GPE, { 8, 10, 12, 14 } },
6518 { ICE_NVGRE, { 0, 2, 4, 6 } },
6519 { ICE_GTP, { 8, 10, 12, 14, 16, 18, 20 } },
6520 { ICE_PPPOE, { 0, 2, 4, 6 } },
6521 { ICE_PFCP, { 8, 10, 12, 14, 16, 18, 20, 22 } },
6522 { ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } },
6523 { ICE_ESP, { 0, 2, 4, 6 } },
6524 { ICE_AH, { 0, 2, 4, 6, 8, 10 } },
6525 { ICE_NAT_T, { 8, 10, 12, 14 } },
6526 { ICE_GTP_NO_PAY, { 8, 10, 12, 14 } },
6527 { ICE_VLAN_EX, { 0, 2 } },
6530 /* The following table describes preferred grouping of recipes.
6531 * If a recipe that needs to be programmed is a superset or matches one of the
6532 * following combinations, then the recipe needs to be chained as per the
6536 static const struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = {
6537 { ICE_MAC_OFOS, ICE_MAC_OFOS_HW },
6538 { ICE_MAC_IL, ICE_MAC_IL_HW },
6539 { ICE_ETYPE_OL, ICE_ETYPE_OL_HW },
6540 { ICE_VLAN_OFOS, ICE_VLAN_OL_HW },
6541 { ICE_IPV4_OFOS, ICE_IPV4_OFOS_HW },
6542 { ICE_IPV4_IL, ICE_IPV4_IL_HW },
6543 { ICE_IPV6_OFOS, ICE_IPV6_OFOS_HW },
6544 { ICE_IPV6_IL, ICE_IPV6_IL_HW },
6545 { ICE_TCP_IL, ICE_TCP_IL_HW },
6546 { ICE_UDP_OF, ICE_UDP_OF_HW },
6547 { ICE_UDP_ILOS, ICE_UDP_ILOS_HW },
6548 { ICE_SCTP_IL, ICE_SCTP_IL_HW },
6549 { ICE_VXLAN, ICE_UDP_OF_HW },
6550 { ICE_GENEVE, ICE_UDP_OF_HW },
6551 { ICE_VXLAN_GPE, ICE_UDP_OF_HW },
6552 { ICE_NVGRE, ICE_GRE_OF_HW },
6553 { ICE_GTP, ICE_UDP_OF_HW },
6554 { ICE_PPPOE, ICE_PPPOE_HW },
6555 { ICE_PFCP, ICE_UDP_ILOS_HW },
6556 { ICE_L2TPV3, ICE_L2TPV3_HW },
6557 { ICE_ESP, ICE_ESP_HW },
6558 { ICE_AH, ICE_AH_HW },
6559 { ICE_NAT_T, ICE_UDP_ILOS_HW },
6560 { ICE_GTP_NO_PAY, ICE_UDP_ILOS_HW },
6561 { ICE_VLAN_EX, ICE_VLAN_OF_HW },
6565 * ice_find_recp - find a recipe
6566 * @hw: pointer to the hardware structure
6567 * @lkup_exts: extension sequence to match
6569 * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
6571 static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts,
6572 enum ice_sw_tunnel_type tun_type)
6574 bool refresh_required = true;
6575 struct ice_sw_recipe *recp;
6578 /* Walk through existing recipes to find a match */
6579 recp = hw->switch_info->recp_list;
6580 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6581 /* If recipe was not created for this ID, in SW bookkeeping,
6582 * check if FW has an entry for this recipe. If the FW has an
6583 * entry update it in our SW bookkeeping and continue with the
6586 if (!recp[i].recp_created)
6587 if (ice_get_recp_frm_fw(hw,
6588 hw->switch_info->recp_list, i,
6592 /* Skip inverse action recipes */
6593 if (recp[i].root_buf && recp[i].root_buf->content.act_ctrl &
6594 ICE_AQ_RECIPE_ACT_INV_ACT)
6597 /* if number of words we are looking for match */
6598 if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
6599 struct ice_fv_word *ar = recp[i].lkup_exts.fv_words;
6600 struct ice_fv_word *be = lkup_exts->fv_words;
6601 u16 *cr = recp[i].lkup_exts.field_mask;
6602 u16 *de = lkup_exts->field_mask;
6606 /* ar, cr, and qr are related to the recipe words, while
6607 * be, de, and pe are related to the lookup words
6609 for (pe = 0; pe < lkup_exts->n_val_words; pe++) {
6610 for (qr = 0; qr < recp[i].lkup_exts.n_val_words;
6612 if (ar[qr].off == be[pe].off &&
6613 ar[qr].prot_id == be[pe].prot_id &&
6615 /* Found the "pe"th word in the
6620 /* After walking through all the words in the
6621 * "i"th recipe if "p"th word was not found then
6622 * this recipe is not what we are looking for.
6623 * So break out from this loop and try the next
6626 if (qr >= recp[i].lkup_exts.n_val_words) {
6631 /* If for "i"th recipe the found was never set to false
6632 * then it means we found our match
6634 if (tun_type == recp[i].tun_type && found)
6635 return i; /* Return the recipe ID */
6638 return ICE_MAX_NUM_RECIPES;
6642 * ice_prot_type_to_id - get protocol ID from protocol type
6643 * @type: protocol type
6644 * @id: pointer to variable that will receive the ID
6646 * Returns true if found, false otherwise
6648 static bool ice_prot_type_to_id(enum ice_protocol_type type, u8 *id)
6652 for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
6653 if (ice_prot_id_tbl[i].type == type) {
6654 *id = ice_prot_id_tbl[i].protocol_id;
6661 * ice_find_valid_words - count valid words
6662 * @rule: advanced rule with lookup information
6663 * @lkup_exts: byte offset extractions of the words that are valid
6665 * calculate valid words in a lookup rule using mask value
6668 ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
6669 struct ice_prot_lkup_ext *lkup_exts)
6671 u8 j, word, prot_id, ret_val;
6673 if (!ice_prot_type_to_id(rule->type, &prot_id))
6676 word = lkup_exts->n_val_words;
6678 for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
6679 if (((u16 *)&rule->m_u)[j] &&
6680 rule->type < ARRAY_SIZE(ice_prot_ext)) {
6681 /* No more space to accommodate */
6682 if (word >= ICE_MAX_CHAIN_WORDS)
6684 lkup_exts->fv_words[word].off =
6685 ice_prot_ext[rule->type].offs[j];
6686 lkup_exts->fv_words[word].prot_id =
6687 ice_prot_id_tbl[rule->type].protocol_id;
6688 lkup_exts->field_mask[word] =
6689 BE16_TO_CPU(((_FORCE_ __be16 *)&rule->m_u)[j]);
6693 ret_val = word - lkup_exts->n_val_words;
6694 lkup_exts->n_val_words = word;
6700 * ice_create_first_fit_recp_def - Create a recipe grouping
6701 * @hw: pointer to the hardware structure
6702 * @lkup_exts: an array of protocol header extractions
6703 * @rg_list: pointer to a list that stores new recipe groups
6704 * @recp_cnt: pointer to a variable that stores returned number of recipe groups
6706 * Using first fit algorithm, take all the words that are still not done
6707 * and start grouping them in 4-word groups. Each group makes up one
6710 static enum ice_status
6711 ice_create_first_fit_recp_def(struct ice_hw *hw,
6712 struct ice_prot_lkup_ext *lkup_exts,
6713 struct LIST_HEAD_TYPE *rg_list,
6716 struct ice_pref_recipe_group *grp = NULL;
6721 if (!lkup_exts->n_val_words) {
6722 struct ice_recp_grp_entry *entry;
6724 entry = (struct ice_recp_grp_entry *)
6725 ice_malloc(hw, sizeof(*entry));
6727 return ICE_ERR_NO_MEMORY;
6728 LIST_ADD(&entry->l_entry, rg_list);
6729 grp = &entry->r_group;
6731 grp->n_val_pairs = 0;
6734 /* Walk through every word in the rule to check if it is not done. If so
6735 * then this word needs to be part of a new recipe.
6737 for (j = 0; j < lkup_exts->n_val_words; j++)
6738 if (!ice_is_bit_set(lkup_exts->done, j)) {
6740 grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
6741 struct ice_recp_grp_entry *entry;
6743 entry = (struct ice_recp_grp_entry *)
6744 ice_malloc(hw, sizeof(*entry));
6746 return ICE_ERR_NO_MEMORY;
6747 LIST_ADD(&entry->l_entry, rg_list);
6748 grp = &entry->r_group;
6752 grp->pairs[grp->n_val_pairs].prot_id =
6753 lkup_exts->fv_words[j].prot_id;
6754 grp->pairs[grp->n_val_pairs].off =
6755 lkup_exts->fv_words[j].off;
6756 grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
6764 * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
6765 * @hw: pointer to the hardware structure
6766 * @fv_list: field vector with the extraction sequence information
6767 * @rg_list: recipe groupings with protocol-offset pairs
6769 * Helper function to fill in the field vector indices for protocol-offset
6770 * pairs. These indexes are then ultimately programmed into a recipe.
6772 static enum ice_status
6773 ice_fill_fv_word_index(struct ice_hw *hw, struct LIST_HEAD_TYPE *fv_list,
6774 struct LIST_HEAD_TYPE *rg_list)
6776 struct ice_sw_fv_list_entry *fv;
6777 struct ice_recp_grp_entry *rg;
6778 struct ice_fv_word *fv_ext;
6780 if (LIST_EMPTY(fv_list))
6783 fv = LIST_FIRST_ENTRY(fv_list, struct ice_sw_fv_list_entry, list_entry);
6784 fv_ext = fv->fv_ptr->ew;
6786 LIST_FOR_EACH_ENTRY(rg, rg_list, ice_recp_grp_entry, l_entry) {
6789 for (i = 0; i < rg->r_group.n_val_pairs; i++) {
6790 struct ice_fv_word *pr;
6795 pr = &rg->r_group.pairs[i];
6796 mask = rg->r_group.mask[i];
6798 for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
6799 if (fv_ext[j].prot_id == pr->prot_id &&
6800 fv_ext[j].off == pr->off) {
6803 /* Store index of field vector */
6805 rg->fv_mask[i] = mask;
6809 /* Protocol/offset could not be found, caller gave an
6813 return ICE_ERR_PARAM;
6821 * ice_find_free_recp_res_idx - find free result indexes for recipe
6822 * @hw: pointer to hardware structure
6823 * @profiles: bitmap of profiles that will be associated with the new recipe
6824 * @free_idx: pointer to variable to receive the free index bitmap
6826 * The algorithm used here is:
6827 * 1. When creating a new recipe, create a set P which contains all
6828 * Profiles that will be associated with our new recipe
6830 * 2. For each Profile p in set P:
6831 * a. Add all recipes associated with Profile p into set R
6832 * b. Optional : PossibleIndexes &= profile[p].possibleIndexes
6833 * [initially PossibleIndexes should be 0xFFFFFFFFFFFFFFFF]
6834 * i. Or just assume they all have the same possible indexes:
6836 * i.e., PossibleIndexes = 0x0000F00000000000
6838 * 3. For each Recipe r in set R:
6839 * a. UsedIndexes |= (bitwise or ) recipe[r].res_indexes
6840 * b. FreeIndexes = UsedIndexes ^ PossibleIndexes
6842 * FreeIndexes will contain the bits indicating the indexes free for use,
6843 * then the code needs to update the recipe[r].used_result_idx_bits to
6844 * indicate which indexes were selected for use by this recipe.
6847 ice_find_free_recp_res_idx(struct ice_hw *hw, const ice_bitmap_t *profiles,
6848 ice_bitmap_t *free_idx)
6850 ice_declare_bitmap(possible_idx, ICE_MAX_FV_WORDS);
6851 ice_declare_bitmap(recipes, ICE_MAX_NUM_RECIPES);
6852 ice_declare_bitmap(used_idx, ICE_MAX_FV_WORDS);
6855 ice_zero_bitmap(possible_idx, ICE_MAX_FV_WORDS);
6856 ice_zero_bitmap(recipes, ICE_MAX_NUM_RECIPES);
6857 ice_zero_bitmap(used_idx, ICE_MAX_FV_WORDS);
6858 ice_zero_bitmap(free_idx, ICE_MAX_FV_WORDS);
6860 ice_bitmap_set(possible_idx, 0, ICE_MAX_FV_WORDS);
6862 /* For each profile we are going to associate the recipe with, add the
6863 * recipes that are associated with that profile. This will give us
6864 * the set of recipes that our recipe may collide with. Also, determine
6865 * what possible result indexes are usable given this set of profiles.
6867 ice_for_each_set_bit(bit, profiles, ICE_MAX_NUM_PROFILES) {
6868 ice_or_bitmap(recipes, recipes, profile_to_recipe[bit],
6869 ICE_MAX_NUM_RECIPES);
6870 ice_and_bitmap(possible_idx, possible_idx,
6871 hw->switch_info->prof_res_bm[bit],
6875 /* For each recipe that our new recipe may collide with, determine
6876 * which indexes have been used.
6878 ice_for_each_set_bit(bit, recipes, ICE_MAX_NUM_RECIPES)
6879 ice_or_bitmap(used_idx, used_idx,
6880 hw->switch_info->recp_list[bit].res_idxs,
6883 ice_xor_bitmap(free_idx, used_idx, possible_idx, ICE_MAX_FV_WORDS);
6885 /* return number of free indexes */
6886 return (u16)ice_bitmap_hweight(free_idx, ICE_MAX_FV_WORDS);
6890 * ice_add_sw_recipe - function to call AQ calls to create switch recipe
6891 * @hw: pointer to hardware structure
6892 * @rm: recipe management list entry
6893 * @profiles: bitmap of profiles that will be associated.
6895 static enum ice_status
6896 ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
6897 ice_bitmap_t *profiles)
6899 ice_declare_bitmap(result_idx_bm, ICE_MAX_FV_WORDS);
6900 struct ice_aqc_recipe_data_elem *tmp;
6901 struct ice_aqc_recipe_data_elem *buf;
6902 struct ice_recp_grp_entry *entry;
6903 enum ice_status status;
6909 /* When more than one recipe are required, another recipe is needed to
6910 * chain them together. Matching a tunnel metadata ID takes up one of
6911 * the match fields in the chaining recipe reducing the number of
6912 * chained recipes by one.
6914 /* check number of free result indices */
6915 ice_zero_bitmap(result_idx_bm, ICE_MAX_FV_WORDS);
6916 free_res_idx = ice_find_free_recp_res_idx(hw, profiles, result_idx_bm);
6918 ice_debug(hw, ICE_DBG_SW, "Result idx slots: %d, need %d\n",
6919 free_res_idx, rm->n_grp_count);
6921 if (rm->n_grp_count > 1) {
6922 if (rm->n_grp_count > free_res_idx)
6923 return ICE_ERR_MAX_LIMIT;
6928 if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE)
6929 return ICE_ERR_MAX_LIMIT;
6931 tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,
6932 ICE_MAX_NUM_RECIPES,
6935 return ICE_ERR_NO_MEMORY;
6937 buf = (struct ice_aqc_recipe_data_elem *)
6938 ice_calloc(hw, rm->n_grp_count, sizeof(*buf));
6940 status = ICE_ERR_NO_MEMORY;
6944 ice_zero_bitmap(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
6945 recipe_count = ICE_MAX_NUM_RECIPES;
6946 status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
6948 if (status || recipe_count == 0)
6951 /* Allocate the recipe resources, and configure them according to the
6952 * match fields from protocol headers and extracted field vectors.
6954 chain_idx = ice_find_first_bit(result_idx_bm, ICE_MAX_FV_WORDS);
6955 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {
6958 status = ice_alloc_recipe(hw, &entry->rid);
6962 /* Clear the result index of the located recipe, as this will be
6963 * updated, if needed, later in the recipe creation process.
6965 tmp[0].content.result_indx = 0;
6967 buf[recps] = tmp[0];
6968 buf[recps].recipe_indx = (u8)entry->rid;
6969 /* if the recipe is a non-root recipe RID should be programmed
6970 * as 0 for the rules to be applied correctly.
6972 buf[recps].content.rid = 0;
6973 ice_memset(&buf[recps].content.lkup_indx, 0,
6974 sizeof(buf[recps].content.lkup_indx),
6977 /* All recipes use look-up index 0 to match switch ID. */
6978 buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
6979 buf[recps].content.mask[0] =
6980 CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK);
6981 /* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
6984 for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
6985 buf[recps].content.lkup_indx[i] = 0x80;
6986 buf[recps].content.mask[i] = 0;
6989 for (i = 0; i < entry->r_group.n_val_pairs; i++) {
6990 buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i];
6991 buf[recps].content.mask[i + 1] =
6992 CPU_TO_LE16(entry->fv_mask[i]);
6995 if (rm->n_grp_count > 1) {
6996 /* Checks to see if there really is a valid result index
6999 if (chain_idx >= ICE_MAX_FV_WORDS) {
7000 ice_debug(hw, ICE_DBG_SW, "No chain index available\n");
7001 status = ICE_ERR_MAX_LIMIT;
7005 entry->chain_idx = chain_idx;
7006 buf[recps].content.result_indx =
7007 ICE_AQ_RECIPE_RESULT_EN |
7008 ((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
7009 ICE_AQ_RECIPE_RESULT_DATA_M);
7010 ice_clear_bit(chain_idx, result_idx_bm);
7011 chain_idx = ice_find_first_bit(result_idx_bm,
7015 /* fill recipe dependencies */
7016 ice_zero_bitmap((ice_bitmap_t *)buf[recps].recipe_bitmap,
7017 ICE_MAX_NUM_RECIPES);
7018 ice_set_bit(buf[recps].recipe_indx,
7019 (ice_bitmap_t *)buf[recps].recipe_bitmap);
7020 buf[recps].content.act_ctrl_fwd_priority = rm->priority;
7024 if (rm->n_grp_count == 1) {
7025 rm->root_rid = buf[0].recipe_indx;
7026 ice_set_bit(buf[0].recipe_indx, rm->r_bitmap);
7027 buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
7028 if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
7029 ice_memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
7030 sizeof(buf[0].recipe_bitmap),
7031 ICE_NONDMA_TO_NONDMA);
7033 status = ICE_ERR_BAD_PTR;
7036 /* Applicable only for ROOT_RECIPE, set the fwd_priority for
7037 * the recipe which is getting created if specified
7038 * by user. Usually any advanced switch filter, which results
7039 * into new extraction sequence, ended up creating a new recipe
7040 * of type ROOT and usually recipes are associated with profiles
7041 * Switch rule referreing newly created recipe, needs to have
7042 * either/or 'fwd' or 'join' priority, otherwise switch rule
7043 * evaluation will not happen correctly. In other words, if
7044 * switch rule to be evaluated on priority basis, then recipe
7045 * needs to have priority, otherwise it will be evaluated last.
7047 buf[0].content.act_ctrl_fwd_priority = rm->priority;
7049 struct ice_recp_grp_entry *last_chain_entry;
7052 /* Allocate the last recipe that will chain the outcomes of the
7053 * other recipes together
7055 status = ice_alloc_recipe(hw, &rid);
7059 buf[recps].recipe_indx = (u8)rid;
7060 buf[recps].content.rid = (u8)rid;
7061 buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
7062 /* the new entry created should also be part of rg_list to
7063 * make sure we have complete recipe
7065 last_chain_entry = (struct ice_recp_grp_entry *)ice_malloc(hw,
7066 sizeof(*last_chain_entry));
7067 if (!last_chain_entry) {
7068 status = ICE_ERR_NO_MEMORY;
7071 last_chain_entry->rid = rid;
7072 ice_memset(&buf[recps].content.lkup_indx, 0,
7073 sizeof(buf[recps].content.lkup_indx),
7075 /* All recipes use look-up index 0 to match switch ID. */
7076 buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
7077 buf[recps].content.mask[0] =
7078 CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK);
7079 for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
7080 buf[recps].content.lkup_indx[i] =
7081 ICE_AQ_RECIPE_LKUP_IGNORE;
7082 buf[recps].content.mask[i] = 0;
7086 /* update r_bitmap with the recp that is used for chaining */
7087 ice_set_bit(rid, rm->r_bitmap);
7088 /* this is the recipe that chains all the other recipes so it
7089 * should not have a chaining ID to indicate the same
7091 last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
7092 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry,
7094 last_chain_entry->fv_idx[i] = entry->chain_idx;
7095 buf[recps].content.lkup_indx[i] = entry->chain_idx;
7096 buf[recps].content.mask[i++] = CPU_TO_LE16(0xFFFF);
7097 ice_set_bit(entry->rid, rm->r_bitmap);
7099 LIST_ADD(&last_chain_entry->l_entry, &rm->rg_list);
7100 if (sizeof(buf[recps].recipe_bitmap) >=
7101 sizeof(rm->r_bitmap)) {
7102 ice_memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
7103 sizeof(buf[recps].recipe_bitmap),
7104 ICE_NONDMA_TO_NONDMA);
7106 status = ICE_ERR_BAD_PTR;
7109 buf[recps].content.act_ctrl_fwd_priority = rm->priority;
7112 rm->root_rid = (u8)rid;
7114 status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
7118 status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
7119 ice_release_change_lock(hw);
7123 /* Every recipe that just got created add it to the recipe
7126 LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {
7127 struct ice_switch_info *sw = hw->switch_info;
7128 bool is_root, idx_found = false;
7129 struct ice_sw_recipe *recp;
7130 u16 idx, buf_idx = 0;
7132 /* find buffer index for copying some data */
7133 for (idx = 0; idx < rm->n_grp_count; idx++)
7134 if (buf[idx].recipe_indx == entry->rid) {
7140 status = ICE_ERR_OUT_OF_RANGE;
7144 recp = &sw->recp_list[entry->rid];
7145 is_root = (rm->root_rid == entry->rid);
7146 recp->is_root = is_root;
7148 recp->root_rid = entry->rid;
7149 recp->big_recp = (is_root && rm->n_grp_count > 1);
7151 ice_memcpy(&recp->ext_words, entry->r_group.pairs,
7152 entry->r_group.n_val_pairs *
7153 sizeof(struct ice_fv_word),
7154 ICE_NONDMA_TO_NONDMA);
7156 ice_memcpy(recp->r_bitmap, buf[buf_idx].recipe_bitmap,
7157 sizeof(recp->r_bitmap), ICE_NONDMA_TO_NONDMA);
7159 /* Copy non-result fv index values and masks to recipe. This
7160 * call will also update the result recipe bitmask.
7162 ice_collect_result_idx(&buf[buf_idx], recp);
7164 /* for non-root recipes, also copy to the root, this allows
7165 * easier matching of a complete chained recipe
7168 ice_collect_result_idx(&buf[buf_idx],
7169 &sw->recp_list[rm->root_rid]);
7171 recp->n_ext_words = entry->r_group.n_val_pairs;
7172 recp->chain_idx = entry->chain_idx;
7173 recp->priority = buf[buf_idx].content.act_ctrl_fwd_priority;
7174 recp->n_grp_count = rm->n_grp_count;
7175 recp->tun_type = rm->tun_type;
7176 recp->recp_created = true;
7190 * ice_create_recipe_group - creates recipe group
7191 * @hw: pointer to hardware structure
7192 * @rm: recipe management list entry
7193 * @lkup_exts: lookup elements
7195 static enum ice_status
7196 ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
7197 struct ice_prot_lkup_ext *lkup_exts)
7199 enum ice_status status;
7202 rm->n_grp_count = 0;
7204 /* Create recipes for words that are marked not done by packing them
7207 status = ice_create_first_fit_recp_def(hw, lkup_exts,
7208 &rm->rg_list, &recp_count);
7210 rm->n_grp_count += recp_count;
7211 rm->n_ext_words = lkup_exts->n_val_words;
7212 ice_memcpy(&rm->ext_words, lkup_exts->fv_words,
7213 sizeof(rm->ext_words), ICE_NONDMA_TO_NONDMA);
7214 ice_memcpy(rm->word_masks, lkup_exts->field_mask,
7215 sizeof(rm->word_masks), ICE_NONDMA_TO_NONDMA);
7222 * ice_get_fv - get field vectors/extraction sequences for spec. lookup types
7223 * @hw: pointer to hardware structure
7224 * @lkups: lookup elements or match criteria for the advanced recipe, one
7225 * structure per protocol header
7226 * @lkups_cnt: number of protocols
7227 * @bm: bitmap of field vectors to consider
7228 * @fv_list: pointer to a list that holds the returned field vectors
7230 static enum ice_status
7231 ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
7232 ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list)
7234 enum ice_status status;
7241 prot_ids = (u8 *)ice_calloc(hw, lkups_cnt, sizeof(*prot_ids));
7243 return ICE_ERR_NO_MEMORY;
7245 for (i = 0; i < lkups_cnt; i++)
7246 if (!ice_prot_type_to_id(lkups[i].type, &prot_ids[i])) {
7247 status = ICE_ERR_CFG;
7251 /* Find field vectors that include all specified protocol types */
7252 status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, bm, fv_list);
7255 ice_free(hw, prot_ids);
7260 * ice_tun_type_match_mask - determine if tun type needs a match mask
7261 * @tun_type: tunnel type
7262 * @mask: mask to be used for the tunnel
7264 static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask)
7267 case ICE_SW_TUN_VXLAN_GPE:
7268 case ICE_SW_TUN_GENEVE:
7269 case ICE_SW_TUN_VXLAN:
7270 case ICE_SW_TUN_NVGRE:
7271 case ICE_SW_TUN_UDP:
7272 case ICE_ALL_TUNNELS:
7273 case ICE_SW_TUN_AND_NON_TUN_QINQ:
7274 case ICE_NON_TUN_QINQ:
7275 case ICE_SW_TUN_PPPOE_QINQ:
7276 case ICE_SW_TUN_PPPOE_PAY_QINQ:
7277 case ICE_SW_TUN_PPPOE_IPV4_QINQ:
7278 case ICE_SW_TUN_PPPOE_IPV6_QINQ:
7279 *mask = ICE_TUN_FLAG_MASK;
7282 case ICE_SW_TUN_GENEVE_VLAN:
7283 case ICE_SW_TUN_VXLAN_VLAN:
7284 *mask = ICE_TUN_FLAG_MASK & ~ICE_TUN_FLAG_VLAN_MASK;
7294 * ice_add_special_words - Add words that are not protocols, such as metadata
7295 * @rinfo: other information regarding the rule e.g. priority and action info
7296 * @lkup_exts: lookup word structure
7298 static enum ice_status
7299 ice_add_special_words(struct ice_adv_rule_info *rinfo,
7300 struct ice_prot_lkup_ext *lkup_exts)
7304 /* If this is a tunneled packet, then add recipe index to match the
7305 * tunnel bit in the packet metadata flags.
7307 if (ice_tun_type_match_word(rinfo->tun_type, &mask)) {
7308 if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) {
7309 u8 word = lkup_exts->n_val_words++;
7311 lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW;
7312 lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF;
7313 lkup_exts->field_mask[word] = mask;
7315 return ICE_ERR_MAX_LIMIT;
7322 /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule
7323 * @hw: pointer to hardware structure
7324 * @rinfo: other information regarding the rule e.g. priority and action info
7325 * @bm: pointer to memory for returning the bitmap of field vectors
7328 ice_get_compat_fv_bitmap(struct ice_hw *hw, struct ice_adv_rule_info *rinfo,
7331 enum ice_prof_type prof_type;
7333 ice_zero_bitmap(bm, ICE_MAX_NUM_PROFILES);
7335 switch (rinfo->tun_type) {
7337 case ICE_NON_TUN_QINQ:
7338 prof_type = ICE_PROF_NON_TUN;
7340 case ICE_ALL_TUNNELS:
7341 prof_type = ICE_PROF_TUN_ALL;
7343 case ICE_SW_TUN_VXLAN_GPE:
7344 case ICE_SW_TUN_GENEVE:
7345 case ICE_SW_TUN_GENEVE_VLAN:
7346 case ICE_SW_TUN_VXLAN:
7347 case ICE_SW_TUN_VXLAN_VLAN:
7348 case ICE_SW_TUN_UDP:
7349 case ICE_SW_TUN_GTP:
7350 prof_type = ICE_PROF_TUN_UDP;
7352 case ICE_SW_TUN_NVGRE:
7353 prof_type = ICE_PROF_TUN_GRE;
7355 case ICE_SW_TUN_PPPOE:
7356 case ICE_SW_TUN_PPPOE_QINQ:
7357 prof_type = ICE_PROF_TUN_PPPOE;
7359 case ICE_SW_TUN_PPPOE_PAY:
7360 case ICE_SW_TUN_PPPOE_PAY_QINQ:
7361 ice_set_bit(ICE_PROFID_PPPOE_PAY, bm);
7363 case ICE_SW_TUN_PPPOE_IPV4:
7364 case ICE_SW_TUN_PPPOE_IPV4_QINQ:
7365 ice_set_bit(ICE_PROFID_PPPOE_IPV4_OTHER, bm);
7366 ice_set_bit(ICE_PROFID_PPPOE_IPV4_UDP, bm);
7367 ice_set_bit(ICE_PROFID_PPPOE_IPV4_TCP, bm);
7369 case ICE_SW_TUN_PPPOE_IPV4_TCP:
7370 ice_set_bit(ICE_PROFID_PPPOE_IPV4_TCP, bm);
7372 case ICE_SW_TUN_PPPOE_IPV4_UDP:
7373 ice_set_bit(ICE_PROFID_PPPOE_IPV4_UDP, bm);
7375 case ICE_SW_TUN_PPPOE_IPV6:
7376 case ICE_SW_TUN_PPPOE_IPV6_QINQ:
7377 ice_set_bit(ICE_PROFID_PPPOE_IPV6_OTHER, bm);
7378 ice_set_bit(ICE_PROFID_PPPOE_IPV6_UDP, bm);
7379 ice_set_bit(ICE_PROFID_PPPOE_IPV6_TCP, bm);
7381 case ICE_SW_TUN_PPPOE_IPV6_TCP:
7382 ice_set_bit(ICE_PROFID_PPPOE_IPV6_TCP, bm);
7384 case ICE_SW_TUN_PPPOE_IPV6_UDP:
7385 ice_set_bit(ICE_PROFID_PPPOE_IPV6_UDP, bm);
7387 case ICE_SW_TUN_PROFID_IPV6_ESP:
7388 case ICE_SW_TUN_IPV6_ESP:
7389 ice_set_bit(ICE_PROFID_IPV6_ESP, bm);
7391 case ICE_SW_TUN_PROFID_IPV6_AH:
7392 case ICE_SW_TUN_IPV6_AH:
7393 ice_set_bit(ICE_PROFID_IPV6_AH, bm);
7395 case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3:
7396 case ICE_SW_TUN_IPV6_L2TPV3:
7397 ice_set_bit(ICE_PROFID_MAC_IPV6_L2TPV3, bm);
7399 case ICE_SW_TUN_PROFID_IPV6_NAT_T:
7400 case ICE_SW_TUN_IPV6_NAT_T:
7401 ice_set_bit(ICE_PROFID_IPV6_NAT_T, bm);
7403 case ICE_SW_TUN_PROFID_IPV4_PFCP_NODE:
7404 ice_set_bit(ICE_PROFID_IPV4_PFCP_NODE, bm);
7406 case ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION:
7407 ice_set_bit(ICE_PROFID_IPV4_PFCP_SESSION, bm);
7409 case ICE_SW_TUN_PROFID_IPV6_PFCP_NODE:
7410 ice_set_bit(ICE_PROFID_IPV6_PFCP_NODE, bm);
7412 case ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION:
7413 ice_set_bit(ICE_PROFID_IPV6_PFCP_SESSION, bm);
7415 case ICE_SW_TUN_IPV4_NAT_T:
7416 ice_set_bit(ICE_PROFID_IPV4_NAT_T, bm);
7418 case ICE_SW_TUN_IPV4_L2TPV3:
7419 ice_set_bit(ICE_PROFID_MAC_IPV4_L2TPV3, bm);
7421 case ICE_SW_TUN_IPV4_ESP:
7422 ice_set_bit(ICE_PROFID_IPV4_ESP, bm);
7424 case ICE_SW_TUN_IPV4_AH:
7425 ice_set_bit(ICE_PROFID_IPV4_AH, bm);
7427 case ICE_SW_IPV4_TCP:
7428 ice_set_bit(ICE_PROFID_IPV4_TCP, bm);
7430 case ICE_SW_IPV4_UDP:
7431 ice_set_bit(ICE_PROFID_IPV4_UDP, bm);
7433 case ICE_SW_IPV6_TCP:
7434 ice_set_bit(ICE_PROFID_IPV6_TCP, bm);
7436 case ICE_SW_IPV6_UDP:
7437 ice_set_bit(ICE_PROFID_IPV6_UDP, bm);
7439 case ICE_SW_TUN_IPV4_GTPU_IPV4:
7440 ice_set_bit(ICE_PROFID_IPV4_GTPU_EH_IPV4_OTHER, bm);
7441 ice_set_bit(ICE_PROFID_IPV4_GTPU_IPV4_OTHER, bm);
7442 ice_set_bit(ICE_PROFID_IPV4_GTPU_EH_IPV4_UDP, bm);
7443 ice_set_bit(ICE_PROFID_IPV4_GTPU_IPV4_UDP, bm);
7444 ice_set_bit(ICE_PROFID_IPV4_GTPU_EH_IPV4_TCP, bm);
7445 ice_set_bit(ICE_PROFID_IPV4_GTPU_IPV4_TCP, bm);
7447 case ICE_SW_TUN_IPV6_GTPU_IPV4:
7448 ice_set_bit(ICE_PROFID_IPV6_GTPU_EH_IPV4_OTHER, bm);
7449 ice_set_bit(ICE_PROFID_IPV6_GTPU_IPV4_OTHER, bm);
7450 ice_set_bit(ICE_PROFID_IPV6_GTPU_EH_IPV4_UDP, bm);
7451 ice_set_bit(ICE_PROFID_IPV6_GTPU_IPV4_UDP, bm);
7452 ice_set_bit(ICE_PROFID_IPV6_GTPU_EH_IPV4_TCP, bm);
7453 ice_set_bit(ICE_PROFID_IPV6_GTPU_IPV4_TCP, bm);
7455 case ICE_SW_TUN_IPV4_GTPU_IPV6:
7456 ice_set_bit(ICE_PROFID_IPV4_GTPU_EH_IPV6_OTHER, bm);
7457 ice_set_bit(ICE_PROFID_IPV4_GTPU_IPV6_OTHER, bm);
7458 ice_set_bit(ICE_PROFID_IPV4_GTPU_EH_IPV6_UDP, bm);
7459 ice_set_bit(ICE_PROFID_IPV4_GTPU_IPV6_UDP, bm);
7460 ice_set_bit(ICE_PROFID_IPV4_GTPU_EH_IPV6_TCP, bm);
7461 ice_set_bit(ICE_PROFID_IPV4_GTPU_IPV6_TCP, bm);
7463 case ICE_SW_TUN_IPV6_GTPU_IPV6:
7464 ice_set_bit(ICE_PROFID_IPV6_GTPU_EH_IPV6_OTHER, bm);
7465 ice_set_bit(ICE_PROFID_IPV6_GTPU_IPV6_OTHER, bm);
7466 ice_set_bit(ICE_PROFID_IPV6_GTPU_EH_IPV6_UDP, bm);
7467 ice_set_bit(ICE_PROFID_IPV6_GTPU_IPV6_UDP, bm);
7468 ice_set_bit(ICE_PROFID_IPV6_GTPU_EH_IPV6_TCP, bm);
7469 ice_set_bit(ICE_PROFID_IPV6_GTPU_IPV6_TCP, bm);
7471 case ICE_SW_TUN_AND_NON_TUN:
7472 case ICE_SW_TUN_AND_NON_TUN_QINQ:
7474 prof_type = ICE_PROF_ALL;
7478 ice_get_sw_fv_bitmap(hw, prof_type, bm);
7482 * ice_is_prof_rule - determine if rule type is a profile rule
7483 * @type: the rule type
7485 * if the rule type is a profile rule, that means that there no field value
7486 * match required, in this case just a profile hit is required.
7488 bool ice_is_prof_rule(enum ice_sw_tunnel_type type)
7491 case ICE_SW_TUN_PROFID_IPV6_ESP:
7492 case ICE_SW_TUN_PROFID_IPV6_AH:
7493 case ICE_SW_TUN_PROFID_MAC_IPV6_L2TPV3:
7494 case ICE_SW_TUN_PROFID_IPV6_NAT_T:
7495 case ICE_SW_TUN_PROFID_IPV4_PFCP_NODE:
7496 case ICE_SW_TUN_PROFID_IPV4_PFCP_SESSION:
7497 case ICE_SW_TUN_PROFID_IPV6_PFCP_NODE:
7498 case ICE_SW_TUN_PROFID_IPV6_PFCP_SESSION:
7508 * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
7509 * @hw: pointer to hardware structure
7510 * @lkups: lookup elements or match criteria for the advanced recipe, one
7511 * structure per protocol header
7512 * @lkups_cnt: number of protocols
7513 * @rinfo: other information regarding the rule e.g. priority and action info
7514 * @rid: return the recipe ID of the recipe created
7516 static enum ice_status
7517 ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
7518 u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
7520 ice_declare_bitmap(fv_bitmap, ICE_MAX_NUM_PROFILES);
7521 ice_declare_bitmap(profiles, ICE_MAX_NUM_PROFILES);
7522 struct ice_prot_lkup_ext *lkup_exts;
7523 struct ice_recp_grp_entry *r_entry;
7524 struct ice_sw_fv_list_entry *fvit;
7525 struct ice_recp_grp_entry *r_tmp;
7526 struct ice_sw_fv_list_entry *tmp;
7527 enum ice_status status = ICE_SUCCESS;
7528 struct ice_sw_recipe *rm;
7531 if (!ice_is_prof_rule(rinfo->tun_type) && !lkups_cnt)
7532 return ICE_ERR_PARAM;
7534 lkup_exts = (struct ice_prot_lkup_ext *)
7535 ice_malloc(hw, sizeof(*lkup_exts));
7537 return ICE_ERR_NO_MEMORY;
7539 /* Determine the number of words to be matched and if it exceeds a
7540 * recipe's restrictions
7542 for (i = 0; i < lkups_cnt; i++) {
7545 if (lkups[i].type >= ICE_PROTOCOL_LAST) {
7546 status = ICE_ERR_CFG;
7547 goto err_free_lkup_exts;
7550 count = ice_fill_valid_words(&lkups[i], lkup_exts);
7552 status = ICE_ERR_CFG;
7553 goto err_free_lkup_exts;
7557 rm = (struct ice_sw_recipe *)ice_malloc(hw, sizeof(*rm));
7559 status = ICE_ERR_NO_MEMORY;
7560 goto err_free_lkup_exts;
7563 /* Get field vectors that contain fields extracted from all the protocol
7564 * headers being programmed.
7566 INIT_LIST_HEAD(&rm->fv_list);
7567 INIT_LIST_HEAD(&rm->rg_list);
7569 /* Get bitmap of field vectors (profiles) that are compatible with the
7570 * rule request; only these will be searched in the subsequent call to
7573 ice_get_compat_fv_bitmap(hw, rinfo, fv_bitmap);
7575 status = ice_get_fv(hw, lkups, lkups_cnt, fv_bitmap, &rm->fv_list);
7579 /* Create any special protocol/offset pairs, such as looking at tunnel
7580 * bits by extracting metadata
7582 status = ice_add_special_words(rinfo, lkup_exts);
7584 goto err_free_lkup_exts;
7586 /* Group match words into recipes using preferred recipe grouping
7589 status = ice_create_recipe_group(hw, rm, lkup_exts);
7593 /* set the recipe priority if specified */
7594 rm->priority = (u8)rinfo->priority;
7596 /* Find offsets from the field vector. Pick the first one for all the
7599 status = ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
7603 /* An empty FV list means to use all the profiles returned in the
7606 if (LIST_EMPTY(&rm->fv_list)) {
7609 ice_for_each_set_bit(j, fv_bitmap, ICE_MAX_NUM_PROFILES) {
7610 struct ice_sw_fv_list_entry *fvl;
7612 fvl = (struct ice_sw_fv_list_entry *)
7613 ice_malloc(hw, sizeof(*fvl));
7617 fvl->profile_id = j;
7618 LIST_ADD(&fvl->list_entry, &rm->fv_list);
7622 /* get bitmap of all profiles the recipe will be associated with */
7623 ice_zero_bitmap(profiles, ICE_MAX_NUM_PROFILES);
7624 LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry,
7626 ice_debug(hw, ICE_DBG_SW, "profile: %d\n", fvit->profile_id);
7627 ice_set_bit((u16)fvit->profile_id, profiles);
7630 /* Look for a recipe which matches our requested fv / mask list */
7631 *rid = ice_find_recp(hw, lkup_exts, rinfo->tun_type);
7632 if (*rid < ICE_MAX_NUM_RECIPES)
7633 /* Success if found a recipe that match the existing criteria */
7636 rm->tun_type = rinfo->tun_type;
7637 /* Recipe we need does not exist, add a recipe */
7638 status = ice_add_sw_recipe(hw, rm, profiles);
7642 /* Associate all the recipes created with all the profiles in the
7643 * common field vector.
7645 LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry,
7647 ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
7650 status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
7651 (u8 *)r_bitmap, NULL);
7655 ice_or_bitmap(r_bitmap, r_bitmap, rm->r_bitmap,
7656 ICE_MAX_NUM_RECIPES);
7657 status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
7661 status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
7664 ice_release_change_lock(hw);
7669 /* Update profile to recipe bitmap array */
7670 ice_cp_bitmap(profile_to_recipe[fvit->profile_id], r_bitmap,
7671 ICE_MAX_NUM_RECIPES);
7673 /* Update recipe to profile bitmap array */
7674 ice_for_each_set_bit(j, rm->r_bitmap, ICE_MAX_NUM_RECIPES)
7675 ice_set_bit((u16)fvit->profile_id,
7676 recipe_to_profile[j]);
7679 *rid = rm->root_rid;
7680 ice_memcpy(&hw->switch_info->recp_list[*rid].lkup_exts,
7681 lkup_exts, sizeof(*lkup_exts), ICE_NONDMA_TO_NONDMA);
7683 LIST_FOR_EACH_ENTRY_SAFE(r_entry, r_tmp, &rm->rg_list,
7684 ice_recp_grp_entry, l_entry) {
7685 LIST_DEL(&r_entry->l_entry);
7686 ice_free(hw, r_entry);
7689 LIST_FOR_EACH_ENTRY_SAFE(fvit, tmp, &rm->fv_list, ice_sw_fv_list_entry,
7691 LIST_DEL(&fvit->list_entry);
7696 ice_free(hw, rm->root_buf);
7701 ice_free(hw, lkup_exts);
7707 * ice_find_dummy_packet - find dummy packet by tunnel type
7709 * @lkups: lookup elements or match criteria for the advanced recipe, one
7710 * structure per protocol header
7711 * @lkups_cnt: number of protocols
7712 * @tun_type: tunnel type from the match criteria
7713 * @pkt: dummy packet to fill according to filter match criteria
7714 * @pkt_len: packet length of dummy packet
7715 * @offsets: pointer to receive the pointer to the offsets for the packet
7718 ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
7719 enum ice_sw_tunnel_type tun_type, const u8 **pkt,
7721 const struct ice_dummy_pkt_offsets **offsets)
7723 bool tcp = false, udp = false, ipv6 = false, vlan = false;
7727 for (i = 0; i < lkups_cnt; i++) {
7728 if (lkups[i].type == ICE_UDP_ILOS)
7730 else if (lkups[i].type == ICE_TCP_IL)
7732 else if (lkups[i].type == ICE_IPV6_OFOS)
7734 else if (lkups[i].type == ICE_VLAN_OFOS)
7736 else if (lkups[i].type == ICE_IPV4_OFOS &&
7737 lkups[i].h_u.ipv4_hdr.protocol ==
7738 ICE_IPV4_NVGRE_PROTO_ID &&
7739 lkups[i].m_u.ipv4_hdr.protocol ==
7742 else if (lkups[i].type == ICE_PPPOE &&
7743 lkups[i].h_u.pppoe_hdr.ppp_prot_id ==
7744 CPU_TO_BE16(ICE_PPP_IPV6_PROTO_ID) &&
7745 lkups[i].m_u.pppoe_hdr.ppp_prot_id ==
7748 else if (lkups[i].type == ICE_ETYPE_OL &&
7749 lkups[i].h_u.ethertype.ethtype_id ==
7750 CPU_TO_BE16(ICE_IPV6_ETHER_ID) &&
7751 lkups[i].m_u.ethertype.ethtype_id ==
7754 else if (lkups[i].type == ICE_IPV4_IL &&
7755 lkups[i].h_u.ipv4_hdr.protocol ==
7757 lkups[i].m_u.ipv4_hdr.protocol ==
7762 if ((tun_type == ICE_SW_TUN_AND_NON_TUN_QINQ ||
7763 tun_type == ICE_NON_TUN_QINQ) && ipv6) {
7764 *pkt = dummy_qinq_ipv6_pkt;
7765 *pkt_len = sizeof(dummy_qinq_ipv6_pkt);
7766 *offsets = dummy_qinq_ipv6_packet_offsets;
7768 } else if (tun_type == ICE_SW_TUN_AND_NON_TUN_QINQ ||
7769 tun_type == ICE_NON_TUN_QINQ) {
7770 *pkt = dummy_qinq_ipv4_pkt;
7771 *pkt_len = sizeof(dummy_qinq_ipv4_pkt);
7772 *offsets = dummy_qinq_ipv4_packet_offsets;
7776 if (tun_type == ICE_SW_TUN_PPPOE_IPV6_QINQ) {
7777 *pkt = dummy_qinq_pppoe_ipv6_packet;
7778 *pkt_len = sizeof(dummy_qinq_pppoe_ipv6_packet);
7779 *offsets = dummy_qinq_pppoe_packet_ipv6_offsets;
7781 } else if (tun_type == ICE_SW_TUN_PPPOE_IPV4_QINQ) {
7782 *pkt = dummy_qinq_pppoe_ipv4_pkt;
7783 *pkt_len = sizeof(dummy_qinq_pppoe_ipv4_pkt);
7784 *offsets = dummy_qinq_pppoe_ipv4_packet_offsets;
7786 } else if (tun_type == ICE_SW_TUN_PPPOE_QINQ ||
7787 tun_type == ICE_SW_TUN_PPPOE_PAY_QINQ) {
7788 *pkt = dummy_qinq_pppoe_ipv4_pkt;
7789 *pkt_len = sizeof(dummy_qinq_pppoe_ipv4_pkt);
7790 *offsets = dummy_qinq_pppoe_packet_offsets;
7794 if (tun_type == ICE_SW_TUN_IPV4_GTPU_NO_PAY) {
7795 *pkt = dummy_ipv4_gtpu_ipv4_packet;
7796 *pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_packet);
7797 *offsets = dummy_ipv4_gtp_no_pay_packet_offsets;
7799 } else if (tun_type == ICE_SW_TUN_IPV6_GTPU_NO_PAY) {
7800 *pkt = dummy_ipv6_gtpu_ipv6_packet;
7801 *pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_packet);
7802 *offsets = dummy_ipv6_gtp_no_pay_packet_offsets;
7804 } else if (tun_type == ICE_SW_TUN_IPV4_GTPU_IPV4) {
7805 *pkt = dummy_ipv4_gtpu_ipv4_packet;
7806 *pkt_len = sizeof(dummy_ipv4_gtpu_ipv4_packet);
7807 *offsets = dummy_ipv4_gtpu_ipv4_packet_offsets;
7809 } else if (tun_type == ICE_SW_TUN_IPV4_GTPU_IPV6) {
7810 *pkt = dummy_ipv4_gtpu_ipv6_packet;
7811 *pkt_len = sizeof(dummy_ipv4_gtpu_ipv6_packet);
7812 *offsets = dummy_ipv4_gtpu_ipv6_packet_offsets;
7814 } else if (tun_type == ICE_SW_TUN_IPV6_GTPU_IPV4) {
7815 *pkt = dummy_ipv6_gtpu_ipv4_packet;
7816 *pkt_len = sizeof(dummy_ipv6_gtpu_ipv4_packet);
7817 *offsets = dummy_ipv6_gtpu_ipv4_packet_offsets;
7819 } else if (tun_type == ICE_SW_TUN_IPV6_GTPU_IPV6) {
7820 *pkt = dummy_ipv6_gtpu_ipv6_packet;
7821 *pkt_len = sizeof(dummy_ipv6_gtpu_ipv6_packet);
7822 *offsets = dummy_ipv6_gtpu_ipv6_packet_offsets;
7826 if (tun_type == ICE_SW_TUN_IPV4_ESP) {
7827 *pkt = dummy_ipv4_esp_pkt;
7828 *pkt_len = sizeof(dummy_ipv4_esp_pkt);
7829 *offsets = dummy_ipv4_esp_packet_offsets;
7833 if (tun_type == ICE_SW_TUN_IPV6_ESP) {
7834 *pkt = dummy_ipv6_esp_pkt;
7835 *pkt_len = sizeof(dummy_ipv6_esp_pkt);
7836 *offsets = dummy_ipv6_esp_packet_offsets;
7840 if (tun_type == ICE_SW_TUN_IPV4_AH) {
7841 *pkt = dummy_ipv4_ah_pkt;
7842 *pkt_len = sizeof(dummy_ipv4_ah_pkt);
7843 *offsets = dummy_ipv4_ah_packet_offsets;
7847 if (tun_type == ICE_SW_TUN_IPV6_AH) {
7848 *pkt = dummy_ipv6_ah_pkt;
7849 *pkt_len = sizeof(dummy_ipv6_ah_pkt);
7850 *offsets = dummy_ipv6_ah_packet_offsets;
7854 if (tun_type == ICE_SW_TUN_IPV4_NAT_T) {
7855 *pkt = dummy_ipv4_nat_pkt;
7856 *pkt_len = sizeof(dummy_ipv4_nat_pkt);
7857 *offsets = dummy_ipv4_nat_packet_offsets;
7861 if (tun_type == ICE_SW_TUN_IPV6_NAT_T) {
7862 *pkt = dummy_ipv6_nat_pkt;
7863 *pkt_len = sizeof(dummy_ipv6_nat_pkt);
7864 *offsets = dummy_ipv6_nat_packet_offsets;
7868 if (tun_type == ICE_SW_TUN_IPV4_L2TPV3) {
7869 *pkt = dummy_ipv4_l2tpv3_pkt;
7870 *pkt_len = sizeof(dummy_ipv4_l2tpv3_pkt);
7871 *offsets = dummy_ipv4_l2tpv3_packet_offsets;
7875 if (tun_type == ICE_SW_TUN_IPV6_L2TPV3) {
7876 *pkt = dummy_ipv6_l2tpv3_pkt;
7877 *pkt_len = sizeof(dummy_ipv6_l2tpv3_pkt);
7878 *offsets = dummy_ipv6_l2tpv3_packet_offsets;
7882 if (tun_type == ICE_SW_TUN_GTP) {
7883 *pkt = dummy_udp_gtp_packet;
7884 *pkt_len = sizeof(dummy_udp_gtp_packet);
7885 *offsets = dummy_udp_gtp_packet_offsets;
7889 if (tun_type == ICE_SW_TUN_PPPOE && ipv6) {
7890 *pkt = dummy_pppoe_ipv6_packet;
7891 *pkt_len = sizeof(dummy_pppoe_ipv6_packet);
7892 *offsets = dummy_pppoe_packet_offsets;
7894 } else if (tun_type == ICE_SW_TUN_PPPOE ||
7895 tun_type == ICE_SW_TUN_PPPOE_PAY) {
7896 *pkt = dummy_pppoe_ipv4_packet;
7897 *pkt_len = sizeof(dummy_pppoe_ipv4_packet);
7898 *offsets = dummy_pppoe_packet_offsets;
7902 if (tun_type == ICE_SW_TUN_PPPOE_IPV4) {
7903 *pkt = dummy_pppoe_ipv4_packet;
7904 *pkt_len = sizeof(dummy_pppoe_ipv4_packet);
7905 *offsets = dummy_pppoe_packet_ipv4_offsets;
7909 if (tun_type == ICE_SW_TUN_PPPOE_IPV4_TCP) {
7910 *pkt = dummy_pppoe_ipv4_tcp_packet;
7911 *pkt_len = sizeof(dummy_pppoe_ipv4_tcp_packet);
7912 *offsets = dummy_pppoe_ipv4_tcp_packet_offsets;
7916 if (tun_type == ICE_SW_TUN_PPPOE_IPV4_UDP) {
7917 *pkt = dummy_pppoe_ipv4_udp_packet;
7918 *pkt_len = sizeof(dummy_pppoe_ipv4_udp_packet);
7919 *offsets = dummy_pppoe_ipv4_udp_packet_offsets;
7923 if (tun_type == ICE_SW_TUN_PPPOE_IPV6) {
7924 *pkt = dummy_pppoe_ipv6_packet;
7925 *pkt_len = sizeof(dummy_pppoe_ipv6_packet);
7926 *offsets = dummy_pppoe_packet_ipv6_offsets;
7930 if (tun_type == ICE_SW_TUN_PPPOE_IPV6_TCP) {
7931 *pkt = dummy_pppoe_ipv6_tcp_packet;
7932 *pkt_len = sizeof(dummy_pppoe_ipv6_tcp_packet);
7933 *offsets = dummy_pppoe_packet_ipv6_tcp_offsets;
7937 if (tun_type == ICE_SW_TUN_PPPOE_IPV6_UDP) {
7938 *pkt = dummy_pppoe_ipv6_udp_packet;
7939 *pkt_len = sizeof(dummy_pppoe_ipv6_udp_packet);
7940 *offsets = dummy_pppoe_packet_ipv6_udp_offsets;
7944 if (tun_type == ICE_SW_IPV4_TCP) {
7945 *pkt = dummy_tcp_packet;
7946 *pkt_len = sizeof(dummy_tcp_packet);
7947 *offsets = dummy_tcp_packet_offsets;
7951 if (tun_type == ICE_SW_IPV4_UDP) {
7952 *pkt = dummy_udp_packet;
7953 *pkt_len = sizeof(dummy_udp_packet);
7954 *offsets = dummy_udp_packet_offsets;
7958 if (tun_type == ICE_SW_IPV6_TCP) {
7959 *pkt = dummy_tcp_ipv6_packet;
7960 *pkt_len = sizeof(dummy_tcp_ipv6_packet);
7961 *offsets = dummy_tcp_ipv6_packet_offsets;
7965 if (tun_type == ICE_SW_IPV6_UDP) {
7966 *pkt = dummy_udp_ipv6_packet;
7967 *pkt_len = sizeof(dummy_udp_ipv6_packet);
7968 *offsets = dummy_udp_ipv6_packet_offsets;
7972 if (tun_type == ICE_ALL_TUNNELS) {
7973 *pkt = dummy_gre_udp_packet;
7974 *pkt_len = sizeof(dummy_gre_udp_packet);
7975 *offsets = dummy_gre_udp_packet_offsets;
7979 if (tun_type == ICE_SW_TUN_NVGRE || gre) {
7981 *pkt = dummy_gre_tcp_packet;
7982 *pkt_len = sizeof(dummy_gre_tcp_packet);
7983 *offsets = dummy_gre_tcp_packet_offsets;
7987 *pkt = dummy_gre_udp_packet;
7988 *pkt_len = sizeof(dummy_gre_udp_packet);
7989 *offsets = dummy_gre_udp_packet_offsets;
7993 if (tun_type == ICE_SW_TUN_VXLAN || tun_type == ICE_SW_TUN_GENEVE ||
7994 tun_type == ICE_SW_TUN_VXLAN_GPE || tun_type == ICE_SW_TUN_UDP ||
7995 tun_type == ICE_SW_TUN_GENEVE_VLAN ||
7996 tun_type == ICE_SW_TUN_VXLAN_VLAN) {
7998 *pkt = dummy_udp_tun_tcp_packet;
7999 *pkt_len = sizeof(dummy_udp_tun_tcp_packet);
8000 *offsets = dummy_udp_tun_tcp_packet_offsets;
8004 *pkt = dummy_udp_tun_udp_packet;
8005 *pkt_len = sizeof(dummy_udp_tun_udp_packet);
8006 *offsets = dummy_udp_tun_udp_packet_offsets;
8012 *pkt = dummy_vlan_udp_packet;
8013 *pkt_len = sizeof(dummy_vlan_udp_packet);
8014 *offsets = dummy_vlan_udp_packet_offsets;
8017 *pkt = dummy_udp_packet;
8018 *pkt_len = sizeof(dummy_udp_packet);
8019 *offsets = dummy_udp_packet_offsets;
8021 } else if (udp && ipv6) {
8023 *pkt = dummy_vlan_udp_ipv6_packet;
8024 *pkt_len = sizeof(dummy_vlan_udp_ipv6_packet);
8025 *offsets = dummy_vlan_udp_ipv6_packet_offsets;
8028 *pkt = dummy_udp_ipv6_packet;
8029 *pkt_len = sizeof(dummy_udp_ipv6_packet);
8030 *offsets = dummy_udp_ipv6_packet_offsets;
8032 } else if ((tcp && ipv6) || ipv6) {
8034 *pkt = dummy_vlan_tcp_ipv6_packet;
8035 *pkt_len = sizeof(dummy_vlan_tcp_ipv6_packet);
8036 *offsets = dummy_vlan_tcp_ipv6_packet_offsets;
8039 *pkt = dummy_tcp_ipv6_packet;
8040 *pkt_len = sizeof(dummy_tcp_ipv6_packet);
8041 *offsets = dummy_tcp_ipv6_packet_offsets;
8046 *pkt = dummy_vlan_tcp_packet;
8047 *pkt_len = sizeof(dummy_vlan_tcp_packet);
8048 *offsets = dummy_vlan_tcp_packet_offsets;
8050 *pkt = dummy_tcp_packet;
8051 *pkt_len = sizeof(dummy_tcp_packet);
8052 *offsets = dummy_tcp_packet_offsets;
8057 * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
8059 * @lkups: lookup elements or match criteria for the advanced recipe, one
8060 * structure per protocol header
8061 * @lkups_cnt: number of protocols
8062 * @s_rule: stores rule information from the match criteria
8063 * @dummy_pkt: dummy packet to fill according to filter match criteria
8064 * @pkt_len: packet length of dummy packet
8065 * @offsets: offset info for the dummy packet
8067 static enum ice_status
8068 ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
8069 struct ice_aqc_sw_rules_elem *s_rule,
8070 const u8 *dummy_pkt, u16 pkt_len,
8071 const struct ice_dummy_pkt_offsets *offsets)
8076 /* Start with a packet with a pre-defined/dummy content. Then, fill
8077 * in the header values to be looked up or matched.
8079 pkt = s_rule->pdata.lkup_tx_rx.hdr;
8081 ice_memcpy(pkt, dummy_pkt, pkt_len, ICE_NONDMA_TO_NONDMA);
8083 for (i = 0; i < lkups_cnt; i++) {
8084 enum ice_protocol_type type;
8085 u16 offset = 0, len = 0, j;
8088 /* find the start of this layer; it should be found since this
8089 * was already checked when search for the dummy packet
8091 type = lkups[i].type;
8092 for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
8093 if (type == offsets[j].type) {
8094 offset = offsets[j].offset;
8099 /* this should never happen in a correct calling sequence */
8101 return ICE_ERR_PARAM;
8103 switch (lkups[i].type) {
8106 len = sizeof(struct ice_ether_hdr);
8109 len = sizeof(struct ice_ethtype_hdr);
8113 len = sizeof(struct ice_vlan_hdr);
8117 len = sizeof(struct ice_ipv4_hdr);
8121 len = sizeof(struct ice_ipv6_hdr);
8126 len = sizeof(struct ice_l4_hdr);
8129 len = sizeof(struct ice_sctp_hdr);
8132 len = sizeof(struct ice_nvgre);
8137 len = sizeof(struct ice_udp_tnl_hdr);
8141 case ICE_GTP_NO_PAY:
8142 len = sizeof(struct ice_udp_gtp_hdr);
8145 len = sizeof(struct ice_pppoe_hdr);
8148 len = sizeof(struct ice_esp_hdr);
8151 len = sizeof(struct ice_nat_t_hdr);
8154 len = sizeof(struct ice_ah_hdr);
8157 len = sizeof(struct ice_l2tpv3_sess_hdr);
8160 return ICE_ERR_PARAM;
8163 /* the length should be a word multiple */
8164 if (len % ICE_BYTES_PER_WORD)
8167 /* We have the offset to the header start, the length, the
8168 * caller's header values and mask. Use this information to
8169 * copy the data into the dummy packet appropriately based on
8170 * the mask. Note that we need to only write the bits as
8171 * indicated by the mask to make sure we don't improperly write
8172 * over any significant packet data.
8174 for (j = 0; j < len / sizeof(u16); j++)
8175 if (((u16 *)&lkups[i].m_u)[j])
8176 ((u16 *)(pkt + offset))[j] =
8177 (((u16 *)(pkt + offset))[j] &
8178 ~((u16 *)&lkups[i].m_u)[j]) |
8179 (((u16 *)&lkups[i].h_u)[j] &
8180 ((u16 *)&lkups[i].m_u)[j]);
8183 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(pkt_len);
8189 * ice_fill_adv_packet_tun - fill dummy packet with udp tunnel port
8190 * @hw: pointer to the hardware structure
8191 * @tun_type: tunnel type
8192 * @pkt: dummy packet to fill in
8193 * @offsets: offset info for the dummy packet
8195 static enum ice_status
8196 ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type,
8197 u8 *pkt, const struct ice_dummy_pkt_offsets *offsets)
8202 case ICE_SW_TUN_AND_NON_TUN:
8203 case ICE_SW_TUN_VXLAN_GPE:
8204 case ICE_SW_TUN_VXLAN:
8205 case ICE_SW_TUN_VXLAN_VLAN:
8206 case ICE_SW_TUN_UDP:
8207 if (!ice_get_open_tunnel_port(hw, TNL_VXLAN, &open_port))
8211 case ICE_SW_TUN_GENEVE:
8212 case ICE_SW_TUN_GENEVE_VLAN:
8213 if (!ice_get_open_tunnel_port(hw, TNL_GENEVE, &open_port))
8218 /* Nothing needs to be done for this tunnel type */
8222 /* Find the outer UDP protocol header and insert the port number */
8223 for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) {
8224 if (offsets[i].type == ICE_UDP_OF) {
8225 struct ice_l4_hdr *hdr;
8228 offset = offsets[i].offset;
8229 hdr = (struct ice_l4_hdr *)&pkt[offset];
8230 hdr->dst_port = CPU_TO_BE16(open_port);
8240 * ice_find_adv_rule_entry - Search a rule entry
8241 * @hw: pointer to the hardware structure
8242 * @lkups: lookup elements or match criteria for the advanced recipe, one
8243 * structure per protocol header
8244 * @lkups_cnt: number of protocols
8245 * @recp_id: recipe ID for which we are finding the rule
8246 * @rinfo: other information regarding the rule e.g. priority and action info
8248 * Helper function to search for a given advance rule entry
8249 * Returns pointer to entry storing the rule if found
8251 static struct ice_adv_fltr_mgmt_list_entry *
8252 ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
8253 u16 lkups_cnt, u16 recp_id,
8254 struct ice_adv_rule_info *rinfo)
8256 struct ice_adv_fltr_mgmt_list_entry *list_itr;
8257 struct ice_switch_info *sw = hw->switch_info;
8260 LIST_FOR_EACH_ENTRY(list_itr, &sw->recp_list[recp_id].filt_rules,
8261 ice_adv_fltr_mgmt_list_entry, list_entry) {
8262 bool lkups_matched = true;
8264 if (lkups_cnt != list_itr->lkups_cnt)
8266 for (i = 0; i < list_itr->lkups_cnt; i++)
8267 if (memcmp(&list_itr->lkups[i], &lkups[i],
8269 lkups_matched = false;
8272 if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
8273 rinfo->tun_type == list_itr->rule_info.tun_type &&
8281 * ice_adv_add_update_vsi_list
8282 * @hw: pointer to the hardware structure
8283 * @m_entry: pointer to current adv filter management list entry
8284 * @cur_fltr: filter information from the book keeping entry
8285 * @new_fltr: filter information with the new VSI to be added
8287 * Call AQ command to add or update previously created VSI list with new VSI.
8289 * Helper function to do book keeping associated with adding filter information
8290 * The algorithm to do the booking keeping is described below :
8291 * When a VSI needs to subscribe to a given advanced filter
8292 * if only one VSI has been added till now
8293 * Allocate a new VSI list and add two VSIs
8294 * to this list using switch rule command
8295 * Update the previously created switch rule with the
8296 * newly created VSI list ID
8297 * if a VSI list was previously created
8298 * Add the new VSI to the previously created VSI list set
8299 * using the update switch rule command
8301 static enum ice_status
8302 ice_adv_add_update_vsi_list(struct ice_hw *hw,
8303 struct ice_adv_fltr_mgmt_list_entry *m_entry,
8304 struct ice_adv_rule_info *cur_fltr,
8305 struct ice_adv_rule_info *new_fltr)
8307 enum ice_status status;
8308 u16 vsi_list_id = 0;
8310 if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
8311 cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
8312 cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
8313 return ICE_ERR_NOT_IMPL;
8315 if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
8316 new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
8317 (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
8318 cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
8319 return ICE_ERR_NOT_IMPL;
8321 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
8322 /* Only one entry existed in the mapping and it was not already
8323 * a part of a VSI list. So, create a VSI list with the old and
8326 struct ice_fltr_info tmp_fltr;
8327 u16 vsi_handle_arr[2];
8329 /* A rule already exists with the new VSI being added */
8330 if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
8331 new_fltr->sw_act.fwd_id.hw_vsi_id)
8332 return ICE_ERR_ALREADY_EXISTS;
8334 vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
8335 vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
8336 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
8342 ice_memset(&tmp_fltr, 0, sizeof(tmp_fltr), ICE_NONDMA_MEM);
8343 tmp_fltr.flag = m_entry->rule_info.sw_act.flag;
8344 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
8345 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
8346 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
8347 tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
8349 /* Update the previous switch rule of "forward to VSI" to
8352 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
8356 cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
8357 cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
8358 m_entry->vsi_list_info =
8359 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
8362 u16 vsi_handle = new_fltr->sw_act.vsi_handle;
8364 if (!m_entry->vsi_list_info)
8367 /* A rule already exists with the new VSI being added */
8368 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
8371 /* Update the previously created VSI list set with
8372 * the new VSI ID passed in
8374 vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
8376 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
8378 ice_aqc_opc_update_sw_rules,
8380 /* update VSI list mapping info with new VSI ID */
8382 ice_set_bit(vsi_handle,
8383 m_entry->vsi_list_info->vsi_map);
8386 m_entry->vsi_count++;
8391 * ice_add_adv_rule - helper function to create an advanced switch rule
8392 * @hw: pointer to the hardware structure
8393 * @lkups: information on the words that needs to be looked up. All words
8394 * together makes one recipe
8395 * @lkups_cnt: num of entries in the lkups array
8396 * @rinfo: other information related to the rule that needs to be programmed
8397 * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
8398 * ignored is case of error.
8400 * This function can program only 1 rule at a time. The lkups is used to
8401 * describe the all the words that forms the "lookup" portion of the recipe.
8402 * These words can span multiple protocols. Callers to this function need to
8403 * pass in a list of protocol headers with lookup information along and mask
8404 * that determines which words are valid from the given protocol header.
8405 * rinfo describes other information related to this rule such as forwarding
8406 * IDs, priority of this rule, etc.
8409 ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
8410 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
8411 struct ice_rule_query_data *added_entry)
8413 struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
8414 u16 rid = 0, i, pkt_len, rule_buf_sz, vsi_handle;
8415 const struct ice_dummy_pkt_offsets *pkt_offsets;
8416 struct ice_aqc_sw_rules_elem *s_rule = NULL;
8417 struct LIST_HEAD_TYPE *rule_head;
8418 struct ice_switch_info *sw;
8419 enum ice_status status;
8420 const u8 *pkt = NULL;
8426 /* Initialize profile to result index bitmap */
8427 if (!hw->switch_info->prof_res_bm_init) {
8428 hw->switch_info->prof_res_bm_init = 1;
8429 ice_init_prof_result_bm(hw);
8432 prof_rule = ice_is_prof_rule(rinfo->tun_type);
8433 if (!prof_rule && !lkups_cnt)
8434 return ICE_ERR_PARAM;
8436 /* get # of words we need to match */
8438 for (i = 0; i < lkups_cnt; i++) {
8441 ptr = (u16 *)&lkups[i].m_u;
8442 for (j = 0; j < sizeof(lkups->m_u) / sizeof(u16); j++)
8448 if (word_cnt > ICE_MAX_CHAIN_WORDS)
8449 return ICE_ERR_PARAM;
8451 if (!word_cnt || word_cnt > ICE_MAX_CHAIN_WORDS)
8452 return ICE_ERR_PARAM;
8455 /* make sure that we can locate a dummy packet */
8456 ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt, &pkt_len,
8459 status = ICE_ERR_PARAM;
8460 goto err_ice_add_adv_rule;
8463 if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
8464 rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
8465 rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
8466 rinfo->sw_act.fltr_act == ICE_DROP_PACKET))
8469 vsi_handle = rinfo->sw_act.vsi_handle;
8470 if (!ice_is_vsi_valid(hw, vsi_handle))
8471 return ICE_ERR_PARAM;
8473 if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
8474 rinfo->sw_act.fwd_id.hw_vsi_id =
8475 ice_get_hw_vsi_num(hw, vsi_handle);
8476 if (rinfo->sw_act.flag & ICE_FLTR_TX)
8477 rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
8479 status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
8482 m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
8484 /* we have to add VSI to VSI_LIST and increment vsi_count.
8485 * Also Update VSI list so that we can change forwarding rule
8486 * if the rule already exists, we will check if it exists with
8487 * same vsi_id, if not then add it to the VSI list if it already
8488 * exists if not then create a VSI list and add the existing VSI
8489 * ID and the new VSI ID to the list
8490 * We will add that VSI to the list
8492 status = ice_adv_add_update_vsi_list(hw, m_entry,
8493 &m_entry->rule_info,
8496 added_entry->rid = rid;
8497 added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
8498 added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
8502 rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE + pkt_len;
8503 s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rule_buf_sz);
8505 return ICE_ERR_NO_MEMORY;
8506 act |= ICE_SINGLE_ACT_LAN_ENABLE;
8507 switch (rinfo->sw_act.fltr_act) {
8508 case ICE_FWD_TO_VSI:
8509 act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
8510 ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
8511 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
8514 act |= ICE_SINGLE_ACT_TO_Q;
8515 act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
8516 ICE_SINGLE_ACT_Q_INDEX_M;
8518 case ICE_FWD_TO_QGRP:
8519 q_rgn = rinfo->sw_act.qgrp_size > 0 ?
8520 (u8)ice_ilog2(rinfo->sw_act.qgrp_size) : 0;
8521 act |= ICE_SINGLE_ACT_TO_Q;
8522 act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
8523 ICE_SINGLE_ACT_Q_INDEX_M;
8524 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
8525 ICE_SINGLE_ACT_Q_REGION_M;
8527 case ICE_DROP_PACKET:
8528 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
8529 ICE_SINGLE_ACT_VALID_BIT;
8532 status = ICE_ERR_CFG;
8533 goto err_ice_add_adv_rule;
8536 /* set the rule LOOKUP type based on caller specified 'RX'
8537 * instead of hardcoding it to be either LOOKUP_TX/RX
8539 * for 'RX' set the source to be the port number
8540 * for 'TX' set the source to be the source HW VSI number (determined
8544 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX);
8545 s_rule->pdata.lkup_tx_rx.src =
8546 CPU_TO_LE16(hw->port_info->lport);
8548 s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
8549 s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(rinfo->sw_act.src);
8552 s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(rid);
8553 s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
8555 status = ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, pkt,
8556 pkt_len, pkt_offsets);
8558 goto err_ice_add_adv_rule;
8560 if (rinfo->tun_type != ICE_NON_TUN &&
8561 rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) {
8562 status = ice_fill_adv_packet_tun(hw, rinfo->tun_type,
8563 s_rule->pdata.lkup_tx_rx.hdr,
8566 goto err_ice_add_adv_rule;
8569 status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
8570 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
8573 goto err_ice_add_adv_rule;
8574 adv_fltr = (struct ice_adv_fltr_mgmt_list_entry *)
8575 ice_malloc(hw, sizeof(struct ice_adv_fltr_mgmt_list_entry));
8577 status = ICE_ERR_NO_MEMORY;
8578 goto err_ice_add_adv_rule;
8581 adv_fltr->lkups = (struct ice_adv_lkup_elem *)
8582 ice_memdup(hw, lkups, lkups_cnt * sizeof(*lkups),
8583 ICE_NONDMA_TO_NONDMA);
8584 if (!adv_fltr->lkups && !prof_rule) {
8585 status = ICE_ERR_NO_MEMORY;
8586 goto err_ice_add_adv_rule;
8589 adv_fltr->lkups_cnt = lkups_cnt;
8590 adv_fltr->rule_info = *rinfo;
8591 adv_fltr->rule_info.fltr_rule_id =
8592 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
8593 sw = hw->switch_info;
8594 sw->recp_list[rid].adv_rule = true;
8595 rule_head = &sw->recp_list[rid].filt_rules;
8597 if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
8598 adv_fltr->vsi_count = 1;
8600 /* Add rule entry to book keeping list */
8601 LIST_ADD(&adv_fltr->list_entry, rule_head);
8603 added_entry->rid = rid;
8604 added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
8605 added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
8607 err_ice_add_adv_rule:
8608 if (status && adv_fltr) {
8609 ice_free(hw, adv_fltr->lkups);
8610 ice_free(hw, adv_fltr);
8613 ice_free(hw, s_rule);
8619 * ice_adv_rem_update_vsi_list
8620 * @hw: pointer to the hardware structure
8621 * @vsi_handle: VSI handle of the VSI to remove
8622 * @fm_list: filter management entry for which the VSI list management needs to
8625 static enum ice_status
8626 ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
8627 struct ice_adv_fltr_mgmt_list_entry *fm_list)
8629 struct ice_vsi_list_map_info *vsi_list_info;
8630 enum ice_sw_lkup_type lkup_type;
8631 enum ice_status status;
8634 if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
8635 fm_list->vsi_count == 0)
8636 return ICE_ERR_PARAM;
8638 /* A rule with the VSI being removed does not exist */
8639 if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
8640 return ICE_ERR_DOES_NOT_EXIST;
8642 lkup_type = ICE_SW_LKUP_LAST;
8643 vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
8644 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
8645 ice_aqc_opc_update_sw_rules,
8650 fm_list->vsi_count--;
8651 ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
8652 vsi_list_info = fm_list->vsi_list_info;
8653 if (fm_list->vsi_count == 1) {
8654 struct ice_fltr_info tmp_fltr;
8657 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
8659 if (!ice_is_vsi_valid(hw, rem_vsi_handle))
8660 return ICE_ERR_OUT_OF_RANGE;
8662 /* Make sure VSI list is empty before removing it below */
8663 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
8665 ice_aqc_opc_update_sw_rules,
8670 ice_memset(&tmp_fltr, 0, sizeof(tmp_fltr), ICE_NONDMA_MEM);
8671 tmp_fltr.flag = fm_list->rule_info.sw_act.flag;
8672 tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
8673 fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
8674 tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
8675 tmp_fltr.fwd_id.hw_vsi_id =
8676 ice_get_hw_vsi_num(hw, rem_vsi_handle);
8677 fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
8678 ice_get_hw_vsi_num(hw, rem_vsi_handle);
8679 fm_list->rule_info.sw_act.vsi_handle = rem_vsi_handle;
8681 /* Update the previous switch rule of "MAC forward to VSI" to
8682 * "MAC fwd to VSI list"
8684 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
8686 ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
8687 tmp_fltr.fwd_id.hw_vsi_id, status);
8690 fm_list->vsi_list_info->ref_cnt--;
8692 /* Remove the VSI list since it is no longer used */
8693 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
8695 ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
8696 vsi_list_id, status);
8700 LIST_DEL(&vsi_list_info->list_entry);
8701 ice_free(hw, vsi_list_info);
8702 fm_list->vsi_list_info = NULL;
8709 * ice_rem_adv_rule - removes existing advanced switch rule
8710 * @hw: pointer to the hardware structure
8711 * @lkups: information on the words that needs to be looked up. All words
8712 * together makes one recipe
8713 * @lkups_cnt: num of entries in the lkups array
8714 * @rinfo: Its the pointer to the rule information for the rule
8716 * This function can be used to remove 1 rule at a time. The lkups is
8717 * used to describe all the words that forms the "lookup" portion of the
8718 * rule. These words can span multiple protocols. Callers to this function
8719 * need to pass in a list of protocol headers with lookup information along
8720 * and mask that determines which words are valid from the given protocol
8721 * header. rinfo describes other information related to this rule such as
8722 * forwarding IDs, priority of this rule, etc.
8725 ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
8726 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
8728 struct ice_adv_fltr_mgmt_list_entry *list_elem;
8729 struct ice_prot_lkup_ext lkup_exts;
8730 struct ice_lock *rule_lock; /* Lock to protect filter rule list */
8731 enum ice_status status = ICE_SUCCESS;
8732 bool remove_rule = false;
8733 u16 i, rid, vsi_handle;
8735 ice_memset(&lkup_exts, 0, sizeof(lkup_exts), ICE_NONDMA_MEM);
8736 for (i = 0; i < lkups_cnt; i++) {
8739 if (lkups[i].type >= ICE_PROTOCOL_LAST)
8742 count = ice_fill_valid_words(&lkups[i], &lkup_exts);
8747 /* Create any special protocol/offset pairs, such as looking at tunnel
8748 * bits by extracting metadata
8750 status = ice_add_special_words(rinfo, &lkup_exts);
8754 rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type);
8755 /* If did not find a recipe that match the existing criteria */
8756 if (rid == ICE_MAX_NUM_RECIPES)
8757 return ICE_ERR_PARAM;
8759 rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
8760 list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
8761 /* the rule is already removed */
8764 ice_acquire_lock(rule_lock);
8765 if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
8767 } else if (list_elem->vsi_count > 1) {
8768 remove_rule = false;
8769 vsi_handle = rinfo->sw_act.vsi_handle;
8770 status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
8772 vsi_handle = rinfo->sw_act.vsi_handle;
8773 status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
8775 ice_release_lock(rule_lock);
8778 if (list_elem->vsi_count == 0)
8781 ice_release_lock(rule_lock);
8783 struct ice_aqc_sw_rules_elem *s_rule;
8786 rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
8787 s_rule = (struct ice_aqc_sw_rules_elem *)
8788 ice_malloc(hw, rule_buf_sz);
8790 return ICE_ERR_NO_MEMORY;
8791 s_rule->pdata.lkup_tx_rx.act = 0;
8792 s_rule->pdata.lkup_tx_rx.index =
8793 CPU_TO_LE16(list_elem->rule_info.fltr_rule_id);
8794 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
8795 status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
8797 ice_aqc_opc_remove_sw_rules, NULL);
8798 if (status == ICE_SUCCESS || status == ICE_ERR_DOES_NOT_EXIST) {
8799 struct ice_switch_info *sw = hw->switch_info;
8801 ice_acquire_lock(rule_lock);
8802 LIST_DEL(&list_elem->list_entry);
8803 ice_free(hw, list_elem->lkups);
8804 ice_free(hw, list_elem);
8805 ice_release_lock(rule_lock);
8806 if (LIST_EMPTY(&sw->recp_list[rid].filt_rules))
8807 sw->recp_list[rid].adv_rule = false;
8809 ice_free(hw, s_rule);
8815 * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
8816 * @hw: pointer to the hardware structure
8817 * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
8819 * This function is used to remove 1 rule at a time. The removal is based on
8820 * the remove_entry parameter. This function will remove rule for a given
8821 * vsi_handle with a given rule_id which is passed as parameter in remove_entry
8824 ice_rem_adv_rule_by_id(struct ice_hw *hw,
8825 struct ice_rule_query_data *remove_entry)
8827 struct ice_adv_fltr_mgmt_list_entry *list_itr;
8828 struct LIST_HEAD_TYPE *list_head;
8829 struct ice_adv_rule_info rinfo;
8830 struct ice_switch_info *sw;
8832 sw = hw->switch_info;
8833 if (!sw->recp_list[remove_entry->rid].recp_created)
8834 return ICE_ERR_PARAM;
8835 list_head = &sw->recp_list[remove_entry->rid].filt_rules;
8836 LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_adv_fltr_mgmt_list_entry,
8838 if (list_itr->rule_info.fltr_rule_id ==
8839 remove_entry->rule_id) {
8840 rinfo = list_itr->rule_info;
8841 rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
8842 return ice_rem_adv_rule(hw, list_itr->lkups,
8843 list_itr->lkups_cnt, &rinfo);
8846 /* either list is empty or unable to find rule */
8847 return ICE_ERR_DOES_NOT_EXIST;
8851 * ice_rem_adv_for_vsi - removes existing advanced switch rules for a
8853 * @hw: pointer to the hardware structure
8854 * @vsi_handle: VSI handle for which we are supposed to remove all the rules.
8856 * This function is used to remove all the rules for a given VSI and as soon
8857 * as removing a rule fails, it will return immediately with the error code,
8858 * else it will return ICE_SUCCESS
8860 enum ice_status ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle)
8862 struct ice_adv_fltr_mgmt_list_entry *list_itr, *tmp_entry;
8863 struct ice_vsi_list_map_info *map_info;
8864 struct LIST_HEAD_TYPE *list_head;
8865 struct ice_adv_rule_info rinfo;
8866 struct ice_switch_info *sw;
8867 enum ice_status status;
8870 sw = hw->switch_info;
8871 for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) {
8872 if (!sw->recp_list[rid].recp_created)
8874 if (!sw->recp_list[rid].adv_rule)
8877 list_head = &sw->recp_list[rid].filt_rules;
8878 LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp_entry, list_head,
8879 ice_adv_fltr_mgmt_list_entry,
8881 rinfo = list_itr->rule_info;
8883 if (rinfo.sw_act.fltr_act == ICE_FWD_TO_VSI_LIST) {
8884 map_info = list_itr->vsi_list_info;
8888 if (!ice_is_bit_set(map_info->vsi_map,
8891 } else if (rinfo.sw_act.vsi_handle != vsi_handle) {
8895 rinfo.sw_act.vsi_handle = vsi_handle;
8896 status = ice_rem_adv_rule(hw, list_itr->lkups,
8897 list_itr->lkups_cnt, &rinfo);
8907 * ice_replay_fltr - Replay all the filters stored by a specific list head
8908 * @hw: pointer to the hardware structure
8909 * @list_head: list for which filters needs to be replayed
8910 * @recp_id: Recipe ID for which rules need to be replayed
8912 static enum ice_status
8913 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head)
8915 struct ice_fltr_mgmt_list_entry *itr;
8916 enum ice_status status = ICE_SUCCESS;
8917 struct ice_sw_recipe *recp_list;
8918 u8 lport = hw->port_info->lport;
8919 struct LIST_HEAD_TYPE l_head;
8921 if (LIST_EMPTY(list_head))
8924 recp_list = &hw->switch_info->recp_list[recp_id];
8925 /* Move entries from the given list_head to a temporary l_head so that
8926 * they can be replayed. Otherwise when trying to re-add the same
8927 * filter, the function will return already exists
8929 LIST_REPLACE_INIT(list_head, &l_head);
8931 /* Mark the given list_head empty by reinitializing it so filters
8932 * could be added again by *handler
8934 LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry,
8936 struct ice_fltr_list_entry f_entry;
8939 f_entry.fltr_info = itr->fltr_info;
8940 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) {
8941 status = ice_add_rule_internal(hw, recp_list, lport,
8943 if (status != ICE_SUCCESS)
8948 /* Add a filter per VSI separately */
8949 ice_for_each_set_bit(vsi_handle, itr->vsi_list_info->vsi_map,
8951 if (!ice_is_vsi_valid(hw, vsi_handle))
8954 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
8955 f_entry.fltr_info.vsi_handle = vsi_handle;
8956 f_entry.fltr_info.fwd_id.hw_vsi_id =
8957 ice_get_hw_vsi_num(hw, vsi_handle);
8958 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
8959 if (recp_id == ICE_SW_LKUP_VLAN)
8960 status = ice_add_vlan_internal(hw, recp_list,
8963 status = ice_add_rule_internal(hw, recp_list,
8966 if (status != ICE_SUCCESS)
8971 /* Clear the filter management list */
8972 ice_rem_sw_rule_info(hw, &l_head);
8977 * ice_replay_all_fltr - replay all filters stored in bookkeeping lists
8978 * @hw: pointer to the hardware structure
8980 * NOTE: This function does not clean up partially added filters on error.
8981 * It is up to caller of the function to issue a reset or fail early.
8983 enum ice_status ice_replay_all_fltr(struct ice_hw *hw)
8985 struct ice_switch_info *sw = hw->switch_info;
8986 enum ice_status status = ICE_SUCCESS;
8989 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
8990 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules;
8992 status = ice_replay_fltr(hw, i, head);
8993 if (status != ICE_SUCCESS)
9000 * ice_replay_vsi_fltr - Replay filters for requested VSI
9001 * @hw: pointer to the hardware structure
9002 * @pi: pointer to port information structure
9003 * @sw: pointer to switch info struct for which function replays filters
9004 * @vsi_handle: driver VSI handle
9005 * @recp_id: Recipe ID for which rules need to be replayed
9006 * @list_head: list for which filters need to be replayed
9008 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
9009 * It is required to pass valid VSI handle.
9011 static enum ice_status
9012 ice_replay_vsi_fltr(struct ice_hw *hw, struct ice_port_info *pi,
9013 struct ice_switch_info *sw, u16 vsi_handle, u8 recp_id,
9014 struct LIST_HEAD_TYPE *list_head)
9016 struct ice_fltr_mgmt_list_entry *itr;
9017 enum ice_status status = ICE_SUCCESS;
9018 struct ice_sw_recipe *recp_list;
9021 if (LIST_EMPTY(list_head))
9023 recp_list = &sw->recp_list[recp_id];
9024 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
9026 LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry,
9028 struct ice_fltr_list_entry f_entry;
9030 f_entry.fltr_info = itr->fltr_info;
9031 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
9032 itr->fltr_info.vsi_handle == vsi_handle) {
9033 /* update the src in case it is VSI num */
9034 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
9035 f_entry.fltr_info.src = hw_vsi_id;
9036 status = ice_add_rule_internal(hw, recp_list,
9039 if (status != ICE_SUCCESS)
9043 if (!itr->vsi_list_info ||
9044 !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle))
9046 /* Clearing it so that the logic can add it back */
9047 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
9048 f_entry.fltr_info.vsi_handle = vsi_handle;
9049 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
9050 /* update the src in case it is VSI num */
9051 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
9052 f_entry.fltr_info.src = hw_vsi_id;
9053 if (recp_id == ICE_SW_LKUP_VLAN)
9054 status = ice_add_vlan_internal(hw, recp_list, &f_entry);
9056 status = ice_add_rule_internal(hw, recp_list,
9059 if (status != ICE_SUCCESS)
9067 * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
9068 * @hw: pointer to the hardware structure
9069 * @vsi_handle: driver VSI handle
9070 * @list_head: list for which filters need to be replayed
9072 * Replay the advanced rule for the given VSI.
9074 static enum ice_status
9075 ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
9076 struct LIST_HEAD_TYPE *list_head)
9078 struct ice_rule_query_data added_entry = { 0 };
9079 struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
9080 enum ice_status status = ICE_SUCCESS;
9082 if (LIST_EMPTY(list_head))
9084 LIST_FOR_EACH_ENTRY(adv_fltr, list_head, ice_adv_fltr_mgmt_list_entry,
9086 struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
9087 u16 lk_cnt = adv_fltr->lkups_cnt;
9089 if (vsi_handle != rinfo->sw_act.vsi_handle)
9091 status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
9100 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
9101 * @hw: pointer to the hardware structure
9102 * @pi: pointer to port information structure
9103 * @vsi_handle: driver VSI handle
9105 * Replays filters for requested VSI via vsi_handle.
9108 ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi,
9111 struct ice_switch_info *sw = hw->switch_info;
9112 enum ice_status status;
9115 /* Update the recipes that were created */
9116 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
9117 struct LIST_HEAD_TYPE *head;
9119 head = &sw->recp_list[i].filt_replay_rules;
9120 if (!sw->recp_list[i].adv_rule)
9121 status = ice_replay_vsi_fltr(hw, pi, sw, vsi_handle, i,
9124 status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
9125 if (status != ICE_SUCCESS)
9133 * ice_rm_all_sw_replay_rule - helper function to delete filter replay rules
9134 * @hw: pointer to the HW struct
9135 * @sw: pointer to switch info struct for which function removes filters
9137 * Deletes the filter replay rules for given switch
9139 void ice_rm_sw_replay_rule_info(struct ice_hw *hw, struct ice_switch_info *sw)
9146 for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
9147 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) {
9148 struct LIST_HEAD_TYPE *l_head;
9150 l_head = &sw->recp_list[i].filt_replay_rules;
9151 if (!sw->recp_list[i].adv_rule)
9152 ice_rem_sw_rule_info(hw, l_head);
9154 ice_rem_adv_rule_info(hw, l_head);
9160 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
9161 * @hw: pointer to the HW struct
9163 * Deletes the filter replay rules.
9165 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
9167 ice_rm_sw_replay_rule_info(hw, hw->switch_info);