diff -ur v2.6.9-rc2-bk10/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c --- v2.6.9-rc2-bk10/linux/net/ipv4/fib_hash.c 2004-09-26 08:56:19.000000000 +0300 +++ linux/net/ipv4/fib_hash.c 2004-09-26 08:56:33.313770344 +0300 @@ -433,6 +433,7 @@ /* Return the first fib alias matching TOS with * priority less than or equal to PRIO. + * Also, control the ordering by TOS: keep the entries with TOS=0 at tail. */ static struct fib_alias *fib_find_alias(struct fib_node *fn, u8 tos, u32 prio) { @@ -443,12 +444,16 @@ prev_fa = NULL; list_for_each_entry(fa, head, fa_list) { if (fa->fa_tos != tos) - continue; + { + if (!prev_fa && fa->fa_tos) + continue; + /* Stop at TOS 0 or after entries from our TOS */ + return fa; + } prev_fa = fa; if (prio <= fa->fa_info->fib_priority) - break; + return fa; } - return prev_fa; } return NULL; } @@ -505,7 +510,7 @@ * and we need to allocate a new one of those as well. */ - if (fa && + if (fa && fa->fa_tos == tos && fa->fa_info->fib_priority == fi->fib_priority) { struct fib_alias *fa_orig; @@ -586,7 +591,7 @@ write_lock_bh(&fib_hash_lock); if (new_f) fib_insert_node(fz, new_f); - list_add(&new_fa->fa_list, + list_add_tail(&new_fa->fa_list, (fa ? &fa->fa_list : &f->fn_alias)); write_unlock_bh(&fib_hash_lock);