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
23 /* Protocol header fields are extracted at the word boundaries as word-sized
24 * values. Specify the displacement value of some non-word-aligned fields needed
25 * to compute the offset of words containing the fields in the corresponding
26 * protocol headers. Displacement values are expressed in number of bits.
28 #define ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP (-4)
29 #define ICE_FLOW_FLD_IPV6_TTL_PROT_DISP ((-2) * BITS_PER_BYTE)
30 #define ICE_FLOW_FLD_IPV6_TTL_TTL_DISP ((-1) * BITS_PER_BYTE)
32 /* Describe properties of a protocol header field */
33 struct ice_flow_field_info {
34 enum ice_flow_seg_hdr hdr;
35 s16 off; /* Offset from start of a protocol header, in bits */
36 u16 size; /* Size of fields in bits */
39 #define ICE_FLOW_FLD_INFO(_hdr, _offset_bytes, _size_bytes) { \
41 .off = _offset_bytes * BITS_PER_BYTE, \
42 .size = _size_bytes * BITS_PER_BYTE, \
45 /* Table containing properties of supported protocol header fields */
47 struct ice_flow_field_info ice_flds_info[ICE_FLOW_FIELD_IDX_MAX] = {
49 /* ICE_FLOW_FIELD_IDX_ETH_DA */
50 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 0, ETH_ALEN),
51 /* ICE_FLOW_FIELD_IDX_ETH_SA */
52 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, ETH_ALEN, ETH_ALEN),
53 /* ICE_FLOW_FIELD_IDX_S_VLAN */
54 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 12, ICE_FLOW_FLD_SZ_VLAN),
55 /* ICE_FLOW_FIELD_IDX_C_VLAN */
56 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_VLAN, 14, ICE_FLOW_FLD_SZ_VLAN),
57 /* ICE_FLOW_FIELD_IDX_ETH_TYPE */
58 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ETH, 12, ICE_FLOW_FLD_SZ_ETH_TYPE),
60 /* ICE_FLOW_FIELD_IDX_IP_DSCP */
61 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 1, 1),
62 /* ICE_FLOW_FIELD_IDX_IP_TTL */
63 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 8, 1),
64 /* ICE_FLOW_FIELD_IDX_IP_PROT */
65 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_NONE, 9, ICE_FLOW_FLD_SZ_IP_PROT),
66 /* ICE_FLOW_FIELD_IDX_IPV4_SA */
67 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 12, ICE_FLOW_FLD_SZ_IPV4_ADDR),
68 /* ICE_FLOW_FIELD_IDX_IPV4_DA */
69 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV4, 16, ICE_FLOW_FLD_SZ_IPV4_ADDR),
71 /* ICE_FLOW_FIELD_IDX_IPV6_SA */
72 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 8, ICE_FLOW_FLD_SZ_IPV6_ADDR),
73 /* ICE_FLOW_FIELD_IDX_IPV6_DA */
74 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_IPV6, 24, ICE_FLOW_FLD_SZ_IPV6_ADDR),
76 /* ICE_FLOW_FIELD_IDX_TCP_SRC_PORT */
77 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 0, ICE_FLOW_FLD_SZ_PORT),
78 /* ICE_FLOW_FIELD_IDX_TCP_DST_PORT */
79 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 2, ICE_FLOW_FLD_SZ_PORT),
80 /* ICE_FLOW_FIELD_IDX_UDP_SRC_PORT */
81 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 0, ICE_FLOW_FLD_SZ_PORT),
82 /* ICE_FLOW_FIELD_IDX_UDP_DST_PORT */
83 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, ICE_FLOW_FLD_SZ_PORT),
84 /* ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT */
85 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 0, ICE_FLOW_FLD_SZ_PORT),
86 /* ICE_FLOW_FIELD_IDX_SCTP_DST_PORT */
87 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_SCTP, 2, ICE_FLOW_FLD_SZ_PORT),
88 /* ICE_FLOW_FIELD_IDX_TCP_FLAGS */
89 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_TCP, 13, ICE_FLOW_FLD_SZ_TCP_FLAGS),
91 /* ICE_FLOW_FIELD_IDX_ARP_SIP */
92 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 14, ICE_FLOW_FLD_SZ_IPV4_ADDR),
93 /* ICE_FLOW_FIELD_IDX_ARP_DIP */
94 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 24, ICE_FLOW_FLD_SZ_IPV4_ADDR),
95 /* ICE_FLOW_FIELD_IDX_ARP_SHA */
96 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 8, ETH_ALEN),
97 /* ICE_FLOW_FIELD_IDX_ARP_DHA */
98 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 18, ETH_ALEN),
99 /* ICE_FLOW_FIELD_IDX_ARP_OP */
100 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ARP, 6, ICE_FLOW_FLD_SZ_ARP_OPER),
102 /* ICE_FLOW_FIELD_IDX_ICMP_TYPE */
103 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 0, ICE_FLOW_FLD_SZ_ICMP_TYPE),
104 /* ICE_FLOW_FIELD_IDX_ICMP_CODE */
105 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_ICMP, 1, ICE_FLOW_FLD_SZ_ICMP_CODE),
107 /* ICE_FLOW_FIELD_IDX_GRE_KEYID */
108 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_GRE, 12, ICE_FLOW_FLD_SZ_GRE_KEYID),
111 /* Bitmaps indicating relevant packet types for a particular protocol header
113 * Packet types for packets with an Outer/First/Single MAC header
115 static const u32 ice_ptypes_mac_ofos[] = {
116 0xFDC00CC6, 0xBFBF7F7E, 0xF7EFDFDF, 0xFEFDFDFB,
117 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
118 0x000B0F0F, 0x00000000, 0x00000000, 0x00000000,
119 0x00000000, 0x00000000, 0x00000000, 0x00000000,
120 0x00000000, 0x00000000, 0x00000000, 0x00000000,
121 0x00000000, 0x00000000, 0x00000000, 0x00000000,
122 0x00000000, 0x00000000, 0x00000000, 0x00000000,
123 0x00000000, 0x00000000, 0x00000000, 0x00000000,
126 /* Packet types for packets with an Innermost/Last MAC VLAN header */
127 static const u32 ice_ptypes_macvlan_il[] = {
128 0x00000000, 0xBC000000, 0x000001DF, 0xF0000000,
129 0x0000077E, 0x00000000, 0x00000000, 0x00000000,
130 0x00000000, 0x00000000, 0x00000000, 0x00000000,
131 0x00000000, 0x00000000, 0x00000000, 0x00000000,
132 0x00000000, 0x00000000, 0x00000000, 0x00000000,
133 0x00000000, 0x00000000, 0x00000000, 0x00000000,
134 0x00000000, 0x00000000, 0x00000000, 0x00000000,
135 0x00000000, 0x00000000, 0x00000000, 0x00000000,
138 /* Packet types for packets with an Outer/First/Single IPv4 header */
139 static const u32 ice_ptypes_ipv4_ofos[] = {
140 0xFDC00000, 0xBFBF7F7E, 0x00EFDFDF, 0x00000000,
141 0x00000000, 0x00000000, 0x00000000, 0x00000000,
142 0x0003000F, 0x00000000, 0x00000000, 0x00000000,
143 0x00000000, 0x00000000, 0x00000000, 0x00000000,
144 0x00000000, 0x00000000, 0x00000000, 0x00000000,
145 0x00000000, 0x00000000, 0x00000000, 0x00000000,
146 0x00000000, 0x00000000, 0x00000000, 0x00000000,
147 0x00000000, 0x00000000, 0x00000000, 0x00000000,
150 /* Packet types for packets with an Innermost/Last IPv4 header */
151 static const u32 ice_ptypes_ipv4_il[] = {
152 0xE0000000, 0xB807700E, 0x8001DC03, 0xE01DC03B,
153 0x0007700E, 0x00000000, 0x00000000, 0x00000000,
154 0x00000000, 0x00000000, 0x00000000, 0x00000000,
155 0x00000000, 0x00000000, 0x00000000, 0x00000000,
156 0x00000000, 0x00000000, 0x00000000, 0x00000000,
157 0x00000000, 0x00000000, 0x00000000, 0x00000000,
158 0x00000000, 0x00000000, 0x00000000, 0x00000000,
159 0x00000000, 0x00000000, 0x00000000, 0x00000000,
162 /* Packet types for packets with an Outer/First/Single IPv6 header */
163 static const u32 ice_ptypes_ipv6_ofos[] = {
164 0x00000000, 0x00000000, 0xF7000000, 0xFEFDFDFB,
165 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
166 0x00080F00, 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,
174 /* Packet types for packets with an Innermost/Last IPv6 header */
175 static const u32 ice_ptypes_ipv6_il[] = {
176 0x00000000, 0x03B80770, 0x00EE01DC, 0x0EE00000,
177 0x03B80770, 0x00000000, 0x00000000, 0x00000000,
178 0x00000000, 0x00000000, 0x00000000, 0x00000000,
179 0x00000000, 0x00000000, 0x00000000, 0x00000000,
180 0x00000000, 0x00000000, 0x00000000, 0x00000000,
181 0x00000000, 0x00000000, 0x00000000, 0x00000000,
182 0x00000000, 0x00000000, 0x00000000, 0x00000000,
183 0x00000000, 0x00000000, 0x00000000, 0x00000000,
186 /* Packet types for packets with an Outermost/First ARP header */
187 static const u32 ice_ptypes_arp_of[] = {
188 0x00000800, 0x00000000, 0x00000000, 0x00000000,
189 0x00000000, 0x00000000, 0x00000000, 0x00000000,
190 0x00000000, 0x00000000, 0x00000000, 0x00000000,
191 0x00000000, 0x00000000, 0x00000000, 0x00000000,
192 0x00000000, 0x00000000, 0x00000000, 0x00000000,
193 0x00000000, 0x00000000, 0x00000000, 0x00000000,
194 0x00000000, 0x00000000, 0x00000000, 0x00000000,
195 0x00000000, 0x00000000, 0x00000000, 0x00000000,
198 /* Packet types for packets with an Outermost/First UDP header */
199 static const u32 ice_ptypes_udp_of[] = {
200 0x81000000, 0x00000000, 0x04000000, 0x00000000,
201 0x00000000, 0x00000000, 0x00000000, 0x00000000,
202 0x00000000, 0x00000000, 0x00000000, 0x00000000,
203 0x00000000, 0x00000000, 0x00000000, 0x00000000,
204 0x00000000, 0x00000000, 0x00000000, 0x00000000,
205 0x00000000, 0x00000000, 0x00000000, 0x00000000,
206 0x00000000, 0x00000000, 0x00000000, 0x00000000,
207 0x00000000, 0x00000000, 0x00000000, 0x00000000,
210 /* Packet types for packets with an Innermost/Last UDP header */
211 static const u32 ice_ptypes_udp_il[] = {
212 0x80000000, 0x20204040, 0x00081010, 0x80810102,
213 0x00204040, 0x00000000, 0x00000000, 0x00000000,
214 0x00000000, 0x00000000, 0x00000000, 0x00000000,
215 0x00000000, 0x00000000, 0x00000000, 0x00000000,
216 0x00000000, 0x00000000, 0x00000000, 0x00000000,
217 0x00000000, 0x00000000, 0x00000000, 0x00000000,
218 0x00000000, 0x00000000, 0x00000000, 0x00000000,
219 0x00000000, 0x00000000, 0x00000000, 0x00000000,
222 /* Packet types for packets with an Innermost/Last TCP header */
223 static const u32 ice_ptypes_tcp_il[] = {
224 0x04000000, 0x80810102, 0x10204040, 0x42040408,
225 0x00810002, 0x00000000, 0x00000000, 0x00000000,
226 0x00000000, 0x00000000, 0x00000000, 0x00000000,
227 0x00000000, 0x00000000, 0x00000000, 0x00000000,
228 0x00000000, 0x00000000, 0x00000000, 0x00000000,
229 0x00000000, 0x00000000, 0x00000000, 0x00000000,
230 0x00000000, 0x00000000, 0x00000000, 0x00000000,
231 0x00000000, 0x00000000, 0x00000000, 0x00000000,
234 /* Packet types for packets with an Innermost/Last SCTP header */
235 static const u32 ice_ptypes_sctp_il[] = {
236 0x08000000, 0x01020204, 0x20408081, 0x04080810,
237 0x01020204, 0x00000000, 0x00000000, 0x00000000,
238 0x00000000, 0x00000000, 0x00000000, 0x00000000,
239 0x00000000, 0x00000000, 0x00000000, 0x00000000,
240 0x00000000, 0x00000000, 0x00000000, 0x00000000,
241 0x00000000, 0x00000000, 0x00000000, 0x00000000,
242 0x00000000, 0x00000000, 0x00000000, 0x00000000,
243 0x00000000, 0x00000000, 0x00000000, 0x00000000,
246 /* Packet types for packets with an Outermost/First ICMP header */
247 static const u32 ice_ptypes_icmp_of[] = {
248 0x10000000, 0x00000000, 0x00000000, 0x00000000,
249 0x00000000, 0x00000000, 0x00000000, 0x00000000,
250 0x00000000, 0x00000000, 0x00000000, 0x00000000,
251 0x00000000, 0x00000000, 0x00000000, 0x00000000,
252 0x00000000, 0x00000000, 0x00000000, 0x00000000,
253 0x00000000, 0x00000000, 0x00000000, 0x00000000,
254 0x00000000, 0x00000000, 0x00000000, 0x00000000,
255 0x00000000, 0x00000000, 0x00000000, 0x00000000,
258 /* Packet types for packets with an Innermost/Last ICMP header */
259 static const u32 ice_ptypes_icmp_il[] = {
260 0x00000000, 0x02040408, 0x40810102, 0x08101020,
261 0x02040408, 0x00000000, 0x00000000, 0x00000000,
262 0x00000000, 0x00000000, 0x00000000, 0x00000000,
263 0x00000000, 0x00000000, 0x00000000, 0x00000000,
264 0x00000000, 0x00000000, 0x00000000, 0x00000000,
265 0x00000000, 0x00000000, 0x00000000, 0x00000000,
266 0x00000000, 0x00000000, 0x00000000, 0x00000000,
267 0x00000000, 0x00000000, 0x00000000, 0x00000000,
270 /* Packet types for packets with an Outermost/First GRE header */
271 static const u32 ice_ptypes_gre_of[] = {
272 0x00000000, 0xBFBF7800, 0x00EFDFDF, 0xFEFDE000,
273 0x03BF7F7E, 0x00000000, 0x00000000, 0x00000000,
274 0x00000000, 0x00000000, 0x00000000, 0x00000000,
275 0x00000000, 0x00000000, 0x00000000, 0x00000000,
276 0x00000000, 0x00000000, 0x00000000, 0x00000000,
277 0x00000000, 0x00000000, 0x00000000, 0x00000000,
278 0x00000000, 0x00000000, 0x00000000, 0x00000000,
279 0x00000000, 0x00000000, 0x00000000, 0x00000000,
282 /* Packet types for packets with an Innermost/Last MAC header */
283 static const u32 ice_ptypes_mac_il[] = {
284 0x00000000, 0x00000000, 0x00EFDE00, 0x00000000,
285 0x03BF7800, 0x00000000, 0x00000000, 0x00000000,
286 0x00000000, 0x00000000, 0x00000000, 0x00000000,
287 0x00000000, 0x00000000, 0x00000000, 0x00000000,
288 0x00000000, 0x00000000, 0x00000000, 0x00000000,
289 0x00000000, 0x00000000, 0x00000000, 0x00000000,
290 0x00000000, 0x00000000, 0x00000000, 0x00000000,
291 0x00000000, 0x00000000, 0x00000000, 0x00000000,
294 /* Manage parameters and info. used during the creation of a flow profile */
295 struct ice_flow_prof_params {
297 struct ice_flow_prof *prof;
299 u16 entry_length; /* # of bytes formatted entry will require */
301 /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0
302 * This will give us the direction flags.
304 struct ice_fv_word es[ICE_MAX_FV_WORDS];
306 ice_declare_bitmap(ptypes, ICE_FLOW_PTYPE_MAX);
310 * ice_is_pow2 - check if integer value is a power of 2
311 * @val: unsigned integer to be validated
313 static bool ice_is_pow2(u64 val)
315 return (val && !(val & (val - 1)));
318 #define ICE_FLOW_SEG_HDRS_L2_MASK \
319 (ICE_FLOW_SEG_HDR_ETH | ICE_FLOW_SEG_HDR_VLAN)
320 #define ICE_FLOW_SEG_HDRS_L3_MASK \
321 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_ARP)
322 #define ICE_FLOW_SEG_HDRS_L4_MASK \
323 (ICE_FLOW_SEG_HDR_ICMP | ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
324 ICE_FLOW_SEG_HDR_SCTP)
327 * ice_flow_val_hdrs - validates packet segments for valid protocol headers
328 * @segs: array of one or more packet segments that describe the flow
329 * @segs_cnt: number of packet segments provided
331 static enum ice_status
332 ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt)
334 const u32 masks = (ICE_FLOW_SEG_HDRS_L2_MASK |
335 ICE_FLOW_SEG_HDRS_L3_MASK |
336 ICE_FLOW_SEG_HDRS_L4_MASK);
339 for (i = 0; i < segs_cnt; i++) {
340 /* No header specified */
341 if (!(segs[i].hdrs & masks) || (segs[i].hdrs & ~masks))
342 return ICE_ERR_PARAM;
344 /* Multiple L3 headers */
345 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK &&
346 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK))
347 return ICE_ERR_PARAM;
349 /* Multiple L4 headers */
350 if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK &&
351 !ice_is_pow2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK))
352 return ICE_ERR_PARAM;
358 /* Sizes of fixed known protocol headers without header options */
359 #define ICE_FLOW_PROT_HDR_SZ_MAC 14
360 #define ICE_FLOW_PROT_HDR_SZ_MAC_VLAN (ICE_FLOW_PROT_HDR_SZ_MAC + 2)
361 #define ICE_FLOW_PROT_HDR_SZ_IPV4 20
362 #define ICE_FLOW_PROT_HDR_SZ_IPV6 40
363 #define ICE_FLOW_PROT_HDR_SZ_ARP 28
364 #define ICE_FLOW_PROT_HDR_SZ_ICMP 8
365 #define ICE_FLOW_PROT_HDR_SZ_TCP 20
366 #define ICE_FLOW_PROT_HDR_SZ_UDP 8
367 #define ICE_FLOW_PROT_HDR_SZ_SCTP 12
370 * ice_flow_calc_seg_sz - calculates size of a packet segment based on headers
371 * @params: information about the flow to be processed
372 * @seg: index of packet segment whose header size is to be determined
374 static u16 ice_flow_calc_seg_sz(struct ice_flow_prof_params *params, u8 seg)
379 sz = (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_VLAN) ?
380 ICE_FLOW_PROT_HDR_SZ_MAC_VLAN : ICE_FLOW_PROT_HDR_SZ_MAC;
383 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4)
384 sz += ICE_FLOW_PROT_HDR_SZ_IPV4;
385 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
386 sz += ICE_FLOW_PROT_HDR_SZ_IPV6;
387 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ARP)
388 sz += ICE_FLOW_PROT_HDR_SZ_ARP;
389 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)
390 /* A L3 header is required if L4 is specified */
394 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_ICMP)
395 sz += ICE_FLOW_PROT_HDR_SZ_ICMP;
396 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_TCP)
397 sz += ICE_FLOW_PROT_HDR_SZ_TCP;
398 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_UDP)
399 sz += ICE_FLOW_PROT_HDR_SZ_UDP;
400 else if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_SCTP)
401 sz += ICE_FLOW_PROT_HDR_SZ_SCTP;
407 * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments
408 * @params: information about the flow to be processed
410 * This function identifies the packet types associated with the protocol
411 * headers being present in packet segments of the specified flow profile.
413 static enum ice_status
414 ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
416 struct ice_flow_prof *prof;
419 ice_memset(params->ptypes, 0xff, sizeof(params->ptypes),
424 for (i = 0; i < params->prof->segs_cnt; i++) {
425 const ice_bitmap_t *src;
428 if (i > 0 && (i + 1) < prof->segs_cnt)
431 hdrs = prof->segs[i].hdrs;
433 if (hdrs & ICE_FLOW_SEG_HDR_ETH) {
434 src = !i ? (const ice_bitmap_t *)ice_ptypes_mac_ofos :
435 (const ice_bitmap_t *)ice_ptypes_mac_il;
436 ice_and_bitmap(params->ptypes, params->ptypes, src,
438 hdrs &= ~ICE_FLOW_SEG_HDR_ETH;
441 if (i && hdrs & ICE_FLOW_SEG_HDR_VLAN) {
442 src = (const ice_bitmap_t *)ice_ptypes_macvlan_il;
443 ice_and_bitmap(params->ptypes, params->ptypes, src,
445 hdrs &= ~ICE_FLOW_SEG_HDR_VLAN;
448 if (!i && hdrs & ICE_FLOW_SEG_HDR_ARP) {
449 ice_and_bitmap(params->ptypes, params->ptypes,
450 (const ice_bitmap_t *)ice_ptypes_arp_of,
452 hdrs &= ~ICE_FLOW_SEG_HDR_ARP;
455 if (hdrs & ICE_FLOW_SEG_HDR_IPV4) {
456 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv4_ofos :
457 (const ice_bitmap_t *)ice_ptypes_ipv4_il;
458 ice_and_bitmap(params->ptypes, params->ptypes, src,
460 hdrs &= ~ICE_FLOW_SEG_HDR_IPV4;
461 } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
462 src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
463 (const ice_bitmap_t *)ice_ptypes_ipv6_il;
464 ice_and_bitmap(params->ptypes, params->ptypes, src,
466 hdrs &= ~ICE_FLOW_SEG_HDR_IPV6;
469 if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
470 src = !i ? (const ice_bitmap_t *)ice_ptypes_icmp_of :
471 (const ice_bitmap_t *)ice_ptypes_icmp_il;
472 ice_and_bitmap(params->ptypes, params->ptypes, src,
474 hdrs &= ~ICE_FLOW_SEG_HDR_ICMP;
475 } else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
476 src = !i ? (const ice_bitmap_t *)ice_ptypes_udp_of :
477 (const ice_bitmap_t *)ice_ptypes_udp_il;
478 ice_and_bitmap(params->ptypes, params->ptypes, src,
480 hdrs &= ~ICE_FLOW_SEG_HDR_UDP;
481 } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
482 ice_and_bitmap(params->ptypes, params->ptypes,
483 (const ice_bitmap_t *)ice_ptypes_tcp_il,
485 hdrs &= ~ICE_FLOW_SEG_HDR_TCP;
486 } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
487 src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
488 ice_and_bitmap(params->ptypes, params->ptypes, src,
490 hdrs &= ~ICE_FLOW_SEG_HDR_SCTP;
491 } else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
493 src = (const ice_bitmap_t *)ice_ptypes_gre_of;
494 ice_and_bitmap(params->ptypes, params->ptypes,
495 src, ICE_FLOW_PTYPE_MAX);
497 hdrs &= ~ICE_FLOW_SEG_HDR_GRE;
505 * ice_flow_xtract_pkt_flags - Create an extr sequence entry for packet flags
506 * @hw: pointer to the HW struct
507 * @params: information about the flow to be processed
508 * @flags: The value of pkt_flags[x:x] in RX/TX MDID metadata.
510 * This function will allocate an extraction sequence entries for a DWORD size
511 * chunk of the packet flags.
513 static enum ice_status
514 ice_flow_xtract_pkt_flags(struct ice_hw *hw,
515 struct ice_flow_prof_params *params,
516 enum ice_flex_mdid_pkt_flags flags)
518 u8 fv_words = hw->blk[params->blk].es.fvw;
521 /* Make sure the number of extraction sequence entries required does not
522 * exceed the block's capacity.
524 if (params->es_cnt >= fv_words)
525 return ICE_ERR_MAX_LIMIT;
527 /* some blocks require a reversed field vector layout */
528 if (hw->blk[params->blk].es.reverse)
529 idx = fv_words - params->es_cnt - 1;
531 idx = params->es_cnt;
533 params->es[idx].prot_id = ICE_PROT_META_ID;
534 params->es[idx].off = flags;
541 * ice_flow_xtract_fld - Create an extraction sequence entry for the given field
542 * @hw: pointer to the HW struct
543 * @params: information about the flow to be processed
544 * @seg: packet segment index of the field to be extracted
545 * @fld: ID of field to be extracted
547 * This function determines the protocol ID, offset, and size of the given
548 * field. It then allocates one or more extraction sequence entries for the
549 * given field, and fill the entries with protocol ID and offset information.
551 static enum ice_status
552 ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params,
553 u8 seg, enum ice_flow_field fld)
555 enum ice_flow_field sib = ICE_FLOW_FIELD_IDX_MAX;
556 enum ice_prot_id prot_id = ICE_PROT_ID_INVAL;
557 u8 fv_words = hw->blk[params->blk].es.fvw;
558 struct ice_flow_fld_info *flds;
559 u16 cnt, ese_bits, i;
563 flds = params->prof->segs[seg].fields;
566 case ICE_FLOW_FIELD_IDX_ETH_DA:
567 case ICE_FLOW_FIELD_IDX_ETH_SA:
568 case ICE_FLOW_FIELD_IDX_S_VLAN:
569 case ICE_FLOW_FIELD_IDX_C_VLAN:
570 prot_id = seg == 0 ? ICE_PROT_MAC_OF_OR_S : ICE_PROT_MAC_IL;
572 case ICE_FLOW_FIELD_IDX_ETH_TYPE:
573 prot_id = seg == 0 ? ICE_PROT_ETYPE_OL : ICE_PROT_ETYPE_IL;
575 case ICE_FLOW_FIELD_IDX_IP_DSCP:
576 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV6)
577 adj = ICE_FLOW_FLD_IPV6_TTL_DSCP_DISP;
579 case ICE_FLOW_FIELD_IDX_IP_TTL:
580 case ICE_FLOW_FIELD_IDX_IP_PROT:
581 /* Some fields are located at different offsets in IPv4 and
584 if (params->prof->segs[seg].hdrs & ICE_FLOW_SEG_HDR_IPV4) {
585 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S :
587 /* TTL and PROT share the same extraction seq. entry.
588 * Each is considered a sibling to the other in term
589 * sharing the same extraction sequence entry.
591 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
592 sib = ICE_FLOW_FIELD_IDX_IP_PROT;
593 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
594 sib = ICE_FLOW_FIELD_IDX_IP_TTL;
595 } else if (params->prof->segs[seg].hdrs &
596 ICE_FLOW_SEG_HDR_IPV6) {
597 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S :
599 if (fld == ICE_FLOW_FIELD_IDX_IP_TTL)
600 adj = ICE_FLOW_FLD_IPV6_TTL_TTL_DISP;
601 else if (fld == ICE_FLOW_FIELD_IDX_IP_PROT)
602 adj = ICE_FLOW_FLD_IPV6_TTL_PROT_DISP;
605 case ICE_FLOW_FIELD_IDX_IPV4_SA:
606 case ICE_FLOW_FIELD_IDX_IPV4_DA:
607 prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL;
609 case ICE_FLOW_FIELD_IDX_IPV6_SA:
610 case ICE_FLOW_FIELD_IDX_IPV6_DA:
611 prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL;
613 case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT:
614 case ICE_FLOW_FIELD_IDX_TCP_DST_PORT:
615 case ICE_FLOW_FIELD_IDX_TCP_FLAGS:
616 prot_id = ICE_PROT_TCP_IL;
618 case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT:
619 case ICE_FLOW_FIELD_IDX_UDP_DST_PORT:
620 prot_id = seg == 0 ? ICE_PROT_UDP_IL_OR_S : ICE_PROT_UDP_OF;
622 case ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT:
623 case ICE_FLOW_FIELD_IDX_SCTP_DST_PORT:
624 prot_id = ICE_PROT_SCTP_IL;
626 case ICE_FLOW_FIELD_IDX_ARP_SIP:
627 case ICE_FLOW_FIELD_IDX_ARP_DIP:
628 case ICE_FLOW_FIELD_IDX_ARP_SHA:
629 case ICE_FLOW_FIELD_IDX_ARP_DHA:
630 case ICE_FLOW_FIELD_IDX_ARP_OP:
631 prot_id = ICE_PROT_ARP_OF;
633 case ICE_FLOW_FIELD_IDX_ICMP_TYPE:
634 case ICE_FLOW_FIELD_IDX_ICMP_CODE:
635 /* ICMP type and code share the same extraction seq. entry */
636 prot_id = (params->prof->segs[seg].hdrs &
637 ICE_FLOW_SEG_HDR_IPV4) ?
638 ICE_PROT_ICMP_IL : ICE_PROT_ICMPV6_IL;
639 sib = fld == ICE_FLOW_FIELD_IDX_ICMP_TYPE ?
640 ICE_FLOW_FIELD_IDX_ICMP_CODE :
641 ICE_FLOW_FIELD_IDX_ICMP_TYPE;
643 case ICE_FLOW_FIELD_IDX_GRE_KEYID:
644 prot_id = ICE_PROT_GRE_OF;
647 return ICE_ERR_NOT_IMPL;
650 /* Each extraction sequence entry is a word in size, and extracts a
651 * word-aligned offset from a protocol header.
653 ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE;
655 flds[fld].xtrct.prot_id = prot_id;
656 flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) *
657 ICE_FLOW_FV_EXTRACT_SZ;
658 flds[fld].xtrct.disp = (u8)((ice_flds_info[fld].off + adj) % ese_bits);
659 flds[fld].xtrct.idx = params->es_cnt;
661 /* Adjust the next field-entry index after accommodating the number of
662 * entries this field consumes
664 cnt = DIVIDE_AND_ROUND_UP(flds[fld].xtrct.disp +
665 ice_flds_info[fld].size, ese_bits);
667 /* Fill in the extraction sequence entries needed for this field */
668 off = flds[fld].xtrct.off;
669 for (i = 0; i < cnt; i++) {
670 /* Only consume an extraction sequence entry if there is no
671 * sibling field associated with this field or the sibling entry
672 * already extracts the word shared with this field.
674 if (sib == ICE_FLOW_FIELD_IDX_MAX ||
675 flds[sib].xtrct.prot_id == ICE_PROT_ID_INVAL ||
676 flds[sib].xtrct.off != off) {
679 /* Make sure the number of extraction sequence required
680 * does not exceed the block's capability
682 if (params->es_cnt >= fv_words)
683 return ICE_ERR_MAX_LIMIT;
685 /* some blocks require a reversed field vector layout */
686 if (hw->blk[params->blk].es.reverse)
687 idx = fv_words - params->es_cnt - 1;
689 idx = params->es_cnt;
691 params->es[idx].prot_id = prot_id;
692 params->es[idx].off = off;
696 off += ICE_FLOW_FV_EXTRACT_SZ;
703 * ice_flow_xtract_raws - Create extract sequence entries for raw bytes
704 * @hw: pointer to the HW struct
705 * @params: information about the flow to be processed
706 * @seg: index of packet segment whose raw fields are to be be extracted
708 static enum ice_status
709 ice_flow_xtract_raws(struct ice_hw *hw, struct ice_flow_prof_params *params,
715 if (!params->prof->segs[seg].raws_cnt)
718 if (params->prof->segs[seg].raws_cnt >
719 ARRAY_SIZE(params->prof->segs[seg].raws))
720 return ICE_ERR_MAX_LIMIT;
722 /* Offsets within the segment headers are not supported */
723 hdrs_sz = ice_flow_calc_seg_sz(params, seg);
725 return ICE_ERR_PARAM;
727 for (i = 0; i < params->prof->segs[seg].raws_cnt; i++) {
728 struct ice_flow_seg_fld_raw *raw;
731 raw = ¶ms->prof->segs[seg].raws[i];
733 /* Only support matching raw fields in the payload */
734 if (raw->off < hdrs_sz)
735 return ICE_ERR_PARAM;
737 /* Convert the segment-relative offset into payload-relative
740 off = raw->off - hdrs_sz;
742 /* Storing extraction information */
743 raw->info.xtrct.prot_id = ICE_PROT_PAY;
744 raw->info.xtrct.off = (off / ICE_FLOW_FV_EXTRACT_SZ) *
745 ICE_FLOW_FV_EXTRACT_SZ;
746 raw->info.xtrct.disp = (off % ICE_FLOW_FV_EXTRACT_SZ) *
748 raw->info.xtrct.idx = params->es_cnt;
750 /* Determine the number of field vector entries this raw field
753 cnt = DIVIDE_AND_ROUND_UP(raw->info.xtrct.disp +
754 (raw->info.src.last * BITS_PER_BYTE),
755 (ICE_FLOW_FV_EXTRACT_SZ *
757 off = raw->info.xtrct.off;
758 for (j = 0; j < cnt; j++) {
759 /* Make sure the number of extraction sequence required
760 * does not exceed the block's capability
762 if (params->es_cnt >= hw->blk[params->blk].es.count ||
763 params->es_cnt >= ICE_MAX_FV_WORDS)
764 return ICE_ERR_MAX_LIMIT;
766 params->es[params->es_cnt].prot_id = ICE_PROT_PAY;
767 params->es[params->es_cnt].off = off;
769 off += ICE_FLOW_FV_EXTRACT_SZ;
777 * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments
778 * @hw: pointer to the HW struct
779 * @params: information about the flow to be processed
781 * This function iterates through all matched fields in the given segments, and
782 * creates an extraction sequence for the fields.
784 static enum ice_status
785 ice_flow_create_xtrct_seq(struct ice_hw *hw,
786 struct ice_flow_prof_params *params)
788 enum ice_status status = ICE_SUCCESS;
791 /* For ACL, we also need to extract the direction bit (Rx,Tx) data from
794 if (params->blk == ICE_BLK_ACL)
795 ice_flow_xtract_pkt_flags(hw, params,
796 ICE_RX_MDID_PKT_FLAGS_15_0);
798 for (i = 0; i < params->prof->segs_cnt; i++) {
799 u64 match = params->prof->segs[i].match;
802 for (j = 0; j < ICE_FLOW_FIELD_IDX_MAX && match; j++) {
803 const u64 bit = BIT_ULL(j);
806 status = ice_flow_xtract_fld
807 (hw, params, i, (enum ice_flow_field)j);
814 /* Process raw matching bytes */
815 status = ice_flow_xtract_raws(hw, params, i);
824 * ice_flow_proc_segs - process all packet segments associated with a profile
825 * @hw: pointer to the HW struct
826 * @params: information about the flow to be processed
828 static enum ice_status
829 ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params)
831 enum ice_status status;
833 status = ice_flow_proc_seg_hdrs(params);
837 status = ice_flow_create_xtrct_seq(hw, params);
841 switch (params->blk) {
843 /* Only header information is provided for RSS configuration.
844 * No further processing is needed.
846 status = ICE_SUCCESS;
849 status = ICE_SUCCESS;
853 return ICE_ERR_NOT_IMPL;
859 #define ICE_FLOW_FIND_PROF_CHK_FLDS 0x00000001
860 #define ICE_FLOW_FIND_PROF_CHK_VSI 0x00000002
863 * ice_flow_find_prof_conds - Find a profile matching headers and conditions
864 * @hw: pointer to the HW struct
865 * @blk: classification stage
866 * @dir: flow direction
867 * @segs: array of one or more packet segments that describe the flow
868 * @segs_cnt: number of packet segments provided
869 * @vsi_handle: software VSI handle to check VSI (ICE_FLOW_FIND_PROF_CHK_VSI)
870 * @conds: additional conditions to be checked (ICE_FLOW_FIND_PROF_CHK_*)
872 static struct ice_flow_prof *
873 ice_flow_find_prof_conds(struct ice_hw *hw, enum ice_block blk,
874 enum ice_flow_dir dir, struct ice_flow_seg_info *segs,
875 u8 segs_cnt, u16 vsi_handle, u32 conds)
877 struct ice_flow_prof *p;
879 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
880 if (p->dir == dir && segs_cnt && segs_cnt == p->segs_cnt) {
883 /* Check for profile-VSI association if specified */
884 if ((conds & ICE_FLOW_FIND_PROF_CHK_VSI) &&
885 ice_is_vsi_valid(hw, vsi_handle) &&
886 !ice_is_bit_set(p->vsis, vsi_handle))
889 /* Protocol headers must be checked. Matched fields are
890 * checked if specified.
892 for (i = 0; i < segs_cnt; i++)
893 if (segs[i].hdrs != p->segs[i].hdrs ||
894 ((conds & ICE_FLOW_FIND_PROF_CHK_FLDS) &&
895 segs[i].match != p->segs[i].match))
898 /* A match is found if all segments are matched */
908 * ice_flow_find_prof - Look up a profile matching headers and matched fields
909 * @hw: pointer to the HW struct
910 * @blk: classification stage
911 * @dir: flow direction
912 * @segs: array of one or more packet segments that describe the flow
913 * @segs_cnt: number of packet segments provided
916 ice_flow_find_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
917 struct ice_flow_seg_info *segs, u8 segs_cnt)
919 struct ice_flow_prof *p;
921 ice_acquire_lock(&hw->fl_profs_locks[blk]);
922 p = ice_flow_find_prof_conds(hw, blk, dir, segs, segs_cnt,
923 ICE_MAX_VSI, ICE_FLOW_FIND_PROF_CHK_FLDS);
924 ice_release_lock(&hw->fl_profs_locks[blk]);
926 return p ? p->id : ICE_FLOW_PROF_ID_INVAL;
930 * ice_flow_find_prof_id - Look up a profile with given profile ID
931 * @hw: pointer to the HW struct
932 * @blk: classification stage
933 * @prof_id: unique ID to identify this flow profile
935 static struct ice_flow_prof *
936 ice_flow_find_prof_id(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
938 struct ice_flow_prof *p;
940 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
941 if (p->id == prof_id)
949 * ice_flow_rem_entry_sync - Remove a flow entry
950 * @hw: pointer to the HW struct
951 * @entry: flow entry to be removed
953 static enum ice_status
954 ice_flow_rem_entry_sync(struct ice_hw *hw, struct ice_flow_entry *entry)
957 return ICE_ERR_BAD_PTR;
959 LIST_DEL(&entry->l_entry);
962 ice_free(hw, entry->entry);
965 ice_free(hw, entry->acts);
976 * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields
977 * @hw: pointer to the HW struct
978 * @blk: classification stage
979 * @dir: flow direction
980 * @prof_id: unique ID to identify this flow profile
981 * @segs: array of one or more packet segments that describe the flow
982 * @segs_cnt: number of packet segments provided
983 * @acts: array of default actions
984 * @acts_cnt: number of default actions
985 * @prof: stores the returned flow profile added
987 * Assumption: the caller has acquired the lock to the profile list
989 static enum ice_status
990 ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
991 enum ice_flow_dir dir, u64 prof_id,
992 struct ice_flow_seg_info *segs, u8 segs_cnt,
993 struct ice_flow_action *acts, u8 acts_cnt,
994 struct ice_flow_prof **prof)
996 struct ice_flow_prof_params params;
997 enum ice_status status = ICE_SUCCESS;
1000 if (!prof || (acts_cnt && !acts))
1001 return ICE_ERR_BAD_PTR;
1003 ice_memset(¶ms, 0, sizeof(params), ICE_NONDMA_MEM);
1004 params.prof = (struct ice_flow_prof *)
1005 ice_malloc(hw, sizeof(*params.prof));
1007 return ICE_ERR_NO_MEMORY;
1009 /* initialize extraction sequence to all invalid (0xff) */
1010 for (i = 0; i < ICE_MAX_FV_WORDS; i++) {
1011 params.es[i].prot_id = ICE_PROT_INVALID;
1012 params.es[i].off = ICE_FV_OFFSET_INVAL;
1016 params.prof->id = prof_id;
1017 params.prof->dir = dir;
1018 params.prof->segs_cnt = segs_cnt;
1020 /* Make a copy of the segments that need to be persistent in the flow
1023 for (i = 0; i < segs_cnt; i++)
1024 ice_memcpy(¶ms.prof->segs[i], &segs[i], sizeof(*segs),
1025 ICE_NONDMA_TO_NONDMA);
1027 /* Make a copy of the actions that need to be persistent in the flow
1031 params.prof->acts = (struct ice_flow_action *)
1032 ice_memdup(hw, acts, acts_cnt * sizeof(*acts),
1033 ICE_NONDMA_TO_NONDMA);
1035 if (!params.prof->acts) {
1036 status = ICE_ERR_NO_MEMORY;
1041 status = ice_flow_proc_segs(hw, ¶ms);
1043 ice_debug(hw, ICE_DBG_FLOW,
1044 "Error processing a flow's packet segments\n");
1048 /* Add a HW profile for this flow profile */
1049 status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es);
1051 ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n");
1055 INIT_LIST_HEAD(¶ms.prof->entries);
1056 ice_init_lock(¶ms.prof->entries_lock);
1057 *prof = params.prof;
1061 if (params.prof->acts)
1062 ice_free(hw, params.prof->acts);
1063 ice_free(hw, params.prof);
1070 * ice_flow_rem_prof_sync - remove a flow profile
1071 * @hw: pointer to the hardware structure
1072 * @blk: classification stage
1073 * @prof: pointer to flow profile to remove
1075 * Assumption: the caller has acquired the lock to the profile list
1077 static enum ice_status
1078 ice_flow_rem_prof_sync(struct ice_hw *hw, enum ice_block blk,
1079 struct ice_flow_prof *prof)
1081 enum ice_status status = ICE_SUCCESS;
1083 /* Remove all remaining flow entries before removing the flow profile */
1084 if (!LIST_EMPTY(&prof->entries)) {
1085 struct ice_flow_entry *e, *t;
1087 ice_acquire_lock(&prof->entries_lock);
1089 LIST_FOR_EACH_ENTRY_SAFE(e, t, &prof->entries, ice_flow_entry,
1091 status = ice_flow_rem_entry_sync(hw, e);
1096 ice_release_lock(&prof->entries_lock);
1099 /* Remove all hardware profiles associated with this flow profile */
1100 status = ice_rem_prof(hw, blk, prof->id);
1102 LIST_DEL(&prof->l_entry);
1103 ice_destroy_lock(&prof->entries_lock);
1105 ice_free(hw, prof->acts);
1113 * ice_flow_assoc_prof - associate a VSI with a flow profile
1114 * @hw: pointer to the hardware structure
1115 * @blk: classification stage
1116 * @prof: pointer to flow profile
1117 * @vsi_handle: software VSI handle
1119 * Assumption: the caller has acquired the lock to the profile list
1120 * and the software VSI handle has been validated
1122 static enum ice_status
1123 ice_flow_assoc_prof(struct ice_hw *hw, enum ice_block blk,
1124 struct ice_flow_prof *prof, u16 vsi_handle)
1126 enum ice_status status = ICE_SUCCESS;
1128 if (!ice_is_bit_set(prof->vsis, vsi_handle)) {
1129 status = ice_add_prof_id_flow(hw, blk,
1130 ice_get_hw_vsi_num(hw,
1134 ice_set_bit(vsi_handle, prof->vsis);
1136 ice_debug(hw, ICE_DBG_FLOW,
1137 "HW profile add failed, %d\n",
1145 * ice_flow_disassoc_prof - disassociate a VSI from a flow profile
1146 * @hw: pointer to the hardware structure
1147 * @blk: classification stage
1148 * @prof: pointer to flow profile
1149 * @vsi_handle: software VSI handle
1151 * Assumption: the caller has acquired the lock to the profile list
1152 * and the software VSI handle has been validated
1154 static enum ice_status
1155 ice_flow_disassoc_prof(struct ice_hw *hw, enum ice_block blk,
1156 struct ice_flow_prof *prof, u16 vsi_handle)
1158 enum ice_status status = ICE_SUCCESS;
1160 if (ice_is_bit_set(prof->vsis, vsi_handle)) {
1161 status = ice_rem_prof_id_flow(hw, blk,
1162 ice_get_hw_vsi_num(hw,
1166 ice_clear_bit(vsi_handle, prof->vsis);
1168 ice_debug(hw, ICE_DBG_FLOW,
1169 "HW profile remove failed, %d\n",
1177 * ice_flow_add_prof - Add a flow profile for packet segments and matched fields
1178 * @hw: pointer to the HW struct
1179 * @blk: classification stage
1180 * @dir: flow direction
1181 * @prof_id: unique ID to identify this flow profile
1182 * @segs: array of one or more packet segments that describe the flow
1183 * @segs_cnt: number of packet segments provided
1184 * @acts: array of default actions
1185 * @acts_cnt: number of default actions
1186 * @prof: stores the returned flow profile added
1189 ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir,
1190 u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt,
1191 struct ice_flow_action *acts, u8 acts_cnt,
1192 struct ice_flow_prof **prof)
1194 enum ice_status status;
1196 if (segs_cnt > ICE_FLOW_SEG_MAX)
1197 return ICE_ERR_MAX_LIMIT;
1200 return ICE_ERR_PARAM;
1203 return ICE_ERR_BAD_PTR;
1205 status = ice_flow_val_hdrs(segs, segs_cnt);
1209 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1211 status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt,
1212 acts, acts_cnt, prof);
1214 LIST_ADD(&(*prof)->l_entry, &hw->fl_profs[blk]);
1216 ice_release_lock(&hw->fl_profs_locks[blk]);
1222 * ice_flow_rem_prof - Remove a flow profile and all entries associated with it
1223 * @hw: pointer to the HW struct
1224 * @blk: the block for which the flow profile is to be removed
1225 * @prof_id: unique ID of the flow profile to be removed
1228 ice_flow_rem_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id)
1230 struct ice_flow_prof *prof;
1231 enum ice_status status;
1233 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1235 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1237 status = ICE_ERR_DOES_NOT_EXIST;
1241 /* prof becomes invalid after the call */
1242 status = ice_flow_rem_prof_sync(hw, blk, prof);
1245 ice_release_lock(&hw->fl_profs_locks[blk]);
1251 * ice_flow_get_hw_prof - return the HW profile for a specific profile ID handle
1252 * @hw: pointer to the HW struct
1253 * @blk: classification stage
1254 * @prof_id: the profile ID handle
1255 * @hw_prof_id: pointer to variable to receive the HW profile ID
1258 ice_flow_get_hw_prof(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1261 struct ice_prof_map *map;
1263 map = ice_search_prof_id(hw, blk, prof_id);
1265 *hw_prof_id = map->prof_id;
1269 return ICE_ERR_DOES_NOT_EXIST;
1273 * ice_flow_find_entry - look for a flow entry using its unique ID
1274 * @hw: pointer to the HW struct
1275 * @blk: classification stage
1276 * @entry_id: unique ID to identify this flow entry
1278 * This function looks for the flow entry with the specified unique ID in all
1279 * flow profiles of the specified classification stage. If the entry is found,
1280 * and it returns the handle to the flow entry. Otherwise, it returns
1281 * ICE_FLOW_ENTRY_ID_INVAL.
1283 u64 ice_flow_find_entry(struct ice_hw *hw, enum ice_block blk, u64 entry_id)
1285 struct ice_flow_entry *found = NULL;
1286 struct ice_flow_prof *p;
1288 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1290 LIST_FOR_EACH_ENTRY(p, &hw->fl_profs[blk], ice_flow_prof, l_entry) {
1291 struct ice_flow_entry *e;
1293 ice_acquire_lock(&p->entries_lock);
1294 LIST_FOR_EACH_ENTRY(e, &p->entries, ice_flow_entry, l_entry)
1295 if (e->id == entry_id) {
1299 ice_release_lock(&p->entries_lock);
1305 ice_release_lock(&hw->fl_profs_locks[blk]);
1307 return found ? ICE_FLOW_ENTRY_HNDL(found) : ICE_FLOW_ENTRY_HANDLE_INVAL;
1311 * ice_flow_add_entry - Add a flow entry
1312 * @hw: pointer to the HW struct
1313 * @blk: classification stage
1314 * @prof_id: ID of the profile to add a new flow entry to
1315 * @entry_id: unique ID to identify this flow entry
1316 * @vsi_handle: software VSI handle for the flow entry
1317 * @prio: priority of the flow entry
1318 * @data: pointer to a data buffer containing flow entry's match values/masks
1319 * @acts: arrays of actions to be performed on a match
1320 * @acts_cnt: number of actions
1321 * @entry_h: pointer to buffer that receives the new flow entry's handle
1324 ice_flow_add_entry(struct ice_hw *hw, enum ice_block blk, u64 prof_id,
1325 u64 entry_id, u16 vsi_handle, enum ice_flow_priority prio,
1326 void *data, struct ice_flow_action *acts, u8 acts_cnt,
1329 struct ice_flow_prof *prof = NULL;
1330 struct ice_flow_entry *e = NULL;
1331 enum ice_status status = ICE_SUCCESS;
1333 if (acts_cnt && !acts)
1334 return ICE_ERR_PARAM;
1336 /* No flow entry data is expected for RSS */
1337 if (!entry_h || (!data && blk != ICE_BLK_RSS))
1338 return ICE_ERR_BAD_PTR;
1340 if (!ice_is_vsi_valid(hw, vsi_handle))
1341 return ICE_ERR_PARAM;
1343 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1345 prof = ice_flow_find_prof_id(hw, blk, prof_id);
1347 status = ICE_ERR_DOES_NOT_EXIST;
1349 /* Allocate memory for the entry being added and associate
1350 * the VSI to the found flow profile
1352 e = (struct ice_flow_entry *)ice_malloc(hw, sizeof(*e));
1354 status = ICE_ERR_NO_MEMORY;
1356 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1359 ice_release_lock(&hw->fl_profs_locks[blk]);
1364 e->vsi_handle = vsi_handle;
1370 /* RSS will add only one entry per VSI per profile */
1377 status = ICE_ERR_NOT_IMPL;
1381 ice_acquire_lock(&prof->entries_lock);
1382 LIST_ADD(&e->l_entry, &prof->entries);
1383 ice_release_lock(&prof->entries_lock);
1385 *entry_h = ICE_FLOW_ENTRY_HNDL(e);
1390 ice_free(hw, e->entry);
1398 * ice_flow_rem_entry - Remove a flow entry
1399 * @hw: pointer to the HW struct
1400 * @entry_h: handle to the flow entry to be removed
1402 enum ice_status ice_flow_rem_entry(struct ice_hw *hw, u64 entry_h)
1404 struct ice_flow_entry *entry;
1405 struct ice_flow_prof *prof;
1406 enum ice_status status;
1408 if (entry_h == ICE_FLOW_ENTRY_HANDLE_INVAL)
1409 return ICE_ERR_PARAM;
1411 entry = ICE_FLOW_ENTRY_PTR((unsigned long)entry_h);
1413 /* Retain the pointer to the flow profile as the entry will be freed */
1416 ice_acquire_lock(&prof->entries_lock);
1417 status = ice_flow_rem_entry_sync(hw, entry);
1418 ice_release_lock(&prof->entries_lock);
1424 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer
1425 * @seg: packet segment the field being set belongs to
1426 * @fld: field to be set
1427 * @type: type of the field
1428 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1429 * entry's input buffer
1430 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1432 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1433 * entry's input buffer
1435 * This helper function stores information of a field being matched, including
1436 * the type of the field and the locations of the value to match, the mask, and
1437 * and the upper-bound value in the start of the input buffer for a flow entry.
1438 * This function should only be used for fixed-size data structures.
1440 * This function also opportunistically determines the protocol headers to be
1441 * present based on the fields being set. Some fields cannot be used alone to
1442 * determine the protocol headers present. Sometimes, fields for particular
1443 * protocol headers are not matched. In those cases, the protocol headers
1444 * must be explicitly set.
1447 ice_flow_set_fld_ext(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1448 enum ice_flow_fld_match_type type, u16 val_loc,
1449 u16 mask_loc, u16 last_loc)
1451 u64 bit = BIT_ULL(fld);
1454 if (type == ICE_FLOW_FLD_TYPE_RANGE)
1457 seg->fields[fld].type = type;
1458 seg->fields[fld].src.val = val_loc;
1459 seg->fields[fld].src.mask = mask_loc;
1460 seg->fields[fld].src.last = last_loc;
1462 ICE_FLOW_SET_HDRS(seg, ice_flds_info[fld].hdr);
1466 * ice_flow_set_fld - specifies locations of field from entry's input buffer
1467 * @seg: packet segment the field being set belongs to
1468 * @fld: field to be set
1469 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1470 * entry's input buffer
1471 * @mask_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of mask value from entry's
1473 * @last_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of last/upper value from
1474 * entry's input buffer
1475 * @range: indicate if field being matched is to be in a range
1477 * This function specifies the locations, in the form of byte offsets from the
1478 * start of the input buffer for a flow entry, from where the value to match,
1479 * the mask value, and upper value can be extracted. These locations are then
1480 * stored in the flow profile. When adding a flow entry associated with the
1481 * flow profile, these locations will be used to quickly extract the values and
1482 * create the content of a match entry. This function should only be used for
1483 * fixed-size data structures.
1486 ice_flow_set_fld(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1487 u16 val_loc, u16 mask_loc, u16 last_loc, bool range)
1489 enum ice_flow_fld_match_type t = range ?
1490 ICE_FLOW_FLD_TYPE_RANGE : ICE_FLOW_FLD_TYPE_REG;
1492 ice_flow_set_fld_ext(seg, fld, t, val_loc, mask_loc, last_loc);
1496 * ice_flow_set_fld_prefix - sets locations of prefix field from entry's buf
1497 * @seg: packet segment the field being set belongs to
1498 * @fld: field to be set
1499 * @val_loc: if not ICE_FLOW_FLD_OFF_INVAL, location of the value to match from
1500 * entry's input buffer
1501 * @pref_loc: location of prefix value from entry's input buffer
1502 * @pref_sz: size of the location holding the prefix value
1504 * This function specifies the locations, in the form of byte offsets from the
1505 * start of the input buffer for a flow entry, from where the value to match
1506 * and the IPv4 prefix value can be extracted. These locations are then stored
1507 * in the flow profile. When adding flow entries to the associated flow profile,
1508 * these locations can be used to quickly extract the values to create the
1509 * content of a match entry. This function should only be used for fixed-size
1513 ice_flow_set_fld_prefix(struct ice_flow_seg_info *seg, enum ice_flow_field fld,
1514 u16 val_loc, u16 pref_loc, u8 pref_sz)
1516 /* For this type of field, the "mask" location is for the prefix value's
1517 * location and the "last" location is for the size of the location of
1520 ice_flow_set_fld_ext(seg, fld, ICE_FLOW_FLD_TYPE_PREFIX, val_loc,
1521 pref_loc, (u16)pref_sz);
1525 * ice_flow_add_fld_raw - sets locations of a raw field from entry's input buf
1526 * @seg: packet segment the field being set belongs to
1527 * @off: offset of the raw field from the beginning of the segment in bytes
1528 * @len: length of the raw pattern to be matched
1529 * @val_loc: location of the value to match from entry's input buffer
1530 * @mask_loc: location of mask value from entry's input buffer
1532 * This function specifies the offset of the raw field to be match from the
1533 * beginning of the specified packet segment, and the locations, in the form of
1534 * byte offsets from the start of the input buffer for a flow entry, from where
1535 * the value to match and the mask value to be extracted. These locations are
1536 * then stored in the flow profile. When adding flow entries to the associated
1537 * flow profile, these locations can be used to quickly extract the values to
1538 * create the content of a match entry. This function should only be used for
1539 * fixed-size data structures.
1542 ice_flow_add_fld_raw(struct ice_flow_seg_info *seg, u16 off, u8 len,
1543 u16 val_loc, u16 mask_loc)
1545 if (seg->raws_cnt < ICE_FLOW_SEG_RAW_FLD_MAX) {
1546 seg->raws[seg->raws_cnt].off = off;
1547 seg->raws[seg->raws_cnt].info.type = ICE_FLOW_FLD_TYPE_SIZE;
1548 seg->raws[seg->raws_cnt].info.src.val = val_loc;
1549 seg->raws[seg->raws_cnt].info.src.mask = mask_loc;
1550 /* The "last" field is used to store the length of the field */
1551 seg->raws[seg->raws_cnt].info.src.last = len;
1554 /* Overflows of "raws" will be handled as an error condition later in
1555 * the flow when this information is processed.
1560 #define ICE_FLOW_RSS_SEG_HDR_L3_MASKS \
1561 (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6)
1563 #define ICE_FLOW_RSS_SEG_HDR_L4_MASKS \
1564 (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | \
1565 ICE_FLOW_SEG_HDR_SCTP)
1567 #define ICE_FLOW_RSS_SEG_HDR_VAL_MASKS \
1568 (ICE_FLOW_RSS_SEG_HDR_L3_MASKS | \
1569 ICE_FLOW_RSS_SEG_HDR_L4_MASKS)
1572 * ice_flow_set_rss_seg_info - setup packet segments for RSS
1573 * @segs: pointer to the flow field segment(s)
1574 * @hash_fields: fields to be hashed on for the segment(s)
1575 * @flow_hdr: protocol header fields within a packet segment
1577 * Helper function to extract fields from hash bitmap and use flow
1578 * header value to set flow field segment for further use in flow
1579 * profile entry or removal.
1581 static enum ice_status
1582 ice_flow_set_rss_seg_info(struct ice_flow_seg_info *segs, u64 hash_fields,
1585 u64 val = hash_fields;
1588 for (i = 0; val && i < ICE_FLOW_FIELD_IDX_MAX; i++) {
1589 u64 bit = BIT_ULL(i);
1592 ice_flow_set_fld(segs, (enum ice_flow_field)i,
1593 ICE_FLOW_FLD_OFF_INVAL,
1594 ICE_FLOW_FLD_OFF_INVAL,
1595 ICE_FLOW_FLD_OFF_INVAL, false);
1599 ICE_FLOW_SET_HDRS(segs, flow_hdr);
1601 if (segs->hdrs & ~ICE_FLOW_RSS_SEG_HDR_VAL_MASKS)
1602 return ICE_ERR_PARAM;
1604 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L3_MASKS);
1605 if (!ice_is_pow2(val))
1608 val = (u64)(segs->hdrs & ICE_FLOW_RSS_SEG_HDR_L4_MASKS);
1609 if (val && !ice_is_pow2(val))
1616 * ice_rem_vsi_rss_list - remove VSI from RSS list
1617 * @hw: pointer to the hardware structure
1618 * @vsi_handle: software VSI handle
1620 * Remove the VSI from all RSS configurations in the list.
1622 void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
1624 struct ice_rss_cfg *r, *tmp;
1626 if (LIST_EMPTY(&hw->rss_list_head))
1629 ice_acquire_lock(&hw->rss_locks);
1630 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1631 ice_rss_cfg, l_entry) {
1632 if (ice_is_bit_set(r->vsis, vsi_handle)) {
1633 ice_clear_bit(vsi_handle, r->vsis);
1635 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1636 LIST_DEL(&r->l_entry);
1641 ice_release_lock(&hw->rss_locks);
1645 * ice_rem_vsi_rss_cfg - remove RSS configurations associated with VSI
1646 * @hw: pointer to the hardware structure
1647 * @vsi_handle: software VSI handle
1649 * This function will iterate through all flow profiles and disassociate
1650 * the VSI from that profile. If the flow profile has no VSIs it will
1653 enum ice_status ice_rem_vsi_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
1655 const enum ice_block blk = ICE_BLK_RSS;
1656 struct ice_flow_prof *p, *t;
1657 enum ice_status status = ICE_SUCCESS;
1659 if (!ice_is_vsi_valid(hw, vsi_handle))
1660 return ICE_ERR_PARAM;
1662 ice_acquire_lock(&hw->fl_profs_locks[blk]);
1663 LIST_FOR_EACH_ENTRY_SAFE(p, t, &hw->fl_profs[blk], ice_flow_prof,
1665 if (ice_is_bit_set(p->vsis, vsi_handle)) {
1666 status = ice_flow_disassoc_prof(hw, blk, p, vsi_handle);
1670 if (!ice_is_any_bit_set(p->vsis, ICE_MAX_VSI)) {
1671 status = ice_flow_rem_prof_sync(hw, blk, p);
1677 ice_release_lock(&hw->fl_profs_locks[blk]);
1683 * ice_rem_rss_list - remove RSS configuration from list
1684 * @hw: pointer to the hardware structure
1685 * @vsi_handle: software VSI handle
1686 * @prof: pointer to flow profile
1688 * Assumption: lock has already been acquired for RSS list
1691 ice_rem_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1693 struct ice_rss_cfg *r, *tmp;
1695 /* Search for RSS hash fields associated to the VSI that match the
1696 * hash configurations associated to the flow profile. If found
1697 * remove from the RSS entry list of the VSI context and delete entry.
1699 LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
1700 ice_rss_cfg, l_entry) {
1701 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1702 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1703 ice_clear_bit(vsi_handle, r->vsis);
1704 if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
1705 LIST_DEL(&r->l_entry);
1714 * ice_add_rss_list - add RSS configuration to list
1715 * @hw: pointer to the hardware structure
1716 * @vsi_handle: software VSI handle
1717 * @prof: pointer to flow profile
1719 * Assumption: lock has already been acquired for RSS list
1721 static enum ice_status
1722 ice_add_rss_list(struct ice_hw *hw, u16 vsi_handle, struct ice_flow_prof *prof)
1724 struct ice_rss_cfg *r, *rss_cfg;
1726 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
1727 ice_rss_cfg, l_entry)
1728 if (r->hashed_flds == prof->segs[prof->segs_cnt - 1].match &&
1729 r->packet_hdr == prof->segs[prof->segs_cnt - 1].hdrs) {
1730 ice_set_bit(vsi_handle, r->vsis);
1734 rss_cfg = (struct ice_rss_cfg *)ice_malloc(hw, sizeof(*rss_cfg));
1736 return ICE_ERR_NO_MEMORY;
1738 rss_cfg->hashed_flds = prof->segs[prof->segs_cnt - 1].match;
1739 rss_cfg->packet_hdr = prof->segs[prof->segs_cnt - 1].hdrs;
1740 ice_set_bit(vsi_handle, rss_cfg->vsis);
1742 LIST_ADD_TAIL(&rss_cfg->l_entry, &hw->rss_list_head);
1747 #define ICE_FLOW_PROF_HASH_S 0
1748 #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S)
1749 #define ICE_FLOW_PROF_HDR_S 32
1750 #define ICE_FLOW_PROF_HDR_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HDR_S)
1752 #define ICE_FLOW_GEN_PROFID(hash, hdr) \
1753 (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \
1754 (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M))
1757 * ice_add_rss_cfg_sync - add an RSS configuration
1758 * @hw: pointer to the hardware structure
1759 * @vsi_handle: software VSI handle
1760 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1761 * @addl_hdrs: protocol header fields
1763 * Assumption: lock has already been acquired for RSS list
1765 static enum ice_status
1766 ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1769 const enum ice_block blk = ICE_BLK_RSS;
1770 struct ice_flow_prof *prof = NULL;
1771 struct ice_flow_seg_info *segs;
1772 enum ice_status status = ICE_SUCCESS;
1774 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1776 return ICE_ERR_NO_MEMORY;
1778 /* Construct the packet segment info from the hashed fields */
1779 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1783 /* Search for a flow profile that has matching headers, hash fields
1784 * and has the input VSI associated to it. If found, no further
1785 * operations required and exit.
1787 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1789 ICE_FLOW_FIND_PROF_CHK_FLDS |
1790 ICE_FLOW_FIND_PROF_CHK_VSI);
1794 /* Check if a flow profile exists with the same protocol headers and
1795 * associated with the input VSI. If so disasscociate the VSI from
1796 * this profile. The VSI will be added to a new profile created with
1797 * the protocol header and new hash field configuration.
1799 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1800 vsi_handle, ICE_FLOW_FIND_PROF_CHK_VSI);
1802 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1804 ice_rem_rss_list(hw, vsi_handle, prof);
1808 /* Remove profile if it has no VSIs associated */
1809 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI)) {
1810 status = ice_flow_rem_prof_sync(hw, blk, prof);
1816 /* Search for a profile that has same match fields only. If this
1817 * exists then associate the VSI to this profile.
1819 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1821 ICE_FLOW_FIND_PROF_CHK_FLDS);
1823 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1825 status = ice_add_rss_list(hw, vsi_handle, prof);
1829 /* Create a new flow profile with generated profile and packet
1830 * segment information.
1832 status = ice_flow_add_prof(hw, blk, ICE_FLOW_RX,
1833 ICE_FLOW_GEN_PROFID(hashed_flds, segs->hdrs),
1834 segs, 1, NULL, 0, &prof);
1838 status = ice_flow_assoc_prof(hw, blk, prof, vsi_handle);
1839 /* If association to a new flow profile failed then this profile can
1843 ice_flow_rem_prof_sync(hw, blk, prof);
1847 status = ice_add_rss_list(hw, vsi_handle, prof);
1855 * ice_add_rss_cfg - add an RSS configuration with specified hashed fields
1856 * @hw: pointer to the hardware structure
1857 * @vsi_handle: software VSI handle
1858 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure
1859 * @addl_hdrs: protocol header fields
1861 * This function will generate a flow profile based on fields associated with
1862 * the input fields to hash on, the flow type and use the VSI number to add
1863 * a flow entry to the profile.
1866 ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1869 enum ice_status status;
1871 if (hashed_flds == ICE_HASH_INVALID ||
1872 !ice_is_vsi_valid(hw, vsi_handle))
1873 return ICE_ERR_PARAM;
1875 ice_acquire_lock(&hw->rss_locks);
1876 status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
1877 ice_release_lock(&hw->rss_locks);
1883 * ice_rem_rss_cfg_sync - remove an existing RSS configuration
1884 * @hw: pointer to the hardware structure
1885 * @vsi_handle: software VSI handle
1886 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
1887 * @addl_hdrs: Protocol header fields within a packet segment
1889 * Assumption: lock has already been acquired for RSS list
1891 static enum ice_status
1892 ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
1895 const enum ice_block blk = ICE_BLK_RSS;
1896 struct ice_flow_seg_info *segs;
1897 struct ice_flow_prof *prof;
1898 enum ice_status status;
1900 segs = (struct ice_flow_seg_info *)ice_malloc(hw, sizeof(*segs));
1902 return ICE_ERR_NO_MEMORY;
1904 /* Construct the packet segment info from the hashed fields */
1905 status = ice_flow_set_rss_seg_info(segs, hashed_flds, addl_hdrs);
1909 prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, 1,
1911 ICE_FLOW_FIND_PROF_CHK_FLDS);
1913 status = ICE_ERR_DOES_NOT_EXIST;
1917 status = ice_flow_disassoc_prof(hw, blk, prof, vsi_handle);
1921 /* Remove RSS configuration from VSI context before deleting
1924 ice_rem_rss_list(hw, vsi_handle, prof);
1926 if (!ice_is_any_bit_set(prof->vsis, ICE_MAX_VSI))
1927 status = ice_flow_rem_prof_sync(hw, blk, prof);
1934 /* Mapping of AVF hash bit fields to an L3-L4 hash combination.
1935 * As the ice_flow_avf_hdr_field represent individual bit shifts in a hash,
1936 * convert its values to their appropriate flow L3, L4 values.
1938 #define ICE_FLOW_AVF_RSS_IPV4_MASKS \
1939 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_OTHER) | \
1940 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV4))
1941 #define ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS \
1942 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP_SYN_NO_ACK) | \
1943 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_TCP))
1944 #define ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS \
1945 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV4_UDP) | \
1946 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV4_UDP) | \
1947 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_UDP))
1948 #define ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS \
1949 (ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS | \
1950 ICE_FLOW_AVF_RSS_IPV4_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP))
1952 #define ICE_FLOW_AVF_RSS_IPV6_MASKS \
1953 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_OTHER) | \
1954 BIT_ULL(ICE_AVF_FLOW_FIELD_FRAG_IPV6))
1955 #define ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS \
1956 (BIT_ULL(ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP) | \
1957 BIT_ULL(ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP) | \
1958 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_UDP))
1959 #define ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS \
1960 (BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP_SYN_NO_ACK) | \
1961 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_TCP))
1962 #define ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS \
1963 (ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS | ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS | \
1964 ICE_FLOW_AVF_RSS_IPV6_MASKS | BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP))
1966 #define ICE_FLOW_MAX_CFG 10
1969 * ice_add_avf_rss_cfg - add an RSS configuration for AVF driver
1970 * @hw: pointer to the hardware structure
1971 * @vsi_handle: software VSI handle
1972 * @avf_hash: hash bit fields (ICE_AVF_FLOW_FIELD_*) to configure
1974 * This function will take the hash bitmap provided by the AVF driver via a
1975 * message, convert it to ICE-compatible values, and configure RSS flow
1979 ice_add_avf_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 avf_hash)
1981 enum ice_status status = ICE_SUCCESS;
1984 if (avf_hash == ICE_AVF_FLOW_FIELD_INVALID ||
1985 !ice_is_vsi_valid(hw, vsi_handle))
1986 return ICE_ERR_PARAM;
1988 /* Make sure no unsupported bits are specified */
1989 if (avf_hash & ~(ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS |
1990 ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS))
1993 hash_flds = avf_hash;
1995 /* Always create an L3 RSS configuration for any L4 RSS configuration */
1996 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS)
1997 hash_flds |= ICE_FLOW_AVF_RSS_IPV4_MASKS;
1999 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS)
2000 hash_flds |= ICE_FLOW_AVF_RSS_IPV6_MASKS;
2002 /* Create the corresponding RSS configuration for each valid hash bit */
2004 u64 rss_hash = ICE_HASH_INVALID;
2006 if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV4_MASKS) {
2007 if (hash_flds & ICE_FLOW_AVF_RSS_IPV4_MASKS) {
2008 rss_hash = ICE_FLOW_HASH_IPV4;
2009 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV4_MASKS;
2010 } else if (hash_flds &
2011 ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS) {
2012 rss_hash = ICE_FLOW_HASH_IPV4 |
2013 ICE_FLOW_HASH_TCP_PORT;
2014 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV4_MASKS;
2015 } else if (hash_flds &
2016 ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS) {
2017 rss_hash = ICE_FLOW_HASH_IPV4 |
2018 ICE_FLOW_HASH_UDP_PORT;
2019 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV4_MASKS;
2020 } else if (hash_flds &
2021 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP)) {
2022 rss_hash = ICE_FLOW_HASH_IPV4 |
2023 ICE_FLOW_HASH_SCTP_PORT;
2025 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV4_SCTP);
2027 } else if (hash_flds & ICE_FLOW_AVF_RSS_ALL_IPV6_MASKS) {
2028 if (hash_flds & ICE_FLOW_AVF_RSS_IPV6_MASKS) {
2029 rss_hash = ICE_FLOW_HASH_IPV6;
2030 hash_flds &= ~ICE_FLOW_AVF_RSS_IPV6_MASKS;
2031 } else if (hash_flds &
2032 ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS) {
2033 rss_hash = ICE_FLOW_HASH_IPV6 |
2034 ICE_FLOW_HASH_TCP_PORT;
2035 hash_flds &= ~ICE_FLOW_AVF_RSS_TCP_IPV6_MASKS;
2036 } else if (hash_flds &
2037 ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS) {
2038 rss_hash = ICE_FLOW_HASH_IPV6 |
2039 ICE_FLOW_HASH_UDP_PORT;
2040 hash_flds &= ~ICE_FLOW_AVF_RSS_UDP_IPV6_MASKS;
2041 } else if (hash_flds &
2042 BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP)) {
2043 rss_hash = ICE_FLOW_HASH_IPV6 |
2044 ICE_FLOW_HASH_SCTP_PORT;
2046 ~BIT_ULL(ICE_AVF_FLOW_FIELD_IPV6_SCTP);
2050 if (rss_hash == ICE_HASH_INVALID)
2051 return ICE_ERR_OUT_OF_RANGE;
2053 status = ice_add_rss_cfg(hw, vsi_handle, rss_hash,
2054 ICE_FLOW_SEG_HDR_NONE);
2063 * ice_rem_rss_cfg - remove an existing RSS config with matching hashed fields
2064 * @hw: pointer to the hardware structure
2065 * @vsi_handle: software VSI handle
2066 * @hashed_flds: Packet hash types (ICE_FLOW_HASH_*) to remove
2067 * @addl_hdrs: Protocol header fields within a packet segment
2069 * This function will lookup the flow profile based on the input
2070 * hash field bitmap, iterate through the profile entry list of
2071 * that profile and find entry associated with input VSI to be
2072 * removed. Calls are made to underlying flow apis which will in
2073 * turn build or update buffers for RSS XLT1 section.
2076 ice_rem_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
2079 enum ice_status status;
2081 if (hashed_flds == ICE_HASH_INVALID ||
2082 !ice_is_vsi_valid(hw, vsi_handle))
2083 return ICE_ERR_PARAM;
2085 ice_acquire_lock(&hw->rss_locks);
2086 status = ice_rem_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs);
2087 ice_release_lock(&hw->rss_locks);
2093 * ice_replay_rss_cfg - replay RSS configurations associated with VSI
2094 * @hw: pointer to the hardware structure
2095 * @vsi_handle: software VSI handle
2097 enum ice_status ice_replay_rss_cfg(struct ice_hw *hw, u16 vsi_handle)
2099 enum ice_status status = ICE_SUCCESS;
2100 struct ice_rss_cfg *r;
2102 if (!ice_is_vsi_valid(hw, vsi_handle))
2103 return ICE_ERR_PARAM;
2105 ice_acquire_lock(&hw->rss_locks);
2106 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2107 ice_rss_cfg, l_entry) {
2108 if (ice_is_bit_set(r->vsis, vsi_handle)) {
2109 status = ice_add_rss_cfg_sync(hw, vsi_handle,
2116 ice_release_lock(&hw->rss_locks);
2122 * ice_get_rss_cfg - returns hashed fields for the given header types
2123 * @hw: pointer to the hardware structure
2124 * @vsi_handle: software VSI handle
2125 * @hdrs: protocol header type
2127 * This function will return the match fields of the first instance of flow
2128 * profile having the given header types and containing input VSI
2130 u64 ice_get_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u32 hdrs)
2132 struct ice_rss_cfg *r, *rss_cfg = NULL;
2134 /* verify if the protocol header is non zero and VSI is valid */
2135 if (hdrs == ICE_FLOW_SEG_HDR_NONE || !ice_is_vsi_valid(hw, vsi_handle))
2136 return ICE_HASH_INVALID;
2138 ice_acquire_lock(&hw->rss_locks);
2139 LIST_FOR_EACH_ENTRY(r, &hw->rss_list_head,
2140 ice_rss_cfg, l_entry)
2141 if (ice_is_bit_set(r->vsis, vsi_handle) &&
2142 r->packet_hdr == hdrs) {
2146 ice_release_lock(&hw->rss_locks);
2148 return rss_cfg ? rss_cfg->hashed_flds : ICE_HASH_INVALID;