Browse Source

mwan3: improve startup performance; version 2.9.0

improve startup and runtime performance by

1) moving common startup procedures out of hotplug script when called
from mwan3 start
2) reducing calls to iptables to check status of rules
3) consolidating iptables updates and updating with iptables-restore
4) do not wait for kill if nothing was killed
5) running interface hotplug scripts in parallel
6) eliminate operations in hotplug script that check status on every
single interface unnecessarily
7) consolidate how mwan3track makes hotplug calls
8) do not restart mwan3track on connected events

This is a significant refactor, but should not result in any breaking
changes or require users to update their configurations.

version bump to 2.9.0

Signed-off-by: Aaron Goodman <aaronjg@stanford.edu>
lilik-openwrt-22.03
Aaron Goodman 4 years ago
parent
commit
c07f5230be
9 changed files with 722 additions and 572 deletions
  1. +2
    -2
      net/mwan3/Makefile
  2. +59
    -54
      net/mwan3/files/etc/hotplug.d/iface/15-mwan3
  3. +4
    -4
      net/mwan3/files/etc/hotplug.d/iface/16-mwan3-user
  4. +3
    -3
      net/mwan3/files/etc/init.d/mwan3
  5. +11
    -0
      net/mwan3/files/lib/mwan3/common.sh
  6. +432
    -369
      net/mwan3/files/lib/mwan3/mwan3.sh
  7. +96
    -53
      net/mwan3/files/usr/sbin/mwan3
  8. +2
    -1
      net/mwan3/files/usr/sbin/mwan3rtmon
  9. +113
    -86
      net/mwan3/files/usr/sbin/mwan3track

+ 2
- 2
net/mwan3/Makefile View File

@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=mwan3 PKG_NAME:=mwan3
PKG_VERSION:=2.8.12
PKG_RELEASE:=2
PKG_VERSION:=2.9.0
PKG_RELEASE:=1
PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de> PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de>
PKG_LICENSE:=GPL-2.0 PKG_LICENSE:=GPL-2.0


+ 59
- 54
net/mwan3/files/etc/hotplug.d/iface/15-mwan3 View File

@ -4,96 +4,101 @@
. /lib/functions/network.sh . /lib/functions/network.sh
. /lib/mwan3/mwan3.sh . /lib/mwan3/mwan3.sh
. /usr/share/libubox/jshn.sh . /usr/share/libubox/jshn.sh
. /lib/mwan3/common.sh
[ "$ACTION" == "ifup" -o "$ACTION" == "ifdown" ] || exit 1
SCRIPTNAME="mwan3-hotplug"
[ "$ACTION" = "ifup" ] || [ "$ACTION" = "ifdown" ] || [ "$ACTION" = "connected" ] || [ "$ACTION" = "disconnected" ] || exit 1
[ -n "$INTERFACE" ] || exit 2 [ -n "$INTERFACE" ] || exit 2
if [ "$ACTION" == "ifup" ]; then
[ -n "$DEVICE" ] || exit 3
if ( [ "$ACTION" = "ifup" ] || [ "$ACTION" = "connected" ] ) && [ -z "$DEVICE" ]; then
LOG notice "$ACTION called on $INTERFACE with no device set"
exit 3
fi fi
mwan3_lock "$ACTION" "$INTERFACE"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_lock "$ACTION" "$INTERFACE"
config_load mwan3 config_load mwan3
config_get_bool enabled globals 'enabled' '0' config_get_bool enabled globals 'enabled' '0'
[ "${enabled}" -gt 0 ] || { [ "${enabled}" -gt 0 ] || {
mwan3_unlock "$ACTION" "$INTERFACE"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_unlock "$ACTION" "$INTERFACE"
LOG notice "mwan3 hotplug on $INTERFACE not called because globally disabled"
mwan3_flush_conntrack "$INTERFACE" "$ACTION" mwan3_flush_conntrack "$INTERFACE" "$ACTION"
exit 0 exit 0
} }
$IPT4 -S mwan3_hook &>/dev/null || {
mwan3_unlock "$ACTION" "$INTERFACE"
LOG warn "hotplug called on $INTERFACE before mwan3 has been set up"
exit 0
}
mwan3_init mwan3_init
mwan3_set_connected_iptables
mwan3_set_custom_ipset
[ "$MWAN3_STARTUP" = 1 ] || {
mwan3_set_connected_iptables
mwan3_set_custom_ipset
}
if [ "$MWAN3_STARTUP" != 1 ]; then
mwan3_set_user_iface_rules $INTERFACE $DEVICE
fi
config_get initial_state $INTERFACE initial_state "online" config_get initial_state $INTERFACE initial_state "online"
config_get_bool enabled $INTERFACE 'enabled' '0' config_get_bool enabled $INTERFACE 'enabled' '0'
[ "${enabled}" -eq 1 ] || { [ "${enabled}" -eq 1 ] || {
mwan3_unlock "$ACTION" "$INTERFACE"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_unlock "$ACTION" "$INTERFACE"
LOG notice "mwan3 hotplug on $INTERFACE not called because interface disabled"
exit 0 exit 0
} }
if [ "$ACTION" = "ifup" ]; then
config_get family $INTERFACE family ipv4
if [ "$family" = "ipv4" ]; then
ubus call network.interface.${INTERFACE}_4 status &>/dev/null
if [ "$?" -eq "0" ]; then
network_get_ipaddr src_ip ${INTERFACE}_4
else
network_get_ipaddr src_ip ${INTERFACE}
fi
[ -n "$src_ip" ] || src_ip="0.0.0.0"
elif [ "$family" = "ipv6" ]; then
ubus call network.interface.${INTERFACE}_6 status &>/dev/null
if [ "$?" -eq "0" ]; then
network_get_ipaddr6 src_ip ${INTERFACE}_6
else
network_get_ipaddr6 src_ip ${INTERFACE}
fi
[ -n "$src_ip" ] || src_ip="::"
fi
fi
trackpid=$(pgrep -f "mwan3track $INTERFACE ")
if [ "$initial_state" = "offline" ]; then if [ "$initial_state" = "offline" ]; then
json_load "$(ubus call mwan3 status '{"section":"interfaces"}')"
json_select "interfaces"
json_select "${INTERFACE}"
json_get_var running running
json_get_var status status
status=$(cat $MWAN3TRACK_STATUS_DIR/$INTERFACE/STATUS 2>/dev/null || echo unknown)
else else
status=online status=online
running=1
fi fi
$LOG notice "Execute "$ACTION" event on interface $INTERFACE (${DEVICE:-unknown})"
[ -z "$TRUE_INTERFACE" ] && mwan3_get_true_iface TRUE_INTERFACE $INTERFACE
binary_status=$status
[ "$binary_status" = "online" ] || binary_status=offline
LOG notice "Execute "$ACTION" event on interface $INTERFACE (${DEVICE:-unknown})"
case "$ACTION" in case "$ACTION" in
ifup)
mwan3_set_general_rules
mwan3_set_general_iptables
ifup|connected)
mwan3_create_iface_iptables $INTERFACE $DEVICE mwan3_create_iface_iptables $INTERFACE $DEVICE
mwan3_create_iface_rules $INTERFACE $DEVICE mwan3_create_iface_rules $INTERFACE $DEVICE
mwan3_create_iface_route $INTERFACE $DEVICE mwan3_create_iface_route $INTERFACE $DEVICE
if [ "${running}" -eq 1 ] && [ "${status}" = "online" ]; then
$LOG notice "Starting tracker on interface $INTERFACE (${DEVICE:-unknown})"
mwan3_set_iface_hotplug_state $INTERFACE "online"
mwan3_track $INTERFACE $DEVICE "online" "$src_ip"
[ "$MWAN3_STARTUP" != 1 ] && mwan3_add_non_default_iface_route $INTERFACE $DEVICE
mwan3_set_iface_hotplug_state $INTERFACE "$binary_status"
mwan3_get_src_ip src_ip "$TRUE_INTERFACE"
if [ -n "${trackpid}" ]; then
device_pid=$(pgrep -f "mwan3track $INTERFACE $DEVICE ")
if [ "$device_pid" = "$trackpid" ]; then
[ "$ACTION" = ifup ] && kill -USR2 "$trackpid"
else
mwan3_track $INTERFACE $DEVICE "$binary_status" "$src_ip"
LOG notice "Restarted tracker [$!] on interface $INTERFACE (${DEVICE:-unknown})"
fi
else else
$LOG notice "Starting tracker on interface $INTERFACE (${DEVICE:-unknown})"
mwan3_set_iface_hotplug_state $INTERFACE "offline"
mwan3_track $INTERFACE $DEVICE "offline" "$src_ip"
mwan3_track $INTERFACE $DEVICE "$binary_status" "$src_ip"
LOG notice "Started tracker [$!] on interface $INTERFACE (${DEVICE:-unknown})"
fi fi
mwan3_set_policies_iptables
mwan3_set_user_rules
[ "$MWAN3_STARTUP" != 1 ] && [ "$binary_status" == "online" ] && mwan3_set_policies_iptables
;; ;;
ifdown)
ifdown|disconnected)
mwan3_set_iface_hotplug_state $INTERFACE "offline" mwan3_set_iface_hotplug_state $INTERFACE "offline"
mwan3_delete_iface_ipset_entries $INTERFACE mwan3_delete_iface_ipset_entries $INTERFACE
mwan3_track_signal $INTERFACE $DEVICE
mwan3_delete_iface_rules $INTERFACE
mwan3_delete_iface_route $INTERFACE
mwan3_delete_iface_iptables $INTERFACE
if [ "$ACTION" = "ifdown" ]; then
[ -n "$trackpid" ] && kill -USR1 "$trackpid"
fi
mwan3_set_policies_iptables mwan3_set_policies_iptables
mwan3_set_user_rules
;; ;;
esac esac
mwan3_unlock "$ACTION" "$INTERFACE"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_unlock "$ACTION" "$INTERFACE"
exit 0 exit 0

+ 4
- 4
net/mwan3/files/etc/hotplug.d/iface/16-mwan3-user View File

@ -4,22 +4,22 @@
. /lib/functions.sh . /lib/functions.sh
. /lib/mwan3/mwan3.sh . /lib/mwan3/mwan3.sh
mwan3_lock "$ACTION" "user"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_lock "$ACTION" "$DEVICE-user"
config_load mwan3 config_load mwan3
config_get_bool enabled globals 'enabled' '0' config_get_bool enabled globals 'enabled' '0'
[ "${enabled}" -gt 0 ] || { [ "${enabled}" -gt 0 ] || {
mwan3_unlock "$ACTION" "user"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_unlock "$ACTION" "$DEVICE-user"
exit 0 exit 0
} }
config_get_bool enabled "$INTERFACE" enabled 0 config_get_bool enabled "$INTERFACE" enabled 0
[ "${enabled}" -eq 1 ] || { [ "${enabled}" -eq 1 ] || {
mwan3_unlock "$ACTION" "user"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_unlock "$ACTION" "$DEVICE-user"
exit 0 exit 0
} }
mwan3_unlock "$ACTION" "user"
[ "$MWAN3_STARTUP" = 1 ] || mwan3_unlock "$ACTION" "$DEVICE-user"
env -i ACTION="$ACTION" INTERFACE="$INTERFACE" DEVICE="$DEVICE" \ env -i ACTION="$ACTION" INTERFACE="$INTERFACE" DEVICE="$DEVICE" \
/bin/sh /etc/mwan3.user /bin/sh /etc/mwan3.user


+ 3
- 3
net/mwan3/files/etc/init.d/mwan3 View File

@ -5,8 +5,9 @@ USE_PROCD=1
boot() { boot() {
. /lib/config/uci.sh . /lib/config/uci.sh
uci_toggle_state mwan3 globals enabled "1"
mwan3_boot=1
# disabled until mwan3 start runs so hotplug scripts
# do not start prematurely
uci_toggle_state mwan3 globals enabled "0"
rc_procd start_service rc_procd start_service
} }
@ -20,7 +21,6 @@ reload_service() {
} }
start_service() { start_service() {
[ -n "${mwan3_boot}" ] && return 0
/usr/sbin/mwan3 start 1000>&- /usr/sbin/mwan3 start 1000>&-
} }


+ 11
- 0
net/mwan3/files/lib/mwan3/common.sh View File

@ -4,3 +4,14 @@ get_uptime() {
local uptime=$(cat /proc/uptime) local uptime=$(cat /proc/uptime)
echo "${uptime%%.*}" echo "${uptime%%.*}"
} }
SCRIPTNAME="$(basename "$0")"
LOG()
{
local facility=$1; shift
# in development, we want to show 'debug' level logs
# when this release is out of beta, the comment in the line below
# should be removed
[ "$facility" = "debug" ] && return
logger -t "$SCRIPTNAME[$$]" -p $facility "$*"
}

+ 432
- 369
net/mwan3/files/lib/mwan3/mwan3.sh
File diff suppressed because it is too large
View File


+ 96
- 53
net/mwan3/files/usr/sbin/mwan3 View File

@ -4,6 +4,7 @@
. /usr/share/libubox/jshn.sh . /usr/share/libubox/jshn.sh
. /lib/functions/network.sh . /lib/functions/network.sh
. /lib/mwan3/mwan3.sh . /lib/mwan3/mwan3.sh
. /lib/mwan3/common.sh
help() help()
{ {
@ -37,52 +38,64 @@ ifdown()
ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface
kill $(pgrep -f "mwan3track $1 $2") &> /dev/null
kill $(pgrep -f "mwan3track $1 ") &> /dev/null
mwan3_track_clean $1 mwan3_track_clean $1
} }
ifup() ifup()
{ {
local device enabled up l3_device status
mwan3_lock "command" "mwan3"
config_load mwan3
config_get_bool enabled globals 'enabled' 0
[ ${enabled} -gt 0 ] || {
echo "The service mwan3 is global disabled."
echo "Please execute \"/etc/init.d/mwan3 start\" first."
mwan3_unlock "command" "mwan3"
exit 1
}
local device enabled up l3_device status interface true_iface
if [ -z "$1" ]; then if [ -z "$1" ]; then
echo "Expecting interface. Usage: mwan3 ifup <interface>" echo "Expecting interface. Usage: mwan3 ifup <interface>"
mwan3_unlock "command" "mwan3"
exit 0 exit 0
fi fi
if [ -n "$2" ]; then if [ -n "$2" ]; then
echo "Too many arguments. Usage: mwan3 ifup <interface>" echo "Too many arguments. Usage: mwan3 ifup <interface>"
mwan3_unlock "command" "mwan3"
exit 0 exit 0
fi fi
config_get enabled "$1" enabled 0
mwan3_unlock "command" "mwan3"
interface=$1
if [ "${MWAN3_STARTUP}" != 1 ]; then
# It is not necessary to obtain a lock here, because it is obtained in the hotplug
# script, but we still want to do the check to print a useful error message
config_load mwan3
config_get_bool enabled globals 'enabled' 0
[ ${enabled} -gt 0 ] || {
echo "The service mwan3 is global disabled."
echo "Please execute \"/etc/init.d/mwan3 start\" first."
exit 1
}
else
enabled=1
fi
mwan3_get_true_iface true_iface $interface
status=$(ubus -S call network.interface.$true_iface status)
status=$(ubus -S call network.interface.$1 status)
[ -n "$status" ] && { [ -n "$status" ] && {
json_load "$status" json_load "$status"
json_get_vars up l3_device json_get_vars up l3_device
} }
hotplug_startup()
{
MWAN3_STARTUP=$MWAN3_STARTUP ACTION=ifup INTERFACE=$interface DEVICE=$l3_device TRUE_INTERFACE=$true_iface sh /etc/hotplug.d/iface/15-mwan3
MWAN3_STARTUP=$MWAN3_STARTUP ACTION=ifup INTERFACE=$interface DEVICE=$l3_device TRUE_INTERFACE=$true_iface sh /etc/hotplug.d/iface/16-mwan3-user
}
if [ "$up" != "1" ] || [ -z "$l3_device" ] || [ "$enabled" != "1" ]; then
return
fi
if [ "$up" = "1" ] \
&& [ -n "$l3_device" ] \
&& [ "$enabled" = "1" ]; then
ACTION=ifup INTERFACE=$1 DEVICE=$l3_device /sbin/hotplug-call iface
if [ "${MWAN3_STARTUP}" = 1 ]; then
hotplug_startup &
hotplug_pids="$hotplug_pids $!"
else
hotplug_startup
fi fi
} }
interfaces() interfaces()
@ -137,58 +150,78 @@ status()
start() start()
{ {
local enabled
local enabled hotplug_pids MWAN3_STARTUP
MWAN3_STARTUP=1
mwan3_lock "command" "mwan3" mwan3_lock "command" "mwan3"
uci_toggle_state mwan3 globals enabled "1" uci_toggle_state mwan3 globals enabled "1"
mwan3_unlock "command" "mwan3"
config_load mwan3 config_load mwan3
mwan3_update_iface_to_table
mwan3_set_connected_iptables
mwan3_set_custom_ipset
mwan3_set_general_rules
mwan3_set_general_iptables
config_foreach ifup interface config_foreach ifup interface
wait $hotplug_pids
mwan3_add_all_nondefault_routes
mwan3_set_policies_iptables
mwan3_set_user_rules
mwan3_unlock "command" "mwan3"
mwan3_rtmon mwan3_rtmon
unset MWAN3_STARTUP
} }
stop() stop()
{ {
local ipset route rule table IP IPT pid
local ipset rule IP IPTR IPT kill_pid family table tid
mwan3_lock "command" "mwan3" mwan3_lock "command" "mwan3"
uci_toggle_state mwan3 globals enabled "0" uci_toggle_state mwan3 globals enabled "0"
kill -TERM $(pgrep -f "mwan3rtmon") > /dev/null 2>&1
kill -TERM $(pgrep -f "mwan3track") > /dev/null 2>&1
{
kill -TERM $(pgrep -f "mwan3rtmon") > /dev/null 2>&1
kill -TERM $(pgrep -f "mwan3track") > /dev/null 2>&1
sleep 1
kill -KILL $(pgrep -f "mwan3rtmon") > /dev/null 2>&1
kill -KILL $(pgrep -f "mwan3track") > /dev/null 2>&1
sleep 1
kill -KILL $(pgrep -f "mwan3rtmon") > /dev/null 2>&1
kill -KILL $(pgrep -f "mwan3track") > /dev/null 2>&1
} &
kill_pid=$!
config_load mwan3 config_load mwan3
config_foreach mwan3_track_clean interface config_foreach mwan3_track_clean interface
for IP in "$IP4" "$IP6"; do
[ "$IP" = "$IP6" ] && [ $NO_IPV6 -ne 0 ] && continue
for route in $(seq 1 $MWAN3_INTERFACE_MAX); do
$IP route flush table $route &> /dev/null
for family in ipv4 ipv6; do
if [ "$family" = "ipv4" ]; then
IPT="$IPT4"
IPTR="$IPT4R"
IP="$IP4"
elif [ "$family" = "ipv6" ]; then
[ $NO_IPV6 -ne 0 ] && continue
IPT="$IPT6"
IPTR="$IPT6R"
IP="$IP6"
fi
for tid in $(ip route list table all | sed -ne 's/.*table \([0-9]\+\).*/\1/p'|sort -u); do
[ $tid -gt $MWAN3_INTERFACE_MAX ] && continue
$IP route flush table $tid &> /dev/null
done done
for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
$IP rule del pref $rule &> /dev/null $IP rule del pref $rule &> /dev/null
done done
done
for IPT in "$IPT4" "$IPT6"; do
[ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue
$IPT -D PREROUTING -j mwan3_hook &> /dev/null
$IPT -D OUTPUT -j mwan3_hook &> /dev/null
for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
$IPT -F $table &> /dev/null
done
for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
$IPT -X $table &> /dev/null
done
table="$($IPT -S)"
{
echo "*mangle";
[ -z "${table##*PREROUTING -j mwan3_hook*}" ] && echo "-D PREROUTING -j mwan3_hook"
[ -z "${table##*OUTPUT -j mwan3_hook*}" ] && echo "-D OUTPUT -j mwan3_hook"
echo "$table" | awk '{print "-F "$2}' | grep mwan3 | sort -u
echo "$table" | awk '{print "-X "$2}' | grep mwan3 | sort -u
echo "COMMIT"
} | $IPTR
done done
for ipset in $($IPS -n list | grep mwan3_); do for ipset in $($IPS -n list | grep mwan3_); do
@ -199,9 +232,19 @@ stop()
$IPS -q destroy $ipset $IPS -q destroy $ipset
done done
if ! pgrep -f "mwan3track" >/dev/null && ! pgrep -f "mwan3rtmon" >/dev/null; then
# mwan3track has already exited, no need to send
# TERM signal
kill $kill_pid 2>/dev/null
else
# mwan3track has not exited, wait for the killer
# to do its work
wait $kill_pid
fi
rm -rf $MWAN3_STATUS_DIR $MWAN3TRACK_STATUS_DIR
mwan3_unlock "command" "mwan3" mwan3_unlock "command" "mwan3"
rm -rf $MWAN3_STATUS_DIR $MWAN3TRACK_STATUS_DIR
} }
restart() { restart() {


+ 2
- 1
net/mwan3/files/usr/sbin/mwan3rtmon View File

@ -1,8 +1,9 @@
#!/bin/sh #!/bin/sh
. /lib/functions.sh . /lib/functions.sh
. /lib/functions/network.sh . /lib/functions/network.sh
. /lib/mwan3/mwan3.sh . /lib/mwan3/mwan3.sh
. /lib/mwan3/common.sh
mwan3_rtmon_route_handle() mwan3_rtmon_route_handle()
{ {


+ 113
- 86
net/mwan3/files/usr/sbin/mwan3track View File

@ -3,60 +3,107 @@
. /lib/functions.sh . /lib/functions.sh
. /lib/mwan3/common.sh . /lib/mwan3/common.sh
LOG="logger -t $(basename "$0")[$$] -p"
INTERFACE="" INTERFACE=""
DEVICE="" DEVICE=""
PING="/bin/ping" PING="/bin/ping"
IFDOWN_EVENT=0 IFDOWN_EVENT=0
IFUP_EVENT=0
clean_up() { clean_up() {
$LOG notice "Stopping mwan3track for interface \"${INTERFACE}\""
LOG notice "Stopping mwan3track for interface \"${INTERFACE}\""
exit 0 exit 0
} }
if_down() { if_down() {
$LOG info "Detect ifdown event on interface ${INTERFACE} (${DEVICE})"
LOG info "Detect ifdown event on interface ${INTERFACE} (${DEVICE})"
IFDOWN_EVENT=1 IFDOWN_EVENT=1
} }
if_up() {
LOG info "Detect ifup event on interface ${INTERFACE} (${DEVICE})"
IFUP_EVENT=1
}
validate_track_method() { validate_track_method() {
case "$1" in case "$1" in
ping) ping)
command -v ping 1>/dev/null 2>&1 || {
$LOG warn "Missing ping. Please install iputils-ping package or enable ping util and recompile busybox."
[ -x "$PING" ] || {
LOG warn "Missing ping. Please enable ping util and recompile busybox."
return 1 return 1
} }
;; ;;
arping) arping)
command -v arping 1>/dev/null 2>&1 || { command -v arping 1>/dev/null 2>&1 || {
$LOG warn "Missing arping. Please install iputils-arping package."
LOG warn "Missing arping. Please install iputils-arping package."
return 1 return 1
} }
;; ;;
httping) httping)
command -v httping 1>/dev/null 2>&1 || { command -v httping 1>/dev/null 2>&1 || {
$LOG warn "Missing httping. Please install httping package."
LOG warn "Missing httping. Please install httping package."
return 1 return 1
} }
[ -n "$2" -a "$2" != "0.0.0.0" -a "$2" != "::" ] || { [ -n "$2" -a "$2" != "0.0.0.0" -a "$2" != "::" ] || {
$LOG warn "Cannot determine source IP for the interface which is required by httping."
LOG warn "Cannot determine source IP for the interface which is required by httping."
return 1 return 1
} }
;; ;;
nping-*) nping-*)
command -v nping 1>/dev/null 2>&1 || { command -v nping 1>/dev/null 2>&1 || {
$LOG warn "Missing nping. Please install nping package."
LOG warn "Missing nping. Please install nping package."
return 1 return 1
} }
;; ;;
*) *)
$LOG warn "Unsupported tracking method: $track_method"
LOG warn "Unsupported tracking method: $track_method"
return 2 return 2
;; ;;
esac esac
} }
disconnected() {
echo "offline" > /var/run/mwan3track/$INTERFACE/STATUS
echo "$(get_uptime)" > /var/run/mwan3track/$INTERFACE/OFFLINE
echo "0" > /var/run/mwan3track/$INTERFACE/ONLINE
score=0
[ "$1" == 1 ] && return
LOG notice "Interface $INTERFACE ($DEVICE) is offline"
env -i ACTION="disconnected" INTERFACE="$INTERFACE" DEVICE="$DEVICE" /sbin/hotplug-call iface
}
connected() {
echo "online" > /var/run/mwan3track/$INTERFACE/STATUS
echo "0" > /var/run/mwan3track/$INTERFACE/OFFLINE
echo "$(get_uptime)" > /var/run/mwan3track/$INTERFACE/ONLINE
host_up_count=0
lost=0
turn=0
loss=0
[ "$1" == 1 ] && return
LOG notice "Interface $INTERFACE ($DEVICE) is online"
env -i ACTION="connected" INTERFACE="$INTERFACE" DEVICE="$DEVICE" /sbin/hotplug-call iface
}
firstconnect() {
if [ "$STATUS" = "offline" ]; then
disconnected 1
else
connected 1
fi
}
update_status() {
local status track_ip
track_ip=$1
status=$2
echo "$1" > /var/run/mwan3track/$INTERFACE/TRACK_${track_ip}
[ -z "$3" ] && return
echo "$3" > /var/run/mwan3track/$INTERFACE/LATENCY_${track_ip}
echo "$4" > /var/run/mwan3track/$INTERFACE/LOSS_${track_ip}
}
main() { main() {
local reliability count timeout interval failure_interval local reliability count timeout interval failure_interval
local recovery_interval down up size local recovery_interval down up size
@ -70,64 +117,49 @@ main() {
DEVICE=$2 DEVICE=$2
STATUS=$3 STATUS=$3
SRC_IP=$4 SRC_IP=$4
mkdir -p /var/run/mwan3track/$1
mkdir -p /var/run/mwan3track/$INTERFACE
trap clean_up TERM trap clean_up TERM
trap if_down USR1 trap if_down USR1
trap if_up USR2
config_load mwan3 config_load mwan3
config_get track_method $1 track_method ping
config_get_bool httping_ssl $1 httping_ssl 0
config_get track_method $INTERFACE track_method ping
config_get_bool httping_ssl $INTERFACE httping_ssl 0
validate_track_method $track_method $SRC_IP || { validate_track_method $track_method $SRC_IP || {
track_method=ping track_method=ping
if validate_track_method $track_method; then if validate_track_method $track_method; then
$LOG warn "Using ping to track interface $INTERFACE avaliability"
LOG warn "Using ping to track interface $INTERFACE avaliability"
else else
$LOG err "No track method avaliable"
LOG err "No track method avaliable"
exit 1 exit 1
fi fi
} }
config_get reliability $1 reliability 1
config_get count $1 count 1
config_get timeout $1 timeout 4
config_get interval $1 interval 10
config_get down $1 down 5
config_get up $1 up 5
config_get size $1 size 56
config_get max_ttl $1 max_ttl 60
config_get failure_interval $1 failure_interval $interval
config_get_bool keep_failure_interval $1 keep_failure_interval 0
config_get recovery_interval $1 recovery_interval $interval
config_get_bool check_quality $1 check_quality 0
config_get failure_latency $1 failure_latency 1000
config_get recovery_latency $1 recovery_latency 500
config_get failure_loss $1 failure_loss 40
config_get recovery_loss $1 recovery_loss 10
config_get reliability $INTERFACE reliability 1
config_get count $INTERFACE count 1
config_get timeout $INTERFACE timeout 4
config_get interval $INTERFACE interval 10
config_get down $INTERFACE down 5
config_get up $INTERFACE up 5
config_get size $INTERFACE size 56
config_get max_ttl $INTERFACE max_ttl 60
config_get failure_interval $INTERFACE failure_interval $interval
config_get_bool keep_failure_interval $INTERFACE keep_failure_interval 0
config_get recovery_interval $INTERFACE recovery_interval $interval
config_get_bool check_quality $INTERFACE check_quality 0
config_get failure_latency $INTERFACE failure_latency 1000
config_get recovery_latency $INTERFACE recovery_latency 500
config_get failure_loss $INTERFACE failure_loss 40
config_get recovery_loss $INTERFACE recovery_loss 10
local score=$(($down+$up)) local score=$(($down+$up))
local track_ips=$(echo $* | cut -d ' ' -f 5-99) local track_ips=$(echo $* | cut -d ' ' -f 5-99)
local host_up_count=0 local host_up_count=0
local lost=0 local lost=0
local sleep_time=0
local turn=0 local turn=0
local result
local ping_protocol=4 local ping_protocol=4
local ping_result
local ping_result_raw
local ping_status
local loss=0
local latency=0
local sleep_time result ping_result ping_result_raw ping_status loss latency
if [ "$STATUS" = "offline" ]; then
echo "offline" > /var/run/mwan3track/$1/STATUS
echo "0" > /var/run/mwan3track/$1/ONLINE
echo "$(get_uptime)" > /var/run/mwan3track/$1/OFFLINE
score=0
else
echo "online" > /var/run/mwan3track/$1/STATUS
echo "0" > /var/run/mwan3track/$1/OFFLINE
echo "$(get_uptime)" > /var/run/mwan3track/$1/ONLINE
env -i ACTION="connected" INTERFACE="$1" DEVICE="$2" /sbin/hotplug-call iface
fi
firstconnect
while true; do while true; do
sleep_time=$interval sleep_time=$interval
@ -139,16 +171,16 @@ main() {
# pinging IPv6 hosts with an interface is troublesome # pinging IPv6 hosts with an interface is troublesome
# https://bugs.openwrt.org/index.php?do=details&task_id=2897 # https://bugs.openwrt.org/index.php?do=details&task_id=2897
# so get the IP address of the interface and use that instead # so get the IP address of the interface and use that instead
if echo $track_ip | grep -q ':'; then
ADDR=$(ip -6 addr ls dev "$DEVICE" | sed -ne '/\/128/d' -e 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p' | head -n1)
[ -z "$ADDR" ] && ADDR=$(ip -6 addr ls dev "$DEVICE" | sed -ne 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p')
if [ -z ${track_ip##*:*} ]; then
ping_protocol=6 ping_protocol=6
else
unset SRC_IP
fi fi
if [ $check_quality -eq 0 ]; then if [ $check_quality -eq 0 ]; then
$PING -$ping_protocol -I ${ADDR:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null
$PING -$ping_protocol -I ${SRC_IP:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null
result=$? result=$?
else else
ping_result_raw="$($PING -$ping_protocol -I ${ADDR:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null)"
ping_result_raw="$($PING -$ping_protocol -I ${SRC_IP:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null)"
ping_status=$? ping_status=$?
ping_result=$(echo "$ping_result_raw" | tail -n2) ping_result=$(echo "$ping_result_raw" | tail -n2)
loss="$(echo "$ping_result" | grep "packet loss" | cut -d "," -f3 | awk '{print $1}' | sed -e 's/%//')" loss="$(echo "$ping_result" | grep "packet loss" | cut -d "," -f3 | awk '{print $1}' | sed -e 's/%//')"
@ -188,42 +220,40 @@ main() {
if [ $check_quality -eq 0 ]; then if [ $check_quality -eq 0 ]; then
if [ $result -eq 0 ]; then if [ $result -eq 0 ]; then
let host_up_count++ let host_up_count++
echo "up" > /var/run/mwan3track/$1/TRACK_${track_ip}
update_status "$track_ip" "up"
if [ $score -le $up ]; then if [ $score -le $up ]; then
$LOG info "Check ($track_method) success for target \"$track_ip\" on interface $1 ($2)"
LOG info "Check ($track_method) success for target \"$track_ip\" on interface $INTERFACE ($DEVICE). Current score: $score"
fi fi
else else
let lost++ let lost++
echo "down" > /var/run/mwan3track/$1/TRACK_${track_ip}
update_status "$track_ip" "down"
if [ $score -gt $up ]; then if [ $score -gt $up ]; then
$LOG info "Check ($track_method) failed for target \"$track_ip\" on interface $1 ($2)"
LOG info "Check ($track_method) failed for target \"$track_ip\" on interface $INTERFACE ($DEVICE). Current score: $score"
fi fi
fi fi
else else
if [ "$loss" -ge "$failure_loss" -o "$latency" -ge "$failure_latency" ]; then if [ "$loss" -ge "$failure_loss" -o "$latency" -ge "$failure_latency" ]; then
let lost++ let lost++
echo "down" > /var/run/mwan3track/$1/TRACK_${track_ip}
echo "$latency" > /var/run/mwan3track/$1/LATENCY_${track_ip}
echo "$loss" > /var/run/mwan3track/$1/LOSS_${track_ip}
update_status "$track_ip" "down" $latency $loss
if [ $score -gt $up ]; then if [ $score -gt $up ]; then
$LOG info "Check (${track_method}: latency=${latency}ms loss=${loss}%) failed for target \"$track_ip\" on interface $1 ($2)"
LOG info "Check (${track_method}: latency=${latency}ms loss=${loss}%) failed for target \"$track_ip\" on interface $INTERFACE ($DEVICE). Current score: $score"
fi fi
elif [ "$loss" -le "$recovery_loss" -a "$latency" -le "$recovery_latency" ]; then elif [ "$loss" -le "$recovery_loss" -a "$latency" -le "$recovery_latency" ]; then
let host_up_count++ let host_up_count++
echo "up" > /var/run/mwan3track/$1/TRACK_${track_ip}
echo "$latency" > /var/run/mwan3track/$1/LATENCY_${track_ip}
echo "$loss" > /var/run/mwan3track/$1/LOSS_${track_ip}
update_status "$track_ip" "up" $latency $loss
if [ $score -le $up ]; then if [ $score -le $up ]; then
$LOG info "Check (${track_method}: latency=${latency}ms loss=${loss}%) success for target \"$track_ip\" on interface $1 ($2)"
LOG info "Check (${track_method}: latency=${latency}ms loss=${loss}%) success for target \"$track_ip\" on interface $INTERFACE ($DEVICE). Current score: $score"
fi fi
else else
echo "skipped" > /var/run/mwan3track/$1/TRACK_${track_ip}
echo "skipped" > /var/run/mwan3track/$INTERFACE/TRACK_${track_ip}
fi fi
fi fi
else else
echo "skipped" > /var/run/mwan3track/$1/TRACK_${track_ip}
echo "skipped" > /var/run/mwan3track/$INTERFACE/TRACK_${track_ip}
fi fi
done done
@ -240,53 +270,50 @@ main() {
fi fi
if [ $score -eq $up ]; then if [ $score -eq $up ]; then
echo "offline" > /var/run/mwan3track/$1/STATUS
env -i ACTION=ifdown INTERFACE=$1 DEVICE=$2 /sbin/hotplug-call iface
disconnected
score=0 score=0
fi fi
else else
if [ $score -lt $(($down+$up)) ] && [ $lost -gt 0 ]; then if [ $score -lt $(($down+$up)) ] && [ $lost -gt 0 ]; then
$LOG info "Lost $(($lost*$count)) ping(s) on interface $1 ($2)"
LOG info "Lost $(($lost*$count)) ping(s) on interface $INTERFACE ($DEVICE). Current score: $score"
fi fi
let score++ let score++
lost=0 lost=0
if [ $score -gt $up ]; then if [ $score -gt $up ]; then
echo "online" > /var/run/mwan3track/$1/STATUS
echo "online" > /var/run/mwan3track/$INTERFACE/STATUS
score=$(($down+$up)) score=$(($down+$up))
elif [ $score -le $up ]; then elif [ $score -le $up ]; then
sleep_time=$recovery_interval sleep_time=$recovery_interval
fi fi
if [ $score -eq $up ]; then if [ $score -eq $up ]; then
$LOG notice "Interface $1 ($2) is online"
echo "online" > /var/run/mwan3track/$1/STATUS
env -i ACTION=ifup INTERFACE=$1 DEVICE=$2 /sbin/hotplug-call iface
exit 0
connected $INTERFACE $DEVICE
fi fi
fi fi
let turn++ let turn++
mkdir -p "/var/run/mwan3track/${1}" mkdir -p "/var/run/mwan3track/${1}"
echo "${lost}" > /var/run/mwan3track/$1/LOST
echo "${score}" > /var/run/mwan3track/$1/SCORE
echo "${turn}" > /var/run/mwan3track/$1/TURN
echo "$(get_uptime)" > /var/run/mwan3track/$1/TIME
echo "${lost}" > /var/run/mwan3track/$INTERFACE/LOST
echo "${score}" > /var/run/mwan3track/$INTERFACE/SCORE
echo "${turn}" > /var/run/mwan3track/$INTERFACE/TURN
echo "$(get_uptime)" > /var/run/mwan3track/$INTERFACE/TIME
host_up_count=0 host_up_count=0
sleep "${sleep_time}" & sleep "${sleep_time}" &
wait wait
if [ "${IFDOWN_EVENT}" -eq 1 ]; then if [ "${IFDOWN_EVENT}" -eq 1 ]; then
echo "offline" > /var/run/mwan3track/$1/STATUS
echo "$(get_uptime)" > /var/run/mwan3track/$1/OFFLINE
echo "0" > /var/run/mwan3track/$1/ONLINE
$LOG notice "Interface $1 ($2) is offline"
env -i ACTION="disconnected" INTERFACE="$1" DEVICE="$2" /sbin/hotplug-call iface
score=0
LOG debug "Register ifdown event on interface ${INTERFACE} (${DEVICE})"
disconnected 1
IFDOWN_EVENT=0 IFDOWN_EVENT=0
fi fi
if [ "${IFUP_EVENT}" -eq 1 ]; then
LOG debug "Register ifup event on interface ${INTERFACE} (${DEVICE})"
firstconnect
IFUP_EVENT=0
fi
done done
} }


Loading…
Cancel
Save