1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2021 Intel Corporation
5 #include "ice_common.h"
8 /* Size of known protocol header fields */
9 #define ICE_FLOW_FLD_SZ_ETH_TYPE 2
10 #define ICE_FLOW_FLD_SZ_VLAN 2
11 #define ICE_FLOW_FLD_SZ_IPV4_ADDR 4
12 #define ICE_FLOW_FLD_SZ_IPV6_ADDR 16
13 #define ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR 4
14 #define ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR 6
15 #define ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR 8
16 #define ICE_FLOW_FLD_SZ_IP_DSCP 1
17 #define ICE_FLOW_FLD_SZ_IP_TTL 1
18 #define ICE_FLOW_FLD_SZ_IP_PROT 1
19 #define ICE_FLOW_FLD_SZ_PORT 2
20 #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1
21 #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1
22 #define ICE_FLOW_FLD_SZ_ICMP_CODE 1
23 #define ICE_FLOW_FLD_SZ_ARP_OPER 2
24 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4
25 #define ICE_FLOW_FLD_SZ_GTP_TEID 4
26 #define ICE_FLOW_FLD_SZ_GTP_QFI 2
27 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2
28 #define ICE_FLOW_FLD_SZ_PFCP_SEID 8
29 #define ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID 4
30 #define ICE_FLOW_FLD_SZ_ESP_SPI 4
31 #define ICE_FLOW_FLD_SZ_AH_SPI 4
32 #define ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI 4
33 #define ICE_FLOW_FLD_SZ_VXLAN_VNI 4
34 #define ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID 2
36 /* Describe properties of a protocol header field */
37 struct ice_flow_field_info {
38 enum ice_flow_seg_hdr hdr;
39 s16 off; /* Offset from start of a protocol header, in bits */
40 u16 size; /* Size of fields in bits */
41 u16 mask; /* 16-bit mask for field */
44 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
46 .off = (_offset_bytes) * BITS_PER_BYTE, \
47 .size = (_size_bytes) * BITS_PER_BYTE, \
51 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
53 .off = (_offset_bytes) * BITS_PER_BYTE, \
54 .size = (_size_bytes) * BITS_PER_BYTE, \
58 /* Table containing properties of supported protocol header fields */
60 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
62 /* ICE_FLOW_FIELD_IDX_ETH_DA */
63 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
64 /* ICE_FLOW_FIELD_IDX_ETH_SA */
65 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
66 /* ICE_FLOW_FIELD_IDX_S_VLAN */
67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
68 /* ICE_FLOW_FIELD_IDX_C_VLAN */
69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
70 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
71 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ICE_FLOW_FLD_SZ_ETH_TYPE),
73 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
74 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
76 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
77 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
79 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
80 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
81 ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
82 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
83 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
84 ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
85 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
86 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
87 ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
88 /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
89 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
90 ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
91 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
93 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
95 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
97 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
99 /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA */
100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
101 ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
102 /* ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA */
103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
104 ICE_FLOW_FLD_SZ_IPV6_PRE32_ADDR),
105 /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA */
106 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
107 ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
108 /* ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA */
109 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
110 ICE_FLOW_FLD_SZ_IPV6_PRE48_ADDR),
111 /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA */
112 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8,
113 ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
114 /* ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA */
115 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24,
116 ICE_FLOW_FLD_SZ_IPV6_PRE64_ADDR),
118 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
120 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
121 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
122 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
123 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
124 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
126 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
127 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
128 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
129 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
130 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
133 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
134 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
135 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
136 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
137 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
138 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
139 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
140 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
141 /* ICE_FLOW_FIELD_IDX_ARP_OP */
142 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
144 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
145 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
146 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
147 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
149 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
150 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
152 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
153 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
154 ICE_FLOW_FLD_SZ_GTP_TEID),
155 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
156 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
157 ICE_FLOW_FLD_SZ_GTP_TEID),
158 /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
159 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12,
160 ICE_FLOW_FLD_SZ_GTP_TEID),
161 /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
162 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22,
163 ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
164 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
165 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
166 ICE_FLOW_FLD_SZ_GTP_TEID),
167 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
168 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
169 ICE_FLOW_FLD_SZ_GTP_TEID),
171 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
172 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
173 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
175 /* ICE_FLOW_FIELD_IDX_PFCP_SEID */
176 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PFCP_SESSION, 12,
177 ICE_FLOW_FLD_SZ_PFCP_SEID),
179 /* ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID */
180 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_L2TPV3, 0,
181 ICE_FLOW_FLD_SZ_L2TPV3_SESS_ID),
183 /* ICE_FLOW_FIELD_IDX_ESP_SPI */
184 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ESP, 0,
185 ICE_FLOW_FLD_SZ_ESP_SPI),
187 /* ICE_FLOW_FIELD_IDX_AH_SPI */
188 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_AH, 4,
189 ICE_FLOW_FLD_SZ_AH_SPI),
191 /* ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI */
192 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NAT_T_ESP, 8,
193 ICE_FLOW_FLD_SZ_NAT_T_ESP_SPI),
194 /* ICE_FLOW_FIELD_IDX_VXLAN_VNI */
195 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VXLAN, 12,
196 ICE_FLOW_FLD_SZ_VXLAN_VNI),
198 /* ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID */
199 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ECPRI_TP0, 4,
200 ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID),
202 /* ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID */
203 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0, 12,
204 ICE_FLOW_FLD_SZ_ECPRI_TP0_PC_ID),
207 /* Bitmaps indicating relevant packet types for a particular protocol header
209 * Packet types for packets with an Outer/First/Single MAC header
211 static const u32 ice_ptypes_mac_ofos[] = {
212 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
213 0x0000077E, 0x000003FF, 0x00000000, 0x00000000,
214 0x00400000, 0x03FFF000, 0xFFFFFFE0, 0x00100707,
215 0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
222 /* Packet types for packets with an Innermost/Last MAC VLAN header */
223 static const u32 ice_ptypes_macvlan_il[] = {
224 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
225 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
226 0x00000000, 0x00000000, 0x00000000, 0x00000000,
227 0x00000000, 0x00000000, 0x00000000, 0x00000000,
228 0x00000000, 0x00000000, 0x00000000, 0x00000000,
229 0x00000000, 0x00000000, 0x00000000, 0x00000000,
230 0x00000000, 0x00000000, 0x00000000, 0x00000000,
231 0x00000000, 0x00000000, 0x00000000, 0x00000000,
234 /* Packet types for packets with an Outer/First/Single IPv4 header, does NOT
235 * include IPV4 other PTYPEs
237 static const u32 ice_ptypes_ipv4_ofos[] = {
238 0x1DC00000, 0x24000800, 0x00000000, 0x00000000,
239 0x00000000, 0x00000155, 0x00000000, 0x00000000,
240 0x00000000, 0x000FC000, 0x000002A0, 0x00100000,
241 0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 /* Packet types for packets with an Outer/First/Single IPv4 header, includes
251 static const u32 ice_ptypes_ipv4_ofos_all[] = {
252 0x1DC00000, 0x24000800, 0x00000000, 0x00000000,
253 0x00000000, 0x00000155, 0x00000000, 0x00000000,
254 0x00000000, 0x000FC000, 0x83E0FAA0, 0x00000101,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
262 /* Packet types for packets with an Innermost/Last IPv4 header */
263 static const u32 ice_ptypes_ipv4_il[] = {
264 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
265 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x001FF800, 0x00100000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000000, 0x00000000, 0x00000000, 0x00000000,
274 /* Packet types for packets with an Outer/First/Single IPv6 header, does NOT
275 * include IVP6 other PTYPEs
277 static const u32 ice_ptypes_ipv6_ofos[] = {
278 0x00000000, 0x00000000, 0x77000000, 0x10002000,
279 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
280 0x00000000, 0x03F00000, 0x00000540, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000,
288 /* Packet types for packets with an Outer/First/Single IPv6 header, includes
291 static const u32 ice_ptypes_ipv6_ofos_all[] = {
292 0x00000000, 0x00000000, 0x77000000, 0x10002000,
293 0x00000000, 0x000002AA, 0x00000000, 0x00000000,
294 0x00000000, 0x03F00000, 0x7C1F0540, 0x00000206,
295 0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 0x00000000, 0x00000000, 0x00000000, 0x00000000,
298 0x00000000, 0x00000000, 0x00000000, 0x00000000,
299 0x00000000, 0x00000000, 0x00000000, 0x00000000,
302 /* Packet types for packets with an Innermost/Last IPv6 header */
303 static const u32 ice_ptypes_ipv6_il[] = {
304 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
305 0x00000770, 0x00000000, 0x00000000, 0x00000000,
306 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
307 0x00000000, 0x00000000, 0x00000000, 0x00000000,
308 0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 0x00000000, 0x00000000, 0x00000000, 0x00000000,
310 0x00000000, 0x00000000, 0x00000000, 0x00000000,
311 0x00000000, 0x00000000, 0x00000000, 0x00000000,
314 /* Packet types for packets with an Outer/First/Single IPv4 header - no L4 */
315 static const u32 ice_ptypes_ipv4_ofos_no_l4[] = {
316 0x10C00000, 0x04000800, 0x00000000, 0x00000000,
317 0x00000000, 0x00000000, 0x00000000, 0x00000000,
318 0x00000000, 0x000cc000, 0x000002A0, 0x00000000,
319 0x00000000, 0x00000000, 0x00000000, 0x00000000,
320 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 0x00000000, 0x00000000, 0x00000000, 0x00000000,
322 0x00000000, 0x00000000, 0x00000000, 0x00000000,
323 0x00000000, 0x00000000, 0x00000000, 0x00000000,
326 /* Packet types for packets with an Innermost/Last IPv4 header - no L4 */
327 static const u32 ice_ptypes_ipv4_il_no_l4[] = {
328 0x60000000, 0x18043008, 0x80000002, 0x6010c021,
329 0x00000008, 0x00000000, 0x00000000, 0x00000000,
330 0x00000000, 0x00000000, 0x00139800, 0x00000000,
331 0x00000000, 0x00000000, 0x00000000, 0x00000000,
332 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 0x00000000, 0x00000000, 0x00000000, 0x00000000,
334 0x00000000, 0x00000000, 0x00000000, 0x00000000,
335 0x00000000, 0x00000000, 0x00000000, 0x00000000,
338 /* Packet types for packets with an Outer/First/Single IPv6 header - no L4 */
339 static const u32 ice_ptypes_ipv6_ofos_no_l4[] = {
340 0x00000000, 0x00000000, 0x43000000, 0x10002000,
341 0x00000000, 0x00000000, 0x00000000, 0x00000000,
342 0x00000000, 0x02300000, 0x00000540, 0x00000000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 0x00000000, 0x00000000, 0x00000000, 0x00000000,
346 0x00000000, 0x00000000, 0x00000000, 0x00000000,
347 0x00000000, 0x00000000, 0x00000000, 0x00000000,
350 /* Packet types for packets with an Innermost/Last IPv6 header - no L4 */
351 static const u32 ice_ptypes_ipv6_il_no_l4[] = {
352 0x00000000, 0x02180430, 0x0000010c, 0x086010c0,
353 0x00000430, 0x00000000, 0x00000000, 0x00000000,
354 0x00000000, 0x00000000, 0x4e600000, 0x00000000,
355 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
358 0x00000000, 0x00000000, 0x00000000, 0x00000000,
359 0x00000000, 0x00000000, 0x00000000, 0x00000000,
362 /* Packet types for packets with an Outermost/First ARP header */
363 static const u32 ice_ptypes_arp_of[] = {
364 0x00000800, 0x00000000, 0x00000000, 0x00000000,
365 0x00000000, 0x00000000, 0x00000000, 0x00000000,
366 0x00000000, 0x00000000, 0x00000000, 0x00000000,
367 0x00000000, 0x00000000, 0x00000000, 0x00000000,
368 0x00000000, 0x00000000, 0x00000000, 0x00000000,
369 0x00000000, 0x00000000, 0x00000000, 0x00000000,
370 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000000, 0x00000000, 0x00000000, 0x00000000,
374 /* UDP Packet types for non-tunneled packets or tunneled
375 * packets with inner UDP.
377 static const u32 ice_ptypes_udp_il[] = {
378 0x81000000, 0x20204040, 0x04000010, 0x80810102,
379 0x00000040, 0x00000000, 0x00000000, 0x00000000,
380 0x00000000, 0x00410000, 0x908427E0, 0x00100007,
381 0x00000000, 0x00000000, 0x00000000, 0x00000000,
382 0x00000000, 0x00000000, 0x00000000, 0x00000000,
383 0x00000000, 0x00000000, 0x00000000, 0x00000000,
384 0x00000000, 0x00000000, 0x00000000, 0x00000000,
385 0x00000000, 0x00000000, 0x00000000, 0x00000000,
388 /* Packet types for packets with an Innermost/Last TCP header */
389 static const u32 ice_ptypes_tcp_il[] = {
390 0x04000000, 0x80810102, 0x10000040, 0x02040408,
391 0x00000102, 0x00000000, 0x00000000, 0x00000000,
392 0x00000000, 0x00820000, 0x21084000, 0x00000000,
393 0x00000000, 0x00000000, 0x00000000, 0x00000000,
394 0x00000000, 0x00000000, 0x00000000, 0x00000000,
395 0x00000000, 0x00000000, 0x00000000, 0x00000000,
396 0x00000000, 0x00000000, 0x00000000, 0x00000000,
397 0x00000000, 0x00000000, 0x00000000, 0x00000000,
400 /* Packet types for packets with an Innermost/Last SCTP header */
401 static const u32 ice_ptypes_sctp_il[] = {
402 0x08000000, 0x01020204, 0x20000081, 0x04080810,
403 0x00000204, 0x00000000, 0x00000000, 0x00000000,
404 0x00000000, 0x01040000, 0x00000000, 0x00000000,
405 0x00000000, 0x00000000, 0x00000000, 0x00000000,
406 0x00000000, 0x00000000, 0x00000000, 0x00000000,
407 0x00000000, 0x00000000, 0x00000000, 0x00000000,
408 0x00000000, 0x00000000, 0x00000000, 0x00000000,
409 0x00000000, 0x00000000, 0x00000000, 0x00000000,
412 /* Packet types for packets with an Outermost/First ICMP header */
413 static const u32 ice_ptypes_icmp_of[] = {
414 0x10000000, 0x00000000, 0x00000000, 0x00000000,
415 0x00000000, 0x00000000, 0x00000000, 0x00000000,
416 0x00000000, 0x00000000, 0x00000000, 0x00000000,
417 0x00000000, 0x00000000, 0x00000000, 0x00000000,
418 0x00000000, 0x00000000, 0x00000000, 0x00000000,
419 0x00000000, 0x00000000, 0x00000000, 0x00000000,
420 0x00000000, 0x00000000, 0x00000000, 0x00000000,
421 0x00000000, 0x00000000, 0x00000000, 0x00000000,
424 /* Packet types for packets with an Innermost/Last ICMP header */
425 static const u32 ice_ptypes_icmp_il[] = {
426 0x00000000, 0x02040408, 0x40000102, 0x08101020,
427 0x00000408, 0x00000000, 0x00000000, 0x00000000,
428 0x00000000, 0x00000000, 0x42108000, 0x00000000,
429 0x00000000, 0x00000000, 0x00000000, 0x00000000,
430 0x00000000, 0x00000000, 0x00000000, 0x00000000,
431 0x00000000, 0x00000000, 0x00000000, 0x00000000,
432 0x00000000, 0x00000000, 0x00000000, 0x00000000,
433 0x00000000, 0x00000000, 0x00000000, 0x00000000,
436 /* Packet types for packets with an Outermost/First GRE header */
437 static const u32 ice_ptypes_gre_of[] = {
438 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
439 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
440 0x00000000, 0x00000000, 0x00000000, 0x00000000,
441 0x00000000, 0x00000000, 0x00000000, 0x00000000,
442 0x00000000, 0x00000000, 0x00000000, 0x00000000,
443 0x00000000, 0x00000000, 0x00000000, 0x00000000,
444 0x00000000, 0x00000000, 0x00000000, 0x00000000,
445 0x00000000, 0x00000000, 0x00000000, 0x00000000,
448 /* Packet types for packets with an Innermost/Last MAC header */
449 static const u32 ice_ptypes_mac_il[] = {
450 0x00000000, 0x20000000, 0x00000000, 0x00000000,
451 0x00000000, 0x00000000, 0x00000000, 0x00000000,
452 0x00000000, 0x00000000, 0x00000000, 0x00000000,
453 0x00000000, 0x00000000, 0x00000000, 0x00000000,
454 0x00000000, 0x00000000, 0x00000000, 0x00000000,
455 0x00000000, 0x00000000, 0x00000000, 0x00000000,
456 0x00000000, 0x00000000, 0x00000000, 0x00000000,
457 0x00000000, 0x00000000, 0x00000000, 0x00000000,
460 /* Packet types for GTPC */
461 static const u32 ice_ptypes_gtpc[] = {
462 0x00000000, 0x00000000, 0x00000000, 0x00000000,
463 0x00000000, 0x00000000, 0x00000000, 0x00000000,
464 0x00000000, 0x00000000, 0x000001E0, 0x00000000,
465 0x00000000, 0x00000000, 0x00000000, 0x00000000,
466 0x00000000, 0x00000000, 0x00000000, 0x00000000,
467 0x00000000, 0x00000000, 0x00000000, 0x00000000,
468 0x00000000, 0x00000000, 0x00000000, 0x00000000,
469 0x00000000, 0x00000000, 0x00000000, 0x00000000,
472 /* Packet types for VXLAN with VNI */
473 static const u32 ice_ptypes_vxlan_vni[] = {
474 0x00000000, 0xBFBFF800, 0x00EFDFDF, 0xFEFDE000,
475 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
476 0x00000000, 0x00000000, 0x00000000, 0x00000000,
477 0x00000000, 0x00000000, 0x00000000, 0x00000000,
478 0x00000000, 0x00000000, 0x00000000, 0x00000000,
479 0x00000000, 0x00000000, 0x00000000, 0x00000000,
480 0x00000000, 0x00000000, 0x00000000, 0x00000000,
481 0x00000000, 0x00000000, 0x00000000, 0x00000000,
484 /* Packet types for GTPC with TEID */
485 static const u32 ice_ptypes_gtpc_tid[] = {
486 0x00000000, 0x00000000, 0x00000000, 0x00000000,
487 0x00000000, 0x00000000, 0x00000000, 0x00000000,
488 0x00000000, 0x00000000, 0x00000060, 0x00000000,
489 0x00000000, 0x00000000, 0x00000000, 0x00000000,
490 0x00000000, 0x00000000, 0x00000000, 0x00000000,
491 0x00000000, 0x00000000, 0x00000000, 0x00000000,
492 0x00000000, 0x00000000, 0x00000000, 0x00000000,
493 0x00000000, 0x00000000, 0x00000000, 0x00000000,
496 /* Packet types for GTPU */
497 static const struct ice_ptype_attributes ice_attr_gtpu_session[] = {
498 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
499 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
500 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
501 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
502 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION },
503 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
504 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
505 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
506 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
507 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_SESSION },
508 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
509 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
510 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
511 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
512 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION },
513 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_SESSION },
514 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
515 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_SESSION },
516 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_SESSION },
517 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_SESSION },
520 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
521 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
522 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
523 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
524 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
525 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
526 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
527 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
528 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
529 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
530 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
531 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
532 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
533 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
534 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
535 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
536 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
537 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
538 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
539 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
540 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
543 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
544 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
545 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
546 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
547 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
548 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
549 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
550 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
551 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
552 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
553 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
554 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
555 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
556 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
557 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
558 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
559 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
560 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
561 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
562 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
563 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
566 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
567 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
568 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
569 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
570 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
571 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
572 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
573 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
574 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
575 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
576 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
577 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
578 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
579 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
580 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
581 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
582 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
583 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
584 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
585 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
586 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
589 static const u32 ice_ptypes_gtpu[] = {
590 0x00000000, 0x00000000, 0x00000000, 0x00000000,
591 0x00000000, 0x00000000, 0x00000000, 0x00000000,
592 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
593 0x00000000, 0x00000000, 0x00000000, 0x00000000,
594 0x00000000, 0x00000000, 0x00000000, 0x00000000,
595 0x00000000, 0x00000000, 0x00000000, 0x00000000,
596 0x00000000, 0x00000000, 0x00000000, 0x00000000,
597 0x00000000, 0x00000000, 0x00000000, 0x00000000,
600 /* Packet types for pppoe */
601 static const u32 ice_ptypes_pppoe[] = {
602 0x00000000, 0x00000000, 0x00000000, 0x00000000,
603 0x00000000, 0x00000000, 0x00000000, 0x00000000,
604 0x00000000, 0x03ffe000, 0x00000000, 0x00000000,
605 0x00000000, 0x00000000, 0x00000000, 0x00000000,
606 0x00000000, 0x00000000, 0x00000000, 0x00000000,
607 0x00000000, 0x00000000, 0x00000000, 0x00000000,
608 0x00000000, 0x00000000, 0x00000000, 0x00000000,
609 0x00000000, 0x00000000, 0x00000000, 0x00000000,
612 /* Packet types for packets with PFCP NODE header */
613 static const u32 ice_ptypes_pfcp_node[] = {
614 0x00000000, 0x00000000, 0x00000000, 0x00000000,
615 0x00000000, 0x00000000, 0x00000000, 0x00000000,
616 0x00000000, 0x00000000, 0x80000000, 0x00000002,
617 0x00000000, 0x00000000, 0x00000000, 0x00000000,
618 0x00000000, 0x00000000, 0x00000000, 0x00000000,
619 0x00000000, 0x00000000, 0x00000000, 0x00000000,
620 0x00000000, 0x00000000, 0x00000000, 0x00000000,
621 0x00000000, 0x00000000, 0x00000000, 0x00000000,
624 /* Packet types for packets with PFCP SESSION header */
625 static const u32 ice_ptypes_pfcp_session[] = {
626 0x00000000, 0x00000000, 0x00000000, 0x00000000,
627 0x00000000, 0x00000000, 0x00000000, 0x00000000,
628 0x00000000, 0x00000000, 0x00000000, 0x00000005,
629 0x00000000, 0x00000000, 0x00000000, 0x00000000,
630 0x00000000, 0x00000000, 0x00000000, 0x00000000,
631 0x00000000, 0x00000000, 0x00000000, 0x00000000,
632 0x00000000, 0x00000000, 0x00000000, 0x00000000,
633 0x00000000, 0x00000000, 0x00000000, 0x00000000,
636 /* Packet types for l2tpv3 */
637 static const u32 ice_ptypes_l2tpv3[] = {
638 0x00000000, 0x00000000, 0x00000000, 0x00000000,
639 0x00000000, 0x00000000, 0x00000000, 0x00000000,
640 0x00000000, 0x00000000, 0x00000000, 0x00000300,
641 0x00000000, 0x00000000, 0x00000000, 0x00000000,
642 0x00000000, 0x00000000, 0x00000000, 0x00000000,
643 0x00000000, 0x00000000, 0x00000000, 0x00000000,
644 0x00000000, 0x00000000, 0x00000000, 0x00000000,
645 0x00000000, 0x00000000, 0x00000000, 0x00000000,
648 /* Packet types for esp */
649 static const u32 ice_ptypes_esp[] = {
650 0x00000000, 0x00000000, 0x00000000, 0x00000000,
651 0x00000000, 0x00000003, 0x00000000, 0x00000000,
652 0x00000000, 0x00000000, 0x00000000, 0x00000000,
653 0x00000000, 0x00000000, 0x00000000, 0x00000000,
654 0x00000000, 0x00000000, 0x00000000, 0x00000000,
655 0x00000000, 0x00000000, 0x00000000, 0x00000000,
656 0x00000000, 0x00000000, 0x00000000, 0x00000000,
657 0x00000000, 0x00000000, 0x00000000, 0x00000000,
660 /* Packet types for ah */
661 static const u32 ice_ptypes_ah[] = {
662 0x00000000, 0x00000000, 0x00000000, 0x00000000,
663 0x00000000, 0x0000000C, 0x00000000, 0x00000000,
664 0x00000000, 0x00000000, 0x00000000, 0x00000000,
665 0x00000000, 0x00000000, 0x00000000, 0x00000000,
666 0x00000000, 0x00000000, 0x00000000, 0x00000000,
667 0x00000000, 0x00000000, 0x00000000, 0x00000000,
668 0x00000000, 0x00000000, 0x00000000, 0x00000000,
669 0x00000000, 0x00000000, 0x00000000, 0x00000000,
672 /* Packet types for packets with NAT_T ESP header */
673 static const u32 ice_ptypes_nat_t_esp[] = {
674 0x00000000, 0x00000000, 0x00000000, 0x00000000,
675 0x00000000, 0x00000030, 0x00000000, 0x00000000,
676 0x00000000, 0x00000000, 0x00000000, 0x00000000,
677 0x00000000, 0x00000000, 0x00000000, 0x00000000,
678 0x00000000, 0x00000000, 0x00000000, 0x00000000,
679 0x00000000, 0x00000000, 0x00000000, 0x00000000,
680 0x00000000, 0x00000000, 0x00000000, 0x00000000,
681 0x00000000, 0x00000000, 0x00000000, 0x00000000,
684 static const u32 ice_ptypes_mac_non_ip_ofos[] = {
685 0x00000846, 0x00000000, 0x00000000, 0x00000000,
686 0x00000000, 0x00000000, 0x00000000, 0x00000000,
687 0x00400000, 0x03FFF000, 0x00000000, 0x00000000,
688 0x00000000, 0x00000000, 0x00000000, 0x00000000,
689 0x00000000, 0x00000000, 0x00000000, 0x00000000,
690 0x00000000, 0x00000000, 0x00000000, 0x00000000,
691 0x00000000, 0x00000000, 0x00000000, 0x00000000,
692 0x00000000, 0x00000000, 0x00000000, 0x00000000,
695 static const u32 ice_ptypes_gtpu_no_ip[] = {
696 0x00000000, 0x00000000, 0x00000000, 0x00000000,
697 0x00000000, 0x00000000, 0x00000000, 0x00000000,
698 0x00000000, 0x00000000, 0x00000600, 0x00000000,
699 0x00000000, 0x00000000, 0x00000000, 0x00000000,
700 0x00000000, 0x00000000, 0x00000000, 0x00000000,
701 0x00000000, 0x00000000, 0x00000000, 0x00000000,
702 0x00000000, 0x00000000, 0x00000000, 0x00000000,
703 0x00000000, 0x00000000, 0x00000000, 0x00000000,
706 static const u32 ice_ptypes_ecpri_tp0[] = {
707 0x00000000, 0x00000000, 0x00000000, 0x00000000,
708 0x00000000, 0x00000000, 0x00000000, 0x00000000,
709 0x00000000, 0x00000000, 0x00000000, 0x00000400,
710 0x00000000, 0x00000000, 0x00000000, 0x00000000,
711 0x00000000, 0x00000000, 0x00000000, 0x00000000,
712 0x00000000, 0x00000000, 0x00000000, 0x00000000,
713 0x00000000, 0x00000000, 0x00000000, 0x00000000,
714 0x00000000, 0x00000000, 0x00000000, 0x00000000,
717 static const u32 ice_ptypes_udp_ecpri_tp0[] = {
718 0x00000000, 0x00000000, 0x00000000, 0x00000000,
719 0x00000000, 0x00000000, 0x00000000, 0x00000000,
720 0x00000000, 0x00000000, 0x00000000, 0x00100000,
721 0x00000000, 0x00000000, 0x00000000, 0x00000000,
722 0x00000000, 0x00000000, 0x00000000, 0x00000000,
723 0x00000000, 0x00000000, 0x00000000, 0x00000000,
724 0x00000000, 0x00000000, 0x00000000, 0x00000000,
725 0x00000000, 0x00000000, 0x00000000, 0x00000000,
728 /* Manage parameters and info. used during the creation of a flow profile */
729 struct ice_flow_prof_params {
731 u16 entry_length; /* # of bytes formatted entry will require */
733 struct ice_flow_prof *prof;
735 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
736 * This will give us the direction flags.
738 struct ice_fv_word es[ICE_MAX_FV_WORDS];
739 /* attributes can be used to add attributes to a particular PTYPE */
740 const struct ice_ptype_attributes *attr;
743 u16 mask[ICE_MAX_FV_WORDS];
744 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
747 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
748 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
749 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU | \
750 ICE_FLOW_SEG_HDR_PFCP_SESSION | ICE_FLOW_SEG_HDR_L2TPV3 | \
751 ICE_FLOW_SEG_HDR_ESP | ICE_FLOW_SEG_HDR_AH | \
752 ICE_FLOW_SEG_HDR_NAT_T_ESP | ICE_FLOW_SEG_HDR_GTPU_NON_IP | \
753 ICE_FLOW_SEG_HDR_ECPRI_TP0 | ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0)
755 #define ICE_FLOW_SEG_HDRS_L2_MASK \
756 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
757 #define ICE_FLOW_SEG_HDRS_L3_MASK \
758 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
759 ICE_FLOW_SEG_HDR_ARP)
760 #define ICE_FLOW_SEG_HDRS_L4_MASK \
761 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
762 ICE_FLOW_SEG_HDR_SCTP)
763 /* mask for L4 protocols that are NOT part of IPV4/6 OTHER PTYPE groups */
764 #define ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER \
765 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
768 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
769 * @segs: array of one or more packet segments that describe the flow
770 * @segs_cnt: number of packet segments provided
772 static enum ice_status
773 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
777 for (i = 0; i < segs_cnt; i++) {
778 /* Multiple L3 headers */
779 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
780 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
781 return ICE_ERR_PARAM;
783 /* Multiple L4 headers */
784 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
785 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
786 return ICE_ERR_PARAM;
792 /* Sizes of fixed known protocol headers without header options */
793 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
794 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
795 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
796 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
797 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
798 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
799 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
800 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
801 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
804 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
805 * @params: information about the flow to be processed
806 * @seg: index of packet segment whose header size is to be determined
808 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
813 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
814 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
817 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
818 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
819 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
820 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
821 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
822 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
823 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
824 /* A L3 header is required if L4 is specified */
828 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
829 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
830 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
831 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
832 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
833 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
834 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
835 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
841 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
842 * @params: information about the flow to be processed
844 * This function identifies the packet types associated with the protocol
845 * headers being present in packet segments of the specified flow profile.
847 static enum ice_status
848 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
850 struct ice_flow_prof *prof;
853 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
858 for (i = 0; i < params->prof->segs_cnt; i++) {
859 const ice_bitmap_t *src;
862 hdrs = prof->segs[i].hdrs;
864 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
865 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
866 (const ice_bitmap_t *)ice_ptypes_mac_il;
867 ice_and_bitmap(params->ptypes, params->ptypes, src,
871 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
872 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
873 ice_and_bitmap(params->ptypes, params->ptypes, src,
877 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
878 ice_and_bitmap(params->ptypes, params->ptypes,
879 (const ice_bitmap_t *)ice_ptypes_arp_of,
883 if (hdrs & ICE_FLOW_SEG_HDR_ECPRI_TP0) {
884 src = (const ice_bitmap_t *)ice_ptypes_ecpri_tp0;
885 ice_and_bitmap(params->ptypes, params->ptypes, src,
888 if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
889 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
891 (const ice_bitmap_t *)ice_ptypes_ipv4_il :
892 (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_all;
893 ice_and_bitmap(params->ptypes, params->ptypes, src,
895 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
896 (hdrs & ICE_FLOW_SEG_HDR_IPV_OTHER)) {
898 (const ice_bitmap_t *)ice_ptypes_ipv6_il :
899 (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_all;
900 ice_and_bitmap(params->ptypes, params->ptypes, src,
902 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV4) &&
903 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
904 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos_no_l4 :
905 (const ice_bitmap_t *)ice_ptypes_ipv4_il_no_l4;
906 ice_and_bitmap(params->ptypes, params->ptypes, src,
908 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
909 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
910 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
911 ice_and_bitmap(params->ptypes, params->ptypes, src,
913 } else if ((hdrs & ICE_FLOW_SEG_HDR_IPV6) &&
914 !(hdrs & ICE_FLOW_SEG_HDRS_L4_MASK_NO_OTHER)) {
915 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos_no_l4 :
916 (const ice_bitmap_t *)ice_ptypes_ipv6_il_no_l4;
917 ice_and_bitmap(params->ptypes, params->ptypes, src,
919 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
920 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
921 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
922 ice_and_bitmap(params->ptypes, params->ptypes, src,
926 if (hdrs & ICE_FLOW_SEG_HDR_ETH_NON_IP) {
927 src = (const ice_bitmap_t *)ice_ptypes_mac_non_ip_ofos;
928 ice_and_bitmap(params->ptypes, params->ptypes,
929 src, ICE_FLOW_PTYPE_MAX);
930 } else if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
931 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
932 ice_and_bitmap(params->ptypes, params->ptypes, src,
935 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
936 ice_andnot_bitmap(params->ptypes, params->ptypes, src,
940 if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
941 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
942 ice_and_bitmap(params->ptypes, params->ptypes, src,
944 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
945 ice_and_bitmap(params->ptypes, params->ptypes,
946 (const ice_bitmap_t *)ice_ptypes_tcp_il,
948 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
949 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
950 ice_and_bitmap(params->ptypes, params->ptypes, src,
954 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
955 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
956 (const ice_bitmap_t *)ice_ptypes_icmp_il;
957 ice_and_bitmap(params->ptypes, params->ptypes, src,
959 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
961 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
962 ice_and_bitmap(params->ptypes, params->ptypes,
963 src, ICE_FLOW_PTYPE_MAX);
965 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
966 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
967 ice_and_bitmap(params->ptypes, params->ptypes,
968 src, ICE_FLOW_PTYPE_MAX);
969 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
970 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
971 ice_and_bitmap(params->ptypes, params->ptypes,
972 src, ICE_FLOW_PTYPE_MAX);
973 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_NON_IP) {
974 src = (const ice_bitmap_t *)ice_ptypes_gtpu_no_ip;
975 ice_and_bitmap(params->ptypes, params->ptypes,
976 src, ICE_FLOW_PTYPE_MAX);
977 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
978 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
979 ice_and_bitmap(params->ptypes, params->ptypes,
980 src, ICE_FLOW_PTYPE_MAX);
982 /* Attributes for GTP packet with downlink */
983 params->attr = ice_attr_gtpu_down;
984 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
985 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
986 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
987 ice_and_bitmap(params->ptypes, params->ptypes,
988 src, ICE_FLOW_PTYPE_MAX);
990 /* Attributes for GTP packet with uplink */
991 params->attr = ice_attr_gtpu_up;
992 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
993 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
994 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
995 ice_and_bitmap(params->ptypes, params->ptypes,
996 src, ICE_FLOW_PTYPE_MAX);
998 /* Attributes for GTP packet with Extension Header */
999 params->attr = ice_attr_gtpu_eh;
1000 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
1001 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
1002 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
1003 ice_and_bitmap(params->ptypes, params->ptypes,
1004 src, ICE_FLOW_PTYPE_MAX);
1006 /* Attributes for GTP packet without Extension Header */
1007 params->attr = ice_attr_gtpu_session;
1008 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_session);
1009 } else if (hdrs & ICE_FLOW_SEG_HDR_L2TPV3) {
1010 src = (const ice_bitmap_t *)ice_ptypes_l2tpv3;
1011 ice_and_bitmap(params->ptypes, params->ptypes,
1012 src, ICE_FLOW_PTYPE_MAX);
1013 } else if (hdrs & ICE_FLOW_SEG_HDR_ESP) {
1014 src = (const ice_bitmap_t *)ice_ptypes_esp;
1015 ice_and_bitmap(params->ptypes, params->ptypes,
1016 src, ICE_FLOW_PTYPE_MAX);
1017 } else if (hdrs & ICE_FLOW_SEG_HDR_AH) {
1018 src = (const ice_bitmap_t *)ice_ptypes_ah;
1019 ice_and_bitmap(params->ptypes, params->ptypes,
1020 src, ICE_FLOW_PTYPE_MAX);
1021 } else if (hdrs & ICE_FLOW_SEG_HDR_NAT_T_ESP) {
1022 src = (const ice_bitmap_t *)ice_ptypes_nat_t_esp;
1023 ice_and_bitmap(params->ptypes, params->ptypes,
1024 src, ICE_FLOW_PTYPE_MAX);
1025 } else if (hdrs & ICE_FLOW_SEG_HDR_VXLAN) {
1026 src = (const ice_bitmap_t *)ice_ptypes_vxlan_vni;
1027 ice_and_bitmap(params->ptypes, params->ptypes,
1028 src, ICE_FLOW_PTYPE_MAX);
1029 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP_ECPRI_TP0) {
1030 src = (const ice_bitmap_t *)ice_ptypes_udp_ecpri_tp0;
1031 ice_and_bitmap(params->ptypes, params->ptypes,
1032 src, ICE_FLOW_PTYPE_MAX);
1035 if (hdrs & ICE_FLOW_SEG_HDR_PFCP) {
1036 if (hdrs & ICE_FLOW_SEG_HDR_PFCP_NODE)
1038 (const ice_bitmap_t *)ice_ptypes_pfcp_node;
1041 (const ice_bitmap_t *)ice_ptypes_pfcp_session;
1043 ice_and_bitmap(params->ptypes, params->ptypes,
1044 src, ICE_FLOW_PTYPE_MAX);
1046 src = (const ice_bitmap_t *)ice_ptypes_pfcp_node;
1047 ice_andnot_bitmap(params->ptypes, params->ptypes,
1048 src, ICE_FLOW_PTYPE_MAX);
1050 src = (const ice_bitmap_t *)ice_ptypes_pfcp_session;
1051 ice_andnot_bitmap(params->ptypes, params->ptypes,
1052 src, ICE_FLOW_PTYPE_MAX);
1060 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
1061 * @hw: pointer to the HW struct
1062 * @params: information about the flow to be processed
1063 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
1065 * This function will allocate an extraction sequence entries for a DWORD size
1066 * chunk of the packet flags.
1068 static enum ice_status
1069 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
1070 struct ice_flow_prof_params *params,
1071 enum ice_flex_mdid_pkt_flags flags)
1073 u8 fv_words = hw->blk[params->blk].es.fvw;
1076 /* Make sure the number of extraction sequence entries required does not
1077 * exceed the block's capacity.
1079 if (params->es_cnt >= fv_words)
1080 return ICE_ERR_MAX_LIMIT;
1082 /* some blocks require a reversed field vector layout */
1083 if (hw->blk[params->blk].es.reverse)
1084 idx = fv_words - params->es_cnt - 1;
1086 idx = params->es_cnt;
1088 params->es[idx].prot_id = ICE_PROT_META_ID;
1089 params->es[idx].off = flags;
1096 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
1097 * @hw: pointer to the HW struct
1098 * @params: information about the flow to be processed
1099 * @seg: packet segment index of the field to be extracted
1100 * @fld: ID of field to be extracted
1101 * @match: bitfield of all fields
1103 * This function determines the protocol ID, offset, and size of the given
1104 * field. It then allocates one or more extraction sequence entries for the
1105 * given field, and fill the entries with protocol ID and offset information.
1107 static enum ice_status
1108 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
1109 u8 seg, enum ice_flow_field fld, u64 match)
1111 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
1112 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
1113 u8 fv_words = hw->blk[params->blk].es.fvw;
1114 struct ice_flow_fld_info *flds;
1115 u16 cnt, ese_bits, i;
1120 flds = params->prof->segs[seg].fields;
1123 case ICE_FLOW_FIELD_IDX_ETH_DA:
1124 case ICE_FLOW_FIELD_IDX_ETH_SA:
1125 case ICE_FLOW_FIELD_IDX_S_VLAN:
1126 case ICE_FLOW_FIELD_IDX_C_VLAN:
1127 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
1129 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
1130 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
1132 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
1133 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1135 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
1136 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1138 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
1139 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
1140 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1142 /* TTL and PROT share the same extraction seq. entry.
1143 * Each is considered a sibling to the other in terms of sharing
1144 * the same extraction sequence entry.
1146 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
1147 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
1149 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
1151 /* If the sibling field is also included, that field's
1152 * mask needs to be included.
1154 if (match & BIT(sib))
1155 sib_mask = ice_flds_info[sib].mask;
1157 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
1158 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
1159 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1161 /* TTL and PROT share the same extraction seq. entry.
1162 * Each is considered a sibling to the other in terms of sharing
1163 * the same extraction sequence entry.
1165 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
1166 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
1168 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
1170 /* If the sibling field is also included, that field's
1171 * mask needs to be included.
1173 if (match & BIT(sib))
1174 sib_mask = ice_flds_info[sib].mask;
1176 case ICE_FLOW_FIELD_IDX_IPV4_SA:
1177 case ICE_FLOW_FIELD_IDX_IPV4_DA:
1178 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
1180 case ICE_FLOW_FIELD_IDX_IPV6_SA:
1181 case ICE_FLOW_FIELD_IDX_IPV6_DA:
1182 case ICE_FLOW_FIELD_IDX_IPV6_PRE32_SA:
1183 case ICE_FLOW_FIELD_IDX_IPV6_PRE32_DA:
1184 case ICE_FLOW_FIELD_IDX_IPV6_PRE48_SA:
1185 case ICE_FLOW_FIELD_IDX_IPV6_PRE48_DA:
1186 case ICE_FLOW_FIELD_IDX_IPV6_PRE64_SA:
1187 case ICE_FLOW_FIELD_IDX_IPV6_PRE64_DA:
1188 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
1190 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
1191 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
1192 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
1193 prot_id = ICE_PROT_TCP_IL;
1195 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
1196 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
1197 prot_id = ICE_PROT_UDP_IL_OR_S;
1199 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
1200 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
1201 prot_id = ICE_PROT_SCTP_IL;
1203 case ICE_FLOW_FIELD_IDX_VXLAN_VNI:
1204 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
1205 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
1206 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
1207 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
1208 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
1209 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
1210 /* GTP is accessed through UDP OF protocol */
1211 prot_id = ICE_PROT_UDP_OF;
1213 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
1214 prot_id = ICE_PROT_PPPOE;
1216 case ICE_FLOW_FIELD_IDX_PFCP_SEID:
1217 prot_id = ICE_PROT_UDP_IL_OR_S;
1219 case ICE_FLOW_FIELD_IDX_L2TPV3_SESS_ID:
1220 prot_id = ICE_PROT_L2TPV3;
1222 case ICE_FLOW_FIELD_IDX_ESP_SPI:
1223 prot_id = ICE_PROT_ESP_F;
1225 case ICE_FLOW_FIELD_IDX_AH_SPI:
1226 prot_id = ICE_PROT_ESP_2;
1228 case ICE_FLOW_FIELD_IDX_NAT_T_ESP_SPI:
1229 prot_id = ICE_PROT_UDP_IL_OR_S;
1231 case ICE_FLOW_FIELD_IDX_ECPRI_TP0_PC_ID:
1232 prot_id = ICE_PROT_ECPRI;
1234 case ICE_FLOW_FIELD_IDX_UDP_ECPRI_TP0_PC_ID:
1235 prot_id = ICE_PROT_UDP_IL_OR_S;
1237 case ICE_FLOW_FIELD_IDX_ARP_SIP:
1238 case ICE_FLOW_FIELD_IDX_ARP_DIP:
1239 case ICE_FLOW_FIELD_IDX_ARP_SHA:
1240 case ICE_FLOW_FIELD_IDX_ARP_DHA:
1241 case ICE_FLOW_FIELD_IDX_ARP_OP:
1242 prot_id = ICE_PROT_ARP_OF;
1244 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
1245 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
1246 /* ICMP type and code share the same extraction seq. entry */
1247 prot_id = (params->prof->segs[seg].hdrs &
1248 ICE_FLOW_SEG_HDR_IPV4) ?
1249 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
1250 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
1251 ICE_FLOW_FIELD_IDX_ICMP_CODE :
1252 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
1254 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
1255 prot_id = ICE_PROT_GRE_OF;
1258 return ICE_ERR_NOT_IMPL;
1261 /* Each extraction sequence entry is a word in size, and extracts a
1262 * word-aligned offset from a protocol header.
1264 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
1266 flds[fld].xtrct.prot_id = prot_id;
1267 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
1268 ICE_FLOW_FV_EXTRACT_SZ;
1269 flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits);
1270 flds[fld].xtrct.idx = params->es_cnt;
1271 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
1273 /* Adjust the next field-entry index after accommodating the number of
1274 * entries this field consumes
1276 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
1277 ice_flds_info[fld].size, ese_bits);
1279 /* Fill in the extraction sequence entries needed for this field */
1280 off = flds[fld].xtrct.off;
1281 mask = flds[fld].xtrct.mask;
1282 for (i = 0; i < cnt; i++) {
1283 /* Only consume an extraction sequence entry if there is no
1284 * sibling field associated with this field or the sibling entry
1285 * already extracts the word shared with this field.
1287 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
1288 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
1289 flds[sib].xtrct.off != off) {
1292 /* Make sure the number of extraction sequence required
1293 * does not exceed the block's capability
1295 if (params->es_cnt >= fv_words)
1296 return ICE_ERR_MAX_LIMIT;
1298 /* some blocks require a reversed field vector layout */
1299 if (hw->blk[params->blk].es.reverse)
1300 idx = fv_words - params->es_cnt - 1;
1302 idx = params->es_cnt;
1304 params->es[idx].prot_id = prot_id;
1305 params->es[idx].off = off;
1306 params->mask[idx] = mask | sib_mask;
1310 off += ICE_FLOW_FV_EXTRACT_SZ;
1317 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
1318 * @hw: pointer to the HW struct
1319 * @params: information about the flow to be processed
1320 * @seg: index of packet segment whose raw fields are to be extracted
1322 static enum ice_status
1323 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
1330 if (!params->prof->segs[seg].raws_cnt)
1333 if (params->prof->segs[seg].raws_cnt >
1334 ARRAY_SIZE(params->prof->segs[seg].raws))
1335 return ICE_ERR_MAX_LIMIT;
1337 /* Offsets within the segment headers are not supported */
1338 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
1340 return ICE_ERR_PARAM;
1342 fv_words = hw->blk[params->blk].es.fvw;
1344 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
1345 struct ice_flow_seg_fld_raw *raw;
1348 raw = ¶ms->prof->segs[seg].raws[i];
1350 /* Storing extraction information */
1351 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
1352 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
1353 ICE_FLOW_FV_EXTRACT_SZ;
1354 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
1356 raw->info.xtrct.idx = params->es_cnt;
1358 /* Determine the number of field vector entries this raw field
1361 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
1362 (raw->info.src.last * BITS_PER_BYTE),
1363 (ICE_FLOW_FV_EXTRACT_SZ *
1365 off = raw->info.xtrct.off;
1366 for (j = 0; j < cnt; j++) {
1369 /* Make sure the number of extraction sequence required
1370 * does not exceed the block's capability
1372 if (params->es_cnt >= hw->blk[params->blk].es.count ||
1373 params->es_cnt >= ICE_MAX_FV_WORDS)
1374 return ICE_ERR_MAX_LIMIT;
1376 /* some blocks require a reversed field vector layout */
1377 if (hw->blk[params->blk].es.reverse)
1378 idx = fv_words - params->es_cnt - 1;
1380 idx = params->es_cnt;
1382 params->es[idx].prot_id = raw->info.xtrct.prot_id;
1383 params->es[idx].off = off;
1385 off += ICE_FLOW_FV_EXTRACT_SZ;
1393 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
1394 * @hw: pointer to the HW struct
1395 * @params: information about the flow to be processed
1397 * This function iterates through all matched fields in the given segments, and
1398 * creates an extraction sequence for the fields.
1400 static enum ice_status
1401 ice_flow_create_xtrct_seq(struct ice_hw *hw,
1402 struct ice_flow_prof_params *params)
1404 enum ice_status status = ICE_SUCCESS;
1407 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
1410 if (params->blk == ICE_BLK_ACL) {
1411 status = ice_flow_xtract_pkt_flags(hw, params,
1412 ICE_RX_MDID_PKT_FLAGS_15_0);
1417 for (i = 0; i < params->prof->segs_cnt; i++) {
1418 u64 match = params->prof->segs[i].match;
1419 enum ice_flow_field j;
1421 ice_for_each_set_bit(j, (ice_bitmap_t *)&match,
1422 ICE_FLOW_FIELD_IDX_MAX) {
1423 status = ice_flow_xtract_fld(hw, params, i, j, match);
1426 ice_clear_bit(j, (ice_bitmap_t *)&match);
1429 /* Process raw matching bytes */
1430 status = ice_flow_xtract_raws(hw, params, i);
1439 * ice_flow_sel_acl_scen - returns the specific scenario
1440 * @hw: pointer to the hardware structure
1441 * @params: information about the flow to be processed
1443 * This function will return the specific scenario based on the
1444 * params passed to it
1446 static enum ice_status
1447 ice_flow_sel_acl_scen(struct ice_hw *hw, struct ice_flow_prof_params *params)
1449 /* Find the best-fit scenario for the provided match width */
1450 struct ice_acl_scen *cand_scen = NULL, *scen;
1453 return ICE_ERR_DOES_NOT_EXIST;
1455 /* Loop through each scenario and match against the scenario width
1456 * to select the specific scenario
1458 LIST_FOR_EACH_ENTRY(scen, &hw->acl_tbl->scens, ice_acl_scen, list_entry)
1459 if (scen->eff_width >= params->entry_length &&
1460 (!cand_scen || cand_scen->eff_width > scen->eff_width))
1463 return ICE_ERR_DOES_NOT_EXIST;
1465 params->prof->cfg.scen = cand_scen;
1471 * ice_flow_acl_def_entry_frmt - Determine the layout of flow entries
1472 * @params: information about the flow to be processed
1474 static enum ice_status
1475 ice_flow_acl_def_entry_frmt(struct ice_flow_prof_params *params)
1477 u16 index, i, range_idx = 0;
1479 index = ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1481 for (i = 0; i < params->prof->segs_cnt; i++) {
1482 struct ice_flow_seg_info *seg = ¶ms->prof->segs[i];
1485 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
1486 ICE_FLOW_FIELD_IDX_MAX) {
1487 struct ice_flow_fld_info *fld = &seg->fields[j];
1489 fld->entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1491 if (fld->type == ICE_FLOW_FLD_TYPE_RANGE) {
1492 fld->entry.last = ICE_FLOW_FLD_OFF_INVAL;
1494 /* Range checking only supported for single
1497 if (DIVIDE_AND_ROUND_UP(ice_flds_info[j].size +
1499 BITS_PER_BYTE * 2) > 1)
1500 return ICE_ERR_PARAM;
1502 /* Ranges must define low and high values */
1503 if (fld->src.val == ICE_FLOW_FLD_OFF_INVAL ||
1504 fld->src.last == ICE_FLOW_FLD_OFF_INVAL)
1505 return ICE_ERR_PARAM;
1507 fld->entry.val = range_idx++;
1509 /* Store adjusted byte-length of field for later
1510 * use, taking into account potential
1511 * non-byte-aligned displacement
1513 fld->entry.last = DIVIDE_AND_ROUND_UP
1514 (ice_flds_info[j].size +
1515 (fld->xtrct.disp % BITS_PER_BYTE),
1517 fld->entry.val = index;
1518 index += fld->entry.last;
1522 for (j = 0; j < seg->raws_cnt; j++) {
1523 struct ice_flow_seg_fld_raw *raw = &seg->raws[j];
1525 raw->info.entry.mask = ICE_FLOW_FLD_OFF_INVAL;
1526 raw->info.entry.val = index;
1527 raw->info.entry.last = raw->info.src.last;
1528 index += raw->info.entry.last;
1532 /* Currently only support using the byte selection base, which only
1533 * allows for an effective entry size of 30 bytes. Reject anything
1536 if (index > ICE_AQC_ACL_PROF_BYTE_SEL_ELEMS)
1537 return ICE_ERR_PARAM;
1539 /* Only 8 range checkers per profile, reject anything trying to use
1542 if (range_idx > ICE_AQC_ACL_PROF_RANGES_NUM_CFG)
1543 return ICE_ERR_PARAM;
1545 /* Store # bytes required for entry for later use */
1546 params->entry_length = index - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
1552 * ice_flow_proc_segs - process all packet segments associated with a profile
1553 * @hw: pointer to the HW struct
1554 * @params: information about the flow to be processed
1556 static enum ice_status
1557 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1559 enum ice_status status;
1561 status = ice_flow_proc_seg_hdrs(params);
1565 status = ice_flow_create_xtrct_seq(hw, params);
1569 switch (params->blk) {
1572 status = ICE_SUCCESS;
1575 status = ice_flow_acl_def_entry_frmt(params);
1578 status = ice_flow_sel_acl_scen(hw, params);
1583 return ICE_ERR_NOT_IMPL;
1589 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1590 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
1591 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
1594 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1595 * @hw: pointer to the HW struct
1596 * @blk: classification stage
1597 * @dir: flow direction
1598 * @segs: array of one or more packet segments that describe the flow
1599 * @segs_cnt: number of packet segments provided
1600 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1601 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1603 static struct ice_flow_prof *
1604 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1605 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1606 u8 segs_cnt, u16 vsi_handle, u32 conds)
1608 struct ice_flow_prof *p, *prof = NULL;
1610 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1611 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1612 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1613 segs_cnt && segs_cnt == p->segs_cnt) {
1616 /* Check for profile-VSI association if specified */
1617 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1618 ice_is_vsi_valid(hw, vsi_handle) &&
1619 !ice_is_bit_set(p->vsis, vsi_handle))
1622 /* Protocol headers must be checked. Matched fields are
1623 * checked if specified.
1625 for (i = 0; i < segs_cnt; i++)
1626 if (segs[i].hdrs != p->segs[i].hdrs ||
1627 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1628 segs[i].match != p->segs[i].match))
1631 /* A match is found if all segments are matched */
1632 if (i == segs_cnt) {
1637 ice_release_lock(&hw->fl_profs_locks[blk]);
1643 * ice_flow_find_prof - Look up a profile matching headers and matched fields
1644 * @hw: pointer to the HW struct
1645 * @blk: classification stage
1646 * @dir: flow direction
1647 * @segs: array of one or more packet segments that describe the flow
1648 * @segs_cnt: number of packet segments provided
1651 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1652 struct ice_flow_seg_info *segs, u8 segs_cnt)
1654 struct ice_flow_prof *p;
1656 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1657 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1659 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1663 * ice_flow_find_prof_id - Look up a profile with given profile ID
1664 * @hw: pointer to the HW struct
1665 * @blk: classification stage
1666 * @prof_id: unique ID to identify this flow profile
1668 static struct ice_flow_prof *
1669 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1671 struct ice_flow_prof *p;
1673 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry)
1674 if (p->id == prof_id)
1681 * ice_dealloc_flow_entry - Deallocate flow entry memory
1682 * @hw: pointer to the HW struct
1683 * @entry: flow entry to be removed
1686 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1692 ice_free(hw, entry->entry);
1694 if (entry->range_buf) {
1695 ice_free(hw, entry->range_buf);
1696 entry->range_buf = NULL;
1700 ice_free(hw, entry->acts);
1702 entry->acts_cnt = 0;
1705 ice_free(hw, entry);
1709 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1710 * @hw: pointer to the HW struct
1711 * @blk: classification stage
1712 * @prof_id: the profile ID handle
1713 * @hw_prof_id: pointer to variable to receive the HW profile ID
1716 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1719 enum ice_status status = ICE_ERR_DOES_NOT_EXIST;
1720 struct ice_prof_map *map;
1722 ice_acquire_lock(&hw->blk[blk].es.prof_map_lock);
1723 map = ice_search_prof_id(hw, blk, prof_id);
1725 *hw_prof_id = map->prof_id;
1726 status = ICE_SUCCESS;
1728 ice_release_lock(&hw->blk[blk].es.prof_map_lock);
1732 #define ICE_ACL_INVALID_SCEN 0x3f
1735 * ice_flow_acl_is_prof_in_use - Verify if the profile is associated to any PF
1736 * @hw: pointer to the hardware structure
1737 * @prof: pointer to flow profile
1738 * @buf: destination buffer function writes partial extraction sequence to
1740 * returns ICE_SUCCESS if no PF is associated to the given profile
1741 * returns ICE_ERR_IN_USE if at least one PF is associated to the given profile
1742 * returns other error code for real error
1744 static enum ice_status
1745 ice_flow_acl_is_prof_in_use(struct ice_hw *hw, struct ice_flow_prof *prof,
1746 struct ice_aqc_acl_prof_generic_frmt *buf)
1748 enum ice_status status;
1751 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1755 status = ice_query_acl_prof(hw, prof_id, buf, NULL);
1759 /* If all PF's associated scenarios are all 0 or all
1760 * ICE_ACL_INVALID_SCEN (63) for the given profile then the latter has
1761 * not been configured yet.
1763 if (buf->pf_scenario_num[0] == 0 && buf->pf_scenario_num[1] == 0 &&
1764 buf->pf_scenario_num[2] == 0 && buf->pf_scenario_num[3] == 0 &&
1765 buf->pf_scenario_num[4] == 0 && buf->pf_scenario_num[5] == 0 &&
1766 buf->pf_scenario_num[6] == 0 && buf->pf_scenario_num[7] == 0)
1769 if (buf->pf_scenario_num[0] == ICE_ACL_INVALID_SCEN &&
1770 buf->pf_scenario_num[1] == ICE_ACL_INVALID_SCEN &&
1771 buf->pf_scenario_num[2] == ICE_ACL_INVALID_SCEN &&
1772 buf->pf_scenario_num[3] == ICE_ACL_INVALID_SCEN &&
1773 buf->pf_scenario_num[4] == ICE_ACL_INVALID_SCEN &&
1774 buf->pf_scenario_num[5] == ICE_ACL_INVALID_SCEN &&
1775 buf->pf_scenario_num[6] == ICE_ACL_INVALID_SCEN &&
1776 buf->pf_scenario_num[7] == ICE_ACL_INVALID_SCEN)
1779 return ICE_ERR_IN_USE;
1783 * ice_flow_acl_free_act_cntr - Free the ACL rule's actions
1784 * @hw: pointer to the hardware structure
1785 * @acts: array of actions to be performed on a match
1786 * @acts_cnt: number of actions
1788 static enum ice_status
1789 ice_flow_acl_free_act_cntr(struct ice_hw *hw, struct ice_flow_action *acts,
1794 for (i = 0; i < acts_cnt; i++) {
1795 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
1796 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
1797 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
1798 struct ice_acl_cntrs cntrs;
1799 enum ice_status status;
1801 cntrs.bank = 0; /* Only bank0 for the moment */
1803 LE16_TO_CPU(acts[i].data.acl_act.value);
1805 LE16_TO_CPU(acts[i].data.acl_act.value);
1807 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
1808 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
1810 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
1812 status = ice_aq_dealloc_acl_cntrs(hw, &cntrs, NULL);
1821 * ice_flow_acl_disassoc_scen - Disassociate the scenario from the profile
1822 * @hw: pointer to the hardware structure
1823 * @prof: pointer to flow profile
1825 * Disassociate the scenario from the profile for the PF of the VSI.
1827 static enum ice_status
1828 ice_flow_acl_disassoc_scen(struct ice_hw *hw, struct ice_flow_prof *prof)
1830 struct ice_aqc_acl_prof_generic_frmt buf;
1831 enum ice_status status = ICE_SUCCESS;
1834 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
1836 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
1840 status = ice_query_acl_prof(hw, prof_id, &buf, NULL);
1844 /* Clear scenario for this PF */
1845 buf.pf_scenario_num[hw->pf_id] = ICE_ACL_INVALID_SCEN;
1846 status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);
1852 * ice_flow_rem_entry_sync - Remove a flow entry
1853 * @hw: pointer to the HW struct
1854 * @blk: classification stage
1855 * @entry: flow entry to be removed
1857 static enum ice_status
1858 ice_flow_rem_entry_sync(struct ice_hw *hw, enum ice_block blk,
1859 struct ice_flow_entry *entry)
1862 return ICE_ERR_BAD_PTR;
1864 if (blk == ICE_BLK_ACL) {
1865 enum ice_status status;
1868 return ICE_ERR_BAD_PTR;
1870 status = ice_acl_rem_entry(hw, entry->prof->cfg.scen,
1871 entry->scen_entry_idx);
1875 /* Checks if we need to release an ACL counter. */
1876 if (entry->acts_cnt && entry->acts)
1877 ice_flow_acl_free_act_cntr(hw, entry->acts,
1881 LIST_DEL(&entry->l_entry);
1883 ice_dealloc_flow_entry(hw, entry);
1889 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1890 * @hw: pointer to the HW struct
1891 * @blk: classification stage
1892 * @dir: flow direction
1893 * @prof_id: unique ID to identify this flow profile
1894 * @segs: array of one or more packet segments that describe the flow
1895 * @segs_cnt: number of packet segments provided
1896 * @acts: array of default actions
1897 * @acts_cnt: number of default actions
1898 * @prof: stores the returned flow profile added
1900 * Assumption: the caller has acquired the lock to the profile list
1902 static enum ice_status
1903 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1904 enum ice_flow_dir dir, u64 prof_id,
1905 struct ice_flow_seg_info *segs, u8 segs_cnt,
1906 struct ice_flow_action *acts, u8 acts_cnt,
1907 struct ice_flow_prof **prof)
1909 struct ice_flow_prof_params *params;
1910 enum ice_status status;
1913 if (!prof || (acts_cnt && !acts))
1914 return ICE_ERR_BAD_PTR;
1916 params = (struct ice_flow_prof_params *)ice_malloc(hw, sizeof(*params));
1918 return ICE_ERR_NO_MEMORY;
1920 params->prof = (struct ice_flow_prof *)
1921 ice_malloc(hw, sizeof(*params->prof));
1922 if (!params->prof) {
1923 status = ICE_ERR_NO_MEMORY;
1927 /* initialize extraction sequence to all invalid (0xff) */
1928 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1929 params->es[i].prot_id = ICE_PROT_INVALID;
1930 params->es[i].off = ICE_FV_OFFSET_INVAL;
1934 params->prof->id = prof_id;
1935 params->prof->dir = dir;
1936 params->prof->segs_cnt = segs_cnt;
1938 /* Make a copy of the segments that need to be persistent in the flow
1941 for (i = 0; i < segs_cnt; i++)
1942 ice_memcpy(¶ms->prof->segs[i], &segs[i], sizeof(*segs),
1943 ICE_NONDMA_TO_NONDMA);
1945 /* Make a copy of the actions that need to be persistent in the flow
1949 params->prof->acts = (struct ice_flow_action *)
1950 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1951 ICE_NONDMA_TO_NONDMA);
1953 if (!params->prof->acts) {
1954 status = ICE_ERR_NO_MEMORY;
1959 status = ice_flow_proc_segs(hw, params);
1961 ice_debug(hw, ICE_DBG_FLOW, "Error processing a flow's packet segments\n");
1965 /* Add a HW profile for this flow profile */
1966 status = ice_add_prof(hw, blk, prof_id, (u8 *)params->ptypes,
1967 params->attr, params->attr_cnt, params->es,
1970 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1974 INIT_LIST_HEAD(¶ms->prof->entries);
1975 ice_init_lock(¶ms->prof->entries_lock);
1976 *prof = params->prof;
1980 if (params->prof->acts)
1981 ice_free(hw, params->prof->acts);
1982 ice_free(hw, params->prof);
1985 ice_free(hw, params);
1991 * ice_flow_rem_prof_sync - remove a flow profile
1992 * @hw: pointer to the hardware structure
1993 * @blk: classification stage
1994 * @prof: pointer to flow profile to remove
1996 * Assumption: the caller has acquired the lock to the profile list
1998 static enum ice_status
1999 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
2000 struct ice_flow_prof *prof)
2002 enum ice_status status;
2004 /* Remove all remaining flow entries before removing the flow profile */
2005 if (!LIST_EMPTY(&prof->entries)) {
2006 struct ice_flow_entry *e, *t;
2008 ice_acquire_lock(&prof->entries_lock);
2010 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
2012 status = ice_flow_rem_entry_sync(hw, blk, e);
2017 ice_release_lock(&prof->entries_lock);
2020 if (blk == ICE_BLK_ACL) {
2021 struct ice_aqc_acl_profile_ranges query_rng_buf;
2022 struct ice_aqc_acl_prof_generic_frmt buf;
2025 /* Disassociate the scenario from the profile for the PF */
2026 status = ice_flow_acl_disassoc_scen(hw, prof);
2030 /* Clear the range-checker if the profile ID is no longer
2033 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2034 if (status && status != ICE_ERR_IN_USE) {
2036 } else if (!status) {
2037 /* Clear the range-checker value for profile ID */
2038 ice_memset(&query_rng_buf, 0,
2039 sizeof(struct ice_aqc_acl_profile_ranges),
2042 status = ice_flow_get_hw_prof(hw, blk, prof->id,
2047 status = ice_prog_acl_prof_ranges(hw, prof_id,
2048 &query_rng_buf, NULL);
2054 /* Remove all hardware profiles associated with this flow profile */
2055 status = ice_rem_prof(hw, blk, prof->id);
2057 LIST_DEL(&prof->l_entry);
2058 ice_destroy_lock(&prof->entries_lock);
2060 ice_free(hw, prof->acts);
2068 * ice_flow_acl_set_xtrct_seq_fld - Populate xtrct seq for single field
2069 * @buf: Destination buffer function writes partial xtrct sequence to
2070 * @info: Info about field
2073 ice_flow_acl_set_xtrct_seq_fld(struct ice_aqc_acl_prof_generic_frmt *buf,
2074 struct ice_flow_fld_info *info)
2079 src = info->xtrct.idx * ICE_FLOW_FV_EXTRACT_SZ +
2080 info->xtrct.disp / BITS_PER_BYTE;
2081 dst = info->entry.val;
2082 for (i = 0; i < info->entry.last; i++)
2083 /* HW stores field vector words in LE, convert words back to BE
2084 * so constructed entries will end up in network order
2086 buf->byte_selection[dst++] = src++ ^ 1;
2090 * ice_flow_acl_set_xtrct_seq - Program ACL extraction sequence
2091 * @hw: pointer to the hardware structure
2092 * @prof: pointer to flow profile
2094 static enum ice_status
2095 ice_flow_acl_set_xtrct_seq(struct ice_hw *hw, struct ice_flow_prof *prof)
2097 struct ice_aqc_acl_prof_generic_frmt buf;
2098 struct ice_flow_fld_info *info;
2099 enum ice_status status;
2103 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2105 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2109 status = ice_flow_acl_is_prof_in_use(hw, prof, &buf);
2110 if (status && status != ICE_ERR_IN_USE)
2114 /* Program the profile dependent configuration. This is done
2115 * only once regardless of the number of PFs using that profile
2117 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM);
2119 for (i = 0; i < prof->segs_cnt; i++) {
2120 struct ice_flow_seg_info *seg = &prof->segs[i];
2123 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2124 ICE_FLOW_FIELD_IDX_MAX) {
2125 info = &seg->fields[j];
2127 if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2128 buf.word_selection[info->entry.val] =
2131 ice_flow_acl_set_xtrct_seq_fld(&buf,
2135 for (j = 0; j < seg->raws_cnt; j++) {
2136 info = &seg->raws[j].info;
2137 ice_flow_acl_set_xtrct_seq_fld(&buf, info);
2141 ice_memset(&buf.pf_scenario_num[0], ICE_ACL_INVALID_SCEN,
2142 ICE_AQC_ACL_PROF_PF_SCEN_NUM_ELEMS,
2146 /* Update the current PF */
2147 buf.pf_scenario_num[hw->pf_id] = (u8)prof->cfg.scen->id;
2148 status = ice_prgm_acl_prof_xtrct(hw, prof_id, &buf, NULL);
2154 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
2155 * @hw: pointer to the hardware structure
2156 * @blk: classification stage
2157 * @vsi_handle: software VSI handle
2158 * @vsig: target VSI group
2160 * Assumption: the caller has already verified that the VSI to
2161 * be added has the same characteristics as the VSIG and will
2162 * thereby have access to all resources added to that VSIG.
2165 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
2168 enum ice_status status;
2170 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
2171 return ICE_ERR_PARAM;
2173 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2174 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
2176 ice_release_lock(&hw->fl_profs_locks[blk]);
2182 * ice_flow_assoc_prof - associate a VSI with a flow profile
2183 * @hw: pointer to the hardware structure
2184 * @blk: classification stage
2185 * @prof: pointer to flow profile
2186 * @vsi_handle: software VSI handle
2188 * Assumption: the caller has acquired the lock to the profile list
2189 * and the software VSI handle has been validated
2192 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
2193 struct ice_flow_prof *prof, u16 vsi_handle)
2195 enum ice_status status = ICE_SUCCESS;
2197 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
2198 if (blk == ICE_BLK_ACL) {
2199 status = ice_flow_acl_set_xtrct_seq(hw, prof);
2203 status = ice_add_prof_id_flow(hw, blk,
2204 ice_get_hw_vsi_num(hw,
2208 ice_set_bit(vsi_handle, prof->vsis);
2210 ice_debug(hw, ICE_DBG_FLOW, "HW profile add failed, %d\n",
2218 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
2219 * @hw: pointer to the hardware structure
2220 * @blk: classification stage
2221 * @prof: pointer to flow profile
2222 * @vsi_handle: software VSI handle
2224 * Assumption: the caller has acquired the lock to the profile list
2225 * and the software VSI handle has been validated
2227 static enum ice_status
2228 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
2229 struct ice_flow_prof *prof, u16 vsi_handle)
2231 enum ice_status status = ICE_SUCCESS;
2233 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
2234 status = ice_rem_prof_id_flow(hw, blk,
2235 ice_get_hw_vsi_num(hw,
2239 ice_clear_bit(vsi_handle, prof->vsis);
2241 ice_debug(hw, ICE_DBG_FLOW, "HW profile remove failed, %d\n",
2249 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
2250 * @hw: pointer to the HW struct
2251 * @blk: classification stage
2252 * @dir: flow direction
2253 * @prof_id: unique ID to identify this flow profile
2254 * @segs: array of one or more packet segments that describe the flow
2255 * @segs_cnt: number of packet segments provided
2256 * @acts: array of default actions
2257 * @acts_cnt: number of default actions
2258 * @prof: stores the returned flow profile added
2261 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
2262 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
2263 struct ice_flow_action *acts, u8 acts_cnt,
2264 struct ice_flow_prof **prof)
2266 enum ice_status status;
2268 if (segs_cnt > ICE_FLOW_SEG_MAX)
2269 return ICE_ERR_MAX_LIMIT;
2272 return ICE_ERR_PARAM;
2275 return ICE_ERR_BAD_PTR;
2277 status = ice_flow_val_hdrs(segs, segs_cnt);
2281 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2283 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
2284 acts, acts_cnt, prof);
2286 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
2288 ice_release_lock(&hw->fl_profs_locks[blk]);
2294 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
2295 * @hw: pointer to the HW struct
2296 * @blk: the block for which the flow profile is to be removed
2297 * @prof_id: unique ID of the flow profile to be removed
2300 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
2302 struct ice_flow_prof *prof;
2303 enum ice_status status;
2305 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2307 prof = ice_flow_find_prof_id(hw, blk, prof_id);
2309 status = ICE_ERR_DOES_NOT_EXIST;
2313 /* prof becomes invalid after the call */
2314 status = ice_flow_rem_prof_sync(hw, blk, prof);
2317 ice_release_lock(&hw->fl_profs_locks[blk]);
2323 * ice_flow_find_entry - look for a flow entry using its unique ID
2324 * @hw: pointer to the HW struct
2325 * @blk: classification stage
2326 * @entry_id: unique ID to identify this flow entry
2328 * This function looks for the flow entry with the specified unique ID in all
2329 * flow profiles of the specified classification stage. If the entry is found,
2330 * and it returns the handle to the flow entry. Otherwise, it returns
2331 * ICE_FLOW_ENTRY_ID_INVAL.
2333 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
2335 struct ice_flow_entry *found = NULL;
2336 struct ice_flow_prof *p;
2338 ice_acquire_lock(&hw->fl_profs_locks[blk]);
2340 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
2341 struct ice_flow_entry *e;
2343 ice_acquire_lock(&p->entries_lock);
2344 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
2345 if (e->id == entry_id) {
2349 ice_release_lock(&p->entries_lock);
2355 ice_release_lock(&hw->fl_profs_locks[blk]);
2357 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
2361 * ice_flow_acl_check_actions - Checks the ACL rule's actions
2362 * @hw: pointer to the hardware structure
2363 * @acts: array of actions to be performed on a match
2364 * @acts_cnt: number of actions
2365 * @cnt_alloc: indicates if an ACL counter has been allocated.
2367 static enum ice_status
2368 ice_flow_acl_check_actions(struct ice_hw *hw, struct ice_flow_action *acts,
2369 u8 acts_cnt, bool *cnt_alloc)
2371 ice_declare_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2374 ice_zero_bitmap(dup_check, ICE_AQC_TBL_MAX_ACTION_PAIRS * 2);
2377 if (acts_cnt > ICE_FLOW_ACL_MAX_NUM_ACT)
2378 return ICE_ERR_OUT_OF_RANGE;
2380 for (i = 0; i < acts_cnt; i++) {
2381 if (acts[i].type != ICE_FLOW_ACT_NOP &&
2382 acts[i].type != ICE_FLOW_ACT_DROP &&
2383 acts[i].type != ICE_FLOW_ACT_CNTR_PKT &&
2384 acts[i].type != ICE_FLOW_ACT_FWD_QUEUE)
2387 /* If the caller want to add two actions of the same type, then
2388 * it is considered invalid configuration.
2390 if (ice_test_and_set_bit(acts[i].type, dup_check))
2391 return ICE_ERR_PARAM;
2394 /* Checks if ACL counters are needed. */
2395 for (i = 0; i < acts_cnt; i++) {
2396 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT ||
2397 acts[i].type == ICE_FLOW_ACT_CNTR_BYTES ||
2398 acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES) {
2399 struct ice_acl_cntrs cntrs;
2400 enum ice_status status;
2403 cntrs.bank = 0; /* Only bank0 for the moment */
2405 if (acts[i].type == ICE_FLOW_ACT_CNTR_PKT_BYTES)
2406 cntrs.type = ICE_AQC_ACL_CNT_TYPE_DUAL;
2408 cntrs.type = ICE_AQC_ACL_CNT_TYPE_SINGLE;
2410 status = ice_aq_alloc_acl_cntrs(hw, &cntrs, NULL);
2413 /* Counter index within the bank */
2414 acts[i].data.acl_act.value =
2415 CPU_TO_LE16(cntrs.first_cntr);
2424 * ice_flow_acl_frmt_entry_range - Format an ACL range checker for a given field
2425 * @fld: number of the given field
2426 * @info: info about field
2427 * @range_buf: range checker configuration buffer
2428 * @data: pointer to a data buffer containing flow entry's match values/masks
2429 * @range: Input/output param indicating which range checkers are being used
2432 ice_flow_acl_frmt_entry_range(u16 fld, struct ice_flow_fld_info *info,
2433 struct ice_aqc_acl_profile_ranges *range_buf,
2434 u8 *data, u8 *range)
2438 /* If not specified, default mask is all bits in field */
2439 new_mask = (info->src.mask == ICE_FLOW_FLD_OFF_INVAL ?
2440 BIT(ice_flds_info[fld].size) - 1 :
2441 (*(u16 *)(data + info->src.mask))) << info->xtrct.disp;
2443 /* If the mask is 0, then we don't need to worry about this input
2444 * range checker value.
2448 (*(u16 *)(data + info->src.last)) << info->xtrct.disp;
2450 (*(u16 *)(data + info->src.val)) << info->xtrct.disp;
2451 u8 range_idx = info->entry.val;
2453 range_buf->checker_cfg[range_idx].low_boundary =
2454 CPU_TO_BE16(new_low);
2455 range_buf->checker_cfg[range_idx].high_boundary =
2456 CPU_TO_BE16(new_high);
2457 range_buf->checker_cfg[range_idx].mask = CPU_TO_BE16(new_mask);
2459 /* Indicate which range checker is being used */
2460 *range |= BIT(range_idx);
2465 * ice_flow_acl_frmt_entry_fld - Partially format ACL entry for a given field
2466 * @fld: number of the given field
2467 * @info: info about the field
2468 * @buf: buffer containing the entry
2469 * @dontcare: buffer containing don't care mask for entry
2470 * @data: pointer to a data buffer containing flow entry's match values/masks
2473 ice_flow_acl_frmt_entry_fld(u16 fld, struct ice_flow_fld_info *info, u8 *buf,
2474 u8 *dontcare, u8 *data)
2476 u16 dst, src, mask, k, end_disp, tmp_s = 0, tmp_m = 0;
2477 bool use_mask = false;
2480 src = info->src.val;
2481 mask = info->src.mask;
2482 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2483 disp = info->xtrct.disp % BITS_PER_BYTE;
2485 if (mask != ICE_FLOW_FLD_OFF_INVAL)
2488 for (k = 0; k < info->entry.last; k++, dst++) {
2489 /* Add overflow bits from previous byte */
2490 buf[dst] = (tmp_s & 0xff00) >> 8;
2492 /* If mask is not valid, tmp_m is always zero, so just setting
2493 * dontcare to 0 (no masked bits). If mask is valid, pulls in
2494 * overflow bits of mask from prev byte
2496 dontcare[dst] = (tmp_m & 0xff00) >> 8;
2498 /* If there is displacement, last byte will only contain
2499 * displaced data, but there is no more data to read from user
2500 * buffer, so skip so as not to potentially read beyond end of
2503 if (!disp || k < info->entry.last - 1) {
2504 /* Store shifted data to use in next byte */
2505 tmp_s = data[src++] << disp;
2507 /* Add current (shifted) byte */
2508 buf[dst] |= tmp_s & 0xff;
2510 /* Handle mask if valid */
2512 tmp_m = (~data[mask++] & 0xff) << disp;
2513 dontcare[dst] |= tmp_m & 0xff;
2518 /* Fill in don't care bits at beginning of field */
2520 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2521 for (k = 0; k < disp; k++)
2522 dontcare[dst] |= BIT(k);
2525 end_disp = (disp + ice_flds_info[fld].size) % BITS_PER_BYTE;
2527 /* Fill in don't care bits at end of field */
2529 dst = info->entry.val - ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX +
2530 info->entry.last - 1;
2531 for (k = end_disp; k < BITS_PER_BYTE; k++)
2532 dontcare[dst] |= BIT(k);
2537 * ice_flow_acl_frmt_entry - Format ACL entry
2538 * @hw: pointer to the hardware structure
2539 * @prof: pointer to flow profile
2540 * @e: pointer to the flow entry
2541 * @data: pointer to a data buffer containing flow entry's match values/masks
2542 * @acts: array of actions to be performed on a match
2543 * @acts_cnt: number of actions
2545 * Formats the key (and key_inverse) to be matched from the data passed in,
2546 * along with data from the flow profile. This key/key_inverse pair makes up
2547 * the 'entry' for an ACL flow entry.
2549 static enum ice_status
2550 ice_flow_acl_frmt_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
2551 struct ice_flow_entry *e, u8 *data,
2552 struct ice_flow_action *acts, u8 acts_cnt)
2554 u8 *buf = NULL, *dontcare = NULL, *key = NULL, range = 0, dir_flag_msk;
2555 struct ice_aqc_acl_profile_ranges *range_buf = NULL;
2556 enum ice_status status;
2561 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id, &prof_id);
2565 /* Format the result action */
2567 status = ice_flow_acl_check_actions(hw, acts, acts_cnt, &cnt_alloc);
2571 status = ICE_ERR_NO_MEMORY;
2573 e->acts = (struct ice_flow_action *)
2574 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
2575 ICE_NONDMA_TO_NONDMA);
2579 e->acts_cnt = acts_cnt;
2581 /* Format the matching data */
2582 buf_sz = prof->cfg.scen->width;
2583 buf = (u8 *)ice_malloc(hw, buf_sz);
2587 dontcare = (u8 *)ice_malloc(hw, buf_sz);
2591 /* 'key' buffer will store both key and key_inverse, so must be twice
2594 key = (u8 *)ice_malloc(hw, buf_sz * 2);
2598 range_buf = (struct ice_aqc_acl_profile_ranges *)
2599 ice_malloc(hw, sizeof(struct ice_aqc_acl_profile_ranges));
2603 /* Set don't care mask to all 1's to start, will zero out used bytes */
2604 ice_memset(dontcare, 0xff, buf_sz, ICE_NONDMA_MEM);
2606 for (i = 0; i < prof->segs_cnt; i++) {
2607 struct ice_flow_seg_info *seg = &prof->segs[i];
2610 ice_for_each_set_bit(j, (ice_bitmap_t *)&seg->match,
2611 ICE_FLOW_FIELD_IDX_MAX) {
2612 struct ice_flow_fld_info *info = &seg->fields[j];
2614 if (info->type == ICE_FLOW_FLD_TYPE_RANGE)
2615 ice_flow_acl_frmt_entry_range(j, info,
2619 ice_flow_acl_frmt_entry_fld(j, info, buf,
2623 for (j = 0; j < seg->raws_cnt; j++) {
2624 struct ice_flow_fld_info *info = &seg->raws[j].info;
2625 u16 dst, src, mask, k;
2626 bool use_mask = false;
2628 src = info->src.val;
2629 dst = info->entry.val -
2630 ICE_AQC_ACL_PROF_BYTE_SEL_START_IDX;
2631 mask = info->src.mask;
2633 if (mask != ICE_FLOW_FLD_OFF_INVAL)
2636 for (k = 0; k < info->entry.last; k++, dst++) {
2637 buf[dst] = data[src++];
2639 dontcare[dst] = ~data[mask++];
2646 buf[prof->cfg.scen->pid_idx] = (u8)prof_id;
2647 dontcare[prof->cfg.scen->pid_idx] = 0;
2649 /* Format the buffer for direction flags */
2650 dir_flag_msk = BIT(ICE_FLG_PKT_DIR);
2652 if (prof->dir == ICE_FLOW_RX)
2653 buf[prof->cfg.scen->pkt_dir_idx] = dir_flag_msk;
2656 buf[prof->cfg.scen->rng_chk_idx] = range;
2657 /* Mark any unused range checkers as don't care */
2658 dontcare[prof->cfg.scen->rng_chk_idx] = ~range;
2659 e->range_buf = range_buf;
2661 ice_free(hw, range_buf);
2664 status = ice_set_key(key, buf_sz * 2, buf, NULL, dontcare, NULL, 0,
2670 e->entry_sz = buf_sz * 2;
2677 ice_free(hw, dontcare);
2682 if (status && range_buf) {
2683 ice_free(hw, range_buf);
2684 e->range_buf = NULL;
2687 if (status && e->acts) {
2688 ice_free(hw, e->acts);
2693 if (status && cnt_alloc)
2694 ice_flow_acl_free_act_cntr(hw, acts, acts_cnt);
2700 * ice_flow_acl_find_scen_entry_cond - Find an ACL scenario entry that matches
2701 * the compared data.
2702 * @prof: pointer to flow profile
2703 * @e: pointer to the comparing flow entry
2704 * @do_chg_action: decide if we want to change the ACL action
2705 * @do_add_entry: decide if we want to add the new ACL entry
2706 * @do_rem_entry: decide if we want to remove the current ACL entry
2708 * Find an ACL scenario entry that matches the compared data. In the same time,
2709 * this function also figure out:
2710 * a/ If we want to change the ACL action
2711 * b/ If we want to add the new ACL entry
2712 * c/ If we want to remove the current ACL entry
2714 static struct ice_flow_entry *
2715 ice_flow_acl_find_scen_entry_cond(struct ice_flow_prof *prof,
2716 struct ice_flow_entry *e, bool *do_chg_action,
2717 bool *do_add_entry, bool *do_rem_entry)
2719 struct ice_flow_entry *p, *return_entry = NULL;
2723 * a/ There exists an entry with same matching data, but different
2724 * priority, then we remove this existing ACL entry. Then, we
2725 * will add the new entry to the ACL scenario.
2726 * b/ There exists an entry with same matching data, priority, and
2727 * result action, then we do nothing
2728 * c/ There exists an entry with same matching data, priority, but
2729 * different, action, then do only change the action's entry.
2730 * d/ Else, we add this new entry to the ACL scenario.
2732 *do_chg_action = false;
2733 *do_add_entry = true;
2734 *do_rem_entry = false;
2735 LIST_FOR_EACH_ENTRY(p, &prof->entries, ice_flow_entry, l_entry) {
2736 if (memcmp(p->entry, e->entry, p->entry_sz))
2739 /* From this point, we have the same matching_data. */
2740 *do_add_entry = false;
2743 if (p->priority != e->priority) {
2744 /* matching data && !priority */
2745 *do_add_entry = true;
2746 *do_rem_entry = true;
2750 /* From this point, we will have matching_data && priority */
2751 if (p->acts_cnt != e->acts_cnt)
2752 *do_chg_action = true;
2753 for (i = 0; i < p->acts_cnt; i++) {
2754 bool found_not_match = false;
2756 for (j = 0; j < e->acts_cnt; j++)
2757 if (memcmp(&p->acts[i], &e->acts[j],
2758 sizeof(struct ice_flow_action))) {
2759 found_not_match = true;
2763 if (found_not_match) {
2764 *do_chg_action = true;
2769 /* (do_chg_action = true) means :
2770 * matching_data && priority && !result_action
2771 * (do_chg_action = false) means :
2772 * matching_data && priority && result_action
2777 return return_entry;
2781 * ice_flow_acl_convert_to_acl_prio - Convert to ACL priority
2784 static enum ice_acl_entry_prio
2785 ice_flow_acl_convert_to_acl_prio(enum ice_flow_priority p)
2787 enum ice_acl_entry_prio acl_prio;
2790 case ICE_FLOW_PRIO_LOW:
2791 acl_prio = ICE_ACL_PRIO_LOW;
2793 case ICE_FLOW_PRIO_NORMAL:
2794 acl_prio = ICE_ACL_PRIO_NORMAL;
2796 case ICE_FLOW_PRIO_HIGH:
2797 acl_prio = ICE_ACL_PRIO_HIGH;
2800 acl_prio = ICE_ACL_PRIO_NORMAL;
2808 * ice_flow_acl_union_rng_chk - Perform union operation between two
2809 * range-range checker buffers
2810 * @dst_buf: pointer to destination range checker buffer
2811 * @src_buf: pointer to source range checker buffer
2813 * For this function, we do the union between dst_buf and src_buf
2814 * range checker buffer, and we will save the result back to dst_buf
2816 static enum ice_status
2817 ice_flow_acl_union_rng_chk(struct ice_aqc_acl_profile_ranges *dst_buf,
2818 struct ice_aqc_acl_profile_ranges *src_buf)
2822 if (!dst_buf || !src_buf)
2823 return ICE_ERR_BAD_PTR;
2825 for (i = 0; i < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; i++) {
2826 struct ice_acl_rng_data *cfg_data = NULL, *in_data;
2827 bool will_populate = false;
2829 in_data = &src_buf->checker_cfg[i];
2834 for (j = 0; j < ICE_AQC_ACL_PROF_RANGES_NUM_CFG; j++) {
2835 cfg_data = &dst_buf->checker_cfg[j];
2837 if (!cfg_data->mask ||
2838 !memcmp(cfg_data, in_data,
2839 sizeof(struct ice_acl_rng_data))) {
2840 will_populate = true;
2845 if (will_populate) {
2846 ice_memcpy(cfg_data, in_data,
2847 sizeof(struct ice_acl_rng_data),
2848 ICE_NONDMA_TO_NONDMA);
2850 /* No available slot left to program range checker */
2851 return ICE_ERR_MAX_LIMIT;
2859 * ice_flow_acl_add_scen_entry_sync - Add entry to ACL scenario sync
2860 * @hw: pointer to the hardware structure
2861 * @prof: pointer to flow profile
2862 * @entry: double pointer to the flow entry
2864 * For this function, we will look at the current added entries in the
2865 * corresponding ACL scenario. Then, we will perform matching logic to
2866 * see if we want to add/modify/do nothing with this new entry.
2868 static enum ice_status
2869 ice_flow_acl_add_scen_entry_sync(struct ice_hw *hw, struct ice_flow_prof *prof,
2870 struct ice_flow_entry **entry)
2872 bool do_add_entry, do_rem_entry, do_chg_action, do_chg_rng_chk;
2873 struct ice_aqc_acl_profile_ranges query_rng_buf, cfg_rng_buf;
2874 struct ice_acl_act_entry *acts = NULL;
2875 struct ice_flow_entry *exist;
2876 enum ice_status status = ICE_SUCCESS;
2877 struct ice_flow_entry *e;
2880 if (!entry || !(*entry) || !prof)
2881 return ICE_ERR_BAD_PTR;
2885 do_chg_rng_chk = false;
2889 status = ice_flow_get_hw_prof(hw, ICE_BLK_ACL, prof->id,
2894 /* Query the current range-checker value in FW */
2895 status = ice_query_acl_prof_ranges(hw, prof_id, &query_rng_buf,
2899 ice_memcpy(&cfg_rng_buf, &query_rng_buf,
2900 sizeof(struct ice_aqc_acl_profile_ranges),
2901 ICE_NONDMA_TO_NONDMA);
2903 /* Generate the new range-checker value */
2904 status = ice_flow_acl_union_rng_chk(&cfg_rng_buf, e->range_buf);
2908 /* Reconfigure the range check if the buffer is changed. */
2909 do_chg_rng_chk = false;
2910 if (memcmp(&query_rng_buf, &cfg_rng_buf,
2911 sizeof(struct ice_aqc_acl_profile_ranges))) {
2912 status = ice_prog_acl_prof_ranges(hw, prof_id,
2913 &cfg_rng_buf, NULL);
2917 do_chg_rng_chk = true;
2921 /* Figure out if we want to (change the ACL action) and/or
2922 * (Add the new ACL entry) and/or (Remove the current ACL entry)
2924 exist = ice_flow_acl_find_scen_entry_cond(prof, e, &do_chg_action,
2925 &do_add_entry, &do_rem_entry);
2927 status = ice_flow_rem_entry_sync(hw, ICE_BLK_ACL, exist);
2932 /* Prepare the result action buffer */
2933 acts = (struct ice_acl_act_entry *)
2934 ice_calloc(hw, e->entry_sz, sizeof(struct ice_acl_act_entry));
2936 return ICE_ERR_NO_MEMORY;
2938 for (i = 0; i < e->acts_cnt; i++)
2939 ice_memcpy(&acts[i], &e->acts[i].data.acl_act,
2940 sizeof(struct ice_acl_act_entry),
2941 ICE_NONDMA_TO_NONDMA);
2944 enum ice_acl_entry_prio prio;
2948 keys = (u8 *)e->entry;
2949 inverts = keys + (e->entry_sz / 2);
2950 prio = ice_flow_acl_convert_to_acl_prio(e->priority);
2952 status = ice_acl_add_entry(hw, prof->cfg.scen, prio, keys,
2953 inverts, acts, e->acts_cnt,
2958 e->scen_entry_idx = entry_idx;
2959 LIST_ADD(&e->l_entry, &prof->entries);
2961 if (do_chg_action) {
2962 /* For the action memory info, update the SW's copy of
2963 * exist entry with e's action memory info
2965 ice_free(hw, exist->acts);
2966 exist->acts_cnt = e->acts_cnt;
2967 exist->acts = (struct ice_flow_action *)
2968 ice_calloc(hw, exist->acts_cnt,
2969 sizeof(struct ice_flow_action));
2971 status = ICE_ERR_NO_MEMORY;
2975 ice_memcpy(exist->acts, e->acts,
2976 sizeof(struct ice_flow_action) * e->acts_cnt,
2977 ICE_NONDMA_TO_NONDMA);
2979 status = ice_acl_prog_act(hw, prof->cfg.scen, acts,
2981 exist->scen_entry_idx);
2986 if (do_chg_rng_chk) {
2987 /* In this case, we want to update the range checker
2988 * information of the exist entry
2990 status = ice_flow_acl_union_rng_chk(exist->range_buf,
2996 /* As we don't add the new entry to our SW DB, deallocate its
2997 * memories, and return the exist entry to the caller
2999 ice_dealloc_flow_entry(hw, e);
3009 * ice_flow_acl_add_scen_entry - Add entry to ACL scenario
3010 * @hw: pointer to the hardware structure
3011 * @prof: pointer to flow profile
3012 * @e: double pointer to the flow entry
3014 static enum ice_status
3015 ice_flow_acl_add_scen_entry(struct ice_hw *hw, struct ice_flow_prof *prof,
3016 struct ice_flow_entry **e)
3018 enum ice_status status;
3020 ice_acquire_lock(&prof->entries_lock);
3021 status = ice_flow_acl_add_scen_entry_sync(hw, prof, e);
3022 ice_release_lock(&prof->entries_lock);
3028 * ice_flow_add_entry - Add a flow entry
3029 * @hw: pointer to the HW struct
3030 * @blk: classification stage
3031 * @prof_id: ID of the profile to add a new flow entry to
3032 * @entry_id: unique ID to identify this flow entry
3033 * @vsi_handle: software VSI handle for the flow entry
3034 * @prio: priority of the flow entry
3035 * @data: pointer to a data buffer containing flow entry's match values/masks
3036 * @acts: arrays of actions to be performed on a match
3037 * @acts_cnt: number of actions
3038 * @entry_h: pointer to buffer that receives the new flow entry's handle
3041 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
3042 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
3043 void *data, struct ice_flow_action *acts, u8 acts_cnt,
3046 struct ice_flow_entry *e = NULL;
3047 struct ice_flow_prof *prof;
3048 enum ice_status status = ICE_SUCCESS;
3050 /* ACL entries must indicate an action */
3051 if (blk == ICE_BLK_ACL && (!acts || !acts_cnt))
3052 return ICE_ERR_PARAM;
3054 /* No flow entry data is expected for RSS */
3055 if (!entry_h || (!data && blk != ICE_BLK_RSS))
3056 return ICE_ERR_BAD_PTR;
3058 if (!ice_is_vsi_valid(hw, vsi_handle))
3059 return ICE_ERR_PARAM;
3061 ice_acquire_lock(&hw->fl_profs_locks[blk]);
3063 prof = ice_flow_find_prof_id(hw, blk, prof_id);
3065 status = ICE_ERR_DOES_NOT_EXIST;
3067 /* Allocate memory for the entry being added and associate
3068 * the VSI to the found flow profile
3070 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
3072 status = ICE_ERR_NO_MEMORY;
3074 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3077 ice_release_lock(&hw->fl_profs_locks[blk]);
3082 e->vsi_handle = vsi_handle;
3091 /* ACL will handle the entry management */
3092 status = ice_flow_acl_frmt_entry(hw, prof, e, (u8 *)data, acts,
3097 status = ice_flow_acl_add_scen_entry(hw, prof, &e);
3103 status = ICE_ERR_NOT_IMPL;
3107 if (blk != ICE_BLK_ACL) {
3108 /* ACL will handle the entry management */
3109 ice_acquire_lock(&prof->entries_lock);
3110 LIST_ADD(&e->l_entry, &prof->entries);
3111 ice_release_lock(&prof->entries_lock);
3114 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
3119 ice_free(hw, e->entry);
3127 * ice_flow_rem_entry - Remove a flow entry
3128 * @hw: pointer to the HW struct
3129 * @blk: classification stage
3130 * @entry_h: handle to the flow entry to be removed
3132 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, enum ice_block blk,
3135 struct ice_flow_entry *entry;
3136 struct ice_flow_prof *prof;
3137 enum ice_status status = ICE_SUCCESS;
3139 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
3140 return ICE_ERR_PARAM;
3142 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
3144 /* Retain the pointer to the flow profile as the entry will be freed */
3148 ice_acquire_lock(&prof->entries_lock);
3149 status = ice_flow_rem_entry_sync(hw, blk, entry);
3150 ice_release_lock(&prof->entries_lock);
3157 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
3158 * @seg: packet segment the field being set belongs to
3159 * @fld: field to be set
3160 * @field_type: type of the field
3161 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3162 * entry's input buffer
3163 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3165 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3166 * entry's input buffer
3168 * This helper function stores information of a field being matched, including
3169 * the type of the field and the locations of the value to match, the mask, and
3170 * the upper-bound value in the start of the input buffer for a flow entry.
3171 * This function should only be used for fixed-size data structures.
3173 * This function also opportunistically determines the protocol headers to be
3174 * present based on the fields being set. Some fields cannot be used alone to
3175 * determine the protocol headers present. Sometimes, fields for particular
3176 * protocol headers are not matched. In those cases, the protocol headers
3177 * must be explicitly set.
3180 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3181 enum ice_flow_fld_match_type field_type, u16 val_loc,
3182 u16 mask_loc, u16 last_loc)
3184 u64 bit = BIT_ULL(fld);
3187 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
3190 seg->fields[fld].type = field_type;
3191 seg->fields[fld].src.val = val_loc;
3192 seg->fields[fld].src.mask = mask_loc;
3193 seg->fields[fld].src.last = last_loc;
3195 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
3199 * ice_flow_set_fld - specifies locations of field from entry's input buffer
3200 * @seg: packet segment the field being set belongs to
3201 * @fld: field to be set
3202 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3203 * entry's input buffer
3204 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
3206 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
3207 * entry's input buffer
3208 * @range: indicate if field being matched is to be in a range
3210 * This function specifies the locations, in the form of byte offsets from the
3211 * start of the input buffer for a flow entry, from where the value to match,
3212 * the mask value, and upper value can be extracted. These locations are then
3213 * stored in the flow profile. When adding a flow entry associated with the
3214 * flow profile, these locations will be used to quickly extract the values and
3215 * create the content of a match entry. This function should only be used for
3216 * fixed-size data structures.
3219 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3220 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
3222 enum ice_flow_fld_match_type t = range ?
3223 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
3225 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
3229 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
3230 * @seg: packet segment the field being set belongs to
3231 * @fld: field to be set
3232 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
3233 * entry's input buffer
3234 * @pref_loc: location of prefix value from entry's input buffer
3235 * @pref_sz: size of the location holding the prefix value
3237 * This function specifies the locations, in the form of byte offsets from the
3238 * start of the input buffer for a flow entry, from where the value to match
3239 * and the IPv4 prefix value can be extracted. These locations are then stored
3240 * in the flow profile. When adding flow entries to the associated flow profile,
3241 * these locations can be used to quickly extract the values to create the
3242 * content of a match entry. This function should only be used for fixed-size
3246 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
3247 u16 val_loc, u16 pref_loc, u8 pref_sz)
3249 /* For this type of field, the "mask" location is for the prefix value's
3250 * location and the "last" location is for the size of the location of
3253 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
3254 pref_loc, (u16)pref_sz);
3258 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
3259 * @seg: packet segment the field being set belongs to
3260 * @off: offset of the raw field from the beginning of the segment in bytes
3261 * @len: length of the raw pattern to be matched
3262 * @val_loc: location of the value to match from entry's input buffer
3263 * @mask_loc: location of mask value from entry's input buffer
3265 * This function specifies the offset of the raw field to be match from the
3266 * beginning of the specified packet segment, and the locations, in the form of
3267 * byte offsets from the start of the input buffer for a flow entry, from where
3268 * the value to match and the mask value to be extracted. These locations are
3269 * then stored in the flow profile. When adding flow entries to the associated
3270 * flow profile, these locations can be used to quickly extract the values to
3271 * create the content of a match entry. This function should only be used for
3272 * fixed-size data structures.
3275 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
3276 u16 val_loc, u16 mask_loc)
3278 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
3279 seg->raws[seg->raws_cnt].off = off;
3280 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
3281 seg->raws[seg->raws_cnt].info.src.val = val_loc;
3282 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
3283 /* The "last" field is used to store the length of the field */
3284 seg->raws[seg->raws_cnt].info.src.last = len;
3287 /* Overflows of "raws" will be handled as an error condition later in
3288 * the flow when this information is processed.
3293 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
3294 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
3296 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
3297 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
3299 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
3300 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP)
3302 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
3303 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
3304 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
3305 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
3308 * ice_flow_set_rss_seg_info - setup packet segments for RSS
3309 * @segs: pointer to the flow field segment(s)
3310 * @seg_cnt: segment count
3311 * @cfg: configure parameters
3313 * Helper function to extract fields from hash bitmap and use flow
3314 * header value to set flow field segment for further use in flow
3315 * profile entry or removal.
3317 static enum ice_status
3318 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u8 seg_cnt,
3319 const struct ice_rss_hash_cfg *cfg)
3321 struct ice_flow_seg_info *seg;
3325 /* set inner most segment */
3326 seg = &segs[seg_cnt - 1];
3328 ice_for_each_set_bit(i, (const ice_bitmap_t *)&cfg->hash_flds,
3329 ICE_FLOW_FIELD_IDX_MAX)
3330 ice_flow_set_fld(seg, (enum ice_flow_field)i,
3331 ICE_FLOW_FLD_OFF_INVAL, ICE_FLOW_FLD_OFF_INVAL,
3332 ICE_FLOW_FLD_OFF_INVAL, false);
3334 ICE_FLOW_SET_HDRS(seg, cfg->addl_hdrs);
3336 /* set outer most header */
3337 if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV4)
3338 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV4 |
3339 ICE_FLOW_SEG_HDR_IPV_OTHER;
3340 else if (cfg->hdr_type == ICE_RSS_INNER_HEADERS_W_OUTER_IPV6)
3341 segs[ICE_RSS_OUTER_HEADERS].hdrs |= ICE_FLOW_SEG_HDR_IPV6 |
3342 ICE_FLOW_SEG_HDR_IPV_OTHER;
3344 if (seg->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
3345 ~ICE_FLOW_RSS_HDRS_INNER_MASK & ~ICE_FLOW_SEG_HDR_IPV_OTHER)
3346 return ICE_ERR_PARAM;
3348 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
3349 if (val && !ice_is_pow2(val))
3352 val = (u64)(seg->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
3353 if (val && !ice_is_pow2(val))
3360 * ice_rem_vsi_rss_list - remove VSI from RSS list
3361 * @hw: pointer to the hardware structure
3362 * @vsi_handle: software VSI handle
3364 * Remove the VSI from all RSS configurations in the list.
3366 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
3368 struct ice_rss_cfg *r, *tmp;
3370 if (LIST_EMPTY(&hw->rss_list_head))
3373 ice_acquire_lock(&hw->rss_locks);
3374 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3375 ice_rss_cfg, l_entry)
3376 if (ice_test_and_clear_bit(vsi_handle, r->vsis))
3377 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3378 LIST_DEL(&r->l_entry);
3381 ice_release_lock(&hw->rss_locks);
3385 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
3386 * @hw: pointer to the hardware structure
3387 * @vsi_handle: software VSI handle
3389 * This function will iterate through all flow profiles and disassociate
3390 * the VSI from that profile. If the flow profile has no VSIs it will
3393 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3395 const enum ice_block blk = ICE_BLK_RSS;
3396 struct ice_flow_prof *p, *t;
3397 enum ice_status status = ICE_SUCCESS;
3399 if (!ice_is_vsi_valid(hw, vsi_handle))
3400 return ICE_ERR_PARAM;
3402 if (LIST_EMPTY(&hw->fl_profs[blk]))
3405 ice_acquire_lock(&hw->rss_locks);
3406 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
3408 if (ice_is_bit_set(p->vsis, vsi_handle)) {
3409 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
3413 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
3414 status = ice_flow_rem_prof(hw, blk, p->id);
3419 ice_release_lock(&hw->rss_locks);
3425 * ice_get_rss_hdr_type - get a RSS profile's header type
3426 * @prof: RSS flow profile
3428 static enum ice_rss_cfg_hdr_type
3429 ice_get_rss_hdr_type(struct ice_flow_prof *prof)
3431 enum ice_rss_cfg_hdr_type hdr_type = ICE_RSS_ANY_HEADERS;
3433 if (prof->segs_cnt == ICE_FLOW_SEG_SINGLE) {
3434 hdr_type = ICE_RSS_OUTER_HEADERS;
3435 } else if (prof->segs_cnt == ICE_FLOW_SEG_MAX) {
3436 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs == ICE_FLOW_SEG_HDR_NONE)
3437 hdr_type = ICE_RSS_INNER_HEADERS;
3438 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV4)
3439 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV4;
3440 if (prof->segs[ICE_RSS_OUTER_HEADERS].hdrs & ICE_FLOW_SEG_HDR_IPV6)
3441 hdr_type = ICE_RSS_INNER_HEADERS_W_OUTER_IPV6;
3448 * ice_rem_rss_list - remove RSS configuration from list
3449 * @hw: pointer to the hardware structure
3450 * @vsi_handle: software VSI handle
3451 * @prof: pointer to flow profile
3453 * Assumption: lock has already been acquired for RSS list
3456 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3458 enum ice_rss_cfg_hdr_type hdr_type;
3459 struct ice_rss_cfg *r, *tmp;
3461 /* Search for RSS hash fields associated to the VSI that match the
3462 * hash configurations associated to the flow profile. If found
3463 * remove from the RSS entry list of the VSI context and delete entry.
3465 hdr_type = ice_get_rss_hdr_type(prof);
3466 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
3467 ice_rss_cfg, l_entry)
3468 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
3469 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
3470 r->hash.hdr_type == hdr_type) {
3471 ice_clear_bit(vsi_handle, r->vsis);
3472 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
3473 LIST_DEL(&r->l_entry);
3481 * ice_add_rss_list - add RSS configuration to list
3482 * @hw: pointer to the hardware structure
3483 * @vsi_handle: software VSI handle
3484 * @prof: pointer to flow profile
3486 * Assumption: lock has already been acquired for RSS list
3488 static enum ice_status
3489 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
3491 enum ice_rss_cfg_hdr_type hdr_type;
3492 struct ice_rss_cfg *r, *rss_cfg;
3494 hdr_type = ice_get_rss_hdr_type(prof);
3495 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3496 ice_rss_cfg, l_entry)
3497 if (r->hash.hash_flds == prof->segs[prof->segs_cnt - 1].match &&
3498 r->hash.addl_hdrs == prof->segs[prof->segs_cnt - 1].hdrs &&
3499 r->hash.hdr_type == hdr_type) {
3500 ice_set_bit(vsi_handle, r->vsis);
3504 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
3506 return ICE_ERR_NO_MEMORY;
3508 rss_cfg->hash.hash_flds = prof->segs[prof->segs_cnt - 1].match;
3509 rss_cfg->hash.addl_hdrs = prof->segs[prof->segs_cnt - 1].hdrs;
3510 rss_cfg->hash.hdr_type = hdr_type;
3511 rss_cfg->hash.symm = prof->cfg.symm;
3512 ice_set_bit(vsi_handle, rss_cfg->vsis);
3514 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
3519 #define ICE_FLOW_PROF_HASH_S 0
3520 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
3521 #define ICE_FLOW_PROF_HDR_S 32
3522 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
3523 #define ICE_FLOW_PROF_ENCAP_S 62
3524 #define ICE_FLOW_PROF_ENCAP_M (0x3ULL << ICE_FLOW_PROF_ENCAP_S)
3526 /* Flow profile ID format:
3527 * [0:31] - Packet match fields
3528 * [32:61] - Protocol header
3529 * [62:63] - Encapsulation flag:
3532 * 2 for tunneled with outer ipv4
3533 * 3 for tunneled with outer ipv6
3535 #define ICE_FLOW_GEN_PROFID(hash, hdr, encap) \
3536 ((u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
3537 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
3538 (((u64)(encap) << ICE_FLOW_PROF_ENCAP_S) & ICE_FLOW_PROF_ENCAP_M)))
3541 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
3543 u32 s = ((src % 4) << 3); /* byte shift */
3544 u32 v = dst | 0x80; /* value to program */
3545 u8 i = src / 4; /* register index */
3548 reg = rd32(hw, GLQF_HSYMM(prof_id, i));
3549 reg = (reg & ~(0xff << s)) | (v << s);
3550 wr32(hw, GLQF_HSYMM(prof_id, i), reg);
3554 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
3557 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
3560 for (i = 0; i < len; i++) {
3561 ice_rss_config_xor_word(hw, prof_id,
3562 /* Yes, field vector in GLQF_HSYMM and
3563 * GLQF_HINSET is inversed!
3565 fv_last_word - (src + i),
3566 fv_last_word - (dst + i));
3567 ice_rss_config_xor_word(hw, prof_id,
3568 fv_last_word - (dst + i),
3569 fv_last_word - (src + i));
3574 ice_rss_update_symm(struct ice_hw *hw,
3575 struct ice_flow_prof *prof)
3577 struct ice_prof_map *map;
3580 ice_acquire_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3581 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
3583 prof_id = map->prof_id;
3584 ice_release_lock(&hw->blk[ICE_BLK_RSS].es.prof_map_lock);
3587 /* clear to default */
3588 for (m = 0; m < 6; m++)
3589 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
3590 if (prof->cfg.symm) {
3591 struct ice_flow_seg_info *seg =
3592 &prof->segs[prof->segs_cnt - 1];
3594 struct ice_flow_seg_xtrct *ipv4_src =
3595 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
3596 struct ice_flow_seg_xtrct *ipv4_dst =
3597 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
3598 struct ice_flow_seg_xtrct *ipv6_src =
3599 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
3600 struct ice_flow_seg_xtrct *ipv6_dst =
3601 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
3603 struct ice_flow_seg_xtrct *tcp_src =
3604 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
3605 struct ice_flow_seg_xtrct *tcp_dst =
3606 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
3608 struct ice_flow_seg_xtrct *udp_src =
3609 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
3610 struct ice_flow_seg_xtrct *udp_dst =
3611 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
3613 struct ice_flow_seg_xtrct *sctp_src =
3614 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
3615 struct ice_flow_seg_xtrct *sctp_dst =
3616 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
3619 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
3620 ice_rss_config_xor(hw, prof_id,
3621 ipv4_src->idx, ipv4_dst->idx, 2);
3624 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
3625 ice_rss_config_xor(hw, prof_id,
3626 ipv6_src->idx, ipv6_dst->idx, 8);
3629 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
3630 ice_rss_config_xor(hw, prof_id,
3631 tcp_src->idx, tcp_dst->idx, 1);
3634 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
3635 ice_rss_config_xor(hw, prof_id,
3636 udp_src->idx, udp_dst->idx, 1);
3639 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
3640 ice_rss_config_xor(hw, prof_id,
3641 sctp_src->idx, sctp_dst->idx, 1);
3646 * ice_add_rss_cfg_sync - add an RSS configuration
3647 * @hw: pointer to the hardware structure
3648 * @vsi_handle: software VSI handle
3649 * @cfg: configure parameters
3651 * Assumption: lock has already been acquired for RSS list
3653 static enum ice_status
3654 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
3655 const struct ice_rss_hash_cfg *cfg)
3657 const enum ice_block blk = ICE_BLK_RSS;
3658 struct ice_flow_prof *prof = NULL;
3659 struct ice_flow_seg_info *segs;
3660 enum ice_status status;
3663 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
3664 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
3666 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3669 return ICE_ERR_NO_MEMORY;
3671 /* Construct the packet segment info from the hashed fields */
3672 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
3676 /* Don't do RSS for GTPU Outer */
3677 if (segs_cnt == ICE_FLOW_SEG_SINGLE &&
3678 segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3679 status = ICE_SUCCESS;
3683 /* Search for a flow profile that has matching headers, hash fields
3684 * and has the input VSI associated to it. If found, no further
3685 * operations required and exit.
3687 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3689 ICE_FLOW_FIND_PROF_CHK_FLDS |
3690 ICE_FLOW_FIND_PROF_CHK_VSI);
3692 if (prof->cfg.symm == cfg->symm)
3694 prof->cfg.symm = cfg->symm;
3698 /* Check if a flow profile exists with the same protocol headers and
3699 * associated with the input VSI. If so disassociate the VSI from
3700 * this profile. The VSI will be added to a new profile created with
3701 * the protocol header and new hash field configuration.
3703 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3704 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
3706 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3708 ice_rem_rss_list(hw, vsi_handle, prof);
3712 /* Remove profile if it has no VSIs associated */
3713 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
3714 status = ice_flow_rem_prof(hw, blk, prof->id);
3720 /* Search for a profile that has same match fields only. If this
3721 * exists then associate the VSI to this profile.
3723 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3725 ICE_FLOW_FIND_PROF_CHK_FLDS);
3727 if (prof->cfg.symm == cfg->symm) {
3728 status = ice_flow_assoc_prof(hw, blk, prof,
3731 status = ice_add_rss_list(hw, vsi_handle,
3734 /* if a profile exist but with different symmetric
3735 * requirement, just return error.
3737 status = ICE_ERR_NOT_SUPPORTED;
3742 /* Create a new flow profile with generated profile and packet
3743 * segment information.
3745 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
3746 ICE_FLOW_GEN_PROFID(cfg->hash_flds,
3747 segs[segs_cnt - 1].hdrs,
3749 segs, segs_cnt, NULL, 0, &prof);
3753 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
3754 /* If association to a new flow profile failed then this profile can
3758 ice_flow_rem_prof(hw, blk, prof->id);
3762 status = ice_add_rss_list(hw, vsi_handle, prof);
3764 prof->cfg.symm = cfg->symm;
3766 ice_rss_update_symm(hw, prof);
3774 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
3775 * @hw: pointer to the hardware structure
3776 * @vsi_handle: software VSI handle
3777 * @cfg: configure parameters
3779 * This function will generate a flow profile based on fields associated with
3780 * the input fields to hash on, the flow type and use the VSI number to add
3781 * a flow entry to the profile.
3784 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
3785 const struct ice_rss_hash_cfg *cfg)
3787 struct ice_rss_hash_cfg local_cfg;
3788 enum ice_status status;
3790 if (!ice_is_vsi_valid(hw, vsi_handle) ||
3791 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
3792 cfg->hash_flds == ICE_HASH_INVALID)
3793 return ICE_ERR_PARAM;
3796 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
3797 ice_acquire_lock(&hw->rss_locks);
3798 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3799 ice_release_lock(&hw->rss_locks);
3801 ice_acquire_lock(&hw->rss_locks);
3802 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
3803 status = ice_add_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3805 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
3806 status = ice_add_rss_cfg_sync(hw, vsi_handle,
3809 ice_release_lock(&hw->rss_locks);
3816 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
3817 * @hw: pointer to the hardware structure
3818 * @vsi_handle: software VSI handle
3819 * @cfg: configure parameters
3821 * Assumption: lock has already been acquired for RSS list
3823 static enum ice_status
3824 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle,
3825 const struct ice_rss_hash_cfg *cfg)
3827 const enum ice_block blk = ICE_BLK_RSS;
3828 struct ice_flow_seg_info *segs;
3829 struct ice_flow_prof *prof;
3830 enum ice_status status;
3833 segs_cnt = (cfg->hdr_type == ICE_RSS_OUTER_HEADERS) ?
3834 ICE_FLOW_SEG_SINGLE : ICE_FLOW_SEG_MAX;
3835 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
3838 return ICE_ERR_NO_MEMORY;
3840 /* Construct the packet segment info from the hashed fields */
3841 status = ice_flow_set_rss_seg_info(segs, segs_cnt, cfg);
3845 /* Don't do RSS for GTPU Outer */
3846 if (segs_cnt == ICE_FLOW_SEG_SINGLE &&
3847 segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
3848 status = ICE_SUCCESS;
3852 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
3854 ICE_FLOW_FIND_PROF_CHK_FLDS);
3856 status = ICE_ERR_DOES_NOT_EXIST;
3860 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
3864 /* Remove RSS configuration from VSI context before deleting
3867 ice_rem_rss_list(hw, vsi_handle, prof);
3869 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
3870 status = ice_flow_rem_prof(hw, blk, prof->id);
3878 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
3879 * @hw: pointer to the hardware structure
3880 * @vsi_handle: software VSI handle
3881 * @cfg: configure parameters
3883 * This function will lookup the flow profile based on the input
3884 * hash field bitmap, iterate through the profile entry list of
3885 * that profile and find entry associated with input VSI to be
3886 * removed. Calls are made to underlying flow apis which will in
3887 * turn build or update buffers for RSS XLT1 section.
3890 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle,
3891 const struct ice_rss_hash_cfg *cfg)
3893 struct ice_rss_hash_cfg local_cfg;
3894 enum ice_status status;
3896 if (!ice_is_vsi_valid(hw, vsi_handle) ||
3897 !cfg || cfg->hdr_type > ICE_RSS_ANY_HEADERS ||
3898 cfg->hash_flds == ICE_HASH_INVALID)
3899 return ICE_ERR_PARAM;
3901 ice_acquire_lock(&hw->rss_locks);
3903 if (cfg->hdr_type < ICE_RSS_ANY_HEADERS) {
3904 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3906 local_cfg.hdr_type = ICE_RSS_OUTER_HEADERS;
3907 status = ice_rem_rss_cfg_sync(hw, vsi_handle, &local_cfg);
3910 local_cfg.hdr_type = ICE_RSS_INNER_HEADERS;
3911 status = ice_rem_rss_cfg_sync(hw, vsi_handle,
3915 ice_release_lock(&hw->rss_locks);
3921 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
3922 * @hw: pointer to the hardware structure
3923 * @vsi_handle: software VSI handle
3925 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
3927 enum ice_status status = ICE_SUCCESS;
3928 struct ice_rss_cfg *r;
3930 if (!ice_is_vsi_valid(hw, vsi_handle))
3931 return ICE_ERR_PARAM;
3933 ice_acquire_lock(&hw->rss_locks);
3934 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3935 ice_rss_cfg, l_entry) {
3936 if (ice_is_bit_set(r->vsis, vsi_handle)) {
3937 status = ice_add_rss_cfg_sync(hw, vsi_handle, &r->hash);
3942 ice_release_lock(&hw->rss_locks);
3948 * ice_get_rss_cfg - returns hashed fields for the given header types
3949 * @hw: pointer to the hardware structure
3950 * @vsi_handle: software VSI handle
3951 * @hdrs: protocol header type
3953 * This function will return the match fields of the first instance of flow
3954 * profile having the given header types and containing input VSI
3956 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
3958 u64 rss_hash = ICE_HASH_INVALID;
3959 struct ice_rss_cfg *r;
3961 /* verify if the protocol header is non zero and VSI is valid */
3962 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
3963 return ICE_HASH_INVALID;
3965 ice_acquire_lock(&hw->rss_locks);
3966 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
3967 ice_rss_cfg, l_entry)
3968 if (ice_is_bit_set(r->vsis, vsi_handle) &&
3969 r->hash.addl_hdrs == hdrs) {
3970 rss_hash = r->hash.hash_flds;
3973 ice_release_lock(&hw->rss_locks);