免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123
最近访问板块 发新帖
楼主: jiufei19
打印 上一主题 下一主题

关于Linux TCP中超时重传定时器的疑问【还有点小问题】 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
21 [报告]
发表于 2009-10-05 17:58 |只看该作者

回复 #19 jiufei19 的帖子

自己再顶下。

这几天我又来来回回阅读了rfc2581,rfc2582,FF96,alexey kuznetsov的那篇文档,初步进行了如下总结,望大家指正

1、因重传超时定时器到时引发的分段丢失,于是就如同eexplorer描述的那样,发送方立即进入loss状态,所有从snd_una -> high_seq之间的包都会被认为是丢失了。然后tcp把cwnd设成1,使用slow start重发所有丢失的包。也就是说,假设S1 timeout了,TCP先发S1,收到ack后,cwnd加1,然后发送S2, S3。

>> 这里有必要说明下,我原来存疑的一个问题就是在重发S1后,是否应该立刻可以发送S2,查了上述若干文献,都没有看到明确说明,但是仔细想想,此时进入了慢启动阶段,如果重发分段不受慢启动控制,似乎有点别扭,因此感觉eexplorer的说明是正确的,在此表示感谢

2、因连续收到3个重复ACKs所引发的分段丢失,此时根据rfc2581可以明确看出,Reno算法中(Stevens 在tcpip协议详解中21.6、21.7及21.8中描述)发送方在进行重发丢失分段后,实际上进入到拥塞避免阶段,此时并不一定要等待重发分段的ACK到达后才能发送新分段,是否可以即刻发送新分段仅受当前cwnd状态变量的限制,如果可以就发送,不行就必须等待额外的重复ACK的到来以增加cwnd直到又可以发送新分段为止(Stevens给出的21.8节例子恰恰是不允许发送,而必须等待cwnd增加到某个程度时的例子)

3、对于Reno算法,快速恢复阶段终止于只要某个ACK有对新数据的确认,而NewReno算法的快速恢复阶段一直保持到一个窗口内所有丢失分段都被重发并成功确认为止

4、Reno和NewReno算法都必然固有一个性能低下的问题,即一个窗口内有多个分段丢失的话,则根据我在20楼发的帖子可以看出,在一个RTT内只能有一个丢失分段被重传,所以效率较低(FF96等几个文献中所给出的该问题的原因,说实话,我没有很好地弄懂,望有人能指点下,这里我是根据这几个文献的描述大概揣摩出的,不晓得正确否)。当然如果有SACK后,则发方就知道哪些该重发,哪些不重发,于是重发效率就高了

5、在rfc2582中有如下一段话
----------------------------------
This NewReno modification differs from the implementation in [RFC2581] only in the introduction of the variable "recover" in step 1, and in the response to a partial or new acknowledgement in step 5.  
...
   ssthresh = max (FlightSize / 2, 2*MSS)           (1)
      
【Record】the highest sequence number transmitted in the variable "recover".
----------------------------------
显然这个recover变量似乎就是linux中的tp->high_seq,代表发送方曾经发出的最大序号,而不是曾经发出的最大序号+1(snd.nxt),eexplorer在我的另外一篇帖子“Linux TCP协议栈处理函数tcp_sacktag_write_queue的分析问题”中认为就是snd.nxt,似乎值得商榷,eexplorer的原文摘录如下:

high_seq是tcp进入recovery state的时候的snd_nxt,以你举的例子为例,当收到连续3个duplicated ack后,tcp进入recovery state,这时已经发送了S5,那么这时的snd_nxt就是s6,high_seq也就是s6了。

论坛徽章:
0
22 [报告]
发表于 2009-10-06 10:36 |只看该作者

回复 #1 jiufei19 的帖子

TCP中的超时定时器是一个有序链表,每个报文的超时是链表上的一个节点,单独的进程定时轮询该链表挑出超时的节点进行重发。那么只要有一个链表就可以同时表示n多的定时器了。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
23 [报告]
发表于 2009-10-09 10:31 |只看该作者

回复 #22 lkjxing 的帖子

感谢帮助。

因为我是在阅读tcp中关于sack部分的处理逻辑时发现之前对于拥塞控制等处的处理概念上没有特别清楚,所以提出此系列问题,

lkjxing在帖子中说:
>> 每个报文的超时是链表上的一个节点,单独的进程定时轮询该链表挑出超时的节点进行重发。

请问每个报文都对应一个该链表上的节点吗?因为我之前的帖子已经举例源码了,似乎不会有多个节点分别对应每个报文的,请lkjxing参考指正

论坛徽章:
0
24 [报告]
发表于 2009-10-10 10:10 |只看该作者
原帖由 jiufei19 于 2009-10-5 17:58 发表
自己再顶下。

这几天我又来来回回阅读了rfc2581,rfc2582,FF96,alexey kuznetsov的那篇文档,初步进行了如下总结,望大家指正

1、因重传超时定时器到时引发的分段丢失,于是就如同eexplorer描述的那样, ...


for 1,2,能不能发送新的数据取决于congestion window的大小(当然还有接受方的rcv_wnd大小的控制),不同的状态决定了cwnd的大小。Linux自己会预估当前in flight的segment有多少,和当前的cwnd相比,如果有盈余的话,就不需要等待ACK,可以立即发送新的数据。

for 3,4,没有sack信息的话,sender一次只能重发一个segment,因为它只有dup ack这个信息。如果一个窗口内有几个segment丢失的话,从recovery -> open需要花费的时间就更长。因为在recovery状态,cwnd是不允许增加的,所以发送新的数据的频率就会比较慢。如果有sack信息的话,sender可以明确的知道哪几个segment丢失了,那么他一次可以重发几个segment,能快速的恢复到open状态。

for 5, 你可以去看一下tcp_fastretrans_alert()中 /* F. Process state. */下的代码,一旦从open进入任何一个别的状态(the default case),tp->high_seq = tp->snd_nxt,只有受到ack的seq > high_seq才会跳出这个状态,重新进入open。


读Linux tcp代码麻烦的就是,它是一个非常大的状态机,不能单独的拿出一个函数来进行分析,因为它牵涉到了很多上下文。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
25 [报告]
发表于 2009-10-10 11:11 |只看该作者

回复 #24 eexplorer 的帖子

非常感谢eexplorer的答复。

我查了下tcp_frastretrans_alert,tcp_enter_cwr,tcp_enter_frto,tcp_enter_loss等等,都是tp->high_seq = tp->snd_nxt,看来我要修正下自己的错误理解了。

论坛徽章:
0
26 [报告]
发表于 2014-04-13 15:46 |只看该作者
回复 25# jiufei19


要好好学习你的精神!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP