Browse code

bump libnetwork to b0186632

Bump libnetwork to b0186632522c68f4e1222c4f6d7dbe518882024f. This
includes the following changes:
* Dockerize protocol buffer generation and update (78d9390a..e12dd44c)
* Use new plugin interfaces provided by plugin pkg (be94e134)
* Improve linux load-balancing scalability (5111c24e..366b9110)

Signed-off-by: Chris Telfer <ctelfer@docker.com>

Chris Telfer authored on 2018/06/06 23:38:04
Showing 20 changed files
... ...
@@ -3,7 +3,7 @@
3 3
 # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When
4 4
 # updating the binary version, consider updating github.com/docker/libnetwork
5 5
 # in vendor.conf accordingly
6
-LIBNETWORK_COMMIT=430c00a6a6b3dfdd774f21e1abd4ad6b0216c629
6
+LIBNETWORK_COMMIT=b0186632522c68f4e1222c4f6d7dbe518882024f
7 7
 
8 8
 install_proxy() {
9 9
 	case "$1" in
... ...
@@ -37,7 +37,7 @@ github.com/mitchellh/hashstructure 2bca23e0e452137f789efbc8610126fd8b94f73b
37 37
 #get libnetwork packages
38 38
 
39 39
 # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy accordingly
40
-github.com/docker/libnetwork 430c00a6a6b3dfdd774f21e1abd4ad6b0216c629
40
+github.com/docker/libnetwork b0186632522c68f4e1222c4f6d7dbe518882024f
41 41
 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
42 42
 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80
43 43
 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec
... ...
@@ -871,7 +871,7 @@ addToStore:
871 871
 		}
872 872
 	}()
873 873
 
874
-	if len(network.loadBalancerIP) != 0 {
874
+	if network.hasLoadBalancerEndpoint() {
875 875
 		if err = network.createLoadBalancerSandbox(); err != nil {
876 876
 			return nil, err
877 877
 		}
... ...
@@ -49,9 +49,11 @@ func (sb *sandbox) setupDefaultGW() error {
49 49
 
50 50
 	createOptions := []EndpointOption{CreateOptionAnonymous()}
51 51
 
52
-	eplen := gwEPlen
53
-	if len(sb.containerID) < gwEPlen {
54
-		eplen = len(sb.containerID)
52
+	var gwName string
53
+	if len(sb.containerID) <= gwEPlen {
54
+		gwName = "gateway_" + sb.containerID
55
+	} else {
56
+		gwName = "gateway_" + sb.id[:gwEPlen]
55 57
 	}
56 58
 
57 59
 	sbLabels := sb.Labels()
... ...
@@ -69,7 +71,7 @@ func (sb *sandbox) setupDefaultGW() error {
69 69
 		createOptions = append(createOptions, epOption)
70 70
 	}
71 71
 
72
-	newEp, err := n.CreateEndpoint("gateway_"+sb.containerID[0:eplen], createOptions...)
72
+	newEp, err := n.CreateEndpoint(gwName, createOptions...)
73 73
 	if err != nil {
74 74
 		return fmt.Errorf("container %s: endpoint create on GW Network failed: %v", sb.containerID, err)
75 75
 	}
... ...
@@ -1,12 +1,11 @@
1
-// Code generated by protoc-gen-gogo.
2
-// source: overlay.proto
3
-// DO NOT EDIT!
1
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
2
+// source: drivers/overlay/overlay.proto
4 3
 
5 4
 /*
6 5
 	Package overlay is a generated protocol buffer package.
7 6
 
8 7
 	It is generated from these files:
9
-		overlay.proto
8
+		drivers/overlay/overlay.proto
10 9
 
11 10
 	It has these top-level messages:
12 11
 		PeerRecord
... ...
@@ -19,9 +18,6 @@ import math "math"
19 19
 import _ "github.com/gogo/protobuf/gogoproto"
20 20
 
21 21
 import strings "strings"
22
-import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
23
-import sort "sort"
24
-import strconv "strconv"
25 22
 import reflect "reflect"
26 23
 
27 24
 import io "io"
... ...
@@ -33,7 +29,9 @@ var _ = math.Inf
33 33
 
34 34
 // This is a compile-time assertion to ensure that this generated file
35 35
 // is compatible with the proto package it is being compiled against.
36
-const _ = proto.GoGoProtoPackageIsVersion1
36
+// A compilation error at this line likely means your copy of the
37
+// proto package needs to be updated.
38
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
37 39
 
38 40
 // PeerRecord defines the information corresponding to a peer
39 41
 // container in the overlay network.
... ...
@@ -54,6 +52,27 @@ func (m *PeerRecord) Reset()                    { *m = PeerRecord{} }
54 54
 func (*PeerRecord) ProtoMessage()               {}
55 55
 func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
56 56
 
57
+func (m *PeerRecord) GetEndpointIP() string {
58
+	if m != nil {
59
+		return m.EndpointIP
60
+	}
61
+	return ""
62
+}
63
+
64
+func (m *PeerRecord) GetEndpointMAC() string {
65
+	if m != nil {
66
+		return m.EndpointMAC
67
+	}
68
+	return ""
69
+}
70
+
71
+func (m *PeerRecord) GetTunnelEndpointIP() string {
72
+	if m != nil {
73
+		return m.TunnelEndpointIP
74
+	}
75
+	return ""
76
+}
77
+
57 78
 func init() {
58 79
 	proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord")
59 80
 }
... ...
@@ -77,84 +96,49 @@ func valueToGoStringOverlay(v interface{}, typ string) string {
77 77
 	pv := reflect.Indirect(rv).Interface()
78 78
 	return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
79 79
 }
80
-func extensionToGoStringOverlay(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
81
-	if e == nil {
82
-		return "nil"
83
-	}
84
-	s := "map[int32]proto.Extension{"
85
-	keys := make([]int, 0, len(e))
86
-	for k := range e {
87
-		keys = append(keys, int(k))
88
-	}
89
-	sort.Ints(keys)
90
-	ss := []string{}
91
-	for _, k := range keys {
92
-		ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
93
-	}
94
-	s += strings.Join(ss, ",") + "}"
95
-	return s
96
-}
97
-func (m *PeerRecord) Marshal() (data []byte, err error) {
80
+func (m *PeerRecord) Marshal() (dAtA []byte, err error) {
98 81
 	size := m.Size()
99
-	data = make([]byte, size)
100
-	n, err := m.MarshalTo(data)
82
+	dAtA = make([]byte, size)
83
+	n, err := m.MarshalTo(dAtA)
101 84
 	if err != nil {
102 85
 		return nil, err
103 86
 	}
104
-	return data[:n], nil
87
+	return dAtA[:n], nil
105 88
 }
106 89
 
107
-func (m *PeerRecord) MarshalTo(data []byte) (int, error) {
90
+func (m *PeerRecord) MarshalTo(dAtA []byte) (int, error) {
108 91
 	var i int
109 92
 	_ = i
110 93
 	var l int
111 94
 	_ = l
112 95
 	if len(m.EndpointIP) > 0 {
113
-		data[i] = 0xa
96
+		dAtA[i] = 0xa
114 97
 		i++
115
-		i = encodeVarintOverlay(data, i, uint64(len(m.EndpointIP)))
116
-		i += copy(data[i:], m.EndpointIP)
98
+		i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointIP)))
99
+		i += copy(dAtA[i:], m.EndpointIP)
117 100
 	}
118 101
 	if len(m.EndpointMAC) > 0 {
119
-		data[i] = 0x12
102
+		dAtA[i] = 0x12
120 103
 		i++
121
-		i = encodeVarintOverlay(data, i, uint64(len(m.EndpointMAC)))
122
-		i += copy(data[i:], m.EndpointMAC)
104
+		i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointMAC)))
105
+		i += copy(dAtA[i:], m.EndpointMAC)
123 106
 	}
124 107
 	if len(m.TunnelEndpointIP) > 0 {
125
-		data[i] = 0x1a
108
+		dAtA[i] = 0x1a
126 109
 		i++
127
-		i = encodeVarintOverlay(data, i, uint64(len(m.TunnelEndpointIP)))
128
-		i += copy(data[i:], m.TunnelEndpointIP)
110
+		i = encodeVarintOverlay(dAtA, i, uint64(len(m.TunnelEndpointIP)))
111
+		i += copy(dAtA[i:], m.TunnelEndpointIP)
129 112
 	}
130 113
 	return i, nil
131 114
 }
132 115
 
133
-func encodeFixed64Overlay(data []byte, offset int, v uint64) int {
134
-	data[offset] = uint8(v)
135
-	data[offset+1] = uint8(v >> 8)
136
-	data[offset+2] = uint8(v >> 16)
137
-	data[offset+3] = uint8(v >> 24)
138
-	data[offset+4] = uint8(v >> 32)
139
-	data[offset+5] = uint8(v >> 40)
140
-	data[offset+6] = uint8(v >> 48)
141
-	data[offset+7] = uint8(v >> 56)
142
-	return offset + 8
143
-}
144
-func encodeFixed32Overlay(data []byte, offset int, v uint32) int {
145
-	data[offset] = uint8(v)
146
-	data[offset+1] = uint8(v >> 8)
147
-	data[offset+2] = uint8(v >> 16)
148
-	data[offset+3] = uint8(v >> 24)
149
-	return offset + 4
150
-}
151
-func encodeVarintOverlay(data []byte, offset int, v uint64) int {
116
+func encodeVarintOverlay(dAtA []byte, offset int, v uint64) int {
152 117
 	for v >= 1<<7 {
153
-		data[offset] = uint8(v&0x7f | 0x80)
118
+		dAtA[offset] = uint8(v&0x7f | 0x80)
154 119
 		v >>= 7
155 120
 		offset++
156 121
 	}
157
-	data[offset] = uint8(v)
122
+	dAtA[offset] = uint8(v)
158 123
 	return offset + 1
159 124
 }
160 125
 func (m *PeerRecord) Size() (n int) {
... ...
@@ -208,8 +192,8 @@ func valueToStringOverlay(v interface{}) string {
208 208
 	pv := reflect.Indirect(rv).Interface()
209 209
 	return fmt.Sprintf("*%v", pv)
210 210
 }
211
-func (m *PeerRecord) Unmarshal(data []byte) error {
212
-	l := len(data)
211
+func (m *PeerRecord) Unmarshal(dAtA []byte) error {
212
+	l := len(dAtA)
213 213
 	iNdEx := 0
214 214
 	for iNdEx < l {
215 215
 		preIndex := iNdEx
... ...
@@ -221,7 +205,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
221 221
 			if iNdEx >= l {
222 222
 				return io.ErrUnexpectedEOF
223 223
 			}
224
-			b := data[iNdEx]
224
+			b := dAtA[iNdEx]
225 225
 			iNdEx++
226 226
 			wire |= (uint64(b) & 0x7F) << shift
227 227
 			if b < 0x80 {
... ...
@@ -249,7 +233,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
249 249
 				if iNdEx >= l {
250 250
 					return io.ErrUnexpectedEOF
251 251
 				}
252
-				b := data[iNdEx]
252
+				b := dAtA[iNdEx]
253 253
 				iNdEx++
254 254
 				stringLen |= (uint64(b) & 0x7F) << shift
255 255
 				if b < 0x80 {
... ...
@@ -264,7 +248,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
264 264
 			if postIndex > l {
265 265
 				return io.ErrUnexpectedEOF
266 266
 			}
267
-			m.EndpointIP = string(data[iNdEx:postIndex])
267
+			m.EndpointIP = string(dAtA[iNdEx:postIndex])
268 268
 			iNdEx = postIndex
269 269
 		case 2:
270 270
 			if wireType != 2 {
... ...
@@ -278,7 +262,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
278 278
 				if iNdEx >= l {
279 279
 					return io.ErrUnexpectedEOF
280 280
 				}
281
-				b := data[iNdEx]
281
+				b := dAtA[iNdEx]
282 282
 				iNdEx++
283 283
 				stringLen |= (uint64(b) & 0x7F) << shift
284 284
 				if b < 0x80 {
... ...
@@ -293,7 +277,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
293 293
 			if postIndex > l {
294 294
 				return io.ErrUnexpectedEOF
295 295
 			}
296
-			m.EndpointMAC = string(data[iNdEx:postIndex])
296
+			m.EndpointMAC = string(dAtA[iNdEx:postIndex])
297 297
 			iNdEx = postIndex
298 298
 		case 3:
299 299
 			if wireType != 2 {
... ...
@@ -307,7 +291,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
307 307
 				if iNdEx >= l {
308 308
 					return io.ErrUnexpectedEOF
309 309
 				}
310
-				b := data[iNdEx]
310
+				b := dAtA[iNdEx]
311 311
 				iNdEx++
312 312
 				stringLen |= (uint64(b) & 0x7F) << shift
313 313
 				if b < 0x80 {
... ...
@@ -322,11 +306,11 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
322 322
 			if postIndex > l {
323 323
 				return io.ErrUnexpectedEOF
324 324
 			}
325
-			m.TunnelEndpointIP = string(data[iNdEx:postIndex])
325
+			m.TunnelEndpointIP = string(dAtA[iNdEx:postIndex])
326 326
 			iNdEx = postIndex
327 327
 		default:
328 328
 			iNdEx = preIndex
329
-			skippy, err := skipOverlay(data[iNdEx:])
329
+			skippy, err := skipOverlay(dAtA[iNdEx:])
330 330
 			if err != nil {
331 331
 				return err
332 332
 			}
... ...
@@ -345,8 +329,8 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
345 345
 	}
346 346
 	return nil
347 347
 }
348
-func skipOverlay(data []byte) (n int, err error) {
349
-	l := len(data)
348
+func skipOverlay(dAtA []byte) (n int, err error) {
349
+	l := len(dAtA)
350 350
 	iNdEx := 0
351 351
 	for iNdEx < l {
352 352
 		var wire uint64
... ...
@@ -357,7 +341,7 @@ func skipOverlay(data []byte) (n int, err error) {
357 357
 			if iNdEx >= l {
358 358
 				return 0, io.ErrUnexpectedEOF
359 359
 			}
360
-			b := data[iNdEx]
360
+			b := dAtA[iNdEx]
361 361
 			iNdEx++
362 362
 			wire |= (uint64(b) & 0x7F) << shift
363 363
 			if b < 0x80 {
... ...
@@ -375,7 +359,7 @@ func skipOverlay(data []byte) (n int, err error) {
375 375
 					return 0, io.ErrUnexpectedEOF
376 376
 				}
377 377
 				iNdEx++
378
-				if data[iNdEx-1] < 0x80 {
378
+				if dAtA[iNdEx-1] < 0x80 {
379 379
 					break
380 380
 				}
381 381
 			}
... ...
@@ -392,7 +376,7 @@ func skipOverlay(data []byte) (n int, err error) {
392 392
 				if iNdEx >= l {
393 393
 					return 0, io.ErrUnexpectedEOF
394 394
 				}
395
-				b := data[iNdEx]
395
+				b := dAtA[iNdEx]
396 396
 				iNdEx++
397 397
 				length |= (int(b) & 0x7F) << shift
398 398
 				if b < 0x80 {
... ...
@@ -415,7 +399,7 @@ func skipOverlay(data []byte) (n int, err error) {
415 415
 					if iNdEx >= l {
416 416
 						return 0, io.ErrUnexpectedEOF
417 417
 					}
418
-					b := data[iNdEx]
418
+					b := dAtA[iNdEx]
419 419
 					iNdEx++
420 420
 					innerWire |= (uint64(b) & 0x7F) << shift
421 421
 					if b < 0x80 {
... ...
@@ -426,7 +410,7 @@ func skipOverlay(data []byte) (n int, err error) {
426 426
 				if innerWireType == 4 {
427 427
 					break
428 428
 				}
429
-				next, err := skipOverlay(data[start:])
429
+				next, err := skipOverlay(dAtA[start:])
430 430
 				if err != nil {
431 431
 					return 0, err
432 432
 				}
... ...
@@ -450,19 +434,22 @@ var (
450 450
 	ErrIntOverflowOverlay   = fmt.Errorf("proto: integer overflow")
451 451
 )
452 452
 
453
+func init() { proto.RegisterFile("drivers/overlay/overlay.proto", fileDescriptorOverlay) }
454
+
453 455
 var fileDescriptorOverlay = []byte{
454
-	// 195 bytes of a gzipped FileDescriptorProto
455
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x2f, 0x4b, 0x2d,
456
-	0xca, 0x49, 0xac, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x44, 0xd2,
457
-	0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x69, 0x2b, 0x23, 0x17, 0x57, 0x40,
458
-	0x6a, 0x6a, 0x51, 0x50, 0x6a, 0x72, 0x7e, 0x51, 0x8a, 0x90, 0x3e, 0x17, 0x77, 0x6a, 0x5e, 0x4a,
459
-	0x41, 0x7e, 0x66, 0x5e, 0x49, 0x7c, 0x66, 0x81, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x13, 0xdf,
460
-	0xa3, 0x7b, 0xf2, 0x5c, 0xae, 0x50, 0x61, 0xcf, 0x80, 0x20, 0x2e, 0x98, 0x12, 0xcf, 0x02, 0x21,
461
-	0x23, 0x2e, 0x1e, 0xb8, 0x86, 0xdc, 0xc4, 0x64, 0x09, 0x26, 0xb0, 0x0e, 0x7e, 0xa0, 0x0e, 0x6e,
462
-	0x98, 0x0e, 0x5f, 0x47, 0xe7, 0x20, 0xb8, 0xa9, 0xbe, 0x89, 0xc9, 0x42, 0x4e, 0x5c, 0x42, 0x25,
463
-	0xa5, 0x79, 0x79, 0xa9, 0x39, 0xf1, 0xc8, 0x76, 0x31, 0x83, 0x75, 0x8a, 0x00, 0x75, 0x0a, 0x84,
464
-	0x80, 0x65, 0x91, 0x6c, 0x14, 0x28, 0x41, 0x15, 0x29, 0x70, 0x92, 0xb8, 0xf1, 0x50, 0x8e, 0xe1,
465
-	0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x80, 0xf8, 0x02, 0x10, 0x3f, 0x00, 0xe2,
466
-	0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xd7, 0x7d, 0x7d, 0x08,
467
-	0x01, 0x00, 0x00,
456
+	// 212 bytes of a gzipped FileDescriptorProto
457
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4d, 0x29, 0xca, 0x2c,
458
+	0x4b, 0x2d, 0x2a, 0xd6, 0xcf, 0x2f, 0x4b, 0x2d, 0xca, 0x49, 0xac, 0x84, 0xd1, 0x7a, 0x05, 0x45,
459
+	0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0xae, 0x94, 0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x58, 0x4c, 0x1f,
460
+	0xc4, 0x82, 0x48, 0x2b, 0x6d, 0x65, 0xe4, 0xe2, 0x0a, 0x48, 0x4d, 0x2d, 0x0a, 0x4a, 0x4d, 0xce,
461
+	0x2f, 0x4a, 0x11, 0xd2, 0xe7, 0xe2, 0x4e, 0xcd, 0x4b, 0x29, 0xc8, 0xcf, 0xcc, 0x2b, 0x89, 0xcf,
462
+	0x2c, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x74, 0xe2, 0x7b, 0x74, 0x4f, 0x9e, 0xcb, 0x15, 0x2a,
463
+	0xec, 0x19, 0x10, 0xc4, 0x05, 0x53, 0xe2, 0x59, 0x20, 0x64, 0xc4, 0xc5, 0x03, 0xd7, 0x90, 0x9b,
464
+	0x98, 0x2c, 0xc1, 0x04, 0xd6, 0xc1, 0xff, 0xe8, 0x9e, 0x3c, 0x37, 0x4c, 0x87, 0xaf, 0xa3, 0x73,
465
+	0x10, 0xdc, 0x54, 0xdf, 0xc4, 0x64, 0x21, 0x27, 0x2e, 0xa1, 0x92, 0xd2, 0xbc, 0xbc, 0xd4, 0x9c,
466
+	0x78, 0x64, 0xbb, 0x98, 0xc1, 0x3a, 0x45, 0x1e, 0xdd, 0x93, 0x17, 0x08, 0x01, 0xcb, 0x22, 0xd9,
467
+	0x28, 0x50, 0x82, 0x2a, 0x52, 0xe0, 0x24, 0x71, 0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c,
468
+	0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39,
469
+	0xc6, 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x48, 0x07, 0xf6, 0xf3,
470
+	0x18, 0x01, 0x00, 0x00,
468 471
 }
... ...
@@ -1,16 +1,17 @@
1 1
 package remote
2 2
 
3 3
 import (
4
-	"errors"
5 4
 	"fmt"
6 5
 	"net"
7 6
 
7
+	"github.com/docker/docker/pkg/plugingetter"
8 8
 	"github.com/docker/docker/pkg/plugins"
9 9
 	"github.com/docker/libnetwork/datastore"
10 10
 	"github.com/docker/libnetwork/discoverapi"
11 11
 	"github.com/docker/libnetwork/driverapi"
12 12
 	"github.com/docker/libnetwork/drivers/remote/api"
13 13
 	"github.com/docker/libnetwork/types"
14
+	"github.com/pkg/errors"
14 15
 	"github.com/sirupsen/logrus"
15 16
 )
16 17
 
... ...
@@ -49,7 +50,11 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
49 49
 		handleFunc = pg.Handle
50 50
 		activePlugins := pg.GetAllManagedPluginsByCap(driverapi.NetworkPluginEndpointType)
51 51
 		for _, ap := range activePlugins {
52
-			newPluginHandler(ap.Name(), ap.Client())
52
+			client, err := getPluginClient(ap)
53
+			if err != nil {
54
+				return err
55
+			}
56
+			newPluginHandler(ap.Name(), client)
53 57
 		}
54 58
 	}
55 59
 	handleFunc(driverapi.NetworkPluginEndpointType, newPluginHandler)
... ...
@@ -57,6 +62,28 @@ func Init(dc driverapi.DriverCallback, config map[string]interface{}) error {
57 57
 	return nil
58 58
 }
59 59
 
60
+func getPluginClient(p plugingetter.CompatPlugin) (*plugins.Client, error) {
61
+	if v1, ok := p.(plugingetter.PluginWithV1Client); ok {
62
+		return v1.Client(), nil
63
+	}
64
+
65
+	pa, ok := p.(plugingetter.PluginAddr)
66
+	if !ok {
67
+		return nil, errors.Errorf("unknown plugin type %T", p)
68
+	}
69
+
70
+	if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
71
+		return nil, errors.Errorf("unsupported plugin protocol %s", pa.Protocol())
72
+	}
73
+
74
+	addr := pa.Addr()
75
+	client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout())
76
+	if err != nil {
77
+		return nil, errors.Wrap(err, "error creating plugin client")
78
+	}
79
+	return client, nil
80
+}
81
+
60 82
 // Get capability from client
61 83
 func (d *driver) getCapabilities() (*driverapi.Capability, error) {
62 84
 	var capResp api.GetCapabilityResponse
... ...
@@ -1,12 +1,11 @@
1
-// Code generated by protoc-gen-gogo.
2
-// source: overlay.proto
3
-// DO NOT EDIT!
1
+// Code generated by protoc-gen-gogo. DO NOT EDIT.
2
+// source: drivers/windows/overlay/overlay.proto
4 3
 
5 4
 /*
6 5
 	Package overlay is a generated protocol buffer package.
7 6
 
8 7
 	It is generated from these files:
9
-		overlay.proto
8
+		drivers/windows/overlay/overlay.proto
10 9
 
11 10
 	It has these top-level messages:
12 11
 		PeerRecord
... ...
@@ -19,9 +18,6 @@ import math "math"
19 19
 import _ "github.com/gogo/protobuf/gogoproto"
20 20
 
21 21
 import strings "strings"
22
-import github_com_gogo_protobuf_proto "github.com/gogo/protobuf/proto"
23
-import sort "sort"
24
-import strconv "strconv"
25 22
 import reflect "reflect"
26 23
 
27 24
 import io "io"
... ...
@@ -33,7 +29,9 @@ var _ = math.Inf
33 33
 
34 34
 // This is a compile-time assertion to ensure that this generated file
35 35
 // is compatible with the proto package it is being compiled against.
36
-const _ = proto.GoGoProtoPackageIsVersion1
36
+// A compilation error at this line likely means your copy of the
37
+// proto package needs to be updated.
38
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
37 39
 
38 40
 // PeerRecord defines the information corresponding to a peer
39 41
 // container in the overlay network.
... ...
@@ -54,6 +52,27 @@ func (m *PeerRecord) Reset()                    { *m = PeerRecord{} }
54 54
 func (*PeerRecord) ProtoMessage()               {}
55 55
 func (*PeerRecord) Descriptor() ([]byte, []int) { return fileDescriptorOverlay, []int{0} }
56 56
 
57
+func (m *PeerRecord) GetEndpointIP() string {
58
+	if m != nil {
59
+		return m.EndpointIP
60
+	}
61
+	return ""
62
+}
63
+
64
+func (m *PeerRecord) GetEndpointMAC() string {
65
+	if m != nil {
66
+		return m.EndpointMAC
67
+	}
68
+	return ""
69
+}
70
+
71
+func (m *PeerRecord) GetTunnelEndpointIP() string {
72
+	if m != nil {
73
+		return m.TunnelEndpointIP
74
+	}
75
+	return ""
76
+}
77
+
57 78
 func init() {
58 79
 	proto.RegisterType((*PeerRecord)(nil), "overlay.PeerRecord")
59 80
 }
... ...
@@ -77,84 +96,49 @@ func valueToGoStringOverlay(v interface{}, typ string) string {
77 77
 	pv := reflect.Indirect(rv).Interface()
78 78
 	return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
79 79
 }
80
-func extensionToGoStringOverlay(e map[int32]github_com_gogo_protobuf_proto.Extension) string {
81
-	if e == nil {
82
-		return "nil"
83
-	}
84
-	s := "map[int32]proto.Extension{"
85
-	keys := make([]int, 0, len(e))
86
-	for k := range e {
87
-		keys = append(keys, int(k))
88
-	}
89
-	sort.Ints(keys)
90
-	ss := []string{}
91
-	for _, k := range keys {
92
-		ss = append(ss, strconv.Itoa(k)+": "+e[int32(k)].GoString())
93
-	}
94
-	s += strings.Join(ss, ",") + "}"
95
-	return s
96
-}
97
-func (m *PeerRecord) Marshal() (data []byte, err error) {
80
+func (m *PeerRecord) Marshal() (dAtA []byte, err error) {
98 81
 	size := m.Size()
99
-	data = make([]byte, size)
100
-	n, err := m.MarshalTo(data)
82
+	dAtA = make([]byte, size)
83
+	n, err := m.MarshalTo(dAtA)
101 84
 	if err != nil {
102 85
 		return nil, err
103 86
 	}
104
-	return data[:n], nil
87
+	return dAtA[:n], nil
105 88
 }
106 89
 
107
-func (m *PeerRecord) MarshalTo(data []byte) (int, error) {
90
+func (m *PeerRecord) MarshalTo(dAtA []byte) (int, error) {
108 91
 	var i int
109 92
 	_ = i
110 93
 	var l int
111 94
 	_ = l
112 95
 	if len(m.EndpointIP) > 0 {
113
-		data[i] = 0xa
96
+		dAtA[i] = 0xa
114 97
 		i++
115
-		i = encodeVarintOverlay(data, i, uint64(len(m.EndpointIP)))
116
-		i += copy(data[i:], m.EndpointIP)
98
+		i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointIP)))
99
+		i += copy(dAtA[i:], m.EndpointIP)
117 100
 	}
118 101
 	if len(m.EndpointMAC) > 0 {
119
-		data[i] = 0x12
102
+		dAtA[i] = 0x12
120 103
 		i++
121
-		i = encodeVarintOverlay(data, i, uint64(len(m.EndpointMAC)))
122
-		i += copy(data[i:], m.EndpointMAC)
104
+		i = encodeVarintOverlay(dAtA, i, uint64(len(m.EndpointMAC)))
105
+		i += copy(dAtA[i:], m.EndpointMAC)
123 106
 	}
124 107
 	if len(m.TunnelEndpointIP) > 0 {
125
-		data[i] = 0x1a
108
+		dAtA[i] = 0x1a
126 109
 		i++
127
-		i = encodeVarintOverlay(data, i, uint64(len(m.TunnelEndpointIP)))
128
-		i += copy(data[i:], m.TunnelEndpointIP)
110
+		i = encodeVarintOverlay(dAtA, i, uint64(len(m.TunnelEndpointIP)))
111
+		i += copy(dAtA[i:], m.TunnelEndpointIP)
129 112
 	}
130 113
 	return i, nil
131 114
 }
132 115
 
133
-func encodeFixed64Overlay(data []byte, offset int, v uint64) int {
134
-	data[offset] = uint8(v)
135
-	data[offset+1] = uint8(v >> 8)
136
-	data[offset+2] = uint8(v >> 16)
137
-	data[offset+3] = uint8(v >> 24)
138
-	data[offset+4] = uint8(v >> 32)
139
-	data[offset+5] = uint8(v >> 40)
140
-	data[offset+6] = uint8(v >> 48)
141
-	data[offset+7] = uint8(v >> 56)
142
-	return offset + 8
143
-}
144
-func encodeFixed32Overlay(data []byte, offset int, v uint32) int {
145
-	data[offset] = uint8(v)
146
-	data[offset+1] = uint8(v >> 8)
147
-	data[offset+2] = uint8(v >> 16)
148
-	data[offset+3] = uint8(v >> 24)
149
-	return offset + 4
150
-}
151
-func encodeVarintOverlay(data []byte, offset int, v uint64) int {
116
+func encodeVarintOverlay(dAtA []byte, offset int, v uint64) int {
152 117
 	for v >= 1<<7 {
153
-		data[offset] = uint8(v&0x7f | 0x80)
118
+		dAtA[offset] = uint8(v&0x7f | 0x80)
154 119
 		v >>= 7
155 120
 		offset++
156 121
 	}
157
-	data[offset] = uint8(v)
122
+	dAtA[offset] = uint8(v)
158 123
 	return offset + 1
159 124
 }
160 125
 func (m *PeerRecord) Size() (n int) {
... ...
@@ -208,8 +192,8 @@ func valueToStringOverlay(v interface{}) string {
208 208
 	pv := reflect.Indirect(rv).Interface()
209 209
 	return fmt.Sprintf("*%v", pv)
210 210
 }
211
-func (m *PeerRecord) Unmarshal(data []byte) error {
212
-	l := len(data)
211
+func (m *PeerRecord) Unmarshal(dAtA []byte) error {
212
+	l := len(dAtA)
213 213
 	iNdEx := 0
214 214
 	for iNdEx < l {
215 215
 		preIndex := iNdEx
... ...
@@ -221,7 +205,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
221 221
 			if iNdEx >= l {
222 222
 				return io.ErrUnexpectedEOF
223 223
 			}
224
-			b := data[iNdEx]
224
+			b := dAtA[iNdEx]
225 225
 			iNdEx++
226 226
 			wire |= (uint64(b) & 0x7F) << shift
227 227
 			if b < 0x80 {
... ...
@@ -249,7 +233,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
249 249
 				if iNdEx >= l {
250 250
 					return io.ErrUnexpectedEOF
251 251
 				}
252
-				b := data[iNdEx]
252
+				b := dAtA[iNdEx]
253 253
 				iNdEx++
254 254
 				stringLen |= (uint64(b) & 0x7F) << shift
255 255
 				if b < 0x80 {
... ...
@@ -264,7 +248,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
264 264
 			if postIndex > l {
265 265
 				return io.ErrUnexpectedEOF
266 266
 			}
267
-			m.EndpointIP = string(data[iNdEx:postIndex])
267
+			m.EndpointIP = string(dAtA[iNdEx:postIndex])
268 268
 			iNdEx = postIndex
269 269
 		case 2:
270 270
 			if wireType != 2 {
... ...
@@ -278,7 +262,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
278 278
 				if iNdEx >= l {
279 279
 					return io.ErrUnexpectedEOF
280 280
 				}
281
-				b := data[iNdEx]
281
+				b := dAtA[iNdEx]
282 282
 				iNdEx++
283 283
 				stringLen |= (uint64(b) & 0x7F) << shift
284 284
 				if b < 0x80 {
... ...
@@ -293,7 +277,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
293 293
 			if postIndex > l {
294 294
 				return io.ErrUnexpectedEOF
295 295
 			}
296
-			m.EndpointMAC = string(data[iNdEx:postIndex])
296
+			m.EndpointMAC = string(dAtA[iNdEx:postIndex])
297 297
 			iNdEx = postIndex
298 298
 		case 3:
299 299
 			if wireType != 2 {
... ...
@@ -307,7 +291,7 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
307 307
 				if iNdEx >= l {
308 308
 					return io.ErrUnexpectedEOF
309 309
 				}
310
-				b := data[iNdEx]
310
+				b := dAtA[iNdEx]
311 311
 				iNdEx++
312 312
 				stringLen |= (uint64(b) & 0x7F) << shift
313 313
 				if b < 0x80 {
... ...
@@ -322,11 +306,11 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
322 322
 			if postIndex > l {
323 323
 				return io.ErrUnexpectedEOF
324 324
 			}
325
-			m.TunnelEndpointIP = string(data[iNdEx:postIndex])
325
+			m.TunnelEndpointIP = string(dAtA[iNdEx:postIndex])
326 326
 			iNdEx = postIndex
327 327
 		default:
328 328
 			iNdEx = preIndex
329
-			skippy, err := skipOverlay(data[iNdEx:])
329
+			skippy, err := skipOverlay(dAtA[iNdEx:])
330 330
 			if err != nil {
331 331
 				return err
332 332
 			}
... ...
@@ -345,8 +329,8 @@ func (m *PeerRecord) Unmarshal(data []byte) error {
345 345
 	}
346 346
 	return nil
347 347
 }
348
-func skipOverlay(data []byte) (n int, err error) {
349
-	l := len(data)
348
+func skipOverlay(dAtA []byte) (n int, err error) {
349
+	l := len(dAtA)
350 350
 	iNdEx := 0
351 351
 	for iNdEx < l {
352 352
 		var wire uint64
... ...
@@ -357,7 +341,7 @@ func skipOverlay(data []byte) (n int, err error) {
357 357
 			if iNdEx >= l {
358 358
 				return 0, io.ErrUnexpectedEOF
359 359
 			}
360
-			b := data[iNdEx]
360
+			b := dAtA[iNdEx]
361 361
 			iNdEx++
362 362
 			wire |= (uint64(b) & 0x7F) << shift
363 363
 			if b < 0x80 {
... ...
@@ -375,7 +359,7 @@ func skipOverlay(data []byte) (n int, err error) {
375 375
 					return 0, io.ErrUnexpectedEOF
376 376
 				}
377 377
 				iNdEx++
378
-				if data[iNdEx-1] < 0x80 {
378
+				if dAtA[iNdEx-1] < 0x80 {
379 379
 					break
380 380
 				}
381 381
 			}
... ...
@@ -392,7 +376,7 @@ func skipOverlay(data []byte) (n int, err error) {
392 392
 				if iNdEx >= l {
393 393
 					return 0, io.ErrUnexpectedEOF
394 394
 				}
395
-				b := data[iNdEx]
395
+				b := dAtA[iNdEx]
396 396
 				iNdEx++
397 397
 				length |= (int(b) & 0x7F) << shift
398 398
 				if b < 0x80 {
... ...
@@ -415,7 +399,7 @@ func skipOverlay(data []byte) (n int, err error) {
415 415
 					if iNdEx >= l {
416 416
 						return 0, io.ErrUnexpectedEOF
417 417
 					}
418
-					b := data[iNdEx]
418
+					b := dAtA[iNdEx]
419 419
 					iNdEx++
420 420
 					innerWire |= (uint64(b) & 0x7F) << shift
421 421
 					if b < 0x80 {
... ...
@@ -426,7 +410,7 @@ func skipOverlay(data []byte) (n int, err error) {
426 426
 				if innerWireType == 4 {
427 427
 					break
428 428
 				}
429
-				next, err := skipOverlay(data[start:])
429
+				next, err := skipOverlay(dAtA[start:])
430 430
 				if err != nil {
431 431
 					return 0, err
432 432
 				}
... ...
@@ -450,19 +434,22 @@ var (
450 450
 	ErrIntOverflowOverlay   = fmt.Errorf("proto: integer overflow")
451 451
 )
452 452
 
453
+func init() { proto.RegisterFile("drivers/windows/overlay/overlay.proto", fileDescriptorOverlay) }
454
+
453 455
 var fileDescriptorOverlay = []byte{
454
-	// 195 bytes of a gzipped FileDescriptorProto
455
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0xcd, 0x2f, 0x4b, 0x2d,
456
-	0xca, 0x49, 0xac, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0xa5, 0x44, 0xd2,
457
-	0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x69, 0x2b, 0x23, 0x17, 0x57, 0x40,
458
-	0x6a, 0x6a, 0x51, 0x50, 0x6a, 0x72, 0x7e, 0x51, 0x8a, 0x90, 0x3e, 0x17, 0x77, 0x6a, 0x5e, 0x4a,
459
-	0x41, 0x7e, 0x66, 0x5e, 0x49, 0x7c, 0x66, 0x81, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xa7, 0x13, 0xdf,
460
-	0xa3, 0x7b, 0xf2, 0x5c, 0xae, 0x50, 0x61, 0xcf, 0x80, 0x20, 0x2e, 0x98, 0x12, 0xcf, 0x02, 0x21,
461
-	0x23, 0x2e, 0x1e, 0xb8, 0x86, 0xdc, 0xc4, 0x64, 0x09, 0x26, 0xb0, 0x0e, 0x7e, 0xa0, 0x0e, 0x6e,
462
-	0x98, 0x0e, 0x5f, 0x47, 0xe7, 0x20, 0xb8, 0xa9, 0xbe, 0x89, 0xc9, 0x42, 0x4e, 0x5c, 0x42, 0x25,
463
-	0xa5, 0x79, 0x79, 0xa9, 0x39, 0xf1, 0xc8, 0x76, 0x31, 0x83, 0x75, 0x8a, 0x00, 0x75, 0x0a, 0x84,
464
-	0x80, 0x65, 0x91, 0x6c, 0x14, 0x28, 0x41, 0x15, 0x29, 0x70, 0x92, 0xb8, 0xf1, 0x50, 0x8e, 0xe1,
465
-	0xc3, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x27, 0x80, 0xf8, 0x02, 0x10, 0x3f, 0x00, 0xe2,
466
-	0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xd7, 0x7d, 0x7d, 0x08,
467
-	0x01, 0x00, 0x00,
456
+	// 220 bytes of a gzipped FileDescriptorProto
457
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0x29, 0xca, 0x2c,
458
+	0x4b, 0x2d, 0x2a, 0xd6, 0x2f, 0xcf, 0xcc, 0x4b, 0xc9, 0x2f, 0x2f, 0xd6, 0xcf, 0x2f, 0x4b, 0x2d,
459
+	0xca, 0x49, 0xac, 0x84, 0xd1, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xec, 0x50, 0xae, 0x94,
460
+	0x48, 0x7a, 0x7e, 0x7a, 0x3e, 0x58, 0x4c, 0x1f, 0xc4, 0x82, 0x48, 0x2b, 0x6d, 0x65, 0xe4, 0xe2,
461
+	0x0a, 0x48, 0x4d, 0x2d, 0x0a, 0x4a, 0x4d, 0xce, 0x2f, 0x4a, 0x11, 0xd2, 0xe7, 0xe2, 0x4e, 0xcd,
462
+	0x4b, 0x29, 0xc8, 0xcf, 0xcc, 0x2b, 0x89, 0xcf, 0x2c, 0x90, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x74,
463
+	0xe2, 0x7b, 0x74, 0x4f, 0x9e, 0xcb, 0x15, 0x2a, 0xec, 0x19, 0x10, 0xc4, 0x05, 0x53, 0xe2, 0x59,
464
+	0x20, 0x64, 0xc4, 0xc5, 0x03, 0xd7, 0x90, 0x9b, 0x98, 0x2c, 0xc1, 0x04, 0xd6, 0xc1, 0xff, 0xe8,
465
+	0x9e, 0x3c, 0x37, 0x4c, 0x87, 0xaf, 0xa3, 0x73, 0x10, 0xdc, 0x54, 0xdf, 0xc4, 0x64, 0x21, 0x27,
466
+	0x2e, 0xa1, 0x92, 0xd2, 0xbc, 0xbc, 0xd4, 0x9c, 0x78, 0x64, 0xbb, 0x98, 0xc1, 0x3a, 0x45, 0x1e,
467
+	0xdd, 0x93, 0x17, 0x08, 0x01, 0xcb, 0x22, 0xd9, 0x28, 0x50, 0x82, 0x2a, 0x52, 0xe0, 0x24, 0x71,
468
+	0xe3, 0xa1, 0x1c, 0xc3, 0x87, 0x87, 0x72, 0x8c, 0x0d, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63,
469
+	0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x24, 0x36, 0xb0, 0xc7, 0x8c, 0x01, 0x01,
470
+	0x00, 0x00, 0xff, 0xff, 0xc0, 0x48, 0xd1, 0xc0, 0x20, 0x01, 0x00, 0x00,
468 471
 }
... ...
@@ -540,6 +540,12 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) {
540 540
 		}
541 541
 	}()
542 542
 
543
+	// Load balancing endpoints should never have a default gateway nor
544
+	// should they alter the status of a network's default gateway
545
+	if ep.loadBalancer && !sb.ingress {
546
+		return nil
547
+	}
548
+
543 549
 	if sb.needDefaultGW() && sb.getEndpointInGWNetwork() == nil {
544 550
 		return sb.setupDefaultGW()
545 551
 	}
... ...
@@ -49,6 +49,9 @@ type InterfaceInfo interface {
49 49
 
50 50
 	// LinkLocalAddresses returns the list of link-local (IPv4/IPv6) addresses assigned to the endpoint.
51 51
 	LinkLocalAddresses() []*net.IPNet
52
+
53
+	// SrcName returns the name of the interface w/in the container
54
+	SrcName() string
52 55
 }
53 56
 
54 57
 type endpointInterface struct {
... ...
@@ -272,6 +275,10 @@ func (epi *endpointInterface) LinkLocalAddresses() []*net.IPNet {
272 272
 	return epi.llAddrs
273 273
 }
274 274
 
275
+func (epi *endpointInterface) SrcName() string {
276
+	return epi.srcName
277
+}
278
+
275 279
 func (epi *endpointInterface) SetNames(srcName string, dstPrefix string) error {
276 280
 	epi.srcName = srcName
277 281
 	epi.dstPrefix = dstPrefix
... ...
@@ -4,11 +4,13 @@ import (
4 4
 	"fmt"
5 5
 	"net"
6 6
 
7
+	"github.com/docker/docker/pkg/plugingetter"
7 8
 	"github.com/docker/docker/pkg/plugins"
8 9
 	"github.com/docker/libnetwork/discoverapi"
9 10
 	"github.com/docker/libnetwork/ipamapi"
10 11
 	"github.com/docker/libnetwork/ipams/remote/api"
11 12
 	"github.com/docker/libnetwork/types"
13
+	"github.com/pkg/errors"
12 14
 	"github.com/sirupsen/logrus"
13 15
 )
14 16
 
... ...
@@ -52,13 +54,39 @@ func Init(cb ipamapi.Callback, l, g interface{}) error {
52 52
 		handleFunc = pg.Handle
53 53
 		activePlugins := pg.GetAllManagedPluginsByCap(ipamapi.PluginEndpointType)
54 54
 		for _, ap := range activePlugins {
55
-			newPluginHandler(ap.Name(), ap.Client())
55
+			client, err := getPluginClient(ap)
56
+			if err != nil {
57
+				return err
58
+			}
59
+			newPluginHandler(ap.Name(), client)
56 60
 		}
57 61
 	}
58 62
 	handleFunc(ipamapi.PluginEndpointType, newPluginHandler)
59 63
 	return nil
60 64
 }
61 65
 
66
+func getPluginClient(p plugingetter.CompatPlugin) (*plugins.Client, error) {
67
+	if v1, ok := p.(plugingetter.PluginWithV1Client); ok {
68
+		return v1.Client(), nil
69
+	}
70
+
71
+	pa, ok := p.(plugingetter.PluginAddr)
72
+	if !ok {
73
+		return nil, errors.Errorf("unknown plugin type %T", p)
74
+	}
75
+
76
+	if pa.Protocol() != plugins.ProtocolSchemeHTTPV1 {
77
+		return nil, errors.Errorf("unsupported plugin protocol %s", pa.Protocol())
78
+	}
79
+
80
+	addr := pa.Addr()
81
+	client, err := plugins.NewClientWithTimeout(addr.Network()+"://"+addr.String(), nil, pa.Timeout())
82
+	if err != nil {
83
+		return nil, errors.Wrap(err, "error creating plugin client")
84
+	}
85
+	return client, nil
86
+}
87
+
62 88
 func (a *allocator) call(methodName string, arg interface{}, retVal PluginResponse) error {
63 89
 	method := ipamapi.PluginEndpointType + "." + methodName
64 90
 	err := a.endpoint.Call(method, arg, retVal)
... ...
@@ -40,7 +40,7 @@ type Network interface {
40 40
 	CreateEndpoint(name string, options ...EndpointOption) (Endpoint, error)
41 41
 
42 42
 	// Delete the network.
43
-	Delete() error
43
+	Delete(options ...NetworkDeleteOption) error
44 44
 
45 45
 	// Endpoints returns the list of Endpoint(s) in this network.
46 46
 	Endpoints() []Endpoint
... ...
@@ -875,6 +875,28 @@ func (n *network) processOptions(options ...NetworkOption) {
875 875
 	}
876 876
 }
877 877
 
878
+type networkDeleteParams struct {
879
+	rmLBEndpoint bool
880
+}
881
+
882
+// NetworkDeleteOption is a type for optional parameters to pass to the
883
+// network.Delete() function.
884
+type NetworkDeleteOption func(p *networkDeleteParams)
885
+
886
+// NetworkDeleteOptionRemoveLB informs a network.Delete() operation that should
887
+// remove the load balancer endpoint for this network.  Note that the Delete()
888
+// method will automatically remove a load balancing endpoint for most networks
889
+// when the network is otherwise empty.  However, this does not occur for some
890
+// networks.  In particular, networks marked as ingress (which are supposed to
891
+// be more permanent than other overlay networks) won't automatically remove
892
+// the LB endpoint on Delete().  This method allows for explicit removal of
893
+// such networks provided there are no other endpoints present in the network.
894
+// If the network still has non-LB endpoints present, Delete() will not
895
+// remove the LB endpoint and will return an error.
896
+func NetworkDeleteOptionRemoveLB(p *networkDeleteParams) {
897
+	p.rmLBEndpoint = true
898
+}
899
+
878 900
 func (n *network) resolveDriver(name string, load bool) (driverapi.Driver, *driverapi.Capability, error) {
879 901
 	c := n.getController()
880 902
 
... ...
@@ -938,11 +960,23 @@ func (n *network) driver(load bool) (driverapi.Driver, error) {
938 938
 	return d, nil
939 939
 }
940 940
 
941
-func (n *network) Delete() error {
942
-	return n.delete(false)
941
+func (n *network) Delete(options ...NetworkDeleteOption) error {
942
+	var params networkDeleteParams
943
+	for _, opt := range options {
944
+		opt(&params)
945
+	}
946
+	return n.delete(false, params.rmLBEndpoint)
943 947
 }
944 948
 
945
-func (n *network) delete(force bool) error {
949
+// This function gets called in 3 ways:
950
+//  * Delete() -- (false, false)
951
+//      remove if endpoint count == 0 or endpoint count == 1 and
952
+//      there is a load balancer IP
953
+//  * Delete(libnetwork.NetworkDeleteOptionRemoveLB) -- (false, true)
954
+//      remove load balancer and network if endpoint count == 1
955
+//  * controller.networkCleanup() -- (true, true)
956
+//      remove the network no matter what
957
+func (n *network) delete(force bool, rmLBEndpoint bool) error {
946 958
 	n.Lock()
947 959
 	c := n.ctrlr
948 960
 	name := n.name
... ...
@@ -957,10 +991,32 @@ func (n *network) delete(force bool) error {
957 957
 		return &UnknownNetworkError{name: name, id: id}
958 958
 	}
959 959
 
960
-	if len(n.loadBalancerIP) != 0 {
961
-		endpoints := n.Endpoints()
962
-		if force || (len(endpoints) == 1 && !n.ingress) {
963
-			n.deleteLoadBalancerSandbox()
960
+	// Only remove ingress on force removal or explicit LB endpoint removal
961
+	if n.ingress && !force && !rmLBEndpoint {
962
+		return &ActiveEndpointsError{name: n.name, id: n.id}
963
+	}
964
+
965
+	// Check that the network is empty
966
+	var emptyCount uint64
967
+	if n.hasLoadBalancerEndpoint() {
968
+		emptyCount = 1
969
+	}
970
+	if !force && n.getEpCnt().EndpointCnt() > emptyCount {
971
+		if n.configOnly {
972
+			return types.ForbiddenErrorf("configuration network %q is in use", n.Name())
973
+		}
974
+		return &ActiveEndpointsError{name: n.name, id: n.id}
975
+	}
976
+
977
+	if n.hasLoadBalancerEndpoint() {
978
+		// If we got to this point, then the following must hold:
979
+		//  * force is true OR endpoint count == 1
980
+		if err := n.deleteLoadBalancerSandbox(); err != nil {
981
+			if !force {
982
+				return err
983
+			}
984
+			// continue deletion when force is true even on error
985
+			logrus.Warnf("Error deleting load balancer sandbox: %v", err)
964 986
 		}
965 987
 		//Reload the network from the store to update the epcnt.
966 988
 		n, err = c.getNetworkFromStore(id)
... ...
@@ -969,12 +1025,10 @@ func (n *network) delete(force bool) error {
969 969
 		}
970 970
 	}
971 971
 
972
-	if !force && n.getEpCnt().EndpointCnt() != 0 {
973
-		if n.configOnly {
974
-			return types.ForbiddenErrorf("configuration network %q is in use", n.Name())
975
-		}
976
-		return &ActiveEndpointsError{name: n.name, id: n.id}
977
-	}
972
+	// Up to this point, errors that we returned were recoverable.
973
+	// From here on, any errors leave us in an inconsistent state.
974
+	// This is unfortunate, but there isn't a safe way to
975
+	// reconstitute a load-balancer endpoint after removing it.
978 976
 
979 977
 	// Mark the network for deletion
980 978
 	n.inDelete = true
... ...
@@ -1023,9 +1077,6 @@ func (n *network) delete(force bool) error {
1023 1023
 	// Cleanup the service discovery for this network
1024 1024
 	c.cleanupServiceDiscovery(n.ID())
1025 1025
 
1026
-	// Cleanup the load balancer
1027
-	c.cleanupServiceBindings(n.ID())
1028
-
1029 1026
 removeFromStore:
1030 1027
 	// deleteFromStore performs an atomic delete operation and the
1031 1028
 	// network.epCnt will help prevent any possible
... ...
@@ -1877,6 +1928,10 @@ func (n *network) hasSpecialDriver() bool {
1877 1877
 	return n.Type() == "host" || n.Type() == "null"
1878 1878
 }
1879 1879
 
1880
+func (n *network) hasLoadBalancerEndpoint() bool {
1881
+	return len(n.loadBalancerIP) != 0
1882
+}
1883
+
1880 1884
 func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
1881 1885
 	var ipv6Miss bool
1882 1886
 
... ...
@@ -2056,8 +2111,20 @@ func (c *controller) getConfigNetwork(name string) (*network, error) {
2056 2056
 	return n.(*network), nil
2057 2057
 }
2058 2058
 
2059
-func (n *network) createLoadBalancerSandbox() error {
2060
-	sandboxName := n.name + "-sbox"
2059
+func (n *network) lbSandboxName() string {
2060
+	name := "lb-" + n.name
2061
+	if n.ingress {
2062
+		name = n.name + "-sbox"
2063
+	}
2064
+	return name
2065
+}
2066
+
2067
+func (n *network) lbEndpointName() string {
2068
+	return n.name + "-endpoint"
2069
+}
2070
+
2071
+func (n *network) createLoadBalancerSandbox() (retErr error) {
2072
+	sandboxName := n.lbSandboxName()
2061 2073
 	sbOptions := []SandboxOption{}
2062 2074
 	if n.ingress {
2063 2075
 		sbOptions = append(sbOptions, OptionIngress())
... ...
@@ -2067,26 +2134,30 @@ func (n *network) createLoadBalancerSandbox() error {
2067 2067
 		return err
2068 2068
 	}
2069 2069
 	defer func() {
2070
-		if err != nil {
2070
+		if retErr != nil {
2071 2071
 			if e := n.ctrlr.SandboxDestroy(sandboxName); e != nil {
2072
-				logrus.Warnf("could not delete sandbox %s on failure on failure (%v): %v", sandboxName, err, e)
2072
+				logrus.Warnf("could not delete sandbox %s on failure on failure (%v): %v", sandboxName, retErr, e)
2073 2073
 			}
2074 2074
 		}
2075 2075
 	}()
2076 2076
 
2077
-	endpointName := n.name + "-endpoint"
2077
+	endpointName := n.lbEndpointName()
2078 2078
 	epOptions := []EndpointOption{
2079 2079
 		CreateOptionIpam(n.loadBalancerIP, nil, nil, nil),
2080 2080
 		CreateOptionLoadBalancer(),
2081 2081
 	}
2082
+	if n.hasLoadBalancerEndpoint() && !n.ingress {
2083
+		// Mark LB endpoints as anonymous so they don't show up in DNS
2084
+		epOptions = append(epOptions, CreateOptionAnonymous())
2085
+	}
2082 2086
 	ep, err := n.createEndpoint(endpointName, epOptions...)
2083 2087
 	if err != nil {
2084 2088
 		return err
2085 2089
 	}
2086 2090
 	defer func() {
2087
-		if err != nil {
2091
+		if retErr != nil {
2088 2092
 			if e := ep.Delete(true); e != nil {
2089
-				logrus.Warnf("could not delete endpoint %s on failure on failure (%v): %v", endpointName, err, e)
2093
+				logrus.Warnf("could not delete endpoint %s on failure on failure (%v): %v", endpointName, retErr, e)
2090 2094
 			}
2091 2095
 		}
2092 2096
 	}()
... ...
@@ -2094,17 +2165,18 @@ func (n *network) createLoadBalancerSandbox() error {
2094 2094
 	if err := ep.Join(sb, nil); err != nil {
2095 2095
 		return err
2096 2096
 	}
2097
+
2097 2098
 	return sb.EnableService()
2098 2099
 }
2099 2100
 
2100
-func (n *network) deleteLoadBalancerSandbox() {
2101
+func (n *network) deleteLoadBalancerSandbox() error {
2101 2102
 	n.Lock()
2102 2103
 	c := n.ctrlr
2103 2104
 	name := n.name
2104 2105
 	n.Unlock()
2105 2106
 
2106
-	endpointName := name + "-endpoint"
2107
-	sandboxName := name + "-sbox"
2107
+	sandboxName := n.lbSandboxName()
2108
+	endpointName := n.lbEndpointName()
2108 2109
 
2109 2110
 	endpoint, err := n.EndpointByName(endpointName)
2110 2111
 	if err != nil {
... ...
@@ -2129,6 +2201,7 @@ func (n *network) deleteLoadBalancerSandbox() {
2129 2129
 	}
2130 2130
 
2131 2131
 	if err := c.SandboxDestroy(sandboxName); err != nil {
2132
-		logrus.Warnf("Failed to delete %s sandbox: %v", sandboxName, err)
2132
+		return fmt.Errorf("Failed to delete %s sandbox: %v", sandboxName, err)
2133 2133
 	}
2134
+	return nil
2134 2135
 }
... ...
@@ -1,11 +1,11 @@
1 1
 // Code generated by protoc-gen-gogo. DO NOT EDIT.
2
-// source: networkdb.proto
2
+// source: networkdb/networkdb.proto
3 3
 
4 4
 /*
5 5
 	Package networkdb is a generated protocol buffer package.
6 6
 
7 7
 	It is generated from these files:
8
-		networkdb.proto
8
+		networkdb/networkdb.proto
9 9
 
10 10
 	It has these top-level messages:
11 11
 		GossipMessage
... ...
@@ -476,7 +476,7 @@ func (m *CompoundMessage) GetMessages() []*CompoundMessage_SimpleMessage {
476 476
 type CompoundMessage_SimpleMessage struct {
477 477
 	// Bytestring payload of a message constructed using
478 478
 	// other message type definitions.
479
-	Payload []byte `protobuf:"bytes,1,opt,name=Payload,proto3" json:"Payload,omitempty"`
479
+	Payload []byte `protobuf:"bytes,1,opt,name=Payload,json=payload,proto3" json:"Payload,omitempty"`
480 480
 }
481 481
 
482 482
 func (m *CompoundMessage_SimpleMessage) Reset()      { *m = CompoundMessage_SimpleMessage{} }
... ...
@@ -997,24 +997,6 @@ func (m *CompoundMessage_SimpleMessage) MarshalTo(dAtA []byte) (int, error) {
997 997
 	return i, nil
998 998
 }
999 999
 
1000
-func encodeFixed64Networkdb(dAtA []byte, offset int, v uint64) int {
1001
-	dAtA[offset] = uint8(v)
1002
-	dAtA[offset+1] = uint8(v >> 8)
1003
-	dAtA[offset+2] = uint8(v >> 16)
1004
-	dAtA[offset+3] = uint8(v >> 24)
1005
-	dAtA[offset+4] = uint8(v >> 32)
1006
-	dAtA[offset+5] = uint8(v >> 40)
1007
-	dAtA[offset+6] = uint8(v >> 48)
1008
-	dAtA[offset+7] = uint8(v >> 56)
1009
-	return offset + 8
1010
-}
1011
-func encodeFixed32Networkdb(dAtA []byte, offset int, v uint32) int {
1012
-	dAtA[offset] = uint8(v)
1013
-	dAtA[offset+1] = uint8(v >> 8)
1014
-	dAtA[offset+2] = uint8(v >> 16)
1015
-	dAtA[offset+3] = uint8(v >> 24)
1016
-	return offset + 4
1017
-}
1018 1000
 func encodeVarintNetworkdb(dAtA []byte, offset int, v uint64) int {
1019 1001
 	for v >= 1<<7 {
1020 1002
 		dAtA[offset] = uint8(v&0x7f | 0x80)
... ...
@@ -2666,68 +2648,68 @@ var (
2666 2666
 	ErrIntOverflowNetworkdb   = fmt.Errorf("proto: integer overflow")
2667 2667
 )
2668 2668
 
2669
-func init() { proto.RegisterFile("networkdb.proto", fileDescriptorNetworkdb) }
2669
+func init() { proto.RegisterFile("networkdb/networkdb.proto", fileDescriptorNetworkdb) }
2670 2670
 
2671 2671
 var fileDescriptorNetworkdb = []byte{
2672
-	// 953 bytes of a gzipped FileDescriptorProto
2672
+	// 955 bytes of a gzipped FileDescriptorProto
2673 2673
 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x96, 0xcd, 0x6e, 0xe3, 0x54,
2674
-	0x14, 0xc7, 0x7b, 0xf3, 0xd5, 0xe4, 0x34, 0xa5, 0xe6, 0x4e, 0x67, 0xc6, 0xe3, 0x81, 0xc4, 0x98,
2675
-	0x99, 0x2a, 0x53, 0x41, 0x8a, 0x3a, 0x4f, 0xd0, 0x24, 0x16, 0x64, 0x26, 0xe3, 0x44, 0x6e, 0x52,
2676
-	0xc4, 0x2a, 0xba, 0xad, 0x2f, 0xa9, 0x55, 0xc7, 0xb6, 0x6c, 0x27, 0x28, 0x2b, 0x10, 0xab, 0x51,
2677
-	0x16, 0xbc, 0x41, 0x56, 0xc3, 0x9a, 0x07, 0x40, 0x2c, 0x59, 0xcc, 0x82, 0x05, 0xec, 0x10, 0x8b,
2678
-	0x88, 0xe6, 0x09, 0x78, 0x04, 0xe4, 0x6b, 0x3b, 0xb9, 0x49, 0xab, 0x91, 0x10, 0x23, 0xc1, 0x26,
2679
-	0xb9, 0x1f, 0xbf, 0x1c, 0x9f, 0xf3, 0xf7, 0xff, 0xdc, 0x1b, 0xd8, 0xb3, 0x69, 0xf0, 0x95, 0xe3,
2680
-	0x5d, 0x19, 0xe7, 0x55, 0xd7, 0x73, 0x02, 0x07, 0x17, 0x96, 0x0b, 0xd2, 0xfe, 0xc0, 0x19, 0x38,
2681
-	0x6c, 0xf5, 0x28, 0x1c, 0x45, 0x80, 0xd2, 0x86, 0xdd, 0x4f, 0x1d, 0xdf, 0x37, 0xdd, 0x17, 0xd4,
2682
-	0xf7, 0xc9, 0x80, 0xe2, 0x43, 0xc8, 0x04, 0x13, 0x97, 0x8a, 0x48, 0x46, 0x95, 0x77, 0x8e, 0xef,
2683
-	0x55, 0x57, 0x11, 0x63, 0xa2, 0x3b, 0x71, 0xa9, 0xce, 0x18, 0x8c, 0x21, 0x63, 0x90, 0x80, 0x88,
2684
-	0x29, 0x19, 0x55, 0x8a, 0x3a, 0x1b, 0x2b, 0xaf, 0x52, 0x50, 0xd0, 0x1c, 0x83, 0xaa, 0x63, 0x6a,
2685
-	0x07, 0xf8, 0xe3, 0xb5, 0x68, 0x0f, 0xb8, 0x68, 0x4b, 0xa6, 0xca, 0x05, 0x6c, 0x42, 0xce, 0xea,
2686
-	0x07, 0xe6, 0x90, 0xb2, 0x90, 0x99, 0xda, 0xf1, 0xeb, 0x79, 0x79, 0xeb, 0x8f, 0x79, 0xf9, 0x70,
2687
-	0x60, 0x06, 0x97, 0xa3, 0xf3, 0xea, 0x85, 0x33, 0x3c, 0xba, 0x24, 0xfe, 0xa5, 0x79, 0xe1, 0x78,
2688
-	0xee, 0x91, 0x4f, 0xbd, 0x2f, 0xd9, 0x47, 0xb5, 0x45, 0x86, 0xae, 0xe3, 0x05, 0x5d, 0x73, 0x48,
2689
-	0xf5, 0xac, 0x15, 0x7e, 0xe1, 0x87, 0x50, 0xb0, 0x1d, 0x83, 0xf6, 0x6d, 0x32, 0xa4, 0x62, 0x5a,
2690
-	0x46, 0x95, 0x82, 0x9e, 0x0f, 0x17, 0x34, 0x32, 0xa4, 0xca, 0xd7, 0x90, 0x09, 0x9f, 0x8a, 0x1f,
2691
-	0xc3, 0x76, 0x53, 0x3b, 0x3b, 0x69, 0x35, 0x1b, 0xc2, 0x96, 0x24, 0x4e, 0x67, 0xf2, 0xfe, 0x32,
2692
-	0xad, 0x70, 0xbf, 0x69, 0x8f, 0x89, 0x65, 0x1a, 0xb8, 0x0c, 0x99, 0x67, 0xed, 0xa6, 0x26, 0x20,
2693
-	0xe9, 0xee, 0x74, 0x26, 0xbf, 0xbb, 0xc6, 0x3c, 0x73, 0x4c, 0x1b, 0x7f, 0x00, 0xd9, 0x96, 0x7a,
2694
-	0x72, 0xa6, 0x0a, 0x29, 0xe9, 0xde, 0x74, 0x26, 0xe3, 0x35, 0xa2, 0x45, 0xc9, 0x98, 0x4a, 0xc5,
2695
-	0x97, 0xaf, 0x4a, 0x5b, 0x3f, 0x7e, 0x5f, 0x62, 0x0f, 0x56, 0xae, 0x53, 0x50, 0xd4, 0x22, 0x2d,
2696
-	0x22, 0xa1, 0x3e, 0x59, 0x13, 0xea, 0x3d, 0x5e, 0x28, 0x0e, 0xfb, 0x0f, 0xb4, 0xc2, 0x1f, 0x01,
2697
-	0xc4, 0xc9, 0xf4, 0x4d, 0x43, 0xcc, 0x84, 0xbb, 0xb5, 0xdd, 0xc5, 0xbc, 0x5c, 0x88, 0x13, 0x6b,
2698
-	0x36, 0xf4, 0xc4, 0x65, 0x4d, 0x43, 0x79, 0x89, 0x62, 0x69, 0x2b, 0xbc, 0xb4, 0x0f, 0xa7, 0x33,
2699
-	0xf9, 0x3e, 0x5f, 0x08, 0xaf, 0xae, 0xb2, 0x54, 0x37, 0x7a, 0x03, 0x1b, 0x18, 0x13, 0xf8, 0xd1,
2700
-	0x4a, 0xe0, 0x07, 0xd3, 0x99, 0x7c, 0x77, 0x13, 0xba, 0x4d, 0xe3, 0x5f, 0xd0, 0x4a, 0x63, 0x3b,
2701
-	0xf0, 0x26, 0x1b, 0x95, 0xa0, 0x37, 0x57, 0xf2, 0x36, 0xf5, 0x7d, 0x72, 0x43, 0xdf, 0x5a, 0x71,
2702
-	0x31, 0x2f, 0xe7, 0xb5, 0x58, 0x63, 0x4e, 0x6d, 0x11, 0xb6, 0x2d, 0x4a, 0xc6, 0xa6, 0x3d, 0x60,
2703
-	0x52, 0xe7, 0xf5, 0x64, 0xaa, 0xfc, 0x84, 0x60, 0x2f, 0x4e, 0xb4, 0x33, 0xf2, 0x2f, 0x3b, 0x23,
2704
-	0xcb, 0xe2, 0x72, 0x44, 0xff, 0x36, 0xc7, 0xa7, 0x90, 0x8f, 0x6b, 0xf7, 0xc5, 0x94, 0x9c, 0xae,
2705
-	0xec, 0x1c, 0xdf, 0xbf, 0xc5, 0x84, 0xa1, 0x8e, 0xfa, 0x12, 0xfc, 0x07, 0x85, 0x29, 0xdf, 0x65,
2706
-	0x00, 0xba, 0xe4, 0xdc, 0x8a, 0x0f, 0x86, 0xea, 0x9a, 0xdf, 0x25, 0xee, 0x51, 0x2b, 0xe8, 0x7f,
2707
-	0xef, 0x76, 0xfc, 0x3e, 0x40, 0x10, 0xa6, 0x1b, 0xc5, 0xca, 0xb2, 0x58, 0x05, 0xb6, 0xc2, 0x82,
2708
-	0x09, 0x90, 0xbe, 0xa2, 0x13, 0x31, 0xc7, 0xd6, 0xc3, 0x21, 0xde, 0x87, 0xec, 0x98, 0x58, 0x23,
2709
-	0x2a, 0x6e, 0xb3, 0x23, 0x33, 0x9a, 0xe0, 0x1a, 0x60, 0x8f, 0xfa, 0xa6, 0x31, 0x22, 0x56, 0xdf,
2710
-	0xa3, 0xc4, 0x8d, 0x0a, 0xcd, 0xcb, 0xa8, 0x92, 0xad, 0xed, 0x2f, 0xe6, 0x65, 0x41, 0x8f, 0x77,
2711
-	0x75, 0x4a, 0x5c, 0x56, 0x8a, 0xe0, 0x6d, 0xac, 0x28, 0x3f, 0x24, 0x8d, 0x77, 0xc0, 0x37, 0x1e,
2712
-	0x6b, 0x96, 0x95, 0xa2, 0x7c, 0xdb, 0x3d, 0x82, 0x5c, 0x5d, 0x57, 0x4f, 0xba, 0x6a, 0xd2, 0x78,
2713
-	0xeb, 0x58, 0xdd, 0xa3, 0x24, 0xa0, 0x21, 0xd5, 0xeb, 0x34, 0x42, 0x2a, 0x75, 0x1b, 0xd5, 0x73,
2714
-	0x8d, 0x98, 0x6a, 0xa8, 0x2d, 0xb5, 0xab, 0x0a, 0xe9, 0xdb, 0xa8, 0x06, 0xb5, 0x68, 0xb0, 0xd9,
2715
-	0x9e, 0xbf, 0x21, 0xd8, 0xab, 0x8d, 0xac, 0xab, 0xd3, 0x89, 0x7d, 0x91, 0x5c, 0x3e, 0x6f, 0xd1,
2716
-	0xcf, 0x32, 0xec, 0x8c, 0x6c, 0xdf, 0xb1, 0xcc, 0x0b, 0x33, 0xa0, 0x06, 0x73, 0x4d, 0x5e, 0xe7,
2717
-	0x97, 0xde, 0xec, 0x03, 0x89, 0x6b, 0x87, 0x8c, 0x9c, 0x66, 0x7b, 0x89, 0xeb, 0x45, 0xd8, 0x76,
2718
-	0xc9, 0xc4, 0x72, 0x88, 0xc1, 0x5e, 0x79, 0x51, 0x4f, 0xa6, 0xca, 0xb7, 0x08, 0xf6, 0xea, 0xce,
2719
-	0xd0, 0x75, 0x46, 0xb6, 0x91, 0xd4, 0xd4, 0x80, 0xfc, 0x30, 0x1a, 0xfa, 0x22, 0x62, 0x8d, 0x55,
2720
-	0xe1, 0xdc, 0xbe, 0x41, 0x57, 0x4f, 0xcd, 0xa1, 0x6b, 0xd1, 0x78, 0xa6, 0x2f, 0x7f, 0x29, 0x3d,
2721
-	0x81, 0xdd, 0xb5, 0xad, 0x30, 0x89, 0x4e, 0x9c, 0x04, 0x8a, 0x92, 0x88, 0xa7, 0x87, 0x3f, 0xa7,
2722
-	0x60, 0x87, 0xbb, 0xab, 0xf1, 0x87, 0xbc, 0x21, 0xd8, 0xf5, 0xc4, 0xed, 0x26, 0x6e, 0xa8, 0xc2,
2723
-	0xae, 0xa6, 0x76, 0x3f, 0x6f, 0xeb, 0xcf, 0xfb, 0xea, 0x99, 0xaa, 0x75, 0x05, 0x14, 0x1d, 0xda,
2724
-	0x1c, 0xba, 0x76, 0x5f, 0x1d, 0xc2, 0x4e, 0xf7, 0xa4, 0xd6, 0x52, 0x63, 0x3a, 0x3e, 0x96, 0x39,
2725
-	0x9a, 0xeb, 0xf5, 0x03, 0x28, 0x74, 0x7a, 0xa7, 0x9f, 0xf5, 0x3b, 0xbd, 0x56, 0x4b, 0x48, 0x4b,
2726
-	0xf7, 0xa7, 0x33, 0xf9, 0x0e, 0x47, 0x2e, 0x4f, 0xb3, 0x03, 0x28, 0xd4, 0x7a, 0xad, 0xe7, 0xfd,
2727
-	0xd3, 0x2f, 0xb4, 0xba, 0x90, 0xb9, 0xc1, 0x25, 0x66, 0xc1, 0x8f, 0x21, 0x5f, 0x6f, 0xbf, 0xe8,
2728
-	0xb4, 0x7b, 0x5a, 0x43, 0xc8, 0xde, 0xc0, 0x12, 0x45, 0x71, 0x05, 0x40, 0x6b, 0x37, 0x92, 0x0c,
2729
-	0x73, 0x91, 0x31, 0xf9, 0x7a, 0x92, 0x4b, 0x5a, 0xba, 0x13, 0x1b, 0x93, 0x97, 0xad, 0x26, 0xfe,
2730
-	0x7e, 0x5d, 0xda, 0xfa, 0xeb, 0xba, 0x84, 0xbe, 0x59, 0x94, 0xd0, 0xeb, 0x45, 0x09, 0xfd, 0xba,
2731
-	0x28, 0xa1, 0x3f, 0x17, 0x25, 0x74, 0x9e, 0x63, 0x7f, 0x9d, 0x9e, 0xfe, 0x1d, 0x00, 0x00, 0xff,
2732
-	0xff, 0x92, 0x82, 0xdb, 0x1a, 0x6e, 0x09, 0x00, 0x00,
2674
+	0x14, 0xc7, 0x7b, 0xf3, 0xd1, 0x26, 0xa7, 0x29, 0x35, 0x77, 0x3a, 0x53, 0xd7, 0x03, 0x89, 0x31,
2675
+	0x33, 0x55, 0xa6, 0x82, 0x14, 0x75, 0x9e, 0xa0, 0x49, 0x2c, 0xc8, 0x4c, 0xc6, 0x89, 0xdc, 0xa4,
2676
+	0x88, 0x55, 0x74, 0x5b, 0x5f, 0x52, 0xab, 0x8e, 0x6d, 0xd9, 0x4e, 0x50, 0x56, 0x20, 0x56, 0xa3,
2677
+	0x2c, 0x78, 0x83, 0xac, 0x86, 0x35, 0x0f, 0x80, 0x58, 0xb2, 0x98, 0x05, 0x0b, 0xd8, 0x21, 0x16,
2678
+	0x11, 0xcd, 0x13, 0xf0, 0x08, 0xc8, 0xd7, 0x76, 0x72, 0x93, 0x56, 0x23, 0x21, 0x46, 0x82, 0x4d,
2679
+	0x72, 0x3f, 0x7e, 0x39, 0x3e, 0xe7, 0xef, 0xff, 0xb9, 0x37, 0x70, 0x60, 0xd3, 0xe0, 0x2b, 0xc7,
2680
+	0xbb, 0x36, 0x2e, 0x8e, 0x17, 0xa3, 0x8a, 0xeb, 0x39, 0x81, 0x83, 0xf3, 0x8b, 0x05, 0x69, 0xaf,
2681
+	0xef, 0xf4, 0x1d, 0xb6, 0x7a, 0x1c, 0x8e, 0x22, 0x40, 0x69, 0xc1, 0xce, 0xa7, 0x8e, 0xef, 0x9b,
2682
+	0xee, 0x0b, 0xea, 0xfb, 0xa4, 0x4f, 0xf1, 0x11, 0x64, 0x82, 0xb1, 0x4b, 0x45, 0x24, 0xa3, 0xf2,
2683
+	0x3b, 0x27, 0x0f, 0x2a, 0xcb, 0x88, 0x31, 0xd1, 0x19, 0xbb, 0x54, 0x67, 0x0c, 0xc6, 0x90, 0x31,
2684
+	0x48, 0x40, 0xc4, 0x94, 0x8c, 0xca, 0x05, 0x9d, 0x8d, 0x95, 0x57, 0x29, 0xc8, 0x6b, 0x8e, 0x41,
2685
+	0xd5, 0x11, 0xb5, 0x03, 0xfc, 0xf1, 0x4a, 0xb4, 0x03, 0x2e, 0xda, 0x82, 0xa9, 0x70, 0x01, 0x1b,
2686
+	0xb0, 0x69, 0xf5, 0x02, 0x73, 0x40, 0x59, 0xc8, 0x4c, 0xf5, 0xe4, 0xf5, 0xac, 0xb4, 0xf1, 0xc7,
2687
+	0xac, 0x74, 0xd4, 0x37, 0x83, 0xab, 0xe1, 0x45, 0xe5, 0xd2, 0x19, 0x1c, 0x5f, 0x11, 0xff, 0xca,
2688
+	0xbc, 0x74, 0x3c, 0xf7, 0xd8, 0xa7, 0xde, 0x97, 0xec, 0xa3, 0xd2, 0x24, 0x03, 0xd7, 0xf1, 0x82,
2689
+	0x8e, 0x39, 0xa0, 0x7a, 0xd6, 0x0a, 0xbf, 0xf0, 0x43, 0xc8, 0xdb, 0x8e, 0x41, 0x7b, 0x36, 0x19,
2690
+	0x50, 0x31, 0x2d, 0xa3, 0x72, 0x5e, 0xcf, 0x85, 0x0b, 0x1a, 0x19, 0x50, 0xe5, 0x6b, 0xc8, 0x84,
2691
+	0x4f, 0xc5, 0x8f, 0x61, 0xab, 0xa1, 0x9d, 0x9f, 0x36, 0x1b, 0x75, 0x61, 0x43, 0x12, 0x27, 0x53,
2692
+	0x79, 0x6f, 0x91, 0x56, 0xb8, 0xdf, 0xb0, 0x47, 0xc4, 0x32, 0x0d, 0x5c, 0x82, 0xcc, 0xb3, 0x56,
2693
+	0x43, 0x13, 0x90, 0x74, 0x7f, 0x32, 0x95, 0xdf, 0x5d, 0x61, 0x9e, 0x39, 0xa6, 0x8d, 0x3f, 0x80,
2694
+	0x6c, 0x53, 0x3d, 0x3d, 0x57, 0x85, 0x94, 0xf4, 0x60, 0x32, 0x95, 0xf1, 0x0a, 0xd1, 0xa4, 0x64,
2695
+	0x44, 0xa5, 0xc2, 0xcb, 0x57, 0xc5, 0x8d, 0x1f, 0xbf, 0x2f, 0xb2, 0x07, 0x2b, 0x37, 0x29, 0x28,
2696
+	0x68, 0x91, 0x16, 0x91, 0x50, 0x9f, 0xac, 0x08, 0xf5, 0x1e, 0x2f, 0x14, 0x87, 0xfd, 0x07, 0x5a,
2697
+	0xe1, 0x8f, 0x00, 0xe2, 0x64, 0x7a, 0xa6, 0x21, 0x66, 0xc2, 0xdd, 0xea, 0xce, 0x7c, 0x56, 0xca,
2698
+	0xc7, 0x89, 0x35, 0xea, 0x7a, 0xe2, 0xb2, 0x86, 0xa1, 0xbc, 0x44, 0xb1, 0xb4, 0x65, 0x5e, 0xda,
2699
+	0x87, 0x93, 0xa9, 0xbc, 0xcf, 0x17, 0xc2, 0xab, 0xab, 0x2c, 0xd4, 0x8d, 0xde, 0xc0, 0x1a, 0xc6,
2700
+	0x04, 0x7e, 0xb4, 0x14, 0xf8, 0x60, 0x32, 0x95, 0xef, 0xaf, 0x43, 0x77, 0x69, 0xfc, 0x0b, 0x5a,
2701
+	0x6a, 0x6c, 0x07, 0xde, 0x78, 0xad, 0x12, 0xf4, 0xe6, 0x4a, 0xde, 0xa6, 0xbe, 0x4f, 0x6e, 0xe9,
2702
+	0x5b, 0x2d, 0xcc, 0x67, 0xa5, 0x9c, 0x16, 0x6b, 0xcc, 0xa9, 0x2d, 0xc2, 0x96, 0x45, 0xc9, 0xc8,
2703
+	0xb4, 0xfb, 0x4c, 0xea, 0x9c, 0x9e, 0x4c, 0x95, 0x9f, 0x10, 0xec, 0xc6, 0x89, 0xb6, 0x87, 0xfe,
2704
+	0x55, 0x7b, 0x68, 0x59, 0x5c, 0x8e, 0xe8, 0xdf, 0xe6, 0xf8, 0x14, 0x72, 0x71, 0xed, 0xbe, 0x98,
2705
+	0x92, 0xd3, 0xe5, 0xed, 0x93, 0xfd, 0x3b, 0x4c, 0x18, 0xea, 0xa8, 0x2f, 0xc0, 0x7f, 0x50, 0x98,
2706
+	0xf2, 0x5d, 0x06, 0xa0, 0x43, 0x2e, 0xac, 0xf8, 0x60, 0xa8, 0xac, 0xf8, 0x5d, 0xe2, 0x1e, 0xb5,
2707
+	0x84, 0xfe, 0xf7, 0x6e, 0xc7, 0xef, 0x03, 0x04, 0x61, 0xba, 0x51, 0xac, 0x2c, 0x8b, 0x95, 0x67,
2708
+	0x2b, 0x2c, 0x98, 0x00, 0xe9, 0x6b, 0x3a, 0x16, 0x37, 0xd9, 0x7a, 0x38, 0xc4, 0x7b, 0x90, 0x1d,
2709
+	0x11, 0x6b, 0x48, 0xc5, 0x2d, 0x76, 0x64, 0x46, 0x13, 0x5c, 0x05, 0xec, 0x51, 0xdf, 0x34, 0x86,
2710
+	0xc4, 0xea, 0x79, 0x94, 0xb8, 0x51, 0xa1, 0x39, 0x19, 0x95, 0xb3, 0xd5, 0xbd, 0xf9, 0xac, 0x24,
2711
+	0xe8, 0xf1, 0xae, 0x4e, 0x89, 0xcb, 0x4a, 0x11, 0xbc, 0xb5, 0x15, 0xe5, 0x87, 0xa4, 0xf1, 0x0e,
2712
+	0xf9, 0xc6, 0x63, 0xcd, 0xb2, 0x54, 0x94, 0x6f, 0xbb, 0x47, 0xb0, 0x59, 0xd3, 0xd5, 0xd3, 0x8e,
2713
+	0x9a, 0x34, 0xde, 0x2a, 0x56, 0xf3, 0x28, 0x09, 0x68, 0x48, 0x75, 0xdb, 0xf5, 0x90, 0x4a, 0xdd,
2714
+	0x45, 0x75, 0x5d, 0x23, 0xa6, 0xea, 0x6a, 0x53, 0xed, 0xa8, 0x42, 0xfa, 0x2e, 0xaa, 0x4e, 0x2d,
2715
+	0x1a, 0xac, 0xb7, 0xe7, 0x6f, 0x08, 0x76, 0xab, 0x43, 0xeb, 0xfa, 0x6c, 0x6c, 0x5f, 0x26, 0x97,
2716
+	0xcf, 0x5b, 0xf4, 0xb3, 0x0c, 0xdb, 0x43, 0xdb, 0x77, 0x2c, 0xf3, 0xd2, 0x0c, 0xa8, 0xc1, 0x5c,
2717
+	0x93, 0xd3, 0xf9, 0xa5, 0x37, 0xfb, 0x40, 0xe2, 0xda, 0x21, 0x23, 0xa7, 0xd9, 0x5e, 0xe2, 0x7a,
2718
+	0x11, 0xb6, 0x5c, 0x32, 0xb6, 0x1c, 0x62, 0xb0, 0x57, 0x5e, 0xd0, 0x93, 0xa9, 0xf2, 0x2d, 0x82,
2719
+	0xdd, 0x9a, 0x33, 0x70, 0x9d, 0xa1, 0x6d, 0x24, 0x35, 0xd5, 0x21, 0x37, 0x88, 0x86, 0xbe, 0x88,
2720
+	0x58, 0x63, 0x95, 0x39, 0xb7, 0xaf, 0xd1, 0x95, 0x33, 0x73, 0xe0, 0x5a, 0x34, 0x9e, 0xe9, 0x8b,
2721
+	0x5f, 0x4a, 0x4f, 0x60, 0x67, 0x65, 0x2b, 0x4c, 0xa2, 0x1d, 0x27, 0x81, 0x56, 0x92, 0x38, 0xfa,
2722
+	0x39, 0x05, 0xdb, 0xdc, 0x5d, 0x8d, 0x3f, 0xe4, 0x0d, 0xc1, 0xae, 0x27, 0x6e, 0x37, 0x71, 0x43,
2723
+	0x05, 0x76, 0x34, 0xb5, 0xf3, 0x79, 0x4b, 0x7f, 0xde, 0x53, 0xcf, 0x55, 0xad, 0x23, 0xa0, 0xe8,
2724
+	0xd0, 0xe6, 0xd0, 0x95, 0xfb, 0xea, 0x08, 0xb6, 0x3b, 0xa7, 0xd5, 0xa6, 0x1a, 0xd3, 0xf1, 0xb1,
2725
+	0xcc, 0xd1, 0x5c, 0xaf, 0x1f, 0x42, 0xbe, 0xdd, 0x3d, 0xfb, 0xac, 0xd7, 0xee, 0x36, 0x9b, 0x42,
2726
+	0x5a, 0xda, 0x9f, 0x4c, 0xe5, 0x7b, 0x1c, 0xb9, 0x38, 0xcd, 0x0e, 0x21, 0x5f, 0xed, 0x36, 0x9f,
2727
+	0xf7, 0xce, 0xbe, 0xd0, 0x6a, 0x42, 0xe6, 0x16, 0x97, 0x98, 0x05, 0x3f, 0x86, 0x5c, 0xad, 0xf5,
2728
+	0xa2, 0xdd, 0xea, 0x6a, 0x75, 0x21, 0x7b, 0x0b, 0x4b, 0x14, 0xc5, 0x65, 0x00, 0xad, 0x55, 0x4f,
2729
+	0x32, 0xdc, 0x8c, 0x8c, 0xc9, 0xd7, 0x93, 0x5c, 0xd2, 0xd2, 0xbd, 0xd8, 0x98, 0xbc, 0x6c, 0x55,
2730
+	0xf1, 0xf7, 0x9b, 0xe2, 0xc6, 0x5f, 0x37, 0x45, 0xf4, 0xcd, 0xbc, 0x88, 0x5e, 0xcf, 0x8b, 0xe8,
2731
+	0xd7, 0x79, 0x11, 0xfd, 0x39, 0x2f, 0xa2, 0x8b, 0x4d, 0xf6, 0xd7, 0xe9, 0xe9, 0xdf, 0x01, 0x00,
2732
+	0x00, 0xff, 0xff, 0x02, 0x9d, 0x53, 0x72, 0x78, 0x09, 0x00, 0x00,
2733 2733
 }
... ...
@@ -358,16 +358,20 @@ func (n *networkNamespace) loopbackUp() error {
358 358
 	return n.nlHandle.LinkSetUp(iface)
359 359
 }
360 360
 
361
-func (n *networkNamespace) AddLoopbackAliasIP(ip *net.IPNet) error {
362
-	iface, err := n.nlHandle.LinkByName("lo")
361
+func (n *networkNamespace) GetLoopbackIfaceName() string {
362
+	return "lo"
363
+}
364
+
365
+func (n *networkNamespace) AddAliasIP(ifName string, ip *net.IPNet) error {
366
+	iface, err := n.nlHandle.LinkByName(ifName)
363 367
 	if err != nil {
364 368
 		return err
365 369
 	}
366 370
 	return n.nlHandle.AddrAdd(iface, &netlink.Addr{IPNet: ip})
367 371
 }
368 372
 
369
-func (n *networkNamespace) RemoveLoopbackAliasIP(ip *net.IPNet) error {
370
-	iface, err := n.nlHandle.LinkByName("lo")
373
+func (n *networkNamespace) RemoveAliasIP(ifName string, ip *net.IPNet) error {
374
+	iface, err := n.nlHandle.LinkByName(ifName)
371 375
 	if err != nil {
372 376
 		return err
373 377
 	}
... ...
@@ -32,11 +32,14 @@ type Sandbox interface {
32 32
 	// Unset the previously set default IPv6 gateway in the sandbox
33 33
 	UnsetGatewayIPv6() error
34 34
 
35
-	// AddLoopbackAliasIP adds the passed IP address to the sandbox loopback interface
36
-	AddLoopbackAliasIP(ip *net.IPNet) error
35
+	// GetLoopbackIfaceName returns the name of the loopback interface
36
+	GetLoopbackIfaceName() string
37 37
 
38
-	// RemoveLoopbackAliasIP removes the passed IP address from the sandbox loopback interface
39
-	RemoveLoopbackAliasIP(ip *net.IPNet) error
38
+	// AddAliasIP adds the passed IP address to the named interface
39
+	AddAliasIP(ifName string, ip *net.IPNet) error
40
+
41
+	// RemoveAliasIP removes the passed IP address from the named interface
42
+	RemoveAliasIP(ifName string, ip *net.IPNet) error
40 43
 
41 44
 	// Add a static route to the sandbox.
42 45
 	AddStaticRoute(*types.StaticRoute) error
... ...
@@ -740,15 +740,8 @@ func releaseOSSboxResources(osSbox osl.Sandbox, ep *endpoint) {
740 740
 
741 741
 	ep.Lock()
742 742
 	joinInfo := ep.joinInfo
743
-	vip := ep.virtualIP
744 743
 	ep.Unlock()
745 744
 
746
-	if len(vip) != 0 {
747
-		if err := osSbox.RemoveLoopbackAliasIP(&net.IPNet{IP: vip, Mask: net.CIDRMask(32, 32)}); err != nil {
748
-			logrus.Warnf("Remove virtual IP %v failed: %v", vip, err)
749
-		}
750
-	}
751
-
752 745
 	if joinInfo == nil {
753 746
 		return
754 747
 	}
... ...
@@ -861,13 +854,6 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
861 861
 		}
862 862
 	}
863 863
 
864
-	if len(ep.virtualIP) != 0 {
865
-		err := sb.osSbox.AddLoopbackAliasIP(&net.IPNet{IP: ep.virtualIP, Mask: net.CIDRMask(32, 32)})
866
-		if err != nil {
867
-			return fmt.Errorf("failed to add virtual IP %v: %v", ep.virtualIP, err)
868
-		}
869
-	}
870
-
871 864
 	if joinInfo != nil {
872 865
 		// Set up non-interface routes.
873 866
 		for _, r := range joinInfo.StaticRoutes {
... ...
@@ -893,7 +879,7 @@ func (sb *sandbox) populateNetworkResources(ep *endpoint) error {
893 893
 	// information including gateway and other routes so that
894 894
 	// loadbalancers are populated all the network state is in
895 895
 	// place in the sandbox.
896
-	sb.populateLoadbalancers(ep)
896
+	sb.populateLoadBalancers(ep)
897 897
 
898 898
 	// Only update the store if we did not come here as part of
899 899
 	// sandbox delete. If we came here as part of delete then do
... ...
@@ -225,6 +225,13 @@ func makeServiceCleanupFunc(c *controller, s *service, nID, eID string, vip net.
225 225
 func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName string, vip net.IP, ingressPorts []*PortConfig, serviceAliases, taskAliases []string, ip net.IP, method string) error {
226 226
 	var addService bool
227 227
 
228
+	// Failure to lock the network ID on add can result in racing
229
+	// racing against network deletion resulting in inconsistent
230
+	// state in the c.serviceBindings map and it's sub-maps. Also,
231
+	// always lock network ID before services to avoid deadlock.
232
+	c.networkLocker.Lock(nID)
233
+	defer c.networkLocker.Unlock(nID)
234
+
228 235
 	n, err := c.NetworkByID(nID)
229 236
 	if err != nil {
230 237
 		return err
... ...
@@ -289,11 +296,8 @@ func (c *controller) addServiceBinding(svcName, svcID, nID, eID, containerName s
289 289
 		logrus.Warnf("addServiceBinding %s possible transient state ok:%t entries:%d set:%t %s", eID, ok, entries, b, setStr)
290 290
 	}
291 291
 
292
-	// Add loadbalancer service and backend in all sandboxes in
293
-	// the network only if vip is valid.
294
-	if len(vip) != 0 {
295
-		n.(*network).addLBBackend(ip, vip, lb, ingressPorts)
296
-	}
292
+	// Add loadbalancer service and backend to the network
293
+	n.(*network).addLBBackend(ip, lb)
297 294
 
298 295
 	// Add the appropriate name resolutions
299 296
 	c.addEndpointNameResolution(svcName, svcID, nID, eID, containerName, vip, serviceAliases, taskAliases, ip, addService, "addServiceBinding")
... ...
@@ -307,11 +311,6 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
307 307
 
308 308
 	var rmService bool
309 309
 
310
-	n, err := c.NetworkByID(nID)
311
-	if err != nil {
312
-		return err
313
-	}
314
-
315 310
 	skey := serviceKey{
316 311
 		id:    svcID,
317 312
 		ports: portConfigs(ingressPorts).String(),
... ...
@@ -368,8 +367,15 @@ func (c *controller) rmServiceBinding(svcName, svcID, nID, eID, containerName st
368 368
 
369 369
 	// Remove loadbalancer service(if needed) and backend in all
370 370
 	// sandboxes in the network only if the vip is valid.
371
-	if len(vip) != 0 && entries == 0 {
372
-		n.(*network).rmLBBackend(ip, vip, lb, ingressPorts, rmService, fullRemove)
371
+	if entries == 0 {
372
+		// The network may well have been deleted before the last
373
+		// of the service bindings.  That's ok, because removing
374
+		// the network sandbox implicitly removes the backend
375
+		// service bindings.
376
+		n, err := c.NetworkByID(nID)
377
+		if err == nil {
378
+			n.(*network).rmLBBackend(ip, lb, rmService, fullRemove)
379
+		}
373 380
 	}
374 381
 
375 382
 	// Delete the name resolutions
... ...
@@ -30,40 +30,9 @@ func init() {
30 30
 	reexec.Register("redirecter", redirecter)
31 31
 }
32 32
 
33
-// Get all loadbalancers on this network that is currently discovered
34
-// on this node.
35
-func (n *network) connectedLoadbalancers() []*loadBalancer {
36
-	c := n.getController()
37
-
38
-	c.Lock()
39
-	serviceBindings := make([]*service, 0, len(c.serviceBindings))
40
-	for _, s := range c.serviceBindings {
41
-		serviceBindings = append(serviceBindings, s)
42
-	}
43
-	c.Unlock()
44
-
45
-	var lbs []*loadBalancer
46
-	for _, s := range serviceBindings {
47
-		s.Lock()
48
-		// Skip the serviceBindings that got deleted
49
-		if s.deleted {
50
-			s.Unlock()
51
-			continue
52
-		}
53
-		if lb, ok := s.loadBalancers[n.ID()]; ok {
54
-			lbs = append(lbs, lb)
55
-		}
56
-		s.Unlock()
57
-	}
58
-
59
-	return lbs
60
-}
61
-
62 33
 // Populate all loadbalancers on the network that the passed endpoint
63 34
 // belongs to, into this sandbox.
64
-func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
65
-	var gwIP net.IP
66
-
35
+func (sb *sandbox) populateLoadBalancers(ep *endpoint) {
67 36
 	// This is an interface less endpoint. Nothing to do.
68 37
 	if ep.Iface() == nil {
69 38
 		return
... ...
@@ -77,96 +46,64 @@ func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
77 77
 			logrus.Errorf("Failed to add redirect rules for ep %s (%s): %v", ep.Name(), ep.ID()[0:7], err)
78 78
 		}
79 79
 	}
80
+}
80 81
 
81
-	if sb.ingress {
82
-		// For the ingress sandbox if this is not gateway
83
-		// endpoint do nothing.
84
-		if ep != sb.getGatewayEndpoint() {
85
-			return
86
-		}
87
-
88
-		// This is the gateway endpoint. Now get the ingress
89
-		// network and plumb the loadbalancers.
90
-		gwIP = ep.Iface().Address().IP
91
-		for _, ep := range sb.getConnectedEndpoints() {
92
-			if !ep.endpointInGWNetwork() {
93
-				n = ep.getNetwork()
94
-				eIP = ep.Iface().Address()
95
-			}
82
+func (n *network) findLBEndpointSandbox() (*endpoint, *sandbox, error) {
83
+	// TODO: get endpoint from store?  See EndpointInfo()
84
+	var ep *endpoint
85
+	// Find this node's LB sandbox endpoint:  there should be exactly one
86
+	for _, e := range n.Endpoints() {
87
+		epi := e.Info()
88
+		if epi != nil && epi.LoadBalancer() {
89
+			ep = e.(*endpoint)
90
+			break
96 91
 		}
97 92
 	}
98
-
99
-	for _, lb := range n.connectedLoadbalancers() {
100
-		// Skip if vip is not valid.
101
-		if len(lb.vip) == 0 {
102
-			continue
103
-		}
104
-
105
-		lb.service.Lock()
106
-		for _, be := range lb.backEnds {
107
-			if !be.disabled {
108
-				sb.addLBBackend(be.ip, lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, gwIP, n.ingress)
109
-			}
110
-		}
111
-		lb.service.Unlock()
93
+	if ep == nil {
94
+		return nil, nil, fmt.Errorf("Unable to find load balancing endpoint for network %s", n.ID())
112 95
 	}
96
+	// Get the load balancer sandbox itself as well
97
+	sb, ok := ep.getSandbox()
98
+	if !ok {
99
+		return nil, nil, fmt.Errorf("Unable to get sandbox for %s(%s) in for %s", ep.Name(), ep.ID(), n.ID())
100
+	}
101
+	ep = sb.getEndpoint(ep.ID())
102
+	if ep == nil {
103
+		return nil, nil, fmt.Errorf("Load balancing endpoint %s(%s) removed from %s", ep.Name(), ep.ID(), n.ID())
104
+	}
105
+	return ep, sb, nil
113 106
 }
114 107
 
115
-// Add loadbalancer backend to all sandboxes which has a connection to
116
-// this network. If needed add the service as well.
117
-func (n *network) addLBBackend(ip, vip net.IP, lb *loadBalancer, ingressPorts []*PortConfig) {
118
-	n.WalkEndpoints(func(e Endpoint) bool {
119
-		ep := e.(*endpoint)
120
-		if sb, ok := ep.getSandbox(); ok {
121
-			if !sb.isEndpointPopulated(ep) {
122
-				return false
123
-			}
124
-
125
-			var gwIP net.IP
126
-			if ep := sb.getGatewayEndpoint(); ep != nil {
127
-				gwIP = ep.Iface().Address().IP
128
-			}
129
-
130
-			sb.addLBBackend(ip, vip, lb.fwMark, ingressPorts, ep.Iface().Address(), gwIP, n.ingress)
131
-		}
132
-
133
-		return false
134
-	})
135
-}
136
-
137
-// Remove loadbalancer backend from all sandboxes which has a
138
-// connection to this network. If needed remove the service entry as
139
-// well, as specified by the rmService bool.
140
-func (n *network) rmLBBackend(ip, vip net.IP, lb *loadBalancer, ingressPorts []*PortConfig, rmService bool, fullRemove bool) {
141
-	n.WalkEndpoints(func(e Endpoint) bool {
142
-		ep := e.(*endpoint)
143
-		if sb, ok := ep.getSandbox(); ok {
144
-			if !sb.isEndpointPopulated(ep) {
145
-				return false
146
-			}
147
-
148
-			var gwIP net.IP
149
-			if ep := sb.getGatewayEndpoint(); ep != nil {
150
-				gwIP = ep.Iface().Address().IP
151
-			}
152
-
153
-			sb.rmLBBackend(ip, vip, lb.fwMark, ingressPorts, ep.Iface().Address(), gwIP, rmService, fullRemove, n.ingress)
108
+// Searches the OS sandbox for the name of the endpoint interface
109
+// within the sandbox.   This is required for adding/removing IP
110
+// aliases to the interface.
111
+func findIfaceDstName(sb *sandbox, ep *endpoint) string {
112
+	srcName := ep.Iface().SrcName()
113
+	for _, i := range sb.osSbox.Info().Interfaces() {
114
+		if i.SrcName() == srcName {
115
+			return i.DstName()
154 116
 		}
155
-
156
-		return false
157
-	})
117
+	}
118
+	return ""
158 119
 }
159 120
 
160
-// Add loadbalancer backend into one connected sandbox.
161
-func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, gwIP net.IP, isIngressNetwork bool) {
162
-	if sb.osSbox == nil {
121
+// Add loadbalancer backend to the loadbalncer sandbox for the network.
122
+// If needed add the service as well.
123
+func (n *network) addLBBackend(ip net.IP, lb *loadBalancer) {
124
+	if len(lb.vip) == 0 {
163 125
 		return
164 126
 	}
165
-
166
-	if isIngressNetwork && !sb.ingress {
127
+	ep, sb, err := n.findLBEndpointSandbox()
128
+	if err != nil {
129
+		logrus.Errorf("addLBBackend %s/%s: %v", n.ID(), n.Name(), err)
130
+		return
131
+	}
132
+	if sb.osSbox == nil {
167 133
 		return
168 134
 	}
169 135
 
136
+	eIP := ep.Iface().Address()
137
+
170 138
 	i, err := ipvs.New(sb.Key())
171 139
 	if err != nil {
172 140
 		logrus.Errorf("Failed to create an ipvs handle for sbox %s (%s,%s) for lb addition: %v", sb.ID()[0:7], sb.ContainerID()[0:7], sb.Key(), err)
... ...
@@ -176,28 +113,43 @@ func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*P
176 176
 
177 177
 	s := &ipvs.Service{
178 178
 		AddressFamily: nl.FAMILY_V4,
179
-		FWMark:        fwMark,
179
+		FWMark:        lb.fwMark,
180 180
 		SchedName:     ipvs.RoundRobin,
181 181
 	}
182 182
 
183 183
 	if !i.IsServicePresent(s) {
184
-		var filteredPorts []*PortConfig
184
+		// Add IP alias for the VIP to the endpoint
185
+		ifName := findIfaceDstName(sb, ep)
186
+		if ifName == "" {
187
+			logrus.Errorf("Failed find interface name for endpoint %s(%s) to create LB alias", ep.ID(), ep.Name())
188
+			return
189
+		}
190
+		err := sb.osSbox.AddAliasIP(ifName, &net.IPNet{IP: lb.vip, Mask: net.CIDRMask(32, 32)})
191
+		if err != nil {
192
+			logrus.Errorf("Failed add IP alias %s to network %s LB endpoint interface %s: %v", lb.vip, n.ID(), ifName, err)
193
+			return
194
+		}
195
+
185 196
 		if sb.ingress {
186
-			filteredPorts = filterPortConfigs(ingressPorts, false)
197
+			var gwIP net.IP
198
+			if ep := sb.getGatewayEndpoint(); ep != nil {
199
+				gwIP = ep.Iface().Address().IP
200
+			}
201
+			filteredPorts := filterPortConfigs(lb.service.ingressPorts, false)
187 202
 			if err := programIngress(gwIP, filteredPorts, false); err != nil {
188 203
 				logrus.Errorf("Failed to add ingress: %v", err)
189 204
 				return
190 205
 			}
191 206
 		}
192 207
 
193
-		logrus.Debugf("Creating service for vip %s fwMark %d ingressPorts %#v in sbox %s (%s)", vip, fwMark, ingressPorts, sb.ID()[0:7], sb.ContainerID()[0:7])
194
-		if err := invokeFWMarker(sb.Key(), vip, fwMark, ingressPorts, eIP, false); err != nil {
208
+		logrus.Debugf("Creating service for vip %s fwMark %d ingressPorts %#v in sbox %s (%s)", lb.vip, lb.fwMark, lb.service.ingressPorts, sb.ID()[0:7], sb.ContainerID()[0:7])
209
+		if err := invokeFWMarker(sb.Key(), lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, false); err != nil {
195 210
 			logrus.Errorf("Failed to add firewall mark rule in sbox %s (%s): %v", sb.ID()[0:7], sb.ContainerID()[0:7], err)
196 211
 			return
197 212
 		}
198 213
 
199 214
 		if err := i.NewService(s); err != nil && err != syscall.EEXIST {
200
-			logrus.Errorf("Failed to create a new service for vip %s fwmark %d in sbox %s (%s): %v", vip, fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
215
+			logrus.Errorf("Failed to create a new service for vip %s fwmark %d in sbox %s (%s): %v", lb.vip, lb.fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
201 216
 			return
202 217
 		}
203 218
 	}
... ...
@@ -212,20 +164,29 @@ func (sb *sandbox) addLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*P
212 212
 	// destination.
213 213
 	s.SchedName = ""
214 214
 	if err := i.NewDestination(s, d); err != nil && err != syscall.EEXIST {
215
-		logrus.Errorf("Failed to create real server %s for vip %s fwmark %d in sbox %s (%s): %v", ip, vip, fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
215
+		logrus.Errorf("Failed to create real server %s for vip %s fwmark %d in sbox %s (%s): %v", ip, lb.vip, lb.fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
216 216
 	}
217 217
 }
218 218
 
219
-// Remove loadbalancer backend from one connected sandbox.
220
-func (sb *sandbox) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*PortConfig, eIP *net.IPNet, gwIP net.IP, rmService bool, fullRemove bool, isIngressNetwork bool) {
221
-	if sb.osSbox == nil {
219
+// Remove loadbalancer backend the load balancing endpoint for this
220
+// network. If 'rmService' is true, then remove the service entry as well.
221
+// If 'fullRemove' is true then completely remove the entry, otherwise
222
+// just deweight it for now.
223
+func (n *network) rmLBBackend(ip net.IP, lb *loadBalancer, rmService bool, fullRemove bool) {
224
+	if len(lb.vip) == 0 {
222 225
 		return
223 226
 	}
224
-
225
-	if isIngressNetwork && !sb.ingress {
227
+	ep, sb, err := n.findLBEndpointSandbox()
228
+	if err != nil {
229
+		logrus.Debugf("rmLBBackend for %s/%s: %v -- probably transient state", n.ID(), n.Name(), err)
230
+		return
231
+	}
232
+	if sb.osSbox == nil {
226 233
 		return
227 234
 	}
228 235
 
236
+	eIP := ep.Iface().Address()
237
+
229 238
 	i, err := ipvs.New(sb.Key())
230 239
 	if err != nil {
231 240
 		logrus.Errorf("Failed to create an ipvs handle for sbox %s (%s,%s) for lb removal: %v", sb.ID()[0:7], sb.ContainerID()[0:7], sb.Key(), err)
... ...
@@ -235,7 +196,7 @@ func (sb *sandbox) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po
235 235
 
236 236
 	s := &ipvs.Service{
237 237
 		AddressFamily: nl.FAMILY_V4,
238
-		FWMark:        fwMark,
238
+		FWMark:        lb.fwMark,
239 239
 	}
240 240
 
241 241
 	d := &ipvs.Destination{
... ...
@@ -246,32 +207,46 @@ func (sb *sandbox) rmLBBackend(ip, vip net.IP, fwMark uint32, ingressPorts []*Po
246 246
 
247 247
 	if fullRemove {
248 248
 		if err := i.DelDestination(s, d); err != nil && err != syscall.ENOENT {
249
-			logrus.Errorf("Failed to delete real server %s for vip %s fwmark %d in sbox %s (%s): %v", ip, vip, fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
249
+			logrus.Errorf("Failed to delete real server %s for vip %s fwmark %d in sbox %s (%s): %v", ip, lb.vip, lb.fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
250 250
 		}
251 251
 	} else {
252 252
 		d.Weight = 0
253 253
 		if err := i.UpdateDestination(s, d); err != nil && err != syscall.ENOENT {
254
-			logrus.Errorf("Failed to set LB weight of real server %s to 0 for vip %s fwmark %d in sbox %s (%s): %v", ip, vip, fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
254
+			logrus.Errorf("Failed to set LB weight of real server %s to 0 for vip %s fwmark %d in sbox %s (%s): %v", ip, lb.vip, lb.fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
255 255
 		}
256 256
 	}
257 257
 
258 258
 	if rmService {
259 259
 		s.SchedName = ipvs.RoundRobin
260 260
 		if err := i.DelService(s); err != nil && err != syscall.ENOENT {
261
-			logrus.Errorf("Failed to delete service for vip %s fwmark %d in sbox %s (%s): %v", vip, fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
261
+			logrus.Errorf("Failed to delete service for vip %s fwmark %d in sbox %s (%s): %v", lb.vip, lb.fwMark, sb.ID()[0:7], sb.ContainerID()[0:7], err)
262 262
 		}
263 263
 
264
-		var filteredPorts []*PortConfig
265 264
 		if sb.ingress {
266
-			filteredPorts = filterPortConfigs(ingressPorts, true)
265
+			var gwIP net.IP
266
+			if ep := sb.getGatewayEndpoint(); ep != nil {
267
+				gwIP = ep.Iface().Address().IP
268
+			}
269
+			filteredPorts := filterPortConfigs(lb.service.ingressPorts, true)
267 270
 			if err := programIngress(gwIP, filteredPorts, true); err != nil {
268 271
 				logrus.Errorf("Failed to delete ingress: %v", err)
269 272
 			}
270 273
 		}
271 274
 
272
-		if err := invokeFWMarker(sb.Key(), vip, fwMark, ingressPorts, eIP, true); err != nil {
275
+		if err := invokeFWMarker(sb.Key(), lb.vip, lb.fwMark, lb.service.ingressPorts, eIP, true); err != nil {
273 276
 			logrus.Errorf("Failed to delete firewall mark rule in sbox %s (%s): %v", sb.ID()[0:7], sb.ContainerID()[0:7], err)
274 277
 		}
278
+
279
+		// Remove IP alias from the VIP to the endpoint
280
+		ifName := findIfaceDstName(sb, ep)
281
+		if ifName == "" {
282
+			logrus.Errorf("Failed find interface name for endpoint %s(%s) to create LB alias", ep.ID(), ep.Name())
283
+			return
284
+		}
285
+		err := sb.osSbox.RemoveAliasIP(ifName, &net.IPNet{IP: lb.vip, Mask: net.CIDRMask(32, 32)})
286
+		if err != nil {
287
+			logrus.Errorf("Failed add IP alias %s to network %s LB endpoint interface %s: %v", lb.vip, n.ID(), ifName, err)
288
+		}
275 289
 	}
276 290
 }
277 291
 
... ...
@@ -617,7 +592,7 @@ func fwMarker() {
617 617
 		ingressPorts, err = readPortsFromFile(os.Args[5])
618 618
 		if err != nil {
619 619
 			logrus.Errorf("Failed reading ingress ports file: %v", err)
620
-			os.Exit(6)
620
+			os.Exit(2)
621 621
 		}
622 622
 	}
623 623
 
... ...
@@ -625,7 +600,7 @@ func fwMarker() {
625 625
 	fwMark, err := strconv.ParseUint(os.Args[3], 10, 32)
626 626
 	if err != nil {
627 627
 		logrus.Errorf("bad fwmark value(%s) passed: %v", os.Args[3], err)
628
-		os.Exit(2)
628
+		os.Exit(3)
629 629
 	}
630 630
 	addDelOpt := os.Args[4]
631 631
 
... ...
@@ -639,20 +614,20 @@ func fwMarker() {
639 639
 	ns, err := netns.GetFromPath(os.Args[1])
640 640
 	if err != nil {
641 641
 		logrus.Errorf("failed get network namespace %q: %v", os.Args[1], err)
642
-		os.Exit(3)
642
+		os.Exit(4)
643 643
 	}
644 644
 	defer ns.Close()
645 645
 
646 646
 	if err := netns.Set(ns); err != nil {
647 647
 		logrus.Errorf("setting into container net ns %v failed, %v", os.Args[1], err)
648
-		os.Exit(4)
648
+		os.Exit(5)
649 649
 	}
650 650
 
651 651
 	if addDelOpt == "-A" {
652 652
 		eIP, subnet, err := net.ParseCIDR(os.Args[6])
653 653
 		if err != nil {
654 654
 			logrus.Errorf("Failed to parse endpoint IP %s: %v", os.Args[6], err)
655
-			os.Exit(9)
655
+			os.Exit(6)
656 656
 		}
657 657
 
658 658
 		ruleParams := strings.Fields(fmt.Sprintf("-m ipvs --ipvs -d %s -j SNAT --to-source %s", subnet, eIP))
... ...
@@ -663,21 +638,18 @@ func fwMarker() {
663 663
 			err := ioutil.WriteFile("/proc/sys/net/ipv4/vs/conntrack", []byte{'1', '\n'}, 0644)
664 664
 			if err != nil {
665 665
 				logrus.Errorf("Failed to write to /proc/sys/net/ipv4/vs/conntrack: %v", err)
666
-				os.Exit(8)
666
+				os.Exit(7)
667 667
 			}
668 668
 		}
669 669
 	}
670 670
 
671
-	rule := strings.Fields(fmt.Sprintf("-t mangle %s OUTPUT -d %s/32 -j MARK --set-mark %d", addDelOpt, vip, fwMark))
672
-	rules = append(rules, rule)
673
-
674
-	rule = strings.Fields(fmt.Sprintf("-t nat %s OUTPUT -p icmp --icmp echo-request -d %s -j DNAT --to 127.0.0.1", addDelOpt, vip))
671
+	rule := strings.Fields(fmt.Sprintf("-t mangle %s INPUT -d %s/32 -j MARK --set-mark %d", addDelOpt, vip, fwMark))
675 672
 	rules = append(rules, rule)
676 673
 
677 674
 	for _, rule := range rules {
678 675
 		if err := iptables.RawCombinedOutputNative(rule...); err != nil {
679 676
 			logrus.Errorf("setting up rule failed, %v: %v", rule, err)
680
-			os.Exit(5)
677
+			os.Exit(8)
681 678
 		}
682 679
 	}
683 680
 }
... ...
@@ -18,7 +18,7 @@ func (c *controller) rmServiceBinding(name, sid, nid, eid string, vip net.IP, in
18 18
 	return fmt.Errorf("not supported")
19 19
 }
20 20
 
21
-func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
21
+func (sb *sandbox) populateLoadBalancers(ep *endpoint) {
22 22
 }
23 23
 
24 24
 func arrangeIngressFilterRule() {
... ...
@@ -19,7 +19,13 @@ func init() {
19 19
 	lbPolicylistMap = make(map[*loadBalancer]*policyLists)
20 20
 }
21 21
 
22
-func (n *network) addLBBackend(ip, vip net.IP, lb *loadBalancer, ingressPorts []*PortConfig) {
22
+func (n *network) addLBBackend(ip net.IP, lb *loadBalancer) {
23
+	if len(lb.vip) == 0 {
24
+		return
25
+	}
26
+
27
+	vip := lb.vip
28
+	ingressPorts := lb.service.ingressPorts
23 29
 
24 30
 	if system.GetOSVersion().Build > 16236 {
25 31
 		lb.Lock()
... ...
@@ -117,11 +123,15 @@ func (n *network) addLBBackend(ip, vip net.IP, lb *loadBalancer, ingressPorts []
117 117
 	}
118 118
 }
119 119
 
120
-func (n *network) rmLBBackend(ip, vip net.IP, lb *loadBalancer, ingressPorts []*PortConfig, rmService bool, fullRemove bool) {
120
+func (n *network) rmLBBackend(ip net.IP, lb *loadBalancer, rmService bool, fullRemove bool) {
121
+	if len(lb.vip) == 0 {
122
+		return
123
+	}
124
+
121 125
 	if system.GetOSVersion().Build > 16236 {
122 126
 		if numEnabledBackends(lb) > 0 {
123 127
 			//Reprogram HNS (actually VFP) with the existing backends.
124
-			n.addLBBackend(ip, vip, lb, ingressPorts)
128
+			n.addLBBackend(ip, lb)
125 129
 		} else {
126 130
 			lb.Lock()
127 131
 			defer lb.Unlock()
... ...
@@ -156,7 +166,7 @@ func numEnabledBackends(lb *loadBalancer) int {
156 156
 	return nEnabled
157 157
 }
158 158
 
159
-func (sb *sandbox) populateLoadbalancers(ep *endpoint) {
159
+func (sb *sandbox) populateLoadBalancers(ep *endpoint) {
160 160
 }
161 161
 
162 162
 func arrangeIngressFilterRule() {
... ...
@@ -479,7 +479,7 @@ func (c *controller) networkCleanup() {
479 479
 	for _, n := range networks {
480 480
 		if n.inDelete {
481 481
 			logrus.Infof("Removing stale network %s (%s)", n.Name(), n.ID())
482
-			if err := n.delete(true); err != nil {
482
+			if err := n.delete(true, true); err != nil {
483 483
 				logrus.Debugf("Error while removing stale network: %v", err)
484 484
 			}
485 485
 		}