A-A+

路由表查找过程(ip_route_input_slow)

2015年11月26日 路由器高级应用 暂无评论 阅读 3 views 次

Linux Version:2.6.33

提示:本文是关于Linux实现路由表查找Flow图!

处理过程如下:

source file:net/ipv4/route.c

method:ip_route_input

L3 IPv4 处理流程:http://blog.chinaunix.net/u3/114767/showart_2272778.html

源IP地址如果是multicast,broadcast,loopback地址,意味着数据报不知道从哪来的,只能把数据报废掉了。

目标IP地址如果是braodcast呢?这时有可能是发给自己的啊,所以这时要处理的。源IP可能是0地址么?其实这种情况在网络中还是经常发生的,比如DHCP的情况。如果Linxu作为DHCP服务器,当然要处理这种情况了。
这时目标IP地址就是广播地址,所以之后的处理就到brd_input。

所以最关键要理解什么时候出现判断条件的情况。如果不是上述的DHCP包,源IP地址就不能为0地址。所以源,目标判断正确了之后就要进行路由查找了,也就是fib_lookup。根据结果,也就是路由类型进行分歧处理了。
为了再这篇文章里看个究竟,所以把源码贴出来,如下:

  1. static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,  
  2.   
  3.              u8 tos, struct net_device *dev)  
  4. {  
  5.     struct fib_result res;  
  6.     struct in_device *in_dev = in_dev_get(dev);   
  7.     struct flowi fl = { .nl_u = { .ip4_u =  
  8.                  { .daddr = daddr,   
  9.                     .saddr = saddr,  
  10.                     .tos = tos,  
  11.                     .scope = RT_SCOPE_UNIVERSE,   
  12.                  } },  
  13.              .mark = skb->mark,   
  14.              .iif = dev->ifindex };  
  15.     unsigned    flags = 0;   
  16.     u32        itag = 0;  
  17.     struct rtable * rth;  
  18.     unsigned    hash;   
  19.     __be32        spec_dst;  
  20.     int        err = -EINVAL;  
  21.     int        free_res = 0;   
  22.     struct net * net = dev_net(dev);  
  23.   
  24.     /* IP on this device is disabled. */  
  25.   
  26.     if (!in_dev)   
  27.         goto out;  
  28.   
  29.     /* Check for the most weird martians, which can be not detected  
  30.      by fib_lookup.  
  31.      */  
  32.   
  33.     if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||   
  34.      ipv4_is_loopback(saddr))  
  35.         goto martian_source;  
  36.   
  37.     if (daddr == htonl(0xFFFFFFFF) || (saddr == 0 && daddr == 0))   
  38.         goto brd_input;  
  39.   
  40.     /* Accept zero addresses only to limited broadcast;  
  41.      * I even do not know to fix it or not. Waiting for complains :-)  
  42.      */  
  43.     if (ipv4_is_zeronet(saddr))   
  44.         goto martian_source;  
  45.   
  46.     if (ipv4_is_lbcast(daddr) || ipv4_is_zeronet(daddr) ||   
  47.      ipv4_is_loopback(daddr))  
  48.         goto martian_destination;  
  49.   
  50.     /*  
  51.      *    Now we are ready to route packet.  
  52.      */  
  53.     if ((err = fib_lookup(net, &fl, &res)) != 0) {   
  54.         if (!IN_DEV_FORWARD(in_dev))  
  55.             goto e_hostunreach;  
  56.         goto no_route;   
  57.     }  
  58.     free_res = 1;  
  59.   
  60.     RT_CACHE_STAT_INC(in_slow_tot);  
  61.   
  62.     if (res.type == RTN_BROADCAST)   
  63.         goto brd_input;  
  64.   
  65.     if (res.type == RTN_LOCAL) {   
  66.         int result;  
  67.         result = fib_validate_source(saddr, daddr, tos,  
  68.                      net->loopback_dev->ifindex,   
  69.                      dev, &spec_dst, &itag, skb->mark);  
  70.         if (result < 0)   
  71.             goto martian_source;  
  72.         if (result)  
  73.             flags |= RTCF_DIRECTSRC;   
  74.         spec_dst = daddr;  
  75.         goto local_input;  
  76.     }  
  77.   
  78.     if (!IN_DEV_FORWARD(in_dev))   
  79.         goto e_hostunreach;  
  80.     if (res.type != RTN_UNICAST)  
  81.         goto martian_destination;   
  82.   
  83.     err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);  
  84. done:  
  85.     in_dev_put(in_dev);  
  86.     if (free_res)  
  87.         fib_res_put(&res);   
  88. out:    return err;  
  89.   
  90. brd_input:  
  91.     if (skb->protocol != htons(ETH_P_IP))   
  92.         goto e_inval;  
  93.   
  94.     if (ipv4_is_zeronet(saddr))  
  95.         spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);   
  96.     else {  
  97.         err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,   
  98.                      &itag, skb->mark);  
  99.         if (err < 0)   
  100.             goto martian_source;  
  101.         if (err)  
  102.             flags |= RTCF_DIRECTSRC;   
  103.     }  
  104.     flags |= RTCF_BROADCAST;  
  105.     res.type = RTN_BROADCAST;  
  106.     RT_CACHE_STAT_INC(in_brd);   
  107.   
  108. local_input:  
  109.     rth = dst_alloc(&ipv4_dst_ops);  
  110.     if (!rth)   
  111.         goto e_nobufs;  
  112.   
  113.     rth->u.dst.outputip_rt_bug;  
  114.     rth->u.dst.obsolete = -1;   
  115.     rth->rt_genidrt_genid = rt_genid(net);  
  116.   
  117.     atomic_set(&rth->u.dst.__refcnt, 1);   
  118.     rth->u.dst.flagsDST_HOST;  
  119.     if (IN_DEV_CONF_GET(in_dev, NOPOLICY))   
  120.         rth->u.dst.flags |= DST_NOPOLICY;  
  121.     rth->fl.fl4_dst    = daddr;   
  122.     rth->rt_dst    = daddr;  
  123.     rth->fl.fl4_tos    = tos;  
  124.     rth->fl.mark = skb->mark;   
  125.     rth->fl.fl4_src    = saddr;  
  126.     rth->rt_src    = saddr;  
  127. #ifdef CONFIG_NET_CLS_ROUTE   
  128.     rth->u.dst.tclassid = itag;  
  129. #endif  
  130.     rth->rt_iif    =   
  131.     rth->fl.iif    = dev->ifindex;  
  132.     rth->u.dst.dev    = net->loopback_dev;   
  133.     dev_hold(rth->u.dst.dev);  
  134.     rth->idev    = in_dev_get(rth->u.dst.dev);   
  135.     rth->rt_gateway    = daddr;  
  136.     rth->rt_spec_dst= spec_dst;  
  137.     rth->u.dst.inputip_local_deliver;   
  138.     rth->rt_flags     = flags|RTCF_LOCAL;  
  139.     if (res.type == RTN_UNREACHABLE) {   
  140.         rth->u.dst.inputip_error;  
  141.         rth->u.dst.error= -err;   
  142.         rth->rt_flags     &= ~RTCF_LOCAL;  
  143.     }  
  144.     rth->rt_type    = res.type;   
  145.     hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));  
  146.     err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);   
  147.     goto done;  
  148.   
  149. no_route:  
  150.     RT_CACHE_STAT_INC(in_no_route);  
  151.     spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);   
  152.     res.type = RTN_UNREACHABLE;  
  153.     if (err == -ESRCH)  
  154.         err = -ENETUNREACH;   
  155.     goto local_input;  
  156.   
  157.     /*  
  158.      *    Do not cache martian addresses: they should be logged (RFC1812)  
  159.      */  
  160. martian_destination:  
  161.     RT_CACHE_STAT_INC(in_martian_dst);   
  162. #ifdef CONFIG_IP_ROUTE_VERBOSE  
  163.     if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())   
  164.         printk(KERN_WARNING "martian destination %pI4 from %pI4, dev %s\n",  
  165.             &daddr, &saddr, dev->name);   
  166. #endif  
  167.   
  168. e_hostunreach:  
  169.     err = -EHOSTUNREACH;  
  170.     goto done;  
  171.   
  172. e_inval:  
  173.     err = -EINVAL;  
  174.     goto done;  
  175.   
  176. e_nobufs:  
  177.     err = -ENOBUFS;   
  178.     goto done;  
  179.   
  180. martian_source:  
  181.     ip_handle_martian_source(dev, in_dev, skb, daddr, saddr);   
  182.     goto e_inval;  
  183. }  

源码还是比较长的,要有耐心读下去啊!其实struct flowi这个结构还是比较有技巧的。

标签:

给我留言