In rootless mode, the Engine needs to call the rootless port driver to
know which IP address it should bind to inside of its network namespace.
The slirp4netns port drivers doesn't support binding to IPv6 address, so
we need to detect that before listening on the port.
Before commit 201968cc0, this wasn't a problem because the Engine was
binding the port, then calling rootless port driver to learn whether the
proto/IP family was supported, and listen on the port if so.
Starting with that commit, the Engine does bind + listen in one go, and
then calls the port driver — this is too late. Fix the bug by checking
if the port driver supports the PortBindingReq, and only allocate the
port if so.
Signed-off-by: Albin Kerouanton <albin.kerouanton@docker.com>
Make the DiscoverNew switch only responsible for asserting the correct
data type, and push the conversion logic into the setKeys and updateKeys
methods.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
- Inline some vars and align between drivers
- Remove nested if's where possible
- Use `WithError` for some logs, and use the context if available
- Scope variables locally where only used locally and, the reverse,
make it clear where a (function-)global variable is used.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This function was calling driver.getNetworks, which copies the networks map
into a new slice. As we're not mutating the networks, we can just use the
networks map itself to check if there's any networks configured with the
same parent.
While changing;
- Also change the signature to accept the parent to compare to as a string
- Return early once we determined there's more than one user
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Both were added as part of the initial implementation in commit [moby@ea30113]
([libnetwork@1d6f2c5]), but never used.
[moby@ea30113]: ea30113303
[libnetwork@1d6f2c5]: 1d6f2c59c4
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This utility was only called with two constant values;
const (
defaultV4RouteCidr = "0.0.0.0/0"
defaultV6RouteCidr = "::/0"
)
However;
- calling it would always execute a `net.ParseCIDR`
- verify if it would produce an error (which would be very unlikely)
- it used a `staticRoute` struct that was ONLY used for this function
- and immediately deconstructed into its components
- furthermore, the `NextHop` field would be discarded by jinfo.AddStaticRoute,
which only used the third argument for `routeType == types.NEXTHOP`
This patch:
- removes the `ifaceGateway` and associated `staticRoute` and consts
- defines two package-level vars for `defaultV4Net` and `defaultV6Net`,
which can be reused (no need to parse / construct them for every join)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
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>
These methods were just wrappers around getSubnetforIP; let's peel away the
abstraction and call it directly; we're already checking for n.config.Ipv4Subnet
and n.config.Ipv6Subnets on the call-site, so may as well just pass it in.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
There were some missing checks whether ep.addr, ep.addrv6 were nil,
which could panic in getSubnetForIP.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
The function was fetching a reference to the endpoint twice; while this
did give the option for an early return, in practice it didn't mean much,
because it could still fail if the endpoint was removed in between.
This code still has a race condition, because while a reference to the
endpoint is retrieved while acquiring a lock, the result is mutated without.
This probably needs to either have some accessor, or the function should
keep a lock for the whole operation (possibly switching to an RWMutex).
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
When the bridge driver encounters an error during network
creation, delete the bridge device if one has been added.
Signed-off-by: Rob Murray <rob.murray@docker.com>
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>
These utilities are going to be needed elsewhere in the daemon to handle
netip values from API requests.
Signed-off-by: Cory Snider <csnider@mirantis.com>
Allow tests to run in parallel with separate network namespaces,
without modifying the global-state namespace/netlink handles in
the "ns" package ... only useful for tests that don't depend on
package "ns".
Use the new option in iptabler/nftabler tests.
Signed-off-by: Rob Murray <rob.murray@docker.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>
After creating a new network, inspect shows that there's no value
for option "com.docker.network.windowsshim.networkname". After
restarting the daemon, it shows up with the docker network name
(not the HNS network name, which defaults to the docker network's
id).
Creating the network with "-o com.docker.network.windowsshim.networkname"
sets the HNS network name, and it shows up in inspect. Until the
daemon is restarted, then it shows the docker network name.
So - set the option value to the HNS network name on creation (the id
if no name is given), and on restore after restart use the name
reported by HNS.
Signed-off-by: Rob Murray <rob.murray@docker.com>
When ipvlan in "l2" mode is given no '--gateway' option, an
address is allocated from IPAM and a default route is set up
via that gateway. But, the gateway address is not assigned to
anything in the Docker ipvlan network - it must be external,
and IPAM shouldn't try to guess it.
So ...
- always disable IPAM gateway address allocation for ipvlan-l2
- tell libnet to assume the endpoint has a gateway instead
- update the Join code to allow for no configured gateway
- always disable 'docker_gwbridge' connection for ipvlan
networks, so it's not hooked up when there is no gateway
address.
Signed-off-by: Rob Murray <rob.murray@docker.com>
When macvlan is given no '--gateway' option, an address is
allocated from IPAM and a default route is set up via that
gateway. But, the gateway address is not assigned to anything
in the Docker macvlan network - it must be external, and
IPAM shouldn't try to guess it.
When IPv6 auto-configuration is enabled in the network the
macvlan is connected to, the macvlan driver races against it
to set up the gateway. When autoconfig wins, container creation
fails because the default route already exists.
So ...
- disable IPAM gateway address allocation for macvlan
- update the Join code to allow for no configured gateway
- always disable 'docker_gwbridge' connection for macvlan
networks, so it's not hooked up when there is no gateway
address.
Libnet assumes an endpoint with no statically configured default
gateway or route does not provide external connectivity. So, it
disables external DNS access, and will not select the endpoint
as gateway for containers. So, where an IPAM allocated gateway
address would have been assigned before, tell libnet to assume
there will be an auto-configured gateway.
Signed-off-by: Rob Murray <rob.murray@docker.com>
The only viable way to allocate a port is to bind and listen to it. So,
the windows PortMapper was really a PortAllocator in disguise.
Rename it to OSAllocator and move it to the portallocator package.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
The windows port mapper is needlessly complex while its job is pretty
straightforward: reserve a port through the port allocator, and start a
dummy proxy to allocate it from the OS.
The biggest source of complexity is the use of the `net.Addr` interface
to pass the host IP, port and proto. `MapRange` now has a proto arg, and
returns the allocated port.
`MapRange` is also instantiating a `mapping` struct whose fields are
all unused, except for its `stopUserlandProxy`. Instead, store
`stopProxy` callbacks directly into the `PortMapper`.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
newDriver, which creates a new instance of the bridge driver, is the
only place where the driver config field is set. So there's no need to
gate access to it with a mutex.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Libnetwork passes a map[string]any to the bridge driver's Register
function. This forces the daemon to convert its configuration into a
map, and the driver to convert that map back into a struct.
This is unnecessary complexity, and makes it harder to track down where
and how bridge driver configuration fields are set.
Refactor libnetwork to let the daemon register the bridge.Configuration
directly through a new option `OptionBridgeConfig`.
The bridge driver now takes a `Configuration` param that needs no
special treatment.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
This method is only used by the cnmallocator to allocate Swarm-scoped
network resources. Its only concrete implementation is in the ovmanager.
Other network drivers are implementing it too to adhere to the
driverapi.Driver interface, but they all return a 'not implemented'
error.
Extract this method into a separate interface, and add a dedicated
RegisterNetworkAllocator to the driver registry. Update the cnmallocator
to load 'network allocators' instead of 'drivers'.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>