mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
88e21c6a75
Right now, MAC addresses are randomly generated by the kernel when creating the veth interfaces. This causes different issues related to ARP, such as #4581, #5737 and #8269. This change adds support for consistent MAC addresses, guaranteeing that an IP address will always end up with the same MAC address, no matter what. Since IP addresses are already guaranteed to be unique by the IPAllocator, MAC addresses will inherit this property as well for free. Consistent mac addresses is also a requirement for stable networking (#8297) since re-using the same IP address on a different MAC address triggers the ARP issue. Finally, this change makes the MAC address accessible through docker inspect, which fixes #4033. Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
120 lines
3 KiB
Go
120 lines
3 KiB
Go
package bridge
|
|
|
|
import (
|
|
"net"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/docker/docker/daemon/networkdriver/portmapper"
|
|
"github.com/docker/docker/engine"
|
|
)
|
|
|
|
func init() {
|
|
// reset the new proxy command for mocking out the userland proxy in tests
|
|
portmapper.NewProxy = portmapper.NewMockProxyCommand
|
|
}
|
|
|
|
func findFreePort(t *testing.T) int {
|
|
l, err := net.Listen("tcp", ":0")
|
|
if err != nil {
|
|
t.Fatal("Failed to find a free port")
|
|
}
|
|
defer l.Close()
|
|
|
|
result, err := net.ResolveTCPAddr("tcp", l.Addr().String())
|
|
if err != nil {
|
|
t.Fatal("Failed to resolve address to identify free port")
|
|
}
|
|
return result.Port
|
|
}
|
|
|
|
func newPortAllocationJob(eng *engine.Engine, port int) (job *engine.Job) {
|
|
strPort := strconv.Itoa(port)
|
|
|
|
job = eng.Job("allocate_port", "container_id")
|
|
job.Setenv("HostIP", "127.0.0.1")
|
|
job.Setenv("HostPort", strPort)
|
|
job.Setenv("Proto", "tcp")
|
|
job.Setenv("ContainerPort", strPort)
|
|
return
|
|
}
|
|
|
|
func newPortAllocationJobWithInvalidHostIP(eng *engine.Engine, port int) (job *engine.Job) {
|
|
strPort := strconv.Itoa(port)
|
|
|
|
job = eng.Job("allocate_port", "container_id")
|
|
job.Setenv("HostIP", "localhost")
|
|
job.Setenv("HostPort", strPort)
|
|
job.Setenv("Proto", "tcp")
|
|
job.Setenv("ContainerPort", strPort)
|
|
return
|
|
}
|
|
|
|
func TestAllocatePortDetection(t *testing.T) {
|
|
eng := engine.New()
|
|
eng.Logging = false
|
|
|
|
freePort := findFreePort(t)
|
|
|
|
// Init driver
|
|
job := eng.Job("initdriver")
|
|
if res := InitDriver(job); res != engine.StatusOK {
|
|
t.Fatal("Failed to initialize network driver")
|
|
}
|
|
|
|
// Allocate interface
|
|
job = eng.Job("allocate_interface", "container_id")
|
|
if res := Allocate(job); res != engine.StatusOK {
|
|
t.Fatal("Failed to allocate network interface")
|
|
}
|
|
|
|
// Allocate same port twice, expect failure on second call
|
|
job = newPortAllocationJob(eng, freePort)
|
|
if res := AllocatePort(job); res != engine.StatusOK {
|
|
t.Fatal("Failed to find a free port to allocate")
|
|
}
|
|
if res := AllocatePort(job); res == engine.StatusOK {
|
|
t.Fatal("Duplicate port allocation granted by AllocatePort")
|
|
}
|
|
}
|
|
|
|
func TestHostnameFormatChecking(t *testing.T) {
|
|
eng := engine.New()
|
|
eng.Logging = false
|
|
|
|
freePort := findFreePort(t)
|
|
|
|
// Init driver
|
|
job := eng.Job("initdriver")
|
|
if res := InitDriver(job); res != engine.StatusOK {
|
|
t.Fatal("Failed to initialize network driver")
|
|
}
|
|
|
|
// Allocate interface
|
|
job = eng.Job("allocate_interface", "container_id")
|
|
if res := Allocate(job); res != engine.StatusOK {
|
|
t.Fatal("Failed to allocate network interface")
|
|
}
|
|
|
|
// Allocate port with invalid HostIP, expect failure with Bad Request http status
|
|
job = newPortAllocationJobWithInvalidHostIP(eng, freePort)
|
|
if res := AllocatePort(job); res == engine.StatusOK {
|
|
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")
|
|
}
|
|
}
|