more debug, better ss->ca condition
[swift-upb.git] / send_control.cpp
1 /*
2  *  send_control.cpp
3  *  p2tp
4  *
5  *  Created by Victor Grishchenko on 12/10/09.
6  *  Copyright 2009 Delft University of Technology. All rights reserved.
7  *
8  */
9
10 #include "p2tp.h"
11
12 using namespace p2tp;
13 using namespace std;
14
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
21
22 tint    Channel::NextSendTime () {
23     switch (send_control_) {
24         case KEEP_ALIVE_CONTROL: return KeepAliveNextSendTime();
25         case PING_PONG_CONTROL:  return PingPongNextSendTime();
26         case SLOW_START_CONTROL: return SlowStartNextSendTime();
27         case AIMD_CONTROL:       return AimdNextSendTime();
28         case LEDBAT_CONTROL:     return LedbatNextSendTime();
29         default:                 assert(false);
30     }
31 }
32
33 tint    Channel::SwitchSendControl (int control_mode) {
34     dprintf("%s #%u sendctrl %i->%i\n",tintstr(),id,send_control_,control_mode);
35     switch (control_mode) {
36         case KEEP_ALIVE_CONTROL:
37             send_interval_ = max(TINT_SEC/10,rtt_avg_);
38             dev_avg_ = max(TINT_SEC,rtt_avg_);
39             cwnd_ = 1;
40             break;
41         case PING_PONG_CONTROL:
42             dev_avg_ = max(TINT_SEC,rtt_avg_);
43             cwnd_ = 1;
44             break;
45         case SLOW_START_CONTROL:
46             break;
47         case AIMD_CONTROL:
48             break;
49         case LEDBAT_CONTROL:
50             break;
51         default: 
52             assert(false);
53     }
54     send_control_ = control_mode;
55     return NextSendTime();
56 }
57
58 // TODO: transitions, consistently
59 // TODO: may send data
60 tint    Channel::KeepAliveNextSendTime () {
61     if (sent_since_recv_>=3 && last_recv_time_<NOW-TINT_MIN)
62         return TINT_NEVER;
63     if (ack_rcvd_recent_)
64         return SwitchSendControl(SLOW_START_CONTROL);
65     send_interval_ <<= 1;
66     if (send_interval_>MAX_SEND_INTERVAL)
67         send_interval_ = MAX_SEND_INTERVAL;
68     return last_send_time_ + send_interval_;
69 }
70
71 tint    Channel::PingPongNextSendTime () {
72     if (last_recv_time_ < last_send_time_-TINT_SEC*3) {
73         // FIXME keepalive <-> pingpong (peers, transition)
74     } // last_data_out_time_ < last_send_time_ - TINT_SEC...
75     if (false)
76         return SwitchSendControl(KEEP_ALIVE_CONTROL);
77     if (ack_rcvd_recent_)
78         return SwitchSendControl(SLOW_START_CONTROL);
79     if (last_recv_time_>last_send_time_)
80         return NOW;
81     else if (last_send_time_)
82         return last_send_time_ + ack_timeout();
83     else
84         return NOW;
85 }
86
87 tint    Channel::CwndRateNextSendTime () {
88     send_interval_ = rtt_avg_/cwnd_;
89     if (data_out_.size()<cwnd_) {
90         dprintf("%s #%u sendctrl next in %llius\n",tintstr(),id,send_interval_);
91         return last_data_out_time_ + send_interval_;
92     } else {
93         tint next_timeout = data_out_.front().time + ack_timeout();
94         return last_data_out_time_ + next_timeout;
95     }
96 }
97
98 void    Channel::BackOffOnLosses () {
99     ack_rcvd_recent_ = 0;
100     ack_not_rcvd_recent_ =  0;
101     if (last_loss_time_<NOW-rtt_avg_) {
102         cwnd_ /= 2;
103         last_loss_time_ = NOW;
104         dprintf("%s #%u sendctrl backoff %3.2f\n",tintstr(),id,cwnd_);
105     }
106 }
107
108 tint    Channel::SlowStartNextSendTime () {
109     if (ack_not_rcvd_recent_) {
110         BackOffOnLosses();
111         return SwitchSendControl(AIMD_CONTROL);
112     } 
113     if (send_interval_<TINT_SEC/10)
114         return SwitchSendControl(AIMD_CONTROL);
115     cwnd_+=ack_rcvd_recent_;
116     ack_rcvd_recent_=0;
117     return CwndRateNextSendTime();
118 }
119
120 tint    Channel::AimdNextSendTime () {
121     if (ack_not_rcvd_recent_)
122         BackOffOnLosses();
123     cwnd_ += ack_rcvd_recent_/cwnd_;
124     ack_rcvd_recent_=0;
125     return CwndRateNextSendTime();
126 }
127
128 tint Channel::LedbatNextSendTime () {
129     tint owd_cur(TINT_NEVER), owd_min(TINT_NEVER);
130     for(int i=0; i<4; i++) {
131         if (owd_min>owd_min_bins_[i])
132             owd_min = owd_min_bins_[i];
133         if (owd_cur>owd_current_[i])
134             owd_cur = owd_current_[i];
135     }
136     if (ack_not_rcvd_recent_)
137         BackOffOnLosses();
138     ack_rcvd_recent_ = 0;
139     tint queueing_delay = owd_cur - owd_min;
140     tint off_target = LEDBAT_TARGET - queueing_delay;
141     cwnd_ += LEDBAT_GAIN * off_target / cwnd_;
142     return CwndRateNextSendTime();
143 }
144
145
146