Skip to content

libnet/cnmallocator: don't fail OnGetNetwork if unallocated - #53325

Merged
vvoland merged 1 commit into
moby:masterfrom
corhere:ongetnetwork-unallocated
Aug 10, 2026
Merged

libnet/cnmallocator: don't fail OnGetNetwork if unallocated#53325
vvoland merged 1 commit into
moby:masterfrom
corhere:ongetnetwork-unallocated

Conversation

@corhere

@corhere corhere commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary

cnmNetworkAllocator.OnGetNetwork returned an error when the network was not in the allocator's map of allocated networks. Its own interface contract forbids that:

// The network may not have been allocated at the time of the call.
// Calling OnGetNetwork with an unallocated network should not be an
// error.

A network is in the store but unallocated in two ordinary situations:

  • The allocator has yet to restore it. allocateNetworks() deliberately skips networks with no driver state or IPAM during manager init, so as not to hand out resources another network already holds.
  • Its allocation failed. allocateNetwork() parks the network in unallocatedNetworks for a later retry and doNetworkAlloc() only logs Failed allocation for network %s. A VNI collision gets you here: pin a com.docker.network.driver.overlay.vxlanid_list that another network already holds and the overlay manager returns could not assign vxlan id. Allocation happens after the spec is committed to Raft, so network create has already returned success.

The consequence reached well past the one network. Cluster.GetNetworks requests every Swarm network with no filters, deliberately — the Engine API's filter semantics are richer than swarmkit's, so the matching has to happen client-side — and swarmkit runs the hook per network over that unfiltered listing. One unallocated network therefore failed the whole response. The network inspect route falls back to that listing to resolve a name and reports a failed lookup as ErrNoSuchNetwork, so:

$ docker network inspect healthy-net
Error response from daemon: network healthy-net not found

...for a network that is perfectly healthy, because an unrelated one could not report status.

Report no status instead. An absent Status is already how "no status available" is expressed — it is what a manager whose IPAM driver does not implement PoolStatuser returns — and the unallocated condition stays visible in what the allocator never filled in: an empty IPAM config and no VNI echoed back.

Scope

Only requests that ask for status reach the hook, so this affected API v1.52 and later only. Within that, the reachable paths are:

Request Before
network inspect <name>, no scope filter 404, even for a healthy network
network inspect <unallocated> 404
network inspect <full-id> / --scope=swarm OK — resolved from a filtered lookup that never sees the unallocated network
network ls OK — does not request status

Testing

TestOnGetNetworkUnallocated covers the contract directly, with TestOnGetNetworkAllocated as a positive control so it cannot pass by status reporting having stopped working altogether.

Release notes (optional)

Fix `docker network inspect` failing to find a healthy Swarm network when another Swarm network could not be allocated.

A picture of a cute animal (not mandatory but encouraged)

Created with: Claude Opus 5

@corhere
corhere requested review from thaJeztah and vvoland August 6, 2026 23:16
@corhere corhere added this to the 29.8.0 milestone Aug 6, 2026
@github-actions github-actions Bot added area/networking Networking area/daemon Core Engine labels Aug 6, 2026
OnGetNetwork errored when the network was absent from the allocator's map of
allocated networks, which its own interface contract forbids:

	// The network may not have been allocated at the time of the call.
	// Calling OnGetNetwork with an unallocated network should not be an
	// error.

That state is not hypothetical. A network is in the store but unallocated
whenever the allocator has yet to restore it - allocateNetworks() skips
networks with no driver state or IPAM during init, so as not to hand out
resources another network already holds - and whenever its allocation
failed, which only logs and parks the network for a later retry.

The consequence reached well past the one network. Cluster.GetNetworks
requests every Swarm network with no filters, deliberately: the Engine API's
filter semantics are richer than swarmkit's, so the matching has to happen
client-side. Swarmkit runs the hook per network over that unfiltered
listing, so one unallocated network failed the whole response. The network
inspect route falls back to that listing to resolve a name and reports a
failed lookup as "no such network", which made inspecting a perfectly
healthy Swarm network by name 404 because an unrelated network could not
report status.

Report no status instead. An absent Status is already how "no status
available" is expressed - it is what a manager whose IPAM driver does not
implement PoolStatuser returns - and the unallocated condition stays visible
in what the allocator never filled in: an empty IPAM config and no VNI.

Only requests which ask for status reach the hook, so this was limited to
API v1.52 and later. Listing networks was unaffected either way; it does not
request status.

Signed-off-by: Cory Snider <csnider@mirantis.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@corhere
corhere force-pushed the ongetnetwork-unallocated branch from 50c46fa to 1b7bdd0 Compare August 7, 2026 00:07

@vvoland vvoland left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@vvoland
vvoland merged commit 4d02298 into moby:master Aug 10, 2026
223 of 225 checks passed
@thaJeztah

Copy link
Copy Markdown
Member

Cluster.GetNetworks requests every Swarm network with no filters, deliberately — the Engine API's filter semantics are richer than swarmkit's, so the matching has to happen client-side — and swarmkit runs the hook per network over that unfiltered listing.

Haven't looked what filters would be relevant here, but is that something that could be added to swarmkit? Would it be useful / improve performance? @corhere

@corhere
corhere deleted the ongetnetwork-unallocated branch August 18, 2026 16:26
@corhere

corhere commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Haven't looked what filters would be relevant here, but is that something that could be added to swarmkit? Would it be useful / improve performance?

It would improve performance on a cluster with a large number of networks when the Engine API request is received on a non-leader manager as the whole unfiltered Swarmkit API response has to traverse the network. But it's still just O(n); pushing the filter into Swarmkit only shrinks n -- a linear improvement. Is the code path hot enough and the existing performance at practical limits (10k networks?) bad enough for optimizations to be worthwhile?

@thaJeztah

Copy link
Copy Markdown
Member

Is the code path hot enough and the existing performance at practical limits (10k networks?) bad enough for optimizations to be worthwhile?

Good question; not sure; mostly considering if it's easy / not much work to add a filter, it could simplify things?

@vvoland vvoland removed the area/api API label Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants