一篇讲解IPv4路由表( 二 )


static inline int fib_lookup(struct net *net, struct flowi4 *flp,struct fib_result *res, unsigned int flags){struct fib_table *tb;int err = -ENETUNREACH;flags |= FIB_LOOKUP_NOREF;if (net->ipv4.fib_has_custom_rules)return __fib_lookup(net, flp, res, flags);rcu_read_lock();res->tclassid = 0;tb = rcu_dereference_rtnl(net->ipv4.fib_main);if (tb)err = fib_table_lookup(tb, flp, res, flags);if (!err)goto out;tb = rcu_dereference_rtnl(net->ipv4.fib_default);if (tb)err = fib_table_lookup(tb, flp, res, flags);【一篇讲解IPv4路由表】由函数fib_insert_alias可知 , 在trie树叶子节点中 , 路由表项时按照表ID由大到小排列的 , 如果local和main表中存在相同的路由 , 优先选择的是local表中的路由 , 宏RT_TABLE_LOCAL(255)大于RT_TABLE_MAIN(254) 。
static int fib_insert_alias(struct trie *t, struct key_vector *tp,struct key_vector *l, struct fib_alias *new, struct fib_alias *fa, t_key key){if (!l)return fib_insert_node(t, tp, new, key);if (fa) {hlist_add_before_rcu(&new->fa_list, &fa->fa_list);} else {struct fib_alias *last;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;}if (fa)hlist_add_behind_rcu(&new->fa_list, &fa->fa_list);elsehlist_add_head_rcu(&new->fa_list, &l->leaf);}



推荐阅读