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->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_rte_flow_rss_conf *rss_conf)
831 : : {
832 : : struct rte_flow_action_rss *rss_info = &rss_conf->conf;
833 : 0 : struct i40e_hw *hw = &pf->adapter->hw;
834 : : uint64_t pctypes;
835 : : int ret;
836 : :
837 [ # # ]: 0 : if (rss_info->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
838 : 0 : ret = i40e_hash_config_func(hw, rss_info->func);
839 [ # # ]: 0 : if (ret)
840 : : return ret;
841 : :
842 [ # # ]: 0 : if (rss_info->func != RTE_ETH_HASH_FUNCTION_TOEPLITZ)
843 : 0 : rss_conf->misc_reset_flags |=
844 : : I40E_HASH_FLOW_RESET_FLAG_FUNC;
845 : : }
846 : :
847 [ # # ]: 0 : if (rss_conf->region_queue_num > 0) {
848 : 0 : ret = i40e_hash_config_region(pf, rss_conf);
849 [ # # ]: 0 : if (ret)
850 : : return ret;
851 : :
852 : 0 : rss_conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_REGION;
853 : : }
854 : :
855 [ # # ]: 0 : if (rss_info->key_len > 0) {
856 : 0 : ret = i40e_set_rss_key(pf->main_vsi, rss_conf->key,
857 : : rss_info->key_len);
858 [ # # ]: 0 : if (ret)
859 : : return ret;
860 : :
861 : 0 : rss_conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_KEY;
862 : : }
863 : :
864 : : /* Update lookup table */
865 [ # # ]: 0 : if (rss_info->queue_num > 0) {
866 : : uint8_t lut[RTE_ETH_RSS_RETA_SIZE_512];
867 : : uint32_t i, j = 0;
868 : :
869 [ # # ]: 0 : for (i = 0; i < hw->func_caps.rss_table_size; i++) {
870 : 0 : lut[i] = (uint8_t)rss_info->queue[j];
871 [ # # ]: 0 : j = (j == rss_info->queue_num - 1) ? 0 : (j + 1);
872 : : }
873 : :
874 : 0 : ret = i40e_set_rss_lut(pf->main_vsi, lut, (uint16_t)i);
875 [ # # ]: 0 : if (ret)
876 : 0 : return ret;
877 : :
878 : 0 : pf->hash_enabled_queues = 0;
879 [ # # ]: 0 : for (i = 0; i < rss_info->queue_num; i++)
880 : 0 : pf->hash_enabled_queues |= BIT_ULL(lut[i]);
881 : :
882 : 0 : pf->adapter->rss_reta_updated = 0;
883 : 0 : rss_conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_QUEUE;
884 : : }
885 : :
886 : : /* The codes behind configure the input sets and symmetric hash
887 : : * function of the packet types and enable hash on them.
888 : : */
889 : 0 : pctypes = rss_conf->config_pctypes;
890 [ # # ]: 0 : if (!pctypes)
891 : : return 0;
892 : :
893 : : /* For first flow that will enable hash on any packet type, we clean
894 : : * the RSS sets that by legacy configuration commands and parameters.
895 : : */
896 [ # # ]: 0 : if (!pf->hash_filter_enabled) {
897 : 0 : i40e_pf_disable_rss(pf);
898 : 0 : pf->hash_filter_enabled = true;
899 : : }
900 : :
901 : : do {
902 : : uint32_t idx = rte_bsf64(pctypes);
903 : 0 : uint64_t bit = BIT_ULL(idx);
904 : :
905 [ # # ]: 0 : if (rss_conf->symmetric_enable) {
906 : 0 : ret = i40e_hash_config_pctype_symmetric(hw, idx, true);
907 [ # # ]: 0 : if (ret)
908 : 0 : return ret;
909 : :
910 : 0 : rss_conf->reset_symmetric_pctypes |= bit;
911 : : }
912 : :
913 : 0 : ret = i40e_hash_config_pctype(hw, rss_conf, idx);
914 [ # # ]: 0 : if (ret)
915 : 0 : return ret;
916 : :
917 : 0 : rss_conf->reset_config_pctypes |= bit;
918 : 0 : pctypes &= ~bit;
919 [ # # ]: 0 : } while (pctypes);
920 : :
921 : : return 0;
922 : : }
923 : :
924 : : static void
925 : 0 : i40e_hash_parse_key(const struct rte_flow_action_rss *rss_act,
926 : : struct i40e_rte_flow_rss_conf *rss_conf)
927 : : {
928 : 0 : const uint8_t *key = rss_act->key;
929 : :
930 [ # # ]: 0 : if (key == NULL) {
931 : 0 : memcpy(rss_conf->key, i40e_rss_key_default, sizeof(rss_conf->key));
932 : : } else {
933 : 0 : memcpy(rss_conf->key, key, sizeof(rss_conf->key));
934 : : }
935 : :
936 : 0 : rss_conf->conf.key = rss_conf->key;
937 : 0 : rss_conf->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->conf.func = rss_act->func;
953 : 0 : rss_conf->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->conf.queue = rss_conf->queue;
967 : 0 : rss_conf->conf.queue_num = rss_act->queue_num;
968 : : return 0;
969 : : }
970 : :
971 : : static int
972 : 0 : i40e_hash_parse_queue_region(const struct rte_flow_item pattern[],
973 : : const struct rte_flow_action_rss *rss_act,
974 : : struct i40e_rte_flow_rss_conf *rss_conf,
975 : : struct rte_flow_error *error)
976 : : {
977 : : const struct rte_flow_item_vlan *vlan_spec, *vlan_mask;
978 : :
979 : 0 : vlan_spec = pattern->spec;
980 : 0 : vlan_mask = pattern->mask;
981 : :
982 : : /* VLAN must have spec and mask */
983 [ # # ]: 0 : if (vlan_spec == NULL || vlan_mask == NULL) {
984 : 0 : return rte_flow_error_set(error, EINVAL,
985 : : RTE_FLOW_ERROR_TYPE_ITEM, &pattern[0],
986 : : "VLAN pattern spec and mask required");
987 : : }
988 : : /* for mask, VLAN/TCI must be masked appropriately */
989 [ # # # # ]: 0 : if ((rte_be_to_cpu_16(vlan_mask->hdr.vlan_tci) >> 13) != 0x7) {
990 : 0 : return rte_flow_error_set(error, EINVAL,
991 : : RTE_FLOW_ERROR_TYPE_ITEM, &pattern[0],
992 : : "VLAN pattern mask invalid");
993 : : }
994 : :
995 : : /* Use a 64 bit variable to represent all queues in a region. */
996 : : RTE_BUILD_BUG_ON(I40E_MAX_Q_PER_TC > 64);
997 : :
998 : 0 : rss_conf->region_queue_num = (uint8_t)rss_act->queue_num;
999 : 0 : rss_conf->region_queue_start = rss_act->queue[0];
1000 [ # # ]: 0 : rss_conf->region_priority = rte_be_to_cpu_16(vlan_spec->hdr.vlan_tci) >> 13;
1001 : 0 : return 0;
1002 : : }
1003 : :
1004 : : static bool
1005 : 0 : i40e_hash_validate_rss_types(uint64_t rss_types)
1006 : : {
1007 : : uint64_t type, mask;
1008 : :
1009 : : /* Validate L2 */
1010 : 0 : type = RTE_ETH_RSS_ETH & rss_types;
1011 : 0 : mask = (RTE_ETH_RSS_L2_SRC_ONLY | RTE_ETH_RSS_L2_DST_ONLY) & rss_types;
1012 [ # # ]: 0 : if (!type && mask)
1013 : : return false;
1014 : :
1015 : : /* Validate L3 */
1016 : 0 : type = (I40E_HASH_L4_TYPES | RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4 |
1017 : : RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_IPV6 |
1018 : : RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_NONFRAG_IPV6_OTHER) & rss_types;
1019 : 0 : mask = (RTE_ETH_RSS_L3_SRC_ONLY | RTE_ETH_RSS_L3_DST_ONLY) & rss_types;
1020 [ # # ]: 0 : if (!type && mask)
1021 : : return false;
1022 : :
1023 : : /* Validate L4 */
1024 : 0 : type = (I40E_HASH_L4_TYPES | RTE_ETH_RSS_PORT) & rss_types;
1025 : 0 : mask = (RTE_ETH_RSS_L4_SRC_ONLY | RTE_ETH_RSS_L4_DST_ONLY) & rss_types;
1026 [ # # ]: 0 : if (!type && mask)
1027 : 0 : return false;
1028 : :
1029 : : return true;
1030 : : }
1031 : :
1032 : : static int
1033 : 0 : i40e_hash_validate_rss_pattern(const struct ci_flow_actions *actions,
1034 : : const struct ci_flow_actions_check_param *param __rte_unused,
1035 : : struct rte_flow_error *error)
1036 : : {
1037 : 0 : const struct rte_flow_action_rss *rss_act = actions->actions[0]->conf;
1038 : :
1039 : : /* queue list is not supported */
1040 [ # # ]: 0 : if (rss_act->queue_num != 0) {
1041 : 0 : return rte_flow_error_set(error, EINVAL,
1042 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1043 : : "RSS queues not supported when pattern specified");
1044 : : }
1045 : :
1046 : : /* disallow unsupported hash functions */
1047 [ # # ]: 0 : switch (rss_act->func) {
1048 : : case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
1049 : : case RTE_ETH_HASH_FUNCTION_DEFAULT:
1050 : : case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
1051 : : case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
1052 : : break;
1053 : 0 : default:
1054 : 0 : return rte_flow_error_set(error, EINVAL,
1055 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1056 : : "RSS hash function not supported when pattern specified");
1057 : : }
1058 : :
1059 [ # # ]: 0 : if (!i40e_hash_validate_rss_types(rss_act->types))
1060 : 0 : return rte_flow_error_set(error, EINVAL,
1061 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1062 : : rss_act, "RSS types are invalid");
1063 : :
1064 : : /* check RSS key length if it is specified */
1065 [ # # ]: 0 : if (rss_act->key_len != 0 && rss_act->key_len != I40E_RSS_KEY_LEN) {
1066 : 0 : return rte_flow_error_set(error, EINVAL,
1067 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1068 : : "RSS key length must be 52 bytes");
1069 : : }
1070 : :
1071 : : return 0;
1072 : : }
1073 : :
1074 : : static int
1075 : 0 : i40e_hash_validate_rss_common(const struct rte_flow_action_rss *rss_act,
1076 : : struct rte_flow_error *error)
1077 : : {
1078 : : /* RSS level is not supported */
1079 [ # # ]: 0 : if (rss_act->level != 0) {
1080 : 0 : return rte_flow_error_set(error, ENOTSUP,
1081 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1082 : : "RSS level is not supported");
1083 : : }
1084 : :
1085 : : /* for empty patterns, symmetric toeplitz is not supported */
1086 [ # # ]: 0 : if (rss_act->func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {
1087 : 0 : return rte_flow_error_set(error, EINVAL,
1088 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1089 : : "Symmetric hash function not supported without specific patterns");
1090 : : }
1091 : :
1092 : : /* hash types are not supported for global RSS configuration */
1093 [ # # ]: 0 : if (rss_act->types != 0) {
1094 : 0 : return rte_flow_error_set(error, EINVAL,
1095 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1096 : : "RSS types not supported without a pattern");
1097 : : }
1098 : :
1099 : : /* check RSS key length if it is specified */
1100 [ # # ]: 0 : if (rss_act->key_len != 0 && rss_act->key_len != I40E_RSS_KEY_LEN) {
1101 : 0 : return rte_flow_error_set(error, EINVAL,
1102 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1103 : : "RSS key length must be 52 bytes");
1104 : : }
1105 : :
1106 : : return 0;
1107 : : }
1108 : :
1109 : : static int
1110 : 0 : i40e_hash_validate_queue_region(const struct ci_flow_actions *actions,
1111 : : const struct ci_flow_actions_check_param *param,
1112 : : struct rte_flow_error *error)
1113 : : {
1114 : 0 : const struct rte_flow_action_rss *rss_act = actions->actions[0]->conf;
1115 : 0 : struct i40e_adapter *adapter = I40E_DEV_PRIVATE_TO_ADAPTER(param->driver_ctx);
1116 : : struct i40e_pf *pf = &adapter->pf;
1117 : : uint64_t hash_queues;
1118 : : int ret;
1119 : :
1120 : 0 : ret = i40e_hash_validate_rss_common(rss_act, error);
1121 [ # # ]: 0 : if (ret)
1122 : : return ret;
1123 : :
1124 : : RTE_BUILD_BUG_ON(sizeof(hash_queues) != sizeof(pf->hash_enabled_queues));
1125 : :
1126 : : /* having RSS key is not supported */
1127 [ # # ]: 0 : if (rss_act->key != NULL) {
1128 : 0 : return rte_flow_error_set(error, EINVAL,
1129 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1130 : : "RSS key not supported");
1131 : : }
1132 : :
1133 : : /* queue region must be specified */
1134 [ # # ]: 0 : if (rss_act->queue_num == 0) {
1135 : 0 : return rte_flow_error_set(error, EINVAL,
1136 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1137 : : "RSS queues missing");
1138 : : }
1139 : :
1140 : : /* queue region must be power of two */
1141 : : if (!rte_is_power_of_2(rss_act->queue_num)) {
1142 : 0 : return rte_flow_error_set(error, EINVAL,
1143 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1144 : : "RSS queue number must be power of two");
1145 : : }
1146 : :
1147 : : /* generic checks already filtered out discontiguous/non-unique RSS queues */
1148 : :
1149 : : /* queues must not exceed maximum queues per traffic class */
1150 [ # # ]: 0 : if (rss_act->queue[rss_act->queue_num - 1] >= I40E_MAX_Q_PER_TC) {
1151 : 0 : return rte_flow_error_set(error, EINVAL,
1152 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1153 : : "Invalid RSS queue index");
1154 : : }
1155 : :
1156 : : /* queues must be in LUT */
1157 : 0 : hash_queues = (BIT_ULL(rss_act->queue[0] + rss_act->queue_num) - 1) &
1158 : 0 : ~(BIT_ULL(rss_act->queue[0]) - 1);
1159 : :
1160 [ # # ]: 0 : if (hash_queues & ~pf->hash_enabled_queues) {
1161 : 0 : return rte_flow_error_set(error, EINVAL,
1162 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1163 : : rss_act, "Some queues are not in LUT");
1164 : : }
1165 : :
1166 : : return 0;
1167 : : }
1168 : :
1169 : : static int
1170 : 0 : i40e_hash_validate_queue_list(const struct ci_flow_actions *actions,
1171 : : const struct ci_flow_actions_check_param *param,
1172 : : struct rte_flow_error *error)
1173 : : {
1174 : 0 : const struct rte_flow_action_rss *rss_act = actions->actions[0]->conf;
1175 : 0 : struct i40e_adapter *adapter = I40E_DEV_PRIVATE_TO_ADAPTER(param->driver_ctx);
1176 : : struct i40e_pf *pf;
1177 : : struct i40e_hw *hw;
1178 : : uint16_t max_queue;
1179 : : bool has_queue, has_key;
1180 : : int ret;
1181 : :
1182 : 0 : ret = i40e_hash_validate_rss_common(rss_act, error);
1183 [ # # ]: 0 : if (ret)
1184 : : return ret;
1185 : :
1186 : 0 : has_queue = rss_act->queue != NULL;
1187 : 0 : has_key = rss_act->key != NULL;
1188 : :
1189 : : /* if we have queues, we must not have key */
1190 [ # # ]: 0 : if (has_queue && has_key) {
1191 : 0 : return rte_flow_error_set(error, EINVAL,
1192 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1193 : : "RSS key for queue region is not supported");
1194 : : }
1195 : :
1196 : : /* if there are no queues, no further checks needed */
1197 [ # # ]: 0 : if (!has_queue)
1198 : : return 0;
1199 : :
1200 : : /* check queue number limits */
1201 : : hw = &adapter->hw;
1202 [ # # ]: 0 : if (rss_act->queue_num > hw->func_caps.rss_table_size) {
1203 : 0 : return rte_flow_error_set(error, EINVAL,
1204 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1205 : : rss_act, "Too many RSS queues");
1206 : : }
1207 : :
1208 : 0 : pf = &adapter->pf;
1209 [ # # ]: 0 : if (pf->dev_data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_VMDQ_FLAG)
1210 : 0 : max_queue = i40e_pf_calc_configured_queues_num(pf);
1211 : : else
1212 : 0 : max_queue = pf->dev_data->nb_rx_queues;
1213 : :
1214 : 0 : max_queue = RTE_MIN(max_queue, I40E_MAX_Q_PER_TC);
1215 : :
1216 : : /* we know RSS queues are contiguous so we only need to check last queue */
1217 [ # # ]: 0 : if (rss_act->queue[rss_act->queue_num - 1] >= max_queue) {
1218 : 0 : return rte_flow_error_set(error, EINVAL,
1219 : : RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
1220 : : "Invalid RSS queue");
1221 : : }
1222 : :
1223 : : return 0;
1224 : : }
1225 : :
1226 : : int
1227 : 0 : i40e_hash_parse(struct rte_eth_dev *dev,
1228 : : const struct rte_flow_item pattern[],
1229 : : const struct rte_flow_action actions[],
1230 : : struct i40e_rte_flow_rss_conf *rss_conf,
1231 : : struct rte_flow_error *error)
1232 : : {
1233 : : struct ci_flow_actions parsed_actions;
1234 : 0 : struct ci_flow_actions_check_param ac_param = {
1235 : 0 : .allowed_types = (enum rte_flow_action_type[]) {
1236 : : RTE_FLOW_ACTION_TYPE_RSS,
1237 : : RTE_FLOW_ACTION_TYPE_END
1238 : : },
1239 : : .max_actions = 1,
1240 : 0 : .driver_ctx = dev->data->dev_private,
1241 : : .rss_queues_contig = true,
1242 : : /* each pattern type will add specific check function */
1243 : : };
1244 : : const struct rte_flow_action_rss *rss_act;
1245 : : int ret;
1246 : :
1247 : : /*
1248 : : * We have two possible paths: global RSS configuration, and an RSS pattern action.
1249 : : *
1250 : : * For global patterns, we act on two types of flows:
1251 : : * - Empty pattern ([END])
1252 : : * - VLAN pattern ([VLAN] -> [END])
1253 : : *
1254 : : * Everything else is handled by pattern action parser.
1255 : : */
1256 : : bool is_empty, is_vlan;
1257 : :
1258 [ # # ]: 0 : while (pattern->type == RTE_FLOW_ITEM_TYPE_VOID)
1259 : 0 : pattern++;
1260 : :
1261 : : is_empty = pattern[0].type == RTE_FLOW_ITEM_TYPE_END;
1262 [ # # ]: 0 : is_vlan = pattern[0].type == RTE_FLOW_ITEM_TYPE_VLAN &&
1263 [ # # ]: 0 : pattern[1].type == RTE_FLOW_ITEM_TYPE_END;
1264 : :
1265 : : /* VLAN path */
1266 [ # # ]: 0 : if (is_vlan) {
1267 : 0 : ac_param.check = i40e_hash_validate_queue_region;
1268 : 0 : ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
1269 [ # # ]: 0 : if (ret)
1270 : : return ret;
1271 : 0 : rss_act = parsed_actions.actions[0]->conf;
1272 : : /* set up RSS functions */
1273 : 0 : rss_conf->conf.func = rss_act->func;
1274 : 0 : return i40e_hash_parse_queue_region(pattern, rss_act, rss_conf, error);
1275 : : }
1276 : : /* Empty pattern path */
1277 [ # # ]: 0 : if (is_empty) {
1278 : 0 : ac_param.check = i40e_hash_validate_queue_list;
1279 : 0 : ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
1280 [ # # ]: 0 : if (ret)
1281 : : return ret;
1282 : 0 : rss_act = parsed_actions.actions[0]->conf;
1283 : 0 : rss_conf->conf.func = rss_act->func;
1284 : : /* if there is a queue list, take that path */
1285 [ # # ]: 0 : if (rss_act->queue != NULL)
1286 : 0 : return i40e_hash_parse_queues(rss_act, rss_conf);
1287 : :
1288 : : /* otherwise just parse RSS key */
1289 [ # # ]: 0 : if (rss_act->key != NULL)
1290 : 0 : i40e_hash_parse_key(rss_act, rss_conf);
1291 : :
1292 : 0 : return 0;
1293 : : }
1294 : 0 : ac_param.check = i40e_hash_validate_rss_pattern;
1295 : 0 : ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
1296 [ # # ]: 0 : if (ret)
1297 : : return ret;
1298 : 0 : rss_act = parsed_actions.actions[0]->conf;
1299 : :
1300 : : /* pattern case */
1301 : 0 : return i40e_hash_parse_pattern_act(dev, pattern, rss_act, rss_conf, error);
1302 : : }
1303 : :
1304 : : static void
1305 : 0 : i40e_invalid_rss_filter(const struct i40e_rte_flow_rss_conf *ref_conf,
1306 : : struct i40e_rte_flow_rss_conf *conf)
1307 : : {
1308 : 0 : uint32_t reset_flags = conf->misc_reset_flags;
1309 : :
1310 : 0 : conf->misc_reset_flags &= ~ref_conf->misc_reset_flags;
1311 : :
1312 [ # # ]: 0 : if ((reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) &&
1313 [ # # ]: 0 : (ref_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) &&
1314 [ # # ]: 0 : (conf->region_queue_start != ref_conf->region_queue_start ||
1315 : : conf->region_queue_num != ref_conf->region_queue_num))
1316 : 0 : conf->misc_reset_flags |= I40E_HASH_FLOW_RESET_FLAG_REGION;
1317 : :
1318 : 0 : conf->reset_config_pctypes &= ~ref_conf->reset_config_pctypes;
1319 : 0 : conf->reset_symmetric_pctypes &= ~ref_conf->reset_symmetric_pctypes;
1320 : 0 : }
1321 : :
1322 : : int
1323 : 0 : i40e_hash_filter_restore(struct i40e_pf *pf)
1324 : : {
1325 : : struct i40e_rss_filter *filter;
1326 : : int ret;
1327 : :
1328 [ # # ]: 0 : TAILQ_FOREACH(filter, &pf->rss_config_list, next) {
1329 : 0 : struct i40e_rte_flow_rss_conf *rss_conf =
1330 : : &filter->rss_filter_info;
1331 : : struct i40e_rss_filter *prev;
1332 : :
1333 : 0 : rss_conf->misc_reset_flags = 0;
1334 : 0 : rss_conf->reset_config_pctypes = 0;
1335 : 0 : rss_conf->reset_symmetric_pctypes = 0;
1336 : :
1337 : 0 : ret = i40e_hash_config(pf, rss_conf);
1338 [ # # ]: 0 : if (ret) {
1339 : 0 : pf->hash_filter_enabled = 0;
1340 : 0 : i40e_pf_disable_rss(pf);
1341 : 0 : PMD_DRV_LOG(ERR,
1342 : : "Re-configure RSS failed, RSS has been disabled");
1343 : 0 : return ret;
1344 : : }
1345 : :
1346 : : /* Invalid previous RSS filter */
1347 [ # # ]: 0 : TAILQ_FOREACH(prev, &pf->rss_config_list, next) {
1348 [ # # ]: 0 : if (prev == filter)
1349 : : break;
1350 : 0 : i40e_invalid_rss_filter(rss_conf,
1351 : : &prev->rss_filter_info);
1352 : : }
1353 : : }
1354 : :
1355 : : return 0;
1356 : : }
1357 : :
1358 : : int
1359 : 0 : i40e_hash_filter_create(struct i40e_pf *pf,
1360 : : struct i40e_rte_flow_rss_conf *rss_conf)
1361 : : {
1362 : : struct i40e_rss_filter *filter, *prev;
1363 : : struct i40e_rte_flow_rss_conf *new_conf;
1364 : : int ret;
1365 : :
1366 : 0 : filter = rte_zmalloc("i40e_rss_filter", sizeof(*filter), 0);
1367 [ # # ]: 0 : if (!filter) {
1368 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory.");
1369 : 0 : return -ENOMEM;
1370 : : }
1371 : :
1372 [ # # ]: 0 : new_conf = &filter->rss_filter_info;
1373 : :
1374 : : memcpy(new_conf, rss_conf, sizeof(*new_conf));
1375 [ # # ]: 0 : if (new_conf->conf.queue_num)
1376 : 0 : new_conf->conf.queue = new_conf->queue;
1377 [ # # ]: 0 : if (new_conf->conf.key_len)
1378 : 0 : new_conf->conf.key = new_conf->key;
1379 : :
1380 : 0 : ret = i40e_hash_config(pf, new_conf);
1381 [ # # ]: 0 : if (ret) {
1382 : 0 : rte_free(filter);
1383 [ # # ]: 0 : if (i40e_pf_config_rss(pf))
1384 : : return ret;
1385 : :
1386 : 0 : (void)i40e_hash_filter_restore(pf);
1387 : 0 : return ret;
1388 : : }
1389 : :
1390 : : /* Invalid previous RSS filter */
1391 [ # # ]: 0 : TAILQ_FOREACH(prev, &pf->rss_config_list, next)
1392 : 0 : i40e_invalid_rss_filter(new_conf, &prev->rss_filter_info);
1393 : :
1394 : 0 : TAILQ_INSERT_TAIL(&pf->rss_config_list, filter, next);
1395 : 0 : return 0;
1396 : : }
1397 : :
1398 : : static int
1399 : 0 : i40e_hash_reset_conf(struct i40e_pf *pf,
1400 : : struct i40e_rte_flow_rss_conf *rss_conf)
1401 : : {
1402 : 0 : struct i40e_hw *hw = &pf->adapter->hw;
1403 : : struct rte_eth_dev *dev;
1404 : : uint64_t inset;
1405 : : uint32_t idx;
1406 : : int ret;
1407 : :
1408 [ # # ]: 0 : if (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_FUNC) {
1409 : 0 : ret = i40e_hash_config_func(hw, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
1410 [ # # ]: 0 : if (ret)
1411 : : return ret;
1412 : :
1413 : 0 : rss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_FUNC;
1414 : : }
1415 : :
1416 [ # # ]: 0 : if (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_REGION) {
1417 : 0 : dev = &rte_eth_devices[pf->dev_data->port_id];
1418 : 0 : ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
1419 [ # # ]: 0 : if (ret)
1420 : : return ret;
1421 : :
1422 : 0 : rss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_REGION;
1423 : : }
1424 : :
1425 [ # # ]: 0 : if (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_KEY) {
1426 : 0 : ret = i40e_pf_reset_rss_key(pf);
1427 [ # # ]: 0 : if (ret)
1428 : : return ret;
1429 : :
1430 : 0 : rss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_KEY;
1431 : : }
1432 : :
1433 [ # # ]: 0 : if (rss_conf->misc_reset_flags & I40E_HASH_FLOW_RESET_FLAG_QUEUE) {
1434 [ # # ]: 0 : if (!pf->adapter->rss_reta_updated) {
1435 : 0 : ret = i40e_pf_reset_rss_reta(pf);
1436 [ # # ]: 0 : if (ret)
1437 : : return ret;
1438 : : }
1439 : :
1440 : 0 : pf->hash_enabled_queues = 0;
1441 : 0 : rss_conf->misc_reset_flags &= ~I40E_HASH_FLOW_RESET_FLAG_QUEUE;
1442 : : }
1443 : :
1444 [ # # ]: 0 : while (rss_conf->reset_config_pctypes) {
1445 : : idx = rte_bsf64(rss_conf->reset_config_pctypes);
1446 : :
1447 : 0 : i40e_hash_enable_pctype(hw, idx, false);
1448 : 0 : inset = i40e_get_default_input_set(idx);
1449 [ # # ]: 0 : if (inset) {
1450 : 0 : ret = i40e_set_hash_inset(hw, inset, idx, false);
1451 [ # # ]: 0 : if (ret)
1452 : 0 : return ret;
1453 : : }
1454 : :
1455 : 0 : rss_conf->reset_config_pctypes &= ~BIT_ULL(idx);
1456 : : }
1457 : :
1458 [ # # ]: 0 : while (rss_conf->reset_symmetric_pctypes) {
1459 : : idx = rte_bsf64(rss_conf->reset_symmetric_pctypes);
1460 : :
1461 : 0 : ret = i40e_hash_config_pctype_symmetric(hw, idx, false);
1462 [ # # ]: 0 : if (ret)
1463 : 0 : return ret;
1464 : :
1465 : 0 : rss_conf->reset_symmetric_pctypes &= ~BIT_ULL(idx);
1466 : : }
1467 : :
1468 : : return 0;
1469 : : }
1470 : :
1471 : : int
1472 : 0 : i40e_hash_filter_destroy(struct i40e_pf *pf,
1473 : : const struct i40e_rss_filter *rss_filter)
1474 : : {
1475 : : struct i40e_rss_filter *filter;
1476 : : int ret;
1477 : :
1478 [ # # ]: 0 : TAILQ_FOREACH(filter, &pf->rss_config_list, next) {
1479 [ # # ]: 0 : if (rss_filter == filter) {
1480 : 0 : ret = i40e_hash_reset_conf(pf,
1481 : : &filter->rss_filter_info);
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->rss_filter_info);
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 : : }
|