mwan3: common.sh: fix src_ip detection for ipv6-PD

IPv6 via PPPoE often receives a prefix, not an address. In that case
mwan3_get_src_ip would not find an address and fall back to ::.  However
in case of multiple IPv6 upstreams, this no longer means a ping (such as
done by uptime check) succeeds, for there are multiple addresses.

With this, mwan3 can effectively load-balance/fail-over on a PPPoE IPv6
prefix and a secondary (LTE) acquired /64 without immediately disabling
the IPv6 prefix interface as soon as the secondary IPv6 interface comes
up.

I think this change is also a fix to #26690
but I'm not 100% sure of that.

Signed-off-by: Fabian Groffen <grobian@bitzolder.nl>
This commit is contained in:
Fabian Groffen
2025-09-02 13:20:13 +02:00
committed by Florian Eckert
parent f933e028f5
commit 47fd548a71
+27 -2
View File
@@ -74,8 +74,33 @@ mwan3_get_src_ip()
$addr_cmd _src_ip "$true_iface"
if [ -z "$_src_ip" ]; then
network_get_device device $true_iface
_src_ip=$($IP address ls dev $device 2>/dev/null | sed -ne "$sed_str")
if [ "$family" = "ipv6" ]; then
# on IPv6-PD interfaces (like PPPoE interfaces) we don't
# have a real address, just a prefix, that can be delegated
# to interfaces, because using :: (the fallback above) or
# the local address (fe80:... which will be returned from
# the sed_str expression defined above) will not work
# (reliably, if at all) try to find an address which we can
# use instead
network_get_prefix6 _src_ip "$true_iface"
if [ -n "$_src_ip" ]; then
# got a prefix like 2001:xxxx:yyyy::/48, clean it up to
# only contain the prefix -> 2001:xxxx:yyyy
_src_ip=$(echo "$_src_ip" | sed -e 's;:*/.*$;;')
# find an interface with a delegated address, and use
# it, this would be sth like 2001:xxxx:yyyy:zzzz:...
# we just select the first address that matches the prefix
# NOTE: is there a better/more reliable way to get a
# usable address to use as source for pings here?
local pfx_sed
pfx_sed='s/ *inet6 \('"$_src_ip"':[0-6a-f:]\+\).* scope.*/\1/'
_src_ip=$($IP address ls | sed -ne "${pfx_sed};T;p;q")
fi
fi
if [ -z "$_src_ip" ]; then
network_get_device device $true_iface
_src_ip=$($IP address ls dev $device 2>/dev/null | sed -ne "$sed_str")
fi
if [ -n "$_src_ip" ]; then
LOG warn "no src $family address found from netifd for interface '$true_iface' dev '$device' guessing $_src_ip"
else