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 	struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
3509 	struct mlxsw_sp_lpm_tree *lpm_tree;
3510 
3511 	/* Aggregate prefix lengths across all virtual routers to make
3512 	 * sure we only have used prefix lengths in the LPM tree.
3513 	 */
3514 	mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage);
3515 	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
3516 					 fib->proto);
3517 	if (IS_ERR(lpm_tree))
3518 		goto err_tree_get;
3519 	mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
3520 
3521 err_tree_get:
3522 	if (!mlxsw_sp_prefix_usage_none(&fib->prefix_usage))
3523 		return;
3524 	mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
3525 	mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree);
3526 	fib->lpm_tree = NULL;
3527 }
3528 
3529 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node *fib_node)
3530 {
3531 	unsigned char prefix_len = fib_node->key.prefix_len;
3532 	struct mlxsw_sp_fib *fib = fib_node->fib;
3533 
3534 	if (fib->prefix_ref_count[prefix_len]++ == 0)
3535 		mlxsw_sp_prefix_usage_set(&fib->prefix_usage, prefix_len);
3536 }
3537 
3538 static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node *fib_node)
3539 {
3540 	unsigned char prefix_len = fib_node->key.prefix_len;
3541 	struct mlxsw_sp_fib *fib = fib_node->fib;
3542 
3543 	if (--fib->prefix_ref_count[prefix_len] == 0)
3544 		mlxsw_sp_prefix_usage_clear(&fib->prefix_usage, prefix_len);
3545 }
3546 
3547 static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
3548 				  struct mlxsw_sp_fib_node *fib_node,
3549 				  struct mlxsw_sp_fib *fib)
3550 {
3551 	int err;
3552 
3553 	err = mlxsw_sp_fib_node_insert(fib, fib_node);
3554 	if (err)
3555 		return err;
3556 	fib_node->fib = fib;
3557 
3558 	err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib, fib_node);
3559 	if (err)
3560 		goto err_fib_lpm_tree_link;
3561 
3562 	mlxsw_sp_fib_node_prefix_inc(fib_node);
3563 
3564 	return 0;
3565 
3566 err_fib_lpm_tree_link:
3567 	fib_node->fib = NULL;
3568 	mlxsw_sp_fib_node_remove(fib, fib_node);
3569 	return err;
3570 }
3571 
3572 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
3573 				   struct mlxsw_sp_fib_node *fib_node)
3574 {
3575 	struct mlxsw_sp_fib *fib = fib_node->fib;
3576 
3577 	mlxsw_sp_fib_node_prefix_dec(fib_node);
3578 	mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib);
3579 	fib_node->fib = NULL;
3580 	mlxsw_sp_fib_node_remove(fib, fib_node);
3581 }
3582 
3583 static struct mlxsw_sp_fib_node *
3584 mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
3585 		      size_t addr_len, unsigned char prefix_len,
3586 		      enum mlxsw_sp_l3proto proto)
3587 {
3588 	struct mlxsw_sp_fib_node *fib_node;
3589 	struct mlxsw_sp_fib *fib;
3590 	struct mlxsw_sp_vr *vr;
3591 	int err;
3592 
3593 	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id);
3594 	if (IS_ERR(vr))
3595 		return ERR_CAST(vr);
3596 	fib = mlxsw_sp_vr_fib(vr, proto);
3597 
3598 	fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len);
3599 	if (fib_node)
3600 		return fib_node;
3601 
3602 	fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len);
3603 	if (!fib_node) {
3604 		err = -ENOMEM;
3605 		goto err_fib_node_create;
3606 	}
3607 
3608 	err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
3609 	if (err)
3610 		goto err_fib_node_init;
3611 
3612 	return fib_node;
3613 
3614 err_fib_node_init:
3615 	mlxsw_sp_fib_node_destroy(fib_node);
3616 err_fib_node_create:
3617 	mlxsw_sp_vr_put(vr);
3618 	return ERR_PTR(err);
3619 }
3620 
3621 static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
3622 				  struct mlxsw_sp_fib_node *fib_node)
3623 {
3624 	struct mlxsw_sp_vr *vr = fib_node->fib->vr;
3625 
3626 	if (!list_empty(&fib_node->entry_list))
3627 		return;
3628 	mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
3629 	mlxsw_sp_fib_node_destroy(fib_node);
3630 	mlxsw_sp_vr_put(vr);
3631 }
3632 
3633 static struct mlxsw_sp_fib4_entry *
3634 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
3635 			      const struct mlxsw_sp_fib4_entry *new4_entry)
3636 {
3637 	struct mlxsw_sp_fib4_entry *fib4_entry;
3638 
3639 	list_for_each_entry(fib4_entry, &fib_node->entry_list, common.list) {
3640 		if (fib4_entry->tb_id > new4_entry->tb_id)
3641 			continue;
3642 		if (fib4_entry->tb_id != new4_entry->tb_id)
3643 			break;
3644 		if (fib4_entry->tos > new4_entry->tos)
3645 			continue;
3646 		if (fib4_entry->prio >= new4_entry->prio ||
3647 		    fib4_entry->tos < new4_entry->tos)
3648 			return fib4_entry;
3649 	}
3650 
3651 	return NULL;
3652 }
3653 
3654 static int
3655 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry *fib4_entry,
3656 			       struct mlxsw_sp_fib4_entry *new4_entry)
3657 {
3658 	struct mlxsw_sp_fib_node *fib_node;
3659 
3660 	if (WARN_ON(!fib4_entry))
3661 		return -EINVAL;
3662 
3663 	fib_node = fib4_entry->common.fib_node;
3664 	list_for_each_entry_from(fib4_entry, &fib_node->entry_list,
3665 				 common.list) {
3666 		if (fib4_entry->tb_id != new4_entry->tb_id ||
3667 		    fib4_entry->tos != new4_entry->tos ||
3668 		    fib4_entry->prio != new4_entry->prio)
3669 			break;
3670 	}
3671 
3672 	list_add_tail(&new4_entry->common.list, &fib4_entry->common.list);
3673 	return 0;
3674 }
3675 
3676 static int
3677 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry *new4_entry,
3678 			       bool replace, bool append)
3679 {
3680 	struct mlxsw_sp_fib_node *fib_node = new4_entry->common.fib_node;
3681 	struct mlxsw_sp_fib4_entry *fib4_entry;
3682 
3683 	fib4_entry = mlxsw_sp_fib4_node_entry_find(fib_node, new4_entry);
3684 
3685 	if (append)
3686 		return mlxsw_sp_fib4_node_list_append(fib4_entry, new4_entry);
3687 	if (replace && WARN_ON(!fib4_entry))
3688 		return -EINVAL;
3689 
3690 	/* Insert new entry before replaced one, so that we can later
3691 	 * remove the second.
3692 	 */
3693 	if (fib4_entry) {
3694 		list_add_tail(&new4_entry->common.list,
3695 			      &fib4_entry->common.list);
3696 	} else {
3697 		struct mlxsw_sp_fib4_entry *last;
3698 
3699 		list_for_each_entry(last, &fib_node->entry_list, common.list) {
3700 			if (new4_entry->tb_id > last->tb_id)
3701 				break;
3702 			fib4_entry = last;
3703 		}
3704 
3705 		if (fib4_entry)
3706 			list_add(&new4_entry->common.list,
3707 				 &fib4_entry->common.list);
3708 		else
3709 			list_add(&new4_entry->common.list,
3710 				 &fib_node->entry_list);
3711 	}
3712 
3713 	return 0;
3714 }
3715 
3716 static void
3717 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry *fib4_entry)
3718 {
3719 	list_del(&fib4_entry->common.list);
3720 }
3721 
3722 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp *mlxsw_sp,
3723 				       struct mlxsw_sp_fib_entry *fib_entry)
3724 {
3725 	struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
3726 
3727 	if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
3728 		return 0;
3729 
3730 	/* To prevent packet loss, overwrite the previously offloaded
3731 	 * entry.
3732 	 */
3733 	if (!list_is_singular(&fib_node->entry_list)) {
3734 		enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
3735 		struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
3736 
3737 		mlxsw_sp_fib_entry_offload_refresh(n, op, 0);
3738 	}
3739 
3740 	return mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
3741 }
3742 
3743 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp *mlxsw_sp,
3744 					struct mlxsw_sp_fib_entry *fib_entry)
3745 {
3746 	struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
3747 
3748 	if (!mlxsw_sp_fib_node_entry_is_first(fib_node, fib_entry))
3749 		return;
3750 
3751 	/* Promote the next entry by overwriting the deleted entry */
3752 	if (!list_is_singular(&fib_node->entry_list)) {
3753 		struct mlxsw_sp_fib_entry *n = list_next_entry(fib_entry, list);
3754 		enum mlxsw_reg_ralue_op op = MLXSW_REG_RALUE_OP_WRITE_DELETE;
3755 
3756 		mlxsw_sp_fib_entry_update(mlxsw_sp, n);
3757 		mlxsw_sp_fib_entry_offload_refresh(fib_entry, op, 0);
3758 		return;
3759 	}
3760 
3761 	mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
3762 }
3763 
3764 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp *mlxsw_sp,
3765 					 struct mlxsw_sp_fib4_entry *fib4_entry,
3766 					 bool replace, bool append)
3767 {
3768 	int err;
3769 
3770 	err = mlxsw_sp_fib4_node_list_insert(fib4_entry, replace, append);
3771 	if (err)
3772 		return err;
3773 
3774 	err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib4_entry->common);
3775 	if (err)
3776 		goto err_fib_node_entry_add;
3777 
3778 	return 0;
3779 
3780 err_fib_node_entry_add:
3781 	mlxsw_sp_fib4_node_list_remove(fib4_entry);
3782 	return err;
3783 }
3784 
3785 static void
3786 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
3787 				struct mlxsw_sp_fib4_entry *fib4_entry)
3788 {
3789 	mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib4_entry->common);
3790 	mlxsw_sp_fib4_node_list_remove(fib4_entry);
3791 
3792 	if (fib4_entry->common.type == MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP)
3793 		mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, &fib4_entry->common);
3794 }
3795 
3796 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp *mlxsw_sp,
3797 					struct mlxsw_sp_fib4_entry *fib4_entry,
3798 					bool replace)
3799 {
3800 	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
3801 	struct mlxsw_sp_fib4_entry *replaced;
3802 
3803 	if (!replace)
3804 		return;
3805 
3806 	/* We inserted the new entry before replaced one */
3807 	replaced = list_next_entry(fib4_entry, common.list);
3808 
3809 	mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, replaced);
3810 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, replaced);
3811 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3812 }
3813 
3814 static int
3815 mlxsw_sp_router_fib4_add(struct mlxsw_sp *mlxsw_sp,
3816 			 const struct fib_entry_notifier_info *fen_info,
3817 			 bool replace, bool append)
3818 {
3819 	struct mlxsw_sp_fib4_entry *fib4_entry;
3820 	struct mlxsw_sp_fib_node *fib_node;
3821 	int err;
3822 
3823 	if (mlxsw_sp->router->aborted)
3824 		return 0;
3825 
3826 	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
3827 					 &fen_info->dst, sizeof(fen_info->dst),
3828 					 fen_info->dst_len,
3829 					 MLXSW_SP_L3_PROTO_IPV4);
3830 	if (IS_ERR(fib_node)) {
3831 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
3832 		return PTR_ERR(fib_node);
3833 	}
3834 
3835 	fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
3836 	if (IS_ERR(fib4_entry)) {
3837 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
3838 		err = PTR_ERR(fib4_entry);
3839 		goto err_fib4_entry_create;
3840 	}
3841 
3842 	err = mlxsw_sp_fib4_node_entry_link(mlxsw_sp, fib4_entry, replace,
3843 					    append);
3844 	if (err) {
3845 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
3846 		goto err_fib4_node_entry_link;
3847 	}
3848 
3849 	mlxsw_sp_fib4_entry_replace(mlxsw_sp, fib4_entry, replace);
3850 
3851 	return 0;
3852 
3853 err_fib4_node_entry_link:
3854 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
3855 err_fib4_entry_create:
3856 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3857 	return err;
3858 }
3859 
3860 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
3861 				     struct fib_entry_notifier_info *fen_info)
3862 {
3863 	struct mlxsw_sp_fib4_entry *fib4_entry;
3864 	struct mlxsw_sp_fib_node *fib_node;
3865 
3866 	if (mlxsw_sp->router->aborted)
3867 		return;
3868 
3869 	fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
3870 	if (WARN_ON(!fib4_entry))
3871 		return;
3872 	fib_node = fib4_entry->common.fib_node;
3873 
3874 	mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
3875 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
3876 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
3877 }
3878 
3879 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info *rt)
3880 {
3881 	/* Packets with link-local destination IP arriving to the router
3882 	 * are trapped to the CPU, so no need to program specific routes
3883 	 * for them.
3884 	 */
3885 	if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_LINKLOCAL)
3886 		return true;
3887 
3888 	/* Multicast routes aren't supported, so ignore them. Neighbour
3889 	 * Discovery packets are specifically trapped.
3890 	 */
3891 	if (ipv6_addr_type(&rt->rt6i_dst.addr) & IPV6_ADDR_MULTICAST)
3892 		return true;
3893 
3894 	/* Cloned routes are irrelevant in the forwarding path. */
3895 	if (rt->rt6i_flags & RTF_CACHE)
3896 		return true;
3897 
3898 	return false;
3899 }
3900 
3901 static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct rt6_info *rt)
3902 {
3903 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3904 
3905 	mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL);
3906 	if (!mlxsw_sp_rt6)
3907 		return ERR_PTR(-ENOMEM);
3908 
3909 	/* In case of route replace, replaced route is deleted with
3910 	 * no notification. Take reference to prevent accessing freed
3911 	 * memory.
3912 	 */
3913 	mlxsw_sp_rt6->rt = rt;
3914 	rt6_hold(rt);
3915 
3916 	return mlxsw_sp_rt6;
3917 }
3918 
3919 #if IS_ENABLED(CONFIG_IPV6)
3920 static void mlxsw_sp_rt6_release(struct rt6_info *rt)
3921 {
3922 	rt6_release(rt);
3923 }
3924 #else
3925 static void mlxsw_sp_rt6_release(struct rt6_info *rt)
3926 {
3927 }
3928 #endif
3929 
3930 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
3931 {
3932 	mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
3933 	kfree(mlxsw_sp_rt6);
3934 }
3935 
3936 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info *rt)
3937 {
3938 	/* RTF_CACHE routes are ignored */
3939 	return (rt->rt6i_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
3940 }
3941 
3942 static struct rt6_info *
3943 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
3944 {
3945 	return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
3946 				list)->rt;
3947 }
3948 
3949 static struct mlxsw_sp_fib6_entry *
3950 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
3951 				 const struct rt6_info *nrt, bool replace)
3952 {
3953 	struct mlxsw_sp_fib6_entry *fib6_entry;
3954 
3955 	if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
3956 		return NULL;
3957 
3958 	list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
3959 		struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
3960 
3961 		/* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
3962 		 * virtual router.
3963 		 */
3964 		if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
3965 			continue;
3966 		if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
3967 			break;
3968 		if (rt->rt6i_metric < nrt->rt6i_metric)
3969 			continue;
3970 		if (rt->rt6i_metric == nrt->rt6i_metric &&
3971 		    mlxsw_sp_fib6_rt_can_mp(rt))
3972 			return fib6_entry;
3973 		if (rt->rt6i_metric > nrt->rt6i_metric)
3974 			break;
3975 	}
3976 
3977 	return NULL;
3978 }
3979 
3980 static struct mlxsw_sp_rt6 *
3981 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
3982 			    const struct rt6_info *rt)
3983 {
3984 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3985 
3986 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3987 		if (mlxsw_sp_rt6->rt == rt)
3988 			return mlxsw_sp_rt6;
3989 	}
3990 
3991 	return NULL;
3992 }
3993 
3994 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
3995 					const struct rt6_info *rt,
3996 					enum mlxsw_sp_ipip_type *ret)
3997 {
3998 	return rt->dst.dev &&
3999 	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->dst.dev, ret);
4000 }
4001 
4002 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
4003 				       struct mlxsw_sp_nexthop_group *nh_grp,
4004 				       struct mlxsw_sp_nexthop *nh,
4005 				       const struct rt6_info *rt)
4006 {
4007 	struct mlxsw_sp_router *router = mlxsw_sp->router;
4008 	struct net_device *dev = rt->dst.dev;
4009 	enum mlxsw_sp_ipip_type ipipt;
4010 	struct mlxsw_sp_rif *rif;
4011 	int err;
4012 
4013 	if (mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, &ipipt) &&
4014 	    router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
4015 						     MLXSW_SP_L3_PROTO_IPV6)) {
4016 		nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
4017 		err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
4018 		if (err)
4019 			return err;
4020 		mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common);
4021 		return 0;
4022 	}
4023 
4024 	nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
4025 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
4026 	if (!rif)
4027 		return 0;
4028 	mlxsw_sp_nexthop_rif_init(nh, rif);
4029 
4030 	err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
4031 	if (err)
4032 		goto err_nexthop_neigh_init;
4033 
4034 	return 0;
4035 
4036 err_nexthop_neigh_init:
4037 	mlxsw_sp_nexthop_rif_fini(nh);
4038 	return err;
4039 }
4040 
4041 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp *mlxsw_sp,
4042 					struct mlxsw_sp_nexthop *nh)
4043 {
4044 	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4045 }
4046 
4047 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
4048 				  struct mlxsw_sp_nexthop_group *nh_grp,
4049 				  struct mlxsw_sp_nexthop *nh,
4050 				  const struct rt6_info *rt)
4051 {
4052 	struct net_device *dev = rt->dst.dev;
4053 
4054 	nh->nh_grp = nh_grp;
4055 	memcpy(&nh->gw_addr, &rt->rt6i_gateway, sizeof(nh->gw_addr));
4056 
4057 	if (!dev)
4058 		return 0;
4059 	nh->ifindex = dev->ifindex;
4060 
4061 	return mlxsw_sp_nexthop6_type_init(mlxsw_sp, nh_grp, nh, rt);
4062 }
4063 
4064 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
4065 				   struct mlxsw_sp_nexthop *nh)
4066 {
4067 	mlxsw_sp_nexthop6_type_fini(mlxsw_sp, nh);
4068 }
4069 
4070 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
4071 				    const struct rt6_info *rt)
4072 {
4073 	return rt->rt6i_flags & RTF_GATEWAY ||
4074 	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
4075 }
4076 
4077 static struct mlxsw_sp_nexthop_group *
4078 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
4079 			       struct mlxsw_sp_fib6_entry *fib6_entry)
4080 {
4081 	struct mlxsw_sp_nexthop_group *nh_grp;
4082 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4083 	struct mlxsw_sp_nexthop *nh;
4084 	size_t alloc_size;
4085 	int i = 0;
4086 	int err;
4087 
4088 	alloc_size = sizeof(*nh_grp) +
4089 		     fib6_entry->nrt6 * sizeof(struct mlxsw_sp_nexthop);
4090 	nh_grp = kzalloc(alloc_size, GFP_KERNEL);
4091 	if (!nh_grp)
4092 		return ERR_PTR(-ENOMEM);
4093 	INIT_LIST_HEAD(&nh_grp->fib_list);
4094 #if IS_ENABLED(CONFIG_IPV6)
4095 	nh_grp->neigh_tbl = &nd_tbl;
4096 #endif
4097 	mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
4098 					struct mlxsw_sp_rt6, list);
4099 	nh_grp->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
4100 	nh_grp->count = fib6_entry->nrt6;
4101 	for (i = 0; i < nh_grp->count; i++) {
4102 		struct rt6_info *rt = mlxsw_sp_rt6->rt;
4103 
4104 		nh = &nh_grp->nexthops[i];
4105 		err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt);
4106 		if (err)
4107 			goto err_nexthop6_init;
4108 		mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list);
4109 	}
4110 
4111 	err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
4112 	if (err)
4113 		goto err_nexthop_group_insert;
4114 
4115 	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4116 	return nh_grp;
4117 
4118 err_nexthop_group_insert:
4119 err_nexthop6_init:
4120 	for (i--; i >= 0; i--) {
4121 		nh = &nh_grp->nexthops[i];
4122 		mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
4123 	}
4124 	kfree(nh_grp);
4125 	return ERR_PTR(err);
4126 }
4127 
4128 static void
4129 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp,
4130 				struct mlxsw_sp_nexthop_group *nh_grp)
4131 {
4132 	struct mlxsw_sp_nexthop *nh;
4133 	int i = nh_grp->count;
4134 
4135 	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
4136 	for (i--; i >= 0; i--) {
4137 		nh = &nh_grp->nexthops[i];
4138 		mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
4139 	}
4140 	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4141 	WARN_ON(nh_grp->adj_index_valid);
4142 	kfree(nh_grp);
4143 }
4144 
4145 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp,
4146 				       struct mlxsw_sp_fib6_entry *fib6_entry)
4147 {
4148 	struct mlxsw_sp_nexthop_group *nh_grp;
4149 
4150 	nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry);
4151 	if (!nh_grp) {
4152 		nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry);
4153 		if (IS_ERR(nh_grp))
4154 			return PTR_ERR(nh_grp);
4155 	}
4156 
4157 	list_add_tail(&fib6_entry->common.nexthop_group_node,
4158 		      &nh_grp->fib_list);
4159 	fib6_entry->common.nh_group = nh_grp;
4160 
4161 	return 0;
4162 }
4163 
4164 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp,
4165 					struct mlxsw_sp_fib_entry *fib_entry)
4166 {
4167 	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
4168 
4169 	list_del(&fib_entry->nexthop_group_node);
4170 	if (!list_empty(&nh_grp->fib_list))
4171 		return;
4172 	mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp);
4173 }
4174 
4175 static int
4176 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
4177 			       struct mlxsw_sp_fib6_entry *fib6_entry)
4178 {
4179 	struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group;
4180 	int err;
4181 
4182 	fib6_entry->common.nh_group = NULL;
4183 	list_del(&fib6_entry->common.nexthop_group_node);
4184 
4185 	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
4186 	if (err)
4187 		goto err_nexthop6_group_get;
4188 
4189 	/* In case this entry is offloaded, then the adjacency index
4190 	 * currently associated with it in the device's table is that
4191 	 * of the old group. Start using the new one instead.
4192 	 */
4193 	err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
4194 	if (err)
4195 		goto err_fib_node_entry_add;
4196 
4197 	if (list_empty(&old_nh_grp->fib_list))
4198 		mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
4199 
4200 	return 0;
4201 
4202 err_fib_node_entry_add:
4203 	mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
4204 err_nexthop6_group_get:
4205 	list_add_tail(&fib6_entry->common.nexthop_group_node,
4206 		      &old_nh_grp->fib_list);
4207 	fib6_entry->common.nh_group = old_nh_grp;
4208 	return err;
4209 }
4210 
4211 static int
4212 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
4213 				struct mlxsw_sp_fib6_entry *fib6_entry,
4214 				struct rt6_info *rt)
4215 {
4216 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4217 	int err;
4218 
4219 	mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
4220 	if (IS_ERR(mlxsw_sp_rt6))
4221 		return PTR_ERR(mlxsw_sp_rt6);
4222 
4223 	list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
4224 	fib6_entry->nrt6++;
4225 
4226 	err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
4227 	if (err)
4228 		goto err_nexthop6_group_update;
4229 
4230 	return 0;
4231 
4232 err_nexthop6_group_update:
4233 	fib6_entry->nrt6--;
4234 	list_del(&mlxsw_sp_rt6->list);
4235 	mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4236 	return err;
4237 }
4238 
4239 static void
4240 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
4241 				struct mlxsw_sp_fib6_entry *fib6_entry,
4242 				struct rt6_info *rt)
4243 {
4244 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4245 
4246 	mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt);
4247 	if (WARN_ON(!mlxsw_sp_rt6))
4248 		return;
4249 
4250 	fib6_entry->nrt6--;
4251 	list_del(&mlxsw_sp_rt6->list);
4252 	mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
4253 	mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4254 }
4255 
4256 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
4257 					 struct mlxsw_sp_fib_entry *fib_entry,
4258 					 const struct rt6_info *rt)
4259 {
4260 	/* Packets hitting RTF_REJECT routes need to be discarded by the
4261 	 * stack. We can rely on their destination device not having a
4262 	 * RIF (it's the loopback device) and can thus use action type
4263 	 * local, which will cause them to be trapped with a lower
4264 	 * priority than packets that need to be locally received.
4265 	 */
4266 	if (rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST))
4267 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
4268 	else if (rt->rt6i_flags & RTF_REJECT)
4269 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4270 	else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
4271 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
4272 	else
4273 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4274 }
4275 
4276 static void
4277 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
4278 {
4279 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp;
4280 
4281 	list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list,
4282 				 list) {
4283 		fib6_entry->nrt6--;
4284 		list_del(&mlxsw_sp_rt6->list);
4285 		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4286 	}
4287 }
4288 
4289 static struct mlxsw_sp_fib6_entry *
4290 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
4291 			   struct mlxsw_sp_fib_node *fib_node,
4292 			   struct rt6_info *rt)
4293 {
4294 	struct mlxsw_sp_fib6_entry *fib6_entry;
4295 	struct mlxsw_sp_fib_entry *fib_entry;
4296 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4297 	int err;
4298 
4299 	fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
4300 	if (!fib6_entry)
4301 		return ERR_PTR(-ENOMEM);
4302 	fib_entry = &fib6_entry->common;
4303 
4304 	mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt);
4305 	if (IS_ERR(mlxsw_sp_rt6)) {
4306 		err = PTR_ERR(mlxsw_sp_rt6);
4307 		goto err_rt6_create;
4308 	}
4309 
4310 	mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, mlxsw_sp_rt6->rt);
4311 
4312 	INIT_LIST_HEAD(&fib6_entry->rt6_list);
4313 	list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
4314 	fib6_entry->nrt6 = 1;
4315 	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
4316 	if (err)
4317 		goto err_nexthop6_group_get;
4318 
4319 	fib_entry->fib_node = fib_node;
4320 
4321 	return fib6_entry;
4322 
4323 err_nexthop6_group_get:
4324 	list_del(&mlxsw_sp_rt6->list);
4325 	mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
4326 err_rt6_create:
4327 	kfree(fib6_entry);
4328 	return ERR_PTR(err);
4329 }
4330 
4331 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
4332 					struct mlxsw_sp_fib6_entry *fib6_entry)
4333 {
4334 	mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
4335 	mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry);
4336 	WARN_ON(fib6_entry->nrt6);
4337 	kfree(fib6_entry);
4338 }
4339 
4340 static struct mlxsw_sp_fib6_entry *
4341 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
4342 			      const struct rt6_info *nrt, bool replace)
4343 {
4344 	struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
4345 
4346 	list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
4347 		struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
4348 
4349 		if (rt->rt6i_table->tb6_id > nrt->rt6i_table->tb6_id)
4350 			continue;
4351 		if (rt->rt6i_table->tb6_id != nrt->rt6i_table->tb6_id)
4352 			break;
4353 		if (replace && rt->rt6i_metric == nrt->rt6i_metric) {
4354 			if (mlxsw_sp_fib6_rt_can_mp(rt) ==
4355 			    mlxsw_sp_fib6_rt_can_mp(nrt))
4356 				return fib6_entry;
4357 			if (mlxsw_sp_fib6_rt_can_mp(nrt))
4358 				fallback = fallback ?: fib6_entry;
4359 		}
4360 		if (rt->rt6i_metric > nrt->rt6i_metric)
4361 			return fallback ?: fib6_entry;
4362 	}
4363 
4364 	return fallback;
4365 }
4366 
4367 static int
4368 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry *new6_entry,
4369 			       bool replace)
4370 {
4371 	struct mlxsw_sp_fib_node *fib_node = new6_entry->common.fib_node;
4372 	struct rt6_info *nrt = mlxsw_sp_fib6_entry_rt(new6_entry);
4373 	struct mlxsw_sp_fib6_entry *fib6_entry;
4374 
4375 	fib6_entry = mlxsw_sp_fib6_node_entry_find(fib_node, nrt, replace);
4376 
4377 	if (replace && WARN_ON(!fib6_entry))
4378 		return -EINVAL;
4379 
4380 	if (fib6_entry) {
4381 		list_add_tail(&new6_entry->common.list,
4382 			      &fib6_entry->common.list);
4383 	} else {
4384 		struct mlxsw_sp_fib6_entry *last;
4385 
4386 		list_for_each_entry(last, &fib_node->entry_list, common.list) {
4387 			struct rt6_info *rt = mlxsw_sp_fib6_entry_rt(last);
4388 
4389 			if (nrt->rt6i_table->tb6_id > rt->rt6i_table->tb6_id)
4390 				break;
4391 			fib6_entry = last;
4392 		}
4393 
4394 		if (fib6_entry)
4395 			list_add(&new6_entry->common.list,
4396 				 &fib6_entry->common.list);
4397 		else
4398 			list_add(&new6_entry->common.list,
4399 				 &fib_node->entry_list);
4400 	}
4401 
4402 	return 0;
4403 }
4404 
4405 static void
4406 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry *fib6_entry)
4407 {
4408 	list_del(&fib6_entry->common.list);
4409 }
4410 
4411 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp *mlxsw_sp,
4412 					 struct mlxsw_sp_fib6_entry *fib6_entry,
4413 					 bool replace)
4414 {
4415 	int err;
4416 
4417 	err = mlxsw_sp_fib6_node_list_insert(fib6_entry, replace);
4418 	if (err)
4419 		return err;
4420 
4421 	err = mlxsw_sp_fib_node_entry_add(mlxsw_sp, &fib6_entry->common);
4422 	if (err)
4423 		goto err_fib_node_entry_add;
4424 
4425 	return 0;
4426 
4427 err_fib_node_entry_add:
4428 	mlxsw_sp_fib6_node_list_remove(fib6_entry);
4429 	return err;
4430 }
4431 
4432 static void
4433 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
4434 				struct mlxsw_sp_fib6_entry *fib6_entry)
4435 {
4436 	mlxsw_sp_fib_node_entry_del(mlxsw_sp, &fib6_entry->common);
4437 	mlxsw_sp_fib6_node_list_remove(fib6_entry);
4438 }
4439 
4440 static struct mlxsw_sp_fib6_entry *
4441 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
4442 			   const struct rt6_info *rt)
4443 {
4444 	struct mlxsw_sp_fib6_entry *fib6_entry;
4445 	struct mlxsw_sp_fib_node *fib_node;
4446 	struct mlxsw_sp_fib *fib;
4447 	struct mlxsw_sp_vr *vr;
4448 
4449 	vr = mlxsw_sp_vr_find(mlxsw_sp, rt->rt6i_table->tb6_id);
4450 	if (!vr)
4451 		return NULL;
4452 	fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
4453 
4454 	fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->rt6i_dst.addr,
4455 					    sizeof(rt->rt6i_dst.addr),
4456 					    rt->rt6i_dst.plen);
4457 	if (!fib_node)
4458 		return NULL;
4459 
4460 	list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
4461 		struct rt6_info *iter_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
4462 
4463 		if (rt->rt6i_table->tb6_id == iter_rt->rt6i_table->tb6_id &&
4464 		    rt->rt6i_metric == iter_rt->rt6i_metric &&
4465 		    mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
4466 			return fib6_entry;
4467 	}
4468 
4469 	return NULL;
4470 }
4471 
4472 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
4473 					struct mlxsw_sp_fib6_entry *fib6_entry,
4474 					bool replace)
4475 {
4476 	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
4477 	struct mlxsw_sp_fib6_entry *replaced;
4478 
4479 	if (!replace)
4480 		return;
4481 
4482 	replaced = list_next_entry(fib6_entry, common.list);
4483 
4484 	mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, replaced);
4485 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, replaced);
4486 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4487 }
4488 
4489 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
4490 				    struct rt6_info *rt, bool replace)
4491 {
4492 	struct mlxsw_sp_fib6_entry *fib6_entry;
4493 	struct mlxsw_sp_fib_node *fib_node;
4494 	int err;
4495 
4496 	if (mlxsw_sp->router->aborted)
4497 		return 0;
4498 
4499 	if (rt->rt6i_src.plen)
4500 		return -EINVAL;
4501 
4502 	if (mlxsw_sp_fib6_rt_should_ignore(rt))
4503 		return 0;
4504 
4505 	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->rt6i_table->tb6_id,
4506 					 &rt->rt6i_dst.addr,
4507 					 sizeof(rt->rt6i_dst.addr),
4508 					 rt->rt6i_dst.plen,
4509 					 MLXSW_SP_L3_PROTO_IPV6);
4510 	if (IS_ERR(fib_node))
4511 		return PTR_ERR(fib_node);
4512 
4513 	/* Before creating a new entry, try to append route to an existing
4514 	 * multipath entry.
4515 	 */
4516 	fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
4517 	if (fib6_entry) {
4518 		err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
4519 		if (err)
4520 			goto err_fib6_entry_nexthop_add;
4521 		return 0;
4522 	}
4523 
4524 	fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
4525 	if (IS_ERR(fib6_entry)) {
4526 		err = PTR_ERR(fib6_entry);
4527 		goto err_fib6_entry_create;
4528 	}
4529 
4530 	err = mlxsw_sp_fib6_node_entry_link(mlxsw_sp, fib6_entry, replace);
4531 	if (err)
4532 		goto err_fib6_node_entry_link;
4533 
4534 	mlxsw_sp_fib6_entry_replace(mlxsw_sp, fib6_entry, replace);
4535 
4536 	return 0;
4537 
4538 err_fib6_node_entry_link:
4539 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4540 err_fib6_entry_create:
4541 err_fib6_entry_nexthop_add:
4542 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4543 	return err;
4544 }
4545 
4546 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
4547 				     struct rt6_info *rt)
4548 {
4549 	struct mlxsw_sp_fib6_entry *fib6_entry;
4550 	struct mlxsw_sp_fib_node *fib_node;
4551 
4552 	if (mlxsw_sp->router->aborted)
4553 		return;
4554 
4555 	if (mlxsw_sp_fib6_rt_should_ignore(rt))
4556 		return;
4557 
4558 	fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
4559 	if (WARN_ON(!fib6_entry))
4560 		return;
4561 
4562 	/* If route is part of a multipath entry, but not the last one
4563 	 * removed, then only reduce its nexthop group.
4564 	 */
4565 	if (!list_is_singular(&fib6_entry->rt6_list)) {
4566 		mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt);
4567 		return;
4568 	}
4569 
4570 	fib_node = fib6_entry->common.fib_node;
4571 
4572 	mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
4573 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4574 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4575 }
4576 
4577 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp,
4578 					    enum mlxsw_reg_ralxx_protocol proto,
4579 					    u8 tree_id)
4580 {
4581 	char ralta_pl[MLXSW_REG_RALTA_LEN];
4582 	char ralst_pl[MLXSW_REG_RALST_LEN];
4583 	int i, err;
4584 
4585 	mlxsw_reg_ralta_pack(ralta_pl, true, proto, tree_id);
4586 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
4587 	if (err)
4588 		return err;
4589 
4590 	mlxsw_reg_ralst_pack(ralst_pl, 0xff, tree_id);
4591 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
4592 	if (err)
4593 		return err;
4594 
4595 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
4596 		struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
4597 		char raltb_pl[MLXSW_REG_RALTB_LEN];
4598 		char ralue_pl[MLXSW_REG_RALUE_LEN];
4599 
4600 		mlxsw_reg_raltb_pack(raltb_pl, vr->id, proto, tree_id);
4601 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb),
4602 				      raltb_pl);
4603 		if (err)
4604 			return err;
4605 
4606 		mlxsw_reg_ralue_pack(ralue_pl, proto,
4607 				     MLXSW_REG_RALUE_OP_WRITE_WRITE, vr->id, 0);
4608 		mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
4609 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue),
4610 				      ralue_pl);
4611 		if (err)
4612 			return err;
4613 	}
4614 
4615 	return 0;
4616 }
4617 
4618 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
4619 {
4620 	enum mlxsw_reg_ralxx_protocol proto = MLXSW_REG_RALXX_PROTOCOL_IPV4;
4621 	int err;
4622 
4623 	err = __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
4624 					       MLXSW_SP_LPM_TREE_MIN);
4625 	if (err)
4626 		return err;
4627 
4628 	proto = MLXSW_REG_RALXX_PROTOCOL_IPV6;
4629 	return __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
4630 						MLXSW_SP_LPM_TREE_MIN + 1);
4631 }
4632 
4633 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
4634 				     struct mlxsw_sp_fib_node *fib_node)
4635 {
4636 	struct mlxsw_sp_fib4_entry *fib4_entry, *tmp;
4637 
4638 	list_for_each_entry_safe(fib4_entry, tmp, &fib_node->entry_list,
4639 				 common.list) {
4640 		bool do_break = &tmp->common.list == &fib_node->entry_list;
4641 
4642 		mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp, fib4_entry);
4643 		mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4644 		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4645 		/* Break when entry list is empty and node was freed.
4646 		 * Otherwise, we'll access freed memory in the next
4647 		 * iteration.
4648 		 */
4649 		if (do_break)
4650 			break;
4651 	}
4652 }
4653 
4654 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
4655 				     struct mlxsw_sp_fib_node *fib_node)
4656 {
4657 	struct mlxsw_sp_fib6_entry *fib6_entry, *tmp;
4658 
4659 	list_for_each_entry_safe(fib6_entry, tmp, &fib_node->entry_list,
4660 				 common.list) {
4661 		bool do_break = &tmp->common.list == &fib_node->entry_list;
4662 
4663 		mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp, fib6_entry);
4664 		mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
4665 		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4666 		if (do_break)
4667 			break;
4668 	}
4669 }
4670 
4671 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
4672 				    struct mlxsw_sp_fib_node *fib_node)
4673 {
4674 	switch (fib_node->fib->proto) {
4675 	case MLXSW_SP_L3_PROTO_IPV4:
4676 		mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
4677 		break;
4678 	case MLXSW_SP_L3_PROTO_IPV6:
4679 		mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node);
4680 		break;
4681 	}
4682 }
4683 
4684 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
4685 				  struct mlxsw_sp_vr *vr,
4686 				  enum mlxsw_sp_l3proto proto)
4687 {
4688 	struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
4689 	struct mlxsw_sp_fib_node *fib_node, *tmp;
4690 
4691 	list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
4692 		bool do_break = &tmp->list == &fib->node_list;
4693 
4694 		mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
4695 		if (do_break)
4696 			break;
4697 	}
4698 }
4699 
4700 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
4701 {
4702 	int i;
4703 
4704 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
4705 		struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
4706 
4707 		if (!mlxsw_sp_vr_is_used(vr))
4708 			continue;
4709 		mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
4710 
4711 		/* If virtual router was only used for IPv4, then it's no
4712 		 * longer used.
4713 		 */
4714 		if (!mlxsw_sp_vr_is_used(vr))
4715 			continue;
4716 		mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
4717 	}
4718 }
4719 
4720 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp)
4721 {
4722 	int err;
4723 
4724 	if (mlxsw_sp->router->aborted)
4725 		return;
4726 	dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
4727 	mlxsw_sp_router_fib_flush(mlxsw_sp);
4728 	mlxsw_sp->router->aborted = true;
4729 	err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
4730 	if (err)
4731 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
4732 }
4733 
4734 struct mlxsw_sp_fib_event_work {
4735 	struct work_struct work;
4736 	union {
4737 		struct fib6_entry_notifier_info fen6_info;
4738 		struct fib_entry_notifier_info fen_info;
4739 		struct fib_rule_notifier_info fr_info;
4740 		struct fib_nh_notifier_info fnh_info;
4741 	};
4742 	struct mlxsw_sp *mlxsw_sp;
4743 	unsigned long event;
4744 };
4745 
4746 static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
4747 {
4748 	struct mlxsw_sp_fib_event_work *fib_work =
4749 		container_of(work, struct mlxsw_sp_fib_event_work, work);
4750 	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
4751 	struct fib_rule *rule;
4752 	bool replace, append;
4753 	int err;
4754 
4755 	/* Protect internal structures from changes */
4756 	rtnl_lock();
4757 	switch (fib_work->event) {
4758 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4759 	case FIB_EVENT_ENTRY_APPEND: /* fall through */
4760 	case FIB_EVENT_ENTRY_ADD:
4761 		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
4762 		append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
4763 		err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info,
4764 					       replace, append);
4765 		if (err)
4766 			mlxsw_sp_router_fib_abort(mlxsw_sp);
4767 		fib_info_put(fib_work->fen_info.fi);
4768 		break;
4769 	case FIB_EVENT_ENTRY_DEL:
4770 		mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
4771 		fib_info_put(fib_work->fen_info.fi);
4772 		break;
4773 	case FIB_EVENT_RULE_ADD: /* fall through */
4774 	case FIB_EVENT_RULE_DEL:
4775 		rule = fib_work->fr_info.rule;
4776 		if (!fib4_rule_default(rule) && !rule->l3mdev)
4777 			mlxsw_sp_router_fib_abort(mlxsw_sp);
4778 		fib_rule_put(rule);
4779 		break;
4780 	case FIB_EVENT_NH_ADD: /* fall through */
4781 	case FIB_EVENT_NH_DEL:
4782 		mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event,
4783 					fib_work->fnh_info.fib_nh);
4784 		fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
4785 		break;
4786 	}
4787 	rtnl_unlock();
4788 	kfree(fib_work);
4789 }
4790 
4791 static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
4792 {
4793 	struct mlxsw_sp_fib_event_work *fib_work =
4794 		container_of(work, struct mlxsw_sp_fib_event_work, work);
4795 	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
4796 	struct fib_rule *rule;
4797 	bool replace;
4798 	int err;
4799 
4800 	rtnl_lock();
4801 	switch (fib_work->event) {
4802 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4803 	case FIB_EVENT_ENTRY_ADD:
4804 		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
4805 		err = mlxsw_sp_router_fib6_add(mlxsw_sp,
4806 					       fib_work->fen6_info.rt, replace);
4807 		if (err)
4808 			mlxsw_sp_router_fib_abort(mlxsw_sp);
4809 		mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
4810 		break;
4811 	case FIB_EVENT_ENTRY_DEL:
4812 		mlxsw_sp_router_fib6_del(mlxsw_sp, fib_work->fen6_info.rt);
4813 		mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
4814 		break;
4815 	case FIB_EVENT_RULE_ADD: /* fall through */
4816 	case FIB_EVENT_RULE_DEL:
4817 		rule = fib_work->fr_info.rule;
4818 		if (!fib6_rule_default(rule) && !rule->l3mdev)
4819 			mlxsw_sp_router_fib_abort(mlxsw_sp);
4820 		fib_rule_put(rule);
4821 		break;
4822 	}
4823 	rtnl_unlock();
4824 	kfree(fib_work);
4825 }
4826 
4827 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
4828 				       struct fib_notifier_info *info)
4829 {
4830 	switch (fib_work->event) {
4831 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4832 	case FIB_EVENT_ENTRY_APPEND: /* fall through */
4833 	case FIB_EVENT_ENTRY_ADD: /* fall through */
4834 	case FIB_EVENT_ENTRY_DEL:
4835 		memcpy(&fib_work->fen_info, info, sizeof(fib_work->fen_info));
4836 		/* Take referece on fib_info to prevent it from being
4837 		 * freed while work is queued. Release it afterwards.
4838 		 */
4839 		fib_info_hold(fib_work->fen_info.fi);
4840 		break;
4841 	case FIB_EVENT_RULE_ADD: /* fall through */
4842 	case FIB_EVENT_RULE_DEL:
4843 		memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
4844 		fib_rule_get(fib_work->fr_info.rule);
4845 		break;
4846 	case FIB_EVENT_NH_ADD: /* fall through */
4847 	case FIB_EVENT_NH_DEL:
4848 		memcpy(&fib_work->fnh_info, info, sizeof(fib_work->fnh_info));
4849 		fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
4850 		break;
4851 	}
4852 }
4853 
4854 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
4855 				       struct fib_notifier_info *info)
4856 {
4857 	switch (fib_work->event) {
4858 	case FIB_EVENT_ENTRY_REPLACE: /* fall through */
4859 	case FIB_EVENT_ENTRY_ADD: /* fall through */
4860 	case FIB_EVENT_ENTRY_DEL:
4861 		memcpy(&fib_work->fen6_info, info, sizeof(fib_work->fen6_info));
4862 		rt6_hold(fib_work->fen6_info.rt);
4863 		break;
4864 	case FIB_EVENT_RULE_ADD: /* fall through */
4865 	case FIB_EVENT_RULE_DEL:
4866 		memcpy(&fib_work->fr_info, info, sizeof(fib_work->fr_info));
4867 		fib_rule_get(fib_work->fr_info.rule);
4868 		break;
4869 	}
4870 }
4871 
4872 /* Called with rcu_read_lock() */
4873 static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
4874 				     unsigned long event, void *ptr)
4875 {
4876 	struct mlxsw_sp_fib_event_work *fib_work;
4877 	struct fib_notifier_info *info = ptr;
4878 	struct mlxsw_sp_router *router;
4879 
4880 	if (!net_eq(info->net, &init_net) ||
4881 	    (info->family != AF_INET && info->family != AF_INET6))
4882 		return NOTIFY_DONE;
4883 
4884 	fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
4885 	if (WARN_ON(!fib_work))
4886 		return NOTIFY_BAD;
4887 
4888 	router = container_of(nb, struct mlxsw_sp_router, fib_nb);
4889 	fib_work->mlxsw_sp = router->mlxsw_sp;
4890 	fib_work->event = event;
4891 
4892 	switch (info->family) {
4893 	case AF_INET:
4894 		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work);
4895 		mlxsw_sp_router_fib4_event(fib_work, info);
4896 		break;
4897 	case AF_INET6:
4898 		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
4899 		mlxsw_sp_router_fib6_event(fib_work, info);
4900 		break;
4901 	}
4902 
4903 	mlxsw_core_schedule_work(&fib_work->work);
4904 
4905 	return NOTIFY_DONE;
4906 }
4907 
4908 static struct mlxsw_sp_rif *
4909 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
4910 			 const struct net_device *dev)
4911 {
4912 	int i;
4913 
4914 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
4915 		if (mlxsw_sp->router->rifs[i] &&
4916 		    mlxsw_sp->router->rifs[i]->dev == dev)
4917 			return mlxsw_sp->router->rifs[i];
4918 
4919 	return NULL;
4920 }
4921 
4922 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
4923 {
4924 	char ritr_pl[MLXSW_REG_RITR_LEN];
4925 	int err;
4926 
4927 	mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
4928 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
4929 	if (WARN_ON_ONCE(err))
4930 		return err;
4931 
4932 	mlxsw_reg_ritr_enable_set(ritr_pl, false);
4933 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
4934 }
4935 
4936 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
4937 					  struct mlxsw_sp_rif *rif)
4938 {
4939 	mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
4940 	mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
4941 	mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
4942 }
4943 
4944 static bool
4945 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
4946 			   unsigned long event)
4947 {
4948 	struct inet6_dev *inet6_dev;
4949 	bool addr_list_empty = true;
4950 	struct in_device *idev;
4951 
4952 	switch (event) {
4953 	case NETDEV_UP:
4954 		return rif == NULL;
4955 	case NETDEV_DOWN:
4956 		idev = __in_dev_get_rtnl(dev);
4957 		if (idev && idev->ifa_list)
4958 			addr_list_empty = false;
4959 
4960 		inet6_dev = __in6_dev_get(dev);
4961 		if (addr_list_empty && inet6_dev &&
4962 		    !list_empty(&inet6_dev->addr_list))
4963 			addr_list_empty = false;
4964 
4965 		if (rif && addr_list_empty &&
4966 		    !netif_is_l3_slave(rif->dev))
4967 			return true;
4968 		/* It is possible we already removed the RIF ourselves
4969 		 * if it was assigned to a netdev that is now a bridge
4970 		 * or LAG slave.
4971 		 */
4972 		return false;
4973 	}
4974 
4975 	return false;
4976 }
4977 
4978 static enum mlxsw_sp_rif_type
4979 mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
4980 		      const struct net_device *dev)
4981 {
4982 	enum mlxsw_sp_fid_type type;
4983 
4984 	if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
4985 		return MLXSW_SP_RIF_TYPE_IPIP_LB;
4986 
4987 	/* Otherwise RIF type is derived from the type of the underlying FID. */
4988 	if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
4989 		type = MLXSW_SP_FID_TYPE_8021Q;
4990 	else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
4991 		type = MLXSW_SP_FID_TYPE_8021Q;
4992 	else if (netif_is_bridge_master(dev))
4993 		type = MLXSW_SP_FID_TYPE_8021D;
4994 	else
4995 		type = MLXSW_SP_FID_TYPE_RFID;
4996 
4997 	return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
4998 }
4999 
5000 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index)
5001 {
5002 	int i;
5003 
5004 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
5005 		if (!mlxsw_sp->router->rifs[i]) {
5006 			*p_rif_index = i;
5007 			return 0;
5008 		}
5009 	}
5010 
5011 	return -ENOBUFS;
5012 }
5013 
5014 static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
5015 					       u16 vr_id,
5016 					       struct net_device *l3_dev)
5017 {
5018 	struct mlxsw_sp_rif *rif;
5019 
5020 	rif = kzalloc(rif_size, GFP_KERNEL);
5021 	if (!rif)
5022 		return NULL;
5023 
5024 	INIT_LIST_HEAD(&rif->nexthop_list);
5025 	INIT_LIST_HEAD(&rif->neigh_list);
5026 	ether_addr_copy(rif->addr, l3_dev->dev_addr);
5027 	rif->mtu = l3_dev->mtu;
5028 	rif->vr_id = vr_id;
5029 	rif->dev = l3_dev;
5030 	rif->rif_index = rif_index;
5031 
5032 	return rif;
5033 }
5034 
5035 struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
5036 					   u16 rif_index)
5037 {
5038 	return mlxsw_sp->router->rifs[rif_index];
5039 }
5040 
5041 u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
5042 {
5043 	return rif->rif_index;
5044 }
5045 
5046 u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
5047 {
5048 	return lb_rif->common.rif_index;
5049 }
5050 
5051 u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
5052 {
5053 	return lb_rif->ul_vr_id;
5054 }
5055 
5056 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
5057 {
5058 	return rif->dev->ifindex;
5059 }
5060 
5061 static struct mlxsw_sp_rif *
5062 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
5063 		    const struct mlxsw_sp_rif_params *params)
5064 {
5065 	u32 tb_id = l3mdev_fib_table(params->dev);
5066 	const struct mlxsw_sp_rif_ops *ops;
5067 	struct mlxsw_sp_fid *fid = NULL;
5068 	enum mlxsw_sp_rif_type type;
5069 	struct mlxsw_sp_rif *rif;
5070 	struct mlxsw_sp_vr *vr;
5071 	u16 rif_index;
5072 	int err;
5073 
5074 	type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
5075 	ops = mlxsw_sp->router->rif_ops_arr[type];
5076 
5077 	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
5078 	if (IS_ERR(vr))
5079 		return ERR_CAST(vr);
5080 	vr->rif_count++;
5081 
5082 	err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
5083 	if (err)
5084 		goto err_rif_index_alloc;
5085 
5086 	rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
5087 	if (!rif) {
5088 		err = -ENOMEM;
5089 		goto err_rif_alloc;
5090 	}
5091 	rif->mlxsw_sp = mlxsw_sp;
5092 	rif->ops = ops;
5093 
5094 	if (ops->fid_get) {
5095 		fid = ops->fid_get(rif);
5096 		if (IS_ERR(fid)) {
5097 			err = PTR_ERR(fid);
5098 			goto err_fid_get;
5099 		}
5100 		rif->fid = fid;
5101 	}
5102 
5103 	if (ops->setup)
5104 		ops->setup(rif, params);
5105 
5106 	err = ops->configure(rif);
5107 	if (err)
5108 		goto err_configure;
5109 
5110 	mlxsw_sp_rif_counters_alloc(rif);
5111 	mlxsw_sp->router->rifs[rif_index] = rif;
5112 
5113 	return rif;
5114 
5115 err_configure:
5116 	if (fid)
5117 		mlxsw_sp_fid_put(fid);
5118 err_fid_get:
5119 	kfree(rif);
5120 err_rif_alloc:
5121 err_rif_index_alloc:
5122 	vr->rif_count--;
5123 	mlxsw_sp_vr_put(vr);
5124 	return ERR_PTR(err);
5125 }
5126 
5127 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
5128 {
5129 	const struct mlxsw_sp_rif_ops *ops = rif->ops;
5130 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5131 	struct mlxsw_sp_fid *fid = rif->fid;
5132 	struct mlxsw_sp_vr *vr;
5133 
5134 	mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
5135 	vr = &mlxsw_sp->router->vrs[rif->vr_id];
5136 
5137 	mlxsw_sp->router->rifs[rif->rif_index] = NULL;
5138 	mlxsw_sp_rif_counters_free(rif);
5139 	ops->deconfigure(rif);
5140 	if (fid)
5141 		/* Loopback RIFs are not associated with a FID. */
5142 		mlxsw_sp_fid_put(fid);
5143 	kfree(rif);
5144 	vr->rif_count--;
5145 	mlxsw_sp_vr_put(vr);
5146 }
5147 
5148 static void
5149 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
5150 				 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
5151 {
5152 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5153 
5154 	params->vid = mlxsw_sp_port_vlan->vid;
5155 	params->lag = mlxsw_sp_port->lagged;
5156 	if (params->lag)
5157 		params->lag_id = mlxsw_sp_port->lag_id;
5158 	else
5159 		params->system_port = mlxsw_sp_port->local_port;
5160 }
5161 
5162 static int
5163 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
5164 			       struct net_device *l3_dev)
5165 {
5166 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5167 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
5168 	u16 vid = mlxsw_sp_port_vlan->vid;
5169 	struct mlxsw_sp_rif *rif;
5170 	struct mlxsw_sp_fid *fid;
5171 	int err;
5172 
5173 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5174 	if (!rif) {
5175 		struct mlxsw_sp_rif_params params = {
5176 			.dev = l3_dev,
5177 		};
5178 
5179 		mlxsw_sp_rif_subport_params_init(&params, mlxsw_sp_port_vlan);
5180 		rif = mlxsw_sp_rif_create(mlxsw_sp, &params);
5181 		if (IS_ERR(rif))
5182 			return PTR_ERR(rif);
5183 	}
5184 
5185 	/* FID was already created, just take a reference */
5186 	fid = rif->ops->fid_get(rif);
5187 	err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid);
5188 	if (err)
5189 		goto err_fid_port_vid_map;
5190 
5191 	err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
5192 	if (err)
5193 		goto err_port_vid_learning_set;
5194 
5195 	err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid,
5196 					BR_STATE_FORWARDING);
5197 	if (err)
5198 		goto err_port_vid_stp_set;
5199 
5200 	mlxsw_sp_port_vlan->fid = fid;
5201 
5202 	return 0;
5203 
5204 err_port_vid_stp_set:
5205 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
5206 err_port_vid_learning_set:
5207 	mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
5208 err_fid_port_vid_map:
5209 	mlxsw_sp_fid_put(fid);
5210 	return err;
5211 }
5212 
5213 void
5214 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
5215 {
5216 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
5217 	struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
5218 	u16 vid = mlxsw_sp_port_vlan->vid;
5219 
5220 	if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID))
5221 		return;
5222 
5223 	mlxsw_sp_port_vlan->fid = NULL;
5224 	mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING);
5225 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
5226 	mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
5227 	/* If router port holds the last reference on the rFID, then the
5228 	 * associated Sub-port RIF will be destroyed.
5229 	 */
5230 	mlxsw_sp_fid_put(fid);
5231 }
5232 
5233 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
5234 					     struct net_device *port_dev,
5235 					     unsigned long event, u16 vid)
5236 {
5237 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
5238 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
5239 
5240 	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
5241 	if (WARN_ON(!mlxsw_sp_port_vlan))
5242 		return -EINVAL;
5243 
5244 	switch (event) {
5245 	case NETDEV_UP:
5246 		return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
5247 						      l3_dev);
5248 	case NETDEV_DOWN:
5249 		mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
5250 		break;
5251 	}
5252 
5253 	return 0;
5254 }
5255 
5256 static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
5257 					unsigned long event)
5258 {
5259 	if (netif_is_bridge_port(port_dev) ||
5260 	    netif_is_lag_port(port_dev) ||
5261 	    netif_is_ovs_port(port_dev))
5262 		return 0;
5263 
5264 	return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event, 1);
5265 }
5266 
5267 static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
5268 					 struct net_device *lag_dev,
5269 					 unsigned long event, u16 vid)
5270 {
5271 	struct net_device *port_dev;
5272 	struct list_head *iter;
5273 	int err;
5274 
5275 	netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
5276 		if (mlxsw_sp_port_dev_check(port_dev)) {
5277 			err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
5278 								port_dev,
5279 								event, vid);
5280 			if (err)
5281 				return err;
5282 		}
5283 	}
5284 
5285 	return 0;
5286 }
5287 
5288 static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
5289 				       unsigned long event)
5290 {
5291 	if (netif_is_bridge_port(lag_dev))
5292 		return 0;
5293 
5294 	return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event, 1);
5295 }
5296 
5297 static int mlxsw_sp_inetaddr_bridge_event(struct net_device *l3_dev,
5298 					  unsigned long event)
5299 {
5300 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
5301 	struct mlxsw_sp_rif_params params = {
5302 		.dev = l3_dev,
5303 	};
5304 	struct mlxsw_sp_rif *rif;
5305 
5306 	switch (event) {
5307 	case NETDEV_UP:
5308 		rif = mlxsw_sp_rif_create(mlxsw_sp, &params);
5309 		if (IS_ERR(rif))
5310 			return PTR_ERR(rif);
5311 		break;
5312 	case NETDEV_DOWN:
5313 		rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5314 		mlxsw_sp_rif_destroy(rif);
5315 		break;
5316 	}
5317 
5318 	return 0;
5319 }
5320 
5321 static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
5322 					unsigned long event)
5323 {
5324 	struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
5325 	u16 vid = vlan_dev_vlan_id(vlan_dev);
5326 
5327 	if (netif_is_bridge_port(vlan_dev))
5328 		return 0;
5329 
5330 	if (mlxsw_sp_port_dev_check(real_dev))
5331 		return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
5332 							 event, vid);
5333 	else if (netif_is_lag_master(real_dev))
5334 		return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
5335 						     vid);
5336 	else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev))
5337 		return mlxsw_sp_inetaddr_bridge_event(vlan_dev, event);
5338 
5339 	return 0;
5340 }
5341 
5342 static int __mlxsw_sp_inetaddr_event(struct net_device *dev,
5343 				     unsigned long event)
5344 {
5345 	if (mlxsw_sp_port_dev_check(dev))
5346 		return mlxsw_sp_inetaddr_port_event(dev, event);
5347 	else if (netif_is_lag_master(dev))
5348 		return mlxsw_sp_inetaddr_lag_event(dev, event);
5349 	else if (netif_is_bridge_master(dev))
5350 		return mlxsw_sp_inetaddr_bridge_event(dev, event);
5351 	else if (is_vlan_dev(dev))
5352 		return mlxsw_sp_inetaddr_vlan_event(dev, event);
5353 	else
5354 		return 0;
5355 }
5356 
5357 int mlxsw_sp_inetaddr_event(struct notifier_block *unused,
5358 			    unsigned long event, void *ptr)
5359 {
5360 	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
5361 	struct net_device *dev = ifa->ifa_dev->dev;
5362 	struct mlxsw_sp *mlxsw_sp;
5363 	struct mlxsw_sp_rif *rif;
5364 	int err = 0;
5365 
5366 	mlxsw_sp = mlxsw_sp_lower_get(dev);
5367 	if (!mlxsw_sp)
5368 		goto out;
5369 
5370 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5371 	if (!mlxsw_sp_rif_should_config(rif, dev, event))
5372 		goto out;
5373 
5374 	err = __mlxsw_sp_inetaddr_event(dev, event);
5375 out:
5376 	return notifier_from_errno(err);
5377 }
5378 
5379 struct mlxsw_sp_inet6addr_event_work {
5380 	struct work_struct work;
5381 	struct net_device *dev;
5382 	unsigned long event;
5383 };
5384 
5385 static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
5386 {
5387 	struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
5388 		container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
5389 	struct net_device *dev = inet6addr_work->dev;
5390 	unsigned long event = inet6addr_work->event;
5391 	struct mlxsw_sp *mlxsw_sp;
5392 	struct mlxsw_sp_rif *rif;
5393 
5394 	rtnl_lock();
5395 	mlxsw_sp = mlxsw_sp_lower_get(dev);
5396 	if (!mlxsw_sp)
5397 		goto out;
5398 
5399 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5400 	if (!mlxsw_sp_rif_should_config(rif, dev, event))
5401 		goto out;
5402 
5403 	__mlxsw_sp_inetaddr_event(dev, event);
5404 out:
5405 	rtnl_unlock();
5406 	dev_put(dev);
5407 	kfree(inet6addr_work);
5408 }
5409 
5410 /* Called with rcu_read_lock() */
5411 int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
5412 			     unsigned long event, void *ptr)
5413 {
5414 	struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
5415 	struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
5416 	struct net_device *dev = if6->idev->dev;
5417 
5418 	if (!mlxsw_sp_port_dev_lower_find_rcu(dev))
5419 		return NOTIFY_DONE;
5420 
5421 	inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
5422 	if (!inet6addr_work)
5423 		return NOTIFY_BAD;
5424 
5425 	INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
5426 	inet6addr_work->dev = dev;
5427 	inet6addr_work->event = event;
5428 	dev_hold(dev);
5429 	mlxsw_core_schedule_work(&inet6addr_work->work);
5430 
5431 	return NOTIFY_DONE;
5432 }
5433 
5434 static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
5435 			     const char *mac, int mtu)
5436 {
5437 	char ritr_pl[MLXSW_REG_RITR_LEN];
5438 	int err;
5439 
5440 	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
5441 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5442 	if (err)
5443 		return err;
5444 
5445 	mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
5446 	mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
5447 	mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
5448 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5449 }
5450 
5451 int mlxsw_sp_netdevice_router_port_event(struct net_device *dev)
5452 {
5453 	struct mlxsw_sp *mlxsw_sp;
5454 	struct mlxsw_sp_rif *rif;
5455 	u16 fid_index;
5456 	int err;
5457 
5458 	mlxsw_sp = mlxsw_sp_lower_get(dev);
5459 	if (!mlxsw_sp)
5460 		return 0;
5461 
5462 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5463 	if (!rif)
5464 		return 0;
5465 	fid_index = mlxsw_sp_fid_index(rif->fid);
5466 
5467 	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false);
5468 	if (err)
5469 		return err;
5470 
5471 	err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
5472 				dev->mtu);
5473 	if (err)
5474 		goto err_rif_edit;
5475 
5476 	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true);
5477 	if (err)
5478 		goto err_rif_fdb_op;
5479 
5480 	ether_addr_copy(rif->addr, dev->dev_addr);
5481 	rif->mtu = dev->mtu;
5482 
5483 	netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
5484 
5485 	return 0;
5486 
5487 err_rif_fdb_op:
5488 	mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu);
5489 err_rif_edit:
5490 	mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true);
5491 	return err;
5492 }
5493 
5494 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
5495 				  struct net_device *l3_dev)
5496 {
5497 	struct mlxsw_sp_rif *rif;
5498 
5499 	/* If netdev is already associated with a RIF, then we need to
5500 	 * destroy it and create a new one with the new virtual router ID.
5501 	 */
5502 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5503 	if (rif)
5504 		__mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
5505 
5506 	return __mlxsw_sp_inetaddr_event(l3_dev, NETDEV_UP);
5507 }
5508 
5509 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
5510 				    struct net_device *l3_dev)
5511 {
5512 	struct mlxsw_sp_rif *rif;
5513 
5514 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
5515 	if (!rif)
5516 		return;
5517 	__mlxsw_sp_inetaddr_event(l3_dev, NETDEV_DOWN);
5518 }
5519 
5520 int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
5521 				 struct netdev_notifier_changeupper_info *info)
5522 {
5523 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
5524 	int err = 0;
5525 
5526 	if (!mlxsw_sp)
5527 		return 0;
5528 
5529 	switch (event) {
5530 	case NETDEV_PRECHANGEUPPER:
5531 		return 0;
5532 	case NETDEV_CHANGEUPPER:
5533 		if (info->linking)
5534 			err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev);
5535 		else
5536 			mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
5537 		break;
5538 	}
5539 
5540 	return err;
5541 }
5542 
5543 static struct mlxsw_sp_rif_subport *
5544 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
5545 {
5546 	return container_of(rif, struct mlxsw_sp_rif_subport, common);
5547 }
5548 
5549 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
5550 				       const struct mlxsw_sp_rif_params *params)
5551 {
5552 	struct mlxsw_sp_rif_subport *rif_subport;
5553 
5554 	rif_subport = mlxsw_sp_rif_subport_rif(rif);
5555 	rif_subport->vid = params->vid;
5556 	rif_subport->lag = params->lag;
5557 	if (params->lag)
5558 		rif_subport->lag_id = params->lag_id;
5559 	else
5560 		rif_subport->system_port = params->system_port;
5561 }
5562 
5563 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
5564 {
5565 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5566 	struct mlxsw_sp_rif_subport *rif_subport;
5567 	char ritr_pl[MLXSW_REG_RITR_LEN];
5568 
5569 	rif_subport = mlxsw_sp_rif_subport_rif(rif);
5570 	mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
5571 			    rif->rif_index, rif->vr_id, rif->dev->mtu);
5572 	mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
5573 	mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
5574 				  rif_subport->lag ? rif_subport->lag_id :
5575 						     rif_subport->system_port,
5576 				  rif_subport->vid);
5577 
5578 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5579 }
5580 
5581 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif)
5582 {
5583 	int err;
5584 
5585 	err = mlxsw_sp_rif_subport_op(rif, true);
5586 	if (err)
5587 		return err;
5588 
5589 	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5590 				  mlxsw_sp_fid_index(rif->fid), true);
5591 	if (err)
5592 		goto err_rif_fdb_op;
5593 
5594 	mlxsw_sp_fid_rif_set(rif->fid, rif);
5595 	return 0;
5596 
5597 err_rif_fdb_op:
5598 	mlxsw_sp_rif_subport_op(rif, false);
5599 	return err;
5600 }
5601 
5602 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
5603 {
5604 	struct mlxsw_sp_fid *fid = rif->fid;
5605 
5606 	mlxsw_sp_fid_rif_set(fid, NULL);
5607 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5608 			    mlxsw_sp_fid_index(fid), false);
5609 	mlxsw_sp_rif_subport_op(rif, false);
5610 }
5611 
5612 static struct mlxsw_sp_fid *
5613 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif)
5614 {
5615 	return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index);
5616 }
5617 
5618 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
5619 	.type			= MLXSW_SP_RIF_TYPE_SUBPORT,
5620 	.rif_size		= sizeof(struct mlxsw_sp_rif_subport),
5621 	.setup			= mlxsw_sp_rif_subport_setup,
5622 	.configure		= mlxsw_sp_rif_subport_configure,
5623 	.deconfigure		= mlxsw_sp_rif_subport_deconfigure,
5624 	.fid_get		= mlxsw_sp_rif_subport_fid_get,
5625 };
5626 
5627 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif,
5628 				    enum mlxsw_reg_ritr_if_type type,
5629 				    u16 vid_fid, bool enable)
5630 {
5631 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5632 	char ritr_pl[MLXSW_REG_RITR_LEN];
5633 
5634 	mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
5635 			    rif->dev->mtu);
5636 	mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
5637 	mlxsw_reg_ritr_fid_set(ritr_pl, type, vid_fid);
5638 
5639 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5640 }
5641 
5642 static u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
5643 {
5644 	return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
5645 }
5646 
5647 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif)
5648 {
5649 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5650 	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
5651 	int err;
5652 
5653 	err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, true);
5654 	if (err)
5655 		return err;
5656 
5657 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5658 				     mlxsw_sp_router_port(mlxsw_sp), true);
5659 	if (err)
5660 		goto err_fid_mc_flood_set;
5661 
5662 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5663 				     mlxsw_sp_router_port(mlxsw_sp), true);
5664 	if (err)
5665 		goto err_fid_bc_flood_set;
5666 
5667 	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5668 				  mlxsw_sp_fid_index(rif->fid), true);
5669 	if (err)
5670 		goto err_rif_fdb_op;
5671 
5672 	mlxsw_sp_fid_rif_set(rif->fid, rif);
5673 	return 0;
5674 
5675 err_rif_fdb_op:
5676 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5677 			       mlxsw_sp_router_port(mlxsw_sp), false);
5678 err_fid_bc_flood_set:
5679 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5680 			       mlxsw_sp_router_port(mlxsw_sp), false);
5681 err_fid_mc_flood_set:
5682 	mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false);
5683 	return err;
5684 }
5685 
5686 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
5687 {
5688 	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
5689 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5690 	struct mlxsw_sp_fid *fid = rif->fid;
5691 
5692 	mlxsw_sp_fid_rif_set(fid, NULL);
5693 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5694 			    mlxsw_sp_fid_index(fid), false);
5695 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5696 			       mlxsw_sp_router_port(mlxsw_sp), false);
5697 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5698 			       mlxsw_sp_router_port(mlxsw_sp), false);
5699 	mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false);
5700 }
5701 
5702 static struct mlxsw_sp_fid *
5703 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif)
5704 {
5705 	u16 vid = is_vlan_dev(rif->dev) ? vlan_dev_vlan_id(rif->dev) : 1;
5706 
5707 	return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid);
5708 }
5709 
5710 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = {
5711 	.type			= MLXSW_SP_RIF_TYPE_VLAN,
5712 	.rif_size		= sizeof(struct mlxsw_sp_rif),
5713 	.configure		= mlxsw_sp_rif_vlan_configure,
5714 	.deconfigure		= mlxsw_sp_rif_vlan_deconfigure,
5715 	.fid_get		= mlxsw_sp_rif_vlan_fid_get,
5716 };
5717 
5718 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif)
5719 {
5720 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5721 	u16 fid_index = mlxsw_sp_fid_index(rif->fid);
5722 	int err;
5723 
5724 	err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index,
5725 				       true);
5726 	if (err)
5727 		return err;
5728 
5729 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5730 				     mlxsw_sp_router_port(mlxsw_sp), true);
5731 	if (err)
5732 		goto err_fid_mc_flood_set;
5733 
5734 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5735 				     mlxsw_sp_router_port(mlxsw_sp), true);
5736 	if (err)
5737 		goto err_fid_bc_flood_set;
5738 
5739 	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5740 				  mlxsw_sp_fid_index(rif->fid), true);
5741 	if (err)
5742 		goto err_rif_fdb_op;
5743 
5744 	mlxsw_sp_fid_rif_set(rif->fid, rif);
5745 	return 0;
5746 
5747 err_rif_fdb_op:
5748 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5749 			       mlxsw_sp_router_port(mlxsw_sp), false);
5750 err_fid_bc_flood_set:
5751 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5752 			       mlxsw_sp_router_port(mlxsw_sp), false);
5753 err_fid_mc_flood_set:
5754 	mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
5755 	return err;
5756 }
5757 
5758 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
5759 {
5760 	u16 fid_index = mlxsw_sp_fid_index(rif->fid);
5761 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5762 	struct mlxsw_sp_fid *fid = rif->fid;
5763 
5764 	mlxsw_sp_fid_rif_set(fid, NULL);
5765 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
5766 			    mlxsw_sp_fid_index(fid), false);
5767 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
5768 			       mlxsw_sp_router_port(mlxsw_sp), false);
5769 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
5770 			       mlxsw_sp_router_port(mlxsw_sp), false);
5771 	mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
5772 }
5773 
5774 static struct mlxsw_sp_fid *
5775 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif)
5776 {
5777 	return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
5778 }
5779 
5780 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
5781 	.type			= MLXSW_SP_RIF_TYPE_FID,
5782 	.rif_size		= sizeof(struct mlxsw_sp_rif),
5783 	.configure		= mlxsw_sp_rif_fid_configure,
5784 	.deconfigure		= mlxsw_sp_rif_fid_deconfigure,
5785 	.fid_get		= mlxsw_sp_rif_fid_fid_get,
5786 };
5787 
5788 static struct mlxsw_sp_rif_ipip_lb *
5789 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
5790 {
5791 	return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
5792 }
5793 
5794 static void
5795 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
5796 			   const struct mlxsw_sp_rif_params *params)
5797 {
5798 	struct mlxsw_sp_rif_params_ipip_lb *params_lb;
5799 	struct mlxsw_sp_rif_ipip_lb *rif_lb;
5800 
5801 	params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
5802 				 common);
5803 	rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
5804 	rif_lb->lb_config = params_lb->lb_config;
5805 }
5806 
5807 static int
5808 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
5809 			struct mlxsw_sp_vr *ul_vr, bool enable)
5810 {
5811 	struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
5812 	struct mlxsw_sp_rif *rif = &lb_rif->common;
5813 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5814 	char ritr_pl[MLXSW_REG_RITR_LEN];
5815 	u32 saddr4;
5816 
5817 	switch (lb_cf.ul_protocol) {
5818 	case MLXSW_SP_L3_PROTO_IPV4:
5819 		saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
5820 		mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
5821 				    rif->rif_index, rif->vr_id, rif->dev->mtu);
5822 		mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
5823 			    MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
5824 			    ul_vr->id, saddr4, lb_cf.okey);
5825 		break;
5826 
5827 	case MLXSW_SP_L3_PROTO_IPV6:
5828 		return -EAFNOSUPPORT;
5829 	}
5830 
5831 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5832 }
5833 
5834 static int
5835 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
5836 {
5837 	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5838 	u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
5839 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5840 	struct mlxsw_sp_vr *ul_vr;
5841 	int err;
5842 
5843 	ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id);
5844 	if (IS_ERR(ul_vr))
5845 		return PTR_ERR(ul_vr);
5846 
5847 	err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
5848 	if (err)
5849 		goto err_loopback_op;
5850 
5851 	lb_rif->ul_vr_id = ul_vr->id;
5852 	++ul_vr->rif_count;
5853 	return 0;
5854 
5855 err_loopback_op:
5856 	mlxsw_sp_vr_put(ul_vr);
5857 	return err;
5858 }
5859 
5860 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
5861 {
5862 	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5863 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5864 	struct mlxsw_sp_vr *ul_vr;
5865 
5866 	ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
5867 	mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false);
5868 
5869 	--ul_vr->rif_count;
5870 	mlxsw_sp_vr_put(ul_vr);
5871 }
5872 
5873 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = {
5874 	.type			= MLXSW_SP_RIF_TYPE_IPIP_LB,
5875 	.rif_size		= sizeof(struct mlxsw_sp_rif_ipip_lb),
5876 	.setup                  = mlxsw_sp_rif_ipip_lb_setup,
5877 	.configure		= mlxsw_sp_rif_ipip_lb_configure,
5878 	.deconfigure		= mlxsw_sp_rif_ipip_lb_deconfigure,
5879 };
5880 
5881 static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = {
5882 	[MLXSW_SP_RIF_TYPE_SUBPORT]	= &mlxsw_sp_rif_subport_ops,
5883 	[MLXSW_SP_RIF_TYPE_VLAN]	= &mlxsw_sp_rif_vlan_ops,
5884 	[MLXSW_SP_RIF_TYPE_FID]		= &mlxsw_sp_rif_fid_ops,
5885 	[MLXSW_SP_RIF_TYPE_IPIP_LB]	= &mlxsw_sp_rif_ipip_lb_ops,
5886 };
5887 
5888 static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
5889 {
5890 	u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
5891 
5892 	mlxsw_sp->router->rifs = kcalloc(max_rifs,
5893 					 sizeof(struct mlxsw_sp_rif *),
5894 					 GFP_KERNEL);
5895 	if (!mlxsw_sp->router->rifs)
5896 		return -ENOMEM;
5897 
5898 	mlxsw_sp->router->rif_ops_arr = mlxsw_sp_rif_ops_arr;
5899 
5900 	return 0;
5901 }
5902 
5903 static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
5904 {
5905 	int i;
5906 
5907 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
5908 		WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
5909 
5910 	kfree(mlxsw_sp->router->rifs);
5911 }
5912 
5913 static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
5914 {
5915 	mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr;
5916 	INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);
5917 	return 0;
5918 }
5919 
5920 static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp)
5921 {
5922 	WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list));
5923 }
5924 
5925 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
5926 {
5927 	struct mlxsw_sp_router *router;
5928 
5929 	/* Flush pending FIB notifications and then flush the device's
5930 	 * table before requesting another dump. The FIB notification
5931 	 * block is unregistered, so no need to take RTNL.
5932 	 */
5933 	mlxsw_core_flush_owq();
5934 	router = container_of(nb, struct mlxsw_sp_router, fib_nb);
5935 	mlxsw_sp_router_fib_flush(router->mlxsw_sp);
5936 }
5937 
5938 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
5939 {
5940 	char rgcr_pl[MLXSW_REG_RGCR_LEN];
5941 	u64 max_rifs;
5942 	int err;
5943 
5944 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
5945 		return -EIO;
5946 	max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
5947 
5948 	mlxsw_reg_rgcr_pack(rgcr_pl, true, true);
5949 	mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
5950 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
5951 	if (err)
5952 		return err;
5953 	return 0;
5954 }
5955 
5956 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
5957 {
5958 	char rgcr_pl[MLXSW_REG_RGCR_LEN];
5959 
5960 	mlxsw_reg_rgcr_pack(rgcr_pl, false, false);
5961 	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
5962 }
5963 
5964 int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
5965 {
5966 	struct mlxsw_sp_router *router;
5967 	int err;
5968 
5969 	router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
5970 	if (!router)
5971 		return -ENOMEM;
5972 	mlxsw_sp->router = router;
5973 	router->mlxsw_sp = mlxsw_sp;
5974 
5975 	INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
5976 	err = __mlxsw_sp_router_init(mlxsw_sp);
5977 	if (err)
5978 		goto err_router_init;
5979 
5980 	err = mlxsw_sp_rifs_init(mlxsw_sp);
5981 	if (err)
5982 		goto err_rifs_init;
5983 
5984 	err = mlxsw_sp_ipips_init(mlxsw_sp);
5985 	if (err)
5986 		goto err_ipips_init;
5987 
5988 	err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
5989 			      &mlxsw_sp_nexthop_ht_params);
5990 	if (err)
5991 		goto err_nexthop_ht_init;
5992 
5993 	err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht,
5994 			      &mlxsw_sp_nexthop_group_ht_params);
5995 	if (err)
5996 		goto err_nexthop_group_ht_init;
5997 
5998 	err = mlxsw_sp_lpm_init(mlxsw_sp);
5999 	if (err)
6000 		goto err_lpm_init;
6001 
6002 	err = mlxsw_sp_vrs_init(mlxsw_sp);
6003 	if (err)
6004 		goto err_vrs_init;
6005 
6006 	err = mlxsw_sp_neigh_init(mlxsw_sp);
6007 	if (err)
6008 		goto err_neigh_init;
6009 
6010 	mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
6011 	err = register_fib_notifier(&mlxsw_sp->router->fib_nb,
6012 				    mlxsw_sp_router_fib_dump_flush);
6013 	if (err)
6014 		goto err_register_fib_notifier;
6015 
6016 	return 0;
6017 
6018 err_register_fib_notifier:
6019 	mlxsw_sp_neigh_fini(mlxsw_sp);
6020 err_neigh_init:
6021 	mlxsw_sp_vrs_fini(mlxsw_sp);
6022 err_vrs_init:
6023 	mlxsw_sp_lpm_fini(mlxsw_sp);
6024 err_lpm_init:
6025 	rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
6026 err_nexthop_group_ht_init:
6027 	rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
6028 err_nexthop_ht_init:
6029 	mlxsw_sp_ipips_fini(mlxsw_sp);
6030 err_ipips_init:
6031 	mlxsw_sp_rifs_fini(mlxsw_sp);
6032 err_rifs_init:
6033 	__mlxsw_sp_router_fini(mlxsw_sp);
6034 err_router_init:
6035 	kfree(mlxsw_sp->router);
6036 	return err;
6037 }
6038 
6039 void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
6040 {
6041 	unregister_fib_notifier(&mlxsw_sp->router->fib_nb);
6042 	mlxsw_sp_neigh_fini(mlxsw_sp);
6043 	mlxsw_sp_vrs_fini(mlxsw_sp);
6044 	mlxsw_sp_lpm_fini(mlxsw_sp);
6045 	rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
6046 	rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
6047 	mlxsw_sp_ipips_fini(mlxsw_sp);
6048 	mlxsw_sp_rifs_fini(mlxsw_sp);
6049 	__mlxsw_sp_router_fini(mlxsw_sp);
6050 	kfree(mlxsw_sp->router);
6051 }
6052