Add files for swift over UDP.
[swifty.git] / src / libswift_udp / tests / congctrltest.cpp
diff --git a/src/libswift_udp/tests/congctrltest.cpp b/src/libswift_udp/tests/congctrltest.cpp
new file mode 100644 (file)
index 0000000..1bae950
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  congctrltest.cpp
+ *  p2tp
+ *
+ *  Created by Victor Grishchenko on 7/13/09.
+ *  Copyright 2009-2012 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved.
+ *
+ */
+#include <stdint.h>
+#include <queue>
+#include <gtest/gtest.h>
+#include <glog/logging.h>
+#include "p2tp.h"
+
+using namespace std;
+using namespace p2tp;
+
+class SimPeer;
+
+struct SimPacket {
+    SimPacket(int from, int to, const SimPacket* toack, bool data) ;
+    int peerfrom, peerto;
+    tint datatime;
+    tint acktime;
+    tint arrivaltime;
+};
+
+tint now = 0;
+
+/** very simplified; uplink is the bottleneck */
+class SimPeer {
+public:
+    SimPeer (tint tt, tint lt, int qlen) : travtime(tt), latency(lt), queue_length(qlen) {}
+    int queue_length;
+    int travtime;
+    tint freetime;
+    tint latency;
+    int unackd;
+    int rcvd, sent;
+    queue<SimPacket> packet_queue;
+    queue<SimPacket> dropped_queue;
+    CongestionControl congc;
+    
+    void send(SimPacket pck) {
+        if (packet_queue.size()==queue_length) {
+            dropped_queue.push(pck);
+            return;
+        }
+        tint start = max(now,freetime);
+        tint done = pck.datatime ? start+travtime : start;
+        freetime = done;
+        pck.arrivaltime = done + latency;
+        packet_queue.push(pck);
+    }
+    
+    SimPacket recv () {
+        assert(!packet_queue.empty());
+        SimPacket ret = packet_queue.front();
+        packet_queue.pop();
+        return ret;
+    }
+    
+    tint next_recv_time () const {
+        return packet_queue.empty() ? NEVER : packet_queue.front().arrivaltime;
+    }
+    
+    void    turn () {
+        SimPacket rp = recv();
+        SimPacket reply;
+        now = rp.arrivaltime;
+        if (rp.acktime) {
+            congc.RttSample(rp.arrivaltime-rp.acktime);
+            congc.OnCongestionEvent(CongestionControl::ACK_EV);
+            unackd--;
+            rcvd++;
+        }
+        if (rp.datatime) {
+            congc.OnCongestionEvent(CongestionControl::DATA_EV);
+            reply.acktime = reply.datatime;
+        }
+        if (!dropped_queue.empty() && dropped_queue.top().datatime<now+THR)
+            congc.OnCongestionEvent(CongestionControl::LOSS_EV);
+        if (congc.cwnd()>unackd) {
+            unackd++;
+            reply.datatime = now;
+            sent++;
+        }
+        rp.from->send(reply);
+    }
+};
+
+TEST(P2TP, TailDropTest) {
+    // two peers exchange packets over 100ms link with tail-drop discipline
+    // bw 1Mbits => travel time of 1KB is ~10ms
+    SimPeer a(10*MSEC,100*MSEC,20), b(10*MSEC,100*MSEC,20);
+    a.send(SimPacket(&b,now,0,0));
+    while (now<60*60*SEC) 
+        if (a.next_recv_time()<b.next_recv_time())
+            a.turn();
+        else
+            b.turn();
+}
+
+int main (int argc, char** argv) {
+       bin::init();
+       bins::init();
+       google::InitGoogleLogging(argv[0]);
+       testing::InitGoogleTest(&argc, argv);
+       return RUN_ALL_TESTS();
+       
+}