88#include <net/switchdev.h>
99#include <linux/rhashtable.h>
1010#include <net/nexthop.h>
11+ #include <net/netevent.h>
1112
1213#include "prestera.h"
1314#include "prestera_router_hw.h"
@@ -604,6 +605,56 @@ static int __prestera_router_fib_event(struct notifier_block *nb,
604605 return NOTIFY_DONE ;
605606}
606607
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+
607658int prestera_router_init (struct prestera_switch * sw )
608659{
609660 struct prestera_router * router ;
@@ -642,6 +693,11 @@ int prestera_router_init(struct prestera_switch *sw)
642693 if (err )
643694 goto err_register_inetaddr_notifier ;
644695
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+
645701 router -> fib_nb .notifier_call = __prestera_router_fib_event ;
646702 err = register_fib_notifier (& init_net , & router -> fib_nb ,
647703 /* TODO: flush fib entries */ NULL , NULL );
@@ -651,6 +707,8 @@ int prestera_router_init(struct prestera_switch *sw)
651707 return 0 ;
652708
653709err_register_fib_notifier :
710+ unregister_netevent_notifier (& router -> netevent_nb );
711+ err_register_netevent_notifier :
654712 unregister_inetaddr_notifier (& router -> inetaddr_nb );
655713err_register_inetaddr_notifier :
656714 unregister_inetaddr_validator_notifier (& router -> inetaddr_valid_nb );
@@ -668,6 +726,7 @@ int prestera_router_init(struct prestera_switch *sw)
668726void prestera_router_fini (struct prestera_switch * sw )
669727{
670728 unregister_fib_notifier (& init_net , & sw -> router -> fib_nb );
729+ unregister_netevent_notifier (& sw -> router -> netevent_nb );
671730 unregister_inetaddr_notifier (& sw -> router -> inetaddr_nb );
672731 unregister_inetaddr_validator_notifier (& sw -> router -> inetaddr_valid_nb );
673732 prestera_queue_drain ();
0 commit comments