Merge pull request #8371 from aluzzardi/f-consistent-mac
Support for consistent MAC address.
This commit is contained in:
commit
beff5067c8
6 changed files with 54 additions and 1 deletions
|
@ -215,6 +215,7 @@ func populateCommand(c *Container, env []string) error {
|
|||
Bridge: network.Bridge,
|
||||
IPAddress: network.IPAddress,
|
||||
IPPrefixLen: network.IPPrefixLen,
|
||||
MacAddress: network.MacAddress,
|
||||
}
|
||||
}
|
||||
case "container":
|
||||
|
@ -504,6 +505,7 @@ func (container *Container) allocateNetwork() error {
|
|||
container.NetworkSettings.Bridge = env.Get("Bridge")
|
||||
container.NetworkSettings.IPAddress = env.Get("IP")
|
||||
container.NetworkSettings.IPPrefixLen = env.GetInt("IPPrefixLen")
|
||||
container.NetworkSettings.MacAddress = env.Get("MacAddress")
|
||||
container.NetworkSettings.Gateway = env.Get("Gateway")
|
||||
|
||||
return nil
|
||||
|
|
|
@ -65,8 +65,9 @@ type Network struct {
|
|||
type NetworkInterface struct {
|
||||
Gateway string `json:"gateway"`
|
||||
IPAddress string `json:"ip"`
|
||||
Bridge string `json:"bridge"`
|
||||
IPPrefixLen int `json:"ip_prefix_len"`
|
||||
MacAddress string `json:"mac_address"`
|
||||
Bridge string `json:"bridge"`
|
||||
}
|
||||
|
||||
type Resources struct {
|
||||
|
|
|
@ -95,6 +95,7 @@ func (d *driver) createNetwork(container *libcontainer.Config, c *execdriver.Com
|
|||
vethNetwork := libcontainer.Network{
|
||||
Mtu: c.Network.Mtu,
|
||||
Address: fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
|
||||
MacAddress: c.Network.Interface.MacAddress,
|
||||
Gateway: c.Network.Interface.Gateway,
|
||||
Type: "veth",
|
||||
Bridge: c.Network.Interface.Bridge,
|
||||
|
|
|
@ -11,6 +11,7 @@ type PortMapping map[string]string // Deprecated
|
|||
type NetworkSettings struct {
|
||||
IPAddress string
|
||||
IPPrefixLen int
|
||||
MacAddress string
|
||||
Gateway string
|
||||
Bridge string
|
||||
PortMapping map[string]PortMapping // Deprecated
|
||||
|
|
|
@ -326,10 +326,36 @@ func createBridgeIface(name string) error {
|
|||
return netlink.CreateBridge(name, setBridgeMacAddr)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Allocate a network interface
|
||||
func Allocate(job *engine.Job) engine.Status {
|
||||
var (
|
||||
ip net.IP
|
||||
mac net.HardwareAddr
|
||||
err error
|
||||
id = job.Args[0]
|
||||
requestedIP = net.ParseIP(job.Getenv("RequestedIP"))
|
||||
|
@ -344,10 +370,16 @@ func Allocate(job *engine.Job) engine.Status {
|
|||
return job.Error(err)
|
||||
}
|
||||
|
||||
// If no explicit mac address was given, generate a random one.
|
||||
if mac, err = net.ParseMAC(job.Getenv("RequestedMac")); err != nil {
|
||||
mac = generateMacAddr(ip)
|
||||
}
|
||||
|
||||
out := engine.Env{}
|
||||
out.Set("IP", ip.String())
|
||||
out.Set("Mask", bridgeNetwork.Mask.String())
|
||||
out.Set("Gateway", bridgeNetwork.IP.String())
|
||||
out.Set("MacAddress", mac.String())
|
||||
out.Set("Bridge", bridgeIface)
|
||||
|
||||
size, _ := bridgeNetwork.Mask.Size()
|
||||
|
|
|
@ -102,3 +102,19 @@ func TestHostnameFormatChecking(t *testing.T) {
|
|||
t.Fatal("Failed to check invalid HostIP")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMacAddrGeneration(t *testing.T) {
|
||||
ip := net.ParseIP("192.168.0.1")
|
||||
mac := generateMacAddr(ip).String()
|
||||
|
||||
// Should be consistent.
|
||||
if generateMacAddr(ip).String() != mac {
|
||||
t.Fatal("Inconsistent MAC address")
|
||||
}
|
||||
|
||||
// Should be unique.
|
||||
ip2 := net.ParseIP("192.168.0.2")
|
||||
if generateMacAddr(ip2).String() == mac {
|
||||
t.Fatal("Non-unique MAC address")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue