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

190 篇文章 1 订阅

http://hi.baidu.com/widebright/item/779aeff92f48f26a3c1485d3

同事发现几张虚拟网卡的时候,有一种奇怪的现象,从不同的接口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);   ///转发的时候往外面发包了? 
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值