- 论坛徽章:
- 0
|
原帖由 scutan 于 2008-8-26 16:59 发表 ![]()
小结一下, UDP协议不会进行分包, 传送的数据会放到同一个UDP头部进行发送, 但是在Linux内核的实现中, 它会在UDP层进行分包, 但是之后会进行合并, 并加上唯一的UDP头部传送给IP层进行处理.
更正一下:
之前的理解有一点错误,应该为:在UDP层进行了分包之后,不会再进行合并了。
解释:
对于UDP协议来说,在发送的时候会调用函数ip_append_data,在该函数中会根据MTU的大小,对数据包进行分片,除第一个sk_buff外,将其余每个在MTU大小内的数据加上sk_buff头部,全部挂接到第一个sk_buff的frag_list链中。如下图所示:
然后将数据包传送到了IP层时,会调用函数ip_fragment。该函数的其中一个功能就是对本机发送的已经经过了分片的数据包进行发送。
但是在之前的内核中,所有的分片工作都是在IP层作的,IP层可能会收到很大的一个数据包,然后将其分成若干个小包,并发送。其中的拷贝就对性能产生了一定的影响。
因此在新的内核中就在将数据从第四层传送到IP层的时候提前将这个分片的工作给完成了。也即是像上图那样,每个sk_buff所包含的数据包的大小都在MTU的范围内,因此,现在在IP层的任务就是为每个数据包建立一个IP头。所以说在发送UDP数据包的时候,会在UDP层提前对数据包进行分片(因为现在不分,以后到了IP层也仍然会分片的)。然后在IP层,只对分了片的数据包添加头部即可了。通过这种方式,提高了传输的性能。
所以,在了L4层的提前分片的功能,使得ip_fragment函数的功能就分成了两个大的方面:快速分片与慢速分片。由于只在本地发送UDP包的时候才会提前进行分片。所以有很多包的大小还是大于MTU的。所以在慢速分片的情况下,会将sk_buff中的数据根据MTU的大小来分片,并添加上IP头部。对于在UDP层已经进行分片了的数据(可以通过frag_list来判断),则使用快速分片的方式,在每个sk_buff中加上IP头部即可。
对于ip_fragment函数更详细的解释在《深入理解Linux网络内幕》中第22章有讲解,我也是最近看到那么才发现之前的想法是错误的。 |
评分
-
查看全部评分
|