8
8
#include <net/switchdev.h>
9
9
#include <linux/rhashtable.h>
10
10
#include <net/nexthop.h>
11
+ #include <net/netevent.h>
11
12
12
13
#include "prestera.h"
13
14
#include "prestera_router_hw.h"
@@ -604,6 +605,56 @@ static int __prestera_router_fib_event(struct notifier_block *nb,
604
605
return NOTIFY_DONE ;
605
606
}
606
607
608
+ struct prestera_netevent_work {
609
+ struct work_struct work ;
610
+ struct prestera_switch * sw ;
611
+ struct neighbour * n ;
612
+ };
613
+
614
+ static void prestera_router_neigh_event_work (struct work_struct * work )
615
+ {
616
+ struct prestera_netevent_work * net_work =
617
+ container_of (work , struct prestera_netevent_work , work );
618
+ struct neighbour * n = net_work -> n ;
619
+
620
+ /* neigh - its not hw related object. It stored only in kernel. So... */
621
+ rtnl_lock ();
622
+
623
+ /* TODO: handler */
624
+
625
+ neigh_release (n );
626
+ rtnl_unlock ();
627
+ kfree (net_work );
628
+ }
629
+
630
+ static int prestera_router_netevent_event (struct notifier_block * nb ,
631
+ unsigned long event , void * ptr )
632
+ {
633
+ struct prestera_netevent_work * net_work ;
634
+ struct prestera_router * router ;
635
+ struct neighbour * n = ptr ;
636
+
637
+ router = container_of (nb , struct prestera_router , netevent_nb );
638
+
639
+ switch (event ) {
640
+ case NETEVENT_NEIGH_UPDATE :
641
+ if (n -> tbl -> family != AF_INET )
642
+ return NOTIFY_DONE ;
643
+
644
+ net_work = kzalloc (sizeof (* net_work ), GFP_ATOMIC );
645
+ if (WARN_ON (!net_work ))
646
+ return NOTIFY_BAD ;
647
+
648
+ neigh_clone (n );
649
+ net_work -> n = n ;
650
+ net_work -> sw = router -> sw ;
651
+ INIT_WORK (& net_work -> work , prestera_router_neigh_event_work );
652
+ prestera_queue_work (& net_work -> work );
653
+ }
654
+
655
+ return NOTIFY_DONE ;
656
+ }
657
+
607
658
int prestera_router_init (struct prestera_switch * sw )
608
659
{
609
660
struct prestera_router * router ;
@@ -642,6 +693,11 @@ int prestera_router_init(struct prestera_switch *sw)
642
693
if (err )
643
694
goto err_register_inetaddr_notifier ;
644
695
696
+ router -> netevent_nb .notifier_call = prestera_router_netevent_event ;
697
+ err = register_netevent_notifier (& router -> netevent_nb );
698
+ if (err )
699
+ goto err_register_netevent_notifier ;
700
+
645
701
router -> fib_nb .notifier_call = __prestera_router_fib_event ;
646
702
err = register_fib_notifier (& init_net , & router -> fib_nb ,
647
703
/* TODO: flush fib entries */ NULL , NULL );
@@ -651,6 +707,8 @@ int prestera_router_init(struct prestera_switch *sw)
651
707
return 0 ;
652
708
653
709
err_register_fib_notifier :
710
+ unregister_netevent_notifier (& router -> netevent_nb );
711
+ err_register_netevent_notifier :
654
712
unregister_inetaddr_notifier (& router -> inetaddr_nb );
655
713
err_register_inetaddr_notifier :
656
714
unregister_inetaddr_validator_notifier (& router -> inetaddr_valid_nb );
@@ -668,6 +726,7 @@ int prestera_router_init(struct prestera_switch *sw)
668
726
void prestera_router_fini (struct prestera_switch * sw )
669
727
{
670
728
unregister_fib_notifier (& init_net , & sw -> router -> fib_nb );
729
+ unregister_netevent_notifier (& sw -> router -> netevent_nb );
671
730
unregister_inetaddr_notifier (& sw -> router -> inetaddr_nb );
672
731
unregister_inetaddr_validator_notifier (& sw -> router -> inetaddr_valid_nb );
673
732
prestera_queue_drain ();
0 commit comments