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