# Harp 拥塞控制 在input函数中 ```c //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函数 ```c 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; } ``` 策略为:只要发送丢包就进入慢启动阶段-》大于阈值时候-》进入拥塞避免阶段 只要发生快速重传-》就进入拥塞避免阶段,这个时候,更贴切的说法是快速恢复阶段