]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
ipv6: fib: Add FIB notifiers callbacks
authorIdo Schimmel <idosch@mellanox.com>
Thu, 3 Aug 2017 11:28:16 +0000 (13:28 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 3 Aug 2017 22:35:59 +0000 (15:35 -0700)
We're about to add IPv6 FIB offload support, so implement the necessary
callbacks in IPv6 code, which will later allow us to add routes and
rules notifications.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_fib.h
include/net/netns/ipv6.h
net/ipv6/Makefile
net/ipv6/fib6_notifier.c [new file with mode: 0644]
net/ipv6/ip6_fib.c

index 6000b0dc51eedb0ff6cc96ed9c1f4c6c16a1225e..be8ddf3253dcf671dbbac81aaf334d087806a63c 100644 (file)
 #include <linux/ipv6_route.h>
 #include <linux/rtnetlink.h>
 #include <linux/spinlock.h>
+#include <linux/notifier.h>
 #include <net/dst.h>
 #include <net/flow.h>
 #include <net/netlink.h>
 #include <net/inetpeer.h>
+#include <net/fib_notifier.h>
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 #define FIB6_TABLE_HASHSZ 256
@@ -292,6 +294,15 @@ int fib6_init(void);
 
 int ipv6_route_open(struct inode *inode, struct file *file);
 
+int call_fib6_notifier(struct notifier_block *nb, struct net *net,
+                      enum fib_event_type event_type,
+                      struct fib_notifier_info *info);
+int call_fib6_notifiers(struct net *net, enum fib_event_type event_type,
+                       struct fib_notifier_info *info);
+
+int __net_init fib6_notifier_init(struct net *net);
+void __net_exit fib6_notifier_exit(struct net *net);
+
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 int fib6_rules_init(void);
 void fib6_rules_cleanup(void);
index de7745e2edcc63e65c1ab224a6835367d55c54c4..abdf3b40303bf7539d3af68acefa55ff94008581 100644 (file)
@@ -86,6 +86,7 @@ struct netns_ipv6 {
        atomic_t                dev_addr_genid;
        atomic_t                fib6_sernum;
        struct seg6_pernet_data *seg6_data;
+       struct fib_notifier_ops *notifier_ops;
 };
 
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
index 217e9ff0e24b6db62307d27ddc50f1a88c2da73e..f8b24c2e0d77acf490c4e77ce5a39f8f59be5451 100644 (file)
@@ -9,7 +9,7 @@ ipv6-objs :=    af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
                route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
                raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \
                exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o \
-               udp_offload.o seg6.o
+               udp_offload.o seg6.o fib6_notifier.o
 
 ipv6-offload :=        ip6_offload.o tcpv6_offload.o exthdrs_offload.o
 
diff --git a/net/ipv6/fib6_notifier.c b/net/ipv6/fib6_notifier.c
new file mode 100644 (file)
index 0000000..c2bb1ab
--- /dev/null
@@ -0,0 +1,55 @@
+#include <linux/notifier.h>
+#include <linux/socket.h>
+#include <linux/kernel.h>
+#include <net/net_namespace.h>
+#include <net/fib_notifier.h>
+#include <net/netns/ipv6.h>
+#include <net/ip6_fib.h>
+
+int call_fib6_notifier(struct notifier_block *nb, struct net *net,
+                      enum fib_event_type event_type,
+                      struct fib_notifier_info *info)
+{
+       info->family = AF_INET6;
+       return call_fib_notifier(nb, net, event_type, info);
+}
+
+int call_fib6_notifiers(struct net *net, enum fib_event_type event_type,
+                       struct fib_notifier_info *info)
+{
+       info->family = AF_INET6;
+       return call_fib_notifiers(net, event_type, info);
+}
+
+static unsigned int fib6_seq_read(struct net *net)
+{
+       return 0;
+}
+
+static int fib6_dump(struct net *net, struct notifier_block *nb)
+{
+       return 0;
+}
+
+static const struct fib_notifier_ops fib6_notifier_ops_template = {
+       .family         = AF_INET6,
+       .fib_seq_read   = fib6_seq_read,
+       .fib_dump       = fib6_dump,
+};
+
+int __net_init fib6_notifier_init(struct net *net)
+{
+       struct fib_notifier_ops *ops;
+
+       ops = fib_notifier_ops_register(&fib6_notifier_ops_template, net);
+       if (IS_ERR(ops))
+               return PTR_ERR(ops);
+       net->ipv6.notifier_ops = ops;
+
+       return 0;
+}
+
+void __net_exit fib6_notifier_exit(struct net *net)
+{
+       fib_notifier_ops_unregister(net->ipv6.notifier_ops);
+}
index ebb299cf72b7e81b77999d43d2e7f83212386f73..f93976e3f65c3185b1e4f1d1ef2994d4f2c1fc93 100644 (file)
@@ -1839,6 +1839,11 @@ static void fib6_gc_timer_cb(unsigned long arg)
 static int __net_init fib6_net_init(struct net *net)
 {
        size_t size = sizeof(struct hlist_head) * FIB6_TABLE_HASHSZ;
+       int err;
+
+       err = fib6_notifier_init(net);
+       if (err)
+               return err;
 
        spin_lock_init(&net->ipv6.fib6_gc_lock);
        rwlock_init(&net->ipv6.fib6_walker_lock);
@@ -1891,6 +1896,7 @@ out_fib_table_hash:
 out_rt6_stats:
        kfree(net->ipv6.rt6_stats);
 out_timer:
+       fib6_notifier_exit(net);
        return -ENOMEM;
 }
 
@@ -1907,6 +1913,7 @@ static void fib6_net_exit(struct net *net)
        kfree(net->ipv6.fib6_main_tbl);
        kfree(net->ipv6.fib_table_hash);
        kfree(net->ipv6.rt6_stats);
+       fib6_notifier_exit(net);
 }
 
 static struct pernet_operations fib6_net_ops = {