aboutsummaryrefslogtreecommitdiff
path: root/net/mwan3/files
diff options
context:
space:
mode:
authorAaron Goodman <aaronjg@stanford.edu>2020-10-11 18:37:25 -0400
committerAaron Goodman <aaronjg@stanford.edu>2020-10-16 09:54:48 -0400
commitbbbc6127abf132a92cc73dd23fa88409dc2b9abd (patch)
treeb0e0de516771222523a601f4cd6c1063e30bacb7 /net/mwan3/files
parentfb4a2d99eff3af53d4eea2db36d270a140bde6bf (diff)
mwan3: use helper library for mwan3track
Rather than using a special mwan3 user to manage mwan3track's tracking packets, this commit implements a small helper library to bind to device and to set a fwmark so that the tracking packets can be routed out of the correct interface. This provides a consistent method for binding to a device rather than relying on various packages potentially buggy implementations. For example: #8139 and #12836 This helper issue also allows for more tracking methods to be added even if they do not have a command line option to bind to device, such as iperf3 (eg #13050). Signed-off-by: Aaron Goodman <aaronjg@stanford.edu>
Diffstat (limited to 'net/mwan3/files')
-rw-r--r--net/mwan3/files/lib/mwan3/common.sh27
-rw-r--r--net/mwan3/files/lib/mwan3/mwan3.sh93
-rwxr-xr-xnet/mwan3/files/usr/sbin/mwan3track48
3 files changed, 49 insertions, 119 deletions
diff --git a/net/mwan3/files/lib/mwan3/common.sh b/net/mwan3/files/lib/mwan3/common.sh
index 53557a6ef..4deb9bfeb 100644
--- a/net/mwan3/files/lib/mwan3/common.sh
+++ b/net/mwan3/files/lib/mwan3/common.sh
@@ -8,8 +8,19 @@ get_uptime() {
IP4="ip -4"
IP6="ip -6"
SCRIPTNAME="$(basename "$0")"
+
+MWAN3_STATUS_DIR="/var/run/mwan3"
MWAN3TRACK_STATUS_DIR="/var/run/mwan3track"
+MWAN3_INTERFACE_MAX=""
+
+MMX_MASK=""
+MMX_DEFAULT=""
+MMX_BLACKHOLE=""
+MM_BLACKHOLE=""
+
+MMX_UNREACHABLE=""
+MM_UNREACHABLE=""
MAX_SLEEP=$(((1<<31)-1))
LOG()
@@ -21,6 +32,21 @@ LOG()
[ "$facility" = "debug" ] && return
logger -t "${SCRIPTNAME}[$$]" -p $facility "$*"
}
+
+mwan3_get_true_iface()
+{
+ local family V
+ _true_iface=$2
+ config_get family "$2" family ipv4
+ if [ "$family" = "ipv4" ]; then
+ V=4
+ elif [ "$family" = "ipv6" ]; then
+ V=6
+ fi
+ ubus call "network.interface.${2}_${V}" status &>/dev/null && _true_iface="${2}_${V}"
+ export "$1=$_true_iface"
+}
+
mwan3_get_src_ip()
{
local family _src_ip true_iface device addr_cmd default_ip IP sed_str
@@ -149,4 +175,3 @@ mwan3_count_one_bits()
done
echo $count
}
->>>>>>> 2a4e0dc6d... review comments
diff --git a/net/mwan3/files/lib/mwan3/mwan3.sh b/net/mwan3/files/lib/mwan3/mwan3.sh
index c3113007a..2a689c0c8 100644
--- a/net/mwan3/files/lib/mwan3/mwan3.sh
+++ b/net/mwan3/files/lib/mwan3/mwan3.sh
@@ -22,16 +22,7 @@ IPv6_REGEX="${IPv6_REGEX}::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
IPv4_REGEX="((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
-MWAN3_STATUS_DIR="/var/run/mwan3"
-MWAN3_INTERFACE_MAX=""
DEFAULT_LOWEST_METRIC=256
-MMX_MASK=""
-MMX_DEFAULT=""
-MMX_BLACKHOLE=""
-MM_BLACKHOLE=""
-
-MMX_UNREACHABLE=""
-MM_UNREACHABLE=""
command -v ip6tables > /dev/null
NO_IPV6=$?
@@ -80,20 +71,6 @@ mwan3_update_iface_to_table()
config_foreach update_table interface
}
-mwan3_get_true_iface()
-{
- local family V
- _true_iface=$2
- config_get family "$iface" family ipv4
- if [ "$family" = "ipv4" ]; then
- V=4
- elif [ "$family" = "ipv6" ]; then
- V=6
- fi
- ubus call "network.interface.${iface}_${V}" status &>/dev/null && _true_iface="${iface}_${V}"
- export "$1=$_true_iface"
-}
-
mwan3_route_line_dev()
{
# must have mwan3 config already loaded
@@ -129,63 +106,6 @@ mwan3_count_one_bits()
echo $count
}
-# maps the 1st parameter so it only uses the bits allowed by the bitmask (2nd parameter)
-# which means spreading the bits of the 1st parameter to only use the bits that are set to 1 in the 2nd parameter
-# 0 0 0 0 0 1 0 1 (0x05) 1st parameter
-# 1 0 1 0 1 0 1 0 (0xAA) 2nd parameter
-# 1 0 1 result
-mwan3_id2mask()
-{
- local bit_msk bit_val result
- bit_val=0
- result=0
- for bit_msk in $(seq 0 31); do
- if [ $((($2>>bit_msk)&1)) = "1" ]; then
- if [ $((($1>>bit_val)&1)) = "1" ]; then
- result=$((result|(1<<bit_msk)))
- fi
- bit_val=$((bit_val+1))
- fi
- done
- printf "0x%x" $result
-}
-
-mwan3_init()
-{
- local bitcnt
- local mmdefault
-
- [ -d $MWAN3_STATUS_DIR ] || mkdir -p $MWAN3_STATUS_DIR/iface_state
-
- # mwan3's MARKing mask (at least 3 bits should be set)
- if [ -e "${MWAN3_STATUS_DIR}/mmx_mask" ]; then
- MMX_MASK=$(cat "${MWAN3_STATUS_DIR}/mmx_mask")
- MWAN3_INTERFACE_MAX=$(uci_get_state mwan3 globals iface_max)
- else
- config_load mwan3
- config_get MMX_MASK globals mmx_mask '0x3F00'
- echo "$MMX_MASK"| tr 'A-F' 'a-f' > "${MWAN3_STATUS_DIR}/mmx_mask"
- LOG debug "Using firewall mask ${MMX_MASK}"
-
- bitcnt=$(mwan3_count_one_bits MMX_MASK)
- mmdefault=$(((1<<bitcnt)-1))
- MWAN3_INTERFACE_MAX=$((mmdefault-3))
- uci_toggle_state mwan3 globals iface_max "$MWAN3_INTERFACE_MAX"
- LOG debug "Max interface count is ${MWAN3_INTERFACE_MAX}"
- fi
-
- # mark mask constants
- bitcnt=$(mwan3_count_one_bits MMX_MASK)
- mmdefault=$(((1<<bitcnt)-1))
- MM_BLACKHOLE=$((mmdefault-2))
- MM_UNREACHABLE=$((mmdefault-1))
-
- # MMX_DEFAULT should equal MMX_MASK
- MMX_DEFAULT=$(mwan3_id2mask mmdefault MMX_MASK)
- MMX_BLACKHOLE=$(mwan3_id2mask MM_BLACKHOLE MMX_MASK)
- MMX_UNREACHABLE=$(mwan3_id2mask MM_UNREACHABLE MMX_MASK)
-}
-
mwan3_lock() {
lock /var/run/mwan3.lock
#LOG debug "$1 $2 (lock)"
@@ -281,7 +201,7 @@ mwan3_set_connected_ipv4()
mwan3_set_connected_ipv6()
{
- local connected_network_v6 source_network_v6 error
+ local connected_network_v6 error
local update=""
[ $NO_IPV6 -eq 0 ] || return
@@ -292,10 +212,6 @@ mwan3_set_connected_ipv6()
mwan3_push_update -! add mwan3_connected_v6 "$connected_network_v6"
done
- mwan3_push_update -! create mwan3_source_v6 hash:net family inet6
- for source_network_v6 in $($IP6 addr ls | sed -ne 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p'); do
- mwan3_push_update -! add mwan3_source_v6 "$source_network_v6"
- done
mwan3_push_update -! add mwan3_connected mwan3_connected_v6
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_connected_ipv6: $error"
}
@@ -384,15 +300,10 @@ mwan3_set_general_iptables()
-p ipv6-icmp \
-m icmp6 --icmpv6-type 137 \
-j RETURN
- # do not mangle outgoing echo request
- mwan3_push_update -A mwan3_hook \
- -m set --match-set mwan3_source_v6 src \
- -p ipv6-icmp \
- -m icmp6 --icmpv6-type 128 \
- -j RETURN
fi
mwan3_push_update -A mwan3_hook \
+ -m mark --mark 0x0/$MMX_MASK \
-j CONNMARK --restore-mark --nfmask "$MMX_MASK" --ctmask "$MMX_MASK"
mwan3_push_update -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
diff --git a/net/mwan3/files/usr/sbin/mwan3track b/net/mwan3/files/usr/sbin/mwan3track
index 32b741ee2..e1f185200 100755
--- a/net/mwan3/files/usr/sbin/mwan3track
+++ b/net/mwan3/files/usr/sbin/mwan3track
@@ -19,6 +19,11 @@ stop_subprocs() {
[ -n "$TRACK_PID" ] && kill "$TRACK_PID" && unset TRACK_PID
}
+WRAP() {
+ # shellcheck disable=SC2048
+ FAMILY=$FAMILY DEVICE=$DEVICE SRCIP=$SRC_IP FWMARK=$MMX_DEFAULT LD_PRELOAD=/lib/mwan3/libwrap_mwan3_sockopt.so.1.0 $*
+}
+
clean_up() {
LOG notice "Stopping mwan3track for interface \"${INTERFACE}\". Status was \"${STATUS}\""
stop_subprocs
@@ -58,10 +63,6 @@ validate_track_method() {
LOG warn "Missing httping. Please install httping package."
return 1
}
- [ -n "$2" ] && { [ "$2" = "0.0.0.0" ] || [ "$2" = "::" ]; } && {
- LOG warn "Cannot determine source IP for the interface which is required by httping."
- return 1
- }
;;
nping-*)
command -v nping 1>/dev/null 2>&1 || {
@@ -76,6 +77,12 @@ validate_track_method() {
esac
}
+validate_wrap() {
+ [ -x /lib/mwan3/libwrap_mwan3_sockopt.so.1.0 ] && return
+ LOG error "Missing libwrap_mwan3_sockopt. Please reinstall mwan3." &&
+ exit 1
+}
+
disconnected() {
STATUS='offline'
echo "offline" > $MWAN3TRACK_STATUS_DIR/$INTERFACE/STATUS
@@ -124,17 +131,6 @@ firstconnect() {
mwan3_get_src_ip SRC_IP $true_iface
- # 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=2167
- # https://forum.openwrt.org/t/ping-and-traceroute-failing-for-eth0-3-on-ipv6/44680/11
- # so use the IP address of the interface
- if [ "$family" = "ipv6" ]; then
- SOURCE="$SRC_IP"
- else
- SOURCE="$DEVICE"
- fi
-
LOG debug "firstconnect: called on $INTERFACE/$true_iface ($DEVICE). Status is $STATUS. SRC_IP is $SRC_IP"
STARTED=1
@@ -159,7 +155,8 @@ main() {
local recovery_interval down up size
local keep_failure_interval check_quality failure_latency
local recovery_latency failure_loss recovery_loss
- local max_ttl httping_ssl family track_ips
+
+ local max_ttl httping_ssl track_ips
INTERFACE=$1
STATUS=""
@@ -171,9 +168,10 @@ main() {
trap if_up USR2
config_load mwan3
+ config_get FAMILY $INTERFACE family ipv4
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 || {
track_method=ping
if validate_track_method $track_method; then
LOG warn "Using ping to track interface $INTERFACE avaliability"
@@ -219,17 +217,13 @@ main() {
if [ $host_up_count -lt $reliability ]; then
case "$track_method" in
ping)
- # pinging IPv6 hosts with an interface is troublesome
- # https://bugs.openwrt.org/index.php?do=details&task_id=2897
- # so get the IP address of the interface and use that instead
-
if [ $check_quality -eq 0 ]; then
- $PING -${family#ipv} -I ${SOURCE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null &
+ WRAP $PING -${FAMILY#ipv} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null &
TRACK_PID=$!
wait $TRACK_PID
result=$?
else
- $PING -${family#ipv} -I ${SOURCE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null > $TRACK_OUTPUT &
+ WRAP $PING -${family#ipv} -I ${SOURCE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null > $TRACK_OUTPUT &
TRACK_PID=$!
wait $TRACK_PID
ping_status=$?
@@ -243,23 +237,23 @@ main() {
fi
;;
arping)
- arping -I $DEVICE -c $count -w $timeout -q $track_ip &> /dev/null &
+ WRAP arping -I $DEVICE -c $count -w $timeout -q $track_ip &> /dev/null &
TRACK_PID=$!
wait $TRACK_PID
result=$?
;;
httping)
if [ "$httping_ssl" -eq 1 ]; then
- httping -y $SRC_IP -c $count -t $timeout -q "https://$track_ip" &> /dev/null &
+ WRAP httping -c $count -t $timeout -q "https://$track_ip" &> /dev/null &
else
- httping -y $SRC_IP -c $count -t $timeout -q "http://$track_ip" &> /dev/null &
+ WRAP httping -c $count -t $timeout -q "http://$track_ip" &> /dev/null &
fi
TRACK_PID=$!
wait $TRACK_PID
result=$?
;;
nping-*)
- nping -c $count $track_ip --${FAMILY#nping-} > $TRACK_OUTPUT &
+ WRAP nping -c $count $track_ip --${FAMILY#nping-} > $TRACK_OUTPUT &
TRACK_PID=$!
wait $TRACK_PID
result=$(grep $TRACK_OUTPUT Lost | awk '{print $12}')