Namespace.RemoveInterface closes the Interface's stopCh to stop the
unsolicited ARP/NA sender, but only unregisters the Interface from the
Namespace once the removal has completed. Several failure exits sit in
between, so a removal that fails part-way leaves the Interface
registered with a closed stopCh.
Callers tear interfaces down by iterating over Namespace.Interfaces, so
the same *Interface is handed back to RemoveInterface during a later
teardown, and the second close panics, taking down the API request
being served:
http: panic serving @: close of closed channel
Seen in CI while disconnecting an endpoint during Sandbox.Refresh:
LinkSetNsFd failed with EBADF after the link had already been renamed
back to its source name, so the following re-join couldn't find the
link, and the rollback in Endpoint.sbJoin removed the same Interface
again.
Close stopCh through a sync.Once, so the ARP/NA sender is still
guaranteed to stop whether or not the netlink teardown succeeds, and
however many times removal is attempted. Keep leaving a failed
Interface registered in the Namespace: the link may still be present
there, and generateIfaceName relies on n.iFaces to avoid handing out
its name again.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Cory Snider <csnider@mirantis.com>
The LinkSubscribe cleanup path is documented as bounded, but the timeout case only logged a warning and kept waiting for the update channel to close. If the subscription goroutine does not terminate, the deferred cleanup can still block forever after the warning.
Return from the drain loop after logging the timeout so waitForIfUpped can finish its bounded cleanup path.
Signed-off-by: Darafei Praliaskouski <me@komzpa.net>
When the Docker daemon restarts with live-restore enabled, containers
retain their network namespaces but neighboring hosts may have stale
ARP/neighbor cache entries. This causes IPv6 connectivity issues because
unlike IPv4, where gratuitous ARP is sent on interface setup, IPv6
relies on Neighbor Discovery Protocol which requires explicit Neighbor
Advertisement messages to update caches.
This change adds unsolicited ARP (for IPv4) and Neighbor Advertisement
(for IPv6) messages when restoring interfaces after a daemon restart,
mirroring the behavior that already exists in AddInterface for new
containers.
The fix also handles network drivers (such as SR-IOV and macvlan) that
don't store the MAC address in the endpoint configuration by fetching
it from the actual link when needed.
Signed-off-by: Paul Saab <ps@mu.org>
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>