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