diff --git a/libnetwork/ipam/allocator.go b/libnetwork/ipam/allocator.go index 54c1eda72f..dfad30bdee 100644 --- a/libnetwork/ipam/allocator.go +++ b/libnetwork/ipam/allocator.go @@ -246,11 +246,6 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { ones, bits := pool.Mask.Size() numAddresses := uint64(1 << uint(bits-ones)) - if ipVer == v4 { - // Do not let broadcast address be reserved - numAddresses-- - } - // Allow /64 subnet if ipVer == v6 && numAddresses == 0 { numAddresses-- @@ -266,6 +261,11 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { // Do the same for IPv6 so that bridge ip starts with XXXX...::1 h.Set(0) + // Do not let broadcast address be reserved + if ipVer == v4 { + h.Set(numAddresses - 1) + } + a.Lock() a.addresses[key] = h a.Unlock() diff --git a/libnetwork/ipam/allocator_test.go b/libnetwork/ipam/allocator_test.go index 82ec43d84e..0b0242df27 100644 --- a/libnetwork/ipam/allocator_test.go +++ b/libnetwork/ipam/allocator_test.go @@ -575,6 +575,23 @@ func TestGetSameAddress(t *testing.T) { } } +func TestGetAddressSubPoolEqualPool(t *testing.T) { + a, err := getAllocator() + if err != nil { + t.Fatal(err) + } + // Requesting a subpool of same size of the master pool should not cause any problem on ip allocation + pid, _, _, err := a.RequestPool(localAddressSpace, "172.18.0.0/16", "172.18.0.0/16", nil, false) + if err != nil { + t.Fatal(err) + } + + _, _, err = a.RequestAddress(pid, nil, nil) + if err != nil { + t.Fatal(err) + } +} + func TestRequestReleaseAddressFromSubPool(t *testing.T) { a, err := getAllocator() if err != nil {