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_PPPOE_SESS_ID 2
25 /* Protocol header fields are extracted at the word boundaries as word-sized
26 * values. Specify the displacement value of some non-word-aligned fields needed
27 * to compute the offset of words containing the fields in the corresponding
28 * protocol headers. Displacement values are expressed in number of bits.
30 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP (-4)
31 #define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * BITS_PER_BYTE)
32 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
34 /* Describe properties of a protocol header field */
35 struct ice_flow_field_info {
36 enum ice_flow_seg_hdr hdr;
37 s16 off; /* Offset from start of a protocol header, in bits */
38 u16 size; /* Size of fields in bits */
39 u16 mask; /* 16-bit mask for field */
42 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
44 .off = (_offset_bytes) * BITS_PER_BYTE, \
45 .size = (_size_bytes) * BITS_PER_BYTE, \
49 #define ICE_FLOW_FLD_INFO_MSK(_hdr, _offset_bytes, _size_bytes, _mask) { \
51 .off = (_offset_bytes) * BITS_PER_BYTE, \
52 .size = (_size_bytes) * BITS_PER_BYTE, \
56 /* Table containing properties of supported protocol header fields */
58 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
60 /* ICE_FLOW_FIELD_IDX_ETH_DA */
61 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
62 /* ICE_FLOW_FIELD_IDX_ETH_SA */
63 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
64 /* ICE_FLOW_FIELD_IDX_S_VLAN */
65 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
66 /* ICE_FLOW_FIELD_IDX_C_VLAN */
67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
68 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
71 /* ICE_FLOW_FIELD_IDX_IP_DSCP */
72 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
73 /* ICE_FLOW_FIELD_IDX_IP_TTL */
74 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
75 /* ICE_FLOW_FIELD_IDX_IP_PROT */
76 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
77 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
78 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
79 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
80 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
82 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
83 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
84 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
85 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
87 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
88 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
89 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
90 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
91 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
93 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
95 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
97 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
99 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
102 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
104 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
105 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
106 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
107 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
108 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
109 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
110 /* ICE_FLOW_FIELD_IDX_ARP_OP */
111 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
113 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
114 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
115 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
116 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
118 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
119 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
121 /* ICE_FLOW_FIELD_IDX_GTPC_TEID */
122 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPC_TEID, 12,
123 ICE_FLOW_FLD_SZ_GTP_TEID),
124 /* ICE_FLOW_FIELD_IDX_GTPU_IP_TEID */
125 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_IP, 12,
126 ICE_FLOW_FLD_SZ_GTP_TEID),
127 /* ICE_FLOW_FIELD_IDX_GTPU_UP_TEID */
128 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_UP, 12,
129 ICE_FLOW_FLD_SZ_GTP_TEID),
130 /* ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID */
131 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GTPU_DWN, 12,
132 ICE_FLOW_FLD_SZ_GTP_TEID),
134 /* ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID */
135 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_PPPOE, 2,
136 ICE_FLOW_FLD_SZ_PPPOE_SESS_ID),
139 /* Bitmaps indicating relevant packet types for a particular protocol header
141 * Packet types for packets with an Outer/First/Single MAC header
143 static const u32 ice_ptypes_mac_ofos[] = {
144 0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
145 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
146 0x000B0F0F, 0x00003000, 0x00000000, 0x00000000,
147 0x00000000, 0x00000000, 0x00000000, 0x00000000,
148 0x00000000, 0x00000000, 0x00000000, 0x00000000,
149 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 0x00000000, 0x00000000, 0x00000000, 0x00000000,
151 0x00000000, 0x00000000, 0x00000000, 0x00000000,
154 /* Packet types for packets with an Innermost/Last MAC VLAN header */
155 static const u32 ice_ptypes_macvlan_il[] = {
156 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
157 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000, 0x00000000,
160 0x00000000, 0x00000000, 0x00000000, 0x00000000,
161 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 0x00000000, 0x00000000, 0x00000000, 0x00000000,
163 0x00000000, 0x00000000, 0x00000000, 0x00000000,
166 /* Packet types for packets with an Outer/First/Single IPv4 header */
167 static const u32 ice_ptypes_ipv4_ofos[] = {
168 0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
169 0x00000000, 0x00000000, 0x00000000, 0x00000000,
170 0x0003000F, 0x000FC000, 0x00000000, 0x00000000,
171 0x00000000, 0x00000000, 0x00000000, 0x00000000,
172 0x00000000, 0x00000000, 0x00000000, 0x00000000,
173 0x00000000, 0x00000000, 0x00000000, 0x00000000,
174 0x00000000, 0x00000000, 0x00000000, 0x00000000,
175 0x00000000, 0x00000000, 0x00000000, 0x00000000,
178 /* Packet types for packets with an Innermost/Last IPv4 header */
179 static const u32 ice_ptypes_ipv4_il[] = {
180 0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
181 0x0007700E, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x000FF800, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
184 0x00000000, 0x00000000, 0x00000000, 0x00000000,
185 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 0x00000000, 0x00000000, 0x00000000, 0x00000000,
187 0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 /* Packet types for packets with an Outer/First/Single IPv6 header */
191 static const u32 ice_ptypes_ipv6_ofos[] = {
192 0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
193 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
194 0x00080F00, 0x03F00000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
196 0x00000000, 0x00000000, 0x00000000, 0x00000000,
197 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 0x00000000, 0x00000000, 0x00000000, 0x00000000,
199 0x00000000, 0x00000000, 0x00000000, 0x00000000,
202 /* Packet types for packets with an Innermost/Last IPv6 header */
203 static const u32 ice_ptypes_ipv6_il[] = {
204 0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
205 0x03B80770, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x7FE00000, 0x00000000,
207 0x00000000, 0x00000000, 0x00000000, 0x00000000,
208 0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 0x00000000, 0x00000000, 0x00000000, 0x00000000,
211 0x00000000, 0x00000000, 0x00000000, 0x00000000,
214 /* Packet types for packets with an Outermost/First ARP header */
215 static const u32 ice_ptypes_arp_of[] = {
216 0x00000800, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
220 0x00000000, 0x00000000, 0x00000000, 0x00000000,
221 0x00000000, 0x00000000, 0x00000000, 0x00000000,
222 0x00000000, 0x00000000, 0x00000000, 0x00000000,
223 0x00000000, 0x00000000, 0x00000000, 0x00000000,
226 /* UDP Packet types for non-tunneled packets or tunneled
227 * packets with inner UDP.
229 static const u32 ice_ptypes_udp_il[] = {
230 0x81000000, 0x20204040, 0x04081010, 0x80810102,
231 0x00204040, 0x00000000, 0x00000000, 0x00000000,
232 0x00000000, 0x00410000, 0x10842000, 0x00000000,
233 0x00000000, 0x00000000, 0x00000000, 0x00000000,
234 0x00000000, 0x00000000, 0x00000000, 0x00000000,
235 0x00000000, 0x00000000, 0x00000000, 0x00000000,
236 0x00000000, 0x00000000, 0x00000000, 0x00000000,
237 0x00000000, 0x00000000, 0x00000000, 0x00000000,
240 /* Packet types for packets with an Innermost/Last TCP header */
241 static const u32 ice_ptypes_tcp_il[] = {
242 0x04000000, 0x80810102, 0x10204040, 0x42040408,
243 0x00810102, 0x00000000, 0x00000000, 0x00000000,
244 0x00000000, 0x00820000, 0x21084000, 0x00000000,
245 0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 0x00000000, 0x00000000, 0x00000000, 0x00000000,
247 0x00000000, 0x00000000, 0x00000000, 0x00000000,
248 0x00000000, 0x00000000, 0x00000000, 0x00000000,
249 0x00000000, 0x00000000, 0x00000000, 0x00000000,
252 /* Packet types for packets with an Innermost/Last SCTP header */
253 static const u32 ice_ptypes_sctp_il[] = {
254 0x08000000, 0x01020204, 0x20408081, 0x04080810,
255 0x01020204, 0x00000000, 0x00000000, 0x00000000,
256 0x00000000, 0x00000000, 0x00000000, 0x00000000,
257 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 0x00000000, 0x00000000, 0x00000000, 0x00000000,
259 0x00000000, 0x00000000, 0x00000000, 0x00000000,
260 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261 0x00000000, 0x00000000, 0x00000000, 0x00000000,
264 /* Packet types for packets with an Outermost/First ICMP header */
265 static const u32 ice_ptypes_icmp_of[] = {
266 0x10000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
268 0x00000000, 0x00000000, 0x00000000, 0x00000000,
269 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 0x00000000, 0x00000000, 0x00000000, 0x00000000,
271 0x00000000, 0x00000000, 0x00000000, 0x00000000,
272 0x00000000, 0x00000000, 0x00000000, 0x00000000,
273 0x00000000, 0x00000000, 0x00000000, 0x00000000,
276 /* Packet types for packets with an Innermost/Last ICMP header */
277 static const u32 ice_ptypes_icmp_il[] = {
278 0x00000000, 0x02040408, 0x40810102, 0x08101020,
279 0x02040408, 0x00000000, 0x00000000, 0x00000000,
280 0x00000000, 0x00000000, 0x42108000, 0x00000000,
281 0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 0x00000000, 0x00000000, 0x00000000, 0x00000000,
283 0x00000000, 0x00000000, 0x00000000, 0x00000000,
284 0x00000000, 0x00000000, 0x00000000, 0x00000000,
285 0x00000000, 0x00000000, 0x00000000, 0x00000000,
288 /* Packet types for packets with an Outermost/First GRE header */
289 static const u32 ice_ptypes_gre_of[] = {
290 0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
291 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
292 0x00000000, 0x00000000, 0x00000000, 0x00000000,
293 0x00000000, 0x00000000, 0x00000000, 0x00000000,
294 0x00000000, 0x00000000, 0x00000000, 0x00000000,
295 0x00000000, 0x00000000, 0x00000000, 0x00000000,
296 0x00000000, 0x00000000, 0x00000000, 0x00000000,
297 0x00000000, 0x00000000, 0x00000000, 0x00000000,
300 /* Packet types for packets with an Innermost/Last MAC header */
301 static const u32 ice_ptypes_mac_il[] = {
302 0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
303 0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
304 0x00000000, 0x00000000, 0x00000000, 0x00000000,
305 0x00000000, 0x00000000, 0x00000000, 0x00000000,
306 0x00000000, 0x00000000, 0x00000000, 0x00000000,
307 0x00000000, 0x00000000, 0x00000000, 0x00000000,
308 0x00000000, 0x00000000, 0x00000000, 0x00000000,
309 0x00000000, 0x00000000, 0x00000000, 0x00000000,
312 /* Packet types for GTPC */
313 static const u32 ice_ptypes_gtpc[] = {
314 0x00000000, 0x00000000, 0x00000000, 0x00000000,
315 0x00000000, 0x00000000, 0x00000000, 0x00000000,
316 0x00000000, 0x00000000, 0x00000180, 0x00000000,
317 0x00000000, 0x00000000, 0x00000000, 0x00000000,
318 0x00000000, 0x00000000, 0x00000000, 0x00000000,
319 0x00000000, 0x00000000, 0x00000000, 0x00000000,
320 0x00000000, 0x00000000, 0x00000000, 0x00000000,
321 0x00000000, 0x00000000, 0x00000000, 0x00000000,
324 /* Packet types for GTPC with TEID */
325 static const u32 ice_ptypes_gtpc_tid[] = {
326 0x00000000, 0x00000000, 0x00000000, 0x00000000,
327 0x00000000, 0x00000000, 0x00000000, 0x00000000,
328 0x00000000, 0x00000000, 0x00000060, 0x00000000,
329 0x00000000, 0x00000000, 0x00000000, 0x00000000,
330 0x00000000, 0x00000000, 0x00000000, 0x00000000,
331 0x00000000, 0x00000000, 0x00000000, 0x00000000,
332 0x00000000, 0x00000000, 0x00000000, 0x00000000,
333 0x00000000, 0x00000000, 0x00000000, 0x00000000,
336 /* Packet types for GTPU */
337 static const u32 ice_ptypes_gtpu[] = {
338 0x00000000, 0x00000000, 0x00000000, 0x00000000,
339 0x00000000, 0x00000000, 0x00000000, 0x00000000,
340 0x00000000, 0x00000000, 0x7FFFF800, 0x00000000,
341 0x00000000, 0x00000000, 0x00000000, 0x00000000,
342 0x00000000, 0x00000000, 0x00000000, 0x00000000,
343 0x00000000, 0x00000000, 0x00000000, 0x00000000,
344 0x00000000, 0x00000000, 0x00000000, 0x00000000,
345 0x00000000, 0x00000000, 0x00000000, 0x00000000,
348 /* Packet types for pppoe */
349 static const u32 ice_ptypes_pppoe[] = {
350 0x00000000, 0x00000000, 0x00000000, 0x00000000,
351 0x00000000, 0x00000000, 0x00000000, 0x00000000,
352 0x00000000, 0x03FFF000, 0x00000000, 0x00000000,
353 0x00000000, 0x00000000, 0x00000000, 0x00000000,
354 0x00000000, 0x00000000, 0x00000000, 0x00000000,
355 0x00000000, 0x00000000, 0x00000000, 0x00000000,
356 0x00000000, 0x00000000, 0x00000000, 0x00000000,
357 0x00000000, 0x00000000, 0x00000000, 0x00000000,
360 /* Manage parameters and info. used during the creation of a flow profile */
361 struct ice_flow_prof_params {
363 u16 entry_length; /* # of bytes formatted entry will require */
365 struct ice_flow_prof *prof;
367 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
368 * This will give us the direction flags.
370 struct ice_fv_word es[ICE_MAX_FV_WORDS];
371 u16 mask[ICE_MAX_FV_WORDS];
372 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
375 #define ICE_FLOW_RSS_HDRS_INNER_MASK \
376 (ICE_FLOW_SEG_HDR_PPPOE | ICE_FLOW_SEG_HDR_GTPC | \
377 ICE_FLOW_SEG_HDR_GTPC_TEID | ICE_FLOW_SEG_HDR_GTPU)
379 #define ICE_FLOW_SEG_HDRS_L2_MASK \
380 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
381 #define ICE_FLOW_SEG_HDRS_L3_MASK \
382 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | \
383 ICE_FLOW_SEG_HDR_ARP)
384 #define ICE_FLOW_SEG_HDRS_L4_MASK \
385 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
386 ICE_FLOW_SEG_HDR_SCTP)
389 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
390 * @segs: array of one or more packet segments that describe the flow
391 * @segs_cnt: number of packet segments provided
393 static enum ice_status
394 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
398 for (i = 0; i < segs_cnt; i++) {
399 /* Multiple L3 headers */
400 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
401 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
402 return ICE_ERR_PARAM;
404 /* Multiple L4 headers */
405 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
406 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
407 return ICE_ERR_PARAM;
413 /* Sizes of fixed known protocol headers without header options */
414 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
415 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
416 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
417 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
418 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
419 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
420 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
421 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
422 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
425 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
426 * @params: information about the flow to be processed
427 * @seg: index of packet segment whose header size is to be determined
429 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
434 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
435 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
438 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
439 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
440 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
441 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
442 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
443 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
444 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
445 /* A L3 header is required if L4 is specified */
449 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
450 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
451 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
452 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
453 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
454 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
455 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
456 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
462 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
463 * @params: information about the flow to be processed
465 * This function identifies the packet types associated with the protocol
466 * headers being present in packet segments of the specified flow profile.
468 static enum ice_status
469 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
471 struct ice_flow_prof *prof;
474 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
479 for (i = 0; i < params->prof->segs_cnt; i++) {
480 const ice_bitmap_t *src;
483 hdrs = prof->segs[i].hdrs;
485 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
486 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
487 (const ice_bitmap_t *)ice_ptypes_mac_il;
488 ice_and_bitmap(params->ptypes, params->ptypes, src,
492 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
493 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
494 ice_and_bitmap(params->ptypes, params->ptypes, src,
498 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
499 ice_and_bitmap(params->ptypes, params->ptypes,
500 (const ice_bitmap_t *)ice_ptypes_arp_of,
504 if (hdrs & ICE_FLOW_SEG_HDR_PPPOE) {
505 src = (const ice_bitmap_t *)ice_ptypes_pppoe;
506 ice_and_bitmap(params->ptypes, params->ptypes, src,
510 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
511 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
512 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
513 ice_and_bitmap(params->ptypes, params->ptypes, src,
515 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
516 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
517 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
518 ice_and_bitmap(params->ptypes, params->ptypes, src,
522 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
523 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
524 (const ice_bitmap_t *)ice_ptypes_icmp_il;
525 ice_and_bitmap(params->ptypes, params->ptypes, src,
527 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
528 src = (const ice_bitmap_t *)ice_ptypes_udp_il;
529 ice_and_bitmap(params->ptypes, params->ptypes, src,
531 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
532 ice_and_bitmap(params->ptypes, params->ptypes,
533 (const ice_bitmap_t *)ice_ptypes_tcp_il,
535 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
536 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
537 ice_and_bitmap(params->ptypes, params->ptypes, src,
539 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
541 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
542 ice_and_bitmap(params->ptypes, params->ptypes,
543 src, ICE_FLOW_PTYPE_MAX);
545 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC) {
547 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
548 ice_and_bitmap(params->ptypes, params->ptypes,
549 src, ICE_FLOW_PTYPE_MAX);
551 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
553 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
554 ice_and_bitmap(params->ptypes, params->ptypes,
555 src, ICE_FLOW_PTYPE_MAX);
557 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
559 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
560 ice_and_bitmap(params->ptypes, params->ptypes,
561 src, ICE_FLOW_PTYPE_MAX);
570 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
571 * @hw: pointer to the HW struct
572 * @params: information about the flow to be processed
573 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
575 * This function will allocate an extraction sequence entries for a DWORD size
576 * chunk of the packet flags.
578 static enum ice_status
579 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
580 struct ice_flow_prof_params *params,
581 enum ice_flex_mdid_pkt_flags flags)
583 u8 fv_words = hw->blk[params->blk].es.fvw;
586 /* Make sure the number of extraction sequence entries required does not
587 * exceed the block's capacity.
589 if (params->es_cnt >= fv_words)
590 return ICE_ERR_MAX_LIMIT;
592 /* some blocks require a reversed field vector layout */
593 if (hw->blk[params->blk].es.reverse)
594 idx = fv_words - params->es_cnt - 1;
596 idx = params->es_cnt;
598 params->es[idx].prot_id = ICE_PROT_META_ID;
599 params->es[idx].off = flags;
606 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
607 * @hw: pointer to the HW struct
608 * @params: information about the flow to be processed
609 * @seg: packet segment index of the field to be extracted
610 * @fld: ID of field to be extracted
612 * This function determines the protocol ID, offset, and size of the given
613 * field. It then allocates one or more extraction sequence entries for the
614 * given field, and fill the entries with protocol ID and offset information.
616 static enum ice_status
617 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
618 u8 seg, enum ice_flow_field fld)
620 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
621 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
622 u8 fv_words = hw->blk[params->blk].es.fvw;
623 struct ice_flow_fld_info *flds;
624 u16 cnt, ese_bits, i;
629 flds = params->prof->segs[seg].fields;
632 case ICE_FLOW_FIELD_IDX_ETH_DA:
633 case ICE_FLOW_FIELD_IDX_ETH_SA:
634 case ICE_FLOW_FIELD_IDX_S_VLAN:
635 case ICE_FLOW_FIELD_IDX_C_VLAN:
636 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
638 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
639 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
641 case ICE_FLOW_FIELD_IDX_IP_DSCP:
642 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
643 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
645 case ICE_FLOW_FIELD_IDX_IP_TTL:
646 case ICE_FLOW_FIELD_IDX_IP_PROT:
647 /* Some fields are located at different offsets in IPv4 and
650 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
651 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
653 /* TTL and PROT share the same extraction seq. entry.
654 * Each is considered a sibling to the other in term
655 * sharing the same extraction sequence entry.
657 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
658 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
659 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
660 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
661 } else if (params->prof->segs[seg].hdrs &
662 ICE_FLOW_SEG_HDR_IPV6) {
663 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
665 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
666 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
667 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
668 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
671 case ICE_FLOW_FIELD_IDX_IPV4_SA:
672 case ICE_FLOW_FIELD_IDX_IPV4_DA:
673 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
675 case ICE_FLOW_FIELD_IDX_IPV6_SA:
676 case ICE_FLOW_FIELD_IDX_IPV6_DA:
677 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
679 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
680 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
681 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
682 prot_id = ICE_PROT_TCP_IL;
684 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
685 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
686 prot_id = ICE_PROT_UDP_IL_OR_S;
688 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
689 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
690 prot_id = ICE_PROT_SCTP_IL;
692 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
693 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
694 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
695 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
696 /* GTP is accessed through UDP OF protocol */
697 prot_id = ICE_PROT_UDP_OF;
699 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
700 prot_id = ICE_PROT_PPPOE;
702 case ICE_FLOW_FIELD_IDX_ARP_SIP:
703 case ICE_FLOW_FIELD_IDX_ARP_DIP:
704 case ICE_FLOW_FIELD_IDX_ARP_SHA:
705 case ICE_FLOW_FIELD_IDX_ARP_DHA:
706 case ICE_FLOW_FIELD_IDX_ARP_OP:
707 prot_id = ICE_PROT_ARP_OF;
709 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
710 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
711 /* ICMP type and code share the same extraction seq. entry */
712 prot_id = (params->prof->segs[seg].hdrs &
713 ICE_FLOW_SEG_HDR_IPV4) ?
714 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
715 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
716 ICE_FLOW_FIELD_IDX_ICMP_CODE :
717 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
719 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
720 prot_id = ICE_PROT_GRE_OF;
723 return ICE_ERR_NOT_IMPL;
726 /* Each extraction sequence entry is a word in size, and extracts a
727 * word-aligned offset from a protocol header.
729 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
731 flds[fld].xtrct.prot_id = prot_id;
732 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
733 ICE_FLOW_FV_EXTRACT_SZ;
734 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
735 flds[fld].xtrct.idx = params->es_cnt;
737 /* Adjust the next field-entry index after accommodating the number of
738 * entries this field consumes
740 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
741 ice_flds_info[fld].size, ese_bits);
743 /* Fill in the extraction sequence entries needed for this field */
744 off = flds[fld].xtrct.off;
745 mask = ice_flds_info[fld].mask;
746 for (i = 0; i < cnt; i++) {
747 /* Only consume an extraction sequence entry if there is no
748 * sibling field associated with this field or the sibling entry
749 * already extracts the word shared with this field.
751 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
752 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
753 flds[sib].xtrct.off != off) {
756 /* Make sure the number of extraction sequence required
757 * does not exceed the block's capability
759 if (params->es_cnt >= fv_words)
760 return ICE_ERR_MAX_LIMIT;
762 /* some blocks require a reversed field vector layout */
763 if (hw->blk[params->blk].es.reverse)
764 idx = fv_words - params->es_cnt - 1;
766 idx = params->es_cnt;
768 params->es[idx].prot_id = prot_id;
769 params->es[idx].off = off;
770 params->mask[idx] = mask;
774 off += ICE_FLOW_FV_EXTRACT_SZ;
781 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
782 * @hw: pointer to the HW struct
783 * @params: information about the flow to be processed
784 * @seg: index of packet segment whose raw fields are to be be extracted
786 static enum ice_status
787 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
793 if (!params->prof->segs[seg].raws_cnt)
796 if (params->prof->segs[seg].raws_cnt >
797 ARRAY_SIZE(params->prof->segs[seg].raws))
798 return ICE_ERR_MAX_LIMIT;
800 /* Offsets within the segment headers are not supported */
801 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
803 return ICE_ERR_PARAM;
805 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
806 struct ice_flow_seg_fld_raw *raw;
809 raw = ¶ms->prof->segs[seg].raws[i];
811 /* Only support matching raw fields in the payload */
812 if (raw->off < hdrs_sz)
813 return ICE_ERR_PARAM;
815 /* Convert the segment-relative offset into payload-relative
818 off = raw->off - hdrs_sz;
820 /* Storing extraction information */
821 raw->info.xtrct.prot_id = ICE_PROT_PAY;
822 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
823 ICE_FLOW_FV_EXTRACT_SZ;
824 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
826 raw->info.xtrct.idx = params->es_cnt;
828 /* Determine the number of field vector entries this raw field
831 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
832 (raw->info.src.last * BITS_PER_BYTE),
833 (ICE_FLOW_FV_EXTRACT_SZ *
835 off = raw->info.xtrct.off;
836 for (j = 0; j < cnt; j++) {
837 /* Make sure the number of extraction sequence required
838 * does not exceed the block's capability
840 if (params->es_cnt >= hw->blk[params->blk].es.count ||
841 params->es_cnt >= ICE_MAX_FV_WORDS)
842 return ICE_ERR_MAX_LIMIT;
844 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
845 params->es[params->es_cnt].off = off;
847 off += ICE_FLOW_FV_EXTRACT_SZ;
855 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
856 * @hw: pointer to the HW struct
857 * @params: information about the flow to be processed
859 * This function iterates through all matched fields in the given segments, and
860 * creates an extraction sequence for the fields.
862 static enum ice_status
863 ice_flow_create_xtrct_seq(struct ice_hw *hw,
864 struct ice_flow_prof_params *params)
866 enum ice_status status = ICE_SUCCESS;
869 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
872 if (params->blk == ICE_BLK_ACL)
873 ice_flow_xtract_pkt_flags(hw, params,
874 ICE_RX_MDID_PKT_FLAGS_15_0);
876 for (i = 0; i < params->prof->segs_cnt; i++) {
877 u64 match = params->prof->segs[i].match;
880 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
881 const u64 bit = BIT_ULL(j);
884 status = ice_flow_xtract_fld
885 (hw, params, i, (enum ice_flow_field)j);
892 /* Process raw matching bytes */
893 status = ice_flow_xtract_raws(hw, params, i);
902 * ice_flow_proc_segs - process all packet segments associated with a profile
903 * @hw: pointer to the HW struct
904 * @params: information about the flow to be processed
906 static enum ice_status
907 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
909 enum ice_status status;
911 status = ice_flow_proc_seg_hdrs(params);
915 status = ice_flow_create_xtrct_seq(hw, params);
919 switch (params->blk) {
921 /* Only header information is provided for RSS configuration.
922 * No further processing is needed.
924 status = ICE_SUCCESS;
927 status = ICE_SUCCESS;
931 return ICE_ERR_NOT_IMPL;
937 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
938 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
939 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
942 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
943 * @hw: pointer to the HW struct
944 * @blk: classification stage
945 * @dir: flow direction
946 * @segs: array of one or more packet segments that describe the flow
947 * @segs_cnt: number of packet segments provided
948 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
949 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
951 static struct ice_flow_prof *
952 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
953 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
954 u8 segs_cnt, u16 vsi_handle, u32 conds)
956 struct ice_flow_prof *p, *prof = NULL;
958 ice_acquire_lock(&hw->fl_profs_locks[blk]);
959 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
960 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
961 segs_cnt && segs_cnt == p->segs_cnt) {
964 /* Check for profile-VSI association if specified */
965 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
966 ice_is_vsi_valid(hw, vsi_handle) &&
967 !ice_is_bit_set(p->vsis, vsi_handle))
970 /* Protocol headers must be checked. Matched fields are
971 * checked if specified.
973 for (i = 0; i < segs_cnt; i++)
974 if (segs[i].hdrs != p->segs[i].hdrs ||
975 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
976 segs[i].match != p->segs[i].match))
979 /* A match is found if all segments are matched */
986 ice_release_lock(&hw->fl_profs_locks[blk]);
992 * ice_flow_find_prof - Look up a profile matching headers and matched fields
993 * @hw: pointer to the HW struct
994 * @blk: classification stage
995 * @dir: flow direction
996 * @segs: array of one or more packet segments that describe the flow
997 * @segs_cnt: number of packet segments provided
1000 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1001 struct ice_flow_seg_info *segs, u8 segs_cnt)
1003 struct ice_flow_prof *p;
1005 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1006 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1008 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1012 * ice_flow_find_prof_id - Look up a profile with given profile ID
1013 * @hw: pointer to the HW struct
1014 * @blk: classification stage
1015 * @prof_id: unique ID to identify this flow profile
1017 static struct ice_flow_prof *
1018 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1020 struct ice_flow_prof *p;
1022 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1023 if (p->id == prof_id)
1031 * ice_dealloc_flow_entry - Deallocate flow entry memory
1032 * @hw: pointer to the HW struct
1033 * @entry: flow entry to be removed
1036 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1042 ice_free(hw, entry->entry);
1045 ice_free(hw, entry->acts);
1047 entry->acts_cnt = 0;
1050 ice_free(hw, entry);
1054 * ice_flow_rem_entry_sync - Remove a flow entry
1055 * @hw: pointer to the HW struct
1056 * @entry: flow entry to be removed
1058 static enum ice_status
1059 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1062 return ICE_ERR_BAD_PTR;
1064 LIST_DEL(&entry->l_entry);
1066 ice_dealloc_flow_entry(hw, entry);
1072 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1073 * @hw: pointer to the HW struct
1074 * @blk: classification stage
1075 * @dir: flow direction
1076 * @prof_id: unique ID to identify this flow profile
1077 * @segs: array of one or more packet segments that describe the flow
1078 * @segs_cnt: number of packet segments provided
1079 * @acts: array of default actions
1080 * @acts_cnt: number of default actions
1081 * @prof: stores the returned flow profile added
1083 * Assumption: the caller has acquired the lock to the profile list
1085 static enum ice_status
1086 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1087 enum ice_flow_dir dir, u64 prof_id,
1088 struct ice_flow_seg_info *segs, u8 segs_cnt,
1089 struct ice_flow_action *acts, u8 acts_cnt,
1090 struct ice_flow_prof **prof)
1092 struct ice_flow_prof_params params;
1093 enum ice_status status = ICE_SUCCESS;
1096 if (!prof || (acts_cnt && !acts))
1097 return ICE_ERR_BAD_PTR;
1099 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1100 params.prof = (struct ice_flow_prof *)
1101 ice_malloc(hw, sizeof(*params.prof));
1103 return ICE_ERR_NO_MEMORY;
1105 /* initialize extraction sequence to all invalid (0xff) */
1106 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1107 params.es[i].prot_id = ICE_PROT_INVALID;
1108 params.es[i].off = ICE_FV_OFFSET_INVAL;
1112 params.prof->id = prof_id;
1113 params.prof->dir = dir;
1114 params.prof->segs_cnt = segs_cnt;
1116 /* Make a copy of the segments that need to be persistent in the flow
1119 for (i = 0; i < segs_cnt; i++)
1120 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1121 ICE_NONDMA_TO_NONDMA);
1123 /* Make a copy of the actions that need to be persistent in the flow
1127 params.prof->acts = (struct ice_flow_action *)
1128 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1129 ICE_NONDMA_TO_NONDMA);
1131 if (!params.prof->acts) {
1132 status = ICE_ERR_NO_MEMORY;
1137 status = ice_flow_proc_segs(hw, ¶ms);
1139 ice_debug(hw, ICE_DBG_FLOW,
1140 "Error processing a flow's packet segments\n");
1144 /* Add a HW profile for this flow profile */
1145 status = ice_add_prof_with_mask(hw, blk, prof_id, (u8 *)params.ptypes,
1146 params.es, params.mask);
1148 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1152 INIT_LIST_HEAD(¶ms.prof->entries);
1153 ice_init_lock(¶ms.prof->entries_lock);
1154 *prof = params.prof;
1158 if (params.prof->acts)
1159 ice_free(hw, params.prof->acts);
1160 ice_free(hw, params.prof);
1167 * ice_flow_rem_prof_sync - remove a flow profile
1168 * @hw: pointer to the hardware structure
1169 * @blk: classification stage
1170 * @prof: pointer to flow profile to remove
1172 * Assumption: the caller has acquired the lock to the profile list
1174 static enum ice_status
1175 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1176 struct ice_flow_prof *prof)
1178 enum ice_status status = ICE_SUCCESS;
1180 /* Remove all remaining flow entries before removing the flow profile */
1181 if (!LIST_EMPTY(&prof->entries)) {
1182 struct ice_flow_entry *e, *t;
1184 ice_acquire_lock(&prof->entries_lock);
1186 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1188 status = ice_flow_rem_entry_sync(hw, e);
1193 ice_release_lock(&prof->entries_lock);
1196 /* Remove all hardware profiles associated with this flow profile */
1197 status = ice_rem_prof(hw, blk, prof->id);
1199 LIST_DEL(&prof->l_entry);
1200 ice_destroy_lock(&prof->entries_lock);
1202 ice_free(hw, prof->acts);
1210 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1211 * @hw: pointer to the hardware structure
1212 * @blk: classification stage
1213 * @vsi_handle: software VSI handle
1214 * @vsig: target VSI group
1216 * Assumption: the caller has already verified that the VSI to
1217 * be added has the same characteristics as the VSIG and will
1218 * thereby have access to all resources added to that VSIG.
1221 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1224 enum ice_status status;
1226 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1227 return ICE_ERR_PARAM;
1229 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1230 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1232 ice_release_lock(&hw->fl_profs_locks[blk]);
1238 * ice_flow_assoc_prof - associate a VSI with a flow profile
1239 * @hw: pointer to the hardware structure
1240 * @blk: classification stage
1241 * @prof: pointer to flow profile
1242 * @vsi_handle: software VSI handle
1244 * Assumption: the caller has acquired the lock to the profile list
1245 * and the software VSI handle has been validated
1247 static enum ice_status
1248 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1249 struct ice_flow_prof *prof, u16 vsi_handle)
1251 enum ice_status status = ICE_SUCCESS;
1253 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1254 status = ice_add_prof_id_flow(hw, blk,
1255 ice_get_hw_vsi_num(hw,
1259 ice_set_bit(vsi_handle, prof->vsis);
1261 ice_debug(hw, ICE_DBG_FLOW,
1262 "HW profile add failed, %d\n",
1270 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1271 * @hw: pointer to the hardware structure
1272 * @blk: classification stage
1273 * @prof: pointer to flow profile
1274 * @vsi_handle: software VSI handle
1276 * Assumption: the caller has acquired the lock to the profile list
1277 * and the software VSI handle has been validated
1279 static enum ice_status
1280 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1281 struct ice_flow_prof *prof, u16 vsi_handle)
1283 enum ice_status status = ICE_SUCCESS;
1285 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1286 status = ice_rem_prof_id_flow(hw, blk,
1287 ice_get_hw_vsi_num(hw,
1291 ice_clear_bit(vsi_handle, prof->vsis);
1293 ice_debug(hw, ICE_DBG_FLOW,
1294 "HW profile remove failed, %d\n",
1302 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1303 * @hw: pointer to the HW struct
1304 * @blk: classification stage
1305 * @dir: flow direction
1306 * @prof_id: unique ID to identify this flow profile
1307 * @segs: array of one or more packet segments that describe the flow
1308 * @segs_cnt: number of packet segments provided
1309 * @acts: array of default actions
1310 * @acts_cnt: number of default actions
1311 * @prof: stores the returned flow profile added
1314 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1315 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1316 struct ice_flow_action *acts, u8 acts_cnt,
1317 struct ice_flow_prof **prof)
1319 enum ice_status status;
1321 if (segs_cnt > ICE_FLOW_SEG_MAX)
1322 return ICE_ERR_MAX_LIMIT;
1325 return ICE_ERR_PARAM;
1328 return ICE_ERR_BAD_PTR;
1330 status = ice_flow_val_hdrs(segs, segs_cnt);
1334 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1336 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1337 acts, acts_cnt, prof);
1339 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1341 ice_release_lock(&hw->fl_profs_locks[blk]);
1347 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1348 * @hw: pointer to the HW struct
1349 * @blk: the block for which the flow profile is to be removed
1350 * @prof_id: unique ID of the flow profile to be removed
1353 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1355 struct ice_flow_prof *prof;
1356 enum ice_status status;
1358 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1360 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1362 status = ICE_ERR_DOES_NOT_EXIST;
1366 /* prof becomes invalid after the call */
1367 status = ice_flow_rem_prof_sync(hw, blk, prof);
1370 ice_release_lock(&hw->fl_profs_locks[blk]);
1376 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1377 * @hw: pointer to the HW struct
1378 * @blk: classification stage
1379 * @prof_id: the profile ID handle
1380 * @hw_prof_id: pointer to variable to receive the HW profile ID
1383 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1386 struct ice_prof_map *map;
1388 map = ice_search_prof_id(hw, blk, prof_id);
1390 *hw_prof_id = map->prof_id;
1394 return ICE_ERR_DOES_NOT_EXIST;
1398 * ice_flow_find_entry - look for a flow entry using its unique ID
1399 * @hw: pointer to the HW struct
1400 * @blk: classification stage
1401 * @entry_id: unique ID to identify this flow entry
1403 * This function looks for the flow entry with the specified unique ID in all
1404 * flow profiles of the specified classification stage. If the entry is found,
1405 * and it returns the handle to the flow entry. Otherwise, it returns
1406 * ICE_FLOW_ENTRY_ID_INVAL.
1408 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1410 struct ice_flow_entry *found = NULL;
1411 struct ice_flow_prof *p;
1413 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1415 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1416 struct ice_flow_entry *e;
1418 ice_acquire_lock(&p->entries_lock);
1419 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1420 if (e->id == entry_id) {
1424 ice_release_lock(&p->entries_lock);
1430 ice_release_lock(&hw->fl_profs_locks[blk]);
1432 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1436 * ice_flow_add_entry - Add a flow entry
1437 * @hw: pointer to the HW struct
1438 * @blk: classification stage
1439 * @prof_id: ID of the profile to add a new flow entry to
1440 * @entry_id: unique ID to identify this flow entry
1441 * @vsi_handle: software VSI handle for the flow entry
1442 * @prio: priority of the flow entry
1443 * @data: pointer to a data buffer containing flow entry's match values/masks
1444 * @acts: arrays of actions to be performed on a match
1445 * @acts_cnt: number of actions
1446 * @entry_h: pointer to buffer that receives the new flow entry's handle
1449 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1450 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1451 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1454 struct ice_flow_prof *prof = NULL;
1455 struct ice_flow_entry *e = NULL;
1456 enum ice_status status = ICE_SUCCESS;
1458 if (acts_cnt && !acts)
1459 return ICE_ERR_PARAM;
1461 /* No flow entry data is expected for RSS */
1462 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1463 return ICE_ERR_BAD_PTR;
1465 if (!ice_is_vsi_valid(hw, vsi_handle))
1466 return ICE_ERR_PARAM;
1468 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1470 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1472 status = ICE_ERR_DOES_NOT_EXIST;
1474 /* Allocate memory for the entry being added and associate
1475 * the VSI to the found flow profile
1477 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1479 status = ICE_ERR_NO_MEMORY;
1481 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1484 ice_release_lock(&hw->fl_profs_locks[blk]);
1489 e->vsi_handle = vsi_handle;
1495 /* RSS will add only one entry per VSI per profile */
1502 status = ICE_ERR_NOT_IMPL;
1506 if (blk != ICE_BLK_ACL) {
1507 /* ACL will handle the entry management */
1508 ice_acquire_lock(&prof->entries_lock);
1509 LIST_ADD(&e->l_entry, &prof->entries);
1510 ice_release_lock(&prof->entries_lock);
1513 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1518 ice_free(hw, e->entry);
1526 * ice_flow_rem_entry - Remove a flow entry
1527 * @hw: pointer to the HW struct
1528 * @entry_h: handle to the flow entry to be removed
1530 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1532 struct ice_flow_entry *entry;
1533 struct ice_flow_prof *prof;
1534 enum ice_status status;
1536 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1537 return ICE_ERR_PARAM;
1539 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1541 /* Retain the pointer to the flow profile as the entry will be freed */
1544 ice_acquire_lock(&prof->entries_lock);
1545 status = ice_flow_rem_entry_sync(hw, entry);
1546 ice_release_lock(&prof->entries_lock);
1552 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1553 * @seg: packet segment the field being set belongs to
1554 * @fld: field to be set
1555 * @type: type of the field
1556 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1557 * entry's input buffer
1558 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1560 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1561 * entry's input buffer
1563 * This helper function stores information of a field being matched, including
1564 * the type of the field and the locations of the value to match, the mask, and
1565 * and the upper-bound value in the start of the input buffer for a flow entry.
1566 * This function should only be used for fixed-size data structures.
1568 * This function also opportunistically determines the protocol headers to be
1569 * present based on the fields being set. Some fields cannot be used alone to
1570 * determine the protocol headers present. Sometimes, fields for particular
1571 * protocol headers are not matched. In those cases, the protocol headers
1572 * must be explicitly set.
1575 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1576 enum ice_flow_fld_match_type type, u16 val_loc,
1577 u16 mask_loc, u16 last_loc)
1579 u64 bit = BIT_ULL(fld);
1582 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1585 seg->fields[fld].type = type;
1586 seg->fields[fld].src.val = val_loc;
1587 seg->fields[fld].src.mask = mask_loc;
1588 seg->fields[fld].src.last = last_loc;
1590 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1594 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1595 * @seg: packet segment the field being set belongs to
1596 * @fld: field to be set
1597 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1598 * entry's input buffer
1599 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1601 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1602 * entry's input buffer
1603 * @range: indicate if field being matched is to be in a range
1605 * This function specifies the locations, in the form of byte offsets from the
1606 * start of the input buffer for a flow entry, from where the value to match,
1607 * the mask value, and upper value can be extracted. These locations are then
1608 * stored in the flow profile. When adding a flow entry associated with the
1609 * flow profile, these locations will be used to quickly extract the values and
1610 * create the content of a match entry. This function should only be used for
1611 * fixed-size data structures.
1614 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1615 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1617 enum ice_flow_fld_match_type t = range ?
1618 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1620 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1624 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1625 * @seg: packet segment the field being set belongs to
1626 * @fld: field to be set
1627 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1628 * entry's input buffer
1629 * @pref_loc: location of prefix value from entry's input buffer
1630 * @pref_sz: size of the location holding the prefix value
1632 * This function specifies the locations, in the form of byte offsets from the
1633 * start of the input buffer for a flow entry, from where the value to match
1634 * and the IPv4 prefix value can be extracted. These locations are then stored
1635 * in the flow profile. When adding flow entries to the associated flow profile,
1636 * these locations can be used to quickly extract the values to create the
1637 * content of a match entry. This function should only be used for fixed-size
1641 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1642 u16 val_loc, u16 pref_loc, u8 pref_sz)
1644 /* For this type of field, the "mask" location is for the prefix value's
1645 * location and the "last" location is for the size of the location of
1648 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1649 pref_loc, (u16)pref_sz);
1653 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1654 * @seg: packet segment the field being set belongs to
1655 * @off: offset of the raw field from the beginning of the segment in bytes
1656 * @len: length of the raw pattern to be matched
1657 * @val_loc: location of the value to match from entry's input buffer
1658 * @mask_loc: location of mask value from entry's input buffer
1660 * This function specifies the offset of the raw field to be match from the
1661 * beginning of the specified packet segment, and the locations, in the form of
1662 * byte offsets from the start of the input buffer for a flow entry, from where
1663 * the value to match and the mask value to be extracted. These locations are
1664 * then stored in the flow profile. When adding flow entries to the associated
1665 * flow profile, these locations can be used to quickly extract the values to
1666 * create the content of a match entry. This function should only be used for
1667 * fixed-size data structures.
1670 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1671 u16 val_loc, u16 mask_loc)
1673 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1674 seg->raws[seg->raws_cnt].off = off;
1675 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1676 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1677 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1678 /* The "last" field is used to store the length of the field */
1679 seg->raws[seg->raws_cnt].info.src.last = len;
1682 /* Overflows of "raws" will be handled as an error condition later in
1683 * the flow when this information is processed.
1688 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1689 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1691 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1692 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1694 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1695 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1696 ICE_FLOW_SEG_HDR_SCTP)
1698 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1699 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1700 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1701 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1704 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1705 * @segs: pointer to the flow field segment(s)
1706 * @hash_fields: fields to be hashed on for the segment(s)
1707 * @flow_hdr: protocol header fields within a packet segment
1709 * Helper function to extract fields from hash bitmap and use flow
1710 * header value to set flow field segment for further use in flow
1711 * profile entry or removal.
1713 static enum ice_status
1714 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1717 u64 val = hash_fields;
1720 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1721 u64 bit = BIT_ULL(i);
1724 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1725 ICE_FLOW_FLD_OFF_INVAL,
1726 ICE_FLOW_FLD_OFF_INVAL,
1727 ICE_FLOW_FLD_OFF_INVAL, false);
1731 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1733 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1734 ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1735 return ICE_ERR_PARAM;
1737 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1738 if (val && !ice_is_pow2(val))
1741 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1742 if (val && !ice_is_pow2(val))
1749 * ice_rem_vsi_rss_list - remove VSI from RSS list
1750 * @hw: pointer to the hardware structure
1751 * @vsi_handle: software VSI handle
1753 * Remove the VSI from all RSS configurations in the list.
1755 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1757 struct ice_rss_cfg *r, *tmp;
1759 if (LIST_EMPTY(&hw->rss_list_head))
1762 ice_acquire_lock(&hw->rss_locks);
1763 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1764 ice_rss_cfg, l_entry) {
1765 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1766 ice_clear_bit(vsi_handle, r->vsis);
1768 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1769 LIST_DEL(&r->l_entry);
1774 ice_release_lock(&hw->rss_locks);
1778 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1779 * @hw: pointer to the hardware structure
1780 * @vsi_handle: software VSI handle
1782 * This function will iterate through all flow profiles and disassociate
1783 * the VSI from that profile. If the flow profile has no VSIs it will
1786 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1788 const enum ice_block blk = ICE_BLK_RSS;
1789 struct ice_flow_prof *p, *t;
1790 enum ice_status status = ICE_SUCCESS;
1792 if (!ice_is_vsi_valid(hw, vsi_handle))
1793 return ICE_ERR_PARAM;
1795 if (LIST_EMPTY(&hw->fl_profs[blk]))
1798 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1799 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1801 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1802 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1806 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1807 status = ice_flow_rem_prof_sync(hw, blk, p);
1813 ice_release_lock(&hw->fl_profs_locks[blk]);
1819 * ice_rem_rss_list - remove RSS configuration from list
1820 * @hw: pointer to the hardware structure
1821 * @vsi_handle: software VSI handle
1822 * @prof: pointer to flow profile
1824 * Assumption: lock has already been acquired for RSS list
1827 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1829 struct ice_rss_cfg *r, *tmp;
1831 /* Search for RSS hash fields associated to the VSI that match the
1832 * hash configurations associated to the flow profile. If found
1833 * remove from the RSS entry list of the VSI context and delete entry.
1835 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1836 ice_rss_cfg, l_entry) {
1837 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1838 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1839 ice_clear_bit(vsi_handle, r->vsis);
1840 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1841 LIST_DEL(&r->l_entry);
1850 * ice_add_rss_list - add RSS configuration to list
1851 * @hw: pointer to the hardware structure
1852 * @vsi_handle: software VSI handle
1853 * @prof: pointer to flow profile
1855 * Assumption: lock has already been acquired for RSS list
1857 static enum ice_status
1858 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1860 struct ice_rss_cfg *r, *rss_cfg;
1862 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1863 ice_rss_cfg, l_entry)
1864 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1865 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1866 ice_set_bit(vsi_handle, r->vsis);
1870 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1872 return ICE_ERR_NO_MEMORY;
1874 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1875 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1876 ice_set_bit(vsi_handle, rss_cfg->vsis);
1878 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1883 #define ICE_FLOW_PROF_HASH_S 0
1884 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1885 #define ICE_FLOW_PROF_HDR_S 32
1886 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1887 #define ICE_FLOW_PROF_ENCAP_S 63
1888 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1890 #define ICE_RSS_OUTER_HEADERS 1
1891 #define ICE_RSS_INNER_HEADERS 2
1893 /* Flow profile ID format:
1894 * [0:31] - Packet match fields
1895 * [32:62] - Protocol header
1896 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1898 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1899 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1900 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1901 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1904 * ice_add_rss_cfg_sync - add an RSS configuration
1905 * @hw: pointer to the hardware structure
1906 * @vsi_handle: software VSI handle
1907 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1908 * @addl_hdrs: protocol header fields
1909 * @segs_cnt: packet segment count
1911 * Assumption: lock has already been acquired for RSS list
1913 static enum ice_status
1914 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1915 u32 addl_hdrs, u8 segs_cnt)
1917 const enum ice_block blk = ICE_BLK_RSS;
1918 struct ice_flow_prof *prof = NULL;
1919 struct ice_flow_seg_info *segs;
1920 enum ice_status status = ICE_SUCCESS;
1922 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
1923 return ICE_ERR_PARAM;
1925 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
1928 return ICE_ERR_NO_MEMORY;
1930 /* Construct the packet segment info from the hashed fields */
1931 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
1936 /* Search for a flow profile that has matching headers, hash fields
1937 * and has the input VSI associated to it. If found, no further
1938 * operations required and exit.
1940 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1942 ICE_FLOW_FIND_PROF_CHK_FLDS |
1943 ICE_FLOW_FIND_PROF_CHK_VSI);
1947 /* Check if a flow profile exists with the same protocol headers and
1948 * associated with the input VSI. If so disasscociate the VSI from
1949 * this profile. The VSI will be added to a new profile created with
1950 * the protocol header and new hash field configuration.
1952 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1953 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1955 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1957 ice_rem_rss_list(hw, vsi_handle, prof);
1961 /* Remove profile if it has no VSIs associated */
1962 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1963 status = ice_flow_rem_prof(hw, blk, prof->id);
1969 /* Search for a profile that has same match fields only. If this
1970 * exists then associate the VSI to this profile.
1972 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
1974 ICE_FLOW_FIND_PROF_CHK_FLDS);
1976 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1978 status = ice_add_rss_list(hw, vsi_handle, prof);
1982 /* Create a new flow profile with generated profile and packet
1983 * segment information.
1985 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1986 ICE_FLOW_GEN_PROFID(hashed_flds,
1987 segs[segs_cnt - 1].hdrs,
1989 segs, segs_cnt, NULL, 0, &prof);
1993 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1994 /* If association to a new flow profile failed then this profile can
1998 ice_flow_rem_prof(hw, blk, prof->id);
2002 status = ice_add_rss_list(hw, vsi_handle, prof);
2010 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2011 * @hw: pointer to the hardware structure
2012 * @vsi_handle: software VSI handle
2013 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2014 * @addl_hdrs: protocol header fields
2016 * This function will generate a flow profile based on fields associated with
2017 * the input fields to hash on, the flow type and use the VSI number to add
2018 * a flow entry to the profile.
2021 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2024 enum ice_status status;
2026 if (hashed_flds == ICE_HASH_INVALID ||
2027 !ice_is_vsi_valid(hw, vsi_handle))
2028 return ICE_ERR_PARAM;
2030 ice_acquire_lock(&hw->rss_locks);
2031 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2032 ICE_RSS_OUTER_HEADERS);
2034 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2035 addl_hdrs, ICE_RSS_INNER_HEADERS);
2036 ice_release_lock(&hw->rss_locks);
2042 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2043 * @hw: pointer to the hardware structure
2044 * @vsi_handle: software VSI handle
2045 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2046 * @addl_hdrs: Protocol header fields within a packet segment
2047 * @segs_cnt: packet segment count
2049 * Assumption: lock has already been acquired for RSS list
2051 static enum ice_status
2052 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2053 u32 addl_hdrs, u8 segs_cnt)
2055 const enum ice_block blk = ICE_BLK_RSS;
2056 struct ice_flow_seg_info *segs;
2057 struct ice_flow_prof *prof;
2058 enum ice_status status;
2060 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
2062 return ICE_ERR_NO_MEMORY;
2064 /* Construct the packet segment info from the hashed fields */
2065 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
2069 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2071 ICE_FLOW_FIND_PROF_CHK_FLDS);
2073 status = ICE_ERR_DOES_NOT_EXIST;
2077 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2081 /* Remove RSS configuration from VSI context before deleting
2084 ice_rem_rss_list(hw, vsi_handle, prof);
2086 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2087 status = ice_flow_rem_prof(hw, blk, prof->id);
2095 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2096 * @hw: pointer to the hardware structure
2097 * @vsi_handle: software VSI handle
2098 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2099 * @addl_hdrs: Protocol header fields within a packet segment
2101 * This function will lookup the flow profile based on the input
2102 * hash field bitmap, iterate through the profile entry list of
2103 * that profile and find entry associated with input VSI to be
2104 * removed. Calls are made to underlying flow apis which will in
2105 * turn build or update buffers for RSS XLT1 section.
2108 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2111 enum ice_status status;
2113 if (hashed_flds == ICE_HASH_INVALID ||
2114 !ice_is_vsi_valid(hw, vsi_handle))
2115 return ICE_ERR_PARAM;
2117 ice_acquire_lock(&hw->rss_locks);
2118 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2119 ICE_RSS_OUTER_HEADERS);
2121 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2122 addl_hdrs, ICE_RSS_INNER_HEADERS);
2123 ice_release_lock(&hw->rss_locks);
2128 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
2129 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
2130 * convert its values to their appropriate flow L3, L4 values.
2132 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
2133 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
2134 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
2135 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
2136 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
2137 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
2138 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
2139 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
2140 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
2141 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
2142 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
2143 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
2144 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
2146 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
2147 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
2148 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
2149 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
2150 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
2151 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
2152 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
2153 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
2154 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
2155 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
2156 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
2157 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
2158 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
2160 #define ICE_FLOW_MAX_CFG 10
2163 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
2164 * @hw: pointer to the hardware structure
2165 * @vsi_handle: software VSI handle
2166 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
2168 * This function will take the hash bitmap provided by the AVF driver via a
2169 * message, convert it to ICE-compatible values, and configure RSS flow
2173 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
2175 enum ice_status status = ICE_SUCCESS;
2178 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
2179 !ice_is_vsi_valid(hw, vsi_handle))
2180 return ICE_ERR_PARAM;
2182 /* Make sure no unsupported bits are specified */
2183 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
2184 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
2187 hash_flds = avf_hash;
2189 /* Always create an L3 RSS configuration for any L4 RSS configuration */
2190 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
2191 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
2193 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2194 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2196 /* Create the corresponding RSS configuration for each valid hash bit */
2198 u64 rss_hash = ICE_HASH_INVALID;
2200 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2201 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2202 rss_hash = ICE_FLOW_HASH_IPV4;
2203 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2204 } else if (hash_flds &
2205 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2206 rss_hash = ICE_FLOW_HASH_IPV4 |
2207 ICE_FLOW_HASH_TCP_PORT;
2208 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2209 } else if (hash_flds &
2210 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2211 rss_hash = ICE_FLOW_HASH_IPV4 |
2212 ICE_FLOW_HASH_UDP_PORT;
2213 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2214 } else if (hash_flds &
2215 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2216 rss_hash = ICE_FLOW_HASH_IPV4 |
2217 ICE_FLOW_HASH_SCTP_PORT;
2219 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2221 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2222 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2223 rss_hash = ICE_FLOW_HASH_IPV6;
2224 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2225 } else if (hash_flds &
2226 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2227 rss_hash = ICE_FLOW_HASH_IPV6 |
2228 ICE_FLOW_HASH_TCP_PORT;
2229 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2230 } else if (hash_flds &
2231 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2232 rss_hash = ICE_FLOW_HASH_IPV6 |
2233 ICE_FLOW_HASH_UDP_PORT;
2234 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2235 } else if (hash_flds &
2236 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2237 rss_hash = ICE_FLOW_HASH_IPV6 |
2238 ICE_FLOW_HASH_SCTP_PORT;
2240 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2244 if (rss_hash == ICE_HASH_INVALID)
2245 return ICE_ERR_OUT_OF_RANGE;
2247 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2248 ICE_FLOW_SEG_HDR_NONE);
2257 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2258 * @hw: pointer to the hardware structure
2259 * @vsi_handle: software VSI handle
2261 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2263 enum ice_status status = ICE_SUCCESS;
2264 struct ice_rss_cfg *r;
2266 if (!ice_is_vsi_valid(hw, vsi_handle))
2267 return ICE_ERR_PARAM;
2269 ice_acquire_lock(&hw->rss_locks);
2270 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2271 ice_rss_cfg, l_entry) {
2272 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2273 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2276 ICE_RSS_OUTER_HEADERS);
2279 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2282 ICE_RSS_INNER_HEADERS);
2287 ice_release_lock(&hw->rss_locks);
2293 * ice_get_rss_cfg - returns hashed fields for the given header types
2294 * @hw: pointer to the hardware structure
2295 * @vsi_handle: software VSI handle
2296 * @hdrs: protocol header type
2298 * This function will return the match fields of the first instance of flow
2299 * profile having the given header types and containing input VSI
2301 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2303 struct ice_rss_cfg *r, *rss_cfg = NULL;
2305 /* verify if the protocol header is non zero and VSI is valid */
2306 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2307 return ICE_HASH_INVALID;
2309 ice_acquire_lock(&hw->rss_locks);
2310 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2311 ice_rss_cfg, l_entry)
2312 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2313 r->packet_hdr == hdrs) {
2317 ice_release_lock(&hw->rss_locks);
2319 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;