|
@@ -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
|