Merge tag 'tilcdc-4.15-fixes' of https://github.com/jsarha/linux into drm-next
[sfrench/cifs-2.6.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_rif_fini(nh);
2727                 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
2728                 break;
2729         }
2730 }
2731
2732 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp,
2733                                        struct mlxsw_sp_nexthop *nh,
2734                                        struct fib_nh *fib_nh)
2735 {
2736         struct mlxsw_sp_router *router = mlxsw_sp->router;
2737         struct net_device *dev = fib_nh->nh_dev;
2738         enum mlxsw_sp_ipip_type ipipt;
2739         struct mlxsw_sp_rif *rif;
2740         int err;
2741
2742         if (mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fib_nh, &ipipt) &&
2743             router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
2744                                                      MLXSW_SP_L3_PROTO_IPV4)) {
2745                 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
2746                 err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
2747                 if (err)
2748                         return err;
2749                 mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common);
2750                 return 0;
2751         }
2752
2753         nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
2754         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
2755         if (!rif)
2756                 return 0;
2757
2758         mlxsw_sp_nexthop_rif_init(nh, rif);
2759         err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
2760         if (err)
2761                 goto err_neigh_init;
2762
2763         return 0;
2764
2765 err_neigh_init:
2766         mlxsw_sp_nexthop_rif_fini(nh);
2767         return err;
2768 }
2769
2770 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp *mlxsw_sp,
2771                                         struct mlxsw_sp_nexthop *nh)
2772 {
2773         mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
2774 }
2775
2776 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
2777                                   struct mlxsw_sp_nexthop_group *nh_grp,
2778                                   struct mlxsw_sp_nexthop *nh,
2779                                   struct fib_nh *fib_nh)
2780 {
2781         struct net_device *dev = fib_nh->nh_dev;
2782         struct in_device *in_dev;
2783         int err;
2784
2785         nh->nh_grp = nh_grp;
2786         nh->key.fib_nh = fib_nh;
2787         memcpy(&nh->gw_addr, &fib_nh->nh_gw, sizeof(fib_nh->nh_gw));
2788         err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
2789         if (err)
2790                 return err;
2791
2792         if (!dev)
2793                 return 0;
2794
2795         in_dev = __in_dev_get_rtnl(dev);
2796         if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
2797             fib_nh->nh_flags & RTNH_F_LINKDOWN)
2798                 return 0;
2799
2800         err = mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
2801         if (err)
2802                 goto err_nexthop_neigh_init;
2803
2804         return 0;
2805
2806 err_nexthop_neigh_init:
2807         mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
2808         return err;
2809 }
2810
2811 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp *mlxsw_sp,
2812                                    struct mlxsw_sp_nexthop *nh)
2813 {
2814         mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh);
2815         mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
2816 }
2817
2818 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
2819                                     unsigned long event, struct fib_nh *fib_nh)
2820 {
2821         struct mlxsw_sp_nexthop_key key;
2822         struct mlxsw_sp_nexthop *nh;
2823
2824         if (mlxsw_sp->router->aborted)
2825                 return;
2826
2827         key.fib_nh = fib_nh;
2828         nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
2829         if (WARN_ON_ONCE(!nh))
2830                 return;
2831
2832         switch (event) {
2833         case FIB_EVENT_NH_ADD:
2834                 mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
2835                 break;
2836         case FIB_EVENT_NH_DEL:
2837                 mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh);
2838                 break;
2839         }
2840
2841         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
2842 }
2843
2844 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
2845                                            struct mlxsw_sp_rif *rif)
2846 {
2847         struct mlxsw_sp_nexthop *nh, *tmp;
2848
2849         list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
2850                 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
2851                 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
2852         }
2853 }
2854
2855 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp,
2856                                    const struct fib_info *fi)
2857 {
2858         return fi->fib_nh->nh_scope == RT_SCOPE_LINK ||
2859                mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, fi->fib_nh, NULL);
2860 }
2861
2862 static struct mlxsw_sp_nexthop_group *
2863 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
2864 {
2865         struct mlxsw_sp_nexthop_group *nh_grp;
2866         struct mlxsw_sp_nexthop *nh;
2867         struct fib_nh *fib_nh;
2868         size_t alloc_size;
2869         int i;
2870         int err;
2871
2872         alloc_size = sizeof(*nh_grp) +
2873                      fi->fib_nhs * sizeof(struct mlxsw_sp_nexthop);
2874         nh_grp = kzalloc(alloc_size, GFP_KERNEL);
2875         if (!nh_grp)
2876                 return ERR_PTR(-ENOMEM);
2877         nh_grp->priv = fi;
2878         INIT_LIST_HEAD(&nh_grp->fib_list);
2879         nh_grp->neigh_tbl = &arp_tbl;
2880
2881         nh_grp->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, fi);
2882         nh_grp->count = fi->fib_nhs;
2883         fib_info_hold(fi);
2884         for (i = 0; i < nh_grp->count; i++) {
2885                 nh = &nh_grp->nexthops[i];
2886                 fib_nh = &fi->fib_nh[i];
2887                 err = mlxsw_sp_nexthop4_init(mlxsw_sp, nh_grp, nh, fib_nh);
2888                 if (err)
2889                         goto err_nexthop4_init;
2890         }
2891         err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
2892         if (err)
2893                 goto err_nexthop_group_insert;
2894         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
2895         return nh_grp;
2896
2897 err_nexthop_group_insert:
2898 err_nexthop4_init:
2899         for (i--; i >= 0; i--) {
2900                 nh = &nh_grp->nexthops[i];
2901                 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
2902         }
2903         fib_info_put(fi);
2904         kfree(nh_grp);
2905         return ERR_PTR(err);
2906 }
2907
2908 static void
2909 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp *mlxsw_sp,
2910                                 struct mlxsw_sp_nexthop_group *nh_grp)
2911 {
2912         struct mlxsw_sp_nexthop *nh;
2913         int i;
2914
2915         mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
2916         for (i = 0; i < nh_grp->count; i++) {
2917                 nh = &nh_grp->nexthops[i];
2918                 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
2919         }
2920         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
2921         WARN_ON_ONCE(nh_grp->adj_index_valid);
2922         fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp));
2923         kfree(nh_grp);
2924 }
2925
2926 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp *mlxsw_sp,
2927                                        struct mlxsw_sp_fib_entry *fib_entry,
2928                                        struct fib_info *fi)
2929 {
2930         struct mlxsw_sp_nexthop_group *nh_grp;
2931
2932         nh_grp = mlxsw_sp_nexthop4_group_lookup(mlxsw_sp, fi);
2933         if (!nh_grp) {
2934                 nh_grp = mlxsw_sp_nexthop4_group_create(mlxsw_sp, fi);
2935                 if (IS_ERR(nh_grp))
2936                         return PTR_ERR(nh_grp);
2937         }
2938         list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list);
2939         fib_entry->nh_group = nh_grp;
2940         return 0;
2941 }
2942
2943 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp *mlxsw_sp,
2944                                         struct mlxsw_sp_fib_entry *fib_entry)
2945 {
2946         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
2947
2948         list_del(&fib_entry->nexthop_group_node);
2949         if (!list_empty(&nh_grp->fib_list))
2950                 return;
2951         mlxsw_sp_nexthop4_group_destroy(mlxsw_sp, nh_grp);
2952 }
2953
2954 static bool
2955 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
2956 {
2957         struct mlxsw_sp_fib4_entry *fib4_entry;
2958
2959         fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
2960                                   common);
2961         return !fib4_entry->tos;
2962 }
2963
2964 static bool
2965 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
2966 {
2967         struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
2968
2969         switch (fib_entry->fib_node->fib->proto) {
2970         case MLXSW_SP_L3_PROTO_IPV4:
2971                 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry))
2972                         return false;
2973                 break;
2974         case MLXSW_SP_L3_PROTO_IPV6:
2975                 break;
2976         }
2977
2978         switch (fib_entry->type) {
2979         case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
2980                 return !!nh_group->adj_index_valid;
2981         case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
2982                 return !!nh_group->nh_rif;
2983         case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
2984                 return true;
2985         default:
2986                 return false;
2987         }
2988 }
2989
2990 static struct mlxsw_sp_nexthop *
2991 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
2992                      const struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
2993 {
2994         int i;
2995
2996         for (i = 0; i < nh_grp->count; i++) {
2997                 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
2998                 struct rt6_info *rt = mlxsw_sp_rt6->rt;
2999
3000                 if (nh->rif && nh->rif->dev == rt->dst.dev &&
3001                     ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
3002                                     &rt->rt6i_gateway))
3003                         return nh;
3004                 continue;
3005         }
3006
3007         return NULL;
3008 }
3009
3010 static void
3011 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3012 {
3013         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
3014         int i;
3015
3016         if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL ||
3017             fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP) {
3018                 nh_grp->nexthops->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
3019                 return;
3020         }
3021
3022         for (i = 0; i < nh_grp->count; i++) {
3023                 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
3024
3025                 if (nh->offloaded)
3026                         nh->key.fib_nh->nh_flags |= RTNH_F_OFFLOAD;
3027                 else
3028                         nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
3029         }
3030 }
3031
3032 static void
3033 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
3034 {
3035         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
3036         int i;
3037
3038         for (i = 0; i < nh_grp->count; i++) {
3039                 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
3040
3041                 nh->key.fib_nh->nh_flags &= ~RTNH_F_OFFLOAD;
3042         }
3043 }
3044
3045 static void
3046 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3047 {
3048         struct mlxsw_sp_fib6_entry *fib6_entry;
3049         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3050
3051         fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
3052                                   common);
3053
3054         if (fib_entry->type == MLXSW_SP_FIB_ENTRY_TYPE_LOCAL) {
3055                 list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
3056                                  list)->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD;
3057                 return;
3058         }
3059
3060         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3061                 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
3062                 struct mlxsw_sp_nexthop *nh;
3063
3064                 nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
3065                 if (nh && nh->offloaded)
3066                         mlxsw_sp_rt6->rt->rt6i_nh_flags |= RTNH_F_OFFLOAD;
3067                 else
3068                         mlxsw_sp_rt6->rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD;
3069         }
3070 }
3071
3072 static void
3073 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
3074 {
3075         struct mlxsw_sp_fib6_entry *fib6_entry;
3076         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3077
3078         fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
3079                                   common);
3080         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3081                 struct rt6_info *rt = mlxsw_sp_rt6->rt;
3082
3083                 rt->rt6i_nh_flags &= ~RTNH_F_OFFLOAD;
3084         }
3085 }
3086
3087 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry *fib_entry)
3088 {
3089         switch (fib_entry->fib_node->fib->proto) {
3090         case MLXSW_SP_L3_PROTO_IPV4:
3091                 mlxsw_sp_fib4_entry_offload_set(fib_entry);
3092                 break;
3093         case MLXSW_SP_L3_PROTO_IPV6:
3094                 mlxsw_sp_fib6_entry_offload_set(fib_entry);
3095                 break;
3096         }
3097 }
3098
3099 static void
3100 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry *fib_entry)
3101 {
3102         switch (fib_entry->fib_node->fib->proto) {
3103         case MLXSW_SP_L3_PROTO_IPV4:
3104                 mlxsw_sp_fib4_entry_offload_unset(fib_entry);
3105                 break;
3106         case MLXSW_SP_L3_PROTO_IPV6:
3107                 mlxsw_sp_fib6_entry_offload_unset(fib_entry);
3108                 break;
3109         }
3110 }
3111
3112 static void
3113 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry *fib_entry,
3114                                    enum mlxsw_reg_ralue_op op, int err)
3115 {
3116         switch (op) {
3117         case MLXSW_REG_RALUE_OP_WRITE_DELETE:
3118                 return mlxsw_sp_fib_entry_offload_unset(fib_entry);
3119         case MLXSW_REG_RALUE_OP_WRITE_WRITE:
3120                 if (err)
3121                         return;
3122                 if (mlxsw_sp_fib_entry_should_offload(fib_entry))
3123                         mlxsw_sp_fib_entry_offload_set(fib_entry);
3124                 else if (!mlxsw_sp_fib_entry_should_offload(fib_entry))
3125                         mlxsw_sp_fib_entry_offload_unset(fib_entry);
3126                 return;
3127         default:
3128                 return;
3129         }
3130 }
3131
3132 static void
3133 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl,
3134                               const struct mlxsw_sp_fib_entry *fib_entry,
3135                               enum mlxsw_reg_ralue_op op)
3136 {
3137         struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
3138         enum mlxsw_reg_ralxx_protocol proto;
3139         u32 *p_dip;
3140
3141         proto = (enum mlxsw_reg_ralxx_protocol) fib->proto;
3142
3143         switch (fib->proto) {
3144         case MLXSW_SP_L3_PROTO_IPV4:
3145                 p_dip = (u32 *) fib_entry->fib_node->key.addr;
3146                 mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id,
3147                                       fib_entry->fib_node->key.prefix_len,
3148                                       *p_dip);
3149                 break;
3150         case MLXSW_SP_L3_PROTO_IPV6:
3151                 mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id,
3152                                       fib_entry->fib_node->key.prefix_len,
3153                                       fib_entry->fib_node->key.addr);
3154                 break;
3155         }
3156 }
3157
3158 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
3159                                         struct mlxsw_sp_fib_entry *fib_entry,
3160                                         enum mlxsw_reg_ralue_op op)
3161 {
3162         char ralue_pl[MLXSW_REG_RALUE_LEN];
3163         enum mlxsw_reg_ralue_trap_action trap_action;
3164         u16 trap_id = 0;
3165         u32 adjacency_index = 0;
3166         u16 ecmp_size = 0;
3167
3168         /* In case the nexthop group adjacency index is valid, use it
3169          * with provided ECMP size. Otherwise, setup trap and pass
3170          * traffic to kernel.
3171          */
3172         if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
3173                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
3174                 adjacency_index = fib_entry->nh_group->adj_index;
3175                 ecmp_size = fib_entry->nh_group->ecmp_size;
3176         } else {
3177                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
3178                 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
3179         }
3180
3181         mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
3182         mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id,
3183                                         adjacency_index, ecmp_size);
3184         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
3185 }
3186
3187 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
3188                                        struct mlxsw_sp_fib_entry *fib_entry,
3189                                        enum mlxsw_reg_ralue_op op)
3190 {
3191         struct mlxsw_sp_rif *rif = fib_entry->nh_group->nh_rif;
3192         enum mlxsw_reg_ralue_trap_action trap_action;
3193         char ralue_pl[MLXSW_REG_RALUE_LEN];
3194         u16 trap_id = 0;
3195         u16 rif_index = 0;
3196
3197         if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
3198                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
3199                 rif_index = rif->rif_index;
3200         } else {
3201                 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
3202                 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
3203         }
3204
3205         mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
3206         mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id,
3207                                        rif_index);
3208         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
3209 }
3210
3211 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
3212                                       struct mlxsw_sp_fib_entry *fib_entry,
3213                                       enum mlxsw_reg_ralue_op op)
3214 {
3215         char ralue_pl[MLXSW_REG_RALUE_LEN];
3216
3217         mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
3218         mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
3219         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
3220 }
3221
3222 static int
3223 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
3224                                  struct mlxsw_sp_fib_entry *fib_entry,
3225                                  enum mlxsw_reg_ralue_op op)
3226 {
3227         struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry;
3228         const struct mlxsw_sp_ipip_ops *ipip_ops;
3229
3230         if (WARN_ON(!ipip_entry))
3231                 return -EINVAL;
3232
3233         ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
3234         return ipip_ops->fib_entry_op(mlxsw_sp, ipip_entry, op,
3235                                       fib_entry->decap.tunnel_index);
3236 }
3237
3238 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
3239                                    struct mlxsw_sp_fib_entry *fib_entry,
3240                                    enum mlxsw_reg_ralue_op op)
3241 {
3242         switch (fib_entry->type) {
3243         case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
3244                 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op);
3245         case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
3246                 return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
3247         case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
3248                 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
3249         case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
3250                 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
3251                                                         fib_entry, op);
3252         }
3253         return -EINVAL;
3254 }
3255
3256 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
3257                                  struct mlxsw_sp_fib_entry *fib_entry,
3258                                  enum mlxsw_reg_ralue_op op)
3259 {
3260         int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op);
3261
3262         mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, err);
3263
3264         return err;
3265 }
3266
3267 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
3268                                      struct mlxsw_sp_fib_entry *fib_entry)
3269 {
3270         return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
3271                                      MLXSW_REG_RALUE_OP_WRITE_WRITE);
3272 }
3273
3274 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
3275                                   struct mlxsw_sp_fib_entry *fib_entry)
3276 {
3277         return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
3278                                      MLXSW_REG_RALUE_OP_WRITE_DELETE);
3279 }
3280
3281 static int
3282 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
3283                              const struct fib_entry_notifier_info *fen_info,
3284                              struct mlxsw_sp_fib_entry *fib_entry)
3285 {
3286         union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) };
3287         struct net_device *dev = fen_info->fi->fib_dev;
3288         struct mlxsw_sp_ipip_entry *ipip_entry;
3289         struct fib_info *fi = fen_info->fi;
3290
3291         switch (fen_info->type) {
3292         case RTN_LOCAL:
3293                 ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, dev,
3294                                                  MLXSW_SP_L3_PROTO_IPV4, dip);
3295                 if (ipip_entry) {
3296                         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
3297                         return mlxsw_sp_fib_entry_decap_init(mlxsw_sp,
3298                                                              fib_entry,
3299                                                              ipip_entry);
3300                 }
3301                 /* fall through */
3302         case RTN_BROADCAST:
3303                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
3304                 return 0;
3305         case RTN_UNREACHABLE: /* fall through */
3306         case RTN_BLACKHOLE: /* fall through */
3307         case RTN_PROHIBIT:
3308                 /* Packets hitting these routes need to be trapped, but
3309                  * can do so with a lower priority than packets directed
3310                  * at the host, so use action type local instead of trap.
3311                  */
3312                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
3313                 return 0;
3314         case RTN_UNICAST:
3315                 if (mlxsw_sp_fi_is_gateway(mlxsw_sp, fi))
3316                         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
3317                 else
3318                         fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
3319                 return 0;
3320         default:
3321                 return -EINVAL;
3322         }
3323 }
3324
3325 static struct mlxsw_sp_fib4_entry *
3326 mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
3327                            struct mlxsw_sp_fib_node *fib_node,
3328                            const struct fib_entry_notifier_info *fen_info)
3329 {
3330         struct mlxsw_sp_fib4_entry *fib4_entry;
3331         struct mlxsw_sp_fib_entry *fib_entry;
3332         int err;
3333
3334         fib4_entry = kzalloc(sizeof(*fib4_entry), GFP_KERNEL);
3335         if (!fib4_entry)
3336                 return ERR_PTR(-ENOMEM);
3337         fib_entry = &fib4_entry->common;
3338
3339         err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry);
3340         if (err)
3341                 goto err_fib4_entry_type_set;
3342
3343         err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi);
3344         if (err)
3345                 goto err_nexthop4_group_get;
3346
3347         fib4_entry->prio = fen_info->fi->fib_priority;
3348         fib4_entry->tb_id = fen_info->tb_id;
3349         fib4_entry->type = fen_info->type;
3350         fib4_entry->tos = fen_info->tos;
3351
3352         fib_entry->fib_node = fib_node;
3353
3354         return fib4_entry;
3355
3356 err_nexthop4_group_get:
3357 err_fib4_entry_type_set:
3358         kfree(fib4_entry);
3359         return ERR_PTR(err);
3360 }
3361
3362 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
3363                                         struct mlxsw_sp_fib4_entry *fib4_entry)
3364 {
3365         mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
3366         kfree(fib4_entry);
3367 }
3368
3369 static struct mlxsw_sp_fib4_entry *
3370 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
3371                            const struct fib_entry_notifier_info *fen_info)
3372 {
3373         struct mlxsw_sp_fib4_entry *fib4_entry;
3374         struct mlxsw_sp_fib_node *fib_node;
3375         struct mlxsw_sp_fib *fib;
3376         struct mlxsw_sp_vr *vr;
3377
3378         vr = mlxsw_sp_vr_find(mlxsw_sp, fen_info->tb_id);
3379         if (!vr)
3380                 return NULL;
3381         fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4);
3382
3383         fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst,
3384                                             sizeof(fen_info->dst),
3385                                             fen_info->dst_len);
3386         if (!fib_node)
3387                 return NULL;
3388
3389         list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
3390                 if (fib4_entry->tb_id == fen_info->tb_id &&
3391                     fib4_entry->tos == fen_info->tos &&
3392                     fib4_entry->type == fen_info->type &&
3393                     mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) ==
3394                     fen_info->fi) {
3395                         return fib4_entry;
3396                 }
3397         }
3398
3399         return NULL;
3400 }
3401
3402 static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
3403         .key_offset = offsetof(struct mlxsw_sp_fib_node, key),
3404         .head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node),
3405         .key_len = sizeof(struct mlxsw_sp_fib_key),
3406         .automatic_shrinking = true,
3407 };
3408
3409 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib,
3410                                     struct mlxsw_sp_fib_node *fib_node)
3411 {
3412         return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node,
3413                                       mlxsw_sp_fib_ht_params);
3414 }
3415
3416 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib,
3417                                      struct mlxsw_sp_fib_node *fib_node)
3418 {
3419         rhashtable_remove_fast(&fib->ht, &fib_node->ht_node,
3420                                mlxsw_sp_fib_ht_params);
3421 }
3422
3423 static struct mlxsw_sp_fib_node *
3424 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
3425                          size_t addr_len, unsigned char prefix_len)
3426 {
3427         struct mlxsw_sp_fib_key key;
3428
3429         memset(&key, 0, sizeof(key));
3430         memcpy(key.addr, addr, addr_len);
3431         key.prefix_len = prefix_len;
3432         return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
3433 }
3434
3435 static struct mlxsw_sp_fib_node *
3436 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
3437                          size_t addr_len, unsigned char prefix_len)
3438 {
3439         struct mlxsw_sp_fib_node *fib_node;
3440
3441         fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL);
3442         if (!fib_node)
3443                 return NULL;
3444
3445         INIT_LIST_HEAD(&fib_node->entry_list);
3446         list_add(&fib_node->list, &fib->node_list);
3447         memcpy(fib_node->key.addr, addr, addr_len);
3448         fib_node->key.prefix_len = prefix_len;
3449
3450         return fib_node;
3451 }
3452
3453 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
3454 {
3455         list_del(&fib_node->list);
3456         WARN_ON(!list_empty(&fib_node->entry_list));
3457         kfree(fib_node);
3458 }
3459
3460 static bool
3461 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node *fib_node,
3462                                  const struct mlxsw_sp_fib_entry *fib_entry)
3463 {
3464         return list_first_entry(&fib_node->entry_list,
3465                                 struct mlxsw_sp_fib_entry, list) == fib_entry;
3466 }
3467
3468 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp,
3469                                       struct mlxsw_sp_fib *fib,
3470                                       struct mlxsw_sp_fib_node *fib_node)
3471 {
3472         struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
3473         struct mlxsw_sp_lpm_tree *lpm_tree;
3474         int err;
3475
3476         /* Since the tree is shared between all virtual routers we must
3477          * make sure it contains all the required prefix lengths. This
3478          * can be computed by either adding the new prefix length to the
3479          * existing prefix usage of a bound tree, or by aggregating the
3480          * prefix lengths across all virtual routers and adding the new
3481          * one as well.
3482          */
3483         if (fib->lpm_tree)
3484                 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage,
3485                                           &fib->lpm_tree->prefix_usage);
3486         else
3487                 mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage);
3488         mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len);
3489
3490         lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
3491                                          fib->proto);
3492         if (IS_ERR(lpm_tree))
3493                 return PTR_ERR(lpm_tree);
3494
3495         if (fib->lpm_tree && fib->lpm_tree->id == lpm_tree->id)
3496                 return 0;
3497
3498         err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
3499         if (err)
3500                 return err;
3501
3502         return 0;
3503 }
3504
3505 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp,
3506                                          struct mlxsw_sp_fib *fib)
3507 {
3508         if (!mlxsw_sp_prefix_usage_none(&fib->prefix_usage))
3509                 return;
3510         mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
3511         mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree);
3512         fib->lpm_tree = NULL;
3513 }
3514
3515 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node *fib_node)
3516 {
3517         unsigned char prefix_len = fib_node->key.prefix_len;
3518         struct mlxsw_sp_fib *fib = fib_node->fib;
3519
3520         if (fib->prefix_ref_count[prefix_len]++ == 0)
3521                 mlxsw_sp_prefix_usage_set(&fib->prefix_usage, prefix_len);
3522 }
3523
3524 static void mlxsw_sp_fib_node_prefix_dec(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_clear(&fib->prefix_usage, prefix_len);
3531 }
3532
3533 static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
3534                                   struct mlxsw_sp_fib_node *fib_node,
3535                                   struct mlxsw_sp_fib *fib)
3536 {
3537         int err;
3538
3539         err = mlxsw_sp_fib_node_insert(fib, fib_node);
3540         if (err)
3541                 return err;
3542         fib_node->fib = fib;
3543
3544         err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib, fib_node);
3545         if (err)
3546                 goto err_fib_lpm_tree_link;
3547
3548         mlxsw_sp_fib_node_prefix_inc(fib_node);
3549
3550         return 0;
3551
3552 err_fib_lpm_tree_link:
3553         fib_node->fib = NULL;
3554         mlxsw_sp_fib_node_remove(fib, fib_node);
3555         return err;
3556 }
3557
3558 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
3559                                    struct mlxsw_sp_fib_node *fib_node)
3560 {
3561         struct mlxsw_sp_fib *fib = fib_node->fib;
3562
3563         mlxsw_sp_fib_node_prefix_dec(fib_node);
3564         mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib);
3565         fib_node->fib = NULL;
3566         mlxsw_sp_fib_node_remove(fib, fib_node);
3567 }
3568
3569 static struct mlxsw_sp_fib_node *
3570 mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
3571                       size_t addr_len, unsigned char prefix_len,
3572                       enum mlxsw_sp_l3proto proto)
3573 {
3574         struct mlxsw_sp_fib_node *fib_node;
3575         struct mlxsw_sp_fib *fib;
3576         struct mlxsw_sp_vr *vr;
3577         int err;
3578
3579         vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id);
3580         if (IS_ERR(vr))
3581                 return ERR_CAST(vr);
3582         fib = mlxsw_sp_vr_fib(vr, proto);
3583
3584         fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len);
3585         if (fib_node)
3586                 return fib_node;
3587
3588         fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len);
3589         if (!fib_node) {
3590                 err = -ENOMEM;
3591                 goto err_fib_node_create;
3592         }
3593
3594         err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
3595         if (err)
3596                 goto err_fib_node_init;
3597
3598         return fib_node;
3599
3600 err_fib_node_init:
3601         mlxsw_sp_fib_node_destroy(fib_node);
3602 err_fib_node_create:
3603         mlxsw_sp_vr_put(vr);
3604         return ERR_PTR(err);
3605 }
3606
3607 static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
3608                                   struct mlxsw_sp_fib_node *fib_node)
3609 {
3610         struct mlxsw_sp_vr *vr = fib_node->fib->vr;
3611
3612         if (!list_empty(&fib_node->entry_list))
3613                 return;
3614         mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
3615         mlxsw_sp_fib_node_destroy(fib_node);
3616         mlxsw_sp_vr_put(vr);
3617 }
3618
3619 static struct mlxsw_sp_fib4_entry *
3620 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
3621                               const struct mlxsw_sp_fib4_entry *new4_entry)
3622 {
3623         struct mlxsw_sp_fib4_entry *fib4_entry;
3624
3625         list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
3626                 if (fib4_entry->tb_id > new4_entry->tb_id)
3627                         continue;
3628                 if (fib4_entry->tb_id != new4_entry->tb_id)
3629                         break;
3630                 if (fib4_entry->tos > new4_entry->tos)
3631                         continue;
3632                 if (fib4_entry->prio >= new4_entry->prio ||
3633                     fib4_entry->tos < new4_entry->tos)
3634                         return fib4_entry;
3635         }
3636
3637         return NULL;
3638 }
3639
3640 static int
3641 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry *fib4_entry,
3642                                struct mlxsw_sp_fib4_entry *new4_entry)
3643 {
3644         struct mlxsw_sp_fib_node *fib_node;
3645
3646         if (WARN_ON(!fib4_entry))
3647                 return -EINVAL;
3648
3649         fib_node = fib4_entry->common.fib_node;
3650         list_for_each_entry_from(fib4_entry, &fib_node->entry_list,
3651                                  common.list) {
3652                 if (fib4_entry->tb_id != new4_entry->tb_id ||
3653                     fib4_entry->tos != new4_entry->tos ||
3654                     fib4_entry->prio != new4_entry->prio)
3655                         break;
3656         }
3657
3658         list_add_tail(&new4_entry->common.list, &fib4_entry->common.list);
3659         return 0;
3660 }
3661
3662 static int
3663 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry *new4_entry,
3664                                bool replace, bool append)
3665 {
3666         struct mlxsw_sp_fib_node *fib_node = new4_entry->common.fib_node;
3667         struct mlxsw_sp_fib4_entry *fib4_entry;
3668
3669         fib4_entry = mlxsw_sp_fib4_node_entry_find(fib_node, new4_entry);
3670
3671         if (append)
3672                 return mlxsw_sp_fib4_node_list_append(fib4_entry, new4_entry);
3673         if (replace && WARN_ON(!fib4_entry))
3674                 return -EINVAL;
3675
3676         /* Insert new entry before replaced one, so that we can later
3677          * remove the second.
3678          */
3679         if (fib4_entry) {
3680                 list_add_tail(&new4_entry->common.list,
3681                               &fib4_entry->common.list);
3682         } else {
3683                 struct mlxsw_sp_fib4_entry *last;
3684
3685                 list_for_each_entry(last, &fib_node->entry_list, common.list) {
3686                         if (new4_entry->tb_id > last->tb_id)
3687                                 break;
3688                         fib4_entry = last;
3689                 }
3690
3691                 if (fib4_entry)
3692                         list_add(&new4_entry->common.list,
3693                                  &fib4_entry->common.list);
3694                 else
3695                         list_add(&new4_entry->common.list,
3696                                  &fib_node->entry_list);
3697         }
3698
3699         return 0;
3700 }
3701
3702 static void
3703 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry *fib4_entry)
3704 {
3705         list_del(&fib4_entry->common.list);
3706 }
3707
3708 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp *mlxsw_sp,
3709                                        struct mlxsw_sp_fib_entry *fib_entry)
3710 {
3711         struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
3712
3713         if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
3714                 return 0;
3715
3716         /* To prevent packet loss, overwrite the previously offloaded
3717          * entry.
3718          */
3719         if (!list_is_singular(&fib_node->entry_list)) {
3720                 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
3721                 struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
3722
3723                 mlxsw_sp_fib_entry_offload_refresh(n, op, 0);
3724         }
3725
3726         return mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
3727 }
3728
3729 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp *mlxsw_sp,
3730                                         struct mlxsw_sp_fib_entry *fib_entry)
3731 {
3732         struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
3733
3734         if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
3735                 return;
3736
3737         /* Promote the next entry by overwriting the deleted entry */
3738         if (!list_is_singular(&fib_node->entry_list)) {
3739                 struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
3740                 enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
3741
3742                 mlxsw_sp_fib_entry_update(mlxsw_sp, n);
3743                 mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
3744                 return;
3745         }
3746
3747         mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
3748 }
3749
3750 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
3751                                          struct mlxsw_sp_fib4_entry *fib4_entry,
3752                                          bool replace, bool append)
3753 {
3754         int err;
3755
3756         err = mlxsw_sp_fib4_node_list_insert(fib4_entry, replace, append);
3757         if (err)
3758                 return err;
3759
3760         err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib4_entry->common);
3761         if (err)
3762                 goto err_fib_node_entry_add;
3763
3764         return 0;
3765
3766 err_fib_node_entry_add:
3767         mlxsw_sp_fib4_node_list_remove(fib4_entry);
3768         return err;
3769 }
3770
3771 static void
3772 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
3773                                 struct mlxsw_sp_fib4_entry *fib4_entry)
3774 {
3775         mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib4_entry->common);
3776         mlxsw_sp_fib4_node_list_remove(fib4_entry);
3777
3778         if (fib4_entry->common.type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP)
3779                 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, &fib4_entry->common);
3780 }
3781
3782 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
3783                                         struct mlxsw_sp_fib4_entry *fib4_entry,
3784                                         bool replace)
3785 {
3786         struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
3787         struct mlxsw_sp_fib4_entry *replaced;
3788
3789         if (!replace)
3790                 return;
3791
3792         /* We inserted the new entry before replaced one */
3793         replaced = list_next_entry(fib4_entry, common.list);
3794
3795         mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, replaced);
3796         mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced);
3797         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3798 }
3799
3800 static int
3801 mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
3802                          const struct fib_entry_notifier_info *fen_info,
3803                          bool replace, bool append)
3804 {
3805         struct mlxsw_sp_fib4_entry *fib4_entry;
3806         struct mlxsw_sp_fib_node *fib_node;
3807         int err;
3808
3809         if (mlxsw_sp->router->aborted)
3810                 return 0;
3811
3812         fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
3813                                          &fen_info->dst, sizeof(fen_info->dst),
3814                                          fen_info->dst_len,
3815                                          MLXSW_SP_L3_PROTO_IPV4);
3816         if (IS_ERR(fib_node)) {
3817                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
3818                 return PTR_ERR(fib_node);
3819         }
3820
3821         fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
3822         if (IS_ERR(fib4_entry)) {
3823                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
3824                 err = PTR_ERR(fib4_entry);
3825                 goto err_fib4_entry_create;
3826         }
3827
3828         err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry, replace,
3829                                             append);
3830         if (err) {
3831                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
3832                 goto err_fib4_node_entry_link;
3833         }
3834
3835         mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry, replace);
3836
3837         return 0;
3838
3839 err_fib4_node_entry_link:
3840         mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
3841 err_fib4_entry_create:
3842         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3843         return err;
3844 }
3845
3846 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
3847                                      struct fib_entry_notifier_info *fen_info)
3848 {
3849         struct mlxsw_sp_fib4_entry *fib4_entry;
3850         struct mlxsw_sp_fib_node *fib_node;
3851
3852         if (mlxsw_sp->router->aborted)
3853                 return;
3854
3855         fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
3856         if (WARN_ON(!fib4_entry))
3857                 return;
3858         fib_node = fib4_entry->common.fib_node;
3859
3860         mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
3861         mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
3862         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3863 }
3864
3865 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info *rt)
3866 {
3867         /* Packets with link-local destination IP arriving to the router
3868          * are trapped to the CPU, so no need to program specific routes
3869          * for them.
3870          */
3871         if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LINKLOCAL)
3872                 return true;
3873
3874         /* Multicast routes aren't supported, so ignore them. Neighbour
3875          * Discovery packets are specifically trapped.
3876          */
3877         if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_MULTICAST)
3878                 return true;
3879
3880         /* Cloned routes are irrelevant in the forwarding path. */
3881         if (rt->rt6i_flags & RTF_CACHE)
3882                 return true;
3883
3884         return false;
3885 }
3886
3887 static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct rt6_info *rt)
3888 {
3889         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3890
3891         mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL);
3892         if (!mlxsw_sp_rt6)
3893                 return ERR_PTR(-ENOMEM);
3894
3895         /* In case of route replace, replaced route is deleted with
3896          * no notification. Take reference to prevent accessing freed
3897          * memory.
3898          */
3899         mlxsw_sp_rt6->rt = rt;
3900         rt6_hold(rt);
3901
3902         return mlxsw_sp_rt6;
3903 }
3904
3905 #if IS_ENABLED(CONFIG_IPV6)
3906 static void mlxsw_sp_rt6_release(struct rt6_info *rt)
3907 {
3908         rt6_release(rt);
3909 }
3910 #else
3911 static void mlxsw_sp_rt6_release(struct rt6_info *rt)
3912 {
3913 }
3914 #endif
3915
3916 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
3917 {
3918         mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
3919         kfree(mlxsw_sp_rt6);
3920 }
3921
3922 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info *rt)
3923 {
3924         /* RTF_CACHE routes are ignored */
3925         return (rt->rt6i_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
3926 }
3927
3928 static struct rt6_info *
3929 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
3930 {
3931         return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
3932                                 list)->rt;
3933 }
3934
3935 static struct mlxsw_sp_fib6_entry *
3936 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
3937                                  const struct rt6_info *nrt, bool replace)
3938 {
3939         struct mlxsw_sp_fib6_entry *fib6_entry;
3940
3941         if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
3942                 return NULL;
3943
3944         list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
3945                 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
3946
3947                 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
3948                  * virtual router.
3949                  */
3950                 if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
3951                         continue;
3952                 if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
3953                         break;
3954                 if (rt->rt6i_metric < nrt->rt6i_metric)
3955                         continue;
3956                 if (rt->rt6i_metric == nrt->rt6i_metric &&
3957                     mlxsw_sp_fib6_rt_can_mp(rt))
3958                         return fib6_entry;
3959                 if (rt->rt6i_metric > nrt->rt6i_metric)
3960                         break;
3961         }
3962
3963         return NULL;
3964 }
3965
3966 static struct mlxsw_sp_rt6 *
3967 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
3968                             const struct rt6_info *rt)
3969 {
3970         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3971
3972         list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3973                 if (mlxsw_sp_rt6->rt == rt)
3974                         return mlxsw_sp_rt6;
3975         }
3976
3977         return NULL;
3978 }
3979
3980 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
3981                                         const struct rt6_info *rt,
3982                                         enum mlxsw_sp_ipip_type *ret)
3983 {
3984         return rt->dst.dev &&
3985                mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->dst.dev, ret);
3986 }
3987
3988 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
3989                                        struct mlxsw_sp_nexthop_group *nh_grp,
3990                                        struct mlxsw_sp_nexthop *nh,
3991                                        const struct rt6_info *rt)
3992 {
3993         struct mlxsw_sp_router *router = mlxsw_sp->router;
3994         struct net_device *dev = rt->dst.dev;
3995         enum mlxsw_sp_ipip_type ipipt;
3996         struct mlxsw_sp_rif *rif;
3997         int err;
3998
3999         if (mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, &ipipt) &&
4000             router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
4001                                                      MLXSW_SP_L3_PROTO_IPV6)) {
4002                 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
4003                 err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
4004                 if (err)
4005                         return err;
4006                 mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common);
4007                 return 0;
4008         }
4009
4010         nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
4011         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
4012         if (!rif)
4013                 return 0;
4014         mlxsw_sp_nexthop_rif_init(nh, rif);
4015
4016         err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
4017         if (err)
4018                 goto err_nexthop_neigh_init;
4019
4020         return 0;
4021
4022 err_nexthop_neigh_init:
4023         mlxsw_sp_nexthop_rif_fini(nh);
4024         return err;
4025 }
4026
4027 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp *mlxsw_sp,
4028                                         struct mlxsw_sp_nexthop *nh)
4029 {
4030         mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4031 }
4032
4033 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
4034                                   struct mlxsw_sp_nexthop_group *nh_grp,
4035                                   struct mlxsw_sp_nexthop *nh,
4036                                   const struct rt6_info *rt)
4037 {
4038         struct net_device *dev = rt->dst.dev;
4039
4040         nh->nh_grp = nh_grp;
4041         memcpy(&nh->gw_addr, &rt->rt6i_gateway, sizeof(nh->gw_addr));
4042
4043         if (!dev)
4044                 return 0;
4045         nh->ifindex = dev->ifindex;
4046
4047         return mlxsw_sp_nexthop6_type_init(mlxsw_sp, nh_grp, nh, rt);
4048 }
4049
4050 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
4051                                    struct mlxsw_sp_nexthop *nh)
4052 {
4053         mlxsw_sp_nexthop6_type_fini(mlxsw_sp, nh);
4054 }
4055
4056 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
4057                                     const struct rt6_info *rt)
4058 {
4059         return rt->rt6i_flags & RTF_GATEWAY ||
4060                mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
4061 }
4062
4063 static struct mlxsw_sp_nexthop_group *
4064 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
4065                                struct mlxsw_sp_fib6_entry *fib6_entry)
4066 {
4067         struct mlxsw_sp_nexthop_group *nh_grp;
4068         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4069         struct mlxsw_sp_nexthop *nh;
4070         size_t alloc_size;
4071         int i = 0;
4072         int err;
4073
4074         alloc_size = sizeof(*nh_grp) +
4075                      fib6_entry->nrt6 * sizeof(struct mlxsw_sp_nexthop);
4076         nh_grp = kzalloc(alloc_size, GFP_KERNEL);
4077         if (!nh_grp)
4078                 return ERR_PTR(-ENOMEM);
4079         INIT_LIST_HEAD(&nh_grp->fib_list);
4080 #if IS_ENABLED(CONFIG_IPV6)
4081         nh_grp->neigh_tbl = &nd_tbl;
4082 #endif
4083         mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
4084                                         struct mlxsw_sp_rt6, list);
4085         nh_grp->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
4086         nh_grp->count = fib6_entry->nrt6;
4087         for (i = 0; i < nh_grp->count; i++) {
4088                 struct rt6_info *rt = mlxsw_sp_rt6->rt;
4089
4090                 nh = &nh_grp->nexthops[i];
4091                 err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt);
4092                 if (err)
4093                         goto err_nexthop6_init;
4094                 mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list);
4095         }
4096
4097         err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
4098         if (err)
4099                 goto err_nexthop_group_insert;
4100
4101         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4102         return nh_grp;
4103
4104 err_nexthop_group_insert:
4105 err_nexthop6_init:
4106         for (i--; i >= 0; i--) {
4107                 nh = &nh_grp->nexthops[i];
4108                 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
4109         }
4110         kfree(nh_grp);
4111         return ERR_PTR(err);
4112 }
4113
4114 static void
4115 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp,
4116                                 struct mlxsw_sp_nexthop_group *nh_grp)
4117 {
4118         struct mlxsw_sp_nexthop *nh;
4119         int i = nh_grp->count;
4120
4121         mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
4122         for (i--; i >= 0; i--) {
4123                 nh = &nh_grp->nexthops[i];
4124                 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
4125         }
4126         mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4127         WARN_ON(nh_grp->adj_index_valid);
4128         kfree(nh_grp);
4129 }
4130
4131 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp,
4132                                        struct mlxsw_sp_fib6_entry *fib6_entry)
4133 {
4134         struct mlxsw_sp_nexthop_group *nh_grp;
4135
4136         nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry);
4137         if (!nh_grp) {
4138                 nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry);
4139                 if (IS_ERR(nh_grp))
4140                         return PTR_ERR(nh_grp);
4141         }
4142
4143         list_add_tail(&fib6_entry->common.nexthop_group_node,
4144                       &nh_grp->fib_list);
4145         fib6_entry->common.nh_group = nh_grp;
4146
4147         return 0;
4148 }
4149
4150 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp,
4151                                         struct mlxsw_sp_fib_entry *fib_entry)
4152 {
4153         struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
4154
4155         list_del(&fib_entry->nexthop_group_node);
4156         if (!list_empty(&nh_grp->fib_list))
4157                 return;
4158         mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp);
4159 }
4160
4161 static int
4162 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
4163                                struct mlxsw_sp_fib6_entry *fib6_entry)
4164 {
4165         struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group;
4166         int err;
4167
4168         fib6_entry->common.nh_group = NULL;
4169         list_del(&fib6_entry->common.nexthop_group_node);
4170
4171         err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
4172         if (err)
4173                 goto err_nexthop6_group_get;
4174
4175         /* In case this entry is offloaded, then the adjacency index
4176          * currently associated with it in the device's table is that
4177          * of the old group. Start using the new one instead.
4178          */
4179         err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
4180         if (err)
4181                 goto err_fib_node_entry_add;
4182
4183         if (list_empty(&old_nh_grp->fib_list))
4184                 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
4185
4186         return 0;
4187
4188 err_fib_node_entry_add:
4189         mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
4190 err_nexthop6_group_get:
4191         list_add_tail(&fib6_entry->common.nexthop_group_node,
4192                       &old_nh_grp->fib_list);
4193         fib6_entry->common.nh_group = old_nh_grp;
4194         return err;
4195 }
4196
4197 static int
4198 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
4199                                 struct mlxsw_sp_fib6_entry *fib6_entry,
4200                                 struct rt6_info *rt)
4201 {
4202         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4203         int err;
4204
4205         mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
4206         if (IS_ERR(mlxsw_sp_rt6))
4207                 return PTR_ERR(mlxsw_sp_rt6);
4208
4209         list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
4210         fib6_entry->nrt6++;
4211
4212         err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
4213         if (err)
4214                 goto err_nexthop6_group_update;
4215
4216         return 0;
4217
4218 err_nexthop6_group_update:
4219         fib6_entry->nrt6--;
4220         list_del(&mlxsw_sp_rt6->list);
4221         mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4222         return err;
4223 }
4224
4225 static void
4226 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
4227                                 struct mlxsw_sp_fib6_entry *fib6_entry,
4228                                 struct rt6_info *rt)
4229 {
4230         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4231
4232         mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt);
4233         if (WARN_ON(!mlxsw_sp_rt6))
4234                 return;
4235
4236         fib6_entry->nrt6--;
4237         list_del(&mlxsw_sp_rt6->list);
4238         mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
4239         mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4240 }
4241
4242 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
4243                                          struct mlxsw_sp_fib_entry *fib_entry,
4244                                          const struct rt6_info *rt)
4245 {
4246         /* Packets hitting RTF_REJECT routes need to be discarded by the
4247          * stack. We can rely on their destination device not having a
4248          * RIF (it's the loopback device) and can thus use action type
4249          * local, which will cause them to be trapped with a lower
4250          * priority than packets that need to be locally received.
4251          */
4252         if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
4253                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
4254         else if (rt->rt6i_flags & RTF_REJECT)
4255                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4256         else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
4257                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
4258         else
4259                 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4260 }
4261
4262 static void
4263 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
4264 {
4265         struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp;
4266
4267         list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list,
4268                                  list) {
4269                 fib6_entry->nrt6--;
4270                 list_del(&mlxsw_sp_rt6->list);
4271                 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4272         }
4273 }
4274
4275 static struct mlxsw_sp_fib6_entry *
4276 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
4277                            struct mlxsw_sp_fib_node *fib_node,
4278                            struct rt6_info *rt)
4279 {
4280         struct mlxsw_sp_fib6_entry *fib6_entry;
4281         struct mlxsw_sp_fib_entry *fib_entry;
4282         struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4283         int err;
4284
4285         fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
4286         if (!fib6_entry)
4287                 return ERR_PTR(-ENOMEM);
4288         fib_entry = &fib6_entry->common;
4289
4290         mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
4291         if (IS_ERR(mlxsw_sp_rt6)) {
4292                 err = PTR_ERR(mlxsw_sp_rt6);
4293                 goto err_rt6_create;
4294         }
4295
4296         mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, mlxsw_sp_rt6->rt);
4297
4298         INIT_LIST_HEAD(&fib6_entry->rt6_list);
4299         list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
4300         fib6_entry->nrt6 = 1;
4301         err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
4302         if (err)
4303                 goto err_nexthop6_group_get;
4304
4305         fib_entry->fib_node = fib_node;
4306
4307         return fib6_entry;
4308
4309 err_nexthop6_group_get:
4310         list_del(&mlxsw_sp_rt6->list);
4311         mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4312 err_rt6_create:
4313         kfree(fib6_entry);
4314         return ERR_PTR(err);
4315 }
4316
4317 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
4318                                         struct mlxsw_sp_fib6_entry *fib6_entry)
4319 {
4320         mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
4321         mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry);
4322         WARN_ON(fib6_entry->nrt6);
4323         kfree(fib6_entry);
4324 }
4325
4326 static struct mlxsw_sp_fib6_entry *
4327 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
4328                               const struct rt6_info *nrt, bool replace)
4329 {
4330         struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
4331
4332         list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
4333                 struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
4334
4335                 if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
4336                         continue;
4337                 if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
4338                         break;
4339                 if (replace && rt->rt6i_metric == nrt->rt6i_metric) {
4340                         if (mlxsw_sp_fib6_rt_can_mp(rt) ==
4341                             mlxsw_sp_fib6_rt_can_mp(nrt))
4342                                 return fib6_entry;
4343                         if (mlxsw_sp_fib6_rt_can_mp(nrt))
4344                                 fallback = fallback ?: fib6_entry;
4345                 }
4346                 if (rt->rt6i_metric > nrt->rt6i_metric)
4347                         return fallback ?: fib6_entry;
4348         }
4349
4350         return fallback;
4351 }
4352
4353 static int
4354 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
4355                                bool replace)
4356 {
4357         struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node;
4358         struct rt6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry);
4359         struct mlxsw_sp_fib6_entry *fib6_entry;
4360
4361         fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, replace);
4362
4363         if (replace && WARN_ON(!fib6_entry))
4364                 return -EINVAL;
4365
4366         if (fib6_entry) {
4367                 list_add_tail(&new6_entry->common.list,
4368                               &fib6_entry->common.list);
4369         } else {
4370                 struct mlxsw_sp_fib6_entry *last;
4371
4372                 list_for_each_entry(last, &fib_node->entry_list, common.list) {
4373                         struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(last);
4374
4375                         if (nrt->rt6i_table->tb6_id > rt->rt6i_table->tb6_id)
4376                                 break;
4377                         fib6_entry = last;
4378                 }
4379
4380                 if (fib6_entry)
4381                         list_add(&new6_entry->common.list,
4382                                  &fib6_entry->common.list);
4383                 else
4384                         list_add(&new6_entry->common.list,
4385                                  &fib_node->entry_list);
4386         }
4387
4388         return 0;
4389 }
4390
4391 static void
4392 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry)
4393 {
4394         list_del(&fib6_entry->common.list);
4395 }
4396
4397 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
4398                                          struct mlxsw_sp_fib6_entry *fib6_entry,
4399                                          bool replace)
4400 {
4401         int err;
4402
4403         err = mlxsw_sp_fib6_node_list_insert(fib6_entry, replace);
4404         if (err)
4405                 return err;
4406
4407         err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
4408         if (err)
4409                 goto err_fib_node_entry_add;
4410
4411         return 0;
4412
4413 err_fib_node_entry_add:
4414         mlxsw_sp_fib6_node_list_remove(fib6_entry);
4415         return err;
4416 }
4417
4418 static void
4419 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
4420                                 struct mlxsw_sp_fib6_entry *fib6_entry)
4421 {
4422         mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common);
4423         mlxsw_sp_fib6_node_list_remove(fib6_entry);
4424 }
4425
4426 static struct mlxsw_sp_fib6_entry *
4427 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
4428                            const struct rt6_info *rt)
4429 {
4430         struct mlxsw_sp_fib6_entry *fib6_entry;
4431         struct mlxsw_sp_fib_node *fib_node;
4432         struct mlxsw_sp_fib *fib;
4433         struct mlxsw_sp_vr *vr;
4434
4435         vr = mlxsw_sp_vr_find(mlxsw_sp, rt->rt6i_table->tb6_id);
4436         if (!vr)
4437                 return NULL;
4438         fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
4439
4440         fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->rt6i_dst.addr,
4441                                             sizeof(rt->rt6i_dst.addr),
4442                                             rt->rt6i_dst.plen);
4443         if (!fib_node)
4444                 return NULL;
4445
4446         list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
4447                 struct rt6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
4448
4449                 if (rt->rt6i_table->tb6_id == iter_rt->rt6i_table->tb6_id &&
4450                     rt->rt6i_metric == iter_rt->rt6i_metric &&
4451                     mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
4452                         return fib6_entry;
4453         }
4454
4455         return NULL;
4456 }
4457
4458 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
4459                                         struct mlxsw_sp_fib6_entry *fib6_entry,
4460                                         bool replace)
4461 {
4462         struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
4463         struct mlxsw_sp_fib6_entry *replaced;
4464
4465         if (!replace)
4466                 return;
4467
4468         replaced = list_next_entry(fib6_entry, common.list);
4469
4470         mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, replaced);
4471         mlxsw_sp_fib6_entry_destroy(mlxsw_sp, replaced);
4472         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4473 }
4474
4475 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
4476                                     struct rt6_info *rt, bool replace)
4477 {
4478         struct mlxsw_sp_fib6_entry *fib6_entry;
4479         struct mlxsw_sp_fib_node *fib_node;
4480         int err;
4481
4482         if (mlxsw_sp->router->aborted)
4483                 return 0;
4484
4485         if (rt->rt6i_src.plen)
4486                 return -EINVAL;
4487
4488         if (mlxsw_sp_fib6_rt_should_ignore(rt))
4489                 return 0;
4490
4491         fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->rt6i_table->tb6_id,
4492                                          &rt->rt6i_dst.addr,
4493                                          sizeof(rt->rt6i_dst.addr),
4494                                          rt->rt6i_dst.plen,
4495                                          MLXSW_SP_L3_PROTO_IPV6);
4496         if (IS_ERR(fib_node))
4497                 return PTR_ERR(fib_node);
4498
4499         /* Before creating a new entry, try to append route to an existing
4500          * multipath entry.
4501          */
4502         fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
4503         if (fib6_entry) {
4504                 err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
4505                 if (err)
4506                         goto err_fib6_entry_nexthop_add;
4507                 return 0;
4508         }
4509
4510         fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
4511         if (IS_ERR(fib6_entry)) {
4512                 err = PTR_ERR(fib6_entry);
4513                 goto err_fib6_entry_create;
4514         }
4515
4516         err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, replace);
4517         if (err)
4518                 goto err_fib6_node_entry_link;
4519
4520         mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry, replace);
4521
4522         return 0;
4523
4524 err_fib6_node_entry_link:
4525         mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4526 err_fib6_entry_create:
4527 err_fib6_entry_nexthop_add:
4528         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4529         return err;
4530 }
4531
4532 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
4533                                      struct rt6_info *rt)
4534 {
4535         struct mlxsw_sp_fib6_entry *fib6_entry;
4536         struct mlxsw_sp_fib_node *fib_node;
4537
4538         if (mlxsw_sp->router->aborted)
4539                 return;
4540
4541         if (mlxsw_sp_fib6_rt_should_ignore(rt))
4542                 return;
4543
4544         fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
4545         if (WARN_ON(!fib6_entry))
4546                 return;
4547
4548         /* If route is part of a multipath entry, but not the last one
4549          * removed, then only reduce its nexthop group.
4550          */
4551         if (!list_is_singular(&fib6_entry->rt6_list)) {
4552                 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt);
4553                 return;
4554         }
4555
4556         fib_node = fib6_entry->common.fib_node;
4557
4558         mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
4559         mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4560         mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4561 }
4562
4563 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp,
4564                                             enum mlxsw_reg_ralxx_protocol proto,
4565                                             u8 tree_id)
4566 {
4567         char ralta_pl[MLXSW_REG_RALTA_LEN];
4568         char ralst_pl[MLXSW_REG_RALST_LEN];
4569         int i, err;
4570
4571         mlxsw_reg_ralta_pack(ralta_pl, true, proto, tree_id);
4572         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
4573         if (err)
4574                 return err;
4575
4576         mlxsw_reg_ralst_pack(ralst_pl, 0xff, tree_id);
4577         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
4578         if (err)
4579                 return err;
4580
4581         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
4582                 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
4583                 char raltb_pl[MLXSW_REG_RALTB_LEN];
4584                 char ralue_pl[MLXSW_REG_RALUE_LEN];
4585
4586                 mlxsw_reg_raltb_pack(raltb_pl, vr->id, proto, tree_id);
4587                 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb),
4588                                       raltb_pl);
4589                 if (err)
4590                         return err;
4591
4592                 mlxsw_reg_ralue_pack(ralue_pl, proto,
4593                                      MLXSW_REG_RALUE_OP_WRITE_WRITE, vr->id, 0);
4594                 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
4595                 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue),
4596                                       ralue_pl);
4597                 if (err)
4598                         return err;
4599         }
4600
4601         return 0;
4602 }
4603
4604 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
4605 {
4606         enum mlxsw_reg_ralxx_protocol proto = MLXSW_REG_RALXX_PROTOCOL_IPV4;
4607         int err;
4608
4609         err = __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
4610                                                MLXSW_SP_LPM_TREE_MIN);
4611         if (err)
4612                 return err;
4613
4614         proto = MLXSW_REG_RALXX_PROTOCOL_IPV6;
4615         return __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
4616                                                 MLXSW_SP_LPM_TREE_MIN + 1);
4617 }
4618
4619 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
4620                                      struct mlxsw_sp_fib_node *fib_node)
4621 {
4622         struct mlxsw_sp_fib4_entry *fib4_entry, *tmp;
4623
4624         list_for_each_entry_safe(fib4_entry, tmp, &fib_node->entry_list,
4625                                  common.list) {
4626                 bool do_break = &tmp->common.list == &fib_node->entry_list;
4627
4628                 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
4629                 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4630                 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4631                 /* Break when entry list is empty and node was freed.
4632                  * Otherwise, we'll access freed memory in the next
4633                  * iteration.
4634                  */
4635                 if (do_break)
4636                         break;
4637         }
4638 }
4639
4640 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
4641                                      struct mlxsw_sp_fib_node *fib_node)
4642 {
4643         struct mlxsw_sp_fib6_entry *fib6_entry, *tmp;
4644
4645         list_for_each_entry_safe(fib6_entry, tmp, &fib_node->entry_list,
4646                                  common.list) {
4647                 bool do_break = &tmp->common.list == &fib_node->entry_list;
4648
4649                 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
4650                 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4651                 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4652                 if (do_break)
4653                         break;
4654         }
4655 }
4656
4657 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
4658                                     struct mlxsw_sp_fib_node *fib_node)
4659 {
4660         switch (fib_node->fib->proto) {
4661         case MLXSW_SP_L3_PROTO_IPV4:
4662                 mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
4663                 break;
4664         case MLXSW_SP_L3_PROTO_IPV6:
4665                 mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node);
4666                 break;
4667         }
4668 }
4669
4670 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
4671                                   struct mlxsw_sp_vr *vr,
4672                                   enum mlxsw_sp_l3proto proto)
4673 {
4674         struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
4675         struct mlxsw_sp_fib_node *fib_node, *tmp;
4676
4677         list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
4678                 bool do_break = &tmp->list == &fib->node_list;
4679
4680                 mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
4681                 if (do_break)
4682                         break;
4683         }
4684 }
4685
4686 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
4687 {
4688         int i;
4689
4690         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
4691                 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
4692
4693                 if (!mlxsw_sp_vr_is_used(vr))
4694                         continue;
4695                 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
4696
4697                 /* If virtual router was only used for IPv4, then it's no
4698                  * longer used.
4699                  */
4700                 if (!mlxsw_sp_vr_is_used(vr))
4701                         continue;
4702                 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
4703         }
4704 }
4705
4706 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp)
4707 {
4708         int err;
4709
4710         if (mlxsw_sp->router->aborted)
4711                 return;
4712         dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
4713         mlxsw_sp_router_fib_flush(mlxsw_sp);
4714         mlxsw_sp->router->aborted = true;
4715         err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
4716         if (err)
4717                 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
4718 }
4719
4720 struct mlxsw_sp_fib_event_work {
4721         struct work_struct work;
4722         union {
4723                 struct fib6_entry_notifier_info fen6_info;
4724                 struct fib_entry_notifier_info fen_info;
4725                 struct fib_rule_notifier_info fr_info;
4726                 struct fib_nh_notifier_info fnh_info;
4727         };
4728         struct mlxsw_sp *mlxsw_sp;
4729         unsigned long event;
4730 };
4731
4732 static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
4733 {
4734         struct mlxsw_sp_fib_event_work *fib_work =
4735                 container_of(work, struct mlxsw_sp_fib_event_work, work);
4736         struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
4737         struct fib_rule *rule;
4738         bool replace, append;
4739         int err;
4740
4741         /* Protect internal structures from changes */
4742         rtnl_lock();
4743         switch (fib_work->event) {
4744         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4745         case FIB_EVENT_ENTRY_APPEND: /* fall through */
4746         case FIB_EVENT_ENTRY_ADD:
4747                 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
4748                 append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
4749                 err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info,
4750                                                replace, append);
4751                 if (err)
4752                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4753                 fib_info_put(fib_work->fen_info.fi);
4754                 break;
4755         case FIB_EVENT_ENTRY_DEL:
4756                 mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
4757                 fib_info_put(fib_work->fen_info.fi);
4758                 break;
4759         case FIB_EVENT_RULE_ADD: /* fall through */
4760         case FIB_EVENT_RULE_DEL:
4761                 rule = fib_work->fr_info.rule;
4762                 if (!fib4_rule_default(rule) && !rule->l3mdev)
4763                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4764                 fib_rule_put(rule);
4765                 break;
4766         case FIB_EVENT_NH_ADD: /* fall through */
4767         case FIB_EVENT_NH_DEL:
4768                 mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event,
4769                                         fib_work->fnh_info.fib_nh);
4770                 fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
4771                 break;
4772         }
4773         rtnl_unlock();
4774         kfree(fib_work);
4775 }
4776
4777 static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
4778 {
4779         struct mlxsw_sp_fib_event_work *fib_work =
4780                 container_of(work, struct mlxsw_sp_fib_event_work, work);
4781         struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
4782         struct fib_rule *rule;
4783         bool replace;
4784         int err;
4785
4786         rtnl_lock();
4787         switch (fib_work->event) {
4788         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4789         case FIB_EVENT_ENTRY_ADD:
4790                 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
4791                 err = mlxsw_sp_router_fib6_add(mlxsw_sp,
4792                                                fib_work->fen6_info.rt, replace);
4793                 if (err)
4794                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4795                 mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
4796                 break;
4797         case FIB_EVENT_ENTRY_DEL:
4798                 mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt);
4799                 mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
4800                 break;
4801         case FIB_EVENT_RULE_ADD: /* fall through */
4802         case FIB_EVENT_RULE_DEL:
4803                 rule = fib_work->fr_info.rule;
4804                 if (!fib6_rule_default(rule) && !rule->l3mdev)
4805                         mlxsw_sp_router_fib_abort(mlxsw_sp);
4806                 fib_rule_put(rule);
4807                 break;
4808         }
4809         rtnl_unlock();
4810         kfree(fib_work);
4811 }
4812
4813 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
4814                                        struct fib_notifier_info *info)
4815 {
4816         switch (fib_work->event) {
4817         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4818         case FIB_EVENT_ENTRY_APPEND: /* fall through */
4819         case FIB_EVENT_ENTRY_ADD: /* fall through */
4820         case FIB_EVENT_ENTRY_DEL:
4821                 memcpy(&fib_work->fen_info, info, sizeof(fib_work->fen_info));
4822                 /* Take referece on fib_info to prevent it from being
4823                  * freed while work is queued. Release it afterwards.
4824                  */
4825                 fib_info_hold(fib_work->fen_info.fi);
4826                 break;
4827         case FIB_EVENT_RULE_ADD: /* fall through */
4828         case FIB_EVENT_RULE_DEL:
4829                 memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
4830                 fib_rule_get(fib_work->fr_info.rule);
4831                 break;
4832         case FIB_EVENT_NH_ADD: /* fall through */
4833         case FIB_EVENT_NH_DEL:
4834                 memcpy(&fib_work->fnh_info, info, sizeof(fib_work->fnh_info));
4835                 fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
4836                 break;
4837         }
4838 }
4839
4840 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
4841                                        struct fib_notifier_info *info)
4842 {
4843         switch (fib_work->event) {
4844         case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4845         case FIB_EVENT_ENTRY_ADD: /* fall through */
4846         case FIB_EVENT_ENTRY_DEL:
4847                 memcpy(&fib_work->fen6_info, info, sizeof(fib_work->fen6_info));
4848                 rt6_hold(fib_work->fen6_info.rt);
4849                 break;
4850         case FIB_EVENT_RULE_ADD: /* fall through */
4851         case FIB_EVENT_RULE_DEL:
4852                 memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
4853                 fib_rule_get(fib_work->fr_info.rule);
4854                 break;
4855         }
4856 }
4857
4858 /* Called with rcu_read_lock() */
4859 static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
4860                                      unsigned long event, void *ptr)
4861 {
4862         struct mlxsw_sp_fib_event_work *fib_work;
4863         struct fib_notifier_info *info = ptr;
4864         struct mlxsw_sp_router *router;
4865
4866         if (!net_eq(info->net, &init_net) ||
4867             (info->family != AF_INET && info->family != AF_INET6))
4868                 return NOTIFY_DONE;
4869
4870         fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
4871         if (WARN_ON(!fib_work))
4872                 return NOTIFY_BAD;
4873
4874         router = container_of(nb, struct mlxsw_sp_router, fib_nb);
4875         fib_work->mlxsw_sp = router->mlxsw_sp;
4876         fib_work->event = event;
4877
4878         switch (info->family) {
4879         case AF_INET:
4880                 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work);
4881                 mlxsw_sp_router_fib4_event(fib_work, info);
4882                 break;
4883         case AF_INET6:
4884                 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
4885                 mlxsw_sp_router_fib6_event(fib_work, info);
4886                 break;
4887         }
4888
4889         mlxsw_core_schedule_work(&fib_work->work);
4890
4891         return NOTIFY_DONE;
4892 }
4893
4894 static struct mlxsw_sp_rif *
4895 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
4896                          const struct net_device *dev)
4897 {
4898         int i;
4899
4900         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
4901                 if (mlxsw_sp->router->rifs[i] &&
4902                     mlxsw_sp->router->rifs[i]->dev == dev)
4903                         return mlxsw_sp->router->rifs[i];
4904
4905         return NULL;
4906 }
4907
4908 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
4909 {
4910         char ritr_pl[MLXSW_REG_RITR_LEN];
4911         int err;
4912
4913         mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
4914         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
4915         if (WARN_ON_ONCE(err))
4916                 return err;
4917
4918         mlxsw_reg_ritr_enable_set(ritr_pl, false);
4919         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
4920 }
4921
4922 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
4923                                           struct mlxsw_sp_rif *rif)
4924 {
4925         mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
4926         mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
4927         mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
4928 }
4929
4930 static bool
4931 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
4932                            unsigned long event)
4933 {
4934         struct inet6_dev *inet6_dev;
4935         bool addr_list_empty = true;
4936         struct in_device *idev;
4937
4938         switch (event) {
4939         case NETDEV_UP:
4940                 return rif == NULL;
4941         case NETDEV_DOWN:
4942                 idev = __in_dev_get_rtnl(dev);
4943                 if (idev && idev->ifa_list)
4944                         addr_list_empty = false;
4945
4946                 inet6_dev = __in6_dev_get(dev);
4947                 if (addr_list_empty && inet6_dev &&
4948                     !list_empty(&inet6_dev->addr_list))
4949                         addr_list_empty = false;
4950
4951                 if (rif && addr_list_empty &&
4952                     !netif_is_l3_slave(rif->dev))
4953                         return true;
4954                 /* It is possible we already removed the RIF ourselves
4955                  * if it was assigned to a netdev that is now a bridge
4956                  * or LAG slave.
4957                  */
4958                 return false;
4959         }
4960
4961         return false;
4962 }
4963
4964 static enum mlxsw_sp_rif_type
4965 mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
4966                       const struct net_device *dev)
4967 {
4968         enum mlxsw_sp_fid_type type;
4969
4970         if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
4971                 return MLXSW_SP_RIF_TYPE_IPIP_LB;
4972
4973         /* Otherwise RIF type is derived from the type of the underlying FID. */
4974         if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
4975                 type = MLXSW_SP_FID_TYPE_8021Q;
4976         else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
4977                 type = MLXSW_SP_FID_TYPE_8021Q;
4978         else if (netif_is_bridge_master(dev))
4979                 type = MLXSW_SP_FID_TYPE_8021D;
4980         else
4981                 type = MLXSW_SP_FID_TYPE_RFID;
4982
4983         return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
4984 }
4985
4986 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index)
4987 {
4988         int i;
4989
4990         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
4991                 if (!mlxsw_sp->router->rifs[i]) {
4992                         *p_rif_index = i;
4993                         return 0;
4994                 }
4995         }
4996
4997         return -ENOBUFS;
4998 }
4999
5000 static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
5001                                                u16 vr_id,
5002                                                struct net_device *l3_dev)
5003 {
5004         struct mlxsw_sp_rif *rif;
5005
5006         rif = kzalloc(rif_size, GFP_KERNEL);
5007         if (!rif)
5008                 return NULL;
5009
5010         INIT_LIST_HEAD(&rif->nexthop_list);
5011         INIT_LIST_HEAD(&rif->neigh_list);
5012         ether_addr_copy(rif->addr, l3_dev->dev_addr);
5013         rif->mtu = l3_dev->mtu;
5014         rif->vr_id = vr_id;
5015         rif->dev = l3_dev;
5016         rif->rif_index = rif_index;
5017
5018         return rif;
5019 }
5020
5021 struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
5022                                            u16 rif_index)
5023 {
5024         return mlxsw_sp->router->rifs[rif_index];
5025 }
5026
5027 u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
5028 {
5029         return rif->rif_index;
5030 }
5031
5032 u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
5033 {
5034         return lb_rif->common.rif_index;
5035 }
5036
5037 u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
5038 {
5039         return lb_rif->ul_vr_id;
5040 }
5041
5042 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
5043 {
5044         return rif->dev->ifindex;
5045 }
5046
5047 static struct mlxsw_sp_rif *
5048 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
5049                     const struct mlxsw_sp_rif_params *params)
5050 {
5051         u32 tb_id = l3mdev_fib_table(params->dev);
5052         const struct mlxsw_sp_rif_ops *ops;
5053         struct mlxsw_sp_fid *fid = NULL;
5054         enum mlxsw_sp_rif_type type;
5055         struct mlxsw_sp_rif *rif;
5056         struct mlxsw_sp_vr *vr;
5057         u16 rif_index;
5058         int err;
5059
5060         type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
5061         ops = mlxsw_sp->router->rif_ops_arr[type];
5062
5063         vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
5064         if (IS_ERR(vr))
5065                 return ERR_CAST(vr);
5066         vr->rif_count++;
5067
5068         err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
5069         if (err)
5070                 goto err_rif_index_alloc;
5071
5072         rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
5073         if (!rif) {
5074                 err = -ENOMEM;
5075                 goto err_rif_alloc;
5076         }
5077         rif->mlxsw_sp = mlxsw_sp;
5078         rif->ops = ops;
5079
5080         if (ops->fid_get) {
5081                 fid = ops->fid_get(rif);
5082                 if (IS_ERR(fid)) {
5083                         err = PTR_ERR(fid);
5084                         goto err_fid_get;
5085                 }
5086                 rif->fid = fid;
5087         }
5088
5089         if (ops->setup)
5090                 ops->setup(rif, params);
5091
5092         err = ops->configure(rif);
5093         if (err)
5094                 goto err_configure;
5095
5096         mlxsw_sp_rif_counters_alloc(rif);
5097         mlxsw_sp->router->rifs[rif_index] = rif;
5098
5099         return rif;
5100
5101 err_configure:
5102         if (fid)
5103                 mlxsw_sp_fid_put(fid);
5104 err_fid_get:
5105         kfree(rif);
5106 err_rif_alloc:
5107 err_rif_index_alloc:
5108         vr->rif_count--;
5109         mlxsw_sp_vr_put(vr);
5110         return ERR_PTR(err);
5111 }
5112
5113 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
5114 {
5115         const struct mlxsw_sp_rif_ops *ops = rif->ops;
5116         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5117         struct mlxsw_sp_fid *fid = rif->fid;
5118         struct mlxsw_sp_vr *vr;
5119
5120         mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
5121         vr = &mlxsw_sp->router->vrs[rif->vr_id];
5122
5123         mlxsw_sp->router->rifs[rif->rif_index] = NULL;
5124         mlxsw_sp_rif_counters_free(rif);
5125         ops->deconfigure(rif);
5126         if (fid)
5127                 /* Loopback RIFs are not associated with a FID. */
5128                 mlxsw_sp_fid_put(fid);
5129         kfree(rif);
5130         vr->rif_count--;
5131         mlxsw_sp_vr_put(vr);
5132 }
5133
5134 static void
5135 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
5136                                  struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
5137 {
5138         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5139
5140         params->vid = mlxsw_sp_port_vlan->vid;
5141         params->lag = mlxsw_sp_port->lagged;
5142         if (params->lag)
5143                 params->lag_id = mlxsw_sp_port->lag_id;
5144         else
5145                 params->system_port = mlxsw_sp_port->local_port;
5146 }
5147
5148 static int
5149 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
5150                                struct net_device *l3_dev)
5151 {
5152         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5153         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5154         u16 vid = mlxsw_sp_port_vlan->vid;
5155         struct mlxsw_sp_rif *rif;
5156         struct mlxsw_sp_fid *fid;
5157         int err;
5158
5159         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5160         if (!rif) {
5161                 struct mlxsw_sp_rif_params params = {
5162                         .dev = l3_dev,
5163                 };
5164
5165                 mlxsw_sp_rif_subport_params_init(&params, mlxsw_sp_port_vlan);
5166                 rif = mlxsw_sp_rif_create(mlxsw_sp, &params);
5167                 if (IS_ERR(rif))
5168                         return PTR_ERR(rif);
5169         }
5170
5171         /* FID was already created, just take a reference */
5172         fid = rif->ops->fid_get(rif);
5173         err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid);
5174         if (err)
5175                 goto err_fid_port_vid_map;
5176
5177         err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
5178         if (err)
5179                 goto err_port_vid_learning_set;
5180
5181         err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid,
5182                                         BR_STATE_FORWARDING);
5183         if (err)
5184                 goto err_port_vid_stp_set;
5185
5186         mlxsw_sp_port_vlan->fid = fid;
5187
5188         return 0;
5189
5190 err_port_vid_stp_set:
5191         mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
5192 err_port_vid_learning_set:
5193         mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
5194 err_fid_port_vid_map:
5195         mlxsw_sp_fid_put(fid);
5196         return err;
5197 }
5198
5199 void
5200 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
5201 {
5202         struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5203         struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
5204         u16 vid = mlxsw_sp_port_vlan->vid;
5205
5206         if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID))
5207                 return;
5208
5209         mlxsw_sp_port_vlan->fid = NULL;
5210         mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING);
5211         mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
5212         mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
5213         /* If router port holds the last reference on the rFID, then the
5214          * associated Sub-port RIF will be destroyed.
5215          */
5216         mlxsw_sp_fid_put(fid);
5217 }
5218
5219 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
5220                                              struct net_device *port_dev,
5221                                              unsigned long event, u16 vid)
5222 {
5223         struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
5224         struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
5225
5226         mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
5227         if (WARN_ON(!mlxsw_sp_port_vlan))
5228                 return -EINVAL;
5229
5230         switch (event) {
5231         case NETDEV_UP:
5232                 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
5233                                                       l3_dev);
5234         case NETDEV_DOWN:
5235                 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
5236                 break;
5237         }
5238
5239         return 0;
5240 }
5241
5242 static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
5243                                         unsigned long event)
5244 {
5245         if (netif_is_bridge_port(port_dev) ||
5246             netif_is_lag_port(port_dev) ||
5247             netif_is_ovs_port(port_dev))
5248                 return 0;
5249
5250         return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1);
5251 }
5252
5253 static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
5254                                          struct net_device *lag_dev,
5255                                          unsigned long event, u16 vid)
5256 {
5257         struct net_device *port_dev;
5258         struct list_head *iter;
5259         int err;
5260
5261         netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
5262                 if (mlxsw_sp_port_dev_check(port_dev)) {
5263                         err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
5264                                                                 port_dev,
5265                                                                 event, vid);
5266                         if (err)
5267                                 return err;
5268                 }
5269         }
5270
5271         return 0;
5272 }
5273
5274 static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
5275                                        unsigned long event)
5276 {
5277         if (netif_is_bridge_port(lag_dev))
5278                 return 0;
5279
5280         return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1);
5281 }
5282
5283 static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
5284                                           unsigned long event)
5285 {
5286         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
5287         struct mlxsw_sp_rif_params params = {
5288                 .dev = l3_dev,
5289         };
5290         struct mlxsw_sp_rif *rif;
5291
5292         switch (event) {
5293         case NETDEV_UP:
5294                 rif = mlxsw_sp_rif_create(mlxsw_sp, &params);
5295                 if (IS_ERR(rif))
5296                         return PTR_ERR(rif);
5297                 break;
5298         case NETDEV_DOWN:
5299                 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5300                 mlxsw_sp_rif_destroy(rif);
5301                 break;
5302         }
5303
5304         return 0;
5305 }
5306
5307 static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
5308                                         unsigned long event)
5309 {
5310         struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
5311         u16 vid = vlan_dev_vlan_id(vlan_dev);
5312
5313         if (netif_is_bridge_port(vlan_dev))
5314                 return 0;
5315
5316         if (mlxsw_sp_port_dev_check(real_dev))
5317                 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
5318                                                          event, vid);
5319         else if (netif_is_lag_master(real_dev))
5320                 return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
5321                                                      vid);
5322         else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev))
5323                 return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event);
5324
5325         return 0;
5326 }
5327
5328 static int __mlxsw_sp_inetaddr_event(struct net_device *dev,
5329                                      unsigned long event)
5330 {
5331         if (mlxsw_sp_port_dev_check(dev))
5332                 return mlxsw_sp_inetaddr_port_event(dev, event);
5333         else if (netif_is_lag_master(dev))
5334                 return mlxsw_sp_inetaddr_lag_event(dev, event);
5335         else if (netif_is_bridge_master(dev))
5336                 return mlxsw_sp_inetaddr_bridge_event(dev, event);
5337         else if (is_vlan_dev(dev))
5338                 return mlxsw_sp_inetaddr_vlan_event(dev, event);
5339         else
5340                 return 0;
5341 }
5342
5343 int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
5344                             unsigned long event, void *ptr)
5345 {
5346         struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
5347         struct net_device *dev = ifa->ifa_dev->dev;
5348         struct mlxsw_sp *mlxsw_sp;
5349         struct mlxsw_sp_rif *rif;
5350         int err = 0;
5351
5352         mlxsw_sp = mlxsw_sp_lower_get(dev);
5353         if (!mlxsw_sp)
5354                 goto out;
5355
5356         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5357         if (!mlxsw_sp_rif_should_config(rif, dev, event))
5358                 goto out;
5359
5360         err = __mlxsw_sp_inetaddr_event(dev, event);
5361 out:
5362         return notifier_from_errno(err);
5363 }
5364
5365 struct mlxsw_sp_inet6addr_event_work {
5366         struct work_struct work;
5367         struct net_device *dev;
5368         unsigned long event;
5369 };
5370
5371 static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
5372 {
5373         struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
5374                 container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
5375         struct net_device *dev = inet6addr_work->dev;
5376         unsigned long event = inet6addr_work->event;
5377         struct mlxsw_sp *mlxsw_sp;
5378         struct mlxsw_sp_rif *rif;
5379
5380         rtnl_lock();
5381         mlxsw_sp = mlxsw_sp_lower_get(dev);
5382         if (!mlxsw_sp)
5383                 goto out;
5384
5385         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5386         if (!mlxsw_sp_rif_should_config(rif, dev, event))
5387                 goto out;
5388
5389         __mlxsw_sp_inetaddr_event(dev, event);
5390 out:
5391         rtnl_unlock();
5392         dev_put(dev);
5393         kfree(inet6addr_work);
5394 }
5395
5396 /* Called with rcu_read_lock() */
5397 int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
5398                              unsigned long event, void *ptr)
5399 {
5400         struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
5401         struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
5402         struct net_device *dev = if6->idev->dev;
5403
5404         if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
5405                 return NOTIFY_DONE;
5406
5407         inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
5408         if (!inet6addr_work)
5409                 return NOTIFY_BAD;
5410
5411         INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
5412         inet6addr_work->dev = dev;
5413         inet6addr_work->event = event;
5414         dev_hold(dev);
5415         mlxsw_core_schedule_work(&inet6addr_work->work);
5416
5417         return NOTIFY_DONE;
5418 }
5419
5420 static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
5421                              const char *mac, int mtu)
5422 {
5423         char ritr_pl[MLXSW_REG_RITR_LEN];
5424         int err;
5425
5426         mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
5427         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5428         if (err)
5429                 return err;
5430
5431         mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
5432         mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
5433         mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
5434         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5435 }
5436
5437 int mlxsw_sp_netdevice_router_port_event(struct net_device *dev)
5438 {
5439         struct mlxsw_sp *mlxsw_sp;
5440         struct mlxsw_sp_rif *rif;
5441         u16 fid_index;
5442         int err;
5443
5444         mlxsw_sp = mlxsw_sp_lower_get(dev);
5445         if (!mlxsw_sp)
5446                 return 0;
5447
5448         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5449         if (!rif)
5450                 return 0;
5451         fid_index = mlxsw_sp_fid_index(rif->fid);
5452
5453         err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false);
5454         if (err)
5455                 return err;
5456
5457         err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
5458                                 dev->mtu);
5459         if (err)
5460                 goto err_rif_edit;
5461
5462         err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true);
5463         if (err)
5464                 goto err_rif_fdb_op;
5465
5466         ether_addr_copy(rif->addr, dev->dev_addr);
5467         rif->mtu = dev->mtu;
5468
5469         netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
5470
5471         return 0;
5472
5473 err_rif_fdb_op:
5474         mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu);
5475 err_rif_edit:
5476         mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true);
5477         return err;
5478 }
5479
5480 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
5481                                   struct net_device *l3_dev)
5482 {
5483         struct mlxsw_sp_rif *rif;
5484
5485         /* If netdev is already associated with a RIF, then we need to
5486          * destroy it and create a new one with the new virtual router ID.
5487          */
5488         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5489         if (rif)
5490                 __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
5491
5492         return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP);
5493 }
5494
5495 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
5496                                     struct net_device *l3_dev)
5497 {
5498         struct mlxsw_sp_rif *rif;
5499
5500         rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5501         if (!rif)
5502                 return;
5503         __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
5504 }
5505
5506 int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
5507                                  struct netdev_notifier_changeupper_info *info)
5508 {
5509         struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
5510         int err = 0;
5511
5512         if (!mlxsw_sp)
5513                 return 0;
5514
5515         switch (event) {
5516         case NETDEV_PRECHANGEUPPER:
5517                 return 0;
5518         case NETDEV_CHANGEUPPER:
5519                 if (info->linking)
5520                         err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev);
5521                 else
5522                         mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
5523                 break;
5524         }
5525
5526         return err;
5527 }
5528
5529 static struct mlxsw_sp_rif_subport *
5530 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
5531 {
5532         return container_of(rif, struct mlxsw_sp_rif_subport, common);
5533 }
5534
5535 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
5536                                        const struct mlxsw_sp_rif_params *params)
5537 {
5538         struct mlxsw_sp_rif_subport *rif_subport;
5539
5540         rif_subport = mlxsw_sp_rif_subport_rif(rif);
5541         rif_subport->vid = params->vid;
5542         rif_subport->lag = params->lag;
5543         if (params->lag)
5544                 rif_subport->lag_id = params->lag_id;
5545         else
5546                 rif_subport->system_port = params->system_port;
5547 }
5548
5549 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
5550 {
5551         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5552         struct mlxsw_sp_rif_subport *rif_subport;
5553         char ritr_pl[MLXSW_REG_RITR_LEN];
5554
5555         rif_subport = mlxsw_sp_rif_subport_rif(rif);
5556         mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
5557                             rif->rif_index, rif->vr_id, rif->dev->mtu);
5558         mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
5559         mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
5560                                   rif_subport->lag ? rif_subport->lag_id :
5561                                                      rif_subport->system_port,
5562                                   rif_subport->vid);
5563
5564         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5565 }
5566
5567 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif)
5568 {
5569         int err;
5570
5571         err = mlxsw_sp_rif_subport_op(rif, true);
5572         if (err)
5573                 return err;
5574
5575         err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5576                                   mlxsw_sp_fid_index(rif->fid), true);
5577         if (err)
5578                 goto err_rif_fdb_op;
5579
5580         mlxsw_sp_fid_rif_set(rif->fid, rif);
5581         return 0;
5582
5583 err_rif_fdb_op:
5584         mlxsw_sp_rif_subport_op(rif, false);
5585         return err;
5586 }
5587
5588 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
5589 {
5590         struct mlxsw_sp_fid *fid = rif->fid;
5591
5592         mlxsw_sp_fid_rif_set(fid, NULL);
5593         mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5594                             mlxsw_sp_fid_index(fid), false);
5595         mlxsw_sp_rif_subport_op(rif, false);
5596 }
5597
5598 static struct mlxsw_sp_fid *
5599 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif)
5600 {
5601         return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index);
5602 }
5603
5604 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
5605         .type                   = MLXSW_SP_RIF_TYPE_SUBPORT,
5606         .rif_size               = sizeof(struct mlxsw_sp_rif_subport),
5607         .setup                  = mlxsw_sp_rif_subport_setup,
5608         .configure              = mlxsw_sp_rif_subport_configure,
5609         .deconfigure            = mlxsw_sp_rif_subport_deconfigure,
5610         .fid_get                = mlxsw_sp_rif_subport_fid_get,
5611 };
5612
5613 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif,
5614                                     enum mlxsw_reg_ritr_if_type type,
5615                                     u16 vid_fid, bool enable)
5616 {
5617         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5618         char ritr_pl[MLXSW_REG_RITR_LEN];
5619
5620         mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
5621                             rif->dev->mtu);
5622         mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
5623         mlxsw_reg_ritr_fid_set(ritr_pl, type, vid_fid);
5624
5625         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5626 }
5627
5628 static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
5629 {
5630         return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
5631 }
5632
5633 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif)
5634 {
5635         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5636         u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
5637         int err;
5638
5639         err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, true);
5640         if (err)
5641                 return err;
5642
5643         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5644                                      mlxsw_sp_router_port(mlxsw_sp), true);
5645         if (err)
5646                 goto err_fid_mc_flood_set;
5647
5648         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5649                                      mlxsw_sp_router_port(mlxsw_sp), true);
5650         if (err)
5651                 goto err_fid_bc_flood_set;
5652
5653         err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5654                                   mlxsw_sp_fid_index(rif->fid), true);
5655         if (err)
5656                 goto err_rif_fdb_op;
5657
5658         mlxsw_sp_fid_rif_set(rif->fid, rif);
5659         return 0;
5660
5661 err_rif_fdb_op:
5662         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5663                                mlxsw_sp_router_port(mlxsw_sp), false);
5664 err_fid_bc_flood_set:
5665         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5666                                mlxsw_sp_router_port(mlxsw_sp), false);
5667 err_fid_mc_flood_set:
5668         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false);
5669         return err;
5670 }
5671
5672 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
5673 {
5674         u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
5675         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5676         struct mlxsw_sp_fid *fid = rif->fid;
5677
5678         mlxsw_sp_fid_rif_set(fid, NULL);
5679         mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5680                             mlxsw_sp_fid_index(fid), false);
5681         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5682                                mlxsw_sp_router_port(mlxsw_sp), false);
5683         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5684                                mlxsw_sp_router_port(mlxsw_sp), false);
5685         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false);
5686 }
5687
5688 static struct mlxsw_sp_fid *
5689 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif)
5690 {
5691         u16 vid = is_vlan_dev(rif->dev) ? vlan_dev_vlan_id(rif->dev) : 1;
5692
5693         return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid);
5694 }
5695
5696 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = {
5697         .type                   = MLXSW_SP_RIF_TYPE_VLAN,
5698         .rif_size               = sizeof(struct mlxsw_sp_rif),
5699         .configure              = mlxsw_sp_rif_vlan_configure,
5700         .deconfigure            = mlxsw_sp_rif_vlan_deconfigure,
5701         .fid_get                = mlxsw_sp_rif_vlan_fid_get,
5702 };
5703
5704 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif)
5705 {
5706         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5707         u16 fid_index = mlxsw_sp_fid_index(rif->fid);
5708         int err;
5709
5710         err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index,
5711                                        true);
5712         if (err)
5713                 return err;
5714
5715         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5716                                      mlxsw_sp_router_port(mlxsw_sp), true);
5717         if (err)
5718                 goto err_fid_mc_flood_set;
5719
5720         err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5721                                      mlxsw_sp_router_port(mlxsw_sp), true);
5722         if (err)
5723                 goto err_fid_bc_flood_set;
5724
5725         err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5726                                   mlxsw_sp_fid_index(rif->fid), true);
5727         if (err)
5728                 goto err_rif_fdb_op;
5729
5730         mlxsw_sp_fid_rif_set(rif->fid, rif);
5731         return 0;
5732
5733 err_rif_fdb_op:
5734         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5735                                mlxsw_sp_router_port(mlxsw_sp), false);
5736 err_fid_bc_flood_set:
5737         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5738                                mlxsw_sp_router_port(mlxsw_sp), false);
5739 err_fid_mc_flood_set:
5740         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
5741         return err;
5742 }
5743
5744 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
5745 {
5746         u16 fid_index = mlxsw_sp_fid_index(rif->fid);
5747         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5748         struct mlxsw_sp_fid *fid = rif->fid;
5749
5750         mlxsw_sp_fid_rif_set(fid, NULL);
5751         mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5752                             mlxsw_sp_fid_index(fid), false);
5753         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5754                                mlxsw_sp_router_port(mlxsw_sp), false);
5755         mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5756                                mlxsw_sp_router_port(mlxsw_sp), false);
5757         mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
5758 }
5759
5760 static struct mlxsw_sp_fid *
5761 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif)
5762 {
5763         return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
5764 }
5765
5766 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
5767         .type                   = MLXSW_SP_RIF_TYPE_FID,
5768         .rif_size               = sizeof(struct mlxsw_sp_rif),
5769         .configure              = mlxsw_sp_rif_fid_configure,
5770         .deconfigure            = mlxsw_sp_rif_fid_deconfigure,
5771         .fid_get                = mlxsw_sp_rif_fid_fid_get,
5772 };
5773
5774 static struct mlxsw_sp_rif_ipip_lb *
5775 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
5776 {
5777         return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
5778 }
5779
5780 static void
5781 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
5782                            const struct mlxsw_sp_rif_params *params)
5783 {
5784         struct mlxsw_sp_rif_params_ipip_lb *params_lb;
5785         struct mlxsw_sp_rif_ipip_lb *rif_lb;
5786
5787         params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
5788                                  common);
5789         rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
5790         rif_lb->lb_config = params_lb->lb_config;
5791 }
5792
5793 static int
5794 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
5795                         struct mlxsw_sp_vr *ul_vr, bool enable)
5796 {
5797         struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
5798         struct mlxsw_sp_rif *rif = &lb_rif->common;
5799         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5800         char ritr_pl[MLXSW_REG_RITR_LEN];
5801         u32 saddr4;
5802
5803         switch (lb_cf.ul_protocol) {
5804         case MLXSW_SP_L3_PROTO_IPV4:
5805                 saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
5806                 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
5807                                     rif->rif_index, rif->vr_id, rif->dev->mtu);
5808                 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
5809                             MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
5810                             ul_vr->id, saddr4, lb_cf.okey);
5811                 break;
5812
5813         case MLXSW_SP_L3_PROTO_IPV6:
5814                 return -EAFNOSUPPORT;
5815         }
5816
5817         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5818 }
5819
5820 static int
5821 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
5822 {
5823         struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5824         u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
5825         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5826         struct mlxsw_sp_vr *ul_vr;
5827         int err;
5828
5829         ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id);
5830         if (IS_ERR(ul_vr))
5831                 return PTR_ERR(ul_vr);
5832
5833         err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
5834         if (err)
5835                 goto err_loopback_op;
5836
5837         lb_rif->ul_vr_id = ul_vr->id;
5838         ++ul_vr->rif_count;
5839         return 0;
5840
5841 err_loopback_op:
5842         mlxsw_sp_vr_put(ul_vr);
5843         return err;
5844 }
5845
5846 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
5847 {
5848         struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5849         struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5850         struct mlxsw_sp_vr *ul_vr;
5851
5852         ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
5853         mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false);
5854
5855         --ul_vr->rif_count;
5856         mlxsw_sp_vr_put(ul_vr);
5857 }
5858
5859 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = {
5860         .type                   = MLXSW_SP_RIF_TYPE_IPIP_LB,
5861         .rif_size               = sizeof(struct mlxsw_sp_rif_ipip_lb),
5862         .setup                  = mlxsw_sp_rif_ipip_lb_setup,
5863         .configure              = mlxsw_sp_rif_ipip_lb_configure,
5864         .deconfigure            = mlxsw_sp_rif_ipip_lb_deconfigure,
5865 };
5866
5867 static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = {
5868         [MLXSW_SP_RIF_TYPE_SUBPORT]     = &mlxsw_sp_rif_subport_ops,
5869         [MLXSW_SP_RIF_TYPE_VLAN]        = &mlxsw_sp_rif_vlan_ops,
5870         [MLXSW_SP_RIF_TYPE_FID]         = &mlxsw_sp_rif_fid_ops,
5871         [MLXSW_SP_RIF_TYPE_IPIP_LB]     = &mlxsw_sp_rif_ipip_lb_ops,
5872 };
5873
5874 static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
5875 {
5876         u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
5877
5878         mlxsw_sp->router->rifs = kcalloc(max_rifs,
5879                                          sizeof(struct mlxsw_sp_rif *),
5880                                          GFP_KERNEL);
5881         if (!mlxsw_sp->router->rifs)
5882                 return -ENOMEM;
5883
5884         mlxsw_sp->router->rif_ops_arr = mlxsw_sp_rif_ops_arr;
5885
5886         return 0;
5887 }
5888
5889 static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
5890 {
5891         int i;
5892
5893         for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
5894                 WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
5895
5896         kfree(mlxsw_sp->router->rifs);
5897 }
5898
5899 static int
5900 mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp *mlxsw_sp)
5901 {
5902         char tigcr_pl[MLXSW_REG_TIGCR_LEN];
5903
5904         mlxsw_reg_tigcr_pack(tigcr_pl, true, 0);
5905         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tigcr), tigcr_pl);
5906 }
5907
5908 static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
5909 {
5910         mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr;
5911         INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);
5912         return mlxsw_sp_ipip_config_tigcr(mlxsw_sp);
5913 }
5914
5915 static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp)
5916 {
5917         WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list));
5918 }
5919
5920 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
5921 {
5922         struct mlxsw_sp_router *router;
5923
5924         /* Flush pending FIB notifications and then flush the device's
5925          * table before requesting another dump. The FIB notification
5926          * block is unregistered, so no need to take RTNL.
5927          */
5928         mlxsw_core_flush_owq();
5929         router = container_of(nb, struct mlxsw_sp_router, fib_nb);
5930         mlxsw_sp_router_fib_flush(router->mlxsw_sp);
5931 }
5932
5933 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
5934 {
5935         char rgcr_pl[MLXSW_REG_RGCR_LEN];
5936         u64 max_rifs;
5937         int err;
5938
5939         if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
5940                 return -EIO;
5941         max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
5942
5943         mlxsw_reg_rgcr_pack(rgcr_pl, true, true);
5944         mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
5945         err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
5946         if (err)
5947                 return err;
5948         return 0;
5949 }
5950
5951 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
5952 {
5953         char rgcr_pl[MLXSW_REG_RGCR_LEN];
5954
5955         mlxsw_reg_rgcr_pack(rgcr_pl, false, false);
5956         mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
5957 }
5958
5959 int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
5960 {
5961         struct mlxsw_sp_router *router;
5962         int err;
5963
5964         router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
5965         if (!router)
5966                 return -ENOMEM;
5967         mlxsw_sp->router = router;
5968         router->mlxsw_sp = mlxsw_sp;
5969
5970         INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
5971         err = __mlxsw_sp_router_init(mlxsw_sp);
5972         if (err)
5973                 goto err_router_init;
5974
5975         err = mlxsw_sp_rifs_init(mlxsw_sp);
5976         if (err)
5977                 goto err_rifs_init;
5978
5979         err = mlxsw_sp_ipips_init(mlxsw_sp);
5980         if (err)
5981                 goto err_ipips_init;
5982
5983         err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
5984                               &mlxsw_sp_nexthop_ht_params);
5985         if (err)
5986                 goto err_nexthop_ht_init;
5987
5988         err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht,
5989                               &mlxsw_sp_nexthop_group_ht_params);
5990         if (err)
5991                 goto err_nexthop_group_ht_init;
5992
5993         err = mlxsw_sp_lpm_init(mlxsw_sp);
5994         if (err)
5995                 goto err_lpm_init;
5996
5997         err = mlxsw_sp_vrs_init(mlxsw_sp);
5998         if (err)
5999                 goto err_vrs_init;
6000
6001         err = mlxsw_sp_neigh_init(mlxsw_sp);
6002         if (err)
6003                 goto err_neigh_init;
6004
6005         mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
6006         err = register_fib_notifier(&mlxsw_sp->router->fib_nb,
6007                                     mlxsw_sp_router_fib_dump_flush);
6008         if (err)
6009                 goto err_register_fib_notifier;
6010
6011         return 0;
6012
6013 err_register_fib_notifier:
6014         mlxsw_sp_neigh_fini(mlxsw_sp);
6015 err_neigh_init:
6016         mlxsw_sp_vrs_fini(mlxsw_sp);
6017 err_vrs_init:
6018         mlxsw_sp_lpm_fini(mlxsw_sp);
6019 err_lpm_init:
6020         rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
6021 err_nexthop_group_ht_init:
6022         rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
6023 err_nexthop_ht_init:
6024         mlxsw_sp_ipips_fini(mlxsw_sp);
6025 err_ipips_init:
6026         mlxsw_sp_rifs_fini(mlxsw_sp);
6027 err_rifs_init:
6028         __mlxsw_sp_router_fini(mlxsw_sp);
6029 err_router_init:
6030         kfree(mlxsw_sp->router);
6031         return err;
6032 }
6033
6034 void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
6035 {
6036         unregister_fib_notifier(&mlxsw_sp->router->fib_nb);
6037         mlxsw_sp_neigh_fini(mlxsw_sp);
6038         mlxsw_sp_vrs_fini(mlxsw_sp);
6039         mlxsw_sp_lpm_fini(mlxsw_sp);
6040         rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
6041         rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
6042         mlxsw_sp_ipips_fini(mlxsw_sp);
6043         mlxsw_sp_rifs_fini(mlxsw_sp);
6044         __mlxsw_sp_router_fini(mlxsw_sp);
6045         kfree(mlxsw_sp->router);
6046 }