Finally, integrated LEDBAT
authorVictor Grishchenko <victor.grishchenko@gmail.com>
Thu, 17 Dec 2009 16:07:45 +0000 (17:07 +0100)
committerVictor Grishchenko <victor.grishchenko@gmail.com>
Thu, 17 Dec 2009 16:07:45 +0000 (17:07 +0100)
Now, LEDBAT works in AIMD mode. Much nicer thing for long-fat networks.
CUBIC is still TODO.

BUGS
exec/trial.cpp
p2tp.h
send_control.cpp
sendrecv.cpp

diff --git a/BUGS b/BUGS
index 28b97ba..d17adfb 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -49,3 +49,8 @@
     * empty datagram hammering (see at linode)
     * make a testkit!!!
     * never back from keepalive syndrome (because of underhashing)
+    * HTTP daemon, combined select() loop
+    * range requests, priorities
+    * LEDBAT
+    * CUBIC
+    v misterious mass packet losses (!data)
index 9d0b75c..10d7728 100644 (file)
@@ -44,7 +44,7 @@ int main (int argn, char** args) {
        p2tp::SetTracker(tracker);
        int file = p2tp::Open(filename,root_hash);
     printf("Downloading %s\n",root_hash.hex().c_str());
-    int count = 200;
+    int count = 400;
     while (!p2tp::IsComplete(file) && count-->0) {
            p2tp::Loop(TINT_SEC/10);
         if (count==100) 
diff --git a/p2tp.h b/p2tp.h
index 3d7f88c..8882aca 100644 (file)
--- a/p2tp.h
+++ b/p2tp.h
@@ -252,7 +252,7 @@ namespace p2tp {
         void        AddPeakHashes (Datagram& dgram);
         void        AddPex (Datagram& dgram);
 
-        void        BackOffOnLosses ();
+        void        BackOffOnLosses (float ratio=0.5);
         tint        SwitchSendControl (int control_mode);
         tint        NextSendTime ();
         tint        KeepAliveNextSendTime ();
index d6d553b..a14d65f 100644 (file)
@@ -39,10 +39,12 @@ tint    Channel::SwitchSendControl (int control_mode) {
         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:
@@ -103,11 +105,11 @@ tint    Channel::CwndRateNextSendTime () {
     }
 }
 
-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_);
     }
@@ -116,10 +118,10 @@ void    Channel::BackOffOnLosses () {
 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();
@@ -147,11 +149,13 @@ tint Channel::LedbatNextSendTime () {
             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();
 }
 
index 6e31e4a..434d848 100644 (file)
@@ -33,8 +33,8 @@ void    Channel::AddPeakHashes (Datagram& dgram) {
 
 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);
@@ -125,12 +125,12 @@ void    Channel::Send () {
         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
@@ -185,8 +185,11 @@ bin64_t        Channel::AddData (Datagram& dgram) {
     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);
     
@@ -357,6 +360,18 @@ void    Channel::CleanDataOut (bin64_t ackd_pos) { // TODO: isn't it too long?
                 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_++;