Merge tag 'iwlwifi-for-kalle-2017-09-15' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_router.c
1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
3  * Copyright (c) 2016-2017 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5  * Copyright (c) 2016 Ido Schimmel <idosch@mellanox.com>
6  * Copyright (c) 2016 Yotam Gigi <yotamg@mellanox.com>
7  * Copyright (c) 2017 Petr Machata <petrm@mellanox.com>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the names of the copyright holders nor the names of its
18  *    contributors may be used to endorse or promote products derived from
19  *    this software without specific prior written permission.
20  *
21  * Alternatively, this software may be distributed under the terms of the
22  * GNU General Public License ("GPL") version 2 as published by the Free
23  * Software Foundation.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37
38 #include <linux/kernel.h>
39 #include <linux/types.h>
40 #include <linux/rhashtable.h>
41 #include <linux/bitops.h>
42 #include <linux/in6.h>
43 #include <linux/notifier.h>
44 #include <linux/inetdevice.h>
45 #include <linux/netdevice.h>
46 #include <linux/if_bridge.h>
47 #include <linux/socket.h>
48 #include <linux/route.h>
49 #include <net/netevent.h>
50 #include <net/neighbour.h>
51 #include <net/arp.h>
52 #include <net/ip_fib.h>
53 #include <net/ip6_fib.h>
54 #include <net/fib_rules.h>
55 #include <net/ip_tunnels.h>
56 #include <net/l3mdev.h>
57 #include <net/addrconf.h>
58 #include <net/ndisc.h>
59 #include <net/ipv6.h>
60 #include <net/fib_notifier.h>
61
62 #include "spectrum.h"
63 #include "core.h"
64 #include "reg.h"
65 #include "spectrum_cnt.h"
66 #include "spectrum_dpipe.h"
67 #include "spectrum_ipip.h"
68 #include "spectrum_router.h"
69
70 struct mlxsw_sp_vr;
71 struct mlxsw_sp_lpm_tree;
72 struct mlxsw_sp_rif_ops;
73
74 struct mlxsw_sp_router {
75         struct mlxsw_sp *mlxsw_sp;
76         struct mlxsw_sp_rif **rifs;
77         struct mlxsw_sp_vr *vrs;
78         struct rhashtable neigh_ht;
79         struct rhashtable nexthop_group_ht;
80         struct rhashtable nexthop_ht;
81         struct {
82                 struct mlxsw_sp_lpm_tree *trees;
83                 unsigned int tree_count;
84         } lpm;
85         struct {
86                 struct delayed_work dw;
87                 unsigned long interval; /* ms */
88         } neighs_update;
89         struct delayed_work nexthop_probe_dw;
90 #define MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL 5000 /* ms */
91         struct list_head nexthop_neighs_list;
92         struct list_head ipip_list;
93         bool aborted;
94         struct notifier_block fib_nb;
95         const struct mlxsw_sp_rif_ops **rif_ops_arr;
96         const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
97 };
98
99 struct mlxsw_sp_rif {
100         struct list_head nexthop_list;
101         struct list_head neigh_list;
102         struct net_device *dev;
103         struct mlxsw_sp_fid *fid;
104         unsigned char addr[ETH_ALEN];
105         int mtu;
106         u16 rif_index;
107         u16 vr_id;
108         const struct mlxsw_sp_rif_ops *ops;
109         struct mlxsw_sp *mlxsw_sp;
110
111         unsigned int counter_ingress;
112         bool counter_ingress_valid;
113         unsigned int counter_egress;
114         bool counter_egress_valid;
115 };
116
117 struct mlxsw_sp_rif_params {
118         struct net_device *dev;
119         union {
120                 u16 system_port;
121                 u16 lag_id;
122         };
123         u16 vid;
124         bool lag;
125 };
126
127 struct mlxsw_sp_rif_subport {
128         struct mlxsw_sp_rif common;
129         union {
130                 u16 system_port;
131                 u16 lag_id;
132         };
133         u16 vid;
134         bool lag;
135 };
136
137 struct mlxsw_sp_rif_ipip_lb {
138         struct mlxsw_sp_rif common;
139         struct mlxsw_sp_rif_ipip_lb_config lb_config;
140         u16 ul_vr_id; /* Reserved for Spectrum-2. */
141 };
142
143 struct mlxsw_sp_rif_params_ipip_lb {
144         struct mlxsw_sp_rif_params common;
145         struct mlxsw_sp_rif_ipip_lb_config lb_config;
146 };
147
148 struct mlxsw_sp_rif_ops {
149         enum mlxsw_sp_rif_type type;
150         size_t rif_size;
151
152         void (*setup)(struct mlxsw_sp_rif *rif,
153                       const struct mlxsw_sp_rif_params *params);
154         int (*configure)(struct mlxsw_sp_rif *rif);
155         void (*deconfigure)(struct mlxsw_sp_rif *rif);
156         struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif);
157 };
158
159 static unsigned int *
160 mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif *rif,
161                            enum mlxsw_sp_rif_counter_dir dir)
162 {
163         switch (dir) {
164         case MLXSW_SP_RIF_COUNTER_EGRESS:
165                 return &rif->counter_egress;
166         case MLXSW_SP_RIF_COUNTER_INGRESS:
167                 return &rif->counter_ingress;
168         }
169         return NULL;
170 }
171
172 static bool
173 mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif *rif,
174                                enum mlxsw_sp_rif_counter_dir dir)
175 {
176         switch (dir) {
177         case MLXSW_SP_RIF_COUNTER_EGRESS:
178                 return rif->counter_egress_valid;
179         case MLXSW_SP_RIF_COUNTER_INGRESS:
180                 return rif->counter_ingress_valid;
181         }
182         return false;
183 }
184
185 static void
186 mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif *rif,
187                                enum mlxsw_sp_rif_counter_dir dir,
188                                bool valid)
189 {
190         switch (dir) {
191         case MLXSW_SP_RIF_COUNTER_EGRESS:
192                 rif->counter_egress_valid = valid;
193                 break;
194         case MLXSW_SP_RIF_COUNTER_INGRESS:
195                 rif->counter_ingress_valid = valid;
196                 break;
197         }
198 }
199
200 static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
201                                      unsigned int counter_index, bool enable,
202                                      enum mlxsw_sp_rif_counter_dir dir)
203 {
204         char ritr_pl[MLXSW_REG_RITR_LEN];
205         bool is_egress = false;
206         int err;
207
208         if (dir == MLXSW_SP_RIF_COUNTER_EGRESS)
209                 is_egress = true;
210         mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
211         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
212         if (err)
213                 return err;
214
215         mlxsw_reg_ritr_counter_pack(ritr_pl, counter_index, enable,
216                                     is_egress);
217         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
218 }
219
220 int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
221                                    struct mlxsw_sp_rif *rif,
222                                    enum mlxsw_sp_rif_counter_dir dir, u64 *cnt)
223 {
224         char ricnt_pl[MLXSW_REG_RICNT_LEN];
225         unsigned int *p_counter_index;
226         bool valid;
227         int err;
228
229         valid = mlxsw_sp_rif_counter_valid_get(rif, dir);
230         if (!valid)
231                 return -EINVAL;
232
233         p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
234         if (!p_counter_index)
235                 return -EINVAL;
236         mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
237                              MLXSW_REG_RICNT_OPCODE_NOP);
238         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
239         if (err)
240                 return err;
241         *cnt = mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl);
242         return 0;
243 }
244
245 static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp *mlxsw_sp,
246                                       unsigned int counter_index)
247 {
248         char ricnt_pl[MLXSW_REG_RICNT_LEN];
249
250         mlxsw_reg_ricnt_pack(ricnt_pl, counter_index,
251                              MLXSW_REG_RICNT_OPCODE_CLEAR);
252         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
253 }
254
255 int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp *mlxsw_sp,
256                                struct mlxsw_sp_rif *rif,
257                                enum mlxsw_sp_rif_counter_dir dir)
258 {
259         unsigned int *p_counter_index;
260         int err;
261
262         p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
263         if (!p_counter_index)
264                 return -EINVAL;
265         err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
266                                      p_counter_index);
267         if (err)
268                 return err;
269
270         err = mlxsw_sp_rif_counter_clear(mlxsw_sp, *p_counter_index);
271         if (err)
272                 goto err_counter_clear;
273
274         err = mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
275                                         *p_counter_index, true, dir);
276         if (err)
277                 goto err_counter_edit;
278         mlxsw_sp_rif_counter_valid_set(rif, dir, true);
279         return 0;
280
281 err_counter_edit:
282 err_counter_clear:
283         mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
284                               *p_counter_index);
285         return err;
286 }
287
288 void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,
289                                struct mlxsw_sp_rif *rif,
290                                enum mlxsw_sp_rif_counter_dir dir)
291 {
292         unsigned int *p_counter_index;
293
294         if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
295                 return;
296
297         p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
298         if (WARN_ON(!p_counter_index))
299                 return;
300         mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
301                                   *p_counter_index, false, dir);
302         mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
303                               *p_counter_index);
304         mlxsw_sp_rif_counter_valid_set(rif, dir, false);
305 }
306
307 static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif *rif)
308 {
309         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
310         struct devlink *devlink;
311
312         devlink = priv_to_devlink(mlxsw_sp->core);
313         if (!devlink_dpipe_table_counter_enabled(devlink,
314                                                  MLXSW_SP_DPIPE_TABLE_NAME_ERIF))
315                 return;
316         mlxsw_sp_rif_counter_alloc(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS);
317 }
318
319 static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif *rif)
320 {
321         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
322
323         mlxsw_sp_rif_counter_free(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS);
324 }
325
326 static struct mlxsw_sp_rif *
327 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
328                          const struct net_device *dev);
329
330 #define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1)
331
332 struct mlxsw_sp_prefix_usage {
333         DECLARE_BITMAP(b, MLXSW_SP_PREFIX_COUNT);
334 };
335
336 #define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
337         for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
338
339 static bool
340 mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage *prefix_usage1,
341                          struct mlxsw_sp_prefix_usage *prefix_usage2)
342 {
343         return !memcmp(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
344 }
345
346 static bool
347 mlxsw_sp_prefix_usage_none(struct mlxsw_sp_prefix_usage *prefix_usage)
348 {
349         struct mlxsw_sp_prefix_usage prefix_usage_none = {{ 0 } };
350
351         return mlxsw_sp_prefix_usage_eq(prefix_usage, &prefix_usage_none);
352 }
353
354 static void
355 mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage *prefix_usage1,
356                           struct mlxsw_sp_prefix_usage *prefix_usage2)
357 {
358         memcpy(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
359 }
360
361 static void
362 mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage,
363                           unsigned char prefix_len)
364 {
365         set_bit(prefix_len, prefix_usage->b);
366 }
367
368 static void
369 mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
370                             unsigned char prefix_len)
371 {
372         clear_bit(prefix_len, prefix_usage->b);
373 }
374
375 struct mlxsw_sp_fib_key {
376         unsigned char addr[sizeof(struct in6_addr)];
377         unsigned char prefix_len;
378 };
379
380 enum mlxsw_sp_fib_entry_type {
381         MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
382         MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
383         MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
384
385         /* This is a special case of local delivery, where a packet should be
386          * decapsulated on reception. Note that there is no corresponding ENCAP,
387          * because that's a type of next hop, not of FIB entry. (There can be
388          * several next hops in a REMOTE entry, and some of them may be
389          * encapsulating entries.)
390          */
391         MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP,
392 };
393
394 struct mlxsw_sp_nexthop_group;
395 struct mlxsw_sp_fib;
396
397 struct mlxsw_sp_fib_node {
398         struct list_head entry_list;
399         struct list_head list;
400         struct rhash_head ht_node;
401         struct mlxsw_sp_fib *fib;
402         struct mlxsw_sp_fib_key key;
403 };
404
405 struct mlxsw_sp_fib_entry_decap {
406         struct mlxsw_sp_ipip_entry *ipip_entry;
407         u32 tunnel_index;
408 };
409
410 struct mlxsw_sp_fib_entry {
411         struct list_head list;
412         struct mlxsw_sp_fib_node *fib_node;
413         enum mlxsw_sp_fib_entry_type type;
414         struct list_head nexthop_group_node;
415         struct mlxsw_sp_nexthop_group *nh_group;
416         struct mlxsw_sp_fib_entry_decap decap; /* Valid for decap entries. */
417 };
418
419 struct mlxsw_sp_fib4_entry {
420         struct mlxsw_sp_fib_entry common;
421         u32 tb_id;
422         u32 prio;
423         u8 tos;
424         u8 type;
425 };
426
427 struct mlxsw_sp_fib6_entry {
428         struct mlxsw_sp_fib_entry common;
429         struct list_head rt6_list;
430         unsigned int nrt6;
431 };
432
433 struct mlxsw_sp_rt6 {
434         struct list_head list;
435         struct rt6_info *rt;
436 };
437
438 struct mlxsw_sp_lpm_tree {
439         u8 id; /* tree ID */
440         unsigned int ref_count;
441         enum mlxsw_sp_l3proto proto;
442         struct mlxsw_sp_prefix_usage prefix_usage;
443 };
444
445 struct mlxsw_sp_fib {
446         struct rhashtable ht;
447         struct list_head node_list;
448         struct mlxsw_sp_vr *vr;
449         struct mlxsw_sp_lpm_tree *lpm_tree;
450         unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
451         struct mlxsw_sp_prefix_usage prefix_usage;
452         enum mlxsw_sp_l3proto proto;
453 };
454
455 struct mlxsw_sp_vr {
456         u16 id; /* virtual router ID */
457         u32 tb_id; /* kernel fib table id */
458         unsigned int rif_count;
459         struct mlxsw_sp_fib *fib4;
460         struct mlxsw_sp_fib *fib6;
461 };
462
463 static const struct rhashtable_params mlxsw_sp_fib_ht_params;
464
465 static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp_vr *vr,
466                                                 enum mlxsw_sp_l3proto proto)
467 {
468         struct mlxsw_sp_fib *fib;
469         int err;
470
471         fib = kzalloc(sizeof(*fib), GFP_KERNEL);
472         if (!fib)
473                 return ERR_PTR(-ENOMEM);
474         err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params);
475         if (err)
476                 goto err_rhashtable_init;
477         INIT_LIST_HEAD(&fib->node_list);
478         fib->proto = proto;
479         fib->vr = vr;
480         return fib;
481
482 err_rhashtable_init:
483         kfree(fib);
484         return ERR_PTR(err);
485 }
486
487 static void mlxsw_sp_fib_destroy(struct mlxsw_sp_fib *fib)
488 {
489         WARN_ON(!list_empty(&fib->node_list));
490         WARN_ON(fib->lpm_tree);
491         rhashtable_destroy(&fib->ht);
492         kfree(fib);
493 }
494
495 static struct mlxsw_sp_lpm_tree *
496 mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
497 {
498         static struct mlxsw_sp_lpm_tree *lpm_tree;
499         int i;
500
501         for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
502                 lpm_tree = &mlxsw_sp->router->lpm.trees[i];
503                 if (lpm_tree->ref_count == 0)
504                         return lpm_tree;
505         }
506         return NULL;
507 }
508
509 static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp,
510                                    struct mlxsw_sp_lpm_tree *lpm_tree)
511 {
512         char ralta_pl[MLXSW_REG_RALTA_LEN];
513
514         mlxsw_reg_ralta_pack(ralta_pl, true,
515                              (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
516                              lpm_tree->id);
517         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
518 }
519
520 static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp,
521                                    struct mlxsw_sp_lpm_tree *lpm_tree)
522 {
523         char ralta_pl[MLXSW_REG_RALTA_LEN];
524
525         mlxsw_reg_ralta_pack(ralta_pl, false,
526                              (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
527                              lpm_tree->id);
528         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
529 }
530
531 static int
532 mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp,
533                                   struct mlxsw_sp_prefix_usage *prefix_usage,
534                                   struct mlxsw_sp_lpm_tree *lpm_tree)
535 {
536         char ralst_pl[MLXSW_REG_RALST_LEN];
537         u8 root_bin = 0;
538         u8 prefix;
539         u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD;
540
541         mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage)
542                 root_bin = prefix;
543
544         mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id);
545         mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) {
546                 if (prefix == 0)
547                         continue;
548                 mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix,
549                                          MLXSW_REG_RALST_BIN_NO_CHILD);
550                 last_prefix = prefix;
551         }
552         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
553 }
554
555 static struct mlxsw_sp_lpm_tree *
556 mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
557                          struct mlxsw_sp_prefix_usage *prefix_usage,
558                          enum mlxsw_sp_l3proto proto)
559 {
560         struct mlxsw_sp_lpm_tree *lpm_tree;
561         int err;
562
563         lpm_tree = mlxsw_sp_lpm_tree_find_unused(mlxsw_sp);
564         if (!lpm_tree)
565                 return ERR_PTR(-EBUSY);
566         lpm_tree->proto = proto;
567         err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree);
568         if (err)
569                 return ERR_PTR(err);
570
571         err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage,
572                                                 lpm_tree);
573         if (err)
574                 goto err_left_struct_set;
575         memcpy(&lpm_tree->prefix_usage, prefix_usage,
576                sizeof(lpm_tree->prefix_usage));
577         return lpm_tree;
578
579 err_left_struct_set:
580         mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
581         return ERR_PTR(err);
582 }
583
584 static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp,
585                                       struct mlxsw_sp_lpm_tree *lpm_tree)
586 {
587         mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
588 }
589
590 static struct mlxsw_sp_lpm_tree *
591 mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
592                       struct mlxsw_sp_prefix_usage *prefix_usage,
593                       enum mlxsw_sp_l3proto proto)
594 {
595         struct mlxsw_sp_lpm_tree *lpm_tree;
596         int i;
597
598         for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
599                 lpm_tree = &mlxsw_sp->router->lpm.trees[i];
600                 if (lpm_tree->ref_count != 0 &&
601                     lpm_tree->proto == proto &&
602                     mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
603                                              prefix_usage))
604                         return lpm_tree;
605         }
606         return mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage, proto);
607 }
608
609 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree)
610 {
611         lpm_tree->ref_count++;
612 }
613
614 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
615                                   struct mlxsw_sp_lpm_tree *lpm_tree)
616 {
617         if (--lpm_tree->ref_count == 0)
618                 mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
619 }
620
621 #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
622
623 static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
624 {
625         struct mlxsw_sp_lpm_tree *lpm_tree;
626         u64 max_trees;
627         int i;
628
629         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES))
630                 return -EIO;
631
632         max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES);
633         mlxsw_sp->router->lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN;
634         mlxsw_sp->router->lpm.trees = kcalloc(mlxsw_sp->router->lpm.tree_count,
635                                              sizeof(struct mlxsw_sp_lpm_tree),
636                                              GFP_KERNEL);
637         if (!mlxsw_sp->router->lpm.trees)
638                 return -ENOMEM;
639
640         for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
641                 lpm_tree = &mlxsw_sp->router->lpm.trees[i];
642                 lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
643         }
644
645         return 0;
646 }
647
648 static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
649 {
650         kfree(mlxsw_sp->router->lpm.trees);
651 }
652
653 static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
654 {
655         return !!vr->fib4 || !!vr->fib6;
656 }
657
658 static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
659 {
660         struct mlxsw_sp_vr *vr;
661         int i;
662
663         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
664                 vr = &mlxsw_sp->router->vrs[i];
665                 if (!mlxsw_sp_vr_is_used(vr))
666                         return vr;
667         }
668         return NULL;
669 }
670
671 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
672                                      const struct mlxsw_sp_fib *fib, u8 tree_id)
673 {
674         char raltb_pl[MLXSW_REG_RALTB_LEN];
675
676         mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
677                              (enum mlxsw_reg_ralxx_protocol) fib->proto,
678                              tree_id);
679         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
680 }
681
682 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
683                                        const struct mlxsw_sp_fib *fib)
684 {
685         char raltb_pl[MLXSW_REG_RALTB_LEN];
686
687         /* Bind to tree 0 which is default */
688         mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
689                              (enum mlxsw_reg_ralxx_protocol) fib->proto, 0);
690         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
691 }
692
693 static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
694 {
695         /* For our purpose, squash main and local table into one */
696         if (tb_id == RT_TABLE_LOCAL)
697                 tb_id = RT_TABLE_MAIN;
698         return tb_id;
699 }
700
701 static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
702                                             u32 tb_id)
703 {
704         struct mlxsw_sp_vr *vr;
705         int i;
706
707         tb_id = mlxsw_sp_fix_tb_id(tb_id);
708
709         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
710                 vr = &mlxsw_sp->router->vrs[i];
711                 if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
712                         return vr;
713         }
714         return NULL;
715 }
716
717 static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr,
718                                             enum mlxsw_sp_l3proto proto)
719 {
720         switch (proto) {
721         case MLXSW_SP_L3_PROTO_IPV4:
722                 return vr->fib4;
723         case MLXSW_SP_L3_PROTO_IPV6:
724                 return vr->fib6;
725         }
726         return NULL;
727 }
728
729 static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
730                                               u32 tb_id)
731 {
732         struct mlxsw_sp_vr *vr;
733         int err;
734
735         vr = mlxsw_sp_vr_find_unused(mlxsw_sp);
736         if (!vr)
737                 return ERR_PTR(-EBUSY);
738         vr->fib4 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV4);
739         if (IS_ERR(vr->fib4))
740                 return ERR_CAST(vr->fib4);
741         vr->fib6 = mlxsw_sp_fib_create(vr, MLXSW_SP_L3_PROTO_IPV6);
742         if (IS_ERR(vr->fib6)) {
743                 err = PTR_ERR(vr->fib6);
744                 goto err_fib6_create;
745         }
746         vr->tb_id = tb_id;
747         return vr;
748
749 err_fib6_create:
750         mlxsw_sp_fib_destroy(vr->fib4);
751         vr->fib4 = NULL;
752         return ERR_PTR(err);
753 }
754
755 static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr *vr)
756 {
757         mlxsw_sp_fib_destroy(vr->fib6);
758         vr->fib6 = NULL;
759         mlxsw_sp_fib_destroy(vr->fib4);
760         vr->fib4 = NULL;
761 }
762
763 static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id)
764 {
765         struct mlxsw_sp_vr *vr;
766
767         tb_id = mlxsw_sp_fix_tb_id(tb_id);
768         vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
769         if (!vr)
770                 vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id);
771         return vr;
772 }
773
774 static void mlxsw_sp_vr_put(struct mlxsw_sp_vr *vr)
775 {
776         if (!vr->rif_count && list_empty(&vr->fib4->node_list) &&
777             list_empty(&vr->fib6->node_list))
778                 mlxsw_sp_vr_destroy(vr);
779 }
780
781 static bool
782 mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr *vr,
783                                     enum mlxsw_sp_l3proto proto, u8 tree_id)
784 {
785         struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
786
787         if (!mlxsw_sp_vr_is_used(vr))
788                 return false;
789         if (fib->lpm_tree && fib->lpm_tree->id == tree_id)
790                 return true;
791         return false;
792 }
793
794 static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
795                                         struct mlxsw_sp_fib *fib,
796                                         struct mlxsw_sp_lpm_tree *new_tree)
797 {
798         struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree;
799         int err;
800
801         err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
802         if (err)
803                 return err;
804         fib->lpm_tree = new_tree;
805         mlxsw_sp_lpm_tree_hold(new_tree);
806         mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
807         return 0;
808 }
809
810 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
811                                          struct mlxsw_sp_fib *fib,
812                                          struct mlxsw_sp_lpm_tree *new_tree)
813 {
814         struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree;
815         enum mlxsw_sp_l3proto proto = fib->proto;
816         u8 old_id, new_id = new_tree->id;
817         struct mlxsw_sp_vr *vr;
818         int i, err;
819
820         if (!old_tree)
821                 goto no_replace;
822         old_id = old_tree->id;
823
824         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
825                 vr = &mlxsw_sp->router->vrs[i];
826                 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id))
827                         continue;
828                 err = mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
829                                                    mlxsw_sp_vr_fib(vr, proto),
830                                                    new_tree);
831                 if (err)
832                         goto err_tree_replace;
833         }
834
835         return 0;
836
837 err_tree_replace:
838         for (i--; i >= 0; i--) {
839                 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, new_id))
840                         continue;
841                 mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
842                                              mlxsw_sp_vr_fib(vr, proto),
843                                              old_tree);
844         }
845         return err;
846
847 no_replace:
848         err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
849         if (err)
850                 return err;
851         fib->lpm_tree = new_tree;
852         mlxsw_sp_lpm_tree_hold(new_tree);
853         return 0;
854 }
855
856 static void
857 mlxsw_sp_vrs_prefixes(struct mlxsw_sp *mlxsw_sp,
858                       enum mlxsw_sp_l3proto proto,
859                       struct mlxsw_sp_prefix_usage *req_prefix_usage)
860 {
861         int i;
862
863         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
864                 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
865                 struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
866                 unsigned char prefix;
867
868                 if (!mlxsw_sp_vr_is_used(vr))
869                         continue;
870                 mlxsw_sp_prefix_usage_for_each(prefix, &fib->prefix_usage)
871                         mlxsw_sp_prefix_usage_set(req_prefix_usage, prefix);
872         }
873 }
874
875 static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
876 {
877         struct mlxsw_sp_vr *vr;
878         u64 max_vrs;
879         int i;
880
881         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
882                 return -EIO;
883
884         max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
885         mlxsw_sp->router->vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
886                                         GFP_KERNEL);
887         if (!mlxsw_sp->router->vrs)
888                 return -ENOMEM;
889
890         for (i = 0; i < max_vrs; i++) {
891                 vr = &mlxsw_sp->router->vrs[i];
892                 vr->id = i;
893         }
894
895         return 0;
896 }
897
898 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp);
899
900 static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
901 {
902         /* At this stage we're guaranteed not to have new incoming
903          * FIB notifications and the work queue is free from FIBs
904          * sitting on top of mlxsw netdevs. However, we can still
905          * have other FIBs queued. Flush the queue before flushing
906          * the device's tables. No need for locks, as we're the only
907          * writer.
908          */
909         mlxsw_core_flush_owq();
910         mlxsw_sp_router_fib_flush(mlxsw_sp);
911         kfree(mlxsw_sp->router->vrs);
912 }
913
914 static struct net_device *
915 __mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev)
916 {
917         struct ip_tunnel *tun = netdev_priv(ol_dev);
918         struct net *net = dev_net(ol_dev);
919
920         return __dev_get_by_index(net, tun->parms.link);
921 }
922
923 static u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
924 {
925         struct net_device *d = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
926
927         if (d)
928                 return l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
929         else
930                 return l3mdev_fib_table(ol_dev) ? : RT_TABLE_MAIN;
931 }
932
933 static struct mlxsw_sp_rif *
934 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
935                     const struct mlxsw_sp_rif_params *params);
936
937 static struct mlxsw_sp_rif_ipip_lb *
938 mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
939                                 enum mlxsw_sp_ipip_type ipipt,
940                                 struct net_device *ol_dev)
941 {
942         struct mlxsw_sp_rif_params_ipip_lb lb_params;
943         const struct mlxsw_sp_ipip_ops *ipip_ops;
944         struct mlxsw_sp_rif *rif;
945
946         ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
947         lb_params = (struct mlxsw_sp_rif_params_ipip_lb) {
948                 .common.dev = ol_dev,
949                 .common.lag = false,
950                 .lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev),
951         };
952
953         rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common);
954         if (IS_ERR(rif))
955                 return ERR_CAST(rif);
956         return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
957 }
958
959 static struct mlxsw_sp_ipip_entry *
960 mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp *mlxsw_sp,
961                           enum mlxsw_sp_ipip_type ipipt,
962                           struct net_device *ol_dev)
963 {
964         struct mlxsw_sp_ipip_entry *ipip_entry;
965         struct mlxsw_sp_ipip_entry *ret = NULL;
966
967         ipip_entry = kzalloc(sizeof(*ipip_entry), GFP_KERNEL);
968         if (!ipip_entry)
969                 return ERR_PTR(-ENOMEM);
970
971         ipip_entry->ol_lb = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp, ipipt,
972                                                             ol_dev);
973         if (IS_ERR(ipip_entry->ol_lb)) {
974                 ret = ERR_CAST(ipip_entry->ol_lb);
975                 goto err_ol_ipip_lb_create;
976         }
977
978         ipip_entry->ipipt = ipipt;
979         ipip_entry->ol_dev = ol_dev;
980
981         return ipip_entry;
982
983 err_ol_ipip_lb_create:
984         kfree(ipip_entry);
985         return ret;
986 }
987
988 static void
989 mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp_ipip_entry *ipip_entry)
990 {
991         WARN_ON(ipip_entry->ref_count > 0);
992         mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
993         kfree(ipip_entry);
994 }
995
996 static __be32
997 mlxsw_sp_ipip_netdev_saddr4(const struct net_device *ol_dev)
998 {
999         struct ip_tunnel *tun = netdev_priv(ol_dev);
1000
1001         return tun->parms.iph.saddr;
1002 }
1003
1004 union mlxsw_sp_l3addr
1005 mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto,
1006                            const struct net_device *ol_dev)
1007 {
1008         switch (proto) {
1009         case MLXSW_SP_L3_PROTO_IPV4:
1010                 return (union mlxsw_sp_l3addr) {
1011                         .addr4 = mlxsw_sp_ipip_netdev_saddr4(ol_dev),
1012                 };
1013         case MLXSW_SP_L3_PROTO_IPV6:
1014                 break;
1015         };
1016
1017         WARN_ON(1);
1018         return (union mlxsw_sp_l3addr) {
1019                 .addr4 = 0,
1020         };
1021 }
1022
1023 __be32 mlxsw_sp_ipip_netdev_daddr4(const struct net_device *ol_dev)
1024 {
1025         struct ip_tunnel *tun = netdev_priv(ol_dev);
1026
1027         return tun->parms.iph.daddr;
1028 }
1029
1030 union mlxsw_sp_l3addr
1031 mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto,
1032                            const struct net_device *ol_dev)
1033 {
1034         switch (proto) {
1035         case MLXSW_SP_L3_PROTO_IPV4:
1036                 return (union mlxsw_sp_l3addr) {
1037                         .addr4 = mlxsw_sp_ipip_netdev_daddr4(ol_dev),
1038                 };
1039         case MLXSW_SP_L3_PROTO_IPV6:
1040                 break;
1041         };
1042
1043         WARN_ON(1);
1044         return (union mlxsw_sp_l3addr) {
1045                 .addr4 = 0,
1046         };
1047 }
1048
1049 static bool mlxsw_sp_l3addr_eq(const union mlxsw_sp_l3addr *addr1,
1050                                const union mlxsw_sp_l3addr *addr2)
1051 {
1052         return !memcmp(addr1, addr2, sizeof(*addr1));
1053 }
1054
1055 static bool
1056 mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp *mlxsw_sp,
1057                                   const enum mlxsw_sp_l3proto ul_proto,
1058                                   union mlxsw_sp_l3addr saddr,
1059                                   u32 ul_tb_id,
1060                                   struct mlxsw_sp_ipip_entry *ipip_entry)
1061 {
1062         u32 tun_ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
1063         enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
1064         union mlxsw_sp_l3addr tun_saddr;
1065
1066         if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
1067                 return false;
1068
1069         tun_saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
1070         return tun_ul_tb_id == ul_tb_id &&
1071                mlxsw_sp_l3addr_eq(&tun_saddr, &saddr);
1072 }
1073
1074 static int
1075 mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp *mlxsw_sp,
1076                               struct mlxsw_sp_fib_entry *fib_entry,
1077                               struct mlxsw_sp_ipip_entry *ipip_entry)
1078 {
1079         u32 tunnel_index;
1080         int err;
1081
1082         err = mlxsw_sp_kvdl_alloc(mlxsw_sp, 1, &tunnel_index);
1083         if (err)
1084                 return err;
1085
1086         ipip_entry->decap_fib_entry = fib_entry;
1087         fib_entry->decap.ipip_entry = ipip_entry;
1088         fib_entry->decap.tunnel_index = tunnel_index;
1089         return 0;
1090 }
1091
1092 static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp,
1093                                           struct mlxsw_sp_fib_entry *fib_entry)
1094 {
1095         /* Unlink this node from the IPIP entry that it's the decap entry of. */
1096         fib_entry->decap.ipip_entry->decap_fib_entry = NULL;
1097         fib_entry->decap.ipip_entry = NULL;
1098         mlxsw_sp_kvdl_free(mlxsw_sp, fib_entry->decap.tunnel_index);
1099 }
1100
1101 static struct mlxsw_sp_fib_node *
1102 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
1103                          size_t addr_len, unsigned char prefix_len);
1104 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
1105                                      struct mlxsw_sp_fib_entry *fib_entry);
1106
1107 static void
1108 mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp,
1109                                  struct mlxsw_sp_ipip_entry *ipip_entry)
1110 {
1111         struct mlxsw_sp_fib_entry *fib_entry = ipip_entry->decap_fib_entry;
1112
1113         mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
1114         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1115
1116         mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
1117 }
1118
1119 static void
1120 mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp *mlxsw_sp,
1121                                   struct mlxsw_sp_ipip_entry *ipip_entry,
1122                                   struct mlxsw_sp_fib_entry *decap_fib_entry)
1123 {
1124         if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp, decap_fib_entry,
1125                                           ipip_entry))
1126                 return;
1127         decap_fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
1128
1129         if (mlxsw_sp_fib_entry_update(mlxsw_sp, decap_fib_entry))
1130                 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1131 }
1132
1133 /* Given an IPIP entry, find the corresponding decap route. */
1134 static struct mlxsw_sp_fib_entry *
1135 mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
1136                                struct mlxsw_sp_ipip_entry *ipip_entry)
1137 {
1138         static struct mlxsw_sp_fib_node *fib_node;
1139         const struct mlxsw_sp_ipip_ops *ipip_ops;
1140         struct mlxsw_sp_fib_entry *fib_entry;
1141         unsigned char saddr_prefix_len;
1142         union mlxsw_sp_l3addr saddr;
1143         struct mlxsw_sp_fib *ul_fib;
1144         struct mlxsw_sp_vr *ul_vr;
1145         const void *saddrp;
1146         size_t saddr_len;
1147         u32 ul_tb_id;
1148         u32 saddr4;
1149
1150         ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
1151
1152         ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
1153         ul_vr = mlxsw_sp_vr_find(mlxsw_sp, ul_tb_id);
1154         if (!ul_vr)
1155                 return NULL;
1156
1157         ul_fib = mlxsw_sp_vr_fib(ul_vr, ipip_ops->ul_proto);
1158         saddr = mlxsw_sp_ipip_netdev_saddr(ipip_ops->ul_proto,
1159                                            ipip_entry->ol_dev);
1160
1161         switch (ipip_ops->ul_proto) {
1162         case MLXSW_SP_L3_PROTO_IPV4:
1163                 saddr4 = be32_to_cpu(saddr.addr4);
1164                 saddrp = &saddr4;
1165                 saddr_len = 4;
1166                 saddr_prefix_len = 32;
1167                 break;
1168         case MLXSW_SP_L3_PROTO_IPV6:
1169                 WARN_ON(1);
1170                 return NULL;
1171         }
1172
1173         fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len,
1174                                             saddr_prefix_len);
1175         if (!fib_node || list_empty(&fib_node->entry_list))
1176                 return NULL;
1177
1178         fib_entry = list_first_entry(&fib_node->entry_list,
1179                                      struct mlxsw_sp_fib_entry, list);
1180         if (fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
1181                 return NULL;
1182
1183         return fib_entry;
1184 }
1185
1186 static struct mlxsw_sp_ipip_entry *
1187 mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
1188                         enum mlxsw_sp_ipip_type ipipt,
1189                         struct net_device *ol_dev)
1190 {
1191         u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
1192         struct mlxsw_sp_router *router = mlxsw_sp->router;
1193         struct mlxsw_sp_fib_entry *decap_fib_entry;
1194         struct mlxsw_sp_ipip_entry *ipip_entry;
1195         enum mlxsw_sp_l3proto ul_proto;
1196         union mlxsw_sp_l3addr saddr;
1197
1198         list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1199                             ipip_list_node) {
1200                 if (ipip_entry->ol_dev == ol_dev)
1201                         goto inc_ref_count;
1202
1203                 /* The configuration where several tunnels have the same local
1204                  * address in the same underlay table needs special treatment in
1205                  * the HW. That is currently not implemented in the driver.
1206                  */
1207                 ul_proto = router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto;
1208                 saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev);
1209                 if (mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, saddr,
1210                                                       ul_tb_id, ipip_entry))
1211                         return ERR_PTR(-EEXIST);
1212         }
1213
1214         ipip_entry = mlxsw_sp_ipip_entry_alloc(mlxsw_sp, ipipt, ol_dev);
1215         if (IS_ERR(ipip_entry))
1216                 return ipip_entry;
1217
1218         decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
1219         if (decap_fib_entry)
1220                 mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
1221                                                   decap_fib_entry);
1222
1223         list_add_tail(&ipip_entry->ipip_list_node,
1224                       &mlxsw_sp->router->ipip_list);
1225
1226 inc_ref_count:
1227         ++ipip_entry->ref_count;
1228         return ipip_entry;
1229 }
1230
1231 static void
1232 mlxsw_sp_ipip_entry_put(struct mlxsw_sp *mlxsw_sp,
1233                         struct mlxsw_sp_ipip_entry *ipip_entry)
1234 {
1235         if (--ipip_entry->ref_count == 0) {
1236                 list_del(&ipip_entry->ipip_list_node);
1237                 if (ipip_entry->decap_fib_entry)
1238                         mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1239                 mlxsw_sp_ipip_entry_destroy(ipip_entry);
1240         }
1241 }
1242
1243 static bool
1244 mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp *mlxsw_sp,
1245                                   const struct net_device *ul_dev,
1246                                   enum mlxsw_sp_l3proto ul_proto,
1247                                   union mlxsw_sp_l3addr ul_dip,
1248                                   struct mlxsw_sp_ipip_entry *ipip_entry)
1249 {
1250         u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
1251         enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
1252         struct net_device *ipip_ul_dev;
1253
1254         if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
1255                 return false;
1256
1257         ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry->ol_dev);
1258         return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, ul_dip,
1259                                                  ul_tb_id, ipip_entry) &&
1260                (!ipip_ul_dev || ipip_ul_dev == ul_dev);
1261 }
1262
1263 /* Given decap parameters, find the corresponding IPIP entry. */
1264 static struct mlxsw_sp_ipip_entry *
1265 mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp *mlxsw_sp,
1266                                   const struct net_device *ul_dev,
1267                                   enum mlxsw_sp_l3proto ul_proto,
1268                                   union mlxsw_sp_l3addr ul_dip)
1269 {
1270         struct mlxsw_sp_ipip_entry *ipip_entry;
1271
1272         list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1273                             ipip_list_node)
1274                 if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp, ul_dev,
1275                                                       ul_proto, ul_dip,
1276                                                       ipip_entry))
1277                         return ipip_entry;
1278
1279         return NULL;
1280 }
1281
1282 struct mlxsw_sp_neigh_key {
1283         struct neighbour *n;
1284 };
1285
1286 struct mlxsw_sp_neigh_entry {
1287         struct list_head rif_list_node;
1288         struct rhash_head ht_node;
1289         struct mlxsw_sp_neigh_key key;
1290         u16 rif;
1291         bool connected;
1292         unsigned char ha[ETH_ALEN];
1293         struct list_head nexthop_list; /* list of nexthops using
1294                                         * this neigh entry
1295                                         */
1296         struct list_head nexthop_neighs_list_node;
1297         unsigned int counter_index;
1298         bool counter_valid;
1299 };
1300
1301 static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
1302         .key_offset = offsetof(struct mlxsw_sp_neigh_entry, key),
1303         .head_offset = offsetof(struct mlxsw_sp_neigh_entry, ht_node),
1304         .key_len = sizeof(struct mlxsw_sp_neigh_key),
1305 };
1306
1307 struct mlxsw_sp_neigh_entry *
1308 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif,
1309                         struct mlxsw_sp_neigh_entry *neigh_entry)
1310 {
1311         if (!neigh_entry) {
1312                 if (list_empty(&rif->neigh_list))
1313                         return NULL;
1314                 else
1315                         return list_first_entry(&rif->neigh_list,
1316                                                 typeof(*neigh_entry),
1317                                                 rif_list_node);
1318         }
1319         if (neigh_entry->rif_list_node.next == &rif->neigh_list)
1320                 return NULL;
1321         return list_next_entry(neigh_entry, rif_list_node);
1322 }
1323
1324 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry)
1325 {
1326         return neigh_entry->key.n->tbl->family;
1327 }
1328
1329 unsigned char *
1330 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry)
1331 {
1332         return neigh_entry->ha;
1333 }
1334
1335 u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
1336 {
1337         struct neighbour *n;
1338
1339         n = neigh_entry->key.n;
1340         return ntohl(*((__be32 *) n->primary_key));
1341 }
1342
1343 struct in6_addr *
1344 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
1345 {
1346         struct neighbour *n;
1347
1348         n = neigh_entry->key.n;
1349         return (struct in6_addr *) &n->primary_key;
1350 }
1351
1352 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
1353                                struct mlxsw_sp_neigh_entry *neigh_entry,
1354                                u64 *p_counter)
1355 {
1356         if (!neigh_entry->counter_valid)
1357                 return -EINVAL;
1358
1359         return mlxsw_sp_flow_counter_get(mlxsw_sp, neigh_entry->counter_index,
1360                                          p_counter, NULL);
1361 }
1362
1363 static struct mlxsw_sp_neigh_entry *
1364 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
1365                            u16 rif)
1366 {
1367         struct mlxsw_sp_neigh_entry *neigh_entry;
1368
1369         neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_KERNEL);
1370         if (!neigh_entry)
1371                 return NULL;
1372
1373         neigh_entry->key.n = n;
1374         neigh_entry->rif = rif;
1375         INIT_LIST_HEAD(&neigh_entry->nexthop_list);
1376
1377         return neigh_entry;
1378 }
1379
1380 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
1381 {
1382         kfree(neigh_entry);
1383 }
1384
1385 static int
1386 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp *mlxsw_sp,
1387                             struct mlxsw_sp_neigh_entry *neigh_entry)
1388 {
1389         return rhashtable_insert_fast(&mlxsw_sp->router->neigh_ht,
1390                                       &neigh_entry->ht_node,
1391                                       mlxsw_sp_neigh_ht_params);
1392 }
1393
1394 static void
1395 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
1396                             struct mlxsw_sp_neigh_entry *neigh_entry)
1397 {
1398         rhashtable_remove_fast(&mlxsw_sp->router->neigh_ht,
1399                                &neigh_entry->ht_node,
1400                                mlxsw_sp_neigh_ht_params);
1401 }
1402
1403 static bool
1404 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp *mlxsw_sp,
1405                                     struct mlxsw_sp_neigh_entry *neigh_entry)
1406 {
1407         struct devlink *devlink;
1408         const char *table_name;
1409
1410         switch (mlxsw_sp_neigh_entry_type(neigh_entry)) {
1411         case AF_INET:
1412                 table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST4;
1413                 break;
1414         case AF_INET6:
1415                 table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST6;
1416                 break;
1417         default:
1418                 WARN_ON(1);
1419                 return false;
1420         }
1421
1422         devlink = priv_to_devlink(mlxsw_sp->core);
1423         return devlink_dpipe_table_counter_enabled(devlink, table_name);
1424 }
1425
1426 static void
1427 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp,
1428                              struct mlxsw_sp_neigh_entry *neigh_entry)
1429 {
1430         if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp, neigh_entry))
1431                 return;
1432
1433         if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index))
1434                 return;
1435
1436         neigh_entry->counter_valid = true;
1437 }
1438
1439 static void
1440 mlxsw_sp_neigh_counter_free(struct mlxsw_sp *mlxsw_sp,
1441                             struct mlxsw_sp_neigh_entry *neigh_entry)
1442 {
1443         if (!neigh_entry->counter_valid)
1444                 return;
1445         mlxsw_sp_flow_counter_free(mlxsw_sp,
1446                                    neigh_entry->counter_index);
1447         neigh_entry->counter_valid = false;
1448 }
1449
1450 static struct mlxsw_sp_neigh_entry *
1451 mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
1452 {
1453         struct mlxsw_sp_neigh_entry *neigh_entry;
1454         struct mlxsw_sp_rif *rif;
1455         int err;
1456
1457         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
1458         if (!rif)
1459                 return ERR_PTR(-EINVAL);
1460
1461         neigh_entry = mlxsw_sp_neigh_entry_alloc(mlxsw_sp, n, rif->rif_index);
1462         if (!neigh_entry)
1463                 return ERR_PTR(-ENOMEM);
1464
1465         err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
1466         if (err)
1467                 goto err_neigh_entry_insert;
1468
1469         mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
1470         list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
1471
1472         return neigh_entry;
1473
1474 err_neigh_entry_insert:
1475         mlxsw_sp_neigh_entry_free(neigh_entry);
1476         return ERR_PTR(err);
1477 }
1478
1479 static void
1480 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
1481                              struct mlxsw_sp_neigh_entry *neigh_entry)
1482 {
1483         list_del(&neigh_entry->rif_list_node);
1484         mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
1485         mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
1486         mlxsw_sp_neigh_entry_free(neigh_entry);
1487 }
1488
1489 static struct mlxsw_sp_neigh_entry *
1490 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
1491 {
1492         struct mlxsw_sp_neigh_key key;
1493
1494         key.n = n;
1495         return rhashtable_lookup_fast(&mlxsw_sp->router->neigh_ht,
1496                                       &key, mlxsw_sp_neigh_ht_params);
1497 }
1498
1499 static void
1500 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp)
1501 {
1502         unsigned long interval;
1503
1504 #if IS_ENABLED(CONFIG_IPV6)
1505         interval = min_t(unsigned long,
1506                          NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME),
1507                          NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME));
1508 #else
1509         interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME);
1510 #endif
1511         mlxsw_sp->router->neighs_update.interval = jiffies_to_msecs(interval);
1512 }
1513
1514 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
1515                                                    char *rauhtd_pl,
1516                                                    int ent_index)
1517 {
1518         struct net_device *dev;
1519         struct neighbour *n;
1520         __be32 dipn;
1521         u32 dip;
1522         u16 rif;
1523
1524         mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip);
1525
1526         if (!mlxsw_sp->router->rifs[rif]) {
1527                 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
1528                 return;
1529         }
1530
1531         dipn = htonl(dip);
1532         dev = mlxsw_sp->router->rifs[rif]->dev;
1533         n = neigh_lookup(&arp_tbl, &dipn, dev);
1534         if (!n) {
1535                 netdev_err(dev, "Failed to find matching neighbour for IP=%pI4h\n",
1536                            &dip);
1537                 return;
1538         }
1539
1540         netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip);
1541         neigh_event_send(n, NULL);
1542         neigh_release(n);
1543 }
1544
1545 #if IS_ENABLED(CONFIG_IPV6)
1546 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
1547                                                    char *rauhtd_pl,
1548                                                    int rec_index)
1549 {
1550         struct net_device *dev;
1551         struct neighbour *n;
1552         struct in6_addr dip;
1553         u16 rif;
1554
1555         mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl, rec_index, &rif,
1556                                          (char *) &dip);
1557
1558         if (!mlxsw_sp->router->rifs[rif]) {
1559                 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
1560                 return;
1561         }
1562
1563         dev = mlxsw_sp->router->rifs[rif]->dev;
1564         n = neigh_lookup(&nd_tbl, &dip, dev);
1565         if (!n) {
1566                 netdev_err(dev, "Failed to find matching neighbour for IP=%pI6c\n",
1567                            &dip);
1568                 return;
1569         }
1570
1571         netdev_dbg(dev, "Updating neighbour with IP=%pI6c\n", &dip);
1572         neigh_event_send(n, NULL);
1573         neigh_release(n);
1574 }
1575 #else
1576 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
1577                                                    char *rauhtd_pl,
1578                                                    int rec_index)
1579 {
1580 }
1581 #endif
1582
1583 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
1584                                                    char *rauhtd_pl,
1585                                                    int rec_index)
1586 {
1587         u8 num_entries;
1588         int i;
1589
1590         num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
1591                                                                 rec_index);
1592         /* Hardware starts counting at 0, so add 1. */
1593         num_entries++;
1594
1595         /* Each record consists of several neighbour entries. */
1596         for (i = 0; i < num_entries; i++) {
1597                 int ent_index;
1598
1599                 ent_index = rec_index * MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC + i;
1600                 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp, rauhtd_pl,
1601                                                        ent_index);
1602         }
1603
1604 }
1605
1606 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp *mlxsw_sp,
1607                                                    char *rauhtd_pl,
1608                                                    int rec_index)
1609 {
1610         /* One record contains one entry. */
1611         mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp, rauhtd_pl,
1612                                                rec_index);
1613 }
1614
1615 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
1616                                               char *rauhtd_pl, int rec_index)
1617 {
1618         switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, rec_index)) {
1619         case MLXSW_REG_RAUHTD_TYPE_IPV4:
1620                 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp, rauhtd_pl,
1621                                                        rec_index);
1622                 break;
1623         case MLXSW_REG_RAUHTD_TYPE_IPV6:
1624                 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp, rauhtd_pl,
1625                                                        rec_index);
1626                 break;
1627         }
1628 }
1629
1630 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl)
1631 {
1632         u8 num_rec, last_rec_index, num_entries;
1633
1634         num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
1635         last_rec_index = num_rec - 1;
1636
1637         if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM)
1638                 return false;
1639         if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) ==
1640             MLXSW_REG_RAUHTD_TYPE_IPV6)
1641                 return true;
1642
1643         num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
1644                                                                 last_rec_index);
1645         if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC)
1646                 return true;
1647         return false;
1648 }
1649
1650 static int
1651 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp,
1652                                        char *rauhtd_pl,
1653                                        enum mlxsw_reg_rauhtd_type type)
1654 {
1655         int i, num_rec;
1656         int err;
1657
1658         /* Make sure the neighbour's netdev isn't removed in the
1659          * process.
1660          */
1661         rtnl_lock();
1662         do {
1663                 mlxsw_reg_rauhtd_pack(rauhtd_pl, type);
1664                 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd),
1665                                       rauhtd_pl);
1666                 if (err) {
1667                         dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to dump neighbour talbe\n");
1668                         break;
1669                 }
1670                 num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
1671                 for (i = 0; i < num_rec; i++)
1672                         mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl,
1673                                                           i);
1674         } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl));
1675         rtnl_unlock();
1676
1677         return err;
1678 }
1679
1680 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
1681 {
1682         enum mlxsw_reg_rauhtd_type type;
1683         char *rauhtd_pl;
1684         int err;
1685
1686         rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
1687         if (!rauhtd_pl)
1688                 return -ENOMEM;
1689
1690         type = MLXSW_REG_RAUHTD_TYPE_IPV4;
1691         err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
1692         if (err)
1693                 goto out;
1694
1695         type = MLXSW_REG_RAUHTD_TYPE_IPV6;
1696         err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
1697 out:
1698         kfree(rauhtd_pl);
1699         return err;
1700 }
1701
1702 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
1703 {
1704         struct mlxsw_sp_neigh_entry *neigh_entry;
1705
1706         /* Take RTNL mutex here to prevent lists from changes */
1707         rtnl_lock();
1708         list_for_each_entry(neigh_entry, &mlxsw_sp->router->nexthop_neighs_list,
1709                             nexthop_neighs_list_node)
1710                 /* If this neigh have nexthops, make the kernel think this neigh
1711                  * is active regardless of the traffic.
1712                  */
1713                 neigh_event_send(neigh_entry->key.n, NULL);
1714         rtnl_unlock();
1715 }
1716
1717 static void
1718 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
1719 {
1720         unsigned long interval = mlxsw_sp->router->neighs_update.interval;
1721
1722         mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw,
1723                                msecs_to_jiffies(interval));
1724 }
1725
1726 static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
1727 {
1728         struct mlxsw_sp_router *router;
1729         int err;
1730
1731         router = container_of(work, struct mlxsw_sp_router,
1732                               neighs_update.dw.work);
1733         err = mlxsw_sp_router_neighs_update_rauhtd(router->mlxsw_sp);
1734         if (err)
1735                 dev_err(router->mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity");
1736
1737         mlxsw_sp_router_neighs_update_nh(router->mlxsw_sp);
1738
1739         mlxsw_sp_router_neighs_update_work_schedule(router->mlxsw_sp);
1740 }
1741
1742 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
1743 {
1744         struct mlxsw_sp_neigh_entry *neigh_entry;
1745         struct mlxsw_sp_router *router;
1746
1747         router = container_of(work, struct mlxsw_sp_router,
1748                               nexthop_probe_dw.work);
1749         /* Iterate over nexthop neighbours, find those who are unresolved and
1750          * send arp on them. This solves the chicken-egg problem when
1751          * the nexthop wouldn't get offloaded until the neighbor is resolved
1752          * but it wouldn't get resolved ever in case traffic is flowing in HW
1753          * using different nexthop.
1754          *
1755          * Take RTNL mutex here to prevent lists from changes.
1756          */
1757         rtnl_lock();
1758         list_for_each_entry(neigh_entry, &router->nexthop_neighs_list,
1759                             nexthop_neighs_list_node)
1760                 if (!neigh_entry->connected)
1761                         neigh_event_send(neigh_entry->key.n, NULL);
1762         rtnl_unlock();
1763
1764         mlxsw_core_schedule_dw(&router->nexthop_probe_dw,
1765                                MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL);
1766 }
1767
1768 static void
1769 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
1770                               struct mlxsw_sp_neigh_entry *neigh_entry,
1771                               bool removing);
1772
1773 static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
1774 {
1775         return adding ? MLXSW_REG_RAUHT_OP_WRITE_ADD :
1776                         MLXSW_REG_RAUHT_OP_WRITE_DELETE;
1777 }
1778
1779 static void
1780 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
1781                                 struct mlxsw_sp_neigh_entry *neigh_entry,
1782                                 enum mlxsw_reg_rauht_op op)
1783 {
1784         struct neighbour *n = neigh_entry->key.n;
1785         u32 dip = ntohl(*((__be32 *) n->primary_key));
1786         char rauht_pl[MLXSW_REG_RAUHT_LEN];
1787
1788         mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
1789                               dip);
1790         if (neigh_entry->counter_valid)
1791                 mlxsw_reg_rauht_pack_counter(rauht_pl,
1792                                              neigh_entry->counter_index);
1793         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
1794 }
1795
1796 static void
1797 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
1798                                 struct mlxsw_sp_neigh_entry *neigh_entry,
1799                                 enum mlxsw_reg_rauht_op op)
1800 {
1801         struct neighbour *n = neigh_entry->key.n;
1802         char rauht_pl[MLXSW_REG_RAUHT_LEN];
1803         const char *dip = n->primary_key;
1804
1805         mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
1806                               dip);
1807         if (neigh_entry->counter_valid)
1808                 mlxsw_reg_rauht_pack_counter(rauht_pl,
1809                                              neigh_entry->counter_index);
1810         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
1811 }
1812
1813 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry)
1814 {
1815         struct neighbour *n = neigh_entry->key.n;
1816
1817         /* Packets with a link-local destination address are trapped
1818          * after LPM lookup and never reach the neighbour table, so
1819          * there is no need to program such neighbours to the device.
1820          */
1821         if (ipv6_addr_type((struct in6_addr *) &n->primary_key) &
1822             IPV6_ADDR_LINKLOCAL)
1823                 return true;
1824         return false;
1825 }
1826
1827 static void
1828 mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
1829                             struct mlxsw_sp_neigh_entry *neigh_entry,
1830                             bool adding)
1831 {
1832         if (!adding && !neigh_entry->connected)
1833                 return;
1834         neigh_entry->connected = adding;
1835         if (neigh_entry->key.n->tbl->family == AF_INET) {
1836                 mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
1837                                                 mlxsw_sp_rauht_op(adding));
1838         } else if (neigh_entry->key.n->tbl->family == AF_INET6) {
1839                 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
1840                         return;
1841                 mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
1842                                                 mlxsw_sp_rauht_op(adding));
1843         } else {
1844                 WARN_ON_ONCE(1);
1845         }
1846 }
1847
1848 void
1849 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
1850                                     struct mlxsw_sp_neigh_entry *neigh_entry,
1851                                     bool adding)
1852 {
1853         if (adding)
1854                 mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
1855         else
1856                 mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
1857         mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, true);
1858 }
1859
1860 struct mlxsw_sp_neigh_event_work {
1861         struct work_struct work;
1862         struct mlxsw_sp *mlxsw_sp;
1863         struct neighbour *n;
1864 };
1865
1866 static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
1867 {
1868         struct mlxsw_sp_neigh_event_work *neigh_work =
1869                 container_of(work, struct mlxsw_sp_neigh_event_work, work);
1870         struct mlxsw_sp *mlxsw_sp = neigh_work->mlxsw_sp;
1871         struct mlxsw_sp_neigh_entry *neigh_entry;
1872         struct neighbour *n = neigh_work->n;
1873         unsigned char ha[ETH_ALEN];
1874         bool entry_connected;
1875         u8 nud_state, dead;
1876
1877         /* If these parameters are changed after we release the lock,
1878          * then we are guaranteed to receive another event letting us
1879          * know about it.
1880          */
1881         read_lock_bh(&n->lock);
1882         memcpy(ha, n->ha, ETH_ALEN);
1883         nud_state = n->nud_state;
1884         dead = n->dead;
1885         read_unlock_bh(&n->lock);
1886
1887         rtnl_lock();
1888         entry_connected = nud_state & NUD_VALID && !dead;
1889         neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
1890         if (!entry_connected && !neigh_entry)
1891                 goto out;
1892         if (!neigh_entry) {
1893                 neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
1894                 if (IS_ERR(neigh_entry))
1895                         goto out;
1896         }
1897
1898         memcpy(neigh_entry->ha, ha, ETH_ALEN);
1899         mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
1900         mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected);
1901
1902         if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
1903                 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
1904
1905 out:
1906         rtnl_unlock();
1907         neigh_release(n);
1908         kfree(neigh_work);
1909 }
1910
1911 int mlxsw_sp_router_netevent_event(struct notifier_block *unused,
1912                                    unsigned long event, void *ptr)
1913 {
1914         struct mlxsw_sp_neigh_event_work *neigh_work;
1915         struct mlxsw_sp_port *mlxsw_sp_port;
1916         struct mlxsw_sp *mlxsw_sp;
1917         unsigned long interval;
1918         struct neigh_parms *p;
1919         struct neighbour *n;
1920
1921         switch (event) {
1922         case NETEVENT_DELAY_PROBE_TIME_UPDATE:
1923                 p = ptr;
1924
1925                 /* We don't care about changes in the default table. */
1926                 if (!p->dev || (p->tbl->family != AF_INET &&
1927                                 p->tbl->family != AF_INET6))
1928                         return NOTIFY_DONE;
1929
1930                 /* We are in atomic context and can't take RTNL mutex,
1931                  * so use RCU variant to walk the device chain.
1932                  */
1933                 mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
1934                 if (!mlxsw_sp_port)
1935                         return NOTIFY_DONE;
1936
1937                 mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1938                 interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
1939                 mlxsw_sp->router->neighs_update.interval = interval;
1940
1941                 mlxsw_sp_port_dev_put(mlxsw_sp_port);
1942                 break;
1943         case NETEVENT_NEIGH_UPDATE:
1944                 n = ptr;
1945
1946                 if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
1947                         return NOTIFY_DONE;
1948
1949                 mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
1950                 if (!mlxsw_sp_port)
1951                         return NOTIFY_DONE;
1952
1953                 neigh_work = kzalloc(sizeof(*neigh_work), GFP_ATOMIC);
1954                 if (!neigh_work) {
1955                         mlxsw_sp_port_dev_put(mlxsw_sp_port);
1956                         return NOTIFY_BAD;
1957                 }
1958
1959                 INIT_WORK(&neigh_work->work, mlxsw_sp_router_neigh_event_work);
1960                 neigh_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1961                 neigh_work->n = n;
1962
1963                 /* Take a reference to ensure the neighbour won't be
1964                  * destructed until we drop the reference in delayed
1965                  * work.
1966                  */
1967                 neigh_clone(n);
1968                 mlxsw_core_schedule_work(&neigh_work->work);
1969                 mlxsw_sp_port_dev_put(mlxsw_sp_port);
1970                 break;
1971         }
1972
1973         return NOTIFY_DONE;
1974 }
1975
1976 static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
1977 {
1978         int err;
1979
1980         err = rhashtable_init(&mlxsw_sp->router->neigh_ht,
1981                               &mlxsw_sp_neigh_ht_params);
1982         if (err)
1983                 return err;
1984
1985         /* Initialize the polling interval according to the default
1986          * table.
1987          */
1988         mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp);
1989
1990         /* Create the delayed works for the activity_update */
1991         INIT_DELAYED_WORK(&mlxsw_sp->router->neighs_update.dw,
1992                           mlxsw_sp_router_neighs_update_work);
1993         INIT_DELAYED_WORK(&mlxsw_sp->router->nexthop_probe_dw,
1994                           mlxsw_sp_router_probe_unresolved_nexthops);
1995         mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw, 0);
1996         mlxsw_core_schedule_dw(&mlxsw_sp->router->nexthop_probe_dw, 0);
1997         return 0;
1998 }
1999
2000 static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp)
2001 {
2002         cancel_delayed_work_sync(&mlxsw_sp->router->neighs_update.dw);
2003         cancel_delayed_work_sync(&mlxsw_sp->router->nexthop_probe_dw);
2004         rhashtable_destroy(&mlxsw_sp->router->neigh_ht);
2005 }
2006
2007 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
2008                                          struct mlxsw_sp_rif *rif)
2009 {
2010         struct mlxsw_sp_neigh_entry *neigh_entry, *tmp;
2011
2012         list_for_each_entry_safe(neigh_entry, tmp, &rif->neigh_list,
2013                                  rif_list_node) {
2014                 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, false);
2015                 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
2016         }
2017 }
2018
2019 enum mlxsw_sp_nexthop_type {
2020         MLXSW_SP_NEXTHOP_TYPE_ETH,
2021         MLXSW_SP_NEXTHOP_TYPE_IPIP,
2022 };
2023
2024 struct mlxsw_sp_nexthop_key {
2025         struct fib_nh *fib_nh;
2026 };
2027
2028 struct mlxsw_sp_nexthop {
2029         struct list_head neigh_list_node; /* member of neigh entry list */
2030         struct list_head rif_list_node;
2031         struct mlxsw_sp_nexthop_group *nh_grp; /* pointer back to the group
2032                                                 * this belongs to
2033                                                 */
2034         struct rhash_head ht_node;
2035         struct mlxsw_sp_nexthop_key key;
2036         unsigned char gw_addr[sizeof(struct in6_addr)];
2037         int ifindex;
2038         struct mlxsw_sp_rif *rif;
2039         u8 should_offload:1, /* set indicates this neigh is connected and
2040                               * should be put to KVD linear area of this group.
2041                               */
2042            offloaded:1, /* set in case the neigh is actually put into
2043                          * KVD linear area of this group.
2044                          */
2045            update:1; /* set indicates that MAC of this neigh should be
2046                       * updated in HW
2047                       */
2048         enum mlxsw_sp_nexthop_type type;
2049         union {
2050                 struct mlxsw_sp_neigh_entry *neigh_entry;
2051                 struct mlxsw_sp_ipip_entry *ipip_entry;
2052         };
2053 };
2054
2055 struct mlxsw_sp_nexthop_group {
2056         void *priv;
2057         struct rhash_head ht_node;
2058         struct list_head fib_list; /* list of fib entries that use this group */
2059         struct neigh_table *neigh_tbl;
2060         u8 adj_index_valid:1,
2061            gateway:1; /* routes using the group use a gateway */
2062         u32 adj_index;
2063         u16 ecmp_size;
2064         u16 count;
2065         struct mlxsw_sp_nexthop nexthops[0];
2066 #define nh_rif  nexthops[0].rif
2067 };
2068
2069 static struct fib_info *
2070 mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group *nh_grp)
2071 {
2072         return nh_grp->priv;
2073 }
2074
2075 struct mlxsw_sp_nexthop_group_cmp_arg {
2076         enum mlxsw_sp_l3proto proto;
2077         union {
2078                 struct fib_info *fi;
2079                 struct mlxsw_sp_fib6_entry *fib6_entry;
2080         };
2081 };
2082
2083 static bool
2084 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group *nh_grp,
2085                                     const struct in6_addr *gw, int ifindex)
2086 {
2087         int i;
2088
2089         for (i = 0; i < nh_grp->count; i++) {
2090                 const struct mlxsw_sp_nexthop *nh;
2091
2092                 nh = &nh_grp->nexthops[i];
2093                 if (nh->ifindex == ifindex &&
2094                     ipv6_addr_equal(gw, (struct in6_addr *) nh->gw_addr))
2095                         return true;
2096         }
2097
2098         return false;
2099 }
2100
2101 static bool
2102 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
2103                             const struct mlxsw_sp_fib6_entry *fib6_entry)
2104 {
2105         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
2106
2107         if (nh_grp->count != fib6_entry->nrt6)
2108                 return false;
2109
2110         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
2111                 struct in6_addr *gw;
2112                 int ifindex;
2113
2114                 ifindex = mlxsw_sp_rt6->rt->dst.dev->ifindex;
2115                 gw = &mlxsw_sp_rt6->rt->rt6i_gateway;
2116                 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex))
2117                         return false;
2118         }
2119
2120         return true;
2121 }
2122
2123 static int
2124 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg *arg, const void *ptr)
2125 {
2126         const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = arg->key;
2127         const struct mlxsw_sp_nexthop_group *nh_grp = ptr;
2128
2129         switch (cmp_arg->proto) {
2130         case MLXSW_SP_L3_PROTO_IPV4:
2131                 return cmp_arg->fi != mlxsw_sp_nexthop4_group_fi(nh_grp);
2132         case MLXSW_SP_L3_PROTO_IPV6:
2133                 return !mlxsw_sp_nexthop6_group_cmp(nh_grp,
2134                                                     cmp_arg->fib6_entry);
2135         default:
2136                 WARN_ON(1);
2137                 return 1;
2138         }
2139 }
2140
2141 static int
2142 mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group *nh_grp)
2143 {
2144         return nh_grp->neigh_tbl->family;
2145 }
2146
2147 static u32 mlxsw_sp_nexthop_group_hash_obj(const void *data, u32 len, u32 seed)
2148 {
2149         const struct mlxsw_sp_nexthop_group *nh_grp = data;
2150         const struct mlxsw_sp_nexthop *nh;
2151         struct fib_info *fi;
2152         unsigned int val;
2153         int i;
2154
2155         switch (mlxsw_sp_nexthop_group_type(nh_grp)) {
2156         case AF_INET:
2157                 fi = mlxsw_sp_nexthop4_group_fi(nh_grp);
2158                 return jhash(&fi, sizeof(fi), seed);
2159         case AF_INET6:
2160                 val = nh_grp->count;
2161                 for (i = 0; i < nh_grp->count; i++) {
2162                         nh = &nh_grp->nexthops[i];
2163                         val ^= nh->ifindex;
2164                 }
2165                 return jhash(&val, sizeof(val), seed);
2166         default:
2167                 WARN_ON(1);
2168                 return 0;
2169         }
2170 }
2171
2172 static u32
2173 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
2174 {
2175         unsigned int val = fib6_entry->nrt6;
2176         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
2177         struct net_device *dev;
2178
2179         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
2180                 dev = mlxsw_sp_rt6->rt->dst.dev;
2181                 val ^= dev->ifindex;
2182         }
2183
2184         return jhash(&val, sizeof(val), seed);
2185 }
2186
2187 static u32
2188 mlxsw_sp_nexthop_group_hash(const void *data, u32 len, u32 seed)
2189 {
2190         const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = data;
2191
2192         switch (cmp_arg->proto) {
2193         case MLXSW_SP_L3_PROTO_IPV4:
2194                 return jhash(&cmp_arg->fi, sizeof(cmp_arg->fi), seed);
2195         case MLXSW_SP_L3_PROTO_IPV6:
2196                 return mlxsw_sp_nexthop6_group_hash(cmp_arg->fib6_entry, seed);
2197         default:
2198                 WARN_ON(1);
2199                 return 0;
2200         }
2201 }
2202
2203 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params = {
2204         .head_offset = offsetof(struct mlxsw_sp_nexthop_group, ht_node),
2205         .hashfn      = mlxsw_sp_nexthop_group_hash,
2206         .obj_hashfn  = mlxsw_sp_nexthop_group_hash_obj,
2207         .obj_cmpfn   = mlxsw_sp_nexthop_group_cmp,
2208 };
2209
2210 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp *mlxsw_sp,
2211                                          struct mlxsw_sp_nexthop_group *nh_grp)
2212 {
2213         if (mlxsw_sp_nexthop_group_type(nh_grp) == AF_INET6 &&
2214             !nh_grp->gateway)
2215                 return 0;
2216
2217         return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_group_ht,
2218                                       &nh_grp->ht_node,
2219                                       mlxsw_sp_nexthop_group_ht_params);
2220 }
2221
2222 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp *mlxsw_sp,
2223                                           struct mlxsw_sp_nexthop_group *nh_grp)
2224 {
2225         if (mlxsw_sp_nexthop_group_type(nh_grp) == AF_INET6 &&
2226             !nh_grp->gateway)
2227                 return;
2228
2229         rhashtable_remove_fast(&mlxsw_sp->router->nexthop_group_ht,
2230                                &nh_grp->ht_node,
2231                                mlxsw_sp_nexthop_group_ht_params);
2232 }
2233
2234 static struct mlxsw_sp_nexthop_group *
2235 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp *mlxsw_sp,
2236                                struct fib_info *fi)
2237 {
2238         struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
2239
2240         cmp_arg.proto = MLXSW_SP_L3_PROTO_IPV4;
2241         cmp_arg.fi = fi;
2242         return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
2243                                       &cmp_arg,
2244                                       mlxsw_sp_nexthop_group_ht_params);
2245 }
2246
2247 static struct mlxsw_sp_nexthop_group *
2248 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp *mlxsw_sp,
2249                                struct mlxsw_sp_fib6_entry *fib6_entry)
2250 {
2251         struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
2252
2253         cmp_arg.proto = MLXSW_SP_L3_PROTO_IPV6;
2254         cmp_arg.fib6_entry = fib6_entry;
2255         return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
2256                                       &cmp_arg,
2257                                       mlxsw_sp_nexthop_group_ht_params);
2258 }
2259
2260 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params = {
2261         .key_offset = offsetof(struct mlxsw_sp_nexthop, key),
2262         .head_offset = offsetof(struct mlxsw_sp_nexthop, ht_node),
2263         .key_len = sizeof(struct mlxsw_sp_nexthop_key),
2264 };
2265
2266 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp *mlxsw_sp,
2267                                    struct mlxsw_sp_nexthop *nh)
2268 {
2269         return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_ht,
2270                                       &nh->ht_node, mlxsw_sp_nexthop_ht_params);
2271 }
2272
2273 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp *mlxsw_sp,
2274                                     struct mlxsw_sp_nexthop *nh)
2275 {
2276         rhashtable_remove_fast(&mlxsw_sp->router->nexthop_ht, &nh->ht_node,
2277                                mlxsw_sp_nexthop_ht_params);
2278 }
2279
2280 static struct mlxsw_sp_nexthop *
2281 mlxsw_sp_nexthop_lookup(struct mlxsw_sp *mlxsw_sp,
2282                         struct mlxsw_sp_nexthop_key key)
2283 {
2284         return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_ht, &key,
2285                                       mlxsw_sp_nexthop_ht_params);
2286 }
2287
2288 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp *mlxsw_sp,
2289                                              const struct mlxsw_sp_fib *fib,
2290                                              u32 adj_index, u16 ecmp_size,
2291                                              u32 new_adj_index,
2292                                              u16 new_ecmp_size)
2293 {
2294         char raleu_pl[MLXSW_REG_RALEU_LEN];
2295
2296         mlxsw_reg_raleu_pack(raleu_pl,
2297                              (enum mlxsw_reg_ralxx_protocol) fib->proto,
2298                              fib->vr->id, adj_index, ecmp_size, new_adj_index,
2299                              new_ecmp_size);
2300         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raleu), raleu_pl);
2301 }
2302
2303 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp *mlxsw_sp,
2304                                           struct mlxsw_sp_nexthop_group *nh_grp,
2305                                           u32 old_adj_index, u16 old_ecmp_size)
2306 {
2307         struct mlxsw_sp_fib_entry *fib_entry;
2308         struct mlxsw_sp_fib *fib = NULL;
2309         int err;
2310
2311         list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
2312                 if (fib == fib_entry->fib_node->fib)
2313                         continue;
2314                 fib = fib_entry->fib_node->fib;
2315                 err = mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp, fib,
2316                                                         old_adj_index,
2317                                                         old_ecmp_size,
2318                                                         nh_grp->adj_index,
2319                                                         nh_grp->ecmp_size);
2320                 if (err)
2321                         return err;
2322         }
2323         return 0;
2324 }
2325
2326 static int mlxsw_sp_nexthop_mac_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
2327                                        struct mlxsw_sp_nexthop *nh)
2328 {
2329         struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
2330         char ratr_pl[MLXSW_REG_RATR_LEN];
2331
2332         mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY,
2333                             true, MLXSW_REG_RATR_TYPE_ETHERNET,
2334                             adj_index, neigh_entry->rif);
2335         mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
2336         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
2337 }
2338
2339 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
2340                                         u32 adj_index,
2341                                         struct mlxsw_sp_nexthop *nh)
2342 {
2343         const struct mlxsw_sp_ipip_ops *ipip_ops;
2344
2345         ipip_ops = mlxsw_sp->router->ipip_ops_arr[nh->ipip_entry->ipipt];
2346         return ipip_ops->nexthop_update(mlxsw_sp, adj_index, nh->ipip_entry);
2347 }
2348
2349 static int
2350 mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
2351                               struct mlxsw_sp_nexthop_group *nh_grp,
2352                               bool reallocate)
2353 {
2354         u32 adj_index = nh_grp->adj_index; /* base */
2355         struct mlxsw_sp_nexthop *nh;
2356         int i;
2357         int err;
2358
2359         for (i = 0; i < nh_grp->count; i++) {
2360                 nh = &nh_grp->nexthops[i];
2361
2362                 if (!nh->should_offload) {
2363                         nh->offloaded = 0;
2364                         continue;
2365                 }
2366
2367                 if (nh->update || reallocate) {
2368                         switch (nh->type) {
2369                         case MLXSW_SP_NEXTHOP_TYPE_ETH:
2370                                 err = mlxsw_sp_nexthop_mac_update
2371                                             (mlxsw_sp, adj_index, nh);
2372                                 break;
2373                         case MLXSW_SP_NEXTHOP_TYPE_IPIP:
2374                                 err = mlxsw_sp_nexthop_ipip_update
2375                                             (mlxsw_sp, adj_index, nh);
2376                                 break;
2377                         }
2378                         if (err)
2379                                 return err;
2380                         nh->update = 0;
2381                         nh->offloaded = 1;
2382                 }
2383                 adj_index++;
2384         }
2385         return 0;
2386 }
2387
2388 static bool
2389 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node,
2390                                  const struct mlxsw_sp_fib_entry *fib_entry);
2391
2392 static int
2393 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
2394                                     struct mlxsw_sp_nexthop_group *nh_grp)
2395 {
2396         struct mlxsw_sp_fib_entry *fib_entry;
2397         int err;
2398
2399         list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
2400                 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node,
2401                                                       fib_entry))
2402                         continue;
2403                 err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
2404                 if (err)
2405                         return err;
2406         }
2407         return 0;
2408 }
2409
2410 static void
2411 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry,
2412                                    enum mlxsw_reg_ralue_op op, int err);
2413
2414 static void
2415 mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group *nh_grp)
2416 {
2417         enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_WRITE;
2418         struct mlxsw_sp_fib_entry *fib_entry;
2419
2420         list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
2421                 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry->fib_node,
2422                                                       fib_entry))
2423                         continue;
2424                 mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
2425         }
2426 }
2427
2428 static void
2429 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
2430                                struct mlxsw_sp_nexthop_group *nh_grp)
2431 {
2432         struct mlxsw_sp_nexthop *nh;
2433         bool offload_change = false;
2434         u32 adj_index;
2435         u16 ecmp_size = 0;
2436         bool old_adj_index_valid;
2437         u32 old_adj_index;
2438         u16 old_ecmp_size;
2439         int i;
2440         int err;
2441
2442         if (!nh_grp->gateway) {
2443                 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
2444                 return;
2445         }
2446
2447         for (i = 0; i < nh_grp->count; i++) {
2448                 nh = &nh_grp->nexthops[i];
2449
2450                 if (nh->should_offload != nh->offloaded) {
2451                         offload_change = true;
2452                         if (nh->should_offload)
2453                                 nh->update = 1;
2454                 }
2455                 if (nh->should_offload)
2456                         ecmp_size++;
2457         }
2458         if (!offload_change) {
2459                 /* Nothing was added or removed, so no need to reallocate. Just
2460                  * update MAC on existing adjacency indexes.
2461                  */
2462                 err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nh_grp, false);
2463                 if (err) {
2464                         dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
2465                         goto set_trap;
2466                 }
2467                 return;
2468         }
2469         if (!ecmp_size)
2470                 /* No neigh of this group is connected so we just set
2471                  * the trap and let everthing flow through kernel.
2472                  */
2473                 goto set_trap;
2474
2475         err = mlxsw_sp_kvdl_alloc(mlxsw_sp, ecmp_size, &adj_index);
2476         if (err) {
2477                 /* We ran out of KVD linear space, just set the
2478                  * trap and let everything flow through kernel.
2479                  */
2480                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to allocate KVD linear area for nexthop group.\n");
2481                 goto set_trap;
2482         }
2483         old_adj_index_valid = nh_grp->adj_index_valid;
2484         old_adj_index = nh_grp->adj_index;
2485         old_ecmp_size = nh_grp->ecmp_size;
2486         nh_grp->adj_index_valid = 1;
2487         nh_grp->adj_index = adj_index;
2488         nh_grp->ecmp_size = ecmp_size;
2489         err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nh_grp, true);
2490         if (err) {
2491                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
2492                 goto set_trap;
2493         }
2494
2495         if (!old_adj_index_valid) {
2496                 /* The trap was set for fib entries, so we have to call
2497                  * fib entry update to unset it and use adjacency index.
2498                  */
2499                 err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
2500                 if (err) {
2501                         dev_warn(mlxsw_sp->bus_info->dev, "Failed to add adjacency index to fib entries.\n");
2502                         goto set_trap;
2503                 }
2504                 return;
2505         }
2506
2507         err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, nh_grp,
2508                                              old_adj_index, old_ecmp_size);
2509         mlxsw_sp_kvdl_free(mlxsw_sp, old_adj_index);
2510         if (err) {
2511                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
2512                 goto set_trap;
2513         }
2514
2515         /* Offload state within the group changed, so update the flags. */
2516         mlxsw_sp_nexthop_fib_entries_refresh(nh_grp);
2517
2518         return;
2519
2520 set_trap:
2521         old_adj_index_valid = nh_grp->adj_index_valid;
2522         nh_grp->adj_index_valid = 0;
2523         for (i = 0; i < nh_grp->count; i++) {
2524                 nh = &nh_grp->nexthops[i];
2525                 nh->offloaded = 0;
2526         }
2527         err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
2528         if (err)
2529                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set traps for fib entries.\n");
2530         if (old_adj_index_valid)
2531                 mlxsw_sp_kvdl_free(mlxsw_sp, nh_grp->adj_index);
2532 }
2533
2534 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
2535                                             bool removing)
2536 {
2537         if (!removing)
2538                 nh->should_offload = 1;
2539         else if (nh->offloaded)
2540                 nh->should_offload = 0;
2541         nh->update = 1;
2542 }
2543
2544 static void
2545 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
2546                               struct mlxsw_sp_neigh_entry *neigh_entry,
2547                               bool removing)
2548 {
2549         struct mlxsw_sp_nexthop *nh;
2550
2551         list_for_each_entry(nh, &neigh_entry->nexthop_list,
2552                             neigh_list_node) {
2553                 __mlxsw_sp_nexthop_neigh_update(nh, removing);
2554                 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
2555         }
2556 }
2557
2558 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
2559                                       struct mlxsw_sp_rif *rif)
2560 {
2561         if (nh->rif)
2562                 return;
2563
2564         nh->rif = rif;
2565         list_add(&nh->rif_list_node, &rif->nexthop_list);
2566 }
2567
2568 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh)
2569 {
2570         if (!nh->rif)
2571                 return;
2572
2573         list_del(&nh->rif_list_node);
2574         nh->rif = NULL;
2575 }
2576
2577 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
2578                                        struct mlxsw_sp_nexthop *nh)
2579 {
2580         struct mlxsw_sp_neigh_entry *neigh_entry;
2581         struct neighbour *n;
2582         u8 nud_state, dead;
2583         int err;
2584
2585         if (!nh->nh_grp->gateway || nh->neigh_entry)
2586                 return 0;
2587
2588         /* Take a reference of neigh here ensuring that neigh would
2589          * not be destructed before the nexthop entry is finished.
2590          * The reference is taken either in neigh_lookup() or
2591          * in neigh_create() in case n is not found.
2592          */
2593         n = neigh_lookup(nh->nh_grp->neigh_tbl, &nh->gw_addr, nh->rif->dev);
2594         if (!n) {
2595                 n = neigh_create(nh->nh_grp->neigh_tbl, &nh->gw_addr,
2596                                  nh->rif->dev);
2597                 if (IS_ERR(n))
2598                         return PTR_ERR(n);
2599                 neigh_event_send(n, NULL);
2600         }
2601         neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
2602         if (!neigh_entry) {
2603                 neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
2604                 if (IS_ERR(neigh_entry)) {
2605                         err = -EINVAL;
2606                         goto err_neigh_entry_create;
2607                 }
2608         }
2609
2610         /* If that is the first nexthop connected to that neigh, add to
2611          * nexthop_neighs_list
2612          */
2613         if (list_empty(&neigh_entry->nexthop_list))
2614                 list_add_tail(&neigh_entry->nexthop_neighs_list_node,
2615                               &mlxsw_sp->router->nexthop_neighs_list);
2616
2617         nh->neigh_entry = neigh_entry;
2618         list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
2619         read_lock_bh(&n->lock);
2620         nud_state = n->nud_state;
2621         dead = n->dead;
2622         read_unlock_bh(&n->lock);
2623         __mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
2624
2625         return 0;
2626
2627 err_neigh_entry_create:
2628         neigh_release(n);
2629         return err;
2630 }
2631
2632 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
2633                                         struct mlxsw_sp_nexthop *nh)
2634 {
2635         struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
2636         struct neighbour *n;
2637
2638         if (!neigh_entry)
2639                 return;
2640         n = neigh_entry->key.n;
2641
2642         __mlxsw_sp_nexthop_neigh_update(nh, true);
2643         list_del(&nh->neigh_list_node);
2644         nh->neigh_entry = NULL;
2645
2646         /* If that is the last nexthop connected to that neigh, remove from
2647          * nexthop_neighs_list
2648          */
2649         if (list_empty(&neigh_entry->nexthop_list))
2650                 list_del(&neigh_entry->nexthop_neighs_list_node);
2651
2652         if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
2653                 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
2654
2655         neigh_release(n);
2656 }
2657
2658 static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
2659                                       const struct net_device *dev,
2660                                       enum mlxsw_sp_ipip_type *p_type)
2661 {
2662         struct mlxsw_sp_router *router = mlxsw_sp->router;
2663         const struct mlxsw_sp_ipip_ops *ipip_ops;
2664         enum mlxsw_sp_ipip_type ipipt;
2665
2666         for (ipipt = 0; ipipt < MLXSW_SP_IPIP_TYPE_MAX; ++ipipt) {
2667                 ipip_ops = router->ipip_ops_arr[ipipt];
2668                 if (dev->type == ipip_ops->dev_type) {
2669                         if (p_type)
2670                                 *p_type = ipipt;
2671                         return true;
2672                 }
2673         }
2674         return false;
2675 }
2676
2677 static int mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
2678                                       enum mlxsw_sp_ipip_type ipipt,
2679                                       struct mlxsw_sp_nexthop *nh,
2680                                       struct net_device *ol_dev)
2681 {
2682         if (!nh->nh_grp->gateway || nh->ipip_entry)
2683                 return 0;
2684
2685         nh->ipip_entry = mlxsw_sp_ipip_entry_get(mlxsw_sp, ipipt, ol_dev);
2686         if (IS_ERR(nh->ipip_entry))
2687                 return PTR_ERR(nh->ipip_entry);
2688
2689         __mlxsw_sp_nexthop_neigh_update(nh, false);
2690         return 0;
2691 }
2692
2693 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
2694                                        struct mlxsw_sp_nexthop *nh)
2695 {
2696         struct mlxsw_sp_ipip_entry *ipip_entry = nh->ipip_entry;
2697
2698         if (!ipip_entry)
2699                 return;
2700
2701         __mlxsw_sp_nexthop_neigh_update(nh, true);
2702         mlxsw_sp_ipip_entry_put(mlxsw_sp, ipip_entry);
2703         nh->ipip_entry = NULL;
2704 }
2705
2706 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp *mlxsw_sp,
2707                                         const struct fib_nh *fib_nh,
2708                                         enum mlxsw_sp_ipip_type *p_ipipt)
2709 {
2710         struct net_device *dev = fib_nh->nh_dev;
2711
2712         return dev &&
2713                fib_nh->nh_parent->fib_type == RTN_UNICAST &&
2714                mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, p_ipipt);
2715 }
2716
2717 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
2718                                        struct mlxsw_sp_nexthop *nh)
2719 {
2720         switch (nh->type) {
2721         case MLXSW_SP_NEXTHOP_TYPE_ETH:
2722                 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
2723                 mlxsw_sp_nexthop_rif_fini(nh);
2724                 break;
2725         case MLXSW_SP_NEXTHOP_TYPE_IPIP:
2726                 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
2727                 break;
2728         }
2729 }
2730
2731 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp,
2732                                        struct mlxsw_sp_nexthop *nh,
2733                                        struct fib_nh *fib_nh)
2734 {
2735         struct mlxsw_sp_router *router = mlxsw_sp->router;
2736         struct net_device *dev = fib_nh->nh_dev;
2737         enum mlxsw_sp_ipip_type ipipt;
2738         struct mlxsw_sp_rif *rif;
2739         int err;
2740
2741         if (mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fib_nh, &ipipt) &&
2742             router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
2743                                                      MLXSW_SP_L3_PROTO_IPV4)) {
2744                 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
2745                 return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
2746         }
2747
2748         nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
2749         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
2750         if (!rif)
2751                 return 0;
2752
2753         mlxsw_sp_nexthop_rif_init(nh, rif);
2754         err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
2755         if (err)
2756                 goto err_neigh_init;
2757
2758         return 0;
2759
2760 err_neigh_init:
2761         mlxsw_sp_nexthop_rif_fini(nh);
2762         return err;
2763 }
2764
2765 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp *mlxsw_sp,
2766                                         struct mlxsw_sp_nexthop *nh)
2767 {
2768         mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
2769 }
2770
2771 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
2772                                   struct mlxsw_sp_nexthop_group *nh_grp,
2773                                   struct mlxsw_sp_nexthop *nh,
2774                                   struct fib_nh *fib_nh)
2775 {
2776         struct net_device *dev = fib_nh->nh_dev;
2777         struct in_device *in_dev;
2778         int err;
2779
2780         nh->nh_grp = nh_grp;
2781         nh->key.fib_nh = fib_nh;
2782         memcpy(&nh->gw_addr, &fib_nh->nh_gw, sizeof(fib_nh->nh_gw));
2783         err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
2784         if (err)
2785                 return err;
2786
2787         if (!dev)
2788                 return 0;
2789
2790         in_dev = __in_dev_get_rtnl(dev);
2791         if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
2792             fib_nh->nh_flags & RTNH_F_LINKDOWN)
2793                 return 0;
2794
2795         err = mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
2796         if (err)
2797                 goto err_nexthop_neigh_init;
2798
2799         return 0;
2800
2801 err_nexthop_neigh_init:
2802         mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
2803         return err;
2804 }
2805
2806 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp *mlxsw_sp,
2807                                    struct mlxsw_sp_nexthop *nh)
2808 {
2809         mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh);
2810         mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
2811 }
2812
2813 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
2814                                     unsigned long event, struct fib_nh *fib_nh)
2815 {
2816         struct mlxsw_sp_nexthop_key key;
2817         struct mlxsw_sp_nexthop *nh;
2818
2819         if (mlxsw_sp->router->aborted)
2820                 return;
2821
2822         key.fib_nh = fib_nh;
2823         nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
2824         if (WARN_ON_ONCE(!nh))
2825                 return;
2826
2827         switch (event) {
2828         case FIB_EVENT_NH_ADD:
2829                 mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
2830                 break;
2831         case FIB_EVENT_NH_DEL:
2832                 mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh);
2833                 break;
2834         }
2835
2836         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
2837 }
2838
2839 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
2840                                            struct mlxsw_sp_rif *rif)
2841 {
2842         struct mlxsw_sp_nexthop *nh, *tmp;
2843
2844         list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
2845                 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
2846                 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
2847         }
2848 }
2849
2850 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp,
2851                                    const struct fib_info *fi)
2852 {
2853         return fi->fib_nh->nh_scope == RT_SCOPE_LINK ||
2854                mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fi->fib_nh, NULL);
2855 }
2856
2857 static struct mlxsw_sp_nexthop_group *
2858 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
2859 {
2860         struct mlxsw_sp_nexthop_group *nh_grp;
2861         struct mlxsw_sp_nexthop *nh;
2862         struct fib_nh *fib_nh;
2863         size_t alloc_size;
2864         int i;
2865         int err;
2866
2867         alloc_size = sizeof(*nh_grp) +
2868                      fi->fib_nhs * sizeof(struct mlxsw_sp_nexthop);
2869         nh_grp = kzalloc(alloc_size, GFP_KERNEL);
2870         if (!nh_grp)
2871                 return ERR_PTR(-ENOMEM);
2872         nh_grp->priv = fi;
2873         INIT_LIST_HEAD(&nh_grp->fib_list);
2874         nh_grp->neigh_tbl = &arp_tbl;
2875
2876         nh_grp->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, fi);
2877         nh_grp->count = fi->fib_nhs;
2878         fib_info_hold(fi);
2879         for (i = 0; i < nh_grp->count; i++) {
2880                 nh = &nh_grp->nexthops[i];
2881                 fib_nh = &fi->fib_nh[i];
2882                 err = mlxsw_sp_nexthop4_init(mlxsw_sp, nh_grp, nh, fib_nh);
2883                 if (err)
2884                         goto err_nexthop4_init;
2885         }
2886         err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
2887         if (err)
2888                 goto err_nexthop_group_insert;
2889         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
2890         return nh_grp;
2891
2892 err_nexthop_group_insert:
2893 err_nexthop4_init:
2894         for (i--; i >= 0; i--) {
2895                 nh = &nh_grp->nexthops[i];
2896                 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
2897         }
2898         fib_info_put(fi);
2899         kfree(nh_grp);
2900         return ERR_PTR(err);
2901 }
2902
2903 static void
2904 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp *mlxsw_sp,
2905                                 struct mlxsw_sp_nexthop_group *nh_grp)
2906 {
2907         struct mlxsw_sp_nexthop *nh;
2908         int i;
2909
2910         mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
2911         for (i = 0; i < nh_grp->count; i++) {
2912                 nh = &nh_grp->nexthops[i];
2913                 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
2914         }
2915         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
2916         WARN_ON_ONCE(nh_grp->adj_index_valid);
2917         fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp));
2918         kfree(nh_grp);
2919 }
2920
2921 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp *mlxsw_sp,
2922                                        struct mlxsw_sp_fib_entry *fib_entry,
2923                                        struct fib_info *fi)
2924 {
2925         struct mlxsw_sp_nexthop_group *nh_grp;
2926
2927         nh_grp = mlxsw_sp_nexthop4_group_lookup(mlxsw_sp, fi);
2928         if (!nh_grp) {
2929                 nh_grp = mlxsw_sp_nexthop4_group_create(mlxsw_sp, fi);
2930                 if (IS_ERR(nh_grp))
2931                         return PTR_ERR(nh_grp);
2932         }
2933         list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list);
2934         fib_entry->nh_group = nh_grp;
2935         return 0;
2936 }
2937
2938 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp *mlxsw_sp,
2939                                         struct mlxsw_sp_fib_entry *fib_entry)
2940 {
2941         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
2942
2943         list_del(&fib_entry->nexthop_group_node);
2944         if (!list_empty(&nh_grp->fib_list))
2945                 return;
2946         mlxsw_sp_nexthop4_group_destroy(mlxsw_sp, nh_grp);
2947 }
2948
2949 static bool
2950 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
2951 {
2952         struct mlxsw_sp_fib4_entry *fib4_entry;
2953
2954         fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
2955                                   common);
2956         return !fib4_entry->tos;
2957 }
2958
2959 static bool
2960 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
2961 {
2962         struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
2963
2964         switch (fib_entry->fib_node->fib->proto) {
2965         case MLXSW_SP_L3_PROTO_IPV4:
2966                 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry))
2967                         return false;
2968                 break;
2969         case MLXSW_SP_L3_PROTO_IPV6:
2970                 break;
2971         }
2972
2973         switch (fib_entry->type) {
2974         case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
2975                 return !!nh_group->adj_index_valid;
2976         case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
2977                 return !!nh_group->nh_rif;
2978         case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
2979                 return true;
2980         default:
2981                 return false;
2982         }
2983 }
2984
2985 static struct mlxsw_sp_nexthop *
2986 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
2987                      const struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
2988 {
2989         int i;
2990
2991         for (i = 0; i < nh_grp->count; i++) {
2992                 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
2993                 struct rt6_info *rt = mlxsw_sp_rt6->rt;
2994
2995                 if (nh->rif && nh->rif->dev == rt->dst.dev &&
2996                     ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
2997                                     &rt->rt6i_gateway))
2998                         return nh;
2999                 continue;
3000         }
3001
3002         return NULL;
3003 }
3004
3005 static void
3006 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3007 {
3008         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
3009         int i;
3010
3011         if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
3012             fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP) {
3013                 nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
3014                 return;
3015         }
3016
3017         for (i = 0; i < nh_grp->count; i++) {
3018                 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
3019
3020                 if (nh->offloaded)
3021                         nh->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
3022                 else
3023                         nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
3024         }
3025 }
3026
3027 static void
3028 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
3029 {
3030         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
3031         int i;
3032
3033         for (i = 0; i < nh_grp->count; i++) {
3034                 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
3035
3036                 nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
3037         }
3038 }
3039
3040 static void
3041 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3042 {
3043         struct mlxsw_sp_fib6_entry *fib6_entry;
3044         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3045
3046         fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
3047                                   common);
3048
3049         if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) {
3050                 list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
3051                                  list)->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD;
3052                 return;
3053         }
3054
3055         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3056                 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
3057                 struct mlxsw_sp_nexthop *nh;
3058
3059                 nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
3060                 if (nh && nh->offloaded)
3061                         mlxsw_sp_rt6->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD;
3062                 else
3063                         mlxsw_sp_rt6->rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD;
3064         }
3065 }
3066
3067 static void
3068 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
3069 {
3070         struct mlxsw_sp_fib6_entry *fib6_entry;
3071         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3072
3073         fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
3074                                   common);
3075         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3076                 struct rt6_info *rt = mlxsw_sp_rt6->rt;
3077
3078                 rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD;
3079         }
3080 }
3081
3082 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3083 {
3084         switch (fib_entry->fib_node->fib->proto) {
3085         case MLXSW_SP_L3_PROTO_IPV4:
3086                 mlxsw_sp_fib4_entry_offload_set(fib_entry);
3087                 break;
3088         case MLXSW_SP_L3_PROTO_IPV6:
3089                 mlxsw_sp_fib6_entry_offload_set(fib_entry);
3090                 break;
3091         }
3092 }
3093
3094 static void
3095 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
3096 {
3097         switch (fib_entry->fib_node->fib->proto) {
3098         case MLXSW_SP_L3_PROTO_IPV4:
3099                 mlxsw_sp_fib4_entry_offload_unset(fib_entry);
3100                 break;
3101         case MLXSW_SP_L3_PROTO_IPV6:
3102                 mlxsw_sp_fib6_entry_offload_unset(fib_entry);
3103                 break;
3104         }
3105 }
3106
3107 static void
3108 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry,
3109                                    enum mlxsw_reg_ralue_op op, int err)
3110 {
3111         switch (op) {
3112         case MLXSW_REG_RALUE_OP_WRITE_DELETE:
3113                 return mlxsw_sp_fib_entry_offload_unset(fib_entry);
3114         case MLXSW_REG_RALUE_OP_WRITE_WRITE:
3115                 if (err)
3116                         return;
3117                 if (mlxsw_sp_fib_entry_should_offload(fib_entry))
3118                         mlxsw_sp_fib_entry_offload_set(fib_entry);
3119                 else if (!mlxsw_sp_fib_entry_should_offload(fib_entry))
3120                         mlxsw_sp_fib_entry_offload_unset(fib_entry);
3121                 return;
3122         default:
3123                 return;
3124         }
3125 }
3126
3127 static void
3128 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl,
3129                               const struct mlxsw_sp_fib_entry *fib_entry,
3130                               enum mlxsw_reg_ralue_op op)
3131 {
3132         struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
3133         enum mlxsw_reg_ralxx_protocol proto;
3134         u32 *p_dip;
3135
3136         proto = (enum mlxsw_reg_ralxx_protocol) fib->proto;
3137
3138         switch (fib->proto) {
3139         case MLXSW_SP_L3_PROTO_IPV4:
3140                 p_dip = (u32 *) fib_entry->fib_node->key.addr;
3141                 mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id,
3142                                       fib_entry->fib_node->key.prefix_len,
3143                                       *p_dip);
3144                 break;
3145         case MLXSW_SP_L3_PROTO_IPV6:
3146                 mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id,
3147                                       fib_entry->fib_node->key.prefix_len,
3148                                       fib_entry->fib_node->key.addr);
3149                 break;
3150         }
3151 }
3152
3153 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
3154                                         struct mlxsw_sp_fib_entry *fib_entry,
3155                                         enum mlxsw_reg_ralue_op op)
3156 {
3157         char ralue_pl[MLXSW_REG_RALUE_LEN];
3158         enum mlxsw_reg_ralue_trap_action trap_action;
3159         u16 trap_id = 0;
3160         u32 adjacency_index = 0;
3161         u16 ecmp_size = 0;
3162
3163         /* In case the nexthop group adjacency index is valid, use it
3164          * with provided ECMP size. Otherwise, setup trap and pass
3165          * traffic to kernel.
3166          */
3167         if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
3168                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
3169                 adjacency_index = fib_entry->nh_group->adj_index;
3170                 ecmp_size = fib_entry->nh_group->ecmp_size;
3171         } else {
3172                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
3173                 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
3174         }
3175
3176         mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
3177         mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id,
3178                                         adjacency_index, ecmp_size);
3179         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
3180 }
3181
3182 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
3183                                        struct mlxsw_sp_fib_entry *fib_entry,
3184                                        enum mlxsw_reg_ralue_op op)
3185 {
3186         struct mlxsw_sp_rif *rif = fib_entry->nh_group->nh_rif;
3187         enum mlxsw_reg_ralue_trap_action trap_action;
3188         char ralue_pl[MLXSW_REG_RALUE_LEN];
3189         u16 trap_id = 0;
3190         u16 rif_index = 0;
3191
3192         if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
3193                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
3194                 rif_index = rif->rif_index;
3195         } else {
3196                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
3197                 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
3198         }
3199
3200         mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
3201         mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id,
3202                                        rif_index);
3203         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
3204 }
3205
3206 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
3207                                       struct mlxsw_sp_fib_entry *fib_entry,
3208                                       enum mlxsw_reg_ralue_op op)
3209 {
3210         char ralue_pl[MLXSW_REG_RALUE_LEN];
3211
3212         mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
3213         mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
3214         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
3215 }
3216
3217 static int
3218 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
3219                                  struct mlxsw_sp_fib_entry *fib_entry,
3220                                  enum mlxsw_reg_ralue_op op)
3221 {
3222         struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry;
3223         const struct mlxsw_sp_ipip_ops *ipip_ops;
3224
3225         if (WARN_ON(!ipip_entry))
3226                 return -EINVAL;
3227
3228         ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
3229         return ipip_ops->fib_entry_op(mlxsw_sp, ipip_entry, op,
3230                                       fib_entry->decap.tunnel_index);
3231 }
3232
3233 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
3234                                    struct mlxsw_sp_fib_entry *fib_entry,
3235                                    enum mlxsw_reg_ralue_op op)
3236 {
3237         switch (fib_entry->type) {
3238         case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
3239                 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op);
3240         case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
3241                 return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
3242         case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
3243                 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
3244         case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
3245                 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
3246                                                         fib_entry, op);
3247         }
3248         return -EINVAL;
3249 }
3250
3251 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
3252                                  struct mlxsw_sp_fib_entry *fib_entry,
3253                                  enum mlxsw_reg_ralue_op op)
3254 {
3255         int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op);
3256
3257         mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, err);
3258
3259         return err;
3260 }
3261
3262 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
3263                                      struct mlxsw_sp_fib_entry *fib_entry)
3264 {
3265         return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
3266                                      MLXSW_REG_RALUE_OP_WRITE_WRITE);
3267 }
3268
3269 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
3270                                   struct mlxsw_sp_fib_entry *fib_entry)
3271 {
3272         return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
3273                                      MLXSW_REG_RALUE_OP_WRITE_DELETE);
3274 }
3275
3276 static int
3277 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
3278                              const struct fib_entry_notifier_info *fen_info,
3279                              struct mlxsw_sp_fib_entry *fib_entry)
3280 {
3281         union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) };
3282         struct net_device *dev = fen_info->fi->fib_dev;
3283         struct mlxsw_sp_ipip_entry *ipip_entry;
3284         struct fib_info *fi = fen_info->fi;
3285
3286         switch (fen_info->type) {
3287         case RTN_LOCAL:
3288                 ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, dev,
3289                                                  MLXSW_SP_L3_PROTO_IPV4, dip);
3290                 if (ipip_entry) {
3291                         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
3292                         return mlxsw_sp_fib_entry_decap_init(mlxsw_sp,
3293                                                              fib_entry,
3294                                                              ipip_entry);
3295                 }
3296                 /* fall through */
3297         case RTN_BROADCAST:
3298                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
3299                 return 0;
3300         case RTN_UNREACHABLE: /* fall through */
3301         case RTN_BLACKHOLE: /* fall through */
3302         case RTN_PROHIBIT:
3303                 /* Packets hitting these routes need to be trapped, but
3304                  * can do so with a lower priority than packets directed
3305                  * at the host, so use action type local instead of trap.
3306                  */
3307                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
3308                 return 0;
3309         case RTN_UNICAST:
3310                 if (mlxsw_sp_fi_is_gateway(mlxsw_sp, fi))
3311                         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
3312                 else
3313                         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
3314                 return 0;
3315         default:
3316                 return -EINVAL;
3317         }
3318 }
3319
3320 static struct mlxsw_sp_fib4_entry *
3321 mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
3322                            struct mlxsw_sp_fib_node *fib_node,
3323                            const struct fib_entry_notifier_info *fen_info)
3324 {
3325         struct mlxsw_sp_fib4_entry *fib4_entry;
3326         struct mlxsw_sp_fib_entry *fib_entry;
3327         int err;
3328
3329         fib4_entry = kzalloc(sizeof(*fib4_entry), GFP_KERNEL);
3330         if (!fib4_entry)
3331                 return ERR_PTR(-ENOMEM);
3332         fib_entry = &fib4_entry->common;
3333
3334         err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry);
3335         if (err)
3336                 goto err_fib4_entry_type_set;
3337
3338         err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi);
3339         if (err)
3340                 goto err_nexthop4_group_get;
3341
3342         fib4_entry->prio = fen_info->fi->fib_priority;
3343         fib4_entry->tb_id = fen_info->tb_id;
3344         fib4_entry->type = fen_info->type;
3345         fib4_entry->tos = fen_info->tos;
3346
3347         fib_entry->fib_node = fib_node;
3348
3349         return fib4_entry;
3350
3351 err_nexthop4_group_get:
3352 err_fib4_entry_type_set:
3353         kfree(fib4_entry);
3354         return ERR_PTR(err);
3355 }
3356
3357 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
3358                                         struct mlxsw_sp_fib4_entry *fib4_entry)
3359 {
3360         mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
3361         kfree(fib4_entry);
3362 }
3363
3364 static struct mlxsw_sp_fib4_entry *
3365 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
3366                            const struct fib_entry_notifier_info *fen_info)
3367 {
3368         struct mlxsw_sp_fib4_entry *fib4_entry;
3369         struct mlxsw_sp_fib_node *fib_node;
3370         struct mlxsw_sp_fib *fib;
3371         struct mlxsw_sp_vr *vr;
3372
3373         vr = mlxsw_sp_vr_find(mlxsw_sp, fen_info->tb_id);
3374         if (!vr)
3375                 return NULL;
3376         fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4);
3377
3378         fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst,
3379                                             sizeof(fen_info->dst),
3380                                             fen_info->dst_len);
3381         if (!fib_node)
3382                 return NULL;
3383
3384         list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
3385                 if (fib4_entry->tb_id == fen_info->tb_id &&
3386                     fib4_entry->tos == fen_info->tos &&
3387                     fib4_entry->type == fen_info->type &&
3388                     mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) ==
3389                     fen_info->fi) {
3390                         return fib4_entry;
3391                 }
3392         }
3393
3394         return NULL;
3395 }
3396
3397 static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
3398         .key_offset = offsetof(struct mlxsw_sp_fib_node, key),
3399         .head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node),
3400         .key_len = sizeof(struct mlxsw_sp_fib_key),
3401         .automatic_shrinking = true,
3402 };
3403
3404 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib,
3405                                     struct mlxsw_sp_fib_node *fib_node)
3406 {
3407         return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node,
3408                                       mlxsw_sp_fib_ht_params);
3409 }
3410
3411 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib,
3412                                      struct mlxsw_sp_fib_node *fib_node)
3413 {
3414         rhashtable_remove_fast(&fib->ht, &fib_node->ht_node,
3415                                mlxsw_sp_fib_ht_params);
3416 }
3417
3418 static struct mlxsw_sp_fib_node *
3419 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
3420                          size_t addr_len, unsigned char prefix_len)
3421 {
3422         struct mlxsw_sp_fib_key key;
3423
3424         memset(&key, 0, sizeof(key));
3425         memcpy(key.addr, addr, addr_len);
3426         key.prefix_len = prefix_len;
3427         return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
3428 }
3429
3430 static struct mlxsw_sp_fib_node *
3431 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
3432                          size_t addr_len, unsigned char prefix_len)
3433 {
3434         struct mlxsw_sp_fib_node *fib_node;
3435
3436         fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL);
3437         if (!fib_node)
3438                 return NULL;
3439
3440         INIT_LIST_HEAD(&fib_node->entry_list);
3441         list_add(&fib_node->list, &fib->node_list);
3442         memcpy(fib_node->key.addr, addr, addr_len);
3443         fib_node->key.prefix_len = prefix_len;
3444
3445         return fib_node;
3446 }
3447
3448 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
3449 {
3450         list_del(&fib_node->list);
3451         WARN_ON(!list_empty(&fib_node->entry_list));
3452         kfree(fib_node);
3453 }
3454
3455 static bool
3456 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node,
3457                                  const struct mlxsw_sp_fib_entry *fib_entry)
3458 {
3459         return list_first_entry(&fib_node->entry_list,
3460                                 struct mlxsw_sp_fib_entry, list) == fib_entry;
3461 }
3462
3463 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp,
3464                                       struct mlxsw_sp_fib *fib,
3465                                       struct mlxsw_sp_fib_node *fib_node)
3466 {
3467         struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
3468         struct mlxsw_sp_lpm_tree *lpm_tree;
3469         int err;
3470
3471         /* Since the tree is shared between all virtual routers we must
3472          * make sure it contains all the required prefix lengths. This
3473          * can be computed by either adding the new prefix length to the
3474          * existing prefix usage of a bound tree, or by aggregating the
3475          * prefix lengths across all virtual routers and adding the new
3476          * one as well.
3477          */
3478         if (fib->lpm_tree)
3479                 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage,
3480                                           &fib->lpm_tree->prefix_usage);
3481         else
3482                 mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage);
3483         mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len);
3484
3485         lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
3486                                          fib->proto);
3487         if (IS_ERR(lpm_tree))
3488                 return PTR_ERR(lpm_tree);
3489
3490         if (fib->lpm_tree && fib->lpm_tree->id == lpm_tree->id)
3491                 return 0;
3492
3493         err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
3494         if (err)
3495                 return err;
3496
3497         return 0;
3498 }
3499
3500 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp,
3501                                          struct mlxsw_sp_fib *fib)
3502 {
3503         struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
3504         struct mlxsw_sp_lpm_tree *lpm_tree;
3505
3506         /* Aggregate prefix lengths across all virtual routers to make
3507          * sure we only have used prefix lengths in the LPM tree.
3508          */
3509         mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage);
3510         lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
3511                                          fib->proto);
3512         if (IS_ERR(lpm_tree))
3513                 goto err_tree_get;
3514         mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
3515
3516 err_tree_get:
3517         if (!mlxsw_sp_prefix_usage_none(&fib->prefix_usage))
3518                 return;
3519         mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
3520         mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree);
3521         fib->lpm_tree = NULL;
3522 }
3523
3524 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node *fib_node)
3525 {
3526         unsigned char prefix_len = fib_node->key.prefix_len;
3527         struct mlxsw_sp_fib *fib = fib_node->fib;
3528
3529         if (fib->prefix_ref_count[prefix_len]++ == 0)
3530                 mlxsw_sp_prefix_usage_set(&fib->prefix_usage, prefix_len);
3531 }
3532
3533 static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node *fib_node)
3534 {
3535         unsigned char prefix_len = fib_node->key.prefix_len;
3536         struct mlxsw_sp_fib *fib = fib_node->fib;
3537
3538         if (--fib->prefix_ref_count[prefix_len] == 0)
3539                 mlxsw_sp_prefix_usage_clear(&fib->prefix_usage, prefix_len);
3540 }
3541
3542 static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
3543                                   struct mlxsw_sp_fib_node *fib_node,
3544                                   struct mlxsw_sp_fib *fib)
3545 {
3546         int err;
3547
3548         err = mlxsw_sp_fib_node_insert(fib, fib_node);
3549         if (err)
3550                 return err;
3551         fib_node->fib = fib;
3552
3553         err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib, fib_node);
3554         if (err)
3555                 goto err_fib_lpm_tree_link;
3556
3557         mlxsw_sp_fib_node_prefix_inc(fib_node);
3558
3559         return 0;
3560
3561 err_fib_lpm_tree_link:
3562         fib_node->fib = NULL;
3563         mlxsw_sp_fib_node_remove(fib, fib_node);
3564         return err;
3565 }
3566
3567 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
3568                                    struct mlxsw_sp_fib_node *fib_node)
3569 {
3570         struct mlxsw_sp_fib *fib = fib_node->fib;
3571
3572         mlxsw_sp_fib_node_prefix_dec(fib_node);
3573         mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib);
3574         fib_node->fib = NULL;
3575         mlxsw_sp_fib_node_remove(fib, fib_node);
3576 }
3577
3578 static struct mlxsw_sp_fib_node *
3579 mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
3580                       size_t addr_len, unsigned char prefix_len,
3581                       enum mlxsw_sp_l3proto proto)
3582 {
3583         struct mlxsw_sp_fib_node *fib_node;
3584         struct mlxsw_sp_fib *fib;
3585         struct mlxsw_sp_vr *vr;
3586         int err;
3587
3588         vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id);
3589         if (IS_ERR(vr))
3590                 return ERR_CAST(vr);
3591         fib = mlxsw_sp_vr_fib(vr, proto);
3592
3593         fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len);
3594         if (fib_node)
3595                 return fib_node;
3596
3597         fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len);
3598         if (!fib_node) {
3599                 err = -ENOMEM;
3600                 goto err_fib_node_create;
3601         }
3602
3603         err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
3604         if (err)
3605                 goto err_fib_node_init;
3606
3607         return fib_node;
3608
3609 err_fib_node_init:
3610         mlxsw_sp_fib_node_destroy(fib_node);
3611 err_fib_node_create:
3612         mlxsw_sp_vr_put(vr);
3613         return ERR_PTR(err);
3614 }
3615
3616 static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
3617                                   struct mlxsw_sp_fib_node *fib_node)
3618 {
3619         struct mlxsw_sp_vr *vr = fib_node->fib->vr;
3620
3621         if (!list_empty(&fib_node->entry_list))
3622                 return;
3623         mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
3624         mlxsw_sp_fib_node_destroy(fib_node);
3625         mlxsw_sp_vr_put(vr);
3626 }
3627
3628 static struct mlxsw_sp_fib4_entry *
3629 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
3630                               const struct mlxsw_sp_fib4_entry *new4_entry)
3631 {
3632         struct mlxsw_sp_fib4_entry *fib4_entry;
3633
3634         list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
3635                 if (fib4_entry->tb_id > new4_entry->tb_id)
3636                         continue;
3637                 if (fib4_entry->tb_id != new4_entry->tb_id)
3638                         break;
3639                 if (fib4_entry->tos > new4_entry->tos)
3640                         continue;
3641                 if (fib4_entry->prio >= new4_entry->prio ||
3642                     fib4_entry->tos < new4_entry->tos)
3643                         return fib4_entry;
3644         }
3645
3646         return NULL;
3647 }
3648
3649 static int
3650 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry *fib4_entry,
3651                                struct mlxsw_sp_fib4_entry *new4_entry)
3652 {
3653         struct mlxsw_sp_fib_node *fib_node;
3654
3655         if (WARN_ON(!fib4_entry))
3656                 return -EINVAL;
3657
3658         fib_node = fib4_entry->common.fib_node;
3659         list_for_each_entry_from(fib4_entry, &fib_node->entry_list,
3660                                  common.list) {
3661                 if (fib4_entry->tb_id != new4_entry->tb_id ||
3662                     fib4_entry->tos != new4_entry->tos ||
3663                     fib4_entry->prio != new4_entry->prio)
3664                         break;
3665         }
3666
3667         list_add_tail(&new4_entry->common.list, &fib4_entry->common.list);
3668         return 0;
3669 }
3670
3671 static int
3672 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry *new4_entry,
3673                                bool replace, bool append)
3674 {
3675         struct mlxsw_sp_fib_node *fib_node = new4_entry->common.fib_node;
3676         struct mlxsw_sp_fib4_entry *fib4_entry;
3677
3678         fib4_entry = mlxsw_sp_fib4_node_entry_find(fib_node, new4_entry);
3679
3680         if (append)
3681                 return mlxsw_sp_fib4_node_list_append(fib4_entry, new4_entry);
3682         if (replace && WARN_ON(!fib4_entry))
3683                 return -EINVAL;
3684
3685         /* Insert new entry before replaced one, so that we can later
3686          * remove the second.
3687          */
3688         if (fib4_entry) {
3689                 list_add_tail(&new4_entry->common.list,
3690                               &fib4_entry->common.list);
3691         } else {
3692                 struct mlxsw_sp_fib4_entry *last;
3693
3694                 list_for_each_entry(last, &fib_node->entry_list, common.list) {
3695                         if (new4_entry->tb_id > last->tb_id)
3696                                 break;
3697                         fib4_entry = last;
3698                 }
3699
3700                 if (fib4_entry)
3701                         list_add(&new4_entry->common.list,
3702                                  &fib4_entry->common.list);
3703                 else
3704                         list_add(&new4_entry->common.list,
3705                                  &fib_node->entry_list);
3706         }
3707
3708         return 0;
3709 }
3710
3711 static void
3712 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry *fib4_entry)
3713 {
3714         list_del(&fib4_entry->common.list);
3715 }
3716
3717 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp *mlxsw_sp,
3718                                        struct mlxsw_sp_fib_entry *fib_entry)
3719 {
3720         struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
3721
3722         if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
3723                 return 0;
3724
3725         /* To prevent packet loss, overwrite the previously offloaded
3726          * entry.
3727          */
3728         if (!list_is_singular(&fib_node->entry_list)) {
3729                 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
3730                 struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
3731
3732                 mlxsw_sp_fib_entry_offload_refresh(n, op, 0);
3733         }
3734
3735         return mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
3736 }
3737
3738 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp *mlxsw_sp,
3739                                         struct mlxsw_sp_fib_entry *fib_entry)
3740 {
3741         struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
3742
3743         if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
3744                 return;
3745
3746         /* Promote the next entry by overwriting the deleted entry */
3747         if (!list_is_singular(&fib_node->entry_list)) {
3748                 struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
3749                 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
3750
3751                 mlxsw_sp_fib_entry_update(mlxsw_sp, n);
3752                 mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
3753                 return;
3754         }
3755
3756         mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
3757 }
3758
3759 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
3760                                          struct mlxsw_sp_fib4_entry *fib4_entry,
3761                                          bool replace, bool append)
3762 {
3763         int err;
3764
3765         err = mlxsw_sp_fib4_node_list_insert(fib4_entry, replace, append);
3766         if (err)
3767                 return err;
3768
3769         err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib4_entry->common);
3770         if (err)
3771                 goto err_fib_node_entry_add;
3772
3773         return 0;
3774
3775 err_fib_node_entry_add:
3776         mlxsw_sp_fib4_node_list_remove(fib4_entry);
3777         return err;
3778 }
3779
3780 static void
3781 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
3782                                 struct mlxsw_sp_fib4_entry *fib4_entry)
3783 {
3784         mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib4_entry->common);
3785         mlxsw_sp_fib4_node_list_remove(fib4_entry);
3786
3787         if (fib4_entry->common.type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP)
3788                 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, &fib4_entry->common);
3789 }
3790
3791 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
3792                                         struct mlxsw_sp_fib4_entry *fib4_entry,
3793                                         bool replace)
3794 {
3795         struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
3796         struct mlxsw_sp_fib4_entry *replaced;
3797
3798         if (!replace)
3799                 return;
3800
3801         /* We inserted the new entry before replaced one */
3802         replaced = list_next_entry(fib4_entry, common.list);
3803
3804         mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, replaced);
3805         mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced);
3806         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3807 }
3808
3809 static int
3810 mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
3811                          const struct fib_entry_notifier_info *fen_info,
3812                          bool replace, bool append)
3813 {
3814         struct mlxsw_sp_fib4_entry *fib4_entry;
3815         struct mlxsw_sp_fib_node *fib_node;
3816         int err;
3817
3818         if (mlxsw_sp->router->aborted)
3819                 return 0;
3820
3821         fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
3822                                          &fen_info->dst, sizeof(fen_info->dst),
3823                                          fen_info->dst_len,
3824                                          MLXSW_SP_L3_PROTO_IPV4);
3825         if (IS_ERR(fib_node)) {
3826                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
3827                 return PTR_ERR(fib_node);
3828         }
3829
3830         fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
3831         if (IS_ERR(fib4_entry)) {
3832                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
3833                 err = PTR_ERR(fib4_entry);
3834                 goto err_fib4_entry_create;
3835         }
3836
3837         err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry, replace,
3838                                             append);
3839         if (err) {
3840                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
3841                 goto err_fib4_node_entry_link;
3842         }
3843
3844         mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry, replace);
3845
3846         return 0;
3847
3848 err_fib4_node_entry_link:
3849         mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
3850 err_fib4_entry_create:
3851         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3852         return err;
3853 }
3854
3855 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
3856                                      struct fib_entry_notifier_info *fen_info)
3857 {
3858         struct mlxsw_sp_fib4_entry *fib4_entry;
3859         struct mlxsw_sp_fib_node *fib_node;
3860
3861         if (mlxsw_sp->router->aborted)
3862                 return;
3863
3864         fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
3865         if (WARN_ON(!fib4_entry))
3866                 return;
3867         fib_node = fib4_entry->common.fib_node;
3868
3869         mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
3870         mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
3871         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3872 }
3873
3874 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info *rt)
3875 {
3876         /* Packets with link-local destination IP arriving to the router
3877          * are trapped to the CPU, so no need to program specific routes
3878          * for them.
3879          */
3880         if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LINKLOCAL)
3881                 return true;
3882
3883         /* Multicast routes aren't supported, so ignore them. Neighbour
3884          * Discovery packets are specifically trapped.
3885          */
3886         if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_MULTICAST)
3887                 return true;
3888
3889         /* Cloned routes are irrelevant in the forwarding path. */
3890         if (rt->rt6i_flags & RTF_CACHE)
3891                 return true;
3892
3893         return false;
3894 }
3895
3896 static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct rt6_info *rt)
3897 {
3898         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3899
3900         mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL);
3901         if (!mlxsw_sp_rt6)
3902                 return ERR_PTR(-ENOMEM);
3903
3904         /* In case of route replace, replaced route is deleted with
3905          * no notification. Take reference to prevent accessing freed
3906          * memory.
3907          */
3908         mlxsw_sp_rt6->rt = rt;
3909         rt6_hold(rt);
3910
3911         return mlxsw_sp_rt6;
3912 }
3913
3914 #if IS_ENABLED(CONFIG_IPV6)
3915 static void mlxsw_sp_rt6_release(struct rt6_info *rt)
3916 {
3917         rt6_release(rt);
3918 }
3919 #else
3920 static void mlxsw_sp_rt6_release(struct rt6_info *rt)
3921 {
3922 }
3923 #endif
3924
3925 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
3926 {
3927         mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
3928         kfree(mlxsw_sp_rt6);
3929 }
3930
3931 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info *rt)
3932 {
3933         /* RTF_CACHE routes are ignored */
3934         return (rt->rt6i_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
3935 }
3936
3937 static struct rt6_info *
3938 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
3939 {
3940         return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
3941                                 list)->rt;
3942 }
3943
3944 static struct mlxsw_sp_fib6_entry *
3945 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
3946                                  const struct rt6_info *nrt, bool replace)
3947 {
3948         struct mlxsw_sp_fib6_entry *fib6_entry;
3949
3950         if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
3951                 return NULL;
3952
3953         list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
3954                 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
3955
3956                 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
3957                  * virtual router.
3958                  */
3959                 if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
3960                         continue;
3961                 if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
3962                         break;
3963                 if (rt->rt6i_metric < nrt->rt6i_metric)
3964                         continue;
3965                 if (rt->rt6i_metric == nrt->rt6i_metric &&
3966                     mlxsw_sp_fib6_rt_can_mp(rt))
3967                         return fib6_entry;
3968                 if (rt->rt6i_metric > nrt->rt6i_metric)
3969                         break;
3970         }
3971
3972         return NULL;
3973 }
3974
3975 static struct mlxsw_sp_rt6 *
3976 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
3977                             const struct rt6_info *rt)
3978 {
3979         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3980
3981         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3982                 if (mlxsw_sp_rt6->rt == rt)
3983                         return mlxsw_sp_rt6;
3984         }
3985
3986         return NULL;
3987 }
3988
3989 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
3990                                         const struct rt6_info *rt,
3991                                         enum mlxsw_sp_ipip_type *ret)
3992 {
3993         return rt->dst.dev &&
3994                mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->dst.dev, ret);
3995 }
3996
3997 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
3998                                        struct mlxsw_sp_nexthop_group *nh_grp,
3999                                        struct mlxsw_sp_nexthop *nh,
4000                                        const struct rt6_info *rt)
4001 {
4002         struct mlxsw_sp_router *router = mlxsw_sp->router;
4003         struct net_device *dev = rt->dst.dev;
4004         enum mlxsw_sp_ipip_type ipipt;
4005         struct mlxsw_sp_rif *rif;
4006         int err;
4007
4008         if (mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, &ipipt) &&
4009             router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
4010                                                      MLXSW_SP_L3_PROTO_IPV6)) {
4011                 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
4012                 return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
4013         }
4014
4015         nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
4016         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
4017         if (!rif)
4018                 return 0;
4019         mlxsw_sp_nexthop_rif_init(nh, rif);
4020
4021         err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
4022         if (err)
4023                 goto err_nexthop_neigh_init;
4024
4025         return 0;
4026
4027 err_nexthop_neigh_init:
4028         mlxsw_sp_nexthop_rif_fini(nh);
4029         return err;
4030 }
4031
4032 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp *mlxsw_sp,
4033                                         struct mlxsw_sp_nexthop *nh)
4034 {
4035         mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4036 }
4037
4038 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
4039                                   struct mlxsw_sp_nexthop_group *nh_grp,
4040                                   struct mlxsw_sp_nexthop *nh,
4041                                   const struct rt6_info *rt)
4042 {
4043         struct net_device *dev = rt->dst.dev;
4044
4045         nh->nh_grp = nh_grp;
4046         memcpy(&nh->gw_addr, &rt->rt6i_gateway, sizeof(nh->gw_addr));
4047
4048         if (!dev)
4049                 return 0;
4050         nh->ifindex = dev->ifindex;
4051
4052         return mlxsw_sp_nexthop6_type_init(mlxsw_sp, nh_grp, nh, rt);
4053 }
4054
4055 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
4056                                    struct mlxsw_sp_nexthop *nh)
4057 {
4058         mlxsw_sp_nexthop6_type_fini(mlxsw_sp, nh);
4059 }
4060
4061 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
4062                                     const struct rt6_info *rt)
4063 {
4064         return rt->rt6i_flags & RTF_GATEWAY ||
4065                mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
4066 }
4067
4068 static struct mlxsw_sp_nexthop_group *
4069 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
4070                                struct mlxsw_sp_fib6_entry *fib6_entry)
4071 {
4072         struct mlxsw_sp_nexthop_group *nh_grp;
4073         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4074         struct mlxsw_sp_nexthop *nh;
4075         size_t alloc_size;
4076         int i = 0;
4077         int err;
4078
4079         alloc_size = sizeof(*nh_grp) +
4080                      fib6_entry->nrt6 * sizeof(struct mlxsw_sp_nexthop);
4081         nh_grp = kzalloc(alloc_size, GFP_KERNEL);
4082         if (!nh_grp)
4083                 return ERR_PTR(-ENOMEM);
4084         INIT_LIST_HEAD(&nh_grp->fib_list);
4085 #if IS_ENABLED(CONFIG_IPV6)
4086         nh_grp->neigh_tbl = &nd_tbl;
4087 #endif
4088         mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
4089                                         struct mlxsw_sp_rt6, list);
4090         nh_grp->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
4091         nh_grp->count = fib6_entry->nrt6;
4092         for (i = 0; i < nh_grp->count; i++) {
4093                 struct rt6_info *rt = mlxsw_sp_rt6->rt;
4094
4095                 nh = &nh_grp->nexthops[i];
4096                 err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt);
4097                 if (err)
4098                         goto err_nexthop6_init;
4099                 mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list);
4100         }
4101
4102         err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
4103         if (err)
4104                 goto err_nexthop_group_insert;
4105
4106         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4107         return nh_grp;
4108
4109 err_nexthop_group_insert:
4110 err_nexthop6_init:
4111         for (i--; i >= 0; i--) {
4112                 nh = &nh_grp->nexthops[i];
4113                 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
4114         }
4115         kfree(nh_grp);
4116         return ERR_PTR(err);
4117 }
4118
4119 static void
4120 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp,
4121                                 struct mlxsw_sp_nexthop_group *nh_grp)
4122 {
4123         struct mlxsw_sp_nexthop *nh;
4124         int i = nh_grp->count;
4125
4126         mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
4127         for (i--; i >= 0; i--) {
4128                 nh = &nh_grp->nexthops[i];
4129                 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
4130         }
4131         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4132         WARN_ON(nh_grp->adj_index_valid);
4133         kfree(nh_grp);
4134 }
4135
4136 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp,
4137                                        struct mlxsw_sp_fib6_entry *fib6_entry)
4138 {
4139         struct mlxsw_sp_nexthop_group *nh_grp;
4140
4141         nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry);
4142         if (!nh_grp) {
4143                 nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry);
4144                 if (IS_ERR(nh_grp))
4145                         return PTR_ERR(nh_grp);
4146         }
4147
4148         list_add_tail(&fib6_entry->common.nexthop_group_node,
4149                       &nh_grp->fib_list);
4150         fib6_entry->common.nh_group = nh_grp;
4151
4152         return 0;
4153 }
4154
4155 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp,
4156                                         struct mlxsw_sp_fib_entry *fib_entry)
4157 {
4158         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
4159
4160         list_del(&fib_entry->nexthop_group_node);
4161         if (!list_empty(&nh_grp->fib_list))
4162                 return;
4163         mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp);
4164 }
4165
4166 static int
4167 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
4168                                struct mlxsw_sp_fib6_entry *fib6_entry)
4169 {
4170         struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group;
4171         int err;
4172
4173         fib6_entry->common.nh_group = NULL;
4174         list_del(&fib6_entry->common.nexthop_group_node);
4175
4176         err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
4177         if (err)
4178                 goto err_nexthop6_group_get;
4179
4180         /* In case this entry is offloaded, then the adjacency index
4181          * currently associated with it in the device's table is that
4182          * of the old group. Start using the new one instead.
4183          */
4184         err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
4185         if (err)
4186                 goto err_fib_node_entry_add;
4187
4188         if (list_empty(&old_nh_grp->fib_list))
4189                 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
4190
4191         return 0;
4192
4193 err_fib_node_entry_add:
4194         mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
4195 err_nexthop6_group_get:
4196         list_add_tail(&fib6_entry->common.nexthop_group_node,
4197                       &old_nh_grp->fib_list);
4198         fib6_entry->common.nh_group = old_nh_grp;
4199         return err;
4200 }
4201
4202 static int
4203 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
4204                                 struct mlxsw_sp_fib6_entry *fib6_entry,
4205                                 struct rt6_info *rt)
4206 {
4207         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4208         int err;
4209
4210         mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
4211         if (IS_ERR(mlxsw_sp_rt6))
4212                 return PTR_ERR(mlxsw_sp_rt6);
4213
4214         list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
4215         fib6_entry->nrt6++;
4216
4217         err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
4218         if (err)
4219                 goto err_nexthop6_group_update;
4220
4221         return 0;
4222
4223 err_nexthop6_group_update:
4224         fib6_entry->nrt6--;
4225         list_del(&mlxsw_sp_rt6->list);
4226         mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4227         return err;
4228 }
4229
4230 static void
4231 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
4232                                 struct mlxsw_sp_fib6_entry *fib6_entry,
4233                                 struct rt6_info *rt)
4234 {
4235         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4236
4237         mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt);
4238         if (WARN_ON(!mlxsw_sp_rt6))
4239                 return;
4240
4241         fib6_entry->nrt6--;
4242         list_del(&mlxsw_sp_rt6->list);
4243         mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
4244         mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4245 }
4246
4247 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
4248                                          struct mlxsw_sp_fib_entry *fib_entry,
4249                                          const struct rt6_info *rt)
4250 {
4251         /* Packets hitting RTF_REJECT routes need to be discarded by the
4252          * stack. We can rely on their destination device not having a
4253          * RIF (it's the loopback device) and can thus use action type
4254          * local, which will cause them to be trapped with a lower
4255          * priority than packets that need to be locally received.
4256          */
4257         if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
4258                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
4259         else if (rt->rt6i_flags & RTF_REJECT)
4260                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4261         else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
4262                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
4263         else
4264                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4265 }
4266
4267 static void
4268 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
4269 {
4270         struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp;
4271
4272         list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list,
4273                                  list) {
4274                 fib6_entry->nrt6--;
4275                 list_del(&mlxsw_sp_rt6->list);
4276                 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4277         }
4278 }
4279
4280 static struct mlxsw_sp_fib6_entry *
4281 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
4282                            struct mlxsw_sp_fib_node *fib_node,
4283                            struct rt6_info *rt)
4284 {
4285         struct mlxsw_sp_fib6_entry *fib6_entry;
4286         struct mlxsw_sp_fib_entry *fib_entry;
4287         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4288         int err;
4289
4290         fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
4291         if (!fib6_entry)
4292                 return ERR_PTR(-ENOMEM);
4293         fib_entry = &fib6_entry->common;
4294
4295         mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
4296         if (IS_ERR(mlxsw_sp_rt6)) {
4297                 err = PTR_ERR(mlxsw_sp_rt6);
4298                 goto err_rt6_create;
4299         }
4300
4301         mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, mlxsw_sp_rt6->rt);
4302
4303         INIT_LIST_HEAD(&fib6_entry->rt6_list);
4304         list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
4305         fib6_entry->nrt6 = 1;
4306         err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
4307         if (err)
4308                 goto err_nexthop6_group_get;
4309
4310         fib_entry->fib_node = fib_node;
4311
4312         return fib6_entry;
4313
4314 err_nexthop6_group_get:
4315         list_del(&mlxsw_sp_rt6->list);
4316         mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4317 err_rt6_create:
4318         kfree(fib6_entry);
4319         return ERR_PTR(err);
4320 }
4321
4322 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
4323                                         struct mlxsw_sp_fib6_entry *fib6_entry)
4324 {
4325         mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
4326         mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry);
4327         WARN_ON(fib6_entry->nrt6);
4328         kfree(fib6_entry);
4329 }
4330
4331 static struct mlxsw_sp_fib6_entry *
4332 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
4333                               const struct rt6_info *nrt, bool replace)
4334 {
4335         struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
4336
4337         list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
4338                 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
4339
4340                 if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
4341                         continue;
4342                 if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
4343                         break;
4344                 if (replace && rt->rt6i_metric == nrt->rt6i_metric) {
4345                         if (mlxsw_sp_fib6_rt_can_mp(rt) ==
4346                             mlxsw_sp_fib6_rt_can_mp(nrt))
4347                                 return fib6_entry;
4348                         if (mlxsw_sp_fib6_rt_can_mp(nrt))
4349                                 fallback = fallback ?: fib6_entry;
4350                 }
4351                 if (rt->rt6i_metric > nrt->rt6i_metric)
4352                         return fallback ?: fib6_entry;
4353         }
4354
4355         return fallback;
4356 }
4357
4358 static int
4359 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
4360                                bool replace)
4361 {
4362         struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node;
4363         struct rt6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry);
4364         struct mlxsw_sp_fib6_entry *fib6_entry;
4365
4366         fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, replace);
4367
4368         if (replace && WARN_ON(!fib6_entry))
4369                 return -EINVAL;
4370
4371         if (fib6_entry) {
4372                 list_add_tail(&new6_entry->common.list,
4373                               &fib6_entry->common.list);
4374         } else {
4375                 struct mlxsw_sp_fib6_entry *last;
4376
4377                 list_for_each_entry(last, &fib_node->entry_list, common.list) {
4378                         struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(last);
4379
4380                         if (nrt->rt6i_table->tb6_id > rt->rt6i_table->tb6_id)
4381                                 break;
4382                         fib6_entry = last;
4383                 }
4384
4385                 if (fib6_entry)
4386                         list_add(&new6_entry->common.list,
4387                                  &fib6_entry->common.list);
4388                 else
4389                         list_add(&new6_entry->common.list,
4390                                  &fib_node->entry_list);
4391         }
4392
4393         return 0;
4394 }
4395
4396 static void
4397 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry)
4398 {
4399         list_del(&fib6_entry->common.list);
4400 }
4401
4402 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
4403                                          struct mlxsw_sp_fib6_entry *fib6_entry,
4404                                          bool replace)
4405 {
4406         int err;
4407
4408         err = mlxsw_sp_fib6_node_list_insert(fib6_entry, replace);
4409         if (err)
4410                 return err;
4411
4412         err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
4413         if (err)
4414                 goto err_fib_node_entry_add;
4415
4416         return 0;
4417
4418 err_fib_node_entry_add:
4419         mlxsw_sp_fib6_node_list_remove(fib6_entry);
4420         return err;
4421 }
4422
4423 static void
4424 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
4425                                 struct mlxsw_sp_fib6_entry *fib6_entry)
4426 {
4427         mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common);
4428         mlxsw_sp_fib6_node_list_remove(fib6_entry);
4429 }
4430
4431 static struct mlxsw_sp_fib6_entry *
4432 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
4433                            const struct rt6_info *rt)
4434 {
4435         struct mlxsw_sp_fib6_entry *fib6_entry;
4436         struct mlxsw_sp_fib_node *fib_node;
4437         struct mlxsw_sp_fib *fib;
4438         struct mlxsw_sp_vr *vr;
4439
4440         vr = mlxsw_sp_vr_find(mlxsw_sp, rt->rt6i_table->tb6_id);
4441         if (!vr)
4442                 return NULL;
4443         fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
4444
4445         fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->rt6i_dst.addr,
4446                                             sizeof(rt->rt6i_dst.addr),
4447                                             rt->rt6i_dst.plen);
4448         if (!fib_node)
4449                 return NULL;
4450
4451         list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
4452                 struct rt6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
4453
4454                 if (rt->rt6i_table->tb6_id == iter_rt->rt6i_table->tb6_id &&
4455                     rt->rt6i_metric == iter_rt->rt6i_metric &&
4456                     mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
4457                         return fib6_entry;
4458         }
4459
4460         return NULL;
4461 }
4462
4463 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
4464                                         struct mlxsw_sp_fib6_entry *fib6_entry,
4465                                         bool replace)
4466 {
4467         struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
4468         struct mlxsw_sp_fib6_entry *replaced;
4469
4470         if (!replace)
4471                 return;
4472
4473         replaced = list_next_entry(fib6_entry, common.list);
4474
4475         mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, replaced);
4476         mlxsw_sp_fib6_entry_destroy(mlxsw_sp, replaced);
4477         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4478 }
4479
4480 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
4481                                     struct rt6_info *rt, bool replace)
4482 {
4483         struct mlxsw_sp_fib6_entry *fib6_entry;
4484         struct mlxsw_sp_fib_node *fib_node;
4485         int err;
4486
4487         if (mlxsw_sp->router->aborted)
4488                 return 0;
4489
4490         if (rt->rt6i_src.plen)
4491                 return -EINVAL;
4492
4493         if (mlxsw_sp_fib6_rt_should_ignore(rt))
4494                 return 0;
4495
4496         fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->rt6i_table->tb6_id,
4497                                          &rt->rt6i_dst.addr,
4498                                          sizeof(rt->rt6i_dst.addr),
4499                                          rt->rt6i_dst.plen,
4500                                          MLXSW_SP_L3_PROTO_IPV6);
4501         if (IS_ERR(fib_node))
4502                 return PTR_ERR(fib_node);
4503
4504         /* Before creating a new entry, try to append route to an existing
4505          * multipath entry.
4506          */
4507         fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
4508         if (fib6_entry) {
4509                 err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
4510                 if (err)
4511                         goto err_fib6_entry_nexthop_add;
4512                 return 0;
4513         }
4514
4515         fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
4516         if (IS_ERR(fib6_entry)) {
4517                 err = PTR_ERR(fib6_entry);
4518                 goto err_fib6_entry_create;
4519         }
4520
4521         err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, replace);
4522         if (err)
4523                 goto err_fib6_node_entry_link;
4524
4525         mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry, replace);
4526
4527         return 0;
4528
4529 err_fib6_node_entry_link:
4530         mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4531 err_fib6_entry_create:
4532 err_fib6_entry_nexthop_add:
4533         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4534         return err;
4535 }
4536
4537 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
4538                                      struct rt6_info *rt)
4539 {
4540         struct mlxsw_sp_fib6_entry *fib6_entry;
4541         struct mlxsw_sp_fib_node *fib_node;
4542
4543         if (mlxsw_sp->router->aborted)
4544                 return;
4545
4546         if (mlxsw_sp_fib6_rt_should_ignore(rt))
4547                 return;
4548
4549         fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
4550         if (WARN_ON(!fib6_entry))
4551                 return;
4552
4553         /* If route is part of a multipath entry, but not the last one
4554          * removed, then only reduce its nexthop group.
4555          */
4556         if (!list_is_singular(&fib6_entry->rt6_list)) {
4557                 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt);
4558                 return;
4559         }
4560
4561         fib_node = fib6_entry->common.fib_node;
4562
4563         mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
4564         mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4565         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4566 }
4567
4568 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp,
4569                                             enum mlxsw_reg_ralxx_protocol proto,
4570                                             u8 tree_id)
4571 {
4572         char ralta_pl[MLXSW_REG_RALTA_LEN];
4573         char ralst_pl[MLXSW_REG_RALST_LEN];
4574         int i, err;
4575
4576         mlxsw_reg_ralta_pack(ralta_pl, true, proto, tree_id);
4577         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
4578         if (err)
4579                 return err;
4580
4581         mlxsw_reg_ralst_pack(ralst_pl, 0xff, tree_id);
4582         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
4583         if (err)
4584                 return err;
4585
4586         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
4587                 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
4588                 char raltb_pl[MLXSW_REG_RALTB_LEN];
4589                 char ralue_pl[MLXSW_REG_RALUE_LEN];
4590
4591                 mlxsw_reg_raltb_pack(raltb_pl, vr->id, proto, tree_id);
4592                 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb),
4593                                       raltb_pl);
4594                 if (err)
4595                         return err;
4596
4597                 mlxsw_reg_ralue_pack(ralue_pl, proto,
4598                                      MLXSW_REG_RALUE_OP_WRITE_WRITE, vr->id, 0);
4599                 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
4600                 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue),
4601                                       ralue_pl);
4602                 if (err)
4603                         return err;
4604         }
4605
4606         return 0;
4607 }
4608
4609 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
4610 {
4611         enum mlxsw_reg_ralxx_protocol proto = MLXSW_REG_RALXX_PROTOCOL_IPV4;
4612         int err;
4613
4614         err = __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
4615                                                MLXSW_SP_LPM_TREE_MIN);
4616         if (err)
4617                 return err;
4618
4619         proto = MLXSW_REG_RALXX_PROTOCOL_IPV6;
4620         return __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
4621                                                 MLXSW_SP_LPM_TREE_MIN + 1);
4622 }
4623
4624 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
4625                                      struct mlxsw_sp_fib_node *fib_node)
4626 {
4627         struct mlxsw_sp_fib4_entry *fib4_entry, *tmp;
4628
4629         list_for_each_entry_safe(fib4_entry, tmp, &fib_node->entry_list,
4630                                  common.list) {
4631                 bool do_break = &tmp->common.list == &fib_node->entry_list;
4632
4633                 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
4634                 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4635                 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4636                 /* Break when entry list is empty and node was freed.
4637                  * Otherwise, we'll access freed memory in the next
4638                  * iteration.
4639                  */
4640                 if (do_break)
4641                         break;
4642         }
4643 }
4644
4645 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
4646                                      struct mlxsw_sp_fib_node *fib_node)
4647 {
4648         struct mlxsw_sp_fib6_entry *fib6_entry, *tmp;
4649
4650         list_for_each_entry_safe(fib6_entry, tmp, &fib_node->entry_list,
4651                                  common.list) {
4652                 bool do_break = &tmp->common.list == &fib_node->entry_list;
4653
4654                 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
4655                 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4656                 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4657                 if (do_break)
4658                         break;
4659         }
4660 }
4661
4662 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
4663                                     struct mlxsw_sp_fib_node *fib_node)
4664 {
4665         switch (fib_node->fib->proto) {
4666         case MLXSW_SP_L3_PROTO_IPV4:
4667                 mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
4668                 break;
4669         case MLXSW_SP_L3_PROTO_IPV6:
4670                 mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node);
4671                 break;
4672         }
4673 }
4674
4675 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
4676                                   struct mlxsw_sp_vr *vr,
4677                                   enum mlxsw_sp_l3proto proto)
4678 {
4679         struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
4680         struct mlxsw_sp_fib_node *fib_node, *tmp;
4681
4682         list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
4683                 bool do_break = &tmp->list == &fib->node_list;
4684
4685                 mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
4686                 if (do_break)
4687                         break;
4688         }
4689 }
4690
4691 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
4692 {
4693         int i;
4694
4695         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
4696                 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
4697
4698                 if (!mlxsw_sp_vr_is_used(vr))
4699                         continue;
4700                 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
4701
4702                 /* If virtual router was only used for IPv4, then it's no
4703                  * longer used.
4704                  */
4705                 if (!mlxsw_sp_vr_is_used(vr))
4706                         continue;
4707                 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
4708         }
4709 }
4710
4711 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp)
4712 {
4713         int err;
4714
4715         if (mlxsw_sp->router->aborted)
4716                 return;
4717         dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
4718         mlxsw_sp_router_fib_flush(mlxsw_sp);
4719         mlxsw_sp->router->aborted = true;
4720         err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
4721         if (err)
4722                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
4723 }
4724
4725 struct mlxsw_sp_fib_event_work {
4726         struct work_struct work;
4727         union {
4728                 struct fib6_entry_notifier_info fen6_info;
4729                 struct fib_entry_notifier_info fen_info;
4730                 struct fib_rule_notifier_info fr_info;
4731                 struct fib_nh_notifier_info fnh_info;
4732         };
4733         struct mlxsw_sp *mlxsw_sp;
4734         unsigned long event;
4735 };
4736
4737 static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
4738 {
4739         struct mlxsw_sp_fib_event_work *fib_work =
4740                 container_of(work, struct mlxsw_sp_fib_event_work, work);
4741         struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
4742         struct fib_rule *rule;
4743         bool replace, append;
4744         int err;
4745
4746         /* Protect internal structures from changes */
4747         rtnl_lock();
4748         switch (fib_work->event) {
4749         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4750         case FIB_EVENT_ENTRY_APPEND: /* fall through */
4751         case FIB_EVENT_ENTRY_ADD:
4752                 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
4753                 append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
4754                 err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info,
4755                                                replace, append);
4756                 if (err)
4757                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4758                 fib_info_put(fib_work->fen_info.fi);
4759                 break;
4760         case FIB_EVENT_ENTRY_DEL:
4761                 mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
4762                 fib_info_put(fib_work->fen_info.fi);
4763                 break;
4764         case FIB_EVENT_RULE_ADD: /* fall through */
4765         case FIB_EVENT_RULE_DEL:
4766                 rule = fib_work->fr_info.rule;
4767                 if (!fib4_rule_default(rule) && !rule->l3mdev)
4768                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4769                 fib_rule_put(rule);
4770                 break;
4771         case FIB_EVENT_NH_ADD: /* fall through */
4772         case FIB_EVENT_NH_DEL:
4773                 mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event,
4774                                         fib_work->fnh_info.fib_nh);
4775                 fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
4776                 break;
4777         }
4778         rtnl_unlock();
4779         kfree(fib_work);
4780 }
4781
4782 static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
4783 {
4784         struct mlxsw_sp_fib_event_work *fib_work =
4785                 container_of(work, struct mlxsw_sp_fib_event_work, work);
4786         struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
4787         struct fib_rule *rule;
4788         bool replace;
4789         int err;
4790
4791         rtnl_lock();
4792         switch (fib_work->event) {
4793         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4794         case FIB_EVENT_ENTRY_ADD:
4795                 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
4796                 err = mlxsw_sp_router_fib6_add(mlxsw_sp,
4797                                                fib_work->fen6_info.rt, replace);
4798                 if (err)
4799                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4800                 mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
4801                 break;
4802         case FIB_EVENT_ENTRY_DEL:
4803                 mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt);
4804                 mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
4805                 break;
4806         case FIB_EVENT_RULE_ADD: /* fall through */
4807         case FIB_EVENT_RULE_DEL:
4808                 rule = fib_work->fr_info.rule;
4809                 if (!fib6_rule_default(rule) && !rule->l3mdev)
4810                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4811                 fib_rule_put(rule);
4812                 break;
4813         }
4814         rtnl_unlock();
4815         kfree(fib_work);
4816 }
4817
4818 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
4819                                        struct fib_notifier_info *info)
4820 {
4821         switch (fib_work->event) {
4822         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4823         case FIB_EVENT_ENTRY_APPEND: /* fall through */
4824         case FIB_EVENT_ENTRY_ADD: /* fall through */
4825         case FIB_EVENT_ENTRY_DEL:
4826                 memcpy(&fib_work->fen_info, info, sizeof(fib_work->fen_info));
4827                 /* Take referece on fib_info to prevent it from being
4828                  * freed while work is queued. Release it afterwards.
4829                  */
4830                 fib_info_hold(fib_work->fen_info.fi);
4831                 break;
4832         case FIB_EVENT_RULE_ADD: /* fall through */
4833         case FIB_EVENT_RULE_DEL:
4834                 memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
4835                 fib_rule_get(fib_work->fr_info.rule);
4836                 break;
4837         case FIB_EVENT_NH_ADD: /* fall through */
4838         case FIB_EVENT_NH_DEL:
4839                 memcpy(&fib_work->fnh_info, info, sizeof(fib_work->fnh_info));
4840                 fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
4841                 break;
4842         }
4843 }
4844
4845 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
4846                                        struct fib_notifier_info *info)
4847 {
4848         switch (fib_work->event) {
4849         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4850         case FIB_EVENT_ENTRY_ADD: /* fall through */
4851         case FIB_EVENT_ENTRY_DEL:
4852                 memcpy(&fib_work->fen6_info, info, sizeof(fib_work->fen6_info));
4853                 rt6_hold(fib_work->fen6_info.rt);
4854                 break;
4855         case FIB_EVENT_RULE_ADD: /* fall through */
4856         case FIB_EVENT_RULE_DEL:
4857                 memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
4858                 fib_rule_get(fib_work->fr_info.rule);
4859                 break;
4860         }
4861 }
4862
4863 /* Called with rcu_read_lock() */
4864 static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
4865                                      unsigned long event, void *ptr)
4866 {
4867         struct mlxsw_sp_fib_event_work *fib_work;
4868         struct fib_notifier_info *info = ptr;
4869         struct mlxsw_sp_router *router;
4870
4871         if (!net_eq(info->net, &init_net) ||
4872             (info->family != AF_INET && info->family != AF_INET6))
4873                 return NOTIFY_DONE;
4874
4875         fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
4876         if (WARN_ON(!fib_work))
4877                 return NOTIFY_BAD;
4878
4879         router = container_of(nb, struct mlxsw_sp_router, fib_nb);
4880         fib_work->mlxsw_sp = router->mlxsw_sp;
4881         fib_work->event = event;
4882
4883         switch (info->family) {
4884         case AF_INET:
4885                 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work);
4886                 mlxsw_sp_router_fib4_event(fib_work, info);
4887                 break;
4888         case AF_INET6:
4889                 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
4890                 mlxsw_sp_router_fib6_event(fib_work, info);
4891                 break;
4892         }
4893
4894         mlxsw_core_schedule_work(&fib_work->work);
4895
4896         return NOTIFY_DONE;
4897 }
4898
4899 static struct mlxsw_sp_rif *
4900 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
4901                          const struct net_device *dev)
4902 {
4903         int i;
4904
4905         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
4906                 if (mlxsw_sp->router->rifs[i] &&
4907                     mlxsw_sp->router->rifs[i]->dev == dev)
4908                         return mlxsw_sp->router->rifs[i];
4909
4910         return NULL;
4911 }
4912
4913 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
4914 {
4915         char ritr_pl[MLXSW_REG_RITR_LEN];
4916         int err;
4917
4918         mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
4919         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
4920         if (WARN_ON_ONCE(err))
4921                 return err;
4922
4923         mlxsw_reg_ritr_enable_set(ritr_pl, false);
4924         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
4925 }
4926
4927 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
4928                                           struct mlxsw_sp_rif *rif)
4929 {
4930         mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
4931         mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
4932         mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
4933 }
4934
4935 static bool
4936 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
4937                            unsigned long event)
4938 {
4939         struct inet6_dev *inet6_dev;
4940         bool addr_list_empty = true;
4941         struct in_device *idev;
4942
4943         switch (event) {
4944         case NETDEV_UP:
4945                 return rif == NULL;
4946         case NETDEV_DOWN:
4947                 idev = __in_dev_get_rtnl(dev);
4948                 if (idev && idev->ifa_list)
4949                         addr_list_empty = false;
4950
4951                 inet6_dev = __in6_dev_get(dev);
4952                 if (addr_list_empty && inet6_dev &&
4953                     !list_empty(&inet6_dev->addr_list))
4954                         addr_list_empty = false;
4955
4956                 if (rif && addr_list_empty &&
4957                     !netif_is_l3_slave(rif->dev))
4958                         return true;
4959                 /* It is possible we already removed the RIF ourselves
4960                  * if it was assigned to a netdev that is now a bridge
4961                  * or LAG slave.
4962                  */
4963                 return false;
4964         }
4965
4966         return false;
4967 }
4968
4969 static enum mlxsw_sp_rif_type
4970 mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
4971                       const struct net_device *dev)
4972 {
4973         enum mlxsw_sp_fid_type type;
4974
4975         if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
4976                 return MLXSW_SP_RIF_TYPE_IPIP_LB;
4977
4978         /* Otherwise RIF type is derived from the type of the underlying FID. */
4979         if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
4980                 type = MLXSW_SP_FID_TYPE_8021Q;
4981         else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
4982                 type = MLXSW_SP_FID_TYPE_8021Q;
4983         else if (netif_is_bridge_master(dev))
4984                 type = MLXSW_SP_FID_TYPE_8021D;
4985         else
4986                 type = MLXSW_SP_FID_TYPE_RFID;
4987
4988         return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
4989 }
4990
4991 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index)
4992 {
4993         int i;
4994
4995         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
4996                 if (!mlxsw_sp->router->rifs[i]) {
4997                         *p_rif_index = i;
4998                         return 0;
4999                 }
5000         }
5001
5002         return -ENOBUFS;
5003 }
5004
5005 static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
5006                                                u16 vr_id,
5007                                                struct net_device *l3_dev)
5008 {
5009         struct mlxsw_sp_rif *rif;
5010
5011         rif = kzalloc(rif_size, GFP_KERNEL);
5012         if (!rif)
5013                 return NULL;
5014
5015         INIT_LIST_HEAD(&rif->nexthop_list);
5016         INIT_LIST_HEAD(&rif->neigh_list);
5017         ether_addr_copy(rif->addr, l3_dev->dev_addr);
5018         rif->mtu = l3_dev->mtu;
5019         rif->vr_id = vr_id;
5020         rif->dev = l3_dev;
5021         rif->rif_index = rif_index;
5022
5023         return rif;
5024 }
5025
5026 struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
5027                                            u16 rif_index)
5028 {
5029         return mlxsw_sp->router->rifs[rif_index];
5030 }
5031
5032 u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
5033 {
5034         return rif->rif_index;
5035 }
5036
5037 u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
5038 {
5039         return lb_rif->common.rif_index;
5040 }
5041
5042 u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
5043 {
5044         return lb_rif->ul_vr_id;
5045 }
5046
5047 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
5048 {
5049         return rif->dev->ifindex;
5050 }
5051
5052 static struct mlxsw_sp_rif *
5053 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
5054                     const struct mlxsw_sp_rif_params *params)
5055 {
5056         u32 tb_id = l3mdev_fib_table(params->dev);
5057         const struct mlxsw_sp_rif_ops *ops;
5058         struct mlxsw_sp_fid *fid = NULL;
5059         enum mlxsw_sp_rif_type type;
5060         struct mlxsw_sp_rif *rif;
5061         struct mlxsw_sp_vr *vr;
5062         u16 rif_index;
5063         int err;
5064
5065         type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
5066         ops = mlxsw_sp->router->rif_ops_arr[type];
5067
5068         vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
5069         if (IS_ERR(vr))
5070                 return ERR_CAST(vr);
5071
5072         err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
5073         if (err)
5074                 goto err_rif_index_alloc;
5075
5076         rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
5077         if (!rif) {
5078                 err = -ENOMEM;
5079                 goto err_rif_alloc;
5080         }
5081         rif->mlxsw_sp = mlxsw_sp;
5082         rif->ops = ops;
5083
5084         if (ops->fid_get) {
5085                 fid = ops->fid_get(rif);
5086                 if (IS_ERR(fid)) {
5087                         err = PTR_ERR(fid);
5088                         goto err_fid_get;
5089                 }
5090                 rif->fid = fid;
5091         }
5092
5093         if (ops->setup)
5094                 ops->setup(rif, params);
5095
5096         err = ops->configure(rif);
5097         if (err)
5098                 goto err_configure;
5099
5100         mlxsw_sp_rif_counters_alloc(rif);
5101         mlxsw_sp->router->rifs[rif_index] = rif;
5102         vr->rif_count++;
5103
5104         return rif;
5105
5106 err_configure:
5107         if (fid)
5108                 mlxsw_sp_fid_put(fid);
5109 err_fid_get:
5110         kfree(rif);
5111 err_rif_alloc:
5112 err_rif_index_alloc:
5113         mlxsw_sp_vr_put(vr);
5114         return ERR_PTR(err);
5115 }
5116
5117 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
5118 {
5119         const struct mlxsw_sp_rif_ops *ops = rif->ops;
5120         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5121         struct mlxsw_sp_fid *fid = rif->fid;
5122         struct mlxsw_sp_vr *vr;
5123
5124         mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
5125         vr = &mlxsw_sp->router->vrs[rif->vr_id];
5126
5127         vr->rif_count--;
5128         mlxsw_sp->router->rifs[rif->rif_index] = NULL;
5129         mlxsw_sp_rif_counters_free(rif);
5130         ops->deconfigure(rif);
5131         if (fid)
5132                 /* Loopback RIFs are not associated with a FID. */
5133                 mlxsw_sp_fid_put(fid);
5134         kfree(rif);
5135         mlxsw_sp_vr_put(vr);
5136 }
5137
5138 static void
5139 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
5140                                  struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
5141 {
5142         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5143
5144         params->vid = mlxsw_sp_port_vlan->vid;
5145         params->lag = mlxsw_sp_port->lagged;
5146         if (params->lag)
5147                 params->lag_id = mlxsw_sp_port->lag_id;
5148         else
5149                 params->system_port = mlxsw_sp_port->local_port;
5150 }
5151
5152 static int
5153 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
5154                                struct net_device *l3_dev)
5155 {
5156         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5157         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5158         u16 vid = mlxsw_sp_port_vlan->vid;
5159         struct mlxsw_sp_rif *rif;
5160         struct mlxsw_sp_fid *fid;
5161         int err;
5162
5163         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5164         if (!rif) {
5165                 struct mlxsw_sp_rif_params params = {
5166                         .dev = l3_dev,
5167                 };
5168
5169                 mlxsw_sp_rif_subport_params_init(&params, mlxsw_sp_port_vlan);
5170                 rif = mlxsw_sp_rif_create(mlxsw_sp, &params);
5171                 if (IS_ERR(rif))
5172                         return PTR_ERR(rif);
5173         }
5174
5175         /* FID was already created, just take a reference */
5176         fid = rif->ops->fid_get(rif);
5177         err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid);
5178         if (err)
5179                 goto err_fid_port_vid_map;
5180
5181         err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
5182         if (err)
5183                 goto err_port_vid_learning_set;
5184
5185         err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid,
5186                                         BR_STATE_FORWARDING);
5187         if (err)
5188                 goto err_port_vid_stp_set;
5189
5190         mlxsw_sp_port_vlan->fid = fid;
5191
5192         return 0;
5193
5194 err_port_vid_stp_set:
5195         mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
5196 err_port_vid_learning_set:
5197         mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
5198 err_fid_port_vid_map:
5199         mlxsw_sp_fid_put(fid);
5200         return err;
5201 }
5202
5203 void
5204 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
5205 {
5206         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5207         struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
5208         u16 vid = mlxsw_sp_port_vlan->vid;
5209
5210         if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID))
5211                 return;
5212
5213         mlxsw_sp_port_vlan->fid = NULL;
5214         mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING);
5215         mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
5216         mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
5217         /* If router port holds the last reference on the rFID, then the
5218          * associated Sub-port RIF will be destroyed.
5219          */
5220         mlxsw_sp_fid_put(fid);
5221 }
5222
5223 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
5224                                              struct net_device *port_dev,
5225                                              unsigned long event, u16 vid)
5226 {
5227         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
5228         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
5229
5230         mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
5231         if (WARN_ON(!mlxsw_sp_port_vlan))
5232                 return -EINVAL;
5233
5234         switch (event) {
5235         case NETDEV_UP:
5236                 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
5237                                                       l3_dev);
5238         case NETDEV_DOWN:
5239                 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
5240                 break;
5241         }
5242
5243         return 0;
5244 }
5245
5246 static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
5247                                         unsigned long event)
5248 {
5249         if (netif_is_bridge_port(port_dev) ||
5250             netif_is_lag_port(port_dev) ||
5251             netif_is_ovs_port(port_dev))
5252                 return 0;
5253
5254         return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1);
5255 }
5256
5257 static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
5258                                          struct net_device *lag_dev,
5259                                          unsigned long event, u16 vid)
5260 {
5261         struct net_device *port_dev;
5262         struct list_head *iter;
5263         int err;
5264
5265         netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
5266                 if (mlxsw_sp_port_dev_check(port_dev)) {
5267                         err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
5268                                                                 port_dev,
5269                                                                 event, vid);
5270                         if (err)
5271                                 return err;
5272                 }
5273         }
5274
5275         return 0;
5276 }
5277
5278 static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
5279                                        unsigned long event)
5280 {
5281         if (netif_is_bridge_port(lag_dev))
5282                 return 0;
5283
5284         return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1);
5285 }
5286
5287 static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
5288                                           unsigned long event)
5289 {
5290         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
5291         struct mlxsw_sp_rif_params params = {
5292                 .dev = l3_dev,
5293         };
5294         struct mlxsw_sp_rif *rif;
5295
5296         switch (event) {
5297         case NETDEV_UP:
5298                 rif = mlxsw_sp_rif_create(mlxsw_sp, &params);
5299                 if (IS_ERR(rif))
5300                         return PTR_ERR(rif);
5301                 break;
5302         case NETDEV_DOWN:
5303                 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5304                 mlxsw_sp_rif_destroy(rif);
5305                 break;
5306         }
5307
5308         return 0;
5309 }
5310
5311 static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
5312                                         unsigned long event)
5313 {
5314         struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
5315         u16 vid = vlan_dev_vlan_id(vlan_dev);
5316
5317         if (netif_is_bridge_port(vlan_dev))
5318                 return 0;
5319
5320         if (mlxsw_sp_port_dev_check(real_dev))
5321                 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
5322                                                          event, vid);
5323         else if (netif_is_lag_master(real_dev))
5324                 return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
5325                                                      vid);
5326         else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev))
5327                 return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event);
5328
5329         return 0;
5330 }
5331
5332 static int __mlxsw_sp_inetaddr_event(struct net_device *dev,
5333                                      unsigned long event)
5334 {
5335         if (mlxsw_sp_port_dev_check(dev))
5336                 return mlxsw_sp_inetaddr_port_event(dev, event);
5337         else if (netif_is_lag_master(dev))
5338                 return mlxsw_sp_inetaddr_lag_event(dev, event);
5339         else if (netif_is_bridge_master(dev))
5340                 return mlxsw_sp_inetaddr_bridge_event(dev, event);
5341         else if (is_vlan_dev(dev))
5342                 return mlxsw_sp_inetaddr_vlan_event(dev, event);
5343         else
5344                 return 0;
5345 }
5346
5347 int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
5348                             unsigned long event, void *ptr)
5349 {
5350         struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
5351         struct net_device *dev = ifa->ifa_dev->dev;
5352         struct mlxsw_sp *mlxsw_sp;
5353         struct mlxsw_sp_rif *rif;
5354         int err = 0;
5355
5356         mlxsw_sp = mlxsw_sp_lower_get(dev);
5357         if (!mlxsw_sp)
5358                 goto out;
5359
5360         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5361         if (!mlxsw_sp_rif_should_config(rif, dev, event))
5362                 goto out;
5363
5364         err = __mlxsw_sp_inetaddr_event(dev, event);
5365 out:
5366         return notifier_from_errno(err);
5367 }
5368
5369 struct mlxsw_sp_inet6addr_event_work {
5370         struct work_struct work;
5371         struct net_device *dev;
5372         unsigned long event;
5373 };
5374
5375 static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
5376 {
5377         struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
5378                 container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
5379         struct net_device *dev = inet6addr_work->dev;
5380         unsigned long event = inet6addr_work->event;
5381         struct mlxsw_sp *mlxsw_sp;
5382         struct mlxsw_sp_rif *rif;
5383
5384         rtnl_lock();
5385         mlxsw_sp = mlxsw_sp_lower_get(dev);
5386         if (!mlxsw_sp)
5387                 goto out;
5388
5389         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5390         if (!mlxsw_sp_rif_should_config(rif, dev, event))
5391                 goto out;
5392
5393         __mlxsw_sp_inetaddr_event(dev, event);
5394 out:
5395         rtnl_unlock();
5396         dev_put(dev);
5397         kfree(inet6addr_work);
5398 }
5399
5400 /* Called with rcu_read_lock() */
5401 int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
5402                              unsigned long event, void *ptr)
5403 {
5404         struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
5405         struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
5406         struct net_device *dev = if6->idev->dev;
5407
5408         if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
5409                 return NOTIFY_DONE;
5410
5411         inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
5412         if (!inet6addr_work)
5413                 return NOTIFY_BAD;
5414
5415         INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
5416         inet6addr_work->dev = dev;
5417         inet6addr_work->event = event;
5418         dev_hold(dev);
5419         mlxsw_core_schedule_work(&inet6addr_work->work);
5420
5421         return NOTIFY_DONE;
5422 }
5423
5424 static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
5425                              const char *mac, int mtu)
5426 {
5427         char ritr_pl[MLXSW_REG_RITR_LEN];
5428         int err;
5429
5430         mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
5431         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5432         if (err)
5433                 return err;
5434
5435         mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
5436         mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
5437         mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
5438         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5439 }
5440
5441 int mlxsw_sp_netdevice_router_port_event(struct net_device *dev)
5442 {
5443         struct mlxsw_sp *mlxsw_sp;
5444         struct mlxsw_sp_rif *rif;
5445         u16 fid_index;
5446         int err;
5447
5448         mlxsw_sp = mlxsw_sp_lower_get(dev);
5449         if (!mlxsw_sp)
5450                 return 0;
5451
5452         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5453         if (!rif)
5454                 return 0;
5455         fid_index = mlxsw_sp_fid_index(rif->fid);
5456
5457         err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false);
5458         if (err)
5459                 return err;
5460
5461         err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
5462                                 dev->mtu);
5463         if (err)
5464                 goto err_rif_edit;
5465
5466         err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true);
5467         if (err)
5468                 goto err_rif_fdb_op;
5469
5470         ether_addr_copy(rif->addr, dev->dev_addr);
5471         rif->mtu = dev->mtu;
5472
5473         netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
5474
5475         return 0;
5476
5477 err_rif_fdb_op:
5478         mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu);
5479 err_rif_edit:
5480         mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true);
5481         return err;
5482 }
5483
5484 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
5485                                   struct net_device *l3_dev)
5486 {
5487         struct mlxsw_sp_rif *rif;
5488
5489         /* If netdev is already associated with a RIF, then we need to
5490          * destroy it and create a new one with the new virtual router ID.
5491          */
5492         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5493         if (rif)
5494                 __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
5495
5496         return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP);
5497 }
5498
5499 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
5500                                     struct net_device *l3_dev)
5501 {
5502         struct mlxsw_sp_rif *rif;
5503
5504         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5505         if (!rif)
5506                 return;
5507         __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
5508 }
5509
5510 int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
5511                                  struct netdev_notifier_changeupper_info *info)
5512 {
5513         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
5514         int err = 0;
5515
5516         if (!mlxsw_sp)
5517                 return 0;
5518
5519         switch (event) {
5520         case NETDEV_PRECHANGEUPPER:
5521                 return 0;
5522         case NETDEV_CHANGEUPPER:
5523                 if (info->linking)
5524                         err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev);
5525                 else
5526                         mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
5527                 break;
5528         }
5529
5530         return err;
5531 }
5532
5533 static struct mlxsw_sp_rif_subport *
5534 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
5535 {
5536         return container_of(rif, struct mlxsw_sp_rif_subport, common);
5537 }
5538
5539 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
5540                                        const struct mlxsw_sp_rif_params *params)
5541 {
5542         struct mlxsw_sp_rif_subport *rif_subport;
5543
5544         rif_subport = mlxsw_sp_rif_subport_rif(rif);
5545         rif_subport->vid = params->vid;
5546         rif_subport->lag = params->lag;
5547         if (params->lag)
5548                 rif_subport->lag_id = params->lag_id;
5549         else
5550                 rif_subport->system_port = params->system_port;
5551 }
5552
5553 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
5554 {
5555         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5556         struct mlxsw_sp_rif_subport *rif_subport;
5557         char ritr_pl[MLXSW_REG_RITR_LEN];
5558
5559         rif_subport = mlxsw_sp_rif_subport_rif(rif);
5560         mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
5561                             rif->rif_index, rif->vr_id, rif->dev->mtu);
5562         mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
5563         mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
5564                                   rif_subport->lag ? rif_subport->lag_id :
5565                                                      rif_subport->system_port,
5566                                   rif_subport->vid);
5567
5568         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5569 }
5570
5571 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif)
5572 {
5573         int err;
5574
5575         err = mlxsw_sp_rif_subport_op(rif, true);
5576         if (err)
5577                 return err;
5578
5579         err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5580                                   mlxsw_sp_fid_index(rif->fid), true);
5581         if (err)
5582                 goto err_rif_fdb_op;
5583
5584         mlxsw_sp_fid_rif_set(rif->fid, rif);
5585         return 0;
5586
5587 err_rif_fdb_op:
5588         mlxsw_sp_rif_subport_op(rif, false);
5589         return err;
5590 }
5591
5592 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
5593 {
5594         struct mlxsw_sp_fid *fid = rif->fid;
5595
5596         mlxsw_sp_fid_rif_set(fid, NULL);
5597         mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5598                             mlxsw_sp_fid_index(fid), false);
5599         mlxsw_sp_rif_subport_op(rif, false);
5600 }
5601
5602 static struct mlxsw_sp_fid *
5603 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif)
5604 {
5605         return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index);
5606 }
5607
5608 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
5609         .type                   = MLXSW_SP_RIF_TYPE_SUBPORT,
5610         .rif_size               = sizeof(struct mlxsw_sp_rif_subport),
5611         .setup                  = mlxsw_sp_rif_subport_setup,
5612         .configure              = mlxsw_sp_rif_subport_configure,
5613         .deconfigure            = mlxsw_sp_rif_subport_deconfigure,
5614         .fid_get                = mlxsw_sp_rif_subport_fid_get,
5615 };
5616
5617 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif,
5618                                     enum mlxsw_reg_ritr_if_type type,
5619                                     u16 vid_fid, bool enable)
5620 {
5621         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5622         char ritr_pl[MLXSW_REG_RITR_LEN];
5623
5624         mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
5625                             rif->dev->mtu);
5626         mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
5627         mlxsw_reg_ritr_fid_set(ritr_pl, type, vid_fid);
5628
5629         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5630 }
5631
5632 static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
5633 {
5634         return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
5635 }
5636
5637 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif)
5638 {
5639         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5640         u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
5641         int err;
5642
5643         err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, true);
5644         if (err)
5645                 return err;
5646
5647         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5648                                      mlxsw_sp_router_port(mlxsw_sp), true);
5649         if (err)
5650                 goto err_fid_mc_flood_set;
5651
5652         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5653                                      mlxsw_sp_router_port(mlxsw_sp), true);
5654         if (err)
5655                 goto err_fid_bc_flood_set;
5656
5657         err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5658                                   mlxsw_sp_fid_index(rif->fid), true);
5659         if (err)
5660                 goto err_rif_fdb_op;
5661
5662         mlxsw_sp_fid_rif_set(rif->fid, rif);
5663         return 0;
5664
5665 err_rif_fdb_op:
5666         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5667                                mlxsw_sp_router_port(mlxsw_sp), false);
5668 err_fid_bc_flood_set:
5669         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5670                                mlxsw_sp_router_port(mlxsw_sp), false);
5671 err_fid_mc_flood_set:
5672         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false);
5673         return err;
5674 }
5675
5676 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
5677 {
5678         u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
5679         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5680         struct mlxsw_sp_fid *fid = rif->fid;
5681
5682         mlxsw_sp_fid_rif_set(fid, NULL);
5683         mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5684                             mlxsw_sp_fid_index(fid), false);
5685         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5686                                mlxsw_sp_router_port(mlxsw_sp), false);
5687         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5688                                mlxsw_sp_router_port(mlxsw_sp), false);
5689         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false);
5690 }
5691
5692 static struct mlxsw_sp_fid *
5693 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif)
5694 {
5695         u16 vid = is_vlan_dev(rif->dev) ? vlan_dev_vlan_id(rif->dev) : 1;
5696
5697         return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid);
5698 }
5699
5700 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = {
5701         .type                   = MLXSW_SP_RIF_TYPE_VLAN,
5702         .rif_size               = sizeof(struct mlxsw_sp_rif),
5703         .configure              = mlxsw_sp_rif_vlan_configure,
5704         .deconfigure            = mlxsw_sp_rif_vlan_deconfigure,
5705         .fid_get                = mlxsw_sp_rif_vlan_fid_get,
5706 };
5707
5708 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif)
5709 {
5710         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5711         u16 fid_index = mlxsw_sp_fid_index(rif->fid);
5712         int err;
5713
5714         err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index,
5715                                        true);
5716         if (err)
5717                 return err;
5718
5719         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5720                                      mlxsw_sp_router_port(mlxsw_sp), true);
5721         if (err)
5722                 goto err_fid_mc_flood_set;
5723
5724         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5725                                      mlxsw_sp_router_port(mlxsw_sp), true);
5726         if (err)
5727                 goto err_fid_bc_flood_set;
5728
5729         err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5730                                   mlxsw_sp_fid_index(rif->fid), true);
5731         if (err)
5732                 goto err_rif_fdb_op;
5733
5734         mlxsw_sp_fid_rif_set(rif->fid, rif);
5735         return 0;
5736
5737 err_rif_fdb_op:
5738         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5739                                mlxsw_sp_router_port(mlxsw_sp), false);
5740 err_fid_bc_flood_set:
5741         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5742                                mlxsw_sp_router_port(mlxsw_sp), false);
5743 err_fid_mc_flood_set:
5744         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
5745         return err;
5746 }
5747
5748 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
5749 {
5750         u16 fid_index = mlxsw_sp_fid_index(rif->fid);
5751         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5752         struct mlxsw_sp_fid *fid = rif->fid;
5753
5754         mlxsw_sp_fid_rif_set(fid, NULL);
5755         mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5756                             mlxsw_sp_fid_index(fid), false);
5757         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5758                                mlxsw_sp_router_port(mlxsw_sp), false);
5759         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5760                                mlxsw_sp_router_port(mlxsw_sp), false);
5761         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
5762 }
5763
5764 static struct mlxsw_sp_fid *
5765 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif)
5766 {
5767         return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
5768 }
5769
5770 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
5771         .type                   = MLXSW_SP_RIF_TYPE_FID,
5772         .rif_size               = sizeof(struct mlxsw_sp_rif),
5773         .configure              = mlxsw_sp_rif_fid_configure,
5774         .deconfigure            = mlxsw_sp_rif_fid_deconfigure,
5775         .fid_get                = mlxsw_sp_rif_fid_fid_get,
5776 };
5777
5778 static struct mlxsw_sp_rif_ipip_lb *
5779 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
5780 {
5781         return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
5782 }
5783
5784 static void
5785 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
5786                            const struct mlxsw_sp_rif_params *params)
5787 {
5788         struct mlxsw_sp_rif_params_ipip_lb *params_lb;
5789         struct mlxsw_sp_rif_ipip_lb *rif_lb;
5790
5791         params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
5792                                  common);
5793         rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
5794         rif_lb->lb_config = params_lb->lb_config;
5795 }
5796
5797 static int
5798 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
5799                         struct mlxsw_sp_vr *ul_vr, bool enable)
5800 {
5801         struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
5802         struct mlxsw_sp_rif *rif = &lb_rif->common;
5803         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5804         char ritr_pl[MLXSW_REG_RITR_LEN];
5805         u32 saddr4;
5806
5807         switch (lb_cf.ul_protocol) {
5808         case MLXSW_SP_L3_PROTO_IPV4:
5809                 saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
5810                 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
5811                                     rif->rif_index, rif->vr_id, rif->dev->mtu);
5812                 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
5813                             MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
5814                             ul_vr->id, saddr4, lb_cf.okey);
5815                 break;
5816
5817         case MLXSW_SP_L3_PROTO_IPV6:
5818                 return -EAFNOSUPPORT;
5819         }
5820
5821         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5822 }
5823
5824 static int
5825 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
5826 {
5827         struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5828         u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
5829         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5830         struct mlxsw_sp_vr *ul_vr;
5831         int err;
5832
5833         ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id);
5834         if (IS_ERR(ul_vr))
5835                 return PTR_ERR(ul_vr);
5836
5837         err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
5838         if (err)
5839                 goto err_loopback_op;
5840
5841         lb_rif->ul_vr_id = ul_vr->id;
5842         ++ul_vr->rif_count;
5843         return 0;
5844
5845 err_loopback_op:
5846         mlxsw_sp_vr_put(ul_vr);
5847         return err;
5848 }
5849
5850 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
5851 {
5852         struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5853         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5854         struct mlxsw_sp_vr *ul_vr;
5855
5856         ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
5857         mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false);
5858
5859         --ul_vr->rif_count;
5860         mlxsw_sp_vr_put(ul_vr);
5861 }
5862
5863 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = {
5864         .type                   = MLXSW_SP_RIF_TYPE_IPIP_LB,
5865         .rif_size               = sizeof(struct mlxsw_sp_rif_ipip_lb),
5866         .setup                  = mlxsw_sp_rif_ipip_lb_setup,
5867         .configure              = mlxsw_sp_rif_ipip_lb_configure,
5868         .deconfigure            = mlxsw_sp_rif_ipip_lb_deconfigure,
5869 };
5870
5871 static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = {
5872         [MLXSW_SP_RIF_TYPE_SUBPORT]     = &mlxsw_sp_rif_subport_ops,
5873         [MLXSW_SP_RIF_TYPE_VLAN]        = &mlxsw_sp_rif_vlan_ops,
5874         [MLXSW_SP_RIF_TYPE_FID]         = &mlxsw_sp_rif_fid_ops,
5875         [MLXSW_SP_RIF_TYPE_IPIP_LB]     = &mlxsw_sp_rif_ipip_lb_ops,
5876 };
5877
5878 static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
5879 {
5880         u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
5881
5882         mlxsw_sp->router->rifs = kcalloc(max_rifs,
5883                                          sizeof(struct mlxsw_sp_rif *),
5884                                          GFP_KERNEL);
5885         if (!mlxsw_sp->router->rifs)
5886                 return -ENOMEM;
5887
5888         mlxsw_sp->router->rif_ops_arr = mlxsw_sp_rif_ops_arr;
5889
5890         return 0;
5891 }
5892
5893 static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
5894 {
5895         int i;
5896
5897         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
5898                 WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
5899
5900         kfree(mlxsw_sp->router->rifs);
5901 }
5902
5903 static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
5904 {
5905         mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr;
5906         INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);
5907         return 0;
5908 }
5909
5910 static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp)
5911 {
5912         WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list));
5913 }
5914
5915 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
5916 {
5917         struct mlxsw_sp_router *router;
5918
5919         /* Flush pending FIB notifications and then flush the device's
5920          * table before requesting another dump. The FIB notification
5921          * block is unregistered, so no need to take RTNL.
5922          */
5923         mlxsw_core_flush_owq();
5924         router = container_of(nb, struct mlxsw_sp_router, fib_nb);
5925         mlxsw_sp_router_fib_flush(router->mlxsw_sp);
5926 }
5927
5928 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
5929 {
5930         char rgcr_pl[MLXSW_REG_RGCR_LEN];
5931         u64 max_rifs;
5932         int err;
5933
5934         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
5935                 return -EIO;
5936         max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
5937
5938         mlxsw_reg_rgcr_pack(rgcr_pl, true, true);
5939         mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
5940         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
5941         if (err)
5942                 return err;
5943         return 0;
5944 }
5945
5946 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
5947 {
5948         char rgcr_pl[MLXSW_REG_RGCR_LEN];
5949
5950         mlxsw_reg_rgcr_pack(rgcr_pl, false, false);
5951         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
5952 }
5953
5954 int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
5955 {
5956         struct mlxsw_sp_router *router;
5957         int err;
5958
5959         router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
5960         if (!router)
5961                 return -ENOMEM;
5962         mlxsw_sp->router = router;
5963         router->mlxsw_sp = mlxsw_sp;
5964
5965         INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
5966         err = __mlxsw_sp_router_init(mlxsw_sp);
5967         if (err)
5968                 goto err_router_init;
5969
5970         err = mlxsw_sp_rifs_init(mlxsw_sp);
5971         if (err)
5972                 goto err_rifs_init;
5973
5974         err = mlxsw_sp_ipips_init(mlxsw_sp);
5975         if (err)
5976                 goto err_ipips_init;
5977
5978         err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
5979                               &mlxsw_sp_nexthop_ht_params);
5980         if (err)
5981                 goto err_nexthop_ht_init;
5982
5983         err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht,
5984                               &mlxsw_sp_nexthop_group_ht_params);
5985         if (err)
5986                 goto err_nexthop_group_ht_init;
5987
5988         err = mlxsw_sp_lpm_init(mlxsw_sp);
5989         if (err)
5990                 goto err_lpm_init;
5991
5992         err = mlxsw_sp_vrs_init(mlxsw_sp);
5993         if (err)
5994                 goto err_vrs_init;
5995
5996         err = mlxsw_sp_neigh_init(mlxsw_sp);
5997         if (err)
5998                 goto err_neigh_init;
5999
6000         mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
6001         err = register_fib_notifier(&mlxsw_sp->router->fib_nb,
6002                                     mlxsw_sp_router_fib_dump_flush);
6003         if (err)
6004                 goto err_register_fib_notifier;
6005
6006         return 0;
6007
6008 err_register_fib_notifier:
6009         mlxsw_sp_neigh_fini(mlxsw_sp);
6010 err_neigh_init:
6011         mlxsw_sp_vrs_fini(mlxsw_sp);
6012 err_vrs_init:
6013         mlxsw_sp_lpm_fini(mlxsw_sp);
6014 err_lpm_init:
6015         rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
6016 err_nexthop_group_ht_init:
6017         rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
6018 err_nexthop_ht_init:
6019         mlxsw_sp_ipips_fini(mlxsw_sp);
6020 err_ipips_init:
6021         mlxsw_sp_rifs_fini(mlxsw_sp);
6022 err_rifs_init:
6023         __mlxsw_sp_router_fini(mlxsw_sp);
6024 err_router_init:
6025         kfree(mlxsw_sp->router);
6026         return err;
6027 }
6028
6029 void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
6030 {
6031         unregister_fib_notifier(&mlxsw_sp->router->fib_nb);
6032         mlxsw_sp_neigh_fini(mlxsw_sp);
6033         mlxsw_sp_vrs_fini(mlxsw_sp);
6034         mlxsw_sp_lpm_fini(mlxsw_sp);
6035         rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
6036         rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
6037         mlxsw_sp_ipips_fini(mlxsw_sp);
6038         mlxsw_sp_rifs_fini(mlxsw_sp);
6039         __mlxsw_sp_router_fini(mlxsw_sp);
6040         kfree(mlxsw_sp->router);
6041 }