1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2001-2019
5 #include "ice_common.h"
8 /* Size of known protocol header fields */
9 #define ICE_FLOW_FLD_SZ_ETH_TYPE 2
10 #define ICE_FLOW_FLD_SZ_VLAN 2
11 #define ICE_FLOW_FLD_SZ_IPV4_ADDR 4
12 #define ICE_FLOW_FLD_SZ_IPV6_ADDR 16
13 #define ICE_FLOW_FLD_SZ_IP_DSCP 1
14 #define ICE_FLOW_FLD_SZ_IP_TTL 1
15 #define ICE_FLOW_FLD_SZ_IP_PROT 1
16 #define ICE_FLOW_FLD_SZ_PORT 2
17 #define ICE_FLOW_FLD_SZ_TCP_FLAGS 1
18 #define ICE_FLOW_FLD_SZ_ICMP_TYPE 1
19 #define ICE_FLOW_FLD_SZ_ICMP_CODE 1
20 #define ICE_FLOW_FLD_SZ_ARP_OPER 2
21 #define ICE_FLOW_FLD_SZ_GRE_KEYID 4
22 #define ICE_FLOW_FLD_SZ_GTP_TEID 4
23 #define ICE_FLOW_FLD_SZ_GTP_QFI 2
24 #define ICE_FLOW_FLD_SZ_PPPOE_SESS_ID 2
26 /* Describe properties of a protocol header field */
27 struct ice_flow_field_info {
28 enum ice_flow_seg_hdr hdr;
29 s16 off; /* Offset from start of a protocol header, in bits */
30 u16 size; /* Size of fields in bits */
31 u16 mask; /* 16-bit mask for field */
34 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
36 .off = (_offset_bytes) * BITS_PER_BYTE, \
37 .size = (_size_bytes) * BITS_PER_BYTE, \
41 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
43 .off = (_offset_bytes) * BITS_PER_BYTE, \
44 .size = (_size_bytes) * BITS_PER_BYTE, \
48 /* Table containing properties of supported protocol header fields */
50 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
52 /* ICE_FLOW_FIELD_IDX_ETH_DA */
53 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
54 /* ICE_FLOW_FIELD_IDX_ETH_SA */
55 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
56 /* ICE_FLOW_FIELD_IDX_S_VLAN */
57 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
58 /* ICE_FLOW_FIELD_IDX_C_VLAN */
59 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
60 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
61 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
63 /* ICE_FLOW_FIELD_IDX_IPV4_DSCP */
64 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV4, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
66 /* ICE_FLOW_FIELD_IDX_IPV6_DSCP */
67 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_IPV6, 0, ICE_FLOW_FLD_SZ_IP_DSCP,
69 /* ICE_FLOW_FIELD_IDX_IPV4_TTL */
70 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
71 ICE_FLOW_FLD_SZ_IP_TTL, 0xff00),
72 /* ICE_FLOW_FIELD_IDX_IPV4_PROT */
73 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 8,
74 ICE_FLOW_FLD_SZ_IP_PROT, 0x00ff),
75 /* ICE_FLOW_FIELD_IDX_IPV6_TTL */
76 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
77 ICE_FLOW_FLD_SZ_IP_TTL, 0x00ff),
78 /* ICE_FLOW_FIELD_IDX_IPV6_PROT */
79 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_NONE, 6,
80 ICE_FLOW_FLD_SZ_IP_PROT, 0xff00),
81 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
82 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
83 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
84 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
85 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
86 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
87 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
88 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
90 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
91 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
92 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
93 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
94 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
95 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
96 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
97 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
98 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
99 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
100 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
101 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
102 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
105 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
106 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
107 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
108 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
109 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
110 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
111 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
112 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
113 /* ICE_FLOW_FIELD_IDX_ARP_OP */
114 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
116 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
117 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
118 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
121 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
122 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
124 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
126 ICE_FLOW_FLD_SZ_GTP_TEID),
127 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
128 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
129 ICE_FLOW_FLD_SZ_GTP_TEID),
130 /* ICE_FLOW_FIELD_IDX_GTPU_EH_TEID */
131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_EH, 12,
132 ICE_FLOW_FLD_SZ_GTP_TEID),
133 /* ICE_FLOW_FIELD_IDX_GTPU_EH_QFI */
134 ICE_FLOW_FLD_INFO_MSK(ICE_FLOW_SEG_HDR_GTPU_EH, 22,
135 ICE_FLOW_FLD_SZ_GTP_QFI, 0x3f00),
136 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
137 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
138 ICE_FLOW_FLD_SZ_GTP_TEID),
139 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
140 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
141 ICE_FLOW_FLD_SZ_GTP_TEID),
143 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
144 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
145 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
148 /* Bitmaps indicating relevant packet types for a particular protocol header
150 * Packet types for packets with an Outer/First/Single MAC header
152 static const u32 ice_ptypes_mac_ofos[] = {
153 0xFDC00846, 0xBFBF7F7E, 0xF70001DF, 0xFEFDFDFB,
154 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
155 0x00000000, 0x03FFF000, 0x7FFFFFE0, 0x00000000,
156 0x00000000, 0x00000000, 0x00000000, 0x00000000,
157 0x00000000, 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000, 0x00000000,
163 /* Packet types for packets with an Innermost/Last MAC VLAN header */
164 static const u32 ice_ptypes_macvlan_il[] = {
165 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
166 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
167 0x00000000, 0x00000000, 0x00000000, 0x00000000,
168 0x00000000, 0x00000000, 0x00000000, 0x00000000,
169 0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 0x00000000, 0x00000000, 0x00000000, 0x00000000,
171 0x00000000, 0x00000000, 0x00000000, 0x00000000,
172 0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 /* Packet types for packets with an Outer/First/Single IPv4 header */
176 static const u32 ice_ptypes_ipv4_ofos[] = {
177 0x1DC00000, 0x04000800, 0x00000000, 0x00000000,
178 0x00000000, 0x00000000, 0x00000000, 0x00000000,
179 0x0003000F, 0x000FC000, 0x03E0F800, 0x00000000,
180 0x00000000, 0x00000000, 0x00000000, 0x00000000,
181 0x00000000, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x00000000, 0x00000000,
187 /* Packet types for packets with an Innermost/Last IPv4 header */
188 static const u32 ice_ptypes_ipv4_il[] = {
189 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B,
190 0x0000000E, 0x00000000, 0x00000000, 0x00000000,
191 0x00000000, 0x00000000, 0x001FF800, 0x00000000,
192 0x00000000, 0x00000000, 0x00000000, 0x00000000,
193 0x00000000, 0x00000000, 0x00000000, 0x00000000,
194 0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x00000000, 0x00000000, 0x00000000,
199 /* Packet types for packets with an Outer/First/Single IPv6 header */
200 static const u32 ice_ptypes_ipv6_ofos[] = {
201 0x00000000, 0x00000000, 0x77000000, 0x10002000,
202 0x00000000, 0x00000000, 0x00000000, 0x00000000,
203 0x00080F00, 0x03F00000, 0x7C1F0000, 0x00000000,
204 0x00000000, 0x00000000, 0x00000000, 0x00000000,
205 0x00000000, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x00000000, 0x00000000,
207 0x00000000, 0x00000000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 /* Packet types for packets with an Innermost/Last IPv6 header */
212 static const u32 ice_ptypes_ipv6_il[] = {
213 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000,
214 0x00000770, 0x00000000, 0x00000000, 0x00000000,
215 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
216 0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
220 0x00000000, 0x00000000, 0x00000000, 0x00000000,
223 /* Packet types for packets with an Outermost/First ARP header */
224 static const u32 ice_ptypes_arp_of[] = {
225 0x00000800, 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,
232 0x00000000, 0x00000000, 0x00000000, 0x00000000,
235 /* UDP Packet types for non-tunneled packets or tunneled
236 * packets with inner UDP.
238 static const u32 ice_ptypes_udp_il[] = {
239 0x81000000, 0x20204040, 0x04000010, 0x80810102,
240 0x00000040, 0x00000000, 0x00000000, 0x00000000,
241 0x00000000, 0x00410000, 0x10842000, 0x00000000,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00000000, 0x00000000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 /* Packet types for packets with an Innermost/Last TCP header */
250 static const u32 ice_ptypes_tcp_il[] = {
251 0x04000000, 0x80810102, 0x10000040, 0x02040408,
252 0x00000102, 0x00000000, 0x00000000, 0x00000000,
253 0x00000000, 0x00820000, 0x21084000, 0x00000000,
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 /* Packet types for packets with an Innermost/Last SCTP header */
262 static const u32 ice_ptypes_sctp_il[] = {
263 0x08000000, 0x01020204, 0x20000081, 0x04080810,
264 0x00000204, 0x00000000, 0x00000000, 0x00000000,
265 0x00000000, 0x01040000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
273 /* Packet types for packets with an Outermost/First ICMP header */
274 static const u32 ice_ptypes_icmp_of[] = {
275 0x10000000, 0x00000000, 0x00000000, 0x00000000,
276 0x00000000, 0x00000000, 0x00000000, 0x00000000,
277 0x00000000, 0x00000000, 0x00000000, 0x00000000,
278 0x00000000, 0x00000000, 0x00000000, 0x00000000,
279 0x00000000, 0x00000000, 0x00000000, 0x00000000,
280 0x00000000, 0x00000000, 0x00000000, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 /* Packet types for packets with an Innermost/Last ICMP header */
286 static const u32 ice_ptypes_icmp_il[] = {
287 0x00000000, 0x02040408, 0x40000102, 0x08101020,
288 0x00000408, 0x00000000, 0x00000000, 0x00000000,
289 0x00000000, 0x00000000, 0x42108000, 0x00000000,
290 0x00000000, 0x00000000, 0x00000000, 0x00000000,
291 0x00000000, 0x00000000, 0x00000000, 0x00000000,
292 0x00000000, 0x00000000, 0x00000000, 0x00000000,
293 0x00000000, 0x00000000, 0x00000000, 0x00000000,
294 0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 /* Packet types for packets with an Outermost/First GRE header */
298 static const u32 ice_ptypes_gre_of[] = {
299 0x00000000, 0xBFBF7800, 0x000001DF, 0xFEFDE000,
300 0x0000017E, 0x00000000, 0x00000000, 0x00000000,
301 0x00000000, 0x00000000, 0x00000000, 0x00000000,
302 0x00000000, 0x00000000, 0x00000000, 0x00000000,
303 0x00000000, 0x00000000, 0x00000000, 0x00000000,
304 0x00000000, 0x00000000, 0x00000000, 0x00000000,
305 0x00000000, 0x00000000, 0x00000000, 0x00000000,
306 0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 /* Packet types for packets with an Innermost/Last MAC header */
310 static const u32 ice_ptypes_mac_il[] = {
311 0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 0x00000000, 0x00000000, 0x00000000, 0x00000000,
313 0x00000000, 0x00000000, 0x00000000, 0x00000000,
314 0x00000000, 0x00000000, 0x00000000, 0x00000000,
315 0x00000000, 0x00000000, 0x00000000, 0x00000000,
316 0x00000000, 0x00000000, 0x00000000, 0x00000000,
317 0x00000000, 0x00000000, 0x00000000, 0x00000000,
318 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 /* Packet types for GTPC */
322 static const u32 ice_ptypes_gtpc[] = {
323 0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 0x00000000, 0x00000000, 0x00000000, 0x00000000,
325 0x00000000, 0x00000000, 0x00000180, 0x00000000,
326 0x00000000, 0x00000000, 0x00000000, 0x00000000,
327 0x00000000, 0x00000000, 0x00000000, 0x00000000,
328 0x00000000, 0x00000000, 0x00000000, 0x00000000,
329 0x00000000, 0x00000000, 0x00000000, 0x00000000,
330 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 /* Packet types for GTPC with TEID */
334 static const u32 ice_ptypes_gtpc_tid[] = {
335 0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 0x00000000, 0x00000000, 0x00000000, 0x00000000,
337 0x00000000, 0x00000000, 0x00000060, 0x00000000,
338 0x00000000, 0x00000000, 0x00000000, 0x00000000,
339 0x00000000, 0x00000000, 0x00000000, 0x00000000,
340 0x00000000, 0x00000000, 0x00000000, 0x00000000,
341 0x00000000, 0x00000000, 0x00000000, 0x00000000,
342 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 /* Packet types for GTPU */
346 static const struct ice_ptype_attributes ice_attr_gtpu_eh[] = {
347 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
348 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
349 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
350 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
351 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
352 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
353 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
354 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
355 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
356 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_PDU_EH },
357 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
358 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
359 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
360 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
361 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
362 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_PDU_EH },
363 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
364 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_PDU_EH },
365 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_PDU_EH },
366 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_PDU_EH },
369 static const struct ice_ptype_attributes ice_attr_gtpu_down[] = {
370 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
371 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
372 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
373 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
374 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
375 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
376 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
377 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
378 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
379 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
380 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
381 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
382 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
383 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
384 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
385 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_DOWNLINK },
386 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
387 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_DOWNLINK },
388 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_DOWNLINK },
389 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_DOWNLINK },
392 static const struct ice_ptype_attributes ice_attr_gtpu_up[] = {
393 { ICE_MAC_IPV4_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
394 { ICE_MAC_IPV4_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
395 { ICE_MAC_IPV4_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
396 { ICE_MAC_IPV4_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
397 { ICE_MAC_IPV4_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
398 { ICE_MAC_IPV6_GTPU_IPV4_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
399 { ICE_MAC_IPV6_GTPU_IPV4_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
400 { ICE_MAC_IPV6_GTPU_IPV4_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
401 { ICE_MAC_IPV6_GTPU_IPV4_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
402 { ICE_MAC_IPV6_GTPU_IPV4_ICMP, ICE_PTYPE_ATTR_GTP_UPLINK },
403 { ICE_MAC_IPV4_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
404 { ICE_MAC_IPV4_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
405 { ICE_MAC_IPV4_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
406 { ICE_MAC_IPV4_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
407 { ICE_MAC_IPV4_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
408 { ICE_MAC_IPV6_GTPU_IPV6_FRAG, ICE_PTYPE_ATTR_GTP_UPLINK },
409 { ICE_MAC_IPV6_GTPU_IPV6_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
410 { ICE_MAC_IPV6_GTPU_IPV6_UDP_PAY, ICE_PTYPE_ATTR_GTP_UPLINK },
411 { ICE_MAC_IPV6_GTPU_IPV6_TCP, ICE_PTYPE_ATTR_GTP_UPLINK },
412 { ICE_MAC_IPV6_GTPU_IPV6_ICMPV6, ICE_PTYPE_ATTR_GTP_UPLINK },
415 static const u32 ice_ptypes_gtpu[] = {
416 0x00000000, 0x00000000, 0x00000000, 0x00000000,
417 0x00000000, 0x00000000, 0x00000000, 0x00000000,
418 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
419 0x00000000, 0x00000000, 0x00000000, 0x00000000,
420 0x00000000, 0x00000000, 0x00000000, 0x00000000,
421 0x00000000, 0x00000000, 0x00000000, 0x00000000,
422 0x00000000, 0x00000000, 0x00000000, 0x00000000,
423 0x00000000, 0x00000000, 0x00000000, 0x00000000,
426 /* Packet types for pppoe */
427 static const u32 ice_ptypes_pppoe[] = {
428 0x00000000, 0x00000000, 0x00000000, 0x00000000,
429 0x00000000, 0x00000000, 0x00000000, 0x00000000,
430 0x00000000, 0x03FFF000, 0x00000000, 0x00000000,
431 0x00000000, 0x00000000, 0x00000000, 0x00000000,
432 0x00000000, 0x00000000, 0x00000000, 0x00000000,
433 0x00000000, 0x00000000, 0x00000000, 0x00000000,
434 0x00000000, 0x00000000, 0x00000000, 0x00000000,
435 0x00000000, 0x00000000, 0x00000000, 0x00000000,
438 /* Manage parameters and info. used during the creation of a flow profile */
439 struct ice_flow_prof_params {
441 u16 entry_length; /* # of bytes formatted entry will require */
443 struct ice_flow_prof *prof;
445 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
446 * This will give us the direction flags.
448 struct ice_fv_word es[ICE_MAX_FV_WORDS];
449 /* attributes can be used to add attributes to a particular PTYPE */
450 const struct ice_ptype_attributes *attr;
453 u16 mask[ICE_MAX_FV_WORDS];
454 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
457 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
458 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
459 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU)
461 #define ICE_FLOW_SEG_HDRS_L2_MASK \
462 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
463 #define ICE_FLOW_SEG_HDRS_L3_MASK \
464 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
465 ICE_FLOW_SEG_HDR_ARP)
466 #define ICE_FLOW_SEG_HDRS_L4_MASK \
467 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
468 ICE_FLOW_SEG_HDR_SCTP)
471 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
472 * @segs: array of one or more packet segments that describe the flow
473 * @segs_cnt: number of packet segments provided
475 static enum ice_status
476 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
480 for (i = 0; i < segs_cnt; i++) {
481 /* Multiple L3 headers */
482 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
483 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
484 return ICE_ERR_PARAM;
486 /* Multiple L4 headers */
487 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
488 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
489 return ICE_ERR_PARAM;
495 /* Sizes of fixed known protocol headers without header options */
496 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
497 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
498 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
499 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
500 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
501 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
502 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
503 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
504 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
507 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
508 * @params: information about the flow to be processed
509 * @seg: index of packet segment whose header size is to be determined
511 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
516 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
517 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
520 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
521 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
522 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
523 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
524 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
525 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
526 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
527 /* A L3 header is required if L4 is specified */
531 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
532 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
533 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
534 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
535 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
536 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
537 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
538 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
544 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
545 * @params: information about the flow to be processed
547 * This function identifies the packet types associated with the protocol
548 * headers being present in packet segments of the specified flow profile.
550 static enum ice_status
551 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
553 struct ice_flow_prof *prof;
556 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
561 for (i = 0; i < params->prof->segs_cnt; i++) {
562 const ice_bitmap_t *src;
565 hdrs = prof->segs[i].hdrs;
567 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
568 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
569 (const ice_bitmap_t *)ice_ptypes_mac_il;
570 ice_and_bitmap(params->ptypes, params->ptypes, src,
574 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
575 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
576 ice_and_bitmap(params->ptypes, params->ptypes, src,
580 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
581 ice_and_bitmap(params->ptypes, params->ptypes,
582 (const ice_bitmap_t *)ice_ptypes_arp_of,
586 if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
587 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
588 ice_and_bitmap(params->ptypes, params->ptypes, src,
592 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
593 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
594 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
595 ice_and_bitmap(params->ptypes, params->ptypes, src,
597 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
598 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
599 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
600 ice_and_bitmap(params->ptypes, params->ptypes, src,
604 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
605 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
606 (const ice_bitmap_t *)ice_ptypes_icmp_il;
607 ice_and_bitmap(params->ptypes, params->ptypes, src,
609 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
610 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
611 ice_and_bitmap(params->ptypes, params->ptypes, src,
613 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
614 ice_and_bitmap(params->ptypes, params->ptypes,
615 (const ice_bitmap_t *)ice_ptypes_tcp_il,
617 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
618 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
619 ice_and_bitmap(params->ptypes, params->ptypes, src,
621 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
623 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
624 ice_and_bitmap(params->ptypes, params->ptypes,
625 src, ICE_FLOW_PTYPE_MAX);
627 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
628 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
629 ice_and_bitmap(params->ptypes, params->ptypes,
630 src, ICE_FLOW_PTYPE_MAX);
631 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
632 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
633 ice_and_bitmap(params->ptypes, params->ptypes,
634 src, ICE_FLOW_PTYPE_MAX);
635 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_DWN) {
636 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
637 ice_and_bitmap(params->ptypes, params->ptypes,
638 src, ICE_FLOW_PTYPE_MAX);
640 /* Attributes for GTP packet with downlink */
641 params->attr = ice_attr_gtpu_down;
642 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_down);
643 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_UP) {
644 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
645 ice_and_bitmap(params->ptypes, params->ptypes,
646 src, ICE_FLOW_PTYPE_MAX);
648 /* Attributes for GTP packet with uplink */
649 params->attr = ice_attr_gtpu_up;
650 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_up);
651 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
652 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
653 ice_and_bitmap(params->ptypes, params->ptypes,
654 src, ICE_FLOW_PTYPE_MAX);
656 /* Attributes for GTP packet with Extension Header */
657 params->attr = ice_attr_gtpu_eh;
658 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
659 } else if ((hdrs & ICE_FLOW_SEG_HDR_GTPU) ==
660 ICE_FLOW_SEG_HDR_GTPU) {
661 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
662 ice_and_bitmap(params->ptypes, params->ptypes,
663 src, ICE_FLOW_PTYPE_MAX);
671 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
672 * @hw: pointer to the HW struct
673 * @params: information about the flow to be processed
674 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
676 * This function will allocate an extraction sequence entries for a DWORD size
677 * chunk of the packet flags.
679 static enum ice_status
680 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
681 struct ice_flow_prof_params *params,
682 enum ice_flex_mdid_pkt_flags flags)
684 u8 fv_words = hw->blk[params->blk].es.fvw;
687 /* Make sure the number of extraction sequence entries required does not
688 * exceed the block's capacity.
690 if (params->es_cnt >= fv_words)
691 return ICE_ERR_MAX_LIMIT;
693 /* some blocks require a reversed field vector layout */
694 if (hw->blk[params->blk].es.reverse)
695 idx = fv_words - params->es_cnt - 1;
697 idx = params->es_cnt;
699 params->es[idx].prot_id = ICE_PROT_META_ID;
700 params->es[idx].off = flags;
707 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
708 * @hw: pointer to the HW struct
709 * @params: information about the flow to be processed
710 * @seg: packet segment index of the field to be extracted
711 * @fld: ID of field to be extracted
712 * @match: bitfield of all fields
714 * This function determines the protocol ID, offset, and size of the given
715 * field. It then allocates one or more extraction sequence entries for the
716 * given field, and fill the entries with protocol ID and offset information.
718 static enum ice_status
719 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
720 u8 seg, enum ice_flow_field fld, u64 match)
722 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
723 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
724 u8 fv_words = hw->blk[params->blk].es.fvw;
725 struct ice_flow_fld_info *flds;
726 u16 cnt, ese_bits, i;
732 flds = params->prof->segs[seg].fields;
735 case ICE_FLOW_FIELD_IDX_ETH_DA:
736 case ICE_FLOW_FIELD_IDX_ETH_SA:
737 case ICE_FLOW_FIELD_IDX_S_VLAN:
738 case ICE_FLOW_FIELD_IDX_C_VLAN:
739 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
741 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
742 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
744 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
745 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
747 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
748 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
750 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
751 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
752 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
754 /* TTL and PROT share the same extraction seq. entry.
755 * Each is considered a sibling to the other in terms of sharing
756 * the same extraction sequence entry.
758 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
759 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
760 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
761 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
763 /* If the sibling field is also included, that field's
764 * mask needs to be included.
766 if (match & BIT(sib))
767 sib_mask = ice_flds_info[sib].mask;
769 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
770 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
771 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
773 /* TTL and PROT share the same extraction seq. entry.
774 * Each is considered a sibling to the other in terms of sharing
775 * the same extraction sequence entry.
777 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
778 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
779 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
780 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
782 /* If the sibling field is also included, that field's
783 * mask needs to be included.
785 if (match & BIT(sib))
786 sib_mask = ice_flds_info[sib].mask;
788 case ICE_FLOW_FIELD_IDX_IPV4_SA:
789 case ICE_FLOW_FIELD_IDX_IPV4_DA:
790 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
792 case ICE_FLOW_FIELD_IDX_IPV6_SA:
793 case ICE_FLOW_FIELD_IDX_IPV6_DA:
794 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
796 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
797 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
798 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
799 prot_id = ICE_PROT_TCP_IL;
801 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
802 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
803 prot_id = ICE_PROT_UDP_IL_OR_S;
805 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
806 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
807 prot_id = ICE_PROT_SCTP_IL;
809 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
810 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
811 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
812 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
813 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
814 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
815 /* GTP is accessed through UDP OF protocol */
816 prot_id = ICE_PROT_UDP_OF;
818 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
819 prot_id = ICE_PROT_PPPOE;
821 case ICE_FLOW_FIELD_IDX_ARP_SIP:
822 case ICE_FLOW_FIELD_IDX_ARP_DIP:
823 case ICE_FLOW_FIELD_IDX_ARP_SHA:
824 case ICE_FLOW_FIELD_IDX_ARP_DHA:
825 case ICE_FLOW_FIELD_IDX_ARP_OP:
826 prot_id = ICE_PROT_ARP_OF;
828 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
829 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
830 /* ICMP type and code share the same extraction seq. entry */
831 prot_id = (params->prof->segs[seg].hdrs &
832 ICE_FLOW_SEG_HDR_IPV4) ?
833 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
834 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
835 ICE_FLOW_FIELD_IDX_ICMP_CODE :
836 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
838 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
839 prot_id = ICE_PROT_GRE_OF;
842 return ICE_ERR_NOT_IMPL;
845 /* Each extraction sequence entry is a word in size, and extracts a
846 * word-aligned offset from a protocol header.
848 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
850 flds[fld].xtrct.prot_id = prot_id;
851 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
852 ICE_FLOW_FV_EXTRACT_SZ;
853 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
854 flds[fld].xtrct.idx = params->es_cnt;
855 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
857 /* Adjust the next field-entry index after accommodating the number of
858 * entries this field consumes
860 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
861 ice_flds_info[fld].size, ese_bits);
863 /* Fill in the extraction sequence entries needed for this field */
864 off = flds[fld].xtrct.off;
865 mask = flds[fld].xtrct.mask;
866 for (i = 0; i < cnt; i++) {
867 /* Only consume an extraction sequence entry if there is no
868 * sibling field associated with this field or the sibling entry
869 * already extracts the word shared with this field.
871 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
872 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
873 flds[sib].xtrct.off != off) {
876 /* Make sure the number of extraction sequence required
877 * does not exceed the block's capability
879 if (params->es_cnt >= fv_words)
880 return ICE_ERR_MAX_LIMIT;
882 /* some blocks require a reversed field vector layout */
883 if (hw->blk[params->blk].es.reverse)
884 idx = fv_words - params->es_cnt - 1;
886 idx = params->es_cnt;
888 params->es[idx].prot_id = prot_id;
889 params->es[idx].off = off;
890 params->mask[idx] = mask | sib_mask;
894 off += ICE_FLOW_FV_EXTRACT_SZ;
901 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
902 * @hw: pointer to the HW struct
903 * @params: information about the flow to be processed
904 * @seg: index of packet segment whose raw fields are to be be extracted
906 static enum ice_status
907 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
914 if (!params->prof->segs[seg].raws_cnt)
917 if (params->prof->segs[seg].raws_cnt >
918 ARRAY_SIZE(params->prof->segs[seg].raws))
919 return ICE_ERR_MAX_LIMIT;
921 /* Offsets within the segment headers are not supported */
922 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
924 return ICE_ERR_PARAM;
926 fv_words = hw->blk[params->blk].es.fvw;
928 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
929 struct ice_flow_seg_fld_raw *raw;
932 raw = ¶ms->prof->segs[seg].raws[i];
934 /* Storing extraction information */
935 raw->info.xtrct.prot_id = ICE_PROT_MAC_OF_OR_S;
936 raw->info.xtrct.off = (raw->off / ICE_FLOW_FV_EXTRACT_SZ) *
937 ICE_FLOW_FV_EXTRACT_SZ;
938 raw->info.xtrct.disp = (raw->off % ICE_FLOW_FV_EXTRACT_SZ) *
940 raw->info.xtrct.idx = params->es_cnt;
942 /* Determine the number of field vector entries this raw field
945 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
946 (raw->info.src.last * BITS_PER_BYTE),
947 (ICE_FLOW_FV_EXTRACT_SZ *
949 off = raw->info.xtrct.off;
950 for (j = 0; j < cnt; j++) {
953 /* Make sure the number of extraction sequence required
954 * does not exceed the block's capability
956 if (params->es_cnt >= hw->blk[params->blk].es.count ||
957 params->es_cnt >= ICE_MAX_FV_WORDS)
958 return ICE_ERR_MAX_LIMIT;
960 /* some blocks require a reversed field vector layout */
961 if (hw->blk[params->blk].es.reverse)
962 idx = fv_words - params->es_cnt - 1;
964 idx = params->es_cnt;
966 params->es[idx].prot_id = raw->info.xtrct.prot_id;
967 params->es[idx].off = off;
969 off += ICE_FLOW_FV_EXTRACT_SZ;
977 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
978 * @hw: pointer to the HW struct
979 * @params: information about the flow to be processed
981 * This function iterates through all matched fields in the given segments, and
982 * creates an extraction sequence for the fields.
984 static enum ice_status
985 ice_flow_create_xtrct_seq(struct ice_hw *hw,
986 struct ice_flow_prof_params *params)
988 enum ice_status status = ICE_SUCCESS;
991 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
994 if (params->blk == ICE_BLK_ACL) {
995 status = ice_flow_xtract_pkt_flags(hw, params,
996 ICE_RX_MDID_PKT_FLAGS_15_0);
1001 for (i = 0; i < params->prof->segs_cnt; i++) {
1002 u64 match = params->prof->segs[i].match;
1003 enum ice_flow_field j;
1005 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
1006 const u64 bit = BIT_ULL(j);
1009 status = ice_flow_xtract_fld(hw, params, i, j,
1017 /* Process raw matching bytes */
1018 status = ice_flow_xtract_raws(hw, params, i);
1027 * ice_flow_proc_segs - process all packet segments associated with a profile
1028 * @hw: pointer to the HW struct
1029 * @params: information about the flow to be processed
1031 static enum ice_status
1032 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
1034 enum ice_status status;
1036 status = ice_flow_proc_seg_hdrs(params);
1040 status = ice_flow_create_xtrct_seq(hw, params);
1044 switch (params->blk) {
1046 /* Only header information is provided for RSS configuration.
1047 * No further processing is needed.
1049 status = ICE_SUCCESS;
1052 status = ICE_SUCCESS;
1056 return ICE_ERR_NOT_IMPL;
1062 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1063 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
1064 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
1067 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1068 * @hw: pointer to the HW struct
1069 * @blk: classification stage
1070 * @dir: flow direction
1071 * @segs: array of one or more packet segments that describe the flow
1072 * @segs_cnt: number of packet segments provided
1073 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1074 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1076 static struct ice_flow_prof *
1077 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1078 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1079 u8 segs_cnt, u16 vsi_handle, u32 conds)
1081 struct ice_flow_prof *p, *prof = NULL;
1083 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1084 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1085 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1086 segs_cnt && segs_cnt == p->segs_cnt) {
1089 /* Check for profile-VSI association if specified */
1090 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1091 ice_is_vsi_valid(hw, vsi_handle) &&
1092 !ice_is_bit_set(p->vsis, vsi_handle))
1095 /* Protocol headers must be checked. Matched fields are
1096 * checked if specified.
1098 for (i = 0; i < segs_cnt; i++)
1099 if (segs[i].hdrs != p->segs[i].hdrs ||
1100 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1101 segs[i].match != p->segs[i].match))
1104 /* A match is found if all segments are matched */
1105 if (i == segs_cnt) {
1111 ice_release_lock(&hw->fl_profs_locks[blk]);
1117 * ice_flow_find_prof - Look up a profile matching headers and matched fields
1118 * @hw: pointer to the HW struct
1119 * @blk: classification stage
1120 * @dir: flow direction
1121 * @segs: array of one or more packet segments that describe the flow
1122 * @segs_cnt: number of packet segments provided
1125 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1126 struct ice_flow_seg_info *segs, u8 segs_cnt)
1128 struct ice_flow_prof *p;
1130 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1131 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1133 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1137 * ice_flow_find_prof_id - Look up a profile with given profile ID
1138 * @hw: pointer to the HW struct
1139 * @blk: classification stage
1140 * @prof_id: unique ID to identify this flow profile
1142 static struct ice_flow_prof *
1143 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1145 struct ice_flow_prof *p;
1147 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1148 if (p->id == prof_id)
1156 * ice_dealloc_flow_entry - Deallocate flow entry memory
1157 * @hw: pointer to the HW struct
1158 * @entry: flow entry to be removed
1161 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1167 ice_free(hw, entry->entry);
1170 ice_free(hw, entry->acts);
1172 entry->acts_cnt = 0;
1175 ice_free(hw, entry);
1179 * ice_flow_rem_entry_sync - Remove a flow entry
1180 * @hw: pointer to the HW struct
1181 * @entry: flow entry to be removed
1183 static enum ice_status
1184 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1187 return ICE_ERR_BAD_PTR;
1189 LIST_DEL(&entry->l_entry);
1191 ice_dealloc_flow_entry(hw, entry);
1197 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1198 * @hw: pointer to the HW struct
1199 * @blk: classification stage
1200 * @dir: flow direction
1201 * @prof_id: unique ID to identify this flow profile
1202 * @segs: array of one or more packet segments that describe the flow
1203 * @segs_cnt: number of packet segments provided
1204 * @acts: array of default actions
1205 * @acts_cnt: number of default actions
1206 * @prof: stores the returned flow profile added
1208 * Assumption: the caller has acquired the lock to the profile list
1210 static enum ice_status
1211 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1212 enum ice_flow_dir dir, u64 prof_id,
1213 struct ice_flow_seg_info *segs, u8 segs_cnt,
1214 struct ice_flow_action *acts, u8 acts_cnt,
1215 struct ice_flow_prof **prof)
1217 struct ice_flow_prof_params params;
1218 enum ice_status status;
1221 if (!prof || (acts_cnt && !acts))
1222 return ICE_ERR_BAD_PTR;
1224 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1225 params.prof = (struct ice_flow_prof *)
1226 ice_malloc(hw, sizeof(*params.prof));
1228 return ICE_ERR_NO_MEMORY;
1230 /* initialize extraction sequence to all invalid (0xff) */
1231 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1232 params.es[i].prot_id = ICE_PROT_INVALID;
1233 params.es[i].off = ICE_FV_OFFSET_INVAL;
1237 params.prof->id = prof_id;
1238 params.prof->dir = dir;
1239 params.prof->segs_cnt = segs_cnt;
1241 /* Make a copy of the segments that need to be persistent in the flow
1244 for (i = 0; i < segs_cnt; i++)
1245 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1246 ICE_NONDMA_TO_NONDMA);
1248 /* Make a copy of the actions that need to be persistent in the flow
1252 params.prof->acts = (struct ice_flow_action *)
1253 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1254 ICE_NONDMA_TO_NONDMA);
1256 if (!params.prof->acts) {
1257 status = ICE_ERR_NO_MEMORY;
1262 status = ice_flow_proc_segs(hw, ¶ms);
1264 ice_debug(hw, ICE_DBG_FLOW,
1265 "Error processing a flow's packet segments\n");
1269 /* Add a HW profile for this flow profile */
1270 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes,
1271 params.attr, params.attr_cnt, params.es,
1274 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1278 INIT_LIST_HEAD(¶ms.prof->entries);
1279 ice_init_lock(¶ms.prof->entries_lock);
1280 *prof = params.prof;
1284 if (params.prof->acts)
1285 ice_free(hw, params.prof->acts);
1286 ice_free(hw, params.prof);
1293 * ice_flow_rem_prof_sync - remove a flow profile
1294 * @hw: pointer to the hardware structure
1295 * @blk: classification stage
1296 * @prof: pointer to flow profile to remove
1298 * Assumption: the caller has acquired the lock to the profile list
1300 static enum ice_status
1301 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1302 struct ice_flow_prof *prof)
1304 enum ice_status status;
1306 /* Remove all remaining flow entries before removing the flow profile */
1307 if (!LIST_EMPTY(&prof->entries)) {
1308 struct ice_flow_entry *e, *t;
1310 ice_acquire_lock(&prof->entries_lock);
1312 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1314 status = ice_flow_rem_entry_sync(hw, e);
1319 ice_release_lock(&prof->entries_lock);
1322 /* Remove all hardware profiles associated with this flow profile */
1323 status = ice_rem_prof(hw, blk, prof->id);
1325 LIST_DEL(&prof->l_entry);
1326 ice_destroy_lock(&prof->entries_lock);
1328 ice_free(hw, prof->acts);
1336 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1337 * @hw: pointer to the hardware structure
1338 * @blk: classification stage
1339 * @vsi_handle: software VSI handle
1340 * @vsig: target VSI group
1342 * Assumption: the caller has already verified that the VSI to
1343 * be added has the same characteristics as the VSIG and will
1344 * thereby have access to all resources added to that VSIG.
1347 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1350 enum ice_status status;
1352 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1353 return ICE_ERR_PARAM;
1355 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1356 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1358 ice_release_lock(&hw->fl_profs_locks[blk]);
1364 * ice_flow_assoc_prof - associate a VSI with a flow profile
1365 * @hw: pointer to the hardware structure
1366 * @blk: classification stage
1367 * @prof: pointer to flow profile
1368 * @vsi_handle: software VSI handle
1370 * Assumption: the caller has acquired the lock to the profile list
1371 * and the software VSI handle has been validated
1373 static enum ice_status
1374 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1375 struct ice_flow_prof *prof, u16 vsi_handle)
1377 enum ice_status status = ICE_SUCCESS;
1379 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1380 status = ice_add_prof_id_flow(hw, blk,
1381 ice_get_hw_vsi_num(hw,
1385 ice_set_bit(vsi_handle, prof->vsis);
1387 ice_debug(hw, ICE_DBG_FLOW,
1388 "HW profile add failed, %d\n",
1396 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1397 * @hw: pointer to the hardware structure
1398 * @blk: classification stage
1399 * @prof: pointer to flow profile
1400 * @vsi_handle: software VSI handle
1402 * Assumption: the caller has acquired the lock to the profile list
1403 * and the software VSI handle has been validated
1405 static enum ice_status
1406 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1407 struct ice_flow_prof *prof, u16 vsi_handle)
1409 enum ice_status status = ICE_SUCCESS;
1411 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1412 status = ice_rem_prof_id_flow(hw, blk,
1413 ice_get_hw_vsi_num(hw,
1417 ice_clear_bit(vsi_handle, prof->vsis);
1419 ice_debug(hw, ICE_DBG_FLOW,
1420 "HW profile remove failed, %d\n",
1428 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1429 * @hw: pointer to the HW struct
1430 * @blk: classification stage
1431 * @dir: flow direction
1432 * @prof_id: unique ID to identify this flow profile
1433 * @segs: array of one or more packet segments that describe the flow
1434 * @segs_cnt: number of packet segments provided
1435 * @acts: array of default actions
1436 * @acts_cnt: number of default actions
1437 * @prof: stores the returned flow profile added
1440 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1441 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1442 struct ice_flow_action *acts, u8 acts_cnt,
1443 struct ice_flow_prof **prof)
1445 enum ice_status status;
1447 if (segs_cnt > ICE_FLOW_SEG_MAX)
1448 return ICE_ERR_MAX_LIMIT;
1451 return ICE_ERR_PARAM;
1454 return ICE_ERR_BAD_PTR;
1456 status = ice_flow_val_hdrs(segs, segs_cnt);
1460 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1462 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1463 acts, acts_cnt, prof);
1465 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1467 ice_release_lock(&hw->fl_profs_locks[blk]);
1473 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1474 * @hw: pointer to the HW struct
1475 * @blk: the block for which the flow profile is to be removed
1476 * @prof_id: unique ID of the flow profile to be removed
1479 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1481 struct ice_flow_prof *prof;
1482 enum ice_status status;
1484 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1486 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1488 status = ICE_ERR_DOES_NOT_EXIST;
1492 /* prof becomes invalid after the call */
1493 status = ice_flow_rem_prof_sync(hw, blk, prof);
1496 ice_release_lock(&hw->fl_profs_locks[blk]);
1502 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1503 * @hw: pointer to the HW struct
1504 * @blk: classification stage
1505 * @prof_id: the profile ID handle
1506 * @hw_prof_id: pointer to variable to receive the HW profile ID
1509 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1512 struct ice_prof_map *map;
1514 map = ice_search_prof_id(hw, blk, prof_id);
1516 *hw_prof_id = map->prof_id;
1520 return ICE_ERR_DOES_NOT_EXIST;
1524 * ice_flow_find_entry - look for a flow entry using its unique ID
1525 * @hw: pointer to the HW struct
1526 * @blk: classification stage
1527 * @entry_id: unique ID to identify this flow entry
1529 * This function looks for the flow entry with the specified unique ID in all
1530 * flow profiles of the specified classification stage. If the entry is found,
1531 * and it returns the handle to the flow entry. Otherwise, it returns
1532 * ICE_FLOW_ENTRY_ID_INVAL.
1534 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1536 struct ice_flow_entry *found = NULL;
1537 struct ice_flow_prof *p;
1539 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1541 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1542 struct ice_flow_entry *e;
1544 ice_acquire_lock(&p->entries_lock);
1545 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1546 if (e->id == entry_id) {
1550 ice_release_lock(&p->entries_lock);
1556 ice_release_lock(&hw->fl_profs_locks[blk]);
1558 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1562 * ice_flow_add_entry - Add a flow entry
1563 * @hw: pointer to the HW struct
1564 * @blk: classification stage
1565 * @prof_id: ID of the profile to add a new flow entry to
1566 * @entry_id: unique ID to identify this flow entry
1567 * @vsi_handle: software VSI handle for the flow entry
1568 * @prio: priority of the flow entry
1569 * @data: pointer to a data buffer containing flow entry's match values/masks
1570 * @acts: arrays of actions to be performed on a match
1571 * @acts_cnt: number of actions
1572 * @entry_h: pointer to buffer that receives the new flow entry's handle
1575 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1576 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1577 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1580 struct ice_flow_prof *prof = NULL;
1581 struct ice_flow_entry *e = NULL;
1582 enum ice_status status = ICE_SUCCESS;
1584 if (acts_cnt && !acts)
1585 return ICE_ERR_PARAM;
1587 /* No flow entry data is expected for RSS */
1588 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1589 return ICE_ERR_BAD_PTR;
1591 if (!ice_is_vsi_valid(hw, vsi_handle))
1592 return ICE_ERR_PARAM;
1594 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1596 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1598 status = ICE_ERR_DOES_NOT_EXIST;
1600 /* Allocate memory for the entry being added and associate
1601 * the VSI to the found flow profile
1603 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1605 status = ICE_ERR_NO_MEMORY;
1607 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1610 ice_release_lock(&hw->fl_profs_locks[blk]);
1615 e->vsi_handle = vsi_handle;
1621 /* RSS will add only one entry per VSI per profile */
1628 status = ICE_ERR_NOT_IMPL;
1632 if (blk != ICE_BLK_ACL) {
1633 /* ACL will handle the entry management */
1634 ice_acquire_lock(&prof->entries_lock);
1635 LIST_ADD(&e->l_entry, &prof->entries);
1636 ice_release_lock(&prof->entries_lock);
1639 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1644 ice_free(hw, e->entry);
1652 * ice_flow_rem_entry - Remove a flow entry
1653 * @hw: pointer to the HW struct
1654 * @entry_h: handle to the flow entry to be removed
1656 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1658 struct ice_flow_entry *entry;
1659 struct ice_flow_prof *prof;
1660 enum ice_status status;
1662 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1663 return ICE_ERR_PARAM;
1665 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1667 /* Retain the pointer to the flow profile as the entry will be freed */
1670 ice_acquire_lock(&prof->entries_lock);
1671 status = ice_flow_rem_entry_sync(hw, entry);
1672 ice_release_lock(&prof->entries_lock);
1678 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1679 * @seg: packet segment the field being set belongs to
1680 * @fld: field to be set
1681 * @field_type: type of the field
1682 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1683 * entry's input buffer
1684 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1686 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1687 * entry's input buffer
1689 * This helper function stores information of a field being matched, including
1690 * the type of the field and the locations of the value to match, the mask, and
1691 * and the upper-bound value in the start of the input buffer for a flow entry.
1692 * This function should only be used for fixed-size data structures.
1694 * This function also opportunistically determines the protocol headers to be
1695 * present based on the fields being set. Some fields cannot be used alone to
1696 * determine the protocol headers present. Sometimes, fields for particular
1697 * protocol headers are not matched. In those cases, the protocol headers
1698 * must be explicitly set.
1701 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1702 enum ice_flow_fld_match_type field_type, u16 val_loc,
1703 u16 mask_loc, u16 last_loc)
1705 u64 bit = BIT_ULL(fld);
1708 if (field_type == ICE_FLOW_FLD_TYPE_RANGE)
1711 seg->fields[fld].type = field_type;
1712 seg->fields[fld].src.val = val_loc;
1713 seg->fields[fld].src.mask = mask_loc;
1714 seg->fields[fld].src.last = last_loc;
1716 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1720 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1721 * @seg: packet segment the field being set belongs to
1722 * @fld: field to be set
1723 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1724 * entry's input buffer
1725 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1727 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1728 * entry's input buffer
1729 * @range: indicate if field being matched is to be in a range
1731 * This function specifies the locations, in the form of byte offsets from the
1732 * start of the input buffer for a flow entry, from where the value to match,
1733 * the mask value, and upper value can be extracted. These locations are then
1734 * stored in the flow profile. When adding a flow entry associated with the
1735 * flow profile, these locations will be used to quickly extract the values and
1736 * create the content of a match entry. This function should only be used for
1737 * fixed-size data structures.
1740 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1741 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1743 enum ice_flow_fld_match_type t = range ?
1744 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1746 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1750 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1751 * @seg: packet segment the field being set belongs to
1752 * @fld: field to be set
1753 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1754 * entry's input buffer
1755 * @pref_loc: location of prefix value from entry's input buffer
1756 * @pref_sz: size of the location holding the prefix value
1758 * This function specifies the locations, in the form of byte offsets from the
1759 * start of the input buffer for a flow entry, from where the value to match
1760 * and the IPv4 prefix value can be extracted. These locations are then stored
1761 * in the flow profile. When adding flow entries to the associated flow profile,
1762 * these locations can be used to quickly extract the values to create the
1763 * content of a match entry. This function should only be used for fixed-size
1767 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1768 u16 val_loc, u16 pref_loc, u8 pref_sz)
1770 /* For this type of field, the "mask" location is for the prefix value's
1771 * location and the "last" location is for the size of the location of
1774 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1775 pref_loc, (u16)pref_sz);
1779 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1780 * @seg: packet segment the field being set belongs to
1781 * @off: offset of the raw field from the beginning of the segment in bytes
1782 * @len: length of the raw pattern to be matched
1783 * @val_loc: location of the value to match from entry's input buffer
1784 * @mask_loc: location of mask value from entry's input buffer
1786 * This function specifies the offset of the raw field to be match from the
1787 * beginning of the specified packet segment, and the locations, in the form of
1788 * byte offsets from the start of the input buffer for a flow entry, from where
1789 * the value to match and the mask value to be extracted. These locations are
1790 * then stored in the flow profile. When adding flow entries to the associated
1791 * flow profile, these locations can be used to quickly extract the values to
1792 * create the content of a match entry. This function should only be used for
1793 * fixed-size data structures.
1796 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1797 u16 val_loc, u16 mask_loc)
1799 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1800 seg->raws[seg->raws_cnt].off = off;
1801 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1802 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1803 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1804 /* The "last" field is used to store the length of the field */
1805 seg->raws[seg->raws_cnt].info.src.last = len;
1808 /* Overflows of "raws" will be handled as an error condition later in
1809 * the flow when this information is processed.
1814 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1815 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1817 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1818 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1820 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1821 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1822 ICE_FLOW_SEG_HDR_SCTP)
1824 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1825 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1826 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1827 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1830 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1831 * @segs: pointer to the flow field segment(s)
1832 * @hash_fields: fields to be hashed on for the segment(s)
1833 * @flow_hdr: protocol header fields within a packet segment
1835 * Helper function to extract fields from hash bitmap and use flow
1836 * header value to set flow field segment for further use in flow
1837 * profile entry or removal.
1839 static enum ice_status
1840 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1843 u64 val = hash_fields;
1846 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1847 u64 bit = BIT_ULL(i);
1850 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1851 ICE_FLOW_FLD_OFF_INVAL,
1852 ICE_FLOW_FLD_OFF_INVAL,
1853 ICE_FLOW_FLD_OFF_INVAL, false);
1857 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1859 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1860 ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1861 return ICE_ERR_PARAM;
1863 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1864 if (val && !ice_is_pow2(val))
1867 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1868 if (val && !ice_is_pow2(val))
1875 * ice_rem_vsi_rss_list - remove VSI from RSS list
1876 * @hw: pointer to the hardware structure
1877 * @vsi_handle: software VSI handle
1879 * Remove the VSI from all RSS configurations in the list.
1881 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1883 struct ice_rss_cfg *r, *tmp;
1885 if (LIST_EMPTY(&hw->rss_list_head))
1888 ice_acquire_lock(&hw->rss_locks);
1889 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1890 ice_rss_cfg, l_entry) {
1891 if (ice_test_and_clear_bit(vsi_handle, r->vsis))
1892 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1893 LIST_DEL(&r->l_entry);
1897 ice_release_lock(&hw->rss_locks);
1901 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1902 * @hw: pointer to the hardware structure
1903 * @vsi_handle: software VSI handle
1905 * This function will iterate through all flow profiles and disassociate
1906 * the VSI from that profile. If the flow profile has no VSIs it will
1909 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1911 const enum ice_block blk = ICE_BLK_RSS;
1912 struct ice_flow_prof *p, *t;
1913 enum ice_status status = ICE_SUCCESS;
1915 if (!ice_is_vsi_valid(hw, vsi_handle))
1916 return ICE_ERR_PARAM;
1918 if (LIST_EMPTY(&hw->fl_profs[blk]))
1921 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1922 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1924 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1925 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1929 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1930 status = ice_flow_rem_prof_sync(hw, blk, p);
1936 ice_release_lock(&hw->fl_profs_locks[blk]);
1942 * ice_rem_rss_list - remove RSS configuration from list
1943 * @hw: pointer to the hardware structure
1944 * @vsi_handle: software VSI handle
1945 * @prof: pointer to flow profile
1947 * Assumption: lock has already been acquired for RSS list
1950 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1952 struct ice_rss_cfg *r, *tmp;
1954 /* Search for RSS hash fields associated to the VSI that match the
1955 * hash configurations associated to the flow profile. If found
1956 * remove from the RSS entry list of the VSI context and delete entry.
1958 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1959 ice_rss_cfg, l_entry) {
1960 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1961 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1962 ice_clear_bit(vsi_handle, r->vsis);
1963 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1964 LIST_DEL(&r->l_entry);
1973 * ice_add_rss_list - add RSS configuration to list
1974 * @hw: pointer to the hardware structure
1975 * @vsi_handle: software VSI handle
1976 * @prof: pointer to flow profile
1978 * Assumption: lock has already been acquired for RSS list
1980 static enum ice_status
1981 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1983 struct ice_rss_cfg *r, *rss_cfg;
1985 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1986 ice_rss_cfg, l_entry)
1987 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1988 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1989 ice_set_bit(vsi_handle, r->vsis);
1993 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1995 return ICE_ERR_NO_MEMORY;
1997 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1998 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1999 rss_cfg->symm = prof->cfg.symm;
2000 ice_set_bit(vsi_handle, rss_cfg->vsis);
2002 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
2007 #define ICE_FLOW_PROF_HASH_S 0
2008 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
2009 #define ICE_FLOW_PROF_HDR_S 32
2010 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
2011 #define ICE_FLOW_PROF_ENCAP_S 63
2012 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
2014 #define ICE_RSS_OUTER_HEADERS 1
2015 #define ICE_RSS_INNER_HEADERS 2
2017 /* Flow profile ID format:
2018 * [0:31] - Packet match fields
2019 * [32:62] - Protocol header
2020 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
2022 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
2023 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
2024 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
2025 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
2028 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
2030 u32 s = ((src % 4) << 3); /* byte shift */
2031 u32 v = dst | 0x80; /* value to program */
2032 u8 i = src / 4; /* register index */
2035 reg = rd32(hw, GLQF_HSYMM(prof_id, i));
2036 reg = (reg & ~(0xff << s)) | (v << s);
2037 wr32(hw, GLQF_HSYMM(prof_id, i), reg);
2041 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
2044 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
2047 for (i = 0; i < len; i++) {
2048 ice_rss_config_xor_word(hw, prof_id,
2049 /* Yes, field vector in GLQF_HSYMM and
2050 * GLQF_HINSET is inversed!
2052 fv_last_word - (src + i),
2053 fv_last_word - (dst + i));
2054 ice_rss_config_xor_word(hw, prof_id,
2055 fv_last_word - (dst + i),
2056 fv_last_word - (src + i));
2061 ice_rss_update_symm(struct ice_hw *hw,
2062 struct ice_flow_prof *prof)
2064 struct ice_prof_map *map;
2067 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
2068 prof_id = map->prof_id;
2070 /* clear to default */
2071 for (m = 0; m < 6; m++)
2072 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
2073 if (prof->cfg.symm) {
2074 struct ice_flow_seg_info *seg =
2075 &prof->segs[prof->segs_cnt - 1];
2077 struct ice_flow_seg_xtrct *ipv4_src =
2078 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
2079 struct ice_flow_seg_xtrct *ipv4_dst =
2080 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
2081 struct ice_flow_seg_xtrct *ipv6_src =
2082 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
2083 struct ice_flow_seg_xtrct *ipv6_dst =
2084 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
2086 struct ice_flow_seg_xtrct *tcp_src =
2087 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
2088 struct ice_flow_seg_xtrct *tcp_dst =
2089 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2091 struct ice_flow_seg_xtrct *udp_src =
2092 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2093 struct ice_flow_seg_xtrct *udp_dst =
2094 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2096 struct ice_flow_seg_xtrct *sctp_src =
2097 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2098 struct ice_flow_seg_xtrct *sctp_dst =
2099 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2102 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2103 ice_rss_config_xor(hw, prof_id,
2104 ipv4_src->idx, ipv4_dst->idx, 2);
2107 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2108 ice_rss_config_xor(hw, prof_id,
2109 ipv6_src->idx, ipv6_dst->idx, 8);
2112 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2113 ice_rss_config_xor(hw, prof_id,
2114 tcp_src->idx, tcp_dst->idx, 1);
2117 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2118 ice_rss_config_xor(hw, prof_id,
2119 udp_src->idx, udp_dst->idx, 1);
2122 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2123 ice_rss_config_xor(hw, prof_id,
2124 sctp_src->idx, sctp_dst->idx, 1);
2129 * ice_add_rss_cfg_sync - add an RSS configuration
2130 * @hw: pointer to the hardware structure
2131 * @vsi_handle: software VSI handle
2132 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2133 * @addl_hdrs: protocol header fields
2134 * @segs_cnt: packet segment count
2135 * @symm: symmetric hash enable/disable
2137 * Assumption: lock has already been acquired for RSS list
2139 static enum ice_status
2140 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2141 u32 addl_hdrs, u8 segs_cnt, bool symm)
2143 const enum ice_block blk = ICE_BLK_RSS;
2144 struct ice_flow_prof *prof = NULL;
2145 struct ice_flow_seg_info *segs;
2146 enum ice_status status;
2148 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2149 return ICE_ERR_PARAM;
2151 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2154 return ICE_ERR_NO_MEMORY;
2156 /* Construct the packet segment info from the hashed fields */
2157 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2162 /* Search for a flow profile that has matching headers, hash fields
2163 * and has the input VSI associated to it. If found, no further
2164 * operations required and exit.
2166 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2168 ICE_FLOW_FIND_PROF_CHK_FLDS |
2169 ICE_FLOW_FIND_PROF_CHK_VSI);
2171 if (prof->cfg.symm == symm)
2173 prof->cfg.symm = symm;
2177 /* Check if a flow profile exists with the same protocol headers and
2178 * associated with the input VSI. If so disasscociate the VSI from
2179 * this profile. The VSI will be added to a new profile created with
2180 * the protocol header and new hash field configuration.
2182 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2183 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
2185 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2187 ice_rem_rss_list(hw, vsi_handle, prof);
2191 /* Remove profile if it has no VSIs associated */
2192 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
2193 status = ice_flow_rem_prof(hw, blk, prof->id);
2199 /* Search for a profile that has same match fields only. If this
2200 * exists then associate the VSI to this profile.
2202 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2204 ICE_FLOW_FIND_PROF_CHK_FLDS);
2206 if (prof->cfg.symm == symm) {
2207 status = ice_flow_assoc_prof(hw, blk, prof,
2210 status = ice_add_rss_list(hw, vsi_handle,
2213 /* if a profile exist but with different symmetric
2214 * requirement, just return error.
2216 status = ICE_ERR_NOT_SUPPORTED;
2221 /* Create a new flow profile with generated profile and packet
2222 * segment information.
2224 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2225 ICE_FLOW_GEN_PROFID(hashed_flds,
2226 segs[segs_cnt - 1].hdrs,
2228 segs, segs_cnt, NULL, 0, &prof);
2232 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2233 /* If association to a new flow profile failed then this profile can
2237 ice_flow_rem_prof(hw, blk, prof->id);
2241 status = ice_add_rss_list(hw, vsi_handle, prof);
2243 prof->cfg.symm = symm;
2246 ice_rss_update_symm(hw, prof);
2254 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2255 * @hw: pointer to the hardware structure
2256 * @vsi_handle: software VSI handle
2257 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2258 * @addl_hdrs: protocol header fields
2259 * @symm: symmetric hash enable/disable
2261 * This function will generate a flow profile based on fields associated with
2262 * the input fields to hash on, the flow type and use the VSI number to add
2263 * a flow entry to the profile.
2266 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2267 u32 addl_hdrs, bool symm)
2269 enum ice_status status;
2271 if (hashed_flds == ICE_HASH_INVALID ||
2272 !ice_is_vsi_valid(hw, vsi_handle))
2273 return ICE_ERR_PARAM;
2275 ice_acquire_lock(&hw->rss_locks);
2276 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2277 ICE_RSS_OUTER_HEADERS, symm);
2279 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2280 addl_hdrs, ICE_RSS_INNER_HEADERS,
2282 ice_release_lock(&hw->rss_locks);
2288 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2289 * @hw: pointer to the hardware structure
2290 * @vsi_handle: software VSI handle
2291 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2292 * @addl_hdrs: Protocol header fields within a packet segment
2293 * @segs_cnt: packet segment count
2295 * Assumption: lock has already been acquired for RSS list
2297 static enum ice_status
2298 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2299 u32 addl_hdrs, u8 segs_cnt)
2301 const enum ice_block blk = ICE_BLK_RSS;
2302 struct ice_flow_seg_info *segs;
2303 struct ice_flow_prof *prof;
2304 enum ice_status status;
2306 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2309 return ICE_ERR_NO_MEMORY;
2311 /* Construct the packet segment info from the hashed fields */
2312 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2317 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2319 ICE_FLOW_FIND_PROF_CHK_FLDS);
2321 status = ICE_ERR_DOES_NOT_EXIST;
2325 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2329 /* Remove RSS configuration from VSI context before deleting
2332 ice_rem_rss_list(hw, vsi_handle, prof);
2334 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2335 status = ice_flow_rem_prof(hw, blk, prof->id);
2343 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2344 * @hw: pointer to the hardware structure
2345 * @vsi_handle: software VSI handle
2346 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2347 * @addl_hdrs: Protocol header fields within a packet segment
2349 * This function will lookup the flow profile based on the input
2350 * hash field bitmap, iterate through the profile entry list of
2351 * that profile and find entry associated with input VSI to be
2352 * removed. Calls are made to underlying flow apis which will in
2353 * turn build or update buffers for RSS XLT1 section.
2356 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2359 enum ice_status status;
2361 if (hashed_flds == ICE_HASH_INVALID ||
2362 !ice_is_vsi_valid(hw, vsi_handle))
2363 return ICE_ERR_PARAM;
2365 ice_acquire_lock(&hw->rss_locks);
2366 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2367 ICE_RSS_OUTER_HEADERS);
2369 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2370 addl_hdrs, ICE_RSS_INNER_HEADERS);
2371 ice_release_lock(&hw->rss_locks);
2377 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2378 * @hw: pointer to the hardware structure
2379 * @vsi_handle: software VSI handle
2381 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2383 enum ice_status status = ICE_SUCCESS;
2384 struct ice_rss_cfg *r;
2386 if (!ice_is_vsi_valid(hw, vsi_handle))
2387 return ICE_ERR_PARAM;
2389 ice_acquire_lock(&hw->rss_locks);
2390 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2391 ice_rss_cfg, l_entry) {
2392 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2393 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2396 ICE_RSS_OUTER_HEADERS,
2400 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2403 ICE_RSS_INNER_HEADERS,
2409 ice_release_lock(&hw->rss_locks);
2415 * ice_get_rss_cfg - returns hashed fields for the given header types
2416 * @hw: pointer to the hardware structure
2417 * @vsi_handle: software VSI handle
2418 * @hdrs: protocol header type
2420 * This function will return the match fields of the first instance of flow
2421 * profile having the given header types and containing input VSI
2423 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2425 struct ice_rss_cfg *r, *rss_cfg = NULL;
2427 /* verify if the protocol header is non zero and VSI is valid */
2428 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2429 return ICE_HASH_INVALID;
2431 ice_acquire_lock(&hw->rss_locks);
2432 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2433 ice_rss_cfg, l_entry)
2434 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2435 r->packet_hdr == hdrs) {
2439 ice_release_lock(&hw->rss_locks);
2441 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;