linux-3.10.36内核网络数据包处理流程
网卡
接收
发送
DMA循环队列
软中断技术
netif_rx()
轮询技术(几乎被淘汰)
netif_receive_skb()
return pt_prev->func(skb, skb->dev,pt_prev, orig_dev)
//调用函数ip_rcv() arp_rcv()等
通过路由表查找:
- 如果是丢弃的报文,则直接drop;
- 如果是不能接收或转发的报文,则input = ip_error
- 如果是发往本机报文,则input = ip_local_deliver;
- 如果是广播报文,则input = ip_local_deliver;
- 如果是组播报文,则input = ip_local_deliver;
- 如果是转发的报文,则input = ip_forward;
arvik 1216601195@ qq.com
http://blog.csdn.net/u012819339
arp_rcv()
该函数主要检验skb包ip头部
信息是否完整、有误等等
该函数主要功能是根据skb中
的路由信息做路由选择
ip_rcv()
NF_INET_PRE_ROUTING
ip_rcv_finsh()
转发
ip_forward()
NF_INET_FORWARD
ip_forward_finish()
dst_output()
多播
nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,skb->dst->dev, xfrm4_output_finish);
在xfrm4_output_finish()调用nf_hook来递归遍历并执行POST_ROUTING节点上的所有钩子
该函数主要检查发送数据包的大小是否超
过MTU,如果是,则先调用ip_fragment将
其分片,然后再传给ip_finish_output2()
ev_queue_xmit()
最终...
ip_output()
单播
NF_INET_POST_ROUTING
ip_finish_output()
如果数据包过长则
要进行分片
ip_finish_output2()
neighbour->output
return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish);
NF_HOOK将skb投入netfilter的PRE_ROUTING节点,若该节点所有钩子都能返回NF_ACCEPT,则
最后调用ip_rcv_finsh()函数来处理
return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL, ip_local_deliver_finish);
同样调用NF_HOOK将skb投递给netfilter的LOCAL_IN节点,最后调用ip_local_deliver_finish()函数处理
上交给本机
ip_local_deliver()
N
F
_
I
N
E
T
_
L
O
C
A
L
_
I
N
ip_local_deliver_finish()
return NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, rt->dst.dev, ip_forward_finish);
丢给FORWORD节点,最后调用ip_forward_finish
return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dst->dev,
x->outer_mode->afinfo->output_finish, !(IPCB(skb)->flags & IPSKB_REROUTED));
该函数主要对ip分片进行重组,到最后
一帧数据包到达后ip_defrag返回0,
skb被重置为完整的数据包,然后调用
NF_HOOK最后发往
ip_local_deliver_finish函数
T
U
O
_
L
A
C
O
L
_
T
E
N
_
F
N
I
此时,确定要将这个数据包传送给上层(L4)协议,故剥离L3层包头,然后首先处理
RAW IP(先查看raw_v4_htable有没有注册到这个L4协议的Raw IP,如果有则要执行
raw_v4_input()函数为其提交一份副本,这就是网络嗅探工具的原理),根据L3层中的
协议指示,调用上层相应的协议(TCP、UDP...)来处理,
local
ip_local_out()
设置ip报文总长度tot_len,校验和
ip_send_skb()
ip_push_pending_frames()