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