• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3 
4 #include <linux/etherdevice.h>
5 #include <linux/inetdevice.h>
6 #include <net/netevent.h>
7 #include <linux/idr.h>
8 #include <net/dst_metadata.h>
9 #include <net/arp.h>
10 
11 #include "cmsg.h"
12 #include "main.h"
13 #include "../nfp_net_repr.h"
14 #include "../nfp_net.h"
15 
16 #define NFP_FL_MAX_ROUTES               32
17 
18 #define NFP_TUN_PRE_TUN_RULE_LIMIT	32
19 #define NFP_TUN_PRE_TUN_RULE_DEL	BIT(0)
20 #define NFP_TUN_PRE_TUN_IDX_BIT		BIT(3)
21 #define NFP_TUN_PRE_TUN_IPV6_BIT	BIT(7)
22 
23 /**
24  * struct nfp_tun_pre_tun_rule - rule matched before decap
25  * @flags:		options for the rule offset
26  * @port_idx:		index of destination MAC address for the rule
27  * @vlan_tci:		VLAN info associated with MAC
28  * @host_ctx_id:	stats context of rule to update
29  */
30 struct nfp_tun_pre_tun_rule {
31 	__be32 flags;
32 	__be16 port_idx;
33 	__be16 vlan_tci;
34 	__be32 host_ctx_id;
35 };
36 
37 /**
38  * struct nfp_tun_active_tuns - periodic message of active tunnels
39  * @seq:		sequence number of the message
40  * @count:		number of tunnels report in message
41  * @flags:		options part of the request
42  * @tun_info.ipv4:		dest IPv4 address of active route
43  * @tun_info.egress_port:	port the encapsulated packet egressed
44  * @tun_info.extra:		reserved for future use
45  * @tun_info:		tunnels that have sent traffic in reported period
46  */
47 struct nfp_tun_active_tuns {
48 	__be32 seq;
49 	__be32 count;
50 	__be32 flags;
51 	struct route_ip_info {
52 		__be32 ipv4;
53 		__be32 egress_port;
54 		__be32 extra[2];
55 	} tun_info[];
56 };
57 
58 /**
59  * struct nfp_tun_active_tuns_v6 - periodic message of active IPv6 tunnels
60  * @seq:		sequence number of the message
61  * @count:		number of tunnels report in message
62  * @flags:		options part of the request
63  * @tun_info.ipv6:		dest IPv6 address of active route
64  * @tun_info.egress_port:	port the encapsulated packet egressed
65  * @tun_info.extra:		reserved for future use
66  * @tun_info:		tunnels that have sent traffic in reported period
67  */
68 struct nfp_tun_active_tuns_v6 {
69 	__be32 seq;
70 	__be32 count;
71 	__be32 flags;
72 	struct route_ip_info_v6 {
73 		struct in6_addr ipv6;
74 		__be32 egress_port;
75 		__be32 extra[2];
76 	} tun_info[];
77 };
78 
79 /**
80  * struct nfp_tun_req_route_ipv4 - NFP requests a route/neighbour lookup
81  * @ingress_port:	ingress port of packet that signalled request
82  * @ipv4_addr:		destination ipv4 address for route
83  * @reserved:		reserved for future use
84  */
85 struct nfp_tun_req_route_ipv4 {
86 	__be32 ingress_port;
87 	__be32 ipv4_addr;
88 	__be32 reserved[2];
89 };
90 
91 /**
92  * struct nfp_tun_req_route_ipv6 - NFP requests an IPv6 route/neighbour lookup
93  * @ingress_port:	ingress port of packet that signalled request
94  * @ipv6_addr:		destination ipv6 address for route
95  */
96 struct nfp_tun_req_route_ipv6 {
97 	__be32 ingress_port;
98 	struct in6_addr ipv6_addr;
99 };
100 
101 /**
102  * struct nfp_offloaded_route - routes that are offloaded to the NFP
103  * @list:	list pointer
104  * @ip_add:	destination of route - can be IPv4 or IPv6
105  */
106 struct nfp_offloaded_route {
107 	struct list_head list;
108 	u8 ip_add[];
109 };
110 
111 #define NFP_FL_IPV4_ADDRS_MAX        32
112 
113 /**
114  * struct nfp_tun_ipv4_addr - set the IP address list on the NFP
115  * @count:	number of IPs populated in the array
116  * @ipv4_addr:	array of IPV4_ADDRS_MAX 32 bit IPv4 addresses
117  */
118 struct nfp_tun_ipv4_addr {
119 	__be32 count;
120 	__be32 ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
121 };
122 
123 /**
124  * struct nfp_ipv4_addr_entry - cached IPv4 addresses
125  * @ipv4_addr:	IP address
126  * @ref_count:	number of rules currently using this IP
127  * @list:	list pointer
128  */
129 struct nfp_ipv4_addr_entry {
130 	__be32 ipv4_addr;
131 	int ref_count;
132 	struct list_head list;
133 };
134 
135 #define NFP_FL_IPV6_ADDRS_MAX        4
136 
137 /**
138  * struct nfp_tun_ipv6_addr - set the IP address list on the NFP
139  * @count:	number of IPs populated in the array
140  * @ipv6_addr:	array of IPV6_ADDRS_MAX 128 bit IPv6 addresses
141  */
142 struct nfp_tun_ipv6_addr {
143 	__be32 count;
144 	struct in6_addr ipv6_addr[NFP_FL_IPV6_ADDRS_MAX];
145 };
146 
147 #define NFP_TUN_MAC_OFFLOAD_DEL_FLAG	0x2
148 
149 /**
150  * struct nfp_tun_mac_addr_offload - configure MAC address of tunnel EP on NFP
151  * @flags:	MAC address offload options
152  * @count:	number of MAC addresses in the message (should be 1)
153  * @index:	index of MAC address in the lookup table
154  * @addr:	interface MAC address
155  */
156 struct nfp_tun_mac_addr_offload {
157 	__be16 flags;
158 	__be16 count;
159 	__be16 index;
160 	u8 addr[ETH_ALEN];
161 };
162 
163 /**
164  * struct nfp_neigh_update_work - update neighbour information to nfp
165  * @work:	Work queue for writing neigh to the nfp
166  * @n:		neighbour entry
167  * @app:	Back pointer to app
168  */
169 struct nfp_neigh_update_work {
170 	struct work_struct work;
171 	struct neighbour *n;
172 	struct nfp_app *app;
173 };
174 
175 enum nfp_flower_mac_offload_cmd {
176 	NFP_TUNNEL_MAC_OFFLOAD_ADD =		0,
177 	NFP_TUNNEL_MAC_OFFLOAD_DEL =		1,
178 	NFP_TUNNEL_MAC_OFFLOAD_MOD =		2,
179 };
180 
181 #define NFP_MAX_MAC_INDEX       0xff
182 
183 /**
184  * struct nfp_tun_offloaded_mac - hashtable entry for an offloaded MAC
185  * @ht_node:		Hashtable entry
186  * @addr:		Offloaded MAC address
187  * @index:		Offloaded index for given MAC address
188  * @ref_count:		Number of devs using this MAC address
189  * @repr_list:		List of reprs sharing this MAC address
190  * @bridge_count:	Number of bridge/internal devs with MAC
191  */
192 struct nfp_tun_offloaded_mac {
193 	struct rhash_head ht_node;
194 	u8 addr[ETH_ALEN];
195 	u16 index;
196 	int ref_count;
197 	struct list_head repr_list;
198 	int bridge_count;
199 };
200 
201 static const struct rhashtable_params offloaded_macs_params = {
202 	.key_offset	= offsetof(struct nfp_tun_offloaded_mac, addr),
203 	.head_offset	= offsetof(struct nfp_tun_offloaded_mac, ht_node),
204 	.key_len	= ETH_ALEN,
205 	.automatic_shrinking	= true,
206 };
207 
nfp_tunnel_keep_alive(struct nfp_app * app,struct sk_buff * skb)208 void nfp_tunnel_keep_alive(struct nfp_app *app, struct sk_buff *skb)
209 {
210 	struct nfp_tun_active_tuns *payload;
211 	struct net_device *netdev;
212 	int count, i, pay_len;
213 	struct neighbour *n;
214 	__be32 ipv4_addr;
215 	u32 port;
216 
217 	payload = nfp_flower_cmsg_get_data(skb);
218 	count = be32_to_cpu(payload->count);
219 	if (count > NFP_FL_MAX_ROUTES) {
220 		nfp_flower_cmsg_warn(app, "Tunnel keep-alive request exceeds max routes.\n");
221 		return;
222 	}
223 
224 	pay_len = nfp_flower_cmsg_get_data_len(skb);
225 	if (pay_len != struct_size(payload, tun_info, count)) {
226 		nfp_flower_cmsg_warn(app, "Corruption in tunnel keep-alive message.\n");
227 		return;
228 	}
229 
230 	rcu_read_lock();
231 	for (i = 0; i < count; i++) {
232 		ipv4_addr = payload->tun_info[i].ipv4;
233 		port = be32_to_cpu(payload->tun_info[i].egress_port);
234 		netdev = nfp_app_dev_get(app, port, NULL);
235 		if (!netdev)
236 			continue;
237 
238 		n = neigh_lookup(&arp_tbl, &ipv4_addr, netdev);
239 		if (!n)
240 			continue;
241 
242 		/* Update the used timestamp of neighbour */
243 		neigh_event_send(n, NULL);
244 		neigh_release(n);
245 	}
246 	rcu_read_unlock();
247 }
248 
nfp_tunnel_keep_alive_v6(struct nfp_app * app,struct sk_buff * skb)249 void nfp_tunnel_keep_alive_v6(struct nfp_app *app, struct sk_buff *skb)
250 {
251 #if IS_ENABLED(CONFIG_IPV6)
252 	struct nfp_tun_active_tuns_v6 *payload;
253 	struct net_device *netdev;
254 	int count, i, pay_len;
255 	struct neighbour *n;
256 	void *ipv6_add;
257 	u32 port;
258 
259 	payload = nfp_flower_cmsg_get_data(skb);
260 	count = be32_to_cpu(payload->count);
261 	if (count > NFP_FL_IPV6_ADDRS_MAX) {
262 		nfp_flower_cmsg_warn(app, "IPv6 tunnel keep-alive request exceeds max routes.\n");
263 		return;
264 	}
265 
266 	pay_len = nfp_flower_cmsg_get_data_len(skb);
267 	if (pay_len != struct_size(payload, tun_info, count)) {
268 		nfp_flower_cmsg_warn(app, "Corruption in tunnel keep-alive message.\n");
269 		return;
270 	}
271 
272 	rcu_read_lock();
273 	for (i = 0; i < count; i++) {
274 		ipv6_add = &payload->tun_info[i].ipv6;
275 		port = be32_to_cpu(payload->tun_info[i].egress_port);
276 		netdev = nfp_app_dev_get(app, port, NULL);
277 		if (!netdev)
278 			continue;
279 
280 		n = neigh_lookup(&nd_tbl, ipv6_add, netdev);
281 		if (!n)
282 			continue;
283 
284 		/* Update the used timestamp of neighbour */
285 		neigh_event_send(n, NULL);
286 		neigh_release(n);
287 	}
288 	rcu_read_unlock();
289 #endif
290 }
291 
292 static int
nfp_flower_xmit_tun_conf(struct nfp_app * app,u8 mtype,u16 plen,void * pdata,gfp_t flag)293 nfp_flower_xmit_tun_conf(struct nfp_app *app, u8 mtype, u16 plen, void *pdata,
294 			 gfp_t flag)
295 {
296 	struct nfp_flower_priv *priv = app->priv;
297 	struct sk_buff *skb;
298 	unsigned char *msg;
299 
300 	if (!(priv->flower_ext_feats & NFP_FL_FEATS_DECAP_V2) &&
301 	    (mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH ||
302 	     mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6))
303 		plen -= sizeof(struct nfp_tun_neigh_ext);
304 
305 	if (!(priv->flower_ext_feats & NFP_FL_FEATS_TUNNEL_NEIGH_LAG) &&
306 	    (mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH ||
307 	     mtype == NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6))
308 		plen -= sizeof(struct nfp_tun_neigh_lag);
309 
310 	skb = nfp_flower_cmsg_alloc(app, plen, mtype, flag);
311 	if (!skb)
312 		return -ENOMEM;
313 
314 	msg = nfp_flower_cmsg_get_data(skb);
315 	memcpy(msg, pdata, nfp_flower_cmsg_get_data_len(skb));
316 
317 	nfp_ctrl_tx(app->ctrl, skb);
318 	return 0;
319 }
320 
321 static void
nfp_tun_mutual_link(struct nfp_predt_entry * predt,struct nfp_neigh_entry * neigh)322 nfp_tun_mutual_link(struct nfp_predt_entry *predt,
323 		    struct nfp_neigh_entry *neigh)
324 {
325 	struct nfp_fl_payload *flow_pay = predt->flow_pay;
326 	struct nfp_tun_neigh_ext *ext;
327 	struct nfp_tun_neigh *common;
328 
329 	if (flow_pay->pre_tun_rule.is_ipv6 != neigh->is_ipv6)
330 		return;
331 
332 	/* In the case of bonding it is possible that there might already
333 	 * be a flow linked (as the MAC address gets shared). If a flow
334 	 * is already linked just return.
335 	 */
336 	if (neigh->flow)
337 		return;
338 
339 	common = neigh->is_ipv6 ?
340 		 &((struct nfp_tun_neigh_v6 *)neigh->payload)->common :
341 		 &((struct nfp_tun_neigh_v4 *)neigh->payload)->common;
342 	ext = neigh->is_ipv6 ?
343 		 &((struct nfp_tun_neigh_v6 *)neigh->payload)->ext :
344 		 &((struct nfp_tun_neigh_v4 *)neigh->payload)->ext;
345 
346 	if (memcmp(flow_pay->pre_tun_rule.loc_mac,
347 		   common->src_addr, ETH_ALEN) ||
348 	    memcmp(flow_pay->pre_tun_rule.rem_mac,
349 		   common->dst_addr, ETH_ALEN))
350 		return;
351 
352 	list_add(&neigh->list_head, &predt->nn_list);
353 	neigh->flow = predt;
354 	ext->host_ctx = flow_pay->meta.host_ctx_id;
355 	ext->vlan_tci = flow_pay->pre_tun_rule.vlan_tci;
356 	ext->vlan_tpid = flow_pay->pre_tun_rule.vlan_tpid;
357 }
358 
359 static void
nfp_tun_link_predt_entries(struct nfp_app * app,struct nfp_neigh_entry * nn_entry)360 nfp_tun_link_predt_entries(struct nfp_app *app,
361 			   struct nfp_neigh_entry *nn_entry)
362 {
363 	struct nfp_flower_priv *priv = app->priv;
364 	struct nfp_predt_entry *predt, *tmp;
365 
366 	list_for_each_entry_safe(predt, tmp, &priv->predt_list, list_head) {
367 		nfp_tun_mutual_link(predt, nn_entry);
368 	}
369 }
370 
nfp_tun_link_and_update_nn_entries(struct nfp_app * app,struct nfp_predt_entry * predt)371 void nfp_tun_link_and_update_nn_entries(struct nfp_app *app,
372 					struct nfp_predt_entry *predt)
373 {
374 	struct nfp_flower_priv *priv = app->priv;
375 	struct nfp_neigh_entry *nn_entry;
376 	struct rhashtable_iter iter;
377 	size_t neigh_size;
378 	u8 type;
379 
380 	rhashtable_walk_enter(&priv->neigh_table, &iter);
381 	rhashtable_walk_start(&iter);
382 	while ((nn_entry = rhashtable_walk_next(&iter)) != NULL) {
383 		if (IS_ERR(nn_entry))
384 			continue;
385 		nfp_tun_mutual_link(predt, nn_entry);
386 		neigh_size = nn_entry->is_ipv6 ?
387 			     sizeof(struct nfp_tun_neigh_v6) :
388 			     sizeof(struct nfp_tun_neigh_v4);
389 		type = nn_entry->is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 :
390 					   NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
391 		nfp_flower_xmit_tun_conf(app, type, neigh_size,
392 					 nn_entry->payload,
393 					 GFP_ATOMIC);
394 	}
395 	rhashtable_walk_stop(&iter);
396 	rhashtable_walk_exit(&iter);
397 }
398 
nfp_tun_cleanup_nn_entries(struct nfp_app * app)399 static void nfp_tun_cleanup_nn_entries(struct nfp_app *app)
400 {
401 	struct nfp_flower_priv *priv = app->priv;
402 	struct nfp_neigh_entry *neigh;
403 	struct nfp_tun_neigh_ext *ext;
404 	struct rhashtable_iter iter;
405 	size_t neigh_size;
406 	u8 type;
407 
408 	rhashtable_walk_enter(&priv->neigh_table, &iter);
409 	rhashtable_walk_start(&iter);
410 	while ((neigh = rhashtable_walk_next(&iter)) != NULL) {
411 		if (IS_ERR(neigh))
412 			continue;
413 		ext = neigh->is_ipv6 ?
414 			 &((struct nfp_tun_neigh_v6 *)neigh->payload)->ext :
415 			 &((struct nfp_tun_neigh_v4 *)neigh->payload)->ext;
416 		ext->host_ctx = cpu_to_be32(U32_MAX);
417 		ext->vlan_tpid = cpu_to_be16(U16_MAX);
418 		ext->vlan_tci = cpu_to_be16(U16_MAX);
419 
420 		neigh_size = neigh->is_ipv6 ?
421 			     sizeof(struct nfp_tun_neigh_v6) :
422 			     sizeof(struct nfp_tun_neigh_v4);
423 		type = neigh->is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 :
424 					   NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
425 		nfp_flower_xmit_tun_conf(app, type, neigh_size, neigh->payload,
426 					 GFP_ATOMIC);
427 
428 		rhashtable_remove_fast(&priv->neigh_table, &neigh->ht_node,
429 				       neigh_table_params);
430 		if (neigh->flow)
431 			list_del(&neigh->list_head);
432 		kfree(neigh);
433 	}
434 	rhashtable_walk_stop(&iter);
435 	rhashtable_walk_exit(&iter);
436 }
437 
nfp_tun_unlink_and_update_nn_entries(struct nfp_app * app,struct nfp_predt_entry * predt)438 void nfp_tun_unlink_and_update_nn_entries(struct nfp_app *app,
439 					  struct nfp_predt_entry *predt)
440 {
441 	struct nfp_neigh_entry *neigh, *tmp;
442 	struct nfp_tun_neigh_ext *ext;
443 	size_t neigh_size;
444 	u8 type;
445 
446 	list_for_each_entry_safe(neigh, tmp, &predt->nn_list, list_head) {
447 		ext = neigh->is_ipv6 ?
448 			 &((struct nfp_tun_neigh_v6 *)neigh->payload)->ext :
449 			 &((struct nfp_tun_neigh_v4 *)neigh->payload)->ext;
450 		neigh->flow = NULL;
451 		ext->host_ctx = cpu_to_be32(U32_MAX);
452 		ext->vlan_tpid = cpu_to_be16(U16_MAX);
453 		ext->vlan_tci = cpu_to_be16(U16_MAX);
454 		list_del(&neigh->list_head);
455 		neigh_size = neigh->is_ipv6 ?
456 			     sizeof(struct nfp_tun_neigh_v6) :
457 			     sizeof(struct nfp_tun_neigh_v4);
458 		type = neigh->is_ipv6 ? NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6 :
459 					   NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
460 		nfp_flower_xmit_tun_conf(app, type, neigh_size, neigh->payload,
461 					 GFP_ATOMIC);
462 	}
463 }
464 
465 static void
nfp_tun_write_neigh(struct net_device * netdev,struct nfp_app * app,void * flow,struct neighbour * neigh,bool is_ipv6,bool override)466 nfp_tun_write_neigh(struct net_device *netdev, struct nfp_app *app,
467 		    void *flow, struct neighbour *neigh, bool is_ipv6,
468 		    bool override)
469 {
470 	bool neigh_invalid = !(neigh->nud_state & NUD_VALID) || neigh->dead;
471 	size_t neigh_size = is_ipv6 ? sizeof(struct nfp_tun_neigh_v6) :
472 			    sizeof(struct nfp_tun_neigh_v4);
473 	unsigned long cookie = (unsigned long)neigh;
474 	struct nfp_flower_priv *priv = app->priv;
475 	struct nfp_tun_neigh_lag lag_info;
476 	struct nfp_neigh_entry *nn_entry;
477 	u32 port_id;
478 	u8 mtype;
479 
480 	port_id = nfp_flower_get_port_id_from_netdev(app, netdev);
481 	if (!port_id)
482 		return;
483 
484 	if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT) {
485 		memset(&lag_info, 0, sizeof(struct nfp_tun_neigh_lag));
486 		nfp_flower_lag_get_info_from_netdev(app, netdev, &lag_info);
487 	}
488 
489 	spin_lock_bh(&priv->predt_lock);
490 	nn_entry = rhashtable_lookup_fast(&priv->neigh_table, &cookie,
491 					  neigh_table_params);
492 	if (!nn_entry && !neigh_invalid) {
493 		struct nfp_tun_neigh_ext *ext;
494 		struct nfp_tun_neigh_lag *lag;
495 		struct nfp_tun_neigh *common;
496 
497 		nn_entry = kzalloc(sizeof(*nn_entry) + neigh_size,
498 				   GFP_ATOMIC);
499 		if (!nn_entry)
500 			goto err;
501 
502 		nn_entry->payload = (char *)&nn_entry[1];
503 		nn_entry->neigh_cookie = cookie;
504 		nn_entry->is_ipv6 = is_ipv6;
505 		nn_entry->flow = NULL;
506 		if (is_ipv6) {
507 			struct flowi6 *flowi6 = (struct flowi6 *)flow;
508 			struct nfp_tun_neigh_v6 *payload;
509 
510 			payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload;
511 			payload->src_ipv6 = flowi6->saddr;
512 			payload->dst_ipv6 = flowi6->daddr;
513 			common = &payload->common;
514 			ext = &payload->ext;
515 			lag = &payload->lag;
516 			mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6;
517 		} else {
518 			struct flowi4 *flowi4 = (struct flowi4 *)flow;
519 			struct nfp_tun_neigh_v4 *payload;
520 
521 			payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload;
522 			payload->src_ipv4 = flowi4->saddr;
523 			payload->dst_ipv4 = flowi4->daddr;
524 			common = &payload->common;
525 			ext = &payload->ext;
526 			lag = &payload->lag;
527 			mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
528 		}
529 		ext->host_ctx = cpu_to_be32(U32_MAX);
530 		ext->vlan_tpid = cpu_to_be16(U16_MAX);
531 		ext->vlan_tci = cpu_to_be16(U16_MAX);
532 		ether_addr_copy(common->src_addr, netdev->dev_addr);
533 		neigh_ha_snapshot(common->dst_addr, neigh, netdev);
534 
535 		if ((port_id & NFP_FL_LAG_OUT) == NFP_FL_LAG_OUT)
536 			memcpy(lag, &lag_info, sizeof(struct nfp_tun_neigh_lag));
537 		common->port_id = cpu_to_be32(port_id);
538 
539 		if (rhashtable_insert_fast(&priv->neigh_table,
540 					   &nn_entry->ht_node,
541 					   neigh_table_params))
542 			goto err;
543 
544 		nfp_tun_link_predt_entries(app, nn_entry);
545 		nfp_flower_xmit_tun_conf(app, mtype, neigh_size,
546 					 nn_entry->payload,
547 					 GFP_ATOMIC);
548 	} else if (nn_entry && neigh_invalid) {
549 		if (is_ipv6) {
550 			struct flowi6 *flowi6 = (struct flowi6 *)flow;
551 			struct nfp_tun_neigh_v6 *payload;
552 
553 			payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload;
554 			memset(payload, 0, sizeof(struct nfp_tun_neigh_v6));
555 			payload->dst_ipv6 = flowi6->daddr;
556 			mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6;
557 		} else {
558 			struct flowi4 *flowi4 = (struct flowi4 *)flow;
559 			struct nfp_tun_neigh_v4 *payload;
560 
561 			payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload;
562 			memset(payload, 0, sizeof(struct nfp_tun_neigh_v4));
563 			payload->dst_ipv4 = flowi4->daddr;
564 			mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
565 		}
566 		/* Trigger ARP to verify invalid neighbour state. */
567 		neigh_event_send(neigh, NULL);
568 		rhashtable_remove_fast(&priv->neigh_table,
569 				       &nn_entry->ht_node,
570 				       neigh_table_params);
571 
572 		nfp_flower_xmit_tun_conf(app, mtype, neigh_size,
573 					 nn_entry->payload,
574 					 GFP_ATOMIC);
575 
576 		if (nn_entry->flow)
577 			list_del(&nn_entry->list_head);
578 		kfree(nn_entry);
579 	} else if (nn_entry && !neigh_invalid) {
580 		struct nfp_tun_neigh *common;
581 		u8 dst_addr[ETH_ALEN];
582 		bool is_mac_change;
583 
584 		if (is_ipv6) {
585 			struct nfp_tun_neigh_v6 *payload;
586 
587 			payload = (struct nfp_tun_neigh_v6 *)nn_entry->payload;
588 			common = &payload->common;
589 			mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6;
590 		} else {
591 			struct nfp_tun_neigh_v4 *payload;
592 
593 			payload = (struct nfp_tun_neigh_v4 *)nn_entry->payload;
594 			common = &payload->common;
595 			mtype = NFP_FLOWER_CMSG_TYPE_TUN_NEIGH;
596 		}
597 
598 		ether_addr_copy(dst_addr, common->dst_addr);
599 		neigh_ha_snapshot(common->dst_addr, neigh, netdev);
600 		is_mac_change = !ether_addr_equal(dst_addr, common->dst_addr);
601 		if (override || is_mac_change) {
602 			if (is_mac_change && nn_entry->flow) {
603 				list_del(&nn_entry->list_head);
604 				nn_entry->flow = NULL;
605 			}
606 			nfp_tun_link_predt_entries(app, nn_entry);
607 			nfp_flower_xmit_tun_conf(app, mtype, neigh_size,
608 						 nn_entry->payload,
609 						 GFP_ATOMIC);
610 		}
611 	}
612 
613 	spin_unlock_bh(&priv->predt_lock);
614 	return;
615 
616 err:
617 	kfree(nn_entry);
618 	spin_unlock_bh(&priv->predt_lock);
619 	nfp_flower_cmsg_warn(app, "Neighbour configuration failed.\n");
620 }
621 
622 static void
nfp_tun_release_neigh_update_work(struct nfp_neigh_update_work * update_work)623 nfp_tun_release_neigh_update_work(struct nfp_neigh_update_work *update_work)
624 {
625 	neigh_release(update_work->n);
626 	kfree(update_work);
627 }
628 
nfp_tun_neigh_update(struct work_struct * work)629 static void nfp_tun_neigh_update(struct work_struct *work)
630 {
631 	struct nfp_neigh_update_work *update_work;
632 	struct nfp_app *app;
633 	struct neighbour *n;
634 	bool neigh_invalid;
635 	int err;
636 
637 	update_work = container_of(work, struct nfp_neigh_update_work, work);
638 	app = update_work->app;
639 	n = update_work->n;
640 
641 	if (!nfp_flower_get_port_id_from_netdev(app, n->dev))
642 		goto out;
643 
644 #if IS_ENABLED(CONFIG_INET)
645 	neigh_invalid = !(n->nud_state & NUD_VALID) || n->dead;
646 	if (n->tbl->family == AF_INET6) {
647 #if IS_ENABLED(CONFIG_IPV6)
648 		struct flowi6 flow6 = {};
649 
650 		flow6.daddr = *(struct in6_addr *)n->primary_key;
651 		if (!neigh_invalid) {
652 			struct dst_entry *dst;
653 			/* Use ipv6_dst_lookup_flow to populate flow6->saddr
654 			 * and other fields. This information is only needed
655 			 * for new entries, lookup can be skipped when an entry
656 			 * gets invalidated - as only the daddr is needed for
657 			 * deleting.
658 			 */
659 			dst = ip6_dst_lookup_flow(dev_net(n->dev), NULL,
660 						  &flow6, NULL);
661 			if (IS_ERR(dst))
662 				goto out;
663 
664 			dst_release(dst);
665 		}
666 		nfp_tun_write_neigh(n->dev, app, &flow6, n, true, false);
667 #endif /* CONFIG_IPV6 */
668 	} else {
669 		struct flowi4 flow4 = {};
670 
671 		flow4.daddr = *(__be32 *)n->primary_key;
672 		if (!neigh_invalid) {
673 			struct rtable *rt;
674 			/* Use ip_route_output_key to populate flow4->saddr and
675 			 * other fields. This information is only needed for
676 			 * new entries, lookup can be skipped when an entry
677 			 * gets invalidated - as only the daddr is needed for
678 			 * deleting.
679 			 */
680 			rt = ip_route_output_key(dev_net(n->dev), &flow4);
681 			err = PTR_ERR_OR_ZERO(rt);
682 			if (err)
683 				goto out;
684 
685 			ip_rt_put(rt);
686 		}
687 		nfp_tun_write_neigh(n->dev, app, &flow4, n, false, false);
688 	}
689 #endif /* CONFIG_INET */
690 out:
691 	nfp_tun_release_neigh_update_work(update_work);
692 }
693 
694 static struct nfp_neigh_update_work *
nfp_tun_alloc_neigh_update_work(struct nfp_app * app,struct neighbour * n)695 nfp_tun_alloc_neigh_update_work(struct nfp_app *app, struct neighbour *n)
696 {
697 	struct nfp_neigh_update_work *update_work;
698 
699 	update_work = kzalloc(sizeof(*update_work), GFP_ATOMIC);
700 	if (!update_work)
701 		return NULL;
702 
703 	INIT_WORK(&update_work->work, nfp_tun_neigh_update);
704 	neigh_hold(n);
705 	update_work->n = n;
706 	update_work->app = app;
707 
708 	return update_work;
709 }
710 
711 static int
nfp_tun_neigh_event_handler(struct notifier_block * nb,unsigned long event,void * ptr)712 nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
713 			    void *ptr)
714 {
715 	struct nfp_neigh_update_work *update_work;
716 	struct nfp_flower_priv *app_priv;
717 	struct netevent_redirect *redir;
718 	struct neighbour *n;
719 	struct nfp_app *app;
720 
721 	switch (event) {
722 	case NETEVENT_REDIRECT:
723 		redir = (struct netevent_redirect *)ptr;
724 		n = redir->neigh;
725 		break;
726 	case NETEVENT_NEIGH_UPDATE:
727 		n = (struct neighbour *)ptr;
728 		break;
729 	default:
730 		return NOTIFY_DONE;
731 	}
732 #if IS_ENABLED(CONFIG_IPV6)
733 	if (n->tbl != ipv6_stub->nd_tbl && n->tbl != &arp_tbl)
734 #else
735 	if (n->tbl != &arp_tbl)
736 #endif
737 		return NOTIFY_DONE;
738 
739 	app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
740 	app = app_priv->app;
741 	update_work = nfp_tun_alloc_neigh_update_work(app, n);
742 	if (!update_work)
743 		return NOTIFY_DONE;
744 
745 	queue_work(system_highpri_wq, &update_work->work);
746 
747 	return NOTIFY_DONE;
748 }
749 
nfp_tunnel_request_route_v4(struct nfp_app * app,struct sk_buff * skb)750 void nfp_tunnel_request_route_v4(struct nfp_app *app, struct sk_buff *skb)
751 {
752 	struct nfp_tun_req_route_ipv4 *payload;
753 	struct net_device *netdev;
754 	struct flowi4 flow = {};
755 	struct neighbour *n;
756 	struct rtable *rt;
757 	int err;
758 
759 	payload = nfp_flower_cmsg_get_data(skb);
760 
761 	rcu_read_lock();
762 	netdev = nfp_app_dev_get(app, be32_to_cpu(payload->ingress_port), NULL);
763 	if (!netdev)
764 		goto fail_rcu_unlock;
765 	dev_hold(netdev);
766 
767 	flow.daddr = payload->ipv4_addr;
768 	flow.flowi4_proto = IPPROTO_UDP;
769 
770 #if IS_ENABLED(CONFIG_INET)
771 	/* Do a route lookup on same namespace as ingress port. */
772 	rt = ip_route_output_key(dev_net(netdev), &flow);
773 	err = PTR_ERR_OR_ZERO(rt);
774 	if (err)
775 		goto fail_rcu_unlock;
776 #else
777 	goto fail_rcu_unlock;
778 #endif
779 
780 	/* Get the neighbour entry for the lookup */
781 	n = dst_neigh_lookup(&rt->dst, &flow.daddr);
782 	ip_rt_put(rt);
783 	if (!n)
784 		goto fail_rcu_unlock;
785 	rcu_read_unlock();
786 
787 	nfp_tun_write_neigh(n->dev, app, &flow, n, false, true);
788 	neigh_release(n);
789 	dev_put(netdev);
790 	return;
791 
792 fail_rcu_unlock:
793 	rcu_read_unlock();
794 	dev_put(netdev);
795 	nfp_flower_cmsg_warn(app, "Requested route not found.\n");
796 }
797 
nfp_tunnel_request_route_v6(struct nfp_app * app,struct sk_buff * skb)798 void nfp_tunnel_request_route_v6(struct nfp_app *app, struct sk_buff *skb)
799 {
800 	struct nfp_tun_req_route_ipv6 *payload;
801 	struct net_device *netdev;
802 	struct flowi6 flow = {};
803 	struct dst_entry *dst;
804 	struct neighbour *n;
805 
806 	payload = nfp_flower_cmsg_get_data(skb);
807 
808 	rcu_read_lock();
809 	netdev = nfp_app_dev_get(app, be32_to_cpu(payload->ingress_port), NULL);
810 	if (!netdev)
811 		goto fail_rcu_unlock;
812 	dev_hold(netdev);
813 
814 	flow.daddr = payload->ipv6_addr;
815 	flow.flowi6_proto = IPPROTO_UDP;
816 
817 #if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
818 	dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(netdev), NULL, &flow,
819 					      NULL);
820 	if (IS_ERR(dst))
821 		goto fail_rcu_unlock;
822 #else
823 	goto fail_rcu_unlock;
824 #endif
825 
826 	n = dst_neigh_lookup(dst, &flow.daddr);
827 	dst_release(dst);
828 	if (!n)
829 		goto fail_rcu_unlock;
830 	rcu_read_unlock();
831 
832 	nfp_tun_write_neigh(n->dev, app, &flow, n, true, true);
833 	neigh_release(n);
834 	dev_put(netdev);
835 	return;
836 
837 fail_rcu_unlock:
838 	rcu_read_unlock();
839 	dev_put(netdev);
840 	nfp_flower_cmsg_warn(app, "Requested IPv6 route not found.\n");
841 }
842 
nfp_tun_write_ipv4_list(struct nfp_app * app)843 static void nfp_tun_write_ipv4_list(struct nfp_app *app)
844 {
845 	struct nfp_flower_priv *priv = app->priv;
846 	struct nfp_ipv4_addr_entry *entry;
847 	struct nfp_tun_ipv4_addr payload;
848 	struct list_head *ptr, *storage;
849 	int count;
850 
851 	memset(&payload, 0, sizeof(struct nfp_tun_ipv4_addr));
852 	mutex_lock(&priv->tun.ipv4_off_lock);
853 	count = 0;
854 	list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
855 		if (count >= NFP_FL_IPV4_ADDRS_MAX) {
856 			mutex_unlock(&priv->tun.ipv4_off_lock);
857 			nfp_flower_cmsg_warn(app, "IPv4 offload exceeds limit.\n");
858 			return;
859 		}
860 		entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
861 		payload.ipv4_addr[count++] = entry->ipv4_addr;
862 	}
863 	payload.count = cpu_to_be32(count);
864 	mutex_unlock(&priv->tun.ipv4_off_lock);
865 
866 	nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS,
867 				 sizeof(struct nfp_tun_ipv4_addr),
868 				 &payload, GFP_KERNEL);
869 }
870 
nfp_tunnel_add_ipv4_off(struct nfp_app * app,__be32 ipv4)871 void nfp_tunnel_add_ipv4_off(struct nfp_app *app, __be32 ipv4)
872 {
873 	struct nfp_flower_priv *priv = app->priv;
874 	struct nfp_ipv4_addr_entry *entry;
875 	struct list_head *ptr, *storage;
876 
877 	mutex_lock(&priv->tun.ipv4_off_lock);
878 	list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
879 		entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
880 		if (entry->ipv4_addr == ipv4) {
881 			entry->ref_count++;
882 			mutex_unlock(&priv->tun.ipv4_off_lock);
883 			return;
884 		}
885 	}
886 
887 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
888 	if (!entry) {
889 		mutex_unlock(&priv->tun.ipv4_off_lock);
890 		nfp_flower_cmsg_warn(app, "Mem error when offloading IP address.\n");
891 		return;
892 	}
893 	entry->ipv4_addr = ipv4;
894 	entry->ref_count = 1;
895 	list_add_tail(&entry->list, &priv->tun.ipv4_off_list);
896 	mutex_unlock(&priv->tun.ipv4_off_lock);
897 
898 	nfp_tun_write_ipv4_list(app);
899 }
900 
nfp_tunnel_del_ipv4_off(struct nfp_app * app,__be32 ipv4)901 void nfp_tunnel_del_ipv4_off(struct nfp_app *app, __be32 ipv4)
902 {
903 	struct nfp_flower_priv *priv = app->priv;
904 	struct nfp_ipv4_addr_entry *entry;
905 	struct list_head *ptr, *storage;
906 
907 	mutex_lock(&priv->tun.ipv4_off_lock);
908 	list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
909 		entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
910 		if (entry->ipv4_addr == ipv4) {
911 			entry->ref_count--;
912 			if (!entry->ref_count) {
913 				list_del(&entry->list);
914 				kfree(entry);
915 			}
916 			break;
917 		}
918 	}
919 	mutex_unlock(&priv->tun.ipv4_off_lock);
920 
921 	nfp_tun_write_ipv4_list(app);
922 }
923 
nfp_tun_write_ipv6_list(struct nfp_app * app)924 static void nfp_tun_write_ipv6_list(struct nfp_app *app)
925 {
926 	struct nfp_flower_priv *priv = app->priv;
927 	struct nfp_ipv6_addr_entry *entry;
928 	struct nfp_tun_ipv6_addr payload;
929 	int count = 0;
930 
931 	memset(&payload, 0, sizeof(struct nfp_tun_ipv6_addr));
932 	mutex_lock(&priv->tun.ipv6_off_lock);
933 	list_for_each_entry(entry, &priv->tun.ipv6_off_list, list) {
934 		if (count >= NFP_FL_IPV6_ADDRS_MAX) {
935 			nfp_flower_cmsg_warn(app, "Too many IPv6 tunnel endpoint addresses, some cannot be offloaded.\n");
936 			break;
937 		}
938 		payload.ipv6_addr[count++] = entry->ipv6_addr;
939 	}
940 	mutex_unlock(&priv->tun.ipv6_off_lock);
941 	payload.count = cpu_to_be32(count);
942 
943 	nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_IPS_V6,
944 				 sizeof(struct nfp_tun_ipv6_addr),
945 				 &payload, GFP_KERNEL);
946 }
947 
948 struct nfp_ipv6_addr_entry *
nfp_tunnel_add_ipv6_off(struct nfp_app * app,struct in6_addr * ipv6)949 nfp_tunnel_add_ipv6_off(struct nfp_app *app, struct in6_addr *ipv6)
950 {
951 	struct nfp_flower_priv *priv = app->priv;
952 	struct nfp_ipv6_addr_entry *entry;
953 
954 	mutex_lock(&priv->tun.ipv6_off_lock);
955 	list_for_each_entry(entry, &priv->tun.ipv6_off_list, list)
956 		if (!memcmp(&entry->ipv6_addr, ipv6, sizeof(*ipv6))) {
957 			entry->ref_count++;
958 			mutex_unlock(&priv->tun.ipv6_off_lock);
959 			return entry;
960 		}
961 
962 	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
963 	if (!entry) {
964 		mutex_unlock(&priv->tun.ipv6_off_lock);
965 		nfp_flower_cmsg_warn(app, "Mem error when offloading IP address.\n");
966 		return NULL;
967 	}
968 	entry->ipv6_addr = *ipv6;
969 	entry->ref_count = 1;
970 	list_add_tail(&entry->list, &priv->tun.ipv6_off_list);
971 	mutex_unlock(&priv->tun.ipv6_off_lock);
972 
973 	nfp_tun_write_ipv6_list(app);
974 
975 	return entry;
976 }
977 
978 void
nfp_tunnel_put_ipv6_off(struct nfp_app * app,struct nfp_ipv6_addr_entry * entry)979 nfp_tunnel_put_ipv6_off(struct nfp_app *app, struct nfp_ipv6_addr_entry *entry)
980 {
981 	struct nfp_flower_priv *priv = app->priv;
982 	bool freed = false;
983 
984 	mutex_lock(&priv->tun.ipv6_off_lock);
985 	if (!--entry->ref_count) {
986 		list_del(&entry->list);
987 		kfree(entry);
988 		freed = true;
989 	}
990 	mutex_unlock(&priv->tun.ipv6_off_lock);
991 
992 	if (freed)
993 		nfp_tun_write_ipv6_list(app);
994 }
995 
996 static int
__nfp_tunnel_offload_mac(struct nfp_app * app,const u8 * mac,u16 idx,bool del)997 __nfp_tunnel_offload_mac(struct nfp_app *app, const u8 *mac, u16 idx, bool del)
998 {
999 	struct nfp_tun_mac_addr_offload payload;
1000 
1001 	memset(&payload, 0, sizeof(payload));
1002 
1003 	if (del)
1004 		payload.flags = cpu_to_be16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
1005 
1006 	/* FW supports multiple MACs per cmsg but restrict to single. */
1007 	payload.count = cpu_to_be16(1);
1008 	payload.index = cpu_to_be16(idx);
1009 	ether_addr_copy(payload.addr, mac);
1010 
1011 	return nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_TUN_MAC,
1012 					sizeof(struct nfp_tun_mac_addr_offload),
1013 					&payload, GFP_KERNEL);
1014 }
1015 
nfp_tunnel_port_is_phy_repr(int port)1016 static bool nfp_tunnel_port_is_phy_repr(int port)
1017 {
1018 	if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) ==
1019 	    NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT)
1020 		return true;
1021 
1022 	return false;
1023 }
1024 
nfp_tunnel_get_mac_idx_from_phy_port_id(int port)1025 static u16 nfp_tunnel_get_mac_idx_from_phy_port_id(int port)
1026 {
1027 	return port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT;
1028 }
1029 
nfp_tunnel_get_global_mac_idx_from_ida(int id)1030 static u16 nfp_tunnel_get_global_mac_idx_from_ida(int id)
1031 {
1032 	return id << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
1033 }
1034 
nfp_tunnel_get_ida_from_global_mac_idx(u16 nfp_mac_idx)1035 static int nfp_tunnel_get_ida_from_global_mac_idx(u16 nfp_mac_idx)
1036 {
1037 	return nfp_mac_idx >> 8;
1038 }
1039 
nfp_tunnel_is_mac_idx_global(u16 nfp_mac_idx)1040 static bool nfp_tunnel_is_mac_idx_global(u16 nfp_mac_idx)
1041 {
1042 	return (nfp_mac_idx & 0xff) == NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
1043 }
1044 
1045 static struct nfp_tun_offloaded_mac *
nfp_tunnel_lookup_offloaded_macs(struct nfp_app * app,const u8 * mac)1046 nfp_tunnel_lookup_offloaded_macs(struct nfp_app *app, const u8 *mac)
1047 {
1048 	struct nfp_flower_priv *priv = app->priv;
1049 
1050 	return rhashtable_lookup_fast(&priv->tun.offloaded_macs, mac,
1051 				      offloaded_macs_params);
1052 }
1053 
1054 static void
nfp_tunnel_offloaded_macs_inc_ref_and_link(struct nfp_tun_offloaded_mac * entry,struct net_device * netdev,bool mod)1055 nfp_tunnel_offloaded_macs_inc_ref_and_link(struct nfp_tun_offloaded_mac *entry,
1056 					   struct net_device *netdev, bool mod)
1057 {
1058 	if (nfp_netdev_is_nfp_repr(netdev)) {
1059 		struct nfp_flower_repr_priv *repr_priv;
1060 		struct nfp_repr *repr;
1061 
1062 		repr = netdev_priv(netdev);
1063 		repr_priv = repr->app_priv;
1064 
1065 		/* If modifing MAC, remove repr from old list first. */
1066 		if (mod)
1067 			list_del(&repr_priv->mac_list);
1068 
1069 		list_add_tail(&repr_priv->mac_list, &entry->repr_list);
1070 	} else if (nfp_flower_is_supported_bridge(netdev)) {
1071 		entry->bridge_count++;
1072 	}
1073 
1074 	entry->ref_count++;
1075 }
1076 
1077 static int
nfp_tunnel_add_shared_mac(struct nfp_app * app,struct net_device * netdev,int port,bool mod)1078 nfp_tunnel_add_shared_mac(struct nfp_app *app, struct net_device *netdev,
1079 			  int port, bool mod)
1080 {
1081 	struct nfp_flower_priv *priv = app->priv;
1082 	struct nfp_tun_offloaded_mac *entry;
1083 	int ida_idx = -1, err;
1084 	u16 nfp_mac_idx = 0;
1085 
1086 	entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr);
1087 	if (entry && (nfp_tunnel_is_mac_idx_global(entry->index) || netif_is_lag_port(netdev))) {
1088 		if (entry->bridge_count ||
1089 		    !nfp_flower_is_supported_bridge(netdev)) {
1090 			nfp_tunnel_offloaded_macs_inc_ref_and_link(entry,
1091 								   netdev, mod);
1092 			return 0;
1093 		}
1094 
1095 		/* MAC is global but matches need to go to pre_tun table. */
1096 		nfp_mac_idx = entry->index | NFP_TUN_PRE_TUN_IDX_BIT;
1097 	}
1098 
1099 	if (!nfp_mac_idx) {
1100 		/* Assign a global index if non-repr or MAC is now shared. */
1101 		if (entry || !port) {
1102 			ida_idx = ida_alloc_max(&priv->tun.mac_off_ids,
1103 						NFP_MAX_MAC_INDEX, GFP_KERNEL);
1104 			if (ida_idx < 0)
1105 				return ida_idx;
1106 
1107 			nfp_mac_idx =
1108 				nfp_tunnel_get_global_mac_idx_from_ida(ida_idx);
1109 
1110 			if (nfp_flower_is_supported_bridge(netdev))
1111 				nfp_mac_idx |= NFP_TUN_PRE_TUN_IDX_BIT;
1112 
1113 		} else {
1114 			nfp_mac_idx =
1115 				nfp_tunnel_get_mac_idx_from_phy_port_id(port);
1116 		}
1117 	}
1118 
1119 	if (!entry) {
1120 		entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1121 		if (!entry) {
1122 			err = -ENOMEM;
1123 			goto err_free_ida;
1124 		}
1125 
1126 		ether_addr_copy(entry->addr, netdev->dev_addr);
1127 		INIT_LIST_HEAD(&entry->repr_list);
1128 
1129 		if (rhashtable_insert_fast(&priv->tun.offloaded_macs,
1130 					   &entry->ht_node,
1131 					   offloaded_macs_params)) {
1132 			err = -ENOMEM;
1133 			goto err_free_entry;
1134 		}
1135 	}
1136 
1137 	err = __nfp_tunnel_offload_mac(app, netdev->dev_addr,
1138 				       nfp_mac_idx, false);
1139 	if (err) {
1140 		/* If not shared then free. */
1141 		if (!entry->ref_count)
1142 			goto err_remove_hash;
1143 		goto err_free_ida;
1144 	}
1145 
1146 	entry->index = nfp_mac_idx;
1147 	nfp_tunnel_offloaded_macs_inc_ref_and_link(entry, netdev, mod);
1148 
1149 	return 0;
1150 
1151 err_remove_hash:
1152 	rhashtable_remove_fast(&priv->tun.offloaded_macs, &entry->ht_node,
1153 			       offloaded_macs_params);
1154 err_free_entry:
1155 	kfree(entry);
1156 err_free_ida:
1157 	if (ida_idx != -1)
1158 		ida_free(&priv->tun.mac_off_ids, ida_idx);
1159 
1160 	return err;
1161 }
1162 
1163 static int
nfp_tunnel_del_shared_mac(struct nfp_app * app,struct net_device * netdev,const u8 * mac,bool mod)1164 nfp_tunnel_del_shared_mac(struct nfp_app *app, struct net_device *netdev,
1165 			  const u8 *mac, bool mod)
1166 {
1167 	struct nfp_flower_priv *priv = app->priv;
1168 	struct nfp_flower_repr_priv *repr_priv;
1169 	struct nfp_tun_offloaded_mac *entry;
1170 	struct nfp_repr *repr;
1171 	u16 nfp_mac_idx;
1172 	int ida_idx;
1173 
1174 	entry = nfp_tunnel_lookup_offloaded_macs(app, mac);
1175 	if (!entry)
1176 		return 0;
1177 
1178 	entry->ref_count--;
1179 	/* If del is part of a mod then mac_list is still in use elsewhere. */
1180 	if (nfp_netdev_is_nfp_repr(netdev) && !mod) {
1181 		repr = netdev_priv(netdev);
1182 		repr_priv = repr->app_priv;
1183 		list_del(&repr_priv->mac_list);
1184 	}
1185 
1186 	if (nfp_flower_is_supported_bridge(netdev)) {
1187 		entry->bridge_count--;
1188 
1189 		if (!entry->bridge_count && entry->ref_count) {
1190 			nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT;
1191 			if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx,
1192 						     false)) {
1193 				nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n",
1194 						     netdev_name(netdev));
1195 				return 0;
1196 			}
1197 
1198 			entry->index = nfp_mac_idx;
1199 			return 0;
1200 		}
1201 	}
1202 
1203 	/* If MAC is now used by 1 repr set the offloaded MAC index to port. */
1204 	if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) {
1205 		int port, err;
1206 
1207 		repr_priv = list_first_entry(&entry->repr_list,
1208 					     struct nfp_flower_repr_priv,
1209 					     mac_list);
1210 		repr = repr_priv->nfp_repr;
1211 		port = nfp_repr_get_port_id(repr->netdev);
1212 		nfp_mac_idx = nfp_tunnel_get_mac_idx_from_phy_port_id(port);
1213 		err = __nfp_tunnel_offload_mac(app, mac, nfp_mac_idx, false);
1214 		if (err) {
1215 			nfp_flower_cmsg_warn(app, "MAC offload index revert failed on %s.\n",
1216 					     netdev_name(netdev));
1217 			return 0;
1218 		}
1219 
1220 		ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index);
1221 		ida_free(&priv->tun.mac_off_ids, ida_idx);
1222 		entry->index = nfp_mac_idx;
1223 		return 0;
1224 	}
1225 
1226 	if (entry->ref_count)
1227 		return 0;
1228 
1229 	WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs,
1230 					    &entry->ht_node,
1231 					    offloaded_macs_params));
1232 
1233 	if (nfp_flower_is_supported_bridge(netdev))
1234 		nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT;
1235 	else
1236 		nfp_mac_idx = entry->index;
1237 
1238 	/* If MAC has global ID then extract and free the ida entry. */
1239 	if (nfp_tunnel_is_mac_idx_global(nfp_mac_idx)) {
1240 		ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index);
1241 		ida_free(&priv->tun.mac_off_ids, ida_idx);
1242 	}
1243 
1244 	kfree(entry);
1245 
1246 	return __nfp_tunnel_offload_mac(app, mac, 0, true);
1247 }
1248 
1249 static int
nfp_tunnel_offload_mac(struct nfp_app * app,struct net_device * netdev,enum nfp_flower_mac_offload_cmd cmd)1250 nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev,
1251 		       enum nfp_flower_mac_offload_cmd cmd)
1252 {
1253 	struct nfp_flower_non_repr_priv *nr_priv = NULL;
1254 	bool non_repr = false, *mac_offloaded;
1255 	u8 *off_mac = NULL;
1256 	int err, port = 0;
1257 
1258 	if (nfp_netdev_is_nfp_repr(netdev)) {
1259 		struct nfp_flower_repr_priv *repr_priv;
1260 		struct nfp_repr *repr;
1261 
1262 		repr = netdev_priv(netdev);
1263 		if (repr->app != app)
1264 			return 0;
1265 
1266 		repr_priv = repr->app_priv;
1267 		if (repr_priv->on_bridge)
1268 			return 0;
1269 
1270 		mac_offloaded = &repr_priv->mac_offloaded;
1271 		off_mac = &repr_priv->offloaded_mac_addr[0];
1272 		port = nfp_repr_get_port_id(netdev);
1273 		if (!nfp_tunnel_port_is_phy_repr(port))
1274 			return 0;
1275 	} else if (nfp_fl_is_netdev_to_offload(netdev)) {
1276 		nr_priv = nfp_flower_non_repr_priv_get(app, netdev);
1277 		if (!nr_priv)
1278 			return -ENOMEM;
1279 
1280 		mac_offloaded = &nr_priv->mac_offloaded;
1281 		off_mac = &nr_priv->offloaded_mac_addr[0];
1282 		non_repr = true;
1283 	} else {
1284 		return 0;
1285 	}
1286 
1287 	if (!is_valid_ether_addr(netdev->dev_addr)) {
1288 		err = -EINVAL;
1289 		goto err_put_non_repr_priv;
1290 	}
1291 
1292 	if (cmd == NFP_TUNNEL_MAC_OFFLOAD_MOD && !*mac_offloaded)
1293 		cmd = NFP_TUNNEL_MAC_OFFLOAD_ADD;
1294 
1295 	switch (cmd) {
1296 	case NFP_TUNNEL_MAC_OFFLOAD_ADD:
1297 		err = nfp_tunnel_add_shared_mac(app, netdev, port, false);
1298 		if (err)
1299 			goto err_put_non_repr_priv;
1300 
1301 		if (non_repr)
1302 			__nfp_flower_non_repr_priv_get(nr_priv);
1303 
1304 		*mac_offloaded = true;
1305 		ether_addr_copy(off_mac, netdev->dev_addr);
1306 		break;
1307 	case NFP_TUNNEL_MAC_OFFLOAD_DEL:
1308 		/* Only attempt delete if add was successful. */
1309 		if (!*mac_offloaded)
1310 			break;
1311 
1312 		if (non_repr)
1313 			__nfp_flower_non_repr_priv_put(nr_priv);
1314 
1315 		*mac_offloaded = false;
1316 
1317 		err = nfp_tunnel_del_shared_mac(app, netdev, netdev->dev_addr,
1318 						false);
1319 		if (err)
1320 			goto err_put_non_repr_priv;
1321 
1322 		break;
1323 	case NFP_TUNNEL_MAC_OFFLOAD_MOD:
1324 		/* Ignore if changing to the same address. */
1325 		if (ether_addr_equal(netdev->dev_addr, off_mac))
1326 			break;
1327 
1328 		err = nfp_tunnel_add_shared_mac(app, netdev, port, true);
1329 		if (err)
1330 			goto err_put_non_repr_priv;
1331 
1332 		/* Delete the previous MAC address. */
1333 		err = nfp_tunnel_del_shared_mac(app, netdev, off_mac, true);
1334 		if (err)
1335 			nfp_flower_cmsg_warn(app, "Failed to remove offload of replaced MAC addr on %s.\n",
1336 					     netdev_name(netdev));
1337 
1338 		ether_addr_copy(off_mac, netdev->dev_addr);
1339 		break;
1340 	default:
1341 		err = -EINVAL;
1342 		goto err_put_non_repr_priv;
1343 	}
1344 
1345 	if (non_repr)
1346 		__nfp_flower_non_repr_priv_put(nr_priv);
1347 
1348 	return 0;
1349 
1350 err_put_non_repr_priv:
1351 	if (non_repr)
1352 		__nfp_flower_non_repr_priv_put(nr_priv);
1353 
1354 	return err;
1355 }
1356 
nfp_tunnel_mac_event_handler(struct nfp_app * app,struct net_device * netdev,unsigned long event,void * ptr)1357 int nfp_tunnel_mac_event_handler(struct nfp_app *app,
1358 				 struct net_device *netdev,
1359 				 unsigned long event, void *ptr)
1360 {
1361 	int err;
1362 
1363 	if (event == NETDEV_DOWN) {
1364 		err = nfp_tunnel_offload_mac(app, netdev,
1365 					     NFP_TUNNEL_MAC_OFFLOAD_DEL);
1366 		if (err)
1367 			nfp_flower_cmsg_warn(app, "Failed to delete offload MAC on %s.\n",
1368 					     netdev_name(netdev));
1369 	} else if (event == NETDEV_UP) {
1370 		err = nfp_tunnel_offload_mac(app, netdev,
1371 					     NFP_TUNNEL_MAC_OFFLOAD_ADD);
1372 		if (err)
1373 			nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n",
1374 					     netdev_name(netdev));
1375 	} else if (event == NETDEV_CHANGEADDR) {
1376 		/* Only offload addr change if netdev is already up. */
1377 		if (!(netdev->flags & IFF_UP))
1378 			return NOTIFY_OK;
1379 
1380 		err = nfp_tunnel_offload_mac(app, netdev,
1381 					     NFP_TUNNEL_MAC_OFFLOAD_MOD);
1382 		if (err)
1383 			nfp_flower_cmsg_warn(app, "Failed to offload MAC change on %s.\n",
1384 					     netdev_name(netdev));
1385 	} else if (event == NETDEV_CHANGEUPPER) {
1386 		/* If a repr is attached to a bridge then tunnel packets
1387 		 * entering the physical port are directed through the bridge
1388 		 * datapath and cannot be directly detunneled. Therefore,
1389 		 * associated offloaded MACs and indexes should not be used
1390 		 * by fw for detunneling.
1391 		 */
1392 		struct netdev_notifier_changeupper_info *info = ptr;
1393 		struct net_device *upper = info->upper_dev;
1394 		struct nfp_flower_repr_priv *repr_priv;
1395 		struct nfp_repr *repr;
1396 
1397 		if (!nfp_netdev_is_nfp_repr(netdev) ||
1398 		    !nfp_flower_is_supported_bridge(upper))
1399 			return NOTIFY_OK;
1400 
1401 		repr = netdev_priv(netdev);
1402 		if (repr->app != app)
1403 			return NOTIFY_OK;
1404 
1405 		repr_priv = repr->app_priv;
1406 
1407 		if (info->linking) {
1408 			if (nfp_tunnel_offload_mac(app, netdev,
1409 						   NFP_TUNNEL_MAC_OFFLOAD_DEL))
1410 				nfp_flower_cmsg_warn(app, "Failed to delete offloaded MAC on %s.\n",
1411 						     netdev_name(netdev));
1412 			repr_priv->on_bridge = true;
1413 		} else {
1414 			repr_priv->on_bridge = false;
1415 
1416 			if (!(netdev->flags & IFF_UP))
1417 				return NOTIFY_OK;
1418 
1419 			if (nfp_tunnel_offload_mac(app, netdev,
1420 						   NFP_TUNNEL_MAC_OFFLOAD_ADD))
1421 				nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n",
1422 						     netdev_name(netdev));
1423 		}
1424 	}
1425 	return NOTIFY_OK;
1426 }
1427 
nfp_flower_xmit_pre_tun_flow(struct nfp_app * app,struct nfp_fl_payload * flow)1428 int nfp_flower_xmit_pre_tun_flow(struct nfp_app *app,
1429 				 struct nfp_fl_payload *flow)
1430 {
1431 	struct nfp_flower_priv *app_priv = app->priv;
1432 	struct nfp_tun_offloaded_mac *mac_entry;
1433 	struct nfp_flower_meta_tci *key_meta;
1434 	struct nfp_tun_pre_tun_rule payload;
1435 	struct net_device *internal_dev;
1436 	int err;
1437 
1438 	if (app_priv->pre_tun_rule_cnt == NFP_TUN_PRE_TUN_RULE_LIMIT)
1439 		return -ENOSPC;
1440 
1441 	memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule));
1442 
1443 	internal_dev = flow->pre_tun_rule.dev;
1444 	payload.vlan_tci = flow->pre_tun_rule.vlan_tci;
1445 	payload.host_ctx_id = flow->meta.host_ctx_id;
1446 
1447 	/* Lookup MAC index for the pre-tunnel rule egress device.
1448 	 * Note that because the device is always an internal port, it will
1449 	 * have a constant global index so does not need to be tracked.
1450 	 */
1451 	mac_entry = nfp_tunnel_lookup_offloaded_macs(app,
1452 						     internal_dev->dev_addr);
1453 	if (!mac_entry)
1454 		return -ENOENT;
1455 
1456 	/* Set/clear IPV6 bit. cpu_to_be16() swap will lead to MSB being
1457 	 * set/clear for port_idx.
1458 	 */
1459 	key_meta = (struct nfp_flower_meta_tci *)flow->unmasked_data;
1460 	if (key_meta->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV6)
1461 		mac_entry->index |= NFP_TUN_PRE_TUN_IPV6_BIT;
1462 	else
1463 		mac_entry->index &= ~NFP_TUN_PRE_TUN_IPV6_BIT;
1464 
1465 	payload.port_idx = cpu_to_be16(mac_entry->index);
1466 
1467 	/* Copy mac id and vlan to flow - dev may not exist at delete time. */
1468 	flow->pre_tun_rule.vlan_tci = payload.vlan_tci;
1469 	flow->pre_tun_rule.port_idx = payload.port_idx;
1470 
1471 	err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE,
1472 				       sizeof(struct nfp_tun_pre_tun_rule),
1473 				       (unsigned char *)&payload, GFP_KERNEL);
1474 	if (err)
1475 		return err;
1476 
1477 	app_priv->pre_tun_rule_cnt++;
1478 
1479 	return 0;
1480 }
1481 
nfp_flower_xmit_pre_tun_del_flow(struct nfp_app * app,struct nfp_fl_payload * flow)1482 int nfp_flower_xmit_pre_tun_del_flow(struct nfp_app *app,
1483 				     struct nfp_fl_payload *flow)
1484 {
1485 	struct nfp_flower_priv *app_priv = app->priv;
1486 	struct nfp_tun_pre_tun_rule payload;
1487 	u32 tmp_flags = 0;
1488 	int err;
1489 
1490 	memset(&payload, 0, sizeof(struct nfp_tun_pre_tun_rule));
1491 
1492 	tmp_flags |= NFP_TUN_PRE_TUN_RULE_DEL;
1493 	payload.flags = cpu_to_be32(tmp_flags);
1494 	payload.vlan_tci = flow->pre_tun_rule.vlan_tci;
1495 	payload.port_idx = flow->pre_tun_rule.port_idx;
1496 
1497 	err = nfp_flower_xmit_tun_conf(app, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE,
1498 				       sizeof(struct nfp_tun_pre_tun_rule),
1499 				       (unsigned char *)&payload, GFP_KERNEL);
1500 	if (err)
1501 		return err;
1502 
1503 	app_priv->pre_tun_rule_cnt--;
1504 
1505 	return 0;
1506 }
1507 
nfp_tunnel_config_start(struct nfp_app * app)1508 int nfp_tunnel_config_start(struct nfp_app *app)
1509 {
1510 	struct nfp_flower_priv *priv = app->priv;
1511 	int err;
1512 
1513 	/* Initialise rhash for MAC offload tracking. */
1514 	err = rhashtable_init(&priv->tun.offloaded_macs,
1515 			      &offloaded_macs_params);
1516 	if (err)
1517 		return err;
1518 
1519 	ida_init(&priv->tun.mac_off_ids);
1520 
1521 	/* Initialise priv data for IPv4/v6 offloading. */
1522 	mutex_init(&priv->tun.ipv4_off_lock);
1523 	INIT_LIST_HEAD(&priv->tun.ipv4_off_list);
1524 	mutex_init(&priv->tun.ipv6_off_lock);
1525 	INIT_LIST_HEAD(&priv->tun.ipv6_off_list);
1526 
1527 	/* Initialise priv data for neighbour offloading. */
1528 	priv->tun.neigh_nb.notifier_call = nfp_tun_neigh_event_handler;
1529 
1530 	err = register_netevent_notifier(&priv->tun.neigh_nb);
1531 	if (err) {
1532 		rhashtable_free_and_destroy(&priv->tun.offloaded_macs,
1533 					    nfp_check_rhashtable_empty, NULL);
1534 		return err;
1535 	}
1536 
1537 	return 0;
1538 }
1539 
nfp_tunnel_config_stop(struct nfp_app * app)1540 void nfp_tunnel_config_stop(struct nfp_app *app)
1541 {
1542 	struct nfp_flower_priv *priv = app->priv;
1543 	struct nfp_ipv4_addr_entry *ip_entry;
1544 	struct list_head *ptr, *storage;
1545 
1546 	unregister_netevent_notifier(&priv->tun.neigh_nb);
1547 
1548 	ida_destroy(&priv->tun.mac_off_ids);
1549 
1550 	/* Free any memory that may be occupied by ipv4 list. */
1551 	list_for_each_safe(ptr, storage, &priv->tun.ipv4_off_list) {
1552 		ip_entry = list_entry(ptr, struct nfp_ipv4_addr_entry, list);
1553 		list_del(&ip_entry->list);
1554 		kfree(ip_entry);
1555 	}
1556 
1557 	mutex_destroy(&priv->tun.ipv6_off_lock);
1558 
1559 	/* Destroy rhash. Entries should be cleaned on netdev notifier unreg. */
1560 	rhashtable_free_and_destroy(&priv->tun.offloaded_macs,
1561 				    nfp_check_rhashtable_empty, NULL);
1562 
1563 	nfp_tun_cleanup_nn_entries(app);
1564 }
1565