接收路由查找

IP层接到一个数据包以后,如果需要进行路由,就调用函数myip_route_input, myip_route_input先在缓存里寻找路由,如果失败则调用myip_route_input_slow, myip_route_input_slow调用myfib_lookup在路由表里寻找路由,如果命中,首先在缓存里添加这个路由,然后返回结果。
    路由缓存的数据结构是一个全局哈希表myrt_hash_table,前面文章讲过,该哈希表在模块初始化时被分配了4096个入口。哈希表的每一项都是 一个rtable结构的链表。每一个rtable数据结构都存放向一个IP主机发送报文的路由信息。下面是结构体struct rtable的定义:
    struct rtable
    {
        union{
            struct dst_entry    dst;
            struct rtable       *rt_next;
        }u;
        struct in_device    *idev;
        unsigned        rt_flags;
        __u16           rt_type;
        __u16           rt_multipath_alg;

        __u32           rt_dst;
        __u32           rt_src;
        int             rt_iif;

        __u32           rt_gateway;
        struct flowi    fl;
        __u32           rt_spec_dst;
        struct inet_peer    *peer;
    };
    接收到的数据包,可能是组播包,也可能是广播包,情况比较复杂,对此myip_route_input_slow都有对应的处理,为了简单起见,我们以一个ARP请求包为例来说明myip_route_input的“一部分”工作流程。
    给我的网络设备接口eth0配置一个secondary地址172.16.48.11(其主地址是172.16.48.2),这样在路由表的local表里就多了一项:
        :          the key ip: 172.16.48.11
        :          the alias:
        :              fa tos: 0
        :              fa type: RTN_LOCAL
        :              fa scope: RT_SCOPE_HOST
        :              fa state: 0
        :              the fa info:
        :                  tree ref: 2
        :                  clnt ref: 1
        :                  fib_dead: 0
        :                  fib flags: 0
        :                  protocol: 2
        :                  pref src: 172.16.48.2.
        :                  priority: 0
        :                  fib_mtu: 0
        :                  fib_window: 0
        :                  fib_power: 0
        :                  fib_nhs: 1
        :                  all the nhs:
        :                      0.16.48.2
    当我们收到来自172.16.48.1的一个对172.16.48.11的ARP请求包时。我们需要对接收到的数据包进行路由查询,这样调用myip_route_input:
        myip_route_input(skb, dst=172.16.48.11, src=172.16.48.1, tos=0, dev)
    因为是第一次,路由缓存中并没有我们要找的路由,所以该函数以同样的参数列表调用myip_route_input_slow接口。 myip_route_input_slow先进行一系例判断,当确定该数据包是单播包时,调用myfib_lookup进行路由查找。 myfib_lookup使用内置的路由规则,先查找local表,查找成功。
    然后,对全局变量myrt_cache_stat的in_slow_tot加1,记录本次进入myip_route_input_slow查找路由。后面还会有很多操作,会相应的更新这个状态结构,不再进行描述。
    路由表查询的结果是由结构struct fib_result表示的,此次查询结果的类型是RTN_LOCAL,表示这个数据包是要本地接收的,而不是转发的。接下来,我们要做的一件事情就是确 认这个数据包的源地址的有效性,方法是把源地址和目的地址反向,再去查找路由表,即查找172.16.48.11->172.16.48.1的路 由。显然,这次我们在main表中查到了type为RTN_UNICAST的路由,即源地址是有效的。
    接下来,分配一个结构struct rtable,并进行初始化,主要是其成员fl,这是一个结构体struct flowi。里面填充数据包的源和目的地址的详细信息,还有输入网络设备接口,tos等详细信息。
    最后我们要做的一件事情就是把这个新创建出来的rtable放到路由缓存中,先确定在myrt_hash_table中的具体哪一项,然后在链表中搜索, 如果发现这个rtable已经存在,则把它提到链表头,同时,销毁创建出来的rtable。关于路由缓存的垃圾回收算法等细节,我们再进行专门分析。
    前面我们看到在调用myip_route_input时,第一个参数是skb,最后,我们需要把创建出来的rtable赋给skb->dst。
    接下来,我们再看一个例子,如果我在172.46.48.1 ping 172.16.48.10。这是一个不存在的ip地址,当172.16.48.1发出ARP请求包时,会发生什么事情?
    显然,在查找路由时,我们可以在main表中查到一个RTN_UNICAST的路由,表示不是本地接收,可能本地只是一个网关,或者需要转发。但这个包显然是不需要转发的,所以,我们得到的返回值是:无可达路由。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值