1
0
mirror of https://git.openwrt.org/feed/packages.git synced 2024-06-17 04:44:10 +02:00

Merge pull request #6515 from ptpt52/mwan3

refine mwan3 link selection
This commit is contained in:
Hannu Nyman 2018-08-31 11:59:36 +03:00 committed by GitHub
commit d0668b02fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 152 additions and 57 deletions

View File

@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mwan3
PKG_VERSION:=2.6.18
PKG_VERSION:=2.7.0
PKG_RELEASE:=1
PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de>
PKG_LICENSE:=GPLv2

View File

@ -1,7 +1,8 @@
config globals 'globals'
option mmx_mask '0x3F00'
option local_source 'lan'
option local_source 'none'
option rtmon_interval '5'
config interface 'wan'
option enabled '1'

View File

@ -0,0 +1,17 @@
#!/bin/sh
. /lib/functions.sh
. /lib/functions/network.sh
. /lib/mwan3/mwan3.sh
config_load mwan3
config_get_bool enabled globals 'enabled' '0'
[ ${enabled} -gt 0 ] || exit 0
if [ "$ACTION" == "ifup" ]; then
mwan3_lock
mwan3_rtmon
mwan3_unlock
fi
exit 0

View File

@ -20,6 +20,63 @@ MM_BLACKHOLE=""
MMX_UNREACHABLE=""
MM_UNREACHABLE=""
mwan3_rtmon_ipv4()
{
local tid=1
local idx=0
local ret=1
main_tbsum=$($IP4 route list table main | grep -v ^default | md5sum | head -c32)
while uci get mwan3.@interface[$idx] >/dev/null 2>&1 ; do
idx=$((idx+1))
tid=$idx
[ "$(uci get mwan3.@interface[$((idx-1))].family)" = "ipv4" ] && {
if $IP4 route list table $tid | grep -q ^default; then
tbsum=$($IP4 route list table $tid | grep -v ^default | md5sum | head -c32)
if [ "$tbsum" != "$main_tbsum" ]; then
$IP4 route list table $tid | grep -v ^default | while read line; do
$IP4 route del table $tid $line
done
$IP4 route list table main | grep -v ^default | while read line; do
$IP4 route add table $tid $line
done
fi
fi
}
if [ "$(uci get mwan3.@interface[$((idx-1))].enabled)" = "1" ]; then
ret=0
fi
done
return $ret
}
mwan3_rtmon_ipv6()
{
local tid=1
local idx=0
local ret=1
main_tbsum=$($IP6 route list table main | grep -v "^default\|^::/" | md5sum | head -c32)
while uci get mwan3.@interface[$idx] >/dev/null 2>&1 ; do
idx=$((idx+1))
tid=$idx
[ "$(uci get mwan3.@interface[$((idx-1))].family)" = "ipv6" ] && {
if $IP6 route list table $tid | grep -q ^::/0; then
tbsum=$($IP6 route list table $tid | grep -v "^default\|^::/" | md5sum | head -c32)
if [ "$tbsum" != "$main_tbsum" ]; then
$IP6 route list table $tid | grep -v "^default\|^::/" | while read line; do
$IP6 route del table $tid $line
done
$IP6 route list table main | grep -v "^default\|^::/" | while read line; do
$IP6 route add table $tid $line
done
fi
fi
}
if [ "$(uci get mwan3.@interface[$((idx-1))].enabled)" = "1" ]; then
ret=0
fi
done
return $ret
}
# counts how many bits are set to 1
# n&(n-1) clears the lowest bit set to 1
@ -188,10 +245,6 @@ mwan3_set_general_iptables()
$IPT -A mwan3_connected -m set --match-set mwan3_connected dst -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
fi
if ! $IPT -S mwan3_ifaces_out &> /dev/null; then
$IPT -N mwan3_ifaces_out
fi
if ! $IPT -S mwan3_rules &> /dev/null; then
$IPT -N mwan3_rules
fi
@ -209,7 +262,6 @@ mwan3_set_general_iptables()
$IPT -A mwan3_hook -j CONNMARK --restore-mark --nfmask $MMX_MASK --ctmask $MMX_MASK
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_ifaces_in
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_connected
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_ifaces_out
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_rules
$IPT -A mwan3_hook -j CONNMARK --save-mark --nfmask $MMX_MASK --ctmask $MMX_MASK
$IPT -A mwan3_hook -m mark ! --mark $MMX_DEFAULT/$MMX_MASK -j mwan3_connected
@ -241,30 +293,16 @@ mwan3_create_iface_iptables()
$IPT4 -N mwan3_ifaces_in
fi
if ! $IPT4 -S mwan3_ifaces_out &> /dev/null; then
$IPT4 -N mwan3_ifaces_out
fi
if ! $IPT4 -S mwan3_iface_in_$1 &> /dev/null; then
$IPT4 -N mwan3_iface_in_$1
fi
if ! $IPT4 -S mwan3_iface_out_$1 &> /dev/null; then
$IPT4 -N mwan3_iface_out_$1
fi
$IPT4 -F mwan3_iface_in_$1
$IPT4 -A mwan3_iface_in_$1 -i $2 -m set --match-set mwan3_connected src -m mark --mark 0x0/$MMX_MASK -m comment --comment "default" -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
$IPT4 -A mwan3_iface_in_$1 -i $2 -m mark --mark 0x0/$MMX_MASK -m comment --comment "$1" -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
$IPT4 -D mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1 &> /dev/null
$IPT4 -A mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1
$IPT4 -F mwan3_iface_out_$1
$IPT4 -A mwan3_iface_out_$1 -o $2 -m mark --mark 0x0/$MMX_MASK -m comment --comment "$1" -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
$IPT4 -D mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT4 -A mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1
fi
if [ "$family" == "ipv6" ]; then
@ -274,30 +312,16 @@ mwan3_create_iface_iptables()
$IPT6 -N mwan3_ifaces_in
fi
if ! $IPT6 -S mwan3_ifaces_out &> /dev/null; then
$IPT6 -N mwan3_ifaces_out
fi
if ! $IPT6 -S mwan3_iface_in_$1 &> /dev/null; then
$IPT6 -N mwan3_iface_in_$1
fi
if ! $IPT6 -S mwan3_iface_out_$1 &> /dev/null; then
$IPT6 -N mwan3_iface_out_$1
fi
$IPT6 -F mwan3_iface_in_$1
$IPT6 -A mwan3_iface_in_$1 -i $2 -m set --match-set mwan3_connected_v6 src -m mark --mark 0x0/$MMX_MASK -m comment --comment "default" -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
$IPT6 -A mwan3_iface_in_$1 -i $2 -m mark --mark 0x0/$MMX_MASK -m comment --comment "$1" -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
$IPT6 -D mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1 &> /dev/null
$IPT6 -A mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1
$IPT6 -F mwan3_iface_out_$1
$IPT6 -A mwan3_iface_out_$1 -o $2 -m mark --mark 0x0/$MMX_MASK -m comment --comment "$1" -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
$IPT6 -D mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT6 -A mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1
fi
}
@ -310,10 +334,6 @@ mwan3_delete_iface_iptables()
$IPT4 -D mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1 &> /dev/null
$IPT4 -F mwan3_iface_in_$1 &> /dev/null
$IPT4 -X mwan3_iface_in_$1 &> /dev/null
$IPT4 -D mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT4 -F mwan3_iface_out_$1 &> /dev/null
$IPT4 -X mwan3_iface_out_$1 &> /dev/null
fi
if [ "$family" == "ipv6" ]; then
@ -321,10 +341,6 @@ mwan3_delete_iface_iptables()
$IPT6 -D mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1 &> /dev/null
$IPT6 -F mwan3_iface_in_$1 &> /dev/null
$IPT6 -X mwan3_iface_in_$1 &> /dev/null
$IPT6 -D mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT6 -F mwan3_iface_out_$1 &> /dev/null
$IPT6 -X mwan3_iface_out_$1 &> /dev/null
fi
}
@ -352,6 +368,7 @@ mwan3_create_iface_route()
$IP4 route flush table $id
$IP4 route add table $id default $route_args dev $2
mwan3_rtmon_ipv4
fi
if [ "$family" == "ipv6" ]; then
@ -369,6 +386,7 @@ mwan3_create_iface_route()
$IP6 route flush table $id
$IP6 route add table $id default $route_args dev $2
mwan3_rtmon_ipv6
fi
}
@ -409,7 +427,7 @@ mwan3_create_iface_rules()
$IP4 rule del pref $(($id+2000))
done
$IP4 rule add pref $(($id+1000)) iif $2 lookup main
$IP4 rule add pref $(($id+1000)) iif $2 lookup $id
$IP4 rule add pref $(($id+2000)) fwmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK lookup $id
fi
@ -423,7 +441,7 @@ mwan3_create_iface_rules()
$IP6 rule del pref $(($id+2000))
done
$IP6 rule add pref $(($id+1000)) iif $2 lookup main
$IP6 rule add pref $(($id+1000)) iif $2 lookup $id
$IP6 rule add pref $(($id+2000)) fwmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK lookup $id
fi
}
@ -475,6 +493,16 @@ mwan3_delete_iface_ipset_entries()
done
}
mwan3_rtmon()
{
pid="$(pgrep -f mwan3rtmon)"
if [ "${pid}" != "" ]; then
kill -USR1 "${pid}"
else
[ -x /usr/sbin/mwan3rtmon ] && /usr/sbin/mwan3rtmon &
fi
}
mwan3_track()
{
local track_ip track_ips pid
@ -507,13 +535,14 @@ mwan3_track_signal()
mwan3_set_policy()
{
local iface_count id iface family metric probability weight
local iface_count id iface family metric probability weight device
config_get iface $1 interface
config_get metric $1 metric 1
config_get weight $1 weight 1
[ -n "$iface" ] || return 0
network_get_device device $iface
[ "$metric" -gt $DEFAULT_LOWEST_METRIC ] && $LOG warn "Member interface $iface has >$DEFAULT_LOWEST_METRIC metric. Not appending to policy" && return 0
mwan3_get_iface_id id $iface
@ -552,6 +581,11 @@ mwan3_set_policy()
$IPT4 -I mwan3_policy_$policy -m mark --mark 0x0/$MMX_MASK $probability -m comment --comment "$iface $weight $total_weight_v4" -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
fi
else
[ -n "$device" ] && {
$IPT4 -S mwan3_policy_$policy | grep -q '.*--comment ".* [0-9]* [0-9]*"' || \
$IPT4 -I mwan3_policy_$policy -o $device -m mark --mark 0x0/$MMX_MASK -m comment --comment "out $iface $device" -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
}
fi
fi
@ -585,6 +619,11 @@ mwan3_set_policy()
$IPT6 -I mwan3_policy_$policy -m mark --mark 0x0/$MMX_MASK $probability -m comment --comment "$iface $weight $total_weight_v6" -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
fi
else
[ -n "$device" ] && {
$IPT6 -S mwan3_policy_$policy | grep -q '.*--comment ".* [0-9]* [0-9]*"' || \
$IPT6 -I mwan3_policy_$policy -o $device -m mark --mark 0x0/$MMX_MASK -m comment --comment "out $iface $device" -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
}
fi
fi
}
@ -649,7 +688,7 @@ mwan3_set_sticky_iptables()
[ -n "$id" ] || return 0
for IPT in "$IPT4" "$IPT6"; do
if [ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -a -n "$($IPT -S mwan3_iface_out_$1 2> /dev/null)" ]; then
if [ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" ]; then
$IPT -I mwan3_rule_$rule -m mark --mark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK -m set ! --match-set mwan3_sticky_$rule src,src -j MARK --set-xmark 0x0/$MMX_MASK
$IPT -I mwan3_rule_$rule -m mark --mark 0/$MMX_MASK -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
fi
@ -822,9 +861,9 @@ mwan3_report_iface_status()
if [ -z "$id" -o -z "$device" ]; then
result="unknown"
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" -a -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" -a -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -a -n "$($IPT -S mwan3_iface_out_$1 2> /dev/null)" -a -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" -a -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" -a -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -a -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then
result="$(mwan3_get_iface_hotplug_state $1)"
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" -o -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" -o -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -o -n "$($IPT -S mwan3_iface_out_$1 2> /dev/null)" -o -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" -o -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" -o -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -o -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then
result="error"
elif [ "$enabled" == "1" ]; then
result="offline"
@ -858,16 +897,16 @@ mwan3_report_policies_v4()
for policy in $($IPT4 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "$policy:" | sed 's/mwan3_policy_//'
[ -n "$total_weight" ] || total_weight=$($IPT4 -S $policy | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
[ -n "$total_weight" ] || total_weight=$($IPT4 -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
if [ ! -z "${total_weight##*[!0-9]*}" ]; then
for iface in $($IPT4 -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT4 -S $policy | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
for iface in $($IPT4 -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT4 -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
percent=$(($weight*100/$total_weight))
echo " $iface ($percent%)"
done
else
echo " $($IPT4 -S $policy | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
echo " $($IPT4 -S $policy | grep -v '.*--comment "out .*" .*$' | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
fi
unset total_weight
@ -883,16 +922,16 @@ mwan3_report_policies_v6()
for policy in $($IPT6 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "$policy:" | sed 's/mwan3_policy_//'
[ -n "$total_weight" ] || total_weight=$($IPT6 -S $policy | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
[ -n "$total_weight" ] || total_weight=$($IPT6 -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
if [ ! -z "${total_weight##*[!0-9]*}" ]; then
for iface in $($IPT6 -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT6 -S $policy | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
for iface in $($IPT6 -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT6 -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
percent=$(($weight*100/$total_weight))
echo " $iface ($percent%)"
done
else
echo " $($IPT6 -S $policy | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
echo " $($IPT6 -S $policy | grep -v '.*--comment "out .*" .*$' | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
fi
unset total_weight

View File

@ -155,6 +155,12 @@ stop()
{
local ipset route rule table IP IPT pid src_ip
for pid in $(pgrep -f "mwan3rtmon"); do
kill -TERM "$pid" > /dev/null 2>&1
sleep 1
kill -KILL "$pid" > /dev/null 2>&1
done
for pid in $(pgrep -f "mwan3track"); do
kill -TERM "$pid" > /dev/null 2>&1
sleep 1

View File

@ -0,0 +1,32 @@
#!/bin/sh
. /lib/functions.sh
. /lib/mwan3/mwan3.sh
LOG="logger -t $(basename "$0")[$$] -p"
clean_up() {
$LOG notice "Stopping mwan3rtmon..."
exit 0
}
rtchange() {
$LOG info "Detect rtchange event."
}
main() {
local rtmon_interval
trap clean_up TERM
trap rtchange USR1
config_load mwan3
config_get rtmon_interval globals rtmon_interval '5'
sleep 3
while mwan3_rtmon_ipv4 || mwan3_rtmon_ipv6; do
[ "$rtmon_interval" = "0" ] && break
sleep $rtmon_interval
done
}
main "$@"