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