libnetwork: respect gw priority per address family

Signed-off-by: Varun Hotani <varunhotani@gmail.com>
This commit is contained in:
Varun Hotani
2026-04-09 16:10:44 +05:30
parent e4a7cd2de3
commit e30a6fa93b
2 changed files with 52 additions and 14 deletions

View File

@@ -190,26 +190,19 @@ func (sb *Sandbox) getGatewayEndpoint() (ep4, ep6 *Endpoint) {
continue
}
gw4, gw6 := ep.hasGatewayOrDefaultRoute()
if gw4 && gw6 {
// The first dual-stack endpoint is the gateway, no need to search further.
//
// FIXME(robmry) - this means a dual-stack gateway is preferred over single-stack
// gateways with higher gateway-priorities. A dual-stack network should probably
// be preferred over two single-stack networks, if they all have equal priorities.
// It'd probably also be better to use a dual-stack endpoint as the gateway for
// a single address family, if there's a higher-priority single-stack gateway for
// the other address family. (But, priority is currently a Sandbox property, not
// an Endpoint property. So, this function doesn't have access to priorities.)
return ep, ep
}
if gw4 && ep4 == nil {
// Found the best IPv4-only gateway, keep searching for an IPv6 or dual-stack gateway.
// Endpoints are already sorted according to Endpoint.Less(). The
// first endpoint with IPv4 connectivity is the IPv4 gateway.
ep4 = ep
}
if gw6 && ep6 == nil {
// Found the best IPv6-only gateway, keep searching for an IPv4 or dual-stack gateway.
// The first endpoint with IPv6 connectivity is the IPv6 gateway.
ep6 = ep
}
if ep4 != nil && ep6 != nil {
// Found both; we're done.
break
}
}
return ep4, ep6
}

View File

@@ -206,6 +206,51 @@ func TestSandboxAddMultiPrio(t *testing.T) {
}
}
func TestGatewayEndpointRespectsPriorityPerAddressFamily(t *testing.T) {
defer netnsutils.SetupTestOSContext(t)()
ctx := t.Context()
opts := [][]NetworkOption{
{
NetworkOptionEnableIPv4(true),
NetworkOptionEnableIPv6(true),
NetworkOptionIpam(defaultipam.DriverName, "",
[]*IpamConf{{PreferredPool: "172.30.0.0/24", Gateway: "172.30.0.1"}},
[]*IpamConf{{PreferredPool: "fe90::/64", Gateway: "fe90::1"}}, nil),
},
{
NetworkOptionEnableIPv4(true),
NetworkOptionIpam(defaultipam.DriverName, "",
[]*IpamConf{{PreferredPool: "172.31.0.0/24", Gateway: "172.31.0.1"}},
nil, nil),
},
}
ctrlr, nws := getTestEnv(t, opts...)
sbx, err := ctrlr.NewSandbox(ctx, "sandbox-prio-per-family")
assert.NilError(t, err)
epDual, err := nws[0].CreateEndpoint(ctx, "ep-dual")
assert.NilError(t, err)
epV4, err := nws[1].CreateEndpoint(ctx, "ep-v4")
assert.NilError(t, err)
err = epDual.Join(ctx, sbx)
assert.NilError(t, err)
err = epV4.Join(ctx, sbx, JoinOptionPriority(1000))
assert.NilError(t, err)
gwep4, gwep6 := sbx.getGatewayEndpoint()
assert.Assert(t, gwep4 != nil)
assert.Assert(t, gwep6 != nil)
assert.Check(t, is.Equal(gwep4.ID(), epV4.ID()))
assert.Check(t, is.Equal(gwep6.ID(), epDual.ID()))
err = sbx.Delete(ctx)
assert.NilError(t, err)
}
func TestSandboxAddSamePrio(t *testing.T) {
defer netnsutils.SetupTestOSContext(t)()