4 #include "compat/stdint.h"
7 #include <sys/socket.h>
8 #include <netinet/in.h>
15 #include <gtest/gtest.h>
17 using namespace swift;
25 * busy pipe => negative cwnd
28 unsigned long dest_addr;
29 int send_port = 10001;
32 TEST(Datagram,LedbatTest) {
34 int MAX_REORDERING = 3;
35 tint TARGET = 25*TINT_MSEC;
36 float GAIN = 1.0/TARGET;
39 tint DELAY_BIN = TINT_SEC*30;
40 tint min_delay = TINT_NEVER;
41 tint rtt_avg = TINT_NEVER>>4, dev_avg = TINT_NEVER>>4;
42 tint last_bin_time = 0;
43 tint last_drop_time = 0;
45 deque<tint> history, delay_history;
46 tint min_delay_bins[4] = {TINT_NEVER,TINT_NEVER,
47 TINT_NEVER,TINT_NEVER};
48 tint cur_delays[4] = {TINT_NEVER,TINT_NEVER,
49 TINT_NEVER,TINT_NEVER};
53 // bind sending socket
54 SOCKET send_sock = Datagram::Bind(Address(INADDR_ANY,send_port));
55 // bind receiving socket
56 SOCKET ack_sock = Datagram::Bind(Address(INADDR_ANY,ack_port));
57 struct sockaddr_in send_to, ack_to;
58 memset(&send_to, 0, sizeof(struct sockaddr_in));
59 memset(&ack_to, 0, sizeof(struct sockaddr_in));
60 send_to.sin_family = AF_INET;
61 send_to.sin_port = htons(ack_port);
62 send_to.sin_addr.s_addr = dest_addr;
63 ack_to.sin_family = AF_INET;
64 ack_to.sin_port = htons(send_port);
65 ack_to.sin_addr.s_addr = dest_addr;
66 uint8_t* garbage = (uint8_t*) malloc(1024);
67 SOCKET socks[2] = {send_sock,ack_sock};
69 tint wait_time = 100*TINT_MSEC;
71 while (sock2read = Datagram::Wait(2,socks,wait_time)) {
72 tint now = Datagram::Time();
73 if (sock2read==ack_sock) {
74 Datagram data(ack_sock); // send an acknowledgement
76 int seq = data.Pull32();
77 Datagram ack(ack_sock,ack_to);
81 fprintf(stderr,"short write\n");
82 fprintf(stderr,"%lli rcvd%i\n",now/TINT_SEC,seq);
83 // TODO: peer cwnd !!!
86 if (sock2read==send_sock) { // process an acknowledgement
87 Datagram ack(send_sock);
89 int seq = ack.Pull32();
90 tint arrival_time = ack.Pull64();
94 if (seq>=history.size())
98 tint send_time = history[seq];
100 if (seq>MAX_REORDERING*2) { //loss
101 if (last_drop_time<now-rtt_avg) {
103 last_drop_time = now;
105 fprintf(stderr,"got %i. LOSS, cwnd drop: %f\n",seq,cwnd);
106 for(int i=0; i<MAX_REORDERING*2 && history.size(); i++) {
112 tint delay = arrival_time - send_time;
113 if (seq==0 && seq_off==0) { // FIXME
114 rtt_avg = now - send_time;
117 if (send_time/DELAY_BIN != last_bin_time) {
118 last_bin_time = send_time/DELAY_BIN;
119 delay_bin = (delay_bin+1) % 4;
120 min_delay_bins[delay_bin] = TINT_NEVER;
121 min_delay = TINT_NEVER;
123 if (min_delay_bins[i]<min_delay)
124 min_delay = min_delay_bins[i];
126 if (min_delay_bins[delay_bin] > delay)
127 min_delay_bins[delay_bin] = delay;
128 if (delay < min_delay)
130 cur_delays[(seq_off+seq)%4] = delay;
131 tint current_delay = TINT_NEVER;
132 for(int i=0; i<4; i++)
133 if (current_delay > cur_delays[i])
134 current_delay = cur_delays[i]; // FIXME avg
135 tint queueing_delay = current_delay - min_delay;
137 tint off_target = TARGET - queueing_delay;
138 //cerr<<"\t"<<cwnd<<"+="<<GAIN<<"*"<<off_target<<"/"<<cwnd<<endl;
139 cwnd += GAIN * off_target / cwnd;
140 fprintf(stderr,"ackd cwnd%f cur%lli min%lli seq%i off%i\n",
141 cwnd,current_delay,min_delay,seq_off+seq,seq);
143 if (now/TINT_SEC!=last_sec/TINT_SEC) {
144 fprintf(stderr,"%i KB/sec\n",sec_ackd);
146 last_sec = now; // FIXME
151 while (history[0]==0 && history.size()) {
155 if (history.size() && history[0]<now-rtt_avg-5*dev_avg) {
156 if (last_drop_time<now-rtt_avg) {
158 last_drop_time = now;
160 fprintf(stderr,"TIMEOUT LOSS, cwnd drop: %f\n",cwnd);
165 if (history.size()<cwnd) {
166 int sendseq = history.size() + seq_off;
167 Datagram send(send_sock,send_to);
168 send.Push32(sendseq);
169 send.Push(garbage,1024);
170 history.push_back(now);
171 fprintf(stderr,"sent%i\n",sendseq);
172 if (4+1024!=send.Send())
173 fprintf(stderr,"short data write\n");
177 if (history.size()<cwnd)
178 wait_time = rtt_avg/cwnd;
180 wait_time = 100*TINT_MSEC;
184 int main (int argc, char** argv) {
187 swift::LibraryInit();
188 printf("Warning: use the script to set up dummynet!\n");
189 testing::InitGoogleTest(&argc, argv);
190 dest_addr = htonl(INADDR_LOOPBACK);
191 while ((opt = getopt(argc, argv, "a:d:s:h")) != -1)
194 if (!inet_aton(optarg, (struct in_addr *)&dest_addr)) {
195 fprintf(stderr, "inet_aton failed for addr: %s\n", optarg);
200 ack_port = (int)strtol(optarg, NULL, 10);
203 send_port = (int)strtol(optarg, NULL, 10);
207 printf("\nledbattest2 usage:\n"
208 " -d Destination IP-address (default: 127.0.0.1)\n"
209 " -s Send port (default: 10001)\n"
210 " -a Ack port (default: 10002)\n");
213 return RUN_ALL_TESTS();