forked from marty90/errant
-
Notifications
You must be signed in to change notification settings - Fork 0
/
errant
executable file
·194 lines (154 loc) · 5.83 KB
/
errant
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
#!/bin/bash
# Default values
VIRTUAL=ifb0
# Utility Function
function go() {
if [ "$DRY_RUN" = true ]; then
echo "+ $*"
else
eval "$*"
fi
return $?
}
# Parse Args
DRY_RUN=false
REMOVE=false
PERIODIC=""
OPERATOR=""
COUNTRY=""
TECHNOLOGY=""
QUALITY=""
INTERFACE=""
LOGFILE=""
UPLOAD=""
DOWNLOAD=""
RTT_AVG=""
LOSS=""
while getopts "o:c:t:q:i:O:p:l:L:u:d:R:rhd" flag
do
case $flag in
o) OPERATOR=$OPTARG;;
c) COUNTRY=$OPTARG;;
t) TECHNOLOGY=$OPTARG;;
q) QUALITY=$OPTARG;;
i) INTERFACE=$OPTARG;;
O) VIRTUAL=$OPTARG;;
l) LOGFILE=$OPTARG;;
u) UPLOAD=$OPTARG;;
d) DOWNLOAD=$OPTARG;;
R) RTT_AVG=$OPTARG;;
L) LOSS=$OPTARG;;
r) REMOVE=true;;
d) DRY_RUN=true;;
p) PERIODIC=$OPTARG;;
h) echo "Usage: errant { -o operator -c country -t technology -q quality | -u upload_speed [-d download_speed] -R RTT } -i interface [-O virtual_interface] [-p period] [-L loss] [-l logfile] [-r] [-d] [-h]" ; exit ;;
esac
done
# Log file header
if [ ! -z $LOGFILE ] ; then
echo "time,operator,country,technology,quality,download,upload,rtt,loss" > "$LOGFILE"
fi
# Remove rules
if [ "$REMOVE" = true ]; then
# Check arguments are correct
if [ -z "$OPERATOR" ] && [ -z "$COUNTRY" ] && [ -z "$TECHNOLOGY" ] \
&& [ -z "$QUALITY" ] && [ -z "$INTERFACE" ] \
&& [ -z "$UPLOAD" ] && [ -z "$DOWNLOAD" ] \
&& [ -z "$RTT_AVG" ] && [ -z "$LOSS" ]; then
echo "Removing shaping rules"
# Remove module IFB
go ip link delete $VIRTUAL type ifb
# Remove all TC policies
for INTERFACE in $( ifconfig -a | sed 's/[: \t].*//;/^$/d' | grep -v ifb ) ; do
go tc qdisc del root dev $INTERFACE 2>/dev/null
go tc qdisc del dev $INTERFACE handle ffff: ingress 2>/dev/null
done
else
echo "When removing rules, all other arguments must be empty"
fi
else
DOWNLOAD=${DOWNLOAD:-UPLOAD}
if [ ! -z "$UPLOAD" ] && [ ! -z "$DOWNLOAD" ] && [ ! -z "$RTT_AVG" ]; then
OPERATOR=${OPERATOR:-"universal"}
COUNTRY=${COUNTRY:-"universal"}
TECHNOLOGY=${TECHNOLOGY:-"universal"}
QUALITY=${QUALITY:-"universal"}
fi
if [ -z "$INTERFACE" ]; then
echo "You should specify the interface"
elif [ -z "$OPERATOR" ] || [ -z "$COUNTRY" ] \
|| [ -z "$TECHNOLOGY" ] || [ -z "$QUALITY" ]; then
echo "You should specify all of operator,country, technology, quality and interface"
else
echo "Imposing shaping on interface: $INTERFACE"
if [ ! -z $PERIODIC ] ; then
if ! [[ "$PERIODIC" =~ ^[0-9]+$ ]] ; then
echo "Wrong periodic shaping value. Only integers allowed."
exit
else
echo "Periodic shaping with period: $PERIODIC"
fi
fi
while true ; do
if [ -z "$UPLOAD" ] || [ -z "$DOWNLOAD" ] || [ -z "$RTT_AVG" ]; then
# Search for profile
values=$( python3 sample_from_distribution.py $OPERATOR $COUNTRY $TECHNOLOGY $QUALITY )
if [ "$values" = "error" ] ; then
echo "Cannot find selected profile"
exit
fi
DOWNLOAD=$(echo $values | cut -d " " -f 1)
UPLOAD=$(echo $values | cut -d " " -f 2)
RTT_AVG=$(echo $values | cut -d " " -f 3)
fi
if [ ! -z $LOSS ]; then
if ! [[ "$LOSS" =~ ^[0-9]+$ ]]; then
echo "Wrong loss shaping value. Only integers allowed. Defaulting to 0%."
LOSS="0"
fi
fi
LOSS=${LOSS:-"0"}
# Print infos
echo "Imposing profile:"
echo " Operator: $OPERATOR"
echo " Country: $COUNTRY"
echo " Technology: $TECHNOLOGY"
echo " Quality: $QUALITY"
echo "Parameters are:"
echo " Download [kbps]: $DOWNLOAD"
echo " Upload [kbps]: $UPLOAD"
echo " RTT [ms]: $RTT_AVG"
echo " LOSS [%]: $LOSS"
# Write Log if needed
if [ ! -z $LOGFILE ] ; then
echo "$(date +%s),$OPERATOR,$COUNTRY,$TECHNOLOGY,$QUALITY,$DOWNLOAD,$UPLOAD,$RTT_AVG,$LOSS" >> $LOGFILE
fi
# Impose shaping
# Create virtual interfaces
go ip link add $VIRTUAL type ifb
go ip link set dev $VIRTUAL up
# Create rules
# Clear old
go tc qdisc del root dev $INTERFACE 2>/dev/null # clear outgoing
go tc qdisc del dev $INTERFACE handle ffff: ingress 2>/dev/null # clear incoming
go tc qdisc del root dev $VIRTUAL 2>/dev/null
# Create Device Pipes
go tc qdisc add dev $INTERFACE handle ffff: ingress
go tc filter add dev $INTERFACE parent ffff: protocol ip u32 match u32 0 0 \
action mirred egress redirect dev $VIRTUAL
# INCOMING
go tc qdisc add dev $VIRTUAL root netem loss random $LOSS rate ${DOWNLOAD}kbit
# OUTGOING
go tc qdisc add dev $INTERFACE root netem loss random $LOSS rate ${UPLOAD}kbit delay ${RTT_AVG}ms
if [ -z $PERIODIC ] ; then
break
else
echo "Sleeping $PERIODIC seconds..."
UPLOAD=""
DOWNLOAD=""
RTT_AVG=""
sleep $PERIODIC
fi
done
fi
fi