mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-29 15:11:44 +08:00
快速恢复 发生了快速重传后 同时开启快速恢复 如果重传成功 退出快速恢复 然后进入拥塞避免线性增加数据包 当rto内没有回复认定丢包 重发数据 然后回到慢启动
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package tcp
|
package tcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"netstack/logger"
|
"netstack/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,7 +32,9 @@ func (r *renoState) updateSlowStart(packetsAcked int) int {
|
|||||||
// 更新拥塞窗口
|
// 更新拥塞窗口
|
||||||
r.s.sndCwnd = newcwnd
|
r.s.sndCwnd = newcwnd
|
||||||
r.cnt++
|
r.cnt++
|
||||||
|
logger.GetInstance().Info(logger.TCP, func() {
|
||||||
logger.NOTICE("一个 RTT 已经结束", atoi(oldcwnd), "慢启动中。。。 reno Update 新的拥塞窗口大小: ", atoi(r.s.sndCwnd), "轮次", atoi(r.cnt))
|
logger.NOTICE("一个 RTT 已经结束", atoi(oldcwnd), "慢启动中。。。 reno Update 新的拥塞窗口大小: ", atoi(r.s.sndCwnd), "轮次", atoi(r.cnt))
|
||||||
|
})
|
||||||
return packetsAcked
|
return packetsAcked
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +80,7 @@ func (r *renoState) HandleRTOExpired() {
|
|||||||
// RFC 5681, page 7, we must use 1 regardless of the value of the
|
// RFC 5681, page 7, we must use 1 regardless of the value of the
|
||||||
// initial congestion window.
|
// initial congestion window.
|
||||||
// 更新拥塞窗口为1,这样就会重新进入慢启动
|
// 更新拥塞窗口为1,这样就会重新进入慢启动
|
||||||
|
log.Fatal("重新进入慢启动")
|
||||||
r.s.sndCwnd = 1
|
r.s.sndCwnd = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// minRTO is the minimum allowed value for the retransmit timeout.
|
// minRTO is the minimum allowed value for the retransmit timeout.
|
||||||
minRTO = 2000 * time.Millisecond
|
minRTO = 200 * time.Millisecond
|
||||||
|
|
||||||
// InitialCwnd is the initial congestion window.
|
// InitialCwnd is the initial congestion window.
|
||||||
// 初始拥塞窗口大小
|
// 初始拥塞窗口大小
|
||||||
@@ -459,7 +459,6 @@ func (s *sender) handleRcvdSegment(seg *segment) {
|
|||||||
s.cc.Update(originalOutstanding - s.outstanding)
|
s.cc.Update(originalOutstanding - s.outstanding)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 如果发生超时重传时,s.outstanding可能会降到零以下,
|
// 如果发生超时重传时,s.outstanding可能会降到零以下,
|
||||||
// 重置为零但后来得到一个覆盖先前发送数据的确认。
|
// 重置为零但后来得到一个覆盖先前发送数据的确认。
|
||||||
if s.outstanding < 0 {
|
if s.outstanding < 0 {
|
||||||
@@ -496,8 +495,23 @@ func (s *sender) retransmitTimerExpired() bool {
|
|||||||
// 每次超时,rto都变成原来的2倍
|
// 每次超时,rto都变成原来的2倍
|
||||||
s.rto *= 2
|
s.rto *= 2
|
||||||
|
|
||||||
// TODO 拥塞控制
|
// tcp的拥塞控制:如果已经是快速恢复阶段,那么退出,因为现在丢包了
|
||||||
// FIXME 添加拥塞控制逻辑
|
if s.fr.active {
|
||||||
|
// We were attempting fast recovery but were not successful.
|
||||||
|
// Leave the state. We don't need to update ssthresh because it
|
||||||
|
// has already been updated when entered fast-recovery.
|
||||||
|
// 我们试图快速恢复,但没有成功,退出这个状态。
|
||||||
|
// 我们不需要更新ssthresh,因为它在进入快速恢复时已经更新。
|
||||||
|
s.leaveFastRecovery()
|
||||||
|
}
|
||||||
|
|
||||||
|
// See: https://tools.ietf.org/html/rfc6582#section-3.2 Step 4.
|
||||||
|
// We store the highest sequence number transmitted in cases where
|
||||||
|
// we were not in fast recovery.
|
||||||
|
s.fr.last = s.sndNxt - 1
|
||||||
|
|
||||||
|
// tcp的拥塞控制:处理丢包的情况
|
||||||
|
s.cc.HandleRTOExpired()
|
||||||
|
|
||||||
// tcp可靠性:将下一个段标记为第一个未确认的段,然后再次开始发送。将未完成的数据包数设置为0,以便我们能够重新传输。
|
// tcp可靠性:将下一个段标记为第一个未确认的段,然后再次开始发送。将未完成的数据包数设置为0,以便我们能够重新传输。
|
||||||
// 当我们收到我们传输的数据时,我们将继续传输(或重新传输)。
|
// 当我们收到我们传输的数据时,我们将继续传输(或重新传输)。
|
||||||
@@ -505,7 +519,6 @@ func (s *sender) retransmitTimerExpired() bool {
|
|||||||
s.writeNext = s.writeList.Front()
|
s.writeNext = s.writeList.Front()
|
||||||
// 重新发送数据包
|
// 重新发送数据包
|
||||||
logger.NOTICE("暂时关闭超时重发", s.rto.String())
|
logger.NOTICE("暂时关闭超时重发", s.rto.String())
|
||||||
panic(nil)
|
|
||||||
s.sendData()
|
s.sendData()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -598,7 +611,6 @@ func (s *sender) sendData() {
|
|||||||
if !s.resendTimer.enabled() && s.sndUna != s.sndNxt {
|
if !s.resendTimer.enabled() && s.sndUna != s.sndNxt {
|
||||||
// NOTE 开启计时器 如果在RTO后没有回信(snd.handleRecvdSegment 中有数据可以处理) 那么将会重发
|
// NOTE 开启计时器 如果在RTO后没有回信(snd.handleRecvdSegment 中有数据可以处理) 那么将会重发
|
||||||
// 在 s.resendTimer.init() 中 将会调用 Assert() 唤醒重发函数 retransmitTimerExpired()
|
// 在 s.resendTimer.init() 中 将会调用 Assert() 唤醒重发函数 retransmitTimerExpired()
|
||||||
logger.NOTICE("snd.go 602 ", s.rto.String())
|
|
||||||
s.resendTimer.enable(s.rto)
|
s.resendTimer.enable(s.rto)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user