5 * Created by Victor Grishchenko on 12/10/09.
6 * Copyright 2009 Delft University of Technology. All rights reserved.
15 tint Channel::MIN_DEV = 50*TINT_MSEC;
16 tint Channel::MAX_SEND_INTERVAL = TINT_SEC*58;
17 tint Channel::LEDBAT_TARGET = TINT_MSEC*25;
18 float Channel::LEDBAT_GAIN = 1.0/LEDBAT_TARGET;
19 tint Channel::LEDBAT_DELAY_BIN = TINT_SEC*30;
20 const char* Channel::SEND_CONTROL_MODES[] = {"keepalive", "pingpong",
21 "slowstart", "standard_aimd", "ledbat"};
24 tint Channel::NextSendTime () {
25 switch (send_control_) {
26 case KEEP_ALIVE_CONTROL: return KeepAliveNextSendTime();
27 case PING_PONG_CONTROL: return PingPongNextSendTime();
28 case SLOW_START_CONTROL: return SlowStartNextSendTime();
29 case AIMD_CONTROL: return AimdNextSendTime();
30 case LEDBAT_CONTROL: return LedbatNextSendTime();
31 default: assert(false);
35 tint Channel::SwitchSendControl (int control_mode) {
36 dprintf("%s #%u sendctrl switch %s->%s\n",tintstr(),id,
37 SEND_CONTROL_MODES[send_control_],SEND_CONTROL_MODES[control_mode]);
38 switch (control_mode) {
39 case KEEP_ALIVE_CONTROL:
40 send_interval_ = max(TINT_SEC/10,rtt_avg_);
41 dev_avg_ = max(TINT_SEC,rtt_avg_);
44 case PING_PONG_CONTROL:
45 dev_avg_ = max(TINT_SEC,rtt_avg_);
48 case SLOW_START_CONTROL:
58 send_control_ = control_mode;
59 return NextSendTime();
62 tint Channel::KeepAliveNextSendTime () {
63 if (sent_since_recv_>=3 && last_recv_time_<NOW-TINT_MIN)
66 return SwitchSendControl(SLOW_START_CONTROL);
67 if (data_in_.time!=TINT_NEVER)
70 if (send_interval_>MAX_SEND_INTERVAL)
71 send_interval_ = MAX_SEND_INTERVAL;
72 return last_send_time_ + send_interval_;
75 tint Channel::PingPongNextSendTime () { // FIXME INFINITE LOOP
77 return SwitchSendControl(KEEP_ALIVE_CONTROL);
79 return SwitchSendControl(SLOW_START_CONTROL);
80 if (data_in_.time!=TINT_NEVER)
82 if (last_recv_time_>last_send_time_)
86 return last_send_time_ + ack_timeout(); // timeout
89 tint Channel::CwndRateNextSendTime () {
90 if (data_in_.time!=TINT_NEVER)
91 return NOW; // TODO: delayed ACKs
92 //if (last_recv_time_<NOW-rtt_avg_*4)
93 // return SwitchSendControl(KEEP_ALIVE_CONTROL);
94 send_interval_ = rtt_avg_/cwnd_;
95 if (send_interval_>std::max(rtt_avg_,TINT_SEC)*4)
96 return SwitchSendControl(KEEP_ALIVE_CONTROL);
97 if (data_out_.size()<cwnd_) {
98 dprintf("%s #%u sendctrl next in %llius\n",tintstr(),id,send_interval_);
99 return last_data_out_time_ + send_interval_;
101 assert(data_out_.front().time!=TINT_NEVER);
102 return data_out_.front().time + ack_timeout();
106 void Channel::BackOffOnLosses () {
107 ack_rcvd_recent_ = 0;
108 ack_not_rcvd_recent_ = 0;
109 if (last_loss_time_<NOW-rtt_avg_) {
111 last_loss_time_ = NOW;
112 dprintf("%s #%u sendctrl backoff %3.2f\n",tintstr(),id,cwnd_);
116 tint Channel::SlowStartNextSendTime () {
117 if (ack_not_rcvd_recent_) {
119 return SwitchSendControl(AIMD_CONTROL);
121 if (rtt_avg_/cwnd_<TINT_SEC/10)
122 return SwitchSendControl(AIMD_CONTROL);
123 cwnd_+=ack_rcvd_recent_;
125 return CwndRateNextSendTime();
128 tint Channel::AimdNextSendTime () {
129 if (ack_not_rcvd_recent_)
132 cwnd_ += ack_rcvd_recent_/cwnd_;
136 return CwndRateNextSendTime();
139 tint Channel::LedbatNextSendTime () {
140 tint owd_cur(TINT_NEVER), owd_min(TINT_NEVER);
141 for(int i=0; i<4; i++) {
142 if (owd_min>owd_min_bins_[i])
143 owd_min = owd_min_bins_[i];
144 if (owd_cur>owd_current_[i])
145 owd_cur = owd_current_[i];
147 if (ack_not_rcvd_recent_)
149 ack_rcvd_recent_ = 0;
150 tint queueing_delay = owd_cur - owd_min;
151 tint off_target = LEDBAT_TARGET - queueing_delay;
152 cwnd_ += LEDBAT_GAIN * off_target / cwnd_;
153 return CwndRateNextSendTime();