ethdev: use extension header for GTP PSC item
[dpdk.git] / drivers / net / iavf / iavf_hash.c
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 <unistd.h>
11 #include <stdarg.h>
12
13 #include <rte_debug.h>
14 #include <rte_ether.h>
15 #include <ethdev_driver.h>
16 #include <rte_log.h>
17 #include <rte_malloc.h>
18 #include <rte_eth_ctrl.h>
19 #include <rte_tailq.h>
20 #include <rte_flow_driver.h>
21
22 #include "iavf_log.h"
23 #include "iavf.h"
24 #include "iavf_generic_flow.h"
25
26 #define IAVF_PHINT_NONE                         0
27 #define IAVF_PHINT_GTPU                         BIT_ULL(0)
28 #define IAVF_PHINT_GTPU_EH                      BIT_ULL(1)
29 #define IAVF_PHINT_GTPU_EH_DWN                  BIT_ULL(2)
30 #define IAVF_PHINT_GTPU_EH_UP                   BIT_ULL(3)
31 #define IAVF_PHINT_OUTER_IPV4                   BIT_ULL(4)
32 #define IAVF_PHINT_OUTER_IPV6                   BIT_ULL(5)
33 #define IAVF_PHINT_GRE                          BIT_ULL(6)
34 /* the second IP header of GTPoGRE */
35 #define IAVF_PHINT_MID_IPV4                     BIT_ULL(7)
36 #define IAVF_PHINT_MID_IPV6                     BIT_ULL(8)
37
38 #define IAVF_PHINT_GTPU_MSK     (IAVF_PHINT_GTPU        | \
39                                  IAVF_PHINT_GTPU_EH     | \
40                                  IAVF_PHINT_GTPU_EH_DWN | \
41                                  IAVF_PHINT_GTPU_EH_UP)
42
43 #define IAVF_PHINT_LAYERS_MSK   (IAVF_PHINT_OUTER_IPV4  | \
44                                  IAVF_PHINT_OUTER_IPV6)
45
46 #define IAVF_GTPU_EH_DWNLINK    0
47 #define IAVF_GTPU_EH_UPLINK     1
48
49 struct iavf_hash_match_type {
50         uint64_t hash_type;
51         struct virtchnl_proto_hdrs *proto_hdrs;
52         uint64_t pattern_hint;
53 };
54
55 struct iavf_rss_meta {
56         struct virtchnl_proto_hdrs proto_hdrs;
57         enum virtchnl_rss_algorithm rss_algorithm;
58 };
59
60 struct iavf_hash_flow_cfg {
61         struct virtchnl_rss_cfg *rss_cfg;
62         bool simple_xor;
63 };
64
65 static int
66 iavf_hash_init(struct iavf_adapter *ad);
67 static int
68 iavf_hash_create(struct iavf_adapter *ad, struct rte_flow *flow, void *meta,
69                  struct rte_flow_error *error);
70 static int
71 iavf_hash_destroy(struct iavf_adapter *ad, struct rte_flow *flow,
72                   struct rte_flow_error *error);
73 static void
74 iavf_hash_uninit(struct iavf_adapter *ad);
75 static void
76 iavf_hash_free(struct rte_flow *flow);
77 static int
78 iavf_hash_parse_pattern_action(struct iavf_adapter *ad,
79                                struct iavf_pattern_match_item *array,
80                                uint32_t array_len,
81                                const struct rte_flow_item pattern[],
82                                const struct rte_flow_action actions[],
83                                void **meta,
84                                struct rte_flow_error *error);
85
86 #define FIELD_SELECTOR(proto_hdr_field) \
87                 (1UL << ((proto_hdr_field) & PROTO_HDR_FIELD_MASK))
88 #define BUFF_NOUSED                     0
89
90 #define proto_hdr_eth { \
91         VIRTCHNL_PROTO_HDR_ETH, \
92         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_SRC) | \
93         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ETH_DST), {BUFF_NOUSED} }
94
95 #define proto_hdr_svlan { \
96         VIRTCHNL_PROTO_HDR_S_VLAN, \
97         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_S_VLAN_ID), {BUFF_NOUSED} }
98
99 #define proto_hdr_cvlan { \
100         VIRTCHNL_PROTO_HDR_C_VLAN, \
101         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_C_VLAN_ID), {BUFF_NOUSED} }
102
103 #define proto_hdr_ipv4 { \
104         VIRTCHNL_PROTO_HDR_IPV4, \
105         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) | \
106         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST), {BUFF_NOUSED} }
107
108 #define proto_hdr_ipv4_with_prot { \
109         VIRTCHNL_PROTO_HDR_IPV4, \
110         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_SRC) | \
111         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_DST) | \
112         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV4_PROT), {BUFF_NOUSED} }
113
114 #define proto_hdr_ipv6 { \
115         VIRTCHNL_PROTO_HDR_IPV6, \
116         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) | \
117         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST), {BUFF_NOUSED} }
118
119 #define proto_hdr_ipv6_frag { \
120         VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG, \
121         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG_PKID), {BUFF_NOUSED} }
122
123 #define proto_hdr_ipv6_with_prot { \
124         VIRTCHNL_PROTO_HDR_IPV6, \
125         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_SRC) | \
126         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_DST) | \
127         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_IPV6_PROT), {BUFF_NOUSED} }
128
129 #define proto_hdr_udp { \
130         VIRTCHNL_PROTO_HDR_UDP, \
131         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_SRC_PORT) | \
132         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_UDP_DST_PORT), {BUFF_NOUSED} }
133
134 #define proto_hdr_tcp { \
135         VIRTCHNL_PROTO_HDR_TCP, \
136         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_SRC_PORT) | \
137         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_TCP_DST_PORT), {BUFF_NOUSED} }
138
139 #define proto_hdr_sctp { \
140         VIRTCHNL_PROTO_HDR_SCTP, \
141         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_SRC_PORT) | \
142         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_SCTP_DST_PORT), {BUFF_NOUSED} }
143
144 #define proto_hdr_esp { \
145         VIRTCHNL_PROTO_HDR_ESP, \
146         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ESP_SPI), {BUFF_NOUSED} }
147
148 #define proto_hdr_ah { \
149         VIRTCHNL_PROTO_HDR_AH, \
150         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_AH_SPI), {BUFF_NOUSED} }
151
152 #define proto_hdr_l2tpv3 { \
153         VIRTCHNL_PROTO_HDR_L2TPV3, \
154         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_L2TPV3_SESS_ID), {BUFF_NOUSED} }
155
156 #define proto_hdr_pfcp { \
157         VIRTCHNL_PROTO_HDR_PFCP, \
158         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_PFCP_SEID), {BUFF_NOUSED} }
159
160 #define proto_hdr_gtpc { \
161         VIRTCHNL_PROTO_HDR_GTPC, 0, {BUFF_NOUSED} }
162
163 #define proto_hdr_ecpri { \
164         VIRTCHNL_PROTO_HDR_ECPRI, \
165         FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ECPRI_PC_RTC_ID), {BUFF_NOUSED} }
166
167 #define TUNNEL_LEVEL_OUTER              0
168 #define TUNNEL_LEVEL_INNER              1
169
170 /* proto_hdrs template */
171 struct virtchnl_proto_hdrs outer_ipv4_tmplt = {
172         TUNNEL_LEVEL_OUTER, 4,
173         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan, proto_hdr_ipv4}
174 };
175
176 struct virtchnl_proto_hdrs outer_ipv4_udp_tmplt = {
177         TUNNEL_LEVEL_OUTER, 5,
178         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan,
179          proto_hdr_ipv4_with_prot,
180          proto_hdr_udp}
181 };
182
183 struct virtchnl_proto_hdrs outer_ipv4_tcp_tmplt = {
184         TUNNEL_LEVEL_OUTER, 5,
185         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan,
186          proto_hdr_ipv4_with_prot,
187          proto_hdr_tcp}
188 };
189
190 struct virtchnl_proto_hdrs outer_ipv4_sctp_tmplt = {
191         TUNNEL_LEVEL_OUTER, 5,
192         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan, proto_hdr_ipv4,
193          proto_hdr_sctp}
194 };
195
196 struct virtchnl_proto_hdrs outer_ipv6_tmplt = {
197         TUNNEL_LEVEL_OUTER, 4,
198         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan, proto_hdr_ipv6}
199 };
200
201 struct virtchnl_proto_hdrs outer_ipv6_frag_tmplt = {
202         TUNNEL_LEVEL_OUTER, 5,
203         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan,
204          proto_hdr_ipv6, proto_hdr_ipv6_frag}
205 };
206
207 struct virtchnl_proto_hdrs outer_ipv6_udp_tmplt = {
208         TUNNEL_LEVEL_OUTER, 5,
209         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan,
210          proto_hdr_ipv6_with_prot,
211          proto_hdr_udp}
212 };
213
214 struct virtchnl_proto_hdrs outer_ipv6_tcp_tmplt = {
215         TUNNEL_LEVEL_OUTER, 5,
216         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan,
217          proto_hdr_ipv6_with_prot,
218          proto_hdr_tcp}
219 };
220
221 struct virtchnl_proto_hdrs outer_ipv6_sctp_tmplt = {
222         TUNNEL_LEVEL_OUTER, 5,
223         {proto_hdr_eth, proto_hdr_svlan, proto_hdr_cvlan, proto_hdr_ipv6,
224          proto_hdr_sctp}
225 };
226
227 struct virtchnl_proto_hdrs inner_ipv4_tmplt = {
228         TUNNEL_LEVEL_INNER, 1, {proto_hdr_ipv4}
229 };
230
231 struct virtchnl_proto_hdrs inner_ipv4_udp_tmplt = {
232         TUNNEL_LEVEL_INNER, 2, {proto_hdr_ipv4_with_prot, proto_hdr_udp}
233 };
234
235 struct virtchnl_proto_hdrs inner_ipv4_tcp_tmplt = {
236         TUNNEL_LEVEL_INNER, 2, {proto_hdr_ipv4_with_prot, proto_hdr_tcp}
237 };
238
239 struct virtchnl_proto_hdrs second_inner_ipv4_tmplt = {
240         2, 1, {proto_hdr_ipv4}
241 };
242
243 struct virtchnl_proto_hdrs second_inner_ipv4_udp_tmplt = {
244         2, 2, {proto_hdr_ipv4_with_prot, proto_hdr_udp}
245 };
246
247 struct virtchnl_proto_hdrs second_inner_ipv4_tcp_tmplt = {
248         2, 2, {proto_hdr_ipv4_with_prot, proto_hdr_tcp}
249 };
250
251 struct virtchnl_proto_hdrs second_inner_ipv6_tmplt = {
252         2, 1, {proto_hdr_ipv6}
253 };
254
255 struct virtchnl_proto_hdrs second_inner_ipv6_udp_tmplt = {
256         2, 2, {proto_hdr_ipv6_with_prot, proto_hdr_udp}
257 };
258
259 struct virtchnl_proto_hdrs second_inner_ipv6_tcp_tmplt = {
260         2, 2, {proto_hdr_ipv6_with_prot, proto_hdr_tcp}
261 };
262
263 struct virtchnl_proto_hdrs inner_ipv4_sctp_tmplt = {
264         TUNNEL_LEVEL_INNER, 2, {proto_hdr_ipv4, proto_hdr_sctp}
265 };
266
267 struct virtchnl_proto_hdrs inner_ipv6_tmplt = {
268         TUNNEL_LEVEL_INNER, 1, {proto_hdr_ipv6}
269 };
270
271 struct virtchnl_proto_hdrs inner_ipv6_udp_tmplt = {
272         TUNNEL_LEVEL_INNER, 2, {proto_hdr_ipv6_with_prot, proto_hdr_udp}
273 };
274
275 struct virtchnl_proto_hdrs inner_ipv6_tcp_tmplt = {
276         TUNNEL_LEVEL_INNER, 2, {proto_hdr_ipv6_with_prot, proto_hdr_tcp}
277 };
278
279 struct virtchnl_proto_hdrs inner_ipv6_sctp_tmplt = {
280         TUNNEL_LEVEL_INNER, 2, {proto_hdr_ipv6, proto_hdr_sctp}
281 };
282
283 struct virtchnl_proto_hdrs ipv4_esp_tmplt = {
284         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv4, proto_hdr_esp}
285 };
286
287 struct virtchnl_proto_hdrs ipv4_udp_esp_tmplt = {
288         TUNNEL_LEVEL_OUTER, 3,
289         {proto_hdr_ipv4, proto_hdr_udp, proto_hdr_esp}
290 };
291
292 struct virtchnl_proto_hdrs ipv4_ah_tmplt = {
293         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv4, proto_hdr_ah}
294 };
295
296 struct virtchnl_proto_hdrs ipv6_esp_tmplt = {
297         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv6, proto_hdr_esp}
298 };
299
300 struct virtchnl_proto_hdrs ipv6_udp_esp_tmplt = {
301         TUNNEL_LEVEL_OUTER, 3,
302         {proto_hdr_ipv6, proto_hdr_udp, proto_hdr_esp}
303 };
304
305 struct virtchnl_proto_hdrs ipv6_ah_tmplt = {
306         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv6, proto_hdr_ah}
307 };
308
309 struct virtchnl_proto_hdrs ipv4_l2tpv3_tmplt = {
310         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv4, proto_hdr_l2tpv3}
311 };
312
313 struct virtchnl_proto_hdrs ipv6_l2tpv3_tmplt = {
314         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv6, proto_hdr_l2tpv3}
315 };
316
317 struct virtchnl_proto_hdrs ipv4_pfcp_tmplt = {
318         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv4, proto_hdr_pfcp}
319 };
320
321 struct virtchnl_proto_hdrs ipv6_pfcp_tmplt = {
322         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_ipv6, proto_hdr_pfcp}
323 };
324
325 struct virtchnl_proto_hdrs ipv4_udp_gtpc_tmplt = {
326         TUNNEL_LEVEL_OUTER, 3, {proto_hdr_ipv4, proto_hdr_udp, proto_hdr_gtpc}
327 };
328
329 struct virtchnl_proto_hdrs ipv6_udp_gtpc_tmplt = {
330         TUNNEL_LEVEL_OUTER, 3, {proto_hdr_ipv6, proto_hdr_udp, proto_hdr_gtpc}
331 };
332
333 struct virtchnl_proto_hdrs eth_ecpri_tmplt = {
334         TUNNEL_LEVEL_OUTER, 2, {proto_hdr_eth, proto_hdr_ecpri}
335 };
336
337 struct virtchnl_proto_hdrs ipv4_ecpri_tmplt = {
338         TUNNEL_LEVEL_OUTER, 3, {proto_hdr_ipv4, proto_hdr_udp, proto_hdr_ecpri}
339 };
340
341 /* rss type super set */
342
343 /* IPv4 outer */
344 #define IAVF_RSS_TYPE_OUTER_IPV4        (ETH_RSS_ETH | ETH_RSS_IPV4 | \
345                                          ETH_RSS_FRAG_IPV4)
346 #define IAVF_RSS_TYPE_OUTER_IPV4_UDP    (IAVF_RSS_TYPE_OUTER_IPV4 | \
347                                          ETH_RSS_NONFRAG_IPV4_UDP)
348 #define IAVF_RSS_TYPE_OUTER_IPV4_TCP    (IAVF_RSS_TYPE_OUTER_IPV4 | \
349                                          ETH_RSS_NONFRAG_IPV4_TCP)
350 #define IAVF_RSS_TYPE_OUTER_IPV4_SCTP   (IAVF_RSS_TYPE_OUTER_IPV4 | \
351                                          ETH_RSS_NONFRAG_IPV4_SCTP)
352 /* IPv6 outer */
353 #define IAVF_RSS_TYPE_OUTER_IPV6        (ETH_RSS_ETH | ETH_RSS_IPV6)
354 #define IAVF_RSS_TYPE_OUTER_IPV6_FRAG   (IAVF_RSS_TYPE_OUTER_IPV6 | \
355                                          ETH_RSS_FRAG_IPV6)
356 #define IAVF_RSS_TYPE_OUTER_IPV6_UDP    (IAVF_RSS_TYPE_OUTER_IPV6 | \
357                                          ETH_RSS_NONFRAG_IPV6_UDP)
358 #define IAVF_RSS_TYPE_OUTER_IPV6_TCP    (IAVF_RSS_TYPE_OUTER_IPV6 | \
359                                          ETH_RSS_NONFRAG_IPV6_TCP)
360 #define IAVF_RSS_TYPE_OUTER_IPV6_SCTP   (IAVF_RSS_TYPE_OUTER_IPV6 | \
361                                          ETH_RSS_NONFRAG_IPV6_SCTP)
362 /* VLAN IPV4 */
363 #define IAVF_RSS_TYPE_VLAN_IPV4         (IAVF_RSS_TYPE_OUTER_IPV4 | \
364                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
365 #define IAVF_RSS_TYPE_VLAN_IPV4_UDP     (IAVF_RSS_TYPE_OUTER_IPV4_UDP | \
366                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
367 #define IAVF_RSS_TYPE_VLAN_IPV4_TCP     (IAVF_RSS_TYPE_OUTER_IPV4_TCP | \
368                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
369 #define IAVF_RSS_TYPE_VLAN_IPV4_SCTP    (IAVF_RSS_TYPE_OUTER_IPV4_SCTP | \
370                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
371 /* VLAN IPv6 */
372 #define IAVF_RSS_TYPE_VLAN_IPV6         (IAVF_RSS_TYPE_OUTER_IPV6 | \
373                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
374 #define IAVF_RSS_TYPE_VLAN_IPV6_FRAG    (IAVF_RSS_TYPE_OUTER_IPV6_FRAG | \
375                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
376 #define IAVF_RSS_TYPE_VLAN_IPV6_UDP     (IAVF_RSS_TYPE_OUTER_IPV6_UDP | \
377                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
378 #define IAVF_RSS_TYPE_VLAN_IPV6_TCP     (IAVF_RSS_TYPE_OUTER_IPV6_TCP | \
379                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
380 #define IAVF_RSS_TYPE_VLAN_IPV6_SCTP    (IAVF_RSS_TYPE_OUTER_IPV6_SCTP | \
381                                          ETH_RSS_S_VLAN | ETH_RSS_C_VLAN)
382 /* IPv4 inner */
383 #define IAVF_RSS_TYPE_INNER_IPV4        ETH_RSS_IPV4
384 #define IAVF_RSS_TYPE_INNER_IPV4_UDP    (ETH_RSS_IPV4 | \
385                                          ETH_RSS_NONFRAG_IPV4_UDP)
386 #define IAVF_RSS_TYPE_INNER_IPV4_TCP    (ETH_RSS_IPV4 | \
387                                          ETH_RSS_NONFRAG_IPV4_TCP)
388 #define IAVF_RSS_TYPE_INNER_IPV4_SCTP   (ETH_RSS_IPV4 | \
389                                          ETH_RSS_NONFRAG_IPV4_SCTP)
390 /* IPv6 inner */
391 #define IAVF_RSS_TYPE_INNER_IPV6        ETH_RSS_IPV6
392 #define IAVF_RSS_TYPE_INNER_IPV6_UDP    (ETH_RSS_IPV6 | \
393                                          ETH_RSS_NONFRAG_IPV6_UDP)
394 #define IAVF_RSS_TYPE_INNER_IPV6_TCP    (ETH_RSS_IPV6 | \
395                                          ETH_RSS_NONFRAG_IPV6_TCP)
396 #define IAVF_RSS_TYPE_INNER_IPV6_SCTP   (ETH_RSS_IPV6 | \
397                                          ETH_RSS_NONFRAG_IPV6_SCTP)
398 /* GTPU IPv4 */
399 #define IAVF_RSS_TYPE_GTPU_IPV4         (IAVF_RSS_TYPE_INNER_IPV4 | \
400                                          ETH_RSS_GTPU)
401 #define IAVF_RSS_TYPE_GTPU_IPV4_UDP     (IAVF_RSS_TYPE_INNER_IPV4_UDP | \
402                                          ETH_RSS_GTPU)
403 #define IAVF_RSS_TYPE_GTPU_IPV4_TCP     (IAVF_RSS_TYPE_INNER_IPV4_TCP | \
404                                          ETH_RSS_GTPU)
405 /* GTPU IPv6 */
406 #define IAVF_RSS_TYPE_GTPU_IPV6         (IAVF_RSS_TYPE_INNER_IPV6 | \
407                                          ETH_RSS_GTPU)
408 #define IAVF_RSS_TYPE_GTPU_IPV6_UDP     (IAVF_RSS_TYPE_INNER_IPV6_UDP | \
409                                          ETH_RSS_GTPU)
410 #define IAVF_RSS_TYPE_GTPU_IPV6_TCP     (IAVF_RSS_TYPE_INNER_IPV6_TCP | \
411                                          ETH_RSS_GTPU)
412 /* ESP, AH, L2TPV3 and PFCP */
413 #define IAVF_RSS_TYPE_IPV4_ESP          (ETH_RSS_ESP | ETH_RSS_IPV4)
414 #define IAVF_RSS_TYPE_IPV4_AH           (ETH_RSS_AH | ETH_RSS_IPV4)
415 #define IAVF_RSS_TYPE_IPV6_ESP          (ETH_RSS_ESP | ETH_RSS_IPV6)
416 #define IAVF_RSS_TYPE_IPV6_AH           (ETH_RSS_AH | ETH_RSS_IPV6)
417 #define IAVF_RSS_TYPE_IPV4_L2TPV3       (ETH_RSS_L2TPV3 | ETH_RSS_IPV4)
418 #define IAVF_RSS_TYPE_IPV6_L2TPV3       (ETH_RSS_L2TPV3 | ETH_RSS_IPV6)
419 #define IAVF_RSS_TYPE_IPV4_PFCP         (ETH_RSS_PFCP | ETH_RSS_IPV4)
420 #define IAVF_RSS_TYPE_IPV6_PFCP         (ETH_RSS_PFCP | ETH_RSS_IPV6)
421
422 /**
423  * Supported pattern for hash.
424  * The first member is pattern item type,
425  * the second member is input set mask,
426  * the third member is virtchnl_proto_hdrs template
427  */
428 static struct iavf_pattern_match_item iavf_hash_pattern_list[] = {
429         /* IPv4 */
430         {iavf_pattern_eth_ipv4,                         IAVF_RSS_TYPE_OUTER_IPV4,       &outer_ipv4_tmplt},
431         {iavf_pattern_eth_ipv4_udp,                     IAVF_RSS_TYPE_OUTER_IPV4_UDP,   &outer_ipv4_udp_tmplt},
432         {iavf_pattern_eth_ipv4_tcp,                     IAVF_RSS_TYPE_OUTER_IPV4_TCP,   &outer_ipv4_tcp_tmplt},
433         {iavf_pattern_eth_ipv4_sctp,                    IAVF_RSS_TYPE_OUTER_IPV4_SCTP,  &outer_ipv4_sctp_tmplt},
434         {iavf_pattern_eth_vlan_ipv4,                    IAVF_RSS_TYPE_VLAN_IPV4,        &outer_ipv4_tmplt},
435         {iavf_pattern_eth_vlan_ipv4_udp,                IAVF_RSS_TYPE_VLAN_IPV4_UDP,    &outer_ipv4_udp_tmplt},
436         {iavf_pattern_eth_vlan_ipv4_tcp,                IAVF_RSS_TYPE_VLAN_IPV4_TCP,    &outer_ipv4_tcp_tmplt},
437         {iavf_pattern_eth_vlan_ipv4_sctp,               IAVF_RSS_TYPE_VLAN_IPV4_SCTP,   &outer_ipv4_sctp_tmplt},
438         {iavf_pattern_eth_ipv4_gtpu,                    ETH_RSS_IPV4,                   &outer_ipv4_udp_tmplt},
439         {iavf_pattern_eth_ipv4_gtpu_ipv4,               IAVF_RSS_TYPE_GTPU_IPV4,        &inner_ipv4_tmplt},
440         {iavf_pattern_eth_ipv4_gtpu_ipv4_udp,           IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &inner_ipv4_udp_tmplt},
441         {iavf_pattern_eth_ipv4_gtpu_ipv4_tcp,           IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &inner_ipv4_tcp_tmplt},
442         {iavf_pattern_eth_ipv6_gtpu_ipv4,               IAVF_RSS_TYPE_GTPU_IPV4,        &inner_ipv4_tmplt},
443         {iavf_pattern_eth_ipv6_gtpu_ipv4_udp,           IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &inner_ipv4_udp_tmplt},
444         {iavf_pattern_eth_ipv6_gtpu_ipv4_tcp,           IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &inner_ipv4_tcp_tmplt},
445         {iavf_pattern_eth_ipv4_gtpu_eh_ipv4,            IAVF_RSS_TYPE_GTPU_IPV4,        &inner_ipv4_tmplt},
446         {iavf_pattern_eth_ipv4_gtpu_eh_ipv4_udp,        IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &inner_ipv4_udp_tmplt},
447         {iavf_pattern_eth_ipv4_gtpu_eh_ipv4_tcp,        IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &inner_ipv4_tcp_tmplt},
448         {iavf_pattern_eth_ipv6_gtpu_eh_ipv4,            IAVF_RSS_TYPE_GTPU_IPV4,        &inner_ipv4_tmplt},
449         {iavf_pattern_eth_ipv6_gtpu_eh_ipv4_udp,        IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &inner_ipv4_udp_tmplt},
450         {iavf_pattern_eth_ipv6_gtpu_eh_ipv4_tcp,        IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &inner_ipv4_tcp_tmplt},
451         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_ipv4,              IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
452         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_ipv4_udp,          IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
453         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_ipv4_tcp,          IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
454         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_ipv4,              IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
455         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_ipv4_udp,          IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
456         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_ipv4_tcp,          IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
457         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_ipv4,              IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
458         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_ipv4_udp,          IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
459         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_ipv4_tcp,          IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
460         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_ipv4,              IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
461         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_ipv4_udp,          IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
462         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_ipv4_tcp,          IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
463         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_eh_ipv4,           IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
464         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_eh_ipv4_udp,       IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
465         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_eh_ipv4_tcp,       IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
466         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_eh_ipv4,           IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
467         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_eh_ipv4_udp,       IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
468         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_eh_ipv4_tcp,       IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
469         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_eh_ipv4,           IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
470         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_eh_ipv4_udp,       IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
471         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_eh_ipv4_tcp,       IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
472         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_eh_ipv4,           IAVF_RSS_TYPE_GTPU_IPV4,        &second_inner_ipv4_tmplt},
473         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_eh_ipv4_udp,       IAVF_RSS_TYPE_GTPU_IPV4_UDP,    &second_inner_ipv4_udp_tmplt},
474         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_eh_ipv4_tcp,       IAVF_RSS_TYPE_GTPU_IPV4_TCP,    &second_inner_ipv4_tcp_tmplt},
475         {iavf_pattern_eth_ipv4_esp,                     IAVF_RSS_TYPE_IPV4_ESP,         &ipv4_esp_tmplt},
476         {iavf_pattern_eth_ipv4_udp_esp,                 IAVF_RSS_TYPE_IPV4_ESP,         &ipv4_udp_esp_tmplt},
477         {iavf_pattern_eth_ipv4_ah,                      IAVF_RSS_TYPE_IPV4_AH,          &ipv4_ah_tmplt},
478         {iavf_pattern_eth_ipv4_l2tpv3,                  IAVF_RSS_TYPE_IPV4_L2TPV3,      &ipv4_l2tpv3_tmplt},
479         {iavf_pattern_eth_ipv4_pfcp,                    IAVF_RSS_TYPE_IPV4_PFCP,        &ipv4_pfcp_tmplt},
480         {iavf_pattern_eth_ipv4_gtpc,                    ETH_RSS_IPV4,                   &ipv4_udp_gtpc_tmplt},
481         {iavf_pattern_eth_ecpri,                        ETH_RSS_ECPRI,                  &eth_ecpri_tmplt},
482         {iavf_pattern_eth_ipv4_ecpri,                   ETH_RSS_ECPRI,                  &ipv4_ecpri_tmplt},
483         {iavf_pattern_eth_ipv4_gre_ipv4,                IAVF_RSS_TYPE_INNER_IPV4,       &inner_ipv4_tmplt},
484         {iavf_pattern_eth_ipv6_gre_ipv4,                IAVF_RSS_TYPE_INNER_IPV4, &inner_ipv4_tmplt},
485         {iavf_pattern_eth_ipv4_gre_ipv4_tcp,    IAVF_RSS_TYPE_INNER_IPV4_TCP, &inner_ipv4_tcp_tmplt},
486         {iavf_pattern_eth_ipv6_gre_ipv4_tcp,    IAVF_RSS_TYPE_INNER_IPV4_TCP, &inner_ipv4_tcp_tmplt},
487         {iavf_pattern_eth_ipv4_gre_ipv4_udp,    IAVF_RSS_TYPE_INNER_IPV4_UDP, &inner_ipv4_udp_tmplt},
488         {iavf_pattern_eth_ipv6_gre_ipv4_udp,    IAVF_RSS_TYPE_INNER_IPV4_UDP, &inner_ipv4_udp_tmplt},
489         /* IPv6 */
490         {iavf_pattern_eth_ipv6,                         IAVF_RSS_TYPE_OUTER_IPV6,       &outer_ipv6_tmplt},
491         {iavf_pattern_eth_ipv6_frag_ext,                IAVF_RSS_TYPE_OUTER_IPV6_FRAG,  &outer_ipv6_frag_tmplt},
492         {iavf_pattern_eth_ipv6_udp,                     IAVF_RSS_TYPE_OUTER_IPV6_UDP,   &outer_ipv6_udp_tmplt},
493         {iavf_pattern_eth_ipv6_tcp,                     IAVF_RSS_TYPE_OUTER_IPV6_TCP,   &outer_ipv6_tcp_tmplt},
494         {iavf_pattern_eth_ipv6_sctp,                    IAVF_RSS_TYPE_OUTER_IPV6_SCTP,  &outer_ipv6_sctp_tmplt},
495         {iavf_pattern_eth_vlan_ipv6,                    IAVF_RSS_TYPE_VLAN_IPV6,        &outer_ipv6_tmplt},
496         {iavf_pattern_eth_vlan_ipv6_frag_ext,           IAVF_RSS_TYPE_OUTER_IPV6_FRAG,  &outer_ipv6_frag_tmplt},
497         {iavf_pattern_eth_vlan_ipv6_udp,                IAVF_RSS_TYPE_VLAN_IPV6_UDP,    &outer_ipv6_udp_tmplt},
498         {iavf_pattern_eth_vlan_ipv6_tcp,                IAVF_RSS_TYPE_VLAN_IPV6_TCP,    &outer_ipv6_tcp_tmplt},
499         {iavf_pattern_eth_vlan_ipv6_sctp,               IAVF_RSS_TYPE_VLAN_IPV6_SCTP,   &outer_ipv6_sctp_tmplt},
500         {iavf_pattern_eth_ipv6_gtpu,                    ETH_RSS_IPV6,                   &outer_ipv6_udp_tmplt},
501         {iavf_pattern_eth_ipv4_gtpu_ipv6,               IAVF_RSS_TYPE_GTPU_IPV6,        &inner_ipv6_tmplt},
502         {iavf_pattern_eth_ipv4_gtpu_ipv6_udp,           IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &inner_ipv6_udp_tmplt},
503         {iavf_pattern_eth_ipv4_gtpu_ipv6_tcp,           IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &inner_ipv6_tcp_tmplt},
504         {iavf_pattern_eth_ipv6_gtpu_ipv6,               IAVF_RSS_TYPE_GTPU_IPV6,        &inner_ipv6_tmplt},
505         {iavf_pattern_eth_ipv6_gtpu_ipv6_udp,           IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &inner_ipv6_udp_tmplt},
506         {iavf_pattern_eth_ipv6_gtpu_ipv6_tcp,           IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &inner_ipv6_tcp_tmplt},
507         {iavf_pattern_eth_ipv4_gtpu_eh_ipv6,            IAVF_RSS_TYPE_GTPU_IPV6,        &inner_ipv6_tmplt},
508         {iavf_pattern_eth_ipv4_gtpu_eh_ipv6_udp,        IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &inner_ipv6_udp_tmplt},
509         {iavf_pattern_eth_ipv4_gtpu_eh_ipv6_tcp,        IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &inner_ipv6_tcp_tmplt},
510         {iavf_pattern_eth_ipv6_gtpu_eh_ipv6,            IAVF_RSS_TYPE_GTPU_IPV6,        &inner_ipv6_tmplt},
511         {iavf_pattern_eth_ipv6_gtpu_eh_ipv6_udp,        IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &inner_ipv6_udp_tmplt},
512         {iavf_pattern_eth_ipv6_gtpu_eh_ipv6_tcp,        IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &inner_ipv6_tcp_tmplt},
513         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_ipv6,              IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
514         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_ipv6_udp,          IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
515         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_ipv6_tcp,          IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
516         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_ipv6,              IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
517         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_ipv6_udp,          IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
518         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_ipv6_tcp,          IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
519         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_ipv6,              IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
520         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_ipv6_udp,          IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
521         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_ipv6_tcp,          IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
522         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_ipv6,              IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
523         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_ipv6_udp,          IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
524         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_ipv6_tcp,          IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
525         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_eh_ipv6,           IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
526         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_eh_ipv6_udp,       IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
527         {iavf_pattern_eth_ipv4_gre_ipv4_gtpu_eh_ipv6_tcp,       IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
528         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_eh_ipv6,           IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
529         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_eh_ipv6_udp,       IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
530         {iavf_pattern_eth_ipv4_gre_ipv6_gtpu_eh_ipv6_tcp,       IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
531         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_eh_ipv6,           IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
532         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_eh_ipv6_udp,       IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
533         {iavf_pattern_eth_ipv6_gre_ipv4_gtpu_eh_ipv6_tcp,       IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
534         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_eh_ipv6,           IAVF_RSS_TYPE_GTPU_IPV6,        &second_inner_ipv6_tmplt},
535         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_eh_ipv6_udp,       IAVF_RSS_TYPE_GTPU_IPV6_UDP,    &second_inner_ipv6_udp_tmplt},
536         {iavf_pattern_eth_ipv6_gre_ipv6_gtpu_eh_ipv6_tcp,       IAVF_RSS_TYPE_GTPU_IPV6_TCP,    &second_inner_ipv6_tcp_tmplt},
537         {iavf_pattern_eth_ipv6_esp,                     IAVF_RSS_TYPE_IPV6_ESP,         &ipv6_esp_tmplt},
538         {iavf_pattern_eth_ipv6_udp_esp,                 IAVF_RSS_TYPE_IPV6_ESP,         &ipv6_udp_esp_tmplt},
539         {iavf_pattern_eth_ipv6_ah,                      IAVF_RSS_TYPE_IPV6_AH,          &ipv6_ah_tmplt},
540         {iavf_pattern_eth_ipv6_l2tpv3,                  IAVF_RSS_TYPE_IPV6_L2TPV3,      &ipv6_l2tpv3_tmplt},
541         {iavf_pattern_eth_ipv6_pfcp,                    IAVF_RSS_TYPE_IPV6_PFCP,        &ipv6_pfcp_tmplt},
542         {iavf_pattern_eth_ipv6_gtpc,                    ETH_RSS_IPV6,                   &ipv6_udp_gtpc_tmplt},
543         {iavf_pattern_eth_ipv4_gre_ipv6,                IAVF_RSS_TYPE_INNER_IPV6,       &inner_ipv6_tmplt},
544         {iavf_pattern_eth_ipv6_gre_ipv6,                IAVF_RSS_TYPE_INNER_IPV6, &inner_ipv6_tmplt},
545         {iavf_pattern_eth_ipv4_gre_ipv6_tcp,    IAVF_RSS_TYPE_INNER_IPV6_TCP, &inner_ipv6_tcp_tmplt},
546         {iavf_pattern_eth_ipv6_gre_ipv6_tcp,    IAVF_RSS_TYPE_INNER_IPV6_TCP, &inner_ipv6_tcp_tmplt},
547         {iavf_pattern_eth_ipv4_gre_ipv6_udp,    IAVF_RSS_TYPE_INNER_IPV6_UDP, &inner_ipv6_udp_tmplt},
548         {iavf_pattern_eth_ipv6_gre_ipv6_udp,    IAVF_RSS_TYPE_INNER_IPV6_UDP, &inner_ipv6_udp_tmplt},
549 };
550
551 static struct iavf_flow_engine iavf_hash_engine = {
552         .init = iavf_hash_init,
553         .create = iavf_hash_create,
554         .destroy = iavf_hash_destroy,
555         .uninit = iavf_hash_uninit,
556         .free = iavf_hash_free,
557         .type = IAVF_FLOW_ENGINE_HASH,
558 };
559
560 /* Register parser for comms package. */
561 static struct iavf_flow_parser iavf_hash_parser = {
562         .engine = &iavf_hash_engine,
563         .array = iavf_hash_pattern_list,
564         .array_len = RTE_DIM(iavf_hash_pattern_list),
565         .parse_pattern_action = iavf_hash_parse_pattern_action,
566         .stage = IAVF_FLOW_STAGE_RSS,
567 };
568
569 int
570 iavf_rss_hash_set(struct iavf_adapter *ad, uint64_t rss_hf, bool add)
571 {
572         struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
573         struct virtchnl_rss_cfg rss_cfg;
574
575 #define IAVF_RSS_HF_ALL ( \
576         ETH_RSS_IPV4 | \
577         ETH_RSS_IPV6 | \
578         ETH_RSS_NONFRAG_IPV4_UDP | \
579         ETH_RSS_NONFRAG_IPV6_UDP | \
580         ETH_RSS_NONFRAG_IPV4_TCP | \
581         ETH_RSS_NONFRAG_IPV6_TCP | \
582         ETH_RSS_NONFRAG_IPV4_SCTP | \
583         ETH_RSS_NONFRAG_IPV6_SCTP)
584
585         rss_cfg.rss_algorithm = VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
586         if (rss_hf & ETH_RSS_IPV4) {
587                 rss_cfg.proto_hdrs = inner_ipv4_tmplt;
588                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
589         }
590
591         if (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) {
592                 rss_cfg.proto_hdrs = inner_ipv4_udp_tmplt;
593                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
594         }
595
596         if (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) {
597                 rss_cfg.proto_hdrs = inner_ipv4_tcp_tmplt;
598                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
599         }
600
601         if (rss_hf & ETH_RSS_NONFRAG_IPV4_SCTP) {
602                 rss_cfg.proto_hdrs = inner_ipv4_sctp_tmplt;
603                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
604         }
605
606         if (rss_hf & ETH_RSS_IPV6) {
607                 rss_cfg.proto_hdrs = inner_ipv6_tmplt;
608                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
609         }
610
611         if (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) {
612                 rss_cfg.proto_hdrs = inner_ipv6_udp_tmplt;
613                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
614         }
615
616         if (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) {
617                 rss_cfg.proto_hdrs = inner_ipv6_tcp_tmplt;
618                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
619         }
620
621         if (rss_hf & ETH_RSS_NONFRAG_IPV6_SCTP) {
622                 rss_cfg.proto_hdrs = inner_ipv6_sctp_tmplt;
623                 iavf_add_del_rss_cfg(ad, &rss_cfg, add);
624         }
625
626         vf->rss_hf = rss_hf & IAVF_RSS_HF_ALL;
627         return 0;
628 }
629
630 RTE_INIT(iavf_hash_engine_init)
631 {
632         struct iavf_flow_engine *engine = &iavf_hash_engine;
633
634         iavf_register_flow_engine(engine);
635 }
636
637 static int
638 iavf_hash_init(struct iavf_adapter *ad)
639 {
640         struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
641         struct iavf_flow_parser *parser;
642         int ret;
643
644         if (vf->vf_reset)
645                 return -EIO;
646
647         if (!vf->vf_res)
648                 return -EINVAL;
649
650         if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF))
651                 return -ENOTSUP;
652
653         parser = &iavf_hash_parser;
654
655         ret = iavf_register_parser(parser, ad);
656         if (ret) {
657                 PMD_DRV_LOG(ERR, "fail to register hash parser");
658                 return ret;
659         }
660
661         return ret;
662 }
663
664 static int
665 iavf_hash_parse_pattern(const struct rte_flow_item pattern[], uint64_t *phint,
666                         struct rte_flow_error *error)
667 {
668         const struct rte_flow_item *item = pattern;
669         const struct rte_flow_item_gtp_psc *psc;
670         const struct rte_flow_item_ecpri *ecpri;
671         struct rte_ecpri_common_hdr ecpri_common;
672
673         for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
674                 if (item->last) {
675                         rte_flow_error_set(error, EINVAL,
676                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
677                                            "Not support range");
678                         return -rte_errno;
679                 }
680
681                 switch (item->type) {
682                 case RTE_FLOW_ITEM_TYPE_IPV4:
683                         if (!(*phint & IAVF_PHINT_GTPU_MSK) && !(*phint & IAVF_PHINT_GRE))
684                                 *phint |= IAVF_PHINT_OUTER_IPV4;
685                         if ((*phint & IAVF_PHINT_GRE) && !(*phint & IAVF_PHINT_GTPU_MSK))
686                                 *phint |= IAVF_PHINT_MID_IPV4;
687                         break;
688                 case RTE_FLOW_ITEM_TYPE_IPV6:
689                         if (!(*phint & IAVF_PHINT_GTPU_MSK) && !(*phint & IAVF_PHINT_GRE))
690                                 *phint |= IAVF_PHINT_OUTER_IPV6;
691                         if ((*phint & IAVF_PHINT_GRE) && !(*phint & IAVF_PHINT_GTPU_MSK))
692                                 *phint |= IAVF_PHINT_MID_IPV6;
693                         break;
694                 case RTE_FLOW_ITEM_TYPE_GTPU:
695                         *phint |= IAVF_PHINT_GTPU;
696                         break;
697                 case RTE_FLOW_ITEM_TYPE_GTP_PSC:
698                         *phint |= IAVF_PHINT_GTPU_EH;
699                         psc = item->spec;
700                         if (!psc)
701                                 break;
702                         else if (psc->hdr.type == IAVF_GTPU_EH_UPLINK)
703                                 *phint |= IAVF_PHINT_GTPU_EH_UP;
704                         else if (psc->hdr.type == IAVF_GTPU_EH_DWNLINK)
705                                 *phint |= IAVF_PHINT_GTPU_EH_DWN;
706                         break;
707                 case RTE_FLOW_ITEM_TYPE_ECPRI:
708                         ecpri = item->spec;
709                         if (!ecpri)
710                                 break;
711
712                         ecpri_common.u32 = rte_be_to_cpu_32(ecpri->hdr.common.u32);
713
714                         if (ecpri_common.type !=
715                                  RTE_ECPRI_MSG_TYPE_IQ_DATA) {
716                                 rte_flow_error_set(error, EINVAL,
717                                         RTE_FLOW_ERROR_TYPE_ITEM, item,
718                                         "Unsupported common type.");
719                                 return -rte_errno;
720                         }
721                         break;
722                 case RTE_FLOW_ITEM_TYPE_GRE:
723                         *phint |= IAVF_PHINT_GRE;
724                 default:
725                         break;
726                 }
727         }
728
729         return 0;
730 }
731
732 #define REFINE_PROTO_FLD(op, fld) \
733         VIRTCHNL_##op##_PROTO_HDR_FIELD(hdr, VIRTCHNL_PROTO_HDR_##fld)
734 #define REPALCE_PROTO_FLD(fld_1, fld_2) \
735 do { \
736         REFINE_PROTO_FLD(DEL, fld_1);   \
737         REFINE_PROTO_FLD(ADD, fld_2);   \
738 } while (0)
739
740 static void
741 iavf_hash_add_fragment_hdr(struct virtchnl_proto_hdrs *hdrs, int layer)
742 {
743         struct virtchnl_proto_hdr *hdr1;
744         struct virtchnl_proto_hdr *hdr2;
745         int i;
746
747         if (layer < 0 || layer > hdrs->count)
748                 return;
749
750         /* shift headers layer */
751         for (i = hdrs->count; i >= layer; i--) {
752                 hdr1 = &hdrs->proto_hdr[i];
753                 hdr2 = &hdrs->proto_hdr[i - 1];
754                 *hdr1 = *hdr2;
755         }
756
757         /* adding dummy fragment header */
758         hdr1 = &hdrs->proto_hdr[layer];
759         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, IPV4_FRAG);
760         hdrs->count = ++layer;
761 }
762
763 /* refine proto hdrs base on l2, l3, l4 rss type */
764 static void
765 iavf_refine_proto_hdrs_l234(struct virtchnl_proto_hdrs *proto_hdrs,
766                             uint64_t rss_type)
767 {
768         struct virtchnl_proto_hdr *hdr;
769         int i;
770
771         for (i = 0; i < proto_hdrs->count; i++) {
772                 hdr = &proto_hdrs->proto_hdr[i];
773                 switch (hdr->type) {
774                 case VIRTCHNL_PROTO_HDR_ETH:
775                         if (!(rss_type & ETH_RSS_ETH))
776                                 hdr->field_selector = 0;
777                         else if (rss_type & ETH_RSS_L2_SRC_ONLY)
778                                 REFINE_PROTO_FLD(DEL, ETH_DST);
779                         else if (rss_type & ETH_RSS_L2_DST_ONLY)
780                                 REFINE_PROTO_FLD(DEL, ETH_SRC);
781                         break;
782                 case VIRTCHNL_PROTO_HDR_IPV4:
783                         if (rss_type &
784                             (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 |
785                              ETH_RSS_NONFRAG_IPV4_UDP |
786                              ETH_RSS_NONFRAG_IPV4_TCP |
787                              ETH_RSS_NONFRAG_IPV4_SCTP)) {
788                                 if (rss_type & ETH_RSS_FRAG_IPV4) {
789                                         iavf_hash_add_fragment_hdr(proto_hdrs, i + 1);
790                                 } else if (rss_type & ETH_RSS_L3_SRC_ONLY) {
791                                         REFINE_PROTO_FLD(DEL, IPV4_DST);
792                                 } else if (rss_type & ETH_RSS_L3_DST_ONLY) {
793                                         REFINE_PROTO_FLD(DEL, IPV4_SRC);
794                                 } else if (rss_type &
795                                            (ETH_RSS_L4_SRC_ONLY |
796                                             ETH_RSS_L4_DST_ONLY)) {
797                                         REFINE_PROTO_FLD(DEL, IPV4_DST);
798                                         REFINE_PROTO_FLD(DEL, IPV4_SRC);
799                                 }
800                         } else {
801                                 hdr->field_selector = 0;
802                         }
803                         break;
804                 case VIRTCHNL_PROTO_HDR_IPV4_FRAG:
805                         if (rss_type &
806                             (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 |
807                              ETH_RSS_NONFRAG_IPV4_UDP |
808                              ETH_RSS_NONFRAG_IPV4_TCP |
809                              ETH_RSS_NONFRAG_IPV4_SCTP)) {
810                                 if (rss_type & ETH_RSS_FRAG_IPV4)
811                                         REFINE_PROTO_FLD(ADD, IPV4_FRAG_PKID);
812                         } else {
813                                 hdr->field_selector = 0;
814                         }
815                         break;
816                 case VIRTCHNL_PROTO_HDR_IPV6:
817                         if (rss_type &
818                             (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 |
819                              ETH_RSS_NONFRAG_IPV6_UDP |
820                              ETH_RSS_NONFRAG_IPV6_TCP |
821                              ETH_RSS_NONFRAG_IPV6_SCTP)) {
822                                 if (rss_type & ETH_RSS_L3_SRC_ONLY) {
823                                         REFINE_PROTO_FLD(DEL, IPV6_DST);
824                                 } else if (rss_type & ETH_RSS_L3_DST_ONLY) {
825                                         REFINE_PROTO_FLD(DEL, IPV6_SRC);
826                                 } else if (rss_type &
827                                            (ETH_RSS_L4_SRC_ONLY |
828                                             ETH_RSS_L4_DST_ONLY)) {
829                                         REFINE_PROTO_FLD(DEL, IPV6_DST);
830                                         REFINE_PROTO_FLD(DEL, IPV6_SRC);
831                                 }
832                         } else {
833                                 hdr->field_selector = 0;
834                         }
835                         if (rss_type & RTE_ETH_RSS_L3_PRE64) {
836                                 if (REFINE_PROTO_FLD(TEST, IPV6_SRC))
837                                         REPALCE_PROTO_FLD(IPV6_SRC,
838                                                           IPV6_PREFIX64_SRC);
839                                 if (REFINE_PROTO_FLD(TEST, IPV6_DST))
840                                         REPALCE_PROTO_FLD(IPV6_DST,
841                                                           IPV6_PREFIX64_DST);
842                         }
843                         break;
844                 case VIRTCHNL_PROTO_HDR_IPV6_EH_FRAG:
845                         if (rss_type & ETH_RSS_FRAG_IPV6)
846                                 REFINE_PROTO_FLD(ADD, IPV6_EH_FRAG_PKID);
847                         else
848                                 hdr->field_selector = 0;
849
850                         break;
851                 case VIRTCHNL_PROTO_HDR_UDP:
852                         if (rss_type &
853                             (ETH_RSS_NONFRAG_IPV4_UDP |
854                              ETH_RSS_NONFRAG_IPV6_UDP)) {
855                                 if (rss_type & ETH_RSS_L4_SRC_ONLY)
856                                         REFINE_PROTO_FLD(DEL, UDP_DST_PORT);
857                                 else if (rss_type & ETH_RSS_L4_DST_ONLY)
858                                         REFINE_PROTO_FLD(DEL, UDP_SRC_PORT);
859                                 else if (rss_type &
860                                          (ETH_RSS_L3_SRC_ONLY |
861                                           ETH_RSS_L3_DST_ONLY))
862                                         hdr->field_selector = 0;
863                         } else {
864                                 hdr->field_selector = 0;
865                         }
866                         break;
867                 case VIRTCHNL_PROTO_HDR_TCP:
868                         if (rss_type &
869                             (ETH_RSS_NONFRAG_IPV4_TCP |
870                              ETH_RSS_NONFRAG_IPV6_TCP)) {
871                                 if (rss_type & ETH_RSS_L4_SRC_ONLY)
872                                         REFINE_PROTO_FLD(DEL, TCP_DST_PORT);
873                                 else if (rss_type & ETH_RSS_L4_DST_ONLY)
874                                         REFINE_PROTO_FLD(DEL, TCP_SRC_PORT);
875                                 else if (rss_type &
876                                          (ETH_RSS_L3_SRC_ONLY |
877                                           ETH_RSS_L3_DST_ONLY))
878                                         hdr->field_selector = 0;
879                         } else {
880                                 hdr->field_selector = 0;
881                         }
882                         break;
883                 case VIRTCHNL_PROTO_HDR_SCTP:
884                         if (rss_type &
885                             (ETH_RSS_NONFRAG_IPV4_SCTP |
886                              ETH_RSS_NONFRAG_IPV6_SCTP)) {
887                                 if (rss_type & ETH_RSS_L4_SRC_ONLY)
888                                         REFINE_PROTO_FLD(DEL, SCTP_DST_PORT);
889                                 else if (rss_type & ETH_RSS_L4_DST_ONLY)
890                                         REFINE_PROTO_FLD(DEL, SCTP_SRC_PORT);
891                                 else if (rss_type &
892                                          (ETH_RSS_L3_SRC_ONLY |
893                                           ETH_RSS_L3_DST_ONLY))
894                                         hdr->field_selector = 0;
895                         } else {
896                                 hdr->field_selector = 0;
897                         }
898                         break;
899                 case VIRTCHNL_PROTO_HDR_S_VLAN:
900                         if (!(rss_type & ETH_RSS_S_VLAN))
901                                 hdr->field_selector = 0;
902                         break;
903                 case VIRTCHNL_PROTO_HDR_C_VLAN:
904                         if (!(rss_type & ETH_RSS_C_VLAN))
905                                 hdr->field_selector = 0;
906                         break;
907                 case VIRTCHNL_PROTO_HDR_L2TPV3:
908                         if (!(rss_type & ETH_RSS_L2TPV3))
909                                 hdr->field_selector = 0;
910                         break;
911                 case VIRTCHNL_PROTO_HDR_ESP:
912                         if (!(rss_type & ETH_RSS_ESP))
913                                 hdr->field_selector = 0;
914                         break;
915                 case VIRTCHNL_PROTO_HDR_AH:
916                         if (!(rss_type & ETH_RSS_AH))
917                                 hdr->field_selector = 0;
918                         break;
919                 case VIRTCHNL_PROTO_HDR_PFCP:
920                         if (!(rss_type & ETH_RSS_PFCP))
921                                 hdr->field_selector = 0;
922                         break;
923                 case VIRTCHNL_PROTO_HDR_ECPRI:
924                         if (!(rss_type & ETH_RSS_ECPRI))
925                                 hdr->field_selector = 0;
926                         break;
927                 default:
928                         break;
929                 }
930         }
931 }
932
933 /* refine proto hdrs base on gtpu rss type */
934 static void
935 iavf_refine_proto_hdrs_gtpu(struct virtchnl_proto_hdrs *proto_hdrs,
936                             uint64_t rss_type)
937 {
938         struct virtchnl_proto_hdr *hdr;
939         int i;
940
941         if (!(rss_type & ETH_RSS_GTPU))
942                 return;
943
944         for (i = 0; i < proto_hdrs->count; i++) {
945                 hdr = &proto_hdrs->proto_hdr[i];
946                 switch (hdr->type) {
947                 case VIRTCHNL_PROTO_HDR_GTPU_IP:
948                         REFINE_PROTO_FLD(ADD, GTPU_IP_TEID);
949                         break;
950                 default:
951                         break;
952                 }
953         }
954 }
955
956 static void
957 iavf_refine_proto_hdrs_by_pattern(struct virtchnl_proto_hdrs *proto_hdrs,
958                                   uint64_t phint)
959 {
960         struct virtchnl_proto_hdr *hdr1;
961         struct virtchnl_proto_hdr *hdr2;
962         int i, shift_count = 1;
963         int tun_lvl = proto_hdrs->tunnel_level;
964
965         if (!(phint & IAVF_PHINT_GTPU_MSK) && !(phint & IAVF_PHINT_GRE))
966                 return;
967
968         while (tun_lvl) {
969                 if (phint & IAVF_PHINT_LAYERS_MSK)
970                         shift_count = 2;
971
972                 /* shift headers layer */
973                 for (i = proto_hdrs->count - 1 + shift_count;
974                      i > shift_count - 1; i--) {
975                         hdr1 = &proto_hdrs->proto_hdr[i];
976                         hdr2 = &proto_hdrs->proto_hdr[i - shift_count];
977                         *hdr1 = *hdr2;
978                 }
979
980                 if (shift_count == 1) {
981                         /* adding tunnel header at layer 0 */
982                         hdr1 = &proto_hdrs->proto_hdr[0];
983                 } else {
984                         /* adding tunnel header and outer ip header */
985                         hdr1 = &proto_hdrs->proto_hdr[1];
986                         hdr2 = &proto_hdrs->proto_hdr[0];
987                         hdr2->field_selector = 0;
988                         proto_hdrs->count++;
989                         tun_lvl--;
990
991                         if (tun_lvl == TUNNEL_LEVEL_OUTER) {
992                                 if (phint & IAVF_PHINT_OUTER_IPV4)
993                                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr2, IPV4);
994                                 else if (phint & IAVF_PHINT_OUTER_IPV6)
995                                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr2, IPV6);
996                         } else if (tun_lvl == TUNNEL_LEVEL_INNER) {
997                                 if (phint & IAVF_PHINT_MID_IPV4)
998                                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr2, IPV4);
999                                 else if (phint & IAVF_PHINT_MID_IPV6)
1000                                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr2, IPV6);
1001                         }
1002                 }
1003
1004                 hdr1->field_selector = 0;
1005                 proto_hdrs->count++;
1006
1007                 if (phint & IAVF_PHINT_GTPU_EH_DWN)
1008                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, GTPU_EH_PDU_DWN);
1009                 else if (phint & IAVF_PHINT_GTPU_EH_UP)
1010                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, GTPU_EH_PDU_UP);
1011                 else if (phint & IAVF_PHINT_GTPU_EH)
1012                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, GTPU_EH);
1013                 else if (phint & IAVF_PHINT_GTPU)
1014                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, GTPU_IP);
1015
1016                 if (phint & IAVF_PHINT_GRE) {
1017                         if (phint & IAVF_PHINT_GTPU) {
1018                                 /* if GTPoGRE, add GRE header at the outer tunnel  */
1019                                 if (tun_lvl == TUNNEL_LEVEL_OUTER)
1020                                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, GRE);
1021                         } else {
1022                                         VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, GRE);
1023                         }
1024                 }
1025         }
1026         proto_hdrs->tunnel_level = tun_lvl;
1027 }
1028
1029 static void iavf_refine_proto_hdrs(struct virtchnl_proto_hdrs *proto_hdrs,
1030                                    uint64_t rss_type, uint64_t phint)
1031 {
1032         iavf_refine_proto_hdrs_l234(proto_hdrs, rss_type);
1033         iavf_refine_proto_hdrs_by_pattern(proto_hdrs, phint);
1034         iavf_refine_proto_hdrs_gtpu(proto_hdrs, rss_type);
1035 }
1036
1037 static uint64_t invalid_rss_comb[] = {
1038         ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_UDP,
1039         ETH_RSS_IPV4 | ETH_RSS_NONFRAG_IPV4_TCP,
1040         ETH_RSS_IPV6 | ETH_RSS_NONFRAG_IPV6_UDP,
1041         ETH_RSS_IPV6 | ETH_RSS_NONFRAG_IPV6_TCP,
1042         RTE_ETH_RSS_L3_PRE32 | RTE_ETH_RSS_L3_PRE40 |
1043         RTE_ETH_RSS_L3_PRE48 | RTE_ETH_RSS_L3_PRE56 |
1044         RTE_ETH_RSS_L3_PRE96
1045 };
1046
1047 struct rss_attr_type {
1048         uint64_t attr;
1049         uint64_t type;
1050 };
1051
1052 #define VALID_RSS_IPV4_L4       (ETH_RSS_NONFRAG_IPV4_UDP       | \
1053                                  ETH_RSS_NONFRAG_IPV4_TCP       | \
1054                                  ETH_RSS_NONFRAG_IPV4_SCTP)
1055
1056 #define VALID_RSS_IPV6_L4       (ETH_RSS_NONFRAG_IPV6_UDP       | \
1057                                  ETH_RSS_NONFRAG_IPV6_TCP       | \
1058                                  ETH_RSS_NONFRAG_IPV6_SCTP)
1059
1060 #define VALID_RSS_IPV4          (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4 | \
1061                                  VALID_RSS_IPV4_L4)
1062 #define VALID_RSS_IPV6          (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6 | \
1063                                  VALID_RSS_IPV6_L4)
1064 #define VALID_RSS_L3            (VALID_RSS_IPV4 | VALID_RSS_IPV6)
1065 #define VALID_RSS_L4            (VALID_RSS_IPV4_L4 | VALID_RSS_IPV6_L4)
1066
1067 #define VALID_RSS_ATTR          (ETH_RSS_L3_SRC_ONLY    | \
1068                                  ETH_RSS_L3_DST_ONLY    | \
1069                                  ETH_RSS_L4_SRC_ONLY    | \
1070                                  ETH_RSS_L4_DST_ONLY    | \
1071                                  ETH_RSS_L2_SRC_ONLY    | \
1072                                  ETH_RSS_L2_DST_ONLY    | \
1073                                  RTE_ETH_RSS_L3_PRE64)
1074
1075 #define INVALID_RSS_ATTR        (RTE_ETH_RSS_L3_PRE32   | \
1076                                  RTE_ETH_RSS_L3_PRE40   | \
1077                                  RTE_ETH_RSS_L3_PRE48   | \
1078                                  RTE_ETH_RSS_L3_PRE56   | \
1079                                  RTE_ETH_RSS_L3_PRE96)
1080
1081 static struct rss_attr_type rss_attr_to_valid_type[] = {
1082         {ETH_RSS_L2_SRC_ONLY | ETH_RSS_L2_DST_ONLY,     ETH_RSS_ETH},
1083         {ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY,     VALID_RSS_L3},
1084         {ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY,     VALID_RSS_L4},
1085         /* current ipv6 prefix only supports prefix 64 bits*/
1086         {RTE_ETH_RSS_L3_PRE64,                          VALID_RSS_IPV6},
1087         {INVALID_RSS_ATTR,                              0}
1088 };
1089
1090 static bool
1091 iavf_any_invalid_rss_type(enum rte_eth_hash_function rss_func,
1092                           uint64_t rss_type, uint64_t allow_rss_type)
1093 {
1094         uint32_t i;
1095
1096         /**
1097          * Check if l3/l4 SRC/DST_ONLY is set for SYMMETRIC_TOEPLITZ
1098          * hash function.
1099          */
1100         if (rss_func == RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {
1101                 if (rss_type & (ETH_RSS_L3_SRC_ONLY | ETH_RSS_L3_DST_ONLY |
1102                     ETH_RSS_L4_SRC_ONLY | ETH_RSS_L4_DST_ONLY))
1103                         return true;
1104
1105                 if (!(rss_type &
1106                    (ETH_RSS_IPV4 | ETH_RSS_IPV6 |
1107                     ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP |
1108                     ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV6_TCP |
1109                     ETH_RSS_NONFRAG_IPV4_SCTP | ETH_RSS_NONFRAG_IPV6_SCTP)))
1110                         return true;
1111         }
1112
1113         /* check invalid combination */
1114         for (i = 0; i < RTE_DIM(invalid_rss_comb); i++) {
1115                 if (__builtin_popcountll(rss_type & invalid_rss_comb[i]) > 1)
1116                         return true;
1117         }
1118
1119         /* check invalid RSS attribute */
1120         for (i = 0; i < RTE_DIM(rss_attr_to_valid_type); i++) {
1121                 struct rss_attr_type *rat = &rss_attr_to_valid_type[i];
1122
1123                 if (rat->attr & rss_type && !(rat->type & rss_type))
1124                         return true;
1125         }
1126
1127         /* check not allowed RSS type */
1128         rss_type &= ~VALID_RSS_ATTR;
1129
1130         return ((rss_type & allow_rss_type) != rss_type);
1131 }
1132
1133 static int
1134 iavf_hash_parse_action(struct iavf_pattern_match_item *match_item,
1135                        const struct rte_flow_action actions[],
1136                        uint64_t pattern_hint, void **meta,
1137                        struct rte_flow_error *error)
1138 {
1139         struct iavf_rss_meta *rss_meta = (struct iavf_rss_meta *)*meta;
1140         struct virtchnl_proto_hdrs *proto_hdrs;
1141         enum rte_flow_action_type action_type;
1142         const struct rte_flow_action_rss *rss;
1143         const struct rte_flow_action *action;
1144         uint64_t rss_type;
1145
1146         /* Supported action is RSS. */
1147         for (action = actions; action->type !=
1148                 RTE_FLOW_ACTION_TYPE_END; action++) {
1149                 action_type = action->type;
1150                 switch (action_type) {
1151                 case RTE_FLOW_ACTION_TYPE_RSS:
1152                         rss = action->conf;
1153                         rss_type = rss->types;
1154
1155                         if (rss->func ==
1156                             RTE_ETH_HASH_FUNCTION_SIMPLE_XOR){
1157                                 rss_meta->rss_algorithm =
1158                                         VIRTCHNL_RSS_ALG_XOR_ASYMMETRIC;
1159                                 return rte_flow_error_set(error, ENOTSUP,
1160                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
1161                                         "function simple_xor is not supported");
1162                         } else if (rss->func ==
1163                                    RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ) {
1164                                 rss_meta->rss_algorithm =
1165                                         VIRTCHNL_RSS_ALG_TOEPLITZ_SYMMETRIC;
1166                         } else {
1167                                 rss_meta->rss_algorithm =
1168                                         VIRTCHNL_RSS_ALG_TOEPLITZ_ASYMMETRIC;
1169                         }
1170
1171                         if (rss->level)
1172                                 return rte_flow_error_set(error, ENOTSUP,
1173                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
1174                                         "a nonzero RSS encapsulation level is not supported");
1175
1176                         if (rss->key_len)
1177                                 return rte_flow_error_set(error, ENOTSUP,
1178                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
1179                                         "a nonzero RSS key_len is not supported");
1180
1181                         if (rss->queue_num)
1182                                 return rte_flow_error_set(error, ENOTSUP,
1183                                         RTE_FLOW_ERROR_TYPE_ACTION, action,
1184                                         "a non-NULL RSS queue is not supported");
1185
1186                         /**
1187                          * Check simultaneous use of SRC_ONLY and DST_ONLY
1188                          * of the same level.
1189                          */
1190                         rss_type = rte_eth_rss_hf_refine(rss_type);
1191
1192                         if (iavf_any_invalid_rss_type(rss->func, rss_type,
1193                                         match_item->input_set_mask))
1194                                 return rte_flow_error_set(error, ENOTSUP,
1195                                                 RTE_FLOW_ERROR_TYPE_ACTION,
1196                                                 action, "RSS type not supported");
1197                         proto_hdrs = match_item->meta;
1198                         rss_meta->proto_hdrs = *proto_hdrs;
1199                         iavf_refine_proto_hdrs(&rss_meta->proto_hdrs,
1200                                                rss_type, pattern_hint);
1201                         break;
1202
1203                 case RTE_FLOW_ACTION_TYPE_END:
1204                         break;
1205
1206                 default:
1207                         rte_flow_error_set(error, EINVAL,
1208                                            RTE_FLOW_ERROR_TYPE_ACTION, action,
1209                                            "Invalid action.");
1210                         return -rte_errno;
1211                 }
1212         }
1213
1214         return 0;
1215 }
1216
1217 static int
1218 iavf_hash_parse_pattern_action(__rte_unused struct iavf_adapter *ad,
1219                                struct iavf_pattern_match_item *array,
1220                                uint32_t array_len,
1221                                const struct rte_flow_item pattern[],
1222                                const struct rte_flow_action actions[],
1223                                void **meta,
1224                                struct rte_flow_error *error)
1225 {
1226         struct iavf_pattern_match_item *pattern_match_item;
1227         struct iavf_rss_meta *rss_meta_ptr;
1228         uint64_t phint = IAVF_PHINT_NONE;
1229         int ret = 0;
1230
1231         rss_meta_ptr = rte_zmalloc(NULL, sizeof(*rss_meta_ptr), 0);
1232         if (!rss_meta_ptr) {
1233                 rte_flow_error_set(error, EINVAL,
1234                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1235                                    "No memory for rss_meta_ptr");
1236                 return -ENOMEM;
1237         }
1238
1239         /* Check rss supported pattern and find matched pattern. */
1240         pattern_match_item =
1241                 iavf_search_pattern_match_item(pattern, array, array_len,
1242                                                error);
1243         if (!pattern_match_item) {
1244                 ret = -rte_errno;
1245                 goto error;
1246         }
1247
1248         ret = iavf_hash_parse_pattern(pattern, &phint, error);
1249         if (ret)
1250                 goto error;
1251
1252         ret = iavf_hash_parse_action(pattern_match_item, actions, phint,
1253                                      (void **)&rss_meta_ptr, error);
1254
1255 error:
1256         if (!ret && meta)
1257                 *meta = rss_meta_ptr;
1258         else
1259                 rte_free(rss_meta_ptr);
1260
1261         rte_free(pattern_match_item);
1262
1263         return ret;
1264 }
1265
1266 static int
1267 iavf_hash_create(__rte_unused struct iavf_adapter *ad,
1268                  __rte_unused struct rte_flow *flow, void *meta,
1269                  __rte_unused struct rte_flow_error *error)
1270 {
1271         struct iavf_rss_meta *rss_meta = (struct iavf_rss_meta *)meta;
1272         struct virtchnl_rss_cfg *rss_cfg;
1273         int ret = 0;
1274
1275         rss_cfg = rte_zmalloc("iavf rss rule",
1276                               sizeof(struct virtchnl_rss_cfg), 0);
1277         if (!rss_cfg) {
1278                 rte_flow_error_set(error, EINVAL,
1279                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1280                                    "No memory for rss rule");
1281                 return -ENOMEM;
1282         }
1283
1284         rss_cfg->proto_hdrs = rss_meta->proto_hdrs;
1285         rss_cfg->rss_algorithm = rss_meta->rss_algorithm;
1286
1287         ret = iavf_add_del_rss_cfg(ad, rss_cfg, true);
1288         if (!ret) {
1289                 flow->rule = rss_cfg;
1290         } else {
1291                 PMD_DRV_LOG(ERR, "fail to add RSS configure");
1292                 rte_flow_error_set(error, -ret,
1293                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1294                                    "Failed to add rss rule.");
1295                 rte_free(rss_cfg);
1296                 return -rte_errno;
1297         }
1298
1299         rte_free(meta);
1300
1301         return ret;
1302 }
1303
1304 static int
1305 iavf_hash_destroy(__rte_unused struct iavf_adapter *ad,
1306                   struct rte_flow *flow,
1307                   __rte_unused struct rte_flow_error *error)
1308 {
1309         struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
1310         struct virtchnl_rss_cfg *rss_cfg;
1311         int ret = 0;
1312
1313         if (vf->vf_reset)
1314                 return 0;
1315
1316         rss_cfg = (struct virtchnl_rss_cfg *)flow->rule;
1317
1318         ret = iavf_add_del_rss_cfg(ad, rss_cfg, false);
1319         if (ret) {
1320                 PMD_DRV_LOG(ERR, "fail to del RSS configure");
1321                 rte_flow_error_set(error, -ret,
1322                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1323                                    "Failed to delete rss rule.");
1324                 return -rte_errno;
1325         }
1326         return ret;
1327 }
1328
1329 static void
1330 iavf_hash_uninit(struct iavf_adapter *ad)
1331 {
1332         struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
1333         struct rte_eth_rss_conf *rss_conf;
1334
1335         if (vf->vf_reset)
1336                 return;
1337
1338         if (!vf->vf_res)
1339                 return;
1340
1341         if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADV_RSS_PF))
1342                 return;
1343
1344         rss_conf = &ad->eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
1345         if (iavf_rss_hash_set(ad, rss_conf->rss_hf, false))
1346                 PMD_DRV_LOG(ERR, "fail to delete default RSS");
1347
1348         iavf_unregister_parser(&iavf_hash_parser, ad);
1349 }
1350
1351 static void
1352 iavf_hash_free(struct rte_flow *flow)
1353 {
1354         rte_free(flow->rule);
1355 }