fib系统分析(linux网络协议栈笔记)

FIB系统初始化

在Linux路由系统中主要保存了三种与路由相关的数据,第一种是在物理上和本机相连接的主机地址信息表——相邻表:neigh_table{ },第二种是保存了在网络访问中判断一个网络地址应该走什么路由的数据表——路由规则表:fib_table{ },第三种表是最新使用过的查询路由地址的缓存地址数据表——路由缓存:rtcache,由rtable{ }节点组成。它们三者之间的关系如下图:
这里写图片描述
上图中FIB主要是和用户层打交道,而RT cache主要是和协议栈打交道,除非处于维护的目的,协议栈是不会去直接访问FIB系统。在一个基本稳定系统中,红线箭头表示用户操作流,蓝线箭头表示底层报文的路由查询过程。只有特殊情况,报文路由过程才会进入到FIB系统查询,这个原理和CPU访问Cache不命中然后才访问内存是一个道理。
现在回过来看ip_init,它一上来就调用ip_rt_init,为FIB搭好一个空架子:

//  路由缓存内存量指定办法:
//      1.通过启动参数rhash_entries指定hash表bucket个数
//      2.根据物理内存页数确定使用的内存量

//  根据物理页数分配缓存内存:
//      1.goal目标内存页数=总页数/(2**(26-PAGE_SHIFT))
//      2.最接近goal内存页数的order,用于从伙伴系统中分配
//      3.rt_hash_mask=order页可容纳的bucket数
//      4.对齐rt_hash_mask到2的幂次
//      5.从伙伴系统中分配order页物理内存

//  路由缓存阈值:
//      1.gc_thresh=bucket个数,当路由缓存数超过此阈值时,rt_garbage_collect同步回收内存
//      2.ip_rt_max_size=16*(bucket个数),当路由缓存超过此阈值时,dst_alloc会失败

//  路由子系统初始化
//  调用路径:ip_init->ip_rt_init
//  函数主要任务:
//      1.分配dst缓存的slab缓存
//      2.分配路由缓存表
//      3.向netdev_chain注册监听块
//      4.初始化默认路由表
//      5.初始化路由缓存使用的定时器
//          5.1 垃圾回收定时器
//          5.2 缓存刷新定时器
//          5.3 缓存周期性刷新定时器
//      6.初始化IPSec与路由子系统交互的衔接点
int __init ip_rt_init(void)
{
    int i, order, goal, rc = 0;
    //
    rt_hash_rnd = (int) ((num_physpages ^ (num_physpages>>8)) ^
                 (jiffies ^ (jiffies >> 7)));
    //dst缓存
    ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
                             sizeof(struct rtable),
                             0, SLAB_HWCACHE_ALIGN,
                             NULL, NULL);

    //根据物理内存数计算路由缓存使用的内存页数
    goal = num_physpages >> (26 - PAGE_SHIFT);
    if (rhash_entries)//rhash_entries为启动参数,
        goal = (rhash_entries * sizeof(struct rt_hash_bucket)) >> PAGE_SHIFT;
    //计算缓存使用内存页个数以2为底的order
    for (order = 0; (1UL << order) < goal; order++);

    //rt_hash_mask为bucket的个数
    do {
        rt_hash_mask = (1UL << order) * PAGE_SIZE /
            sizeof(struct rt_hash_bucket);
        //使rt_hash_mask 对齐到2的幂次
        while (rt_hash_mask & (rt_hash_mask - 1))
            rt_hash_mask--;

        //分配路由缓存
        rt_hash_table = (struct rt_hash_bucket *)
            __get_free_pages(GFP_ATOMIC, order);
    } while (rt_hash_table == NULL && --order > 0);


    for (rt_hash_log = 0; (1 << rt_hash_log) != rt_hash_mask; rt_hash_log++);

    //初始化每个bucket使用的自选锁
    rt_hash_mask--;
    for (i = 0; i <= rt_hash_mask; i++) {
        spin_lock_init(&rt_hash_table[i].lock);
        rt_hash_table[i].chain = NULL;
    }

    //垃圾回收的域值
    ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
    //路由缓存最多保存的缓存个数
    ip_rt_max_size = (rt_hash_mask + 1) * 16;
    //per-cpu统计变量
    rt_cache_stat = alloc_percpu(struct rt_cache_stat);

    //向netdev_chain注册监听块,用netlink为地址和路由命令注册处理函数
    devinet_init();
    //初始化默认路由表
    ip_fib_init();
    //缓存刷新定时器
    init_timer(&rt_flush_timer);
    rt_flush_timer.function = rt_run_flush;
    //垃圾回收定时器
    init_timer(&rt_periodic_timer);
    rt_periodic_timer.function<
  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值