Browse code

Vendor libnetwork v0.6.0-rc3

- Fixes docker/docker#19576
- Fixed embedded DNS to listen in TCP as well
- Fixed a race-condition in IPAM to choose non-overlapping subnet for concurrent requests

Signed-off-by: Madhu Venugopal <madhu@docker.com>

Madhu Venugopal authored on 2016/01/26 06:22:47
Showing 8 changed files
... ...
@@ -27,7 +27,7 @@ clone git github.com/RackSec/srslog 6eb773f331e46fbba8eecb8e794e635e75fc04de
27 27
 clone git github.com/imdario/mergo 0.2.1
28 28
 
29 29
 #get libnetwork packages
30
-clone git github.com/docker/libnetwork v0.6.0-rc2
30
+clone git github.com/docker/libnetwork v0.6.0-rc3
31 31
 clone git github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
32 32
 clone git github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
33 33
 clone git github.com/hashicorp/memberlist 9a1e242e454d2443df330bdd51a436d5a9058fc4
... ...
@@ -1,5 +1,10 @@
1 1
 # Changelog
2 2
 
3
+## 0.6.0-rc3 (2016-01-25)
4
+- Fixes docker/docker#19576
5
+- Fixed embedded DNS to listen in TCP as well
6
+- Fixed a race-condition in IPAM to choose non-overlapping subnet for concurrent requests
7
+
3 8
 ## 0.6.0-rc2 (2016-01-21)
4 9
 - Fixes docker/docker#19376
5 10
 - Fixes docker/docker#15819
... ...
@@ -63,7 +63,7 @@ run-tests:
63 63
 	    if ls $$dir/*.go &> /dev/null; then \
64 64
 		pushd . &> /dev/null ; \
65 65
 		cd $$dir ; \
66
-		$(shell which godep) go test ${INSIDECONTAINER} -test.parallel 3 -test.v -covermode=count -coverprofile=./profile.tmp ; \
66
+		$(shell which godep) go test ${INSIDECONTAINER} -test.parallel 5 -test.v -covermode=count -coverprofile=./profile.tmp ; \
67 67
 		ret=$$? ;\
68 68
 		if [ $$ret -ne 0 ]; then exit $$ret; fi ;\
69 69
 		popd &> /dev/null; \
... ...
@@ -465,7 +465,7 @@ func (ep *endpoint) sbJoin(sbox Sandbox, options ...EndpointOption) error {
465 465
 	if sb.needDefaultGW() {
466 466
 		return sb.setupDefaultGW(ep)
467 467
 	}
468
-	return sb.clearDefaultGW()
468
+	return nil
469 469
 }
470 470
 
471 471
 func (ep *endpoint) rename(name string) error {
... ...
@@ -597,15 +597,7 @@ func (ep *endpoint) sbLeave(sbox Sandbox, force bool, options ...EndpointOption)
597 597
 	}
598 598
 
599 599
 	sb.deleteHostsEntries(n.getSvcRecords(ep))
600
-
601
-	if !sb.inDelete && sb.needDefaultGW() {
602
-		ep := sb.getEPwithoutGateway()
603
-		if ep == nil {
604
-			return fmt.Errorf("endpoint without GW expected, but not found")
605
-		}
606
-		return sb.setupDefaultGW(ep)
607
-	}
608
-	return sb.clearDefaultGW()
600
+	return nil
609 601
 }
610 602
 
611 603
 func (n *network) validateForceDelete(locator string) error {
... ...
@@ -145,12 +145,12 @@ func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) {
145 145
 // RequestPool returns an address pool along with its unique id.
146 146
 func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) {
147 147
 	log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6)
148
-	k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6)
148
+retry:
149
+	k, nw, ipr, pdf, err := a.parsePoolRequest(addressSpace, pool, subPool, v6)
149 150
 	if err != nil {
150 151
 		return "", nil, nil, types.InternalErrorf("failed to parse pool request for address space %q pool %q subpool %q: %v", addressSpace, pool, subPool, err)
151 152
 	}
152 153
 
153
-retry:
154 154
 	if err := a.refresh(addressSpace); err != nil {
155 155
 		return "", nil, nil, err
156 156
 	}
... ...
@@ -160,8 +160,12 @@ retry:
160 160
 		return "", nil, nil, err
161 161
 	}
162 162
 
163
-	insert, err := aSpace.updatePoolDBOnAdd(*k, nw, ipr)
163
+	insert, err := aSpace.updatePoolDBOnAdd(*k, nw, ipr, pdf)
164 164
 	if err != nil {
165
+		if _, ok := err.(types.MaskableError); ok {
166
+			log.Debugf("Retrying predefined pool search: %v", err)
167
+			goto retry
168
+		}
165 169
 		return "", nil, nil, err
166 170
 	}
167 171
 
... ...
@@ -221,38 +225,39 @@ func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) {
221 221
 	return aSpace, nil
222 222
 }
223 223
 
224
-func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) {
224
+func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, bool, error) {
225 225
 	var (
226 226
 		nw  *net.IPNet
227 227
 		ipr *AddressRange
228 228
 		err error
229
+		pdf = false
229 230
 	)
230 231
 
231 232
 	if addressSpace == "" {
232
-		return nil, nil, nil, ipamapi.ErrInvalidAddressSpace
233
+		return nil, nil, nil, false, ipamapi.ErrInvalidAddressSpace
233 234
 	}
234 235
 
235 236
 	if pool == "" && subPool != "" {
236
-		return nil, nil, nil, ipamapi.ErrInvalidSubPool
237
+		return nil, nil, nil, false, ipamapi.ErrInvalidSubPool
237 238
 	}
238 239
 
239 240
 	if pool != "" {
240 241
 		if _, nw, err = net.ParseCIDR(pool); err != nil {
241
-			return nil, nil, nil, ipamapi.ErrInvalidPool
242
+			return nil, nil, nil, false, ipamapi.ErrInvalidPool
242 243
 		}
243 244
 		if subPool != "" {
244 245
 			if ipr, err = getAddressRange(subPool, nw); err != nil {
245
-				return nil, nil, nil, err
246
+				return nil, nil, nil, false, err
246 247
 			}
247 248
 		}
248 249
 	} else {
249 250
 		if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil {
250
-			return nil, nil, nil, err
251
+			return nil, nil, nil, false, err
251 252
 		}
252
-
253
+		pdf = true
253 254
 	}
254 255
 
255
-	return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil
256
+	return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, pdf, nil
256 257
 }
257 258
 
258 259
 func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
... ...
@@ -257,12 +257,15 @@ func (aSpace *addrSpace) New() datastore.KVObject {
257 257
 	}
258 258
 }
259 259
 
260
-func (aSpace *addrSpace) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange) (func() error, error) {
260
+func (aSpace *addrSpace) updatePoolDBOnAdd(k SubnetKey, nw *net.IPNet, ipr *AddressRange, pdf bool) (func() error, error) {
261 261
 	aSpace.Lock()
262 262
 	defer aSpace.Unlock()
263 263
 
264 264
 	// Check if already allocated
265 265
 	if p, ok := aSpace.subnets[k]; ok {
266
+		if pdf {
267
+			return nil, types.InternalMaskableErrorf("predefined pool %s is already reserved", nw)
268
+		}
266 269
 		aSpace.incRefCount(p, 1)
267 270
 		return func() error { return nil }, nil
268 271
 	}
... ...
@@ -41,11 +41,13 @@ const (
41 41
 
42 42
 // resolver implements the Resolver interface
43 43
 type resolver struct {
44
-	sb     *sandbox
45
-	extDNS []string
46
-	server *dns.Server
47
-	conn   *net.UDPConn
48
-	err    error
44
+	sb        *sandbox
45
+	extDNS    []string
46
+	server    *dns.Server
47
+	conn      *net.UDPConn
48
+	tcpServer *dns.Server
49
+	tcpListen *net.TCPListener
50
+	err       error
49 51
 }
50 52
 
51 53
 // NewResolver creates a new instance of the Resolver
... ...
@@ -60,6 +62,7 @@ func (r *resolver) SetupFunc() func() {
60 60
 	return (func() {
61 61
 		var err error
62 62
 
63
+		// DNS operates primarily on UDP
63 64
 		addr := &net.UDPAddr{
64 65
 			IP: net.ParseIP(resolverIP),
65 66
 		}
... ...
@@ -72,9 +75,23 @@ func (r *resolver) SetupFunc() func() {
72 72
 		laddr := r.conn.LocalAddr()
73 73
 		_, ipPort, _ := net.SplitHostPort(laddr.String())
74 74
 
75
+		// Listen on a TCP as well
76
+		tcpaddr := &net.TCPAddr{
77
+			IP: net.ParseIP(resolverIP),
78
+		}
79
+
80
+		r.tcpListen, err = net.ListenTCP("tcp", tcpaddr)
81
+		if err != nil {
82
+			r.err = fmt.Errorf("error in opening name TCP server socket %v", err)
83
+			return
84
+		}
85
+		ltcpaddr := r.tcpListen.Addr()
86
+		_, tcpPort, _ := net.SplitHostPort(ltcpaddr.String())
75 87
 		rules := [][]string{
76 88
 			{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "udp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", laddr.String()},
77 89
 			{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "udp", "--sport", ipPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
90
+			{"-t", "nat", "-A", "OUTPUT", "-d", resolverIP, "-p", "tcp", "--dport", dnsPort, "-j", "DNAT", "--to-destination", ltcpaddr.String()},
91
+			{"-t", "nat", "-A", "POSTROUTING", "-s", resolverIP, "-p", "tcp", "--sport", tcpPort, "-j", "SNAT", "--to-source", ":" + dnsPort},
78 92
 		}
79 93
 
80 94
 		for _, rule := range rules {
... ...
@@ -97,6 +114,12 @@ func (r *resolver) Start() error {
97 97
 	go func() {
98 98
 		s.ActivateAndServe()
99 99
 	}()
100
+
101
+	tcpServer := &dns.Server{Handler: r, Listener: r.tcpListen}
102
+	r.tcpServer = tcpServer
103
+	go func() {
104
+		tcpServer.ActivateAndServe()
105
+	}()
100 106
 	return nil
101 107
 }
102 108
 
... ...
@@ -104,7 +127,11 @@ func (r *resolver) Stop() {
104 104
 	if r.server != nil {
105 105
 		r.server.Shutdown()
106 106
 	}
107
+	if r.tcpServer != nil {
108
+		r.tcpServer.Shutdown()
109
+	}
107 110
 	r.conn = nil
111
+	r.tcpServer = nil
108 112
 	r.err = fmt.Errorf("setup not done yet")
109 113
 }
110 114
 
... ...
@@ -195,9 +222,9 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
195 195
 			num = len(r.extDNS)
196 196
 		}
197 197
 		for i := 0; i < num; i++ {
198
-			log.Debugf("Querying ext dns %s for %s[%d]", r.extDNS[i], name, query.Question[0].Qtype)
198
+			log.Debugf("Querying ext dns %s:%s for %s[%d]", w.LocalAddr().Network(), r.extDNS[i], name, query.Question[0].Qtype)
199 199
 
200
-			c := &dns.Client{Net: "udp"}
200
+			c := &dns.Client{Net: w.LocalAddr().Network()}
201 201
 			addr := fmt.Sprintf("%s:%d", r.extDNS[i], 53)
202 202
 
203 203
 			resp, _, err = c.Exchange(query, addr)
... ...
@@ -186,12 +186,6 @@ func (sb *sandbox) delete(force bool) error {
186 186
 	// Detach from all endpoints
187 187
 	retain := false
188 188
 	for _, ep := range sb.getConnectedEndpoints() {
189
-		// endpoint in the Gateway network will be cleaned up
190
-		// when when sandbox no longer needs external connectivity
191
-		if ep.endpointInGWNetwork() {
192
-			continue
193
-		}
194
-
195 189
 		// Retain the sanbdox if we can't obtain the network from store.
196 190
 		if _, err := c.getNetworkFromStore(ep.getNetwork().ID()); err != nil {
197 191
 			retain = true