summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/ip_fib.h3
-rw-r--r--net/ipv4/fib_trie.c7
-rw-r--r--net/ipv4/route.c4
3 files changed, 12 insertions, 2 deletions
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 514627f5633..10422ef14e2 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -160,7 +160,8 @@ struct fib_table {
struct hlist_node tb_hlist;
u32 tb_id;
int tb_default;
- unsigned char tb_data[0];
+ int tb_num_default;
+ unsigned long tb_data[0];
};
extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index bde80c450b5..9ac481a10d3 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1332,6 +1332,9 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
}
}
+ if (!plen)
+ tb->tb_num_default++;
+
list_add_tail_rcu(&new_fa->fa_list,
(fa ? &fa->fa_list : fa_head));
@@ -1697,6 +1700,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
list_del_rcu(&fa->fa_list);
+ if (!plen)
+ tb->tb_num_default--;
+
if (list_empty(fa_head)) {
hlist_del_rcu(&li->hlist);
free_leaf_info(li);
@@ -1987,6 +1993,7 @@ struct fib_table *fib_trie_table(u32 id)
tb->tb_id = id;
tb->tb_default = -1;
+ tb->tb_num_default = 0;
t = (struct trie *) tb->tb_data;
memset(t, 0, sizeof(*t));
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 0e7430c327a..e9aee81de3e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2615,7 +2615,9 @@ static struct rtable *ip_route_output_slow(struct net *net,
fib_select_multipath(&res);
else
#endif
- if (!res.prefixlen && res.type == RTN_UNICAST && !fl4.flowi4_oif)
+ if (!res.prefixlen &&
+ res.table->tb_num_default > 1 &&
+ res.type == RTN_UNICAST && !fl4.flowi4_oif)
fib_select_default(&res);
if (!fl4.saddr)