Skip to content

Instantly share code, notes, and snippets.

@andrewhodel
Last active August 29, 2022 23:27
Show Gist options
  • Save andrewhodel/9b5ec6805d202ca84cc1a2db7d424355 to your computer and use it in GitHub Desktop.
Save andrewhodel/9b5ec6805d202ca84cc1a2db7d424355 to your computer and use it in GitHub Desktop.
network congestion steps (latency and loss) for linux (iptables and tc)
#!/bin/sh
remove_rules()
{
echo "removing iptables and tc rules"
sudo iptables -F
echo "removing tc qdisc for ${netif}"
sudo tc qdisc del dev ${netif} root
}
ctrl_c()
{
# remove rules
remove_rules
# exit
exit 0
}
trap ctrl_c INT
ip="${2}"
netif="${1}"
cycle_duration_seconds=120
rejected_step_percent=5
rejected_step_current_percent=85
latency_step_ms=500
latency_max=4000
latency_first=500
latency_current=${latency_first}
if [[ -z "${ip}" ]]
then
echo "An IP Address is required as the second argument."
exit 1
fi
if [[ -z "${netif}" ]]
then
echo "An interface name is required as the first argument."
exit 1
fi
duration=0
((duration=${cycle_duration_seconds}*(${latency_max}/${latency_step_ms})))
echo "Executing network congestion for ${ip}"
echo -e "\tduration per rejected packet step: ${rejected_step_current_percent}% to 0% at ${rejected_step_percent}%: ${duration}s"
echo -e "\tlatency range per rejected packet step: ${latency_current}ms to ${latency_max}ms at ${latency_step_ms}ms per latency step"
echo -e "\tTest your network code during this time, the levels are printed to the console to allow you to repeat network conditions that cause problems and fix them."
echo ""
while [[ "$rejected_step_current_percent" > "0" ]]
do
# drop % of traffic through range
remove_rules
if [[ "${rejected_step_current_percent}" == "100" ]]
then
# from IP
sudo iptables -I INPUT -m statistic --mode random --probability 1 -s ${ip} -j REJECT
# to IP
sudo iptables -I OUTPUT -m statistic --mode random --probability 1 -d ${ip} -j REJECT
else
# from IP
sudo iptables -I INPUT -m statistic --mode random --probability 0.${rejected_step_current_percent} -s ${ip} -j REJECT
# to IP
sudo iptables -I OUTPUT -m statistic --mode random --probability 0.${rejected_step_current_percent} -d ${ip} -j REJECT
fi
while [[ ${latency_current} -lt ${latency_max} ]]
do
# set latency through range
# remove existing queues
echo "removing tc qdisc for ${netif}"
sudo tc qdisc del dev ${netif} root
sudo tc qdisc add dev ${netif} root handle 1: prio
sudo tc qdisc add dev ${netif} parent 1:3 handle 30: netem delay ${latency_current}ms
sudo tc filter add dev ${netif} protocol ip parent 1:0 prio 3 u32 match ip dst ${ip} flowid 1:3
sudo tc filter add dev ${netif} protocol ip parent 1:0 prio 3 u32 match ip src ${ip} flowid 1:3
echo "latency: ${latency_current}ms with ${rejected_step_current_percent}% traffic rejected to and from ${ip} for ${cycle_duration_seconds} seconds."
# wait for the cycle
sleep ${cycle_duration_seconds}
# increase the step value of latency
((latency_current=${latency_current}+${latency_step_ms}))
done
# increase the step value of drop percent
((rejected_step_current_percent=${rejected_step_current_percent}+${rejected_step_percent}))
# reset latency step to first value
latency_current=${latency_first}
done
remove_rules
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment