TCP发送端收到ACK后对传输队列的4次扫描
Posted ksiwnhiwhs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP发送端收到ACK后对传输队列的4次扫描相关的知识,希望对你有一定的参考价值。
1.第一遍扫面,分别做以下事情:
故事发生在tcp_ack->tcp_sacktag_write_queue函数
1.1.标记被SACK的数据包
1.2.标记哪些已经重传的包可能丢失
1.3.更新网络乱序度reordering
如果UNA向前推进了,我们就不多说了,如果没有推进UNA,而且有SACK标记(请注意,FACK并不是一种特殊的模式,它只是SACK的一种激进重传方案)的情况下,第一遍扫描会完成上述的1.1,1.2,1.3这三件事,其中第一件事就不说了,就是按照ACK数据包的选项,将传输队列中的被选项选中的数据包标记为SACK;第二件事有点复杂,一般而言,TCP的每一种重传机制除了RTO的退避机制会重传多次之外,只会将数据包重传一次,但是事实上并不绝对,如果可以启发到重传的数据包有很高的概率丢失,那么就可以将该重传过的数据包抹去其“已重传”标志,这意味着如果有哪个执行路径认为其可以被重传,那么它将会被再次重传一次!
如何判断一个重传的数据包已经丢失呢?请看Linux协议栈之tcp_mark_lost_retrans函数,其主要思想是:在重传每一个数据包的时候,记录重传当时的snd_nxt,记为其ack_seq字段,如果发现一个被重传的数据包的ack_seq后面的数据包都被SACK了,那么就说明该重传数据包可能又一次没有到达接收端,丢失了!注意,这也是一种启发式算法,因为在重传数据包N的时候,其ack_seq几乎同时也被传输了,那么正常来讲,它们的ACK应该同时到来,然而数据包N的ack_seq后面的都被SACK了,而数据包N却没有被SACK,说明它可能丢失了。如下图所示:
关于1.3,请看《TCP拥塞控制图解(不包括RTO,因为它太简单了)》 原图中的网络重排序一节。
需要说明的是,对于1.3而言,扫描的时候,总是找到fack(请注意,它仅仅是一个计数器而已)最左边的第一个数据包(fack计数器每次都要从左到右撸一遍,撸的同时,记录从左到右第一个遇到的被SACK的数据包【它可能是被SACK的,也可能是被DSACK的】),然后fack与该数据包之间的距离就是新的reordering的值(如果它比老的reordering大的话)。
2.第二遍扫描:清除已经被顺序接收的数据包,更新诸多计数器
故事发生在tcp_ack->tcp_clean_rtx_queue
a).sacked_out:如果该数据包曾经被SACK过,即有SACKed标记,那么sacked_out会递减相应被清除掉的数据包大小;
b).lost_out:如果该数据包曾经被标记为LOST,那么lost_out会递减相应的数据包的大小;
c).packets_out:由于被ACK,那么packets_out会无条件递减被清除掉的数据包的大小;
d).retrans_out:如果该数据包被重传过,那么retrans_out会递减被清除掉的数据包的大小;
e).fackets_out:由于fack计数器仅仅与最右边被SACKed的数据包以及UNA有关,因此如果被清除掉的数据包大于fack计数器,那么fack归零,否则递减被清除掉的数据包大小。如图所示:
第二遍扫面的宗旨有二,其一是向前推进UNA,清除发送队列的skb,其二就是更新TCP的计数器,标准化“在途流量”。
3.第三遍扫描:标记可能已经LOST的数据包
4.第四遍扫描:按照RFC3517 nxtSeg例程传输该传输的数据包
5.结语
本文用很短的篇幅简述了Linux协议栈收到TCP的ack包后的反应,开启了4遍扫描(对于fast路径,没有第一遍!),每一遍扫描都完成很少的特定任务,最终完成TCP的快速重传。
故事还没有结束
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow
以上是关于TCP发送端收到ACK后对传输队列的4次扫描的主要内容,如果未能解决你的问题,请参考以下文章