Переглянути джерело

Reorganize MAC generation functions

- We have more than one function doing the same thing

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 10 роки тому
батько
коміт
3da75632f7

+ 1 - 26
libnetwork/drivers/bridge/bridge.go

@@ -1381,34 +1381,9 @@ func parseContainerOptions(cOptions map[string]interface{}) (*containerConfigura
 	}
 }
 
-// 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 generateMacAddr(ip)
+	return netutils.GenerateMACFromIP(ip)
 }

+ 3 - 11
libnetwork/drivers/bridge/netlink_deprecated_linux.go

@@ -7,6 +7,8 @@ import (
 	"syscall"
 	"time"
 	"unsafe"
+
+	"github.com/docker/libnetwork/netutils"
 )
 
 const (
@@ -74,16 +76,6 @@ func ioctlAddToBridge(iface, master *net.Interface) error {
 	return ifIoctBridge(iface, master, ioctlBrAddIf)
 }
 
-func randMacAddr() string {
-	hw := make(net.HardwareAddr, 6)
-	for i := 0; i < 6; i++ {
-		hw[i] = byte(rnd.Intn(255))
-	}
-	hw[0] &^= 0x1 // clear multicast bit
-	hw[0] |= 0x2  // set local assignment bit (IEEE802)
-	return hw.String()
-}
-
 func ioctlSetMacAddress(name, addr string) error {
 	if len(name) >= ifNameSize {
 		return fmt.Errorf("Interface name %s too long", name)
@@ -133,7 +125,7 @@ func ioctlCreateBridge(name string, setMacAddr bool) error {
 		return err
 	}
 	if setMacAddr {
-		return ioctlSetMacAddress(name, randMacAddr())
+		return ioctlSetMacAddress(name, netutils.GenerateRandomMAC().String())
 	}
 	return nil
 }

+ 17 - 7
libnetwork/netutils/utils.go

@@ -122,26 +122,36 @@ func GetIfaceAddr(name string) (net.Addr, []net.Addr, error) {
 	return addrs4[0], addrs6, nil
 }
 
-// GenerateRandomMAC returns a new 6-byte(48-bit) hardware address (MAC)
-func GenerateRandomMAC() net.HardwareAddr {
+func genMAC(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
-	// Randomly generate the remaining 4 bytes (2^32)
-	_, err := rand.Read(hw[2:])
-	if err != nil {
-		return nil
+	// Fill the remaining 4 bytes based on the input
+	if ip == nil {
+		rand.Read(hw[2:])
+	} else {
+		copy(hw[2:], ip.To4())
 	}
 	return hw
 }
 
+// GenerateRandomMAC returns a new 6-byte(48-bit) hardware address (MAC)
+func GenerateRandomMAC() net.HardwareAddr {
+	return genMAC(nil)
+}
+
+// GenerateMACFromIP returns a locally administered MAC address where the 4 least
+// significant bytes are derived from the IPv4 address.
+func GenerateMACFromIP(ip net.IP) net.HardwareAddr {
+	return genMAC(ip)
+}
+
 // GenerateRandomName returns a new name joined with a prefix.  This size
 // specified is used to truncate the randomly generated value
 func GenerateRandomName(prefix string, size int) (string, error) {