• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 struct prestera_kern_neigh_cache_key {
23 	struct prestera_ip_addr addr;
24 	struct net_device *dev;
25 };
26 
27 struct 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 
39 struct 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 */
46 struct 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 
67 static 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 
74 static 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 */
prestera_fix_tb_id(u32 tb_id)82 static 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 
92 static void
prestera_util_fen_info2fib_cache_key(struct fib_notifier_info * info,struct prestera_kern_fib_cache_key * key)93 prestera_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 
prestera_util_nhc2nc_key(struct prestera_switch * sw,struct fib_nh_common * nhc,struct prestera_kern_neigh_cache_key * nk)106 static 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 
123 static void
prestera_util_nc_key2nh_key(struct prestera_kern_neigh_cache_key * ck,struct prestera_nh_neigh_key * nk)124 prestera_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 
132 static bool
prestera_util_nhc_eq_n_cache_key(struct prestera_switch * sw,struct fib_nh_common * nhc,struct prestera_kern_neigh_cache_key * nk)133 prestera_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 
150 static int
prestera_util_neigh2nc_key(struct prestera_switch * sw,struct neighbour * n,struct prestera_kern_neigh_cache_key * key)151 prestera_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 
__prestera_fi_is_direct(struct fib_info * fi)167 static 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 
prestera_fi_is_direct(struct fib_info * fi)180 static 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 
prestera_fi_is_nh(struct fib_info * fi)188 static 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 
__prestera_fi6_is_direct(struct fib6_info * fi)196 static 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 
prestera_fi6_is_direct(struct fib6_info * fi)204 static 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 
prestera_fi6_is_nh(struct fib6_info * fi)212 static 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 
prestera_fib_info_is_direct(struct fib_notifier_info * info)220 static 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 
prestera_fib_info_is_nh(struct fib_notifier_info * info)233 static 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() */
prestera_util_kern_get_route(struct fib_result * res,u32 tb_id,__be32 * addr)247 static 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 
260 static bool
__prestera_util_kern_n_is_reachable_v4(u32 tb_id,__be32 * addr,struct net_device * dev)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 */
281 static bool
prestera_util_kern_n_is_reachable(u32 tb_id,struct prestera_ip_addr * addr,struct net_device * dev)282 prestera_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 
prestera_util_kern_set_neigh_offload(struct neighbour * n,bool offloaded)294 static 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 
303 static void
prestera_util_kern_set_nh_offload(struct fib_nh_common * nhc,bool offloaded,bool trap)304 prestera_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 
317 static struct fib_nh_common *
prestera_kern_fib_info_nhc(struct fib_notifier_info * info,int n)318 prestera_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 
prestera_kern_fib_info_nhs(struct fib_notifier_info * info)350 static 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 
368 static unsigned char
prestera_kern_fib_info_type(struct fib_notifier_info * info)369 prestera_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 */
391 static bool
prestera_fib_node_util_is_neighbour(struct prestera_fib_node * fib_node)392 prestera_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 
prestera_dev_if_type(const struct net_device * dev)410 static 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 
429 static int
prestera_neigh_iface_init(struct prestera_switch * sw,struct prestera_iface * iface,struct neighbour * n)430 prestera_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 
451 static struct prestera_kern_neigh_cache *
prestera_kern_neigh_cache_find(struct prestera_switch * sw,struct prestera_kern_neigh_cache_key * key)452 prestera_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 
463 static void
__prestera_kern_neigh_cache_destruct(struct prestera_switch * sw,struct prestera_kern_neigh_cache * n_cache)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 
470 static void
__prestera_kern_neigh_cache_destroy(struct prestera_switch * sw,struct prestera_kern_neigh_cache * n_cache)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 
481 static struct prestera_kern_neigh_cache *
__prestera_kern_neigh_cache_create(struct prestera_switch * sw,struct prestera_kern_neigh_cache_key * key)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 
504 err_ht_insert:
505 	dev_put(n_cache->key.dev);
506 	kfree(n_cache);
507 err_kzalloc:
508 	return NULL;
509 }
510 
511 static struct prestera_kern_neigh_cache *
prestera_kern_neigh_cache_get(struct prestera_switch * sw,struct prestera_kern_neigh_cache_key * key)512 prestera_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 
524 static struct prestera_kern_neigh_cache *
prestera_kern_neigh_cache_put(struct prestera_switch * sw,struct prestera_kern_neigh_cache * n_cache)525 prestera_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 
537 static struct prestera_kern_fib_cache *
prestera_kern_fib_cache_find(struct prestera_switch * sw,struct prestera_kern_fib_cache_key * key)538 prestera_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 
549 static void
__prestera_kern_fib_cache_destruct(struct prestera_switch * sw,struct prestera_kern_fib_cache * fib_cache)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 
567 static void
prestera_kern_fib_cache_destroy(struct prestera_switch * sw,struct prestera_kern_fib_cache * fib_cache)568 prestera_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 
578 static int
__prestera_kern_fib_cache_create_nhs(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc)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  */
616 static struct prestera_kern_fib_cache *
prestera_kern_fib_cache_create(struct prestera_switch * sw,struct prestera_kern_fib_cache_key * key,struct fib_notifier_info * info)617 prestera_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 
645 out:
646 	return fib_cache;
647 
648 err_ht_insert:
649 	fib_info_put(fen_info->fi);
650 	kfree(fib_cache);
651 err_kzalloc:
652 	return NULL;
653 }
654 
655 static void
__prestera_k_arb_fib_nh_offload_set(struct prestera_switch * sw,struct prestera_kern_fib_cache * fibc,struct prestera_kern_neigh_cache * nc,bool offloaded,bool trap)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 
679 static void
__prestera_k_arb_n_offload_set(struct prestera_switch * sw,struct prestera_kern_neigh_cache * nc,bool offloaded)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 
695 static void
__prestera_k_arb_fib_lpm_offload_set(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc,bool fail,bool offload,bool trap)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 
723 static void
__prestera_k_arb_n_lpm_set(struct prestera_switch * sw,struct prestera_kern_neigh_cache * n_cache,bool enabled)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 
773 static void
__prestera_k_arb_nc_kern_fib_fetch(struct prestera_switch * sw,struct prestera_kern_neigh_cache * nc)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 */
785 static void
__prestera_k_arb_nc_kern_n_fetch(struct prestera_switch * sw,struct prestera_kern_neigh_cache * nc)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 	}
807 n_read_out:
808 	read_unlock_bh(&n->lock);
809 out:
810 	nc->in_kernel = nc->nh_neigh_info.connected;
811 	if (n)
812 		neigh_release(n);
813 }
814 
815 /* neigh_cache info -> lpm update */
816 static void
__prestera_k_arb_nc_apply(struct prestera_switch * sw,struct prestera_kern_neigh_cache * nc)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 
848 out:
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 
856 static int
__prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc)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 
__prestera_k_arb_f_lpm_set(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc,bool enabled)929 static 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 
__prestera_k_arb_fc_apply(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc)956 static 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 
992 static struct prestera_kern_fib_cache *
__prestera_k_arb_util_fib_overlaps(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc)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 
1010 static struct prestera_kern_fib_cache *
__prestera_k_arb_util_fib_overlapped(struct prestera_switch * sw,struct prestera_kern_fib_cache * fc)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 
__prestera_k_arb_hw_state_upd(struct prestera_switch * sw,struct prestera_kern_neigh_cache * nc)1028 static 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 
1071 out:
1072 	return;
1073 }
1074 
1075 /* Propagate hw state to kernel */
prestera_k_arb_hw_evt(struct prestera_switch * sw)1076 static 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 */
prestera_k_arb_n_evt(struct prestera_switch * sw,struct neighbour * n)1101 static 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 
__prestera_k_arb_fib_evt2nc(struct prestera_switch * sw)1126 static 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 
1151 static int
prestera_k_arb_fib_evt(struct prestera_switch * sw,bool replace,struct fib_notifier_info * info)1152 prestera_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 
__prestera_k_arb_abort_neigh_ht_cb(void * ptr,void * arg)1214 static 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 
__prestera_k_arb_abort_fib_ht_cb(void * ptr,void * arg)1232 static 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 
prestera_k_arb_abort(struct prestera_switch * sw)1249 static 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 
__prestera_inetaddr_port_event(struct net_device * port_dev,unsigned long event,struct netlink_ext_ack * extack)1267 static 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 
__prestera_inetaddr_event(struct prestera_switch * sw,struct net_device * dev,unsigned long event,struct netlink_ext_ack * extack)1317 static 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 
__prestera_inetaddr_cb(struct notifier_block * nb,unsigned long event,void * ptr)1329 static 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);
1349 out:
1350 	return notifier_from_errno(err);
1351 }
1352 
__prestera_inetaddr_valid_cb(struct notifier_block * nb,unsigned long event,void * ptr)1353 static 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);
1380 out:
1381 	return notifier_from_errno(err);
1382 }
1383 
1384 struct 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 
__prestera_router_fib_event_work(struct work_struct * work)1391 static 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 
1419 err_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);
1423 out:
1424 	fib_info_put(fib_work->fen_info.fi);
1425 	rtnl_unlock();
1426 	kfree(fib_work);
1427 }
1428 
1429 /* Called with rcu_read_lock() */
__prestera_router_fib_event(struct notifier_block * nb,unsigned long event,void * ptr)1430 static 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 
1469 struct prestera_netevent_work {
1470 	struct work_struct work;
1471 	struct prestera_switch *sw;
1472 	struct neighbour *n;
1473 };
1474 
prestera_router_neigh_event_work(struct work_struct * work)1475 static 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 
prestera_router_netevent_event(struct notifier_block * nb,unsigned long event,void * ptr)1492 static 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 
prestera_router_update_neighs_work(struct work_struct * work)1520 static 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 
prestera_neigh_work_init(struct prestera_switch * sw)1535 static 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 
prestera_neigh_work_fini(struct prestera_switch * sw)1543 static void prestera_neigh_work_fini(struct prestera_switch *sw)
1544 {
1545 	cancel_delayed_work_sync(&sw->router->neighs_update.dw);
1546 }
1547 
prestera_router_init(struct prestera_switch * sw)1548 int 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 
1608 err_register_fib_notifier:
1609 	unregister_netevent_notifier(&router->netevent_nb);
1610 err_register_netevent_notifier:
1611 	unregister_inetaddr_notifier(&router->inetaddr_nb);
1612 err_register_inetaddr_notifier:
1613 	unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb);
1614 err_register_inetaddr_validator_notifier:
1615 	prestera_neigh_work_fini(sw);
1616 err_neigh_work_init:
1617 	kfree(router->nhgrp_hw_state_cache);
1618 err_nh_state_cache_alloc:
1619 	rhashtable_destroy(&router->kern_neigh_cache_ht);
1620 err_kern_neigh_cache_ht_init:
1621 	rhashtable_destroy(&router->kern_fib_cache_ht);
1622 err_kern_fib_cache_ht_init:
1623 	prestera_router_hw_fini(sw);
1624 err_router_lib_init:
1625 	kfree(sw->router);
1626 	return err;
1627 }
1628 
prestera_router_fini(struct prestera_switch * sw)1629 void 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