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_update(struct mlxsw_sp
*mlxsw_sp
,
1374 struct mlxsw_sp_rif
*rif
);
1376 mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp
*mlxsw_sp
,
1377 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1379 struct netlink_ext_ack
*extack
)
1381 struct mlxsw_sp_rif_ipip_lb
*old_lb_rif
= ipip_entry
->ol_lb
;
1382 struct mlxsw_sp_rif_ipip_lb
*new_lb_rif
;
1384 new_lb_rif
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
,
1388 if (IS_ERR(new_lb_rif
))
1389 return PTR_ERR(new_lb_rif
);
1390 ipip_entry
->ol_lb
= new_lb_rif
;
1393 list_splice_init(&old_lb_rif
->common
.nexthop_list
,
1394 &new_lb_rif
->common
.nexthop_list
);
1395 mlxsw_sp_nexthop_rif_update(mlxsw_sp
, &new_lb_rif
->common
);
1398 mlxsw_sp_rif_destroy(&old_lb_rif
->common
);
1404 * Update the offload related to an IPIP entry. This always updates decap, and
1405 * in addition to that it also:
1406 * @recreate_loopback: recreates the associated loopback RIF
1407 * @keep_encap: updates next hops that use the tunnel netdevice. This is only
1408 * relevant when recreate_loopback is true.
1409 * @update_nexthops: updates next hops, keeping the current loopback RIF. This
1410 * is only relevant when recreate_loopback is false.
1412 int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1413 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1414 bool recreate_loopback
,
1416 bool update_nexthops
,
1417 struct netlink_ext_ack
*extack
)
1421 /* RIFs can't be edited, so to update loopback, we need to destroy and
1422 * recreate it. That creates a window of opportunity where RALUE and
1423 * RATR registers end up referencing a RIF that's already gone. RATRs
1424 * are handled in mlxsw_sp_ipip_entry_ol_lb_update(), and to take care
1425 * of RALUE, demote the decap route back.
1427 if (ipip_entry
->decap_fib_entry
)
1428 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1430 if (recreate_loopback
) {
1431 err
= mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp
, ipip_entry
,
1432 keep_encap
, extack
);
1435 } else if (update_nexthops
) {
1436 mlxsw_sp_nexthop_rif_update(mlxsw_sp
,
1437 &ipip_entry
->ol_lb
->common
);
1440 if (ipip_entry
->ol_dev
->flags
& IFF_UP
)
1441 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1446 static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1447 struct net_device
*ol_dev
,
1448 struct netlink_ext_ack
*extack
)
1450 struct mlxsw_sp_ipip_entry
*ipip_entry
=
1451 mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1455 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1456 true, false, false, extack
);
1460 mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1461 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1462 struct net_device
*ul_dev
,
1463 struct netlink_ext_ack
*extack
)
1465 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1466 true, true, false, extack
);
1470 mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp
*mlxsw_sp
,
1471 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1472 struct net_device
*ul_dev
)
1474 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1475 false, false, true, NULL
);
1479 mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp
*mlxsw_sp
,
1480 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1481 struct net_device
*ul_dev
)
1483 /* A down underlay device causes encapsulated packets to not be
1484 * forwarded, but decap still works. So refresh next hops without
1485 * touching anything else.
1487 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1488 false, false, true, NULL
);
1492 mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp
*mlxsw_sp
,
1493 struct net_device
*ol_dev
,
1494 struct netlink_ext_ack
*extack
)
1496 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1497 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1500 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1502 /* A change might make a tunnel eligible for offloading, but
1503 * that is currently not implemented. What falls to slow path
1508 /* A change might make a tunnel not eligible for offloading. */
1509 if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
,
1510 ipip_entry
->ipipt
)) {
1511 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1515 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1516 err
= ipip_ops
->ol_netdev_change(mlxsw_sp
, ipip_entry
, extack
);
1520 void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1521 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1523 struct net_device
*ol_dev
= ipip_entry
->ol_dev
;
1525 if (ol_dev
->flags
& IFF_UP
)
1526 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1527 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1530 /* The configuration where several tunnels have the same local address in the
1531 * same underlay table needs special treatment in the HW. That is currently not
1532 * implemented in the driver. This function finds and demotes the first tunnel
1533 * with a given source address, except the one passed in in the argument
1537 mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp
*mlxsw_sp
,
1538 enum mlxsw_sp_l3proto ul_proto
,
1539 union mlxsw_sp_l3addr saddr
,
1541 const struct mlxsw_sp_ipip_entry
*except
)
1543 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1545 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1547 if (ipip_entry
!= except
&&
1548 mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, saddr
,
1549 ul_tb_id
, ipip_entry
)) {
1550 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1558 static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp
*mlxsw_sp
,
1559 struct net_device
*ul_dev
)
1561 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1563 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1565 struct net_device
*ipip_ul_dev
=
1566 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1568 if (ipip_ul_dev
== ul_dev
)
1569 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1573 int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp
*mlxsw_sp
,
1574 struct net_device
*ol_dev
,
1575 unsigned long event
,
1576 struct netdev_notifier_info
*info
)
1578 struct netdev_notifier_changeupper_info
*chup
;
1579 struct netlink_ext_ack
*extack
;
1582 case NETDEV_REGISTER
:
1583 return mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp
, ol_dev
);
1584 case NETDEV_UNREGISTER
:
1585 mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp
, ol_dev
);
1588 mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp
, ol_dev
);
1591 mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp
, ol_dev
);
1593 case NETDEV_CHANGEUPPER
:
1594 chup
= container_of(info
, typeof(*chup
), info
);
1595 extack
= info
->extack
;
1596 if (netif_is_l3_master(chup
->upper_dev
))
1597 return mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp
,
1602 extack
= info
->extack
;
1603 return mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp
,
1610 __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1611 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1612 struct net_device
*ul_dev
,
1613 unsigned long event
,
1614 struct netdev_notifier_info
*info
)
1616 struct netdev_notifier_changeupper_info
*chup
;
1617 struct netlink_ext_ack
*extack
;
1620 case NETDEV_CHANGEUPPER
:
1621 chup
= container_of(info
, typeof(*chup
), info
);
1622 extack
= info
->extack
;
1623 if (netif_is_l3_master(chup
->upper_dev
))
1624 return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp
,
1631 return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp
, ipip_entry
,
1634 return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp
,
1642 mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1643 struct net_device
*ul_dev
,
1644 unsigned long event
,
1645 struct netdev_notifier_info
*info
)
1647 struct mlxsw_sp_ipip_entry
*ipip_entry
= NULL
;
1650 while ((ipip_entry
= mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
,
1653 err
= __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp
, ipip_entry
,
1654 ul_dev
, event
, info
);
1656 mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp
,
1665 struct mlxsw_sp_neigh_key
{
1666 struct neighbour
*n
;
1669 struct mlxsw_sp_neigh_entry
{
1670 struct list_head rif_list_node
;
1671 struct rhash_head ht_node
;
1672 struct mlxsw_sp_neigh_key key
;
1675 unsigned char ha
[ETH_ALEN
];
1676 struct list_head nexthop_list
; /* list of nexthops using
1679 struct list_head nexthop_neighs_list_node
;
1680 unsigned int counter_index
;
1684 static const struct rhashtable_params mlxsw_sp_neigh_ht_params
= {
1685 .key_offset
= offsetof(struct mlxsw_sp_neigh_entry
, key
),
1686 .head_offset
= offsetof(struct mlxsw_sp_neigh_entry
, ht_node
),
1687 .key_len
= sizeof(struct mlxsw_sp_neigh_key
),
1690 struct mlxsw_sp_neigh_entry
*
1691 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif
*rif
,
1692 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1695 if (list_empty(&rif
->neigh_list
))
1698 return list_first_entry(&rif
->neigh_list
,
1699 typeof(*neigh_entry
),
1702 if (list_is_last(&neigh_entry
->rif_list_node
, &rif
->neigh_list
))
1704 return list_next_entry(neigh_entry
, rif_list_node
);
1707 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1709 return neigh_entry
->key
.n
->tbl
->family
;
1713 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1715 return neigh_entry
->ha
;
1718 u32
mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1720 struct neighbour
*n
;
1722 n
= neigh_entry
->key
.n
;
1723 return ntohl(*((__be32
*) n
->primary_key
));
1727 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1729 struct neighbour
*n
;
1731 n
= neigh_entry
->key
.n
;
1732 return (struct in6_addr
*) &n
->primary_key
;
1735 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp
*mlxsw_sp
,
1736 struct mlxsw_sp_neigh_entry
*neigh_entry
,
1739 if (!neigh_entry
->counter_valid
)
1742 return mlxsw_sp_flow_counter_get(mlxsw_sp
, neigh_entry
->counter_index
,
1746 static struct mlxsw_sp_neigh_entry
*
1747 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
,
1750 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1752 neigh_entry
= kzalloc(sizeof(*neigh_entry
), GFP_KERNEL
);
1756 neigh_entry
->key
.n
= n
;
1757 neigh_entry
->rif
= rif
;
1758 INIT_LIST_HEAD(&neigh_entry
->nexthop_list
);
1763 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1769 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp
*mlxsw_sp
,
1770 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1772 return rhashtable_insert_fast(&mlxsw_sp
->router
->neigh_ht
,
1773 &neigh_entry
->ht_node
,
1774 mlxsw_sp_neigh_ht_params
);
1778 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp
*mlxsw_sp
,
1779 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1781 rhashtable_remove_fast(&mlxsw_sp
->router
->neigh_ht
,
1782 &neigh_entry
->ht_node
,
1783 mlxsw_sp_neigh_ht_params
);
1787 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp
*mlxsw_sp
,
1788 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1790 struct devlink
*devlink
;
1791 const char *table_name
;
1793 switch (mlxsw_sp_neigh_entry_type(neigh_entry
)) {
1795 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST4
;
1798 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST6
;
1805 devlink
= priv_to_devlink(mlxsw_sp
->core
);
1806 return devlink_dpipe_table_counter_enabled(devlink
, table_name
);
1810 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
1811 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1813 if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp
, neigh_entry
))
1816 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &neigh_entry
->counter_index
))
1819 neigh_entry
->counter_valid
= true;
1823 mlxsw_sp_neigh_counter_free(struct mlxsw_sp
*mlxsw_sp
,
1824 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1826 if (!neigh_entry
->counter_valid
)
1828 mlxsw_sp_flow_counter_free(mlxsw_sp
,
1829 neigh_entry
->counter_index
);
1830 neigh_entry
->counter_valid
= false;
1833 static struct mlxsw_sp_neigh_entry
*
1834 mlxsw_sp_neigh_entry_create(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
1836 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1837 struct mlxsw_sp_rif
*rif
;
1840 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, n
->dev
);
1842 return ERR_PTR(-EINVAL
);
1844 neigh_entry
= mlxsw_sp_neigh_entry_alloc(mlxsw_sp
, n
, rif
->rif_index
);
1846 return ERR_PTR(-ENOMEM
);
1848 err
= mlxsw_sp_neigh_entry_insert(mlxsw_sp
, neigh_entry
);
1850 goto err_neigh_entry_insert
;
1852 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
1853 list_add(&neigh_entry
->rif_list_node
, &rif
->neigh_list
);
1857 err_neigh_entry_insert
:
1858 mlxsw_sp_neigh_entry_free(neigh_entry
);
1859 return ERR_PTR(err
);
1863 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
1864 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1866 list_del(&neigh_entry
->rif_list_node
);
1867 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
1868 mlxsw_sp_neigh_entry_remove(mlxsw_sp
, neigh_entry
);
1869 mlxsw_sp_neigh_entry_free(neigh_entry
);
1872 static struct mlxsw_sp_neigh_entry
*
1873 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
1875 struct mlxsw_sp_neigh_key key
;
1878 return rhashtable_lookup_fast(&mlxsw_sp
->router
->neigh_ht
,
1879 &key
, mlxsw_sp_neigh_ht_params
);
1883 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp
*mlxsw_sp
)
1885 unsigned long interval
;
1887 #if IS_ENABLED(CONFIG_IPV6)
1888 interval
= min_t(unsigned long,
1889 NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
),
1890 NEIGH_VAR(&nd_tbl
.parms
, DELAY_PROBE_TIME
));
1892 interval
= NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
);
1894 mlxsw_sp
->router
->neighs_update
.interval
= jiffies_to_msecs(interval
);
1897 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
1901 struct net_device
*dev
;
1902 struct neighbour
*n
;
1907 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl
, ent_index
, &rif
, &dip
);
1909 if (!mlxsw_sp
->router
->rifs
[rif
]) {
1910 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
1915 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
1916 n
= neigh_lookup(&arp_tbl
, &dipn
, dev
);
1918 netdev_err(dev
, "Failed to find matching neighbour for IP=%pI4h\n",
1923 netdev_dbg(dev
, "Updating neighbour with IP=%pI4h\n", &dip
);
1924 neigh_event_send(n
, NULL
);
1928 #if IS_ENABLED(CONFIG_IPV6)
1929 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1933 struct net_device
*dev
;
1934 struct neighbour
*n
;
1935 struct in6_addr dip
;
1938 mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl
, rec_index
, &rif
,
1941 if (!mlxsw_sp
->router
->rifs
[rif
]) {
1942 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
1946 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
1947 n
= neigh_lookup(&nd_tbl
, &dip
, dev
);
1949 netdev_err(dev
, "Failed to find matching neighbour for IP=%pI6c\n",
1954 netdev_dbg(dev
, "Updating neighbour with IP=%pI6c\n", &dip
);
1955 neigh_event_send(n
, NULL
);
1959 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1966 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
1973 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
1975 /* Hardware starts counting at 0, so add 1. */
1978 /* Each record consists of several neighbour entries. */
1979 for (i
= 0; i
< num_entries
; i
++) {
1982 ent_index
= rec_index
* MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
+ i
;
1983 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp
, rauhtd_pl
,
1989 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1993 /* One record contains one entry. */
1994 mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp
, rauhtd_pl
,
1998 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp
*mlxsw_sp
,
1999 char *rauhtd_pl
, int rec_index
)
2001 switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, rec_index
)) {
2002 case MLXSW_REG_RAUHTD_TYPE_IPV4
:
2003 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2006 case MLXSW_REG_RAUHTD_TYPE_IPV6
:
2007 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2013 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl
)
2015 u8 num_rec
, last_rec_index
, num_entries
;
2017 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2018 last_rec_index
= num_rec
- 1;
2020 if (num_rec
< MLXSW_REG_RAUHTD_REC_MAX_NUM
)
2022 if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, last_rec_index
) ==
2023 MLXSW_REG_RAUHTD_TYPE_IPV6
)
2026 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
2028 if (++num_entries
== MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
)
2034 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
,
2036 enum mlxsw_reg_rauhtd_type type
)
2041 /* Make sure the neighbour's netdev isn't removed in the
2046 mlxsw_reg_rauhtd_pack(rauhtd_pl
, type
);
2047 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(rauhtd
),
2050 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Failed to dump neighbour table\n");
2053 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2054 for (i
= 0; i
< num_rec
; i
++)
2055 mlxsw_sp_router_neigh_rec_process(mlxsw_sp
, rauhtd_pl
,
2057 } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl
));
2063 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
)
2065 enum mlxsw_reg_rauhtd_type type
;
2069 rauhtd_pl
= kmalloc(MLXSW_REG_RAUHTD_LEN
, GFP_KERNEL
);
2073 type
= MLXSW_REG_RAUHTD_TYPE_IPV4
;
2074 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2078 type
= MLXSW_REG_RAUHTD_TYPE_IPV6
;
2079 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2085 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp
*mlxsw_sp
)
2087 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2089 /* Take RTNL mutex here to prevent lists from changes */
2091 list_for_each_entry(neigh_entry
, &mlxsw_sp
->router
->nexthop_neighs_list
,
2092 nexthop_neighs_list_node
)
2093 /* If this neigh have nexthops, make the kernel think this neigh
2094 * is active regardless of the traffic.
2096 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2101 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp
*mlxsw_sp
)
2103 unsigned long interval
= mlxsw_sp
->router
->neighs_update
.interval
;
2105 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
,
2106 msecs_to_jiffies(interval
));
2109 static void mlxsw_sp_router_neighs_update_work(struct work_struct
*work
)
2111 struct mlxsw_sp_router
*router
;
2114 router
= container_of(work
, struct mlxsw_sp_router
,
2115 neighs_update
.dw
.work
);
2116 err
= mlxsw_sp_router_neighs_update_rauhtd(router
->mlxsw_sp
);
2118 dev_err(router
->mlxsw_sp
->bus_info
->dev
, "Could not update kernel for neigh activity");
2120 mlxsw_sp_router_neighs_update_nh(router
->mlxsw_sp
);
2122 mlxsw_sp_router_neighs_update_work_schedule(router
->mlxsw_sp
);
2125 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct
*work
)
2127 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2128 struct mlxsw_sp_router
*router
;
2130 router
= container_of(work
, struct mlxsw_sp_router
,
2131 nexthop_probe_dw
.work
);
2132 /* Iterate over nexthop neighbours, find those who are unresolved and
2133 * send arp on them. This solves the chicken-egg problem when
2134 * the nexthop wouldn't get offloaded until the neighbor is resolved
2135 * but it wouldn't get resolved ever in case traffic is flowing in HW
2136 * using different nexthop.
2138 * Take RTNL mutex here to prevent lists from changes.
2141 list_for_each_entry(neigh_entry
, &router
->nexthop_neighs_list
,
2142 nexthop_neighs_list_node
)
2143 if (!neigh_entry
->connected
)
2144 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2147 mlxsw_core_schedule_dw(&router
->nexthop_probe_dw
,
2148 MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL
);
2152 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
2153 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2156 static enum mlxsw_reg_rauht_op
mlxsw_sp_rauht_op(bool adding
)
2158 return adding
? MLXSW_REG_RAUHT_OP_WRITE_ADD
:
2159 MLXSW_REG_RAUHT_OP_WRITE_DELETE
;
2163 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp
*mlxsw_sp
,
2164 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2165 enum mlxsw_reg_rauht_op op
)
2167 struct neighbour
*n
= neigh_entry
->key
.n
;
2168 u32 dip
= ntohl(*((__be32
*) n
->primary_key
));
2169 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2171 mlxsw_reg_rauht_pack4(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2173 if (neigh_entry
->counter_valid
)
2174 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2175 neigh_entry
->counter_index
);
2176 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2180 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp
*mlxsw_sp
,
2181 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2182 enum mlxsw_reg_rauht_op op
)
2184 struct neighbour
*n
= neigh_entry
->key
.n
;
2185 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2186 const char *dip
= n
->primary_key
;
2188 mlxsw_reg_rauht_pack6(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2190 if (neigh_entry
->counter_valid
)
2191 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2192 neigh_entry
->counter_index
);
2193 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2196 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry
*neigh_entry
)
2198 struct neighbour
*n
= neigh_entry
->key
.n
;
2200 /* Packets with a link-local destination address are trapped
2201 * after LPM lookup and never reach the neighbour table, so
2202 * there is no need to program such neighbours to the device.
2204 if (ipv6_addr_type((struct in6_addr
*) &n
->primary_key
) &
2205 IPV6_ADDR_LINKLOCAL
)
2211 mlxsw_sp_neigh_entry_update(struct mlxsw_sp
*mlxsw_sp
,
2212 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2215 if (!adding
&& !neigh_entry
->connected
)
2217 neigh_entry
->connected
= adding
;
2218 if (neigh_entry
->key
.n
->tbl
->family
== AF_INET
) {
2219 mlxsw_sp_router_neigh_entry_op4(mlxsw_sp
, neigh_entry
,
2220 mlxsw_sp_rauht_op(adding
));
2221 } else if (neigh_entry
->key
.n
->tbl
->family
== AF_INET6
) {
2222 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
2224 mlxsw_sp_router_neigh_entry_op6(mlxsw_sp
, neigh_entry
,
2225 mlxsw_sp_rauht_op(adding
));
2232 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp
*mlxsw_sp
,
2233 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2237 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
2239 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
2240 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, true);
2243 struct mlxsw_sp_netevent_work
{
2244 struct work_struct work
;
2245 struct mlxsw_sp
*mlxsw_sp
;
2246 struct neighbour
*n
;
2249 static void mlxsw_sp_router_neigh_event_work(struct work_struct
*work
)
2251 struct mlxsw_sp_netevent_work
*net_work
=
2252 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2253 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2254 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2255 struct neighbour
*n
= net_work
->n
;
2256 unsigned char ha
[ETH_ALEN
];
2257 bool entry_connected
;
2260 /* If these parameters are changed after we release the lock,
2261 * then we are guaranteed to receive another event letting us
2264 read_lock_bh(&n
->lock
);
2265 memcpy(ha
, n
->ha
, ETH_ALEN
);
2266 nud_state
= n
->nud_state
;
2268 read_unlock_bh(&n
->lock
);
2271 entry_connected
= nud_state
& NUD_VALID
&& !dead
;
2272 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
2273 if (!entry_connected
&& !neigh_entry
)
2276 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
2277 if (IS_ERR(neigh_entry
))
2281 memcpy(neigh_entry
->ha
, ha
, ETH_ALEN
);
2282 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, entry_connected
);
2283 mlxsw_sp_nexthop_neigh_update(mlxsw_sp
, neigh_entry
, !entry_connected
);
2285 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
2286 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2294 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
);
2296 static void mlxsw_sp_router_mp_hash_event_work(struct work_struct
*work
)
2298 struct mlxsw_sp_netevent_work
*net_work
=
2299 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2300 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2302 mlxsw_sp_mp_hash_init(mlxsw_sp
);
2306 static int mlxsw_sp_router_netevent_event(struct notifier_block
*nb
,
2307 unsigned long event
, void *ptr
)
2309 struct mlxsw_sp_netevent_work
*net_work
;
2310 struct mlxsw_sp_port
*mlxsw_sp_port
;
2311 struct mlxsw_sp_router
*router
;
2312 struct mlxsw_sp
*mlxsw_sp
;
2313 unsigned long interval
;
2314 struct neigh_parms
*p
;
2315 struct neighbour
*n
;
2319 case NETEVENT_DELAY_PROBE_TIME_UPDATE
:
2322 /* We don't care about changes in the default table. */
2323 if (!p
->dev
|| (p
->tbl
->family
!= AF_INET
&&
2324 p
->tbl
->family
!= AF_INET6
))
2327 /* We are in atomic context and can't take RTNL mutex,
2328 * so use RCU variant to walk the device chain.
2330 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(p
->dev
);
2334 mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2335 interval
= jiffies_to_msecs(NEIGH_VAR(p
, DELAY_PROBE_TIME
));
2336 mlxsw_sp
->router
->neighs_update
.interval
= interval
;
2338 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2340 case NETEVENT_NEIGH_UPDATE
:
2343 if (n
->tbl
->family
!= AF_INET
&& n
->tbl
->family
!= AF_INET6
)
2346 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(n
->dev
);
2350 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2352 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2356 INIT_WORK(&net_work
->work
, mlxsw_sp_router_neigh_event_work
);
2357 net_work
->mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2360 /* Take a reference to ensure the neighbour won't be
2361 * destructed until we drop the reference in delayed
2365 mlxsw_core_schedule_work(&net_work
->work
);
2366 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2368 case NETEVENT_MULTIPATH_HASH_UPDATE
:
2371 if (!net_eq(net
, &init_net
))
2374 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2378 router
= container_of(nb
, struct mlxsw_sp_router
, netevent_nb
);
2379 INIT_WORK(&net_work
->work
, mlxsw_sp_router_mp_hash_event_work
);
2380 net_work
->mlxsw_sp
= router
->mlxsw_sp
;
2381 mlxsw_core_schedule_work(&net_work
->work
);
2388 static int mlxsw_sp_neigh_init(struct mlxsw_sp
*mlxsw_sp
)
2392 err
= rhashtable_init(&mlxsw_sp
->router
->neigh_ht
,
2393 &mlxsw_sp_neigh_ht_params
);
2397 /* Initialize the polling interval according to the default
2400 mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp
);
2402 /* Create the delayed works for the activity_update */
2403 INIT_DELAYED_WORK(&mlxsw_sp
->router
->neighs_update
.dw
,
2404 mlxsw_sp_router_neighs_update_work
);
2405 INIT_DELAYED_WORK(&mlxsw_sp
->router
->nexthop_probe_dw
,
2406 mlxsw_sp_router_probe_unresolved_nexthops
);
2407 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
, 0);
2408 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->nexthop_probe_dw
, 0);
2412 static void mlxsw_sp_neigh_fini(struct mlxsw_sp
*mlxsw_sp
)
2414 cancel_delayed_work_sync(&mlxsw_sp
->router
->neighs_update
.dw
);
2415 cancel_delayed_work_sync(&mlxsw_sp
->router
->nexthop_probe_dw
);
2416 rhashtable_destroy(&mlxsw_sp
->router
->neigh_ht
);
2419 static int mlxsw_sp_neigh_rif_flush(struct mlxsw_sp
*mlxsw_sp
,
2420 const struct mlxsw_sp_rif
*rif
)
2422 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2424 mlxsw_reg_rauht_pack(rauht_pl
, MLXSW_REG_RAUHT_OP_WRITE_DELETE_ALL
,
2425 rif
->rif_index
, rif
->addr
);
2426 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2429 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
2430 struct mlxsw_sp_rif
*rif
)
2432 struct mlxsw_sp_neigh_entry
*neigh_entry
, *tmp
;
2434 mlxsw_sp_neigh_rif_flush(mlxsw_sp
, rif
);
2435 list_for_each_entry_safe(neigh_entry
, tmp
, &rif
->neigh_list
,
2437 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2440 enum mlxsw_sp_nexthop_type
{
2441 MLXSW_SP_NEXTHOP_TYPE_ETH
,
2442 MLXSW_SP_NEXTHOP_TYPE_IPIP
,
2445 struct mlxsw_sp_nexthop_key
{
2446 struct fib_nh
*fib_nh
;
2449 struct mlxsw_sp_nexthop
{
2450 struct list_head neigh_list_node
; /* member of neigh entry list */
2451 struct list_head rif_list_node
;
2452 struct list_head router_list_node
;
2453 struct mlxsw_sp_nexthop_group
*nh_grp
; /* pointer back to the group
2456 struct rhash_head ht_node
;
2457 struct mlxsw_sp_nexthop_key key
;
2458 unsigned char gw_addr
[sizeof(struct in6_addr
)];
2462 int num_adj_entries
;
2463 struct mlxsw_sp_rif
*rif
;
2464 u8 should_offload
:1, /* set indicates this neigh is connected and
2465 * should be put to KVD linear area of this group.
2467 offloaded
:1, /* set in case the neigh is actually put into
2468 * KVD linear area of this group.
2470 update
:1; /* set indicates that MAC of this neigh should be
2473 enum mlxsw_sp_nexthop_type type
;
2475 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2476 struct mlxsw_sp_ipip_entry
*ipip_entry
;
2478 unsigned int counter_index
;
2482 struct mlxsw_sp_nexthop_group
{
2484 struct rhash_head ht_node
;
2485 struct list_head fib_list
; /* list of fib entries that use this group */
2486 struct neigh_table
*neigh_tbl
;
2487 u8 adj_index_valid
:1,
2488 gateway
:1; /* routes using the group use a gateway */
2492 int sum_norm_weight
;
2493 struct mlxsw_sp_nexthop nexthops
[0];
2494 #define nh_rif nexthops[0].rif
2497 void mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
2498 struct mlxsw_sp_nexthop
*nh
)
2500 struct devlink
*devlink
;
2502 devlink
= priv_to_devlink(mlxsw_sp
->core
);
2503 if (!devlink_dpipe_table_counter_enabled(devlink
,
2504 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
))
2507 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &nh
->counter_index
))
2510 nh
->counter_valid
= true;
2513 void mlxsw_sp_nexthop_counter_free(struct mlxsw_sp
*mlxsw_sp
,
2514 struct mlxsw_sp_nexthop
*nh
)
2516 if (!nh
->counter_valid
)
2518 mlxsw_sp_flow_counter_free(mlxsw_sp
, nh
->counter_index
);
2519 nh
->counter_valid
= false;
2522 int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp
*mlxsw_sp
,
2523 struct mlxsw_sp_nexthop
*nh
, u64
*p_counter
)
2525 if (!nh
->counter_valid
)
2528 return mlxsw_sp_flow_counter_get(mlxsw_sp
, nh
->counter_index
,
2532 struct mlxsw_sp_nexthop
*mlxsw_sp_nexthop_next(struct mlxsw_sp_router
*router
,
2533 struct mlxsw_sp_nexthop
*nh
)
2536 if (list_empty(&router
->nexthop_list
))
2539 return list_first_entry(&router
->nexthop_list
,
2540 typeof(*nh
), router_list_node
);
2542 if (list_is_last(&nh
->router_list_node
, &router
->nexthop_list
))
2544 return list_next_entry(nh
, router_list_node
);
2547 bool mlxsw_sp_nexthop_offload(struct mlxsw_sp_nexthop
*nh
)
2549 return nh
->offloaded
;
2552 unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop
*nh
)
2556 return nh
->neigh_entry
->ha
;
2559 int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop
*nh
, u32
*p_adj_index
,
2560 u32
*p_adj_size
, u32
*p_adj_hash_index
)
2562 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2563 u32 adj_hash_index
= 0;
2566 if (!nh
->offloaded
|| !nh_grp
->adj_index_valid
)
2569 *p_adj_index
= nh_grp
->adj_index
;
2570 *p_adj_size
= nh_grp
->ecmp_size
;
2572 for (i
= 0; i
< nh_grp
->count
; i
++) {
2573 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2577 if (nh_iter
->offloaded
)
2578 adj_hash_index
+= nh_iter
->num_adj_entries
;
2581 *p_adj_hash_index
= adj_hash_index
;
2585 struct mlxsw_sp_rif
*mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop
*nh
)
2590 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop
*nh
)
2592 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2595 for (i
= 0; i
< nh_grp
->count
; i
++) {
2596 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2598 if (nh_iter
->type
== MLXSW_SP_NEXTHOP_TYPE_IPIP
)
2604 static struct fib_info
*
2605 mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2607 return nh_grp
->priv
;
2610 struct mlxsw_sp_nexthop_group_cmp_arg
{
2611 enum mlxsw_sp_l3proto proto
;
2613 struct fib_info
*fi
;
2614 struct mlxsw_sp_fib6_entry
*fib6_entry
;
2619 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2620 const struct in6_addr
*gw
, int ifindex
)
2624 for (i
= 0; i
< nh_grp
->count
; i
++) {
2625 const struct mlxsw_sp_nexthop
*nh
;
2627 nh
= &nh_grp
->nexthops
[i
];
2628 if (nh
->ifindex
== ifindex
&&
2629 ipv6_addr_equal(gw
, (struct in6_addr
*) nh
->gw_addr
))
2637 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2638 const struct mlxsw_sp_fib6_entry
*fib6_entry
)
2640 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2642 if (nh_grp
->count
!= fib6_entry
->nrt6
)
2645 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2646 struct in6_addr
*gw
;
2649 ifindex
= mlxsw_sp_rt6
->rt
->dst
.dev
->ifindex
;
2650 gw
= &mlxsw_sp_rt6
->rt
->rt6i_gateway
;
2651 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp
, gw
, ifindex
))
2659 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg
*arg
, const void *ptr
)
2661 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= arg
->key
;
2662 const struct mlxsw_sp_nexthop_group
*nh_grp
= ptr
;
2664 switch (cmp_arg
->proto
) {
2665 case MLXSW_SP_L3_PROTO_IPV4
:
2666 return cmp_arg
->fi
!= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2667 case MLXSW_SP_L3_PROTO_IPV6
:
2668 return !mlxsw_sp_nexthop6_group_cmp(nh_grp
,
2669 cmp_arg
->fib6_entry
);
2677 mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2679 return nh_grp
->neigh_tbl
->family
;
2682 static u32
mlxsw_sp_nexthop_group_hash_obj(const void *data
, u32 len
, u32 seed
)
2684 const struct mlxsw_sp_nexthop_group
*nh_grp
= data
;
2685 const struct mlxsw_sp_nexthop
*nh
;
2686 struct fib_info
*fi
;
2690 switch (mlxsw_sp_nexthop_group_type(nh_grp
)) {
2692 fi
= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2693 return jhash(&fi
, sizeof(fi
), seed
);
2695 val
= nh_grp
->count
;
2696 for (i
= 0; i
< nh_grp
->count
; i
++) {
2697 nh
= &nh_grp
->nexthops
[i
];
2700 return jhash(&val
, sizeof(val
), seed
);
2708 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry
*fib6_entry
, u32 seed
)
2710 unsigned int val
= fib6_entry
->nrt6
;
2711 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2712 struct net_device
*dev
;
2714 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2715 dev
= mlxsw_sp_rt6
->rt
->dst
.dev
;
2716 val
^= dev
->ifindex
;
2719 return jhash(&val
, sizeof(val
), seed
);
2723 mlxsw_sp_nexthop_group_hash(const void *data
, u32 len
, u32 seed
)
2725 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= data
;
2727 switch (cmp_arg
->proto
) {
2728 case MLXSW_SP_L3_PROTO_IPV4
:
2729 return jhash(&cmp_arg
->fi
, sizeof(cmp_arg
->fi
), seed
);
2730 case MLXSW_SP_L3_PROTO_IPV6
:
2731 return mlxsw_sp_nexthop6_group_hash(cmp_arg
->fib6_entry
, seed
);
2738 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params
= {
2739 .head_offset
= offsetof(struct mlxsw_sp_nexthop_group
, ht_node
),
2740 .hashfn
= mlxsw_sp_nexthop_group_hash
,
2741 .obj_hashfn
= mlxsw_sp_nexthop_group_hash_obj
,
2742 .obj_cmpfn
= mlxsw_sp_nexthop_group_cmp
,
2745 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp
*mlxsw_sp
,
2746 struct mlxsw_sp_nexthop_group
*nh_grp
)
2748 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
2752 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2754 mlxsw_sp_nexthop_group_ht_params
);
2757 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp
*mlxsw_sp
,
2758 struct mlxsw_sp_nexthop_group
*nh_grp
)
2760 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
2764 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2766 mlxsw_sp_nexthop_group_ht_params
);
2769 static struct mlxsw_sp_nexthop_group
*
2770 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
2771 struct fib_info
*fi
)
2773 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
2775 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV4
;
2777 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2779 mlxsw_sp_nexthop_group_ht_params
);
2782 static struct mlxsw_sp_nexthop_group
*
2783 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
2784 struct mlxsw_sp_fib6_entry
*fib6_entry
)
2786 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
2788 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV6
;
2789 cmp_arg
.fib6_entry
= fib6_entry
;
2790 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2792 mlxsw_sp_nexthop_group_ht_params
);
2795 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params
= {
2796 .key_offset
= offsetof(struct mlxsw_sp_nexthop
, key
),
2797 .head_offset
= offsetof(struct mlxsw_sp_nexthop
, ht_node
),
2798 .key_len
= sizeof(struct mlxsw_sp_nexthop_key
),
2801 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp
*mlxsw_sp
,
2802 struct mlxsw_sp_nexthop
*nh
)
2804 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_ht
,
2805 &nh
->ht_node
, mlxsw_sp_nexthop_ht_params
);
2808 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp
*mlxsw_sp
,
2809 struct mlxsw_sp_nexthop
*nh
)
2811 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_ht
, &nh
->ht_node
,
2812 mlxsw_sp_nexthop_ht_params
);
2815 static struct mlxsw_sp_nexthop
*
2816 mlxsw_sp_nexthop_lookup(struct mlxsw_sp
*mlxsw_sp
,
2817 struct mlxsw_sp_nexthop_key key
)
2819 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_ht
, &key
,
2820 mlxsw_sp_nexthop_ht_params
);
2823 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp
*mlxsw_sp
,
2824 const struct mlxsw_sp_fib
*fib
,
2825 u32 adj_index
, u16 ecmp_size
,
2829 char raleu_pl
[MLXSW_REG_RALEU_LEN
];
2831 mlxsw_reg_raleu_pack(raleu_pl
,
2832 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
,
2833 fib
->vr
->id
, adj_index
, ecmp_size
, new_adj_index
,
2835 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raleu
), raleu_pl
);
2838 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp
*mlxsw_sp
,
2839 struct mlxsw_sp_nexthop_group
*nh_grp
,
2840 u32 old_adj_index
, u16 old_ecmp_size
)
2842 struct mlxsw_sp_fib_entry
*fib_entry
;
2843 struct mlxsw_sp_fib
*fib
= NULL
;
2846 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2847 if (fib
== fib_entry
->fib_node
->fib
)
2849 fib
= fib_entry
->fib_node
->fib
;
2850 err
= mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp
, fib
,
2861 static int __mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
2862 struct mlxsw_sp_nexthop
*nh
)
2864 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
2865 char ratr_pl
[MLXSW_REG_RATR_LEN
];
2867 mlxsw_reg_ratr_pack(ratr_pl
, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY
,
2868 true, MLXSW_REG_RATR_TYPE_ETHERNET
,
2869 adj_index
, neigh_entry
->rif
);
2870 mlxsw_reg_ratr_eth_entry_pack(ratr_pl
, neigh_entry
->ha
);
2871 if (nh
->counter_valid
)
2872 mlxsw_reg_ratr_counter_pack(ratr_pl
, nh
->counter_index
, true);
2874 mlxsw_reg_ratr_counter_pack(ratr_pl
, 0, false);
2876 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ratr
), ratr_pl
);
2879 int mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
2880 struct mlxsw_sp_nexthop
*nh
)
2884 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
2887 err
= __mlxsw_sp_nexthop_update(mlxsw_sp
, adj_index
+ i
, nh
);
2895 static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
2897 struct mlxsw_sp_nexthop
*nh
)
2899 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
2901 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[nh
->ipip_entry
->ipipt
];
2902 return ipip_ops
->nexthop_update(mlxsw_sp
, adj_index
, nh
->ipip_entry
);
2905 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
2907 struct mlxsw_sp_nexthop
*nh
)
2911 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
2914 err
= __mlxsw_sp_nexthop_ipip_update(mlxsw_sp
, adj_index
+ i
,
2924 mlxsw_sp_nexthop_group_update(struct mlxsw_sp
*mlxsw_sp
,
2925 struct mlxsw_sp_nexthop_group
*nh_grp
,
2928 u32 adj_index
= nh_grp
->adj_index
; /* base */
2929 struct mlxsw_sp_nexthop
*nh
;
2933 for (i
= 0; i
< nh_grp
->count
; i
++) {
2934 nh
= &nh_grp
->nexthops
[i
];
2936 if (!nh
->should_offload
) {
2941 if (nh
->update
|| reallocate
) {
2943 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
2944 err
= mlxsw_sp_nexthop_update
2945 (mlxsw_sp
, adj_index
, nh
);
2947 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
2948 err
= mlxsw_sp_nexthop_ipip_update
2949 (mlxsw_sp
, adj_index
, nh
);
2957 adj_index
+= nh
->num_adj_entries
;
2963 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
2964 const struct mlxsw_sp_fib_entry
*fib_entry
);
2967 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp
*mlxsw_sp
,
2968 struct mlxsw_sp_nexthop_group
*nh_grp
)
2970 struct mlxsw_sp_fib_entry
*fib_entry
;
2973 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2974 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
2977 err
= mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
2985 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
2986 enum mlxsw_reg_ralue_op op
, int err
);
2989 mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group
*nh_grp
)
2991 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_WRITE
;
2992 struct mlxsw_sp_fib_entry
*fib_entry
;
2994 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2995 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
2998 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
3002 static void mlxsw_sp_adj_grp_size_round_up(u16
*p_adj_grp_size
)
3004 /* Valid sizes for an adjacency group are:
3005 * 1-64, 512, 1024, 2048 and 4096.
3007 if (*p_adj_grp_size
<= 64)
3009 else if (*p_adj_grp_size
<= 512)
3010 *p_adj_grp_size
= 512;
3011 else if (*p_adj_grp_size
<= 1024)
3012 *p_adj_grp_size
= 1024;
3013 else if (*p_adj_grp_size
<= 2048)
3014 *p_adj_grp_size
= 2048;
3016 *p_adj_grp_size
= 4096;
3019 static void mlxsw_sp_adj_grp_size_round_down(u16
*p_adj_grp_size
,
3020 unsigned int alloc_size
)
3022 if (alloc_size
>= 4096)
3023 *p_adj_grp_size
= 4096;
3024 else if (alloc_size
>= 2048)
3025 *p_adj_grp_size
= 2048;
3026 else if (alloc_size
>= 1024)
3027 *p_adj_grp_size
= 1024;
3028 else if (alloc_size
>= 512)
3029 *p_adj_grp_size
= 512;
3032 static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp
*mlxsw_sp
,
3033 u16
*p_adj_grp_size
)
3035 unsigned int alloc_size
;
3038 /* Round up the requested group size to the next size supported
3039 * by the device and make sure the request can be satisfied.
3041 mlxsw_sp_adj_grp_size_round_up(p_adj_grp_size
);
3042 err
= mlxsw_sp_kvdl_alloc_size_query(mlxsw_sp
, *p_adj_grp_size
,
3046 /* It is possible the allocation results in more allocated
3047 * entries than requested. Try to use as much of them as
3050 mlxsw_sp_adj_grp_size_round_down(p_adj_grp_size
, alloc_size
);
3056 mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group
*nh_grp
)
3058 int i
, g
= 0, sum_norm_weight
= 0;
3059 struct mlxsw_sp_nexthop
*nh
;
3061 for (i
= 0; i
< nh_grp
->count
; i
++) {
3062 nh
= &nh_grp
->nexthops
[i
];
3064 if (!nh
->should_offload
)
3067 g
= gcd(nh
->nh_weight
, g
);
3072 for (i
= 0; i
< nh_grp
->count
; i
++) {
3073 nh
= &nh_grp
->nexthops
[i
];
3075 if (!nh
->should_offload
)
3077 nh
->norm_nh_weight
= nh
->nh_weight
/ g
;
3078 sum_norm_weight
+= nh
->norm_nh_weight
;
3081 nh_grp
->sum_norm_weight
= sum_norm_weight
;
3085 mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group
*nh_grp
)
3087 int total
= nh_grp
->sum_norm_weight
;
3088 u16 ecmp_size
= nh_grp
->ecmp_size
;
3089 int i
, weight
= 0, lower_bound
= 0;
3091 for (i
= 0; i
< nh_grp
->count
; i
++) {
3092 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3095 if (!nh
->should_offload
)
3097 weight
+= nh
->norm_nh_weight
;
3098 upper_bound
= DIV_ROUND_CLOSEST(ecmp_size
* weight
, total
);
3099 nh
->num_adj_entries
= upper_bound
- lower_bound
;
3100 lower_bound
= upper_bound
;
3105 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp
*mlxsw_sp
,
3106 struct mlxsw_sp_nexthop_group
*nh_grp
)
3108 u16 ecmp_size
, old_ecmp_size
;
3109 struct mlxsw_sp_nexthop
*nh
;
3110 bool offload_change
= false;
3112 bool old_adj_index_valid
;
3117 if (!nh_grp
->gateway
) {
3118 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3122 for (i
= 0; i
< nh_grp
->count
; i
++) {
3123 nh
= &nh_grp
->nexthops
[i
];
3125 if (nh
->should_offload
!= nh
->offloaded
) {
3126 offload_change
= true;
3127 if (nh
->should_offload
)
3131 if (!offload_change
) {
3132 /* Nothing was added or removed, so no need to reallocate. Just
3133 * update MAC on existing adjacency indexes.
3135 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, false);
3137 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3142 mlxsw_sp_nexthop_group_normalize(nh_grp
);
3143 if (!nh_grp
->sum_norm_weight
)
3144 /* No neigh of this group is connected so we just set
3145 * the trap and let everthing flow through kernel.
3149 ecmp_size
= nh_grp
->sum_norm_weight
;
3150 err
= mlxsw_sp_fix_adj_grp_size(mlxsw_sp
, &ecmp_size
);
3152 /* No valid allocation size available. */
3155 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, ecmp_size
, &adj_index
);
3157 /* We ran out of KVD linear space, just set the
3158 * trap and let everything flow through kernel.
3160 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to allocate KVD linear area for nexthop group.\n");
3163 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3164 old_adj_index
= nh_grp
->adj_index
;
3165 old_ecmp_size
= nh_grp
->ecmp_size
;
3166 nh_grp
->adj_index_valid
= 1;
3167 nh_grp
->adj_index
= adj_index
;
3168 nh_grp
->ecmp_size
= ecmp_size
;
3169 mlxsw_sp_nexthop_group_rebalance(nh_grp
);
3170 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, true);
3172 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3176 if (!old_adj_index_valid
) {
3177 /* The trap was set for fib entries, so we have to call
3178 * fib entry update to unset it and use adjacency index.
3180 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3182 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to add adjacency index to fib entries.\n");
3188 err
= mlxsw_sp_adj_index_mass_update(mlxsw_sp
, nh_grp
,
3189 old_adj_index
, old_ecmp_size
);
3190 mlxsw_sp_kvdl_free(mlxsw_sp
, old_adj_index
);
3192 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to mass-update adjacency index for nexthop group.\n");
3196 /* Offload state within the group changed, so update the flags. */
3197 mlxsw_sp_nexthop_fib_entries_refresh(nh_grp
);
3202 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3203 nh_grp
->adj_index_valid
= 0;
3204 for (i
= 0; i
< nh_grp
->count
; i
++) {
3205 nh
= &nh_grp
->nexthops
[i
];
3208 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3210 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set traps for fib entries.\n");
3211 if (old_adj_index_valid
)
3212 mlxsw_sp_kvdl_free(mlxsw_sp
, nh_grp
->adj_index
);
3215 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop
*nh
,
3219 nh
->should_offload
= 1;
3220 else if (nh
->offloaded
)
3221 nh
->should_offload
= 0;
3226 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
3227 struct mlxsw_sp_neigh_entry
*neigh_entry
,
3230 struct mlxsw_sp_nexthop
*nh
;
3232 list_for_each_entry(nh
, &neigh_entry
->nexthop_list
,
3234 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3235 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3239 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop
*nh
,
3240 struct mlxsw_sp_rif
*rif
)
3246 list_add(&nh
->rif_list_node
, &rif
->nexthop_list
);
3249 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop
*nh
)
3254 list_del(&nh
->rif_list_node
);
3258 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp
*mlxsw_sp
,
3259 struct mlxsw_sp_nexthop
*nh
)
3261 struct mlxsw_sp_neigh_entry
*neigh_entry
;
3262 struct neighbour
*n
;
3266 if (!nh
->nh_grp
->gateway
|| nh
->neigh_entry
)
3269 /* Take a reference of neigh here ensuring that neigh would
3270 * not be destructed before the nexthop entry is finished.
3271 * The reference is taken either in neigh_lookup() or
3272 * in neigh_create() in case n is not found.
3274 n
= neigh_lookup(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
, nh
->rif
->dev
);
3276 n
= neigh_create(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
,
3280 neigh_event_send(n
, NULL
);
3282 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
3284 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
3285 if (IS_ERR(neigh_entry
)) {
3287 goto err_neigh_entry_create
;
3291 /* If that is the first nexthop connected to that neigh, add to
3292 * nexthop_neighs_list
3294 if (list_empty(&neigh_entry
->nexthop_list
))
3295 list_add_tail(&neigh_entry
->nexthop_neighs_list_node
,
3296 &mlxsw_sp
->router
->nexthop_neighs_list
);
3298 nh
->neigh_entry
= neigh_entry
;
3299 list_add_tail(&nh
->neigh_list_node
, &neigh_entry
->nexthop_list
);
3300 read_lock_bh(&n
->lock
);
3301 nud_state
= n
->nud_state
;
3303 read_unlock_bh(&n
->lock
);
3304 __mlxsw_sp_nexthop_neigh_update(nh
, !(nud_state
& NUD_VALID
&& !dead
));
3308 err_neigh_entry_create
:
3313 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp
*mlxsw_sp
,
3314 struct mlxsw_sp_nexthop
*nh
)
3316 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
3317 struct neighbour
*n
;
3321 n
= neigh_entry
->key
.n
;
3323 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3324 list_del(&nh
->neigh_list_node
);
3325 nh
->neigh_entry
= NULL
;
3327 /* If that is the last nexthop connected to that neigh, remove from
3328 * nexthop_neighs_list
3330 if (list_empty(&neigh_entry
->nexthop_list
))
3331 list_del(&neigh_entry
->nexthop_neighs_list_node
);
3333 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
3334 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
3339 static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device
*ol_dev
)
3341 struct net_device
*ul_dev
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
3343 return ul_dev
? (ul_dev
->flags
& IFF_UP
) : true;
3346 static int mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp
*mlxsw_sp
,
3347 struct mlxsw_sp_nexthop
*nh
,
3348 struct net_device
*ol_dev
)
3352 if (!nh
->nh_grp
->gateway
|| nh
->ipip_entry
)
3355 nh
->ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
3356 if (!nh
->ipip_entry
)
3359 removing
= !mlxsw_sp_ipip_netdev_ul_up(ol_dev
);
3360 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3364 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp
*mlxsw_sp
,
3365 struct mlxsw_sp_nexthop
*nh
)
3367 struct mlxsw_sp_ipip_entry
*ipip_entry
= nh
->ipip_entry
;
3372 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3373 nh
->ipip_entry
= NULL
;
3376 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
3377 const struct fib_nh
*fib_nh
,
3378 enum mlxsw_sp_ipip_type
*p_ipipt
)
3380 struct net_device
*dev
= fib_nh
->nh_dev
;
3383 fib_nh
->nh_parent
->fib_type
== RTN_UNICAST
&&
3384 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, p_ipipt
);
3387 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3388 struct mlxsw_sp_nexthop
*nh
)
3391 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3392 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp
, nh
);
3393 mlxsw_sp_nexthop_rif_fini(nh
);
3395 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3396 mlxsw_sp_nexthop_rif_fini(nh
);
3397 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp
, nh
);
3402 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp
*mlxsw_sp
,
3403 struct mlxsw_sp_nexthop
*nh
,
3404 struct fib_nh
*fib_nh
)
3406 struct mlxsw_sp_router
*router
= mlxsw_sp
->router
;
3407 struct net_device
*dev
= fib_nh
->nh_dev
;
3408 enum mlxsw_sp_ipip_type ipipt
;
3409 struct mlxsw_sp_rif
*rif
;
3412 if (mlxsw_sp_nexthop4_ipip_type(mlxsw_sp
, fib_nh
, &ipipt
) &&
3413 router
->ipip_ops_arr
[ipipt
]->can_offload(mlxsw_sp
, dev
,
3414 MLXSW_SP_L3_PROTO_IPV4
)) {
3415 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
3416 err
= mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, dev
);
3419 mlxsw_sp_nexthop_rif_init(nh
, &nh
->ipip_entry
->ol_lb
->common
);
3423 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
3424 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
3428 mlxsw_sp_nexthop_rif_init(nh
, rif
);
3429 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
3431 goto err_neigh_init
;
3436 mlxsw_sp_nexthop_rif_fini(nh
);
3440 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3441 struct mlxsw_sp_nexthop
*nh
)
3443 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3446 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp
*mlxsw_sp
,
3447 struct mlxsw_sp_nexthop_group
*nh_grp
,
3448 struct mlxsw_sp_nexthop
*nh
,
3449 struct fib_nh
*fib_nh
)
3451 struct net_device
*dev
= fib_nh
->nh_dev
;
3452 struct in_device
*in_dev
;
3455 nh
->nh_grp
= nh_grp
;
3456 nh
->key
.fib_nh
= fib_nh
;
3457 #ifdef CONFIG_IP_ROUTE_MULTIPATH
3458 nh
->nh_weight
= fib_nh
->nh_weight
;
3462 memcpy(&nh
->gw_addr
, &fib_nh
->nh_gw
, sizeof(fib_nh
->nh_gw
));
3463 err
= mlxsw_sp_nexthop_insert(mlxsw_sp
, nh
);
3467 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
3468 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
3473 in_dev
= __in_dev_get_rtnl(dev
);
3474 if (in_dev
&& IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev
) &&
3475 fib_nh
->nh_flags
& RTNH_F_LINKDOWN
)
3478 err
= mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3480 goto err_nexthop_neigh_init
;
3484 err_nexthop_neigh_init
:
3485 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3489 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp
*mlxsw_sp
,
3490 struct mlxsw_sp_nexthop
*nh
)
3492 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3493 list_del(&nh
->router_list_node
);
3494 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
3495 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3498 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp
*mlxsw_sp
,
3499 unsigned long event
, struct fib_nh
*fib_nh
)
3501 struct mlxsw_sp_nexthop_key key
;
3502 struct mlxsw_sp_nexthop
*nh
;
3504 if (mlxsw_sp
->router
->aborted
)
3507 key
.fib_nh
= fib_nh
;
3508 nh
= mlxsw_sp_nexthop_lookup(mlxsw_sp
, key
);
3509 if (WARN_ON_ONCE(!nh
))
3513 case FIB_EVENT_NH_ADD
:
3514 mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3516 case FIB_EVENT_NH_DEL
:
3517 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3521 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3524 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
3525 struct mlxsw_sp_rif
*rif
)
3527 struct mlxsw_sp_nexthop
*nh
;
3530 list_for_each_entry(nh
, &rif
->nexthop_list
, rif_list_node
) {
3532 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3535 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3536 removing
= !mlxsw_sp_ipip_netdev_ul_up(rif
->dev
);
3543 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3544 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3548 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
3549 struct mlxsw_sp_rif
*rif
)
3551 struct mlxsw_sp_nexthop
*nh
, *tmp
;
3553 list_for_each_entry_safe(nh
, tmp
, &rif
->nexthop_list
, rif_list_node
) {
3554 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3555 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3559 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
3560 const struct fib_info
*fi
)
3562 return fi
->fib_nh
->nh_scope
== RT_SCOPE_LINK
||
3563 mlxsw_sp_nexthop4_ipip_type(mlxsw_sp
, fi
->fib_nh
, NULL
);
3566 static struct mlxsw_sp_nexthop_group
*
3567 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp
*mlxsw_sp
, struct fib_info
*fi
)
3569 struct mlxsw_sp_nexthop_group
*nh_grp
;
3570 struct mlxsw_sp_nexthop
*nh
;
3571 struct fib_nh
*fib_nh
;
3576 alloc_size
= sizeof(*nh_grp
) +
3577 fi
->fib_nhs
* sizeof(struct mlxsw_sp_nexthop
);
3578 nh_grp
= kzalloc(alloc_size
, GFP_KERNEL
);
3580 return ERR_PTR(-ENOMEM
);
3582 INIT_LIST_HEAD(&nh_grp
->fib_list
);
3583 nh_grp
->neigh_tbl
= &arp_tbl
;
3585 nh_grp
->gateway
= mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
);
3586 nh_grp
->count
= fi
->fib_nhs
;
3588 for (i
= 0; i
< nh_grp
->count
; i
++) {
3589 nh
= &nh_grp
->nexthops
[i
];
3590 fib_nh
= &fi
->fib_nh
[i
];
3591 err
= mlxsw_sp_nexthop4_init(mlxsw_sp
, nh_grp
, nh
, fib_nh
);
3593 goto err_nexthop4_init
;
3595 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
3597 goto err_nexthop_group_insert
;
3598 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3601 err_nexthop_group_insert
:
3603 for (i
--; i
>= 0; i
--) {
3604 nh
= &nh_grp
->nexthops
[i
];
3605 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3609 return ERR_PTR(err
);
3613 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
3614 struct mlxsw_sp_nexthop_group
*nh_grp
)
3616 struct mlxsw_sp_nexthop
*nh
;
3619 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
3620 for (i
= 0; i
< nh_grp
->count
; i
++) {
3621 nh
= &nh_grp
->nexthops
[i
];
3622 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3624 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3625 WARN_ON_ONCE(nh_grp
->adj_index_valid
);
3626 fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp
));
3630 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp
*mlxsw_sp
,
3631 struct mlxsw_sp_fib_entry
*fib_entry
,
3632 struct fib_info
*fi
)
3634 struct mlxsw_sp_nexthop_group
*nh_grp
;
3636 nh_grp
= mlxsw_sp_nexthop4_group_lookup(mlxsw_sp
, fi
);
3638 nh_grp
= mlxsw_sp_nexthop4_group_create(mlxsw_sp
, fi
);
3640 return PTR_ERR(nh_grp
);
3642 list_add_tail(&fib_entry
->nexthop_group_node
, &nh_grp
->fib_list
);
3643 fib_entry
->nh_group
= nh_grp
;
3647 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp
*mlxsw_sp
,
3648 struct mlxsw_sp_fib_entry
*fib_entry
)
3650 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3652 list_del(&fib_entry
->nexthop_group_node
);
3653 if (!list_empty(&nh_grp
->fib_list
))
3655 mlxsw_sp_nexthop4_group_destroy(mlxsw_sp
, nh_grp
);
3659 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
3661 struct mlxsw_sp_fib4_entry
*fib4_entry
;
3663 fib4_entry
= container_of(fib_entry
, struct mlxsw_sp_fib4_entry
,
3665 return !fib4_entry
->tos
;
3669 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
3671 struct mlxsw_sp_nexthop_group
*nh_group
= fib_entry
->nh_group
;
3673 switch (fib_entry
->fib_node
->fib
->proto
) {
3674 case MLXSW_SP_L3_PROTO_IPV4
:
3675 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry
))
3678 case MLXSW_SP_L3_PROTO_IPV6
:
3682 switch (fib_entry
->type
) {
3683 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
3684 return !!nh_group
->adj_index_valid
;
3685 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
3686 return !!nh_group
->nh_rif
;
3687 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
3694 static struct mlxsw_sp_nexthop
*
3695 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group
*nh_grp
,
3696 const struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
3700 for (i
= 0; i
< nh_grp
->count
; i
++) {
3701 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3702 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
3704 if (nh
->rif
&& nh
->rif
->dev
== rt
->dst
.dev
&&
3705 ipv6_addr_equal((const struct in6_addr
*) &nh
->gw_addr
,
3715 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3717 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3720 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
||
3721 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
) {
3722 nh_grp
->nexthops
->key
.fib_nh
->nh_flags
|= RTNH_F_OFFLOAD
;
3726 for (i
= 0; i
< nh_grp
->count
; i
++) {
3727 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3730 nh
->key
.fib_nh
->nh_flags
|= RTNH_F_OFFLOAD
;
3732 nh
->key
.fib_nh
->nh_flags
&= ~RTNH_F_OFFLOAD
;
3737 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3739 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3742 for (i
= 0; i
< nh_grp
->count
; i
++) {
3743 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3745 nh
->key
.fib_nh
->nh_flags
&= ~RTNH_F_OFFLOAD
;
3750 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3752 struct mlxsw_sp_fib6_entry
*fib6_entry
;
3753 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
3755 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
3758 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
) {
3759 list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
3760 list
)->rt
->rt6i_nh_flags
|= RTNH_F_OFFLOAD
;
3764 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
3765 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3766 struct mlxsw_sp_nexthop
*nh
;
3768 nh
= mlxsw_sp_rt6_nexthop(nh_grp
, mlxsw_sp_rt6
);
3769 if (nh
&& nh
->offloaded
)
3770 mlxsw_sp_rt6
->rt
->rt6i_nh_flags
|= RTNH_F_OFFLOAD
;
3772 mlxsw_sp_rt6
->rt
->rt6i_nh_flags
&= ~RTNH_F_OFFLOAD
;
3777 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3779 struct mlxsw_sp_fib6_entry
*fib6_entry
;
3780 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
3782 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
3784 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
3785 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
3787 rt
->rt6i_nh_flags
&= ~RTNH_F_OFFLOAD
;
3791 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3793 switch (fib_entry
->fib_node
->fib
->proto
) {
3794 case MLXSW_SP_L3_PROTO_IPV4
:
3795 mlxsw_sp_fib4_entry_offload_set(fib_entry
);
3797 case MLXSW_SP_L3_PROTO_IPV6
:
3798 mlxsw_sp_fib6_entry_offload_set(fib_entry
);
3804 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3806 switch (fib_entry
->fib_node
->fib
->proto
) {
3807 case MLXSW_SP_L3_PROTO_IPV4
:
3808 mlxsw_sp_fib4_entry_offload_unset(fib_entry
);
3810 case MLXSW_SP_L3_PROTO_IPV6
:
3811 mlxsw_sp_fib6_entry_offload_unset(fib_entry
);
3817 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
3818 enum mlxsw_reg_ralue_op op
, int err
)
3821 case MLXSW_REG_RALUE_OP_WRITE_DELETE
:
3822 return mlxsw_sp_fib_entry_offload_unset(fib_entry
);
3823 case MLXSW_REG_RALUE_OP_WRITE_WRITE
:
3826 if (mlxsw_sp_fib_entry_should_offload(fib_entry
))
3827 mlxsw_sp_fib_entry_offload_set(fib_entry
);
3829 mlxsw_sp_fib_entry_offload_unset(fib_entry
);
3837 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl
,
3838 const struct mlxsw_sp_fib_entry
*fib_entry
,
3839 enum mlxsw_reg_ralue_op op
)
3841 struct mlxsw_sp_fib
*fib
= fib_entry
->fib_node
->fib
;
3842 enum mlxsw_reg_ralxx_protocol proto
;
3845 proto
= (enum mlxsw_reg_ralxx_protocol
) fib
->proto
;
3847 switch (fib
->proto
) {
3848 case MLXSW_SP_L3_PROTO_IPV4
:
3849 p_dip
= (u32
*) fib_entry
->fib_node
->key
.addr
;
3850 mlxsw_reg_ralue_pack4(ralue_pl
, proto
, op
, fib
->vr
->id
,
3851 fib_entry
->fib_node
->key
.prefix_len
,
3854 case MLXSW_SP_L3_PROTO_IPV6
:
3855 mlxsw_reg_ralue_pack6(ralue_pl
, proto
, op
, fib
->vr
->id
,
3856 fib_entry
->fib_node
->key
.prefix_len
,
3857 fib_entry
->fib_node
->key
.addr
);
3862 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp
*mlxsw_sp
,
3863 struct mlxsw_sp_fib_entry
*fib_entry
,
3864 enum mlxsw_reg_ralue_op op
)
3866 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3867 enum mlxsw_reg_ralue_trap_action trap_action
;
3869 u32 adjacency_index
= 0;
3872 /* In case the nexthop group adjacency index is valid, use it
3873 * with provided ECMP size. Otherwise, setup trap and pass
3874 * traffic to kernel.
3876 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
3877 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
3878 adjacency_index
= fib_entry
->nh_group
->adj_index
;
3879 ecmp_size
= fib_entry
->nh_group
->ecmp_size
;
3881 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
3882 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
3885 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3886 mlxsw_reg_ralue_act_remote_pack(ralue_pl
, trap_action
, trap_id
,
3887 adjacency_index
, ecmp_size
);
3888 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3891 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp
*mlxsw_sp
,
3892 struct mlxsw_sp_fib_entry
*fib_entry
,
3893 enum mlxsw_reg_ralue_op op
)
3895 struct mlxsw_sp_rif
*rif
= fib_entry
->nh_group
->nh_rif
;
3896 enum mlxsw_reg_ralue_trap_action trap_action
;
3897 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3901 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
3902 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
3903 rif_index
= rif
->rif_index
;
3905 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
3906 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
3909 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3910 mlxsw_reg_ralue_act_local_pack(ralue_pl
, trap_action
, trap_id
,
3912 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3915 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp
*mlxsw_sp
,
3916 struct mlxsw_sp_fib_entry
*fib_entry
,
3917 enum mlxsw_reg_ralue_op op
)
3919 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3921 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3922 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
3923 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3927 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp
*mlxsw_sp
,
3928 struct mlxsw_sp_fib_entry
*fib_entry
,
3929 enum mlxsw_reg_ralue_op op
)
3931 struct mlxsw_sp_ipip_entry
*ipip_entry
= fib_entry
->decap
.ipip_entry
;
3932 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3934 if (WARN_ON(!ipip_entry
))
3937 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
3938 return ipip_ops
->fib_entry_op(mlxsw_sp
, ipip_entry
, op
,
3939 fib_entry
->decap
.tunnel_index
);
3942 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
3943 struct mlxsw_sp_fib_entry
*fib_entry
,
3944 enum mlxsw_reg_ralue_op op
)
3946 switch (fib_entry
->type
) {
3947 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
3948 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp
, fib_entry
, op
);
3949 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
3950 return mlxsw_sp_fib_entry_op_local(mlxsw_sp
, fib_entry
, op
);
3951 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP
:
3952 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp
, fib_entry
, op
);
3953 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
3954 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp
,
3960 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
3961 struct mlxsw_sp_fib_entry
*fib_entry
,
3962 enum mlxsw_reg_ralue_op op
)
3964 int err
= __mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
, op
);
3966 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, err
);
3971 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
3972 struct mlxsw_sp_fib_entry
*fib_entry
)
3974 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
3975 MLXSW_REG_RALUE_OP_WRITE_WRITE
);
3978 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp
*mlxsw_sp
,
3979 struct mlxsw_sp_fib_entry
*fib_entry
)
3981 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
3982 MLXSW_REG_RALUE_OP_WRITE_DELETE
);
3986 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
3987 const struct fib_entry_notifier_info
*fen_info
,
3988 struct mlxsw_sp_fib_entry
*fib_entry
)
3990 union mlxsw_sp_l3addr dip
= { .addr4
= htonl(fen_info
->dst
) };
3991 struct net_device
*dev
= fen_info
->fi
->fib_dev
;
3992 struct mlxsw_sp_ipip_entry
*ipip_entry
;
3993 struct fib_info
*fi
= fen_info
->fi
;
3995 switch (fen_info
->type
) {
3997 ipip_entry
= mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp
, dev
,
3998 MLXSW_SP_L3_PROTO_IPV4
, dip
);
4000 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
4001 return mlxsw_sp_fib_entry_decap_init(mlxsw_sp
,
4007 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4009 case RTN_UNREACHABLE
: /* fall through */
4010 case RTN_BLACKHOLE
: /* fall through */
4012 /* Packets hitting these routes need to be trapped, but
4013 * can do so with a lower priority than packets directed
4014 * at the host, so use action type local instead of trap.
4016 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4019 if (mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
))
4020 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4022 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4029 static struct mlxsw_sp_fib4_entry
*
4030 mlxsw_sp_fib4_entry_create(struct mlxsw_sp
*mlxsw_sp
,
4031 struct mlxsw_sp_fib_node
*fib_node
,
4032 const struct fib_entry_notifier_info
*fen_info
)
4034 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4035 struct mlxsw_sp_fib_entry
*fib_entry
;
4038 fib4_entry
= kzalloc(sizeof(*fib4_entry
), GFP_KERNEL
);
4040 return ERR_PTR(-ENOMEM
);
4041 fib_entry
= &fib4_entry
->common
;
4043 err
= mlxsw_sp_fib4_entry_type_set(mlxsw_sp
, fen_info
, fib_entry
);
4045 goto err_fib4_entry_type_set
;
4047 err
= mlxsw_sp_nexthop4_group_get(mlxsw_sp
, fib_entry
, fen_info
->fi
);
4049 goto err_nexthop4_group_get
;
4051 fib4_entry
->prio
= fen_info
->fi
->fib_priority
;
4052 fib4_entry
->tb_id
= fen_info
->tb_id
;
4053 fib4_entry
->type
= fen_info
->type
;
4054 fib4_entry
->tos
= fen_info
->tos
;
4056 fib_entry
->fib_node
= fib_node
;
4060 err_nexthop4_group_get
:
4061 err_fib4_entry_type_set
:
4063 return ERR_PTR(err
);
4066 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
4067 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4069 mlxsw_sp_nexthop4_group_put(mlxsw_sp
, &fib4_entry
->common
);
4073 static struct mlxsw_sp_fib4_entry
*
4074 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
4075 const struct fib_entry_notifier_info
*fen_info
)
4077 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4078 struct mlxsw_sp_fib_node
*fib_node
;
4079 struct mlxsw_sp_fib
*fib
;
4080 struct mlxsw_sp_vr
*vr
;
4082 vr
= mlxsw_sp_vr_find(mlxsw_sp
, fen_info
->tb_id
);
4085 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV4
);
4087 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &fen_info
->dst
,
4088 sizeof(fen_info
->dst
),
4093 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4094 if (fib4_entry
->tb_id
== fen_info
->tb_id
&&
4095 fib4_entry
->tos
== fen_info
->tos
&&
4096 fib4_entry
->type
== fen_info
->type
&&
4097 mlxsw_sp_nexthop4_group_fi(fib4_entry
->common
.nh_group
) ==
4106 static const struct rhashtable_params mlxsw_sp_fib_ht_params
= {
4107 .key_offset
= offsetof(struct mlxsw_sp_fib_node
, key
),
4108 .head_offset
= offsetof(struct mlxsw_sp_fib_node
, ht_node
),
4109 .key_len
= sizeof(struct mlxsw_sp_fib_key
),
4110 .automatic_shrinking
= true,
4113 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib
*fib
,
4114 struct mlxsw_sp_fib_node
*fib_node
)
4116 return rhashtable_insert_fast(&fib
->ht
, &fib_node
->ht_node
,
4117 mlxsw_sp_fib_ht_params
);
4120 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib
*fib
,
4121 struct mlxsw_sp_fib_node
*fib_node
)
4123 rhashtable_remove_fast(&fib
->ht
, &fib_node
->ht_node
,
4124 mlxsw_sp_fib_ht_params
);
4127 static struct mlxsw_sp_fib_node
*
4128 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
4129 size_t addr_len
, unsigned char prefix_len
)
4131 struct mlxsw_sp_fib_key key
;
4133 memset(&key
, 0, sizeof(key
));
4134 memcpy(key
.addr
, addr
, addr_len
);
4135 key
.prefix_len
= prefix_len
;
4136 return rhashtable_lookup_fast(&fib
->ht
, &key
, mlxsw_sp_fib_ht_params
);
4139 static struct mlxsw_sp_fib_node
*
4140 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib
*fib
, const void *addr
,
4141 size_t addr_len
, unsigned char prefix_len
)
4143 struct mlxsw_sp_fib_node
*fib_node
;
4145 fib_node
= kzalloc(sizeof(*fib_node
), GFP_KERNEL
);
4149 INIT_LIST_HEAD(&fib_node
->entry_list
);
4150 list_add(&fib_node
->list
, &fib
->node_list
);
4151 memcpy(fib_node
->key
.addr
, addr
, addr_len
);
4152 fib_node
->key
.prefix_len
= prefix_len
;
4157 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node
*fib_node
)
4159 list_del(&fib_node
->list
);
4160 WARN_ON(!list_empty(&fib_node
->entry_list
));
4165 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
4166 const struct mlxsw_sp_fib_entry
*fib_entry
)
4168 return list_first_entry(&fib_node
->entry_list
,
4169 struct mlxsw_sp_fib_entry
, list
) == fib_entry
;
4172 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp
*mlxsw_sp
,
4173 struct mlxsw_sp_fib
*fib
,
4174 struct mlxsw_sp_fib_node
*fib_node
)
4176 struct mlxsw_sp_prefix_usage req_prefix_usage
= {{ 0 } };
4177 struct mlxsw_sp_lpm_tree
*lpm_tree
;
4180 /* Since the tree is shared between all virtual routers we must
4181 * make sure it contains all the required prefix lengths. This
4182 * can be computed by either adding the new prefix length to the
4183 * existing prefix usage of a bound tree, or by aggregating the
4184 * prefix lengths across all virtual routers and adding the new
4188 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage
,
4189 &fib
->lpm_tree
->prefix_usage
);
4191 mlxsw_sp_vrs_prefixes(mlxsw_sp
, fib
->proto
, &req_prefix_usage
);
4192 mlxsw_sp_prefix_usage_set(&req_prefix_usage
, fib_node
->key
.prefix_len
);
4194 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
4196 if (IS_ERR(lpm_tree
))
4197 return PTR_ERR(lpm_tree
);
4199 if (fib
->lpm_tree
&& fib
->lpm_tree
->id
== lpm_tree
->id
)
4202 err
= mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp
, fib
, lpm_tree
);
4209 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp
*mlxsw_sp
,
4210 struct mlxsw_sp_fib
*fib
)
4212 if (!mlxsw_sp_prefix_usage_none(&fib
->prefix_usage
))
4214 mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp
, fib
);
4215 mlxsw_sp_lpm_tree_put(mlxsw_sp
, fib
->lpm_tree
);
4216 fib
->lpm_tree
= NULL
;
4219 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node
*fib_node
)
4221 unsigned char prefix_len
= fib_node
->key
.prefix_len
;
4222 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4224 if (fib
->prefix_ref_count
[prefix_len
]++ == 0)
4225 mlxsw_sp_prefix_usage_set(&fib
->prefix_usage
, prefix_len
);
4228 static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node
*fib_node
)
4230 unsigned char prefix_len
= fib_node
->key
.prefix_len
;
4231 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4233 if (--fib
->prefix_ref_count
[prefix_len
] == 0)
4234 mlxsw_sp_prefix_usage_clear(&fib
->prefix_usage
, prefix_len
);
4237 static int mlxsw_sp_fib_node_init(struct mlxsw_sp
*mlxsw_sp
,
4238 struct mlxsw_sp_fib_node
*fib_node
,
4239 struct mlxsw_sp_fib
*fib
)
4243 err
= mlxsw_sp_fib_node_insert(fib
, fib_node
);
4246 fib_node
->fib
= fib
;
4248 err
= mlxsw_sp_fib_lpm_tree_link(mlxsw_sp
, fib
, fib_node
);
4250 goto err_fib_lpm_tree_link
;
4252 mlxsw_sp_fib_node_prefix_inc(fib_node
);
4256 err_fib_lpm_tree_link
:
4257 fib_node
->fib
= NULL
;
4258 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4262 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp
*mlxsw_sp
,
4263 struct mlxsw_sp_fib_node
*fib_node
)
4265 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4267 mlxsw_sp_fib_node_prefix_dec(fib_node
);
4268 mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp
, fib
);
4269 fib_node
->fib
= NULL
;
4270 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4273 static struct mlxsw_sp_fib_node
*
4274 mlxsw_sp_fib_node_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
, const void *addr
,
4275 size_t addr_len
, unsigned char prefix_len
,
4276 enum mlxsw_sp_l3proto proto
)
4278 struct mlxsw_sp_fib_node
*fib_node
;
4279 struct mlxsw_sp_fib
*fib
;
4280 struct mlxsw_sp_vr
*vr
;
4283 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
, NULL
);
4285 return ERR_CAST(vr
);
4286 fib
= mlxsw_sp_vr_fib(vr
, proto
);
4288 fib_node
= mlxsw_sp_fib_node_lookup(fib
, addr
, addr_len
, prefix_len
);
4292 fib_node
= mlxsw_sp_fib_node_create(fib
, addr
, addr_len
, prefix_len
);
4295 goto err_fib_node_create
;
4298 err
= mlxsw_sp_fib_node_init(mlxsw_sp
, fib_node
, fib
);
4300 goto err_fib_node_init
;
4305 mlxsw_sp_fib_node_destroy(fib_node
);
4306 err_fib_node_create
:
4307 mlxsw_sp_vr_put(vr
);
4308 return ERR_PTR(err
);
4311 static void mlxsw_sp_fib_node_put(struct mlxsw_sp
*mlxsw_sp
,
4312 struct mlxsw_sp_fib_node
*fib_node
)
4314 struct mlxsw_sp_vr
*vr
= fib_node
->fib
->vr
;
4316 if (!list_empty(&fib_node
->entry_list
))
4318 mlxsw_sp_fib_node_fini(mlxsw_sp
, fib_node
);
4319 mlxsw_sp_fib_node_destroy(fib_node
);
4320 mlxsw_sp_vr_put(vr
);
4323 static struct mlxsw_sp_fib4_entry
*
4324 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
4325 const struct mlxsw_sp_fib4_entry
*new4_entry
)
4327 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4329 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4330 if (fib4_entry
->tb_id
> new4_entry
->tb_id
)
4332 if (fib4_entry
->tb_id
!= new4_entry
->tb_id
)
4334 if (fib4_entry
->tos
> new4_entry
->tos
)
4336 if (fib4_entry
->prio
>= new4_entry
->prio
||
4337 fib4_entry
->tos
< new4_entry
->tos
)
4345 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry
*fib4_entry
,
4346 struct mlxsw_sp_fib4_entry
*new4_entry
)
4348 struct mlxsw_sp_fib_node
*fib_node
;
4350 if (WARN_ON(!fib4_entry
))
4353 fib_node
= fib4_entry
->common
.fib_node
;
4354 list_for_each_entry_from(fib4_entry
, &fib_node
->entry_list
,
4356 if (fib4_entry
->tb_id
!= new4_entry
->tb_id
||
4357 fib4_entry
->tos
!= new4_entry
->tos
||
4358 fib4_entry
->prio
!= new4_entry
->prio
)
4362 list_add_tail(&new4_entry
->common
.list
, &fib4_entry
->common
.list
);
4367 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry
*new4_entry
,
4368 bool replace
, bool append
)
4370 struct mlxsw_sp_fib_node
*fib_node
= new4_entry
->common
.fib_node
;
4371 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4373 fib4_entry
= mlxsw_sp_fib4_node_entry_find(fib_node
, new4_entry
);
4376 return mlxsw_sp_fib4_node_list_append(fib4_entry
, new4_entry
);
4377 if (replace
&& WARN_ON(!fib4_entry
))
4380 /* Insert new entry before replaced one, so that we can later
4381 * remove the second.
4384 list_add_tail(&new4_entry
->common
.list
,
4385 &fib4_entry
->common
.list
);
4387 struct mlxsw_sp_fib4_entry
*last
;
4389 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
4390 if (new4_entry
->tb_id
> last
->tb_id
)
4396 list_add(&new4_entry
->common
.list
,
4397 &fib4_entry
->common
.list
);
4399 list_add(&new4_entry
->common
.list
,
4400 &fib_node
->entry_list
);
4407 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry
*fib4_entry
)
4409 list_del(&fib4_entry
->common
.list
);
4412 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp
*mlxsw_sp
,
4413 struct mlxsw_sp_fib_entry
*fib_entry
)
4415 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4417 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4420 /* To prevent packet loss, overwrite the previously offloaded
4423 if (!list_is_singular(&fib_node
->entry_list
)) {
4424 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4425 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4427 mlxsw_sp_fib_entry_offload_refresh(n
, op
, 0);
4430 return mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
4433 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4434 struct mlxsw_sp_fib_entry
*fib_entry
)
4436 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4438 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4441 /* Promote the next entry by overwriting the deleted entry */
4442 if (!list_is_singular(&fib_node
->entry_list
)) {
4443 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4444 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4446 mlxsw_sp_fib_entry_update(mlxsw_sp
, n
);
4447 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
4451 mlxsw_sp_fib_entry_del(mlxsw_sp
, fib_entry
);
4454 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
4455 struct mlxsw_sp_fib4_entry
*fib4_entry
,
4456 bool replace
, bool append
)
4460 err
= mlxsw_sp_fib4_node_list_insert(fib4_entry
, replace
, append
);
4464 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib4_entry
->common
);
4466 goto err_fib_node_entry_add
;
4470 err_fib_node_entry_add
:
4471 mlxsw_sp_fib4_node_list_remove(fib4_entry
);
4476 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
4477 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4479 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib4_entry
->common
);
4480 mlxsw_sp_fib4_node_list_remove(fib4_entry
);
4482 if (fib4_entry
->common
.type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
)
4483 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, &fib4_entry
->common
);
4486 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
4487 struct mlxsw_sp_fib4_entry
*fib4_entry
,
4490 struct mlxsw_sp_fib_node
*fib_node
= fib4_entry
->common
.fib_node
;
4491 struct mlxsw_sp_fib4_entry
*replaced
;
4496 /* We inserted the new entry before replaced one */
4497 replaced
= list_next_entry(fib4_entry
, common
.list
);
4499 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, replaced
);
4500 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, replaced
);
4501 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4505 mlxsw_sp_router_fib4_add(struct mlxsw_sp
*mlxsw_sp
,
4506 const struct fib_entry_notifier_info
*fen_info
,
4507 bool replace
, bool append
)
4509 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4510 struct mlxsw_sp_fib_node
*fib_node
;
4513 if (mlxsw_sp
->router
->aborted
)
4516 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, fen_info
->tb_id
,
4517 &fen_info
->dst
, sizeof(fen_info
->dst
),
4519 MLXSW_SP_L3_PROTO_IPV4
);
4520 if (IS_ERR(fib_node
)) {
4521 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to get FIB node\n");
4522 return PTR_ERR(fib_node
);
4525 fib4_entry
= mlxsw_sp_fib4_entry_create(mlxsw_sp
, fib_node
, fen_info
);
4526 if (IS_ERR(fib4_entry
)) {
4527 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to create FIB entry\n");
4528 err
= PTR_ERR(fib4_entry
);
4529 goto err_fib4_entry_create
;
4532 err
= mlxsw_sp_fib4_node_entry_link(mlxsw_sp
, fib4_entry
, replace
,
4535 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to link FIB entry to node\n");
4536 goto err_fib4_node_entry_link
;
4539 mlxsw_sp_fib4_entry_replace(mlxsw_sp
, fib4_entry
, replace
);
4543 err_fib4_node_entry_link
:
4544 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4545 err_fib4_entry_create
:
4546 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4550 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp
*mlxsw_sp
,
4551 struct fib_entry_notifier_info
*fen_info
)
4553 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4554 struct mlxsw_sp_fib_node
*fib_node
;
4556 if (mlxsw_sp
->router
->aborted
)
4559 fib4_entry
= mlxsw_sp_fib4_entry_lookup(mlxsw_sp
, fen_info
);
4560 if (WARN_ON(!fib4_entry
))
4562 fib_node
= fib4_entry
->common
.fib_node
;
4564 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
4565 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4566 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4569 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info
*rt
)
4571 /* Packets with link-local destination IP arriving to the router
4572 * are trapped to the CPU, so no need to program specific routes
4575 if (ipv6_addr_type(&rt
->rt6i_dst
.addr
) & IPV6_ADDR_LINKLOCAL
)
4578 /* Multicast routes aren't supported, so ignore them. Neighbour
4579 * Discovery packets are specifically trapped.
4581 if (ipv6_addr_type(&rt
->rt6i_dst
.addr
) & IPV6_ADDR_MULTICAST
)
4584 /* Cloned routes are irrelevant in the forwarding path. */
4585 if (rt
->rt6i_flags
& RTF_CACHE
)
4591 static struct mlxsw_sp_rt6
*mlxsw_sp_rt6_create(struct rt6_info
*rt
)
4593 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4595 mlxsw_sp_rt6
= kzalloc(sizeof(*mlxsw_sp_rt6
), GFP_KERNEL
);
4597 return ERR_PTR(-ENOMEM
);
4599 /* In case of route replace, replaced route is deleted with
4600 * no notification. Take reference to prevent accessing freed
4603 mlxsw_sp_rt6
->rt
= rt
;
4606 return mlxsw_sp_rt6
;
4609 #if IS_ENABLED(CONFIG_IPV6)
4610 static void mlxsw_sp_rt6_release(struct rt6_info
*rt
)
4615 static void mlxsw_sp_rt6_release(struct rt6_info
*rt
)
4620 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
4622 mlxsw_sp_rt6_release(mlxsw_sp_rt6
->rt
);
4623 kfree(mlxsw_sp_rt6
);
4626 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info
*rt
)
4628 /* RTF_CACHE routes are ignored */
4629 return (rt
->rt6i_flags
& (RTF_GATEWAY
| RTF_ADDRCONF
)) == RTF_GATEWAY
;
4632 static struct rt6_info
*
4633 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry
*fib6_entry
)
4635 return list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
4639 static struct mlxsw_sp_fib6_entry
*
4640 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
4641 const struct rt6_info
*nrt
, bool replace
)
4643 struct mlxsw_sp_fib6_entry
*fib6_entry
;
4645 if (!mlxsw_sp_fib6_rt_can_mp(nrt
) || replace
)
4648 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
4649 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
4651 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
4654 if (rt
->rt6i_table
->tb6_id
> nrt
->rt6i_table
->tb6_id
)
4656 if (rt
->rt6i_table
->tb6_id
!= nrt
->rt6i_table
->tb6_id
)
4658 if (rt
->rt6i_metric
< nrt
->rt6i_metric
)
4660 if (rt
->rt6i_metric
== nrt
->rt6i_metric
&&
4661 mlxsw_sp_fib6_rt_can_mp(rt
))
4663 if (rt
->rt6i_metric
> nrt
->rt6i_metric
)
4670 static struct mlxsw_sp_rt6
*
4671 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry
*fib6_entry
,
4672 const struct rt6_info
*rt
)
4674 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4676 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
4677 if (mlxsw_sp_rt6
->rt
== rt
)
4678 return mlxsw_sp_rt6
;
4684 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
4685 const struct rt6_info
*rt
,
4686 enum mlxsw_sp_ipip_type
*ret
)
4688 return rt
->dst
.dev
&&
4689 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, rt
->dst
.dev
, ret
);
4692 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp
*mlxsw_sp
,
4693 struct mlxsw_sp_nexthop_group
*nh_grp
,
4694 struct mlxsw_sp_nexthop
*nh
,
4695 const struct rt6_info
*rt
)
4697 struct mlxsw_sp_router
*router
= mlxsw_sp
->router
;
4698 struct net_device
*dev
= rt
->dst
.dev
;
4699 enum mlxsw_sp_ipip_type ipipt
;
4700 struct mlxsw_sp_rif
*rif
;
4703 if (mlxsw_sp_nexthop6_ipip_type(mlxsw_sp
, rt
, &ipipt
) &&
4704 router
->ipip_ops_arr
[ipipt
]->can_offload(mlxsw_sp
, dev
,
4705 MLXSW_SP_L3_PROTO_IPV6
)) {
4706 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
4707 err
= mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, dev
);
4710 mlxsw_sp_nexthop_rif_init(nh
, &nh
->ipip_entry
->ol_lb
->common
);
4714 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
4715 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
4718 mlxsw_sp_nexthop_rif_init(nh
, rif
);
4720 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
4722 goto err_nexthop_neigh_init
;
4726 err_nexthop_neigh_init
:
4727 mlxsw_sp_nexthop_rif_fini(nh
);
4731 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp
*mlxsw_sp
,
4732 struct mlxsw_sp_nexthop
*nh
)
4734 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
4737 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp
*mlxsw_sp
,
4738 struct mlxsw_sp_nexthop_group
*nh_grp
,
4739 struct mlxsw_sp_nexthop
*nh
,
4740 const struct rt6_info
*rt
)
4742 struct net_device
*dev
= rt
->dst
.dev
;
4744 nh
->nh_grp
= nh_grp
;
4746 memcpy(&nh
->gw_addr
, &rt
->rt6i_gateway
, sizeof(nh
->gw_addr
));
4747 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
4749 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
4753 nh
->ifindex
= dev
->ifindex
;
4755 return mlxsw_sp_nexthop6_type_init(mlxsw_sp
, nh_grp
, nh
, rt
);
4758 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp
*mlxsw_sp
,
4759 struct mlxsw_sp_nexthop
*nh
)
4761 mlxsw_sp_nexthop6_type_fini(mlxsw_sp
, nh
);
4762 list_del(&nh
->router_list_node
);
4763 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
4766 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
4767 const struct rt6_info
*rt
)
4769 return rt
->rt6i_flags
& RTF_GATEWAY
||
4770 mlxsw_sp_nexthop6_ipip_type(mlxsw_sp
, rt
, NULL
);
4773 static struct mlxsw_sp_nexthop_group
*
4774 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp
*mlxsw_sp
,
4775 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4777 struct mlxsw_sp_nexthop_group
*nh_grp
;
4778 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4779 struct mlxsw_sp_nexthop
*nh
;
4784 alloc_size
= sizeof(*nh_grp
) +
4785 fib6_entry
->nrt6
* sizeof(struct mlxsw_sp_nexthop
);
4786 nh_grp
= kzalloc(alloc_size
, GFP_KERNEL
);
4788 return ERR_PTR(-ENOMEM
);
4789 INIT_LIST_HEAD(&nh_grp
->fib_list
);
4790 #if IS_ENABLED(CONFIG_IPV6)
4791 nh_grp
->neigh_tbl
= &nd_tbl
;
4793 mlxsw_sp_rt6
= list_first_entry(&fib6_entry
->rt6_list
,
4794 struct mlxsw_sp_rt6
, list
);
4795 nh_grp
->gateway
= mlxsw_sp_rt6_is_gateway(mlxsw_sp
, mlxsw_sp_rt6
->rt
);
4796 nh_grp
->count
= fib6_entry
->nrt6
;
4797 for (i
= 0; i
< nh_grp
->count
; i
++) {
4798 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
4800 nh
= &nh_grp
->nexthops
[i
];
4801 err
= mlxsw_sp_nexthop6_init(mlxsw_sp
, nh_grp
, nh
, rt
);
4803 goto err_nexthop6_init
;
4804 mlxsw_sp_rt6
= list_next_entry(mlxsw_sp_rt6
, list
);
4807 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
4809 goto err_nexthop_group_insert
;
4811 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
4814 err_nexthop_group_insert
:
4816 for (i
--; i
>= 0; i
--) {
4817 nh
= &nh_grp
->nexthops
[i
];
4818 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
4821 return ERR_PTR(err
);
4825 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
4826 struct mlxsw_sp_nexthop_group
*nh_grp
)
4828 struct mlxsw_sp_nexthop
*nh
;
4829 int i
= nh_grp
->count
;
4831 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
4832 for (i
--; i
>= 0; i
--) {
4833 nh
= &nh_grp
->nexthops
[i
];
4834 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
4836 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
4837 WARN_ON(nh_grp
->adj_index_valid
);
4841 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp
*mlxsw_sp
,
4842 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4844 struct mlxsw_sp_nexthop_group
*nh_grp
;
4846 nh_grp
= mlxsw_sp_nexthop6_group_lookup(mlxsw_sp
, fib6_entry
);
4848 nh_grp
= mlxsw_sp_nexthop6_group_create(mlxsw_sp
, fib6_entry
);
4850 return PTR_ERR(nh_grp
);
4853 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
4855 fib6_entry
->common
.nh_group
= nh_grp
;
4860 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp
*mlxsw_sp
,
4861 struct mlxsw_sp_fib_entry
*fib_entry
)
4863 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4865 list_del(&fib_entry
->nexthop_group_node
);
4866 if (!list_empty(&nh_grp
->fib_list
))
4868 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, nh_grp
);
4872 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp
*mlxsw_sp
,
4873 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4875 struct mlxsw_sp_nexthop_group
*old_nh_grp
= fib6_entry
->common
.nh_group
;
4878 fib6_entry
->common
.nh_group
= NULL
;
4879 list_del(&fib6_entry
->common
.nexthop_group_node
);
4881 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
4883 goto err_nexthop6_group_get
;
4885 /* In case this entry is offloaded, then the adjacency index
4886 * currently associated with it in the device's table is that
4887 * of the old group. Start using the new one instead.
4889 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
4891 goto err_fib_node_entry_add
;
4893 if (list_empty(&old_nh_grp
->fib_list
))
4894 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, old_nh_grp
);
4898 err_fib_node_entry_add
:
4899 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
4900 err_nexthop6_group_get
:
4901 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
4902 &old_nh_grp
->fib_list
);
4903 fib6_entry
->common
.nh_group
= old_nh_grp
;
4908 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp
*mlxsw_sp
,
4909 struct mlxsw_sp_fib6_entry
*fib6_entry
,
4910 struct rt6_info
*rt
)
4912 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4915 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt
);
4916 if (IS_ERR(mlxsw_sp_rt6
))
4917 return PTR_ERR(mlxsw_sp_rt6
);
4919 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
4922 err
= mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
4924 goto err_nexthop6_group_update
;
4928 err_nexthop6_group_update
:
4930 list_del(&mlxsw_sp_rt6
->list
);
4931 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4936 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp
*mlxsw_sp
,
4937 struct mlxsw_sp_fib6_entry
*fib6_entry
,
4938 struct rt6_info
*rt
)
4940 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4942 mlxsw_sp_rt6
= mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
);
4943 if (WARN_ON(!mlxsw_sp_rt6
))
4947 list_del(&mlxsw_sp_rt6
->list
);
4948 mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
4949 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4952 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
4953 struct mlxsw_sp_fib_entry
*fib_entry
,
4954 const struct rt6_info
*rt
)
4956 /* Packets hitting RTF_REJECT routes need to be discarded by the
4957 * stack. We can rely on their destination device not having a
4958 * RIF (it's the loopback device) and can thus use action type
4959 * local, which will cause them to be trapped with a lower
4960 * priority than packets that need to be locally received.
4962 if (rt
->rt6i_flags
& (RTF_LOCAL
| RTF_ANYCAST
))
4963 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4964 else if (rt
->rt6i_flags
& RTF_REJECT
)
4965 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4966 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp
, rt
))
4967 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4969 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4973 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry
*fib6_entry
)
4975 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
, *tmp
;
4977 list_for_each_entry_safe(mlxsw_sp_rt6
, tmp
, &fib6_entry
->rt6_list
,
4980 list_del(&mlxsw_sp_rt6
->list
);
4981 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4985 static struct mlxsw_sp_fib6_entry
*
4986 mlxsw_sp_fib6_entry_create(struct mlxsw_sp
*mlxsw_sp
,
4987 struct mlxsw_sp_fib_node
*fib_node
,
4988 struct rt6_info
*rt
)
4990 struct mlxsw_sp_fib6_entry
*fib6_entry
;
4991 struct mlxsw_sp_fib_entry
*fib_entry
;
4992 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4995 fib6_entry
= kzalloc(sizeof(*fib6_entry
), GFP_KERNEL
);
4997 return ERR_PTR(-ENOMEM
);
4998 fib_entry
= &fib6_entry
->common
;
5000 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt
);
5001 if (IS_ERR(mlxsw_sp_rt6
)) {
5002 err
= PTR_ERR(mlxsw_sp_rt6
);
5003 goto err_rt6_create
;
5006 mlxsw_sp_fib6_entry_type_set(mlxsw_sp
, fib_entry
, mlxsw_sp_rt6
->rt
);
5008 INIT_LIST_HEAD(&fib6_entry
->rt6_list
);
5009 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
5010 fib6_entry
->nrt6
= 1;
5011 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
5013 goto err_nexthop6_group_get
;
5015 fib_entry
->fib_node
= fib_node
;
5019 err_nexthop6_group_get
:
5020 list_del(&mlxsw_sp_rt6
->list
);
5021 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5024 return ERR_PTR(err
);
5027 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
5028 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5030 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
5031 mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry
);
5032 WARN_ON(fib6_entry
->nrt6
);
5036 static struct mlxsw_sp_fib6_entry
*
5037 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
5038 const struct rt6_info
*nrt
, bool replace
)
5040 struct mlxsw_sp_fib6_entry
*fib6_entry
, *fallback
= NULL
;
5042 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5043 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5045 if (rt
->rt6i_table
->tb6_id
> nrt
->rt6i_table
->tb6_id
)
5047 if (rt
->rt6i_table
->tb6_id
!= nrt
->rt6i_table
->tb6_id
)
5049 if (replace
&& rt
->rt6i_metric
== nrt
->rt6i_metric
) {
5050 if (mlxsw_sp_fib6_rt_can_mp(rt
) ==
5051 mlxsw_sp_fib6_rt_can_mp(nrt
))
5053 if (mlxsw_sp_fib6_rt_can_mp(nrt
))
5054 fallback
= fallback
?: fib6_entry
;
5056 if (rt
->rt6i_metric
> nrt
->rt6i_metric
)
5057 return fallback
?: fib6_entry
;
5064 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry
*new6_entry
,
5067 struct mlxsw_sp_fib_node
*fib_node
= new6_entry
->common
.fib_node
;
5068 struct rt6_info
*nrt
= mlxsw_sp_fib6_entry_rt(new6_entry
);
5069 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5071 fib6_entry
= mlxsw_sp_fib6_node_entry_find(fib_node
, nrt
, replace
);
5073 if (replace
&& WARN_ON(!fib6_entry
))
5077 list_add_tail(&new6_entry
->common
.list
,
5078 &fib6_entry
->common
.list
);
5080 struct mlxsw_sp_fib6_entry
*last
;
5082 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
5083 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(last
);
5085 if (nrt
->rt6i_table
->tb6_id
> rt
->rt6i_table
->tb6_id
)
5091 list_add(&new6_entry
->common
.list
,
5092 &fib6_entry
->common
.list
);
5094 list_add(&new6_entry
->common
.list
,
5095 &fib_node
->entry_list
);
5102 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5104 list_del(&fib6_entry
->common
.list
);
5107 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
5108 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5113 err
= mlxsw_sp_fib6_node_list_insert(fib6_entry
, replace
);
5117 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
5119 goto err_fib_node_entry_add
;
5123 err_fib_node_entry_add
:
5124 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5129 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
5130 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5132 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib6_entry
->common
);
5133 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5136 static struct mlxsw_sp_fib6_entry
*
5137 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
5138 const struct rt6_info
*rt
)
5140 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5141 struct mlxsw_sp_fib_node
*fib_node
;
5142 struct mlxsw_sp_fib
*fib
;
5143 struct mlxsw_sp_vr
*vr
;
5145 vr
= mlxsw_sp_vr_find(mlxsw_sp
, rt
->rt6i_table
->tb6_id
);
5148 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV6
);
5150 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &rt
->rt6i_dst
.addr
,
5151 sizeof(rt
->rt6i_dst
.addr
),
5156 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5157 struct rt6_info
*iter_rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5159 if (rt
->rt6i_table
->tb6_id
== iter_rt
->rt6i_table
->tb6_id
&&
5160 rt
->rt6i_metric
== iter_rt
->rt6i_metric
&&
5161 mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
))
5168 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
5169 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5172 struct mlxsw_sp_fib_node
*fib_node
= fib6_entry
->common
.fib_node
;
5173 struct mlxsw_sp_fib6_entry
*replaced
;
5178 replaced
= list_next_entry(fib6_entry
, common
.list
);
5180 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, replaced
);
5181 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, replaced
);
5182 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5185 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp
*mlxsw_sp
,
5186 struct rt6_info
*rt
, bool replace
)
5188 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5189 struct mlxsw_sp_fib_node
*fib_node
;
5192 if (mlxsw_sp
->router
->aborted
)
5195 if (rt
->rt6i_src
.plen
)
5198 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5201 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, rt
->rt6i_table
->tb6_id
,
5203 sizeof(rt
->rt6i_dst
.addr
),
5205 MLXSW_SP_L3_PROTO_IPV6
);
5206 if (IS_ERR(fib_node
))
5207 return PTR_ERR(fib_node
);
5209 /* Before creating a new entry, try to append route to an existing
5212 fib6_entry
= mlxsw_sp_fib6_node_mp_entry_find(fib_node
, rt
, replace
);
5214 err
= mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp
, fib6_entry
, rt
);
5216 goto err_fib6_entry_nexthop_add
;
5220 fib6_entry
= mlxsw_sp_fib6_entry_create(mlxsw_sp
, fib_node
, rt
);
5221 if (IS_ERR(fib6_entry
)) {
5222 err
= PTR_ERR(fib6_entry
);
5223 goto err_fib6_entry_create
;
5226 err
= mlxsw_sp_fib6_node_entry_link(mlxsw_sp
, fib6_entry
, replace
);
5228 goto err_fib6_node_entry_link
;
5230 mlxsw_sp_fib6_entry_replace(mlxsw_sp
, fib6_entry
, replace
);
5234 err_fib6_node_entry_link
:
5235 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5236 err_fib6_entry_create
:
5237 err_fib6_entry_nexthop_add
:
5238 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5242 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp
*mlxsw_sp
,
5243 struct rt6_info
*rt
)
5245 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5246 struct mlxsw_sp_fib_node
*fib_node
;
5248 if (mlxsw_sp
->router
->aborted
)
5251 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5254 fib6_entry
= mlxsw_sp_fib6_entry_lookup(mlxsw_sp
, rt
);
5255 if (WARN_ON(!fib6_entry
))
5258 /* If route is part of a multipath entry, but not the last one
5259 * removed, then only reduce its nexthop group.
5261 if (!list_is_singular(&fib6_entry
->rt6_list
)) {
5262 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp
, fib6_entry
, rt
);
5266 fib_node
= fib6_entry
->common
.fib_node
;
5268 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5269 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5270 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5273 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
,
5274 enum mlxsw_reg_ralxx_protocol proto
,
5277 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
5278 char ralst_pl
[MLXSW_REG_RALST_LEN
];
5281 mlxsw_reg_ralta_pack(ralta_pl
, true, proto
, tree_id
);
5282 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
5286 mlxsw_reg_ralst_pack(ralst_pl
, 0xff, tree_id
);
5287 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralst
), ralst_pl
);
5291 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5292 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5293 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
5294 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
5296 mlxsw_reg_raltb_pack(raltb_pl
, vr
->id
, proto
, tree_id
);
5297 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
),
5302 mlxsw_reg_ralue_pack(ralue_pl
, proto
,
5303 MLXSW_REG_RALUE_OP_WRITE_WRITE
, vr
->id
, 0);
5304 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
5305 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
),
5314 static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp
*mlxsw_sp
,
5315 struct mfc_entry_notifier_info
*men_info
,
5318 struct mlxsw_sp_vr
*vr
;
5320 if (mlxsw_sp
->router
->aborted
)
5323 vr
= mlxsw_sp_vr_get(mlxsw_sp
, men_info
->tb_id
, NULL
);
5327 return mlxsw_sp_mr_route4_add(vr
->mr4_table
, men_info
->mfc
, replace
);
5330 static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp
*mlxsw_sp
,
5331 struct mfc_entry_notifier_info
*men_info
)
5333 struct mlxsw_sp_vr
*vr
;
5335 if (mlxsw_sp
->router
->aborted
)
5338 vr
= mlxsw_sp_vr_find(mlxsw_sp
, men_info
->tb_id
);
5342 mlxsw_sp_mr_route4_del(vr
->mr4_table
, men_info
->mfc
);
5343 mlxsw_sp_vr_put(vr
);
5347 mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp
*mlxsw_sp
,
5348 struct vif_entry_notifier_info
*ven_info
)
5350 struct mlxsw_sp_rif
*rif
;
5351 struct mlxsw_sp_vr
*vr
;
5353 if (mlxsw_sp
->router
->aborted
)
5356 vr
= mlxsw_sp_vr_get(mlxsw_sp
, ven_info
->tb_id
, NULL
);
5360 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, ven_info
->dev
);
5361 return mlxsw_sp_mr_vif_add(vr
->mr4_table
, ven_info
->dev
,
5362 ven_info
->vif_index
,
5363 ven_info
->vif_flags
, rif
);
5367 mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp
*mlxsw_sp
,
5368 struct vif_entry_notifier_info
*ven_info
)
5370 struct mlxsw_sp_vr
*vr
;
5372 if (mlxsw_sp
->router
->aborted
)
5375 vr
= mlxsw_sp_vr_find(mlxsw_sp
, ven_info
->tb_id
);
5379 mlxsw_sp_mr_vif_del(vr
->mr4_table
, ven_info
->vif_index
);
5380 mlxsw_sp_vr_put(vr
);
5383 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
)
5385 enum mlxsw_reg_ralxx_protocol proto
= MLXSW_REG_RALXX_PROTOCOL_IPV4
;
5388 err
= __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5389 MLXSW_SP_LPM_TREE_MIN
);
5393 /* The multicast router code does not need an abort trap as by default,
5394 * packets that don't match any routes are trapped to the CPU.
5397 proto
= MLXSW_REG_RALXX_PROTOCOL_IPV6
;
5398 return __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5399 MLXSW_SP_LPM_TREE_MIN
+ 1);
5402 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5403 struct mlxsw_sp_fib_node
*fib_node
)
5405 struct mlxsw_sp_fib4_entry
*fib4_entry
, *tmp
;
5407 list_for_each_entry_safe(fib4_entry
, tmp
, &fib_node
->entry_list
,
5409 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5411 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
5412 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
5413 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5414 /* Break when entry list is empty and node was freed.
5415 * Otherwise, we'll access freed memory in the next
5423 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5424 struct mlxsw_sp_fib_node
*fib_node
)
5426 struct mlxsw_sp_fib6_entry
*fib6_entry
, *tmp
;
5428 list_for_each_entry_safe(fib6_entry
, tmp
, &fib_node
->entry_list
,
5430 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5432 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5433 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5434 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5440 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5441 struct mlxsw_sp_fib_node
*fib_node
)
5443 switch (fib_node
->fib
->proto
) {
5444 case MLXSW_SP_L3_PROTO_IPV4
:
5445 mlxsw_sp_fib4_node_flush(mlxsw_sp
, fib_node
);
5447 case MLXSW_SP_L3_PROTO_IPV6
:
5448 mlxsw_sp_fib6_node_flush(mlxsw_sp
, fib_node
);
5453 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp
*mlxsw_sp
,
5454 struct mlxsw_sp_vr
*vr
,
5455 enum mlxsw_sp_l3proto proto
)
5457 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
5458 struct mlxsw_sp_fib_node
*fib_node
, *tmp
;
5460 list_for_each_entry_safe(fib_node
, tmp
, &fib
->node_list
, list
) {
5461 bool do_break
= &tmp
->list
== &fib
->node_list
;
5463 mlxsw_sp_fib_node_flush(mlxsw_sp
, fib_node
);
5469 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
)
5473 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5474 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5476 if (!mlxsw_sp_vr_is_used(vr
))
5479 mlxsw_sp_mr_table_flush(vr
->mr4_table
);
5480 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV4
);
5482 /* If virtual router was only used for IPv4, then it's no
5485 if (!mlxsw_sp_vr_is_used(vr
))
5487 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV6
);
5491 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp
*mlxsw_sp
)
5495 if (mlxsw_sp
->router
->aborted
)
5497 dev_warn(mlxsw_sp
->bus_info
->dev
, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
5498 mlxsw_sp_router_fib_flush(mlxsw_sp
);
5499 mlxsw_sp
->router
->aborted
= true;
5500 err
= mlxsw_sp_router_set_abort_trap(mlxsw_sp
);
5502 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set abort trap.\n");
5505 struct mlxsw_sp_fib_event_work
{
5506 struct work_struct work
;
5508 struct fib6_entry_notifier_info fen6_info
;
5509 struct fib_entry_notifier_info fen_info
;
5510 struct fib_rule_notifier_info fr_info
;
5511 struct fib_nh_notifier_info fnh_info
;
5512 struct mfc_entry_notifier_info men_info
;
5513 struct vif_entry_notifier_info ven_info
;
5515 struct mlxsw_sp
*mlxsw_sp
;
5516 unsigned long event
;
5519 static void mlxsw_sp_router_fib4_event_work(struct work_struct
*work
)
5521 struct mlxsw_sp_fib_event_work
*fib_work
=
5522 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5523 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5524 bool replace
, append
;
5527 /* Protect internal structures from changes */
5529 switch (fib_work
->event
) {
5530 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5531 case FIB_EVENT_ENTRY_APPEND
: /* fall through */
5532 case FIB_EVENT_ENTRY_ADD
:
5533 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5534 append
= fib_work
->event
== FIB_EVENT_ENTRY_APPEND
;
5535 err
= mlxsw_sp_router_fib4_add(mlxsw_sp
, &fib_work
->fen_info
,
5538 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5539 fib_info_put(fib_work
->fen_info
.fi
);
5541 case FIB_EVENT_ENTRY_DEL
:
5542 mlxsw_sp_router_fib4_del(mlxsw_sp
, &fib_work
->fen_info
);
5543 fib_info_put(fib_work
->fen_info
.fi
);
5545 case FIB_EVENT_RULE_ADD
:
5546 /* if we get here, a rule was added that we do not support.
5547 * just do the fib_abort
5549 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5551 case FIB_EVENT_NH_ADD
: /* fall through */
5552 case FIB_EVENT_NH_DEL
:
5553 mlxsw_sp_nexthop4_event(mlxsw_sp
, fib_work
->event
,
5554 fib_work
->fnh_info
.fib_nh
);
5555 fib_info_put(fib_work
->fnh_info
.fib_nh
->nh_parent
);
5562 static void mlxsw_sp_router_fib6_event_work(struct work_struct
*work
)
5564 struct mlxsw_sp_fib_event_work
*fib_work
=
5565 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5566 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5571 switch (fib_work
->event
) {
5572 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5573 case FIB_EVENT_ENTRY_ADD
:
5574 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5575 err
= mlxsw_sp_router_fib6_add(mlxsw_sp
,
5576 fib_work
->fen6_info
.rt
, replace
);
5578 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5579 mlxsw_sp_rt6_release(fib_work
->fen6_info
.rt
);
5581 case FIB_EVENT_ENTRY_DEL
:
5582 mlxsw_sp_router_fib6_del(mlxsw_sp
, fib_work
->fen6_info
.rt
);
5583 mlxsw_sp_rt6_release(fib_work
->fen6_info
.rt
);
5585 case FIB_EVENT_RULE_ADD
:
5586 /* if we get here, a rule was added that we do not support.
5587 * just do the fib_abort
5589 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5596 static void mlxsw_sp_router_fibmr_event_work(struct work_struct
*work
)
5598 struct mlxsw_sp_fib_event_work
*fib_work
=
5599 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5600 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5605 switch (fib_work
->event
) {
5606 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5607 case FIB_EVENT_ENTRY_ADD
:
5608 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5610 err
= mlxsw_sp_router_fibmr_add(mlxsw_sp
, &fib_work
->men_info
,
5613 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5614 ipmr_cache_put(fib_work
->men_info
.mfc
);
5616 case FIB_EVENT_ENTRY_DEL
:
5617 mlxsw_sp_router_fibmr_del(mlxsw_sp
, &fib_work
->men_info
);
5618 ipmr_cache_put(fib_work
->men_info
.mfc
);
5620 case FIB_EVENT_VIF_ADD
:
5621 err
= mlxsw_sp_router_fibmr_vif_add(mlxsw_sp
,
5622 &fib_work
->ven_info
);
5624 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5625 dev_put(fib_work
->ven_info
.dev
);
5627 case FIB_EVENT_VIF_DEL
:
5628 mlxsw_sp_router_fibmr_vif_del(mlxsw_sp
,
5629 &fib_work
->ven_info
);
5630 dev_put(fib_work
->ven_info
.dev
);
5632 case FIB_EVENT_RULE_ADD
:
5633 /* if we get here, a rule was added that we do not support.
5634 * just do the fib_abort
5636 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5643 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5644 struct fib_notifier_info
*info
)
5646 struct fib_entry_notifier_info
*fen_info
;
5647 struct fib_nh_notifier_info
*fnh_info
;
5649 switch (fib_work
->event
) {
5650 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5651 case FIB_EVENT_ENTRY_APPEND
: /* fall through */
5652 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5653 case FIB_EVENT_ENTRY_DEL
:
5654 fen_info
= container_of(info
, struct fib_entry_notifier_info
,
5656 fib_work
->fen_info
= *fen_info
;
5657 /* Take reference on fib_info to prevent it from being
5658 * freed while work is queued. Release it afterwards.
5660 fib_info_hold(fib_work
->fen_info
.fi
);
5662 case FIB_EVENT_NH_ADD
: /* fall through */
5663 case FIB_EVENT_NH_DEL
:
5664 fnh_info
= container_of(info
, struct fib_nh_notifier_info
,
5666 fib_work
->fnh_info
= *fnh_info
;
5667 fib_info_hold(fib_work
->fnh_info
.fib_nh
->nh_parent
);
5672 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5673 struct fib_notifier_info
*info
)
5675 struct fib6_entry_notifier_info
*fen6_info
;
5677 switch (fib_work
->event
) {
5678 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5679 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5680 case FIB_EVENT_ENTRY_DEL
:
5681 fen6_info
= container_of(info
, struct fib6_entry_notifier_info
,
5683 fib_work
->fen6_info
= *fen6_info
;
5684 rt6_hold(fib_work
->fen6_info
.rt
);
5690 mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5691 struct fib_notifier_info
*info
)
5693 switch (fib_work
->event
) {
5694 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5695 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5696 case FIB_EVENT_ENTRY_DEL
:
5697 memcpy(&fib_work
->men_info
, info
, sizeof(fib_work
->men_info
));
5698 ipmr_cache_hold(fib_work
->men_info
.mfc
);
5700 case FIB_EVENT_VIF_ADD
: /* fall through */
5701 case FIB_EVENT_VIF_DEL
:
5702 memcpy(&fib_work
->ven_info
, info
, sizeof(fib_work
->ven_info
));
5703 dev_hold(fib_work
->ven_info
.dev
);
5708 static int mlxsw_sp_router_fib_rule_event(unsigned long event
,
5709 struct fib_notifier_info
*info
,
5710 struct mlxsw_sp
*mlxsw_sp
)
5712 struct netlink_ext_ack
*extack
= info
->extack
;
5713 struct fib_rule_notifier_info
*fr_info
;
5714 struct fib_rule
*rule
;
5717 /* nothing to do at the moment */
5718 if (event
== FIB_EVENT_RULE_DEL
)
5721 if (mlxsw_sp
->router
->aborted
)
5724 fr_info
= container_of(info
, struct fib_rule_notifier_info
, info
);
5725 rule
= fr_info
->rule
;
5727 switch (info
->family
) {
5729 if (!fib4_rule_default(rule
) && !rule
->l3mdev
)
5733 if (!fib6_rule_default(rule
) && !rule
->l3mdev
)
5736 case RTNL_FAMILY_IPMR
:
5737 if (!ipmr_rule_default(rule
) && !rule
->l3mdev
)
5743 NL_SET_ERR_MSG(extack
, "spectrum: FIB rules not supported. Aborting offload");
5748 /* Called with rcu_read_lock() */
5749 static int mlxsw_sp_router_fib_event(struct notifier_block
*nb
,
5750 unsigned long event
, void *ptr
)
5752 struct mlxsw_sp_fib_event_work
*fib_work
;
5753 struct fib_notifier_info
*info
= ptr
;
5754 struct mlxsw_sp_router
*router
;
5757 if (!net_eq(info
->net
, &init_net
) ||
5758 (info
->family
!= AF_INET
&& info
->family
!= AF_INET6
&&
5759 info
->family
!= RTNL_FAMILY_IPMR
))
5762 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
5765 case FIB_EVENT_RULE_ADD
: /* fall through */
5766 case FIB_EVENT_RULE_DEL
:
5767 err
= mlxsw_sp_router_fib_rule_event(event
, info
,
5773 fib_work
= kzalloc(sizeof(*fib_work
), GFP_ATOMIC
);
5774 if (WARN_ON(!fib_work
))
5777 fib_work
->mlxsw_sp
= router
->mlxsw_sp
;
5778 fib_work
->event
= event
;
5780 switch (info
->family
) {
5782 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib4_event_work
);
5783 mlxsw_sp_router_fib4_event(fib_work
, info
);
5786 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib6_event_work
);
5787 mlxsw_sp_router_fib6_event(fib_work
, info
);
5789 case RTNL_FAMILY_IPMR
:
5790 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fibmr_event_work
);
5791 mlxsw_sp_router_fibmr_event(fib_work
, info
);
5795 mlxsw_core_schedule_work(&fib_work
->work
);
5800 static struct mlxsw_sp_rif
*
5801 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp
*mlxsw_sp
,
5802 const struct net_device
*dev
)
5806 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
5807 if (mlxsw_sp
->router
->rifs
[i
] &&
5808 mlxsw_sp
->router
->rifs
[i
]->dev
== dev
)
5809 return mlxsw_sp
->router
->rifs
[i
];
5814 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp
*mlxsw_sp
, u16 rif
)
5816 char ritr_pl
[MLXSW_REG_RITR_LEN
];
5819 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif
);
5820 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
5821 if (WARN_ON_ONCE(err
))
5824 mlxsw_reg_ritr_enable_set(ritr_pl
, false);
5825 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
5828 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
5829 struct mlxsw_sp_rif
*rif
)
5831 mlxsw_sp_router_rif_disable(mlxsw_sp
, rif
->rif_index
);
5832 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp
, rif
);
5833 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp
, rif
);
5837 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif
*rif
, struct net_device
*dev
,
5838 unsigned long event
)
5840 struct inet6_dev
*inet6_dev
;
5841 bool addr_list_empty
= true;
5842 struct in_device
*idev
;
5848 idev
= __in_dev_get_rtnl(dev
);
5849 if (idev
&& idev
->ifa_list
)
5850 addr_list_empty
= false;
5852 inet6_dev
= __in6_dev_get(dev
);
5853 if (addr_list_empty
&& inet6_dev
&&
5854 !list_empty(&inet6_dev
->addr_list
))
5855 addr_list_empty
= false;
5857 if (rif
&& addr_list_empty
&&
5858 !netif_is_l3_slave(rif
->dev
))
5860 /* It is possible we already removed the RIF ourselves
5861 * if it was assigned to a netdev that is now a bridge
5870 static enum mlxsw_sp_rif_type
5871 mlxsw_sp_dev_rif_type(const struct mlxsw_sp
*mlxsw_sp
,
5872 const struct net_device
*dev
)
5874 enum mlxsw_sp_fid_type type
;
5876 if (mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
))
5877 return MLXSW_SP_RIF_TYPE_IPIP_LB
;
5879 /* Otherwise RIF type is derived from the type of the underlying FID. */
5880 if (is_vlan_dev(dev
) && netif_is_bridge_master(vlan_dev_real_dev(dev
)))
5881 type
= MLXSW_SP_FID_TYPE_8021Q
;
5882 else if (netif_is_bridge_master(dev
) && br_vlan_enabled(dev
))
5883 type
= MLXSW_SP_FID_TYPE_8021Q
;
5884 else if (netif_is_bridge_master(dev
))
5885 type
= MLXSW_SP_FID_TYPE_8021D
;
5887 type
= MLXSW_SP_FID_TYPE_RFID
;
5889 return mlxsw_sp_fid_type_rif_type(mlxsw_sp
, type
);
5892 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp
*mlxsw_sp
, u16
*p_rif_index
)
5896 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
5897 if (!mlxsw_sp
->router
->rifs
[i
]) {
5906 static struct mlxsw_sp_rif
*mlxsw_sp_rif_alloc(size_t rif_size
, u16 rif_index
,
5908 struct net_device
*l3_dev
)
5910 struct mlxsw_sp_rif
*rif
;
5912 rif
= kzalloc(rif_size
, GFP_KERNEL
);
5916 INIT_LIST_HEAD(&rif
->nexthop_list
);
5917 INIT_LIST_HEAD(&rif
->neigh_list
);
5918 ether_addr_copy(rif
->addr
, l3_dev
->dev_addr
);
5919 rif
->mtu
= l3_dev
->mtu
;
5922 rif
->rif_index
= rif_index
;
5927 struct mlxsw_sp_rif
*mlxsw_sp_rif_by_index(const struct mlxsw_sp
*mlxsw_sp
,
5930 return mlxsw_sp
->router
->rifs
[rif_index
];
5933 u16
mlxsw_sp_rif_index(const struct mlxsw_sp_rif
*rif
)
5935 return rif
->rif_index
;
5938 u16
mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
5940 return lb_rif
->common
.rif_index
;
5943 u16
mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
5945 return lb_rif
->ul_vr_id
;
5948 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif
*rif
)
5950 return rif
->dev
->ifindex
;
5953 const struct net_device
*mlxsw_sp_rif_dev(const struct mlxsw_sp_rif
*rif
)
5958 static struct mlxsw_sp_rif
*
5959 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
5960 const struct mlxsw_sp_rif_params
*params
,
5961 struct netlink_ext_ack
*extack
)
5963 u32 tb_id
= l3mdev_fib_table(params
->dev
);
5964 const struct mlxsw_sp_rif_ops
*ops
;
5965 struct mlxsw_sp_fid
*fid
= NULL
;
5966 enum mlxsw_sp_rif_type type
;
5967 struct mlxsw_sp_rif
*rif
;
5968 struct mlxsw_sp_vr
*vr
;
5972 type
= mlxsw_sp_dev_rif_type(mlxsw_sp
, params
->dev
);
5973 ops
= mlxsw_sp
->router
->rif_ops_arr
[type
];
5975 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
? : RT_TABLE_MAIN
, extack
);
5977 return ERR_CAST(vr
);
5980 err
= mlxsw_sp_rif_index_alloc(mlxsw_sp
, &rif_index
);
5982 NL_SET_ERR_MSG(extack
, "spectrum: Exceeded number of supported router interfaces");
5983 goto err_rif_index_alloc
;
5986 rif
= mlxsw_sp_rif_alloc(ops
->rif_size
, rif_index
, vr
->id
, params
->dev
);
5991 rif
->mlxsw_sp
= mlxsw_sp
;
5995 fid
= ops
->fid_get(rif
);
6004 ops
->setup(rif
, params
);
6006 err
= ops
->configure(rif
);
6010 err
= mlxsw_sp_mr_rif_add(vr
->mr4_table
, rif
);
6012 goto err_mr_rif_add
;
6014 mlxsw_sp_rif_counters_alloc(rif
);
6015 mlxsw_sp
->router
->rifs
[rif_index
] = rif
;
6020 ops
->deconfigure(rif
);
6023 mlxsw_sp_fid_put(fid
);
6027 err_rif_index_alloc
:
6029 mlxsw_sp_vr_put(vr
);
6030 return ERR_PTR(err
);
6033 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif
*rif
)
6035 const struct mlxsw_sp_rif_ops
*ops
= rif
->ops
;
6036 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6037 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6038 struct mlxsw_sp_vr
*vr
;
6040 mlxsw_sp_router_rif_gone_sync(mlxsw_sp
, rif
);
6041 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6043 mlxsw_sp
->router
->rifs
[rif
->rif_index
] = NULL
;
6044 mlxsw_sp_rif_counters_free(rif
);
6045 mlxsw_sp_mr_rif_del(vr
->mr4_table
, rif
);
6046 ops
->deconfigure(rif
);
6048 /* Loopback RIFs are not associated with a FID. */
6049 mlxsw_sp_fid_put(fid
);
6052 mlxsw_sp_vr_put(vr
);
6056 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params
*params
,
6057 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6059 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6061 params
->vid
= mlxsw_sp_port_vlan
->vid
;
6062 params
->lag
= mlxsw_sp_port
->lagged
;
6064 params
->lag_id
= mlxsw_sp_port
->lag_id
;
6066 params
->system_port
= mlxsw_sp_port
->local_port
;
6070 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
,
6071 struct net_device
*l3_dev
,
6072 struct netlink_ext_ack
*extack
)
6074 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6075 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
6076 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6077 struct mlxsw_sp_rif
*rif
;
6078 struct mlxsw_sp_fid
*fid
;
6081 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6083 struct mlxsw_sp_rif_params params
= {
6087 mlxsw_sp_rif_subport_params_init(¶ms
, mlxsw_sp_port_vlan
);
6088 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6090 return PTR_ERR(rif
);
6093 /* FID was already created, just take a reference */
6094 fid
= rif
->ops
->fid_get(rif
);
6095 err
= mlxsw_sp_fid_port_vid_map(fid
, mlxsw_sp_port
, vid
);
6097 goto err_fid_port_vid_map
;
6099 err
= mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, false);
6101 goto err_port_vid_learning_set
;
6103 err
= mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
,
6104 BR_STATE_FORWARDING
);
6106 goto err_port_vid_stp_set
;
6108 mlxsw_sp_port_vlan
->fid
= fid
;
6112 err_port_vid_stp_set
:
6113 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6114 err_port_vid_learning_set
:
6115 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6116 err_fid_port_vid_map
:
6117 mlxsw_sp_fid_put(fid
);
6122 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6124 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6125 struct mlxsw_sp_fid
*fid
= mlxsw_sp_port_vlan
->fid
;
6126 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6128 if (WARN_ON(mlxsw_sp_fid_type(fid
) != MLXSW_SP_FID_TYPE_RFID
))
6131 mlxsw_sp_port_vlan
->fid
= NULL
;
6132 mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
, BR_STATE_BLOCKING
);
6133 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6134 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6135 /* If router port holds the last reference on the rFID, then the
6136 * associated Sub-port RIF will be destroyed.
6138 mlxsw_sp_fid_put(fid
);
6141 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device
*l3_dev
,
6142 struct net_device
*port_dev
,
6143 unsigned long event
, u16 vid
,
6144 struct netlink_ext_ack
*extack
)
6146 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(port_dev
);
6147 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
;
6149 mlxsw_sp_port_vlan
= mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port
, vid
);
6150 if (WARN_ON(!mlxsw_sp_port_vlan
))
6155 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan
,
6158 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan
);
6165 static int mlxsw_sp_inetaddr_port_event(struct net_device
*port_dev
,
6166 unsigned long event
,
6167 struct netlink_ext_ack
*extack
)
6169 if (netif_is_bridge_port(port_dev
) ||
6170 netif_is_lag_port(port_dev
) ||
6171 netif_is_ovs_port(port_dev
))
6174 return mlxsw_sp_inetaddr_port_vlan_event(port_dev
, port_dev
, event
, 1,
6178 static int __mlxsw_sp_inetaddr_lag_event(struct net_device
*l3_dev
,
6179 struct net_device
*lag_dev
,
6180 unsigned long event
, u16 vid
,
6181 struct netlink_ext_ack
*extack
)
6183 struct net_device
*port_dev
;
6184 struct list_head
*iter
;
6187 netdev_for_each_lower_dev(lag_dev
, port_dev
, iter
) {
6188 if (mlxsw_sp_port_dev_check(port_dev
)) {
6189 err
= mlxsw_sp_inetaddr_port_vlan_event(l3_dev
,
6201 static int mlxsw_sp_inetaddr_lag_event(struct net_device
*lag_dev
,
6202 unsigned long event
,
6203 struct netlink_ext_ack
*extack
)
6205 if (netif_is_bridge_port(lag_dev
))
6208 return __mlxsw_sp_inetaddr_lag_event(lag_dev
, lag_dev
, event
, 1,
6212 static int mlxsw_sp_inetaddr_bridge_event(struct net_device
*l3_dev
,
6213 unsigned long event
,
6214 struct netlink_ext_ack
*extack
)
6216 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
6217 struct mlxsw_sp_rif_params params
= {
6220 struct mlxsw_sp_rif
*rif
;
6224 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6226 return PTR_ERR(rif
);
6229 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6230 mlxsw_sp_rif_destroy(rif
);
6237 static int mlxsw_sp_inetaddr_vlan_event(struct net_device
*vlan_dev
,
6238 unsigned long event
,
6239 struct netlink_ext_ack
*extack
)
6241 struct net_device
*real_dev
= vlan_dev_real_dev(vlan_dev
);
6242 u16 vid
= vlan_dev_vlan_id(vlan_dev
);
6244 if (netif_is_bridge_port(vlan_dev
))
6247 if (mlxsw_sp_port_dev_check(real_dev
))
6248 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev
, real_dev
,
6249 event
, vid
, extack
);
6250 else if (netif_is_lag_master(real_dev
))
6251 return __mlxsw_sp_inetaddr_lag_event(vlan_dev
, real_dev
, event
,
6253 else if (netif_is_bridge_master(real_dev
) && br_vlan_enabled(real_dev
))
6254 return mlxsw_sp_inetaddr_bridge_event(vlan_dev
, event
, extack
);
6259 static int __mlxsw_sp_inetaddr_event(struct net_device
*dev
,
6260 unsigned long event
,
6261 struct netlink_ext_ack
*extack
)
6263 if (mlxsw_sp_port_dev_check(dev
))
6264 return mlxsw_sp_inetaddr_port_event(dev
, event
, extack
);
6265 else if (netif_is_lag_master(dev
))
6266 return mlxsw_sp_inetaddr_lag_event(dev
, event
, extack
);
6267 else if (netif_is_bridge_master(dev
))
6268 return mlxsw_sp_inetaddr_bridge_event(dev
, event
, extack
);
6269 else if (is_vlan_dev(dev
))
6270 return mlxsw_sp_inetaddr_vlan_event(dev
, event
, extack
);
6275 int mlxsw_sp_inetaddr_event(struct notifier_block
*unused
,
6276 unsigned long event
, void *ptr
)
6278 struct in_ifaddr
*ifa
= (struct in_ifaddr
*) ptr
;
6279 struct net_device
*dev
= ifa
->ifa_dev
->dev
;
6280 struct mlxsw_sp
*mlxsw_sp
;
6281 struct mlxsw_sp_rif
*rif
;
6284 /* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
6285 if (event
== NETDEV_UP
)
6288 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6292 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6293 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6296 err
= __mlxsw_sp_inetaddr_event(dev
, event
, NULL
);
6298 return notifier_from_errno(err
);
6301 int mlxsw_sp_inetaddr_valid_event(struct notifier_block
*unused
,
6302 unsigned long event
, void *ptr
)
6304 struct in_validator_info
*ivi
= (struct in_validator_info
*) ptr
;
6305 struct net_device
*dev
= ivi
->ivi_dev
->dev
;
6306 struct mlxsw_sp
*mlxsw_sp
;
6307 struct mlxsw_sp_rif
*rif
;
6310 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6314 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6315 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6318 err
= __mlxsw_sp_inetaddr_event(dev
, event
, ivi
->extack
);
6320 return notifier_from_errno(err
);
6323 struct mlxsw_sp_inet6addr_event_work
{
6324 struct work_struct work
;
6325 struct net_device
*dev
;
6326 unsigned long event
;
6329 static void mlxsw_sp_inet6addr_event_work(struct work_struct
*work
)
6331 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
=
6332 container_of(work
, struct mlxsw_sp_inet6addr_event_work
, work
);
6333 struct net_device
*dev
= inet6addr_work
->dev
;
6334 unsigned long event
= inet6addr_work
->event
;
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 __mlxsw_sp_inetaddr_event(dev
, event
, NULL
);
6351 kfree(inet6addr_work
);
6354 /* Called with rcu_read_lock() */
6355 int mlxsw_sp_inet6addr_event(struct notifier_block
*unused
,
6356 unsigned long event
, void *ptr
)
6358 struct inet6_ifaddr
*if6
= (struct inet6_ifaddr
*) ptr
;
6359 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
;
6360 struct net_device
*dev
= if6
->idev
->dev
;
6362 /* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
6363 if (event
== NETDEV_UP
)
6366 if (!mlxsw_sp_port_dev_lower_find_rcu(dev
))
6369 inet6addr_work
= kzalloc(sizeof(*inet6addr_work
), GFP_ATOMIC
);
6370 if (!inet6addr_work
)
6373 INIT_WORK(&inet6addr_work
->work
, mlxsw_sp_inet6addr_event_work
);
6374 inet6addr_work
->dev
= dev
;
6375 inet6addr_work
->event
= event
;
6377 mlxsw_core_schedule_work(&inet6addr_work
->work
);
6382 int mlxsw_sp_inet6addr_valid_event(struct notifier_block
*unused
,
6383 unsigned long event
, void *ptr
)
6385 struct in6_validator_info
*i6vi
= (struct in6_validator_info
*) ptr
;
6386 struct net_device
*dev
= i6vi
->i6vi_dev
->dev
;
6387 struct mlxsw_sp
*mlxsw_sp
;
6388 struct mlxsw_sp_rif
*rif
;
6391 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6395 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6396 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6399 err
= __mlxsw_sp_inetaddr_event(dev
, event
, i6vi
->extack
);
6401 return notifier_from_errno(err
);
6404 static int mlxsw_sp_rif_edit(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
6405 const char *mac
, int mtu
)
6407 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6410 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
6411 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6415 mlxsw_reg_ritr_mtu_set(ritr_pl
, mtu
);
6416 mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl
, mac
);
6417 mlxsw_reg_ritr_op_set(ritr_pl
, MLXSW_REG_RITR_RIF_CREATE
);
6418 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6421 int mlxsw_sp_netdevice_router_port_event(struct net_device
*dev
)
6423 struct mlxsw_sp
*mlxsw_sp
;
6424 struct mlxsw_sp_rif
*rif
;
6428 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6432 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6435 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6437 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, false);
6441 err
= mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, dev
->dev_addr
,
6446 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, dev
->dev_addr
, fid_index
, true);
6448 goto err_rif_fdb_op
;
6450 if (rif
->mtu
!= dev
->mtu
) {
6451 struct mlxsw_sp_vr
*vr
;
6453 /* The RIF is relevant only to its mr_table instance, as unlike
6454 * unicast routing, in multicast routing a RIF cannot be shared
6455 * between several multicast routing tables.
6457 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6458 mlxsw_sp_mr_rif_mtu_update(vr
->mr4_table
, rif
, dev
->mtu
);
6461 ether_addr_copy(rif
->addr
, dev
->dev_addr
);
6462 rif
->mtu
= dev
->mtu
;
6464 netdev_dbg(dev
, "Updated RIF=%d\n", rif
->rif_index
);
6469 mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, rif
->addr
, rif
->mtu
);
6471 mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, true);
6475 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp
*mlxsw_sp
,
6476 struct net_device
*l3_dev
,
6477 struct netlink_ext_ack
*extack
)
6479 struct mlxsw_sp_rif
*rif
;
6481 /* If netdev is already associated with a RIF, then we need to
6482 * destroy it and create a new one with the new virtual router ID.
6484 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6486 __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_DOWN
, extack
);
6488 return __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_UP
, extack
);
6491 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp
*mlxsw_sp
,
6492 struct net_device
*l3_dev
)
6494 struct mlxsw_sp_rif
*rif
;
6496 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6499 __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_DOWN
, NULL
);
6502 int mlxsw_sp_netdevice_vrf_event(struct net_device
*l3_dev
, unsigned long event
,
6503 struct netdev_notifier_changeupper_info
*info
)
6505 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
6512 case NETDEV_PRECHANGEUPPER
:
6514 case NETDEV_CHANGEUPPER
:
6515 if (info
->linking
) {
6516 struct netlink_ext_ack
*extack
;
6518 extack
= netdev_notifier_info_to_extack(&info
->info
);
6519 err
= mlxsw_sp_port_vrf_join(mlxsw_sp
, l3_dev
, extack
);
6521 mlxsw_sp_port_vrf_leave(mlxsw_sp
, l3_dev
);
6529 static struct mlxsw_sp_rif_subport
*
6530 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif
*rif
)
6532 return container_of(rif
, struct mlxsw_sp_rif_subport
, common
);
6535 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif
*rif
,
6536 const struct mlxsw_sp_rif_params
*params
)
6538 struct mlxsw_sp_rif_subport
*rif_subport
;
6540 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6541 rif_subport
->vid
= params
->vid
;
6542 rif_subport
->lag
= params
->lag
;
6544 rif_subport
->lag_id
= params
->lag_id
;
6546 rif_subport
->system_port
= params
->system_port
;
6549 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif
*rif
, bool enable
)
6551 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6552 struct mlxsw_sp_rif_subport
*rif_subport
;
6553 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6555 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6556 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_SP_IF
,
6557 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
6558 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
6559 mlxsw_reg_ritr_sp_if_pack(ritr_pl
, rif_subport
->lag
,
6560 rif_subport
->lag
? rif_subport
->lag_id
:
6561 rif_subport
->system_port
,
6564 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6567 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif
*rif
)
6571 err
= mlxsw_sp_rif_subport_op(rif
, true);
6575 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6576 mlxsw_sp_fid_index(rif
->fid
), true);
6578 goto err_rif_fdb_op
;
6580 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6584 mlxsw_sp_rif_subport_op(rif
, false);
6588 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif
*rif
)
6590 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6592 mlxsw_sp_fid_rif_set(fid
, NULL
);
6593 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6594 mlxsw_sp_fid_index(fid
), false);
6595 mlxsw_sp_rif_subport_op(rif
, false);
6598 static struct mlxsw_sp_fid
*
6599 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif
*rif
)
6601 return mlxsw_sp_fid_rfid_get(rif
->mlxsw_sp
, rif
->rif_index
);
6604 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops
= {
6605 .type
= MLXSW_SP_RIF_TYPE_SUBPORT
,
6606 .rif_size
= sizeof(struct mlxsw_sp_rif_subport
),
6607 .setup
= mlxsw_sp_rif_subport_setup
,
6608 .configure
= mlxsw_sp_rif_subport_configure
,
6609 .deconfigure
= mlxsw_sp_rif_subport_deconfigure
,
6610 .fid_get
= mlxsw_sp_rif_subport_fid_get
,
6613 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif
*rif
,
6614 enum mlxsw_reg_ritr_if_type type
,
6615 u16 vid_fid
, bool enable
)
6617 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6618 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6620 mlxsw_reg_ritr_pack(ritr_pl
, enable
, type
, rif
->rif_index
, rif
->vr_id
,
6622 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
6623 mlxsw_reg_ritr_fid_set(ritr_pl
, type
, vid_fid
);
6625 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6628 u8
mlxsw_sp_router_port(const struct mlxsw_sp
*mlxsw_sp
)
6630 return mlxsw_core_max_ports(mlxsw_sp
->core
) + 1;
6633 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif
*rif
)
6635 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6636 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
6639 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, true);
6643 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6644 mlxsw_sp_router_port(mlxsw_sp
), true);
6646 goto err_fid_mc_flood_set
;
6648 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6649 mlxsw_sp_router_port(mlxsw_sp
), true);
6651 goto err_fid_bc_flood_set
;
6653 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6654 mlxsw_sp_fid_index(rif
->fid
), true);
6656 goto err_rif_fdb_op
;
6658 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6662 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6663 mlxsw_sp_router_port(mlxsw_sp
), false);
6664 err_fid_bc_flood_set
:
6665 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6666 mlxsw_sp_router_port(mlxsw_sp
), false);
6667 err_fid_mc_flood_set
:
6668 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
6672 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif
*rif
)
6674 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
6675 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6676 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6678 mlxsw_sp_fid_rif_set(fid
, NULL
);
6679 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6680 mlxsw_sp_fid_index(fid
), false);
6681 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6682 mlxsw_sp_router_port(mlxsw_sp
), false);
6683 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6684 mlxsw_sp_router_port(mlxsw_sp
), false);
6685 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
6688 static struct mlxsw_sp_fid
*
6689 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif
*rif
)
6691 u16 vid
= is_vlan_dev(rif
->dev
) ? vlan_dev_vlan_id(rif
->dev
) : 1;
6693 return mlxsw_sp_fid_8021q_get(rif
->mlxsw_sp
, vid
);
6696 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops
= {
6697 .type
= MLXSW_SP_RIF_TYPE_VLAN
,
6698 .rif_size
= sizeof(struct mlxsw_sp_rif
),
6699 .configure
= mlxsw_sp_rif_vlan_configure
,
6700 .deconfigure
= mlxsw_sp_rif_vlan_deconfigure
,
6701 .fid_get
= mlxsw_sp_rif_vlan_fid_get
,
6704 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif
*rif
)
6706 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6707 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6710 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
,
6715 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6716 mlxsw_sp_router_port(mlxsw_sp
), true);
6718 goto err_fid_mc_flood_set
;
6720 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6721 mlxsw_sp_router_port(mlxsw_sp
), true);
6723 goto err_fid_bc_flood_set
;
6725 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6726 mlxsw_sp_fid_index(rif
->fid
), true);
6728 goto err_rif_fdb_op
;
6730 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6734 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6735 mlxsw_sp_router_port(mlxsw_sp
), false);
6736 err_fid_bc_flood_set
:
6737 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6738 mlxsw_sp_router_port(mlxsw_sp
), false);
6739 err_fid_mc_flood_set
:
6740 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
6744 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif
*rif
)
6746 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6747 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6748 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6750 mlxsw_sp_fid_rif_set(fid
, NULL
);
6751 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6752 mlxsw_sp_fid_index(fid
), false);
6753 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6754 mlxsw_sp_router_port(mlxsw_sp
), false);
6755 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6756 mlxsw_sp_router_port(mlxsw_sp
), false);
6757 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
6760 static struct mlxsw_sp_fid
*
6761 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif
*rif
)
6763 return mlxsw_sp_fid_8021d_get(rif
->mlxsw_sp
, rif
->dev
->ifindex
);
6766 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops
= {
6767 .type
= MLXSW_SP_RIF_TYPE_FID
,
6768 .rif_size
= sizeof(struct mlxsw_sp_rif
),
6769 .configure
= mlxsw_sp_rif_fid_configure
,
6770 .deconfigure
= mlxsw_sp_rif_fid_deconfigure
,
6771 .fid_get
= mlxsw_sp_rif_fid_fid_get
,
6774 static struct mlxsw_sp_rif_ipip_lb
*
6775 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif
*rif
)
6777 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
6781 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif
*rif
,
6782 const struct mlxsw_sp_rif_params
*params
)
6784 struct mlxsw_sp_rif_params_ipip_lb
*params_lb
;
6785 struct mlxsw_sp_rif_ipip_lb
*rif_lb
;
6787 params_lb
= container_of(params
, struct mlxsw_sp_rif_params_ipip_lb
,
6789 rif_lb
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6790 rif_lb
->lb_config
= params_lb
->lb_config
;
6794 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb
*lb_rif
,
6795 struct mlxsw_sp_vr
*ul_vr
, bool enable
)
6797 struct mlxsw_sp_rif_ipip_lb_config lb_cf
= lb_rif
->lb_config
;
6798 struct mlxsw_sp_rif
*rif
= &lb_rif
->common
;
6799 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6800 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6803 switch (lb_cf
.ul_protocol
) {
6804 case MLXSW_SP_L3_PROTO_IPV4
:
6805 saddr4
= be32_to_cpu(lb_cf
.saddr
.addr4
);
6806 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_LOOPBACK_IF
,
6807 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
6808 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl
, lb_cf
.lb_ipipt
,
6809 MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET
,
6810 ul_vr
->id
, saddr4
, lb_cf
.okey
);
6813 case MLXSW_SP_L3_PROTO_IPV6
:
6814 return -EAFNOSUPPORT
;
6817 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6821 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif
*rif
)
6823 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6824 u32 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(rif
->dev
);
6825 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6826 struct mlxsw_sp_vr
*ul_vr
;
6829 ul_vr
= mlxsw_sp_vr_get(mlxsw_sp
, ul_tb_id
, NULL
);
6831 return PTR_ERR(ul_vr
);
6833 err
= mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
, true);
6835 goto err_loopback_op
;
6837 lb_rif
->ul_vr_id
= ul_vr
->id
;
6842 mlxsw_sp_vr_put(ul_vr
);
6846 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif
*rif
)
6848 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6849 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6850 struct mlxsw_sp_vr
*ul_vr
;
6852 ul_vr
= &mlxsw_sp
->router
->vrs
[lb_rif
->ul_vr_id
];
6853 mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
, false);
6856 mlxsw_sp_vr_put(ul_vr
);
6859 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops
= {
6860 .type
= MLXSW_SP_RIF_TYPE_IPIP_LB
,
6861 .rif_size
= sizeof(struct mlxsw_sp_rif_ipip_lb
),
6862 .setup
= mlxsw_sp_rif_ipip_lb_setup
,
6863 .configure
= mlxsw_sp_rif_ipip_lb_configure
,
6864 .deconfigure
= mlxsw_sp_rif_ipip_lb_deconfigure
,
6867 static const struct mlxsw_sp_rif_ops
*mlxsw_sp_rif_ops_arr
[] = {
6868 [MLXSW_SP_RIF_TYPE_SUBPORT
] = &mlxsw_sp_rif_subport_ops
,
6869 [MLXSW_SP_RIF_TYPE_VLAN
] = &mlxsw_sp_rif_vlan_ops
,
6870 [MLXSW_SP_RIF_TYPE_FID
] = &mlxsw_sp_rif_fid_ops
,
6871 [MLXSW_SP_RIF_TYPE_IPIP_LB
] = &mlxsw_sp_rif_ipip_lb_ops
,
6874 static int mlxsw_sp_rifs_init(struct mlxsw_sp
*mlxsw_sp
)
6876 u64 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
6878 mlxsw_sp
->router
->rifs
= kcalloc(max_rifs
,
6879 sizeof(struct mlxsw_sp_rif
*),
6881 if (!mlxsw_sp
->router
->rifs
)
6884 mlxsw_sp
->router
->rif_ops_arr
= mlxsw_sp_rif_ops_arr
;
6889 static void mlxsw_sp_rifs_fini(struct mlxsw_sp
*mlxsw_sp
)
6893 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
6894 WARN_ON_ONCE(mlxsw_sp
->router
->rifs
[i
]);
6896 kfree(mlxsw_sp
->router
->rifs
);
6900 mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp
*mlxsw_sp
)
6902 char tigcr_pl
[MLXSW_REG_TIGCR_LEN
];
6904 mlxsw_reg_tigcr_pack(tigcr_pl
, true, 0);
6905 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(tigcr
), tigcr_pl
);
6908 static int mlxsw_sp_ipips_init(struct mlxsw_sp
*mlxsw_sp
)
6910 mlxsw_sp
->router
->ipip_ops_arr
= mlxsw_sp_ipip_ops_arr
;
6911 INIT_LIST_HEAD(&mlxsw_sp
->router
->ipip_list
);
6912 return mlxsw_sp_ipip_config_tigcr(mlxsw_sp
);
6915 static void mlxsw_sp_ipips_fini(struct mlxsw_sp
*mlxsw_sp
)
6917 WARN_ON(!list_empty(&mlxsw_sp
->router
->ipip_list
));
6920 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block
*nb
)
6922 struct mlxsw_sp_router
*router
;
6924 /* Flush pending FIB notifications and then flush the device's
6925 * table before requesting another dump. The FIB notification
6926 * block is unregistered, so no need to take RTNL.
6928 mlxsw_core_flush_owq();
6929 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
6930 mlxsw_sp_router_fib_flush(router
->mlxsw_sp
);
6933 #ifdef CONFIG_IP_ROUTE_MULTIPATH
6934 static void mlxsw_sp_mp_hash_header_set(char *recr2_pl
, int header
)
6936 mlxsw_reg_recr2_outer_header_enables_set(recr2_pl
, header
, true);
6939 static void mlxsw_sp_mp_hash_field_set(char *recr2_pl
, int field
)
6941 mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl
, field
, true);
6944 static void mlxsw_sp_mp4_hash_init(char *recr2_pl
)
6946 bool only_l3
= !init_net
.ipv4
.sysctl_fib_multipath_hash_policy
;
6948 mlxsw_sp_mp_hash_header_set(recr2_pl
,
6949 MLXSW_REG_RECR2_IPV4_EN_NOT_TCP_NOT_UDP
);
6950 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_EN_TCP_UDP
);
6951 mlxsw_reg_recr2_ipv4_sip_enable(recr2_pl
);
6952 mlxsw_reg_recr2_ipv4_dip_enable(recr2_pl
);
6955 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_EN_IPV4
);
6956 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_PROTOCOL
);
6957 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_SPORT
);
6958 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_DPORT
);
6961 static void mlxsw_sp_mp6_hash_init(char *recr2_pl
)
6963 mlxsw_sp_mp_hash_header_set(recr2_pl
,
6964 MLXSW_REG_RECR2_IPV6_EN_NOT_TCP_NOT_UDP
);
6965 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_EN_TCP_UDP
);
6966 mlxsw_reg_recr2_ipv6_sip_enable(recr2_pl
);
6967 mlxsw_reg_recr2_ipv6_dip_enable(recr2_pl
);
6968 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_FLOW_LABEL
);
6969 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_NEXT_HEADER
);
6972 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
6974 char recr2_pl
[MLXSW_REG_RECR2_LEN
];
6977 get_random_bytes(&seed
, sizeof(seed
));
6978 mlxsw_reg_recr2_pack(recr2_pl
, seed
);
6979 mlxsw_sp_mp4_hash_init(recr2_pl
);
6980 mlxsw_sp_mp6_hash_init(recr2_pl
);
6982 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(recr2
), recr2_pl
);
6985 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
6991 static int __mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
6993 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
6997 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_RIFS
))
6999 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
7001 mlxsw_reg_rgcr_pack(rgcr_pl
, true, true);
7002 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl
, max_rifs
);
7003 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
7009 static void __mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
7011 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
7013 mlxsw_reg_rgcr_pack(rgcr_pl
, false, false);
7014 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
7017 int mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
7019 struct mlxsw_sp_router
*router
;
7022 router
= kzalloc(sizeof(*mlxsw_sp
->router
), GFP_KERNEL
);
7025 mlxsw_sp
->router
= router
;
7026 router
->mlxsw_sp
= mlxsw_sp
;
7028 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_neighs_list
);
7029 err
= __mlxsw_sp_router_init(mlxsw_sp
);
7031 goto err_router_init
;
7033 err
= mlxsw_sp_rifs_init(mlxsw_sp
);
7037 err
= mlxsw_sp_ipips_init(mlxsw_sp
);
7039 goto err_ipips_init
;
7041 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_ht
,
7042 &mlxsw_sp_nexthop_ht_params
);
7044 goto err_nexthop_ht_init
;
7046 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_group_ht
,
7047 &mlxsw_sp_nexthop_group_ht_params
);
7049 goto err_nexthop_group_ht_init
;
7051 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_list
);
7052 err
= mlxsw_sp_lpm_init(mlxsw_sp
);
7056 err
= mlxsw_sp_mr_init(mlxsw_sp
, &mlxsw_sp_mr_tcam_ops
);
7060 err
= mlxsw_sp_vrs_init(mlxsw_sp
);
7064 err
= mlxsw_sp_neigh_init(mlxsw_sp
);
7066 goto err_neigh_init
;
7068 mlxsw_sp
->router
->netevent_nb
.notifier_call
=
7069 mlxsw_sp_router_netevent_event
;
7070 err
= register_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7072 goto err_register_netevent_notifier
;
7074 err
= mlxsw_sp_mp_hash_init(mlxsw_sp
);
7076 goto err_mp_hash_init
;
7078 mlxsw_sp
->router
->fib_nb
.notifier_call
= mlxsw_sp_router_fib_event
;
7079 err
= register_fib_notifier(&mlxsw_sp
->router
->fib_nb
,
7080 mlxsw_sp_router_fib_dump_flush
);
7082 goto err_register_fib_notifier
;
7086 err_register_fib_notifier
:
7088 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7089 err_register_netevent_notifier
:
7090 mlxsw_sp_neigh_fini(mlxsw_sp
);
7092 mlxsw_sp_vrs_fini(mlxsw_sp
);
7094 mlxsw_sp_mr_fini(mlxsw_sp
);
7096 mlxsw_sp_lpm_fini(mlxsw_sp
);
7098 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
7099 err_nexthop_group_ht_init
:
7100 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
7101 err_nexthop_ht_init
:
7102 mlxsw_sp_ipips_fini(mlxsw_sp
);
7104 mlxsw_sp_rifs_fini(mlxsw_sp
);
7106 __mlxsw_sp_router_fini(mlxsw_sp
);
7108 kfree(mlxsw_sp
->router
);
7112 void mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
7114 unregister_fib_notifier(&mlxsw_sp
->router
->fib_nb
);
7115 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7116 mlxsw_sp_neigh_fini(mlxsw_sp
);
7117 mlxsw_sp_vrs_fini(mlxsw_sp
);
7118 mlxsw_sp_mr_fini(mlxsw_sp
);
7119 mlxsw_sp_lpm_fini(mlxsw_sp
);
7120 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
7121 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
7122 mlxsw_sp_ipips_fini(mlxsw_sp
);
7123 mlxsw_sp_rifs_fini(mlxsw_sp
);
7124 __mlxsw_sp_router_fini(mlxsw_sp
);
7125 kfree(mlxsw_sp
->router
);