linux网络协议栈分析笔记14-路由4-FIB3

本文详细解析了Linux内核中路由表的创建过程,重点介绍了fib_magic函数如何根据不同的路由类型选择路由表,并通过fib_new_table函数创建或获取指定ID的路由表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看完fib的查找,弄清了一些数据结构的组织,我们再来看看路由表是如何创建的
从ip_fib_init注册的两个通知链来看,在IP地址发送变动时会触发通知链的处理函数,都会调用fib_add_ifaddr()来添加地址到路由中
这个里面由调用了fib_magic来进行路由地址的操作。
static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
{
     struct net *net = dev_net(ifa->ifa_dev->dev);
     struct fib_table *tb;
     struct fib_config cfg = {                                   路由配置结构
          .fc_protocol = RTPROT_KERNEL,
          .fc_type = type,
          .fc_dst = dst,
          .fc_dst_len = dst_len,
          .fc_prefsrc = ifa->ifa_local,
          .fc_oif = ifa->ifa_dev->dev->ifindex,
          .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
          .fc_nlinfo = {
               .nl_net = net,
          },
     };

     if (type == RTN_UNICAST)
          tb = fib_new_table(net, RT_TABLE_MAIN);
     else
          tb = fib_new_table(net, RT_TABLE_LOCAL);

     if (tb == NULL)
          return;

     cfg.fc_table = tb->tb_id;

     if (type != RTN_LOCAL)
          cfg.fc_scope = RT_SCOPE_LINK;
     else
          cfg.fc_scope = RT_SCOPE_HOST;

     if (cmd == RTM_NEWROUTE)         如果是添加命令 则插入
          tb->tb_insert(tb, &cfg);                         fn_hash_insert;
     else
          tb->tb_delete(tb, &cfg);          否则,进行删除
}

fib_new_table()
先看CONFIG_IP_MULTIPLE_TABLES开启的时候

struct fib_table *fib_new_table(struct net *net, u32 id)
{
     struct fib_table *tb;
     unsigned int h;

     if (id == 0)
          id = RT_TABLE_MAIN;
     tb = fib_get_table(net, id);            通过id查找路由表函数
     if (tb)
          return tb;

     tb = fib_hash_table(id);      申请创建路由表
     if (!tb)
          return NULL;
     h = id & (FIB_TABLE_HASHSZ - 1);
     hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]);
     return tb;
}

struct fib_table *fib_get_table(struct net *net, u32 id)
{
     struct fib_table *tb;
     struct hlist_node *node;
     struct hlist_head *head;
     unsigned int h;

     if (id == 0)
          id = RT_TABLE_MAIN;
     h = id & (FIB_TABLE_HASHSZ - 1);

     rcu_read_lock();
     head = &net->ipv4.fib_table_hash[h];                    得到冲突链头
     hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {             匹配
          if (tb->tb_id == id) {
               rcu_read_unlock();
               return tb;
          }
     }
     rcu_read_unlock();
     return NULL;
}
当然FIB的东西还有很多很多,数据结构关系错综复杂,鉴于时间和精力,无法再深入分析,这里也只是弄清大概流程,拉通整个协议栈,等到有了系统的、全流程的观念后,我们再来仔细深入分析具体的模块。
这里有篇文章很好的阐述了linux kernel路由机制http://blog.youkuaiyun.com/bin323/article/details/642192  算是对上述的流程分析一个总结
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值