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