xref: /linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c (revision 52990390f91c1c39ca742fc8f390b29891d95127)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
3 
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/rhashtable.h>
7 #include <linux/bitops.h>
8 #include <linux/in6.h>
9 #include <linux/notifier.h>
10 #include <linux/inetdevice.h>
11 #include <linux/netdevice.h>
12 #include <linux/if_bridge.h>
13 #include <linux/socket.h>
14 #include <linux/route.h>
15 #include <linux/gcd.h>
16 #include <linux/if_macvlan.h>
17 #include <linux/refcount.h>
18 #include <linux/jhash.h>
19 #include <linux/net_namespace.h>
20 #include <linux/mutex.h>
21 #include <linux/genalloc.h>
22 #include <net/netevent.h>
23 #include <net/neighbour.h>
24 #include <net/arp.h>
25 #include <net/inet_dscp.h>
26 #include <net/ip_fib.h>
27 #include <net/ip6_fib.h>
28 #include <net/nexthop.h>
29 #include <net/fib_rules.h>
30 #include <net/ip_tunnels.h>
31 #include <net/l3mdev.h>
32 #include <net/addrconf.h>
33 #include <net/ndisc.h>
34 #include <net/ipv6.h>
35 #include <net/fib_notifier.h>
36 #include <net/switchdev.h>
37 
38 #include "spectrum.h"
39 #include "core.h"
40 #include "reg.h"
41 #include "spectrum_cnt.h"
42 #include "spectrum_dpipe.h"
43 #include "spectrum_ipip.h"
44 #include "spectrum_mr.h"
45 #include "spectrum_mr_tcam.h"
46 #include "spectrum_router.h"
47 #include "spectrum_span.h"
48 
49 struct mlxsw_sp_fib;
50 struct mlxsw_sp_vr;
51 struct mlxsw_sp_lpm_tree;
52 struct mlxsw_sp_rif_ops;
53 
54 struct mlxsw_sp_rif {
55 	struct list_head nexthop_list;
56 	struct list_head neigh_list;
57 	struct net_device *dev; /* NULL for underlay RIF */
58 	struct mlxsw_sp_fid *fid;
59 	unsigned char addr[ETH_ALEN];
60 	int mtu;
61 	u16 rif_index;
62 	u8 mac_profile_id;
63 	u8 rif_entries;
64 	u16 vr_id;
65 	const struct mlxsw_sp_rif_ops *ops;
66 	struct mlxsw_sp *mlxsw_sp;
67 
68 	unsigned int counter_ingress;
69 	bool counter_ingress_valid;
70 	unsigned int counter_egress;
71 	bool counter_egress_valid;
72 };
73 
74 struct mlxsw_sp_rif_params {
75 	struct net_device *dev;
76 	union {
77 		u16 system_port;
78 		u16 lag_id;
79 	};
80 	u16 vid;
81 	bool lag;
82 	bool double_entry;
83 };
84 
85 struct mlxsw_sp_rif_subport {
86 	struct mlxsw_sp_rif common;
87 	refcount_t ref_count;
88 	union {
89 		u16 system_port;
90 		u16 lag_id;
91 	};
92 	u16 vid;
93 	bool lag;
94 };
95 
96 struct mlxsw_sp_rif_ipip_lb {
97 	struct mlxsw_sp_rif common;
98 	struct mlxsw_sp_rif_ipip_lb_config lb_config;
99 	u16 ul_vr_id; /* Reserved for Spectrum-2. */
100 	u16 ul_rif_id; /* Reserved for Spectrum. */
101 };
102 
103 struct mlxsw_sp_rif_params_ipip_lb {
104 	struct mlxsw_sp_rif_params common;
105 	struct mlxsw_sp_rif_ipip_lb_config lb_config;
106 };
107 
108 struct mlxsw_sp_rif_ops {
109 	enum mlxsw_sp_rif_type type;
110 	size_t rif_size;
111 
112 	void (*setup)(struct mlxsw_sp_rif *rif,
113 		      const struct mlxsw_sp_rif_params *params);
114 	int (*configure)(struct mlxsw_sp_rif *rif,
115 			 struct netlink_ext_ack *extack);
116 	void (*deconfigure)(struct mlxsw_sp_rif *rif);
117 	struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif,
118 					 struct netlink_ext_ack *extack);
119 	void (*fdb_del)(struct mlxsw_sp_rif *rif, const char *mac);
120 };
121 
122 struct mlxsw_sp_rif_mac_profile {
123 	unsigned char mac_prefix[ETH_ALEN];
124 	refcount_t ref_count;
125 	u8 id;
126 };
127 
128 struct mlxsw_sp_router_ops {
129 	int (*init)(struct mlxsw_sp *mlxsw_sp);
130 	int (*ipips_init)(struct mlxsw_sp *mlxsw_sp);
131 };
132 
133 static struct mlxsw_sp_rif *
134 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
135 			 const struct net_device *dev);
136 static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif);
137 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree);
138 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
139 				  struct mlxsw_sp_lpm_tree *lpm_tree);
140 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
141 				     const struct mlxsw_sp_fib *fib,
142 				     u8 tree_id);
143 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
144 				       const struct mlxsw_sp_fib *fib);
145 
146 static unsigned int *
147 mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif *rif,
148 			   enum mlxsw_sp_rif_counter_dir dir)
149 {
150 	switch (dir) {
151 	case MLXSW_SP_RIF_COUNTER_EGRESS:
152 		return &rif->counter_egress;
153 	case MLXSW_SP_RIF_COUNTER_INGRESS:
154 		return &rif->counter_ingress;
155 	}
156 	return NULL;
157 }
158 
159 static bool
160 mlxsw_sp_rif_counter_valid_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_valid;
166 	case MLXSW_SP_RIF_COUNTER_INGRESS:
167 		return rif->counter_ingress_valid;
168 	}
169 	return false;
170 }
171 
172 static void
173 mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif *rif,
174 			       enum mlxsw_sp_rif_counter_dir dir,
175 			       bool valid)
176 {
177 	switch (dir) {
178 	case MLXSW_SP_RIF_COUNTER_EGRESS:
179 		rif->counter_egress_valid = valid;
180 		break;
181 	case MLXSW_SP_RIF_COUNTER_INGRESS:
182 		rif->counter_ingress_valid = valid;
183 		break;
184 	}
185 }
186 
187 static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
188 				     unsigned int counter_index, bool enable,
189 				     enum mlxsw_sp_rif_counter_dir dir)
190 {
191 	char ritr_pl[MLXSW_REG_RITR_LEN];
192 	bool is_egress = false;
193 	int err;
194 
195 	if (dir == MLXSW_SP_RIF_COUNTER_EGRESS)
196 		is_egress = true;
197 	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
198 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
199 	if (err)
200 		return err;
201 
202 	mlxsw_reg_ritr_counter_pack(ritr_pl, counter_index, enable,
203 				    is_egress);
204 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
205 }
206 
207 int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
208 				   struct mlxsw_sp_rif *rif,
209 				   enum mlxsw_sp_rif_counter_dir dir, u64 *cnt)
210 {
211 	char ricnt_pl[MLXSW_REG_RICNT_LEN];
212 	unsigned int *p_counter_index;
213 	bool valid;
214 	int err;
215 
216 	valid = mlxsw_sp_rif_counter_valid_get(rif, dir);
217 	if (!valid)
218 		return -EINVAL;
219 
220 	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
221 	if (!p_counter_index)
222 		return -EINVAL;
223 	mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
224 			     MLXSW_REG_RICNT_OPCODE_NOP);
225 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
226 	if (err)
227 		return err;
228 	*cnt = mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl);
229 	return 0;
230 }
231 
232 struct mlxsw_sp_rif_counter_set_basic {
233 	u64 good_unicast_packets;
234 	u64 good_multicast_packets;
235 	u64 good_broadcast_packets;
236 	u64 good_unicast_bytes;
237 	u64 good_multicast_bytes;
238 	u64 good_broadcast_bytes;
239 	u64 error_packets;
240 	u64 discard_packets;
241 	u64 error_bytes;
242 	u64 discard_bytes;
243 };
244 
245 static int
246 mlxsw_sp_rif_counter_fetch_clear(struct mlxsw_sp_rif *rif,
247 				 enum mlxsw_sp_rif_counter_dir dir,
248 				 struct mlxsw_sp_rif_counter_set_basic *set)
249 {
250 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
251 	char ricnt_pl[MLXSW_REG_RICNT_LEN];
252 	unsigned int *p_counter_index;
253 	int err;
254 
255 	if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
256 		return -EINVAL;
257 
258 	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
259 	if (!p_counter_index)
260 		return -EINVAL;
261 
262 	mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
263 			     MLXSW_REG_RICNT_OPCODE_CLEAR);
264 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
265 	if (err)
266 		return err;
267 
268 	if (!set)
269 		return 0;
270 
271 #define MLXSW_SP_RIF_COUNTER_EXTRACT(NAME)				\
272 		(set->NAME = mlxsw_reg_ricnt_ ## NAME ## _get(ricnt_pl))
273 
274 	MLXSW_SP_RIF_COUNTER_EXTRACT(good_unicast_packets);
275 	MLXSW_SP_RIF_COUNTER_EXTRACT(good_multicast_packets);
276 	MLXSW_SP_RIF_COUNTER_EXTRACT(good_broadcast_packets);
277 	MLXSW_SP_RIF_COUNTER_EXTRACT(good_unicast_bytes);
278 	MLXSW_SP_RIF_COUNTER_EXTRACT(good_multicast_bytes);
279 	MLXSW_SP_RIF_COUNTER_EXTRACT(good_broadcast_bytes);
280 	MLXSW_SP_RIF_COUNTER_EXTRACT(error_packets);
281 	MLXSW_SP_RIF_COUNTER_EXTRACT(discard_packets);
282 	MLXSW_SP_RIF_COUNTER_EXTRACT(error_bytes);
283 	MLXSW_SP_RIF_COUNTER_EXTRACT(discard_bytes);
284 
285 #undef MLXSW_SP_RIF_COUNTER_EXTRACT
286 
287 	return 0;
288 }
289 
290 static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp *mlxsw_sp,
291 				      unsigned int counter_index)
292 {
293 	char ricnt_pl[MLXSW_REG_RICNT_LEN];
294 
295 	mlxsw_reg_ricnt_pack(ricnt_pl, counter_index,
296 			     MLXSW_REG_RICNT_OPCODE_CLEAR);
297 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
298 }
299 
300 int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp_rif *rif,
301 			       enum mlxsw_sp_rif_counter_dir dir)
302 {
303 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
304 	unsigned int *p_counter_index;
305 	int err;
306 
307 	if (mlxsw_sp_rif_counter_valid_get(rif, dir))
308 		return 0;
309 
310 	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
311 	if (!p_counter_index)
312 		return -EINVAL;
313 
314 	err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
315 				     p_counter_index);
316 	if (err)
317 		return err;
318 
319 	err = mlxsw_sp_rif_counter_clear(mlxsw_sp, *p_counter_index);
320 	if (err)
321 		goto err_counter_clear;
322 
323 	err = mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
324 					*p_counter_index, true, dir);
325 	if (err)
326 		goto err_counter_edit;
327 	mlxsw_sp_rif_counter_valid_set(rif, dir, true);
328 	return 0;
329 
330 err_counter_edit:
331 err_counter_clear:
332 	mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
333 			      *p_counter_index);
334 	return err;
335 }
336 
337 void mlxsw_sp_rif_counter_free(struct mlxsw_sp_rif *rif,
338 			       enum mlxsw_sp_rif_counter_dir dir)
339 {
340 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
341 	unsigned int *p_counter_index;
342 
343 	if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
344 		return;
345 
346 	p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
347 	if (WARN_ON(!p_counter_index))
348 		return;
349 	mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
350 				  *p_counter_index, false, dir);
351 	mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
352 			      *p_counter_index);
353 	mlxsw_sp_rif_counter_valid_set(rif, dir, false);
354 }
355 
356 static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif *rif)
357 {
358 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
359 	struct devlink *devlink;
360 
361 	devlink = priv_to_devlink(mlxsw_sp->core);
362 	if (!devlink_dpipe_table_counter_enabled(devlink,
363 						 MLXSW_SP_DPIPE_TABLE_NAME_ERIF))
364 		return;
365 	mlxsw_sp_rif_counter_alloc(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
366 }
367 
368 static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif *rif)
369 {
370 	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
371 }
372 
373 #define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1)
374 
375 struct mlxsw_sp_prefix_usage {
376 	DECLARE_BITMAP(b, MLXSW_SP_PREFIX_COUNT);
377 };
378 
379 #define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
380 	for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
381 
382 static bool
383 mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage *prefix_usage1,
384 			 struct mlxsw_sp_prefix_usage *prefix_usage2)
385 {
386 	return !memcmp(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
387 }
388 
389 static void
390 mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage *prefix_usage1,
391 			  struct mlxsw_sp_prefix_usage *prefix_usage2)
392 {
393 	memcpy(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
394 }
395 
396 static void
397 mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage,
398 			  unsigned char prefix_len)
399 {
400 	set_bit(prefix_len, prefix_usage->b);
401 }
402 
403 static void
404 mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
405 			    unsigned char prefix_len)
406 {
407 	clear_bit(prefix_len, prefix_usage->b);
408 }
409 
410 struct mlxsw_sp_fib_key {
411 	unsigned char addr[sizeof(struct in6_addr)];
412 	unsigned char prefix_len;
413 };
414 
415 enum mlxsw_sp_fib_entry_type {
416 	MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
417 	MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
418 	MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
419 	MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE,
420 	MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE,
421 
422 	/* This is a special case of local delivery, where a packet should be
423 	 * decapsulated on reception. Note that there is no corresponding ENCAP,
424 	 * because that's a type of next hop, not of FIB entry. (There can be
425 	 * several next hops in a REMOTE entry, and some of them may be
426 	 * encapsulating entries.)
427 	 */
428 	MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP,
429 	MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP,
430 };
431 
432 struct mlxsw_sp_nexthop_group_info;
433 struct mlxsw_sp_nexthop_group;
434 struct mlxsw_sp_fib_entry;
435 
436 struct mlxsw_sp_fib_node {
437 	struct mlxsw_sp_fib_entry *fib_entry;
438 	struct list_head list;
439 	struct rhash_head ht_node;
440 	struct mlxsw_sp_fib *fib;
441 	struct mlxsw_sp_fib_key key;
442 };
443 
444 struct mlxsw_sp_fib_entry_decap {
445 	struct mlxsw_sp_ipip_entry *ipip_entry;
446 	u32 tunnel_index;
447 };
448 
449 struct mlxsw_sp_fib_entry {
450 	struct mlxsw_sp_fib_node *fib_node;
451 	enum mlxsw_sp_fib_entry_type type;
452 	struct list_head nexthop_group_node;
453 	struct mlxsw_sp_nexthop_group *nh_group;
454 	struct mlxsw_sp_fib_entry_decap decap; /* Valid for decap entries. */
455 };
456 
457 struct mlxsw_sp_fib4_entry {
458 	struct mlxsw_sp_fib_entry common;
459 	struct fib_info *fi;
460 	u32 tb_id;
461 	dscp_t dscp;
462 	u8 type;
463 };
464 
465 struct mlxsw_sp_fib6_entry {
466 	struct mlxsw_sp_fib_entry common;
467 	struct list_head rt6_list;
468 	unsigned int nrt6;
469 };
470 
471 struct mlxsw_sp_rt6 {
472 	struct list_head list;
473 	struct fib6_info *rt;
474 };
475 
476 struct mlxsw_sp_lpm_tree {
477 	u8 id; /* tree ID */
478 	unsigned int ref_count;
479 	enum mlxsw_sp_l3proto proto;
480 	unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
481 	struct mlxsw_sp_prefix_usage prefix_usage;
482 };
483 
484 struct mlxsw_sp_fib {
485 	struct rhashtable ht;
486 	struct list_head node_list;
487 	struct mlxsw_sp_vr *vr;
488 	struct mlxsw_sp_lpm_tree *lpm_tree;
489 	enum mlxsw_sp_l3proto proto;
490 };
491 
492 struct mlxsw_sp_vr {
493 	u16 id; /* virtual router ID */
494 	u32 tb_id; /* kernel fib table id */
495 	unsigned int rif_count;
496 	struct mlxsw_sp_fib *fib4;
497 	struct mlxsw_sp_fib *fib6;
498 	struct mlxsw_sp_mr_table *mr_table[MLXSW_SP_L3_PROTO_MAX];
499 	struct mlxsw_sp_rif *ul_rif;
500 	refcount_t ul_rif_refcnt;
501 };
502 
503 static const struct rhashtable_params mlxsw_sp_fib_ht_params;
504 
505 static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp *mlxsw_sp,
506 						struct mlxsw_sp_vr *vr,
507 						enum mlxsw_sp_l3proto proto)
508 {
509 	struct mlxsw_sp_lpm_tree *lpm_tree;
510 	struct mlxsw_sp_fib *fib;
511 	int err;
512 
513 	lpm_tree = mlxsw_sp->router->lpm.proto_trees[proto];
514 	fib = kzalloc(sizeof(*fib), GFP_KERNEL);
515 	if (!fib)
516 		return ERR_PTR(-ENOMEM);
517 	err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params);
518 	if (err)
519 		goto err_rhashtable_init;
520 	INIT_LIST_HEAD(&fib->node_list);
521 	fib->proto = proto;
522 	fib->vr = vr;
523 	fib->lpm_tree = lpm_tree;
524 	mlxsw_sp_lpm_tree_hold(lpm_tree);
525 	err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, lpm_tree->id);
526 	if (err)
527 		goto err_lpm_tree_bind;
528 	return fib;
529 
530 err_lpm_tree_bind:
531 	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
532 err_rhashtable_init:
533 	kfree(fib);
534 	return ERR_PTR(err);
535 }
536 
537 static void mlxsw_sp_fib_destroy(struct mlxsw_sp *mlxsw_sp,
538 				 struct mlxsw_sp_fib *fib)
539 {
540 	mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
541 	mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree);
542 	WARN_ON(!list_empty(&fib->node_list));
543 	rhashtable_destroy(&fib->ht);
544 	kfree(fib);
545 }
546 
547 static struct mlxsw_sp_lpm_tree *
548 mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
549 {
550 	static struct mlxsw_sp_lpm_tree *lpm_tree;
551 	int i;
552 
553 	for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
554 		lpm_tree = &mlxsw_sp->router->lpm.trees[i];
555 		if (lpm_tree->ref_count == 0)
556 			return lpm_tree;
557 	}
558 	return NULL;
559 }
560 
561 static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp,
562 				   struct mlxsw_sp_lpm_tree *lpm_tree)
563 {
564 	char ralta_pl[MLXSW_REG_RALTA_LEN];
565 
566 	mlxsw_reg_ralta_pack(ralta_pl, true,
567 			     (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
568 			     lpm_tree->id);
569 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
570 }
571 
572 static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp,
573 				   struct mlxsw_sp_lpm_tree *lpm_tree)
574 {
575 	char ralta_pl[MLXSW_REG_RALTA_LEN];
576 
577 	mlxsw_reg_ralta_pack(ralta_pl, false,
578 			     (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
579 			     lpm_tree->id);
580 	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
581 }
582 
583 static int
584 mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp,
585 				  struct mlxsw_sp_prefix_usage *prefix_usage,
586 				  struct mlxsw_sp_lpm_tree *lpm_tree)
587 {
588 	char ralst_pl[MLXSW_REG_RALST_LEN];
589 	u8 root_bin = 0;
590 	u8 prefix;
591 	u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD;
592 
593 	mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage)
594 		root_bin = prefix;
595 
596 	mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id);
597 	mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) {
598 		if (prefix == 0)
599 			continue;
600 		mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix,
601 					 MLXSW_REG_RALST_BIN_NO_CHILD);
602 		last_prefix = prefix;
603 	}
604 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
605 }
606 
607 static struct mlxsw_sp_lpm_tree *
608 mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
609 			 struct mlxsw_sp_prefix_usage *prefix_usage,
610 			 enum mlxsw_sp_l3proto proto)
611 {
612 	struct mlxsw_sp_lpm_tree *lpm_tree;
613 	int err;
614 
615 	lpm_tree = mlxsw_sp_lpm_tree_find_unused(mlxsw_sp);
616 	if (!lpm_tree)
617 		return ERR_PTR(-EBUSY);
618 	lpm_tree->proto = proto;
619 	err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree);
620 	if (err)
621 		return ERR_PTR(err);
622 
623 	err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage,
624 						lpm_tree);
625 	if (err)
626 		goto err_left_struct_set;
627 	memcpy(&lpm_tree->prefix_usage, prefix_usage,
628 	       sizeof(lpm_tree->prefix_usage));
629 	memset(&lpm_tree->prefix_ref_count, 0,
630 	       sizeof(lpm_tree->prefix_ref_count));
631 	lpm_tree->ref_count = 1;
632 	return lpm_tree;
633 
634 err_left_struct_set:
635 	mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
636 	return ERR_PTR(err);
637 }
638 
639 static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp,
640 				      struct mlxsw_sp_lpm_tree *lpm_tree)
641 {
642 	mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
643 }
644 
645 static struct mlxsw_sp_lpm_tree *
646 mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
647 		      struct mlxsw_sp_prefix_usage *prefix_usage,
648 		      enum mlxsw_sp_l3proto proto)
649 {
650 	struct mlxsw_sp_lpm_tree *lpm_tree;
651 	int i;
652 
653 	for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
654 		lpm_tree = &mlxsw_sp->router->lpm.trees[i];
655 		if (lpm_tree->ref_count != 0 &&
656 		    lpm_tree->proto == proto &&
657 		    mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
658 					     prefix_usage)) {
659 			mlxsw_sp_lpm_tree_hold(lpm_tree);
660 			return lpm_tree;
661 		}
662 	}
663 	return mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage, proto);
664 }
665 
666 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree)
667 {
668 	lpm_tree->ref_count++;
669 }
670 
671 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
672 				  struct mlxsw_sp_lpm_tree *lpm_tree)
673 {
674 	if (--lpm_tree->ref_count == 0)
675 		mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
676 }
677 
678 #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
679 
680 static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
681 {
682 	struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
683 	struct mlxsw_sp_lpm_tree *lpm_tree;
684 	u64 max_trees;
685 	int err, i;
686 
687 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES))
688 		return -EIO;
689 
690 	max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES);
691 	mlxsw_sp->router->lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN;
692 	mlxsw_sp->router->lpm.trees = kcalloc(mlxsw_sp->router->lpm.tree_count,
693 					     sizeof(struct mlxsw_sp_lpm_tree),
694 					     GFP_KERNEL);
695 	if (!mlxsw_sp->router->lpm.trees)
696 		return -ENOMEM;
697 
698 	for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
699 		lpm_tree = &mlxsw_sp->router->lpm.trees[i];
700 		lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
701 	}
702 
703 	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
704 					 MLXSW_SP_L3_PROTO_IPV4);
705 	if (IS_ERR(lpm_tree)) {
706 		err = PTR_ERR(lpm_tree);
707 		goto err_ipv4_tree_get;
708 	}
709 	mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4] = lpm_tree;
710 
711 	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
712 					 MLXSW_SP_L3_PROTO_IPV6);
713 	if (IS_ERR(lpm_tree)) {
714 		err = PTR_ERR(lpm_tree);
715 		goto err_ipv6_tree_get;
716 	}
717 	mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV6] = lpm_tree;
718 
719 	return 0;
720 
721 err_ipv6_tree_get:
722 	lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4];
723 	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
724 err_ipv4_tree_get:
725 	kfree(mlxsw_sp->router->lpm.trees);
726 	return err;
727 }
728 
729 static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
730 {
731 	struct mlxsw_sp_lpm_tree *lpm_tree;
732 
733 	lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV6];
734 	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
735 
736 	lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4];
737 	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
738 
739 	kfree(mlxsw_sp->router->lpm.trees);
740 }
741 
742 static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
743 {
744 	return !!vr->fib4 || !!vr->fib6 ||
745 	       !!vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] ||
746 	       !!vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
747 }
748 
749 static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
750 {
751 	struct mlxsw_sp_vr *vr;
752 	int i;
753 
754 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
755 		vr = &mlxsw_sp->router->vrs[i];
756 		if (!mlxsw_sp_vr_is_used(vr))
757 			return vr;
758 	}
759 	return NULL;
760 }
761 
762 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
763 				     const struct mlxsw_sp_fib *fib, u8 tree_id)
764 {
765 	char raltb_pl[MLXSW_REG_RALTB_LEN];
766 
767 	mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
768 			     (enum mlxsw_reg_ralxx_protocol) fib->proto,
769 			     tree_id);
770 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
771 }
772 
773 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
774 				       const struct mlxsw_sp_fib *fib)
775 {
776 	char raltb_pl[MLXSW_REG_RALTB_LEN];
777 
778 	/* Bind to tree 0 which is default */
779 	mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
780 			     (enum mlxsw_reg_ralxx_protocol) fib->proto, 0);
781 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
782 }
783 
784 static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
785 {
786 	/* For our purpose, squash main, default and local tables into one */
787 	if (tb_id == RT_TABLE_LOCAL || tb_id == RT_TABLE_DEFAULT)
788 		tb_id = RT_TABLE_MAIN;
789 	return tb_id;
790 }
791 
792 static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
793 					    u32 tb_id)
794 {
795 	struct mlxsw_sp_vr *vr;
796 	int i;
797 
798 	tb_id = mlxsw_sp_fix_tb_id(tb_id);
799 
800 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
801 		vr = &mlxsw_sp->router->vrs[i];
802 		if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
803 			return vr;
804 	}
805 	return NULL;
806 }
807 
808 int mlxsw_sp_router_tb_id_vr_id(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
809 				u16 *vr_id)
810 {
811 	struct mlxsw_sp_vr *vr;
812 	int err = 0;
813 
814 	mutex_lock(&mlxsw_sp->router->lock);
815 	vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
816 	if (!vr) {
817 		err = -ESRCH;
818 		goto out;
819 	}
820 	*vr_id = vr->id;
821 out:
822 	mutex_unlock(&mlxsw_sp->router->lock);
823 	return err;
824 }
825 
826 static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr,
827 					    enum mlxsw_sp_l3proto proto)
828 {
829 	switch (proto) {
830 	case MLXSW_SP_L3_PROTO_IPV4:
831 		return vr->fib4;
832 	case MLXSW_SP_L3_PROTO_IPV6:
833 		return vr->fib6;
834 	}
835 	return NULL;
836 }
837 
838 static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
839 					      u32 tb_id,
840 					      struct netlink_ext_ack *extack)
841 {
842 	struct mlxsw_sp_mr_table *mr4_table, *mr6_table;
843 	struct mlxsw_sp_fib *fib4;
844 	struct mlxsw_sp_fib *fib6;
845 	struct mlxsw_sp_vr *vr;
846 	int err;
847 
848 	vr = mlxsw_sp_vr_find_unused(mlxsw_sp);
849 	if (!vr) {
850 		NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported virtual routers");
851 		return ERR_PTR(-EBUSY);
852 	}
853 	fib4 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
854 	if (IS_ERR(fib4))
855 		return ERR_CAST(fib4);
856 	fib6 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
857 	if (IS_ERR(fib6)) {
858 		err = PTR_ERR(fib6);
859 		goto err_fib6_create;
860 	}
861 	mr4_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
862 					     MLXSW_SP_L3_PROTO_IPV4);
863 	if (IS_ERR(mr4_table)) {
864 		err = PTR_ERR(mr4_table);
865 		goto err_mr4_table_create;
866 	}
867 	mr6_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
868 					     MLXSW_SP_L3_PROTO_IPV6);
869 	if (IS_ERR(mr6_table)) {
870 		err = PTR_ERR(mr6_table);
871 		goto err_mr6_table_create;
872 	}
873 
874 	vr->fib4 = fib4;
875 	vr->fib6 = fib6;
876 	vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = mr4_table;
877 	vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = mr6_table;
878 	vr->tb_id = tb_id;
879 	return vr;
880 
881 err_mr6_table_create:
882 	mlxsw_sp_mr_table_destroy(mr4_table);
883 err_mr4_table_create:
884 	mlxsw_sp_fib_destroy(mlxsw_sp, fib6);
885 err_fib6_create:
886 	mlxsw_sp_fib_destroy(mlxsw_sp, fib4);
887 	return ERR_PTR(err);
888 }
889 
890 static void mlxsw_sp_vr_destroy(struct mlxsw_sp *mlxsw_sp,
891 				struct mlxsw_sp_vr *vr)
892 {
893 	mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]);
894 	vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = NULL;
895 	mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]);
896 	vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = NULL;
897 	mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib6);
898 	vr->fib6 = NULL;
899 	mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib4);
900 	vr->fib4 = NULL;
901 }
902 
903 static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
904 					   struct netlink_ext_ack *extack)
905 {
906 	struct mlxsw_sp_vr *vr;
907 
908 	tb_id = mlxsw_sp_fix_tb_id(tb_id);
909 	vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
910 	if (!vr)
911 		vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id, extack);
912 	return vr;
913 }
914 
915 static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr)
916 {
917 	if (!vr->rif_count && list_empty(&vr->fib4->node_list) &&
918 	    list_empty(&vr->fib6->node_list) &&
919 	    mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]) &&
920 	    mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]))
921 		mlxsw_sp_vr_destroy(mlxsw_sp, vr);
922 }
923 
924 static bool
925 mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr *vr,
926 				    enum mlxsw_sp_l3proto proto, u8 tree_id)
927 {
928 	struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
929 
930 	if (!mlxsw_sp_vr_is_used(vr))
931 		return false;
932 	if (fib->lpm_tree->id == tree_id)
933 		return true;
934 	return false;
935 }
936 
937 static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
938 					struct mlxsw_sp_fib *fib,
939 					struct mlxsw_sp_lpm_tree *new_tree)
940 {
941 	struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree;
942 	int err;
943 
944 	fib->lpm_tree = new_tree;
945 	mlxsw_sp_lpm_tree_hold(new_tree);
946 	err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
947 	if (err)
948 		goto err_tree_bind;
949 	mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
950 	return 0;
951 
952 err_tree_bind:
953 	mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree);
954 	fib->lpm_tree = old_tree;
955 	return err;
956 }
957 
958 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
959 					 struct mlxsw_sp_fib *fib,
960 					 struct mlxsw_sp_lpm_tree *new_tree)
961 {
962 	enum mlxsw_sp_l3proto proto = fib->proto;
963 	struct mlxsw_sp_lpm_tree *old_tree;
964 	u8 old_id, new_id = new_tree->id;
965 	struct mlxsw_sp_vr *vr;
966 	int i, err;
967 
968 	old_tree = mlxsw_sp->router->lpm.proto_trees[proto];
969 	old_id = old_tree->id;
970 
971 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
972 		vr = &mlxsw_sp->router->vrs[i];
973 		if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id))
974 			continue;
975 		err = mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
976 						   mlxsw_sp_vr_fib(vr, proto),
977 						   new_tree);
978 		if (err)
979 			goto err_tree_replace;
980 	}
981 
982 	memcpy(new_tree->prefix_ref_count, old_tree->prefix_ref_count,
983 	       sizeof(new_tree->prefix_ref_count));
984 	mlxsw_sp->router->lpm.proto_trees[proto] = new_tree;
985 	mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
986 
987 	return 0;
988 
989 err_tree_replace:
990 	for (i--; i >= 0; i--) {
991 		if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, new_id))
992 			continue;
993 		mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
994 					     mlxsw_sp_vr_fib(vr, proto),
995 					     old_tree);
996 	}
997 	return err;
998 }
999 
1000 static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
1001 {
1002 	struct mlxsw_sp_vr *vr;
1003 	u64 max_vrs;
1004 	int i;
1005 
1006 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
1007 		return -EIO;
1008 
1009 	max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
1010 	mlxsw_sp->router->vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
1011 					GFP_KERNEL);
1012 	if (!mlxsw_sp->router->vrs)
1013 		return -ENOMEM;
1014 
1015 	for (i = 0; i < max_vrs; i++) {
1016 		vr = &mlxsw_sp->router->vrs[i];
1017 		vr->id = i;
1018 	}
1019 
1020 	return 0;
1021 }
1022 
1023 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp);
1024 
1025 static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
1026 {
1027 	/* At this stage we're guaranteed not to have new incoming
1028 	 * FIB notifications and the work queue is free from FIBs
1029 	 * sitting on top of mlxsw netdevs. However, we can still
1030 	 * have other FIBs queued. Flush the queue before flushing
1031 	 * the device's tables. No need for locks, as we're the only
1032 	 * writer.
1033 	 */
1034 	mlxsw_core_flush_owq();
1035 	mlxsw_sp_router_fib_flush(mlxsw_sp);
1036 	kfree(mlxsw_sp->router->vrs);
1037 }
1038 
1039 u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
1040 {
1041 	struct net_device *d;
1042 	u32 tb_id;
1043 
1044 	rcu_read_lock();
1045 	d = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
1046 	if (d)
1047 		tb_id = l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
1048 	else
1049 		tb_id = RT_TABLE_MAIN;
1050 	rcu_read_unlock();
1051 
1052 	return tb_id;
1053 }
1054 
1055 static struct mlxsw_sp_rif *
1056 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
1057 		    const struct mlxsw_sp_rif_params *params,
1058 		    struct netlink_ext_ack *extack);
1059 
1060 static struct mlxsw_sp_rif_ipip_lb *
1061 mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
1062 				enum mlxsw_sp_ipip_type ipipt,
1063 				struct net_device *ol_dev,
1064 				struct netlink_ext_ack *extack)
1065 {
1066 	struct mlxsw_sp_rif_params_ipip_lb lb_params;
1067 	const struct mlxsw_sp_ipip_ops *ipip_ops;
1068 	struct mlxsw_sp_rif *rif;
1069 
1070 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
1071 	lb_params = (struct mlxsw_sp_rif_params_ipip_lb) {
1072 		.common.dev = ol_dev,
1073 		.common.lag = false,
1074 		.common.double_entry = ipip_ops->double_rif_entry,
1075 		.lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev),
1076 	};
1077 
1078 	rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common, extack);
1079 	if (IS_ERR(rif))
1080 		return ERR_CAST(rif);
1081 	return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
1082 }
1083 
1084 static struct mlxsw_sp_ipip_entry *
1085 mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp *mlxsw_sp,
1086 			  enum mlxsw_sp_ipip_type ipipt,
1087 			  struct net_device *ol_dev)
1088 {
1089 	const struct mlxsw_sp_ipip_ops *ipip_ops;
1090 	struct mlxsw_sp_ipip_entry *ipip_entry;
1091 	struct mlxsw_sp_ipip_entry *ret = NULL;
1092 	int err;
1093 
1094 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
1095 	ipip_entry = kzalloc(sizeof(*ipip_entry), GFP_KERNEL);
1096 	if (!ipip_entry)
1097 		return ERR_PTR(-ENOMEM);
1098 
1099 	ipip_entry->ol_lb = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp, ipipt,
1100 							    ol_dev, NULL);
1101 	if (IS_ERR(ipip_entry->ol_lb)) {
1102 		ret = ERR_CAST(ipip_entry->ol_lb);
1103 		goto err_ol_ipip_lb_create;
1104 	}
1105 
1106 	ipip_entry->ipipt = ipipt;
1107 	ipip_entry->ol_dev = ol_dev;
1108 	ipip_entry->parms = ipip_ops->parms_init(ol_dev);
1109 
1110 	err = ipip_ops->rem_ip_addr_set(mlxsw_sp, ipip_entry);
1111 	if (err) {
1112 		ret = ERR_PTR(err);
1113 		goto err_rem_ip_addr_set;
1114 	}
1115 
1116 	return ipip_entry;
1117 
1118 err_rem_ip_addr_set:
1119 	mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
1120 err_ol_ipip_lb_create:
1121 	kfree(ipip_entry);
1122 	return ret;
1123 }
1124 
1125 static void mlxsw_sp_ipip_entry_dealloc(struct mlxsw_sp *mlxsw_sp,
1126 					struct mlxsw_sp_ipip_entry *ipip_entry)
1127 {
1128 	const struct mlxsw_sp_ipip_ops *ipip_ops =
1129 		mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
1130 
1131 	ipip_ops->rem_ip_addr_unset(mlxsw_sp, ipip_entry);
1132 	mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
1133 	kfree(ipip_entry);
1134 }
1135 
1136 static bool
1137 mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp *mlxsw_sp,
1138 				  const enum mlxsw_sp_l3proto ul_proto,
1139 				  union mlxsw_sp_l3addr saddr,
1140 				  u32 ul_tb_id,
1141 				  struct mlxsw_sp_ipip_entry *ipip_entry)
1142 {
1143 	u32 tun_ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
1144 	enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
1145 	union mlxsw_sp_l3addr tun_saddr;
1146 
1147 	if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
1148 		return false;
1149 
1150 	tun_saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
1151 	return tun_ul_tb_id == ul_tb_id &&
1152 	       mlxsw_sp_l3addr_eq(&tun_saddr, &saddr);
1153 }
1154 
1155 static int mlxsw_sp_ipip_decap_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp,
1156 						 enum mlxsw_sp_ipip_type ipipt)
1157 {
1158 	const struct mlxsw_sp_ipip_ops *ipip_ops;
1159 
1160 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
1161 
1162 	/* Not all tunnels require to increase the default pasing depth
1163 	 * (96 bytes).
1164 	 */
1165 	if (ipip_ops->inc_parsing_depth)
1166 		return mlxsw_sp_parsing_depth_inc(mlxsw_sp);
1167 
1168 	return 0;
1169 }
1170 
1171 static void mlxsw_sp_ipip_decap_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp,
1172 						  enum mlxsw_sp_ipip_type ipipt)
1173 {
1174 	const struct mlxsw_sp_ipip_ops *ipip_ops =
1175 		mlxsw_sp->router->ipip_ops_arr[ipipt];
1176 
1177 	if (ipip_ops->inc_parsing_depth)
1178 		mlxsw_sp_parsing_depth_dec(mlxsw_sp);
1179 }
1180 
1181 static int
1182 mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp *mlxsw_sp,
1183 			      struct mlxsw_sp_fib_entry *fib_entry,
1184 			      struct mlxsw_sp_ipip_entry *ipip_entry)
1185 {
1186 	u32 tunnel_index;
1187 	int err;
1188 
1189 	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
1190 				  1, &tunnel_index);
1191 	if (err)
1192 		return err;
1193 
1194 	err = mlxsw_sp_ipip_decap_parsing_depth_inc(mlxsw_sp,
1195 						    ipip_entry->ipipt);
1196 	if (err)
1197 		goto err_parsing_depth_inc;
1198 
1199 	ipip_entry->decap_fib_entry = fib_entry;
1200 	fib_entry->decap.ipip_entry = ipip_entry;
1201 	fib_entry->decap.tunnel_index = tunnel_index;
1202 
1203 	return 0;
1204 
1205 err_parsing_depth_inc:
1206 	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
1207 			   fib_entry->decap.tunnel_index);
1208 	return err;
1209 }
1210 
1211 static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp,
1212 					  struct mlxsw_sp_fib_entry *fib_entry)
1213 {
1214 	enum mlxsw_sp_ipip_type ipipt = fib_entry->decap.ipip_entry->ipipt;
1215 
1216 	/* Unlink this node from the IPIP entry that it's the decap entry of. */
1217 	fib_entry->decap.ipip_entry->decap_fib_entry = NULL;
1218 	fib_entry->decap.ipip_entry = NULL;
1219 	mlxsw_sp_ipip_decap_parsing_depth_dec(mlxsw_sp, ipipt);
1220 	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
1221 			   1, fib_entry->decap.tunnel_index);
1222 }
1223 
1224 static struct mlxsw_sp_fib_node *
1225 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
1226 			 size_t addr_len, unsigned char prefix_len);
1227 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
1228 				     struct mlxsw_sp_fib_entry *fib_entry);
1229 
1230 static void
1231 mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp,
1232 				 struct mlxsw_sp_ipip_entry *ipip_entry)
1233 {
1234 	struct mlxsw_sp_fib_entry *fib_entry = ipip_entry->decap_fib_entry;
1235 
1236 	mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
1237 	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1238 
1239 	mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
1240 }
1241 
1242 static void
1243 mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp *mlxsw_sp,
1244 				  struct mlxsw_sp_ipip_entry *ipip_entry,
1245 				  struct mlxsw_sp_fib_entry *decap_fib_entry)
1246 {
1247 	if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp, decap_fib_entry,
1248 					  ipip_entry))
1249 		return;
1250 	decap_fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
1251 
1252 	if (mlxsw_sp_fib_entry_update(mlxsw_sp, decap_fib_entry))
1253 		mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1254 }
1255 
1256 static struct mlxsw_sp_fib_entry *
1257 mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
1258 				     enum mlxsw_sp_l3proto proto,
1259 				     const union mlxsw_sp_l3addr *addr,
1260 				     enum mlxsw_sp_fib_entry_type type)
1261 {
1262 	struct mlxsw_sp_fib_node *fib_node;
1263 	unsigned char addr_prefix_len;
1264 	struct mlxsw_sp_fib *fib;
1265 	struct mlxsw_sp_vr *vr;
1266 	const void *addrp;
1267 	size_t addr_len;
1268 	u32 addr4;
1269 
1270 	vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
1271 	if (!vr)
1272 		return NULL;
1273 	fib = mlxsw_sp_vr_fib(vr, proto);
1274 
1275 	switch (proto) {
1276 	case MLXSW_SP_L3_PROTO_IPV4:
1277 		addr4 = be32_to_cpu(addr->addr4);
1278 		addrp = &addr4;
1279 		addr_len = 4;
1280 		addr_prefix_len = 32;
1281 		break;
1282 	case MLXSW_SP_L3_PROTO_IPV6:
1283 		addrp = &addr->addr6;
1284 		addr_len = 16;
1285 		addr_prefix_len = 128;
1286 		break;
1287 	default:
1288 		WARN_ON(1);
1289 		return NULL;
1290 	}
1291 
1292 	fib_node = mlxsw_sp_fib_node_lookup(fib, addrp, addr_len,
1293 					    addr_prefix_len);
1294 	if (!fib_node || fib_node->fib_entry->type != type)
1295 		return NULL;
1296 
1297 	return fib_node->fib_entry;
1298 }
1299 
1300 /* Given an IPIP entry, find the corresponding decap route. */
1301 static struct mlxsw_sp_fib_entry *
1302 mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
1303 			       struct mlxsw_sp_ipip_entry *ipip_entry)
1304 {
1305 	static struct mlxsw_sp_fib_node *fib_node;
1306 	const struct mlxsw_sp_ipip_ops *ipip_ops;
1307 	unsigned char saddr_prefix_len;
1308 	union mlxsw_sp_l3addr saddr;
1309 	struct mlxsw_sp_fib *ul_fib;
1310 	struct mlxsw_sp_vr *ul_vr;
1311 	const void *saddrp;
1312 	size_t saddr_len;
1313 	u32 ul_tb_id;
1314 	u32 saddr4;
1315 
1316 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
1317 
1318 	ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
1319 	ul_vr = mlxsw_sp_vr_find(mlxsw_sp, ul_tb_id);
1320 	if (!ul_vr)
1321 		return NULL;
1322 
1323 	ul_fib = mlxsw_sp_vr_fib(ul_vr, ipip_ops->ul_proto);
1324 	saddr = mlxsw_sp_ipip_netdev_saddr(ipip_ops->ul_proto,
1325 					   ipip_entry->ol_dev);
1326 
1327 	switch (ipip_ops->ul_proto) {
1328 	case MLXSW_SP_L3_PROTO_IPV4:
1329 		saddr4 = be32_to_cpu(saddr.addr4);
1330 		saddrp = &saddr4;
1331 		saddr_len = 4;
1332 		saddr_prefix_len = 32;
1333 		break;
1334 	case MLXSW_SP_L3_PROTO_IPV6:
1335 		saddrp = &saddr.addr6;
1336 		saddr_len = 16;
1337 		saddr_prefix_len = 128;
1338 		break;
1339 	default:
1340 		WARN_ON(1);
1341 		return NULL;
1342 	}
1343 
1344 	fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len,
1345 					    saddr_prefix_len);
1346 	if (!fib_node ||
1347 	    fib_node->fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
1348 		return NULL;
1349 
1350 	return fib_node->fib_entry;
1351 }
1352 
1353 static struct mlxsw_sp_ipip_entry *
1354 mlxsw_sp_ipip_entry_create(struct mlxsw_sp *mlxsw_sp,
1355 			   enum mlxsw_sp_ipip_type ipipt,
1356 			   struct net_device *ol_dev)
1357 {
1358 	struct mlxsw_sp_ipip_entry *ipip_entry;
1359 
1360 	ipip_entry = mlxsw_sp_ipip_entry_alloc(mlxsw_sp, ipipt, ol_dev);
1361 	if (IS_ERR(ipip_entry))
1362 		return ipip_entry;
1363 
1364 	list_add_tail(&ipip_entry->ipip_list_node,
1365 		      &mlxsw_sp->router->ipip_list);
1366 
1367 	return ipip_entry;
1368 }
1369 
1370 static void
1371 mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp *mlxsw_sp,
1372 			    struct mlxsw_sp_ipip_entry *ipip_entry)
1373 {
1374 	list_del(&ipip_entry->ipip_list_node);
1375 	mlxsw_sp_ipip_entry_dealloc(mlxsw_sp, ipip_entry);
1376 }
1377 
1378 static bool
1379 mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp *mlxsw_sp,
1380 				  const struct net_device *ul_dev,
1381 				  enum mlxsw_sp_l3proto ul_proto,
1382 				  union mlxsw_sp_l3addr ul_dip,
1383 				  struct mlxsw_sp_ipip_entry *ipip_entry)
1384 {
1385 	u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
1386 	enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
1387 
1388 	if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
1389 		return false;
1390 
1391 	return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, ul_dip,
1392 						 ul_tb_id, ipip_entry);
1393 }
1394 
1395 /* Given decap parameters, find the corresponding IPIP entry. */
1396 static struct mlxsw_sp_ipip_entry *
1397 mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp *mlxsw_sp, int ul_dev_ifindex,
1398 				  enum mlxsw_sp_l3proto ul_proto,
1399 				  union mlxsw_sp_l3addr ul_dip)
1400 {
1401 	struct mlxsw_sp_ipip_entry *ipip_entry = NULL;
1402 	struct net_device *ul_dev;
1403 
1404 	rcu_read_lock();
1405 
1406 	ul_dev = dev_get_by_index_rcu(mlxsw_sp_net(mlxsw_sp), ul_dev_ifindex);
1407 	if (!ul_dev)
1408 		goto out_unlock;
1409 
1410 	list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1411 			    ipip_list_node)
1412 		if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp, ul_dev,
1413 						      ul_proto, ul_dip,
1414 						      ipip_entry))
1415 			goto out_unlock;
1416 
1417 	rcu_read_unlock();
1418 
1419 	return NULL;
1420 
1421 out_unlock:
1422 	rcu_read_unlock();
1423 	return ipip_entry;
1424 }
1425 
1426 static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
1427 				      const struct net_device *dev,
1428 				      enum mlxsw_sp_ipip_type *p_type)
1429 {
1430 	struct mlxsw_sp_router *router = mlxsw_sp->router;
1431 	const struct mlxsw_sp_ipip_ops *ipip_ops;
1432 	enum mlxsw_sp_ipip_type ipipt;
1433 
1434 	for (ipipt = 0; ipipt < MLXSW_SP_IPIP_TYPE_MAX; ++ipipt) {
1435 		ipip_ops = router->ipip_ops_arr[ipipt];
1436 		if (dev->type == ipip_ops->dev_type) {
1437 			if (p_type)
1438 				*p_type = ipipt;
1439 			return true;
1440 		}
1441 	}
1442 	return false;
1443 }
1444 
1445 static bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp *mlxsw_sp,
1446 				       const struct net_device *dev)
1447 {
1448 	return mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
1449 }
1450 
1451 static struct mlxsw_sp_ipip_entry *
1452 mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp *mlxsw_sp,
1453 				   const struct net_device *ol_dev)
1454 {
1455 	struct mlxsw_sp_ipip_entry *ipip_entry;
1456 
1457 	list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1458 			    ipip_list_node)
1459 		if (ipip_entry->ol_dev == ol_dev)
1460 			return ipip_entry;
1461 
1462 	return NULL;
1463 }
1464 
1465 static struct mlxsw_sp_ipip_entry *
1466 mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp *mlxsw_sp,
1467 				   const struct net_device *ul_dev,
1468 				   struct mlxsw_sp_ipip_entry *start)
1469 {
1470 	struct mlxsw_sp_ipip_entry *ipip_entry;
1471 
1472 	ipip_entry = list_prepare_entry(start, &mlxsw_sp->router->ipip_list,
1473 					ipip_list_node);
1474 	list_for_each_entry_continue(ipip_entry, &mlxsw_sp->router->ipip_list,
1475 				     ipip_list_node) {
1476 		struct net_device *ol_dev = ipip_entry->ol_dev;
1477 		struct net_device *ipip_ul_dev;
1478 
1479 		rcu_read_lock();
1480 		ipip_ul_dev = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
1481 		rcu_read_unlock();
1482 
1483 		if (ipip_ul_dev == ul_dev)
1484 			return ipip_entry;
1485 	}
1486 
1487 	return NULL;
1488 }
1489 
1490 static bool mlxsw_sp_netdev_is_ipip_ul(struct mlxsw_sp *mlxsw_sp,
1491 				       const struct net_device *dev)
1492 {
1493 	return mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp, dev, NULL);
1494 }
1495 
1496 static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp *mlxsw_sp,
1497 						const struct net_device *ol_dev,
1498 						enum mlxsw_sp_ipip_type ipipt)
1499 {
1500 	const struct mlxsw_sp_ipip_ops *ops
1501 		= mlxsw_sp->router->ipip_ops_arr[ipipt];
1502 
1503 	return ops->can_offload(mlxsw_sp, ol_dev);
1504 }
1505 
1506 static int mlxsw_sp_netdevice_ipip_ol_reg_event(struct mlxsw_sp *mlxsw_sp,
1507 						struct net_device *ol_dev)
1508 {
1509 	enum mlxsw_sp_ipip_type ipipt = MLXSW_SP_IPIP_TYPE_MAX;
1510 	struct mlxsw_sp_ipip_entry *ipip_entry;
1511 	enum mlxsw_sp_l3proto ul_proto;
1512 	union mlxsw_sp_l3addr saddr;
1513 	u32 ul_tb_id;
1514 
1515 	mlxsw_sp_netdev_ipip_type(mlxsw_sp, ol_dev, &ipipt);
1516 	if (mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp, ol_dev, ipipt)) {
1517 		ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
1518 		ul_proto = mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto;
1519 		saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev);
1520 		if (!mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
1521 							  saddr, ul_tb_id,
1522 							  NULL)) {
1523 			ipip_entry = mlxsw_sp_ipip_entry_create(mlxsw_sp, ipipt,
1524 								ol_dev);
1525 			if (IS_ERR(ipip_entry))
1526 				return PTR_ERR(ipip_entry);
1527 		}
1528 	}
1529 
1530 	return 0;
1531 }
1532 
1533 static void mlxsw_sp_netdevice_ipip_ol_unreg_event(struct mlxsw_sp *mlxsw_sp,
1534 						   struct net_device *ol_dev)
1535 {
1536 	struct mlxsw_sp_ipip_entry *ipip_entry;
1537 
1538 	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1539 	if (ipip_entry)
1540 		mlxsw_sp_ipip_entry_destroy(mlxsw_sp, ipip_entry);
1541 }
1542 
1543 static void
1544 mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp,
1545 				struct mlxsw_sp_ipip_entry *ipip_entry)
1546 {
1547 	struct mlxsw_sp_fib_entry *decap_fib_entry;
1548 
1549 	decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
1550 	if (decap_fib_entry)
1551 		mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
1552 						  decap_fib_entry);
1553 }
1554 
1555 static int
1556 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
1557 			u16 ul_rif_id, bool enable)
1558 {
1559 	struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
1560 	enum mlxsw_reg_ritr_loopback_ipip_options ipip_options;
1561 	struct mlxsw_sp_rif *rif = &lb_rif->common;
1562 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
1563 	char ritr_pl[MLXSW_REG_RITR_LEN];
1564 	struct in6_addr *saddr6;
1565 	u32 saddr4;
1566 
1567 	ipip_options = MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET;
1568 	switch (lb_cf.ul_protocol) {
1569 	case MLXSW_SP_L3_PROTO_IPV4:
1570 		saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
1571 		mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
1572 				    rif->rif_index, rif->vr_id, rif->dev->mtu);
1573 		mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
1574 						   ipip_options, ul_vr_id,
1575 						   ul_rif_id, saddr4,
1576 						   lb_cf.okey);
1577 		break;
1578 
1579 	case MLXSW_SP_L3_PROTO_IPV6:
1580 		saddr6 = &lb_cf.saddr.addr6;
1581 		mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
1582 				    rif->rif_index, rif->vr_id, rif->dev->mtu);
1583 		mlxsw_reg_ritr_loopback_ipip6_pack(ritr_pl, lb_cf.lb_ipipt,
1584 						   ipip_options, ul_vr_id,
1585 						   ul_rif_id, saddr6,
1586 						   lb_cf.okey);
1587 		break;
1588 	}
1589 
1590 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
1591 }
1592 
1593 static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp,
1594 						 struct net_device *ol_dev)
1595 {
1596 	struct mlxsw_sp_ipip_entry *ipip_entry;
1597 	struct mlxsw_sp_rif_ipip_lb *lb_rif;
1598 	int err = 0;
1599 
1600 	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1601 	if (ipip_entry) {
1602 		lb_rif = ipip_entry->ol_lb;
1603 		err = mlxsw_sp_rif_ipip_lb_op(lb_rif, lb_rif->ul_vr_id,
1604 					      lb_rif->ul_rif_id, true);
1605 		if (err)
1606 			goto out;
1607 		lb_rif->common.mtu = ol_dev->mtu;
1608 	}
1609 
1610 out:
1611 	return err;
1612 }
1613 
1614 static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp *mlxsw_sp,
1615 						struct net_device *ol_dev)
1616 {
1617 	struct mlxsw_sp_ipip_entry *ipip_entry;
1618 
1619 	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1620 	if (ipip_entry)
1621 		mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp, ipip_entry);
1622 }
1623 
1624 static void
1625 mlxsw_sp_ipip_entry_ol_down_event(struct mlxsw_sp *mlxsw_sp,
1626 				  struct mlxsw_sp_ipip_entry *ipip_entry)
1627 {
1628 	if (ipip_entry->decap_fib_entry)
1629 		mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1630 }
1631 
1632 static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
1633 						  struct net_device *ol_dev)
1634 {
1635 	struct mlxsw_sp_ipip_entry *ipip_entry;
1636 
1637 	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1638 	if (ipip_entry)
1639 		mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
1640 }
1641 
1642 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
1643 					 struct mlxsw_sp_rif *old_rif,
1644 					 struct mlxsw_sp_rif *new_rif);
1645 static int
1646 mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
1647 				 struct mlxsw_sp_ipip_entry *ipip_entry,
1648 				 bool keep_encap,
1649 				 struct netlink_ext_ack *extack)
1650 {
1651 	struct mlxsw_sp_rif_ipip_lb *old_lb_rif = ipip_entry->ol_lb;
1652 	struct mlxsw_sp_rif_ipip_lb *new_lb_rif;
1653 
1654 	new_lb_rif = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp,
1655 						     ipip_entry->ipipt,
1656 						     ipip_entry->ol_dev,
1657 						     extack);
1658 	if (IS_ERR(new_lb_rif))
1659 		return PTR_ERR(new_lb_rif);
1660 	ipip_entry->ol_lb = new_lb_rif;
1661 
1662 	if (keep_encap)
1663 		mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common,
1664 					     &new_lb_rif->common);
1665 
1666 	mlxsw_sp_rif_destroy(&old_lb_rif->common);
1667 
1668 	return 0;
1669 }
1670 
1671 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
1672 					struct mlxsw_sp_rif *rif);
1673 
1674 /**
1675  * __mlxsw_sp_ipip_entry_update_tunnel - Update offload related to IPIP entry.
1676  * @mlxsw_sp: mlxsw_sp.
1677  * @ipip_entry: IPIP entry.
1678  * @recreate_loopback: Recreates the associated loopback RIF.
1679  * @keep_encap: Updates next hops that use the tunnel netdevice. This is only
1680  *              relevant when recreate_loopback is true.
1681  * @update_nexthops: Updates next hops, keeping the current loopback RIF. This
1682  *                   is only relevant when recreate_loopback is false.
1683  * @extack: extack.
1684  *
1685  * Return: Non-zero value on failure.
1686  */
1687 int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp *mlxsw_sp,
1688 					struct mlxsw_sp_ipip_entry *ipip_entry,
1689 					bool recreate_loopback,
1690 					bool keep_encap,
1691 					bool update_nexthops,
1692 					struct netlink_ext_ack *extack)
1693 {
1694 	int err;
1695 
1696 	/* RIFs can't be edited, so to update loopback, we need to destroy and
1697 	 * recreate it. That creates a window of opportunity where RALUE and
1698 	 * RATR registers end up referencing a RIF that's already gone. RATRs
1699 	 * are handled in mlxsw_sp_ipip_entry_ol_lb_update(), and to take care
1700 	 * of RALUE, demote the decap route back.
1701 	 */
1702 	if (ipip_entry->decap_fib_entry)
1703 		mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1704 
1705 	if (recreate_loopback) {
1706 		err = mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp, ipip_entry,
1707 						       keep_encap, extack);
1708 		if (err)
1709 			return err;
1710 	} else if (update_nexthops) {
1711 		mlxsw_sp_nexthop_rif_update(mlxsw_sp,
1712 					    &ipip_entry->ol_lb->common);
1713 	}
1714 
1715 	if (ipip_entry->ol_dev->flags & IFF_UP)
1716 		mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp, ipip_entry);
1717 
1718 	return 0;
1719 }
1720 
1721 static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp *mlxsw_sp,
1722 						struct net_device *ol_dev,
1723 						struct netlink_ext_ack *extack)
1724 {
1725 	struct mlxsw_sp_ipip_entry *ipip_entry =
1726 		mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1727 
1728 	if (!ipip_entry)
1729 		return 0;
1730 
1731 	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1732 						   true, false, false, extack);
1733 }
1734 
1735 static int
1736 mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp *mlxsw_sp,
1737 				     struct mlxsw_sp_ipip_entry *ipip_entry,
1738 				     struct net_device *ul_dev,
1739 				     bool *demote_this,
1740 				     struct netlink_ext_ack *extack)
1741 {
1742 	u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
1743 	enum mlxsw_sp_l3proto ul_proto;
1744 	union mlxsw_sp_l3addr saddr;
1745 
1746 	/* Moving underlay to a different VRF might cause local address
1747 	 * conflict, and the conflicting tunnels need to be demoted.
1748 	 */
1749 	ul_proto = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto;
1750 	saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
1751 	if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
1752 						 saddr, ul_tb_id,
1753 						 ipip_entry)) {
1754 		*demote_this = true;
1755 		return 0;
1756 	}
1757 
1758 	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1759 						   true, true, false, extack);
1760 }
1761 
1762 static int
1763 mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp *mlxsw_sp,
1764 				    struct mlxsw_sp_ipip_entry *ipip_entry,
1765 				    struct net_device *ul_dev)
1766 {
1767 	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1768 						   false, false, true, NULL);
1769 }
1770 
1771 static int
1772 mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp *mlxsw_sp,
1773 				      struct mlxsw_sp_ipip_entry *ipip_entry,
1774 				      struct net_device *ul_dev)
1775 {
1776 	/* A down underlay device causes encapsulated packets to not be
1777 	 * forwarded, but decap still works. So refresh next hops without
1778 	 * touching anything else.
1779 	 */
1780 	return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1781 						   false, false, true, NULL);
1782 }
1783 
1784 static int
1785 mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp *mlxsw_sp,
1786 					struct net_device *ol_dev,
1787 					struct netlink_ext_ack *extack)
1788 {
1789 	const struct mlxsw_sp_ipip_ops *ipip_ops;
1790 	struct mlxsw_sp_ipip_entry *ipip_entry;
1791 	int err;
1792 
1793 	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1794 	if (!ipip_entry)
1795 		/* A change might make a tunnel eligible for offloading, but
1796 		 * that is currently not implemented. What falls to slow path
1797 		 * stays there.
1798 		 */
1799 		return 0;
1800 
1801 	/* A change might make a tunnel not eligible for offloading. */
1802 	if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp, ol_dev,
1803 						 ipip_entry->ipipt)) {
1804 		mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1805 		return 0;
1806 	}
1807 
1808 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
1809 	err = ipip_ops->ol_netdev_change(mlxsw_sp, ipip_entry, extack);
1810 	return err;
1811 }
1812 
1813 void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp *mlxsw_sp,
1814 				       struct mlxsw_sp_ipip_entry *ipip_entry)
1815 {
1816 	struct net_device *ol_dev = ipip_entry->ol_dev;
1817 
1818 	if (ol_dev->flags & IFF_UP)
1819 		mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
1820 	mlxsw_sp_ipip_entry_destroy(mlxsw_sp, ipip_entry);
1821 }
1822 
1823 /* The configuration where several tunnels have the same local address in the
1824  * same underlay table needs special treatment in the HW. That is currently not
1825  * implemented in the driver. This function finds and demotes the first tunnel
1826  * with a given source address, except the one passed in the argument
1827  * `except'.
1828  */
1829 bool
1830 mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp *mlxsw_sp,
1831 				     enum mlxsw_sp_l3proto ul_proto,
1832 				     union mlxsw_sp_l3addr saddr,
1833 				     u32 ul_tb_id,
1834 				     const struct mlxsw_sp_ipip_entry *except)
1835 {
1836 	struct mlxsw_sp_ipip_entry *ipip_entry, *tmp;
1837 
1838 	list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
1839 				 ipip_list_node) {
1840 		if (ipip_entry != except &&
1841 		    mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, saddr,
1842 						      ul_tb_id, ipip_entry)) {
1843 			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1844 			return true;
1845 		}
1846 	}
1847 
1848 	return false;
1849 }
1850 
1851 static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp *mlxsw_sp,
1852 						     struct net_device *ul_dev)
1853 {
1854 	struct mlxsw_sp_ipip_entry *ipip_entry, *tmp;
1855 
1856 	list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
1857 				 ipip_list_node) {
1858 		struct net_device *ol_dev = ipip_entry->ol_dev;
1859 		struct net_device *ipip_ul_dev;
1860 
1861 		rcu_read_lock();
1862 		ipip_ul_dev = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
1863 		rcu_read_unlock();
1864 		if (ipip_ul_dev == ul_dev)
1865 			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1866 	}
1867 }
1868 
1869 static int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
1870 					    struct net_device *ol_dev,
1871 					    unsigned long event,
1872 					    struct netdev_notifier_info *info)
1873 {
1874 	struct netdev_notifier_changeupper_info *chup;
1875 	struct netlink_ext_ack *extack;
1876 	int err = 0;
1877 
1878 	switch (event) {
1879 	case NETDEV_REGISTER:
1880 		err = mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp, ol_dev);
1881 		break;
1882 	case NETDEV_UNREGISTER:
1883 		mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp, ol_dev);
1884 		break;
1885 	case NETDEV_UP:
1886 		mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp, ol_dev);
1887 		break;
1888 	case NETDEV_DOWN:
1889 		mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp, ol_dev);
1890 		break;
1891 	case NETDEV_CHANGEUPPER:
1892 		chup = container_of(info, typeof(*chup), info);
1893 		extack = info->extack;
1894 		if (netif_is_l3_master(chup->upper_dev))
1895 			err = mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp,
1896 								   ol_dev,
1897 								   extack);
1898 		break;
1899 	case NETDEV_CHANGE:
1900 		extack = info->extack;
1901 		err = mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp,
1902 							      ol_dev, extack);
1903 		break;
1904 	case NETDEV_CHANGEMTU:
1905 		err = mlxsw_sp_netdevice_ipip_ol_update_mtu(mlxsw_sp, ol_dev);
1906 		break;
1907 	}
1908 	return err;
1909 }
1910 
1911 static int
1912 __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
1913 				   struct mlxsw_sp_ipip_entry *ipip_entry,
1914 				   struct net_device *ul_dev,
1915 				   bool *demote_this,
1916 				   unsigned long event,
1917 				   struct netdev_notifier_info *info)
1918 {
1919 	struct netdev_notifier_changeupper_info *chup;
1920 	struct netlink_ext_ack *extack;
1921 
1922 	switch (event) {
1923 	case NETDEV_CHANGEUPPER:
1924 		chup = container_of(info, typeof(*chup), info);
1925 		extack = info->extack;
1926 		if (netif_is_l3_master(chup->upper_dev))
1927 			return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp,
1928 								    ipip_entry,
1929 								    ul_dev,
1930 								    demote_this,
1931 								    extack);
1932 		break;
1933 
1934 	case NETDEV_UP:
1935 		return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp, ipip_entry,
1936 							   ul_dev);
1937 	case NETDEV_DOWN:
1938 		return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp,
1939 							     ipip_entry,
1940 							     ul_dev);
1941 	}
1942 	return 0;
1943 }
1944 
1945 static int
1946 mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
1947 				 struct net_device *ul_dev,
1948 				 unsigned long event,
1949 				 struct netdev_notifier_info *info)
1950 {
1951 	struct mlxsw_sp_ipip_entry *ipip_entry = NULL;
1952 	int err;
1953 
1954 	while ((ipip_entry = mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp,
1955 								ul_dev,
1956 								ipip_entry))) {
1957 		struct mlxsw_sp_ipip_entry *prev;
1958 		bool demote_this = false;
1959 
1960 		err = __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, ipip_entry,
1961 							 ul_dev, &demote_this,
1962 							 event, info);
1963 		if (err) {
1964 			mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp,
1965 								 ul_dev);
1966 			return err;
1967 		}
1968 
1969 		if (demote_this) {
1970 			if (list_is_first(&ipip_entry->ipip_list_node,
1971 					  &mlxsw_sp->router->ipip_list))
1972 				prev = NULL;
1973 			else
1974 				/* This can't be cached from previous iteration,
1975 				 * because that entry could be gone now.
1976 				 */
1977 				prev = list_prev_entry(ipip_entry,
1978 						       ipip_list_node);
1979 			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1980 			ipip_entry = prev;
1981 		}
1982 	}
1983 
1984 	return 0;
1985 }
1986 
1987 int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
1988 				      enum mlxsw_sp_l3proto ul_proto,
1989 				      const union mlxsw_sp_l3addr *ul_sip,
1990 				      u32 tunnel_index)
1991 {
1992 	enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1993 	struct mlxsw_sp_router *router = mlxsw_sp->router;
1994 	struct mlxsw_sp_fib_entry *fib_entry;
1995 	int err = 0;
1996 
1997 	mutex_lock(&mlxsw_sp->router->lock);
1998 
1999 	if (WARN_ON_ONCE(router->nve_decap_config.valid)) {
2000 		err = -EINVAL;
2001 		goto out;
2002 	}
2003 
2004 	router->nve_decap_config.ul_tb_id = ul_tb_id;
2005 	router->nve_decap_config.tunnel_index = tunnel_index;
2006 	router->nve_decap_config.ul_proto = ul_proto;
2007 	router->nve_decap_config.ul_sip = *ul_sip;
2008 	router->nve_decap_config.valid = true;
2009 
2010 	/* It is valid to create a tunnel with a local IP and only later
2011 	 * assign this IP address to a local interface
2012 	 */
2013 	fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
2014 							 ul_proto, ul_sip,
2015 							 type);
2016 	if (!fib_entry)
2017 		goto out;
2018 
2019 	fib_entry->decap.tunnel_index = tunnel_index;
2020 	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
2021 
2022 	err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
2023 	if (err)
2024 		goto err_fib_entry_update;
2025 
2026 	goto out;
2027 
2028 err_fib_entry_update:
2029 	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
2030 	mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
2031 out:
2032 	mutex_unlock(&mlxsw_sp->router->lock);
2033 	return err;
2034 }
2035 
2036 void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
2037 				      enum mlxsw_sp_l3proto ul_proto,
2038 				      const union mlxsw_sp_l3addr *ul_sip)
2039 {
2040 	enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
2041 	struct mlxsw_sp_router *router = mlxsw_sp->router;
2042 	struct mlxsw_sp_fib_entry *fib_entry;
2043 
2044 	mutex_lock(&mlxsw_sp->router->lock);
2045 
2046 	if (WARN_ON_ONCE(!router->nve_decap_config.valid))
2047 		goto out;
2048 
2049 	router->nve_decap_config.valid = false;
2050 
2051 	fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
2052 							 ul_proto, ul_sip,
2053 							 type);
2054 	if (!fib_entry)
2055 		goto out;
2056 
2057 	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
2058 	mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
2059 out:
2060 	mutex_unlock(&mlxsw_sp->router->lock);
2061 }
2062 
2063 static bool mlxsw_sp_router_nve_is_decap(struct mlxsw_sp *mlxsw_sp,
2064 					 u32 ul_tb_id,
2065 					 enum mlxsw_sp_l3proto ul_proto,
2066 					 const union mlxsw_sp_l3addr *ul_sip)
2067 {
2068 	struct mlxsw_sp_router *router = mlxsw_sp->router;
2069 
2070 	return router->nve_decap_config.valid &&
2071 	       router->nve_decap_config.ul_tb_id == ul_tb_id &&
2072 	       router->nve_decap_config.ul_proto == ul_proto &&
2073 	       !memcmp(&router->nve_decap_config.ul_sip, ul_sip,
2074 		       sizeof(*ul_sip));
2075 }
2076 
2077 struct mlxsw_sp_neigh_key {
2078 	struct neighbour *n;
2079 };
2080 
2081 struct mlxsw_sp_neigh_entry {
2082 	struct list_head rif_list_node;
2083 	struct rhash_head ht_node;
2084 	struct mlxsw_sp_neigh_key key;
2085 	u16 rif;
2086 	bool connected;
2087 	unsigned char ha[ETH_ALEN];
2088 	struct list_head nexthop_list; /* list of nexthops using
2089 					* this neigh entry
2090 					*/
2091 	struct list_head nexthop_neighs_list_node;
2092 	unsigned int counter_index;
2093 	bool counter_valid;
2094 };
2095 
2096 static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
2097 	.key_offset = offsetof(struct mlxsw_sp_neigh_entry, key),
2098 	.head_offset = offsetof(struct mlxsw_sp_neigh_entry, ht_node),
2099 	.key_len = sizeof(struct mlxsw_sp_neigh_key),
2100 };
2101 
2102 struct mlxsw_sp_neigh_entry *
2103 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif,
2104 			struct mlxsw_sp_neigh_entry *neigh_entry)
2105 {
2106 	if (!neigh_entry) {
2107 		if (list_empty(&rif->neigh_list))
2108 			return NULL;
2109 		else
2110 			return list_first_entry(&rif->neigh_list,
2111 						typeof(*neigh_entry),
2112 						rif_list_node);
2113 	}
2114 	if (list_is_last(&neigh_entry->rif_list_node, &rif->neigh_list))
2115 		return NULL;
2116 	return list_next_entry(neigh_entry, rif_list_node);
2117 }
2118 
2119 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry)
2120 {
2121 	return neigh_entry->key.n->tbl->family;
2122 }
2123 
2124 unsigned char *
2125 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry)
2126 {
2127 	return neigh_entry->ha;
2128 }
2129 
2130 u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
2131 {
2132 	struct neighbour *n;
2133 
2134 	n = neigh_entry->key.n;
2135 	return ntohl(*((__be32 *) n->primary_key));
2136 }
2137 
2138 struct in6_addr *
2139 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
2140 {
2141 	struct neighbour *n;
2142 
2143 	n = neigh_entry->key.n;
2144 	return (struct in6_addr *) &n->primary_key;
2145 }
2146 
2147 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
2148 			       struct mlxsw_sp_neigh_entry *neigh_entry,
2149 			       u64 *p_counter)
2150 {
2151 	if (!neigh_entry->counter_valid)
2152 		return -EINVAL;
2153 
2154 	return mlxsw_sp_flow_counter_get(mlxsw_sp, neigh_entry->counter_index,
2155 					 p_counter, NULL);
2156 }
2157 
2158 static struct mlxsw_sp_neigh_entry *
2159 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
2160 			   u16 rif)
2161 {
2162 	struct mlxsw_sp_neigh_entry *neigh_entry;
2163 
2164 	neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_KERNEL);
2165 	if (!neigh_entry)
2166 		return NULL;
2167 
2168 	neigh_entry->key.n = n;
2169 	neigh_entry->rif = rif;
2170 	INIT_LIST_HEAD(&neigh_entry->nexthop_list);
2171 
2172 	return neigh_entry;
2173 }
2174 
2175 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
2176 {
2177 	kfree(neigh_entry);
2178 }
2179 
2180 static int
2181 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp *mlxsw_sp,
2182 			    struct mlxsw_sp_neigh_entry *neigh_entry)
2183 {
2184 	return rhashtable_insert_fast(&mlxsw_sp->router->neigh_ht,
2185 				      &neigh_entry->ht_node,
2186 				      mlxsw_sp_neigh_ht_params);
2187 }
2188 
2189 static void
2190 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
2191 			    struct mlxsw_sp_neigh_entry *neigh_entry)
2192 {
2193 	rhashtable_remove_fast(&mlxsw_sp->router->neigh_ht,
2194 			       &neigh_entry->ht_node,
2195 			       mlxsw_sp_neigh_ht_params);
2196 }
2197 
2198 static bool
2199 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp *mlxsw_sp,
2200 				    struct mlxsw_sp_neigh_entry *neigh_entry)
2201 {
2202 	struct devlink *devlink;
2203 	const char *table_name;
2204 
2205 	switch (mlxsw_sp_neigh_entry_type(neigh_entry)) {
2206 	case AF_INET:
2207 		table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST4;
2208 		break;
2209 	case AF_INET6:
2210 		table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST6;
2211 		break;
2212 	default:
2213 		WARN_ON(1);
2214 		return false;
2215 	}
2216 
2217 	devlink = priv_to_devlink(mlxsw_sp->core);
2218 	return devlink_dpipe_table_counter_enabled(devlink, table_name);
2219 }
2220 
2221 static void
2222 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp,
2223 			     struct mlxsw_sp_neigh_entry *neigh_entry)
2224 {
2225 	if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp, neigh_entry))
2226 		return;
2227 
2228 	if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index))
2229 		return;
2230 
2231 	neigh_entry->counter_valid = true;
2232 }
2233 
2234 static void
2235 mlxsw_sp_neigh_counter_free(struct mlxsw_sp *mlxsw_sp,
2236 			    struct mlxsw_sp_neigh_entry *neigh_entry)
2237 {
2238 	if (!neigh_entry->counter_valid)
2239 		return;
2240 	mlxsw_sp_flow_counter_free(mlxsw_sp,
2241 				   neigh_entry->counter_index);
2242 	neigh_entry->counter_valid = false;
2243 }
2244 
2245 static struct mlxsw_sp_neigh_entry *
2246 mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
2247 {
2248 	struct mlxsw_sp_neigh_entry *neigh_entry;
2249 	struct mlxsw_sp_rif *rif;
2250 	int err;
2251 
2252 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
2253 	if (!rif)
2254 		return ERR_PTR(-EINVAL);
2255 
2256 	neigh_entry = mlxsw_sp_neigh_entry_alloc(mlxsw_sp, n, rif->rif_index);
2257 	if (!neigh_entry)
2258 		return ERR_PTR(-ENOMEM);
2259 
2260 	err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
2261 	if (err)
2262 		goto err_neigh_entry_insert;
2263 
2264 	mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
2265 	atomic_inc(&mlxsw_sp->router->neighs_update.neigh_count);
2266 	list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
2267 
2268 	return neigh_entry;
2269 
2270 err_neigh_entry_insert:
2271 	mlxsw_sp_neigh_entry_free(neigh_entry);
2272 	return ERR_PTR(err);
2273 }
2274 
2275 static void
2276 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
2277 			     struct mlxsw_sp_neigh_entry *neigh_entry)
2278 {
2279 	list_del(&neigh_entry->rif_list_node);
2280 	atomic_dec(&mlxsw_sp->router->neighs_update.neigh_count);
2281 	mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
2282 	mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
2283 	mlxsw_sp_neigh_entry_free(neigh_entry);
2284 }
2285 
2286 static struct mlxsw_sp_neigh_entry *
2287 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
2288 {
2289 	struct mlxsw_sp_neigh_key key;
2290 
2291 	key.n = n;
2292 	return rhashtable_lookup_fast(&mlxsw_sp->router->neigh_ht,
2293 				      &key, mlxsw_sp_neigh_ht_params);
2294 }
2295 
2296 static void
2297 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp)
2298 {
2299 	unsigned long interval;
2300 
2301 #if IS_ENABLED(CONFIG_IPV6)
2302 	interval = min_t(unsigned long,
2303 			 NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME),
2304 			 NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME));
2305 #else
2306 	interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME);
2307 #endif
2308 	mlxsw_sp->router->neighs_update.interval = jiffies_to_msecs(interval);
2309 }
2310 
2311 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
2312 						   char *rauhtd_pl,
2313 						   int ent_index)
2314 {
2315 	u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
2316 	struct net_device *dev;
2317 	struct neighbour *n;
2318 	__be32 dipn;
2319 	u32 dip;
2320 	u16 rif;
2321 
2322 	mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip);
2323 
2324 	if (WARN_ON_ONCE(rif >= max_rifs))
2325 		return;
2326 	if (!mlxsw_sp->router->rifs[rif]) {
2327 		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
2328 		return;
2329 	}
2330 
2331 	dipn = htonl(dip);
2332 	dev = mlxsw_sp->router->rifs[rif]->dev;
2333 	n = neigh_lookup(&arp_tbl, &dipn, dev);
2334 	if (!n)
2335 		return;
2336 
2337 	netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip);
2338 	neigh_event_send(n, NULL);
2339 	neigh_release(n);
2340 }
2341 
2342 #if IS_ENABLED(CONFIG_IPV6)
2343 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
2344 						   char *rauhtd_pl,
2345 						   int rec_index)
2346 {
2347 	struct net_device *dev;
2348 	struct neighbour *n;
2349 	struct in6_addr dip;
2350 	u16 rif;
2351 
2352 	mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl, rec_index, &rif,
2353 					 (char *) &dip);
2354 
2355 	if (!mlxsw_sp->router->rifs[rif]) {
2356 		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
2357 		return;
2358 	}
2359 
2360 	dev = mlxsw_sp->router->rifs[rif]->dev;
2361 	n = neigh_lookup(&nd_tbl, &dip, dev);
2362 	if (!n)
2363 		return;
2364 
2365 	netdev_dbg(dev, "Updating neighbour with IP=%pI6c\n", &dip);
2366 	neigh_event_send(n, NULL);
2367 	neigh_release(n);
2368 }
2369 #else
2370 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
2371 						   char *rauhtd_pl,
2372 						   int rec_index)
2373 {
2374 }
2375 #endif
2376 
2377 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
2378 						   char *rauhtd_pl,
2379 						   int rec_index)
2380 {
2381 	u8 num_entries;
2382 	int i;
2383 
2384 	num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
2385 								rec_index);
2386 	/* Hardware starts counting at 0, so add 1. */
2387 	num_entries++;
2388 
2389 	/* Each record consists of several neighbour entries. */
2390 	for (i = 0; i < num_entries; i++) {
2391 		int ent_index;
2392 
2393 		ent_index = rec_index * MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC + i;
2394 		mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp, rauhtd_pl,
2395 						       ent_index);
2396 	}
2397 
2398 }
2399 
2400 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp *mlxsw_sp,
2401 						   char *rauhtd_pl,
2402 						   int rec_index)
2403 {
2404 	/* One record contains one entry. */
2405 	mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp, rauhtd_pl,
2406 					       rec_index);
2407 }
2408 
2409 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
2410 					      char *rauhtd_pl, int rec_index)
2411 {
2412 	switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, rec_index)) {
2413 	case MLXSW_REG_RAUHTD_TYPE_IPV4:
2414 		mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp, rauhtd_pl,
2415 						       rec_index);
2416 		break;
2417 	case MLXSW_REG_RAUHTD_TYPE_IPV6:
2418 		mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp, rauhtd_pl,
2419 						       rec_index);
2420 		break;
2421 	}
2422 }
2423 
2424 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl)
2425 {
2426 	u8 num_rec, last_rec_index, num_entries;
2427 
2428 	num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
2429 	last_rec_index = num_rec - 1;
2430 
2431 	if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM)
2432 		return false;
2433 	if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) ==
2434 	    MLXSW_REG_RAUHTD_TYPE_IPV6)
2435 		return true;
2436 
2437 	num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
2438 								last_rec_index);
2439 	if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC)
2440 		return true;
2441 	return false;
2442 }
2443 
2444 static int
2445 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp,
2446 				       char *rauhtd_pl,
2447 				       enum mlxsw_reg_rauhtd_type type)
2448 {
2449 	int i, num_rec;
2450 	int err;
2451 
2452 	/* Ensure the RIF we read from the device does not change mid-dump. */
2453 	mutex_lock(&mlxsw_sp->router->lock);
2454 	do {
2455 		mlxsw_reg_rauhtd_pack(rauhtd_pl, type);
2456 		err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd),
2457 				      rauhtd_pl);
2458 		if (err) {
2459 			dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to dump neighbour table\n");
2460 			break;
2461 		}
2462 		num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
2463 		for (i = 0; i < num_rec; i++)
2464 			mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl,
2465 							  i);
2466 	} while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl));
2467 	mutex_unlock(&mlxsw_sp->router->lock);
2468 
2469 	return err;
2470 }
2471 
2472 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
2473 {
2474 	enum mlxsw_reg_rauhtd_type type;
2475 	char *rauhtd_pl;
2476 	int err;
2477 
2478 	if (!atomic_read(&mlxsw_sp->router->neighs_update.neigh_count))
2479 		return 0;
2480 
2481 	rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
2482 	if (!rauhtd_pl)
2483 		return -ENOMEM;
2484 
2485 	type = MLXSW_REG_RAUHTD_TYPE_IPV4;
2486 	err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
2487 	if (err)
2488 		goto out;
2489 
2490 	type = MLXSW_REG_RAUHTD_TYPE_IPV6;
2491 	err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
2492 out:
2493 	kfree(rauhtd_pl);
2494 	return err;
2495 }
2496 
2497 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
2498 {
2499 	struct mlxsw_sp_neigh_entry *neigh_entry;
2500 
2501 	mutex_lock(&mlxsw_sp->router->lock);
2502 	list_for_each_entry(neigh_entry, &mlxsw_sp->router->nexthop_neighs_list,
2503 			    nexthop_neighs_list_node)
2504 		/* If this neigh have nexthops, make the kernel think this neigh
2505 		 * is active regardless of the traffic.
2506 		 */
2507 		neigh_event_send(neigh_entry->key.n, NULL);
2508 	mutex_unlock(&mlxsw_sp->router->lock);
2509 }
2510 
2511 static void
2512 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
2513 {
2514 	unsigned long interval = mlxsw_sp->router->neighs_update.interval;
2515 
2516 	mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw,
2517 			       msecs_to_jiffies(interval));
2518 }
2519 
2520 static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
2521 {
2522 	struct mlxsw_sp_router *router;
2523 	int err;
2524 
2525 	router = container_of(work, struct mlxsw_sp_router,
2526 			      neighs_update.dw.work);
2527 	err = mlxsw_sp_router_neighs_update_rauhtd(router->mlxsw_sp);
2528 	if (err)
2529 		dev_err(router->mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity");
2530 
2531 	mlxsw_sp_router_neighs_update_nh(router->mlxsw_sp);
2532 
2533 	mlxsw_sp_router_neighs_update_work_schedule(router->mlxsw_sp);
2534 }
2535 
2536 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
2537 {
2538 	struct mlxsw_sp_neigh_entry *neigh_entry;
2539 	struct mlxsw_sp_router *router;
2540 
2541 	router = container_of(work, struct mlxsw_sp_router,
2542 			      nexthop_probe_dw.work);
2543 	/* Iterate over nexthop neighbours, find those who are unresolved and
2544 	 * send arp on them. This solves the chicken-egg problem when
2545 	 * the nexthop wouldn't get offloaded until the neighbor is resolved
2546 	 * but it wouldn't get resolved ever in case traffic is flowing in HW
2547 	 * using different nexthop.
2548 	 */
2549 	mutex_lock(&router->lock);
2550 	list_for_each_entry(neigh_entry, &router->nexthop_neighs_list,
2551 			    nexthop_neighs_list_node)
2552 		if (!neigh_entry->connected)
2553 			neigh_event_send(neigh_entry->key.n, NULL);
2554 	mutex_unlock(&router->lock);
2555 
2556 	mlxsw_core_schedule_dw(&router->nexthop_probe_dw,
2557 			       MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL);
2558 }
2559 
2560 static void
2561 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
2562 			      struct mlxsw_sp_neigh_entry *neigh_entry,
2563 			      bool removing, bool dead);
2564 
2565 static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
2566 {
2567 	return adding ? MLXSW_REG_RAUHT_OP_WRITE_ADD :
2568 			MLXSW_REG_RAUHT_OP_WRITE_DELETE;
2569 }
2570 
2571 static int
2572 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
2573 				struct mlxsw_sp_neigh_entry *neigh_entry,
2574 				enum mlxsw_reg_rauht_op op)
2575 {
2576 	struct neighbour *n = neigh_entry->key.n;
2577 	u32 dip = ntohl(*((__be32 *) n->primary_key));
2578 	char rauht_pl[MLXSW_REG_RAUHT_LEN];
2579 
2580 	mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
2581 			      dip);
2582 	if (neigh_entry->counter_valid)
2583 		mlxsw_reg_rauht_pack_counter(rauht_pl,
2584 					     neigh_entry->counter_index);
2585 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
2586 }
2587 
2588 static int
2589 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
2590 				struct mlxsw_sp_neigh_entry *neigh_entry,
2591 				enum mlxsw_reg_rauht_op op)
2592 {
2593 	struct neighbour *n = neigh_entry->key.n;
2594 	char rauht_pl[MLXSW_REG_RAUHT_LEN];
2595 	const char *dip = n->primary_key;
2596 
2597 	mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
2598 			      dip);
2599 	if (neigh_entry->counter_valid)
2600 		mlxsw_reg_rauht_pack_counter(rauht_pl,
2601 					     neigh_entry->counter_index);
2602 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
2603 }
2604 
2605 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry)
2606 {
2607 	struct neighbour *n = neigh_entry->key.n;
2608 
2609 	/* Packets with a link-local destination address are trapped
2610 	 * after LPM lookup and never reach the neighbour table, so
2611 	 * there is no need to program such neighbours to the device.
2612 	 */
2613 	if (ipv6_addr_type((struct in6_addr *) &n->primary_key) &
2614 	    IPV6_ADDR_LINKLOCAL)
2615 		return true;
2616 	return false;
2617 }
2618 
2619 static void
2620 mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
2621 			    struct mlxsw_sp_neigh_entry *neigh_entry,
2622 			    bool adding)
2623 {
2624 	enum mlxsw_reg_rauht_op op = mlxsw_sp_rauht_op(adding);
2625 	int err;
2626 
2627 	if (!adding && !neigh_entry->connected)
2628 		return;
2629 	neigh_entry->connected = adding;
2630 	if (neigh_entry->key.n->tbl->family == AF_INET) {
2631 		err = mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
2632 						      op);
2633 		if (err)
2634 			return;
2635 	} else if (neigh_entry->key.n->tbl->family == AF_INET6) {
2636 		if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
2637 			return;
2638 		err = mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
2639 						      op);
2640 		if (err)
2641 			return;
2642 	} else {
2643 		WARN_ON_ONCE(1);
2644 		return;
2645 	}
2646 
2647 	if (adding)
2648 		neigh_entry->key.n->flags |= NTF_OFFLOADED;
2649 	else
2650 		neigh_entry->key.n->flags &= ~NTF_OFFLOADED;
2651 }
2652 
2653 void
2654 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
2655 				    struct mlxsw_sp_neigh_entry *neigh_entry,
2656 				    bool adding)
2657 {
2658 	if (adding)
2659 		mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
2660 	else
2661 		mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
2662 	mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, true);
2663 }
2664 
2665 struct mlxsw_sp_netevent_work {
2666 	struct work_struct work;
2667 	struct mlxsw_sp *mlxsw_sp;
2668 	struct neighbour *n;
2669 };
2670 
2671 static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
2672 {
2673 	struct mlxsw_sp_netevent_work *net_work =
2674 		container_of(work, struct mlxsw_sp_netevent_work, work);
2675 	struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
2676 	struct mlxsw_sp_neigh_entry *neigh_entry;
2677 	struct neighbour *n = net_work->n;
2678 	unsigned char ha[ETH_ALEN];
2679 	bool entry_connected;
2680 	u8 nud_state, dead;
2681 
2682 	/* If these parameters are changed after we release the lock,
2683 	 * then we are guaranteed to receive another event letting us
2684 	 * know about it.
2685 	 */
2686 	read_lock_bh(&n->lock);
2687 	memcpy(ha, n->ha, ETH_ALEN);
2688 	nud_state = n->nud_state;
2689 	dead = n->dead;
2690 	read_unlock_bh(&n->lock);
2691 
2692 	mutex_lock(&mlxsw_sp->router->lock);
2693 	mlxsw_sp_span_respin(mlxsw_sp);
2694 
2695 	entry_connected = nud_state & NUD_VALID && !dead;
2696 	neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
2697 	if (!entry_connected && !neigh_entry)
2698 		goto out;
2699 	if (!neigh_entry) {
2700 		neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
2701 		if (IS_ERR(neigh_entry))
2702 			goto out;
2703 	}
2704 
2705 	if (neigh_entry->connected && entry_connected &&
2706 	    !memcmp(neigh_entry->ha, ha, ETH_ALEN))
2707 		goto out;
2708 
2709 	memcpy(neigh_entry->ha, ha, ETH_ALEN);
2710 	mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
2711 	mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected,
2712 				      dead);
2713 
2714 	if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
2715 		mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
2716 
2717 out:
2718 	mutex_unlock(&mlxsw_sp->router->lock);
2719 	neigh_release(n);
2720 	kfree(net_work);
2721 }
2722 
2723 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp);
2724 
2725 static void mlxsw_sp_router_mp_hash_event_work(struct work_struct *work)
2726 {
2727 	struct mlxsw_sp_netevent_work *net_work =
2728 		container_of(work, struct mlxsw_sp_netevent_work, work);
2729 	struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
2730 
2731 	mlxsw_sp_mp_hash_init(mlxsw_sp);
2732 	kfree(net_work);
2733 }
2734 
2735 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp);
2736 
2737 static void mlxsw_sp_router_update_priority_work(struct work_struct *work)
2738 {
2739 	struct mlxsw_sp_netevent_work *net_work =
2740 		container_of(work, struct mlxsw_sp_netevent_work, work);
2741 	struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
2742 
2743 	__mlxsw_sp_router_init(mlxsw_sp);
2744 	kfree(net_work);
2745 }
2746 
2747 static int mlxsw_sp_router_schedule_work(struct net *net,
2748 					 struct notifier_block *nb,
2749 					 void (*cb)(struct work_struct *))
2750 {
2751 	struct mlxsw_sp_netevent_work *net_work;
2752 	struct mlxsw_sp_router *router;
2753 
2754 	router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
2755 	if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp)))
2756 		return NOTIFY_DONE;
2757 
2758 	net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
2759 	if (!net_work)
2760 		return NOTIFY_BAD;
2761 
2762 	INIT_WORK(&net_work->work, cb);
2763 	net_work->mlxsw_sp = router->mlxsw_sp;
2764 	mlxsw_core_schedule_work(&net_work->work);
2765 	return NOTIFY_DONE;
2766 }
2767 
2768 static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
2769 					  unsigned long event, void *ptr)
2770 {
2771 	struct mlxsw_sp_netevent_work *net_work;
2772 	struct mlxsw_sp_port *mlxsw_sp_port;
2773 	struct mlxsw_sp *mlxsw_sp;
2774 	unsigned long interval;
2775 	struct neigh_parms *p;
2776 	struct neighbour *n;
2777 
2778 	switch (event) {
2779 	case NETEVENT_DELAY_PROBE_TIME_UPDATE:
2780 		p = ptr;
2781 
2782 		/* We don't care about changes in the default table. */
2783 		if (!p->dev || (p->tbl->family != AF_INET &&
2784 				p->tbl->family != AF_INET6))
2785 			return NOTIFY_DONE;
2786 
2787 		/* We are in atomic context and can't take RTNL mutex,
2788 		 * so use RCU variant to walk the device chain.
2789 		 */
2790 		mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
2791 		if (!mlxsw_sp_port)
2792 			return NOTIFY_DONE;
2793 
2794 		mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2795 		interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
2796 		mlxsw_sp->router->neighs_update.interval = interval;
2797 
2798 		mlxsw_sp_port_dev_put(mlxsw_sp_port);
2799 		break;
2800 	case NETEVENT_NEIGH_UPDATE:
2801 		n = ptr;
2802 
2803 		if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
2804 			return NOTIFY_DONE;
2805 
2806 		mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
2807 		if (!mlxsw_sp_port)
2808 			return NOTIFY_DONE;
2809 
2810 		net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
2811 		if (!net_work) {
2812 			mlxsw_sp_port_dev_put(mlxsw_sp_port);
2813 			return NOTIFY_BAD;
2814 		}
2815 
2816 		INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work);
2817 		net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2818 		net_work->n = n;
2819 
2820 		/* Take a reference to ensure the neighbour won't be
2821 		 * destructed until we drop the reference in delayed
2822 		 * work.
2823 		 */
2824 		neigh_clone(n);
2825 		mlxsw_core_schedule_work(&net_work->work);
2826 		mlxsw_sp_port_dev_put(mlxsw_sp_port);
2827 		break;
2828 	case NETEVENT_IPV4_MPATH_HASH_UPDATE:
2829 	case NETEVENT_IPV6_MPATH_HASH_UPDATE:
2830 		return mlxsw_sp_router_schedule_work(ptr, nb,
2831 				mlxsw_sp_router_mp_hash_event_work);
2832 
2833 	case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE:
2834 		return mlxsw_sp_router_schedule_work(ptr, nb,
2835 				mlxsw_sp_router_update_priority_work);
2836 	}
2837 
2838 	return NOTIFY_DONE;
2839 }
2840 
2841 static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
2842 {
2843 	int err;
2844 
2845 	err = rhashtable_init(&mlxsw_sp->router->neigh_ht,
2846 			      &mlxsw_sp_neigh_ht_params);
2847 	if (err)
2848 		return err;
2849 
2850 	/* Initialize the polling interval according to the default
2851 	 * table.
2852 	 */
2853 	mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp);
2854 
2855 	/* Create the delayed works for the activity_update */
2856 	INIT_DELAYED_WORK(&mlxsw_sp->router->neighs_update.dw,
2857 			  mlxsw_sp_router_neighs_update_work);
2858 	INIT_DELAYED_WORK(&mlxsw_sp->router->nexthop_probe_dw,
2859 			  mlxsw_sp_router_probe_unresolved_nexthops);
2860 	atomic_set(&mlxsw_sp->router->neighs_update.neigh_count, 0);
2861 	mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw, 0);
2862 	mlxsw_core_schedule_dw(&mlxsw_sp->router->nexthop_probe_dw, 0);
2863 	return 0;
2864 }
2865 
2866 static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp)
2867 {
2868 	cancel_delayed_work_sync(&mlxsw_sp->router->neighs_update.dw);
2869 	cancel_delayed_work_sync(&mlxsw_sp->router->nexthop_probe_dw);
2870 	rhashtable_destroy(&mlxsw_sp->router->neigh_ht);
2871 }
2872 
2873 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
2874 					 struct mlxsw_sp_rif *rif)
2875 {
2876 	struct mlxsw_sp_neigh_entry *neigh_entry, *tmp;
2877 
2878 	list_for_each_entry_safe(neigh_entry, tmp, &rif->neigh_list,
2879 				 rif_list_node) {
2880 		mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, false);
2881 		mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
2882 	}
2883 }
2884 
2885 enum mlxsw_sp_nexthop_type {
2886 	MLXSW_SP_NEXTHOP_TYPE_ETH,
2887 	MLXSW_SP_NEXTHOP_TYPE_IPIP,
2888 };
2889 
2890 enum mlxsw_sp_nexthop_action {
2891 	/* Nexthop forwards packets to an egress RIF */
2892 	MLXSW_SP_NEXTHOP_ACTION_FORWARD,
2893 	/* Nexthop discards packets */
2894 	MLXSW_SP_NEXTHOP_ACTION_DISCARD,
2895 	/* Nexthop traps packets */
2896 	MLXSW_SP_NEXTHOP_ACTION_TRAP,
2897 };
2898 
2899 struct mlxsw_sp_nexthop_key {
2900 	struct fib_nh *fib_nh;
2901 };
2902 
2903 struct mlxsw_sp_nexthop {
2904 	struct list_head neigh_list_node; /* member of neigh entry list */
2905 	struct list_head rif_list_node;
2906 	struct list_head router_list_node;
2907 	struct mlxsw_sp_nexthop_group_info *nhgi; /* pointer back to the group
2908 						   * this nexthop belongs to
2909 						   */
2910 	struct rhash_head ht_node;
2911 	struct neigh_table *neigh_tbl;
2912 	struct mlxsw_sp_nexthop_key key;
2913 	unsigned char gw_addr[sizeof(struct in6_addr)];
2914 	int ifindex;
2915 	int nh_weight;
2916 	int norm_nh_weight;
2917 	int num_adj_entries;
2918 	struct mlxsw_sp_rif *rif;
2919 	u8 should_offload:1, /* set indicates this nexthop should be written
2920 			      * to the adjacency table.
2921 			      */
2922 	   offloaded:1, /* set indicates this nexthop was written to the
2923 			 * adjacency table.
2924 			 */
2925 	   update:1; /* set indicates this nexthop should be updated in the
2926 		      * adjacency table (f.e., its MAC changed).
2927 		      */
2928 	enum mlxsw_sp_nexthop_action action;
2929 	enum mlxsw_sp_nexthop_type type;
2930 	union {
2931 		struct mlxsw_sp_neigh_entry *neigh_entry;
2932 		struct mlxsw_sp_ipip_entry *ipip_entry;
2933 	};
2934 	unsigned int counter_index;
2935 	bool counter_valid;
2936 };
2937 
2938 enum mlxsw_sp_nexthop_group_type {
2939 	MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4,
2940 	MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6,
2941 	MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ,
2942 };
2943 
2944 struct mlxsw_sp_nexthop_group_info {
2945 	struct mlxsw_sp_nexthop_group *nh_grp;
2946 	u32 adj_index;
2947 	u16 ecmp_size;
2948 	u16 count;
2949 	int sum_norm_weight;
2950 	u8 adj_index_valid:1,
2951 	   gateway:1, /* routes using the group use a gateway */
2952 	   is_resilient:1;
2953 	struct list_head list; /* member in nh_res_grp_list */
2954 	struct mlxsw_sp_nexthop nexthops[];
2955 #define nh_rif	nexthops[0].rif
2956 };
2957 
2958 struct mlxsw_sp_nexthop_group_vr_key {
2959 	u16 vr_id;
2960 	enum mlxsw_sp_l3proto proto;
2961 };
2962 
2963 struct mlxsw_sp_nexthop_group_vr_entry {
2964 	struct list_head list; /* member in vr_list */
2965 	struct rhash_head ht_node; /* member in vr_ht */
2966 	refcount_t ref_count;
2967 	struct mlxsw_sp_nexthop_group_vr_key key;
2968 };
2969 
2970 struct mlxsw_sp_nexthop_group {
2971 	struct rhash_head ht_node;
2972 	struct list_head fib_list; /* list of fib entries that use this group */
2973 	union {
2974 		struct {
2975 			struct fib_info *fi;
2976 		} ipv4;
2977 		struct {
2978 			u32 id;
2979 		} obj;
2980 	};
2981 	struct mlxsw_sp_nexthop_group_info *nhgi;
2982 	struct list_head vr_list;
2983 	struct rhashtable vr_ht;
2984 	enum mlxsw_sp_nexthop_group_type type;
2985 	bool can_destroy;
2986 };
2987 
2988 void mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp *mlxsw_sp,
2989 				    struct mlxsw_sp_nexthop *nh)
2990 {
2991 	struct devlink *devlink;
2992 
2993 	devlink = priv_to_devlink(mlxsw_sp->core);
2994 	if (!devlink_dpipe_table_counter_enabled(devlink,
2995 						 MLXSW_SP_DPIPE_TABLE_NAME_ADJ))
2996 		return;
2997 
2998 	if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &nh->counter_index))
2999 		return;
3000 
3001 	nh->counter_valid = true;
3002 }
3003 
3004 void mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp,
3005 				   struct mlxsw_sp_nexthop *nh)
3006 {
3007 	if (!nh->counter_valid)
3008 		return;
3009 	mlxsw_sp_flow_counter_free(mlxsw_sp, nh->counter_index);
3010 	nh->counter_valid = false;
3011 }
3012 
3013 int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp *mlxsw_sp,
3014 				 struct mlxsw_sp_nexthop *nh, u64 *p_counter)
3015 {
3016 	if (!nh->counter_valid)
3017 		return -EINVAL;
3018 
3019 	return mlxsw_sp_flow_counter_get(mlxsw_sp, nh->counter_index,
3020 					 p_counter, NULL);
3021 }
3022 
3023 struct mlxsw_sp_nexthop *mlxsw_sp_nexthop_next(struct mlxsw_sp_router *router,
3024 					       struct mlxsw_sp_nexthop *nh)
3025 {
3026 	if (!nh) {
3027 		if (list_empty(&router->nexthop_list))
3028 			return NULL;
3029 		else
3030 			return list_first_entry(&router->nexthop_list,
3031 						typeof(*nh), router_list_node);
3032 	}
3033 	if (list_is_last(&nh->router_list_node, &router->nexthop_list))
3034 		return NULL;
3035 	return list_next_entry(nh, router_list_node);
3036 }
3037 
3038 bool mlxsw_sp_nexthop_is_forward(const struct mlxsw_sp_nexthop *nh)
3039 {
3040 	return nh->offloaded && nh->action == MLXSW_SP_NEXTHOP_ACTION_FORWARD;
3041 }
3042 
3043 unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop *nh)
3044 {
3045 	if (nh->type != MLXSW_SP_NEXTHOP_TYPE_ETH ||
3046 	    !mlxsw_sp_nexthop_is_forward(nh))
3047 		return NULL;
3048 	return nh->neigh_entry->ha;
3049 }
3050 
3051 int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
3052 			     u32 *p_adj_size, u32 *p_adj_hash_index)
3053 {
3054 	struct mlxsw_sp_nexthop_group_info *nhgi = nh->nhgi;
3055 	u32 adj_hash_index = 0;
3056 	int i;
3057 
3058 	if (!nh->offloaded || !nhgi->adj_index_valid)
3059 		return -EINVAL;
3060 
3061 	*p_adj_index = nhgi->adj_index;
3062 	*p_adj_size = nhgi->ecmp_size;
3063 
3064 	for (i = 0; i < nhgi->count; i++) {
3065 		struct mlxsw_sp_nexthop *nh_iter = &nhgi->nexthops[i];
3066 
3067 		if (nh_iter == nh)
3068 			break;
3069 		if (nh_iter->offloaded)
3070 			adj_hash_index += nh_iter->num_adj_entries;
3071 	}
3072 
3073 	*p_adj_hash_index = adj_hash_index;
3074 	return 0;
3075 }
3076 
3077 struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh)
3078 {
3079 	return nh->rif;
3080 }
3081 
3082 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
3083 {
3084 	struct mlxsw_sp_nexthop_group_info *nhgi = nh->nhgi;
3085 	int i;
3086 
3087 	for (i = 0; i < nhgi->count; i++) {
3088 		struct mlxsw_sp_nexthop *nh_iter = &nhgi->nexthops[i];
3089 
3090 		if (nh_iter->type == MLXSW_SP_NEXTHOP_TYPE_IPIP)
3091 			return true;
3092 	}
3093 	return false;
3094 }
3095 
3096 static const struct rhashtable_params mlxsw_sp_nexthop_group_vr_ht_params = {
3097 	.key_offset = offsetof(struct mlxsw_sp_nexthop_group_vr_entry, key),
3098 	.head_offset = offsetof(struct mlxsw_sp_nexthop_group_vr_entry, ht_node),
3099 	.key_len = sizeof(struct mlxsw_sp_nexthop_group_vr_key),
3100 	.automatic_shrinking = true,
3101 };
3102 
3103 static struct mlxsw_sp_nexthop_group_vr_entry *
3104 mlxsw_sp_nexthop_group_vr_entry_lookup(struct mlxsw_sp_nexthop_group *nh_grp,
3105 				       const struct mlxsw_sp_fib *fib)
3106 {
3107 	struct mlxsw_sp_nexthop_group_vr_key key;
3108 
3109 	memset(&key, 0, sizeof(key));
3110 	key.vr_id = fib->vr->id;
3111 	key.proto = fib->proto;
3112 	return rhashtable_lookup_fast(&nh_grp->vr_ht, &key,
3113 				      mlxsw_sp_nexthop_group_vr_ht_params);
3114 }
3115 
3116 static int
3117 mlxsw_sp_nexthop_group_vr_entry_create(struct mlxsw_sp_nexthop_group *nh_grp,
3118 				       const struct mlxsw_sp_fib *fib)
3119 {
3120 	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
3121 	int err;
3122 
3123 	vr_entry = kzalloc(sizeof(*vr_entry), GFP_KERNEL);
3124 	if (!vr_entry)
3125 		return -ENOMEM;
3126 
3127 	vr_entry->key.vr_id = fib->vr->id;
3128 	vr_entry->key.proto = fib->proto;
3129 	refcount_set(&vr_entry->ref_count, 1);
3130 
3131 	err = rhashtable_insert_fast(&nh_grp->vr_ht, &vr_entry->ht_node,
3132 				     mlxsw_sp_nexthop_group_vr_ht_params);
3133 	if (err)
3134 		goto err_hashtable_insert;
3135 
3136 	list_add(&vr_entry->list, &nh_grp->vr_list);
3137 
3138 	return 0;
3139 
3140 err_hashtable_insert:
3141 	kfree(vr_entry);
3142 	return err;
3143 }
3144 
3145 static void
3146 mlxsw_sp_nexthop_group_vr_entry_destroy(struct mlxsw_sp_nexthop_group *nh_grp,
3147 					struct mlxsw_sp_nexthop_group_vr_entry *vr_entry)
3148 {
3149 	list_del(&vr_entry->list);
3150 	rhashtable_remove_fast(&nh_grp->vr_ht, &vr_entry->ht_node,
3151 			       mlxsw_sp_nexthop_group_vr_ht_params);
3152 	kfree(vr_entry);
3153 }
3154 
3155 static int
3156 mlxsw_sp_nexthop_group_vr_link(struct mlxsw_sp_nexthop_group *nh_grp,
3157 			       const struct mlxsw_sp_fib *fib)
3158 {
3159 	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
3160 
3161 	vr_entry = mlxsw_sp_nexthop_group_vr_entry_lookup(nh_grp, fib);
3162 	if (vr_entry) {
3163 		refcount_inc(&vr_entry->ref_count);
3164 		return 0;
3165 	}
3166 
3167 	return mlxsw_sp_nexthop_group_vr_entry_create(nh_grp, fib);
3168 }
3169 
3170 static void
3171 mlxsw_sp_nexthop_group_vr_unlink(struct mlxsw_sp_nexthop_group *nh_grp,
3172 				 const struct mlxsw_sp_fib *fib)
3173 {
3174 	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
3175 
3176 	vr_entry = mlxsw_sp_nexthop_group_vr_entry_lookup(nh_grp, fib);
3177 	if (WARN_ON_ONCE(!vr_entry))
3178 		return;
3179 
3180 	if (!refcount_dec_and_test(&vr_entry->ref_count))
3181 		return;
3182 
3183 	mlxsw_sp_nexthop_group_vr_entry_destroy(nh_grp, vr_entry);
3184 }
3185 
3186 struct mlxsw_sp_nexthop_group_cmp_arg {
3187 	enum mlxsw_sp_nexthop_group_type type;
3188 	union {
3189 		struct fib_info *fi;
3190 		struct mlxsw_sp_fib6_entry *fib6_entry;
3191 		u32 id;
3192 	};
3193 };
3194 
3195 static bool
3196 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group *nh_grp,
3197 				    const struct in6_addr *gw, int ifindex,
3198 				    int weight)
3199 {
3200 	int i;
3201 
3202 	for (i = 0; i < nh_grp->nhgi->count; i++) {
3203 		const struct mlxsw_sp_nexthop *nh;
3204 
3205 		nh = &nh_grp->nhgi->nexthops[i];
3206 		if (nh->ifindex == ifindex && nh->nh_weight == weight &&
3207 		    ipv6_addr_equal(gw, (struct in6_addr *) nh->gw_addr))
3208 			return true;
3209 	}
3210 
3211 	return false;
3212 }
3213 
3214 static bool
3215 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
3216 			    const struct mlxsw_sp_fib6_entry *fib6_entry)
3217 {
3218 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3219 
3220 	if (nh_grp->nhgi->count != fib6_entry->nrt6)
3221 		return false;
3222 
3223 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3224 		struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
3225 		struct in6_addr *gw;
3226 		int ifindex, weight;
3227 
3228 		ifindex = fib6_nh->fib_nh_dev->ifindex;
3229 		weight = fib6_nh->fib_nh_weight;
3230 		gw = &fib6_nh->fib_nh_gw6;
3231 		if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex,
3232 							 weight))
3233 			return false;
3234 	}
3235 
3236 	return true;
3237 }
3238 
3239 static int
3240 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg *arg, const void *ptr)
3241 {
3242 	const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = arg->key;
3243 	const struct mlxsw_sp_nexthop_group *nh_grp = ptr;
3244 
3245 	if (nh_grp->type != cmp_arg->type)
3246 		return 1;
3247 
3248 	switch (cmp_arg->type) {
3249 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
3250 		return cmp_arg->fi != nh_grp->ipv4.fi;
3251 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
3252 		return !mlxsw_sp_nexthop6_group_cmp(nh_grp,
3253 						    cmp_arg->fib6_entry);
3254 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
3255 		return cmp_arg->id != nh_grp->obj.id;
3256 	default:
3257 		WARN_ON(1);
3258 		return 1;
3259 	}
3260 }
3261 
3262 static u32 mlxsw_sp_nexthop_group_hash_obj(const void *data, u32 len, u32 seed)
3263 {
3264 	const struct mlxsw_sp_nexthop_group *nh_grp = data;
3265 	const struct mlxsw_sp_nexthop *nh;
3266 	struct fib_info *fi;
3267 	unsigned int val;
3268 	int i;
3269 
3270 	switch (nh_grp->type) {
3271 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
3272 		fi = nh_grp->ipv4.fi;
3273 		return jhash(&fi, sizeof(fi), seed);
3274 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
3275 		val = nh_grp->nhgi->count;
3276 		for (i = 0; i < nh_grp->nhgi->count; i++) {
3277 			nh = &nh_grp->nhgi->nexthops[i];
3278 			val ^= jhash(&nh->ifindex, sizeof(nh->ifindex), seed);
3279 			val ^= jhash(&nh->gw_addr, sizeof(nh->gw_addr), seed);
3280 		}
3281 		return jhash(&val, sizeof(val), seed);
3282 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
3283 		return jhash(&nh_grp->obj.id, sizeof(nh_grp->obj.id), seed);
3284 	default:
3285 		WARN_ON(1);
3286 		return 0;
3287 	}
3288 }
3289 
3290 static u32
3291 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
3292 {
3293 	unsigned int val = fib6_entry->nrt6;
3294 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3295 
3296 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3297 		struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
3298 		struct net_device *dev = fib6_nh->fib_nh_dev;
3299 		struct in6_addr *gw = &fib6_nh->fib_nh_gw6;
3300 
3301 		val ^= jhash(&dev->ifindex, sizeof(dev->ifindex), seed);
3302 		val ^= jhash(gw, sizeof(*gw), seed);
3303 	}
3304 
3305 	return jhash(&val, sizeof(val), seed);
3306 }
3307 
3308 static u32
3309 mlxsw_sp_nexthop_group_hash(const void *data, u32 len, u32 seed)
3310 {
3311 	const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = data;
3312 
3313 	switch (cmp_arg->type) {
3314 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
3315 		return jhash(&cmp_arg->fi, sizeof(cmp_arg->fi), seed);
3316 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
3317 		return mlxsw_sp_nexthop6_group_hash(cmp_arg->fib6_entry, seed);
3318 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
3319 		return jhash(&cmp_arg->id, sizeof(cmp_arg->id), seed);
3320 	default:
3321 		WARN_ON(1);
3322 		return 0;
3323 	}
3324 }
3325 
3326 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params = {
3327 	.head_offset = offsetof(struct mlxsw_sp_nexthop_group, ht_node),
3328 	.hashfn	     = mlxsw_sp_nexthop_group_hash,
3329 	.obj_hashfn  = mlxsw_sp_nexthop_group_hash_obj,
3330 	.obj_cmpfn   = mlxsw_sp_nexthop_group_cmp,
3331 };
3332 
3333 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp *mlxsw_sp,
3334 					 struct mlxsw_sp_nexthop_group *nh_grp)
3335 {
3336 	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6 &&
3337 	    !nh_grp->nhgi->gateway)
3338 		return 0;
3339 
3340 	return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_group_ht,
3341 				      &nh_grp->ht_node,
3342 				      mlxsw_sp_nexthop_group_ht_params);
3343 }
3344 
3345 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp *mlxsw_sp,
3346 					  struct mlxsw_sp_nexthop_group *nh_grp)
3347 {
3348 	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6 &&
3349 	    !nh_grp->nhgi->gateway)
3350 		return;
3351 
3352 	rhashtable_remove_fast(&mlxsw_sp->router->nexthop_group_ht,
3353 			       &nh_grp->ht_node,
3354 			       mlxsw_sp_nexthop_group_ht_params);
3355 }
3356 
3357 static struct mlxsw_sp_nexthop_group *
3358 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp *mlxsw_sp,
3359 			       struct fib_info *fi)
3360 {
3361 	struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
3362 
3363 	cmp_arg.type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4;
3364 	cmp_arg.fi = fi;
3365 	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
3366 				      &cmp_arg,
3367 				      mlxsw_sp_nexthop_group_ht_params);
3368 }
3369 
3370 static struct mlxsw_sp_nexthop_group *
3371 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp *mlxsw_sp,
3372 			       struct mlxsw_sp_fib6_entry *fib6_entry)
3373 {
3374 	struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
3375 
3376 	cmp_arg.type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6;
3377 	cmp_arg.fib6_entry = fib6_entry;
3378 	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
3379 				      &cmp_arg,
3380 				      mlxsw_sp_nexthop_group_ht_params);
3381 }
3382 
3383 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params = {
3384 	.key_offset = offsetof(struct mlxsw_sp_nexthop, key),
3385 	.head_offset = offsetof(struct mlxsw_sp_nexthop, ht_node),
3386 	.key_len = sizeof(struct mlxsw_sp_nexthop_key),
3387 };
3388 
3389 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp *mlxsw_sp,
3390 				   struct mlxsw_sp_nexthop *nh)
3391 {
3392 	return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_ht,
3393 				      &nh->ht_node, mlxsw_sp_nexthop_ht_params);
3394 }
3395 
3396 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp *mlxsw_sp,
3397 				    struct mlxsw_sp_nexthop *nh)
3398 {
3399 	rhashtable_remove_fast(&mlxsw_sp->router->nexthop_ht, &nh->ht_node,
3400 			       mlxsw_sp_nexthop_ht_params);
3401 }
3402 
3403 static struct mlxsw_sp_nexthop *
3404 mlxsw_sp_nexthop_lookup(struct mlxsw_sp *mlxsw_sp,
3405 			struct mlxsw_sp_nexthop_key key)
3406 {
3407 	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_ht, &key,
3408 				      mlxsw_sp_nexthop_ht_params);
3409 }
3410 
3411 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp *mlxsw_sp,
3412 					     enum mlxsw_sp_l3proto proto,
3413 					     u16 vr_id,
3414 					     u32 adj_index, u16 ecmp_size,
3415 					     u32 new_adj_index,
3416 					     u16 new_ecmp_size)
3417 {
3418 	char raleu_pl[MLXSW_REG_RALEU_LEN];
3419 
3420 	mlxsw_reg_raleu_pack(raleu_pl,
3421 			     (enum mlxsw_reg_ralxx_protocol) proto, vr_id,
3422 			     adj_index, ecmp_size, new_adj_index,
3423 			     new_ecmp_size);
3424 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raleu), raleu_pl);
3425 }
3426 
3427 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp *mlxsw_sp,
3428 					  struct mlxsw_sp_nexthop_group *nh_grp,
3429 					  u32 old_adj_index, u16 old_ecmp_size)
3430 {
3431 	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
3432 	struct mlxsw_sp_nexthop_group_vr_entry *vr_entry;
3433 	int err;
3434 
3435 	list_for_each_entry(vr_entry, &nh_grp->vr_list, list) {
3436 		err = mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp,
3437 							vr_entry->key.proto,
3438 							vr_entry->key.vr_id,
3439 							old_adj_index,
3440 							old_ecmp_size,
3441 							nhgi->adj_index,
3442 							nhgi->ecmp_size);
3443 		if (err)
3444 			goto err_mass_update_vr;
3445 	}
3446 	return 0;
3447 
3448 err_mass_update_vr:
3449 	list_for_each_entry_continue_reverse(vr_entry, &nh_grp->vr_list, list)
3450 		mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp, vr_entry->key.proto,
3451 						  vr_entry->key.vr_id,
3452 						  nhgi->adj_index,
3453 						  nhgi->ecmp_size,
3454 						  old_adj_index, old_ecmp_size);
3455 	return err;
3456 }
3457 
3458 static int __mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp,
3459 					 u32 adj_index,
3460 					 struct mlxsw_sp_nexthop *nh,
3461 					 bool force, char *ratr_pl)
3462 {
3463 	struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
3464 	enum mlxsw_reg_ratr_op op;
3465 	u16 rif_index;
3466 
3467 	rif_index = nh->rif ? nh->rif->rif_index :
3468 			      mlxsw_sp->router->lb_rif_index;
3469 	op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
3470 		     MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
3471 	mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_ETHERNET,
3472 			    adj_index, rif_index);
3473 	switch (nh->action) {
3474 	case MLXSW_SP_NEXTHOP_ACTION_FORWARD:
3475 		mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
3476 		break;
3477 	case MLXSW_SP_NEXTHOP_ACTION_DISCARD:
3478 		mlxsw_reg_ratr_trap_action_set(ratr_pl,
3479 					       MLXSW_REG_RATR_TRAP_ACTION_DISCARD_ERRORS);
3480 		break;
3481 	case MLXSW_SP_NEXTHOP_ACTION_TRAP:
3482 		mlxsw_reg_ratr_trap_action_set(ratr_pl,
3483 					       MLXSW_REG_RATR_TRAP_ACTION_TRAP);
3484 		mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
3485 		break;
3486 	default:
3487 		WARN_ON_ONCE(1);
3488 		return -EINVAL;
3489 	}
3490 	if (nh->counter_valid)
3491 		mlxsw_reg_ratr_counter_pack(ratr_pl, nh->counter_index, true);
3492 	else
3493 		mlxsw_reg_ratr_counter_pack(ratr_pl, 0, false);
3494 
3495 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
3496 }
3497 
3498 int mlxsw_sp_nexthop_eth_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
3499 				struct mlxsw_sp_nexthop *nh, bool force,
3500 				char *ratr_pl)
3501 {
3502 	int i;
3503 
3504 	for (i = 0; i < nh->num_adj_entries; i++) {
3505 		int err;
3506 
3507 		err = __mlxsw_sp_nexthop_eth_update(mlxsw_sp, adj_index + i,
3508 						    nh, force, ratr_pl);
3509 		if (err)
3510 			return err;
3511 	}
3512 
3513 	return 0;
3514 }
3515 
3516 static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
3517 					  u32 adj_index,
3518 					  struct mlxsw_sp_nexthop *nh,
3519 					  bool force, char *ratr_pl)
3520 {
3521 	const struct mlxsw_sp_ipip_ops *ipip_ops;
3522 
3523 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[nh->ipip_entry->ipipt];
3524 	return ipip_ops->nexthop_update(mlxsw_sp, adj_index, nh->ipip_entry,
3525 					force, ratr_pl);
3526 }
3527 
3528 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
3529 					u32 adj_index,
3530 					struct mlxsw_sp_nexthop *nh, bool force,
3531 					char *ratr_pl)
3532 {
3533 	int i;
3534 
3535 	for (i = 0; i < nh->num_adj_entries; i++) {
3536 		int err;
3537 
3538 		err = __mlxsw_sp_nexthop_ipip_update(mlxsw_sp, adj_index + i,
3539 						     nh, force, ratr_pl);
3540 		if (err)
3541 			return err;
3542 	}
3543 
3544 	return 0;
3545 }
3546 
3547 static int mlxsw_sp_nexthop_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
3548 				   struct mlxsw_sp_nexthop *nh, bool force,
3549 				   char *ratr_pl)
3550 {
3551 	/* When action is discard or trap, the nexthop must be
3552 	 * programmed as an Ethernet nexthop.
3553 	 */
3554 	if (nh->type == MLXSW_SP_NEXTHOP_TYPE_ETH ||
3555 	    nh->action == MLXSW_SP_NEXTHOP_ACTION_DISCARD ||
3556 	    nh->action == MLXSW_SP_NEXTHOP_ACTION_TRAP)
3557 		return mlxsw_sp_nexthop_eth_update(mlxsw_sp, adj_index, nh,
3558 						   force, ratr_pl);
3559 	else
3560 		return mlxsw_sp_nexthop_ipip_update(mlxsw_sp, adj_index, nh,
3561 						    force, ratr_pl);
3562 }
3563 
3564 static int
3565 mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
3566 			      struct mlxsw_sp_nexthop_group_info *nhgi,
3567 			      bool reallocate)
3568 {
3569 	char ratr_pl[MLXSW_REG_RATR_LEN];
3570 	u32 adj_index = nhgi->adj_index; /* base */
3571 	struct mlxsw_sp_nexthop *nh;
3572 	int i;
3573 
3574 	for (i = 0; i < nhgi->count; i++) {
3575 		nh = &nhgi->nexthops[i];
3576 
3577 		if (!nh->should_offload) {
3578 			nh->offloaded = 0;
3579 			continue;
3580 		}
3581 
3582 		if (nh->update || reallocate) {
3583 			int err = 0;
3584 
3585 			err = mlxsw_sp_nexthop_update(mlxsw_sp, adj_index, nh,
3586 						      true, ratr_pl);
3587 			if (err)
3588 				return err;
3589 			nh->update = 0;
3590 			nh->offloaded = 1;
3591 		}
3592 		adj_index += nh->num_adj_entries;
3593 	}
3594 	return 0;
3595 }
3596 
3597 static int
3598 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
3599 				    struct mlxsw_sp_nexthop_group *nh_grp)
3600 {
3601 	struct mlxsw_sp_fib_entry *fib_entry;
3602 	int err;
3603 
3604 	list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
3605 		err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
3606 		if (err)
3607 			return err;
3608 	}
3609 	return 0;
3610 }
3611 
3612 struct mlxsw_sp_adj_grp_size_range {
3613 	u16 start; /* Inclusive */
3614 	u16 end; /* Inclusive */
3615 };
3616 
3617 /* Ordered by range start value */
3618 static const struct mlxsw_sp_adj_grp_size_range
3619 mlxsw_sp1_adj_grp_size_ranges[] = {
3620 	{ .start = 1, .end = 64 },
3621 	{ .start = 512, .end = 512 },
3622 	{ .start = 1024, .end = 1024 },
3623 	{ .start = 2048, .end = 2048 },
3624 	{ .start = 4096, .end = 4096 },
3625 };
3626 
3627 /* Ordered by range start value */
3628 static const struct mlxsw_sp_adj_grp_size_range
3629 mlxsw_sp2_adj_grp_size_ranges[] = {
3630 	{ .start = 1, .end = 128 },
3631 	{ .start = 256, .end = 256 },
3632 	{ .start = 512, .end = 512 },
3633 	{ .start = 1024, .end = 1024 },
3634 	{ .start = 2048, .end = 2048 },
3635 	{ .start = 4096, .end = 4096 },
3636 };
3637 
3638 static void mlxsw_sp_adj_grp_size_round_up(const struct mlxsw_sp *mlxsw_sp,
3639 					   u16 *p_adj_grp_size)
3640 {
3641 	int i;
3642 
3643 	for (i = 0; i < mlxsw_sp->router->adj_grp_size_ranges_count; i++) {
3644 		const struct mlxsw_sp_adj_grp_size_range *size_range;
3645 
3646 		size_range = &mlxsw_sp->router->adj_grp_size_ranges[i];
3647 
3648 		if (*p_adj_grp_size >= size_range->start &&
3649 		    *p_adj_grp_size <= size_range->end)
3650 			return;
3651 
3652 		if (*p_adj_grp_size <= size_range->end) {
3653 			*p_adj_grp_size = size_range->end;
3654 			return;
3655 		}
3656 	}
3657 }
3658 
3659 static void mlxsw_sp_adj_grp_size_round_down(const struct mlxsw_sp *mlxsw_sp,
3660 					     u16 *p_adj_grp_size,
3661 					     unsigned int alloc_size)
3662 {
3663 	int i;
3664 
3665 	for (i = mlxsw_sp->router->adj_grp_size_ranges_count - 1; i >= 0; i--) {
3666 		const struct mlxsw_sp_adj_grp_size_range *size_range;
3667 
3668 		size_range = &mlxsw_sp->router->adj_grp_size_ranges[i];
3669 
3670 		if (alloc_size >= size_range->end) {
3671 			*p_adj_grp_size = size_range->end;
3672 			return;
3673 		}
3674 	}
3675 }
3676 
3677 static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp *mlxsw_sp,
3678 				     u16 *p_adj_grp_size)
3679 {
3680 	unsigned int alloc_size;
3681 	int err;
3682 
3683 	/* Round up the requested group size to the next size supported
3684 	 * by the device and make sure the request can be satisfied.
3685 	 */
3686 	mlxsw_sp_adj_grp_size_round_up(mlxsw_sp, p_adj_grp_size);
3687 	err = mlxsw_sp_kvdl_alloc_count_query(mlxsw_sp,
3688 					      MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3689 					      *p_adj_grp_size, &alloc_size);
3690 	if (err)
3691 		return err;
3692 	/* It is possible the allocation results in more allocated
3693 	 * entries than requested. Try to use as much of them as
3694 	 * possible.
3695 	 */
3696 	mlxsw_sp_adj_grp_size_round_down(mlxsw_sp, p_adj_grp_size, alloc_size);
3697 
3698 	return 0;
3699 }
3700 
3701 static void
3702 mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group_info *nhgi)
3703 {
3704 	int i, g = 0, sum_norm_weight = 0;
3705 	struct mlxsw_sp_nexthop *nh;
3706 
3707 	for (i = 0; i < nhgi->count; i++) {
3708 		nh = &nhgi->nexthops[i];
3709 
3710 		if (!nh->should_offload)
3711 			continue;
3712 		if (g > 0)
3713 			g = gcd(nh->nh_weight, g);
3714 		else
3715 			g = nh->nh_weight;
3716 	}
3717 
3718 	for (i = 0; i < nhgi->count; i++) {
3719 		nh = &nhgi->nexthops[i];
3720 
3721 		if (!nh->should_offload)
3722 			continue;
3723 		nh->norm_nh_weight = nh->nh_weight / g;
3724 		sum_norm_weight += nh->norm_nh_weight;
3725 	}
3726 
3727 	nhgi->sum_norm_weight = sum_norm_weight;
3728 }
3729 
3730 static void
3731 mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group_info *nhgi)
3732 {
3733 	int i, weight = 0, lower_bound = 0;
3734 	int total = nhgi->sum_norm_weight;
3735 	u16 ecmp_size = nhgi->ecmp_size;
3736 
3737 	for (i = 0; i < nhgi->count; i++) {
3738 		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
3739 		int upper_bound;
3740 
3741 		if (!nh->should_offload)
3742 			continue;
3743 		weight += nh->norm_nh_weight;
3744 		upper_bound = DIV_ROUND_CLOSEST(ecmp_size * weight, total);
3745 		nh->num_adj_entries = upper_bound - lower_bound;
3746 		lower_bound = upper_bound;
3747 	}
3748 }
3749 
3750 static struct mlxsw_sp_nexthop *
3751 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
3752 		     const struct mlxsw_sp_rt6 *mlxsw_sp_rt6);
3753 
3754 static void
3755 mlxsw_sp_nexthop4_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3756 					struct mlxsw_sp_nexthop_group *nh_grp)
3757 {
3758 	int i;
3759 
3760 	for (i = 0; i < nh_grp->nhgi->count; i++) {
3761 		struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
3762 
3763 		if (nh->offloaded)
3764 			nh->key.fib_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
3765 		else
3766 			nh->key.fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
3767 	}
3768 }
3769 
3770 static void
3771 __mlxsw_sp_nexthop6_group_offload_refresh(struct mlxsw_sp_nexthop_group *nh_grp,
3772 					  struct mlxsw_sp_fib6_entry *fib6_entry)
3773 {
3774 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3775 
3776 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3777 		struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
3778 		struct mlxsw_sp_nexthop *nh;
3779 
3780 		nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
3781 		if (nh && nh->offloaded)
3782 			fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
3783 		else
3784 			fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
3785 	}
3786 }
3787 
3788 static void
3789 mlxsw_sp_nexthop6_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3790 					struct mlxsw_sp_nexthop_group *nh_grp)
3791 {
3792 	struct mlxsw_sp_fib6_entry *fib6_entry;
3793 
3794 	/* Unfortunately, in IPv6 the route and the nexthop are described by
3795 	 * the same struct, so we need to iterate over all the routes using the
3796 	 * nexthop group and set / clear the offload indication for them.
3797 	 */
3798 	list_for_each_entry(fib6_entry, &nh_grp->fib_list,
3799 			    common.nexthop_group_node)
3800 		__mlxsw_sp_nexthop6_group_offload_refresh(nh_grp, fib6_entry);
3801 }
3802 
3803 static void
3804 mlxsw_sp_nexthop_bucket_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3805 					const struct mlxsw_sp_nexthop *nh,
3806 					u16 bucket_index)
3807 {
3808 	struct mlxsw_sp_nexthop_group *nh_grp = nh->nhgi->nh_grp;
3809 	bool offload = false, trap = false;
3810 
3811 	if (nh->offloaded) {
3812 		if (nh->action == MLXSW_SP_NEXTHOP_ACTION_TRAP)
3813 			trap = true;
3814 		else
3815 			offload = true;
3816 	}
3817 	nexthop_bucket_set_hw_flags(mlxsw_sp_net(mlxsw_sp), nh_grp->obj.id,
3818 				    bucket_index, offload, trap);
3819 }
3820 
3821 static void
3822 mlxsw_sp_nexthop_obj_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3823 					   struct mlxsw_sp_nexthop_group *nh_grp)
3824 {
3825 	int i;
3826 
3827 	/* Do not update the flags if the nexthop group is being destroyed
3828 	 * since:
3829 	 * 1. The nexthop objects is being deleted, in which case the flags are
3830 	 * irrelevant.
3831 	 * 2. The nexthop group was replaced by a newer group, in which case
3832 	 * the flags of the nexthop object were already updated based on the
3833 	 * new group.
3834 	 */
3835 	if (nh_grp->can_destroy)
3836 		return;
3837 
3838 	nexthop_set_hw_flags(mlxsw_sp_net(mlxsw_sp), nh_grp->obj.id,
3839 			     nh_grp->nhgi->adj_index_valid, false);
3840 
3841 	/* Update flags of individual nexthop buckets in case of a resilient
3842 	 * nexthop group.
3843 	 */
3844 	if (!nh_grp->nhgi->is_resilient)
3845 		return;
3846 
3847 	for (i = 0; i < nh_grp->nhgi->count; i++) {
3848 		struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
3849 
3850 		mlxsw_sp_nexthop_bucket_offload_refresh(mlxsw_sp, nh, i);
3851 	}
3852 }
3853 
3854 static void
3855 mlxsw_sp_nexthop_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3856 				       struct mlxsw_sp_nexthop_group *nh_grp)
3857 {
3858 	switch (nh_grp->type) {
3859 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4:
3860 		mlxsw_sp_nexthop4_group_offload_refresh(mlxsw_sp, nh_grp);
3861 		break;
3862 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6:
3863 		mlxsw_sp_nexthop6_group_offload_refresh(mlxsw_sp, nh_grp);
3864 		break;
3865 	case MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ:
3866 		mlxsw_sp_nexthop_obj_group_offload_refresh(mlxsw_sp, nh_grp);
3867 		break;
3868 	}
3869 }
3870 
3871 static int
3872 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
3873 			       struct mlxsw_sp_nexthop_group *nh_grp)
3874 {
3875 	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
3876 	u16 ecmp_size, old_ecmp_size;
3877 	struct mlxsw_sp_nexthop *nh;
3878 	bool offload_change = false;
3879 	u32 adj_index;
3880 	bool old_adj_index_valid;
3881 	u32 old_adj_index;
3882 	int i, err2, err;
3883 
3884 	if (!nhgi->gateway)
3885 		return mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
3886 
3887 	for (i = 0; i < nhgi->count; i++) {
3888 		nh = &nhgi->nexthops[i];
3889 
3890 		if (nh->should_offload != nh->offloaded) {
3891 			offload_change = true;
3892 			if (nh->should_offload)
3893 				nh->update = 1;
3894 		}
3895 	}
3896 	if (!offload_change) {
3897 		/* Nothing was added or removed, so no need to reallocate. Just
3898 		 * update MAC on existing adjacency indexes.
3899 		 */
3900 		err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nhgi, false);
3901 		if (err) {
3902 			dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
3903 			goto set_trap;
3904 		}
3905 		/* Flags of individual nexthop buckets might need to be
3906 		 * updated.
3907 		 */
3908 		mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
3909 		return 0;
3910 	}
3911 	mlxsw_sp_nexthop_group_normalize(nhgi);
3912 	if (!nhgi->sum_norm_weight) {
3913 		/* No neigh of this group is connected so we just set
3914 		 * the trap and let everthing flow through kernel.
3915 		 */
3916 		err = 0;
3917 		goto set_trap;
3918 	}
3919 
3920 	ecmp_size = nhgi->sum_norm_weight;
3921 	err = mlxsw_sp_fix_adj_grp_size(mlxsw_sp, &ecmp_size);
3922 	if (err)
3923 		/* No valid allocation size available. */
3924 		goto set_trap;
3925 
3926 	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3927 				  ecmp_size, &adj_index);
3928 	if (err) {
3929 		/* We ran out of KVD linear space, just set the
3930 		 * trap and let everything flow through kernel.
3931 		 */
3932 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to allocate KVD linear area for nexthop group.\n");
3933 		goto set_trap;
3934 	}
3935 	old_adj_index_valid = nhgi->adj_index_valid;
3936 	old_adj_index = nhgi->adj_index;
3937 	old_ecmp_size = nhgi->ecmp_size;
3938 	nhgi->adj_index_valid = 1;
3939 	nhgi->adj_index = adj_index;
3940 	nhgi->ecmp_size = ecmp_size;
3941 	mlxsw_sp_nexthop_group_rebalance(nhgi);
3942 	err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nhgi, true);
3943 	if (err) {
3944 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
3945 		goto set_trap;
3946 	}
3947 
3948 	mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
3949 
3950 	if (!old_adj_index_valid) {
3951 		/* The trap was set for fib entries, so we have to call
3952 		 * fib entry update to unset it and use adjacency index.
3953 		 */
3954 		err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
3955 		if (err) {
3956 			dev_warn(mlxsw_sp->bus_info->dev, "Failed to add adjacency index to fib entries.\n");
3957 			goto set_trap;
3958 		}
3959 		return 0;
3960 	}
3961 
3962 	err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, nh_grp,
3963 					     old_adj_index, old_ecmp_size);
3964 	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3965 			   old_ecmp_size, old_adj_index);
3966 	if (err) {
3967 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
3968 		goto set_trap;
3969 	}
3970 
3971 	return 0;
3972 
3973 set_trap:
3974 	old_adj_index_valid = nhgi->adj_index_valid;
3975 	nhgi->adj_index_valid = 0;
3976 	for (i = 0; i < nhgi->count; i++) {
3977 		nh = &nhgi->nexthops[i];
3978 		nh->offloaded = 0;
3979 	}
3980 	err2 = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
3981 	if (err2)
3982 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to set traps for fib entries.\n");
3983 	mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
3984 	if (old_adj_index_valid)
3985 		mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3986 				   nhgi->ecmp_size, nhgi->adj_index);
3987 	return err;
3988 }
3989 
3990 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
3991 					    bool removing)
3992 {
3993 	if (!removing) {
3994 		nh->action = MLXSW_SP_NEXTHOP_ACTION_FORWARD;
3995 		nh->should_offload = 1;
3996 	} else if (nh->nhgi->is_resilient) {
3997 		nh->action = MLXSW_SP_NEXTHOP_ACTION_TRAP;
3998 		nh->should_offload = 1;
3999 	} else {
4000 		nh->should_offload = 0;
4001 	}
4002 	nh->update = 1;
4003 }
4004 
4005 static int
4006 mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
4007 				    struct mlxsw_sp_neigh_entry *neigh_entry)
4008 {
4009 	struct neighbour *n, *old_n = neigh_entry->key.n;
4010 	struct mlxsw_sp_nexthop *nh;
4011 	bool entry_connected;
4012 	u8 nud_state, dead;
4013 	int err;
4014 
4015 	nh = list_first_entry(&neigh_entry->nexthop_list,
4016 			      struct mlxsw_sp_nexthop, neigh_list_node);
4017 
4018 	n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
4019 	if (!n) {
4020 		n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
4021 		if (IS_ERR(n))
4022 			return PTR_ERR(n);
4023 		neigh_event_send(n, NULL);
4024 	}
4025 
4026 	mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
4027 	neigh_entry->key.n = n;
4028 	err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
4029 	if (err)
4030 		goto err_neigh_entry_insert;
4031 
4032 	read_lock_bh(&n->lock);
4033 	nud_state = n->nud_state;
4034 	dead = n->dead;
4035 	read_unlock_bh(&n->lock);
4036 	entry_connected = nud_state & NUD_VALID && !dead;
4037 
4038 	list_for_each_entry(nh, &neigh_entry->nexthop_list,
4039 			    neigh_list_node) {
4040 		neigh_release(old_n);
4041 		neigh_clone(n);
4042 		__mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
4043 		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
4044 	}
4045 
4046 	neigh_release(n);
4047 
4048 	return 0;
4049 
4050 err_neigh_entry_insert:
4051 	neigh_entry->key.n = old_n;
4052 	mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
4053 	neigh_release(n);
4054 	return err;
4055 }
4056 
4057 static void
4058 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
4059 			      struct mlxsw_sp_neigh_entry *neigh_entry,
4060 			      bool removing, bool dead)
4061 {
4062 	struct mlxsw_sp_nexthop *nh;
4063 
4064 	if (list_empty(&neigh_entry->nexthop_list))
4065 		return;
4066 
4067 	if (dead) {
4068 		int err;
4069 
4070 		err = mlxsw_sp_nexthop_dead_neigh_replace(mlxsw_sp,
4071 							  neigh_entry);
4072 		if (err)
4073 			dev_err(mlxsw_sp->bus_info->dev, "Failed to replace dead neigh\n");
4074 		return;
4075 	}
4076 
4077 	list_for_each_entry(nh, &neigh_entry->nexthop_list,
4078 			    neigh_list_node) {
4079 		__mlxsw_sp_nexthop_neigh_update(nh, removing);
4080 		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
4081 	}
4082 }
4083 
4084 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
4085 				      struct mlxsw_sp_rif *rif)
4086 {
4087 	if (nh->rif)
4088 		return;
4089 
4090 	nh->rif = rif;
4091 	list_add(&nh->rif_list_node, &rif->nexthop_list);
4092 }
4093 
4094 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh)
4095 {
4096 	if (!nh->rif)
4097 		return;
4098 
4099 	list_del(&nh->rif_list_node);
4100 	nh->rif = NULL;
4101 }
4102 
4103 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
4104 				       struct mlxsw_sp_nexthop *nh)
4105 {
4106 	struct mlxsw_sp_neigh_entry *neigh_entry;
4107 	struct neighbour *n;
4108 	u8 nud_state, dead;
4109 	int err;
4110 
4111 	if (!nh->nhgi->gateway || nh->neigh_entry)
4112 		return 0;
4113 
4114 	/* Take a reference of neigh here ensuring that neigh would
4115 	 * not be destructed before the nexthop entry is finished.
4116 	 * The reference is taken either in neigh_lookup() or
4117 	 * in neigh_create() in case n is not found.
4118 	 */
4119 	n = neigh_lookup(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
4120 	if (!n) {
4121 		n = neigh_create(nh->neigh_tbl, &nh->gw_addr, nh->rif->dev);
4122 		if (IS_ERR(n))
4123 			return PTR_ERR(n);
4124 		neigh_event_send(n, NULL);
4125 	}
4126 	neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
4127 	if (!neigh_entry) {
4128 		neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
4129 		if (IS_ERR(neigh_entry)) {
4130 			err = -EINVAL;
4131 			goto err_neigh_entry_create;
4132 		}
4133 	}
4134 
4135 	/* If that is the first nexthop connected to that neigh, add to
4136 	 * nexthop_neighs_list
4137 	 */
4138 	if (list_empty(&neigh_entry->nexthop_list))
4139 		list_add_tail(&neigh_entry->nexthop_neighs_list_node,
4140 			      &mlxsw_sp->router->nexthop_neighs_list);
4141 
4142 	nh->neigh_entry = neigh_entry;
4143 	list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
4144 	read_lock_bh(&n->lock);
4145 	nud_state = n->nud_state;
4146 	dead = n->dead;
4147 	read_unlock_bh(&n->lock);
4148 	__mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
4149 
4150 	return 0;
4151 
4152 err_neigh_entry_create:
4153 	neigh_release(n);
4154 	return err;
4155 }
4156 
4157 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
4158 					struct mlxsw_sp_nexthop *nh)
4159 {
4160 	struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
4161 	struct neighbour *n;
4162 
4163 	if (!neigh_entry)
4164 		return;
4165 	n = neigh_entry->key.n;
4166 
4167 	__mlxsw_sp_nexthop_neigh_update(nh, true);
4168 	list_del(&nh->neigh_list_node);
4169 	nh->neigh_entry = NULL;
4170 
4171 	/* If that is the last nexthop connected to that neigh, remove from
4172 	 * nexthop_neighs_list
4173 	 */
4174 	if (list_empty(&neigh_entry->nexthop_list))
4175 		list_del(&neigh_entry->nexthop_neighs_list_node);
4176 
4177 	if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
4178 		mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
4179 
4180 	neigh_release(n);
4181 }
4182 
4183 static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
4184 {
4185 	struct net_device *ul_dev;
4186 	bool is_up;
4187 
4188 	rcu_read_lock();
4189 	ul_dev = mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
4190 	is_up = ul_dev ? (ul_dev->flags & IFF_UP) : true;
4191 	rcu_read_unlock();
4192 
4193 	return is_up;
4194 }
4195 
4196 static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
4197 				       struct mlxsw_sp_nexthop *nh,
4198 				       struct mlxsw_sp_ipip_entry *ipip_entry)
4199 {
4200 	bool removing;
4201 
4202 	if (!nh->nhgi->gateway || nh->ipip_entry)
4203 		return;
4204 
4205 	nh->ipip_entry = ipip_entry;
4206 	removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev);
4207 	__mlxsw_sp_nexthop_neigh_update(nh, removing);
4208 	mlxsw_sp_nexthop_rif_init(nh, &ipip_entry->ol_lb->common);
4209 }
4210 
4211 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
4212 				       struct mlxsw_sp_nexthop *nh)
4213 {
4214 	struct mlxsw_sp_ipip_entry *ipip_entry = nh->ipip_entry;
4215 
4216 	if (!ipip_entry)
4217 		return;
4218 
4219 	__mlxsw_sp_nexthop_neigh_update(nh, true);
4220 	nh->ipip_entry = NULL;
4221 }
4222 
4223 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp *mlxsw_sp,
4224 					const struct fib_nh *fib_nh,
4225 					enum mlxsw_sp_ipip_type *p_ipipt)
4226 {
4227 	struct net_device *dev = fib_nh->fib_nh_dev;
4228 
4229 	return dev &&
4230 	       fib_nh->nh_parent->fib_type == RTN_UNICAST &&
4231 	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, p_ipipt);
4232 }
4233 
4234 static int mlxsw_sp_nexthop_type_init(struct mlxsw_sp *mlxsw_sp,
4235 				      struct mlxsw_sp_nexthop *nh,
4236 				      const struct net_device *dev)
4237 {
4238 	const struct mlxsw_sp_ipip_ops *ipip_ops;
4239 	struct mlxsw_sp_ipip_entry *ipip_entry;
4240 	struct mlxsw_sp_rif *rif;
4241 	int err;
4242 
4243 	ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
4244 	if (ipip_entry) {
4245 		ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
4246 		if (ipip_ops->can_offload(mlxsw_sp, dev)) {
4247 			nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
4248 			mlxsw_sp_nexthop_ipip_init(mlxsw_sp, nh, ipip_entry);
4249 			return 0;
4250 		}
4251 	}
4252 
4253 	nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
4254 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
4255 	if (!rif)
4256 		return 0;
4257 
4258 	mlxsw_sp_nexthop_rif_init(nh, rif);
4259 	err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
4260 	if (err)
4261 		goto err_neigh_init;
4262 
4263 	return 0;
4264 
4265 err_neigh_init:
4266 	mlxsw_sp_nexthop_rif_fini(nh);
4267 	return err;
4268 }
4269 
4270 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
4271 				       struct mlxsw_sp_nexthop *nh)
4272 {
4273 	switch (nh->type) {
4274 	case MLXSW_SP_NEXTHOP_TYPE_ETH:
4275 		mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
4276 		mlxsw_sp_nexthop_rif_fini(nh);
4277 		break;
4278 	case MLXSW_SP_NEXTHOP_TYPE_IPIP:
4279 		mlxsw_sp_nexthop_rif_fini(nh);
4280 		mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
4281 		break;
4282 	}
4283 }
4284 
4285 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
4286 				  struct mlxsw_sp_nexthop_group *nh_grp,
4287 				  struct mlxsw_sp_nexthop *nh,
4288 				  struct fib_nh *fib_nh)
4289 {
4290 	struct net_device *dev = fib_nh->fib_nh_dev;
4291 	struct in_device *in_dev;
4292 	int err;
4293 
4294 	nh->nhgi = nh_grp->nhgi;
4295 	nh->key.fib_nh = fib_nh;
4296 #ifdef CONFIG_IP_ROUTE_MULTIPATH
4297 	nh->nh_weight = fib_nh->fib_nh_weight;
4298 #else
4299 	nh->nh_weight = 1;
4300 #endif
4301 	memcpy(&nh->gw_addr, &fib_nh->fib_nh_gw4, sizeof(fib_nh->fib_nh_gw4));
4302 	nh->neigh_tbl = &arp_tbl;
4303 	err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
4304 	if (err)
4305 		return err;
4306 
4307 	mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
4308 	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
4309 
4310 	if (!dev)
4311 		return 0;
4312 	nh->ifindex = dev->ifindex;
4313 
4314 	rcu_read_lock();
4315 	in_dev = __in_dev_get_rcu(dev);
4316 	if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
4317 	    fib_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
4318 		rcu_read_unlock();
4319 		return 0;
4320 	}
4321 	rcu_read_unlock();
4322 
4323 	err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
4324 	if (err)
4325 		goto err_nexthop_neigh_init;
4326 
4327 	return 0;
4328 
4329 err_nexthop_neigh_init:
4330 	list_del(&nh->router_list_node);
4331 	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
4332 	mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
4333 	return err;
4334 }
4335 
4336 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp *mlxsw_sp,
4337 				   struct mlxsw_sp_nexthop *nh)
4338 {
4339 	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4340 	list_del(&nh->router_list_node);
4341 	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
4342 	mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
4343 }
4344 
4345 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
4346 				    unsigned long event, struct fib_nh *fib_nh)
4347 {
4348 	struct mlxsw_sp_nexthop_key key;
4349 	struct mlxsw_sp_nexthop *nh;
4350 
4351 	key.fib_nh = fib_nh;
4352 	nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
4353 	if (!nh)
4354 		return;
4355 
4356 	switch (event) {
4357 	case FIB_EVENT_NH_ADD:
4358 		mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, fib_nh->fib_nh_dev);
4359 		break;
4360 	case FIB_EVENT_NH_DEL:
4361 		mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4362 		break;
4363 	}
4364 
4365 	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
4366 }
4367 
4368 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
4369 					struct mlxsw_sp_rif *rif)
4370 {
4371 	struct mlxsw_sp_nexthop *nh;
4372 	bool removing;
4373 
4374 	list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) {
4375 		switch (nh->type) {
4376 		case MLXSW_SP_NEXTHOP_TYPE_ETH:
4377 			removing = false;
4378 			break;
4379 		case MLXSW_SP_NEXTHOP_TYPE_IPIP:
4380 			removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev);
4381 			break;
4382 		default:
4383 			WARN_ON(1);
4384 			continue;
4385 		}
4386 
4387 		__mlxsw_sp_nexthop_neigh_update(nh, removing);
4388 		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
4389 	}
4390 }
4391 
4392 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
4393 					 struct mlxsw_sp_rif *old_rif,
4394 					 struct mlxsw_sp_rif *new_rif)
4395 {
4396 	struct mlxsw_sp_nexthop *nh;
4397 
4398 	list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list);
4399 	list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node)
4400 		nh->rif = new_rif;
4401 	mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
4402 }
4403 
4404 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
4405 					   struct mlxsw_sp_rif *rif)
4406 {
4407 	struct mlxsw_sp_nexthop *nh, *tmp;
4408 
4409 	list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
4410 		mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4411 		mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nhgi->nh_grp);
4412 	}
4413 }
4414 
4415 static int mlxsw_sp_adj_trap_entry_init(struct mlxsw_sp *mlxsw_sp)
4416 {
4417 	enum mlxsw_reg_ratr_trap_action trap_action;
4418 	char ratr_pl[MLXSW_REG_RATR_LEN];
4419 	int err;
4420 
4421 	err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
4422 				  &mlxsw_sp->router->adj_trap_index);
4423 	if (err)
4424 		return err;
4425 
4426 	trap_action = MLXSW_REG_RATR_TRAP_ACTION_TRAP;
4427 	mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
4428 			    MLXSW_REG_RATR_TYPE_ETHERNET,
4429 			    mlxsw_sp->router->adj_trap_index,
4430 			    mlxsw_sp->router->lb_rif_index);
4431 	mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
4432 	mlxsw_reg_ratr_trap_id_set(ratr_pl, MLXSW_TRAP_ID_RTR_EGRESS0);
4433 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
4434 	if (err)
4435 		goto err_ratr_write;
4436 
4437 	return 0;
4438 
4439 err_ratr_write:
4440 	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
4441 			   mlxsw_sp->router->adj_trap_index);
4442 	return err;
4443 }
4444 
4445 static void mlxsw_sp_adj_trap_entry_fini(struct mlxsw_sp *mlxsw_sp)
4446 {
4447 	mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
4448 			   mlxsw_sp->router->adj_trap_index);
4449 }
4450 
4451 static int mlxsw_sp_nexthop_group_inc(struct mlxsw_sp *mlxsw_sp)
4452 {
4453 	int err;
4454 
4455 	if (refcount_inc_not_zero(&mlxsw_sp->router->num_groups))
4456 		return 0;
4457 
4458 	err = mlxsw_sp_adj_trap_entry_init(mlxsw_sp);
4459 	if (err)
4460 		return err;
4461 
4462 	refcount_set(&mlxsw_sp->router->num_groups, 1);
4463 
4464 	return 0;
4465 }
4466 
4467 static void mlxsw_sp_nexthop_group_dec(struct mlxsw_sp *mlxsw_sp)
4468 {
4469 	if (!refcount_dec_and_test(&mlxsw_sp->router->num_groups))
4470 		return;
4471 
4472 	mlxsw_sp_adj_trap_entry_fini(mlxsw_sp);
4473 }
4474 
4475 static void
4476 mlxsw_sp_nh_grp_activity_get(struct mlxsw_sp *mlxsw_sp,
4477 			     const struct mlxsw_sp_nexthop_group *nh_grp,
4478 			     unsigned long *activity)
4479 {
4480 	char *ratrad_pl;
4481 	int i, err;
4482 
4483 	ratrad_pl = kmalloc(MLXSW_REG_RATRAD_LEN, GFP_KERNEL);
4484 	if (!ratrad_pl)
4485 		return;
4486 
4487 	mlxsw_reg_ratrad_pack(ratrad_pl, nh_grp->nhgi->adj_index,
4488 			      nh_grp->nhgi->count);
4489 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ratrad), ratrad_pl);
4490 	if (err)
4491 		goto out;
4492 
4493 	for (i = 0; i < nh_grp->nhgi->count; i++) {
4494 		if (!mlxsw_reg_ratrad_activity_vector_get(ratrad_pl, i))
4495 			continue;
4496 		bitmap_set(activity, i, 1);
4497 	}
4498 
4499 out:
4500 	kfree(ratrad_pl);
4501 }
4502 
4503 #define MLXSW_SP_NH_GRP_ACTIVITY_UPDATE_INTERVAL 1000 /* ms */
4504 
4505 static void
4506 mlxsw_sp_nh_grp_activity_update(struct mlxsw_sp *mlxsw_sp,
4507 				const struct mlxsw_sp_nexthop_group *nh_grp)
4508 {
4509 	unsigned long *activity;
4510 
4511 	activity = bitmap_zalloc(nh_grp->nhgi->count, GFP_KERNEL);
4512 	if (!activity)
4513 		return;
4514 
4515 	mlxsw_sp_nh_grp_activity_get(mlxsw_sp, nh_grp, activity);
4516 	nexthop_res_grp_activity_update(mlxsw_sp_net(mlxsw_sp), nh_grp->obj.id,
4517 					nh_grp->nhgi->count, activity);
4518 
4519 	bitmap_free(activity);
4520 }
4521 
4522 static void
4523 mlxsw_sp_nh_grp_activity_work_schedule(struct mlxsw_sp *mlxsw_sp)
4524 {
4525 	unsigned int interval = MLXSW_SP_NH_GRP_ACTIVITY_UPDATE_INTERVAL;
4526 
4527 	mlxsw_core_schedule_dw(&mlxsw_sp->router->nh_grp_activity_dw,
4528 			       msecs_to_jiffies(interval));
4529 }
4530 
4531 static void mlxsw_sp_nh_grp_activity_work(struct work_struct *work)
4532 {
4533 	struct mlxsw_sp_nexthop_group_info *nhgi;
4534 	struct mlxsw_sp_router *router;
4535 	bool reschedule = false;
4536 
4537 	router = container_of(work, struct mlxsw_sp_router,
4538 			      nh_grp_activity_dw.work);
4539 
4540 	mutex_lock(&router->lock);
4541 
4542 	list_for_each_entry(nhgi, &router->nh_res_grp_list, list) {
4543 		mlxsw_sp_nh_grp_activity_update(router->mlxsw_sp, nhgi->nh_grp);
4544 		reschedule = true;
4545 	}
4546 
4547 	mutex_unlock(&router->lock);
4548 
4549 	if (!reschedule)
4550 		return;
4551 	mlxsw_sp_nh_grp_activity_work_schedule(router->mlxsw_sp);
4552 }
4553 
4554 static int
4555 mlxsw_sp_nexthop_obj_single_validate(struct mlxsw_sp *mlxsw_sp,
4556 				     const struct nh_notifier_single_info *nh,
4557 				     struct netlink_ext_ack *extack)
4558 {
4559 	int err = -EINVAL;
4560 
4561 	if (nh->is_fdb)
4562 		NL_SET_ERR_MSG_MOD(extack, "FDB nexthops are not supported");
4563 	else if (nh->has_encap)
4564 		NL_SET_ERR_MSG_MOD(extack, "Encapsulating nexthops are not supported");
4565 	else
4566 		err = 0;
4567 
4568 	return err;
4569 }
4570 
4571 static int
4572 mlxsw_sp_nexthop_obj_group_entry_validate(struct mlxsw_sp *mlxsw_sp,
4573 					  const struct nh_notifier_single_info *nh,
4574 					  struct netlink_ext_ack *extack)
4575 {
4576 	int err;
4577 
4578 	err = mlxsw_sp_nexthop_obj_single_validate(mlxsw_sp, nh, extack);
4579 	if (err)
4580 		return err;
4581 
4582 	/* Device only nexthops with an IPIP device are programmed as
4583 	 * encapsulating adjacency entries.
4584 	 */
4585 	if (!nh->gw_family && !nh->is_reject &&
4586 	    !mlxsw_sp_netdev_ipip_type(mlxsw_sp, nh->dev, NULL)) {
4587 		NL_SET_ERR_MSG_MOD(extack, "Nexthop group entry does not have a gateway");
4588 		return -EINVAL;
4589 	}
4590 
4591 	return 0;
4592 }
4593 
4594 static int
4595 mlxsw_sp_nexthop_obj_group_validate(struct mlxsw_sp *mlxsw_sp,
4596 				    const struct nh_notifier_grp_info *nh_grp,
4597 				    struct netlink_ext_ack *extack)
4598 {
4599 	int i;
4600 
4601 	if (nh_grp->is_fdb) {
4602 		NL_SET_ERR_MSG_MOD(extack, "FDB nexthop groups are not supported");
4603 		return -EINVAL;
4604 	}
4605 
4606 	for (i = 0; i < nh_grp->num_nh; i++) {
4607 		const struct nh_notifier_single_info *nh;
4608 		int err;
4609 
4610 		nh = &nh_grp->nh_entries[i].nh;
4611 		err = mlxsw_sp_nexthop_obj_group_entry_validate(mlxsw_sp, nh,
4612 								extack);
4613 		if (err)
4614 			return err;
4615 	}
4616 
4617 	return 0;
4618 }
4619 
4620 static int
4621 mlxsw_sp_nexthop_obj_res_group_size_validate(struct mlxsw_sp *mlxsw_sp,
4622 					     const struct nh_notifier_res_table_info *nh_res_table,
4623 					     struct netlink_ext_ack *extack)
4624 {
4625 	unsigned int alloc_size;
4626 	bool valid_size = false;
4627 	int err, i;
4628 
4629 	if (nh_res_table->num_nh_buckets < 32) {
4630 		NL_SET_ERR_MSG_MOD(extack, "Minimum number of buckets is 32");
4631 		return -EINVAL;
4632 	}
4633 
4634 	for (i = 0; i < mlxsw_sp->router->adj_grp_size_ranges_count; i++) {
4635 		const struct mlxsw_sp_adj_grp_size_range *size_range;
4636 
4637 		size_range = &mlxsw_sp->router->adj_grp_size_ranges[i];
4638 
4639 		if (nh_res_table->num_nh_buckets >= size_range->start &&
4640 		    nh_res_table->num_nh_buckets <= size_range->end) {
4641 			valid_size = true;
4642 			break;
4643 		}
4644 	}
4645 
4646 	if (!valid_size) {
4647 		NL_SET_ERR_MSG_MOD(extack, "Invalid number of buckets");
4648 		return -EINVAL;
4649 	}
4650 
4651 	err = mlxsw_sp_kvdl_alloc_count_query(mlxsw_sp,
4652 					      MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
4653 					      nh_res_table->num_nh_buckets,
4654 					      &alloc_size);
4655 	if (err || nh_res_table->num_nh_buckets != alloc_size) {
4656 		NL_SET_ERR_MSG_MOD(extack, "Number of buckets does not fit allocation size of any KVDL partition");
4657 		return -EINVAL;
4658 	}
4659 
4660 	return 0;
4661 }
4662 
4663 static int
4664 mlxsw_sp_nexthop_obj_res_group_validate(struct mlxsw_sp *mlxsw_sp,
4665 					const struct nh_notifier_res_table_info *nh_res_table,
4666 					struct netlink_ext_ack *extack)
4667 {
4668 	int err;
4669 	u16 i;
4670 
4671 	err = mlxsw_sp_nexthop_obj_res_group_size_validate(mlxsw_sp,
4672 							   nh_res_table,
4673 							   extack);
4674 	if (err)
4675 		return err;
4676 
4677 	for (i = 0; i < nh_res_table->num_nh_buckets; i++) {
4678 		const struct nh_notifier_single_info *nh;
4679 		int err;
4680 
4681 		nh = &nh_res_table->nhs[i];
4682 		err = mlxsw_sp_nexthop_obj_group_entry_validate(mlxsw_sp, nh,
4683 								extack);
4684 		if (err)
4685 			return err;
4686 	}
4687 
4688 	return 0;
4689 }
4690 
4691 static int mlxsw_sp_nexthop_obj_validate(struct mlxsw_sp *mlxsw_sp,
4692 					 unsigned long event,
4693 					 struct nh_notifier_info *info)
4694 {
4695 	struct nh_notifier_single_info *nh;
4696 
4697 	if (event != NEXTHOP_EVENT_REPLACE &&
4698 	    event != NEXTHOP_EVENT_RES_TABLE_PRE_REPLACE &&
4699 	    event != NEXTHOP_EVENT_BUCKET_REPLACE)
4700 		return 0;
4701 
4702 	switch (info->type) {
4703 	case NH_NOTIFIER_INFO_TYPE_SINGLE:
4704 		return mlxsw_sp_nexthop_obj_single_validate(mlxsw_sp, info->nh,
4705 							    info->extack);
4706 	case NH_NOTIFIER_INFO_TYPE_GRP:
4707 		return mlxsw_sp_nexthop_obj_group_validate(mlxsw_sp,
4708 							   info->nh_grp,
4709 							   info->extack);
4710 	case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
4711 		return mlxsw_sp_nexthop_obj_res_group_validate(mlxsw_sp,
4712 							       info->nh_res_table,
4713 							       info->extack);
4714 	case NH_NOTIFIER_INFO_TYPE_RES_BUCKET:
4715 		nh = &info->nh_res_bucket->new_nh;
4716 		return mlxsw_sp_nexthop_obj_group_entry_validate(mlxsw_sp, nh,
4717 								 info->extack);
4718 	default:
4719 		NL_SET_ERR_MSG_MOD(info->extack, "Unsupported nexthop type");
4720 		return -EOPNOTSUPP;
4721 	}
4722 }
4723 
4724 static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp,
4725 					    const struct nh_notifier_info *info)
4726 {
4727 	const struct net_device *dev;
4728 
4729 	switch (info->type) {
4730 	case NH_NOTIFIER_INFO_TYPE_SINGLE:
4731 		dev = info->nh->dev;
4732 		return info->nh->gw_family || info->nh->is_reject ||
4733 		       mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
4734 	case NH_NOTIFIER_INFO_TYPE_GRP:
4735 	case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
4736 		/* Already validated earlier. */
4737 		return true;
4738 	default:
4739 		return false;
4740 	}
4741 }
4742 
4743 static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
4744 						struct mlxsw_sp_nexthop *nh)
4745 {
4746 	u16 lb_rif_index = mlxsw_sp->router->lb_rif_index;
4747 
4748 	nh->action = MLXSW_SP_NEXTHOP_ACTION_DISCARD;
4749 	nh->should_offload = 1;
4750 	/* While nexthops that discard packets do not forward packets
4751 	 * via an egress RIF, they still need to be programmed using a
4752 	 * valid RIF, so use the loopback RIF created during init.
4753 	 */
4754 	nh->rif = mlxsw_sp->router->rifs[lb_rif_index];
4755 }
4756 
4757 static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp,
4758 						struct mlxsw_sp_nexthop *nh)
4759 {
4760 	nh->rif = NULL;
4761 	nh->should_offload = 0;
4762 }
4763 
4764 static int
4765 mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
4766 			  struct mlxsw_sp_nexthop_group *nh_grp,
4767 			  struct mlxsw_sp_nexthop *nh,
4768 			  struct nh_notifier_single_info *nh_obj, int weight)
4769 {
4770 	struct net_device *dev = nh_obj->dev;
4771 	int err;
4772 
4773 	nh->nhgi = nh_grp->nhgi;
4774 	nh->nh_weight = weight;
4775 
4776 	switch (nh_obj->gw_family) {
4777 	case AF_INET:
4778 		memcpy(&nh->gw_addr, &nh_obj->ipv4, sizeof(nh_obj->ipv4));
4779 		nh->neigh_tbl = &arp_tbl;
4780 		break;
4781 	case AF_INET6:
4782 		memcpy(&nh->gw_addr, &nh_obj->ipv6, sizeof(nh_obj->ipv6));
4783 #if IS_ENABLED(CONFIG_IPV6)
4784 		nh->neigh_tbl = &nd_tbl;
4785 #endif
4786 		break;
4787 	}
4788 
4789 	mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
4790 	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
4791 	nh->ifindex = dev->ifindex;
4792 
4793 	err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
4794 	if (err)
4795 		goto err_type_init;
4796 
4797 	if (nh_obj->is_reject)
4798 		mlxsw_sp_nexthop_obj_blackhole_init(mlxsw_sp, nh);
4799 
4800 	/* In a resilient nexthop group, all the nexthops must be written to
4801 	 * the adjacency table. Even if they do not have a valid neighbour or
4802 	 * RIF.
4803 	 */
4804 	if (nh_grp->nhgi->is_resilient && !nh->should_offload) {
4805 		nh->action = MLXSW_SP_NEXTHOP_ACTION_TRAP;
4806 		nh->should_offload = 1;
4807 	}
4808 
4809 	return 0;
4810 
4811 err_type_init:
4812 	list_del(&nh->router_list_node);
4813 	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
4814 	return err;
4815 }
4816 
4817 static void mlxsw_sp_nexthop_obj_fini(struct mlxsw_sp *mlxsw_sp,
4818 				      struct mlxsw_sp_nexthop *nh)
4819 {
4820 	if (nh->action == MLXSW_SP_NEXTHOP_ACTION_DISCARD)
4821 		mlxsw_sp_nexthop_obj_blackhole_fini(mlxsw_sp, nh);
4822 	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
4823 	list_del(&nh->router_list_node);
4824 	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
4825 	nh->should_offload = 0;
4826 }
4827 
4828 static int
4829 mlxsw_sp_nexthop_obj_group_info_init(struct mlxsw_sp *mlxsw_sp,
4830 				     struct mlxsw_sp_nexthop_group *nh_grp,
4831 				     struct nh_notifier_info *info)
4832 {
4833 	struct mlxsw_sp_nexthop_group_info *nhgi;
4834 	struct mlxsw_sp_nexthop *nh;
4835 	bool is_resilient = false;
4836 	unsigned int nhs;
4837 	int err, i;
4838 
4839 	switch (info->type) {
4840 	case NH_NOTIFIER_INFO_TYPE_SINGLE:
4841 		nhs = 1;
4842 		break;
4843 	case NH_NOTIFIER_INFO_TYPE_GRP:
4844 		nhs = info->nh_grp->num_nh;
4845 		break;
4846 	case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
4847 		nhs = info->nh_res_table->num_nh_buckets;
4848 		is_resilient = true;
4849 		break;
4850 	default:
4851 		return -EINVAL;
4852 	}
4853 
4854 	nhgi = kzalloc(struct_size(nhgi, nexthops, nhs), GFP_KERNEL);
4855 	if (!nhgi)
4856 		return -ENOMEM;
4857 	nh_grp->nhgi = nhgi;
4858 	nhgi->nh_grp = nh_grp;
4859 	nhgi->gateway = mlxsw_sp_nexthop_obj_is_gateway(mlxsw_sp, info);
4860 	nhgi->is_resilient = is_resilient;
4861 	nhgi->count = nhs;
4862 	for (i = 0; i < nhgi->count; i++) {
4863 		struct nh_notifier_single_info *nh_obj;
4864 		int weight;
4865 
4866 		nh = &nhgi->nexthops[i];
4867 		switch (info->type) {
4868 		case NH_NOTIFIER_INFO_TYPE_SINGLE:
4869 			nh_obj = info->nh;
4870 			weight = 1;
4871 			break;
4872 		case NH_NOTIFIER_INFO_TYPE_GRP:
4873 			nh_obj = &info->nh_grp->nh_entries[i].nh;
4874 			weight = info->nh_grp->nh_entries[i].weight;
4875 			break;
4876 		case NH_NOTIFIER_INFO_TYPE_RES_TABLE:
4877 			nh_obj = &info->nh_res_table->nhs[i];
4878 			weight = 1;
4879 			break;
4880 		default:
4881 			err = -EINVAL;
4882 			goto err_nexthop_obj_init;
4883 		}
4884 		err = mlxsw_sp_nexthop_obj_init(mlxsw_sp, nh_grp, nh, nh_obj,
4885 						weight);
4886 		if (err)
4887 			goto err_nexthop_obj_init;
4888 	}
4889 	err = mlxsw_sp_nexthop_group_inc(mlxsw_sp);
4890 	if (err)
4891 		goto err_group_inc;
4892 	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4893 	if (err) {
4894 		NL_SET_ERR_MSG_MOD(info->extack, "Failed to write adjacency entries to the device");
4895 		goto err_group_refresh;
4896 	}
4897 
4898 	/* Add resilient nexthop groups to a list so that the activity of their
4899 	 * nexthop buckets will be periodically queried and cleared.
4900 	 */
4901 	if (nhgi->is_resilient) {
4902 		if (list_empty(&mlxsw_sp->router->nh_res_grp_list))
4903 			mlxsw_sp_nh_grp_activity_work_schedule(mlxsw_sp);
4904 		list_add(&nhgi->list, &mlxsw_sp->router->nh_res_grp_list);
4905 	}
4906 
4907 	return 0;
4908 
4909 err_group_refresh:
4910 	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
4911 err_group_inc:
4912 	i = nhgi->count;
4913 err_nexthop_obj_init:
4914 	for (i--; i >= 0; i--) {
4915 		nh = &nhgi->nexthops[i];
4916 		mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
4917 	}
4918 	kfree(nhgi);
4919 	return err;
4920 }
4921 
4922 static void
4923 mlxsw_sp_nexthop_obj_group_info_fini(struct mlxsw_sp *mlxsw_sp,
4924 				     struct mlxsw_sp_nexthop_group *nh_grp)
4925 {
4926 	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
4927 	struct mlxsw_sp_router *router = mlxsw_sp->router;
4928 	int i;
4929 
4930 	if (nhgi->is_resilient) {
4931 		list_del(&nhgi->list);
4932 		if (list_empty(&mlxsw_sp->router->nh_res_grp_list))
4933 			cancel_delayed_work(&router->nh_grp_activity_dw);
4934 	}
4935 
4936 	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
4937 	for (i = nhgi->count - 1; i >= 0; i--) {
4938 		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
4939 
4940 		mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
4941 	}
4942 	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4943 	WARN_ON_ONCE(nhgi->adj_index_valid);
4944 	kfree(nhgi);
4945 }
4946 
4947 static struct mlxsw_sp_nexthop_group *
4948 mlxsw_sp_nexthop_obj_group_create(struct mlxsw_sp *mlxsw_sp,
4949 				  struct nh_notifier_info *info)
4950 {
4951 	struct mlxsw_sp_nexthop_group *nh_grp;
4952 	int err;
4953 
4954 	nh_grp = kzalloc(sizeof(*nh_grp), GFP_KERNEL);
4955 	if (!nh_grp)
4956 		return ERR_PTR(-ENOMEM);
4957 	INIT_LIST_HEAD(&nh_grp->vr_list);
4958 	err = rhashtable_init(&nh_grp->vr_ht,
4959 			      &mlxsw_sp_nexthop_group_vr_ht_params);
4960 	if (err)
4961 		goto err_nexthop_group_vr_ht_init;
4962 	INIT_LIST_HEAD(&nh_grp->fib_list);
4963 	nh_grp->type = MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ;
4964 	nh_grp->obj.id = info->id;
4965 
4966 	err = mlxsw_sp_nexthop_obj_group_info_init(mlxsw_sp, nh_grp, info);
4967 	if (err)
4968 		goto err_nexthop_group_info_init;
4969 
4970 	nh_grp->can_destroy = false;
4971 
4972 	return nh_grp;
4973 
4974 err_nexthop_group_info_init:
4975 	rhashtable_destroy(&nh_grp->vr_ht);
4976 err_nexthop_group_vr_ht_init:
4977 	kfree(nh_grp);
4978 	return ERR_PTR(err);
4979 }
4980 
4981 static void
4982 mlxsw_sp_nexthop_obj_group_destroy(struct mlxsw_sp *mlxsw_sp,
4983 				   struct mlxsw_sp_nexthop_group *nh_grp)
4984 {
4985 	if (!nh_grp->can_destroy)
4986 		return;
4987 	mlxsw_sp_nexthop_obj_group_info_fini(mlxsw_sp, nh_grp);
4988 	WARN_ON_ONCE(!list_empty(&nh_grp->fib_list));
4989 	WARN_ON_ONCE(!list_empty(&nh_grp->vr_list));
4990 	rhashtable_destroy(&nh_grp->vr_ht);
4991 	kfree(nh_grp);
4992 }
4993 
4994 static struct mlxsw_sp_nexthop_group *
4995 mlxsw_sp_nexthop_obj_group_lookup(struct mlxsw_sp *mlxsw_sp, u32 id)
4996 {
4997 	struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
4998 
4999 	cmp_arg.type = MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ;
5000 	cmp_arg.id = id;
5001 	return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
5002 				      &cmp_arg,
5003 				      mlxsw_sp_nexthop_group_ht_params);
5004 }
5005 
5006 static int mlxsw_sp_nexthop_obj_group_add(struct mlxsw_sp *mlxsw_sp,
5007 					  struct mlxsw_sp_nexthop_group *nh_grp)
5008 {
5009 	return mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
5010 }
5011 
5012 static int
5013 mlxsw_sp_nexthop_obj_group_replace(struct mlxsw_sp *mlxsw_sp,
5014 				   struct mlxsw_sp_nexthop_group *nh_grp,
5015 				   struct mlxsw_sp_nexthop_group *old_nh_grp,
5016 				   struct netlink_ext_ack *extack)
5017 {
5018 	struct mlxsw_sp_nexthop_group_info *old_nhgi = old_nh_grp->nhgi;
5019 	struct mlxsw_sp_nexthop_group_info *new_nhgi = nh_grp->nhgi;
5020 	int err;
5021 
5022 	old_nh_grp->nhgi = new_nhgi;
5023 	new_nhgi->nh_grp = old_nh_grp;
5024 	nh_grp->nhgi = old_nhgi;
5025 	old_nhgi->nh_grp = nh_grp;
5026 
5027 	if (old_nhgi->adj_index_valid && new_nhgi->adj_index_valid) {
5028 		/* Both the old adjacency index and the new one are valid.
5029 		 * Routes are currently using the old one. Tell the device to
5030 		 * replace the old adjacency index with the new one.
5031 		 */
5032 		err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, old_nh_grp,
5033 						     old_nhgi->adj_index,
5034 						     old_nhgi->ecmp_size);
5035 		if (err) {
5036 			NL_SET_ERR_MSG_MOD(extack, "Failed to replace old adjacency index with new one");
5037 			goto err_out;
5038 		}
5039 	} else if (old_nhgi->adj_index_valid && !new_nhgi->adj_index_valid) {
5040 		/* The old adjacency index is valid, while the new one is not.
5041 		 * Iterate over all the routes using the group and change them
5042 		 * to trap packets to the CPU.
5043 		 */
5044 		err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, old_nh_grp);
5045 		if (err) {
5046 			NL_SET_ERR_MSG_MOD(extack, "Failed to update routes to trap packets");
5047 			goto err_out;
5048 		}
5049 	} else if (!old_nhgi->adj_index_valid && new_nhgi->adj_index_valid) {
5050 		/* The old adjacency index is invalid, while the new one is.
5051 		 * Iterate over all the routes using the group and change them
5052 		 * to forward packets using the new valid index.
5053 		 */
5054 		err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, old_nh_grp);
5055 		if (err) {
5056 			NL_SET_ERR_MSG_MOD(extack, "Failed to update routes to forward packets");
5057 			goto err_out;
5058 		}
5059 	}
5060 
5061 	/* Make sure the flags are set / cleared based on the new nexthop group
5062 	 * information.
5063 	 */
5064 	mlxsw_sp_nexthop_obj_group_offload_refresh(mlxsw_sp, old_nh_grp);
5065 
5066 	/* At this point 'nh_grp' is just a shell that is not used by anyone
5067 	 * and its nexthop group info is the old info that was just replaced
5068 	 * with the new one. Remove it.
5069 	 */
5070 	nh_grp->can_destroy = true;
5071 	mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
5072 
5073 	return 0;
5074 
5075 err_out:
5076 	old_nhgi->nh_grp = old_nh_grp;
5077 	nh_grp->nhgi = new_nhgi;
5078 	new_nhgi->nh_grp = nh_grp;
5079 	old_nh_grp->nhgi = old_nhgi;
5080 	return err;
5081 }
5082 
5083 static int mlxsw_sp_nexthop_obj_new(struct mlxsw_sp *mlxsw_sp,
5084 				    struct nh_notifier_info *info)
5085 {
5086 	struct mlxsw_sp_nexthop_group *nh_grp, *old_nh_grp;
5087 	struct netlink_ext_ack *extack = info->extack;
5088 	int err;
5089 
5090 	nh_grp = mlxsw_sp_nexthop_obj_group_create(mlxsw_sp, info);
5091 	if (IS_ERR(nh_grp))
5092 		return PTR_ERR(nh_grp);
5093 
5094 	old_nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
5095 	if (!old_nh_grp)
5096 		err = mlxsw_sp_nexthop_obj_group_add(mlxsw_sp, nh_grp);
5097 	else
5098 		err = mlxsw_sp_nexthop_obj_group_replace(mlxsw_sp, nh_grp,
5099 							 old_nh_grp, extack);
5100 
5101 	if (err) {
5102 		nh_grp->can_destroy = true;
5103 		mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
5104 	}
5105 
5106 	return err;
5107 }
5108 
5109 static void mlxsw_sp_nexthop_obj_del(struct mlxsw_sp *mlxsw_sp,
5110 				     struct nh_notifier_info *info)
5111 {
5112 	struct mlxsw_sp_nexthop_group *nh_grp;
5113 
5114 	nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
5115 	if (!nh_grp)
5116 		return;
5117 
5118 	nh_grp->can_destroy = true;
5119 	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
5120 
5121 	/* If the group still has routes using it, then defer the delete
5122 	 * operation until the last route using it is deleted.
5123 	 */
5124 	if (!list_empty(&nh_grp->fib_list))
5125 		return;
5126 	mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
5127 }
5128 
5129 static int mlxsw_sp_nexthop_obj_bucket_query(struct mlxsw_sp *mlxsw_sp,
5130 					     u32 adj_index, char *ratr_pl)
5131 {
5132 	MLXSW_REG_ZERO(ratr, ratr_pl);
5133 	mlxsw_reg_ratr_op_set(ratr_pl, MLXSW_REG_RATR_OP_QUERY_READ);
5134 	mlxsw_reg_ratr_adjacency_index_low_set(ratr_pl, adj_index);
5135 	mlxsw_reg_ratr_adjacency_index_high_set(ratr_pl, adj_index >> 16);
5136 
5137 	return mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
5138 }
5139 
5140 static int mlxsw_sp_nexthop_obj_bucket_compare(char *ratr_pl, char *ratr_pl_new)
5141 {
5142 	/* Clear the opcode and activity on both the old and new payload as
5143 	 * they are irrelevant for the comparison.
5144 	 */
5145 	mlxsw_reg_ratr_op_set(ratr_pl, MLXSW_REG_RATR_OP_QUERY_READ);
5146 	mlxsw_reg_ratr_a_set(ratr_pl, 0);
5147 	mlxsw_reg_ratr_op_set(ratr_pl_new, MLXSW_REG_RATR_OP_QUERY_READ);
5148 	mlxsw_reg_ratr_a_set(ratr_pl_new, 0);
5149 
5150 	/* If the contents of the adjacency entry are consistent with the
5151 	 * replacement request, then replacement was successful.
5152 	 */
5153 	if (!memcmp(ratr_pl, ratr_pl_new, MLXSW_REG_RATR_LEN))
5154 		return 0;
5155 
5156 	return -EINVAL;
5157 }
5158 
5159 static int
5160 mlxsw_sp_nexthop_obj_bucket_adj_update(struct mlxsw_sp *mlxsw_sp,
5161 				       struct mlxsw_sp_nexthop *nh,
5162 				       struct nh_notifier_info *info)
5163 {
5164 	u16 bucket_index = info->nh_res_bucket->bucket_index;
5165 	struct netlink_ext_ack *extack = info->extack;
5166 	bool force = info->nh_res_bucket->force;
5167 	char ratr_pl_new[MLXSW_REG_RATR_LEN];
5168 	char ratr_pl[MLXSW_REG_RATR_LEN];
5169 	u32 adj_index;
5170 	int err;
5171 
5172 	/* No point in trying an atomic replacement if the idle timer interval
5173 	 * is smaller than the interval in which we query and clear activity.
5174 	 */
5175 	if (!force && info->nh_res_bucket->idle_timer_ms <
5176 	    MLXSW_SP_NH_GRP_ACTIVITY_UPDATE_INTERVAL)
5177 		force = true;
5178 
5179 	adj_index = nh->nhgi->adj_index + bucket_index;
5180 	err = mlxsw_sp_nexthop_update(mlxsw_sp, adj_index, nh, force, ratr_pl);
5181 	if (err) {
5182 		NL_SET_ERR_MSG_MOD(extack, "Failed to overwrite nexthop bucket");
5183 		return err;
5184 	}
5185 
5186 	if (!force) {
5187 		err = mlxsw_sp_nexthop_obj_bucket_query(mlxsw_sp, adj_index,
5188 							ratr_pl_new);
5189 		if (err) {
5190 			NL_SET_ERR_MSG_MOD(extack, "Failed to query nexthop bucket state after replacement. State might be inconsistent");
5191 			return err;
5192 		}
5193 
5194 		err = mlxsw_sp_nexthop_obj_bucket_compare(ratr_pl, ratr_pl_new);
5195 		if (err) {
5196 			NL_SET_ERR_MSG_MOD(extack, "Nexthop bucket was not replaced because it was active during replacement");
5197 			return err;
5198 		}
5199 	}
5200 
5201 	nh->update = 0;
5202 	nh->offloaded = 1;
5203 	mlxsw_sp_nexthop_bucket_offload_refresh(mlxsw_sp, nh, bucket_index);
5204 
5205 	return 0;
5206 }
5207 
5208 static int mlxsw_sp_nexthop_obj_bucket_replace(struct mlxsw_sp *mlxsw_sp,
5209 					       struct nh_notifier_info *info)
5210 {
5211 	u16 bucket_index = info->nh_res_bucket->bucket_index;
5212 	struct netlink_ext_ack *extack = info->extack;
5213 	struct mlxsw_sp_nexthop_group_info *nhgi;
5214 	struct nh_notifier_single_info *nh_obj;
5215 	struct mlxsw_sp_nexthop_group *nh_grp;
5216 	struct mlxsw_sp_nexthop *nh;
5217 	int err;
5218 
5219 	nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, info->id);
5220 	if (!nh_grp) {
5221 		NL_SET_ERR_MSG_MOD(extack, "Nexthop group was not found");
5222 		return -EINVAL;
5223 	}
5224 
5225 	nhgi = nh_grp->nhgi;
5226 
5227 	if (bucket_index >= nhgi->count) {
5228 		NL_SET_ERR_MSG_MOD(extack, "Nexthop bucket index out of range");
5229 		return -EINVAL;
5230 	}
5231 
5232 	nh = &nhgi->nexthops[bucket_index];
5233 	mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
5234 
5235 	nh_obj = &info->nh_res_bucket->new_nh;
5236 	err = mlxsw_sp_nexthop_obj_init(mlxsw_sp, nh_grp, nh, nh_obj, 1);
5237 	if (err) {
5238 		NL_SET_ERR_MSG_MOD(extack, "Failed to initialize nexthop object for nexthop bucket replacement");
5239 		goto err_nexthop_obj_init;
5240 	}
5241 
5242 	err = mlxsw_sp_nexthop_obj_bucket_adj_update(mlxsw_sp, nh, info);
5243 	if (err)
5244 		goto err_nexthop_obj_bucket_adj_update;
5245 
5246 	return 0;
5247 
5248 err_nexthop_obj_bucket_adj_update:
5249 	mlxsw_sp_nexthop_obj_fini(mlxsw_sp, nh);
5250 err_nexthop_obj_init:
5251 	nh_obj = &info->nh_res_bucket->old_nh;
5252 	mlxsw_sp_nexthop_obj_init(mlxsw_sp, nh_grp, nh, nh_obj, 1);
5253 	/* The old adjacency entry was not overwritten */
5254 	nh->update = 0;
5255 	nh->offloaded = 1;
5256 	return err;
5257 }
5258 
5259 static int mlxsw_sp_nexthop_obj_event(struct notifier_block *nb,
5260 				      unsigned long event, void *ptr)
5261 {
5262 	struct nh_notifier_info *info = ptr;
5263 	struct mlxsw_sp_router *router;
5264 	int err = 0;
5265 
5266 	router = container_of(nb, struct mlxsw_sp_router, nexthop_nb);
5267 	err = mlxsw_sp_nexthop_obj_validate(router->mlxsw_sp, event, info);
5268 	if (err)
5269 		goto out;
5270 
5271 	mutex_lock(&router->lock);
5272 
5273 	switch (event) {
5274 	case NEXTHOP_EVENT_REPLACE:
5275 		err = mlxsw_sp_nexthop_obj_new(router->mlxsw_sp, info);
5276 		break;
5277 	case NEXTHOP_EVENT_DEL:
5278 		mlxsw_sp_nexthop_obj_del(router->mlxsw_sp, info);
5279 		break;
5280 	case NEXTHOP_EVENT_BUCKET_REPLACE:
5281 		err = mlxsw_sp_nexthop_obj_bucket_replace(router->mlxsw_sp,
5282 							  info);
5283 		break;
5284 	default:
5285 		break;
5286 	}
5287 
5288 	mutex_unlock(&router->lock);
5289 
5290 out:
5291 	return notifier_from_errno(err);
5292 }
5293 
5294 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp,
5295 				   struct fib_info *fi)
5296 {
5297 	const struct fib_nh *nh = fib_info_nh(fi, 0);
5298 
5299 	return nh->fib_nh_gw_family ||
5300 	       mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, nh, NULL);
5301 }
5302 
5303 static int
5304 mlxsw_sp_nexthop4_group_info_init(struct mlxsw_sp *mlxsw_sp,
5305 				  struct mlxsw_sp_nexthop_group *nh_grp)
5306 {
5307 	unsigned int nhs = fib_info_num_path(nh_grp->ipv4.fi);
5308 	struct mlxsw_sp_nexthop_group_info *nhgi;
5309 	struct mlxsw_sp_nexthop *nh;
5310 	int err, i;
5311 
5312 	nhgi = kzalloc(struct_size(nhgi, nexthops, nhs), GFP_KERNEL);
5313 	if (!nhgi)
5314 		return -ENOMEM;
5315 	nh_grp->nhgi = nhgi;
5316 	nhgi->nh_grp = nh_grp;
5317 	nhgi->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, nh_grp->ipv4.fi);
5318 	nhgi->count = nhs;
5319 	for (i = 0; i < nhgi->count; i++) {
5320 		struct fib_nh *fib_nh;
5321 
5322 		nh = &nhgi->nexthops[i];
5323 		fib_nh = fib_info_nh(nh_grp->ipv4.fi, i);
5324 		err = mlxsw_sp_nexthop4_init(mlxsw_sp, nh_grp, nh, fib_nh);
5325 		if (err)
5326 			goto err_nexthop4_init;
5327 	}
5328 	err = mlxsw_sp_nexthop_group_inc(mlxsw_sp);
5329 	if (err)
5330 		goto err_group_inc;
5331 	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
5332 	if (err)
5333 		goto err_group_refresh;
5334 
5335 	return 0;
5336 
5337 err_group_refresh:
5338 	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
5339 err_group_inc:
5340 	i = nhgi->count;
5341 err_nexthop4_init:
5342 	for (i--; i >= 0; i--) {
5343 		nh = &nhgi->nexthops[i];
5344 		mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
5345 	}
5346 	kfree(nhgi);
5347 	return err;
5348 }
5349 
5350 static void
5351 mlxsw_sp_nexthop4_group_info_fini(struct mlxsw_sp *mlxsw_sp,
5352 				  struct mlxsw_sp_nexthop_group *nh_grp)
5353 {
5354 	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
5355 	int i;
5356 
5357 	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
5358 	for (i = nhgi->count - 1; i >= 0; i--) {
5359 		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
5360 
5361 		mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
5362 	}
5363 	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
5364 	WARN_ON_ONCE(nhgi->adj_index_valid);
5365 	kfree(nhgi);
5366 }
5367 
5368 static struct mlxsw_sp_nexthop_group *
5369 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
5370 {
5371 	struct mlxsw_sp_nexthop_group *nh_grp;
5372 	int err;
5373 
5374 	nh_grp = kzalloc(sizeof(*nh_grp), GFP_KERNEL);
5375 	if (!nh_grp)
5376 		return ERR_PTR(-ENOMEM);
5377 	INIT_LIST_HEAD(&nh_grp->vr_list);
5378 	err = rhashtable_init(&nh_grp->vr_ht,
5379 			      &mlxsw_sp_nexthop_group_vr_ht_params);
5380 	if (err)
5381 		goto err_nexthop_group_vr_ht_init;
5382 	INIT_LIST_HEAD(&nh_grp->fib_list);
5383 	nh_grp->type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV4;
5384 	nh_grp->ipv4.fi = fi;
5385 	fib_info_hold(fi);
5386 
5387 	err = mlxsw_sp_nexthop4_group_info_init(mlxsw_sp, nh_grp);
5388 	if (err)
5389 		goto err_nexthop_group_info_init;
5390 
5391 	err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
5392 	if (err)
5393 		goto err_nexthop_group_insert;
5394 
5395 	nh_grp->can_destroy = true;
5396 
5397 	return nh_grp;
5398 
5399 err_nexthop_group_insert:
5400 	mlxsw_sp_nexthop4_group_info_fini(mlxsw_sp, nh_grp);
5401 err_nexthop_group_info_init:
5402 	fib_info_put(fi);
5403 	rhashtable_destroy(&nh_grp->vr_ht);
5404 err_nexthop_group_vr_ht_init:
5405 	kfree(nh_grp);
5406 	return ERR_PTR(err);
5407 }
5408 
5409 static void
5410 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp *mlxsw_sp,
5411 				struct mlxsw_sp_nexthop_group *nh_grp)
5412 {
5413 	if (!nh_grp->can_destroy)
5414 		return;
5415 	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
5416 	mlxsw_sp_nexthop4_group_info_fini(mlxsw_sp, nh_grp);
5417 	fib_info_put(nh_grp->ipv4.fi);
5418 	WARN_ON_ONCE(!list_empty(&nh_grp->vr_list));
5419 	rhashtable_destroy(&nh_grp->vr_ht);
5420 	kfree(nh_grp);
5421 }
5422 
5423 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp *mlxsw_sp,
5424 				       struct mlxsw_sp_fib_entry *fib_entry,
5425 				       struct fib_info *fi)
5426 {
5427 	struct mlxsw_sp_nexthop_group *nh_grp;
5428 
5429 	if (fi->nh) {
5430 		nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp,
5431 							   fi->nh->id);
5432 		if (WARN_ON_ONCE(!nh_grp))
5433 			return -EINVAL;
5434 		goto out;
5435 	}
5436 
5437 	nh_grp = mlxsw_sp_nexthop4_group_lookup(mlxsw_sp, fi);
5438 	if (!nh_grp) {
5439 		nh_grp = mlxsw_sp_nexthop4_group_create(mlxsw_sp, fi);
5440 		if (IS_ERR(nh_grp))
5441 			return PTR_ERR(nh_grp);
5442 	}
5443 out:
5444 	list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list);
5445 	fib_entry->nh_group = nh_grp;
5446 	return 0;
5447 }
5448 
5449 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp *mlxsw_sp,
5450 					struct mlxsw_sp_fib_entry *fib_entry)
5451 {
5452 	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
5453 
5454 	list_del(&fib_entry->nexthop_group_node);
5455 	if (!list_empty(&nh_grp->fib_list))
5456 		return;
5457 
5458 	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ) {
5459 		mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
5460 		return;
5461 	}
5462 
5463 	mlxsw_sp_nexthop4_group_destroy(mlxsw_sp, nh_grp);
5464 }
5465 
5466 static bool
5467 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
5468 {
5469 	struct mlxsw_sp_fib4_entry *fib4_entry;
5470 
5471 	fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
5472 				  common);
5473 	return !fib4_entry->dscp;
5474 }
5475 
5476 static bool
5477 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
5478 {
5479 	struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
5480 
5481 	switch (fib_entry->fib_node->fib->proto) {
5482 	case MLXSW_SP_L3_PROTO_IPV4:
5483 		if (!mlxsw_sp_fib4_entry_should_offload(fib_entry))
5484 			return false;
5485 		break;
5486 	case MLXSW_SP_L3_PROTO_IPV6:
5487 		break;
5488 	}
5489 
5490 	switch (fib_entry->type) {
5491 	case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
5492 		return !!nh_group->nhgi->adj_index_valid;
5493 	case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
5494 		return !!nh_group->nhgi->nh_rif;
5495 	case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
5496 	case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
5497 	case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
5498 		return true;
5499 	default:
5500 		return false;
5501 	}
5502 }
5503 
5504 static struct mlxsw_sp_nexthop *
5505 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
5506 		     const struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
5507 {
5508 	int i;
5509 
5510 	for (i = 0; i < nh_grp->nhgi->count; i++) {
5511 		struct mlxsw_sp_nexthop *nh = &nh_grp->nhgi->nexthops[i];
5512 		struct fib6_info *rt = mlxsw_sp_rt6->rt;
5513 
5514 		if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev &&
5515 		    ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
5516 				    &rt->fib6_nh->fib_nh_gw6))
5517 			return nh;
5518 	}
5519 
5520 	return NULL;
5521 }
5522 
5523 static void
5524 mlxsw_sp_fib4_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
5525 				      struct fib_entry_notifier_info *fen_info)
5526 {
5527 	u32 *p_dst = (u32 *) &fen_info->dst;
5528 	struct fib_rt_info fri;
5529 
5530 	fri.fi = fen_info->fi;
5531 	fri.tb_id = fen_info->tb_id;
5532 	fri.dst = cpu_to_be32(*p_dst);
5533 	fri.dst_len = fen_info->dst_len;
5534 	fri.dscp = fen_info->dscp;
5535 	fri.type = fen_info->type;
5536 	fri.offload = false;
5537 	fri.trap = false;
5538 	fri.offload_failed = true;
5539 	fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
5540 }
5541 
5542 static void
5543 mlxsw_sp_fib4_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
5544 				 struct mlxsw_sp_fib_entry *fib_entry)
5545 {
5546 	u32 *p_dst = (u32 *) fib_entry->fib_node->key.addr;
5547 	int dst_len = fib_entry->fib_node->key.prefix_len;
5548 	struct mlxsw_sp_fib4_entry *fib4_entry;
5549 	struct fib_rt_info fri;
5550 	bool should_offload;
5551 
5552 	should_offload = mlxsw_sp_fib_entry_should_offload(fib_entry);
5553 	fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
5554 				  common);
5555 	fri.fi = fib4_entry->fi;
5556 	fri.tb_id = fib4_entry->tb_id;
5557 	fri.dst = cpu_to_be32(*p_dst);
5558 	fri.dst_len = dst_len;
5559 	fri.dscp = fib4_entry->dscp;
5560 	fri.type = fib4_entry->type;
5561 	fri.offload = should_offload;
5562 	fri.trap = !should_offload;
5563 	fri.offload_failed = false;
5564 	fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
5565 }
5566 
5567 static void
5568 mlxsw_sp_fib4_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
5569 				   struct mlxsw_sp_fib_entry *fib_entry)
5570 {
5571 	u32 *p_dst = (u32 *) fib_entry->fib_node->key.addr;
5572 	int dst_len = fib_entry->fib_node->key.prefix_len;
5573 	struct mlxsw_sp_fib4_entry *fib4_entry;
5574 	struct fib_rt_info fri;
5575 
5576 	fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
5577 				  common);
5578 	fri.fi = fib4_entry->fi;
5579 	fri.tb_id = fib4_entry->tb_id;
5580 	fri.dst = cpu_to_be32(*p_dst);
5581 	fri.dst_len = dst_len;
5582 	fri.dscp = fib4_entry->dscp;
5583 	fri.type = fib4_entry->type;
5584 	fri.offload = false;
5585 	fri.trap = false;
5586 	fri.offload_failed = false;
5587 	fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
5588 }
5589 
5590 #if IS_ENABLED(CONFIG_IPV6)
5591 static void
5592 mlxsw_sp_fib6_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
5593 				      struct fib6_info **rt_arr,
5594 				      unsigned int nrt6)
5595 {
5596 	int i;
5597 
5598 	/* In IPv6 a multipath route is represented using multiple routes, so
5599 	 * we need to set the flags on all of them.
5600 	 */
5601 	for (i = 0; i < nrt6; i++)
5602 		fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), rt_arr[i],
5603 				       false, false, true);
5604 }
5605 #else
5606 static void
5607 mlxsw_sp_fib6_offload_failed_flag_set(struct mlxsw_sp *mlxsw_sp,
5608 				      struct fib6_info **rt_arr,
5609 				      unsigned int nrt6)
5610 {
5611 }
5612 #endif
5613 
5614 #if IS_ENABLED(CONFIG_IPV6)
5615 static void
5616 mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
5617 				 struct mlxsw_sp_fib_entry *fib_entry)
5618 {
5619 	struct mlxsw_sp_fib6_entry *fib6_entry;
5620 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5621 	bool should_offload;
5622 
5623 	should_offload = mlxsw_sp_fib_entry_should_offload(fib_entry);
5624 
5625 	/* In IPv6 a multipath route is represented using multiple routes, so
5626 	 * we need to set the flags on all of them.
5627 	 */
5628 	fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
5629 				  common);
5630 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
5631 		fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), mlxsw_sp_rt6->rt,
5632 				       should_offload, !should_offload, false);
5633 }
5634 #else
5635 static void
5636 mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
5637 				 struct mlxsw_sp_fib_entry *fib_entry)
5638 {
5639 }
5640 #endif
5641 
5642 #if IS_ENABLED(CONFIG_IPV6)
5643 static void
5644 mlxsw_sp_fib6_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
5645 				   struct mlxsw_sp_fib_entry *fib_entry)
5646 {
5647 	struct mlxsw_sp_fib6_entry *fib6_entry;
5648 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5649 
5650 	fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
5651 				  common);
5652 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
5653 		fib6_info_hw_flags_set(mlxsw_sp_net(mlxsw_sp), mlxsw_sp_rt6->rt,
5654 				       false, false, false);
5655 }
5656 #else
5657 static void
5658 mlxsw_sp_fib6_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
5659 				   struct mlxsw_sp_fib_entry *fib_entry)
5660 {
5661 }
5662 #endif
5663 
5664 static void
5665 mlxsw_sp_fib_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
5666 				struct mlxsw_sp_fib_entry *fib_entry)
5667 {
5668 	switch (fib_entry->fib_node->fib->proto) {
5669 	case MLXSW_SP_L3_PROTO_IPV4:
5670 		mlxsw_sp_fib4_entry_hw_flags_set(mlxsw_sp, fib_entry);
5671 		break;
5672 	case MLXSW_SP_L3_PROTO_IPV6:
5673 		mlxsw_sp_fib6_entry_hw_flags_set(mlxsw_sp, fib_entry);
5674 		break;
5675 	}
5676 }
5677 
5678 static void
5679 mlxsw_sp_fib_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
5680 				  struct mlxsw_sp_fib_entry *fib_entry)
5681 {
5682 	switch (fib_entry->fib_node->fib->proto) {
5683 	case MLXSW_SP_L3_PROTO_IPV4:
5684 		mlxsw_sp_fib4_entry_hw_flags_clear(mlxsw_sp, fib_entry);
5685 		break;
5686 	case MLXSW_SP_L3_PROTO_IPV6:
5687 		mlxsw_sp_fib6_entry_hw_flags_clear(mlxsw_sp, fib_entry);
5688 		break;
5689 	}
5690 }
5691 
5692 static void
5693 mlxsw_sp_fib_entry_hw_flags_refresh(struct mlxsw_sp *mlxsw_sp,
5694 				    struct mlxsw_sp_fib_entry *fib_entry,
5695 				    enum mlxsw_reg_ralue_op op)
5696 {
5697 	switch (op) {
5698 	case MLXSW_REG_RALUE_OP_WRITE_WRITE:
5699 		mlxsw_sp_fib_entry_hw_flags_set(mlxsw_sp, fib_entry);
5700 		break;
5701 	case MLXSW_REG_RALUE_OP_WRITE_DELETE:
5702 		mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, fib_entry);
5703 		break;
5704 	default:
5705 		break;
5706 	}
5707 }
5708 
5709 static void
5710 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl,
5711 			      const struct mlxsw_sp_fib_entry *fib_entry,
5712 			      enum mlxsw_reg_ralue_op op)
5713 {
5714 	struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
5715 	enum mlxsw_reg_ralxx_protocol proto;
5716 	u32 *p_dip;
5717 
5718 	proto = (enum mlxsw_reg_ralxx_protocol) fib->proto;
5719 
5720 	switch (fib->proto) {
5721 	case MLXSW_SP_L3_PROTO_IPV4:
5722 		p_dip = (u32 *) fib_entry->fib_node->key.addr;
5723 		mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id,
5724 				      fib_entry->fib_node->key.prefix_len,
5725 				      *p_dip);
5726 		break;
5727 	case MLXSW_SP_L3_PROTO_IPV6:
5728 		mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id,
5729 				      fib_entry->fib_node->key.prefix_len,
5730 				      fib_entry->fib_node->key.addr);
5731 		break;
5732 	}
5733 }
5734 
5735 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
5736 					struct mlxsw_sp_fib_entry *fib_entry,
5737 					enum mlxsw_reg_ralue_op op)
5738 {
5739 	struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
5740 	struct mlxsw_sp_nexthop_group_info *nhgi = nh_group->nhgi;
5741 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5742 	enum mlxsw_reg_ralue_trap_action trap_action;
5743 	u16 trap_id = 0;
5744 	u32 adjacency_index = 0;
5745 	u16 ecmp_size = 0;
5746 
5747 	/* In case the nexthop group adjacency index is valid, use it
5748 	 * with provided ECMP size. Otherwise, setup trap and pass
5749 	 * traffic to kernel.
5750 	 */
5751 	if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
5752 		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
5753 		adjacency_index = nhgi->adj_index;
5754 		ecmp_size = nhgi->ecmp_size;
5755 	} else if (!nhgi->adj_index_valid && nhgi->count && nhgi->nh_rif) {
5756 		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
5757 		adjacency_index = mlxsw_sp->router->adj_trap_index;
5758 		ecmp_size = 1;
5759 	} else {
5760 		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
5761 		trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
5762 	}
5763 
5764 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5765 	mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id,
5766 					adjacency_index, ecmp_size);
5767 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5768 }
5769 
5770 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
5771 				       struct mlxsw_sp_fib_entry *fib_entry,
5772 				       enum mlxsw_reg_ralue_op op)
5773 {
5774 	struct mlxsw_sp_rif *rif = fib_entry->nh_group->nhgi->nh_rif;
5775 	enum mlxsw_reg_ralue_trap_action trap_action;
5776 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5777 	u16 trap_id = 0;
5778 	u16 rif_index = 0;
5779 
5780 	if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
5781 		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
5782 		rif_index = rif->rif_index;
5783 	} else {
5784 		trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
5785 		trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
5786 	}
5787 
5788 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5789 	mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id,
5790 				       rif_index);
5791 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5792 }
5793 
5794 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
5795 				      struct mlxsw_sp_fib_entry *fib_entry,
5796 				      enum mlxsw_reg_ralue_op op)
5797 {
5798 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5799 
5800 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5801 	mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
5802 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5803 }
5804 
5805 static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp,
5806 					   struct mlxsw_sp_fib_entry *fib_entry,
5807 					   enum mlxsw_reg_ralue_op op)
5808 {
5809 	enum mlxsw_reg_ralue_trap_action trap_action;
5810 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5811 
5812 	trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR;
5813 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5814 	mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0);
5815 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5816 }
5817 
5818 static int
5819 mlxsw_sp_fib_entry_op_unreachable(struct mlxsw_sp *mlxsw_sp,
5820 				  struct mlxsw_sp_fib_entry *fib_entry,
5821 				  enum mlxsw_reg_ralue_op op)
5822 {
5823 	enum mlxsw_reg_ralue_trap_action trap_action;
5824 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5825 	u16 trap_id;
5826 
5827 	trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
5828 	trap_id = MLXSW_TRAP_ID_RTR_INGRESS1;
5829 
5830 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5831 	mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, 0);
5832 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5833 }
5834 
5835 static int
5836 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
5837 				 struct mlxsw_sp_fib_entry *fib_entry,
5838 				 enum mlxsw_reg_ralue_op op)
5839 {
5840 	struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry;
5841 	const struct mlxsw_sp_ipip_ops *ipip_ops;
5842 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5843 	int err;
5844 
5845 	if (WARN_ON(!ipip_entry))
5846 		return -EINVAL;
5847 
5848 	ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
5849 	err = ipip_ops->decap_config(mlxsw_sp, ipip_entry,
5850 				     fib_entry->decap.tunnel_index);
5851 	if (err)
5852 		return err;
5853 
5854 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5855 	mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl,
5856 					   fib_entry->decap.tunnel_index);
5857 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5858 }
5859 
5860 static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp *mlxsw_sp,
5861 					   struct mlxsw_sp_fib_entry *fib_entry,
5862 					   enum mlxsw_reg_ralue_op op)
5863 {
5864 	char ralue_pl[MLXSW_REG_RALUE_LEN];
5865 
5866 	mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
5867 	mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl,
5868 					   fib_entry->decap.tunnel_index);
5869 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
5870 }
5871 
5872 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
5873 				   struct mlxsw_sp_fib_entry *fib_entry,
5874 				   enum mlxsw_reg_ralue_op op)
5875 {
5876 	switch (fib_entry->type) {
5877 	case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
5878 		return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op);
5879 	case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
5880 		return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
5881 	case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
5882 		return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
5883 	case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
5884 		return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op);
5885 	case MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE:
5886 		return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp, fib_entry,
5887 							 op);
5888 	case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
5889 		return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
5890 							fib_entry, op);
5891 	case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
5892 		return mlxsw_sp_fib_entry_op_nve_decap(mlxsw_sp, fib_entry, op);
5893 	}
5894 	return -EINVAL;
5895 }
5896 
5897 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
5898 				 struct mlxsw_sp_fib_entry *fib_entry,
5899 				 enum mlxsw_reg_ralue_op op)
5900 {
5901 	int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op);
5902 
5903 	if (err)
5904 		return err;
5905 
5906 	mlxsw_sp_fib_entry_hw_flags_refresh(mlxsw_sp, fib_entry, op);
5907 
5908 	return err;
5909 }
5910 
5911 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
5912 				     struct mlxsw_sp_fib_entry *fib_entry)
5913 {
5914 	return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
5915 				     MLXSW_REG_RALUE_OP_WRITE_WRITE);
5916 }
5917 
5918 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
5919 				  struct mlxsw_sp_fib_entry *fib_entry)
5920 {
5921 	return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
5922 				     MLXSW_REG_RALUE_OP_WRITE_DELETE);
5923 }
5924 
5925 static int
5926 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
5927 			     const struct fib_entry_notifier_info *fen_info,
5928 			     struct mlxsw_sp_fib_entry *fib_entry)
5929 {
5930 	struct mlxsw_sp_nexthop_group_info *nhgi = fib_entry->nh_group->nhgi;
5931 	union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) };
5932 	struct mlxsw_sp_router *router = mlxsw_sp->router;
5933 	u32 tb_id = mlxsw_sp_fix_tb_id(fen_info->tb_id);
5934 	int ifindex = nhgi->nexthops[0].ifindex;
5935 	struct mlxsw_sp_ipip_entry *ipip_entry;
5936 
5937 	switch (fen_info->type) {
5938 	case RTN_LOCAL:
5939 		ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, ifindex,
5940 							       MLXSW_SP_L3_PROTO_IPV4, dip);
5941 		if (ipip_entry && ipip_entry->ol_dev->flags & IFF_UP) {
5942 			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
5943 			return mlxsw_sp_fib_entry_decap_init(mlxsw_sp,
5944 							     fib_entry,
5945 							     ipip_entry);
5946 		}
5947 		if (mlxsw_sp_router_nve_is_decap(mlxsw_sp, tb_id,
5948 						 MLXSW_SP_L3_PROTO_IPV4,
5949 						 &dip)) {
5950 			u32 tunnel_index;
5951 
5952 			tunnel_index = router->nve_decap_config.tunnel_index;
5953 			fib_entry->decap.tunnel_index = tunnel_index;
5954 			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
5955 			return 0;
5956 		}
5957 		fallthrough;
5958 	case RTN_BROADCAST:
5959 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
5960 		return 0;
5961 	case RTN_BLACKHOLE:
5962 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
5963 		return 0;
5964 	case RTN_UNREACHABLE:
5965 	case RTN_PROHIBIT:
5966 		/* Packets hitting these routes need to be trapped, but
5967 		 * can do so with a lower priority than packets directed
5968 		 * at the host, so use action type local instead of trap.
5969 		 */
5970 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
5971 		return 0;
5972 	case RTN_UNICAST:
5973 		if (nhgi->gateway)
5974 			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
5975 		else
5976 			fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
5977 		return 0;
5978 	default:
5979 		return -EINVAL;
5980 	}
5981 }
5982 
5983 static void
5984 mlxsw_sp_fib_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
5985 			      struct mlxsw_sp_fib_entry *fib_entry)
5986 {
5987 	switch (fib_entry->type) {
5988 	case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
5989 		mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
5990 		break;
5991 	default:
5992 		break;
5993 	}
5994 }
5995 
5996 static void
5997 mlxsw_sp_fib4_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
5998 			       struct mlxsw_sp_fib4_entry *fib4_entry)
5999 {
6000 	mlxsw_sp_fib_entry_type_unset(mlxsw_sp, &fib4_entry->common);
6001 }
6002 
6003 static struct mlxsw_sp_fib4_entry *
6004 mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
6005 			   struct mlxsw_sp_fib_node *fib_node,
6006 			   const struct fib_entry_notifier_info *fen_info)
6007 {
6008 	struct mlxsw_sp_fib4_entry *fib4_entry;
6009 	struct mlxsw_sp_fib_entry *fib_entry;
6010 	int err;
6011 
6012 	fib4_entry = kzalloc(sizeof(*fib4_entry), GFP_KERNEL);
6013 	if (!fib4_entry)
6014 		return ERR_PTR(-ENOMEM);
6015 	fib_entry = &fib4_entry->common;
6016 
6017 	err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi);
6018 	if (err)
6019 		goto err_nexthop4_group_get;
6020 
6021 	err = mlxsw_sp_nexthop_group_vr_link(fib_entry->nh_group,
6022 					     fib_node->fib);
6023 	if (err)
6024 		goto err_nexthop_group_vr_link;
6025 
6026 	err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry);
6027 	if (err)
6028 		goto err_fib4_entry_type_set;
6029 
6030 	fib4_entry->fi = fen_info->fi;
6031 	fib_info_hold(fib4_entry->fi);
6032 	fib4_entry->tb_id = fen_info->tb_id;
6033 	fib4_entry->type = fen_info->type;
6034 	fib4_entry->dscp = fen_info->dscp;
6035 
6036 	fib_entry->fib_node = fib_node;
6037 
6038 	return fib4_entry;
6039 
6040 err_fib4_entry_type_set:
6041 	mlxsw_sp_nexthop_group_vr_unlink(fib_entry->nh_group, fib_node->fib);
6042 err_nexthop_group_vr_link:
6043 	mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
6044 err_nexthop4_group_get:
6045 	kfree(fib4_entry);
6046 	return ERR_PTR(err);
6047 }
6048 
6049 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
6050 					struct mlxsw_sp_fib4_entry *fib4_entry)
6051 {
6052 	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
6053 
6054 	fib_info_put(fib4_entry->fi);
6055 	mlxsw_sp_fib4_entry_type_unset(mlxsw_sp, fib4_entry);
6056 	mlxsw_sp_nexthop_group_vr_unlink(fib4_entry->common.nh_group,
6057 					 fib_node->fib);
6058 	mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
6059 	kfree(fib4_entry);
6060 }
6061 
6062 static struct mlxsw_sp_fib4_entry *
6063 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
6064 			   const struct fib_entry_notifier_info *fen_info)
6065 {
6066 	struct mlxsw_sp_fib4_entry *fib4_entry;
6067 	struct mlxsw_sp_fib_node *fib_node;
6068 	struct mlxsw_sp_fib *fib;
6069 	struct mlxsw_sp_vr *vr;
6070 
6071 	vr = mlxsw_sp_vr_find(mlxsw_sp, fen_info->tb_id);
6072 	if (!vr)
6073 		return NULL;
6074 	fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4);
6075 
6076 	fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst,
6077 					    sizeof(fen_info->dst),
6078 					    fen_info->dst_len);
6079 	if (!fib_node)
6080 		return NULL;
6081 
6082 	fib4_entry = container_of(fib_node->fib_entry,
6083 				  struct mlxsw_sp_fib4_entry, common);
6084 	if (fib4_entry->tb_id == fen_info->tb_id &&
6085 	    fib4_entry->dscp == fen_info->dscp &&
6086 	    fib4_entry->type == fen_info->type &&
6087 	    fib4_entry->fi == fen_info->fi)
6088 		return fib4_entry;
6089 
6090 	return NULL;
6091 }
6092 
6093 static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
6094 	.key_offset = offsetof(struct mlxsw_sp_fib_node, key),
6095 	.head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node),
6096 	.key_len = sizeof(struct mlxsw_sp_fib_key),
6097 	.automatic_shrinking = true,
6098 };
6099 
6100 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib,
6101 				    struct mlxsw_sp_fib_node *fib_node)
6102 {
6103 	return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node,
6104 				      mlxsw_sp_fib_ht_params);
6105 }
6106 
6107 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib,
6108 				     struct mlxsw_sp_fib_node *fib_node)
6109 {
6110 	rhashtable_remove_fast(&fib->ht, &fib_node->ht_node,
6111 			       mlxsw_sp_fib_ht_params);
6112 }
6113 
6114 static struct mlxsw_sp_fib_node *
6115 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
6116 			 size_t addr_len, unsigned char prefix_len)
6117 {
6118 	struct mlxsw_sp_fib_key key;
6119 
6120 	memset(&key, 0, sizeof(key));
6121 	memcpy(key.addr, addr, addr_len);
6122 	key.prefix_len = prefix_len;
6123 	return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
6124 }
6125 
6126 static struct mlxsw_sp_fib_node *
6127 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
6128 			 size_t addr_len, unsigned char prefix_len)
6129 {
6130 	struct mlxsw_sp_fib_node *fib_node;
6131 
6132 	fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL);
6133 	if (!fib_node)
6134 		return NULL;
6135 
6136 	list_add(&fib_node->list, &fib->node_list);
6137 	memcpy(fib_node->key.addr, addr, addr_len);
6138 	fib_node->key.prefix_len = prefix_len;
6139 
6140 	return fib_node;
6141 }
6142 
6143 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
6144 {
6145 	list_del(&fib_node->list);
6146 	kfree(fib_node);
6147 }
6148 
6149 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp,
6150 				      struct mlxsw_sp_fib_node *fib_node)
6151 {
6152 	struct mlxsw_sp_prefix_usage req_prefix_usage;
6153 	struct mlxsw_sp_fib *fib = fib_node->fib;
6154 	struct mlxsw_sp_lpm_tree *lpm_tree;
6155 	int err;
6156 
6157 	lpm_tree = mlxsw_sp->router->lpm.proto_trees[fib->proto];
6158 	if (lpm_tree->prefix_ref_count[fib_node->key.prefix_len] != 0)
6159 		goto out;
6160 
6161 	mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &lpm_tree->prefix_usage);
6162 	mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len);
6163 	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
6164 					 fib->proto);
6165 	if (IS_ERR(lpm_tree))
6166 		return PTR_ERR(lpm_tree);
6167 
6168 	err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
6169 	if (err)
6170 		goto err_lpm_tree_replace;
6171 
6172 out:
6173 	lpm_tree->prefix_ref_count[fib_node->key.prefix_len]++;
6174 	return 0;
6175 
6176 err_lpm_tree_replace:
6177 	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
6178 	return err;
6179 }
6180 
6181 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp,
6182 					 struct mlxsw_sp_fib_node *fib_node)
6183 {
6184 	struct mlxsw_sp_lpm_tree *lpm_tree = fib_node->fib->lpm_tree;
6185 	struct mlxsw_sp_prefix_usage req_prefix_usage;
6186 	struct mlxsw_sp_fib *fib = fib_node->fib;
6187 	int err;
6188 
6189 	if (--lpm_tree->prefix_ref_count[fib_node->key.prefix_len] != 0)
6190 		return;
6191 	/* Try to construct a new LPM tree from the current prefix usage
6192 	 * minus the unused one. If we fail, continue using the old one.
6193 	 */
6194 	mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &lpm_tree->prefix_usage);
6195 	mlxsw_sp_prefix_usage_clear(&req_prefix_usage,
6196 				    fib_node->key.prefix_len);
6197 	lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
6198 					 fib->proto);
6199 	if (IS_ERR(lpm_tree))
6200 		return;
6201 
6202 	err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
6203 	if (err)
6204 		goto err_lpm_tree_replace;
6205 
6206 	return;
6207 
6208 err_lpm_tree_replace:
6209 	mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
6210 }
6211 
6212 static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
6213 				  struct mlxsw_sp_fib_node *fib_node,
6214 				  struct mlxsw_sp_fib *fib)
6215 {
6216 	int err;
6217 
6218 	err = mlxsw_sp_fib_node_insert(fib, fib_node);
6219 	if (err)
6220 		return err;
6221 	fib_node->fib = fib;
6222 
6223 	err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib_node);
6224 	if (err)
6225 		goto err_fib_lpm_tree_link;
6226 
6227 	return 0;
6228 
6229 err_fib_lpm_tree_link:
6230 	fib_node->fib = NULL;
6231 	mlxsw_sp_fib_node_remove(fib, fib_node);
6232 	return err;
6233 }
6234 
6235 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
6236 				   struct mlxsw_sp_fib_node *fib_node)
6237 {
6238 	struct mlxsw_sp_fib *fib = fib_node->fib;
6239 
6240 	mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib_node);
6241 	fib_node->fib = NULL;
6242 	mlxsw_sp_fib_node_remove(fib, fib_node);
6243 }
6244 
6245 static struct mlxsw_sp_fib_node *
6246 mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
6247 		      size_t addr_len, unsigned char prefix_len,
6248 		      enum mlxsw_sp_l3proto proto)
6249 {
6250 	struct mlxsw_sp_fib_node *fib_node;
6251 	struct mlxsw_sp_fib *fib;
6252 	struct mlxsw_sp_vr *vr;
6253 	int err;
6254 
6255 	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, NULL);
6256 	if (IS_ERR(vr))
6257 		return ERR_CAST(vr);
6258 	fib = mlxsw_sp_vr_fib(vr, proto);
6259 
6260 	fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len);
6261 	if (fib_node)
6262 		return fib_node;
6263 
6264 	fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len);
6265 	if (!fib_node) {
6266 		err = -ENOMEM;
6267 		goto err_fib_node_create;
6268 	}
6269 
6270 	err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
6271 	if (err)
6272 		goto err_fib_node_init;
6273 
6274 	return fib_node;
6275 
6276 err_fib_node_init:
6277 	mlxsw_sp_fib_node_destroy(fib_node);
6278 err_fib_node_create:
6279 	mlxsw_sp_vr_put(mlxsw_sp, vr);
6280 	return ERR_PTR(err);
6281 }
6282 
6283 static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
6284 				  struct mlxsw_sp_fib_node *fib_node)
6285 {
6286 	struct mlxsw_sp_vr *vr = fib_node->fib->vr;
6287 
6288 	if (fib_node->fib_entry)
6289 		return;
6290 	mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
6291 	mlxsw_sp_fib_node_destroy(fib_node);
6292 	mlxsw_sp_vr_put(mlxsw_sp, vr);
6293 }
6294 
6295 static int mlxsw_sp_fib_node_entry_link(struct mlxsw_sp *mlxsw_sp,
6296 					struct mlxsw_sp_fib_entry *fib_entry)
6297 {
6298 	struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
6299 	int err;
6300 
6301 	fib_node->fib_entry = fib_entry;
6302 
6303 	err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
6304 	if (err)
6305 		goto err_fib_entry_update;
6306 
6307 	return 0;
6308 
6309 err_fib_entry_update:
6310 	fib_node->fib_entry = NULL;
6311 	return err;
6312 }
6313 
6314 static void
6315 mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
6316 			       struct mlxsw_sp_fib_entry *fib_entry)
6317 {
6318 	struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
6319 
6320 	mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
6321 	fib_node->fib_entry = NULL;
6322 }
6323 
6324 static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry)
6325 {
6326 	struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
6327 	struct mlxsw_sp_fib4_entry *fib4_replaced;
6328 
6329 	if (!fib_node->fib_entry)
6330 		return true;
6331 
6332 	fib4_replaced = container_of(fib_node->fib_entry,
6333 				     struct mlxsw_sp_fib4_entry, common);
6334 	if (fib4_entry->tb_id == RT_TABLE_MAIN &&
6335 	    fib4_replaced->tb_id == RT_TABLE_LOCAL)
6336 		return false;
6337 
6338 	return true;
6339 }
6340 
6341 static int
6342 mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
6343 			     const struct fib_entry_notifier_info *fen_info)
6344 {
6345 	struct mlxsw_sp_fib4_entry *fib4_entry, *fib4_replaced;
6346 	struct mlxsw_sp_fib_entry *replaced;
6347 	struct mlxsw_sp_fib_node *fib_node;
6348 	int err;
6349 
6350 	if (fen_info->fi->nh &&
6351 	    !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, fen_info->fi->nh->id))
6352 		return 0;
6353 
6354 	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
6355 					 &fen_info->dst, sizeof(fen_info->dst),
6356 					 fen_info->dst_len,
6357 					 MLXSW_SP_L3_PROTO_IPV4);
6358 	if (IS_ERR(fib_node)) {
6359 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
6360 		return PTR_ERR(fib_node);
6361 	}
6362 
6363 	fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
6364 	if (IS_ERR(fib4_entry)) {
6365 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
6366 		err = PTR_ERR(fib4_entry);
6367 		goto err_fib4_entry_create;
6368 	}
6369 
6370 	if (!mlxsw_sp_fib4_allow_replace(fib4_entry)) {
6371 		mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
6372 		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
6373 		return 0;
6374 	}
6375 
6376 	replaced = fib_node->fib_entry;
6377 	err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
6378 	if (err) {
6379 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
6380 		goto err_fib_node_entry_link;
6381 	}
6382 
6383 	/* Nothing to replace */
6384 	if (!replaced)
6385 		return 0;
6386 
6387 	mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, replaced);
6388 	fib4_replaced = container_of(replaced, struct mlxsw_sp_fib4_entry,
6389 				     common);
6390 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_replaced);
6391 
6392 	return 0;
6393 
6394 err_fib_node_entry_link:
6395 	fib_node->fib_entry = replaced;
6396 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
6397 err_fib4_entry_create:
6398 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
6399 	return err;
6400 }
6401 
6402 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
6403 				     struct fib_entry_notifier_info *fen_info)
6404 {
6405 	struct mlxsw_sp_fib4_entry *fib4_entry;
6406 	struct mlxsw_sp_fib_node *fib_node;
6407 
6408 	fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
6409 	if (!fib4_entry)
6410 		return;
6411 	fib_node = fib4_entry->common.fib_node;
6412 
6413 	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib4_entry->common);
6414 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
6415 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
6416 }
6417 
6418 static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info *rt)
6419 {
6420 	/* Multicast routes aren't supported, so ignore them. Neighbour
6421 	 * Discovery packets are specifically trapped.
6422 	 */
6423 	if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_MULTICAST)
6424 		return true;
6425 
6426 	/* Cloned routes are irrelevant in the forwarding path. */
6427 	if (rt->fib6_flags & RTF_CACHE)
6428 		return true;
6429 
6430 	return false;
6431 }
6432 
6433 static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct fib6_info *rt)
6434 {
6435 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
6436 
6437 	mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL);
6438 	if (!mlxsw_sp_rt6)
6439 		return ERR_PTR(-ENOMEM);
6440 
6441 	/* In case of route replace, replaced route is deleted with
6442 	 * no notification. Take reference to prevent accessing freed
6443 	 * memory.
6444 	 */
6445 	mlxsw_sp_rt6->rt = rt;
6446 	fib6_info_hold(rt);
6447 
6448 	return mlxsw_sp_rt6;
6449 }
6450 
6451 #if IS_ENABLED(CONFIG_IPV6)
6452 static void mlxsw_sp_rt6_release(struct fib6_info *rt)
6453 {
6454 	fib6_info_release(rt);
6455 }
6456 #else
6457 static void mlxsw_sp_rt6_release(struct fib6_info *rt)
6458 {
6459 }
6460 #endif
6461 
6462 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
6463 {
6464 	struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
6465 
6466 	if (!mlxsw_sp_rt6->rt->nh)
6467 		fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
6468 	mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
6469 	kfree(mlxsw_sp_rt6);
6470 }
6471 
6472 static struct fib6_info *
6473 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
6474 {
6475 	return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
6476 				list)->rt;
6477 }
6478 
6479 static struct mlxsw_sp_rt6 *
6480 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
6481 			    const struct fib6_info *rt)
6482 {
6483 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
6484 
6485 	list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
6486 		if (mlxsw_sp_rt6->rt == rt)
6487 			return mlxsw_sp_rt6;
6488 	}
6489 
6490 	return NULL;
6491 }
6492 
6493 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
6494 					const struct fib6_info *rt,
6495 					enum mlxsw_sp_ipip_type *ret)
6496 {
6497 	return rt->fib6_nh->fib_nh_dev &&
6498 	       mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh->fib_nh_dev, ret);
6499 }
6500 
6501 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
6502 				  struct mlxsw_sp_nexthop_group *nh_grp,
6503 				  struct mlxsw_sp_nexthop *nh,
6504 				  const struct fib6_info *rt)
6505 {
6506 	struct net_device *dev = rt->fib6_nh->fib_nh_dev;
6507 	int err;
6508 
6509 	nh->nhgi = nh_grp->nhgi;
6510 	nh->nh_weight = rt->fib6_nh->fib_nh_weight;
6511 	memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
6512 #if IS_ENABLED(CONFIG_IPV6)
6513 	nh->neigh_tbl = &nd_tbl;
6514 #endif
6515 	mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
6516 
6517 	list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
6518 
6519 	if (!dev)
6520 		return 0;
6521 	nh->ifindex = dev->ifindex;
6522 
6523 	err = mlxsw_sp_nexthop_type_init(mlxsw_sp, nh, dev);
6524 	if (err)
6525 		goto err_nexthop_type_init;
6526 
6527 	return 0;
6528 
6529 err_nexthop_type_init:
6530 	list_del(&nh->router_list_node);
6531 	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
6532 	return err;
6533 }
6534 
6535 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
6536 				   struct mlxsw_sp_nexthop *nh)
6537 {
6538 	mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
6539 	list_del(&nh->router_list_node);
6540 	mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
6541 }
6542 
6543 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
6544 				    const struct fib6_info *rt)
6545 {
6546 	return rt->fib6_nh->fib_nh_gw_family ||
6547 	       mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
6548 }
6549 
6550 static int
6551 mlxsw_sp_nexthop6_group_info_init(struct mlxsw_sp *mlxsw_sp,
6552 				  struct mlxsw_sp_nexthop_group *nh_grp,
6553 				  struct mlxsw_sp_fib6_entry *fib6_entry)
6554 {
6555 	struct mlxsw_sp_nexthop_group_info *nhgi;
6556 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
6557 	struct mlxsw_sp_nexthop *nh;
6558 	int err, i;
6559 
6560 	nhgi = kzalloc(struct_size(nhgi, nexthops, fib6_entry->nrt6),
6561 		       GFP_KERNEL);
6562 	if (!nhgi)
6563 		return -ENOMEM;
6564 	nh_grp->nhgi = nhgi;
6565 	nhgi->nh_grp = nh_grp;
6566 	mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
6567 					struct mlxsw_sp_rt6, list);
6568 	nhgi->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
6569 	nhgi->count = fib6_entry->nrt6;
6570 	for (i = 0; i < nhgi->count; i++) {
6571 		struct fib6_info *rt = mlxsw_sp_rt6->rt;
6572 
6573 		nh = &nhgi->nexthops[i];
6574 		err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt);
6575 		if (err)
6576 			goto err_nexthop6_init;
6577 		mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list);
6578 	}
6579 	nh_grp->nhgi = nhgi;
6580 	err = mlxsw_sp_nexthop_group_inc(mlxsw_sp);
6581 	if (err)
6582 		goto err_group_inc;
6583 	err = mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
6584 	if (err)
6585 		goto err_group_refresh;
6586 
6587 	return 0;
6588 
6589 err_group_refresh:
6590 	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
6591 err_group_inc:
6592 	i = nhgi->count;
6593 err_nexthop6_init:
6594 	for (i--; i >= 0; i--) {
6595 		nh = &nhgi->nexthops[i];
6596 		mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
6597 	}
6598 	kfree(nhgi);
6599 	return err;
6600 }
6601 
6602 static void
6603 mlxsw_sp_nexthop6_group_info_fini(struct mlxsw_sp *mlxsw_sp,
6604 				  struct mlxsw_sp_nexthop_group *nh_grp)
6605 {
6606 	struct mlxsw_sp_nexthop_group_info *nhgi = nh_grp->nhgi;
6607 	int i;
6608 
6609 	mlxsw_sp_nexthop_group_dec(mlxsw_sp);
6610 	for (i = nhgi->count - 1; i >= 0; i--) {
6611 		struct mlxsw_sp_nexthop *nh = &nhgi->nexthops[i];
6612 
6613 		mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
6614 	}
6615 	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
6616 	WARN_ON_ONCE(nhgi->adj_index_valid);
6617 	kfree(nhgi);
6618 }
6619 
6620 static struct mlxsw_sp_nexthop_group *
6621 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
6622 			       struct mlxsw_sp_fib6_entry *fib6_entry)
6623 {
6624 	struct mlxsw_sp_nexthop_group *nh_grp;
6625 	int err;
6626 
6627 	nh_grp = kzalloc(sizeof(*nh_grp), GFP_KERNEL);
6628 	if (!nh_grp)
6629 		return ERR_PTR(-ENOMEM);
6630 	INIT_LIST_HEAD(&nh_grp->vr_list);
6631 	err = rhashtable_init(&nh_grp->vr_ht,
6632 			      &mlxsw_sp_nexthop_group_vr_ht_params);
6633 	if (err)
6634 		goto err_nexthop_group_vr_ht_init;
6635 	INIT_LIST_HEAD(&nh_grp->fib_list);
6636 	nh_grp->type = MLXSW_SP_NEXTHOP_GROUP_TYPE_IPV6;
6637 
6638 	err = mlxsw_sp_nexthop6_group_info_init(mlxsw_sp, nh_grp, fib6_entry);
6639 	if (err)
6640 		goto err_nexthop_group_info_init;
6641 
6642 	err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
6643 	if (err)
6644 		goto err_nexthop_group_insert;
6645 
6646 	nh_grp->can_destroy = true;
6647 
6648 	return nh_grp;
6649 
6650 err_nexthop_group_insert:
6651 	mlxsw_sp_nexthop6_group_info_fini(mlxsw_sp, nh_grp);
6652 err_nexthop_group_info_init:
6653 	rhashtable_destroy(&nh_grp->vr_ht);
6654 err_nexthop_group_vr_ht_init:
6655 	kfree(nh_grp);
6656 	return ERR_PTR(err);
6657 }
6658 
6659 static void
6660 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp,
6661 				struct mlxsw_sp_nexthop_group *nh_grp)
6662 {
6663 	if (!nh_grp->can_destroy)
6664 		return;
6665 	mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
6666 	mlxsw_sp_nexthop6_group_info_fini(mlxsw_sp, nh_grp);
6667 	WARN_ON_ONCE(!list_empty(&nh_grp->vr_list));
6668 	rhashtable_destroy(&nh_grp->vr_ht);
6669 	kfree(nh_grp);
6670 }
6671 
6672 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp,
6673 				       struct mlxsw_sp_fib6_entry *fib6_entry)
6674 {
6675 	struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
6676 	struct mlxsw_sp_nexthop_group *nh_grp;
6677 
6678 	if (rt->nh) {
6679 		nh_grp = mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp,
6680 							   rt->nh->id);
6681 		if (WARN_ON_ONCE(!nh_grp))
6682 			return -EINVAL;
6683 		goto out;
6684 	}
6685 
6686 	nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry);
6687 	if (!nh_grp) {
6688 		nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry);
6689 		if (IS_ERR(nh_grp))
6690 			return PTR_ERR(nh_grp);
6691 	}
6692 
6693 	/* The route and the nexthop are described by the same struct, so we
6694 	 * need to the update the nexthop offload indication for the new route.
6695 	 */
6696 	__mlxsw_sp_nexthop6_group_offload_refresh(nh_grp, fib6_entry);
6697 
6698 out:
6699 	list_add_tail(&fib6_entry->common.nexthop_group_node,
6700 		      &nh_grp->fib_list);
6701 	fib6_entry->common.nh_group = nh_grp;
6702 
6703 	return 0;
6704 }
6705 
6706 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp,
6707 					struct mlxsw_sp_fib_entry *fib_entry)
6708 {
6709 	struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
6710 
6711 	list_del(&fib_entry->nexthop_group_node);
6712 	if (!list_empty(&nh_grp->fib_list))
6713 		return;
6714 
6715 	if (nh_grp->type == MLXSW_SP_NEXTHOP_GROUP_TYPE_OBJ) {
6716 		mlxsw_sp_nexthop_obj_group_destroy(mlxsw_sp, nh_grp);
6717 		return;
6718 	}
6719 
6720 	mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp);
6721 }
6722 
6723 static int
6724 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
6725 			       struct mlxsw_sp_fib6_entry *fib6_entry)
6726 {
6727 	struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group;
6728 	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
6729 	int err;
6730 
6731 	mlxsw_sp_nexthop_group_vr_unlink(old_nh_grp, fib_node->fib);
6732 	fib6_entry->common.nh_group = NULL;
6733 	list_del(&fib6_entry->common.nexthop_group_node);
6734 
6735 	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
6736 	if (err)
6737 		goto err_nexthop6_group_get;
6738 
6739 	err = mlxsw_sp_nexthop_group_vr_link(fib6_entry->common.nh_group,
6740 					     fib_node->fib);
6741 	if (err)
6742 		goto err_nexthop_group_vr_link;
6743 
6744 	/* In case this entry is offloaded, then the adjacency index
6745 	 * currently associated with it in the device's table is that
6746 	 * of the old group. Start using the new one instead.
6747 	 */
6748 	err = mlxsw_sp_fib_entry_update(mlxsw_sp, &fib6_entry->common);
6749 	if (err)
6750 		goto err_fib_entry_update;
6751 
6752 	if (list_empty(&old_nh_grp->fib_list))
6753 		mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
6754 
6755 	return 0;
6756 
6757 err_fib_entry_update:
6758 	mlxsw_sp_nexthop_group_vr_unlink(fib6_entry->common.nh_group,
6759 					 fib_node->fib);
6760 err_nexthop_group_vr_link:
6761 	mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
6762 err_nexthop6_group_get:
6763 	list_add_tail(&fib6_entry->common.nexthop_group_node,
6764 		      &old_nh_grp->fib_list);
6765 	fib6_entry->common.nh_group = old_nh_grp;
6766 	mlxsw_sp_nexthop_group_vr_link(old_nh_grp, fib_node->fib);
6767 	return err;
6768 }
6769 
6770 static int
6771 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
6772 				struct mlxsw_sp_fib6_entry *fib6_entry,
6773 				struct fib6_info **rt_arr, unsigned int nrt6)
6774 {
6775 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
6776 	int err, i;
6777 
6778 	for (i = 0; i < nrt6; i++) {
6779 		mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
6780 		if (IS_ERR(mlxsw_sp_rt6)) {
6781 			err = PTR_ERR(mlxsw_sp_rt6);
6782 			goto err_rt6_unwind;
6783 		}
6784 
6785 		list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
6786 		fib6_entry->nrt6++;
6787 	}
6788 
6789 	err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
6790 	if (err)
6791 		goto err_rt6_unwind;
6792 
6793 	return 0;
6794 
6795 err_rt6_unwind:
6796 	for (; i > 0; i--) {
6797 		fib6_entry->nrt6--;
6798 		mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
6799 					       struct mlxsw_sp_rt6, list);
6800 		list_del(&mlxsw_sp_rt6->list);
6801 		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
6802 	}
6803 	return err;
6804 }
6805 
6806 static void
6807 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
6808 				struct mlxsw_sp_fib6_entry *fib6_entry,
6809 				struct fib6_info **rt_arr, unsigned int nrt6)
6810 {
6811 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
6812 	int i;
6813 
6814 	for (i = 0; i < nrt6; i++) {
6815 		mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry,
6816 							   rt_arr[i]);
6817 		if (WARN_ON_ONCE(!mlxsw_sp_rt6))
6818 			continue;
6819 
6820 		fib6_entry->nrt6--;
6821 		list_del(&mlxsw_sp_rt6->list);
6822 		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
6823 	}
6824 
6825 	mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
6826 }
6827 
6828 static int
6829 mlxsw_sp_fib6_entry_type_set_local(struct mlxsw_sp *mlxsw_sp,
6830 				   struct mlxsw_sp_fib_entry *fib_entry,
6831 				   const struct fib6_info *rt)
6832 {
6833 	struct mlxsw_sp_nexthop_group_info *nhgi = fib_entry->nh_group->nhgi;
6834 	union mlxsw_sp_l3addr dip = { .addr6 = rt->fib6_dst.addr };
6835 	u32 tb_id = mlxsw_sp_fix_tb_id(rt->fib6_table->tb6_id);
6836 	struct mlxsw_sp_router *router = mlxsw_sp->router;
6837 	int ifindex = nhgi->nexthops[0].ifindex;
6838 	struct mlxsw_sp_ipip_entry *ipip_entry;
6839 
6840 	fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
6841 	ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, ifindex,
6842 						       MLXSW_SP_L3_PROTO_IPV6,
6843 						       dip);
6844 
6845 	if (ipip_entry && ipip_entry->ol_dev->flags & IFF_UP) {
6846 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
6847 		return mlxsw_sp_fib_entry_decap_init(mlxsw_sp, fib_entry,
6848 						     ipip_entry);
6849 	}
6850 	if (mlxsw_sp_router_nve_is_decap(mlxsw_sp, tb_id,
6851 					 MLXSW_SP_L3_PROTO_IPV6, &dip)) {
6852 		u32 tunnel_index;
6853 
6854 		tunnel_index = router->nve_decap_config.tunnel_index;
6855 		fib_entry->decap.tunnel_index = tunnel_index;
6856 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
6857 	}
6858 
6859 	return 0;
6860 }
6861 
6862 static int mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
6863 					struct mlxsw_sp_fib_entry *fib_entry,
6864 					const struct fib6_info *rt)
6865 {
6866 	if (rt->fib6_flags & RTF_LOCAL)
6867 		return mlxsw_sp_fib6_entry_type_set_local(mlxsw_sp, fib_entry,
6868 							  rt);
6869 	if (rt->fib6_flags & RTF_ANYCAST)
6870 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
6871 	else if (rt->fib6_type == RTN_BLACKHOLE)
6872 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
6873 	else if (rt->fib6_flags & RTF_REJECT)
6874 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
6875 	else if (fib_entry->nh_group->nhgi->gateway)
6876 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
6877 	else
6878 		fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
6879 
6880 	return 0;
6881 }
6882 
6883 static void
6884 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
6885 {
6886 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp;
6887 
6888 	list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list,
6889 				 list) {
6890 		fib6_entry->nrt6--;
6891 		list_del(&mlxsw_sp_rt6->list);
6892 		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
6893 	}
6894 }
6895 
6896 static struct mlxsw_sp_fib6_entry *
6897 mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
6898 			   struct mlxsw_sp_fib_node *fib_node,
6899 			   struct fib6_info **rt_arr, unsigned int nrt6)
6900 {
6901 	struct mlxsw_sp_fib6_entry *fib6_entry;
6902 	struct mlxsw_sp_fib_entry *fib_entry;
6903 	struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
6904 	int err, i;
6905 
6906 	fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
6907 	if (!fib6_entry)
6908 		return ERR_PTR(-ENOMEM);
6909 	fib_entry = &fib6_entry->common;
6910 
6911 	INIT_LIST_HEAD(&fib6_entry->rt6_list);
6912 
6913 	for (i = 0; i < nrt6; i++) {
6914 		mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
6915 		if (IS_ERR(mlxsw_sp_rt6)) {
6916 			err = PTR_ERR(mlxsw_sp_rt6);
6917 			goto err_rt6_unwind;
6918 		}
6919 		list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
6920 		fib6_entry->nrt6++;
6921 	}
6922 
6923 	err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
6924 	if (err)
6925 		goto err_rt6_unwind;
6926 
6927 	err = mlxsw_sp_nexthop_group_vr_link(fib_entry->nh_group,
6928 					     fib_node->fib);
6929 	if (err)
6930 		goto err_nexthop_group_vr_link;
6931 
6932 	err = mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, rt_arr[0]);
6933 	if (err)
6934 		goto err_fib6_entry_type_set;
6935 
6936 	fib_entry->fib_node = fib_node;
6937 
6938 	return fib6_entry;
6939 
6940 err_fib6_entry_type_set:
6941 	mlxsw_sp_nexthop_group_vr_unlink(fib_entry->nh_group, fib_node->fib);
6942 err_nexthop_group_vr_link:
6943 	mlxsw_sp_nexthop6_group_put(mlxsw_sp, fib_entry);
6944 err_rt6_unwind:
6945 	for (; i > 0; i--) {
6946 		fib6_entry->nrt6--;
6947 		mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
6948 					       struct mlxsw_sp_rt6, list);
6949 		list_del(&mlxsw_sp_rt6->list);
6950 		mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
6951 	}
6952 	kfree(fib6_entry);
6953 	return ERR_PTR(err);
6954 }
6955 
6956 static void
6957 mlxsw_sp_fib6_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
6958 			       struct mlxsw_sp_fib6_entry *fib6_entry)
6959 {
6960 	mlxsw_sp_fib_entry_type_unset(mlxsw_sp, &fib6_entry->common);
6961 }
6962 
6963 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
6964 					struct mlxsw_sp_fib6_entry *fib6_entry)
6965 {
6966 	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
6967 
6968 	mlxsw_sp_fib6_entry_type_unset(mlxsw_sp, fib6_entry);
6969 	mlxsw_sp_nexthop_group_vr_unlink(fib6_entry->common.nh_group,
6970 					 fib_node->fib);
6971 	mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
6972 	mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry);
6973 	WARN_ON(fib6_entry->nrt6);
6974 	kfree(fib6_entry);
6975 }
6976 
6977 static struct mlxsw_sp_fib6_entry *
6978 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
6979 			   const struct fib6_info *rt)
6980 {
6981 	struct mlxsw_sp_fib6_entry *fib6_entry;
6982 	struct mlxsw_sp_fib_node *fib_node;
6983 	struct mlxsw_sp_fib *fib;
6984 	struct fib6_info *cmp_rt;
6985 	struct mlxsw_sp_vr *vr;
6986 
6987 	vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
6988 	if (!vr)
6989 		return NULL;
6990 	fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
6991 
6992 	fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->fib6_dst.addr,
6993 					    sizeof(rt->fib6_dst.addr),
6994 					    rt->fib6_dst.plen);
6995 	if (!fib_node)
6996 		return NULL;
6997 
6998 	fib6_entry = container_of(fib_node->fib_entry,
6999 				  struct mlxsw_sp_fib6_entry, common);
7000 	cmp_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
7001 	if (rt->fib6_table->tb6_id == cmp_rt->fib6_table->tb6_id &&
7002 	    rt->fib6_metric == cmp_rt->fib6_metric &&
7003 	    mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
7004 		return fib6_entry;
7005 
7006 	return NULL;
7007 }
7008 
7009 static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry)
7010 {
7011 	struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
7012 	struct mlxsw_sp_fib6_entry *fib6_replaced;
7013 	struct fib6_info *rt, *rt_replaced;
7014 
7015 	if (!fib_node->fib_entry)
7016 		return true;
7017 
7018 	fib6_replaced = container_of(fib_node->fib_entry,
7019 				     struct mlxsw_sp_fib6_entry,
7020 				     common);
7021 	rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
7022 	rt_replaced = mlxsw_sp_fib6_entry_rt(fib6_replaced);
7023 	if (rt->fib6_table->tb6_id == RT_TABLE_MAIN &&
7024 	    rt_replaced->fib6_table->tb6_id == RT_TABLE_LOCAL)
7025 		return false;
7026 
7027 	return true;
7028 }
7029 
7030 static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
7031 					struct fib6_info **rt_arr,
7032 					unsigned int nrt6)
7033 {
7034 	struct mlxsw_sp_fib6_entry *fib6_entry, *fib6_replaced;
7035 	struct mlxsw_sp_fib_entry *replaced;
7036 	struct mlxsw_sp_fib_node *fib_node;
7037 	struct fib6_info *rt = rt_arr[0];
7038 	int err;
7039 
7040 	if (rt->fib6_src.plen)
7041 		return -EINVAL;
7042 
7043 	if (mlxsw_sp_fib6_rt_should_ignore(rt))
7044 		return 0;
7045 
7046 	if (rt->nh && !mlxsw_sp_nexthop_obj_group_lookup(mlxsw_sp, rt->nh->id))
7047 		return 0;
7048 
7049 	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
7050 					 &rt->fib6_dst.addr,
7051 					 sizeof(rt->fib6_dst.addr),
7052 					 rt->fib6_dst.plen,
7053 					 MLXSW_SP_L3_PROTO_IPV6);
7054 	if (IS_ERR(fib_node))
7055 		return PTR_ERR(fib_node);
7056 
7057 	fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
7058 						nrt6);
7059 	if (IS_ERR(fib6_entry)) {
7060 		err = PTR_ERR(fib6_entry);
7061 		goto err_fib6_entry_create;
7062 	}
7063 
7064 	if (!mlxsw_sp_fib6_allow_replace(fib6_entry)) {
7065 		mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
7066 		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7067 		return 0;
7068 	}
7069 
7070 	replaced = fib_node->fib_entry;
7071 	err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
7072 	if (err)
7073 		goto err_fib_node_entry_link;
7074 
7075 	/* Nothing to replace */
7076 	if (!replaced)
7077 		return 0;
7078 
7079 	mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, replaced);
7080 	fib6_replaced = container_of(replaced, struct mlxsw_sp_fib6_entry,
7081 				     common);
7082 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_replaced);
7083 
7084 	return 0;
7085 
7086 err_fib_node_entry_link:
7087 	fib_node->fib_entry = replaced;
7088 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
7089 err_fib6_entry_create:
7090 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7091 	return err;
7092 }
7093 
7094 static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
7095 				       struct fib6_info **rt_arr,
7096 				       unsigned int nrt6)
7097 {
7098 	struct mlxsw_sp_fib6_entry *fib6_entry;
7099 	struct mlxsw_sp_fib_node *fib_node;
7100 	struct fib6_info *rt = rt_arr[0];
7101 	int err;
7102 
7103 	if (rt->fib6_src.plen)
7104 		return -EINVAL;
7105 
7106 	if (mlxsw_sp_fib6_rt_should_ignore(rt))
7107 		return 0;
7108 
7109 	fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
7110 					 &rt->fib6_dst.addr,
7111 					 sizeof(rt->fib6_dst.addr),
7112 					 rt->fib6_dst.plen,
7113 					 MLXSW_SP_L3_PROTO_IPV6);
7114 	if (IS_ERR(fib_node))
7115 		return PTR_ERR(fib_node);
7116 
7117 	if (WARN_ON_ONCE(!fib_node->fib_entry)) {
7118 		mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7119 		return -EINVAL;
7120 	}
7121 
7122 	fib6_entry = container_of(fib_node->fib_entry,
7123 				  struct mlxsw_sp_fib6_entry, common);
7124 	err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
7125 					      nrt6);
7126 	if (err)
7127 		goto err_fib6_entry_nexthop_add;
7128 
7129 	return 0;
7130 
7131 err_fib6_entry_nexthop_add:
7132 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7133 	return err;
7134 }
7135 
7136 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
7137 				     struct fib6_info **rt_arr,
7138 				     unsigned int nrt6)
7139 {
7140 	struct mlxsw_sp_fib6_entry *fib6_entry;
7141 	struct mlxsw_sp_fib_node *fib_node;
7142 	struct fib6_info *rt = rt_arr[0];
7143 
7144 	if (mlxsw_sp_fib6_rt_should_ignore(rt))
7145 		return;
7146 
7147 	/* Multipath routes are first added to the FIB trie and only then
7148 	 * notified. If we vetoed the addition, we will get a delete
7149 	 * notification for a route we do not have. Therefore, do not warn if
7150 	 * route was not found.
7151 	 */
7152 	fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
7153 	if (!fib6_entry)
7154 		return;
7155 
7156 	/* If not all the nexthops are deleted, then only reduce the nexthop
7157 	 * group.
7158 	 */
7159 	if (nrt6 != fib6_entry->nrt6) {
7160 		mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt_arr,
7161 						nrt6);
7162 		return;
7163 	}
7164 
7165 	fib_node = fib6_entry->common.fib_node;
7166 
7167 	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib6_entry->common);
7168 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
7169 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7170 }
7171 
7172 static struct mlxsw_sp_mr_table *
7173 mlxsw_sp_router_fibmr_family_to_table(struct mlxsw_sp_vr *vr, int family)
7174 {
7175 	if (family == RTNL_FAMILY_IPMR)
7176 		return vr->mr_table[MLXSW_SP_L3_PROTO_IPV4];
7177 	else
7178 		return vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
7179 }
7180 
7181 static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp,
7182 				     struct mfc_entry_notifier_info *men_info,
7183 				     bool replace)
7184 {
7185 	struct mlxsw_sp_mr_table *mrt;
7186 	struct mlxsw_sp_vr *vr;
7187 
7188 	vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id, NULL);
7189 	if (IS_ERR(vr))
7190 		return PTR_ERR(vr);
7191 
7192 	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, men_info->info.family);
7193 	return mlxsw_sp_mr_route_add(mrt, men_info->mfc, replace);
7194 }
7195 
7196 static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp *mlxsw_sp,
7197 				      struct mfc_entry_notifier_info *men_info)
7198 {
7199 	struct mlxsw_sp_mr_table *mrt;
7200 	struct mlxsw_sp_vr *vr;
7201 
7202 	vr = mlxsw_sp_vr_find(mlxsw_sp, men_info->tb_id);
7203 	if (WARN_ON(!vr))
7204 		return;
7205 
7206 	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, men_info->info.family);
7207 	mlxsw_sp_mr_route_del(mrt, men_info->mfc);
7208 	mlxsw_sp_vr_put(mlxsw_sp, vr);
7209 }
7210 
7211 static int
7212 mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp,
7213 			      struct vif_entry_notifier_info *ven_info)
7214 {
7215 	struct mlxsw_sp_mr_table *mrt;
7216 	struct mlxsw_sp_rif *rif;
7217 	struct mlxsw_sp_vr *vr;
7218 
7219 	vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id, NULL);
7220 	if (IS_ERR(vr))
7221 		return PTR_ERR(vr);
7222 
7223 	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, ven_info->info.family);
7224 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, ven_info->dev);
7225 	return mlxsw_sp_mr_vif_add(mrt, ven_info->dev,
7226 				   ven_info->vif_index,
7227 				   ven_info->vif_flags, rif);
7228 }
7229 
7230 static void
7231 mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp *mlxsw_sp,
7232 			      struct vif_entry_notifier_info *ven_info)
7233 {
7234 	struct mlxsw_sp_mr_table *mrt;
7235 	struct mlxsw_sp_vr *vr;
7236 
7237 	vr = mlxsw_sp_vr_find(mlxsw_sp, ven_info->tb_id);
7238 	if (WARN_ON(!vr))
7239 		return;
7240 
7241 	mrt = mlxsw_sp_router_fibmr_family_to_table(vr, ven_info->info.family);
7242 	mlxsw_sp_mr_vif_del(mrt, ven_info->vif_index);
7243 	mlxsw_sp_vr_put(mlxsw_sp, vr);
7244 }
7245 
7246 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
7247 				     struct mlxsw_sp_fib_node *fib_node)
7248 {
7249 	struct mlxsw_sp_fib4_entry *fib4_entry;
7250 
7251 	fib4_entry = container_of(fib_node->fib_entry,
7252 				  struct mlxsw_sp_fib4_entry, common);
7253 	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
7254 	mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
7255 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7256 }
7257 
7258 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
7259 				     struct mlxsw_sp_fib_node *fib_node)
7260 {
7261 	struct mlxsw_sp_fib6_entry *fib6_entry;
7262 
7263 	fib6_entry = container_of(fib_node->fib_entry,
7264 				  struct mlxsw_sp_fib6_entry, common);
7265 	mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
7266 	mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
7267 	mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
7268 }
7269 
7270 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
7271 				    struct mlxsw_sp_fib_node *fib_node)
7272 {
7273 	switch (fib_node->fib->proto) {
7274 	case MLXSW_SP_L3_PROTO_IPV4:
7275 		mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
7276 		break;
7277 	case MLXSW_SP_L3_PROTO_IPV6:
7278 		mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node);
7279 		break;
7280 	}
7281 }
7282 
7283 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
7284 				  struct mlxsw_sp_vr *vr,
7285 				  enum mlxsw_sp_l3proto proto)
7286 {
7287 	struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
7288 	struct mlxsw_sp_fib_node *fib_node, *tmp;
7289 
7290 	list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
7291 		bool do_break = &tmp->list == &fib->node_list;
7292 
7293 		mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
7294 		if (do_break)
7295 			break;
7296 	}
7297 }
7298 
7299 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
7300 {
7301 	int i, j;
7302 
7303 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
7304 		struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
7305 
7306 		if (!mlxsw_sp_vr_is_used(vr))
7307 			continue;
7308 
7309 		for (j = 0; j < MLXSW_SP_L3_PROTO_MAX; j++)
7310 			mlxsw_sp_mr_table_flush(vr->mr_table[j]);
7311 		mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
7312 
7313 		/* If virtual router was only used for IPv4, then it's no
7314 		 * longer used.
7315 		 */
7316 		if (!mlxsw_sp_vr_is_used(vr))
7317 			continue;
7318 		mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
7319 	}
7320 }
7321 
7322 struct mlxsw_sp_fib6_event_work {
7323 	struct fib6_info **rt_arr;
7324 	unsigned int nrt6;
7325 };
7326 
7327 struct mlxsw_sp_fib_event_work {
7328 	struct work_struct work;
7329 	union {
7330 		struct mlxsw_sp_fib6_event_work fib6_work;
7331 		struct fib_entry_notifier_info fen_info;
7332 		struct fib_rule_notifier_info fr_info;
7333 		struct fib_nh_notifier_info fnh_info;
7334 		struct mfc_entry_notifier_info men_info;
7335 		struct vif_entry_notifier_info ven_info;
7336 	};
7337 	struct mlxsw_sp *mlxsw_sp;
7338 	unsigned long event;
7339 };
7340 
7341 static int
7342 mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work *fib6_work,
7343 			       struct fib6_entry_notifier_info *fen6_info)
7344 {
7345 	struct fib6_info *rt = fen6_info->rt;
7346 	struct fib6_info **rt_arr;
7347 	struct fib6_info *iter;
7348 	unsigned int nrt6;
7349 	int i = 0;
7350 
7351 	nrt6 = fen6_info->nsiblings + 1;
7352 
7353 	rt_arr = kcalloc(nrt6, sizeof(struct fib6_info *), GFP_ATOMIC);
7354 	if (!rt_arr)
7355 		return -ENOMEM;
7356 
7357 	fib6_work->rt_arr = rt_arr;
7358 	fib6_work->nrt6 = nrt6;
7359 
7360 	rt_arr[0] = rt;
7361 	fib6_info_hold(rt);
7362 
7363 	if (!fen6_info->nsiblings)
7364 		return 0;
7365 
7366 	list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
7367 		if (i == fen6_info->nsiblings)
7368 			break;
7369 
7370 		rt_arr[i + 1] = iter;
7371 		fib6_info_hold(iter);
7372 		i++;
7373 	}
7374 	WARN_ON_ONCE(i != fen6_info->nsiblings);
7375 
7376 	return 0;
7377 }
7378 
7379 static void
7380 mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work *fib6_work)
7381 {
7382 	int i;
7383 
7384 	for (i = 0; i < fib6_work->nrt6; i++)
7385 		mlxsw_sp_rt6_release(fib6_work->rt_arr[i]);
7386 	kfree(fib6_work->rt_arr);
7387 }
7388 
7389 static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
7390 {
7391 	struct mlxsw_sp_fib_event_work *fib_work =
7392 		container_of(work, struct mlxsw_sp_fib_event_work, work);
7393 	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
7394 	int err;
7395 
7396 	mutex_lock(&mlxsw_sp->router->lock);
7397 	mlxsw_sp_span_respin(mlxsw_sp);
7398 
7399 	switch (fib_work->event) {
7400 	case FIB_EVENT_ENTRY_REPLACE:
7401 		err = mlxsw_sp_router_fib4_replace(mlxsw_sp,
7402 						   &fib_work->fen_info);
7403 		if (err) {
7404 			dev_warn(mlxsw_sp->bus_info->dev, "FIB replace failed.\n");
7405 			mlxsw_sp_fib4_offload_failed_flag_set(mlxsw_sp,
7406 							      &fib_work->fen_info);
7407 		}
7408 		fib_info_put(fib_work->fen_info.fi);
7409 		break;
7410 	case FIB_EVENT_ENTRY_DEL:
7411 		mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
7412 		fib_info_put(fib_work->fen_info.fi);
7413 		break;
7414 	case FIB_EVENT_NH_ADD:
7415 	case FIB_EVENT_NH_DEL:
7416 		mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event,
7417 					fib_work->fnh_info.fib_nh);
7418 		fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
7419 		break;
7420 	}
7421 	mutex_unlock(&mlxsw_sp->router->lock);
7422 	kfree(fib_work);
7423 }
7424 
7425 static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
7426 {
7427 	struct mlxsw_sp_fib_event_work *fib_work =
7428 		    container_of(work, struct mlxsw_sp_fib_event_work, work);
7429 	struct mlxsw_sp_fib6_event_work *fib6_work = &fib_work->fib6_work;
7430 	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
7431 	int err;
7432 
7433 	mutex_lock(&mlxsw_sp->router->lock);
7434 	mlxsw_sp_span_respin(mlxsw_sp);
7435 
7436 	switch (fib_work->event) {
7437 	case FIB_EVENT_ENTRY_REPLACE:
7438 		err = mlxsw_sp_router_fib6_replace(mlxsw_sp,
7439 						   fib6_work->rt_arr,
7440 						   fib6_work->nrt6);
7441 		if (err) {
7442 			dev_warn(mlxsw_sp->bus_info->dev, "FIB replace failed.\n");
7443 			mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp,
7444 							      fib6_work->rt_arr,
7445 							      fib6_work->nrt6);
7446 		}
7447 		mlxsw_sp_router_fib6_work_fini(fib6_work);
7448 		break;
7449 	case FIB_EVENT_ENTRY_APPEND:
7450 		err = mlxsw_sp_router_fib6_append(mlxsw_sp,
7451 						  fib6_work->rt_arr,
7452 						  fib6_work->nrt6);
7453 		if (err) {
7454 			dev_warn(mlxsw_sp->bus_info->dev, "FIB append failed.\n");
7455 			mlxsw_sp_fib6_offload_failed_flag_set(mlxsw_sp,
7456 							      fib6_work->rt_arr,
7457 							      fib6_work->nrt6);
7458 		}
7459 		mlxsw_sp_router_fib6_work_fini(fib6_work);
7460 		break;
7461 	case FIB_EVENT_ENTRY_DEL:
7462 		mlxsw_sp_router_fib6_del(mlxsw_sp,
7463 					 fib6_work->rt_arr,
7464 					 fib6_work->nrt6);
7465 		mlxsw_sp_router_fib6_work_fini(fib6_work);
7466 		break;
7467 	}
7468 	mutex_unlock(&mlxsw_sp->router->lock);
7469 	kfree(fib_work);
7470 }
7471 
7472 static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work)
7473 {
7474 	struct mlxsw_sp_fib_event_work *fib_work =
7475 		container_of(work, struct mlxsw_sp_fib_event_work, work);
7476 	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
7477 	bool replace;
7478 	int err;
7479 
7480 	rtnl_lock();
7481 	mutex_lock(&mlxsw_sp->router->lock);
7482 	switch (fib_work->event) {
7483 	case FIB_EVENT_ENTRY_REPLACE:
7484 	case FIB_EVENT_ENTRY_ADD:
7485 		replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
7486 
7487 		err = mlxsw_sp_router_fibmr_add(mlxsw_sp, &fib_work->men_info,
7488 						replace);
7489 		if (err)
7490 			dev_warn(mlxsw_sp->bus_info->dev, "MR entry add failed.\n");
7491 		mr_cache_put(fib_work->men_info.mfc);
7492 		break;
7493 	case FIB_EVENT_ENTRY_DEL:
7494 		mlxsw_sp_router_fibmr_del(mlxsw_sp, &fib_work->men_info);
7495 		mr_cache_put(fib_work->men_info.mfc);
7496 		break;
7497 	case FIB_EVENT_VIF_ADD:
7498 		err = mlxsw_sp_router_fibmr_vif_add(mlxsw_sp,
7499 						    &fib_work->ven_info);
7500 		if (err)
7501 			dev_warn(mlxsw_sp->bus_info->dev, "MR VIF add failed.\n");
7502 		dev_put(fib_work->ven_info.dev);
7503 		break;
7504 	case FIB_EVENT_VIF_DEL:
7505 		mlxsw_sp_router_fibmr_vif_del(mlxsw_sp,
7506 					      &fib_work->ven_info);
7507 		dev_put(fib_work->ven_info.dev);
7508 		break;
7509 	}
7510 	mutex_unlock(&mlxsw_sp->router->lock);
7511 	rtnl_unlock();
7512 	kfree(fib_work);
7513 }
7514 
7515 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
7516 				       struct fib_notifier_info *info)
7517 {
7518 	struct fib_entry_notifier_info *fen_info;
7519 	struct fib_nh_notifier_info *fnh_info;
7520 
7521 	switch (fib_work->event) {
7522 	case FIB_EVENT_ENTRY_REPLACE:
7523 	case FIB_EVENT_ENTRY_DEL:
7524 		fen_info = container_of(info, struct fib_entry_notifier_info,
7525 					info);
7526 		fib_work->fen_info = *fen_info;
7527 		/* Take reference on fib_info to prevent it from being
7528 		 * freed while work is queued. Release it afterwards.
7529 		 */
7530 		fib_info_hold(fib_work->fen_info.fi);
7531 		break;
7532 	case FIB_EVENT_NH_ADD:
7533 	case FIB_EVENT_NH_DEL:
7534 		fnh_info = container_of(info, struct fib_nh_notifier_info,
7535 					info);
7536 		fib_work->fnh_info = *fnh_info;
7537 		fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
7538 		break;
7539 	}
7540 }
7541 
7542 static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
7543 				      struct fib_notifier_info *info)
7544 {
7545 	struct fib6_entry_notifier_info *fen6_info;
7546 	int err;
7547 
7548 	switch (fib_work->event) {
7549 	case FIB_EVENT_ENTRY_REPLACE:
7550 	case FIB_EVENT_ENTRY_APPEND:
7551 	case FIB_EVENT_ENTRY_DEL:
7552 		fen6_info = container_of(info, struct fib6_entry_notifier_info,
7553 					 info);
7554 		err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
7555 						     fen6_info);
7556 		if (err)
7557 			return err;
7558 		break;
7559 	}
7560 
7561 	return 0;
7562 }
7563 
7564 static void
7565 mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work,
7566 			    struct fib_notifier_info *info)
7567 {
7568 	switch (fib_work->event) {
7569 	case FIB_EVENT_ENTRY_REPLACE:
7570 	case FIB_EVENT_ENTRY_ADD:
7571 	case FIB_EVENT_ENTRY_DEL:
7572 		memcpy(&fib_work->men_info, info, sizeof(fib_work->men_info));
7573 		mr_cache_hold(fib_work->men_info.mfc);
7574 		break;
7575 	case FIB_EVENT_VIF_ADD:
7576 	case FIB_EVENT_VIF_DEL:
7577 		memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info));
7578 		dev_hold(fib_work->ven_info.dev);
7579 		break;
7580 	}
7581 }
7582 
7583 static int mlxsw_sp_router_fib_rule_event(unsigned long event,
7584 					  struct fib_notifier_info *info,
7585 					  struct mlxsw_sp *mlxsw_sp)
7586 {
7587 	struct netlink_ext_ack *extack = info->extack;
7588 	struct fib_rule_notifier_info *fr_info;
7589 	struct fib_rule *rule;
7590 	int err = 0;
7591 
7592 	/* nothing to do at the moment */
7593 	if (event == FIB_EVENT_RULE_DEL)
7594 		return 0;
7595 
7596 	fr_info = container_of(info, struct fib_rule_notifier_info, info);
7597 	rule = fr_info->rule;
7598 
7599 	/* Rule only affects locally generated traffic */
7600 	if (rule->iifindex == mlxsw_sp_net(mlxsw_sp)->loopback_dev->ifindex)
7601 		return 0;
7602 
7603 	switch (info->family) {
7604 	case AF_INET:
7605 		if (!fib4_rule_default(rule) && !rule->l3mdev)
7606 			err = -EOPNOTSUPP;
7607 		break;
7608 	case AF_INET6:
7609 		if (!fib6_rule_default(rule) && !rule->l3mdev)
7610 			err = -EOPNOTSUPP;
7611 		break;
7612 	case RTNL_FAMILY_IPMR:
7613 		if (!ipmr_rule_default(rule) && !rule->l3mdev)
7614 			err = -EOPNOTSUPP;
7615 		break;
7616 	case RTNL_FAMILY_IP6MR:
7617 		if (!ip6mr_rule_default(rule) && !rule->l3mdev)
7618 			err = -EOPNOTSUPP;
7619 		break;
7620 	}
7621 
7622 	if (err < 0)
7623 		NL_SET_ERR_MSG_MOD(extack, "FIB rules not supported");
7624 
7625 	return err;
7626 }
7627 
7628 /* Called with rcu_read_lock() */
7629 static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
7630 				     unsigned long event, void *ptr)
7631 {
7632 	struct mlxsw_sp_fib_event_work *fib_work;
7633 	struct fib_notifier_info *info = ptr;
7634 	struct mlxsw_sp_router *router;
7635 	int err;
7636 
7637 	if ((info->family != AF_INET && info->family != AF_INET6 &&
7638 	     info->family != RTNL_FAMILY_IPMR &&
7639 	     info->family != RTNL_FAMILY_IP6MR))
7640 		return NOTIFY_DONE;
7641 
7642 	router = container_of(nb, struct mlxsw_sp_router, fib_nb);
7643 
7644 	switch (event) {
7645 	case FIB_EVENT_RULE_ADD:
7646 	case FIB_EVENT_RULE_DEL:
7647 		err = mlxsw_sp_router_fib_rule_event(event, info,
7648 						     router->mlxsw_sp);
7649 		return notifier_from_errno(err);
7650 	case FIB_EVENT_ENTRY_ADD:
7651 	case FIB_EVENT_ENTRY_REPLACE:
7652 	case FIB_EVENT_ENTRY_APPEND:
7653 		if (info->family == AF_INET) {
7654 			struct fib_entry_notifier_info *fen_info = ptr;
7655 
7656 			if (fen_info->fi->fib_nh_is_v6) {
7657 				NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
7658 				return notifier_from_errno(-EINVAL);
7659 			}
7660 		}
7661 		break;
7662 	}
7663 
7664 	fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
7665 	if (!fib_work)
7666 		return NOTIFY_BAD;
7667 
7668 	fib_work->mlxsw_sp = router->mlxsw_sp;
7669 	fib_work->event = event;
7670 
7671 	switch (info->family) {
7672 	case AF_INET:
7673 		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work);
7674 		mlxsw_sp_router_fib4_event(fib_work, info);
7675 		break;
7676 	case AF_INET6:
7677 		INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
7678 		err = mlxsw_sp_router_fib6_event(fib_work, info);
7679 		if (err)
7680 			goto err_fib_event;
7681 		break;
7682 	case RTNL_FAMILY_IP6MR:
7683 	case RTNL_FAMILY_IPMR:
7684 		INIT_WORK(&fib_work->work, mlxsw_sp_router_fibmr_event_work);
7685 		mlxsw_sp_router_fibmr_event(fib_work, info);
7686 		break;
7687 	}
7688 
7689 	mlxsw_core_schedule_work(&fib_work->work);
7690 
7691 	return NOTIFY_DONE;
7692 
7693 err_fib_event:
7694 	kfree(fib_work);
7695 	return NOTIFY_BAD;
7696 }
7697 
7698 static struct mlxsw_sp_rif *
7699 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
7700 			 const struct net_device *dev)
7701 {
7702 	int i;
7703 
7704 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
7705 		if (mlxsw_sp->router->rifs[i] &&
7706 		    mlxsw_sp->router->rifs[i]->dev == dev)
7707 			return mlxsw_sp->router->rifs[i];
7708 
7709 	return NULL;
7710 }
7711 
7712 bool mlxsw_sp_rif_exists(struct mlxsw_sp *mlxsw_sp,
7713 			 const struct net_device *dev)
7714 {
7715 	struct mlxsw_sp_rif *rif;
7716 
7717 	mutex_lock(&mlxsw_sp->router->lock);
7718 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
7719 	mutex_unlock(&mlxsw_sp->router->lock);
7720 
7721 	return rif;
7722 }
7723 
7724 u16 mlxsw_sp_rif_vid(struct mlxsw_sp *mlxsw_sp, const struct net_device *dev)
7725 {
7726 	struct mlxsw_sp_rif *rif;
7727 	u16 vid = 0;
7728 
7729 	mutex_lock(&mlxsw_sp->router->lock);
7730 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
7731 	if (!rif)
7732 		goto out;
7733 
7734 	/* We only return the VID for VLAN RIFs. Otherwise we return an
7735 	 * invalid value (0).
7736 	 */
7737 	if (rif->ops->type != MLXSW_SP_RIF_TYPE_VLAN)
7738 		goto out;
7739 
7740 	vid = mlxsw_sp_fid_8021q_vid(rif->fid);
7741 
7742 out:
7743 	mutex_unlock(&mlxsw_sp->router->lock);
7744 	return vid;
7745 }
7746 
7747 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
7748 {
7749 	char ritr_pl[MLXSW_REG_RITR_LEN];
7750 	int err;
7751 
7752 	mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
7753 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7754 	if (err)
7755 		return err;
7756 
7757 	mlxsw_reg_ritr_enable_set(ritr_pl, false);
7758 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7759 }
7760 
7761 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
7762 					  struct mlxsw_sp_rif *rif)
7763 {
7764 	mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
7765 	mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
7766 	mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
7767 }
7768 
7769 static bool
7770 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
7771 			   unsigned long event)
7772 {
7773 	struct inet6_dev *inet6_dev;
7774 	bool addr_list_empty = true;
7775 	struct in_device *idev;
7776 
7777 	switch (event) {
7778 	case NETDEV_UP:
7779 		return rif == NULL;
7780 	case NETDEV_DOWN:
7781 		rcu_read_lock();
7782 		idev = __in_dev_get_rcu(dev);
7783 		if (idev && idev->ifa_list)
7784 			addr_list_empty = false;
7785 
7786 		inet6_dev = __in6_dev_get(dev);
7787 		if (addr_list_empty && inet6_dev &&
7788 		    !list_empty(&inet6_dev->addr_list))
7789 			addr_list_empty = false;
7790 		rcu_read_unlock();
7791 
7792 		/* macvlans do not have a RIF, but rather piggy back on the
7793 		 * RIF of their lower device.
7794 		 */
7795 		if (netif_is_macvlan(dev) && addr_list_empty)
7796 			return true;
7797 
7798 		if (rif && addr_list_empty &&
7799 		    !netif_is_l3_slave(rif->dev))
7800 			return true;
7801 		/* It is possible we already removed the RIF ourselves
7802 		 * if it was assigned to a netdev that is now a bridge
7803 		 * or LAG slave.
7804 		 */
7805 		return false;
7806 	}
7807 
7808 	return false;
7809 }
7810 
7811 static enum mlxsw_sp_rif_type
7812 mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
7813 		      const struct net_device *dev)
7814 {
7815 	enum mlxsw_sp_fid_type type;
7816 
7817 	if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
7818 		return MLXSW_SP_RIF_TYPE_IPIP_LB;
7819 
7820 	/* Otherwise RIF type is derived from the type of the underlying FID. */
7821 	if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
7822 		type = MLXSW_SP_FID_TYPE_8021Q;
7823 	else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
7824 		type = MLXSW_SP_FID_TYPE_8021Q;
7825 	else if (netif_is_bridge_master(dev))
7826 		type = MLXSW_SP_FID_TYPE_8021D;
7827 	else
7828 		type = MLXSW_SP_FID_TYPE_RFID;
7829 
7830 	return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
7831 }
7832 
7833 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index,
7834 				    u8 rif_entries)
7835 {
7836 	*p_rif_index = gen_pool_alloc(mlxsw_sp->router->rifs_table,
7837 				      rif_entries);
7838 	if (*p_rif_index == 0)
7839 		return -ENOBUFS;
7840 	*p_rif_index -= MLXSW_SP_ROUTER_GENALLOC_OFFSET;
7841 
7842 	/* RIF indexes must be aligned to the allocation size. */
7843 	WARN_ON_ONCE(*p_rif_index % rif_entries);
7844 
7845 	return 0;
7846 }
7847 
7848 static void mlxsw_sp_rif_index_free(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
7849 				    u8 rif_entries)
7850 {
7851 	gen_pool_free(mlxsw_sp->router->rifs_table,
7852 		      MLXSW_SP_ROUTER_GENALLOC_OFFSET + rif_index, rif_entries);
7853 }
7854 
7855 static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
7856 					       u16 vr_id,
7857 					       struct net_device *l3_dev)
7858 {
7859 	struct mlxsw_sp_rif *rif;
7860 
7861 	rif = kzalloc(rif_size, GFP_KERNEL);
7862 	if (!rif)
7863 		return NULL;
7864 
7865 	INIT_LIST_HEAD(&rif->nexthop_list);
7866 	INIT_LIST_HEAD(&rif->neigh_list);
7867 	if (l3_dev) {
7868 		ether_addr_copy(rif->addr, l3_dev->dev_addr);
7869 		rif->mtu = l3_dev->mtu;
7870 		rif->dev = l3_dev;
7871 	}
7872 	rif->vr_id = vr_id;
7873 	rif->rif_index = rif_index;
7874 
7875 	return rif;
7876 }
7877 
7878 struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
7879 					   u16 rif_index)
7880 {
7881 	return mlxsw_sp->router->rifs[rif_index];
7882 }
7883 
7884 u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
7885 {
7886 	return rif->rif_index;
7887 }
7888 
7889 u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
7890 {
7891 	return lb_rif->common.rif_index;
7892 }
7893 
7894 u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
7895 {
7896 	u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev);
7897 	struct mlxsw_sp_vr *ul_vr;
7898 
7899 	ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL);
7900 	if (WARN_ON(IS_ERR(ul_vr)))
7901 		return 0;
7902 
7903 	return ul_vr->id;
7904 }
7905 
7906 u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
7907 {
7908 	return lb_rif->ul_rif_id;
7909 }
7910 
7911 static bool
7912 mlxsw_sp_router_port_l3_stats_enabled(struct mlxsw_sp_rif *rif)
7913 {
7914 	return mlxsw_sp_rif_counter_valid_get(rif,
7915 					      MLXSW_SP_RIF_COUNTER_EGRESS) &&
7916 	       mlxsw_sp_rif_counter_valid_get(rif,
7917 					      MLXSW_SP_RIF_COUNTER_INGRESS);
7918 }
7919 
7920 static int
7921 mlxsw_sp_router_port_l3_stats_enable(struct mlxsw_sp_rif *rif)
7922 {
7923 	int err;
7924 
7925 	err = mlxsw_sp_rif_counter_alloc(rif, MLXSW_SP_RIF_COUNTER_INGRESS);
7926 	if (err)
7927 		return err;
7928 
7929 	/* Clear stale data. */
7930 	err = mlxsw_sp_rif_counter_fetch_clear(rif,
7931 					       MLXSW_SP_RIF_COUNTER_INGRESS,
7932 					       NULL);
7933 	if (err)
7934 		goto err_clear_ingress;
7935 
7936 	err = mlxsw_sp_rif_counter_alloc(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
7937 	if (err)
7938 		goto err_alloc_egress;
7939 
7940 	/* Clear stale data. */
7941 	err = mlxsw_sp_rif_counter_fetch_clear(rif,
7942 					       MLXSW_SP_RIF_COUNTER_EGRESS,
7943 					       NULL);
7944 	if (err)
7945 		goto err_clear_egress;
7946 
7947 	return 0;
7948 
7949 err_clear_egress:
7950 	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
7951 err_alloc_egress:
7952 err_clear_ingress:
7953 	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_INGRESS);
7954 	return err;
7955 }
7956 
7957 static void
7958 mlxsw_sp_router_port_l3_stats_disable(struct mlxsw_sp_rif *rif)
7959 {
7960 	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_EGRESS);
7961 	mlxsw_sp_rif_counter_free(rif, MLXSW_SP_RIF_COUNTER_INGRESS);
7962 }
7963 
7964 static void
7965 mlxsw_sp_router_port_l3_stats_report_used(struct mlxsw_sp_rif *rif,
7966 					  struct netdev_notifier_offload_xstats_info *info)
7967 {
7968 	if (!mlxsw_sp_router_port_l3_stats_enabled(rif))
7969 		return;
7970 	netdev_offload_xstats_report_used(info->report_used);
7971 }
7972 
7973 static int
7974 mlxsw_sp_router_port_l3_stats_fetch(struct mlxsw_sp_rif *rif,
7975 				    struct rtnl_hw_stats64 *p_stats)
7976 {
7977 	struct mlxsw_sp_rif_counter_set_basic ingress;
7978 	struct mlxsw_sp_rif_counter_set_basic egress;
7979 	int err;
7980 
7981 	err = mlxsw_sp_rif_counter_fetch_clear(rif,
7982 					       MLXSW_SP_RIF_COUNTER_INGRESS,
7983 					       &ingress);
7984 	if (err)
7985 		return err;
7986 
7987 	err = mlxsw_sp_rif_counter_fetch_clear(rif,
7988 					       MLXSW_SP_RIF_COUNTER_EGRESS,
7989 					       &egress);
7990 	if (err)
7991 		return err;
7992 
7993 #define MLXSW_SP_ROUTER_ALL_GOOD(SET, SFX)		\
7994 		((SET.good_unicast_ ## SFX) +		\
7995 		 (SET.good_multicast_ ## SFX) +		\
7996 		 (SET.good_broadcast_ ## SFX))
7997 
7998 	p_stats->rx_packets = MLXSW_SP_ROUTER_ALL_GOOD(ingress, packets);
7999 	p_stats->tx_packets = MLXSW_SP_ROUTER_ALL_GOOD(egress, packets);
8000 	p_stats->rx_bytes = MLXSW_SP_ROUTER_ALL_GOOD(ingress, bytes);
8001 	p_stats->tx_bytes = MLXSW_SP_ROUTER_ALL_GOOD(egress, bytes);
8002 	p_stats->rx_errors = ingress.error_packets;
8003 	p_stats->tx_errors = egress.error_packets;
8004 	p_stats->rx_dropped = ingress.discard_packets;
8005 	p_stats->tx_dropped = egress.discard_packets;
8006 	p_stats->multicast = ingress.good_multicast_packets +
8007 			     ingress.good_broadcast_packets;
8008 
8009 #undef MLXSW_SP_ROUTER_ALL_GOOD
8010 
8011 	return 0;
8012 }
8013 
8014 static int
8015 mlxsw_sp_router_port_l3_stats_report_delta(struct mlxsw_sp_rif *rif,
8016 					   struct netdev_notifier_offload_xstats_info *info)
8017 {
8018 	struct rtnl_hw_stats64 stats = {};
8019 	int err;
8020 
8021 	if (!mlxsw_sp_router_port_l3_stats_enabled(rif))
8022 		return 0;
8023 
8024 	err = mlxsw_sp_router_port_l3_stats_fetch(rif, &stats);
8025 	if (err)
8026 		return err;
8027 
8028 	netdev_offload_xstats_report_delta(info->report_delta, &stats);
8029 	return 0;
8030 }
8031 
8032 struct mlxsw_sp_router_hwstats_notify_work {
8033 	struct work_struct work;
8034 	struct net_device *dev;
8035 };
8036 
8037 static void mlxsw_sp_router_hwstats_notify_work(struct work_struct *work)
8038 {
8039 	struct mlxsw_sp_router_hwstats_notify_work *hws_work =
8040 		container_of(work, struct mlxsw_sp_router_hwstats_notify_work,
8041 			     work);
8042 
8043 	rtnl_lock();
8044 	rtnl_offload_xstats_notify(hws_work->dev);
8045 	rtnl_unlock();
8046 	dev_put(hws_work->dev);
8047 	kfree(hws_work);
8048 }
8049 
8050 static void
8051 mlxsw_sp_router_hwstats_notify_schedule(struct net_device *dev)
8052 {
8053 	struct mlxsw_sp_router_hwstats_notify_work *hws_work;
8054 
8055 	/* To collect notification payload, the core ends up sending another
8056 	 * notifier block message, which would deadlock on the attempt to
8057 	 * acquire the router lock again. Just postpone the notification until
8058 	 * later.
8059 	 */
8060 
8061 	hws_work = kzalloc(sizeof(*hws_work), GFP_KERNEL);
8062 	if (!hws_work)
8063 		return;
8064 
8065 	INIT_WORK(&hws_work->work, mlxsw_sp_router_hwstats_notify_work);
8066 	dev_hold(dev);
8067 	hws_work->dev = dev;
8068 	mlxsw_core_schedule_work(&hws_work->work);
8069 }
8070 
8071 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
8072 {
8073 	return rif->dev->ifindex;
8074 }
8075 
8076 const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
8077 {
8078 	return rif->dev;
8079 }
8080 
8081 static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif)
8082 {
8083 	struct rtnl_hw_stats64 stats = {};
8084 
8085 	if (!mlxsw_sp_router_port_l3_stats_fetch(rif, &stats))
8086 		netdev_offload_xstats_push_delta(rif->dev,
8087 						 NETDEV_OFFLOAD_XSTATS_TYPE_L3,
8088 						 &stats);
8089 }
8090 
8091 static struct mlxsw_sp_rif *
8092 mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
8093 		    const struct mlxsw_sp_rif_params *params,
8094 		    struct netlink_ext_ack *extack)
8095 {
8096 	u8 rif_entries = params->double_entry ? 2 : 1;
8097 	u32 tb_id = l3mdev_fib_table(params->dev);
8098 	const struct mlxsw_sp_rif_ops *ops;
8099 	struct mlxsw_sp_fid *fid = NULL;
8100 	enum mlxsw_sp_rif_type type;
8101 	struct mlxsw_sp_rif *rif;
8102 	struct mlxsw_sp_vr *vr;
8103 	u16 rif_index;
8104 	int i, err;
8105 
8106 	type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
8107 	ops = mlxsw_sp->router->rif_ops_arr[type];
8108 
8109 	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack);
8110 	if (IS_ERR(vr))
8111 		return ERR_CAST(vr);
8112 	vr->rif_count++;
8113 
8114 	err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index, rif_entries);
8115 	if (err) {
8116 		NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
8117 		goto err_rif_index_alloc;
8118 	}
8119 
8120 	rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
8121 	if (!rif) {
8122 		err = -ENOMEM;
8123 		goto err_rif_alloc;
8124 	}
8125 	dev_hold(rif->dev);
8126 	mlxsw_sp->router->rifs[rif_index] = rif;
8127 	rif->mlxsw_sp = mlxsw_sp;
8128 	rif->ops = ops;
8129 	rif->rif_entries = rif_entries;
8130 
8131 	if (ops->fid_get) {
8132 		fid = ops->fid_get(rif, extack);
8133 		if (IS_ERR(fid)) {
8134 			err = PTR_ERR(fid);
8135 			goto err_fid_get;
8136 		}
8137 		rif->fid = fid;
8138 	}
8139 
8140 	if (ops->setup)
8141 		ops->setup(rif, params);
8142 
8143 	err = ops->configure(rif, extack);
8144 	if (err)
8145 		goto err_configure;
8146 
8147 	for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++) {
8148 		err = mlxsw_sp_mr_rif_add(vr->mr_table[i], rif);
8149 		if (err)
8150 			goto err_mr_rif_add;
8151 	}
8152 
8153 	if (netdev_offload_xstats_enabled(rif->dev,
8154 					  NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
8155 		err = mlxsw_sp_router_port_l3_stats_enable(rif);
8156 		if (err)
8157 			goto err_stats_enable;
8158 		mlxsw_sp_router_hwstats_notify_schedule(rif->dev);
8159 	} else {
8160 		mlxsw_sp_rif_counters_alloc(rif);
8161 	}
8162 
8163 	atomic_add(rif_entries, &mlxsw_sp->router->rifs_count);
8164 	return rif;
8165 
8166 err_stats_enable:
8167 err_mr_rif_add:
8168 	for (i--; i >= 0; i--)
8169 		mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
8170 	ops->deconfigure(rif);
8171 err_configure:
8172 	if (fid)
8173 		mlxsw_sp_fid_put(fid);
8174 err_fid_get:
8175 	mlxsw_sp->router->rifs[rif_index] = NULL;
8176 	dev_put(rif->dev);
8177 	kfree(rif);
8178 err_rif_alloc:
8179 	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
8180 err_rif_index_alloc:
8181 	vr->rif_count--;
8182 	mlxsw_sp_vr_put(mlxsw_sp, vr);
8183 	return ERR_PTR(err);
8184 }
8185 
8186 static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
8187 {
8188 	const struct mlxsw_sp_rif_ops *ops = rif->ops;
8189 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
8190 	struct mlxsw_sp_fid *fid = rif->fid;
8191 	u8 rif_entries = rif->rif_entries;
8192 	u16 rif_index = rif->rif_index;
8193 	struct mlxsw_sp_vr *vr;
8194 	int i;
8195 
8196 	atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
8197 	mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
8198 	vr = &mlxsw_sp->router->vrs[rif->vr_id];
8199 
8200 	if (netdev_offload_xstats_enabled(rif->dev,
8201 					  NETDEV_OFFLOAD_XSTATS_TYPE_L3)) {
8202 		mlxsw_sp_rif_push_l3_stats(rif);
8203 		mlxsw_sp_router_port_l3_stats_disable(rif);
8204 		mlxsw_sp_router_hwstats_notify_schedule(rif->dev);
8205 	} else {
8206 		mlxsw_sp_rif_counters_free(rif);
8207 	}
8208 
8209 	for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
8210 		mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
8211 	ops->deconfigure(rif);
8212 	if (fid)
8213 		/* Loopback RIFs are not associated with a FID. */
8214 		mlxsw_sp_fid_put(fid);
8215 	mlxsw_sp->router->rifs[rif->rif_index] = NULL;
8216 	dev_put(rif->dev);
8217 	kfree(rif);
8218 	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
8219 	vr->rif_count--;
8220 	mlxsw_sp_vr_put(mlxsw_sp, vr);
8221 }
8222 
8223 void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
8224 				 struct net_device *dev)
8225 {
8226 	struct mlxsw_sp_rif *rif;
8227 
8228 	mutex_lock(&mlxsw_sp->router->lock);
8229 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
8230 	if (!rif)
8231 		goto out;
8232 	mlxsw_sp_rif_destroy(rif);
8233 out:
8234 	mutex_unlock(&mlxsw_sp->router->lock);
8235 }
8236 
8237 static void
8238 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
8239 				 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
8240 {
8241 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
8242 
8243 	params->vid = mlxsw_sp_port_vlan->vid;
8244 	params->lag = mlxsw_sp_port->lagged;
8245 	if (params->lag)
8246 		params->lag_id = mlxsw_sp_port->lag_id;
8247 	else
8248 		params->system_port = mlxsw_sp_port->local_port;
8249 }
8250 
8251 static struct mlxsw_sp_rif_subport *
8252 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
8253 {
8254 	return container_of(rif, struct mlxsw_sp_rif_subport, common);
8255 }
8256 
8257 static struct mlxsw_sp_rif *
8258 mlxsw_sp_rif_subport_get(struct mlxsw_sp *mlxsw_sp,
8259 			 const struct mlxsw_sp_rif_params *params,
8260 			 struct netlink_ext_ack *extack)
8261 {
8262 	struct mlxsw_sp_rif_subport *rif_subport;
8263 	struct mlxsw_sp_rif *rif;
8264 
8265 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, params->dev);
8266 	if (!rif)
8267 		return mlxsw_sp_rif_create(mlxsw_sp, params, extack);
8268 
8269 	rif_subport = mlxsw_sp_rif_subport_rif(rif);
8270 	refcount_inc(&rif_subport->ref_count);
8271 	return rif;
8272 }
8273 
8274 static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif)
8275 {
8276 	struct mlxsw_sp_rif_subport *rif_subport;
8277 
8278 	rif_subport = mlxsw_sp_rif_subport_rif(rif);
8279 	if (!refcount_dec_and_test(&rif_subport->ref_count))
8280 		return;
8281 
8282 	mlxsw_sp_rif_destroy(rif);
8283 }
8284 
8285 static int mlxsw_sp_rif_mac_profile_index_alloc(struct mlxsw_sp *mlxsw_sp,
8286 						struct mlxsw_sp_rif_mac_profile *profile,
8287 						struct netlink_ext_ack *extack)
8288 {
8289 	u8 max_rif_mac_profiles = mlxsw_sp->router->max_rif_mac_profile;
8290 	struct mlxsw_sp_router *router = mlxsw_sp->router;
8291 	int id;
8292 
8293 	id = idr_alloc(&router->rif_mac_profiles_idr, profile, 0,
8294 		       max_rif_mac_profiles, GFP_KERNEL);
8295 
8296 	if (id >= 0) {
8297 		profile->id = id;
8298 		return 0;
8299 	}
8300 
8301 	if (id == -ENOSPC)
8302 		NL_SET_ERR_MSG_MOD(extack,
8303 				   "Exceeded number of supported router interface MAC profiles");
8304 
8305 	return id;
8306 }
8307 
8308 static struct mlxsw_sp_rif_mac_profile *
8309 mlxsw_sp_rif_mac_profile_index_free(struct mlxsw_sp *mlxsw_sp, u8 mac_profile)
8310 {
8311 	struct mlxsw_sp_rif_mac_profile *profile;
8312 
8313 	profile = idr_remove(&mlxsw_sp->router->rif_mac_profiles_idr,
8314 			     mac_profile);
8315 	WARN_ON(!profile);
8316 	return profile;
8317 }
8318 
8319 static struct mlxsw_sp_rif_mac_profile *
8320 mlxsw_sp_rif_mac_profile_alloc(const char *mac)
8321 {
8322 	struct mlxsw_sp_rif_mac_profile *profile;
8323 
8324 	profile = kzalloc(sizeof(*profile), GFP_KERNEL);
8325 	if (!profile)
8326 		return NULL;
8327 
8328 	ether_addr_copy(profile->mac_prefix, mac);
8329 	refcount_set(&profile->ref_count, 1);
8330 	return profile;
8331 }
8332 
8333 static struct mlxsw_sp_rif_mac_profile *
8334 mlxsw_sp_rif_mac_profile_find(const struct mlxsw_sp *mlxsw_sp, const char *mac)
8335 {
8336 	struct mlxsw_sp_router *router = mlxsw_sp->router;
8337 	struct mlxsw_sp_rif_mac_profile *profile;
8338 	int id;
8339 
8340 	idr_for_each_entry(&router->rif_mac_profiles_idr, profile, id) {
8341 		if (ether_addr_equal_masked(profile->mac_prefix, mac,
8342 					    mlxsw_sp->mac_mask))
8343 			return profile;
8344 	}
8345 
8346 	return NULL;
8347 }
8348 
8349 static u64 mlxsw_sp_rif_mac_profiles_occ_get(void *priv)
8350 {
8351 	const struct mlxsw_sp *mlxsw_sp = priv;
8352 
8353 	return atomic_read(&mlxsw_sp->router->rif_mac_profiles_count);
8354 }
8355 
8356 static u64 mlxsw_sp_rifs_occ_get(void *priv)
8357 {
8358 	const struct mlxsw_sp *mlxsw_sp = priv;
8359 
8360 	return atomic_read(&mlxsw_sp->router->rifs_count);
8361 }
8362 
8363 static struct mlxsw_sp_rif_mac_profile *
8364 mlxsw_sp_rif_mac_profile_create(struct mlxsw_sp *mlxsw_sp, const char *mac,
8365 				struct netlink_ext_ack *extack)
8366 {
8367 	struct mlxsw_sp_rif_mac_profile *profile;
8368 	int err;
8369 
8370 	profile = mlxsw_sp_rif_mac_profile_alloc(mac);
8371 	if (!profile)
8372 		return ERR_PTR(-ENOMEM);
8373 
8374 	err = mlxsw_sp_rif_mac_profile_index_alloc(mlxsw_sp, profile, extack);
8375 	if (err)
8376 		goto profile_index_alloc_err;
8377 
8378 	atomic_inc(&mlxsw_sp->router->rif_mac_profiles_count);
8379 	return profile;
8380 
8381 profile_index_alloc_err:
8382 	kfree(profile);
8383 	return ERR_PTR(err);
8384 }
8385 
8386 static void mlxsw_sp_rif_mac_profile_destroy(struct mlxsw_sp *mlxsw_sp,
8387 					     u8 mac_profile)
8388 {
8389 	struct mlxsw_sp_rif_mac_profile *profile;
8390 
8391 	atomic_dec(&mlxsw_sp->router->rif_mac_profiles_count);
8392 	profile = mlxsw_sp_rif_mac_profile_index_free(mlxsw_sp, mac_profile);
8393 	kfree(profile);
8394 }
8395 
8396 static int mlxsw_sp_rif_mac_profile_get(struct mlxsw_sp *mlxsw_sp,
8397 					const char *mac, u8 *p_mac_profile,
8398 					struct netlink_ext_ack *extack)
8399 {
8400 	struct mlxsw_sp_rif_mac_profile *profile;
8401 
8402 	profile = mlxsw_sp_rif_mac_profile_find(mlxsw_sp, mac);
8403 	if (profile) {
8404 		refcount_inc(&profile->ref_count);
8405 		goto out;
8406 	}
8407 
8408 	profile = mlxsw_sp_rif_mac_profile_create(mlxsw_sp, mac, extack);
8409 	if (IS_ERR(profile))
8410 		return PTR_ERR(profile);
8411 
8412 out:
8413 	*p_mac_profile = profile->id;
8414 	return 0;
8415 }
8416 
8417 static void mlxsw_sp_rif_mac_profile_put(struct mlxsw_sp *mlxsw_sp,
8418 					 u8 mac_profile)
8419 {
8420 	struct mlxsw_sp_rif_mac_profile *profile;
8421 
8422 	profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr,
8423 			   mac_profile);
8424 	if (WARN_ON(!profile))
8425 		return;
8426 
8427 	if (!refcount_dec_and_test(&profile->ref_count))
8428 		return;
8429 
8430 	mlxsw_sp_rif_mac_profile_destroy(mlxsw_sp, mac_profile);
8431 }
8432 
8433 static bool mlxsw_sp_rif_mac_profile_is_shared(const struct mlxsw_sp_rif *rif)
8434 {
8435 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
8436 	struct mlxsw_sp_rif_mac_profile *profile;
8437 
8438 	profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr,
8439 			   rif->mac_profile_id);
8440 	if (WARN_ON(!profile))
8441 		return false;
8442 
8443 	return refcount_read(&profile->ref_count) > 1;
8444 }
8445 
8446 static int mlxsw_sp_rif_mac_profile_edit(struct mlxsw_sp_rif *rif,
8447 					 const char *new_mac)
8448 {
8449 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
8450 	struct mlxsw_sp_rif_mac_profile *profile;
8451 
8452 	profile = idr_find(&mlxsw_sp->router->rif_mac_profiles_idr,
8453 			   rif->mac_profile_id);
8454 	if (WARN_ON(!profile))
8455 		return -EINVAL;
8456 
8457 	ether_addr_copy(profile->mac_prefix, new_mac);
8458 	return 0;
8459 }
8460 
8461 static int
8462 mlxsw_sp_rif_mac_profile_replace(struct mlxsw_sp *mlxsw_sp,
8463 				 struct mlxsw_sp_rif *rif,
8464 				 const char *new_mac,
8465 				 struct netlink_ext_ack *extack)
8466 {
8467 	u8 mac_profile;
8468 	int err;
8469 
8470 	if (!mlxsw_sp_rif_mac_profile_is_shared(rif) &&
8471 	    !mlxsw_sp_rif_mac_profile_find(mlxsw_sp, new_mac))
8472 		return mlxsw_sp_rif_mac_profile_edit(rif, new_mac);
8473 
8474 	err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, new_mac,
8475 					   &mac_profile, extack);
8476 	if (err)
8477 		return err;
8478 
8479 	mlxsw_sp_rif_mac_profile_put(mlxsw_sp, rif->mac_profile_id);
8480 	rif->mac_profile_id = mac_profile;
8481 	return 0;
8482 }
8483 
8484 static int
8485 __mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
8486 				 struct net_device *l3_dev,
8487 				 struct netlink_ext_ack *extack)
8488 {
8489 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
8490 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
8491 	struct mlxsw_sp_rif_params params = {
8492 		.dev = l3_dev,
8493 	};
8494 	u16 vid = mlxsw_sp_port_vlan->vid;
8495 	struct mlxsw_sp_rif *rif;
8496 	struct mlxsw_sp_fid *fid;
8497 	int err;
8498 
8499 	mlxsw_sp_rif_subport_params_init(&params, mlxsw_sp_port_vlan);
8500 	rif = mlxsw_sp_rif_subport_get(mlxsw_sp, &params, extack);
8501 	if (IS_ERR(rif))
8502 		return PTR_ERR(rif);
8503 
8504 	/* FID was already created, just take a reference */
8505 	fid = rif->ops->fid_get(rif, extack);
8506 	err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid);
8507 	if (err)
8508 		goto err_fid_port_vid_map;
8509 
8510 	err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
8511 	if (err)
8512 		goto err_port_vid_learning_set;
8513 
8514 	err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid,
8515 					BR_STATE_FORWARDING);
8516 	if (err)
8517 		goto err_port_vid_stp_set;
8518 
8519 	mlxsw_sp_port_vlan->fid = fid;
8520 
8521 	return 0;
8522 
8523 err_port_vid_stp_set:
8524 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
8525 err_port_vid_learning_set:
8526 	mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
8527 err_fid_port_vid_map:
8528 	mlxsw_sp_fid_put(fid);
8529 	mlxsw_sp_rif_subport_put(rif);
8530 	return err;
8531 }
8532 
8533 static void
8534 __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
8535 {
8536 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
8537 	struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
8538 	struct mlxsw_sp_rif *rif = mlxsw_sp_fid_rif(fid);
8539 	u16 vid = mlxsw_sp_port_vlan->vid;
8540 
8541 	if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID))
8542 		return;
8543 
8544 	mlxsw_sp_port_vlan->fid = NULL;
8545 	mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING);
8546 	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
8547 	mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
8548 	mlxsw_sp_fid_put(fid);
8549 	mlxsw_sp_rif_subport_put(rif);
8550 }
8551 
8552 int
8553 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
8554 			       struct net_device *l3_dev,
8555 			       struct netlink_ext_ack *extack)
8556 {
8557 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
8558 	struct mlxsw_sp_rif *rif;
8559 	int err = 0;
8560 
8561 	mutex_lock(&mlxsw_sp->router->lock);
8562 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
8563 	if (!rif)
8564 		goto out;
8565 
8566 	err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
8567 					       extack);
8568 out:
8569 	mutex_unlock(&mlxsw_sp->router->lock);
8570 	return err;
8571 }
8572 
8573 void
8574 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
8575 {
8576 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
8577 
8578 	mutex_lock(&mlxsw_sp->router->lock);
8579 	__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
8580 	mutex_unlock(&mlxsw_sp->router->lock);
8581 }
8582 
8583 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
8584 					     struct net_device *port_dev,
8585 					     unsigned long event, u16 vid,
8586 					     struct netlink_ext_ack *extack)
8587 {
8588 	struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
8589 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
8590 
8591 	mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
8592 	if (WARN_ON(!mlxsw_sp_port_vlan))
8593 		return -EINVAL;
8594 
8595 	switch (event) {
8596 	case NETDEV_UP:
8597 		return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
8598 							l3_dev, extack);
8599 	case NETDEV_DOWN:
8600 		__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
8601 		break;
8602 	}
8603 
8604 	return 0;
8605 }
8606 
8607 static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
8608 					unsigned long event,
8609 					struct netlink_ext_ack *extack)
8610 {
8611 	if (netif_is_any_bridge_port(port_dev) || netif_is_lag_port(port_dev))
8612 		return 0;
8613 
8614 	return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event,
8615 						 MLXSW_SP_DEFAULT_VID, extack);
8616 }
8617 
8618 static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
8619 					 struct net_device *lag_dev,
8620 					 unsigned long event, u16 vid,
8621 					 struct netlink_ext_ack *extack)
8622 {
8623 	struct net_device *port_dev;
8624 	struct list_head *iter;
8625 	int err;
8626 
8627 	netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
8628 		if (mlxsw_sp_port_dev_check(port_dev)) {
8629 			err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
8630 								port_dev,
8631 								event, vid,
8632 								extack);
8633 			if (err)
8634 				return err;
8635 		}
8636 	}
8637 
8638 	return 0;
8639 }
8640 
8641 static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
8642 				       unsigned long event,
8643 				       struct netlink_ext_ack *extack)
8644 {
8645 	if (netif_is_bridge_port(lag_dev))
8646 		return 0;
8647 
8648 	return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event,
8649 					     MLXSW_SP_DEFAULT_VID, extack);
8650 }
8651 
8652 static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp,
8653 					  struct net_device *l3_dev,
8654 					  unsigned long event,
8655 					  struct netlink_ext_ack *extack)
8656 {
8657 	struct mlxsw_sp_rif_params params = {
8658 		.dev = l3_dev,
8659 	};
8660 	struct mlxsw_sp_rif *rif;
8661 
8662 	switch (event) {
8663 	case NETDEV_UP:
8664 		if (netif_is_bridge_master(l3_dev) && br_vlan_enabled(l3_dev)) {
8665 			u16 proto;
8666 
8667 			br_vlan_get_proto(l3_dev, &proto);
8668 			if (proto == ETH_P_8021AD) {
8669 				NL_SET_ERR_MSG_MOD(extack, "Adding an IP address to 802.1ad bridge is not supported");
8670 				return -EOPNOTSUPP;
8671 			}
8672 		}
8673 		rif = mlxsw_sp_rif_create(mlxsw_sp, &params, extack);
8674 		if (IS_ERR(rif))
8675 			return PTR_ERR(rif);
8676 		break;
8677 	case NETDEV_DOWN:
8678 		rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
8679 		mlxsw_sp_rif_destroy(rif);
8680 		break;
8681 	}
8682 
8683 	return 0;
8684 }
8685 
8686 static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp,
8687 					struct net_device *vlan_dev,
8688 					unsigned long event,
8689 					struct netlink_ext_ack *extack)
8690 {
8691 	struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
8692 	u16 vid = vlan_dev_vlan_id(vlan_dev);
8693 
8694 	if (netif_is_bridge_port(vlan_dev))
8695 		return 0;
8696 
8697 	if (mlxsw_sp_port_dev_check(real_dev))
8698 		return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
8699 							 event, vid, extack);
8700 	else if (netif_is_lag_master(real_dev))
8701 		return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
8702 						     vid, extack);
8703 	else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev))
8704 		return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, vlan_dev, event,
8705 						      extack);
8706 
8707 	return 0;
8708 }
8709 
8710 static bool mlxsw_sp_rif_macvlan_is_vrrp4(const u8 *mac)
8711 {
8712 	u8 vrrp4[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x01, 0x00 };
8713 	u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
8714 
8715 	return ether_addr_equal_masked(mac, vrrp4, mask);
8716 }
8717 
8718 static bool mlxsw_sp_rif_macvlan_is_vrrp6(const u8 *mac)
8719 {
8720 	u8 vrrp6[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x02, 0x00 };
8721 	u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
8722 
8723 	return ether_addr_equal_masked(mac, vrrp6, mask);
8724 }
8725 
8726 static int mlxsw_sp_rif_vrrp_op(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
8727 				const u8 *mac, bool adding)
8728 {
8729 	char ritr_pl[MLXSW_REG_RITR_LEN];
8730 	u8 vrrp_id = adding ? mac[5] : 0;
8731 	int err;
8732 
8733 	if (!mlxsw_sp_rif_macvlan_is_vrrp4(mac) &&
8734 	    !mlxsw_sp_rif_macvlan_is_vrrp6(mac))
8735 		return 0;
8736 
8737 	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
8738 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
8739 	if (err)
8740 		return err;
8741 
8742 	if (mlxsw_sp_rif_macvlan_is_vrrp4(mac))
8743 		mlxsw_reg_ritr_if_vrrp_id_ipv4_set(ritr_pl, vrrp_id);
8744 	else
8745 		mlxsw_reg_ritr_if_vrrp_id_ipv6_set(ritr_pl, vrrp_id);
8746 
8747 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
8748 }
8749 
8750 static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp,
8751 				    const struct net_device *macvlan_dev,
8752 				    struct netlink_ext_ack *extack)
8753 {
8754 	struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
8755 	struct mlxsw_sp_rif *rif;
8756 	int err;
8757 
8758 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev);
8759 	if (!rif) {
8760 		NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
8761 		return -EOPNOTSUPP;
8762 	}
8763 
8764 	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
8765 				  mlxsw_sp_fid_index(rif->fid), true);
8766 	if (err)
8767 		return err;
8768 
8769 	err = mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index,
8770 				   macvlan_dev->dev_addr, true);
8771 	if (err)
8772 		goto err_rif_vrrp_add;
8773 
8774 	/* Make sure the bridge driver does not have this MAC pointing at
8775 	 * some other port.
8776 	 */
8777 	if (rif->ops->fdb_del)
8778 		rif->ops->fdb_del(rif, macvlan_dev->dev_addr);
8779 
8780 	return 0;
8781 
8782 err_rif_vrrp_add:
8783 	mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
8784 			    mlxsw_sp_fid_index(rif->fid), false);
8785 	return err;
8786 }
8787 
8788 static void __mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
8789 				       const struct net_device *macvlan_dev)
8790 {
8791 	struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
8792 	struct mlxsw_sp_rif *rif;
8793 
8794 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev);
8795 	/* If we do not have a RIF, then we already took care of
8796 	 * removing the macvlan's MAC during RIF deletion.
8797 	 */
8798 	if (!rif)
8799 		return;
8800 	mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index, macvlan_dev->dev_addr,
8801 			     false);
8802 	mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
8803 			    mlxsw_sp_fid_index(rif->fid), false);
8804 }
8805 
8806 void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
8807 			      const struct net_device *macvlan_dev)
8808 {
8809 	mutex_lock(&mlxsw_sp->router->lock);
8810 	__mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
8811 	mutex_unlock(&mlxsw_sp->router->lock);
8812 }
8813 
8814 static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp,
8815 					   struct net_device *macvlan_dev,
8816 					   unsigned long event,
8817 					   struct netlink_ext_ack *extack)
8818 {
8819 	switch (event) {
8820 	case NETDEV_UP:
8821 		return mlxsw_sp_rif_macvlan_add(mlxsw_sp, macvlan_dev, extack);
8822 	case NETDEV_DOWN:
8823 		__mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
8824 		break;
8825 	}
8826 
8827 	return 0;
8828 }
8829 
8830 static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp,
8831 				     struct net_device *dev,
8832 				     unsigned long event,
8833 				     struct netlink_ext_ack *extack)
8834 {
8835 	if (mlxsw_sp_port_dev_check(dev))
8836 		return mlxsw_sp_inetaddr_port_event(dev, event, extack);
8837 	else if (netif_is_lag_master(dev))
8838 		return mlxsw_sp_inetaddr_lag_event(dev, event, extack);
8839 	else if (netif_is_bridge_master(dev))
8840 		return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, dev, event,
8841 						      extack);
8842 	else if (is_vlan_dev(dev))
8843 		return mlxsw_sp_inetaddr_vlan_event(mlxsw_sp, dev, event,
8844 						    extack);
8845 	else if (netif_is_macvlan(dev))
8846 		return mlxsw_sp_inetaddr_macvlan_event(mlxsw_sp, dev, event,
8847 						       extack);
8848 	else
8849 		return 0;
8850 }
8851 
8852 static int mlxsw_sp_inetaddr_event(struct notifier_block *nb,
8853 				   unsigned long event, void *ptr)
8854 {
8855 	struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
8856 	struct net_device *dev = ifa->ifa_dev->dev;
8857 	struct mlxsw_sp_router *router;
8858 	struct mlxsw_sp_rif *rif;
8859 	int err = 0;
8860 
8861 	/* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
8862 	if (event == NETDEV_UP)
8863 		return NOTIFY_DONE;
8864 
8865 	router = container_of(nb, struct mlxsw_sp_router, inetaddr_nb);
8866 	mutex_lock(&router->lock);
8867 	rif = mlxsw_sp_rif_find_by_dev(router->mlxsw_sp, dev);
8868 	if (!mlxsw_sp_rif_should_config(rif, dev, event))
8869 		goto out;
8870 
8871 	err = __mlxsw_sp_inetaddr_event(router->mlxsw_sp, dev, event, NULL);
8872 out:
8873 	mutex_unlock(&router->lock);
8874 	return notifier_from_errno(err);
8875 }
8876 
8877 int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
8878 				  unsigned long event, void *ptr)
8879 {
8880 	struct in_validator_info *ivi = (struct in_validator_info *) ptr;
8881 	struct net_device *dev = ivi->ivi_dev->dev;
8882 	struct mlxsw_sp *mlxsw_sp;
8883 	struct mlxsw_sp_rif *rif;
8884 	int err = 0;
8885 
8886 	mlxsw_sp = mlxsw_sp_lower_get(dev);
8887 	if (!mlxsw_sp)
8888 		return NOTIFY_DONE;
8889 
8890 	mutex_lock(&mlxsw_sp->router->lock);
8891 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
8892 	if (!mlxsw_sp_rif_should_config(rif, dev, event))
8893 		goto out;
8894 
8895 	err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, ivi->extack);
8896 out:
8897 	mutex_unlock(&mlxsw_sp->router->lock);
8898 	return notifier_from_errno(err);
8899 }
8900 
8901 struct mlxsw_sp_inet6addr_event_work {
8902 	struct work_struct work;
8903 	struct mlxsw_sp *mlxsw_sp;
8904 	struct net_device *dev;
8905 	unsigned long event;
8906 };
8907 
8908 static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
8909 {
8910 	struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
8911 		container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
8912 	struct mlxsw_sp *mlxsw_sp = inet6addr_work->mlxsw_sp;
8913 	struct net_device *dev = inet6addr_work->dev;
8914 	unsigned long event = inet6addr_work->event;
8915 	struct mlxsw_sp_rif *rif;
8916 
8917 	rtnl_lock();
8918 	mutex_lock(&mlxsw_sp->router->lock);
8919 
8920 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
8921 	if (!mlxsw_sp_rif_should_config(rif, dev, event))
8922 		goto out;
8923 
8924 	__mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, NULL);
8925 out:
8926 	mutex_unlock(&mlxsw_sp->router->lock);
8927 	rtnl_unlock();
8928 	dev_put(dev);
8929 	kfree(inet6addr_work);
8930 }
8931 
8932 /* Called with rcu_read_lock() */
8933 static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
8934 				    unsigned long event, void *ptr)
8935 {
8936 	struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
8937 	struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
8938 	struct net_device *dev = if6->idev->dev;
8939 	struct mlxsw_sp_router *router;
8940 
8941 	/* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
8942 	if (event == NETDEV_UP)
8943 		return NOTIFY_DONE;
8944 
8945 	inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
8946 	if (!inet6addr_work)
8947 		return NOTIFY_BAD;
8948 
8949 	router = container_of(nb, struct mlxsw_sp_router, inet6addr_nb);
8950 	INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
8951 	inet6addr_work->mlxsw_sp = router->mlxsw_sp;
8952 	inet6addr_work->dev = dev;
8953 	inet6addr_work->event = event;
8954 	dev_hold(dev);
8955 	mlxsw_core_schedule_work(&inet6addr_work->work);
8956 
8957 	return NOTIFY_DONE;
8958 }
8959 
8960 int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
8961 				   unsigned long event, void *ptr)
8962 {
8963 	struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
8964 	struct net_device *dev = i6vi->i6vi_dev->dev;
8965 	struct mlxsw_sp *mlxsw_sp;
8966 	struct mlxsw_sp_rif *rif;
8967 	int err = 0;
8968 
8969 	mlxsw_sp = mlxsw_sp_lower_get(dev);
8970 	if (!mlxsw_sp)
8971 		return NOTIFY_DONE;
8972 
8973 	mutex_lock(&mlxsw_sp->router->lock);
8974 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
8975 	if (!mlxsw_sp_rif_should_config(rif, dev, event))
8976 		goto out;
8977 
8978 	err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, i6vi->extack);
8979 out:
8980 	mutex_unlock(&mlxsw_sp->router->lock);
8981 	return notifier_from_errno(err);
8982 }
8983 
8984 static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
8985 			     const char *mac, int mtu, u8 mac_profile)
8986 {
8987 	char ritr_pl[MLXSW_REG_RITR_LEN];
8988 	int err;
8989 
8990 	mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
8991 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
8992 	if (err)
8993 		return err;
8994 
8995 	mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
8996 	mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
8997 	mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, mac_profile);
8998 	mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
8999 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
9000 }
9001 
9002 static int
9003 mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp,
9004 				  struct mlxsw_sp_rif *rif,
9005 				  struct netlink_ext_ack *extack)
9006 {
9007 	struct net_device *dev = rif->dev;
9008 	u8 old_mac_profile;
9009 	u16 fid_index;
9010 	int err;
9011 
9012 	fid_index = mlxsw_sp_fid_index(rif->fid);
9013 
9014 	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false);
9015 	if (err)
9016 		return err;
9017 
9018 	old_mac_profile = rif->mac_profile_id;
9019 	err = mlxsw_sp_rif_mac_profile_replace(mlxsw_sp, rif, dev->dev_addr,
9020 					       extack);
9021 	if (err)
9022 		goto err_rif_mac_profile_replace;
9023 
9024 	err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
9025 				dev->mtu, rif->mac_profile_id);
9026 	if (err)
9027 		goto err_rif_edit;
9028 
9029 	err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true);
9030 	if (err)
9031 		goto err_rif_fdb_op;
9032 
9033 	if (rif->mtu != dev->mtu) {
9034 		struct mlxsw_sp_vr *vr;
9035 		int i;
9036 
9037 		/* The RIF is relevant only to its mr_table instance, as unlike
9038 		 * unicast routing, in multicast routing a RIF cannot be shared
9039 		 * between several multicast routing tables.
9040 		 */
9041 		vr = &mlxsw_sp->router->vrs[rif->vr_id];
9042 		for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
9043 			mlxsw_sp_mr_rif_mtu_update(vr->mr_table[i],
9044 						   rif, dev->mtu);
9045 	}
9046 
9047 	ether_addr_copy(rif->addr, dev->dev_addr);
9048 	rif->mtu = dev->mtu;
9049 
9050 	netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
9051 
9052 	return 0;
9053 
9054 err_rif_fdb_op:
9055 	mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu,
9056 			  old_mac_profile);
9057 err_rif_edit:
9058 	mlxsw_sp_rif_mac_profile_replace(mlxsw_sp, rif, rif->addr, extack);
9059 err_rif_mac_profile_replace:
9060 	mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true);
9061 	return err;
9062 }
9063 
9064 static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
9065 			    struct netdev_notifier_pre_changeaddr_info *info)
9066 {
9067 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9068 	struct mlxsw_sp_rif_mac_profile *profile;
9069 	struct netlink_ext_ack *extack;
9070 	u8 max_rif_mac_profiles;
9071 	u64 occ;
9072 
9073 	extack = netdev_notifier_info_to_extack(&info->info);
9074 
9075 	profile = mlxsw_sp_rif_mac_profile_find(mlxsw_sp, info->dev_addr);
9076 	if (profile)
9077 		return 0;
9078 
9079 	max_rif_mac_profiles = mlxsw_sp->router->max_rif_mac_profile;
9080 	occ = mlxsw_sp_rif_mac_profiles_occ_get(mlxsw_sp);
9081 	if (occ < max_rif_mac_profiles)
9082 		return 0;
9083 
9084 	if (!mlxsw_sp_rif_mac_profile_is_shared(rif))
9085 		return 0;
9086 
9087 	NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interface MAC profiles");
9088 	return -ENOBUFS;
9089 }
9090 
9091 static bool mlxsw_sp_is_offload_xstats_event(unsigned long event)
9092 {
9093 	switch (event) {
9094 	case NETDEV_OFFLOAD_XSTATS_ENABLE:
9095 	case NETDEV_OFFLOAD_XSTATS_DISABLE:
9096 	case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
9097 	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
9098 		return true;
9099 	}
9100 
9101 	return false;
9102 }
9103 
9104 static int
9105 mlxsw_sp_router_port_offload_xstats_cmd(struct mlxsw_sp_rif *rif,
9106 					unsigned long event,
9107 					struct netdev_notifier_offload_xstats_info *info)
9108 {
9109 	switch (info->type) {
9110 	case NETDEV_OFFLOAD_XSTATS_TYPE_L3:
9111 		break;
9112 	default:
9113 		return 0;
9114 	}
9115 
9116 	switch (event) {
9117 	case NETDEV_OFFLOAD_XSTATS_ENABLE:
9118 		return mlxsw_sp_router_port_l3_stats_enable(rif);
9119 	case NETDEV_OFFLOAD_XSTATS_DISABLE:
9120 		mlxsw_sp_router_port_l3_stats_disable(rif);
9121 		return 0;
9122 	case NETDEV_OFFLOAD_XSTATS_REPORT_USED:
9123 		mlxsw_sp_router_port_l3_stats_report_used(rif, info);
9124 		return 0;
9125 	case NETDEV_OFFLOAD_XSTATS_REPORT_DELTA:
9126 		return mlxsw_sp_router_port_l3_stats_report_delta(rif, info);
9127 	}
9128 
9129 	WARN_ON_ONCE(1);
9130 	return 0;
9131 }
9132 
9133 static int
9134 mlxsw_sp_netdevice_offload_xstats_cmd(struct mlxsw_sp *mlxsw_sp,
9135 				      struct net_device *dev,
9136 				      unsigned long event,
9137 				      struct netdev_notifier_offload_xstats_info *info)
9138 {
9139 	struct mlxsw_sp_rif *rif;
9140 
9141 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
9142 	if (!rif)
9143 		return 0;
9144 
9145 	return mlxsw_sp_router_port_offload_xstats_cmd(rif, event, info);
9146 }
9147 
9148 static bool mlxsw_sp_is_router_event(unsigned long event)
9149 {
9150 	switch (event) {
9151 	case NETDEV_PRE_CHANGEADDR:
9152 	case NETDEV_CHANGEADDR:
9153 	case NETDEV_CHANGEMTU:
9154 		return true;
9155 	default:
9156 		return false;
9157 	}
9158 }
9159 
9160 static int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
9161 						unsigned long event, void *ptr)
9162 {
9163 	struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr);
9164 	struct mlxsw_sp *mlxsw_sp;
9165 	struct mlxsw_sp_rif *rif;
9166 
9167 	mlxsw_sp = mlxsw_sp_lower_get(dev);
9168 	if (!mlxsw_sp)
9169 		return 0;
9170 
9171 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
9172 	if (!rif)
9173 		return 0;
9174 
9175 	switch (event) {
9176 	case NETDEV_CHANGEMTU:
9177 	case NETDEV_CHANGEADDR:
9178 		return mlxsw_sp_router_port_change_event(mlxsw_sp, rif, extack);
9179 	case NETDEV_PRE_CHANGEADDR:
9180 		return mlxsw_sp_router_port_pre_changeaddr_event(rif, ptr);
9181 	default:
9182 		WARN_ON_ONCE(1);
9183 		break;
9184 	}
9185 
9186 	return 0;
9187 }
9188 
9189 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
9190 				  struct net_device *l3_dev,
9191 				  struct netlink_ext_ack *extack)
9192 {
9193 	struct mlxsw_sp_rif *rif;
9194 
9195 	/* If netdev is already associated with a RIF, then we need to
9196 	 * destroy it and create a new one with the new virtual router ID.
9197 	 */
9198 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
9199 	if (rif)
9200 		__mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN,
9201 					  extack);
9202 
9203 	return __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_UP, extack);
9204 }
9205 
9206 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
9207 				    struct net_device *l3_dev)
9208 {
9209 	struct mlxsw_sp_rif *rif;
9210 
9211 	rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
9212 	if (!rif)
9213 		return;
9214 	__mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, NULL);
9215 }
9216 
9217 static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
9218 {
9219 	struct netdev_notifier_changeupper_info *info = ptr;
9220 
9221 	if (event != NETDEV_PRECHANGEUPPER && event != NETDEV_CHANGEUPPER)
9222 		return false;
9223 	return netif_is_l3_master(info->upper_dev);
9224 }
9225 
9226 static int
9227 mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
9228 			     struct netdev_notifier_changeupper_info *info)
9229 {
9230 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
9231 	int err = 0;
9232 
9233 	/* We do not create a RIF for a macvlan, but only use it to
9234 	 * direct more MAC addresses to the router.
9235 	 */
9236 	if (!mlxsw_sp || netif_is_macvlan(l3_dev))
9237 		return 0;
9238 
9239 	switch (event) {
9240 	case NETDEV_PRECHANGEUPPER:
9241 		break;
9242 	case NETDEV_CHANGEUPPER:
9243 		if (info->linking) {
9244 			struct netlink_ext_ack *extack;
9245 
9246 			extack = netdev_notifier_info_to_extack(&info->info);
9247 			err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev, extack);
9248 		} else {
9249 			mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
9250 		}
9251 		break;
9252 	}
9253 
9254 	return err;
9255 }
9256 
9257 static int mlxsw_sp_router_netdevice_event(struct notifier_block *nb,
9258 					   unsigned long event, void *ptr)
9259 {
9260 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
9261 	struct mlxsw_sp_router *router;
9262 	struct mlxsw_sp *mlxsw_sp;
9263 	int err = 0;
9264 
9265 	router = container_of(nb, struct mlxsw_sp_router, netdevice_nb);
9266 	mlxsw_sp = router->mlxsw_sp;
9267 
9268 	mutex_lock(&mlxsw_sp->router->lock);
9269 
9270 	if (mlxsw_sp_is_offload_xstats_event(event))
9271 		err = mlxsw_sp_netdevice_offload_xstats_cmd(mlxsw_sp, dev,
9272 							    event, ptr);
9273 	else if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
9274 		err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
9275 						       event, ptr);
9276 	else if (mlxsw_sp_netdev_is_ipip_ul(mlxsw_sp, dev))
9277 		err = mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, dev,
9278 						       event, ptr);
9279 	else if (mlxsw_sp_is_router_event(event))
9280 		err = mlxsw_sp_netdevice_router_port_event(dev, event, ptr);
9281 	else if (mlxsw_sp_is_vrf_event(event, ptr))
9282 		err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);
9283 
9284 	mutex_unlock(&mlxsw_sp->router->lock);
9285 
9286 	return notifier_from_errno(err);
9287 }
9288 
9289 static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev,
9290 					struct netdev_nested_priv *priv)
9291 {
9292 	struct mlxsw_sp_rif *rif = (struct mlxsw_sp_rif *)priv->data;
9293 
9294 	if (!netif_is_macvlan(dev))
9295 		return 0;
9296 
9297 	return mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
9298 				   mlxsw_sp_fid_index(rif->fid), false);
9299 }
9300 
9301 static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif)
9302 {
9303 	struct netdev_nested_priv priv = {
9304 		.data = (void *)rif,
9305 	};
9306 
9307 	if (!netif_is_macvlan_port(rif->dev))
9308 		return 0;
9309 
9310 	netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n");
9311 	return netdev_walk_all_upper_dev_rcu(rif->dev,
9312 					     __mlxsw_sp_rif_macvlan_flush, &priv);
9313 }
9314 
9315 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
9316 				       const struct mlxsw_sp_rif_params *params)
9317 {
9318 	struct mlxsw_sp_rif_subport *rif_subport;
9319 
9320 	rif_subport = mlxsw_sp_rif_subport_rif(rif);
9321 	refcount_set(&rif_subport->ref_count, 1);
9322 	rif_subport->vid = params->vid;
9323 	rif_subport->lag = params->lag;
9324 	if (params->lag)
9325 		rif_subport->lag_id = params->lag_id;
9326 	else
9327 		rif_subport->system_port = params->system_port;
9328 }
9329 
9330 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
9331 {
9332 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9333 	struct mlxsw_sp_rif_subport *rif_subport;
9334 	char ritr_pl[MLXSW_REG_RITR_LEN];
9335 	u16 efid;
9336 
9337 	rif_subport = mlxsw_sp_rif_subport_rif(rif);
9338 	mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
9339 			    rif->rif_index, rif->vr_id, rif->dev->mtu);
9340 	mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
9341 	mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
9342 	efid = mlxsw_sp_fid_index(rif->fid);
9343 	mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
9344 				  rif_subport->lag ? rif_subport->lag_id :
9345 						     rif_subport->system_port,
9346 				  efid, 0);
9347 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
9348 }
9349 
9350 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif,
9351 					  struct netlink_ext_ack *extack)
9352 {
9353 	u8 mac_profile;
9354 	int err;
9355 
9356 	err = mlxsw_sp_rif_mac_profile_get(rif->mlxsw_sp, rif->addr,
9357 					   &mac_profile, extack);
9358 	if (err)
9359 		return err;
9360 	rif->mac_profile_id = mac_profile;
9361 
9362 	err = mlxsw_sp_rif_subport_op(rif, true);
9363 	if (err)
9364 		goto err_rif_subport_op;
9365 
9366 	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9367 				  mlxsw_sp_fid_index(rif->fid), true);
9368 	if (err)
9369 		goto err_rif_fdb_op;
9370 
9371 	err = mlxsw_sp_fid_rif_set(rif->fid, rif);
9372 	if (err)
9373 		goto err_fid_rif_set;
9374 
9375 	return 0;
9376 
9377 err_fid_rif_set:
9378 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9379 			    mlxsw_sp_fid_index(rif->fid), false);
9380 err_rif_fdb_op:
9381 	mlxsw_sp_rif_subport_op(rif, false);
9382 err_rif_subport_op:
9383 	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, mac_profile);
9384 	return err;
9385 }
9386 
9387 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
9388 {
9389 	struct mlxsw_sp_fid *fid = rif->fid;
9390 
9391 	mlxsw_sp_fid_rif_unset(fid);
9392 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9393 			    mlxsw_sp_fid_index(fid), false);
9394 	mlxsw_sp_rif_macvlan_flush(rif);
9395 	mlxsw_sp_rif_subport_op(rif, false);
9396 	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id);
9397 }
9398 
9399 static struct mlxsw_sp_fid *
9400 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif,
9401 			     struct netlink_ext_ack *extack)
9402 {
9403 	return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index);
9404 }
9405 
9406 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
9407 	.type			= MLXSW_SP_RIF_TYPE_SUBPORT,
9408 	.rif_size		= sizeof(struct mlxsw_sp_rif_subport),
9409 	.setup			= mlxsw_sp_rif_subport_setup,
9410 	.configure		= mlxsw_sp_rif_subport_configure,
9411 	.deconfigure		= mlxsw_sp_rif_subport_deconfigure,
9412 	.fid_get		= mlxsw_sp_rif_subport_fid_get,
9413 };
9414 
9415 static int mlxsw_sp_rif_fid_op(struct mlxsw_sp_rif *rif, u16 fid, bool enable)
9416 {
9417 	enum mlxsw_reg_ritr_if_type type = MLXSW_REG_RITR_FID_IF;
9418 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9419 	char ritr_pl[MLXSW_REG_RITR_LEN];
9420 
9421 	mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
9422 			    rif->dev->mtu);
9423 	mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
9424 	mlxsw_reg_ritr_if_mac_profile_id_set(ritr_pl, rif->mac_profile_id);
9425 	mlxsw_reg_ritr_fid_if_fid_set(ritr_pl, fid);
9426 
9427 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
9428 }
9429 
9430 u16 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
9431 {
9432 	return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
9433 }
9434 
9435 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif,
9436 				      struct netlink_ext_ack *extack)
9437 {
9438 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9439 	u16 fid_index = mlxsw_sp_fid_index(rif->fid);
9440 	u8 mac_profile;
9441 	int err;
9442 
9443 	err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, rif->addr,
9444 					   &mac_profile, extack);
9445 	if (err)
9446 		return err;
9447 	rif->mac_profile_id = mac_profile;
9448 
9449 	err = mlxsw_sp_rif_fid_op(rif, fid_index, true);
9450 	if (err)
9451 		goto err_rif_fid_op;
9452 
9453 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
9454 				     mlxsw_sp_router_port(mlxsw_sp), true);
9455 	if (err)
9456 		goto err_fid_mc_flood_set;
9457 
9458 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
9459 				     mlxsw_sp_router_port(mlxsw_sp), true);
9460 	if (err)
9461 		goto err_fid_bc_flood_set;
9462 
9463 	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9464 				  mlxsw_sp_fid_index(rif->fid), true);
9465 	if (err)
9466 		goto err_rif_fdb_op;
9467 
9468 	err = mlxsw_sp_fid_rif_set(rif->fid, rif);
9469 	if (err)
9470 		goto err_fid_rif_set;
9471 
9472 	return 0;
9473 
9474 err_fid_rif_set:
9475 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9476 			    mlxsw_sp_fid_index(rif->fid), false);
9477 err_rif_fdb_op:
9478 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
9479 			       mlxsw_sp_router_port(mlxsw_sp), false);
9480 err_fid_bc_flood_set:
9481 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
9482 			       mlxsw_sp_router_port(mlxsw_sp), false);
9483 err_fid_mc_flood_set:
9484 	mlxsw_sp_rif_fid_op(rif, fid_index, false);
9485 err_rif_fid_op:
9486 	mlxsw_sp_rif_mac_profile_put(mlxsw_sp, mac_profile);
9487 	return err;
9488 }
9489 
9490 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
9491 {
9492 	u16 fid_index = mlxsw_sp_fid_index(rif->fid);
9493 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9494 	struct mlxsw_sp_fid *fid = rif->fid;
9495 
9496 	mlxsw_sp_fid_rif_unset(fid);
9497 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9498 			    mlxsw_sp_fid_index(fid), false);
9499 	mlxsw_sp_rif_macvlan_flush(rif);
9500 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
9501 			       mlxsw_sp_router_port(mlxsw_sp), false);
9502 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
9503 			       mlxsw_sp_router_port(mlxsw_sp), false);
9504 	mlxsw_sp_rif_fid_op(rif, fid_index, false);
9505 	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id);
9506 }
9507 
9508 static struct mlxsw_sp_fid *
9509 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
9510 			 struct netlink_ext_ack *extack)
9511 {
9512 	return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
9513 }
9514 
9515 static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
9516 {
9517 	struct switchdev_notifier_fdb_info info = {};
9518 	struct net_device *dev;
9519 
9520 	dev = br_fdb_find_port(rif->dev, mac, 0);
9521 	if (!dev)
9522 		return;
9523 
9524 	info.addr = mac;
9525 	info.vid = 0;
9526 	call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
9527 				 NULL);
9528 }
9529 
9530 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
9531 	.type			= MLXSW_SP_RIF_TYPE_FID,
9532 	.rif_size		= sizeof(struct mlxsw_sp_rif),
9533 	.configure		= mlxsw_sp_rif_fid_configure,
9534 	.deconfigure		= mlxsw_sp_rif_fid_deconfigure,
9535 	.fid_get		= mlxsw_sp_rif_fid_fid_get,
9536 	.fdb_del		= mlxsw_sp_rif_fid_fdb_del,
9537 };
9538 
9539 static struct mlxsw_sp_fid *
9540 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
9541 			  struct netlink_ext_ack *extack)
9542 {
9543 	struct net_device *br_dev;
9544 	u16 vid;
9545 	int err;
9546 
9547 	if (is_vlan_dev(rif->dev)) {
9548 		vid = vlan_dev_vlan_id(rif->dev);
9549 		br_dev = vlan_dev_real_dev(rif->dev);
9550 		if (WARN_ON(!netif_is_bridge_master(br_dev)))
9551 			return ERR_PTR(-EINVAL);
9552 	} else {
9553 		err = br_vlan_get_pvid(rif->dev, &vid);
9554 		if (err < 0 || !vid) {
9555 			NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID");
9556 			return ERR_PTR(-EINVAL);
9557 		}
9558 	}
9559 
9560 	return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid);
9561 }
9562 
9563 static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
9564 {
9565 	struct switchdev_notifier_fdb_info info = {};
9566 	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
9567 	struct net_device *br_dev;
9568 	struct net_device *dev;
9569 
9570 	br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev;
9571 	dev = br_fdb_find_port(br_dev, mac, vid);
9572 	if (!dev)
9573 		return;
9574 
9575 	info.addr = mac;
9576 	info.vid = vid;
9577 	call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
9578 				 NULL);
9579 }
9580 
9581 static int mlxsw_sp_rif_vlan_op(struct mlxsw_sp_rif *rif, u16 vid, u16 efid,
9582 				bool enable)
9583 {
9584 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9585 	char ritr_pl[MLXSW_REG_RITR_LEN];
9586 
9587 	mlxsw_reg_ritr_vlan_if_pack(ritr_pl, enable, rif->rif_index, rif->vr_id,
9588 				    rif->dev->mtu, rif->dev->dev_addr,
9589 				    rif->mac_profile_id, vid, efid);
9590 
9591 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
9592 }
9593 
9594 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif, u16 efid,
9595 				       struct netlink_ext_ack *extack)
9596 {
9597 	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
9598 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9599 	u8 mac_profile;
9600 	int err;
9601 
9602 	err = mlxsw_sp_rif_mac_profile_get(mlxsw_sp, rif->addr,
9603 					   &mac_profile, extack);
9604 	if (err)
9605 		return err;
9606 	rif->mac_profile_id = mac_profile;
9607 
9608 	err = mlxsw_sp_rif_vlan_op(rif, vid, efid, true);
9609 	if (err)
9610 		goto err_rif_vlan_fid_op;
9611 
9612 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
9613 				     mlxsw_sp_router_port(mlxsw_sp), true);
9614 	if (err)
9615 		goto err_fid_mc_flood_set;
9616 
9617 	err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
9618 				     mlxsw_sp_router_port(mlxsw_sp), true);
9619 	if (err)
9620 		goto err_fid_bc_flood_set;
9621 
9622 	err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9623 				  mlxsw_sp_fid_index(rif->fid), true);
9624 	if (err)
9625 		goto err_rif_fdb_op;
9626 
9627 	err = mlxsw_sp_fid_rif_set(rif->fid, rif);
9628 	if (err)
9629 		goto err_fid_rif_set;
9630 
9631 	return 0;
9632 
9633 err_fid_rif_set:
9634 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9635 			    mlxsw_sp_fid_index(rif->fid), false);
9636 err_rif_fdb_op:
9637 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
9638 			       mlxsw_sp_router_port(mlxsw_sp), false);
9639 err_fid_bc_flood_set:
9640 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
9641 			       mlxsw_sp_router_port(mlxsw_sp), false);
9642 err_fid_mc_flood_set:
9643 	mlxsw_sp_rif_vlan_op(rif, vid, 0, false);
9644 err_rif_vlan_fid_op:
9645 	mlxsw_sp_rif_mac_profile_put(mlxsw_sp, mac_profile);
9646 	return err;
9647 }
9648 
9649 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif)
9650 {
9651 	u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
9652 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9653 
9654 	mlxsw_sp_fid_rif_unset(rif->fid);
9655 	mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
9656 			    mlxsw_sp_fid_index(rif->fid), false);
9657 	mlxsw_sp_rif_macvlan_flush(rif);
9658 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
9659 			       mlxsw_sp_router_port(mlxsw_sp), false);
9660 	mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
9661 			       mlxsw_sp_router_port(mlxsw_sp), false);
9662 	mlxsw_sp_rif_vlan_op(rif, vid, 0, false);
9663 	mlxsw_sp_rif_mac_profile_put(rif->mlxsw_sp, rif->mac_profile_id);
9664 }
9665 
9666 static int mlxsw_sp1_rif_vlan_configure(struct mlxsw_sp_rif *rif,
9667 					struct netlink_ext_ack *extack)
9668 {
9669 	return mlxsw_sp_rif_vlan_configure(rif, 0, extack);
9670 }
9671 
9672 static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_vlan_ops = {
9673 	.type			= MLXSW_SP_RIF_TYPE_VLAN,
9674 	.rif_size		= sizeof(struct mlxsw_sp_rif),
9675 	.configure		= mlxsw_sp1_rif_vlan_configure,
9676 	.deconfigure		= mlxsw_sp_rif_vlan_deconfigure,
9677 	.fid_get		= mlxsw_sp_rif_vlan_fid_get,
9678 	.fdb_del		= mlxsw_sp_rif_vlan_fdb_del,
9679 };
9680 
9681 static int mlxsw_sp2_rif_vlan_configure(struct mlxsw_sp_rif *rif,
9682 					struct netlink_ext_ack *extack)
9683 {
9684 	u16 efid = mlxsw_sp_fid_index(rif->fid);
9685 
9686 	return mlxsw_sp_rif_vlan_configure(rif, efid, extack);
9687 }
9688 
9689 static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_vlan_ops = {
9690 	.type			= MLXSW_SP_RIF_TYPE_VLAN,
9691 	.rif_size		= sizeof(struct mlxsw_sp_rif),
9692 	.configure		= mlxsw_sp2_rif_vlan_configure,
9693 	.deconfigure		= mlxsw_sp_rif_vlan_deconfigure,
9694 	.fid_get		= mlxsw_sp_rif_vlan_fid_get,
9695 	.fdb_del		= mlxsw_sp_rif_vlan_fdb_del,
9696 };
9697 
9698 static struct mlxsw_sp_rif_ipip_lb *
9699 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
9700 {
9701 	return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
9702 }
9703 
9704 static void
9705 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
9706 			   const struct mlxsw_sp_rif_params *params)
9707 {
9708 	struct mlxsw_sp_rif_params_ipip_lb *params_lb;
9709 	struct mlxsw_sp_rif_ipip_lb *rif_lb;
9710 
9711 	params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
9712 				 common);
9713 	rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
9714 	rif_lb->lb_config = params_lb->lb_config;
9715 }
9716 
9717 static int
9718 mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
9719 				struct netlink_ext_ack *extack)
9720 {
9721 	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
9722 	u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
9723 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9724 	struct mlxsw_sp_vr *ul_vr;
9725 	int err;
9726 
9727 	ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL);
9728 	if (IS_ERR(ul_vr))
9729 		return PTR_ERR(ul_vr);
9730 
9731 	err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true);
9732 	if (err)
9733 		goto err_loopback_op;
9734 
9735 	lb_rif->ul_vr_id = ul_vr->id;
9736 	lb_rif->ul_rif_id = 0;
9737 	++ul_vr->rif_count;
9738 	return 0;
9739 
9740 err_loopback_op:
9741 	mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
9742 	return err;
9743 }
9744 
9745 static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
9746 {
9747 	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
9748 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9749 	struct mlxsw_sp_vr *ul_vr;
9750 
9751 	ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
9752 	mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, false);
9753 
9754 	--ul_vr->rif_count;
9755 	mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
9756 }
9757 
9758 static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_ipip_lb_ops = {
9759 	.type			= MLXSW_SP_RIF_TYPE_IPIP_LB,
9760 	.rif_size		= sizeof(struct mlxsw_sp_rif_ipip_lb),
9761 	.setup                  = mlxsw_sp_rif_ipip_lb_setup,
9762 	.configure		= mlxsw_sp1_rif_ipip_lb_configure,
9763 	.deconfigure		= mlxsw_sp1_rif_ipip_lb_deconfigure,
9764 };
9765 
9766 static const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[] = {
9767 	[MLXSW_SP_RIF_TYPE_SUBPORT]	= &mlxsw_sp_rif_subport_ops,
9768 	[MLXSW_SP_RIF_TYPE_VLAN]	= &mlxsw_sp1_rif_vlan_ops,
9769 	[MLXSW_SP_RIF_TYPE_FID]		= &mlxsw_sp_rif_fid_ops,
9770 	[MLXSW_SP_RIF_TYPE_IPIP_LB]	= &mlxsw_sp1_rif_ipip_lb_ops,
9771 };
9772 
9773 static int
9774 mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
9775 {
9776 	struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
9777 	char ritr_pl[MLXSW_REG_RITR_LEN];
9778 
9779 	mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
9780 			    ul_rif->rif_index, ul_rif->vr_id, IP_MAX_MTU);
9781 	mlxsw_reg_ritr_loopback_protocol_set(ritr_pl,
9782 					     MLXSW_REG_RITR_LOOPBACK_GENERIC);
9783 
9784 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
9785 }
9786 
9787 static struct mlxsw_sp_rif *
9788 mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
9789 		       struct netlink_ext_ack *extack)
9790 {
9791 	struct mlxsw_sp_rif *ul_rif;
9792 	u8 rif_entries = 1;
9793 	u16 rif_index;
9794 	int err;
9795 
9796 	err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index, rif_entries);
9797 	if (err) {
9798 		NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
9799 		return ERR_PTR(err);
9800 	}
9801 
9802 	ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
9803 	if (!ul_rif) {
9804 		err = -ENOMEM;
9805 		goto err_rif_alloc;
9806 	}
9807 
9808 	mlxsw_sp->router->rifs[rif_index] = ul_rif;
9809 	ul_rif->mlxsw_sp = mlxsw_sp;
9810 	ul_rif->rif_entries = rif_entries;
9811 	err = mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, true);
9812 	if (err)
9813 		goto ul_rif_op_err;
9814 
9815 	atomic_add(rif_entries, &mlxsw_sp->router->rifs_count);
9816 	return ul_rif;
9817 
9818 ul_rif_op_err:
9819 	mlxsw_sp->router->rifs[rif_index] = NULL;
9820 	kfree(ul_rif);
9821 err_rif_alloc:
9822 	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
9823 	return ERR_PTR(err);
9824 }
9825 
9826 static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
9827 {
9828 	struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
9829 	u8 rif_entries = ul_rif->rif_entries;
9830 	u16 rif_index = ul_rif->rif_index;
9831 
9832 	atomic_sub(rif_entries, &mlxsw_sp->router->rifs_count);
9833 	mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
9834 	mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
9835 	kfree(ul_rif);
9836 	mlxsw_sp_rif_index_free(mlxsw_sp, rif_index, rif_entries);
9837 }
9838 
9839 static struct mlxsw_sp_rif *
9840 mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
9841 		    struct netlink_ext_ack *extack)
9842 {
9843 	struct mlxsw_sp_vr *vr;
9844 	int err;
9845 
9846 	vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, extack);
9847 	if (IS_ERR(vr))
9848 		return ERR_CAST(vr);
9849 
9850 	if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
9851 		return vr->ul_rif;
9852 
9853 	vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
9854 	if (IS_ERR(vr->ul_rif)) {
9855 		err = PTR_ERR(vr->ul_rif);
9856 		goto err_ul_rif_create;
9857 	}
9858 
9859 	vr->rif_count++;
9860 	refcount_set(&vr->ul_rif_refcnt, 1);
9861 
9862 	return vr->ul_rif;
9863 
9864 err_ul_rif_create:
9865 	mlxsw_sp_vr_put(mlxsw_sp, vr);
9866 	return ERR_PTR(err);
9867 }
9868 
9869 static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif *ul_rif)
9870 {
9871 	struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
9872 	struct mlxsw_sp_vr *vr;
9873 
9874 	vr = &mlxsw_sp->router->vrs[ul_rif->vr_id];
9875 
9876 	if (!refcount_dec_and_test(&vr->ul_rif_refcnt))
9877 		return;
9878 
9879 	vr->rif_count--;
9880 	mlxsw_sp_ul_rif_destroy(ul_rif);
9881 	mlxsw_sp_vr_put(mlxsw_sp, vr);
9882 }
9883 
9884 int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
9885 			       u16 *ul_rif_index)
9886 {
9887 	struct mlxsw_sp_rif *ul_rif;
9888 	int err = 0;
9889 
9890 	mutex_lock(&mlxsw_sp->router->lock);
9891 	ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
9892 	if (IS_ERR(ul_rif)) {
9893 		err = PTR_ERR(ul_rif);
9894 		goto out;
9895 	}
9896 	*ul_rif_index = ul_rif->rif_index;
9897 out:
9898 	mutex_unlock(&mlxsw_sp->router->lock);
9899 	return err;
9900 }
9901 
9902 void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index)
9903 {
9904 	struct mlxsw_sp_rif *ul_rif;
9905 
9906 	mutex_lock(&mlxsw_sp->router->lock);
9907 	ul_rif = mlxsw_sp->router->rifs[ul_rif_index];
9908 	if (WARN_ON(!ul_rif))
9909 		goto out;
9910 
9911 	mlxsw_sp_ul_rif_put(ul_rif);
9912 out:
9913 	mutex_unlock(&mlxsw_sp->router->lock);
9914 }
9915 
9916 static int
9917 mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif,
9918 				struct netlink_ext_ack *extack)
9919 {
9920 	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
9921 	u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
9922 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9923 	struct mlxsw_sp_rif *ul_rif;
9924 	int err;
9925 
9926 	ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
9927 	if (IS_ERR(ul_rif))
9928 		return PTR_ERR(ul_rif);
9929 
9930 	err = mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, ul_rif->rif_index, true);
9931 	if (err)
9932 		goto err_loopback_op;
9933 
9934 	lb_rif->ul_vr_id = 0;
9935 	lb_rif->ul_rif_id = ul_rif->rif_index;
9936 
9937 	return 0;
9938 
9939 err_loopback_op:
9940 	mlxsw_sp_ul_rif_put(ul_rif);
9941 	return err;
9942 }
9943 
9944 static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
9945 {
9946 	struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
9947 	struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
9948 	struct mlxsw_sp_rif *ul_rif;
9949 
9950 	ul_rif = mlxsw_sp_rif_by_index(mlxsw_sp, lb_rif->ul_rif_id);
9951 	mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, lb_rif->ul_rif_id, false);
9952 	mlxsw_sp_ul_rif_put(ul_rif);
9953 }
9954 
9955 static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops = {
9956 	.type			= MLXSW_SP_RIF_TYPE_IPIP_LB,
9957 	.rif_size		= sizeof(struct mlxsw_sp_rif_ipip_lb),
9958 	.setup                  = mlxsw_sp_rif_ipip_lb_setup,
9959 	.configure		= mlxsw_sp2_rif_ipip_lb_configure,
9960 	.deconfigure		= mlxsw_sp2_rif_ipip_lb_deconfigure,
9961 };
9962 
9963 static const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = {
9964 	[MLXSW_SP_RIF_TYPE_SUBPORT]	= &mlxsw_sp_rif_subport_ops,
9965 	[MLXSW_SP_RIF_TYPE_VLAN]	= &mlxsw_sp2_rif_vlan_ops,
9966 	[MLXSW_SP_RIF_TYPE_FID]		= &mlxsw_sp_rif_fid_ops,
9967 	[MLXSW_SP_RIF_TYPE_IPIP_LB]	= &mlxsw_sp2_rif_ipip_lb_ops,
9968 };
9969 
9970 static int mlxsw_sp_rifs_table_init(struct mlxsw_sp *mlxsw_sp)
9971 {
9972 	struct gen_pool *rifs_table;
9973 	int err;
9974 
9975 	rifs_table = gen_pool_create(0, -1);
9976 	if (!rifs_table)
9977 		return -ENOMEM;
9978 
9979 	gen_pool_set_algo(rifs_table, gen_pool_first_fit_order_align,
9980 			  NULL);
9981 
9982 	err = gen_pool_add(rifs_table, MLXSW_SP_ROUTER_GENALLOC_OFFSET,
9983 			   MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS), -1);
9984 	if (err)
9985 		goto err_gen_pool_add;
9986 
9987 	mlxsw_sp->router->rifs_table = rifs_table;
9988 
9989 	return 0;
9990 
9991 err_gen_pool_add:
9992 	gen_pool_destroy(rifs_table);
9993 	return err;
9994 }
9995 
9996 static void mlxsw_sp_rifs_table_fini(struct mlxsw_sp *mlxsw_sp)
9997 {
9998 	gen_pool_destroy(mlxsw_sp->router->rifs_table);
9999 }
10000 
10001 static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
10002 {
10003 	u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
10004 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
10005 	struct mlxsw_core *core = mlxsw_sp->core;
10006 	int err;
10007 
10008 	if (!MLXSW_CORE_RES_VALID(core, MAX_RIF_MAC_PROFILES))
10009 		return -EIO;
10010 	mlxsw_sp->router->max_rif_mac_profile =
10011 		MLXSW_CORE_RES_GET(core, MAX_RIF_MAC_PROFILES);
10012 
10013 	mlxsw_sp->router->rifs = kcalloc(max_rifs,
10014 					 sizeof(struct mlxsw_sp_rif *),
10015 					 GFP_KERNEL);
10016 	if (!mlxsw_sp->router->rifs)
10017 		return -ENOMEM;
10018 
10019 	err = mlxsw_sp_rifs_table_init(mlxsw_sp);
10020 	if (err)
10021 		goto err_rifs_table_init;
10022 
10023 	idr_init(&mlxsw_sp->router->rif_mac_profiles_idr);
10024 	atomic_set(&mlxsw_sp->router->rif_mac_profiles_count, 0);
10025 	atomic_set(&mlxsw_sp->router->rifs_count, 0);
10026 	devl_resource_occ_get_register(devlink,
10027 				       MLXSW_SP_RESOURCE_RIF_MAC_PROFILES,
10028 				       mlxsw_sp_rif_mac_profiles_occ_get,
10029 				       mlxsw_sp);
10030 	devl_resource_occ_get_register(devlink,
10031 				       MLXSW_SP_RESOURCE_RIFS,
10032 				       mlxsw_sp_rifs_occ_get,
10033 				       mlxsw_sp);
10034 
10035 	return 0;
10036 
10037 err_rifs_table_init:
10038 	kfree(mlxsw_sp->router->rifs);
10039 	return err;
10040 }
10041 
10042 static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
10043 {
10044 	struct devlink *devlink = priv_to_devlink(mlxsw_sp->core);
10045 	int i;
10046 
10047 	WARN_ON_ONCE(atomic_read(&mlxsw_sp->router->rifs_count));
10048 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
10049 		WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
10050 
10051 	devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_RIFS);
10052 	devl_resource_occ_get_unregister(devlink,
10053 					 MLXSW_SP_RESOURCE_RIF_MAC_PROFILES);
10054 	WARN_ON(!idr_is_empty(&mlxsw_sp->router->rif_mac_profiles_idr));
10055 	idr_destroy(&mlxsw_sp->router->rif_mac_profiles_idr);
10056 	mlxsw_sp_rifs_table_fini(mlxsw_sp);
10057 	kfree(mlxsw_sp->router->rifs);
10058 }
10059 
10060 static int
10061 mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp *mlxsw_sp)
10062 {
10063 	char tigcr_pl[MLXSW_REG_TIGCR_LEN];
10064 
10065 	mlxsw_reg_tigcr_pack(tigcr_pl, true, 0);
10066 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tigcr), tigcr_pl);
10067 }
10068 
10069 static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
10070 {
10071 	int err;
10072 
10073 	INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);
10074 
10075 	err = mlxsw_sp_ipip_ecn_encap_init(mlxsw_sp);
10076 	if (err)
10077 		return err;
10078 	err = mlxsw_sp_ipip_ecn_decap_init(mlxsw_sp);
10079 	if (err)
10080 		return err;
10081 
10082 	return mlxsw_sp_ipip_config_tigcr(mlxsw_sp);
10083 }
10084 
10085 static int mlxsw_sp1_ipips_init(struct mlxsw_sp *mlxsw_sp)
10086 {
10087 	mlxsw_sp->router->ipip_ops_arr = mlxsw_sp1_ipip_ops_arr;
10088 	return mlxsw_sp_ipips_init(mlxsw_sp);
10089 }
10090 
10091 static int mlxsw_sp2_ipips_init(struct mlxsw_sp *mlxsw_sp)
10092 {
10093 	mlxsw_sp->router->ipip_ops_arr = mlxsw_sp2_ipip_ops_arr;
10094 	return mlxsw_sp_ipips_init(mlxsw_sp);
10095 }
10096 
10097 static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp)
10098 {
10099 	WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list));
10100 }
10101 
10102 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
10103 {
10104 	struct mlxsw_sp_router *router;
10105 
10106 	/* Flush pending FIB notifications and then flush the device's
10107 	 * table before requesting another dump. The FIB notification
10108 	 * block is unregistered, so no need to take RTNL.
10109 	 */
10110 	mlxsw_core_flush_owq();
10111 	router = container_of(nb, struct mlxsw_sp_router, fib_nb);
10112 	mlxsw_sp_router_fib_flush(router->mlxsw_sp);
10113 }
10114 
10115 #ifdef CONFIG_IP_ROUTE_MULTIPATH
10116 struct mlxsw_sp_mp_hash_config {
10117 	DECLARE_BITMAP(headers, __MLXSW_REG_RECR2_HEADER_CNT);
10118 	DECLARE_BITMAP(fields, __MLXSW_REG_RECR2_FIELD_CNT);
10119 	DECLARE_BITMAP(inner_headers, __MLXSW_REG_RECR2_HEADER_CNT);
10120 	DECLARE_BITMAP(inner_fields, __MLXSW_REG_RECR2_INNER_FIELD_CNT);
10121 	bool inc_parsing_depth;
10122 };
10123 
10124 #define MLXSW_SP_MP_HASH_HEADER_SET(_headers, _header) \
10125 	bitmap_set(_headers, MLXSW_REG_RECR2_##_header, 1)
10126 
10127 #define MLXSW_SP_MP_HASH_FIELD_SET(_fields, _field) \
10128 	bitmap_set(_fields, MLXSW_REG_RECR2_##_field, 1)
10129 
10130 #define MLXSW_SP_MP_HASH_FIELD_RANGE_SET(_fields, _field, _nr) \
10131 	bitmap_set(_fields, MLXSW_REG_RECR2_##_field, _nr)
10132 
10133 static void mlxsw_sp_mp_hash_inner_l3(struct mlxsw_sp_mp_hash_config *config)
10134 {
10135 	unsigned long *inner_headers = config->inner_headers;
10136 	unsigned long *inner_fields = config->inner_fields;
10137 
10138 	/* IPv4 inner */
10139 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_NOT_TCP_NOT_UDP);
10140 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_TCP_UDP);
10141 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_SIP0, 4);
10142 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_DIP0, 4);
10143 	/* IPv6 inner */
10144 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_NOT_TCP_NOT_UDP);
10145 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_TCP_UDP);
10146 	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_SIP0_7);
10147 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_SIP8, 8);
10148 	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_DIP0_7);
10149 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_DIP8, 8);
10150 	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_NEXT_HEADER);
10151 	MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_FLOW_LABEL);
10152 }
10153 
10154 static void mlxsw_sp_mp4_hash_outer_addr(struct mlxsw_sp_mp_hash_config *config)
10155 {
10156 	unsigned long *headers = config->headers;
10157 	unsigned long *fields = config->fields;
10158 
10159 	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_NOT_TCP_NOT_UDP);
10160 	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_TCP_UDP);
10161 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_SIP0, 4);
10162 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_DIP0, 4);
10163 }
10164 
10165 static void
10166 mlxsw_sp_mp_hash_inner_custom(struct mlxsw_sp_mp_hash_config *config,
10167 			      u32 hash_fields)
10168 {
10169 	unsigned long *inner_headers = config->inner_headers;
10170 	unsigned long *inner_fields = config->inner_fields;
10171 
10172 	/* IPv4 Inner */
10173 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_NOT_TCP_NOT_UDP);
10174 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV4_EN_TCP_UDP);
10175 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP)
10176 		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_SIP0, 4);
10177 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP)
10178 		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV4_DIP0, 4);
10179 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO)
10180 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV4_PROTOCOL);
10181 	/* IPv6 inner */
10182 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_NOT_TCP_NOT_UDP);
10183 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, IPV6_EN_TCP_UDP);
10184 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP) {
10185 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_SIP0_7);
10186 		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_SIP8, 8);
10187 	}
10188 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP) {
10189 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_DIP0_7);
10190 		MLXSW_SP_MP_HASH_FIELD_RANGE_SET(inner_fields, INNER_IPV6_DIP8, 8);
10191 	}
10192 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO)
10193 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_NEXT_HEADER);
10194 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL)
10195 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_IPV6_FLOW_LABEL);
10196 	/* L4 inner */
10197 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, TCP_UDP_EN_IPV4);
10198 	MLXSW_SP_MP_HASH_HEADER_SET(inner_headers, TCP_UDP_EN_IPV6);
10199 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT)
10200 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_TCP_UDP_SPORT);
10201 	if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT)
10202 		MLXSW_SP_MP_HASH_FIELD_SET(inner_fields, INNER_TCP_UDP_DPORT);
10203 }
10204 
10205 static void mlxsw_sp_mp4_hash_init(struct mlxsw_sp *mlxsw_sp,
10206 				   struct mlxsw_sp_mp_hash_config *config)
10207 {
10208 	struct net *net = mlxsw_sp_net(mlxsw_sp);
10209 	unsigned long *headers = config->headers;
10210 	unsigned long *fields = config->fields;
10211 	u32 hash_fields;
10212 
10213 	switch (READ_ONCE(net->ipv4.sysctl_fib_multipath_hash_policy)) {
10214 	case 0:
10215 		mlxsw_sp_mp4_hash_outer_addr(config);
10216 		break;
10217 	case 1:
10218 		mlxsw_sp_mp4_hash_outer_addr(config);
10219 		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV4);
10220 		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV4_PROTOCOL);
10221 		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
10222 		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
10223 		break;
10224 	case 2:
10225 		/* Outer */
10226 		mlxsw_sp_mp4_hash_outer_addr(config);
10227 		/* Inner */
10228 		mlxsw_sp_mp_hash_inner_l3(config);
10229 		break;
10230 	case 3:
10231 		hash_fields = READ_ONCE(net->ipv4.sysctl_fib_multipath_hash_fields);
10232 		/* Outer */
10233 		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_NOT_TCP_NOT_UDP);
10234 		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV4_EN_TCP_UDP);
10235 		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV4);
10236 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP)
10237 			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_SIP0, 4);
10238 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP)
10239 			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV4_DIP0, 4);
10240 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
10241 			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV4_PROTOCOL);
10242 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
10243 			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
10244 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
10245 			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
10246 		/* Inner */
10247 		mlxsw_sp_mp_hash_inner_custom(config, hash_fields);
10248 		break;
10249 	}
10250 }
10251 
10252 static void mlxsw_sp_mp6_hash_outer_addr(struct mlxsw_sp_mp_hash_config *config)
10253 {
10254 	unsigned long *headers = config->headers;
10255 	unsigned long *fields = config->fields;
10256 
10257 	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_NOT_TCP_NOT_UDP);
10258 	MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_TCP_UDP);
10259 	MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_SIP0_7);
10260 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_SIP8, 8);
10261 	MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_DIP0_7);
10262 	MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_DIP8, 8);
10263 }
10264 
10265 static void mlxsw_sp_mp6_hash_init(struct mlxsw_sp *mlxsw_sp,
10266 				   struct mlxsw_sp_mp_hash_config *config)
10267 {
10268 	u32 hash_fields = ip6_multipath_hash_fields(mlxsw_sp_net(mlxsw_sp));
10269 	unsigned long *headers = config->headers;
10270 	unsigned long *fields = config->fields;
10271 
10272 	switch (ip6_multipath_hash_policy(mlxsw_sp_net(mlxsw_sp))) {
10273 	case 0:
10274 		mlxsw_sp_mp6_hash_outer_addr(config);
10275 		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
10276 		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_FLOW_LABEL);
10277 		break;
10278 	case 1:
10279 		mlxsw_sp_mp6_hash_outer_addr(config);
10280 		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV6);
10281 		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
10282 		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
10283 		MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
10284 		break;
10285 	case 2:
10286 		/* Outer */
10287 		mlxsw_sp_mp6_hash_outer_addr(config);
10288 		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
10289 		MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_FLOW_LABEL);
10290 		/* Inner */
10291 		mlxsw_sp_mp_hash_inner_l3(config);
10292 		config->inc_parsing_depth = true;
10293 		break;
10294 	case 3:
10295 		/* Outer */
10296 		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_NOT_TCP_NOT_UDP);
10297 		MLXSW_SP_MP_HASH_HEADER_SET(headers, IPV6_EN_TCP_UDP);
10298 		MLXSW_SP_MP_HASH_HEADER_SET(headers, TCP_UDP_EN_IPV6);
10299 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_IP) {
10300 			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_SIP0_7);
10301 			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_SIP8, 8);
10302 		}
10303 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_IP) {
10304 			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_DIP0_7);
10305 			MLXSW_SP_MP_HASH_FIELD_RANGE_SET(fields, IPV6_DIP8, 8);
10306 		}
10307 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_IP_PROTO)
10308 			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_NEXT_HEADER);
10309 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_FLOWLABEL)
10310 			MLXSW_SP_MP_HASH_FIELD_SET(fields, IPV6_FLOW_LABEL);
10311 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_SRC_PORT)
10312 			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_SPORT);
10313 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_DST_PORT)
10314 			MLXSW_SP_MP_HASH_FIELD_SET(fields, TCP_UDP_DPORT);
10315 		/* Inner */
10316 		mlxsw_sp_mp_hash_inner_custom(config, hash_fields);
10317 		if (hash_fields & FIB_MULTIPATH_HASH_FIELD_INNER_MASK)
10318 			config->inc_parsing_depth = true;
10319 		break;
10320 	}
10321 }
10322 
10323 static int mlxsw_sp_mp_hash_parsing_depth_adjust(struct mlxsw_sp *mlxsw_sp,
10324 						 bool old_inc_parsing_depth,
10325 						 bool new_inc_parsing_depth)
10326 {
10327 	int err;
10328 
10329 	if (!old_inc_parsing_depth && new_inc_parsing_depth) {
10330 		err = mlxsw_sp_parsing_depth_inc(mlxsw_sp);
10331 		if (err)
10332 			return err;
10333 		mlxsw_sp->router->inc_parsing_depth = true;
10334 	} else if (old_inc_parsing_depth && !new_inc_parsing_depth) {
10335 		mlxsw_sp_parsing_depth_dec(mlxsw_sp);
10336 		mlxsw_sp->router->inc_parsing_depth = false;
10337 	}
10338 
10339 	return 0;
10340 }
10341 
10342 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
10343 {
10344 	bool old_inc_parsing_depth, new_inc_parsing_depth;
10345 	struct mlxsw_sp_mp_hash_config config = {};
10346 	char recr2_pl[MLXSW_REG_RECR2_LEN];
10347 	unsigned long bit;
10348 	u32 seed;
10349 	int err;
10350 
10351 	seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac), 0);
10352 	mlxsw_reg_recr2_pack(recr2_pl, seed);
10353 	mlxsw_sp_mp4_hash_init(mlxsw_sp, &config);
10354 	mlxsw_sp_mp6_hash_init(mlxsw_sp, &config);
10355 
10356 	old_inc_parsing_depth = mlxsw_sp->router->inc_parsing_depth;
10357 	new_inc_parsing_depth = config.inc_parsing_depth;
10358 	err = mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp,
10359 						    old_inc_parsing_depth,
10360 						    new_inc_parsing_depth);
10361 	if (err)
10362 		return err;
10363 
10364 	for_each_set_bit(bit, config.headers, __MLXSW_REG_RECR2_HEADER_CNT)
10365 		mlxsw_reg_recr2_outer_header_enables_set(recr2_pl, bit, 1);
10366 	for_each_set_bit(bit, config.fields, __MLXSW_REG_RECR2_FIELD_CNT)
10367 		mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl, bit, 1);
10368 	for_each_set_bit(bit, config.inner_headers, __MLXSW_REG_RECR2_HEADER_CNT)
10369 		mlxsw_reg_recr2_inner_header_enables_set(recr2_pl, bit, 1);
10370 	for_each_set_bit(bit, config.inner_fields, __MLXSW_REG_RECR2_INNER_FIELD_CNT)
10371 		mlxsw_reg_recr2_inner_header_fields_enable_set(recr2_pl, bit, 1);
10372 
10373 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(recr2), recr2_pl);
10374 	if (err)
10375 		goto err_reg_write;
10376 
10377 	return 0;
10378 
10379 err_reg_write:
10380 	mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp, new_inc_parsing_depth,
10381 					      old_inc_parsing_depth);
10382 	return err;
10383 }
10384 
10385 static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp)
10386 {
10387 	bool old_inc_parsing_depth = mlxsw_sp->router->inc_parsing_depth;
10388 
10389 	mlxsw_sp_mp_hash_parsing_depth_adjust(mlxsw_sp, old_inc_parsing_depth,
10390 					      false);
10391 }
10392 #else
10393 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
10394 {
10395 	return 0;
10396 }
10397 
10398 static void mlxsw_sp_mp_hash_fini(struct mlxsw_sp *mlxsw_sp)
10399 {
10400 }
10401 #endif
10402 
10403 static int mlxsw_sp_dscp_init(struct mlxsw_sp *mlxsw_sp)
10404 {
10405 	char rdpm_pl[MLXSW_REG_RDPM_LEN];
10406 	unsigned int i;
10407 
10408 	MLXSW_REG_ZERO(rdpm, rdpm_pl);
10409 
10410 	/* HW is determining switch priority based on DSCP-bits, but the
10411 	 * kernel is still doing that based on the ToS. Since there's a
10412 	 * mismatch in bits we need to make sure to translate the right
10413 	 * value ToS would observe, skipping the 2 least-significant ECN bits.
10414 	 */
10415 	for (i = 0; i < MLXSW_REG_RDPM_DSCP_ENTRY_REC_MAX_COUNT; i++)
10416 		mlxsw_reg_rdpm_pack(rdpm_pl, i, rt_tos2priority(i << 2));
10417 
10418 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rdpm), rdpm_pl);
10419 }
10420 
10421 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
10422 {
10423 	struct net *net = mlxsw_sp_net(mlxsw_sp);
10424 	char rgcr_pl[MLXSW_REG_RGCR_LEN];
10425 	u64 max_rifs;
10426 	bool usp;
10427 
10428 	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
10429 		return -EIO;
10430 	max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
10431 	usp = READ_ONCE(net->ipv4.sysctl_ip_fwd_update_priority);
10432 
10433 	mlxsw_reg_rgcr_pack(rgcr_pl, true, true);
10434 	mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
10435 	mlxsw_reg_rgcr_usp_set(rgcr_pl, usp);
10436 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
10437 }
10438 
10439 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
10440 {
10441 	char rgcr_pl[MLXSW_REG_RGCR_LEN];
10442 
10443 	mlxsw_reg_rgcr_pack(rgcr_pl, false, false);
10444 	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
10445 }
10446 
10447 static int mlxsw_sp_lb_rif_init(struct mlxsw_sp *mlxsw_sp)
10448 {
10449 	u16 lb_rif_index;
10450 	int err;
10451 
10452 	/* Create a generic loopback RIF associated with the main table
10453 	 * (default VRF). Any table can be used, but the main table exists
10454 	 * anyway, so we do not waste resources.
10455 	 */
10456 	err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, RT_TABLE_MAIN,
10457 					 &lb_rif_index);
10458 	if (err)
10459 		return err;
10460 
10461 	mlxsw_sp->router->lb_rif_index = lb_rif_index;
10462 
10463 	return 0;
10464 }
10465 
10466 static void mlxsw_sp_lb_rif_fini(struct mlxsw_sp *mlxsw_sp)
10467 {
10468 	mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->router->lb_rif_index);
10469 }
10470 
10471 static int mlxsw_sp1_router_init(struct mlxsw_sp *mlxsw_sp)
10472 {
10473 	size_t size_ranges_count = ARRAY_SIZE(mlxsw_sp1_adj_grp_size_ranges);
10474 
10475 	mlxsw_sp->router->rif_ops_arr = mlxsw_sp1_rif_ops_arr;
10476 	mlxsw_sp->router->adj_grp_size_ranges = mlxsw_sp1_adj_grp_size_ranges;
10477 	mlxsw_sp->router->adj_grp_size_ranges_count = size_ranges_count;
10478 
10479 	return 0;
10480 }
10481 
10482 const struct mlxsw_sp_router_ops mlxsw_sp1_router_ops = {
10483 	.init = mlxsw_sp1_router_init,
10484 	.ipips_init = mlxsw_sp1_ipips_init,
10485 };
10486 
10487 static int mlxsw_sp2_router_init(struct mlxsw_sp *mlxsw_sp)
10488 {
10489 	size_t size_ranges_count = ARRAY_SIZE(mlxsw_sp2_adj_grp_size_ranges);
10490 
10491 	mlxsw_sp->router->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
10492 	mlxsw_sp->router->adj_grp_size_ranges = mlxsw_sp2_adj_grp_size_ranges;
10493 	mlxsw_sp->router->adj_grp_size_ranges_count = size_ranges_count;
10494 
10495 	return 0;
10496 }
10497 
10498 const struct mlxsw_sp_router_ops mlxsw_sp2_router_ops = {
10499 	.init = mlxsw_sp2_router_init,
10500 	.ipips_init = mlxsw_sp2_ipips_init,
10501 };
10502 
10503 int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
10504 			 struct netlink_ext_ack *extack)
10505 {
10506 	struct mlxsw_sp_router *router;
10507 	int err;
10508 
10509 	router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
10510 	if (!router)
10511 		return -ENOMEM;
10512 	mutex_init(&router->lock);
10513 	mlxsw_sp->router = router;
10514 	router->mlxsw_sp = mlxsw_sp;
10515 
10516 	err = mlxsw_sp->router_ops->init(mlxsw_sp);
10517 	if (err)
10518 		goto err_router_ops_init;
10519 
10520 	INIT_LIST_HEAD(&mlxsw_sp->router->nh_res_grp_list);
10521 	INIT_DELAYED_WORK(&mlxsw_sp->router->nh_grp_activity_dw,
10522 			  mlxsw_sp_nh_grp_activity_work);
10523 	INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
10524 	err = __mlxsw_sp_router_init(mlxsw_sp);
10525 	if (err)
10526 		goto err_router_init;
10527 
10528 	err = mlxsw_sp_rifs_init(mlxsw_sp);
10529 	if (err)
10530 		goto err_rifs_init;
10531 
10532 	err = mlxsw_sp->router_ops->ipips_init(mlxsw_sp);
10533 	if (err)
10534 		goto err_ipips_init;
10535 
10536 	err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
10537 			      &mlxsw_sp_nexthop_ht_params);
10538 	if (err)
10539 		goto err_nexthop_ht_init;
10540 
10541 	err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht,
10542 			      &mlxsw_sp_nexthop_group_ht_params);
10543 	if (err)
10544 		goto err_nexthop_group_ht_init;
10545 
10546 	INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_list);
10547 	err = mlxsw_sp_lpm_init(mlxsw_sp);
10548 	if (err)
10549 		goto err_lpm_init;
10550 
10551 	err = mlxsw_sp_mr_init(mlxsw_sp, &mlxsw_sp_mr_tcam_ops);
10552 	if (err)
10553 		goto err_mr_init;
10554 
10555 	err = mlxsw_sp_vrs_init(mlxsw_sp);
10556 	if (err)
10557 		goto err_vrs_init;
10558 
10559 	err = mlxsw_sp_lb_rif_init(mlxsw_sp);
10560 	if (err)
10561 		goto err_lb_rif_init;
10562 
10563 	err = mlxsw_sp_neigh_init(mlxsw_sp);
10564 	if (err)
10565 		goto err_neigh_init;
10566 
10567 	err = mlxsw_sp_mp_hash_init(mlxsw_sp);
10568 	if (err)
10569 		goto err_mp_hash_init;
10570 
10571 	err = mlxsw_sp_dscp_init(mlxsw_sp);
10572 	if (err)
10573 		goto err_dscp_init;
10574 
10575 	router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event;
10576 	err = register_inetaddr_notifier(&router->inetaddr_nb);
10577 	if (err)
10578 		goto err_register_inetaddr_notifier;
10579 
10580 	router->inet6addr_nb.notifier_call = mlxsw_sp_inet6addr_event;
10581 	err = register_inet6addr_notifier(&router->inet6addr_nb);
10582 	if (err)
10583 		goto err_register_inet6addr_notifier;
10584 
10585 	mlxsw_sp->router->netevent_nb.notifier_call =
10586 		mlxsw_sp_router_netevent_event;
10587 	err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
10588 	if (err)
10589 		goto err_register_netevent_notifier;
10590 
10591 	mlxsw_sp->router->nexthop_nb.notifier_call =
10592 		mlxsw_sp_nexthop_obj_event;
10593 	err = register_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
10594 					&mlxsw_sp->router->nexthop_nb,
10595 					extack);
10596 	if (err)
10597 		goto err_register_nexthop_notifier;
10598 
10599 	mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
10600 	err = register_fib_notifier(mlxsw_sp_net(mlxsw_sp),
10601 				    &mlxsw_sp->router->fib_nb,
10602 				    mlxsw_sp_router_fib_dump_flush, extack);
10603 	if (err)
10604 		goto err_register_fib_notifier;
10605 
10606 	mlxsw_sp->router->netdevice_nb.notifier_call =
10607 		mlxsw_sp_router_netdevice_event;
10608 	err = register_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
10609 					      &mlxsw_sp->router->netdevice_nb);
10610 	if (err)
10611 		goto err_register_netdev_notifier;
10612 
10613 	return 0;
10614 
10615 err_register_netdev_notifier:
10616 	unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
10617 				&mlxsw_sp->router->fib_nb);
10618 err_register_fib_notifier:
10619 	unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
10620 				    &mlxsw_sp->router->nexthop_nb);
10621 err_register_nexthop_notifier:
10622 	unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
10623 err_register_netevent_notifier:
10624 	unregister_inet6addr_notifier(&router->inet6addr_nb);
10625 err_register_inet6addr_notifier:
10626 	unregister_inetaddr_notifier(&router->inetaddr_nb);
10627 err_register_inetaddr_notifier:
10628 	mlxsw_core_flush_owq();
10629 err_dscp_init:
10630 	mlxsw_sp_mp_hash_fini(mlxsw_sp);
10631 err_mp_hash_init:
10632 	mlxsw_sp_neigh_fini(mlxsw_sp);
10633 err_neigh_init:
10634 	mlxsw_sp_lb_rif_fini(mlxsw_sp);
10635 err_lb_rif_init:
10636 	mlxsw_sp_vrs_fini(mlxsw_sp);
10637 err_vrs_init:
10638 	mlxsw_sp_mr_fini(mlxsw_sp);
10639 err_mr_init:
10640 	mlxsw_sp_lpm_fini(mlxsw_sp);
10641 err_lpm_init:
10642 	rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
10643 err_nexthop_group_ht_init:
10644 	rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
10645 err_nexthop_ht_init:
10646 	mlxsw_sp_ipips_fini(mlxsw_sp);
10647 err_ipips_init:
10648 	mlxsw_sp_rifs_fini(mlxsw_sp);
10649 err_rifs_init:
10650 	__mlxsw_sp_router_fini(mlxsw_sp);
10651 err_router_init:
10652 	cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
10653 err_router_ops_init:
10654 	mutex_destroy(&mlxsw_sp->router->lock);
10655 	kfree(mlxsw_sp->router);
10656 	return err;
10657 }
10658 
10659 void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
10660 {
10661 	unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp),
10662 					  &mlxsw_sp->router->netdevice_nb);
10663 	unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp),
10664 				&mlxsw_sp->router->fib_nb);
10665 	unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp),
10666 				    &mlxsw_sp->router->nexthop_nb);
10667 	unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
10668 	unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb);
10669 	unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb);
10670 	mlxsw_core_flush_owq();
10671 	mlxsw_sp_mp_hash_fini(mlxsw_sp);
10672 	mlxsw_sp_neigh_fini(mlxsw_sp);
10673 	mlxsw_sp_lb_rif_fini(mlxsw_sp);
10674 	mlxsw_sp_vrs_fini(mlxsw_sp);
10675 	mlxsw_sp_mr_fini(mlxsw_sp);
10676 	mlxsw_sp_lpm_fini(mlxsw_sp);
10677 	rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
10678 	rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
10679 	mlxsw_sp_ipips_fini(mlxsw_sp);
10680 	mlxsw_sp_rifs_fini(mlxsw_sp);
10681 	__mlxsw_sp_router_fini(mlxsw_sp);
10682 	cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw);
10683 	mutex_destroy(&mlxsw_sp->router->lock);
10684 	kfree(mlxsw_sp->router);
10685 }
10686