mirror of
https://github.com/novatiq/packages.git
synced 2026-04-30 07:28:39 +01:00
mwan3: improvements to route creation
handle creation of routing tables in mwan3rtmon to avoid race conditions and potentially missing routes handle ipv6 routes that have expiry update directly connected ipset when routes are added or deleted add fall through rules so that the default routing table is not used if no rule in the interface-specific routing table matches add option to comply with mwan3 source based routing get default route parameters from main routing table Signed-off-by: Aaron Goodman <aaronjg@stanford.edu>
This commit is contained in:
@@ -5,81 +5,139 @@
|
||||
. /lib/mwan3/mwan3.sh
|
||||
. /lib/mwan3/common.sh
|
||||
|
||||
trap_with_arg()
|
||||
{
|
||||
func="$1" ; shift
|
||||
pid="$1" ; shift
|
||||
for sig ; do
|
||||
# shellcheck disable=SC2064
|
||||
trap "$func $sig $pid" "$sig"
|
||||
done
|
||||
}
|
||||
|
||||
func_trap()
|
||||
{
|
||||
kill -${1} ${2} 2>/dev/null
|
||||
}
|
||||
|
||||
mwan3_add_all_routes()
|
||||
{
|
||||
local tid IP IPT route_line family active_tbls tid initial_state
|
||||
local ipv=$1
|
||||
|
||||
add_active_tbls()
|
||||
{
|
||||
let tid++
|
||||
config_get family "$1" family ipv4
|
||||
config_get initial_state "$1" initial_state "online"
|
||||
[ "$family" != "$ipv" ] && return
|
||||
if [ "$initial_state" = "online" ] && $IPT -S "mwan3_iface_in_$1" &> /dev/null; then
|
||||
active_tbls="$active_tbls${tid} "
|
||||
fi
|
||||
}
|
||||
|
||||
add_route()
|
||||
{
|
||||
let tid++
|
||||
[ -n "${active_tbls##* $tid *}" ] && return
|
||||
$IP route add table $tid $route_line ||
|
||||
LOG warn "failed to add $route_line to table $tid"
|
||||
}
|
||||
|
||||
mwan3_update_dev_to_table
|
||||
[ "$ipv" = "ipv6" ] && [ $NO_IPV6 -ne 0 ] && return
|
||||
if [ "$ipv" = "ipv4" ]; then
|
||||
IP="$IP4"
|
||||
IPT="$IPT4"
|
||||
elif [ "$ipv" = "ipv6" ]; then
|
||||
IP="$IP6"
|
||||
IPT="$IPT6"
|
||||
fi
|
||||
tid=0
|
||||
active_tbls=" "
|
||||
config_foreach add_active_tbls interface
|
||||
[ $active_tbls = " " ] && return
|
||||
mwan3_get_routes | while read -r route_line; do
|
||||
mwan3_route_line_dev "tid" "$route_line" "$ipv"
|
||||
if [ -n "$tid" ] && [ -z "${active_tbls##* $tid *}" ]; then
|
||||
$IP route add table $tid $route_line
|
||||
elif [ -n "${route_line##default*}" ] && [ -n "${route_line##fe80::/64*}" ]; then
|
||||
config_foreach add_route interface
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
mwan3_rtmon_route_handle()
|
||||
{
|
||||
config_load mwan3
|
||||
local section action route_line family tbl device metric tos dst line tid
|
||||
local action route_line family tbl device line route_line_exp tid source_routing
|
||||
|
||||
route_line=${1##"Deleted "}
|
||||
route_family=$2
|
||||
|
||||
config_get_boolean source_routing globals source_routing 0
|
||||
[ $source_routing -eq 0 ] && unset source_routing
|
||||
|
||||
if [ "$route_line" = "$1" ]; then
|
||||
action="replace"
|
||||
route_line_exp="s/expires \([0-9]\+\)sec//;s/error [0-9]\+//; ${source_routing:+s/default\(.*\) from [^ ]*/default\1/}"
|
||||
$IPS -! add mwan3_connected_${route_family##ip} ${route_line%% *}
|
||||
else
|
||||
action="del"
|
||||
route_line_exp="s/expires [0-9]\+sec//;s/error [0-9]\+//; ${source_routing:+s/default\(.*\) from [^ ]*/default\1/}"
|
||||
mwan3_set_connected_${route_family}
|
||||
fi
|
||||
|
||||
if [ "$route_family" = "ipv4" ]; then
|
||||
IP="$IP4"
|
||||
elif [ "$route_family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
|
||||
IP="$IP6"
|
||||
route_line=$(echo "$route_line" | sed "$route_line_exp")
|
||||
else
|
||||
LOG warn "route update called with invalid family - $route_family"
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$route_line" == "$1" ]; then
|
||||
action="add"
|
||||
else
|
||||
action="del"
|
||||
# don't try to add routes when link has gone down
|
||||
if [ -z "${route_line##linkdown*}" ]; then
|
||||
LOG debug "not adding route due to linkdown - skipping $route_line"
|
||||
return
|
||||
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
|
||||
local iface=$1
|
||||
tbl=$($IP route list table $tid 2>/dev/null)$'\n'
|
||||
|
||||
[ $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"
|
||||
if [ "$(cat /var/run/mwan3track/$iface/STATUS)" != "online" ]; then
|
||||
LOG debug "interface $iface is offline - skipping $route_line";
|
||||
return
|
||||
fi
|
||||
|
||||
# check that action needs to be performed. May not need to take action if we
|
||||
# got a delete event, but table was already flushed
|
||||
if [ $action = "del" ] && [ -n "${tbl##*$route_line$'\n'*}" ]; then
|
||||
LOG debug "skipping already deleted route table $tid - skipping $route_line"
|
||||
return
|
||||
fi
|
||||
|
||||
network_get_device device "$iface"
|
||||
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(){
|
||||
local iface=$1
|
||||
let tid++
|
||||
config_get family "$section" family ipv4
|
||||
config_get family "$iface" family ipv4
|
||||
[ "$family" != "$route_family" ] && return
|
||||
handle_route
|
||||
handle_route "$iface"
|
||||
}
|
||||
|
||||
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 -r 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
|
||||
mwan3_update_dev_to_table
|
||||
mwan3_route_line_dev "tid" "$route_line" "$route_family"
|
||||
|
||||
if [ -n "$tid" ]; then
|
||||
handle_route
|
||||
else
|
||||
elif [ -n "${route_line##default*}" ] && [ -n "${route_line##fe80::/64*}" ]; then
|
||||
config_foreach handle_route_cb interface
|
||||
fi
|
||||
}
|
||||
@@ -91,19 +149,35 @@ main()
|
||||
config_load mwan3
|
||||
family=$1
|
||||
[ -z $family ] && family=ipv4
|
||||
if [ "$family" = ipv6 ]; then
|
||||
if [ "$family" = "ipv6" ]; then
|
||||
if [ $NO_IPV6 -ne 0 ]; then
|
||||
LOG warn "mwan3rtmon started for ipv6, but ipv6 not enabled on system"
|
||||
exit 1
|
||||
fi
|
||||
IP="$IP6"
|
||||
else
|
||||
IP="$IP4"
|
||||
fi
|
||||
mwan3_init
|
||||
|
||||
$IP monitor route | while read -r line; do
|
||||
[ -z "${line##*table*}" ] && continue
|
||||
LOG debug "handling route update $family $line"
|
||||
mwan3_lock "service" "mwan3rtmon"
|
||||
mwan3_rtmon_route_handle "$line" "$family"
|
||||
mwan3_unlock "service" "mwan3rtmon"
|
||||
done
|
||||
mwan3_lock "mwan3rtmon" "start"
|
||||
sh -c "echo \$\$; exec $IP monitor route" | {
|
||||
read -r monitor_pid
|
||||
trap_with_arg func_trap "$monitor_pid" SIGINT SIGTERM SIGKILL
|
||||
while read -r line; do
|
||||
[ -z "${line##*table*}" ] && continue
|
||||
LOG debug "handling route update $family $line"
|
||||
mwan3_lock "service" "mwan3rtmon"
|
||||
mwan3_rtmon_route_handle "$line" "$family"
|
||||
mwan3_unlock "service" "mwan3rtmon"
|
||||
done
|
||||
} &
|
||||
child=$!
|
||||
kill -SIGSTOP $child
|
||||
trap_with_arg func_trap "$child" SIGINT SIGTERM SIGKILL
|
||||
mwan3_set_connected_${family}
|
||||
mwan3_add_all_routes ${family}
|
||||
mwan3_unlock "mwan3rtmon" "start"
|
||||
kill -SIGCONT $child
|
||||
wait $!
|
||||
}
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user