-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun_tcp_accuracy_test.sh
executable file
·304 lines (229 loc) · 8.14 KB
/
run_tcp_accuracy_test.sh
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
# A modification of the run_performance_test script, Instead of running a test
# without monitoring (baseline), one with PPing and one with ePPing, it only
# runs a test with ePPing + tcpdump at the same time. Furthermore, it sets
# up a netem qdisc at M3 and updates it every PER_DELAY_TEST_LENGTH interval to
# a new delay in NETEM_DELAYS (and automatically ends the test one all delays
# have been tested)
# To be able to analyze the results properly the build from
# https://doi.org/10.5281/zenodo.7573207 must be used, which adds TSecr
# and ACK no. to the output.
# Author: Simon Sundberg
source experiments.conf
IPERF3_FLAGS=${IPERF3_FLAGS:-"-Z --fq-rate 100M -t 3600"} # Set test duratiion really long, iperf automatically killed by script when done
EPPING_FLAGS=${EPPING_FLAGS:-"-r 0 -I xdp -f -F ppviz"} # The TSecr and ACK numbers where only added to the ppviz format
PIN_CORE=${PIN_CORE:-""}
# Which netem delays to use
NETEM_DELAYS=${NETEM_DELAYS:-"0ms 10ms 20ms 30ms 40ms 50ms 60ms 70ms 80ms 90ms 100ms"}
# Which machine to setup netem on
NETEM_MACHINE=${NETEM_MACHINE:-$M3}
# Which interface on $NETEM_MACHINE to setup netem on
NETEM_IFACE=${NETEM_IFACE:-"enp1s0f1np1"}
# Arguments to TCPDUMP (except --interface)
TCPDUMP_ARGS="-s 96"
# Length (in seconds) to run the test at each netem delay
PER_DELAY_TEST_LENGTH=${PER_DELAY_TEST_LENGTH:-10}
ADD_DATETIME_SUBPATH=${ADD_DATETIME_SUBPATH:-true}
export MPLBACKEND=agg
start_sar() {
local machine=$1
local save_path=$2
echo "${machine}: Starting sar..."
ssh $machine "mkdir -p $save_path; TZ=UTC nohup sar -o ${save_path}/${GENERIC_MACHINE_NAMES[$machine]}_stats.sar 1 > /dev/null 2>&1 &"
}
stop_sar() {
local machine=$1
echo "${machine}: Stopping sar..."
# The ^ in the begining of pkill -f ^sar is to ensure it will only match
# against processes starting with sar rather than containing sar anywhere
# in its arguments, thus preventing it from killing this command itself
ssh $machine 'pkill -u $(whoami) -f "^sar -o .*_stats.sar"'
}
start_tcp_monitoring() {
local machine=$1
local save_path=$2
local interval=${3:-1}
local CMD="mkdir -p $save_path;"
CMD+=" watch -pn $interval "\""(TZ=UTC date +%Y-%m-%dT%H:%M:%S; ss -tinHO) >> ${save_path}/ss_tcp.log"\"" &> /dev/null"
echo "${machine}: Starting TCP monitoring (periodic ss -ti)..."
ssh -tt $machine "$CMD" &
}
stop_tcp_monitoring() {
local machine=$1
echo "${machine}: Stopping tcp monitoring..."
ssh $machine 'pkill -u $(whoami) -f "^watch.* ss -ti"'
}
start_tcpdump() {
local machine=$1
local savepath=$2
local iface=${3:-$IFACE}
local tcpdump_args=${4:-$TCPDUMP_ARGS}
local CMD="mkdir -p $savepath; "
CMD+="TZ=UTC sudo nohup tcpdump -i $iface -w ${savepath}/packetdump.pcap $tcpdump_args > ${savepath}/tcpdump_info.txt 2>&1 &"
echo "${machine}: Starting tcpdump with args: $tcpdump_args"
ssh $machine "$CMD"
}
stop_tcpdump() {
local machine=$1
local iface=${2:-$IFACE}
echo "${machine}: Stopping tcpdump -i $iface"
ssh $machine "sudo pkill -f '^tcpdump -i $iface'"
}
start_system_monitoring() {
local save_path=$1
for M in $M1 $M2 $M3; do
start_sar $M $save_path
done
start_tcp_monitoring $M1 $save_path
start_tcpdump $M2 $save_path
sleep 2 # Give the monitoring some time to set up
}
stop_system_monitoring() {
for M in $M1 $M2 $M3; do
stop_sar $M
done
stop_tcp_monitoring $M1
stop_tcpdump $M2
}
start_iperf3_servers() {
local machine=$1
echo "${machine}: Setting up iperf3 servers..."
local CMD=""
for ((i=0; i < IPERF_INSTANCES; i++)); do
CMD+="nohup iperf3 -s -p $(( IPERF_PORT_START + i)) > /dev/null 2>&1 & "
done
ssh $machine "$CMD"
sleep 1
}
stop_iperf3_servers() {
local machine=$1
echo "${machine}: Killing iperf3 servers"
ssh $machine 'pkill -u $(whoami) -f "^iperf3 -s"'
}
start_iperf3_clients() {
local machine=$1
local save_path=$2
local n_flows=$3
echo "${machine}: Running iperf3 tests..."
local CMD="mkdir -p $save_path; echo "\""Start: \$(TZ=UTC date -Iseconds)"\"" > ${save_path}/test_interval.log; "
for ((i=0; i < IPERF_INSTANCES; i++)); do
local N=$(( (n_flows / IPERF_INSTANCES) + (i < n_flows % IPERF_INSTANCES) ))
if (( N > 0 )); then
CMD+="nohup iperf3 -c $IP_TARGET -p $(( IPERF_PORT_START + i )) -P $N $IPERF3_FLAGS --json > ${save_path}/iperf_${i}.json 2> /dev/null & "
fi
done
ssh $machine "$CMD"
}
stop_iperf3_clients() {
local machine=$1
local save_path=$2
echo "${machine}: Killing iperf3 clients"
CMD='pkill -u $(whoami) -f "^iperf3 -c"'
CMD+="; echo "\""End: \$(TZ=UTC date -Iseconds)"\"" >> ${save_path}/test_interval.log"
ssh $machine "$CMD"
}
start_epping() {
# My eBPF pping
local machine=$1
local save_path=$2
echo "${machine}: Settig up eBPF pping on ${IFACE}..."
local pin_cmd=""
if [[ -n "$PIN_CORE" ]]; then
pin_cmd="taskset -c $PIN_CORE"
fi
local CMD="mkdir -p $save_path; cd $EPPING_PATH; "
CMD+="TZ=UTC sudo nohup $pin_cmd ./pping -i $IFACE $EPPING_FLAGS > ~/${save_path}/pping.out 2> ~/${save_path}/pping.err &"
ssh $machine "$CMD"
sleep 2 # Give pping some time to set up
}
stop_pping() {
local machine=$1
local iface=${2:-$IFACE}
echo "${machine}: Stopping (e)PPing on $iface"
# The brackets around [p] is used to avoid pkill -f from matching against
# this command itself (and thus kill this ssh-command). The [p]ping pattern
# will match against pping but not [p]ping
ssh $machine "sudo pkill -f '[p]ping -i $iface'"
}
setup_netem() {
local machine=$1
local iface=${2:-$NETEM_IFACE}
local netem_args=${3:-$NETEM_ARGS}
echo "${machine}: Setting up netem $netem_args on dev $iface"
ssh $machine "sudo tc qdisc add dev $iface root netem $netem_args"
}
change_netem() {
local machine=$1
local iface=${2:-$NETEM_IFACE}
local netem_args=${3:-$NETEM_ARGS}
echo "${machine}: Changing netem to $netem_args on dev $iface"
ssh $machine "sudo tc qdisc change dev $iface root netem $netem_args"
}
teardown_netem() {
local machine=$1
local iface=${2:-$NETEM_IFACE}
echo "${machine}: Removing netem from dev ${iface}"
ssh $machine "sudo tc qdisc del dev $iface root netem"
}
start_test() {
local save_path=$1
local n_flows=${2:-1}
mkdir -p $save_path
start_epping $M2 $save_path
start_iperf3_servers $M3
start_system_monitoring $save_path
sleep 1
start_iperf3_clients $M1 $save_path $n_flows
}
stop_test() {
local save_path=$1
stop_iperf3_clients $M1 $save_path
sleep 1
stop_system_monitoring
stop_iperf3_servers $M3
stop_pping $M2
sleep 1
}
copy_back_results() {
local save_path=$1
echo "Copying back results to local machine..."
for M in $M1 $M2 $M3; do
local subfolder=${save_path}/${GENERIC_MACHINE_NAMES[$M]}
mkdir -p $subfolder
ssh $M "xz -T0 ${save_path}/*"
scp -p "${M}:${save_path}/*" "${subfolder}/"
ssh $M "rm -r ${save_path}"
done
xz -d ${save_path}/${GENERIC_MACHINE_NAMES[$M1]}/test_interval.log.xz
mv ${save_path}/${GENERIC_MACHINE_NAMES[$M1]}/test_interval.log -t $save_path
}
basepath=$1
n_flows=1
if (( $# != 1 )); then
echo "Usage: $0 <save_path>"
exit 1
fi
if (( $n_flows > 128 * $IPERF_INSTANCES )); then
echo "Error - cannot create $n_flows concurrent flows with just $IPERF_INSTANCES instances of iperf3"
exit 1
fi
if [[ "$ADD_DATETIME_SUBPATH" == true ]]; then
currtime=$(date +%Y-%m-%dT%H%M%S)
basepath=${basepath}/${currtime}
fi
is_first=true
for delay in $NETEM_DELAYS; do
if [[ "$is_first" == true ]]; then
setup_netem $NETEM_MACHINE $NETEM_IFACE "delay $delay"
start_test "${basepath}/e_pping" $n_flows
is_first=false
else
change_netem $NETEM_MACHINE $NETEM_IFACE "delay $delay"
fi
sleep $PER_DELAY_TEST_LENGTH
done
stop_test "${basepath}/e_pping"
teardown_netem $NETEM_MACHINE $NETEM_IFACE
copy_back_results "${basepath}/e_pping"
IFACE=$IFACE OMIT=0 ./plot_results.sh $basepath $IP_TARGET