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, 0x00003000, 0x00000000, 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 u32 ice_ptypes_gtpu[] = {
370 0x00000000, 0x00000000, 0x00000000, 0x00000000,
371 0x00000000, 0x00000000, 0x00000000, 0x00000000,
372 0x00000000, 0x00000000, 0x7FFFFE00, 0x00000000,
373 0x00000000, 0x00000000, 0x00000000, 0x00000000,
374 0x00000000, 0x00000000, 0x00000000, 0x00000000,
375 0x00000000, 0x00000000, 0x00000000, 0x00000000,
376 0x00000000, 0x00000000, 0x00000000, 0x00000000,
377 0x00000000, 0x00000000, 0x00000000, 0x00000000,
380 /* Packet types for pppoe */
381 static const u32 ice_ptypes_pppoe[] = {
382 0x00000000, 0x00000000, 0x00000000, 0x00000000,
383 0x00000000, 0x00000000, 0x00000000, 0x00000000,
384 0x00000000, 0x03FFF000, 0x00000000, 0x00000000,
385 0x00000000, 0x00000000, 0x00000000, 0x00000000,
386 0x00000000, 0x00000000, 0x00000000, 0x00000000,
387 0x00000000, 0x00000000, 0x00000000, 0x00000000,
388 0x00000000, 0x00000000, 0x00000000, 0x00000000,
389 0x00000000, 0x00000000, 0x00000000, 0x00000000,
392 /* Manage parameters and info. used during the creation of a flow profile */
393 struct ice_flow_prof_params {
395 u16 entry_length; /* # of bytes formatted entry will require */
397 struct ice_flow_prof *prof;
399 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
400 * This will give us the direction flags.
402 struct ice_fv_word es[ICE_MAX_FV_WORDS];
403 /* attributes can be used to add attributes to a particular PTYPE */
404 const struct ice_ptype_attributes *attr;
407 u16 mask[ICE_MAX_FV_WORDS];
408 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
411 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
412 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
413 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU)
415 #define ICE_FLOW_SEG_HDRS_L2_MASK \
416 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
417 #define ICE_FLOW_SEG_HDRS_L3_MASK \
418 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
419 ICE_FLOW_SEG_HDR_ARP)
420 #define ICE_FLOW_SEG_HDRS_L4_MASK \
421 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
422 ICE_FLOW_SEG_HDR_SCTP)
425 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
426 * @segs: array of one or more packet segments that describe the flow
427 * @segs_cnt: number of packet segments provided
429 static enum ice_status
430 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
434 for (i = 0; i < segs_cnt; i++) {
435 /* Multiple L3 headers */
436 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
437 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
438 return ICE_ERR_PARAM;
440 /* Multiple L4 headers */
441 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
442 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
443 return ICE_ERR_PARAM;
449 /* Sizes of fixed known protocol headers without header options */
450 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
451 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
452 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
453 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
454 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
455 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
456 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
457 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
458 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
461 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
462 * @params: information about the flow to be processed
463 * @seg: index of packet segment whose header size is to be determined
465 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
470 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
471 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
474 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
475 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
476 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
477 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
478 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
479 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
480 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
481 /* A L3 header is required if L4 is specified */
485 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
486 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
487 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
488 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
489 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
490 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
491 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
492 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
498 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
499 * @params: information about the flow to be processed
501 * This function identifies the packet types associated with the protocol
502 * headers being present in packet segments of the specified flow profile.
504 static enum ice_status
505 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
507 struct ice_flow_prof *prof;
510 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
515 for (i = 0; i < params->prof->segs_cnt; i++) {
516 const ice_bitmap_t *src;
519 hdrs = prof->segs[i].hdrs;
521 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
522 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
523 (const ice_bitmap_t *)ice_ptypes_mac_il;
524 ice_and_bitmap(params->ptypes, params->ptypes, src,
528 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
529 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
530 ice_and_bitmap(params->ptypes, params->ptypes, src,
534 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
535 ice_and_bitmap(params->ptypes, params->ptypes,
536 (const ice_bitmap_t *)ice_ptypes_arp_of,
540 if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
541 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
542 ice_and_bitmap(params->ptypes, params->ptypes, src,
546 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
547 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
548 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
549 ice_and_bitmap(params->ptypes, params->ptypes, src,
551 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
552 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
553 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
554 ice_and_bitmap(params->ptypes, params->ptypes, src,
558 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
559 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
560 (const ice_bitmap_t *)ice_ptypes_icmp_il;
561 ice_and_bitmap(params->ptypes, params->ptypes, src,
563 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
564 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
565 ice_and_bitmap(params->ptypes, params->ptypes, src,
567 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
568 ice_and_bitmap(params->ptypes, params->ptypes,
569 (const ice_bitmap_t *)ice_ptypes_tcp_il,
571 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
572 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
573 ice_and_bitmap(params->ptypes, params->ptypes, src,
575 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
577 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
578 ice_and_bitmap(params->ptypes, params->ptypes,
579 src, ICE_FLOW_PTYPE_MAX);
581 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
582 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
583 ice_and_bitmap(params->ptypes, params->ptypes,
584 src, ICE_FLOW_PTYPE_MAX);
585 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
586 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
587 ice_and_bitmap(params->ptypes, params->ptypes,
588 src, ICE_FLOW_PTYPE_MAX);
589 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
590 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
591 ice_and_bitmap(params->ptypes, params->ptypes,
592 src, ICE_FLOW_PTYPE_MAX);
593 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
594 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
595 ice_and_bitmap(params->ptypes, params->ptypes,
596 src, ICE_FLOW_PTYPE_MAX);
598 /* Attributes for GTP packet with Extension Header */
599 params->attr = ice_attr_gtpu_eh;
600 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
608 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
609 * @hw: pointer to the HW struct
610 * @params: information about the flow to be processed
611 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
613 * This function will allocate an extraction sequence entries for a DWORD size
614 * chunk of the packet flags.
616 static enum ice_status
617 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
618 struct ice_flow_prof_params *params,
619 enum ice_flex_mdid_pkt_flags flags)
621 u8 fv_words = hw->blk[params->blk].es.fvw;
624 /* Make sure the number of extraction sequence entries required does not
625 * exceed the block's capacity.
627 if (params->es_cnt >= fv_words)
628 return ICE_ERR_MAX_LIMIT;
630 /* some blocks require a reversed field vector layout */
631 if (hw->blk[params->blk].es.reverse)
632 idx = fv_words - params->es_cnt - 1;
634 idx = params->es_cnt;
636 params->es[idx].prot_id = ICE_PROT_META_ID;
637 params->es[idx].off = flags;
644 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
645 * @hw: pointer to the HW struct
646 * @params: information about the flow to be processed
647 * @seg: packet segment index of the field to be extracted
648 * @fld: ID of field to be extracted
649 * @match: bitfield of all fields
651 * This function determines the protocol ID, offset, and size of the given
652 * field. It then allocates one or more extraction sequence entries for the
653 * given field, and fill the entries with protocol ID and offset information.
655 static enum ice_status
656 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
657 u8 seg, enum ice_flow_field fld, u64 match)
659 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
660 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
661 u8 fv_words = hw->blk[params->blk].es.fvw;
662 struct ice_flow_fld_info *flds;
663 u16 cnt, ese_bits, i;
669 flds = params->prof->segs[seg].fields;
672 case ICE_FLOW_FIELD_IDX_ETH_DA:
673 case ICE_FLOW_FIELD_IDX_ETH_SA:
674 case ICE_FLOW_FIELD_IDX_S_VLAN:
675 case ICE_FLOW_FIELD_IDX_C_VLAN:
676 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
678 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
679 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
681 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
682 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
684 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
685 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
687 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
688 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
689 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
691 /* TTL and PROT share the same extraction seq. entry.
692 * Each is considered a sibling to the other in terms of sharing
693 * the same extraction sequence entry.
695 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
696 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
697 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
698 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
700 /* If the sibling field is also included, that field's
701 * mask needs to be included.
703 if (match & BIT(sib))
704 sib_mask = ice_flds_info[sib].mask;
706 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
707 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
708 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
710 /* TTL and PROT share the same extraction seq. entry.
711 * Each is considered a sibling to the other in terms of sharing
712 * the same extraction sequence entry.
714 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
715 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
716 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
717 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
719 /* If the sibling field is also included, that field's
720 * mask needs to be included.
722 if (match & BIT(sib))
723 sib_mask = ice_flds_info[sib].mask;
725 case ICE_FLOW_FIELD_IDX_IPV4_SA:
726 case ICE_FLOW_FIELD_IDX_IPV4_DA:
727 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
729 case ICE_FLOW_FIELD_IDX_IPV6_SA:
730 case ICE_FLOW_FIELD_IDX_IPV6_DA:
731 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
733 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
734 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
735 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
736 prot_id = ICE_PROT_TCP_IL;
738 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
739 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
740 prot_id = ICE_PROT_UDP_IL_OR_S;
742 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
743 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
744 prot_id = ICE_PROT_SCTP_IL;
746 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
747 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
748 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
749 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
750 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
751 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
752 /* GTP is accessed through UDP OF protocol */
753 prot_id = ICE_PROT_UDP_OF;
755 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
756 prot_id = ICE_PROT_PPPOE;
758 case ICE_FLOW_FIELD_IDX_ARP_SIP:
759 case ICE_FLOW_FIELD_IDX_ARP_DIP:
760 case ICE_FLOW_FIELD_IDX_ARP_SHA:
761 case ICE_FLOW_FIELD_IDX_ARP_DHA:
762 case ICE_FLOW_FIELD_IDX_ARP_OP:
763 prot_id = ICE_PROT_ARP_OF;
765 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
766 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
767 /* ICMP type and code share the same extraction seq. entry */
768 prot_id = (params->prof->segs[seg].hdrs &
769 ICE_FLOW_SEG_HDR_IPV4) ?
770 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
771 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
772 ICE_FLOW_FIELD_IDX_ICMP_CODE :
773 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
775 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
776 prot_id = ICE_PROT_GRE_OF;
779 return ICE_ERR_NOT_IMPL;
782 /* Each extraction sequence entry is a word in size, and extracts a
783 * word-aligned offset from a protocol header.
785 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
787 flds[fld].xtrct.prot_id = prot_id;
788 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
789 ICE_FLOW_FV_EXTRACT_SZ;
790 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
791 flds[fld].xtrct.idx = params->es_cnt;
792 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
794 /* Adjust the next field-entry index after accommodating the number of
795 * entries this field consumes
797 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
798 ice_flds_info[fld].size, ese_bits);
800 /* Fill in the extraction sequence entries needed for this field */
801 off = flds[fld].xtrct.off;
802 mask = flds[fld].xtrct.mask;
803 for (i = 0; i < cnt; i++) {
804 /* Only consume an extraction sequence entry if there is no
805 * sibling field associated with this field or the sibling entry
806 * already extracts the word shared with this field.
808 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
809 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
810 flds[sib].xtrct.off != off) {
813 /* Make sure the number of extraction sequence required
814 * does not exceed the block's capability
816 if (params->es_cnt >= fv_words)
817 return ICE_ERR_MAX_LIMIT;
819 /* some blocks require a reversed field vector layout */
820 if (hw->blk[params->blk].es.reverse)
821 idx = fv_words - params->es_cnt - 1;
823 idx = params->es_cnt;
825 params->es[idx].prot_id = prot_id;
826 params->es[idx].off = off;
827 params->mask[idx] = mask | sib_mask;
831 off += ICE_FLOW_FV_EXTRACT_SZ;
838 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
839 * @hw: pointer to the HW struct
840 * @params: information about the flow to be processed
841 * @seg: index of packet segment whose raw fields are to be be extracted
843 static enum ice_status
844 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
851 if (!params->prof->segs[seg].raws_cnt)
854 if (params->prof->segs[seg].raws_cnt >
855 ARRAY_SIZE(params->prof->segs[seg].raws))
856 return ICE_ERR_MAX_LIMIT;
858 /* Offsets within the segment headers are not supported */
859 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
861 return ICE_ERR_PARAM;
863 fv_words = hw->blk[params->blk].es.fvw;
865 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
866 struct ice_flow_seg_fld_raw *raw;
869 raw = ¶ms->prof->segs[seg].raws[i];
871 /* Only support matching raw fields in the payload */
872 if (raw->off < hdrs_sz)
873 return ICE_ERR_PARAM;
875 /* Convert the segment-relative offset into payload-relative
878 off = raw->off - hdrs_sz;
880 /* Storing extraction information */
881 raw->info.xtrct.prot_id = ICE_PROT_PAY;
882 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
883 ICE_FLOW_FV_EXTRACT_SZ;
884 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
886 raw->info.xtrct.idx = params->es_cnt;
888 /* Determine the number of field vector entries this raw field
891 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
892 (raw->info.src.last * BITS_PER_BYTE),
893 (ICE_FLOW_FV_EXTRACT_SZ *
895 off = raw->info.xtrct.off;
896 for (j = 0; j < cnt; j++) {
899 /* Make sure the number of extraction sequence required
900 * does not exceed the block's capability
902 if (params->es_cnt >= hw->blk[params->blk].es.count ||
903 params->es_cnt >= ICE_MAX_FV_WORDS)
904 return ICE_ERR_MAX_LIMIT;
906 /* some blocks require a reversed field vector layout */
907 if (hw->blk[params->blk].es.reverse)
908 idx = fv_words - params->es_cnt - 1;
910 idx = params->es_cnt;
912 params->es[idx].prot_id = ICE_PROT_PAY;
913 params->es[idx].off = off;
915 off += ICE_FLOW_FV_EXTRACT_SZ;
923 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
924 * @hw: pointer to the HW struct
925 * @params: information about the flow to be processed
927 * This function iterates through all matched fields in the given segments, and
928 * creates an extraction sequence for the fields.
930 static enum ice_status
931 ice_flow_create_xtrct_seq(struct ice_hw *hw,
932 struct ice_flow_prof_params *params)
934 enum ice_status status = ICE_SUCCESS;
937 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
940 if (params->blk == ICE_BLK_ACL) {
941 status = ice_flow_xtract_pkt_flags(hw, params,
942 ICE_RX_MDID_PKT_FLAGS_15_0);
947 for (i = 0; i < params->prof->segs_cnt; i++) {
948 u64 match = params->prof->segs[i].match;
951 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
952 const u64 bit = BIT_ULL(j);
955 status = ice_flow_xtract_fld
956 (hw, params, i, (enum ice_flow_field)j,
964 /* Process raw matching bytes */
965 status = ice_flow_xtract_raws(hw, params, i);
974 * ice_flow_proc_segs - process all packet segments associated with a profile
975 * @hw: pointer to the HW struct
976 * @params: information about the flow to be processed
978 static enum ice_status
979 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
981 enum ice_status status;
983 status = ice_flow_proc_seg_hdrs(params);
987 status = ice_flow_create_xtrct_seq(hw, params);
991 switch (params->blk) {
993 /* Only header information is provided for RSS configuration.
994 * No further processing is needed.
996 status = ICE_SUCCESS;
999 status = ICE_SUCCESS;
1003 return ICE_ERR_NOT_IMPL;
1009 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1010 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
1011 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
1014 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1015 * @hw: pointer to the HW struct
1016 * @blk: classification stage
1017 * @dir: flow direction
1018 * @segs: array of one or more packet segments that describe the flow
1019 * @segs_cnt: number of packet segments provided
1020 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1021 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1023 static struct ice_flow_prof *
1024 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1025 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1026 u8 segs_cnt, u16 vsi_handle, u32 conds)
1028 struct ice_flow_prof *p, *prof = NULL;
1030 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1031 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1032 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1033 segs_cnt && segs_cnt == p->segs_cnt) {
1036 /* Check for profile-VSI association if specified */
1037 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1038 ice_is_vsi_valid(hw, vsi_handle) &&
1039 !ice_is_bit_set(p->vsis, vsi_handle))
1042 /* Protocol headers must be checked. Matched fields are
1043 * checked if specified.
1045 for (i = 0; i < segs_cnt; i++)
1046 if (segs[i].hdrs != p->segs[i].hdrs ||
1047 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1048 segs[i].match != p->segs[i].match))
1051 /* A match is found if all segments are matched */
1052 if (i == segs_cnt) {
1058 ice_release_lock(&hw->fl_profs_locks[blk]);
1064 * ice_flow_find_prof - Look up a profile matching headers and matched fields
1065 * @hw: pointer to the HW struct
1066 * @blk: classification stage
1067 * @dir: flow direction
1068 * @segs: array of one or more packet segments that describe the flow
1069 * @segs_cnt: number of packet segments provided
1072 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1073 struct ice_flow_seg_info *segs, u8 segs_cnt)
1075 struct ice_flow_prof *p;
1077 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1078 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1080 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1084 * ice_flow_find_prof_id - Look up a profile with given profile ID
1085 * @hw: pointer to the HW struct
1086 * @blk: classification stage
1087 * @prof_id: unique ID to identify this flow profile
1089 static struct ice_flow_prof *
1090 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1092 struct ice_flow_prof *p;
1094 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1095 if (p->id == prof_id)
1103 * ice_dealloc_flow_entry - Deallocate flow entry memory
1104 * @hw: pointer to the HW struct
1105 * @entry: flow entry to be removed
1108 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1114 ice_free(hw, entry->entry);
1117 ice_free(hw, entry->acts);
1119 entry->acts_cnt = 0;
1122 ice_free(hw, entry);
1126 * ice_flow_rem_entry_sync - Remove a flow entry
1127 * @hw: pointer to the HW struct
1128 * @entry: flow entry to be removed
1130 static enum ice_status
1131 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1134 return ICE_ERR_BAD_PTR;
1136 LIST_DEL(&entry->l_entry);
1138 ice_dealloc_flow_entry(hw, entry);
1144 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1145 * @hw: pointer to the HW struct
1146 * @blk: classification stage
1147 * @dir: flow direction
1148 * @prof_id: unique ID to identify this flow profile
1149 * @segs: array of one or more packet segments that describe the flow
1150 * @segs_cnt: number of packet segments provided
1151 * @acts: array of default actions
1152 * @acts_cnt: number of default actions
1153 * @prof: stores the returned flow profile added
1155 * Assumption: the caller has acquired the lock to the profile list
1157 static enum ice_status
1158 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1159 enum ice_flow_dir dir, u64 prof_id,
1160 struct ice_flow_seg_info *segs, u8 segs_cnt,
1161 struct ice_flow_action *acts, u8 acts_cnt,
1162 struct ice_flow_prof **prof)
1164 struct ice_flow_prof_params params;
1165 enum ice_status status = ICE_SUCCESS;
1168 if (!prof || (acts_cnt && !acts))
1169 return ICE_ERR_BAD_PTR;
1171 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1172 params.prof = (struct ice_flow_prof *)
1173 ice_malloc(hw, sizeof(*params.prof));
1175 return ICE_ERR_NO_MEMORY;
1177 /* initialize extraction sequence to all invalid (0xff) */
1178 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1179 params.es[i].prot_id = ICE_PROT_INVALID;
1180 params.es[i].off = ICE_FV_OFFSET_INVAL;
1184 params.prof->id = prof_id;
1185 params.prof->dir = dir;
1186 params.prof->segs_cnt = segs_cnt;
1188 /* Make a copy of the segments that need to be persistent in the flow
1191 for (i = 0; i < segs_cnt; i++)
1192 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1193 ICE_NONDMA_TO_NONDMA);
1195 /* Make a copy of the actions that need to be persistent in the flow
1199 params.prof->acts = (struct ice_flow_action *)
1200 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1201 ICE_NONDMA_TO_NONDMA);
1203 if (!params.prof->acts) {
1204 status = ICE_ERR_NO_MEMORY;
1209 status = ice_flow_proc_segs(hw, ¶ms);
1211 ice_debug(hw, ICE_DBG_FLOW,
1212 "Error processing a flow's packet segments\n");
1216 /* Add a HW profile for this flow profile */
1217 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes,
1218 params.attr, params.attr_cnt, params.es,
1221 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1225 INIT_LIST_HEAD(¶ms.prof->entries);
1226 ice_init_lock(¶ms.prof->entries_lock);
1227 *prof = params.prof;
1231 if (params.prof->acts)
1232 ice_free(hw, params.prof->acts);
1233 ice_free(hw, params.prof);
1240 * ice_flow_rem_prof_sync - remove a flow profile
1241 * @hw: pointer to the hardware structure
1242 * @blk: classification stage
1243 * @prof: pointer to flow profile to remove
1245 * Assumption: the caller has acquired the lock to the profile list
1247 static enum ice_status
1248 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1249 struct ice_flow_prof *prof)
1251 enum ice_status status = ICE_SUCCESS;
1253 /* Remove all remaining flow entries before removing the flow profile */
1254 if (!LIST_EMPTY(&prof->entries)) {
1255 struct ice_flow_entry *e, *t;
1257 ice_acquire_lock(&prof->entries_lock);
1259 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1261 status = ice_flow_rem_entry_sync(hw, e);
1266 ice_release_lock(&prof->entries_lock);
1269 /* Remove all hardware profiles associated with this flow profile */
1270 status = ice_rem_prof(hw, blk, prof->id);
1272 LIST_DEL(&prof->l_entry);
1273 ice_destroy_lock(&prof->entries_lock);
1275 ice_free(hw, prof->acts);
1283 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1284 * @hw: pointer to the hardware structure
1285 * @blk: classification stage
1286 * @vsi_handle: software VSI handle
1287 * @vsig: target VSI group
1289 * Assumption: the caller has already verified that the VSI to
1290 * be added has the same characteristics as the VSIG and will
1291 * thereby have access to all resources added to that VSIG.
1294 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1297 enum ice_status status;
1299 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1300 return ICE_ERR_PARAM;
1302 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1303 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1305 ice_release_lock(&hw->fl_profs_locks[blk]);
1311 * ice_flow_assoc_prof - associate a VSI with a flow profile
1312 * @hw: pointer to the hardware structure
1313 * @blk: classification stage
1314 * @prof: pointer to flow profile
1315 * @vsi_handle: software VSI handle
1317 * Assumption: the caller has acquired the lock to the profile list
1318 * and the software VSI handle has been validated
1320 static enum ice_status
1321 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1322 struct ice_flow_prof *prof, u16 vsi_handle)
1324 enum ice_status status = ICE_SUCCESS;
1326 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1327 status = ice_add_prof_id_flow(hw, blk,
1328 ice_get_hw_vsi_num(hw,
1332 ice_set_bit(vsi_handle, prof->vsis);
1334 ice_debug(hw, ICE_DBG_FLOW,
1335 "HW profile add failed, %d\n",
1343 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1344 * @hw: pointer to the hardware structure
1345 * @blk: classification stage
1346 * @prof: pointer to flow profile
1347 * @vsi_handle: software VSI handle
1349 * Assumption: the caller has acquired the lock to the profile list
1350 * and the software VSI handle has been validated
1352 static enum ice_status
1353 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1354 struct ice_flow_prof *prof, u16 vsi_handle)
1356 enum ice_status status = ICE_SUCCESS;
1358 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1359 status = ice_rem_prof_id_flow(hw, blk,
1360 ice_get_hw_vsi_num(hw,
1364 ice_clear_bit(vsi_handle, prof->vsis);
1366 ice_debug(hw, ICE_DBG_FLOW,
1367 "HW profile remove failed, %d\n",
1375 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1376 * @hw: pointer to the HW struct
1377 * @blk: classification stage
1378 * @dir: flow direction
1379 * @prof_id: unique ID to identify this flow profile
1380 * @segs: array of one or more packet segments that describe the flow
1381 * @segs_cnt: number of packet segments provided
1382 * @acts: array of default actions
1383 * @acts_cnt: number of default actions
1384 * @prof: stores the returned flow profile added
1387 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1388 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1389 struct ice_flow_action *acts, u8 acts_cnt,
1390 struct ice_flow_prof **prof)
1392 enum ice_status status;
1394 if (segs_cnt > ICE_FLOW_SEG_MAX)
1395 return ICE_ERR_MAX_LIMIT;
1398 return ICE_ERR_PARAM;
1401 return ICE_ERR_BAD_PTR;
1403 status = ice_flow_val_hdrs(segs, segs_cnt);
1407 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1409 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1410 acts, acts_cnt, prof);
1412 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1414 ice_release_lock(&hw->fl_profs_locks[blk]);
1420 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1421 * @hw: pointer to the HW struct
1422 * @blk: the block for which the flow profile is to be removed
1423 * @prof_id: unique ID of the flow profile to be removed
1426 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1428 struct ice_flow_prof *prof;
1429 enum ice_status status;
1431 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1433 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1435 status = ICE_ERR_DOES_NOT_EXIST;
1439 /* prof becomes invalid after the call */
1440 status = ice_flow_rem_prof_sync(hw, blk, prof);
1443 ice_release_lock(&hw->fl_profs_locks[blk]);
1449 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1450 * @hw: pointer to the HW struct
1451 * @blk: classification stage
1452 * @prof_id: the profile ID handle
1453 * @hw_prof_id: pointer to variable to receive the HW profile ID
1456 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1459 struct ice_prof_map *map;
1461 map = ice_search_prof_id(hw, blk, prof_id);
1463 *hw_prof_id = map->prof_id;
1467 return ICE_ERR_DOES_NOT_EXIST;
1471 * ice_flow_find_entry - look for a flow entry using its unique ID
1472 * @hw: pointer to the HW struct
1473 * @blk: classification stage
1474 * @entry_id: unique ID to identify this flow entry
1476 * This function looks for the flow entry with the specified unique ID in all
1477 * flow profiles of the specified classification stage. If the entry is found,
1478 * and it returns the handle to the flow entry. Otherwise, it returns
1479 * ICE_FLOW_ENTRY_ID_INVAL.
1481 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1483 struct ice_flow_entry *found = NULL;
1484 struct ice_flow_prof *p;
1486 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1488 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1489 struct ice_flow_entry *e;
1491 ice_acquire_lock(&p->entries_lock);
1492 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1493 if (e->id == entry_id) {
1497 ice_release_lock(&p->entries_lock);
1503 ice_release_lock(&hw->fl_profs_locks[blk]);
1505 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1509 * ice_flow_add_entry - Add a flow entry
1510 * @hw: pointer to the HW struct
1511 * @blk: classification stage
1512 * @prof_id: ID of the profile to add a new flow entry to
1513 * @entry_id: unique ID to identify this flow entry
1514 * @vsi_handle: software VSI handle for the flow entry
1515 * @prio: priority of the flow entry
1516 * @data: pointer to a data buffer containing flow entry's match values/masks
1517 * @acts: arrays of actions to be performed on a match
1518 * @acts_cnt: number of actions
1519 * @entry_h: pointer to buffer that receives the new flow entry's handle
1522 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1523 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1524 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1527 struct ice_flow_prof *prof = NULL;
1528 struct ice_flow_entry *e = NULL;
1529 enum ice_status status = ICE_SUCCESS;
1531 if (acts_cnt && !acts)
1532 return ICE_ERR_PARAM;
1534 /* No flow entry data is expected for RSS */
1535 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1536 return ICE_ERR_BAD_PTR;
1538 if (!ice_is_vsi_valid(hw, vsi_handle))
1539 return ICE_ERR_PARAM;
1541 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1543 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1545 status = ICE_ERR_DOES_NOT_EXIST;
1547 /* Allocate memory for the entry being added and associate
1548 * the VSI to the found flow profile
1550 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1552 status = ICE_ERR_NO_MEMORY;
1554 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1557 ice_release_lock(&hw->fl_profs_locks[blk]);
1562 e->vsi_handle = vsi_handle;
1568 /* RSS will add only one entry per VSI per profile */
1575 status = ICE_ERR_NOT_IMPL;
1579 if (blk != ICE_BLK_ACL) {
1580 /* ACL will handle the entry management */
1581 ice_acquire_lock(&prof->entries_lock);
1582 LIST_ADD(&e->l_entry, &prof->entries);
1583 ice_release_lock(&prof->entries_lock);
1586 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1591 ice_free(hw, e->entry);
1599 * ice_flow_rem_entry - Remove a flow entry
1600 * @hw: pointer to the HW struct
1601 * @entry_h: handle to the flow entry to be removed
1603 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1605 struct ice_flow_entry *entry;
1606 struct ice_flow_prof *prof;
1607 enum ice_status status;
1609 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1610 return ICE_ERR_PARAM;
1612 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1614 /* Retain the pointer to the flow profile as the entry will be freed */
1617 ice_acquire_lock(&prof->entries_lock);
1618 status = ice_flow_rem_entry_sync(hw, entry);
1619 ice_release_lock(&prof->entries_lock);
1625 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1626 * @seg: packet segment the field being set belongs to
1627 * @fld: field to be set
1628 * @type: type of the field
1629 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1630 * entry's input buffer
1631 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1633 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1634 * entry's input buffer
1636 * This helper function stores information of a field being matched, including
1637 * the type of the field and the locations of the value to match, the mask, and
1638 * and the upper-bound value in the start of the input buffer for a flow entry.
1639 * This function should only be used for fixed-size data structures.
1641 * This function also opportunistically determines the protocol headers to be
1642 * present based on the fields being set. Some fields cannot be used alone to
1643 * determine the protocol headers present. Sometimes, fields for particular
1644 * protocol headers are not matched. In those cases, the protocol headers
1645 * must be explicitly set.
1648 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1649 enum ice_flow_fld_match_type type, u16 val_loc,
1650 u16 mask_loc, u16 last_loc)
1652 u64 bit = BIT_ULL(fld);
1655 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1658 seg->fields[fld].type = type;
1659 seg->fields[fld].src.val = val_loc;
1660 seg->fields[fld].src.mask = mask_loc;
1661 seg->fields[fld].src.last = last_loc;
1663 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1667 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1668 * @seg: packet segment the field being set belongs to
1669 * @fld: field to be set
1670 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1671 * entry's input buffer
1672 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1674 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1675 * entry's input buffer
1676 * @range: indicate if field being matched is to be in a range
1678 * This function specifies the locations, in the form of byte offsets from the
1679 * start of the input buffer for a flow entry, from where the value to match,
1680 * the mask value, and upper value can be extracted. These locations are then
1681 * stored in the flow profile. When adding a flow entry associated with the
1682 * flow profile, these locations will be used to quickly extract the values and
1683 * create the content of a match entry. This function should only be used for
1684 * fixed-size data structures.
1687 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1688 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1690 enum ice_flow_fld_match_type t = range ?
1691 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1693 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1697 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1698 * @seg: packet segment the field being set belongs to
1699 * @fld: field to be set
1700 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1701 * entry's input buffer
1702 * @pref_loc: location of prefix value from entry's input buffer
1703 * @pref_sz: size of the location holding the prefix value
1705 * This function specifies the locations, in the form of byte offsets from the
1706 * start of the input buffer for a flow entry, from where the value to match
1707 * and the IPv4 prefix value can be extracted. These locations are then stored
1708 * in the flow profile. When adding flow entries to the associated flow profile,
1709 * these locations can be used to quickly extract the values to create the
1710 * content of a match entry. This function should only be used for fixed-size
1714 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1715 u16 val_loc, u16 pref_loc, u8 pref_sz)
1717 /* For this type of field, the "mask" location is for the prefix value's
1718 * location and the "last" location is for the size of the location of
1721 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1722 pref_loc, (u16)pref_sz);
1726 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1727 * @seg: packet segment the field being set belongs to
1728 * @off: offset of the raw field from the beginning of the segment in bytes
1729 * @len: length of the raw pattern to be matched
1730 * @val_loc: location of the value to match from entry's input buffer
1731 * @mask_loc: location of mask value from entry's input buffer
1733 * This function specifies the offset of the raw field to be match from the
1734 * beginning of the specified packet segment, and the locations, in the form of
1735 * byte offsets from the start of the input buffer for a flow entry, from where
1736 * the value to match and the mask value to be extracted. These locations are
1737 * then stored in the flow profile. When adding flow entries to the associated
1738 * flow profile, these locations can be used to quickly extract the values to
1739 * create the content of a match entry. This function should only be used for
1740 * fixed-size data structures.
1743 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1744 u16 val_loc, u16 mask_loc)
1746 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1747 seg->raws[seg->raws_cnt].off = off;
1748 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1749 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1750 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1751 /* The "last" field is used to store the length of the field */
1752 seg->raws[seg->raws_cnt].info.src.last = len;
1755 /* Overflows of "raws" will be handled as an error condition later in
1756 * the flow when this information is processed.
1761 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1762 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1764 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1765 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1767 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1768 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1769 ICE_FLOW_SEG_HDR_SCTP)
1771 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1772 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1773 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1774 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1777 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1778 * @segs: pointer to the flow field segment(s)
1779 * @hash_fields: fields to be hashed on for the segment(s)
1780 * @flow_hdr: protocol header fields within a packet segment
1782 * Helper function to extract fields from hash bitmap and use flow
1783 * header value to set flow field segment for further use in flow
1784 * profile entry or removal.
1786 static enum ice_status
1787 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1790 u64 val = hash_fields;
1793 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1794 u64 bit = BIT_ULL(i);
1797 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1798 ICE_FLOW_FLD_OFF_INVAL,
1799 ICE_FLOW_FLD_OFF_INVAL,
1800 ICE_FLOW_FLD_OFF_INVAL, false);
1804 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1806 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1807 ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1808 return ICE_ERR_PARAM;
1810 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1811 if (val && !ice_is_pow2(val))
1814 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1815 if (val && !ice_is_pow2(val))
1822 * ice_rem_vsi_rss_list - remove VSI from RSS list
1823 * @hw: pointer to the hardware structure
1824 * @vsi_handle: software VSI handle
1826 * Remove the VSI from all RSS configurations in the list.
1828 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1830 struct ice_rss_cfg *r, *tmp;
1832 if (LIST_EMPTY(&hw->rss_list_head))
1835 ice_acquire_lock(&hw->rss_locks);
1836 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1837 ice_rss_cfg, l_entry) {
1838 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1839 ice_clear_bit(vsi_handle, r->vsis);
1841 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1842 LIST_DEL(&r->l_entry);
1847 ice_release_lock(&hw->rss_locks);
1851 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1852 * @hw: pointer to the hardware structure
1853 * @vsi_handle: software VSI handle
1855 * This function will iterate through all flow profiles and disassociate
1856 * the VSI from that profile. If the flow profile has no VSIs it will
1859 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1861 const enum ice_block blk = ICE_BLK_RSS;
1862 struct ice_flow_prof *p, *t;
1863 enum ice_status status = ICE_SUCCESS;
1865 if (!ice_is_vsi_valid(hw, vsi_handle))
1866 return ICE_ERR_PARAM;
1868 if (LIST_EMPTY(&hw->fl_profs[blk]))
1871 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1872 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1874 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1875 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1879 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1880 status = ice_flow_rem_prof_sync(hw, blk, p);
1886 ice_release_lock(&hw->fl_profs_locks[blk]);
1892 * ice_rem_rss_list - remove RSS configuration from list
1893 * @hw: pointer to the hardware structure
1894 * @vsi_handle: software VSI handle
1895 * @prof: pointer to flow profile
1897 * Assumption: lock has already been acquired for RSS list
1900 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1902 struct ice_rss_cfg *r, *tmp;
1904 /* Search for RSS hash fields associated to the VSI that match the
1905 * hash configurations associated to the flow profile. If found
1906 * remove from the RSS entry list of the VSI context and delete entry.
1908 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1909 ice_rss_cfg, l_entry) {
1910 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1911 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1912 ice_clear_bit(vsi_handle, r->vsis);
1913 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1914 LIST_DEL(&r->l_entry);
1923 * ice_add_rss_list - add RSS configuration to list
1924 * @hw: pointer to the hardware structure
1925 * @vsi_handle: software VSI handle
1926 * @prof: pointer to flow profile
1928 * Assumption: lock has already been acquired for RSS list
1930 static enum ice_status
1931 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1933 struct ice_rss_cfg *r, *rss_cfg;
1935 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1936 ice_rss_cfg, l_entry)
1937 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1938 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1939 ice_set_bit(vsi_handle, r->vsis);
1943 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1945 return ICE_ERR_NO_MEMORY;
1947 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1948 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1949 rss_cfg->symm = prof->cfg.symm;
1950 ice_set_bit(vsi_handle, rss_cfg->vsis);
1952 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1957 #define ICE_FLOW_PROF_HASH_S 0
1958 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1959 #define ICE_FLOW_PROF_HDR_S 32
1960 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1961 #define ICE_FLOW_PROF_ENCAP_S 63
1962 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1964 #define ICE_RSS_OUTER_HEADERS 1
1965 #define ICE_RSS_INNER_HEADERS 2
1967 /* Flow profile ID format:
1968 * [0:31] - Packet match fields
1969 * [32:62] - Protocol header
1970 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1972 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1973 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1974 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1975 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1978 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
1980 u32 s = ((src % 4) << 3); /* byte shift */
1981 u32 v = dst | 0x80; /* value to program */
1982 u8 i = src / 4; /* register index */
1985 reg = rd32(hw, GLQF_HSYMM(prof_id, i));
1986 reg = (reg & ~(0xff << s)) | (v << s);
1987 wr32(hw, GLQF_HSYMM(prof_id, i), reg);
1991 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
1994 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
1997 for (i = 0; i < len; i++) {
1998 ice_rss_config_xor_word(hw, prof_id,
1999 /* Yes, field vector in GLQF_HSYMM and
2000 * GLQF_HINSET is inversed!
2002 fv_last_word - (src + i),
2003 fv_last_word - (dst + i));
2004 ice_rss_config_xor_word(hw, prof_id,
2005 fv_last_word - (dst + i),
2006 fv_last_word - (src + i));
2011 ice_rss_update_symm(struct ice_hw *hw,
2012 struct ice_flow_prof *prof)
2014 struct ice_prof_map *map;
2017 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
2018 prof_id = map->prof_id;
2020 /* clear to default */
2021 for (m = 0; m < 6; m++)
2022 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
2023 if (prof->cfg.symm) {
2024 struct ice_flow_seg_info *seg =
2025 &prof->segs[prof->segs_cnt - 1];
2027 struct ice_flow_seg_xtrct *ipv4_src =
2028 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
2029 struct ice_flow_seg_xtrct *ipv4_dst =
2030 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
2031 struct ice_flow_seg_xtrct *ipv6_src =
2032 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
2033 struct ice_flow_seg_xtrct *ipv6_dst =
2034 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
2036 struct ice_flow_seg_xtrct *tcp_src =
2037 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
2038 struct ice_flow_seg_xtrct *tcp_dst =
2039 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2041 struct ice_flow_seg_xtrct *udp_src =
2042 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2043 struct ice_flow_seg_xtrct *udp_dst =
2044 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2046 struct ice_flow_seg_xtrct *sctp_src =
2047 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2048 struct ice_flow_seg_xtrct *sctp_dst =
2049 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2052 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2053 ice_rss_config_xor(hw, prof_id,
2054 ipv4_src->idx, ipv4_dst->idx, 2);
2057 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2058 ice_rss_config_xor(hw, prof_id,
2059 ipv6_src->idx, ipv6_dst->idx, 8);
2062 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2063 ice_rss_config_xor(hw, prof_id,
2064 tcp_src->idx, tcp_dst->idx, 1);
2067 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2068 ice_rss_config_xor(hw, prof_id,
2069 udp_src->idx, udp_dst->idx, 1);
2072 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2073 ice_rss_config_xor(hw, prof_id,
2074 sctp_src->idx, sctp_dst->idx, 1);
2079 * ice_add_rss_cfg_sync - add an RSS configuration
2080 * @hw: pointer to the hardware structure
2081 * @vsi_handle: software VSI handle
2082 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2083 * @addl_hdrs: protocol header fields
2084 * @segs_cnt: packet segment count
2085 * @symm: symmetric hash enable/disable
2087 * Assumption: lock has already been acquired for RSS list
2089 static enum ice_status
2090 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2091 u32 addl_hdrs, u8 segs_cnt, bool symm)
2093 const enum ice_block blk = ICE_BLK_RSS;
2094 struct ice_flow_prof *prof = NULL;
2095 struct ice_flow_seg_info *segs;
2096 enum ice_status status = ICE_SUCCESS;
2098 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2099 return ICE_ERR_PARAM;
2101 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2104 return ICE_ERR_NO_MEMORY;
2106 /* Construct the packet segment info from the hashed fields */
2107 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2112 /* Search for a flow profile that has matching headers, hash fields
2113 * and has the input VSI associated to it. If found, no further
2114 * operations required and exit.
2116 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2118 ICE_FLOW_FIND_PROF_CHK_FLDS |
2119 ICE_FLOW_FIND_PROF_CHK_VSI);
2121 if (prof->cfg.symm == symm)
2123 prof->cfg.symm = symm;
2127 /* Check if a flow profile exists with the same protocol headers and
2128 * associated with the input VSI. If so disasscociate the VSI from
2129 * this profile. The VSI will be added to a new profile created with
2130 * the protocol header and new hash field configuration.
2132 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2133 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
2135 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2137 ice_rem_rss_list(hw, vsi_handle, prof);
2141 /* Remove profile if it has no VSIs associated */
2142 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
2143 status = ice_flow_rem_prof(hw, blk, prof->id);
2149 /* Search for a profile that has same match fields only. If this
2150 * exists then associate the VSI to this profile.
2152 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2154 ICE_FLOW_FIND_PROF_CHK_FLDS);
2156 if (prof->cfg.symm == symm) {
2157 status = ice_flow_assoc_prof(hw, blk, prof,
2160 status = ice_add_rss_list(hw, vsi_handle,
2163 /* if a profile exist but with different symmetric
2164 * requirement, just return error.
2166 status = ICE_ERR_NOT_SUPPORTED;
2171 /* Create a new flow profile with generated profile and packet
2172 * segment information.
2174 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2175 ICE_FLOW_GEN_PROFID(hashed_flds,
2176 segs[segs_cnt - 1].hdrs,
2178 segs, segs_cnt, NULL, 0, &prof);
2182 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2183 /* If association to a new flow profile failed then this profile can
2187 ice_flow_rem_prof(hw, blk, prof->id);
2191 status = ice_add_rss_list(hw, vsi_handle, prof);
2193 prof->cfg.symm = symm;
2198 ice_rss_update_symm(hw, prof);
2206 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2207 * @hw: pointer to the hardware structure
2208 * @vsi_handle: software VSI handle
2209 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2210 * @addl_hdrs: protocol header fields
2211 * @symm: symmetric hash enable/disable
2213 * This function will generate a flow profile based on fields associated with
2214 * the input fields to hash on, the flow type and use the VSI number to add
2215 * a flow entry to the profile.
2218 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2219 u32 addl_hdrs, bool symm)
2221 enum ice_status status;
2223 if (hashed_flds == ICE_HASH_INVALID ||
2224 !ice_is_vsi_valid(hw, vsi_handle))
2225 return ICE_ERR_PARAM;
2227 ice_acquire_lock(&hw->rss_locks);
2228 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2229 ICE_RSS_OUTER_HEADERS, symm);
2231 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2232 addl_hdrs, ICE_RSS_INNER_HEADERS,
2234 ice_release_lock(&hw->rss_locks);
2240 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2241 * @hw: pointer to the hardware structure
2242 * @vsi_handle: software VSI handle
2243 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2244 * @addl_hdrs: Protocol header fields within a packet segment
2245 * @segs_cnt: packet segment count
2247 * Assumption: lock has already been acquired for RSS list
2249 static enum ice_status
2250 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2251 u32 addl_hdrs, u8 segs_cnt)
2253 const enum ice_block blk = ICE_BLK_RSS;
2254 struct ice_flow_seg_info *segs;
2255 struct ice_flow_prof *prof;
2256 enum ice_status status;
2258 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2261 return ICE_ERR_NO_MEMORY;
2263 /* Construct the packet segment info from the hashed fields */
2264 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2269 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2271 ICE_FLOW_FIND_PROF_CHK_FLDS);
2273 status = ICE_ERR_DOES_NOT_EXIST;
2277 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2281 /* Remove RSS configuration from VSI context before deleting
2284 ice_rem_rss_list(hw, vsi_handle, prof);
2286 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2287 status = ice_flow_rem_prof(hw, blk, prof->id);
2295 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2296 * @hw: pointer to the hardware structure
2297 * @vsi_handle: software VSI handle
2298 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2299 * @addl_hdrs: Protocol header fields within a packet segment
2301 * This function will lookup the flow profile based on the input
2302 * hash field bitmap, iterate through the profile entry list of
2303 * that profile and find entry associated with input VSI to be
2304 * removed. Calls are made to underlying flow apis which will in
2305 * turn build or update buffers for RSS XLT1 section.
2308 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2311 enum ice_status status;
2313 if (hashed_flds == ICE_HASH_INVALID ||
2314 !ice_is_vsi_valid(hw, vsi_handle))
2315 return ICE_ERR_PARAM;
2317 ice_acquire_lock(&hw->rss_locks);
2318 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2319 ICE_RSS_OUTER_HEADERS);
2321 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2322 addl_hdrs, ICE_RSS_INNER_HEADERS);
2323 ice_release_lock(&hw->rss_locks);
2329 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2330 * @hw: pointer to the hardware structure
2331 * @vsi_handle: software VSI handle
2333 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2335 enum ice_status status = ICE_SUCCESS;
2336 struct ice_rss_cfg *r;
2338 if (!ice_is_vsi_valid(hw, vsi_handle))
2339 return ICE_ERR_PARAM;
2341 ice_acquire_lock(&hw->rss_locks);
2342 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2343 ice_rss_cfg, l_entry) {
2344 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2345 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2348 ICE_RSS_OUTER_HEADERS,
2352 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2355 ICE_RSS_INNER_HEADERS,
2361 ice_release_lock(&hw->rss_locks);
2367 * ice_get_rss_cfg - returns hashed fields for the given header types
2368 * @hw: pointer to the hardware structure
2369 * @vsi_handle: software VSI handle
2370 * @hdrs: protocol header type
2372 * This function will return the match fields of the first instance of flow
2373 * profile having the given header types and containing input VSI
2375 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2377 struct ice_rss_cfg *r, *rss_cfg = NULL;
2379 /* verify if the protocol header is non zero and VSI is valid */
2380 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2381 return ICE_HASH_INVALID;
2383 ice_acquire_lock(&hw->rss_locks);
2384 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2385 ice_rss_cfg, l_entry)
2386 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2387 r->packet_hdr == hdrs) {
2391 ice_release_lock(&hw->rss_locks);
2393 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;