1、sk_buff
在这里,我不想描述sk_buff的结构,因为网上已经有很多资料了。
当一个数据包被网络设备接收时,alloc_skb()将被调用,用来为packet分配一块空的buffer,如下图:
起初,它是一个空的buffer,所以所有的指针都有跟head相同的值,当packet到达时,skb_put()被调用,它会改变几个头部指针,让他们指向正确的位置,就形成了下面的结构:
当packet从协议下层往上层移动时,他的头部会被一层一层地剥离掉,每当这个时候,skb_pull()会被调用,他会将pointer data向下移动,,看起来就像下面的图形:
最后,kfree_skb()被调用,释放内存空间。
2、A packet’s life in a web server
Packet’s life如下:
1、client发送一个get request
2、Web server的NIC先对signal进行decode,然后NIC产生一个interrupt,通知driver将数据包拿走。
3、Driver会从skb_buff pool中分配一个skb_buff用来存放get request。
4、Driver会将skb_buff的pointer传给IP layer的接收函数。
5、IP layer的接收函数检查packet的合法性,然后将该packet hook到prerouting table上,学过netfilter的读者应该对prerouting不陌生。
6、数据包被netfiler push到tcp layer中
7、Tcp layer处理完后将给packet发给应用层,也就是web server。在该过程中,需要做一次数据拷贝。
8、同时,tcp layer会基于给get request产生一个ack packet,发往client。
9、Web server会产生一个http response,通过socket interface发送它,该packet会通过tcp ip NIC最后到达client。
10、Client收到http response后发送一个tcp ack 表示已经收到该response。
在一个服务器中,从socket到driver各层的性能排名:
最消耗cpu time的是tcp layer,因为他要赋值数据;ip layer居中,用时最少的是link layer,当link layer的用时很大程度依赖于driver和hardware。在某些情况下,它可能会超过ip layer。
从经验上来看,一个http request和response 的处理大概耗时34us。
3、A packet’s life in a gateway
最为一个router or gateway,它的大部分数据包可能不需要经过tcp layer或者更高层的模块,但是它需要forwarding、firewall、Qos等功能。它处理数据包的过程如下:
1、gateway(or router)从内网收到一个数据包。
2、Gateway首先检查它的正确性,然后检查pre-routing chain来决定是否将它转发到internet上,另外,在pre-routing上,数据包可能会被打上一个tag来决定数据包的服务类型和转发的优先级
3、Gateway 会用该数据包的目的IP地址检查forward chain 来对该 Packet 做出forwarding and routing的决定。
4、如果数据包被forwarding,则需要做nat,而nat就是检查post-routing chain,数据包的source Ip address会在这里被替换。
5、最后gateway会在这里对数据包进行traffic control。
在一个router中,从socket到driver各层的性能排名:
最消耗cpu time的是link layer和ip layer,tcp layer基本上不耗时,但link layer的用时很大程度依赖于driver和hardware。从经验上来看,一个router处理数据包所消耗的cpu time会比一个web server少很多。