当然,我们选择路由1那章的遗留的接口进入分析
fib_lookup() 我们前面提到过fib初始化时,CONFIG_IP_MULTIPLE_TABLES 宏导致了两种方式的fib表初始化,
因此存在了有多路由表存在和无多路由表存在的情况,我们先看无多路由表的情况
static inline int
fib_lookup(struct net *net, const struct flowi *flp,
struct fib_result *res)
{
struct fib_table *table;
table = fib_get_table(net, RT_TABLE_LOCAL); 先查LOCAL
if (!table-> tb_lookup(table, flp, res))
return 0;
table = fib_get_table(net, RT_TABLE_MAIN); 再查MAIN
if (!table-> tb_lookup(table, flp, res))
return 0;
return -ENETUNREACH;
}
struct fib_result *res)
{
struct fib_table *table;
table = fib_get_table(net, RT_TABLE_LOCAL); 先查LOCAL
if (!table-> tb_lookup(table, flp, res))
return 0;
table = fib_get_table(net, RT_TABLE_MAIN); 再查MAIN
if (!table-> tb_lookup(table, flp, res))
return 0;
return -ENETUNREACH;
}
static inline struct fib_table *
fib_get_table(struct net *net, u32 id)
{
struct hlist_head *ptr;
ptr = id == RT_TABLE_LOCAL ?
&net->ipv4.fib_table_hash[ TABLE_LOCAL_INDEX] :
&net->ipv4.fib_table_hash[ TABLE_MAIN_INDEX];
return hlist_entry(ptr->first, struct fib_table, tb_hlist); 根据传入的id找到fib_table
}
{
struct hlist_head *ptr;
ptr = id == RT_TABLE_LOCAL ?
&net->ipv4.fib_table_hash[ TABLE_LOCAL_INDEX] :
&net->ipv4.fib_table_hash[ TABLE_MAIN_INDEX];
return hlist_entry(ptr->first, struct fib_table, tb_hlist); 根据传入的id找到fib_table
}
上一章的一幅图说明了这种结构
!table->
tb_lookup(table, flp, res)) 即
fn_hash_lookup
static int
fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
{
int err;
struct fn_zone *fz;
struct fn_hash *t = (struct fn_hash *)tb->tb_data; 获得路由区队列
read_lock(&fib_hash_lock);
for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { 扫描网络区
struct hlist_head *head;
struct hlist_node *node;
struct fib_node *f;
__be32 k = fz_key(flp->fl4_dst, fz); 取目标地址在该网络区的网络号 fl4_det&((fz)->fz_mask)
head = &fz->fz_hash [fn_hash(k, fz)]; fn_hash(k, fz)得到hash关键字 获得hash链头
hlist_for_each_entry(f, node, head, fn_hash) {
if (f->fn_key != k) 通过fn_key找到匹配的fib node节点
continue;
err = fib_semantic_match(&f->fn_alias, 进入fib semantic查找
flp, res,
fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
{
int err;
struct fn_zone *fz;
struct fn_hash *t = (struct fn_hash *)tb->tb_data; 获得路由区队列
read_lock(&fib_hash_lock);
for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { 扫描网络区
struct hlist_head *head;
struct hlist_node *node;
struct fib_node *f;
__be32 k = fz_key(flp->fl4_dst, fz); 取目标地址在该网络区的网络号 fl4_det&((fz)->fz_mask)
head = &fz->fz_hash [fn_hash(k, fz)]; fn_hash(k, fz)得到hash关键字 获得hash链头
hlist_for_each_entry(f, node, head, fn_hash) {
if (f->fn_key != k) 通过fn_key找到匹配的fib node节点
continue;
err = fib_semantic_match(&f->fn_alias, 进入fib semantic查找
flp, res,

本文详细分析了Linux网络协议栈中路由选择的过程,首先从无多路由表的情况入手,讲解了`fib_lookup`函数如何依次查询LOCAL和MAIN路由表,并通过`fib_get_table`获取路由表。接着,介绍了开启多路由表时的`fib_rules_lookup`函数,涉及路由规则匹配和动作执行。文章通过代码和流程梳理了路由查找的关键步骤。
最低0.47元/天 解锁文章
455

被折叠的 条评论
为什么被折叠?



