312 Commits

Author SHA1 Message Date
Rob Murray
fbf2fe8b7d Eliminate warning about endpoint count store delete
Commit 380ded6 restored a now-unused endpoint count to the
store, so that when the daemon is downgraded it exists for
the old code to find.

But, on network deletion, the endpoint count was not loaded
from the store - so the delete code saw the wrong "index",
and logged a warning before deleting it anyway.

Use DeleteObject instead of DeleteObjectAtomic, so the old
index isn't checked.

Signed-off-by: Rob Murray <rob.murray@docker.com>
(cherry picked from commit 94bcf89412)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-29 15:15:55 +02:00
Paweł Gronowski
6a1fb46d48 Merge pull request #50169 from robmry/revert_overlay_refactoring
[28.x]: Revert overlay bug fixes / refactoring
2025-06-13 15:49:07 +00:00
Matthieu MOREL
6d737371b8 fix comparison rule from errorlint
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>

Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-13 08:26:56 +00:00
Rob Murray
ea818a7f6f Revert "libnetwork/internal/setmatrix: make keys generic"
This reverts commit 0317f773a6.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-06-11 12:05:33 +01:00
Matthieu MOREL
a62de57aa1 fix sprintfQuotedString from go-critic
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-07 09:57:59 +02:00
Matthieu MOREL
bc9ec5fc02 fix emptyStringTest from go-critic
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-07 09:57:59 +02:00
Matthieu MOREL
e5be7b54b1 fix yodaStyleExpr from go-critic
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2025-06-07 09:57:58 +02:00
Cory Snider
0317f773a6 libnetwork/internal/setmatrix: make keys generic
Make the SetMatrix key's type generic so that e.g. netip.Addr values can
be used as matrix keys.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2025-05-27 13:29:41 -04:00
Sebastiaan van Stijn
1028b123e8 integration, libnetwork: fix some godoc comments (ST1020)
integration/internal/network/ops.go:137:1: ST1020: comment on exported function WithIPAMRange should be of the form "WithIPAMRange ..." (staticcheck)
    // WithIPAM adds an IPAM with the specified Subnet, IPRange and Gateway to the network
    ^
    libnetwork/bitmap/sequence.go:50:1: ST1020: comment on exported function New should be of the form "New ..." (staticcheck)
    // NewHandle returns a new Bitmap of ordinals in the interval [0, n).
    ^
    libnetwork/diagnostic/server.go:61:1: ST1020: comment on exported method HandleFunc should be of the form "HandleFunc ..." (staticcheck)
    // Handle registers the handler function for the given pattern,
    ^
    libnetwork/endpoint.go:388:1: ST1020: comment on exported method Key should be of the form "Key ..." (staticcheck)
    // endpoint Key structure : endpoint/network-id/endpoint-id
    ^
    libnetwork/network.go:574:1: ST1020: comment on exported method MarshalJSON should be of the form "MarshalJSON ..." (staticcheck)
    // TODO : Can be made much more generic with the help of reflection (but has some golang limitations)
    ^
    libnetwork/network.go:633:1: ST1020: comment on exported method UnmarshalJSON should be of the form "UnmarshalJSON ..." (staticcheck)
    // TODO : Can be made much more generic with the help of reflection (but has some golang limitations)
    ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-05-14 10:11:59 +02:00
Rob Murray
f848191e40 Merge pull request #49901 from robmry/active_endpoints_error_error
Active endpoints error error
2025-05-09 09:29:33 +01:00
Rob Murray
5d8192fcce Report endpoint id as well as name in ActiveEndpointsError
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-30 12:42:26 +01:00
Sebastiaan van Stijn
7edd83a1b3 libnetwork: fix vars that shadowed, and slight refactor (govet)
libnetwork/network.go:637:6: shadow: declaration of "v" shadows declaration at line 634 (govet)
            if v, ok := n.generic[netlabel.GenericData]; ok {
               ^
    libnetwork/service_linux.go:125:7: shadow: declaration of "ep" shadows declaration at line 86 (govet)
                if ep := sb.getGatewayEndpoint(); ep != nil {
                   ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-28 15:23:51 +02:00
Sebastiaan van Stijn
7c52c4d92e update go:build tags to go1.23 to align with vendor.mod
Go maintainers started to unconditionally update the minimum go version
for golang.org/x/ dependencies to go1.23, which means that we'll no longer
be able to support any version below that when updating those dependencies;

> all: upgrade go directive to at least 1.23.0 [generated]
>
> By now Go 1.24.0 has been released, and Go 1.22 is no longer supported
> per the Go Release Policy (https://go.dev/doc/devel/release#policy).
>
> For golang/go#69095.

This updates our minimum version to go1.23, as we won't be able to maintain
compatibility with older versions because of the above.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-17 15:43:19 +02:00
Rob Murray
380ded6309 Store an endpoint count for networks, for downgrade
Since commit 51d7f95 ("libnet: remove struct endpointCnt") an
endpoint count for networks has not been persisted.

But, on downgrade to a version older than that commit, the
missing field caused daemon startup to fail.

So, create the count in the store - it only needs to exist, it's
no longer maintained as a count of endpoints. On downgrade, the
count is probably zero anyway (the daemon is stopped), but the
older daemon fixes it up on startup if necessary.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-15 17:59:34 +01:00
Albin Kerouanton
241d685574 libnet: add ep name in 'has active endpoints' error
There have been numerous reports of the "has active endpoints" error
over the years. Historically, there were some faulty code paths that
could lead to this error, but we believe they all have been fixed by
now.

However, users are still facing this error from time to time. Either
because they forgot that some containers are still running, or because
we still have bugs lying around.

To help users figure whether this error is legitimate, and what triggers
it, add endpoint names (which are just container names) to the error
message.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 10:53:56 +02:00
Albin Kerouanton
51d7f95c4b libnet: remove struct endpointCnt
endpointCnt is a refcounter used to track how many endpoints use a
network, and how many networks references a config-only network. It's
stored separately from the network.

This is only used to determine if a network can be removed.

This commit removes the `endpointCnt` struct and all its references. The
refcounter is replaced by two lookups in the newly introduced `networks`
and `endpoints` caches added to the `Controller`.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 11:21:17 +02:00
Albin Kerouanton
d377cd3810 libnet: Controller: cache networks in-memory
The `Controller`'s store is used by:

- `deleteFromStore`
- `getNetworks`
- `getNetworksFromStore`
- `updateToStore`
- … and other methods that can't store / delete / retrieve a Network

Calls to `updateToStore` and `deleteFromStore` have been replaced with
`upsertNetwork` and `deleteNetwork`.

Both `getNetworks` and `getNetworksFromStore` call `cacheNetwork` to
ensure networks loaded from the datastore are kept in-memory.

Finally, `sandboxRestore` was instantiating `Network` itself. These are
cached too.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 10:03:02 +02:00
Albin Kerouanton
cc8bd2016e libnet: Controller: cache endpoints in-memory
The `Controller`'s store is used by:

- `deleteFromStore`
- `getEndpointFromStore`
- `getEndpointsFromStore`
- `updateToStore`
- … and other methods that can't store / delete / retrieve an Endpoint

Calls to `updateToStore` and `deleteFromStore` have been replaced with
`upsertEndpoint` and `deleteEndpoint`.

Both `getEndpointFromStore` and `getEndpointsFromStore` call
`cacheEndpoint` to ensure endpoints loaded from the datastore are kept
in-memory.

Finally, `sandboxRestore` was instantiating `Endpoint` itself. These are
cached too.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 10:03:02 +02:00
Paweł Gronowski
f14c23a90f libnetwork: Update to any from interface{}
Only files that have go build version enforcing tag

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:42:51 +01:00
Rob Murray
468c2c814d Fix swarm network creation from a config-only network
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>
2025-02-24 17:48:23 +00:00
Sebastiaan van Stijn
1a047bbe8b libnetwork: ignore unchecked json (Un)Marshal errors (errchkjson)
These need revisiting, similar to similar code in libnetwork/drivers/bridge.
There was already a TODO in place for this, so ignoring these for now.

    libnetwork/endpoint.go:148:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        ib, _ := json.Marshal(epMap["ep_iface"])
                 ^
    libnetwork/endpoint.go:151:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        jb, _ := json.Marshal(epMap["joinInfo"])
                 ^
    libnetwork/endpoint.go:154:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        tb, _ := json.Marshal(epMap["exposed_ports"])
                 ^
    libnetwork/endpoint.go:159:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        cb, _ := json.Marshal(epMap["sandbox"])
                 ^
    libnetwork/endpoint.go:237:12: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        sal, _ := json.Marshal(epMap["svcAliases"])
                  ^
    libnetwork/endpoint.go:242:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        pc, _ := json.Marshal(epMap["ingressPorts"])
                 ^
    libnetwork/endpoint.go:247:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        ma, _ := json.Marshal(epMap["myAliases"])
                 ^
    libnetwork/endpoint.go:252:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        dn, _ := json.Marshal(epMap["dnsNames"])
                 ^
    libnetwork/endpoint_info.go:123:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
        rb, _ := json.Marshal(epMap["routes"])
                 ^
    libnetwork/endpoint_info.go:490:12: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
            tb, _ := json.Marshal(v)
                     ^
    libnetwork/network.go:161:11: Error return value of `encoding/json.Marshal` is not checked: unsafe type `interface{}` found (errchkjson)
            b, _ := json.Marshal(v)
                    ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-02-09 13:22:50 +01:00
Sebastiaan van Stijn
49b1ed6d27 libnetwork: remove ErrInvalidName
It was only returned in a few places, and not used any different than
a "invalid parameter" error, so let's use a standard errdefs.ErrInvalidParameter

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-27 14:19:19 +01:00
Sebastiaan van Stijn
548b0b6290 libnetwork: remove ErrNoSuchEndpoint
It was only returned in 1 place, and not used any different than
a "notfound" error, so let's use a standard errdefs.ErrNotFound

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-27 14:19:08 +01:00
Sebastiaan van Stijn
cef6fd2fa2 libnetwork: remove Network.EndpointByID as it must not be used
commit 80c44b4b2e removed uses of this
method and added a comment that it should never be used;

> EndpointByID should *never* be called as it's going to create a 2nd instance
> of an Endpoint. The first one lives in the Sandbox the endpoint is attached to.
> Instead, the endpoint should be retrieved by calling [Sandbox.Endpoints()].

Given that the only use of this method is in tests, we can remove if altogether.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-27 10:49:40 +01:00
Sebastiaan van Stijn
5c1fe287fc libnetwork: remove UnknownNetworkError
It was only returned in 2 places, and not used any different than
a "notfound" error, so let's use a standard errdefs.NotFound

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-26 21:35:22 +01:00
Rob Murray
bc130f367d bridge/macvlan endpoints always use a random MAC address
Now a gratuitous/unsolicted ARP is sent, there's no need to
use an IPv4-based MAC address to preserve arp-cache mappings
between an endpoint's IP addresses and its MAC addresses.

Because a random MAC address is used for the default bridge,
it no longer makes sense to derive container IPv6 addresses
from the MAC address. This "postIPv6" behaviour was needed
before IPv6 addresses could be configured, but not now. So,
IPv6 addresses will now be IPAM-allocated on the default
bridge network, just as they are for user-defined bridges.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-01-22 16:59:27 +00:00
Rob Murray
522016a842 Configurable count and interval for gratuitous ARP/NA messages
The default is to send 3 messages at 1s intervals.

That can be overridden in "docker network create" using:
  -o com.docker.network.advertise_addr_nmsgs=3
  -o com.docker.network.advertise_addr_ms=1000

Or, in daemon.json for each driver:
  "default-network-opts": {
    "bridge": {
      "com.docker.network.advertise_addr_nmsgs": "3",
      "com.docker.network.advertise_addr_ms": "1000"
    }
  }

The allowed range is 0-3 for the number of messages, and
100-2000ms for the interval. Setting nmsgs to 0 disables the
gratuitous ARP/NA messages.

The default bridge will always use the built-in defaults,
it cannot be configured.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-01-22 16:59:27 +00:00
Rob Murray
38e76ebea9 Only allocate a gateway if the n/w driver wants one
A gateway address is always reserved before the network driver is
asked to create the network. But, the driver doesn't always need a
gateway address, so the address reservation can be unnecessary.

This means, for example, an "--internal" IPv4 "/31" network cannot
be used as a point-to-point link, because one of its two addresses
is always reserved for a gateway.

So, before allocating a gateway address, ask the network driver if
it will need one (based on options that only the network driver can
interpret). Implement that as an optional interface for network
drivers.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-01-13 10:28:55 +00:00
Rob Murray
64006f964a Simplify selection of gateway address
When setting up a gateway in IpamInfo, and reserving that address in
IPAM ... the IPAM driver may return its own default gateway. That
gateway address is currently always parsed, but it's only used if the
user did not supply their own gateway address. If the user supplied
an address, it's always reserved and used. Otherwise, the IPAM driver
is asked to select and reserve an address.

The logic to deal with that was a bit confusing - and it's probably
better just to ignore the IPAM driver's gateway if it's not going to
be used.

So, simplify it little.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-01-13 10:28:55 +00:00
Rob Murray
354dfdb928 Delete /etc/hosts entries on network disconnect
Delete the entries that were added, rather than looking at the service
map (DNS config) and trying to delete entries without accounting for
the container's --hostname.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-11-15 10:58:30 +00:00
Sebastiaan van Stijn
b453aa65fa update go:build tags to use go1.22
commit a0807e7cfe configured golangci-lint
to use go1.23 semantics, which alowed linters like `copyloopvar` to lint
using thee correct semantics.

go1.22 now creates a copy of variables when assigned in a loop; make sure we
don't have files that may downgrade semantics to go1.21 in case that also means
disabling that feature; https://go.dev/ref/spec#Go_1.22

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-12 14:02:09 +01:00
Rob Murray
80e4631998 Use netip.Addr instead of string when building /etc/hosts
Also, libnetwork: Sandbox.buildHostsFile: rename var that shadowed type

Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-11-07 11:05:34 +00:00
Rob Murray
caf2d5dc7c Change meaning of return from DNSBackend.ResolveName
Interface DNSBackend.ResolveName, implemented by Network,
Sandbox (and noopDNSBackend) had a bool return value that
meant 'ipv6Miss'.

But, it was always set to true on a hit, and callers had
to deal with that.

So, changed the meaning of the return value to indicate
whether the name was found - which will also work for
'ipv4Miss' when we have IPv6-only containers/networks.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-11-05 10:01:52 +00:00
Rob Murray
ec3dde7001 Only allocate IPv6 addresses if IPv6 is enabled.
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>
2024-11-05 10:01:52 +00:00
Rob Murray
3dd96ce3c4 Fix enableIPv4 for old networks
The new Network.enableIPv4 flag needs to be set for IPv4
networks created before it was introduced.

Commit 903daa4 attempted to do that in the unmarshalling code
by checking Network.ipamV4Info - but, that field hadn't been
unmarshalled yet, so it was never present.

Instead, check for its presence in the saved map.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-09-12 20:40:23 +01:00
Nathan Baulch
59eba0ae13 Fix typos
Signed-off-by: Nathan Baulch <nathan.baulch@gmail.com>
2024-09-06 21:53:09 +10:00
Rob Murray
344039b9ae Populate DNS records for IPv6-only endpoints
Also, return IPv6 records from Network.getSvcRecords()
so that /etc/hosts entries are deleted when an IPv6-only
endpoint is removed.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-08-06 10:33:04 +01:00
Rob Murray
ea914a66a2 Use retErr in Network.ipamAllocate
Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-08-05 15:45:05 +01:00
Rob Murray
3b1341972b Only assign an IPv4 address if required
Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-08-01 16:21:26 +01:00
Rob Murray
15e5f6868a Don't auto-allocate IPv4 IPAM if !enableIPv4
Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-08-01 16:21:20 +01:00
Rob Murray
903daa4dc4 Add flag 'enableIPv4' to libnetwork.Network
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>
2024-07-31 18:38:43 +01:00
Rob Murray
58808e7748 Remove code to update Network.enableIPv6 if false
Commit 4b9dc647 (from 2016) added this in response to a
review comment, but I don't think it can ever have worked
because n.enableIPv6 = netMap["enableIPv6"].(bool), added
in 2015, would already have panic'd if the field wasn't
stored.

In any case, it's no longer needed.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2024-07-26 16:26:34 +01:00
Albin Kerouanton
1882da852e Merge pull request #47906 from akerouanton/libnet-add-otel-spans-v3
api, daemon, libnet: Create OTel spans at various places
2024-06-14 17:03:56 +02:00
Albin Kerouanton
cec0d50361 libnet: add ctx to Sandbox.Destroy()
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-06-13 17:13:43 +02:00
Albin Kerouanton
af23a024a1 libnet: Endpoint: add ctx to Join and Leave
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-06-13 17:00:05 +02:00
Albin Kerouanton
566026af8f libnet: Controller: add ctx to store methods
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-06-13 16:59:05 +02:00
Albin Kerouanton
9391052700 libnet: Add ctx to NewSandbox
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-06-13 16:52:48 +02:00
Albin Kerouanton
c5c1d133ef libnet/driverapi: Add ctx to Join
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-06-13 16:45:54 +02:00
Albin Kerouanton
8dcded102e libnet: add OTel spans to CreateEndpoint
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2024-06-13 16:45:31 +02:00
Sebastiaan van Stijn
b7d5a42168 Update go:build comments to go1.21
Match the minimum version that's specified on our vendor.mod.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-13 14:59:54 +02:00