Browse code

Refactor and fix register interface when bridge does not exist

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

Michael Crosby authored on 2014/01/24 07:39:10
Showing 5 changed files
... ...
@@ -2,6 +2,7 @@ package docker
2 2
 
3 3
 import (
4 4
 	"fmt"
5
+	"github.com/dotcloud/docker/networkdriver"
5 6
 	"github.com/dotcloud/docker/networkdriver/ipallocator"
6 7
 	"github.com/dotcloud/docker/pkg/iptables"
7 8
 	"github.com/dotcloud/docker/pkg/netlink"
... ...
@@ -60,13 +61,10 @@ func CreateBridgeIface(config *DaemonConfig) error {
60 60
 
61 61
 	var ifaceAddr string
62 62
 	if len(config.BridgeIp) != 0 {
63
-		_, dockerNetwork, err := net.ParseCIDR(config.BridgeIp)
63
+		_, _, err := net.ParseCIDR(config.BridgeIp)
64 64
 		if err != nil {
65 65
 			return err
66 66
 		}
67
-		if err := ipallocator.RegisterNetwork(dockerNetwork, nameservers); err != nil {
68
-			return err
69
-		}
70 67
 		ifaceAddr = config.BridgeIp
71 68
 	} else {
72 69
 		for _, addr := range addrs {
... ...
@@ -74,12 +72,13 @@ func CreateBridgeIface(config *DaemonConfig) error {
74 74
 			if err != nil {
75 75
 				return err
76 76
 			}
77
-
78
-			if err := ipallocator.RegisterNetwork(dockerNetwork, nameservers); err == nil {
79
-				ifaceAddr = addr
80
-				break
81
-			} else {
82
-				utils.Debugf("%s: %s", addr, err)
77
+			if err := networkdriver.CheckNameserverOverlaps(nameservers, dockerNetwork); err == nil {
78
+				if err := networkdriver.CheckRouteOverlaps(dockerNetwork); err == nil {
79
+					ifaceAddr = addr
80
+					break
81
+				} else {
82
+					utils.Debugf("%s %s", addr, err)
83
+				}
83 84
 			}
84 85
 		}
85 86
 	}
... ...
@@ -491,21 +490,6 @@ func (manager *NetworkManager) Allocate() (*NetworkInterface, error) {
491 491
 		return nil, err
492 492
 	}
493 493
 
494
-	// TODO: @crosbymichael why are we doing this ?
495
-	/*
496
-		// avoid duplicate IP
497
-		ipNum := ipToInt(ip)
498
-		firstIP := manager.ipAllocator.network.IP.To4().Mask(manager.ipAllocator.network.Mask)
499
-		firstIPNum := ipToInt(firstIP) + 1
500
-
501
-		if firstIPNum == ipNum {
502
-			ip, err = manager.ipAllocator.Acquire()
503
-			if err != nil {
504
-				return nil, err
505
-			}
506
-		}
507
-	*/
508
-
509 494
 	iface := &NetworkInterface{
510 495
 		IPNet:   net.IPNet{IP: *ip, Mask: manager.bridgeNetwork.Mask},
511 496
 		Gateway: manager.bridgeNetwork.IP,
... ...
@@ -551,9 +535,6 @@ func newNetworkManager(config *DaemonConfig) (*NetworkManager, error) {
551 551
 		network = addr.(*net.IPNet)
552 552
 	} else {
553 553
 		network = addr.(*net.IPNet)
554
-		if err := ipallocator.RegisterExistingNetwork(network); err != nil {
555
-			return nil, err
556
-		}
557 554
 	}
558 555
 
559 556
 	// Configure iptables for link support
... ...
@@ -3,93 +3,43 @@ package ipallocator
3 3
 import (
4 4
 	"encoding/binary"
5 5
 	"errors"
6
-	"github.com/dotcloud/docker/pkg/netlink"
6
+	"github.com/dotcloud/docker/networkdriver"
7 7
 	"net"
8 8
 	"sync"
9 9
 )
10 10
 
11
-type networkSet map[iPNet]*iPSet
12
-
13
-type iPNet struct {
14
-	IP   string
15
-	Mask string
16
-}
11
+type networkSet map[string]*iPSet
17 12
 
18 13
 var (
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 ip addresses on network")
23
-	ErrIPAlreadyAllocated             = errors.New("ip already allocated")
24
-	ErrNetworkNotRegistered           = errors.New("network not registered")
14
+	ErrNoAvailableIPs     = errors.New("no available ip addresses on network")
15
+	ErrIPAlreadyAllocated = errors.New("ip already allocated")
16
+)
25 17
 
18
+var (
26 19
 	lock         = sync.Mutex{}
27 20
 	allocatedIPs = networkSet{}
28 21
 	availableIPS = networkSet{}
29 22
 )
30 23
 
31
-// RegisterNetwork registers a new network with the allocator
32
-// and validates that it contains a valid ip that does not overlap
33
-// with existing routes and nameservers
34
-func RegisterNetwork(network *net.IPNet, nameservers []string) error {
35
-	lock.Lock()
36
-	defer lock.Unlock()
37
-
38
-	if err := checkExistingNetworkOverlaps(network); err != nil {
39
-		return err
40
-	}
41
-
42
-	routes, err := netlink.NetworkGetRoutes()
43
-	if err != nil {
44
-		return err
45
-	}
46
-
47
-	if err := checkRouteOverlaps(routes, network); err != nil {
48
-		return err
49
-	}
50
-
51
-	if err := checkNameserverOverlaps(nameservers, network); err != nil {
52
-		return err
53
-	}
54
-	return RegisterExistingNetwork(network)
55
-}
56
-
57
-// RegisterExistingNetwork registers an exising network created
58
-// for use with the allocator but does not perform any validation
59
-func RegisterExistingNetwork(network *net.IPNet) error {
60
-	n := newIPNet(network)
61
-
62
-	if _, exists := allocatedIPs[n]; !exists {
63
-		allocatedIPs[n] = &iPSet{}
64
-	}
65
-	if _, exists := availableIPS[n]; !exists {
66
-		availableIPS[n] = &iPSet{}
67
-	}
68
-
69
-	return nil
70
-}
71
-
72 24
 // RequestIP requests an available ip from the given network.  It
73 25
 // will return the next available ip if the ip provided is nil.  If the
74 26
 // ip provided is not nil it will validate that the provided ip is available
75 27
 // for use or return an error
76
-func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) {
28
+func RequestIP(address *net.IPNet, ip *net.IP) (*net.IP, error) {
77 29
 	lock.Lock()
78 30
 	defer lock.Unlock()
79 31
 
80
-	if !networkExists(network) {
81
-		return nil, ErrNetworkNotRegistered
82
-	}
32
+	checkAddress(address)
83 33
 
84 34
 	if ip == nil {
85
-		next, err := getNextIp(network)
35
+		next, err := getNextIp(address)
86 36
 		if err != nil {
87 37
 			return nil, err
88 38
 		}
89 39
 		return next, nil
90 40
 	}
91 41
 
92
-	if err := registerIP(network, ip); err != nil {
42
+	if err := registerIP(address, ip); err != nil {
93 43
 		return nil, err
94 44
 	}
95 45
 	return ip, nil
... ...
@@ -97,19 +47,16 @@ func RequestIP(network *net.IPNet, ip *net.IP) (*net.IP, error) {
97 97
 
98 98
 // ReleaseIP adds the provided ip back into the pool of
99 99
 // available ips to be returned for use.
100
-func ReleaseIP(network *net.IPNet, ip *net.IP) error {
100
+func ReleaseIP(address *net.IPNet, ip *net.IP) error {
101 101
 	lock.Lock()
102 102
 	defer lock.Unlock()
103 103
 
104
-	if !networkExists(network) {
105
-		return ErrNetworkNotRegistered
106
-	}
104
+	checkAddress(address)
107 105
 
108 106
 	var (
109
-		n         = newIPNet(network)
110
-		existing  = allocatedIPs[n]
111
-		available = availableIPS[n]
112
-		pos       = getPosition(network, ip)
107
+		existing  = allocatedIPs[address.String()]
108
+		available = availableIPS[address.String()]
109
+		pos       = getPosition(address, ip)
113 110
 	)
114 111
 
115 112
 	existing.Remove(int(pos))
... ...
@@ -120,9 +67,9 @@ func ReleaseIP(network *net.IPNet, ip *net.IP) error {
120 120
 
121 121
 // convert the ip into the position in the subnet.  Only
122 122
 // position are saved in the set
123
-func getPosition(network *net.IPNet, ip *net.IP) int32 {
123
+func getPosition(address *net.IPNet, ip *net.IP) int32 {
124 124
 	var (
125
-		first, _ = networkRange(network)
125
+		first, _ = networkdriver.NetworkRange(address)
126 126
 		base     = ipToInt(&first)
127 127
 		i        = ipToInt(ip)
128 128
 	)
... ...
@@ -131,15 +78,14 @@ func getPosition(network *net.IPNet, ip *net.IP) int32 {
131 131
 
132 132
 // return an available ip if one is currently available.  If not,
133 133
 // return the next available ip for the nextwork
134
-func getNextIp(network *net.IPNet) (*net.IP, error) {
134
+func getNextIp(address *net.IPNet) (*net.IP, error) {
135 135
 	var (
136
-		n         = newIPNet(network)
137
-		ownIP     = ipToInt(&network.IP)
138
-		available = availableIPS[n]
139
-		allocated = allocatedIPs[n]
140
-		first, _  = networkRange(network)
136
+		ownIP     = ipToInt(&address.IP)
137
+		available = availableIPS[address.String()]
138
+		allocated = allocatedIPs[address.String()]
139
+		first, _  = networkdriver.NetworkRange(address)
141 140
 		base      = ipToInt(&first)
142
-		size      = int(networkSize(network.Mask))
141
+		size      = int(networkdriver.NetworkSize(address.Mask))
143 142
 		max       = int32(size - 2) // size -1 for the broadcast address, -1 for the gateway address
144 143
 		pos       = int32(available.Pop())
145 144
 	)
... ...
@@ -170,12 +116,11 @@ func getNextIp(network *net.IPNet) (*net.IP, error) {
170 170
 	return nil, ErrNoAvailableIPs
171 171
 }
172 172
 
173
-func registerIP(network *net.IPNet, ip *net.IP) error {
173
+func registerIP(address *net.IPNet, ip *net.IP) error {
174 174
 	var (
175
-		n         = newIPNet(network)
176
-		existing  = allocatedIPs[n]
177
-		available = availableIPS[n]
178
-		pos       = getPosition(network, ip)
175
+		existing  = allocatedIPs[address.String()]
176
+		available = availableIPS[address.String()]
177
+		pos       = getPosition(address, ip)
179 178
 	)
180 179
 
181 180
 	if existing.Exists(int(pos)) {
... ...
@@ -186,68 +131,6 @@ func registerIP(network *net.IPNet, ip *net.IP) error {
186 186
 	return nil
187 187
 }
188 188
 
189
-func checkRouteOverlaps(networks []netlink.Route, toCheck *net.IPNet) error {
190
-	for _, network := range networks {
191
-		if network.IPNet != nil && networkOverlaps(toCheck, network.IPNet) {
192
-			return ErrNetworkAlreadyAllocated
193
-		}
194
-	}
195
-	return nil
196
-}
197
-
198
-// Detects overlap between one IPNet and another
199
-func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
200
-	if firstIP, _ := networkRange(netX); netY.Contains(firstIP) {
201
-		return true
202
-	}
203
-	if firstIP, _ := networkRange(netY); netX.Contains(firstIP) {
204
-		return true
205
-	}
206
-	return false
207
-}
208
-
209
-func checkExistingNetworkOverlaps(network *net.IPNet) error {
210
-	for existing := range allocatedIPs {
211
-		if newIPNet(network) == existing {
212
-			return ErrNetworkAlreadyRegisterd
213
-		}
214
-
215
-		ex := newNetIPNet(existing)
216
-		if networkOverlaps(network, ex) {
217
-			return ErrNetworkAlreadyAllocated
218
-		}
219
-	}
220
-	return nil
221
-}
222
-
223
-// Calculates the first and last IP addresses in an IPNet
224
-func networkRange(network *net.IPNet) (net.IP, net.IP) {
225
-	var (
226
-		netIP   = network.IP.To4()
227
-		firstIP = netIP.Mask(network.Mask)
228
-		lastIP  = net.IPv4(0, 0, 0, 0).To4()
229
-	)
230
-
231
-	for i := 0; i < len(lastIP); i++ {
232
-		lastIP[i] = netIP[i] | ^network.Mask[i]
233
-	}
234
-	return firstIP, lastIP
235
-}
236
-
237
-func newIPNet(network *net.IPNet) iPNet {
238
-	return iPNet{
239
-		IP:   string(network.IP),
240
-		Mask: string(network.Mask),
241
-	}
242
-}
243
-
244
-func newNetIPNet(network iPNet) *net.IPNet {
245
-	return &net.IPNet{
246
-		IP:   []byte(network.IP),
247
-		Mask: []byte(network.Mask),
248
-	}
249
-}
250
-
251 189
 // Converts a 4 bytes IP into a 32 bit integer
252 190
 func ipToInt(ip *net.IP) int32 {
253 191
 	return int32(binary.BigEndian.Uint32(ip.To4()))
... ...
@@ -261,33 +144,10 @@ func intToIP(n int32) *net.IP {
261 261
 	return &ip
262 262
 }
263 263
 
264
-// Given a netmask, calculates the number of available hosts
265
-func networkSize(mask net.IPMask) int32 {
266
-	m := net.IPv4Mask(0, 0, 0, 0)
267
-	for i := 0; i < net.IPv4len; i++ {
268
-		m[i] = ^mask[i]
264
+func checkAddress(address *net.IPNet) {
265
+	key := address.String()
266
+	if _, exists := allocatedIPs[key]; !exists {
267
+		allocatedIPs[key] = &iPSet{}
268
+		availableIPS[key] = &iPSet{}
269 269
 	}
270
-
271
-	return int32(binary.BigEndian.Uint32(m)) + 1
272
-}
273
-
274
-func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
275
-	if len(nameservers) > 0 {
276
-		for _, ns := range nameservers {
277
-			_, nsNetwork, err := net.ParseCIDR(ns)
278
-			if err != nil {
279
-				return err
280
-			}
281
-			if networkOverlaps(toCheck, nsNetwork) {
282
-				return ErrNetworkOverlapsWithNameservers
283
-			}
284
-		}
285
-	}
286
-	return nil
287
-}
288
-
289
-func networkExists(network *net.IPNet) bool {
290
-	n := newIPNet(network)
291
-	_, exists := allocatedIPs[n]
292
-	return exists
293 270
 }
... ...
@@ -2,7 +2,6 @@ package ipallocator
2 2
 
3 3
 import (
4 4
 	"fmt"
5
-	"github.com/dotcloud/docker/pkg/netlink"
6 5
 	"net"
7 6
 	"testing"
8 7
 )
... ...
@@ -12,64 +11,6 @@ func reset() {
12 12
 	availableIPS = networkSet{}
13 13
 }
14 14
 
15
-func TestRegisterNetwork(t *testing.T) {
16
-	defer reset()
17
-	network := &net.IPNet{
18
-		IP:   []byte{192, 168, 0, 1},
19
-		Mask: []byte{255, 255, 255, 0},
20
-	}
21
-
22
-	if err := RegisterNetwork(network, nil); err != nil {
23
-		t.Fatal(err)
24
-	}
25
-
26
-	n := newIPNet(network)
27
-	if _, exists := allocatedIPs[n]; !exists {
28
-		t.Fatal("IPNet should exist in allocated IPs")
29
-	}
30
-
31
-	if _, exists := availableIPS[n]; !exists {
32
-		t.Fatal("IPNet should exist in available IPs")
33
-	}
34
-}
35
-
36
-func TestRegisterTwoNetworks(t *testing.T) {
37
-	defer reset()
38
-	network := &net.IPNet{
39
-		IP:   []byte{192, 168, 0, 1},
40
-		Mask: []byte{255, 255, 255, 0},
41
-	}
42
-
43
-	if err := RegisterNetwork(network, nil); err != nil {
44
-		t.Fatal(err)
45
-	}
46
-
47
-	network2 := &net.IPNet{
48
-		IP:   []byte{10, 1, 42, 1},
49
-		Mask: []byte{255, 255, 255, 0},
50
-	}
51
-
52
-	if err := RegisterNetwork(network2, nil); err != nil {
53
-		t.Fatal(err)
54
-	}
55
-}
56
-
57
-func TestRegisterNetworkThatExists(t *testing.T) {
58
-	defer reset()
59
-	network := &net.IPNet{
60
-		IP:   []byte{192, 168, 0, 1},
61
-		Mask: []byte{255, 255, 255, 0},
62
-	}
63
-
64
-	if err := RegisterNetwork(network, nil); err != nil {
65
-		t.Fatal(err)
66
-	}
67
-
68
-	if err := RegisterNetwork(network, nil); err != ErrNetworkAlreadyRegisterd {
69
-		t.Fatalf("Expected error of %s got %s", ErrNetworkAlreadyRegisterd, err)
70
-	}
71
-}
72
-
73 15
 func TestRequestNewIps(t *testing.T) {
74 16
 	defer reset()
75 17
 	network := &net.IPNet{
... ...
@@ -77,10 +18,6 @@ func TestRequestNewIps(t *testing.T) {
77 77
 		Mask: []byte{255, 255, 255, 0},
78 78
 	}
79 79
 
80
-	if err := RegisterNetwork(network, nil); err != nil {
81
-		t.Fatal(err)
82
-	}
83
-
84 80
 	for i := 2; i < 10; i++ {
85 81
 		ip, err := RequestIP(network, nil)
86 82
 		if err != nil {
... ...
@@ -100,10 +37,6 @@ func TestReleaseIp(t *testing.T) {
100 100
 		Mask: []byte{255, 255, 255, 0},
101 101
 	}
102 102
 
103
-	if err := RegisterNetwork(network, nil); err != nil {
104
-		t.Fatal(err)
105
-	}
106
-
107 103
 	ip, err := RequestIP(network, nil)
108 104
 	if err != nil {
109 105
 		t.Fatal(err)
... ...
@@ -121,10 +54,6 @@ func TestGetReleasedIp(t *testing.T) {
121 121
 		Mask: []byte{255, 255, 255, 0},
122 122
 	}
123 123
 
124
-	if err := RegisterNetwork(network, nil); err != nil {
125
-		t.Fatal(err)
126
-	}
127
-
128 124
 	ip, err := RequestIP(network, nil)
129 125
 	if err != nil {
130 126
 		t.Fatal(err)
... ...
@@ -152,10 +81,6 @@ func TestRequesetSpecificIp(t *testing.T) {
152 152
 		Mask: []byte{255, 255, 255, 0},
153 153
 	}
154 154
 
155
-	if err := RegisterNetwork(network, nil); err != nil {
156
-		t.Fatal(err)
157
-	}
158
-
159 155
 	ip := net.ParseIP("192.168.1.5")
160 156
 
161 157
 	if _, err := RequestIP(network, &ip); err != nil {
... ...
@@ -163,113 +88,6 @@ func TestRequesetSpecificIp(t *testing.T) {
163 163
 	}
164 164
 }
165 165
 
166
-func TestNonOverlapingNameservers(t *testing.T) {
167
-	defer reset()
168
-	network := &net.IPNet{
169
-		IP:   []byte{192, 168, 0, 1},
170
-		Mask: []byte{255, 255, 255, 0},
171
-	}
172
-	nameservers := []string{
173
-		"127.0.0.1/32",
174
-	}
175
-
176
-	if err := RegisterNetwork(network, nameservers); err != nil {
177
-		t.Fatal(err)
178
-	}
179
-}
180
-
181
-func TestOverlapingNameservers(t *testing.T) {
182
-	defer reset()
183
-	network := &net.IPNet{
184
-		IP:   []byte{192, 168, 0, 1},
185
-		Mask: []byte{255, 255, 255, 0},
186
-	}
187
-	nameservers := []string{
188
-		"192.168.0.1/32",
189
-	}
190
-
191
-	if err := RegisterNetwork(network, nameservers); err != ErrNetworkOverlapsWithNameservers {
192
-		t.Fatalf("Expectecd error of %s got %s", ErrNetworkOverlapsWithNameservers, err)
193
-	}
194
-}
195
-
196
-func TestNetworkRange(t *testing.T) {
197
-	// Simple class C test
198
-	_, network, _ := net.ParseCIDR("192.168.0.1/24")
199
-	first, last := networkRange(network)
200
-	if !first.Equal(net.ParseIP("192.168.0.0")) {
201
-		t.Error(first.String())
202
-	}
203
-	if !last.Equal(net.ParseIP("192.168.0.255")) {
204
-		t.Error(last.String())
205
-	}
206
-	if size := networkSize(network.Mask); size != 256 {
207
-		t.Error(size)
208
-	}
209
-
210
-	// Class A test
211
-	_, network, _ = net.ParseCIDR("10.0.0.1/8")
212
-	first, last = networkRange(network)
213
-	if !first.Equal(net.ParseIP("10.0.0.0")) {
214
-		t.Error(first.String())
215
-	}
216
-	if !last.Equal(net.ParseIP("10.255.255.255")) {
217
-		t.Error(last.String())
218
-	}
219
-	if size := networkSize(network.Mask); size != 16777216 {
220
-		t.Error(size)
221
-	}
222
-
223
-	// Class A, random IP address
224
-	_, network, _ = net.ParseCIDR("10.1.2.3/8")
225
-	first, last = networkRange(network)
226
-	if !first.Equal(net.ParseIP("10.0.0.0")) {
227
-		t.Error(first.String())
228
-	}
229
-	if !last.Equal(net.ParseIP("10.255.255.255")) {
230
-		t.Error(last.String())
231
-	}
232
-
233
-	// 32bit mask
234
-	_, network, _ = net.ParseCIDR("10.1.2.3/32")
235
-	first, last = networkRange(network)
236
-	if !first.Equal(net.ParseIP("10.1.2.3")) {
237
-		t.Error(first.String())
238
-	}
239
-	if !last.Equal(net.ParseIP("10.1.2.3")) {
240
-		t.Error(last.String())
241
-	}
242
-	if size := networkSize(network.Mask); size != 1 {
243
-		t.Error(size)
244
-	}
245
-
246
-	// 31bit mask
247
-	_, network, _ = net.ParseCIDR("10.1.2.3/31")
248
-	first, last = networkRange(network)
249
-	if !first.Equal(net.ParseIP("10.1.2.2")) {
250
-		t.Error(first.String())
251
-	}
252
-	if !last.Equal(net.ParseIP("10.1.2.3")) {
253
-		t.Error(last.String())
254
-	}
255
-	if size := networkSize(network.Mask); size != 2 {
256
-		t.Error(size)
257
-	}
258
-
259
-	// 26bit mask
260
-	_, network, _ = net.ParseCIDR("10.1.2.3/26")
261
-	first, last = networkRange(network)
262
-	if !first.Equal(net.ParseIP("10.1.2.0")) {
263
-		t.Error(first.String())
264
-	}
265
-	if !last.Equal(net.ParseIP("10.1.2.63")) {
266
-		t.Error(last.String())
267
-	}
268
-	if size := networkSize(network.Mask); size != 64 {
269
-		t.Error(size)
270
-	}
271
-}
272
-
273 166
 func TestConversion(t *testing.T) {
274 167
 	ip := net.ParseIP("127.0.0.1")
275 168
 	i := ipToInt(&ip)
... ...
@@ -293,9 +111,6 @@ func TestIPAllocator(t *testing.T) {
293 293
 
294 294
 	gwIP, n, _ := net.ParseCIDR("127.0.0.1/29")
295 295
 	network := &net.IPNet{IP: gwIP, Mask: n.Mask}
296
-	if err := RegisterNetwork(network, nil); err != nil {
297
-		t.Fatal(err)
298
-	}
299 296
 	// Pool after initialisation (f = free, u = used)
300 297
 	// 2(f) - 3(f) - 4(f) - 5(f) - 6(f)
301 298
 	//  ↑
... ...
@@ -403,74 +218,3 @@ func assertIPEquals(t *testing.T, ip1, ip2 *net.IP) {
403 403
 		t.Fatalf("Expected IP %s, got %s", ip1, ip2)
404 404
 	}
405 405
 }
406
-
407
-func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
408
-	_, netX, _ := net.ParseCIDR(CIDRx)
409
-	_, netY, _ := net.ParseCIDR(CIDRy)
410
-	if !networkOverlaps(netX, netY) {
411
-		t.Errorf("%v and %v should overlap", netX, netY)
412
-	}
413
-}
414
-
415
-func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
416
-	_, netX, _ := net.ParseCIDR(CIDRx)
417
-	_, netY, _ := net.ParseCIDR(CIDRy)
418
-	if networkOverlaps(netX, netY) {
419
-		t.Errorf("%v and %v should not overlap", netX, netY)
420
-	}
421
-}
422
-
423
-func TestNetworkOverlaps(t *testing.T) {
424
-	//netY starts at same IP and ends within netX
425
-	AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
426
-	//netY starts within netX and ends at same IP
427
-	AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
428
-	//netY starts and ends within netX
429
-	AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
430
-	//netY starts at same IP and ends outside of netX
431
-	AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
432
-	//netY starts before and ends at same IP of netX
433
-	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
434
-	//netY starts before and ends outside of netX
435
-	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
436
-	//netY starts and ends before netX
437
-	AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
438
-	//netX starts and ends before netY
439
-	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
440
-}
441
-
442
-func TestCheckRouteOverlaps(t *testing.T) {
443
-	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"}
444
-
445
-	routes := []netlink.Route{}
446
-	for _, addr := range routesData {
447
-		_, netX, _ := net.ParseCIDR(addr)
448
-		routes = append(routes, netlink.Route{IPNet: netX})
449
-	}
450
-
451
-	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
452
-	if err := checkRouteOverlaps(routes, netX); err != nil {
453
-		t.Fatal(err)
454
-	}
455
-
456
-	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
457
-	if err := checkRouteOverlaps(routes, netX); err == nil {
458
-		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
459
-	}
460
-}
461
-
462
-func TestCheckNameserverOverlaps(t *testing.T) {
463
-	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
464
-
465
-	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
466
-
467
-	if err := checkNameserverOverlaps(nameservers, netX); err == nil {
468
-		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
469
-	}
470
-
471
-	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
472
-
473
-	if err := checkNameserverOverlaps(nameservers, netX); err != nil {
474
-		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
475
-	}
476
-}
... ...
@@ -1 +1,76 @@
1 1
 package networkdriver
2
+
3
+import (
4
+	"encoding/binary"
5
+	"errors"
6
+	"github.com/dotcloud/docker/pkg/netlink"
7
+	"net"
8
+)
9
+
10
+var (
11
+	ErrNetworkOverlapsWithNameservers = errors.New("requested network overlaps with nameserver")
12
+	ErrNetworkOverlaps                = errors.New("requested network overlaps with existing network")
13
+)
14
+
15
+func CheckNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error {
16
+	if len(nameservers) > 0 {
17
+		for _, ns := range nameservers {
18
+			_, nsNetwork, err := net.ParseCIDR(ns)
19
+			if err != nil {
20
+				return err
21
+			}
22
+			if NetworkOverlaps(toCheck, nsNetwork) {
23
+				return ErrNetworkOverlapsWithNameservers
24
+			}
25
+		}
26
+	}
27
+	return nil
28
+}
29
+
30
+func CheckRouteOverlaps(toCheck *net.IPNet) error {
31
+	networks, err := netlink.NetworkGetRoutes()
32
+	if err != nil {
33
+		return err
34
+	}
35
+
36
+	for _, network := range networks {
37
+		if network.IPNet != nil && NetworkOverlaps(toCheck, network.IPNet) {
38
+			return ErrNetworkOverlaps
39
+		}
40
+	}
41
+	return nil
42
+}
43
+
44
+// Detects overlap between one IPNet and another
45
+func NetworkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
46
+	if firstIP, _ := NetworkRange(netX); netY.Contains(firstIP) {
47
+		return true
48
+	}
49
+	if firstIP, _ := NetworkRange(netY); netX.Contains(firstIP) {
50
+		return true
51
+	}
52
+	return false
53
+}
54
+
55
+// Calculates the first and last IP addresses in an IPNet
56
+func NetworkRange(network *net.IPNet) (net.IP, net.IP) {
57
+	var (
58
+		netIP   = network.IP.To4()
59
+		firstIP = netIP.Mask(network.Mask)
60
+		lastIP  = net.IPv4(0, 0, 0, 0).To4()
61
+	)
62
+
63
+	for i := 0; i < len(lastIP); i++ {
64
+		lastIP[i] = netIP[i] | ^network.Mask[i]
65
+	}
66
+	return firstIP, lastIP
67
+}
68
+
69
+// Given a netmask, calculates the number of available hosts
70
+func NetworkSize(mask net.IPMask) int32 {
71
+	m := net.IPv4Mask(0, 0, 0, 0)
72
+	for i := 0; i < net.IPv4len; i++ {
73
+		m[i] = ^mask[i]
74
+	}
75
+	return int32(binary.BigEndian.Uint32(m)) + 1
76
+}
2 77
new file mode 100644
... ...
@@ -0,0 +1,183 @@
0
+package networkdriver
1
+
2
+import (
3
+	"github.com/dotcloud/docker/pkg/netlink"
4
+	"net"
5
+	"testing"
6
+)
7
+
8
+func TestNonOverlapingNameservers(t *testing.T) {
9
+	network := &net.IPNet{
10
+		IP:   []byte{192, 168, 0, 1},
11
+		Mask: []byte{255, 255, 255, 0},
12
+	}
13
+	nameservers := []string{
14
+		"127.0.0.1/32",
15
+	}
16
+
17
+	if err := CheckNameserverOverlaps(nameservers, network); err != nil {
18
+		t.Fatal(err)
19
+	}
20
+}
21
+
22
+func TestOverlapingNameservers(t *testing.T) {
23
+	network := &net.IPNet{
24
+		IP:   []byte{192, 168, 0, 1},
25
+		Mask: []byte{255, 255, 255, 0},
26
+	}
27
+	nameservers := []string{
28
+		"192.168.0.1/32",
29
+	}
30
+
31
+	if err := CheckNameserverOverlaps(nameservers, network); err == nil {
32
+		t.Fatalf("Expected error %s got %s", ErrNetworkOverlapsWithNameservers, err)
33
+	}
34
+}
35
+
36
+func TestCheckRouteOverlaps(t *testing.T) {
37
+	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"}
38
+
39
+	routes := []netlink.Route{}
40
+	for _, addr := range routesData {
41
+		_, netX, _ := net.ParseCIDR(addr)
42
+		routes = append(routes, netlink.Route{IPNet: netX})
43
+	}
44
+
45
+	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
46
+	if err := CheckRouteOverlaps(netX); err != nil {
47
+		t.Fatal(err)
48
+	}
49
+
50
+	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
51
+	if err := CheckRouteOverlaps(netX); err == nil {
52
+		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
53
+	}
54
+}
55
+
56
+func TestCheckNameserverOverlaps(t *testing.T) {
57
+	nameservers := []string{"10.0.2.3/32", "192.168.102.1/32"}
58
+
59
+	_, netX, _ := net.ParseCIDR("10.0.2.3/32")
60
+
61
+	if err := CheckNameserverOverlaps(nameservers, netX); err == nil {
62
+		t.Fatalf("%s should overlap 10.0.2.3/32 but doesn't", netX)
63
+	}
64
+
65
+	_, netX, _ = net.ParseCIDR("192.168.102.2/32")
66
+
67
+	if err := CheckNameserverOverlaps(nameservers, netX); err != nil {
68
+		t.Fatalf("%s should not overlap %v but it does", netX, nameservers)
69
+	}
70
+}
71
+
72
+func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
73
+	_, netX, _ := net.ParseCIDR(CIDRx)
74
+	_, netY, _ := net.ParseCIDR(CIDRy)
75
+	if !NetworkOverlaps(netX, netY) {
76
+		t.Errorf("%v and %v should overlap", netX, netY)
77
+	}
78
+}
79
+
80
+func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
81
+	_, netX, _ := net.ParseCIDR(CIDRx)
82
+	_, netY, _ := net.ParseCIDR(CIDRy)
83
+	if NetworkOverlaps(netX, netY) {
84
+		t.Errorf("%v and %v should not overlap", netX, netY)
85
+	}
86
+}
87
+
88
+func TestNetworkOverlaps(t *testing.T) {
89
+	//netY starts at same IP and ends within netX
90
+	AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
91
+	//netY starts within netX and ends at same IP
92
+	AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
93
+	//netY starts and ends within netX
94
+	AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
95
+	//netY starts at same IP and ends outside of netX
96
+	AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
97
+	//netY starts before and ends at same IP of netX
98
+	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
99
+	//netY starts before and ends outside of netX
100
+	AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
101
+	//netY starts and ends before netX
102
+	AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
103
+	//netX starts and ends before netY
104
+	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
105
+}
106
+
107
+func TestNetworkRange(t *testing.T) {
108
+	// Simple class C test
109
+	_, network, _ := net.ParseCIDR("192.168.0.1/24")
110
+	first, last := NetworkRange(network)
111
+	if !first.Equal(net.ParseIP("192.168.0.0")) {
112
+		t.Error(first.String())
113
+	}
114
+	if !last.Equal(net.ParseIP("192.168.0.255")) {
115
+		t.Error(last.String())
116
+	}
117
+	if size := NetworkSize(network.Mask); size != 256 {
118
+		t.Error(size)
119
+	}
120
+
121
+	// Class A test
122
+	_, network, _ = net.ParseCIDR("10.0.0.1/8")
123
+	first, last = NetworkRange(network)
124
+	if !first.Equal(net.ParseIP("10.0.0.0")) {
125
+		t.Error(first.String())
126
+	}
127
+	if !last.Equal(net.ParseIP("10.255.255.255")) {
128
+		t.Error(last.String())
129
+	}
130
+	if size := NetworkSize(network.Mask); size != 16777216 {
131
+		t.Error(size)
132
+	}
133
+
134
+	// Class A, random IP address
135
+	_, network, _ = net.ParseCIDR("10.1.2.3/8")
136
+	first, last = NetworkRange(network)
137
+	if !first.Equal(net.ParseIP("10.0.0.0")) {
138
+		t.Error(first.String())
139
+	}
140
+	if !last.Equal(net.ParseIP("10.255.255.255")) {
141
+		t.Error(last.String())
142
+	}
143
+
144
+	// 32bit mask
145
+	_, network, _ = net.ParseCIDR("10.1.2.3/32")
146
+	first, last = NetworkRange(network)
147
+	if !first.Equal(net.ParseIP("10.1.2.3")) {
148
+		t.Error(first.String())
149
+	}
150
+	if !last.Equal(net.ParseIP("10.1.2.3")) {
151
+		t.Error(last.String())
152
+	}
153
+	if size := NetworkSize(network.Mask); size != 1 {
154
+		t.Error(size)
155
+	}
156
+
157
+	// 31bit mask
158
+	_, network, _ = net.ParseCIDR("10.1.2.3/31")
159
+	first, last = NetworkRange(network)
160
+	if !first.Equal(net.ParseIP("10.1.2.2")) {
161
+		t.Error(first.String())
162
+	}
163
+	if !last.Equal(net.ParseIP("10.1.2.3")) {
164
+		t.Error(last.String())
165
+	}
166
+	if size := NetworkSize(network.Mask); size != 2 {
167
+		t.Error(size)
168
+	}
169
+
170
+	// 26bit mask
171
+	_, network, _ = net.ParseCIDR("10.1.2.3/26")
172
+	first, last = NetworkRange(network)
173
+	if !first.Equal(net.ParseIP("10.1.2.0")) {
174
+		t.Error(first.String())
175
+	}
176
+	if !last.Equal(net.ParseIP("10.1.2.63")) {
177
+		t.Error(last.String())
178
+	}
179
+	if size := NetworkSize(network.Mask); size != 64 {
180
+		t.Error(size)
181
+	}
182
+}