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