Re: [patch net-next 1/2] ipv4: fib: Move FIB notification code to a separate file

2017-03-10 Thread David Ahern
On 3/10/17 12:56 AM, Jiri Pirko wrote:
> From: Ido Schimmel 
> 
> Most of the code concerned with the FIB notification chain currently
> resides in fib_trie.c, but this isn't really appropriate, as the FIB
> notification chain is also used for FIB rules.
> 
> Therefore, it makes sense to move the common FIB notification code to a
> separate file and have it export the relevant functions, which can be
> invoked by its different users (e.g., fib_trie.c, fib_rules.c).
> 
> Signed-off-by: Ido Schimmel 
> Signed-off-by: Jiri Pirko 
> ---
>  include/net/ip_fib.h| 15 
>  net/ipv4/Makefile   |  2 +-
>  net/ipv4/fib_notifier.c | 86 +++
>  net/ipv4/fib_rules.c|  9 +
>  net/ipv4/fib_trie.c | 97 
> +
>  5 files changed, 113 insertions(+), 96 deletions(-)
>  create mode 100644 net/ipv4/fib_notifier.c
> 

Acked-by: David Ahern 


[patch net-next 1/2] ipv4: fib: Move FIB notification code to a separate file

2017-03-09 Thread Jiri Pirko
From: Ido Schimmel 

Most of the code concerned with the FIB notification chain currently
resides in fib_trie.c, but this isn't really appropriate, as the FIB
notification chain is also used for FIB rules.

Therefore, it makes sense to move the common FIB notification code to a
separate file and have it export the relevant functions, which can be
invoked by its different users (e.g., fib_trie.c, fib_rules.c).

Signed-off-by: Ido Schimmel 
Signed-off-by: Jiri Pirko 
---
 include/net/ip_fib.h| 15 
 net/ipv4/Makefile   |  2 +-
 net/ipv4/fib_notifier.c | 86 +++
 net/ipv4/fib_rules.c|  9 +
 net/ipv4/fib_trie.c | 97 +
 5 files changed, 113 insertions(+), 96 deletions(-)
 create mode 100644 net/ipv4/fib_notifier.c

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 368bb40..3ad8706 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -232,9 +232,24 @@ enum fib_event_type {
 int register_fib_notifier(struct notifier_block *nb,
  void (*cb)(struct notifier_block *nb));
 int unregister_fib_notifier(struct notifier_block *nb);
+int call_fib_notifier(struct notifier_block *nb, struct net *net,
+ enum fib_event_type event_type,
+ struct fib_notifier_info *info);
 int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
   struct fib_notifier_info *info);
 
+void fib_notify(struct net *net, struct notifier_block *nb,
+   enum fib_event_type event_type);
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+void fib_rules_notify(struct net *net, struct notifier_block *nb,
+ enum fib_event_type event_type);
+#else
+static inline void fib_rules_notify(struct net *net, struct notifier_block *nb,
+   enum fib_event_type event_type)
+{
+}
+#endif
+
 struct fib_table {
struct hlist_node   tb_hlist;
u32 tb_id;
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index c6d4238..f83de23 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -11,7 +11,7 @@ obj-y := route.o inetpeer.o protocol.o \
 tcp_rate.o tcp_recovery.o \
 tcp_offload.o datagram.o raw.o udp.o udplite.o \
 udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \
-fib_frontend.o fib_semantics.o fib_trie.o \
+fib_frontend.o fib_semantics.o fib_trie.o fib_notifier.o \
 inet_fragment.o ping.o ip_tunnel_core.o gre_offload.o
 
 obj-$(CONFIG_NET_IP_TUNNEL) += ip_tunnel.o
diff --git a/net/ipv4/fib_notifier.c b/net/ipv4/fib_notifier.c
new file mode 100644
index 000..91f8f18
--- /dev/null
+++ b/net/ipv4/fib_notifier.c
@@ -0,0 +1,86 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static ATOMIC_NOTIFIER_HEAD(fib_chain);
+
+int call_fib_notifier(struct notifier_block *nb, struct net *net,
+ enum fib_event_type event_type,
+ struct fib_notifier_info *info)
+{
+   info->net = net;
+   return nb->notifier_call(nb, event_type, info);
+}
+
+int call_fib_notifiers(struct net *net, enum fib_event_type event_type,
+  struct fib_notifier_info *info)
+{
+   net->ipv4.fib_seq++;
+   info->net = net;
+   return atomic_notifier_call_chain(_chain, event_type, info);
+}
+
+static unsigned int fib_seq_sum(void)
+{
+   unsigned int fib_seq = 0;
+   struct net *net;
+
+   rtnl_lock();
+   for_each_net(net)
+   fib_seq += net->ipv4.fib_seq;
+   rtnl_unlock();
+
+   return fib_seq;
+}
+
+static bool fib_dump_is_consistent(struct notifier_block *nb,
+  void (*cb)(struct notifier_block *nb),
+  unsigned int fib_seq)
+{
+   atomic_notifier_chain_register(_chain, nb);
+   if (fib_seq == fib_seq_sum())
+   return true;
+   atomic_notifier_chain_unregister(_chain, nb);
+   if (cb)
+   cb(nb);
+   return false;
+}
+
+#define FIB_DUMP_MAX_RETRIES 5
+int register_fib_notifier(struct notifier_block *nb,
+ void (*cb)(struct notifier_block *nb))
+{
+   int retries = 0;
+
+   do {
+   unsigned int fib_seq = fib_seq_sum();
+   struct net *net;
+
+   /* Mutex semantics guarantee that every change done to
+* FIB tries before we read the change sequence counter
+* is now visible to us.
+*/
+   rcu_read_lock();
+   for_each_net_rcu(net) {
+   fib_rules_notify(net, nb, FIB_EVENT_RULE_ADD);
+   fib_notify(net, nb, FIB_EVENT_ENTRY_ADD);
+   }
+   rcu_read_unlock();
+
+   if