-
Notifications
You must be signed in to change notification settings - Fork 2
/
app_stuff.h
217 lines (210 loc) · 10.8 KB
/
app_stuff.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#ifndef APP_STUFF_H
#define APP_STUFF_H
// app_stuff.h:
// Collecting all app related stuff in this object
//
#include <string>
#include "prague_cc.h"
// to avoid int64 printf incompatibility between platforms:
#define C_STR(i) std::to_string(i).c_str()
// app related stuff collected in this object to avoid obfuscation of the main Prague loop
struct AppStuff
{
bool sender_role;
// Argument parser
bool verbose;
bool quiet;
const char *rcv_addr;
uint32_t rcv_port;
bool connect;
size_tp max_pkt;
rate_tp max_rate;
// state for verbose reporting
time_tp data_tm; // send diff reference
time_tp ack_tm; // ack diff reference
// state for default (non-quiet) reporting
time_tp rept_tm; // timer for reporting interval
rate_tp acc_bytes_sent; // accumulated bytes sent
rate_tp acc_bytes_rcvd; // accumulated bytes received
rate_tp acc_rtts; // accumulated rtts to calculate the average
count_tp count_rtts; // count the RTT reports
count_tp prev_packets; // prev packets received
count_tp prev_marks; // prev marks received
count_tp prev_losts; // prev losts received
void ExitIf(bool stop, const char* reason)
{
if (stop) {
perror(reason);
exit(1);
}
}
AppStuff(bool sender, int argc, char **argv):
sender_role(sender), verbose(false), quiet(false), rcv_addr("0.0.0.0"), rcv_port(8080), connect(false),
max_pkt(PRAGUE_INITMTU), max_rate(PRAGUE_MAXRATE), data_tm(1), ack_tm(1), rept_tm(1000000),
acc_bytes_sent(0), acc_bytes_rcvd(0), acc_rtts(0), count_rtts(0), prev_packets(0), prev_marks(0), prev_losts(0)
{
const char *def_rcv_addr = rcv_addr;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if (arg == "-a" && i + 1 < argc) {
rcv_addr = argv[++i];
} else if (arg == "-b" && i + 1 < argc) {
char *p;
max_rate = strtoull(argv[++i], &p, 10) * 125; // from kbps to B/s
ExitIf(errno != 0 || *p != '\0', "Error during converting max bitrate");
} else if (arg == "-p" && i + 1 < argc) {
char *p;
rcv_port = strtol(argv[++i], &p, 10);
ExitIf(errno != 0 || *p != '\0' || rcv_port > 65535, "Error during converting max port");
} else if (arg == "-c") {
connect = true;
} else if (arg == "-m" && i + 1 < argc) {
char *p;
max_pkt = strtoull(argv[++i], &p, 10);
ExitIf(errno != 0 || *p != '\0', "Error during converting max packet size");
} else if (arg == "-v") {
verbose = true;
quiet = true;
} else if (arg == "-q") {
quiet = true;
} else {
printf("UDP Prague %s usage:\n"
" -a <IP address, def: 0.0.0.0 or 127.0.0.1 if client>\n"
" -p <server port, def: 8080>\n"
" -c (connect first as a client, otherwise bind and wait for connection)\n"
" -b <sender specific max bitrate, def: %s kbps>\n"
" -m <sender specific max packet size, def: %s B>\n"
" -v (for verbose prints)\n"
" -q (quiet)\n",
sender_role ? "sender" : "receiver", C_STR(PRAGUE_MAXRATE / 125), C_STR(PRAGUE_INITMTU));
exit(1);
}
}
if (connect && (rcv_addr == def_rcv_addr))
rcv_addr = "127.0.0.1";
if (max_rate < PRAGUE_MINRATE || max_rate > PRAGUE_MAXRATE)
max_rate = PRAGUE_MAXRATE;
printf("UDP Prague %s %s %s on port %d with max packet size %s bytes.\n",
sender_role ? "sender" : "receiver",
connect ? "connecting to" : "listening at",
rcv_addr, rcv_port, C_STR(max_pkt));
if (verbose) {
if (sender_role) {
printf("s: time, timestamp, echoed_timestamp, time_diff, seqnr, packet_size,,,,, "
"pacing_rate, packet_window, packet_burst, inflight, inburst, nextSend\n");
printf("r: time, timestamp, echoed_timestamp, time_diff, seqnr, bytes_received, packets_received, packets_CE, packets_lost, error_L4S,,,,, "
"inflight, inburst, nextSend\n");
} else {
printf("r: time, timestamp, echoed_timestamp, time_diff, seqnr, bytes_received\n");
printf("s: time, timestamp, echoed_timestamp, time_diff, seqnr, packet_size, packets_received, packets_CE, packets_lost, error_L4S\n");
}
}
}
void LogSendData(time_tp now, time_tp timestamp, time_tp echoed_timestamp, count_tp seqnr, size_tp packet_size,
rate_tp pacing_rate, count_tp packet_window, count_tp packet_burst, count_tp inflight, count_tp inburst, time_tp nextSend)
{
if (verbose) {
// "s: time, timestamp, echoed_timestamp, time_diff, seqnr, packet_size,,,,, "
// "pacing_rate, packet_window, packet_burst, inflight, inburst, nextSend"
printf("s: %d, %d, %d, %d, %d, %s,,,,, %s, %d, %d, %d, %d, %d\n",
now, timestamp, echoed_timestamp, timestamp - data_tm, seqnr, C_STR(packet_size),
C_STR(pacing_rate), packet_window, packet_burst, inflight, inburst, nextSend - now);
data_tm = timestamp;
}
if (!quiet) acc_bytes_sent += packet_size;
}
void LogRecvACK(time_tp now, time_tp timestamp, time_tp echoed_timestamp, count_tp seqnr, size_tp bytes_received,
count_tp packets_received, count_tp packets_CE, count_tp packets_lost, bool error_L4S,
rate_tp pacing_rate, count_tp packet_window, count_tp packet_burst, count_tp inflight, count_tp inburst, time_tp nextSend)
{
if (verbose) {
// "r: time, timestamp, echoed_timestamp, time_diff, seqnr, bytes_received, packets_received, packets_CE, packets_lost, error_L4S,,,,, "
// "inflight, inburst, nextSend"
printf("r: %d, %d, %d, %d, %d, %s, %d, %d, %d, %d,,,,, %d, %d, %d\n",
now, timestamp, echoed_timestamp, timestamp - ack_tm, seqnr, C_STR(bytes_received), packets_received, packets_CE, packets_lost,
error_L4S, inflight, inburst, nextSend - now);
ack_tm = timestamp;
}
if (!quiet) {
acc_bytes_rcvd += bytes_received;
acc_rtts += (now - echoed_timestamp);
count_rtts++;
// Display sender side info
if (now - rept_tm >= 0) {
float rate_rcvd = 8.0f * acc_bytes_rcvd / (now - rept_tm + 1000000);
float rate_sent = 8.0f * acc_bytes_sent / (now - rept_tm + 1000000);
float rate_pacing = 8.0f * pacing_rate / 1000000.0;
float rtt = (count_rtts > 0) ? 0.001f * acc_rtts / count_rtts : 0.0f;
float mark_prob = (packets_received - prev_packets > 0) ?
100.0f * (packets_CE - prev_marks) / (packets_received - prev_packets) : 0.0f;
float loss_prob = (packets_received - prev_packets > 0) ?
100.0f*(packets_lost - prev_losts) / (packets_received - prev_packets) : 0.0f;
printf("[SENDER]: %.2f sec, Sent: %.3f Mbps, Rcvd: %.3f Mbps, RTT: %.3f ms, "
"Mark: %.2f%%(%d/%d), Lost: %.2f%%(%d/%d), Pacing rate: %.3f Mbps, InFlight/W: %d/%d packets, InBurst/B: %d/%d packets\n",
now / 1000000.0f, rate_sent, rate_rcvd, rtt,
mark_prob, packets_CE - prev_marks, packets_received - prev_packets,
loss_prob, packets_lost - prev_losts, packets_received - prev_packets, rate_pacing, inflight, packet_window, inburst, packet_burst);
rept_tm = now + 1000000;
acc_bytes_sent = 0;
acc_bytes_rcvd = 0;
acc_rtts = 0;
count_rtts = 0;
prev_packets = packets_received;
prev_marks = packets_CE;
prev_losts = packets_lost;
}
}
}
void LogRecvData(time_tp now, time_tp timestamp, time_tp echoed_timestamp, count_tp seqnr, size_tp bytes_received)
{
if (verbose) {
// "r: time, timestamp, echoed_timestamp, time_diff, seqnr, bytes_received"
printf("r: %d, %d, %d, %d, %d, %s\n",
now, timestamp, echoed_timestamp, timestamp - data_tm, seqnr, C_STR(bytes_received));
data_tm = timestamp;
}
if (!quiet) {
acc_bytes_rcvd += bytes_received;
if (echoed_timestamp) {
acc_rtts += (now - echoed_timestamp);
count_rtts++;
}
}
}
void LogSendACK(time_tp now, time_tp timestamp, time_tp echoed_timestamp, count_tp seqnr, size_tp packet_size,
count_tp packets_received, count_tp packets_CE, count_tp packets_lost, bool error_L4S)
{
if (verbose) {
// "s: time, timestamp, echoed_timestamp, time_diff, seqnr, packet_size, packets_received, packets_CE, packets_lost, error_L4S"
printf("s: %d, %d, %d, %d, %d, %s, %d, %d, %d, %d\n",
now, timestamp, echoed_timestamp, timestamp - ack_tm, seqnr, C_STR(packet_size), packets_received, packets_CE, packets_lost, error_L4S);
ack_tm = timestamp;
}
if (!quiet) {
// Display receiver side info
acc_bytes_sent += packet_size;
if (now - rept_tm >= 0) {
float rate_rcvd = 8.0f * acc_bytes_rcvd / (now - rept_tm + 1000000);
float rate_sent = 8.0f * acc_bytes_sent / (now - rept_tm + 1000000);
float rtt = (count_rtts > 0) ? 0.001f * acc_rtts / count_rtts : 0.0f;
float mark_prob = (packets_received - prev_packets > 0) ?
100.0f * (packets_CE - prev_marks) / (packets_received - prev_packets) : 0.0f;
float loss_prob = (packets_received - prev_packets > 0) ?
100.0f*(packets_lost - prev_losts) / (packets_received - prev_packets) : 0.0f;
printf("[RECVER]: %.2f sec, Rcvd: %.3f Mbps, Sent: %.3f Mbps, RTT: %.3f ms, Mark: %.2f%%(%d/%d), Lost: %.2f%%(%d/%d)\n",
now / 1000000.0f, rate_rcvd, rate_sent, rtt,
mark_prob, packets_CE - prev_marks, packets_received - prev_packets,
loss_prob, packets_lost - prev_losts, packets_received - prev_packets);
rept_tm = now + 1000000;
acc_bytes_rcvd = 0;
acc_bytes_sent = 0;
acc_rtts = 0;
count_rtts = 0;
prev_packets = packets_received;
prev_marks = packets_CE;
prev_losts = packets_lost;
}
}
}
};
#endif //APP_STUFF_H