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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
06741d055b
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) &&
|
||||
|
|
Loading…
Reference in a new issue