mwan3: use ip monitor route to detect routing changes

use only committed uci changes for updating routing table

use functions.sh functions rather than uci command line tool
to find interfaces for routing table.

consolidate rtmon_ipv4 and rtmon_ipv6 functions into a single function

Signed-off-by: Aaron Goodman <aaronjg@stanford.edu>
This commit is contained in:
Aaron Goodman
2020-07-25 11:35:09 -04:00
parent 9c1670ed61
commit 39f58789e6
6 changed files with 272 additions and 187 deletions
+5 -14
View File
@@ -145,6 +145,7 @@ start()
config_load mwan3
config_foreach ifup interface
mwan3_rtmon
}
stop()
@@ -154,23 +155,13 @@ stop()
mwan3_lock "command" "mwan3"
uci_toggle_state mwan3 globals enabled "0"
for pid in $(pgrep -f "mwan3rtmon"); do
kill -TERM "$pid" > /dev/null 2>&1
done
for pid in $(pgrep -f "mwan3track"); do
kill -TERM "$pid" > /dev/null 2>&1
done
kill -TERM $(pgrep -f "mwan3rtmon") > /dev/null 2>&1
kill -TERM $(pgrep -f "mwan3track") > /dev/null 2>&1
sleep 1
for pid in $(pgrep -f "mwan3rtmon"); do
kill -KILL "$pid" > /dev/null 2>&1
done
for pid in $(pgrep -f "mwan3track"); do
kill -KILL "$pid" > /dev/null 2>&1
done
kill -KILL $(pgrep -f "mwan3rtmon") > /dev/null 2>&1
kill -KILL $(pgrep -f "mwan3track") > /dev/null 2>&1
config_load mwan3
config_foreach mwan3_track_clean interface
+94 -23
View File
@@ -1,38 +1,109 @@
#!/bin/sh
. /lib/functions.sh
. /lib/functions/network.sh
. /lib/mwan3/mwan3.sh
LOG="logger -t $(basename "$0")[$$] -p"
clean_up() {
$LOG notice "Stopping mwan3rtmon..."
exit 0
mwan3_rtmon_route_handle()
{
config_load mwan3
local section action route_line family tbl device metric tos dst line
local route_device tid
route_line=${1##"Deleted "}
route_family=$2
if [ "$route_family" = "ipv4" ]; then
IP="$IP4"
elif [ "$route_family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
IP="$IP6"
else
return
fi
if [ "$route_line" == "$1" ]; then
action="add"
else
action="del"
fi
# never add default route lines, since this is handled elsewhere
[ -z "${route_line##default*}" ] && return
[ -z "${route_line##::/0*}" ] && return
route_line=${route_line%% linkdown*}
route_line=${route_line%% unreachable*}
mwan3_update_dev_to_table
mwan3_route_line_dev "tid" "$route_line" "$route_family"
handle_route() {
tbl=$($IP route list table $tid)
if [ $action = "add" ]; then
echo "$tbl" | grep -q "^default\|^::/0" || return
else
[ -z "$tbl" ] && return
fi
# check that action needs to be performed. May not need to take action if:
# Got a route update on ipv6 where route is already in the table
# Got a delete event, but table was already flushed
[ $action = "add" ] && [ -z "${tbl##*$route_line*}" ] && return
[ $action = "del" ] && [ -n "${tbl##*$route_line*}" ] && return
network_get_device device "$section"
LOG debug "adjusting route $device: $IP route "$action" table $tid $route_line"
$IP route "$action" table $tid $route_line ||
LOG warn "failed: $IP route $action table $tid $route_line"
}
handle_route_cb(){
let tid++
config_get family "$section" family ipv4
[ "$family" != "$route_family" ] && return
handle_route
}
if [ $action = "add" ]; then
## handle old routes from 'change' or 'replace'
metric=${route_line##*metric }
[ "$metric" = "$route_line" ] && unset metric || metric=${metric%% *}
tos=${route_line##*tos }
[ "$tos" = "$route_line" ] && unset tos || tos=${tos%% *}
dst=${route_line%% *}
grep_line="$dst ${tos:+tos $tos}.*table [0-9].*${metric:+metric $metric}"
$IP route list table all | grep "$grep_line" | while read line; do
tbl=${line##*table }
tbl=${tbl%% *}
[ $tbl -gt $MWAN3_INTERFACE_MAX ] && continue
LOG debug "removing route on ip route change/replace: $line"
$IP route del $line
done
fi
if [ -n "$tid" ]; then
handle_route
else
config_foreach handle_route_cb interface
fi
}
rtchange() {
$LOG info "Detect rtchange event."
}
main() {
local rtmon_interval
trap clean_up TERM
trap rtchange USR1
main()
{
local IP family
config_load mwan3
config_get rtmon_interval globals rtmon_interval '5'
family=$1
[ -z $family ] && family=ipv4
if [ "$family" = ipv6 ]; then
IP="$IP6"
else
IP="$IP4"
fi
mwan3_init
sleep 3
while true; do
$IP monitor route | while read line; do
[ -z "${line##*table*}" ] && continue
LOG debug "handling route update $family $line"
mwan3_lock "service" "mwan3rtmon"
mwan3_rtmon_ipv4 || mwan3_rtmon_ipv6
ret=$?
mwan3_rtmon_route_handle "$line" "$family"
mwan3_unlock "service" "mwan3rtmon"
[ "$ret" = "0" ] || break
[ "$rtmon_interval" = "0" ] && break
sleep "$rtmon_interval" &
wait
done
}
main "$@"