From 3d805de2461c4a0b4207dcdbe6d6bf0206d8811f Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Thu, 11 Jun 2015 23:21:50 -0700 Subject: [PATCH] Pass a canonical subnet to ipallocator - Currently both network and host bits in the subnet are passed when requesting an address from ipallocator. The way ip allocator determines the first available IP is tainted when caller passes the subnet host bits. - Verified this patch applied to libnetwork vendored in docker fixes the issue when starting the daemon. - Fixes #287 Signed-off-by: Alessandro Boch --- libnetwork/drivers/bridge/bridge.go | 4 +++- libnetwork/drivers/bridge/bridge_test.go | 18 ++++++++++++++---- libnetwork/drivers/bridge/setup_ipv4.go | 7 ++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libnetwork/drivers/bridge/bridge.go b/libnetwork/drivers/bridge/bridge.go index 7fd2e5ffc3..4804d128a0 100644 --- a/libnetwork/drivers/bridge/bridge.go +++ b/libnetwork/drivers/bridge/bridge.go @@ -877,7 +877,9 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn } // v4 address for the sandbox side pipe interface - ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil) + sub := types.GetIPNetCopy(n.bridge.bridgeIPv4) + sub.IP = sub.IP.Mask(sub.Mask) + ip4, err := ipAllocator.RequestIP(sub, nil) if err != nil { return err } diff --git a/libnetwork/drivers/bridge/bridge_test.go b/libnetwork/drivers/bridge/bridge_test.go index d872e4a1f1..760e3f699d 100644 --- a/libnetwork/drivers/bridge/bridge_test.go +++ b/libnetwork/drivers/bridge/bridge_test.go @@ -23,11 +23,21 @@ func TestCreateFullOptions(t *testing.T) { EnableIPForwarding: true, } + // Test this scenario: Default gw address does not belong to + // container network and it's greater than bridge address + cip, cnw, _ := net.ParseCIDR("172.16.122.0/24") + cnw.IP = cip + ip, nw, _ := net.ParseCIDR("172.16.0.10/16") + nw.IP = ip + gw := net.ParseIP("172.16.0.1") + netConfig := &networkConfiguration{ - BridgeName: DefaultBridgeName, - EnableIPv6: true, - FixedCIDR: bridgeNetworks[0], - EnableIPTables: true, + BridgeName: DefaultBridgeName, + AddressIPv4: nw, + FixedCIDR: cnw, + DefaultGatewayIPv4: gw, + EnableIPv6: true, + EnableIPTables: true, } _, netConfig.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48") genericOption := make(map[string]interface{}) diff --git a/libnetwork/drivers/bridge/setup_ipv4.go b/libnetwork/drivers/bridge/setup_ipv4.go index d05a47aea0..a89d81d0f4 100644 --- a/libnetwork/drivers/bridge/setup_ipv4.go +++ b/libnetwork/drivers/bridge/setup_ipv4.go @@ -8,6 +8,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/docker/libnetwork/netutils" + "github.com/docker/libnetwork/types" "github.com/vishvananda/netlink" ) @@ -109,7 +110,11 @@ func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error { if !i.bridgeIPv4.Contains(config.DefaultGatewayIPv4) { return &ErrInvalidGateway{} } - if _, err := ipAllocator.RequestIP(i.bridgeIPv4, config.DefaultGatewayIPv4); err != nil { + + // Pass the real network subnet to ip allocator (no host bits set) + sub := types.GetIPNetCopy(i.bridgeIPv4) + sub.IP = sub.IP.Mask(sub.Mask) + if _, err := ipAllocator.RequestIP(sub, config.DefaultGatewayIPv4); err != nil { return err }