196de2506SJakub Kicinski // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
296de2506SJakub Kicinski /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
35571e8c9SPieter Jansen van Vuuren
45571e8c9SPieter Jansen van Vuuren #include <linux/bitfield.h>
55571e8c9SPieter Jansen van Vuuren #include <net/pkt_cls.h>
65571e8c9SPieter Jansen van Vuuren
75571e8c9SPieter Jansen van Vuuren #include "cmsg.h"
85571e8c9SPieter Jansen van Vuuren #include "main.h"
95571e8c9SPieter Jansen van Vuuren
1016416d37SYinjun Zhang void
nfp_flower_compile_meta(struct nfp_flower_meta_tci * ext,struct nfp_flower_meta_tci * msk,u8 key_type)1116416d37SYinjun Zhang nfp_flower_compile_meta(struct nfp_flower_meta_tci *ext,
1216416d37SYinjun Zhang struct nfp_flower_meta_tci *msk, u8 key_type)
135571e8c9SPieter Jansen van Vuuren {
148f256622SPablo Neira Ayuso /* Populate the metadata frame. */
158f256622SPablo Neira Ayuso ext->nfp_flow_key_layer = key_type;
168f256622SPablo Neira Ayuso ext->mask_id = ~0;
178f256622SPablo Neira Ayuso
188f256622SPablo Neira Ayuso msk->nfp_flow_key_layer = key_type;
198f256622SPablo Neira Ayuso msk->mask_id = ~0;
2016416d37SYinjun Zhang }
218f256622SPablo Neira Ayuso
2216416d37SYinjun Zhang void
nfp_flower_compile_tci(struct nfp_flower_meta_tci * ext,struct nfp_flower_meta_tci * msk,struct flow_rule * rule)2316416d37SYinjun Zhang nfp_flower_compile_tci(struct nfp_flower_meta_tci *ext,
2416416d37SYinjun Zhang struct nfp_flower_meta_tci *msk,
2516416d37SYinjun Zhang struct flow_rule *rule)
2616416d37SYinjun Zhang {
2716416d37SYinjun Zhang u16 msk_tci, key_tci;
2816416d37SYinjun Zhang
2916416d37SYinjun Zhang if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
308f256622SPablo Neira Ayuso struct flow_match_vlan match;
318f256622SPablo Neira Ayuso
328f256622SPablo Neira Ayuso flow_rule_match_vlan(rule, &match);
335571e8c9SPieter Jansen van Vuuren /* Populate the tci field. */
3416416d37SYinjun Zhang key_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
3516416d37SYinjun Zhang key_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
368f256622SPablo Neira Ayuso match.key->vlan_priority) |
375571e8c9SPieter Jansen van Vuuren FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
38f7ee799aSPieter Jansen van Vuuren match.key->vlan_id);
39f7ee799aSPieter Jansen van Vuuren
4016416d37SYinjun Zhang msk_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
4116416d37SYinjun Zhang msk_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
428f256622SPablo Neira Ayuso match.mask->vlan_priority) |
438f256622SPablo Neira Ayuso FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
44f7ee799aSPieter Jansen van Vuuren match.mask->vlan_id);
4516416d37SYinjun Zhang
4616416d37SYinjun Zhang ext->tci |= cpu_to_be16((key_tci & msk_tci));
4716416d37SYinjun Zhang msk->tci |= cpu_to_be16(msk_tci);
485571e8c9SPieter Jansen van Vuuren }
49a7cd39e0SPieter Jansen van Vuuren }
505571e8c9SPieter Jansen van Vuuren
51bedeca15SJohn Hurley static void
nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci * ext,struct nfp_flower_meta_tci * msk,struct flow_rule * rule,u8 key_type,bool qinq_sup)5216416d37SYinjun Zhang nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext,
5316416d37SYinjun Zhang struct nfp_flower_meta_tci *msk,
5416416d37SYinjun Zhang struct flow_rule *rule, u8 key_type, bool qinq_sup)
5516416d37SYinjun Zhang {
5616416d37SYinjun Zhang memset(ext, 0, sizeof(struct nfp_flower_meta_tci));
5716416d37SYinjun Zhang memset(msk, 0, sizeof(struct nfp_flower_meta_tci));
5816416d37SYinjun Zhang
5916416d37SYinjun Zhang nfp_flower_compile_meta(ext, msk, key_type);
6016416d37SYinjun Zhang
6116416d37SYinjun Zhang if (!qinq_sup)
6216416d37SYinjun Zhang nfp_flower_compile_tci(ext, msk, rule);
6316416d37SYinjun Zhang }
6416416d37SYinjun Zhang
6516416d37SYinjun Zhang void
nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta * frame,u32 key_ext)66bedeca15SJohn Hurley nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta *frame, u32 key_ext)
67bedeca15SJohn Hurley {
68bedeca15SJohn Hurley frame->nfp_flow_key_layer2 = cpu_to_be32(key_ext);
69bedeca15SJohn Hurley }
70bedeca15SJohn Hurley
7116416d37SYinjun Zhang int
nfp_flower_compile_port(struct nfp_flower_in_port * frame,u32 cmsg_port,bool mask_version,enum nfp_flower_tun_type tun_type,struct netlink_ext_ack * extack)725571e8c9SPieter Jansen van Vuuren nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
73bef6e97dSPieter Jansen van Vuuren bool mask_version, enum nfp_flower_tun_type tun_type,
74bef6e97dSPieter Jansen van Vuuren struct netlink_ext_ack *extack)
755571e8c9SPieter Jansen van Vuuren {
765571e8c9SPieter Jansen van Vuuren if (mask_version) {
775571e8c9SPieter Jansen van Vuuren frame->in_port = cpu_to_be32(~0);
785571e8c9SPieter Jansen van Vuuren return 0;
795571e8c9SPieter Jansen van Vuuren }
805571e8c9SPieter Jansen van Vuuren
817885b4fcSJohn Hurley if (tun_type) {
82611aec10SJohn Hurley frame->in_port = cpu_to_be32(NFP_FL_PORT_TYPE_TUN | tun_type);
837885b4fcSJohn Hurley } else {
84bef6e97dSPieter Jansen van Vuuren if (!cmsg_port) {
85bef6e97dSPieter Jansen van Vuuren NL_SET_ERR_MSG_MOD(extack, "unsupported offload: invalid ingress interface for match offload");
867885b4fcSJohn Hurley return -EOPNOTSUPP;
87bef6e97dSPieter Jansen van Vuuren }
885571e8c9SPieter Jansen van Vuuren frame->in_port = cpu_to_be32(cmsg_port);
897885b4fcSJohn Hurley }
905571e8c9SPieter Jansen van Vuuren
915571e8c9SPieter Jansen van Vuuren return 0;
925571e8c9SPieter Jansen van Vuuren }
935571e8c9SPieter Jansen van Vuuren
9416416d37SYinjun Zhang void
nfp_flower_compile_mac(struct nfp_flower_mac_mpls * ext,struct nfp_flower_mac_mpls * msk,struct flow_rule * rule)958f256622SPablo Neira Ayuso nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext,
9616416d37SYinjun Zhang struct nfp_flower_mac_mpls *msk,
9716416d37SYinjun Zhang struct flow_rule *rule)
985571e8c9SPieter Jansen van Vuuren {
998f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
1008f256622SPablo Neira Ayuso struct flow_match_eth_addrs match;
101e43d940fSYinjun Zhang u8 tmp;
10216416d37SYinjun Zhang int i;
1038f256622SPablo Neira Ayuso
1048f256622SPablo Neira Ayuso flow_rule_match_eth_addrs(rule, &match);
1055571e8c9SPieter Jansen van Vuuren /* Populate mac frame. */
10616416d37SYinjun Zhang for (i = 0; i < ETH_ALEN; i++) {
107e43d940fSYinjun Zhang tmp = match.key->dst[i] & match.mask->dst[i];
108e43d940fSYinjun Zhang ext->mac_dst[i] |= tmp & (~msk->mac_dst[i]);
10916416d37SYinjun Zhang msk->mac_dst[i] |= match.mask->dst[i];
110e43d940fSYinjun Zhang
111e43d940fSYinjun Zhang tmp = match.key->src[i] & match.mask->src[i];
112e43d940fSYinjun Zhang ext->mac_src[i] |= tmp & (~msk->mac_src[i]);
11316416d37SYinjun Zhang msk->mac_src[i] |= match.mask->src[i];
11416416d37SYinjun Zhang }
11516416d37SYinjun Zhang }
116a7cd39e0SPieter Jansen van Vuuren }
1175571e8c9SPieter Jansen van Vuuren
11816416d37SYinjun Zhang int
nfp_flower_compile_mpls(struct nfp_flower_mac_mpls * ext,struct nfp_flower_mac_mpls * msk,struct flow_rule * rule,struct netlink_ext_ack * extack)11916416d37SYinjun Zhang nfp_flower_compile_mpls(struct nfp_flower_mac_mpls *ext,
12016416d37SYinjun Zhang struct nfp_flower_mac_mpls *msk,
12116416d37SYinjun Zhang struct flow_rule *rule,
12216416d37SYinjun Zhang struct netlink_ext_ack *extack)
12316416d37SYinjun Zhang {
1248f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
1258f256622SPablo Neira Ayuso struct flow_match_mpls match;
12616416d37SYinjun Zhang u32 key_mpls, msk_mpls;
127bb055c19SPieter Jansen van Vuuren
1288f256622SPablo Neira Ayuso flow_rule_match_mpls(rule, &match);
12958cff782SGuillaume Nault
13058cff782SGuillaume Nault /* Only support matching the first LSE */
13158cff782SGuillaume Nault if (match.mask->used_lses != 1) {
13258cff782SGuillaume Nault NL_SET_ERR_MSG_MOD(extack,
13358cff782SGuillaume Nault "unsupported offload: invalid LSE depth for MPLS match offload");
13458cff782SGuillaume Nault return -EOPNOTSUPP;
13558cff782SGuillaume Nault }
13658cff782SGuillaume Nault
13716416d37SYinjun Zhang key_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB,
13858cff782SGuillaume Nault match.key->ls[0].mpls_label) |
13958cff782SGuillaume Nault FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC,
14058cff782SGuillaume Nault match.key->ls[0].mpls_tc) |
14158cff782SGuillaume Nault FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS,
14258cff782SGuillaume Nault match.key->ls[0].mpls_bos) |
143bb055c19SPieter Jansen van Vuuren NFP_FLOWER_MASK_MPLS_Q;
14416416d37SYinjun Zhang
14516416d37SYinjun Zhang msk_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB,
14658cff782SGuillaume Nault match.mask->ls[0].mpls_label) |
14758cff782SGuillaume Nault FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC,
14858cff782SGuillaume Nault match.mask->ls[0].mpls_tc) |
14958cff782SGuillaume Nault FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS,
15058cff782SGuillaume Nault match.mask->ls[0].mpls_bos) |
1518f256622SPablo Neira Ayuso NFP_FLOWER_MASK_MPLS_Q;
15216416d37SYinjun Zhang
15316416d37SYinjun Zhang ext->mpls_lse |= cpu_to_be32((key_mpls & msk_mpls));
15416416d37SYinjun Zhang msk->mpls_lse |= cpu_to_be32(msk_mpls);
1558f256622SPablo Neira Ayuso } else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
156a6411941SPieter Jansen van Vuuren /* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q
157a6411941SPieter Jansen van Vuuren * bit, which indicates an mpls ether type but without any
158a6411941SPieter Jansen van Vuuren * mpls fields.
159a6411941SPieter Jansen van Vuuren */
1608f256622SPablo Neira Ayuso struct flow_match_basic match;
161a6411941SPieter Jansen van Vuuren
1628f256622SPablo Neira Ayuso flow_rule_match_basic(rule, &match);
1638f256622SPablo Neira Ayuso if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) ||
1648f256622SPablo Neira Ayuso match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) {
16516416d37SYinjun Zhang ext->mpls_lse |= cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
16616416d37SYinjun Zhang msk->mpls_lse |= cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
1678f256622SPablo Neira Ayuso }
168bb055c19SPieter Jansen van Vuuren }
16958cff782SGuillaume Nault
17058cff782SGuillaume Nault return 0;
1715571e8c9SPieter Jansen van Vuuren }
1725571e8c9SPieter Jansen van Vuuren
17316416d37SYinjun Zhang static int
nfp_flower_compile_mac_mpls(struct nfp_flower_mac_mpls * ext,struct nfp_flower_mac_mpls * msk,struct flow_rule * rule,struct netlink_ext_ack * extack)17416416d37SYinjun Zhang nfp_flower_compile_mac_mpls(struct nfp_flower_mac_mpls *ext,
17516416d37SYinjun Zhang struct nfp_flower_mac_mpls *msk,
17616416d37SYinjun Zhang struct flow_rule *rule,
17716416d37SYinjun Zhang struct netlink_ext_ack *extack)
17816416d37SYinjun Zhang {
17916416d37SYinjun Zhang memset(ext, 0, sizeof(struct nfp_flower_mac_mpls));
18016416d37SYinjun Zhang memset(msk, 0, sizeof(struct nfp_flower_mac_mpls));
18116416d37SYinjun Zhang
18216416d37SYinjun Zhang nfp_flower_compile_mac(ext, msk, rule);
18316416d37SYinjun Zhang
18416416d37SYinjun Zhang return nfp_flower_compile_mpls(ext, msk, rule, extack);
18516416d37SYinjun Zhang }
18616416d37SYinjun Zhang
18716416d37SYinjun Zhang void
nfp_flower_compile_tport(struct nfp_flower_tp_ports * ext,struct nfp_flower_tp_ports * msk,struct flow_rule * rule)1888f256622SPablo Neira Ayuso nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext,
1898f256622SPablo Neira Ayuso struct nfp_flower_tp_ports *msk,
19031c491e5SJohn Hurley struct flow_rule *rule)
1915571e8c9SPieter Jansen van Vuuren {
1928f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
1938f256622SPablo Neira Ayuso struct flow_match_ports match;
194e43d940fSYinjun Zhang __be16 tmp;
1958f256622SPablo Neira Ayuso
1968f256622SPablo Neira Ayuso flow_rule_match_ports(rule, &match);
197e43d940fSYinjun Zhang
198e43d940fSYinjun Zhang tmp = match.key->src & match.mask->src;
199e43d940fSYinjun Zhang ext->port_src |= tmp & (~msk->port_src);
20016416d37SYinjun Zhang msk->port_src |= match.mask->src;
201e43d940fSYinjun Zhang
202e43d940fSYinjun Zhang tmp = match.key->dst & match.mask->dst;
203e43d940fSYinjun Zhang ext->port_dst |= tmp & (~msk->port_dst);
20416416d37SYinjun Zhang msk->port_dst |= match.mask->dst;
205a7cd39e0SPieter Jansen van Vuuren }
2065571e8c9SPieter Jansen van Vuuren }
2075571e8c9SPieter Jansen van Vuuren
2085571e8c9SPieter Jansen van Vuuren static void
nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext * ext,struct nfp_flower_ip_ext * msk,struct flow_rule * rule)2098f256622SPablo Neira Ayuso nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext,
21031c491e5SJohn Hurley struct nfp_flower_ip_ext *msk, struct flow_rule *rule)
2115571e8c9SPieter Jansen van Vuuren {
2128f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
2138f256622SPablo Neira Ayuso struct flow_match_basic match;
21407e1671cSPieter Jansen van Vuuren
2158f256622SPablo Neira Ayuso flow_rule_match_basic(rule, &match);
21616416d37SYinjun Zhang ext->proto |= match.key->ip_proto & match.mask->ip_proto;
21716416d37SYinjun Zhang msk->proto |= match.mask->ip_proto;
218a7cd39e0SPieter Jansen van Vuuren }
219a1e9203cSPieter Jansen van Vuuren
2208f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
2218f256622SPablo Neira Ayuso struct flow_match_ip match;
222e43d940fSYinjun Zhang u8 tmp;
223a1e9203cSPieter Jansen van Vuuren
2248f256622SPablo Neira Ayuso flow_rule_match_ip(rule, &match);
225e43d940fSYinjun Zhang
226e43d940fSYinjun Zhang tmp = match.key->tos & match.mask->tos;
227e43d940fSYinjun Zhang ext->tos |= tmp & (~msk->tos);
22816416d37SYinjun Zhang msk->tos |= match.mask->tos;
229e43d940fSYinjun Zhang
230e43d940fSYinjun Zhang tmp = match.key->ttl & match.mask->ttl;
231e43d940fSYinjun Zhang ext->ttl |= tmp & (~msk->ttl);
23216416d37SYinjun Zhang msk->ttl |= match.mask->ttl;
233a1e9203cSPieter Jansen van Vuuren }
234ffa61202SPieter Jansen van Vuuren
2358f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
2360496743bSPieter Jansen van Vuuren u16 tcp_flags, tcp_flags_mask;
2378f256622SPablo Neira Ayuso struct flow_match_tcp match;
238ffa61202SPieter Jansen van Vuuren
2398f256622SPablo Neira Ayuso flow_rule_match_tcp(rule, &match);
2408f256622SPablo Neira Ayuso tcp_flags = be16_to_cpu(match.key->flags);
2410496743bSPieter Jansen van Vuuren tcp_flags_mask = be16_to_cpu(match.mask->flags);
242ffa61202SPieter Jansen van Vuuren
2430496743bSPieter Jansen van Vuuren if (tcp_flags & TCPHDR_FIN)
2448f256622SPablo Neira Ayuso ext->flags |= NFP_FL_TCP_FLAG_FIN;
2450496743bSPieter Jansen van Vuuren if (tcp_flags_mask & TCPHDR_FIN)
2468f256622SPablo Neira Ayuso msk->flags |= NFP_FL_TCP_FLAG_FIN;
2470496743bSPieter Jansen van Vuuren
2480496743bSPieter Jansen van Vuuren if (tcp_flags & TCPHDR_SYN)
2498f256622SPablo Neira Ayuso ext->flags |= NFP_FL_TCP_FLAG_SYN;
2500496743bSPieter Jansen van Vuuren if (tcp_flags_mask & TCPHDR_SYN)
2518f256622SPablo Neira Ayuso msk->flags |= NFP_FL_TCP_FLAG_SYN;
2520496743bSPieter Jansen van Vuuren
2530496743bSPieter Jansen van Vuuren if (tcp_flags & TCPHDR_RST)
2548f256622SPablo Neira Ayuso ext->flags |= NFP_FL_TCP_FLAG_RST;
2550496743bSPieter Jansen van Vuuren if (tcp_flags_mask & TCPHDR_RST)
2568f256622SPablo Neira Ayuso msk->flags |= NFP_FL_TCP_FLAG_RST;
2570496743bSPieter Jansen van Vuuren
2580496743bSPieter Jansen van Vuuren if (tcp_flags & TCPHDR_PSH)
2598f256622SPablo Neira Ayuso ext->flags |= NFP_FL_TCP_FLAG_PSH;
2600496743bSPieter Jansen van Vuuren if (tcp_flags_mask & TCPHDR_PSH)
2618f256622SPablo Neira Ayuso msk->flags |= NFP_FL_TCP_FLAG_PSH;
2620496743bSPieter Jansen van Vuuren
2630496743bSPieter Jansen van Vuuren if (tcp_flags & TCPHDR_URG)
2648f256622SPablo Neira Ayuso ext->flags |= NFP_FL_TCP_FLAG_URG;
2650496743bSPieter Jansen van Vuuren if (tcp_flags_mask & TCPHDR_URG)
2668f256622SPablo Neira Ayuso msk->flags |= NFP_FL_TCP_FLAG_URG;
2678f256622SPablo Neira Ayuso }
26871ea5343SPieter Jansen van Vuuren
2698f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
2708f256622SPablo Neira Ayuso struct flow_match_control match;
27171ea5343SPieter Jansen van Vuuren
2728f256622SPablo Neira Ayuso flow_rule_match_control(rule, &match);
2730496743bSPieter Jansen van Vuuren if (match.key->flags & FLOW_DIS_IS_FRAGMENT)
2748f256622SPablo Neira Ayuso ext->flags |= NFP_FL_IP_FRAGMENTED;
2750496743bSPieter Jansen van Vuuren if (match.mask->flags & FLOW_DIS_IS_FRAGMENT)
2768f256622SPablo Neira Ayuso msk->flags |= NFP_FL_IP_FRAGMENTED;
2770496743bSPieter Jansen van Vuuren if (match.key->flags & FLOW_DIS_FIRST_FRAG)
2788f256622SPablo Neira Ayuso ext->flags |= NFP_FL_IP_FRAG_FIRST;
2790496743bSPieter Jansen van Vuuren if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
2808f256622SPablo Neira Ayuso msk->flags |= NFP_FL_IP_FRAG_FIRST;
2818f256622SPablo Neira Ayuso }
28271ea5343SPieter Jansen van Vuuren }
2835571e8c9SPieter Jansen van Vuuren
2845571e8c9SPieter Jansen van Vuuren static void
nfp_flower_fill_vlan(struct flow_match_vlan * match,struct nfp_flower_vlan * ext,struct nfp_flower_vlan * msk,bool outer_vlan)28516416d37SYinjun Zhang nfp_flower_fill_vlan(struct flow_match_vlan *match,
28616416d37SYinjun Zhang struct nfp_flower_vlan *ext,
28716416d37SYinjun Zhang struct nfp_flower_vlan *msk, bool outer_vlan)
2880d630f58SLouis Peens {
28916416d37SYinjun Zhang struct flow_dissector_key_vlan *mask = match->mask;
29016416d37SYinjun Zhang struct flow_dissector_key_vlan *key = match->key;
29116416d37SYinjun Zhang u16 msk_tci, key_tci;
2920d630f58SLouis Peens
29316416d37SYinjun Zhang key_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
29416416d37SYinjun Zhang key_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
2950d630f58SLouis Peens key->vlan_priority) |
2960d630f58SLouis Peens FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
2970d630f58SLouis Peens key->vlan_id);
29816416d37SYinjun Zhang msk_tci = NFP_FLOWER_MASK_VLAN_PRESENT;
29916416d37SYinjun Zhang msk_tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
30016416d37SYinjun Zhang mask->vlan_priority) |
30116416d37SYinjun Zhang FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
30216416d37SYinjun Zhang mask->vlan_id);
3030d630f58SLouis Peens
3040d630f58SLouis Peens if (outer_vlan) {
30516416d37SYinjun Zhang ext->outer_tci |= cpu_to_be16((key_tci & msk_tci));
30616416d37SYinjun Zhang ext->outer_tpid |= key->vlan_tpid & mask->vlan_tpid;
30716416d37SYinjun Zhang msk->outer_tci |= cpu_to_be16(msk_tci);
30816416d37SYinjun Zhang msk->outer_tpid |= mask->vlan_tpid;
3090d630f58SLouis Peens } else {
31016416d37SYinjun Zhang ext->inner_tci |= cpu_to_be16((key_tci & msk_tci));
31116416d37SYinjun Zhang ext->inner_tpid |= key->vlan_tpid & mask->vlan_tpid;
31216416d37SYinjun Zhang msk->inner_tci |= cpu_to_be16(msk_tci);
31316416d37SYinjun Zhang msk->inner_tpid |= mask->vlan_tpid;
3140d630f58SLouis Peens }
3150d630f58SLouis Peens }
3160d630f58SLouis Peens
31716416d37SYinjun Zhang void
nfp_flower_compile_vlan(struct nfp_flower_vlan * ext,struct nfp_flower_vlan * msk,struct flow_rule * rule)3180d630f58SLouis Peens nfp_flower_compile_vlan(struct nfp_flower_vlan *ext,
3190d630f58SLouis Peens struct nfp_flower_vlan *msk,
3200d630f58SLouis Peens struct flow_rule *rule)
3210d630f58SLouis Peens {
3220d630f58SLouis Peens struct flow_match_vlan match;
3230d630f58SLouis Peens
3240d630f58SLouis Peens if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
3250d630f58SLouis Peens flow_rule_match_vlan(rule, &match);
32616416d37SYinjun Zhang nfp_flower_fill_vlan(&match, ext, msk, true);
3270d630f58SLouis Peens }
3280d630f58SLouis Peens if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
3290d630f58SLouis Peens flow_rule_match_cvlan(rule, &match);
33016416d37SYinjun Zhang nfp_flower_fill_vlan(&match, ext, msk, false);
3310d630f58SLouis Peens }
3320d630f58SLouis Peens }
3330d630f58SLouis Peens
33416416d37SYinjun Zhang void
nfp_flower_compile_ipv4(struct nfp_flower_ipv4 * ext,struct nfp_flower_ipv4 * msk,struct flow_rule * rule)3358f256622SPablo Neira Ayuso nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext,
33631c491e5SJohn Hurley struct nfp_flower_ipv4 *msk, struct flow_rule *rule)
33707e1671cSPieter Jansen van Vuuren {
33816416d37SYinjun Zhang if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
3398f256622SPablo Neira Ayuso struct flow_match_ipv4_addrs match;
340e43d940fSYinjun Zhang __be32 tmp;
34107e1671cSPieter Jansen van Vuuren
3428f256622SPablo Neira Ayuso flow_rule_match_ipv4_addrs(rule, &match);
343e43d940fSYinjun Zhang
344e43d940fSYinjun Zhang tmp = match.key->src & match.mask->src;
345e43d940fSYinjun Zhang ext->ipv4_src |= tmp & (~msk->ipv4_src);
34616416d37SYinjun Zhang msk->ipv4_src |= match.mask->src;
347e43d940fSYinjun Zhang
348e43d940fSYinjun Zhang tmp = match.key->dst & match.mask->dst;
349e43d940fSYinjun Zhang ext->ipv4_dst |= tmp & (~msk->ipv4_dst);
35016416d37SYinjun Zhang msk->ipv4_dst |= match.mask->dst;
35107e1671cSPieter Jansen van Vuuren }
35207e1671cSPieter Jansen van Vuuren
35331c491e5SJohn Hurley nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
35407e1671cSPieter Jansen van Vuuren }
35507e1671cSPieter Jansen van Vuuren
35616416d37SYinjun Zhang void
nfp_flower_compile_ipv6(struct nfp_flower_ipv6 * ext,struct nfp_flower_ipv6 * msk,struct flow_rule * rule)3578f256622SPablo Neira Ayuso nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext,
35831c491e5SJohn Hurley struct nfp_flower_ipv6 *msk, struct flow_rule *rule)
3595571e8c9SPieter Jansen van Vuuren {
3608f256622SPablo Neira Ayuso if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
3618f256622SPablo Neira Ayuso struct flow_match_ipv6_addrs match;
362e43d940fSYinjun Zhang u8 tmp;
36316416d37SYinjun Zhang int i;
3648f256622SPablo Neira Ayuso
3658f256622SPablo Neira Ayuso flow_rule_match_ipv6_addrs(rule, &match);
36616416d37SYinjun Zhang for (i = 0; i < sizeof(ext->ipv6_src); i++) {
367e43d940fSYinjun Zhang tmp = match.key->src.s6_addr[i] &
36816416d37SYinjun Zhang match.mask->src.s6_addr[i];
369e43d940fSYinjun Zhang ext->ipv6_src.s6_addr[i] |= tmp &
370e43d940fSYinjun Zhang (~msk->ipv6_src.s6_addr[i]);
37116416d37SYinjun Zhang msk->ipv6_src.s6_addr[i] |= match.mask->src.s6_addr[i];
372e43d940fSYinjun Zhang
373e43d940fSYinjun Zhang tmp = match.key->dst.s6_addr[i] &
374e43d940fSYinjun Zhang match.mask->dst.s6_addr[i];
375e43d940fSYinjun Zhang ext->ipv6_dst.s6_addr[i] |= tmp &
376e43d940fSYinjun Zhang (~msk->ipv6_dst.s6_addr[i]);
37716416d37SYinjun Zhang msk->ipv6_dst.s6_addr[i] |= match.mask->dst.s6_addr[i];
37816416d37SYinjun Zhang }
379a7cd39e0SPieter Jansen van Vuuren }
3805571e8c9SPieter Jansen van Vuuren
38131c491e5SJohn Hurley nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
3825571e8c9SPieter Jansen van Vuuren }
3835571e8c9SPieter Jansen van Vuuren
38416416d37SYinjun Zhang void
nfp_flower_compile_geneve_opt(u8 * ext,u8 * msk,struct flow_rule * rule)38516416d37SYinjun Zhang nfp_flower_compile_geneve_opt(u8 *ext, u8 *msk, struct flow_rule *rule)
3860a22b17aSPieter Jansen van Vuuren {
3878f256622SPablo Neira Ayuso struct flow_match_enc_opts match;
38816416d37SYinjun Zhang int i;
3890a22b17aSPieter Jansen van Vuuren
39016416d37SYinjun Zhang if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_OPTS)) {
39131c491e5SJohn Hurley flow_rule_match_enc_opts(rule, &match);
3920a22b17aSPieter Jansen van Vuuren
39316416d37SYinjun Zhang for (i = 0; i < match.mask->len; i++) {
39416416d37SYinjun Zhang ext[i] |= match.key->data[i] & match.mask->data[i];
39516416d37SYinjun Zhang msk[i] |= match.mask->data[i];
39616416d37SYinjun Zhang }
39716416d37SYinjun Zhang }
3980a22b17aSPieter Jansen van Vuuren }
3990a22b17aSPieter Jansen van Vuuren
400611aec10SJohn Hurley static void
nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 * ext,struct nfp_flower_tun_ipv4 * msk,struct flow_rule * rule)4014bf8758aSPieter Jansen van Vuuren nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 *ext,
4024bf8758aSPieter Jansen van Vuuren struct nfp_flower_tun_ipv4 *msk,
40331c491e5SJohn Hurley struct flow_rule *rule)
4044bf8758aSPieter Jansen van Vuuren {
4054bf8758aSPieter Jansen van Vuuren if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
4064bf8758aSPieter Jansen van Vuuren struct flow_match_ipv4_addrs match;
4074bf8758aSPieter Jansen van Vuuren
4084bf8758aSPieter Jansen van Vuuren flow_rule_match_enc_ipv4_addrs(rule, &match);
40916416d37SYinjun Zhang ext->src |= match.key->src & match.mask->src;
41016416d37SYinjun Zhang ext->dst |= match.key->dst & match.mask->dst;
41116416d37SYinjun Zhang msk->src |= match.mask->src;
41216416d37SYinjun Zhang msk->dst |= match.mask->dst;
4134bf8758aSPieter Jansen van Vuuren }
4144bf8758aSPieter Jansen van Vuuren }
4154bf8758aSPieter Jansen van Vuuren
4164bf8758aSPieter Jansen van Vuuren static void
nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 * ext,struct nfp_flower_tun_ipv6 * msk,struct flow_rule * rule)41778a722afSJohn Hurley nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 *ext,
41878a722afSJohn Hurley struct nfp_flower_tun_ipv6 *msk,
41978a722afSJohn Hurley struct flow_rule *rule)
42078a722afSJohn Hurley {
42178a722afSJohn Hurley if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
42278a722afSJohn Hurley struct flow_match_ipv6_addrs match;
42316416d37SYinjun Zhang int i;
42478a722afSJohn Hurley
42578a722afSJohn Hurley flow_rule_match_enc_ipv6_addrs(rule, &match);
42616416d37SYinjun Zhang for (i = 0; i < sizeof(ext->src); i++) {
42716416d37SYinjun Zhang ext->src.s6_addr[i] |= match.key->src.s6_addr[i] &
42816416d37SYinjun Zhang match.mask->src.s6_addr[i];
42916416d37SYinjun Zhang ext->dst.s6_addr[i] |= match.key->dst.s6_addr[i] &
43016416d37SYinjun Zhang match.mask->dst.s6_addr[i];
43116416d37SYinjun Zhang msk->src.s6_addr[i] |= match.mask->src.s6_addr[i];
43216416d37SYinjun Zhang msk->dst.s6_addr[i] |= match.mask->dst.s6_addr[i];
43316416d37SYinjun Zhang }
43478a722afSJohn Hurley }
43578a722afSJohn Hurley }
43678a722afSJohn Hurley
43778a722afSJohn Hurley static void
nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext * ext,struct nfp_flower_tun_ip_ext * msk,struct flow_rule * rule)4384bf8758aSPieter Jansen van Vuuren nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext *ext,
4394bf8758aSPieter Jansen van Vuuren struct nfp_flower_tun_ip_ext *msk,
44031c491e5SJohn Hurley struct flow_rule *rule)
4414bf8758aSPieter Jansen van Vuuren {
4424bf8758aSPieter Jansen van Vuuren if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
4434bf8758aSPieter Jansen van Vuuren struct flow_match_ip match;
4444bf8758aSPieter Jansen van Vuuren
4454bf8758aSPieter Jansen van Vuuren flow_rule_match_enc_ip(rule, &match);
44616416d37SYinjun Zhang ext->tos |= match.key->tos & match.mask->tos;
44716416d37SYinjun Zhang ext->ttl |= match.key->ttl & match.mask->ttl;
44816416d37SYinjun Zhang msk->tos |= match.mask->tos;
44916416d37SYinjun Zhang msk->ttl |= match.mask->ttl;
4504bf8758aSPieter Jansen van Vuuren }
4514bf8758aSPieter Jansen van Vuuren }
4524bf8758aSPieter Jansen van Vuuren
4534bf8758aSPieter Jansen van Vuuren static void
nfp_flower_compile_tun_udp_key(__be32 * key,__be32 * key_msk,struct flow_rule * rule)45477a5f73aSJohn Hurley nfp_flower_compile_tun_udp_key(__be32 *key, __be32 *key_msk,
45577a5f73aSJohn Hurley struct flow_rule *rule)
45677a5f73aSJohn Hurley {
45777a5f73aSJohn Hurley if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
45877a5f73aSJohn Hurley struct flow_match_enc_keyid match;
45977a5f73aSJohn Hurley u32 vni;
46077a5f73aSJohn Hurley
46177a5f73aSJohn Hurley flow_rule_match_enc_keyid(rule, &match);
46216416d37SYinjun Zhang vni = be32_to_cpu((match.key->keyid & match.mask->keyid)) <<
46316416d37SYinjun Zhang NFP_FL_TUN_VNI_OFFSET;
46416416d37SYinjun Zhang *key |= cpu_to_be32(vni);
46577a5f73aSJohn Hurley vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET;
46616416d37SYinjun Zhang *key_msk |= cpu_to_be32(vni);
46777a5f73aSJohn Hurley }
46877a5f73aSJohn Hurley }
46977a5f73aSJohn Hurley
47077a5f73aSJohn Hurley static void
nfp_flower_compile_tun_gre_key(__be32 * key,__be32 * key_msk,__be16 * flags,__be16 * flags_msk,struct flow_rule * rule)47177a5f73aSJohn Hurley nfp_flower_compile_tun_gre_key(__be32 *key, __be32 *key_msk, __be16 *flags,
47277a5f73aSJohn Hurley __be16 *flags_msk, struct flow_rule *rule)
47377a5f73aSJohn Hurley {
47477a5f73aSJohn Hurley if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
47577a5f73aSJohn Hurley struct flow_match_enc_keyid match;
47677a5f73aSJohn Hurley
47777a5f73aSJohn Hurley flow_rule_match_enc_keyid(rule, &match);
47816416d37SYinjun Zhang *key |= match.key->keyid & match.mask->keyid;
47916416d37SYinjun Zhang *key_msk |= match.mask->keyid;
48077a5f73aSJohn Hurley
48177a5f73aSJohn Hurley *flags = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
48277a5f73aSJohn Hurley *flags_msk = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
48377a5f73aSJohn Hurley }
48477a5f73aSJohn Hurley }
48577a5f73aSJohn Hurley
48616416d37SYinjun Zhang void
nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun * ext,struct nfp_flower_ipv4_gre_tun * msk,struct flow_rule * rule)487e3a6aba0SPieter Jansen van Vuuren nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun *ext,
488e3a6aba0SPieter Jansen van Vuuren struct nfp_flower_ipv4_gre_tun *msk,
48931c491e5SJohn Hurley struct flow_rule *rule)
490e3a6aba0SPieter Jansen van Vuuren {
491e3a6aba0SPieter Jansen van Vuuren /* NVGRE is the only supported GRE tunnel type */
492e3a6aba0SPieter Jansen van Vuuren ext->ethertype = cpu_to_be16(ETH_P_TEB);
493e3a6aba0SPieter Jansen van Vuuren msk->ethertype = cpu_to_be16(~0);
494e3a6aba0SPieter Jansen van Vuuren
49531c491e5SJohn Hurley nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
49631c491e5SJohn Hurley nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
49777a5f73aSJohn Hurley nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
49877a5f73aSJohn Hurley &ext->tun_flags, &msk->tun_flags, rule);
499e3a6aba0SPieter Jansen van Vuuren }
500e3a6aba0SPieter Jansen van Vuuren
50116416d37SYinjun Zhang void
nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun * ext,struct nfp_flower_ipv4_udp_tun * msk,struct flow_rule * rule)5028f256622SPablo Neira Ayuso nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext,
5038f256622SPablo Neira Ayuso struct nfp_flower_ipv4_udp_tun *msk,
50431c491e5SJohn Hurley struct flow_rule *rule)
505611aec10SJohn Hurley {
50631c491e5SJohn Hurley nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
50731c491e5SJohn Hurley nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
50877a5f73aSJohn Hurley nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
509611aec10SJohn Hurley }
510611aec10SJohn Hurley
51116416d37SYinjun Zhang void
nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun * ext,struct nfp_flower_ipv6_udp_tun * msk,struct flow_rule * rule)51278a722afSJohn Hurley nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun *ext,
51378a722afSJohn Hurley struct nfp_flower_ipv6_udp_tun *msk,
51478a722afSJohn Hurley struct flow_rule *rule)
51578a722afSJohn Hurley {
51678a722afSJohn Hurley nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
51778a722afSJohn Hurley nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
51878a722afSJohn Hurley nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
51978a722afSJohn Hurley }
52078a722afSJohn Hurley
52116416d37SYinjun Zhang void
nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun * ext,struct nfp_flower_ipv6_gre_tun * msk,struct flow_rule * rule)52278a722afSJohn Hurley nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun *ext,
52378a722afSJohn Hurley struct nfp_flower_ipv6_gre_tun *msk,
52478a722afSJohn Hurley struct flow_rule *rule)
52578a722afSJohn Hurley {
52678a722afSJohn Hurley /* NVGRE is the only supported GRE tunnel type */
52778a722afSJohn Hurley ext->ethertype = cpu_to_be16(ETH_P_TEB);
52878a722afSJohn Hurley msk->ethertype = cpu_to_be16(~0);
52978a722afSJohn Hurley
53078a722afSJohn Hurley nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
53178a722afSJohn Hurley nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
53278a722afSJohn Hurley nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
53378a722afSJohn Hurley &ext->tun_flags, &msk->tun_flags, rule);
53478a722afSJohn Hurley }
53578a722afSJohn Hurley
nfp_flower_compile_flow_match(struct nfp_app * app,struct flow_rule * rule,struct nfp_fl_key_ls * key_ls,struct net_device * netdev,struct nfp_fl_payload * nfp_flow,enum nfp_flower_tun_type tun_type,struct netlink_ext_ack * extack)5367885b4fcSJohn Hurley int nfp_flower_compile_flow_match(struct nfp_app *app,
5374b15fb18SLouis Peens struct flow_rule *rule,
5385571e8c9SPieter Jansen van Vuuren struct nfp_fl_key_ls *key_ls,
5395571e8c9SPieter Jansen van Vuuren struct net_device *netdev,
540bedeca15SJohn Hurley struct nfp_fl_payload *nfp_flow,
541bef6e97dSPieter Jansen van Vuuren enum nfp_flower_tun_type tun_type,
542bef6e97dSPieter Jansen van Vuuren struct netlink_ext_ack *extack)
5435571e8c9SPieter Jansen van Vuuren {
5440d630f58SLouis Peens struct nfp_flower_priv *priv = app->priv;
5450d630f58SLouis Peens bool qinq_sup;
5464d12ba42SJohn Hurley u32 port_id;
547e4cab45aSLouis Peens int ext_len;
5485571e8c9SPieter Jansen van Vuuren int err;
5495571e8c9SPieter Jansen van Vuuren u8 *ext;
5505571e8c9SPieter Jansen van Vuuren u8 *msk;
5515571e8c9SPieter Jansen van Vuuren
5524d12ba42SJohn Hurley port_id = nfp_flower_get_port_id_from_netdev(app, netdev);
5537885b4fcSJohn Hurley
5545571e8c9SPieter Jansen van Vuuren memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
5555571e8c9SPieter Jansen van Vuuren memset(nfp_flow->mask_data, 0, key_ls->key_size);
5565571e8c9SPieter Jansen van Vuuren
5575571e8c9SPieter Jansen van Vuuren ext = nfp_flow->unmasked_data;
5585571e8c9SPieter Jansen van Vuuren msk = nfp_flow->mask_data;
559a427673eSJohn Hurley
5600d630f58SLouis Peens qinq_sup = !!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ);
5610d630f58SLouis Peens
562a427673eSJohn Hurley nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext,
5638f256622SPablo Neira Ayuso (struct nfp_flower_meta_tci *)msk,
5640d630f58SLouis Peens rule, key_ls->key_layer, qinq_sup);
565a427673eSJohn Hurley ext += sizeof(struct nfp_flower_meta_tci);
566a427673eSJohn Hurley msk += sizeof(struct nfp_flower_meta_tci);
5675571e8c9SPieter Jansen van Vuuren
568bedeca15SJohn Hurley /* Populate Extended Metadata if Required. */
569bedeca15SJohn Hurley if (NFP_FLOWER_LAYER_EXT_META & key_ls->key_layer) {
570bedeca15SJohn Hurley nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)ext,
571bedeca15SJohn Hurley key_ls->key_layer_two);
572bedeca15SJohn Hurley nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)msk,
573bedeca15SJohn Hurley key_ls->key_layer_two);
574bedeca15SJohn Hurley ext += sizeof(struct nfp_flower_ext_meta);
575bedeca15SJohn Hurley msk += sizeof(struct nfp_flower_ext_meta);
576bedeca15SJohn Hurley }
577bedeca15SJohn Hurley
5785571e8c9SPieter Jansen van Vuuren /* Populate Exact Port data. */
5795571e8c9SPieter Jansen van Vuuren err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
580bef6e97dSPieter Jansen van Vuuren port_id, false, tun_type, extack);
5815571e8c9SPieter Jansen van Vuuren if (err)
5825571e8c9SPieter Jansen van Vuuren return err;
5835571e8c9SPieter Jansen van Vuuren
5845571e8c9SPieter Jansen van Vuuren /* Populate Mask Port Data. */
5855571e8c9SPieter Jansen van Vuuren err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
586bef6e97dSPieter Jansen van Vuuren port_id, true, tun_type, extack);
5875571e8c9SPieter Jansen van Vuuren if (err)
5885571e8c9SPieter Jansen van Vuuren return err;
5895571e8c9SPieter Jansen van Vuuren
5905571e8c9SPieter Jansen van Vuuren ext += sizeof(struct nfp_flower_in_port);
5915571e8c9SPieter Jansen van Vuuren msk += sizeof(struct nfp_flower_in_port);
5925571e8c9SPieter Jansen van Vuuren
5935571e8c9SPieter Jansen van Vuuren if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) {
59416416d37SYinjun Zhang err = nfp_flower_compile_mac_mpls((struct nfp_flower_mac_mpls *)ext,
5958f256622SPablo Neira Ayuso (struct nfp_flower_mac_mpls *)msk,
59658cff782SGuillaume Nault rule, extack);
59758cff782SGuillaume Nault if (err)
59858cff782SGuillaume Nault return err;
59958cff782SGuillaume Nault
6005571e8c9SPieter Jansen van Vuuren ext += sizeof(struct nfp_flower_mac_mpls);
6015571e8c9SPieter Jansen van Vuuren msk += sizeof(struct nfp_flower_mac_mpls);
6025571e8c9SPieter Jansen van Vuuren }
6035571e8c9SPieter Jansen van Vuuren
6045571e8c9SPieter Jansen van Vuuren if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) {
6055571e8c9SPieter Jansen van Vuuren nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext,
6068f256622SPablo Neira Ayuso (struct nfp_flower_tp_ports *)msk,
60731c491e5SJohn Hurley rule);
6085571e8c9SPieter Jansen van Vuuren ext += sizeof(struct nfp_flower_tp_ports);
6095571e8c9SPieter Jansen van Vuuren msk += sizeof(struct nfp_flower_tp_ports);
6105571e8c9SPieter Jansen van Vuuren }
6115571e8c9SPieter Jansen van Vuuren
6125571e8c9SPieter Jansen van Vuuren if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) {
6135571e8c9SPieter Jansen van Vuuren nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext,
6148f256622SPablo Neira Ayuso (struct nfp_flower_ipv4 *)msk,
61531c491e5SJohn Hurley rule);
6165571e8c9SPieter Jansen van Vuuren ext += sizeof(struct nfp_flower_ipv4);
6175571e8c9SPieter Jansen van Vuuren msk += sizeof(struct nfp_flower_ipv4);
6185571e8c9SPieter Jansen van Vuuren }
6195571e8c9SPieter Jansen van Vuuren
6205571e8c9SPieter Jansen van Vuuren if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) {
6215571e8c9SPieter Jansen van Vuuren nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext,
6228f256622SPablo Neira Ayuso (struct nfp_flower_ipv6 *)msk,
62331c491e5SJohn Hurley rule);
6245571e8c9SPieter Jansen van Vuuren ext += sizeof(struct nfp_flower_ipv6);
6255571e8c9SPieter Jansen van Vuuren msk += sizeof(struct nfp_flower_ipv6);
6265571e8c9SPieter Jansen van Vuuren }
6275571e8c9SPieter Jansen van Vuuren
628*a0b84334SEtienne van der Linde if (NFP_FLOWER_LAYER2_QINQ & key_ls->key_layer_two) {
629*a0b84334SEtienne van der Linde nfp_flower_compile_vlan((struct nfp_flower_vlan *)ext,
630*a0b84334SEtienne van der Linde (struct nfp_flower_vlan *)msk,
631*a0b84334SEtienne van der Linde rule);
632*a0b84334SEtienne van der Linde ext += sizeof(struct nfp_flower_vlan);
633*a0b84334SEtienne van der Linde msk += sizeof(struct nfp_flower_vlan);
634*a0b84334SEtienne van der Linde }
635*a0b84334SEtienne van der Linde
636e3a6aba0SPieter Jansen van Vuuren if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GRE) {
63778a722afSJohn Hurley if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
638cfa18993SJohn Hurley struct nfp_flower_ipv6_gre_tun *gre_match;
639cfa18993SJohn Hurley struct nfp_ipv6_addr_entry *entry;
640cfa18993SJohn Hurley struct in6_addr *dst;
641cfa18993SJohn Hurley
64278a722afSJohn Hurley nfp_flower_compile_ipv6_gre_tun((void *)ext,
64378a722afSJohn Hurley (void *)msk, rule);
644cfa18993SJohn Hurley gre_match = (struct nfp_flower_ipv6_gre_tun *)ext;
645cfa18993SJohn Hurley dst = &gre_match->ipv6.dst;
64678a722afSJohn Hurley ext += sizeof(struct nfp_flower_ipv6_gre_tun);
64778a722afSJohn Hurley msk += sizeof(struct nfp_flower_ipv6_gre_tun);
648cfa18993SJohn Hurley
649cfa18993SJohn Hurley entry = nfp_tunnel_add_ipv6_off(app, dst);
650cfa18993SJohn Hurley if (!entry)
651cfa18993SJohn Hurley return -EOPNOTSUPP;
652cfa18993SJohn Hurley
653cfa18993SJohn Hurley nfp_flow->nfp_tun_ipv6 = entry;
65478a722afSJohn Hurley } else {
65578a722afSJohn Hurley __be32 dst;
656e3a6aba0SPieter Jansen van Vuuren
65778a722afSJohn Hurley nfp_flower_compile_ipv4_gre_tun((void *)ext,
65878a722afSJohn Hurley (void *)msk, rule);
65978a722afSJohn Hurley dst = ((struct nfp_flower_ipv4_gre_tun *)ext)->ipv4.dst;
660e3a6aba0SPieter Jansen van Vuuren ext += sizeof(struct nfp_flower_ipv4_gre_tun);
661e3a6aba0SPieter Jansen van Vuuren msk += sizeof(struct nfp_flower_ipv4_gre_tun);
662e3a6aba0SPieter Jansen van Vuuren
663e3a6aba0SPieter Jansen van Vuuren /* Store the tunnel destination in the rule data.
664e3a6aba0SPieter Jansen van Vuuren * This must be present and be an exact match.
665e3a6aba0SPieter Jansen van Vuuren */
66678a722afSJohn Hurley nfp_flow->nfp_tun_ipv4_addr = dst;
66778a722afSJohn Hurley nfp_tunnel_add_ipv4_off(app, dst);
66878a722afSJohn Hurley }
669e3a6aba0SPieter Jansen van Vuuren }
670e3a6aba0SPieter Jansen van Vuuren
671bedeca15SJohn Hurley if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN ||
672bedeca15SJohn Hurley key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) {
67378a722afSJohn Hurley if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
674cfa18993SJohn Hurley struct nfp_flower_ipv6_udp_tun *udp_match;
675cfa18993SJohn Hurley struct nfp_ipv6_addr_entry *entry;
676cfa18993SJohn Hurley struct in6_addr *dst;
677cfa18993SJohn Hurley
67878a722afSJohn Hurley nfp_flower_compile_ipv6_udp_tun((void *)ext,
67978a722afSJohn Hurley (void *)msk, rule);
680cfa18993SJohn Hurley udp_match = (struct nfp_flower_ipv6_udp_tun *)ext;
681cfa18993SJohn Hurley dst = &udp_match->ipv6.dst;
68278a722afSJohn Hurley ext += sizeof(struct nfp_flower_ipv6_udp_tun);
68378a722afSJohn Hurley msk += sizeof(struct nfp_flower_ipv6_udp_tun);
684cfa18993SJohn Hurley
685cfa18993SJohn Hurley entry = nfp_tunnel_add_ipv6_off(app, dst);
686cfa18993SJohn Hurley if (!entry)
687cfa18993SJohn Hurley return -EOPNOTSUPP;
688cfa18993SJohn Hurley
689cfa18993SJohn Hurley nfp_flow->nfp_tun_ipv6 = entry;
69078a722afSJohn Hurley } else {
69178a722afSJohn Hurley __be32 dst;
692574f1e9cSJohn Hurley
69378a722afSJohn Hurley nfp_flower_compile_ipv4_udp_tun((void *)ext,
69478a722afSJohn Hurley (void *)msk, rule);
69578a722afSJohn Hurley dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ipv4.dst;
696bedeca15SJohn Hurley ext += sizeof(struct nfp_flower_ipv4_udp_tun);
697bedeca15SJohn Hurley msk += sizeof(struct nfp_flower_ipv4_udp_tun);
698fd0dd1abSJohn Hurley
6992d9ad71aSJohn Hurley /* Store the tunnel destination in the rule data.
7002d9ad71aSJohn Hurley * This must be present and be an exact match.
7012d9ad71aSJohn Hurley */
70278a722afSJohn Hurley nfp_flow->nfp_tun_ipv4_addr = dst;
70378a722afSJohn Hurley nfp_tunnel_add_ipv4_off(app, dst);
70478a722afSJohn Hurley }
7050a22b17aSPieter Jansen van Vuuren
7060a22b17aSPieter Jansen van Vuuren if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) {
70716416d37SYinjun Zhang nfp_flower_compile_geneve_opt(ext, msk, rule);
7080a22b17aSPieter Jansen van Vuuren }
709611aec10SJohn Hurley }
710611aec10SJohn Hurley
711e4cab45aSLouis Peens /* Check that the flow key does not exceed the maximum limit.
712e4cab45aSLouis Peens * All structures in the key is multiples of 4 bytes, so use u32.
713e4cab45aSLouis Peens */
714e4cab45aSLouis Peens ext_len = (u32 *)ext - (u32 *)nfp_flow->unmasked_data;
715e4cab45aSLouis Peens if (ext_len > NFP_FLOWER_KEY_MAX_LW) {
716e4cab45aSLouis Peens NL_SET_ERR_MSG_MOD(extack,
717e4cab45aSLouis Peens "unsupported offload: flow key too long");
718e4cab45aSLouis Peens return -EOPNOTSUPP;
719e4cab45aSLouis Peens }
720e4cab45aSLouis Peens
7215571e8c9SPieter Jansen van Vuuren return 0;
7225571e8c9SPieter Jansen van Vuuren }
723