Commit 06741d05 authored by David S. Miller's avatar David S. Miller

Merge branch 'fib_trie_table_merge_fixes'

Alexander Duyck says:

====================
fib_trie: Minor fixes for table merge

This patch set addresses two issues reported with the tables merged, the
first is a NULL pointer dereference, and the other is to remove a WARN_ON
and set the ordering for aliases from different tables with the same slen
values.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 80f1d68c 0b65bd97
...@@ -156,9 +156,12 @@ int fib_unmerge(struct net *net) ...@@ -156,9 +156,12 @@ int fib_unmerge(struct net *net)
{ {
struct fib_table *old, *new; struct fib_table *old, *new;
/* attempt to fetch local table if it has been allocated */
old = fib_get_table(net, RT_TABLE_LOCAL); old = fib_get_table(net, RT_TABLE_LOCAL);
new = fib_trie_unmerge(old); if (!old)
return 0;
new = fib_trie_unmerge(old);
if (!new) if (!new)
return -ENOMEM; return -ENOMEM;
......
...@@ -950,7 +950,7 @@ static struct key_vector *fib_find_node(struct trie *t, ...@@ -950,7 +950,7 @@ static struct key_vector *fib_find_node(struct trie *t,
* priority less than or equal to PRIO. * priority less than or equal to PRIO.
*/ */
static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen, static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
u8 tos, u32 prio) u8 tos, u32 prio, u32 tb_id)
{ {
struct fib_alias *fa; struct fib_alias *fa;
...@@ -962,6 +962,10 @@ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen, ...@@ -962,6 +962,10 @@ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
continue; continue;
if (fa->fa_slen != slen) if (fa->fa_slen != slen)
break; break;
if (fa->tb_id > tb_id)
continue;
if (fa->tb_id != tb_id)
break;
if (fa->fa_tos > tos) if (fa->fa_tos > tos)
continue; continue;
if (fa->fa_info->fib_priority >= prio || fa->fa_tos < tos) if (fa->fa_info->fib_priority >= prio || fa->fa_tos < tos)
...@@ -1041,6 +1045,9 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp, ...@@ -1041,6 +1045,9 @@ static int fib_insert_alias(struct trie *t, struct key_vector *tp,
hlist_for_each_entry(last, &l->leaf, fa_list) { hlist_for_each_entry(last, &l->leaf, fa_list) {
if (new->fa_slen < last->fa_slen) if (new->fa_slen < last->fa_slen)
break; break;
if ((new->fa_slen == last->fa_slen) &&
(new->tb_id > last->tb_id))
break;
fa = last; fa = last;
} }
...@@ -1089,7 +1096,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1089,7 +1096,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
} }
l = fib_find_node(t, &tp, key); l = fib_find_node(t, &tp, key);
fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority) : NULL; fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority,
tb->tb_id) : NULL;
/* Now fa, if non-NULL, points to the first fib alias /* Now fa, if non-NULL, points to the first fib alias
* with the same keys [prefix,tos,priority], if such key already * with the same keys [prefix,tos,priority], if such key already
...@@ -1116,13 +1124,12 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) ...@@ -1116,13 +1124,12 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
fa_match = NULL; fa_match = NULL;
fa_first = fa; fa_first = fa;
hlist_for_each_entry_from(fa, fa_list) { hlist_for_each_entry_from(fa, fa_list) {
if ((fa->fa_slen != slen) || (fa->fa_tos != tos)) if ((fa->fa_slen != slen) ||
(fa->tb_id != tb->tb_id) ||
(fa->fa_tos != tos))
break; break;
if (fa->fa_info->fib_priority != fi->fib_priority) if (fa->fa_info->fib_priority != fi->fib_priority)
break; break;
/* duplicate entry from another table */
if (WARN_ON(fa->tb_id != tb->tb_id))
continue;
if (fa->fa_type == cfg->fc_type && if (fa->fa_type == cfg->fc_type &&
fa->fa_info == fi) { fa->fa_info == fi) {
fa_match = fa; fa_match = fa;
...@@ -1474,7 +1481,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) ...@@ -1474,7 +1481,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
if (!l) if (!l)
return -ESRCH; return -ESRCH;
fa = fib_find_alias(&l->leaf, slen, tos, 0); fa = fib_find_alias(&l->leaf, slen, tos, 0, tb->tb_id);
if (!fa) if (!fa)
return -ESRCH; return -ESRCH;
...@@ -1484,12 +1491,11 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) ...@@ -1484,12 +1491,11 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
hlist_for_each_entry_from(fa, fa_list) { hlist_for_each_entry_from(fa, fa_list) {
struct fib_info *fi = fa->fa_info; struct fib_info *fi = fa->fa_info;
if ((fa->fa_slen != slen) || (fa->fa_tos != tos)) if ((fa->fa_slen != slen) ||
(fa->tb_id != tb->tb_id) ||
(fa->fa_tos != tos))
break; break;
if (fa->tb_id != tb->tb_id)
continue;
if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
(cfg->fc_scope == RT_SCOPE_NOWHERE || (cfg->fc_scope == RT_SCOPE_NOWHERE ||
fa->fa_info->fib_scope == cfg->fc_scope) && fa->fa_info->fib_scope == cfg->fc_scope) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment