网络协议栈12:Connect函数分解之IP层

Tcp层把数据从传输层下传到网络层,之后,网络层将对下传的数据进行处理。

 

首先,要对下传的数据进行排列。

经过TCP层的处理,现在的数据已经被放置到skb_buff结构体中的数据空间部分,TP层就要对这个skb_buff进行必要的排列,使得数据有个先来后到的顺序,从而达到公平。对skb_buff的排列,是通过skb_buff对应的sock结构体成员sock->send_tail , sock->send_head 和skb_buff->link3 这三个成员来完成的,大致的排列图示如下:

 

当前sock的所有skb_buff结构体都被按照 图 1 /2 /3 的方式插入到队列中,sock->send_head一直指向队列的首部,IP层下传数据时,都是从send_head获得数据的,sock->send_tail一直指向队列的尾部,TCP层下传skb_buff到IP层时,都被插入到这个队列的尾部的。

 

接下来判断skb_buff中数据的大小,这里的数据是指数据空间的大小,不包含skb_buff部分,如果数据空间的大小大于已经定义好的每帧数据的大小,就需要对数据进行分片处理,比如,用户空间发送一个100MB的电影文件,但是系统定义的每次可以传输的数据大小为576字节,那就要对100MB的数据进行多次分片,每次发送576字节,直到最后的数据小于576字节为止。因为要把分片的数据又重新组合成一个完整的数据,比如要把很多个576字节的数据组成100MB的数据,就需要知道每个分片数据的排列序号,才能按照这个序号重新排列,因此,在IP首部中有一个frag_off成员,用于记录每个分片数据在原来数据中的偏移位置。

 

由于有两种情况,数据会经过IP层的排列而转发给链路层,一种是本地数据刚下传到IP层,另一种是数据发送不成功,需要重发的,针对本地数据,即刚刚下传到IP层的数据,就需要排队,把数据放到队列的尾部,而如果是因为发送不成功,需要重发,就直接从队列的首部获得,因为数据已经在对列里了。

 

当skb_buff到达IP层后,原来所在队列要把这个skb_buff剔除出链表,使得skb_buff->next,skb_buff->prev指针为空,这样才能在链路层中进行传输

 

接下来,由于数据就要经过链路层,准备发送了,根据要求,多播和广播,是需要把数据复制一份发送回本机的,因此,此时,就需要判断发送类型了,如果是多播,或者广播,就需要把数据发送一份回本机,loopback软设备通过新建一个skb_buff,并把原来的skb_buff中的TCP,IP的内容复制,并把设备设置成了loopback_dev,在链路层时,就通过loopback_dev设备,而不是经过网卡,把数据发送了。

 

总之,connect函数在IP层的处理,先根据是本地数据还是重发数据,而决定是否需要把数据进行排列,之后,判断数据是否需要分片,需要分片的数据,先按照规定分片,再进行发送,最后判断是否是多播或者广播,如是,还需要复制一份数据,通过loopback设备进行发送,当然还有防火墙是在IP层上实现的。

posted on 2012-01-12 12:09  image eye  阅读(714)  评论(0编辑  收藏  举报