mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-10 15:39:07 +02:00
[client] Skip IPv6 route tests when the default nexthop is unusable (#7212)
* [client] Skip IPv6 route tests when the default nexthop is unusable
ensureIPv6DefaultRoute treated a successful netlink RouteAdd as proof that
a usable IPv6 nexthop exists. Installing ::/0 via loopback can succeed while
the kernel still rejects that nexthop for a concrete prefix, which surfaced
on ubuntu22/20260810.260 runners as:
add route to table: netlink add route: invalid argument
Probe the resolved nexthop by installing and removing a discard-prefix route
through the same code path the tests use, and skip when it fails. EEXIST
means the nexthop already carries a route, so it counts as usable.
* [client] Probe the IPv6 nexthop through raw netlink
addRoute swallows EAFNOSUPPORT and EOPNOTSUPP via isOpErr, so a nil return
did not prove the probe route was installed. Call netlink directly so an
unsupported operation skips the test instead of passing as usable.
This commit is contained in:
@@ -5,6 +5,7 @@ package systemops
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ func ensureIPv6DefaultRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if err := netlink.RouteAdd(route); err != nil {
|
if err := netlink.RouteAdd(route); err != nil {
|
||||||
if errors.Is(err, syscall.EEXIST) {
|
if errors.Is(err, syscall.EEXIST) {
|
||||||
|
requireUsableIPv6Nexthop(t)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Skipf("install IPv6 fallback default route: %v", err)
|
t.Skipf("install IPv6 fallback default route: %v", err)
|
||||||
@@ -38,4 +40,36 @@ func ensureIPv6DefaultRoute(t *testing.T) {
|
|||||||
t.Logf("delete IPv6 fallback default route: %v", err)
|
t.Logf("delete IPv6 fallback default route: %v", err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
requireUsableIPv6Nexthop(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// requireUsableIPv6Nexthop skips the test unless the resolved IPv6 default
|
||||||
|
// nexthop can actually carry a route. Installing the default route succeeding
|
||||||
|
// does not imply the kernel accepts it as a nexthop for a concrete prefix.
|
||||||
|
func requireUsableIPv6Nexthop(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
nexthop, err := GetNextHop(netip.IPv6Unspecified())
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf("resolve IPv6 default nexthop: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
probe := &netlink.Route{
|
||||||
|
Scope: netlink.SCOPE_UNIVERSE,
|
||||||
|
Table: syscall.RT_TABLE_MAIN,
|
||||||
|
Family: netlink.FAMILY_V6,
|
||||||
|
Dst: &net.IPNet{IP: net.ParseIP("100::64"), Mask: net.CIDRMask(128, 128)},
|
||||||
|
}
|
||||||
|
require.NoError(t, addNextHop(nexthop, probe), "build IPv6 probe route")
|
||||||
|
|
||||||
|
switch err := netlink.RouteAdd(probe); {
|
||||||
|
case err == nil:
|
||||||
|
if err := netlink.RouteDel(probe); err != nil && !errors.Is(err, syscall.ESRCH) {
|
||||||
|
t.Logf("delete IPv6 probe route: %v", err)
|
||||||
|
}
|
||||||
|
case errors.Is(err, syscall.EEXIST):
|
||||||
|
default:
|
||||||
|
t.Skipf("IPv6 nexthop %s unusable for route installation: %v", nexthop, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user