Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : :
5 : : #include <sys/queue.h>
6 : : #include <stdio.h>
7 : : #include <errno.h>
8 : : #include <stdint.h>
9 : : #include <string.h>
10 : : #include <assert.h>
11 : :
12 : : #include <rte_malloc.h>
13 : : #include <rte_tailq.h>
14 : : #include "base/i40e_prototype.h"
15 : : #include "i40e_logs.h"
16 : : #include "i40e_ethdev.h"
17 : : #include "i40e_hash.h"
18 : :
19 : : #include "../common/flow_check.h"
20 : :
21 : : #ifndef BIT
22 : : #define BIT(n) (1UL << (n))
23 : : #endif
24 : :
25 : : #ifndef BIT_ULL
26 : : #define BIT_ULL(n) (1ULL << (n))
27 : : #endif
28 : :
29 : : /* Pattern item headers */
30 : : #define I40E_HASH_HDR_ETH 0x01ULL
31 : : #define I40E_HASH_HDR_IPV4 0x10ULL
32 : : #define I40E_HASH_HDR_IPV6 0x20ULL
33 : : #define I40E_HASH_HDR_IPV6_FRAG 0x40ULL
34 : : #define I40E_HASH_HDR_TCP 0x100ULL
35 : : #define I40E_HASH_HDR_UDP 0x200ULL
36 : : #define I40E_HASH_HDR_SCTP 0x400ULL
37 : : #define I40E_HASH_HDR_ESP 0x10000ULL
38 : : #define I40E_HASH_HDR_L2TPV3 0x20000ULL
39 : : #define I40E_HASH_HDR_AH 0x40000ULL
40 : : #define I40E_HASH_HDR_GTPC 0x100000ULL
41 : : #define I40E_HASH_HDR_GTPU 0x200000ULL
42 : :
43 : : #define I40E_HASH_HDR_INNER_SHIFT 32
44 : : #define I40E_HASH_HDR_IPV4_INNER (I40E_HASH_HDR_IPV4 << \
45 : : I40E_HASH_HDR_INNER_SHIFT)
46 : : #define I40E_HASH_HDR_IPV6_INNER (I40E_HASH_HDR_IPV6 << \
47 : : I40E_HASH_HDR_INNER_SHIFT)
48 : :
49 : : /* ETH */
50 : : #define I40E_PHINT_ETH I40E_HASH_HDR_ETH
51 : :
52 : : /* IPv4 */
53 : : #define I40E_PHINT_IPV4 (I40E_HASH_HDR_ETH | I40E_HASH_HDR_IPV4)
54 : : #define I40E_PHINT_IPV4_TCP (I40E_PHINT_IPV4 | I40E_HASH_HDR_TCP)
55 : : #define I40E_PHINT_IPV4_UDP (I40E_PHINT_IPV4 | I40E_HASH_HDR_UDP)
56 : : #define I40E_PHINT_IPV4_SCTP (I40E_PHINT_IPV4 | I40E_HASH_HDR_SCTP)
57 : :
58 : : /* IPv6 */
59 : : #define I40E_PHINT_IPV6 (I40E_HASH_HDR_ETH | I40E_HASH_HDR_IPV6)
60 : : #define I40E_PHINT_IPV6_FRAG (I40E_PHINT_IPV6 | \
61 : : I40E_HASH_HDR_IPV6_FRAG)
62 : : #define I40E_PHINT_IPV6_TCP (I40E_PHINT_IPV6 | I40E_HASH_HDR_TCP)
63 : : #define I40E_PHINT_IPV6_UDP (I40E_PHINT_IPV6 | I40E_HASH_HDR_UDP)
64 : : #define I40E_PHINT_IPV6_SCTP (I40E_PHINT_IPV6 | I40E_HASH_HDR_SCTP)
65 : :
66 : : /* ESP */
67 : : #define I40E_PHINT_IPV4_ESP (I40E_PHINT_IPV4 | I40E_HASH_HDR_ESP)
68 : : #define I40E_PHINT_IPV6_ESP (I40E_PHINT_IPV6 | I40E_HASH_HDR_ESP)
69 : : #define I40E_PHINT_IPV4_UDP_ESP (I40E_PHINT_IPV4_UDP | \
70 : : I40E_HASH_HDR_ESP)
71 : : #define I40E_PHINT_IPV6_UDP_ESP (I40E_PHINT_IPV6_UDP | \
72 : : I40E_HASH_HDR_ESP)
73 : :
74 : : /* GTPC */
75 : : #define I40E_PHINT_IPV4_GTPC (I40E_PHINT_IPV4_UDP | \
76 : : I40E_HASH_HDR_GTPC)
77 : : #define I40E_PHINT_IPV6_GTPC (I40E_PHINT_IPV6_UDP | \
78 : : I40E_HASH_HDR_GTPC)
79 : :
80 : : /* GTPU */
81 : : #define I40E_PHINT_IPV4_GTPU (I40E_PHINT_IPV4_UDP | \
82 : : I40E_HASH_HDR_GTPU)
83 : : #define I40E_PHINT_IPV4_GTPU_IPV4 (I40E_PHINT_IPV4_GTPU | \
84 : : I40E_HASH_HDR_IPV4_INNER)
85 : : #define I40E_PHINT_IPV4_GTPU_IPV6 (I40E_PHINT_IPV4_GTPU | \
86 : : I40E_HASH_HDR_IPV6_INNER)
87 : : #define I40E_PHINT_IPV6_GTPU (I40E_PHINT_IPV6_UDP | \
88 : : I40E_HASH_HDR_GTPU)
89 : : #define I40E_PHINT_IPV6_GTPU_IPV4 (I40E_PHINT_IPV6_GTPU | \
90 : : I40E_HASH_HDR_IPV4_INNER)
91 : : #define I40E_PHINT_IPV6_GTPU_IPV6 (I40E_PHINT_IPV6_GTPU | \
92 : : I40E_HASH_HDR_IPV6_INNER)
93 : :
94 : : /* L2TPV3 */
95 : : #define I40E_PHINT_IPV4_L2TPV3 (I40E_PHINT_IPV4 | I40E_HASH_HDR_L2TPV3)
96 : : #define I40E_PHINT_IPV6_L2TPV3 (I40E_PHINT_IPV6 | I40E_HASH_HDR_L2TPV3)
97 : :
98 : : /* AH */
99 : : #define I40E_PHINT_IPV4_AH (I40E_PHINT_IPV4 | I40E_HASH_HDR_AH)
100 : : #define I40E_PHINT_IPV6_AH (I40E_PHINT_IPV6 | I40E_HASH_HDR_AH)
101 : :
102 : : /* Structure of mapping RSS type to input set */
103 : : struct i40e_hash_map_rss_inset {
104 : : uint64_t rss_type;
105 : : uint64_t inset;
106 : : };
107 : :
108 : : const struct i40e_hash_map_rss_inset i40e_hash_rss_inset[] = {
109 : : /* IPv4 */
110 : : { RTE_ETH_RSS_IPV4, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST },
111 : : { RTE_ETH_RSS_FRAG_IPV4, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST },
112 : :
113 : : { RTE_ETH_RSS_NONFRAG_IPV4_OTHER,
114 : : I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST },
115 : :
116 : : { RTE_ETH_RSS_NONFRAG_IPV4_TCP, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
117 : : I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },
118 : :
119 : : { RTE_ETH_RSS_NONFRAG_IPV4_UDP, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
120 : : I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },
121 : :
122 : : { RTE_ETH_RSS_NONFRAG_IPV4_SCTP, I40E_INSET_IPV4_SRC | I40E_INSET_IPV4_DST |
123 : : I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT },
124 : :
125 : : /* IPv6 */
126 : : { RTE_ETH_RSS_IPV6, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST },
127 : : { RTE_ETH_RSS_FRAG_IPV6, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST },
128 : :
129 : : { RTE_ETH_RSS_NONFRAG_IPV6_OTHER,
130 : : I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST },
131 : :
132 : : { RTE_ETH_RSS_NONFRAG_IPV6_TCP, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
133 : : I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },
134 : :
135 : : { RTE_ETH_RSS_NONFRAG_IPV6_UDP, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
136 : : I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },
137 : :
138 : : { RTE_ETH_RSS_NONFRAG_IPV6_SCTP, I40E_INSET_IPV6_SRC | I40E_INSET_IPV6_DST |
139 : : I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT | I40E_INSET_SCTP_VT },
140 : :
141 : : /* Port */
142 : : { RTE_ETH_RSS_PORT, I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT },
143 : :
144 : : /* Ether */
145 : : { RTE_ETH_RSS_L2_PAYLOAD, I40E_INSET_LAST_ETHER_TYPE },
146 : : { RTE_ETH_RSS_ETH, I40E_INSET_DMAC | I40E_INSET_SMAC },
147 : :
148 : : /* VLAN */
149 : : { RTE_ETH_RSS_S_VLAN, I40E_INSET_VLAN_OUTER },
150 : : { RTE_ETH_RSS_C_VLAN, I40E_INSET_VLAN_INNER },
151 : : };
152 : :
153 : : #define I40E_HASH_VOID_NEXT_ALLOW BIT_ULL(RTE_FLOW_ITEM_TYPE_ETH)
154 : :
155 : : #define I40E_HASH_ETH_NEXT_ALLOW (BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV4) | \
156 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6) | \
157 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_VLAN))
158 : :
159 : : #define I40E_HASH_IP_NEXT_ALLOW (BIT_ULL(RTE_FLOW_ITEM_TYPE_TCP) | \
160 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_UDP) | \
161 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_SCTP) | \
162 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_ESP) | \
163 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_L2TPV3OIP) |\
164 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_AH))
165 : :
166 : : #define I40E_HASH_IPV6_NEXT_ALLOW (I40E_HASH_IP_NEXT_ALLOW | \
167 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT))
168 : :
169 : : #define I40E_HASH_UDP_NEXT_ALLOW (BIT_ULL(RTE_FLOW_ITEM_TYPE_GTPU) | \
170 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_GTPC))
171 : :
172 : : #define I40E_HASH_GTPU_NEXT_ALLOW (BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV4) | \
173 : : BIT_ULL(RTE_FLOW_ITEM_TYPE_IPV6))
174 : :
175 : : static const uint64_t pattern_next_allow_items[] = {
176 : : [RTE_FLOW_ITEM_TYPE_VOID] = I40E_HASH_VOID_NEXT_ALLOW,
177 : : [RTE_FLOW_ITEM_TYPE_ETH] = I40E_HASH_ETH_NEXT_ALLOW,
178 : : [RTE_FLOW_ITEM_TYPE_IPV4] = I40E_HASH_IP_NEXT_ALLOW,
179 : : [RTE_FLOW_ITEM_TYPE_IPV6] = I40E_HASH_IPV6_NEXT_ALLOW,
180 : : [RTE_FLOW_ITEM_TYPE_UDP] = I40E_HASH_UDP_NEXT_ALLOW,
181 : : [RTE_FLOW_ITEM_TYPE_GTPU] = I40E_HASH_GTPU_NEXT_ALLOW,
182 : : };
183 : :
184 : : static const uint64_t pattern_item_header[] = {
185 : : [RTE_FLOW_ITEM_TYPE_ETH] = I40E_HASH_HDR_ETH,
186 : : [RTE_FLOW_ITEM_TYPE_IPV4] = I40E_HASH_HDR_IPV4,
187 : : [RTE_FLOW_ITEM_TYPE_IPV6] = I40E_HASH_HDR_IPV6,
188 : : [RTE_FLOW_ITEM_TYPE_IPV6_FRAG_EXT] = I40E_HASH_HDR_IPV6_FRAG,
189 : : [RTE_FLOW_ITEM_TYPE_TCP] = I40E_HASH_HDR_TCP,
190 : : [RTE_FLOW_ITEM_TYPE_UDP] = I40E_HASH_HDR_UDP,
191 : : [RTE_FLOW_ITEM_TYPE_SCTP] = I40E_HASH_HDR_SCTP,
192 : : [RTE_FLOW_ITEM_TYPE_ESP] = I40E_HASH_HDR_ESP,
193 : : [RTE_FLOW_ITEM_TYPE_GTPC] = I40E_HASH_HDR_GTPC,
194 : : [RTE_FLOW_ITEM_TYPE_GTPU] = I40E_HASH_HDR_GTPU,
195 : : [RTE_FLOW_ITEM_TYPE_L2TPV3OIP] = I40E_HASH_HDR_L2TPV3,
196 : : [RTE_FLOW_ITEM_TYPE_AH] = I40E_HASH_HDR_AH,
197 : : };
198 : :
199 : : /* Structure of matched pattern */
200 : : struct i40e_hash_match_pattern {
201 : : uint64_t pattern_type;
202 : : uint64_t rss_mask; /* Supported RSS type for this pattern */
203 : : bool custom_pctype_flag;/* true for custom packet type */
204 : : uint8_t pctype;
205 : : };
206 : :
207 : : #define I40E_HASH_MAP_PATTERN(pattern, rss_mask, pctype) { \
208 : : pattern, rss_mask, false, pctype }
209 : :
210 : : #define I40E_HASH_MAP_CUS_PATTERN(pattern, rss_mask, cus_pctype) { \
211 : : pattern, rss_mask, true, cus_pctype }
212 : :
213 : : #define I40E_HASH_L2_RSS_MASK (RTE_ETH_RSS_VLAN | RTE_ETH_RSS_ETH | \
214 : : RTE_ETH_RSS_L2_SRC_ONLY | \
215 : : RTE_ETH_RSS_L2_DST_ONLY)
216 : :
217 : : #define I40E_HASH_L23_RSS_MASK (I40E_HASH_L2_RSS_MASK | \
218 : : RTE_ETH_RSS_L3_SRC_ONLY | \
219 : : RTE_ETH_RSS_L3_DST_ONLY)
220 : :
221 : : #define I40E_HASH_IPV4_L23_RSS_MASK (RTE_ETH_RSS_IPV4 | I40E_HASH_L23_RSS_MASK)
222 : : #define I40E_HASH_IPV6_L23_RSS_MASK (RTE_ETH_RSS_IPV6 | I40E_HASH_L23_RSS_MASK)
223 : :
224 : : #define I40E_HASH_L234_RSS_MASK (I40E_HASH_L23_RSS_MASK | \
225 : : RTE_ETH_RSS_PORT | RTE_ETH_RSS_L4_SRC_ONLY | \
226 : : RTE_ETH_RSS_L4_DST_ONLY)
227 : :
228 : : #define I40E_HASH_IPV4_L234_RSS_MASK (I40E_HASH_L234_RSS_MASK | RTE_ETH_RSS_IPV4)
229 : : #define I40E_HASH_IPV6_L234_RSS_MASK (I40E_HASH_L234_RSS_MASK | RTE_ETH_RSS_IPV6)
230 : :
231 : : #define I40E_HASH_L4_TYPES (RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
232 : : RTE_ETH_RSS_NONFRAG_IPV4_UDP | \
233 : : RTE_ETH_RSS_NONFRAG_IPV4_SCTP | \
234 : : RTE_ETH_RSS_NONFRAG_IPV6_TCP | \
235 : : RTE_ETH_RSS_NONFRAG_IPV6_UDP | \
236 : : RTE_ETH_RSS_NONFRAG_IPV6_SCTP)
237 : :
238 : : const uint8_t i40e_rss_key_default[] = {
239 : : 0x44, 0x39, 0x79, 0x6b,
240 : : 0xb5, 0x4c, 0x50, 0x23,
241 : : 0xb6, 0x75, 0xea, 0x5b,
242 : : 0x12, 0x4f, 0x9f, 0x30,
243 : : 0xb8, 0xa2, 0xc0, 0x3d,
244 : : 0xdf, 0xdc, 0x4d, 0x02,
245 : : 0xa0, 0x8c, 0x9b, 0x33,
246 : : 0x4a, 0xf6, 0x4a, 0x4c,
247 : : 0x05, 0xc6, 0xfa, 0x34,
248 : : 0x39, 0x58, 0xd8, 0x55,
249 : : 0x7d, 0x99, 0x58, 0x3a,
250 : : 0xe1, 0x38, 0xc9, 0x2e,
251 : : 0x81, 0x15, 0x03, 0x66
252 : : };
253 : :
254 : : /* Current supported patterns and RSS types.
255 : : * All items that have the same pattern types are together.
256 : : */
257 : : static const struct i40e_hash_match_pattern match_patterns[] = {
258 : : /* Ether */
259 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_ETH,
260 : : RTE_ETH_RSS_L2_PAYLOAD | I40E_HASH_L2_RSS_MASK,
261 : : I40E_FILTER_PCTYPE_L2_PAYLOAD),
262 : :
263 : : /* IPv4 */
264 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4,
265 : : RTE_ETH_RSS_FRAG_IPV4 | I40E_HASH_IPV4_L23_RSS_MASK,
266 : : I40E_FILTER_PCTYPE_FRAG_IPV4),
267 : :
268 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4,
269 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER |
270 : : I40E_HASH_IPV4_L23_RSS_MASK,
271 : : I40E_FILTER_PCTYPE_NONF_IPV4_OTHER),
272 : :
273 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4_TCP,
274 : : RTE_ETH_RSS_NONFRAG_IPV4_TCP |
275 : : I40E_HASH_IPV4_L234_RSS_MASK,
276 : : I40E_FILTER_PCTYPE_NONF_IPV4_TCP),
277 : :
278 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4_UDP,
279 : : RTE_ETH_RSS_NONFRAG_IPV4_UDP |
280 : : I40E_HASH_IPV4_L234_RSS_MASK,
281 : : I40E_FILTER_PCTYPE_NONF_IPV4_UDP),
282 : :
283 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV4_SCTP,
284 : : RTE_ETH_RSS_NONFRAG_IPV4_SCTP |
285 : : I40E_HASH_IPV4_L234_RSS_MASK,
286 : : I40E_FILTER_PCTYPE_NONF_IPV4_SCTP),
287 : :
288 : : /* IPv6 */
289 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6,
290 : : RTE_ETH_RSS_FRAG_IPV6 | I40E_HASH_IPV6_L23_RSS_MASK,
291 : : I40E_FILTER_PCTYPE_FRAG_IPV6),
292 : :
293 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6,
294 : : RTE_ETH_RSS_NONFRAG_IPV6_OTHER |
295 : : I40E_HASH_IPV6_L23_RSS_MASK,
296 : : I40E_FILTER_PCTYPE_NONF_IPV6_OTHER),
297 : :
298 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_FRAG,
299 : : RTE_ETH_RSS_FRAG_IPV6 | I40E_HASH_L23_RSS_MASK,
300 : : I40E_FILTER_PCTYPE_FRAG_IPV6),
301 : :
302 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_TCP,
303 : : RTE_ETH_RSS_NONFRAG_IPV6_TCP |
304 : : I40E_HASH_IPV6_L234_RSS_MASK,
305 : : I40E_FILTER_PCTYPE_NONF_IPV6_TCP),
306 : :
307 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_UDP,
308 : : RTE_ETH_RSS_NONFRAG_IPV6_UDP |
309 : : I40E_HASH_IPV6_L234_RSS_MASK,
310 : : I40E_FILTER_PCTYPE_NONF_IPV6_UDP),
311 : :
312 : : I40E_HASH_MAP_PATTERN(I40E_PHINT_IPV6_SCTP,
313 : : RTE_ETH_RSS_NONFRAG_IPV6_SCTP |
314 : : I40E_HASH_IPV6_L234_RSS_MASK,
315 : : I40E_FILTER_PCTYPE_NONF_IPV6_SCTP),
316 : :
317 : : /* ESP */
318 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_ESP,
319 : : RTE_ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV4),
320 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_ESP,
321 : : RTE_ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV6),
322 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_UDP_ESP,
323 : : RTE_ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV4_UDP),
324 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_UDP_ESP,
325 : : RTE_ETH_RSS_ESP, I40E_CUSTOMIZED_ESP_IPV6_UDP),
326 : :
327 : : /* GTPC */
328 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPC,
329 : : I40E_HASH_IPV4_L234_RSS_MASK,
330 : : I40E_CUSTOMIZED_GTPC),
331 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPC,
332 : : I40E_HASH_IPV6_L234_RSS_MASK,
333 : : I40E_CUSTOMIZED_GTPC),
334 : :
335 : : /* GTPU */
336 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPU,
337 : : I40E_HASH_IPV4_L234_RSS_MASK,
338 : : I40E_CUSTOMIZED_GTPU),
339 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPU_IPV4,
340 : : RTE_ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV4),
341 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_GTPU_IPV6,
342 : : RTE_ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV6),
343 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPU,
344 : : I40E_HASH_IPV6_L234_RSS_MASK,
345 : : I40E_CUSTOMIZED_GTPU),
346 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPU_IPV4,
347 : : RTE_ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV4),
348 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_GTPU_IPV6,
349 : : RTE_ETH_RSS_GTPU, I40E_CUSTOMIZED_GTPU_IPV6),
350 : :
351 : : /* L2TPV3 */
352 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_L2TPV3,
353 : : RTE_ETH_RSS_L2TPV3, I40E_CUSTOMIZED_IPV4_L2TPV3),
354 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_L2TPV3,
355 : : RTE_ETH_RSS_L2TPV3, I40E_CUSTOMIZED_IPV6_L2TPV3),
356 : :
357 : : /* AH */
358 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV4_AH, RTE_ETH_RSS_AH,
359 : : I40E_CUSTOMIZED_AH_IPV4),
360 : : I40E_HASH_MAP_CUS_PATTERN(I40E_PHINT_IPV6_AH, RTE_ETH_RSS_AH,
361 : : I40E_CUSTOMIZED_AH_IPV6),
362 : : };
363 : :
364 : : static int
365 : 0 : i40e_hash_get_pattern_type(const struct rte_flow_item pattern[],
366 : : uint64_t *pattern_types,
367 : : struct rte_flow_error *error)
368 : : {
369 : : const char *message = "Pattern not supported";
370 : : enum rte_flow_item_type prev_item_type = RTE_FLOW_ITEM_TYPE_VOID;
371 : : enum rte_flow_item_type last_item_type = prev_item_type;
372 : : uint64_t item_hdr, pattern_hdrs = 0;
373 : : bool inner_flag = false;
374 : : int vlan_count = 0;
375 : :
376 [ # # ]: 0 : for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
377 [ # # ]: 0 : if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID)
378 : 0 : continue;
379 : :
380 [ # # # # : 0 : if (pattern->mask || pattern->spec || pattern->last) {
# # ]
381 : : message = "Header info should not be specified";
382 : 0 : goto not_sup;
383 : : }
384 : :
385 : : /* Check the previous item allows this sub-item. */
386 [ # # ]: 0 : if (prev_item_type >= (enum rte_flow_item_type)
387 : 0 : RTE_DIM(pattern_next_allow_items) ||
388 [ # # ]: 0 : !(pattern_next_allow_items[prev_item_type] &
389 : : BIT_ULL(pattern->type)))
390 : 0 : goto not_sup;
391 : :
392 : : /* For VLAN item, it does no matter about to pattern type
393 : : * recognition. So just count the number of VLAN and do not
394 : : * change the value of variable `prev_item_type`.
395 : : */
396 : : last_item_type = pattern->type;
397 [ # # ]: 0 : if (last_item_type == RTE_FLOW_ITEM_TYPE_VLAN) {
398 [ # # ]: 0 : if (vlan_count >= 2)
399 : 0 : goto not_sup;
400 : 0 : vlan_count++;
401 : 0 : continue;
402 : : }
403 : :
404 : : prev_item_type = last_item_type;
405 [ # # ]: 0 : if (last_item_type >= (enum rte_flow_item_type)
406 : : RTE_DIM(pattern_item_header))
407 : 0 : goto not_sup;
408 : :
409 : 0 : item_hdr = pattern_item_header[last_item_type];
410 [ # # ]: 0 : assert(item_hdr);
411 : :
412 [ # # ]: 0 : if (inner_flag) {
413 : 0 : item_hdr <<= I40E_HASH_HDR_INNER_SHIFT;
414 : :
415 : : /* Inner layer should not have GTPU item */
416 [ # # ]: 0 : if (last_item_type == RTE_FLOW_ITEM_TYPE_GTPU)
417 : 0 : goto not_sup;
418 : : } else {
419 [ # # ]: 0 : if (last_item_type == RTE_FLOW_ITEM_TYPE_GTPU) {
420 : : inner_flag = true;
421 : : vlan_count = 0;
422 : : }
423 : : }
424 : :
425 [ # # ]: 0 : if (item_hdr & pattern_hdrs)
426 : 0 : goto not_sup;
427 : :
428 : 0 : pattern_hdrs |= item_hdr;
429 : : }
430 : :
431 [ # # ]: 0 : if (pattern_hdrs && last_item_type != RTE_FLOW_ITEM_TYPE_VLAN) {
432 : 0 : *pattern_types = pattern_hdrs;
433 : 0 : return 0;
434 : : }
435 : :
436 : 0 : not_sup:
437 : 0 : return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
438 : : pattern, message);
439 : : }
440 : :
441 : : static uint64_t
442 : : i40e_hash_get_x722_ext_pctypes(uint8_t match_pctype)
443 : : {
444 : : uint64_t pctypes = 0;
445 : :
446 : : switch (match_pctype) {
447 : : case I40E_FILTER_PCTYPE_NONF_IPV4_TCP:
448 : : pctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
449 : : break;
450 : :
451 : : case I40E_FILTER_PCTYPE_NONF_IPV4_UDP:
452 : : pctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
453 : : BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
454 : : break;
455 : :
456 : : case I40E_FILTER_PCTYPE_NONF_IPV6_TCP:
457 : : pctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
458 : : break;
459 : :
460 : : case I40E_FILTER_PCTYPE_NONF_IPV6_UDP:
461 : : pctypes = BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
462 : : BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
463 : : break;
464 : : }
465 : :
466 : : return pctypes;
467 : : }
468 : :
469 : : static int
470 : 0 : i40e_hash_translate_gtp_inset(struct i40e_rte_flow_rss_conf *rss_conf,
471 : : struct rte_flow_error *error)
472 : : {
473 [ # # ]: 0 : if (rss_conf->inset &
474 : : (I40E_INSET_IPV4_SRC | I40E_INSET_IPV6_SRC |
475 : : I40E_INSET_DST_PORT | I40E_INSET_SRC_PORT))
476 : 0 : return rte_flow_error_set(error, ENOTSUP,
477 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
478 : : NULL,
479 : : "Only support external destination IP");
480 : :
481 [ # # ]: 0 : if (rss_conf->inset & I40E_INSET_IPV4_DST)
482 : 0 : rss_conf->inset = (rss_conf->inset & ~I40E_INSET_IPV4_DST) |
483 : : I40E_INSET_TUNNEL_IPV4_DST;
484 : :
485 [ # # ]: 0 : if (rss_conf->inset & I40E_INSET_IPV6_DST)
486 : 0 : rss_conf->inset = (rss_conf->inset & ~I40E_INSET_IPV6_DST) |
487 : : I40E_INSET_TUNNEL_IPV6_DST;
488 : :
489 : : return 0;
490 : : }
491 : :
492 : : static int
493 : 0 : i40e_hash_get_pctypes(const struct rte_eth_dev *dev,
494 : : const struct i40e_hash_match_pattern *match,
495 : : struct i40e_rte_flow_rss_conf *rss_conf,
496 : : struct rte_flow_error *error)
497 : : {
498 [ # # ]: 0 : if (match->custom_pctype_flag) {
499 : : struct i40e_pf *pf;
500 : : struct i40e_customized_pctype *custom_type;
501 : :
502 : 0 : pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
503 : 0 : custom_type = i40e_find_customized_pctype(pf, match->pctype);
504 [ # # # # ]: 0 : if (!custom_type || !custom_type->valid)
505 : 0 : return rte_flow_error_set(error, ENOTSUP,
506 : : RTE_FLOW_ERROR_TYPE_ITEM,
507 : : NULL, "PCTYPE not supported");
508 : :
509 : 0 : rss_conf->config_pctypes |= BIT_ULL(custom_type->pctype);
510 : :
511 [ # # ]: 0 : if (match->pctype == I40E_CUSTOMIZED_GTPU ||
512 : : match->pctype == I40E_CUSTOMIZED_GTPC)
513 : 0 : return i40e_hash_translate_gtp_inset(rss_conf, error);
514 : : } else {
515 : : struct i40e_hw *hw =
516 : 0 : I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
517 : : uint64_t types;
518 : :
519 : 0 : rss_conf->config_pctypes |= BIT_ULL(match->pctype);
520 [ # # ]: 0 : if (hw->mac.type == I40E_MAC_X722) {
521 : : types = i40e_hash_get_x722_ext_pctypes(match->pctype);
522 : 0 : rss_conf->config_pctypes |= types;
523 : : }
524 : : }
525 : :
526 : : return 0;
527 : : }
528 : :
529 : : static int
530 : 0 : i40e_hash_get_pattern_pctypes(const struct rte_eth_dev *dev,
531 : : const struct rte_flow_item pattern[],
532 : : const struct rte_flow_action_rss *rss_act,
533 : : struct i40e_rte_flow_rss_conf *rss_conf,
534 : : struct rte_flow_error *error)
535 : : {
536 : 0 : uint64_t pattern_types = 0;
537 : : bool match_flag = false;
538 : : int i, ret;
539 : :
540 : 0 : ret = i40e_hash_get_pattern_type(pattern, &pattern_types, error);
541 [ # # ]: 0 : if (ret)
542 : : return ret;
543 : :
544 [ # # ]: 0 : for (i = 0; i < (int)RTE_DIM(match_patterns); i++) {
545 : 0 : const struct i40e_hash_match_pattern *match =
546 : : &match_patterns[i];
547 : :
548 : : /* Check pattern types match. All items that have the same
549 : : * pattern types are together, so if the pattern types match
550 : : * previous item but they doesn't match current item, it means
551 : : * the pattern types do not match all remain items.
552 : : */
553 [ # # ]: 0 : if (pattern_types != match->pattern_type) {
554 [ # # ]: 0 : if (match_flag)
555 : : break;
556 : 0 : continue;
557 : : }
558 : : match_flag = true;
559 : :
560 : : /* Check RSS types match */
561 [ # # ]: 0 : if (!(rss_act->types & ~match->rss_mask)) {
562 : 0 : ret = i40e_hash_get_pctypes(dev, match,
563 : : rss_conf, error);
564 [ # # ]: 0 : if (ret)
565 : 0 : return ret;
566 : : }
567 : : }
568 : :
569 [ # # ]: 0 : if (rss_conf->config_pctypes)
570 : : return 0;
571 : :
572 [ # # ]: 0 : if (match_flag)
573 : 0 : return rte_flow_error_set(error, ENOTSUP,
574 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
575 : : NULL, "RSS types not supported");
576 : :
577 : 0 : return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
578 : : NULL, "Pattern not supported");
579 : : }
580 : :
581 : : static uint64_t
582 : 0 : i40e_hash_get_inset(uint64_t rss_types, bool symmetric_enable)
583 : : {
584 : : uint64_t mask, inset = 0;
585 : : int i;
586 : :
587 [ # # ]: 0 : for (i = 0; i < (int)RTE_DIM(i40e_hash_rss_inset); i++) {
588 [ # # ]: 0 : if (rss_types & i40e_hash_rss_inset[i].rss_type)
589 : 0 : inset |= i40e_hash_rss_inset[i].inset;
590 : : }
591 : :
592 [ # # ]: 0 : if (!inset)
593 : : return 0;
594 : :
595 : : /* If SRC_ONLY and DST_ONLY of the same level are used simultaneously,
596 : : * it is the same case as none of them are added.
597 : : */
598 : 0 : mask = rss_types & (RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY);
599 [ # # ]: 0 : if (mask == RTE_ETH_RSS_L2_SRC_ONLY)
600 : 0 : inset &= ~I40E_INSET_DMAC;
601 [ # # ]: 0 : else if (mask == RTE_ETH_RSS_L2_DST_ONLY)
602 : 0 : inset &= ~I40E_INSET_SMAC;
603 : :
604 : 0 : mask = rss_types & (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY);
605 [ # # ]: 0 : if (mask == RTE_ETH_RSS_L3_SRC_ONLY)
606 : 0 : inset &= ~(I40E_INSET_IPV4_DST | I40E_INSET_IPV6_DST);
607 [ # # ]: 0 : else if (mask == RTE_ETH_RSS_L3_DST_ONLY)
608 : 0 : inset &= ~(I40E_INSET_IPV4_SRC | I40E_INSET_IPV6_SRC);
609 : :
610 : 0 : mask = rss_types & (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY);
611 [ # # ]: 0 : if (mask == RTE_ETH_RSS_L4_SRC_ONLY)
612 : 0 : inset &= ~I40E_INSET_DST_PORT;
613 [ # # ]: 0 : else if (mask == RTE_ETH_RSS_L4_DST_ONLY)
614 : 0 : inset &= ~I40E_INSET_SRC_PORT;
615 : :
616 [ # # ]: 0 : if (rss_types & I40E_HASH_L4_TYPES) {
617 : : uint64_t l3_mask = rss_types &
618 : : (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY);
619 : : uint64_t l4_mask = rss_types &
620 : : (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY);
621 : :
622 [ # # ]: 0 : if (l3_mask && !l4_mask)
623 : 0 : inset &= ~(I40E_INSET_SRC_PORT | I40E_INSET_DST_PORT);
624 [ # # ]: 0 : else if (!l3_mask && l4_mask)
625 : 0 : inset &= ~(I40E_INSET_IPV4_DST | I40E_INSET_IPV6_DST |
626 : : I40E_INSET_IPV4_SRC | I40E_INSET_IPV6_SRC);
627 : : }
628 : :
629 : : /* SCTP Verification Tag is not required in hash computation for SYMMETRIC_TOEPLITZ */
630 [ # # ]: 0 : if (symmetric_enable) {
631 : 0 : mask = rss_types & RTE_ETH_RSS_NONFRAG_IPV4_SCTP;
632 [ # # ]: 0 : if (mask == RTE_ETH_RSS_NONFRAG_IPV4_SCTP)
633 : 0 : inset &= ~I40E_INSET_SCTP_VT;
634 : :
635 : 0 : mask = rss_types & RTE_ETH_RSS_NONFRAG_IPV6_SCTP;
636 [ # # ]: 0 : if (mask == RTE_ETH_RSS_NONFRAG_IPV6_SCTP)
637 : 0 : inset &= ~I40E_INSET_SCTP_VT;
638 : : }
639 : :
640 : : return inset;
641 : : }
642 : :
643 : : static int
644 : 0 : i40e_hash_config_func(struct i40e_hw *hw, enum rte_eth_hash_function func)
645 : : {
646 : : struct i40e_pf *pf;
647 : : uint32_t reg;
648 : : uint8_t symmetric = 0;
649 : :
650 : 0 : reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
651 : :
652 [ # # ]: 0 : if (func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR) {
653 [ # # ]: 0 : if (!(reg & I40E_GLQF_CTL_HTOEP_MASK))
654 : 0 : goto set_symmetric;
655 : :
656 : 0 : reg &= ~I40E_GLQF_CTL_HTOEP_MASK;
657 : : } else {
658 [ # # ]: 0 : if (func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ)
659 : : symmetric = 1;
660 : :
661 [ # # ]: 0 : if (reg & I40E_GLQF_CTL_HTOEP_MASK)
662 : 0 : goto set_symmetric;
663 : :
664 : 0 : reg |= I40E_GLQF_CTL_HTOEP_MASK;
665 : : }
666 : :
667 : 0 : pf = &((struct i40e_adapter *)hw->back)->pf;
668 [ # # ]: 0 : if (pf->support_multi_driver) {
669 : 0 : PMD_DRV_LOG(ERR,
670 : : "Modify hash function is not permitted when multi-driver enabled");
671 : 0 : return -EPERM;
672 : : }
673 : :
674 : 0 : PMD_DRV_LOG(INFO, "NIC hash function is setting to %d", func);
675 : 0 : i40e_write_rx_ctl(hw, I40E_GLQF_CTL, reg);
676 : 0 : I40E_WRITE_FLUSH(hw);
677 : :
678 : 0 : set_symmetric:
679 : 0 : i40e_set_symmetric_hash_enable_per_port(hw, symmetric);
680 : 0 : return 0;
681 : : }
682 : :
683 : : static int
684 : 0 : i40e_hash_config_pctype_symmetric(struct i40e_hw *hw,
685 : : uint32_t pctype,
686 : : bool symmetric)
687 : : {
688 : 0 : struct i40e_pf *pf = &((struct i40e_adapter *)hw->back)->pf;
689 : : uint32_t reg;
690 : :
691 : 0 : reg = i40e_read_rx_ctl(hw, I40E_GLQF_HSYM(pctype));
692 [ # # ]: 0 : if (symmetric) {
693 [ # # ]: 0 : if (reg & I40E_GLQF_HSYM_SYMH_ENA_MASK)
694 : : return 0;
695 : 0 : reg |= I40E_GLQF_HSYM_SYMH_ENA_MASK;
696 : : } else {
697 [ # # ]: 0 : if (!(reg & I40E_GLQF_HSYM_SYMH_ENA_MASK))
698 : : return 0;
699 : 0 : reg &= ~I40E_GLQF_HSYM_SYMH_ENA_MASK;
700 : : }
701 : :
702 [ # # ]: 0 : if (pf->support_multi_driver) {
703 : 0 : PMD_DRV_LOG(ERR,
704 : : "Enable/Disable symmetric hash is not permitted when multi-driver enabled");
705 : 0 : return -EPERM;
706 : : }
707 : :
708 : 0 : i40e_write_rx_ctl(hw, I40E_GLQF_HSYM(pctype), reg);
709 : 0 : I40E_WRITE_FLUSH(hw);
710 : 0 : return 0;
711 : : }
712 : :
713 : : static void
714 : 0 : i40e_hash_enable_pctype(struct i40e_hw *hw,
715 : : uint32_t pctype, bool enable)
716 : : {
717 : : uint32_t reg, reg_val, mask;
718 : :
719 [ # # ]: 0 : if (pctype < 32) {
720 : 0 : mask = BIT(pctype);
721 : : reg = I40E_PFQF_HENA(0);
722 : : } else {
723 : 0 : mask = BIT(pctype - 32);
724 : : reg = I40E_PFQF_HENA(1);
725 : : }
726 : :
727 : 0 : reg_val = i40e_read_rx_ctl(hw, reg);
728 : :
729 [ # # ]: 0 : if (enable) {
730 [ # # ]: 0 : if (reg_val & mask)
731 : : return;
732 : :
733 : 0 : reg_val |= mask;
734 : : } else {
735 [ # # ]: 0 : if (!(reg_val & mask))
736 : : return;
737 : :
738 : 0 : reg_val &= ~mask;
739 : : }
740 : :
741 : 0 : i40e_write_rx_ctl(hw, reg, reg_val);
742 : 0 : I40E_WRITE_FLUSH(hw);
743 : : }
744 : :
745 : : static int
746 : 0 : i40e_hash_config_pctype(struct i40e_hw *hw,
747 : : struct i40e_rte_flow_rss_conf *rss_conf,
748 : : uint32_t pctype)
749 : : {
750 : 0 : uint64_t rss_types = rss_conf->types;
751 : : int ret;
752 : :
753 [ # # ]: 0 : if (rss_types == 0) {
754 : 0 : i40e_hash_enable_pctype(hw, pctype, false);
755 : 0 : return 0;
756 : : }
757 : :
758 [ # # ]: 0 : if (rss_conf->inset) {
759 : 0 : ret = i40e_set_hash_inset(hw, rss_conf->inset, pctype, false);
760 [ # # ]: 0 : if (ret)
761 : : return ret;
762 : : }
763 : :
764 : 0 : i40e_hash_enable_pctype(hw, pctype, true);
765 : 0 : return 0;
766 : : }
767 : :
768 : : static int
769 : 0 : i40e_hash_config_region(struct i40e_pf *pf,
770 : : const struct i40e_rte_flow_rss_conf *rss_conf)
771 : : {
772 : 0 : struct i40e_hw *hw = &pf->adapter->hw;
773 : 0 : struct rte_eth_dev *dev = &rte_eth_devices[pf->dev_data->port_id];
774 : 0 : struct i40e_queue_region_info *regions = pf->queue_region.region;
775 : 0 : uint32_t num = pf->queue_region.queue_region_number;
776 : : uint32_t i, region_id_mask = 0;
777 : :
778 : : /* Use a 32 bit variable to represent all regions */
779 : : RTE_BUILD_BUG_ON(I40E_REGION_MAX_INDEX > 31);
780 : :
781 : : /* Re-configure the region if it existed */
782 [ # # ]: 0 : for (i = 0; i < num; i++) {
783 : 0 : if (rss_conf->region_queue_start ==
784 [ # # ]: 0 : regions[i].queue_start_index &&
785 [ # # ]: 0 : rss_conf->region_queue_num == regions[i].queue_num) {
786 : : uint32_t j;
787 : :
788 [ # # ]: 0 : for (j = 0; j < regions[i].user_priority_num; j++) {
789 : 0 : if (regions[i].user_priority[j] ==
790 [ # # ]: 0 : rss_conf->region_priority)
791 : : return 0;
792 : : }
793 : :
794 [ # # ]: 0 : if (j >= I40E_MAX_USER_PRIORITY) {
795 : 0 : PMD_DRV_LOG(ERR,
796 : : "Priority number exceed the maximum %d",
797 : : I40E_MAX_USER_PRIORITY);
798 : 0 : return -ENOSPC;
799 : : }
800 : :
801 : 0 : regions[i].user_priority[j] = rss_conf->region_priority;
802 : 0 : regions[i].user_priority_num++;
803 : 0 : return i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
804 : : }
805 : :
806 : 0 : region_id_mask |= BIT(regions[i].region_id);
807 : : }
808 : :
809 [ # # ]: 0 : if (num > I40E_REGION_MAX_INDEX) {
810 : 0 : PMD_DRV_LOG(ERR, "Queue region resource used up");
811 : 0 : return -ENOSPC;
812 : : }
813 : :
814 : : /* Add a new region */
815 : :
816 : 0 : pf->queue_region.queue_region_number++;
817 : 0 : memset(®ions[num], 0, sizeof(regions[0]));
818 : :
819 : 0 : regions[num].region_id = rte_bsf32(~region_id_mask);
820 : 0 : regions[num].queue_num = rss_conf->region_queue_num;
821 : 0 : regions[num].queue_start_index = rss_conf->region_queue_start;
822 : 0 : regions[num].user_priority[0] = rss_conf->region_priority;
823 : 0 : regions[num].user_priority_num = 1;
824 : :
825 : 0 : return i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
826 : : }
827 : :
828 : : static int
829 : 0 : i40e_hash_config(struct i40e_pf *pf,
830 : : struct i40e_rss_filter *filter)
831 : : {
832 : 0 : struct i40e_rte_flow_rss_conf *rss_conf = &filter->rss_filter_info;
833 : : struct i40e_rss_filter_data *filter_data = &filter->filter_data;
834 : 0 : struct i40e_hw *hw = &pf->adapter->hw;
835 : : uint64_t pctypes;
836 : : int ret;
837 : :
838 [ # # ]: 0 : if (rss_conf->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
839 : 0 : ret = i40e_hash_config_func(hw, rss_conf->func);
840 [ # # ]: 0 : if (ret)
841 : : return ret;
842 : :
843 [ # # ]: 0 : if (rss_conf->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ)
844 : 0 : filter_data->misc_reset_flags |=
845 : : I40E_HASH_FLOW_RESET_FLAG_FUNC;
846 : : }
847 : :
848 [ # # ]: 0 : if (rss_conf->region_queue_num > 0) {
849 : 0 : ret = i40e_hash_config_region(pf, rss_conf);
850 [ # # ]: 0 : if (ret)
851 : : return ret;
852 : :
853 : 0 : filter_data->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_REGION;
854 : : }
855 : :
856 [ # # ]: 0 : if (rss_conf->key_len > 0) {
857 : 0 : ret = i40e_set_rss_key(pf->main_vsi, rss_conf->key,
858 : : rss_conf->key_len);
859 [ # # ]: 0 : if (ret)
860 : : return ret;
861 : :
862 : 0 : filter_data->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_KEY;
863 : : }
864 : :
865 : : /* Update lookup table */
866 [ # # ]: 0 : if (rss_conf->queue_num > 0) {
867 : : uint8_t lut[RTE_ETH_RSS_RETA_SIZE_512];
868 : : uint32_t i, j = 0;
869 : :
870 [ # # ]: 0 : for (i = 0; i < hw->func_caps.rss_table_size; i++) {
871 : 0 : lut[i] = (uint8_t)rss_conf->queue[j];
872 [ # # ]: 0 : j = (j == rss_conf->queue_num - 1) ? 0 : (j + 1);
873 : : }
874 : :
875 : 0 : ret = i40e_set_rss_lut(pf->main_vsi, lut, (uint16_t)i);
876 [ # # ]: 0 : if (ret)
877 : 0 : return ret;
878 : :
879 : 0 : pf->hash_enabled_queues = 0;
880 [ # # ]: 0 : for (i = 0; i < rss_conf->queue_num; i++)
881 : 0 : pf->hash_enabled_queues |= BIT_ULL(lut[i]);
882 : :
883 : 0 : pf->adapter->rss_reta_updated = 0;
884 : 0 : filter_data->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_QUEUE;
885 : : }
886 : :
887 : : /* The codes behind configure the input sets and symmetric hash
888 : : * function of the packet types and enable hash on them.
889 : : */
890 : 0 : pctypes = rss_conf->config_pctypes;
891 [ # # ]: 0 : if (!pctypes)
892 : : return 0;
893 : :
894 : : /* For first flow that will enable hash on any packet type, we clean
895 : : * the RSS sets that by legacy configuration commands and parameters.
896 : : */
897 [ # # ]: 0 : if (!pf->hash_filter_enabled) {
898 : 0 : i40e_pf_disable_rss(pf);
899 : 0 : pf->hash_filter_enabled = true;
900 : : }
901 : :
902 : : do {
903 : : uint32_t idx = rte_bsf64(pctypes);
904 : 0 : uint64_t bit = BIT_ULL(idx);
905 : :
906 [ # # ]: 0 : if (rss_conf->symmetric_enable) {
907 : 0 : ret = i40e_hash_config_pctype_symmetric(hw, idx, true);
908 [ # # ]: 0 : if (ret)
909 : 0 : return ret;
910 : :
911 : 0 : filter_data->reset_symmetric_pctypes |= bit;
912 : : }
913 : :
914 : 0 : ret = i40e_hash_config_pctype(hw, rss_conf, idx);
915 [ # # ]: 0 : if (ret)
916 : 0 : return ret;
917 : :
918 : 0 : filter_data->reset_config_pctypes |= bit;
919 : 0 : pctypes &= ~bit;
920 [ # # ]: 0 : } while (pctypes);
921 : :
922 : : return 0;
923 : : }
924 : :
925 : : static void
926 : 0 : i40e_hash_parse_key(const struct rte_flow_action_rss *rss_act,
927 : : struct i40e_rte_flow_rss_conf *rss_conf)
928 : : {
929 : 0 : const uint8_t *key = rss_act->key;
930 : :
931 [ # # ]: 0 : if (key == NULL) {
932 : 0 : memcpy(rss_conf->key, i40e_rss_key_default, sizeof(rss_conf->key));
933 : : } else {
934 : 0 : memcpy(rss_conf->key, key, sizeof(rss_conf->key));
935 : : }
936 : :
937 : 0 : rss_conf->key_len = sizeof(rss_conf->key);
938 : 0 : }
939 : :
940 : : static int
941 : 0 : i40e_hash_parse_pattern_act(const struct rte_eth_dev *dev,
942 : : const struct rte_flow_item pattern[],
943 : : const struct rte_flow_action_rss *rss_act,
944 : : struct i40e_rte_flow_rss_conf *rss_conf,
945 : : struct rte_flow_error *error)
946 : : {
947 : 0 : rss_conf->symmetric_enable = rss_act->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
948 : :
949 [ # # ]: 0 : if (rss_act->key_len)
950 : 0 : i40e_hash_parse_key(rss_act, rss_conf);
951 : :
952 : 0 : rss_conf->func = rss_act->func;
953 : 0 : rss_conf->types = rss_act->types;
954 : 0 : rss_conf->inset = i40e_hash_get_inset(rss_act->types, rss_conf->symmetric_enable);
955 : :
956 : 0 : return i40e_hash_get_pattern_pctypes(dev, pattern, rss_act,
957 : : rss_conf, error);
958 : : }
959 : :
960 : : static int
961 : : i40e_hash_parse_queues(const struct rte_flow_action_rss *rss_act,
962 : : struct i40e_rte_flow_rss_conf *rss_conf)
963 : : {
964 : 0 : memcpy(rss_conf->queue, rss_act->queue,
965 : 0 : rss_act->queue_num * sizeof(rss_conf->queue[0]));
966 : 0 : rss_conf->queue_num = rss_act->queue_num;
967 : : return 0;
968 : : }
969 : :
970 : : static int
971 : 0 : i40e_hash_parse_queue_region(const struct rte_flow_item pattern[],
972 : : const struct rte_flow_action_rss *rss_act,
973 : : struct i40e_rte_flow_rss_conf *rss_conf,
974 : : struct rte_flow_error *error)
975 : : {
976 : : const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
977 : :
978 : 0 : vlan_spec = pattern->spec;
979 : 0 : vlan_mask = pattern->mask;
980 : :
981 : : /* VLAN must have spec and mask */
982 [ # # ]: 0 : if (vlan_spec == NULL || vlan_mask == NULL) {
983 : 0 : return rte_flow_error_set(error, EINVAL,
984 : : RTE_FLOW_ERROR_TYPE_ITEM, &pattern[0],
985 : : "VLAN pattern spec and mask required");
986 : : }
987 : : /* for mask, VLAN/TCI must be masked appropriately */
988 [ # # # # ]: 0 : if ((rte_be_to_cpu_16(vlan_mask->hdr.vlan_tci) >> 13) != 0x7) {
989 : 0 : return rte_flow_error_set(error, EINVAL,
990 : : RTE_FLOW_ERROR_TYPE_ITEM, &pattern[0],
991 : : "VLAN pattern mask invalid");
992 : : }
993 : :
994 : : /* Use a 64 bit variable to represent all queues in a region. */
995 : : RTE_BUILD_BUG_ON(I40E_MAX_Q_PER_TC > 64);
996 : :
997 : 0 : rss_conf->region_queue_num = (uint8_t)rss_act->queue_num;
998 : 0 : rss_conf->region_queue_start = rss_act->queue[0];
999 [ # # ]: 0 : rss_conf->region_priority = rte_be_to_cpu_16(vlan_spec->hdr.vlan_tci) >> 13;
1000 : 0 : return 0;
1001 : : }
1002 : :
1003 : : static bool
1004 : 0 : i40e_hash_validate_rss_types(uint64_t rss_types)
1005 : : {
1006 : : uint64_t type, mask;
1007 : :
1008 : : /* Validate L2 */
1009 : 0 : type = RTE_ETH_RSS_ETH & rss_types;
1010 : 0 : mask = (RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY) & rss_types;
1011 [ # # ]: 0 : if (!type && mask)
1012 : : return false;
1013 : :
1014 : : /* Validate L3 */
1015 : 0 : type = (I40E_HASH_L4_TYPES | RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
1016 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_IPV6 |
1017 : : RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_NONFRAG_IPV6_OTHER) & rss_types;
1018 : 0 : mask = (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY) & rss_types;
1019 [ # # ]: 0 : if (!type && mask)
1020 : : return false;
1021 : :
1022 : : /* Validate L4 */
1023 : 0 : type = (I40E_HASH_L4_TYPES | RTE_ETH_RSS_PORT) & rss_types;
1024 : 0 : mask = (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY) & rss_types;
1025 [ # # ]: 0 : if (!type && mask)
1026 : 0 : return false;
1027 : :
1028 : : return true;
1029 : : }
1030 : :
1031 : : static int
1032 : 0 : i40e_hash_validate_rss_pattern(const struct ci_flow_actions *actions,
1033 : : const struct ci_flow_actions_check_param *param __rte_unused,
1034 : : struct rte_flow_error *error)
1035 : : {
1036 : 0 : const struct rte_flow_action_rss *rss_act = actions->actions[0]->conf;
1037 : :
1038 : : /* queue list is not supported */
1039 [ # # ]: 0 : if (rss_act->queue_num != 0) {
1040 : 0 : return rte_flow_error_set(error, EINVAL,
1041 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1042 : : "RSS queues not supported when pattern specified");
1043 : : }
1044 : :
1045 : : /* disallow unsupported hash functions */
1046 [ # # ]: 0 : switch (rss_act->func) {
1047 : : case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
1048 : : case RTE_ETH_HASH_FUNCTION_DEFAULT:
1049 : : case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
1050 : : case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
1051 : : break;
1052 : 0 : default:
1053 : 0 : return rte_flow_error_set(error, EINVAL,
1054 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1055 : : "RSS hash function not supported when pattern specified");
1056 : : }
1057 : :
1058 [ # # ]: 0 : if (!i40e_hash_validate_rss_types(rss_act->types))
1059 : 0 : return rte_flow_error_set(error, EINVAL,
1060 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1061 : : rss_act, "RSS types are invalid");
1062 : :
1063 : : /* check RSS key length if it is specified */
1064 [ # # ]: 0 : if (rss_act->key_len != 0 && rss_act->key_len != I40E_RSS_KEY_LEN) {
1065 : 0 : return rte_flow_error_set(error, EINVAL,
1066 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1067 : : "RSS key length must be 52 bytes");
1068 : : }
1069 : :
1070 : : return 0;
1071 : : }
1072 : :
1073 : : static int
1074 : 0 : i40e_hash_validate_rss_common(const struct rte_flow_action_rss *rss_act,
1075 : : struct rte_flow_error *error)
1076 : : {
1077 : : /* RSS level is not supported */
1078 [ # # ]: 0 : if (rss_act->level != 0) {
1079 : 0 : return rte_flow_error_set(error, ENOTSUP,
1080 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1081 : : "RSS level is not supported");
1082 : : }
1083 : :
1084 : : /* for empty patterns, symmetric toeplitz is not supported */
1085 [ # # ]: 0 : if (rss_act->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {
1086 : 0 : return rte_flow_error_set(error, EINVAL,
1087 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1088 : : "Symmetric hash function not supported without specific patterns");
1089 : : }
1090 : :
1091 : : /*
1092 : : * When RSS types is not specified in testpmd, it will set up a default
1093 : : * RSS types value for the flow. Even though no hash engine part calling
1094 : : * this particular function will use RSS types parameter for anything,
1095 : : * we cannot reject having it because it is extra effort for testpmd
1096 : : * user to avoid specifying it.
1097 : : *
1098 : : * So, instead, accept types value even though we are not using it for
1099 : : * anything, but produce a warning for the user.
1100 : : */
1101 [ # # ]: 0 : if (rss_act->types != 0)
1102 : 0 : PMD_DRV_LOG(WARNING, "RSS types specified but will not be used");
1103 : :
1104 : : /* check RSS key length if it is specified */
1105 [ # # ]: 0 : if (rss_act->key_len != 0 && rss_act->key_len != I40E_RSS_KEY_LEN) {
1106 : 0 : return rte_flow_error_set(error, EINVAL,
1107 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1108 : : "RSS key length must be 52 bytes");
1109 : : }
1110 : :
1111 : : return 0;
1112 : : }
1113 : :
1114 : : static int
1115 : 0 : i40e_hash_validate_queue_region(const struct ci_flow_actions *actions,
1116 : : const struct ci_flow_actions_check_param *param,
1117 : : struct rte_flow_error *error)
1118 : : {
1119 : 0 : const struct rte_flow_action_rss *rss_act = actions->actions[0]->conf;
1120 : 0 : struct i40e_adapter *adapter = I40E_DEV_PRIVATE_TO_ADAPTER(param->driver_ctx);
1121 : : struct i40e_pf *pf = &adapter->pf;
1122 : : uint64_t hash_queues;
1123 : : int ret;
1124 : :
1125 : 0 : ret = i40e_hash_validate_rss_common(rss_act, error);
1126 [ # # ]: 0 : if (ret)
1127 : : return ret;
1128 : :
1129 : : RTE_BUILD_BUG_ON(sizeof(hash_queues) != sizeof(pf->hash_enabled_queues));
1130 : :
1131 : : /* having RSS key is not supported */
1132 [ # # ]: 0 : if (rss_act->key != NULL) {
1133 : 0 : return rte_flow_error_set(error, EINVAL,
1134 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1135 : : "RSS key not supported");
1136 : : }
1137 : :
1138 : : /* queue region must be specified */
1139 [ # # ]: 0 : if (rss_act->queue_num == 0) {
1140 : 0 : return rte_flow_error_set(error, EINVAL,
1141 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1142 : : "RSS queues missing");
1143 : : }
1144 : :
1145 : : /* queue region must be power of two */
1146 : : if (!rte_is_power_of_2(rss_act->queue_num)) {
1147 : 0 : return rte_flow_error_set(error, EINVAL,
1148 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1149 : : "RSS queue number must be power of two");
1150 : : }
1151 : :
1152 : : /* generic checks already filtered out discontiguous/non-unique RSS queues */
1153 : :
1154 : : /* queues must not exceed maximum queues per traffic class */
1155 [ # # ]: 0 : if (rss_act->queue[rss_act->queue_num - 1] >= I40E_MAX_Q_PER_TC) {
1156 : 0 : return rte_flow_error_set(error, EINVAL,
1157 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1158 : : "Invalid RSS queue index");
1159 : : }
1160 : :
1161 : : /* queues must be in LUT */
1162 : 0 : hash_queues = (BIT_ULL(rss_act->queue[0] + rss_act->queue_num) - 1) &
1163 : 0 : ~(BIT_ULL(rss_act->queue[0]) - 1);
1164 : :
1165 [ # # ]: 0 : if (hash_queues & ~pf->hash_enabled_queues) {
1166 : 0 : return rte_flow_error_set(error, EINVAL,
1167 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1168 : : rss_act, "Some queues are not in LUT");
1169 : : }
1170 : :
1171 : : return 0;
1172 : : }
1173 : :
1174 : : static int
1175 : 0 : i40e_hash_validate_queue_list(const struct ci_flow_actions *actions,
1176 : : const struct ci_flow_actions_check_param *param,
1177 : : struct rte_flow_error *error)
1178 : : {
1179 : 0 : const struct rte_flow_action_rss *rss_act = actions->actions[0]->conf;
1180 : 0 : struct i40e_adapter *adapter = I40E_DEV_PRIVATE_TO_ADAPTER(param->driver_ctx);
1181 : : struct i40e_pf *pf;
1182 : : struct i40e_hw *hw;
1183 : : uint16_t max_queue;
1184 : : bool has_queue, has_key;
1185 : : int ret;
1186 : :
1187 : 0 : ret = i40e_hash_validate_rss_common(rss_act, error);
1188 [ # # ]: 0 : if (ret)
1189 : : return ret;
1190 : :
1191 : 0 : has_queue = rss_act->queue != NULL;
1192 : 0 : has_key = rss_act->key != NULL;
1193 : :
1194 : : /* if we have queues, we must not have key */
1195 [ # # ]: 0 : if (has_queue && has_key) {
1196 : 0 : return rte_flow_error_set(error, EINVAL,
1197 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1198 : : "RSS key for queue region is not supported");
1199 : : }
1200 : :
1201 : : /* if there are no queues, no further checks needed */
1202 [ # # ]: 0 : if (!has_queue)
1203 : : return 0;
1204 : :
1205 : : /* check queue number limits */
1206 : : hw = &adapter->hw;
1207 [ # # ]: 0 : if (rss_act->queue_num > hw->func_caps.rss_table_size) {
1208 : 0 : return rte_flow_error_set(error, EINVAL,
1209 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1210 : : rss_act, "Too many RSS queues");
1211 : : }
1212 : :
1213 : 0 : pf = &adapter->pf;
1214 [ # # ]: 0 : if (pf->dev_data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG)
1215 : 0 : max_queue = i40e_pf_calc_configured_queues_num(pf);
1216 : : else
1217 : 0 : max_queue = pf->dev_data->nb_rx_queues;
1218 : :
1219 : 0 : max_queue = RTE_MIN(max_queue, I40E_MAX_Q_PER_TC);
1220 : :
1221 : : /* we know RSS queues are contiguous so we only need to check last queue */
1222 [ # # ]: 0 : if (rss_act->queue[rss_act->queue_num - 1] >= max_queue) {
1223 : 0 : return rte_flow_error_set(error, EINVAL,
1224 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1225 : : "Invalid RSS queue");
1226 : : }
1227 : :
1228 : : return 0;
1229 : : }
1230 : :
1231 : : int
1232 : 0 : i40e_hash_parse(struct rte_eth_dev *dev,
1233 : : const struct rte_flow_item pattern[],
1234 : : const struct rte_flow_action actions[],
1235 : : struct i40e_rte_flow_rss_conf *rss_conf,
1236 : : struct rte_flow_error *error)
1237 : : {
1238 : : struct ci_flow_actions parsed_actions;
1239 : 0 : struct ci_flow_actions_check_param ac_param = {
1240 : 0 : .allowed_types = (enum rte_flow_action_type[]) {
1241 : : RTE_FLOW_ACTION_TYPE_RSS,
1242 : : RTE_FLOW_ACTION_TYPE_END
1243 : : },
1244 : : .max_actions = 1,
1245 : 0 : .driver_ctx = dev->data->dev_private,
1246 : : /* each pattern type will add specific check function */
1247 : : };
1248 : : const struct rte_flow_action_rss *rss_act;
1249 : : int ret;
1250 : :
1251 : : /*
1252 : : * We have two possible paths: global RSS configuration, and an RSS pattern action.
1253 : : *
1254 : : * For global patterns, we act on two types of flows:
1255 : : * - Empty pattern ([END])
1256 : : * - VLAN pattern ([VLAN] -> [END])
1257 : : *
1258 : : * Everything else is handled by pattern action parser.
1259 : : */
1260 : : bool is_empty, is_vlan;
1261 : :
1262 [ # # ]: 0 : while (pattern->type == RTE_FLOW_ITEM_TYPE_VOID)
1263 : 0 : pattern++;
1264 : :
1265 : : is_empty = pattern[0].type == RTE_FLOW_ITEM_TYPE_END;
1266 [ # # ]: 0 : is_vlan = pattern[0].type == RTE_FLOW_ITEM_TYPE_VLAN &&
1267 [ # # ]: 0 : pattern[1].type == RTE_FLOW_ITEM_TYPE_END;
1268 : :
1269 : : /* VLAN path */
1270 [ # # ]: 0 : if (is_vlan) {
1271 : 0 : ac_param.check = i40e_hash_validate_queue_region;
1272 : : /* queue regions must be contiguous */
1273 : 0 : ac_param.rss_queues_contig = true;
1274 : 0 : ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
1275 [ # # ]: 0 : if (ret)
1276 : : return ret;
1277 : 0 : rss_act = parsed_actions.actions[0]->conf;
1278 : : /* set up RSS functions */
1279 : 0 : rss_conf->func = rss_act->func;
1280 : 0 : return i40e_hash_parse_queue_region(pattern, rss_act, rss_conf, error);
1281 : : }
1282 : : /* Empty pattern path */
1283 [ # # ]: 0 : if (is_empty) {
1284 : 0 : ac_param.check = i40e_hash_validate_queue_list;
1285 : 0 : ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
1286 [ # # ]: 0 : if (ret)
1287 : : return ret;
1288 : 0 : rss_act = parsed_actions.actions[0]->conf;
1289 : 0 : rss_conf->func = rss_act->func;
1290 : : /* if there is a queue list, take that path */
1291 [ # # ]: 0 : if (rss_act->queue != NULL)
1292 : 0 : return i40e_hash_parse_queues(rss_act, rss_conf);
1293 : :
1294 : : /* otherwise just parse RSS key */
1295 [ # # ]: 0 : if (rss_act->key != NULL)
1296 : 0 : i40e_hash_parse_key(rss_act, rss_conf);
1297 : :
1298 : 0 : return 0;
1299 : : }
1300 : 0 : ac_param.check = i40e_hash_validate_rss_pattern;
1301 : 0 : ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
1302 [ # # ]: 0 : if (ret)
1303 : : return ret;
1304 : 0 : rss_act = parsed_actions.actions[0]->conf;
1305 : :
1306 : : /* pattern case */
1307 : 0 : return i40e_hash_parse_pattern_act(dev, pattern, rss_act, rss_conf, error);
1308 : : }
1309 : :
1310 : : static void
1311 : 0 : i40e_invalid_rss_filter(const struct i40e_rss_filter *ref,
1312 : : struct i40e_rss_filter *filter)
1313 : : {
1314 : : const struct i40e_rte_flow_rss_conf *ref_conf = &ref->rss_filter_info;
1315 : : const struct i40e_rss_filter_data *ref_data = &ref->filter_data;
1316 : : const struct i40e_rte_flow_rss_conf *conf = &filter->rss_filter_info;
1317 : : struct i40e_rss_filter_data *data = &filter->filter_data;
1318 : 0 : uint32_t reset_flags = data->misc_reset_flags;
1319 : :
1320 : 0 : data->misc_reset_flags &= ~ref_data->misc_reset_flags;
1321 : :
1322 [ # # ]: 0 : if ((reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) &&
1323 [ # # ]: 0 : (ref_data->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) &&
1324 [ # # ]: 0 : (conf->region_queue_start != ref_conf->region_queue_start ||
1325 : : conf->region_queue_num != ref_conf->region_queue_num))
1326 : 0 : data->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_REGION;
1327 : :
1328 : 0 : data->reset_config_pctypes &= ~ref_data->reset_config_pctypes;
1329 : 0 : data->reset_symmetric_pctypes &= ~ref_data->reset_symmetric_pctypes;
1330 : 0 : }
1331 : :
1332 : : int
1333 : 0 : i40e_hash_filter_restore(struct i40e_pf *pf)
1334 : : {
1335 : : struct i40e_rss_filter *filter;
1336 : : int ret;
1337 : :
1338 [ # # ]: 0 : TAILQ_FOREACH(filter, &pf->rss_config_list, next) {
1339 : : struct i40e_rss_filter *prev;
1340 : :
1341 : 0 : filter->filter_data = (struct i40e_rss_filter_data){0};
1342 : :
1343 : 0 : ret = i40e_hash_config(pf, filter);
1344 [ # # ]: 0 : if (ret) {
1345 : 0 : pf->hash_filter_enabled = 0;
1346 : 0 : i40e_pf_disable_rss(pf);
1347 : 0 : PMD_DRV_LOG(ERR,
1348 : : "Re-configure RSS failed, RSS has been disabled");
1349 : : return ret;
1350 : : }
1351 : :
1352 : : /* Invalid previous RSS filter */
1353 [ # # ]: 0 : TAILQ_FOREACH(prev, &pf->rss_config_list, next) {
1354 [ # # ]: 0 : if (prev == filter)
1355 : : break;
1356 : 0 : i40e_invalid_rss_filter(filter, prev);
1357 : : }
1358 : : }
1359 : :
1360 : : return 0;
1361 : : }
1362 : :
1363 : : int
1364 : 0 : i40e_hash_filter_create(struct i40e_pf *pf,
1365 : : struct i40e_rte_flow_rss_conf *rss_conf)
1366 : : {
1367 : : struct i40e_rss_filter *filter, *prev;
1368 : : struct i40e_rte_flow_rss_conf *new_conf;
1369 : : int ret;
1370 : :
1371 : 0 : filter = rte_zmalloc("i40e_rss_filter", sizeof(*filter), 0);
1372 [ # # ]: 0 : if (!filter) {
1373 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory.");
1374 : 0 : return -ENOMEM;
1375 : : }
1376 : :
1377 : 0 : new_conf = &filter->rss_filter_info;
1378 : :
1379 : : memcpy(new_conf, rss_conf, sizeof(*new_conf));
1380 : :
1381 : 0 : ret = i40e_hash_config(pf, filter);
1382 [ # # ]: 0 : if (ret) {
1383 : 0 : rte_free(filter);
1384 [ # # ]: 0 : if (i40e_pf_config_rss(pf))
1385 : : return ret;
1386 : :
1387 : 0 : (void)i40e_hash_filter_restore(pf);
1388 : 0 : return ret;
1389 : : }
1390 : :
1391 : : /* Invalid previous RSS filter */
1392 [ # # ]: 0 : TAILQ_FOREACH(prev, &pf->rss_config_list, next)
1393 : 0 : i40e_invalid_rss_filter(filter, prev);
1394 : :
1395 : 0 : TAILQ_INSERT_TAIL(&pf->rss_config_list, filter, next);
1396 : 0 : return 0;
1397 : : }
1398 : :
1399 : : static int
1400 : 0 : i40e_hash_reset_conf(struct i40e_pf *pf,
1401 : : struct i40e_rss_filter_data *filter_data)
1402 : : {
1403 : 0 : struct i40e_hw *hw = &pf->adapter->hw;
1404 : : struct rte_eth_dev *dev;
1405 : : uint64_t inset;
1406 : : uint32_t idx;
1407 : : int ret;
1408 : :
1409 [ # # ]: 0 : if (filter_data->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_FUNC) {
1410 : 0 : ret = i40e_hash_config_func(hw, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
1411 [ # # ]: 0 : if (ret)
1412 : : return ret;
1413 : :
1414 : 0 : filter_data->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_FUNC;
1415 : : }
1416 : :
1417 [ # # ]: 0 : if (filter_data->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) {
1418 : 0 : dev = &rte_eth_devices[pf->dev_data->port_id];
1419 : 0 : ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
1420 [ # # ]: 0 : if (ret)
1421 : : return ret;
1422 : :
1423 : 0 : filter_data->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_REGION;
1424 : : }
1425 : :
1426 [ # # ]: 0 : if (filter_data->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_KEY) {
1427 : 0 : ret = i40e_pf_reset_rss_key(pf);
1428 [ # # ]: 0 : if (ret)
1429 : : return ret;
1430 : :
1431 : 0 : filter_data->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_KEY;
1432 : : }
1433 : :
1434 [ # # ]: 0 : if (filter_data->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_QUEUE) {
1435 [ # # ]: 0 : if (!pf->adapter->rss_reta_updated) {
1436 : 0 : ret = i40e_pf_reset_rss_reta(pf);
1437 [ # # ]: 0 : if (ret)
1438 : : return ret;
1439 : : }
1440 : :
1441 : 0 : pf->hash_enabled_queues = 0;
1442 : 0 : filter_data->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_QUEUE;
1443 : : }
1444 : :
1445 [ # # ]: 0 : while (filter_data->reset_config_pctypes) {
1446 : : idx = rte_bsf64(filter_data->reset_config_pctypes);
1447 : :
1448 : 0 : i40e_hash_enable_pctype(hw, idx, false);
1449 : 0 : inset = i40e_get_default_input_set(idx);
1450 [ # # ]: 0 : if (inset) {
1451 : 0 : ret = i40e_set_hash_inset(hw, inset, idx, false);
1452 [ # # ]: 0 : if (ret)
1453 : 0 : return ret;
1454 : : }
1455 : :
1456 : 0 : filter_data->reset_config_pctypes &= ~BIT_ULL(idx);
1457 : : }
1458 : :
1459 [ # # ]: 0 : while (filter_data->reset_symmetric_pctypes) {
1460 : : idx = rte_bsf64(filter_data->reset_symmetric_pctypes);
1461 : :
1462 : 0 : ret = i40e_hash_config_pctype_symmetric(hw, idx, false);
1463 [ # # ]: 0 : if (ret)
1464 : 0 : return ret;
1465 : :
1466 : 0 : filter_data->reset_symmetric_pctypes &= ~BIT_ULL(idx);
1467 : : }
1468 : :
1469 : : return 0;
1470 : : }
1471 : :
1472 : : int
1473 : 0 : i40e_hash_filter_destroy(struct i40e_pf *pf,
1474 : : const struct i40e_rss_filter *rss_filter)
1475 : : {
1476 : : struct i40e_rss_filter *filter;
1477 : : int ret;
1478 : :
1479 [ # # ]: 0 : TAILQ_FOREACH(filter, &pf->rss_config_list, next) {
1480 [ # # ]: 0 : if (rss_filter == filter) {
1481 : 0 : ret = i40e_hash_reset_conf(pf, &filter->filter_data);
1482 [ # # ]: 0 : if (ret)
1483 : : return ret;
1484 : :
1485 [ # # ]: 0 : TAILQ_REMOVE(&pf->rss_config_list, filter, next);
1486 : 0 : rte_free(filter);
1487 : 0 : return 0;
1488 : : }
1489 : : }
1490 : :
1491 : : return -ENOENT;
1492 : : }
1493 : :
1494 : : int
1495 : 0 : i40e_hash_filter_flush(struct i40e_pf *pf)
1496 : : {
1497 : : struct rte_flow *flow, *next;
1498 : :
1499 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(flow, &pf->flow_list, node, next) {
1500 [ # # ]: 0 : if (flow->filter_type != RTE_ETH_FILTER_HASH)
1501 : 0 : continue;
1502 : :
1503 [ # # ]: 0 : if (flow->rule) {
1504 : : struct i40e_rss_filter *filter = flow->rule;
1505 : : int ret;
1506 : :
1507 : 0 : ret = i40e_hash_reset_conf(pf,
1508 : : &filter->filter_data);
1509 [ # # ]: 0 : if (ret)
1510 : 0 : return ret;
1511 : :
1512 [ # # ]: 0 : TAILQ_REMOVE(&pf->rss_config_list, filter, next);
1513 : 0 : rte_free(filter);
1514 : : }
1515 : :
1516 [ # # ]: 0 : TAILQ_REMOVE(&pf->flow_list, flow, node);
1517 : 0 : rte_free(flow);
1518 : : }
1519 : :
1520 [ # # ]: 0 : assert(!pf->rss_config_list.tqh_first);
1521 : : return 0;
1522 : : }
|