getting cong control back to sanity
authorVictor Grishchenko <victor.grishchenko@gmail.com>
Sun, 13 Dec 2009 11:59:50 +0000 (12:59 +0100)
committerVictor Grishchenko <victor.grishchenko@gmail.com>
Sun, 13 Dec 2009 11:59:50 +0000 (12:59 +0100)
BUGS
hashtree.cpp
p2tp.h
send_control.cpp
sendrecv.cpp

diff --git a/BUGS b/BUGS
index 373b47e..12d3b41 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -42,3 +42,4 @@
     v whether sending is limited by cwnd or app
     * actually: whether packets are ACKed faster than sent
     * uproot DATA NONE: complicates and deceives
+    * r735 goes to github
index 7f19502..0a4626f 100644 (file)
@@ -315,8 +315,11 @@ bool            HashTree::OfferData (bin64_t pos, const char* data, size_t lengt
     if (peak==bin64_t::NONE)
         return false;
 
-    if (!OfferHash(pos, Sha1Hash(data,length)))
+    Sha1Hash data_hash(data,length);
+    if (!OfferHash(pos, data_hash)) {
+        printf("invalid hash for %s: %s\n",pos.str(),data_hash.hex().c_str());
         return false;
+    }
 
     //printf("g %lli %s\n",(uint64_t)pos,hash.hex().c_str());
     ack_out_.set(pos,bins::FILLED);
diff --git a/p2tp.h b/p2tp.h
index b2ac571..95354aa 100644 (file)
--- a/p2tp.h
+++ b/p2tp.h
@@ -226,6 +226,8 @@ namespace p2tp {
             AIMD_CONTROL,
             LEDBAT_CONTROL
         } send_control_t;
+        
+        static const char* SEND_CONTROL_MODES[];
 
         static Channel*
                     RecvDatagram (int socket);
@@ -288,9 +290,9 @@ namespace p2tp {
         /** Channel id: index in the channel array. */
         uint32_t    id;
         /**    Socket address of the peer. */
-        Address    peer_;
+        Address     peer_;
         /**    The UDP socket fd. */
-        int            socket_;
+        int         socket_;
         /**    Descriptor of the file in question. */
         FileTransfer*    transfer_;
         /**    Peer channel id; zero if we are trying to open a channel. */
@@ -299,7 +301,7 @@ namespace p2tp {
         /**    Peer's progress, based on acknowledgements. */
         bins        ack_in_;
         /**    Last data received; needs to be acked immediately. */
-        tintbin        data_in_;
+        tintbin     data_in_;
         bin64_t     data_in_dbl_;
         /** The history of data sent and still unacknowledged. */
         tbqueue     data_out_;
index ff46b4d..a49909f 100644 (file)
@@ -17,6 +17,8 @@ tint Channel::MAX_SEND_INTERVAL = TINT_SEC*58;
 tint Channel::LEDBAT_TARGET = TINT_MSEC*25;
 float Channel::LEDBAT_GAIN = 1.0/LEDBAT_TARGET;
 tint Channel::LEDBAT_DELAY_BIN = TINT_SEC*30;
+const char* Channel::SEND_CONTROL_MODES[] = {"keepalive", "pingpong",
+    "slowstart", "standard_aimd", "ledbat"};
 
 
 tint    Channel::NextSendTime () {
@@ -62,13 +64,15 @@ tint    Channel::KeepAliveNextSendTime () {
         return TINT_NEVER;
     if (ack_rcvd_recent_)
         return SwitchSendControl(SLOW_START_CONTROL);
+    if (data_in_.bin!=bin64_t::NONE)
+        return NOW;
     send_interval_ <<= 1;
     if (send_interval_>MAX_SEND_INTERVAL)
         send_interval_ = MAX_SEND_INTERVAL;
     return last_send_time_ + send_interval_;
 }
 
-tint    Channel::PingPongNextSendTime () {
+tint    Channel::PingPongNextSendTime () { // FIXME INFINITE LOOP
     if (last_recv_time_ < last_send_time_-TINT_SEC*3) {
         // FIXME keepalive <-> pingpong (peers, transition)
     } // last_data_out_time_ < last_send_time_ - TINT_SEC...
@@ -76,6 +80,8 @@ tint    Channel::PingPongNextSendTime () {
         return SwitchSendControl(KEEP_ALIVE_CONTROL);
     if (ack_rcvd_recent_)
         return SwitchSendControl(SLOW_START_CONTROL);
+    if (data_in_.bin!=bin64_t::NONE)
+        return NOW;
     if (last_recv_time_>last_send_time_)
         return NOW;
     else if (last_send_time_)
@@ -85,6 +91,8 @@ tint    Channel::PingPongNextSendTime () {
 }
 
 tint    Channel::CwndRateNextSendTime () {
+    if (data_in_.bin!=bin64_t::NONE)
+        return NOW; // TODO: delayed ACKs
     send_interval_ = rtt_avg_/cwnd_;
     if (data_out_.size()<cwnd_) {
         return last_data_out_time_ + send_interval_;
@@ -108,6 +116,8 @@ tint    Channel::SlowStartNextSendTime () {
         BackOffOnLosses();
         return SwitchSendControl(AIMD_CONTROL);
     } 
+    if (rtt_avg_/cwnd_<TINT_SEC/10) 
+        return SwitchSendControl(AIMD_CONTROL);
     cwnd_+=ack_rcvd_recent_;
     ack_rcvd_recent_=0;
     return CwndRateNextSendTime();
index 374512b..7e1cec2 100644 (file)
@@ -97,7 +97,7 @@ void    Channel::AddHandshake (Datagram& dgram) {
     dgram.Push8(P2TP_HANDSHAKE);
     int encoded = EncodeID(id);
     dgram.Push32(encoded);
-    dprintf("%s #%u +hs %i\n",tintstr(),id,encoded);
+    dprintf("%s #%u +hs %x\n",tintstr(),id,encoded);
     ack_out_.clear();
     AddAck(dgram);
 }
@@ -119,14 +119,18 @@ void    Channel::Send () {
         AddHandshake(dgram);
         AddAck(dgram);
     }
-    dprintf("%s #%u sent %ib %s:%u\n",
+    dprintf("%s #%u sent %ib %s:%x\n",
             tintstr(),id,dgram.size(),peer().str(),peer_channel_id_);
     if (dgram.size()==4) {// only the channel id; bare keep-alive
         data = bin64_t::ALL;
-        if (send_control_!=KEEP_ALIVE_CONTROL) // we did our best
-            SwitchSendControl(KEEP_ALIVE_CONTROL);
-        if (NOW<last_send_time_+MAX_SEND_INTERVAL) // no need for keepalive
-            return; // don't send empty dgram
+        if (send_control_!=KEEP_ALIVE_CONTROL) {
+            if ( (cwnd_/=2) < 1 )
+                SwitchSendControl(KEEP_ALIVE_CONTROL);
+        }
+        //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
+        //    return; // don't send empty dgram
     }
     if (dgram.Send()==-1)
         print_error("can't send datagram");
@@ -402,7 +406,7 @@ void    Channel::OnAck (Datagram& dgram) {
     }
     dprintf("%s #%u -ack %s\n",tintstr(),id,ackd_pos.str());
     ack_in_.set(ackd_pos);
-    CleanDataOut(ackd_pos);
+    CleanDataOut(ackd_pos); // FIXME do AFTER all ACKs
 }
 
 
@@ -423,7 +427,7 @@ void    Channel::OnHint (Datagram& dgram) {
 
 void Channel::OnHandshake (Datagram& dgram) {
     peer_channel_id_ = dgram.Pull32();
-    dprintf("%s #%u -hs %i\n",tintstr(),id,peer_channel_id_);
+    dprintf("%s #%u -hs %x\n",tintstr(),id,peer_channel_id_);
     // FUTURE: channel forking
 }
 
@@ -504,15 +508,15 @@ void    Channel::Loop (tint howlong) {
         tint send_time(TINT_NEVER);
         Channel* sender(NULL);
         while (!sender && !send_queue.is_empty()) { // dequeue
-            send_time = send_queue.peek().time;
-            sender = channel((int)send_queue.peek().bin);
-            send_queue.pop();
+            tintbin next = send_queue.pop();
+            send_time = next.time;
+            sender = channel((int)next.bin);
             if (sender && sender->next_send_time_!=send_time &&
                      sender->next_send_time_!=TINT_NEVER )
                 sender = NULL; // it was a stale entry
         }
         
-        if ( sender && send_time <= NOW ) { // it's time
+        if ( sender!=NULL && send_time<=NOW ) { // it's time
             
             if (sender->next_send_time_<NOW+TINT_MIN) {  // either send
                 dprintf("%s #%u sch_send %s\n",tintstr(),sender->id,
@@ -539,7 +543,7 @@ void    Channel::Loop (tint howlong) {
             
         }
         
-    } while (Datagram::Time()<limit);
+    } while (NOW<limit);
             
 }