Skip to content

Commit

Permalink
Merge branch 'fib_trie_table_merge_fixes'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 12, 2015
2 parents 80f1d68 + 0b65bd9 commit 06741d0
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 12 deletions.
5 changes: 4 additions & 1 deletion net/ipv4/fib_frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,12 @@ int fib_unmerge(struct net *net)
{
struct fib_table *old, *new;

/* attempt to fetch local table if it has been allocated */
old = fib_get_table(net, RT_TABLE_LOCAL);
new = fib_trie_unmerge(old);
if (!old)
return 0;

new = fib_trie_unmerge(old);
if (!new)
return -ENOMEM;

Expand Down
28 changes: 17 additions & 11 deletions net/ipv4/fib_trie.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ static struct key_vector *fib_find_node(struct trie *t,
* priority less than or equal to PRIO.
*/
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;

Expand All @@ -962,6 +962,10 @@ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
continue;
if (fa->fa_slen != slen)
break;
if (fa->tb_id > tb_id)
continue;
if (fa->tb_id != tb_id)
break;
if (fa->fa_tos > tos)
continue;
if (fa->fa_info->fib_priority >= prio || fa->fa_tos < tos)
Expand Down Expand Up @@ -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) {
if (new->fa_slen < last->fa_slen)
break;
if ((new->fa_slen == last->fa_slen) &&
(new->tb_id > last->tb_id))
break;
fa = last;
}

Expand Down Expand Up @@ -1089,7 +1096,8 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
}

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
* with the same keys [prefix,tos,priority], if such key already
Expand All @@ -1116,13 +1124,12 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
fa_match = NULL;
fa_first = fa;
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;
if (fa->fa_info->fib_priority != fi->fib_priority)
break;
/* duplicate entry from another table */
if (WARN_ON(fa->tb_id != tb->tb_id))
continue;
if (fa->fa_type == cfg->fc_type &&
fa->fa_info == fi) {
fa_match = fa;
Expand Down Expand Up @@ -1474,7 +1481,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
if (!l)
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)
return -ESRCH;

Expand All @@ -1484,12 +1491,11 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
hlist_for_each_entry_from(fa, fa_list) {
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;

if (fa->tb_id != tb->tb_id)
continue;

if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
(cfg->fc_scope == RT_SCOPE_NOWHERE ||
fa->fa_info->fib_scope == cfg->fc_scope) &&
Expand Down

0 comments on commit 06741d0

Please sign in to comment.