Browse code

Move tests from core into ipallocator

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)

Michael Crosby authored on 2014/01/23 18:31:38
Showing 6 changed files
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"github.com/dotcloud/docker/archive"
8 8
 	"github.com/dotcloud/docker/execdriver"
9 9
 	"github.com/dotcloud/docker/graphdriver"
10
+	"github.com/dotcloud/docker/networkdriver/ipallocator"
10 11
 	"github.com/dotcloud/docker/pkg/mount"
11 12
 	"github.com/dotcloud/docker/pkg/term"
12 13
 	"github.com/dotcloud/docker/utils"
... ...
@@ -1039,8 +1040,9 @@ func (container *Container) allocateNetwork() error {
1039 1039
 				manager: manager,
1040 1040
 			}
1041 1041
 			if iface != nil && iface.IPNet.IP != nil {
1042
-				ipNum := ipToInt(iface.IPNet.IP)
1043
-				manager.ipAllocator.inUse[ipNum] = struct{}{}
1042
+				if _, err := ipallocator.RequestIP(manager.bridgeNetwork, &iface.IPNet.IP); err != nil {
1043
+					return err
1044
+				}
1044 1045
 			} else {
1045 1046
 				iface, err = container.runtime.networkManager.Allocate()
1046 1047
 				if err != nil {
... ...
@@ -1,8 +1,8 @@
1 1
 package docker
2 2
 
3 3
 import (
4
-	"errors"
5 4
 	"fmt"
5
+	"github.com/dotcloud/docker/networkdriver/ipallocator"
6 6
 	"github.com/dotcloud/docker/pkg/iptables"
7 7
 	"github.com/dotcloud/docker/pkg/netlink"
8 8
 	"github.com/dotcloud/docker/proxy"
... ...
@@ -24,21 +24,6 @@ const (
24 24
 	siocBRADDBR          = 0x89a0
25 25
 )
26 26
 
27
-func checkNameserverOverlaps(nameservers []string, dockerNetwork *net.IPNet) error {
28
-	if len(nameservers) > 0 {
29
-		for _, ns := range nameservers {
30
-			_, nsNetwork, err := net.ParseCIDR(ns)
31
-			if err != nil {
32
-				return err
33
-			}
34
-			if networkOverlaps(dockerNetwork, nsNetwork) {
35
-				return fmt.Errorf("%s overlaps nameserver %s", dockerNetwork, nsNetwork)
36
-			}
37
-		}
38
-	}
39
-	return nil
40
-}
41
-
42 27
 // CreateBridgeIface creates a network bridge interface on the host system with the name `ifaceName`,
43 28
 // and attempts to configure it with an address which doesn't conflict with any other interface on the host.
44 29
 // If it can't find an address which doesn't conflict, it will return an error.
... ...
@@ -86,17 +71,16 @@ func CreateBridgeIface(config *DaemonConfig) error {
86 86
 			if err != nil {
87 87
 				return err
88 88
 			}
89
-			// TODO: @crosbymichael register route
90
-			if err := checkRouteOverlaps(routes, dockerNetwork); err == nil {
91
-				if err := checkNameserverOverlaps(nameservers, dockerNetwork); err == nil {
92
-					ifaceAddr = addr
93
-					break
94
-				}
89
+
90
+			if err := ipallocator.RegisterNetwork(dockerNetwork, nameservers); err == nil {
91
+				ifaceAddr = addr
92
+				break
95 93
 			} else {
96 94
 				utils.Debugf("%s: %s", addr, err)
97 95
 			}
98 96
 		}
99 97
 	}
98
+
100 99
 	if ifaceAddr == "" {
101 100
 		return fmt.Errorf("Could not find a free IP address range for interface '%s'. Please configure its address manually and run 'docker -b %s'", config.BridgeIface, config.BridgeIface)
102 101
 	}
... ...
@@ -367,54 +351,6 @@ func newPortAllocator() (*PortAllocator, error) {
367 367
 	return allocator, nil
368 368
 }
369 369
 
370
-// IP allocator: Automatically allocate and release networking ports
371
-type IPAllocator struct {
372
-	network       *net.IPNet
373
-	queueAlloc    chan allocatedIP
374
-	queueReleased chan net.IP
375
-	inUse         map[int32]struct{}
376
-	quit          chan bool
377
-}
378
-
379
-type allocatedIP struct {
380
-	ip  net.IP
381
-	err error
382
-}
383
-
384
-func (alloc *IPAllocator) run() {
385
-}
386
-
387
-func (alloc *IPAllocator) Acquire() (net.IP, error) {
388
-	ip := <-alloc.queueAlloc
389
-	return ip.ip, ip.err
390
-}
391
-
392
-func (alloc *IPAllocator) Release(ip net.IP) {
393
-	alloc.queueReleased <- ip
394
-}
395
-
396
-func (alloc *IPAllocator) Close() error {
397
-	alloc.quit <- true
398
-	close(alloc.quit)
399
-	close(alloc.queueAlloc)
400
-	close(alloc.queueReleased)
401
-	return nil
402
-}
403
-
404
-func newIPAllocator(network *net.IPNet) *IPAllocator {
405
-	alloc := &IPAllocator{
406
-		network:       network,
407
-		queueAlloc:    make(chan allocatedIP),
408
-		queueReleased: make(chan net.IP),
409
-		inUse:         make(map[int32]struct{}),
410
-		quit:          make(chan bool),
411
-	}
412
-
413
-	go alloc.run()
414
-
415
-	return alloc
416
-}
417
-
418 370
 // Network interface represents the networking stack of a container
419 371
 type NetworkInterface struct {
420 372
 	IPNet   net.IPNet
... ...
@@ -519,7 +455,9 @@ func (iface *NetworkInterface) Release() {
519 519
 		}
520 520
 	}
521 521
 
522
-	iface.manager.ipAllocator.Release(iface.IPNet.IP)
522
+	if err := ipallocator.ReleaseIP(iface.manager.bridgeNetwork, &iface.IPNet.IP); err != nil {
523
+		log.Printf("Unable to release ip %s\n", err)
524
+	}
523 525
 }
524 526
 
525 527
 // Network Manager manages a set of network interfaces
... ...
@@ -528,7 +466,6 @@ type NetworkManager struct {
528 528
 	bridgeIface   string
529 529
 	bridgeNetwork *net.IPNet
530 530
 
531
-	ipAllocator      *IPAllocator
532 531
 	tcpPortAllocator *PortAllocator
533 532
 	udpPortAllocator *PortAllocator
534 533
 	portMapper       *PortMapper
... ...
@@ -543,27 +480,31 @@ func (manager *NetworkManager) Allocate() (*NetworkInterface, error) {
543 543
 		return &NetworkInterface{disabled: true}, nil
544 544
 	}
545 545
 
546
-	var ip net.IP
546
+	var ip *net.IP
547 547
 	var err error
548 548
 
549
-	ip, err = manager.ipAllocator.Acquire()
549
+	ip, err = ipallocator.RequestIP(manager.bridgeNetwork, nil)
550 550
 	if err != nil {
551 551
 		return nil, err
552 552
 	}
553
-	// avoid duplicate IP
554
-	ipNum := ipToInt(ip)
555
-	firstIP := manager.ipAllocator.network.IP.To4().Mask(manager.ipAllocator.network.Mask)
556
-	firstIPNum := ipToInt(firstIP) + 1
557 553
 
558
-	if firstIPNum == ipNum {
559
-		ip, err = manager.ipAllocator.Acquire()
560
-		if err != nil {
561
-			return nil, err
554
+	// TODO: @crosbymichael why are we doing this ?
555
+	/*
556
+		// avoid duplicate IP
557
+		ipNum := ipToInt(ip)
558
+		firstIP := manager.ipAllocator.network.IP.To4().Mask(manager.ipAllocator.network.Mask)
559
+		firstIPNum := ipToInt(firstIP) + 1
560
+
561
+		if firstIPNum == ipNum {
562
+			ip, err = manager.ipAllocator.Acquire()
563
+			if err != nil {
564
+				return nil, err
565
+			}
562 566
 		}
563
-	}
567
+	*/
564 568
 
565 569
 	iface := &NetworkInterface{
566
-		IPNet:   net.IPNet{IP: ip, Mask: manager.bridgeNetwork.Mask},
570
+		IPNet:   net.IPNet{IP: *ip, Mask: manager.bridgeNetwork.Mask},
567 571
 		Gateway: manager.bridgeNetwork.IP,
568 572
 		manager: manager,
569 573
 	}
... ...
@@ -576,14 +517,13 @@ func (manager *NetworkManager) Close() error {
576 576
 	}
577 577
 	err1 := manager.tcpPortAllocator.Close()
578 578
 	err2 := manager.udpPortAllocator.Close()
579
-	err3 := manager.ipAllocator.Close()
580 579
 	if err1 != nil {
581 580
 		return err1
582 581
 	}
583 582
 	if err2 != nil {
584 583
 		return err2
585 584
 	}
586
-	return err3
585
+	return nil
587 586
 }
588 587
 
589 588
 func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) {
... ...
@@ -670,8 +610,6 @@ func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) {
670 670
 		}
671 671
 	}
672 672
 
673
-	ipAllocator := newIPAllocator(network)
674
-
675 673
 	tcpPortAllocator, err := newPortAllocator()
676 674
 	if err != nil {
677 675
 		return nil, err
... ...
@@ -690,7 +628,6 @@ func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) {
690 690
 	manager := &NetworkManager{
691 691
 		bridgeIface:      config.BridgeIface,
692 692
 		bridgeNetwork:    network,
693
-		ipAllocator:      ipAllocator,
694 693
 		tcpPortAllocator: tcpPortAllocator,
695 694
 		udpPortAllocator: udpPortAllocator,
696 695
 		portMapper:       portMapper,
... ...
@@ -2,9 +2,7 @@ package docker
2 2
 
3 3
 import (
4 4
 	"github.com/dotcloud/docker/pkg/iptables"
5
-	"github.com/dotcloud/docker/pkg/netlink"
6 5
 	"github.com/dotcloud/docker/proxy"
7
-
8 6
 	"net"
9 7
 	"testing"
10 8
 )
... ...
@@ -53,277 +51,6 @@ func TestPortAllocation(t *testing.T) {
53 53
 	}
54 54
 }
55 55
 
56
-func TestNetworkRange(t *testing.T) {
57
-	// Simple class C test
58
-	_, network, _ := net.ParseCIDR("192.168.0.1/24")
59
-	first, last := networkRange(network)
60
-	if !first.Equal(net.ParseIP("192.168.0.0")) {
61
-		t.Error(first.String())
62
-	}
63
-	if !last.Equal(net.ParseIP("192.168.0.255")) {
64
-		t.Error(last.String())
65
-	}
66
-	if size := networkSize(network.Mask); size != 256 {
67
-		t.Error(size)
68
-	}
69
-
70
-	// Class A test
71
-	_, network, _ = net.ParseCIDR("10.0.0.1/8")
72
-	first, last = networkRange(network)
73
-	if !first.Equal(net.ParseIP("10.0.0.0")) {
74
-		t.Error(first.String())
75
-	}
76
-	if !last.Equal(net.ParseIP("10.255.255.255")) {
77
-		t.Error(last.String())
78
-	}
79
-	if size := networkSize(network.Mask); size != 16777216 {
80
-		t.Error(size)
81
-	}
82
-
83
-	// Class A, random IP address
84
-	_, network, _ = net.ParseCIDR("10.1.2.3/8")
85
-	first, last = networkRange(network)
86
-	if !first.Equal(net.ParseIP("10.0.0.0")) {
87
-		t.Error(first.String())
88
-	}
89
-	if !last.Equal(net.ParseIP("10.255.255.255")) {
90
-		t.Error(last.String())
91
-	}
92
-
93
-	// 32bit mask
94
-	_, network, _ = net.ParseCIDR("10.1.2.3/32")
95
-	first, last = networkRange(network)
96
-	if !first.Equal(net.ParseIP("10.1.2.3")) {
97
-		t.Error(first.String())
98
-	}
99
-	if !last.Equal(net.ParseIP("10.1.2.3")) {
100
-		t.Error(last.String())
101
-	}
102
-	if size := networkSize(network.Mask); size != 1 {
103
-		t.Error(size)
104
-	}
105
-
106
-	// 31bit mask
107
-	_, network, _ = net.ParseCIDR("10.1.2.3/31")
108
-	first, last = networkRange(network)
109
-	if !first.Equal(net.ParseIP("10.1.2.2")) {
110
-		t.Error(first.String())
111
-	}
112
-	if !last.Equal(net.ParseIP("10.1.2.3")) {
113
-		t.Error(last.String())
114
-	}
115
-	if size := networkSize(network.Mask); size != 2 {
116
-		t.Error(size)
117
-	}
118
-
119
-	// 26bit mask
120
-	_, network, _ = net.ParseCIDR("10.1.2.3/26")
121
-	first, last = networkRange(network)
122
-	if !first.Equal(net.ParseIP("10.1.2.0")) {
123
-		t.Error(first.String())
124
-	}
125
-	if !last.Equal(net.ParseIP("10.1.2.63")) {
126
-		t.Error(last.String())
127
-	}
128
-	if size := networkSize(network.Mask); size != 64 {
129
-		t.Error(size)
130
-	}
131
-}
132
-
133
-func TestConversion(t *testing.T) {
134
-	ip := net.ParseIP("127.0.0.1")
135
-	i := ipToInt(ip)
136
-	if i == 0 {
137
-		t.Fatal("converted to zero")
138
-	}
139
-	conv := intToIP(i)
140
-	if !ip.Equal(conv) {
141
-		t.Error(conv.String())
142
-	}
143
-}
144
-
145
-func TestIPAllocator(t *testing.T) {
146
-	expectedIPs := []net.IP{
147
-		0: net.IPv4(127, 0, 0, 2),
148
-		1: net.IPv4(127, 0, 0, 3),
149
-		2: net.IPv4(127, 0, 0, 4),
150
-		3: net.IPv4(127, 0, 0, 5),
151
-		4: net.IPv4(127, 0, 0, 6),
152
-	}
153
-
154
-	gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
155
-	alloc := newIPAllocator(&net.IPNet{IP: gwIP, Mask: n.Mask})
156
-	// Pool after initialisation (f = free, u = used)
157
-	// 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
158
-	//  ↑
159
-
160
-	// Check that we get 5 IPs, from 127.0.0.2–127.0.0.6, in that
161
-	// order.
162
-	for i := 0; i < 5; i++ {
163
-		ip, err := alloc.Acquire()
164
-		if err != nil {
165
-			t.Fatal(err)
166
-		}
167
-
168
-		assertIPEquals(t, expectedIPs[i], ip)
169
-	}
170
-	// Before loop begin
171
-	// 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
172
-	//  ↑
173
-
174
-	// After i = 0
175
-	// 2(u) - 3(f) - 4(f) - 5(f) - 6(f)
176
-	//         ↑
177
-
178
-	// After i = 1
179
-	// 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
180
-	//                ↑
181
-
182
-	// After i = 2
183
-	// 2(u) - 3(u) - 4(u) - 5(f) - 6(f)
184
-	//                       ↑
185
-
186
-	// After i = 3
187
-	// 2(u) - 3(u) - 4(u) - 5(u) - 6(f)
188
-	//                              ↑
189
-
190
-	// After i = 4
191
-	// 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
192
-	//  ↑
193
-
194
-	// Check that there are no more IPs
195
-	_, err := alloc.Acquire()
196
-	if err == nil {
197
-		t.Fatal("There shouldn't be any IP addresses at this point")
198
-	}
199
-
200
-	// Release some IPs in non-sequential order
201
-	alloc.Release(expectedIPs[3])
202
-	// 2(u) - 3(u) - 4(u) - 5(f) - 6(u)
203
-	//                       ↑
204
-
205
-	alloc.Release(expectedIPs[2])
206
-	// 2(u) - 3(u) - 4(f) - 5(f) - 6(u)
207
-	//                       ↑
208
-
209
-	alloc.Release(expectedIPs[4])
210
-	// 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
211
-	//                       ↑
212
-
213
-	// Make sure that IPs are reused in sequential order, starting
214
-	// with the first released IP
215
-	newIPs := make([]net.IP, 3)
216
-	for i := 0; i < 3; i++ {
217
-		ip, err := alloc.Acquire()
218
-		if err != nil {
219
-			t.Fatal(err)
220
-		}
221
-
222
-		newIPs[i] = ip
223
-	}
224
-	// Before loop begin
225
-	// 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
226
-	//                       ↑
227
-
228
-	// After i = 0
229
-	// 2(u) - 3(u) - 4(f) - 5(u) - 6(f)
230
-	//                              ↑
231
-
232
-	// After i = 1
233
-	// 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
234
-	//                ↑
235
-
236
-	// After i = 2
237
-	// 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
238
-	//                       ↑
239
-
240
-	assertIPEquals(t, expectedIPs[3], newIPs[0])
241
-	assertIPEquals(t, expectedIPs[4], newIPs[1])
242
-	assertIPEquals(t, expectedIPs[2], newIPs[2])
243
-
244
-	_, err = alloc.Acquire()
245
-	if err == nil {
246
-		t.Fatal("There shouldn't be any IP addresses at this point")
247
-	}
248
-}
249
-
250
-func assertIPEquals(t *testing.T, ip1, ip2 net.IP) {
251
-	if !ip1.Equal(ip2) {
252
-		t.Fatalf("Expected IP %s, got %s", ip1, ip2)
253
-	}
254
-}
255
-
256
-func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
257
-	_, netX, _ := net.ParseCIDR(CIDRx)
258
-	_, netY, _ := net.ParseCIDR(CIDRy)
259
-	if !networkOverlaps(netX, netY) {
260
-		t.Errorf("%v and %v should overlap", netX, netY)
261
-	}
262
-}
263
-
264
-func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
265
-	_, netX, _ := net.ParseCIDR(CIDRx)
266
-	_, netY, _ := net.ParseCIDR(CIDRy)
267
-	if networkOverlaps(netX, netY) {
268
-		t.Errorf("%v and %v should not overlap", netX, netY)
269
-	}
270
-}
271
-
272
-func TestNetworkOverlaps(t *testing.T) {
273
-	//netY starts at same IP and ends within netX
274
-	AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
275
-	//netY starts within netX and ends at same IP
276
-	AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
277
-	//netY starts and ends within netX
278
-	AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
279
-	//netY starts at same IP and ends outside of netX
280
-	AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
281
-	//netY starts before and ends at same IP of netX
282
-	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
283
-	//netY starts before and ends outside of netX
284
-	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
285
-	//netY starts and ends before netX
286
-	AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
287
-	//netX starts and ends before netY
288
-	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
289
-}
290
-
291
-func TestCheckRouteOverlaps(t *testing.T) {
292
-	routesData := []string{"10.0.2.0/32", "10.0.3.0/24", "10.0.42.0/24", "172.16.42.0/24", "192.168.142.0/24"}
293
-
294
-	routes := []netlink.Route{}
295
-	for _, addr := range routesData {
296
-		_, netX, _ := net.ParseCIDR(addr)
297
-		routes = append(routes, netlink.Route{IPNet: netX})
298
-	}
299
-
300
-	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
301
-	if err := checkRouteOverlaps(routes, netX); err != nil {
302
-		t.Fatal(err)
303
-	}
304
-
305
-	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
306
-	if err := checkRouteOverlaps(routes, netX); err == nil {
307
-		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
308
-	}
309
-}
310
-
311
-func TestCheckNameserverOverlaps(t *testing.T) {
312
-	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
313
-
314
-	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
315
-
316
-	if err := checkNameserverOverlaps(nameservers, netX); err == nil {
317
-		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
318
-	}
319
-
320
-	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
321
-
322
-	if err := checkNameserverOverlaps(nameservers, netX); err != nil {
323
-		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
324
-	}
325
-}
326
-
327 56
 type StubProxy struct {
328 57
 	frontendAddr *net.Addr
329 58
 	backendAddr  *net.Addr
... ...
@@ -16,20 +16,25 @@ type iPNet struct {
16 16
 }
17 17
 
18 18
 var (
19
-	ErrNetworkAlreadyAllocated = errors.New("requested network overlaps with existing network")
20
-	ErrNetworkAlreadyRegisterd = errors.New("requested network is already registered")
21
-	ErrNoAvailableIps          = errors.New("no available ips on network")
22
-	ErrIPAlreadyAllocated      = errors.New("ip already allocated")
19
+	ErrNetworkAlreadyAllocated        = errors.New("requested network overlaps with existing network")
20
+	ErrNetworkAlreadyRegisterd        = errors.New("requested network is already registered")
21
+	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
22
+	ErrNoAvailableIps                 = errors.New("no available ips on network")
23
+	ErrIPAlreadyAllocated             = errors.New("ip already allocated")
23 24
 
24 25
 	lock         = sync.Mutex{}
25 26
 	allocatedIPs = networkSet{}
26 27
 	availableIPS = networkSet{}
27 28
 )
28 29
 
29
-func RegisterNetwork(network *net.IPNet) error {
30
+func RegisterNetwork(network *net.IPNet, nameservers []string) error {
30 31
 	lock.Lock()
31 32
 	defer lock.Unlock()
32 33
 
34
+	if err := checkExistingNetworkOverlaps(network); err != nil {
35
+		return err
36
+	}
37
+
33 38
 	routes, err := netlink.NetworkGetRoutes()
34 39
 	if err != nil {
35 40
 		return err
... ...
@@ -39,9 +44,10 @@ func RegisterNetwork(network *net.IPNet) error {
39 39
 		return err
40 40
 	}
41 41
 
42
-	if err := checkExistingNetworkOverlaps(network); err != nil {
42
+	if err := checkNameserverOverlaps(nameservers, network); err != nil {
43 43
 		return err
44 44
 	}
45
+
45 46
 	n := newIPNet(network)
46 47
 
47 48
 	allocatedIPs[n] = &iPSet{}
... ...
@@ -227,3 +233,18 @@ func networkSize(mask net.IPMask) int32 {
227 227
 
228 228
 	return int32(binary.BigEndian.Uint32(m)) + 1
229 229
 }
230
+
231
+func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
232
+	if len(nameservers) > 0 {
233
+		for _, ns := range nameservers {
234
+			_, nsNetwork, err := net.ParseCIDR(ns)
235
+			if err != nil {
236
+				return err
237
+			}
238
+			if networkOverlaps(toCheck, nsNetwork) {
239
+				return ErrNetworkOverlapsWithNameservers
240
+			}
241
+		}
242
+	}
243
+	return nil
244
+}
... ...
@@ -2,6 +2,7 @@ package ipallocator
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"github.com/dotcloud/docker/pkg/netlink"
5 6
 	"net"
6 7
 	"testing"
7 8
 )
... ...
@@ -18,7 +19,7 @@ func TestRegisterNetwork(t *testing.T) {
18 18
 		Mask: []byte{255, 255, 255, 0},
19 19
 	}
20 20
 
21
-	if err := RegisterNetwork(network); err != nil {
21
+	if err := RegisterNetwork(network, nil); err != nil {
22 22
 		t.Fatal(err)
23 23
 	}
24 24
 
... ...
@@ -39,7 +40,7 @@ func TestRegisterTwoNetworks(t *testing.T) {
39 39
 		Mask: []byte{255, 255, 255, 0},
40 40
 	}
41 41
 
42
-	if err := RegisterNetwork(network); err != nil {
42
+	if err := RegisterNetwork(network, nil); err != nil {
43 43
 		t.Fatal(err)
44 44
 	}
45 45
 
... ...
@@ -48,7 +49,7 @@ func TestRegisterTwoNetworks(t *testing.T) {
48 48
 		Mask: []byte{255, 255, 255, 0},
49 49
 	}
50 50
 
51
-	if err := RegisterNetwork(network2); err != nil {
51
+	if err := RegisterNetwork(network2, nil); err != nil {
52 52
 		t.Fatal(err)
53 53
 	}
54 54
 }
... ...
@@ -60,11 +61,11 @@ func TestRegisterNetworkThatExists(t *testing.T) {
60 60
 		Mask: []byte{255, 255, 255, 0},
61 61
 	}
62 62
 
63
-	if err := RegisterNetwork(network); err != nil {
63
+	if err := RegisterNetwork(network, nil); err != nil {
64 64
 		t.Fatal(err)
65 65
 	}
66 66
 
67
-	if err := RegisterNetwork(network); err != ErrNetworkAlreadyRegisterd {
67
+	if err := RegisterNetwork(network, nil); err != ErrNetworkAlreadyRegisterd {
68 68
 		t.Fatalf("Expected error of %s got %s", ErrNetworkAlreadyRegisterd, err)
69 69
 	}
70 70
 }
... ...
@@ -76,7 +77,7 @@ func TestRequestNewIps(t *testing.T) {
76 76
 		Mask: []byte{255, 255, 255, 0},
77 77
 	}
78 78
 
79
-	if err := RegisterNetwork(network); err != nil {
79
+	if err := RegisterNetwork(network, nil); err != nil {
80 80
 		t.Fatal(err)
81 81
 	}
82 82
 
... ...
@@ -99,7 +100,7 @@ func TestReleaseIp(t *testing.T) {
99 99
 		Mask: []byte{255, 255, 255, 0},
100 100
 	}
101 101
 
102
-	if err := RegisterNetwork(network); err != nil {
102
+	if err := RegisterNetwork(network, nil); err != nil {
103 103
 		t.Fatal(err)
104 104
 	}
105 105
 
... ...
@@ -120,7 +121,7 @@ func TestGetReleasedIp(t *testing.T) {
120 120
 		Mask: []byte{255, 255, 255, 0},
121 121
 	}
122 122
 
123
-	if err := RegisterNetwork(network); err != nil {
123
+	if err := RegisterNetwork(network, nil); err != nil {
124 124
 		t.Fatal(err)
125 125
 	}
126 126
 
... ...
@@ -151,7 +152,7 @@ func TestRequesetSpecificIp(t *testing.T) {
151 151
 		Mask: []byte{255, 255, 255, 0},
152 152
 	}
153 153
 
154
-	if err := RegisterNetwork(network); err != nil {
154
+	if err := RegisterNetwork(network, nil); err != nil {
155 155
 		t.Fatal(err)
156 156
 	}
157 157
 
... ...
@@ -161,3 +162,313 @@ func TestRequesetSpecificIp(t *testing.T) {
161 161
 		t.Fatal(err)
162 162
 	}
163 163
 }
164
+
165
+func TestNonOverlapingNameservers(t *testing.T) {
166
+	defer reset()
167
+	network := &net.IPNet{
168
+		IP:   []byte{192, 168, 0, 1},
169
+		Mask: []byte{255, 255, 255, 0},
170
+	}
171
+	nameservers := []string{
172
+		"127.0.0.1/32",
173
+	}
174
+
175
+	if err := RegisterNetwork(network, nameservers); err != nil {
176
+		t.Fatal(err)
177
+	}
178
+}
179
+
180
+func TestOverlapingNameservers(t *testing.T) {
181
+	defer reset()
182
+	network := &net.IPNet{
183
+		IP:   []byte{192, 168, 0, 1},
184
+		Mask: []byte{255, 255, 255, 0},
185
+	}
186
+	nameservers := []string{
187
+		"192.168.0.1/32",
188
+	}
189
+
190
+	if err := RegisterNetwork(network, nameservers); err != ErrNetworkOverlapsWithNameservers {
191
+		t.Fatalf("Expectecd error of %s got %s", ErrNetworkOverlapsWithNameservers, err)
192
+	}
193
+}
194
+
195
+func TestNetworkRange(t *testing.T) {
196
+	// Simple class C test
197
+	_, network, _ := net.ParseCIDR("192.168.0.1/24")
198
+	first, last := networkRange(network)
199
+	if !first.Equal(net.ParseIP("192.168.0.0")) {
200
+		t.Error(first.String())
201
+	}
202
+	if !last.Equal(net.ParseIP("192.168.0.255")) {
203
+		t.Error(last.String())
204
+	}
205
+	if size := networkSize(network.Mask); size != 256 {
206
+		t.Error(size)
207
+	}
208
+
209
+	// Class A test
210
+	_, network, _ = net.ParseCIDR("10.0.0.1/8")
211
+	first, last = networkRange(network)
212
+	if !first.Equal(net.ParseIP("10.0.0.0")) {
213
+		t.Error(first.String())
214
+	}
215
+	if !last.Equal(net.ParseIP("10.255.255.255")) {
216
+		t.Error(last.String())
217
+	}
218
+	if size := networkSize(network.Mask); size != 16777216 {
219
+		t.Error(size)
220
+	}
221
+
222
+	// Class A, random IP address
223
+	_, network, _ = net.ParseCIDR("10.1.2.3/8")
224
+	first, last = networkRange(network)
225
+	if !first.Equal(net.ParseIP("10.0.0.0")) {
226
+		t.Error(first.String())
227
+	}
228
+	if !last.Equal(net.ParseIP("10.255.255.255")) {
229
+		t.Error(last.String())
230
+	}
231
+
232
+	// 32bit mask
233
+	_, network, _ = net.ParseCIDR("10.1.2.3/32")
234
+	first, last = networkRange(network)
235
+	if !first.Equal(net.ParseIP("10.1.2.3")) {
236
+		t.Error(first.String())
237
+	}
238
+	if !last.Equal(net.ParseIP("10.1.2.3")) {
239
+		t.Error(last.String())
240
+	}
241
+	if size := networkSize(network.Mask); size != 1 {
242
+		t.Error(size)
243
+	}
244
+
245
+	// 31bit mask
246
+	_, network, _ = net.ParseCIDR("10.1.2.3/31")
247
+	first, last = networkRange(network)
248
+	if !first.Equal(net.ParseIP("10.1.2.2")) {
249
+		t.Error(first.String())
250
+	}
251
+	if !last.Equal(net.ParseIP("10.1.2.3")) {
252
+		t.Error(last.String())
253
+	}
254
+	if size := networkSize(network.Mask); size != 2 {
255
+		t.Error(size)
256
+	}
257
+
258
+	// 26bit mask
259
+	_, network, _ = net.ParseCIDR("10.1.2.3/26")
260
+	first, last = networkRange(network)
261
+	if !first.Equal(net.ParseIP("10.1.2.0")) {
262
+		t.Error(first.String())
263
+	}
264
+	if !last.Equal(net.ParseIP("10.1.2.63")) {
265
+		t.Error(last.String())
266
+	}
267
+	if size := networkSize(network.Mask); size != 64 {
268
+		t.Error(size)
269
+	}
270
+}
271
+
272
+func TestConversion(t *testing.T) {
273
+	ip := net.ParseIP("127.0.0.1")
274
+	i := ipToInt(&ip)
275
+	if i == 0 {
276
+		t.Fatal("converted to zero")
277
+	}
278
+	conv := intToIP(i)
279
+	if !ip.Equal(*conv) {
280
+		t.Error(conv.String())
281
+	}
282
+}
283
+
284
+func TestIPAllocator(t *testing.T) {
285
+	expectedIPs := []net.IP{
286
+		0: net.IPv4(127, 0, 0, 2),
287
+		1: net.IPv4(127, 0, 0, 3),
288
+		2: net.IPv4(127, 0, 0, 4),
289
+		3: net.IPv4(127, 0, 0, 5),
290
+		4: net.IPv4(127, 0, 0, 6),
291
+	}
292
+
293
+	gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
294
+	network := &net.IPNet{IP: gwIP, Mask: n.Mask}
295
+	if err := RegisterNetwork(network, nil); err != nil {
296
+		t.Fatal(err)
297
+	}
298
+	// Pool after initialisation (f = free, u = used)
299
+	// 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
300
+	//  ↑
301
+
302
+	// Check that we get 5 IPs, from 127.0.0.2–127.0.0.6, in that
303
+	// order.
304
+	for i := 0; i < 5; i++ {
305
+		ip, err := RequestIP(network, nil)
306
+		if err != nil {
307
+			t.Fatal(err)
308
+		}
309
+
310
+		assertIPEquals(t, &expectedIPs[i], ip)
311
+	}
312
+	// Before loop begin
313
+	// 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
314
+	//  ↑
315
+
316
+	// After i = 0
317
+	// 2(u) - 3(f) - 4(f) - 5(f) - 6(f)
318
+	//         ↑
319
+
320
+	// After i = 1
321
+	// 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
322
+	//                ↑
323
+
324
+	// After i = 2
325
+	// 2(u) - 3(u) - 4(u) - 5(f) - 6(f)
326
+	//                       ↑
327
+
328
+	// After i = 3
329
+	// 2(u) - 3(u) - 4(u) - 5(u) - 6(f)
330
+	//                              ↑
331
+
332
+	// After i = 4
333
+	// 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
334
+	//  ↑
335
+
336
+	// Check that there are no more IPs
337
+	ip, err := RequestIP(network, nil)
338
+	if err == nil {
339
+		t.Fatalf("There shouldn't be any IP addresses at this point, got %s\n", ip)
340
+	}
341
+
342
+	// Release some IPs in non-sequential order
343
+	if err := ReleaseIP(network, &expectedIPs[3]); err != nil {
344
+		t.Fatal(err)
345
+	}
346
+	// 2(u) - 3(u) - 4(u) - 5(f) - 6(u)
347
+	//                       ↑
348
+
349
+	if err := ReleaseIP(network, &expectedIPs[2]); err != nil {
350
+		t.Fatal(err)
351
+	}
352
+	// 2(u) - 3(u) - 4(f) - 5(f) - 6(u)
353
+	//                       ↑
354
+
355
+	if err := ReleaseIP(network, &expectedIPs[4]); err != nil {
356
+		t.Fatal(err)
357
+	}
358
+	// 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
359
+	//                       ↑
360
+
361
+	// Make sure that IPs are reused in sequential order, starting
362
+	// with the first released IP
363
+	newIPs := make([]*net.IP, 3)
364
+	for i := 0; i < 3; i++ {
365
+		ip, err := RequestIP(network, nil)
366
+		if err != nil {
367
+			t.Fatal(err)
368
+		}
369
+
370
+		newIPs[i] = ip
371
+	}
372
+	// Before loop begin
373
+	// 2(u) - 3(u) - 4(f) - 5(f) - 6(f)
374
+	//                       ↑
375
+
376
+	// After i = 0
377
+	// 2(u) - 3(u) - 4(f) - 5(u) - 6(f)
378
+	//                              ↑
379
+
380
+	// After i = 1
381
+	// 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
382
+	//                ↑
383
+
384
+	// After i = 2
385
+	// 2(u) - 3(u) - 4(u) - 5(u) - 6(u)
386
+	//                       ↑
387
+
388
+	assertIPEquals(t, &expectedIPs[3], newIPs[0])
389
+	assertIPEquals(t, &expectedIPs[4], newIPs[1])
390
+	assertIPEquals(t, &expectedIPs[2], newIPs[2])
391
+
392
+	_, err = RequestIP(network, nil)
393
+	if err == nil {
394
+		t.Fatal("There shouldn't be any IP addresses at this point")
395
+	}
396
+}
397
+
398
+func assertIPEquals(t *testing.T, ip1, ip2 *net.IP) {
399
+	if !ip1.Equal(*ip2) {
400
+		t.Fatalf("Expected IP %s, got %s", ip1, ip2)
401
+	}
402
+}
403
+
404
+func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
405
+	_, netX, _ := net.ParseCIDR(CIDRx)
406
+	_, netY, _ := net.ParseCIDR(CIDRy)
407
+	if !networkOverlaps(netX, netY) {
408
+		t.Errorf("%v and %v should overlap", netX, netY)
409
+	}
410
+}
411
+
412
+func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
413
+	_, netX, _ := net.ParseCIDR(CIDRx)
414
+	_, netY, _ := net.ParseCIDR(CIDRy)
415
+	if networkOverlaps(netX, netY) {
416
+		t.Errorf("%v and %v should not overlap", netX, netY)
417
+	}
418
+}
419
+
420
+func TestNetworkOverlaps(t *testing.T) {
421
+	//netY starts at same IP and ends within netX
422
+	AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
423
+	//netY starts within netX and ends at same IP
424
+	AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
425
+	//netY starts and ends within netX
426
+	AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
427
+	//netY starts at same IP and ends outside of netX
428
+	AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
429
+	//netY starts before and ends at same IP of netX
430
+	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
431
+	//netY starts before and ends outside of netX
432
+	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
433
+	//netY starts and ends before netX
434
+	AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
435
+	//netX starts and ends before netY
436
+	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
437
+}
438
+
439
+func TestCheckRouteOverlaps(t *testing.T) {
440
+	routesData := []string{"10.0.2.0/32", "10.0.3.0/24", "10.0.42.0/24", "172.16.42.0/24", "192.168.142.0/24"}
441
+
442
+	routes := []netlink.Route{}
443
+	for _, addr := range routesData {
444
+		_, netX, _ := net.ParseCIDR(addr)
445
+		routes = append(routes, netlink.Route{IPNet: netX})
446
+	}
447
+
448
+	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
449
+	if err := checkRouteOverlaps(routes, netX); err != nil {
450
+		t.Fatal(err)
451
+	}
452
+
453
+	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
454
+	if err := checkRouteOverlaps(routes, netX); err == nil {
455
+		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
456
+	}
457
+}
458
+
459
+func TestCheckNameserverOverlaps(t *testing.T) {
460
+	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
461
+
462
+	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
463
+
464
+	if err := checkNameserverOverlaps(nameservers, netX); err == nil {
465
+		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
466
+	}
467
+
468
+	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
469
+
470
+	if err := checkNameserverOverlaps(nameservers, netX); err != nil {
471
+		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
472
+	}
473
+}
164 474
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+package networkdriver