case KEEP_ALIVE_CONTROL:
send_interval_ = max(TINT_SEC/10,rtt_avg_);
dev_avg_ = max(TINT_SEC,rtt_avg_);
+ data_out_cap_ = bin64_t::ALL;
cwnd_ = 1;
break;
case PING_PONG_CONTROL:
dev_avg_ = max(TINT_SEC,rtt_avg_);
+ data_out_cap_ = bin64_t::ALL;
cwnd_ = 1;
break;
case SLOW_START_CONTROL:
}
}
-void Channel::BackOffOnLosses () {
+void Channel::BackOffOnLosses (float ratio) {
ack_rcvd_recent_ = 0;
ack_not_rcvd_recent_ = 0;
if (last_loss_time_<NOW-rtt_avg_) {
- cwnd_ /= 2;
+ cwnd_ *= ratio;
last_loss_time_ = NOW;
dprintf("%s #%u sendctrl backoff %3.2f\n",tintstr(),id,cwnd_);
}
tint Channel::SlowStartNextSendTime () {
if (ack_not_rcvd_recent_) {
BackOffOnLosses();
- return SwitchSendControl(AIMD_CONTROL);
+ return SwitchSendControl(LEDBAT_CONTROL);//AIMD_CONTROL);
}
if (rtt_avg_/cwnd_<TINT_SEC/10)
- return SwitchSendControl(AIMD_CONTROL);
+ return SwitchSendControl(LEDBAT_CONTROL);//AIMD_CONTROL);
cwnd_+=ack_rcvd_recent_;
ack_rcvd_recent_=0;
return CwndRateNextSendTime();
owd_cur = owd_current_[i];
}
if (ack_not_rcvd_recent_)
- BackOffOnLosses();
+ BackOffOnLosses(0.8);
ack_rcvd_recent_ = 0;
tint queueing_delay = owd_cur - owd_min;
tint off_target = LEDBAT_TARGET - queueing_delay;
cwnd_ += LEDBAT_GAIN * off_target / cwnd_;
+ dprintf("%s #%u sendctrl ledbat %lli-%lli => %3.2f\n",
+ tintstr(),id,owd_cur,owd_min,cwnd_);
return CwndRateNextSendTime();
}
void Channel::AddUncleHashes (Datagram& dgram, bin64_t pos) {
bin64_t peak = file().peak_for(pos);
- while (pos!=peak && /*((NOW&3)==3 || !data_out_cap_.within(pos.parent())) &&*/
- ack_in_.get(pos.parent())==bins::EMPTY) {
+ while (pos!=peak && ((NOW&3)==3 || !data_out_cap_.within(pos.parent())) &&
+ ack_in_.get(pos.parent())==bins::EMPTY ) {
bin64_t uncle = pos.sibling();
dgram.Push8(P2TP_HASH);
dgram.Push32((uint32_t)uncle);
data = bin64_t::ALL;
//dprintf("%s #%u considering keepalive %i %f %s\n",
// tintstr(),id,(int)data_out_.size(),cwnd_,SEND_CONTROL_MODES[send_control_]);
- if (data_out_.size()<cwnd_ && send_control_!=KEEP_ALIVE_CONTROL) {
- if ( cwnd_ < 1 )
- SwitchSendControl(KEEP_ALIVE_CONTROL);
- else
- cwnd_ = cwnd_/2.0;
- }
+ //if (data_out_.size()<cwnd_ && send_control_!=KEEP_ALIVE_CONTROL) {
+ //if ( cwnd_ < 1 )
+ // SwitchSendControl(KEEP_ALIVE_CONTROL);
+ //else
+ // cwnd_ = cwnd_/2.0;
+ //}
//if (data_out_.empty() && send_control_!=KEEP_ALIVE_CONTROL)
// SwitchSendControl(KEEP_ALIVE_CONTROL);// we did our best
//if (NOW<last_send_time_+MAX_SEND_INTERVAL) // no need for keepalive
bin64_t tosend = bin64_t::NONE;
if (data_out_.size()<cwnd_ && last_data_out_time_<=NOW-send_interval_) {
tosend = DequeueHint();
- if (tosend==bin64_t::NONE)
- dprintf("%s #%u out of hints #sendctrl\n",tintstr(),id);
+ if (tosend==bin64_t::NONE) {
+ dprintf("%s #%u no idea what to send #sendctrl\n",tintstr(),id);
+ if (send_control_!=KEEP_ALIVE_CONTROL)
+ SwitchSendControl(KEEP_ALIVE_CONTROL);
+ }
} else
dprintf("%s #%u no cwnd #sendctrl\n",tintstr(),id);
tint rtt = NOW-data_out_[i].time;
rtt_avg_ = (rtt_avg_*7 + rtt) >> 3;
dev_avg_ = ( dev_avg_*3 + abs(rtt-rtt_avg_) ) >> 2;
+ if (peer_send_time_) {
+ tint owd = peer_send_time_ - data_out_[i].time;
+ owd_cur_bin_ = (owd_cur_bin_+1) & 3;
+ owd_current_[owd_cur_bin_] = owd;
+ if (owd_min_bin_start_<NOW+TINT_SEC*30) {
+ owd_min_bin_start_ = NOW;
+ owd_min_bin_ = (owd_min_bin_+1) & 3;
+ owd_min_bins_[owd_min_bin_] = TINT_NEVER;
+ }
+ if (owd_min_bins_[owd_min_bin_]>owd)
+ owd_min_bins_[owd_min_bin_] = owd;
+ }
dprintf("%s #%u rtt %lli dev %lli\n",tintstr(),id,rtt_avg_,dev_avg_);
bin64_t pos = data_out_[i].bin;
ack_rcvd_recent_++;