This code was added in 85b260fba8, but didn't
account for maps.Clone returning a `nil` map if the map cloned was `nil`.
This could lead to a panic, similar to the panic that was fixed in
7517464283d29969c4d3615397b369abd99ce395;
panic: assignment to entry in nil map
goroutine 498 [running]:
github.com/moby/moby/v2/daemon.buildPortsRelatedCreateEndpointOptions(0x400042f348, 0xaaaabcc8f458?, 0x40006feb40)
/root/build-deb/engine/daemon/network.go:1047 +0x844
github.com/moby/moby/v2/daemon.buildCreateEndpointOptions(0x400042f348, 0x4001015040, 0x400027d320, 0x40006feb40, {0x0, 0x0, 0x4001506cb8?})
/root/build-deb/engine/daemon/network.go:988 +0x20c
github.com/moby/moby/v2/daemon.(*Daemon).connectToNetwork(0x4000898008, {0xaaaabe21d9f8, 0x4000f12b10}, 0x400089a008, 0x400042f348, {0x400077a9f0, 0x6}, 0x400027d320)
/root/build-deb/engine/daemon/container_operations.go:738 +0x66c
github.com/moby/moby/v2/daemon.(*Daemon).allocateNetwork(0x4000898008, {0xaaaabe21d9f8, 0x4000f12b10}, 0x400089a008, 0x400042f348)
/root/build-deb/engine/daemon/container_operations.go:421 +0x298
github.com/moby/moby/v2/daemon.(*Daemon).initializeCreatedTask(0x4000898008, {0xaaaabe21d9f8, 0x4000f12b10}, 0x400089a008, {0xaaaabe23dc60, 0x4000eb21c8}, 0x400042f348, 0xaaaabd4db3df?)
/root/build-deb/engine/daemon/start_linux.go:37 +0x260
github.com/moby/moby/v2/daemon.(*Daemon).containerStart(0x4000898008, {0xaaaabe21d9c0, 0xaaaabfa05300}, 0x400089a008, 0x400042f348, {0x0, 0x0}, {0x0, 0x0}, 0x1)
/root/build-deb/engine/daemon/start.go:242 +0xba8
github.com/moby/moby/v2/daemon.(*Daemon).restore.func4(0x400042f348, 0x400117f1f0)
/root/build-deb/engine/daemon/daemon.go:633 +0x308
created by github.com/moby/moby/v2/daemon.(*Daemon).restore in goroutine 1
/root/build-deb/engine/daemon/daemon.go:607 +0x5ec
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Make invalid states unrepresentable by moving away from stringly-typed
MAC address values in API structs. As go.dev/issue/29678 has not yet
been implemented, provide our own HardwareAddr byte-slice type which
implements TextMarshaler and TextUnmarshaler to retain compatibility
with the API wire format.
When stdlib's net.HardwareAddr type implements TextMarshaler and
TextUnmarshaler and GODEBUG=netmarshal becomes the default, we should be
able to make the type a straight alias for stdlib net.HardwareAddr as a
non-breaking change.
Signed-off-by: Cory Snider <csnider@mirantis.com>
Clients should not make assumptions about the validity of an API struct
as the set of well-formed values may differ across daemon versions.
Remove it from the API module so client-application authors are not
tempted to apply it, which would restrict the forward compatibility of
the client.
Signed-off-by: Cory Snider <csnider@mirantis.com>
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>
On API v1.52 and newer, the GET /networks/{id} endpoint returns
statistics about the IPAM state for the subnets assigned to the network.
Signed-off-by: Cory Snider <csnider@mirantis.com>
While the network Summary and Inspect types have been aliases in Go's
type system, in practice there is a difference: the Containers and
Services fields are only populated when inspecting a network. Split out
the common fields into a base network.Network struct which is embedded
in the network.Summary and network.Inspect types.
Signed-off-by: Cory Snider <csnider@mirantis.com>
Construct a network.Filter from the filters.Args only once per API
request so we don't waste cycles re-validating an already validated
filter. Since (*Daemon).NetworksPrune is implemented in terms of
(Cluster).GetNetworks, that method now accepts a network.Filter instead
of a filter.Args. Change the signature of (*Daemon).GetNetworks for
consistency as both of the GetNetworks methods are used by network API
route handlers.
Signed-off-by: Cory Snider <csnider@mirantis.com>
Internally a network is represented by either a libnetwork.Network or a
swarmapi.Network. The daemon functions backing the API server map
these values to the Engine API network.Inspect type on demand. Since
they have to convert, the functions to get a list of networks have to
loop over the slice of Networks and append them to a slice of
network.Inspect values.
The function used to filter the list of networks by a user-supplied
predicate takes a []network.Inspect and returns a shorter slice.
Therefore the daemon functions backing the API server have to loop
through the list twice: once to convert, and again inside the
FilterNetworks function to delete networks from the slice which do not
match the filter predicate. Each time an item is deleted from a slice,
all items at higher indices need to be copied to lower indices in the
backing array to close the hole.
Replace FilterNetworks with a function that accepts a single
interface-valued network and returns a boolean. Amend libnetwork.Network
and write a thin adapter for swarmapi.Network so both implement the
aforementioned interface. The daemon functions can thus filter networks
before projecting the values into API structs, and can completely skip
over non-matching networks, which cuts down on a nontrivial amount of
copying.
Split the validation of the filter predicate from filter evaluation to
both make it more ergonomic to use inside loops, and to make invalid
states (a filter with an ill-formed predicate) unrepresentable.
Signed-off-by: Cory Snider <csnider@mirantis.com>
Modernize the field and allow using it as-is in some places, or
convert it to a string (which won't produce an error down the line).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Staticcheck is suggesting to cast the type or to directly copy, but
doesn't account for nat.SortPortMap mutating the second argument, so
mutating the HostConfig.PortBindings. From the code, it looks like the
intent here was to prevent that (creating a deep copy), so let's keep
that.
daemon/container_operations.go:109:39: S1016: should convert bb (type github.com/docker/docker/vendor/github.com/docker/go-connections/nat.PortBinding) to github.com/docker/docker/vendor/github.com/moby/moby/api/types/container.PortBinding instead of using struct literal (staticcheck)
bindings[p] = append(bindings[p], containertypes.PortBinding{
^
daemon/network.go:952:39: S1016: should convert bb (type github.com/docker/docker/vendor/github.com/docker/go-connections/nat.PortBinding) to github.com/docker/docker/vendor/github.com/moby/moby/api/types/container.PortBinding instead of using struct literal (staticcheck)
bindings[p] = append(bindings[p], containertypes.PortBinding{
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Follow-up to 494677f93f, which added
the aliases, but did not yet replace our own use of the nat types.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The "backend" types in API were designed to decouple the API server
implementation from the daemon, or other parts of the code that
back the API server. This would allow the daemon to evolve (e.g.
functionality moved to different subsystems) without that impacting
the API server's implementation.
Now that the API server is no longer part of the API package (module),
there is no benefit to having it in the API module. The API server
may evolve (and require changes in the backend), which has no direct
relation with the API module (types, responses); the backend definition
is, however, coupled to the API server implementation.
It's worth noting that, while "technically" possible to use the API
server package, and implement an alternative backend implementation,
this has never been a prime objective. The backend definition was
never considered "stable", and we don't expect external users to
(attempt) to use it as such.
This patch moves the backend types to the daemon/server package,
so that they can evolve with the daemon and API server implementation
without that impacting the API module (which we intend to be stable,
following SemVer).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
These comments were added to enforce using the correct import path for
our packages ("github.com/docker/docker", not "github.com/moby/moby").
However, when working in go module mode (not GOPATH / vendor), they have
no effect, so their impact is limited.
Remove these imports in preparation of migrating our code to become an
actual go module.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
daemon/network.go:156:3: S1000: should use for range instead of for { select {} } (staticcheck)
for {
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
When a network is created with "-o com.docker.network.enable_ipv4'
(including via "default-network-opts" in daemon config), and
EnableIPv4 is present in the API request (including when CLI option
"--ipv4" is used) - the top-level API value is used and the '-o'
is ignored.
But, the "-o" still shows up in Options in inspect output, which is
confusing if the values are different.
So, drop the "-o" if the top-level API option is set. Ditto IPv6.
Signed-off-by: Rob Murray <rob.murray@docker.com>
Add an OTel span processor copying the 'trigger' baggage member
propagated through contexts to all children spans. It's used to identify
what triggered a trace / span (API call, libnet init, etc...)
All code paths that call libnet's `NewNetwork` set this baggage member
with a unique value.
For instance, this can be used to distinguish bridge's `createNetwork`
spans triggered by daemon / libnet initialization from custom network
creation triggerd by an API call.
Two util functions are added to wrap `baggage.New` and
`baggage.NewMemberRaw` to make it easier to deal with baggage and
members by panicking on error. These should not be used with dynamic
values.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Plumb context from the API down to libnet driver method `CreateNetwork`,
and add an OTel span to the bridge driver's `createNetwork` method.
Include a few attributes describing the network configuration (e.g.
IPv4/IPv6, ICC, internal and MTU).
A new util function, `RecordStatus`, is added to the `otelutil` package
to easily record any error, and update the span status accordingly.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
With improved IPv6 support, a dual-stack container can map a port using
two different networks -- one IPv4-only, the other IPv6-only.
The daemon was updating containers' `EndpointSettings.Ports` by looking
for the first network providing port-mappings. This was incorrect.
Instead, iterate over the whole list of endpoints, and merge everything
together.
The function doing that, ie. `getEndpointPortMapInfo`, is also
considered exposed ports, and nil the PortMap entry if an exposed port
is found. However, exposed ports are always set on a bridge network, so
this was erasing port-mappings found for other networks.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Instead, log the error returned by `nat.NewPort` and move on to the
next port mapping / exposed port.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Creating a swarm network from a config-only network failed
because the new EnableIPv4 wasn't validated/propagated
correctly.
So:
- Always initialise EnableIPv4 to true, including for a config
only network, and on load from the store.
- Treat enableIPv4=true as the no-overridden state when checking
params for a config-from network.
- Propagate settings from the config 'Network' objects attributes
to its generic options, because the network driver only sees
generic options.
- This was happening already for Network.internal, after the
config-only network options were processed. Move that to
'applyConfigurationTo'.
- Add enableIPv4/enableIpv6 - enableIPv6 will normaly be present
anyway. But, for a network created pre-28.x and restored from
the store, there was no entry for 'netlabel.EnableIpv4'.
- Extend TestSwarmScopedNetFromConfig to start a service and
check it's ok.
Signed-off-by: Rob Murray <rob.murray@docker.com>
When an IPv6 network is first created with no specific IPAM config,
network inspect adds a CIDR range to the gateway address. After the
daemon has been restarted, it's just a plain address.
Once the daaemon's been restated, "info" becomes "config", and the
address is reported correctly from "config".
Make the IPv6 code to report the gateway from "info" use net.IPNet.IP
instead of the whole net.IPNet - like the IPv4 code.
Signed-off-by: Rob Murray <rob.murray@docker.com>
Since commit 933fcc9 (Re-remove the SetKey OCI prestart hook),
the network namespace will be set up before endpoints are
created in most cases, apart from build containers.
So, when possible, create the veth with one end in that netns
to save moving it in later. On my host, that saves about 20ms
for each bridge network a container is connected to.
Signed-off-by: Rob Murray <rob.murray@docker.com>
This function was added in eb982e7c00, at
which time networking was not yet implemented for Windows, resulting
in a panic when trying to call network-related endpoints.
That's no longer the case, so we should be able to add network-endpoints
unconditionally.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This new field is used by libnetwork to determine which endpoint
provides the default gateway for a container.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
When a container doesn't support IPv6 and it's joined to an IPv6
network, don't allocate an IPv6 address for it.
Update the DNS resolver to understand that it can have an 'ipv6miss'
(meaning an IPv4 address exists, but no IPv6) when a network is
IPv6 enabled.
Signed-off-by: Rob Murray <rob.murray@docker.com>
Similar to EnableIPv6:
- Set it if EnableIPv4 is specified in a create request.
- Otherwise, set it if included in `default-network-opts`.
- Apart from in a config-from network, so that it doesn't look
like the API request set the field.
- Include the new field in Network marshalling/unmarshalling test.
Signed-off-by: Rob Murray <rob.murray@docker.com>