Skip to content

Instantly share code, notes, and snippets.

@scoky
Created January 5, 2023 16:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scoky/a096f5bd5381024da79f4ca6f4ccfa9f to your computer and use it in GitHub Desktop.
Save scoky/a096f5bd5381024da79f4ca6f4ccfa9f to your computer and use it in GitHub Desktop.
Adding simulate network delay, jitter, and loss
network_simulate() {
[ $# -ne 3 ] && echo 'usage: loss (fraction) delay (ms) jitter (ms)' && return 0
loss=$1
delay=$2
jitter=$3
if [ "$loss" != "0" ]; then
# Rather than drop, use NFQUEUE.
# Drop is detected by the application as an error and may trigger a retry, negating the impact of probabilistic loss.
# NFQUEUE moves the packets to a queue (666 here) which, because it is unread, silently drops the packets on overflow.
iptables -A INPUT -m statistic --mode random --probability $loss -s $REMOTE_IP -j NFQUEUE --queue-num 666
iptables -A OUTPUT -m statistic --mode random --probability $loss -d $REMOTE_IP -j NFQUEUE --queue-num 666
# N.B. using iptables to simulate loss because, like DROP, loss using tc is also detected by applications.
fi
if [ "$delay" != "0" ]; then
# Construct the filter parameters for delay and jitter
filter="delay ${delay}ms"
if [ "$jitter" != "0" ]; then
# This is uniform jitter. Others are possible.
# N.B. jitter can cause packet reordering
filter="$filter ${jitter}ms"
fi
# Simulate egress properties
tc qdisc add dev $INTERFACE root handle 1: prio
tc filter add dev $INTERFACE parent 1:0 protocol ip prio 1 u32 match ip dst $REMOTE_IP flowid 2:1
tc qdisc add dev $INTERFACE parent 1:1 handle 2: netem $filter
# Simulate ingress properties
tc qdisc add dev $INTERFACE ingress
# Need to create $IFB first, e.g.,:
# ip link add name $IFB type ifb
# ip link set dev $IFB up
tc filter add dev $INTERFACE parent ffff: protocol ip u32 match ip src $REMOTE_IP flowid 1:1 action mirred egress redirect dev $IFB
tc qdisc add dev $IFB root netem $filter
fi
}
network_simulate_clean() {
[ $# -ne 3 ] && echo 'usage: loss (fraction) delay (ms) jitter (ms)' && return 0
loss=$1
delay=$2
jitter=$3
if [ "$delay" != "0" ]; then
# Delete tc configuration
tc qdisc del dev $INTERFACE root
tc qdisc del dev $INTERFACE ingress
tc qdisc del dev $IFB root
fi
if [ "$loss" != "0" ]; then
# Delete ingress/egress loss rules
iptables -D INPUT -m statistic --mode random --probability $loss -s $REMOTE_IP -j NFQUEUE --queue-num 666
iptables -D OUTPUT -m statistic --mode random --probability $loss -d $REMOTE_IP -j NFQUEUE --queue-num 666
fi
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment