38
38
#include <linux/rhashtable.h>
39
39
#include <linux/bitops.h>
40
40
#include <linux/in6.h>
41
+ #include <net/neighbour.h>
42
+ #include <net/arp.h>
41
43
42
44
#include "spectrum.h"
43
45
#include "core.h"
@@ -544,6 +546,147 @@ static void mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
544
546
}
545
547
}
546
548
549
+ struct mlxsw_sp_neigh_key {
550
+ unsigned char addr [sizeof (struct in6_addr )];
551
+ struct net_device * dev ;
552
+ };
553
+
554
+ struct mlxsw_sp_neigh_entry {
555
+ struct rhash_head ht_node ;
556
+ struct mlxsw_sp_neigh_key key ;
557
+ u16 rif ;
558
+ struct neighbour * n ;
559
+ };
560
+
561
+ static const struct rhashtable_params mlxsw_sp_neigh_ht_params = {
562
+ .key_offset = offsetof(struct mlxsw_sp_neigh_entry , key ),
563
+ .head_offset = offsetof(struct mlxsw_sp_neigh_entry , ht_node ),
564
+ .key_len = sizeof (struct mlxsw_sp_neigh_key ),
565
+ };
566
+
567
+ static int
568
+ mlxsw_sp_neigh_entry_insert (struct mlxsw_sp * mlxsw_sp ,
569
+ struct mlxsw_sp_neigh_entry * neigh_entry )
570
+ {
571
+ return rhashtable_insert_fast (& mlxsw_sp -> router .neigh_ht ,
572
+ & neigh_entry -> ht_node ,
573
+ mlxsw_sp_neigh_ht_params );
574
+ }
575
+
576
+ static void
577
+ mlxsw_sp_neigh_entry_remove (struct mlxsw_sp * mlxsw_sp ,
578
+ struct mlxsw_sp_neigh_entry * neigh_entry )
579
+ {
580
+ rhashtable_remove_fast (& mlxsw_sp -> router .neigh_ht ,
581
+ & neigh_entry -> ht_node ,
582
+ mlxsw_sp_neigh_ht_params );
583
+ }
584
+
585
+ static struct mlxsw_sp_neigh_entry *
586
+ mlxsw_sp_neigh_entry_create (const void * addr , size_t addr_len ,
587
+ struct net_device * dev , u16 rif ,
588
+ struct neighbour * n )
589
+ {
590
+ struct mlxsw_sp_neigh_entry * neigh_entry ;
591
+
592
+ neigh_entry = kzalloc (sizeof (* neigh_entry ), GFP_ATOMIC );
593
+ if (!neigh_entry )
594
+ return NULL ;
595
+ memcpy (neigh_entry -> key .addr , addr , addr_len );
596
+ neigh_entry -> key .dev = dev ;
597
+ neigh_entry -> rif = rif ;
598
+ neigh_entry -> n = n ;
599
+ return neigh_entry ;
600
+ }
601
+
602
+ static void
603
+ mlxsw_sp_neigh_entry_destroy (struct mlxsw_sp_neigh_entry * neigh_entry )
604
+ {
605
+ kfree (neigh_entry );
606
+ }
607
+
608
+ static struct mlxsw_sp_neigh_entry *
609
+ mlxsw_sp_neigh_entry_lookup (struct mlxsw_sp * mlxsw_sp , const void * addr ,
610
+ size_t addr_len , struct net_device * dev )
611
+ {
612
+ struct mlxsw_sp_neigh_key key = {{ 0 } };
613
+
614
+ memcpy (key .addr , addr , addr_len );
615
+ key .dev = dev ;
616
+ return rhashtable_lookup_fast (& mlxsw_sp -> router .neigh_ht ,
617
+ & key , mlxsw_sp_neigh_ht_params );
618
+ }
619
+
620
+ int mlxsw_sp_router_neigh_construct (struct net_device * dev ,
621
+ struct neighbour * n )
622
+ {
623
+ struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (dev );
624
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
625
+ struct mlxsw_sp_neigh_entry * neigh_entry ;
626
+ struct mlxsw_sp_rif * r ;
627
+ u32 dip ;
628
+ int err ;
629
+
630
+ if (n -> tbl != & arp_tbl )
631
+ return 0 ;
632
+
633
+ dip = ntohl (* ((__be32 * ) n -> primary_key ));
634
+ neigh_entry = mlxsw_sp_neigh_entry_lookup (mlxsw_sp , & dip , sizeof (dip ),
635
+ n -> dev );
636
+ if (neigh_entry ) {
637
+ WARN_ON (neigh_entry -> n != n );
638
+ return 0 ;
639
+ }
640
+
641
+ r = mlxsw_sp_rif_find_by_dev (mlxsw_sp , dev );
642
+ if (WARN_ON (!r ))
643
+ return - EINVAL ;
644
+
645
+ neigh_entry = mlxsw_sp_neigh_entry_create (& dip , sizeof (dip ), n -> dev ,
646
+ r -> rif , n );
647
+ if (!neigh_entry )
648
+ return - ENOMEM ;
649
+ err = mlxsw_sp_neigh_entry_insert (mlxsw_sp , neigh_entry );
650
+ if (err )
651
+ goto err_neigh_entry_insert ;
652
+ return 0 ;
653
+
654
+ err_neigh_entry_insert :
655
+ mlxsw_sp_neigh_entry_destroy (neigh_entry );
656
+ return err ;
657
+ }
658
+
659
+ void mlxsw_sp_router_neigh_destroy (struct net_device * dev ,
660
+ struct neighbour * n )
661
+ {
662
+ struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (dev );
663
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
664
+ struct mlxsw_sp_neigh_entry * neigh_entry ;
665
+ u32 dip ;
666
+
667
+ if (n -> tbl != & arp_tbl )
668
+ return ;
669
+
670
+ dip = ntohl (* ((__be32 * ) n -> primary_key ));
671
+ neigh_entry = mlxsw_sp_neigh_entry_lookup (mlxsw_sp , & dip , sizeof (dip ),
672
+ n -> dev );
673
+ if (!neigh_entry )
674
+ return ;
675
+ mlxsw_sp_neigh_entry_remove (mlxsw_sp , neigh_entry );
676
+ mlxsw_sp_neigh_entry_destroy (neigh_entry );
677
+ }
678
+
679
+ static int mlxsw_sp_neigh_init (struct mlxsw_sp * mlxsw_sp )
680
+ {
681
+ return rhashtable_init (& mlxsw_sp -> router .neigh_ht ,
682
+ & mlxsw_sp_neigh_ht_params );
683
+ }
684
+
685
+ static void mlxsw_sp_neigh_fini (struct mlxsw_sp * mlxsw_sp )
686
+ {
687
+ rhashtable_destroy (& mlxsw_sp -> router .neigh_ht );
688
+ }
689
+
547
690
static int __mlxsw_sp_router_init (struct mlxsw_sp * mlxsw_sp )
548
691
{
549
692
char rgcr_pl [MLXSW_REG_RGCR_LEN ];
@@ -570,11 +713,12 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
570
713
return err ;
571
714
mlxsw_sp_lpm_init (mlxsw_sp );
572
715
mlxsw_sp_vrs_init (mlxsw_sp );
573
- return 0 ;
716
+ return mlxsw_sp_neigh_init ( mlxsw_sp ) ;
574
717
}
575
718
576
719
void mlxsw_sp_router_fini (struct mlxsw_sp * mlxsw_sp )
577
720
{
721
+ mlxsw_sp_neigh_fini (mlxsw_sp );
578
722
__mlxsw_sp_router_fini (mlxsw_sp );
579
723
}
580
724
0 commit comments