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
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)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, bool qinq_sup)
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 (!qinq_sup && 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
nfp_flower_compile_ext_meta(struct nfp_flower_ext_meta * frame,u32 key_ext)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
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)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 int
nfp_flower_compile_mac(struct nfp_flower_mac_mpls * ext,struct nfp_flower_mac_mpls * msk,struct flow_rule * rule,struct netlink_ext_ack * extack)78 nfp_flower_compile_mac(struct nfp_flower_mac_mpls *ext,
79 		       struct nfp_flower_mac_mpls *msk, struct flow_rule *rule,
80 		       struct netlink_ext_ack *extack)
81 {
82 	memset(ext, 0, sizeof(struct nfp_flower_mac_mpls));
83 	memset(msk, 0, sizeof(struct nfp_flower_mac_mpls));
84 
85 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
86 		struct flow_match_eth_addrs match;
87 
88 		flow_rule_match_eth_addrs(rule, &match);
89 		/* Populate mac frame. */
90 		ether_addr_copy(ext->mac_dst, &match.key->dst[0]);
91 		ether_addr_copy(ext->mac_src, &match.key->src[0]);
92 		ether_addr_copy(msk->mac_dst, &match.mask->dst[0]);
93 		ether_addr_copy(msk->mac_src, &match.mask->src[0]);
94 	}
95 
96 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS)) {
97 		struct flow_match_mpls match;
98 		u32 t_mpls;
99 
100 		flow_rule_match_mpls(rule, &match);
101 
102 		/* Only support matching the first LSE */
103 		if (match.mask->used_lses != 1) {
104 			NL_SET_ERR_MSG_MOD(extack,
105 					   "unsupported offload: invalid LSE depth for MPLS match offload");
106 			return -EOPNOTSUPP;
107 		}
108 
109 		t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB,
110 				    match.key->ls[0].mpls_label) |
111 			 FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC,
112 				    match.key->ls[0].mpls_tc) |
113 			 FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS,
114 				    match.key->ls[0].mpls_bos) |
115 			 NFP_FLOWER_MASK_MPLS_Q;
116 		ext->mpls_lse = cpu_to_be32(t_mpls);
117 		t_mpls = FIELD_PREP(NFP_FLOWER_MASK_MPLS_LB,
118 				    match.mask->ls[0].mpls_label) |
119 			 FIELD_PREP(NFP_FLOWER_MASK_MPLS_TC,
120 				    match.mask->ls[0].mpls_tc) |
121 			 FIELD_PREP(NFP_FLOWER_MASK_MPLS_BOS,
122 				    match.mask->ls[0].mpls_bos) |
123 			 NFP_FLOWER_MASK_MPLS_Q;
124 		msk->mpls_lse = cpu_to_be32(t_mpls);
125 	} else if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
126 		/* Check for mpls ether type and set NFP_FLOWER_MASK_MPLS_Q
127 		 * bit, which indicates an mpls ether type but without any
128 		 * mpls fields.
129 		 */
130 		struct flow_match_basic match;
131 
132 		flow_rule_match_basic(rule, &match);
133 		if (match.key->n_proto == cpu_to_be16(ETH_P_MPLS_UC) ||
134 		    match.key->n_proto == cpu_to_be16(ETH_P_MPLS_MC)) {
135 			ext->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
136 			msk->mpls_lse = cpu_to_be32(NFP_FLOWER_MASK_MPLS_Q);
137 		}
138 	}
139 
140 	return 0;
141 }
142 
143 static void
nfp_flower_compile_tport(struct nfp_flower_tp_ports * ext,struct nfp_flower_tp_ports * msk,struct flow_rule * rule)144 nfp_flower_compile_tport(struct nfp_flower_tp_ports *ext,
145 			 struct nfp_flower_tp_ports *msk,
146 			 struct flow_rule *rule)
147 {
148 	memset(ext, 0, sizeof(struct nfp_flower_tp_ports));
149 	memset(msk, 0, sizeof(struct nfp_flower_tp_ports));
150 
151 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
152 		struct flow_match_ports match;
153 
154 		flow_rule_match_ports(rule, &match);
155 		ext->port_src = match.key->src;
156 		ext->port_dst = match.key->dst;
157 		msk->port_src = match.mask->src;
158 		msk->port_dst = match.mask->dst;
159 	}
160 }
161 
162 static void
nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext * ext,struct nfp_flower_ip_ext * msk,struct flow_rule * rule)163 nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext,
164 			  struct nfp_flower_ip_ext *msk, struct flow_rule *rule)
165 {
166 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
167 		struct flow_match_basic match;
168 
169 		flow_rule_match_basic(rule, &match);
170 		ext->proto = match.key->ip_proto;
171 		msk->proto = match.mask->ip_proto;
172 	}
173 
174 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
175 		struct flow_match_ip match;
176 
177 		flow_rule_match_ip(rule, &match);
178 		ext->tos = match.key->tos;
179 		ext->ttl = match.key->ttl;
180 		msk->tos = match.mask->tos;
181 		msk->ttl = match.mask->ttl;
182 	}
183 
184 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
185 		u16 tcp_flags, tcp_flags_mask;
186 		struct flow_match_tcp match;
187 
188 		flow_rule_match_tcp(rule, &match);
189 		tcp_flags = be16_to_cpu(match.key->flags);
190 		tcp_flags_mask = be16_to_cpu(match.mask->flags);
191 
192 		if (tcp_flags & TCPHDR_FIN)
193 			ext->flags |= NFP_FL_TCP_FLAG_FIN;
194 		if (tcp_flags_mask & TCPHDR_FIN)
195 			msk->flags |= NFP_FL_TCP_FLAG_FIN;
196 
197 		if (tcp_flags & TCPHDR_SYN)
198 			ext->flags |= NFP_FL_TCP_FLAG_SYN;
199 		if (tcp_flags_mask & TCPHDR_SYN)
200 			msk->flags |= NFP_FL_TCP_FLAG_SYN;
201 
202 		if (tcp_flags & TCPHDR_RST)
203 			ext->flags |= NFP_FL_TCP_FLAG_RST;
204 		if (tcp_flags_mask & TCPHDR_RST)
205 			msk->flags |= NFP_FL_TCP_FLAG_RST;
206 
207 		if (tcp_flags & TCPHDR_PSH)
208 			ext->flags |= NFP_FL_TCP_FLAG_PSH;
209 		if (tcp_flags_mask & TCPHDR_PSH)
210 			msk->flags |= NFP_FL_TCP_FLAG_PSH;
211 
212 		if (tcp_flags & TCPHDR_URG)
213 			ext->flags |= NFP_FL_TCP_FLAG_URG;
214 		if (tcp_flags_mask & TCPHDR_URG)
215 			msk->flags |= NFP_FL_TCP_FLAG_URG;
216 	}
217 
218 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
219 		struct flow_match_control match;
220 
221 		flow_rule_match_control(rule, &match);
222 		if (match.key->flags & FLOW_DIS_IS_FRAGMENT)
223 			ext->flags |= NFP_FL_IP_FRAGMENTED;
224 		if (match.mask->flags & FLOW_DIS_IS_FRAGMENT)
225 			msk->flags |= NFP_FL_IP_FRAGMENTED;
226 		if (match.key->flags & FLOW_DIS_FIRST_FRAG)
227 			ext->flags |= NFP_FL_IP_FRAG_FIRST;
228 		if (match.mask->flags & FLOW_DIS_FIRST_FRAG)
229 			msk->flags |= NFP_FL_IP_FRAG_FIRST;
230 	}
231 }
232 
233 static void
nfp_flower_fill_vlan(struct flow_dissector_key_vlan * key,struct nfp_flower_vlan * frame,bool outer_vlan)234 nfp_flower_fill_vlan(struct flow_dissector_key_vlan *key,
235 		     struct nfp_flower_vlan *frame,
236 		     bool outer_vlan)
237 {
238 	u16 tci;
239 
240 	tci = NFP_FLOWER_MASK_VLAN_PRESENT;
241 	tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
242 			  key->vlan_priority) |
243 	       FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
244 			  key->vlan_id);
245 
246 	if (outer_vlan) {
247 		frame->outer_tci = cpu_to_be16(tci);
248 		frame->outer_tpid = key->vlan_tpid;
249 	} else {
250 		frame->inner_tci = cpu_to_be16(tci);
251 		frame->inner_tpid = key->vlan_tpid;
252 	}
253 }
254 
255 static void
nfp_flower_compile_vlan(struct nfp_flower_vlan * ext,struct nfp_flower_vlan * msk,struct flow_rule * rule)256 nfp_flower_compile_vlan(struct nfp_flower_vlan *ext,
257 			struct nfp_flower_vlan *msk,
258 			struct flow_rule *rule)
259 {
260 	struct flow_match_vlan match;
261 
262 	memset(ext, 0, sizeof(struct nfp_flower_vlan));
263 	memset(msk, 0, sizeof(struct nfp_flower_vlan));
264 
265 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
266 		flow_rule_match_vlan(rule, &match);
267 		nfp_flower_fill_vlan(match.key, ext, true);
268 		nfp_flower_fill_vlan(match.mask, msk, true);
269 	}
270 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) {
271 		flow_rule_match_cvlan(rule, &match);
272 		nfp_flower_fill_vlan(match.key, ext, false);
273 		nfp_flower_fill_vlan(match.mask, msk, false);
274 	}
275 }
276 
277 static void
nfp_flower_compile_ipv4(struct nfp_flower_ipv4 * ext,struct nfp_flower_ipv4 * msk,struct flow_rule * rule)278 nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext,
279 			struct nfp_flower_ipv4 *msk, struct flow_rule *rule)
280 {
281 	struct flow_match_ipv4_addrs match;
282 
283 	memset(ext, 0, sizeof(struct nfp_flower_ipv4));
284 	memset(msk, 0, sizeof(struct nfp_flower_ipv4));
285 
286 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
287 		flow_rule_match_ipv4_addrs(rule, &match);
288 		ext->ipv4_src = match.key->src;
289 		ext->ipv4_dst = match.key->dst;
290 		msk->ipv4_src = match.mask->src;
291 		msk->ipv4_dst = match.mask->dst;
292 	}
293 
294 	nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
295 }
296 
297 static void
nfp_flower_compile_ipv6(struct nfp_flower_ipv6 * ext,struct nfp_flower_ipv6 * msk,struct flow_rule * rule)298 nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *ext,
299 			struct nfp_flower_ipv6 *msk, struct flow_rule *rule)
300 {
301 	memset(ext, 0, sizeof(struct nfp_flower_ipv6));
302 	memset(msk, 0, sizeof(struct nfp_flower_ipv6));
303 
304 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
305 		struct flow_match_ipv6_addrs match;
306 
307 		flow_rule_match_ipv6_addrs(rule, &match);
308 		ext->ipv6_src = match.key->src;
309 		ext->ipv6_dst = match.key->dst;
310 		msk->ipv6_src = match.mask->src;
311 		msk->ipv6_dst = match.mask->dst;
312 	}
313 
314 	nfp_flower_compile_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
315 }
316 
317 static int
nfp_flower_compile_geneve_opt(void * ext,void * msk,struct flow_rule * rule)318 nfp_flower_compile_geneve_opt(void *ext, void *msk, struct flow_rule *rule)
319 {
320 	struct flow_match_enc_opts match;
321 
322 	flow_rule_match_enc_opts(rule, &match);
323 	memcpy(ext, match.key->data, match.key->len);
324 	memcpy(msk, match.mask->data, match.mask->len);
325 
326 	return 0;
327 }
328 
329 static void
nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 * ext,struct nfp_flower_tun_ipv4 * msk,struct flow_rule * rule)330 nfp_flower_compile_tun_ipv4_addrs(struct nfp_flower_tun_ipv4 *ext,
331 				  struct nfp_flower_tun_ipv4 *msk,
332 				  struct flow_rule *rule)
333 {
334 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS)) {
335 		struct flow_match_ipv4_addrs match;
336 
337 		flow_rule_match_enc_ipv4_addrs(rule, &match);
338 		ext->src = match.key->src;
339 		ext->dst = match.key->dst;
340 		msk->src = match.mask->src;
341 		msk->dst = match.mask->dst;
342 	}
343 }
344 
345 static void
nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 * ext,struct nfp_flower_tun_ipv6 * msk,struct flow_rule * rule)346 nfp_flower_compile_tun_ipv6_addrs(struct nfp_flower_tun_ipv6 *ext,
347 				  struct nfp_flower_tun_ipv6 *msk,
348 				  struct flow_rule *rule)
349 {
350 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS)) {
351 		struct flow_match_ipv6_addrs match;
352 
353 		flow_rule_match_enc_ipv6_addrs(rule, &match);
354 		ext->src = match.key->src;
355 		ext->dst = match.key->dst;
356 		msk->src = match.mask->src;
357 		msk->dst = match.mask->dst;
358 	}
359 }
360 
361 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)362 nfp_flower_compile_tun_ip_ext(struct nfp_flower_tun_ip_ext *ext,
363 			      struct nfp_flower_tun_ip_ext *msk,
364 			      struct flow_rule *rule)
365 {
366 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_IP)) {
367 		struct flow_match_ip match;
368 
369 		flow_rule_match_enc_ip(rule, &match);
370 		ext->tos = match.key->tos;
371 		ext->ttl = match.key->ttl;
372 		msk->tos = match.mask->tos;
373 		msk->ttl = match.mask->ttl;
374 	}
375 }
376 
377 static void
nfp_flower_compile_tun_udp_key(__be32 * key,__be32 * key_msk,struct flow_rule * rule)378 nfp_flower_compile_tun_udp_key(__be32 *key, __be32 *key_msk,
379 			       struct flow_rule *rule)
380 {
381 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
382 		struct flow_match_enc_keyid match;
383 		u32 vni;
384 
385 		flow_rule_match_enc_keyid(rule, &match);
386 		vni = be32_to_cpu(match.key->keyid) << NFP_FL_TUN_VNI_OFFSET;
387 		*key = cpu_to_be32(vni);
388 		vni = be32_to_cpu(match.mask->keyid) << NFP_FL_TUN_VNI_OFFSET;
389 		*key_msk = cpu_to_be32(vni);
390 	}
391 }
392 
393 static void
nfp_flower_compile_tun_gre_key(__be32 * key,__be32 * key_msk,__be16 * flags,__be16 * flags_msk,struct flow_rule * rule)394 nfp_flower_compile_tun_gre_key(__be32 *key, __be32 *key_msk, __be16 *flags,
395 			       __be16 *flags_msk, struct flow_rule *rule)
396 {
397 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
398 		struct flow_match_enc_keyid match;
399 
400 		flow_rule_match_enc_keyid(rule, &match);
401 		*key = match.key->keyid;
402 		*key_msk = match.mask->keyid;
403 
404 		*flags = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
405 		*flags_msk = cpu_to_be16(NFP_FL_GRE_FLAG_KEY);
406 	}
407 }
408 
409 static 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)410 nfp_flower_compile_ipv4_gre_tun(struct nfp_flower_ipv4_gre_tun *ext,
411 				struct nfp_flower_ipv4_gre_tun *msk,
412 				struct flow_rule *rule)
413 {
414 	memset(ext, 0, sizeof(struct nfp_flower_ipv4_gre_tun));
415 	memset(msk, 0, sizeof(struct nfp_flower_ipv4_gre_tun));
416 
417 	/* NVGRE is the only supported GRE tunnel type */
418 	ext->ethertype = cpu_to_be16(ETH_P_TEB);
419 	msk->ethertype = cpu_to_be16(~0);
420 
421 	nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
422 	nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
423 	nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
424 				       &ext->tun_flags, &msk->tun_flags, rule);
425 }
426 
427 static 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)428 nfp_flower_compile_ipv4_udp_tun(struct nfp_flower_ipv4_udp_tun *ext,
429 				struct nfp_flower_ipv4_udp_tun *msk,
430 				struct flow_rule *rule)
431 {
432 	memset(ext, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
433 	memset(msk, 0, sizeof(struct nfp_flower_ipv4_udp_tun));
434 
435 	nfp_flower_compile_tun_ipv4_addrs(&ext->ipv4, &msk->ipv4, rule);
436 	nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
437 	nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
438 }
439 
440 static 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)441 nfp_flower_compile_ipv6_udp_tun(struct nfp_flower_ipv6_udp_tun *ext,
442 				struct nfp_flower_ipv6_udp_tun *msk,
443 				struct flow_rule *rule)
444 {
445 	memset(ext, 0, sizeof(struct nfp_flower_ipv6_udp_tun));
446 	memset(msk, 0, sizeof(struct nfp_flower_ipv6_udp_tun));
447 
448 	nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
449 	nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
450 	nfp_flower_compile_tun_udp_key(&ext->tun_id, &msk->tun_id, rule);
451 }
452 
453 static 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)454 nfp_flower_compile_ipv6_gre_tun(struct nfp_flower_ipv6_gre_tun *ext,
455 				struct nfp_flower_ipv6_gre_tun *msk,
456 				struct flow_rule *rule)
457 {
458 	memset(ext, 0, sizeof(struct nfp_flower_ipv6_gre_tun));
459 	memset(msk, 0, sizeof(struct nfp_flower_ipv6_gre_tun));
460 
461 	/* NVGRE is the only supported GRE tunnel type */
462 	ext->ethertype = cpu_to_be16(ETH_P_TEB);
463 	msk->ethertype = cpu_to_be16(~0);
464 
465 	nfp_flower_compile_tun_ipv6_addrs(&ext->ipv6, &msk->ipv6, rule);
466 	nfp_flower_compile_tun_ip_ext(&ext->ip_ext, &msk->ip_ext, rule);
467 	nfp_flower_compile_tun_gre_key(&ext->tun_key, &msk->tun_key,
468 				       &ext->tun_flags, &msk->tun_flags, rule);
469 }
470 
nfp_flower_compile_flow_match(struct nfp_app * app,struct flow_cls_offload * flow,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)471 int nfp_flower_compile_flow_match(struct nfp_app *app,
472 				  struct flow_cls_offload *flow,
473 				  struct nfp_fl_key_ls *key_ls,
474 				  struct net_device *netdev,
475 				  struct nfp_fl_payload *nfp_flow,
476 				  enum nfp_flower_tun_type tun_type,
477 				  struct netlink_ext_ack *extack)
478 {
479 	struct flow_rule *rule = flow_cls_offload_flow_rule(flow);
480 	struct nfp_flower_priv *priv = app->priv;
481 	bool qinq_sup;
482 	u32 port_id;
483 	int ext_len;
484 	int err;
485 	u8 *ext;
486 	u8 *msk;
487 
488 	port_id = nfp_flower_get_port_id_from_netdev(app, netdev);
489 
490 	memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
491 	memset(nfp_flow->mask_data, 0, key_ls->key_size);
492 
493 	ext = nfp_flow->unmasked_data;
494 	msk = nfp_flow->mask_data;
495 
496 	qinq_sup = !!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ);
497 
498 	nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext,
499 				    (struct nfp_flower_meta_tci *)msk,
500 				    rule, key_ls->key_layer, qinq_sup);
501 	ext += sizeof(struct nfp_flower_meta_tci);
502 	msk += sizeof(struct nfp_flower_meta_tci);
503 
504 	/* Populate Extended Metadata if Required. */
505 	if (NFP_FLOWER_LAYER_EXT_META & key_ls->key_layer) {
506 		nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)ext,
507 					    key_ls->key_layer_two);
508 		nfp_flower_compile_ext_meta((struct nfp_flower_ext_meta *)msk,
509 					    key_ls->key_layer_two);
510 		ext += sizeof(struct nfp_flower_ext_meta);
511 		msk += sizeof(struct nfp_flower_ext_meta);
512 	}
513 
514 	/* Populate Exact Port data. */
515 	err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
516 				      port_id, false, tun_type, extack);
517 	if (err)
518 		return err;
519 
520 	/* Populate Mask Port Data. */
521 	err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
522 				      port_id, true, tun_type, extack);
523 	if (err)
524 		return err;
525 
526 	ext += sizeof(struct nfp_flower_in_port);
527 	msk += sizeof(struct nfp_flower_in_port);
528 
529 	if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) {
530 		err = nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext,
531 					     (struct nfp_flower_mac_mpls *)msk,
532 					     rule, extack);
533 		if (err)
534 			return err;
535 
536 		ext += sizeof(struct nfp_flower_mac_mpls);
537 		msk += sizeof(struct nfp_flower_mac_mpls);
538 	}
539 
540 	if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) {
541 		nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext,
542 					 (struct nfp_flower_tp_ports *)msk,
543 					 rule);
544 		ext += sizeof(struct nfp_flower_tp_ports);
545 		msk += sizeof(struct nfp_flower_tp_ports);
546 	}
547 
548 	if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) {
549 		nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext,
550 					(struct nfp_flower_ipv4 *)msk,
551 					rule);
552 		ext += sizeof(struct nfp_flower_ipv4);
553 		msk += sizeof(struct nfp_flower_ipv4);
554 	}
555 
556 	if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) {
557 		nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext,
558 					(struct nfp_flower_ipv6 *)msk,
559 					rule);
560 		ext += sizeof(struct nfp_flower_ipv6);
561 		msk += sizeof(struct nfp_flower_ipv6);
562 	}
563 
564 	if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GRE) {
565 		if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
566 			struct nfp_flower_ipv6_gre_tun *gre_match;
567 			struct nfp_ipv6_addr_entry *entry;
568 			struct in6_addr *dst;
569 
570 			nfp_flower_compile_ipv6_gre_tun((void *)ext,
571 							(void *)msk, rule);
572 			gre_match = (struct nfp_flower_ipv6_gre_tun *)ext;
573 			dst = &gre_match->ipv6.dst;
574 			ext += sizeof(struct nfp_flower_ipv6_gre_tun);
575 			msk += sizeof(struct nfp_flower_ipv6_gre_tun);
576 
577 			entry = nfp_tunnel_add_ipv6_off(app, dst);
578 			if (!entry)
579 				return -EOPNOTSUPP;
580 
581 			nfp_flow->nfp_tun_ipv6 = entry;
582 		} else {
583 			__be32 dst;
584 
585 			nfp_flower_compile_ipv4_gre_tun((void *)ext,
586 							(void *)msk, rule);
587 			dst = ((struct nfp_flower_ipv4_gre_tun *)ext)->ipv4.dst;
588 			ext += sizeof(struct nfp_flower_ipv4_gre_tun);
589 			msk += sizeof(struct nfp_flower_ipv4_gre_tun);
590 
591 			/* Store the tunnel destination in the rule data.
592 			 * This must be present and be an exact match.
593 			 */
594 			nfp_flow->nfp_tun_ipv4_addr = dst;
595 			nfp_tunnel_add_ipv4_off(app, dst);
596 		}
597 	}
598 
599 	if (NFP_FLOWER_LAYER2_QINQ & key_ls->key_layer_two) {
600 		nfp_flower_compile_vlan((struct nfp_flower_vlan *)ext,
601 					(struct nfp_flower_vlan *)msk,
602 					rule);
603 		ext += sizeof(struct nfp_flower_vlan);
604 		msk += sizeof(struct nfp_flower_vlan);
605 	}
606 
607 	if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN ||
608 	    key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) {
609 		if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) {
610 			struct nfp_flower_ipv6_udp_tun *udp_match;
611 			struct nfp_ipv6_addr_entry *entry;
612 			struct in6_addr *dst;
613 
614 			nfp_flower_compile_ipv6_udp_tun((void *)ext,
615 							(void *)msk, rule);
616 			udp_match = (struct nfp_flower_ipv6_udp_tun *)ext;
617 			dst = &udp_match->ipv6.dst;
618 			ext += sizeof(struct nfp_flower_ipv6_udp_tun);
619 			msk += sizeof(struct nfp_flower_ipv6_udp_tun);
620 
621 			entry = nfp_tunnel_add_ipv6_off(app, dst);
622 			if (!entry)
623 				return -EOPNOTSUPP;
624 
625 			nfp_flow->nfp_tun_ipv6 = entry;
626 		} else {
627 			__be32 dst;
628 
629 			nfp_flower_compile_ipv4_udp_tun((void *)ext,
630 							(void *)msk, rule);
631 			dst = ((struct nfp_flower_ipv4_udp_tun *)ext)->ipv4.dst;
632 			ext += sizeof(struct nfp_flower_ipv4_udp_tun);
633 			msk += sizeof(struct nfp_flower_ipv4_udp_tun);
634 
635 			/* Store the tunnel destination in the rule data.
636 			 * This must be present and be an exact match.
637 			 */
638 			nfp_flow->nfp_tun_ipv4_addr = dst;
639 			nfp_tunnel_add_ipv4_off(app, dst);
640 		}
641 
642 		if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE_OP) {
643 			err = nfp_flower_compile_geneve_opt(ext, msk, rule);
644 			if (err)
645 				return err;
646 		}
647 	}
648 
649 	/* Check that the flow key does not exceed the maximum limit.
650 	 * All structures in the key is multiples of 4 bytes, so use u32.
651 	 */
652 	ext_len = (u32 *)ext - (u32 *)nfp_flow->unmasked_data;
653 	if (ext_len > NFP_FLOWER_KEY_MAX_LW) {
654 		NL_SET_ERR_MSG_MOD(extack,
655 				   "unsupported offload: flow key too long");
656 		return -EOPNOTSUPP;
657 	}
658 
659 	return 0;
660 }
661