瀏覽代碼

Merge pull request #276 from mrjana/cnm

Generate container mac address based on IP
Jana Radhakrishnan 10 年之前
父節點
當前提交
d67a1b3908
共有 1 個文件被更改,包括 35 次插入10 次删除
  1. 35 10
      libnetwork/drivers/bridge/bridge.go

+ 35 - 10
libnetwork/drivers/bridge/bridge.go

@@ -852,14 +852,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
-
 	n.Lock()
 	config := n.config
 	n.Unlock()
@@ -889,6 +881,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 {
@@ -1289,9 +1289,34 @@ 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)
 }