注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

Linux ip协议收包与路由相关代码  

2011-07-26 12:52:53|  分类: linux相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |


同事发现几张虚拟网卡的时候,有一种奇怪的现象,从不同的接口ping 外面网络的时候,有的接口可以通,有的不行。

不通的时候,发现其实包已经回来了,tcpdump都可以抓得到,但是ping程序就是没有收到。怀疑和路由设置有关,好像设置乱七八糟的什么高级路由上面之后就是可以的,还不清楚是什么问题,不知道和我们自己的代码有关系没有。什么时候有空去研究一下。


翻一下源码,随便记录一下


网卡受到包之后 调用 netif_tx  函数把包交给啮合协议栈,然后排在队列上

__netif_receive_skb  
 {
    遍历每个协议 ,这里调用tcpdump的pf协议和 ip_rcv函数
 
 }


ip_rcv {

     
         return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,
                     ip_rcv_finish);
         //NF_HOOK 这个函数就是判断如果iptables的规则没有把这个包丢掉的,就调用 ip_rcv_finish 函数来继续处理这个包
         // 这个NF_INET_PRE_ROUTING就是在 路由之前的挂在点了,路由处理在ip_rcv_finish函数里面
         
                     
}

ip_rcv_finish {
    if (skb_dst(skb) == NULL) {
       ip_route_input_noref  -->>ip_route_input_common   ip_route_input_slow  这里处理路由
    }
    
     dst_input(skb);   ///调用dst_etnry->input 函数
}


http://book.chinaunix.net/special/ebook/oreilly/Understanding_Linux_Network_Internals/0596002556/understandlni-CHP-33-SECT-5.html   一书有对  dst_entry  的解析


__mkroute_input {

        rth->dst.input = ip_forward;  初始化 为这个函数?
        rth->dst.output = ip_output;

}








ip_forward {
        if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
                 return NET_RX_SUCCESS;    //普通的 ip包
                 
 
        //需要转发的ip包
        return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev,
                      rt->dst.dev, ip_forward_finish);  //原来这个NF_INET_FORWARD 挂载点在这里
 
 
 
 }
 
 
 
  148/*
 149 *      Process Router Attention IP option (RFC 2113)
 150 */
 151int ip_call_ra_chain(struct sk_buff *skb)
 152{
 153        struct ip_ra_chain *ra;
 154        u8 protocol = ip_hdr(skb)->protocol;
 155        struct sock *last = NULL;
 156        struct net_device *dev = skb->dev;
 157
 158        for (ra = rcu_dereference(ip_ra_chain); ra; ra = rcu_dereference(ra->next)) {
 159                struct sock *sk = ra->sk;
 160
 161                /* If socket is bound to an interface, only report
 162                 * the packet if it came  from that interface.
 163                 */
 164                if (sk && inet_sk(sk)->inet_num == protocol &&
 165                    (!sk->sk_bound_dev_if ||
 166                     sk->sk_bound_dev_if == dev->ifindex) &&
 167                    net_eq(sock_net(sk), dev_net(dev))) {
 168                        if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
 169                                if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN))
 170                                        return 1;
 171                        }
 172                        if (last) {
 173                                struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 174                                if (skb2)
 175                                        raw_rcv(last, skb2);     ///这里受到包??
 176                        }
 177                        last = sk;
 178                }
 179        }
 180
 181        if (last) {
 182                raw_rcv(last, skb);
 183                return 1;
 184        }
 185        return 0;
 186}



 
static int ip_forward_finish(struct sk_buff *skb)
{
        struct ip_options * opt = &(IPCB(skb)->opt);

        IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
 
         if (unlikely(opt->optlen))
                ip_forward_options(skb);

         return dst_output(skb);   ///转发的时候往外面发包了?
}
 
 
 
 可以结合 tcpdump点和netfilter点,加点调试信息看包到底在上面地方被丢掉了!什么时候有空试试。这个问题很奇怪好像在redhat4上面可以正常工作,是在redhat5还是什么地方发现的问题。
  评论这张
 
阅读(792)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017