Browse code

libnet/cnmallocator: use a list of local netdrivers

The cnmallocator package has a map of supported network drivers which
are registered using a pkg-local driver registry. This registry is then
used to load drivers, and if they have a 'local' DataScope, they aren't
used for anything. Drivers with a 'global' DataScope are called to
allocate cluster-wide network resources.

Instantiating builtin network drivers may have unintended side-effects
(e.g. the bridge driver registers a callback that should run when
firewalld is reloaded), so libnetwork has dummy '*manager' drivers that
do nothing but carry the same Capability than the original driver they
masquerade.

Put 'local drivers' (e.g. those with DataScope 'local') into a separate
list that just contains drivers' name, and don't register them into the
cnmallocator's driver registry.

Remove all the dummy '*manager' drivers as they're not needed anymore.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>

Albin Kerouanton authored on 2025/09/01 07:03:38
Showing 7 changed files
... ...
@@ -2,20 +2,28 @@ package cnmallocator
2 2
 
3 3
 import (
4 4
 	"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
5
-	"github.com/moby/moby/v2/daemon/libnetwork/drivers/bridge/brmanager"
5
+	"github.com/moby/moby/v2/daemon/libnetwork/drivers/bridge"
6 6
 	"github.com/moby/moby/v2/daemon/libnetwork/drivers/host"
7
-	"github.com/moby/moby/v2/daemon/libnetwork/drivers/ipvlan/ivmanager"
8
-	"github.com/moby/moby/v2/daemon/libnetwork/drivers/macvlan/mvmanager"
7
+	"github.com/moby/moby/v2/daemon/libnetwork/drivers/ipvlan"
8
+	"github.com/moby/moby/v2/daemon/libnetwork/drivers/macvlan"
9 9
 	"github.com/moby/moby/v2/daemon/libnetwork/drivers/overlay/ovmanager"
10 10
 	"github.com/moby/swarmkit/v2/manager/allocator/networkallocator"
11 11
 )
12 12
 
13
-var initializers = map[string]func(driverapi.Registerer) error{
13
+// globalDrivers is a map of network drivers that support cluster-wide
14
+// definition and require cluster-wide resources allocation (i.e. DataScope == scope.Global).
15
+var globalDrivers = map[string]func(driverapi.Registerer) error{
14 16
 	"overlay": ovmanager.Register,
15
-	"macvlan": mvmanager.Register,
16
-	"bridge":  brmanager.Register,
17
-	"ipvlan":  ivmanager.Register,
18
-	"host":    host.Register,
17
+}
18
+
19
+// localDrivers is a list of builtin network drivers that support cluster-wide
20
+// definition (i.e. --scope=swarm on the CLI), but don't need global
21
+// resources allocations (i.e., DataScope == scope.Local).
22
+var localDrivers = []string{
23
+	bridge.NetworkType,
24
+	host.NetworkType,
25
+	ipvlan.NetworkType,
26
+	macvlan.NetworkType,
19 27
 }
20 28
 
21 29
 // PredefinedNetworks returns the list of predefined network structures
... ...
@@ -6,11 +6,19 @@ import (
6 6
 	"github.com/moby/swarmkit/v2/manager/allocator/networkallocator"
7 7
 )
8 8
 
9
-var initializers = map[string]func(driverapi.Registerer) error{
10
-	"overlay":  ovmanager.Register,
11
-	"internal": stubManager("internal"),
12
-	"l2bridge": stubManager("l2bridge"),
13
-	"nat":      stubManager("nat"),
9
+// globalDrivers is a map of network drivers that support cluster-wide
10
+// definition and require cluster-wide resources allocation (i.e. DataScope == scope.Global).
11
+var globalDrivers = map[string]func(driverapi.Registerer) error{
12
+	"overlay": ovmanager.Register,
13
+}
14
+
15
+// localDrivers is a list of builtin network drivers that support cluster-wide
16
+// definition (i.e. --scope=swarm on the CLI), but don't need global
17
+// resources allocations (i.e., DataScope == scope.Local).
18
+var localDrivers = []string{
19
+	"internal",
20
+	"l2bridge",
21
+	"nat",
14 22
 }
15 23
 
16 24
 // PredefinedNetworks returns the list of predefined network structures
... ...
@@ -19,9 +27,3 @@ func (*Provider) PredefinedNetworks() []networkallocator.PredefinedNetworkData {
19 19
 		{Name: "nat", Driver: "nat"},
20 20
 	}
21 21
 }
22
-
23
-func stubManager(ntype string) func(driverapi.Registerer) error {
24
-	return func(r driverapi.Registerer) error {
25
-		return RegisterManager(r, ntype)
26
-	}
27
-}
28 22
deleted file mode 100644
... ...
@@ -1,65 +0,0 @@
1
-package cnmallocator
2
-
3
-import (
4
-	"context"
5
-
6
-	"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
7
-	"github.com/moby/moby/v2/daemon/libnetwork/scope"
8
-	"github.com/moby/moby/v2/daemon/libnetwork/types"
9
-)
10
-
11
-type manager struct {
12
-	networkType string
13
-}
14
-
15
-// RegisterManager registers a new instance of the manager driver for networkType with r.
16
-func RegisterManager(r driverapi.Registerer, networkType string) error {
17
-	return r.RegisterDriver(networkType, &manager{networkType: networkType}, driverapi.Capability{
18
-		DataScope:         scope.Local,
19
-		ConnectivityScope: scope.Local,
20
-	})
21
-}
22
-
23
-func (d *manager) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
24
-	return nil, types.NotImplementedErrorf("not implemented")
25
-}
26
-
27
-func (d *manager) NetworkFree(id string) error {
28
-	return types.NotImplementedErrorf("not implemented")
29
-}
30
-
31
-func (d *manager) CreateNetwork(ctx context.Context, id string, option map[string]any, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
32
-	return types.NotImplementedErrorf("not implemented")
33
-}
34
-
35
-func (d *manager) DeleteNetwork(nid string) error {
36
-	return types.NotImplementedErrorf("not implemented")
37
-}
38
-
39
-func (d *manager) CreateEndpoint(_ context.Context, nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]any) error {
40
-	return types.NotImplementedErrorf("not implemented")
41
-}
42
-
43
-func (d *manager) DeleteEndpoint(nid, eid string) error {
44
-	return types.NotImplementedErrorf("not implemented")
45
-}
46
-
47
-func (d *manager) EndpointOperInfo(nid, eid string) (map[string]any, error) {
48
-	return nil, types.NotImplementedErrorf("not implemented")
49
-}
50
-
51
-func (d *manager) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]any) error {
52
-	return types.NotImplementedErrorf("not implemented")
53
-}
54
-
55
-func (d *manager) Leave(nid, eid string) error {
56
-	return types.NotImplementedErrorf("not implemented")
57
-}
58
-
59
-func (d *manager) Type() string {
60
-	return d.networkType
61
-}
62
-
63
-func (d *manager) IsBuiltIn() bool {
64
-	return true
65
-}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"context"
5 5
 	"fmt"
6 6
 	"net"
7
+	"slices"
7 8
 	"strings"
8 9
 
9 10
 	"github.com/containerd/log"
... ...
@@ -80,9 +81,11 @@ type network struct {
80 80
 }
81 81
 
82 82
 type networkDriver struct {
83
-	driver     driverapi.Driver
84
-	name       string
85
-	capability *driverapi.Capability
83
+	driver driverapi.Driver // driver is nil when isNodeLocal == true
84
+	name   string
85
+	// isNodeLocal indicates whether that driver is locally-managed or requires
86
+	// global resources allocation.
87
+	isNodeLocal bool
86 88
 }
87 89
 
88 90
 // NewAllocator returns a new NetworkAllocator handle
... ...
@@ -95,7 +98,7 @@ func (p *Provider) NewAllocator(netConfig *networkallocator.Config) (networkallo
95 95
 		pg:       p.pg,
96 96
 	}
97 97
 
98
-	for ntype, i := range initializers {
98
+	for ntype, i := range globalDrivers {
99 99
 		if err := i(&na.networkRegistry); err != nil {
100 100
 			return nil, fmt.Errorf("failed to register %q network driver: %w", ntype, err)
101 101
 		}
... ...
@@ -129,7 +132,7 @@ func (na *cnmNetworkAllocator) Allocate(n *api.Network) error {
129 129
 	nw := &network{
130 130
 		nw:          n,
131 131
 		endpoints:   make(map[string]string),
132
-		isNodeLocal: d.capability.DataScope == scope.Local,
132
+		isNodeLocal: d.isNodeLocal,
133 133
 	}
134 134
 
135 135
 	// No swarm-level allocation can be provided by the network driver for
... ...
@@ -149,7 +152,7 @@ func (na *cnmNetworkAllocator) Allocate(n *api.Network) error {
149 149
 			return errors.Wrapf(err, "failed allocating pools and gateway IP for network %s", n.ID)
150 150
 		}
151 151
 
152
-		if err := na.allocateDriverState(n); err != nil {
152
+		if err := na.allocateDriverState(d, n); err != nil {
153 153
 			na.freePools(n, nw.pools)
154 154
 			return errors.Wrapf(err, "failed while allocating driver state for network %s", n.ID)
155 155
 		}
... ...
@@ -706,13 +709,16 @@ func (na *cnmNetworkAllocator) freeDriverState(n *api.Network) error {
706 706
 		return err
707 707
 	}
708 708
 
709
+	if d.driver == nil {
710
+		return fmt.Errorf("driver %s was loaded from localDrivers and can't be used to free driver state", d.name)
711
+	}
712
+
709 713
 	return d.driver.NetworkFree(n.ID)
710 714
 }
711 715
 
712
-func (na *cnmNetworkAllocator) allocateDriverState(n *api.Network) error {
713
-	d, err := na.resolveDriver(n)
714
-	if err != nil {
715
-		return err
716
+func (na *cnmNetworkAllocator) allocateDriverState(d *networkDriver, n *api.Network) error {
717
+	if d.driver == nil {
718
+		return fmt.Errorf("driver %s was loaded from localDrivers and can't be used to allocate driver state", d.name)
716 719
 	}
717 720
 
718 721
 	options := make(map[string]string)
... ...
@@ -776,20 +782,28 @@ func (na *cnmNetworkAllocator) resolveDriver(n *api.Network) (*networkDriver, er
776 776
 		dName = n.Spec.DriverConfig.Name
777 777
 	}
778 778
 
779
-	d, drvcap := na.networkRegistry.Driver(dName)
779
+	if slices.Contains(localDrivers, dName) {
780
+		return &networkDriver{name: dName, isNodeLocal: true}, nil
781
+	}
782
+
783
+	d, drvCap := na.networkRegistry.Driver(dName)
780 784
 	if d == nil {
781 785
 		err := na.loadDriver(dName)
782 786
 		if err != nil {
783 787
 			return nil, err
784 788
 		}
785 789
 
786
-		d, drvcap = na.networkRegistry.Driver(dName)
790
+		d, drvCap = na.networkRegistry.Driver(dName)
787 791
 		if d == nil {
788 792
 			return nil, fmt.Errorf("could not resolve network driver %s", dName)
789 793
 		}
790 794
 	}
791 795
 
792
-	return &networkDriver{driver: d, capability: &drvcap, name: dName}, nil
796
+	return &networkDriver{
797
+		driver:      d,
798
+		name:        dName,
799
+		isNodeLocal: drvCap.DataScope == scope.Local,
800
+	}, nil
793 801
 }
794 802
 
795 803
 func (na *cnmNetworkAllocator) loadDriver(name string) error {
... ...
@@ -966,8 +980,8 @@ func (na *cnmNetworkAllocator) IsVIPOnIngressNetwork(vip *api.Endpoint_VirtualIP
966 966
 // IsBuiltInDriver returns whether the passed driver is an internal network driver
967 967
 func IsBuiltInDriver(name string) bool {
968 968
 	n := strings.ToLower(name)
969
-	_, ok := initializers[n]
970
-	return ok
969
+	_, isGlobal := globalDrivers[n]
970
+	return isGlobal || slices.Contains(localDrivers, n)
971 971
 }
972 972
 
973 973
 // setIPAMSerialAlloc sets the ipam allocation method to serial
974 974
deleted file mode 100644
... ...
@@ -1,65 +0,0 @@
1
-package brmanager
2
-
3
-import (
4
-	"context"
5
-
6
-	"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
7
-	"github.com/moby/moby/v2/daemon/libnetwork/scope"
8
-	"github.com/moby/moby/v2/daemon/libnetwork/types"
9
-)
10
-
11
-const networkType = "bridge"
12
-
13
-type driver struct{}
14
-
15
-// Register registers a new instance of the bridge manager driver with r.
16
-func Register(r driverapi.Registerer) error {
17
-	return r.RegisterDriver(networkType, &driver{}, driverapi.Capability{
18
-		DataScope:         scope.Local,
19
-		ConnectivityScope: scope.Local,
20
-	})
21
-}
22
-
23
-func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
24
-	return nil, types.NotImplementedErrorf("not implemented")
25
-}
26
-
27
-func (d *driver) NetworkFree(id string) error {
28
-	return types.NotImplementedErrorf("not implemented")
29
-}
30
-
31
-func (d *driver) CreateNetwork(ctx context.Context, id string, option map[string]any, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
32
-	return types.NotImplementedErrorf("not implemented")
33
-}
34
-
35
-func (d *driver) DeleteNetwork(nid string) error {
36
-	return types.NotImplementedErrorf("not implemented")
37
-}
38
-
39
-func (d *driver) CreateEndpoint(_ context.Context, nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]any) error {
40
-	return types.NotImplementedErrorf("not implemented")
41
-}
42
-
43
-func (d *driver) DeleteEndpoint(nid, eid string) error {
44
-	return types.NotImplementedErrorf("not implemented")
45
-}
46
-
47
-func (d *driver) EndpointOperInfo(nid, eid string) (map[string]any, error) {
48
-	return nil, types.NotImplementedErrorf("not implemented")
49
-}
50
-
51
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]any) error {
52
-	return types.NotImplementedErrorf("not implemented")
53
-}
54
-
55
-func (d *driver) Leave(nid, eid string) error {
56
-	return types.NotImplementedErrorf("not implemented")
57
-}
58
-
59
-func (d *driver) Type() string {
60
-	return networkType
61
-}
62
-
63
-func (d *driver) IsBuiltIn() bool {
64
-	return true
65
-}
66 1
deleted file mode 100644
... ...
@@ -1,65 +0,0 @@
1
-package ivmanager
2
-
3
-import (
4
-	"context"
5
-
6
-	"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
7
-	"github.com/moby/moby/v2/daemon/libnetwork/scope"
8
-	"github.com/moby/moby/v2/daemon/libnetwork/types"
9
-)
10
-
11
-const networkType = "ipvlan"
12
-
13
-type driver struct{}
14
-
15
-// Register registers a new instance of the ipvlan manager driver.
16
-func Register(r driverapi.Registerer) error {
17
-	return r.RegisterDriver(networkType, &driver{}, driverapi.Capability{
18
-		DataScope:         scope.Local,
19
-		ConnectivityScope: scope.Global,
20
-	})
21
-}
22
-
23
-func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
24
-	return nil, types.NotImplementedErrorf("not implemented")
25
-}
26
-
27
-func (d *driver) NetworkFree(id string) error {
28
-	return types.NotImplementedErrorf("not implemented")
29
-}
30
-
31
-func (d *driver) CreateNetwork(ctx context.Context, id string, option map[string]any, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
32
-	return types.NotImplementedErrorf("not implemented")
33
-}
34
-
35
-func (d *driver) DeleteNetwork(nid string) error {
36
-	return types.NotImplementedErrorf("not implemented")
37
-}
38
-
39
-func (d *driver) CreateEndpoint(_ context.Context, nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]any) error {
40
-	return types.NotImplementedErrorf("not implemented")
41
-}
42
-
43
-func (d *driver) DeleteEndpoint(nid, eid string) error {
44
-	return types.NotImplementedErrorf("not implemented")
45
-}
46
-
47
-func (d *driver) EndpointOperInfo(nid, eid string) (map[string]any, error) {
48
-	return nil, types.NotImplementedErrorf("not implemented")
49
-}
50
-
51
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]any) error {
52
-	return types.NotImplementedErrorf("not implemented")
53
-}
54
-
55
-func (d *driver) Leave(nid, eid string) error {
56
-	return types.NotImplementedErrorf("not implemented")
57
-}
58
-
59
-func (d *driver) Type() string {
60
-	return networkType
61
-}
62
-
63
-func (d *driver) IsBuiltIn() bool {
64
-	return true
65
-}
66 1
deleted file mode 100644
... ...
@@ -1,65 +0,0 @@
1
-package mvmanager
2
-
3
-import (
4
-	"context"
5
-
6
-	"github.com/moby/moby/v2/daemon/libnetwork/driverapi"
7
-	"github.com/moby/moby/v2/daemon/libnetwork/scope"
8
-	"github.com/moby/moby/v2/daemon/libnetwork/types"
9
-)
10
-
11
-const networkType = "macvlan"
12
-
13
-type driver struct{}
14
-
15
-// Register registers a new instance of the macvlan manager driver.
16
-func Register(r driverapi.Registerer) error {
17
-	return r.RegisterDriver(networkType, &driver{}, driverapi.Capability{
18
-		DataScope:         scope.Local,
19
-		ConnectivityScope: scope.Global,
20
-	})
21
-}
22
-
23
-func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, ipV6Data []driverapi.IPAMData) (map[string]string, error) {
24
-	return nil, types.NotImplementedErrorf("not implemented")
25
-}
26
-
27
-func (d *driver) NetworkFree(id string) error {
28
-	return types.NotImplementedErrorf("not implemented")
29
-}
30
-
31
-func (d *driver) CreateNetwork(ctx context.Context, id string, option map[string]any, nInfo driverapi.NetworkInfo, ipV4Data, ipV6Data []driverapi.IPAMData) error {
32
-	return types.NotImplementedErrorf("not implemented")
33
-}
34
-
35
-func (d *driver) DeleteNetwork(nid string) error {
36
-	return types.NotImplementedErrorf("not implemented")
37
-}
38
-
39
-func (d *driver) CreateEndpoint(_ context.Context, nid, eid string, ifInfo driverapi.InterfaceInfo, epOptions map[string]any) error {
40
-	return types.NotImplementedErrorf("not implemented")
41
-}
42
-
43
-func (d *driver) DeleteEndpoint(nid, eid string) error {
44
-	return types.NotImplementedErrorf("not implemented")
45
-}
46
-
47
-func (d *driver) EndpointOperInfo(nid, eid string) (map[string]any, error) {
48
-	return nil, types.NotImplementedErrorf("not implemented")
49
-}
50
-
51
-func (d *driver) Join(_ context.Context, nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, _, _ map[string]any) error {
52
-	return types.NotImplementedErrorf("not implemented")
53
-}
54
-
55
-func (d *driver) Leave(nid, eid string) error {
56
-	return types.NotImplementedErrorf("not implemented")
57
-}
58
-
59
-func (d *driver) Type() string {
60
-	return networkType
61
-}
62
-
63
-func (d *driver) IsBuiltIn() bool {
64
-	return true
65
-}