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) {
583 src = (const ice_bitmap_t *)ice_ptypes_gtpc;
584 ice_and_bitmap(params->ptypes, params->ptypes,
585 src, ICE_FLOW_PTYPE_MAX);
587 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPC_TEID) {
589 src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
590 ice_and_bitmap(params->ptypes, params->ptypes,
591 src, ICE_FLOW_PTYPE_MAX);
593 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
595 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
596 ice_and_bitmap(params->ptypes, params->ptypes,
597 src, ICE_FLOW_PTYPE_MAX);
599 } else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
601 src = (const ice_bitmap_t *)ice_ptypes_gtpu;
602 ice_and_bitmap(params->ptypes, params->ptypes,
603 src, ICE_FLOW_PTYPE_MAX);
606 /* Attributes for GTP packet with Extension Header */
607 params->attr = ice_attr_gtpu_eh;
608 params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
616 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
617 * @hw: pointer to the HW struct
618 * @params: information about the flow to be processed
619 * @flags: The value of pkt_flags[x:x] in Rx/Tx MDID metadata.
621 * This function will allocate an extraction sequence entries for a DWORD size
622 * chunk of the packet flags.
624 static enum ice_status
625 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
626 struct ice_flow_prof_params *params,
627 enum ice_flex_mdid_pkt_flags flags)
629 u8 fv_words = hw->blk[params->blk].es.fvw;
632 /* Make sure the number of extraction sequence entries required does not
633 * exceed the block's capacity.
635 if (params->es_cnt >= fv_words)
636 return ICE_ERR_MAX_LIMIT;
638 /* some blocks require a reversed field vector layout */
639 if (hw->blk[params->blk].es.reverse)
640 idx = fv_words - params->es_cnt - 1;
642 idx = params->es_cnt;
644 params->es[idx].prot_id = ICE_PROT_META_ID;
645 params->es[idx].off = flags;
652 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
653 * @hw: pointer to the HW struct
654 * @params: information about the flow to be processed
655 * @seg: packet segment index of the field to be extracted
656 * @fld: ID of field to be extracted
657 * @match: bitfield of all fields
659 * This function determines the protocol ID, offset, and size of the given
660 * field. It then allocates one or more extraction sequence entries for the
661 * given field, and fill the entries with protocol ID and offset information.
663 static enum ice_status
664 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
665 u8 seg, enum ice_flow_field fld, u64 match)
667 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
668 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
669 u8 fv_words = hw->blk[params->blk].es.fvw;
670 struct ice_flow_fld_info *flds;
671 u16 cnt, ese_bits, i;
677 flds = params->prof->segs[seg].fields;
680 case ICE_FLOW_FIELD_IDX_ETH_DA:
681 case ICE_FLOW_FIELD_IDX_ETH_SA:
682 case ICE_FLOW_FIELD_IDX_S_VLAN:
683 case ICE_FLOW_FIELD_IDX_C_VLAN:
684 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
686 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
687 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
689 case ICE_FLOW_FIELD_IDX_IPV4_DSCP:
690 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
692 case ICE_FLOW_FIELD_IDX_IPV6_DSCP:
693 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
695 case ICE_FLOW_FIELD_IDX_IPV4_TTL:
696 case ICE_FLOW_FIELD_IDX_IPV4_PROT:
697 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
699 /* TTL and PROT share the same extraction seq. entry.
700 * Each is considered a sibling to the other in terms of sharing
701 * the same extraction sequence entry.
703 if (fld == ICE_FLOW_FIELD_IDX_IPV4_TTL)
704 sib = ICE_FLOW_FIELD_IDX_IPV4_PROT;
705 else if (fld == ICE_FLOW_FIELD_IDX_IPV4_PROT)
706 sib = ICE_FLOW_FIELD_IDX_IPV4_TTL;
708 /* If the sibling field is also included, that field's
709 * mask needs to be included.
711 if (match & BIT(sib))
712 sib_mask = ice_flds_info[sib].mask;
714 case ICE_FLOW_FIELD_IDX_IPV6_TTL:
715 case ICE_FLOW_FIELD_IDX_IPV6_PROT:
716 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
718 /* TTL and PROT share the same extraction seq. entry.
719 * Each is considered a sibling to the other in terms of sharing
720 * the same extraction sequence entry.
722 if (fld == ICE_FLOW_FIELD_IDX_IPV6_TTL)
723 sib = ICE_FLOW_FIELD_IDX_IPV6_PROT;
724 else if (fld == ICE_FLOW_FIELD_IDX_IPV6_PROT)
725 sib = ICE_FLOW_FIELD_IDX_IPV6_TTL;
727 /* If the sibling field is also included, that field's
728 * mask needs to be included.
730 if (match & BIT(sib))
731 sib_mask = ice_flds_info[sib].mask;
733 case ICE_FLOW_FIELD_IDX_IPV4_SA:
734 case ICE_FLOW_FIELD_IDX_IPV4_DA:
735 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
737 case ICE_FLOW_FIELD_IDX_IPV6_SA:
738 case ICE_FLOW_FIELD_IDX_IPV6_DA:
739 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
741 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
742 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
743 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
744 prot_id = ICE_PROT_TCP_IL;
746 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
747 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
748 prot_id = ICE_PROT_UDP_IL_OR_S;
750 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
751 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
752 prot_id = ICE_PROT_SCTP_IL;
754 case ICE_FLOW_FIELD_IDX_GTPC_TEID:
755 case ICE_FLOW_FIELD_IDX_GTPU_IP_TEID:
756 case ICE_FLOW_FIELD_IDX_GTPU_UP_TEID:
757 case ICE_FLOW_FIELD_IDX_GTPU_DWN_TEID:
758 case ICE_FLOW_FIELD_IDX_GTPU_EH_TEID:
759 case ICE_FLOW_FIELD_IDX_GTPU_EH_QFI:
760 /* GTP is accessed through UDP OF protocol */
761 prot_id = ICE_PROT_UDP_OF;
763 case ICE_FLOW_FIELD_IDX_PPPOE_SESS_ID:
764 prot_id = ICE_PROT_PPPOE;
766 case ICE_FLOW_FIELD_IDX_ARP_SIP:
767 case ICE_FLOW_FIELD_IDX_ARP_DIP:
768 case ICE_FLOW_FIELD_IDX_ARP_SHA:
769 case ICE_FLOW_FIELD_IDX_ARP_DHA:
770 case ICE_FLOW_FIELD_IDX_ARP_OP:
771 prot_id = ICE_PROT_ARP_OF;
773 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
774 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
775 /* ICMP type and code share the same extraction seq. entry */
776 prot_id = (params->prof->segs[seg].hdrs &
777 ICE_FLOW_SEG_HDR_IPV4) ?
778 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
779 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
780 ICE_FLOW_FIELD_IDX_ICMP_CODE :
781 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
783 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
784 prot_id = ICE_PROT_GRE_OF;
787 return ICE_ERR_NOT_IMPL;
790 /* Each extraction sequence entry is a word in size, and extracts a
791 * word-aligned offset from a protocol header.
793 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
795 flds[fld].xtrct.prot_id = prot_id;
796 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
797 ICE_FLOW_FV_EXTRACT_SZ;
798 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
799 flds[fld].xtrct.idx = params->es_cnt;
800 flds[fld].xtrct.mask = ice_flds_info[fld].mask;
802 /* Adjust the next field-entry index after accommodating the number of
803 * entries this field consumes
805 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
806 ice_flds_info[fld].size, ese_bits);
808 /* Fill in the extraction sequence entries needed for this field */
809 off = flds[fld].xtrct.off;
810 mask = flds[fld].xtrct.mask;
811 for (i = 0; i < cnt; i++) {
812 /* Only consume an extraction sequence entry if there is no
813 * sibling field associated with this field or the sibling entry
814 * already extracts the word shared with this field.
816 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
817 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
818 flds[sib].xtrct.off != off) {
821 /* Make sure the number of extraction sequence required
822 * does not exceed the block's capability
824 if (params->es_cnt >= fv_words)
825 return ICE_ERR_MAX_LIMIT;
827 /* some blocks require a reversed field vector layout */
828 if (hw->blk[params->blk].es.reverse)
829 idx = fv_words - params->es_cnt - 1;
831 idx = params->es_cnt;
833 params->es[idx].prot_id = prot_id;
834 params->es[idx].off = off;
835 params->mask[idx] = mask | sib_mask;
839 off += ICE_FLOW_FV_EXTRACT_SZ;
846 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
847 * @hw: pointer to the HW struct
848 * @params: information about the flow to be processed
849 * @seg: index of packet segment whose raw fields are to be be extracted
851 static enum ice_status
852 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
859 if (!params->prof->segs[seg].raws_cnt)
862 if (params->prof->segs[seg].raws_cnt >
863 ARRAY_SIZE(params->prof->segs[seg].raws))
864 return ICE_ERR_MAX_LIMIT;
866 /* Offsets within the segment headers are not supported */
867 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
869 return ICE_ERR_PARAM;
871 fv_words = hw->blk[params->blk].es.fvw;
873 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
874 struct ice_flow_seg_fld_raw *raw;
877 raw = ¶ms->prof->segs[seg].raws[i];
879 /* Only support matching raw fields in the payload */
880 if (raw->off < hdrs_sz)
881 return ICE_ERR_PARAM;
883 /* Convert the segment-relative offset into payload-relative
886 off = raw->off - hdrs_sz;
888 /* Storing extraction information */
889 raw->info.xtrct.prot_id = ICE_PROT_PAY;
890 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
891 ICE_FLOW_FV_EXTRACT_SZ;
892 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
894 raw->info.xtrct.idx = params->es_cnt;
896 /* Determine the number of field vector entries this raw field
899 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
900 (raw->info.src.last * BITS_PER_BYTE),
901 (ICE_FLOW_FV_EXTRACT_SZ *
903 off = raw->info.xtrct.off;
904 for (j = 0; j < cnt; j++) {
907 /* Make sure the number of extraction sequence required
908 * does not exceed the block's capability
910 if (params->es_cnt >= hw->blk[params->blk].es.count ||
911 params->es_cnt >= ICE_MAX_FV_WORDS)
912 return ICE_ERR_MAX_LIMIT;
914 /* some blocks require a reversed field vector layout */
915 if (hw->blk[params->blk].es.reverse)
916 idx = fv_words - params->es_cnt - 1;
918 idx = params->es_cnt;
920 params->es[idx].prot_id = ICE_PROT_PAY;
921 params->es[idx].off = off;
923 off += ICE_FLOW_FV_EXTRACT_SZ;
931 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
932 * @hw: pointer to the HW struct
933 * @params: information about the flow to be processed
935 * This function iterates through all matched fields in the given segments, and
936 * creates an extraction sequence for the fields.
938 static enum ice_status
939 ice_flow_create_xtrct_seq(struct ice_hw *hw,
940 struct ice_flow_prof_params *params)
942 enum ice_status status = ICE_SUCCESS;
945 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
948 if (params->blk == ICE_BLK_ACL) {
949 status = ice_flow_xtract_pkt_flags(hw, params,
950 ICE_RX_MDID_PKT_FLAGS_15_0);
955 for (i = 0; i < params->prof->segs_cnt; i++) {
956 u64 match = params->prof->segs[i].match;
959 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
960 const u64 bit = BIT_ULL(j);
963 status = ice_flow_xtract_fld
964 (hw, params, i, (enum ice_flow_field)j,
972 /* Process raw matching bytes */
973 status = ice_flow_xtract_raws(hw, params, i);
982 * ice_flow_proc_segs - process all packet segments associated with a profile
983 * @hw: pointer to the HW struct
984 * @params: information about the flow to be processed
986 static enum ice_status
987 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
989 enum ice_status status;
991 status = ice_flow_proc_seg_hdrs(params);
995 status = ice_flow_create_xtrct_seq(hw, params);
999 switch (params->blk) {
1001 /* Only header information is provided for RSS configuration.
1002 * No further processing is needed.
1004 status = ICE_SUCCESS;
1007 status = ICE_SUCCESS;
1011 return ICE_ERR_NOT_IMPL;
1017 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
1018 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
1019 #define ICE_FLOW_FIND_PROF_NOT_CHK_DIR 0x00000004
1022 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
1023 * @hw: pointer to the HW struct
1024 * @blk: classification stage
1025 * @dir: flow direction
1026 * @segs: array of one or more packet segments that describe the flow
1027 * @segs_cnt: number of packet segments provided
1028 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
1029 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
1031 static struct ice_flow_prof *
1032 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
1033 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
1034 u8 segs_cnt, u16 vsi_handle, u32 conds)
1036 struct ice_flow_prof *p, *prof = NULL;
1038 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1039 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1040 if ((p->dir == dir || conds & ICE_FLOW_FIND_PROF_NOT_CHK_DIR) &&
1041 segs_cnt && segs_cnt == p->segs_cnt) {
1044 /* Check for profile-VSI association if specified */
1045 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
1046 ice_is_vsi_valid(hw, vsi_handle) &&
1047 !ice_is_bit_set(p->vsis, vsi_handle))
1050 /* Protocol headers must be checked. Matched fields are
1051 * checked if specified.
1053 for (i = 0; i < segs_cnt; i++)
1054 if (segs[i].hdrs != p->segs[i].hdrs ||
1055 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
1056 segs[i].match != p->segs[i].match))
1059 /* A match is found if all segments are matched */
1060 if (i == segs_cnt) {
1066 ice_release_lock(&hw->fl_profs_locks[blk]);
1072 * ice_flow_find_prof - Look up a profile matching headers and matched fields
1073 * @hw: pointer to the HW struct
1074 * @blk: classification stage
1075 * @dir: flow direction
1076 * @segs: array of one or more packet segments that describe the flow
1077 * @segs_cnt: number of packet segments provided
1080 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1081 struct ice_flow_seg_info *segs, u8 segs_cnt)
1083 struct ice_flow_prof *p;
1085 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
1086 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
1088 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
1092 * ice_flow_find_prof_id - Look up a profile with given profile ID
1093 * @hw: pointer to the HW struct
1094 * @blk: classification stage
1095 * @prof_id: unique ID to identify this flow profile
1097 static struct ice_flow_prof *
1098 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1100 struct ice_flow_prof *p;
1102 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1103 if (p->id == prof_id)
1111 * ice_dealloc_flow_entry - Deallocate flow entry memory
1112 * @hw: pointer to the HW struct
1113 * @entry: flow entry to be removed
1116 ice_dealloc_flow_entry(struct ice_hw *hw, struct ice_flow_entry *entry)
1122 ice_free(hw, entry->entry);
1125 ice_free(hw, entry->acts);
1127 entry->acts_cnt = 0;
1130 ice_free(hw, entry);
1134 * ice_flow_rem_entry_sync - Remove a flow entry
1135 * @hw: pointer to the HW struct
1136 * @entry: flow entry to be removed
1138 static enum ice_status
1139 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
1142 return ICE_ERR_BAD_PTR;
1144 LIST_DEL(&entry->l_entry);
1146 ice_dealloc_flow_entry(hw, entry);
1152 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
1153 * @hw: pointer to the HW struct
1154 * @blk: classification stage
1155 * @dir: flow direction
1156 * @prof_id: unique ID to identify this flow profile
1157 * @segs: array of one or more packet segments that describe the flow
1158 * @segs_cnt: number of packet segments provided
1159 * @acts: array of default actions
1160 * @acts_cnt: number of default actions
1161 * @prof: stores the returned flow profile added
1163 * Assumption: the caller has acquired the lock to the profile list
1165 static enum ice_status
1166 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
1167 enum ice_flow_dir dir, u64 prof_id,
1168 struct ice_flow_seg_info *segs, u8 segs_cnt,
1169 struct ice_flow_action *acts, u8 acts_cnt,
1170 struct ice_flow_prof **prof)
1172 struct ice_flow_prof_params params;
1173 enum ice_status status = ICE_SUCCESS;
1176 if (!prof || (acts_cnt && !acts))
1177 return ICE_ERR_BAD_PTR;
1179 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1180 params.prof = (struct ice_flow_prof *)
1181 ice_malloc(hw, sizeof(*params.prof));
1183 return ICE_ERR_NO_MEMORY;
1185 /* initialize extraction sequence to all invalid (0xff) */
1186 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1187 params.es[i].prot_id = ICE_PROT_INVALID;
1188 params.es[i].off = ICE_FV_OFFSET_INVAL;
1192 params.prof->id = prof_id;
1193 params.prof->dir = dir;
1194 params.prof->segs_cnt = segs_cnt;
1196 /* Make a copy of the segments that need to be persistent in the flow
1199 for (i = 0; i < segs_cnt; i++)
1200 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1201 ICE_NONDMA_TO_NONDMA);
1203 /* Make a copy of the actions that need to be persistent in the flow
1207 params.prof->acts = (struct ice_flow_action *)
1208 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1209 ICE_NONDMA_TO_NONDMA);
1211 if (!params.prof->acts) {
1212 status = ICE_ERR_NO_MEMORY;
1217 status = ice_flow_proc_segs(hw, ¶ms);
1219 ice_debug(hw, ICE_DBG_FLOW,
1220 "Error processing a flow's packet segments\n");
1224 /* Add a HW profile for this flow profile */
1225 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes,
1226 params.attr, params.attr_cnt, params.es,
1229 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1233 INIT_LIST_HEAD(¶ms.prof->entries);
1234 ice_init_lock(¶ms.prof->entries_lock);
1235 *prof = params.prof;
1239 if (params.prof->acts)
1240 ice_free(hw, params.prof->acts);
1241 ice_free(hw, params.prof);
1248 * ice_flow_rem_prof_sync - remove a flow profile
1249 * @hw: pointer to the hardware structure
1250 * @blk: classification stage
1251 * @prof: pointer to flow profile to remove
1253 * Assumption: the caller has acquired the lock to the profile list
1255 static enum ice_status
1256 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1257 struct ice_flow_prof *prof)
1259 enum ice_status status = ICE_SUCCESS;
1261 /* Remove all remaining flow entries before removing the flow profile */
1262 if (!LIST_EMPTY(&prof->entries)) {
1263 struct ice_flow_entry *e, *t;
1265 ice_acquire_lock(&prof->entries_lock);
1267 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1269 status = ice_flow_rem_entry_sync(hw, e);
1274 ice_release_lock(&prof->entries_lock);
1277 /* Remove all hardware profiles associated with this flow profile */
1278 status = ice_rem_prof(hw, blk, prof->id);
1280 LIST_DEL(&prof->l_entry);
1281 ice_destroy_lock(&prof->entries_lock);
1283 ice_free(hw, prof->acts);
1291 * ice_flow_assoc_vsig_vsi - associate a VSI with VSIG
1292 * @hw: pointer to the hardware structure
1293 * @blk: classification stage
1294 * @vsi_handle: software VSI handle
1295 * @vsig: target VSI group
1297 * Assumption: the caller has already verified that the VSI to
1298 * be added has the same characteristics as the VSIG and will
1299 * thereby have access to all resources added to that VSIG.
1302 ice_flow_assoc_vsig_vsi(struct ice_hw *hw, enum ice_block blk, u16 vsi_handle,
1305 enum ice_status status;
1307 if (!ice_is_vsi_valid(hw, vsi_handle) || blk >= ICE_BLK_COUNT)
1308 return ICE_ERR_PARAM;
1310 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1311 status = ice_add_vsi_flow(hw, blk, ice_get_hw_vsi_num(hw, vsi_handle),
1313 ice_release_lock(&hw->fl_profs_locks[blk]);
1319 * ice_flow_assoc_prof - associate a VSI with a flow profile
1320 * @hw: pointer to the hardware structure
1321 * @blk: classification stage
1322 * @prof: pointer to flow profile
1323 * @vsi_handle: software VSI handle
1325 * Assumption: the caller has acquired the lock to the profile list
1326 * and the software VSI handle has been validated
1328 static enum ice_status
1329 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1330 struct ice_flow_prof *prof, u16 vsi_handle)
1332 enum ice_status status = ICE_SUCCESS;
1334 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1335 status = ice_add_prof_id_flow(hw, blk,
1336 ice_get_hw_vsi_num(hw,
1340 ice_set_bit(vsi_handle, prof->vsis);
1342 ice_debug(hw, ICE_DBG_FLOW,
1343 "HW profile add failed, %d\n",
1351 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1352 * @hw: pointer to the hardware structure
1353 * @blk: classification stage
1354 * @prof: pointer to flow profile
1355 * @vsi_handle: software VSI handle
1357 * Assumption: the caller has acquired the lock to the profile list
1358 * and the software VSI handle has been validated
1360 static enum ice_status
1361 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1362 struct ice_flow_prof *prof, u16 vsi_handle)
1364 enum ice_status status = ICE_SUCCESS;
1366 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1367 status = ice_rem_prof_id_flow(hw, blk,
1368 ice_get_hw_vsi_num(hw,
1372 ice_clear_bit(vsi_handle, prof->vsis);
1374 ice_debug(hw, ICE_DBG_FLOW,
1375 "HW profile remove failed, %d\n",
1383 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1384 * @hw: pointer to the HW struct
1385 * @blk: classification stage
1386 * @dir: flow direction
1387 * @prof_id: unique ID to identify this flow profile
1388 * @segs: array of one or more packet segments that describe the flow
1389 * @segs_cnt: number of packet segments provided
1390 * @acts: array of default actions
1391 * @acts_cnt: number of default actions
1392 * @prof: stores the returned flow profile added
1395 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1396 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1397 struct ice_flow_action *acts, u8 acts_cnt,
1398 struct ice_flow_prof **prof)
1400 enum ice_status status;
1402 if (segs_cnt > ICE_FLOW_SEG_MAX)
1403 return ICE_ERR_MAX_LIMIT;
1406 return ICE_ERR_PARAM;
1409 return ICE_ERR_BAD_PTR;
1411 status = ice_flow_val_hdrs(segs, segs_cnt);
1415 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1417 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1418 acts, acts_cnt, prof);
1420 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1422 ice_release_lock(&hw->fl_profs_locks[blk]);
1428 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1429 * @hw: pointer to the HW struct
1430 * @blk: the block for which the flow profile is to be removed
1431 * @prof_id: unique ID of the flow profile to be removed
1434 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1436 struct ice_flow_prof *prof;
1437 enum ice_status status;
1439 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1441 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1443 status = ICE_ERR_DOES_NOT_EXIST;
1447 /* prof becomes invalid after the call */
1448 status = ice_flow_rem_prof_sync(hw, blk, prof);
1451 ice_release_lock(&hw->fl_profs_locks[blk]);
1457 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1458 * @hw: pointer to the HW struct
1459 * @blk: classification stage
1460 * @prof_id: the profile ID handle
1461 * @hw_prof_id: pointer to variable to receive the HW profile ID
1464 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1467 struct ice_prof_map *map;
1469 map = ice_search_prof_id(hw, blk, prof_id);
1471 *hw_prof_id = map->prof_id;
1475 return ICE_ERR_DOES_NOT_EXIST;
1479 * ice_flow_find_entry - look for a flow entry using its unique ID
1480 * @hw: pointer to the HW struct
1481 * @blk: classification stage
1482 * @entry_id: unique ID to identify this flow entry
1484 * This function looks for the flow entry with the specified unique ID in all
1485 * flow profiles of the specified classification stage. If the entry is found,
1486 * and it returns the handle to the flow entry. Otherwise, it returns
1487 * ICE_FLOW_ENTRY_ID_INVAL.
1489 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1491 struct ice_flow_entry *found = NULL;
1492 struct ice_flow_prof *p;
1494 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1496 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1497 struct ice_flow_entry *e;
1499 ice_acquire_lock(&p->entries_lock);
1500 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1501 if (e->id == entry_id) {
1505 ice_release_lock(&p->entries_lock);
1511 ice_release_lock(&hw->fl_profs_locks[blk]);
1513 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1517 * ice_flow_add_entry - Add a flow entry
1518 * @hw: pointer to the HW struct
1519 * @blk: classification stage
1520 * @prof_id: ID of the profile to add a new flow entry to
1521 * @entry_id: unique ID to identify this flow entry
1522 * @vsi_handle: software VSI handle for the flow entry
1523 * @prio: priority of the flow entry
1524 * @data: pointer to a data buffer containing flow entry's match values/masks
1525 * @acts: arrays of actions to be performed on a match
1526 * @acts_cnt: number of actions
1527 * @entry_h: pointer to buffer that receives the new flow entry's handle
1530 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1531 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1532 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1535 struct ice_flow_prof *prof = NULL;
1536 struct ice_flow_entry *e = NULL;
1537 enum ice_status status = ICE_SUCCESS;
1539 if (acts_cnt && !acts)
1540 return ICE_ERR_PARAM;
1542 /* No flow entry data is expected for RSS */
1543 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1544 return ICE_ERR_BAD_PTR;
1546 if (!ice_is_vsi_valid(hw, vsi_handle))
1547 return ICE_ERR_PARAM;
1549 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1551 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1553 status = ICE_ERR_DOES_NOT_EXIST;
1555 /* Allocate memory for the entry being added and associate
1556 * the VSI to the found flow profile
1558 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1560 status = ICE_ERR_NO_MEMORY;
1562 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1565 ice_release_lock(&hw->fl_profs_locks[blk]);
1570 e->vsi_handle = vsi_handle;
1576 /* RSS will add only one entry per VSI per profile */
1583 status = ICE_ERR_NOT_IMPL;
1587 if (blk != ICE_BLK_ACL) {
1588 /* ACL will handle the entry management */
1589 ice_acquire_lock(&prof->entries_lock);
1590 LIST_ADD(&e->l_entry, &prof->entries);
1591 ice_release_lock(&prof->entries_lock);
1594 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1599 ice_free(hw, e->entry);
1607 * ice_flow_rem_entry - Remove a flow entry
1608 * @hw: pointer to the HW struct
1609 * @entry_h: handle to the flow entry to be removed
1611 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1613 struct ice_flow_entry *entry;
1614 struct ice_flow_prof *prof;
1615 enum ice_status status;
1617 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1618 return ICE_ERR_PARAM;
1620 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1622 /* Retain the pointer to the flow profile as the entry will be freed */
1625 ice_acquire_lock(&prof->entries_lock);
1626 status = ice_flow_rem_entry_sync(hw, entry);
1627 ice_release_lock(&prof->entries_lock);
1633 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1634 * @seg: packet segment the field being set belongs to
1635 * @fld: field to be set
1636 * @type: type of the field
1637 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1638 * entry's input buffer
1639 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1641 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1642 * entry's input buffer
1644 * This helper function stores information of a field being matched, including
1645 * the type of the field and the locations of the value to match, the mask, and
1646 * and the upper-bound value in the start of the input buffer for a flow entry.
1647 * This function should only be used for fixed-size data structures.
1649 * This function also opportunistically determines the protocol headers to be
1650 * present based on the fields being set. Some fields cannot be used alone to
1651 * determine the protocol headers present. Sometimes, fields for particular
1652 * protocol headers are not matched. In those cases, the protocol headers
1653 * must be explicitly set.
1656 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1657 enum ice_flow_fld_match_type type, u16 val_loc,
1658 u16 mask_loc, u16 last_loc)
1660 u64 bit = BIT_ULL(fld);
1663 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1666 seg->fields[fld].type = type;
1667 seg->fields[fld].src.val = val_loc;
1668 seg->fields[fld].src.mask = mask_loc;
1669 seg->fields[fld].src.last = last_loc;
1671 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1675 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1676 * @seg: packet segment the field being set belongs to
1677 * @fld: field to be set
1678 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1679 * entry's input buffer
1680 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1682 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1683 * entry's input buffer
1684 * @range: indicate if field being matched is to be in a range
1686 * This function specifies the locations, in the form of byte offsets from the
1687 * start of the input buffer for a flow entry, from where the value to match,
1688 * the mask value, and upper value can be extracted. These locations are then
1689 * stored in the flow profile. When adding a flow entry associated with the
1690 * flow profile, these locations will be used to quickly extract the values and
1691 * create the content of a match entry. This function should only be used for
1692 * fixed-size data structures.
1695 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1696 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1698 enum ice_flow_fld_match_type t = range ?
1699 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1701 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1705 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1706 * @seg: packet segment the field being set belongs to
1707 * @fld: field to be set
1708 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1709 * entry's input buffer
1710 * @pref_loc: location of prefix value from entry's input buffer
1711 * @pref_sz: size of the location holding the prefix value
1713 * This function specifies the locations, in the form of byte offsets from the
1714 * start of the input buffer for a flow entry, from where the value to match
1715 * and the IPv4 prefix value can be extracted. These locations are then stored
1716 * in the flow profile. When adding flow entries to the associated flow profile,
1717 * these locations can be used to quickly extract the values to create the
1718 * content of a match entry. This function should only be used for fixed-size
1722 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1723 u16 val_loc, u16 pref_loc, u8 pref_sz)
1725 /* For this type of field, the "mask" location is for the prefix value's
1726 * location and the "last" location is for the size of the location of
1729 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1730 pref_loc, (u16)pref_sz);
1734 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1735 * @seg: packet segment the field being set belongs to
1736 * @off: offset of the raw field from the beginning of the segment in bytes
1737 * @len: length of the raw pattern to be matched
1738 * @val_loc: location of the value to match from entry's input buffer
1739 * @mask_loc: location of mask value from entry's input buffer
1741 * This function specifies the offset of the raw field to be match from the
1742 * beginning of the specified packet segment, and the locations, in the form of
1743 * byte offsets from the start of the input buffer for a flow entry, from where
1744 * the value to match and the mask value to be extracted. These locations are
1745 * then stored in the flow profile. When adding flow entries to the associated
1746 * flow profile, these locations can be used to quickly extract the values to
1747 * create the content of a match entry. This function should only be used for
1748 * fixed-size data structures.
1751 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1752 u16 val_loc, u16 mask_loc)
1754 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1755 seg->raws[seg->raws_cnt].off = off;
1756 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1757 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1758 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1759 /* The "last" field is used to store the length of the field */
1760 seg->raws[seg->raws_cnt].info.src.last = len;
1763 /* Overflows of "raws" will be handled as an error condition later in
1764 * the flow when this information is processed.
1769 #define ICE_FLOW_RSS_SEG_HDR_L2_MASKS \
1770 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
1772 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1773 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1775 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1776 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1777 ICE_FLOW_SEG_HDR_SCTP)
1779 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1780 (ICE_FLOW_RSS_SEG_HDR_L2_MASKS | \
1781 ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1782 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1785 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1786 * @segs: pointer to the flow field segment(s)
1787 * @hash_fields: fields to be hashed on for the segment(s)
1788 * @flow_hdr: protocol header fields within a packet segment
1790 * Helper function to extract fields from hash bitmap and use flow
1791 * header value to set flow field segment for further use in flow
1792 * profile entry or removal.
1794 static enum ice_status
1795 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1798 u64 val = hash_fields;
1801 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1802 u64 bit = BIT_ULL(i);
1805 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1806 ICE_FLOW_FLD_OFF_INVAL,
1807 ICE_FLOW_FLD_OFF_INVAL,
1808 ICE_FLOW_FLD_OFF_INVAL, false);
1812 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1814 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS &
1815 ~ICE_FLOW_RSS_HDRS_INNER_MASK)
1816 return ICE_ERR_PARAM;
1818 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1819 if (val && !ice_is_pow2(val))
1822 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1823 if (val && !ice_is_pow2(val))
1830 * ice_rem_vsi_rss_list - remove VSI from RSS list
1831 * @hw: pointer to the hardware structure
1832 * @vsi_handle: software VSI handle
1834 * Remove the VSI from all RSS configurations in the list.
1836 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1838 struct ice_rss_cfg *r, *tmp;
1840 if (LIST_EMPTY(&hw->rss_list_head))
1843 ice_acquire_lock(&hw->rss_locks);
1844 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1845 ice_rss_cfg, l_entry) {
1846 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1847 ice_clear_bit(vsi_handle, r->vsis);
1849 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1850 LIST_DEL(&r->l_entry);
1855 ice_release_lock(&hw->rss_locks);
1859 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1860 * @hw: pointer to the hardware structure
1861 * @vsi_handle: software VSI handle
1863 * This function will iterate through all flow profiles and disassociate
1864 * the VSI from that profile. If the flow profile has no VSIs it will
1867 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1869 const enum ice_block blk = ICE_BLK_RSS;
1870 struct ice_flow_prof *p, *t;
1871 enum ice_status status = ICE_SUCCESS;
1873 if (!ice_is_vsi_valid(hw, vsi_handle))
1874 return ICE_ERR_PARAM;
1876 if (LIST_EMPTY(&hw->fl_profs[blk]))
1879 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1880 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1882 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1883 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1887 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1888 status = ice_flow_rem_prof_sync(hw, blk, p);
1894 ice_release_lock(&hw->fl_profs_locks[blk]);
1900 * ice_rem_rss_list - remove RSS configuration from list
1901 * @hw: pointer to the hardware structure
1902 * @vsi_handle: software VSI handle
1903 * @prof: pointer to flow profile
1905 * Assumption: lock has already been acquired for RSS list
1908 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1910 struct ice_rss_cfg *r, *tmp;
1912 /* Search for RSS hash fields associated to the VSI that match the
1913 * hash configurations associated to the flow profile. If found
1914 * remove from the RSS entry list of the VSI context and delete entry.
1916 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1917 ice_rss_cfg, l_entry) {
1918 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1919 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1920 ice_clear_bit(vsi_handle, r->vsis);
1921 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1922 LIST_DEL(&r->l_entry);
1931 * ice_add_rss_list - add RSS configuration to list
1932 * @hw: pointer to the hardware structure
1933 * @vsi_handle: software VSI handle
1934 * @prof: pointer to flow profile
1936 * Assumption: lock has already been acquired for RSS list
1938 static enum ice_status
1939 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1941 struct ice_rss_cfg *r, *rss_cfg;
1943 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1944 ice_rss_cfg, l_entry)
1945 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1946 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1947 ice_set_bit(vsi_handle, r->vsis);
1951 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1953 return ICE_ERR_NO_MEMORY;
1955 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1956 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1957 rss_cfg->symm = prof->cfg.symm;
1958 ice_set_bit(vsi_handle, rss_cfg->vsis);
1960 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1965 #define ICE_FLOW_PROF_HASH_S 0
1966 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1967 #define ICE_FLOW_PROF_HDR_S 32
1968 #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1969 #define ICE_FLOW_PROF_ENCAP_S 63
1970 #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S))
1972 #define ICE_RSS_OUTER_HEADERS 1
1973 #define ICE_RSS_INNER_HEADERS 2
1975 /* Flow profile ID format:
1976 * [0:31] - Packet match fields
1977 * [32:62] - Protocol header
1978 * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled
1980 #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \
1981 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1982 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \
1983 ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0))
1986 ice_rss_config_xor_word(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst)
1988 u32 s = ((src % 4) << 3); /* byte shift */
1989 u32 v = dst | 0x80; /* value to program */
1990 u8 i = src / 4; /* register index */
1993 reg = rd32(hw, GLQF_HSYMM(prof_id, i));
1994 reg = (reg & ~(0xff << s)) | (v << s);
1995 wr32(hw, GLQF_HSYMM(prof_id, i), reg);
1999 ice_rss_config_xor(struct ice_hw *hw, u8 prof_id, u8 src, u8 dst, u8 len)
2002 ICE_FLOW_SW_FIELD_VECTOR_MAX / ICE_FLOW_FV_EXTRACT_SZ - 1;
2005 for (i = 0; i < len; i++) {
2006 ice_rss_config_xor_word(hw, prof_id,
2007 /* Yes, field vector in GLQF_HSYMM and
2008 * GLQF_HINSET is inversed!
2010 fv_last_word - (src + i),
2011 fv_last_word - (dst + i));
2012 ice_rss_config_xor_word(hw, prof_id,
2013 fv_last_word - (dst + i),
2014 fv_last_word - (src + i));
2019 ice_rss_update_symm(struct ice_hw *hw,
2020 struct ice_flow_prof *prof)
2022 struct ice_prof_map *map;
2025 map = ice_search_prof_id(hw, ICE_BLK_RSS, prof->id);
2026 prof_id = map->prof_id;
2028 /* clear to default */
2029 for (m = 0; m < 6; m++)
2030 wr32(hw, GLQF_HSYMM(prof_id, m), 0);
2031 if (prof->cfg.symm) {
2032 struct ice_flow_seg_info *seg =
2033 &prof->segs[prof->segs_cnt - 1];
2035 struct ice_flow_seg_xtrct *ipv4_src =
2036 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_SA].xtrct;
2037 struct ice_flow_seg_xtrct *ipv4_dst =
2038 &seg->fields[ICE_FLOW_FIELD_IDX_IPV4_DA].xtrct;
2039 struct ice_flow_seg_xtrct *ipv6_src =
2040 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_SA].xtrct;
2041 struct ice_flow_seg_xtrct *ipv6_dst =
2042 &seg->fields[ICE_FLOW_FIELD_IDX_IPV6_DA].xtrct;
2044 struct ice_flow_seg_xtrct *tcp_src =
2045 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_SRC_PORT].xtrct;
2046 struct ice_flow_seg_xtrct *tcp_dst =
2047 &seg->fields[ICE_FLOW_FIELD_IDX_TCP_DST_PORT].xtrct;
2049 struct ice_flow_seg_xtrct *udp_src =
2050 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_SRC_PORT].xtrct;
2051 struct ice_flow_seg_xtrct *udp_dst =
2052 &seg->fields[ICE_FLOW_FIELD_IDX_UDP_DST_PORT].xtrct;
2054 struct ice_flow_seg_xtrct *sctp_src =
2055 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT].xtrct;
2056 struct ice_flow_seg_xtrct *sctp_dst =
2057 &seg->fields[ICE_FLOW_FIELD_IDX_SCTP_DST_PORT].xtrct;
2060 if (ipv4_src->prot_id != 0 && ipv4_dst->prot_id != 0)
2061 ice_rss_config_xor(hw, prof_id,
2062 ipv4_src->idx, ipv4_dst->idx, 2);
2065 if (ipv6_src->prot_id != 0 && ipv6_dst->prot_id != 0)
2066 ice_rss_config_xor(hw, prof_id,
2067 ipv6_src->idx, ipv6_dst->idx, 8);
2070 if (tcp_src->prot_id != 0 && tcp_dst->prot_id != 0)
2071 ice_rss_config_xor(hw, prof_id,
2072 tcp_src->idx, tcp_dst->idx, 1);
2075 if (udp_src->prot_id != 0 && udp_dst->prot_id != 0)
2076 ice_rss_config_xor(hw, prof_id,
2077 udp_src->idx, udp_dst->idx, 1);
2080 if (sctp_src->prot_id != 0 && sctp_dst->prot_id != 0)
2081 ice_rss_config_xor(hw, prof_id,
2082 sctp_src->idx, sctp_dst->idx, 1);
2087 * ice_add_rss_cfg_sync - add an RSS configuration
2088 * @hw: pointer to the hardware structure
2089 * @vsi_handle: software VSI handle
2090 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2091 * @addl_hdrs: protocol header fields
2092 * @segs_cnt: packet segment count
2093 * @symm: symmetric hash enable/disable
2095 * Assumption: lock has already been acquired for RSS list
2097 static enum ice_status
2098 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2099 u32 addl_hdrs, u8 segs_cnt, bool symm)
2101 const enum ice_block blk = ICE_BLK_RSS;
2102 struct ice_flow_prof *prof = NULL;
2103 struct ice_flow_seg_info *segs;
2104 enum ice_status status = ICE_SUCCESS;
2106 if (!segs_cnt || segs_cnt > ICE_FLOW_SEG_MAX)
2107 return ICE_ERR_PARAM;
2109 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2112 return ICE_ERR_NO_MEMORY;
2114 /* Construct the packet segment info from the hashed fields */
2115 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2120 /* Search for a flow profile that has matching headers, hash fields
2121 * and has the input VSI associated to it. If found, no further
2122 * operations required and exit.
2124 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2126 ICE_FLOW_FIND_PROF_CHK_FLDS |
2127 ICE_FLOW_FIND_PROF_CHK_VSI);
2129 if (prof->cfg.symm == symm)
2131 prof->cfg.symm = symm;
2135 /* Check if a flow profile exists with the same protocol headers and
2136 * associated with the input VSI. If so disasscociate the VSI from
2137 * this profile. The VSI will be added to a new profile created with
2138 * the protocol header and new hash field configuration.
2140 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2141 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
2143 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2145 ice_rem_rss_list(hw, vsi_handle, prof);
2149 /* Remove profile if it has no VSIs associated */
2150 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
2151 status = ice_flow_rem_prof(hw, blk, prof->id);
2157 /* Search for a profile that has same match fields only. If this
2158 * exists then associate the VSI to this profile.
2160 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2162 ICE_FLOW_FIND_PROF_CHK_FLDS);
2164 if (prof->cfg.symm == symm) {
2165 status = ice_flow_assoc_prof(hw, blk, prof,
2168 status = ice_add_rss_list(hw, vsi_handle,
2171 /* if a profile exist but with different symmetric
2172 * requirement, just return error.
2174 status = ICE_ERR_NOT_SUPPORTED;
2179 /* Create a new flow profile with generated profile and packet
2180 * segment information.
2182 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
2183 ICE_FLOW_GEN_PROFID(hashed_flds,
2184 segs[segs_cnt - 1].hdrs,
2186 segs, segs_cnt, NULL, 0, &prof);
2190 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
2191 /* If association to a new flow profile failed then this profile can
2195 ice_flow_rem_prof(hw, blk, prof->id);
2199 status = ice_add_rss_list(hw, vsi_handle, prof);
2201 prof->cfg.symm = symm;
2206 ice_rss_update_symm(hw, prof);
2214 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
2215 * @hw: pointer to the hardware structure
2216 * @vsi_handle: software VSI handle
2217 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
2218 * @addl_hdrs: protocol header fields
2219 * @symm: symmetric hash enable/disable
2221 * This function will generate a flow profile based on fields associated with
2222 * the input fields to hash on, the flow type and use the VSI number to add
2223 * a flow entry to the profile.
2226 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2227 u32 addl_hdrs, bool symm)
2229 enum ice_status status;
2231 if (hashed_flds == ICE_HASH_INVALID ||
2232 !ice_is_vsi_valid(hw, vsi_handle))
2233 return ICE_ERR_PARAM;
2235 ice_acquire_lock(&hw->rss_locks);
2236 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2237 ICE_RSS_OUTER_HEADERS, symm);
2239 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2240 addl_hdrs, ICE_RSS_INNER_HEADERS,
2242 ice_release_lock(&hw->rss_locks);
2248 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
2249 * @hw: pointer to the hardware structure
2250 * @vsi_handle: software VSI handle
2251 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2252 * @addl_hdrs: Protocol header fields within a packet segment
2253 * @segs_cnt: packet segment count
2255 * Assumption: lock has already been acquired for RSS list
2257 static enum ice_status
2258 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2259 u32 addl_hdrs, u8 segs_cnt)
2261 const enum ice_block blk = ICE_BLK_RSS;
2262 struct ice_flow_seg_info *segs;
2263 struct ice_flow_prof *prof;
2264 enum ice_status status;
2266 segs = (struct ice_flow_seg_info *)ice_calloc(hw, segs_cnt,
2269 return ICE_ERR_NO_MEMORY;
2271 /* Construct the packet segment info from the hashed fields */
2272 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds,
2277 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
2279 ICE_FLOW_FIND_PROF_CHK_FLDS);
2281 status = ICE_ERR_DOES_NOT_EXIST;
2285 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
2289 /* Remove RSS configuration from VSI context before deleting
2292 ice_rem_rss_list(hw, vsi_handle, prof);
2294 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
2295 status = ice_flow_rem_prof(hw, blk, prof->id);
2303 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2304 * @hw: pointer to the hardware structure
2305 * @vsi_handle: software VSI handle
2306 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2307 * @addl_hdrs: Protocol header fields within a packet segment
2309 * This function will lookup the flow profile based on the input
2310 * hash field bitmap, iterate through the profile entry list of
2311 * that profile and find entry associated with input VSI to be
2312 * removed. Calls are made to underlying flow apis which will in
2313 * turn build or update buffers for RSS XLT1 section.
2316 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2319 enum ice_status status;
2321 if (hashed_flds == ICE_HASH_INVALID ||
2322 !ice_is_vsi_valid(hw, vsi_handle))
2323 return ICE_ERR_PARAM;
2325 ice_acquire_lock(&hw->rss_locks);
2326 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
2327 ICE_RSS_OUTER_HEADERS);
2329 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds,
2330 addl_hdrs, ICE_RSS_INNER_HEADERS);
2331 ice_release_lock(&hw->rss_locks);
2337 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2338 * @hw: pointer to the hardware structure
2339 * @vsi_handle: software VSI handle
2341 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2343 enum ice_status status = ICE_SUCCESS;
2344 struct ice_rss_cfg *r;
2346 if (!ice_is_vsi_valid(hw, vsi_handle))
2347 return ICE_ERR_PARAM;
2349 ice_acquire_lock(&hw->rss_locks);
2350 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2351 ice_rss_cfg, l_entry) {
2352 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2353 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2356 ICE_RSS_OUTER_HEADERS,
2360 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2363 ICE_RSS_INNER_HEADERS,
2369 ice_release_lock(&hw->rss_locks);
2375 * ice_get_rss_cfg - returns hashed fields for the given header types
2376 * @hw: pointer to the hardware structure
2377 * @vsi_handle: software VSI handle
2378 * @hdrs: protocol header type
2380 * This function will return the match fields of the first instance of flow
2381 * profile having the given header types and containing input VSI
2383 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2385 struct ice_rss_cfg *r, *rss_cfg = NULL;
2387 /* verify if the protocol header is non zero and VSI is valid */
2388 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2389 return ICE_HASH_INVALID;
2391 ice_acquire_lock(&hw->rss_locks);
2392 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2393 ice_rss_cfg, l_entry)
2394 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2395 r->packet_hdr == hdrs) {
2399 ice_release_lock(&hw->rss_locks);
2401 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;