1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2/* Copyright (c) 2019-2021 Marvell International Ltd. All rights reserved */
3
4#include <linux/kernel.h>
5#include <linux/types.h>
6#include <linux/inetdevice.h>
7#include <net/inet_dscp.h>
8#include <net/switchdev.h>
9#include <linux/rhashtable.h>
10#include <net/nexthop.h>
11#include <net/arp.h>
12#include <linux/if_vlan.h>
13#include <linux/if_macvlan.h>
14#include <net/netevent.h>
15
16#include "prestera.h"
17#include "prestera_router_hw.h"
18
19#define PRESTERA_IMPLICITY_RESOLVE_DEAD_NEIGH
20#define PRESTERA_NH_PROBE_INTERVAL 5000 /* ms */
21
22struct prestera_kern_neigh_cache_key {
23	struct prestera_ip_addr addr;
24	struct net_device *dev;
25};
26
27struct prestera_kern_neigh_cache {
28	struct prestera_kern_neigh_cache_key key;
29	struct rhash_head ht_node;
30	struct list_head kern_fib_cache_list;
31	/* Hold prepared nh_neigh info if is in_kernel */
32	struct prestera_neigh_info nh_neigh_info;
33	/* Indicate if neighbour is reachable by direct route */
34	bool reachable;
35	/* Lock cache if neigh is present in kernel */
36	bool in_kernel;
37};
38
39struct prestera_kern_fib_cache_key {
40	struct prestera_ip_addr addr;
41	u32 prefix_len;
42	u32 kern_tb_id; /* tb_id from kernel (not fixed) */
43};
44
45/* Subscribing on neighbours in kernel */
46struct prestera_kern_fib_cache {
47	struct prestera_kern_fib_cache_key key;
48	struct {
49		struct prestera_fib_key fib_key;
50		enum prestera_fib_type fib_type;
51		struct prestera_nexthop_group_key nh_grp_key;
52	} lpm_info; /* hold prepared lpm info */
53	/* Indicate if route is not overlapped by another table */
54	struct rhash_head ht_node; /* node of prestera_router */
55	struct prestera_kern_neigh_cache_head {
56		struct prestera_kern_fib_cache *this;
57		struct list_head head;
58		struct prestera_kern_neigh_cache *n_cache;
59	} kern_neigh_cache_head[PRESTERA_NHGR_SIZE_MAX];
60	union {
61		struct fib_notifier_info info; /* point to any of 4/6 */
62		struct fib_entry_notifier_info fen4_info;
63	};
64	bool reachable;
65};
66
67static const struct rhashtable_params __prestera_kern_neigh_cache_ht_params = {
68	.key_offset  = offsetof(struct prestera_kern_neigh_cache, key),
69	.head_offset = offsetof(struct prestera_kern_neigh_cache, ht_node),
70	.key_len     = sizeof(struct prestera_kern_neigh_cache_key),
71	.automatic_shrinking = true,
72};
73
74static const struct rhashtable_params __prestera_kern_fib_cache_ht_params = {
75	.key_offset  = offsetof(struct prestera_kern_fib_cache, key),
76	.head_offset = offsetof(struct prestera_kern_fib_cache, ht_node),
77	.key_len     = sizeof(struct prestera_kern_fib_cache_key),
78	.automatic_shrinking = true,
79};
80
81/* This util to be used, to convert kernel rules for default vr in hw_vr */
82static u32 prestera_fix_tb_id(u32 tb_id)
83{
84	if (tb_id == RT_TABLE_UNSPEC ||
85	    tb_id == RT_TABLE_LOCAL ||
86	    tb_id == RT_TABLE_DEFAULT)
87		tb_id = RT_TABLE_MAIN;
88
89	return tb_id;
90}
91
92static void
93prestera_util_fen_info2fib_cache_key(struct fib_notifier_info *info,
94				     struct prestera_kern_fib_cache_key *key)
95{
96	struct fib_entry_notifier_info *fen_info =
97		container_of(info, struct fib_entry_notifier_info, info);
98
99	memset(key, 0, sizeof(*key));
100	key->addr.v = PRESTERA_IPV4;
101	key->addr.u.ipv4 = cpu_to_be32(fen_info->dst);
102	key->prefix_len = fen_info->dst_len;
103	key->kern_tb_id = fen_info->tb_id;
104}
105
106static int prestera_util_nhc2nc_key(struct prestera_switch *sw,
107				    struct fib_nh_common *nhc,
108				    struct prestera_kern_neigh_cache_key *nk)
109{
110	memset(nk, 0, sizeof(*nk));
111	if (nhc->nhc_gw_family == AF_INET) {
112		nk->addr.v = PRESTERA_IPV4;
113		nk->addr.u.ipv4 = nhc->nhc_gw.ipv4;
114	} else {
115		nk->addr.v = PRESTERA_IPV6;
116		nk->addr.u.ipv6 = nhc->nhc_gw.ipv6;
117	}
118
119	nk->dev = nhc->nhc_dev;
120	return 0;
121}
122
123static void
124prestera_util_nc_key2nh_key(struct prestera_kern_neigh_cache_key *ck,
125			    struct prestera_nh_neigh_key *nk)
126{
127	memset(nk, 0, sizeof(*nk));
128	nk->addr = ck->addr;
129	nk->rif = (void *)ck->dev;
130}
131
132static bool
133prestera_util_nhc_eq_n_cache_key(struct prestera_switch *sw,
134				 struct fib_nh_common *nhc,
135				 struct prestera_kern_neigh_cache_key *nk)
136{
137	struct prestera_kern_neigh_cache_key tk;
138	int err;
139
140	err = prestera_util_nhc2nc_key(sw, nhc, &tk);
141	if (err)
142		return false;
143
144	if (memcmp(&tk, nk, sizeof(tk)))
145		return false;
146
147	return true;
148}
149
150static int
151prestera_util_neigh2nc_key(struct prestera_switch *sw, struct neighbour *n,
152			   struct prestera_kern_neigh_cache_key *key)
153{
154	memset(key, 0, sizeof(*key));
155	if (n->tbl->family == AF_INET) {
156		key->addr.v = PRESTERA_IPV4;
157		key->addr.u.ipv4 = *(__be32 *)n->primary_key;
158	} else {
159		return -ENOENT;
160	}
161
162	key->dev = n->dev;
163
164	return 0;
165}
166
167static bool __prestera_fi_is_direct(struct fib_info *fi)
168{
169	struct fib_nh_common *fib_nhc;
170
171	if (fib_info_num_path(fi) == 1) {
172		fib_nhc = fib_info_nhc(fi, 0);
173		if (fib_nhc->nhc_gw_family == AF_UNSPEC)
174			return true;
175	}
176
177	return false;
178}
179
180static bool prestera_fi_is_direct(struct fib_info *fi)
181{
182	if (fi->fib_type != RTN_UNICAST)
183		return false;
184
185	return __prestera_fi_is_direct(fi);
186}
187
188static bool prestera_fi_is_nh(struct fib_info *fi)
189{
190	if (fi->fib_type != RTN_UNICAST)
191		return false;
192
193	return !__prestera_fi_is_direct(fi);
194}
195
196static bool __prestera_fi6_is_direct(struct fib6_info *fi)
197{
198	if (!fi->fib6_nh->nh_common.nhc_gw_family)
199		return true;
200
201	return false;
202}
203
204static bool prestera_fi6_is_direct(struct fib6_info *fi)
205{
206	if (fi->fib6_type != RTN_UNICAST)
207		return false;
208
209	return __prestera_fi6_is_direct(fi);
210}
211
212static bool prestera_fi6_is_nh(struct fib6_info *fi)
213{
214	if (fi->fib6_type != RTN_UNICAST)
215		return false;
216
217	return !__prestera_fi6_is_direct(fi);
218}
219
220static bool prestera_fib_info_is_direct(struct fib_notifier_info *info)
221{
222	struct fib6_entry_notifier_info *fen6_info =
223		container_of(info, struct fib6_entry_notifier_info, info);
224	struct fib_entry_notifier_info *fen_info =
225		container_of(info, struct fib_entry_notifier_info, info);
226
227	if (info->family == AF_INET)
228		return prestera_fi_is_direct(fen_info->fi);
229	else
230		return prestera_fi6_is_direct(fen6_info->rt);
231}
232
233static bool prestera_fib_info_is_nh(struct fib_notifier_info *info)
234{
235	struct fib6_entry_notifier_info *fen6_info =
236		container_of(info, struct fib6_entry_notifier_info, info);
237	struct fib_entry_notifier_info *fen_info =
238		container_of(info, struct fib_entry_notifier_info, info);
239
240	if (info->family == AF_INET)
241		return prestera_fi_is_nh(fen_info->fi);
242	else
243		return prestera_fi6_is_nh(fen6_info->rt);
244}
245
246/* must be called with rcu_read_lock() */
247static int prestera_util_kern_get_route(struct fib_result *res, u32 tb_id,
248					__be32 *addr)
249{
250	struct flowi4 fl4;
251
252	/* TODO: walkthrough appropriate tables in kernel
253	 * to know if the same prefix exists in several tables
254	 */
255	memset(&fl4, 0, sizeof(fl4));
256	fl4.daddr = *addr;
257	return fib_lookup(&init_net, &fl4, res, 0 /* FIB_LOOKUP_NOREF */);
258}
259
260static bool
261__prestera_util_kern_n_is_reachable_v4(u32 tb_id, __be32 *addr,
262				       struct net_device *dev)
263{
264	struct fib_nh_common *fib_nhc;
265	struct fib_result res;
266	bool reachable;
267
268	reachable = false;
269
270	if (!prestera_util_kern_get_route(&res, tb_id, addr))
271		if (prestera_fi_is_direct(res.fi)) {
272			fib_nhc = fib_info_nhc(res.fi, 0);
273			if (dev == fib_nhc->nhc_dev)
274				reachable = true;
275		}
276
277	return reachable;
278}
279
280/* Check if neigh route is reachable */
281static bool
282prestera_util_kern_n_is_reachable(u32 tb_id,
283				  struct prestera_ip_addr *addr,
284				  struct net_device *dev)
285{
286	if (addr->v == PRESTERA_IPV4)
287		return __prestera_util_kern_n_is_reachable_v4(tb_id,
288							      &addr->u.ipv4,
289							      dev);
290	else
291		return false;
292}
293
294static void prestera_util_kern_set_neigh_offload(struct neighbour *n,
295						 bool offloaded)
296{
297	if (offloaded)
298		n->flags |= NTF_OFFLOADED;
299	else
300		n->flags &= ~NTF_OFFLOADED;
301}
302
303static void
304prestera_util_kern_set_nh_offload(struct fib_nh_common *nhc, bool offloaded, bool trap)
305{
306		if (offloaded)
307			nhc->nhc_flags |= RTNH_F_OFFLOAD;
308		else
309			nhc->nhc_flags &= ~RTNH_F_OFFLOAD;
310
311		if (trap)
312			nhc->nhc_flags |= RTNH_F_TRAP;
313		else
314			nhc->nhc_flags &= ~RTNH_F_TRAP;
315}
316
317static struct fib_nh_common *
318prestera_kern_fib_info_nhc(struct fib_notifier_info *info, int n)
319{
320	struct fib6_entry_notifier_info *fen6_info;
321	struct fib_entry_notifier_info *fen4_info;
322	struct fib6_info *iter;
323
324	if (info->family == AF_INET) {
325		fen4_info = container_of(info, struct fib_entry_notifier_info,
326					 info);
327		return fib_info_nhc(fen4_info->fi, n);
328	} else if (info->family == AF_INET6) {
329		fen6_info = container_of(info, struct fib6_entry_notifier_info,
330					 info);
331		if (!n)
332			return &fen6_info->rt->fib6_nh->nh_common;
333
334		list_for_each_entry(iter, &fen6_info->rt->fib6_siblings,
335				    fib6_siblings) {
336			if (!--n)
337				return &iter->fib6_nh->nh_common;
338		}
339	}
340
341	/* if family is incorrect - than upper functions has BUG */
342	/* if doesn't find requested index - there is alsi bug, because
343	 * valid index must be produced by nhs, which checks list length
344	 */
345	WARN(1, "Invalid parameters passed to %s n=%d i=%p",
346	     __func__, n, info);
347	return NULL;
348}
349
350static int prestera_kern_fib_info_nhs(struct fib_notifier_info *info)
351{
352	struct fib6_entry_notifier_info *fen6_info;
353	struct fib_entry_notifier_info *fen4_info;
354
355	if (info->family == AF_INET) {
356		fen4_info = container_of(info, struct fib_entry_notifier_info,
357					 info);
358		return fib_info_num_path(fen4_info->fi);
359	} else if (info->family == AF_INET6) {
360		fen6_info = container_of(info, struct fib6_entry_notifier_info,
361					 info);
362		return fen6_info->rt->fib6_nsiblings + 1;
363	}
364
365	return 0;
366}
367
368static unsigned char
369prestera_kern_fib_info_type(struct fib_notifier_info *info)
370{
371	struct fib6_entry_notifier_info *fen6_info;
372	struct fib_entry_notifier_info *fen4_info;
373
374	if (info->family == AF_INET) {
375		fen4_info = container_of(info, struct fib_entry_notifier_info,
376					 info);
377		return fen4_info->fi->fib_type;
378	} else if (info->family == AF_INET6) {
379		fen6_info = container_of(info, struct fib6_entry_notifier_info,
380					 info);
381		/* TODO: ECMP in ipv6 is several routes.
382		 * Every route has single nh.
383		 */
384		return fen6_info->rt->fib6_type;
385	}
386
387	return RTN_UNSPEC;
388}
389
390/* Decided, that uc_nh route with key==nh is obviously neighbour route */
391static bool
392prestera_fib_node_util_is_neighbour(struct prestera_fib_node *fib_node)
393{
394	if (fib_node->info.type != PRESTERA_FIB_TYPE_UC_NH)
395		return false;
396
397	if (fib_node->info.nh_grp->nh_neigh_head[1].neigh)
398		return false;
399
400	if (!fib_node->info.nh_grp->nh_neigh_head[0].neigh)
401		return false;
402
403	if (memcmp(&fib_node->info.nh_grp->nh_neigh_head[0].neigh->key.addr,
404		   &fib_node->key.addr, sizeof(struct prestera_ip_addr)))
405		return false;
406
407	return true;
408}
409
410static int prestera_dev_if_type(const struct net_device *dev)
411{
412	struct macvlan_dev *vlan;
413
414	if (is_vlan_dev(dev) &&
415	    netif_is_bridge_master(vlan_dev_real_dev(dev))) {
416		return PRESTERA_IF_VID_E;
417	} else if (netif_is_bridge_master(dev)) {
418		return PRESTERA_IF_VID_E;
419	} else if (netif_is_lag_master(dev)) {
420		return PRESTERA_IF_LAG_E;
421	} else if (netif_is_macvlan(dev)) {
422		vlan = netdev_priv(dev);
423		return prestera_dev_if_type(vlan->lowerdev);
424	} else {
425		return PRESTERA_IF_PORT_E;
426	}
427}
428
429static int
430prestera_neigh_iface_init(struct prestera_switch *sw,
431			  struct prestera_iface *iface,
432			  struct neighbour *n)
433{
434	struct prestera_port *port;
435
436	iface->vlan_id = 0; /* TODO: vlan egress */
437	iface->type = prestera_dev_if_type(n->dev);
438	if (iface->type != PRESTERA_IF_PORT_E)
439		return -EINVAL;
440
441	if (!prestera_netdev_check(n->dev))
442		return -EINVAL;
443
444	port = netdev_priv(n->dev);
445	iface->dev_port.hw_dev_num = port->dev_id;
446	iface->dev_port.port_num = port->hw_id;
447
448	return 0;
449}
450
451static struct prestera_kern_neigh_cache *
452prestera_kern_neigh_cache_find(struct prestera_switch *sw,
453			       struct prestera_kern_neigh_cache_key *key)
454{
455	struct prestera_kern_neigh_cache *n_cache;
456
457	n_cache =
458	 rhashtable_lookup_fast(&sw->router->kern_neigh_cache_ht, key,
459				__prestera_kern_neigh_cache_ht_params);
460	return n_cache;
461}
462
463static void
464__prestera_kern_neigh_cache_destruct(struct prestera_switch *sw,
465				     struct prestera_kern_neigh_cache *n_cache)
466{
467	dev_put(n_cache->key.dev);
468}
469
470static void
471__prestera_kern_neigh_cache_destroy(struct prestera_switch *sw,
472				    struct prestera_kern_neigh_cache *n_cache)
473{
474	rhashtable_remove_fast(&sw->router->kern_neigh_cache_ht,
475			       &n_cache->ht_node,
476			       __prestera_kern_neigh_cache_ht_params);
477	__prestera_kern_neigh_cache_destruct(sw, n_cache);
478	kfree(n_cache);
479}
480
481static struct prestera_kern_neigh_cache *
482__prestera_kern_neigh_cache_create(struct prestera_switch *sw,
483				   struct prestera_kern_neigh_cache_key *key)
484{
485	struct prestera_kern_neigh_cache *n_cache;
486	int err;
487
488	n_cache = kzalloc(sizeof(*n_cache), GFP_KERNEL);
489	if (!n_cache)
490		goto err_kzalloc;
491
492	memcpy(&n_cache->key, key, sizeof(*key));
493	dev_hold(n_cache->key.dev);
494
495	INIT_LIST_HEAD(&n_cache->kern_fib_cache_list);
496	err = rhashtable_insert_fast(&sw->router->kern_neigh_cache_ht,
497				     &n_cache->ht_node,
498				     __prestera_kern_neigh_cache_ht_params);
499	if (err)
500		goto err_ht_insert;
501
502	return n_cache;
503
504err_ht_insert:
505	dev_put(n_cache->key.dev);
506	kfree(n_cache);
507err_kzalloc:
508	return NULL;
509}
510
511static struct prestera_kern_neigh_cache *
512prestera_kern_neigh_cache_get(struct prestera_switch *sw,
513			      struct prestera_kern_neigh_cache_key *key)
514{
515	struct prestera_kern_neigh_cache *n_cache;
516
517	n_cache = prestera_kern_neigh_cache_find(sw, key);
518	if (!n_cache)
519		n_cache = __prestera_kern_neigh_cache_create(sw, key);
520
521	return n_cache;
522}
523
524static struct prestera_kern_neigh_cache *
525prestera_kern_neigh_cache_put(struct prestera_switch *sw,
526			      struct prestera_kern_neigh_cache *n_cache)
527{
528	if (!n_cache->in_kernel &&
529	    list_empty(&n_cache->kern_fib_cache_list)) {
530		__prestera_kern_neigh_cache_destroy(sw, n_cache);
531		return NULL;
532	}
533
534	return n_cache;
535}
536
537static struct prestera_kern_fib_cache *
538prestera_kern_fib_cache_find(struct prestera_switch *sw,
539			     struct prestera_kern_fib_cache_key *key)
540{
541	struct prestera_kern_fib_cache *fib_cache;
542
543	fib_cache =
544	 rhashtable_lookup_fast(&sw->router->kern_fib_cache_ht, key,
545				__prestera_kern_fib_cache_ht_params);
546	return fib_cache;
547}
548
549static void
550__prestera_kern_fib_cache_destruct(struct prestera_switch *sw,
551				   struct prestera_kern_fib_cache *fib_cache)
552{
553	struct prestera_kern_neigh_cache *n_cache;
554	int i;
555
556	for (i = 0; i < PRESTERA_NHGR_SIZE_MAX; i++) {
557		n_cache = fib_cache->kern_neigh_cache_head[i].n_cache;
558		if (n_cache) {
559			list_del(&fib_cache->kern_neigh_cache_head[i].head);
560			prestera_kern_neigh_cache_put(sw, n_cache);
561		}
562	}
563
564	fib_info_put(fib_cache->fen4_info.fi);
565}
566
567static void
568prestera_kern_fib_cache_destroy(struct prestera_switch *sw,
569				struct prestera_kern_fib_cache *fib_cache)
570{
571	rhashtable_remove_fast(&sw->router->kern_fib_cache_ht,
572			       &fib_cache->ht_node,
573			       __prestera_kern_fib_cache_ht_params);
574	__prestera_kern_fib_cache_destruct(sw, fib_cache);
575	kfree(fib_cache);
576}
577
578static int
579__prestera_kern_fib_cache_create_nhs(struct prestera_switch *sw,
580				     struct prestera_kern_fib_cache *fc)
581{
582	struct prestera_kern_neigh_cache_key nc_key;
583	struct prestera_kern_neigh_cache *n_cache;
584	struct fib_nh_common *nhc;
585	int i, nhs, err;
586
587	if (!prestera_fib_info_is_nh(&fc->info))
588		return 0;
589
590	nhs = prestera_kern_fib_info_nhs(&fc->info);
591	if (nhs > PRESTERA_NHGR_SIZE_MAX)
592		return 0;
593
594	for (i = 0; i < nhs; i++) {
595		nhc = prestera_kern_fib_info_nhc(&fc->fen4_info.info, i);
596		err = prestera_util_nhc2nc_key(sw, nhc, &nc_key);
597		if (err)
598			return 0;
599
600		n_cache = prestera_kern_neigh_cache_get(sw, &nc_key);
601		if (!n_cache)
602			return 0;
603
604		fc->kern_neigh_cache_head[i].this = fc;
605		fc->kern_neigh_cache_head[i].n_cache = n_cache;
606		list_add(&fc->kern_neigh_cache_head[i].head,
607			 &n_cache->kern_fib_cache_list);
608	}
609
610	return 0;
611}
612
613/* Operations on fi (offload, etc) must be wrapped in utils.
614 * This function just create storage.
615 */
616static struct prestera_kern_fib_cache *
617prestera_kern_fib_cache_create(struct prestera_switch *sw,
618			       struct prestera_kern_fib_cache_key *key,
619			       struct fib_notifier_info *info)
620{
621	struct fib_entry_notifier_info *fen_info =
622		container_of(info, struct fib_entry_notifier_info, info);
623	struct prestera_kern_fib_cache *fib_cache;
624	int err;
625
626	fib_cache = kzalloc(sizeof(*fib_cache), GFP_KERNEL);
627	if (!fib_cache)
628		goto err_kzalloc;
629
630	memcpy(&fib_cache->key, key, sizeof(*key));
631	fib_info_hold(fen_info->fi);
632	memcpy(&fib_cache->fen4_info, fen_info, sizeof(*fen_info));
633
634	err = rhashtable_insert_fast(&sw->router->kern_fib_cache_ht,
635				     &fib_cache->ht_node,
636				     __prestera_kern_fib_cache_ht_params);
637	if (err)
638		goto err_ht_insert;
639
640	/* Handle nexthops */
641	err = __prestera_kern_fib_cache_create_nhs(sw, fib_cache);
642	if (err)
643		goto out; /* Not critical */
644
645out:
646	return fib_cache;
647
648err_ht_insert:
649	fib_info_put(fen_info->fi);
650	kfree(fib_cache);
651err_kzalloc:
652	return NULL;
653}
654
655static void
656__prestera_k_arb_fib_nh_offload_set(struct prestera_switch *sw,
657				    struct prestera_kern_fib_cache *fibc,
658				    struct prestera_kern_neigh_cache *nc,
659				    bool offloaded, bool trap)
660{
661	struct fib_nh_common *nhc;
662	int i, nhs;
663
664	nhs = prestera_kern_fib_info_nhs(&fibc->info);
665	for (i = 0; i < nhs; i++) {
666		nhc = prestera_kern_fib_info_nhc(&fibc->info, i);
667		if (!nc) {
668			prestera_util_kern_set_nh_offload(nhc, offloaded, trap);
669			continue;
670		}
671
672		if (prestera_util_nhc_eq_n_cache_key(sw, nhc, &nc->key)) {
673			prestera_util_kern_set_nh_offload(nhc, offloaded, trap);
674			break;
675		}
676	}
677}
678
679static void
680__prestera_k_arb_n_offload_set(struct prestera_switch *sw,
681			       struct prestera_kern_neigh_cache *nc,
682			       bool offloaded)
683{
684	struct neighbour *n;
685
686	n = neigh_lookup(&arp_tbl, &nc->key.addr.u.ipv4,
687			 nc->key.dev);
688	if (!n)
689		return;
690
691	prestera_util_kern_set_neigh_offload(n, offloaded);
692	neigh_release(n);
693}
694
695static void
696__prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw,
697				     struct prestera_kern_fib_cache *fc,
698				     bool fail, bool offload, bool trap)
699{
700	struct fib_rt_info fri;
701
702	switch (fc->key.addr.v) {
703	case PRESTERA_IPV4:
704		fri.fi = fc->fen4_info.fi;
705		fri.tb_id = fc->key.kern_tb_id;
706		fri.dst = fc->key.addr.u.ipv4;
707		fri.dst_len = fc->key.prefix_len;
708		fri.dscp = fc->fen4_info.dscp;
709		fri.type = fc->fen4_info.type;
710		/* flags begin */
711		fri.offload = offload;
712		fri.trap = trap;
713		fri.offload_failed = fail;
714		/* flags end */
715		fib_alias_hw_flags_set(&init_net, &fri);
716		return;
717	case PRESTERA_IPV6:
718		/* TODO */
719		return;
720	}
721}
722
723static void
724__prestera_k_arb_n_lpm_set(struct prestera_switch *sw,
725			   struct prestera_kern_neigh_cache *n_cache,
726			   bool enabled)
727{
728	struct prestera_nexthop_group_key nh_grp_key;
729	struct prestera_kern_fib_cache_key fc_key;
730	struct prestera_kern_fib_cache *fib_cache;
731	struct prestera_fib_node *fib_node;
732	struct prestera_fib_key fib_key;
733
734	/* Exception for fc with prefix 32: LPM entry is already used by fib */
735	memset(&fc_key, 0, sizeof(fc_key));
736	fc_key.addr = n_cache->key.addr;
737	fc_key.prefix_len = PRESTERA_IP_ADDR_PLEN(n_cache->key.addr.v);
738	/* But better to use tb_id of route, which pointed to this neighbour. */
739	/* We take it from rif, because rif inconsistent.
740	 * Must be separated in_rif and out_rif.
741	 * Also note: for each fib pointed to this neigh should be separated
742	 *            neigh lpm entry (for each ingress vr)
743	 */
744	fc_key.kern_tb_id = l3mdev_fib_table(n_cache->key.dev);
745	fib_cache = prestera_kern_fib_cache_find(sw, &fc_key);
746	memset(&fib_key, 0, sizeof(fib_key));
747	fib_key.addr = n_cache->key.addr;
748	fib_key.prefix_len = PRESTERA_IP_ADDR_PLEN(n_cache->key.addr.v);
749	fib_key.tb_id = prestera_fix_tb_id(fc_key.kern_tb_id);
750	fib_node = prestera_fib_node_find(sw, &fib_key);
751	if (!fib_cache || !fib_cache->reachable) {
752		if (!enabled && fib_node) {
753			if (prestera_fib_node_util_is_neighbour(fib_node))
754				prestera_fib_node_destroy(sw, fib_node);
755			return;
756		}
757	}
758
759	if (enabled && !fib_node) {
760		memset(&nh_grp_key, 0, sizeof(nh_grp_key));
761		prestera_util_nc_key2nh_key(&n_cache->key,
762					    &nh_grp_key.neigh[0]);
763		fib_node = prestera_fib_node_create(sw, &fib_key,
764						    PRESTERA_FIB_TYPE_UC_NH,
765						    &nh_grp_key);
766		if (!fib_node)
767			pr_err("%s failed ip=%pI4n", "prestera_fib_node_create",
768			       &fib_key.addr.u.ipv4);
769		return;
770	}
771}
772
773static void
774__prestera_k_arb_nc_kern_fib_fetch(struct prestera_switch *sw,
775				   struct prestera_kern_neigh_cache *nc)
776{
777	if (prestera_util_kern_n_is_reachable(l3mdev_fib_table(nc->key.dev),
778					      &nc->key.addr, nc->key.dev))
779		nc->reachable = true;
780	else
781		nc->reachable = false;
782}
783
784/* Kernel neighbour -> neigh_cache info */
785static void
786__prestera_k_arb_nc_kern_n_fetch(struct prestera_switch *sw,
787				 struct prestera_kern_neigh_cache *nc)
788{
789	struct neighbour *n;
790	int err;
791
792	memset(&nc->nh_neigh_info, 0, sizeof(nc->nh_neigh_info));
793	n = neigh_lookup(&arp_tbl, &nc->key.addr.u.ipv4, nc->key.dev);
794	if (!n)
795		goto out;
796
797	read_lock_bh(&n->lock);
798	if (n->nud_state & NUD_VALID && !n->dead) {
799		err = prestera_neigh_iface_init(sw, &nc->nh_neigh_info.iface,
800						n);
801		if (err)
802			goto n_read_out;
803
804		memcpy(&nc->nh_neigh_info.ha[0], &n->ha[0], ETH_ALEN);
805		nc->nh_neigh_info.connected = true;
806	}
807n_read_out:
808	read_unlock_bh(&n->lock);
809out:
810	nc->in_kernel = nc->nh_neigh_info.connected;
811	if (n)
812		neigh_release(n);
813}
814
815/* neigh_cache info -> lpm update */
816static void
817__prestera_k_arb_nc_apply(struct prestera_switch *sw,
818			  struct prestera_kern_neigh_cache *nc)
819{
820	struct prestera_kern_neigh_cache_head *nhead;
821	struct prestera_nh_neigh_key nh_key;
822	struct prestera_nh_neigh *nh_neigh;
823	int err;
824
825	__prestera_k_arb_n_lpm_set(sw, nc, nc->reachable && nc->in_kernel);
826	__prestera_k_arb_n_offload_set(sw, nc, nc->reachable && nc->in_kernel);
827
828	prestera_util_nc_key2nh_key(&nc->key, &nh_key);
829	nh_neigh = prestera_nh_neigh_find(sw, &nh_key);
830	if (!nh_neigh)
831		goto out;
832
833	/* Do hw update only if something changed to prevent nh flap */
834	if (memcmp(&nc->nh_neigh_info, &nh_neigh->info,
835		   sizeof(nh_neigh->info))) {
836		memcpy(&nh_neigh->info, &nc->nh_neigh_info,
837		       sizeof(nh_neigh->info));
838		err = prestera_nh_neigh_set(sw, nh_neigh);
839		if (err) {
840			pr_err("%s failed with err=%d ip=%pI4n mac=%pM",
841			       "prestera_nh_neigh_set", err,
842			       &nh_neigh->key.addr.u.ipv4,
843			       &nh_neigh->info.ha[0]);
844			goto out;
845		}
846	}
847
848out:
849	list_for_each_entry(nhead, &nc->kern_fib_cache_list, head) {
850		__prestera_k_arb_fib_nh_offload_set(sw, nhead->this, nc,
851						    nc->in_kernel,
852						    !nc->in_kernel);
853	}
854}
855
856static int
857__prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch *sw,
858				     struct prestera_kern_fib_cache *fc)
859{
860	struct fib_nh_common *nhc;
861	int nh_cnt;
862
863	memset(&fc->lpm_info, 0, sizeof(fc->lpm_info));
864
865	switch (prestera_kern_fib_info_type(&fc->info)) {
866	case RTN_UNICAST:
867		if (prestera_fib_info_is_direct(&fc->info) &&
868		    fc->key.prefix_len ==
869			PRESTERA_IP_ADDR_PLEN(fc->key.addr.v)) {
870			/* This is special case.
871			 * When prefix is 32. Than we will have conflict in lpm
872			 * for direct route - once TRAP added, there is no
873			 * place for neighbour entry. So represent direct route
874			 * with prefix 32, as NH. So neighbour will be resolved
875			 * as nexthop of this route.
876			 */
877			nhc = prestera_kern_fib_info_nhc(&fc->info, 0);
878			fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_UC_NH;
879			fc->lpm_info.nh_grp_key.neigh[0].addr =
880				fc->key.addr;
881			fc->lpm_info.nh_grp_key.neigh[0].rif =
882				nhc->nhc_dev;
883
884			break;
885		}
886
887		/* We can also get nh_grp_key from fi. This will be correct to
888		 * because cache not always represent, what actually written to
889		 * lpm. But we use nh cache, as well for now (for this case).
890		 */
891		for (nh_cnt = 0; nh_cnt < PRESTERA_NHGR_SIZE_MAX; nh_cnt++) {
892			if (!fc->kern_neigh_cache_head[nh_cnt].n_cache)
893				break;
894
895			fc->lpm_info.nh_grp_key.neigh[nh_cnt].addr =
896				fc->kern_neigh_cache_head[nh_cnt].n_cache->key.addr;
897			fc->lpm_info.nh_grp_key.neigh[nh_cnt].rif =
898				fc->kern_neigh_cache_head[nh_cnt].n_cache->key.dev;
899		}
900
901		fc->lpm_info.fib_type = nh_cnt ?
902					PRESTERA_FIB_TYPE_UC_NH :
903					PRESTERA_FIB_TYPE_TRAP;
904		break;
905	/* Unsupported. Leave it for kernel: */
906	case RTN_BROADCAST:
907	case RTN_MULTICAST:
908	/* Routes we must trap by design: */
909	case RTN_LOCAL:
910	case RTN_UNREACHABLE:
911	case RTN_PROHIBIT:
912		fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_TRAP;
913		break;
914	case RTN_BLACKHOLE:
915		fc->lpm_info.fib_type = PRESTERA_FIB_TYPE_DROP;
916		break;
917	default:
918		dev_err(sw->dev->dev, "Unsupported fib_type");
919		return -EOPNOTSUPP;
920	}
921
922	fc->lpm_info.fib_key.addr = fc->key.addr;
923	fc->lpm_info.fib_key.prefix_len = fc->key.prefix_len;
924	fc->lpm_info.fib_key.tb_id = prestera_fix_tb_id(fc->key.kern_tb_id);
925
926	return 0;
927}
928
929static int __prestera_k_arb_f_lpm_set(struct prestera_switch *sw,
930				      struct prestera_kern_fib_cache *fc,
931				      bool enabled)
932{
933	struct prestera_fib_node *fib_node;
934
935	fib_node = prestera_fib_node_find(sw, &fc->lpm_info.fib_key);
936	if (fib_node)
937		prestera_fib_node_destroy(sw, fib_node);
938
939	if (!enabled)
940		return 0;
941
942	fib_node = prestera_fib_node_create(sw, &fc->lpm_info.fib_key,
943					    fc->lpm_info.fib_type,
944					    &fc->lpm_info.nh_grp_key);
945
946	if (!fib_node) {
947		dev_err(sw->dev->dev, "fib_node=NULL %pI4n/%d kern_tb_id = %d",
948			&fc->key.addr.u.ipv4, fc->key.prefix_len,
949			fc->key.kern_tb_id);
950		return -ENOENT;
951	}
952
953	return 0;
954}
955
956static int __prestera_k_arb_fc_apply(struct prestera_switch *sw,
957				     struct prestera_kern_fib_cache *fc)
958{
959	int err;
960
961	err = __prestera_pr_k_arb_fc_lpm_info_calc(sw, fc);
962	if (err)
963		return err;
964
965	err = __prestera_k_arb_f_lpm_set(sw, fc, fc->reachable);
966	if (err) {
967		__prestera_k_arb_fib_lpm_offload_set(sw, fc,
968						     true, false, false);
969		return err;
970	}
971
972	switch (fc->lpm_info.fib_type) {
973	case PRESTERA_FIB_TYPE_UC_NH:
974		__prestera_k_arb_fib_lpm_offload_set(sw, fc, false,
975						     fc->reachable, false);
976		break;
977	case PRESTERA_FIB_TYPE_TRAP:
978		__prestera_k_arb_fib_lpm_offload_set(sw, fc, false,
979						     false, fc->reachable);
980		break;
981	case PRESTERA_FIB_TYPE_DROP:
982		__prestera_k_arb_fib_lpm_offload_set(sw, fc, false, true,
983						     fc->reachable);
984		break;
985	case PRESTERA_FIB_TYPE_INVALID:
986		break;
987	}
988
989	return 0;
990}
991
992static struct prestera_kern_fib_cache *
993__prestera_k_arb_util_fib_overlaps(struct prestera_switch *sw,
994				   struct prestera_kern_fib_cache *fc)
995{
996	struct prestera_kern_fib_cache_key fc_key;
997	struct prestera_kern_fib_cache *rfc;
998
999	/* TODO: parse kernel rules */
1000	rfc = NULL;
1001	if (fc->key.kern_tb_id == RT_TABLE_LOCAL) {
1002		memcpy(&fc_key, &fc->key, sizeof(fc_key));
1003		fc_key.kern_tb_id = RT_TABLE_MAIN;
1004		rfc = prestera_kern_fib_cache_find(sw, &fc_key);
1005	}
1006
1007	return rfc;
1008}
1009
1010static struct prestera_kern_fib_cache *
1011__prestera_k_arb_util_fib_overlapped(struct prestera_switch *sw,
1012				     struct prestera_kern_fib_cache *fc)
1013{
1014	struct prestera_kern_fib_cache_key fc_key;
1015	struct prestera_kern_fib_cache *rfc;
1016
1017	/* TODO: parse kernel rules */
1018	rfc = NULL;
1019	if (fc->key.kern_tb_id == RT_TABLE_MAIN) {
1020		memcpy(&fc_key, &fc->key, sizeof(fc_key));
1021		fc_key.kern_tb_id = RT_TABLE_LOCAL;
1022		rfc = prestera_kern_fib_cache_find(sw, &fc_key);
1023	}
1024
1025	return rfc;
1026}
1027
1028static void __prestera_k_arb_hw_state_upd(struct prestera_switch *sw,
1029					  struct prestera_kern_neigh_cache *nc)
1030{
1031	struct prestera_nh_neigh_key nh_key;
1032	struct prestera_nh_neigh *nh_neigh;
1033	struct neighbour *n;
1034	bool hw_active;
1035
1036	prestera_util_nc_key2nh_key(&nc->key, &nh_key);
1037	nh_neigh = prestera_nh_neigh_find(sw, &nh_key);
1038	if (!nh_neigh) {
1039		pr_err("Cannot find nh_neigh for cached %pI4n",
1040		       &nc->key.addr.u.ipv4);
1041		return;
1042	}
1043
1044	hw_active = prestera_nh_neigh_util_hw_state(sw, nh_neigh);
1045
1046#ifdef PRESTERA_IMPLICITY_RESOLVE_DEAD_NEIGH
1047	if (!hw_active && nc->in_kernel)
1048		goto out;
1049#else /* PRESTERA_IMPLICITY_RESOLVE_DEAD_NEIGH */
1050	if (!hw_active)
1051		goto out;
1052#endif /* PRESTERA_IMPLICITY_RESOLVE_DEAD_NEIGH */
1053
1054	if (nc->key.addr.v == PRESTERA_IPV4) {
1055		n = neigh_lookup(&arp_tbl, &nc->key.addr.u.ipv4,
1056				 nc->key.dev);
1057		if (!n)
1058			n = neigh_create(&arp_tbl, &nc->key.addr.u.ipv4,
1059					 nc->key.dev);
1060	} else {
1061		n = NULL;
1062	}
1063
1064	if (!IS_ERR(n) && n) {
1065		neigh_event_send(n, NULL);
1066		neigh_release(n);
1067	} else {
1068		pr_err("Cannot create neighbour %pI4n", &nc->key.addr.u.ipv4);
1069	}
1070
1071out:
1072	return;
1073}
1074
1075/* Propagate hw state to kernel */
1076static void prestera_k_arb_hw_evt(struct prestera_switch *sw)
1077{
1078	struct prestera_kern_neigh_cache *n_cache;
1079	struct rhashtable_iter iter;
1080
1081	rhashtable_walk_enter(&sw->router->kern_neigh_cache_ht, &iter);
1082	rhashtable_walk_start(&iter);
1083	while (1) {
1084		n_cache = rhashtable_walk_next(&iter);
1085
1086		if (!n_cache)
1087			break;
1088
1089		if (IS_ERR(n_cache))
1090			continue;
1091
1092		rhashtable_walk_stop(&iter);
1093		__prestera_k_arb_hw_state_upd(sw, n_cache);
1094		rhashtable_walk_start(&iter);
1095	}
1096	rhashtable_walk_stop(&iter);
1097	rhashtable_walk_exit(&iter);
1098}
1099
1100/* Propagate kernel event to hw */
1101static void prestera_k_arb_n_evt(struct prestera_switch *sw,
1102				 struct neighbour *n)
1103{
1104	struct prestera_kern_neigh_cache_key n_key;
1105	struct prestera_kern_neigh_cache *n_cache;
1106	int err;
1107
1108	err = prestera_util_neigh2nc_key(sw, n, &n_key);
1109	if (err)
1110		return;
1111
1112	n_cache = prestera_kern_neigh_cache_find(sw, &n_key);
1113	if (!n_cache) {
1114		n_cache = prestera_kern_neigh_cache_get(sw, &n_key);
1115		if (!n_cache)
1116			return;
1117		__prestera_k_arb_nc_kern_fib_fetch(sw, n_cache);
1118	}
1119
1120	__prestera_k_arb_nc_kern_n_fetch(sw, n_cache);
1121	__prestera_k_arb_nc_apply(sw, n_cache);
1122
1123	prestera_kern_neigh_cache_put(sw, n_cache);
1124}
1125
1126static void __prestera_k_arb_fib_evt2nc(struct prestera_switch *sw)
1127{
1128	struct prestera_kern_neigh_cache *n_cache;
1129	struct rhashtable_iter iter;
1130
1131	rhashtable_walk_enter(&sw->router->kern_neigh_cache_ht, &iter);
1132	rhashtable_walk_start(&iter);
1133	while (1) {
1134		n_cache = rhashtable_walk_next(&iter);
1135
1136		if (!n_cache)
1137			break;
1138
1139		if (IS_ERR(n_cache))
1140			continue;
1141
1142		rhashtable_walk_stop(&iter);
1143		__prestera_k_arb_nc_kern_fib_fetch(sw, n_cache);
1144		__prestera_k_arb_nc_apply(sw, n_cache);
1145		rhashtable_walk_start(&iter);
1146	}
1147	rhashtable_walk_stop(&iter);
1148	rhashtable_walk_exit(&iter);
1149}
1150
1151static int
1152prestera_k_arb_fib_evt(struct prestera_switch *sw,
1153		       bool replace, /* replace or del */
1154		       struct fib_notifier_info *info)
1155{
1156	struct prestera_kern_fib_cache *tfib_cache, *bfib_cache; /* top/btm */
1157	struct prestera_kern_fib_cache_key fc_key;
1158	struct prestera_kern_fib_cache *fib_cache;
1159	int err;
1160
1161	prestera_util_fen_info2fib_cache_key(info, &fc_key);
1162	fib_cache = prestera_kern_fib_cache_find(sw, &fc_key);
1163	if (fib_cache) {
1164		fib_cache->reachable = false;
1165		err = __prestera_k_arb_fc_apply(sw, fib_cache);
1166		if (err)
1167			dev_err(sw->dev->dev,
1168				"Applying destroyed fib_cache failed");
1169
1170		bfib_cache = __prestera_k_arb_util_fib_overlaps(sw, fib_cache);
1171		tfib_cache = __prestera_k_arb_util_fib_overlapped(sw, fib_cache);
1172		if (!tfib_cache && bfib_cache) {
1173			bfib_cache->reachable = true;
1174			err = __prestera_k_arb_fc_apply(sw, bfib_cache);
1175			if (err)
1176				dev_err(sw->dev->dev,
1177					"Applying fib_cache btm failed");
1178		}
1179
1180		prestera_kern_fib_cache_destroy(sw, fib_cache);
1181	}
1182
1183	if (replace) {
1184		fib_cache = prestera_kern_fib_cache_create(sw, &fc_key, info);
1185		if (!fib_cache) {
1186			dev_err(sw->dev->dev, "fib_cache == NULL");
1187			return -ENOENT;
1188		}
1189
1190		bfib_cache = __prestera_k_arb_util_fib_overlaps(sw, fib_cache);
1191		tfib_cache = __prestera_k_arb_util_fib_overlapped(sw, fib_cache);
1192		if (!tfib_cache)
1193			fib_cache->reachable = true;
1194
1195		if (bfib_cache) {
1196			bfib_cache->reachable = false;
1197			err = __prestera_k_arb_fc_apply(sw, bfib_cache);
1198			if (err)
1199				dev_err(sw->dev->dev,
1200					"Applying fib_cache btm failed");
1201		}
1202
1203		err = __prestera_k_arb_fc_apply(sw, fib_cache);
1204		if (err)
1205			dev_err(sw->dev->dev, "Applying fib_cache failed");
1206	}
1207
1208	/* Update all neighs to resolve overlapped and apply related */
1209	__prestera_k_arb_fib_evt2nc(sw);
1210
1211	return 0;
1212}
1213
1214static void __prestera_k_arb_abort_neigh_ht_cb(void *ptr, void *arg)
1215{
1216	struct prestera_kern_neigh_cache *n_cache = ptr;
1217	struct prestera_switch *sw = arg;
1218
1219	if (!list_empty(&n_cache->kern_fib_cache_list)) {
1220		WARN_ON(1); /* BUG */
1221		return;
1222	}
1223	__prestera_k_arb_n_offload_set(sw, n_cache, false);
1224	n_cache->in_kernel = false;
1225	/* No need to destroy lpm.
1226	 * It will be aborted by destroy_ht
1227	 */
1228	__prestera_kern_neigh_cache_destruct(sw, n_cache);
1229	kfree(n_cache);
1230}
1231
1232static void __prestera_k_arb_abort_fib_ht_cb(void *ptr, void *arg)
1233{
1234	struct prestera_kern_fib_cache *fib_cache = ptr;
1235	struct prestera_switch *sw = arg;
1236
1237	__prestera_k_arb_fib_lpm_offload_set(sw, fib_cache,
1238					     false, false,
1239					     false);
1240	__prestera_k_arb_fib_nh_offload_set(sw, fib_cache, NULL,
1241					    false, false);
1242	/* No need to destroy lpm.
1243	 * It will be aborted by destroy_ht
1244	 */
1245	__prestera_kern_fib_cache_destruct(sw, fib_cache);
1246	kfree(fib_cache);
1247}
1248
1249static void prestera_k_arb_abort(struct prestera_switch *sw)
1250{
1251	/* Function to remove all arbiter entries and related hw objects. */
1252	/* Sequence:
1253	 *   1) Clear arbiter tables, but don't touch hw
1254	 *   2) Clear hw
1255	 * We use such approach, because arbiter object is not directly mapped
1256	 * to hw. So deletion of one arbiter object may even lead to creation of
1257	 * hw object (e.g. in case of overlapped routes).
1258	 */
1259	rhashtable_free_and_destroy(&sw->router->kern_fib_cache_ht,
1260				    __prestera_k_arb_abort_fib_ht_cb,
1261				    sw);
1262	rhashtable_free_and_destroy(&sw->router->kern_neigh_cache_ht,
1263				    __prestera_k_arb_abort_neigh_ht_cb,
1264				    sw);
1265}
1266
1267static int __prestera_inetaddr_port_event(struct net_device *port_dev,
1268					  unsigned long event,
1269					  struct netlink_ext_ack *extack)
1270{
1271	struct prestera_port *port = netdev_priv(port_dev);
1272	struct prestera_rif_entry_key re_key = {};
1273	struct prestera_rif_entry *re;
1274	u32 kern_tb_id;
1275	int err;
1276
1277	err = prestera_is_valid_mac_addr(port, port_dev->dev_addr);
1278	if (err) {
1279		NL_SET_ERR_MSG_MOD(extack, "RIF MAC must have the same prefix");
1280		return err;
1281	}
1282
1283	kern_tb_id = l3mdev_fib_table(port_dev);
1284	re_key.iface.type = PRESTERA_IF_PORT_E;
1285	re_key.iface.dev_port.hw_dev_num  = port->dev_id;
1286	re_key.iface.dev_port.port_num  = port->hw_id;
1287	re = prestera_rif_entry_find(port->sw, &re_key);
1288
1289	switch (event) {
1290	case NETDEV_UP:
1291		if (re) {
1292			NL_SET_ERR_MSG_MOD(extack, "RIF already exist");
1293			return -EEXIST;
1294		}
1295		re = prestera_rif_entry_create(port->sw, &re_key,
1296					       prestera_fix_tb_id(kern_tb_id),
1297					       port_dev->dev_addr);
1298		if (!re) {
1299			NL_SET_ERR_MSG_MOD(extack, "Can't create RIF");
1300			return -EINVAL;
1301		}
1302		dev_hold(port_dev);
1303		break;
1304	case NETDEV_DOWN:
1305		if (!re) {
1306			NL_SET_ERR_MSG_MOD(extack, "Can't find RIF");
1307			return -EEXIST;
1308		}
1309		prestera_rif_entry_destroy(port->sw, re);
1310		dev_put(port_dev);
1311		break;
1312	}
1313
1314	return 0;
1315}
1316
1317static int __prestera_inetaddr_event(struct prestera_switch *sw,
1318				     struct net_device *dev,
1319				     unsigned long event,
1320				     struct netlink_ext_ack *extack)
1321{
1322	if (!prestera_netdev_check(dev) || netif_is_any_bridge_port(dev) ||
1323	    netif_is_lag_port(dev))
1324		return 0;
1325
1326	return __prestera_inetaddr_port_event(dev, event, extack);
1327}
1328
1329static int __prestera_inetaddr_cb(struct notifier_block *nb,
1330				  unsigned long event, void *ptr)
1331{
1332	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
1333	struct net_device *dev = ifa->ifa_dev->dev;
1334	struct prestera_router *router = container_of(nb,
1335						      struct prestera_router,
1336						      inetaddr_nb);
1337	struct in_device *idev;
1338	int err = 0;
1339
1340	if (event != NETDEV_DOWN)
1341		goto out;
1342
1343	/* Ignore if this is not latest address */
1344	idev = __in_dev_get_rtnl(dev);
1345	if (idev && idev->ifa_list)
1346		goto out;
1347
1348	err = __prestera_inetaddr_event(router->sw, dev, event, NULL);
1349out:
1350	return notifier_from_errno(err);
1351}
1352
1353static int __prestera_inetaddr_valid_cb(struct notifier_block *nb,
1354					unsigned long event, void *ptr)
1355{
1356	struct in_validator_info *ivi = (struct in_validator_info *)ptr;
1357	struct net_device *dev = ivi->ivi_dev->dev;
1358	struct prestera_router *router = container_of(nb,
1359						      struct prestera_router,
1360						      inetaddr_valid_nb);
1361	struct in_device *idev;
1362	int err = 0;
1363
1364	if (event != NETDEV_UP)
1365		goto out;
1366
1367	/* Ignore if this is not first address */
1368	idev = __in_dev_get_rtnl(dev);
1369	if (idev && idev->ifa_list)
1370		goto out;
1371
1372	if (ipv4_is_multicast(ivi->ivi_addr)) {
1373		NL_SET_ERR_MSG_MOD(ivi->extack,
1374				   "Multicast addr on RIF is not supported");
1375		err = -EINVAL;
1376		goto out;
1377	}
1378
1379	err = __prestera_inetaddr_event(router->sw, dev, event, ivi->extack);
1380out:
1381	return notifier_from_errno(err);
1382}
1383
1384struct prestera_fib_event_work {
1385	struct work_struct work;
1386	struct prestera_switch *sw;
1387	struct fib_entry_notifier_info fen_info;
1388	unsigned long event;
1389};
1390
1391static void __prestera_router_fib_event_work(struct work_struct *work)
1392{
1393	struct prestera_fib_event_work *fib_work =
1394			container_of(work, struct prestera_fib_event_work, work);
1395	struct prestera_switch *sw = fib_work->sw;
1396	int err;
1397
1398	rtnl_lock();
1399
1400	switch (fib_work->event) {
1401	case FIB_EVENT_ENTRY_REPLACE:
1402		err = prestera_k_arb_fib_evt(sw, true,
1403					     &fib_work->fen_info.info);
1404		if (err)
1405			goto err_out;
1406
1407		break;
1408	case FIB_EVENT_ENTRY_DEL:
1409		err = prestera_k_arb_fib_evt(sw, false,
1410					     &fib_work->fen_info.info);
1411		if (err)
1412			goto err_out;
1413
1414		break;
1415	}
1416
1417	goto out;
1418
1419err_out:
1420	dev_err(sw->dev->dev, "Error when processing %pI4h/%d",
1421		&fib_work->fen_info.dst,
1422		fib_work->fen_info.dst_len);
1423out:
1424	fib_info_put(fib_work->fen_info.fi);
1425	rtnl_unlock();
1426	kfree(fib_work);
1427}
1428
1429/* Called with rcu_read_lock() */
1430static int __prestera_router_fib_event(struct notifier_block *nb,
1431				       unsigned long event, void *ptr)
1432{
1433	struct prestera_fib_event_work *fib_work;
1434	struct fib_entry_notifier_info *fen_info;
1435	struct fib_notifier_info *info = ptr;
1436	struct prestera_router *router;
1437
1438	if (info->family != AF_INET)
1439		return NOTIFY_DONE;
1440
1441	router = container_of(nb, struct prestera_router, fib_nb);
1442
1443	switch (event) {
1444	case FIB_EVENT_ENTRY_REPLACE:
1445	case FIB_EVENT_ENTRY_DEL:
1446		fen_info = container_of(info, struct fib_entry_notifier_info,
1447					info);
1448		if (!fen_info->fi)
1449			return NOTIFY_DONE;
1450
1451		fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
1452		if (WARN_ON(!fib_work))
1453			return NOTIFY_BAD;
1454
1455		fib_info_hold(fen_info->fi);
1456		fib_work->fen_info = *fen_info;
1457		fib_work->event = event;
1458		fib_work->sw = router->sw;
1459		INIT_WORK(&fib_work->work, __prestera_router_fib_event_work);
1460		prestera_queue_work(&fib_work->work);
1461		break;
1462	default:
1463		return NOTIFY_DONE;
1464	}
1465
1466	return NOTIFY_DONE;
1467}
1468
1469struct prestera_netevent_work {
1470	struct work_struct work;
1471	struct prestera_switch *sw;
1472	struct neighbour *n;
1473};
1474
1475static void prestera_router_neigh_event_work(struct work_struct *work)
1476{
1477	struct prestera_netevent_work *net_work =
1478		container_of(work, struct prestera_netevent_work, work);
1479	struct prestera_switch *sw = net_work->sw;
1480	struct neighbour *n = net_work->n;
1481
1482	/* neigh - its not hw related object. It stored only in kernel. So... */
1483	rtnl_lock();
1484
1485	prestera_k_arb_n_evt(sw, n);
1486
1487	neigh_release(n);
1488	rtnl_unlock();
1489	kfree(net_work);
1490}
1491
1492static int prestera_router_netevent_event(struct notifier_block *nb,
1493					  unsigned long event, void *ptr)
1494{
1495	struct prestera_netevent_work *net_work;
1496	struct prestera_router *router;
1497	struct neighbour *n = ptr;
1498
1499	router = container_of(nb, struct prestera_router, netevent_nb);
1500
1501	switch (event) {
1502	case NETEVENT_NEIGH_UPDATE:
1503		if (n->tbl->family != AF_INET)
1504			return NOTIFY_DONE;
1505
1506		net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
1507		if (WARN_ON(!net_work))
1508			return NOTIFY_BAD;
1509
1510		neigh_clone(n);
1511		net_work->n = n;
1512		net_work->sw = router->sw;
1513		INIT_WORK(&net_work->work, prestera_router_neigh_event_work);
1514		prestera_queue_work(&net_work->work);
1515	}
1516
1517	return NOTIFY_DONE;
1518}
1519
1520static void prestera_router_update_neighs_work(struct work_struct *work)
1521{
1522	struct prestera_router *router;
1523
1524	router = container_of(work, struct prestera_router,
1525			      neighs_update.dw.work);
1526	rtnl_lock();
1527
1528	prestera_k_arb_hw_evt(router->sw);
1529
1530	rtnl_unlock();
1531	prestera_queue_delayed_work(&router->neighs_update.dw,
1532				    msecs_to_jiffies(PRESTERA_NH_PROBE_INTERVAL));
1533}
1534
1535static int prestera_neigh_work_init(struct prestera_switch *sw)
1536{
1537	INIT_DELAYED_WORK(&sw->router->neighs_update.dw,
1538			  prestera_router_update_neighs_work);
1539	prestera_queue_delayed_work(&sw->router->neighs_update.dw, 0);
1540	return 0;
1541}
1542
1543static void prestera_neigh_work_fini(struct prestera_switch *sw)
1544{
1545	cancel_delayed_work_sync(&sw->router->neighs_update.dw);
1546}
1547
1548int prestera_router_init(struct prestera_switch *sw)
1549{
1550	struct prestera_router *router;
1551	int err, nhgrp_cache_bytes;
1552
1553	router = kzalloc(sizeof(*sw->router), GFP_KERNEL);
1554	if (!router)
1555		return -ENOMEM;
1556
1557	sw->router = router;
1558	router->sw = sw;
1559
1560	err = prestera_router_hw_init(sw);
1561	if (err)
1562		goto err_router_lib_init;
1563
1564	err = rhashtable_init(&router->kern_fib_cache_ht,
1565			      &__prestera_kern_fib_cache_ht_params);
1566	if (err)
1567		goto err_kern_fib_cache_ht_init;
1568
1569	err = rhashtable_init(&router->kern_neigh_cache_ht,
1570			      &__prestera_kern_neigh_cache_ht_params);
1571	if (err)
1572		goto err_kern_neigh_cache_ht_init;
1573
1574	nhgrp_cache_bytes = sw->size_tbl_router_nexthop / 8 + 1;
1575	router->nhgrp_hw_state_cache = kzalloc(nhgrp_cache_bytes, GFP_KERNEL);
1576	if (!router->nhgrp_hw_state_cache) {
1577		err = -ENOMEM;
1578		goto err_nh_state_cache_alloc;
1579	}
1580
1581	err = prestera_neigh_work_init(sw);
1582	if (err)
1583		goto err_neigh_work_init;
1584
1585	router->inetaddr_valid_nb.notifier_call = __prestera_inetaddr_valid_cb;
1586	err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
1587	if (err)
1588		goto err_register_inetaddr_validator_notifier;
1589
1590	router->inetaddr_nb.notifier_call = __prestera_inetaddr_cb;
1591	err = register_inetaddr_notifier(&router->inetaddr_nb);
1592	if (err)
1593		goto err_register_inetaddr_notifier;
1594
1595	router->netevent_nb.notifier_call = prestera_router_netevent_event;
1596	err = register_netevent_notifier(&router->netevent_nb);
1597	if (err)
1598		goto err_register_netevent_notifier;
1599
1600	router->fib_nb.notifier_call = __prestera_router_fib_event;
1601	err = register_fib_notifier(&init_net, &router->fib_nb,
1602				    /* TODO: flush fib entries */ NULL, NULL);
1603	if (err)
1604		goto err_register_fib_notifier;
1605
1606	return 0;
1607
1608err_register_fib_notifier:
1609	unregister_netevent_notifier(&router->netevent_nb);
1610err_register_netevent_notifier:
1611	unregister_inetaddr_notifier(&router->inetaddr_nb);
1612err_register_inetaddr_notifier:
1613	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
1614err_register_inetaddr_validator_notifier:
1615	prestera_neigh_work_fini(sw);
1616err_neigh_work_init:
1617	kfree(router->nhgrp_hw_state_cache);
1618err_nh_state_cache_alloc:
1619	rhashtable_destroy(&router->kern_neigh_cache_ht);
1620err_kern_neigh_cache_ht_init:
1621	rhashtable_destroy(&router->kern_fib_cache_ht);
1622err_kern_fib_cache_ht_init:
1623	prestera_router_hw_fini(sw);
1624err_router_lib_init:
1625	kfree(sw->router);
1626	return err;
1627}
1628
1629void prestera_router_fini(struct prestera_switch *sw)
1630{
1631	unregister_fib_notifier(&init_net, &sw->router->fib_nb);
1632	unregister_netevent_notifier(&sw->router->netevent_nb);
1633	unregister_inetaddr_notifier(&sw->router->inetaddr_nb);
1634	unregister_inetaddr_validator_notifier(&sw->router->inetaddr_valid_nb);
1635	prestera_neigh_work_fini(sw);
1636	prestera_queue_drain();
1637
1638	prestera_k_arb_abort(sw);
1639
1640	kfree(sw->router->nhgrp_hw_state_cache);
1641	rhashtable_destroy(&sw->router->kern_fib_cache_ht);
1642	prestera_router_hw_fini(sw);
1643	kfree(sw->router);
1644	sw->router = NULL;
1645}
1646