Преглед на файлове

Merge pull request #13861 from mrjana/cnm_integ

Vendoring libnetwork to fix stale arp cache issue
Brian Goff преди 10 години
родител
ревизия
4fc6449944

+ 1 - 1
hack/vendor.sh

@@ -55,7 +55,7 @@ clone hg code.google.com/p/go.net 84a4013f96e0
 clone hg code.google.com/p/gosqlite 74691fb6f837
 
 #get libnetwork packages
-clone git github.com/docker/libnetwork ace6b576239cd671d1645d82520b16791737f60d
+clone git github.com/docker/libnetwork 90638ec9cf7fa7b7f5d0e96b0854f136d66bff92
 clone git github.com/vishvananda/netns 5478c060110032f972e86a1f844fdb9a2f008f2c
 clone git github.com/vishvananda/netlink 8eb64238879fed52fd51c5b30ad20b928fb4c36c
 

+ 35 - 10
vendor/src/github.com/docker/libnetwork/drivers/bridge/bridge.go

@@ -498,14 +498,6 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 		}
 	}()
 
-	// Set the sbox's MAC. If specified, use the one configured by user, otherwise use a random one
-	mac := electMacAddress(epConfig)
-	err = netlink.LinkSetHardwareAddr(sbox, mac)
-	if err != nil {
-		return err
-	}
-	endpoint.macAddress = mac
-
 	// Add bridge inherited attributes to pipe interfaces
 	if config.Mtu != 0 {
 		err = netlink.LinkSetMTU(host, config.Mtu)
@@ -531,6 +523,14 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 	ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
 
+	// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
+	mac := electMacAddress(epConfig, ip4)
+	err = netlink.LinkSetHardwareAddr(sbox, mac)
+	if err != nil {
+		return err
+	}
+	endpoint.macAddress = mac
+
 	// v6 address for the sandbox side pipe interface
 	ipv6Addr = &net.IPNet{}
 	if config.EnableIPv6 {
@@ -926,11 +926,36 @@ func parseContainerOptions(cOptions map[string]interface{}) (*ContainerConfigura
 	}
 }
 
-func electMacAddress(epConfig *EndpointConfiguration) net.HardwareAddr {
+// Generate a IEEE802 compliant MAC address from the given IP address.
+//
+// The generator is guaranteed to be consistent: the same IP will always yield the same
+// MAC address. This is to avoid ARP cache issues.
+func generateMacAddr(ip net.IP) net.HardwareAddr {
+	hw := make(net.HardwareAddr, 6)
+
+	// The first byte of the MAC address has to comply with these rules:
+	// 1. Unicast: Set the least-significant bit to 0.
+	// 2. Address is locally administered: Set the second-least-significant bit (U/L) to 1.
+	// 3. As "small" as possible: The veth address has to be "smaller" than the bridge address.
+	hw[0] = 0x02
+
+	// The first 24 bits of the MAC represent the Organizationally Unique Identifier (OUI).
+	// Since this address is locally administered, we can do whatever we want as long as
+	// it doesn't conflict with other addresses.
+	hw[1] = 0x42
+
+	// Insert the IP address into the last 32 bits of the MAC address.
+	// This is a simple way to guarantee the address will be consistent and unique.
+	copy(hw[2:], ip.To4())
+
+	return hw
+}
+
+func electMacAddress(epConfig *EndpointConfiguration, ip net.IP) net.HardwareAddr {
 	if epConfig != nil && epConfig.MacAddress != nil {
 		return epConfig.MacAddress
 	}
-	return netutils.GenerateRandomMAC()
+	return generateMacAddr(ip)
 }
 
 // Generates a name to be used for a virtual ethernet

+ 12 - 4
vendor/src/github.com/docker/libnetwork/sandbox/namespace_linux.go

@@ -103,12 +103,20 @@ func removeFromGarbagePaths(path string) {
 // GC triggers garbage collection of namespace path right away
 // and waits for it.
 func GC() {
-	waitGC := make(chan struct{})
+	gpmLock.Lock()
+	if len(garbagePathMap) == 0 {
+		// No need for GC if map is empty
+		gpmLock.Unlock()
+		return
+	}
+	gpmLock.Unlock()
 
-	// Trigger GC now
+	// if content exists in the garbage paths
+	// we can trigger GC to run, providing a
+	// channel to be notified on completion
+	waitGC := make(chan struct{})
 	gpmChan <- waitGC
-
-	// wait for gc to complete
+	// wait for GC completion
 	<-waitGC
 }