1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved */
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/rhashtable.h>
7 #include <linux/bitops.h>
9 #include <linux/notifier.h>
10 #include <linux/inetdevice.h>
11 #include <linux/netdevice.h>
12 #include <linux/if_bridge.h>
13 #include <linux/socket.h>
14 #include <linux/route.h>
15 #include <linux/gcd.h>
16 #include <linux/if_macvlan.h>
17 #include <linux/refcount.h>
18 #include <linux/jhash.h>
19 #include <linux/net_namespace.h>
20 #include <net/netevent.h>
21 #include <net/neighbour.h>
23 #include <net/ip_fib.h>
24 #include <net/ip6_fib.h>
25 #include <net/nexthop.h>
26 #include <net/fib_rules.h>
27 #include <net/ip_tunnels.h>
28 #include <net/l3mdev.h>
29 #include <net/addrconf.h>
30 #include <net/ndisc.h>
32 #include <net/fib_notifier.h>
33 #include <net/switchdev.h>
38 #include "spectrum_cnt.h"
39 #include "spectrum_dpipe.h"
40 #include "spectrum_ipip.h"
41 #include "spectrum_mr.h"
42 #include "spectrum_mr_tcam.h"
43 #include "spectrum_router.h"
44 #include "spectrum_span.h"
48 struct mlxsw_sp_lpm_tree
;
49 struct mlxsw_sp_rif_ops
;
51 struct mlxsw_sp_router
{
52 struct mlxsw_sp
*mlxsw_sp
;
53 struct mlxsw_sp_rif
**rifs
;
54 struct mlxsw_sp_vr
*vrs
;
55 struct rhashtable neigh_ht
;
56 struct rhashtable nexthop_group_ht
;
57 struct rhashtable nexthop_ht
;
58 struct list_head nexthop_list
;
60 /* One tree for each protocol: IPv4 and IPv6 */
61 struct mlxsw_sp_lpm_tree
*proto_trees
[2];
62 struct mlxsw_sp_lpm_tree
*trees
;
63 unsigned int tree_count
;
66 struct delayed_work dw
;
67 unsigned long interval
; /* ms */
69 struct delayed_work nexthop_probe_dw
;
70 #define MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL 5000 /* ms */
71 struct list_head nexthop_neighs_list
;
72 struct list_head ipip_list
;
74 struct notifier_block fib_nb
;
75 struct notifier_block netevent_nb
;
76 struct notifier_block inetaddr_nb
;
77 struct notifier_block inet6addr_nb
;
78 const struct mlxsw_sp_rif_ops
**rif_ops_arr
;
79 const struct mlxsw_sp_ipip_ops
**ipip_ops_arr
;
80 u32 adj_discard_index
;
81 bool adj_discard_index_valid
;
85 struct list_head nexthop_list
;
86 struct list_head neigh_list
;
87 struct net_device
*dev
; /* NULL for underlay RIF */
88 struct mlxsw_sp_fid
*fid
;
89 unsigned char addr
[ETH_ALEN
];
93 const struct mlxsw_sp_rif_ops
*ops
;
94 struct mlxsw_sp
*mlxsw_sp
;
96 unsigned int counter_ingress
;
97 bool counter_ingress_valid
;
98 unsigned int counter_egress
;
99 bool counter_egress_valid
;
102 struct mlxsw_sp_rif_params
{
103 struct net_device
*dev
;
112 struct mlxsw_sp_rif_subport
{
113 struct mlxsw_sp_rif common
;
114 refcount_t ref_count
;
123 struct mlxsw_sp_rif_ipip_lb
{
124 struct mlxsw_sp_rif common
;
125 struct mlxsw_sp_rif_ipip_lb_config lb_config
;
126 u16 ul_vr_id
; /* Reserved for Spectrum-2. */
127 u16 ul_rif_id
; /* Reserved for Spectrum. */
130 struct mlxsw_sp_rif_params_ipip_lb
{
131 struct mlxsw_sp_rif_params common
;
132 struct mlxsw_sp_rif_ipip_lb_config lb_config
;
135 struct mlxsw_sp_rif_ops
{
136 enum mlxsw_sp_rif_type type
;
139 void (*setup
)(struct mlxsw_sp_rif
*rif
,
140 const struct mlxsw_sp_rif_params
*params
);
141 int (*configure
)(struct mlxsw_sp_rif
*rif
);
142 void (*deconfigure
)(struct mlxsw_sp_rif
*rif
);
143 struct mlxsw_sp_fid
* (*fid_get
)(struct mlxsw_sp_rif
*rif
,
144 struct netlink_ext_ack
*extack
);
145 void (*fdb_del
)(struct mlxsw_sp_rif
*rif
, const char *mac
);
148 static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif
*rif
);
149 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree
*lpm_tree
);
150 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp
*mlxsw_sp
,
151 struct mlxsw_sp_lpm_tree
*lpm_tree
);
152 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp
*mlxsw_sp
,
153 const struct mlxsw_sp_fib
*fib
,
155 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp
*mlxsw_sp
,
156 const struct mlxsw_sp_fib
*fib
);
158 static unsigned int *
159 mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif
*rif
,
160 enum mlxsw_sp_rif_counter_dir dir
)
163 case MLXSW_SP_RIF_COUNTER_EGRESS
:
164 return &rif
->counter_egress
;
165 case MLXSW_SP_RIF_COUNTER_INGRESS
:
166 return &rif
->counter_ingress
;
172 mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif
*rif
,
173 enum mlxsw_sp_rif_counter_dir dir
)
176 case MLXSW_SP_RIF_COUNTER_EGRESS
:
177 return rif
->counter_egress_valid
;
178 case MLXSW_SP_RIF_COUNTER_INGRESS
:
179 return rif
->counter_ingress_valid
;
185 mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif
*rif
,
186 enum mlxsw_sp_rif_counter_dir dir
,
190 case MLXSW_SP_RIF_COUNTER_EGRESS
:
191 rif
->counter_egress_valid
= valid
;
193 case MLXSW_SP_RIF_COUNTER_INGRESS
:
194 rif
->counter_ingress_valid
= valid
;
199 static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
200 unsigned int counter_index
, bool enable
,
201 enum mlxsw_sp_rif_counter_dir dir
)
203 char ritr_pl
[MLXSW_REG_RITR_LEN
];
204 bool is_egress
= false;
207 if (dir
== MLXSW_SP_RIF_COUNTER_EGRESS
)
209 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
210 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
214 mlxsw_reg_ritr_counter_pack(ritr_pl
, counter_index
, enable
,
216 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
219 int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp
*mlxsw_sp
,
220 struct mlxsw_sp_rif
*rif
,
221 enum mlxsw_sp_rif_counter_dir dir
, u64
*cnt
)
223 char ricnt_pl
[MLXSW_REG_RICNT_LEN
];
224 unsigned int *p_counter_index
;
228 valid
= mlxsw_sp_rif_counter_valid_get(rif
, dir
);
232 p_counter_index
= mlxsw_sp_rif_p_counter_get(rif
, dir
);
233 if (!p_counter_index
)
235 mlxsw_reg_ricnt_pack(ricnt_pl
, *p_counter_index
,
236 MLXSW_REG_RICNT_OPCODE_NOP
);
237 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ricnt
), ricnt_pl
);
240 *cnt
= mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl
);
244 static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp
*mlxsw_sp
,
245 unsigned int counter_index
)
247 char ricnt_pl
[MLXSW_REG_RICNT_LEN
];
249 mlxsw_reg_ricnt_pack(ricnt_pl
, counter_index
,
250 MLXSW_REG_RICNT_OPCODE_CLEAR
);
251 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ricnt
), ricnt_pl
);
254 int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
255 struct mlxsw_sp_rif
*rif
,
256 enum mlxsw_sp_rif_counter_dir dir
)
258 unsigned int *p_counter_index
;
261 p_counter_index
= mlxsw_sp_rif_p_counter_get(rif
, dir
);
262 if (!p_counter_index
)
264 err
= mlxsw_sp_counter_alloc(mlxsw_sp
, MLXSW_SP_COUNTER_SUB_POOL_RIF
,
269 err
= mlxsw_sp_rif_counter_clear(mlxsw_sp
, *p_counter_index
);
271 goto err_counter_clear
;
273 err
= mlxsw_sp_rif_counter_edit(mlxsw_sp
, rif
->rif_index
,
274 *p_counter_index
, true, dir
);
276 goto err_counter_edit
;
277 mlxsw_sp_rif_counter_valid_set(rif
, dir
, true);
282 mlxsw_sp_counter_free(mlxsw_sp
, MLXSW_SP_COUNTER_SUB_POOL_RIF
,
287 void mlxsw_sp_rif_counter_free(struct mlxsw_sp
*mlxsw_sp
,
288 struct mlxsw_sp_rif
*rif
,
289 enum mlxsw_sp_rif_counter_dir dir
)
291 unsigned int *p_counter_index
;
293 if (!mlxsw_sp_rif_counter_valid_get(rif
, dir
))
296 p_counter_index
= mlxsw_sp_rif_p_counter_get(rif
, dir
);
297 if (WARN_ON(!p_counter_index
))
299 mlxsw_sp_rif_counter_edit(mlxsw_sp
, rif
->rif_index
,
300 *p_counter_index
, false, dir
);
301 mlxsw_sp_counter_free(mlxsw_sp
, MLXSW_SP_COUNTER_SUB_POOL_RIF
,
303 mlxsw_sp_rif_counter_valid_set(rif
, dir
, false);
306 static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif
*rif
)
308 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
309 struct devlink
*devlink
;
311 devlink
= priv_to_devlink(mlxsw_sp
->core
);
312 if (!devlink_dpipe_table_counter_enabled(devlink
,
313 MLXSW_SP_DPIPE_TABLE_NAME_ERIF
))
315 mlxsw_sp_rif_counter_alloc(mlxsw_sp
, rif
, MLXSW_SP_RIF_COUNTER_EGRESS
);
318 static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif
*rif
)
320 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
322 mlxsw_sp_rif_counter_free(mlxsw_sp
, rif
, MLXSW_SP_RIF_COUNTER_EGRESS
);
325 #define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1)
327 struct mlxsw_sp_prefix_usage
{
328 DECLARE_BITMAP(b
, MLXSW_SP_PREFIX_COUNT
);
331 #define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
332 for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
335 mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage
*prefix_usage1
,
336 struct mlxsw_sp_prefix_usage
*prefix_usage2
)
338 return !memcmp(prefix_usage1
, prefix_usage2
, sizeof(*prefix_usage1
));
342 mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage
*prefix_usage1
,
343 struct mlxsw_sp_prefix_usage
*prefix_usage2
)
345 memcpy(prefix_usage1
, prefix_usage2
, sizeof(*prefix_usage1
));
349 mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage
*prefix_usage
,
350 unsigned char prefix_len
)
352 set_bit(prefix_len
, prefix_usage
->b
);
356 mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage
*prefix_usage
,
357 unsigned char prefix_len
)
359 clear_bit(prefix_len
, prefix_usage
->b
);
362 struct mlxsw_sp_fib_key
{
363 unsigned char addr
[sizeof(struct in6_addr
)];
364 unsigned char prefix_len
;
367 enum mlxsw_sp_fib_entry_type
{
368 MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
,
369 MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
,
370 MLXSW_SP_FIB_ENTRY_TYPE_TRAP
,
371 MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
,
372 MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE
,
374 /* This is a special case of local delivery, where a packet should be
375 * decapsulated on reception. Note that there is no corresponding ENCAP,
376 * because that's a type of next hop, not of FIB entry. (There can be
377 * several next hops in a REMOTE entry, and some of them may be
378 * encapsulating entries.)
380 MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
,
381 MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
,
384 struct mlxsw_sp_nexthop_group
;
386 struct mlxsw_sp_fib_node
{
387 struct list_head entry_list
;
388 struct list_head list
;
389 struct rhash_head ht_node
;
390 struct mlxsw_sp_fib
*fib
;
391 struct mlxsw_sp_fib_key key
;
394 struct mlxsw_sp_fib_entry_decap
{
395 struct mlxsw_sp_ipip_entry
*ipip_entry
;
399 struct mlxsw_sp_fib_entry
{
400 struct list_head list
;
401 struct mlxsw_sp_fib_node
*fib_node
;
402 enum mlxsw_sp_fib_entry_type type
;
403 struct list_head nexthop_group_node
;
404 struct mlxsw_sp_nexthop_group
*nh_group
;
405 struct mlxsw_sp_fib_entry_decap decap
; /* Valid for decap entries. */
408 struct mlxsw_sp_fib4_entry
{
409 struct mlxsw_sp_fib_entry common
;
416 struct mlxsw_sp_fib6_entry
{
417 struct mlxsw_sp_fib_entry common
;
418 struct list_head rt6_list
;
422 struct mlxsw_sp_rt6
{
423 struct list_head list
;
424 struct fib6_info
*rt
;
427 struct mlxsw_sp_lpm_tree
{
429 unsigned int ref_count
;
430 enum mlxsw_sp_l3proto proto
;
431 unsigned long prefix_ref_count
[MLXSW_SP_PREFIX_COUNT
];
432 struct mlxsw_sp_prefix_usage prefix_usage
;
435 struct mlxsw_sp_fib
{
436 struct rhashtable ht
;
437 struct list_head node_list
;
438 struct mlxsw_sp_vr
*vr
;
439 struct mlxsw_sp_lpm_tree
*lpm_tree
;
440 enum mlxsw_sp_l3proto proto
;
444 u16 id
; /* virtual router ID */
445 u32 tb_id
; /* kernel fib table id */
446 unsigned int rif_count
;
447 struct mlxsw_sp_fib
*fib4
;
448 struct mlxsw_sp_fib
*fib6
;
449 struct mlxsw_sp_mr_table
*mr_table
[MLXSW_SP_L3_PROTO_MAX
];
450 struct mlxsw_sp_rif
*ul_rif
;
451 refcount_t ul_rif_refcnt
;
454 static const struct rhashtable_params mlxsw_sp_fib_ht_params
;
456 static struct mlxsw_sp_fib
*mlxsw_sp_fib_create(struct mlxsw_sp
*mlxsw_sp
,
457 struct mlxsw_sp_vr
*vr
,
458 enum mlxsw_sp_l3proto proto
)
460 struct mlxsw_sp_lpm_tree
*lpm_tree
;
461 struct mlxsw_sp_fib
*fib
;
464 lpm_tree
= mlxsw_sp
->router
->lpm
.proto_trees
[proto
];
465 fib
= kzalloc(sizeof(*fib
), GFP_KERNEL
);
467 return ERR_PTR(-ENOMEM
);
468 err
= rhashtable_init(&fib
->ht
, &mlxsw_sp_fib_ht_params
);
470 goto err_rhashtable_init
;
471 INIT_LIST_HEAD(&fib
->node_list
);
474 fib
->lpm_tree
= lpm_tree
;
475 mlxsw_sp_lpm_tree_hold(lpm_tree
);
476 err
= mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp
, fib
, lpm_tree
->id
);
478 goto err_lpm_tree_bind
;
482 mlxsw_sp_lpm_tree_put(mlxsw_sp
, lpm_tree
);
488 static void mlxsw_sp_fib_destroy(struct mlxsw_sp
*mlxsw_sp
,
489 struct mlxsw_sp_fib
*fib
)
491 mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp
, fib
);
492 mlxsw_sp_lpm_tree_put(mlxsw_sp
, fib
->lpm_tree
);
493 WARN_ON(!list_empty(&fib
->node_list
));
494 rhashtable_destroy(&fib
->ht
);
498 static struct mlxsw_sp_lpm_tree
*
499 mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp
*mlxsw_sp
)
501 static struct mlxsw_sp_lpm_tree
*lpm_tree
;
504 for (i
= 0; i
< mlxsw_sp
->router
->lpm
.tree_count
; i
++) {
505 lpm_tree
= &mlxsw_sp
->router
->lpm
.trees
[i
];
506 if (lpm_tree
->ref_count
== 0)
512 static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp
*mlxsw_sp
,
513 struct mlxsw_sp_lpm_tree
*lpm_tree
)
515 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
517 mlxsw_reg_ralta_pack(ralta_pl
, true,
518 (enum mlxsw_reg_ralxx_protocol
) lpm_tree
->proto
,
520 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
523 static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp
*mlxsw_sp
,
524 struct mlxsw_sp_lpm_tree
*lpm_tree
)
526 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
528 mlxsw_reg_ralta_pack(ralta_pl
, false,
529 (enum mlxsw_reg_ralxx_protocol
) lpm_tree
->proto
,
531 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
535 mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp
*mlxsw_sp
,
536 struct mlxsw_sp_prefix_usage
*prefix_usage
,
537 struct mlxsw_sp_lpm_tree
*lpm_tree
)
539 char ralst_pl
[MLXSW_REG_RALST_LEN
];
542 u8 last_prefix
= MLXSW_REG_RALST_BIN_NO_CHILD
;
544 mlxsw_sp_prefix_usage_for_each(prefix
, prefix_usage
)
547 mlxsw_reg_ralst_pack(ralst_pl
, root_bin
, lpm_tree
->id
);
548 mlxsw_sp_prefix_usage_for_each(prefix
, prefix_usage
) {
551 mlxsw_reg_ralst_bin_pack(ralst_pl
, prefix
, last_prefix
,
552 MLXSW_REG_RALST_BIN_NO_CHILD
);
553 last_prefix
= prefix
;
555 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralst
), ralst_pl
);
558 static struct mlxsw_sp_lpm_tree
*
559 mlxsw_sp_lpm_tree_create(struct mlxsw_sp
*mlxsw_sp
,
560 struct mlxsw_sp_prefix_usage
*prefix_usage
,
561 enum mlxsw_sp_l3proto proto
)
563 struct mlxsw_sp_lpm_tree
*lpm_tree
;
566 lpm_tree
= mlxsw_sp_lpm_tree_find_unused(mlxsw_sp
);
568 return ERR_PTR(-EBUSY
);
569 lpm_tree
->proto
= proto
;
570 err
= mlxsw_sp_lpm_tree_alloc(mlxsw_sp
, lpm_tree
);
574 err
= mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp
, prefix_usage
,
577 goto err_left_struct_set
;
578 memcpy(&lpm_tree
->prefix_usage
, prefix_usage
,
579 sizeof(lpm_tree
->prefix_usage
));
580 memset(&lpm_tree
->prefix_ref_count
, 0,
581 sizeof(lpm_tree
->prefix_ref_count
));
582 lpm_tree
->ref_count
= 1;
586 mlxsw_sp_lpm_tree_free(mlxsw_sp
, lpm_tree
);
590 static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp
*mlxsw_sp
,
591 struct mlxsw_sp_lpm_tree
*lpm_tree
)
593 mlxsw_sp_lpm_tree_free(mlxsw_sp
, lpm_tree
);
596 static struct mlxsw_sp_lpm_tree
*
597 mlxsw_sp_lpm_tree_get(struct mlxsw_sp
*mlxsw_sp
,
598 struct mlxsw_sp_prefix_usage
*prefix_usage
,
599 enum mlxsw_sp_l3proto proto
)
601 struct mlxsw_sp_lpm_tree
*lpm_tree
;
604 for (i
= 0; i
< mlxsw_sp
->router
->lpm
.tree_count
; i
++) {
605 lpm_tree
= &mlxsw_sp
->router
->lpm
.trees
[i
];
606 if (lpm_tree
->ref_count
!= 0 &&
607 lpm_tree
->proto
== proto
&&
608 mlxsw_sp_prefix_usage_eq(&lpm_tree
->prefix_usage
,
610 mlxsw_sp_lpm_tree_hold(lpm_tree
);
614 return mlxsw_sp_lpm_tree_create(mlxsw_sp
, prefix_usage
, proto
);
617 static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree
*lpm_tree
)
619 lpm_tree
->ref_count
++;
622 static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp
*mlxsw_sp
,
623 struct mlxsw_sp_lpm_tree
*lpm_tree
)
625 if (--lpm_tree
->ref_count
== 0)
626 mlxsw_sp_lpm_tree_destroy(mlxsw_sp
, lpm_tree
);
629 #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
631 static int mlxsw_sp_lpm_init(struct mlxsw_sp
*mlxsw_sp
)
633 struct mlxsw_sp_prefix_usage req_prefix_usage
= {{ 0 } };
634 struct mlxsw_sp_lpm_tree
*lpm_tree
;
638 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_LPM_TREES
))
641 max_trees
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_LPM_TREES
);
642 mlxsw_sp
->router
->lpm
.tree_count
= max_trees
- MLXSW_SP_LPM_TREE_MIN
;
643 mlxsw_sp
->router
->lpm
.trees
= kcalloc(mlxsw_sp
->router
->lpm
.tree_count
,
644 sizeof(struct mlxsw_sp_lpm_tree
),
646 if (!mlxsw_sp
->router
->lpm
.trees
)
649 for (i
= 0; i
< mlxsw_sp
->router
->lpm
.tree_count
; i
++) {
650 lpm_tree
= &mlxsw_sp
->router
->lpm
.trees
[i
];
651 lpm_tree
->id
= i
+ MLXSW_SP_LPM_TREE_MIN
;
654 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
655 MLXSW_SP_L3_PROTO_IPV4
);
656 if (IS_ERR(lpm_tree
)) {
657 err
= PTR_ERR(lpm_tree
);
658 goto err_ipv4_tree_get
;
660 mlxsw_sp
->router
->lpm
.proto_trees
[MLXSW_SP_L3_PROTO_IPV4
] = lpm_tree
;
662 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
663 MLXSW_SP_L3_PROTO_IPV6
);
664 if (IS_ERR(lpm_tree
)) {
665 err
= PTR_ERR(lpm_tree
);
666 goto err_ipv6_tree_get
;
668 mlxsw_sp
->router
->lpm
.proto_trees
[MLXSW_SP_L3_PROTO_IPV6
] = lpm_tree
;
673 lpm_tree
= mlxsw_sp
->router
->lpm
.proto_trees
[MLXSW_SP_L3_PROTO_IPV4
];
674 mlxsw_sp_lpm_tree_put(mlxsw_sp
, lpm_tree
);
676 kfree(mlxsw_sp
->router
->lpm
.trees
);
680 static void mlxsw_sp_lpm_fini(struct mlxsw_sp
*mlxsw_sp
)
682 struct mlxsw_sp_lpm_tree
*lpm_tree
;
684 lpm_tree
= mlxsw_sp
->router
->lpm
.proto_trees
[MLXSW_SP_L3_PROTO_IPV6
];
685 mlxsw_sp_lpm_tree_put(mlxsw_sp
, lpm_tree
);
687 lpm_tree
= mlxsw_sp
->router
->lpm
.proto_trees
[MLXSW_SP_L3_PROTO_IPV4
];
688 mlxsw_sp_lpm_tree_put(mlxsw_sp
, lpm_tree
);
690 kfree(mlxsw_sp
->router
->lpm
.trees
);
693 static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr
*vr
)
695 return !!vr
->fib4
|| !!vr
->fib6
||
696 !!vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV4
] ||
697 !!vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV6
];
700 static struct mlxsw_sp_vr
*mlxsw_sp_vr_find_unused(struct mlxsw_sp
*mlxsw_sp
)
702 struct mlxsw_sp_vr
*vr
;
705 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
706 vr
= &mlxsw_sp
->router
->vrs
[i
];
707 if (!mlxsw_sp_vr_is_used(vr
))
713 static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp
*mlxsw_sp
,
714 const struct mlxsw_sp_fib
*fib
, u8 tree_id
)
716 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
718 mlxsw_reg_raltb_pack(raltb_pl
, fib
->vr
->id
,
719 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
,
721 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
), raltb_pl
);
724 static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp
*mlxsw_sp
,
725 const struct mlxsw_sp_fib
*fib
)
727 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
729 /* Bind to tree 0 which is default */
730 mlxsw_reg_raltb_pack(raltb_pl
, fib
->vr
->id
,
731 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
, 0);
732 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
), raltb_pl
);
735 static u32
mlxsw_sp_fix_tb_id(u32 tb_id
)
737 /* For our purpose, squash main, default and local tables into one */
738 if (tb_id
== RT_TABLE_LOCAL
|| tb_id
== RT_TABLE_DEFAULT
)
739 tb_id
= RT_TABLE_MAIN
;
743 static struct mlxsw_sp_vr
*mlxsw_sp_vr_find(struct mlxsw_sp
*mlxsw_sp
,
746 struct mlxsw_sp_vr
*vr
;
749 tb_id
= mlxsw_sp_fix_tb_id(tb_id
);
751 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
752 vr
= &mlxsw_sp
->router
->vrs
[i
];
753 if (mlxsw_sp_vr_is_used(vr
) && vr
->tb_id
== tb_id
)
759 int mlxsw_sp_router_tb_id_vr_id(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
,
762 struct mlxsw_sp_vr
*vr
;
764 vr
= mlxsw_sp_vr_find(mlxsw_sp
, tb_id
);
772 static struct mlxsw_sp_fib
*mlxsw_sp_vr_fib(const struct mlxsw_sp_vr
*vr
,
773 enum mlxsw_sp_l3proto proto
)
776 case MLXSW_SP_L3_PROTO_IPV4
:
778 case MLXSW_SP_L3_PROTO_IPV6
:
784 static struct mlxsw_sp_vr
*mlxsw_sp_vr_create(struct mlxsw_sp
*mlxsw_sp
,
786 struct netlink_ext_ack
*extack
)
788 struct mlxsw_sp_mr_table
*mr4_table
, *mr6_table
;
789 struct mlxsw_sp_fib
*fib4
;
790 struct mlxsw_sp_fib
*fib6
;
791 struct mlxsw_sp_vr
*vr
;
794 vr
= mlxsw_sp_vr_find_unused(mlxsw_sp
);
796 NL_SET_ERR_MSG_MOD(extack
, "Exceeded number of supported virtual routers");
797 return ERR_PTR(-EBUSY
);
799 fib4
= mlxsw_sp_fib_create(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV4
);
801 return ERR_CAST(fib4
);
802 fib6
= mlxsw_sp_fib_create(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV6
);
805 goto err_fib6_create
;
807 mr4_table
= mlxsw_sp_mr_table_create(mlxsw_sp
, vr
->id
,
808 MLXSW_SP_L3_PROTO_IPV4
);
809 if (IS_ERR(mr4_table
)) {
810 err
= PTR_ERR(mr4_table
);
811 goto err_mr4_table_create
;
813 mr6_table
= mlxsw_sp_mr_table_create(mlxsw_sp
, vr
->id
,
814 MLXSW_SP_L3_PROTO_IPV6
);
815 if (IS_ERR(mr6_table
)) {
816 err
= PTR_ERR(mr6_table
);
817 goto err_mr6_table_create
;
822 vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV4
] = mr4_table
;
823 vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV6
] = mr6_table
;
827 err_mr6_table_create
:
828 mlxsw_sp_mr_table_destroy(mr4_table
);
829 err_mr4_table_create
:
830 mlxsw_sp_fib_destroy(mlxsw_sp
, fib6
);
832 mlxsw_sp_fib_destroy(mlxsw_sp
, fib4
);
836 static void mlxsw_sp_vr_destroy(struct mlxsw_sp
*mlxsw_sp
,
837 struct mlxsw_sp_vr
*vr
)
839 mlxsw_sp_mr_table_destroy(vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV6
]);
840 vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV6
] = NULL
;
841 mlxsw_sp_mr_table_destroy(vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV4
]);
842 vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV4
] = NULL
;
843 mlxsw_sp_fib_destroy(mlxsw_sp
, vr
->fib6
);
845 mlxsw_sp_fib_destroy(mlxsw_sp
, vr
->fib4
);
849 static struct mlxsw_sp_vr
*mlxsw_sp_vr_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
,
850 struct netlink_ext_ack
*extack
)
852 struct mlxsw_sp_vr
*vr
;
854 tb_id
= mlxsw_sp_fix_tb_id(tb_id
);
855 vr
= mlxsw_sp_vr_find(mlxsw_sp
, tb_id
);
857 vr
= mlxsw_sp_vr_create(mlxsw_sp
, tb_id
, extack
);
861 static void mlxsw_sp_vr_put(struct mlxsw_sp
*mlxsw_sp
, struct mlxsw_sp_vr
*vr
)
863 if (!vr
->rif_count
&& list_empty(&vr
->fib4
->node_list
) &&
864 list_empty(&vr
->fib6
->node_list
) &&
865 mlxsw_sp_mr_table_empty(vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV4
]) &&
866 mlxsw_sp_mr_table_empty(vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV6
]))
867 mlxsw_sp_vr_destroy(mlxsw_sp
, vr
);
871 mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr
*vr
,
872 enum mlxsw_sp_l3proto proto
, u8 tree_id
)
874 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
876 if (!mlxsw_sp_vr_is_used(vr
))
878 if (fib
->lpm_tree
->id
== tree_id
)
883 static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp
*mlxsw_sp
,
884 struct mlxsw_sp_fib
*fib
,
885 struct mlxsw_sp_lpm_tree
*new_tree
)
887 struct mlxsw_sp_lpm_tree
*old_tree
= fib
->lpm_tree
;
890 fib
->lpm_tree
= new_tree
;
891 mlxsw_sp_lpm_tree_hold(new_tree
);
892 err
= mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp
, fib
, new_tree
->id
);
895 mlxsw_sp_lpm_tree_put(mlxsw_sp
, old_tree
);
899 mlxsw_sp_lpm_tree_put(mlxsw_sp
, new_tree
);
900 fib
->lpm_tree
= old_tree
;
904 static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp
*mlxsw_sp
,
905 struct mlxsw_sp_fib
*fib
,
906 struct mlxsw_sp_lpm_tree
*new_tree
)
908 enum mlxsw_sp_l3proto proto
= fib
->proto
;
909 struct mlxsw_sp_lpm_tree
*old_tree
;
910 u8 old_id
, new_id
= new_tree
->id
;
911 struct mlxsw_sp_vr
*vr
;
914 old_tree
= mlxsw_sp
->router
->lpm
.proto_trees
[proto
];
915 old_id
= old_tree
->id
;
917 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
918 vr
= &mlxsw_sp
->router
->vrs
[i
];
919 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr
, proto
, old_id
))
921 err
= mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp
,
922 mlxsw_sp_vr_fib(vr
, proto
),
925 goto err_tree_replace
;
928 memcpy(new_tree
->prefix_ref_count
, old_tree
->prefix_ref_count
,
929 sizeof(new_tree
->prefix_ref_count
));
930 mlxsw_sp
->router
->lpm
.proto_trees
[proto
] = new_tree
;
931 mlxsw_sp_lpm_tree_put(mlxsw_sp
, old_tree
);
936 for (i
--; i
>= 0; i
--) {
937 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr
, proto
, new_id
))
939 mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp
,
940 mlxsw_sp_vr_fib(vr
, proto
),
946 static int mlxsw_sp_vrs_init(struct mlxsw_sp
*mlxsw_sp
)
948 struct mlxsw_sp_vr
*vr
;
952 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_VRS
))
955 max_vrs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
);
956 mlxsw_sp
->router
->vrs
= kcalloc(max_vrs
, sizeof(struct mlxsw_sp_vr
),
958 if (!mlxsw_sp
->router
->vrs
)
961 for (i
= 0; i
< max_vrs
; i
++) {
962 vr
= &mlxsw_sp
->router
->vrs
[i
];
969 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
);
971 static void mlxsw_sp_vrs_fini(struct mlxsw_sp
*mlxsw_sp
)
973 /* At this stage we're guaranteed not to have new incoming
974 * FIB notifications and the work queue is free from FIBs
975 * sitting on top of mlxsw netdevs. However, we can still
976 * have other FIBs queued. Flush the queue before flushing
977 * the device's tables. No need for locks, as we're the only
980 mlxsw_core_flush_owq();
981 mlxsw_sp_router_fib_flush(mlxsw_sp
);
982 kfree(mlxsw_sp
->router
->vrs
);
985 static struct net_device
*
986 __mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device
*ol_dev
)
988 struct ip_tunnel
*tun
= netdev_priv(ol_dev
);
989 struct net
*net
= dev_net(ol_dev
);
991 return __dev_get_by_index(net
, tun
->parms
.link
);
994 u32
mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device
*ol_dev
)
996 struct net_device
*d
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
999 return l3mdev_fib_table(d
) ? : RT_TABLE_MAIN
;
1001 return RT_TABLE_MAIN
;
1004 static struct mlxsw_sp_rif
*
1005 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
1006 const struct mlxsw_sp_rif_params
*params
,
1007 struct netlink_ext_ack
*extack
);
1009 static struct mlxsw_sp_rif_ipip_lb
*
1010 mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp
*mlxsw_sp
,
1011 enum mlxsw_sp_ipip_type ipipt
,
1012 struct net_device
*ol_dev
,
1013 struct netlink_ext_ack
*extack
)
1015 struct mlxsw_sp_rif_params_ipip_lb lb_params
;
1016 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1017 struct mlxsw_sp_rif
*rif
;
1019 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
1020 lb_params
= (struct mlxsw_sp_rif_params_ipip_lb
) {
1021 .common
.dev
= ol_dev
,
1022 .common
.lag
= false,
1023 .lb_config
= ipip_ops
->ol_loopback_config(mlxsw_sp
, ol_dev
),
1026 rif
= mlxsw_sp_rif_create(mlxsw_sp
, &lb_params
.common
, extack
);
1028 return ERR_CAST(rif
);
1029 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
1032 static struct mlxsw_sp_ipip_entry
*
1033 mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp
*mlxsw_sp
,
1034 enum mlxsw_sp_ipip_type ipipt
,
1035 struct net_device
*ol_dev
)
1037 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1038 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1039 struct mlxsw_sp_ipip_entry
*ret
= NULL
;
1041 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
1042 ipip_entry
= kzalloc(sizeof(*ipip_entry
), GFP_KERNEL
);
1044 return ERR_PTR(-ENOMEM
);
1046 ipip_entry
->ol_lb
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
, ipipt
,
1048 if (IS_ERR(ipip_entry
->ol_lb
)) {
1049 ret
= ERR_CAST(ipip_entry
->ol_lb
);
1050 goto err_ol_ipip_lb_create
;
1053 ipip_entry
->ipipt
= ipipt
;
1054 ipip_entry
->ol_dev
= ol_dev
;
1056 switch (ipip_ops
->ul_proto
) {
1057 case MLXSW_SP_L3_PROTO_IPV4
:
1058 ipip_entry
->parms4
= mlxsw_sp_ipip_netdev_parms4(ol_dev
);
1060 case MLXSW_SP_L3_PROTO_IPV6
:
1067 err_ol_ipip_lb_create
:
1073 mlxsw_sp_ipip_entry_dealloc(struct mlxsw_sp_ipip_entry
*ipip_entry
)
1075 mlxsw_sp_rif_destroy(&ipip_entry
->ol_lb
->common
);
1080 mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp
*mlxsw_sp
,
1081 const enum mlxsw_sp_l3proto ul_proto
,
1082 union mlxsw_sp_l3addr saddr
,
1084 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1086 u32 tun_ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry
->ol_dev
);
1087 enum mlxsw_sp_ipip_type ipipt
= ipip_entry
->ipipt
;
1088 union mlxsw_sp_l3addr tun_saddr
;
1090 if (mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
!= ul_proto
)
1093 tun_saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ipip_entry
->ol_dev
);
1094 return tun_ul_tb_id
== ul_tb_id
&&
1095 mlxsw_sp_l3addr_eq(&tun_saddr
, &saddr
);
1099 mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp
*mlxsw_sp
,
1100 struct mlxsw_sp_fib_entry
*fib_entry
,
1101 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1106 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
,
1111 ipip_entry
->decap_fib_entry
= fib_entry
;
1112 fib_entry
->decap
.ipip_entry
= ipip_entry
;
1113 fib_entry
->decap
.tunnel_index
= tunnel_index
;
1117 static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp
*mlxsw_sp
,
1118 struct mlxsw_sp_fib_entry
*fib_entry
)
1120 /* Unlink this node from the IPIP entry that it's the decap entry of. */
1121 fib_entry
->decap
.ipip_entry
->decap_fib_entry
= NULL
;
1122 fib_entry
->decap
.ipip_entry
= NULL
;
1123 mlxsw_sp_kvdl_free(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
,
1124 1, fib_entry
->decap
.tunnel_index
);
1127 static struct mlxsw_sp_fib_node
*
1128 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
1129 size_t addr_len
, unsigned char prefix_len
);
1130 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
1131 struct mlxsw_sp_fib_entry
*fib_entry
);
1134 mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp
*mlxsw_sp
,
1135 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1137 struct mlxsw_sp_fib_entry
*fib_entry
= ipip_entry
->decap_fib_entry
;
1139 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, fib_entry
);
1140 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
1142 mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
1146 mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp
*mlxsw_sp
,
1147 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1148 struct mlxsw_sp_fib_entry
*decap_fib_entry
)
1150 if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp
, decap_fib_entry
,
1153 decap_fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
1155 if (mlxsw_sp_fib_entry_update(mlxsw_sp
, decap_fib_entry
))
1156 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1159 static struct mlxsw_sp_fib_entry
*
1160 mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
,
1161 enum mlxsw_sp_l3proto proto
,
1162 const union mlxsw_sp_l3addr
*addr
,
1163 enum mlxsw_sp_fib_entry_type type
)
1165 struct mlxsw_sp_fib_entry
*fib_entry
;
1166 struct mlxsw_sp_fib_node
*fib_node
;
1167 unsigned char addr_prefix_len
;
1168 struct mlxsw_sp_fib
*fib
;
1169 struct mlxsw_sp_vr
*vr
;
1174 vr
= mlxsw_sp_vr_find(mlxsw_sp
, tb_id
);
1177 fib
= mlxsw_sp_vr_fib(vr
, proto
);
1180 case MLXSW_SP_L3_PROTO_IPV4
:
1181 addr4
= be32_to_cpu(addr
->addr4
);
1184 addr_prefix_len
= 32;
1186 case MLXSW_SP_L3_PROTO_IPV6
: /* fall through */
1192 fib_node
= mlxsw_sp_fib_node_lookup(fib
, addrp
, addr_len
,
1194 if (!fib_node
|| list_empty(&fib_node
->entry_list
))
1197 fib_entry
= list_first_entry(&fib_node
->entry_list
,
1198 struct mlxsw_sp_fib_entry
, list
);
1199 if (fib_entry
->type
!= type
)
1205 /* Given an IPIP entry, find the corresponding decap route. */
1206 static struct mlxsw_sp_fib_entry
*
1207 mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp
*mlxsw_sp
,
1208 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1210 static struct mlxsw_sp_fib_node
*fib_node
;
1211 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1212 struct mlxsw_sp_fib_entry
*fib_entry
;
1213 unsigned char saddr_prefix_len
;
1214 union mlxsw_sp_l3addr saddr
;
1215 struct mlxsw_sp_fib
*ul_fib
;
1216 struct mlxsw_sp_vr
*ul_vr
;
1222 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1224 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry
->ol_dev
);
1225 ul_vr
= mlxsw_sp_vr_find(mlxsw_sp
, ul_tb_id
);
1229 ul_fib
= mlxsw_sp_vr_fib(ul_vr
, ipip_ops
->ul_proto
);
1230 saddr
= mlxsw_sp_ipip_netdev_saddr(ipip_ops
->ul_proto
,
1231 ipip_entry
->ol_dev
);
1233 switch (ipip_ops
->ul_proto
) {
1234 case MLXSW_SP_L3_PROTO_IPV4
:
1235 saddr4
= be32_to_cpu(saddr
.addr4
);
1238 saddr_prefix_len
= 32;
1240 case MLXSW_SP_L3_PROTO_IPV6
:
1245 fib_node
= mlxsw_sp_fib_node_lookup(ul_fib
, saddrp
, saddr_len
,
1247 if (!fib_node
|| list_empty(&fib_node
->entry_list
))
1250 fib_entry
= list_first_entry(&fib_node
->entry_list
,
1251 struct mlxsw_sp_fib_entry
, list
);
1252 if (fib_entry
->type
!= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
)
1258 static struct mlxsw_sp_ipip_entry
*
1259 mlxsw_sp_ipip_entry_create(struct mlxsw_sp
*mlxsw_sp
,
1260 enum mlxsw_sp_ipip_type ipipt
,
1261 struct net_device
*ol_dev
)
1263 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1265 ipip_entry
= mlxsw_sp_ipip_entry_alloc(mlxsw_sp
, ipipt
, ol_dev
);
1266 if (IS_ERR(ipip_entry
))
1269 list_add_tail(&ipip_entry
->ipip_list_node
,
1270 &mlxsw_sp
->router
->ipip_list
);
1276 mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
1277 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1279 list_del(&ipip_entry
->ipip_list_node
);
1280 mlxsw_sp_ipip_entry_dealloc(ipip_entry
);
1284 mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp
*mlxsw_sp
,
1285 const struct net_device
*ul_dev
,
1286 enum mlxsw_sp_l3proto ul_proto
,
1287 union mlxsw_sp_l3addr ul_dip
,
1288 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1290 u32 ul_tb_id
= l3mdev_fib_table(ul_dev
) ? : RT_TABLE_MAIN
;
1291 enum mlxsw_sp_ipip_type ipipt
= ipip_entry
->ipipt
;
1293 if (mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
!= ul_proto
)
1296 return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, ul_dip
,
1297 ul_tb_id
, ipip_entry
);
1300 /* Given decap parameters, find the corresponding IPIP entry. */
1301 static struct mlxsw_sp_ipip_entry
*
1302 mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp
*mlxsw_sp
,
1303 const struct net_device
*ul_dev
,
1304 enum mlxsw_sp_l3proto ul_proto
,
1305 union mlxsw_sp_l3addr ul_dip
)
1307 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1309 list_for_each_entry(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1311 if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp
, ul_dev
,
1319 static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
1320 const struct net_device
*dev
,
1321 enum mlxsw_sp_ipip_type
*p_type
)
1323 struct mlxsw_sp_router
*router
= mlxsw_sp
->router
;
1324 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1325 enum mlxsw_sp_ipip_type ipipt
;
1327 for (ipipt
= 0; ipipt
< MLXSW_SP_IPIP_TYPE_MAX
; ++ipipt
) {
1328 ipip_ops
= router
->ipip_ops_arr
[ipipt
];
1329 if (dev
->type
== ipip_ops
->dev_type
) {
1338 bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp
*mlxsw_sp
,
1339 const struct net_device
*dev
)
1341 return mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
);
1344 static struct mlxsw_sp_ipip_entry
*
1345 mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp
*mlxsw_sp
,
1346 const struct net_device
*ol_dev
)
1348 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1350 list_for_each_entry(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1352 if (ipip_entry
->ol_dev
== ol_dev
)
1358 static struct mlxsw_sp_ipip_entry
*
1359 mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp
*mlxsw_sp
,
1360 const struct net_device
*ul_dev
,
1361 struct mlxsw_sp_ipip_entry
*start
)
1363 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1365 ipip_entry
= list_prepare_entry(start
, &mlxsw_sp
->router
->ipip_list
,
1367 list_for_each_entry_continue(ipip_entry
, &mlxsw_sp
->router
->ipip_list
,
1369 struct net_device
*ipip_ul_dev
=
1370 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1372 if (ipip_ul_dev
== ul_dev
)
1379 bool mlxsw_sp_netdev_is_ipip_ul(const struct mlxsw_sp
*mlxsw_sp
,
1380 const struct net_device
*dev
)
1382 return mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
, dev
, NULL
);
1385 static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp
*mlxsw_sp
,
1386 const struct net_device
*ol_dev
,
1387 enum mlxsw_sp_ipip_type ipipt
)
1389 const struct mlxsw_sp_ipip_ops
*ops
1390 = mlxsw_sp
->router
->ipip_ops_arr
[ipipt
];
1392 /* For deciding whether decap should be offloaded, we don't care about
1393 * overlay protocol, so ask whether either one is supported.
1395 return ops
->can_offload(mlxsw_sp
, ol_dev
, MLXSW_SP_L3_PROTO_IPV4
) ||
1396 ops
->can_offload(mlxsw_sp
, ol_dev
, MLXSW_SP_L3_PROTO_IPV6
);
1399 static int mlxsw_sp_netdevice_ipip_ol_reg_event(struct mlxsw_sp
*mlxsw_sp
,
1400 struct net_device
*ol_dev
)
1402 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1403 enum mlxsw_sp_l3proto ul_proto
;
1404 enum mlxsw_sp_ipip_type ipipt
;
1405 union mlxsw_sp_l3addr saddr
;
1408 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, ol_dev
, &ipipt
);
1409 if (mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
, ipipt
)) {
1410 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(ol_dev
);
1411 ul_proto
= mlxsw_sp
->router
->ipip_ops_arr
[ipipt
]->ul_proto
;
1412 saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ol_dev
);
1413 if (!mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp
, ul_proto
,
1416 ipip_entry
= mlxsw_sp_ipip_entry_create(mlxsw_sp
, ipipt
,
1418 if (IS_ERR(ipip_entry
))
1419 return PTR_ERR(ipip_entry
);
1426 static void mlxsw_sp_netdevice_ipip_ol_unreg_event(struct mlxsw_sp
*mlxsw_sp
,
1427 struct net_device
*ol_dev
)
1429 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1431 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1433 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1437 mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp
*mlxsw_sp
,
1438 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1440 struct mlxsw_sp_fib_entry
*decap_fib_entry
;
1442 decap_fib_entry
= mlxsw_sp_ipip_entry_find_decap(mlxsw_sp
, ipip_entry
);
1443 if (decap_fib_entry
)
1444 mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp
, ipip_entry
,
1449 mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb
*lb_rif
, u16 ul_vr_id
,
1450 u16 ul_rif_id
, bool enable
)
1452 struct mlxsw_sp_rif_ipip_lb_config lb_cf
= lb_rif
->lb_config
;
1453 struct mlxsw_sp_rif
*rif
= &lb_rif
->common
;
1454 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
1455 char ritr_pl
[MLXSW_REG_RITR_LEN
];
1458 switch (lb_cf
.ul_protocol
) {
1459 case MLXSW_SP_L3_PROTO_IPV4
:
1460 saddr4
= be32_to_cpu(lb_cf
.saddr
.addr4
);
1461 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_LOOPBACK_IF
,
1462 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
1463 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl
, lb_cf
.lb_ipipt
,
1464 MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET
,
1465 ul_vr_id
, ul_rif_id
, saddr4
, lb_cf
.okey
);
1468 case MLXSW_SP_L3_PROTO_IPV6
:
1469 return -EAFNOSUPPORT
;
1472 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
1475 static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp
*mlxsw_sp
,
1476 struct net_device
*ol_dev
)
1478 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1479 struct mlxsw_sp_rif_ipip_lb
*lb_rif
;
1482 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1484 lb_rif
= ipip_entry
->ol_lb
;
1485 err
= mlxsw_sp_rif_ipip_lb_op(lb_rif
, lb_rif
->ul_vr_id
,
1486 lb_rif
->ul_rif_id
, true);
1489 lb_rif
->common
.mtu
= ol_dev
->mtu
;
1496 static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp
*mlxsw_sp
,
1497 struct net_device
*ol_dev
)
1499 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1501 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1503 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1507 mlxsw_sp_ipip_entry_ol_down_event(struct mlxsw_sp
*mlxsw_sp
,
1508 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1510 if (ipip_entry
->decap_fib_entry
)
1511 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1514 static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp
*mlxsw_sp
,
1515 struct net_device
*ol_dev
)
1517 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1519 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1521 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1524 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp
*mlxsw_sp
,
1525 struct mlxsw_sp_rif
*old_rif
,
1526 struct mlxsw_sp_rif
*new_rif
);
1528 mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp
*mlxsw_sp
,
1529 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1531 struct netlink_ext_ack
*extack
)
1533 struct mlxsw_sp_rif_ipip_lb
*old_lb_rif
= ipip_entry
->ol_lb
;
1534 struct mlxsw_sp_rif_ipip_lb
*new_lb_rif
;
1536 new_lb_rif
= mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp
,
1540 if (IS_ERR(new_lb_rif
))
1541 return PTR_ERR(new_lb_rif
);
1542 ipip_entry
->ol_lb
= new_lb_rif
;
1545 mlxsw_sp_nexthop_rif_migrate(mlxsw_sp
, &old_lb_rif
->common
,
1546 &new_lb_rif
->common
);
1548 mlxsw_sp_rif_destroy(&old_lb_rif
->common
);
1553 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
1554 struct mlxsw_sp_rif
*rif
);
1557 * Update the offload related to an IPIP entry. This always updates decap, and
1558 * in addition to that it also:
1559 * @recreate_loopback: recreates the associated loopback RIF
1560 * @keep_encap: updates next hops that use the tunnel netdevice. This is only
1561 * relevant when recreate_loopback is true.
1562 * @update_nexthops: updates next hops, keeping the current loopback RIF. This
1563 * is only relevant when recreate_loopback is false.
1565 int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1566 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1567 bool recreate_loopback
,
1569 bool update_nexthops
,
1570 struct netlink_ext_ack
*extack
)
1574 /* RIFs can't be edited, so to update loopback, we need to destroy and
1575 * recreate it. That creates a window of opportunity where RALUE and
1576 * RATR registers end up referencing a RIF that's already gone. RATRs
1577 * are handled in mlxsw_sp_ipip_entry_ol_lb_update(), and to take care
1578 * of RALUE, demote the decap route back.
1580 if (ipip_entry
->decap_fib_entry
)
1581 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp
, ipip_entry
);
1583 if (recreate_loopback
) {
1584 err
= mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp
, ipip_entry
,
1585 keep_encap
, extack
);
1588 } else if (update_nexthops
) {
1589 mlxsw_sp_nexthop_rif_update(mlxsw_sp
,
1590 &ipip_entry
->ol_lb
->common
);
1593 if (ipip_entry
->ol_dev
->flags
& IFF_UP
)
1594 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp
, ipip_entry
);
1599 static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1600 struct net_device
*ol_dev
,
1601 struct netlink_ext_ack
*extack
)
1603 struct mlxsw_sp_ipip_entry
*ipip_entry
=
1604 mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1609 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1610 true, false, false, extack
);
1614 mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp
*mlxsw_sp
,
1615 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1616 struct net_device
*ul_dev
,
1618 struct netlink_ext_ack
*extack
)
1620 u32 ul_tb_id
= l3mdev_fib_table(ul_dev
) ? : RT_TABLE_MAIN
;
1621 enum mlxsw_sp_l3proto ul_proto
;
1622 union mlxsw_sp_l3addr saddr
;
1624 /* Moving underlay to a different VRF might cause local address
1625 * conflict, and the conflicting tunnels need to be demoted.
1627 ul_proto
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
]->ul_proto
;
1628 saddr
= mlxsw_sp_ipip_netdev_saddr(ul_proto
, ipip_entry
->ol_dev
);
1629 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp
, ul_proto
,
1632 *demote_this
= true;
1636 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1637 true, true, false, extack
);
1641 mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp
*mlxsw_sp
,
1642 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1643 struct net_device
*ul_dev
)
1645 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1646 false, false, true, NULL
);
1650 mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp
*mlxsw_sp
,
1651 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1652 struct net_device
*ul_dev
)
1654 /* A down underlay device causes encapsulated packets to not be
1655 * forwarded, but decap still works. So refresh next hops without
1656 * touching anything else.
1658 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp
, ipip_entry
,
1659 false, false, true, NULL
);
1663 mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp
*mlxsw_sp
,
1664 struct net_device
*ol_dev
,
1665 struct netlink_ext_ack
*extack
)
1667 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
1668 struct mlxsw_sp_ipip_entry
*ipip_entry
;
1671 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, ol_dev
);
1673 /* A change might make a tunnel eligible for offloading, but
1674 * that is currently not implemented. What falls to slow path
1679 /* A change might make a tunnel not eligible for offloading. */
1680 if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp
, ol_dev
,
1681 ipip_entry
->ipipt
)) {
1682 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1686 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
1687 err
= ipip_ops
->ol_netdev_change(mlxsw_sp
, ipip_entry
, extack
);
1691 void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp
*mlxsw_sp
,
1692 struct mlxsw_sp_ipip_entry
*ipip_entry
)
1694 struct net_device
*ol_dev
= ipip_entry
->ol_dev
;
1696 if (ol_dev
->flags
& IFF_UP
)
1697 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp
, ipip_entry
);
1698 mlxsw_sp_ipip_entry_destroy(mlxsw_sp
, ipip_entry
);
1701 /* The configuration where several tunnels have the same local address in the
1702 * same underlay table needs special treatment in the HW. That is currently not
1703 * implemented in the driver. This function finds and demotes the first tunnel
1704 * with a given source address, except the one passed in in the argument
1708 mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp
*mlxsw_sp
,
1709 enum mlxsw_sp_l3proto ul_proto
,
1710 union mlxsw_sp_l3addr saddr
,
1712 const struct mlxsw_sp_ipip_entry
*except
)
1714 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1716 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1718 if (ipip_entry
!= except
&&
1719 mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp
, ul_proto
, saddr
,
1720 ul_tb_id
, ipip_entry
)) {
1721 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1729 static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp
*mlxsw_sp
,
1730 struct net_device
*ul_dev
)
1732 struct mlxsw_sp_ipip_entry
*ipip_entry
, *tmp
;
1734 list_for_each_entry_safe(ipip_entry
, tmp
, &mlxsw_sp
->router
->ipip_list
,
1736 struct net_device
*ipip_ul_dev
=
1737 __mlxsw_sp_ipip_netdev_ul_dev_get(ipip_entry
->ol_dev
);
1739 if (ipip_ul_dev
== ul_dev
)
1740 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1744 int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp
*mlxsw_sp
,
1745 struct net_device
*ol_dev
,
1746 unsigned long event
,
1747 struct netdev_notifier_info
*info
)
1749 struct netdev_notifier_changeupper_info
*chup
;
1750 struct netlink_ext_ack
*extack
;
1753 case NETDEV_REGISTER
:
1754 return mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp
, ol_dev
);
1755 case NETDEV_UNREGISTER
:
1756 mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp
, ol_dev
);
1759 mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp
, ol_dev
);
1762 mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp
, ol_dev
);
1764 case NETDEV_CHANGEUPPER
:
1765 chup
= container_of(info
, typeof(*chup
), info
);
1766 extack
= info
->extack
;
1767 if (netif_is_l3_master(chup
->upper_dev
))
1768 return mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp
,
1773 extack
= info
->extack
;
1774 return mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp
,
1776 case NETDEV_CHANGEMTU
:
1777 return mlxsw_sp_netdevice_ipip_ol_update_mtu(mlxsw_sp
, ol_dev
);
1783 __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1784 struct mlxsw_sp_ipip_entry
*ipip_entry
,
1785 struct net_device
*ul_dev
,
1787 unsigned long event
,
1788 struct netdev_notifier_info
*info
)
1790 struct netdev_notifier_changeupper_info
*chup
;
1791 struct netlink_ext_ack
*extack
;
1794 case NETDEV_CHANGEUPPER
:
1795 chup
= container_of(info
, typeof(*chup
), info
);
1796 extack
= info
->extack
;
1797 if (netif_is_l3_master(chup
->upper_dev
))
1798 return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp
,
1806 return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp
, ipip_entry
,
1809 return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp
,
1817 mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp
*mlxsw_sp
,
1818 struct net_device
*ul_dev
,
1819 unsigned long event
,
1820 struct netdev_notifier_info
*info
)
1822 struct mlxsw_sp_ipip_entry
*ipip_entry
= NULL
;
1825 while ((ipip_entry
= mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp
,
1828 struct mlxsw_sp_ipip_entry
*prev
;
1829 bool demote_this
= false;
1831 err
= __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp
, ipip_entry
,
1832 ul_dev
, &demote_this
,
1835 mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp
,
1841 if (list_is_first(&ipip_entry
->ipip_list_node
,
1842 &mlxsw_sp
->router
->ipip_list
))
1845 /* This can't be cached from previous iteration,
1846 * because that entry could be gone now.
1848 prev
= list_prev_entry(ipip_entry
,
1850 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp
, ipip_entry
);
1858 int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp
*mlxsw_sp
, u32 ul_tb_id
,
1859 enum mlxsw_sp_l3proto ul_proto
,
1860 const union mlxsw_sp_l3addr
*ul_sip
,
1863 enum mlxsw_sp_fib_entry_type type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
1864 struct mlxsw_sp_fib_entry
*fib_entry
;
1867 /* It is valid to create a tunnel with a local IP and only later
1868 * assign this IP address to a local interface
1870 fib_entry
= mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp
, ul_tb_id
,
1876 fib_entry
->decap
.tunnel_index
= tunnel_index
;
1877 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
;
1879 err
= mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
1881 goto err_fib_entry_update
;
1885 err_fib_entry_update
:
1886 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
1887 mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
1891 void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp
*mlxsw_sp
, u32 ul_tb_id
,
1892 enum mlxsw_sp_l3proto ul_proto
,
1893 const union mlxsw_sp_l3addr
*ul_sip
)
1895 enum mlxsw_sp_fib_entry_type type
= MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
;
1896 struct mlxsw_sp_fib_entry
*fib_entry
;
1898 fib_entry
= mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp
, ul_tb_id
,
1904 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
1905 mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
1908 struct mlxsw_sp_neigh_key
{
1909 struct neighbour
*n
;
1912 struct mlxsw_sp_neigh_entry
{
1913 struct list_head rif_list_node
;
1914 struct rhash_head ht_node
;
1915 struct mlxsw_sp_neigh_key key
;
1918 unsigned char ha
[ETH_ALEN
];
1919 struct list_head nexthop_list
; /* list of nexthops using
1922 struct list_head nexthop_neighs_list_node
;
1923 unsigned int counter_index
;
1927 static const struct rhashtable_params mlxsw_sp_neigh_ht_params
= {
1928 .key_offset
= offsetof(struct mlxsw_sp_neigh_entry
, key
),
1929 .head_offset
= offsetof(struct mlxsw_sp_neigh_entry
, ht_node
),
1930 .key_len
= sizeof(struct mlxsw_sp_neigh_key
),
1933 struct mlxsw_sp_neigh_entry
*
1934 mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif
*rif
,
1935 struct mlxsw_sp_neigh_entry
*neigh_entry
)
1938 if (list_empty(&rif
->neigh_list
))
1941 return list_first_entry(&rif
->neigh_list
,
1942 typeof(*neigh_entry
),
1945 if (list_is_last(&neigh_entry
->rif_list_node
, &rif
->neigh_list
))
1947 return list_next_entry(neigh_entry
, rif_list_node
);
1950 int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1952 return neigh_entry
->key
.n
->tbl
->family
;
1956 mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1958 return neigh_entry
->ha
;
1961 u32
mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1963 struct neighbour
*n
;
1965 n
= neigh_entry
->key
.n
;
1966 return ntohl(*((__be32
*) n
->primary_key
));
1970 mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry
*neigh_entry
)
1972 struct neighbour
*n
;
1974 n
= neigh_entry
->key
.n
;
1975 return (struct in6_addr
*) &n
->primary_key
;
1978 int mlxsw_sp_neigh_counter_get(struct mlxsw_sp
*mlxsw_sp
,
1979 struct mlxsw_sp_neigh_entry
*neigh_entry
,
1982 if (!neigh_entry
->counter_valid
)
1985 return mlxsw_sp_flow_counter_get(mlxsw_sp
, neigh_entry
->counter_index
,
1989 static struct mlxsw_sp_neigh_entry
*
1990 mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
,
1993 struct mlxsw_sp_neigh_entry
*neigh_entry
;
1995 neigh_entry
= kzalloc(sizeof(*neigh_entry
), GFP_KERNEL
);
1999 neigh_entry
->key
.n
= n
;
2000 neigh_entry
->rif
= rif
;
2001 INIT_LIST_HEAD(&neigh_entry
->nexthop_list
);
2006 static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry
*neigh_entry
)
2012 mlxsw_sp_neigh_entry_insert(struct mlxsw_sp
*mlxsw_sp
,
2013 struct mlxsw_sp_neigh_entry
*neigh_entry
)
2015 return rhashtable_insert_fast(&mlxsw_sp
->router
->neigh_ht
,
2016 &neigh_entry
->ht_node
,
2017 mlxsw_sp_neigh_ht_params
);
2021 mlxsw_sp_neigh_entry_remove(struct mlxsw_sp
*mlxsw_sp
,
2022 struct mlxsw_sp_neigh_entry
*neigh_entry
)
2024 rhashtable_remove_fast(&mlxsw_sp
->router
->neigh_ht
,
2025 &neigh_entry
->ht_node
,
2026 mlxsw_sp_neigh_ht_params
);
2030 mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp
*mlxsw_sp
,
2031 struct mlxsw_sp_neigh_entry
*neigh_entry
)
2033 struct devlink
*devlink
;
2034 const char *table_name
;
2036 switch (mlxsw_sp_neigh_entry_type(neigh_entry
)) {
2038 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST4
;
2041 table_name
= MLXSW_SP_DPIPE_TABLE_NAME_HOST6
;
2048 devlink
= priv_to_devlink(mlxsw_sp
->core
);
2049 return devlink_dpipe_table_counter_enabled(devlink
, table_name
);
2053 mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
2054 struct mlxsw_sp_neigh_entry
*neigh_entry
)
2056 if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp
, neigh_entry
))
2059 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &neigh_entry
->counter_index
))
2062 neigh_entry
->counter_valid
= true;
2066 mlxsw_sp_neigh_counter_free(struct mlxsw_sp
*mlxsw_sp
,
2067 struct mlxsw_sp_neigh_entry
*neigh_entry
)
2069 if (!neigh_entry
->counter_valid
)
2071 mlxsw_sp_flow_counter_free(mlxsw_sp
,
2072 neigh_entry
->counter_index
);
2073 neigh_entry
->counter_valid
= false;
2076 static struct mlxsw_sp_neigh_entry
*
2077 mlxsw_sp_neigh_entry_create(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
2079 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2080 struct mlxsw_sp_rif
*rif
;
2083 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, n
->dev
);
2085 return ERR_PTR(-EINVAL
);
2087 neigh_entry
= mlxsw_sp_neigh_entry_alloc(mlxsw_sp
, n
, rif
->rif_index
);
2089 return ERR_PTR(-ENOMEM
);
2091 err
= mlxsw_sp_neigh_entry_insert(mlxsw_sp
, neigh_entry
);
2093 goto err_neigh_entry_insert
;
2095 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
2096 list_add(&neigh_entry
->rif_list_node
, &rif
->neigh_list
);
2100 err_neigh_entry_insert
:
2101 mlxsw_sp_neigh_entry_free(neigh_entry
);
2102 return ERR_PTR(err
);
2106 mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
2107 struct mlxsw_sp_neigh_entry
*neigh_entry
)
2109 list_del(&neigh_entry
->rif_list_node
);
2110 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
2111 mlxsw_sp_neigh_entry_remove(mlxsw_sp
, neigh_entry
);
2112 mlxsw_sp_neigh_entry_free(neigh_entry
);
2115 static struct mlxsw_sp_neigh_entry
*
2116 mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp
*mlxsw_sp
, struct neighbour
*n
)
2118 struct mlxsw_sp_neigh_key key
;
2121 return rhashtable_lookup_fast(&mlxsw_sp
->router
->neigh_ht
,
2122 &key
, mlxsw_sp_neigh_ht_params
);
2126 mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp
*mlxsw_sp
)
2128 unsigned long interval
;
2130 #if IS_ENABLED(CONFIG_IPV6)
2131 interval
= min_t(unsigned long,
2132 NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
),
2133 NEIGH_VAR(&nd_tbl
.parms
, DELAY_PROBE_TIME
));
2135 interval
= NEIGH_VAR(&arp_tbl
.parms
, DELAY_PROBE_TIME
);
2137 mlxsw_sp
->router
->neighs_update
.interval
= jiffies_to_msecs(interval
);
2140 static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
2144 struct net_device
*dev
;
2145 struct neighbour
*n
;
2150 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl
, ent_index
, &rif
, &dip
);
2152 if (!mlxsw_sp
->router
->rifs
[rif
]) {
2153 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
2158 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
2159 n
= neigh_lookup(&arp_tbl
, &dipn
, dev
);
2163 netdev_dbg(dev
, "Updating neighbour with IP=%pI4h\n", &dip
);
2164 neigh_event_send(n
, NULL
);
2168 #if IS_ENABLED(CONFIG_IPV6)
2169 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
2173 struct net_device
*dev
;
2174 struct neighbour
*n
;
2175 struct in6_addr dip
;
2178 mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl
, rec_index
, &rif
,
2181 if (!mlxsw_sp
->router
->rifs
[rif
]) {
2182 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Incorrect RIF in neighbour entry\n");
2186 dev
= mlxsw_sp
->router
->rifs
[rif
]->dev
;
2187 n
= neigh_lookup(&nd_tbl
, &dip
, dev
);
2191 netdev_dbg(dev
, "Updating neighbour with IP=%pI6c\n", &dip
);
2192 neigh_event_send(n
, NULL
);
2196 static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
2203 static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp
*mlxsw_sp
,
2210 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
2212 /* Hardware starts counting at 0, so add 1. */
2215 /* Each record consists of several neighbour entries. */
2216 for (i
= 0; i
< num_entries
; i
++) {
2219 ent_index
= rec_index
* MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
+ i
;
2220 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2226 static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp
*mlxsw_sp
,
2230 /* One record contains one entry. */
2231 mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2235 static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp
*mlxsw_sp
,
2236 char *rauhtd_pl
, int rec_index
)
2238 switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, rec_index
)) {
2239 case MLXSW_REG_RAUHTD_TYPE_IPV4
:
2240 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp
, rauhtd_pl
,
2243 case MLXSW_REG_RAUHTD_TYPE_IPV6
:
2244 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp
, rauhtd_pl
,
2250 static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl
)
2252 u8 num_rec
, last_rec_index
, num_entries
;
2254 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2255 last_rec_index
= num_rec
- 1;
2257 if (num_rec
< MLXSW_REG_RAUHTD_REC_MAX_NUM
)
2259 if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl
, last_rec_index
) ==
2260 MLXSW_REG_RAUHTD_TYPE_IPV6
)
2263 num_entries
= mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl
,
2265 if (++num_entries
== MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC
)
2271 __mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
,
2273 enum mlxsw_reg_rauhtd_type type
)
2278 /* Make sure the neighbour's netdev isn't removed in the
2283 mlxsw_reg_rauhtd_pack(rauhtd_pl
, type
);
2284 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(rauhtd
),
2287 dev_err_ratelimited(mlxsw_sp
->bus_info
->dev
, "Failed to dump neighbour table\n");
2290 num_rec
= mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl
);
2291 for (i
= 0; i
< num_rec
; i
++)
2292 mlxsw_sp_router_neigh_rec_process(mlxsw_sp
, rauhtd_pl
,
2294 } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl
));
2300 static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp
*mlxsw_sp
)
2302 enum mlxsw_reg_rauhtd_type type
;
2306 rauhtd_pl
= kmalloc(MLXSW_REG_RAUHTD_LEN
, GFP_KERNEL
);
2310 type
= MLXSW_REG_RAUHTD_TYPE_IPV4
;
2311 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2315 type
= MLXSW_REG_RAUHTD_TYPE_IPV6
;
2316 err
= __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp
, rauhtd_pl
, type
);
2322 static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp
*mlxsw_sp
)
2324 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2326 /* Take RTNL mutex here to prevent lists from changes */
2328 list_for_each_entry(neigh_entry
, &mlxsw_sp
->router
->nexthop_neighs_list
,
2329 nexthop_neighs_list_node
)
2330 /* If this neigh have nexthops, make the kernel think this neigh
2331 * is active regardless of the traffic.
2333 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2338 mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp
*mlxsw_sp
)
2340 unsigned long interval
= mlxsw_sp
->router
->neighs_update
.interval
;
2342 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
,
2343 msecs_to_jiffies(interval
));
2346 static void mlxsw_sp_router_neighs_update_work(struct work_struct
*work
)
2348 struct mlxsw_sp_router
*router
;
2351 router
= container_of(work
, struct mlxsw_sp_router
,
2352 neighs_update
.dw
.work
);
2353 err
= mlxsw_sp_router_neighs_update_rauhtd(router
->mlxsw_sp
);
2355 dev_err(router
->mlxsw_sp
->bus_info
->dev
, "Could not update kernel for neigh activity");
2357 mlxsw_sp_router_neighs_update_nh(router
->mlxsw_sp
);
2359 mlxsw_sp_router_neighs_update_work_schedule(router
->mlxsw_sp
);
2362 static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct
*work
)
2364 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2365 struct mlxsw_sp_router
*router
;
2367 router
= container_of(work
, struct mlxsw_sp_router
,
2368 nexthop_probe_dw
.work
);
2369 /* Iterate over nexthop neighbours, find those who are unresolved and
2370 * send arp on them. This solves the chicken-egg problem when
2371 * the nexthop wouldn't get offloaded until the neighbor is resolved
2372 * but it wouldn't get resolved ever in case traffic is flowing in HW
2373 * using different nexthop.
2375 * Take RTNL mutex here to prevent lists from changes.
2378 list_for_each_entry(neigh_entry
, &router
->nexthop_neighs_list
,
2379 nexthop_neighs_list_node
)
2380 if (!neigh_entry
->connected
)
2381 neigh_event_send(neigh_entry
->key
.n
, NULL
);
2384 mlxsw_core_schedule_dw(&router
->nexthop_probe_dw
,
2385 MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL
);
2389 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
2390 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2391 bool removing
, bool dead
);
2393 static enum mlxsw_reg_rauht_op
mlxsw_sp_rauht_op(bool adding
)
2395 return adding
? MLXSW_REG_RAUHT_OP_WRITE_ADD
:
2396 MLXSW_REG_RAUHT_OP_WRITE_DELETE
;
2400 mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp
*mlxsw_sp
,
2401 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2402 enum mlxsw_reg_rauht_op op
)
2404 struct neighbour
*n
= neigh_entry
->key
.n
;
2405 u32 dip
= ntohl(*((__be32
*) n
->primary_key
));
2406 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2408 mlxsw_reg_rauht_pack4(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2410 if (neigh_entry
->counter_valid
)
2411 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2412 neigh_entry
->counter_index
);
2413 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2417 mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp
*mlxsw_sp
,
2418 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2419 enum mlxsw_reg_rauht_op op
)
2421 struct neighbour
*n
= neigh_entry
->key
.n
;
2422 char rauht_pl
[MLXSW_REG_RAUHT_LEN
];
2423 const char *dip
= n
->primary_key
;
2425 mlxsw_reg_rauht_pack6(rauht_pl
, op
, neigh_entry
->rif
, neigh_entry
->ha
,
2427 if (neigh_entry
->counter_valid
)
2428 mlxsw_reg_rauht_pack_counter(rauht_pl
,
2429 neigh_entry
->counter_index
);
2430 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rauht
), rauht_pl
);
2433 bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry
*neigh_entry
)
2435 struct neighbour
*n
= neigh_entry
->key
.n
;
2437 /* Packets with a link-local destination address are trapped
2438 * after LPM lookup and never reach the neighbour table, so
2439 * there is no need to program such neighbours to the device.
2441 if (ipv6_addr_type((struct in6_addr
*) &n
->primary_key
) &
2442 IPV6_ADDR_LINKLOCAL
)
2448 mlxsw_sp_neigh_entry_update(struct mlxsw_sp
*mlxsw_sp
,
2449 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2452 enum mlxsw_reg_rauht_op op
= mlxsw_sp_rauht_op(adding
);
2455 if (!adding
&& !neigh_entry
->connected
)
2457 neigh_entry
->connected
= adding
;
2458 if (neigh_entry
->key
.n
->tbl
->family
== AF_INET
) {
2459 err
= mlxsw_sp_router_neigh_entry_op4(mlxsw_sp
, neigh_entry
,
2463 } else if (neigh_entry
->key
.n
->tbl
->family
== AF_INET6
) {
2464 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry
))
2466 err
= mlxsw_sp_router_neigh_entry_op6(mlxsw_sp
, neigh_entry
,
2476 neigh_entry
->key
.n
->flags
|= NTF_OFFLOADED
;
2478 neigh_entry
->key
.n
->flags
&= ~NTF_OFFLOADED
;
2482 mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp
*mlxsw_sp
,
2483 struct mlxsw_sp_neigh_entry
*neigh_entry
,
2487 mlxsw_sp_neigh_counter_alloc(mlxsw_sp
, neigh_entry
);
2489 mlxsw_sp_neigh_counter_free(mlxsw_sp
, neigh_entry
);
2490 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, true);
2493 struct mlxsw_sp_netevent_work
{
2494 struct work_struct work
;
2495 struct mlxsw_sp
*mlxsw_sp
;
2496 struct neighbour
*n
;
2499 static void mlxsw_sp_router_neigh_event_work(struct work_struct
*work
)
2501 struct mlxsw_sp_netevent_work
*net_work
=
2502 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2503 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2504 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2505 struct neighbour
*n
= net_work
->n
;
2506 unsigned char ha
[ETH_ALEN
];
2507 bool entry_connected
;
2510 /* If these parameters are changed after we release the lock,
2511 * then we are guaranteed to receive another event letting us
2514 read_lock_bh(&n
->lock
);
2515 memcpy(ha
, n
->ha
, ETH_ALEN
);
2516 nud_state
= n
->nud_state
;
2518 read_unlock_bh(&n
->lock
);
2521 mlxsw_sp_span_respin(mlxsw_sp
);
2523 entry_connected
= nud_state
& NUD_VALID
&& !dead
;
2524 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
2525 if (!entry_connected
&& !neigh_entry
)
2528 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
2529 if (IS_ERR(neigh_entry
))
2533 memcpy(neigh_entry
->ha
, ha
, ETH_ALEN
);
2534 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, entry_connected
);
2535 mlxsw_sp_nexthop_neigh_update(mlxsw_sp
, neigh_entry
, !entry_connected
,
2538 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
2539 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2547 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
);
2549 static void mlxsw_sp_router_mp_hash_event_work(struct work_struct
*work
)
2551 struct mlxsw_sp_netevent_work
*net_work
=
2552 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2553 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2555 mlxsw_sp_mp_hash_init(mlxsw_sp
);
2559 static int __mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
);
2561 static void mlxsw_sp_router_update_priority_work(struct work_struct
*work
)
2563 struct mlxsw_sp_netevent_work
*net_work
=
2564 container_of(work
, struct mlxsw_sp_netevent_work
, work
);
2565 struct mlxsw_sp
*mlxsw_sp
= net_work
->mlxsw_sp
;
2567 __mlxsw_sp_router_init(mlxsw_sp
);
2571 static int mlxsw_sp_router_schedule_work(struct net
*net
,
2572 struct notifier_block
*nb
,
2573 void (*cb
)(struct work_struct
*))
2575 struct mlxsw_sp_netevent_work
*net_work
;
2576 struct mlxsw_sp_router
*router
;
2578 router
= container_of(nb
, struct mlxsw_sp_router
, netevent_nb
);
2579 if (!net_eq(net
, mlxsw_sp_net(router
->mlxsw_sp
)))
2582 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2586 INIT_WORK(&net_work
->work
, cb
);
2587 net_work
->mlxsw_sp
= router
->mlxsw_sp
;
2588 mlxsw_core_schedule_work(&net_work
->work
);
2592 static int mlxsw_sp_router_netevent_event(struct notifier_block
*nb
,
2593 unsigned long event
, void *ptr
)
2595 struct mlxsw_sp_netevent_work
*net_work
;
2596 struct mlxsw_sp_port
*mlxsw_sp_port
;
2597 struct mlxsw_sp
*mlxsw_sp
;
2598 unsigned long interval
;
2599 struct neigh_parms
*p
;
2600 struct neighbour
*n
;
2603 case NETEVENT_DELAY_PROBE_TIME_UPDATE
:
2606 /* We don't care about changes in the default table. */
2607 if (!p
->dev
|| (p
->tbl
->family
!= AF_INET
&&
2608 p
->tbl
->family
!= AF_INET6
))
2611 /* We are in atomic context and can't take RTNL mutex,
2612 * so use RCU variant to walk the device chain.
2614 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(p
->dev
);
2618 mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2619 interval
= jiffies_to_msecs(NEIGH_VAR(p
, DELAY_PROBE_TIME
));
2620 mlxsw_sp
->router
->neighs_update
.interval
= interval
;
2622 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2624 case NETEVENT_NEIGH_UPDATE
:
2627 if (n
->tbl
->family
!= AF_INET
&& n
->tbl
->family
!= AF_INET6
)
2630 mlxsw_sp_port
= mlxsw_sp_port_lower_dev_hold(n
->dev
);
2634 net_work
= kzalloc(sizeof(*net_work
), GFP_ATOMIC
);
2636 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2640 INIT_WORK(&net_work
->work
, mlxsw_sp_router_neigh_event_work
);
2641 net_work
->mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
2644 /* Take a reference to ensure the neighbour won't be
2645 * destructed until we drop the reference in delayed
2649 mlxsw_core_schedule_work(&net_work
->work
);
2650 mlxsw_sp_port_dev_put(mlxsw_sp_port
);
2652 case NETEVENT_IPV4_MPATH_HASH_UPDATE
:
2653 case NETEVENT_IPV6_MPATH_HASH_UPDATE
:
2654 return mlxsw_sp_router_schedule_work(ptr
, nb
,
2655 mlxsw_sp_router_mp_hash_event_work
);
2657 case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE
:
2658 return mlxsw_sp_router_schedule_work(ptr
, nb
,
2659 mlxsw_sp_router_update_priority_work
);
2665 static int mlxsw_sp_neigh_init(struct mlxsw_sp
*mlxsw_sp
)
2669 err
= rhashtable_init(&mlxsw_sp
->router
->neigh_ht
,
2670 &mlxsw_sp_neigh_ht_params
);
2674 /* Initialize the polling interval according to the default
2677 mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp
);
2679 /* Create the delayed works for the activity_update */
2680 INIT_DELAYED_WORK(&mlxsw_sp
->router
->neighs_update
.dw
,
2681 mlxsw_sp_router_neighs_update_work
);
2682 INIT_DELAYED_WORK(&mlxsw_sp
->router
->nexthop_probe_dw
,
2683 mlxsw_sp_router_probe_unresolved_nexthops
);
2684 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->neighs_update
.dw
, 0);
2685 mlxsw_core_schedule_dw(&mlxsw_sp
->router
->nexthop_probe_dw
, 0);
2689 static void mlxsw_sp_neigh_fini(struct mlxsw_sp
*mlxsw_sp
)
2691 cancel_delayed_work_sync(&mlxsw_sp
->router
->neighs_update
.dw
);
2692 cancel_delayed_work_sync(&mlxsw_sp
->router
->nexthop_probe_dw
);
2693 rhashtable_destroy(&mlxsw_sp
->router
->neigh_ht
);
2696 static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
2697 struct mlxsw_sp_rif
*rif
)
2699 struct mlxsw_sp_neigh_entry
*neigh_entry
, *tmp
;
2701 list_for_each_entry_safe(neigh_entry
, tmp
, &rif
->neigh_list
,
2703 mlxsw_sp_neigh_entry_update(mlxsw_sp
, neigh_entry
, false);
2704 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
2708 enum mlxsw_sp_nexthop_type
{
2709 MLXSW_SP_NEXTHOP_TYPE_ETH
,
2710 MLXSW_SP_NEXTHOP_TYPE_IPIP
,
2713 struct mlxsw_sp_nexthop_key
{
2714 struct fib_nh
*fib_nh
;
2717 struct mlxsw_sp_nexthop
{
2718 struct list_head neigh_list_node
; /* member of neigh entry list */
2719 struct list_head rif_list_node
;
2720 struct list_head router_list_node
;
2721 struct mlxsw_sp_nexthop_group
*nh_grp
; /* pointer back to the group
2724 struct rhash_head ht_node
;
2725 struct mlxsw_sp_nexthop_key key
;
2726 unsigned char gw_addr
[sizeof(struct in6_addr
)];
2730 int num_adj_entries
;
2731 struct mlxsw_sp_rif
*rif
;
2732 u8 should_offload
:1, /* set indicates this neigh is connected and
2733 * should be put to KVD linear area of this group.
2735 offloaded
:1, /* set in case the neigh is actually put into
2736 * KVD linear area of this group.
2738 update
:1; /* set indicates that MAC of this neigh should be
2741 enum mlxsw_sp_nexthop_type type
;
2743 struct mlxsw_sp_neigh_entry
*neigh_entry
;
2744 struct mlxsw_sp_ipip_entry
*ipip_entry
;
2746 unsigned int counter_index
;
2750 struct mlxsw_sp_nexthop_group
{
2752 struct rhash_head ht_node
;
2753 struct list_head fib_list
; /* list of fib entries that use this group */
2754 struct neigh_table
*neigh_tbl
;
2755 u8 adj_index_valid
:1,
2756 gateway
:1; /* routes using the group use a gateway */
2760 int sum_norm_weight
;
2761 struct mlxsw_sp_nexthop nexthops
[0];
2762 #define nh_rif nexthops[0].rif
2765 void mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp
*mlxsw_sp
,
2766 struct mlxsw_sp_nexthop
*nh
)
2768 struct devlink
*devlink
;
2770 devlink
= priv_to_devlink(mlxsw_sp
->core
);
2771 if (!devlink_dpipe_table_counter_enabled(devlink
,
2772 MLXSW_SP_DPIPE_TABLE_NAME_ADJ
))
2775 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp
, &nh
->counter_index
))
2778 nh
->counter_valid
= true;
2781 void mlxsw_sp_nexthop_counter_free(struct mlxsw_sp
*mlxsw_sp
,
2782 struct mlxsw_sp_nexthop
*nh
)
2784 if (!nh
->counter_valid
)
2786 mlxsw_sp_flow_counter_free(mlxsw_sp
, nh
->counter_index
);
2787 nh
->counter_valid
= false;
2790 int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp
*mlxsw_sp
,
2791 struct mlxsw_sp_nexthop
*nh
, u64
*p_counter
)
2793 if (!nh
->counter_valid
)
2796 return mlxsw_sp_flow_counter_get(mlxsw_sp
, nh
->counter_index
,
2800 struct mlxsw_sp_nexthop
*mlxsw_sp_nexthop_next(struct mlxsw_sp_router
*router
,
2801 struct mlxsw_sp_nexthop
*nh
)
2804 if (list_empty(&router
->nexthop_list
))
2807 return list_first_entry(&router
->nexthop_list
,
2808 typeof(*nh
), router_list_node
);
2810 if (list_is_last(&nh
->router_list_node
, &router
->nexthop_list
))
2812 return list_next_entry(nh
, router_list_node
);
2815 bool mlxsw_sp_nexthop_offload(struct mlxsw_sp_nexthop
*nh
)
2817 return nh
->offloaded
;
2820 unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop
*nh
)
2824 return nh
->neigh_entry
->ha
;
2827 int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop
*nh
, u32
*p_adj_index
,
2828 u32
*p_adj_size
, u32
*p_adj_hash_index
)
2830 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2831 u32 adj_hash_index
= 0;
2834 if (!nh
->offloaded
|| !nh_grp
->adj_index_valid
)
2837 *p_adj_index
= nh_grp
->adj_index
;
2838 *p_adj_size
= nh_grp
->ecmp_size
;
2840 for (i
= 0; i
< nh_grp
->count
; i
++) {
2841 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2845 if (nh_iter
->offloaded
)
2846 adj_hash_index
+= nh_iter
->num_adj_entries
;
2849 *p_adj_hash_index
= adj_hash_index
;
2853 struct mlxsw_sp_rif
*mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop
*nh
)
2858 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop
*nh
)
2860 struct mlxsw_sp_nexthop_group
*nh_grp
= nh
->nh_grp
;
2863 for (i
= 0; i
< nh_grp
->count
; i
++) {
2864 struct mlxsw_sp_nexthop
*nh_iter
= &nh_grp
->nexthops
[i
];
2866 if (nh_iter
->type
== MLXSW_SP_NEXTHOP_TYPE_IPIP
)
2872 static struct fib_info
*
2873 mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2875 return nh_grp
->priv
;
2878 struct mlxsw_sp_nexthop_group_cmp_arg
{
2879 enum mlxsw_sp_l3proto proto
;
2881 struct fib_info
*fi
;
2882 struct mlxsw_sp_fib6_entry
*fib6_entry
;
2887 mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2888 const struct in6_addr
*gw
, int ifindex
,
2893 for (i
= 0; i
< nh_grp
->count
; i
++) {
2894 const struct mlxsw_sp_nexthop
*nh
;
2896 nh
= &nh_grp
->nexthops
[i
];
2897 if (nh
->ifindex
== ifindex
&& nh
->nh_weight
== weight
&&
2898 ipv6_addr_equal(gw
, (struct in6_addr
*) nh
->gw_addr
))
2906 mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group
*nh_grp
,
2907 const struct mlxsw_sp_fib6_entry
*fib6_entry
)
2909 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2911 if (nh_grp
->count
!= fib6_entry
->nrt6
)
2914 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2915 struct fib6_nh
*fib6_nh
= mlxsw_sp_rt6
->rt
->fib6_nh
;
2916 struct in6_addr
*gw
;
2917 int ifindex
, weight
;
2919 ifindex
= fib6_nh
->fib_nh_dev
->ifindex
;
2920 weight
= fib6_nh
->fib_nh_weight
;
2921 gw
= &fib6_nh
->fib_nh_gw6
;
2922 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp
, gw
, ifindex
,
2931 mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg
*arg
, const void *ptr
)
2933 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= arg
->key
;
2934 const struct mlxsw_sp_nexthop_group
*nh_grp
= ptr
;
2936 switch (cmp_arg
->proto
) {
2937 case MLXSW_SP_L3_PROTO_IPV4
:
2938 return cmp_arg
->fi
!= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2939 case MLXSW_SP_L3_PROTO_IPV6
:
2940 return !mlxsw_sp_nexthop6_group_cmp(nh_grp
,
2941 cmp_arg
->fib6_entry
);
2949 mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group
*nh_grp
)
2951 return nh_grp
->neigh_tbl
->family
;
2954 static u32
mlxsw_sp_nexthop_group_hash_obj(const void *data
, u32 len
, u32 seed
)
2956 const struct mlxsw_sp_nexthop_group
*nh_grp
= data
;
2957 const struct mlxsw_sp_nexthop
*nh
;
2958 struct fib_info
*fi
;
2962 switch (mlxsw_sp_nexthop_group_type(nh_grp
)) {
2964 fi
= mlxsw_sp_nexthop4_group_fi(nh_grp
);
2965 return jhash(&fi
, sizeof(fi
), seed
);
2967 val
= nh_grp
->count
;
2968 for (i
= 0; i
< nh_grp
->count
; i
++) {
2969 nh
= &nh_grp
->nexthops
[i
];
2970 val
^= jhash(&nh
->ifindex
, sizeof(nh
->ifindex
), seed
);
2972 return jhash(&val
, sizeof(val
), seed
);
2980 mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry
*fib6_entry
, u32 seed
)
2982 unsigned int val
= fib6_entry
->nrt6
;
2983 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
2984 struct net_device
*dev
;
2986 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
2987 dev
= mlxsw_sp_rt6
->rt
->fib6_nh
->fib_nh_dev
;
2988 val
^= jhash(&dev
->ifindex
, sizeof(dev
->ifindex
), seed
);
2991 return jhash(&val
, sizeof(val
), seed
);
2995 mlxsw_sp_nexthop_group_hash(const void *data
, u32 len
, u32 seed
)
2997 const struct mlxsw_sp_nexthop_group_cmp_arg
*cmp_arg
= data
;
2999 switch (cmp_arg
->proto
) {
3000 case MLXSW_SP_L3_PROTO_IPV4
:
3001 return jhash(&cmp_arg
->fi
, sizeof(cmp_arg
->fi
), seed
);
3002 case MLXSW_SP_L3_PROTO_IPV6
:
3003 return mlxsw_sp_nexthop6_group_hash(cmp_arg
->fib6_entry
, seed
);
3010 static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params
= {
3011 .head_offset
= offsetof(struct mlxsw_sp_nexthop_group
, ht_node
),
3012 .hashfn
= mlxsw_sp_nexthop_group_hash
,
3013 .obj_hashfn
= mlxsw_sp_nexthop_group_hash_obj
,
3014 .obj_cmpfn
= mlxsw_sp_nexthop_group_cmp
,
3017 static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp
*mlxsw_sp
,
3018 struct mlxsw_sp_nexthop_group
*nh_grp
)
3020 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
3024 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
3026 mlxsw_sp_nexthop_group_ht_params
);
3029 static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp
*mlxsw_sp
,
3030 struct mlxsw_sp_nexthop_group
*nh_grp
)
3032 if (mlxsw_sp_nexthop_group_type(nh_grp
) == AF_INET6
&&
3036 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
3038 mlxsw_sp_nexthop_group_ht_params
);
3041 static struct mlxsw_sp_nexthop_group
*
3042 mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
3043 struct fib_info
*fi
)
3045 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
3047 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV4
;
3049 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
3051 mlxsw_sp_nexthop_group_ht_params
);
3054 static struct mlxsw_sp_nexthop_group
*
3055 mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp
*mlxsw_sp
,
3056 struct mlxsw_sp_fib6_entry
*fib6_entry
)
3058 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg
;
3060 cmp_arg
.proto
= MLXSW_SP_L3_PROTO_IPV6
;
3061 cmp_arg
.fib6_entry
= fib6_entry
;
3062 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_group_ht
,
3064 mlxsw_sp_nexthop_group_ht_params
);
3067 static const struct rhashtable_params mlxsw_sp_nexthop_ht_params
= {
3068 .key_offset
= offsetof(struct mlxsw_sp_nexthop
, key
),
3069 .head_offset
= offsetof(struct mlxsw_sp_nexthop
, ht_node
),
3070 .key_len
= sizeof(struct mlxsw_sp_nexthop_key
),
3073 static int mlxsw_sp_nexthop_insert(struct mlxsw_sp
*mlxsw_sp
,
3074 struct mlxsw_sp_nexthop
*nh
)
3076 return rhashtable_insert_fast(&mlxsw_sp
->router
->nexthop_ht
,
3077 &nh
->ht_node
, mlxsw_sp_nexthop_ht_params
);
3080 static void mlxsw_sp_nexthop_remove(struct mlxsw_sp
*mlxsw_sp
,
3081 struct mlxsw_sp_nexthop
*nh
)
3083 rhashtable_remove_fast(&mlxsw_sp
->router
->nexthop_ht
, &nh
->ht_node
,
3084 mlxsw_sp_nexthop_ht_params
);
3087 static struct mlxsw_sp_nexthop
*
3088 mlxsw_sp_nexthop_lookup(struct mlxsw_sp
*mlxsw_sp
,
3089 struct mlxsw_sp_nexthop_key key
)
3091 return rhashtable_lookup_fast(&mlxsw_sp
->router
->nexthop_ht
, &key
,
3092 mlxsw_sp_nexthop_ht_params
);
3095 static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp
*mlxsw_sp
,
3096 const struct mlxsw_sp_fib
*fib
,
3097 u32 adj_index
, u16 ecmp_size
,
3101 char raleu_pl
[MLXSW_REG_RALEU_LEN
];
3103 mlxsw_reg_raleu_pack(raleu_pl
,
3104 (enum mlxsw_reg_ralxx_protocol
) fib
->proto
,
3105 fib
->vr
->id
, adj_index
, ecmp_size
, new_adj_index
,
3107 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raleu
), raleu_pl
);
3110 static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp
*mlxsw_sp
,
3111 struct mlxsw_sp_nexthop_group
*nh_grp
,
3112 u32 old_adj_index
, u16 old_ecmp_size
)
3114 struct mlxsw_sp_fib_entry
*fib_entry
;
3115 struct mlxsw_sp_fib
*fib
= NULL
;
3118 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
3119 if (fib
== fib_entry
->fib_node
->fib
)
3121 fib
= fib_entry
->fib_node
->fib
;
3122 err
= mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp
, fib
,
3133 static int __mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
3134 struct mlxsw_sp_nexthop
*nh
)
3136 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
3137 char ratr_pl
[MLXSW_REG_RATR_LEN
];
3139 mlxsw_reg_ratr_pack(ratr_pl
, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY
,
3140 true, MLXSW_REG_RATR_TYPE_ETHERNET
,
3141 adj_index
, neigh_entry
->rif
);
3142 mlxsw_reg_ratr_eth_entry_pack(ratr_pl
, neigh_entry
->ha
);
3143 if (nh
->counter_valid
)
3144 mlxsw_reg_ratr_counter_pack(ratr_pl
, nh
->counter_index
, true);
3146 mlxsw_reg_ratr_counter_pack(ratr_pl
, 0, false);
3148 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ratr
), ratr_pl
);
3151 int mlxsw_sp_nexthop_update(struct mlxsw_sp
*mlxsw_sp
, u32 adj_index
,
3152 struct mlxsw_sp_nexthop
*nh
)
3156 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
3159 err
= __mlxsw_sp_nexthop_update(mlxsw_sp
, adj_index
+ i
, nh
);
3167 static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
3169 struct mlxsw_sp_nexthop
*nh
)
3171 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3173 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[nh
->ipip_entry
->ipipt
];
3174 return ipip_ops
->nexthop_update(mlxsw_sp
, adj_index
, nh
->ipip_entry
);
3177 static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp
*mlxsw_sp
,
3179 struct mlxsw_sp_nexthop
*nh
)
3183 for (i
= 0; i
< nh
->num_adj_entries
; i
++) {
3186 err
= __mlxsw_sp_nexthop_ipip_update(mlxsw_sp
, adj_index
+ i
,
3196 mlxsw_sp_nexthop_group_update(struct mlxsw_sp
*mlxsw_sp
,
3197 struct mlxsw_sp_nexthop_group
*nh_grp
,
3200 u32 adj_index
= nh_grp
->adj_index
; /* base */
3201 struct mlxsw_sp_nexthop
*nh
;
3205 for (i
= 0; i
< nh_grp
->count
; i
++) {
3206 nh
= &nh_grp
->nexthops
[i
];
3208 if (!nh
->should_offload
) {
3213 if (nh
->update
|| reallocate
) {
3215 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3216 err
= mlxsw_sp_nexthop_update
3217 (mlxsw_sp
, adj_index
, nh
);
3219 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3220 err
= mlxsw_sp_nexthop_ipip_update
3221 (mlxsw_sp
, adj_index
, nh
);
3229 adj_index
+= nh
->num_adj_entries
;
3235 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
3236 const struct mlxsw_sp_fib_entry
*fib_entry
);
3239 mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp
*mlxsw_sp
,
3240 struct mlxsw_sp_nexthop_group
*nh_grp
)
3242 struct mlxsw_sp_fib_entry
*fib_entry
;
3245 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
3246 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
3249 err
= mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
3257 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
3258 enum mlxsw_reg_ralue_op op
, int err
);
3261 mlxsw_sp_nexthop_fib_entries_refresh(struct mlxsw_sp_nexthop_group
*nh_grp
)
3263 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_WRITE
;
3264 struct mlxsw_sp_fib_entry
*fib_entry
;
3266 list_for_each_entry(fib_entry
, &nh_grp
->fib_list
, nexthop_group_node
) {
3267 if (!mlxsw_sp_fib_node_entry_is_first(fib_entry
->fib_node
,
3270 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
3274 static void mlxsw_sp_adj_grp_size_round_up(u16
*p_adj_grp_size
)
3276 /* Valid sizes for an adjacency group are:
3277 * 1-64, 512, 1024, 2048 and 4096.
3279 if (*p_adj_grp_size
<= 64)
3281 else if (*p_adj_grp_size
<= 512)
3282 *p_adj_grp_size
= 512;
3283 else if (*p_adj_grp_size
<= 1024)
3284 *p_adj_grp_size
= 1024;
3285 else if (*p_adj_grp_size
<= 2048)
3286 *p_adj_grp_size
= 2048;
3288 *p_adj_grp_size
= 4096;
3291 static void mlxsw_sp_adj_grp_size_round_down(u16
*p_adj_grp_size
,
3292 unsigned int alloc_size
)
3294 if (alloc_size
>= 4096)
3295 *p_adj_grp_size
= 4096;
3296 else if (alloc_size
>= 2048)
3297 *p_adj_grp_size
= 2048;
3298 else if (alloc_size
>= 1024)
3299 *p_adj_grp_size
= 1024;
3300 else if (alloc_size
>= 512)
3301 *p_adj_grp_size
= 512;
3304 static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp
*mlxsw_sp
,
3305 u16
*p_adj_grp_size
)
3307 unsigned int alloc_size
;
3310 /* Round up the requested group size to the next size supported
3311 * by the device and make sure the request can be satisfied.
3313 mlxsw_sp_adj_grp_size_round_up(p_adj_grp_size
);
3314 err
= mlxsw_sp_kvdl_alloc_count_query(mlxsw_sp
,
3315 MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
,
3316 *p_adj_grp_size
, &alloc_size
);
3319 /* It is possible the allocation results in more allocated
3320 * entries than requested. Try to use as much of them as
3323 mlxsw_sp_adj_grp_size_round_down(p_adj_grp_size
, alloc_size
);
3329 mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group
*nh_grp
)
3331 int i
, g
= 0, sum_norm_weight
= 0;
3332 struct mlxsw_sp_nexthop
*nh
;
3334 for (i
= 0; i
< nh_grp
->count
; i
++) {
3335 nh
= &nh_grp
->nexthops
[i
];
3337 if (!nh
->should_offload
)
3340 g
= gcd(nh
->nh_weight
, g
);
3345 for (i
= 0; i
< nh_grp
->count
; i
++) {
3346 nh
= &nh_grp
->nexthops
[i
];
3348 if (!nh
->should_offload
)
3350 nh
->norm_nh_weight
= nh
->nh_weight
/ g
;
3351 sum_norm_weight
+= nh
->norm_nh_weight
;
3354 nh_grp
->sum_norm_weight
= sum_norm_weight
;
3358 mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group
*nh_grp
)
3360 int total
= nh_grp
->sum_norm_weight
;
3361 u16 ecmp_size
= nh_grp
->ecmp_size
;
3362 int i
, weight
= 0, lower_bound
= 0;
3364 for (i
= 0; i
< nh_grp
->count
; i
++) {
3365 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
3368 if (!nh
->should_offload
)
3370 weight
+= nh
->norm_nh_weight
;
3371 upper_bound
= DIV_ROUND_CLOSEST(ecmp_size
* weight
, total
);
3372 nh
->num_adj_entries
= upper_bound
- lower_bound
;
3373 lower_bound
= upper_bound
;
3378 mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp
*mlxsw_sp
,
3379 struct mlxsw_sp_nexthop_group
*nh_grp
)
3381 u16 ecmp_size
, old_ecmp_size
;
3382 struct mlxsw_sp_nexthop
*nh
;
3383 bool offload_change
= false;
3385 bool old_adj_index_valid
;
3390 if (!nh_grp
->gateway
) {
3391 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3395 for (i
= 0; i
< nh_grp
->count
; i
++) {
3396 nh
= &nh_grp
->nexthops
[i
];
3398 if (nh
->should_offload
!= nh
->offloaded
) {
3399 offload_change
= true;
3400 if (nh
->should_offload
)
3404 if (!offload_change
) {
3405 /* Nothing was added or removed, so no need to reallocate. Just
3406 * update MAC on existing adjacency indexes.
3408 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, false);
3410 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3415 mlxsw_sp_nexthop_group_normalize(nh_grp
);
3416 if (!nh_grp
->sum_norm_weight
)
3417 /* No neigh of this group is connected so we just set
3418 * the trap and let everthing flow through kernel.
3422 ecmp_size
= nh_grp
->sum_norm_weight
;
3423 err
= mlxsw_sp_fix_adj_grp_size(mlxsw_sp
, &ecmp_size
);
3425 /* No valid allocation size available. */
3428 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
,
3429 ecmp_size
, &adj_index
);
3431 /* We ran out of KVD linear space, just set the
3432 * trap and let everything flow through kernel.
3434 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to allocate KVD linear area for nexthop group.\n");
3437 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3438 old_adj_index
= nh_grp
->adj_index
;
3439 old_ecmp_size
= nh_grp
->ecmp_size
;
3440 nh_grp
->adj_index_valid
= 1;
3441 nh_grp
->adj_index
= adj_index
;
3442 nh_grp
->ecmp_size
= ecmp_size
;
3443 mlxsw_sp_nexthop_group_rebalance(nh_grp
);
3444 err
= mlxsw_sp_nexthop_group_update(mlxsw_sp
, nh_grp
, true);
3446 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to update neigh MAC in adjacency table.\n");
3450 if (!old_adj_index_valid
) {
3451 /* The trap was set for fib entries, so we have to call
3452 * fib entry update to unset it and use adjacency index.
3454 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3456 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to add adjacency index to fib entries.\n");
3462 err
= mlxsw_sp_adj_index_mass_update(mlxsw_sp
, nh_grp
,
3463 old_adj_index
, old_ecmp_size
);
3464 mlxsw_sp_kvdl_free(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
,
3465 old_ecmp_size
, old_adj_index
);
3467 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to mass-update adjacency index for nexthop group.\n");
3471 /* Offload state within the group changed, so update the flags. */
3472 mlxsw_sp_nexthop_fib_entries_refresh(nh_grp
);
3477 old_adj_index_valid
= nh_grp
->adj_index_valid
;
3478 nh_grp
->adj_index_valid
= 0;
3479 for (i
= 0; i
< nh_grp
->count
; i
++) {
3480 nh
= &nh_grp
->nexthops
[i
];
3483 err
= mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp
, nh_grp
);
3485 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set traps for fib entries.\n");
3486 if (old_adj_index_valid
)
3487 mlxsw_sp_kvdl_free(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
,
3488 nh_grp
->ecmp_size
, nh_grp
->adj_index
);
3491 static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop
*nh
,
3495 nh
->should_offload
= 1;
3497 nh
->should_offload
= 0;
3502 mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp
*mlxsw_sp
,
3503 struct mlxsw_sp_neigh_entry
*neigh_entry
)
3505 struct neighbour
*n
, *old_n
= neigh_entry
->key
.n
;
3506 struct mlxsw_sp_nexthop
*nh
;
3507 bool entry_connected
;
3511 nh
= list_first_entry(&neigh_entry
->nexthop_list
,
3512 struct mlxsw_sp_nexthop
, neigh_list_node
);
3514 n
= neigh_lookup(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
, nh
->rif
->dev
);
3516 n
= neigh_create(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
,
3520 neigh_event_send(n
, NULL
);
3523 mlxsw_sp_neigh_entry_remove(mlxsw_sp
, neigh_entry
);
3524 neigh_entry
->key
.n
= n
;
3525 err
= mlxsw_sp_neigh_entry_insert(mlxsw_sp
, neigh_entry
);
3527 goto err_neigh_entry_insert
;
3529 read_lock_bh(&n
->lock
);
3530 nud_state
= n
->nud_state
;
3532 read_unlock_bh(&n
->lock
);
3533 entry_connected
= nud_state
& NUD_VALID
&& !dead
;
3535 list_for_each_entry(nh
, &neigh_entry
->nexthop_list
,
3537 neigh_release(old_n
);
3539 __mlxsw_sp_nexthop_neigh_update(nh
, !entry_connected
);
3540 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3547 err_neigh_entry_insert
:
3548 neigh_entry
->key
.n
= old_n
;
3549 mlxsw_sp_neigh_entry_insert(mlxsw_sp
, neigh_entry
);
3555 mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp
*mlxsw_sp
,
3556 struct mlxsw_sp_neigh_entry
*neigh_entry
,
3557 bool removing
, bool dead
)
3559 struct mlxsw_sp_nexthop
*nh
;
3561 if (list_empty(&neigh_entry
->nexthop_list
))
3567 err
= mlxsw_sp_nexthop_dead_neigh_replace(mlxsw_sp
,
3570 dev_err(mlxsw_sp
->bus_info
->dev
, "Failed to replace dead neigh\n");
3574 list_for_each_entry(nh
, &neigh_entry
->nexthop_list
,
3576 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3577 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3581 static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop
*nh
,
3582 struct mlxsw_sp_rif
*rif
)
3588 list_add(&nh
->rif_list_node
, &rif
->nexthop_list
);
3591 static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop
*nh
)
3596 list_del(&nh
->rif_list_node
);
3600 static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp
*mlxsw_sp
,
3601 struct mlxsw_sp_nexthop
*nh
)
3603 struct mlxsw_sp_neigh_entry
*neigh_entry
;
3604 struct neighbour
*n
;
3608 if (!nh
->nh_grp
->gateway
|| nh
->neigh_entry
)
3611 /* Take a reference of neigh here ensuring that neigh would
3612 * not be destructed before the nexthop entry is finished.
3613 * The reference is taken either in neigh_lookup() or
3614 * in neigh_create() in case n is not found.
3616 n
= neigh_lookup(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
, nh
->rif
->dev
);
3618 n
= neigh_create(nh
->nh_grp
->neigh_tbl
, &nh
->gw_addr
,
3622 neigh_event_send(n
, NULL
);
3624 neigh_entry
= mlxsw_sp_neigh_entry_lookup(mlxsw_sp
, n
);
3626 neigh_entry
= mlxsw_sp_neigh_entry_create(mlxsw_sp
, n
);
3627 if (IS_ERR(neigh_entry
)) {
3629 goto err_neigh_entry_create
;
3633 /* If that is the first nexthop connected to that neigh, add to
3634 * nexthop_neighs_list
3636 if (list_empty(&neigh_entry
->nexthop_list
))
3637 list_add_tail(&neigh_entry
->nexthop_neighs_list_node
,
3638 &mlxsw_sp
->router
->nexthop_neighs_list
);
3640 nh
->neigh_entry
= neigh_entry
;
3641 list_add_tail(&nh
->neigh_list_node
, &neigh_entry
->nexthop_list
);
3642 read_lock_bh(&n
->lock
);
3643 nud_state
= n
->nud_state
;
3645 read_unlock_bh(&n
->lock
);
3646 __mlxsw_sp_nexthop_neigh_update(nh
, !(nud_state
& NUD_VALID
&& !dead
));
3650 err_neigh_entry_create
:
3655 static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp
*mlxsw_sp
,
3656 struct mlxsw_sp_nexthop
*nh
)
3658 struct mlxsw_sp_neigh_entry
*neigh_entry
= nh
->neigh_entry
;
3659 struct neighbour
*n
;
3663 n
= neigh_entry
->key
.n
;
3665 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3666 list_del(&nh
->neigh_list_node
);
3667 nh
->neigh_entry
= NULL
;
3669 /* If that is the last nexthop connected to that neigh, remove from
3670 * nexthop_neighs_list
3672 if (list_empty(&neigh_entry
->nexthop_list
))
3673 list_del(&neigh_entry
->nexthop_neighs_list_node
);
3675 if (!neigh_entry
->connected
&& list_empty(&neigh_entry
->nexthop_list
))
3676 mlxsw_sp_neigh_entry_destroy(mlxsw_sp
, neigh_entry
);
3681 static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device
*ol_dev
)
3683 struct net_device
*ul_dev
= __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev
);
3685 return ul_dev
? (ul_dev
->flags
& IFF_UP
) : true;
3688 static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp
*mlxsw_sp
,
3689 struct mlxsw_sp_nexthop
*nh
,
3690 struct mlxsw_sp_ipip_entry
*ipip_entry
)
3694 if (!nh
->nh_grp
->gateway
|| nh
->ipip_entry
)
3697 nh
->ipip_entry
= ipip_entry
;
3698 removing
= !mlxsw_sp_ipip_netdev_ul_up(ipip_entry
->ol_dev
);
3699 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3700 mlxsw_sp_nexthop_rif_init(nh
, &ipip_entry
->ol_lb
->common
);
3703 static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp
*mlxsw_sp
,
3704 struct mlxsw_sp_nexthop
*nh
)
3706 struct mlxsw_sp_ipip_entry
*ipip_entry
= nh
->ipip_entry
;
3711 __mlxsw_sp_nexthop_neigh_update(nh
, true);
3712 nh
->ipip_entry
= NULL
;
3715 static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
3716 const struct fib_nh
*fib_nh
,
3717 enum mlxsw_sp_ipip_type
*p_ipipt
)
3719 struct net_device
*dev
= fib_nh
->fib_nh_dev
;
3722 fib_nh
->nh_parent
->fib_type
== RTN_UNICAST
&&
3723 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, p_ipipt
);
3726 static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3727 struct mlxsw_sp_nexthop
*nh
)
3730 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3731 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp
, nh
);
3732 mlxsw_sp_nexthop_rif_fini(nh
);
3734 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3735 mlxsw_sp_nexthop_rif_fini(nh
);
3736 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp
, nh
);
3741 static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp
*mlxsw_sp
,
3742 struct mlxsw_sp_nexthop
*nh
,
3743 struct fib_nh
*fib_nh
)
3745 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
3746 struct net_device
*dev
= fib_nh
->fib_nh_dev
;
3747 struct mlxsw_sp_ipip_entry
*ipip_entry
;
3748 struct mlxsw_sp_rif
*rif
;
3751 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, dev
);
3753 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
3754 if (ipip_ops
->can_offload(mlxsw_sp
, dev
,
3755 MLXSW_SP_L3_PROTO_IPV4
)) {
3756 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
3757 mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, ipip_entry
);
3762 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
3763 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
3767 mlxsw_sp_nexthop_rif_init(nh
, rif
);
3768 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
3770 goto err_neigh_init
;
3775 mlxsw_sp_nexthop_rif_fini(nh
);
3779 static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp
*mlxsw_sp
,
3780 struct mlxsw_sp_nexthop
*nh
)
3782 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3785 static int mlxsw_sp_nexthop4_init(struct mlxsw_sp
*mlxsw_sp
,
3786 struct mlxsw_sp_nexthop_group
*nh_grp
,
3787 struct mlxsw_sp_nexthop
*nh
,
3788 struct fib_nh
*fib_nh
)
3790 struct net_device
*dev
= fib_nh
->fib_nh_dev
;
3791 struct in_device
*in_dev
;
3794 nh
->nh_grp
= nh_grp
;
3795 nh
->key
.fib_nh
= fib_nh
;
3796 #ifdef CONFIG_IP_ROUTE_MULTIPATH
3797 nh
->nh_weight
= fib_nh
->fib_nh_weight
;
3801 memcpy(&nh
->gw_addr
, &fib_nh
->fib_nh_gw4
, sizeof(fib_nh
->fib_nh_gw4
));
3802 err
= mlxsw_sp_nexthop_insert(mlxsw_sp
, nh
);
3806 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
3807 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
3812 in_dev
= __in_dev_get_rtnl(dev
);
3813 if (in_dev
&& IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev
) &&
3814 fib_nh
->fib_nh_flags
& RTNH_F_LINKDOWN
)
3817 err
= mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3819 goto err_nexthop_neigh_init
;
3823 err_nexthop_neigh_init
:
3824 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3828 static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp
*mlxsw_sp
,
3829 struct mlxsw_sp_nexthop
*nh
)
3831 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3832 list_del(&nh
->router_list_node
);
3833 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
3834 mlxsw_sp_nexthop_remove(mlxsw_sp
, nh
);
3837 static void mlxsw_sp_nexthop4_event(struct mlxsw_sp
*mlxsw_sp
,
3838 unsigned long event
, struct fib_nh
*fib_nh
)
3840 struct mlxsw_sp_nexthop_key key
;
3841 struct mlxsw_sp_nexthop
*nh
;
3843 if (mlxsw_sp
->router
->aborted
)
3846 key
.fib_nh
= fib_nh
;
3847 nh
= mlxsw_sp_nexthop_lookup(mlxsw_sp
, key
);
3852 case FIB_EVENT_NH_ADD
:
3853 mlxsw_sp_nexthop4_type_init(mlxsw_sp
, nh
, fib_nh
);
3855 case FIB_EVENT_NH_DEL
:
3856 mlxsw_sp_nexthop4_type_fini(mlxsw_sp
, nh
);
3860 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3863 static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp
*mlxsw_sp
,
3864 struct mlxsw_sp_rif
*rif
)
3866 struct mlxsw_sp_nexthop
*nh
;
3869 list_for_each_entry(nh
, &rif
->nexthop_list
, rif_list_node
) {
3871 case MLXSW_SP_NEXTHOP_TYPE_ETH
:
3874 case MLXSW_SP_NEXTHOP_TYPE_IPIP
:
3875 removing
= !mlxsw_sp_ipip_netdev_ul_up(rif
->dev
);
3882 __mlxsw_sp_nexthop_neigh_update(nh
, removing
);
3883 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3887 static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp
*mlxsw_sp
,
3888 struct mlxsw_sp_rif
*old_rif
,
3889 struct mlxsw_sp_rif
*new_rif
)
3891 struct mlxsw_sp_nexthop
*nh
;
3893 list_splice_init(&old_rif
->nexthop_list
, &new_rif
->nexthop_list
);
3894 list_for_each_entry(nh
, &new_rif
->nexthop_list
, rif_list_node
)
3896 mlxsw_sp_nexthop_rif_update(mlxsw_sp
, new_rif
);
3899 static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
3900 struct mlxsw_sp_rif
*rif
)
3902 struct mlxsw_sp_nexthop
*nh
, *tmp
;
3904 list_for_each_entry_safe(nh
, tmp
, &rif
->nexthop_list
, rif_list_node
) {
3905 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
3906 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh
->nh_grp
);
3910 static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
3911 struct fib_info
*fi
)
3913 const struct fib_nh
*nh
= fib_info_nh(fi
, 0);
3915 return nh
->fib_nh_scope
== RT_SCOPE_LINK
||
3916 mlxsw_sp_nexthop4_ipip_type(mlxsw_sp
, nh
, NULL
);
3919 static struct mlxsw_sp_nexthop_group
*
3920 mlxsw_sp_nexthop4_group_create(struct mlxsw_sp
*mlxsw_sp
, struct fib_info
*fi
)
3922 unsigned int nhs
= fib_info_num_path(fi
);
3923 struct mlxsw_sp_nexthop_group
*nh_grp
;
3924 struct mlxsw_sp_nexthop
*nh
;
3925 struct fib_nh
*fib_nh
;
3929 nh_grp
= kzalloc(struct_size(nh_grp
, nexthops
, nhs
), GFP_KERNEL
);
3931 return ERR_PTR(-ENOMEM
);
3933 INIT_LIST_HEAD(&nh_grp
->fib_list
);
3934 nh_grp
->neigh_tbl
= &arp_tbl
;
3936 nh_grp
->gateway
= mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
);
3937 nh_grp
->count
= nhs
;
3939 for (i
= 0; i
< nh_grp
->count
; i
++) {
3940 nh
= &nh_grp
->nexthops
[i
];
3941 fib_nh
= fib_info_nh(fi
, i
);
3942 err
= mlxsw_sp_nexthop4_init(mlxsw_sp
, nh_grp
, nh
, fib_nh
);
3944 goto err_nexthop4_init
;
3946 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
3948 goto err_nexthop_group_insert
;
3949 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3952 err_nexthop_group_insert
:
3954 for (i
--; i
>= 0; i
--) {
3955 nh
= &nh_grp
->nexthops
[i
];
3956 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3960 return ERR_PTR(err
);
3964 mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
3965 struct mlxsw_sp_nexthop_group
*nh_grp
)
3967 struct mlxsw_sp_nexthop
*nh
;
3970 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
3971 for (i
= 0; i
< nh_grp
->count
; i
++) {
3972 nh
= &nh_grp
->nexthops
[i
];
3973 mlxsw_sp_nexthop4_fini(mlxsw_sp
, nh
);
3975 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
3976 WARN_ON_ONCE(nh_grp
->adj_index_valid
);
3977 fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp
));
3981 static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp
*mlxsw_sp
,
3982 struct mlxsw_sp_fib_entry
*fib_entry
,
3983 struct fib_info
*fi
)
3985 struct mlxsw_sp_nexthop_group
*nh_grp
;
3987 nh_grp
= mlxsw_sp_nexthop4_group_lookup(mlxsw_sp
, fi
);
3989 nh_grp
= mlxsw_sp_nexthop4_group_create(mlxsw_sp
, fi
);
3991 return PTR_ERR(nh_grp
);
3993 list_add_tail(&fib_entry
->nexthop_group_node
, &nh_grp
->fib_list
);
3994 fib_entry
->nh_group
= nh_grp
;
3998 static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp
*mlxsw_sp
,
3999 struct mlxsw_sp_fib_entry
*fib_entry
)
4001 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4003 list_del(&fib_entry
->nexthop_group_node
);
4004 if (!list_empty(&nh_grp
->fib_list
))
4006 mlxsw_sp_nexthop4_group_destroy(mlxsw_sp
, nh_grp
);
4010 mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
4012 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4014 fib4_entry
= container_of(fib_entry
, struct mlxsw_sp_fib4_entry
,
4016 return !fib4_entry
->tos
;
4020 mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry
*fib_entry
)
4022 struct mlxsw_sp_nexthop_group
*nh_group
= fib_entry
->nh_group
;
4024 switch (fib_entry
->fib_node
->fib
->proto
) {
4025 case MLXSW_SP_L3_PROTO_IPV4
:
4026 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry
))
4029 case MLXSW_SP_L3_PROTO_IPV6
:
4033 switch (fib_entry
->type
) {
4034 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
4035 return !!nh_group
->adj_index_valid
;
4036 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
4037 return !!nh_group
->nh_rif
;
4038 case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
:
4039 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
4040 case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
:
4047 static struct mlxsw_sp_nexthop
*
4048 mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group
*nh_grp
,
4049 const struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
4053 for (i
= 0; i
< nh_grp
->count
; i
++) {
4054 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
4055 struct fib6_info
*rt
= mlxsw_sp_rt6
->rt
;
4057 if (nh
->rif
&& nh
->rif
->dev
== rt
->fib6_nh
->fib_nh_dev
&&
4058 ipv6_addr_equal((const struct in6_addr
*) &nh
->gw_addr
,
4059 &rt
->fib6_nh
->fib_nh_gw6
))
4068 mlxsw_sp_fib4_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
4070 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4073 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
||
4074 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
||
4075 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
||
4076 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
) {
4077 nh_grp
->nexthops
->key
.fib_nh
->fib_nh_flags
|= RTNH_F_OFFLOAD
;
4081 for (i
= 0; i
< nh_grp
->count
; i
++) {
4082 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
4085 nh
->key
.fib_nh
->fib_nh_flags
|= RTNH_F_OFFLOAD
;
4087 nh
->key
.fib_nh
->fib_nh_flags
&= ~RTNH_F_OFFLOAD
;
4092 mlxsw_sp_fib4_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
4094 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4097 if (!list_is_singular(&nh_grp
->fib_list
))
4100 for (i
= 0; i
< nh_grp
->count
; i
++) {
4101 struct mlxsw_sp_nexthop
*nh
= &nh_grp
->nexthops
[i
];
4103 nh
->key
.fib_nh
->fib_nh_flags
&= ~RTNH_F_OFFLOAD
;
4108 mlxsw_sp_fib6_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
4110 struct mlxsw_sp_fib6_entry
*fib6_entry
;
4111 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4113 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
4116 if (fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
||
4117 fib_entry
->type
== MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
) {
4118 list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
4119 list
)->rt
->fib6_nh
->fib_nh_flags
|= RTNH_F_OFFLOAD
;
4123 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
4124 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
4125 struct fib6_nh
*fib6_nh
= mlxsw_sp_rt6
->rt
->fib6_nh
;
4126 struct mlxsw_sp_nexthop
*nh
;
4128 nh
= mlxsw_sp_rt6_nexthop(nh_grp
, mlxsw_sp_rt6
);
4129 if (nh
&& nh
->offloaded
)
4130 fib6_nh
->fib_nh_flags
|= RTNH_F_OFFLOAD
;
4132 fib6_nh
->fib_nh_flags
&= ~RTNH_F_OFFLOAD
;
4137 mlxsw_sp_fib6_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
4139 struct mlxsw_sp_fib6_entry
*fib6_entry
;
4140 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4142 fib6_entry
= container_of(fib_entry
, struct mlxsw_sp_fib6_entry
,
4144 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
4145 struct fib6_info
*rt
= mlxsw_sp_rt6
->rt
;
4147 rt
->fib6_nh
->fib_nh_flags
&= ~RTNH_F_OFFLOAD
;
4151 static void mlxsw_sp_fib_entry_offload_set(struct mlxsw_sp_fib_entry
*fib_entry
)
4153 switch (fib_entry
->fib_node
->fib
->proto
) {
4154 case MLXSW_SP_L3_PROTO_IPV4
:
4155 mlxsw_sp_fib4_entry_offload_set(fib_entry
);
4157 case MLXSW_SP_L3_PROTO_IPV6
:
4158 mlxsw_sp_fib6_entry_offload_set(fib_entry
);
4164 mlxsw_sp_fib_entry_offload_unset(struct mlxsw_sp_fib_entry
*fib_entry
)
4166 switch (fib_entry
->fib_node
->fib
->proto
) {
4167 case MLXSW_SP_L3_PROTO_IPV4
:
4168 mlxsw_sp_fib4_entry_offload_unset(fib_entry
);
4170 case MLXSW_SP_L3_PROTO_IPV6
:
4171 mlxsw_sp_fib6_entry_offload_unset(fib_entry
);
4177 mlxsw_sp_fib_entry_offload_refresh(struct mlxsw_sp_fib_entry
*fib_entry
,
4178 enum mlxsw_reg_ralue_op op
, int err
)
4181 case MLXSW_REG_RALUE_OP_WRITE_DELETE
:
4182 return mlxsw_sp_fib_entry_offload_unset(fib_entry
);
4183 case MLXSW_REG_RALUE_OP_WRITE_WRITE
:
4186 if (mlxsw_sp_fib_entry_should_offload(fib_entry
))
4187 mlxsw_sp_fib_entry_offload_set(fib_entry
);
4189 mlxsw_sp_fib_entry_offload_unset(fib_entry
);
4197 mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl
,
4198 const struct mlxsw_sp_fib_entry
*fib_entry
,
4199 enum mlxsw_reg_ralue_op op
)
4201 struct mlxsw_sp_fib
*fib
= fib_entry
->fib_node
->fib
;
4202 enum mlxsw_reg_ralxx_protocol proto
;
4205 proto
= (enum mlxsw_reg_ralxx_protocol
) fib
->proto
;
4207 switch (fib
->proto
) {
4208 case MLXSW_SP_L3_PROTO_IPV4
:
4209 p_dip
= (u32
*) fib_entry
->fib_node
->key
.addr
;
4210 mlxsw_reg_ralue_pack4(ralue_pl
, proto
, op
, fib
->vr
->id
,
4211 fib_entry
->fib_node
->key
.prefix_len
,
4214 case MLXSW_SP_L3_PROTO_IPV6
:
4215 mlxsw_reg_ralue_pack6(ralue_pl
, proto
, op
, fib
->vr
->id
,
4216 fib_entry
->fib_node
->key
.prefix_len
,
4217 fib_entry
->fib_node
->key
.addr
);
4222 static int mlxsw_sp_adj_discard_write(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
)
4224 enum mlxsw_reg_ratr_trap_action trap_action
;
4225 char ratr_pl
[MLXSW_REG_RATR_LEN
];
4228 if (mlxsw_sp
->router
->adj_discard_index_valid
)
4231 err
= mlxsw_sp_kvdl_alloc(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
, 1,
4232 &mlxsw_sp
->router
->adj_discard_index
);
4236 trap_action
= MLXSW_REG_RATR_TRAP_ACTION_DISCARD_ERRORS
;
4237 mlxsw_reg_ratr_pack(ratr_pl
, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY
, true,
4238 MLXSW_REG_RATR_TYPE_ETHERNET
,
4239 mlxsw_sp
->router
->adj_discard_index
, rif_index
);
4240 mlxsw_reg_ratr_trap_action_set(ratr_pl
, trap_action
);
4241 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ratr
), ratr_pl
);
4243 goto err_ratr_write
;
4245 mlxsw_sp
->router
->adj_discard_index_valid
= true;
4250 mlxsw_sp_kvdl_free(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
, 1,
4251 mlxsw_sp
->router
->adj_discard_index
);
4255 static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp
*mlxsw_sp
,
4256 struct mlxsw_sp_fib_entry
*fib_entry
,
4257 enum mlxsw_reg_ralue_op op
)
4259 struct mlxsw_sp_nexthop_group
*nh_group
= fib_entry
->nh_group
;
4260 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
4261 enum mlxsw_reg_ralue_trap_action trap_action
;
4263 u32 adjacency_index
= 0;
4267 /* In case the nexthop group adjacency index is valid, use it
4268 * with provided ECMP size. Otherwise, setup trap and pass
4269 * traffic to kernel.
4271 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
4272 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
4273 adjacency_index
= fib_entry
->nh_group
->adj_index
;
4274 ecmp_size
= fib_entry
->nh_group
->ecmp_size
;
4275 } else if (!nh_group
->adj_index_valid
&& nh_group
->count
&&
4277 err
= mlxsw_sp_adj_discard_write(mlxsw_sp
,
4278 nh_group
->nh_rif
->rif_index
);
4281 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
4282 adjacency_index
= mlxsw_sp
->router
->adj_discard_index
;
4285 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
4286 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
4289 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
4290 mlxsw_reg_ralue_act_remote_pack(ralue_pl
, trap_action
, trap_id
,
4291 adjacency_index
, ecmp_size
);
4292 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
4295 static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp
*mlxsw_sp
,
4296 struct mlxsw_sp_fib_entry
*fib_entry
,
4297 enum mlxsw_reg_ralue_op op
)
4299 struct mlxsw_sp_rif
*rif
= fib_entry
->nh_group
->nh_rif
;
4300 enum mlxsw_reg_ralue_trap_action trap_action
;
4301 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
4305 if (mlxsw_sp_fib_entry_should_offload(fib_entry
)) {
4306 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_NOP
;
4307 rif_index
= rif
->rif_index
;
4309 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
4310 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS0
;
4313 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
4314 mlxsw_reg_ralue_act_local_pack(ralue_pl
, trap_action
, trap_id
,
4316 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
4319 static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp
*mlxsw_sp
,
4320 struct mlxsw_sp_fib_entry
*fib_entry
,
4321 enum mlxsw_reg_ralue_op op
)
4323 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
4325 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
4326 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
4327 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
4330 static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp
*mlxsw_sp
,
4331 struct mlxsw_sp_fib_entry
*fib_entry
,
4332 enum mlxsw_reg_ralue_op op
)
4334 enum mlxsw_reg_ralue_trap_action trap_action
;
4335 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
4337 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR
;
4338 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
4339 mlxsw_reg_ralue_act_local_pack(ralue_pl
, trap_action
, 0, 0);
4340 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
4344 mlxsw_sp_fib_entry_op_unreachable(struct mlxsw_sp
*mlxsw_sp
,
4345 struct mlxsw_sp_fib_entry
*fib_entry
,
4346 enum mlxsw_reg_ralue_op op
)
4348 enum mlxsw_reg_ralue_trap_action trap_action
;
4349 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
4352 trap_action
= MLXSW_REG_RALUE_TRAP_ACTION_TRAP
;
4353 trap_id
= MLXSW_TRAP_ID_RTR_INGRESS1
;
4355 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
4356 mlxsw_reg_ralue_act_local_pack(ralue_pl
, trap_action
, trap_id
, 0);
4357 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
4361 mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp
*mlxsw_sp
,
4362 struct mlxsw_sp_fib_entry
*fib_entry
,
4363 enum mlxsw_reg_ralue_op op
)
4365 struct mlxsw_sp_ipip_entry
*ipip_entry
= fib_entry
->decap
.ipip_entry
;
4366 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
4368 if (WARN_ON(!ipip_entry
))
4371 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
4372 return ipip_ops
->fib_entry_op(mlxsw_sp
, ipip_entry
, op
,
4373 fib_entry
->decap
.tunnel_index
);
4376 static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp
*mlxsw_sp
,
4377 struct mlxsw_sp_fib_entry
*fib_entry
,
4378 enum mlxsw_reg_ralue_op op
)
4380 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
4382 mlxsw_sp_fib_entry_ralue_pack(ralue_pl
, fib_entry
, op
);
4383 mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl
,
4384 fib_entry
->decap
.tunnel_index
);
4385 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
), ralue_pl
);
4388 static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
4389 struct mlxsw_sp_fib_entry
*fib_entry
,
4390 enum mlxsw_reg_ralue_op op
)
4392 switch (fib_entry
->type
) {
4393 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
:
4394 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp
, fib_entry
, op
);
4395 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
:
4396 return mlxsw_sp_fib_entry_op_local(mlxsw_sp
, fib_entry
, op
);
4397 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP
:
4398 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp
, fib_entry
, op
);
4399 case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
:
4400 return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp
, fib_entry
, op
);
4401 case MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE
:
4402 return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp
, fib_entry
,
4404 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
:
4405 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp
,
4407 case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
:
4408 return mlxsw_sp_fib_entry_op_nve_decap(mlxsw_sp
, fib_entry
, op
);
4413 static int mlxsw_sp_fib_entry_op(struct mlxsw_sp
*mlxsw_sp
,
4414 struct mlxsw_sp_fib_entry
*fib_entry
,
4415 enum mlxsw_reg_ralue_op op
)
4417 int err
= __mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
, op
);
4419 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, err
);
4424 static int mlxsw_sp_fib_entry_update(struct mlxsw_sp
*mlxsw_sp
,
4425 struct mlxsw_sp_fib_entry
*fib_entry
)
4427 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
4428 MLXSW_REG_RALUE_OP_WRITE_WRITE
);
4431 static int mlxsw_sp_fib_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4432 struct mlxsw_sp_fib_entry
*fib_entry
)
4434 return mlxsw_sp_fib_entry_op(mlxsw_sp
, fib_entry
,
4435 MLXSW_REG_RALUE_OP_WRITE_DELETE
);
4439 mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
4440 const struct fib_entry_notifier_info
*fen_info
,
4441 struct mlxsw_sp_fib_entry
*fib_entry
)
4443 struct net_device
*dev
= fib_info_nh(fen_info
->fi
, 0)->fib_nh_dev
;
4444 union mlxsw_sp_l3addr dip
= { .addr4
= htonl(fen_info
->dst
) };
4445 u32 tb_id
= mlxsw_sp_fix_tb_id(fen_info
->tb_id
);
4446 struct mlxsw_sp_ipip_entry
*ipip_entry
;
4447 struct fib_info
*fi
= fen_info
->fi
;
4449 switch (fen_info
->type
) {
4451 ipip_entry
= mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp
, dev
,
4452 MLXSW_SP_L3_PROTO_IPV4
, dip
);
4453 if (ipip_entry
&& ipip_entry
->ol_dev
->flags
& IFF_UP
) {
4454 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
;
4455 return mlxsw_sp_fib_entry_decap_init(mlxsw_sp
,
4459 if (mlxsw_sp_nve_ipv4_route_is_decap(mlxsw_sp
, tb_id
,
4463 t_index
= mlxsw_sp_nve_decap_tunnel_index_get(mlxsw_sp
);
4464 fib_entry
->decap
.tunnel_index
= t_index
;
4465 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP
;
4470 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
4473 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
;
4475 case RTN_UNREACHABLE
: /* fall through */
4477 /* Packets hitting these routes need to be trapped, but
4478 * can do so with a lower priority than packets directed
4479 * at the host, so use action type local instead of trap.
4481 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE
;
4484 if (mlxsw_sp_fi_is_gateway(mlxsw_sp
, fi
))
4485 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
4487 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
4494 static struct mlxsw_sp_fib4_entry
*
4495 mlxsw_sp_fib4_entry_create(struct mlxsw_sp
*mlxsw_sp
,
4496 struct mlxsw_sp_fib_node
*fib_node
,
4497 const struct fib_entry_notifier_info
*fen_info
)
4499 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4500 struct mlxsw_sp_fib_entry
*fib_entry
;
4503 fib4_entry
= kzalloc(sizeof(*fib4_entry
), GFP_KERNEL
);
4505 return ERR_PTR(-ENOMEM
);
4506 fib_entry
= &fib4_entry
->common
;
4508 err
= mlxsw_sp_fib4_entry_type_set(mlxsw_sp
, fen_info
, fib_entry
);
4510 goto err_fib4_entry_type_set
;
4512 err
= mlxsw_sp_nexthop4_group_get(mlxsw_sp
, fib_entry
, fen_info
->fi
);
4514 goto err_nexthop4_group_get
;
4516 fib4_entry
->prio
= fen_info
->fi
->fib_priority
;
4517 fib4_entry
->tb_id
= fen_info
->tb_id
;
4518 fib4_entry
->type
= fen_info
->type
;
4519 fib4_entry
->tos
= fen_info
->tos
;
4521 fib_entry
->fib_node
= fib_node
;
4525 err_nexthop4_group_get
:
4526 err_fib4_entry_type_set
:
4528 return ERR_PTR(err
);
4531 static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
4532 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4534 mlxsw_sp_nexthop4_group_put(mlxsw_sp
, &fib4_entry
->common
);
4538 static struct mlxsw_sp_fib4_entry
*
4539 mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
4540 const struct fib_entry_notifier_info
*fen_info
)
4542 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4543 struct mlxsw_sp_fib_node
*fib_node
;
4544 struct mlxsw_sp_fib
*fib
;
4545 struct mlxsw_sp_vr
*vr
;
4547 vr
= mlxsw_sp_vr_find(mlxsw_sp
, fen_info
->tb_id
);
4550 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV4
);
4552 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &fen_info
->dst
,
4553 sizeof(fen_info
->dst
),
4558 list_for_each_entry(fib4_entry
, &fib_node
->entry_list
, common
.list
) {
4559 if (fib4_entry
->tb_id
== fen_info
->tb_id
&&
4560 fib4_entry
->tos
== fen_info
->tos
&&
4561 fib4_entry
->type
== fen_info
->type
&&
4562 mlxsw_sp_nexthop4_group_fi(fib4_entry
->common
.nh_group
) ==
4571 static const struct rhashtable_params mlxsw_sp_fib_ht_params
= {
4572 .key_offset
= offsetof(struct mlxsw_sp_fib_node
, key
),
4573 .head_offset
= offsetof(struct mlxsw_sp_fib_node
, ht_node
),
4574 .key_len
= sizeof(struct mlxsw_sp_fib_key
),
4575 .automatic_shrinking
= true,
4578 static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib
*fib
,
4579 struct mlxsw_sp_fib_node
*fib_node
)
4581 return rhashtable_insert_fast(&fib
->ht
, &fib_node
->ht_node
,
4582 mlxsw_sp_fib_ht_params
);
4585 static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib
*fib
,
4586 struct mlxsw_sp_fib_node
*fib_node
)
4588 rhashtable_remove_fast(&fib
->ht
, &fib_node
->ht_node
,
4589 mlxsw_sp_fib_ht_params
);
4592 static struct mlxsw_sp_fib_node
*
4593 mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib
*fib
, const void *addr
,
4594 size_t addr_len
, unsigned char prefix_len
)
4596 struct mlxsw_sp_fib_key key
;
4598 memset(&key
, 0, sizeof(key
));
4599 memcpy(key
.addr
, addr
, addr_len
);
4600 key
.prefix_len
= prefix_len
;
4601 return rhashtable_lookup_fast(&fib
->ht
, &key
, mlxsw_sp_fib_ht_params
);
4604 static struct mlxsw_sp_fib_node
*
4605 mlxsw_sp_fib_node_create(struct mlxsw_sp_fib
*fib
, const void *addr
,
4606 size_t addr_len
, unsigned char prefix_len
)
4608 struct mlxsw_sp_fib_node
*fib_node
;
4610 fib_node
= kzalloc(sizeof(*fib_node
), GFP_KERNEL
);
4614 INIT_LIST_HEAD(&fib_node
->entry_list
);
4615 list_add(&fib_node
->list
, &fib
->node_list
);
4616 memcpy(fib_node
->key
.addr
, addr
, addr_len
);
4617 fib_node
->key
.prefix_len
= prefix_len
;
4622 static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node
*fib_node
)
4624 list_del(&fib_node
->list
);
4625 WARN_ON(!list_empty(&fib_node
->entry_list
));
4630 mlxsw_sp_fib_node_entry_is_first(const struct mlxsw_sp_fib_node
*fib_node
,
4631 const struct mlxsw_sp_fib_entry
*fib_entry
)
4633 return list_first_entry(&fib_node
->entry_list
,
4634 struct mlxsw_sp_fib_entry
, list
) == fib_entry
;
4637 static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp
*mlxsw_sp
,
4638 struct mlxsw_sp_fib_node
*fib_node
)
4640 struct mlxsw_sp_prefix_usage req_prefix_usage
;
4641 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4642 struct mlxsw_sp_lpm_tree
*lpm_tree
;
4645 lpm_tree
= mlxsw_sp
->router
->lpm
.proto_trees
[fib
->proto
];
4646 if (lpm_tree
->prefix_ref_count
[fib_node
->key
.prefix_len
] != 0)
4649 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage
, &lpm_tree
->prefix_usage
);
4650 mlxsw_sp_prefix_usage_set(&req_prefix_usage
, fib_node
->key
.prefix_len
);
4651 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
4653 if (IS_ERR(lpm_tree
))
4654 return PTR_ERR(lpm_tree
);
4656 err
= mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp
, fib
, lpm_tree
);
4658 goto err_lpm_tree_replace
;
4661 lpm_tree
->prefix_ref_count
[fib_node
->key
.prefix_len
]++;
4664 err_lpm_tree_replace
:
4665 mlxsw_sp_lpm_tree_put(mlxsw_sp
, lpm_tree
);
4669 static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp
*mlxsw_sp
,
4670 struct mlxsw_sp_fib_node
*fib_node
)
4672 struct mlxsw_sp_lpm_tree
*lpm_tree
= fib_node
->fib
->lpm_tree
;
4673 struct mlxsw_sp_prefix_usage req_prefix_usage
;
4674 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4677 if (--lpm_tree
->prefix_ref_count
[fib_node
->key
.prefix_len
] != 0)
4679 /* Try to construct a new LPM tree from the current prefix usage
4680 * minus the unused one. If we fail, continue using the old one.
4682 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage
, &lpm_tree
->prefix_usage
);
4683 mlxsw_sp_prefix_usage_clear(&req_prefix_usage
,
4684 fib_node
->key
.prefix_len
);
4685 lpm_tree
= mlxsw_sp_lpm_tree_get(mlxsw_sp
, &req_prefix_usage
,
4687 if (IS_ERR(lpm_tree
))
4690 err
= mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp
, fib
, lpm_tree
);
4692 goto err_lpm_tree_replace
;
4696 err_lpm_tree_replace
:
4697 mlxsw_sp_lpm_tree_put(mlxsw_sp
, lpm_tree
);
4700 static int mlxsw_sp_fib_node_init(struct mlxsw_sp
*mlxsw_sp
,
4701 struct mlxsw_sp_fib_node
*fib_node
,
4702 struct mlxsw_sp_fib
*fib
)
4706 err
= mlxsw_sp_fib_node_insert(fib
, fib_node
);
4709 fib_node
->fib
= fib
;
4711 err
= mlxsw_sp_fib_lpm_tree_link(mlxsw_sp
, fib_node
);
4713 goto err_fib_lpm_tree_link
;
4717 err_fib_lpm_tree_link
:
4718 fib_node
->fib
= NULL
;
4719 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4723 static void mlxsw_sp_fib_node_fini(struct mlxsw_sp
*mlxsw_sp
,
4724 struct mlxsw_sp_fib_node
*fib_node
)
4726 struct mlxsw_sp_fib
*fib
= fib_node
->fib
;
4728 mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp
, fib_node
);
4729 fib_node
->fib
= NULL
;
4730 mlxsw_sp_fib_node_remove(fib
, fib_node
);
4733 static struct mlxsw_sp_fib_node
*
4734 mlxsw_sp_fib_node_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
, const void *addr
,
4735 size_t addr_len
, unsigned char prefix_len
,
4736 enum mlxsw_sp_l3proto proto
)
4738 struct mlxsw_sp_fib_node
*fib_node
;
4739 struct mlxsw_sp_fib
*fib
;
4740 struct mlxsw_sp_vr
*vr
;
4743 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
, NULL
);
4745 return ERR_CAST(vr
);
4746 fib
= mlxsw_sp_vr_fib(vr
, proto
);
4748 fib_node
= mlxsw_sp_fib_node_lookup(fib
, addr
, addr_len
, prefix_len
);
4752 fib_node
= mlxsw_sp_fib_node_create(fib
, addr
, addr_len
, prefix_len
);
4755 goto err_fib_node_create
;
4758 err
= mlxsw_sp_fib_node_init(mlxsw_sp
, fib_node
, fib
);
4760 goto err_fib_node_init
;
4765 mlxsw_sp_fib_node_destroy(fib_node
);
4766 err_fib_node_create
:
4767 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
4768 return ERR_PTR(err
);
4771 static void mlxsw_sp_fib_node_put(struct mlxsw_sp
*mlxsw_sp
,
4772 struct mlxsw_sp_fib_node
*fib_node
)
4774 struct mlxsw_sp_vr
*vr
= fib_node
->fib
->vr
;
4776 if (!list_empty(&fib_node
->entry_list
))
4778 mlxsw_sp_fib_node_fini(mlxsw_sp
, fib_node
);
4779 mlxsw_sp_fib_node_destroy(fib_node
);
4780 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
4783 static int mlxsw_sp_fib_node_entry_add(struct mlxsw_sp
*mlxsw_sp
,
4784 struct mlxsw_sp_fib_entry
*fib_entry
)
4786 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4788 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4791 /* To prevent packet loss, overwrite the previously offloaded
4794 if (!list_is_singular(&fib_node
->entry_list
)) {
4795 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4796 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4798 mlxsw_sp_fib_entry_offload_refresh(n
, op
, 0);
4801 return mlxsw_sp_fib_entry_update(mlxsw_sp
, fib_entry
);
4804 static void mlxsw_sp_fib_node_entry_del(struct mlxsw_sp
*mlxsw_sp
,
4805 struct mlxsw_sp_fib_entry
*fib_entry
)
4807 struct mlxsw_sp_fib_node
*fib_node
= fib_entry
->fib_node
;
4809 if (!mlxsw_sp_fib_node_entry_is_first(fib_node
, fib_entry
))
4812 /* Promote the next entry by overwriting the deleted entry */
4813 if (!list_is_singular(&fib_node
->entry_list
)) {
4814 struct mlxsw_sp_fib_entry
*n
= list_next_entry(fib_entry
, list
);
4815 enum mlxsw_reg_ralue_op op
= MLXSW_REG_RALUE_OP_WRITE_DELETE
;
4817 mlxsw_sp_fib_entry_update(mlxsw_sp
, n
);
4818 mlxsw_sp_fib_entry_offload_refresh(fib_entry
, op
, 0);
4822 mlxsw_sp_fib_entry_del(mlxsw_sp
, fib_entry
);
4825 static int mlxsw_sp_fib4_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
4826 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4828 struct mlxsw_sp_fib_node
*fib_node
= fib4_entry
->common
.fib_node
;
4831 list_add(&fib4_entry
->common
.list
, &fib_node
->entry_list
);
4833 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib4_entry
->common
);
4835 goto err_fib_node_entry_add
;
4839 err_fib_node_entry_add
:
4840 list_del(&fib4_entry
->common
.list
);
4845 mlxsw_sp_fib4_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
4846 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4848 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib4_entry
->common
);
4849 list_del(&fib4_entry
->common
.list
);
4851 if (fib4_entry
->common
.type
== MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP
)
4852 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp
, &fib4_entry
->common
);
4855 static void mlxsw_sp_fib4_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
4856 struct mlxsw_sp_fib4_entry
*fib4_entry
)
4858 struct mlxsw_sp_fib_node
*fib_node
= fib4_entry
->common
.fib_node
;
4859 struct mlxsw_sp_fib4_entry
*replaced
;
4861 if (list_is_singular(&fib_node
->entry_list
))
4864 /* We inserted the new entry before replaced one */
4865 replaced
= list_next_entry(fib4_entry
, common
.list
);
4867 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, replaced
);
4868 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, replaced
);
4869 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4873 mlxsw_sp_router_fib4_replace(struct mlxsw_sp
*mlxsw_sp
,
4874 const struct fib_entry_notifier_info
*fen_info
)
4876 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4877 struct mlxsw_sp_fib_node
*fib_node
;
4880 if (mlxsw_sp
->router
->aborted
)
4883 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, fen_info
->tb_id
,
4884 &fen_info
->dst
, sizeof(fen_info
->dst
),
4886 MLXSW_SP_L3_PROTO_IPV4
);
4887 if (IS_ERR(fib_node
)) {
4888 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to get FIB node\n");
4889 return PTR_ERR(fib_node
);
4892 fib4_entry
= mlxsw_sp_fib4_entry_create(mlxsw_sp
, fib_node
, fen_info
);
4893 if (IS_ERR(fib4_entry
)) {
4894 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to create FIB entry\n");
4895 err
= PTR_ERR(fib4_entry
);
4896 goto err_fib4_entry_create
;
4899 err
= mlxsw_sp_fib4_node_entry_link(mlxsw_sp
, fib4_entry
);
4901 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to link FIB entry to node\n");
4902 goto err_fib4_node_entry_link
;
4905 mlxsw_sp_fib4_entry_replace(mlxsw_sp
, fib4_entry
);
4909 err_fib4_node_entry_link
:
4910 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4911 err_fib4_entry_create
:
4912 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4916 static void mlxsw_sp_router_fib4_del(struct mlxsw_sp
*mlxsw_sp
,
4917 struct fib_entry_notifier_info
*fen_info
)
4919 struct mlxsw_sp_fib4_entry
*fib4_entry
;
4920 struct mlxsw_sp_fib_node
*fib_node
;
4922 if (mlxsw_sp
->router
->aborted
)
4925 fib4_entry
= mlxsw_sp_fib4_entry_lookup(mlxsw_sp
, fen_info
);
4926 if (WARN_ON(!fib4_entry
))
4928 fib_node
= fib4_entry
->common
.fib_node
;
4930 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
4931 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
4932 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
4935 static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info
*rt
)
4937 /* Packets with link-local destination IP arriving to the router
4938 * are trapped to the CPU, so no need to program specific routes
4941 if (ipv6_addr_type(&rt
->fib6_dst
.addr
) & IPV6_ADDR_LINKLOCAL
)
4944 /* Multicast routes aren't supported, so ignore them. Neighbour
4945 * Discovery packets are specifically trapped.
4947 if (ipv6_addr_type(&rt
->fib6_dst
.addr
) & IPV6_ADDR_MULTICAST
)
4950 /* Cloned routes are irrelevant in the forwarding path. */
4951 if (rt
->fib6_flags
& RTF_CACHE
)
4957 static struct mlxsw_sp_rt6
*mlxsw_sp_rt6_create(struct fib6_info
*rt
)
4959 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
4961 mlxsw_sp_rt6
= kzalloc(sizeof(*mlxsw_sp_rt6
), GFP_KERNEL
);
4963 return ERR_PTR(-ENOMEM
);
4965 /* In case of route replace, replaced route is deleted with
4966 * no notification. Take reference to prevent accessing freed
4969 mlxsw_sp_rt6
->rt
= rt
;
4972 return mlxsw_sp_rt6
;
4975 #if IS_ENABLED(CONFIG_IPV6)
4976 static void mlxsw_sp_rt6_release(struct fib6_info
*rt
)
4978 fib6_info_release(rt
);
4981 static void mlxsw_sp_rt6_release(struct fib6_info
*rt
)
4986 static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6
*mlxsw_sp_rt6
)
4988 mlxsw_sp_rt6_release(mlxsw_sp_rt6
->rt
);
4989 kfree(mlxsw_sp_rt6
);
4992 static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info
*rt
)
4994 /* RTF_CACHE routes are ignored */
4995 return !(rt
->fib6_flags
& RTF_ADDRCONF
) &&
4996 rt
->fib6_nh
->fib_nh_gw_family
;
4999 static struct fib6_info
*
5000 mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry
*fib6_entry
)
5002 return list_first_entry(&fib6_entry
->rt6_list
, struct mlxsw_sp_rt6
,
5006 static struct mlxsw_sp_fib6_entry
*
5007 mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
5008 const struct fib6_info
*nrt
, bool replace
)
5010 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5012 if (!mlxsw_sp_fib6_rt_can_mp(nrt
) || replace
)
5015 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5016 struct fib6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5018 /* RT6_TABLE_LOCAL and RT6_TABLE_MAIN share the same
5021 if (rt
->fib6_table
->tb6_id
> nrt
->fib6_table
->tb6_id
)
5023 if (rt
->fib6_table
->tb6_id
!= nrt
->fib6_table
->tb6_id
)
5025 if (rt
->fib6_metric
< nrt
->fib6_metric
)
5027 if (rt
->fib6_metric
== nrt
->fib6_metric
&&
5028 mlxsw_sp_fib6_rt_can_mp(rt
))
5030 if (rt
->fib6_metric
> nrt
->fib6_metric
)
5037 static struct mlxsw_sp_rt6
*
5038 mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry
*fib6_entry
,
5039 const struct fib6_info
*rt
)
5041 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5043 list_for_each_entry(mlxsw_sp_rt6
, &fib6_entry
->rt6_list
, list
) {
5044 if (mlxsw_sp_rt6
->rt
== rt
)
5045 return mlxsw_sp_rt6
;
5051 static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp
*mlxsw_sp
,
5052 const struct fib6_info
*rt
,
5053 enum mlxsw_sp_ipip_type
*ret
)
5055 return rt
->fib6_nh
->fib_nh_dev
&&
5056 mlxsw_sp_netdev_ipip_type(mlxsw_sp
, rt
->fib6_nh
->fib_nh_dev
, ret
);
5059 static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp
*mlxsw_sp
,
5060 struct mlxsw_sp_nexthop_group
*nh_grp
,
5061 struct mlxsw_sp_nexthop
*nh
,
5062 const struct fib6_info
*rt
)
5064 const struct mlxsw_sp_ipip_ops
*ipip_ops
;
5065 struct mlxsw_sp_ipip_entry
*ipip_entry
;
5066 struct net_device
*dev
= rt
->fib6_nh
->fib_nh_dev
;
5067 struct mlxsw_sp_rif
*rif
;
5070 ipip_entry
= mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp
, dev
);
5072 ipip_ops
= mlxsw_sp
->router
->ipip_ops_arr
[ipip_entry
->ipipt
];
5073 if (ipip_ops
->can_offload(mlxsw_sp
, dev
,
5074 MLXSW_SP_L3_PROTO_IPV6
)) {
5075 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_IPIP
;
5076 mlxsw_sp_nexthop_ipip_init(mlxsw_sp
, nh
, ipip_entry
);
5081 nh
->type
= MLXSW_SP_NEXTHOP_TYPE_ETH
;
5082 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
5085 mlxsw_sp_nexthop_rif_init(nh
, rif
);
5087 err
= mlxsw_sp_nexthop_neigh_init(mlxsw_sp
, nh
);
5089 goto err_nexthop_neigh_init
;
5093 err_nexthop_neigh_init
:
5094 mlxsw_sp_nexthop_rif_fini(nh
);
5098 static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp
*mlxsw_sp
,
5099 struct mlxsw_sp_nexthop
*nh
)
5101 mlxsw_sp_nexthop_type_fini(mlxsw_sp
, nh
);
5104 static int mlxsw_sp_nexthop6_init(struct mlxsw_sp
*mlxsw_sp
,
5105 struct mlxsw_sp_nexthop_group
*nh_grp
,
5106 struct mlxsw_sp_nexthop
*nh
,
5107 const struct fib6_info
*rt
)
5109 struct net_device
*dev
= rt
->fib6_nh
->fib_nh_dev
;
5111 nh
->nh_grp
= nh_grp
;
5112 nh
->nh_weight
= rt
->fib6_nh
->fib_nh_weight
;
5113 memcpy(&nh
->gw_addr
, &rt
->fib6_nh
->fib_nh_gw6
, sizeof(nh
->gw_addr
));
5114 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp
, nh
);
5116 list_add_tail(&nh
->router_list_node
, &mlxsw_sp
->router
->nexthop_list
);
5120 nh
->ifindex
= dev
->ifindex
;
5122 return mlxsw_sp_nexthop6_type_init(mlxsw_sp
, nh_grp
, nh
, rt
);
5125 static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp
*mlxsw_sp
,
5126 struct mlxsw_sp_nexthop
*nh
)
5128 mlxsw_sp_nexthop6_type_fini(mlxsw_sp
, nh
);
5129 list_del(&nh
->router_list_node
);
5130 mlxsw_sp_nexthop_counter_free(mlxsw_sp
, nh
);
5133 static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp
*mlxsw_sp
,
5134 const struct fib6_info
*rt
)
5136 return rt
->fib6_nh
->fib_nh_gw_family
||
5137 mlxsw_sp_nexthop6_ipip_type(mlxsw_sp
, rt
, NULL
);
5140 static struct mlxsw_sp_nexthop_group
*
5141 mlxsw_sp_nexthop6_group_create(struct mlxsw_sp
*mlxsw_sp
,
5142 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5144 struct mlxsw_sp_nexthop_group
*nh_grp
;
5145 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5146 struct mlxsw_sp_nexthop
*nh
;
5150 nh_grp
= kzalloc(struct_size(nh_grp
, nexthops
, fib6_entry
->nrt6
),
5153 return ERR_PTR(-ENOMEM
);
5154 INIT_LIST_HEAD(&nh_grp
->fib_list
);
5155 #if IS_ENABLED(CONFIG_IPV6)
5156 nh_grp
->neigh_tbl
= &nd_tbl
;
5158 mlxsw_sp_rt6
= list_first_entry(&fib6_entry
->rt6_list
,
5159 struct mlxsw_sp_rt6
, list
);
5160 nh_grp
->gateway
= mlxsw_sp_rt6_is_gateway(mlxsw_sp
, mlxsw_sp_rt6
->rt
);
5161 nh_grp
->count
= fib6_entry
->nrt6
;
5162 for (i
= 0; i
< nh_grp
->count
; i
++) {
5163 struct fib6_info
*rt
= mlxsw_sp_rt6
->rt
;
5165 nh
= &nh_grp
->nexthops
[i
];
5166 err
= mlxsw_sp_nexthop6_init(mlxsw_sp
, nh_grp
, nh
, rt
);
5168 goto err_nexthop6_init
;
5169 mlxsw_sp_rt6
= list_next_entry(mlxsw_sp_rt6
, list
);
5172 err
= mlxsw_sp_nexthop_group_insert(mlxsw_sp
, nh_grp
);
5174 goto err_nexthop_group_insert
;
5176 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
5179 err_nexthop_group_insert
:
5181 for (i
--; i
>= 0; i
--) {
5182 nh
= &nh_grp
->nexthops
[i
];
5183 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
5186 return ERR_PTR(err
);
5190 mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp
*mlxsw_sp
,
5191 struct mlxsw_sp_nexthop_group
*nh_grp
)
5193 struct mlxsw_sp_nexthop
*nh
;
5194 int i
= nh_grp
->count
;
5196 mlxsw_sp_nexthop_group_remove(mlxsw_sp
, nh_grp
);
5197 for (i
--; i
>= 0; i
--) {
5198 nh
= &nh_grp
->nexthops
[i
];
5199 mlxsw_sp_nexthop6_fini(mlxsw_sp
, nh
);
5201 mlxsw_sp_nexthop_group_refresh(mlxsw_sp
, nh_grp
);
5202 WARN_ON(nh_grp
->adj_index_valid
);
5206 static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp
*mlxsw_sp
,
5207 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5209 struct mlxsw_sp_nexthop_group
*nh_grp
;
5211 nh_grp
= mlxsw_sp_nexthop6_group_lookup(mlxsw_sp
, fib6_entry
);
5213 nh_grp
= mlxsw_sp_nexthop6_group_create(mlxsw_sp
, fib6_entry
);
5215 return PTR_ERR(nh_grp
);
5218 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
5220 fib6_entry
->common
.nh_group
= nh_grp
;
5225 static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp
*mlxsw_sp
,
5226 struct mlxsw_sp_fib_entry
*fib_entry
)
5228 struct mlxsw_sp_nexthop_group
*nh_grp
= fib_entry
->nh_group
;
5230 list_del(&fib_entry
->nexthop_group_node
);
5231 if (!list_empty(&nh_grp
->fib_list
))
5233 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, nh_grp
);
5237 mlxsw_sp_nexthop6_group_update(struct mlxsw_sp
*mlxsw_sp
,
5238 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5240 struct mlxsw_sp_nexthop_group
*old_nh_grp
= fib6_entry
->common
.nh_group
;
5243 fib6_entry
->common
.nh_group
= NULL
;
5244 list_del(&fib6_entry
->common
.nexthop_group_node
);
5246 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
5248 goto err_nexthop6_group_get
;
5250 /* In case this entry is offloaded, then the adjacency index
5251 * currently associated with it in the device's table is that
5252 * of the old group. Start using the new one instead.
5254 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
5256 goto err_fib_node_entry_add
;
5258 if (list_empty(&old_nh_grp
->fib_list
))
5259 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp
, old_nh_grp
);
5263 err_fib_node_entry_add
:
5264 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
5265 err_nexthop6_group_get
:
5266 list_add_tail(&fib6_entry
->common
.nexthop_group_node
,
5267 &old_nh_grp
->fib_list
);
5268 fib6_entry
->common
.nh_group
= old_nh_grp
;
5273 mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp
*mlxsw_sp
,
5274 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5275 struct fib6_info
**rt_arr
, unsigned int nrt6
)
5277 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5280 for (i
= 0; i
< nrt6
; i
++) {
5281 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt_arr
[i
]);
5282 if (IS_ERR(mlxsw_sp_rt6
)) {
5283 err
= PTR_ERR(mlxsw_sp_rt6
);
5284 goto err_rt6_create
;
5287 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
5291 err
= mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
5293 goto err_nexthop6_group_update
;
5297 err_nexthop6_group_update
:
5300 for (i
--; i
>= 0; i
--) {
5302 mlxsw_sp_rt6
= list_last_entry(&fib6_entry
->rt6_list
,
5303 struct mlxsw_sp_rt6
, list
);
5304 list_del(&mlxsw_sp_rt6
->list
);
5305 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5311 mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp
*mlxsw_sp
,
5312 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5313 struct fib6_info
**rt_arr
, unsigned int nrt6
)
5315 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5318 for (i
= 0; i
< nrt6
; i
++) {
5319 mlxsw_sp_rt6
= mlxsw_sp_fib6_entry_rt_find(fib6_entry
,
5321 if (WARN_ON_ONCE(!mlxsw_sp_rt6
))
5325 list_del(&mlxsw_sp_rt6
->list
);
5326 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5329 mlxsw_sp_nexthop6_group_update(mlxsw_sp
, fib6_entry
);
5332 static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp
*mlxsw_sp
,
5333 struct mlxsw_sp_fib_entry
*fib_entry
,
5334 const struct fib6_info
*rt
)
5336 /* Packets hitting RTF_REJECT routes need to be discarded by the
5337 * stack. We can rely on their destination device not having a
5338 * RIF (it's the loopback device) and can thus use action type
5339 * local, which will cause them to be trapped with a lower
5340 * priority than packets that need to be locally received.
5342 if (rt
->fib6_flags
& (RTF_LOCAL
| RTF_ANYCAST
))
5343 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_TRAP
;
5344 else if (rt
->fib6_type
== RTN_BLACKHOLE
)
5345 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE
;
5346 else if (rt
->fib6_flags
& RTF_REJECT
)
5347 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE
;
5348 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp
, rt
))
5349 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_REMOTE
;
5351 fib_entry
->type
= MLXSW_SP_FIB_ENTRY_TYPE_LOCAL
;
5355 mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5357 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
, *tmp
;
5359 list_for_each_entry_safe(mlxsw_sp_rt6
, tmp
, &fib6_entry
->rt6_list
,
5362 list_del(&mlxsw_sp_rt6
->list
);
5363 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5367 static struct mlxsw_sp_fib6_entry
*
5368 mlxsw_sp_fib6_entry_create(struct mlxsw_sp
*mlxsw_sp
,
5369 struct mlxsw_sp_fib_node
*fib_node
,
5370 struct fib6_info
**rt_arr
, unsigned int nrt6
)
5372 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5373 struct mlxsw_sp_fib_entry
*fib_entry
;
5374 struct mlxsw_sp_rt6
*mlxsw_sp_rt6
;
5377 fib6_entry
= kzalloc(sizeof(*fib6_entry
), GFP_KERNEL
);
5379 return ERR_PTR(-ENOMEM
);
5380 fib_entry
= &fib6_entry
->common
;
5382 INIT_LIST_HEAD(&fib6_entry
->rt6_list
);
5384 for (i
= 0; i
< nrt6
; i
++) {
5385 mlxsw_sp_rt6
= mlxsw_sp_rt6_create(rt_arr
[i
]);
5386 if (IS_ERR(mlxsw_sp_rt6
)) {
5387 err
= PTR_ERR(mlxsw_sp_rt6
);
5388 goto err_rt6_create
;
5390 list_add_tail(&mlxsw_sp_rt6
->list
, &fib6_entry
->rt6_list
);
5394 mlxsw_sp_fib6_entry_type_set(mlxsw_sp
, fib_entry
, rt_arr
[0]);
5396 err
= mlxsw_sp_nexthop6_group_get(mlxsw_sp
, fib6_entry
);
5398 goto err_nexthop6_group_get
;
5400 fib_entry
->fib_node
= fib_node
;
5404 err_nexthop6_group_get
:
5407 for (i
--; i
>= 0; i
--) {
5409 mlxsw_sp_rt6
= list_last_entry(&fib6_entry
->rt6_list
,
5410 struct mlxsw_sp_rt6
, list
);
5411 list_del(&mlxsw_sp_rt6
->list
);
5412 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6
);
5415 return ERR_PTR(err
);
5418 static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp
*mlxsw_sp
,
5419 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5421 mlxsw_sp_nexthop6_group_put(mlxsw_sp
, &fib6_entry
->common
);
5422 mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry
);
5423 WARN_ON(fib6_entry
->nrt6
);
5427 static struct mlxsw_sp_fib6_entry
*
5428 mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node
*fib_node
,
5429 const struct fib6_info
*nrt
, bool replace
)
5431 struct mlxsw_sp_fib6_entry
*fib6_entry
, *fallback
= NULL
;
5433 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5434 struct fib6_info
*rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5436 if (rt
->fib6_table
->tb6_id
> nrt
->fib6_table
->tb6_id
)
5438 if (rt
->fib6_table
->tb6_id
!= nrt
->fib6_table
->tb6_id
)
5440 if (replace
&& rt
->fib6_metric
== nrt
->fib6_metric
) {
5441 if (mlxsw_sp_fib6_rt_can_mp(rt
) ==
5442 mlxsw_sp_fib6_rt_can_mp(nrt
))
5444 if (mlxsw_sp_fib6_rt_can_mp(nrt
))
5445 fallback
= fallback
?: fib6_entry
;
5447 if (rt
->fib6_metric
> nrt
->fib6_metric
)
5448 return fallback
?: fib6_entry
;
5455 mlxsw_sp_fib6_node_list_insert(struct mlxsw_sp_fib6_entry
*new6_entry
,
5458 struct mlxsw_sp_fib_node
*fib_node
= new6_entry
->common
.fib_node
;
5459 struct fib6_info
*nrt
= mlxsw_sp_fib6_entry_rt(new6_entry
);
5460 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5462 fib6_entry
= mlxsw_sp_fib6_node_entry_find(fib_node
, nrt
, *p_replace
);
5464 if (*p_replace
&& !fib6_entry
)
5468 list_add_tail(&new6_entry
->common
.list
,
5469 &fib6_entry
->common
.list
);
5471 struct mlxsw_sp_fib6_entry
*last
;
5473 list_for_each_entry(last
, &fib_node
->entry_list
, common
.list
) {
5474 struct fib6_info
*rt
= mlxsw_sp_fib6_entry_rt(last
);
5476 if (nrt
->fib6_table
->tb6_id
> rt
->fib6_table
->tb6_id
)
5482 list_add(&new6_entry
->common
.list
,
5483 &fib6_entry
->common
.list
);
5485 list_add(&new6_entry
->common
.list
,
5486 &fib_node
->entry_list
);
5493 mlxsw_sp_fib6_node_list_remove(struct mlxsw_sp_fib6_entry
*fib6_entry
)
5495 list_del(&fib6_entry
->common
.list
);
5498 static int mlxsw_sp_fib6_node_entry_link(struct mlxsw_sp
*mlxsw_sp
,
5499 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5504 err
= mlxsw_sp_fib6_node_list_insert(fib6_entry
, p_replace
);
5508 err
= mlxsw_sp_fib_node_entry_add(mlxsw_sp
, &fib6_entry
->common
);
5510 goto err_fib_node_entry_add
;
5514 err_fib_node_entry_add
:
5515 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5520 mlxsw_sp_fib6_node_entry_unlink(struct mlxsw_sp
*mlxsw_sp
,
5521 struct mlxsw_sp_fib6_entry
*fib6_entry
)
5523 mlxsw_sp_fib_node_entry_del(mlxsw_sp
, &fib6_entry
->common
);
5524 mlxsw_sp_fib6_node_list_remove(fib6_entry
);
5527 static struct mlxsw_sp_fib6_entry
*
5528 mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp
*mlxsw_sp
,
5529 const struct fib6_info
*rt
)
5531 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5532 struct mlxsw_sp_fib_node
*fib_node
;
5533 struct mlxsw_sp_fib
*fib
;
5534 struct mlxsw_sp_vr
*vr
;
5536 vr
= mlxsw_sp_vr_find(mlxsw_sp
, rt
->fib6_table
->tb6_id
);
5539 fib
= mlxsw_sp_vr_fib(vr
, MLXSW_SP_L3_PROTO_IPV6
);
5541 fib_node
= mlxsw_sp_fib_node_lookup(fib
, &rt
->fib6_dst
.addr
,
5542 sizeof(rt
->fib6_dst
.addr
),
5547 list_for_each_entry(fib6_entry
, &fib_node
->entry_list
, common
.list
) {
5548 struct fib6_info
*iter_rt
= mlxsw_sp_fib6_entry_rt(fib6_entry
);
5550 if (rt
->fib6_table
->tb6_id
== iter_rt
->fib6_table
->tb6_id
&&
5551 rt
->fib6_metric
== iter_rt
->fib6_metric
&&
5552 mlxsw_sp_fib6_entry_rt_find(fib6_entry
, rt
))
5559 static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp
*mlxsw_sp
,
5560 struct mlxsw_sp_fib6_entry
*fib6_entry
,
5563 struct mlxsw_sp_fib_node
*fib_node
= fib6_entry
->common
.fib_node
;
5564 struct mlxsw_sp_fib6_entry
*replaced
;
5569 replaced
= list_next_entry(fib6_entry
, common
.list
);
5571 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, replaced
);
5572 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, replaced
);
5573 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5576 static int mlxsw_sp_router_fib6_add(struct mlxsw_sp
*mlxsw_sp
,
5577 struct fib6_info
**rt_arr
,
5578 unsigned int nrt6
, bool replace
)
5580 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5581 struct mlxsw_sp_fib_node
*fib_node
;
5582 struct fib6_info
*rt
= rt_arr
[0];
5585 if (mlxsw_sp
->router
->aborted
)
5588 if (rt
->fib6_src
.plen
)
5591 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5594 fib_node
= mlxsw_sp_fib_node_get(mlxsw_sp
, rt
->fib6_table
->tb6_id
,
5596 sizeof(rt
->fib6_dst
.addr
),
5598 MLXSW_SP_L3_PROTO_IPV6
);
5599 if (IS_ERR(fib_node
))
5600 return PTR_ERR(fib_node
);
5602 /* Before creating a new entry, try to append route to an existing
5605 fib6_entry
= mlxsw_sp_fib6_node_mp_entry_find(fib_node
, rt
, replace
);
5607 err
= mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp
, fib6_entry
,
5610 goto err_fib6_entry_nexthop_add
;
5614 fib6_entry
= mlxsw_sp_fib6_entry_create(mlxsw_sp
, fib_node
, rt_arr
,
5616 if (IS_ERR(fib6_entry
)) {
5617 err
= PTR_ERR(fib6_entry
);
5618 goto err_fib6_entry_create
;
5621 err
= mlxsw_sp_fib6_node_entry_link(mlxsw_sp
, fib6_entry
, &replace
);
5623 goto err_fib6_node_entry_link
;
5625 mlxsw_sp_fib6_entry_replace(mlxsw_sp
, fib6_entry
, replace
);
5629 err_fib6_node_entry_link
:
5630 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5631 err_fib6_entry_create
:
5632 err_fib6_entry_nexthop_add
:
5633 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5637 static void mlxsw_sp_router_fib6_del(struct mlxsw_sp
*mlxsw_sp
,
5638 struct fib6_info
**rt_arr
,
5641 struct mlxsw_sp_fib6_entry
*fib6_entry
;
5642 struct mlxsw_sp_fib_node
*fib_node
;
5643 struct fib6_info
*rt
= rt_arr
[0];
5645 if (mlxsw_sp
->router
->aborted
)
5648 if (mlxsw_sp_fib6_rt_should_ignore(rt
))
5651 /* Multipath routes are first added to the FIB trie and only then
5652 * notified. If we vetoed the addition, we will get a delete
5653 * notification for a route we do not have. Therefore, do not warn if
5654 * route was not found.
5656 fib6_entry
= mlxsw_sp_fib6_entry_lookup(mlxsw_sp
, rt
);
5660 /* If not all the nexthops are deleted, then only reduce the nexthop
5663 if (nrt6
!= fib6_entry
->nrt6
) {
5664 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp
, fib6_entry
, rt_arr
,
5669 fib_node
= fib6_entry
->common
.fib_node
;
5671 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5672 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5673 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5676 static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
,
5677 enum mlxsw_reg_ralxx_protocol proto
,
5680 char ralta_pl
[MLXSW_REG_RALTA_LEN
];
5681 char ralst_pl
[MLXSW_REG_RALST_LEN
];
5684 mlxsw_reg_ralta_pack(ralta_pl
, true, proto
, tree_id
);
5685 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralta
), ralta_pl
);
5689 mlxsw_reg_ralst_pack(ralst_pl
, 0xff, tree_id
);
5690 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralst
), ralst_pl
);
5694 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5695 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5696 char raltb_pl
[MLXSW_REG_RALTB_LEN
];
5697 char ralue_pl
[MLXSW_REG_RALUE_LEN
];
5699 mlxsw_reg_raltb_pack(raltb_pl
, vr
->id
, proto
, tree_id
);
5700 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(raltb
),
5705 mlxsw_reg_ralue_pack(ralue_pl
, proto
,
5706 MLXSW_REG_RALUE_OP_WRITE_WRITE
, vr
->id
, 0);
5707 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl
);
5708 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ralue
),
5717 static struct mlxsw_sp_mr_table
*
5718 mlxsw_sp_router_fibmr_family_to_table(struct mlxsw_sp_vr
*vr
, int family
)
5720 if (family
== RTNL_FAMILY_IPMR
)
5721 return vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV4
];
5723 return vr
->mr_table
[MLXSW_SP_L3_PROTO_IPV6
];
5726 static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp
*mlxsw_sp
,
5727 struct mfc_entry_notifier_info
*men_info
,
5730 struct mlxsw_sp_mr_table
*mrt
;
5731 struct mlxsw_sp_vr
*vr
;
5733 if (mlxsw_sp
->router
->aborted
)
5736 vr
= mlxsw_sp_vr_get(mlxsw_sp
, men_info
->tb_id
, NULL
);
5740 mrt
= mlxsw_sp_router_fibmr_family_to_table(vr
, men_info
->info
.family
);
5741 return mlxsw_sp_mr_route_add(mrt
, men_info
->mfc
, replace
);
5744 static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp
*mlxsw_sp
,
5745 struct mfc_entry_notifier_info
*men_info
)
5747 struct mlxsw_sp_mr_table
*mrt
;
5748 struct mlxsw_sp_vr
*vr
;
5750 if (mlxsw_sp
->router
->aborted
)
5753 vr
= mlxsw_sp_vr_find(mlxsw_sp
, men_info
->tb_id
);
5757 mrt
= mlxsw_sp_router_fibmr_family_to_table(vr
, men_info
->info
.family
);
5758 mlxsw_sp_mr_route_del(mrt
, men_info
->mfc
);
5759 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
5763 mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp
*mlxsw_sp
,
5764 struct vif_entry_notifier_info
*ven_info
)
5766 struct mlxsw_sp_mr_table
*mrt
;
5767 struct mlxsw_sp_rif
*rif
;
5768 struct mlxsw_sp_vr
*vr
;
5770 if (mlxsw_sp
->router
->aborted
)
5773 vr
= mlxsw_sp_vr_get(mlxsw_sp
, ven_info
->tb_id
, NULL
);
5777 mrt
= mlxsw_sp_router_fibmr_family_to_table(vr
, ven_info
->info
.family
);
5778 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, ven_info
->dev
);
5779 return mlxsw_sp_mr_vif_add(mrt
, ven_info
->dev
,
5780 ven_info
->vif_index
,
5781 ven_info
->vif_flags
, rif
);
5785 mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp
*mlxsw_sp
,
5786 struct vif_entry_notifier_info
*ven_info
)
5788 struct mlxsw_sp_mr_table
*mrt
;
5789 struct mlxsw_sp_vr
*vr
;
5791 if (mlxsw_sp
->router
->aborted
)
5794 vr
= mlxsw_sp_vr_find(mlxsw_sp
, ven_info
->tb_id
);
5798 mrt
= mlxsw_sp_router_fibmr_family_to_table(vr
, ven_info
->info
.family
);
5799 mlxsw_sp_mr_vif_del(mrt
, ven_info
->vif_index
);
5800 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
5803 static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp
*mlxsw_sp
)
5805 enum mlxsw_reg_ralxx_protocol proto
= MLXSW_REG_RALXX_PROTOCOL_IPV4
;
5808 err
= __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5809 MLXSW_SP_LPM_TREE_MIN
);
5813 /* The multicast router code does not need an abort trap as by default,
5814 * packets that don't match any routes are trapped to the CPU.
5817 proto
= MLXSW_REG_RALXX_PROTOCOL_IPV6
;
5818 return __mlxsw_sp_router_set_abort_trap(mlxsw_sp
, proto
,
5819 MLXSW_SP_LPM_TREE_MIN
+ 1);
5822 static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5823 struct mlxsw_sp_fib_node
*fib_node
)
5825 struct mlxsw_sp_fib4_entry
*fib4_entry
, *tmp
;
5827 list_for_each_entry_safe(fib4_entry
, tmp
, &fib_node
->entry_list
,
5829 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5831 mlxsw_sp_fib4_node_entry_unlink(mlxsw_sp
, fib4_entry
);
5832 mlxsw_sp_fib4_entry_destroy(mlxsw_sp
, fib4_entry
);
5833 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5834 /* Break when entry list is empty and node was freed.
5835 * Otherwise, we'll access freed memory in the next
5843 static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5844 struct mlxsw_sp_fib_node
*fib_node
)
5846 struct mlxsw_sp_fib6_entry
*fib6_entry
, *tmp
;
5848 list_for_each_entry_safe(fib6_entry
, tmp
, &fib_node
->entry_list
,
5850 bool do_break
= &tmp
->common
.list
== &fib_node
->entry_list
;
5852 mlxsw_sp_fib6_node_entry_unlink(mlxsw_sp
, fib6_entry
);
5853 mlxsw_sp_fib6_entry_destroy(mlxsw_sp
, fib6_entry
);
5854 mlxsw_sp_fib_node_put(mlxsw_sp
, fib_node
);
5860 static void mlxsw_sp_fib_node_flush(struct mlxsw_sp
*mlxsw_sp
,
5861 struct mlxsw_sp_fib_node
*fib_node
)
5863 switch (fib_node
->fib
->proto
) {
5864 case MLXSW_SP_L3_PROTO_IPV4
:
5865 mlxsw_sp_fib4_node_flush(mlxsw_sp
, fib_node
);
5867 case MLXSW_SP_L3_PROTO_IPV6
:
5868 mlxsw_sp_fib6_node_flush(mlxsw_sp
, fib_node
);
5873 static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp
*mlxsw_sp
,
5874 struct mlxsw_sp_vr
*vr
,
5875 enum mlxsw_sp_l3proto proto
)
5877 struct mlxsw_sp_fib
*fib
= mlxsw_sp_vr_fib(vr
, proto
);
5878 struct mlxsw_sp_fib_node
*fib_node
, *tmp
;
5880 list_for_each_entry_safe(fib_node
, tmp
, &fib
->node_list
, list
) {
5881 bool do_break
= &tmp
->list
== &fib
->node_list
;
5883 mlxsw_sp_fib_node_flush(mlxsw_sp
, fib_node
);
5889 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp
*mlxsw_sp
)
5893 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_VRS
); i
++) {
5894 struct mlxsw_sp_vr
*vr
= &mlxsw_sp
->router
->vrs
[i
];
5896 if (!mlxsw_sp_vr_is_used(vr
))
5899 for (j
= 0; j
< MLXSW_SP_L3_PROTO_MAX
; j
++)
5900 mlxsw_sp_mr_table_flush(vr
->mr_table
[j
]);
5901 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV4
);
5903 /* If virtual router was only used for IPv4, then it's no
5906 if (!mlxsw_sp_vr_is_used(vr
))
5908 mlxsw_sp_vr_fib_flush(mlxsw_sp
, vr
, MLXSW_SP_L3_PROTO_IPV6
);
5911 /* After flushing all the routes, it is not possible anyone is still
5912 * using the adjacency index that is discarding packets, so free it in
5913 * case it was allocated.
5915 if (!mlxsw_sp
->router
->adj_discard_index_valid
)
5917 mlxsw_sp_kvdl_free(mlxsw_sp
, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ
, 1,
5918 mlxsw_sp
->router
->adj_discard_index
);
5919 mlxsw_sp
->router
->adj_discard_index_valid
= false;
5922 static void mlxsw_sp_router_fib_abort(struct mlxsw_sp
*mlxsw_sp
)
5926 if (mlxsw_sp
->router
->aborted
)
5928 dev_warn(mlxsw_sp
->bus_info
->dev
, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
5929 mlxsw_sp_router_fib_flush(mlxsw_sp
);
5930 mlxsw_sp
->router
->aborted
= true;
5931 err
= mlxsw_sp_router_set_abort_trap(mlxsw_sp
);
5933 dev_warn(mlxsw_sp
->bus_info
->dev
, "Failed to set abort trap.\n");
5936 struct mlxsw_sp_fib6_event_work
{
5937 struct fib6_info
**rt_arr
;
5941 struct mlxsw_sp_fib_event_work
{
5942 struct work_struct work
;
5944 struct mlxsw_sp_fib6_event_work fib6_work
;
5945 struct fib_entry_notifier_info fen_info
;
5946 struct fib_rule_notifier_info fr_info
;
5947 struct fib_nh_notifier_info fnh_info
;
5948 struct mfc_entry_notifier_info men_info
;
5949 struct vif_entry_notifier_info ven_info
;
5951 struct mlxsw_sp
*mlxsw_sp
;
5952 unsigned long event
;
5956 mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work
*fib6_work
,
5957 struct fib6_entry_notifier_info
*fen6_info
)
5959 struct fib6_info
*rt
= fen6_info
->rt
;
5960 struct fib6_info
**rt_arr
;
5961 struct fib6_info
*iter
;
5965 nrt6
= fen6_info
->nsiblings
+ 1;
5967 rt_arr
= kcalloc(nrt6
, sizeof(struct fib6_info
*), GFP_ATOMIC
);
5971 fib6_work
->rt_arr
= rt_arr
;
5972 fib6_work
->nrt6
= nrt6
;
5977 if (!fen6_info
->nsiblings
)
5980 list_for_each_entry(iter
, &rt
->fib6_siblings
, fib6_siblings
) {
5981 if (i
== fen6_info
->nsiblings
)
5984 rt_arr
[i
+ 1] = iter
;
5985 fib6_info_hold(iter
);
5988 WARN_ON_ONCE(i
!= fen6_info
->nsiblings
);
5994 mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work
*fib6_work
)
5998 for (i
= 0; i
< fib6_work
->nrt6
; i
++)
5999 mlxsw_sp_rt6_release(fib6_work
->rt_arr
[i
]);
6000 kfree(fib6_work
->rt_arr
);
6003 static void mlxsw_sp_router_fib4_event_work(struct work_struct
*work
)
6005 struct mlxsw_sp_fib_event_work
*fib_work
=
6006 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
6007 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
6010 /* Protect internal structures from changes */
6012 mlxsw_sp_span_respin(mlxsw_sp
);
6014 switch (fib_work
->event
) {
6015 case FIB_EVENT_ENTRY_REPLACE
:
6016 err
= mlxsw_sp_router_fib4_replace(mlxsw_sp
,
6017 &fib_work
->fen_info
);
6019 mlxsw_sp_router_fib_abort(mlxsw_sp
);
6020 fib_info_put(fib_work
->fen_info
.fi
);
6022 case FIB_EVENT_ENTRY_DEL
:
6023 mlxsw_sp_router_fib4_del(mlxsw_sp
, &fib_work
->fen_info
);
6024 fib_info_put(fib_work
->fen_info
.fi
);
6026 case FIB_EVENT_NH_ADD
: /* fall through */
6027 case FIB_EVENT_NH_DEL
:
6028 mlxsw_sp_nexthop4_event(mlxsw_sp
, fib_work
->event
,
6029 fib_work
->fnh_info
.fib_nh
);
6030 fib_info_put(fib_work
->fnh_info
.fib_nh
->nh_parent
);
6037 static void mlxsw_sp_router_fib6_event_work(struct work_struct
*work
)
6039 struct mlxsw_sp_fib_event_work
*fib_work
=
6040 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
6041 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
6046 mlxsw_sp_span_respin(mlxsw_sp
);
6048 switch (fib_work
->event
) {
6049 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
6050 case FIB_EVENT_ENTRY_ADD
:
6051 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
6052 err
= mlxsw_sp_router_fib6_add(mlxsw_sp
,
6053 fib_work
->fib6_work
.rt_arr
,
6054 fib_work
->fib6_work
.nrt6
,
6057 mlxsw_sp_router_fib_abort(mlxsw_sp
);
6058 mlxsw_sp_router_fib6_work_fini(&fib_work
->fib6_work
);
6060 case FIB_EVENT_ENTRY_DEL
:
6061 mlxsw_sp_router_fib6_del(mlxsw_sp
,
6062 fib_work
->fib6_work
.rt_arr
,
6063 fib_work
->fib6_work
.nrt6
);
6064 mlxsw_sp_router_fib6_work_fini(&fib_work
->fib6_work
);
6071 static void mlxsw_sp_router_fibmr_event_work(struct work_struct
*work
)
6073 struct mlxsw_sp_fib_event_work
*fib_work
=
6074 container_of(work
, struct mlxsw_sp_fib_event_work
, work
);
6075 struct mlxsw_sp
*mlxsw_sp
= fib_work
->mlxsw_sp
;
6080 switch (fib_work
->event
) {
6081 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
6082 case FIB_EVENT_ENTRY_ADD
:
6083 replace
= fib_work
->event
== FIB_EVENT_ENTRY_REPLACE
;
6085 err
= mlxsw_sp_router_fibmr_add(mlxsw_sp
, &fib_work
->men_info
,
6088 mlxsw_sp_router_fib_abort(mlxsw_sp
);
6089 mr_cache_put(fib_work
->men_info
.mfc
);
6091 case FIB_EVENT_ENTRY_DEL
:
6092 mlxsw_sp_router_fibmr_del(mlxsw_sp
, &fib_work
->men_info
);
6093 mr_cache_put(fib_work
->men_info
.mfc
);
6095 case FIB_EVENT_VIF_ADD
:
6096 err
= mlxsw_sp_router_fibmr_vif_add(mlxsw_sp
,
6097 &fib_work
->ven_info
);
6099 mlxsw_sp_router_fib_abort(mlxsw_sp
);
6100 dev_put(fib_work
->ven_info
.dev
);
6102 case FIB_EVENT_VIF_DEL
:
6103 mlxsw_sp_router_fibmr_vif_del(mlxsw_sp
,
6104 &fib_work
->ven_info
);
6105 dev_put(fib_work
->ven_info
.dev
);
6112 static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work
*fib_work
,
6113 struct fib_notifier_info
*info
)
6115 struct fib_entry_notifier_info
*fen_info
;
6116 struct fib_nh_notifier_info
*fnh_info
;
6118 switch (fib_work
->event
) {
6119 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
6120 case FIB_EVENT_ENTRY_DEL
:
6121 fen_info
= container_of(info
, struct fib_entry_notifier_info
,
6123 fib_work
->fen_info
= *fen_info
;
6124 /* Take reference on fib_info to prevent it from being
6125 * freed while work is queued. Release it afterwards.
6127 fib_info_hold(fib_work
->fen_info
.fi
);
6129 case FIB_EVENT_NH_ADD
: /* fall through */
6130 case FIB_EVENT_NH_DEL
:
6131 fnh_info
= container_of(info
, struct fib_nh_notifier_info
,
6133 fib_work
->fnh_info
= *fnh_info
;
6134 fib_info_hold(fib_work
->fnh_info
.fib_nh
->nh_parent
);
6139 static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work
*fib_work
,
6140 struct fib_notifier_info
*info
)
6142 struct fib6_entry_notifier_info
*fen6_info
;
6145 switch (fib_work
->event
) {
6146 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
6147 case FIB_EVENT_ENTRY_ADD
: /* fall through */
6148 case FIB_EVENT_ENTRY_DEL
:
6149 fen6_info
= container_of(info
, struct fib6_entry_notifier_info
,
6151 err
= mlxsw_sp_router_fib6_work_init(&fib_work
->fib6_work
,
6162 mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work
*fib_work
,
6163 struct fib_notifier_info
*info
)
6165 switch (fib_work
->event
) {
6166 case FIB_EVENT_ENTRY_REPLACE
: /* fall through */
6167 case FIB_EVENT_ENTRY_ADD
: /* fall through */
6168 case FIB_EVENT_ENTRY_DEL
:
6169 memcpy(&fib_work
->men_info
, info
, sizeof(fib_work
->men_info
));
6170 mr_cache_hold(fib_work
->men_info
.mfc
);
6172 case FIB_EVENT_VIF_ADD
: /* fall through */
6173 case FIB_EVENT_VIF_DEL
:
6174 memcpy(&fib_work
->ven_info
, info
, sizeof(fib_work
->ven_info
));
6175 dev_hold(fib_work
->ven_info
.dev
);
6180 static int mlxsw_sp_router_fib_rule_event(unsigned long event
,
6181 struct fib_notifier_info
*info
,
6182 struct mlxsw_sp
*mlxsw_sp
)
6184 struct netlink_ext_ack
*extack
= info
->extack
;
6185 struct fib_rule_notifier_info
*fr_info
;
6186 struct fib_rule
*rule
;
6189 /* nothing to do at the moment */
6190 if (event
== FIB_EVENT_RULE_DEL
)
6193 if (mlxsw_sp
->router
->aborted
)
6196 fr_info
= container_of(info
, struct fib_rule_notifier_info
, info
);
6197 rule
= fr_info
->rule
;
6199 /* Rule only affects locally generated traffic */
6200 if (rule
->iifindex
== mlxsw_sp_net(mlxsw_sp
)->loopback_dev
->ifindex
)
6203 switch (info
->family
) {
6205 if (!fib4_rule_default(rule
) && !rule
->l3mdev
)
6209 if (!fib6_rule_default(rule
) && !rule
->l3mdev
)
6212 case RTNL_FAMILY_IPMR
:
6213 if (!ipmr_rule_default(rule
) && !rule
->l3mdev
)
6216 case RTNL_FAMILY_IP6MR
:
6217 if (!ip6mr_rule_default(rule
) && !rule
->l3mdev
)
6223 NL_SET_ERR_MSG_MOD(extack
, "FIB rules not supported");
6228 /* Called with rcu_read_lock() */
6229 static int mlxsw_sp_router_fib_event(struct notifier_block
*nb
,
6230 unsigned long event
, void *ptr
)
6232 struct mlxsw_sp_fib_event_work
*fib_work
;
6233 struct fib_notifier_info
*info
= ptr
;
6234 struct mlxsw_sp_router
*router
;
6237 if ((info
->family
!= AF_INET
&& info
->family
!= AF_INET6
&&
6238 info
->family
!= RTNL_FAMILY_IPMR
&&
6239 info
->family
!= RTNL_FAMILY_IP6MR
))
6242 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
6245 case FIB_EVENT_RULE_ADD
: /* fall through */
6246 case FIB_EVENT_RULE_DEL
:
6247 err
= mlxsw_sp_router_fib_rule_event(event
, info
,
6249 return notifier_from_errno(err
);
6250 case FIB_EVENT_ENTRY_ADD
: /* fall through */
6251 case FIB_EVENT_ENTRY_REPLACE
:
6252 if (router
->aborted
) {
6253 NL_SET_ERR_MSG_MOD(info
->extack
, "FIB offload was aborted. Not configuring route");
6254 return notifier_from_errno(-EINVAL
);
6256 if (info
->family
== AF_INET
) {
6257 struct fib_entry_notifier_info
*fen_info
= ptr
;
6259 if (fen_info
->fi
->fib_nh_is_v6
) {
6260 NL_SET_ERR_MSG_MOD(info
->extack
, "IPv6 gateway with IPv4 route is not supported");
6261 return notifier_from_errno(-EINVAL
);
6263 if (fen_info
->fi
->nh
) {
6264 NL_SET_ERR_MSG_MOD(info
->extack
, "IPv4 route with nexthop objects is not supported");
6265 return notifier_from_errno(-EINVAL
);
6267 } else if (info
->family
== AF_INET6
) {
6268 struct fib6_entry_notifier_info
*fen6_info
;
6270 fen6_info
= container_of(info
,
6271 struct fib6_entry_notifier_info
,
6273 if (fen6_info
->rt
->nh
) {
6274 NL_SET_ERR_MSG_MOD(info
->extack
, "IPv6 route with nexthop objects is not supported");
6275 return notifier_from_errno(-EINVAL
);
6281 fib_work
= kzalloc(sizeof(*fib_work
), GFP_ATOMIC
);
6282 if (WARN_ON(!fib_work
))
6285 fib_work
->mlxsw_sp
= router
->mlxsw_sp
;
6286 fib_work
->event
= event
;
6288 switch (info
->family
) {
6290 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib4_event_work
);
6291 mlxsw_sp_router_fib4_event(fib_work
, info
);
6294 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fib6_event_work
);
6295 err
= mlxsw_sp_router_fib6_event(fib_work
, info
);
6299 case RTNL_FAMILY_IP6MR
:
6300 case RTNL_FAMILY_IPMR
:
6301 INIT_WORK(&fib_work
->work
, mlxsw_sp_router_fibmr_event_work
);
6302 mlxsw_sp_router_fibmr_event(fib_work
, info
);
6306 mlxsw_core_schedule_work(&fib_work
->work
);
6315 struct mlxsw_sp_rif
*
6316 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp
*mlxsw_sp
,
6317 const struct net_device
*dev
)
6321 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
6322 if (mlxsw_sp
->router
->rifs
[i
] &&
6323 mlxsw_sp
->router
->rifs
[i
]->dev
== dev
)
6324 return mlxsw_sp
->router
->rifs
[i
];
6329 static int mlxsw_sp_router_rif_disable(struct mlxsw_sp
*mlxsw_sp
, u16 rif
)
6331 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6334 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif
);
6335 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6339 mlxsw_reg_ritr_enable_set(ritr_pl
, false);
6340 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6343 static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp
*mlxsw_sp
,
6344 struct mlxsw_sp_rif
*rif
)
6346 mlxsw_sp_router_rif_disable(mlxsw_sp
, rif
->rif_index
);
6347 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp
, rif
);
6348 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp
, rif
);
6352 mlxsw_sp_rif_should_config(struct mlxsw_sp_rif
*rif
, struct net_device
*dev
,
6353 unsigned long event
)
6355 struct inet6_dev
*inet6_dev
;
6356 bool addr_list_empty
= true;
6357 struct in_device
*idev
;
6363 idev
= __in_dev_get_rtnl(dev
);
6364 if (idev
&& idev
->ifa_list
)
6365 addr_list_empty
= false;
6367 inet6_dev
= __in6_dev_get(dev
);
6368 if (addr_list_empty
&& inet6_dev
&&
6369 !list_empty(&inet6_dev
->addr_list
))
6370 addr_list_empty
= false;
6372 /* macvlans do not have a RIF, but rather piggy back on the
6373 * RIF of their lower device.
6375 if (netif_is_macvlan(dev
) && addr_list_empty
)
6378 if (rif
&& addr_list_empty
&&
6379 !netif_is_l3_slave(rif
->dev
))
6381 /* It is possible we already removed the RIF ourselves
6382 * if it was assigned to a netdev that is now a bridge
6391 static enum mlxsw_sp_rif_type
6392 mlxsw_sp_dev_rif_type(const struct mlxsw_sp
*mlxsw_sp
,
6393 const struct net_device
*dev
)
6395 enum mlxsw_sp_fid_type type
;
6397 if (mlxsw_sp_netdev_ipip_type(mlxsw_sp
, dev
, NULL
))
6398 return MLXSW_SP_RIF_TYPE_IPIP_LB
;
6400 /* Otherwise RIF type is derived from the type of the underlying FID. */
6401 if (is_vlan_dev(dev
) && netif_is_bridge_master(vlan_dev_real_dev(dev
)))
6402 type
= MLXSW_SP_FID_TYPE_8021Q
;
6403 else if (netif_is_bridge_master(dev
) && br_vlan_enabled(dev
))
6404 type
= MLXSW_SP_FID_TYPE_8021Q
;
6405 else if (netif_is_bridge_master(dev
))
6406 type
= MLXSW_SP_FID_TYPE_8021D
;
6408 type
= MLXSW_SP_FID_TYPE_RFID
;
6410 return mlxsw_sp_fid_type_rif_type(mlxsw_sp
, type
);
6413 static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp
*mlxsw_sp
, u16
*p_rif_index
)
6417 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
6418 if (!mlxsw_sp
->router
->rifs
[i
]) {
6427 static struct mlxsw_sp_rif
*mlxsw_sp_rif_alloc(size_t rif_size
, u16 rif_index
,
6429 struct net_device
*l3_dev
)
6431 struct mlxsw_sp_rif
*rif
;
6433 rif
= kzalloc(rif_size
, GFP_KERNEL
);
6437 INIT_LIST_HEAD(&rif
->nexthop_list
);
6438 INIT_LIST_HEAD(&rif
->neigh_list
);
6440 ether_addr_copy(rif
->addr
, l3_dev
->dev_addr
);
6441 rif
->mtu
= l3_dev
->mtu
;
6445 rif
->rif_index
= rif_index
;
6450 struct mlxsw_sp_rif
*mlxsw_sp_rif_by_index(const struct mlxsw_sp
*mlxsw_sp
,
6453 return mlxsw_sp
->router
->rifs
[rif_index
];
6456 u16
mlxsw_sp_rif_index(const struct mlxsw_sp_rif
*rif
)
6458 return rif
->rif_index
;
6461 u16
mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
6463 return lb_rif
->common
.rif_index
;
6466 u16
mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
6468 u32 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(lb_rif
->common
.dev
);
6469 struct mlxsw_sp_vr
*ul_vr
;
6471 ul_vr
= mlxsw_sp_vr_get(lb_rif
->common
.mlxsw_sp
, ul_tb_id
, NULL
);
6472 if (WARN_ON(IS_ERR(ul_vr
)))
6478 u16
mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb
*lb_rif
)
6480 return lb_rif
->ul_rif_id
;
6483 int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif
*rif
)
6485 return rif
->dev
->ifindex
;
6488 const struct net_device
*mlxsw_sp_rif_dev(const struct mlxsw_sp_rif
*rif
)
6493 struct mlxsw_sp_fid
*mlxsw_sp_rif_fid(const struct mlxsw_sp_rif
*rif
)
6498 static struct mlxsw_sp_rif
*
6499 mlxsw_sp_rif_create(struct mlxsw_sp
*mlxsw_sp
,
6500 const struct mlxsw_sp_rif_params
*params
,
6501 struct netlink_ext_ack
*extack
)
6503 u32 tb_id
= l3mdev_fib_table(params
->dev
);
6504 const struct mlxsw_sp_rif_ops
*ops
;
6505 struct mlxsw_sp_fid
*fid
= NULL
;
6506 enum mlxsw_sp_rif_type type
;
6507 struct mlxsw_sp_rif
*rif
;
6508 struct mlxsw_sp_vr
*vr
;
6512 type
= mlxsw_sp_dev_rif_type(mlxsw_sp
, params
->dev
);
6513 ops
= mlxsw_sp
->rif_ops_arr
[type
];
6515 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
? : RT_TABLE_MAIN
, extack
);
6517 return ERR_CAST(vr
);
6520 err
= mlxsw_sp_rif_index_alloc(mlxsw_sp
, &rif_index
);
6522 NL_SET_ERR_MSG_MOD(extack
, "Exceeded number of supported router interfaces");
6523 goto err_rif_index_alloc
;
6526 rif
= mlxsw_sp_rif_alloc(ops
->rif_size
, rif_index
, vr
->id
, params
->dev
);
6532 mlxsw_sp
->router
->rifs
[rif_index
] = rif
;
6533 rif
->mlxsw_sp
= mlxsw_sp
;
6537 fid
= ops
->fid_get(rif
, extack
);
6546 ops
->setup(rif
, params
);
6548 err
= ops
->configure(rif
);
6552 for (i
= 0; i
< MLXSW_SP_L3_PROTO_MAX
; i
++) {
6553 err
= mlxsw_sp_mr_rif_add(vr
->mr_table
[i
], rif
);
6555 goto err_mr_rif_add
;
6558 mlxsw_sp_rif_counters_alloc(rif
);
6563 for (i
--; i
>= 0; i
--)
6564 mlxsw_sp_mr_rif_del(vr
->mr_table
[i
], rif
);
6565 ops
->deconfigure(rif
);
6568 mlxsw_sp_fid_put(fid
);
6570 mlxsw_sp
->router
->rifs
[rif_index
] = NULL
;
6574 err_rif_index_alloc
:
6576 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
6577 return ERR_PTR(err
);
6580 static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif
*rif
)
6582 const struct mlxsw_sp_rif_ops
*ops
= rif
->ops
;
6583 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
6584 struct mlxsw_sp_fid
*fid
= rif
->fid
;
6585 struct mlxsw_sp_vr
*vr
;
6588 mlxsw_sp_router_rif_gone_sync(mlxsw_sp
, rif
);
6589 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
6591 mlxsw_sp_rif_counters_free(rif
);
6592 for (i
= 0; i
< MLXSW_SP_L3_PROTO_MAX
; i
++)
6593 mlxsw_sp_mr_rif_del(vr
->mr_table
[i
], rif
);
6594 ops
->deconfigure(rif
);
6596 /* Loopback RIFs are not associated with a FID. */
6597 mlxsw_sp_fid_put(fid
);
6598 mlxsw_sp
->router
->rifs
[rif
->rif_index
] = NULL
;
6602 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
6605 void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp
*mlxsw_sp
,
6606 struct net_device
*dev
)
6608 struct mlxsw_sp_rif
*rif
;
6610 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
6613 mlxsw_sp_rif_destroy(rif
);
6617 mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params
*params
,
6618 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6620 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6622 params
->vid
= mlxsw_sp_port_vlan
->vid
;
6623 params
->lag
= mlxsw_sp_port
->lagged
;
6625 params
->lag_id
= mlxsw_sp_port
->lag_id
;
6627 params
->system_port
= mlxsw_sp_port
->local_port
;
6630 static struct mlxsw_sp_rif_subport
*
6631 mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif
*rif
)
6633 return container_of(rif
, struct mlxsw_sp_rif_subport
, common
);
6636 static struct mlxsw_sp_rif
*
6637 mlxsw_sp_rif_subport_get(struct mlxsw_sp
*mlxsw_sp
,
6638 const struct mlxsw_sp_rif_params
*params
,
6639 struct netlink_ext_ack
*extack
)
6641 struct mlxsw_sp_rif_subport
*rif_subport
;
6642 struct mlxsw_sp_rif
*rif
;
6644 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, params
->dev
);
6646 return mlxsw_sp_rif_create(mlxsw_sp
, params
, extack
);
6648 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6649 refcount_inc(&rif_subport
->ref_count
);
6653 static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif
*rif
)
6655 struct mlxsw_sp_rif_subport
*rif_subport
;
6657 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
6658 if (!refcount_dec_and_test(&rif_subport
->ref_count
))
6661 mlxsw_sp_rif_destroy(rif
);
6665 mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
,
6666 struct net_device
*l3_dev
,
6667 struct netlink_ext_ack
*extack
)
6669 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6670 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_port
->mlxsw_sp
;
6671 struct mlxsw_sp_rif_params params
= {
6674 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6675 struct mlxsw_sp_rif
*rif
;
6676 struct mlxsw_sp_fid
*fid
;
6679 mlxsw_sp_rif_subport_params_init(¶ms
, mlxsw_sp_port_vlan
);
6680 rif
= mlxsw_sp_rif_subport_get(mlxsw_sp
, ¶ms
, extack
);
6682 return PTR_ERR(rif
);
6684 /* FID was already created, just take a reference */
6685 fid
= rif
->ops
->fid_get(rif
, extack
);
6686 err
= mlxsw_sp_fid_port_vid_map(fid
, mlxsw_sp_port
, vid
);
6688 goto err_fid_port_vid_map
;
6690 err
= mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, false);
6692 goto err_port_vid_learning_set
;
6694 err
= mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
,
6695 BR_STATE_FORWARDING
);
6697 goto err_port_vid_stp_set
;
6699 mlxsw_sp_port_vlan
->fid
= fid
;
6703 err_port_vid_stp_set
:
6704 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6705 err_port_vid_learning_set
:
6706 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6707 err_fid_port_vid_map
:
6708 mlxsw_sp_fid_put(fid
);
6709 mlxsw_sp_rif_subport_put(rif
);
6714 mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
)
6716 struct mlxsw_sp_port
*mlxsw_sp_port
= mlxsw_sp_port_vlan
->mlxsw_sp_port
;
6717 struct mlxsw_sp_fid
*fid
= mlxsw_sp_port_vlan
->fid
;
6718 struct mlxsw_sp_rif
*rif
= mlxsw_sp_fid_rif(fid
);
6719 u16 vid
= mlxsw_sp_port_vlan
->vid
;
6721 if (WARN_ON(mlxsw_sp_fid_type(fid
) != MLXSW_SP_FID_TYPE_RFID
))
6724 mlxsw_sp_port_vlan
->fid
= NULL
;
6725 mlxsw_sp_port_vid_stp_set(mlxsw_sp_port
, vid
, BR_STATE_BLOCKING
);
6726 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port
, vid
, true);
6727 mlxsw_sp_fid_port_vid_unmap(fid
, mlxsw_sp_port
, vid
);
6728 mlxsw_sp_fid_put(fid
);
6729 mlxsw_sp_rif_subport_put(rif
);
6732 static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device
*l3_dev
,
6733 struct net_device
*port_dev
,
6734 unsigned long event
, u16 vid
,
6735 struct netlink_ext_ack
*extack
)
6737 struct mlxsw_sp_port
*mlxsw_sp_port
= netdev_priv(port_dev
);
6738 struct mlxsw_sp_port_vlan
*mlxsw_sp_port_vlan
;
6740 mlxsw_sp_port_vlan
= mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port
, vid
);
6741 if (WARN_ON(!mlxsw_sp_port_vlan
))
6746 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan
,
6749 mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan
);
6756 static int mlxsw_sp_inetaddr_port_event(struct net_device
*port_dev
,
6757 unsigned long event
,
6758 struct netlink_ext_ack
*extack
)
6760 if (netif_is_bridge_port(port_dev
) ||
6761 netif_is_lag_port(port_dev
) ||
6762 netif_is_ovs_port(port_dev
))
6765 return mlxsw_sp_inetaddr_port_vlan_event(port_dev
, port_dev
, event
,
6766 MLXSW_SP_DEFAULT_VID
, extack
);
6769 static int __mlxsw_sp_inetaddr_lag_event(struct net_device
*l3_dev
,
6770 struct net_device
*lag_dev
,
6771 unsigned long event
, u16 vid
,
6772 struct netlink_ext_ack
*extack
)
6774 struct net_device
*port_dev
;
6775 struct list_head
*iter
;
6778 netdev_for_each_lower_dev(lag_dev
, port_dev
, iter
) {
6779 if (mlxsw_sp_port_dev_check(port_dev
)) {
6780 err
= mlxsw_sp_inetaddr_port_vlan_event(l3_dev
,
6792 static int mlxsw_sp_inetaddr_lag_event(struct net_device
*lag_dev
,
6793 unsigned long event
,
6794 struct netlink_ext_ack
*extack
)
6796 if (netif_is_bridge_port(lag_dev
))
6799 return __mlxsw_sp_inetaddr_lag_event(lag_dev
, lag_dev
, event
,
6800 MLXSW_SP_DEFAULT_VID
, extack
);
6803 static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp
*mlxsw_sp
,
6804 struct net_device
*l3_dev
,
6805 unsigned long event
,
6806 struct netlink_ext_ack
*extack
)
6808 struct mlxsw_sp_rif_params params
= {
6811 struct mlxsw_sp_rif
*rif
;
6815 rif
= mlxsw_sp_rif_create(mlxsw_sp
, ¶ms
, extack
);
6817 return PTR_ERR(rif
);
6820 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
6821 mlxsw_sp_rif_destroy(rif
);
6828 static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp
*mlxsw_sp
,
6829 struct net_device
*vlan_dev
,
6830 unsigned long event
,
6831 struct netlink_ext_ack
*extack
)
6833 struct net_device
*real_dev
= vlan_dev_real_dev(vlan_dev
);
6834 u16 vid
= vlan_dev_vlan_id(vlan_dev
);
6836 if (netif_is_bridge_port(vlan_dev
))
6839 if (mlxsw_sp_port_dev_check(real_dev
))
6840 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev
, real_dev
,
6841 event
, vid
, extack
);
6842 else if (netif_is_lag_master(real_dev
))
6843 return __mlxsw_sp_inetaddr_lag_event(vlan_dev
, real_dev
, event
,
6845 else if (netif_is_bridge_master(real_dev
) && br_vlan_enabled(real_dev
))
6846 return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp
, vlan_dev
, event
,
6852 static bool mlxsw_sp_rif_macvlan_is_vrrp4(const u8
*mac
)
6854 u8 vrrp4
[ETH_ALEN
] = { 0x00, 0x00, 0x5e, 0x00, 0x01, 0x00 };
6855 u8 mask
[ETH_ALEN
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
6857 return ether_addr_equal_masked(mac
, vrrp4
, mask
);
6860 static bool mlxsw_sp_rif_macvlan_is_vrrp6(const u8
*mac
)
6862 u8 vrrp6
[ETH_ALEN
] = { 0x00, 0x00, 0x5e, 0x00, 0x02, 0x00 };
6863 u8 mask
[ETH_ALEN
] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
6865 return ether_addr_equal_masked(mac
, vrrp6
, mask
);
6868 static int mlxsw_sp_rif_vrrp_op(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
6869 const u8
*mac
, bool adding
)
6871 char ritr_pl
[MLXSW_REG_RITR_LEN
];
6872 u8 vrrp_id
= adding
? mac
[5] : 0;
6875 if (!mlxsw_sp_rif_macvlan_is_vrrp4(mac
) &&
6876 !mlxsw_sp_rif_macvlan_is_vrrp6(mac
))
6879 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
6880 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6884 if (mlxsw_sp_rif_macvlan_is_vrrp4(mac
))
6885 mlxsw_reg_ritr_if_vrrp_id_ipv4_set(ritr_pl
, vrrp_id
);
6887 mlxsw_reg_ritr_if_vrrp_id_ipv6_set(ritr_pl
, vrrp_id
);
6889 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
6892 static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp
*mlxsw_sp
,
6893 const struct net_device
*macvlan_dev
,
6894 struct netlink_ext_ack
*extack
)
6896 struct macvlan_dev
*vlan
= netdev_priv(macvlan_dev
);
6897 struct mlxsw_sp_rif
*rif
;
6900 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, vlan
->lowerdev
);
6902 NL_SET_ERR_MSG_MOD(extack
, "macvlan is only supported on top of router interfaces");
6906 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, macvlan_dev
->dev_addr
,
6907 mlxsw_sp_fid_index(rif
->fid
), true);
6911 err
= mlxsw_sp_rif_vrrp_op(mlxsw_sp
, rif
->rif_index
,
6912 macvlan_dev
->dev_addr
, true);
6914 goto err_rif_vrrp_add
;
6916 /* Make sure the bridge driver does not have this MAC pointing at
6919 if (rif
->ops
->fdb_del
)
6920 rif
->ops
->fdb_del(rif
, macvlan_dev
->dev_addr
);
6925 mlxsw_sp_rif_fdb_op(mlxsw_sp
, macvlan_dev
->dev_addr
,
6926 mlxsw_sp_fid_index(rif
->fid
), false);
6930 void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp
*mlxsw_sp
,
6931 const struct net_device
*macvlan_dev
)
6933 struct macvlan_dev
*vlan
= netdev_priv(macvlan_dev
);
6934 struct mlxsw_sp_rif
*rif
;
6936 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, vlan
->lowerdev
);
6937 /* If we do not have a RIF, then we already took care of
6938 * removing the macvlan's MAC during RIF deletion.
6942 mlxsw_sp_rif_vrrp_op(mlxsw_sp
, rif
->rif_index
, macvlan_dev
->dev_addr
,
6944 mlxsw_sp_rif_fdb_op(mlxsw_sp
, macvlan_dev
->dev_addr
,
6945 mlxsw_sp_fid_index(rif
->fid
), false);
6948 static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp
*mlxsw_sp
,
6949 struct net_device
*macvlan_dev
,
6950 unsigned long event
,
6951 struct netlink_ext_ack
*extack
)
6955 return mlxsw_sp_rif_macvlan_add(mlxsw_sp
, macvlan_dev
, extack
);
6957 mlxsw_sp_rif_macvlan_del(mlxsw_sp
, macvlan_dev
);
6964 static int mlxsw_sp_router_port_check_rif_addr(struct mlxsw_sp
*mlxsw_sp
,
6965 struct net_device
*dev
,
6966 const unsigned char *dev_addr
,
6967 struct netlink_ext_ack
*extack
)
6969 struct mlxsw_sp_rif
*rif
;
6972 /* A RIF is not created for macvlan netdevs. Their MAC is used to
6975 if (netif_is_macvlan(dev
) || netif_is_l3_master(dev
))
6978 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++) {
6979 rif
= mlxsw_sp
->router
->rifs
[i
];
6980 if (rif
&& rif
->dev
&& rif
->dev
!= dev
&&
6981 !ether_addr_equal_masked(rif
->dev
->dev_addr
, dev_addr
,
6982 mlxsw_sp
->mac_mask
)) {
6983 NL_SET_ERR_MSG_MOD(extack
, "All router interface MAC addresses must have the same prefix");
6991 static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp
*mlxsw_sp
,
6992 struct net_device
*dev
,
6993 unsigned long event
,
6994 struct netlink_ext_ack
*extack
)
6996 if (mlxsw_sp_port_dev_check(dev
))
6997 return mlxsw_sp_inetaddr_port_event(dev
, event
, extack
);
6998 else if (netif_is_lag_master(dev
))
6999 return mlxsw_sp_inetaddr_lag_event(dev
, event
, extack
);
7000 else if (netif_is_bridge_master(dev
))
7001 return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp
, dev
, event
,
7003 else if (is_vlan_dev(dev
))
7004 return mlxsw_sp_inetaddr_vlan_event(mlxsw_sp
, dev
, event
,
7006 else if (netif_is_macvlan(dev
))
7007 return mlxsw_sp_inetaddr_macvlan_event(mlxsw_sp
, dev
, event
,
7013 static int mlxsw_sp_inetaddr_event(struct notifier_block
*nb
,
7014 unsigned long event
, void *ptr
)
7016 struct in_ifaddr
*ifa
= (struct in_ifaddr
*) ptr
;
7017 struct net_device
*dev
= ifa
->ifa_dev
->dev
;
7018 struct mlxsw_sp_router
*router
;
7019 struct mlxsw_sp_rif
*rif
;
7022 /* NETDEV_UP event is handled by mlxsw_sp_inetaddr_valid_event */
7023 if (event
== NETDEV_UP
)
7026 router
= container_of(nb
, struct mlxsw_sp_router
, inetaddr_nb
);
7027 rif
= mlxsw_sp_rif_find_by_dev(router
->mlxsw_sp
, dev
);
7028 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
7031 err
= __mlxsw_sp_inetaddr_event(router
->mlxsw_sp
, dev
, event
, NULL
);
7033 return notifier_from_errno(err
);
7036 int mlxsw_sp_inetaddr_valid_event(struct notifier_block
*unused
,
7037 unsigned long event
, void *ptr
)
7039 struct in_validator_info
*ivi
= (struct in_validator_info
*) ptr
;
7040 struct net_device
*dev
= ivi
->ivi_dev
->dev
;
7041 struct mlxsw_sp
*mlxsw_sp
;
7042 struct mlxsw_sp_rif
*rif
;
7045 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
7049 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
7050 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
7053 err
= mlxsw_sp_router_port_check_rif_addr(mlxsw_sp
, dev
, dev
->dev_addr
,
7058 err
= __mlxsw_sp_inetaddr_event(mlxsw_sp
, dev
, event
, ivi
->extack
);
7060 return notifier_from_errno(err
);
7063 struct mlxsw_sp_inet6addr_event_work
{
7064 struct work_struct work
;
7065 struct mlxsw_sp
*mlxsw_sp
;
7066 struct net_device
*dev
;
7067 unsigned long event
;
7070 static void mlxsw_sp_inet6addr_event_work(struct work_struct
*work
)
7072 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
=
7073 container_of(work
, struct mlxsw_sp_inet6addr_event_work
, work
);
7074 struct mlxsw_sp
*mlxsw_sp
= inet6addr_work
->mlxsw_sp
;
7075 struct net_device
*dev
= inet6addr_work
->dev
;
7076 unsigned long event
= inet6addr_work
->event
;
7077 struct mlxsw_sp_rif
*rif
;
7081 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
7082 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
7085 __mlxsw_sp_inetaddr_event(mlxsw_sp
, dev
, event
, NULL
);
7089 kfree(inet6addr_work
);
7092 /* Called with rcu_read_lock() */
7093 static int mlxsw_sp_inet6addr_event(struct notifier_block
*nb
,
7094 unsigned long event
, void *ptr
)
7096 struct inet6_ifaddr
*if6
= (struct inet6_ifaddr
*) ptr
;
7097 struct mlxsw_sp_inet6addr_event_work
*inet6addr_work
;
7098 struct net_device
*dev
= if6
->idev
->dev
;
7099 struct mlxsw_sp_router
*router
;
7101 /* NETDEV_UP event is handled by mlxsw_sp_inet6addr_valid_event */
7102 if (event
== NETDEV_UP
)
7105 inet6addr_work
= kzalloc(sizeof(*inet6addr_work
), GFP_ATOMIC
);
7106 if (!inet6addr_work
)
7109 router
= container_of(nb
, struct mlxsw_sp_router
, inet6addr_nb
);
7110 INIT_WORK(&inet6addr_work
->work
, mlxsw_sp_inet6addr_event_work
);
7111 inet6addr_work
->mlxsw_sp
= router
->mlxsw_sp
;
7112 inet6addr_work
->dev
= dev
;
7113 inet6addr_work
->event
= event
;
7115 mlxsw_core_schedule_work(&inet6addr_work
->work
);
7120 int mlxsw_sp_inet6addr_valid_event(struct notifier_block
*unused
,
7121 unsigned long event
, void *ptr
)
7123 struct in6_validator_info
*i6vi
= (struct in6_validator_info
*) ptr
;
7124 struct net_device
*dev
= i6vi
->i6vi_dev
->dev
;
7125 struct mlxsw_sp
*mlxsw_sp
;
7126 struct mlxsw_sp_rif
*rif
;
7129 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
7133 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
7134 if (!mlxsw_sp_rif_should_config(rif
, dev
, event
))
7137 err
= mlxsw_sp_router_port_check_rif_addr(mlxsw_sp
, dev
, dev
->dev_addr
,
7142 err
= __mlxsw_sp_inetaddr_event(mlxsw_sp
, dev
, event
, i6vi
->extack
);
7144 return notifier_from_errno(err
);
7147 static int mlxsw_sp_rif_edit(struct mlxsw_sp
*mlxsw_sp
, u16 rif_index
,
7148 const char *mac
, int mtu
)
7150 char ritr_pl
[MLXSW_REG_RITR_LEN
];
7153 mlxsw_reg_ritr_rif_pack(ritr_pl
, rif_index
);
7154 err
= mlxsw_reg_query(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
7158 mlxsw_reg_ritr_mtu_set(ritr_pl
, mtu
);
7159 mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl
, mac
);
7160 mlxsw_reg_ritr_op_set(ritr_pl
, MLXSW_REG_RITR_RIF_CREATE
);
7161 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
7165 mlxsw_sp_router_port_change_event(struct mlxsw_sp
*mlxsw_sp
,
7166 struct mlxsw_sp_rif
*rif
)
7168 struct net_device
*dev
= rif
->dev
;
7172 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
7174 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, false);
7178 err
= mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, dev
->dev_addr
,
7183 err
= mlxsw_sp_rif_fdb_op(mlxsw_sp
, dev
->dev_addr
, fid_index
, true);
7185 goto err_rif_fdb_op
;
7187 if (rif
->mtu
!= dev
->mtu
) {
7188 struct mlxsw_sp_vr
*vr
;
7191 /* The RIF is relevant only to its mr_table instance, as unlike
7192 * unicast routing, in multicast routing a RIF cannot be shared
7193 * between several multicast routing tables.
7195 vr
= &mlxsw_sp
->router
->vrs
[rif
->vr_id
];
7196 for (i
= 0; i
< MLXSW_SP_L3_PROTO_MAX
; i
++)
7197 mlxsw_sp_mr_rif_mtu_update(vr
->mr_table
[i
],
7201 ether_addr_copy(rif
->addr
, dev
->dev_addr
);
7202 rif
->mtu
= dev
->mtu
;
7204 netdev_dbg(dev
, "Updated RIF=%d\n", rif
->rif_index
);
7209 mlxsw_sp_rif_edit(mlxsw_sp
, rif
->rif_index
, rif
->addr
, rif
->mtu
);
7211 mlxsw_sp_rif_fdb_op(mlxsw_sp
, rif
->addr
, fid_index
, true);
7215 static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif
*rif
,
7216 struct netdev_notifier_pre_changeaddr_info
*info
)
7218 struct netlink_ext_ack
*extack
;
7220 extack
= netdev_notifier_info_to_extack(&info
->info
);
7221 return mlxsw_sp_router_port_check_rif_addr(rif
->mlxsw_sp
, rif
->dev
,
7222 info
->dev_addr
, extack
);
7225 int mlxsw_sp_netdevice_router_port_event(struct net_device
*dev
,
7226 unsigned long event
, void *ptr
)
7228 struct mlxsw_sp
*mlxsw_sp
;
7229 struct mlxsw_sp_rif
*rif
;
7231 mlxsw_sp
= mlxsw_sp_lower_get(dev
);
7235 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, dev
);
7240 case NETDEV_CHANGEMTU
: /* fall through */
7241 case NETDEV_CHANGEADDR
:
7242 return mlxsw_sp_router_port_change_event(mlxsw_sp
, rif
);
7243 case NETDEV_PRE_CHANGEADDR
:
7244 return mlxsw_sp_router_port_pre_changeaddr_event(rif
, ptr
);
7250 static int mlxsw_sp_port_vrf_join(struct mlxsw_sp
*mlxsw_sp
,
7251 struct net_device
*l3_dev
,
7252 struct netlink_ext_ack
*extack
)
7254 struct mlxsw_sp_rif
*rif
;
7256 /* If netdev is already associated with a RIF, then we need to
7257 * destroy it and create a new one with the new virtual router ID.
7259 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
7261 __mlxsw_sp_inetaddr_event(mlxsw_sp
, l3_dev
, NETDEV_DOWN
,
7264 return __mlxsw_sp_inetaddr_event(mlxsw_sp
, l3_dev
, NETDEV_UP
, extack
);
7267 static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp
*mlxsw_sp
,
7268 struct net_device
*l3_dev
)
7270 struct mlxsw_sp_rif
*rif
;
7272 rif
= mlxsw_sp_rif_find_by_dev(mlxsw_sp
, l3_dev
);
7275 __mlxsw_sp_inetaddr_event(mlxsw_sp
, l3_dev
, NETDEV_DOWN
, NULL
);
7278 int mlxsw_sp_netdevice_vrf_event(struct net_device
*l3_dev
, unsigned long event
,
7279 struct netdev_notifier_changeupper_info
*info
)
7281 struct mlxsw_sp
*mlxsw_sp
= mlxsw_sp_lower_get(l3_dev
);
7284 /* We do not create a RIF for a macvlan, but only use it to
7285 * direct more MAC addresses to the router.
7287 if (!mlxsw_sp
|| netif_is_macvlan(l3_dev
))
7291 case NETDEV_PRECHANGEUPPER
:
7293 case NETDEV_CHANGEUPPER
:
7294 if (info
->linking
) {
7295 struct netlink_ext_ack
*extack
;
7297 extack
= netdev_notifier_info_to_extack(&info
->info
);
7298 err
= mlxsw_sp_port_vrf_join(mlxsw_sp
, l3_dev
, extack
);
7300 mlxsw_sp_port_vrf_leave(mlxsw_sp
, l3_dev
);
7308 static int __mlxsw_sp_rif_macvlan_flush(struct net_device
*dev
, void *data
)
7310 struct mlxsw_sp_rif
*rif
= data
;
7312 if (!netif_is_macvlan(dev
))
7315 return mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, dev
->dev_addr
,
7316 mlxsw_sp_fid_index(rif
->fid
), false);
7319 static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif
*rif
)
7321 if (!netif_is_macvlan_port(rif
->dev
))
7324 netdev_warn(rif
->dev
, "Router interface is deleted. Upper macvlans will not work\n");
7325 return netdev_walk_all_upper_dev_rcu(rif
->dev
,
7326 __mlxsw_sp_rif_macvlan_flush
, rif
);
7329 static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif
*rif
,
7330 const struct mlxsw_sp_rif_params
*params
)
7332 struct mlxsw_sp_rif_subport
*rif_subport
;
7334 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
7335 refcount_set(&rif_subport
->ref_count
, 1);
7336 rif_subport
->vid
= params
->vid
;
7337 rif_subport
->lag
= params
->lag
;
7339 rif_subport
->lag_id
= params
->lag_id
;
7341 rif_subport
->system_port
= params
->system_port
;
7344 static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif
*rif
, bool enable
)
7346 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7347 struct mlxsw_sp_rif_subport
*rif_subport
;
7348 char ritr_pl
[MLXSW_REG_RITR_LEN
];
7350 rif_subport
= mlxsw_sp_rif_subport_rif(rif
);
7351 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_SP_IF
,
7352 rif
->rif_index
, rif
->vr_id
, rif
->dev
->mtu
);
7353 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
7354 mlxsw_reg_ritr_sp_if_pack(ritr_pl
, rif_subport
->lag
,
7355 rif_subport
->lag
? rif_subport
->lag_id
:
7356 rif_subport
->system_port
,
7359 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
7362 static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif
*rif
)
7366 err
= mlxsw_sp_rif_subport_op(rif
, true);
7370 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
7371 mlxsw_sp_fid_index(rif
->fid
), true);
7373 goto err_rif_fdb_op
;
7375 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
7379 mlxsw_sp_rif_subport_op(rif
, false);
7383 static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif
*rif
)
7385 struct mlxsw_sp_fid
*fid
= rif
->fid
;
7387 mlxsw_sp_fid_rif_set(fid
, NULL
);
7388 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
7389 mlxsw_sp_fid_index(fid
), false);
7390 mlxsw_sp_rif_macvlan_flush(rif
);
7391 mlxsw_sp_rif_subport_op(rif
, false);
7394 static struct mlxsw_sp_fid
*
7395 mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif
*rif
,
7396 struct netlink_ext_ack
*extack
)
7398 return mlxsw_sp_fid_rfid_get(rif
->mlxsw_sp
, rif
->rif_index
);
7401 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops
= {
7402 .type
= MLXSW_SP_RIF_TYPE_SUBPORT
,
7403 .rif_size
= sizeof(struct mlxsw_sp_rif_subport
),
7404 .setup
= mlxsw_sp_rif_subport_setup
,
7405 .configure
= mlxsw_sp_rif_subport_configure
,
7406 .deconfigure
= mlxsw_sp_rif_subport_deconfigure
,
7407 .fid_get
= mlxsw_sp_rif_subport_fid_get
,
7410 static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif
*rif
,
7411 enum mlxsw_reg_ritr_if_type type
,
7412 u16 vid_fid
, bool enable
)
7414 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7415 char ritr_pl
[MLXSW_REG_RITR_LEN
];
7417 mlxsw_reg_ritr_pack(ritr_pl
, enable
, type
, rif
->rif_index
, rif
->vr_id
,
7419 mlxsw_reg_ritr_mac_pack(ritr_pl
, rif
->dev
->dev_addr
);
7420 mlxsw_reg_ritr_fid_set(ritr_pl
, type
, vid_fid
);
7422 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
7425 u8
mlxsw_sp_router_port(const struct mlxsw_sp
*mlxsw_sp
)
7427 return mlxsw_core_max_ports(mlxsw_sp
->core
) + 1;
7430 static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif
*rif
)
7432 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7433 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
7436 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, true);
7440 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
7441 mlxsw_sp_router_port(mlxsw_sp
), true);
7443 goto err_fid_mc_flood_set
;
7445 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
7446 mlxsw_sp_router_port(mlxsw_sp
), true);
7448 goto err_fid_bc_flood_set
;
7450 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
7451 mlxsw_sp_fid_index(rif
->fid
), true);
7453 goto err_rif_fdb_op
;
7455 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
7459 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
7460 mlxsw_sp_router_port(mlxsw_sp
), false);
7461 err_fid_bc_flood_set
:
7462 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
7463 mlxsw_sp_router_port(mlxsw_sp
), false);
7464 err_fid_mc_flood_set
:
7465 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
7469 static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif
*rif
)
7471 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
7472 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7473 struct mlxsw_sp_fid
*fid
= rif
->fid
;
7475 mlxsw_sp_fid_rif_set(fid
, NULL
);
7476 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
7477 mlxsw_sp_fid_index(fid
), false);
7478 mlxsw_sp_rif_macvlan_flush(rif
);
7479 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
7480 mlxsw_sp_router_port(mlxsw_sp
), false);
7481 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
7482 mlxsw_sp_router_port(mlxsw_sp
), false);
7483 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_VLAN_IF
, vid
, false);
7486 static struct mlxsw_sp_fid
*
7487 mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif
*rif
,
7488 struct netlink_ext_ack
*extack
)
7490 struct net_device
*br_dev
= rif
->dev
;
7494 if (is_vlan_dev(rif
->dev
)) {
7495 vid
= vlan_dev_vlan_id(rif
->dev
);
7496 br_dev
= vlan_dev_real_dev(rif
->dev
);
7497 if (WARN_ON(!netif_is_bridge_master(br_dev
)))
7498 return ERR_PTR(-EINVAL
);
7500 err
= br_vlan_get_pvid(rif
->dev
, &vid
);
7501 if (err
< 0 || !vid
) {
7502 NL_SET_ERR_MSG_MOD(extack
, "Couldn't determine bridge PVID");
7503 return ERR_PTR(-EINVAL
);
7507 return mlxsw_sp_bridge_fid_get(rif
->mlxsw_sp
, br_dev
, vid
, extack
);
7510 static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif
*rif
, const char *mac
)
7512 u16 vid
= mlxsw_sp_fid_8021q_vid(rif
->fid
);
7513 struct switchdev_notifier_fdb_info info
;
7514 struct net_device
*br_dev
;
7515 struct net_device
*dev
;
7517 br_dev
= is_vlan_dev(rif
->dev
) ? vlan_dev_real_dev(rif
->dev
) : rif
->dev
;
7518 dev
= br_fdb_find_port(br_dev
, mac
, vid
);
7524 call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE
, dev
, &info
.info
,
7528 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops
= {
7529 .type
= MLXSW_SP_RIF_TYPE_VLAN
,
7530 .rif_size
= sizeof(struct mlxsw_sp_rif
),
7531 .configure
= mlxsw_sp_rif_vlan_configure
,
7532 .deconfigure
= mlxsw_sp_rif_vlan_deconfigure
,
7533 .fid_get
= mlxsw_sp_rif_vlan_fid_get
,
7534 .fdb_del
= mlxsw_sp_rif_vlan_fdb_del
,
7537 static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif
*rif
)
7539 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7540 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
7543 err
= mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
,
7548 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
7549 mlxsw_sp_router_port(mlxsw_sp
), true);
7551 goto err_fid_mc_flood_set
;
7553 err
= mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
7554 mlxsw_sp_router_port(mlxsw_sp
), true);
7556 goto err_fid_bc_flood_set
;
7558 err
= mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
7559 mlxsw_sp_fid_index(rif
->fid
), true);
7561 goto err_rif_fdb_op
;
7563 mlxsw_sp_fid_rif_set(rif
->fid
, rif
);
7567 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
7568 mlxsw_sp_router_port(mlxsw_sp
), false);
7569 err_fid_bc_flood_set
:
7570 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
7571 mlxsw_sp_router_port(mlxsw_sp
), false);
7572 err_fid_mc_flood_set
:
7573 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
7577 static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif
*rif
)
7579 u16 fid_index
= mlxsw_sp_fid_index(rif
->fid
);
7580 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7581 struct mlxsw_sp_fid
*fid
= rif
->fid
;
7583 mlxsw_sp_fid_rif_set(fid
, NULL
);
7584 mlxsw_sp_rif_fdb_op(rif
->mlxsw_sp
, rif
->dev
->dev_addr
,
7585 mlxsw_sp_fid_index(fid
), false);
7586 mlxsw_sp_rif_macvlan_flush(rif
);
7587 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_BC
,
7588 mlxsw_sp_router_port(mlxsw_sp
), false);
7589 mlxsw_sp_fid_flood_set(rif
->fid
, MLXSW_SP_FLOOD_TYPE_MC
,
7590 mlxsw_sp_router_port(mlxsw_sp
), false);
7591 mlxsw_sp_rif_vlan_fid_op(rif
, MLXSW_REG_RITR_FID_IF
, fid_index
, false);
7594 static struct mlxsw_sp_fid
*
7595 mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif
*rif
,
7596 struct netlink_ext_ack
*extack
)
7598 return mlxsw_sp_bridge_fid_get(rif
->mlxsw_sp
, rif
->dev
, 0, extack
);
7601 static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif
*rif
, const char *mac
)
7603 struct switchdev_notifier_fdb_info info
;
7604 struct net_device
*dev
;
7606 dev
= br_fdb_find_port(rif
->dev
, mac
, 0);
7612 call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE
, dev
, &info
.info
,
7616 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops
= {
7617 .type
= MLXSW_SP_RIF_TYPE_FID
,
7618 .rif_size
= sizeof(struct mlxsw_sp_rif
),
7619 .configure
= mlxsw_sp_rif_fid_configure
,
7620 .deconfigure
= mlxsw_sp_rif_fid_deconfigure
,
7621 .fid_get
= mlxsw_sp_rif_fid_fid_get
,
7622 .fdb_del
= mlxsw_sp_rif_fid_fdb_del
,
7625 static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_emu_ops
= {
7626 .type
= MLXSW_SP_RIF_TYPE_VLAN
,
7627 .rif_size
= sizeof(struct mlxsw_sp_rif
),
7628 .configure
= mlxsw_sp_rif_fid_configure
,
7629 .deconfigure
= mlxsw_sp_rif_fid_deconfigure
,
7630 .fid_get
= mlxsw_sp_rif_vlan_fid_get
,
7631 .fdb_del
= mlxsw_sp_rif_vlan_fdb_del
,
7634 static struct mlxsw_sp_rif_ipip_lb
*
7635 mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif
*rif
)
7637 return container_of(rif
, struct mlxsw_sp_rif_ipip_lb
, common
);
7641 mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif
*rif
,
7642 const struct mlxsw_sp_rif_params
*params
)
7644 struct mlxsw_sp_rif_params_ipip_lb
*params_lb
;
7645 struct mlxsw_sp_rif_ipip_lb
*rif_lb
;
7647 params_lb
= container_of(params
, struct mlxsw_sp_rif_params_ipip_lb
,
7649 rif_lb
= mlxsw_sp_rif_ipip_lb_rif(rif
);
7650 rif_lb
->lb_config
= params_lb
->lb_config
;
7654 mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif
*rif
)
7656 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
7657 u32 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(rif
->dev
);
7658 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7659 struct mlxsw_sp_vr
*ul_vr
;
7662 ul_vr
= mlxsw_sp_vr_get(mlxsw_sp
, ul_tb_id
, NULL
);
7664 return PTR_ERR(ul_vr
);
7666 err
= mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
->id
, 0, true);
7668 goto err_loopback_op
;
7670 lb_rif
->ul_vr_id
= ul_vr
->id
;
7671 lb_rif
->ul_rif_id
= 0;
7676 mlxsw_sp_vr_put(mlxsw_sp
, ul_vr
);
7680 static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif
*rif
)
7682 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
7683 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7684 struct mlxsw_sp_vr
*ul_vr
;
7686 ul_vr
= &mlxsw_sp
->router
->vrs
[lb_rif
->ul_vr_id
];
7687 mlxsw_sp_rif_ipip_lb_op(lb_rif
, ul_vr
->id
, 0, false);
7690 mlxsw_sp_vr_put(mlxsw_sp
, ul_vr
);
7693 static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_ipip_lb_ops
= {
7694 .type
= MLXSW_SP_RIF_TYPE_IPIP_LB
,
7695 .rif_size
= sizeof(struct mlxsw_sp_rif_ipip_lb
),
7696 .setup
= mlxsw_sp_rif_ipip_lb_setup
,
7697 .configure
= mlxsw_sp1_rif_ipip_lb_configure
,
7698 .deconfigure
= mlxsw_sp1_rif_ipip_lb_deconfigure
,
7701 const struct mlxsw_sp_rif_ops
*mlxsw_sp1_rif_ops_arr
[] = {
7702 [MLXSW_SP_RIF_TYPE_SUBPORT
] = &mlxsw_sp_rif_subport_ops
,
7703 [MLXSW_SP_RIF_TYPE_VLAN
] = &mlxsw_sp_rif_vlan_emu_ops
,
7704 [MLXSW_SP_RIF_TYPE_FID
] = &mlxsw_sp_rif_fid_ops
,
7705 [MLXSW_SP_RIF_TYPE_IPIP_LB
] = &mlxsw_sp1_rif_ipip_lb_ops
,
7709 mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif
*ul_rif
, bool enable
)
7711 struct mlxsw_sp
*mlxsw_sp
= ul_rif
->mlxsw_sp
;
7712 char ritr_pl
[MLXSW_REG_RITR_LEN
];
7714 mlxsw_reg_ritr_pack(ritr_pl
, enable
, MLXSW_REG_RITR_LOOPBACK_IF
,
7715 ul_rif
->rif_index
, ul_rif
->vr_id
, IP_MAX_MTU
);
7716 mlxsw_reg_ritr_loopback_protocol_set(ritr_pl
,
7717 MLXSW_REG_RITR_LOOPBACK_GENERIC
);
7719 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(ritr
), ritr_pl
);
7722 static struct mlxsw_sp_rif
*
7723 mlxsw_sp_ul_rif_create(struct mlxsw_sp
*mlxsw_sp
, struct mlxsw_sp_vr
*vr
,
7724 struct netlink_ext_ack
*extack
)
7726 struct mlxsw_sp_rif
*ul_rif
;
7730 err
= mlxsw_sp_rif_index_alloc(mlxsw_sp
, &rif_index
);
7732 NL_SET_ERR_MSG_MOD(extack
, "Exceeded number of supported router interfaces");
7733 return ERR_PTR(err
);
7736 ul_rif
= mlxsw_sp_rif_alloc(sizeof(*ul_rif
), rif_index
, vr
->id
, NULL
);
7738 return ERR_PTR(-ENOMEM
);
7740 mlxsw_sp
->router
->rifs
[rif_index
] = ul_rif
;
7741 ul_rif
->mlxsw_sp
= mlxsw_sp
;
7742 err
= mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif
, true);
7749 mlxsw_sp
->router
->rifs
[rif_index
] = NULL
;
7751 return ERR_PTR(err
);
7754 static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif
*ul_rif
)
7756 struct mlxsw_sp
*mlxsw_sp
= ul_rif
->mlxsw_sp
;
7758 mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif
, false);
7759 mlxsw_sp
->router
->rifs
[ul_rif
->rif_index
] = NULL
;
7763 static struct mlxsw_sp_rif
*
7764 mlxsw_sp_ul_rif_get(struct mlxsw_sp
*mlxsw_sp
, u32 tb_id
,
7765 struct netlink_ext_ack
*extack
)
7767 struct mlxsw_sp_vr
*vr
;
7770 vr
= mlxsw_sp_vr_get(mlxsw_sp
, tb_id
, extack
);
7772 return ERR_CAST(vr
);
7774 if (refcount_inc_not_zero(&vr
->ul_rif_refcnt
))
7777 vr
->ul_rif
= mlxsw_sp_ul_rif_create(mlxsw_sp
, vr
, extack
);
7778 if (IS_ERR(vr
->ul_rif
)) {
7779 err
= PTR_ERR(vr
->ul_rif
);
7780 goto err_ul_rif_create
;
7784 refcount_set(&vr
->ul_rif_refcnt
, 1);
7789 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
7790 return ERR_PTR(err
);
7793 static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif
*ul_rif
)
7795 struct mlxsw_sp
*mlxsw_sp
= ul_rif
->mlxsw_sp
;
7796 struct mlxsw_sp_vr
*vr
;
7798 vr
= &mlxsw_sp
->router
->vrs
[ul_rif
->vr_id
];
7800 if (!refcount_dec_and_test(&vr
->ul_rif_refcnt
))
7804 mlxsw_sp_ul_rif_destroy(ul_rif
);
7805 mlxsw_sp_vr_put(mlxsw_sp
, vr
);
7808 int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp
*mlxsw_sp
, u32 ul_tb_id
,
7811 struct mlxsw_sp_rif
*ul_rif
;
7815 ul_rif
= mlxsw_sp_ul_rif_get(mlxsw_sp
, ul_tb_id
, NULL
);
7817 return PTR_ERR(ul_rif
);
7818 *ul_rif_index
= ul_rif
->rif_index
;
7823 void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp
*mlxsw_sp
, u16 ul_rif_index
)
7825 struct mlxsw_sp_rif
*ul_rif
;
7829 ul_rif
= mlxsw_sp
->router
->rifs
[ul_rif_index
];
7830 if (WARN_ON(!ul_rif
))
7833 mlxsw_sp_ul_rif_put(ul_rif
);
7837 mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif
*rif
)
7839 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
7840 u32 ul_tb_id
= mlxsw_sp_ipip_dev_ul_tb_id(rif
->dev
);
7841 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7842 struct mlxsw_sp_rif
*ul_rif
;
7845 ul_rif
= mlxsw_sp_ul_rif_get(mlxsw_sp
, ul_tb_id
, NULL
);
7847 return PTR_ERR(ul_rif
);
7849 err
= mlxsw_sp_rif_ipip_lb_op(lb_rif
, 0, ul_rif
->rif_index
, true);
7851 goto err_loopback_op
;
7853 lb_rif
->ul_vr_id
= 0;
7854 lb_rif
->ul_rif_id
= ul_rif
->rif_index
;
7859 mlxsw_sp_ul_rif_put(ul_rif
);
7863 static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif
*rif
)
7865 struct mlxsw_sp_rif_ipip_lb
*lb_rif
= mlxsw_sp_rif_ipip_lb_rif(rif
);
7866 struct mlxsw_sp
*mlxsw_sp
= rif
->mlxsw_sp
;
7867 struct mlxsw_sp_rif
*ul_rif
;
7869 ul_rif
= mlxsw_sp_rif_by_index(mlxsw_sp
, lb_rif
->ul_rif_id
);
7870 mlxsw_sp_rif_ipip_lb_op(lb_rif
, 0, lb_rif
->ul_rif_id
, false);
7871 mlxsw_sp_ul_rif_put(ul_rif
);
7874 static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops
= {
7875 .type
= MLXSW_SP_RIF_TYPE_IPIP_LB
,
7876 .rif_size
= sizeof(struct mlxsw_sp_rif_ipip_lb
),
7877 .setup
= mlxsw_sp_rif_ipip_lb_setup
,
7878 .configure
= mlxsw_sp2_rif_ipip_lb_configure
,
7879 .deconfigure
= mlxsw_sp2_rif_ipip_lb_deconfigure
,
7882 const struct mlxsw_sp_rif_ops
*mlxsw_sp2_rif_ops_arr
[] = {
7883 [MLXSW_SP_RIF_TYPE_SUBPORT
] = &mlxsw_sp_rif_subport_ops
,
7884 [MLXSW_SP_RIF_TYPE_VLAN
] = &mlxsw_sp_rif_vlan_emu_ops
,
7885 [MLXSW_SP_RIF_TYPE_FID
] = &mlxsw_sp_rif_fid_ops
,
7886 [MLXSW_SP_RIF_TYPE_IPIP_LB
] = &mlxsw_sp2_rif_ipip_lb_ops
,
7889 static int mlxsw_sp_rifs_init(struct mlxsw_sp
*mlxsw_sp
)
7891 u64 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
7893 mlxsw_sp
->router
->rifs
= kcalloc(max_rifs
,
7894 sizeof(struct mlxsw_sp_rif
*),
7896 if (!mlxsw_sp
->router
->rifs
)
7902 static void mlxsw_sp_rifs_fini(struct mlxsw_sp
*mlxsw_sp
)
7906 for (i
= 0; i
< MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
); i
++)
7907 WARN_ON_ONCE(mlxsw_sp
->router
->rifs
[i
]);
7909 kfree(mlxsw_sp
->router
->rifs
);
7913 mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp
*mlxsw_sp
)
7915 char tigcr_pl
[MLXSW_REG_TIGCR_LEN
];
7917 mlxsw_reg_tigcr_pack(tigcr_pl
, true, 0);
7918 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(tigcr
), tigcr_pl
);
7921 static int mlxsw_sp_ipips_init(struct mlxsw_sp
*mlxsw_sp
)
7923 mlxsw_sp
->router
->ipip_ops_arr
= mlxsw_sp_ipip_ops_arr
;
7924 INIT_LIST_HEAD(&mlxsw_sp
->router
->ipip_list
);
7925 return mlxsw_sp_ipip_config_tigcr(mlxsw_sp
);
7928 static void mlxsw_sp_ipips_fini(struct mlxsw_sp
*mlxsw_sp
)
7930 WARN_ON(!list_empty(&mlxsw_sp
->router
->ipip_list
));
7933 static void mlxsw_sp_router_fib_dump_flush(struct notifier_block
*nb
)
7935 struct mlxsw_sp_router
*router
;
7937 /* Flush pending FIB notifications and then flush the device's
7938 * table before requesting another dump. The FIB notification
7939 * block is unregistered, so no need to take RTNL.
7941 mlxsw_core_flush_owq();
7942 router
= container_of(nb
, struct mlxsw_sp_router
, fib_nb
);
7943 mlxsw_sp_router_fib_flush(router
->mlxsw_sp
);
7946 #ifdef CONFIG_IP_ROUTE_MULTIPATH
7947 static void mlxsw_sp_mp_hash_header_set(char *recr2_pl
, int header
)
7949 mlxsw_reg_recr2_outer_header_enables_set(recr2_pl
, header
, true);
7952 static void mlxsw_sp_mp_hash_field_set(char *recr2_pl
, int field
)
7954 mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl
, field
, true);
7957 static void mlxsw_sp_mp4_hash_init(struct mlxsw_sp
*mlxsw_sp
, char *recr2_pl
)
7959 struct net
*net
= mlxsw_sp_net(mlxsw_sp
);
7960 bool only_l3
= !net
->ipv4
.sysctl_fib_multipath_hash_policy
;
7962 mlxsw_sp_mp_hash_header_set(recr2_pl
,
7963 MLXSW_REG_RECR2_IPV4_EN_NOT_TCP_NOT_UDP
);
7964 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_EN_TCP_UDP
);
7965 mlxsw_reg_recr2_ipv4_sip_enable(recr2_pl
);
7966 mlxsw_reg_recr2_ipv4_dip_enable(recr2_pl
);
7969 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_EN_IPV4
);
7970 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV4_PROTOCOL
);
7971 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_SPORT
);
7972 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_TCP_UDP_DPORT
);
7975 static void mlxsw_sp_mp6_hash_init(struct mlxsw_sp
*mlxsw_sp
, char *recr2_pl
)
7977 bool only_l3
= !ip6_multipath_hash_policy(mlxsw_sp_net(mlxsw_sp
));
7979 mlxsw_sp_mp_hash_header_set(recr2_pl
,
7980 MLXSW_REG_RECR2_IPV6_EN_NOT_TCP_NOT_UDP
);
7981 mlxsw_sp_mp_hash_header_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_EN_TCP_UDP
);
7982 mlxsw_reg_recr2_ipv6_sip_enable(recr2_pl
);
7983 mlxsw_reg_recr2_ipv6_dip_enable(recr2_pl
);
7984 mlxsw_sp_mp_hash_field_set(recr2_pl
, MLXSW_REG_RECR2_IPV6_NEXT_HEADER
);
7986 mlxsw_sp_mp_hash_field_set(recr2_pl
,
7987 MLXSW_REG_RECR2_IPV6_FLOW_LABEL
);
7989 mlxsw_sp_mp_hash_header_set(recr2_pl
,
7990 MLXSW_REG_RECR2_TCP_UDP_EN_IPV6
);
7991 mlxsw_sp_mp_hash_field_set(recr2_pl
,
7992 MLXSW_REG_RECR2_TCP_UDP_SPORT
);
7993 mlxsw_sp_mp_hash_field_set(recr2_pl
,
7994 MLXSW_REG_RECR2_TCP_UDP_DPORT
);
7998 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
8000 char recr2_pl
[MLXSW_REG_RECR2_LEN
];
8003 seed
= jhash(mlxsw_sp
->base_mac
, sizeof(mlxsw_sp
->base_mac
), 0);
8004 mlxsw_reg_recr2_pack(recr2_pl
, seed
);
8005 mlxsw_sp_mp4_hash_init(mlxsw_sp
, recr2_pl
);
8006 mlxsw_sp_mp6_hash_init(mlxsw_sp
, recr2_pl
);
8008 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(recr2
), recr2_pl
);
8011 static int mlxsw_sp_mp_hash_init(struct mlxsw_sp
*mlxsw_sp
)
8017 static int mlxsw_sp_dscp_init(struct mlxsw_sp
*mlxsw_sp
)
8019 char rdpm_pl
[MLXSW_REG_RDPM_LEN
];
8022 MLXSW_REG_ZERO(rdpm
, rdpm_pl
);
8024 /* HW is determining switch priority based on DSCP-bits, but the
8025 * kernel is still doing that based on the ToS. Since there's a
8026 * mismatch in bits we need to make sure to translate the right
8027 * value ToS would observe, skipping the 2 least-significant ECN bits.
8029 for (i
= 0; i
< MLXSW_REG_RDPM_DSCP_ENTRY_REC_MAX_COUNT
; i
++)
8030 mlxsw_reg_rdpm_pack(rdpm_pl
, i
, rt_tos2priority(i
<< 2));
8032 return mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rdpm
), rdpm_pl
);
8035 static int __mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
)
8037 struct net
*net
= mlxsw_sp_net(mlxsw_sp
);
8038 bool usp
= net
->ipv4
.sysctl_ip_fwd_update_priority
;
8039 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
8043 if (!MLXSW_CORE_RES_VALID(mlxsw_sp
->core
, MAX_RIFS
))
8045 max_rifs
= MLXSW_CORE_RES_GET(mlxsw_sp
->core
, MAX_RIFS
);
8047 mlxsw_reg_rgcr_pack(rgcr_pl
, true, true);
8048 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl
, max_rifs
);
8049 mlxsw_reg_rgcr_usp_set(rgcr_pl
, usp
);
8050 err
= mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
8056 static void __mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
8058 char rgcr_pl
[MLXSW_REG_RGCR_LEN
];
8060 mlxsw_reg_rgcr_pack(rgcr_pl
, false, false);
8061 mlxsw_reg_write(mlxsw_sp
->core
, MLXSW_REG(rgcr
), rgcr_pl
);
8064 int mlxsw_sp_router_init(struct mlxsw_sp
*mlxsw_sp
,
8065 struct netlink_ext_ack
*extack
)
8067 struct mlxsw_sp_router
*router
;
8070 router
= kzalloc(sizeof(*mlxsw_sp
->router
), GFP_KERNEL
);
8073 mlxsw_sp
->router
= router
;
8074 router
->mlxsw_sp
= mlxsw_sp
;
8076 router
->inetaddr_nb
.notifier_call
= mlxsw_sp_inetaddr_event
;
8077 err
= register_inetaddr_notifier(&router
->inetaddr_nb
);
8079 goto err_register_inetaddr_notifier
;
8081 router
->inet6addr_nb
.notifier_call
= mlxsw_sp_inet6addr_event
;
8082 err
= register_inet6addr_notifier(&router
->inet6addr_nb
);
8084 goto err_register_inet6addr_notifier
;
8086 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_neighs_list
);
8087 err
= __mlxsw_sp_router_init(mlxsw_sp
);
8089 goto err_router_init
;
8091 err
= mlxsw_sp_rifs_init(mlxsw_sp
);
8095 err
= mlxsw_sp_ipips_init(mlxsw_sp
);
8097 goto err_ipips_init
;
8099 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_ht
,
8100 &mlxsw_sp_nexthop_ht_params
);
8102 goto err_nexthop_ht_init
;
8104 err
= rhashtable_init(&mlxsw_sp
->router
->nexthop_group_ht
,
8105 &mlxsw_sp_nexthop_group_ht_params
);
8107 goto err_nexthop_group_ht_init
;
8109 INIT_LIST_HEAD(&mlxsw_sp
->router
->nexthop_list
);
8110 err
= mlxsw_sp_lpm_init(mlxsw_sp
);
8114 err
= mlxsw_sp_mr_init(mlxsw_sp
, &mlxsw_sp_mr_tcam_ops
);
8118 err
= mlxsw_sp_vrs_init(mlxsw_sp
);
8122 err
= mlxsw_sp_neigh_init(mlxsw_sp
);
8124 goto err_neigh_init
;
8126 mlxsw_sp
->router
->netevent_nb
.notifier_call
=
8127 mlxsw_sp_router_netevent_event
;
8128 err
= register_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
8130 goto err_register_netevent_notifier
;
8132 err
= mlxsw_sp_mp_hash_init(mlxsw_sp
);
8134 goto err_mp_hash_init
;
8136 err
= mlxsw_sp_dscp_init(mlxsw_sp
);
8140 mlxsw_sp
->router
->fib_nb
.notifier_call
= mlxsw_sp_router_fib_event
;
8141 err
= register_fib_notifier(mlxsw_sp_net(mlxsw_sp
),
8142 &mlxsw_sp
->router
->fib_nb
,
8143 mlxsw_sp_router_fib_dump_flush
, extack
);
8145 goto err_register_fib_notifier
;
8149 err_register_fib_notifier
:
8152 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
8153 err_register_netevent_notifier
:
8154 mlxsw_sp_neigh_fini(mlxsw_sp
);
8156 mlxsw_sp_vrs_fini(mlxsw_sp
);
8158 mlxsw_sp_mr_fini(mlxsw_sp
);
8160 mlxsw_sp_lpm_fini(mlxsw_sp
);
8162 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
8163 err_nexthop_group_ht_init
:
8164 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
8165 err_nexthop_ht_init
:
8166 mlxsw_sp_ipips_fini(mlxsw_sp
);
8168 mlxsw_sp_rifs_fini(mlxsw_sp
);
8170 __mlxsw_sp_router_fini(mlxsw_sp
);
8172 unregister_inet6addr_notifier(&router
->inet6addr_nb
);
8173 err_register_inet6addr_notifier
:
8174 unregister_inetaddr_notifier(&router
->inetaddr_nb
);
8175 err_register_inetaddr_notifier
:
8176 kfree(mlxsw_sp
->router
);
8180 void mlxsw_sp_router_fini(struct mlxsw_sp
*mlxsw_sp
)
8182 unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp
),
8183 &mlxsw_sp
->router
->fib_nb
);
8184 unregister_netevent_notifier(&mlxsw_sp
->router
->netevent_nb
);
8185 mlxsw_sp_neigh_fini(mlxsw_sp
);
8186 mlxsw_sp_vrs_fini(mlxsw_sp
);
8187 mlxsw_sp_mr_fini(mlxsw_sp
);
8188 mlxsw_sp_lpm_fini(mlxsw_sp
);
8189 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_group_ht
);
8190 rhashtable_destroy(&mlxsw_sp
->router
->nexthop_ht
);
8191 mlxsw_sp_ipips_fini(mlxsw_sp
);
8192 mlxsw_sp_rifs_fini(mlxsw_sp
);
8193 __mlxsw_sp_router_fini(mlxsw_sp
);
8194 unregister_inet6addr_notifier(&mlxsw_sp
->router
->inet6addr_nb
);
8195 unregister_inetaddr_notifier(&mlxsw_sp
->router
->inetaddr_nb
);
8196 kfree(mlxsw_sp
->router
);