Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01461abe authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'fib-notifications-cleanup'



Jiri Pirko says:

====================
ipv4: fib: FIB notifications cleanup

Ido says:

The first patch moves the core FIB notification code to a separate file,
so that code related to FIB rules is placed in fib_rules.c and not
fib_trie.c. The reason for the change will become even more apparent in
follow-up patchset where we extend the FIB rules notifications.

Second patch removes a redundant argument.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 71e8727e d05f7a7d
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -232,9 +232,21 @@ 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);
#ifdef CONFIG_IP_MULTIPLE_TABLES
void fib_rules_notify(struct net *net, struct notifier_block *nb);
#else
static inline void fib_rules_notify(struct net *net, struct notifier_block *nb)
{
}
#endif

struct fib_table {
	struct hlist_node	tb_hlist;
	u32			tb_id;
+1 −1
Original line number Diff line number Diff line
@@ -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
+86 −0
Original line number Diff line number Diff line
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
#include <linux/rcupdate.h>
#include <linux/kernel.h>
#include <net/net_namespace.h>
#include <net/netns/ipv4.h>
#include <net/ip_fib.h>

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(&fib_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(&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_notify(net, nb);
		}
		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);
+8 −0
Original line number Diff line number Diff line
@@ -172,6 +172,14 @@ static int call_fib_rule_notifiers(struct net *net,
	return call_fib_notifiers(net, event_type, &info);
}

void fib_rules_notify(struct net *net, struct notifier_block *nb)
{
	struct fib_notifier_info info;

	if (net->ipv4.fib_has_custom_rules)
		call_fib_notifier(nb, net, FIB_EVENT_RULE_ADD, &info);
}

static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {
	FRA_GENERIC_POLICY,
	[FRA_FLOW]	= { .type = NLA_U32 },
+6 −102
Original line number Diff line number Diff line
@@ -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,
@@ -1995,8 +1902,7 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
}

static void fib_leaf_notify(struct net *net, struct key_vector *l,
			    struct fib_table *tb, struct notifier_block *nb,
			    enum fib_event_type event_type)
			    struct fib_table *tb, struct notifier_block *nb)
{
	struct fib_alias *fa;

@@ -2012,22 +1918,21 @@ static void fib_leaf_notify(struct net *net, struct key_vector *l,
		if (tb->tb_id != fa->tb_id)
			continue;

		call_fib_entry_notifier(nb, net, event_type, l->key,
		call_fib_entry_notifier(nb, net, FIB_EVENT_ENTRY_ADD, l->key,
					KEYLENGTH - fa->fa_slen, fi, fa->fa_tos,
					fa->fa_type, fa->tb_id);
	}
}

static void fib_table_notify(struct net *net, struct fib_table *tb,
			     struct notifier_block *nb,
			     enum fib_event_type event_type)
			     struct notifier_block *nb)
{
	struct trie *t = (struct trie *)tb->tb_data;
	struct key_vector *l, *tp = t->kv;
	t_key key = 0;

	while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
		fib_leaf_notify(net, l, tb, nb, event_type);
		fib_leaf_notify(net, l, tb, nb);

		key = l->key + 1;
		/* stop in case of wrap around */
@@ -2036,8 +1941,7 @@ 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)
{
	unsigned int h;

@@ -2046,7 +1950,7 @@ static void fib_notify(struct net *net, struct notifier_block *nb,
		struct fib_table *tb;

		hlist_for_each_entry_rcu(tb, head, tb_hlist)
			fib_table_notify(net, tb, nb, event_type);
			fib_table_notify(net, tb, nb);
	}
}