免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3619 | 回复: 11

[网络子系统] sk_buff, skb和MSS的分段 [复制链接]

论坛徽章:
0
发表于 2013-03-10 16:41 |显示全部楼层
10可用积分
   最近做TCP协议优化,需要将十几K的包一次投递出去。
   在编码测试过程中,发现问题:虽然我在tcp_ipv4.c和tcp_input.c中将snd_cwnd初始窗口调整很大,但发送数据出不去。
   捕捉了一下数据,找到两个原因:
1. 对端通告窗口snd_wnd(这个就是对端的通告窗口,在snd_cwnd值很大的情况下,也是下一次的发送窗口)没有超过7480Byte
    这个值很奇怪,按我读到的协议设计来讲,通告窗口应该很大,至少比十几KB大得多。
    这个问题我解决了,在发送过程强制更改源码,增大包处理过程的snd_wnd
2. 还有一个问题:skb的分段,TCP发送流程中,skb占据举足轻重地位,这货实际上就是sk_buff,而sk_buff是整个网络协议栈的核心。
    skb在发送过程中会根据当前MSS的值分段。
    比如说当前MSS的值是1000Byte,而我要发送5999Byte的数据,就会分成这样:5000B+999B,两次发送。
    但是如果我要发6000B的数据,刚好被MSS整除,反而可以一次发送出去。
   (我已经把窗口调整到足够大了,不用担心窗口不够用)。
    我的问题是:为啥要这样分段?这样分段比发送6000B要慢一个RTT,一次全投递不是更好吗?在网络其它层,有根据MSS分段吗?

欢迎大家对两个问题进行讨论,第一个问题我虽然暴力解决了,但是没有理解。第二个问题则是完全不理解,也没办法优化。
本来想找大神问的,没找到,找到的也不理我,谁有TCP大神,比如《Linux内核源码剖析》作者,或者其他人联系方式的,求不吝赐教。

最佳答案

查看完整内容

回复 5# henrystark 这么做同样是为了效率的问题。当根据MSS分割后,如果最后剩余的部分不到一个MSS,那么内核会等待一定的时间后,才会发送这个分片。内核这么做的原因如下:(1)如果内核每次收到一个字节就马上发送出去的话,那么带宽的利用率非常低(大部分的带宽都被协议栈头给占据了)(2)内核会等待一定的时间,如果这个时间内又有新的用户态数据需要发送,那么就可以组装到一个skb中发送,而不用分成多个skb发送了。

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2013-03-10 16:41 |显示全部楼层
回复 5# henrystark
比如tso分出的一个段可以有7KB,但是同时带来的问题就是:不能被整除的段会延迟到下一次发送,哪怕不能被整除的只剩下一个字节,也是这样。
极端的例子也有5999Byte和6000Byte的,很奇怪的机制,不懂。


这么做同样是为了效率的问题。
当根据MSS分割后,如果最后剩余的部分不到一个MSS,那么内核会等待一定的时间后,才会发送这个分片。内核这么做的原因如下:
(1)如果内核每次收到一个字节就马上发送出去的话,那么带宽的利用率非常低(大部分的带宽都被协议栈头给占据了)
(2)内核会等待一定的时间,如果这个时间内又有新的用户态数据需要发送,那么就可以组装到一个skb中发送,而不用分成多个skb发送了。

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2013-03-10 20:28 |显示全部楼层
我要发6000B的数据,刚好被MSS整除,反而可以一次发送出去

----------------------
真的?

论坛徽章:
0
发表于 2013-03-11 09:14 |显示全部楼层
回复 2# chishanmingshen
真的,哥测过

   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2013-03-11 14:01 |显示全部楼层
回复 1# henrystark
    skb在发送过程中会根据当前MSS的值分段。
    比如说当前MSS的值是1000Byte,而我要发送5999Byte的数据,就会分成这样:5000B+999B,两次发送。
    但是如果我要发6000B的数据,刚好被MSS整除,反而可以一次发送出去。

看看是否开启了TSO和GSO的特性。如果开启了这个特性的话,传输层(TCP)是不会根据MSS进行分片的,而是将分片推迟到最后发送数据包的时候进行。
   

论坛徽章:
0
发表于 2013-03-11 14:12 |显示全部楼层
回复 4# 瀚海书香
开启了,所以在TCP层,可以支持n*MSS的很大段。
比如tso分出的一个段可以有7KB,但是同时带来的问题就是:不能被整除的段会延迟到下一次发送,哪怕不能被整除的只剩下一个字节,也是这样。
极端的例子也有5999Byte和6000Byte的,很奇怪的机制,不懂。

   

论坛徽章:
0
发表于 2013-03-11 15:33 |显示全部楼层
回复 6# 瀚海书香
在tcp发送流程中,看到有小包拼接的nagle算法,你说的这个效率问题算不算是nagle算法呢?
虽然这种措施在普遍意义上可以提升效率,但是在我测试的条件下,还是拿5999B和6000B例子来说,反而会拖慢一个RTT,如果RTT很大,就浪费带宽。
内核能不能支持:如果是最后发送的数据,就一起投递呢?
或者有没有关闭这种策略,直接投递的?

   

论坛徽章:
4
酉鸡
日期:2014-03-21 23:19:50狮子座
日期:2014-08-01 22:11:40酉鸡
日期:2015-01-10 21:31:442015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2013-03-11 16:06 |显示全部楼层
tcp是stream的,不知道何时结束。。。

所以只能类似nagle地处理了,估计是这样的。

论坛徽章:
0
发表于 2013-03-11 17:08 |显示全部楼层
回复 6# 瀚海书香
谢谢斑竹,那个问题解决了,在TCP发送流程中,有nagle_test函数调用。
把nagle_test源码返回值改掉,虽然skb还是分为了两段,但是发送的时候可以一次投递出去了。


   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
发表于 2013-03-11 18:33 |显示全部楼层
回复 9# henrystark
谢谢斑竹,那个问题解决了,在TCP发送流程中,有nagle_test函数调用。
把nagle_test源码返回值改掉,虽然skb还是分为了两段,但是发送的时候可以一次投递出去了。


从设计的角度来说,不建议这样搞。最好是在应用层设置TCP_NODELAY,来避开nagel算法
   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP