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