blob: ad2084590f5b5e89de57db4b04e0f1b2aced2525 [file] [log] [blame]
Jordan Halterman4d32a582017-05-26 19:14:30 -07001#!/bin/bash
2# ---------------------------------
3# Disrupts links between ONOS nodes
4# ---------------------------------
5
6[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7. $ONOS_ROOT/tools/build/envDefaults
8
9function print_usage {
10 command_name=`basename $0`
11 echo "Disrupts links between ONOS nodes."
12 echo
13 echo "Usage: $command_name [<HOST>] <COMMAND> <ARGS>"
14 echo
15 echo "Options:"
16 echo " HOST The host on which to run the command"
17 echo " COMMAND The command to run"
18 echo " ARGS The command arguments"
19 echo " [-h | --help] Print this help"
20 echo
21 echo "COMMAND: <crash | partition | partition-halves | partition-bridge | heal | delay | drop | reorder | duplicate | corrupt | restore>"
22 echo
23 echo " crash Crashes the given host using \"kill -9\""
24 echo
25 echo " Syntax:"
26 echo " $command_name <HOST> crash"
27 echo
28 echo " Examples:"
29 echo " $command_name 10.127.10.111 crash"
30 echo
31 echo " partition Partitions the given host from a list of source host or all ONOS hosts if no sources are specified"
32 echo
33 echo " Syntax:"
34 echo " $command_name <HOST> partition [<SOURCE> [<SOURCE>...]]"
35 echo
36 echo " Examples:"
37 echo " $command_name 10.127.10.111 partition"
38 echo " $command_name 10.127.10.111 partition 10.127.10.111"
39 echo " $command_name 10.127.10.111 partition 10.127.10.112 10.127.10.113"
40 echo
41 echo " partition-halves Splits the cluster into two partitions - this is only recommended for clusters with an odd number of nodes"
42 echo
43 echo " Syntax:"
44 echo " $command_name partition-halves"
45 echo
46 echo " Examples:"
47 echo " $command_name partition-halves"
48 echo
49 echo " partition-bridge Creates a bridge partition where the cluster is partitioned into two halves and the target host is connected to both halves"
50 echo
51 echo " Syntax:"
52 echo " $command_name <HOST> bridge"
53 echo
54 echo " Examples:"
55 echo " $command_name 10.127.10.111 bridge"
56 echo
57 echo " heal Heals a partition on the given host"
58 echo
59 echo " Syntax:"
60 echo " $command_name [<HOST>] heal"
61 echo
62 echo " Examples:"
63 echo " $command_name heal"
64 echo " $command_name 10.127.10.111 heal"
65 echo
66 echo " delay Delays packets incoming to the given host by an optional LATENCY, JITTER, CORRELATION, and DISTRIBUTION"
67 echo
68 echo " Syntax:"
69 echo " $command_name [<HOST>] delay [<LATENCY> [<JITTER> [<CORRELATION> [<DISTRIBUTION>]]]]"
70 echo
71 echo " Examples:"
72 echo " $command_name delay"
73 echo " $command_name delay 50ms"
74 echo " $command_name delay 50ms 10ms"
75 echo " $command_name delay 50ms 10ms 75%"
76 echo " $command_name delay 50ms 10ms 75% normal"
77 echo " $command_name 10.127.10.111 delay"
78 echo " $command_name 10.127.10.111 delay 50ms"
79 echo " $command_name 10.127.10.111 delay 50ms 10ms"
80 echo " $command_name 10.127.10.111 delay 50ms 10ms 75%"
81 echo " $command_name 10.127.10.111 delay 50ms 10ms 75% normal"
82 echo
83 echo " drop Drops packets incoming to the given host by an optional PROBABILITY and CORRELATION"
84 echo
85 echo " Syntax:"
86 echo " $command_name [<HOST>] drop [<PROBABILITY> [<CORRELATION>]]"
87 echo
88 echo " Examples:"
89 echo " $command_name drop"
90 echo " $command_name drop 2%"
91 echo " $command_name drop 2% 25%"
92 echo " $command_name 10.127.10.111 drop"
93 echo " $command_name 10.127.10.111 drop 2%"
94 echo " $command_name 10.127.10.111 drop 2% 25%"
95 echo
96 echo " reorder Reorders packets incoming to the given host by an optional PROBABILITY and CORRELATION"
97 echo
98 echo " Syntax:"
99 echo " $command_name [<HOST>] reorder [<PROBABILITY> [<CORRELATION>]]"
100 echo
101 echo " Examples:"
102 echo " $command_name reorder"
103 echo " $command_name reorder 2%"
104 echo " $command_name reorder 2% 50%"
105 echo " $command_name 10.127.10.111 reorder"
106 echo " $command_name 10.127.10.111 reorder 2%"
107 echo " $command_name 10.127.10.111 reorder 2% 50%"
108 echo
109 echo " duplicate Duplicates packets incoming to the given host by an optional PROBABILITY and CORRELATION"
110 echo
111 echo " Syntax:"
112 echo " $command_name [<HOST>] duplicate [<PROBABILITY> [<CORRELATION>]]"
113 echo
114 echo " Examples:"
115 echo " $command_name duplicate"
116 echo " $command_name duplicate 0.5%"
117 echo " $command_name duplicate 0.5% 5%"
118 echo " $command_name 10.127.10.111 duplicate"
119 echo " $command_name 10.127.10.111 duplicate 0.5%"
120 echo " $command_name 10.127.10.111 duplicate 0.5% 5%"
121 echo
122 echo " corrupt Corrupts packets incoming to the given host by an optional PROBABILITY"
123 echo
124 echo " Syntax:"
125 echo " $command_name [<HOST>] corrupt [<PROBABILITY>]"
126 echo
127 echo " Examples:"
128 echo " $command_name corrupt"
129 echo " $command_name corrupt 0.1%"
130 echo " $command_name 10.127.10.111 corrupt"
131 echo " $command_name 10.127.10.111 corrupt 0.1%"
132 echo
133 echo " restore Restores the given host from all delay/drop/reorder/duplicate/corrupt states"
134 echo
135 echo " Syntax:"
136 echo " $command_name [<HOST>] restore"
137 echo
138 echo " Examples:"
139 echo " $command_name restore"
140 echo " $command_name 10.127.10.111 restore"
141 echo
142}
143
144# Print usage
145if [ "${1}" = "-h" -o "${1}" = "--help" ]; then
146 print_usage
147 exit 0
148fi
149
150# Converts an argument into a milliseconds string unless it's already in the correct format.
151function to_millis() {
152 if [[ ${1: -2} != "ms" ]]; then
153 echo "${1}ms"
154 else
155 echo ${1}
156 fi
157}
158
159function onos_nodes() {
160 echo $(env | sort | egrep "^OC[0-9]+" | cut -d= -f2)
161}
162
163function partition() {
164 local=${1}
165 remote=${2}
166 echo "Severing link ${remote}->${local}"
167 ssh $ONOS_USER@${local} "sudo iptables -A INPUT -s ${remote} -j DROP -w"
168}
169
170function heal() {
171 local=${1}
172 remote=${2}
173 echo "Restoring link ${remote}->${local}"
174 ssh $ONOS_USER@${local} "sudo iptables -D INPUT -s ${remote} -j DROP -w" &>/dev/null
175}
176
177function delay() {
178 host=${1}
179 latency=$(to_millis ${2:-"50ms"})
180 jitter=$(to_millis ${3:-"10ms"})
181 correlation=${4:-"75%"}
182 distribution=${5:-"normal"}
183 echo "Delaying packets for ${host} (latency: ${latency}, jitter: ${jitter}, correlation: ${correlation}, distribution: ${distribution})"
184 ssh $ONOS_USER@${host} "sudo tc qdisc add dev eth0 root netem delay ${latency} ${jitter} ${correlation} distribution ${distribution}"
185}
186
187function drop() {
188 host=${1}
189 probability=${2:-"2%"}
190 correlation=${3:-"25%"}
191 echo "Dropping packets for ${host} (probability: ${probability}, correlation: ${correlation})"
192 ssh $ONOS_USER@${host} "sudo tc qdisc add dev eth0 root netem loss ${probability} ${correlation}"
193}
194
195function reorder() {
196 host=${1}
197 probability=${2:-"2%"}
198 correlation=${3:-"50%"}
199 echo "Reordering packets for ${host} (probability: ${probability}, correlation: ${correlation})"
200 ssh $ONOS_USER@${host} "sudo tc qdisc add dev eth0 root netem reorder ${probability} ${correlation}"
201}
202
203function duplicate() {
204 host=${1}
205 probability=${2:-"0.5%"}
206 correlation=${3:-"5%"}
207 echo "Duplicating packets for ${host} (probability: ${probability}, correlation: ${correlation})"
208 ssh $ONOS_USER@${host} "sudo tc qdisc add dev eth0 root netem duplicate ${probability} ${correlation}"
209}
210
211function corrupt() {
212 host=${1}
213 probability=${2:-"0.1%"}
214 echo "Corrupting packets for ${host} (probability: ${probability})"
215 ssh $ONOS_USER@${host} "sudo tc qdisc add dev eth0 root netem corrupt ${probability}"
216}
217
218function restore() {
219 host=${1}
220 echo "Restoring packets for ${host}"
221 ssh $ONOS_USER@${host} "sudo tc qdisc del dev eth0 root" &>/dev/null
222}
223
224cmd=${1} && shift
225
226case $cmd in
227
228# Partitions the cluster into two halves.
229partition-halves)
230 # Get the list of ONOS nodes.
231 nodes=($(onos_nodes))
232
233 # Use a nested loop to split the network into two halves using index mod 2.
234 for i in "${!nodes[@]}"; do
235 if [[ $((i % 2)) == 0 ]]; then
236 for j in "${!nodes[@]}"; do
237 if [[ $i != $j ]] && [[ $((j % 2)) == 1 ]]; then
238 partition ${nodes[i]} ${nodes[j]}
239 partition ${nodes[j]} ${nodes[i]}
240 fi
241 done
242 fi
243 done
244 ;;
245
246# Heals all partitions on all nodes.
247heal)
248 # Get the list of ONOS nodes and heal partitions between each node in both directions.
249 nodes=$(onos_nodes)
250 for lnode in ${nodes}; do
251 for rnode in ${nodes}; do
252 if [[ ${lnode} != ${rnode} ]]; then
253 heal ${lnode} ${rnode}
254 fi
255 done
256 done
257 ;;
258
259*)
260 # If a function with the command name exists, iterate through all ONOS nodes and call the function for each node.
261 if [ -n "$(type -t $cmd)" ] && [ "$(type -t $cmd)" = function ]; then
262 nodes=$(onos_nodes)
263 for node in ${nodes}; do
264 ${cmd} ${node} "${@}"
265 done
266 exit 0
267 fi
268
269 host=$cmd
270 cmd="$1" && shift
271
272 case $cmd in
273
274 # Kills a node.
275 crash)
276 onos-kill "${host}"
277 ;;
278
279 # Creates a partition between the source node and a set of destination nodes.
280 partition)
281
282 # Default to ONOS nodes.
283 if [ -z "${1}" ]; then
284 nodes=$(onos_nodes)
285 else
286 nodes="${*}"
287 fi
288
289 # Iterate through all provided nodes and create partitions.
290 for node in $nodes; do
291 partition ${host} ${node}
292 done
293 ;;
294
295 # Splits the cluster into two halves, preserving the provided host as a bridge between the two halves.
296 partition-bridge)
297
298 # Get the list of ONOS nodes.
299 nodes=($(onos_nodes))
300
301 # Use a nested loop and split the network into two halves using index mod 2. Exclude
302 # the indicated host to ensure it can communicate with both sides of the partition.
303 for i in "${!nodes[@]}"; do
304 if [[ $((i % 2)) == 0 ]] && [[ ${nodes[i]} != ${host} ]]; then
305 for j in "${!nodes[@]}"; do
306 if [[ $i != $j ]] && [[ $((j % 2)) == 1 ]] && [[ ${nodes[j]} != ${host} ]]; then
307 partition ${nodes[i]} ${nodes[j]}
308 partition ${nodes[j]} ${nodes[i]}
309 fi
310 done
311 fi
312 done
313 ;;
314
315 # Heals a partition between the provided host and a set of ONOS nodes.
316 heal)
317
318 # Default to ONOS nodes.
319 if [ -z "${1}" ]; then
320 nodes=$(onos_nodes)
321 else
322 nodes="${*}"
323 fi
324
325 # Iterate through all provided nodes and heal partitions.
326 for node in $nodes; do
327 heal ${host} ${node}
328 done
329 ;;
330
331 # If we made it this far, use the command name variable to call the associated function.
332 *)
333 ${cmd} ${host} "${@}"
334 ;;
335
336 esac
337 ;;
338
339esac