Linux 6.9-rc1
[linux-2.6-microblaze.git] / drivers / net / ethernet / marvell / prestera / prestera_router.c
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 */
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
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
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
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
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
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
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
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
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
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
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
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
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
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() */
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
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
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
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
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 *
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
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
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
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
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
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 *
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
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
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 *
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 *
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 *
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 *
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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 */
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 */
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
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
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
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
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
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
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
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
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
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
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() */
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
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
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
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
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
1543 static void prestera_neigh_work_fini(struct prestera_switch *sw)
1544 {
1545         cancel_delayed_work_sync(&sw->router->neighs_update.dw);
1546 }
1547
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
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 }