Browse code

Global Default Address Pool support

This change brings global default address pool feature into
libnetwork. Idea is to reuse same code flow and functions that were
implemented for local scope default address pool.
Function InitNetworks carries most of the changes. local scope default
address pool init should always happen only once. But Global scope
default address pool can be initialized multiple times.

Signed-off-by: selansen <elango.siva@docker.com>

selansen authored on 2018/07/25 04:46:59
Showing 9 changed files
... ...
@@ -10,7 +10,6 @@ import (
10 10
 	"testing"
11 11
 
12 12
 	"github.com/docker/libnetwork/driverapi"
13
-	"github.com/docker/libnetwork/ipamutils"
14 13
 	"github.com/docker/libnetwork/iptables"
15 14
 	"github.com/docker/libnetwork/netlabel"
16 15
 	"github.com/docker/libnetwork/netutils"
... ...
@@ -20,10 +19,6 @@ import (
20 20
 	"github.com/vishvananda/netlink"
21 21
 )
22 22
 
23
-func init() {
24
-	ipamutils.InitNetworks(nil)
25
-}
26
-
27 23
 func TestEndpointMarshalling(t *testing.T) {
28 24
 	ip1, _ := types.ParseCIDR("172.22.0.9/16")
29 25
 	ip2, _ := types.ParseCIDR("2001:db8::9")
... ...
@@ -46,8 +46,8 @@ func NewAllocator(lcDs, glDs datastore.DataStore) (*Allocator, error) {
46 46
 
47 47
 	// Load predefined subnet pools
48 48
 	a.predefined = map[string][]*net.IPNet{
49
-		localAddressSpace:  ipamutils.PredefinedBroadNetworks,
50
-		globalAddressSpace: ipamutils.PredefinedGranularNetworks,
49
+		localAddressSpace:  ipamutils.PredefinedLocalScopeDefaultNetworks,
50
+		globalAddressSpace: ipamutils.PredefinedGlobalScopeDefaultNetworks,
51 51
 	}
52 52
 
53 53
 	// Initialize asIndices map
... ...
@@ -17,7 +17,6 @@ import (
17 17
 	"github.com/docker/libnetwork/bitseq"
18 18
 	"github.com/docker/libnetwork/datastore"
19 19
 	"github.com/docker/libnetwork/ipamapi"
20
-	"github.com/docker/libnetwork/ipamutils"
21 20
 	_ "github.com/docker/libnetwork/testutils"
22 21
 	"github.com/docker/libnetwork/types"
23 22
 	"gotest.tools/assert"
... ...
@@ -57,7 +56,6 @@ func randomLocalStore(needStore bool) (datastore.DataStore, error) {
57 57
 }
58 58
 
59 59
 func getAllocator(store bool) (*Allocator, error) {
60
-	ipamutils.InitNetworks(nil)
61 60
 	ds, err := randomLocalStore(store)
62 61
 	if err != nil {
63 62
 		return nil, err
... ...
@@ -35,7 +35,7 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
35 35
 		}
36 36
 	}
37 37
 
38
-	ipamutils.InitNetworks(GetDefaultIPAddressPool())
38
+	ipamutils.ConfigLocalScopeDefaultNetworks(GetDefaultIPAddressPool())
39 39
 
40 40
 	a, err := ipam.NewAllocator(localDs, globalDs)
41 41
 	if err != nil {
... ...
@@ -37,7 +37,7 @@ func InitDockerDefault(ic ipamapi.Callback, l, g interface{}) error {
37 37
 		}
38 38
 	}
39 39
 
40
-	ipamutils.InitNetworks(nil)
40
+	ipamutils.ConfigLocalScopeDefaultNetworks(nil)
41 41
 
42 42
 	a, err := ipam.NewAllocator(localDs, globalDs)
43 43
 	if err != nil {
... ...
@@ -5,23 +5,20 @@ import (
5 5
 	"fmt"
6 6
 	"net"
7 7
 	"sync"
8
-
9
-	"github.com/sirupsen/logrus"
10 8
 )
11 9
 
12 10
 var (
13
-	// PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
14
-	// (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGranularNetworks`
15
-	PredefinedBroadNetworks []*net.IPNet
16
-	// PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
17
-	// (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
18
-	PredefinedGranularNetworks []*net.IPNet
19
-	initNetworksOnce           sync.Once
20
-
21
-	defaultBroadNetwork = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
11
+	// PredefinedLocalScopeDefaultNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
12
+	// (172.17-31.x.x/16, 192.168.x.x/20) which do not overlap with the networks in `PredefinedGlobalScopeDefaultNetworks`
13
+	PredefinedLocalScopeDefaultNetworks []*net.IPNet
14
+	// PredefinedGlobalScopeDefaultNetworks contains a list of 64K IPv4 private networks with host size 8
15
+	// (10.x.x.x/24) which do not overlap with the networks in `PredefinedLocalScopeDefaultNetworks`
16
+	PredefinedGlobalScopeDefaultNetworks []*net.IPNet
17
+	mutex                                sync.Mutex
18
+	localScopeDefaultNetworks            = []*NetworkToSplit{{"172.17.0.0/16", 16}, {"172.18.0.0/16", 16}, {"172.19.0.0/16", 16},
22 19
 		{"172.20.0.0/14", 16}, {"172.24.0.0/14", 16}, {"172.28.0.0/14", 16},
23 20
 		{"192.168.0.0/16", 20}}
24
-	defaultGranularNetwork = []*NetworkToSplit{{"10.0.0.0/8", 24}}
21
+	globalScopeDefaultNetworks = []*NetworkToSplit{{"10.0.0.0/8", 24}}
25 22
 )
26 23
 
27 24
 // NetworkToSplit represent a network that has to be split in chunks with mask length Size.
... ...
@@ -34,19 +31,47 @@ type NetworkToSplit struct {
34 34
 	Size int    `json:"size"`
35 35
 }
36 36
 
37
-// InitNetworks initializes the broad network pool and the granular network pool
38
-func InitNetworks(defaultAddressPool []*NetworkToSplit) {
39
-	initNetworksOnce.Do(func() {
40
-		// error ingnored should never fail
41
-		PredefinedGranularNetworks, _ = splitNetworks(defaultGranularNetwork)
42
-		if defaultAddressPool == nil {
43
-			defaultAddressPool = defaultBroadNetwork
44
-		}
45
-		var err error
46
-		if PredefinedBroadNetworks, err = splitNetworks(defaultAddressPool); err != nil {
47
-			logrus.WithError(err).Error("InitAddressPools failed to initialize the default address pool")
48
-		}
49
-	})
37
+func init() {
38
+	var err error
39
+	if PredefinedGlobalScopeDefaultNetworks, err = splitNetworks(globalScopeDefaultNetworks); err != nil {
40
+		//we are going to panic in case of error as we should never get into this state
41
+		panic("InitAddressPools failed to initialize the global scope default address pool")
42
+	}
43
+
44
+	if PredefinedLocalScopeDefaultNetworks, err = splitNetworks(localScopeDefaultNetworks); err != nil {
45
+		//we are going to panic in case of error as we should never get into this state
46
+		panic("InitAddressPools failed to initialize the local scope default address pool")
47
+	}
48
+}
49
+
50
+// configDefaultNetworks configures local as well global default pool based on input
51
+func configDefaultNetworks(defaultAddressPool []*NetworkToSplit, result *[]*net.IPNet) error {
52
+	mutex.Lock()
53
+	defer mutex.Unlock()
54
+	defaultNetworks, err := splitNetworks(defaultAddressPool)
55
+	if err != nil {
56
+		return err
57
+	}
58
+	*result = defaultNetworks
59
+	return nil
60
+}
61
+
62
+// ConfigGlobalScopeDefaultNetworks configures global default pool.
63
+// Ideally this will be called from SwarmKit as part of swarm init
64
+func ConfigGlobalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
65
+	if defaultAddressPool == nil {
66
+		defaultAddressPool = globalScopeDefaultNetworks
67
+	}
68
+	return configDefaultNetworks(defaultAddressPool, &PredefinedGlobalScopeDefaultNetworks)
69
+}
70
+
71
+// ConfigLocalScopeDefaultNetworks configures local default pool.
72
+// Ideally this will be called during libnetwork init
73
+func ConfigLocalScopeDefaultNetworks(defaultAddressPool []*NetworkToSplit) error {
74
+	if defaultAddressPool == nil {
75
+		return nil
76
+	}
77
+	return configDefaultNetworks(defaultAddressPool, &PredefinedLocalScopeDefaultNetworks)
50 78
 }
51 79
 
52 80
 // splitNetworks takes a slice of networks, split them accordingly and returns them
... ...
@@ -2,7 +2,6 @@ package ipamutils
2 2
 
3 3
 import (
4 4
 	"net"
5
-	"sync"
6 5
 	"testing"
7 6
 
8 7
 	_ "github.com/docker/libnetwork/testutils"
... ...
@@ -34,15 +33,25 @@ func initGranularPredefinedNetworks() []*net.IPNet {
34 34
 	return pl
35 35
 }
36 36
 
37
+func initGlobalScopeNetworks() []*net.IPNet {
38
+	pl := make([]*net.IPNet, 0, 256*256)
39
+	mask := []byte{255, 255, 255, 0}
40
+	for i := 0; i < 256; i++ {
41
+		for j := 0; j < 256; j++ {
42
+			pl = append(pl, &net.IPNet{IP: []byte{30, byte(i), byte(j), 0}, Mask: mask})
43
+		}
44
+	}
45
+	return pl
46
+}
47
+
37 48
 func TestDefaultNetwork(t *testing.T) {
38
-	InitNetworks(nil)
39
-	for _, nw := range PredefinedGranularNetworks {
49
+	for _, nw := range PredefinedGlobalScopeDefaultNetworks {
40 50
 		if ones, bits := nw.Mask.Size(); bits != 32 || ones != 24 {
41 51
 			t.Fatalf("Unexpected size for network in granular list: %v", nw)
42 52
 		}
43 53
 	}
44 54
 
45
-	for _, nw := range PredefinedBroadNetworks {
55
+	for _, nw := range PredefinedLocalScopeDefaultNetworks {
46 56
 		if ones, bits := nw.Mask.Size(); bits != 32 || (ones != 20 && ones != 16) {
47 57
 			t.Fatalf("Unexpected size for network in broad list: %v", nw)
48 58
 		}
... ...
@@ -53,7 +62,7 @@ func TestDefaultNetwork(t *testing.T) {
53 53
 	for _, v := range originalBroadNets {
54 54
 		m[v.String()] = true
55 55
 	}
56
-	for _, nw := range PredefinedBroadNetworks {
56
+	for _, nw := range PredefinedLocalScopeDefaultNetworks {
57 57
 		_, ok := m[nw.String()]
58 58
 		assert.Check(t, ok)
59 59
 		delete(m, nw.String())
... ...
@@ -67,7 +76,25 @@ func TestDefaultNetwork(t *testing.T) {
67 67
 	for _, v := range originalGranularNets {
68 68
 		m[v.String()] = true
69 69
 	}
70
-	for _, nw := range PredefinedGranularNetworks {
70
+	for _, nw := range PredefinedGlobalScopeDefaultNetworks {
71
+		_, ok := m[nw.String()]
72
+		assert.Check(t, ok)
73
+		delete(m, nw.String())
74
+	}
75
+
76
+	assert.Check(t, is.Len(m, 0))
77
+}
78
+
79
+func TestConfigGlobalScopeDefaultNetworks(t *testing.T) {
80
+	err := ConfigGlobalScopeDefaultNetworks([]*NetworkToSplit{{"30.0.0.0/8", 24}})
81
+	assert.NilError(t, err)
82
+
83
+	originalGlobalScopeNetworks := initGlobalScopeNetworks()
84
+	m := make(map[string]bool)
85
+	for _, v := range originalGlobalScopeNetworks {
86
+		m[v.String()] = true
87
+	}
88
+	for _, nw := range PredefinedGlobalScopeDefaultNetworks {
71 89
 		_, ok := m[nw.String()]
72 90
 		assert.Check(t, ok)
73 91
 		delete(m, nw.String())
... ...
@@ -77,15 +104,15 @@ func TestDefaultNetwork(t *testing.T) {
77 77
 }
78 78
 
79 79
 func TestInitAddressPools(t *testing.T) {
80
-	initNetworksOnce = sync.Once{}
81
-	InitNetworks([]*NetworkToSplit{{"172.80.0.0/16", 24}, {"172.90.0.0/16", 24}})
82
-
83
-	// Check for Random IPAddresses in PredefinedBroadNetworks  ex: first , last and middle
84
-	assert.Check(t, is.Len(PredefinedBroadNetworks, 512), "Failed to find PredefinedBroadNetworks")
85
-	assert.Check(t, is.Equal(PredefinedBroadNetworks[0].String(), "172.80.0.0/24"))
86
-	assert.Check(t, is.Equal(PredefinedBroadNetworks[127].String(), "172.80.127.0/24"))
87
-	assert.Check(t, is.Equal(PredefinedBroadNetworks[255].String(), "172.80.255.0/24"))
88
-	assert.Check(t, is.Equal(PredefinedBroadNetworks[256].String(), "172.90.0.0/24"))
89
-	assert.Check(t, is.Equal(PredefinedBroadNetworks[383].String(), "172.90.127.0/24"))
90
-	assert.Check(t, is.Equal(PredefinedBroadNetworks[511].String(), "172.90.255.0/24"))
80
+	err := ConfigLocalScopeDefaultNetworks([]*NetworkToSplit{{"172.80.0.0/16", 24}, {"172.90.0.0/16", 24}})
81
+	assert.NilError(t, err)
82
+
83
+	// Check for Random IPAddresses in PredefinedLocalScopeDefaultNetworks  ex: first , last and middle
84
+	assert.Check(t, is.Len(PredefinedLocalScopeDefaultNetworks, 512), "Failed to find PredefinedLocalScopeDefaultNetworks")
85
+	assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[0].String(), "172.80.0.0/24"))
86
+	assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[127].String(), "172.80.127.0/24"))
87
+	assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[255].String(), "172.80.255.0/24"))
88
+	assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[256].String(), "172.90.0.0/24"))
89
+	assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[383].String(), "172.90.127.0/24"))
90
+	assert.Check(t, is.Equal(PredefinedLocalScopeDefaultNetworks[511].String(), "172.90.255.0/24"))
91 91
 }
... ...
@@ -94,8 +94,8 @@ func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
94 94
 	}
95 95
 
96 96
 	if link == nil || len(v4Nets) == 0 {
97
-		// Choose from predefined broad networks
98
-		v4Net, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
97
+		// Choose from predefined local scope  networks
98
+		v4Net, err := FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
99 99
 		if err != nil {
100 100
 			return nil, nil, err
101 101
 		}
... ...
@@ -212,15 +212,14 @@ func TestUtilGenerateRandomMAC(t *testing.T) {
212 212
 
213 213
 func TestNetworkRequest(t *testing.T) {
214 214
 	defer testutils.SetupTestOSContext(t)()
215
-	ipamutils.InitNetworks(nil)
216 215
 
217
-	nw, err := FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
216
+	nw, err := FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
218 217
 	if err != nil {
219 218
 		t.Fatal(err)
220 219
 	}
221 220
 
222 221
 	var found bool
223
-	for _, exp := range ipamutils.PredefinedBroadNetworks {
222
+	for _, exp := range ipamutils.PredefinedLocalScopeDefaultNetworks {
224 223
 		if types.CompareIPNet(exp, nw) {
225 224
 			found = true
226 225
 			break
... ...
@@ -231,13 +230,13 @@ func TestNetworkRequest(t *testing.T) {
231 231
 		t.Fatalf("Found unexpected broad network %s", nw)
232 232
 	}
233 233
 
234
-	nw, err = FindAvailableNetwork(ipamutils.PredefinedGranularNetworks)
234
+	nw, err = FindAvailableNetwork(ipamutils.PredefinedGlobalScopeDefaultNetworks)
235 235
 	if err != nil {
236 236
 		t.Fatal(err)
237 237
 	}
238 238
 
239 239
 	found = false
240
-	for _, exp := range ipamutils.PredefinedGranularNetworks {
240
+	for _, exp := range ipamutils.PredefinedGlobalScopeDefaultNetworks {
241 241
 		if types.CompareIPNet(exp, nw) {
242 242
 			found = true
243 243
 			break
... ...
@@ -255,7 +254,7 @@ func TestNetworkRequest(t *testing.T) {
255 255
 	if err != nil {
256 256
 		t.Fatal(err)
257 257
 	}
258
-	nw, err = FindAvailableNetwork(ipamutils.PredefinedBroadNetworks)
258
+	nw, err = FindAvailableNetwork(ipamutils.PredefinedLocalScopeDefaultNetworks)
259 259
 	if err != nil {
260 260
 		t.Fatal(err)
261 261
 	}
... ...
@@ -266,7 +265,6 @@ func TestNetworkRequest(t *testing.T) {
266 266
 
267 267
 func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
268 268
 	defer testutils.SetupTestOSContext(t)()
269
-	ipamutils.InitNetworks(nil)
270 269
 
271 270
 	nws := []string{"172.101.202.254/16", "172.102.202.254/16"}
272 271
 	createInterface(t, "test", nws...)
... ...
@@ -303,7 +301,6 @@ func TestElectInterfaceAddressMultipleAddresses(t *testing.T) {
303 303
 
304 304
 func TestElectInterfaceAddress(t *testing.T) {
305 305
 	defer testutils.SetupTestOSContext(t)()
306
-	ipamutils.InitNetworks(nil)
307 306
 
308 307
 	nws := "172.101.202.254/16"
309 308
 	createInterface(t, "test", nws)