Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
[linux-2.6-microblaze.git] / drivers / net / ethernet / netronome / nfp / flower / match.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3
4 #include <linux/bitfield.h>
5 #include <net/pkt_cls.h>
6
7 #include "cmsg.h"
8 #include "main.h"
9
10 static void
11 nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext,
12                             struct nfp_flower_meta_tci *msk,
13                             struct flow_rule *rule, u8 key_type)
14 {
15         u16 tmp_tci;
16
17         memset(ext, 0, sizeof(struct nfp_flower_meta_tci));
18         memset(msk, 0, sizeof(struct nfp_flower_meta_tci));
19
20         /* Populate the metadata frame. */
21         ext->nfp_flow_key_layer = key_type;
22         ext->mask_id = ~0;
23
24         msk->nfp_flow_key_layer = key_type;
25         msk->mask_id = ~0;
26
27         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
28                 struct flow_match_vlan match;
29
30                 flow_rule_match_vlan(rule, &match);
31                 /* Populate the tci field. */
32                 tmp_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
33                 tmp_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
34                                       match.key->vlan_priority) |
35                            FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
36                                       match.key->vlan_id);
37                 ext->tci = cpu_to_be16(tmp_tci);
38
39                 tmp_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
40                 tmp_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
41                                       match.mask->vlan_priority) |
42                            FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
43                                       match.mask->vlan_id);
44                 msk->tci = cpu_to_be16(tmp_tci);
45         }
46 }
47
48 static void
49 nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta *frame, u32 key_ext)
50 {
51         frame->nfp_flow_key_layer2 = cpu_to_be32(key_ext);
52 }
53
54 static int
55 nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
56                         bool mask_version, enum nfp_flower_tun_type tun_type,
57                         struct netlink_ext_ack *extack)
58 {
59         if (mask_version) {
60                 frame->in_port = cpu_to_be32(~0);
61                 return 0;
62         }
63
64         if (tun_type) {
65                 frame->in_port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
66         } else {
67                 if (!cmsg_port) {
68                         NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid ingress interface for match offload");
69                         return -EOPNOTSUPP;
70                 }
71                 frame->in_port = cpu_to_be32(cmsg_port);
72         }
73
74         return 0;
75 }
76
77 static void
78 nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext,
79                        struct nfp_flower_mac_mpls *msk, struct flow_rule *rule)
80 {
81         memset(ext, 0, sizeof(struct nfp_flower_mac_mpls));
82         memset(msk, 0, sizeof(struct nfp_flower_mac_mpls));
83
84         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
85                 struct flow_match_eth_addrs match;
86
87                 flow_rule_match_eth_addrs(rule, &match);
88                 /* Populate mac frame. */
89                 ether_addr_copy(ext->mac_dst, &match.key->dst[0]);
90                 ether_addr_copy(ext->mac_src, &match.key->src[0]);
91                 ether_addr_copy(msk->mac_dst, &match.mask->dst[0]);
92                 ether_addr_copy(msk->mac_src, &match.mask->src[0]);
93         }
94
95         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
96                 struct flow_match_mpls match;
97                 u32 t_mpls;
98
99                 flow_rule_match_mpls(rule, &match);
100                 t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.key->mpls_label) |
101                          FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.key->mpls_tc) |
102                          FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.key->mpls_bos) |
103                          NFP_FLOWER_MASK_MPLS_Q;
104                 ext->mpls_lse = cpu_to_be32(t_mpls);
105                 t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB, match.mask->mpls_label) |
106                          FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC, match.mask->mpls_tc) |
107                          FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS, match.mask->mpls_bos) |
108                          NFP_FLOWER_MASK_MPLS_Q;
109                 msk->mpls_lse = cpu_to_be32(t_mpls);
110         } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
111                 /* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q
112                  * bit, which indicates an mpls ether type but without any
113                  * mpls fields.
114                  */
115                 struct flow_match_basic match;
116
117                 flow_rule_match_basic(rule, &match);
118                 if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) ||
119                     match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) {
120                         ext->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
121                         msk->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
122                 }
123         }
124 }
125
126 static void
127 nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext,
128                          struct nfp_flower_tp_ports *msk,
129                          struct flow_rule *rule)
130 {
131         memset(ext, 0, sizeof(struct nfp_flower_tp_ports));
132         memset(msk, 0, sizeof(struct nfp_flower_tp_ports));
133
134         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
135                 struct flow_match_ports match;
136
137                 flow_rule_match_ports(rule, &match);
138                 ext->port_src = match.key->src;
139                 ext->port_dst = match.key->dst;
140                 msk->port_src = match.mask->src;
141                 msk->port_dst = match.mask->dst;
142         }
143 }
144
145 static void
146 nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext,
147                           struct nfp_flower_ip_ext *msk, struct flow_rule *rule)
148 {
149         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
150                 struct flow_match_basic match;
151
152                 flow_rule_match_basic(rule, &match);
153                 ext->proto = match.key->ip_proto;
154                 msk->proto = match.mask->ip_proto;
155         }
156
157         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
158                 struct flow_match_ip match;
159
160                 flow_rule_match_ip(rule, &match);
161                 ext->tos = match.key->tos;
162                 ext->ttl = match.key->ttl;
163                 msk->tos = match.mask->tos;
164                 msk->ttl = match.mask->ttl;
165         }
166
167         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
168                 u16 tcp_flags, tcp_flags_mask;
169                 struct flow_match_tcp match;
170
171                 flow_rule_match_tcp(rule, &match);
172                 tcp_flags = be16_to_cpu(match.key->flags);
173                 tcp_flags_mask = be16_to_cpu(match.mask->flags);
174
175                 if (tcp_flags & TCPHDR_FIN)
176                         ext->flags |= NFP_FL_TCP_FLAG_FIN;
177                 if (tcp_flags_mask & TCPHDR_FIN)
178                         msk->flags |= NFP_FL_TCP_FLAG_FIN;
179
180                 if (tcp_flags & TCPHDR_SYN)
181                         ext->flags |= NFP_FL_TCP_FLAG_SYN;
182                 if (tcp_flags_mask & TCPHDR_SYN)
183                         msk->flags |= NFP_FL_TCP_FLAG_SYN;
184
185                 if (tcp_flags & TCPHDR_RST)
186                         ext->flags |= NFP_FL_TCP_FLAG_RST;
187                 if (tcp_flags_mask & TCPHDR_RST)
188                         msk->flags |= NFP_FL_TCP_FLAG_RST;
189
190                 if (tcp_flags & TCPHDR_PSH)
191                         ext->flags |= NFP_FL_TCP_FLAG_PSH;
192                 if (tcp_flags_mask & TCPHDR_PSH)
193                         msk->flags |= NFP_FL_TCP_FLAG_PSH;
194
195                 if (tcp_flags & TCPHDR_URG)
196                         ext->flags |= NFP_FL_TCP_FLAG_URG;
197                 if (tcp_flags_mask & TCPHDR_URG)
198                         msk->flags |= NFP_FL_TCP_FLAG_URG;
199         }
200
201         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
202                 struct flow_match_control match;
203
204                 flow_rule_match_control(rule, &match);
205                 if (match.key->flags & FLOW_DIS_IS_FRAGMENT)
206                         ext->flags |= NFP_FL_IP_FRAGMENTED;
207                 if (match.mask->flags & FLOW_DIS_IS_FRAGMENT)
208                         msk->flags |= NFP_FL_IP_FRAGMENTED;
209                 if (match.key->flags & FLOW_DIS_FIRST_FRAG)
210                         ext->flags |= NFP_FL_IP_FRAG_FIRST;
211                 if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
212                         msk->flags |= NFP_FL_IP_FRAG_FIRST;
213         }
214 }
215
216 static void
217 nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext,
218                         struct nfp_flower_ipv4 *msk, struct flow_rule *rule)
219 {
220         struct flow_match_ipv4_addrs match;
221
222         memset(ext, 0, sizeof(struct nfp_flower_ipv4));
223         memset(msk, 0, sizeof(struct nfp_flower_ipv4));
224
225         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
226                 flow_rule_match_ipv4_addrs(rule, &match);
227                 ext->ipv4_src = match.key->src;
228                 ext->ipv4_dst = match.key->dst;
229                 msk->ipv4_src = match.mask->src;
230                 msk->ipv4_dst = match.mask->dst;
231         }
232
233         nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
234 }
235
236 static void
237 nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext,
238                         struct nfp_flower_ipv6 *msk, struct flow_rule *rule)
239 {
240         memset(ext, 0, sizeof(struct nfp_flower_ipv6));
241         memset(msk, 0, sizeof(struct nfp_flower_ipv6));
242
243         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
244                 struct flow_match_ipv6_addrs match;
245
246                 flow_rule_match_ipv6_addrs(rule, &match);
247                 ext->ipv6_src = match.key->src;
248                 ext->ipv6_dst = match.key->dst;
249                 msk->ipv6_src = match.mask->src;
250                 msk->ipv6_dst = match.mask->dst;
251         }
252
253         nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
254 }
255
256 static int
257 nfp_flower_compile_geneve_opt(void *ext, void *msk, struct flow_rule *rule)
258 {
259         struct flow_match_enc_opts match;
260
261         flow_rule_match_enc_opts(rule, &match);
262         memcpy(ext, match.key->data, match.key->len);
263         memcpy(msk, match.mask->data, match.mask->len);
264
265         return 0;
266 }
267
268 static void
269 nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 *ext,
270                                   struct nfp_flower_tun_ipv4 *msk,
271                                   struct flow_rule *rule)
272 {
273         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
274                 struct flow_match_ipv4_addrs match;
275
276                 flow_rule_match_enc_ipv4_addrs(rule, &match);
277                 ext->src = match.key->src;
278                 ext->dst = match.key->dst;
279                 msk->src = match.mask->src;
280                 msk->dst = match.mask->dst;
281         }
282 }
283
284 static void
285 nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 *ext,
286                                   struct nfp_flower_tun_ipv6 *msk,
287                                   struct flow_rule *rule)
288 {
289         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
290                 struct flow_match_ipv6_addrs match;
291
292                 flow_rule_match_enc_ipv6_addrs(rule, &match);
293                 ext->src = match.key->src;
294                 ext->dst = match.key->dst;
295                 msk->src = match.mask->src;
296                 msk->dst = match.mask->dst;
297         }
298 }
299
300 static void
301 nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext *ext,
302                               struct nfp_flower_tun_ip_ext *msk,
303                               struct flow_rule *rule)
304 {
305         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
306                 struct flow_match_ip match;
307
308                 flow_rule_match_enc_ip(rule, &match);
309                 ext->tos = match.key->tos;
310                 ext->ttl = match.key->ttl;
311                 msk->tos = match.mask->tos;
312                 msk->ttl = match.mask->ttl;
313         }
314 }
315
316 static void
317 nfp_flower_compile_tun_udp_key(__be32 *key, __be32 *key_msk,
318                                struct flow_rule *rule)
319 {
320         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
321                 struct flow_match_enc_keyid match;
322                 u32 vni;
323
324                 flow_rule_match_enc_keyid(rule, &match);
325                 vni = be32_to_cpu(match.key->keyid) << NFP_FL_TUN_VNI_OFFSET;
326                 *key = cpu_to_be32(vni);
327                 vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET;
328                 *key_msk = cpu_to_be32(vni);
329         }
330 }
331
332 static void
333 nfp_flower_compile_tun_gre_key(__be32 *key, __be32 *key_msk, __be16 *flags,
334                                __be16 *flags_msk, struct flow_rule *rule)
335 {
336         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
337                 struct flow_match_enc_keyid match;
338
339                 flow_rule_match_enc_keyid(rule, &match);
340                 *key = match.key->keyid;
341                 *key_msk = match.mask->keyid;
342
343                 *flags = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
344                 *flags_msk = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
345         }
346 }
347
348 static void
349 nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun *ext,
350                                 struct nfp_flower_ipv4_gre_tun *msk,
351                                 struct flow_rule *rule)
352 {
353         memset(ext, 0, sizeof(struct nfp_flower_ipv4_gre_tun));
354         memset(msk, 0, sizeof(struct nfp_flower_ipv4_gre_tun));
355
356         /* NVGRE is the only supported GRE tunnel type */
357         ext->ethertype = cpu_to_be16(ETH_P_TEB);
358         msk->ethertype = cpu_to_be16(~0);
359
360         nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
361         nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
362         nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
363                                        &ext->tun_flags, &msk->tun_flags, rule);
364 }
365
366 static void
367 nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext,
368                                 struct nfp_flower_ipv4_udp_tun *msk,
369                                 struct flow_rule *rule)
370 {
371         memset(ext, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
372         memset(msk, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
373
374         nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
375         nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
376         nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
377 }
378
379 static void
380 nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun *ext,
381                                 struct nfp_flower_ipv6_udp_tun *msk,
382                                 struct flow_rule *rule)
383 {
384         memset(ext, 0, sizeof(struct nfp_flower_ipv6_udp_tun));
385         memset(msk, 0, sizeof(struct nfp_flower_ipv6_udp_tun));
386
387         nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
388         nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
389         nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
390 }
391
392 static void
393 nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun *ext,
394                                 struct nfp_flower_ipv6_gre_tun *msk,
395                                 struct flow_rule *rule)
396 {
397         memset(ext, 0, sizeof(struct nfp_flower_ipv6_gre_tun));
398         memset(msk, 0, sizeof(struct nfp_flower_ipv6_gre_tun));
399
400         /* NVGRE is the only supported GRE tunnel type */
401         ext->ethertype = cpu_to_be16(ETH_P_TEB);
402         msk->ethertype = cpu_to_be16(~0);
403
404         nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
405         nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
406         nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
407                                        &ext->tun_flags, &msk->tun_flags, rule);
408 }
409
410 int nfp_flower_compile_flow_match(struct nfp_app *app,
411                                   struct flow_cls_offload *flow,
412                                   struct nfp_fl_key_ls *key_ls,
413                                   struct net_device *netdev,
414                                   struct nfp_fl_payload *nfp_flow,
415                                   enum nfp_flower_tun_type tun_type,
416                                   struct netlink_ext_ack *extack)
417 {
418         struct flow_rule *rule = flow_cls_offload_flow_rule(flow);
419         u32 port_id;
420         int err;
421         u8 *ext;
422         u8 *msk;
423
424         port_id = nfp_flower_get_port_id_from_netdev(app, netdev);
425
426         memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
427         memset(nfp_flow->mask_data, 0, key_ls->key_size);
428
429         ext = nfp_flow->unmasked_data;
430         msk = nfp_flow->mask_data;
431
432         nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext,
433                                     (struct nfp_flower_meta_tci *)msk,
434                                     rule, key_ls->key_layer);
435         ext += sizeof(struct nfp_flower_meta_tci);
436         msk += sizeof(struct nfp_flower_meta_tci);
437
438         /* Populate Extended Metadata if Required. */
439         if (NFP_FLOWER_LAYER_EXT_META & key_ls->key_layer) {
440                 nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)ext,
441                                             key_ls->key_layer_two);
442                 nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)msk,
443                                             key_ls->key_layer_two);
444                 ext += sizeof(struct nfp_flower_ext_meta);
445                 msk += sizeof(struct nfp_flower_ext_meta);
446         }
447
448         /* Populate Exact Port data. */
449         err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
450                                       port_id, false, tun_type, extack);
451         if (err)
452                 return err;
453
454         /* Populate Mask Port Data. */
455         err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
456                                       port_id, true, tun_type, extack);
457         if (err)
458                 return err;
459
460         ext += sizeof(struct nfp_flower_in_port);
461         msk += sizeof(struct nfp_flower_in_port);
462
463         if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) {
464                 nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext,
465                                        (struct nfp_flower_mac_mpls *)msk,
466                                        rule);
467                 ext += sizeof(struct nfp_flower_mac_mpls);
468                 msk += sizeof(struct nfp_flower_mac_mpls);
469         }
470
471         if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) {
472                 nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext,
473                                          (struct nfp_flower_tp_ports *)msk,
474                                          rule);
475                 ext += sizeof(struct nfp_flower_tp_ports);
476                 msk += sizeof(struct nfp_flower_tp_ports);
477         }
478
479         if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) {
480                 nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext,
481                                         (struct nfp_flower_ipv4 *)msk,
482                                         rule);
483                 ext += sizeof(struct nfp_flower_ipv4);
484                 msk += sizeof(struct nfp_flower_ipv4);
485         }
486
487         if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) {
488                 nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext,
489                                         (struct nfp_flower_ipv6 *)msk,
490                                         rule);
491                 ext += sizeof(struct nfp_flower_ipv6);
492                 msk += sizeof(struct nfp_flower_ipv6);
493         }
494
495         if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GRE) {
496                 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
497                         struct nfp_flower_ipv6_gre_tun *gre_match;
498                         struct nfp_ipv6_addr_entry *entry;
499                         struct in6_addr *dst;
500
501                         nfp_flower_compile_ipv6_gre_tun((void *)ext,
502                                                         (void *)msk, rule);
503                         gre_match = (struct nfp_flower_ipv6_gre_tun *)ext;
504                         dst = &gre_match->ipv6.dst;
505                         ext += sizeof(struct nfp_flower_ipv6_gre_tun);
506                         msk += sizeof(struct nfp_flower_ipv6_gre_tun);
507
508                         entry = nfp_tunnel_add_ipv6_off(app, dst);
509                         if (!entry)
510                                 return -EOPNOTSUPP;
511
512                         nfp_flow->nfp_tun_ipv6 = entry;
513                 } else {
514                         __be32 dst;
515
516                         nfp_flower_compile_ipv4_gre_tun((void *)ext,
517                                                         (void *)msk, rule);
518                         dst = ((struct nfp_flower_ipv4_gre_tun *)ext)->ipv4.dst;
519                         ext += sizeof(struct nfp_flower_ipv4_gre_tun);
520                         msk += sizeof(struct nfp_flower_ipv4_gre_tun);
521
522                         /* Store the tunnel destination in the rule data.
523                          * This must be present and be an exact match.
524                          */
525                         nfp_flow->nfp_tun_ipv4_addr = dst;
526                         nfp_tunnel_add_ipv4_off(app, dst);
527                 }
528         }
529
530         if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN ||
531             key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) {
532                 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
533                         struct nfp_flower_ipv6_udp_tun *udp_match;
534                         struct nfp_ipv6_addr_entry *entry;
535                         struct in6_addr *dst;
536
537                         nfp_flower_compile_ipv6_udp_tun((void *)ext,
538                                                         (void *)msk, rule);
539                         udp_match = (struct nfp_flower_ipv6_udp_tun *)ext;
540                         dst = &udp_match->ipv6.dst;
541                         ext += sizeof(struct nfp_flower_ipv6_udp_tun);
542                         msk += sizeof(struct nfp_flower_ipv6_udp_tun);
543
544                         entry = nfp_tunnel_add_ipv6_off(app, dst);
545                         if (!entry)
546                                 return -EOPNOTSUPP;
547
548                         nfp_flow->nfp_tun_ipv6 = entry;
549                 } else {
550                         __be32 dst;
551
552                         nfp_flower_compile_ipv4_udp_tun((void *)ext,
553                                                         (void *)msk, rule);
554                         dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ipv4.dst;
555                         ext += sizeof(struct nfp_flower_ipv4_udp_tun);
556                         msk += sizeof(struct nfp_flower_ipv4_udp_tun);
557
558                         /* Store the tunnel destination in the rule data.
559                          * This must be present and be an exact match.
560                          */
561                         nfp_flow->nfp_tun_ipv4_addr = dst;
562                         nfp_tunnel_add_ipv4_off(app, dst);
563                 }
564
565                 if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) {
566                         err = nfp_flower_compile_geneve_opt(ext, msk, rule);
567                         if (err)
568                                 return err;
569                 }
570         }
571
572         return 0;
573 }