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

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

Merge branch 'fib_trie-next'



Alexander Duyck says:

====================
ipv4/fib_trie: Cleanups to prepare for introduction of key vector

This patch series is meant to mostly just clean up the fib_trie to prepare
it for the introduction of the key_vector.  As such there are a number of
minor clean-ups such as reformatting the tnode to match the format once the
key vector is introduced, some optimizations to drop the need for a leaf
parent pointer, and some changes to remove duplication of effort such as
the 2 look-ups that were essentially being done per node insertion.

v2: Added code to cleanup idx >> n->bits and explain unsigned long logic
    Added code to prevent allocation when tnode size is larger than size_t
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3a65f63f 1de3d87b
Loading
Loading
Loading
Loading
+42 −28
Original line number Diff line number Diff line
@@ -185,6 +185,7 @@ struct fib_table {
	u32			tb_id;
	int			tb_default;
	int			tb_num_default;
	struct rcu_head		rcu;
	unsigned long		tb_data[0];
};

@@ -206,12 +207,16 @@ void fib_free_table(struct fib_table *tb);

static inline struct fib_table *fib_get_table(struct net *net, u32 id)
{
	struct hlist_node *tb_hlist;
	struct hlist_head *ptr;

	ptr = id == RT_TABLE_LOCAL ?
		&net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
		&net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
	return hlist_entry(ptr->first, struct fib_table, tb_hlist);

	tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr));

	return hlist_entry(tb_hlist, struct fib_table, tb_hlist);
}

static inline struct fib_table *fib_new_table(struct net *net, u32 id)
@@ -222,15 +227,19 @@ static inline struct fib_table *fib_new_table(struct net *net, u32 id)
static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
			     struct fib_result *res)
{
	int err = -ENETUNREACH;
	struct fib_table *tb;
	int err;

	rcu_read_lock();

	if (!fib_table_lookup(fib_get_table(net, RT_TABLE_LOCAL), flp, res,
			      FIB_LOOKUP_NOREF) ||
	    !fib_table_lookup(fib_get_table(net, RT_TABLE_MAIN), flp, res,
			      FIB_LOOKUP_NOREF))
		err = 0;
	for (err = 0; !err; err = -ENETUNREACH) {
		tb = fib_get_table(net, RT_TABLE_LOCAL);
		if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
			break;
		tb = fib_get_table(net, RT_TABLE_MAIN);
		if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
			break;
	}

	rcu_read_unlock();

@@ -249,29 +258,34 @@ int __fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res);
static inline int fib_lookup(struct net *net, struct flowi4 *flp,
			     struct fib_result *res)
{
	if (!net->ipv4.fib_has_custom_rules) {
		int err = -ENETUNREACH;
	struct fib_table *tb;
	int err;

	if (net->ipv4.fib_has_custom_rules)
		return __fib_lookup(net, flp, res);

	rcu_read_lock();

	res->tclassid = 0;
		if ((net->ipv4.fib_local &&
		     !fib_table_lookup(net->ipv4.fib_local, flp, res,
				       FIB_LOOKUP_NOREF)) ||
		    (net->ipv4.fib_main &&
		     !fib_table_lookup(net->ipv4.fib_main, flp, res,
				       FIB_LOOKUP_NOREF)) ||
		    (net->ipv4.fib_default &&
		     !fib_table_lookup(net->ipv4.fib_default, flp, res,
				       FIB_LOOKUP_NOREF)))
			err = 0;

	for (err = 0; !err; err = -ENETUNREACH) {
		tb = rcu_dereference_rtnl(net->ipv4.fib_local);
		if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
			break;

		tb = rcu_dereference_rtnl(net->ipv4.fib_main);
		if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
			break;

		tb = rcu_dereference_rtnl(net->ipv4.fib_default);
		if (tb && !fib_table_lookup(tb, flp, res, FIB_LOOKUP_NOREF))
			break;
	}

	rcu_read_unlock();

	return err;
}
	return __fib_lookup(net, flp, res);
}

#endif /* CONFIG_IP_MULTIPLE_TABLES */

+4 −3
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@

#include <linux/uidgid.h>
#include <net/inet_frag.h>
#include <linux/rcupdate.h>

struct tcpm_hash_bucket;
struct ctl_table_header;
@@ -38,9 +39,9 @@ struct netns_ipv4 {
#ifdef CONFIG_IP_MULTIPLE_TABLES
	struct fib_rules_ops	*rules_ops;
	bool			fib_has_custom_rules;
	struct fib_table	*fib_local;
	struct fib_table	*fib_main;
	struct fib_table	*fib_default;
	struct fib_table __rcu	*fib_local;
	struct fib_table __rcu	*fib_main;
	struct fib_table __rcu	*fib_default;
#endif
#ifdef CONFIG_IP_ROUTE_CLASSID
	int			fib_num_tclassid_users;
+37 −15
Original line number Diff line number Diff line
@@ -89,17 +89,14 @@ struct fib_table *fib_new_table(struct net *net, u32 id)

	switch (id) {
	case RT_TABLE_LOCAL:
		net->ipv4.fib_local = tb;
		rcu_assign_pointer(net->ipv4.fib_local, tb);
		break;

	case RT_TABLE_MAIN:
		net->ipv4.fib_main = tb;
		rcu_assign_pointer(net->ipv4.fib_main, tb);
		break;

	case RT_TABLE_DEFAULT:
		net->ipv4.fib_default = tb;
		rcu_assign_pointer(net->ipv4.fib_default, tb);
		break;

	default:
		break;
	}
@@ -132,13 +129,14 @@ struct fib_table *fib_get_table(struct net *net, u32 id)
static void fib_flush(struct net *net)
{
	int flushed = 0;
	struct fib_table *tb;
	struct hlist_head *head;
	unsigned int h;

	for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
		head = &net->ipv4.fib_table_hash[h];
		hlist_for_each_entry(tb, head, tb_hlist)
		struct hlist_head *head = &net->ipv4.fib_table_hash[h];
		struct hlist_node *tmp;
		struct fib_table *tb;

		hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
			flushed += fib_table_flush(tb);
	}

@@ -665,10 +663,12 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
	s_h = cb->args[0];
	s_e = cb->args[1];

	rcu_read_lock();

	for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
		e = 0;
		head = &net->ipv4.fib_table_hash[h];
		hlist_for_each_entry(tb, head, tb_hlist) {
		hlist_for_each_entry_rcu(tb, head, tb_hlist) {
			if (e < s_e)
				goto next;
			if (dumped)
@@ -682,6 +682,8 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
		}
	}
out:
	rcu_read_unlock();

	cb->args[1] = e;
	cb->args[0] = h;

@@ -1117,14 +1119,34 @@ static void ip_fib_net_exit(struct net *net)

	rtnl_lock();
	for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
		struct fib_table *tb;
		struct hlist_head *head;
		struct hlist_head *head = &net->ipv4.fib_table_hash[i];
		struct hlist_node *tmp;
		struct fib_table *tb;

		/* this is done in two passes as flushing the table could
		 * cause it to be reallocated in order to accommodate new
		 * tnodes at the root as the table shrinks.
		 */
		hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
			fib_table_flush(tb);

		head = &net->ipv4.fib_table_hash[i];
		hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
#ifdef CONFIG_IP_MULTIPLE_TABLES
			switch (tb->tb_id) {
			case RT_TABLE_LOCAL:
				RCU_INIT_POINTER(net->ipv4.fib_local, NULL);
				break;
			case RT_TABLE_MAIN:
				RCU_INIT_POINTER(net->ipv4.fib_main, NULL);
				break;
			case RT_TABLE_DEFAULT:
				RCU_INIT_POINTER(net->ipv4.fib_default, NULL);
				break;
			default:
				break;
			}
#endif
			hlist_del(&tb->tb_hlist);
			fib_table_flush(tb);
			fib_free_table(tb);
		}
	}
+350 −322

File changed.

Preview size limit exceeded, changes collapsed.