Skip to content

Instantly share code, notes, and snippets.

@popmonkey
Last active April 16, 2023 05:20
Show Gist options
  • Save popmonkey/75352f967d9fc5a9e275ef157b54cec7 to your computer and use it in GitHub Desktop.
Save popmonkey/75352f967d9fc5a9e275ef157b54cec7 to your computer and use it in GitHub Desktop.
EdgeOS ready script that tests for WAN connection degradation (via packet loss and latency checks)
#!/bin/sh
#
# USG and EdgeRouter route-test script for failover
#
# uses ping to check latency and packet loss.
# returns zero when within thresholds and non zero (1) when above thresholds
# uses ping, traceroute, and logger
#
# by https://github.com/popmonkey
#
# v0.8.1 2019.10.12 - don't wait for log_traceroute to return failure
# v0.8.0 2019.10.06 - on failure, dump traceroute info
# v0.7.0 2019.10.05 - ping more than one host
# v0.6.2 2019.10.04 - refactored - also checks packetloss
# v0.5.0 2019.10.03 - first working version
#
# this is meant to be used as the test script in the load-balance groups
# e.g.
# group wan_failover {
# interface eth0 {
# route-test {
# count {
# failure 1
# success 1
# }
# type {
# script /config/scripts/network_test.sh
# }
# }
# }
# interface eth2 {
# failover-only
# route-test {
# count {
# failure 1
# success 1
# }
# type {
# script /config/scripts/network_test.sh
# }
# }
# }
# sticky {
# dest-addr enable
# dest-port enable
# source-addr enable
# }
# transition-script /config/scripts/wan-event-report.sh
# }
PING_HOSTS='1.1.1.1 8.8.8.8'
MAX_AVERAGE_PING=50
MAX_PACKET_LOSS=0
PING_COUNT=5
GROUP=${1:-unknown}
IFACE=${2:-eth0}
STATE=${3:-DOWN}
# floating point greater than
fp_gt() {
# NOTE: in bash 0 - true, 1 - false
return $((1 - $(echo "$1 $2" | awk '{print ($1 > $2)}')))
}
# average of n floats (space separated)
fp_avg() {
echo $(echo $@ | awk "{ for (i = 1; i <= NF; i++) s = s+\$i }; END { print s / NF }")
}
# logging function
log() {
logger -t "network_test" -- "[$GROUP : $IFACE ($STATE)] $@"
debug $@
}
debug() {
echo "[$(date)] [$GROUP : $IFACE ($STATE)] $@" #>> /tmp/network_test.log
}
# examine ping
do_ping() {
PACKET_LOSS_RE='[^0-9.]([0-9.]+)% packet loss'
AVERAGE_PING_RE='[0-9.]+\/([0-9.]+)\/[0-9.]+\/[0-9.]'
PINGOUT=$(/bin/ping -c $PING_COUNT -I $IFACE $1)
if [[ $PINGOUT =~ $PACKET_LOSS_RE ]]; then
PACKET_LOSS=${BASH_REMATCH[1]}
fi
if [[ $PINGOUT =~ $AVERAGE_PING_RE ]]; then
AVERAGE_PING=${BASH_REMATCH[1]}
fi
echo "$(echo $PACKET_LOSS | awk '{print $1+0}') $(echo $AVERAGE_PING | awk '{print $1+0}')"
}
# dump traceroute
log_traceroute() {
set -f # turns off globs
log $(/usr/bin/traceroute -rnIi $IFACE -w 1 -q 1 1.1.1.1)
}
LOSSES=""
PINGS=""
for host in $(echo $PING_HOSTS); do
PING_OUT=$(do_ping $host)
debug "$host: $PING_OUT"
LOSSES="$LOSSES $(echo $PING_OUT | awk '{print $1}')"
PINGS="$PINGS $(echo $PING_OUT | awk '{print $2}')"
done
AVG_LOSS=$(fp_avg "$LOSSES")
AVG_PING=$(fp_avg "$PINGS")
if fp_gt $AVG_LOSS $MAX_PACKET_LOSS; then
log "Too much packetloss: $AVG_LOSS% > $MAX_PACKET_LOSS%"
log_traceroute &
exit 1
fi
if fp_gt $AVG_PING $MAX_AVERAGE_PING; then
log "Ping too high: ${AVG_PING}ms > ${MAX_AVERAGE_PING}ms"
log_traceroute &
exit 1
fi
exit 0
@zackramjan
Copy link

looks good! I'm going to try it out as a more comprehensive test instead of the the simple ping

@safwan07
Copy link

safwan07 commented Jul 9, 2021

Can you guys help in using this JSON config on USG?

@danielbald
Copy link

I really appreciate the packet loss detection. I use it with a 10km long microwave link.

transition-script /config/scripts/wan-event-report.sh does this do anything interesting?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment