用户态协议栈tapip代码分析-TCP重传

作者

QQ群:852283276
微信:arm80x86
微信公众号:青儿创客基地
B站:主页 https://space.bilibili.com/208826118

自动重发请求机制

很多保证可靠性的协议都有自动重发请求ARQ(Automatic Repeat reQuest)特性,在ARQ中,接收机发送已接收到的数据的ACK,发送者会重传未接收到ACK的数据。TCP保存发送数据的序列号,已经发送的数据被放入重传队列,并启动与数据相关联的定时器。如果在定时器用完之前没有接收到数据序列的确认,则会发起重传。但这样会产生很多问题,比如发送者应该等待多久就发起重传,这会影响到性能。TCP通过SACK对无序数据ACK,避免不必要的往返确认交互,浪费效率。

TCP重传

TCP考重传机制来保证数据的可靠性。当TCP传输一个带有数据的报文段的时候,TCP就会将它复制一份放到重传队列中,然后开启一个定时器,当收到对应的ACK之后,就从队列中删除这个报文,如果产生超时,则该报文会被重传。
最新的重传方法在RFC62986中描述,下面三个变量用来计算RTO

  • srtt 是RTT的平均值
  • rttvar 是RTT值
  • rto 是重传超时时间
  • g 是时钟精度

在第一次计算RTT之前,

rto = 1000ms

第一次计算RTT,

srtt = R
rttvar = R/2
rto = srtt + max(g, 4*rttvar)

在接下来的计算中,

alpha = 0.125
beta = 0.25
rttvar = (1 - beta) * rttvar + beta * abs(srtt - r)
srtt = (1 - alpha) * srtt + alpha * r
rto = srtt + max(g, 4*rttvar)

计算出RTO值之后,如果小于1s,那么向上取整到1s,最大是按60s取整,这是为了避免产生太多重传,引起网络阻塞。时钟精度可以去相当大的值,比如500ms到1s之间,但现在的操作系统比如linux,RTO最小为200ms,同时g取值为1ms。linux下的RTO计算参考博客TCP中RTT的测量和RTO的计算

Karn算法

Karn算法是为了防止RTT测算出错误的结果,它要求RTT的采样值不能是发生重传的包,因为我们无法确定某个ACK包是前面报文的ACK还是重传包的ACK,但是如果开启了TCP时间戳选项,那就可以分辨出ACK对应的是哪个报文,就可以应用这个ACK来更新RTT。

#RTO定时器管理

RFC6298推荐用下面的方法来管理RTO定时器,

  • 当发送报文时,RTO定时器若没有开启,则打开RTO定时器,设置超时时间为变量rto的值
  • 当所有数据报文都收到ACK,关闭RTO定时器
  • 当收到ACK之后,用新的的rto重启定时器

当RTO定时器超时(expire),重传最早的没有收到ACK的报文,增加(back off)超时重传时间(比如rto = rto * 2,指数增加),重启定时器。当back off发生之后,再次测算到RTT之后,RTO可能会迅速减小,协议栈可能会清除srtt和rttvar当back off等待ACK的时候。

#请求重传

TCP不仅仅是依靠发送端的定时器来控制丢包,接收方也可以主动通知发送方重传丢失报文,利用SACK(Selective Acknowledgment),接收端可以通过发送带SACK选项的报文段准确告诉发送方需要重传哪个报文。SACK具体参考博文TCP-IP详解:SACK选项(Selective Acknowledgment),和TCP 选择性应答的性能权衡

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值