Skip to content

Allocate IPv6 addresses after detecting IPv6 support#47406

Merged
robmry merged 7 commits intomoby:masterfrom
robmry:defer_ipv6_addr_allocation
Nov 5, 2024
Merged

Allocate IPv6 addresses after detecting IPv6 support#47406
robmry merged 7 commits intomoby:masterfrom
robmry:defer_ipv6_addr_allocation

Conversation

@robmry
Copy link
Copy Markdown
Contributor

@robmry robmry commented Feb 19, 2024

- What I did

If IPv6 is disabled for a container, do not allocate an IPv6 address when it's attached to an IPv6 network.

- How I did it

There are a few commits - it's probably easiest to review them separately ...

Unconditionally update container.NetworkSettings

In daemon.allocateNetwork(), flag updateSettings was set if container.NetworkSettings.Networks was empty. That flag was passed down through the call stack to avoid a call to daemon.updateNetworkSettings() in daemon.updateNetworkConfig().

Other calls to daemon.updateNetworkSettings(), which happen when connecting an existing container to another network, unconditionally made the NetworkSettings update.

I don't think there's a circumstance where NetworkSettings is not empty during container creation. Even if there is, the update is harmless and cheap. Eliminating the updateSettings flag simplifies the code a little and, in the next commit where allocateNetwork() is split out of initializeNetworking(), it avoids the need to pass that flag between the two.

Separate Sandbox/Endpoint construction

Previously, the libnetwork.Sandbox was created in daemon.allocateNetwork() if there was no network - otherwise it happened while connecting an Endpoint in daemon.connectToNetwork(). If there was an endpoint in the default bridge, it had to be connected first, because extra configuration is needed in the Sandbox for legacy links and that could only happen during Sandbox construction.

Now, config for legacy links is added to the Sandbox when constructing the Endpoint that needs it - removing the constraint on ordering of Endpoint construction, and the dependency between Endpoint and Sandbox construction.

So, now a Sandbox can be constructed in one place, before the first Endpoint.

Also, replaces some legacy-link specific Sandbox option-setters with Sandbox methods for updating /etc/hosts, and updates a legacy-link parent's IPv6 address as well as its IPv4 address when a child container restarts.

Configure network endpoints after creating a container

This commit splits the bulk of daemon.allocateNetwork() out of daemon.initializeNetworking().

daemon.initializeNetworking() hasn't moved, but it now only prepares configuration and doesn't do any Endpoint construction or configuration. Sandbox construction still happens here.

Endpoint construction is in daemon.allocateNetwork() which, on non-Windows, is called after the container task has been created (before it's started).

On Windows, Endpoint construction still happens before the container task is created. If it's created afterwards, some DNS lookups for the container don't seem to end up in our resolver - see the TODO comment in the code. (But, Windows can't benefit from the delayed assignment of IPv6 addresses anyway.)

Doing the Endpoint construction after the osSbox has been set up makes it possible to probe the container's network for IPv6 support first - enabling the next commit ...

Only assign IPv6 addresses if required

If a Sandbox is provided to CreateEndpointForSandbox, check whether it has IPv6 before allocating IPv6 addresses.

Because no IPv6 address is added to the DNS when the Sandbox doesn't support it, a lookup for a container on an IPv6 network can now have no IPv6 address. The resolver is updated to treat a missing IPv6 address on an IPv4 hit as ipv6miss even if the network has IPv6 enabled. (So, an empty DNS response is returned, avoiding the upstream DNS request and NXDOMAIN.)

The macvlan driver expected an endpoint on a network with IPv6 subnets to have an IPv6 address - it searched the subnets for the address assigned to the endpoint, to work out which gateway address to use (crashing if there was no address). Now, it only makes that search if there is an IPv6 address.

- How to verify it

Existing regression tests for the refactoring.

New integration test checks that a container with IPv6 disabled via sysctl on an IPv6 network has no IPv6 address.

- Description for the changelog

If IPv6 is disabled for a container, do not allocate an IPv6 address when it's attached to an IPv6 network.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/networking/dns Networking area/networking Networking kind/bugfix PR's that fix bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IPv4 only container are resolved with an IPv6 address on an IPv6 enabled network

6 participants