|
@@ -84,43 +84,6 @@
|
|
|
#include <trace/events/fib.h>
|
|
|
#include "fib_lookup.h"
|
|
|
|
|
|
-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 ATOMIC_NOTIFIER_HEAD(fib_chain);
|
|
|
-
|
|
|
-static 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);
|
|
|
-}
|
|
|
-
|
|
|
-static void fib_rules_notify(struct net *net, struct notifier_block *nb,
|
|
|
- enum fib_event_type event_type)
|
|
|
-{
|
|
|
-#ifdef CONFIG_IP_MULTIPLE_TABLES
|
|
|
- struct fib_notifier_info info;
|
|
|
-
|
|
|
- if (net->ipv4.fib_has_custom_rules)
|
|
|
- call_fib_notifier(nb, net, event_type, &info);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-static void fib_notify(struct net *net, struct notifier_block *nb,
|
|
|
- enum fib_event_type event_type);
|
|
|
-
|
|
|
static int call_fib_entry_notifier(struct notifier_block *nb, struct net *net,
|
|
|
enum fib_event_type event_type, u32 dst,
|
|
|
int dst_len, struct fib_info *fi,
|
|
@@ -137,62 +100,6 @@ static int call_fib_entry_notifier(struct notifier_block *nb, struct net *net,
|
|
|
return call_fib_notifier(nb, net, event_type, &info.info);
|
|
|
}
|
|
|
|
|
|
-static bool fib_dump_is_consistent(struct notifier_block *nb,
|
|
|
- void (*cb)(struct notifier_block *nb),
|
|
|
- unsigned int fib_seq)
|
|
|
-{
|
|
|
- atomic_notifier_chain_register(&fib_chain, nb);
|
|
|
- if (fib_seq == fib_seq_sum())
|
|
|
- return true;
|
|
|
- atomic_notifier_chain_unregister(&fib_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 (fib_dump_is_consistent(nb, cb, fib_seq))
|
|
|
- return 0;
|
|
|
- } while (++retries < FIB_DUMP_MAX_RETRIES);
|
|
|
-
|
|
|
- return -EBUSY;
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(register_fib_notifier);
|
|
|
-
|
|
|
-int unregister_fib_notifier(struct notifier_block *nb)
|
|
|
-{
|
|
|
- return atomic_notifier_chain_unregister(&fib_chain, nb);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL(unregister_fib_notifier);
|
|
|
-
|
|
|
-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(&fib_chain, event_type, info);
|
|
|
-}
|
|
|
-
|
|
|
static int call_fib_entry_notifiers(struct net *net,
|
|
|
enum fib_event_type event_type, u32 dst,
|
|
|
int dst_len, struct fib_info *fi,
|
|
@@ -2036,8 +1943,8 @@ static void fib_table_notify(struct net *net, struct fib_table *tb,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void fib_notify(struct net *net, struct notifier_block *nb,
|
|
|
- enum fib_event_type event_type)
|
|
|
+void fib_notify(struct net *net, struct notifier_block *nb,
|
|
|
+ enum fib_event_type event_type)
|
|
|
{
|
|
|
unsigned int h;
|
|
|
|