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); ///转发的时候往外面发包了?
}