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_mr_table
*mr4_table
;
741 struct mlxsw_sp_fib
*fib4
;
742 struct mlxsw_sp_fib
*fib6
;
743 struct mlxsw_sp_vr
*vr
;
746 vr
= mlxsw_sp_vr_find_unused(mlxsw_sp
);
748 NL_SET_ERR_MSG(extack
, "spectrum: Exceeded number of supported virtual routers");
749 return ERR_PTR(-EBUSY
);
751 fib4
= mlxsw_sp_fib_create(vr
, MLXSW_SP_L3_PROTO_IPV4
);
753 return ERR_CAST(fib4
);
754 fib6
= mlxsw_sp_fib_create(vr
, MLXSW_SP_L3_PROTO_IPV6
);
757 goto err_fib6_create
;
759 mr4_table
= mlxsw_sp_mr_table_create(mlxsw_sp
, vr
->id
,
760 MLXSW_SP_L3_PROTO_IPV4
);
761 if (IS_ERR(mr4_table
)) {
762 err
= PTR_ERR(mr4_table
);
763 goto err_mr_table_create
;
767 vr
->mr4_table
= mr4_table
;
772 mlxsw_sp_fib_destroy(fib6
);
774 mlxsw_sp_fib_destroy(fib4
);
778 static void mlxsw_sp_vr_destroy(struct mlxsw_sp_vr
*vr
)
780 mlxsw_sp_mr_table_destroy(vr
->mr4_table
);
781 vr
->mr4_table
= NULL
;
782 mlxsw_sp_fib_destroy(vr
->fib6
);
784 mlxsw_sp_fib_destroy(vr
->fib4
);
788 static struct mlxsw_sp_vr
*mlxsw_sp_vr_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
,
789 struct netlink_ext_ack
*extack
)
791 struct mlxsw_sp_vr
*vr
;
793 tb_id
= mlxsw_sp_fix_tb_id(tb_id
);
794 vr
= mlxsw_sp_vr_find(mlxsw_sp
, tb_id
);
796 vr
= mlxsw_sp_vr_create(mlxsw_sp
, tb_id
, extack
);
800 static void mlxsw_sp_vr_put(struct mlxsw_sp_vr
*vr
)
802 if (!vr
->rif_count
&& list_empty(&vr
->fib4
->node_list
) &&
803 list_empty(&vr
->fib6
->node_list
) &&
804 mlxsw_sp_mr_table_empty(vr
->mr4_table
))
805 mlxsw_sp_vr_destroy(vr
);
809 mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr
*vr
,
810 enum mlxsw_sp_l3proto proto
, u8 tree_id
)
812 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
814 if (!mlxsw_sp_vr_is_used(vr
))
816 if (fib
->lpm_tree
&& fib
->lpm_tree
->id
== tree_id
)
821 static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp
*mlxsw_sp
,
822 struct mlxsw_sp_fib
*fib
,
823 struct mlxsw_sp_lpm_tree
*new_tree
)
825 struct mlxsw_sp_lpm_tree
*old_tree
= fib
->lpm_tree
;
828 fib
->lpm_tree
= new_tree
;
829 mlxsw_sp_lpm_tree_hold(new_tree
);
830 err
= mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp
, fib
, new_tree
->id
);
833 mlxsw_sp_lpm_tree_put(mlxsw_sp
, old_tree
);
837 mlxsw_sp_lpm_tree_put(mlxsw_sp
, new_tree
);
838 fib
->lpm_tree
= old_tree
;
842 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp
*mlxsw_sp
,
843 struct mlxsw_sp_fib
*fib
,
844 struct mlxsw_sp_lpm_tree
*new_tree
)
846 struct mlxsw_sp_lpm_tree
*old_tree
= fib
->lpm_tree
;
847 enum mlxsw_sp_l3proto proto
= fib
->proto
;
848 u8 old_id
, new_id
= new_tree
->id
;
849 struct mlxsw_sp_vr
*vr
;
854 old_id
= old_tree
->id
;
856 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
857 vr
= &mlxsw_sp
->router
->vrs
[i
];
858 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr
, proto
, old_id
))
860 err
= mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp
,
861 mlxsw_sp_vr_fib(vr
, proto
),
864 goto err_tree_replace
;
870 for (i
--; i
>= 0; i
--) {
871 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr
, proto
, new_id
))
873 mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp
,
874 mlxsw_sp_vr_fib(vr
, proto
),
880 fib
->lpm_tree
= new_tree
;
881 mlxsw_sp_lpm_tree_hold(new_tree
);
882 err
= mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp
, fib
, new_tree
->id
);
884 mlxsw_sp_lpm_tree_put(mlxsw_sp
, new_tree
);
885 fib
->lpm_tree
= NULL
;
892 mlxsw_sp_vrs_prefixes(struct mlxsw_sp
*mlxsw_sp
,
893 enum mlxsw_sp_l3proto proto
,
894 struct mlxsw_sp_prefix_usage
*req_prefix_usage
)
898 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
899 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
900 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
901 unsigned char prefix
;
903 if (!mlxsw_sp_vr_is_used(vr
))
905 mlxsw_sp_prefix_usage_for_each(prefix
, &fib
->prefix_usage
)
906 mlxsw_sp_prefix_usage_set(req_prefix_usage
, prefix
);
910 static int mlxsw_sp_vrs_init(struct mlxsw_sp
*mlxsw_sp
)
912 struct mlxsw_sp_vr
*vr
;
916 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_VRS
))
919 max_vrs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
);
920 mlxsw_sp
->router
->vrs
= kcalloc(max_vrs
, sizeof(struct mlxsw_sp_vr
),
922 if (!mlxsw_sp
->router
->vrs
)
925 for (i
= 0; i
< max_vrs
; i
++) {
926 vr
= &mlxsw_sp
->router
->vrs
[i
];
933 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
);
935 static void mlxsw_sp_vrs_fini(struct mlxsw_sp
*mlxsw_sp
)
937 /* At this stage we're guaranteed not to have new incoming
938 * FIB notifications and the work queue is free from FIBs
939 * sitting on top of mlxsw netdevs. However, we can still
940 * have other FIBs queued. Flush the queue before flushing
941 * the device's tables. No need for locks, as we're the only
944 mlxsw_core_flush_owq();
945 mlxsw_sp_router_fib_flush(mlxsw_sp
);
946 kfree(mlxsw_sp
->router
->vrs
);
949 static struct net_device
*
950 __mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device
*ol_dev
)
952 struct ip_tunnel
*tun
= netdev_priv(ol_dev
);
953 struct net
*net
= dev_net(ol_dev
);
955 return __dev_get_by_index(net
, tun
->parms
.link
);
958 u32
mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device
*ol_dev
)
960 struct net_device
*d
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
963 return l3mdev_fib_table(d
) ? : RT_TABLE_MAIN
;
965 return l3mdev_fib_table(ol_dev
) ? : RT_TABLE_MAIN
;
968 static struct mlxsw_sp_rif
*
969 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
970 const struct mlxsw_sp_rif_params
*params
,
971 struct netlink_ext_ack
*extack
);
973 static struct mlxsw_sp_rif_ipip_lb
*
974 mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp
*mlxsw_sp
,
975 enum mlxsw_sp_ipip_type ipipt
,
976 struct net_device
*ol_dev
,
977 struct netlink_ext_ack
*extack
)
979 struct mlxsw_sp_rif_params_ipip_lb lb_params
;
980 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
981 struct mlxsw_sp_rif
*rif
;
983 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
984 lb_params
= (struct mlxsw_sp_rif_params_ipip_lb
) {
985 .common
.dev
= ol_dev
,
987 .lb_config
= ipip_ops
->ol_loopback_config(mlxsw_sp
, ol_dev
),
990 rif
= mlxsw_sp_rif_create(mlxsw_sp
, &lb_params
.common
, extack
);
992 return ERR_CAST(rif
);
993 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
996 static struct mlxsw_sp_ipip_entry
*
997 mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp
*mlxsw_sp
,
998 enum mlxsw_sp_ipip_type ipipt
,
999 struct net_device
*ol_dev
)
1001 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1002 struct mlxsw_sp_ipip_entry
*ret
= NULL
;
1004 ipip_entry
= kzalloc(sizeof(*ipip_entry
), GFP_KERNEL
);
1006 return ERR_PTR(-ENOMEM
);
1008 ipip_entry
->ol_lb
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
, ipipt
,
1010 if (IS_ERR(ipip_entry
->ol_lb
)) {
1011 ret
= ERR_CAST(ipip_entry
->ol_lb
);
1012 goto err_ol_ipip_lb_create
;
1015 ipip_entry
->ipipt
= ipipt
;
1016 ipip_entry
->ol_dev
= ol_dev
;
1017 ipip_entry
->parms
= mlxsw_sp_ipip_netdev_parms(ol_dev
);
1021 err_ol_ipip_lb_create
:
1027 mlxsw_sp_ipip_entry_dealloc(struct mlxsw_sp_ipip_entry
*ipip_entry
)
1029 mlxsw_sp_rif_destroy(&ipip_entry
->ol_lb
->common
);
1034 mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp
*mlxsw_sp
,
1035 const enum mlxsw_sp_l3proto ul_proto
,
1036 union mlxsw_sp_l3addr saddr
,
1038 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1040 u32 tun_ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry
->ol_dev
);
1041 enum mlxsw_sp_ipip_type ipipt
= ipip_entry
->ipipt
;
1042 union mlxsw_sp_l3addr tun_saddr
;
1044 if (mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
!= ul_proto
)
1047 tun_saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ipip_entry
->ol_dev
);
1048 return tun_ul_tb_id
== ul_tb_id
&&
1049 mlxsw_sp_l3addr_eq(&tun_saddr
, &saddr
);
1053 mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp
*mlxsw_sp
,
1054 struct mlxsw_sp_fib_entry
*fib_entry
,
1055 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1060 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, 1, &tunnel_index
);
1064 ipip_entry
->decap_fib_entry
= fib_entry
;
1065 fib_entry
->decap
.ipip_entry
= ipip_entry
;
1066 fib_entry
->decap
.tunnel_index
= tunnel_index
;
1070 static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp
*mlxsw_sp
,
1071 struct mlxsw_sp_fib_entry
*fib_entry
)
1073 /* Unlink this node from the IPIP entry that it's the decap entry of. */
1074 fib_entry
->decap
.ipip_entry
->decap_fib_entry
= NULL
;
1075 fib_entry
->decap
.ipip_entry
= NULL
;
1076 mlxsw_sp_kvdl_free(mlxsw_sp
, fib_entry
->decap
.tunnel_index
);
1079 static struct mlxsw_sp_fib_node
*
1080 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
1081 size_t addr_len
, unsigned char prefix_len
);
1082 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
1083 struct mlxsw_sp_fib_entry
*fib_entry
);
1086 mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp
*mlxsw_sp
,
1087 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1089 struct mlxsw_sp_fib_entry
*fib_entry
= ipip_entry
->decap_fib_entry
;
1091 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, fib_entry
);
1092 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
1094 mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
1098 mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp
*mlxsw_sp
,
1099 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1100 struct mlxsw_sp_fib_entry
*decap_fib_entry
)
1102 if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp
, decap_fib_entry
,
1105 decap_fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
1107 if (mlxsw_sp_fib_entry_update(mlxsw_sp
, decap_fib_entry
))
1108 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1111 /* Given an IPIP entry, find the corresponding decap route. */
1112 static struct mlxsw_sp_fib_entry
*
1113 mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp
*mlxsw_sp
,
1114 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1116 static struct mlxsw_sp_fib_node
*fib_node
;
1117 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1118 struct mlxsw_sp_fib_entry
*fib_entry
;
1119 unsigned char saddr_prefix_len
;
1120 union mlxsw_sp_l3addr saddr
;
1121 struct mlxsw_sp_fib
*ul_fib
;
1122 struct mlxsw_sp_vr
*ul_vr
;
1128 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1130 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry
->ol_dev
);
1131 ul_vr
= mlxsw_sp_vr_find(mlxsw_sp
, ul_tb_id
);
1135 ul_fib
= mlxsw_sp_vr_fib(ul_vr
, ipip_ops
->ul_proto
);
1136 saddr
= mlxsw_sp_ipip_netdev_saddr(ipip_ops
->ul_proto
,
1137 ipip_entry
->ol_dev
);
1139 switch (ipip_ops
->ul_proto
) {
1140 case MLXSW_SP_L3_PROTO_IPV4
:
1141 saddr4
= be32_to_cpu(saddr
.addr4
);
1144 saddr_prefix_len
= 32;
1146 case MLXSW_SP_L3_PROTO_IPV6
:
1151 fib_node
= mlxsw_sp_fib_node_lookup(ul_fib
, saddrp
, saddr_len
,
1153 if (!fib_node
|| list_empty(&fib_node
->entry_list
))
1156 fib_entry
= list_first_entry(&fib_node
->entry_list
,
1157 struct mlxsw_sp_fib_entry
, list
);
1158 if (fib_entry
->type
!= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
)
1164 static struct mlxsw_sp_ipip_entry
*
1165 mlxsw_sp_ipip_entry_create(struct mlxsw_sp
*mlxsw_sp
,
1166 enum mlxsw_sp_ipip_type ipipt
,
1167 struct net_device
*ol_dev
)
1169 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1171 ipip_entry
= mlxsw_sp_ipip_entry_alloc(mlxsw_sp
, ipipt
, ol_dev
);
1172 if (IS_ERR(ipip_entry
))
1175 list_add_tail(&ipip_entry
->ipip_list_node
,
1176 &mlxsw_sp
->router
->ipip_list
);
1182 mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
1183 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1185 list_del(&ipip_entry
->ipip_list_node
);
1186 mlxsw_sp_ipip_entry_dealloc(ipip_entry
);
1190 mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp
*mlxsw_sp
,
1191 const struct net_device
*ul_dev
,
1192 enum mlxsw_sp_l3proto ul_proto
,
1193 union mlxsw_sp_l3addr ul_dip
,
1194 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1196 u32 ul_tb_id
= l3mdev_fib_table(ul_dev
) ? : RT_TABLE_MAIN
;
1197 enum mlxsw_sp_ipip_type ipipt
= ipip_entry
->ipipt
;
1198 struct net_device
*ipip_ul_dev
;
1200 if (mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
!= ul_proto
)
1203 ipip_ul_dev
= __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1204 return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, ul_dip
,
1205 ul_tb_id
, ipip_entry
) &&
1206 (!ipip_ul_dev
|| ipip_ul_dev
== ul_dev
);
1209 /* Given decap parameters, find the corresponding IPIP entry. */
1210 static struct mlxsw_sp_ipip_entry
*
1211 mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp
*mlxsw_sp
,
1212 const struct net_device
*ul_dev
,
1213 enum mlxsw_sp_l3proto ul_proto
,
1214 union mlxsw_sp_l3addr ul_dip
)
1216 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1218 list_for_each_entry(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1220 if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp
, ul_dev
,
1228 static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
1229 const struct net_device
*dev
,
1230 enum mlxsw_sp_ipip_type
*p_type
)
1232 struct mlxsw_sp_router
*router
= mlxsw_sp
->router
;
1233 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1234 enum mlxsw_sp_ipip_type ipipt
;
1236 for (ipipt
= 0; ipipt
< MLXSW_SP_IPIP_TYPE_MAX
; ++ipipt
) {
1237 ipip_ops
= router
->ipip_ops_arr
[ipipt
];
1238 if (dev
->type
== ipip_ops
->dev_type
) {
1247 bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp
*mlxsw_sp
,
1248 const struct net_device
*dev
)
1250 return mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
);
1253 static struct mlxsw_sp_ipip_entry
*
1254 mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp
*mlxsw_sp
,
1255 const struct net_device
*ol_dev
)
1257 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1259 list_for_each_entry(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1261 if (ipip_entry
->ol_dev
== ol_dev
)
1267 static struct mlxsw_sp_ipip_entry
*
1268 mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp
*mlxsw_sp
,
1269 const struct net_device
*ul_dev
,
1270 struct mlxsw_sp_ipip_entry
*start
)
1272 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1274 ipip_entry
= list_prepare_entry(start
, &mlxsw_sp
->router
->ipip_list
,
1276 list_for_each_entry_continue(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1278 struct net_device
*ipip_ul_dev
=
1279 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1281 if (ipip_ul_dev
== ul_dev
)
1288 bool mlxsw_sp_netdev_is_ipip_ul(const struct mlxsw_sp
*mlxsw_sp
,
1289 const struct net_device
*dev
)
1291 return mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
, dev
, NULL
);
1294 static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp
*mlxsw_sp
,
1295 const struct net_device
*ol_dev
,
1296 enum mlxsw_sp_ipip_type ipipt
)
1298 const struct mlxsw_sp_ipip_ops
*ops
1299 = mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
1301 /* For deciding whether decap should be offloaded, we don't care about
1302 * overlay protocol, so ask whether either one is supported.
1304 return ops
->can_offload(mlxsw_sp
, ol_dev
, MLXSW_SP_L3_PROTO_IPV4
) ||
1305 ops
->can_offload(mlxsw_sp
, ol_dev
, MLXSW_SP_L3_PROTO_IPV6
);
1308 static int mlxsw_sp_netdevice_ipip_ol_reg_event(struct mlxsw_sp
*mlxsw_sp
,
1309 struct net_device
*ol_dev
)
1311 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1312 enum mlxsw_sp_l3proto ul_proto
;
1313 enum mlxsw_sp_ipip_type ipipt
;
1314 union mlxsw_sp_l3addr saddr
;
1317 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, ol_dev
, &ipipt
);
1318 if (mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
, ipipt
)) {
1319 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ol_dev
);
1320 ul_proto
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
;
1321 saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ol_dev
);
1322 if (!mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp
, ul_proto
,
1325 ipip_entry
= mlxsw_sp_ipip_entry_create(mlxsw_sp
, ipipt
,
1327 if (IS_ERR(ipip_entry
))
1328 return PTR_ERR(ipip_entry
);
1335 static void mlxsw_sp_netdevice_ipip_ol_unreg_event(struct mlxsw_sp
*mlxsw_sp
,
1336 struct net_device
*ol_dev
)
1338 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1340 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1342 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1346 mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp
*mlxsw_sp
,
1347 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1349 struct mlxsw_sp_fib_entry
*decap_fib_entry
;
1351 decap_fib_entry
= mlxsw_sp_ipip_entry_find_decap(mlxsw_sp
, ipip_entry
);
1352 if (decap_fib_entry
)
1353 mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp
, ipip_entry
,
1357 static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp
*mlxsw_sp
,
1358 struct net_device
*ol_dev
)
1360 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1362 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1364 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1368 mlxsw_sp_ipip_entry_ol_down_event(struct mlxsw_sp
*mlxsw_sp
,
1369 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1371 if (ipip_entry
->decap_fib_entry
)
1372 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1375 static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp
*mlxsw_sp
,
1376 struct net_device
*ol_dev
)
1378 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1380 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1382 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1385 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp
*mlxsw_sp
,
1386 struct mlxsw_sp_rif
*old_rif
,
1387 struct mlxsw_sp_rif
*new_rif
);
1389 mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp
*mlxsw_sp
,
1390 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1392 struct netlink_ext_ack
*extack
)
1394 struct mlxsw_sp_rif_ipip_lb
*old_lb_rif
= ipip_entry
->ol_lb
;
1395 struct mlxsw_sp_rif_ipip_lb
*new_lb_rif
;
1397 new_lb_rif
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
,
1401 if (IS_ERR(new_lb_rif
))
1402 return PTR_ERR(new_lb_rif
);
1403 ipip_entry
->ol_lb
= new_lb_rif
;
1406 mlxsw_sp_nexthop_rif_migrate(mlxsw_sp
, &old_lb_rif
->common
,
1407 &new_lb_rif
->common
);
1409 mlxsw_sp_rif_destroy(&old_lb_rif
->common
);
1414 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
1415 struct mlxsw_sp_rif
*rif
);
1418 * Update the offload related to an IPIP entry. This always updates decap, and
1419 * in addition to that it also:
1420 * @recreate_loopback: recreates the associated loopback RIF
1421 * @keep_encap: updates next hops that use the tunnel netdevice. This is only
1422 * relevant when recreate_loopback is true.
1423 * @update_nexthops: updates next hops, keeping the current loopback RIF. This
1424 * is only relevant when recreate_loopback is false.
1426 int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1427 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1428 bool recreate_loopback
,
1430 bool update_nexthops
,
1431 struct netlink_ext_ack
*extack
)
1435 /* RIFs can't be edited, so to update loopback, we need to destroy and
1436 * recreate it. That creates a window of opportunity where RALUE and
1437 * RATR registers end up referencing a RIF that's already gone. RATRs
1438 * are handled in mlxsw_sp_ipip_entry_ol_lb_update(), and to take care
1439 * of RALUE, demote the decap route back.
1441 if (ipip_entry
->decap_fib_entry
)
1442 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1444 if (recreate_loopback
) {
1445 err
= mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp
, ipip_entry
,
1446 keep_encap
, extack
);
1449 } else if (update_nexthops
) {
1450 mlxsw_sp_nexthop_rif_update(mlxsw_sp
,
1451 &ipip_entry
->ol_lb
->common
);
1454 if (ipip_entry
->ol_dev
->flags
& IFF_UP
)
1455 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1460 static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1461 struct net_device
*ol_dev
,
1462 struct netlink_ext_ack
*extack
)
1464 struct mlxsw_sp_ipip_entry
*ipip_entry
=
1465 mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1466 enum mlxsw_sp_l3proto ul_proto
;
1467 union mlxsw_sp_l3addr saddr
;
1473 /* For flat configuration cases, moving overlay to a different VRF might
1474 * cause local address conflict, and the conflicting tunnels need to be
1477 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ol_dev
);
1478 ul_proto
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
]->ul_proto
;
1479 saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ol_dev
);
1480 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp
, ul_proto
,
1483 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1487 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1488 true, false, false, extack
);
1492 mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1493 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1494 struct net_device
*ul_dev
,
1495 struct netlink_ext_ack
*extack
)
1497 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1498 true, true, false, extack
);
1502 mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp
*mlxsw_sp
,
1503 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1504 struct net_device
*ul_dev
)
1506 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1507 false, false, true, NULL
);
1511 mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp
*mlxsw_sp
,
1512 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1513 struct net_device
*ul_dev
)
1515 /* A down underlay device causes encapsulated packets to not be
1516 * forwarded, but decap still works. So refresh next hops without
1517 * touching anything else.
1519 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1520 false, false, true, NULL
);
1524 mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp
*mlxsw_sp
,
1525 struct net_device
*ol_dev
,
1526 struct netlink_ext_ack
*extack
)
1528 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1529 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1532 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1534 /* A change might make a tunnel eligible for offloading, but
1535 * that is currently not implemented. What falls to slow path
1540 /* A change might make a tunnel not eligible for offloading. */
1541 if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
,
1542 ipip_entry
->ipipt
)) {
1543 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1547 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1548 err
= ipip_ops
->ol_netdev_change(mlxsw_sp
, ipip_entry
, extack
);
1552 void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1553 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1555 struct net_device
*ol_dev
= ipip_entry
->ol_dev
;
1557 if (ol_dev
->flags
& IFF_UP
)
1558 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1559 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1562 /* The configuration where several tunnels have the same local address in the
1563 * same underlay table needs special treatment in the HW. That is currently not
1564 * implemented in the driver. This function finds and demotes the first tunnel
1565 * with a given source address, except the one passed in in the argument
1569 mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp
*mlxsw_sp
,
1570 enum mlxsw_sp_l3proto ul_proto
,
1571 union mlxsw_sp_l3addr saddr
,
1573 const struct mlxsw_sp_ipip_entry
*except
)
1575 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1577 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1579 if (ipip_entry
!= except
&&
1580 mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, saddr
,
1581 ul_tb_id
, ipip_entry
)) {
1582 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1590 static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp
*mlxsw_sp
,
1591 struct net_device
*ul_dev
)
1593 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1595 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1597 struct net_device
*ipip_ul_dev
=
1598 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1600 if (ipip_ul_dev
== ul_dev
)
1601 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1605 int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp
*mlxsw_sp
,
1606 struct net_device
*ol_dev
,
1607 unsigned long event
,
1608 struct netdev_notifier_info
*info
)
1610 struct netdev_notifier_changeupper_info
*chup
;
1611 struct netlink_ext_ack
*extack
;
1614 case NETDEV_REGISTER
:
1615 return mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp
, ol_dev
);
1616 case NETDEV_UNREGISTER
:
1617 mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp
, ol_dev
);
1620 mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp
, ol_dev
);
1623 mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp
, ol_dev
);
1625 case NETDEV_CHANGEUPPER
:
1626 chup
= container_of(info
, typeof(*chup
), info
);
1627 extack
= info
->extack
;
1628 if (netif_is_l3_master(chup
->upper_dev
))
1629 return mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp
,
1634 extack
= info
->extack
;
1635 return mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp
,
1642 __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1643 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1644 struct net_device
*ul_dev
,
1645 unsigned long event
,
1646 struct netdev_notifier_info
*info
)
1648 struct netdev_notifier_changeupper_info
*chup
;
1649 struct netlink_ext_ack
*extack
;
1652 case NETDEV_CHANGEUPPER
:
1653 chup
= container_of(info
, typeof(*chup
), info
);
1654 extack
= info
->extack
;
1655 if (netif_is_l3_master(chup
->upper_dev
))
1656 return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp
,
1663 return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp
, ipip_entry
,
1666 return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp
,
1674 mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1675 struct net_device
*ul_dev
,
1676 unsigned long event
,
1677 struct netdev_notifier_info
*info
)
1679 struct mlxsw_sp_ipip_entry
*ipip_entry
= NULL
;
1682 while ((ipip_entry
= mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
,
1685 err
= __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp
, ipip_entry
,
1686 ul_dev
, event
, info
);
1688 mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp
,
1697 struct mlxsw_sp_neigh_key
{
1698 struct neighbour
*n
;
1701 struct mlxsw_sp_neigh_entry
{
1702 struct list_head rif_list_node
;
1703 struct rhash_head ht_node
;
1704 struct mlxsw_sp_neigh_key key
;
1707 unsigned char ha
[ETH_ALEN
];
1708 struct list_head nexthop_list
; /* list of nexthops using
1711 struct list_head nexthop_neighs_list_node
;
1712 unsigned int counter_index
;
1716 static const struct rhashtable_params mlxsw_sp_neigh_ht_params
= {
1717 .key_offset
= offsetof(struct mlxsw_sp_neigh_entry
, key
),
1718 .head_offset
= offsetof(struct mlxsw_sp_neigh_entry
, ht_node
),
1719 .key_len
= sizeof(struct mlxsw_sp_neigh_key
),
1722 struct mlxsw_sp_neigh_entry
*
1723 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif
*rif
,
1724 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1727 if (list_empty(&rif
->neigh_list
))
1730 return list_first_entry(&rif
->neigh_list
,
1731 typeof(*neigh_entry
),
1734 if (list_is_last(&neigh_entry
->rif_list_node
, &rif
->neigh_list
))
1736 return list_next_entry(neigh_entry
, rif_list_node
);
1739 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1741 return neigh_entry
->key
.n
->tbl
->family
;
1745 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1747 return neigh_entry
->ha
;
1750 u32
mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1752 struct neighbour
*n
;
1754 n
= neigh_entry
->key
.n
;
1755 return ntohl(*((__be32
*) n
->primary_key
));
1759 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1761 struct neighbour
*n
;
1763 n
= neigh_entry
->key
.n
;
1764 return (struct in6_addr
*) &n
->primary_key
;
1767 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp
*mlxsw_sp
,
1768 struct mlxsw_sp_neigh_entry
*neigh_entry
,
1771 if (!neigh_entry
->counter_valid
)
1774 return mlxsw_sp_flow_counter_get(mlxsw_sp
, neigh_entry
->counter_index
,
1778 static struct mlxsw_sp_neigh_entry
*
1779 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
,
1782 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1784 neigh_entry
= kzalloc(sizeof(*neigh_entry
), GFP_KERNEL
);
1788 neigh_entry
->key
.n
= n
;
1789 neigh_entry
->rif
= rif
;
1790 INIT_LIST_HEAD(&neigh_entry
->nexthop_list
);
1795 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1801 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp
*mlxsw_sp
,
1802 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1804 return rhashtable_insert_fast(&mlxsw_sp
->router
->neigh_ht
,
1805 &neigh_entry
->ht_node
,
1806 mlxsw_sp_neigh_ht_params
);
1810 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp
*mlxsw_sp
,
1811 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1813 rhashtable_remove_fast(&mlxsw_sp
->router
->neigh_ht
,
1814 &neigh_entry
->ht_node
,
1815 mlxsw_sp_neigh_ht_params
);
1819 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp
*mlxsw_sp
,
1820 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1822 struct devlink
*devlink
;
1823 const char *table_name
;
1825 switch (mlxsw_sp_neigh_entry_type(neigh_entry
)) {
1827 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST4
;
1830 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST6
;
1837 devlink
= priv_to_devlink(mlxsw_sp
->core
);
1838 return devlink_dpipe_table_counter_enabled(devlink
, table_name
);
1842 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
1843 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1845 if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp
, neigh_entry
))
1848 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &neigh_entry
->counter_index
))
1851 neigh_entry
->counter_valid
= true;
1855 mlxsw_sp_neigh_counter_free(struct mlxsw_sp
*mlxsw_sp
,
1856 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1858 if (!neigh_entry
->counter_valid
)
1860 mlxsw_sp_flow_counter_free(mlxsw_sp
,
1861 neigh_entry
->counter_index
);
1862 neigh_entry
->counter_valid
= false;
1865 static struct mlxsw_sp_neigh_entry
*
1866 mlxsw_sp_neigh_entry_create(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
1868 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1869 struct mlxsw_sp_rif
*rif
;
1872 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, n
->dev
);
1874 return ERR_PTR(-EINVAL
);
1876 neigh_entry
= mlxsw_sp_neigh_entry_alloc(mlxsw_sp
, n
, rif
->rif_index
);
1878 return ERR_PTR(-ENOMEM
);
1880 err
= mlxsw_sp_neigh_entry_insert(mlxsw_sp
, neigh_entry
);
1882 goto err_neigh_entry_insert
;
1884 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
1885 list_add(&neigh_entry
->rif_list_node
, &rif
->neigh_list
);
1889 err_neigh_entry_insert
:
1890 mlxsw_sp_neigh_entry_free(neigh_entry
);
1891 return ERR_PTR(err
);
1895 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
1896 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1898 list_del(&neigh_entry
->rif_list_node
);
1899 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
1900 mlxsw_sp_neigh_entry_remove(mlxsw_sp
, neigh_entry
);
1901 mlxsw_sp_neigh_entry_free(neigh_entry
);
1904 static struct mlxsw_sp_neigh_entry
*
1905 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
1907 struct mlxsw_sp_neigh_key key
;
1910 return rhashtable_lookup_fast(&mlxsw_sp
->router
->neigh_ht
,
1911 &key
, mlxsw_sp_neigh_ht_params
);
1915 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp
*mlxsw_sp
)
1917 unsigned long interval
;
1919 #if IS_ENABLED(CONFIG_IPV6)
1920 interval
= min_t(unsigned long,
1921 NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
),
1922 NEIGH_VAR(&nd_tbl
.parms
, DELAY_PROBE_TIME
));
1924 interval
= NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
);
1926 mlxsw_sp
->router
->neighs_update
.interval
= jiffies_to_msecs(interval
);
1929 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
1933 struct net_device
*dev
;
1934 struct neighbour
*n
;
1939 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl
, ent_index
, &rif
, &dip
);
1941 if (!mlxsw_sp
->router
->rifs
[rif
]) {
1942 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
1947 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
1948 n
= neigh_lookup(&arp_tbl
, &dipn
, dev
);
1952 netdev_dbg(dev
, "Updating neighbour with IP=%pI4h\n", &dip
);
1953 neigh_event_send(n
, NULL
);
1957 #if IS_ENABLED(CONFIG_IPV6)
1958 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1962 struct net_device
*dev
;
1963 struct neighbour
*n
;
1964 struct in6_addr dip
;
1967 mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl
, rec_index
, &rif
,
1970 if (!mlxsw_sp
->router
->rifs
[rif
]) {
1971 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
1975 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
1976 n
= neigh_lookup(&nd_tbl
, &dip
, dev
);
1980 netdev_dbg(dev
, "Updating neighbour with IP=%pI6c\n", &dip
);
1981 neigh_event_send(n
, NULL
);
1985 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
1992 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
1999 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
2001 /* Hardware starts counting at 0, so add 1. */
2004 /* Each record consists of several neighbour entries. */
2005 for (i
= 0; i
< num_entries
; i
++) {
2008 ent_index
= rec_index
* MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
+ i
;
2009 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2015 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
2019 /* One record contains one entry. */
2020 mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2024 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp
*mlxsw_sp
,
2025 char *rauhtd_pl
, int rec_index
)
2027 switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, rec_index
)) {
2028 case MLXSW_REG_RAUHTD_TYPE_IPV4
:
2029 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2032 case MLXSW_REG_RAUHTD_TYPE_IPV6
:
2033 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2039 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl
)
2041 u8 num_rec
, last_rec_index
, num_entries
;
2043 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2044 last_rec_index
= num_rec
- 1;
2046 if (num_rec
< MLXSW_REG_RAUHTD_REC_MAX_NUM
)
2048 if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, last_rec_index
) ==
2049 MLXSW_REG_RAUHTD_TYPE_IPV6
)
2052 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
2054 if (++num_entries
== MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
)
2060 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
,
2062 enum mlxsw_reg_rauhtd_type type
)
2067 /* Make sure the neighbour's netdev isn't removed in the
2072 mlxsw_reg_rauhtd_pack(rauhtd_pl
, type
);
2073 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(rauhtd
),
2076 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Failed to dump neighbour table\n");
2079 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2080 for (i
= 0; i
< num_rec
; i
++)
2081 mlxsw_sp_router_neigh_rec_process(mlxsw_sp
, rauhtd_pl
,
2083 } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl
));
2089 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
)
2091 enum mlxsw_reg_rauhtd_type type
;
2095 rauhtd_pl
= kmalloc(MLXSW_REG_RAUHTD_LEN
, GFP_KERNEL
);
2099 type
= MLXSW_REG_RAUHTD_TYPE_IPV4
;
2100 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2104 type
= MLXSW_REG_RAUHTD_TYPE_IPV6
;
2105 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2111 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp
*mlxsw_sp
)
2113 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2115 /* Take RTNL mutex here to prevent lists from changes */
2117 list_for_each_entry(neigh_entry
, &mlxsw_sp
->router
->nexthop_neighs_list
,
2118 nexthop_neighs_list_node
)
2119 /* If this neigh have nexthops, make the kernel think this neigh
2120 * is active regardless of the traffic.
2122 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2127 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp
*mlxsw_sp
)
2129 unsigned long interval
= mlxsw_sp
->router
->neighs_update
.interval
;
2131 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
,
2132 msecs_to_jiffies(interval
));
2135 static void mlxsw_sp_router_neighs_update_work(struct work_struct
*work
)
2137 struct mlxsw_sp_router
*router
;
2140 router
= container_of(work
, struct mlxsw_sp_router
,
2141 neighs_update
.dw
.work
);
2142 err
= mlxsw_sp_router_neighs_update_rauhtd(router
->mlxsw_sp
);
2144 dev_err(router
->mlxsw_sp
->bus_info
->dev
, "Could not update kernel for neigh activity");
2146 mlxsw_sp_router_neighs_update_nh(router
->mlxsw_sp
);
2148 mlxsw_sp_router_neighs_update_work_schedule(router
->mlxsw_sp
);
2151 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct
*work
)
2153 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2154 struct mlxsw_sp_router
*router
;
2156 router
= container_of(work
, struct mlxsw_sp_router
,
2157 nexthop_probe_dw
.work
);
2158 /* Iterate over nexthop neighbours, find those who are unresolved and
2159 * send arp on them. This solves the chicken-egg problem when
2160 * the nexthop wouldn't get offloaded until the neighbor is resolved
2161 * but it wouldn't get resolved ever in case traffic is flowing in HW
2162 * using different nexthop.
2164 * Take RTNL mutex here to prevent lists from changes.
2167 list_for_each_entry(neigh_entry
, &router
->nexthop_neighs_list
,
2168 nexthop_neighs_list_node
)
2169 if (!neigh_entry
->connected
)
2170 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2173 mlxsw_core_schedule_dw(&router
->nexthop_probe_dw
,
2174 MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL
);
2178 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
2179 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2182 static enum mlxsw_reg_rauht_op
mlxsw_sp_rauht_op(bool adding
)
2184 return adding
? MLXSW_REG_RAUHT_OP_WRITE_ADD
:
2185 MLXSW_REG_RAUHT_OP_WRITE_DELETE
;
2189 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp
*mlxsw_sp
,
2190 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2191 enum mlxsw_reg_rauht_op op
)
2193 struct neighbour
*n
= neigh_entry
->key
.n
;
2194 u32 dip
= ntohl(*((__be32
*) n
->primary_key
));
2195 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2197 mlxsw_reg_rauht_pack4(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2199 if (neigh_entry
->counter_valid
)
2200 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2201 neigh_entry
->counter_index
);
2202 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2206 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp
*mlxsw_sp
,
2207 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2208 enum mlxsw_reg_rauht_op op
)
2210 struct neighbour
*n
= neigh_entry
->key
.n
;
2211 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2212 const char *dip
= n
->primary_key
;
2214 mlxsw_reg_rauht_pack6(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2216 if (neigh_entry
->counter_valid
)
2217 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2218 neigh_entry
->counter_index
);
2219 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2222 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry
*neigh_entry
)
2224 struct neighbour
*n
= neigh_entry
->key
.n
;
2226 /* Packets with a link-local destination address are trapped
2227 * after LPM lookup and never reach the neighbour table, so
2228 * there is no need to program such neighbours to the device.
2230 if (ipv6_addr_type((struct in6_addr
*) &n
->primary_key
) &
2231 IPV6_ADDR_LINKLOCAL
)
2237 mlxsw_sp_neigh_entry_update(struct mlxsw_sp
*mlxsw_sp
,
2238 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2241 if (!adding
&& !neigh_entry
->connected
)
2243 neigh_entry
->connected
= adding
;
2244 if (neigh_entry
->key
.n
->tbl
->family
== AF_INET
) {
2245 mlxsw_sp_router_neigh_entry_op4(mlxsw_sp
, neigh_entry
,
2246 mlxsw_sp_rauht_op(adding
));
2247 } else if (neigh_entry
->key
.n
->tbl
->family
== AF_INET6
) {
2248 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
2250 mlxsw_sp_router_neigh_entry_op6(mlxsw_sp
, neigh_entry
,
2251 mlxsw_sp_rauht_op(adding
));
2258 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp
*mlxsw_sp
,
2259 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2263 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
2265 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
2266 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, true);
2269 struct mlxsw_sp_netevent_work
{
2270 struct work_struct work
;
2271 struct mlxsw_sp
*mlxsw_sp
;
2272 struct neighbour
*n
;
2275 static void mlxsw_sp_router_neigh_event_work(struct work_struct
*work
)
2277 struct mlxsw_sp_netevent_work
*net_work
=
2278 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2279 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2280 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2281 struct neighbour
*n
= net_work
->n
;
2282 unsigned char ha
[ETH_ALEN
];
2283 bool entry_connected
;
2286 /* If these parameters are changed after we release the lock,
2287 * then we are guaranteed to receive another event letting us
2290 read_lock_bh(&n
->lock
);
2291 memcpy(ha
, n
->ha
, ETH_ALEN
);
2292 nud_state
= n
->nud_state
;
2294 read_unlock_bh(&n
->lock
);
2297 entry_connected
= nud_state
& NUD_VALID
&& !dead
;
2298 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
2299 if (!entry_connected
&& !neigh_entry
)
2302 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
2303 if (IS_ERR(neigh_entry
))
2307 memcpy(neigh_entry
->ha
, ha
, ETH_ALEN
);
2308 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, entry_connected
);
2309 mlxsw_sp_nexthop_neigh_update(mlxsw_sp
, neigh_entry
, !entry_connected
);
2311 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
2312 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2320 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
);
2322 static void mlxsw_sp_router_mp_hash_event_work(struct work_struct
*work
)
2324 struct mlxsw_sp_netevent_work
*net_work
=
2325 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2326 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2328 mlxsw_sp_mp_hash_init(mlxsw_sp
);
2332 static int mlxsw_sp_router_netevent_event(struct notifier_block
*nb
,
2333 unsigned long event
, void *ptr
)
2335 struct mlxsw_sp_netevent_work
*net_work
;
2336 struct mlxsw_sp_port
*mlxsw_sp_port
;
2337 struct mlxsw_sp_router
*router
;
2338 struct mlxsw_sp
*mlxsw_sp
;
2339 unsigned long interval
;
2340 struct neigh_parms
*p
;
2341 struct neighbour
*n
;
2345 case NETEVENT_DELAY_PROBE_TIME_UPDATE
:
2348 /* We don't care about changes in the default table. */
2349 if (!p
->dev
|| (p
->tbl
->family
!= AF_INET
&&
2350 p
->tbl
->family
!= AF_INET6
))
2353 /* We are in atomic context and can't take RTNL mutex,
2354 * so use RCU variant to walk the device chain.
2356 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(p
->dev
);
2360 mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2361 interval
= jiffies_to_msecs(NEIGH_VAR(p
, DELAY_PROBE_TIME
));
2362 mlxsw_sp
->router
->neighs_update
.interval
= interval
;
2364 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2366 case NETEVENT_NEIGH_UPDATE
:
2369 if (n
->tbl
->family
!= AF_INET
&& n
->tbl
->family
!= AF_INET6
)
2372 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(n
->dev
);
2376 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2378 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2382 INIT_WORK(&net_work
->work
, mlxsw_sp_router_neigh_event_work
);
2383 net_work
->mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2386 /* Take a reference to ensure the neighbour won't be
2387 * destructed until we drop the reference in delayed
2391 mlxsw_core_schedule_work(&net_work
->work
);
2392 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2394 case NETEVENT_MULTIPATH_HASH_UPDATE
:
2397 if (!net_eq(net
, &init_net
))
2400 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2404 router
= container_of(nb
, struct mlxsw_sp_router
, netevent_nb
);
2405 INIT_WORK(&net_work
->work
, mlxsw_sp_router_mp_hash_event_work
);
2406 net_work
->mlxsw_sp
= router
->mlxsw_sp
;
2407 mlxsw_core_schedule_work(&net_work
->work
);
2414 static int mlxsw_sp_neigh_init(struct mlxsw_sp
*mlxsw_sp
)
2418 err
= rhashtable_init(&mlxsw_sp
->router
->neigh_ht
,
2419 &mlxsw_sp_neigh_ht_params
);
2423 /* Initialize the polling interval according to the default
2426 mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp
);
2428 /* Create the delayed works for the activity_update */
2429 INIT_DELAYED_WORK(&mlxsw_sp
->router
->neighs_update
.dw
,
2430 mlxsw_sp_router_neighs_update_work
);
2431 INIT_DELAYED_WORK(&mlxsw_sp
->router
->nexthop_probe_dw
,
2432 mlxsw_sp_router_probe_unresolved_nexthops
);
2433 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
, 0);
2434 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->nexthop_probe_dw
, 0);
2438 static void mlxsw_sp_neigh_fini(struct mlxsw_sp
*mlxsw_sp
)
2440 cancel_delayed_work_sync(&mlxsw_sp
->router
->neighs_update
.dw
);
2441 cancel_delayed_work_sync(&mlxsw_sp
->router
->nexthop_probe_dw
);
2442 rhashtable_destroy(&mlxsw_sp
->router
->neigh_ht
);
2445 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
2446 struct mlxsw_sp_rif
*rif
)
2448 struct mlxsw_sp_neigh_entry
*neigh_entry
, *tmp
;
2450 list_for_each_entry_safe(neigh_entry
, tmp
, &rif
->neigh_list
,
2452 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, false);
2453 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2457 enum mlxsw_sp_nexthop_type
{
2458 MLXSW_SP_NEXTHOP_TYPE_ETH
,
2459 MLXSW_SP_NEXTHOP_TYPE_IPIP
,
2462 struct mlxsw_sp_nexthop_key
{
2463 struct fib_nh
*fib_nh
;
2466 struct mlxsw_sp_nexthop
{
2467 struct list_head neigh_list_node
; /* member of neigh entry list */
2468 struct list_head rif_list_node
;
2469 struct list_head router_list_node
;
2470 struct mlxsw_sp_nexthop_group
*nh_grp
; /* pointer back to the group
2473 struct rhash_head ht_node
;
2474 struct mlxsw_sp_nexthop_key key
;
2475 unsigned char gw_addr
[sizeof(struct in6_addr
)];
2479 int num_adj_entries
;
2480 struct mlxsw_sp_rif
*rif
;
2481 u8 should_offload
:1, /* set indicates this neigh is connected and
2482 * should be put to KVD linear area of this group.
2484 offloaded
:1, /* set in case the neigh is actually put into
2485 * KVD linear area of this group.
2487 update
:1; /* set indicates that MAC of this neigh should be
2490 enum mlxsw_sp_nexthop_type type
;
2492 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2493 struct mlxsw_sp_ipip_entry
*ipip_entry
;
2495 unsigned int counter_index
;
2499 struct mlxsw_sp_nexthop_group
{
2501 struct rhash_head ht_node
;
2502 struct list_head fib_list
; /* list of fib entries that use this group */
2503 struct neigh_table
*neigh_tbl
;
2504 u8 adj_index_valid
:1,
2505 gateway
:1; /* routes using the group use a gateway */
2509 int sum_norm_weight
;
2510 struct mlxsw_sp_nexthop nexthops
[0];
2511 #define nh_rif nexthops[0].rif
2514 void mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
2515 struct mlxsw_sp_nexthop
*nh
)
2517 struct devlink
*devlink
;
2519 devlink
= priv_to_devlink(mlxsw_sp
->core
);
2520 if (!devlink_dpipe_table_counter_enabled(devlink
,
2521 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
))
2524 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &nh
->counter_index
))
2527 nh
->counter_valid
= true;
2530 void mlxsw_sp_nexthop_counter_free(struct mlxsw_sp
*mlxsw_sp
,
2531 struct mlxsw_sp_nexthop
*nh
)
2533 if (!nh
->counter_valid
)
2535 mlxsw_sp_flow_counter_free(mlxsw_sp
, nh
->counter_index
);
2536 nh
->counter_valid
= false;
2539 int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp
*mlxsw_sp
,
2540 struct mlxsw_sp_nexthop
*nh
, u64
*p_counter
)
2542 if (!nh
->counter_valid
)
2545 return mlxsw_sp_flow_counter_get(mlxsw_sp
, nh
->counter_index
,
2549 struct mlxsw_sp_nexthop
*mlxsw_sp_nexthop_next(struct mlxsw_sp_router
*router
,
2550 struct mlxsw_sp_nexthop
*nh
)
2553 if (list_empty(&router
->nexthop_list
))
2556 return list_first_entry(&router
->nexthop_list
,
2557 typeof(*nh
), router_list_node
);
2559 if (list_is_last(&nh
->router_list_node
, &router
->nexthop_list
))
2561 return list_next_entry(nh
, router_list_node
);
2564 bool mlxsw_sp_nexthop_offload(struct mlxsw_sp_nexthop
*nh
)
2566 return nh
->offloaded
;
2569 unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop
*nh
)
2573 return nh
->neigh_entry
->ha
;
2576 int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop
*nh
, u32
*p_adj_index
,
2577 u32
*p_adj_size
, u32
*p_adj_hash_index
)
2579 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2580 u32 adj_hash_index
= 0;
2583 if (!nh
->offloaded
|| !nh_grp
->adj_index_valid
)
2586 *p_adj_index
= nh_grp
->adj_index
;
2587 *p_adj_size
= nh_grp
->ecmp_size
;
2589 for (i
= 0; i
< nh_grp
->count
; i
++) {
2590 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2594 if (nh_iter
->offloaded
)
2595 adj_hash_index
+= nh_iter
->num_adj_entries
;
2598 *p_adj_hash_index
= adj_hash_index
;
2602 struct mlxsw_sp_rif
*mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop
*nh
)
2607 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop
*nh
)
2609 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2612 for (i
= 0; i
< nh_grp
->count
; i
++) {
2613 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2615 if (nh_iter
->type
== MLXSW_SP_NEXTHOP_TYPE_IPIP
)
2621 static struct fib_info
*
2622 mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2624 return nh_grp
->priv
;
2627 struct mlxsw_sp_nexthop_group_cmp_arg
{
2628 enum mlxsw_sp_l3proto proto
;
2630 struct fib_info
*fi
;
2631 struct mlxsw_sp_fib6_entry
*fib6_entry
;
2636 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2637 const struct in6_addr
*gw
, int ifindex
)
2641 for (i
= 0; i
< nh_grp
->count
; i
++) {
2642 const struct mlxsw_sp_nexthop
*nh
;
2644 nh
= &nh_grp
->nexthops
[i
];
2645 if (nh
->ifindex
== ifindex
&&
2646 ipv6_addr_equal(gw
, (struct in6_addr
*) nh
->gw_addr
))
2654 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2655 const struct mlxsw_sp_fib6_entry
*fib6_entry
)
2657 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2659 if (nh_grp
->count
!= fib6_entry
->nrt6
)
2662 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2663 struct in6_addr
*gw
;
2666 ifindex
= mlxsw_sp_rt6
->rt
->dst
.dev
->ifindex
;
2667 gw
= &mlxsw_sp_rt6
->rt
->rt6i_gateway
;
2668 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp
, gw
, ifindex
))
2676 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg
*arg
, const void *ptr
)
2678 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= arg
->key
;
2679 const struct mlxsw_sp_nexthop_group
*nh_grp
= ptr
;
2681 switch (cmp_arg
->proto
) {
2682 case MLXSW_SP_L3_PROTO_IPV4
:
2683 return cmp_arg
->fi
!= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2684 case MLXSW_SP_L3_PROTO_IPV6
:
2685 return !mlxsw_sp_nexthop6_group_cmp(nh_grp
,
2686 cmp_arg
->fib6_entry
);
2694 mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2696 return nh_grp
->neigh_tbl
->family
;
2699 static u32
mlxsw_sp_nexthop_group_hash_obj(const void *data
, u32 len
, u32 seed
)
2701 const struct mlxsw_sp_nexthop_group
*nh_grp
= data
;
2702 const struct mlxsw_sp_nexthop
*nh
;
2703 struct fib_info
*fi
;
2707 switch (mlxsw_sp_nexthop_group_type(nh_grp
)) {
2709 fi
= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2710 return jhash(&fi
, sizeof(fi
), seed
);
2712 val
= nh_grp
->count
;
2713 for (i
= 0; i
< nh_grp
->count
; i
++) {
2714 nh
= &nh_grp
->nexthops
[i
];
2717 return jhash(&val
, sizeof(val
), seed
);
2725 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry
*fib6_entry
, u32 seed
)
2727 unsigned int val
= fib6_entry
->nrt6
;
2728 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2729 struct net_device
*dev
;
2731 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2732 dev
= mlxsw_sp_rt6
->rt
->dst
.dev
;
2733 val
^= dev
->ifindex
;
2736 return jhash(&val
, sizeof(val
), seed
);
2740 mlxsw_sp_nexthop_group_hash(const void *data
, u32 len
, u32 seed
)
2742 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= data
;
2744 switch (cmp_arg
->proto
) {
2745 case MLXSW_SP_L3_PROTO_IPV4
:
2746 return jhash(&cmp_arg
->fi
, sizeof(cmp_arg
->fi
), seed
);
2747 case MLXSW_SP_L3_PROTO_IPV6
:
2748 return mlxsw_sp_nexthop6_group_hash(cmp_arg
->fib6_entry
, seed
);
2755 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params
= {
2756 .head_offset
= offsetof(struct mlxsw_sp_nexthop_group
, ht_node
),
2757 .hashfn
= mlxsw_sp_nexthop_group_hash
,
2758 .obj_hashfn
= mlxsw_sp_nexthop_group_hash_obj
,
2759 .obj_cmpfn
= mlxsw_sp_nexthop_group_cmp
,
2762 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp
*mlxsw_sp
,
2763 struct mlxsw_sp_nexthop_group
*nh_grp
)
2765 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
2769 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2771 mlxsw_sp_nexthop_group_ht_params
);
2774 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp
*mlxsw_sp
,
2775 struct mlxsw_sp_nexthop_group
*nh_grp
)
2777 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
2781 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2783 mlxsw_sp_nexthop_group_ht_params
);
2786 static struct mlxsw_sp_nexthop_group
*
2787 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
2788 struct fib_info
*fi
)
2790 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
2792 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV4
;
2794 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2796 mlxsw_sp_nexthop_group_ht_params
);
2799 static struct mlxsw_sp_nexthop_group
*
2800 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
2801 struct mlxsw_sp_fib6_entry
*fib6_entry
)
2803 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
2805 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV6
;
2806 cmp_arg
.fib6_entry
= fib6_entry
;
2807 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
2809 mlxsw_sp_nexthop_group_ht_params
);
2812 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params
= {
2813 .key_offset
= offsetof(struct mlxsw_sp_nexthop
, key
),
2814 .head_offset
= offsetof(struct mlxsw_sp_nexthop
, ht_node
),
2815 .key_len
= sizeof(struct mlxsw_sp_nexthop_key
),
2818 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp
*mlxsw_sp
,
2819 struct mlxsw_sp_nexthop
*nh
)
2821 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_ht
,
2822 &nh
->ht_node
, mlxsw_sp_nexthop_ht_params
);
2825 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp
*mlxsw_sp
,
2826 struct mlxsw_sp_nexthop
*nh
)
2828 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_ht
, &nh
->ht_node
,
2829 mlxsw_sp_nexthop_ht_params
);
2832 static struct mlxsw_sp_nexthop
*
2833 mlxsw_sp_nexthop_lookup(struct mlxsw_sp
*mlxsw_sp
,
2834 struct mlxsw_sp_nexthop_key key
)
2836 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_ht
, &key
,
2837 mlxsw_sp_nexthop_ht_params
);
2840 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp
*mlxsw_sp
,
2841 const struct mlxsw_sp_fib
*fib
,
2842 u32 adj_index
, u16 ecmp_size
,
2846 char raleu_pl
[MLXSW_REG_RALEU_LEN
];
2848 mlxsw_reg_raleu_pack(raleu_pl
,
2849 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
,
2850 fib
->vr
->id
, adj_index
, ecmp_size
, new_adj_index
,
2852 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raleu
), raleu_pl
);
2855 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp
*mlxsw_sp
,
2856 struct mlxsw_sp_nexthop_group
*nh_grp
,
2857 u32 old_adj_index
, u16 old_ecmp_size
)
2859 struct mlxsw_sp_fib_entry
*fib_entry
;
2860 struct mlxsw_sp_fib
*fib
= NULL
;
2863 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2864 if (fib
== fib_entry
->fib_node
->fib
)
2866 fib
= fib_entry
->fib_node
->fib
;
2867 err
= mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp
, fib
,
2878 static int __mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
2879 struct mlxsw_sp_nexthop
*nh
)
2881 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
2882 char ratr_pl
[MLXSW_REG_RATR_LEN
];
2884 mlxsw_reg_ratr_pack(ratr_pl
, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY
,
2885 true, MLXSW_REG_RATR_TYPE_ETHERNET
,
2886 adj_index
, neigh_entry
->rif
);
2887 mlxsw_reg_ratr_eth_entry_pack(ratr_pl
, neigh_entry
->ha
);
2888 if (nh
->counter_valid
)
2889 mlxsw_reg_ratr_counter_pack(ratr_pl
, nh
->counter_index
, true);
2891 mlxsw_reg_ratr_counter_pack(ratr_pl
, 0, false);
2893 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ratr
), ratr_pl
);
2896 int mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
2897 struct mlxsw_sp_nexthop
*nh
)
2901 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
2904 err
= __mlxsw_sp_nexthop_update(mlxsw_sp
, adj_index
+ i
, nh
);
2912 static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
2914 struct mlxsw_sp_nexthop
*nh
)
2916 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
2918 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[nh
->ipip_entry
->ipipt
];
2919 return ipip_ops
->nexthop_update(mlxsw_sp
, adj_index
, nh
->ipip_entry
);
2922 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
2924 struct mlxsw_sp_nexthop
*nh
)
2928 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
2931 err
= __mlxsw_sp_nexthop_ipip_update(mlxsw_sp
, adj_index
+ i
,
2941 mlxsw_sp_nexthop_group_update(struct mlxsw_sp
*mlxsw_sp
,
2942 struct mlxsw_sp_nexthop_group
*nh_grp
,
2945 u32 adj_index
= nh_grp
->adj_index
; /* base */
2946 struct mlxsw_sp_nexthop
*nh
;
2950 for (i
= 0; i
< nh_grp
->count
; i
++) {
2951 nh
= &nh_grp
->nexthops
[i
];
2953 if (!nh
->should_offload
) {
2958 if (nh
->update
|| reallocate
) {
2960 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
2961 err
= mlxsw_sp_nexthop_update
2962 (mlxsw_sp
, adj_index
, nh
);
2964 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
2965 err
= mlxsw_sp_nexthop_ipip_update
2966 (mlxsw_sp
, adj_index
, nh
);
2974 adj_index
+= nh
->num_adj_entries
;
2980 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
2981 const struct mlxsw_sp_fib_entry
*fib_entry
);
2984 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp
*mlxsw_sp
,
2985 struct mlxsw_sp_nexthop_group
*nh_grp
)
2987 struct mlxsw_sp_fib_entry
*fib_entry
;
2990 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
2991 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
2994 err
= mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
3002 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
3003 enum mlxsw_reg_ralue_op op
, int err
);
3006 mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group
*nh_grp
)
3008 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_WRITE
;
3009 struct mlxsw_sp_fib_entry
*fib_entry
;
3011 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
3012 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
3015 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
3019 static void mlxsw_sp_adj_grp_size_round_up(u16
*p_adj_grp_size
)
3021 /* Valid sizes for an adjacency group are:
3022 * 1-64, 512, 1024, 2048 and 4096.
3024 if (*p_adj_grp_size
<= 64)
3026 else if (*p_adj_grp_size
<= 512)
3027 *p_adj_grp_size
= 512;
3028 else if (*p_adj_grp_size
<= 1024)
3029 *p_adj_grp_size
= 1024;
3030 else if (*p_adj_grp_size
<= 2048)
3031 *p_adj_grp_size
= 2048;
3033 *p_adj_grp_size
= 4096;
3036 static void mlxsw_sp_adj_grp_size_round_down(u16
*p_adj_grp_size
,
3037 unsigned int alloc_size
)
3039 if (alloc_size
>= 4096)
3040 *p_adj_grp_size
= 4096;
3041 else if (alloc_size
>= 2048)
3042 *p_adj_grp_size
= 2048;
3043 else if (alloc_size
>= 1024)
3044 *p_adj_grp_size
= 1024;
3045 else if (alloc_size
>= 512)
3046 *p_adj_grp_size
= 512;
3049 static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp
*mlxsw_sp
,
3050 u16
*p_adj_grp_size
)
3052 unsigned int alloc_size
;
3055 /* Round up the requested group size to the next size supported
3056 * by the device and make sure the request can be satisfied.
3058 mlxsw_sp_adj_grp_size_round_up(p_adj_grp_size
);
3059 err
= mlxsw_sp_kvdl_alloc_size_query(mlxsw_sp
, *p_adj_grp_size
,
3063 /* It is possible the allocation results in more allocated
3064 * entries than requested. Try to use as much of them as
3067 mlxsw_sp_adj_grp_size_round_down(p_adj_grp_size
, alloc_size
);
3073 mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group
*nh_grp
)
3075 int i
, g
= 0, sum_norm_weight
= 0;
3076 struct mlxsw_sp_nexthop
*nh
;
3078 for (i
= 0; i
< nh_grp
->count
; i
++) {
3079 nh
= &nh_grp
->nexthops
[i
];
3081 if (!nh
->should_offload
)
3084 g
= gcd(nh
->nh_weight
, g
);
3089 for (i
= 0; i
< nh_grp
->count
; i
++) {
3090 nh
= &nh_grp
->nexthops
[i
];
3092 if (!nh
->should_offload
)
3094 nh
->norm_nh_weight
= nh
->nh_weight
/ g
;
3095 sum_norm_weight
+= nh
->norm_nh_weight
;
3098 nh_grp
->sum_norm_weight
= sum_norm_weight
;
3102 mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group
*nh_grp
)
3104 int total
= nh_grp
->sum_norm_weight
;
3105 u16 ecmp_size
= nh_grp
->ecmp_size
;
3106 int i
, weight
= 0, lower_bound
= 0;
3108 for (i
= 0; i
< nh_grp
->count
; i
++) {
3109 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3112 if (!nh
->should_offload
)
3114 weight
+= nh
->norm_nh_weight
;
3115 upper_bound
= DIV_ROUND_CLOSEST(ecmp_size
* weight
, total
);
3116 nh
->num_adj_entries
= upper_bound
- lower_bound
;
3117 lower_bound
= upper_bound
;
3122 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp
*mlxsw_sp
,
3123 struct mlxsw_sp_nexthop_group
*nh_grp
)
3125 u16 ecmp_size
, old_ecmp_size
;
3126 struct mlxsw_sp_nexthop
*nh
;
3127 bool offload_change
= false;
3129 bool old_adj_index_valid
;
3134 if (!nh_grp
->gateway
) {
3135 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3139 for (i
= 0; i
< nh_grp
->count
; i
++) {
3140 nh
= &nh_grp
->nexthops
[i
];
3142 if (nh
->should_offload
!= nh
->offloaded
) {
3143 offload_change
= true;
3144 if (nh
->should_offload
)
3148 if (!offload_change
) {
3149 /* Nothing was added or removed, so no need to reallocate. Just
3150 * update MAC on existing adjacency indexes.
3152 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, false);
3154 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3159 mlxsw_sp_nexthop_group_normalize(nh_grp
);
3160 if (!nh_grp
->sum_norm_weight
)
3161 /* No neigh of this group is connected so we just set
3162 * the trap and let everthing flow through kernel.
3166 ecmp_size
= nh_grp
->sum_norm_weight
;
3167 err
= mlxsw_sp_fix_adj_grp_size(mlxsw_sp
, &ecmp_size
);
3169 /* No valid allocation size available. */
3172 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, ecmp_size
, &adj_index
);
3174 /* We ran out of KVD linear space, just set the
3175 * trap and let everything flow through kernel.
3177 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to allocate KVD linear area for nexthop group.\n");
3180 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3181 old_adj_index
= nh_grp
->adj_index
;
3182 old_ecmp_size
= nh_grp
->ecmp_size
;
3183 nh_grp
->adj_index_valid
= 1;
3184 nh_grp
->adj_index
= adj_index
;
3185 nh_grp
->ecmp_size
= ecmp_size
;
3186 mlxsw_sp_nexthop_group_rebalance(nh_grp
);
3187 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, true);
3189 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3193 if (!old_adj_index_valid
) {
3194 /* The trap was set for fib entries, so we have to call
3195 * fib entry update to unset it and use adjacency index.
3197 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3199 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to add adjacency index to fib entries.\n");
3205 err
= mlxsw_sp_adj_index_mass_update(mlxsw_sp
, nh_grp
,
3206 old_adj_index
, old_ecmp_size
);
3207 mlxsw_sp_kvdl_free(mlxsw_sp
, old_adj_index
);
3209 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to mass-update adjacency index for nexthop group.\n");
3213 /* Offload state within the group changed, so update the flags. */
3214 mlxsw_sp_nexthop_fib_entries_refresh(nh_grp
);
3219 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3220 nh_grp
->adj_index_valid
= 0;
3221 for (i
= 0; i
< nh_grp
->count
; i
++) {
3222 nh
= &nh_grp
->nexthops
[i
];
3225 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3227 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set traps for fib entries.\n");
3228 if (old_adj_index_valid
)
3229 mlxsw_sp_kvdl_free(mlxsw_sp
, nh_grp
->adj_index
);
3232 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop
*nh
,
3236 nh
->should_offload
= 1;
3238 nh
->should_offload
= 0;
3243 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
3244 struct mlxsw_sp_neigh_entry
*neigh_entry
,
3247 struct mlxsw_sp_nexthop
*nh
;
3249 list_for_each_entry(nh
, &neigh_entry
->nexthop_list
,
3251 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3252 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3256 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop
*nh
,
3257 struct mlxsw_sp_rif
*rif
)
3263 list_add(&nh
->rif_list_node
, &rif
->nexthop_list
);
3266 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop
*nh
)
3271 list_del(&nh
->rif_list_node
);
3275 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp
*mlxsw_sp
,
3276 struct mlxsw_sp_nexthop
*nh
)
3278 struct mlxsw_sp_neigh_entry
*neigh_entry
;
3279 struct neighbour
*n
;
3283 if (!nh
->nh_grp
->gateway
|| nh
->neigh_entry
)
3286 /* Take a reference of neigh here ensuring that neigh would
3287 * not be destructed before the nexthop entry is finished.
3288 * The reference is taken either in neigh_lookup() or
3289 * in neigh_create() in case n is not found.
3291 n
= neigh_lookup(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
, nh
->rif
->dev
);
3293 n
= neigh_create(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
,
3297 neigh_event_send(n
, NULL
);
3299 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
3301 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
3302 if (IS_ERR(neigh_entry
)) {
3304 goto err_neigh_entry_create
;
3308 /* If that is the first nexthop connected to that neigh, add to
3309 * nexthop_neighs_list
3311 if (list_empty(&neigh_entry
->nexthop_list
))
3312 list_add_tail(&neigh_entry
->nexthop_neighs_list_node
,
3313 &mlxsw_sp
->router
->nexthop_neighs_list
);
3315 nh
->neigh_entry
= neigh_entry
;
3316 list_add_tail(&nh
->neigh_list_node
, &neigh_entry
->nexthop_list
);
3317 read_lock_bh(&n
->lock
);
3318 nud_state
= n
->nud_state
;
3320 read_unlock_bh(&n
->lock
);
3321 __mlxsw_sp_nexthop_neigh_update(nh
, !(nud_state
& NUD_VALID
&& !dead
));
3325 err_neigh_entry_create
:
3330 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp
*mlxsw_sp
,
3331 struct mlxsw_sp_nexthop
*nh
)
3333 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
3334 struct neighbour
*n
;
3338 n
= neigh_entry
->key
.n
;
3340 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3341 list_del(&nh
->neigh_list_node
);
3342 nh
->neigh_entry
= NULL
;
3344 /* If that is the last nexthop connected to that neigh, remove from
3345 * nexthop_neighs_list
3347 if (list_empty(&neigh_entry
->nexthop_list
))
3348 list_del(&neigh_entry
->nexthop_neighs_list_node
);
3350 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
3351 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
3356 static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device
*ol_dev
)
3358 struct net_device
*ul_dev
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
3360 return ul_dev
? (ul_dev
->flags
& IFF_UP
) : true;
3363 static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp
*mlxsw_sp
,
3364 struct mlxsw_sp_nexthop
*nh
,
3365 struct mlxsw_sp_ipip_entry
*ipip_entry
)
3369 if (!nh
->nh_grp
->gateway
|| nh
->ipip_entry
)
3372 nh
->ipip_entry
= ipip_entry
;
3373 removing
= !mlxsw_sp_ipip_netdev_ul_up(ipip_entry
->ol_dev
);
3374 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3375 mlxsw_sp_nexthop_rif_init(nh
, &ipip_entry
->ol_lb
->common
);
3378 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp
*mlxsw_sp
,
3379 struct mlxsw_sp_nexthop
*nh
)
3381 struct mlxsw_sp_ipip_entry
*ipip_entry
= nh
->ipip_entry
;
3386 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3387 nh
->ipip_entry
= NULL
;
3390 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
3391 const struct fib_nh
*fib_nh
,
3392 enum mlxsw_sp_ipip_type
*p_ipipt
)
3394 struct net_device
*dev
= fib_nh
->nh_dev
;
3397 fib_nh
->nh_parent
->fib_type
== RTN_UNICAST
&&
3398 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, p_ipipt
);
3401 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3402 struct mlxsw_sp_nexthop
*nh
)
3405 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3406 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp
, nh
);
3407 mlxsw_sp_nexthop_rif_fini(nh
);
3409 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3410 mlxsw_sp_nexthop_rif_fini(nh
);
3411 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp
, nh
);
3416 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp
*mlxsw_sp
,
3417 struct mlxsw_sp_nexthop
*nh
,
3418 struct fib_nh
*fib_nh
)
3420 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3421 struct net_device
*dev
= fib_nh
->nh_dev
;
3422 struct mlxsw_sp_ipip_entry
*ipip_entry
;
3423 struct mlxsw_sp_rif
*rif
;
3426 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, dev
);
3428 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
3429 if (ipip_ops
->can_offload(mlxsw_sp
, dev
,
3430 MLXSW_SP_L3_PROTO_IPV4
)) {
3431 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
3432 mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, ipip_entry
);
3437 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
3438 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
3442 mlxsw_sp_nexthop_rif_init(nh
, rif
);
3443 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
3445 goto err_neigh_init
;
3450 mlxsw_sp_nexthop_rif_fini(nh
);
3454 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3455 struct mlxsw_sp_nexthop
*nh
)
3457 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3460 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp
*mlxsw_sp
,
3461 struct mlxsw_sp_nexthop_group
*nh_grp
,
3462 struct mlxsw_sp_nexthop
*nh
,
3463 struct fib_nh
*fib_nh
)
3465 struct net_device
*dev
= fib_nh
->nh_dev
;
3466 struct in_device
*in_dev
;
3469 nh
->nh_grp
= nh_grp
;
3470 nh
->key
.fib_nh
= fib_nh
;
3471 #ifdef CONFIG_IP_ROUTE_MULTIPATH
3472 nh
->nh_weight
= fib_nh
->nh_weight
;
3476 memcpy(&nh
->gw_addr
, &fib_nh
->nh_gw
, sizeof(fib_nh
->nh_gw
));
3477 err
= mlxsw_sp_nexthop_insert(mlxsw_sp
, nh
);
3481 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
3482 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
3487 in_dev
= __in_dev_get_rtnl(dev
);
3488 if (in_dev
&& IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev
) &&
3489 fib_nh
->nh_flags
& RTNH_F_LINKDOWN
)
3492 err
= mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3494 goto err_nexthop_neigh_init
;
3498 err_nexthop_neigh_init
:
3499 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3503 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp
*mlxsw_sp
,
3504 struct mlxsw_sp_nexthop
*nh
)
3506 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3507 list_del(&nh
->router_list_node
);
3508 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
3509 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3512 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp
*mlxsw_sp
,
3513 unsigned long event
, struct fib_nh
*fib_nh
)
3515 struct mlxsw_sp_nexthop_key key
;
3516 struct mlxsw_sp_nexthop
*nh
;
3518 if (mlxsw_sp
->router
->aborted
)
3521 key
.fib_nh
= fib_nh
;
3522 nh
= mlxsw_sp_nexthop_lookup(mlxsw_sp
, key
);
3523 if (WARN_ON_ONCE(!nh
))
3527 case FIB_EVENT_NH_ADD
:
3528 mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3530 case FIB_EVENT_NH_DEL
:
3531 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3535 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3538 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
3539 struct mlxsw_sp_rif
*rif
)
3541 struct mlxsw_sp_nexthop
*nh
;
3544 list_for_each_entry(nh
, &rif
->nexthop_list
, rif_list_node
) {
3546 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3549 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3550 removing
= !mlxsw_sp_ipip_netdev_ul_up(rif
->dev
);
3557 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3558 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3562 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp
*mlxsw_sp
,
3563 struct mlxsw_sp_rif
*old_rif
,
3564 struct mlxsw_sp_rif
*new_rif
)
3566 struct mlxsw_sp_nexthop
*nh
;
3568 list_splice_init(&old_rif
->nexthop_list
, &new_rif
->nexthop_list
);
3569 list_for_each_entry(nh
, &new_rif
->nexthop_list
, rif_list_node
)
3571 mlxsw_sp_nexthop_rif_update(mlxsw_sp
, new_rif
);
3574 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
3575 struct mlxsw_sp_rif
*rif
)
3577 struct mlxsw_sp_nexthop
*nh
, *tmp
;
3579 list_for_each_entry_safe(nh
, tmp
, &rif
->nexthop_list
, rif_list_node
) {
3580 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3581 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3585 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
3586 const struct fib_info
*fi
)
3588 return fi
->fib_nh
->nh_scope
== RT_SCOPE_LINK
||
3589 mlxsw_sp_nexthop4_ipip_type(mlxsw_sp
, fi
->fib_nh
, NULL
);
3592 static struct mlxsw_sp_nexthop_group
*
3593 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp
*mlxsw_sp
, struct fib_info
*fi
)
3595 struct mlxsw_sp_nexthop_group
*nh_grp
;
3596 struct mlxsw_sp_nexthop
*nh
;
3597 struct fib_nh
*fib_nh
;
3602 alloc_size
= sizeof(*nh_grp
) +
3603 fi
->fib_nhs
* sizeof(struct mlxsw_sp_nexthop
);
3604 nh_grp
= kzalloc(alloc_size
, GFP_KERNEL
);
3606 return ERR_PTR(-ENOMEM
);
3608 INIT_LIST_HEAD(&nh_grp
->fib_list
);
3609 nh_grp
->neigh_tbl
= &arp_tbl
;
3611 nh_grp
->gateway
= mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
);
3612 nh_grp
->count
= fi
->fib_nhs
;
3614 for (i
= 0; i
< nh_grp
->count
; i
++) {
3615 nh
= &nh_grp
->nexthops
[i
];
3616 fib_nh
= &fi
->fib_nh
[i
];
3617 err
= mlxsw_sp_nexthop4_init(mlxsw_sp
, nh_grp
, nh
, fib_nh
);
3619 goto err_nexthop4_init
;
3621 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
3623 goto err_nexthop_group_insert
;
3624 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3627 err_nexthop_group_insert
:
3629 for (i
--; i
>= 0; i
--) {
3630 nh
= &nh_grp
->nexthops
[i
];
3631 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3635 return ERR_PTR(err
);
3639 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
3640 struct mlxsw_sp_nexthop_group
*nh_grp
)
3642 struct mlxsw_sp_nexthop
*nh
;
3645 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
3646 for (i
= 0; i
< nh_grp
->count
; i
++) {
3647 nh
= &nh_grp
->nexthops
[i
];
3648 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3650 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3651 WARN_ON_ONCE(nh_grp
->adj_index_valid
);
3652 fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp
));
3656 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp
*mlxsw_sp
,
3657 struct mlxsw_sp_fib_entry
*fib_entry
,
3658 struct fib_info
*fi
)
3660 struct mlxsw_sp_nexthop_group
*nh_grp
;
3662 nh_grp
= mlxsw_sp_nexthop4_group_lookup(mlxsw_sp
, fi
);
3664 nh_grp
= mlxsw_sp_nexthop4_group_create(mlxsw_sp
, fi
);
3666 return PTR_ERR(nh_grp
);
3668 list_add_tail(&fib_entry
->nexthop_group_node
, &nh_grp
->fib_list
);
3669 fib_entry
->nh_group
= nh_grp
;
3673 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp
*mlxsw_sp
,
3674 struct mlxsw_sp_fib_entry
*fib_entry
)
3676 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3678 list_del(&fib_entry
->nexthop_group_node
);
3679 if (!list_empty(&nh_grp
->fib_list
))
3681 mlxsw_sp_nexthop4_group_destroy(mlxsw_sp
, nh_grp
);
3685 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
3687 struct mlxsw_sp_fib4_entry
*fib4_entry
;
3689 fib4_entry
= container_of(fib_entry
, struct mlxsw_sp_fib4_entry
,
3691 return !fib4_entry
->tos
;
3695 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
3697 struct mlxsw_sp_nexthop_group
*nh_group
= fib_entry
->nh_group
;
3699 switch (fib_entry
->fib_node
->fib
->proto
) {
3700 case MLXSW_SP_L3_PROTO_IPV4
:
3701 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry
))
3704 case MLXSW_SP_L3_PROTO_IPV6
:
3708 switch (fib_entry
->type
) {
3709 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
3710 return !!nh_group
->adj_index_valid
;
3711 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
3712 return !!nh_group
->nh_rif
;
3713 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
3720 static struct mlxsw_sp_nexthop
*
3721 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group
*nh_grp
,
3722 const struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
3726 for (i
= 0; i
< nh_grp
->count
; i
++) {
3727 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3728 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
3730 if (nh
->rif
&& nh
->rif
->dev
== rt
->dst
.dev
&&
3731 ipv6_addr_equal((const struct in6_addr
*) &nh
->gw_addr
,
3741 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3743 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3746 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
||
3747 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
) {
3748 nh_grp
->nexthops
->key
.fib_nh
->nh_flags
|= RTNH_F_OFFLOAD
;
3752 for (i
= 0; i
< nh_grp
->count
; i
++) {
3753 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3756 nh
->key
.fib_nh
->nh_flags
|= RTNH_F_OFFLOAD
;
3758 nh
->key
.fib_nh
->nh_flags
&= ~RTNH_F_OFFLOAD
;
3763 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3765 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3768 if (!list_is_singular(&nh_grp
->fib_list
))
3771 for (i
= 0; i
< nh_grp
->count
; i
++) {
3772 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3774 nh
->key
.fib_nh
->nh_flags
&= ~RTNH_F_OFFLOAD
;
3779 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3781 struct mlxsw_sp_fib6_entry
*fib6_entry
;
3782 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
3784 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
3787 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
) {
3788 list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
3789 list
)->rt
->rt6i_nh_flags
|= RTNH_F_OFFLOAD
;
3793 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
3794 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
3795 struct mlxsw_sp_nexthop
*nh
;
3797 nh
= mlxsw_sp_rt6_nexthop(nh_grp
, mlxsw_sp_rt6
);
3798 if (nh
&& nh
->offloaded
)
3799 mlxsw_sp_rt6
->rt
->rt6i_nh_flags
|= RTNH_F_OFFLOAD
;
3801 mlxsw_sp_rt6
->rt
->rt6i_nh_flags
&= ~RTNH_F_OFFLOAD
;
3806 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3808 struct mlxsw_sp_fib6_entry
*fib6_entry
;
3809 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
3811 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
3813 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
3814 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
3816 rt
->rt6i_nh_flags
&= ~RTNH_F_OFFLOAD
;
3820 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
3822 switch (fib_entry
->fib_node
->fib
->proto
) {
3823 case MLXSW_SP_L3_PROTO_IPV4
:
3824 mlxsw_sp_fib4_entry_offload_set(fib_entry
);
3826 case MLXSW_SP_L3_PROTO_IPV6
:
3827 mlxsw_sp_fib6_entry_offload_set(fib_entry
);
3833 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
3835 switch (fib_entry
->fib_node
->fib
->proto
) {
3836 case MLXSW_SP_L3_PROTO_IPV4
:
3837 mlxsw_sp_fib4_entry_offload_unset(fib_entry
);
3839 case MLXSW_SP_L3_PROTO_IPV6
:
3840 mlxsw_sp_fib6_entry_offload_unset(fib_entry
);
3846 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
3847 enum mlxsw_reg_ralue_op op
, int err
)
3850 case MLXSW_REG_RALUE_OP_WRITE_DELETE
:
3851 return mlxsw_sp_fib_entry_offload_unset(fib_entry
);
3852 case MLXSW_REG_RALUE_OP_WRITE_WRITE
:
3855 if (mlxsw_sp_fib_entry_should_offload(fib_entry
))
3856 mlxsw_sp_fib_entry_offload_set(fib_entry
);
3858 mlxsw_sp_fib_entry_offload_unset(fib_entry
);
3866 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl
,
3867 const struct mlxsw_sp_fib_entry
*fib_entry
,
3868 enum mlxsw_reg_ralue_op op
)
3870 struct mlxsw_sp_fib
*fib
= fib_entry
->fib_node
->fib
;
3871 enum mlxsw_reg_ralxx_protocol proto
;
3874 proto
= (enum mlxsw_reg_ralxx_protocol
) fib
->proto
;
3876 switch (fib
->proto
) {
3877 case MLXSW_SP_L3_PROTO_IPV4
:
3878 p_dip
= (u32
*) fib_entry
->fib_node
->key
.addr
;
3879 mlxsw_reg_ralue_pack4(ralue_pl
, proto
, op
, fib
->vr
->id
,
3880 fib_entry
->fib_node
->key
.prefix_len
,
3883 case MLXSW_SP_L3_PROTO_IPV6
:
3884 mlxsw_reg_ralue_pack6(ralue_pl
, proto
, op
, fib
->vr
->id
,
3885 fib_entry
->fib_node
->key
.prefix_len
,
3886 fib_entry
->fib_node
->key
.addr
);
3891 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp
*mlxsw_sp
,
3892 struct mlxsw_sp_fib_entry
*fib_entry
,
3893 enum mlxsw_reg_ralue_op op
)
3895 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3896 enum mlxsw_reg_ralue_trap_action trap_action
;
3898 u32 adjacency_index
= 0;
3901 /* In case the nexthop group adjacency index is valid, use it
3902 * with provided ECMP size. Otherwise, setup trap and pass
3903 * traffic to kernel.
3905 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
3906 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
3907 adjacency_index
= fib_entry
->nh_group
->adj_index
;
3908 ecmp_size
= fib_entry
->nh_group
->ecmp_size
;
3910 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
3911 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
3914 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3915 mlxsw_reg_ralue_act_remote_pack(ralue_pl
, trap_action
, trap_id
,
3916 adjacency_index
, ecmp_size
);
3917 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3920 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp
*mlxsw_sp
,
3921 struct mlxsw_sp_fib_entry
*fib_entry
,
3922 enum mlxsw_reg_ralue_op op
)
3924 struct mlxsw_sp_rif
*rif
= fib_entry
->nh_group
->nh_rif
;
3925 enum mlxsw_reg_ralue_trap_action trap_action
;
3926 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3930 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
3931 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
3932 rif_index
= rif
->rif_index
;
3934 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
3935 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
3938 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3939 mlxsw_reg_ralue_act_local_pack(ralue_pl
, trap_action
, trap_id
,
3941 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3944 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp
*mlxsw_sp
,
3945 struct mlxsw_sp_fib_entry
*fib_entry
,
3946 enum mlxsw_reg_ralue_op op
)
3948 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
3950 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
3951 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
3952 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
3956 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp
*mlxsw_sp
,
3957 struct mlxsw_sp_fib_entry
*fib_entry
,
3958 enum mlxsw_reg_ralue_op op
)
3960 struct mlxsw_sp_ipip_entry
*ipip_entry
= fib_entry
->decap
.ipip_entry
;
3961 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3963 if (WARN_ON(!ipip_entry
))
3966 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
3967 return ipip_ops
->fib_entry_op(mlxsw_sp
, ipip_entry
, op
,
3968 fib_entry
->decap
.tunnel_index
);
3971 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
3972 struct mlxsw_sp_fib_entry
*fib_entry
,
3973 enum mlxsw_reg_ralue_op op
)
3975 switch (fib_entry
->type
) {
3976 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
3977 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp
, fib_entry
, op
);
3978 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
3979 return mlxsw_sp_fib_entry_op_local(mlxsw_sp
, fib_entry
, op
);
3980 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP
:
3981 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp
, fib_entry
, op
);
3982 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
3983 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp
,
3989 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
3990 struct mlxsw_sp_fib_entry
*fib_entry
,
3991 enum mlxsw_reg_ralue_op op
)
3993 int err
= __mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
, op
);
3995 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, err
);
4000 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
4001 struct mlxsw_sp_fib_entry
*fib_entry
)
4003 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
4004 MLXSW_REG_RALUE_OP_WRITE_WRITE
);
4007 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4008 struct mlxsw_sp_fib_entry
*fib_entry
)
4010 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
4011 MLXSW_REG_RALUE_OP_WRITE_DELETE
);
4015 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
4016 const struct fib_entry_notifier_info
*fen_info
,
4017 struct mlxsw_sp_fib_entry
*fib_entry
)
4019 union mlxsw_sp_l3addr dip
= { .addr4
= htonl(fen_info
->dst
) };
4020 struct net_device
*dev
= fen_info
->fi
->fib_dev
;
4021 struct mlxsw_sp_ipip_entry
*ipip_entry
;
4022 struct fib_info
*fi
= fen_info
->fi
;
4024 switch (fen_info
->type
) {
4026 ipip_entry
= mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp
, dev
,
4027 MLXSW_SP_L3_PROTO_IPV4
, dip
);
4028 if (ipip_entry
&& ipip_entry
->ol_dev
->flags
& IFF_UP
) {
4029 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
4030 return mlxsw_sp_fib_entry_decap_init(mlxsw_sp
,
4036 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4038 case RTN_UNREACHABLE
: /* fall through */
4039 case RTN_BLACKHOLE
: /* fall through */
4041 /* Packets hitting these routes need to be trapped, but
4042 * can do so with a lower priority than packets directed
4043 * at the host, so use action type local instead of trap.
4045 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4048 if (mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
))
4049 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4051 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4058 static struct mlxsw_sp_fib4_entry
*
4059 mlxsw_sp_fib4_entry_create(struct mlxsw_sp
*mlxsw_sp
,
4060 struct mlxsw_sp_fib_node
*fib_node
,
4061 const struct fib_entry_notifier_info
*fen_info
)
4063 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4064 struct mlxsw_sp_fib_entry
*fib_entry
;
4067 fib4_entry
= kzalloc(sizeof(*fib4_entry
), GFP_KERNEL
);
4069 return ERR_PTR(-ENOMEM
);
4070 fib_entry
= &fib4_entry
->common
;
4072 err
= mlxsw_sp_fib4_entry_type_set(mlxsw_sp
, fen_info
, fib_entry
);
4074 goto err_fib4_entry_type_set
;
4076 err
= mlxsw_sp_nexthop4_group_get(mlxsw_sp
, fib_entry
, fen_info
->fi
);
4078 goto err_nexthop4_group_get
;
4080 fib4_entry
->prio
= fen_info
->fi
->fib_priority
;
4081 fib4_entry
->tb_id
= fen_info
->tb_id
;
4082 fib4_entry
->type
= fen_info
->type
;
4083 fib4_entry
->tos
= fen_info
->tos
;
4085 fib_entry
->fib_node
= fib_node
;
4089 err_nexthop4_group_get
:
4090 err_fib4_entry_type_set
:
4092 return ERR_PTR(err
);
4095 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
4096 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4098 mlxsw_sp_nexthop4_group_put(mlxsw_sp
, &fib4_entry
->common
);
4102 static struct mlxsw_sp_fib4_entry
*
4103 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
4104 const struct fib_entry_notifier_info
*fen_info
)
4106 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4107 struct mlxsw_sp_fib_node
*fib_node
;
4108 struct mlxsw_sp_fib
*fib
;
4109 struct mlxsw_sp_vr
*vr
;
4111 vr
= mlxsw_sp_vr_find(mlxsw_sp
, fen_info
->tb_id
);
4114 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV4
);
4116 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &fen_info
->dst
,
4117 sizeof(fen_info
->dst
),
4122 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4123 if (fib4_entry
->tb_id
== fen_info
->tb_id
&&
4124 fib4_entry
->tos
== fen_info
->tos
&&
4125 fib4_entry
->type
== fen_info
->type
&&
4126 mlxsw_sp_nexthop4_group_fi(fib4_entry
->common
.nh_group
) ==
4135 static const struct rhashtable_params mlxsw_sp_fib_ht_params
= {
4136 .key_offset
= offsetof(struct mlxsw_sp_fib_node
, key
),
4137 .head_offset
= offsetof(struct mlxsw_sp_fib_node
, ht_node
),
4138 .key_len
= sizeof(struct mlxsw_sp_fib_key
),
4139 .automatic_shrinking
= true,
4142 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib
*fib
,
4143 struct mlxsw_sp_fib_node
*fib_node
)
4145 return rhashtable_insert_fast(&fib
->ht
, &fib_node
->ht_node
,
4146 mlxsw_sp_fib_ht_params
);
4149 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib
*fib
,
4150 struct mlxsw_sp_fib_node
*fib_node
)
4152 rhashtable_remove_fast(&fib
->ht
, &fib_node
->ht_node
,
4153 mlxsw_sp_fib_ht_params
);
4156 static struct mlxsw_sp_fib_node
*
4157 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
4158 size_t addr_len
, unsigned char prefix_len
)
4160 struct mlxsw_sp_fib_key key
;
4162 memset(&key
, 0, sizeof(key
));
4163 memcpy(key
.addr
, addr
, addr_len
);
4164 key
.prefix_len
= prefix_len
;
4165 return rhashtable_lookup_fast(&fib
->ht
, &key
, mlxsw_sp_fib_ht_params
);
4168 static struct mlxsw_sp_fib_node
*
4169 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib
*fib
, const void *addr
,
4170 size_t addr_len
, unsigned char prefix_len
)
4172 struct mlxsw_sp_fib_node
*fib_node
;
4174 fib_node
= kzalloc(sizeof(*fib_node
), GFP_KERNEL
);
4178 INIT_LIST_HEAD(&fib_node
->entry_list
);
4179 list_add(&fib_node
->list
, &fib
->node_list
);
4180 memcpy(fib_node
->key
.addr
, addr
, addr_len
);
4181 fib_node
->key
.prefix_len
= prefix_len
;
4186 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node
*fib_node
)
4188 list_del(&fib_node
->list
);
4189 WARN_ON(!list_empty(&fib_node
->entry_list
));
4194 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
4195 const struct mlxsw_sp_fib_entry
*fib_entry
)
4197 return list_first_entry(&fib_node
->entry_list
,
4198 struct mlxsw_sp_fib_entry
, list
) == fib_entry
;
4201 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp
*mlxsw_sp
,
4202 struct mlxsw_sp_fib
*fib
,
4203 struct mlxsw_sp_fib_node
*fib_node
)
4205 struct mlxsw_sp_prefix_usage req_prefix_usage
= {{ 0 } };
4206 struct mlxsw_sp_lpm_tree
*lpm_tree
;
4209 /* Since the tree is shared between all virtual routers we must
4210 * make sure it contains all the required prefix lengths. This
4211 * can be computed by either adding the new prefix length to the
4212 * existing prefix usage of a bound tree, or by aggregating the
4213 * prefix lengths across all virtual routers and adding the new
4217 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage
,
4218 &fib
->lpm_tree
->prefix_usage
);
4220 mlxsw_sp_vrs_prefixes(mlxsw_sp
, fib
->proto
, &req_prefix_usage
);
4221 mlxsw_sp_prefix_usage_set(&req_prefix_usage
, fib_node
->key
.prefix_len
);
4223 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
4225 if (IS_ERR(lpm_tree
))
4226 return PTR_ERR(lpm_tree
);
4228 if (fib
->lpm_tree
&& fib
->lpm_tree
->id
== lpm_tree
->id
)
4231 err
= mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp
, fib
, lpm_tree
);
4238 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp
*mlxsw_sp
,
4239 struct mlxsw_sp_fib
*fib
)
4241 if (!mlxsw_sp_prefix_usage_none(&fib
->prefix_usage
))
4243 mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp
, fib
);
4244 mlxsw_sp_lpm_tree_put(mlxsw_sp
, fib
->lpm_tree
);
4245 fib
->lpm_tree
= NULL
;
4248 static void mlxsw_sp_fib_node_prefix_inc(struct mlxsw_sp_fib_node
*fib_node
)
4250 unsigned char prefix_len
= fib_node
->key
.prefix_len
;
4251 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4253 if (fib
->prefix_ref_count
[prefix_len
]++ == 0)
4254 mlxsw_sp_prefix_usage_set(&fib
->prefix_usage
, prefix_len
);
4257 static void mlxsw_sp_fib_node_prefix_dec(struct mlxsw_sp_fib_node
*fib_node
)
4259 unsigned char prefix_len
= fib_node
->key
.prefix_len
;
4260 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4262 if (--fib
->prefix_ref_count
[prefix_len
] == 0)
4263 mlxsw_sp_prefix_usage_clear(&fib
->prefix_usage
, prefix_len
);
4266 static int mlxsw_sp_fib_node_init(struct mlxsw_sp
*mlxsw_sp
,
4267 struct mlxsw_sp_fib_node
*fib_node
,
4268 struct mlxsw_sp_fib
*fib
)
4272 err
= mlxsw_sp_fib_node_insert(fib
, fib_node
);
4275 fib_node
->fib
= fib
;
4277 err
= mlxsw_sp_fib_lpm_tree_link(mlxsw_sp
, fib
, fib_node
);
4279 goto err_fib_lpm_tree_link
;
4281 mlxsw_sp_fib_node_prefix_inc(fib_node
);
4285 err_fib_lpm_tree_link
:
4286 fib_node
->fib
= NULL
;
4287 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4291 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp
*mlxsw_sp
,
4292 struct mlxsw_sp_fib_node
*fib_node
)
4294 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4296 mlxsw_sp_fib_node_prefix_dec(fib_node
);
4297 mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp
, fib
);
4298 fib_node
->fib
= NULL
;
4299 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4302 static struct mlxsw_sp_fib_node
*
4303 mlxsw_sp_fib_node_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
, const void *addr
,
4304 size_t addr_len
, unsigned char prefix_len
,
4305 enum mlxsw_sp_l3proto proto
)
4307 struct mlxsw_sp_fib_node
*fib_node
;
4308 struct mlxsw_sp_fib
*fib
;
4309 struct mlxsw_sp_vr
*vr
;
4312 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
, NULL
);
4314 return ERR_CAST(vr
);
4315 fib
= mlxsw_sp_vr_fib(vr
, proto
);
4317 fib_node
= mlxsw_sp_fib_node_lookup(fib
, addr
, addr_len
, prefix_len
);
4321 fib_node
= mlxsw_sp_fib_node_create(fib
, addr
, addr_len
, prefix_len
);
4324 goto err_fib_node_create
;
4327 err
= mlxsw_sp_fib_node_init(mlxsw_sp
, fib_node
, fib
);
4329 goto err_fib_node_init
;
4334 mlxsw_sp_fib_node_destroy(fib_node
);
4335 err_fib_node_create
:
4336 mlxsw_sp_vr_put(vr
);
4337 return ERR_PTR(err
);
4340 static void mlxsw_sp_fib_node_put(struct mlxsw_sp
*mlxsw_sp
,
4341 struct mlxsw_sp_fib_node
*fib_node
)
4343 struct mlxsw_sp_vr
*vr
= fib_node
->fib
->vr
;
4345 if (!list_empty(&fib_node
->entry_list
))
4347 mlxsw_sp_fib_node_fini(mlxsw_sp
, fib_node
);
4348 mlxsw_sp_fib_node_destroy(fib_node
);
4349 mlxsw_sp_vr_put(vr
);
4352 static struct mlxsw_sp_fib4_entry
*
4353 mlxsw_sp_fib4_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
4354 const struct mlxsw_sp_fib4_entry
*new4_entry
)
4356 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4358 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4359 if (fib4_entry
->tb_id
> new4_entry
->tb_id
)
4361 if (fib4_entry
->tb_id
!= new4_entry
->tb_id
)
4363 if (fib4_entry
->tos
> new4_entry
->tos
)
4365 if (fib4_entry
->prio
>= new4_entry
->prio
||
4366 fib4_entry
->tos
< new4_entry
->tos
)
4374 mlxsw_sp_fib4_node_list_append(struct mlxsw_sp_fib4_entry
*fib4_entry
,
4375 struct mlxsw_sp_fib4_entry
*new4_entry
)
4377 struct mlxsw_sp_fib_node
*fib_node
;
4379 if (WARN_ON(!fib4_entry
))
4382 fib_node
= fib4_entry
->common
.fib_node
;
4383 list_for_each_entry_from(fib4_entry
, &fib_node
->entry_list
,
4385 if (fib4_entry
->tb_id
!= new4_entry
->tb_id
||
4386 fib4_entry
->tos
!= new4_entry
->tos
||
4387 fib4_entry
->prio
!= new4_entry
->prio
)
4391 list_add_tail(&new4_entry
->common
.list
, &fib4_entry
->common
.list
);
4396 mlxsw_sp_fib4_node_list_insert(struct mlxsw_sp_fib4_entry
*new4_entry
,
4397 bool replace
, bool append
)
4399 struct mlxsw_sp_fib_node
*fib_node
= new4_entry
->common
.fib_node
;
4400 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4402 fib4_entry
= mlxsw_sp_fib4_node_entry_find(fib_node
, new4_entry
);
4405 return mlxsw_sp_fib4_node_list_append(fib4_entry
, new4_entry
);
4406 if (replace
&& WARN_ON(!fib4_entry
))
4409 /* Insert new entry before replaced one, so that we can later
4410 * remove the second.
4413 list_add_tail(&new4_entry
->common
.list
,
4414 &fib4_entry
->common
.list
);
4416 struct mlxsw_sp_fib4_entry
*last
;
4418 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
4419 if (new4_entry
->tb_id
> last
->tb_id
)
4425 list_add(&new4_entry
->common
.list
,
4426 &fib4_entry
->common
.list
);
4428 list_add(&new4_entry
->common
.list
,
4429 &fib_node
->entry_list
);
4436 mlxsw_sp_fib4_node_list_remove(struct mlxsw_sp_fib4_entry
*fib4_entry
)
4438 list_del(&fib4_entry
->common
.list
);
4441 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp
*mlxsw_sp
,
4442 struct mlxsw_sp_fib_entry
*fib_entry
)
4444 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4446 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4449 /* To prevent packet loss, overwrite the previously offloaded
4452 if (!list_is_singular(&fib_node
->entry_list
)) {
4453 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4454 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4456 mlxsw_sp_fib_entry_offload_refresh(n
, op
, 0);
4459 return mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
4462 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4463 struct mlxsw_sp_fib_entry
*fib_entry
)
4465 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4467 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4470 /* Promote the next entry by overwriting the deleted entry */
4471 if (!list_is_singular(&fib_node
->entry_list
)) {
4472 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4473 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4475 mlxsw_sp_fib_entry_update(mlxsw_sp
, n
);
4476 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
4480 mlxsw_sp_fib_entry_del(mlxsw_sp
, fib_entry
);
4483 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
4484 struct mlxsw_sp_fib4_entry
*fib4_entry
,
4485 bool replace
, bool append
)
4489 err
= mlxsw_sp_fib4_node_list_insert(fib4_entry
, replace
, append
);
4493 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib4_entry
->common
);
4495 goto err_fib_node_entry_add
;
4499 err_fib_node_entry_add
:
4500 mlxsw_sp_fib4_node_list_remove(fib4_entry
);
4505 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
4506 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4508 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib4_entry
->common
);
4509 mlxsw_sp_fib4_node_list_remove(fib4_entry
);
4511 if (fib4_entry
->common
.type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
)
4512 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, &fib4_entry
->common
);
4515 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
4516 struct mlxsw_sp_fib4_entry
*fib4_entry
,
4519 struct mlxsw_sp_fib_node
*fib_node
= fib4_entry
->common
.fib_node
;
4520 struct mlxsw_sp_fib4_entry
*replaced
;
4525 /* We inserted the new entry before replaced one */
4526 replaced
= list_next_entry(fib4_entry
, common
.list
);
4528 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, replaced
);
4529 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, replaced
);
4530 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4534 mlxsw_sp_router_fib4_add(struct mlxsw_sp
*mlxsw_sp
,
4535 const struct fib_entry_notifier_info
*fen_info
,
4536 bool replace
, bool append
)
4538 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4539 struct mlxsw_sp_fib_node
*fib_node
;
4542 if (mlxsw_sp
->router
->aborted
)
4545 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, fen_info
->tb_id
,
4546 &fen_info
->dst
, sizeof(fen_info
->dst
),
4548 MLXSW_SP_L3_PROTO_IPV4
);
4549 if (IS_ERR(fib_node
)) {
4550 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to get FIB node\n");
4551 return PTR_ERR(fib_node
);
4554 fib4_entry
= mlxsw_sp_fib4_entry_create(mlxsw_sp
, fib_node
, fen_info
);
4555 if (IS_ERR(fib4_entry
)) {
4556 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to create FIB entry\n");
4557 err
= PTR_ERR(fib4_entry
);
4558 goto err_fib4_entry_create
;
4561 err
= mlxsw_sp_fib4_node_entry_link(mlxsw_sp
, fib4_entry
, replace
,
4564 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to link FIB entry to node\n");
4565 goto err_fib4_node_entry_link
;
4568 mlxsw_sp_fib4_entry_replace(mlxsw_sp
, fib4_entry
, replace
);
4572 err_fib4_node_entry_link
:
4573 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4574 err_fib4_entry_create
:
4575 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4579 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp
*mlxsw_sp
,
4580 struct fib_entry_notifier_info
*fen_info
)
4582 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4583 struct mlxsw_sp_fib_node
*fib_node
;
4585 if (mlxsw_sp
->router
->aborted
)
4588 fib4_entry
= mlxsw_sp_fib4_entry_lookup(mlxsw_sp
, fen_info
);
4589 if (WARN_ON(!fib4_entry
))
4591 fib_node
= fib4_entry
->common
.fib_node
;
4593 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
4594 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4595 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4598 static bool mlxsw_sp_fib6_rt_should_ignore(const struct rt6_info
*rt
)
4600 /* Packets with link-local destination IP arriving to the router
4601 * are trapped to the CPU, so no need to program specific routes
4604 if (ipv6_addr_type(&rt
->rt6i_dst
.addr
) & IPV6_ADDR_LINKLOCAL
)
4607 /* Multicast routes aren't supported, so ignore them. Neighbour
4608 * Discovery packets are specifically trapped.
4610 if (ipv6_addr_type(&rt
->rt6i_dst
.addr
) & IPV6_ADDR_MULTICAST
)
4613 /* Cloned routes are irrelevant in the forwarding path. */
4614 if (rt
->rt6i_flags
& RTF_CACHE
)
4620 static struct mlxsw_sp_rt6
*mlxsw_sp_rt6_create(struct rt6_info
*rt
)
4622 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4624 mlxsw_sp_rt6
= kzalloc(sizeof(*mlxsw_sp_rt6
), GFP_KERNEL
);
4626 return ERR_PTR(-ENOMEM
);
4628 /* In case of route replace, replaced route is deleted with
4629 * no notification. Take reference to prevent accessing freed
4632 mlxsw_sp_rt6
->rt
= rt
;
4635 return mlxsw_sp_rt6
;
4638 #if IS_ENABLED(CONFIG_IPV6)
4639 static void mlxsw_sp_rt6_release(struct rt6_info
*rt
)
4644 static void mlxsw_sp_rt6_release(struct rt6_info
*rt
)
4649 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
4651 mlxsw_sp_rt6_release(mlxsw_sp_rt6
->rt
);
4652 kfree(mlxsw_sp_rt6
);
4655 static bool mlxsw_sp_fib6_rt_can_mp(const struct rt6_info
*rt
)
4657 /* RTF_CACHE routes are ignored */
4658 return (rt
->rt6i_flags
& (RTF_GATEWAY
| RTF_ADDRCONF
)) == RTF_GATEWAY
;
4661 static struct rt6_info
*
4662 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry
*fib6_entry
)
4664 return list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
4668 static struct mlxsw_sp_fib6_entry
*
4669 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
4670 const struct rt6_info
*nrt
, bool replace
)
4672 struct mlxsw_sp_fib6_entry
*fib6_entry
;
4674 if (!mlxsw_sp_fib6_rt_can_mp(nrt
) || replace
)
4677 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
4678 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
4680 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
4683 if (rt
->rt6i_table
->tb6_id
> nrt
->rt6i_table
->tb6_id
)
4685 if (rt
->rt6i_table
->tb6_id
!= nrt
->rt6i_table
->tb6_id
)
4687 if (rt
->rt6i_metric
< nrt
->rt6i_metric
)
4689 if (rt
->rt6i_metric
== nrt
->rt6i_metric
&&
4690 mlxsw_sp_fib6_rt_can_mp(rt
))
4692 if (rt
->rt6i_metric
> nrt
->rt6i_metric
)
4699 static struct mlxsw_sp_rt6
*
4700 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry
*fib6_entry
,
4701 const struct rt6_info
*rt
)
4703 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4705 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
4706 if (mlxsw_sp_rt6
->rt
== rt
)
4707 return mlxsw_sp_rt6
;
4713 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
4714 const struct rt6_info
*rt
,
4715 enum mlxsw_sp_ipip_type
*ret
)
4717 return rt
->dst
.dev
&&
4718 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, rt
->dst
.dev
, ret
);
4721 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp
*mlxsw_sp
,
4722 struct mlxsw_sp_nexthop_group
*nh_grp
,
4723 struct mlxsw_sp_nexthop
*nh
,
4724 const struct rt6_info
*rt
)
4726 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
4727 struct mlxsw_sp_ipip_entry
*ipip_entry
;
4728 struct net_device
*dev
= rt
->dst
.dev
;
4729 struct mlxsw_sp_rif
*rif
;
4732 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, dev
);
4734 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
4735 if (ipip_ops
->can_offload(mlxsw_sp
, dev
,
4736 MLXSW_SP_L3_PROTO_IPV6
)) {
4737 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
4738 mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, ipip_entry
);
4743 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
4744 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
4747 mlxsw_sp_nexthop_rif_init(nh
, rif
);
4749 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
4751 goto err_nexthop_neigh_init
;
4755 err_nexthop_neigh_init
:
4756 mlxsw_sp_nexthop_rif_fini(nh
);
4760 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp
*mlxsw_sp
,
4761 struct mlxsw_sp_nexthop
*nh
)
4763 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
4766 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp
*mlxsw_sp
,
4767 struct mlxsw_sp_nexthop_group
*nh_grp
,
4768 struct mlxsw_sp_nexthop
*nh
,
4769 const struct rt6_info
*rt
)
4771 struct net_device
*dev
= rt
->dst
.dev
;
4773 nh
->nh_grp
= nh_grp
;
4775 memcpy(&nh
->gw_addr
, &rt
->rt6i_gateway
, sizeof(nh
->gw_addr
));
4776 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
4778 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
4782 nh
->ifindex
= dev
->ifindex
;
4784 return mlxsw_sp_nexthop6_type_init(mlxsw_sp
, nh_grp
, nh
, rt
);
4787 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp
*mlxsw_sp
,
4788 struct mlxsw_sp_nexthop
*nh
)
4790 mlxsw_sp_nexthop6_type_fini(mlxsw_sp
, nh
);
4791 list_del(&nh
->router_list_node
);
4792 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
4795 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
4796 const struct rt6_info
*rt
)
4798 return rt
->rt6i_flags
& RTF_GATEWAY
||
4799 mlxsw_sp_nexthop6_ipip_type(mlxsw_sp
, rt
, NULL
);
4802 static struct mlxsw_sp_nexthop_group
*
4803 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp
*mlxsw_sp
,
4804 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4806 struct mlxsw_sp_nexthop_group
*nh_grp
;
4807 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4808 struct mlxsw_sp_nexthop
*nh
;
4813 alloc_size
= sizeof(*nh_grp
) +
4814 fib6_entry
->nrt6
* sizeof(struct mlxsw_sp_nexthop
);
4815 nh_grp
= kzalloc(alloc_size
, GFP_KERNEL
);
4817 return ERR_PTR(-ENOMEM
);
4818 INIT_LIST_HEAD(&nh_grp
->fib_list
);
4819 #if IS_ENABLED(CONFIG_IPV6)
4820 nh_grp
->neigh_tbl
= &nd_tbl
;
4822 mlxsw_sp_rt6
= list_first_entry(&fib6_entry
->rt6_list
,
4823 struct mlxsw_sp_rt6
, list
);
4824 nh_grp
->gateway
= mlxsw_sp_rt6_is_gateway(mlxsw_sp
, mlxsw_sp_rt6
->rt
);
4825 nh_grp
->count
= fib6_entry
->nrt6
;
4826 for (i
= 0; i
< nh_grp
->count
; i
++) {
4827 struct rt6_info
*rt
= mlxsw_sp_rt6
->rt
;
4829 nh
= &nh_grp
->nexthops
[i
];
4830 err
= mlxsw_sp_nexthop6_init(mlxsw_sp
, nh_grp
, nh
, rt
);
4832 goto err_nexthop6_init
;
4833 mlxsw_sp_rt6
= list_next_entry(mlxsw_sp_rt6
, list
);
4836 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
4838 goto err_nexthop_group_insert
;
4840 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
4843 err_nexthop_group_insert
:
4845 for (i
--; i
>= 0; i
--) {
4846 nh
= &nh_grp
->nexthops
[i
];
4847 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
4850 return ERR_PTR(err
);
4854 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
4855 struct mlxsw_sp_nexthop_group
*nh_grp
)
4857 struct mlxsw_sp_nexthop
*nh
;
4858 int i
= nh_grp
->count
;
4860 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
4861 for (i
--; i
>= 0; i
--) {
4862 nh
= &nh_grp
->nexthops
[i
];
4863 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
4865 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
4866 WARN_ON(nh_grp
->adj_index_valid
);
4870 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp
*mlxsw_sp
,
4871 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4873 struct mlxsw_sp_nexthop_group
*nh_grp
;
4875 nh_grp
= mlxsw_sp_nexthop6_group_lookup(mlxsw_sp
, fib6_entry
);
4877 nh_grp
= mlxsw_sp_nexthop6_group_create(mlxsw_sp
, fib6_entry
);
4879 return PTR_ERR(nh_grp
);
4882 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
4884 fib6_entry
->common
.nh_group
= nh_grp
;
4889 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp
*mlxsw_sp
,
4890 struct mlxsw_sp_fib_entry
*fib_entry
)
4892 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4894 list_del(&fib_entry
->nexthop_group_node
);
4895 if (!list_empty(&nh_grp
->fib_list
))
4897 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, nh_grp
);
4901 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp
*mlxsw_sp
,
4902 struct mlxsw_sp_fib6_entry
*fib6_entry
)
4904 struct mlxsw_sp_nexthop_group
*old_nh_grp
= fib6_entry
->common
.nh_group
;
4907 fib6_entry
->common
.nh_group
= NULL
;
4908 list_del(&fib6_entry
->common
.nexthop_group_node
);
4910 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
4912 goto err_nexthop6_group_get
;
4914 /* In case this entry is offloaded, then the adjacency index
4915 * currently associated with it in the device's table is that
4916 * of the old group. Start using the new one instead.
4918 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
4920 goto err_fib_node_entry_add
;
4922 if (list_empty(&old_nh_grp
->fib_list
))
4923 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, old_nh_grp
);
4927 err_fib_node_entry_add
:
4928 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
4929 err_nexthop6_group_get
:
4930 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
4931 &old_nh_grp
->fib_list
);
4932 fib6_entry
->common
.nh_group
= old_nh_grp
;
4937 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp
*mlxsw_sp
,
4938 struct mlxsw_sp_fib6_entry
*fib6_entry
,
4939 struct rt6_info
*rt
)
4941 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4944 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt
);
4945 if (IS_ERR(mlxsw_sp_rt6
))
4946 return PTR_ERR(mlxsw_sp_rt6
);
4948 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
4951 err
= mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
4953 goto err_nexthop6_group_update
;
4957 err_nexthop6_group_update
:
4959 list_del(&mlxsw_sp_rt6
->list
);
4960 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4965 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp
*mlxsw_sp
,
4966 struct mlxsw_sp_fib6_entry
*fib6_entry
,
4967 struct rt6_info
*rt
)
4969 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4971 mlxsw_sp_rt6
= mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
);
4972 if (WARN_ON(!mlxsw_sp_rt6
))
4976 list_del(&mlxsw_sp_rt6
->list
);
4977 mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
4978 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
4981 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
4982 struct mlxsw_sp_fib_entry
*fib_entry
,
4983 const struct rt6_info
*rt
)
4985 /* Packets hitting RTF_REJECT routes need to be discarded by the
4986 * stack. We can rely on their destination device not having a
4987 * RIF (it's the loopback device) and can thus use action type
4988 * local, which will cause them to be trapped with a lower
4989 * priority than packets that need to be locally received.
4991 if (rt
->rt6i_flags
& (RTF_LOCAL
| RTF_ANYCAST
))
4992 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4993 else if (rt
->rt6i_flags
& RTF_REJECT
)
4994 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4995 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp
, rt
))
4996 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4998 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
5002 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5004 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
, *tmp
;
5006 list_for_each_entry_safe(mlxsw_sp_rt6
, tmp
, &fib6_entry
->rt6_list
,
5009 list_del(&mlxsw_sp_rt6
->list
);
5010 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5014 static struct mlxsw_sp_fib6_entry
*
5015 mlxsw_sp_fib6_entry_create(struct mlxsw_sp
*mlxsw_sp
,
5016 struct mlxsw_sp_fib_node
*fib_node
,
5017 struct rt6_info
*rt
)
5019 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5020 struct mlxsw_sp_fib_entry
*fib_entry
;
5021 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5024 fib6_entry
= kzalloc(sizeof(*fib6_entry
), GFP_KERNEL
);
5026 return ERR_PTR(-ENOMEM
);
5027 fib_entry
= &fib6_entry
->common
;
5029 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt
);
5030 if (IS_ERR(mlxsw_sp_rt6
)) {
5031 err
= PTR_ERR(mlxsw_sp_rt6
);
5032 goto err_rt6_create
;
5035 mlxsw_sp_fib6_entry_type_set(mlxsw_sp
, fib_entry
, mlxsw_sp_rt6
->rt
);
5037 INIT_LIST_HEAD(&fib6_entry
->rt6_list
);
5038 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
5039 fib6_entry
->nrt6
= 1;
5040 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
5042 goto err_nexthop6_group_get
;
5044 fib_entry
->fib_node
= fib_node
;
5048 err_nexthop6_group_get
:
5049 list_del(&mlxsw_sp_rt6
->list
);
5050 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5053 return ERR_PTR(err
);
5056 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
5057 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5059 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
5060 mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry
);
5061 WARN_ON(fib6_entry
->nrt6
);
5065 static struct mlxsw_sp_fib6_entry
*
5066 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
5067 const struct rt6_info
*nrt
, bool replace
)
5069 struct mlxsw_sp_fib6_entry
*fib6_entry
, *fallback
= NULL
;
5071 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5072 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5074 if (rt
->rt6i_table
->tb6_id
> nrt
->rt6i_table
->tb6_id
)
5076 if (rt
->rt6i_table
->tb6_id
!= nrt
->rt6i_table
->tb6_id
)
5078 if (replace
&& rt
->rt6i_metric
== nrt
->rt6i_metric
) {
5079 if (mlxsw_sp_fib6_rt_can_mp(rt
) ==
5080 mlxsw_sp_fib6_rt_can_mp(nrt
))
5082 if (mlxsw_sp_fib6_rt_can_mp(nrt
))
5083 fallback
= fallback
?: fib6_entry
;
5085 if (rt
->rt6i_metric
> nrt
->rt6i_metric
)
5086 return fallback
?: fib6_entry
;
5093 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry
*new6_entry
,
5096 struct mlxsw_sp_fib_node
*fib_node
= new6_entry
->common
.fib_node
;
5097 struct rt6_info
*nrt
= mlxsw_sp_fib6_entry_rt(new6_entry
);
5098 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5100 fib6_entry
= mlxsw_sp_fib6_node_entry_find(fib_node
, nrt
, replace
);
5102 if (replace
&& WARN_ON(!fib6_entry
))
5106 list_add_tail(&new6_entry
->common
.list
,
5107 &fib6_entry
->common
.list
);
5109 struct mlxsw_sp_fib6_entry
*last
;
5111 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
5112 struct rt6_info
*rt
= mlxsw_sp_fib6_entry_rt(last
);
5114 if (nrt
->rt6i_table
->tb6_id
> rt
->rt6i_table
->tb6_id
)
5120 list_add(&new6_entry
->common
.list
,
5121 &fib6_entry
->common
.list
);
5123 list_add(&new6_entry
->common
.list
,
5124 &fib_node
->entry_list
);
5131 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5133 list_del(&fib6_entry
->common
.list
);
5136 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
5137 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5142 err
= mlxsw_sp_fib6_node_list_insert(fib6_entry
, replace
);
5146 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
5148 goto err_fib_node_entry_add
;
5152 err_fib_node_entry_add
:
5153 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5158 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
5159 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5161 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib6_entry
->common
);
5162 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5165 static struct mlxsw_sp_fib6_entry
*
5166 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
5167 const struct rt6_info
*rt
)
5169 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5170 struct mlxsw_sp_fib_node
*fib_node
;
5171 struct mlxsw_sp_fib
*fib
;
5172 struct mlxsw_sp_vr
*vr
;
5174 vr
= mlxsw_sp_vr_find(mlxsw_sp
, rt
->rt6i_table
->tb6_id
);
5177 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV6
);
5179 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &rt
->rt6i_dst
.addr
,
5180 sizeof(rt
->rt6i_dst
.addr
),
5185 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5186 struct rt6_info
*iter_rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5188 if (rt
->rt6i_table
->tb6_id
== iter_rt
->rt6i_table
->tb6_id
&&
5189 rt
->rt6i_metric
== iter_rt
->rt6i_metric
&&
5190 mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
))
5197 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
5198 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5201 struct mlxsw_sp_fib_node
*fib_node
= fib6_entry
->common
.fib_node
;
5202 struct mlxsw_sp_fib6_entry
*replaced
;
5207 replaced
= list_next_entry(fib6_entry
, common
.list
);
5209 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, replaced
);
5210 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, replaced
);
5211 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5214 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp
*mlxsw_sp
,
5215 struct rt6_info
*rt
, bool replace
)
5217 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5218 struct mlxsw_sp_fib_node
*fib_node
;
5221 if (mlxsw_sp
->router
->aborted
)
5224 if (rt
->rt6i_src
.plen
)
5227 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5230 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, rt
->rt6i_table
->tb6_id
,
5232 sizeof(rt
->rt6i_dst
.addr
),
5234 MLXSW_SP_L3_PROTO_IPV6
);
5235 if (IS_ERR(fib_node
))
5236 return PTR_ERR(fib_node
);
5238 /* Before creating a new entry, try to append route to an existing
5241 fib6_entry
= mlxsw_sp_fib6_node_mp_entry_find(fib_node
, rt
, replace
);
5243 err
= mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp
, fib6_entry
, rt
);
5245 goto err_fib6_entry_nexthop_add
;
5249 fib6_entry
= mlxsw_sp_fib6_entry_create(mlxsw_sp
, fib_node
, rt
);
5250 if (IS_ERR(fib6_entry
)) {
5251 err
= PTR_ERR(fib6_entry
);
5252 goto err_fib6_entry_create
;
5255 err
= mlxsw_sp_fib6_node_entry_link(mlxsw_sp
, fib6_entry
, replace
);
5257 goto err_fib6_node_entry_link
;
5259 mlxsw_sp_fib6_entry_replace(mlxsw_sp
, fib6_entry
, replace
);
5263 err_fib6_node_entry_link
:
5264 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5265 err_fib6_entry_create
:
5266 err_fib6_entry_nexthop_add
:
5267 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5271 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp
*mlxsw_sp
,
5272 struct rt6_info
*rt
)
5274 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5275 struct mlxsw_sp_fib_node
*fib_node
;
5277 if (mlxsw_sp
->router
->aborted
)
5280 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5283 fib6_entry
= mlxsw_sp_fib6_entry_lookup(mlxsw_sp
, rt
);
5284 if (WARN_ON(!fib6_entry
))
5287 /* If route is part of a multipath entry, but not the last one
5288 * removed, then only reduce its nexthop group.
5290 if (!list_is_singular(&fib6_entry
->rt6_list
)) {
5291 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp
, fib6_entry
, rt
);
5295 fib_node
= fib6_entry
->common
.fib_node
;
5297 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5298 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5299 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5302 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
,
5303 enum mlxsw_reg_ralxx_protocol proto
,
5306 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
5307 char ralst_pl
[MLXSW_REG_RALST_LEN
];
5310 mlxsw_reg_ralta_pack(ralta_pl
, true, proto
, tree_id
);
5311 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
5315 mlxsw_reg_ralst_pack(ralst_pl
, 0xff, tree_id
);
5316 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralst
), ralst_pl
);
5320 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5321 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5322 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
5323 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
5325 mlxsw_reg_raltb_pack(raltb_pl
, vr
->id
, proto
, tree_id
);
5326 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
),
5331 mlxsw_reg_ralue_pack(ralue_pl
, proto
,
5332 MLXSW_REG_RALUE_OP_WRITE_WRITE
, vr
->id
, 0);
5333 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
5334 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
),
5343 static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp
*mlxsw_sp
,
5344 struct mfc_entry_notifier_info
*men_info
,
5347 struct mlxsw_sp_vr
*vr
;
5349 if (mlxsw_sp
->router
->aborted
)
5352 vr
= mlxsw_sp_vr_get(mlxsw_sp
, men_info
->tb_id
, NULL
);
5356 return mlxsw_sp_mr_route4_add(vr
->mr4_table
, men_info
->mfc
, replace
);
5359 static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp
*mlxsw_sp
,
5360 struct mfc_entry_notifier_info
*men_info
)
5362 struct mlxsw_sp_vr
*vr
;
5364 if (mlxsw_sp
->router
->aborted
)
5367 vr
= mlxsw_sp_vr_find(mlxsw_sp
, men_info
->tb_id
);
5371 mlxsw_sp_mr_route4_del(vr
->mr4_table
, men_info
->mfc
);
5372 mlxsw_sp_vr_put(vr
);
5376 mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp
*mlxsw_sp
,
5377 struct vif_entry_notifier_info
*ven_info
)
5379 struct mlxsw_sp_rif
*rif
;
5380 struct mlxsw_sp_vr
*vr
;
5382 if (mlxsw_sp
->router
->aborted
)
5385 vr
= mlxsw_sp_vr_get(mlxsw_sp
, ven_info
->tb_id
, NULL
);
5389 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, ven_info
->dev
);
5390 return mlxsw_sp_mr_vif_add(vr
->mr4_table
, ven_info
->dev
,
5391 ven_info
->vif_index
,
5392 ven_info
->vif_flags
, rif
);
5396 mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp
*mlxsw_sp
,
5397 struct vif_entry_notifier_info
*ven_info
)
5399 struct mlxsw_sp_vr
*vr
;
5401 if (mlxsw_sp
->router
->aborted
)
5404 vr
= mlxsw_sp_vr_find(mlxsw_sp
, ven_info
->tb_id
);
5408 mlxsw_sp_mr_vif_del(vr
->mr4_table
, ven_info
->vif_index
);
5409 mlxsw_sp_vr_put(vr
);
5412 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
)
5414 enum mlxsw_reg_ralxx_protocol proto
= MLXSW_REG_RALXX_PROTOCOL_IPV4
;
5417 err
= __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5418 MLXSW_SP_LPM_TREE_MIN
);
5422 /* The multicast router code does not need an abort trap as by default,
5423 * packets that don't match any routes are trapped to the CPU.
5426 proto
= MLXSW_REG_RALXX_PROTOCOL_IPV6
;
5427 return __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5428 MLXSW_SP_LPM_TREE_MIN
+ 1);
5431 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5432 struct mlxsw_sp_fib_node
*fib_node
)
5434 struct mlxsw_sp_fib4_entry
*fib4_entry
, *tmp
;
5436 list_for_each_entry_safe(fib4_entry
, tmp
, &fib_node
->entry_list
,
5438 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5440 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
5441 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
5442 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5443 /* Break when entry list is empty and node was freed.
5444 * Otherwise, we'll access freed memory in the next
5452 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5453 struct mlxsw_sp_fib_node
*fib_node
)
5455 struct mlxsw_sp_fib6_entry
*fib6_entry
, *tmp
;
5457 list_for_each_entry_safe(fib6_entry
, tmp
, &fib_node
->entry_list
,
5459 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5461 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5462 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5463 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5469 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5470 struct mlxsw_sp_fib_node
*fib_node
)
5472 switch (fib_node
->fib
->proto
) {
5473 case MLXSW_SP_L3_PROTO_IPV4
:
5474 mlxsw_sp_fib4_node_flush(mlxsw_sp
, fib_node
);
5476 case MLXSW_SP_L3_PROTO_IPV6
:
5477 mlxsw_sp_fib6_node_flush(mlxsw_sp
, fib_node
);
5482 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp
*mlxsw_sp
,
5483 struct mlxsw_sp_vr
*vr
,
5484 enum mlxsw_sp_l3proto proto
)
5486 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
5487 struct mlxsw_sp_fib_node
*fib_node
, *tmp
;
5489 list_for_each_entry_safe(fib_node
, tmp
, &fib
->node_list
, list
) {
5490 bool do_break
= &tmp
->list
== &fib
->node_list
;
5492 mlxsw_sp_fib_node_flush(mlxsw_sp
, fib_node
);
5498 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
)
5502 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5503 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5505 if (!mlxsw_sp_vr_is_used(vr
))
5508 mlxsw_sp_mr_table_flush(vr
->mr4_table
);
5509 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV4
);
5511 /* If virtual router was only used for IPv4, then it's no
5514 if (!mlxsw_sp_vr_is_used(vr
))
5516 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV6
);
5520 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp
*mlxsw_sp
)
5524 if (mlxsw_sp
->router
->aborted
)
5526 dev_warn(mlxsw_sp
->bus_info
->dev
, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
5527 mlxsw_sp_router_fib_flush(mlxsw_sp
);
5528 mlxsw_sp
->router
->aborted
= true;
5529 err
= mlxsw_sp_router_set_abort_trap(mlxsw_sp
);
5531 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set abort trap.\n");
5534 struct mlxsw_sp_fib_event_work
{
5535 struct work_struct work
;
5537 struct fib6_entry_notifier_info fen6_info
;
5538 struct fib_entry_notifier_info fen_info
;
5539 struct fib_rule_notifier_info fr_info
;
5540 struct fib_nh_notifier_info fnh_info
;
5541 struct mfc_entry_notifier_info men_info
;
5542 struct vif_entry_notifier_info ven_info
;
5544 struct mlxsw_sp
*mlxsw_sp
;
5545 unsigned long event
;
5548 static void mlxsw_sp_router_fib4_event_work(struct work_struct
*work
)
5550 struct mlxsw_sp_fib_event_work
*fib_work
=
5551 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5552 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5553 bool replace
, append
;
5556 /* Protect internal structures from changes */
5558 switch (fib_work
->event
) {
5559 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5560 case FIB_EVENT_ENTRY_APPEND
: /* fall through */
5561 case FIB_EVENT_ENTRY_ADD
:
5562 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5563 append
= fib_work
->event
== FIB_EVENT_ENTRY_APPEND
;
5564 err
= mlxsw_sp_router_fib4_add(mlxsw_sp
, &fib_work
->fen_info
,
5567 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5568 fib_info_put(fib_work
->fen_info
.fi
);
5570 case FIB_EVENT_ENTRY_DEL
:
5571 mlxsw_sp_router_fib4_del(mlxsw_sp
, &fib_work
->fen_info
);
5572 fib_info_put(fib_work
->fen_info
.fi
);
5574 case FIB_EVENT_RULE_ADD
:
5575 /* if we get here, a rule was added that we do not support.
5576 * just do the fib_abort
5578 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5580 case FIB_EVENT_NH_ADD
: /* fall through */
5581 case FIB_EVENT_NH_DEL
:
5582 mlxsw_sp_nexthop4_event(mlxsw_sp
, fib_work
->event
,
5583 fib_work
->fnh_info
.fib_nh
);
5584 fib_info_put(fib_work
->fnh_info
.fib_nh
->nh_parent
);
5591 static void mlxsw_sp_router_fib6_event_work(struct work_struct
*work
)
5593 struct mlxsw_sp_fib_event_work
*fib_work
=
5594 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5595 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5600 switch (fib_work
->event
) {
5601 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5602 case FIB_EVENT_ENTRY_ADD
:
5603 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5604 err
= mlxsw_sp_router_fib6_add(mlxsw_sp
,
5605 fib_work
->fen6_info
.rt
, replace
);
5607 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5608 mlxsw_sp_rt6_release(fib_work
->fen6_info
.rt
);
5610 case FIB_EVENT_ENTRY_DEL
:
5611 mlxsw_sp_router_fib6_del(mlxsw_sp
, fib_work
->fen6_info
.rt
);
5612 mlxsw_sp_rt6_release(fib_work
->fen6_info
.rt
);
5614 case FIB_EVENT_RULE_ADD
:
5615 /* if we get here, a rule was added that we do not support.
5616 * just do the fib_abort
5618 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5625 static void mlxsw_sp_router_fibmr_event_work(struct work_struct
*work
)
5627 struct mlxsw_sp_fib_event_work
*fib_work
=
5628 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
5629 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
5634 switch (fib_work
->event
) {
5635 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5636 case FIB_EVENT_ENTRY_ADD
:
5637 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
5639 err
= mlxsw_sp_router_fibmr_add(mlxsw_sp
, &fib_work
->men_info
,
5642 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5643 ipmr_cache_put(fib_work
->men_info
.mfc
);
5645 case FIB_EVENT_ENTRY_DEL
:
5646 mlxsw_sp_router_fibmr_del(mlxsw_sp
, &fib_work
->men_info
);
5647 ipmr_cache_put(fib_work
->men_info
.mfc
);
5649 case FIB_EVENT_VIF_ADD
:
5650 err
= mlxsw_sp_router_fibmr_vif_add(mlxsw_sp
,
5651 &fib_work
->ven_info
);
5653 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5654 dev_put(fib_work
->ven_info
.dev
);
5656 case FIB_EVENT_VIF_DEL
:
5657 mlxsw_sp_router_fibmr_vif_del(mlxsw_sp
,
5658 &fib_work
->ven_info
);
5659 dev_put(fib_work
->ven_info
.dev
);
5661 case FIB_EVENT_RULE_ADD
:
5662 /* if we get here, a rule was added that we do not support.
5663 * just do the fib_abort
5665 mlxsw_sp_router_fib_abort(mlxsw_sp
);
5672 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5673 struct fib_notifier_info
*info
)
5675 struct fib_entry_notifier_info
*fen_info
;
5676 struct fib_nh_notifier_info
*fnh_info
;
5678 switch (fib_work
->event
) {
5679 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5680 case FIB_EVENT_ENTRY_APPEND
: /* fall through */
5681 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5682 case FIB_EVENT_ENTRY_DEL
:
5683 fen_info
= container_of(info
, struct fib_entry_notifier_info
,
5685 fib_work
->fen_info
= *fen_info
;
5686 /* Take reference on fib_info to prevent it from being
5687 * freed while work is queued. Release it afterwards.
5689 fib_info_hold(fib_work
->fen_info
.fi
);
5691 case FIB_EVENT_NH_ADD
: /* fall through */
5692 case FIB_EVENT_NH_DEL
:
5693 fnh_info
= container_of(info
, struct fib_nh_notifier_info
,
5695 fib_work
->fnh_info
= *fnh_info
;
5696 fib_info_hold(fib_work
->fnh_info
.fib_nh
->nh_parent
);
5701 static void mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5702 struct fib_notifier_info
*info
)
5704 struct fib6_entry_notifier_info
*fen6_info
;
5706 switch (fib_work
->event
) {
5707 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5708 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5709 case FIB_EVENT_ENTRY_DEL
:
5710 fen6_info
= container_of(info
, struct fib6_entry_notifier_info
,
5712 fib_work
->fen6_info
= *fen6_info
;
5713 rt6_hold(fib_work
->fen6_info
.rt
);
5719 mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work
*fib_work
,
5720 struct fib_notifier_info
*info
)
5722 switch (fib_work
->event
) {
5723 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
5724 case FIB_EVENT_ENTRY_ADD
: /* fall through */
5725 case FIB_EVENT_ENTRY_DEL
:
5726 memcpy(&fib_work
->men_info
, info
, sizeof(fib_work
->men_info
));
5727 ipmr_cache_hold(fib_work
->men_info
.mfc
);
5729 case FIB_EVENT_VIF_ADD
: /* fall through */
5730 case FIB_EVENT_VIF_DEL
:
5731 memcpy(&fib_work
->ven_info
, info
, sizeof(fib_work
->ven_info
));
5732 dev_hold(fib_work
->ven_info
.dev
);
5737 static int mlxsw_sp_router_fib_rule_event(unsigned long event
,
5738 struct fib_notifier_info
*info
,
5739 struct mlxsw_sp
*mlxsw_sp
)
5741 struct netlink_ext_ack
*extack
= info
->extack
;
5742 struct fib_rule_notifier_info
*fr_info
;
5743 struct fib_rule
*rule
;
5746 /* nothing to do at the moment */
5747 if (event
== FIB_EVENT_RULE_DEL
)
5750 if (mlxsw_sp
->router
->aborted
)
5753 fr_info
= container_of(info
, struct fib_rule_notifier_info
, info
);
5754 rule
= fr_info
->rule
;
5756 switch (info
->family
) {
5758 if (!fib4_rule_default(rule
) && !rule
->l3mdev
)
5762 if (!fib6_rule_default(rule
) && !rule
->l3mdev
)
5765 case RTNL_FAMILY_IPMR
:
5766 if (!ipmr_rule_default(rule
) && !rule
->l3mdev
)
5772 NL_SET_ERR_MSG(extack
, "spectrum: FIB rules not supported. Aborting offload");
5777 /* Called with rcu_read_lock() */
5778 static int mlxsw_sp_router_fib_event(struct notifier_block
*nb
,
5779 unsigned long event
, void *ptr
)
5781 struct mlxsw_sp_fib_event_work
*fib_work
;
5782 struct fib_notifier_info
*info
= ptr
;
5783 struct mlxsw_sp_router
*router
;
5786 if (!net_eq(info
->net
, &init_net
) ||
5787 (info
->family
!= AF_INET
&& info
->family
!= AF_INET6
&&
5788 info
->family
!= RTNL_FAMILY_IPMR
))
5791 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
5794 case FIB_EVENT_RULE_ADD
: /* fall through */
5795 case FIB_EVENT_RULE_DEL
:
5796 err
= mlxsw_sp_router_fib_rule_event(event
, info
,
5802 fib_work
= kzalloc(sizeof(*fib_work
), GFP_ATOMIC
);
5803 if (WARN_ON(!fib_work
))
5806 fib_work
->mlxsw_sp
= router
->mlxsw_sp
;
5807 fib_work
->event
= event
;
5809 switch (info
->family
) {
5811 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib4_event_work
);
5812 mlxsw_sp_router_fib4_event(fib_work
, info
);
5815 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib6_event_work
);
5816 mlxsw_sp_router_fib6_event(fib_work
, info
);
5818 case RTNL_FAMILY_IPMR
:
5819 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fibmr_event_work
);
5820 mlxsw_sp_router_fibmr_event(fib_work
, info
);
5824 mlxsw_core_schedule_work(&fib_work
->work
);
5829 static struct mlxsw_sp_rif
*
5830 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp
*mlxsw_sp
,
5831 const struct net_device
*dev
)
5835 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
5836 if (mlxsw_sp
->router
->rifs
[i
] &&
5837 mlxsw_sp
->router
->rifs
[i
]->dev
== dev
)
5838 return mlxsw_sp
->router
->rifs
[i
];
5843 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp
*mlxsw_sp
, u16 rif
)
5845 char ritr_pl
[MLXSW_REG_RITR_LEN
];
5848 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif
);
5849 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
5850 if (WARN_ON_ONCE(err
))
5853 mlxsw_reg_ritr_enable_set(ritr_pl
, false);
5854 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
5857 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
5858 struct mlxsw_sp_rif
*rif
)
5860 mlxsw_sp_router_rif_disable(mlxsw_sp
, rif
->rif_index
);
5861 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp
, rif
);
5862 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp
, rif
);
5866 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif
*rif
, struct net_device
*dev
,
5867 unsigned long event
)
5869 struct inet6_dev
*inet6_dev
;
5870 bool addr_list_empty
= true;
5871 struct in_device
*idev
;
5877 idev
= __in_dev_get_rtnl(dev
);
5878 if (idev
&& idev
->ifa_list
)
5879 addr_list_empty
= false;
5881 inet6_dev
= __in6_dev_get(dev
);
5882 if (addr_list_empty
&& inet6_dev
&&
5883 !list_empty(&inet6_dev
->addr_list
))
5884 addr_list_empty
= false;
5886 if (rif
&& addr_list_empty
&&
5887 !netif_is_l3_slave(rif
->dev
))
5889 /* It is possible we already removed the RIF ourselves
5890 * if it was assigned to a netdev that is now a bridge
5899 static enum mlxsw_sp_rif_type
5900 mlxsw_sp_dev_rif_type(const struct mlxsw_sp
*mlxsw_sp
,
5901 const struct net_device
*dev
)
5903 enum mlxsw_sp_fid_type type
;
5905 if (mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
))
5906 return MLXSW_SP_RIF_TYPE_IPIP_LB
;
5908 /* Otherwise RIF type is derived from the type of the underlying FID. */
5909 if (is_vlan_dev(dev
) && netif_is_bridge_master(vlan_dev_real_dev(dev
)))
5910 type
= MLXSW_SP_FID_TYPE_8021Q
;
5911 else if (netif_is_bridge_master(dev
) && br_vlan_enabled(dev
))
5912 type
= MLXSW_SP_FID_TYPE_8021Q
;
5913 else if (netif_is_bridge_master(dev
))
5914 type
= MLXSW_SP_FID_TYPE_8021D
;
5916 type
= MLXSW_SP_FID_TYPE_RFID
;
5918 return mlxsw_sp_fid_type_rif_type(mlxsw_sp
, type
);
5921 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp
*mlxsw_sp
, u16
*p_rif_index
)
5925 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
5926 if (!mlxsw_sp
->router
->rifs
[i
]) {
5935 static struct mlxsw_sp_rif
*mlxsw_sp_rif_alloc(size_t rif_size
, u16 rif_index
,
5937 struct net_device
*l3_dev
)
5939 struct mlxsw_sp_rif
*rif
;
5941 rif
= kzalloc(rif_size
, GFP_KERNEL
);
5945 INIT_LIST_HEAD(&rif
->nexthop_list
);
5946 INIT_LIST_HEAD(&rif
->neigh_list
);
5947 ether_addr_copy(rif
->addr
, l3_dev
->dev_addr
);
5948 rif
->mtu
= l3_dev
->mtu
;
5951 rif
->rif_index
= rif_index
;
5956 struct mlxsw_sp_rif
*mlxsw_sp_rif_by_index(const struct mlxsw_sp
*mlxsw_sp
,
5959 return mlxsw_sp
->router
->rifs
[rif_index
];
5962 u16
mlxsw_sp_rif_index(const struct mlxsw_sp_rif
*rif
)
5964 return rif
->rif_index
;
5967 u16
mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
5969 return lb_rif
->common
.rif_index
;
5972 u16
mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
5974 return lb_rif
->ul_vr_id
;
5977 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif
*rif
)
5979 return rif
->dev
->ifindex
;
5982 const struct net_device
*mlxsw_sp_rif_dev(const struct mlxsw_sp_rif
*rif
)
5987 static struct mlxsw_sp_rif
*
5988 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
5989 const struct mlxsw_sp_rif_params
*params
,
5990 struct netlink_ext_ack
*extack
)
5992 u32 tb_id
= l3mdev_fib_table(params
->dev
);
5993 const struct mlxsw_sp_rif_ops
*ops
;
5994 struct mlxsw_sp_fid
*fid
= NULL
;
5995 enum mlxsw_sp_rif_type type
;
5996 struct mlxsw_sp_rif
*rif
;
5997 struct mlxsw_sp_vr
*vr
;
6001 type
= mlxsw_sp_dev_rif_type(mlxsw_sp
, params
->dev
);
6002 ops
= mlxsw_sp
->router
->rif_ops_arr
[type
];
6004 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
? : RT_TABLE_MAIN
, extack
);
6006 return ERR_CAST(vr
);
6009 err
= mlxsw_sp_rif_index_alloc(mlxsw_sp
, &rif_index
);
6011 NL_SET_ERR_MSG(extack
, "spectrum: Exceeded number of supported router interfaces");
6012 goto err_rif_index_alloc
;
6015 rif
= mlxsw_sp_rif_alloc(ops
->rif_size
, rif_index
, vr
->id
, params
->dev
);
6020 rif
->mlxsw_sp
= mlxsw_sp
;
6024 fid
= ops
->fid_get(rif
);
6033 ops
->setup(rif
, params
);
6035 err
= ops
->configure(rif
);
6039 err
= mlxsw_sp_mr_rif_add(vr
->mr4_table
, rif
);
6041 goto err_mr_rif_add
;
6043 mlxsw_sp_rif_counters_alloc(rif
);
6044 mlxsw_sp
->router
->rifs
[rif_index
] = rif
;
6049 ops
->deconfigure(rif
);
6052 mlxsw_sp_fid_put(fid
);
6056 err_rif_index_alloc
:
6058 mlxsw_sp_vr_put(vr
);
6059 return ERR_PTR(err
);
6062 void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif
*rif
)
6064 const struct mlxsw_sp_rif_ops
*ops
= rif
->ops
;
6065 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6066 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6067 struct mlxsw_sp_vr
*vr
;
6069 mlxsw_sp_router_rif_gone_sync(mlxsw_sp
, rif
);
6070 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6072 mlxsw_sp
->router
->rifs
[rif
->rif_index
] = NULL
;
6073 mlxsw_sp_rif_counters_free(rif
);
6074 mlxsw_sp_mr_rif_del(vr
->mr4_table
, rif
);
6075 ops
->deconfigure(rif
);
6077 /* Loopback RIFs are not associated with a FID. */
6078 mlxsw_sp_fid_put(fid
);
6081 mlxsw_sp_vr_put(vr
);
6085 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params
*params
,
6086 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6088 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6090 params
->vid
= mlxsw_sp_port_vlan
->vid
;
6091 params
->lag
= mlxsw_sp_port
->lagged
;
6093 params
->lag_id
= mlxsw_sp_port
->lag_id
;
6095 params
->system_port
= mlxsw_sp_port
->local_port
;
6099 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
,
6100 struct net_device
*l3_dev
,
6101 struct netlink_ext_ack
*extack
)
6103 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6104 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
6105 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6106 struct mlxsw_sp_rif
*rif
;
6107 struct mlxsw_sp_fid
*fid
;
6110 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6112 struct mlxsw_sp_rif_params params
= {
6116 mlxsw_sp_rif_subport_params_init(¶ms
, mlxsw_sp_port_vlan
);
6117 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6119 return PTR_ERR(rif
);
6122 /* FID was already created, just take a reference */
6123 fid
= rif
->ops
->fid_get(rif
);
6124 err
= mlxsw_sp_fid_port_vid_map(fid
, mlxsw_sp_port
, vid
);
6126 goto err_fid_port_vid_map
;
6128 err
= mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, false);
6130 goto err_port_vid_learning_set
;
6132 err
= mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
,
6133 BR_STATE_FORWARDING
);
6135 goto err_port_vid_stp_set
;
6137 mlxsw_sp_port_vlan
->fid
= fid
;
6141 err_port_vid_stp_set
:
6142 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6143 err_port_vid_learning_set
:
6144 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6145 err_fid_port_vid_map
:
6146 mlxsw_sp_fid_put(fid
);
6151 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6153 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6154 struct mlxsw_sp_fid
*fid
= mlxsw_sp_port_vlan
->fid
;
6155 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6157 if (WARN_ON(mlxsw_sp_fid_type(fid
) != MLXSW_SP_FID_TYPE_RFID
))
6160 mlxsw_sp_port_vlan
->fid
= NULL
;
6161 mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
, BR_STATE_BLOCKING
);
6162 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6163 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6164 /* If router port holds the last reference on the rFID, then the
6165 * associated Sub-port RIF will be destroyed.
6167 mlxsw_sp_fid_put(fid
);
6170 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device
*l3_dev
,
6171 struct net_device
*port_dev
,
6172 unsigned long event
, u16 vid
,
6173 struct netlink_ext_ack
*extack
)
6175 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(port_dev
);
6176 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
;
6178 mlxsw_sp_port_vlan
= mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port
, vid
);
6179 if (WARN_ON(!mlxsw_sp_port_vlan
))
6184 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan
,
6187 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan
);
6194 static int mlxsw_sp_inetaddr_port_event(struct net_device
*port_dev
,
6195 unsigned long event
,
6196 struct netlink_ext_ack
*extack
)
6198 if (netif_is_bridge_port(port_dev
) ||
6199 netif_is_lag_port(port_dev
) ||
6200 netif_is_ovs_port(port_dev
))
6203 return mlxsw_sp_inetaddr_port_vlan_event(port_dev
, port_dev
, event
, 1,
6207 static int __mlxsw_sp_inetaddr_lag_event(struct net_device
*l3_dev
,
6208 struct net_device
*lag_dev
,
6209 unsigned long event
, u16 vid
,
6210 struct netlink_ext_ack
*extack
)
6212 struct net_device
*port_dev
;
6213 struct list_head
*iter
;
6216 netdev_for_each_lower_dev(lag_dev
, port_dev
, iter
) {
6217 if (mlxsw_sp_port_dev_check(port_dev
)) {
6218 err
= mlxsw_sp_inetaddr_port_vlan_event(l3_dev
,
6230 static int mlxsw_sp_inetaddr_lag_event(struct net_device
*lag_dev
,
6231 unsigned long event
,
6232 struct netlink_ext_ack
*extack
)
6234 if (netif_is_bridge_port(lag_dev
))
6237 return __mlxsw_sp_inetaddr_lag_event(lag_dev
, lag_dev
, event
, 1,
6241 static int mlxsw_sp_inetaddr_bridge_event(struct net_device
*l3_dev
,
6242 unsigned long event
,
6243 struct netlink_ext_ack
*extack
)
6245 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
6246 struct mlxsw_sp_rif_params params
= {
6249 struct mlxsw_sp_rif
*rif
;
6253 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6255 return PTR_ERR(rif
);
6258 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6259 mlxsw_sp_rif_destroy(rif
);
6266 static int mlxsw_sp_inetaddr_vlan_event(struct net_device
*vlan_dev
,
6267 unsigned long event
,
6268 struct netlink_ext_ack
*extack
)
6270 struct net_device
*real_dev
= vlan_dev_real_dev(vlan_dev
);
6271 u16 vid
= vlan_dev_vlan_id(vlan_dev
);
6273 if (netif_is_bridge_port(vlan_dev
))
6276 if (mlxsw_sp_port_dev_check(real_dev
))
6277 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev
, real_dev
,
6278 event
, vid
, extack
);
6279 else if (netif_is_lag_master(real_dev
))
6280 return __mlxsw_sp_inetaddr_lag_event(vlan_dev
, real_dev
, event
,
6282 else if (netif_is_bridge_master(real_dev
) && br_vlan_enabled(real_dev
))
6283 return mlxsw_sp_inetaddr_bridge_event(vlan_dev
, event
, extack
);
6288 static int __mlxsw_sp_inetaddr_event(struct net_device
*dev
,
6289 unsigned long event
,
6290 struct netlink_ext_ack
*extack
)
6292 if (mlxsw_sp_port_dev_check(dev
))
6293 return mlxsw_sp_inetaddr_port_event(dev
, event
, extack
);
6294 else if (netif_is_lag_master(dev
))
6295 return mlxsw_sp_inetaddr_lag_event(dev
, event
, extack
);
6296 else if (netif_is_bridge_master(dev
))
6297 return mlxsw_sp_inetaddr_bridge_event(dev
, event
, extack
);
6298 else if (is_vlan_dev(dev
))
6299 return mlxsw_sp_inetaddr_vlan_event(dev
, event
, extack
);
6304 int mlxsw_sp_inetaddr_event(struct notifier_block
*unused
,
6305 unsigned long event
, void *ptr
)
6307 struct in_ifaddr
*ifa
= (struct in_ifaddr
*) ptr
;
6308 struct net_device
*dev
= ifa
->ifa_dev
->dev
;
6309 struct mlxsw_sp
*mlxsw_sp
;
6310 struct mlxsw_sp_rif
*rif
;
6313 /* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
6314 if (event
== NETDEV_UP
)
6317 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6321 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6322 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6325 err
= __mlxsw_sp_inetaddr_event(dev
, event
, NULL
);
6327 return notifier_from_errno(err
);
6330 int mlxsw_sp_inetaddr_valid_event(struct notifier_block
*unused
,
6331 unsigned long event
, void *ptr
)
6333 struct in_validator_info
*ivi
= (struct in_validator_info
*) ptr
;
6334 struct net_device
*dev
= ivi
->ivi_dev
->dev
;
6335 struct mlxsw_sp
*mlxsw_sp
;
6336 struct mlxsw_sp_rif
*rif
;
6339 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6343 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6344 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6347 err
= __mlxsw_sp_inetaddr_event(dev
, event
, ivi
->extack
);
6349 return notifier_from_errno(err
);
6352 struct mlxsw_sp_inet6addr_event_work
{
6353 struct work_struct work
;
6354 struct net_device
*dev
;
6355 unsigned long event
;
6358 static void mlxsw_sp_inet6addr_event_work(struct work_struct
*work
)
6360 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
=
6361 container_of(work
, struct mlxsw_sp_inet6addr_event_work
, work
);
6362 struct net_device
*dev
= inet6addr_work
->dev
;
6363 unsigned long event
= inet6addr_work
->event
;
6364 struct mlxsw_sp
*mlxsw_sp
;
6365 struct mlxsw_sp_rif
*rif
;
6368 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6372 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6373 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6376 __mlxsw_sp_inetaddr_event(dev
, event
, NULL
);
6380 kfree(inet6addr_work
);
6383 /* Called with rcu_read_lock() */
6384 int mlxsw_sp_inet6addr_event(struct notifier_block
*unused
,
6385 unsigned long event
, void *ptr
)
6387 struct inet6_ifaddr
*if6
= (struct inet6_ifaddr
*) ptr
;
6388 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
;
6389 struct net_device
*dev
= if6
->idev
->dev
;
6391 /* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
6392 if (event
== NETDEV_UP
)
6395 if (!mlxsw_sp_port_dev_lower_find_rcu(dev
))
6398 inet6addr_work
= kzalloc(sizeof(*inet6addr_work
), GFP_ATOMIC
);
6399 if (!inet6addr_work
)
6402 INIT_WORK(&inet6addr_work
->work
, mlxsw_sp_inet6addr_event_work
);
6403 inet6addr_work
->dev
= dev
;
6404 inet6addr_work
->event
= event
;
6406 mlxsw_core_schedule_work(&inet6addr_work
->work
);
6411 int mlxsw_sp_inet6addr_valid_event(struct notifier_block
*unused
,
6412 unsigned long event
, void *ptr
)
6414 struct in6_validator_info
*i6vi
= (struct in6_validator_info
*) ptr
;
6415 struct net_device
*dev
= i6vi
->i6vi_dev
->dev
;
6416 struct mlxsw_sp
*mlxsw_sp
;
6417 struct mlxsw_sp_rif
*rif
;
6420 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6424 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6425 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
6428 err
= __mlxsw_sp_inetaddr_event(dev
, event
, i6vi
->extack
);
6430 return notifier_from_errno(err
);
6433 static int mlxsw_sp_rif_edit(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
6434 const char *mac
, int mtu
)
6436 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6439 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
6440 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6444 mlxsw_reg_ritr_mtu_set(ritr_pl
, mtu
);
6445 mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl
, mac
);
6446 mlxsw_reg_ritr_op_set(ritr_pl
, MLXSW_REG_RITR_RIF_CREATE
);
6447 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6450 int mlxsw_sp_netdevice_router_port_event(struct net_device
*dev
)
6452 struct mlxsw_sp
*mlxsw_sp
;
6453 struct mlxsw_sp_rif
*rif
;
6457 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
6461 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6464 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6466 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, false);
6470 err
= mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, dev
->dev_addr
,
6475 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, dev
->dev_addr
, fid_index
, true);
6477 goto err_rif_fdb_op
;
6479 if (rif
->mtu
!= dev
->mtu
) {
6480 struct mlxsw_sp_vr
*vr
;
6482 /* The RIF is relevant only to its mr_table instance, as unlike
6483 * unicast routing, in multicast routing a RIF cannot be shared
6484 * between several multicast routing tables.
6486 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6487 mlxsw_sp_mr_rif_mtu_update(vr
->mr4_table
, rif
, dev
->mtu
);
6490 ether_addr_copy(rif
->addr
, dev
->dev_addr
);
6491 rif
->mtu
= dev
->mtu
;
6493 netdev_dbg(dev
, "Updated RIF=%d\n", rif
->rif_index
);
6498 mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, rif
->addr
, rif
->mtu
);
6500 mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, true);
6504 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp
*mlxsw_sp
,
6505 struct net_device
*l3_dev
,
6506 struct netlink_ext_ack
*extack
)
6508 struct mlxsw_sp_rif
*rif
;
6510 /* If netdev is already associated with a RIF, then we need to
6511 * destroy it and create a new one with the new virtual router ID.
6513 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6515 __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_DOWN
, extack
);
6517 return __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_UP
, extack
);
6520 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp
*mlxsw_sp
,
6521 struct net_device
*l3_dev
)
6523 struct mlxsw_sp_rif
*rif
;
6525 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6528 __mlxsw_sp_inetaddr_event(l3_dev
, NETDEV_DOWN
, NULL
);
6531 int mlxsw_sp_netdevice_vrf_event(struct net_device
*l3_dev
, unsigned long event
,
6532 struct netdev_notifier_changeupper_info
*info
)
6534 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
6541 case NETDEV_PRECHANGEUPPER
:
6543 case NETDEV_CHANGEUPPER
:
6544 if (info
->linking
) {
6545 struct netlink_ext_ack
*extack
;
6547 extack
= netdev_notifier_info_to_extack(&info
->info
);
6548 err
= mlxsw_sp_port_vrf_join(mlxsw_sp
, l3_dev
, extack
);
6550 mlxsw_sp_port_vrf_leave(mlxsw_sp
, l3_dev
);
6558 static struct mlxsw_sp_rif_subport
*
6559 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif
*rif
)
6561 return container_of(rif
, struct mlxsw_sp_rif_subport
, common
);
6564 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif
*rif
,
6565 const struct mlxsw_sp_rif_params
*params
)
6567 struct mlxsw_sp_rif_subport
*rif_subport
;
6569 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6570 rif_subport
->vid
= params
->vid
;
6571 rif_subport
->lag
= params
->lag
;
6573 rif_subport
->lag_id
= params
->lag_id
;
6575 rif_subport
->system_port
= params
->system_port
;
6578 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif
*rif
, bool enable
)
6580 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6581 struct mlxsw_sp_rif_subport
*rif_subport
;
6582 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6584 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6585 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_SP_IF
,
6586 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
6587 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
6588 mlxsw_reg_ritr_sp_if_pack(ritr_pl
, rif_subport
->lag
,
6589 rif_subport
->lag
? rif_subport
->lag_id
:
6590 rif_subport
->system_port
,
6593 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6596 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif
*rif
)
6600 err
= mlxsw_sp_rif_subport_op(rif
, true);
6604 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6605 mlxsw_sp_fid_index(rif
->fid
), true);
6607 goto err_rif_fdb_op
;
6609 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6613 mlxsw_sp_rif_subport_op(rif
, false);
6617 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif
*rif
)
6619 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6621 mlxsw_sp_fid_rif_set(fid
, NULL
);
6622 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6623 mlxsw_sp_fid_index(fid
), false);
6624 mlxsw_sp_rif_subport_op(rif
, false);
6627 static struct mlxsw_sp_fid
*
6628 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif
*rif
)
6630 return mlxsw_sp_fid_rfid_get(rif
->mlxsw_sp
, rif
->rif_index
);
6633 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops
= {
6634 .type
= MLXSW_SP_RIF_TYPE_SUBPORT
,
6635 .rif_size
= sizeof(struct mlxsw_sp_rif_subport
),
6636 .setup
= mlxsw_sp_rif_subport_setup
,
6637 .configure
= mlxsw_sp_rif_subport_configure
,
6638 .deconfigure
= mlxsw_sp_rif_subport_deconfigure
,
6639 .fid_get
= mlxsw_sp_rif_subport_fid_get
,
6642 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif
*rif
,
6643 enum mlxsw_reg_ritr_if_type type
,
6644 u16 vid_fid
, bool enable
)
6646 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6647 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6649 mlxsw_reg_ritr_pack(ritr_pl
, enable
, type
, rif
->rif_index
, rif
->vr_id
,
6651 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
6652 mlxsw_reg_ritr_fid_set(ritr_pl
, type
, vid_fid
);
6654 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6657 u8
mlxsw_sp_router_port(const struct mlxsw_sp
*mlxsw_sp
)
6659 return mlxsw_core_max_ports(mlxsw_sp
->core
) + 1;
6662 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif
*rif
)
6664 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6665 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
6668 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, true);
6672 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6673 mlxsw_sp_router_port(mlxsw_sp
), true);
6675 goto err_fid_mc_flood_set
;
6677 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6678 mlxsw_sp_router_port(mlxsw_sp
), true);
6680 goto err_fid_bc_flood_set
;
6682 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6683 mlxsw_sp_fid_index(rif
->fid
), true);
6685 goto err_rif_fdb_op
;
6687 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6691 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6692 mlxsw_sp_router_port(mlxsw_sp
), false);
6693 err_fid_bc_flood_set
:
6694 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6695 mlxsw_sp_router_port(mlxsw_sp
), false);
6696 err_fid_mc_flood_set
:
6697 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
6701 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif
*rif
)
6703 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
6704 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6705 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6707 mlxsw_sp_fid_rif_set(fid
, NULL
);
6708 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6709 mlxsw_sp_fid_index(fid
), false);
6710 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6711 mlxsw_sp_router_port(mlxsw_sp
), false);
6712 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6713 mlxsw_sp_router_port(mlxsw_sp
), false);
6714 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
6717 static struct mlxsw_sp_fid
*
6718 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif
*rif
)
6720 u16 vid
= is_vlan_dev(rif
->dev
) ? vlan_dev_vlan_id(rif
->dev
) : 1;
6722 return mlxsw_sp_fid_8021q_get(rif
->mlxsw_sp
, vid
);
6725 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops
= {
6726 .type
= MLXSW_SP_RIF_TYPE_VLAN
,
6727 .rif_size
= sizeof(struct mlxsw_sp_rif
),
6728 .configure
= mlxsw_sp_rif_vlan_configure
,
6729 .deconfigure
= mlxsw_sp_rif_vlan_deconfigure
,
6730 .fid_get
= mlxsw_sp_rif_vlan_fid_get
,
6733 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif
*rif
)
6735 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6736 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6739 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
,
6744 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6745 mlxsw_sp_router_port(mlxsw_sp
), true);
6747 goto err_fid_mc_flood_set
;
6749 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6750 mlxsw_sp_router_port(mlxsw_sp
), true);
6752 goto err_fid_bc_flood_set
;
6754 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6755 mlxsw_sp_fid_index(rif
->fid
), true);
6757 goto err_rif_fdb_op
;
6759 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
6763 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6764 mlxsw_sp_router_port(mlxsw_sp
), false);
6765 err_fid_bc_flood_set
:
6766 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6767 mlxsw_sp_router_port(mlxsw_sp
), false);
6768 err_fid_mc_flood_set
:
6769 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
6773 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif
*rif
)
6775 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
6776 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6777 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6779 mlxsw_sp_fid_rif_set(fid
, NULL
);
6780 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
6781 mlxsw_sp_fid_index(fid
), false);
6782 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
6783 mlxsw_sp_router_port(mlxsw_sp
), false);
6784 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
6785 mlxsw_sp_router_port(mlxsw_sp
), false);
6786 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
6789 static struct mlxsw_sp_fid
*
6790 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif
*rif
)
6792 return mlxsw_sp_fid_8021d_get(rif
->mlxsw_sp
, rif
->dev
->ifindex
);
6795 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops
= {
6796 .type
= MLXSW_SP_RIF_TYPE_FID
,
6797 .rif_size
= sizeof(struct mlxsw_sp_rif
),
6798 .configure
= mlxsw_sp_rif_fid_configure
,
6799 .deconfigure
= mlxsw_sp_rif_fid_deconfigure
,
6800 .fid_get
= mlxsw_sp_rif_fid_fid_get
,
6803 static struct mlxsw_sp_rif_ipip_lb
*
6804 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif
*rif
)
6806 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
6810 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif
*rif
,
6811 const struct mlxsw_sp_rif_params
*params
)
6813 struct mlxsw_sp_rif_params_ipip_lb
*params_lb
;
6814 struct mlxsw_sp_rif_ipip_lb
*rif_lb
;
6816 params_lb
= container_of(params
, struct mlxsw_sp_rif_params_ipip_lb
,
6818 rif_lb
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6819 rif_lb
->lb_config
= params_lb
->lb_config
;
6823 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb
*lb_rif
,
6824 struct mlxsw_sp_vr
*ul_vr
, bool enable
)
6826 struct mlxsw_sp_rif_ipip_lb_config lb_cf
= lb_rif
->lb_config
;
6827 struct mlxsw_sp_rif
*rif
= &lb_rif
->common
;
6828 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6829 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6832 switch (lb_cf
.ul_protocol
) {
6833 case MLXSW_SP_L3_PROTO_IPV4
:
6834 saddr4
= be32_to_cpu(lb_cf
.saddr
.addr4
);
6835 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_LOOPBACK_IF
,
6836 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
6837 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl
, lb_cf
.lb_ipipt
,
6838 MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET
,
6839 ul_vr
->id
, saddr4
, lb_cf
.okey
);
6842 case MLXSW_SP_L3_PROTO_IPV6
:
6843 return -EAFNOSUPPORT
;
6846 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6850 mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif
*rif
)
6852 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6853 u32 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(rif
->dev
);
6854 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6855 struct mlxsw_sp_vr
*ul_vr
;
6858 ul_vr
= mlxsw_sp_vr_get(mlxsw_sp
, ul_tb_id
, NULL
);
6860 return PTR_ERR(ul_vr
);
6862 err
= mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
, true);
6864 goto err_loopback_op
;
6866 lb_rif
->ul_vr_id
= ul_vr
->id
;
6871 mlxsw_sp_vr_put(ul_vr
);
6875 static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif
*rif
)
6877 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
6878 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6879 struct mlxsw_sp_vr
*ul_vr
;
6881 ul_vr
= &mlxsw_sp
->router
->vrs
[lb_rif
->ul_vr_id
];
6882 mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
, false);
6885 mlxsw_sp_vr_put(ul_vr
);
6888 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops
= {
6889 .type
= MLXSW_SP_RIF_TYPE_IPIP_LB
,
6890 .rif_size
= sizeof(struct mlxsw_sp_rif_ipip_lb
),
6891 .setup
= mlxsw_sp_rif_ipip_lb_setup
,
6892 .configure
= mlxsw_sp_rif_ipip_lb_configure
,
6893 .deconfigure
= mlxsw_sp_rif_ipip_lb_deconfigure
,
6896 static const struct mlxsw_sp_rif_ops
*mlxsw_sp_rif_ops_arr
[] = {
6897 [MLXSW_SP_RIF_TYPE_SUBPORT
] = &mlxsw_sp_rif_subport_ops
,
6898 [MLXSW_SP_RIF_TYPE_VLAN
] = &mlxsw_sp_rif_vlan_ops
,
6899 [MLXSW_SP_RIF_TYPE_FID
] = &mlxsw_sp_rif_fid_ops
,
6900 [MLXSW_SP_RIF_TYPE_IPIP_LB
] = &mlxsw_sp_rif_ipip_lb_ops
,
6903 static int mlxsw_sp_rifs_init(struct mlxsw_sp
*mlxsw_sp
)
6905 u64 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
6907 mlxsw_sp
->router
->rifs
= kcalloc(max_rifs
,
6908 sizeof(struct mlxsw_sp_rif
*),
6910 if (!mlxsw_sp
->router
->rifs
)
6913 mlxsw_sp
->router
->rif_ops_arr
= mlxsw_sp_rif_ops_arr
;
6918 static void mlxsw_sp_rifs_fini(struct mlxsw_sp
*mlxsw_sp
)
6922 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
6923 WARN_ON_ONCE(mlxsw_sp
->router
->rifs
[i
]);
6925 kfree(mlxsw_sp
->router
->rifs
);
6929 mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp
*mlxsw_sp
)
6931 char tigcr_pl
[MLXSW_REG_TIGCR_LEN
];
6933 mlxsw_reg_tigcr_pack(tigcr_pl
, true, 0);
6934 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(tigcr
), tigcr_pl
);
6937 static int mlxsw_sp_ipips_init(struct mlxsw_sp
*mlxsw_sp
)
6939 mlxsw_sp
->router
->ipip_ops_arr
= mlxsw_sp_ipip_ops_arr
;
6940 INIT_LIST_HEAD(&mlxsw_sp
->router
->ipip_list
);
6941 return mlxsw_sp_ipip_config_tigcr(mlxsw_sp
);
6944 static void mlxsw_sp_ipips_fini(struct mlxsw_sp
*mlxsw_sp
)
6946 WARN_ON(!list_empty(&mlxsw_sp
->router
->ipip_list
));
6949 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block
*nb
)
6951 struct mlxsw_sp_router
*router
;
6953 /* Flush pending FIB notifications and then flush the device's
6954 * table before requesting another dump. The FIB notification
6955 * block is unregistered, so no need to take RTNL.
6957 mlxsw_core_flush_owq();
6958 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
6959 mlxsw_sp_router_fib_flush(router
->mlxsw_sp
);
6962 #ifdef CONFIG_IP_ROUTE_MULTIPATH
6963 static void mlxsw_sp_mp_hash_header_set(char *recr2_pl
, int header
)
6965 mlxsw_reg_recr2_outer_header_enables_set(recr2_pl
, header
, true);
6968 static void mlxsw_sp_mp_hash_field_set(char *recr2_pl
, int field
)
6970 mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl
, field
, true);
6973 static void mlxsw_sp_mp4_hash_init(char *recr2_pl
)
6975 bool only_l3
= !init_net
.ipv4
.sysctl_fib_multipath_hash_policy
;
6977 mlxsw_sp_mp_hash_header_set(recr2_pl
,
6978 MLXSW_REG_RECR2_IPV4_EN_NOT_TCP_NOT_UDP
);
6979 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_EN_TCP_UDP
);
6980 mlxsw_reg_recr2_ipv4_sip_enable(recr2_pl
);
6981 mlxsw_reg_recr2_ipv4_dip_enable(recr2_pl
);
6984 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_EN_IPV4
);
6985 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_PROTOCOL
);
6986 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_SPORT
);
6987 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_DPORT
);
6990 static void mlxsw_sp_mp6_hash_init(char *recr2_pl
)
6992 mlxsw_sp_mp_hash_header_set(recr2_pl
,
6993 MLXSW_REG_RECR2_IPV6_EN_NOT_TCP_NOT_UDP
);
6994 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_EN_TCP_UDP
);
6995 mlxsw_reg_recr2_ipv6_sip_enable(recr2_pl
);
6996 mlxsw_reg_recr2_ipv6_dip_enable(recr2_pl
);
6997 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_FLOW_LABEL
);
6998 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_NEXT_HEADER
);
7001 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
7003 char recr2_pl
[MLXSW_REG_RECR2_LEN
];
7006 get_random_bytes(&seed
, sizeof(seed
));
7007 mlxsw_reg_recr2_pack(recr2_pl
, seed
);
7008 mlxsw_sp_mp4_hash_init(recr2_pl
);
7009 mlxsw_sp_mp6_hash_init(recr2_pl
);
7011 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(recr2
), recr2_pl
);
7014 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
7020 static int __mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
7022 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
7026 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_RIFS
))
7028 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
7030 mlxsw_reg_rgcr_pack(rgcr_pl
, true, true);
7031 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl
, max_rifs
);
7032 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
7038 static void __mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
7040 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
7042 mlxsw_reg_rgcr_pack(rgcr_pl
, false, false);
7043 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
7046 int mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
7048 struct mlxsw_sp_router
*router
;
7051 router
= kzalloc(sizeof(*mlxsw_sp
->router
), GFP_KERNEL
);
7054 mlxsw_sp
->router
= router
;
7055 router
->mlxsw_sp
= mlxsw_sp
;
7057 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_neighs_list
);
7058 err
= __mlxsw_sp_router_init(mlxsw_sp
);
7060 goto err_router_init
;
7062 err
= mlxsw_sp_rifs_init(mlxsw_sp
);
7066 err
= mlxsw_sp_ipips_init(mlxsw_sp
);
7068 goto err_ipips_init
;
7070 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_ht
,
7071 &mlxsw_sp_nexthop_ht_params
);
7073 goto err_nexthop_ht_init
;
7075 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_group_ht
,
7076 &mlxsw_sp_nexthop_group_ht_params
);
7078 goto err_nexthop_group_ht_init
;
7080 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_list
);
7081 err
= mlxsw_sp_lpm_init(mlxsw_sp
);
7085 err
= mlxsw_sp_mr_init(mlxsw_sp
, &mlxsw_sp_mr_tcam_ops
);
7089 err
= mlxsw_sp_vrs_init(mlxsw_sp
);
7093 err
= mlxsw_sp_neigh_init(mlxsw_sp
);
7095 goto err_neigh_init
;
7097 mlxsw_sp
->router
->netevent_nb
.notifier_call
=
7098 mlxsw_sp_router_netevent_event
;
7099 err
= register_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7101 goto err_register_netevent_notifier
;
7103 err
= mlxsw_sp_mp_hash_init(mlxsw_sp
);
7105 goto err_mp_hash_init
;
7107 mlxsw_sp
->router
->fib_nb
.notifier_call
= mlxsw_sp_router_fib_event
;
7108 err
= register_fib_notifier(&mlxsw_sp
->router
->fib_nb
,
7109 mlxsw_sp_router_fib_dump_flush
);
7111 goto err_register_fib_notifier
;
7115 err_register_fib_notifier
:
7117 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7118 err_register_netevent_notifier
:
7119 mlxsw_sp_neigh_fini(mlxsw_sp
);
7121 mlxsw_sp_vrs_fini(mlxsw_sp
);
7123 mlxsw_sp_mr_fini(mlxsw_sp
);
7125 mlxsw_sp_lpm_fini(mlxsw_sp
);
7127 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
7128 err_nexthop_group_ht_init
:
7129 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
7130 err_nexthop_ht_init
:
7131 mlxsw_sp_ipips_fini(mlxsw_sp
);
7133 mlxsw_sp_rifs_fini(mlxsw_sp
);
7135 __mlxsw_sp_router_fini(mlxsw_sp
);
7137 kfree(mlxsw_sp
->router
);
7141 void mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
7143 unregister_fib_notifier(&mlxsw_sp
->router
->fib_nb
);
7144 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
7145 mlxsw_sp_neigh_fini(mlxsw_sp
);
7146 mlxsw_sp_vrs_fini(mlxsw_sp
);
7147 mlxsw_sp_mr_fini(mlxsw_sp
);
7148 mlxsw_sp_lpm_fini(mlxsw_sp
);
7149 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
7150 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
7151 mlxsw_sp_ipips_fini(mlxsw_sp
);
7152 mlxsw_sp_rifs_fini(mlxsw_sp
);
7153 __mlxsw_sp_router_fini(mlxsw_sp
);
7154 kfree(mlxsw_sp
->router
);