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