4 * BROKEN: Arno: must be rewritten to libevent
6 * Created by Victor Grishchenko on 3/22/09.
7 * Copyright 2009-2012 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved.
13 #include "compat/stdint.h"
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
24 #include <gtest/gtest.h>
26 using namespace swift;
34 * busy pipe => negative cwnd
37 unsigned long dest_addr;
38 int send_port = 10001;
41 TEST(Datagram,LedbatTest) {
43 int MAX_REORDERING = 3;
44 tint TARGET = 25*TINT_MSEC;
45 float GAIN = 1.0/TARGET;
48 tint DELAY_BIN = TINT_SEC*30;
49 tint min_delay = TINT_NEVER;
50 tint rtt_avg = TINT_NEVER>>4, dev_avg = TINT_NEVER>>4;
51 tint last_bin_time = 0;
52 tint last_drop_time = 0;
54 deque<tint> history, delay_history;
55 tint min_delay_bins[4] = {TINT_NEVER,TINT_NEVER,
56 TINT_NEVER,TINT_NEVER};
57 tint cur_delays[4] = {TINT_NEVER,TINT_NEVER,
58 TINT_NEVER,TINT_NEVER};
62 // bind sending socket
63 evutil_socket_t send_sock = Datagram::Bind(Address(INADDR_ANY,send_port));
64 // bind receiving socket
65 evutil_socket_t ack_sock = Datagram::Bind(Address(INADDR_ANY,ack_port));
66 struct sockaddr_in send_to, ack_to;
67 memset(&send_to, 0, sizeof(struct sockaddr_in));
68 memset(&ack_to, 0, sizeof(struct sockaddr_in));
69 send_to.sin_family = AF_INET;
70 send_to.sin_port = htons(ack_port);
71 send_to.sin_addr.s_addr = dest_addr;
72 ack_to.sin_family = AF_INET;
73 ack_to.sin_port = htons(send_port);
74 ack_to.sin_addr.s_addr = dest_addr;
75 uint8_t* garbage = (uint8_t*) malloc(1024);
76 evutil_socket_t socks[2] = {send_sock,ack_sock};
77 evutil_socket_t sock2read;
78 tint wait_time = 100*TINT_MSEC;
80 while (sock2read = Datagram::Wait(2,socks,wait_time)) {
81 tint now = Datagram::Time();
82 if (sock2read==ack_sock) {
83 Datagram data(ack_sock); // send an acknowledgement
85 int seq = data.Pull32();
86 Datagram ack(ack_sock,ack_to);
90 fprintf(stderr,"short write\n");
91 fprintf(stderr,"%lli rcvd%i\n",now/TINT_SEC,seq);
92 // TODO: peer cwnd !!!
95 if (sock2read==send_sock) { // process an acknowledgement
96 Datagram ack(send_sock);
98 int seq = ack.Pull32();
99 tint arrival_time = ack.Pull64();
103 if (seq>=history.size())
107 tint send_time = history[seq];
109 if (seq>MAX_REORDERING*2) { //loss
110 if (last_drop_time<now-rtt_avg) {
112 last_drop_time = now;
114 fprintf(stderr,"got %i. LOSS, cwnd drop: %f\n",seq,cwnd);
115 for(int i=0; i<MAX_REORDERING*2 && history.size(); i++) {
121 tint delay = arrival_time - send_time;
122 if (seq==0 && seq_off==0) { // FIXME
123 rtt_avg = now - send_time;
126 if (send_time/DELAY_BIN != last_bin_time) {
127 last_bin_time = send_time/DELAY_BIN;
128 delay_bin = (delay_bin+1) % 4;
129 min_delay_bins[delay_bin] = TINT_NEVER;
130 min_delay = TINT_NEVER;
132 if (min_delay_bins[i]<min_delay)
133 min_delay = min_delay_bins[i];
135 if (min_delay_bins[delay_bin] > delay)
136 min_delay_bins[delay_bin] = delay;
137 if (delay < min_delay)
139 cur_delays[(seq_off+seq)%4] = delay;
140 tint current_delay = TINT_NEVER;
141 for(int i=0; i<4; i++)
142 if (current_delay > cur_delays[i])
143 current_delay = cur_delays[i]; // FIXME avg
144 tint queueing_delay = current_delay - min_delay;
146 tint off_target = TARGET - queueing_delay;
147 //cerr<<"\t"<<cwnd<<"+="<<GAIN<<"*"<<off_target<<"/"<<cwnd<<endl;
148 cwnd += GAIN * off_target / cwnd;
149 fprintf(stderr,"ackd cwnd%f cur%lli min%lli seq%i off%i\n",
150 cwnd,current_delay,min_delay,seq_off+seq,seq);
152 if (now/TINT_SEC!=last_sec/TINT_SEC) {
153 fprintf(stderr,"%i KB/sec\n",sec_ackd);
155 last_sec = now; // FIXME
160 while (history[0]==0 && history.size()) {
164 if (history.size() && history[0]<now-rtt_avg-5*dev_avg) {
165 if (last_drop_time<now-rtt_avg) {
167 last_drop_time = now;
169 fprintf(stderr,"TIMEOUT LOSS, cwnd drop: %f\n",cwnd);
174 if (history.size()<cwnd) {
175 int sendseq = history.size() + seq_off;
176 Datagram send(send_sock,send_to);
177 send.Push32(sendseq);
178 send.Push(garbage,1024);
179 history.push_back(now);
180 fprintf(stderr,"sent%i\n",sendseq);
181 if (4+1024!=send.Send())
182 fprintf(stderr,"short data write\n");
186 if (history.size()<cwnd)
187 wait_time = rtt_avg/cwnd;
189 wait_time = 100*TINT_MSEC;
193 int main (int argc, char** argv) {
196 swift::LibraryInit();
197 printf("Warning: use the script to set up dummynet!\n");
198 testing::InitGoogleTest(&argc, argv);
199 dest_addr = htonl(INADDR_LOOPBACK);
200 while ((opt = getopt(argc, argv, "a:d:s:h")) != -1)
203 if (!inet_aton(optarg, (struct in_addr *)&dest_addr)) {
204 fprintf(stderr, "inet_aton failed for addr: %s\n", optarg);
209 ack_port = (int)strtol(optarg, NULL, 10);
212 send_port = (int)strtol(optarg, NULL, 10);
216 printf("\nledbattest2 usage:\n"
217 " -d Destination IP-address (default: 127.0.0.1)\n"
218 " -s Send port (default: 10001)\n"
219 " -a Ack port (default: 10002)\n");
222 return RUN_ALL_TESTS();