From: Roopa Prabhu <ro...@cumulusnetworks.com> This patch adds nexthop add/del notifiers. To be used by vxlan driver in a later patch. Could possibly be used by switchdev drivers in the future.
Signed-off-by: Roopa Prabhu <ro...@cumulusnetworks.com> --- include/net/netns/nexthop.h | 1 + include/net/nexthop.h | 12 ++++++++++++ net/ipv4/nexthop.c | 27 +++++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/include/net/netns/nexthop.h b/include/net/netns/nexthop.h index c712ee5..1937476 100644 --- a/include/net/netns/nexthop.h +++ b/include/net/netns/nexthop.h @@ -14,5 +14,6 @@ struct netns_nexthop { unsigned int seq; /* protected by rtnl_mutex */ u32 last_id_allocated; + struct atomic_notifier_head notifier_chain; }; #endif diff --git a/include/net/nexthop.h b/include/net/nexthop.h index 3ad4e97..0301740 100644 --- a/include/net/nexthop.h +++ b/include/net/nexthop.h @@ -10,6 +10,7 @@ #define __LINUX_NEXTHOP_H #include <linux/netdevice.h> +#include <linux/notifier.h> #include <linux/route.h> #include <linux/types.h> #include <net/ip_fib.h> @@ -102,6 +103,17 @@ struct nexthop { }; }; +enum nexthop_event_type { + NEXTHOP_EVENT_ADD, + NEXTHOP_EVENT_DEL +}; + +int call_nexthop_notifier(struct notifier_block *nb, struct net *net, + enum nexthop_event_type event_type, + struct nexthop *nh); +int register_nexthop_notifier(struct notifier_block *nb); +int unregister_nexthop_notifier(struct notifier_block *nb); + /* caller is holding rcu or rtnl; no reference taken to nexthop */ struct nexthop *nexthop_find_by_id(struct net *net, u32 id); void nexthop_free_rcu(struct rcu_head *head); diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c index 98f8d2a..514bb4e 100644 --- a/net/ipv4/nexthop.c +++ b/net/ipv4/nexthop.c @@ -36,6 +36,17 @@ static const struct nla_policy rtm_nh_policy[NHA_MAX + 1] = { [NHA_FDB] = { .type = NLA_FLAG }, }; +static int call_nexthop_notifiers(struct net *net, + enum fib_event_type event_type, + struct nexthop *nh) +{ + int err; + + err = atomic_notifier_call_chain(&net->nexthop.notifier_chain, + event_type, nh); + return notifier_to_errno(err); +} + static unsigned int nh_dev_hashfn(unsigned int val) { unsigned int mask = NH_DEV_HASHSIZE - 1; @@ -814,6 +825,8 @@ static void __remove_nexthop_fib(struct net *net, struct nexthop *nh) ipv6_stub->ip6_del_rt(net, f6i, !net->ipv4.sysctl_nexthop_compat_mode); } + + call_nexthop_notifiers(net, NEXTHOP_EVENT_DEL, nh); } static void __remove_nexthop(struct net *net, struct nexthop *nh, @@ -1838,6 +1851,20 @@ static struct notifier_block nh_netdev_notifier = { .notifier_call = nh_netdev_event, }; +static ATOMIC_NOTIFIER_HEAD(nexthop_notif_chain); + +int register_nexthop_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&nexthop_notif_chain, nb); +} +EXPORT_SYMBOL(register_nexthop_notifier); + +int unregister_nexthop_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&nexthop_notif_chain, nb); +} +EXPORT_SYMBOL(unregister_nexthop_notifier); + static void __net_exit nexthop_net_exit(struct net *net) { rtnl_lock(); -- 2.1.4