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>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
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 <linux/gcd.h>
50 #include <linux/random.h>
51 #include <net/netevent.h>
52 #include <net/neighbour.h>
54 #include <net/ip_fib.h>
55 #include <net/ip6_fib.h>
56 #include <net/fib_rules.h>
57 #include <net/ip_tunnels.h>
58 #include <net/l3mdev.h>
59 #include <net/addrconf.h>
60 #include <net/ndisc.h>
62 #include <net/fib_notifier.h>
67 #include "spectrum_cnt.h"
68 #include "spectrum_dpipe.h"
69 #include "spectrum_ipip.h"
70 #include "spectrum_mr.h"
71 #include "spectrum_mr_tcam.h"
72 #include "spectrum_router.h"
75 struct mlxsw_sp_lpm_tree
;
76 struct mlxsw_sp_rif_ops
;
78 struct mlxsw_sp_router
{
79 struct mlxsw_sp
*mlxsw_sp
;
80 struct mlxsw_sp_rif
**rifs
;
81 struct mlxsw_sp_vr
*vrs
;
82 struct rhashtable neigh_ht
;
83 struct rhashtable nexthop_group_ht
;
84 struct rhashtable nexthop_ht
;
85 struct list_head nexthop_list
;
87 struct mlxsw_sp_lpm_tree
*trees
;
88 unsigned int tree_count
;
91 struct delayed_work dw
;
92 unsigned long interval
; /* ms */
94 struct delayed_work nexthop_probe_dw
;
95 #define MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL 5000 /* ms */
96 struct list_head nexthop_neighs_list
;
97 struct list_head ipip_list
;
99 struct notifier_block fib_nb
;
100 struct notifier_block netevent_nb
;
101 const struct mlxsw_sp_rif_ops
**rif_ops_arr
;
102 const struct mlxsw_sp_ipip_ops
**ipip_ops_arr
;
105 struct mlxsw_sp_rif
{
106 struct list_head nexthop_list
;
107 struct list_head neigh_list
;
108 struct net_device
*dev
;
109 struct mlxsw_sp_fid
*fid
;
110 unsigned char addr
[ETH_ALEN
];
114 const struct mlxsw_sp_rif_ops
*ops
;
115 struct mlxsw_sp
*mlxsw_sp
;
117 unsigned int counter_ingress
;
118 bool counter_ingress_valid
;
119 unsigned int counter_egress
;
120 bool counter_egress_valid
;
123 struct mlxsw_sp_rif_params
{
124 struct net_device
*dev
;
133 struct mlxsw_sp_rif_subport
{
134 struct mlxsw_sp_rif common
;
143 struct mlxsw_sp_rif_ipip_lb
{
144 struct mlxsw_sp_rif common
;
145 struct mlxsw_sp_rif_ipip_lb_config lb_config
;
146 u16 ul_vr_id
; /* Reserved for Spectrum-2. */
149 struct mlxsw_sp_rif_params_ipip_lb
{
150 struct mlxsw_sp_rif_params common
;
151 struct mlxsw_sp_rif_ipip_lb_config lb_config
;
154 struct mlxsw_sp_rif_ops
{
155 enum mlxsw_sp_rif_type type
;
158 void (*setup
)(struct mlxsw_sp_rif
*rif
,
159 const struct mlxsw_sp_rif_params
*params
);
160 int (*configure
)(struct mlxsw_sp_rif
*rif
);
161 void (*deconfigure
)(struct mlxsw_sp_rif
*rif
);
162 struct mlxsw_sp_fid
* (*fid_get
)(struct mlxsw_sp_rif
*rif
);
165 static unsigned int *
166 mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif
*rif
,
167 enum mlxsw_sp_rif_counter_dir dir
)
170 case MLXSW_SP_RIF_COUNTER_EGRESS
:
171 return &rif
->counter_egress
;
172 case MLXSW_SP_RIF_COUNTER_INGRESS
:
173 return &rif
->counter_ingress
;
179 mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif
*rif
,
180 enum mlxsw_sp_rif_counter_dir dir
)
183 case MLXSW_SP_RIF_COUNTER_EGRESS
:
184 return rif
->counter_egress_valid
;
185 case MLXSW_SP_RIF_COUNTER_INGRESS
:
186 return rif
->counter_ingress_valid
;
192 mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif
*rif
,
193 enum mlxsw_sp_rif_counter_dir dir
,
197 case MLXSW_SP_RIF_COUNTER_EGRESS
:
198 rif
->counter_egress_valid
= valid
;
200 case MLXSW_SP_RIF_COUNTER_INGRESS
:
201 rif
->counter_ingress_valid
= valid
;
206 static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
207 unsigned int counter_index
, bool enable
,
208 enum mlxsw_sp_rif_counter_dir dir
)
210 char ritr_pl
[MLXSW_REG_RITR_LEN
];
211 bool is_egress
= false;
214 if (dir
== MLXSW_SP_RIF_COUNTER_EGRESS
)
216 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
217 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
221 mlxsw_reg_ritr_counter_pack(ritr_pl
, counter_index
, enable
,
223 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
226 int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp
*mlxsw_sp
,
227 struct mlxsw_sp_rif
*rif
,
228 enum mlxsw_sp_rif_counter_dir dir
, u64
*cnt
)
230 char ricnt_pl
[MLXSW_REG_RICNT_LEN
];
231 unsigned int *p_counter_index
;
235 valid
= mlxsw_sp_rif_counter_valid_get(rif
, dir
);
239 p_counter_index
= mlxsw_sp_rif_p_counter_get(rif
, dir
);
240 if (!p_counter_index
)
242 mlxsw_reg_ricnt_pack(ricnt_pl
, *p_counter_index
,
243 MLXSW_REG_RICNT_OPCODE_NOP
);
244 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ricnt
), ricnt_pl
);
247 *cnt
= mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl
);
251 static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp
*mlxsw_sp
,
252 unsigned int counter_index
)
254 char ricnt_pl
[MLXSW_REG_RICNT_LEN
];
256 mlxsw_reg_ricnt_pack(ricnt_pl
, counter_index
,
257 MLXSW_REG_RICNT_OPCODE_CLEAR
);
258 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ricnt
), ricnt_pl
);
261 int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
262 struct mlxsw_sp_rif
*rif
,
263 enum mlxsw_sp_rif_counter_dir dir
)
265 unsigned int *p_counter_index
;
268 p_counter_index
= mlxsw_sp_rif_p_counter_get(rif
, dir
);
269 if (!p_counter_index
)
271 err
= mlxsw_sp_counter_alloc(mlxsw_sp
, MLXSW_SP_COUNTER_SUB_POOL_RIF
,
276 err
= mlxsw_sp_rif_counter_clear(mlxsw_sp
, *p_counter_index
);
278 goto err_counter_clear
;
280 err
= mlxsw_sp_rif_counter_edit(mlxsw_sp
, rif
->rif_index
,
281 *p_counter_index
, true, dir
);
283 goto err_counter_edit
;
284 mlxsw_sp_rif_counter_valid_set(rif
, dir
, true);
289 mlxsw_sp_counter_free(mlxsw_sp
, MLXSW_SP_COUNTER_SUB_POOL_RIF
,
294 void mlxsw_sp_rif_counter_free(struct mlxsw_sp
*mlxsw_sp
,
295 struct mlxsw_sp_rif
*rif
,
296 enum mlxsw_sp_rif_counter_dir dir
)
298 unsigned int *p_counter_index
;
300 if (!mlxsw_sp_rif_counter_valid_get(rif
, dir
))
303 p_counter_index
= mlxsw_sp_rif_p_counter_get(rif
, dir
);
304 if (WARN_ON(!p_counter_index
))
306 mlxsw_sp_rif_counter_edit(mlxsw_sp
, rif
->rif_index
,
307 *p_counter_index
, false, dir
);
308 mlxsw_sp_counter_free(mlxsw_sp
, MLXSW_SP_COUNTER_SUB_POOL_RIF
,
310 mlxsw_sp_rif_counter_valid_set(rif
, dir
, false);
313 static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif
*rif
)
315 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
316 struct devlink
*devlink
;
318 devlink
= priv_to_devlink(mlxsw_sp
->core
);
319 if (!devlink_dpipe_table_counter_enabled(devlink
,
320 MLXSW_SP_DPIPE_TABLE_NAME_ERIF
))
322 mlxsw_sp_rif_counter_alloc(mlxsw_sp
, rif
, MLXSW_SP_RIF_COUNTER_EGRESS
);
325 static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif
*rif
)
327 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
329 mlxsw_sp_rif_counter_free(mlxsw_sp
, rif
, MLXSW_SP_RIF_COUNTER_EGRESS
);
332 static struct mlxsw_sp_rif
*
333 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp
*mlxsw_sp
,
334 const struct net_device
*dev
);
336 #define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1)
338 struct mlxsw_sp_prefix_usage
{
339 DECLARE_BITMAP(b
, MLXSW_SP_PREFIX_COUNT
);
342 #define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
343 for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
346 mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage
*prefix_usage1
,
347 struct mlxsw_sp_prefix_usage
*prefix_usage2
)
349 return !memcmp(prefix_usage1
, prefix_usage2
, sizeof(*prefix_usage1
));
353 mlxsw_sp_prefix_usage_none(struct mlxsw_sp_prefix_usage
*prefix_usage
)
355 struct mlxsw_sp_prefix_usage prefix_usage_none
= {{ 0 } };
357 return mlxsw_sp_prefix_usage_eq(prefix_usage
, &prefix_usage_none
);
361 mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage
*prefix_usage1
,
362 struct mlxsw_sp_prefix_usage
*prefix_usage2
)
364 memcpy(prefix_usage1
, prefix_usage2
, sizeof(*prefix_usage1
));
368 mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage
*prefix_usage
,
369 unsigned char prefix_len
)
371 set_bit(prefix_len
, prefix_usage
->b
);
375 mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage
*prefix_usage
,
376 unsigned char prefix_len
)
378 clear_bit(prefix_len
, prefix_usage
->b
);
381 struct mlxsw_sp_fib_key
{
382 unsigned char addr
[sizeof(struct in6_addr
)];
383 unsigned char prefix_len
;
386 enum mlxsw_sp_fib_entry_type
{
387 MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
,
388 MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
,
389 MLXSW_SP_FIB_ENTRY_TYPE_TRAP
,
391 /* This is a special case of local delivery, where a packet should be
392 * decapsulated on reception. Note that there is no corresponding ENCAP,
393 * because that's a type of next hop, not of FIB entry. (There can be
394 * several next hops in a REMOTE entry, and some of them may be
395 * encapsulating entries.)
397 MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
,
400 struct mlxsw_sp_nexthop_group
;
403 struct mlxsw_sp_fib_node
{
404 struct list_head entry_list
;
405 struct list_head list
;
406 struct rhash_head ht_node
;
407 struct mlxsw_sp_fib
*fib
;
408 struct mlxsw_sp_fib_key key
;
411 struct mlxsw_sp_fib_entry_decap
{
412 struct mlxsw_sp_ipip_entry
*ipip_entry
;
416 struct mlxsw_sp_fib_entry
{
417 struct list_head list
;
418 struct mlxsw_sp_fib_node
*fib_node
;
419 enum mlxsw_sp_fib_entry_type type
;
420 struct list_head nexthop_group_node
;
421 struct mlxsw_sp_nexthop_group
*nh_group
;
422 struct mlxsw_sp_fib_entry_decap decap
; /* Valid for decap entries. */
425 struct mlxsw_sp_fib4_entry
{
426 struct mlxsw_sp_fib_entry common
;
433 struct mlxsw_sp_fib6_entry
{
434 struct mlxsw_sp_fib_entry common
;
435 struct list_head rt6_list
;
439 struct mlxsw_sp_rt6
{
440 struct list_head list
;
444 struct mlxsw_sp_lpm_tree
{
446 unsigned int ref_count
;
447 enum mlxsw_sp_l3proto proto
;
448 struct mlxsw_sp_prefix_usage prefix_usage
;
451 struct mlxsw_sp_fib
{
452 struct rhashtable ht
;
453 struct list_head node_list
;
454 struct mlxsw_sp_vr
*vr
;
455 struct mlxsw_sp_lpm_tree
*lpm_tree
;
456 unsigned long prefix_ref_count
[MLXSW_SP_PREFIX_COUNT
];
457 struct mlxsw_sp_prefix_usage prefix_usage
;
458 enum mlxsw_sp_l3proto proto
;
462 u16 id
; /* virtual router ID */
463 u32 tb_id
; /* kernel fib table id */
464 unsigned int rif_count
;
465 struct mlxsw_sp_fib
*fib4
;
466 struct mlxsw_sp_fib
*fib6
;
467 struct mlxsw_sp_mr_table
*mr4_table
;
470 static const struct rhashtable_params mlxsw_sp_fib_ht_params
;
472 static struct mlxsw_sp_fib
*mlxsw_sp_fib_create(struct mlxsw_sp_vr
*vr
,
473 enum mlxsw_sp_l3proto proto
)
475 struct mlxsw_sp_fib
*fib
;
478 fib
= kzalloc(sizeof(*fib
), GFP_KERNEL
);
480 return ERR_PTR(-ENOMEM
);
481 err
= rhashtable_init(&fib
->ht
, &mlxsw_sp_fib_ht_params
);
483 goto err_rhashtable_init
;
484 INIT_LIST_HEAD(&fib
->node_list
);
494 static void mlxsw_sp_fib_destroy(struct mlxsw_sp_fib
*fib
)
496 WARN_ON(!list_empty(&fib
->node_list
));
497 WARN_ON(fib
->lpm_tree
);
498 rhashtable_destroy(&fib
->ht
);
502 static struct mlxsw_sp_lpm_tree
*
503 mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp
*mlxsw_sp
)
505 static struct mlxsw_sp_lpm_tree
*lpm_tree
;
508 for (i
= 0; i
< mlxsw_sp
->router
->lpm
.tree_count
; i
++) {
509 lpm_tree
= &mlxsw_sp
->router
->lpm
.trees
[i
];
510 if (lpm_tree
->ref_count
== 0)
516 static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp
*mlxsw_sp
,
517 struct mlxsw_sp_lpm_tree
*lpm_tree
)
519 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
521 mlxsw_reg_ralta_pack(ralta_pl
, true,
522 (enum mlxsw_reg_ralxx_protocol
) lpm_tree
->proto
,
524 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
527 static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp
*mlxsw_sp
,
528 struct mlxsw_sp_lpm_tree
*lpm_tree
)
530 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
532 mlxsw_reg_ralta_pack(ralta_pl
, false,
533 (enum mlxsw_reg_ralxx_protocol
) lpm_tree
->proto
,
535 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
539 mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp
*mlxsw_sp
,
540 struct mlxsw_sp_prefix_usage
*prefix_usage
,
541 struct mlxsw_sp_lpm_tree
*lpm_tree
)
543 char ralst_pl
[MLXSW_REG_RALST_LEN
];
546 u8 last_prefix
= MLXSW_REG_RALST_BIN_NO_CHILD
;
548 mlxsw_sp_prefix_usage_for_each(prefix
, prefix_usage
)
551 mlxsw_reg_ralst_pack(ralst_pl
, root_bin
, lpm_tree
->id
);
552 mlxsw_sp_prefix_usage_for_each(prefix
, prefix_usage
) {
555 mlxsw_reg_ralst_bin_pack(ralst_pl
, prefix
, last_prefix
,
556 MLXSW_REG_RALST_BIN_NO_CHILD
);
557 last_prefix
= prefix
;
559 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralst
), ralst_pl
);
562 static struct mlxsw_sp_lpm_tree
*
563 mlxsw_sp_lpm_tree_create(struct mlxsw_sp
*mlxsw_sp
,
564 struct mlxsw_sp_prefix_usage
*prefix_usage
,
565 enum mlxsw_sp_l3proto proto
)
567 struct mlxsw_sp_lpm_tree
*lpm_tree
;
570 lpm_tree
= mlxsw_sp_lpm_tree_find_unused(mlxsw_sp
);
572 return ERR_PTR(-EBUSY
);
573 lpm_tree
->proto
= proto
;
574 err
= mlxsw_sp_lpm_tree_alloc(mlxsw_sp
, lpm_tree
);
578 err
= mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp
, prefix_usage
,
581 goto err_left_struct_set
;
582 memcpy(&lpm_tree
->prefix_usage
, prefix_usage
,
583 sizeof(lpm_tree
->prefix_usage
));
587 mlxsw_sp_lpm_tree_free(mlxsw_sp
, lpm_tree
);
591 static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp
*mlxsw_sp
,
592 struct mlxsw_sp_lpm_tree
*lpm_tree
)
594 mlxsw_sp_lpm_tree_free(mlxsw_sp
, lpm_tree
);
597 static struct mlxsw_sp_lpm_tree
*
598 mlxsw_sp_lpm_tree_get(struct mlxsw_sp
*mlxsw_sp
,
599 struct mlxsw_sp_prefix_usage
*prefix_usage
,
600 enum mlxsw_sp_l3proto proto
)
602 struct mlxsw_sp_lpm_tree
*lpm_tree
;
605 for (i
= 0; i
< mlxsw_sp
->router
->lpm
.tree_count
; i
++) {
606 lpm_tree
= &mlxsw_sp
->router
->lpm
.trees
[i
];
607 if (lpm_tree
->ref_count
!= 0 &&
608 lpm_tree
->proto
== proto
&&
609 mlxsw_sp_prefix_usage_eq(&lpm_tree
->prefix_usage
,
613 return mlxsw_sp_lpm_tree_create(mlxsw_sp
, prefix_usage
, proto
);
616 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree
*lpm_tree
)
618 lpm_tree
->ref_count
++;
621 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp
*mlxsw_sp
,
622 struct mlxsw_sp_lpm_tree
*lpm_tree
)
624 if (--lpm_tree
->ref_count
== 0)
625 mlxsw_sp_lpm_tree_destroy(mlxsw_sp
, lpm_tree
);
628 #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
630 static int mlxsw_sp_lpm_init(struct mlxsw_sp
*mlxsw_sp
)
632 struct mlxsw_sp_lpm_tree
*lpm_tree
;
636 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_LPM_TREES
))
639 max_trees
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_LPM_TREES
);
640 mlxsw_sp
->router
->lpm
.tree_count
= max_trees
- MLXSW_SP_LPM_TREE_MIN
;
641 mlxsw_sp
->router
->lpm
.trees
= kcalloc(mlxsw_sp
->router
->lpm
.tree_count
,
642 sizeof(struct mlxsw_sp_lpm_tree
),
644 if (!mlxsw_sp
->router
->lpm
.trees
)
647 for (i
= 0; i
< mlxsw_sp
->router
->lpm
.tree_count
; i
++) {
648 lpm_tree
= &mlxsw_sp
->router
->lpm
.trees
[i
];
649 lpm_tree
->id
= i
+ MLXSW_SP_LPM_TREE_MIN
;
655 static void mlxsw_sp_lpm_fini(struct mlxsw_sp
*mlxsw_sp
)
657 kfree(mlxsw_sp
->router
->lpm
.trees
);
660 static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr
*vr
)
662 return !!vr
->fib4
|| !!vr
->fib6
|| !!vr
->mr4_table
;
665 static struct mlxsw_sp_vr
*mlxsw_sp_vr_find_unused(struct mlxsw_sp
*mlxsw_sp
)
667 struct mlxsw_sp_vr
*vr
;
670 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
671 vr
= &mlxsw_sp
->router
->vrs
[i
];
672 if (!mlxsw_sp_vr_is_used(vr
))
678 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp
*mlxsw_sp
,
679 const struct mlxsw_sp_fib
*fib
, u8 tree_id
)
681 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
683 mlxsw_reg_raltb_pack(raltb_pl
, fib
->vr
->id
,
684 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
,
686 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
), raltb_pl
);
689 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp
*mlxsw_sp
,
690 const struct mlxsw_sp_fib
*fib
)
692 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
694 /* Bind to tree 0 which is default */
695 mlxsw_reg_raltb_pack(raltb_pl
, fib
->vr
->id
,
696 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
, 0);
697 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
), raltb_pl
);
700 static u32
mlxsw_sp_fix_tb_id(u32 tb_id
)
702 /* For our purpose, squash main, default and local tables into one */
703 if (tb_id
== RT_TABLE_LOCAL
|| tb_id
== RT_TABLE_DEFAULT
)
704 tb_id
= RT_TABLE_MAIN
;
708 static struct mlxsw_sp_vr
*mlxsw_sp_vr_find(struct mlxsw_sp
*mlxsw_sp
,
711 struct mlxsw_sp_vr
*vr
;
714 tb_id
= mlxsw_sp_fix_tb_id(tb_id
);
716 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
717 vr
= &mlxsw_sp
->router
->vrs
[i
];
718 if (mlxsw_sp_vr_is_used(vr
) && vr
->tb_id
== tb_id
)
724 static struct mlxsw_sp_fib
*mlxsw_sp_vr_fib(const struct mlxsw_sp_vr
*vr
,
725 enum mlxsw_sp_l3proto proto
)
728 case MLXSW_SP_L3_PROTO_IPV4
:
730 case MLXSW_SP_L3_PROTO_IPV6
:
736 static struct mlxsw_sp_vr
*mlxsw_sp_vr_create(struct mlxsw_sp
*mlxsw_sp
,
738 struct netlink_ext_ack
*extack
)
740 struct mlxsw_sp_vr
*vr
;
743 vr
= mlxsw_sp_vr_find_unused(mlxsw_sp
);
745 NL_SET_ERR_MSG(extack
, "spectrum: Exceeded number of supported virtual routers");
746 return ERR_PTR(-EBUSY
);
748 vr
->fib4
= mlxsw_sp_fib_create(vr
, MLXSW_SP_L3_PROTO_IPV4
);
749 if (IS_ERR(vr
->fib4
))
750 return ERR_CAST(vr
->fib4
);
751 vr
->fib6
= mlxsw_sp_fib_create(vr
, MLXSW_SP_L3_PROTO_IPV6
);
752 if (IS_ERR(vr
->fib6
)) {
753 err
= PTR_ERR(vr
->fib6
);
754 goto err_fib6_create
;
756 vr
->mr4_table
= mlxsw_sp_mr_table_create(mlxsw_sp
, vr
->id
,
757 MLXSW_SP_L3_PROTO_IPV4
);
758 if (IS_ERR(vr
->mr4_table
)) {
759 err
= PTR_ERR(vr
->mr4_table
);
760 goto err_mr_table_create
;
766 mlxsw_sp_fib_destroy(vr
->fib6
);
769 mlxsw_sp_fib_destroy(vr
->fib4
);
774 static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr
*vr
)
776 mlxsw_sp_mr_table_destroy(vr
->mr4_table
);
777 vr
->mr4_table
= NULL
;
778 mlxsw_sp_fib_destroy(vr
->fib6
);
780 mlxsw_sp_fib_destroy(vr
->fib4
);
784 static struct mlxsw_sp_vr
*mlxsw_sp_vr_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
,
785 struct netlink_ext_ack
*extack
)
787 struct mlxsw_sp_vr
*vr
;
789 tb_id
= mlxsw_sp_fix_tb_id(tb_id
);
790 vr
= mlxsw_sp_vr_find(mlxsw_sp
, tb_id
);
792 vr
= mlxsw_sp_vr_create(mlxsw_sp
, tb_id
, extack
);
796 static void mlxsw_sp_vr_put(struct mlxsw_sp_vr
*vr
)
798 if (!vr
->rif_count
&& list_empty(&vr
->fib4
->node_list
) &&
799 list_empty(&vr
->fib6
->node_list
) &&
800 mlxsw_sp_mr_table_empty(vr
->mr4_table
))
801 mlxsw_sp_vr_destroy(vr
);
805 mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr
*vr
,
806 enum mlxsw_sp_l3proto proto
, u8 tree_id
)
808 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
810 if (!mlxsw_sp_vr_is_used(vr
))
812 if (fib
->lpm_tree
&& fib
->lpm_tree
->id
== tree_id
)
817 static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp
*mlxsw_sp
,
818 struct mlxsw_sp_fib
*fib
,
819 struct mlxsw_sp_lpm_tree
*new_tree
)
821 struct mlxsw_sp_lpm_tree
*old_tree
= fib
->lpm_tree
;
824 err
= mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp
, fib
, new_tree
->id
);
827 fib
->lpm_tree
= new_tree
;
828 mlxsw_sp_lpm_tree_hold(new_tree
);
829 mlxsw_sp_lpm_tree_put(mlxsw_sp
, old_tree
);
833 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp
*mlxsw_sp
,
834 struct mlxsw_sp_fib
*fib
,
835 struct mlxsw_sp_lpm_tree
*new_tree
)
837 struct mlxsw_sp_lpm_tree
*old_tree
= fib
->lpm_tree
;
838 enum mlxsw_sp_l3proto proto
= fib
->proto
;
839 u8 old_id
, new_id
= new_tree
->id
;
840 struct mlxsw_sp_vr
*vr
;
845 old_id
= old_tree
->id
;
847 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
848 vr
= &mlxsw_sp
->router
->vrs
[i
];
849 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr
, proto
, old_id
))
851 err
= mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp
,
852 mlxsw_sp_vr_fib(vr
, proto
),
855 goto err_tree_replace
;
861 for (i
--; i
>= 0; i
--) {
862 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr
, proto
, new_id
))
864 mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp
,
865 mlxsw_sp_vr_fib(vr
, proto
),
871 err
= mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp
, fib
, new_tree
->id
);
874 fib
->lpm_tree
= new_tree
;
875 mlxsw_sp_lpm_tree_hold(new_tree
);
880 mlxsw_sp_vrs_prefixes(struct mlxsw_sp
*mlxsw_sp
,
881 enum mlxsw_sp_l3proto proto
,
882 struct mlxsw_sp_prefix_usage
*req_prefix_usage
)
886 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
887 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
888 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
889 unsigned char prefix
;
891 if (!mlxsw_sp_vr_is_used(vr
))
893 mlxsw_sp_prefix_usage_for_each(prefix
, &fib
->prefix_usage
)
894 mlxsw_sp_prefix_usage_set(req_prefix_usage
, prefix
);
898 static int mlxsw_sp_vrs_init(struct mlxsw_sp
*mlxsw_sp
)
900 struct mlxsw_sp_vr
*vr
;
904 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_VRS
))
907 max_vrs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
);
908 mlxsw_sp
->router
->vrs
= kcalloc(max_vrs
, sizeof(struct mlxsw_sp_vr
),
910 if (!mlxsw_sp
->router
->vrs
)
913 for (i
= 0; i
< max_vrs
; i
++) {
914 vr
= &mlxsw_sp
->router
->vrs
[i
];
921 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
);
923 static void mlxsw_sp_vrs_fini(struct mlxsw_sp
*mlxsw_sp
)
925 /* At this stage we're guaranteed not to have new incoming
926 * FIB notifications and the work queue is free from FIBs
927 * sitting on top of mlxsw netdevs. However, we can still
928 * have other FIBs queued. Flush the queue before flushing
929 * the device's tables. No need for locks, as we're the only
932 mlxsw_core_flush_owq();
933 mlxsw_sp_router_fib_flush(mlxsw_sp
);
934 kfree(mlxsw_sp
->router
->vrs
);
937 static struct net_device
*
938 __mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device
*ol_dev
)
940 struct ip_tunnel
*tun
= netdev_priv(ol_dev
);
941 struct net
*net
= dev_net(ol_dev
);
943 return __dev_get_by_index(net
, tun
->parms
.link
);
946 u32
mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device
*ol_dev
)
948 struct net_device
*d
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
951 return l3mdev_fib_table(d
) ? : RT_TABLE_MAIN
;
953 return l3mdev_fib_table(ol_dev
) ? : RT_TABLE_MAIN
;
956 static struct mlxsw_sp_rif
*
957 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
958 const struct mlxsw_sp_rif_params
*params
,
959 struct netlink_ext_ack
*extack
);
961 static struct mlxsw_sp_rif_ipip_lb
*
962 mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp
*mlxsw_sp
,
963 enum mlxsw_sp_ipip_type ipipt
,
964 struct net_device
*ol_dev
,
965 struct netlink_ext_ack
*extack
)
967 struct mlxsw_sp_rif_params_ipip_lb lb_params
;
968 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
969 struct mlxsw_sp_rif
*rif
;
971 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
972 lb_params
= (struct mlxsw_sp_rif_params_ipip_lb
) {
973 .common
.dev
= ol_dev
,
975 .lb_config
= ipip_ops
->ol_loopback_config(mlxsw_sp
, ol_dev
),
978 rif
= mlxsw_sp_rif_create(mlxsw_sp
, &lb_params
.common
, extack
);
980 return ERR_CAST(rif
);
981 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
984 static struct mlxsw_sp_ipip_entry
*
985 mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp
*mlxsw_sp
,
986 enum mlxsw_sp_ipip_type ipipt
,
987 struct net_device
*ol_dev
)
989 struct mlxsw_sp_ipip_entry
*ipip_entry
;
990 struct mlxsw_sp_ipip_entry
*ret
= NULL
;
992 ipip_entry
= kzalloc(sizeof(*ipip_entry
), GFP_KERNEL
);
994 return ERR_PTR(-ENOMEM
);
996 ipip_entry
->ol_lb
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
, ipipt
,
998 if (IS_ERR(ipip_entry
->ol_lb
)) {
999 ret
= ERR_CAST(ipip_entry
->ol_lb
);
1000 goto err_ol_ipip_lb_create
;
1003 ipip_entry
->ipipt
= ipipt
;
1004 ipip_entry
->ol_dev
= ol_dev
;
1005 ipip_entry
->parms
= mlxsw_sp_ipip_netdev_parms(ol_dev
);
1009 err_ol_ipip_lb_create
:
1015 mlxsw_sp_ipip_entry_dealloc(struct mlxsw_sp_ipip_entry
*ipip_entry
)
1017 mlxsw_sp_rif_destroy(&ipip_entry
->ol_lb
->common
);
1022 mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp
*mlxsw_sp
,
1023 const enum mlxsw_sp_l3proto ul_proto
,
1024 union mlxsw_sp_l3addr saddr
,
1026 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1028 u32 tun_ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry
->ol_dev
);
1029 enum mlxsw_sp_ipip_type ipipt
= ipip_entry
->ipipt
;
1030 union mlxsw_sp_l3addr tun_saddr
;
1032 if (mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
!= ul_proto
)
1035 tun_saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ipip_entry
->ol_dev
);
1036 return tun_ul_tb_id
== ul_tb_id
&&
1037 mlxsw_sp_l3addr_eq(&tun_saddr
, &saddr
);
1041 mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp
*mlxsw_sp
,
1042 struct mlxsw_sp_fib_entry
*fib_entry
,
1043 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1048 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, 1, &tunnel_index
);
1052 ipip_entry
->decap_fib_entry
= fib_entry
;
1053 fib_entry
->decap
.ipip_entry
= ipip_entry
;
1054 fib_entry
->decap
.tunnel_index
= tunnel_index
;
1058 static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp
*mlxsw_sp
,
1059 struct mlxsw_sp_fib_entry
*fib_entry
)
1061 /* Unlink this node from the IPIP entry that it's the decap entry of. */
1062 fib_entry
->decap
.ipip_entry
->decap_fib_entry
= NULL
;
1063 fib_entry
->decap
.ipip_entry
= NULL
;
1064 mlxsw_sp_kvdl_free(mlxsw_sp
, fib_entry
->decap
.tunnel_index
);
1067 static struct mlxsw_sp_fib_node
*
1068 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
1069 size_t addr_len
, unsigned char prefix_len
);
1070 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
1071 struct mlxsw_sp_fib_entry
*fib_entry
);
1074 mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp
*mlxsw_sp
,
1075 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1077 struct mlxsw_sp_fib_entry
*fib_entry
= ipip_entry
->decap_fib_entry
;
1079 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, fib_entry
);
1080 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
1082 mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
1086 mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp
*mlxsw_sp
,
1087 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1088 struct mlxsw_sp_fib_entry
*decap_fib_entry
)
1090 if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp
, decap_fib_entry
,
1093 decap_fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
1095 if (mlxsw_sp_fib_entry_update(mlxsw_sp
, decap_fib_entry
))
1096 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1099 /* Given an IPIP entry, find the corresponding decap route. */
1100 static struct mlxsw_sp_fib_entry
*
1101 mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp
*mlxsw_sp
,
1102 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1104 static struct mlxsw_sp_fib_node
*fib_node
;
1105 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1106 struct mlxsw_sp_fib_entry
*fib_entry
;
1107 unsigned char saddr_prefix_len
;
1108 union mlxsw_sp_l3addr saddr
;
1109 struct mlxsw_sp_fib
*ul_fib
;
1110 struct mlxsw_sp_vr
*ul_vr
;
1116 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1118 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry
->ol_dev
);
1119 ul_vr
= mlxsw_sp_vr_find(mlxsw_sp
, ul_tb_id
);
1123 ul_fib
= mlxsw_sp_vr_fib(ul_vr
, ipip_ops
->ul_proto
);
1124 saddr
= mlxsw_sp_ipip_netdev_saddr(ipip_ops
->ul_proto
,
1125 ipip_entry
->ol_dev
);
1127 switch (ipip_ops
->ul_proto
) {
1128 case MLXSW_SP_L3_PROTO_IPV4
:
1129 saddr4
= be32_to_cpu(saddr
.addr4
);
1132 saddr_prefix_len
= 32;
1134 case MLXSW_SP_L3_PROTO_IPV6
:
1139 fib_node
= mlxsw_sp_fib_node_lookup(ul_fib
, saddrp
, saddr_len
,
1141 if (!fib_node
|| list_empty(&fib_node
->entry_list
))
1144 fib_entry
= list_first_entry(&fib_node
->entry_list
,
1145 struct mlxsw_sp_fib_entry
, list
);
1146 if (fib_entry
->type
!= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
)
1152 static struct mlxsw_sp_ipip_entry
*
1153 mlxsw_sp_ipip_entry_create(struct mlxsw_sp
*mlxsw_sp
,
1154 enum mlxsw_sp_ipip_type ipipt
,
1155 struct net_device
*ol_dev
)
1157 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1159 ipip_entry
= mlxsw_sp_ipip_entry_alloc(mlxsw_sp
, ipipt
, ol_dev
);
1160 if (IS_ERR(ipip_entry
))
1163 list_add_tail(&ipip_entry
->ipip_list_node
,
1164 &mlxsw_sp
->router
->ipip_list
);
1170 mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
1171 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1173 list_del(&ipip_entry
->ipip_list_node
);
1174 mlxsw_sp_ipip_entry_dealloc(ipip_entry
);
1178 mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp
*mlxsw_sp
,
1179 const struct net_device
*ul_dev
,
1180 enum mlxsw_sp_l3proto ul_proto
,
1181 union mlxsw_sp_l3addr ul_dip
,
1182 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1184 u32 ul_tb_id
= l3mdev_fib_table(ul_dev
) ? : RT_TABLE_MAIN
;
1185 enum mlxsw_sp_ipip_type ipipt
= ipip_entry
->ipipt
;
1186 struct net_device
*ipip_ul_dev
;
1188 if (mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
!= ul_proto
)
1191 ipip_ul_dev
= __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1192 return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, ul_dip
,
1193 ul_tb_id
, ipip_entry
) &&
1194 (!ipip_ul_dev
|| ipip_ul_dev
== ul_dev
);
1197 /* Given decap parameters, find the corresponding IPIP entry. */
1198 static struct mlxsw_sp_ipip_entry
*
1199 mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp
*mlxsw_sp
,
1200 const struct net_device
*ul_dev
,
1201 enum mlxsw_sp_l3proto ul_proto
,
1202 union mlxsw_sp_l3addr ul_dip
)
1204 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1206 list_for_each_entry(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1208 if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp
, ul_dev
,
1216 static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
1217 const struct net_device
*dev
,
1218 enum mlxsw_sp_ipip_type
*p_type
)
1220 struct mlxsw_sp_router
*router
= mlxsw_sp
->router
;
1221 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1222 enum mlxsw_sp_ipip_type ipipt
;
1224 for (ipipt
= 0; ipipt
< MLXSW_SP_IPIP_TYPE_MAX
; ++ipipt
) {
1225 ipip_ops
= router
->ipip_ops_arr
[ipipt
];
1226 if (dev
->type
== ipip_ops
->dev_type
) {
1235 bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp
*mlxsw_sp
,
1236 const struct net_device
*dev
)
1238 return mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
);
1241 static struct mlxsw_sp_ipip_entry
*
1242 mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp
*mlxsw_sp
,
1243 const struct net_device
*ol_dev
)
1245 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1247 list_for_each_entry(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1249 if (ipip_entry
->ol_dev
== ol_dev
)
1255 static struct mlxsw_sp_ipip_entry
*
1256 mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp
*mlxsw_sp
,
1257 const struct net_device
*ul_dev
,
1258 struct mlxsw_sp_ipip_entry
*start
)
1260 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1262 ipip_entry
= list_prepare_entry(start
, &mlxsw_sp
->router
->ipip_list
,
1264 list_for_each_entry_continue(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1266 struct net_device
*ipip_ul_dev
=
1267 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1269 if (ipip_ul_dev
== ul_dev
)
1276 bool mlxsw_sp_netdev_is_ipip_ul(const struct mlxsw_sp
*mlxsw_sp
,
1277 const struct net_device
*dev
)
1279 return mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
, dev
, NULL
);
1282 static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp
*mlxsw_sp
,
1283 const struct net_device
*ol_dev
,
1284 enum mlxsw_sp_ipip_type ipipt
)
1286 const struct mlxsw_sp_ipip_ops
*ops
1287 = mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
1289 /* For deciding whether decap should be offloaded, we don't care about
1290 * overlay protocol, so ask whether either one is supported.
1292 return ops
->can_offload(mlxsw_sp
, ol_dev
, MLXSW_SP_L3_PROTO_IPV4
) ||
1293 ops
->can_offload(mlxsw_sp
, ol_dev
, MLXSW_SP_L3_PROTO_IPV6
);
1296 static int mlxsw_sp_netdevice_ipip_ol_reg_event(struct mlxsw_sp
*mlxsw_sp
,
1297 struct net_device
*ol_dev
)
1299 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1300 enum mlxsw_sp_l3proto ul_proto
;
1301 enum mlxsw_sp_ipip_type ipipt
;
1302 union mlxsw_sp_l3addr saddr
;
1305 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, ol_dev
, &ipipt
);
1306 if (mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
, ipipt
)) {
1307 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ol_dev
);
1308 ul_proto
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
;
1309 saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ol_dev
);
1310 if (!mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp
, ul_proto
,
1313 ipip_entry
= mlxsw_sp_ipip_entry_create(mlxsw_sp
, ipipt
,
1315 if (IS_ERR(ipip_entry
))
1316 return PTR_ERR(ipip_entry
);
1323 static void mlxsw_sp_netdevice_ipip_ol_unreg_event(struct mlxsw_sp
*mlxsw_sp
,
1324 struct net_device
*ol_dev
)
1326 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1328 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1330 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1334 mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp
*mlxsw_sp
,
1335 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1337 struct mlxsw_sp_fib_entry
*decap_fib_entry
;
1339 decap_fib_entry
= mlxsw_sp_ipip_entry_find_decap(mlxsw_sp
, ipip_entry
);
1340 if (decap_fib_entry
)
1341 mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp
, ipip_entry
,
1345 static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp
*mlxsw_sp
,
1346 struct net_device
*ol_dev
)
1348 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1350 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1352 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1356 mlxsw_sp_ipip_entry_ol_down_event(struct mlxsw_sp
*mlxsw_sp
,
1357 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1359 if (ipip_entry
->decap_fib_entry
)
1360 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1363 static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp
*mlxsw_sp
,
1364 struct net_device
*ol_dev
)
1366 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1368 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1370 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1373 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp
*mlxsw_sp
,
1374 struct mlxsw_sp_rif
*old_rif
,
1375 struct mlxsw_sp_rif
*new_rif
);
1377 mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp
*mlxsw_sp
,
1378 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1380 struct netlink_ext_ack
*extack
)
1382 struct mlxsw_sp_rif_ipip_lb
*old_lb_rif
= ipip_entry
->ol_lb
;
1383 struct mlxsw_sp_rif_ipip_lb
*new_lb_rif
;
1385 new_lb_rif
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
,
1389 if (IS_ERR(new_lb_rif
))
1390 return PTR_ERR(new_lb_rif
);
1391 ipip_entry
->ol_lb
= new_lb_rif
;
1394 mlxsw_sp_nexthop_rif_migrate(mlxsw_sp
, &old_lb_rif
->common
,
1395 &new_lb_rif
->common
);
1397 mlxsw_sp_rif_destroy(&old_lb_rif
->common
);
1402 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
1403 struct mlxsw_sp_rif
*rif
);
1406 * Update the offload related to an IPIP entry. This always updates decap, and
1407 * in addition to that it also:
1408 * @recreate_loopback: recreates the associated loopback RIF
1409 * @keep_encap: updates next hops that use the tunnel netdevice. This is only
1410 * relevant when recreate_loopback is true.
1411 * @update_nexthops: updates next hops, keeping the current loopback RIF. This
1412 * is only relevant when recreate_loopback is false.
1414 int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1415 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1416 bool recreate_loopback
,
1418 bool update_nexthops
,
1419 struct netlink_ext_ack
*extack
)
1423 /* RIFs can't be edited, so to update loopback, we need to destroy and
1424 * recreate it. That creates a window of opportunity where RALUE and
1425 * RATR registers end up referencing a RIF that's already gone. RATRs
1426 * are handled in mlxsw_sp_ipip_entry_ol_lb_update(), and to take care
1427 * of RALUE, demote the decap route back.
1429 if (ipip_entry
->decap_fib_entry
)
1430 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1432 if (recreate_loopback
) {
1433 err
= mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp
, ipip_entry
,
1434 keep_encap
, extack
);
1437 } else if (update_nexthops
) {
1438 mlxsw_sp_nexthop_rif_update(mlxsw_sp
,
1439 &ipip_entry
->ol_lb
->common
);
1442 if (ipip_entry
->ol_dev
->flags
& IFF_UP
)
1443 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1448 static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1449 struct net_device
*ol_dev
,
1450 struct netlink_ext_ack
*extack
)
1452 struct mlxsw_sp_ipip_entry
*ipip_entry
=
1453 mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1454 enum mlxsw_sp_l3proto ul_proto
;
1455 union mlxsw_sp_l3addr saddr
;
1461 /* For flat configuration cases, moving overlay to a different VRF might
1462 * cause local address conflict, and the conflicting tunnels need to be
1465 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ol_dev
);
1466 ul_proto
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
]->ul_proto
;
1467 saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ol_dev
);
1468 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp
, ul_proto
,
1471 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1475 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1476 true, false, false, extack
);
1480 mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1481 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1482 struct net_device
*ul_dev
,
1483 struct netlink_ext_ack
*extack
)
1485 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1486 true, true, false, extack
);
1490 mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp
*mlxsw_sp
,
1491 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1492 struct net_device
*ul_dev
)
1494 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1495 false, false, true, NULL
);
1499 mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp
*mlxsw_sp
,
1500 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1501 struct net_device
*ul_dev
)
1503 /* A down underlay device causes encapsulated packets to not be
1504 * forwarded, but decap still works. So refresh next hops without
1505 * touching anything else.
1507 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1508 false, false, true, NULL
);
1512 mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp
*mlxsw_sp
,
1513 struct net_device
*ol_dev
,
1514 struct netlink_ext_ack
*extack
)
1516 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1517 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1520 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1522 /* A change might make a tunnel eligible for offloading, but
1523 * that is currently not implemented. What falls to slow path
1528 /* A change might make a tunnel not eligible for offloading. */
1529 if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
,
1530 ipip_entry
->ipipt
)) {
1531 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1535 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1536 err
= ipip_ops
->ol_netdev_change(mlxsw_sp
, ipip_entry
, extack
);
1540 void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1541 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1543 struct net_device
*ol_dev
= ipip_entry
->ol_dev
;
1545 if (ol_dev
->flags
& IFF_UP
)
1546 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1547 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1550 /* The configuration where several tunnels have the same local address in the
1551 * same underlay table needs special treatment in the HW. That is currently not
1552 * implemented in the driver. This function finds and demotes the first tunnel
1553 * with a given source address, except the one passed in in the argument
1557 mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp
*mlxsw_sp
,
1558 enum mlxsw_sp_l3proto ul_proto
,
1559 union mlxsw_sp_l3addr saddr
,
1561 const struct mlxsw_sp_ipip_entry
*except
)
1563 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1565 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1567 if (ipip_entry
!= except
&&
1568 mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, saddr
,
1569 ul_tb_id
, ipip_entry
)) {
1570 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1578 static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp
*mlxsw_sp
,
1579 struct net_device
*ul_dev
)
1581 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1583 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1585 struct net_device
*ipip_ul_dev
=
1586 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1588 if (ipip_ul_dev
== ul_dev
)
1589 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1593 int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp
*mlxsw_sp
,
1594 struct net_device
*ol_dev
,
1595 unsigned long event
,
1596 struct netdev_notifier_info
*info
)
1598 struct netdev_notifier_changeupper_info
*chup
;
1599 struct netlink_ext_ack
*extack
;
1602 case NETDEV_REGISTER
:
1603 return mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp
, ol_dev
);
1604 case NETDEV_UNREGISTER
:
1605 mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp
, ol_dev
);
1608 mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp
, ol_dev
);
1611 mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp
, ol_dev
);
1613 case NETDEV_CHANGEUPPER
:
1614 chup
= container_of(info
, typeof(*chup
), info
);
1615 extack
= info
->extack
;
1616 if (netif_is_l3_master(chup
->upper_dev
))
1617 return mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp
,
1622 extack
= info
->extack
;
1623 return mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp
,
1630 __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1631 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1632 struct net_device
*ul_dev
,
1633 unsigned long event
,
1634 struct netdev_notifier_info
*info
)
1636 struct netdev_notifier_changeupper_info
*chup
;
1637 struct netlink_ext_ack
*extack
;
1640 case NETDEV_CHANGEUPPER
:
1641 chup
= container_of(info
, typeof(*chup
), info
);
1642 extack
= info
->extack
;
1643 if (netif_is_l3_master(chup
->upper_dev
))
1644 return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp
,
1651 return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp
, ipip_entry
,
1654 return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp
,
1662 mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1663 struct net_device
*ul_dev
,
1664 unsigned long event
,
1665 struct netdev_notifier_info
*info
)
1667 struct mlxsw_sp_ipip_entry
*ipip_entry
= NULL
;
1670 while ((ipip_entry
= mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
,
1673 err
= __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp
, ipip_entry
,
1674 ul_dev
, event
, info
);
1676 mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp
,
1685 struct mlxsw_sp_neigh_key
{
1686 struct neighbour
*n
;
1689 struct mlxsw_sp_neigh_entry
{
1690 struct list_head rif_list_node
;
1691 struct rhash_head ht_node
;
1692 struct mlxsw_sp_neigh_key key
;
1695 unsigned char ha
[ETH_ALEN
];
1696 struct list_head nexthop_list
; /* list of nexthops using
1699 struct list_head nexthop_neighs_list_node
;
1700 unsigned int counter_index
;
1704 static const struct rhashtable_params mlxsw_sp_neigh_ht_params
= {
1705 .key_offset
= offsetof(struct mlxsw_sp_neigh_entry
, key
),
1706 .head_offset
= offsetof(struct mlxsw_sp_neigh_entry
, ht_node
),
1707 .key_len
= sizeof(struct mlxsw_sp_neigh_key
),
1710 struct mlxsw_sp_neigh_entry
*
1711 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif
*rif
,
1712 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1715 if (list_empty(&rif
->neigh_list
))
1718 return list_first_entry(&rif
->neigh_list
,
1719 typeof(*neigh_entry
),
1722 if (list_is_last(&neigh_entry
->rif_list_node
, &rif
->neigh_list
))
1724 return list_next_entry(neigh_entry
, rif_list_node
);
1727 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1729 return neigh_entry
->key
.n
->tbl
->family
;
1733 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1735 return neigh_entry
->ha
;
1738 u32
mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1740 struct neighbour
*n
;
1742 n
= neigh_entry
->key
.n
;
1743 return ntohl(*((__be32
*) n
->primary_key
));
1747 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1749 struct neighbour
*n
;
1751 n
= neigh_entry
->key
.n
;
1752 return (struct in6_addr
*) &n
->primary_key
;
1755 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp
*mlxsw_sp
,
1756 struct mlxsw_sp_neigh_entry
*neigh_entry
,
1759 if (!neigh_entry
->counter_valid
)
1762 return mlxsw_sp_flow_counter_get(mlxsw_sp
, neigh_entry
->counter_index
,
1766 static struct mlxsw_sp_neigh_entry
*
1767 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
,
1770 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1772 neigh_entry
= kzalloc(sizeof(*neigh_entry
), GFP_KERNEL
);
1776 neigh_entry
->key
.n
= n
;
1777 neigh_entry
->rif
= rif
;
1778 INIT_LIST_HEAD(&neigh_entry
->nexthop_list
);
1783 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1789 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp
*mlxsw_sp
,
1790 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1792 return rhashtable_insert_fast(&mlxsw_sp
->router
->neigh_ht
,
1793 &neigh_entry
->ht_node
,
1794 mlxsw_sp_neigh_ht_params
);
1798 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp
*mlxsw_sp
,
1799 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1801 rhashtable_remove_fast(&mlxsw_sp
->router
->neigh_ht
,
1802 &neigh_entry
->ht_node
,
1803 mlxsw_sp_neigh_ht_params
);
1807 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp
*mlxsw_sp
,
1808 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1810 struct devlink
*devlink
;
1811 const char *table_name
;
1813 switch (mlxsw_sp_neigh_entry_type(neigh_entry
)) {
1815 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST4
;
1818 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST6
;
1825 devlink
= priv_to_devlink(mlxsw_sp
->core
);
1826 return devlink_dpipe_table_counter_enabled(devlink
, table_name
);
1830 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
1831 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1833 if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp
, neigh_entry
))
1836 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &neigh_entry
->counter_index
))
1839 neigh_entry
->counter_valid
= true;
1843 mlxsw_sp_neigh_counter_free(struct mlxsw_sp
*mlxsw_sp
,
1844 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1846 if (!neigh_entry
->counter_valid
)
1848 mlxsw_sp_flow_counter_free(mlxsw_sp
,
1849 neigh_entry
->counter_index
);
1850 neigh_entry
->counter_valid
= false;
1853 static struct mlxsw_sp_neigh_entry
*
1854 mlxsw_sp_neigh_entry_create(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
1856 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1857 struct mlxsw_sp_rif
*rif
;
1860 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, n
->dev
);
1862 return ERR_PTR(-EINVAL
);
1864 neigh_entry
= mlxsw_sp_neigh_entry_alloc(mlxsw_sp
, n
, rif
->rif_index
);
1866 return ERR_PTR(-ENOMEM
);
1868 err
= mlxsw_sp_neigh_entry_insert(mlxsw_sp
, neigh_entry
);
1870 goto err_neigh_entry_insert
;
1872 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
1873 list_add(&neigh_entry
->rif_list_node
, &rif
->neigh_list
);
1877 err_neigh_entry_insert
:
1878 mlxsw_sp_neigh_entry_free(neigh_entry
);
1879 return ERR_PTR(err
);
1883 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
1884 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1886 list_del(&neigh_entry
->rif_list_node
);
1887 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
1888 mlxsw_sp_neigh_entry_remove(mlxsw_sp
, neigh_entry
);
1889 mlxsw_sp_neigh_entry_free(neigh_entry
);
1892 static struct mlxsw_sp_neigh_entry
*
1893 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
1895 struct mlxsw_sp_neigh_key key
;
1898 return rhashtable_lookup_fast(&mlxsw_sp
->router
->neigh_ht
,
1899 &key
, mlxsw_sp_neigh_ht_params
);
1903 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp
*mlxsw_sp
)
1905 unsigned long interval
;
1907 #if IS_ENABLED(CONFIG_IPV6)
1908 interval
= min_t(unsigned long,
1909 NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
),
1910 NEIGH_VAR(&nd_tbl
.parms
, DELAY_PROBE_TIME
));
1912 interval
= NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
);
1914 mlxsw_sp
->router
->neighs_update
.interval
= jiffies_to_msecs(interval
);
1917 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
1921 struct net_device
*dev
;
1922 struct neighbour
*n
;
1927 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl
, ent_index
, &rif
, &dip
);
1929 if (!mlxsw_sp
->router
->rifs
[rif
]) {
1930 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
1935 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
1936 n
= neigh_lookup(&arp_tbl
, &dipn
, dev
);
1938 netdev_err(dev
, "Failed to find matching neighbour for IP=%pI4h\n",
1943 netdev_dbg(dev
, "Updating neighbour with IP=%pI4h\n", &dip
);
1944 neigh_event_send(n
, NULL
);
1948 #if IS_ENABLED(CONFIG_IPV6)
1949 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1953 struct net_device
*dev
;
1954 struct neighbour
*n
;
1955 struct in6_addr dip
;
1958 mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl
, rec_index
, &rif
,
1961 if (!mlxsw_sp
->router
->rifs
[rif
]) {
1962 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
1966 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
1967 n
= neigh_lookup(&nd_tbl
, &dip
, dev
);
1969 netdev_err(dev
, "Failed to find matching neighbour for IP=%pI6c\n",
1974 netdev_dbg(dev
, "Updating neighbour with IP=%pI6c\n", &dip
);
1975 neigh_event_send(n
, NULL
);
1979 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1986 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
1993 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
1995 /* Hardware starts counting at 0, so add 1. */
1998 /* Each record consists of several neighbour entries. */
1999 for (i
= 0; i
< num_entries
; i
++) {
2002 ent_index
= rec_index
* MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
+ i
;
2003 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2009 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
2013 /* One record contains one entry. */
2014 mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2018 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp
*mlxsw_sp
,
2019 char *rauhtd_pl
, int rec_index
)
2021 switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, rec_index
)) {
2022 case MLXSW_REG_RAUHTD_TYPE_IPV4
:
2023 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2026 case MLXSW_REG_RAUHTD_TYPE_IPV6
:
2027 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2033 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl
)
2035 u8 num_rec
, last_rec_index
, num_entries
;
2037 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2038 last_rec_index
= num_rec
- 1;
2040 if (num_rec
< MLXSW_REG_RAUHTD_REC_MAX_NUM
)
2042 if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, last_rec_index
) ==
2043 MLXSW_REG_RAUHTD_TYPE_IPV6
)
2046 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
2048 if (++num_entries
== MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
)
2054 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
,
2056 enum mlxsw_reg_rauhtd_type type
)
2061 /* Make sure the neighbour's netdev isn't removed in the
2066 mlxsw_reg_rauhtd_pack(rauhtd_pl
, type
);
2067 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(rauhtd
),
2070 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Failed to dump neighbour table\n");
2073 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2074 for (i
= 0; i
< num_rec
; i
++)
2075 mlxsw_sp_router_neigh_rec_process(mlxsw_sp
, rauhtd_pl
,
2077 } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl
));
2083 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
)
2085 enum mlxsw_reg_rauhtd_type type
;
2089 rauhtd_pl
= kmalloc(MLXSW_REG_RAUHTD_LEN
, GFP_KERNEL
);
2093 type
= MLXSW_REG_RAUHTD_TYPE_IPV4
;
2094 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2098 type
= MLXSW_REG_RAUHTD_TYPE_IPV6
;
2099 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2105 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp
*mlxsw_sp
)
2107 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2109 /* Take RTNL mutex here to prevent lists from changes */
2111 list_for_each_entry(neigh_entry
, &mlxsw_sp
->router
->nexthop_neighs_list
,
2112 nexthop_neighs_list_node
)
2113 /* If this neigh have nexthops, make the kernel think this neigh
2114 * is active regardless of the traffic.
2116 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2121 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp
*mlxsw_sp
)
2123 unsigned long interval
= mlxsw_sp
->router
->neighs_update
.interval
;
2125 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
,
2126 msecs_to_jiffies(interval
));
2129 static void mlxsw_sp_router_neighs_update_work(struct work_struct
*work
)
2131 struct mlxsw_sp_router
*router
;
2134 router
= container_of(work
, struct mlxsw_sp_router
,
2135 neighs_update
.dw
.work
);
2136 err
= mlxsw_sp_router_neighs_update_rauhtd(router
->mlxsw_sp
);
2138 dev_err(router
->mlxsw_sp
->bus_info
->dev
, "Could not update kernel for neigh activity");
2140 mlxsw_sp_router_neighs_update_nh(router
->mlxsw_sp
);
2142 mlxsw_sp_router_neighs_update_work_schedule(router
->mlxsw_sp
);
2145 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct
*work
)
2147 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2148 struct mlxsw_sp_router
*router
;
2150 router
= container_of(work
, struct mlxsw_sp_router
,
2151 nexthop_probe_dw
.work
);
2152 /* Iterate over nexthop neighbours, find those who are unresolved and
2153 * send arp on them. This solves the chicken-egg problem when
2154 * the nexthop wouldn't get offloaded until the neighbor is resolved
2155 * but it wouldn't get resolved ever in case traffic is flowing in HW
2156 * using different nexthop.
2158 * Take RTNL mutex here to prevent lists from changes.
2161 list_for_each_entry(neigh_entry
, &router
->nexthop_neighs_list
,
2162 nexthop_neighs_list_node
)
2163 if (!neigh_entry
->connected
)
2164 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2167 mlxsw_core_schedule_dw(&router
->nexthop_probe_dw
,
2168 MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL
);
2172 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
2173 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2176 static enum mlxsw_reg_rauht_op
mlxsw_sp_rauht_op(bool adding
)
2178 return adding
? MLXSW_REG_RAUHT_OP_WRITE_ADD
:
2179 MLXSW_REG_RAUHT_OP_WRITE_DELETE
;
2183 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp
*mlxsw_sp
,
2184 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2185 enum mlxsw_reg_rauht_op op
)
2187 struct neighbour
*n
= neigh_entry
->key
.n
;
2188 u32 dip
= ntohl(*((__be32
*) n
->primary_key
));
2189 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2191 mlxsw_reg_rauht_pack4(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2193 if (neigh_entry
->counter_valid
)
2194 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2195 neigh_entry
->counter_index
);
2196 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2200 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp
*mlxsw_sp
,
2201 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2202 enum mlxsw_reg_rauht_op op
)
2204 struct neighbour
*n
= neigh_entry
->key
.n
;
2205 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2206 const char *dip
= n
->primary_key
;
2208 mlxsw_reg_rauht_pack6(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2210 if (neigh_entry
->counter_valid
)
2211 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2212 neigh_entry
->counter_index
);
2213 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2216 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry
*neigh_entry
)
2218 struct neighbour
*n
= neigh_entry
->key
.n
;
2220 /* Packets with a link-local destination address are trapped
2221 * after LPM lookup and never reach the neighbour table, so
2222 * there is no need to program such neighbours to the device.
2224 if (ipv6_addr_type((struct in6_addr
*) &n
->primary_key
) &
2225 IPV6_ADDR_LINKLOCAL
)
2231 mlxsw_sp_neigh_entry_update(struct mlxsw_sp
*mlxsw_sp
,
2232 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2235 if (!adding
&& !neigh_entry
->connected
)
2237 neigh_entry
->connected
= adding
;
2238 if (neigh_entry
->key
.n
->tbl
->family
== AF_INET
) {
2239 mlxsw_sp_router_neigh_entry_op4(mlxsw_sp
, neigh_entry
,
2240 mlxsw_sp_rauht_op(adding
));
2241 } else if (neigh_entry
->key
.n
->tbl
->family
== AF_INET6
) {
2242 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
2244 mlxsw_sp_router_neigh_entry_op6(mlxsw_sp
, neigh_entry
,
2245 mlxsw_sp_rauht_op(adding
));
2252 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp
*mlxsw_sp
,
2253 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2257 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
2259 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
2260 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, true);
2263 struct mlxsw_sp_netevent_work
{
2264 struct work_struct work
;
2265 struct mlxsw_sp
*mlxsw_sp
;
2266 struct neighbour
*n
;
2269 static void mlxsw_sp_router_neigh_event_work(struct work_struct
*work
)
2271 struct mlxsw_sp_netevent_work
*net_work
=
2272 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2273 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2274 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2275 struct neighbour
*n
= net_work
->n
;
2276 unsigned char ha
[ETH_ALEN
];
2277 bool entry_connected
;
2280 /* If these parameters are changed after we release the lock,
2281 * then we are guaranteed to receive another event letting us
2284 read_lock_bh(&n
->lock
);
2285 memcpy(ha
, n
->ha
, ETH_ALEN
);
2286 nud_state
= n
->nud_state
;
2288 read_unlock_bh(&n
->lock
);
2291 entry_connected
= nud_state
& NUD_VALID
&& !dead
;
2292 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
2293 if (!entry_connected
&& !neigh_entry
)
2296 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
2297 if (IS_ERR(neigh_entry
))
2301 memcpy(neigh_entry
->ha
, ha
, ETH_ALEN
);
2302 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, entry_connected
);
2303 mlxsw_sp_nexthop_neigh_update(mlxsw_sp
, neigh_entry
, !entry_connected
);
2305 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
2306 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2314 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
);
2316 static void mlxsw_sp_router_mp_hash_event_work(struct work_struct
*work
)
2318 struct mlxsw_sp_netevent_work
*net_work
=
2319 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2320 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2322 mlxsw_sp_mp_hash_init(mlxsw_sp
);
2326 static int mlxsw_sp_router_netevent_event(struct notifier_block
*nb
,
2327 unsigned long event
, void *ptr
)
2329 struct mlxsw_sp_netevent_work
*net_work
;
2330 struct mlxsw_sp_port
*mlxsw_sp_port
;
2331 struct mlxsw_sp_router
*router
;
2332 struct mlxsw_sp
*mlxsw_sp
;
2333 unsigned long interval
;
2334 struct neigh_parms
*p
;
2335 struct neighbour
*n
;
2339 case NETEVENT_DELAY_PROBE_TIME_UPDATE
:
2342 /* We don't care about changes in the default table. */
2343 if (!p
->dev
|| (p
->tbl
->family
!= AF_INET
&&
2344 p
->tbl
->family
!= AF_INET6
))
2347 /* We are in atomic context and can't take RTNL mutex,
2348 * so use RCU variant to walk the device chain.
2350 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(p
->dev
);
2354 mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2355 interval
= jiffies_to_msecs(NEIGH_VAR(p
, DELAY_PROBE_TIME
));
2356 mlxsw_sp
->router
->neighs_update
.interval
= interval
;
2358 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2360 case NETEVENT_NEIGH_UPDATE
:
2363 if (n
->tbl
->family
!= AF_INET
&& n
->tbl
->family
!= AF_INET6
)
2366 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(n
->dev
);
2370 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2372 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2376 INIT_WORK(&net_work
->work
, mlxsw_sp_router_neigh_event_work
);
2377 net_work
->mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2380 /* Take a reference to ensure the neighbour won't be
2381 * destructed until we drop the reference in delayed
2385 mlxsw_core_schedule_work(&net_work
->work
);
2386 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2388 case NETEVENT_MULTIPATH_HASH_UPDATE
:
2391 if (!net_eq(net
, &init_net
))
2394 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2398 router
= container_of(nb
, struct mlxsw_sp_router
, netevent_nb
);
2399 INIT_WORK(&net_work
->work
, mlxsw_sp_router_mp_hash_event_work
);
2400 net_work
->mlxsw_sp
= router
->mlxsw_sp
;
2401 mlxsw_core_schedule_work(&net_work
->work
);
2408 static int mlxsw_sp_neigh_init(struct mlxsw_sp
*mlxsw_sp
)
2412 err
= rhashtable_init(&mlxsw_sp
->router
->neigh_ht
,
2413 &mlxsw_sp_neigh_ht_params
);
2417 /* Initialize the polling interval according to the default
2420 mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp
);
2422 /* Create the delayed works for the activity_update */
2423 INIT_DELAYED_WORK(&mlxsw_sp
->router
->neighs_update
.dw
,
2424 mlxsw_sp_router_neighs_update_work
);
2425 INIT_DELAYED_WORK(&mlxsw_sp
->router
->nexthop_probe_dw
,
2426 mlxsw_sp_router_probe_unresolved_nexthops
);
2427 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
, 0);
2428 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->nexthop_probe_dw
, 0);
2432 static void mlxsw_sp_neigh_fini(struct mlxsw_sp
*mlxsw_sp
)
2434 cancel_delayed_work_sync(&mlxsw_sp
->router
->neighs_update
.dw
);
2435 cancel_delayed_work_sync(&mlxsw_sp
->router
->nexthop_probe_dw
);
2436 rhashtable_destroy(&mlxsw_sp
->router
->neigh_ht
);
2439 static int mlxsw_sp_neigh_rif_flush(struct mlxsw_sp
*mlxsw_sp
,
2440 const struct mlxsw_sp_rif
*rif
)
2442 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2444 mlxsw_reg_rauht_pack(rauht_pl
, MLXSW_REG_RAUHT_OP_WRITE_DELETE_ALL
,
2445 rif
->rif_index
, rif
->addr
);
2446 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2449 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
2450 struct mlxsw_sp_rif
*rif
)
2452 struct mlxsw_sp_neigh_entry
*neigh_entry
, *tmp
;
2454 mlxsw_sp_neigh_rif_flush(mlxsw_sp
, rif
);
2455 list_for_each_entry_safe(neigh_entry
, tmp
, &rif
->neigh_list
,
2457 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2460 enum mlxsw_sp_nexthop_type
{
2461 MLXSW_SP_NEXTHOP_TYPE_ETH
,
2462 MLXSW_SP_NEXTHOP_TYPE_IPIP
,
2465 struct mlxsw_sp_nexthop_key
{
2466 struct fib_nh
*fib_nh
;
2469 struct mlxsw_sp_nexthop
{
2470 struct list_head neigh_list_node
; /* member of neigh entry list */
2471 struct list_head rif_list_node
;
2472 struct list_head router_list_node
;
2473 struct mlxsw_sp_nexthop_group
*nh_grp
; /* pointer back to the group
2476 struct rhash_head ht_node
;
2477 struct mlxsw_sp_nexthop_key key
;
2478 unsigned char gw_addr
[sizeof(struct in6_addr
)];
2482 int num_adj_entries
;
2483 struct mlxsw_sp_rif
*rif
;
2484 u8 should_offload
:1, /* set indicates this neigh is connected and
2485 * should be put to KVD linear area of this group.
2487 offloaded
:1, /* set in case the neigh is actually put into
2488 * KVD linear area of this group.
2490 update
:1; /* set indicates that MAC of this neigh should be
2493 enum mlxsw_sp_nexthop_type type
;
2495 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2496 struct mlxsw_sp_ipip_entry
*ipip_entry
;
2498 unsigned int counter_index
;
2502 struct mlxsw_sp_nexthop_group
{
2504 struct rhash_head ht_node
;
2505 struct list_head fib_list
; /* list of fib entries that use this group */
2506 struct neigh_table
*neigh_tbl
;
2507 u8 adj_index_valid
:1,
2508 gateway
:1; /* routes using the group use a gateway */
2512 int sum_norm_weight
;
2513 struct mlxsw_sp_nexthop nexthops
[0];
2514 #define nh_rif nexthops[0].rif
2517 void mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
2518 struct mlxsw_sp_nexthop
*nh
)
2520 struct devlink
*devlink
;
2522 devlink
= priv_to_devlink(mlxsw_sp
->core
);
2523 if (!devlink_dpipe_table_counter_enabled(devlink
,
2524 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
))
2527 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &nh
->counter_index
))
2530 nh
->counter_valid
= true;
2533 void mlxsw_sp_nexthop_counter_free(struct mlxsw_sp
*mlxsw_sp
,
2534 struct mlxsw_sp_nexthop
*nh
)
2536 if (!nh
->counter_valid
)
2538 mlxsw_sp_flow_counter_free(mlxsw_sp
, nh
->counter_index
);
2539 nh
->counter_valid
= false;
2542 int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp
*mlxsw_sp
,
2543 struct mlxsw_sp_nexthop
*nh
, u64
*p_counter
)
2545 if (!nh
->counter_valid
)
2548 return mlxsw_sp_flow_counter_get(mlxsw_sp
, nh
->counter_index
,
2552 struct mlxsw_sp_nexthop
*mlxsw_sp_nexthop_next(struct mlxsw_sp_router
*router
,
2553 struct mlxsw_sp_nexthop
*nh
)
2556 if (list_empty(&router
->nexthop_list
))
2559 return list_first_entry(&router
->nexthop_list
,
2560 typeof(*nh
), router_list_node
);
2562 if (list_is_last(&nh
->router_list_node
, &router
->nexthop_list
))
2564 return list_next_entry(nh
, router_list_node
);
2567 bool mlxsw_sp_nexthop_offload(struct mlxsw_sp_nexthop
*nh
)
2569 return nh
->offloaded
;
2572 unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop
*nh
)
2576 return nh
->neigh_entry
->ha
;
2579 int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop
*nh
, u32
*p_adj_index
,
2580 u32
*p_adj_size
, u32
*p_adj_hash_index
)
2582 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2583 u32 adj_hash_index
= 0;
2586 if (!nh
->offloaded
|| !nh_grp
->adj_index_valid
)
2589 *p_adj_index
= nh_grp
->adj_index
;
2590 *p_adj_size
= nh_grp
->ecmp_size
;
2592 for (i
= 0; i
< nh_grp
->count
; i
++) {
2593 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2597 if (nh_iter
->offloaded
)
2598 adj_hash_index
+= nh_iter
->num_adj_entries
;
2601 *p_adj_hash_index
= adj_hash_index
;
2605 struct mlxsw_sp_rif
*mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop
*nh
)
2610 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop
*nh
)
2612 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2615 for (i
= 0; i
< nh_grp
->count
; i
++) {
2616 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2618 if (nh_iter
->type
== MLXSW_SP_NEXTHOP_TYPE_IPIP
)
2624 static struct fib_info
*
2625 mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2627 return nh_grp
->priv
;
2630 struct mlxsw_sp_nexthop_group_cmp_arg
{
2631 enum mlxsw_sp_l3proto proto
;
2633 struct fib_info
*fi
;
2634 struct mlxsw_sp_fib6_entry
*fib6_entry
;
2639 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2640 const struct in6_addr
*gw
, int ifindex
)
2644 for (i
= 0; i
< nh_grp
->count
; i
++) {
2645 const struct mlxsw_sp_nexthop
*nh
;
2647 nh
= &nh_grp
->nexthops
[i
];
2648 if (nh
->ifindex
== ifindex
&&
2649 ipv6_addr_equal(gw
, (struct in6_addr
*) nh
->gw_addr
))
2657 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2658 const struct mlxsw_sp_fib6_entry
*fib6_entry
)
2660 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2662 if (nh_grp
->count
!= fib6_entry
->nrt6
)
2665 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2666 struct in6_addr
*gw
;
2669 ifindex
= mlxsw_sp_rt6
->rt
->dst
.dev
->ifindex
;
2670 gw
= &mlxsw_sp_rt6
->rt
->rt6i_gateway
;
2671 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp
, gw
, ifindex
))
2679 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg
*arg
, const void *ptr
)
2681 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= arg
->key
;
2682 const struct mlxsw_sp_nexthop_group
*nh_grp
= ptr
;
2684 switch (cmp_arg
->proto
) {
2685 case MLXSW_SP_L3_PROTO_IPV4
:
2686 return cmp_arg
->fi
!= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2687 case MLXSW_SP_L3_PROTO_IPV6
:
2688 return !mlxsw_sp_nexthop6_group_cmp(nh_grp
,
2689 cmp_arg
->fib6_entry
);
2697 mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2699 return nh_grp
->neigh_tbl
->family
;
2702 static u32
mlxsw_sp_nexthop_group_hash_obj(const void *data
, u32 len
, u32 seed
)
2704 const struct mlxsw_sp_nexthop_group
*nh_grp
= data
;
2705 const struct mlxsw_sp_nexthop
*nh
;
2706 struct fib_info
*fi
;
2710 switch (mlxsw_sp_nexthop_group_type(nh_grp
)) {
2712 fi
= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2713 return jhash(&fi
, sizeof(fi
), seed
);
2715 val
= nh_grp
->count
;
2716 for (i
= 0; i
< nh_grp
->count
; i
++) {
2717 nh
= &nh_grp
->nexthops
[i
];
2720 return jhash(&val
, sizeof(val
), seed
);
2728 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry
*fib6_entry
, u32 seed
)
2730 unsigned int val
= fib6_entry
->nrt6
;
2731 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2732 struct net_device
*dev
;
2734 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2735 dev
= mlxsw_sp_rt6
->rt
->dst
.dev
;
2736 val
^= dev
->ifindex
;
2739 return jhash(&val
, sizeof(val
), seed
);
2743 mlxsw_sp_nexthop_group_hash(const void *data
, u32 len
, u32 seed
)
2745 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= data
;
2747 switch (cmp_arg
->proto
) {
2748 case MLXSW_SP_L3_PROTO_IPV4
:
2749 return jhash(&cmp_arg
->fi
, sizeof(cmp_arg
->fi
), seed
);
2750 case MLXSW_SP_L3_PROTO_IPV6
:
2751 return mlxsw_sp_nexthop6_group_hash(cmp_arg
->fib6_entry
, seed
);
2758 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params
= {
2759 .head_offset
= offsetof(struct mlxsw_sp_nexthop_group
, ht_node
),
2760 .hashfn
= mlxsw_sp_nexthop_group_hash
,
2761 .obj_hashfn
= mlxsw_sp_nexthop_group_hash_obj
,
2762 .obj_cmpfn
= mlxsw_sp_nexthop_group_cmp
,
2765 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp
*mlxsw_sp
,
2766 struct mlxsw_sp_nexthop_group
*nh_grp
)
2768 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
2772 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2774 mlxsw_sp_nexthop_group_ht_params
);
2777 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp
*mlxsw_sp
,
2778 struct mlxsw_sp_nexthop_group
*nh_grp
)
2780 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
2784 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2786 mlxsw_sp_nexthop_group_ht_params
);
2789 static struct mlxsw_sp_nexthop_group
*
2790 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
2791 struct fib_info
*fi
)
2793 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
2795 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV4
;
2797 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2799 mlxsw_sp_nexthop_group_ht_params
);
2802 static struct mlxsw_sp_nexthop_group
*
2803 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
2804 struct mlxsw_sp_fib6_entry
*fib6_entry
)
2806 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
2808 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV6
;
2809 cmp_arg
.fib6_entry
= fib6_entry
;
2810 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2812 mlxsw_sp_nexthop_group_ht_params
);
2815 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params
= {
2816 .key_offset
= offsetof(struct mlxsw_sp_nexthop
, key
),
2817 .head_offset
= offsetof(struct mlxsw_sp_nexthop
, ht_node
),
2818 .key_len
= sizeof(struct mlxsw_sp_nexthop_key
),
2821 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp
*mlxsw_sp
,
2822 struct mlxsw_sp_nexthop
*nh
)
2824 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_ht
,
2825 &nh
->ht_node
, mlxsw_sp_nexthop_ht_params
);
2828 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp
*mlxsw_sp
,
2829 struct mlxsw_sp_nexthop
*nh
)
2831 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_ht
, &nh
->ht_node
,
2832 mlxsw_sp_nexthop_ht_params
);
2835 static struct mlxsw_sp_nexthop
*
2836 mlxsw_sp_nexthop_lookup(struct mlxsw_sp
*mlxsw_sp
,
2837 struct mlxsw_sp_nexthop_key key
)
2839 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_ht
, &key
,
2840 mlxsw_sp_nexthop_ht_params
);
2843 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp
*mlxsw_sp
,
2844 const struct mlxsw_sp_fib
*fib
,
2845 u32 adj_index
, u16 ecmp_size
,
2849 char raleu_pl
[MLXSW_REG_RALEU_LEN
];
2851 mlxsw_reg_raleu_pack(raleu_pl
,
2852 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
,
2853 fib
->vr
->id
, adj_index
, ecmp_size
, new_adj_index
,
2855 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raleu
), raleu_pl
);
2858 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp
*mlxsw_sp
,
2859 struct mlxsw_sp_nexthop_group
*nh_grp
,
2860 u32 old_adj_index
, u16 old_ecmp_size
)
2862 struct mlxsw_sp_fib_entry
*fib_entry
;
2863 struct mlxsw_sp_fib
*fib
= NULL
;
2866 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2867 if (fib
== fib_entry
->fib_node
->fib
)
2869 fib
= fib_entry
->fib_node
->fib
;
2870 err
= mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp
, fib
,
2881 static int __mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
2882 struct mlxsw_sp_nexthop
*nh
)
2884 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
2885 char ratr_pl
[MLXSW_REG_RATR_LEN
];
2887 mlxsw_reg_ratr_pack(ratr_pl
, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY
,
2888 true, MLXSW_REG_RATR_TYPE_ETHERNET
,
2889 adj_index
, neigh_entry
->rif
);
2890 mlxsw_reg_ratr_eth_entry_pack(ratr_pl
, neigh_entry
->ha
);
2891 if (nh
->counter_valid
)
2892 mlxsw_reg_ratr_counter_pack(ratr_pl
, nh
->counter_index
, true);
2894 mlxsw_reg_ratr_counter_pack(ratr_pl
, 0, false);
2896 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ratr
), ratr_pl
);
2899 int mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
2900 struct mlxsw_sp_nexthop
*nh
)
2904 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
2907 err
= __mlxsw_sp_nexthop_update(mlxsw_sp
, adj_index
+ i
, nh
);
2915 static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
2917 struct mlxsw_sp_nexthop
*nh
)
2919 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
2921 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[nh
->ipip_entry
->ipipt
];
2922 return ipip_ops
->nexthop_update(mlxsw_sp
, adj_index
, nh
->ipip_entry
);
2925 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
2927 struct mlxsw_sp_nexthop
*nh
)
2931 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
2934 err
= __mlxsw_sp_nexthop_ipip_update(mlxsw_sp
, adj_index
+ i
,
2944 mlxsw_sp_nexthop_group_update(struct mlxsw_sp
*mlxsw_sp
,
2945 struct mlxsw_sp_nexthop_group
*nh_grp
,
2948 u32 adj_index
= nh_grp
->adj_index
; /* base */
2949 struct mlxsw_sp_nexthop
*nh
;
2953 for (i
= 0; i
< nh_grp
->count
; i
++) {
2954 nh
= &nh_grp
->nexthops
[i
];
2956 if (!nh
->should_offload
) {
2961 if (nh
->update
|| reallocate
) {
2963 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
2964 err
= mlxsw_sp_nexthop_update
2965 (mlxsw_sp
, adj_index
, nh
);
2967 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
2968 err
= mlxsw_sp_nexthop_ipip_update
2969 (mlxsw_sp
, adj_index
, nh
);
2977 adj_index
+= nh
->num_adj_entries
;
2983 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
2984 const struct mlxsw_sp_fib_entry
*fib_entry
);
2987 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp
*mlxsw_sp
,
2988 struct mlxsw_sp_nexthop_group
*nh_grp
)
2990 struct mlxsw_sp_fib_entry
*fib_entry
;
2993 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2994 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
2997 err
= mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
3005 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
3006 enum mlxsw_reg_ralue_op op
, int err
);
3009 mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group
*nh_grp
)
3011 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_WRITE
;
3012 struct mlxsw_sp_fib_entry
*fib_entry
;
3014 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
3015 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
3018 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
3022 static void mlxsw_sp_adj_grp_size_round_up(u16
*p_adj_grp_size
)
3024 /* Valid sizes for an adjacency group are:
3025 * 1-64, 512, 1024, 2048 and 4096.
3027 if (*p_adj_grp_size
<= 64)
3029 else if (*p_adj_grp_size
<= 512)
3030 *p_adj_grp_size
= 512;
3031 else if (*p_adj_grp_size
<= 1024)
3032 *p_adj_grp_size
= 1024;
3033 else if (*p_adj_grp_size
<= 2048)
3034 *p_adj_grp_size
= 2048;
3036 *p_adj_grp_size
= 4096;
3039 static void mlxsw_sp_adj_grp_size_round_down(u16
*p_adj_grp_size
,
3040 unsigned int alloc_size
)
3042 if (alloc_size
>= 4096)
3043 *p_adj_grp_size
= 4096;
3044 else if (alloc_size
>= 2048)
3045 *p_adj_grp_size
= 2048;
3046 else if (alloc_size
>= 1024)
3047 *p_adj_grp_size
= 1024;
3048 else if (alloc_size
>= 512)
3049 *p_adj_grp_size
= 512;
3052 static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp
*mlxsw_sp
,
3053 u16
*p_adj_grp_size
)
3055 unsigned int alloc_size
;
3058 /* Round up the requested group size to the next size supported
3059 * by the device and make sure the request can be satisfied.
3061 mlxsw_sp_adj_grp_size_round_up(p_adj_grp_size
);
3062 err
= mlxsw_sp_kvdl_alloc_size_query(mlxsw_sp
, *p_adj_grp_size
,
3066 /* It is possible the allocation results in more allocated
3067 * entries than requested. Try to use as much of them as
3070 mlxsw_sp_adj_grp_size_round_down(p_adj_grp_size
, alloc_size
);
3076 mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group
*nh_grp
)
3078 int i
, g
= 0, sum_norm_weight
= 0;
3079 struct mlxsw_sp_nexthop
*nh
;
3081 for (i
= 0; i
< nh_grp
->count
; i
++) {
3082 nh
= &nh_grp
->nexthops
[i
];
3084 if (!nh
->should_offload
)
3087 g
= gcd(nh
->nh_weight
, g
);
3092 for (i
= 0; i
< nh_grp
->count
; i
++) {
3093 nh
= &nh_grp
->nexthops
[i
];
3095 if (!nh
->should_offload
)
3097 nh
->norm_nh_weight
= nh
->nh_weight
/ g
;
3098 sum_norm_weight
+= nh
->norm_nh_weight
;
3101 nh_grp
->sum_norm_weight
= sum_norm_weight
;
3105 mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group
*nh_grp
)
3107 int total
= nh_grp
->sum_norm_weight
;
3108 u16 ecmp_size
= nh_grp
->ecmp_size
;
3109 int i
, weight
= 0, lower_bound
= 0;
3111 for (i
= 0; i
< nh_grp
->count
; i
++) {
3112 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3115 if (!nh
->should_offload
)
3117 weight
+= nh
->norm_nh_weight
;
3118 upper_bound
= DIV_ROUND_CLOSEST(ecmp_size
* weight
, total
);
3119 nh
->num_adj_entries
= upper_bound
- lower_bound
;
3120 lower_bound
= upper_bound
;
3125 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp
*mlxsw_sp
,
3126 struct mlxsw_sp_nexthop_group
*nh_grp
)
3128 u16 ecmp_size
, old_ecmp_size
;
3129 struct mlxsw_sp_nexthop
*nh
;
3130 bool offload_change
= false;
3132 bool old_adj_index_valid
;
3137 if (!nh_grp
->gateway
) {
3138 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3142 for (i
= 0; i
< nh_grp
->count
; i
++) {
3143 nh
= &nh_grp
->nexthops
[i
];
3145 if (nh
->should_offload
!= nh
->offloaded
) {
3146 offload_change
= true;
3147 if (nh
->should_offload
)
3151 if (!offload_change
) {
3152 /* Nothing was added or removed, so no need to reallocate. Just
3153 * update MAC on existing adjacency indexes.
3155 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, false);
3157 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3162 mlxsw_sp_nexthop_group_normalize(nh_grp
);
3163 if (!nh_grp
->sum_norm_weight
)
3164 /* No neigh of this group is connected so we just set
3165 * the trap and let everthing flow through kernel.
3169 ecmp_size
= nh_grp
->sum_norm_weight
;
3170 err
= mlxsw_sp_fix_adj_grp_size(mlxsw_sp
, &ecmp_size
);
3172 /* No valid allocation size available. */
3175 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, ecmp_size
, &adj_index
);
3177 /* We ran out of KVD linear space, just set the
3178 * trap and let everything flow through kernel.
3180 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to allocate KVD linear area for nexthop group.\n");
3183 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3184 old_adj_index
= nh_grp
->adj_index
;
3185 old_ecmp_size
= nh_grp
->ecmp_size
;
3186 nh_grp
->adj_index_valid
= 1;
3187 nh_grp
->adj_index
= adj_index
;
3188 nh_grp
->ecmp_size
= ecmp_size
;
3189 mlxsw_sp_nexthop_group_rebalance(nh_grp
);
3190 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, true);
3192 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3196 if (!old_adj_index_valid
) {
3197 /* The trap was set for fib entries, so we have to call
3198 * fib entry update to unset it and use adjacency index.
3200 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3202 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to add adjacency index to fib entries.\n");
3208 err
= mlxsw_sp_adj_index_mass_update(mlxsw_sp
, nh_grp
,
3209 old_adj_index
, old_ecmp_size
);
3210 mlxsw_sp_kvdl_free(mlxsw_sp
, old_adj_index
);
3212 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to mass-update adjacency index for nexthop group.\n");
3216 /* Offload state within the group changed, so update the flags. */
3217 mlxsw_sp_nexthop_fib_entries_refresh(nh_grp
);
3222 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3223 nh_grp
->adj_index_valid
= 0;
3224 for (i
= 0; i
< nh_grp
->count
; i
++) {
3225 nh
= &nh_grp
->nexthops
[i
];
3228 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3230 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set traps for fib entries.\n");
3231 if (old_adj_index_valid
)
3232 mlxsw_sp_kvdl_free(mlxsw_sp
, nh_grp
->adj_index
);
3235 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop
*nh
,
3239 nh
->should_offload
= 1;
3240 else if (nh
->offloaded
)
3241 nh
->should_offload
= 0;
3246 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
3247 struct mlxsw_sp_neigh_entry
*neigh_entry
,
3250 struct mlxsw_sp_nexthop
*nh
;
3252 list_for_each_entry(nh
, &neigh_entry
->nexthop_list
,
3254 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3255 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3259 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop
*nh
,
3260 struct mlxsw_sp_rif
*rif
)
3266 list_add(&nh
->rif_list_node
, &rif
->nexthop_list
);
3269 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop
*nh
)
3274 list_del(&nh
->rif_list_node
);
3278 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp
*mlxsw_sp
,
3279 struct mlxsw_sp_nexthop
*nh
)
3281 struct mlxsw_sp_neigh_entry
*neigh_entry
;
3282 struct neighbour
*n
;
3286 if (!nh
->nh_grp
->gateway
|| nh
->neigh_entry
)
3289 /* Take a reference of neigh here ensuring that neigh would
3290 * not be destructed before the nexthop entry is finished.
3291 * The reference is taken either in neigh_lookup() or
3292 * in neigh_create() in case n is not found.
3294 n
= neigh_lookup(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
, nh
->rif
->dev
);
3296 n
= neigh_create(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
,
3300 neigh_event_send(n
, NULL
);
3302 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
3304 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
3305 if (IS_ERR(neigh_entry
)) {
3307 goto err_neigh_entry_create
;
3311 /* If that is the first nexthop connected to that neigh, add to
3312 * nexthop_neighs_list
3314 if (list_empty(&neigh_entry
->nexthop_list
))
3315 list_add_tail(&neigh_entry
->nexthop_neighs_list_node
,
3316 &mlxsw_sp
->router
->nexthop_neighs_list
);
3318 nh
->neigh_entry
= neigh_entry
;
3319 list_add_tail(&nh
->neigh_list_node
, &neigh_entry
->nexthop_list
);
3320 read_lock_bh(&n
->lock
);
3321 nud_state
= n
->nud_state
;
3323 read_unlock_bh(&n
->lock
);
3324 __mlxsw_sp_nexthop_neigh_update(nh
, !(nud_state
& NUD_VALID
&& !dead
));
3328 err_neigh_entry_create
:
3333 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp
*mlxsw_sp
,
3334 struct mlxsw_sp_nexthop
*nh
)
3336 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
3337 struct neighbour
*n
;
3341 n
= neigh_entry
->key
.n
;
3343 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3344 list_del(&nh
->neigh_list_node
);
3345 nh
->neigh_entry
= NULL
;
3347 /* If that is the last nexthop connected to that neigh, remove from
3348 * nexthop_neighs_list
3350 if (list_empty(&neigh_entry
->nexthop_list
))
3351 list_del(&neigh_entry
->nexthop_neighs_list_node
);
3353 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
3354 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
3359 static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device
*ol_dev
)
3361 struct net_device
*ul_dev
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
3363 return ul_dev
? (ul_dev
->flags
& IFF_UP
) : true;
3366 static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp
*mlxsw_sp
,
3367 struct mlxsw_sp_nexthop
*nh
,
3368 struct mlxsw_sp_ipip_entry
*ipip_entry
)
3372 if (!nh
->nh_grp
->gateway
|| nh
->ipip_entry
)
3375 nh
->ipip_entry
= ipip_entry
;
3376 removing
= !mlxsw_sp_ipip_netdev_ul_up(ipip_entry
->ol_dev
);
3377 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3378 mlxsw_sp_nexthop_rif_init(nh
, &ipip_entry
->ol_lb
->common
);
3381 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp
*mlxsw_sp
,
3382 struct mlxsw_sp_nexthop
*nh
)
3384 struct mlxsw_sp_ipip_entry
*ipip_entry
= nh
->ipip_entry
;
3389 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3390 nh
->ipip_entry
= NULL
;
3393 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
3394 const struct fib_nh
*fib_nh
,
3395 enum mlxsw_sp_ipip_type
*p_ipipt
)
3397 struct net_device
*dev
= fib_nh
->nh_dev
;
3400 fib_nh
->nh_parent
->fib_type
== RTN_UNICAST
&&
3401 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, p_ipipt
);
3404 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3405 struct mlxsw_sp_nexthop
*nh
)
3408 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3409 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp
, nh
);
3410 mlxsw_sp_nexthop_rif_fini(nh
);
3412 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3413 mlxsw_sp_nexthop_rif_fini(nh
);
3414 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp
, nh
);
3419 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp
*mlxsw_sp
,
3420 struct mlxsw_sp_nexthop
*nh
,
3421 struct fib_nh
*fib_nh
)
3423 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3424 struct net_device
*dev
= fib_nh
->nh_dev
;
3425 struct mlxsw_sp_ipip_entry
*ipip_entry
;
3426 struct mlxsw_sp_rif
*rif
;
3429 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, dev
);
3431 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
3432 if (ipip_ops
->can_offload(mlxsw_sp
, dev
,
3433 MLXSW_SP_L3_PROTO_IPV4
)) {
3434 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
3435 mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, ipip_entry
);
3440 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
3441 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
3445 mlxsw_sp_nexthop_rif_init(nh
, rif
);
3446 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
3448 goto err_neigh_init
;
3453 mlxsw_sp_nexthop_rif_fini(nh
);
3457 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3458 struct mlxsw_sp_nexthop
*nh
)
3460 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3463 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp
*mlxsw_sp
,
3464 struct mlxsw_sp_nexthop_group
*nh_grp
,
3465 struct mlxsw_sp_nexthop
*nh
,
3466 struct fib_nh
*fib_nh
)
3468 struct net_device
*dev
= fib_nh
->nh_dev
;
3469 struct in_device
*in_dev
;
3472 nh
->nh_grp
= nh_grp
;
3473 nh
->key
.fib_nh
= fib_nh
;
3474 #ifdef CONFIG_IP_ROUTE_MULTIPATH
3475 nh
->nh_weight
= fib_nh
->nh_weight
;
3479 memcpy(&nh
->gw_addr
, &fib_nh
->nh_gw
, sizeof(fib_nh
->nh_gw
));
3480 err
= mlxsw_sp_nexthop_insert(mlxsw_sp
, nh
);
3484 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
3485 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
3490 in_dev
= __in_dev_get_rtnl(dev
);
3491 if (in_dev
&& IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev
) &&
3492 fib_nh
->nh_flags
& RTNH_F_LINKDOWN
)
3495 err
= mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3497 goto err_nexthop_neigh_init
;
3501 err_nexthop_neigh_init
:
3502 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3506 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp
*mlxsw_sp
,
3507 struct mlxsw_sp_nexthop
*nh
)
3509 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3510 list_del(&nh
->router_list_node
);
3511 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
3512 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3515 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp
*mlxsw_sp
,
3516 unsigned long event
, struct fib_nh
*fib_nh
)
3518 struct mlxsw_sp_nexthop_key key
;
3519 struct mlxsw_sp_nexthop
*nh
;
3521 if (mlxsw_sp
->router
->aborted
)
3524 key
.fib_nh
= fib_nh
;
3525 nh
= mlxsw_sp_nexthop_lookup(mlxsw_sp
, key
);
3526 if (WARN_ON_ONCE(!nh
))
3530 case FIB_EVENT_NH_ADD
:
3531 mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3533 case FIB_EVENT_NH_DEL
:
3534 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3538 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3541 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
3542 struct mlxsw_sp_rif
*rif
)
3544 struct mlxsw_sp_nexthop
*nh
;
3547 list_for_each_entry(nh
, &rif
->nexthop_list
, rif_list_node
) {
3549 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3552 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3553 removing
= !mlxsw_sp_ipip_netdev_ul_up(rif
->dev
);
3560 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3561 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3565 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp
*mlxsw_sp
,
3566 struct mlxsw_sp_rif
*old_rif
,
3567 struct mlxsw_sp_rif
*new_rif
)
3569 struct mlxsw_sp_nexthop
*nh
;
3571 list_splice_init(&old_rif
->nexthop_list
, &new_rif
->nexthop_list
);
3572 list_for_each_entry(nh
, &new_rif
->nexthop_list
, rif_list_node
)
3574 mlxsw_sp_nexthop_rif_update(mlxsw_sp
, new_rif
);
3577 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
3578 struct mlxsw_sp_rif
*rif
)
3580 struct mlxsw_sp_nexthop
*nh
, *tmp
;
3582 list_for_each_entry_safe(nh
, tmp
, &rif
->nexthop_list
, rif_list_node
) {
3583 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3584 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3588 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
3589 const struct fib_info
*fi
)
3591 return fi
->fib_nh
->nh_scope
== RT_SCOPE_LINK
||
3592 mlxsw_sp_nexthop4_ipip_type(mlxsw_sp
, fi
->fib_nh
, NULL
);
3595 static struct mlxsw_sp_nexthop_group
*
3596 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp
*mlxsw_sp
, struct fib_info
*fi
)
3598 struct mlxsw_sp_nexthop_group
*nh_grp
;
3599 struct mlxsw_sp_nexthop
*nh
;
3600 struct fib_nh
*fib_nh
;
3605 alloc_size
= sizeof(*nh_grp
) +
3606 fi
->fib_nhs
* sizeof(struct mlxsw_sp_nexthop
);
3607 nh_grp
= kzalloc(alloc_size
, GFP_KERNEL
);
3609 return ERR_PTR(-ENOMEM
);
3611 INIT_LIST_HEAD(&nh_grp
->fib_list
);
3612 nh_grp
->neigh_tbl
= &arp_tbl
;
3614 nh_grp
->gateway
= mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
);
3615 nh_grp
->count
= fi
->fib_nhs
;
3617 for (i
= 0; i
< nh_grp
->count
; i
++) {
3618 nh
= &nh_grp
->nexthops
[i
];
3619 fib_nh
= &fi
->fib_nh
[i
];
3620 err
= mlxsw_sp_nexthop4_init(mlxsw_sp
, nh_grp
, nh
, fib_nh
);
3622 goto err_nexthop4_init
;
3624 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
3626 goto err_nexthop_group_insert
;
3627 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3630 err_nexthop_group_insert
:
3632 for (i
--; i
>= 0; i
--) {
3633 nh
= &nh_grp
->nexthops
[i
];
3634 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3638 return ERR_PTR(err
);
3642 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
3643 struct mlxsw_sp_nexthop_group
*nh_grp
)
3645 struct mlxsw_sp_nexthop
*nh
;
3648 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
3649 for (i
= 0; i
< nh_grp
->count
; i
++) {
3650 nh
= &nh_grp
->nexthops
[i
];
3651 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3653 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3654 WARN_ON_ONCE(nh_grp
->adj_index_valid
);
3655 fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp
));
3659 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp
*mlxsw_sp
,
3660 struct mlxsw_sp_fib_entry
*fib_entry
,
3661 struct fib_info
*fi
)
3663 struct mlxsw_sp_nexthop_group
*nh_grp
;
3665 nh_grp
= mlxsw_sp_nexthop4_group_lookup(mlxsw_sp
, fi
);
3667 nh_grp
= mlxsw_sp_nexthop4_group_create(mlxsw_sp
, fi
);
3669 return PTR_ERR(nh_grp
);
3671 list_add_tail(&fib_entry
->nexthop_group_node
, &nh_grp
->fib_list
);
3672 fib_entry
->nh_group
= nh_grp
;
3676 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp
*mlxsw_sp
,
3677 struct mlxsw_sp_fib_entry
*fib_entry
)
3679 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3681 list_del(&fib_entry
->nexthop_group_node
);
3682 if (!list_empty(&nh_grp
->fib_list
))
3684 mlxsw_sp_nexthop4_group_destroy(mlxsw_sp
, nh_grp
);
3688 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
3690 struct mlxsw_sp_fib4_entry
*fib4_entry
;
3692 fib4_entry
= container_of(fib_entry
, struct mlxsw_sp_fib4_entry
,
3694 return !fib4_entry
->tos
;
3698 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
3700 struct mlxsw_sp_nexthop_group
*nh_group
= fib_entry
->nh_group
;
3702 switch (fib_entry
->fib_node
->fib
->proto
) {
3703 case MLXSW_SP_L3_PROTO_IPV4
:
3704 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry
))
3707 case MLXSW_SP_L3_PROTO_IPV6
:
3711 switch (fib_entry
->type
) {
3712 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
3713 return !!nh_group
->adj_index_valid
;
3714 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
3715 return !!nh_group
->nh_rif
;
3716 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
3723 static struct mlxsw_sp_nexthop
*
3724 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group
*nh_grp
,
3725 const struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
3729 for (i
= 0; i
< nh_grp
->count
; i
++) {
3730 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3731 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
3733 if (nh
->rif
&& nh
->rif
->dev
== rt
->dst
.dev
&&
3734 ipv6_addr_equal((const struct in6_addr
*) &nh
->gw_addr
,
3744 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3746 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3749 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
||
3750 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
) {
3751 nh_grp
->nexthops
->key
.fib_nh
->nh_flags
|= RTNH_F_OFFLOAD
;
3755 for (i
= 0; i
< nh_grp
->count
; i
++) {
3756 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3759 nh
->key
.fib_nh
->nh_flags
|= RTNH_F_OFFLOAD
;
3761 nh
->key
.fib_nh
->nh_flags
&= ~RTNH_F_OFFLOAD
;
3766 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3768 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3771 for (i
= 0; i
< nh_grp
->count
; i
++) {
3772 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3774 nh
->key
.fib_nh
->nh_flags
&= ~RTNH_F_OFFLOAD
;
3779 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3781 struct mlxsw_sp_fib6_entry
*fib6_entry
;
3782 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
3784 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
3787 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
) {
3788 list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
3789 list
)->rt
->rt6i_nh_flags
|= RTNH_F_OFFLOAD
;
3793 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
3794 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3795 struct mlxsw_sp_nexthop
*nh
;
3797 nh
= mlxsw_sp_rt6_nexthop(nh_grp
, mlxsw_sp_rt6
);
3798 if (nh
&& nh
->offloaded
)
3799 mlxsw_sp_rt6
->rt
->rt6i_nh_flags
|= RTNH_F_OFFLOAD
;
3801 mlxsw_sp_rt6
->rt
->rt6i_nh_flags
&= ~RTNH_F_OFFLOAD
;
3806 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3808 struct mlxsw_sp_fib6_entry
*fib6_entry
;
3809 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
3811 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
3813 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
3814 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
3816 rt
->rt6i_nh_flags
&= ~RTNH_F_OFFLOAD
;
3820 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3822 switch (fib_entry
->fib_node
->fib
->proto
) {
3823 case MLXSW_SP_L3_PROTO_IPV4
:
3824 mlxsw_sp_fib4_entry_offload_set(fib_entry
);
3826 case MLXSW_SP_L3_PROTO_IPV6
:
3827 mlxsw_sp_fib6_entry_offload_set(fib_entry
);
3833 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3835 switch (fib_entry
->fib_node
->fib
->proto
) {
3836 case MLXSW_SP_L3_PROTO_IPV4
:
3837 mlxsw_sp_fib4_entry_offload_unset(fib_entry
);
3839 case MLXSW_SP_L3_PROTO_IPV6
:
3840 mlxsw_sp_fib6_entry_offload_unset(fib_entry
);
3846 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
3847 enum mlxsw_reg_ralue_op op
, int err
)
3850 case MLXSW_REG_RALUE_OP_WRITE_DELETE
:
3851 return mlxsw_sp_fib_entry_offload_unset(fib_entry
);
3852 case MLXSW_REG_RALUE_OP_WRITE_WRITE
:
3855 if (mlxsw_sp_fib_entry_should_offload(fib_entry
))
3856 mlxsw_sp_fib_entry_offload_set(fib_entry
);
3858 mlxsw_sp_fib_entry_offload_unset(fib_entry
);
3866 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl
,
3867 const struct mlxsw_sp_fib_entry
*fib_entry
,
3868 enum mlxsw_reg_ralue_op op
)
3870 struct mlxsw_sp_fib
*fib
= fib_entry
->fib_node
->fib
;
3871 enum mlxsw_reg_ralxx_protocol proto
;
3874 proto
= (enum mlxsw_reg_ralxx_protocol
) fib
->proto
;
3876 switch (fib
->proto
) {
3877 case MLXSW_SP_L3_PROTO_IPV4
:
3878 p_dip
= (u32
*) fib_entry
->fib_node
->key
.addr
;
3879 mlxsw_reg_ralue_pack4(ralue_pl
, proto
, op
, fib
->vr
->id
,
3880 fib_entry
->fib_node
->key
.prefix_len
,
3883 case MLXSW_SP_L3_PROTO_IPV6
:
3884 mlxsw_reg_ralue_pack6(ralue_pl
, proto
, op
, fib
->vr
->id
,
3885 fib_entry
->fib_node
->key
.prefix_len
,
3886 fib_entry
->fib_node
->key
.addr
);
3891 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp
*mlxsw_sp
,
3892 struct mlxsw_sp_fib_entry
*fib_entry
,
3893 enum mlxsw_reg_ralue_op op
)
3895 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3896 enum mlxsw_reg_ralue_trap_action trap_action
;
3898 u32 adjacency_index
= 0;
3901 /* In case the nexthop group adjacency index is valid, use it
3902 * with provided ECMP size. Otherwise, setup trap and pass
3903 * traffic to kernel.
3905 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
3906 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
3907 adjacency_index
= fib_entry
->nh_group
->adj_index
;
3908 ecmp_size
= fib_entry
->nh_group
->ecmp_size
;
3910 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
3911 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
3914 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3915 mlxsw_reg_ralue_act_remote_pack(ralue_pl
, trap_action
, trap_id
,
3916 adjacency_index
, ecmp_size
);
3917 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3920 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp
*mlxsw_sp
,
3921 struct mlxsw_sp_fib_entry
*fib_entry
,
3922 enum mlxsw_reg_ralue_op op
)
3924 struct mlxsw_sp_rif
*rif
= fib_entry
->nh_group
->nh_rif
;
3925 enum mlxsw_reg_ralue_trap_action trap_action
;
3926 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3930 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
3931 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
3932 rif_index
= rif
->rif_index
;
3934 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
3935 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
3938 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3939 mlxsw_reg_ralue_act_local_pack(ralue_pl
, trap_action
, trap_id
,
3941 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3944 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp
*mlxsw_sp
,
3945 struct mlxsw_sp_fib_entry
*fib_entry
,
3946 enum mlxsw_reg_ralue_op op
)
3948 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3950 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3951 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
3952 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3956 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp
*mlxsw_sp
,
3957 struct mlxsw_sp_fib_entry
*fib_entry
,
3958 enum mlxsw_reg_ralue_op op
)
3960 struct mlxsw_sp_ipip_entry
*ipip_entry
= fib_entry
->decap
.ipip_entry
;
3961 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3963 if (WARN_ON(!ipip_entry
))
3966 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
3967 return ipip_ops
->fib_entry_op(mlxsw_sp
, ipip_entry
, op
,
3968 fib_entry
->decap
.tunnel_index
);
3971 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
3972 struct mlxsw_sp_fib_entry
*fib_entry
,
3973 enum mlxsw_reg_ralue_op op
)
3975 switch (fib_entry
->type
) {
3976 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
3977 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp
, fib_entry
, op
);
3978 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
3979 return mlxsw_sp_fib_entry_op_local(mlxsw_sp
, fib_entry
, op
);
3980 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP
:
3981 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp
, fib_entry
, op
);
3982 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
3983 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp
,
3989 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
3990 struct mlxsw_sp_fib_entry
*fib_entry
,
3991 enum mlxsw_reg_ralue_op op
)
3993 int err
= __mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
, op
);
3995 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, err
);
4000 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
4001 struct mlxsw_sp_fib_entry
*fib_entry
)
4003 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
4004 MLXSW_REG_RALUE_OP_WRITE_WRITE
);
4007 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4008 struct mlxsw_sp_fib_entry
*fib_entry
)
4010 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
4011 MLXSW_REG_RALUE_OP_WRITE_DELETE
);
4015 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
4016 const struct fib_entry_notifier_info
*fen_info
,
4017 struct mlxsw_sp_fib_entry
*fib_entry
)
4019 union mlxsw_sp_l3addr dip
= { .addr4
= htonl(fen_info
->dst
) };
4020 struct net_device
*dev
= fen_info
->fi
->fib_dev
;
4021 struct mlxsw_sp_ipip_entry
*ipip_entry
;
4022 struct fib_info
*fi
= fen_info
->fi
;
4024 switch (fen_info
->type
) {
4026 ipip_entry
= mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp
, dev
,
4027 MLXSW_SP_L3_PROTO_IPV4
, dip
);
4028 if (ipip_entry
&& ipip_entry
->ol_dev
->flags
& IFF_UP
) {
4029 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
4030 return mlxsw_sp_fib_entry_decap_init(mlxsw_sp
,
4036 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4038 case RTN_UNREACHABLE
: /* fall through */
4039 case RTN_BLACKHOLE
: /* fall through */
4041 /* Packets hitting these routes need to be trapped, but
4042 * can do so with a lower priority than packets directed
4043 * at the host, so use action type local instead of trap.
4045 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4048 if (mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
))
4049 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4051 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4058 static struct mlxsw_sp_fib4_entry
*
4059 mlxsw_sp_fib4_entry_create(struct mlxsw_sp
*mlxsw_sp
,
4060 struct mlxsw_sp_fib_node
*fib_node
,
4061 const struct fib_entry_notifier_info
*fen_info
)
4063 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4064 struct mlxsw_sp_fib_entry
*fib_entry
;
4067 fib4_entry
= kzalloc(sizeof(*fib4_entry
), GFP_KERNEL
);
4069 return ERR_PTR(-ENOMEM
);
4070 fib_entry
= &fib4_entry
->common
;
4072 err
= mlxsw_sp_fib4_entry_type_set(mlxsw_sp
, fen_info
, fib_entry
);
4074 goto err_fib4_entry_type_set
;
4076 err
= mlxsw_sp_nexthop4_group_get(mlxsw_sp
, fib_entry
, fen_info
->fi
);
4078 goto err_nexthop4_group_get
;
4080 fib4_entry
->prio
= fen_info
->fi
->fib_priority
;
4081 fib4_entry
->tb_id
= fen_info
->tb_id
;
4082 fib4_entry
->type
= fen_info
->type
;
4083 fib4_entry
->tos
= fen_info
->tos
;
4085 fib_entry
->fib_node
= fib_node
;
4089 err_nexthop4_group_get
:
4090 err_fib4_entry_type_set
:
4092 return ERR_PTR(err
);
4095 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
4096 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4098 mlxsw_sp_nexthop4_group_put(mlxsw_sp
, &fib4_entry
->common
);
4102 static struct mlxsw_sp_fib4_entry
*
4103 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
4104 const struct fib_entry_notifier_info
*fen_info
)
4106 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4107 struct mlxsw_sp_fib_node
*fib_node
;
4108 struct mlxsw_sp_fib
*fib
;
4109 struct mlxsw_sp_vr
*vr
;
4111 vr
= mlxsw_sp_vr_find(mlxsw_sp
, fen_info
->tb_id
);
4114 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV4
);
4116 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &fen_info
->dst
,
4117 sizeof(fen_info
->dst
),
4122 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4123 if (fib4_entry
->tb_id
== fen_info
->tb_id
&&
4124 fib4_entry
->tos
== fen_info
->tos
&&
4125 fib4_entry
->type
== fen_info
->type
&&
4126 mlxsw_sp_nexthop4_group_fi(fib4_entry
->common
.nh_group
) ==
4135 static const struct rhashtable_params mlxsw_sp_fib_ht_params
= {
4136 .key_offset
= offsetof(struct mlxsw_sp_fib_node
, key
),
4137 .head_offset
= offsetof(struct mlxsw_sp_fib_node
, ht_node
),
4138 .key_len
= sizeof(struct mlxsw_sp_fib_key
),
4139 .automatic_shrinking
= true,
4142 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib
*fib
,
4143 struct mlxsw_sp_fib_node
*fib_node
)
4145 return rhashtable_insert_fast(&fib
->ht
, &fib_node
->ht_node
,
4146 mlxsw_sp_fib_ht_params
);
4149 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib
*fib
,
4150 struct mlxsw_sp_fib_node
*fib_node
)
4152 rhashtable_remove_fast(&fib
->ht
, &fib_node
->ht_node
,
4153 mlxsw_sp_fib_ht_params
);
4156 static struct mlxsw_sp_fib_node
*
4157 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
4158 size_t addr_len
, unsigned char prefix_len
)
4160 struct mlxsw_sp_fib_key key
;
4162 memset(&key
, 0, sizeof(key
));
4163 memcpy(key
.addr
, addr
, addr_len
);
4164 key
.prefix_len
= prefix_len
;
4165 return rhashtable_lookup_fast(&fib
->ht
, &key
, mlxsw_sp_fib_ht_params
);
4168 static struct mlxsw_sp_fib_node
*
4169 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib
*fib
, const void *addr
,
4170 size_t addr_len
, unsigned char prefix_len
)
4172 struct mlxsw_sp_fib_node
*fib_node
;
4174 fib_node
= kzalloc(sizeof(*fib_node
), GFP_KERNEL
);
4178 INIT_LIST_HEAD(&fib_node
->entry_list
);
4179 list_add(&fib_node
->list
, &fib
->node_list
);
4180 memcpy(fib_node
->key
.addr
, addr
, addr_len
);
4181 fib_node
->key
.prefix_len
= prefix_len
;
4186 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node
*fib_node
)
4188 list_del(&fib_node
->list
);
4189 WARN_ON(!list_empty(&fib_node
->entry_list
));
4194 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
4195 const struct mlxsw_sp_fib_entry
*fib_entry
)
4197 return list_first_entry(&fib_node
->entry_list
,
4198 struct mlxsw_sp_fib_entry
, list
) == fib_entry
;
4201 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp
*mlxsw_sp
,
4202 struct mlxsw_sp_fib
*fib
,
4203 struct mlxsw_sp_fib_node
*fib_node
)
4205 struct mlxsw_sp_prefix_usage req_prefix_usage
= {{ 0 } };
4206 struct mlxsw_sp_lpm_tree
*lpm_tree
;
4209 /* Since the tree is shared between all virtual routers we must
4210 * make sure it contains all the required prefix lengths. This
4211 * can be computed by either adding the new prefix length to the
4212 * existing prefix usage of a bound tree, or by aggregating the
4213 * prefix lengths across all virtual routers and adding the new
4217 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage
,
4218 &fib
->lpm_tree
->prefix_usage
);
4220 mlxsw_sp_vrs_prefixes(mlxsw_sp
, fib
->proto
, &req_prefix_usage
);
4221 mlxsw_sp_prefix_usage_set(&req_prefix_usage
, fib_node
->key
.prefix_len
);
4223 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
4225 if (IS_ERR(lpm_tree
))
4226 return PTR_ERR(lpm_tree
);
4228 if (fib
->lpm_tree
&& fib
->lpm_tree
->id
== lpm_tree
->id
)
4231 err
= mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp
, fib
, lpm_tree
);
4238 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp
*mlxsw_sp
,
4239 struct mlxsw_sp_fib
*fib
)
4241 if (!mlxsw_sp_prefix_usage_none(&fib
->prefix_usage
))
4243 mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp
, fib
);
4244 mlxsw_sp_lpm_tree_put(mlxsw_sp
, fib
->lpm_tree
);
4245 fib
->lpm_tree
= NULL
;
4248 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node
*fib_node
)
4250 unsigned char prefix_len
= fib_node
->key
.prefix_len
;
4251 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4253 if (fib
->prefix_ref_count
[prefix_len
]++ == 0)
4254 mlxsw_sp_prefix_usage_set(&fib
->prefix_usage
, prefix_len
);
4257 static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node
*fib_node
)
4259 unsigned char prefix_len
= fib_node
->key
.prefix_len
;
4260 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4262 if (--fib
->prefix_ref_count
[prefix_len
] == 0)
4263 mlxsw_sp_prefix_usage_clear(&fib
->prefix_usage
, prefix_len
);
4266 static int mlxsw_sp_fib_node_init(struct mlxsw_sp
*mlxsw_sp
,
4267 struct mlxsw_sp_fib_node
*fib_node
,
4268 struct mlxsw_sp_fib
*fib
)
4272 err
= mlxsw_sp_fib_node_insert(fib
, fib_node
);
4275 fib_node
->fib
= fib
;
4277 err
= mlxsw_sp_fib_lpm_tree_link(mlxsw_sp
, fib
, fib_node
);
4279 goto err_fib_lpm_tree_link
;
4281 mlxsw_sp_fib_node_prefix_inc(fib_node
);
4285 err_fib_lpm_tree_link
:
4286 fib_node
->fib
= NULL
;
4287 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4291 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp
*mlxsw_sp
,
4292 struct mlxsw_sp_fib_node
*fib_node
)
4294 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4296 mlxsw_sp_fib_node_prefix_dec(fib_node
);
4297 mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp
, fib
);
4298 fib_node
->fib
= NULL
;
4299 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4302 static struct mlxsw_sp_fib_node
*
4303 mlxsw_sp_fib_node_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
, const void *addr
,
4304 size_t addr_len
, unsigned char prefix_len
,
4305 enum mlxsw_sp_l3proto proto
)
4307 struct mlxsw_sp_fib_node
*fib_node
;
4308 struct mlxsw_sp_fib
*fib
;
4309 struct mlxsw_sp_vr
*vr
;
4312 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
, NULL
);
4314 return ERR_CAST(vr
);
4315 fib
= mlxsw_sp_vr_fib(vr
, proto
);
4317 fib_node
= mlxsw_sp_fib_node_lookup(fib
, addr
, addr_len
, prefix_len
);
4321 fib_node
= mlxsw_sp_fib_node_create(fib
, addr
, addr_len
, prefix_len
);
4324 goto err_fib_node_create
;
4327 err
= mlxsw_sp_fib_node_init(mlxsw_sp
, fib_node
, fib
);
4329 goto err_fib_node_init
;
4334 mlxsw_sp_fib_node_destroy(fib_node
);
4335 err_fib_node_create
:
4336 mlxsw_sp_vr_put(vr
);
4337 return ERR_PTR(err
);
4340 static void mlxsw_sp_fib_node_put(struct mlxsw_sp
*mlxsw_sp
,
4341 struct mlxsw_sp_fib_node
*fib_node
)
4343 struct mlxsw_sp_vr
*vr
= fib_node
->fib
->vr
;
4345 if (!list_empty(&fib_node
->entry_list
))
4347 mlxsw_sp_fib_node_fini(mlxsw_sp
, fib_node
);
4348 mlxsw_sp_fib_node_destroy(fib_node
);
4349 mlxsw_sp_vr_put(vr
);
4352 static struct mlxsw_sp_fib4_entry
*
4353 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
4354 const struct mlxsw_sp_fib4_entry
*new4_entry
)
4356 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4358 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4359 if (fib4_entry
->tb_id
> new4_entry
->tb_id
)
4361 if (fib4_entry
->tb_id
!= new4_entry
->tb_id
)
4363 if (fib4_entry
->tos
> new4_entry
->tos
)
4365 if (fib4_entry
->prio
>= new4_entry
->prio
||
4366 fib4_entry
->tos
< new4_entry
->tos
)
4374 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry
*fib4_entry
,
4375 struct mlxsw_sp_fib4_entry
*new4_entry
)
4377 struct mlxsw_sp_fib_node
*fib_node
;
4379 if (WARN_ON(!fib4_entry
))
4382 fib_node
= fib4_entry
->common
.fib_node
;
4383 list_for_each_entry_from(fib4_entry
, &fib_node
->entry_list
,
4385 if (fib4_entry
->tb_id
!= new4_entry
->tb_id
||
4386 fib4_entry
->tos
!= new4_entry
->tos
||
4387 fib4_entry
->prio
!= new4_entry
->prio
)
4391 list_add_tail(&new4_entry
->common
.list
, &fib4_entry
->common
.list
);
4396 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry
*new4_entry
,
4397 bool replace
, bool append
)
4399 struct mlxsw_sp_fib_node
*fib_node
= new4_entry
->common
.fib_node
;
4400 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4402 fib4_entry
= mlxsw_sp_fib4_node_entry_find(fib_node
, new4_entry
);
4405 return mlxsw_sp_fib4_node_list_append(fib4_entry
, new4_entry
);
4406 if (replace
&& WARN_ON(!fib4_entry
))
4409 /* Insert new entry before replaced one, so that we can later
4410 * remove the second.
4413 list_add_tail(&new4_entry
->common
.list
,
4414 &fib4_entry
->common
.list
);
4416 struct mlxsw_sp_fib4_entry
*last
;
4418 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
4419 if (new4_entry
->tb_id
> last
->tb_id
)
4425 list_add(&new4_entry
->common
.list
,
4426 &fib4_entry
->common
.list
);
4428 list_add(&new4_entry
->common
.list
,
4429 &fib_node
->entry_list
);
4436 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry
*fib4_entry
)
4438 list_del(&fib4_entry
->common
.list
);
4441 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp
*mlxsw_sp
,
4442 struct mlxsw_sp_fib_entry
*fib_entry
)
4444 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4446 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4449 /* To prevent packet loss, overwrite the previously offloaded
4452 if (!list_is_singular(&fib_node
->entry_list
)) {
4453 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4454 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4456 mlxsw_sp_fib_entry_offload_refresh(n
, op
, 0);
4459 return mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
4462 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4463 struct mlxsw_sp_fib_entry
*fib_entry
)
4465 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4467 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4470 /* Promote the next entry by overwriting the deleted entry */
4471 if (!list_is_singular(&fib_node
->entry_list
)) {
4472 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4473 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4475 mlxsw_sp_fib_entry_update(mlxsw_sp
, n
);
4476 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
4480 mlxsw_sp_fib_entry_del(mlxsw_sp
, fib_entry
);
4483 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
4484 struct mlxsw_sp_fib4_entry
*fib4_entry
,
4485 bool replace
, bool append
)
4489 err
= mlxsw_sp_fib4_node_list_insert(fib4_entry
, replace
, append
);
4493 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib4_entry
->common
);
4495 goto err_fib_node_entry_add
;
4499 err_fib_node_entry_add
:
4500 mlxsw_sp_fib4_node_list_remove(fib4_entry
);
4505 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
4506 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4508 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib4_entry
->common
);
4509 mlxsw_sp_fib4_node_list_remove(fib4_entry
);
4511 if (fib4_entry
->common
.type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
)
4512 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, &fib4_entry
->common
);
4515 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
4516 struct mlxsw_sp_fib4_entry
*fib4_entry
,
4519 struct mlxsw_sp_fib_node
*fib_node
= fib4_entry
->common
.fib_node
;
4520 struct mlxsw_sp_fib4_entry
*replaced
;
4525 /* We inserted the new entry before replaced one */
4526 replaced
= list_next_entry(fib4_entry
, common
.list
);
4528 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, replaced
);
4529 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, replaced
);
4530 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4534 mlxsw_sp_router_fib4_add(struct mlxsw_sp
*mlxsw_sp
,
4535 const struct fib_entry_notifier_info
*fen_info
,
4536 bool replace
, bool append
)
4538 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4539 struct mlxsw_sp_fib_node
*fib_node
;
4542 if (mlxsw_sp
->router
->aborted
)
4545 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, fen_info
->tb_id
,
4546 &fen_info
->dst
, sizeof(fen_info
->dst
),
4548 MLXSW_SP_L3_PROTO_IPV4
);
4549 if (IS_ERR(fib_node
)) {
4550 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to get FIB node\n");
4551 return PTR_ERR(fib_node
);
4554 fib4_entry
= mlxsw_sp_fib4_entry_create(mlxsw_sp
, fib_node
, fen_info
);
4555 if (IS_ERR(fib4_entry
)) {
4556 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to create FIB entry\n");
4557 err
= PTR_ERR(fib4_entry
);
4558 goto err_fib4_entry_create
;
4561 err
= mlxsw_sp_fib4_node_entry_link(mlxsw_sp
, fib4_entry
, replace
,
4564 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to link FIB entry to node\n");
4565 goto err_fib4_node_entry_link
;
4568 mlxsw_sp_fib4_entry_replace(mlxsw_sp
, fib4_entry
, replace
);
4572 err_fib4_node_entry_link
:
4573 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4574 err_fib4_entry_create
:
4575 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4579 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp
*mlxsw_sp
,
4580 struct fib_entry_notifier_info
*fen_info
)
4582 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4583 struct mlxsw_sp_fib_node
*fib_node
;
4585 if (mlxsw_sp
->router
->aborted
)
4588 fib4_entry
= mlxsw_sp_fib4_entry_lookup(mlxsw_sp
, fen_info
);
4589 if (WARN_ON(!fib4_entry
))
4591 fib_node
= fib4_entry
->common
.fib_node
;
4593 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
4594 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4595 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4598 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info
*rt
)
4600 /* Packets with link-local destination IP arriving to the router
4601 * are trapped to the CPU, so no need to program specific routes
4604 if (ipv6_addr_type(&rt
->rt6i_dst
.addr
) & IPV6_ADDR_LINKLOCAL
)
4607 /* Multicast routes aren't supported, so ignore them. Neighbour
4608 * Discovery packets are specifically trapped.
4610 if (ipv6_addr_type(&rt
->rt6i_dst
.addr
) & IPV6_ADDR_MULTICAST
)
4613 /* Cloned routes are irrelevant in the forwarding path. */
4614 if (rt
->rt6i_flags
& RTF_CACHE
)
4620 static struct mlxsw_sp_rt6
*mlxsw_sp_rt6_create(struct rt6_info
*rt
)
4622 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4624 mlxsw_sp_rt6
= kzalloc(sizeof(*mlxsw_sp_rt6
), GFP_KERNEL
);
4626 return ERR_PTR(-ENOMEM
);
4628 /* In case of route replace, replaced route is deleted with
4629 * no notification. Take reference to prevent accessing freed
4632 mlxsw_sp_rt6
->rt
= rt
;
4635 return mlxsw_sp_rt6
;
4638 #if IS_ENABLED(CONFIG_IPV6)
4639 static void mlxsw_sp_rt6_release(struct rt6_info
*rt
)
4644 static void mlxsw_sp_rt6_release(struct rt6_info
*rt
)
4649 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
4651 mlxsw_sp_rt6_release(mlxsw_sp_rt6
->rt
);
4652 kfree(mlxsw_sp_rt6
);
4655 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info
*rt
)
4657 /* RTF_CACHE routes are ignored */
4658 return (rt
->rt6i_flags
& (RTF_GATEWAY
| RTF_ADDRCONF
)) == RTF_GATEWAY
;
4661 static struct rt6_info
*
4662 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry
*fib6_entry
)
4664 return list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
4668 static struct mlxsw_sp_fib6_entry
*
4669 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
4670 const struct rt6_info
*nrt
, bool replace
)
4672 struct mlxsw_sp_fib6_entry
*fib6_entry
;
4674 if (!mlxsw_sp_fib6_rt_can_mp(nrt
) || replace
)
4677 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
4678 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
4680 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
4683 if (rt
->rt6i_table
->tb6_id
> nrt
->rt6i_table
->tb6_id
)
4685 if (rt
->rt6i_table
->tb6_id
!= nrt
->rt6i_table
->tb6_id
)
4687 if (rt
->rt6i_metric
< nrt
->rt6i_metric
)
4689 if (rt
->rt6i_metric
== nrt
->rt6i_metric
&&
4690 mlxsw_sp_fib6_rt_can_mp(rt
))
4692 if (rt
->rt6i_metric
> nrt
->rt6i_metric
)
4699 static struct mlxsw_sp_rt6
*
4700 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry
*fib6_entry
,
4701 const struct rt6_info
*rt
)
4703 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4705 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
4706 if (mlxsw_sp_rt6
->rt
== rt
)
4707 return mlxsw_sp_rt6
;
4713 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
4714 const struct rt6_info
*rt
,
4715 enum mlxsw_sp_ipip_type
*ret
)
4717 return rt
->dst
.dev
&&
4718 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, rt
->dst
.dev
, ret
);
4721 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp
*mlxsw_sp
,
4722 struct mlxsw_sp_nexthop_group
*nh_grp
,
4723 struct mlxsw_sp_nexthop
*nh
,
4724 const struct rt6_info
*rt
)
4726 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
4727 struct mlxsw_sp_ipip_entry
*ipip_entry
;
4728 struct net_device
*dev
= rt
->dst
.dev
;
4729 struct mlxsw_sp_rif
*rif
;
4732 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, dev
);
4734 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
4735 if (ipip_ops
->can_offload(mlxsw_sp
, dev
,
4736 MLXSW_SP_L3_PROTO_IPV6
)) {
4737 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
4738 mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, ipip_entry
);
4743 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
4744 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
4747 mlxsw_sp_nexthop_rif_init(nh
, rif
);
4749 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
4751 goto err_nexthop_neigh_init
;
4755 err_nexthop_neigh_init
:
4756 mlxsw_sp_nexthop_rif_fini(nh
);
4760 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp
*mlxsw_sp
,
4761 struct mlxsw_sp_nexthop
*nh
)
4763 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
4766 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp
*mlxsw_sp
,
4767 struct mlxsw_sp_nexthop_group
*nh_grp
,
4768 struct mlxsw_sp_nexthop
*nh
,
4769 const struct rt6_info
*rt
)
4771 struct net_device
*dev
= rt
->dst
.dev
;
4773 nh
->nh_grp
= nh_grp
;
4775 memcpy(&nh
->gw_addr
, &rt
->rt6i_gateway
, sizeof(nh
->gw_addr
));
4776 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
4778 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
4782 nh
->ifindex
= dev
->ifindex
;
4784 return mlxsw_sp_nexthop6_type_init(mlxsw_sp
, nh_grp
, nh
, rt
);
4787 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp
*mlxsw_sp
,
4788 struct mlxsw_sp_nexthop
*nh
)
4790 mlxsw_sp_nexthop6_type_fini(mlxsw_sp
, nh
);
4791 list_del(&nh
->router_list_node
);
4792 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
4795 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
4796 const struct rt6_info
*rt
)
4798 return rt
->rt6i_flags
& RTF_GATEWAY
||
4799 mlxsw_sp_nexthop6_ipip_type(mlxsw_sp
, rt
, NULL
);
4802 static struct mlxsw_sp_nexthop_group
*
4803 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp
*mlxsw_sp
,
4804 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4806 struct mlxsw_sp_nexthop_group
*nh_grp
;
4807 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4808 struct mlxsw_sp_nexthop
*nh
;
4813 alloc_size
= sizeof(*nh_grp
) +
4814 fib6_entry
->nrt6
* sizeof(struct mlxsw_sp_nexthop
);
4815 nh_grp
= kzalloc(alloc_size
, GFP_KERNEL
);
4817 return ERR_PTR(-ENOMEM
);
4818 INIT_LIST_HEAD(&nh_grp
->fib_list
);
4819 #if IS_ENABLED(CONFIG_IPV6)
4820 nh_grp
->neigh_tbl
= &nd_tbl
;
4822 mlxsw_sp_rt6
= list_first_entry(&fib6_entry
->rt6_list
,
4823 struct mlxsw_sp_rt6
, list
);
4824 nh_grp
->gateway
= mlxsw_sp_rt6_is_gateway(mlxsw_sp
, mlxsw_sp_rt6
->rt
);
4825 nh_grp
->count
= fib6_entry
->nrt6
;
4826 for (i
= 0; i
< nh_grp
->count
; i
++) {
4827 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
4829 nh
= &nh_grp
->nexthops
[i
];
4830 err
= mlxsw_sp_nexthop6_init(mlxsw_sp
, nh_grp
, nh
, rt
);
4832 goto err_nexthop6_init
;
4833 mlxsw_sp_rt6
= list_next_entry(mlxsw_sp_rt6
, list
);
4836 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
4838 goto err_nexthop_group_insert
;
4840 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
4843 err_nexthop_group_insert
:
4845 for (i
--; i
>= 0; i
--) {
4846 nh
= &nh_grp
->nexthops
[i
];
4847 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
4850 return ERR_PTR(err
);
4854 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
4855 struct mlxsw_sp_nexthop_group
*nh_grp
)
4857 struct mlxsw_sp_nexthop
*nh
;
4858 int i
= nh_grp
->count
;
4860 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
4861 for (i
--; i
>= 0; i
--) {
4862 nh
= &nh_grp
->nexthops
[i
];
4863 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
4865 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
4866 WARN_ON(nh_grp
->adj_index_valid
);
4870 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp
*mlxsw_sp
,
4871 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4873 struct mlxsw_sp_nexthop_group
*nh_grp
;
4875 nh_grp
= mlxsw_sp_nexthop6_group_lookup(mlxsw_sp
, fib6_entry
);
4877 nh_grp
= mlxsw_sp_nexthop6_group_create(mlxsw_sp
, fib6_entry
);
4879 return PTR_ERR(nh_grp
);
4882 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
4884 fib6_entry
->common
.nh_group
= nh_grp
;
4889 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp
*mlxsw_sp
,
4890 struct mlxsw_sp_fib_entry
*fib_entry
)
4892 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4894 list_del(&fib_entry
->nexthop_group_node
);
4895 if (!list_empty(&nh_grp
->fib_list
))
4897 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, nh_grp
);
4901 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp
*mlxsw_sp
,
4902 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4904 struct mlxsw_sp_nexthop_group
*old_nh_grp
= fib6_entry
->common
.nh_group
;
4907 fib6_entry
->common
.nh_group
= NULL
;
4908 list_del(&fib6_entry
->common
.nexthop_group_node
);
4910 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
4912 goto err_nexthop6_group_get
;
4914 /* In case this entry is offloaded, then the adjacency index
4915 * currently associated with it in the device's table is that
4916 * of the old group. Start using the new one instead.
4918 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
4920 goto err_fib_node_entry_add
;
4922 if (list_empty(&old_nh_grp
->fib_list
))
4923 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, old_nh_grp
);
4927 err_fib_node_entry_add
:
4928 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
4929 err_nexthop6_group_get
:
4930 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
4931 &old_nh_grp
->fib_list
);
4932 fib6_entry
->common
.nh_group
= old_nh_grp
;
4937 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp
*mlxsw_sp
,
4938 struct mlxsw_sp_fib6_entry
*fib6_entry
,
4939 struct rt6_info
*rt
)
4941 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4944 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt
);
4945 if (IS_ERR(mlxsw_sp_rt6
))
4946 return PTR_ERR(mlxsw_sp_rt6
);
4948 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
4951 err
= mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
4953 goto err_nexthop6_group_update
;
4957 err_nexthop6_group_update
:
4959 list_del(&mlxsw_sp_rt6
->list
);
4960 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4965 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp
*mlxsw_sp
,
4966 struct mlxsw_sp_fib6_entry
*fib6_entry
,
4967 struct rt6_info
*rt
)
4969 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4971 mlxsw_sp_rt6
= mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
);
4972 if (WARN_ON(!mlxsw_sp_rt6
))
4976 list_del(&mlxsw_sp_rt6
->list
);
4977 mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
4978 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4981 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
4982 struct mlxsw_sp_fib_entry
*fib_entry
,
4983 const struct rt6_info
*rt
)
4985 /* Packets hitting RTF_REJECT routes need to be discarded by the
4986 * stack. We can rely on their destination device not having a
4987 * RIF (it's the loopback device) and can thus use action type
4988 * local, which will cause them to be trapped with a lower
4989 * priority than packets that need to be locally received.
4991 if (rt
->rt6i_flags
& (RTF_LOCAL
| RTF_ANYCAST
))
4992 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4993 else if (rt
->rt6i_flags
& RTF_REJECT
)
4994 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4995 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp
, rt
))
4996 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4998 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
5002 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5004 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
, *tmp
;
5006 list_for_each_entry_safe(mlxsw_sp_rt6
, tmp
, &fib6_entry
->rt6_list
,
5009 list_del(&mlxsw_sp_rt6
->list
);
5010 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5014 static struct mlxsw_sp_fib6_entry
*
5015 mlxsw_sp_fib6_entry_create(struct mlxsw_sp
*mlxsw_sp
,
5016 struct mlxsw_sp_fib_node
*fib_node
,
5017 struct rt6_info
*rt
)
5019 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5020 struct mlxsw_sp_fib_entry
*fib_entry
;
5021 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5024 fib6_entry
= kzalloc(sizeof(*fib6_entry
), GFP_KERNEL
);
5026 return ERR_PTR(-ENOMEM
);
5027 fib_entry
= &fib6_entry
->common
;
5029 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt
);
5030 if (IS_ERR(mlxsw_sp_rt6
)) {
5031 err
= PTR_ERR(mlxsw_sp_rt6
);
5032 goto err_rt6_create
;
5035 mlxsw_sp_fib6_entry_type_set(mlxsw_sp
, fib_entry
, mlxsw_sp_rt6
->rt
);
5037 INIT_LIST_HEAD(&fib6_entry
->rt6_list
);
5038 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
5039 fib6_entry
->nrt6
= 1;
5040 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
5042 goto err_nexthop6_group_get
;
5044 fib_entry
->fib_node
= fib_node
;
5048 err_nexthop6_group_get
:
5049 list_del(&mlxsw_sp_rt6
->list
);
5050 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5053 return ERR_PTR(err
);
5056 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
5057 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5059 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
5060 mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry
);
5061 WARN_ON(fib6_entry
->nrt6
);
5065 static struct mlxsw_sp_fib6_entry
*
5066 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
5067 const struct rt6_info
*nrt
, bool replace
)
5069 struct mlxsw_sp_fib6_entry
*fib6_entry
, *fallback
= NULL
;
5071 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5072 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5074 if (rt
->rt6i_table
->tb6_id
> nrt
->rt6i_table
->tb6_id
)
5076 if (rt
->rt6i_table
->tb6_id
!= nrt
->rt6i_table
->tb6_id
)
5078 if (replace
&& rt
->rt6i_metric
== nrt
->rt6i_metric
) {
5079 if (mlxsw_sp_fib6_rt_can_mp(rt
) ==
5080 mlxsw_sp_fib6_rt_can_mp(nrt
))
5082 if (mlxsw_sp_fib6_rt_can_mp(nrt
))
5083 fallback
= fallback
?: fib6_entry
;
5085 if (rt
->rt6i_metric
> nrt
->rt6i_metric
)
5086 return fallback
?: fib6_entry
;
5093 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry
*new6_entry
,
5096 struct mlxsw_sp_fib_node
*fib_node
= new6_entry
->common
.fib_node
;
5097 struct rt6_info
*nrt
= mlxsw_sp_fib6_entry_rt(new6_entry
);
5098 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5100 fib6_entry
= mlxsw_sp_fib6_node_entry_find(fib_node
, nrt
, replace
);
5102 if (replace
&& WARN_ON(!fib6_entry
))
5106 list_add_tail(&new6_entry
->common
.list
,
5107 &fib6_entry
->common
.list
);
5109 struct mlxsw_sp_fib6_entry
*last
;
5111 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
5112 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(last
);
5114 if (nrt
->rt6i_table
->tb6_id
> rt
->rt6i_table
->tb6_id
)
5120 list_add(&new6_entry
->common
.list
,
5121 &fib6_entry
->common
.list
);
5123 list_add(&new6_entry
->common
.list
,
5124 &fib_node
->entry_list
);
5131 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5133 list_del(&fib6_entry
->common
.list
);
5136 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
5137 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5142 err
= mlxsw_sp_fib6_node_list_insert(fib6_entry
, replace
);
5146 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
5148 goto err_fib_node_entry_add
;
5152 err_fib_node_entry_add
:
5153 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5158 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
5159 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5161 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib6_entry
->common
);
5162 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5165 static struct mlxsw_sp_fib6_entry
*
5166 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
5167 const struct rt6_info
*rt
)
5169 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5170 struct mlxsw_sp_fib_node
*fib_node
;
5171 struct mlxsw_sp_fib
*fib
;
5172 struct mlxsw_sp_vr
*vr
;
5174 vr
= mlxsw_sp_vr_find(mlxsw_sp
, rt
->rt6i_table
->tb6_id
);
5177 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV6
);
5179 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &rt
->rt6i_dst
.addr
,
5180 sizeof(rt
->rt6i_dst
.addr
),
5185 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5186 struct rt6_info
*iter_rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5188 if (rt
->rt6i_table
->tb6_id
== iter_rt
->rt6i_table
->tb6_id
&&
5189 rt
->rt6i_metric
== iter_rt
->rt6i_metric
&&
5190 mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
))
5197 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
5198 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5201 struct mlxsw_sp_fib_node
*fib_node
= fib6_entry
->common
.fib_node
;
5202 struct mlxsw_sp_fib6_entry
*replaced
;
5207 replaced
= list_next_entry(fib6_entry
, common
.list
);
5209 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, replaced
);
5210 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, replaced
);
5211 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5214 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp
*mlxsw_sp
,
5215 struct rt6_info
*rt
, bool replace
)
5217 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5218 struct mlxsw_sp_fib_node
*fib_node
;
5221 if (mlxsw_sp
->router
->aborted
)
5224 if (rt
->rt6i_src
.plen
)
5227 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5230 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, rt
->rt6i_table
->tb6_id
,
5232 sizeof(rt
->rt6i_dst
.addr
),
5234 MLXSW_SP_L3_PROTO_IPV6
);
5235 if (IS_ERR(fib_node
))
5236 return PTR_ERR(fib_node
);
5238 /* Before creating a new entry, try to append route to an existing
5241 fib6_entry
= mlxsw_sp_fib6_node_mp_entry_find(fib_node
, rt
, replace
);
5243 err
= mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp
, fib6_entry
, rt
);
5245 goto err_fib6_entry_nexthop_add
;
5249 fib6_entry
= mlxsw_sp_fib6_entry_create(mlxsw_sp
, fib_node
, rt
);
5250 if (IS_ERR(fib6_entry
)) {
5251 err
= PTR_ERR(fib6_entry
);
5252 goto err_fib6_entry_create
;
5255 err
= mlxsw_sp_fib6_node_entry_link(mlxsw_sp
, fib6_entry
, replace
);
5257 goto err_fib6_node_entry_link
;
5259 mlxsw_sp_fib6_entry_replace(mlxsw_sp
, fib6_entry
, replace
);
5263 err_fib6_node_entry_link
:
5264 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5265 err_fib6_entry_create
:
5266 err_fib6_entry_nexthop_add
:
5267 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5271 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp
*mlxsw_sp
,
5272 struct rt6_info
*rt
)
5274 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5275 struct mlxsw_sp_fib_node
*fib_node
;
5277 if (mlxsw_sp
->router
->aborted
)
5280 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5283 fib6_entry
= mlxsw_sp_fib6_entry_lookup(mlxsw_sp
, rt
);
5284 if (WARN_ON(!fib6_entry
))
5287 /* If route is part of a multipath entry, but not the last one
5288 * removed, then only reduce its nexthop group.
5290 if (!list_is_singular(&fib6_entry
->rt6_list
)) {
5291 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp
, fib6_entry
, rt
);
5295 fib_node
= fib6_entry
->common
.fib_node
;
5297 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5298 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5299 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5302 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
,
5303 enum mlxsw_reg_ralxx_protocol proto
,
5306 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
5307 char ralst_pl
[MLXSW_REG_RALST_LEN
];
5310 mlxsw_reg_ralta_pack(ralta_pl
, true, proto
, tree_id
);
5311 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
5315 mlxsw_reg_ralst_pack(ralst_pl
, 0xff, tree_id
);
5316 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralst
), ralst_pl
);
5320 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5321 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5322 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
5323 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
5325 mlxsw_reg_raltb_pack(raltb_pl
, vr
->id
, proto
, tree_id
);
5326 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
),
5331 mlxsw_reg_ralue_pack(ralue_pl
, proto
,
5332 MLXSW_REG_RALUE_OP_WRITE_WRITE
, vr
->id
, 0);
5333 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
5334 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
),
5343 static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp
*mlxsw_sp
,
5344 struct mfc_entry_notifier_info
*men_info
,
5347 struct mlxsw_sp_vr
*vr
;
5349 if (mlxsw_sp
->router
->aborted
)
5352 vr
= mlxsw_sp_vr_get(mlxsw_sp
, men_info
->tb_id
, NULL
);
5356 return mlxsw_sp_mr_route4_add(vr
->mr4_table
, men_info
->mfc
, replace
);
5359 static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp
*mlxsw_sp
,
5360 struct mfc_entry_notifier_info
*men_info
)
5362 struct mlxsw_sp_vr
*vr
;
5364 if (mlxsw_sp
->router
->aborted
)
5367 vr
= mlxsw_sp_vr_find(mlxsw_sp
, men_info
->tb_id
);
5371 mlxsw_sp_mr_route4_del(vr
->mr4_table
, men_info
->mfc
);
5372 mlxsw_sp_vr_put(vr
);
5376 mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp
*mlxsw_sp
,
5377 struct vif_entry_notifier_info
*ven_info
)
5379 struct mlxsw_sp_rif
*rif
;
5380 struct mlxsw_sp_vr
*vr
;
5382 if (mlxsw_sp
->router
->aborted
)
5385 vr
= mlxsw_sp_vr_get(mlxsw_sp
, ven_info
->tb_id
, NULL
);
5389 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, ven_info
->dev
);
5390 return mlxsw_sp_mr_vif_add(vr
->mr4_table
, ven_info
->dev
,
5391 ven_info
->vif_index
,
5392 ven_info
->vif_flags
, rif
);
5396 mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp
*mlxsw_sp
,
5397 struct vif_entry_notifier_info
*ven_info
)
5399 struct mlxsw_sp_vr
*vr
;
5401 if (mlxsw_sp
->router
->aborted
)
5404 vr
= mlxsw_sp_vr_find(mlxsw_sp
, ven_info
->tb_id
);
5408 mlxsw_sp_mr_vif_del(vr
->mr4_table
, ven_info
->vif_index
);
5409 mlxsw_sp_vr_put(vr
);
5412 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
)
5414 enum mlxsw_reg_ralxx_protocol proto
= MLXSW_REG_RALXX_PROTOCOL_IPV4
;
5417 err
= __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5418 MLXSW_SP_LPM_TREE_MIN
);
5422 /* The multicast router code does not need an abort trap as by default,
5423 * packets that don't match any routes are trapped to the CPU.
5426 proto
= MLXSW_REG_RALXX_PROTOCOL_IPV6
;
5427 return __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5428 MLXSW_SP_LPM_TREE_MIN
+ 1);
5431 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5432 struct mlxsw_sp_fib_node
*fib_node
)
5434 struct mlxsw_sp_fib4_entry
*fib4_entry
, *tmp
;
5436 list_for_each_entry_safe(fib4_entry
, tmp
, &fib_node
->entry_list
,
5438 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5440 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
5441 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
5442 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5443 /* Break when entry list is empty and node was freed.
5444 * Otherwise, we'll access freed memory in the next
5452 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5453 struct mlxsw_sp_fib_node
*fib_node
)
5455 struct mlxsw_sp_fib6_entry
*fib6_entry
, *tmp
;
5457 list_for_each_entry_safe(fib6_entry
, tmp
, &fib_node
->entry_list
,
5459 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5461 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5462 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5463 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5469 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5470 struct mlxsw_sp_fib_node
*fib_node
)
5472 switch (fib_node
->fib
->proto
) {
5473 case MLXSW_SP_L3_PROTO_IPV4
:
5474 mlxsw_sp_fib4_node_flush(mlxsw_sp
, fib_node
);
5476 case MLXSW_SP_L3_PROTO_IPV6
:
5477 mlxsw_sp_fib6_node_flush(mlxsw_sp
, fib_node
);
5482 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp
*mlxsw_sp
,
5483 struct mlxsw_sp_vr
*vr
,
5484 enum mlxsw_sp_l3proto proto
)
5486 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
5487 struct mlxsw_sp_fib_node
*fib_node
, *tmp
;
5489 list_for_each_entry_safe(fib_node
, tmp
, &fib
->node_list
, list
) {
5490 bool do_break
= &tmp
->list
== &fib
->node_list
;
5492 mlxsw_sp_fib_node_flush(mlxsw_sp
, fib_node
);
5498 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
)
5502 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5503 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5505 if (!mlxsw_sp_vr_is_used(vr
))
5508 mlxsw_sp_mr_table_flush(vr
->mr4_table
);
5509 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV4
);
5511 /* If virtual router was only used for IPv4, then it's no
5514 if (!mlxsw_sp_vr_is_used(vr
))
5516 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV6
);
5520 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp
*mlxsw_sp
)
5524 if (mlxsw_sp
->router
->aborted
)
5526 dev_warn(mlxsw_sp
->bus_info
->dev
, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
5527 mlxsw_sp_router_fib_flush(mlxsw_sp
);
5528 mlxsw_sp
->router
->aborted
= true;
5529 err
= mlxsw_sp_router_set_abort_trap(mlxsw_sp
);
5531 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set abort trap.\n");
5534 struct mlxsw_sp_fib_event_work
{
5535 struct work_struct work
;
5537 struct fib6_entry_notifier_info fen6_info
;
5538 struct fib_entry_notifier_info fen_info
;
5539 struct fib_rule_notifier_info fr_info
;
5540 struct fib_nh_notifier_info fnh_info
;
5541 struct mfc_entry_notifier_info men_info
;
5542 struct vif_entry_notifier_info ven_info
;
5544 struct mlxsw_sp
*mlxsw_sp
;
5545 unsigned long event
;
5548 static void mlxsw_sp_router_fib4_event_work(struct work_struct
*work
)
5550 struct mlxsw_sp_fib_event_work
*fib_work
=
5551 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5552 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5553 bool replace
, append
;
5556 /* Protect internal structures from changes */
5558 switch (fib_work
->event
) {
5559 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5560 case FIB_EVENT_ENTRY_APPEND
: /* fall through */
5561 case FIB_EVENT_ENTRY_ADD
:
5562 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5563 append
= fib_work
->event
== FIB_EVENT_ENTRY_APPEND
;
5564 err
= mlxsw_sp_router_fib4_add(mlxsw_sp
, &fib_work
->fen_info
,
5567 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5568 fib_info_put(fib_work
->fen_info
.fi
);
5570 case FIB_EVENT_ENTRY_DEL
:
5571 mlxsw_sp_router_fib4_del(mlxsw_sp
, &fib_work
->fen_info
);
5572 fib_info_put(fib_work
->fen_info
.fi
);
5574 case FIB_EVENT_RULE_ADD
:
5575 /* if we get here, a rule was added that we do not support.
5576 * just do the fib_abort
5578 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5580 case FIB_EVENT_NH_ADD
: /* fall through */
5581 case FIB_EVENT_NH_DEL
:
5582 mlxsw_sp_nexthop4_event(mlxsw_sp
, fib_work
->event
,
5583 fib_work
->fnh_info
.fib_nh
);
5584 fib_info_put(fib_work
->fnh_info
.fib_nh
->nh_parent
);
5591 static void mlxsw_sp_router_fib6_event_work(struct work_struct
*work
)
5593 struct mlxsw_sp_fib_event_work
*fib_work
=
5594 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5595 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5600 switch (fib_work
->event
) {
5601 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5602 case FIB_EVENT_ENTRY_ADD
:
5603 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5604 err
= mlxsw_sp_router_fib6_add(mlxsw_sp
,
5605 fib_work
->fen6_info
.rt
, replace
);
5607 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5608 mlxsw_sp_rt6_release(fib_work
->fen6_info
.rt
);
5610 case FIB_EVENT_ENTRY_DEL
:
5611 mlxsw_sp_router_fib6_del(mlxsw_sp
, fib_work
->fen6_info
.rt
);
5612 mlxsw_sp_rt6_release(fib_work
->fen6_info
.rt
);
5614 case FIB_EVENT_RULE_ADD
:
5615 /* if we get here, a rule was added that we do not support.
5616 * just do the fib_abort
5618 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5625 static void mlxsw_sp_router_fibmr_event_work(struct work_struct
*work
)
5627 struct mlxsw_sp_fib_event_work
*fib_work
=
5628 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5629 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5634 switch (fib_work
->event
) {
5635 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5636 case FIB_EVENT_ENTRY_ADD
:
5637 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5639 err
= mlxsw_sp_router_fibmr_add(mlxsw_sp
, &fib_work
->men_info
,
5642 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5643 ipmr_cache_put(fib_work
->men_info
.mfc
);
5645 case FIB_EVENT_ENTRY_DEL
:
5646 mlxsw_sp_router_fibmr_del(mlxsw_sp
, &fib_work
->men_info
);
5647 ipmr_cache_put(fib_work
->men_info
.mfc
);
5649 case FIB_EVENT_VIF_ADD
:
5650 err
= mlxsw_sp_router_fibmr_vif_add(mlxsw_sp
,
5651 &fib_work
->ven_info
);
5653 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5654 dev_put(fib_work
->ven_info
.dev
);
5656 case FIB_EVENT_VIF_DEL
:
5657 mlxsw_sp_router_fibmr_vif_del(mlxsw_sp
,
5658 &fib_work
->ven_info
);
5659 dev_put(fib_work
->ven_info
.dev
);
5661 case FIB_EVENT_RULE_ADD
:
5662 /* if we get here, a rule was added that we do not support.
5663 * just do the fib_abort
5665 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5672 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5673 struct fib_notifier_info
*info
)
5675 struct fib_entry_notifier_info
*fen_info
;
5676 struct fib_nh_notifier_info
*fnh_info
;
5678 switch (fib_work
->event
) {
5679 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5680 case FIB_EVENT_ENTRY_APPEND
: /* fall through */
5681 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5682 case FIB_EVENT_ENTRY_DEL
:
5683 fen_info
= container_of(info
, struct fib_entry_notifier_info
,
5685 fib_work
->fen_info
= *fen_info
;
5686 /* Take reference on fib_info to prevent it from being
5687 * freed while work is queued. Release it afterwards.
5689 fib_info_hold(fib_work
->fen_info
.fi
);
5691 case FIB_EVENT_NH_ADD
: /* fall through */
5692 case FIB_EVENT_NH_DEL
:
5693 fnh_info
= container_of(info
, struct fib_nh_notifier_info
,
5695 fib_work
->fnh_info
= *fnh_info
;
5696 fib_info_hold(fib_work
->fnh_info
.fib_nh
->nh_parent
);
5701 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5702 struct fib_notifier_info
*info
)
5704 struct fib6_entry_notifier_info
*fen6_info
;
5706 switch (fib_work
->event
) {
5707 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5708 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5709 case FIB_EVENT_ENTRY_DEL
:
5710 fen6_info
= container_of(info
, struct fib6_entry_notifier_info
,
5712 fib_work
->fen6_info
= *fen6_info
;
5713 rt6_hold(fib_work
->fen6_info
.rt
);
5719 mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5720 struct fib_notifier_info
*info
)
5722 switch (fib_work
->event
) {
5723 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5724 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5725 case FIB_EVENT_ENTRY_DEL
:
5726 memcpy(&fib_work
->men_info
, info
, sizeof(fib_work
->men_info
));
5727 ipmr_cache_hold(fib_work
->men_info
.mfc
);
5729 case FIB_EVENT_VIF_ADD
: /* fall through */
5730 case FIB_EVENT_VIF_DEL
:
5731 memcpy(&fib_work
->ven_info
, info
, sizeof(fib_work
->ven_info
));
5732 dev_hold(fib_work
->ven_info
.dev
);
5737 static int mlxsw_sp_router_fib_rule_event(unsigned long event
,
5738 struct fib_notifier_info
*info
,
5739 struct mlxsw_sp
*mlxsw_sp
)
5741 struct netlink_ext_ack
*extack
= info
->extack
;
5742 struct fib_rule_notifier_info
*fr_info
;
5743 struct fib_rule
*rule
;
5746 /* nothing to do at the moment */
5747 if (event
== FIB_EVENT_RULE_DEL
)
5750 if (mlxsw_sp
->router
->aborted
)
5753 fr_info
= container_of(info
, struct fib_rule_notifier_info
, info
);
5754 rule
= fr_info
->rule
;
5756 switch (info
->family
) {
5758 if (!fib4_rule_default(rule
) && !rule
->l3mdev
)
5762 if (!fib6_rule_default(rule
) && !rule
->l3mdev
)
5765 case RTNL_FAMILY_IPMR
:
5766 if (!ipmr_rule_default(rule
) && !rule
->l3mdev
)
5772 NL_SET_ERR_MSG(extack
, "spectrum: FIB rules not supported. Aborting offload");
5777 /* Called with rcu_read_lock() */
5778 static int mlxsw_sp_router_fib_event(struct notifier_block
*nb
,
5779 unsigned long event
, void *ptr
)
5781 struct mlxsw_sp_fib_event_work
*fib_work
;
5782 struct fib_notifier_info
*info
= ptr
;
5783 struct mlxsw_sp_router
*router
;
5786 if (!net_eq(info
->net
, &init_net
) ||
5787 (info
->family
!= AF_INET
&& info
->family
!= AF_INET6
&&
5788 info
->family
!= RTNL_FAMILY_IPMR
))
5791 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
5794 case FIB_EVENT_RULE_ADD
: /* fall through */
5795 case FIB_EVENT_RULE_DEL
:
5796 err
= mlxsw_sp_router_fib_rule_event(event
, info
,
5802 fib_work
= kzalloc(sizeof(*fib_work
), GFP_ATOMIC
);
5803 if (WARN_ON(!fib_work
))
5806 fib_work
->mlxsw_sp
= router
->mlxsw_sp
;
5807 fib_work
->event
= event
;
5809 switch (info
->family
) {
5811 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib4_event_work
);
5812 mlxsw_sp_router_fib4_event(fib_work
, info
);
5815 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib6_event_work
);
5816 mlxsw_sp_router_fib6_event(fib_work
, info
);
5818 case RTNL_FAMILY_IPMR
:
5819 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fibmr_event_work
);
5820 mlxsw_sp_router_fibmr_event(fib_work
, info
);
5824 mlxsw_core_schedule_work(&fib_work
->work
);
5829 static struct mlxsw_sp_rif
*
5830 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp
*mlxsw_sp
,
5831 const struct net_device
*dev
)
5835 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
5836 if (mlxsw_sp
->router
->rifs
[i
] &&
5837 mlxsw_sp
->router
->rifs
[i
]->dev
== dev
)
5838 return mlxsw_sp
->router
->rifs
[i
];
5843 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp
*mlxsw_sp
, u16 rif
)
5845 char ritr_pl
[MLXSW_REG_RITR_LEN
];
5848 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif
);
5849 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
5850 if (WARN_ON_ONCE(err
))
5853 mlxsw_reg_ritr_enable_set(ritr_pl
, false);
5854 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
5857 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
5858 struct mlxsw_sp_rif
*rif
)
5860 mlxsw_sp_router_rif_disable(mlxsw_sp
, rif
->rif_index
);
5861 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp
, rif
);
5862 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp
, rif
);
5866 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif
*rif
, struct net_device
*dev
,
5867 unsigned long event
)
5869 struct inet6_dev
*inet6_dev
;
5870 bool addr_list_empty
= true;
5871 struct in_device
*idev
;
5877 idev
= __in_dev_get_rtnl(dev
);
5878 if (idev
&& idev
->ifa_list
)
5879 addr_list_empty
= false;
5881 inet6_dev
= __in6_dev_get(dev
);
5882 if (addr_list_empty
&& inet6_dev
&&
5883 !list_empty(&inet6_dev
->addr_list
))
5884 addr_list_empty
= false;
5886 if (rif
&& addr_list_empty
&&
5887 !netif_is_l3_slave(rif
->dev
))
5889 /* It is possible we already removed the RIF ourselves
5890 * if it was assigned to a netdev that is now a bridge
5899 static enum mlxsw_sp_rif_type
5900 mlxsw_sp_dev_rif_type(const struct mlxsw_sp
*mlxsw_sp
,
5901 const struct net_device
*dev
)
5903 enum mlxsw_sp_fid_type type
;
5905 if (mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
))
5906 return MLXSW_SP_RIF_TYPE_IPIP_LB
;
5908 /* Otherwise RIF type is derived from the type of the underlying FID. */
5909 if (is_vlan_dev(dev
) && netif_is_bridge_master(vlan_dev_real_dev(dev
)))
5910 type
= MLXSW_SP_FID_TYPE_8021Q
;
5911 else if (netif_is_bridge_master(dev
) && br_vlan_enabled(dev
))
5912 type
= MLXSW_SP_FID_TYPE_8021Q
;
5913 else if (netif_is_bridge_master(dev
))
5914 type
= MLXSW_SP_FID_TYPE_8021D
;
5916 type
= MLXSW_SP_FID_TYPE_RFID
;
5918 return mlxsw_sp_fid_type_rif_type(mlxsw_sp
, type
);
5921 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp
*mlxsw_sp
, u16
*p_rif_index
)
5925 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
5926 if (!mlxsw_sp
->router
->rifs
[i
]) {
5935 static struct mlxsw_sp_rif
*mlxsw_sp_rif_alloc(size_t rif_size
, u16 rif_index
,
5937 struct net_device
*l3_dev
)
5939 struct mlxsw_sp_rif
*rif
;
5941 rif
= kzalloc(rif_size
, GFP_KERNEL
);
5945 INIT_LIST_HEAD(&rif
->nexthop_list
);
5946 INIT_LIST_HEAD(&rif
->neigh_list
);
5947 ether_addr_copy(rif
->addr
, l3_dev
->dev_addr
);
5948 rif
->mtu
= l3_dev
->mtu
;
5951 rif
->rif_index
= rif_index
;
5956 struct mlxsw_sp_rif
*mlxsw_sp_rif_by_index(const struct mlxsw_sp
*mlxsw_sp
,
5959 return mlxsw_sp
->router
->rifs
[rif_index
];
5962 u16
mlxsw_sp_rif_index(const struct mlxsw_sp_rif
*rif
)
5964 return rif
->rif_index
;
5967 u16
mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
5969 return lb_rif
->common
.rif_index
;
5972 u16
mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
5974 return lb_rif
->ul_vr_id
;
5977 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif
*rif
)
5979 return rif
->dev
->ifindex
;
5982 const struct net_device
*mlxsw_sp_rif_dev(const struct mlxsw_sp_rif
*rif
)
5987 static struct mlxsw_sp_rif
*
5988 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
5989 const struct mlxsw_sp_rif_params
*params
,
5990 struct netlink_ext_ack
*extack
)
5992 u32 tb_id
= l3mdev_fib_table(params
->dev
);
5993 const struct mlxsw_sp_rif_ops
*ops
;
5994 struct mlxsw_sp_fid
*fid
= NULL
;
5995 enum mlxsw_sp_rif_type type
;
5996 struct mlxsw_sp_rif
*rif
;
5997 struct mlxsw_sp_vr
*vr
;
6001 type
= mlxsw_sp_dev_rif_type(mlxsw_sp
, params
->dev
);
6002 ops
= mlxsw_sp
->router
->rif_ops_arr
[type
];
6004 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
? : RT_TABLE_MAIN
, extack
);
6006 return ERR_CAST(vr
);
6009 err
= mlxsw_sp_rif_index_alloc(mlxsw_sp
, &rif_index
);
6011 NL_SET_ERR_MSG(extack
, "spectrum: Exceeded number of supported router interfaces");
6012 goto err_rif_index_alloc
;
6015 rif
= mlxsw_sp_rif_alloc(ops
->rif_size
, rif_index
, vr
->id
, params
->dev
);
6020 rif
->mlxsw_sp
= mlxsw_sp
;
6024 fid
= ops
->fid_get(rif
);
6033 ops
->setup(rif
, params
);
6035 err
= ops
->configure(rif
);
6039 err
= mlxsw_sp_mr_rif_add(vr
->mr4_table
, rif
);
6041 goto err_mr_rif_add
;
6043 mlxsw_sp_rif_counters_alloc(rif
);
6044 mlxsw_sp
->router
->rifs
[rif_index
] = rif
;
6049 ops
->deconfigure(rif
);
6052 mlxsw_sp_fid_put(fid
);
6056 err_rif_index_alloc
:
6058 mlxsw_sp_vr_put(vr
);
6059 return ERR_PTR(err
);
6062 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif
*rif
)
6064 const struct mlxsw_sp_rif_ops
*ops
= rif
->ops
;
6065 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6066 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6067 struct mlxsw_sp_vr
*vr
;
6069 mlxsw_sp_router_rif_gone_sync(mlxsw_sp
, rif
);
6070 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6072 mlxsw_sp
->router
->rifs
[rif
->rif_index
] = NULL
;
6073 mlxsw_sp_rif_counters_free(rif
);
6074 mlxsw_sp_mr_rif_del(vr
->mr4_table
, rif
);
6075 ops
->deconfigure(rif
);
6077 /* Loopback RIFs are not associated with a FID. */
6078 mlxsw_sp_fid_put(fid
);
6081 mlxsw_sp_vr_put(vr
);
6085 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params
*params
,
6086 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6088 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6090 params
->vid
= mlxsw_sp_port_vlan
->vid
;
6091 params
->lag
= mlxsw_sp_port
->lagged
;
6093 params
->lag_id
= mlxsw_sp_port
->lag_id
;
6095 params
->system_port
= mlxsw_sp_port
->local_port
;
6099 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
,
6100 struct net_device
*l3_dev
,
6101 struct netlink_ext_ack
*extack
)
6103 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6104 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
6105 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6106 struct mlxsw_sp_rif
*rif
;
6107 struct mlxsw_sp_fid
*fid
;
6110 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6112 struct mlxsw_sp_rif_params params
= {
6116 mlxsw_sp_rif_subport_params_init(¶ms
, mlxsw_sp_port_vlan
);
6117 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6119 return PTR_ERR(rif
);
6122 /* FID was already created, just take a reference */
6123 fid
= rif
->ops
->fid_get(rif
);
6124 err
= mlxsw_sp_fid_port_vid_map(fid
, mlxsw_sp_port
, vid
);
6126 goto err_fid_port_vid_map
;
6128 err
= mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, false);
6130 goto err_port_vid_learning_set
;
6132 err
= mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
,
6133 BR_STATE_FORWARDING
);
6135 goto err_port_vid_stp_set
;
6137 mlxsw_sp_port_vlan
->fid
= fid
;
6141 err_port_vid_stp_set
:
6142 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6143 err_port_vid_learning_set
:
6144 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6145 err_fid_port_vid_map
:
6146 mlxsw_sp_fid_put(fid
);
6151 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6153 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6154 struct mlxsw_sp_fid
*fid
= mlxsw_sp_port_vlan
->fid
;
6155 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6157 if (WARN_ON(mlxsw_sp_fid_type(fid
) != MLXSW_SP_FID_TYPE_RFID
))
6160 mlxsw_sp_port_vlan
->fid
= NULL
;
6161 mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
, BR_STATE_BLOCKING
);
6162 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6163 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6164 /* If router port holds the last reference on the rFID, then the
6165 * associated Sub-port RIF will be destroyed.
6167 mlxsw_sp_fid_put(fid
);
6170 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device
*l3_dev
,
6171 struct net_device
*port_dev
,
6172 unsigned long event
, u16 vid
,
6173 struct netlink_ext_ack
*extack
)
6175 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(port_dev
);
6176 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
;
6178 mlxsw_sp_port_vlan
= mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port
, vid
);
6179 if (WARN_ON(!mlxsw_sp_port_vlan
))
6184 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan
,
6187 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan
);
6194 static int mlxsw_sp_inetaddr_port_event(struct net_device
*port_dev
,
6195 unsigned long event
,
6196 struct netlink_ext_ack
*extack
)
6198 if (netif_is_bridge_port(port_dev
) ||
6199 netif_is_lag_port(port_dev
) ||
6200 netif_is_ovs_port(port_dev
))
6203 return mlxsw_sp_inetaddr_port_vlan_event(port_dev
, port_dev
, event
, 1,
6207 static int __mlxsw_sp_inetaddr_lag_event(struct net_device
*l3_dev
,
6208 struct net_device
*lag_dev
,
6209 unsigned long event
, u16 vid
,
6210 struct netlink_ext_ack
*extack
)
6212 struct net_device
*port_dev
;
6213 struct list_head
*iter
;
6216 netdev_for_each_lower_dev(lag_dev
, port_dev
, iter
) {
6217 if (mlxsw_sp_port_dev_check(port_dev
)) {
6218 err
= mlxsw_sp_inetaddr_port_vlan_event(l3_dev
,
6230 static int mlxsw_sp_inetaddr_lag_event(struct net_device
*lag_dev
,
6231 unsigned long event
,
6232 struct netlink_ext_ack
*extack
)
6234 if (netif_is_bridge_port(lag_dev
))
6237 return __mlxsw_sp_inetaddr_lag_event(lag_dev
, lag_dev
, event
, 1,
6241 static int mlxsw_sp_inetaddr_bridge_event(struct net_device
*l3_dev
,
6242 unsigned long event
,
6243 struct netlink_ext_ack
*extack
)
6245 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
6246 struct mlxsw_sp_rif_params params
= {
6249 struct mlxsw_sp_rif
*rif
;
6253 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6255 return PTR_ERR(rif
);
6258 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6259 mlxsw_sp_rif_destroy(rif
);
6266 static int mlxsw_sp_inetaddr_vlan_event(struct net_device
*vlan_dev
,
6267 unsigned long event
,
6268 struct netlink_ext_ack
*extack
)
6270 struct net_device
*real_dev
= vlan_dev_real_dev(vlan_dev
);
6271 u16 vid
= vlan_dev_vlan_id(vlan_dev
);
6273 if (netif_is_bridge_port(vlan_dev
))
6276 if (mlxsw_sp_port_dev_check(real_dev
))
6277 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev
, real_dev
,
6278 event
, vid
, extack
);
6279 else if (netif_is_lag_master(real_dev
))
6280 return __mlxsw_sp_inetaddr_lag_event(vlan_dev
, real_dev
, event
,
6282 else if (netif_is_bridge_master(real_dev
) && br_vlan_enabled(real_dev
))
6283 return mlxsw_sp_inetaddr_bridge_event(vlan_dev
, event
, extack
);
6288 static int __mlxsw_sp_inetaddr_event(struct net_device
*dev
,
6289 unsigned long event
,
6290 struct netlink_ext_ack
*extack
)
6292 if (mlxsw_sp_port_dev_check(dev
))
6293 return mlxsw_sp_inetaddr_port_event(dev
, event
, extack
);
6294 else if (netif_is_lag_master(dev
))
6295 return mlxsw_sp_inetaddr_lag_event(dev
, event
, extack
);
6296 else if (netif_is_bridge_master(dev
))
6297 return mlxsw_sp_inetaddr_bridge_event(dev
, event
, extack
);
6298 else if (is_vlan_dev(dev
))
6299 return mlxsw_sp_inetaddr_vlan_event(dev
, event
, extack
);
6304 int mlxsw_sp_inetaddr_event(struct notifier_block
*unused
,
6305 unsigned long event
, void *ptr
)
6307 struct in_ifaddr
*ifa
= (struct in_ifaddr
*) ptr
;
6308 struct net_device
*dev
= ifa
->ifa_dev
->dev
;
6309 struct mlxsw_sp
*mlxsw_sp
;
6310 struct mlxsw_sp_rif
*rif
;
6313 /* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
6314 if (event
== NETDEV_UP
)
6317 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6321 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6322 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6325 err
= __mlxsw_sp_inetaddr_event(dev
, event
, NULL
);
6327 return notifier_from_errno(err
);
6330 int mlxsw_sp_inetaddr_valid_event(struct notifier_block
*unused
,
6331 unsigned long event
, void *ptr
)
6333 struct in_validator_info
*ivi
= (struct in_validator_info
*) ptr
;
6334 struct net_device
*dev
= ivi
->ivi_dev
->dev
;
6335 struct mlxsw_sp
*mlxsw_sp
;
6336 struct mlxsw_sp_rif
*rif
;
6339 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6343 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6344 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6347 err
= __mlxsw_sp_inetaddr_event(dev
, event
, ivi
->extack
);
6349 return notifier_from_errno(err
);
6352 struct mlxsw_sp_inet6addr_event_work
{
6353 struct work_struct work
;
6354 struct net_device
*dev
;
6355 unsigned long event
;
6358 static void mlxsw_sp_inet6addr_event_work(struct work_struct
*work
)
6360 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
=
6361 container_of(work
, struct mlxsw_sp_inet6addr_event_work
, work
);
6362 struct net_device
*dev
= inet6addr_work
->dev
;
6363 unsigned long event
= inet6addr_work
->event
;
6364 struct mlxsw_sp
*mlxsw_sp
;
6365 struct mlxsw_sp_rif
*rif
;
6368 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6372 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6373 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6376 __mlxsw_sp_inetaddr_event(dev
, event
, NULL
);
6380 kfree(inet6addr_work
);
6383 /* Called with rcu_read_lock() */
6384 int mlxsw_sp_inet6addr_event(struct notifier_block
*unused
,
6385 unsigned long event
, void *ptr
)
6387 struct inet6_ifaddr
*if6
= (struct inet6_ifaddr
*) ptr
;
6388 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
;
6389 struct net_device
*dev
= if6
->idev
->dev
;
6391 /* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
6392 if (event
== NETDEV_UP
)
6395 if (!mlxsw_sp_port_dev_lower_find_rcu(dev
))
6398 inet6addr_work
= kzalloc(sizeof(*inet6addr_work
), GFP_ATOMIC
);
6399 if (!inet6addr_work
)
6402 INIT_WORK(&inet6addr_work
->work
, mlxsw_sp_inet6addr_event_work
);
6403 inet6addr_work
->dev
= dev
;
6404 inet6addr_work
->event
= event
;
6406 mlxsw_core_schedule_work(&inet6addr_work
->work
);
6411 int mlxsw_sp_inet6addr_valid_event(struct notifier_block
*unused
,
6412 unsigned long event
, void *ptr
)
6414 struct in6_validator_info
*i6vi
= (struct in6_validator_info
*) ptr
;
6415 struct net_device
*dev
= i6vi
->i6vi_dev
->dev
;
6416 struct mlxsw_sp
*mlxsw_sp
;
6417 struct mlxsw_sp_rif
*rif
;
6420 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6424 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6425 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6428 err
= __mlxsw_sp_inetaddr_event(dev
, event
, i6vi
->extack
);
6430 return notifier_from_errno(err
);
6433 static int mlxsw_sp_rif_edit(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
6434 const char *mac
, int mtu
)
6436 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6439 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
6440 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6444 mlxsw_reg_ritr_mtu_set(ritr_pl
, mtu
);
6445 mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl
, mac
);
6446 mlxsw_reg_ritr_op_set(ritr_pl
, MLXSW_REG_RITR_RIF_CREATE
);
6447 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6450 int mlxsw_sp_netdevice_router_port_event(struct net_device
*dev
)
6452 struct mlxsw_sp
*mlxsw_sp
;
6453 struct mlxsw_sp_rif
*rif
;
6457 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6461 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6464 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6466 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, false);
6470 err
= mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, dev
->dev_addr
,
6475 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, dev
->dev_addr
, fid_index
, true);
6477 goto err_rif_fdb_op
;
6479 if (rif
->mtu
!= dev
->mtu
) {
6480 struct mlxsw_sp_vr
*vr
;
6482 /* The RIF is relevant only to its mr_table instance, as unlike
6483 * unicast routing, in multicast routing a RIF cannot be shared
6484 * between several multicast routing tables.
6486 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6487 mlxsw_sp_mr_rif_mtu_update(vr
->mr4_table
, rif
, dev
->mtu
);
6490 ether_addr_copy(rif
->addr
, dev
->dev_addr
);
6491 rif
->mtu
= dev
->mtu
;
6493 netdev_dbg(dev
, "Updated RIF=%d\n", rif
->rif_index
);
6498 mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, rif
->addr
, rif
->mtu
);
6500 mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, true);
6504 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp
*mlxsw_sp
,
6505 struct net_device
*l3_dev
,
6506 struct netlink_ext_ack
*extack
)
6508 struct mlxsw_sp_rif
*rif
;
6510 /* If netdev is already associated with a RIF, then we need to
6511 * destroy it and create a new one with the new virtual router ID.
6513 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6515 __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_DOWN
, extack
);
6517 return __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_UP
, extack
);
6520 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp
*mlxsw_sp
,
6521 struct net_device
*l3_dev
)
6523 struct mlxsw_sp_rif
*rif
;
6525 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6528 __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_DOWN
, NULL
);
6531 int mlxsw_sp_netdevice_vrf_event(struct net_device
*l3_dev
, unsigned long event
,
6532 struct netdev_notifier_changeupper_info
*info
)
6534 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
6541 case NETDEV_PRECHANGEUPPER
:
6543 case NETDEV_CHANGEUPPER
:
6544 if (info
->linking
) {
6545 struct netlink_ext_ack
*extack
;
6547 extack
= netdev_notifier_info_to_extack(&info
->info
);
6548 err
= mlxsw_sp_port_vrf_join(mlxsw_sp
, l3_dev
, extack
);
6550 mlxsw_sp_port_vrf_leave(mlxsw_sp
, l3_dev
);
6558 static struct mlxsw_sp_rif_subport
*
6559 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif
*rif
)
6561 return container_of(rif
, struct mlxsw_sp_rif_subport
, common
);
6564 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif
*rif
,
6565 const struct mlxsw_sp_rif_params
*params
)
6567 struct mlxsw_sp_rif_subport
*rif_subport
;
6569 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6570 rif_subport
->vid
= params
->vid
;
6571 rif_subport
->lag
= params
->lag
;
6573 rif_subport
->lag_id
= params
->lag_id
;
6575 rif_subport
->system_port
= params
->system_port
;
6578 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif
*rif
, bool enable
)
6580 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6581 struct mlxsw_sp_rif_subport
*rif_subport
;
6582 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6584 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6585 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_SP_IF
,
6586 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
6587 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
6588 mlxsw_reg_ritr_sp_if_pack(ritr_pl
, rif_subport
->lag
,
6589 rif_subport
->lag
? rif_subport
->lag_id
:
6590 rif_subport
->system_port
,
6593 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6596 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif
*rif
)
6600 err
= mlxsw_sp_rif_subport_op(rif
, true);
6604 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6605 mlxsw_sp_fid_index(rif
->fid
), true);
6607 goto err_rif_fdb_op
;
6609 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6613 mlxsw_sp_rif_subport_op(rif
, false);
6617 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif
*rif
)
6619 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6621 mlxsw_sp_fid_rif_set(fid
, NULL
);
6622 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6623 mlxsw_sp_fid_index(fid
), false);
6624 mlxsw_sp_rif_subport_op(rif
, false);
6627 static struct mlxsw_sp_fid
*
6628 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif
*rif
)
6630 return mlxsw_sp_fid_rfid_get(rif
->mlxsw_sp
, rif
->rif_index
);
6633 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops
= {
6634 .type
= MLXSW_SP_RIF_TYPE_SUBPORT
,
6635 .rif_size
= sizeof(struct mlxsw_sp_rif_subport
),
6636 .setup
= mlxsw_sp_rif_subport_setup
,
6637 .configure
= mlxsw_sp_rif_subport_configure
,
6638 .deconfigure
= mlxsw_sp_rif_subport_deconfigure
,
6639 .fid_get
= mlxsw_sp_rif_subport_fid_get
,
6642 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif
*rif
,
6643 enum mlxsw_reg_ritr_if_type type
,
6644 u16 vid_fid
, bool enable
)
6646 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6647 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6649 mlxsw_reg_ritr_pack(ritr_pl
, enable
, type
, rif
->rif_index
, rif
->vr_id
,
6651 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
6652 mlxsw_reg_ritr_fid_set(ritr_pl
, type
, vid_fid
);
6654 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6657 u8
mlxsw_sp_router_port(const struct mlxsw_sp
*mlxsw_sp
)
6659 return mlxsw_core_max_ports(mlxsw_sp
->core
) + 1;
6662 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif
*rif
)
6664 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6665 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
6668 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, true);
6672 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6673 mlxsw_sp_router_port(mlxsw_sp
), true);
6675 goto err_fid_mc_flood_set
;
6677 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6678 mlxsw_sp_router_port(mlxsw_sp
), true);
6680 goto err_fid_bc_flood_set
;
6682 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6683 mlxsw_sp_fid_index(rif
->fid
), true);
6685 goto err_rif_fdb_op
;
6687 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6691 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6692 mlxsw_sp_router_port(mlxsw_sp
), false);
6693 err_fid_bc_flood_set
:
6694 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6695 mlxsw_sp_router_port(mlxsw_sp
), false);
6696 err_fid_mc_flood_set
:
6697 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
6701 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif
*rif
)
6703 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
6704 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6705 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6707 mlxsw_sp_fid_rif_set(fid
, NULL
);
6708 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6709 mlxsw_sp_fid_index(fid
), false);
6710 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6711 mlxsw_sp_router_port(mlxsw_sp
), false);
6712 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6713 mlxsw_sp_router_port(mlxsw_sp
), false);
6714 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
6717 static struct mlxsw_sp_fid
*
6718 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif
*rif
)
6720 u16 vid
= is_vlan_dev(rif
->dev
) ? vlan_dev_vlan_id(rif
->dev
) : 1;
6722 return mlxsw_sp_fid_8021q_get(rif
->mlxsw_sp
, vid
);
6725 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops
= {
6726 .type
= MLXSW_SP_RIF_TYPE_VLAN
,
6727 .rif_size
= sizeof(struct mlxsw_sp_rif
),
6728 .configure
= mlxsw_sp_rif_vlan_configure
,
6729 .deconfigure
= mlxsw_sp_rif_vlan_deconfigure
,
6730 .fid_get
= mlxsw_sp_rif_vlan_fid_get
,
6733 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif
*rif
)
6735 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6736 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6739 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
,
6744 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6745 mlxsw_sp_router_port(mlxsw_sp
), true);
6747 goto err_fid_mc_flood_set
;
6749 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6750 mlxsw_sp_router_port(mlxsw_sp
), true);
6752 goto err_fid_bc_flood_set
;
6754 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6755 mlxsw_sp_fid_index(rif
->fid
), true);
6757 goto err_rif_fdb_op
;
6759 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6763 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6764 mlxsw_sp_router_port(mlxsw_sp
), false);
6765 err_fid_bc_flood_set
:
6766 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6767 mlxsw_sp_router_port(mlxsw_sp
), false);
6768 err_fid_mc_flood_set
:
6769 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
6773 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif
*rif
)
6775 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6776 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6777 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6779 mlxsw_sp_fid_rif_set(fid
, NULL
);
6780 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6781 mlxsw_sp_fid_index(fid
), false);
6782 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6783 mlxsw_sp_router_port(mlxsw_sp
), false);
6784 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6785 mlxsw_sp_router_port(mlxsw_sp
), false);
6786 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
6789 static struct mlxsw_sp_fid
*
6790 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif
*rif
)
6792 return mlxsw_sp_fid_8021d_get(rif
->mlxsw_sp
, rif
->dev
->ifindex
);
6795 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops
= {
6796 .type
= MLXSW_SP_RIF_TYPE_FID
,
6797 .rif_size
= sizeof(struct mlxsw_sp_rif
),
6798 .configure
= mlxsw_sp_rif_fid_configure
,
6799 .deconfigure
= mlxsw_sp_rif_fid_deconfigure
,
6800 .fid_get
= mlxsw_sp_rif_fid_fid_get
,
6803 static struct mlxsw_sp_rif_ipip_lb
*
6804 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif
*rif
)
6806 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
6810 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif
*rif
,
6811 const struct mlxsw_sp_rif_params
*params
)
6813 struct mlxsw_sp_rif_params_ipip_lb
*params_lb
;
6814 struct mlxsw_sp_rif_ipip_lb
*rif_lb
;
6816 params_lb
= container_of(params
, struct mlxsw_sp_rif_params_ipip_lb
,
6818 rif_lb
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6819 rif_lb
->lb_config
= params_lb
->lb_config
;
6823 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb
*lb_rif
,
6824 struct mlxsw_sp_vr
*ul_vr
, bool enable
)
6826 struct mlxsw_sp_rif_ipip_lb_config lb_cf
= lb_rif
->lb_config
;
6827 struct mlxsw_sp_rif
*rif
= &lb_rif
->common
;
6828 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6829 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6832 switch (lb_cf
.ul_protocol
) {
6833 case MLXSW_SP_L3_PROTO_IPV4
:
6834 saddr4
= be32_to_cpu(lb_cf
.saddr
.addr4
);
6835 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_LOOPBACK_IF
,
6836 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
6837 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl
, lb_cf
.lb_ipipt
,
6838 MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET
,
6839 ul_vr
->id
, saddr4
, lb_cf
.okey
);
6842 case MLXSW_SP_L3_PROTO_IPV6
:
6843 return -EAFNOSUPPORT
;
6846 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6850 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif
*rif
)
6852 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6853 u32 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(rif
->dev
);
6854 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6855 struct mlxsw_sp_vr
*ul_vr
;
6858 ul_vr
= mlxsw_sp_vr_get(mlxsw_sp
, ul_tb_id
, NULL
);
6860 return PTR_ERR(ul_vr
);
6862 err
= mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
, true);
6864 goto err_loopback_op
;
6866 lb_rif
->ul_vr_id
= ul_vr
->id
;
6871 mlxsw_sp_vr_put(ul_vr
);
6875 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif
*rif
)
6877 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6878 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6879 struct mlxsw_sp_vr
*ul_vr
;
6881 ul_vr
= &mlxsw_sp
->router
->vrs
[lb_rif
->ul_vr_id
];
6882 mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
, false);
6885 mlxsw_sp_vr_put(ul_vr
);
6888 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops
= {
6889 .type
= MLXSW_SP_RIF_TYPE_IPIP_LB
,
6890 .rif_size
= sizeof(struct mlxsw_sp_rif_ipip_lb
),
6891 .setup
= mlxsw_sp_rif_ipip_lb_setup
,
6892 .configure
= mlxsw_sp_rif_ipip_lb_configure
,
6893 .deconfigure
= mlxsw_sp_rif_ipip_lb_deconfigure
,
6896 static const struct mlxsw_sp_rif_ops
*mlxsw_sp_rif_ops_arr
[] = {
6897 [MLXSW_SP_RIF_TYPE_SUBPORT
] = &mlxsw_sp_rif_subport_ops
,
6898 [MLXSW_SP_RIF_TYPE_VLAN
] = &mlxsw_sp_rif_vlan_ops
,
6899 [MLXSW_SP_RIF_TYPE_FID
] = &mlxsw_sp_rif_fid_ops
,
6900 [MLXSW_SP_RIF_TYPE_IPIP_LB
] = &mlxsw_sp_rif_ipip_lb_ops
,
6903 static int mlxsw_sp_rifs_init(struct mlxsw_sp
*mlxsw_sp
)
6905 u64 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
6907 mlxsw_sp
->router
->rifs
= kcalloc(max_rifs
,
6908 sizeof(struct mlxsw_sp_rif
*),
6910 if (!mlxsw_sp
->router
->rifs
)
6913 mlxsw_sp
->router
->rif_ops_arr
= mlxsw_sp_rif_ops_arr
;
6918 static void mlxsw_sp_rifs_fini(struct mlxsw_sp
*mlxsw_sp
)
6922 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
6923 WARN_ON_ONCE(mlxsw_sp
->router
->rifs
[i
]);
6925 kfree(mlxsw_sp
->router
->rifs
);
6929 mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp
*mlxsw_sp
)
6931 char tigcr_pl
[MLXSW_REG_TIGCR_LEN
];
6933 mlxsw_reg_tigcr_pack(tigcr_pl
, true, 0);
6934 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(tigcr
), tigcr_pl
);
6937 static int mlxsw_sp_ipips_init(struct mlxsw_sp
*mlxsw_sp
)
6939 mlxsw_sp
->router
->ipip_ops_arr
= mlxsw_sp_ipip_ops_arr
;
6940 INIT_LIST_HEAD(&mlxsw_sp
->router
->ipip_list
);
6941 return mlxsw_sp_ipip_config_tigcr(mlxsw_sp
);
6944 static void mlxsw_sp_ipips_fini(struct mlxsw_sp
*mlxsw_sp
)
6946 WARN_ON(!list_empty(&mlxsw_sp
->router
->ipip_list
));
6949 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block
*nb
)
6951 struct mlxsw_sp_router
*router
;
6953 /* Flush pending FIB notifications and then flush the device's
6954 * table before requesting another dump. The FIB notification
6955 * block is unregistered, so no need to take RTNL.
6957 mlxsw_core_flush_owq();
6958 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
6959 mlxsw_sp_router_fib_flush(router
->mlxsw_sp
);
6962 #ifdef CONFIG_IP_ROUTE_MULTIPATH
6963 static void mlxsw_sp_mp_hash_header_set(char *recr2_pl
, int header
)
6965 mlxsw_reg_recr2_outer_header_enables_set(recr2_pl
, header
, true);
6968 static void mlxsw_sp_mp_hash_field_set(char *recr2_pl
, int field
)
6970 mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl
, field
, true);
6973 static void mlxsw_sp_mp4_hash_init(char *recr2_pl
)
6975 bool only_l3
= !init_net
.ipv4
.sysctl_fib_multipath_hash_policy
;
6977 mlxsw_sp_mp_hash_header_set(recr2_pl
,
6978 MLXSW_REG_RECR2_IPV4_EN_NOT_TCP_NOT_UDP
);
6979 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_EN_TCP_UDP
);
6980 mlxsw_reg_recr2_ipv4_sip_enable(recr2_pl
);
6981 mlxsw_reg_recr2_ipv4_dip_enable(recr2_pl
);
6984 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_EN_IPV4
);
6985 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_PROTOCOL
);
6986 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_SPORT
);
6987 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_DPORT
);
6990 static void mlxsw_sp_mp6_hash_init(char *recr2_pl
)
6992 mlxsw_sp_mp_hash_header_set(recr2_pl
,
6993 MLXSW_REG_RECR2_IPV6_EN_NOT_TCP_NOT_UDP
);
6994 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_EN_TCP_UDP
);
6995 mlxsw_reg_recr2_ipv6_sip_enable(recr2_pl
);
6996 mlxsw_reg_recr2_ipv6_dip_enable(recr2_pl
);
6997 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_FLOW_LABEL
);
6998 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_NEXT_HEADER
);
7001 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
7003 char recr2_pl
[MLXSW_REG_RECR2_LEN
];
7006 get_random_bytes(&seed
, sizeof(seed
));
7007 mlxsw_reg_recr2_pack(recr2_pl
, seed
);
7008 mlxsw_sp_mp4_hash_init(recr2_pl
);
7009 mlxsw_sp_mp6_hash_init(recr2_pl
);
7011 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(recr2
), recr2_pl
);
7014 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
7020 static int __mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
7022 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
7026 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_RIFS
))
7028 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
7030 mlxsw_reg_rgcr_pack(rgcr_pl
, true, true);
7031 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl
, max_rifs
);
7032 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
7038 static void __mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
7040 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
7042 mlxsw_reg_rgcr_pack(rgcr_pl
, false, false);
7043 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
7046 int mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
7048 struct mlxsw_sp_router
*router
;
7051 router
= kzalloc(sizeof(*mlxsw_sp
->router
), GFP_KERNEL
);
7054 mlxsw_sp
->router
= router
;
7055 router
->mlxsw_sp
= mlxsw_sp
;
7057 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_neighs_list
);
7058 err
= __mlxsw_sp_router_init(mlxsw_sp
);
7060 goto err_router_init
;
7062 err
= mlxsw_sp_rifs_init(mlxsw_sp
);
7066 err
= mlxsw_sp_ipips_init(mlxsw_sp
);
7068 goto err_ipips_init
;
7070 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_ht
,
7071 &mlxsw_sp_nexthop_ht_params
);
7073 goto err_nexthop_ht_init
;
7075 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_group_ht
,
7076 &mlxsw_sp_nexthop_group_ht_params
);
7078 goto err_nexthop_group_ht_init
;
7080 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_list
);
7081 err
= mlxsw_sp_lpm_init(mlxsw_sp
);
7085 err
= mlxsw_sp_mr_init(mlxsw_sp
, &mlxsw_sp_mr_tcam_ops
);
7089 err
= mlxsw_sp_vrs_init(mlxsw_sp
);
7093 err
= mlxsw_sp_neigh_init(mlxsw_sp
);
7095 goto err_neigh_init
;
7097 mlxsw_sp
->router
->netevent_nb
.notifier_call
=
7098 mlxsw_sp_router_netevent_event
;
7099 err
= register_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7101 goto err_register_netevent_notifier
;
7103 err
= mlxsw_sp_mp_hash_init(mlxsw_sp
);
7105 goto err_mp_hash_init
;
7107 mlxsw_sp
->router
->fib_nb
.notifier_call
= mlxsw_sp_router_fib_event
;
7108 err
= register_fib_notifier(&mlxsw_sp
->router
->fib_nb
,
7109 mlxsw_sp_router_fib_dump_flush
);
7111 goto err_register_fib_notifier
;
7115 err_register_fib_notifier
:
7117 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7118 err_register_netevent_notifier
:
7119 mlxsw_sp_neigh_fini(mlxsw_sp
);
7121 mlxsw_sp_vrs_fini(mlxsw_sp
);
7123 mlxsw_sp_mr_fini(mlxsw_sp
);
7125 mlxsw_sp_lpm_fini(mlxsw_sp
);
7127 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
7128 err_nexthop_group_ht_init
:
7129 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
7130 err_nexthop_ht_init
:
7131 mlxsw_sp_ipips_fini(mlxsw_sp
);
7133 mlxsw_sp_rifs_fini(mlxsw_sp
);
7135 __mlxsw_sp_router_fini(mlxsw_sp
);
7137 kfree(mlxsw_sp
->router
);
7141 void mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
7143 unregister_fib_notifier(&mlxsw_sp
->router
->fib_nb
);
7144 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7145 mlxsw_sp_neigh_fini(mlxsw_sp
);
7146 mlxsw_sp_vrs_fini(mlxsw_sp
);
7147 mlxsw_sp_mr_fini(mlxsw_sp
);
7148 mlxsw_sp_lpm_fini(mlxsw_sp
);
7149 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
7150 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
7151 mlxsw_sp_ipips_fini(mlxsw_sp
);
7152 mlxsw_sp_rifs_fini(mlxsw_sp
);
7153 __mlxsw_sp_router_fini(mlxsw_sp
);
7154 kfree(mlxsw_sp
->router
);