Harp 拥塞控制
在input函数中
//1:收到了能让 snd_una 移动的 ACK,或者其他包中的head->una 能让snd_una 移动
if (_itimediff(this->snd_una, prev_una) > 0) {
//2:cwnd 无论怎么调整,也不能超过远端窗口rmt_wnd
if (this->cwnd < this->rmt_wnd) {
fr_uint32_t mss = this->mss;
if (this->cwnd < this->ssthresh) {
/*
* a:慢启动阶段:cwnd 小于 ssthresh, this->cwnd 自增1 指数增长
*/
this->cwnd++;
this->incr += mss;
}else {
/*
* b:拥塞避免阶段:this->cwnd 自增零点几
*/
// this->cwnd = cwnd + 1/cwnd + 1/16
if (this->incr < mss) {
this->incr = mss;
}
this->incr += (mss * mss) / this->incr + (mss / 16);
if ((this->cwnd + 1) * mss <= this->incr) {
//当 incr 累计增加的值超过一个 mss 时, cwnd 增加 1
#if 1
this->cwnd = (this->incr + mss - 1) / ((mss > 0)? mss : 1);
#else
this->cwnd++;
#endif
}
}
if (this->cwnd > this->rmt_wnd) {
// 保持 cwnd 不超过 rmt_wnd
this->cwnd = this->rmt_wnd;
this->incr = this->rmt_wnd * mss;
}
}
}
flush函数
resent = (this->fastresend > 0)? (fr_uint32_t)this->fastresend : 0xffffffff;
if (change) {
/*
* 快速重传,会直接进入b阶段
*/
// inflight=发送窗口中报文的数量, 这个值小于等于 cwnd 把 inflight设置为inflight的一半
// 但 this->cwnd 置为比 this->ssthresh 稍高的值就进入快速恢复阶段,
// cwnd 会以与拥塞避免相同的方式,线性增长
fr_uint32_t inflight = this->snd_nxt - this->snd_una;
this->ssthresh = inflight / 2;
if (this->ssthresh < FR_HARP_THRESH_MIN)
this->ssthresh = FR_HARP_THRESH_MIN;
this->cwnd = this->ssthresh + resent;
this->incr = this->cwnd * this->mss; //incr 为 cwnd 的 mss 倍
this->cwd_status = FR_HARP_STATUS_CONGESTION_FAST_RECOVERY;
}
if (lost) {
/*
* 超时重传,进入a阶段
*/
// 修改慢启动阈值this->ssthresh 为窗口的一半 然后 this->cwnd =1 进入慢启动
this->ssthresh = this->cwd_min / 2;
if (this->ssthresh < FR_HARP_THRESH_MIN)
this->ssthresh = FR_HARP_THRESH_MIN;
this->cwnd = 1; // cwnd 置为 1, 进入慢启动
this->incr = this->mss;
this->cwd_status = FR_HARP_STATUS_SLOW_START_E;
}
if (this->cwnd < 1) {
this->cwnd = 1;
this->incr = this->mss;
}
策略为:只要发送丢包就进入慢启动阶段-》大于阈值时候-》进入拥塞避免阶段
只要发生快速重传-》就进入拥塞避免阶段,这个时候,更贴切的说法是快速恢复阶段