Chinaunix首页 | 论坛 | 博客
  • 博客访问: 199747
  • 博文数量: 40
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 25
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-31 10:34
文章分类
文章存档

2019年(2)

2017年(14)

2016年(8)

2015年(10)

2014年(6)

我的朋友

分类: LINUX

2015-08-12 11:29:25

1、当上层发送的数据包大小超过mtu时,会进行分片(或分段)

2、通常情况下网络包分片(分段)在传输层(level 4,TCP或UDP)进行,即根据mtu大小将数据包分成mtu大小的段,然后然发送。

3、当传输层分段后,下发的数据包大小就肯定小于MTU了,此时IP层就不会再分片了。

问题:那什么情况下会在IP层分片呢?
有如下情形:
1)在IP层进行转发时,当下一条的mtu比较小时,此时会在IP层分片。
2)使用IPSEC时,此时也可能在IP层分片。
3)内核中的某些bug导致。案例见后面。

4、tcp是基于流的传输协议。当上层发小包时,通常会在tcp层将小包数据组合成大包,并根据mtu对包进行分段,将其切割成mtu大小的数据包;当上层发送大包时(大于MTU),则会直接进行分段。分段后的数据放在skb中,每个skb对应一个数据包,并链入sock结构的链表中。

5、内核中的sock对应于一个应用层的socket,每个sock包含一个skb的链表,每个skb中包含一个数据包,一个sock上发送的所有数据包逻辑上
被看做放入了sock的发送缓冲区中(wmem),当向该sock对应的socket发送数据时,数据包被放入相应的发送缓冲区中,发送缓冲区大小增加。当skb被发送出去时,相应的发送缓冲区大小减少,最少为1,因为sock创建时会将其大小置为1,只有当sock被释放,同时发送缓冲区大小为0时,该sock才能被释放。

6、skb->frag_lists用于存放IP层的分片。由于通常在传输层已经分好,所以这里通常装的是传输层分好的数据包。具体原理为:
tcp/udp进行分段后,数据包被传入IP层,IP层会从sock的skb链表中取出第一个skb,然后将剩下的所有skb依次链入skb->frag_lists中,所以sock中的skb链表到IP层后,其实就只有一个skb了,其它的数据都放入这个skb的frag_lists中了。
在这个过程中,IP层还是会检查每个skb的大小,如果大于mtu,同时第一个skb中又没有设置UFO或GSO标志时,此时则会在IP层进行分片。
但会出现这样的情况么?每个skb不是都在传输层进行过分段了吗?怎么会出现大于Mtu的情况?
是的,正常情况下,的确不会这样,但如下场景中(其实是内核的一个bug)就会出现:
在开启UFO或GSO的情况下,先发送一系列小包(比如1200,mtu为1500),然后再发送一个大包(如1600),此时前面的包都没有带UFO或GSO标记,但最后一个大包却带上了UFO或GSO标记,在IP层将skb合并时,由于:1、第一个skb中没有UFO或GSO标记,所以不会将大包继续下发到底层;1、最后一个包大于mtu,此时IP会检查到,然后在IP层对其进行分片。

阅读(2027) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~