28 Commits

Author SHA1 Message Date
Paweł Gronowski
c621624e2f libnetwork: Always clean up endpoint driver info in sbLeave
In Swarm overlay networks, remote nodes program VXLAN FDB and neighbor
entries from the overlay driver's NetworkDB table (overlay_peer_table).
Those entries are installed as static/permanent neighbors and are
removed only when the endpoint's driver table entries are deleted from
NetworkDB and the delete event is gossiped to peers.

Endpoint.sbLeave() updates the local endpoint object in the store via
storeEndpoint(). If that store update fails (notably
datastore.ErrKeyModified from a boltDB CAS conflict during concurrent
endpoint operations), sbLeave() returned early without calling
deleteDriverInfoFromCluster(). This left the endpoint's
overlay_peer_table record behind in NetworkDB, so no DELETE gossip event
was emitted, and remote nodes never removed the corresponding
neighbor/FDB state. This causes stale permanent ARP/FDB entries to
accumulate in overlay network namespaces, eventually blackholing TCP
traffic and producing intermittent 502/504 until the service is
redeployed.

Fix this by removing the early return on storeEndpoint failure.
Instead, accumulate errors and continue the full leave operation.

Assisted-by: GPT-5.2 (AI)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-04-16 12:59:36 +02:00
Paweł Gronowski
cdce8f4f92 modernize: Use maps.Copy instead of for loops
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-12-15 18:56:33 +01:00
Rob Murray
baf59d62d6 Merge pull request #51592 from robmry/sbleave_gw_config_error
Suppress errors from gateway re-config when disconnecting a network
2025-11-26 16:07:41 +00:00
Rob Murray
8f2aa3e0f5 Network disconnect: log rather than error on gateway update
During a network disconnect, log rather than returning an error
if it's not possible to set up a new gateway.

This restores the behaviour from before commit 53390f8 ("Put
clearNetworkResources() inline in its only caller"). It's not
ideal, but by the time new gateways are selected the old
endpoint has been disconnected - and nothing puts things back.
Until that's cleaned up, a broken state is inevitable, but
letting endpoint deletion complete means the container can
be restarted or re-connected to the network without a zombie
endpoint causing further issues.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-11-26 14:45:18 +00:00
Rob Murray
731ae07e65 Endpint.sbLeave: when deleting container, no new gateway
When the endpoint providing a container's default gateway
is removed, there's no need to select a new gateway if the
container is being removed.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-11-25 18:11:07 +00:00
Rob Murray
a2de9bb334 Unmap more netip.Addr vars created using AddrFromSlice
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-11-24 16:51:14 +00:00
Rob Murray
1731e9e729 Don't try to remove cleared docker_gwbridge endpoint
If a container is using a docker_gwbridge endpoint as its gateway,
when it's connected to another network that provides a gateway, the
docker_gwbridge endpoint is removed when that endpoint is added (in
a recursive nightmare).

So, the "before" gateway for the container has been removed
before the new gateway is updateExternalConnectivity'd.

Don't pass the old gateway to updateExternalConnectivity in that
case, because the network driver's already forgotten about it.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-11-14 17:41:01 +00:00
Sebastiaan van Stijn
d481c09fa7 libnetwork/drivers/macvlan, ipvlan: make driver.leave a stub
These drivers did not do anything meaningful in the `Leave` method; they
would check if the network and/or endpoint were missing, in which case
they produced an error, but the network and endpoint (if present) would
not be used, so it was only validation.

Such validation could still be relevant elsewhere, but looking at where
this method is called; the `Driver.Leave()` is called in two places, both
of which don't handle the error, other than logging it as a warning / error;

It's called by `Endpoint.sbJoin()`, as part of the rollback;
d5c838dc5e/daemon/libnetwork/endpoint.go (L539-L545)

And `Endpoint.sbLeave()`, which also discards the error;
d5c838dc5e/daemon/libnetwork/endpoint.go (L772-L776)

Based on he above, this code looks to be redundant, so replacing it with
a stub; returning `nil`.

As replacing the code removed the use of network.getEndpoint, which was effectively
a copy of network.endpoint (which didn't have error handling), I merged the two
methods, and removed custom error-handling elsewhere.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-10-20 08:14:44 +02:00
Cory Snider
d5c838dc5e internal: move sliceutil from daemon/internal
These utilities are very handy to use in integration tests, too. Move
the package so it can be imported by them.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2025-10-03 21:39:14 +02:00
Rob Murray
2bb0443ae9 Release IPv6 address if unused due to sysctl setting
When running:
  docker network create --ipv6 b46
  docker run --rm -ti \
    --network name=b46,driver-opt=com.docker.network.endpoint.sysctls=net.ipv6.conf.IFNAME.disable_ipv6=1 \
     busybox

IPv6 is enabled in the container and the network, so an IPv6 address
will be allocated for the endpoint.

But, when the sysctl is applied, the IPv6 address will be removed
from the interface ... so, no unsolicited neighbour advertisement
should be (or can be) sent and, the endpoint should not be treated
as dual-stack when selecting a gateway endpoint and, if it is
selected as the gateway endpoint, setting up an IPv6 route via the
network will fail.

So, if the IPv6 address disappears after sysctls have been applied,
release the address and remove it from the endpoint's config.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-15 10:39:08 +01:00
Rob Murray
252659278e Configure addresses before adding them to DNS or /etc/hosts
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-15 10:39:08 +01:00
Rob Murray
18b8e369ae Split OS-specific code out of Sandbox.populateNetworkResources
And move the Endpoint.populateNetworkResources code into the
all-platforms part of the Sandbox method.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-15 10:39:08 +01:00
Rob Murray
ddf10ee1cd Delay Endpoint config until the osSbox exists
When the SetKey hook is used (by a build container) it's called after
Endpoint.sbJoin, which will have called Sandbox.populateNetworkResources
to set up address, routes, sysctls and so on - but it's not able to do
any config until the osSbox exists. So, Sandbox.populateNetworkResources
is called again by SetKey to finish that config.

But, that means the rest of Endpoint.sbJoin has already happened before
the osSbox existed - it will have configured DNS, /etc/hosts, gateways
and so on before anything was set up for the OS.

So, if the osSbox configuration isn't applied as expected (for example,
a sysctl disables IPv6 on the endpoint), that sbJoin configuration is
incorrect.

To avoid unnecessary config+cleanup in thoses cases - delay the config
currently done by sbJoin until the osSbox exists.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-15 10:39:08 +01:00
Rob Murray
52c9cfd016 Use sbLeave to roll back on error from sbJoin
The old deferred error handling cleared ep.sandboxID, but only
in a copy of the Endpoint loaded from the store, not stored or
returned - so the modification was immediately lost.

It also tried to remove the endpoint from the Sandbox's 'endpoints',
but the remove function compared pointers rather than ids, so
nothing was removed. Removing it would have broken rollback anyway.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-11 13:02:41 +01:00
Rob Murray
53390f85dd Put clearNetworkResources() inline in its only caller
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-11 13:02:41 +01:00
Rob Murray
916fa31ab5 Acquire Sandbox.joinLeaveMu for Endpoint force-Delete
If an endpoint is still attached to a Sandbox when
Endpoint.Delete is called with force=true, sbLeave is
called. It may change the Sandbox's gateway, which may
conflict with a concurrent Join.

So, acquire the Sandbox's joinLeaveMu to do that, and
clarify the purpose of that mutex in struct Sandbox
comments.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-11 13:02:41 +01:00
Rob Murray
a9db1e9a26 Endpoint.sbLeave: don't load ep from store
Because it loaded the Endpoint object from store and operated
on that copy rather than its own receiver, sbJoin couldn't
successfully roll back on error if the Endpoint was not included
in the Sandbox's list of endpoints, or its current state had
not been written to store after the error occurred.

So, for example, releaseOSSboxResources() would not be called
to delete interfaces created in the container's netns.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-09-11 13:02:41 +01:00
Albin Kerouanton
3003c5fe45 d/libnet: fix CreateOptionIPAM capitalization
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-08-27 00:18:46 +02:00
Albin Kerouanton
c9a0c93b04 d/libnet: remove unused arg from CreateOptionIpam
CreateOptionIpam takes an `ipamOptions` argument, but all callers are
passing nil. So, remove it.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-08-26 20:15:24 +02:00
Sebastiaan van Stijn
7960f742a2 daemon/libnetwork: Endpoint.CopyTo: use maps/slices.Clone
Modernize using maps.Clone, slices.Clone. This method is needed to
satisfy the datastore.KVObject interface, so also assert it does.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-12 11:39:55 +02:00
Sebastiaan van Stijn
a82a68a445 daemon/libnetwork: replace endpointJoinInfo.CopyTo with Copy()
The endpointJoinInfo.CopyTo function expected the caller to construct an
EndpointInterface to copy to, but all callsites created an empty struct.
In addition, `CopyTo` would never return an error, so the error return
was redundant.

Replace it with a `Copy()` function, which makes it easier to
consume.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-12 11:39:55 +02:00
Sebastiaan van Stijn
2d5100749d daemon/libnetwork: replace EndpointInterface.CopyTo with Copy()
The EndpointInterface.CopyTo function expected the caller to construct an
EndpointInterface to copy to, but all callsites created an empty struct.
In addition, `CopyTo` would never return an error, so the error return
was redundant.

Replace it with a `Copy()` function, which makes it easier to
consume.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-12 11:39:48 +02:00
Sebastiaan van Stijn
0a89d98bad daemon/libnetwork/types: remove errdefs aliases
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-10 20:18:02 +02:00
Sebastiaan van Stijn
cf15d5bbc6 remove obsolete //go:build tags
These are no longer needed as these are now part of a module.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-01 00:49:22 +02:00
Derek McGowan
f74e5d48b3 Create github.com/moby/moby/v2 module
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-31 10:13:29 -07:00
Sebastiaan van Stijn
ca1c5ee08f pkg/stringid: move to daemon, and provide copy in client
The stringid package is used in many places; while it's trivial
to implement a similar utility, let's just provide it as a utility
package in the client, removing the daemon-specific logic.

For integration tests, I opted to use the implementation in the
client, as those should not ideally not make assumptions about
the daemon implementation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-07-25 13:39:32 +02:00
Derek McGowan
5b913b3ea0 Move internal/sliceutil to daemon/internal/sliceutil
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-24 12:15:19 -07:00
Derek McGowan
7a720df61f Move libnetwork to daemon/libnetwork
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-14 09:25:23 -07:00