1
2
3
4#include <linux/kernel.h>
5#include <linux/types.h>
6#include <linux/rhashtable.h>
7#include <linux/bitops.h>
8#include <linux/in6.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 <linux/mutex.h>
21#include <net/netevent.h>
22#include <net/neighbour.h>
23#include <net/arp.h>
24#include <net/ip_fib.h>
25#include <net/ip6_fib.h>
26#include <net/nexthop.h>
27#include <net/fib_rules.h>
28#include <net/ip_tunnels.h>
29#include <net/l3mdev.h>
30#include <net/addrconf.h>
31#include <net/ndisc.h>
32#include <net/ipv6.h>
33#include <net/fib_notifier.h>
34#include <net/switchdev.h>
35
36#include "spectrum.h"
37#include "core.h"
38#include "reg.h"
39#include "spectrum_cnt.h"
40#include "spectrum_dpipe.h"
41#include "spectrum_ipip.h"
42#include "spectrum_mr.h"
43#include "spectrum_mr_tcam.h"
44#include "spectrum_router.h"
45#include "spectrum_span.h"
46
47struct mlxsw_sp_fib;
48struct mlxsw_sp_vr;
49struct mlxsw_sp_lpm_tree;
50struct mlxsw_sp_rif_ops;
51
52struct mlxsw_sp_rif {
53 struct list_head nexthop_list;
54 struct list_head neigh_list;
55 struct net_device *dev;
56 struct mlxsw_sp_fid *fid;
57 unsigned char addr[ETH_ALEN];
58 int mtu;
59 u16 rif_index;
60 u16 vr_id;
61 const struct mlxsw_sp_rif_ops *ops;
62 struct mlxsw_sp *mlxsw_sp;
63
64 unsigned int counter_ingress;
65 bool counter_ingress_valid;
66 unsigned int counter_egress;
67 bool counter_egress_valid;
68};
69
70struct mlxsw_sp_rif_params {
71 struct net_device *dev;
72 union {
73 u16 system_port;
74 u16 lag_id;
75 };
76 u16 vid;
77 bool lag;
78};
79
80struct mlxsw_sp_rif_subport {
81 struct mlxsw_sp_rif common;
82 refcount_t ref_count;
83 union {
84 u16 system_port;
85 u16 lag_id;
86 };
87 u16 vid;
88 bool lag;
89};
90
91struct mlxsw_sp_rif_ipip_lb {
92 struct mlxsw_sp_rif common;
93 struct mlxsw_sp_rif_ipip_lb_config lb_config;
94 u16 ul_vr_id;
95 u16 ul_rif_id;
96};
97
98struct mlxsw_sp_rif_params_ipip_lb {
99 struct mlxsw_sp_rif_params common;
100 struct mlxsw_sp_rif_ipip_lb_config lb_config;
101};
102
103struct mlxsw_sp_rif_ops {
104 enum mlxsw_sp_rif_type type;
105 size_t rif_size;
106
107 void (*setup)(struct mlxsw_sp_rif *rif,
108 const struct mlxsw_sp_rif_params *params);
109 int (*configure)(struct mlxsw_sp_rif *rif);
110 void (*deconfigure)(struct mlxsw_sp_rif *rif);
111 struct mlxsw_sp_fid * (*fid_get)(struct mlxsw_sp_rif *rif,
112 struct netlink_ext_ack *extack);
113 void (*fdb_del)(struct mlxsw_sp_rif *rif, const char *mac);
114};
115
116static struct mlxsw_sp_rif *
117mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
118 const struct net_device *dev);
119static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif);
120static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree);
121static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
122 struct mlxsw_sp_lpm_tree *lpm_tree);
123static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
124 const struct mlxsw_sp_fib *fib,
125 u8 tree_id);
126static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
127 const struct mlxsw_sp_fib *fib);
128
129static unsigned int *
130mlxsw_sp_rif_p_counter_get(struct mlxsw_sp_rif *rif,
131 enum mlxsw_sp_rif_counter_dir dir)
132{
133 switch (dir) {
134 case MLXSW_SP_RIF_COUNTER_EGRESS:
135 return &rif->counter_egress;
136 case MLXSW_SP_RIF_COUNTER_INGRESS:
137 return &rif->counter_ingress;
138 }
139 return NULL;
140}
141
142static bool
143mlxsw_sp_rif_counter_valid_get(struct mlxsw_sp_rif *rif,
144 enum mlxsw_sp_rif_counter_dir dir)
145{
146 switch (dir) {
147 case MLXSW_SP_RIF_COUNTER_EGRESS:
148 return rif->counter_egress_valid;
149 case MLXSW_SP_RIF_COUNTER_INGRESS:
150 return rif->counter_ingress_valid;
151 }
152 return false;
153}
154
155static void
156mlxsw_sp_rif_counter_valid_set(struct mlxsw_sp_rif *rif,
157 enum mlxsw_sp_rif_counter_dir dir,
158 bool valid)
159{
160 switch (dir) {
161 case MLXSW_SP_RIF_COUNTER_EGRESS:
162 rif->counter_egress_valid = valid;
163 break;
164 case MLXSW_SP_RIF_COUNTER_INGRESS:
165 rif->counter_ingress_valid = valid;
166 break;
167 }
168}
169
170static int mlxsw_sp_rif_counter_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
171 unsigned int counter_index, bool enable,
172 enum mlxsw_sp_rif_counter_dir dir)
173{
174 char ritr_pl[MLXSW_REG_RITR_LEN];
175 bool is_egress = false;
176 int err;
177
178 if (dir == MLXSW_SP_RIF_COUNTER_EGRESS)
179 is_egress = true;
180 mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
181 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
182 if (err)
183 return err;
184
185 mlxsw_reg_ritr_counter_pack(ritr_pl, counter_index, enable,
186 is_egress);
187 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
188}
189
190int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp,
191 struct mlxsw_sp_rif *rif,
192 enum mlxsw_sp_rif_counter_dir dir, u64 *cnt)
193{
194 char ricnt_pl[MLXSW_REG_RICNT_LEN];
195 unsigned int *p_counter_index;
196 bool valid;
197 int err;
198
199 valid = mlxsw_sp_rif_counter_valid_get(rif, dir);
200 if (!valid)
201 return -EINVAL;
202
203 p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
204 if (!p_counter_index)
205 return -EINVAL;
206 mlxsw_reg_ricnt_pack(ricnt_pl, *p_counter_index,
207 MLXSW_REG_RICNT_OPCODE_NOP);
208 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
209 if (err)
210 return err;
211 *cnt = mlxsw_reg_ricnt_good_unicast_packets_get(ricnt_pl);
212 return 0;
213}
214
215static int mlxsw_sp_rif_counter_clear(struct mlxsw_sp *mlxsw_sp,
216 unsigned int counter_index)
217{
218 char ricnt_pl[MLXSW_REG_RICNT_LEN];
219
220 mlxsw_reg_ricnt_pack(ricnt_pl, counter_index,
221 MLXSW_REG_RICNT_OPCODE_CLEAR);
222 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ricnt), ricnt_pl);
223}
224
225int mlxsw_sp_rif_counter_alloc(struct mlxsw_sp *mlxsw_sp,
226 struct mlxsw_sp_rif *rif,
227 enum mlxsw_sp_rif_counter_dir dir)
228{
229 unsigned int *p_counter_index;
230 int err;
231
232 p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
233 if (!p_counter_index)
234 return -EINVAL;
235 err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
236 p_counter_index);
237 if (err)
238 return err;
239
240 err = mlxsw_sp_rif_counter_clear(mlxsw_sp, *p_counter_index);
241 if (err)
242 goto err_counter_clear;
243
244 err = mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
245 *p_counter_index, true, dir);
246 if (err)
247 goto err_counter_edit;
248 mlxsw_sp_rif_counter_valid_set(rif, dir, true);
249 return 0;
250
251err_counter_edit:
252err_counter_clear:
253 mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
254 *p_counter_index);
255 return err;
256}
257
258void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,
259 struct mlxsw_sp_rif *rif,
260 enum mlxsw_sp_rif_counter_dir dir)
261{
262 unsigned int *p_counter_index;
263
264 if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
265 return;
266
267 p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
268 if (WARN_ON(!p_counter_index))
269 return;
270 mlxsw_sp_rif_counter_edit(mlxsw_sp, rif->rif_index,
271 *p_counter_index, false, dir);
272 mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_RIF,
273 *p_counter_index);
274 mlxsw_sp_rif_counter_valid_set(rif, dir, false);
275}
276
277static void mlxsw_sp_rif_counters_alloc(struct mlxsw_sp_rif *rif)
278{
279 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
280 struct devlink *devlink;
281
282 devlink = priv_to_devlink(mlxsw_sp->core);
283 if (!devlink_dpipe_table_counter_enabled(devlink,
284 MLXSW_SP_DPIPE_TABLE_NAME_ERIF))
285 return;
286 mlxsw_sp_rif_counter_alloc(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS);
287}
288
289static void mlxsw_sp_rif_counters_free(struct mlxsw_sp_rif *rif)
290{
291 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
292
293 mlxsw_sp_rif_counter_free(mlxsw_sp, rif, MLXSW_SP_RIF_COUNTER_EGRESS);
294}
295
296#define MLXSW_SP_PREFIX_COUNT (sizeof(struct in6_addr) * BITS_PER_BYTE + 1)
297
298struct mlxsw_sp_prefix_usage {
299 DECLARE_BITMAP(b, MLXSW_SP_PREFIX_COUNT);
300};
301
302#define mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) \
303 for_each_set_bit(prefix, (prefix_usage)->b, MLXSW_SP_PREFIX_COUNT)
304
305static bool
306mlxsw_sp_prefix_usage_eq(struct mlxsw_sp_prefix_usage *prefix_usage1,
307 struct mlxsw_sp_prefix_usage *prefix_usage2)
308{
309 return !memcmp(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
310}
311
312static void
313mlxsw_sp_prefix_usage_cpy(struct mlxsw_sp_prefix_usage *prefix_usage1,
314 struct mlxsw_sp_prefix_usage *prefix_usage2)
315{
316 memcpy(prefix_usage1, prefix_usage2, sizeof(*prefix_usage1));
317}
318
319static void
320mlxsw_sp_prefix_usage_set(struct mlxsw_sp_prefix_usage *prefix_usage,
321 unsigned char prefix_len)
322{
323 set_bit(prefix_len, prefix_usage->b);
324}
325
326static void
327mlxsw_sp_prefix_usage_clear(struct mlxsw_sp_prefix_usage *prefix_usage,
328 unsigned char prefix_len)
329{
330 clear_bit(prefix_len, prefix_usage->b);
331}
332
333struct mlxsw_sp_fib_key {
334 unsigned char addr[sizeof(struct in6_addr)];
335 unsigned char prefix_len;
336};
337
338enum mlxsw_sp_fib_entry_type {
339 MLXSW_SP_FIB_ENTRY_TYPE_REMOTE,
340 MLXSW_SP_FIB_ENTRY_TYPE_LOCAL,
341 MLXSW_SP_FIB_ENTRY_TYPE_TRAP,
342 MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE,
343 MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE,
344
345
346
347
348
349
350
351 MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP,
352 MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP,
353};
354
355struct mlxsw_sp_nexthop_group;
356struct mlxsw_sp_fib_entry;
357
358struct mlxsw_sp_fib_node {
359 struct mlxsw_sp_fib_entry *fib_entry;
360 struct list_head list;
361 struct rhash_head ht_node;
362 struct mlxsw_sp_fib *fib;
363 struct mlxsw_sp_fib_key key;
364};
365
366struct mlxsw_sp_fib_entry_decap {
367 struct mlxsw_sp_ipip_entry *ipip_entry;
368 u32 tunnel_index;
369};
370
371struct mlxsw_sp_fib_entry {
372 struct mlxsw_sp_fib_node *fib_node;
373 enum mlxsw_sp_fib_entry_type type;
374 struct list_head nexthop_group_node;
375 struct mlxsw_sp_nexthop_group *nh_group;
376 struct mlxsw_sp_fib_entry_decap decap;
377};
378
379struct mlxsw_sp_fib4_entry {
380 struct mlxsw_sp_fib_entry common;
381 u32 tb_id;
382 u32 prio;
383 u8 tos;
384 u8 type;
385};
386
387struct mlxsw_sp_fib6_entry {
388 struct mlxsw_sp_fib_entry common;
389 struct list_head rt6_list;
390 unsigned int nrt6;
391};
392
393struct mlxsw_sp_rt6 {
394 struct list_head list;
395 struct fib6_info *rt;
396};
397
398struct mlxsw_sp_lpm_tree {
399 u8 id;
400 unsigned int ref_count;
401 enum mlxsw_sp_l3proto proto;
402 unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
403 struct mlxsw_sp_prefix_usage prefix_usage;
404};
405
406struct mlxsw_sp_fib {
407 struct rhashtable ht;
408 struct list_head node_list;
409 struct mlxsw_sp_vr *vr;
410 struct mlxsw_sp_lpm_tree *lpm_tree;
411 enum mlxsw_sp_l3proto proto;
412};
413
414struct mlxsw_sp_vr {
415 u16 id;
416 u32 tb_id;
417 unsigned int rif_count;
418 struct mlxsw_sp_fib *fib4;
419 struct mlxsw_sp_fib *fib6;
420 struct mlxsw_sp_mr_table *mr_table[MLXSW_SP_L3_PROTO_MAX];
421 struct mlxsw_sp_rif *ul_rif;
422 refcount_t ul_rif_refcnt;
423};
424
425static const struct rhashtable_params mlxsw_sp_fib_ht_params;
426
427static struct mlxsw_sp_fib *mlxsw_sp_fib_create(struct mlxsw_sp *mlxsw_sp,
428 struct mlxsw_sp_vr *vr,
429 enum mlxsw_sp_l3proto proto)
430{
431 struct mlxsw_sp_lpm_tree *lpm_tree;
432 struct mlxsw_sp_fib *fib;
433 int err;
434
435 lpm_tree = mlxsw_sp->router->lpm.proto_trees[proto];
436 fib = kzalloc(sizeof(*fib), GFP_KERNEL);
437 if (!fib)
438 return ERR_PTR(-ENOMEM);
439 err = rhashtable_init(&fib->ht, &mlxsw_sp_fib_ht_params);
440 if (err)
441 goto err_rhashtable_init;
442 INIT_LIST_HEAD(&fib->node_list);
443 fib->proto = proto;
444 fib->vr = vr;
445 fib->lpm_tree = lpm_tree;
446 mlxsw_sp_lpm_tree_hold(lpm_tree);
447 err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, lpm_tree->id);
448 if (err)
449 goto err_lpm_tree_bind;
450 return fib;
451
452err_lpm_tree_bind:
453 mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
454err_rhashtable_init:
455 kfree(fib);
456 return ERR_PTR(err);
457}
458
459static void mlxsw_sp_fib_destroy(struct mlxsw_sp *mlxsw_sp,
460 struct mlxsw_sp_fib *fib)
461{
462 mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib);
463 mlxsw_sp_lpm_tree_put(mlxsw_sp, fib->lpm_tree);
464 WARN_ON(!list_empty(&fib->node_list));
465 rhashtable_destroy(&fib->ht);
466 kfree(fib);
467}
468
469static struct mlxsw_sp_lpm_tree *
470mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
471{
472 static struct mlxsw_sp_lpm_tree *lpm_tree;
473 int i;
474
475 for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
476 lpm_tree = &mlxsw_sp->router->lpm.trees[i];
477 if (lpm_tree->ref_count == 0)
478 return lpm_tree;
479 }
480 return NULL;
481}
482
483static int mlxsw_sp_lpm_tree_alloc(struct mlxsw_sp *mlxsw_sp,
484 struct mlxsw_sp_lpm_tree *lpm_tree)
485{
486 char ralta_pl[MLXSW_REG_RALTA_LEN];
487
488 mlxsw_reg_ralta_pack(ralta_pl, true,
489 (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
490 lpm_tree->id);
491 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
492}
493
494static void mlxsw_sp_lpm_tree_free(struct mlxsw_sp *mlxsw_sp,
495 struct mlxsw_sp_lpm_tree *lpm_tree)
496{
497 char ralta_pl[MLXSW_REG_RALTA_LEN];
498
499 mlxsw_reg_ralta_pack(ralta_pl, false,
500 (enum mlxsw_reg_ralxx_protocol) lpm_tree->proto,
501 lpm_tree->id);
502 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
503}
504
505static int
506mlxsw_sp_lpm_tree_left_struct_set(struct mlxsw_sp *mlxsw_sp,
507 struct mlxsw_sp_prefix_usage *prefix_usage,
508 struct mlxsw_sp_lpm_tree *lpm_tree)
509{
510 char ralst_pl[MLXSW_REG_RALST_LEN];
511 u8 root_bin = 0;
512 u8 prefix;
513 u8 last_prefix = MLXSW_REG_RALST_BIN_NO_CHILD;
514
515 mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage)
516 root_bin = prefix;
517
518 mlxsw_reg_ralst_pack(ralst_pl, root_bin, lpm_tree->id);
519 mlxsw_sp_prefix_usage_for_each(prefix, prefix_usage) {
520 if (prefix == 0)
521 continue;
522 mlxsw_reg_ralst_bin_pack(ralst_pl, prefix, last_prefix,
523 MLXSW_REG_RALST_BIN_NO_CHILD);
524 last_prefix = prefix;
525 }
526 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
527}
528
529static struct mlxsw_sp_lpm_tree *
530mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
531 struct mlxsw_sp_prefix_usage *prefix_usage,
532 enum mlxsw_sp_l3proto proto)
533{
534 struct mlxsw_sp_lpm_tree *lpm_tree;
535 int err;
536
537 lpm_tree = mlxsw_sp_lpm_tree_find_unused(mlxsw_sp);
538 if (!lpm_tree)
539 return ERR_PTR(-EBUSY);
540 lpm_tree->proto = proto;
541 err = mlxsw_sp_lpm_tree_alloc(mlxsw_sp, lpm_tree);
542 if (err)
543 return ERR_PTR(err);
544
545 err = mlxsw_sp_lpm_tree_left_struct_set(mlxsw_sp, prefix_usage,
546 lpm_tree);
547 if (err)
548 goto err_left_struct_set;
549 memcpy(&lpm_tree->prefix_usage, prefix_usage,
550 sizeof(lpm_tree->prefix_usage));
551 memset(&lpm_tree->prefix_ref_count, 0,
552 sizeof(lpm_tree->prefix_ref_count));
553 lpm_tree->ref_count = 1;
554 return lpm_tree;
555
556err_left_struct_set:
557 mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
558 return ERR_PTR(err);
559}
560
561static void mlxsw_sp_lpm_tree_destroy(struct mlxsw_sp *mlxsw_sp,
562 struct mlxsw_sp_lpm_tree *lpm_tree)
563{
564 mlxsw_sp_lpm_tree_free(mlxsw_sp, lpm_tree);
565}
566
567static struct mlxsw_sp_lpm_tree *
568mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
569 struct mlxsw_sp_prefix_usage *prefix_usage,
570 enum mlxsw_sp_l3proto proto)
571{
572 struct mlxsw_sp_lpm_tree *lpm_tree;
573 int i;
574
575 for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
576 lpm_tree = &mlxsw_sp->router->lpm.trees[i];
577 if (lpm_tree->ref_count != 0 &&
578 lpm_tree->proto == proto &&
579 mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
580 prefix_usage)) {
581 mlxsw_sp_lpm_tree_hold(lpm_tree);
582 return lpm_tree;
583 }
584 }
585 return mlxsw_sp_lpm_tree_create(mlxsw_sp, prefix_usage, proto);
586}
587
588static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree)
589{
590 lpm_tree->ref_count++;
591}
592
593static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
594 struct mlxsw_sp_lpm_tree *lpm_tree)
595{
596 if (--lpm_tree->ref_count == 0)
597 mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
598}
599
600#define MLXSW_SP_LPM_TREE_MIN 1
601
602static int mlxsw_sp_lpm_init(struct mlxsw_sp *mlxsw_sp)
603{
604 struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } };
605 struct mlxsw_sp_lpm_tree *lpm_tree;
606 u64 max_trees;
607 int err, i;
608
609 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LPM_TREES))
610 return -EIO;
611
612 max_trees = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LPM_TREES);
613 mlxsw_sp->router->lpm.tree_count = max_trees - MLXSW_SP_LPM_TREE_MIN;
614 mlxsw_sp->router->lpm.trees = kcalloc(mlxsw_sp->router->lpm.tree_count,
615 sizeof(struct mlxsw_sp_lpm_tree),
616 GFP_KERNEL);
617 if (!mlxsw_sp->router->lpm.trees)
618 return -ENOMEM;
619
620 for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
621 lpm_tree = &mlxsw_sp->router->lpm.trees[i];
622 lpm_tree->id = i + MLXSW_SP_LPM_TREE_MIN;
623 }
624
625 lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
626 MLXSW_SP_L3_PROTO_IPV4);
627 if (IS_ERR(lpm_tree)) {
628 err = PTR_ERR(lpm_tree);
629 goto err_ipv4_tree_get;
630 }
631 mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4] = lpm_tree;
632
633 lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
634 MLXSW_SP_L3_PROTO_IPV6);
635 if (IS_ERR(lpm_tree)) {
636 err = PTR_ERR(lpm_tree);
637 goto err_ipv6_tree_get;
638 }
639 mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV6] = lpm_tree;
640
641 return 0;
642
643err_ipv6_tree_get:
644 lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4];
645 mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
646err_ipv4_tree_get:
647 kfree(mlxsw_sp->router->lpm.trees);
648 return err;
649}
650
651static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
652{
653 struct mlxsw_sp_lpm_tree *lpm_tree;
654
655 lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV6];
656 mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
657
658 lpm_tree = mlxsw_sp->router->lpm.proto_trees[MLXSW_SP_L3_PROTO_IPV4];
659 mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
660
661 kfree(mlxsw_sp->router->lpm.trees);
662}
663
664static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
665{
666 return !!vr->fib4 || !!vr->fib6 ||
667 !!vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] ||
668 !!vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
669}
670
671static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
672{
673 struct mlxsw_sp_vr *vr;
674 int i;
675
676 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
677 vr = &mlxsw_sp->router->vrs[i];
678 if (!mlxsw_sp_vr_is_used(vr))
679 return vr;
680 }
681 return NULL;
682}
683
684static int mlxsw_sp_vr_lpm_tree_bind(struct mlxsw_sp *mlxsw_sp,
685 const struct mlxsw_sp_fib *fib, u8 tree_id)
686{
687 char raltb_pl[MLXSW_REG_RALTB_LEN];
688
689 mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
690 (enum mlxsw_reg_ralxx_protocol) fib->proto,
691 tree_id);
692 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
693}
694
695static int mlxsw_sp_vr_lpm_tree_unbind(struct mlxsw_sp *mlxsw_sp,
696 const struct mlxsw_sp_fib *fib)
697{
698 char raltb_pl[MLXSW_REG_RALTB_LEN];
699
700
701 mlxsw_reg_raltb_pack(raltb_pl, fib->vr->id,
702 (enum mlxsw_reg_ralxx_protocol) fib->proto, 0);
703 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb), raltb_pl);
704}
705
706static u32 mlxsw_sp_fix_tb_id(u32 tb_id)
707{
708
709 if (tb_id == RT_TABLE_LOCAL || tb_id == RT_TABLE_DEFAULT)
710 tb_id = RT_TABLE_MAIN;
711 return tb_id;
712}
713
714static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp,
715 u32 tb_id)
716{
717 struct mlxsw_sp_vr *vr;
718 int i;
719
720 tb_id = mlxsw_sp_fix_tb_id(tb_id);
721
722 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
723 vr = &mlxsw_sp->router->vrs[i];
724 if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id)
725 return vr;
726 }
727 return NULL;
728}
729
730int mlxsw_sp_router_tb_id_vr_id(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
731 u16 *vr_id)
732{
733 struct mlxsw_sp_vr *vr;
734 int err = 0;
735
736 mutex_lock(&mlxsw_sp->router->lock);
737 vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
738 if (!vr) {
739 err = -ESRCH;
740 goto out;
741 }
742 *vr_id = vr->id;
743out:
744 mutex_unlock(&mlxsw_sp->router->lock);
745 return err;
746}
747
748static struct mlxsw_sp_fib *mlxsw_sp_vr_fib(const struct mlxsw_sp_vr *vr,
749 enum mlxsw_sp_l3proto proto)
750{
751 switch (proto) {
752 case MLXSW_SP_L3_PROTO_IPV4:
753 return vr->fib4;
754 case MLXSW_SP_L3_PROTO_IPV6:
755 return vr->fib6;
756 }
757 return NULL;
758}
759
760static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
761 u32 tb_id,
762 struct netlink_ext_ack *extack)
763{
764 struct mlxsw_sp_mr_table *mr4_table, *mr6_table;
765 struct mlxsw_sp_fib *fib4;
766 struct mlxsw_sp_fib *fib6;
767 struct mlxsw_sp_vr *vr;
768 int err;
769
770 vr = mlxsw_sp_vr_find_unused(mlxsw_sp);
771 if (!vr) {
772 NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported virtual routers");
773 return ERR_PTR(-EBUSY);
774 }
775 fib4 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
776 if (IS_ERR(fib4))
777 return ERR_CAST(fib4);
778 fib6 = mlxsw_sp_fib_create(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
779 if (IS_ERR(fib6)) {
780 err = PTR_ERR(fib6);
781 goto err_fib6_create;
782 }
783 mr4_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
784 MLXSW_SP_L3_PROTO_IPV4);
785 if (IS_ERR(mr4_table)) {
786 err = PTR_ERR(mr4_table);
787 goto err_mr4_table_create;
788 }
789 mr6_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
790 MLXSW_SP_L3_PROTO_IPV6);
791 if (IS_ERR(mr6_table)) {
792 err = PTR_ERR(mr6_table);
793 goto err_mr6_table_create;
794 }
795
796 vr->fib4 = fib4;
797 vr->fib6 = fib6;
798 vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = mr4_table;
799 vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = mr6_table;
800 vr->tb_id = tb_id;
801 return vr;
802
803err_mr6_table_create:
804 mlxsw_sp_mr_table_destroy(mr4_table);
805err_mr4_table_create:
806 mlxsw_sp_fib_destroy(mlxsw_sp, fib6);
807err_fib6_create:
808 mlxsw_sp_fib_destroy(mlxsw_sp, fib4);
809 return ERR_PTR(err);
810}
811
812static void mlxsw_sp_vr_destroy(struct mlxsw_sp *mlxsw_sp,
813 struct mlxsw_sp_vr *vr)
814{
815 mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]);
816 vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = NULL;
817 mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]);
818 vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = NULL;
819 mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib6);
820 vr->fib6 = NULL;
821 mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib4);
822 vr->fib4 = NULL;
823}
824
825static struct mlxsw_sp_vr *mlxsw_sp_vr_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
826 struct netlink_ext_ack *extack)
827{
828 struct mlxsw_sp_vr *vr;
829
830 tb_id = mlxsw_sp_fix_tb_id(tb_id);
831 vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
832 if (!vr)
833 vr = mlxsw_sp_vr_create(mlxsw_sp, tb_id, extack);
834 return vr;
835}
836
837static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr)
838{
839 if (!vr->rif_count && list_empty(&vr->fib4->node_list) &&
840 list_empty(&vr->fib6->node_list) &&
841 mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]) &&
842 mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]))
843 mlxsw_sp_vr_destroy(mlxsw_sp, vr);
844}
845
846static bool
847mlxsw_sp_vr_lpm_tree_should_replace(struct mlxsw_sp_vr *vr,
848 enum mlxsw_sp_l3proto proto, u8 tree_id)
849{
850 struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
851
852 if (!mlxsw_sp_vr_is_used(vr))
853 return false;
854 if (fib->lpm_tree->id == tree_id)
855 return true;
856 return false;
857}
858
859static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
860 struct mlxsw_sp_fib *fib,
861 struct mlxsw_sp_lpm_tree *new_tree)
862{
863 struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree;
864 int err;
865
866 fib->lpm_tree = new_tree;
867 mlxsw_sp_lpm_tree_hold(new_tree);
868 err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id);
869 if (err)
870 goto err_tree_bind;
871 mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
872 return 0;
873
874err_tree_bind:
875 mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree);
876 fib->lpm_tree = old_tree;
877 return err;
878}
879
880static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp,
881 struct mlxsw_sp_fib *fib,
882 struct mlxsw_sp_lpm_tree *new_tree)
883{
884 enum mlxsw_sp_l3proto proto = fib->proto;
885 struct mlxsw_sp_lpm_tree *old_tree;
886 u8 old_id, new_id = new_tree->id;
887 struct mlxsw_sp_vr *vr;
888 int i, err;
889
890 old_tree = mlxsw_sp->router->lpm.proto_trees[proto];
891 old_id = old_tree->id;
892
893 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
894 vr = &mlxsw_sp->router->vrs[i];
895 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id))
896 continue;
897 err = mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
898 mlxsw_sp_vr_fib(vr, proto),
899 new_tree);
900 if (err)
901 goto err_tree_replace;
902 }
903
904 memcpy(new_tree->prefix_ref_count, old_tree->prefix_ref_count,
905 sizeof(new_tree->prefix_ref_count));
906 mlxsw_sp->router->lpm.proto_trees[proto] = new_tree;
907 mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree);
908
909 return 0;
910
911err_tree_replace:
912 for (i--; i >= 0; i--) {
913 if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, new_id))
914 continue;
915 mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
916 mlxsw_sp_vr_fib(vr, proto),
917 old_tree);
918 }
919 return err;
920}
921
922static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
923{
924 struct mlxsw_sp_vr *vr;
925 u64 max_vrs;
926 int i;
927
928 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
929 return -EIO;
930
931 max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
932 mlxsw_sp->router->vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
933 GFP_KERNEL);
934 if (!mlxsw_sp->router->vrs)
935 return -ENOMEM;
936
937 for (i = 0; i < max_vrs; i++) {
938 vr = &mlxsw_sp->router->vrs[i];
939 vr->id = i;
940 }
941
942 return 0;
943}
944
945static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp);
946
947static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
948{
949
950
951
952
953
954
955
956 mlxsw_core_flush_owq();
957 mlxsw_sp_router_fib_flush(mlxsw_sp);
958 kfree(mlxsw_sp->router->vrs);
959}
960
961static struct net_device *
962__mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev)
963{
964 struct ip_tunnel *tun = netdev_priv(ol_dev);
965 struct net *net = dev_net(ol_dev);
966
967 return dev_get_by_index_rcu(net, tun->parms.link);
968}
969
970u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
971{
972 struct net_device *d;
973 u32 tb_id;
974
975 rcu_read_lock();
976 d = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
977 if (d)
978 tb_id = l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
979 else
980 tb_id = RT_TABLE_MAIN;
981 rcu_read_unlock();
982
983 return tb_id;
984}
985
986static struct mlxsw_sp_rif *
987mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
988 const struct mlxsw_sp_rif_params *params,
989 struct netlink_ext_ack *extack);
990
991static struct mlxsw_sp_rif_ipip_lb *
992mlxsw_sp_ipip_ol_ipip_lb_create(struct mlxsw_sp *mlxsw_sp,
993 enum mlxsw_sp_ipip_type ipipt,
994 struct net_device *ol_dev,
995 struct netlink_ext_ack *extack)
996{
997 struct mlxsw_sp_rif_params_ipip_lb lb_params;
998 const struct mlxsw_sp_ipip_ops *ipip_ops;
999 struct mlxsw_sp_rif *rif;
1000
1001 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
1002 lb_params = (struct mlxsw_sp_rif_params_ipip_lb) {
1003 .common.dev = ol_dev,
1004 .common.lag = false,
1005 .lb_config = ipip_ops->ol_loopback_config(mlxsw_sp, ol_dev),
1006 };
1007
1008 rif = mlxsw_sp_rif_create(mlxsw_sp, &lb_params.common, extack);
1009 if (IS_ERR(rif))
1010 return ERR_CAST(rif);
1011 return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
1012}
1013
1014static struct mlxsw_sp_ipip_entry *
1015mlxsw_sp_ipip_entry_alloc(struct mlxsw_sp *mlxsw_sp,
1016 enum mlxsw_sp_ipip_type ipipt,
1017 struct net_device *ol_dev)
1018{
1019 const struct mlxsw_sp_ipip_ops *ipip_ops;
1020 struct mlxsw_sp_ipip_entry *ipip_entry;
1021 struct mlxsw_sp_ipip_entry *ret = NULL;
1022
1023 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipipt];
1024 ipip_entry = kzalloc(sizeof(*ipip_entry), GFP_KERNEL);
1025 if (!ipip_entry)
1026 return ERR_PTR(-ENOMEM);
1027
1028 ipip_entry->ol_lb = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp, ipipt,
1029 ol_dev, NULL);
1030 if (IS_ERR(ipip_entry->ol_lb)) {
1031 ret = ERR_CAST(ipip_entry->ol_lb);
1032 goto err_ol_ipip_lb_create;
1033 }
1034
1035 ipip_entry->ipipt = ipipt;
1036 ipip_entry->ol_dev = ol_dev;
1037
1038 switch (ipip_ops->ul_proto) {
1039 case MLXSW_SP_L3_PROTO_IPV4:
1040 ipip_entry->parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
1041 break;
1042 case MLXSW_SP_L3_PROTO_IPV6:
1043 WARN_ON(1);
1044 break;
1045 }
1046
1047 return ipip_entry;
1048
1049err_ol_ipip_lb_create:
1050 kfree(ipip_entry);
1051 return ret;
1052}
1053
1054static void
1055mlxsw_sp_ipip_entry_dealloc(struct mlxsw_sp_ipip_entry *ipip_entry)
1056{
1057 mlxsw_sp_rif_destroy(&ipip_entry->ol_lb->common);
1058 kfree(ipip_entry);
1059}
1060
1061static bool
1062mlxsw_sp_ipip_entry_saddr_matches(struct mlxsw_sp *mlxsw_sp,
1063 const enum mlxsw_sp_l3proto ul_proto,
1064 union mlxsw_sp_l3addr saddr,
1065 u32 ul_tb_id,
1066 struct mlxsw_sp_ipip_entry *ipip_entry)
1067{
1068 u32 tun_ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
1069 enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
1070 union mlxsw_sp_l3addr tun_saddr;
1071
1072 if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
1073 return false;
1074
1075 tun_saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
1076 return tun_ul_tb_id == ul_tb_id &&
1077 mlxsw_sp_l3addr_eq(&tun_saddr, &saddr);
1078}
1079
1080static int
1081mlxsw_sp_fib_entry_decap_init(struct mlxsw_sp *mlxsw_sp,
1082 struct mlxsw_sp_fib_entry *fib_entry,
1083 struct mlxsw_sp_ipip_entry *ipip_entry)
1084{
1085 u32 tunnel_index;
1086 int err;
1087
1088 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
1089 1, &tunnel_index);
1090 if (err)
1091 return err;
1092
1093 ipip_entry->decap_fib_entry = fib_entry;
1094 fib_entry->decap.ipip_entry = ipip_entry;
1095 fib_entry->decap.tunnel_index = tunnel_index;
1096 return 0;
1097}
1098
1099static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp,
1100 struct mlxsw_sp_fib_entry *fib_entry)
1101{
1102
1103 fib_entry->decap.ipip_entry->decap_fib_entry = NULL;
1104 fib_entry->decap.ipip_entry = NULL;
1105 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
1106 1, fib_entry->decap.tunnel_index);
1107}
1108
1109static struct mlxsw_sp_fib_node *
1110mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
1111 size_t addr_len, unsigned char prefix_len);
1112static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
1113 struct mlxsw_sp_fib_entry *fib_entry);
1114
1115static void
1116mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp,
1117 struct mlxsw_sp_ipip_entry *ipip_entry)
1118{
1119 struct mlxsw_sp_fib_entry *fib_entry = ipip_entry->decap_fib_entry;
1120
1121 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
1122 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1123
1124 mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
1125}
1126
1127static void
1128mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp *mlxsw_sp,
1129 struct mlxsw_sp_ipip_entry *ipip_entry,
1130 struct mlxsw_sp_fib_entry *decap_fib_entry)
1131{
1132 if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp, decap_fib_entry,
1133 ipip_entry))
1134 return;
1135 decap_fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
1136
1137 if (mlxsw_sp_fib_entry_update(mlxsw_sp, decap_fib_entry))
1138 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1139}
1140
1141static struct mlxsw_sp_fib_entry *
1142mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
1143 enum mlxsw_sp_l3proto proto,
1144 const union mlxsw_sp_l3addr *addr,
1145 enum mlxsw_sp_fib_entry_type type)
1146{
1147 struct mlxsw_sp_fib_node *fib_node;
1148 unsigned char addr_prefix_len;
1149 struct mlxsw_sp_fib *fib;
1150 struct mlxsw_sp_vr *vr;
1151 const void *addrp;
1152 size_t addr_len;
1153 u32 addr4;
1154
1155 vr = mlxsw_sp_vr_find(mlxsw_sp, tb_id);
1156 if (!vr)
1157 return NULL;
1158 fib = mlxsw_sp_vr_fib(vr, proto);
1159
1160 switch (proto) {
1161 case MLXSW_SP_L3_PROTO_IPV4:
1162 addr4 = be32_to_cpu(addr->addr4);
1163 addrp = &addr4;
1164 addr_len = 4;
1165 addr_prefix_len = 32;
1166 break;
1167 case MLXSW_SP_L3_PROTO_IPV6:
1168 default:
1169 WARN_ON(1);
1170 return NULL;
1171 }
1172
1173 fib_node = mlxsw_sp_fib_node_lookup(fib, addrp, addr_len,
1174 addr_prefix_len);
1175 if (!fib_node || fib_node->fib_entry->type != type)
1176 return NULL;
1177
1178 return fib_node->fib_entry;
1179}
1180
1181
1182static struct mlxsw_sp_fib_entry *
1183mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
1184 struct mlxsw_sp_ipip_entry *ipip_entry)
1185{
1186 static struct mlxsw_sp_fib_node *fib_node;
1187 const struct mlxsw_sp_ipip_ops *ipip_ops;
1188 unsigned char saddr_prefix_len;
1189 union mlxsw_sp_l3addr saddr;
1190 struct mlxsw_sp_fib *ul_fib;
1191 struct mlxsw_sp_vr *ul_vr;
1192 const void *saddrp;
1193 size_t saddr_len;
1194 u32 ul_tb_id;
1195 u32 saddr4;
1196
1197 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
1198
1199 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
1200 ul_vr = mlxsw_sp_vr_find(mlxsw_sp, ul_tb_id);
1201 if (!ul_vr)
1202 return NULL;
1203
1204 ul_fib = mlxsw_sp_vr_fib(ul_vr, ipip_ops->ul_proto);
1205 saddr = mlxsw_sp_ipip_netdev_saddr(ipip_ops->ul_proto,
1206 ipip_entry->ol_dev);
1207
1208 switch (ipip_ops->ul_proto) {
1209 case MLXSW_SP_L3_PROTO_IPV4:
1210 saddr4 = be32_to_cpu(saddr.addr4);
1211 saddrp = &saddr4;
1212 saddr_len = 4;
1213 saddr_prefix_len = 32;
1214 break;
1215 default:
1216 WARN_ON(1);
1217 return NULL;
1218 }
1219
1220 fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len,
1221 saddr_prefix_len);
1222 if (!fib_node ||
1223 fib_node->fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
1224 return NULL;
1225
1226 return fib_node->fib_entry;
1227}
1228
1229static struct mlxsw_sp_ipip_entry *
1230mlxsw_sp_ipip_entry_create(struct mlxsw_sp *mlxsw_sp,
1231 enum mlxsw_sp_ipip_type ipipt,
1232 struct net_device *ol_dev)
1233{
1234 struct mlxsw_sp_ipip_entry *ipip_entry;
1235
1236 ipip_entry = mlxsw_sp_ipip_entry_alloc(mlxsw_sp, ipipt, ol_dev);
1237 if (IS_ERR(ipip_entry))
1238 return ipip_entry;
1239
1240 list_add_tail(&ipip_entry->ipip_list_node,
1241 &mlxsw_sp->router->ipip_list);
1242
1243 return ipip_entry;
1244}
1245
1246static void
1247mlxsw_sp_ipip_entry_destroy(struct mlxsw_sp *mlxsw_sp,
1248 struct mlxsw_sp_ipip_entry *ipip_entry)
1249{
1250 list_del(&ipip_entry->ipip_list_node);
1251 mlxsw_sp_ipip_entry_dealloc(ipip_entry);
1252}
1253
1254static bool
1255mlxsw_sp_ipip_entry_matches_decap(struct mlxsw_sp *mlxsw_sp,
1256 const struct net_device *ul_dev,
1257 enum mlxsw_sp_l3proto ul_proto,
1258 union mlxsw_sp_l3addr ul_dip,
1259 struct mlxsw_sp_ipip_entry *ipip_entry)
1260{
1261 u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
1262 enum mlxsw_sp_ipip_type ipipt = ipip_entry->ipipt;
1263
1264 if (mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto != ul_proto)
1265 return false;
1266
1267 return mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, ul_dip,
1268 ul_tb_id, ipip_entry);
1269}
1270
1271
1272static struct mlxsw_sp_ipip_entry *
1273mlxsw_sp_ipip_entry_find_by_decap(struct mlxsw_sp *mlxsw_sp,
1274 const struct net_device *ul_dev,
1275 enum mlxsw_sp_l3proto ul_proto,
1276 union mlxsw_sp_l3addr ul_dip)
1277{
1278 struct mlxsw_sp_ipip_entry *ipip_entry;
1279
1280 list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1281 ipip_list_node)
1282 if (mlxsw_sp_ipip_entry_matches_decap(mlxsw_sp, ul_dev,
1283 ul_proto, ul_dip,
1284 ipip_entry))
1285 return ipip_entry;
1286
1287 return NULL;
1288}
1289
1290static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
1291 const struct net_device *dev,
1292 enum mlxsw_sp_ipip_type *p_type)
1293{
1294 struct mlxsw_sp_router *router = mlxsw_sp->router;
1295 const struct mlxsw_sp_ipip_ops *ipip_ops;
1296 enum mlxsw_sp_ipip_type ipipt;
1297
1298 for (ipipt = 0; ipipt < MLXSW_SP_IPIP_TYPE_MAX; ++ipipt) {
1299 ipip_ops = router->ipip_ops_arr[ipipt];
1300 if (dev->type == ipip_ops->dev_type) {
1301 if (p_type)
1302 *p_type = ipipt;
1303 return true;
1304 }
1305 }
1306 return false;
1307}
1308
1309bool mlxsw_sp_netdev_is_ipip_ol(const struct mlxsw_sp *mlxsw_sp,
1310 const struct net_device *dev)
1311{
1312 return mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
1313}
1314
1315static struct mlxsw_sp_ipip_entry *
1316mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp *mlxsw_sp,
1317 const struct net_device *ol_dev)
1318{
1319 struct mlxsw_sp_ipip_entry *ipip_entry;
1320
1321 list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1322 ipip_list_node)
1323 if (ipip_entry->ol_dev == ol_dev)
1324 return ipip_entry;
1325
1326 return NULL;
1327}
1328
1329static struct mlxsw_sp_ipip_entry *
1330mlxsw_sp_ipip_entry_find_by_ul_dev(const struct mlxsw_sp *mlxsw_sp,
1331 const struct net_device *ul_dev,
1332 struct mlxsw_sp_ipip_entry *start)
1333{
1334 struct mlxsw_sp_ipip_entry *ipip_entry;
1335
1336 ipip_entry = list_prepare_entry(start, &mlxsw_sp->router->ipip_list,
1337 ipip_list_node);
1338 list_for_each_entry_continue(ipip_entry, &mlxsw_sp->router->ipip_list,
1339 ipip_list_node) {
1340 struct net_device *ol_dev = ipip_entry->ol_dev;
1341 struct net_device *ipip_ul_dev;
1342
1343 rcu_read_lock();
1344 ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
1345 rcu_read_unlock();
1346
1347 if (ipip_ul_dev == ul_dev)
1348 return ipip_entry;
1349 }
1350
1351 return NULL;
1352}
1353
1354bool mlxsw_sp_netdev_is_ipip_ul(struct mlxsw_sp *mlxsw_sp,
1355 const struct net_device *dev)
1356{
1357 bool is_ipip_ul;
1358
1359 mutex_lock(&mlxsw_sp->router->lock);
1360 is_ipip_ul = mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp, dev, NULL);
1361 mutex_unlock(&mlxsw_sp->router->lock);
1362
1363 return is_ipip_ul;
1364}
1365
1366static bool mlxsw_sp_netdevice_ipip_can_offload(struct mlxsw_sp *mlxsw_sp,
1367 const struct net_device *ol_dev,
1368 enum mlxsw_sp_ipip_type ipipt)
1369{
1370 const struct mlxsw_sp_ipip_ops *ops
1371 = mlxsw_sp->router->ipip_ops_arr[ipipt];
1372
1373
1374
1375
1376 return ops->can_offload(mlxsw_sp, ol_dev, MLXSW_SP_L3_PROTO_IPV4) ||
1377 ops->can_offload(mlxsw_sp, ol_dev, MLXSW_SP_L3_PROTO_IPV6);
1378}
1379
1380static int mlxsw_sp_netdevice_ipip_ol_reg_event(struct mlxsw_sp *mlxsw_sp,
1381 struct net_device *ol_dev)
1382{
1383 enum mlxsw_sp_ipip_type ipipt = MLXSW_SP_IPIP_TYPE_MAX;
1384 struct mlxsw_sp_ipip_entry *ipip_entry;
1385 enum mlxsw_sp_l3proto ul_proto;
1386 union mlxsw_sp_l3addr saddr;
1387 u32 ul_tb_id;
1388
1389 mlxsw_sp_netdev_ipip_type(mlxsw_sp, ol_dev, &ipipt);
1390 if (mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp, ol_dev, ipipt)) {
1391 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
1392 ul_proto = mlxsw_sp->router->ipip_ops_arr[ipipt]->ul_proto;
1393 saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ol_dev);
1394 if (!mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
1395 saddr, ul_tb_id,
1396 NULL)) {
1397 ipip_entry = mlxsw_sp_ipip_entry_create(mlxsw_sp, ipipt,
1398 ol_dev);
1399 if (IS_ERR(ipip_entry))
1400 return PTR_ERR(ipip_entry);
1401 }
1402 }
1403
1404 return 0;
1405}
1406
1407static void mlxsw_sp_netdevice_ipip_ol_unreg_event(struct mlxsw_sp *mlxsw_sp,
1408 struct net_device *ol_dev)
1409{
1410 struct mlxsw_sp_ipip_entry *ipip_entry;
1411
1412 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1413 if (ipip_entry)
1414 mlxsw_sp_ipip_entry_destroy(mlxsw_sp, ipip_entry);
1415}
1416
1417static void
1418mlxsw_sp_ipip_entry_ol_up_event(struct mlxsw_sp *mlxsw_sp,
1419 struct mlxsw_sp_ipip_entry *ipip_entry)
1420{
1421 struct mlxsw_sp_fib_entry *decap_fib_entry;
1422
1423 decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
1424 if (decap_fib_entry)
1425 mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
1426 decap_fib_entry);
1427}
1428
1429static int
1430mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif, u16 ul_vr_id,
1431 u16 ul_rif_id, bool enable)
1432{
1433 struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
1434 struct mlxsw_sp_rif *rif = &lb_rif->common;
1435 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
1436 char ritr_pl[MLXSW_REG_RITR_LEN];
1437 u32 saddr4;
1438
1439 switch (lb_cf.ul_protocol) {
1440 case MLXSW_SP_L3_PROTO_IPV4:
1441 saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
1442 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
1443 rif->rif_index, rif->vr_id, rif->dev->mtu);
1444 mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
1445 MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
1446 ul_vr_id, ul_rif_id, saddr4, lb_cf.okey);
1447 break;
1448
1449 case MLXSW_SP_L3_PROTO_IPV6:
1450 return -EAFNOSUPPORT;
1451 }
1452
1453 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
1454}
1455
1456static int mlxsw_sp_netdevice_ipip_ol_update_mtu(struct mlxsw_sp *mlxsw_sp,
1457 struct net_device *ol_dev)
1458{
1459 struct mlxsw_sp_ipip_entry *ipip_entry;
1460 struct mlxsw_sp_rif_ipip_lb *lb_rif;
1461 int err = 0;
1462
1463 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1464 if (ipip_entry) {
1465 lb_rif = ipip_entry->ol_lb;
1466 err = mlxsw_sp_rif_ipip_lb_op(lb_rif, lb_rif->ul_vr_id,
1467 lb_rif->ul_rif_id, true);
1468 if (err)
1469 goto out;
1470 lb_rif->common.mtu = ol_dev->mtu;
1471 }
1472
1473out:
1474 return err;
1475}
1476
1477static void mlxsw_sp_netdevice_ipip_ol_up_event(struct mlxsw_sp *mlxsw_sp,
1478 struct net_device *ol_dev)
1479{
1480 struct mlxsw_sp_ipip_entry *ipip_entry;
1481
1482 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1483 if (ipip_entry)
1484 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp, ipip_entry);
1485}
1486
1487static void
1488mlxsw_sp_ipip_entry_ol_down_event(struct mlxsw_sp *mlxsw_sp,
1489 struct mlxsw_sp_ipip_entry *ipip_entry)
1490{
1491 if (ipip_entry->decap_fib_entry)
1492 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1493}
1494
1495static void mlxsw_sp_netdevice_ipip_ol_down_event(struct mlxsw_sp *mlxsw_sp,
1496 struct net_device *ol_dev)
1497{
1498 struct mlxsw_sp_ipip_entry *ipip_entry;
1499
1500 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1501 if (ipip_entry)
1502 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
1503}
1504
1505static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
1506 struct mlxsw_sp_rif *old_rif,
1507 struct mlxsw_sp_rif *new_rif);
1508static int
1509mlxsw_sp_ipip_entry_ol_lb_update(struct mlxsw_sp *mlxsw_sp,
1510 struct mlxsw_sp_ipip_entry *ipip_entry,
1511 bool keep_encap,
1512 struct netlink_ext_ack *extack)
1513{
1514 struct mlxsw_sp_rif_ipip_lb *old_lb_rif = ipip_entry->ol_lb;
1515 struct mlxsw_sp_rif_ipip_lb *new_lb_rif;
1516
1517 new_lb_rif = mlxsw_sp_ipip_ol_ipip_lb_create(mlxsw_sp,
1518 ipip_entry->ipipt,
1519 ipip_entry->ol_dev,
1520 extack);
1521 if (IS_ERR(new_lb_rif))
1522 return PTR_ERR(new_lb_rif);
1523 ipip_entry->ol_lb = new_lb_rif;
1524
1525 if (keep_encap)
1526 mlxsw_sp_nexthop_rif_migrate(mlxsw_sp, &old_lb_rif->common,
1527 &new_lb_rif->common);
1528
1529 mlxsw_sp_rif_destroy(&old_lb_rif->common);
1530
1531 return 0;
1532}
1533
1534static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
1535 struct mlxsw_sp_rif *rif);
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550int __mlxsw_sp_ipip_entry_update_tunnel(struct mlxsw_sp *mlxsw_sp,
1551 struct mlxsw_sp_ipip_entry *ipip_entry,
1552 bool recreate_loopback,
1553 bool keep_encap,
1554 bool update_nexthops,
1555 struct netlink_ext_ack *extack)
1556{
1557 int err;
1558
1559
1560
1561
1562
1563
1564
1565 if (ipip_entry->decap_fib_entry)
1566 mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1567
1568 if (recreate_loopback) {
1569 err = mlxsw_sp_ipip_entry_ol_lb_update(mlxsw_sp, ipip_entry,
1570 keep_encap, extack);
1571 if (err)
1572 return err;
1573 } else if (update_nexthops) {
1574 mlxsw_sp_nexthop_rif_update(mlxsw_sp,
1575 &ipip_entry->ol_lb->common);
1576 }
1577
1578 if (ipip_entry->ol_dev->flags & IFF_UP)
1579 mlxsw_sp_ipip_entry_ol_up_event(mlxsw_sp, ipip_entry);
1580
1581 return 0;
1582}
1583
1584static int mlxsw_sp_netdevice_ipip_ol_vrf_event(struct mlxsw_sp *mlxsw_sp,
1585 struct net_device *ol_dev,
1586 struct netlink_ext_ack *extack)
1587{
1588 struct mlxsw_sp_ipip_entry *ipip_entry =
1589 mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1590
1591 if (!ipip_entry)
1592 return 0;
1593
1594 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1595 true, false, false, extack);
1596}
1597
1598static int
1599mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp *mlxsw_sp,
1600 struct mlxsw_sp_ipip_entry *ipip_entry,
1601 struct net_device *ul_dev,
1602 bool *demote_this,
1603 struct netlink_ext_ack *extack)
1604{
1605 u32 ul_tb_id = l3mdev_fib_table(ul_dev) ? : RT_TABLE_MAIN;
1606 enum mlxsw_sp_l3proto ul_proto;
1607 union mlxsw_sp_l3addr saddr;
1608
1609
1610
1611
1612 ul_proto = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]->ul_proto;
1613 saddr = mlxsw_sp_ipip_netdev_saddr(ul_proto, ipip_entry->ol_dev);
1614 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, ul_proto,
1615 saddr, ul_tb_id,
1616 ipip_entry)) {
1617 *demote_this = true;
1618 return 0;
1619 }
1620
1621 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1622 true, true, false, extack);
1623}
1624
1625static int
1626mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp *mlxsw_sp,
1627 struct mlxsw_sp_ipip_entry *ipip_entry,
1628 struct net_device *ul_dev)
1629{
1630 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1631 false, false, true, NULL);
1632}
1633
1634static int
1635mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp *mlxsw_sp,
1636 struct mlxsw_sp_ipip_entry *ipip_entry,
1637 struct net_device *ul_dev)
1638{
1639
1640
1641
1642
1643 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1644 false, false, true, NULL);
1645}
1646
1647static int
1648mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp *mlxsw_sp,
1649 struct net_device *ol_dev,
1650 struct netlink_ext_ack *extack)
1651{
1652 const struct mlxsw_sp_ipip_ops *ipip_ops;
1653 struct mlxsw_sp_ipip_entry *ipip_entry;
1654 int err;
1655
1656 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1657 if (!ipip_entry)
1658
1659
1660
1661
1662 return 0;
1663
1664
1665 if (!mlxsw_sp_netdevice_ipip_can_offload(mlxsw_sp, ol_dev,
1666 ipip_entry->ipipt)) {
1667 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1668 return 0;
1669 }
1670
1671 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
1672 err = ipip_ops->ol_netdev_change(mlxsw_sp, ipip_entry, extack);
1673 return err;
1674}
1675
1676void mlxsw_sp_ipip_entry_demote_tunnel(struct mlxsw_sp *mlxsw_sp,
1677 struct mlxsw_sp_ipip_entry *ipip_entry)
1678{
1679 struct net_device *ol_dev = ipip_entry->ol_dev;
1680
1681 if (ol_dev->flags & IFF_UP)
1682 mlxsw_sp_ipip_entry_ol_down_event(mlxsw_sp, ipip_entry);
1683 mlxsw_sp_ipip_entry_destroy(mlxsw_sp, ipip_entry);
1684}
1685
1686
1687
1688
1689
1690
1691
1692bool
1693mlxsw_sp_ipip_demote_tunnel_by_saddr(struct mlxsw_sp *mlxsw_sp,
1694 enum mlxsw_sp_l3proto ul_proto,
1695 union mlxsw_sp_l3addr saddr,
1696 u32 ul_tb_id,
1697 const struct mlxsw_sp_ipip_entry *except)
1698{
1699 struct mlxsw_sp_ipip_entry *ipip_entry, *tmp;
1700
1701 list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
1702 ipip_list_node) {
1703 if (ipip_entry != except &&
1704 mlxsw_sp_ipip_entry_saddr_matches(mlxsw_sp, ul_proto, saddr,
1705 ul_tb_id, ipip_entry)) {
1706 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1707 return true;
1708 }
1709 }
1710
1711 return false;
1712}
1713
1714static void mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(struct mlxsw_sp *mlxsw_sp,
1715 struct net_device *ul_dev)
1716{
1717 struct mlxsw_sp_ipip_entry *ipip_entry, *tmp;
1718
1719 list_for_each_entry_safe(ipip_entry, tmp, &mlxsw_sp->router->ipip_list,
1720 ipip_list_node) {
1721 struct net_device *ol_dev = ipip_entry->ol_dev;
1722 struct net_device *ipip_ul_dev;
1723
1724 rcu_read_lock();
1725 ipip_ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
1726 rcu_read_unlock();
1727 if (ipip_ul_dev == ul_dev)
1728 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1729 }
1730}
1731
1732int mlxsw_sp_netdevice_ipip_ol_event(struct mlxsw_sp *mlxsw_sp,
1733 struct net_device *ol_dev,
1734 unsigned long event,
1735 struct netdev_notifier_info *info)
1736{
1737 struct netdev_notifier_changeupper_info *chup;
1738 struct netlink_ext_ack *extack;
1739 int err = 0;
1740
1741 mutex_lock(&mlxsw_sp->router->lock);
1742 switch (event) {
1743 case NETDEV_REGISTER:
1744 err = mlxsw_sp_netdevice_ipip_ol_reg_event(mlxsw_sp, ol_dev);
1745 break;
1746 case NETDEV_UNREGISTER:
1747 mlxsw_sp_netdevice_ipip_ol_unreg_event(mlxsw_sp, ol_dev);
1748 break;
1749 case NETDEV_UP:
1750 mlxsw_sp_netdevice_ipip_ol_up_event(mlxsw_sp, ol_dev);
1751 break;
1752 case NETDEV_DOWN:
1753 mlxsw_sp_netdevice_ipip_ol_down_event(mlxsw_sp, ol_dev);
1754 break;
1755 case NETDEV_CHANGEUPPER:
1756 chup = container_of(info, typeof(*chup), info);
1757 extack = info->extack;
1758 if (netif_is_l3_master(chup->upper_dev))
1759 err = mlxsw_sp_netdevice_ipip_ol_vrf_event(mlxsw_sp,
1760 ol_dev,
1761 extack);
1762 break;
1763 case NETDEV_CHANGE:
1764 extack = info->extack;
1765 err = mlxsw_sp_netdevice_ipip_ol_change_event(mlxsw_sp,
1766 ol_dev, extack);
1767 break;
1768 case NETDEV_CHANGEMTU:
1769 err = mlxsw_sp_netdevice_ipip_ol_update_mtu(mlxsw_sp, ol_dev);
1770 break;
1771 }
1772 mutex_unlock(&mlxsw_sp->router->lock);
1773 return err;
1774}
1775
1776static int
1777__mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
1778 struct mlxsw_sp_ipip_entry *ipip_entry,
1779 struct net_device *ul_dev,
1780 bool *demote_this,
1781 unsigned long event,
1782 struct netdev_notifier_info *info)
1783{
1784 struct netdev_notifier_changeupper_info *chup;
1785 struct netlink_ext_ack *extack;
1786
1787 switch (event) {
1788 case NETDEV_CHANGEUPPER:
1789 chup = container_of(info, typeof(*chup), info);
1790 extack = info->extack;
1791 if (netif_is_l3_master(chup->upper_dev))
1792 return mlxsw_sp_netdevice_ipip_ul_vrf_event(mlxsw_sp,
1793 ipip_entry,
1794 ul_dev,
1795 demote_this,
1796 extack);
1797 break;
1798
1799 case NETDEV_UP:
1800 return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp, ipip_entry,
1801 ul_dev);
1802 case NETDEV_DOWN:
1803 return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp,
1804 ipip_entry,
1805 ul_dev);
1806 }
1807 return 0;
1808}
1809
1810int
1811mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
1812 struct net_device *ul_dev,
1813 unsigned long event,
1814 struct netdev_notifier_info *info)
1815{
1816 struct mlxsw_sp_ipip_entry *ipip_entry = NULL;
1817 int err = 0;
1818
1819 mutex_lock(&mlxsw_sp->router->lock);
1820 while ((ipip_entry = mlxsw_sp_ipip_entry_find_by_ul_dev(mlxsw_sp,
1821 ul_dev,
1822 ipip_entry))) {
1823 struct mlxsw_sp_ipip_entry *prev;
1824 bool demote_this = false;
1825
1826 err = __mlxsw_sp_netdevice_ipip_ul_event(mlxsw_sp, ipip_entry,
1827 ul_dev, &demote_this,
1828 event, info);
1829 if (err) {
1830 mlxsw_sp_ipip_demote_tunnel_by_ul_netdev(mlxsw_sp,
1831 ul_dev);
1832 break;
1833 }
1834
1835 if (demote_this) {
1836 if (list_is_first(&ipip_entry->ipip_list_node,
1837 &mlxsw_sp->router->ipip_list))
1838 prev = NULL;
1839 else
1840
1841
1842
1843 prev = list_prev_entry(ipip_entry,
1844 ipip_list_node);
1845 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
1846 ipip_entry = prev;
1847 }
1848 }
1849 mutex_unlock(&mlxsw_sp->router->lock);
1850
1851 return err;
1852}
1853
1854int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
1855 enum mlxsw_sp_l3proto ul_proto,
1856 const union mlxsw_sp_l3addr *ul_sip,
1857 u32 tunnel_index)
1858{
1859 enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1860 struct mlxsw_sp_router *router = mlxsw_sp->router;
1861 struct mlxsw_sp_fib_entry *fib_entry;
1862 int err = 0;
1863
1864 mutex_lock(&mlxsw_sp->router->lock);
1865
1866 if (WARN_ON_ONCE(router->nve_decap_config.valid)) {
1867 err = -EINVAL;
1868 goto out;
1869 }
1870
1871 router->nve_decap_config.ul_tb_id = ul_tb_id;
1872 router->nve_decap_config.tunnel_index = tunnel_index;
1873 router->nve_decap_config.ul_proto = ul_proto;
1874 router->nve_decap_config.ul_sip = *ul_sip;
1875 router->nve_decap_config.valid = true;
1876
1877
1878
1879
1880 fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
1881 ul_proto, ul_sip,
1882 type);
1883 if (!fib_entry)
1884 goto out;
1885
1886 fib_entry->decap.tunnel_index = tunnel_index;
1887 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
1888
1889 err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
1890 if (err)
1891 goto err_fib_entry_update;
1892
1893 goto out;
1894
1895err_fib_entry_update:
1896 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1897 mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
1898out:
1899 mutex_unlock(&mlxsw_sp->router->lock);
1900 return err;
1901}
1902
1903void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
1904 enum mlxsw_sp_l3proto ul_proto,
1905 const union mlxsw_sp_l3addr *ul_sip)
1906{
1907 enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
1908 struct mlxsw_sp_router *router = mlxsw_sp->router;
1909 struct mlxsw_sp_fib_entry *fib_entry;
1910
1911 mutex_lock(&mlxsw_sp->router->lock);
1912
1913 if (WARN_ON_ONCE(!router->nve_decap_config.valid))
1914 goto out;
1915
1916 router->nve_decap_config.valid = false;
1917
1918 fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
1919 ul_proto, ul_sip,
1920 type);
1921 if (!fib_entry)
1922 goto out;
1923
1924 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
1925 mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
1926out:
1927 mutex_unlock(&mlxsw_sp->router->lock);
1928}
1929
1930static bool mlxsw_sp_router_nve_is_decap(struct mlxsw_sp *mlxsw_sp,
1931 u32 ul_tb_id,
1932 enum mlxsw_sp_l3proto ul_proto,
1933 const union mlxsw_sp_l3addr *ul_sip)
1934{
1935 struct mlxsw_sp_router *router = mlxsw_sp->router;
1936
1937 return router->nve_decap_config.valid &&
1938 router->nve_decap_config.ul_tb_id == ul_tb_id &&
1939 router->nve_decap_config.ul_proto == ul_proto &&
1940 !memcmp(&router->nve_decap_config.ul_sip, ul_sip,
1941 sizeof(*ul_sip));
1942}
1943
1944struct mlxsw_sp_neigh_key {
1945 struct neighbour *n;
1946};
1947
1948struct mlxsw_sp_neigh_entry {
1949 struct list_head rif_list_node;
1950 struct rhash_head ht_node;
1951 struct mlxsw_sp_neigh_key key;
1952 u16 rif;
1953 bool connected;
1954 unsigned char ha[ETH_ALEN];
1955 struct list_head nexthop_list;
1956
1957
1958 struct list_head nexthop_neighs_list_node;
1959 unsigned int counter_index;
1960 bool counter_valid;
1961};
1962
1963static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
1964 .key_offset = offsetof(struct mlxsw_sp_neigh_entry, key),
1965 .head_offset = offsetof(struct mlxsw_sp_neigh_entry, ht_node),
1966 .key_len = sizeof(struct mlxsw_sp_neigh_key),
1967};
1968
1969struct mlxsw_sp_neigh_entry *
1970mlxsw_sp_rif_neigh_next(struct mlxsw_sp_rif *rif,
1971 struct mlxsw_sp_neigh_entry *neigh_entry)
1972{
1973 if (!neigh_entry) {
1974 if (list_empty(&rif->neigh_list))
1975 return NULL;
1976 else
1977 return list_first_entry(&rif->neigh_list,
1978 typeof(*neigh_entry),
1979 rif_list_node);
1980 }
1981 if (list_is_last(&neigh_entry->rif_list_node, &rif->neigh_list))
1982 return NULL;
1983 return list_next_entry(neigh_entry, rif_list_node);
1984}
1985
1986int mlxsw_sp_neigh_entry_type(struct mlxsw_sp_neigh_entry *neigh_entry)
1987{
1988 return neigh_entry->key.n->tbl->family;
1989}
1990
1991unsigned char *
1992mlxsw_sp_neigh_entry_ha(struct mlxsw_sp_neigh_entry *neigh_entry)
1993{
1994 return neigh_entry->ha;
1995}
1996
1997u32 mlxsw_sp_neigh4_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
1998{
1999 struct neighbour *n;
2000
2001 n = neigh_entry->key.n;
2002 return ntohl(*((__be32 *) n->primary_key));
2003}
2004
2005struct in6_addr *
2006mlxsw_sp_neigh6_entry_dip(struct mlxsw_sp_neigh_entry *neigh_entry)
2007{
2008 struct neighbour *n;
2009
2010 n = neigh_entry->key.n;
2011 return (struct in6_addr *) &n->primary_key;
2012}
2013
2014int mlxsw_sp_neigh_counter_get(struct mlxsw_sp *mlxsw_sp,
2015 struct mlxsw_sp_neigh_entry *neigh_entry,
2016 u64 *p_counter)
2017{
2018 if (!neigh_entry->counter_valid)
2019 return -EINVAL;
2020
2021 return mlxsw_sp_flow_counter_get(mlxsw_sp, neigh_entry->counter_index,
2022 p_counter, NULL);
2023}
2024
2025static struct mlxsw_sp_neigh_entry *
2026mlxsw_sp_neigh_entry_alloc(struct mlxsw_sp *mlxsw_sp, struct neighbour *n,
2027 u16 rif)
2028{
2029 struct mlxsw_sp_neigh_entry *neigh_entry;
2030
2031 neigh_entry = kzalloc(sizeof(*neigh_entry), GFP_KERNEL);
2032 if (!neigh_entry)
2033 return NULL;
2034
2035 neigh_entry->key.n = n;
2036 neigh_entry->rif = rif;
2037 INIT_LIST_HEAD(&neigh_entry->nexthop_list);
2038
2039 return neigh_entry;
2040}
2041
2042static void mlxsw_sp_neigh_entry_free(struct mlxsw_sp_neigh_entry *neigh_entry)
2043{
2044 kfree(neigh_entry);
2045}
2046
2047static int
2048mlxsw_sp_neigh_entry_insert(struct mlxsw_sp *mlxsw_sp,
2049 struct mlxsw_sp_neigh_entry *neigh_entry)
2050{
2051 return rhashtable_insert_fast(&mlxsw_sp->router->neigh_ht,
2052 &neigh_entry->ht_node,
2053 mlxsw_sp_neigh_ht_params);
2054}
2055
2056static void
2057mlxsw_sp_neigh_entry_remove(struct mlxsw_sp *mlxsw_sp,
2058 struct mlxsw_sp_neigh_entry *neigh_entry)
2059{
2060 rhashtable_remove_fast(&mlxsw_sp->router->neigh_ht,
2061 &neigh_entry->ht_node,
2062 mlxsw_sp_neigh_ht_params);
2063}
2064
2065static bool
2066mlxsw_sp_neigh_counter_should_alloc(struct mlxsw_sp *mlxsw_sp,
2067 struct mlxsw_sp_neigh_entry *neigh_entry)
2068{
2069 struct devlink *devlink;
2070 const char *table_name;
2071
2072 switch (mlxsw_sp_neigh_entry_type(neigh_entry)) {
2073 case AF_INET:
2074 table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST4;
2075 break;
2076 case AF_INET6:
2077 table_name = MLXSW_SP_DPIPE_TABLE_NAME_HOST6;
2078 break;
2079 default:
2080 WARN_ON(1);
2081 return false;
2082 }
2083
2084 devlink = priv_to_devlink(mlxsw_sp->core);
2085 return devlink_dpipe_table_counter_enabled(devlink, table_name);
2086}
2087
2088static void
2089mlxsw_sp_neigh_counter_alloc(struct mlxsw_sp *mlxsw_sp,
2090 struct mlxsw_sp_neigh_entry *neigh_entry)
2091{
2092 if (!mlxsw_sp_neigh_counter_should_alloc(mlxsw_sp, neigh_entry))
2093 return;
2094
2095 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &neigh_entry->counter_index))
2096 return;
2097
2098 neigh_entry->counter_valid = true;
2099}
2100
2101static void
2102mlxsw_sp_neigh_counter_free(struct mlxsw_sp *mlxsw_sp,
2103 struct mlxsw_sp_neigh_entry *neigh_entry)
2104{
2105 if (!neigh_entry->counter_valid)
2106 return;
2107 mlxsw_sp_flow_counter_free(mlxsw_sp,
2108 neigh_entry->counter_index);
2109 neigh_entry->counter_valid = false;
2110}
2111
2112static struct mlxsw_sp_neigh_entry *
2113mlxsw_sp_neigh_entry_create(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
2114{
2115 struct mlxsw_sp_neigh_entry *neigh_entry;
2116 struct mlxsw_sp_rif *rif;
2117 int err;
2118
2119 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, n->dev);
2120 if (!rif)
2121 return ERR_PTR(-EINVAL);
2122
2123 neigh_entry = mlxsw_sp_neigh_entry_alloc(mlxsw_sp, n, rif->rif_index);
2124 if (!neigh_entry)
2125 return ERR_PTR(-ENOMEM);
2126
2127 err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
2128 if (err)
2129 goto err_neigh_entry_insert;
2130
2131 mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
2132 list_add(&neigh_entry->rif_list_node, &rif->neigh_list);
2133
2134 return neigh_entry;
2135
2136err_neigh_entry_insert:
2137 mlxsw_sp_neigh_entry_free(neigh_entry);
2138 return ERR_PTR(err);
2139}
2140
2141static void
2142mlxsw_sp_neigh_entry_destroy(struct mlxsw_sp *mlxsw_sp,
2143 struct mlxsw_sp_neigh_entry *neigh_entry)
2144{
2145 list_del(&neigh_entry->rif_list_node);
2146 mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
2147 mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
2148 mlxsw_sp_neigh_entry_free(neigh_entry);
2149}
2150
2151static struct mlxsw_sp_neigh_entry *
2152mlxsw_sp_neigh_entry_lookup(struct mlxsw_sp *mlxsw_sp, struct neighbour *n)
2153{
2154 struct mlxsw_sp_neigh_key key;
2155
2156 key.n = n;
2157 return rhashtable_lookup_fast(&mlxsw_sp->router->neigh_ht,
2158 &key, mlxsw_sp_neigh_ht_params);
2159}
2160
2161static void
2162mlxsw_sp_router_neighs_update_interval_init(struct mlxsw_sp *mlxsw_sp)
2163{
2164 unsigned long interval;
2165
2166#if IS_ENABLED(CONFIG_IPV6)
2167 interval = min_t(unsigned long,
2168 NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME),
2169 NEIGH_VAR(&nd_tbl.parms, DELAY_PROBE_TIME));
2170#else
2171 interval = NEIGH_VAR(&arp_tbl.parms, DELAY_PROBE_TIME);
2172#endif
2173 mlxsw_sp->router->neighs_update.interval = jiffies_to_msecs(interval);
2174}
2175
2176static void mlxsw_sp_router_neigh_ent_ipv4_process(struct mlxsw_sp *mlxsw_sp,
2177 char *rauhtd_pl,
2178 int ent_index)
2179{
2180 struct net_device *dev;
2181 struct neighbour *n;
2182 __be32 dipn;
2183 u32 dip;
2184 u16 rif;
2185
2186 mlxsw_reg_rauhtd_ent_ipv4_unpack(rauhtd_pl, ent_index, &rif, &dip);
2187
2188 if (!mlxsw_sp->router->rifs[rif]) {
2189 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
2190 return;
2191 }
2192
2193 dipn = htonl(dip);
2194 dev = mlxsw_sp->router->rifs[rif]->dev;
2195 n = neigh_lookup(&arp_tbl, &dipn, dev);
2196 if (!n)
2197 return;
2198
2199 netdev_dbg(dev, "Updating neighbour with IP=%pI4h\n", &dip);
2200 neigh_event_send(n, NULL);
2201 neigh_release(n);
2202}
2203
2204#if IS_ENABLED(CONFIG_IPV6)
2205static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
2206 char *rauhtd_pl,
2207 int rec_index)
2208{
2209 struct net_device *dev;
2210 struct neighbour *n;
2211 struct in6_addr dip;
2212 u16 rif;
2213
2214 mlxsw_reg_rauhtd_ent_ipv6_unpack(rauhtd_pl, rec_index, &rif,
2215 (char *) &dip);
2216
2217 if (!mlxsw_sp->router->rifs[rif]) {
2218 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect RIF in neighbour entry\n");
2219 return;
2220 }
2221
2222 dev = mlxsw_sp->router->rifs[rif]->dev;
2223 n = neigh_lookup(&nd_tbl, &dip, dev);
2224 if (!n)
2225 return;
2226
2227 netdev_dbg(dev, "Updating neighbour with IP=%pI6c\n", &dip);
2228 neigh_event_send(n, NULL);
2229 neigh_release(n);
2230}
2231#else
2232static void mlxsw_sp_router_neigh_ent_ipv6_process(struct mlxsw_sp *mlxsw_sp,
2233 char *rauhtd_pl,
2234 int rec_index)
2235{
2236}
2237#endif
2238
2239static void mlxsw_sp_router_neigh_rec_ipv4_process(struct mlxsw_sp *mlxsw_sp,
2240 char *rauhtd_pl,
2241 int rec_index)
2242{
2243 u8 num_entries;
2244 int i;
2245
2246 num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
2247 rec_index);
2248
2249 num_entries++;
2250
2251
2252 for (i = 0; i < num_entries; i++) {
2253 int ent_index;
2254
2255 ent_index = rec_index * MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC + i;
2256 mlxsw_sp_router_neigh_ent_ipv4_process(mlxsw_sp, rauhtd_pl,
2257 ent_index);
2258 }
2259
2260}
2261
2262static void mlxsw_sp_router_neigh_rec_ipv6_process(struct mlxsw_sp *mlxsw_sp,
2263 char *rauhtd_pl,
2264 int rec_index)
2265{
2266
2267 mlxsw_sp_router_neigh_ent_ipv6_process(mlxsw_sp, rauhtd_pl,
2268 rec_index);
2269}
2270
2271static void mlxsw_sp_router_neigh_rec_process(struct mlxsw_sp *mlxsw_sp,
2272 char *rauhtd_pl, int rec_index)
2273{
2274 switch (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, rec_index)) {
2275 case MLXSW_REG_RAUHTD_TYPE_IPV4:
2276 mlxsw_sp_router_neigh_rec_ipv4_process(mlxsw_sp, rauhtd_pl,
2277 rec_index);
2278 break;
2279 case MLXSW_REG_RAUHTD_TYPE_IPV6:
2280 mlxsw_sp_router_neigh_rec_ipv6_process(mlxsw_sp, rauhtd_pl,
2281 rec_index);
2282 break;
2283 }
2284}
2285
2286static bool mlxsw_sp_router_rauhtd_is_full(char *rauhtd_pl)
2287{
2288 u8 num_rec, last_rec_index, num_entries;
2289
2290 num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
2291 last_rec_index = num_rec - 1;
2292
2293 if (num_rec < MLXSW_REG_RAUHTD_REC_MAX_NUM)
2294 return false;
2295 if (mlxsw_reg_rauhtd_rec_type_get(rauhtd_pl, last_rec_index) ==
2296 MLXSW_REG_RAUHTD_TYPE_IPV6)
2297 return true;
2298
2299 num_entries = mlxsw_reg_rauhtd_ipv4_rec_num_entries_get(rauhtd_pl,
2300 last_rec_index);
2301 if (++num_entries == MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC)
2302 return true;
2303 return false;
2304}
2305
2306static int
2307__mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp,
2308 char *rauhtd_pl,
2309 enum mlxsw_reg_rauhtd_type type)
2310{
2311 int i, num_rec;
2312 int err;
2313
2314
2315 mutex_lock(&mlxsw_sp->router->lock);
2316 do {
2317 mlxsw_reg_rauhtd_pack(rauhtd_pl, type);
2318 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(rauhtd),
2319 rauhtd_pl);
2320 if (err) {
2321 dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to dump neighbour table\n");
2322 break;
2323 }
2324 num_rec = mlxsw_reg_rauhtd_num_rec_get(rauhtd_pl);
2325 for (i = 0; i < num_rec; i++)
2326 mlxsw_sp_router_neigh_rec_process(mlxsw_sp, rauhtd_pl,
2327 i);
2328 } while (mlxsw_sp_router_rauhtd_is_full(rauhtd_pl));
2329 mutex_unlock(&mlxsw_sp->router->lock);
2330
2331 return err;
2332}
2333
2334static int mlxsw_sp_router_neighs_update_rauhtd(struct mlxsw_sp *mlxsw_sp)
2335{
2336 enum mlxsw_reg_rauhtd_type type;
2337 char *rauhtd_pl;
2338 int err;
2339
2340 rauhtd_pl = kmalloc(MLXSW_REG_RAUHTD_LEN, GFP_KERNEL);
2341 if (!rauhtd_pl)
2342 return -ENOMEM;
2343
2344 type = MLXSW_REG_RAUHTD_TYPE_IPV4;
2345 err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
2346 if (err)
2347 goto out;
2348
2349 type = MLXSW_REG_RAUHTD_TYPE_IPV6;
2350 err = __mlxsw_sp_router_neighs_update_rauhtd(mlxsw_sp, rauhtd_pl, type);
2351out:
2352 kfree(rauhtd_pl);
2353 return err;
2354}
2355
2356static void mlxsw_sp_router_neighs_update_nh(struct mlxsw_sp *mlxsw_sp)
2357{
2358 struct mlxsw_sp_neigh_entry *neigh_entry;
2359
2360 mutex_lock(&mlxsw_sp->router->lock);
2361 list_for_each_entry(neigh_entry, &mlxsw_sp->router->nexthop_neighs_list,
2362 nexthop_neighs_list_node)
2363
2364
2365
2366 neigh_event_send(neigh_entry->key.n, NULL);
2367 mutex_unlock(&mlxsw_sp->router->lock);
2368}
2369
2370static void
2371mlxsw_sp_router_neighs_update_work_schedule(struct mlxsw_sp *mlxsw_sp)
2372{
2373 unsigned long interval = mlxsw_sp->router->neighs_update.interval;
2374
2375 mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw,
2376 msecs_to_jiffies(interval));
2377}
2378
2379static void mlxsw_sp_router_neighs_update_work(struct work_struct *work)
2380{
2381 struct mlxsw_sp_router *router;
2382 int err;
2383
2384 router = container_of(work, struct mlxsw_sp_router,
2385 neighs_update.dw.work);
2386 err = mlxsw_sp_router_neighs_update_rauhtd(router->mlxsw_sp);
2387 if (err)
2388 dev_err(router->mlxsw_sp->bus_info->dev, "Could not update kernel for neigh activity");
2389
2390 mlxsw_sp_router_neighs_update_nh(router->mlxsw_sp);
2391
2392 mlxsw_sp_router_neighs_update_work_schedule(router->mlxsw_sp);
2393}
2394
2395static void mlxsw_sp_router_probe_unresolved_nexthops(struct work_struct *work)
2396{
2397 struct mlxsw_sp_neigh_entry *neigh_entry;
2398 struct mlxsw_sp_router *router;
2399
2400 router = container_of(work, struct mlxsw_sp_router,
2401 nexthop_probe_dw.work);
2402
2403
2404
2405
2406
2407
2408 mutex_lock(&router->lock);
2409 list_for_each_entry(neigh_entry, &router->nexthop_neighs_list,
2410 nexthop_neighs_list_node)
2411 if (!neigh_entry->connected)
2412 neigh_event_send(neigh_entry->key.n, NULL);
2413 mutex_unlock(&router->lock);
2414
2415 mlxsw_core_schedule_dw(&router->nexthop_probe_dw,
2416 MLXSW_SP_UNRESOLVED_NH_PROBE_INTERVAL);
2417}
2418
2419static void
2420mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
2421 struct mlxsw_sp_neigh_entry *neigh_entry,
2422 bool removing, bool dead);
2423
2424static enum mlxsw_reg_rauht_op mlxsw_sp_rauht_op(bool adding)
2425{
2426 return adding ? MLXSW_REG_RAUHT_OP_WRITE_ADD :
2427 MLXSW_REG_RAUHT_OP_WRITE_DELETE;
2428}
2429
2430static int
2431mlxsw_sp_router_neigh_entry_op4(struct mlxsw_sp *mlxsw_sp,
2432 struct mlxsw_sp_neigh_entry *neigh_entry,
2433 enum mlxsw_reg_rauht_op op)
2434{
2435 struct neighbour *n = neigh_entry->key.n;
2436 u32 dip = ntohl(*((__be32 *) n->primary_key));
2437 char rauht_pl[MLXSW_REG_RAUHT_LEN];
2438
2439 mlxsw_reg_rauht_pack4(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
2440 dip);
2441 if (neigh_entry->counter_valid)
2442 mlxsw_reg_rauht_pack_counter(rauht_pl,
2443 neigh_entry->counter_index);
2444 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
2445}
2446
2447static int
2448mlxsw_sp_router_neigh_entry_op6(struct mlxsw_sp *mlxsw_sp,
2449 struct mlxsw_sp_neigh_entry *neigh_entry,
2450 enum mlxsw_reg_rauht_op op)
2451{
2452 struct neighbour *n = neigh_entry->key.n;
2453 char rauht_pl[MLXSW_REG_RAUHT_LEN];
2454 const char *dip = n->primary_key;
2455
2456 mlxsw_reg_rauht_pack6(rauht_pl, op, neigh_entry->rif, neigh_entry->ha,
2457 dip);
2458 if (neigh_entry->counter_valid)
2459 mlxsw_reg_rauht_pack_counter(rauht_pl,
2460 neigh_entry->counter_index);
2461 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rauht), rauht_pl);
2462}
2463
2464bool mlxsw_sp_neigh_ipv6_ignore(struct mlxsw_sp_neigh_entry *neigh_entry)
2465{
2466 struct neighbour *n = neigh_entry->key.n;
2467
2468
2469
2470
2471
2472 if (ipv6_addr_type((struct in6_addr *) &n->primary_key) &
2473 IPV6_ADDR_LINKLOCAL)
2474 return true;
2475 return false;
2476}
2477
2478static void
2479mlxsw_sp_neigh_entry_update(struct mlxsw_sp *mlxsw_sp,
2480 struct mlxsw_sp_neigh_entry *neigh_entry,
2481 bool adding)
2482{
2483 enum mlxsw_reg_rauht_op op = mlxsw_sp_rauht_op(adding);
2484 int err;
2485
2486 if (!adding && !neigh_entry->connected)
2487 return;
2488 neigh_entry->connected = adding;
2489 if (neigh_entry->key.n->tbl->family == AF_INET) {
2490 err = mlxsw_sp_router_neigh_entry_op4(mlxsw_sp, neigh_entry,
2491 op);
2492 if (err)
2493 return;
2494 } else if (neigh_entry->key.n->tbl->family == AF_INET6) {
2495 if (mlxsw_sp_neigh_ipv6_ignore(neigh_entry))
2496 return;
2497 err = mlxsw_sp_router_neigh_entry_op6(mlxsw_sp, neigh_entry,
2498 op);
2499 if (err)
2500 return;
2501 } else {
2502 WARN_ON_ONCE(1);
2503 return;
2504 }
2505
2506 if (adding)
2507 neigh_entry->key.n->flags |= NTF_OFFLOADED;
2508 else
2509 neigh_entry->key.n->flags &= ~NTF_OFFLOADED;
2510}
2511
2512void
2513mlxsw_sp_neigh_entry_counter_update(struct mlxsw_sp *mlxsw_sp,
2514 struct mlxsw_sp_neigh_entry *neigh_entry,
2515 bool adding)
2516{
2517 if (adding)
2518 mlxsw_sp_neigh_counter_alloc(mlxsw_sp, neigh_entry);
2519 else
2520 mlxsw_sp_neigh_counter_free(mlxsw_sp, neigh_entry);
2521 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, true);
2522}
2523
2524struct mlxsw_sp_netevent_work {
2525 struct work_struct work;
2526 struct mlxsw_sp *mlxsw_sp;
2527 struct neighbour *n;
2528};
2529
2530static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
2531{
2532 struct mlxsw_sp_netevent_work *net_work =
2533 container_of(work, struct mlxsw_sp_netevent_work, work);
2534 struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
2535 struct mlxsw_sp_neigh_entry *neigh_entry;
2536 struct neighbour *n = net_work->n;
2537 unsigned char ha[ETH_ALEN];
2538 bool entry_connected;
2539 u8 nud_state, dead;
2540
2541
2542
2543
2544
2545 read_lock_bh(&n->lock);
2546 memcpy(ha, n->ha, ETH_ALEN);
2547 nud_state = n->nud_state;
2548 dead = n->dead;
2549 read_unlock_bh(&n->lock);
2550
2551 mutex_lock(&mlxsw_sp->router->lock);
2552 mlxsw_sp_span_respin(mlxsw_sp);
2553
2554 entry_connected = nud_state & NUD_VALID && !dead;
2555 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
2556 if (!entry_connected && !neigh_entry)
2557 goto out;
2558 if (!neigh_entry) {
2559 neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
2560 if (IS_ERR(neigh_entry))
2561 goto out;
2562 }
2563
2564 memcpy(neigh_entry->ha, ha, ETH_ALEN);
2565 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, entry_connected);
2566 mlxsw_sp_nexthop_neigh_update(mlxsw_sp, neigh_entry, !entry_connected,
2567 dead);
2568
2569 if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
2570 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
2571
2572out:
2573 mutex_unlock(&mlxsw_sp->router->lock);
2574 neigh_release(n);
2575 kfree(net_work);
2576}
2577
2578static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp);
2579
2580static void mlxsw_sp_router_mp_hash_event_work(struct work_struct *work)
2581{
2582 struct mlxsw_sp_netevent_work *net_work =
2583 container_of(work, struct mlxsw_sp_netevent_work, work);
2584 struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
2585
2586 mlxsw_sp_mp_hash_init(mlxsw_sp);
2587 kfree(net_work);
2588}
2589
2590static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp);
2591
2592static void mlxsw_sp_router_update_priority_work(struct work_struct *work)
2593{
2594 struct mlxsw_sp_netevent_work *net_work =
2595 container_of(work, struct mlxsw_sp_netevent_work, work);
2596 struct mlxsw_sp *mlxsw_sp = net_work->mlxsw_sp;
2597
2598 __mlxsw_sp_router_init(mlxsw_sp);
2599 kfree(net_work);
2600}
2601
2602static int mlxsw_sp_router_schedule_work(struct net *net,
2603 struct notifier_block *nb,
2604 void (*cb)(struct work_struct *))
2605{
2606 struct mlxsw_sp_netevent_work *net_work;
2607 struct mlxsw_sp_router *router;
2608
2609 router = container_of(nb, struct mlxsw_sp_router, netevent_nb);
2610 if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp)))
2611 return NOTIFY_DONE;
2612
2613 net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
2614 if (!net_work)
2615 return NOTIFY_BAD;
2616
2617 INIT_WORK(&net_work->work, cb);
2618 net_work->mlxsw_sp = router->mlxsw_sp;
2619 mlxsw_core_schedule_work(&net_work->work);
2620 return NOTIFY_DONE;
2621}
2622
2623static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
2624 unsigned long event, void *ptr)
2625{
2626 struct mlxsw_sp_netevent_work *net_work;
2627 struct mlxsw_sp_port *mlxsw_sp_port;
2628 struct mlxsw_sp *mlxsw_sp;
2629 unsigned long interval;
2630 struct neigh_parms *p;
2631 struct neighbour *n;
2632
2633 switch (event) {
2634 case NETEVENT_DELAY_PROBE_TIME_UPDATE:
2635 p = ptr;
2636
2637
2638 if (!p->dev || (p->tbl->family != AF_INET &&
2639 p->tbl->family != AF_INET6))
2640 return NOTIFY_DONE;
2641
2642
2643
2644
2645 mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
2646 if (!mlxsw_sp_port)
2647 return NOTIFY_DONE;
2648
2649 mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2650 interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
2651 mlxsw_sp->router->neighs_update.interval = interval;
2652
2653 mlxsw_sp_port_dev_put(mlxsw_sp_port);
2654 break;
2655 case NETEVENT_NEIGH_UPDATE:
2656 n = ptr;
2657
2658 if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6)
2659 return NOTIFY_DONE;
2660
2661 mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev);
2662 if (!mlxsw_sp_port)
2663 return NOTIFY_DONE;
2664
2665 net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
2666 if (!net_work) {
2667 mlxsw_sp_port_dev_put(mlxsw_sp_port);
2668 return NOTIFY_BAD;
2669 }
2670
2671 INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work);
2672 net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
2673 net_work->n = n;
2674
2675
2676
2677
2678
2679 neigh_clone(n);
2680 mlxsw_core_schedule_work(&net_work->work);
2681 mlxsw_sp_port_dev_put(mlxsw_sp_port);
2682 break;
2683 case NETEVENT_IPV4_MPATH_HASH_UPDATE:
2684 case NETEVENT_IPV6_MPATH_HASH_UPDATE:
2685 return mlxsw_sp_router_schedule_work(ptr, nb,
2686 mlxsw_sp_router_mp_hash_event_work);
2687
2688 case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE:
2689 return mlxsw_sp_router_schedule_work(ptr, nb,
2690 mlxsw_sp_router_update_priority_work);
2691 }
2692
2693 return NOTIFY_DONE;
2694}
2695
2696static int mlxsw_sp_neigh_init(struct mlxsw_sp *mlxsw_sp)
2697{
2698 int err;
2699
2700 err = rhashtable_init(&mlxsw_sp->router->neigh_ht,
2701 &mlxsw_sp_neigh_ht_params);
2702 if (err)
2703 return err;
2704
2705
2706
2707
2708 mlxsw_sp_router_neighs_update_interval_init(mlxsw_sp);
2709
2710
2711 INIT_DELAYED_WORK(&mlxsw_sp->router->neighs_update.dw,
2712 mlxsw_sp_router_neighs_update_work);
2713 INIT_DELAYED_WORK(&mlxsw_sp->router->nexthop_probe_dw,
2714 mlxsw_sp_router_probe_unresolved_nexthops);
2715 mlxsw_core_schedule_dw(&mlxsw_sp->router->neighs_update.dw, 0);
2716 mlxsw_core_schedule_dw(&mlxsw_sp->router->nexthop_probe_dw, 0);
2717 return 0;
2718}
2719
2720static void mlxsw_sp_neigh_fini(struct mlxsw_sp *mlxsw_sp)
2721{
2722 cancel_delayed_work_sync(&mlxsw_sp->router->neighs_update.dw);
2723 cancel_delayed_work_sync(&mlxsw_sp->router->nexthop_probe_dw);
2724 rhashtable_destroy(&mlxsw_sp->router->neigh_ht);
2725}
2726
2727static void mlxsw_sp_neigh_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
2728 struct mlxsw_sp_rif *rif)
2729{
2730 struct mlxsw_sp_neigh_entry *neigh_entry, *tmp;
2731
2732 list_for_each_entry_safe(neigh_entry, tmp, &rif->neigh_list,
2733 rif_list_node) {
2734 mlxsw_sp_neigh_entry_update(mlxsw_sp, neigh_entry, false);
2735 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
2736 }
2737}
2738
2739enum mlxsw_sp_nexthop_type {
2740 MLXSW_SP_NEXTHOP_TYPE_ETH,
2741 MLXSW_SP_NEXTHOP_TYPE_IPIP,
2742};
2743
2744struct mlxsw_sp_nexthop_key {
2745 struct fib_nh *fib_nh;
2746};
2747
2748struct mlxsw_sp_nexthop {
2749 struct list_head neigh_list_node;
2750 struct list_head rif_list_node;
2751 struct list_head router_list_node;
2752 struct mlxsw_sp_nexthop_group *nh_grp;
2753
2754
2755 struct rhash_head ht_node;
2756 struct mlxsw_sp_nexthop_key key;
2757 unsigned char gw_addr[sizeof(struct in6_addr)];
2758 int ifindex;
2759 int nh_weight;
2760 int norm_nh_weight;
2761 int num_adj_entries;
2762 struct mlxsw_sp_rif *rif;
2763 u8 should_offload:1,
2764
2765
2766 offloaded:1,
2767
2768
2769 update:1;
2770
2771
2772 enum mlxsw_sp_nexthop_type type;
2773 union {
2774 struct mlxsw_sp_neigh_entry *neigh_entry;
2775 struct mlxsw_sp_ipip_entry *ipip_entry;
2776 };
2777 unsigned int counter_index;
2778 bool counter_valid;
2779};
2780
2781struct mlxsw_sp_nexthop_group {
2782 void *priv;
2783 struct rhash_head ht_node;
2784 struct list_head fib_list;
2785 struct neigh_table *neigh_tbl;
2786 u8 adj_index_valid:1,
2787 gateway:1;
2788 u32 adj_index;
2789 u16 ecmp_size;
2790 u16 count;
2791 int sum_norm_weight;
2792 struct mlxsw_sp_nexthop nexthops[0];
2793#define nh_rif nexthops[0].rif
2794};
2795
2796void mlxsw_sp_nexthop_counter_alloc(struct mlxsw_sp *mlxsw_sp,
2797 struct mlxsw_sp_nexthop *nh)
2798{
2799 struct devlink *devlink;
2800
2801 devlink = priv_to_devlink(mlxsw_sp->core);
2802 if (!devlink_dpipe_table_counter_enabled(devlink,
2803 MLXSW_SP_DPIPE_TABLE_NAME_ADJ))
2804 return;
2805
2806 if (mlxsw_sp_flow_counter_alloc(mlxsw_sp, &nh->counter_index))
2807 return;
2808
2809 nh->counter_valid = true;
2810}
2811
2812void mlxsw_sp_nexthop_counter_free(struct mlxsw_sp *mlxsw_sp,
2813 struct mlxsw_sp_nexthop *nh)
2814{
2815 if (!nh->counter_valid)
2816 return;
2817 mlxsw_sp_flow_counter_free(mlxsw_sp, nh->counter_index);
2818 nh->counter_valid = false;
2819}
2820
2821int mlxsw_sp_nexthop_counter_get(struct mlxsw_sp *mlxsw_sp,
2822 struct mlxsw_sp_nexthop *nh, u64 *p_counter)
2823{
2824 if (!nh->counter_valid)
2825 return -EINVAL;
2826
2827 return mlxsw_sp_flow_counter_get(mlxsw_sp, nh->counter_index,
2828 p_counter, NULL);
2829}
2830
2831struct mlxsw_sp_nexthop *mlxsw_sp_nexthop_next(struct mlxsw_sp_router *router,
2832 struct mlxsw_sp_nexthop *nh)
2833{
2834 if (!nh) {
2835 if (list_empty(&router->nexthop_list))
2836 return NULL;
2837 else
2838 return list_first_entry(&router->nexthop_list,
2839 typeof(*nh), router_list_node);
2840 }
2841 if (list_is_last(&nh->router_list_node, &router->nexthop_list))
2842 return NULL;
2843 return list_next_entry(nh, router_list_node);
2844}
2845
2846bool mlxsw_sp_nexthop_offload(struct mlxsw_sp_nexthop *nh)
2847{
2848 return nh->offloaded;
2849}
2850
2851unsigned char *mlxsw_sp_nexthop_ha(struct mlxsw_sp_nexthop *nh)
2852{
2853 if (!nh->offloaded)
2854 return NULL;
2855 return nh->neigh_entry->ha;
2856}
2857
2858int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
2859 u32 *p_adj_size, u32 *p_adj_hash_index)
2860{
2861 struct mlxsw_sp_nexthop_group *nh_grp = nh->nh_grp;
2862 u32 adj_hash_index = 0;
2863 int i;
2864
2865 if (!nh->offloaded || !nh_grp->adj_index_valid)
2866 return -EINVAL;
2867
2868 *p_adj_index = nh_grp->adj_index;
2869 *p_adj_size = nh_grp->ecmp_size;
2870
2871 for (i = 0; i < nh_grp->count; i++) {
2872 struct mlxsw_sp_nexthop *nh_iter = &nh_grp->nexthops[i];
2873
2874 if (nh_iter == nh)
2875 break;
2876 if (nh_iter->offloaded)
2877 adj_hash_index += nh_iter->num_adj_entries;
2878 }
2879
2880 *p_adj_hash_index = adj_hash_index;
2881 return 0;
2882}
2883
2884struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh)
2885{
2886 return nh->rif;
2887}
2888
2889bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
2890{
2891 struct mlxsw_sp_nexthop_group *nh_grp = nh->nh_grp;
2892 int i;
2893
2894 for (i = 0; i < nh_grp->count; i++) {
2895 struct mlxsw_sp_nexthop *nh_iter = &nh_grp->nexthops[i];
2896
2897 if (nh_iter->type == MLXSW_SP_NEXTHOP_TYPE_IPIP)
2898 return true;
2899 }
2900 return false;
2901}
2902
2903static struct fib_info *
2904mlxsw_sp_nexthop4_group_fi(const struct mlxsw_sp_nexthop_group *nh_grp)
2905{
2906 return nh_grp->priv;
2907}
2908
2909struct mlxsw_sp_nexthop_group_cmp_arg {
2910 enum mlxsw_sp_l3proto proto;
2911 union {
2912 struct fib_info *fi;
2913 struct mlxsw_sp_fib6_entry *fib6_entry;
2914 };
2915};
2916
2917static bool
2918mlxsw_sp_nexthop6_group_has_nexthop(const struct mlxsw_sp_nexthop_group *nh_grp,
2919 const struct in6_addr *gw, int ifindex,
2920 int weight)
2921{
2922 int i;
2923
2924 for (i = 0; i < nh_grp->count; i++) {
2925 const struct mlxsw_sp_nexthop *nh;
2926
2927 nh = &nh_grp->nexthops[i];
2928 if (nh->ifindex == ifindex && nh->nh_weight == weight &&
2929 ipv6_addr_equal(gw, (struct in6_addr *) nh->gw_addr))
2930 return true;
2931 }
2932
2933 return false;
2934}
2935
2936static bool
2937mlxsw_sp_nexthop6_group_cmp(const struct mlxsw_sp_nexthop_group *nh_grp,
2938 const struct mlxsw_sp_fib6_entry *fib6_entry)
2939{
2940 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
2941
2942 if (nh_grp->count != fib6_entry->nrt6)
2943 return false;
2944
2945 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
2946 struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
2947 struct in6_addr *gw;
2948 int ifindex, weight;
2949
2950 ifindex = fib6_nh->fib_nh_dev->ifindex;
2951 weight = fib6_nh->fib_nh_weight;
2952 gw = &fib6_nh->fib_nh_gw6;
2953 if (!mlxsw_sp_nexthop6_group_has_nexthop(nh_grp, gw, ifindex,
2954 weight))
2955 return false;
2956 }
2957
2958 return true;
2959}
2960
2961static int
2962mlxsw_sp_nexthop_group_cmp(struct rhashtable_compare_arg *arg, const void *ptr)
2963{
2964 const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = arg->key;
2965 const struct mlxsw_sp_nexthop_group *nh_grp = ptr;
2966
2967 switch (cmp_arg->proto) {
2968 case MLXSW_SP_L3_PROTO_IPV4:
2969 return cmp_arg->fi != mlxsw_sp_nexthop4_group_fi(nh_grp);
2970 case MLXSW_SP_L3_PROTO_IPV6:
2971 return !mlxsw_sp_nexthop6_group_cmp(nh_grp,
2972 cmp_arg->fib6_entry);
2973 default:
2974 WARN_ON(1);
2975 return 1;
2976 }
2977}
2978
2979static int
2980mlxsw_sp_nexthop_group_type(const struct mlxsw_sp_nexthop_group *nh_grp)
2981{
2982 return nh_grp->neigh_tbl->family;
2983}
2984
2985static u32 mlxsw_sp_nexthop_group_hash_obj(const void *data, u32 len, u32 seed)
2986{
2987 const struct mlxsw_sp_nexthop_group *nh_grp = data;
2988 const struct mlxsw_sp_nexthop *nh;
2989 struct fib_info *fi;
2990 unsigned int val;
2991 int i;
2992
2993 switch (mlxsw_sp_nexthop_group_type(nh_grp)) {
2994 case AF_INET:
2995 fi = mlxsw_sp_nexthop4_group_fi(nh_grp);
2996 return jhash(&fi, sizeof(fi), seed);
2997 case AF_INET6:
2998 val = nh_grp->count;
2999 for (i = 0; i < nh_grp->count; i++) {
3000 nh = &nh_grp->nexthops[i];
3001 val ^= jhash(&nh->ifindex, sizeof(nh->ifindex), seed);
3002 }
3003 return jhash(&val, sizeof(val), seed);
3004 default:
3005 WARN_ON(1);
3006 return 0;
3007 }
3008}
3009
3010static u32
3011mlxsw_sp_nexthop6_group_hash(struct mlxsw_sp_fib6_entry *fib6_entry, u32 seed)
3012{
3013 unsigned int val = fib6_entry->nrt6;
3014 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3015 struct net_device *dev;
3016
3017 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3018 dev = mlxsw_sp_rt6->rt->fib6_nh->fib_nh_dev;
3019 val ^= jhash(&dev->ifindex, sizeof(dev->ifindex), seed);
3020 }
3021
3022 return jhash(&val, sizeof(val), seed);
3023}
3024
3025static u32
3026mlxsw_sp_nexthop_group_hash(const void *data, u32 len, u32 seed)
3027{
3028 const struct mlxsw_sp_nexthop_group_cmp_arg *cmp_arg = data;
3029
3030 switch (cmp_arg->proto) {
3031 case MLXSW_SP_L3_PROTO_IPV4:
3032 return jhash(&cmp_arg->fi, sizeof(cmp_arg->fi), seed);
3033 case MLXSW_SP_L3_PROTO_IPV6:
3034 return mlxsw_sp_nexthop6_group_hash(cmp_arg->fib6_entry, seed);
3035 default:
3036 WARN_ON(1);
3037 return 0;
3038 }
3039}
3040
3041static const struct rhashtable_params mlxsw_sp_nexthop_group_ht_params = {
3042 .head_offset = offsetof(struct mlxsw_sp_nexthop_group, ht_node),
3043 .hashfn = mlxsw_sp_nexthop_group_hash,
3044 .obj_hashfn = mlxsw_sp_nexthop_group_hash_obj,
3045 .obj_cmpfn = mlxsw_sp_nexthop_group_cmp,
3046};
3047
3048static int mlxsw_sp_nexthop_group_insert(struct mlxsw_sp *mlxsw_sp,
3049 struct mlxsw_sp_nexthop_group *nh_grp)
3050{
3051 if (mlxsw_sp_nexthop_group_type(nh_grp) == AF_INET6 &&
3052 !nh_grp->gateway)
3053 return 0;
3054
3055 return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_group_ht,
3056 &nh_grp->ht_node,
3057 mlxsw_sp_nexthop_group_ht_params);
3058}
3059
3060static void mlxsw_sp_nexthop_group_remove(struct mlxsw_sp *mlxsw_sp,
3061 struct mlxsw_sp_nexthop_group *nh_grp)
3062{
3063 if (mlxsw_sp_nexthop_group_type(nh_grp) == AF_INET6 &&
3064 !nh_grp->gateway)
3065 return;
3066
3067 rhashtable_remove_fast(&mlxsw_sp->router->nexthop_group_ht,
3068 &nh_grp->ht_node,
3069 mlxsw_sp_nexthop_group_ht_params);
3070}
3071
3072static struct mlxsw_sp_nexthop_group *
3073mlxsw_sp_nexthop4_group_lookup(struct mlxsw_sp *mlxsw_sp,
3074 struct fib_info *fi)
3075{
3076 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
3077
3078 cmp_arg.proto = MLXSW_SP_L3_PROTO_IPV4;
3079 cmp_arg.fi = fi;
3080 return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
3081 &cmp_arg,
3082 mlxsw_sp_nexthop_group_ht_params);
3083}
3084
3085static struct mlxsw_sp_nexthop_group *
3086mlxsw_sp_nexthop6_group_lookup(struct mlxsw_sp *mlxsw_sp,
3087 struct mlxsw_sp_fib6_entry *fib6_entry)
3088{
3089 struct mlxsw_sp_nexthop_group_cmp_arg cmp_arg;
3090
3091 cmp_arg.proto = MLXSW_SP_L3_PROTO_IPV6;
3092 cmp_arg.fib6_entry = fib6_entry;
3093 return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_group_ht,
3094 &cmp_arg,
3095 mlxsw_sp_nexthop_group_ht_params);
3096}
3097
3098static const struct rhashtable_params mlxsw_sp_nexthop_ht_params = {
3099 .key_offset = offsetof(struct mlxsw_sp_nexthop, key),
3100 .head_offset = offsetof(struct mlxsw_sp_nexthop, ht_node),
3101 .key_len = sizeof(struct mlxsw_sp_nexthop_key),
3102};
3103
3104static int mlxsw_sp_nexthop_insert(struct mlxsw_sp *mlxsw_sp,
3105 struct mlxsw_sp_nexthop *nh)
3106{
3107 return rhashtable_insert_fast(&mlxsw_sp->router->nexthop_ht,
3108 &nh->ht_node, mlxsw_sp_nexthop_ht_params);
3109}
3110
3111static void mlxsw_sp_nexthop_remove(struct mlxsw_sp *mlxsw_sp,
3112 struct mlxsw_sp_nexthop *nh)
3113{
3114 rhashtable_remove_fast(&mlxsw_sp->router->nexthop_ht, &nh->ht_node,
3115 mlxsw_sp_nexthop_ht_params);
3116}
3117
3118static struct mlxsw_sp_nexthop *
3119mlxsw_sp_nexthop_lookup(struct mlxsw_sp *mlxsw_sp,
3120 struct mlxsw_sp_nexthop_key key)
3121{
3122 return rhashtable_lookup_fast(&mlxsw_sp->router->nexthop_ht, &key,
3123 mlxsw_sp_nexthop_ht_params);
3124}
3125
3126static int mlxsw_sp_adj_index_mass_update_vr(struct mlxsw_sp *mlxsw_sp,
3127 const struct mlxsw_sp_fib *fib,
3128 u32 adj_index, u16 ecmp_size,
3129 u32 new_adj_index,
3130 u16 new_ecmp_size)
3131{
3132 char raleu_pl[MLXSW_REG_RALEU_LEN];
3133
3134 mlxsw_reg_raleu_pack(raleu_pl,
3135 (enum mlxsw_reg_ralxx_protocol) fib->proto,
3136 fib->vr->id, adj_index, ecmp_size, new_adj_index,
3137 new_ecmp_size);
3138 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raleu), raleu_pl);
3139}
3140
3141static int mlxsw_sp_adj_index_mass_update(struct mlxsw_sp *mlxsw_sp,
3142 struct mlxsw_sp_nexthop_group *nh_grp,
3143 u32 old_adj_index, u16 old_ecmp_size)
3144{
3145 struct mlxsw_sp_fib_entry *fib_entry;
3146 struct mlxsw_sp_fib *fib = NULL;
3147 int err;
3148
3149 list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
3150 if (fib == fib_entry->fib_node->fib)
3151 continue;
3152 fib = fib_entry->fib_node->fib;
3153 err = mlxsw_sp_adj_index_mass_update_vr(mlxsw_sp, fib,
3154 old_adj_index,
3155 old_ecmp_size,
3156 nh_grp->adj_index,
3157 nh_grp->ecmp_size);
3158 if (err)
3159 return err;
3160 }
3161 return 0;
3162}
3163
3164static int __mlxsw_sp_nexthop_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
3165 struct mlxsw_sp_nexthop *nh)
3166{
3167 struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
3168 char ratr_pl[MLXSW_REG_RATR_LEN];
3169
3170 mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY,
3171 true, MLXSW_REG_RATR_TYPE_ETHERNET,
3172 adj_index, neigh_entry->rif);
3173 mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
3174 if (nh->counter_valid)
3175 mlxsw_reg_ratr_counter_pack(ratr_pl, nh->counter_index, true);
3176 else
3177 mlxsw_reg_ratr_counter_pack(ratr_pl, 0, false);
3178
3179 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
3180}
3181
3182int mlxsw_sp_nexthop_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
3183 struct mlxsw_sp_nexthop *nh)
3184{
3185 int i;
3186
3187 for (i = 0; i < nh->num_adj_entries; i++) {
3188 int err;
3189
3190 err = __mlxsw_sp_nexthop_update(mlxsw_sp, adj_index + i, nh);
3191 if (err)
3192 return err;
3193 }
3194
3195 return 0;
3196}
3197
3198static int __mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
3199 u32 adj_index,
3200 struct mlxsw_sp_nexthop *nh)
3201{
3202 const struct mlxsw_sp_ipip_ops *ipip_ops;
3203
3204 ipip_ops = mlxsw_sp->router->ipip_ops_arr[nh->ipip_entry->ipipt];
3205 return ipip_ops->nexthop_update(mlxsw_sp, adj_index, nh->ipip_entry);
3206}
3207
3208static int mlxsw_sp_nexthop_ipip_update(struct mlxsw_sp *mlxsw_sp,
3209 u32 adj_index,
3210 struct mlxsw_sp_nexthop *nh)
3211{
3212 int i;
3213
3214 for (i = 0; i < nh->num_adj_entries; i++) {
3215 int err;
3216
3217 err = __mlxsw_sp_nexthop_ipip_update(mlxsw_sp, adj_index + i,
3218 nh);
3219 if (err)
3220 return err;
3221 }
3222
3223 return 0;
3224}
3225
3226static int
3227mlxsw_sp_nexthop_group_update(struct mlxsw_sp *mlxsw_sp,
3228 struct mlxsw_sp_nexthop_group *nh_grp,
3229 bool reallocate)
3230{
3231 u32 adj_index = nh_grp->adj_index;
3232 struct mlxsw_sp_nexthop *nh;
3233 int i;
3234
3235 for (i = 0; i < nh_grp->count; i++) {
3236 nh = &nh_grp->nexthops[i];
3237
3238 if (!nh->should_offload) {
3239 nh->offloaded = 0;
3240 continue;
3241 }
3242
3243 if (nh->update || reallocate) {
3244 int err = 0;
3245
3246 switch (nh->type) {
3247 case MLXSW_SP_NEXTHOP_TYPE_ETH:
3248 err = mlxsw_sp_nexthop_update
3249 (mlxsw_sp, adj_index, nh);
3250 break;
3251 case MLXSW_SP_NEXTHOP_TYPE_IPIP:
3252 err = mlxsw_sp_nexthop_ipip_update
3253 (mlxsw_sp, adj_index, nh);
3254 break;
3255 }
3256 if (err)
3257 return err;
3258 nh->update = 0;
3259 nh->offloaded = 1;
3260 }
3261 adj_index += nh->num_adj_entries;
3262 }
3263 return 0;
3264}
3265
3266static int
3267mlxsw_sp_nexthop_fib_entries_update(struct mlxsw_sp *mlxsw_sp,
3268 struct mlxsw_sp_nexthop_group *nh_grp)
3269{
3270 struct mlxsw_sp_fib_entry *fib_entry;
3271 int err;
3272
3273 list_for_each_entry(fib_entry, &nh_grp->fib_list, nexthop_group_node) {
3274 err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
3275 if (err)
3276 return err;
3277 }
3278 return 0;
3279}
3280
3281static void mlxsw_sp_adj_grp_size_round_up(u16 *p_adj_grp_size)
3282{
3283
3284
3285
3286 if (*p_adj_grp_size <= 64)
3287 return;
3288 else if (*p_adj_grp_size <= 512)
3289 *p_adj_grp_size = 512;
3290 else if (*p_adj_grp_size <= 1024)
3291 *p_adj_grp_size = 1024;
3292 else if (*p_adj_grp_size <= 2048)
3293 *p_adj_grp_size = 2048;
3294 else
3295 *p_adj_grp_size = 4096;
3296}
3297
3298static void mlxsw_sp_adj_grp_size_round_down(u16 *p_adj_grp_size,
3299 unsigned int alloc_size)
3300{
3301 if (alloc_size >= 4096)
3302 *p_adj_grp_size = 4096;
3303 else if (alloc_size >= 2048)
3304 *p_adj_grp_size = 2048;
3305 else if (alloc_size >= 1024)
3306 *p_adj_grp_size = 1024;
3307 else if (alloc_size >= 512)
3308 *p_adj_grp_size = 512;
3309}
3310
3311static int mlxsw_sp_fix_adj_grp_size(struct mlxsw_sp *mlxsw_sp,
3312 u16 *p_adj_grp_size)
3313{
3314 unsigned int alloc_size;
3315 int err;
3316
3317
3318
3319
3320 mlxsw_sp_adj_grp_size_round_up(p_adj_grp_size);
3321 err = mlxsw_sp_kvdl_alloc_count_query(mlxsw_sp,
3322 MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3323 *p_adj_grp_size, &alloc_size);
3324 if (err)
3325 return err;
3326
3327
3328
3329
3330 mlxsw_sp_adj_grp_size_round_down(p_adj_grp_size, alloc_size);
3331
3332 return 0;
3333}
3334
3335static void
3336mlxsw_sp_nexthop_group_normalize(struct mlxsw_sp_nexthop_group *nh_grp)
3337{
3338 int i, g = 0, sum_norm_weight = 0;
3339 struct mlxsw_sp_nexthop *nh;
3340
3341 for (i = 0; i < nh_grp->count; i++) {
3342 nh = &nh_grp->nexthops[i];
3343
3344 if (!nh->should_offload)
3345 continue;
3346 if (g > 0)
3347 g = gcd(nh->nh_weight, g);
3348 else
3349 g = nh->nh_weight;
3350 }
3351
3352 for (i = 0; i < nh_grp->count; i++) {
3353 nh = &nh_grp->nexthops[i];
3354
3355 if (!nh->should_offload)
3356 continue;
3357 nh->norm_nh_weight = nh->nh_weight / g;
3358 sum_norm_weight += nh->norm_nh_weight;
3359 }
3360
3361 nh_grp->sum_norm_weight = sum_norm_weight;
3362}
3363
3364static void
3365mlxsw_sp_nexthop_group_rebalance(struct mlxsw_sp_nexthop_group *nh_grp)
3366{
3367 int total = nh_grp->sum_norm_weight;
3368 u16 ecmp_size = nh_grp->ecmp_size;
3369 int i, weight = 0, lower_bound = 0;
3370
3371 for (i = 0; i < nh_grp->count; i++) {
3372 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
3373 int upper_bound;
3374
3375 if (!nh->should_offload)
3376 continue;
3377 weight += nh->norm_nh_weight;
3378 upper_bound = DIV_ROUND_CLOSEST(ecmp_size * weight, total);
3379 nh->num_adj_entries = upper_bound - lower_bound;
3380 lower_bound = upper_bound;
3381 }
3382}
3383
3384static struct mlxsw_sp_nexthop *
3385mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
3386 const struct mlxsw_sp_rt6 *mlxsw_sp_rt6);
3387
3388static void
3389mlxsw_sp_nexthop4_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3390 struct mlxsw_sp_nexthop_group *nh_grp)
3391{
3392 int i;
3393
3394 for (i = 0; i < nh_grp->count; i++) {
3395 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
3396
3397 if (nh->offloaded)
3398 nh->key.fib_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
3399 else
3400 nh->key.fib_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
3401 }
3402}
3403
3404static void
3405__mlxsw_sp_nexthop6_group_offload_refresh(struct mlxsw_sp_nexthop_group *nh_grp,
3406 struct mlxsw_sp_fib6_entry *fib6_entry)
3407{
3408 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
3409
3410 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
3411 struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
3412 struct mlxsw_sp_nexthop *nh;
3413
3414 nh = mlxsw_sp_rt6_nexthop(nh_grp, mlxsw_sp_rt6);
3415 if (nh && nh->offloaded)
3416 fib6_nh->fib_nh_flags |= RTNH_F_OFFLOAD;
3417 else
3418 fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
3419 }
3420}
3421
3422static void
3423mlxsw_sp_nexthop6_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3424 struct mlxsw_sp_nexthop_group *nh_grp)
3425{
3426 struct mlxsw_sp_fib6_entry *fib6_entry;
3427
3428
3429
3430
3431
3432 list_for_each_entry(fib6_entry, &nh_grp->fib_list,
3433 common.nexthop_group_node)
3434 __mlxsw_sp_nexthop6_group_offload_refresh(nh_grp, fib6_entry);
3435}
3436
3437static void
3438mlxsw_sp_nexthop_group_offload_refresh(struct mlxsw_sp *mlxsw_sp,
3439 struct mlxsw_sp_nexthop_group *nh_grp)
3440{
3441 switch (mlxsw_sp_nexthop_group_type(nh_grp)) {
3442 case AF_INET:
3443 mlxsw_sp_nexthop4_group_offload_refresh(mlxsw_sp, nh_grp);
3444 break;
3445 case AF_INET6:
3446 mlxsw_sp_nexthop6_group_offload_refresh(mlxsw_sp, nh_grp);
3447 break;
3448 }
3449}
3450
3451static void
3452mlxsw_sp_nexthop_group_refresh(struct mlxsw_sp *mlxsw_sp,
3453 struct mlxsw_sp_nexthop_group *nh_grp)
3454{
3455 u16 ecmp_size, old_ecmp_size;
3456 struct mlxsw_sp_nexthop *nh;
3457 bool offload_change = false;
3458 u32 adj_index;
3459 bool old_adj_index_valid;
3460 u32 old_adj_index;
3461 int i;
3462 int err;
3463
3464 if (!nh_grp->gateway) {
3465 mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
3466 return;
3467 }
3468
3469 for (i = 0; i < nh_grp->count; i++) {
3470 nh = &nh_grp->nexthops[i];
3471
3472 if (nh->should_offload != nh->offloaded) {
3473 offload_change = true;
3474 if (nh->should_offload)
3475 nh->update = 1;
3476 }
3477 }
3478 if (!offload_change) {
3479
3480
3481
3482 err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nh_grp, false);
3483 if (err) {
3484 dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
3485 goto set_trap;
3486 }
3487 return;
3488 }
3489 mlxsw_sp_nexthop_group_normalize(nh_grp);
3490 if (!nh_grp->sum_norm_weight)
3491
3492
3493
3494 goto set_trap;
3495
3496 ecmp_size = nh_grp->sum_norm_weight;
3497 err = mlxsw_sp_fix_adj_grp_size(mlxsw_sp, &ecmp_size);
3498 if (err)
3499
3500 goto set_trap;
3501
3502 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3503 ecmp_size, &adj_index);
3504 if (err) {
3505
3506
3507
3508 dev_warn(mlxsw_sp->bus_info->dev, "Failed to allocate KVD linear area for nexthop group.\n");
3509 goto set_trap;
3510 }
3511 old_adj_index_valid = nh_grp->adj_index_valid;
3512 old_adj_index = nh_grp->adj_index;
3513 old_ecmp_size = nh_grp->ecmp_size;
3514 nh_grp->adj_index_valid = 1;
3515 nh_grp->adj_index = adj_index;
3516 nh_grp->ecmp_size = ecmp_size;
3517 mlxsw_sp_nexthop_group_rebalance(nh_grp);
3518 err = mlxsw_sp_nexthop_group_update(mlxsw_sp, nh_grp, true);
3519 if (err) {
3520 dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
3521 goto set_trap;
3522 }
3523
3524 mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
3525
3526 if (!old_adj_index_valid) {
3527
3528
3529
3530 err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
3531 if (err) {
3532 dev_warn(mlxsw_sp->bus_info->dev, "Failed to add adjacency index to fib entries.\n");
3533 goto set_trap;
3534 }
3535 return;
3536 }
3537
3538 err = mlxsw_sp_adj_index_mass_update(mlxsw_sp, nh_grp,
3539 old_adj_index, old_ecmp_size);
3540 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3541 old_ecmp_size, old_adj_index);
3542 if (err) {
3543 dev_warn(mlxsw_sp->bus_info->dev, "Failed to mass-update adjacency index for nexthop group.\n");
3544 goto set_trap;
3545 }
3546
3547 return;
3548
3549set_trap:
3550 old_adj_index_valid = nh_grp->adj_index_valid;
3551 nh_grp->adj_index_valid = 0;
3552 for (i = 0; i < nh_grp->count; i++) {
3553 nh = &nh_grp->nexthops[i];
3554 nh->offloaded = 0;
3555 }
3556 err = mlxsw_sp_nexthop_fib_entries_update(mlxsw_sp, nh_grp);
3557 if (err)
3558 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set traps for fib entries.\n");
3559 mlxsw_sp_nexthop_group_offload_refresh(mlxsw_sp, nh_grp);
3560 if (old_adj_index_valid)
3561 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ,
3562 nh_grp->ecmp_size, nh_grp->adj_index);
3563}
3564
3565static void __mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp_nexthop *nh,
3566 bool removing)
3567{
3568 if (!removing)
3569 nh->should_offload = 1;
3570 else
3571 nh->should_offload = 0;
3572 nh->update = 1;
3573}
3574
3575static int
3576mlxsw_sp_nexthop_dead_neigh_replace(struct mlxsw_sp *mlxsw_sp,
3577 struct mlxsw_sp_neigh_entry *neigh_entry)
3578{
3579 struct neighbour *n, *old_n = neigh_entry->key.n;
3580 struct mlxsw_sp_nexthop *nh;
3581 bool entry_connected;
3582 u8 nud_state, dead;
3583 int err;
3584
3585 nh = list_first_entry(&neigh_entry->nexthop_list,
3586 struct mlxsw_sp_nexthop, neigh_list_node);
3587
3588 n = neigh_lookup(nh->nh_grp->neigh_tbl, &nh->gw_addr, nh->rif->dev);
3589 if (!n) {
3590 n = neigh_create(nh->nh_grp->neigh_tbl, &nh->gw_addr,
3591 nh->rif->dev);
3592 if (IS_ERR(n))
3593 return PTR_ERR(n);
3594 neigh_event_send(n, NULL);
3595 }
3596
3597 mlxsw_sp_neigh_entry_remove(mlxsw_sp, neigh_entry);
3598 neigh_entry->key.n = n;
3599 err = mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
3600 if (err)
3601 goto err_neigh_entry_insert;
3602
3603 read_lock_bh(&n->lock);
3604 nud_state = n->nud_state;
3605 dead = n->dead;
3606 read_unlock_bh(&n->lock);
3607 entry_connected = nud_state & NUD_VALID && !dead;
3608
3609 list_for_each_entry(nh, &neigh_entry->nexthop_list,
3610 neigh_list_node) {
3611 neigh_release(old_n);
3612 neigh_clone(n);
3613 __mlxsw_sp_nexthop_neigh_update(nh, !entry_connected);
3614 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
3615 }
3616
3617 neigh_release(n);
3618
3619 return 0;
3620
3621err_neigh_entry_insert:
3622 neigh_entry->key.n = old_n;
3623 mlxsw_sp_neigh_entry_insert(mlxsw_sp, neigh_entry);
3624 neigh_release(n);
3625 return err;
3626}
3627
3628static void
3629mlxsw_sp_nexthop_neigh_update(struct mlxsw_sp *mlxsw_sp,
3630 struct mlxsw_sp_neigh_entry *neigh_entry,
3631 bool removing, bool dead)
3632{
3633 struct mlxsw_sp_nexthop *nh;
3634
3635 if (list_empty(&neigh_entry->nexthop_list))
3636 return;
3637
3638 if (dead) {
3639 int err;
3640
3641 err = mlxsw_sp_nexthop_dead_neigh_replace(mlxsw_sp,
3642 neigh_entry);
3643 if (err)
3644 dev_err(mlxsw_sp->bus_info->dev, "Failed to replace dead neigh\n");
3645 return;
3646 }
3647
3648 list_for_each_entry(nh, &neigh_entry->nexthop_list,
3649 neigh_list_node) {
3650 __mlxsw_sp_nexthop_neigh_update(nh, removing);
3651 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
3652 }
3653}
3654
3655static void mlxsw_sp_nexthop_rif_init(struct mlxsw_sp_nexthop *nh,
3656 struct mlxsw_sp_rif *rif)
3657{
3658 if (nh->rif)
3659 return;
3660
3661 nh->rif = rif;
3662 list_add(&nh->rif_list_node, &rif->nexthop_list);
3663}
3664
3665static void mlxsw_sp_nexthop_rif_fini(struct mlxsw_sp_nexthop *nh)
3666{
3667 if (!nh->rif)
3668 return;
3669
3670 list_del(&nh->rif_list_node);
3671 nh->rif = NULL;
3672}
3673
3674static int mlxsw_sp_nexthop_neigh_init(struct mlxsw_sp *mlxsw_sp,
3675 struct mlxsw_sp_nexthop *nh)
3676{
3677 struct mlxsw_sp_neigh_entry *neigh_entry;
3678 struct neighbour *n;
3679 u8 nud_state, dead;
3680 int err;
3681
3682 if (!nh->nh_grp->gateway || nh->neigh_entry)
3683 return 0;
3684
3685
3686
3687
3688
3689
3690 n = neigh_lookup(nh->nh_grp->neigh_tbl, &nh->gw_addr, nh->rif->dev);
3691 if (!n) {
3692 n = neigh_create(nh->nh_grp->neigh_tbl, &nh->gw_addr,
3693 nh->rif->dev);
3694 if (IS_ERR(n))
3695 return PTR_ERR(n);
3696 neigh_event_send(n, NULL);
3697 }
3698 neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
3699 if (!neigh_entry) {
3700 neigh_entry = mlxsw_sp_neigh_entry_create(mlxsw_sp, n);
3701 if (IS_ERR(neigh_entry)) {
3702 err = -EINVAL;
3703 goto err_neigh_entry_create;
3704 }
3705 }
3706
3707
3708
3709
3710 if (list_empty(&neigh_entry->nexthop_list))
3711 list_add_tail(&neigh_entry->nexthop_neighs_list_node,
3712 &mlxsw_sp->router->nexthop_neighs_list);
3713
3714 nh->neigh_entry = neigh_entry;
3715 list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
3716 read_lock_bh(&n->lock);
3717 nud_state = n->nud_state;
3718 dead = n->dead;
3719 read_unlock_bh(&n->lock);
3720 __mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
3721
3722 return 0;
3723
3724err_neigh_entry_create:
3725 neigh_release(n);
3726 return err;
3727}
3728
3729static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
3730 struct mlxsw_sp_nexthop *nh)
3731{
3732 struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
3733 struct neighbour *n;
3734
3735 if (!neigh_entry)
3736 return;
3737 n = neigh_entry->key.n;
3738
3739 __mlxsw_sp_nexthop_neigh_update(nh, true);
3740 list_del(&nh->neigh_list_node);
3741 nh->neigh_entry = NULL;
3742
3743
3744
3745
3746 if (list_empty(&neigh_entry->nexthop_list))
3747 list_del(&neigh_entry->nexthop_neighs_list_node);
3748
3749 if (!neigh_entry->connected && list_empty(&neigh_entry->nexthop_list))
3750 mlxsw_sp_neigh_entry_destroy(mlxsw_sp, neigh_entry);
3751
3752 neigh_release(n);
3753}
3754
3755static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
3756{
3757 struct net_device *ul_dev;
3758 bool is_up;
3759
3760 rcu_read_lock();
3761 ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
3762 is_up = ul_dev ? (ul_dev->flags & IFF_UP) : true;
3763 rcu_read_unlock();
3764
3765 return is_up;
3766}
3767
3768static void mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
3769 struct mlxsw_sp_nexthop *nh,
3770 struct mlxsw_sp_ipip_entry *ipip_entry)
3771{
3772 bool removing;
3773
3774 if (!nh->nh_grp->gateway || nh->ipip_entry)
3775 return;
3776
3777 nh->ipip_entry = ipip_entry;
3778 removing = !mlxsw_sp_ipip_netdev_ul_up(ipip_entry->ol_dev);
3779 __mlxsw_sp_nexthop_neigh_update(nh, removing);
3780 mlxsw_sp_nexthop_rif_init(nh, &ipip_entry->ol_lb->common);
3781}
3782
3783static void mlxsw_sp_nexthop_ipip_fini(struct mlxsw_sp *mlxsw_sp,
3784 struct mlxsw_sp_nexthop *nh)
3785{
3786 struct mlxsw_sp_ipip_entry *ipip_entry = nh->ipip_entry;
3787
3788 if (!ipip_entry)
3789 return;
3790
3791 __mlxsw_sp_nexthop_neigh_update(nh, true);
3792 nh->ipip_entry = NULL;
3793}
3794
3795static bool mlxsw_sp_nexthop4_ipip_type(const struct mlxsw_sp *mlxsw_sp,
3796 const struct fib_nh *fib_nh,
3797 enum mlxsw_sp_ipip_type *p_ipipt)
3798{
3799 struct net_device *dev = fib_nh->fib_nh_dev;
3800
3801 return dev &&
3802 fib_nh->nh_parent->fib_type == RTN_UNICAST &&
3803 mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, p_ipipt);
3804}
3805
3806static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
3807 struct mlxsw_sp_nexthop *nh)
3808{
3809 switch (nh->type) {
3810 case MLXSW_SP_NEXTHOP_TYPE_ETH:
3811 mlxsw_sp_nexthop_neigh_fini(mlxsw_sp, nh);
3812 mlxsw_sp_nexthop_rif_fini(nh);
3813 break;
3814 case MLXSW_SP_NEXTHOP_TYPE_IPIP:
3815 mlxsw_sp_nexthop_rif_fini(nh);
3816 mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
3817 break;
3818 }
3819}
3820
3821static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp,
3822 struct mlxsw_sp_nexthop *nh,
3823 struct fib_nh *fib_nh)
3824{
3825 const struct mlxsw_sp_ipip_ops *ipip_ops;
3826 struct net_device *dev = fib_nh->fib_nh_dev;
3827 struct mlxsw_sp_ipip_entry *ipip_entry;
3828 struct mlxsw_sp_rif *rif;
3829 int err;
3830
3831 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
3832 if (ipip_entry) {
3833 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
3834 if (ipip_ops->can_offload(mlxsw_sp, dev,
3835 MLXSW_SP_L3_PROTO_IPV4)) {
3836 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
3837 mlxsw_sp_nexthop_ipip_init(mlxsw_sp, nh, ipip_entry);
3838 return 0;
3839 }
3840 }
3841
3842 nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
3843 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
3844 if (!rif)
3845 return 0;
3846
3847 mlxsw_sp_nexthop_rif_init(nh, rif);
3848 err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
3849 if (err)
3850 goto err_neigh_init;
3851
3852 return 0;
3853
3854err_neigh_init:
3855 mlxsw_sp_nexthop_rif_fini(nh);
3856 return err;
3857}
3858
3859static void mlxsw_sp_nexthop4_type_fini(struct mlxsw_sp *mlxsw_sp,
3860 struct mlxsw_sp_nexthop *nh)
3861{
3862 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
3863}
3864
3865static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
3866 struct mlxsw_sp_nexthop_group *nh_grp,
3867 struct mlxsw_sp_nexthop *nh,
3868 struct fib_nh *fib_nh)
3869{
3870 struct net_device *dev = fib_nh->fib_nh_dev;
3871 struct in_device *in_dev;
3872 int err;
3873
3874 nh->nh_grp = nh_grp;
3875 nh->key.fib_nh = fib_nh;
3876#ifdef CONFIG_IP_ROUTE_MULTIPATH
3877 nh->nh_weight = fib_nh->fib_nh_weight;
3878#else
3879 nh->nh_weight = 1;
3880#endif
3881 memcpy(&nh->gw_addr, &fib_nh->fib_nh_gw4, sizeof(fib_nh->fib_nh_gw4));
3882 err = mlxsw_sp_nexthop_insert(mlxsw_sp, nh);
3883 if (err)
3884 return err;
3885
3886 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
3887 list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
3888
3889 if (!dev)
3890 return 0;
3891
3892 rcu_read_lock();
3893 in_dev = __in_dev_get_rcu(dev);
3894 if (in_dev && IN_DEV_IGNORE_ROUTES_WITH_LINKDOWN(in_dev) &&
3895 fib_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
3896 rcu_read_unlock();
3897 return 0;
3898 }
3899 rcu_read_unlock();
3900
3901 err = mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
3902 if (err)
3903 goto err_nexthop_neigh_init;
3904
3905 return 0;
3906
3907err_nexthop_neigh_init:
3908 mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
3909 return err;
3910}
3911
3912static void mlxsw_sp_nexthop4_fini(struct mlxsw_sp *mlxsw_sp,
3913 struct mlxsw_sp_nexthop *nh)
3914{
3915 mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh);
3916 list_del(&nh->router_list_node);
3917 mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
3918 mlxsw_sp_nexthop_remove(mlxsw_sp, nh);
3919}
3920
3921static void mlxsw_sp_nexthop4_event(struct mlxsw_sp *mlxsw_sp,
3922 unsigned long event, struct fib_nh *fib_nh)
3923{
3924 struct mlxsw_sp_nexthop_key key;
3925 struct mlxsw_sp_nexthop *nh;
3926
3927 if (mlxsw_sp->router->aborted)
3928 return;
3929
3930 key.fib_nh = fib_nh;
3931 nh = mlxsw_sp_nexthop_lookup(mlxsw_sp, key);
3932 if (!nh)
3933 return;
3934
3935 switch (event) {
3936 case FIB_EVENT_NH_ADD:
3937 mlxsw_sp_nexthop4_type_init(mlxsw_sp, nh, fib_nh);
3938 break;
3939 case FIB_EVENT_NH_DEL:
3940 mlxsw_sp_nexthop4_type_fini(mlxsw_sp, nh);
3941 break;
3942 }
3943
3944 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
3945}
3946
3947static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
3948 struct mlxsw_sp_rif *rif)
3949{
3950 struct mlxsw_sp_nexthop *nh;
3951 bool removing;
3952
3953 list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) {
3954 switch (nh->type) {
3955 case MLXSW_SP_NEXTHOP_TYPE_ETH:
3956 removing = false;
3957 break;
3958 case MLXSW_SP_NEXTHOP_TYPE_IPIP:
3959 removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev);
3960 break;
3961 default:
3962 WARN_ON(1);
3963 continue;
3964 }
3965
3966 __mlxsw_sp_nexthop_neigh_update(nh, removing);
3967 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
3968 }
3969}
3970
3971static void mlxsw_sp_nexthop_rif_migrate(struct mlxsw_sp *mlxsw_sp,
3972 struct mlxsw_sp_rif *old_rif,
3973 struct mlxsw_sp_rif *new_rif)
3974{
3975 struct mlxsw_sp_nexthop *nh;
3976
3977 list_splice_init(&old_rif->nexthop_list, &new_rif->nexthop_list);
3978 list_for_each_entry(nh, &new_rif->nexthop_list, rif_list_node)
3979 nh->rif = new_rif;
3980 mlxsw_sp_nexthop_rif_update(mlxsw_sp, new_rif);
3981}
3982
3983static void mlxsw_sp_nexthop_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
3984 struct mlxsw_sp_rif *rif)
3985{
3986 struct mlxsw_sp_nexthop *nh, *tmp;
3987
3988 list_for_each_entry_safe(nh, tmp, &rif->nexthop_list, rif_list_node) {
3989 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
3990 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
3991 }
3992}
3993
3994static bool mlxsw_sp_fi_is_gateway(const struct mlxsw_sp *mlxsw_sp,
3995 struct fib_info *fi)
3996{
3997 const struct fib_nh *nh = fib_info_nh(fi, 0);
3998
3999 return nh->fib_nh_scope == RT_SCOPE_LINK ||
4000 mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, nh, NULL);
4001}
4002
4003static struct mlxsw_sp_nexthop_group *
4004mlxsw_sp_nexthop4_group_create(struct mlxsw_sp *mlxsw_sp, struct fib_info *fi)
4005{
4006 unsigned int nhs = fib_info_num_path(fi);
4007 struct mlxsw_sp_nexthop_group *nh_grp;
4008 struct mlxsw_sp_nexthop *nh;
4009 struct fib_nh *fib_nh;
4010 int i;
4011 int err;
4012
4013 nh_grp = kzalloc(struct_size(nh_grp, nexthops, nhs), GFP_KERNEL);
4014 if (!nh_grp)
4015 return ERR_PTR(-ENOMEM);
4016 nh_grp->priv = fi;
4017 INIT_LIST_HEAD(&nh_grp->fib_list);
4018 nh_grp->neigh_tbl = &arp_tbl;
4019
4020 nh_grp->gateway = mlxsw_sp_fi_is_gateway(mlxsw_sp, fi);
4021 nh_grp->count = nhs;
4022 fib_info_hold(fi);
4023 for (i = 0; i < nh_grp->count; i++) {
4024 nh = &nh_grp->nexthops[i];
4025 fib_nh = fib_info_nh(fi, i);
4026 err = mlxsw_sp_nexthop4_init(mlxsw_sp, nh_grp, nh, fib_nh);
4027 if (err)
4028 goto err_nexthop4_init;
4029 }
4030 err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
4031 if (err)
4032 goto err_nexthop_group_insert;
4033 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4034 return nh_grp;
4035
4036err_nexthop_group_insert:
4037err_nexthop4_init:
4038 for (i--; i >= 0; i--) {
4039 nh = &nh_grp->nexthops[i];
4040 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
4041 }
4042 fib_info_put(fi);
4043 kfree(nh_grp);
4044 return ERR_PTR(err);
4045}
4046
4047static void
4048mlxsw_sp_nexthop4_group_destroy(struct mlxsw_sp *mlxsw_sp,
4049 struct mlxsw_sp_nexthop_group *nh_grp)
4050{
4051 struct mlxsw_sp_nexthop *nh;
4052 int i;
4053
4054 mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
4055 for (i = 0; i < nh_grp->count; i++) {
4056 nh = &nh_grp->nexthops[i];
4057 mlxsw_sp_nexthop4_fini(mlxsw_sp, nh);
4058 }
4059 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
4060 WARN_ON_ONCE(nh_grp->adj_index_valid);
4061 fib_info_put(mlxsw_sp_nexthop4_group_fi(nh_grp));
4062 kfree(nh_grp);
4063}
4064
4065static int mlxsw_sp_nexthop4_group_get(struct mlxsw_sp *mlxsw_sp,
4066 struct mlxsw_sp_fib_entry *fib_entry,
4067 struct fib_info *fi)
4068{
4069 struct mlxsw_sp_nexthop_group *nh_grp;
4070
4071 nh_grp = mlxsw_sp_nexthop4_group_lookup(mlxsw_sp, fi);
4072 if (!nh_grp) {
4073 nh_grp = mlxsw_sp_nexthop4_group_create(mlxsw_sp, fi);
4074 if (IS_ERR(nh_grp))
4075 return PTR_ERR(nh_grp);
4076 }
4077 list_add_tail(&fib_entry->nexthop_group_node, &nh_grp->fib_list);
4078 fib_entry->nh_group = nh_grp;
4079 return 0;
4080}
4081
4082static void mlxsw_sp_nexthop4_group_put(struct mlxsw_sp *mlxsw_sp,
4083 struct mlxsw_sp_fib_entry *fib_entry)
4084{
4085 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
4086
4087 list_del(&fib_entry->nexthop_group_node);
4088 if (!list_empty(&nh_grp->fib_list))
4089 return;
4090 mlxsw_sp_nexthop4_group_destroy(mlxsw_sp, nh_grp);
4091}
4092
4093static bool
4094mlxsw_sp_fib4_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
4095{
4096 struct mlxsw_sp_fib4_entry *fib4_entry;
4097
4098 fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
4099 common);
4100 return !fib4_entry->tos;
4101}
4102
4103static bool
4104mlxsw_sp_fib_entry_should_offload(const struct mlxsw_sp_fib_entry *fib_entry)
4105{
4106 struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
4107
4108 switch (fib_entry->fib_node->fib->proto) {
4109 case MLXSW_SP_L3_PROTO_IPV4:
4110 if (!mlxsw_sp_fib4_entry_should_offload(fib_entry))
4111 return false;
4112 break;
4113 case MLXSW_SP_L3_PROTO_IPV6:
4114 break;
4115 }
4116
4117 switch (fib_entry->type) {
4118 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
4119 return !!nh_group->adj_index_valid;
4120 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
4121 return !!nh_group->nh_rif;
4122 case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
4123 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
4124 case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
4125 return true;
4126 default:
4127 return false;
4128 }
4129}
4130
4131static struct mlxsw_sp_nexthop *
4132mlxsw_sp_rt6_nexthop(struct mlxsw_sp_nexthop_group *nh_grp,
4133 const struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
4134{
4135 int i;
4136
4137 for (i = 0; i < nh_grp->count; i++) {
4138 struct mlxsw_sp_nexthop *nh = &nh_grp->nexthops[i];
4139 struct fib6_info *rt = mlxsw_sp_rt6->rt;
4140
4141 if (nh->rif && nh->rif->dev == rt->fib6_nh->fib_nh_dev &&
4142 ipv6_addr_equal((const struct in6_addr *) &nh->gw_addr,
4143 &rt->fib6_nh->fib_nh_gw6))
4144 return nh;
4145 continue;
4146 }
4147
4148 return NULL;
4149}
4150
4151static void
4152mlxsw_sp_fib4_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
4153 struct mlxsw_sp_fib_entry *fib_entry)
4154{
4155 struct fib_info *fi = mlxsw_sp_nexthop4_group_fi(fib_entry->nh_group);
4156 u32 *p_dst = (u32 *) fib_entry->fib_node->key.addr;
4157 int dst_len = fib_entry->fib_node->key.prefix_len;
4158 struct mlxsw_sp_fib4_entry *fib4_entry;
4159 struct fib_rt_info fri;
4160 bool should_offload;
4161
4162 should_offload = mlxsw_sp_fib_entry_should_offload(fib_entry);
4163 fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
4164 common);
4165 fri.fi = fi;
4166 fri.tb_id = fib4_entry->tb_id;
4167 fri.dst = cpu_to_be32(*p_dst);
4168 fri.dst_len = dst_len;
4169 fri.tos = fib4_entry->tos;
4170 fri.type = fib4_entry->type;
4171 fri.offload = should_offload;
4172 fri.trap = !should_offload;
4173 fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
4174}
4175
4176static void
4177mlxsw_sp_fib4_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
4178 struct mlxsw_sp_fib_entry *fib_entry)
4179{
4180 struct fib_info *fi = mlxsw_sp_nexthop4_group_fi(fib_entry->nh_group);
4181 u32 *p_dst = (u32 *) fib_entry->fib_node->key.addr;
4182 int dst_len = fib_entry->fib_node->key.prefix_len;
4183 struct mlxsw_sp_fib4_entry *fib4_entry;
4184 struct fib_rt_info fri;
4185
4186 fib4_entry = container_of(fib_entry, struct mlxsw_sp_fib4_entry,
4187 common);
4188 fri.fi = fi;
4189 fri.tb_id = fib4_entry->tb_id;
4190 fri.dst = cpu_to_be32(*p_dst);
4191 fri.dst_len = dst_len;
4192 fri.tos = fib4_entry->tos;
4193 fri.type = fib4_entry->type;
4194 fri.offload = false;
4195 fri.trap = false;
4196 fib_alias_hw_flags_set(mlxsw_sp_net(mlxsw_sp), &fri);
4197}
4198
4199static void
4200mlxsw_sp_fib6_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
4201 struct mlxsw_sp_fib_entry *fib_entry)
4202{
4203 struct mlxsw_sp_fib6_entry *fib6_entry;
4204 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4205 bool should_offload;
4206
4207 should_offload = mlxsw_sp_fib_entry_should_offload(fib_entry);
4208
4209
4210
4211
4212 fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
4213 common);
4214 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
4215 fib6_info_hw_flags_set(mlxsw_sp_rt6->rt, should_offload,
4216 !should_offload);
4217}
4218
4219static void
4220mlxsw_sp_fib6_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
4221 struct mlxsw_sp_fib_entry *fib_entry)
4222{
4223 struct mlxsw_sp_fib6_entry *fib6_entry;
4224 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
4225
4226 fib6_entry = container_of(fib_entry, struct mlxsw_sp_fib6_entry,
4227 common);
4228 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list)
4229 fib6_info_hw_flags_set(mlxsw_sp_rt6->rt, false, false);
4230}
4231
4232static void
4233mlxsw_sp_fib_entry_hw_flags_set(struct mlxsw_sp *mlxsw_sp,
4234 struct mlxsw_sp_fib_entry *fib_entry)
4235{
4236 switch (fib_entry->fib_node->fib->proto) {
4237 case MLXSW_SP_L3_PROTO_IPV4:
4238 mlxsw_sp_fib4_entry_hw_flags_set(mlxsw_sp, fib_entry);
4239 break;
4240 case MLXSW_SP_L3_PROTO_IPV6:
4241 mlxsw_sp_fib6_entry_hw_flags_set(mlxsw_sp, fib_entry);
4242 break;
4243 }
4244}
4245
4246static void
4247mlxsw_sp_fib_entry_hw_flags_clear(struct mlxsw_sp *mlxsw_sp,
4248 struct mlxsw_sp_fib_entry *fib_entry)
4249{
4250 switch (fib_entry->fib_node->fib->proto) {
4251 case MLXSW_SP_L3_PROTO_IPV4:
4252 mlxsw_sp_fib4_entry_hw_flags_clear(mlxsw_sp, fib_entry);
4253 break;
4254 case MLXSW_SP_L3_PROTO_IPV6:
4255 mlxsw_sp_fib6_entry_hw_flags_clear(mlxsw_sp, fib_entry);
4256 break;
4257 }
4258}
4259
4260static void
4261mlxsw_sp_fib_entry_hw_flags_refresh(struct mlxsw_sp *mlxsw_sp,
4262 struct mlxsw_sp_fib_entry *fib_entry,
4263 enum mlxsw_reg_ralue_op op)
4264{
4265 switch (op) {
4266 case MLXSW_REG_RALUE_OP_WRITE_WRITE:
4267 mlxsw_sp_fib_entry_hw_flags_set(mlxsw_sp, fib_entry);
4268 break;
4269 case MLXSW_REG_RALUE_OP_WRITE_DELETE:
4270 mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, fib_entry);
4271 break;
4272 default:
4273 break;
4274 }
4275}
4276
4277static void
4278mlxsw_sp_fib_entry_ralue_pack(char *ralue_pl,
4279 const struct mlxsw_sp_fib_entry *fib_entry,
4280 enum mlxsw_reg_ralue_op op)
4281{
4282 struct mlxsw_sp_fib *fib = fib_entry->fib_node->fib;
4283 enum mlxsw_reg_ralxx_protocol proto;
4284 u32 *p_dip;
4285
4286 proto = (enum mlxsw_reg_ralxx_protocol) fib->proto;
4287
4288 switch (fib->proto) {
4289 case MLXSW_SP_L3_PROTO_IPV4:
4290 p_dip = (u32 *) fib_entry->fib_node->key.addr;
4291 mlxsw_reg_ralue_pack4(ralue_pl, proto, op, fib->vr->id,
4292 fib_entry->fib_node->key.prefix_len,
4293 *p_dip);
4294 break;
4295 case MLXSW_SP_L3_PROTO_IPV6:
4296 mlxsw_reg_ralue_pack6(ralue_pl, proto, op, fib->vr->id,
4297 fib_entry->fib_node->key.prefix_len,
4298 fib_entry->fib_node->key.addr);
4299 break;
4300 }
4301}
4302
4303static int mlxsw_sp_adj_discard_write(struct mlxsw_sp *mlxsw_sp, u16 rif_index)
4304{
4305 enum mlxsw_reg_ratr_trap_action trap_action;
4306 char ratr_pl[MLXSW_REG_RATR_LEN];
4307 int err;
4308
4309 if (mlxsw_sp->router->adj_discard_index_valid)
4310 return 0;
4311
4312 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
4313 &mlxsw_sp->router->adj_discard_index);
4314 if (err)
4315 return err;
4316
4317 trap_action = MLXSW_REG_RATR_TRAP_ACTION_DISCARD_ERRORS;
4318 mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, true,
4319 MLXSW_REG_RATR_TYPE_ETHERNET,
4320 mlxsw_sp->router->adj_discard_index, rif_index);
4321 mlxsw_reg_ratr_trap_action_set(ratr_pl, trap_action);
4322 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
4323 if (err)
4324 goto err_ratr_write;
4325
4326 mlxsw_sp->router->adj_discard_index_valid = true;
4327
4328 return 0;
4329
4330err_ratr_write:
4331 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
4332 mlxsw_sp->router->adj_discard_index);
4333 return err;
4334}
4335
4336static int mlxsw_sp_fib_entry_op_remote(struct mlxsw_sp *mlxsw_sp,
4337 struct mlxsw_sp_fib_entry *fib_entry,
4338 enum mlxsw_reg_ralue_op op)
4339{
4340 struct mlxsw_sp_nexthop_group *nh_group = fib_entry->nh_group;
4341 char ralue_pl[MLXSW_REG_RALUE_LEN];
4342 enum mlxsw_reg_ralue_trap_action trap_action;
4343 u16 trap_id = 0;
4344 u32 adjacency_index = 0;
4345 u16 ecmp_size = 0;
4346 int err;
4347
4348
4349
4350
4351
4352 if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
4353 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
4354 adjacency_index = fib_entry->nh_group->adj_index;
4355 ecmp_size = fib_entry->nh_group->ecmp_size;
4356 } else if (!nh_group->adj_index_valid && nh_group->count &&
4357 nh_group->nh_rif) {
4358 err = mlxsw_sp_adj_discard_write(mlxsw_sp,
4359 nh_group->nh_rif->rif_index);
4360 if (err)
4361 return err;
4362 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
4363 adjacency_index = mlxsw_sp->router->adj_discard_index;
4364 ecmp_size = 1;
4365 } else {
4366 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
4367 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
4368 }
4369
4370 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4371 mlxsw_reg_ralue_act_remote_pack(ralue_pl, trap_action, trap_id,
4372 adjacency_index, ecmp_size);
4373 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4374}
4375
4376static int mlxsw_sp_fib_entry_op_local(struct mlxsw_sp *mlxsw_sp,
4377 struct mlxsw_sp_fib_entry *fib_entry,
4378 enum mlxsw_reg_ralue_op op)
4379{
4380 struct mlxsw_sp_rif *rif = fib_entry->nh_group->nh_rif;
4381 enum mlxsw_reg_ralue_trap_action trap_action;
4382 char ralue_pl[MLXSW_REG_RALUE_LEN];
4383 u16 trap_id = 0;
4384 u16 rif_index = 0;
4385
4386 if (mlxsw_sp_fib_entry_should_offload(fib_entry)) {
4387 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_NOP;
4388 rif_index = rif->rif_index;
4389 } else {
4390 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
4391 trap_id = MLXSW_TRAP_ID_RTR_INGRESS0;
4392 }
4393
4394 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4395 mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id,
4396 rif_index);
4397 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4398}
4399
4400static int mlxsw_sp_fib_entry_op_trap(struct mlxsw_sp *mlxsw_sp,
4401 struct mlxsw_sp_fib_entry *fib_entry,
4402 enum mlxsw_reg_ralue_op op)
4403{
4404 char ralue_pl[MLXSW_REG_RALUE_LEN];
4405
4406 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4407 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
4408 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4409}
4410
4411static int mlxsw_sp_fib_entry_op_blackhole(struct mlxsw_sp *mlxsw_sp,
4412 struct mlxsw_sp_fib_entry *fib_entry,
4413 enum mlxsw_reg_ralue_op op)
4414{
4415 enum mlxsw_reg_ralue_trap_action trap_action;
4416 char ralue_pl[MLXSW_REG_RALUE_LEN];
4417
4418 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_DISCARD_ERROR;
4419 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4420 mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, 0, 0);
4421 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4422}
4423
4424static int
4425mlxsw_sp_fib_entry_op_unreachable(struct mlxsw_sp *mlxsw_sp,
4426 struct mlxsw_sp_fib_entry *fib_entry,
4427 enum mlxsw_reg_ralue_op op)
4428{
4429 enum mlxsw_reg_ralue_trap_action trap_action;
4430 char ralue_pl[MLXSW_REG_RALUE_LEN];
4431 u16 trap_id;
4432
4433 trap_action = MLXSW_REG_RALUE_TRAP_ACTION_TRAP;
4434 trap_id = MLXSW_TRAP_ID_RTR_INGRESS1;
4435
4436 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4437 mlxsw_reg_ralue_act_local_pack(ralue_pl, trap_action, trap_id, 0);
4438 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4439}
4440
4441static int
4442mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
4443 struct mlxsw_sp_fib_entry *fib_entry,
4444 enum mlxsw_reg_ralue_op op)
4445{
4446 struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry;
4447 const struct mlxsw_sp_ipip_ops *ipip_ops;
4448
4449 if (WARN_ON(!ipip_entry))
4450 return -EINVAL;
4451
4452 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
4453 return ipip_ops->fib_entry_op(mlxsw_sp, ipip_entry, op,
4454 fib_entry->decap.tunnel_index);
4455}
4456
4457static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp *mlxsw_sp,
4458 struct mlxsw_sp_fib_entry *fib_entry,
4459 enum mlxsw_reg_ralue_op op)
4460{
4461 char ralue_pl[MLXSW_REG_RALUE_LEN];
4462
4463 mlxsw_sp_fib_entry_ralue_pack(ralue_pl, fib_entry, op);
4464 mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl,
4465 fib_entry->decap.tunnel_index);
4466 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl);
4467}
4468
4469static int __mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
4470 struct mlxsw_sp_fib_entry *fib_entry,
4471 enum mlxsw_reg_ralue_op op)
4472{
4473 switch (fib_entry->type) {
4474 case MLXSW_SP_FIB_ENTRY_TYPE_REMOTE:
4475 return mlxsw_sp_fib_entry_op_remote(mlxsw_sp, fib_entry, op);
4476 case MLXSW_SP_FIB_ENTRY_TYPE_LOCAL:
4477 return mlxsw_sp_fib_entry_op_local(mlxsw_sp, fib_entry, op);
4478 case MLXSW_SP_FIB_ENTRY_TYPE_TRAP:
4479 return mlxsw_sp_fib_entry_op_trap(mlxsw_sp, fib_entry, op);
4480 case MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE:
4481 return mlxsw_sp_fib_entry_op_blackhole(mlxsw_sp, fib_entry, op);
4482 case MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE:
4483 return mlxsw_sp_fib_entry_op_unreachable(mlxsw_sp, fib_entry,
4484 op);
4485 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
4486 return mlxsw_sp_fib_entry_op_ipip_decap(mlxsw_sp,
4487 fib_entry, op);
4488 case MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP:
4489 return mlxsw_sp_fib_entry_op_nve_decap(mlxsw_sp, fib_entry, op);
4490 }
4491 return -EINVAL;
4492}
4493
4494static int mlxsw_sp_fib_entry_op(struct mlxsw_sp *mlxsw_sp,
4495 struct mlxsw_sp_fib_entry *fib_entry,
4496 enum mlxsw_reg_ralue_op op)
4497{
4498 int err = __mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry, op);
4499
4500 if (err)
4501 return err;
4502
4503 mlxsw_sp_fib_entry_hw_flags_refresh(mlxsw_sp, fib_entry, op);
4504
4505 return err;
4506}
4507
4508static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
4509 struct mlxsw_sp_fib_entry *fib_entry)
4510{
4511 return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
4512 MLXSW_REG_RALUE_OP_WRITE_WRITE);
4513}
4514
4515static int mlxsw_sp_fib_entry_del(struct mlxsw_sp *mlxsw_sp,
4516 struct mlxsw_sp_fib_entry *fib_entry)
4517{
4518 return mlxsw_sp_fib_entry_op(mlxsw_sp, fib_entry,
4519 MLXSW_REG_RALUE_OP_WRITE_DELETE);
4520}
4521
4522static int
4523mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
4524 const struct fib_entry_notifier_info *fen_info,
4525 struct mlxsw_sp_fib_entry *fib_entry)
4526{
4527 struct net_device *dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev;
4528 union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) };
4529 struct mlxsw_sp_router *router = mlxsw_sp->router;
4530 u32 tb_id = mlxsw_sp_fix_tb_id(fen_info->tb_id);
4531 struct mlxsw_sp_ipip_entry *ipip_entry;
4532 struct fib_info *fi = fen_info->fi;
4533
4534 switch (fen_info->type) {
4535 case RTN_LOCAL:
4536 ipip_entry = mlxsw_sp_ipip_entry_find_by_decap(mlxsw_sp, dev,
4537 MLXSW_SP_L3_PROTO_IPV4, dip);
4538 if (ipip_entry && ipip_entry->ol_dev->flags & IFF_UP) {
4539 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
4540 return mlxsw_sp_fib_entry_decap_init(mlxsw_sp,
4541 fib_entry,
4542 ipip_entry);
4543 }
4544 if (mlxsw_sp_router_nve_is_decap(mlxsw_sp, tb_id,
4545 MLXSW_SP_L3_PROTO_IPV4,
4546 &dip)) {
4547 u32 tunnel_index;
4548
4549 tunnel_index = router->nve_decap_config.tunnel_index;
4550 fib_entry->decap.tunnel_index = tunnel_index;
4551 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
4552 return 0;
4553 }
4554
4555 case RTN_BROADCAST:
4556 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
4557 return 0;
4558 case RTN_BLACKHOLE:
4559 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
4560 return 0;
4561 case RTN_UNREACHABLE:
4562 case RTN_PROHIBIT:
4563
4564
4565
4566
4567 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
4568 return 0;
4569 case RTN_UNICAST:
4570 if (mlxsw_sp_fi_is_gateway(mlxsw_sp, fi))
4571 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
4572 else
4573 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
4574 return 0;
4575 default:
4576 return -EINVAL;
4577 }
4578}
4579
4580static void
4581mlxsw_sp_fib4_entry_type_unset(struct mlxsw_sp *mlxsw_sp,
4582 struct mlxsw_sp_fib_entry *fib_entry)
4583{
4584 switch (fib_entry->type) {
4585 case MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP:
4586 mlxsw_sp_fib_entry_decap_fini(mlxsw_sp, fib_entry);
4587 break;
4588 default:
4589 break;
4590 }
4591}
4592
4593static struct mlxsw_sp_fib4_entry *
4594mlxsw_sp_fib4_entry_create(struct mlxsw_sp *mlxsw_sp,
4595 struct mlxsw_sp_fib_node *fib_node,
4596 const struct fib_entry_notifier_info *fen_info)
4597{
4598 struct mlxsw_sp_fib4_entry *fib4_entry;
4599 struct mlxsw_sp_fib_entry *fib_entry;
4600 int err;
4601
4602 fib4_entry = kzalloc(sizeof(*fib4_entry), GFP_KERNEL);
4603 if (!fib4_entry)
4604 return ERR_PTR(-ENOMEM);
4605 fib_entry = &fib4_entry->common;
4606
4607 err = mlxsw_sp_fib4_entry_type_set(mlxsw_sp, fen_info, fib_entry);
4608 if (err)
4609 goto err_fib4_entry_type_set;
4610
4611 err = mlxsw_sp_nexthop4_group_get(mlxsw_sp, fib_entry, fen_info->fi);
4612 if (err)
4613 goto err_nexthop4_group_get;
4614
4615 fib4_entry->prio = fen_info->fi->fib_priority;
4616 fib4_entry->tb_id = fen_info->tb_id;
4617 fib4_entry->type = fen_info->type;
4618 fib4_entry->tos = fen_info->tos;
4619
4620 fib_entry->fib_node = fib_node;
4621
4622 return fib4_entry;
4623
4624err_nexthop4_group_get:
4625 mlxsw_sp_fib4_entry_type_unset(mlxsw_sp, fib_entry);
4626err_fib4_entry_type_set:
4627 kfree(fib4_entry);
4628 return ERR_PTR(err);
4629}
4630
4631static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
4632 struct mlxsw_sp_fib4_entry *fib4_entry)
4633{
4634 mlxsw_sp_nexthop4_group_put(mlxsw_sp, &fib4_entry->common);
4635 mlxsw_sp_fib4_entry_type_unset(mlxsw_sp, &fib4_entry->common);
4636 kfree(fib4_entry);
4637}
4638
4639static struct mlxsw_sp_fib4_entry *
4640mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
4641 const struct fib_entry_notifier_info *fen_info)
4642{
4643 struct mlxsw_sp_fib4_entry *fib4_entry;
4644 struct mlxsw_sp_fib_node *fib_node;
4645 struct mlxsw_sp_fib *fib;
4646 struct mlxsw_sp_vr *vr;
4647
4648 vr = mlxsw_sp_vr_find(mlxsw_sp, fen_info->tb_id);
4649 if (!vr)
4650 return NULL;
4651 fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV4);
4652
4653 fib_node = mlxsw_sp_fib_node_lookup(fib, &fen_info->dst,
4654 sizeof(fen_info->dst),
4655 fen_info->dst_len);
4656 if (!fib_node)
4657 return NULL;
4658
4659 fib4_entry = container_of(fib_node->fib_entry,
4660 struct mlxsw_sp_fib4_entry, common);
4661 if (fib4_entry->tb_id == fen_info->tb_id &&
4662 fib4_entry->tos == fen_info->tos &&
4663 fib4_entry->type == fen_info->type &&
4664 mlxsw_sp_nexthop4_group_fi(fib4_entry->common.nh_group) ==
4665 fen_info->fi)
4666 return fib4_entry;
4667
4668 return NULL;
4669}
4670
4671static const struct rhashtable_params mlxsw_sp_fib_ht_params = {
4672 .key_offset = offsetof(struct mlxsw_sp_fib_node, key),
4673 .head_offset = offsetof(struct mlxsw_sp_fib_node, ht_node),
4674 .key_len = sizeof(struct mlxsw_sp_fib_key),
4675 .automatic_shrinking = true,
4676};
4677
4678static int mlxsw_sp_fib_node_insert(struct mlxsw_sp_fib *fib,
4679 struct mlxsw_sp_fib_node *fib_node)
4680{
4681 return rhashtable_insert_fast(&fib->ht, &fib_node->ht_node,
4682 mlxsw_sp_fib_ht_params);
4683}
4684
4685static void mlxsw_sp_fib_node_remove(struct mlxsw_sp_fib *fib,
4686 struct mlxsw_sp_fib_node *fib_node)
4687{
4688 rhashtable_remove_fast(&fib->ht, &fib_node->ht_node,
4689 mlxsw_sp_fib_ht_params);
4690}
4691
4692static struct mlxsw_sp_fib_node *
4693mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
4694 size_t addr_len, unsigned char prefix_len)
4695{
4696 struct mlxsw_sp_fib_key key;
4697
4698 memset(&key, 0, sizeof(key));
4699 memcpy(key.addr, addr, addr_len);
4700 key.prefix_len = prefix_len;
4701 return rhashtable_lookup_fast(&fib->ht, &key, mlxsw_sp_fib_ht_params);
4702}
4703
4704static struct mlxsw_sp_fib_node *
4705mlxsw_sp_fib_node_create(struct mlxsw_sp_fib *fib, const void *addr,
4706 size_t addr_len, unsigned char prefix_len)
4707{
4708 struct mlxsw_sp_fib_node *fib_node;
4709
4710 fib_node = kzalloc(sizeof(*fib_node), GFP_KERNEL);
4711 if (!fib_node)
4712 return NULL;
4713
4714 list_add(&fib_node->list, &fib->node_list);
4715 memcpy(fib_node->key.addr, addr, addr_len);
4716 fib_node->key.prefix_len = prefix_len;
4717
4718 return fib_node;
4719}
4720
4721static void mlxsw_sp_fib_node_destroy(struct mlxsw_sp_fib_node *fib_node)
4722{
4723 list_del(&fib_node->list);
4724 kfree(fib_node);
4725}
4726
4727static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp,
4728 struct mlxsw_sp_fib_node *fib_node)
4729{
4730 struct mlxsw_sp_prefix_usage req_prefix_usage;
4731 struct mlxsw_sp_fib *fib = fib_node->fib;
4732 struct mlxsw_sp_lpm_tree *lpm_tree;
4733 int err;
4734
4735 lpm_tree = mlxsw_sp->router->lpm.proto_trees[fib->proto];
4736 if (lpm_tree->prefix_ref_count[fib_node->key.prefix_len] != 0)
4737 goto out;
4738
4739 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &lpm_tree->prefix_usage);
4740 mlxsw_sp_prefix_usage_set(&req_prefix_usage, fib_node->key.prefix_len);
4741 lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
4742 fib->proto);
4743 if (IS_ERR(lpm_tree))
4744 return PTR_ERR(lpm_tree);
4745
4746 err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
4747 if (err)
4748 goto err_lpm_tree_replace;
4749
4750out:
4751 lpm_tree->prefix_ref_count[fib_node->key.prefix_len]++;
4752 return 0;
4753
4754err_lpm_tree_replace:
4755 mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
4756 return err;
4757}
4758
4759static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp,
4760 struct mlxsw_sp_fib_node *fib_node)
4761{
4762 struct mlxsw_sp_lpm_tree *lpm_tree = fib_node->fib->lpm_tree;
4763 struct mlxsw_sp_prefix_usage req_prefix_usage;
4764 struct mlxsw_sp_fib *fib = fib_node->fib;
4765 int err;
4766
4767 if (--lpm_tree->prefix_ref_count[fib_node->key.prefix_len] != 0)
4768 return;
4769
4770
4771
4772 mlxsw_sp_prefix_usage_cpy(&req_prefix_usage, &lpm_tree->prefix_usage);
4773 mlxsw_sp_prefix_usage_clear(&req_prefix_usage,
4774 fib_node->key.prefix_len);
4775 lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage,
4776 fib->proto);
4777 if (IS_ERR(lpm_tree))
4778 return;
4779
4780 err = mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree);
4781 if (err)
4782 goto err_lpm_tree_replace;
4783
4784 return;
4785
4786err_lpm_tree_replace:
4787 mlxsw_sp_lpm_tree_put(mlxsw_sp, lpm_tree);
4788}
4789
4790static int mlxsw_sp_fib_node_init(struct mlxsw_sp *mlxsw_sp,
4791 struct mlxsw_sp_fib_node *fib_node,
4792 struct mlxsw_sp_fib *fib)
4793{
4794 int err;
4795
4796 err = mlxsw_sp_fib_node_insert(fib, fib_node);
4797 if (err)
4798 return err;
4799 fib_node->fib = fib;
4800
4801 err = mlxsw_sp_fib_lpm_tree_link(mlxsw_sp, fib_node);
4802 if (err)
4803 goto err_fib_lpm_tree_link;
4804
4805 return 0;
4806
4807err_fib_lpm_tree_link:
4808 fib_node->fib = NULL;
4809 mlxsw_sp_fib_node_remove(fib, fib_node);
4810 return err;
4811}
4812
4813static void mlxsw_sp_fib_node_fini(struct mlxsw_sp *mlxsw_sp,
4814 struct mlxsw_sp_fib_node *fib_node)
4815{
4816 struct mlxsw_sp_fib *fib = fib_node->fib;
4817
4818 mlxsw_sp_fib_lpm_tree_unlink(mlxsw_sp, fib_node);
4819 fib_node->fib = NULL;
4820 mlxsw_sp_fib_node_remove(fib, fib_node);
4821}
4822
4823static struct mlxsw_sp_fib_node *
4824mlxsw_sp_fib_node_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id, const void *addr,
4825 size_t addr_len, unsigned char prefix_len,
4826 enum mlxsw_sp_l3proto proto)
4827{
4828 struct mlxsw_sp_fib_node *fib_node;
4829 struct mlxsw_sp_fib *fib;
4830 struct mlxsw_sp_vr *vr;
4831 int err;
4832
4833 vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, NULL);
4834 if (IS_ERR(vr))
4835 return ERR_CAST(vr);
4836 fib = mlxsw_sp_vr_fib(vr, proto);
4837
4838 fib_node = mlxsw_sp_fib_node_lookup(fib, addr, addr_len, prefix_len);
4839 if (fib_node)
4840 return fib_node;
4841
4842 fib_node = mlxsw_sp_fib_node_create(fib, addr, addr_len, prefix_len);
4843 if (!fib_node) {
4844 err = -ENOMEM;
4845 goto err_fib_node_create;
4846 }
4847
4848 err = mlxsw_sp_fib_node_init(mlxsw_sp, fib_node, fib);
4849 if (err)
4850 goto err_fib_node_init;
4851
4852 return fib_node;
4853
4854err_fib_node_init:
4855 mlxsw_sp_fib_node_destroy(fib_node);
4856err_fib_node_create:
4857 mlxsw_sp_vr_put(mlxsw_sp, vr);
4858 return ERR_PTR(err);
4859}
4860
4861static void mlxsw_sp_fib_node_put(struct mlxsw_sp *mlxsw_sp,
4862 struct mlxsw_sp_fib_node *fib_node)
4863{
4864 struct mlxsw_sp_vr *vr = fib_node->fib->vr;
4865
4866 if (fib_node->fib_entry)
4867 return;
4868 mlxsw_sp_fib_node_fini(mlxsw_sp, fib_node);
4869 mlxsw_sp_fib_node_destroy(fib_node);
4870 mlxsw_sp_vr_put(mlxsw_sp, vr);
4871}
4872
4873static int mlxsw_sp_fib_node_entry_link(struct mlxsw_sp *mlxsw_sp,
4874 struct mlxsw_sp_fib_entry *fib_entry)
4875{
4876 struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
4877 int err;
4878
4879 fib_node->fib_entry = fib_entry;
4880
4881 err = mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
4882 if (err)
4883 goto err_fib_entry_update;
4884
4885 return 0;
4886
4887err_fib_entry_update:
4888 fib_node->fib_entry = NULL;
4889 return err;
4890}
4891
4892static void
4893mlxsw_sp_fib_node_entry_unlink(struct mlxsw_sp *mlxsw_sp,
4894 struct mlxsw_sp_fib_entry *fib_entry)
4895{
4896 struct mlxsw_sp_fib_node *fib_node = fib_entry->fib_node;
4897
4898 mlxsw_sp_fib_entry_del(mlxsw_sp, fib_entry);
4899 fib_node->fib_entry = NULL;
4900}
4901
4902static bool mlxsw_sp_fib4_allow_replace(struct mlxsw_sp_fib4_entry *fib4_entry)
4903{
4904 struct mlxsw_sp_fib_node *fib_node = fib4_entry->common.fib_node;
4905 struct mlxsw_sp_fib4_entry *fib4_replaced;
4906
4907 if (!fib_node->fib_entry)
4908 return true;
4909
4910 fib4_replaced = container_of(fib_node->fib_entry,
4911 struct mlxsw_sp_fib4_entry, common);
4912 if (fib4_entry->tb_id == RT_TABLE_MAIN &&
4913 fib4_replaced->tb_id == RT_TABLE_LOCAL)
4914 return false;
4915
4916 return true;
4917}
4918
4919static int
4920mlxsw_sp_router_fib4_replace(struct mlxsw_sp *mlxsw_sp,
4921 const struct fib_entry_notifier_info *fen_info)
4922{
4923 struct mlxsw_sp_fib4_entry *fib4_entry, *fib4_replaced;
4924 struct mlxsw_sp_fib_entry *replaced;
4925 struct mlxsw_sp_fib_node *fib_node;
4926 int err;
4927
4928 if (mlxsw_sp->router->aborted)
4929 return 0;
4930
4931 fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, fen_info->tb_id,
4932 &fen_info->dst, sizeof(fen_info->dst),
4933 fen_info->dst_len,
4934 MLXSW_SP_L3_PROTO_IPV4);
4935 if (IS_ERR(fib_node)) {
4936 dev_warn(mlxsw_sp->bus_info->dev, "Failed to get FIB node\n");
4937 return PTR_ERR(fib_node);
4938 }
4939
4940 fib4_entry = mlxsw_sp_fib4_entry_create(mlxsw_sp, fib_node, fen_info);
4941 if (IS_ERR(fib4_entry)) {
4942 dev_warn(mlxsw_sp->bus_info->dev, "Failed to create FIB entry\n");
4943 err = PTR_ERR(fib4_entry);
4944 goto err_fib4_entry_create;
4945 }
4946
4947 if (!mlxsw_sp_fib4_allow_replace(fib4_entry)) {
4948 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4949 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4950 return 0;
4951 }
4952
4953 replaced = fib_node->fib_entry;
4954 err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib4_entry->common);
4955 if (err) {
4956 dev_warn(mlxsw_sp->bus_info->dev, "Failed to link FIB entry to node\n");
4957 goto err_fib_node_entry_link;
4958 }
4959
4960
4961 if (!replaced)
4962 return 0;
4963
4964 mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, replaced);
4965 fib4_replaced = container_of(replaced, struct mlxsw_sp_fib4_entry,
4966 common);
4967 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_replaced);
4968
4969 return 0;
4970
4971err_fib_node_entry_link:
4972 fib_node->fib_entry = replaced;
4973 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4974err_fib4_entry_create:
4975 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4976 return err;
4977}
4978
4979static void mlxsw_sp_router_fib4_del(struct mlxsw_sp *mlxsw_sp,
4980 struct fib_entry_notifier_info *fen_info)
4981{
4982 struct mlxsw_sp_fib4_entry *fib4_entry;
4983 struct mlxsw_sp_fib_node *fib_node;
4984
4985 if (mlxsw_sp->router->aborted)
4986 return;
4987
4988 fib4_entry = mlxsw_sp_fib4_entry_lookup(mlxsw_sp, fen_info);
4989 if (!fib4_entry)
4990 return;
4991 fib_node = fib4_entry->common.fib_node;
4992
4993 mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib4_entry->common);
4994 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
4995 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
4996}
4997
4998static bool mlxsw_sp_fib6_rt_should_ignore(const struct fib6_info *rt)
4999{
5000
5001
5002
5003
5004 if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_LINKLOCAL)
5005 return true;
5006
5007
5008
5009
5010 if (ipv6_addr_type(&rt->fib6_dst.addr) & IPV6_ADDR_MULTICAST)
5011 return true;
5012
5013
5014 if (rt->fib6_flags & RTF_CACHE)
5015 return true;
5016
5017 return false;
5018}
5019
5020static struct mlxsw_sp_rt6 *mlxsw_sp_rt6_create(struct fib6_info *rt)
5021{
5022 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5023
5024 mlxsw_sp_rt6 = kzalloc(sizeof(*mlxsw_sp_rt6), GFP_KERNEL);
5025 if (!mlxsw_sp_rt6)
5026 return ERR_PTR(-ENOMEM);
5027
5028
5029
5030
5031
5032 mlxsw_sp_rt6->rt = rt;
5033 fib6_info_hold(rt);
5034
5035 return mlxsw_sp_rt6;
5036}
5037
5038#if IS_ENABLED(CONFIG_IPV6)
5039static void mlxsw_sp_rt6_release(struct fib6_info *rt)
5040{
5041 fib6_info_release(rt);
5042}
5043#else
5044static void mlxsw_sp_rt6_release(struct fib6_info *rt)
5045{
5046}
5047#endif
5048
5049static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
5050{
5051 struct fib6_nh *fib6_nh = mlxsw_sp_rt6->rt->fib6_nh;
5052
5053 fib6_nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
5054 mlxsw_sp_rt6_release(mlxsw_sp_rt6->rt);
5055 kfree(mlxsw_sp_rt6);
5056}
5057
5058static struct fib6_info *
5059mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
5060{
5061 return list_first_entry(&fib6_entry->rt6_list, struct mlxsw_sp_rt6,
5062 list)->rt;
5063}
5064
5065static struct mlxsw_sp_rt6 *
5066mlxsw_sp_fib6_entry_rt_find(const struct mlxsw_sp_fib6_entry *fib6_entry,
5067 const struct fib6_info *rt)
5068{
5069 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5070
5071 list_for_each_entry(mlxsw_sp_rt6, &fib6_entry->rt6_list, list) {
5072 if (mlxsw_sp_rt6->rt == rt)
5073 return mlxsw_sp_rt6;
5074 }
5075
5076 return NULL;
5077}
5078
5079static bool mlxsw_sp_nexthop6_ipip_type(const struct mlxsw_sp *mlxsw_sp,
5080 const struct fib6_info *rt,
5081 enum mlxsw_sp_ipip_type *ret)
5082{
5083 return rt->fib6_nh->fib_nh_dev &&
5084 mlxsw_sp_netdev_ipip_type(mlxsw_sp, rt->fib6_nh->fib_nh_dev, ret);
5085}
5086
5087static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
5088 struct mlxsw_sp_nexthop_group *nh_grp,
5089 struct mlxsw_sp_nexthop *nh,
5090 const struct fib6_info *rt)
5091{
5092 const struct mlxsw_sp_ipip_ops *ipip_ops;
5093 struct mlxsw_sp_ipip_entry *ipip_entry;
5094 struct net_device *dev = rt->fib6_nh->fib_nh_dev;
5095 struct mlxsw_sp_rif *rif;
5096 int err;
5097
5098 ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, dev);
5099 if (ipip_entry) {
5100 ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
5101 if (ipip_ops->can_offload(mlxsw_sp, dev,
5102 MLXSW_SP_L3_PROTO_IPV6)) {
5103 nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
5104 mlxsw_sp_nexthop_ipip_init(mlxsw_sp, nh, ipip_entry);
5105 return 0;
5106 }
5107 }
5108
5109 nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
5110 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
5111 if (!rif)
5112 return 0;
5113 mlxsw_sp_nexthop_rif_init(nh, rif);
5114
5115 err = mlxsw_sp_nexthop_neigh_init(mlxsw_sp, nh);
5116 if (err)
5117 goto err_nexthop_neigh_init;
5118
5119 return 0;
5120
5121err_nexthop_neigh_init:
5122 mlxsw_sp_nexthop_rif_fini(nh);
5123 return err;
5124}
5125
5126static void mlxsw_sp_nexthop6_type_fini(struct mlxsw_sp *mlxsw_sp,
5127 struct mlxsw_sp_nexthop *nh)
5128{
5129 mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
5130}
5131
5132static int mlxsw_sp_nexthop6_init(struct mlxsw_sp *mlxsw_sp,
5133 struct mlxsw_sp_nexthop_group *nh_grp,
5134 struct mlxsw_sp_nexthop *nh,
5135 const struct fib6_info *rt)
5136{
5137 struct net_device *dev = rt->fib6_nh->fib_nh_dev;
5138
5139 nh->nh_grp = nh_grp;
5140 nh->nh_weight = rt->fib6_nh->fib_nh_weight;
5141 memcpy(&nh->gw_addr, &rt->fib6_nh->fib_nh_gw6, sizeof(nh->gw_addr));
5142 mlxsw_sp_nexthop_counter_alloc(mlxsw_sp, nh);
5143
5144 list_add_tail(&nh->router_list_node, &mlxsw_sp->router->nexthop_list);
5145
5146 if (!dev)
5147 return 0;
5148 nh->ifindex = dev->ifindex;
5149
5150 return mlxsw_sp_nexthop6_type_init(mlxsw_sp, nh_grp, nh, rt);
5151}
5152
5153static void mlxsw_sp_nexthop6_fini(struct mlxsw_sp *mlxsw_sp,
5154 struct mlxsw_sp_nexthop *nh)
5155{
5156 mlxsw_sp_nexthop6_type_fini(mlxsw_sp, nh);
5157 list_del(&nh->router_list_node);
5158 mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
5159}
5160
5161static bool mlxsw_sp_rt6_is_gateway(const struct mlxsw_sp *mlxsw_sp,
5162 const struct fib6_info *rt)
5163{
5164 return rt->fib6_nh->fib_nh_gw_family ||
5165 mlxsw_sp_nexthop6_ipip_type(mlxsw_sp, rt, NULL);
5166}
5167
5168static struct mlxsw_sp_nexthop_group *
5169mlxsw_sp_nexthop6_group_create(struct mlxsw_sp *mlxsw_sp,
5170 struct mlxsw_sp_fib6_entry *fib6_entry)
5171{
5172 struct mlxsw_sp_nexthop_group *nh_grp;
5173 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5174 struct mlxsw_sp_nexthop *nh;
5175 int i = 0;
5176 int err;
5177
5178 nh_grp = kzalloc(struct_size(nh_grp, nexthops, fib6_entry->nrt6),
5179 GFP_KERNEL);
5180 if (!nh_grp)
5181 return ERR_PTR(-ENOMEM);
5182 INIT_LIST_HEAD(&nh_grp->fib_list);
5183#if IS_ENABLED(CONFIG_IPV6)
5184 nh_grp->neigh_tbl = &nd_tbl;
5185#endif
5186 mlxsw_sp_rt6 = list_first_entry(&fib6_entry->rt6_list,
5187 struct mlxsw_sp_rt6, list);
5188 nh_grp->gateway = mlxsw_sp_rt6_is_gateway(mlxsw_sp, mlxsw_sp_rt6->rt);
5189 nh_grp->count = fib6_entry->nrt6;
5190 for (i = 0; i < nh_grp->count; i++) {
5191 struct fib6_info *rt = mlxsw_sp_rt6->rt;
5192
5193 nh = &nh_grp->nexthops[i];
5194 err = mlxsw_sp_nexthop6_init(mlxsw_sp, nh_grp, nh, rt);
5195 if (err)
5196 goto err_nexthop6_init;
5197 mlxsw_sp_rt6 = list_next_entry(mlxsw_sp_rt6, list);
5198 }
5199
5200 err = mlxsw_sp_nexthop_group_insert(mlxsw_sp, nh_grp);
5201 if (err)
5202 goto err_nexthop_group_insert;
5203
5204 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
5205 return nh_grp;
5206
5207err_nexthop_group_insert:
5208err_nexthop6_init:
5209 for (i--; i >= 0; i--) {
5210 nh = &nh_grp->nexthops[i];
5211 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
5212 }
5213 kfree(nh_grp);
5214 return ERR_PTR(err);
5215}
5216
5217static void
5218mlxsw_sp_nexthop6_group_destroy(struct mlxsw_sp *mlxsw_sp,
5219 struct mlxsw_sp_nexthop_group *nh_grp)
5220{
5221 struct mlxsw_sp_nexthop *nh;
5222 int i = nh_grp->count;
5223
5224 mlxsw_sp_nexthop_group_remove(mlxsw_sp, nh_grp);
5225 for (i--; i >= 0; i--) {
5226 nh = &nh_grp->nexthops[i];
5227 mlxsw_sp_nexthop6_fini(mlxsw_sp, nh);
5228 }
5229 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
5230 WARN_ON(nh_grp->adj_index_valid);
5231 kfree(nh_grp);
5232}
5233
5234static int mlxsw_sp_nexthop6_group_get(struct mlxsw_sp *mlxsw_sp,
5235 struct mlxsw_sp_fib6_entry *fib6_entry)
5236{
5237 struct mlxsw_sp_nexthop_group *nh_grp;
5238
5239 nh_grp = mlxsw_sp_nexthop6_group_lookup(mlxsw_sp, fib6_entry);
5240 if (!nh_grp) {
5241 nh_grp = mlxsw_sp_nexthop6_group_create(mlxsw_sp, fib6_entry);
5242 if (IS_ERR(nh_grp))
5243 return PTR_ERR(nh_grp);
5244 }
5245
5246 list_add_tail(&fib6_entry->common.nexthop_group_node,
5247 &nh_grp->fib_list);
5248 fib6_entry->common.nh_group = nh_grp;
5249
5250
5251
5252
5253 __mlxsw_sp_nexthop6_group_offload_refresh(nh_grp, fib6_entry);
5254
5255 return 0;
5256}
5257
5258static void mlxsw_sp_nexthop6_group_put(struct mlxsw_sp *mlxsw_sp,
5259 struct mlxsw_sp_fib_entry *fib_entry)
5260{
5261 struct mlxsw_sp_nexthop_group *nh_grp = fib_entry->nh_group;
5262
5263 list_del(&fib_entry->nexthop_group_node);
5264 if (!list_empty(&nh_grp->fib_list))
5265 return;
5266 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, nh_grp);
5267}
5268
5269static int
5270mlxsw_sp_nexthop6_group_update(struct mlxsw_sp *mlxsw_sp,
5271 struct mlxsw_sp_fib6_entry *fib6_entry)
5272{
5273 struct mlxsw_sp_nexthop_group *old_nh_grp = fib6_entry->common.nh_group;
5274 int err;
5275
5276 fib6_entry->common.nh_group = NULL;
5277 list_del(&fib6_entry->common.nexthop_group_node);
5278
5279 err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
5280 if (err)
5281 goto err_nexthop6_group_get;
5282
5283
5284
5285
5286
5287 err = mlxsw_sp_fib_entry_update(mlxsw_sp, &fib6_entry->common);
5288 if (err)
5289 goto err_fib_entry_update;
5290
5291 if (list_empty(&old_nh_grp->fib_list))
5292 mlxsw_sp_nexthop6_group_destroy(mlxsw_sp, old_nh_grp);
5293
5294 return 0;
5295
5296err_fib_entry_update:
5297 mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
5298err_nexthop6_group_get:
5299 list_add_tail(&fib6_entry->common.nexthop_group_node,
5300 &old_nh_grp->fib_list);
5301 fib6_entry->common.nh_group = old_nh_grp;
5302 return err;
5303}
5304
5305static int
5306mlxsw_sp_fib6_entry_nexthop_add(struct mlxsw_sp *mlxsw_sp,
5307 struct mlxsw_sp_fib6_entry *fib6_entry,
5308 struct fib6_info **rt_arr, unsigned int nrt6)
5309{
5310 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5311 int err, i;
5312
5313 for (i = 0; i < nrt6; i++) {
5314 mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
5315 if (IS_ERR(mlxsw_sp_rt6)) {
5316 err = PTR_ERR(mlxsw_sp_rt6);
5317 goto err_rt6_create;
5318 }
5319
5320 list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
5321 fib6_entry->nrt6++;
5322 }
5323
5324 err = mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
5325 if (err)
5326 goto err_nexthop6_group_update;
5327
5328 return 0;
5329
5330err_nexthop6_group_update:
5331 i = nrt6;
5332err_rt6_create:
5333 for (i--; i >= 0; i--) {
5334 fib6_entry->nrt6--;
5335 mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
5336 struct mlxsw_sp_rt6, list);
5337 list_del(&mlxsw_sp_rt6->list);
5338 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
5339 }
5340 return err;
5341}
5342
5343static void
5344mlxsw_sp_fib6_entry_nexthop_del(struct mlxsw_sp *mlxsw_sp,
5345 struct mlxsw_sp_fib6_entry *fib6_entry,
5346 struct fib6_info **rt_arr, unsigned int nrt6)
5347{
5348 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5349 int i;
5350
5351 for (i = 0; i < nrt6; i++) {
5352 mlxsw_sp_rt6 = mlxsw_sp_fib6_entry_rt_find(fib6_entry,
5353 rt_arr[i]);
5354 if (WARN_ON_ONCE(!mlxsw_sp_rt6))
5355 continue;
5356
5357 fib6_entry->nrt6--;
5358 list_del(&mlxsw_sp_rt6->list);
5359 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
5360 }
5361
5362 mlxsw_sp_nexthop6_group_update(mlxsw_sp, fib6_entry);
5363}
5364
5365static void mlxsw_sp_fib6_entry_type_set(struct mlxsw_sp *mlxsw_sp,
5366 struct mlxsw_sp_fib_entry *fib_entry,
5367 const struct fib6_info *rt)
5368{
5369
5370
5371
5372
5373
5374
5375 if (rt->fib6_flags & (RTF_LOCAL | RTF_ANYCAST))
5376 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
5377 else if (rt->fib6_type == RTN_BLACKHOLE)
5378 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE;
5379 else if (rt->fib6_flags & RTF_REJECT)
5380 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_UNREACHABLE;
5381 else if (mlxsw_sp_rt6_is_gateway(mlxsw_sp, rt))
5382 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_REMOTE;
5383 else
5384 fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_LOCAL;
5385}
5386
5387static void
5388mlxsw_sp_fib6_entry_rt_destroy_all(struct mlxsw_sp_fib6_entry *fib6_entry)
5389{
5390 struct mlxsw_sp_rt6 *mlxsw_sp_rt6, *tmp;
5391
5392 list_for_each_entry_safe(mlxsw_sp_rt6, tmp, &fib6_entry->rt6_list,
5393 list) {
5394 fib6_entry->nrt6--;
5395 list_del(&mlxsw_sp_rt6->list);
5396 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
5397 }
5398}
5399
5400static struct mlxsw_sp_fib6_entry *
5401mlxsw_sp_fib6_entry_create(struct mlxsw_sp *mlxsw_sp,
5402 struct mlxsw_sp_fib_node *fib_node,
5403 struct fib6_info **rt_arr, unsigned int nrt6)
5404{
5405 struct mlxsw_sp_fib6_entry *fib6_entry;
5406 struct mlxsw_sp_fib_entry *fib_entry;
5407 struct mlxsw_sp_rt6 *mlxsw_sp_rt6;
5408 int err, i;
5409
5410 fib6_entry = kzalloc(sizeof(*fib6_entry), GFP_KERNEL);
5411 if (!fib6_entry)
5412 return ERR_PTR(-ENOMEM);
5413 fib_entry = &fib6_entry->common;
5414
5415 INIT_LIST_HEAD(&fib6_entry->rt6_list);
5416
5417 for (i = 0; i < nrt6; i++) {
5418 mlxsw_sp_rt6 = mlxsw_sp_rt6_create(rt_arr[i]);
5419 if (IS_ERR(mlxsw_sp_rt6)) {
5420 err = PTR_ERR(mlxsw_sp_rt6);
5421 goto err_rt6_create;
5422 }
5423 list_add_tail(&mlxsw_sp_rt6->list, &fib6_entry->rt6_list);
5424 fib6_entry->nrt6++;
5425 }
5426
5427 mlxsw_sp_fib6_entry_type_set(mlxsw_sp, fib_entry, rt_arr[0]);
5428
5429 err = mlxsw_sp_nexthop6_group_get(mlxsw_sp, fib6_entry);
5430 if (err)
5431 goto err_nexthop6_group_get;
5432
5433 fib_entry->fib_node = fib_node;
5434
5435 return fib6_entry;
5436
5437err_nexthop6_group_get:
5438 i = nrt6;
5439err_rt6_create:
5440 for (i--; i >= 0; i--) {
5441 fib6_entry->nrt6--;
5442 mlxsw_sp_rt6 = list_last_entry(&fib6_entry->rt6_list,
5443 struct mlxsw_sp_rt6, list);
5444 list_del(&mlxsw_sp_rt6->list);
5445 mlxsw_sp_rt6_destroy(mlxsw_sp_rt6);
5446 }
5447 kfree(fib6_entry);
5448 return ERR_PTR(err);
5449}
5450
5451static void mlxsw_sp_fib6_entry_destroy(struct mlxsw_sp *mlxsw_sp,
5452 struct mlxsw_sp_fib6_entry *fib6_entry)
5453{
5454 mlxsw_sp_nexthop6_group_put(mlxsw_sp, &fib6_entry->common);
5455 mlxsw_sp_fib6_entry_rt_destroy_all(fib6_entry);
5456 WARN_ON(fib6_entry->nrt6);
5457 kfree(fib6_entry);
5458}
5459
5460static struct mlxsw_sp_fib6_entry *
5461mlxsw_sp_fib6_entry_lookup(struct mlxsw_sp *mlxsw_sp,
5462 const struct fib6_info *rt)
5463{
5464 struct mlxsw_sp_fib6_entry *fib6_entry;
5465 struct mlxsw_sp_fib_node *fib_node;
5466 struct mlxsw_sp_fib *fib;
5467 struct fib6_info *cmp_rt;
5468 struct mlxsw_sp_vr *vr;
5469
5470 vr = mlxsw_sp_vr_find(mlxsw_sp, rt->fib6_table->tb6_id);
5471 if (!vr)
5472 return NULL;
5473 fib = mlxsw_sp_vr_fib(vr, MLXSW_SP_L3_PROTO_IPV6);
5474
5475 fib_node = mlxsw_sp_fib_node_lookup(fib, &rt->fib6_dst.addr,
5476 sizeof(rt->fib6_dst.addr),
5477 rt->fib6_dst.plen);
5478 if (!fib_node)
5479 return NULL;
5480
5481 fib6_entry = container_of(fib_node->fib_entry,
5482 struct mlxsw_sp_fib6_entry, common);
5483 cmp_rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
5484 if (rt->fib6_table->tb6_id == cmp_rt->fib6_table->tb6_id &&
5485 rt->fib6_metric == cmp_rt->fib6_metric &&
5486 mlxsw_sp_fib6_entry_rt_find(fib6_entry, rt))
5487 return fib6_entry;
5488
5489 return NULL;
5490}
5491
5492static bool mlxsw_sp_fib6_allow_replace(struct mlxsw_sp_fib6_entry *fib6_entry)
5493{
5494 struct mlxsw_sp_fib_node *fib_node = fib6_entry->common.fib_node;
5495 struct mlxsw_sp_fib6_entry *fib6_replaced;
5496 struct fib6_info *rt, *rt_replaced;
5497
5498 if (!fib_node->fib_entry)
5499 return true;
5500
5501 fib6_replaced = container_of(fib_node->fib_entry,
5502 struct mlxsw_sp_fib6_entry,
5503 common);
5504 rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
5505 rt_replaced = mlxsw_sp_fib6_entry_rt(fib6_replaced);
5506 if (rt->fib6_table->tb6_id == RT_TABLE_MAIN &&
5507 rt_replaced->fib6_table->tb6_id == RT_TABLE_LOCAL)
5508 return false;
5509
5510 return true;
5511}
5512
5513static int mlxsw_sp_router_fib6_replace(struct mlxsw_sp *mlxsw_sp,
5514 struct fib6_info **rt_arr,
5515 unsigned int nrt6)
5516{
5517 struct mlxsw_sp_fib6_entry *fib6_entry, *fib6_replaced;
5518 struct mlxsw_sp_fib_entry *replaced;
5519 struct mlxsw_sp_fib_node *fib_node;
5520 struct fib6_info *rt = rt_arr[0];
5521 int err;
5522
5523 if (mlxsw_sp->router->aborted)
5524 return 0;
5525
5526 if (rt->fib6_src.plen)
5527 return -EINVAL;
5528
5529 if (mlxsw_sp_fib6_rt_should_ignore(rt))
5530 return 0;
5531
5532 fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
5533 &rt->fib6_dst.addr,
5534 sizeof(rt->fib6_dst.addr),
5535 rt->fib6_dst.plen,
5536 MLXSW_SP_L3_PROTO_IPV6);
5537 if (IS_ERR(fib_node))
5538 return PTR_ERR(fib_node);
5539
5540 fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt_arr,
5541 nrt6);
5542 if (IS_ERR(fib6_entry)) {
5543 err = PTR_ERR(fib6_entry);
5544 goto err_fib6_entry_create;
5545 }
5546
5547 if (!mlxsw_sp_fib6_allow_replace(fib6_entry)) {
5548 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
5549 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5550 return 0;
5551 }
5552
5553 replaced = fib_node->fib_entry;
5554 err = mlxsw_sp_fib_node_entry_link(mlxsw_sp, &fib6_entry->common);
5555 if (err)
5556 goto err_fib_node_entry_link;
5557
5558
5559 if (!replaced)
5560 return 0;
5561
5562 mlxsw_sp_fib_entry_hw_flags_clear(mlxsw_sp, replaced);
5563 fib6_replaced = container_of(replaced, struct mlxsw_sp_fib6_entry,
5564 common);
5565 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_replaced);
5566
5567 return 0;
5568
5569err_fib_node_entry_link:
5570 fib_node->fib_entry = replaced;
5571 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
5572err_fib6_entry_create:
5573 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5574 return err;
5575}
5576
5577static int mlxsw_sp_router_fib6_append(struct mlxsw_sp *mlxsw_sp,
5578 struct fib6_info **rt_arr,
5579 unsigned int nrt6)
5580{
5581 struct mlxsw_sp_fib6_entry *fib6_entry;
5582 struct mlxsw_sp_fib_node *fib_node;
5583 struct fib6_info *rt = rt_arr[0];
5584 int err;
5585
5586 if (mlxsw_sp->router->aborted)
5587 return 0;
5588
5589 if (rt->fib6_src.plen)
5590 return -EINVAL;
5591
5592 if (mlxsw_sp_fib6_rt_should_ignore(rt))
5593 return 0;
5594
5595 fib_node = mlxsw_sp_fib_node_get(mlxsw_sp, rt->fib6_table->tb6_id,
5596 &rt->fib6_dst.addr,
5597 sizeof(rt->fib6_dst.addr),
5598 rt->fib6_dst.plen,
5599 MLXSW_SP_L3_PROTO_IPV6);
5600 if (IS_ERR(fib_node))
5601 return PTR_ERR(fib_node);
5602
5603 if (WARN_ON_ONCE(!fib_node->fib_entry)) {
5604 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5605 return -EINVAL;
5606 }
5607
5608 fib6_entry = container_of(fib_node->fib_entry,
5609 struct mlxsw_sp_fib6_entry, common);
5610 err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt_arr,
5611 nrt6);
5612 if (err)
5613 goto err_fib6_entry_nexthop_add;
5614
5615 return 0;
5616
5617err_fib6_entry_nexthop_add:
5618 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5619 return err;
5620}
5621
5622static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
5623 struct fib6_info **rt_arr,
5624 unsigned int nrt6)
5625{
5626 struct mlxsw_sp_fib6_entry *fib6_entry;
5627 struct mlxsw_sp_fib_node *fib_node;
5628 struct fib6_info *rt = rt_arr[0];
5629
5630 if (mlxsw_sp->router->aborted)
5631 return;
5632
5633 if (mlxsw_sp_fib6_rt_should_ignore(rt))
5634 return;
5635
5636
5637
5638
5639
5640
5641 fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
5642 if (!fib6_entry)
5643 return;
5644
5645
5646
5647
5648 if (nrt6 != fib6_entry->nrt6) {
5649 mlxsw_sp_fib6_entry_nexthop_del(mlxsw_sp, fib6_entry, rt_arr,
5650 nrt6);
5651 return;
5652 }
5653
5654 fib_node = fib6_entry->common.fib_node;
5655
5656 mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, &fib6_entry->common);
5657 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
5658 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5659}
5660
5661static int __mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp,
5662 enum mlxsw_reg_ralxx_protocol proto,
5663 u8 tree_id)
5664{
5665 char ralta_pl[MLXSW_REG_RALTA_LEN];
5666 char ralst_pl[MLXSW_REG_RALST_LEN];
5667 int i, err;
5668
5669 mlxsw_reg_ralta_pack(ralta_pl, true, proto, tree_id);
5670 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralta), ralta_pl);
5671 if (err)
5672 return err;
5673
5674 mlxsw_reg_ralst_pack(ralst_pl, 0xff, tree_id);
5675 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralst), ralst_pl);
5676 if (err)
5677 return err;
5678
5679 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
5680 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
5681 char raltb_pl[MLXSW_REG_RALTB_LEN];
5682 char ralue_pl[MLXSW_REG_RALUE_LEN];
5683
5684 mlxsw_reg_raltb_pack(raltb_pl, vr->id, proto, tree_id);
5685 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(raltb),
5686 raltb_pl);
5687 if (err)
5688 return err;
5689
5690 mlxsw_reg_ralue_pack(ralue_pl, proto,
5691 MLXSW_REG_RALUE_OP_WRITE_WRITE, vr->id, 0);
5692 mlxsw_reg_ralue_act_ip2me_pack(ralue_pl);
5693 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue),
5694 ralue_pl);
5695 if (err)
5696 return err;
5697 }
5698
5699 return 0;
5700}
5701
5702static struct mlxsw_sp_mr_table *
5703mlxsw_sp_router_fibmr_family_to_table(struct mlxsw_sp_vr *vr, int family)
5704{
5705 if (family == RTNL_FAMILY_IPMR)
5706 return vr->mr_table[MLXSW_SP_L3_PROTO_IPV4];
5707 else
5708 return vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
5709}
5710
5711static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp,
5712 struct mfc_entry_notifier_info *men_info,
5713 bool replace)
5714{
5715 struct mlxsw_sp_mr_table *mrt;
5716 struct mlxsw_sp_vr *vr;
5717
5718 if (mlxsw_sp->router->aborted)
5719 return 0;
5720
5721 vr = mlxsw_sp_vr_get(mlxsw_sp, men_info->tb_id, NULL);
5722 if (IS_ERR(vr))
5723 return PTR_ERR(vr);
5724
5725 mrt = mlxsw_sp_router_fibmr_family_to_table(vr, men_info->info.family);
5726 return mlxsw_sp_mr_route_add(mrt, men_info->mfc, replace);
5727}
5728
5729static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp *mlxsw_sp,
5730 struct mfc_entry_notifier_info *men_info)
5731{
5732 struct mlxsw_sp_mr_table *mrt;
5733 struct mlxsw_sp_vr *vr;
5734
5735 if (mlxsw_sp->router->aborted)
5736 return;
5737
5738 vr = mlxsw_sp_vr_find(mlxsw_sp, men_info->tb_id);
5739 if (WARN_ON(!vr))
5740 return;
5741
5742 mrt = mlxsw_sp_router_fibmr_family_to_table(vr, men_info->info.family);
5743 mlxsw_sp_mr_route_del(mrt, men_info->mfc);
5744 mlxsw_sp_vr_put(mlxsw_sp, vr);
5745}
5746
5747static int
5748mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp,
5749 struct vif_entry_notifier_info *ven_info)
5750{
5751 struct mlxsw_sp_mr_table *mrt;
5752 struct mlxsw_sp_rif *rif;
5753 struct mlxsw_sp_vr *vr;
5754
5755 if (mlxsw_sp->router->aborted)
5756 return 0;
5757
5758 vr = mlxsw_sp_vr_get(mlxsw_sp, ven_info->tb_id, NULL);
5759 if (IS_ERR(vr))
5760 return PTR_ERR(vr);
5761
5762 mrt = mlxsw_sp_router_fibmr_family_to_table(vr, ven_info->info.family);
5763 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, ven_info->dev);
5764 return mlxsw_sp_mr_vif_add(mrt, ven_info->dev,
5765 ven_info->vif_index,
5766 ven_info->vif_flags, rif);
5767}
5768
5769static void
5770mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp *mlxsw_sp,
5771 struct vif_entry_notifier_info *ven_info)
5772{
5773 struct mlxsw_sp_mr_table *mrt;
5774 struct mlxsw_sp_vr *vr;
5775
5776 if (mlxsw_sp->router->aborted)
5777 return;
5778
5779 vr = mlxsw_sp_vr_find(mlxsw_sp, ven_info->tb_id);
5780 if (WARN_ON(!vr))
5781 return;
5782
5783 mrt = mlxsw_sp_router_fibmr_family_to_table(vr, ven_info->info.family);
5784 mlxsw_sp_mr_vif_del(mrt, ven_info->vif_index);
5785 mlxsw_sp_vr_put(mlxsw_sp, vr);
5786}
5787
5788static int mlxsw_sp_router_set_abort_trap(struct mlxsw_sp *mlxsw_sp)
5789{
5790 enum mlxsw_reg_ralxx_protocol proto = MLXSW_REG_RALXX_PROTOCOL_IPV4;
5791 int err;
5792
5793 err = __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
5794 MLXSW_SP_LPM_TREE_MIN);
5795 if (err)
5796 return err;
5797
5798
5799
5800
5801
5802 proto = MLXSW_REG_RALXX_PROTOCOL_IPV6;
5803 return __mlxsw_sp_router_set_abort_trap(mlxsw_sp, proto,
5804 MLXSW_SP_LPM_TREE_MIN + 1);
5805}
5806
5807static void mlxsw_sp_fib4_node_flush(struct mlxsw_sp *mlxsw_sp,
5808 struct mlxsw_sp_fib_node *fib_node)
5809{
5810 struct mlxsw_sp_fib4_entry *fib4_entry;
5811
5812 fib4_entry = container_of(fib_node->fib_entry,
5813 struct mlxsw_sp_fib4_entry, common);
5814 mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
5815 mlxsw_sp_fib4_entry_destroy(mlxsw_sp, fib4_entry);
5816 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5817}
5818
5819static void mlxsw_sp_fib6_node_flush(struct mlxsw_sp *mlxsw_sp,
5820 struct mlxsw_sp_fib_node *fib_node)
5821{
5822 struct mlxsw_sp_fib6_entry *fib6_entry;
5823
5824 fib6_entry = container_of(fib_node->fib_entry,
5825 struct mlxsw_sp_fib6_entry, common);
5826 mlxsw_sp_fib_node_entry_unlink(mlxsw_sp, fib_node->fib_entry);
5827 mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
5828 mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
5829}
5830
5831static void mlxsw_sp_fib_node_flush(struct mlxsw_sp *mlxsw_sp,
5832 struct mlxsw_sp_fib_node *fib_node)
5833{
5834 switch (fib_node->fib->proto) {
5835 case MLXSW_SP_L3_PROTO_IPV4:
5836 mlxsw_sp_fib4_node_flush(mlxsw_sp, fib_node);
5837 break;
5838 case MLXSW_SP_L3_PROTO_IPV6:
5839 mlxsw_sp_fib6_node_flush(mlxsw_sp, fib_node);
5840 break;
5841 }
5842}
5843
5844static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
5845 struct mlxsw_sp_vr *vr,
5846 enum mlxsw_sp_l3proto proto)
5847{
5848 struct mlxsw_sp_fib *fib = mlxsw_sp_vr_fib(vr, proto);
5849 struct mlxsw_sp_fib_node *fib_node, *tmp;
5850
5851 list_for_each_entry_safe(fib_node, tmp, &fib->node_list, list) {
5852 bool do_break = &tmp->list == &fib->node_list;
5853
5854 mlxsw_sp_fib_node_flush(mlxsw_sp, fib_node);
5855 if (do_break)
5856 break;
5857 }
5858}
5859
5860static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
5861{
5862 int i, j;
5863
5864 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
5865 struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
5866
5867 if (!mlxsw_sp_vr_is_used(vr))
5868 continue;
5869
5870 for (j = 0; j < MLXSW_SP_L3_PROTO_MAX; j++)
5871 mlxsw_sp_mr_table_flush(vr->mr_table[j]);
5872 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
5873
5874
5875
5876
5877 if (!mlxsw_sp_vr_is_used(vr))
5878 continue;
5879 mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV6);
5880 }
5881
5882
5883
5884
5885
5886 if (!mlxsw_sp->router->adj_discard_index_valid)
5887 return;
5888 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
5889 mlxsw_sp->router->adj_discard_index);
5890 mlxsw_sp->router->adj_discard_index_valid = false;
5891}
5892
5893static void mlxsw_sp_router_fib_abort(struct mlxsw_sp *mlxsw_sp)
5894{
5895 int err;
5896
5897 if (mlxsw_sp->router->aborted)
5898 return;
5899 dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
5900 mlxsw_sp_router_fib_flush(mlxsw_sp);
5901 mlxsw_sp->router->aborted = true;
5902 err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
5903 if (err)
5904 dev_warn(mlxsw_sp->bus_info->dev, "Failed to set abort trap.\n");
5905}
5906
5907struct mlxsw_sp_fib6_event_work {
5908 struct fib6_info **rt_arr;
5909 unsigned int nrt6;
5910};
5911
5912struct mlxsw_sp_fib_event_work {
5913 struct work_struct work;
5914 union {
5915 struct mlxsw_sp_fib6_event_work fib6_work;
5916 struct fib_entry_notifier_info fen_info;
5917 struct fib_rule_notifier_info fr_info;
5918 struct fib_nh_notifier_info fnh_info;
5919 struct mfc_entry_notifier_info men_info;
5920 struct vif_entry_notifier_info ven_info;
5921 };
5922 struct mlxsw_sp *mlxsw_sp;
5923 unsigned long event;
5924};
5925
5926static int
5927mlxsw_sp_router_fib6_work_init(struct mlxsw_sp_fib6_event_work *fib6_work,
5928 struct fib6_entry_notifier_info *fen6_info)
5929{
5930 struct fib6_info *rt = fen6_info->rt;
5931 struct fib6_info **rt_arr;
5932 struct fib6_info *iter;
5933 unsigned int nrt6;
5934 int i = 0;
5935
5936 nrt6 = fen6_info->nsiblings + 1;
5937
5938 rt_arr = kcalloc(nrt6, sizeof(struct fib6_info *), GFP_ATOMIC);
5939 if (!rt_arr)
5940 return -ENOMEM;
5941
5942 fib6_work->rt_arr = rt_arr;
5943 fib6_work->nrt6 = nrt6;
5944
5945 rt_arr[0] = rt;
5946 fib6_info_hold(rt);
5947
5948 if (!fen6_info->nsiblings)
5949 return 0;
5950
5951 list_for_each_entry(iter, &rt->fib6_siblings, fib6_siblings) {
5952 if (i == fen6_info->nsiblings)
5953 break;
5954
5955 rt_arr[i + 1] = iter;
5956 fib6_info_hold(iter);
5957 i++;
5958 }
5959 WARN_ON_ONCE(i != fen6_info->nsiblings);
5960
5961 return 0;
5962}
5963
5964static void
5965mlxsw_sp_router_fib6_work_fini(struct mlxsw_sp_fib6_event_work *fib6_work)
5966{
5967 int i;
5968
5969 for (i = 0; i < fib6_work->nrt6; i++)
5970 mlxsw_sp_rt6_release(fib6_work->rt_arr[i]);
5971 kfree(fib6_work->rt_arr);
5972}
5973
5974static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
5975{
5976 struct mlxsw_sp_fib_event_work *fib_work =
5977 container_of(work, struct mlxsw_sp_fib_event_work, work);
5978 struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
5979 int err;
5980
5981 mutex_lock(&mlxsw_sp->router->lock);
5982 mlxsw_sp_span_respin(mlxsw_sp);
5983
5984 switch (fib_work->event) {
5985 case FIB_EVENT_ENTRY_REPLACE:
5986 err = mlxsw_sp_router_fib4_replace(mlxsw_sp,
5987 &fib_work->fen_info);
5988 if (err)
5989 mlxsw_sp_router_fib_abort(mlxsw_sp);
5990 fib_info_put(fib_work->fen_info.fi);
5991 break;
5992 case FIB_EVENT_ENTRY_DEL:
5993 mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
5994 fib_info_put(fib_work->fen_info.fi);
5995 break;
5996 case FIB_EVENT_NH_ADD:
5997 case FIB_EVENT_NH_DEL:
5998 mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event,
5999 fib_work->fnh_info.fib_nh);
6000 fib_info_put(fib_work->fnh_info.fib_nh->nh_parent);
6001 break;
6002 }
6003 mutex_unlock(&mlxsw_sp->router->lock);
6004 kfree(fib_work);
6005}
6006
6007static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
6008{
6009 struct mlxsw_sp_fib_event_work *fib_work =
6010 container_of(work, struct mlxsw_sp_fib_event_work, work);
6011 struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
6012 int err;
6013
6014 mutex_lock(&mlxsw_sp->router->lock);
6015 mlxsw_sp_span_respin(mlxsw_sp);
6016
6017 switch (fib_work->event) {
6018 case FIB_EVENT_ENTRY_REPLACE:
6019 err = mlxsw_sp_router_fib6_replace(mlxsw_sp,
6020 fib_work->fib6_work.rt_arr,
6021 fib_work->fib6_work.nrt6);
6022 if (err)
6023 mlxsw_sp_router_fib_abort(mlxsw_sp);
6024 mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
6025 break;
6026 case FIB_EVENT_ENTRY_APPEND:
6027 err = mlxsw_sp_router_fib6_append(mlxsw_sp,
6028 fib_work->fib6_work.rt_arr,
6029 fib_work->fib6_work.nrt6);
6030 if (err)
6031 mlxsw_sp_router_fib_abort(mlxsw_sp);
6032 mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
6033 break;
6034 case FIB_EVENT_ENTRY_DEL:
6035 mlxsw_sp_router_fib6_del(mlxsw_sp,
6036 fib_work->fib6_work.rt_arr,
6037 fib_work->fib6_work.nrt6);
6038 mlxsw_sp_router_fib6_work_fini(&fib_work->fib6_work);
6039 break;
6040 }
6041 mutex_unlock(&mlxsw_sp->router->lock);
6042 kfree(fib_work);
6043}
6044
6045static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work)
6046{
6047 struct mlxsw_sp_fib_event_work *fib_work =
6048 container_of(work, struct mlxsw_sp_fib_event_work, work);
6049 struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
6050 bool replace;
6051 int err;
6052
6053 rtnl_lock();
6054 mutex_lock(&mlxsw_sp->router->lock);
6055 switch (fib_work->event) {
6056 case FIB_EVENT_ENTRY_REPLACE:
6057 case FIB_EVENT_ENTRY_ADD:
6058 replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
6059
6060 err = mlxsw_sp_router_fibmr_add(mlxsw_sp, &fib_work->men_info,
6061 replace);
6062 if (err)
6063 mlxsw_sp_router_fib_abort(mlxsw_sp);
6064 mr_cache_put(fib_work->men_info.mfc);
6065 break;
6066 case FIB_EVENT_ENTRY_DEL:
6067 mlxsw_sp_router_fibmr_del(mlxsw_sp, &fib_work->men_info);
6068 mr_cache_put(fib_work->men_info.mfc);
6069 break;
6070 case FIB_EVENT_VIF_ADD:
6071 err = mlxsw_sp_router_fibmr_vif_add(mlxsw_sp,
6072 &fib_work->ven_info);
6073 if (err)
6074 mlxsw_sp_router_fib_abort(mlxsw_sp);
6075 dev_put(fib_work->ven_info.dev);
6076 break;
6077 case FIB_EVENT_VIF_DEL:
6078 mlxsw_sp_router_fibmr_vif_del(mlxsw_sp,
6079 &fib_work->ven_info);
6080 dev_put(fib_work->ven_info.dev);
6081 break;
6082 }
6083 mutex_unlock(&mlxsw_sp->router->lock);
6084 rtnl_unlock();
6085 kfree(fib_work);
6086}
6087
6088static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work,
6089 struct fib_notifier_info *info)
6090{
6091 struct fib_entry_notifier_info *fen_info;
6092 struct fib_nh_notifier_info *fnh_info;
6093
6094 switch (fib_work->event) {
6095 case FIB_EVENT_ENTRY_REPLACE:
6096 case FIB_EVENT_ENTRY_DEL:
6097 fen_info = container_of(info, struct fib_entry_notifier_info,
6098 info);
6099 fib_work->fen_info = *fen_info;
6100
6101
6102
6103 fib_info_hold(fib_work->fen_info.fi);
6104 break;
6105 case FIB_EVENT_NH_ADD:
6106 case FIB_EVENT_NH_DEL:
6107 fnh_info = container_of(info, struct fib_nh_notifier_info,
6108 info);
6109 fib_work->fnh_info = *fnh_info;
6110 fib_info_hold(fib_work->fnh_info.fib_nh->nh_parent);
6111 break;
6112 }
6113}
6114
6115static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work,
6116 struct fib_notifier_info *info)
6117{
6118 struct fib6_entry_notifier_info *fen6_info;
6119 int err;
6120
6121 switch (fib_work->event) {
6122 case FIB_EVENT_ENTRY_REPLACE:
6123 case FIB_EVENT_ENTRY_APPEND:
6124 case FIB_EVENT_ENTRY_DEL:
6125 fen6_info = container_of(info, struct fib6_entry_notifier_info,
6126 info);
6127 err = mlxsw_sp_router_fib6_work_init(&fib_work->fib6_work,
6128 fen6_info);
6129 if (err)
6130 return err;
6131 break;
6132 }
6133
6134 return 0;
6135}
6136
6137static void
6138mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work,
6139 struct fib_notifier_info *info)
6140{
6141 switch (fib_work->event) {
6142 case FIB_EVENT_ENTRY_REPLACE:
6143 case FIB_EVENT_ENTRY_ADD:
6144 case FIB_EVENT_ENTRY_DEL:
6145 memcpy(&fib_work->men_info, info, sizeof(fib_work->men_info));
6146 mr_cache_hold(fib_work->men_info.mfc);
6147 break;
6148 case FIB_EVENT_VIF_ADD:
6149 case FIB_EVENT_VIF_DEL:
6150 memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info));
6151 dev_hold(fib_work->ven_info.dev);
6152 break;
6153 }
6154}
6155
6156static int mlxsw_sp_router_fib_rule_event(unsigned long event,
6157 struct fib_notifier_info *info,
6158 struct mlxsw_sp *mlxsw_sp)
6159{
6160 struct netlink_ext_ack *extack = info->extack;
6161 struct fib_rule_notifier_info *fr_info;
6162 struct fib_rule *rule;
6163 int err = 0;
6164
6165
6166 if (event == FIB_EVENT_RULE_DEL)
6167 return 0;
6168
6169 if (mlxsw_sp->router->aborted)
6170 return 0;
6171
6172 fr_info = container_of(info, struct fib_rule_notifier_info, info);
6173 rule = fr_info->rule;
6174
6175
6176 if (rule->iifindex == mlxsw_sp_net(mlxsw_sp)->loopback_dev->ifindex)
6177 return 0;
6178
6179 switch (info->family) {
6180 case AF_INET:
6181 if (!fib4_rule_default(rule) && !rule->l3mdev)
6182 err = -EOPNOTSUPP;
6183 break;
6184 case AF_INET6:
6185 if (!fib6_rule_default(rule) && !rule->l3mdev)
6186 err = -EOPNOTSUPP;
6187 break;
6188 case RTNL_FAMILY_IPMR:
6189 if (!ipmr_rule_default(rule) && !rule->l3mdev)
6190 err = -EOPNOTSUPP;
6191 break;
6192 case RTNL_FAMILY_IP6MR:
6193 if (!ip6mr_rule_default(rule) && !rule->l3mdev)
6194 err = -EOPNOTSUPP;
6195 break;
6196 }
6197
6198 if (err < 0)
6199 NL_SET_ERR_MSG_MOD(extack, "FIB rules not supported");
6200
6201 return err;
6202}
6203
6204
6205static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
6206 unsigned long event, void *ptr)
6207{
6208 struct mlxsw_sp_fib_event_work *fib_work;
6209 struct fib_notifier_info *info = ptr;
6210 struct mlxsw_sp_router *router;
6211 int err;
6212
6213 if ((info->family != AF_INET && info->family != AF_INET6 &&
6214 info->family != RTNL_FAMILY_IPMR &&
6215 info->family != RTNL_FAMILY_IP6MR))
6216 return NOTIFY_DONE;
6217
6218 router = container_of(nb, struct mlxsw_sp_router, fib_nb);
6219
6220 switch (event) {
6221 case FIB_EVENT_RULE_ADD:
6222 case FIB_EVENT_RULE_DEL:
6223 err = mlxsw_sp_router_fib_rule_event(event, info,
6224 router->mlxsw_sp);
6225 return notifier_from_errno(err);
6226 case FIB_EVENT_ENTRY_ADD:
6227 case FIB_EVENT_ENTRY_REPLACE:
6228 case FIB_EVENT_ENTRY_APPEND:
6229 if (router->aborted) {
6230 NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route");
6231 return notifier_from_errno(-EINVAL);
6232 }
6233 if (info->family == AF_INET) {
6234 struct fib_entry_notifier_info *fen_info = ptr;
6235
6236 if (fen_info->fi->fib_nh_is_v6) {
6237 NL_SET_ERR_MSG_MOD(info->extack, "IPv6 gateway with IPv4 route is not supported");
6238 return notifier_from_errno(-EINVAL);
6239 }
6240 if (fen_info->fi->nh) {
6241 NL_SET_ERR_MSG_MOD(info->extack, "IPv4 route with nexthop objects is not supported");
6242 return notifier_from_errno(-EINVAL);
6243 }
6244 } else if (info->family == AF_INET6) {
6245 struct fib6_entry_notifier_info *fen6_info;
6246
6247 fen6_info = container_of(info,
6248 struct fib6_entry_notifier_info,
6249 info);
6250 if (fen6_info->rt->nh) {
6251 NL_SET_ERR_MSG_MOD(info->extack, "IPv6 route with nexthop objects is not supported");
6252 return notifier_from_errno(-EINVAL);
6253 }
6254 }
6255 break;
6256 }
6257
6258 fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
6259 if (WARN_ON(!fib_work))
6260 return NOTIFY_BAD;
6261
6262 fib_work->mlxsw_sp = router->mlxsw_sp;
6263 fib_work->event = event;
6264
6265 switch (info->family) {
6266 case AF_INET:
6267 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib4_event_work);
6268 mlxsw_sp_router_fib4_event(fib_work, info);
6269 break;
6270 case AF_INET6:
6271 INIT_WORK(&fib_work->work, mlxsw_sp_router_fib6_event_work);
6272 err = mlxsw_sp_router_fib6_event(fib_work, info);
6273 if (err)
6274 goto err_fib_event;
6275 break;
6276 case RTNL_FAMILY_IP6MR:
6277 case RTNL_FAMILY_IPMR:
6278 INIT_WORK(&fib_work->work, mlxsw_sp_router_fibmr_event_work);
6279 mlxsw_sp_router_fibmr_event(fib_work, info);
6280 break;
6281 }
6282
6283 mlxsw_core_schedule_work(&fib_work->work);
6284
6285 return NOTIFY_DONE;
6286
6287err_fib_event:
6288 kfree(fib_work);
6289 return NOTIFY_BAD;
6290}
6291
6292static struct mlxsw_sp_rif *
6293mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
6294 const struct net_device *dev)
6295{
6296 int i;
6297
6298 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
6299 if (mlxsw_sp->router->rifs[i] &&
6300 mlxsw_sp->router->rifs[i]->dev == dev)
6301 return mlxsw_sp->router->rifs[i];
6302
6303 return NULL;
6304}
6305
6306bool mlxsw_sp_rif_exists(struct mlxsw_sp *mlxsw_sp,
6307 const struct net_device *dev)
6308{
6309 struct mlxsw_sp_rif *rif;
6310
6311 mutex_lock(&mlxsw_sp->router->lock);
6312 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
6313 mutex_unlock(&mlxsw_sp->router->lock);
6314
6315 return rif;
6316}
6317
6318u16 mlxsw_sp_rif_vid(struct mlxsw_sp *mlxsw_sp, const struct net_device *dev)
6319{
6320 struct mlxsw_sp_rif *rif;
6321 u16 vid = 0;
6322
6323 mutex_lock(&mlxsw_sp->router->lock);
6324 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
6325 if (!rif)
6326 goto out;
6327
6328
6329
6330
6331 if (rif->ops->type != MLXSW_SP_RIF_TYPE_VLAN)
6332 goto out;
6333
6334 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
6335
6336out:
6337 mutex_unlock(&mlxsw_sp->router->lock);
6338 return vid;
6339}
6340
6341static int mlxsw_sp_router_rif_disable(struct mlxsw_sp *mlxsw_sp, u16 rif)
6342{
6343 char ritr_pl[MLXSW_REG_RITR_LEN];
6344 int err;
6345
6346 mlxsw_reg_ritr_rif_pack(ritr_pl, rif);
6347 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
6348 if (err)
6349 return err;
6350
6351 mlxsw_reg_ritr_enable_set(ritr_pl, false);
6352 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
6353}
6354
6355static void mlxsw_sp_router_rif_gone_sync(struct mlxsw_sp *mlxsw_sp,
6356 struct mlxsw_sp_rif *rif)
6357{
6358 mlxsw_sp_router_rif_disable(mlxsw_sp, rif->rif_index);
6359 mlxsw_sp_nexthop_rif_gone_sync(mlxsw_sp, rif);
6360 mlxsw_sp_neigh_rif_gone_sync(mlxsw_sp, rif);
6361}
6362
6363static bool
6364mlxsw_sp_rif_should_config(struct mlxsw_sp_rif *rif, struct net_device *dev,
6365 unsigned long event)
6366{
6367 struct inet6_dev *inet6_dev;
6368 bool addr_list_empty = true;
6369 struct in_device *idev;
6370
6371 switch (event) {
6372 case NETDEV_UP:
6373 return rif == NULL;
6374 case NETDEV_DOWN:
6375 rcu_read_lock();
6376 idev = __in_dev_get_rcu(dev);
6377 if (idev && idev->ifa_list)
6378 addr_list_empty = false;
6379
6380 inet6_dev = __in6_dev_get(dev);
6381 if (addr_list_empty && inet6_dev &&
6382 !list_empty(&inet6_dev->addr_list))
6383 addr_list_empty = false;
6384 rcu_read_unlock();
6385
6386
6387
6388
6389 if (netif_is_macvlan(dev) && addr_list_empty)
6390 return true;
6391
6392 if (rif && addr_list_empty &&
6393 !netif_is_l3_slave(rif->dev))
6394 return true;
6395
6396
6397
6398
6399 return false;
6400 }
6401
6402 return false;
6403}
6404
6405static enum mlxsw_sp_rif_type
6406mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
6407 const struct net_device *dev)
6408{
6409 enum mlxsw_sp_fid_type type;
6410
6411 if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
6412 return MLXSW_SP_RIF_TYPE_IPIP_LB;
6413
6414
6415 if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
6416 type = MLXSW_SP_FID_TYPE_8021Q;
6417 else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
6418 type = MLXSW_SP_FID_TYPE_8021Q;
6419 else if (netif_is_bridge_master(dev))
6420 type = MLXSW_SP_FID_TYPE_8021D;
6421 else
6422 type = MLXSW_SP_FID_TYPE_RFID;
6423
6424 return mlxsw_sp_fid_type_rif_type(mlxsw_sp, type);
6425}
6426
6427static int mlxsw_sp_rif_index_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_rif_index)
6428{
6429 int i;
6430
6431 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
6432 if (!mlxsw_sp->router->rifs[i]) {
6433 *p_rif_index = i;
6434 return 0;
6435 }
6436 }
6437
6438 return -ENOBUFS;
6439}
6440
6441static struct mlxsw_sp_rif *mlxsw_sp_rif_alloc(size_t rif_size, u16 rif_index,
6442 u16 vr_id,
6443 struct net_device *l3_dev)
6444{
6445 struct mlxsw_sp_rif *rif;
6446
6447 rif = kzalloc(rif_size, GFP_KERNEL);
6448 if (!rif)
6449 return NULL;
6450
6451 INIT_LIST_HEAD(&rif->nexthop_list);
6452 INIT_LIST_HEAD(&rif->neigh_list);
6453 if (l3_dev) {
6454 ether_addr_copy(rif->addr, l3_dev->dev_addr);
6455 rif->mtu = l3_dev->mtu;
6456 rif->dev = l3_dev;
6457 }
6458 rif->vr_id = vr_id;
6459 rif->rif_index = rif_index;
6460
6461 return rif;
6462}
6463
6464struct mlxsw_sp_rif *mlxsw_sp_rif_by_index(const struct mlxsw_sp *mlxsw_sp,
6465 u16 rif_index)
6466{
6467 return mlxsw_sp->router->rifs[rif_index];
6468}
6469
6470u16 mlxsw_sp_rif_index(const struct mlxsw_sp_rif *rif)
6471{
6472 return rif->rif_index;
6473}
6474
6475u16 mlxsw_sp_ipip_lb_rif_index(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
6476{
6477 return lb_rif->common.rif_index;
6478}
6479
6480u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
6481{
6482 u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(lb_rif->common.dev);
6483 struct mlxsw_sp_vr *ul_vr;
6484
6485 ul_vr = mlxsw_sp_vr_get(lb_rif->common.mlxsw_sp, ul_tb_id, NULL);
6486 if (WARN_ON(IS_ERR(ul_vr)))
6487 return 0;
6488
6489 return ul_vr->id;
6490}
6491
6492u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif)
6493{
6494 return lb_rif->ul_rif_id;
6495}
6496
6497int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif)
6498{
6499 return rif->dev->ifindex;
6500}
6501
6502const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif)
6503{
6504 return rif->dev;
6505}
6506
6507static struct mlxsw_sp_rif *
6508mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
6509 const struct mlxsw_sp_rif_params *params,
6510 struct netlink_ext_ack *extack)
6511{
6512 u32 tb_id = l3mdev_fib_table(params->dev);
6513 const struct mlxsw_sp_rif_ops *ops;
6514 struct mlxsw_sp_fid *fid = NULL;
6515 enum mlxsw_sp_rif_type type;
6516 struct mlxsw_sp_rif *rif;
6517 struct mlxsw_sp_vr *vr;
6518 u16 rif_index;
6519 int i, err;
6520
6521 type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
6522 ops = mlxsw_sp->rif_ops_arr[type];
6523
6524 vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN, extack);
6525 if (IS_ERR(vr))
6526 return ERR_CAST(vr);
6527 vr->rif_count++;
6528
6529 err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
6530 if (err) {
6531 NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
6532 goto err_rif_index_alloc;
6533 }
6534
6535 rif = mlxsw_sp_rif_alloc(ops->rif_size, rif_index, vr->id, params->dev);
6536 if (!rif) {
6537 err = -ENOMEM;
6538 goto err_rif_alloc;
6539 }
6540 dev_hold(rif->dev);
6541 mlxsw_sp->router->rifs[rif_index] = rif;
6542 rif->mlxsw_sp = mlxsw_sp;
6543 rif->ops = ops;
6544
6545 if (ops->fid_get) {
6546 fid = ops->fid_get(rif, extack);
6547 if (IS_ERR(fid)) {
6548 err = PTR_ERR(fid);
6549 goto err_fid_get;
6550 }
6551 rif->fid = fid;
6552 }
6553
6554 if (ops->setup)
6555 ops->setup(rif, params);
6556
6557 err = ops->configure(rif);
6558 if (err)
6559 goto err_configure;
6560
6561 for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++) {
6562 err = mlxsw_sp_mr_rif_add(vr->mr_table[i], rif);
6563 if (err)
6564 goto err_mr_rif_add;
6565 }
6566
6567 mlxsw_sp_rif_counters_alloc(rif);
6568
6569 return rif;
6570
6571err_mr_rif_add:
6572 for (i--; i >= 0; i--)
6573 mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
6574 ops->deconfigure(rif);
6575err_configure:
6576 if (fid)
6577 mlxsw_sp_fid_put(fid);
6578err_fid_get:
6579 mlxsw_sp->router->rifs[rif_index] = NULL;
6580 dev_put(rif->dev);
6581 kfree(rif);
6582err_rif_alloc:
6583err_rif_index_alloc:
6584 vr->rif_count--;
6585 mlxsw_sp_vr_put(mlxsw_sp, vr);
6586 return ERR_PTR(err);
6587}
6588
6589static void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
6590{
6591 const struct mlxsw_sp_rif_ops *ops = rif->ops;
6592 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
6593 struct mlxsw_sp_fid *fid = rif->fid;
6594 struct mlxsw_sp_vr *vr;
6595 int i;
6596
6597 mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
6598 vr = &mlxsw_sp->router->vrs[rif->vr_id];
6599
6600 mlxsw_sp_rif_counters_free(rif);
6601 for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
6602 mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
6603 ops->deconfigure(rif);
6604 if (fid)
6605
6606 mlxsw_sp_fid_put(fid);
6607 mlxsw_sp->router->rifs[rif->rif_index] = NULL;
6608 dev_put(rif->dev);
6609 kfree(rif);
6610 vr->rif_count--;
6611 mlxsw_sp_vr_put(mlxsw_sp, vr);
6612}
6613
6614void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
6615 struct net_device *dev)
6616{
6617 struct mlxsw_sp_rif *rif;
6618
6619 mutex_lock(&mlxsw_sp->router->lock);
6620 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
6621 if (!rif)
6622 goto out;
6623 mlxsw_sp_rif_destroy(rif);
6624out:
6625 mutex_unlock(&mlxsw_sp->router->lock);
6626}
6627
6628static void
6629mlxsw_sp_rif_subport_params_init(struct mlxsw_sp_rif_params *params,
6630 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
6631{
6632 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
6633
6634 params->vid = mlxsw_sp_port_vlan->vid;
6635 params->lag = mlxsw_sp_port->lagged;
6636 if (params->lag)
6637 params->lag_id = mlxsw_sp_port->lag_id;
6638 else
6639 params->system_port = mlxsw_sp_port->local_port;
6640}
6641
6642static struct mlxsw_sp_rif_subport *
6643mlxsw_sp_rif_subport_rif(const struct mlxsw_sp_rif *rif)
6644{
6645 return container_of(rif, struct mlxsw_sp_rif_subport, common);
6646}
6647
6648static struct mlxsw_sp_rif *
6649mlxsw_sp_rif_subport_get(struct mlxsw_sp *mlxsw_sp,
6650 const struct mlxsw_sp_rif_params *params,
6651 struct netlink_ext_ack *extack)
6652{
6653 struct mlxsw_sp_rif_subport *rif_subport;
6654 struct mlxsw_sp_rif *rif;
6655
6656 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, params->dev);
6657 if (!rif)
6658 return mlxsw_sp_rif_create(mlxsw_sp, params, extack);
6659
6660 rif_subport = mlxsw_sp_rif_subport_rif(rif);
6661 refcount_inc(&rif_subport->ref_count);
6662 return rif;
6663}
6664
6665static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif)
6666{
6667 struct mlxsw_sp_rif_subport *rif_subport;
6668
6669 rif_subport = mlxsw_sp_rif_subport_rif(rif);
6670 if (!refcount_dec_and_test(&rif_subport->ref_count))
6671 return;
6672
6673 mlxsw_sp_rif_destroy(rif);
6674}
6675
6676static int
6677mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
6678 struct net_device *l3_dev,
6679 struct netlink_ext_ack *extack)
6680{
6681 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
6682 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
6683 struct mlxsw_sp_rif_params params = {
6684 .dev = l3_dev,
6685 };
6686 u16 vid = mlxsw_sp_port_vlan->vid;
6687 struct mlxsw_sp_rif *rif;
6688 struct mlxsw_sp_fid *fid;
6689 int err;
6690
6691 mlxsw_sp_rif_subport_params_init(¶ms, mlxsw_sp_port_vlan);
6692 rif = mlxsw_sp_rif_subport_get(mlxsw_sp, ¶ms, extack);
6693 if (IS_ERR(rif))
6694 return PTR_ERR(rif);
6695
6696
6697 fid = rif->ops->fid_get(rif, extack);
6698 err = mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port, vid);
6699 if (err)
6700 goto err_fid_port_vid_map;
6701
6702 err = mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
6703 if (err)
6704 goto err_port_vid_learning_set;
6705
6706 err = mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid,
6707 BR_STATE_FORWARDING);
6708 if (err)
6709 goto err_port_vid_stp_set;
6710
6711 mlxsw_sp_port_vlan->fid = fid;
6712
6713 return 0;
6714
6715err_port_vid_stp_set:
6716 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
6717err_port_vid_learning_set:
6718 mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
6719err_fid_port_vid_map:
6720 mlxsw_sp_fid_put(fid);
6721 mlxsw_sp_rif_subport_put(rif);
6722 return err;
6723}
6724
6725static void
6726__mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
6727{
6728 struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
6729 struct mlxsw_sp_fid *fid = mlxsw_sp_port_vlan->fid;
6730 struct mlxsw_sp_rif *rif = mlxsw_sp_fid_rif(fid);
6731 u16 vid = mlxsw_sp_port_vlan->vid;
6732
6733 if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_RFID))
6734 return;
6735
6736 mlxsw_sp_port_vlan->fid = NULL;
6737 mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_BLOCKING);
6738 mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, true);
6739 mlxsw_sp_fid_port_vid_unmap(fid, mlxsw_sp_port, vid);
6740 mlxsw_sp_fid_put(fid);
6741 mlxsw_sp_rif_subport_put(rif);
6742}
6743
6744void
6745mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
6746{
6747 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
6748
6749 mutex_lock(&mlxsw_sp->router->lock);
6750 __mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
6751 mutex_unlock(&mlxsw_sp->router->lock);
6752}
6753
6754static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
6755 struct net_device *port_dev,
6756 unsigned long event, u16 vid,
6757 struct netlink_ext_ack *extack)
6758{
6759 struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(port_dev);
6760 struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
6761
6762 mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
6763 if (WARN_ON(!mlxsw_sp_port_vlan))
6764 return -EINVAL;
6765
6766 switch (event) {
6767 case NETDEV_UP:
6768 return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
6769 l3_dev, extack);
6770 case NETDEV_DOWN:
6771 __mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
6772 break;
6773 }
6774
6775 return 0;
6776}
6777
6778static int mlxsw_sp_inetaddr_port_event(struct net_device *port_dev,
6779 unsigned long event,
6780 struct netlink_ext_ack *extack)
6781{
6782 if (netif_is_bridge_port(port_dev) ||
6783 netif_is_lag_port(port_dev) ||
6784 netif_is_ovs_port(port_dev))
6785 return 0;
6786
6787 return mlxsw_sp_inetaddr_port_vlan_event(port_dev, port_dev, event,
6788 MLXSW_SP_DEFAULT_VID, extack);
6789}
6790
6791static int __mlxsw_sp_inetaddr_lag_event(struct net_device *l3_dev,
6792 struct net_device *lag_dev,
6793 unsigned long event, u16 vid,
6794 struct netlink_ext_ack *extack)
6795{
6796 struct net_device *port_dev;
6797 struct list_head *iter;
6798 int err;
6799
6800 netdev_for_each_lower_dev(lag_dev, port_dev, iter) {
6801 if (mlxsw_sp_port_dev_check(port_dev)) {
6802 err = mlxsw_sp_inetaddr_port_vlan_event(l3_dev,
6803 port_dev,
6804 event, vid,
6805 extack);
6806 if (err)
6807 return err;
6808 }
6809 }
6810
6811 return 0;
6812}
6813
6814static int mlxsw_sp_inetaddr_lag_event(struct net_device *lag_dev,
6815 unsigned long event,
6816 struct netlink_ext_ack *extack)
6817{
6818 if (netif_is_bridge_port(lag_dev))
6819 return 0;
6820
6821 return __mlxsw_sp_inetaddr_lag_event(lag_dev, lag_dev, event,
6822 MLXSW_SP_DEFAULT_VID, extack);
6823}
6824
6825static int mlxsw_sp_inetaddr_bridge_event(struct mlxsw_sp *mlxsw_sp,
6826 struct net_device *l3_dev,
6827 unsigned long event,
6828 struct netlink_ext_ack *extack)
6829{
6830 struct mlxsw_sp_rif_params params = {
6831 .dev = l3_dev,
6832 };
6833 struct mlxsw_sp_rif *rif;
6834
6835 switch (event) {
6836 case NETDEV_UP:
6837 rif = mlxsw_sp_rif_create(mlxsw_sp, ¶ms, extack);
6838 if (IS_ERR(rif))
6839 return PTR_ERR(rif);
6840 break;
6841 case NETDEV_DOWN:
6842 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
6843 mlxsw_sp_rif_destroy(rif);
6844 break;
6845 }
6846
6847 return 0;
6848}
6849
6850static int mlxsw_sp_inetaddr_vlan_event(struct mlxsw_sp *mlxsw_sp,
6851 struct net_device *vlan_dev,
6852 unsigned long event,
6853 struct netlink_ext_ack *extack)
6854{
6855 struct net_device *real_dev = vlan_dev_real_dev(vlan_dev);
6856 u16 vid = vlan_dev_vlan_id(vlan_dev);
6857
6858 if (netif_is_bridge_port(vlan_dev))
6859 return 0;
6860
6861 if (mlxsw_sp_port_dev_check(real_dev))
6862 return mlxsw_sp_inetaddr_port_vlan_event(vlan_dev, real_dev,
6863 event, vid, extack);
6864 else if (netif_is_lag_master(real_dev))
6865 return __mlxsw_sp_inetaddr_lag_event(vlan_dev, real_dev, event,
6866 vid, extack);
6867 else if (netif_is_bridge_master(real_dev) && br_vlan_enabled(real_dev))
6868 return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, vlan_dev, event,
6869 extack);
6870
6871 return 0;
6872}
6873
6874static bool mlxsw_sp_rif_macvlan_is_vrrp4(const u8 *mac)
6875{
6876 u8 vrrp4[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x01, 0x00 };
6877 u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
6878
6879 return ether_addr_equal_masked(mac, vrrp4, mask);
6880}
6881
6882static bool mlxsw_sp_rif_macvlan_is_vrrp6(const u8 *mac)
6883{
6884 u8 vrrp6[ETH_ALEN] = { 0x00, 0x00, 0x5e, 0x00, 0x02, 0x00 };
6885 u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
6886
6887 return ether_addr_equal_masked(mac, vrrp6, mask);
6888}
6889
6890static int mlxsw_sp_rif_vrrp_op(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
6891 const u8 *mac, bool adding)
6892{
6893 char ritr_pl[MLXSW_REG_RITR_LEN];
6894 u8 vrrp_id = adding ? mac[5] : 0;
6895 int err;
6896
6897 if (!mlxsw_sp_rif_macvlan_is_vrrp4(mac) &&
6898 !mlxsw_sp_rif_macvlan_is_vrrp6(mac))
6899 return 0;
6900
6901 mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
6902 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
6903 if (err)
6904 return err;
6905
6906 if (mlxsw_sp_rif_macvlan_is_vrrp4(mac))
6907 mlxsw_reg_ritr_if_vrrp_id_ipv4_set(ritr_pl, vrrp_id);
6908 else
6909 mlxsw_reg_ritr_if_vrrp_id_ipv6_set(ritr_pl, vrrp_id);
6910
6911 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
6912}
6913
6914static int mlxsw_sp_rif_macvlan_add(struct mlxsw_sp *mlxsw_sp,
6915 const struct net_device *macvlan_dev,
6916 struct netlink_ext_ack *extack)
6917{
6918 struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
6919 struct mlxsw_sp_rif *rif;
6920 int err;
6921
6922 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev);
6923 if (!rif) {
6924 NL_SET_ERR_MSG_MOD(extack, "macvlan is only supported on top of router interfaces");
6925 return -EOPNOTSUPP;
6926 }
6927
6928 err = mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
6929 mlxsw_sp_fid_index(rif->fid), true);
6930 if (err)
6931 return err;
6932
6933 err = mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index,
6934 macvlan_dev->dev_addr, true);
6935 if (err)
6936 goto err_rif_vrrp_add;
6937
6938
6939
6940
6941 if (rif->ops->fdb_del)
6942 rif->ops->fdb_del(rif, macvlan_dev->dev_addr);
6943
6944 return 0;
6945
6946err_rif_vrrp_add:
6947 mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
6948 mlxsw_sp_fid_index(rif->fid), false);
6949 return err;
6950}
6951
6952static void __mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
6953 const struct net_device *macvlan_dev)
6954{
6955 struct macvlan_dev *vlan = netdev_priv(macvlan_dev);
6956 struct mlxsw_sp_rif *rif;
6957
6958 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, vlan->lowerdev);
6959
6960
6961
6962 if (!rif)
6963 return;
6964 mlxsw_sp_rif_vrrp_op(mlxsw_sp, rif->rif_index, macvlan_dev->dev_addr,
6965 false);
6966 mlxsw_sp_rif_fdb_op(mlxsw_sp, macvlan_dev->dev_addr,
6967 mlxsw_sp_fid_index(rif->fid), false);
6968}
6969
6970void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp,
6971 const struct net_device *macvlan_dev)
6972{
6973 mutex_lock(&mlxsw_sp->router->lock);
6974 __mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
6975 mutex_unlock(&mlxsw_sp->router->lock);
6976}
6977
6978static int mlxsw_sp_inetaddr_macvlan_event(struct mlxsw_sp *mlxsw_sp,
6979 struct net_device *macvlan_dev,
6980 unsigned long event,
6981 struct netlink_ext_ack *extack)
6982{
6983 switch (event) {
6984 case NETDEV_UP:
6985 return mlxsw_sp_rif_macvlan_add(mlxsw_sp, macvlan_dev, extack);
6986 case NETDEV_DOWN:
6987 __mlxsw_sp_rif_macvlan_del(mlxsw_sp, macvlan_dev);
6988 break;
6989 }
6990
6991 return 0;
6992}
6993
6994static int mlxsw_sp_router_port_check_rif_addr(struct mlxsw_sp *mlxsw_sp,
6995 struct net_device *dev,
6996 const unsigned char *dev_addr,
6997 struct netlink_ext_ack *extack)
6998{
6999 struct mlxsw_sp_rif *rif;
7000 int i;
7001
7002
7003
7004
7005 if (netif_is_macvlan(dev) || netif_is_l3_master(dev))
7006 return 0;
7007
7008 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
7009 rif = mlxsw_sp->router->rifs[i];
7010 if (rif && rif->ops &&
7011 rif->ops->type == MLXSW_SP_RIF_TYPE_IPIP_LB)
7012 continue;
7013 if (rif && rif->dev && rif->dev != dev &&
7014 !ether_addr_equal_masked(rif->dev->dev_addr, dev_addr,
7015 mlxsw_sp->mac_mask)) {
7016 NL_SET_ERR_MSG_MOD(extack, "All router interface MAC addresses must have the same prefix");
7017 return -EINVAL;
7018 }
7019 }
7020
7021 return 0;
7022}
7023
7024static int __mlxsw_sp_inetaddr_event(struct mlxsw_sp *mlxsw_sp,
7025 struct net_device *dev,
7026 unsigned long event,
7027 struct netlink_ext_ack *extack)
7028{
7029 if (mlxsw_sp_port_dev_check(dev))
7030 return mlxsw_sp_inetaddr_port_event(dev, event, extack);
7031 else if (netif_is_lag_master(dev))
7032 return mlxsw_sp_inetaddr_lag_event(dev, event, extack);
7033 else if (netif_is_bridge_master(dev))
7034 return mlxsw_sp_inetaddr_bridge_event(mlxsw_sp, dev, event,
7035 extack);
7036 else if (is_vlan_dev(dev))
7037 return mlxsw_sp_inetaddr_vlan_event(mlxsw_sp, dev, event,
7038 extack);
7039 else if (netif_is_macvlan(dev))
7040 return mlxsw_sp_inetaddr_macvlan_event(mlxsw_sp, dev, event,
7041 extack);
7042 else
7043 return 0;
7044}
7045
7046static int mlxsw_sp_inetaddr_event(struct notifier_block *nb,
7047 unsigned long event, void *ptr)
7048{
7049 struct in_ifaddr *ifa = (struct in_ifaddr *) ptr;
7050 struct net_device *dev = ifa->ifa_dev->dev;
7051 struct mlxsw_sp_router *router;
7052 struct mlxsw_sp_rif *rif;
7053 int err = 0;
7054
7055
7056 if (event == NETDEV_UP)
7057 return NOTIFY_DONE;
7058
7059 router = container_of(nb, struct mlxsw_sp_router, inetaddr_nb);
7060 mutex_lock(&router->lock);
7061 rif = mlxsw_sp_rif_find_by_dev(router->mlxsw_sp, dev);
7062 if (!mlxsw_sp_rif_should_config(rif, dev, event))
7063 goto out;
7064
7065 err = __mlxsw_sp_inetaddr_event(router->mlxsw_sp, dev, event, NULL);
7066out:
7067 mutex_unlock(&router->lock);
7068 return notifier_from_errno(err);
7069}
7070
7071int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused,
7072 unsigned long event, void *ptr)
7073{
7074 struct in_validator_info *ivi = (struct in_validator_info *) ptr;
7075 struct net_device *dev = ivi->ivi_dev->dev;
7076 struct mlxsw_sp *mlxsw_sp;
7077 struct mlxsw_sp_rif *rif;
7078 int err = 0;
7079
7080 mlxsw_sp = mlxsw_sp_lower_get(dev);
7081 if (!mlxsw_sp)
7082 return NOTIFY_DONE;
7083
7084 mutex_lock(&mlxsw_sp->router->lock);
7085 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
7086 if (!mlxsw_sp_rif_should_config(rif, dev, event))
7087 goto out;
7088
7089 err = mlxsw_sp_router_port_check_rif_addr(mlxsw_sp, dev, dev->dev_addr,
7090 ivi->extack);
7091 if (err)
7092 goto out;
7093
7094 err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, ivi->extack);
7095out:
7096 mutex_unlock(&mlxsw_sp->router->lock);
7097 return notifier_from_errno(err);
7098}
7099
7100struct mlxsw_sp_inet6addr_event_work {
7101 struct work_struct work;
7102 struct mlxsw_sp *mlxsw_sp;
7103 struct net_device *dev;
7104 unsigned long event;
7105};
7106
7107static void mlxsw_sp_inet6addr_event_work(struct work_struct *work)
7108{
7109 struct mlxsw_sp_inet6addr_event_work *inet6addr_work =
7110 container_of(work, struct mlxsw_sp_inet6addr_event_work, work);
7111 struct mlxsw_sp *mlxsw_sp = inet6addr_work->mlxsw_sp;
7112 struct net_device *dev = inet6addr_work->dev;
7113 unsigned long event = inet6addr_work->event;
7114 struct mlxsw_sp_rif *rif;
7115
7116 rtnl_lock();
7117 mutex_lock(&mlxsw_sp->router->lock);
7118
7119 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
7120 if (!mlxsw_sp_rif_should_config(rif, dev, event))
7121 goto out;
7122
7123 __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, NULL);
7124out:
7125 mutex_unlock(&mlxsw_sp->router->lock);
7126 rtnl_unlock();
7127 dev_put(dev);
7128 kfree(inet6addr_work);
7129}
7130
7131
7132static int mlxsw_sp_inet6addr_event(struct notifier_block *nb,
7133 unsigned long event, void *ptr)
7134{
7135 struct inet6_ifaddr *if6 = (struct inet6_ifaddr *) ptr;
7136 struct mlxsw_sp_inet6addr_event_work *inet6addr_work;
7137 struct net_device *dev = if6->idev->dev;
7138 struct mlxsw_sp_router *router;
7139
7140
7141 if (event == NETDEV_UP)
7142 return NOTIFY_DONE;
7143
7144 inet6addr_work = kzalloc(sizeof(*inet6addr_work), GFP_ATOMIC);
7145 if (!inet6addr_work)
7146 return NOTIFY_BAD;
7147
7148 router = container_of(nb, struct mlxsw_sp_router, inet6addr_nb);
7149 INIT_WORK(&inet6addr_work->work, mlxsw_sp_inet6addr_event_work);
7150 inet6addr_work->mlxsw_sp = router->mlxsw_sp;
7151 inet6addr_work->dev = dev;
7152 inet6addr_work->event = event;
7153 dev_hold(dev);
7154 mlxsw_core_schedule_work(&inet6addr_work->work);
7155
7156 return NOTIFY_DONE;
7157}
7158
7159int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused,
7160 unsigned long event, void *ptr)
7161{
7162 struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr;
7163 struct net_device *dev = i6vi->i6vi_dev->dev;
7164 struct mlxsw_sp *mlxsw_sp;
7165 struct mlxsw_sp_rif *rif;
7166 int err = 0;
7167
7168 mlxsw_sp = mlxsw_sp_lower_get(dev);
7169 if (!mlxsw_sp)
7170 return NOTIFY_DONE;
7171
7172 mutex_lock(&mlxsw_sp->router->lock);
7173 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
7174 if (!mlxsw_sp_rif_should_config(rif, dev, event))
7175 goto out;
7176
7177 err = mlxsw_sp_router_port_check_rif_addr(mlxsw_sp, dev, dev->dev_addr,
7178 i6vi->extack);
7179 if (err)
7180 goto out;
7181
7182 err = __mlxsw_sp_inetaddr_event(mlxsw_sp, dev, event, i6vi->extack);
7183out:
7184 mutex_unlock(&mlxsw_sp->router->lock);
7185 return notifier_from_errno(err);
7186}
7187
7188static int mlxsw_sp_rif_edit(struct mlxsw_sp *mlxsw_sp, u16 rif_index,
7189 const char *mac, int mtu)
7190{
7191 char ritr_pl[MLXSW_REG_RITR_LEN];
7192 int err;
7193
7194 mlxsw_reg_ritr_rif_pack(ritr_pl, rif_index);
7195 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7196 if (err)
7197 return err;
7198
7199 mlxsw_reg_ritr_mtu_set(ritr_pl, mtu);
7200 mlxsw_reg_ritr_if_mac_memcpy_to(ritr_pl, mac);
7201 mlxsw_reg_ritr_op_set(ritr_pl, MLXSW_REG_RITR_RIF_CREATE);
7202 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7203}
7204
7205static int
7206mlxsw_sp_router_port_change_event(struct mlxsw_sp *mlxsw_sp,
7207 struct mlxsw_sp_rif *rif)
7208{
7209 struct net_device *dev = rif->dev;
7210 u16 fid_index;
7211 int err;
7212
7213 fid_index = mlxsw_sp_fid_index(rif->fid);
7214
7215 err = mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, false);
7216 if (err)
7217 return err;
7218
7219 err = mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, dev->dev_addr,
7220 dev->mtu);
7221 if (err)
7222 goto err_rif_edit;
7223
7224 err = mlxsw_sp_rif_fdb_op(mlxsw_sp, dev->dev_addr, fid_index, true);
7225 if (err)
7226 goto err_rif_fdb_op;
7227
7228 if (rif->mtu != dev->mtu) {
7229 struct mlxsw_sp_vr *vr;
7230 int i;
7231
7232
7233
7234
7235
7236 vr = &mlxsw_sp->router->vrs[rif->vr_id];
7237 for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
7238 mlxsw_sp_mr_rif_mtu_update(vr->mr_table[i],
7239 rif, dev->mtu);
7240 }
7241
7242 ether_addr_copy(rif->addr, dev->dev_addr);
7243 rif->mtu = dev->mtu;
7244
7245 netdev_dbg(dev, "Updated RIF=%d\n", rif->rif_index);
7246
7247 return 0;
7248
7249err_rif_fdb_op:
7250 mlxsw_sp_rif_edit(mlxsw_sp, rif->rif_index, rif->addr, rif->mtu);
7251err_rif_edit:
7252 mlxsw_sp_rif_fdb_op(mlxsw_sp, rif->addr, fid_index, true);
7253 return err;
7254}
7255
7256static int mlxsw_sp_router_port_pre_changeaddr_event(struct mlxsw_sp_rif *rif,
7257 struct netdev_notifier_pre_changeaddr_info *info)
7258{
7259 struct netlink_ext_ack *extack;
7260
7261 extack = netdev_notifier_info_to_extack(&info->info);
7262 return mlxsw_sp_router_port_check_rif_addr(rif->mlxsw_sp, rif->dev,
7263 info->dev_addr, extack);
7264}
7265
7266int mlxsw_sp_netdevice_router_port_event(struct net_device *dev,
7267 unsigned long event, void *ptr)
7268{
7269 struct mlxsw_sp *mlxsw_sp;
7270 struct mlxsw_sp_rif *rif;
7271 int err = 0;
7272
7273 mlxsw_sp = mlxsw_sp_lower_get(dev);
7274 if (!mlxsw_sp)
7275 return 0;
7276
7277 mutex_lock(&mlxsw_sp->router->lock);
7278 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, dev);
7279 if (!rif)
7280 goto out;
7281
7282 switch (event) {
7283 case NETDEV_CHANGEMTU:
7284 case NETDEV_CHANGEADDR:
7285 err = mlxsw_sp_router_port_change_event(mlxsw_sp, rif);
7286 break;
7287 case NETDEV_PRE_CHANGEADDR:
7288 err = mlxsw_sp_router_port_pre_changeaddr_event(rif, ptr);
7289 break;
7290 }
7291
7292out:
7293 mutex_unlock(&mlxsw_sp->router->lock);
7294 return err;
7295}
7296
7297static int mlxsw_sp_port_vrf_join(struct mlxsw_sp *mlxsw_sp,
7298 struct net_device *l3_dev,
7299 struct netlink_ext_ack *extack)
7300{
7301 struct mlxsw_sp_rif *rif;
7302
7303
7304
7305
7306 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
7307 if (rif)
7308 __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN,
7309 extack);
7310
7311 return __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_UP, extack);
7312}
7313
7314static void mlxsw_sp_port_vrf_leave(struct mlxsw_sp *mlxsw_sp,
7315 struct net_device *l3_dev)
7316{
7317 struct mlxsw_sp_rif *rif;
7318
7319 rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
7320 if (!rif)
7321 return;
7322 __mlxsw_sp_inetaddr_event(mlxsw_sp, l3_dev, NETDEV_DOWN, NULL);
7323}
7324
7325int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
7326 struct netdev_notifier_changeupper_info *info)
7327{
7328 struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(l3_dev);
7329 int err = 0;
7330
7331
7332
7333
7334 if (!mlxsw_sp || netif_is_macvlan(l3_dev))
7335 return 0;
7336
7337 mutex_lock(&mlxsw_sp->router->lock);
7338 switch (event) {
7339 case NETDEV_PRECHANGEUPPER:
7340 break;
7341 case NETDEV_CHANGEUPPER:
7342 if (info->linking) {
7343 struct netlink_ext_ack *extack;
7344
7345 extack = netdev_notifier_info_to_extack(&info->info);
7346 err = mlxsw_sp_port_vrf_join(mlxsw_sp, l3_dev, extack);
7347 } else {
7348 mlxsw_sp_port_vrf_leave(mlxsw_sp, l3_dev);
7349 }
7350 break;
7351 }
7352 mutex_unlock(&mlxsw_sp->router->lock);
7353
7354 return err;
7355}
7356
7357static int __mlxsw_sp_rif_macvlan_flush(struct net_device *dev, void *data)
7358{
7359 struct mlxsw_sp_rif *rif = data;
7360
7361 if (!netif_is_macvlan(dev))
7362 return 0;
7363
7364 return mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, dev->dev_addr,
7365 mlxsw_sp_fid_index(rif->fid), false);
7366}
7367
7368static int mlxsw_sp_rif_macvlan_flush(struct mlxsw_sp_rif *rif)
7369{
7370 if (!netif_is_macvlan_port(rif->dev))
7371 return 0;
7372
7373 netdev_warn(rif->dev, "Router interface is deleted. Upper macvlans will not work\n");
7374 return netdev_walk_all_upper_dev_rcu(rif->dev,
7375 __mlxsw_sp_rif_macvlan_flush, rif);
7376}
7377
7378static void mlxsw_sp_rif_subport_setup(struct mlxsw_sp_rif *rif,
7379 const struct mlxsw_sp_rif_params *params)
7380{
7381 struct mlxsw_sp_rif_subport *rif_subport;
7382
7383 rif_subport = mlxsw_sp_rif_subport_rif(rif);
7384 refcount_set(&rif_subport->ref_count, 1);
7385 rif_subport->vid = params->vid;
7386 rif_subport->lag = params->lag;
7387 if (params->lag)
7388 rif_subport->lag_id = params->lag_id;
7389 else
7390 rif_subport->system_port = params->system_port;
7391}
7392
7393static int mlxsw_sp_rif_subport_op(struct mlxsw_sp_rif *rif, bool enable)
7394{
7395 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7396 struct mlxsw_sp_rif_subport *rif_subport;
7397 char ritr_pl[MLXSW_REG_RITR_LEN];
7398
7399 rif_subport = mlxsw_sp_rif_subport_rif(rif);
7400 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_SP_IF,
7401 rif->rif_index, rif->vr_id, rif->dev->mtu);
7402 mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
7403 mlxsw_reg_ritr_sp_if_pack(ritr_pl, rif_subport->lag,
7404 rif_subport->lag ? rif_subport->lag_id :
7405 rif_subport->system_port,
7406 rif_subport->vid);
7407
7408 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7409}
7410
7411static int mlxsw_sp_rif_subport_configure(struct mlxsw_sp_rif *rif)
7412{
7413 int err;
7414
7415 err = mlxsw_sp_rif_subport_op(rif, true);
7416 if (err)
7417 return err;
7418
7419 err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
7420 mlxsw_sp_fid_index(rif->fid), true);
7421 if (err)
7422 goto err_rif_fdb_op;
7423
7424 mlxsw_sp_fid_rif_set(rif->fid, rif);
7425 return 0;
7426
7427err_rif_fdb_op:
7428 mlxsw_sp_rif_subport_op(rif, false);
7429 return err;
7430}
7431
7432static void mlxsw_sp_rif_subport_deconfigure(struct mlxsw_sp_rif *rif)
7433{
7434 struct mlxsw_sp_fid *fid = rif->fid;
7435
7436 mlxsw_sp_fid_rif_set(fid, NULL);
7437 mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
7438 mlxsw_sp_fid_index(fid), false);
7439 mlxsw_sp_rif_macvlan_flush(rif);
7440 mlxsw_sp_rif_subport_op(rif, false);
7441}
7442
7443static struct mlxsw_sp_fid *
7444mlxsw_sp_rif_subport_fid_get(struct mlxsw_sp_rif *rif,
7445 struct netlink_ext_ack *extack)
7446{
7447 return mlxsw_sp_fid_rfid_get(rif->mlxsw_sp, rif->rif_index);
7448}
7449
7450static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_subport_ops = {
7451 .type = MLXSW_SP_RIF_TYPE_SUBPORT,
7452 .rif_size = sizeof(struct mlxsw_sp_rif_subport),
7453 .setup = mlxsw_sp_rif_subport_setup,
7454 .configure = mlxsw_sp_rif_subport_configure,
7455 .deconfigure = mlxsw_sp_rif_subport_deconfigure,
7456 .fid_get = mlxsw_sp_rif_subport_fid_get,
7457};
7458
7459static int mlxsw_sp_rif_vlan_fid_op(struct mlxsw_sp_rif *rif,
7460 enum mlxsw_reg_ritr_if_type type,
7461 u16 vid_fid, bool enable)
7462{
7463 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7464 char ritr_pl[MLXSW_REG_RITR_LEN];
7465
7466 mlxsw_reg_ritr_pack(ritr_pl, enable, type, rif->rif_index, rif->vr_id,
7467 rif->dev->mtu);
7468 mlxsw_reg_ritr_mac_pack(ritr_pl, rif->dev->dev_addr);
7469 mlxsw_reg_ritr_fid_set(ritr_pl, type, vid_fid);
7470
7471 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7472}
7473
7474u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp)
7475{
7476 return mlxsw_core_max_ports(mlxsw_sp->core) + 1;
7477}
7478
7479static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif)
7480{
7481 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7482 u16 fid_index = mlxsw_sp_fid_index(rif->fid);
7483 int err;
7484
7485 err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index,
7486 true);
7487 if (err)
7488 return err;
7489
7490 err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
7491 mlxsw_sp_router_port(mlxsw_sp), true);
7492 if (err)
7493 goto err_fid_mc_flood_set;
7494
7495 err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
7496 mlxsw_sp_router_port(mlxsw_sp), true);
7497 if (err)
7498 goto err_fid_bc_flood_set;
7499
7500 err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
7501 mlxsw_sp_fid_index(rif->fid), true);
7502 if (err)
7503 goto err_rif_fdb_op;
7504
7505 mlxsw_sp_fid_rif_set(rif->fid, rif);
7506 return 0;
7507
7508err_rif_fdb_op:
7509 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
7510 mlxsw_sp_router_port(mlxsw_sp), false);
7511err_fid_bc_flood_set:
7512 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
7513 mlxsw_sp_router_port(mlxsw_sp), false);
7514err_fid_mc_flood_set:
7515 mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
7516 return err;
7517}
7518
7519static void mlxsw_sp_rif_fid_deconfigure(struct mlxsw_sp_rif *rif)
7520{
7521 u16 fid_index = mlxsw_sp_fid_index(rif->fid);
7522 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7523 struct mlxsw_sp_fid *fid = rif->fid;
7524
7525 mlxsw_sp_fid_rif_set(fid, NULL);
7526 mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr,
7527 mlxsw_sp_fid_index(fid), false);
7528 mlxsw_sp_rif_macvlan_flush(rif);
7529 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC,
7530 mlxsw_sp_router_port(mlxsw_sp), false);
7531 mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC,
7532 mlxsw_sp_router_port(mlxsw_sp), false);
7533 mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_FID_IF, fid_index, false);
7534}
7535
7536static struct mlxsw_sp_fid *
7537mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
7538 struct netlink_ext_ack *extack)
7539{
7540 return mlxsw_sp_fid_8021d_get(rif->mlxsw_sp, rif->dev->ifindex);
7541}
7542
7543static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
7544{
7545 struct switchdev_notifier_fdb_info info;
7546 struct net_device *dev;
7547
7548 dev = br_fdb_find_port(rif->dev, mac, 0);
7549 if (!dev)
7550 return;
7551
7552 info.addr = mac;
7553 info.vid = 0;
7554 call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
7555 NULL);
7556}
7557
7558static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
7559 .type = MLXSW_SP_RIF_TYPE_FID,
7560 .rif_size = sizeof(struct mlxsw_sp_rif),
7561 .configure = mlxsw_sp_rif_fid_configure,
7562 .deconfigure = mlxsw_sp_rif_fid_deconfigure,
7563 .fid_get = mlxsw_sp_rif_fid_fid_get,
7564 .fdb_del = mlxsw_sp_rif_fid_fdb_del,
7565};
7566
7567static struct mlxsw_sp_fid *
7568mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
7569 struct netlink_ext_ack *extack)
7570{
7571 struct net_device *br_dev = rif->dev;
7572 u16 vid;
7573 int err;
7574
7575 if (is_vlan_dev(rif->dev)) {
7576 vid = vlan_dev_vlan_id(rif->dev);
7577 br_dev = vlan_dev_real_dev(rif->dev);
7578 if (WARN_ON(!netif_is_bridge_master(br_dev)))
7579 return ERR_PTR(-EINVAL);
7580 } else {
7581 err = br_vlan_get_pvid(rif->dev, &vid);
7582 if (err < 0 || !vid) {
7583 NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID");
7584 return ERR_PTR(-EINVAL);
7585 }
7586 }
7587
7588 return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid);
7589}
7590
7591static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
7592{
7593 u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
7594 struct switchdev_notifier_fdb_info info;
7595 struct net_device *br_dev;
7596 struct net_device *dev;
7597
7598 br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev;
7599 dev = br_fdb_find_port(br_dev, mac, vid);
7600 if (!dev)
7601 return;
7602
7603 info.addr = mac;
7604 info.vid = vid;
7605 call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info,
7606 NULL);
7607}
7608
7609static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_emu_ops = {
7610 .type = MLXSW_SP_RIF_TYPE_VLAN,
7611 .rif_size = sizeof(struct mlxsw_sp_rif),
7612 .configure = mlxsw_sp_rif_fid_configure,
7613 .deconfigure = mlxsw_sp_rif_fid_deconfigure,
7614 .fid_get = mlxsw_sp_rif_vlan_fid_get,
7615 .fdb_del = mlxsw_sp_rif_vlan_fdb_del,
7616};
7617
7618static struct mlxsw_sp_rif_ipip_lb *
7619mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
7620{
7621 return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
7622}
7623
7624static void
7625mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
7626 const struct mlxsw_sp_rif_params *params)
7627{
7628 struct mlxsw_sp_rif_params_ipip_lb *params_lb;
7629 struct mlxsw_sp_rif_ipip_lb *rif_lb;
7630
7631 params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
7632 common);
7633 rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
7634 rif_lb->lb_config = params_lb->lb_config;
7635}
7636
7637static int
7638mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
7639{
7640 struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
7641 u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
7642 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7643 struct mlxsw_sp_vr *ul_vr;
7644 int err;
7645
7646 ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL);
7647 if (IS_ERR(ul_vr))
7648 return PTR_ERR(ul_vr);
7649
7650 err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, true);
7651 if (err)
7652 goto err_loopback_op;
7653
7654 lb_rif->ul_vr_id = ul_vr->id;
7655 lb_rif->ul_rif_id = 0;
7656 ++ul_vr->rif_count;
7657 return 0;
7658
7659err_loopback_op:
7660 mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
7661 return err;
7662}
7663
7664static void mlxsw_sp1_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
7665{
7666 struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
7667 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7668 struct mlxsw_sp_vr *ul_vr;
7669
7670 ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
7671 mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr->id, 0, false);
7672
7673 --ul_vr->rif_count;
7674 mlxsw_sp_vr_put(mlxsw_sp, ul_vr);
7675}
7676
7677static const struct mlxsw_sp_rif_ops mlxsw_sp1_rif_ipip_lb_ops = {
7678 .type = MLXSW_SP_RIF_TYPE_IPIP_LB,
7679 .rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb),
7680 .setup = mlxsw_sp_rif_ipip_lb_setup,
7681 .configure = mlxsw_sp1_rif_ipip_lb_configure,
7682 .deconfigure = mlxsw_sp1_rif_ipip_lb_deconfigure,
7683};
7684
7685const struct mlxsw_sp_rif_ops *mlxsw_sp1_rif_ops_arr[] = {
7686 [MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops,
7687 [MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_emu_ops,
7688 [MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops,
7689 [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp1_rif_ipip_lb_ops,
7690};
7691
7692static int
7693mlxsw_sp_rif_ipip_lb_ul_rif_op(struct mlxsw_sp_rif *ul_rif, bool enable)
7694{
7695 struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
7696 char ritr_pl[MLXSW_REG_RITR_LEN];
7697
7698 mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
7699 ul_rif->rif_index, ul_rif->vr_id, IP_MAX_MTU);
7700 mlxsw_reg_ritr_loopback_protocol_set(ritr_pl,
7701 MLXSW_REG_RITR_LOOPBACK_GENERIC);
7702
7703 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
7704}
7705
7706static struct mlxsw_sp_rif *
7707mlxsw_sp_ul_rif_create(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr,
7708 struct netlink_ext_ack *extack)
7709{
7710 struct mlxsw_sp_rif *ul_rif;
7711 u16 rif_index;
7712 int err;
7713
7714 err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
7715 if (err) {
7716 NL_SET_ERR_MSG_MOD(extack, "Exceeded number of supported router interfaces");
7717 return ERR_PTR(err);
7718 }
7719
7720 ul_rif = mlxsw_sp_rif_alloc(sizeof(*ul_rif), rif_index, vr->id, NULL);
7721 if (!ul_rif)
7722 return ERR_PTR(-ENOMEM);
7723
7724 mlxsw_sp->router->rifs[rif_index] = ul_rif;
7725 ul_rif->mlxsw_sp = mlxsw_sp;
7726 err = mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, true);
7727 if (err)
7728 goto ul_rif_op_err;
7729
7730 return ul_rif;
7731
7732ul_rif_op_err:
7733 mlxsw_sp->router->rifs[rif_index] = NULL;
7734 kfree(ul_rif);
7735 return ERR_PTR(err);
7736}
7737
7738static void mlxsw_sp_ul_rif_destroy(struct mlxsw_sp_rif *ul_rif)
7739{
7740 struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
7741
7742 mlxsw_sp_rif_ipip_lb_ul_rif_op(ul_rif, false);
7743 mlxsw_sp->router->rifs[ul_rif->rif_index] = NULL;
7744 kfree(ul_rif);
7745}
7746
7747static struct mlxsw_sp_rif *
7748mlxsw_sp_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 tb_id,
7749 struct netlink_ext_ack *extack)
7750{
7751 struct mlxsw_sp_vr *vr;
7752 int err;
7753
7754 vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id, extack);
7755 if (IS_ERR(vr))
7756 return ERR_CAST(vr);
7757
7758 if (refcount_inc_not_zero(&vr->ul_rif_refcnt))
7759 return vr->ul_rif;
7760
7761 vr->ul_rif = mlxsw_sp_ul_rif_create(mlxsw_sp, vr, extack);
7762 if (IS_ERR(vr->ul_rif)) {
7763 err = PTR_ERR(vr->ul_rif);
7764 goto err_ul_rif_create;
7765 }
7766
7767 vr->rif_count++;
7768 refcount_set(&vr->ul_rif_refcnt, 1);
7769
7770 return vr->ul_rif;
7771
7772err_ul_rif_create:
7773 mlxsw_sp_vr_put(mlxsw_sp, vr);
7774 return ERR_PTR(err);
7775}
7776
7777static void mlxsw_sp_ul_rif_put(struct mlxsw_sp_rif *ul_rif)
7778{
7779 struct mlxsw_sp *mlxsw_sp = ul_rif->mlxsw_sp;
7780 struct mlxsw_sp_vr *vr;
7781
7782 vr = &mlxsw_sp->router->vrs[ul_rif->vr_id];
7783
7784 if (!refcount_dec_and_test(&vr->ul_rif_refcnt))
7785 return;
7786
7787 vr->rif_count--;
7788 mlxsw_sp_ul_rif_destroy(ul_rif);
7789 mlxsw_sp_vr_put(mlxsw_sp, vr);
7790}
7791
7792int mlxsw_sp_router_ul_rif_get(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
7793 u16 *ul_rif_index)
7794{
7795 struct mlxsw_sp_rif *ul_rif;
7796 int err = 0;
7797
7798 mutex_lock(&mlxsw_sp->router->lock);
7799 ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
7800 if (IS_ERR(ul_rif)) {
7801 err = PTR_ERR(ul_rif);
7802 goto out;
7803 }
7804 *ul_rif_index = ul_rif->rif_index;
7805out:
7806 mutex_unlock(&mlxsw_sp->router->lock);
7807 return err;
7808}
7809
7810void mlxsw_sp_router_ul_rif_put(struct mlxsw_sp *mlxsw_sp, u16 ul_rif_index)
7811{
7812 struct mlxsw_sp_rif *ul_rif;
7813
7814 mutex_lock(&mlxsw_sp->router->lock);
7815 ul_rif = mlxsw_sp->router->rifs[ul_rif_index];
7816 if (WARN_ON(!ul_rif))
7817 goto out;
7818
7819 mlxsw_sp_ul_rif_put(ul_rif);
7820out:
7821 mutex_unlock(&mlxsw_sp->router->lock);
7822}
7823
7824static int
7825mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
7826{
7827 struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
7828 u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
7829 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7830 struct mlxsw_sp_rif *ul_rif;
7831 int err;
7832
7833 ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL);
7834 if (IS_ERR(ul_rif))
7835 return PTR_ERR(ul_rif);
7836
7837 err = mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, ul_rif->rif_index, true);
7838 if (err)
7839 goto err_loopback_op;
7840
7841 lb_rif->ul_vr_id = 0;
7842 lb_rif->ul_rif_id = ul_rif->rif_index;
7843
7844 return 0;
7845
7846err_loopback_op:
7847 mlxsw_sp_ul_rif_put(ul_rif);
7848 return err;
7849}
7850
7851static void mlxsw_sp2_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
7852{
7853 struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
7854 struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
7855 struct mlxsw_sp_rif *ul_rif;
7856
7857 ul_rif = mlxsw_sp_rif_by_index(mlxsw_sp, lb_rif->ul_rif_id);
7858 mlxsw_sp_rif_ipip_lb_op(lb_rif, 0, lb_rif->ul_rif_id, false);
7859 mlxsw_sp_ul_rif_put(ul_rif);
7860}
7861
7862static const struct mlxsw_sp_rif_ops mlxsw_sp2_rif_ipip_lb_ops = {
7863 .type = MLXSW_SP_RIF_TYPE_IPIP_LB,
7864 .rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb),
7865 .setup = mlxsw_sp_rif_ipip_lb_setup,
7866 .configure = mlxsw_sp2_rif_ipip_lb_configure,
7867 .deconfigure = mlxsw_sp2_rif_ipip_lb_deconfigure,
7868};
7869
7870const struct mlxsw_sp_rif_ops *mlxsw_sp2_rif_ops_arr[] = {
7871 [MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops,
7872 [MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_emu_ops,
7873 [MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops,
7874 [MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp2_rif_ipip_lb_ops,
7875};
7876
7877static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)
7878{
7879 u64 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
7880
7881 mlxsw_sp->router->rifs = kcalloc(max_rifs,
7882 sizeof(struct mlxsw_sp_rif *),
7883 GFP_KERNEL);
7884 if (!mlxsw_sp->router->rifs)
7885 return -ENOMEM;
7886
7887 return 0;
7888}
7889
7890static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp)
7891{
7892 int i;
7893
7894 for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
7895 WARN_ON_ONCE(mlxsw_sp->router->rifs[i]);
7896
7897 kfree(mlxsw_sp->router->rifs);
7898}
7899
7900static int
7901mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp *mlxsw_sp)
7902{
7903 char tigcr_pl[MLXSW_REG_TIGCR_LEN];
7904
7905 mlxsw_reg_tigcr_pack(tigcr_pl, true, 0);
7906 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tigcr), tigcr_pl);
7907}
7908
7909static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
7910{
7911 int err;
7912
7913 mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr;
7914 INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);
7915
7916 err = mlxsw_sp_ipip_ecn_encap_init(mlxsw_sp);
7917 if (err)
7918 return err;
7919 err = mlxsw_sp_ipip_ecn_decap_init(mlxsw_sp);
7920 if (err)
7921 return err;
7922
7923 return mlxsw_sp_ipip_config_tigcr(mlxsw_sp);
7924}
7925
7926static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp)
7927{
7928 WARN_ON(!list_empty(&mlxsw_sp->router->ipip_list));
7929}
7930
7931static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
7932{
7933 struct mlxsw_sp_router *router;
7934
7935
7936
7937
7938
7939 mlxsw_core_flush_owq();
7940 router = container_of(nb, struct mlxsw_sp_router, fib_nb);
7941 mlxsw_sp_router_fib_flush(router->mlxsw_sp);
7942}
7943
7944#ifdef CONFIG_IP_ROUTE_MULTIPATH
7945static void mlxsw_sp_mp_hash_header_set(char *recr2_pl, int header)
7946{
7947 mlxsw_reg_recr2_outer_header_enables_set(recr2_pl, header, true);
7948}
7949
7950static void mlxsw_sp_mp_hash_field_set(char *recr2_pl, int field)
7951{
7952 mlxsw_reg_recr2_outer_header_fields_enable_set(recr2_pl, field, true);
7953}
7954
7955static void mlxsw_sp_mp4_hash_init(struct mlxsw_sp *mlxsw_sp, char *recr2_pl)
7956{
7957 struct net *net = mlxsw_sp_net(mlxsw_sp);
7958 bool only_l3 = !net->ipv4.sysctl_fib_multipath_hash_policy;
7959
7960 mlxsw_sp_mp_hash_header_set(recr2_pl,
7961 MLXSW_REG_RECR2_IPV4_EN_NOT_TCP_NOT_UDP);
7962 mlxsw_sp_mp_hash_header_set(recr2_pl, MLXSW_REG_RECR2_IPV4_EN_TCP_UDP);
7963 mlxsw_reg_recr2_ipv4_sip_enable(recr2_pl);
7964 mlxsw_reg_recr2_ipv4_dip_enable(recr2_pl);
7965 if (only_l3)
7966 return;
7967 mlxsw_sp_mp_hash_header_set(recr2_pl, MLXSW_REG_RECR2_TCP_UDP_EN_IPV4);
7968 mlxsw_sp_mp_hash_field_set(recr2_pl, MLXSW_REG_RECR2_IPV4_PROTOCOL);
7969 mlxsw_sp_mp_hash_field_set(recr2_pl, MLXSW_REG_RECR2_TCP_UDP_SPORT);
7970 mlxsw_sp_mp_hash_field_set(recr2_pl, MLXSW_REG_RECR2_TCP_UDP_DPORT);
7971}
7972
7973static void mlxsw_sp_mp6_hash_init(struct mlxsw_sp *mlxsw_sp, char *recr2_pl)
7974{
7975 bool only_l3 = !ip6_multipath_hash_policy(mlxsw_sp_net(mlxsw_sp));
7976
7977 mlxsw_sp_mp_hash_header_set(recr2_pl,
7978 MLXSW_REG_RECR2_IPV6_EN_NOT_TCP_NOT_UDP);
7979 mlxsw_sp_mp_hash_header_set(recr2_pl, MLXSW_REG_RECR2_IPV6_EN_TCP_UDP);
7980 mlxsw_reg_recr2_ipv6_sip_enable(recr2_pl);
7981 mlxsw_reg_recr2_ipv6_dip_enable(recr2_pl);
7982 mlxsw_sp_mp_hash_field_set(recr2_pl, MLXSW_REG_RECR2_IPV6_NEXT_HEADER);
7983 if (only_l3) {
7984 mlxsw_sp_mp_hash_field_set(recr2_pl,
7985 MLXSW_REG_RECR2_IPV6_FLOW_LABEL);
7986 } else {
7987 mlxsw_sp_mp_hash_header_set(recr2_pl,
7988 MLXSW_REG_RECR2_TCP_UDP_EN_IPV6);
7989 mlxsw_sp_mp_hash_field_set(recr2_pl,
7990 MLXSW_REG_RECR2_TCP_UDP_SPORT);
7991 mlxsw_sp_mp_hash_field_set(recr2_pl,
7992 MLXSW_REG_RECR2_TCP_UDP_DPORT);
7993 }
7994}
7995
7996static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
7997{
7998 char recr2_pl[MLXSW_REG_RECR2_LEN];
7999 u32 seed;
8000
8001 seed = jhash(mlxsw_sp->base_mac, sizeof(mlxsw_sp->base_mac), 0);
8002 mlxsw_reg_recr2_pack(recr2_pl, seed);
8003 mlxsw_sp_mp4_hash_init(mlxsw_sp, recr2_pl);
8004 mlxsw_sp_mp6_hash_init(mlxsw_sp, recr2_pl);
8005
8006 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(recr2), recr2_pl);
8007}
8008#else
8009static int mlxsw_sp_mp_hash_init(struct mlxsw_sp *mlxsw_sp)
8010{
8011 return 0;
8012}
8013#endif
8014
8015static int mlxsw_sp_dscp_init(struct mlxsw_sp *mlxsw_sp)
8016{
8017 char rdpm_pl[MLXSW_REG_RDPM_LEN];
8018 unsigned int i;
8019
8020 MLXSW_REG_ZERO(rdpm, rdpm_pl);
8021
8022
8023
8024
8025
8026
8027 for (i = 0; i < MLXSW_REG_RDPM_DSCP_ENTRY_REC_MAX_COUNT; i++)
8028 mlxsw_reg_rdpm_pack(rdpm_pl, i, rt_tos2priority(i << 2));
8029
8030 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rdpm), rdpm_pl);
8031}
8032
8033static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
8034{
8035 struct net *net = mlxsw_sp_net(mlxsw_sp);
8036 bool usp = net->ipv4.sysctl_ip_fwd_update_priority;
8037 char rgcr_pl[MLXSW_REG_RGCR_LEN];
8038 u64 max_rifs;
8039 int err;
8040
8041 if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
8042 return -EIO;
8043 max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
8044
8045 mlxsw_reg_rgcr_pack(rgcr_pl, true, true);
8046 mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
8047 mlxsw_reg_rgcr_usp_set(rgcr_pl, usp);
8048 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
8049 if (err)
8050 return err;
8051 return 0;
8052}
8053
8054static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
8055{
8056 char rgcr_pl[MLXSW_REG_RGCR_LEN];
8057
8058 mlxsw_reg_rgcr_pack(rgcr_pl, false, false);
8059 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
8060}
8061
8062int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp,
8063 struct netlink_ext_ack *extack)
8064{
8065 struct mlxsw_sp_router *router;
8066 int err;
8067
8068 router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL);
8069 if (!router)
8070 return -ENOMEM;
8071 mutex_init(&router->lock);
8072 mlxsw_sp->router = router;
8073 router->mlxsw_sp = mlxsw_sp;
8074
8075 router->inetaddr_nb.notifier_call = mlxsw_sp_inetaddr_event;
8076 err = register_inetaddr_notifier(&router->inetaddr_nb);
8077 if (err)
8078 goto err_register_inetaddr_notifier;
8079
8080 router->inet6addr_nb.notifier_call = mlxsw_sp_inet6addr_event;
8081 err = register_inet6addr_notifier(&router->inet6addr_nb);
8082 if (err)
8083 goto err_register_inet6addr_notifier;
8084
8085 INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_neighs_list);
8086 err = __mlxsw_sp_router_init(mlxsw_sp);
8087 if (err)
8088 goto err_router_init;
8089
8090 err = mlxsw_sp_rifs_init(mlxsw_sp);
8091 if (err)
8092 goto err_rifs_init;
8093
8094 err = mlxsw_sp_ipips_init(mlxsw_sp);
8095 if (err)
8096 goto err_ipips_init;
8097
8098 err = rhashtable_init(&mlxsw_sp->router->nexthop_ht,
8099 &mlxsw_sp_nexthop_ht_params);
8100 if (err)
8101 goto err_nexthop_ht_init;
8102
8103 err = rhashtable_init(&mlxsw_sp->router->nexthop_group_ht,
8104 &mlxsw_sp_nexthop_group_ht_params);
8105 if (err)
8106 goto err_nexthop_group_ht_init;
8107
8108 INIT_LIST_HEAD(&mlxsw_sp->router->nexthop_list);
8109 err = mlxsw_sp_lpm_init(mlxsw_sp);
8110 if (err)
8111 goto err_lpm_init;
8112
8113 err = mlxsw_sp_mr_init(mlxsw_sp, &mlxsw_sp_mr_tcam_ops);
8114 if (err)
8115 goto err_mr_init;
8116
8117 err = mlxsw_sp_vrs_init(mlxsw_sp);
8118 if (err)
8119 goto err_vrs_init;
8120
8121 err = mlxsw_sp_neigh_init(mlxsw_sp);
8122 if (err)
8123 goto err_neigh_init;
8124
8125 mlxsw_sp->router->netevent_nb.notifier_call =
8126 mlxsw_sp_router_netevent_event;
8127 err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb);
8128 if (err)
8129 goto err_register_netevent_notifier;
8130
8131 err = mlxsw_sp_mp_hash_init(mlxsw_sp);
8132 if (err)
8133 goto err_mp_hash_init;
8134
8135 err = mlxsw_sp_dscp_init(mlxsw_sp);
8136 if (err)
8137 goto err_dscp_init;
8138
8139 mlxsw_sp->router->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
8140 err = register_fib_notifier(mlxsw_sp_net(mlxsw_sp),
8141 &mlxsw_sp->router->fib_nb,
8142 mlxsw_sp_router_fib_dump_flush, extack);
8143 if (err)
8144 goto err_register_fib_notifier;
8145
8146 return 0;
8147
8148err_register_fib_notifier:
8149err_dscp_init:
8150err_mp_hash_init:
8151 unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb);
8152err_register_netevent_notifier:
8153 mlxsw_sp_neigh_fini(mlxsw_sp);
8154err_neigh_init:
8155 mlxsw_sp_vrs_fini(mlxsw_sp);
8156err_vrs_init:
8157 mlxsw_sp_mr_fini(mlxsw_sp);
8158err_mr_init:
8159 mlxsw_sp_lpm_fini(mlxsw_sp);
8160err_lpm_init:
8161 rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht);
8162err_nexthop_group_ht_init:
8163 rhashtable_destroy(&mlxsw_sp->router->nexthop_ht);
8164err_nexthop_ht_init:
8165 mlxsw_sp_ipips_fini(mlxsw_sp);
8166err_ipips_init:
8167 mlxsw_sp_rifs_fini(mlxsw_sp);
8168err_rifs_init:
8169 __mlxsw_sp_router_fini(mlxsw_sp);
8170err_router_init:
8171 unregister_inet6addr_notifier(&router->inet6addr_nb);
8172err_register_inet6addr_notifier:
8173 unregister_inetaddr_notifier(&router->inetaddr_nb);
8174err_register_inetaddr_notifier:
8175 mutex_destroy(&mlxsw_sp->router->lock);
8176 kfree(mlxsw_sp->router);
8177 return err;
8178}
8179
8180void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
8181{
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 mutex_destroy(&mlxsw_sp->router->lock);
8197 kfree(mlxsw_sp->router);
8198}
8199