From 6026fe772c21cd190f58e6ef666e7b2d955bdd33 Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Thu, 8 Oct 2015 20:04:13 -0700 Subject: [PATCH 1/2] Remove 2^32 bits restriction on bitsequence - Allow bitsequence of length 2^64-1 - Updated ID Manager and IPAM Signed-off-by: Alessandro Boch --- libnetwork/bitseq/sequence.go | 78 ++++++++++++------------ libnetwork/bitseq/sequence_test.go | 54 ++++++++-------- libnetwork/drivers/overlay/ov_network.go | 6 +- libnetwork/idm/idm.go | 12 ++-- libnetwork/ipam/allocator.go | 54 ++++++++-------- libnetwork/ipam/allocator_test.go | 33 ++-------- libnetwork/ipam/structures.go | 6 +- libnetwork/ipam/utils.go | 36 +++-------- libnetwork/libnetwork_test.go | 4 +- 9 files changed, 120 insertions(+), 163 deletions(-) diff --git a/libnetwork/bitseq/sequence.go b/libnetwork/bitseq/sequence.go index 0ad173a0fe..14304e3400 100644 --- a/libnetwork/bitseq/sequence.go +++ b/libnetwork/bitseq/sequence.go @@ -17,10 +17,10 @@ import ( // If needed we can think of making these configurable const ( blockLen = uint32(32) - blockBytes = blockLen / 8 + blockBytes = uint64(blockLen / 8) blockMAX = uint32(1<= h.bits { return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end) } @@ -203,7 +203,7 @@ func (h *Handle) SetAnyInRange(start, end uint32) (uint32, error) { } // SetAny atomically sets the first unset bit in the sequence and returns the corresponding ordinal -func (h *Handle) SetAny() (uint32, error) { +func (h *Handle) SetAny() (uint64, error) { if h.Unselected() == 0 { return invalidPos, errNoBitAvailable } @@ -211,7 +211,7 @@ func (h *Handle) SetAny() (uint32, error) { } // Set atomically sets the corresponding bit in the sequence -func (h *Handle) Set(ordinal uint32) error { +func (h *Handle) Set(ordinal uint64) error { if err := h.validateOrdinal(ordinal); err != nil { return err } @@ -220,7 +220,7 @@ func (h *Handle) Set(ordinal uint32) error { } // Unset atomically unsets the corresponding bit in the sequence -func (h *Handle) Unset(ordinal uint32) error { +func (h *Handle) Unset(ordinal uint64) error { if err := h.validateOrdinal(ordinal); err != nil { return err } @@ -230,7 +230,7 @@ func (h *Handle) Unset(ordinal uint32) error { // IsSet atomically checks if the ordinal bit is set. In case ordinal // is outside of the bit sequence limits, false is returned. -func (h *Handle) IsSet(ordinal uint32) bool { +func (h *Handle) IsSet(ordinal uint64) bool { if err := h.validateOrdinal(ordinal); err != nil { return false } @@ -241,11 +241,11 @@ func (h *Handle) IsSet(ordinal uint32) bool { } // set/reset the bit -func (h *Handle) set(ordinal, start, end uint32, any bool, release bool) (uint32, error) { +func (h *Handle) set(ordinal, start, end uint64, any bool, release bool) (uint64, error) { var ( - bitPos uint32 - bytePos uint32 - ret uint32 + bitPos uint64 + bytePos uint64 + ret uint64 err error ) @@ -309,7 +309,7 @@ func (h *Handle) set(ordinal, start, end uint32, any bool, release bool) (uint32 } // checks is needed because to cover the case where the number of bits is not a multiple of blockLen -func (h *Handle) validateOrdinal(ordinal uint32) error { +func (h *Handle) validateOrdinal(ordinal uint64) error { if ordinal >= h.bits { return fmt.Errorf("bit does not belong to the sequence") } @@ -341,9 +341,9 @@ func (h *Handle) ToByteArray() ([]byte, error) { h.Lock() defer h.Unlock() - ba := make([]byte, 8) - binary.BigEndian.PutUint32(ba[0:], h.bits) - binary.BigEndian.PutUint32(ba[4:], h.unselected) + ba := make([]byte, 16) + binary.BigEndian.PutUint64(ba[0:], h.bits) + binary.BigEndian.PutUint64(ba[8:], h.unselected) bm, err := h.head.toByteArray() if err != nil { return nil, fmt.Errorf("failed to serialize head: %s", err.Error()) @@ -360,27 +360,27 @@ func (h *Handle) FromByteArray(ba []byte) error { } nh := &sequence{} - err := nh.fromByteArray(ba[8:]) + err := nh.fromByteArray(ba[16:]) if err != nil { return fmt.Errorf("failed to deserialize head: %s", err.Error()) } h.Lock() h.head = nh - h.bits = binary.BigEndian.Uint32(ba[0:4]) - h.unselected = binary.BigEndian.Uint32(ba[4:8]) + h.bits = binary.BigEndian.Uint64(ba[0:8]) + h.unselected = binary.BigEndian.Uint64(ba[8:16]) h.Unlock() return nil } // Bits returns the length of the bit sequence -func (h *Handle) Bits() uint32 { +func (h *Handle) Bits() uint64 { return h.bits } // Unselected returns the number of bits which are not selected -func (h *Handle) Unselected() uint32 { +func (h *Handle) Unselected() uint64 { h.Lock() defer h.Unlock() return h.unselected @@ -426,7 +426,7 @@ func (h *Handle) UnmarshalJSON(data []byte) error { } // getFirstAvailable looks for the first unset bit in passed mask starting from start -func getFirstAvailable(head *sequence, start uint32) (uint32, uint32, error) { +func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) { // Find sequence which contains the start bit byteStart, bitStart := ordinalToPos(start) current, _, _, inBlockBytePos := findSequence(head, byteStart) @@ -450,7 +450,7 @@ func getFirstAvailable(head *sequence, start uint32) (uint32, uint32, error) { // checkIfAvailable checks if the bit correspondent to the specified ordinal is unset // If the ordinal is beyond the sequence limits, a negative response is returned -func checkIfAvailable(head *sequence, ordinal uint32) (uint32, uint32, error) { +func checkIfAvailable(head *sequence, ordinal uint64) (uint64, uint64, error) { bytePos, bitPos := ordinalToPos(ordinal) // Find the sequence containing this byte @@ -470,7 +470,7 @@ func checkIfAvailable(head *sequence, ordinal uint32) (uint32, uint32, error) { // sequence containing the byte (current), the pointer to the previous sequence, // the number of blocks preceding the block containing the byte inside the current sequence. // If bytePos is outside of the list, function will return (nil, nil, 0, invalidPos) -func findSequence(head *sequence, bytePos uint32) (*sequence, *sequence, uint32, uint32) { +func findSequence(head *sequence, bytePos uint64) (*sequence, *sequence, uint64, uint64) { // Find the sequence containing this byte previous := head current := head @@ -511,7 +511,7 @@ func findSequence(head *sequence, bytePos uint32) (*sequence, *sequence, uint32, // A) block is first in current: [prev seq] [new] [modified current seq] [next seq] // B) block is last in current: [prev seq] [modified current seq] [new] [next seq] // C) block is in the middle of current: [prev seq] [curr pre] [new] [curr post] [next seq] -func pushReservation(bytePos, bitPos uint32, head *sequence, release bool) *sequence { +func pushReservation(bytePos, bitPos uint64, head *sequence, release bool) *sequence { // Store list's head newHead := head @@ -599,18 +599,18 @@ func mergeSequences(seq *sequence) { } } -func getNumBlocks(numBits uint32) uint32 { - numBlocks := numBits / blockLen - if numBits%blockLen != 0 { +func getNumBlocks(numBits uint64) uint64 { + numBlocks := numBits / uint64(blockLen) + if numBits%uint64(blockLen) != 0 { numBlocks++ } return numBlocks } -func ordinalToPos(ordinal uint32) (uint32, uint32) { +func ordinalToPos(ordinal uint64) (uint64, uint64) { return ordinal / 8, ordinal % 8 } -func posToOrdinal(bytePos, bitPos uint32) uint32 { +func posToOrdinal(bytePos, bitPos uint64) uint64 { return bytePos*8 + bitPos } diff --git a/libnetwork/bitseq/sequence_test.go b/libnetwork/bitseq/sequence_test.go index 55ba318dfa..f650778f04 100644 --- a/libnetwork/bitseq/sequence_test.go +++ b/libnetwork/bitseq/sequence_test.go @@ -9,9 +9,9 @@ import ( func TestSequenceGetAvailableBit(t *testing.T) { input := []struct { head *sequence - from uint32 - bytePos uint32 - bitPos uint32 + from uint64 + bytePos uint64 + bitPos uint64 }{ {&sequence{block: 0x0, count: 0}, 0, invalidPos, invalidPos}, {&sequence{block: 0x0, count: 1}, 0, 0, 0}, @@ -120,8 +120,8 @@ func TestSequenceCopy(t *testing.T) { func TestGetFirstAvailable(t *testing.T) { input := []struct { mask *sequence - bytePos uint32 - bitPos uint32 + bytePos uint64 + bitPos uint64 }{ {&sequence{block: 0xffffffff, count: 2048}, invalidPos, invalidPos}, {&sequence{block: 0x0, count: 8}, 0, 0}, @@ -167,9 +167,9 @@ func TestGetFirstAvailable(t *testing.T) { func TestFindSequence(t *testing.T) { input := []struct { head *sequence - bytePos uint32 - precBlocks uint32 - inBlockBytePos uint32 + bytePos uint64 + precBlocks uint64 + inBlockBytePos uint64 }{ {&sequence{block: 0xffffffff, count: 0}, 0, 0, invalidPos}, {&sequence{block: 0xffffffff, count: 0}, 31, 0, invalidPos}, @@ -202,9 +202,9 @@ func TestFindSequence(t *testing.T) { func TestCheckIfAvailable(t *testing.T) { input := []struct { head *sequence - ordinal uint32 - bytePos uint32 - bitPos uint32 + ordinal uint64 + bytePos uint64 + bitPos uint64 }{ {&sequence{block: 0xffffffff, count: 0}, 0, invalidPos, invalidPos}, {&sequence{block: 0xffffffff, count: 0}, 31, invalidPos, invalidPos}, @@ -274,8 +274,8 @@ func TestMergeSequences(t *testing.T) { func TestPushReservation(t *testing.T) { input := []struct { mask *sequence - bytePos uint32 - bitPos uint32 + bytePos uint64 + bitPos uint64 newMask *sequence }{ // Create first sequence and fill in 8 addresses starting from address 0 @@ -445,8 +445,8 @@ func TestSet(t *testing.T) { } hnd.head = getTestSequence() - firstAv := uint32(32*100 + 31) - last := uint32(1024*32 - 1) + firstAv := uint64(32*100 + 31) + last := uint64(1024*32 - 1) if hnd.IsSet(100000) { t.Fatal("IsSet() returned wrong result") @@ -497,7 +497,7 @@ func TestSet(t *testing.T) { } func TestSetUnset(t *testing.T) { - numBits := uint32(64 * 1024) + numBits := uint64(64 * 1024) hnd, err := NewHandle("", nil, "", numBits) if err != nil { t.Fatal(err) @@ -508,7 +508,7 @@ func TestSetUnset(t *testing.T) { t.Fatal(err) } } - i := uint32(0) + i := uint64(0) for hnd.Unselected() < numBits { if err := hnd.Unset(i); err != nil { t.Fatal(err) @@ -518,14 +518,14 @@ func TestSetUnset(t *testing.T) { } func TestSetInRange(t *testing.T) { - numBits := uint32(1024 * blockLen) + numBits := uint64(1024 * blockLen) hnd, err := NewHandle("", nil, "", numBits) if err != nil { t.Fatal(err) } hnd.head = getTestSequence() - firstAv := uint32(100*blockLen + blockLen - 1) + firstAv := uint64(100*blockLen + blockLen - 1) if o, err := hnd.SetAnyInRange(4, 3); err == nil { t.Fatalf("Expected failure. Got success with ordinal:%d", o) @@ -539,7 +539,7 @@ func TestSetInRange(t *testing.T) { t.Fatalf("Expected failure. Got success with ordinal:%d", o) } - o, err := hnd.SetAnyInRange(100*blockLen, 101*blockLen) + o, err := hnd.SetAnyInRange(100*uint64(blockLen), 101*uint64(blockLen)) if err != nil { t.Fatalf("Unexpected failure: (%d, %v)", o, err) } @@ -547,7 +547,7 @@ func TestSetInRange(t *testing.T) { t.Fatalf("Unexpected ordinal: %d", o) } - if o, err := hnd.SetAnyInRange(0, blockLen); err == nil { + if o, err := hnd.SetAnyInRange(0, uint64(blockLen)); err == nil { t.Fatalf("Expected failure. Got success with ordinal:%d", o) } @@ -555,27 +555,27 @@ func TestSetInRange(t *testing.T) { t.Fatalf("Expected failure. Got success with ordinal:%d", o) } - if o, err := hnd.SetAnyInRange(111*blockLen, 161*blockLen); err == nil { + if o, err := hnd.SetAnyInRange(111*uint64(blockLen), 161*uint64(blockLen)); err == nil { t.Fatalf("Expected failure. Got success with ordinal:%d", o) } - o, err = hnd.SetAnyInRange(161*blockLen, 162*blockLen) + o, err = hnd.SetAnyInRange(161*uint64(blockLen), 162*uint64(blockLen)) if err != nil { t.Fatal(err) } - if o != 161*blockLen+30 { + if o != 161*uint64(blockLen)+30 { t.Fatalf("Unexpected ordinal: %d", o) } - o, err = hnd.SetAnyInRange(161*blockLen, 162*blockLen) + o, err = hnd.SetAnyInRange(161*uint64(blockLen), 162*uint64(blockLen)) if err != nil { t.Fatal(err) } - if o != 161*blockLen+31 { + if o != 161*uint64(blockLen)+31 { t.Fatalf("Unexpected ordinal: %d", o) } - o, err = hnd.SetAnyInRange(161*blockLen, 162*blockLen) + o, err = hnd.SetAnyInRange(161*uint64(blockLen), 162*uint64(blockLen)) if err == nil { t.Fatalf("Expected failure. Got success with ordinal:%d", o) } diff --git a/libnetwork/drivers/overlay/ov_network.go b/libnetwork/drivers/overlay/ov_network.go index 756d9e7b9c..c7a82b3d75 100644 --- a/libnetwork/drivers/overlay/ov_network.go +++ b/libnetwork/drivers/overlay/ov_network.go @@ -475,7 +475,7 @@ func (n *network) releaseVxlanID() error { } for _, s := range n.subnets { - n.driver.vxlanIdm.Release(n.vxlanID(s)) + n.driver.vxlanIdm.Release(uint64(n.vxlanID(s))) n.setVxlanID(s, 0) } return nil @@ -502,9 +502,9 @@ func (n *network) obtainVxlanID(s *subnet) error { return fmt.Errorf("failed to allocate vxlan id: %v", err) } - n.setVxlanID(s, vxlanID) + n.setVxlanID(s, uint32(vxlanID)) if err := n.writeToStore(); err != nil { - n.driver.vxlanIdm.Release(n.vxlanID(s)) + n.driver.vxlanIdm.Release(uint64(n.vxlanID(s))) n.setVxlanID(s, 0) if err == datastore.ErrKeyModified { continue diff --git a/libnetwork/idm/idm.go b/libnetwork/idm/idm.go index 8c15cfe4ec..37ae79e558 100644 --- a/libnetwork/idm/idm.go +++ b/libnetwork/idm/idm.go @@ -10,13 +10,13 @@ import ( // Idm manages the reservation/release of numerical ids from a contiguos set type Idm struct { - start uint32 - end uint32 + start uint64 + end uint64 handle *bitseq.Handle } // New returns an instance of id manager for a set of [start-end] numerical ids -func New(ds datastore.DataStore, id string, start, end uint32) (*Idm, error) { +func New(ds datastore.DataStore, id string, start, end uint64) (*Idm, error) { if id == "" { return nil, fmt.Errorf("Invalid id") } @@ -33,7 +33,7 @@ func New(ds datastore.DataStore, id string, start, end uint32) (*Idm, error) { } // GetID returns the first available id in the set -func (i *Idm) GetID() (uint32, error) { +func (i *Idm) GetID() (uint64, error) { if i.handle == nil { return 0, fmt.Errorf("ID set is not initialized") } @@ -42,7 +42,7 @@ func (i *Idm) GetID() (uint32, error) { } // GetSpecificID tries to reserve the specified id -func (i *Idm) GetSpecificID(id uint32) error { +func (i *Idm) GetSpecificID(id uint64) error { if i.handle == nil { return fmt.Errorf("ID set is not initialized") } @@ -55,6 +55,6 @@ func (i *Idm) GetSpecificID(id uint32) error { } // Release releases the specified id -func (i *Idm) Release(id uint32) { +func (i *Idm) Release(id uint64) { i.handle.Unset(id - i.start) } diff --git a/libnetwork/ipam/allocator.go b/libnetwork/ipam/allocator.go index 7c3815c3d1..33164bd83a 100644 --- a/libnetwork/ipam/allocator.go +++ b/libnetwork/ipam/allocator.go @@ -17,9 +17,8 @@ const ( localAddressSpace = "LocalDefault" globalAddressSpace = "GlobalDefault" // The biggest configurable host subnets - minNetSize = 8 - minNetSizeV6 = 64 - minNetSizeV6Eff = 96 + minNetSize = 8 + minNetSizeV6 = 64 // datastore keyes for ipam objects dsConfigKey = "ipam/" + ipamapi.DefaultIPAM + "/config" dsDataKey = "ipam/" + ipamapi.DefaultIPAM + "/data" @@ -129,7 +128,7 @@ func (a *Allocator) GetDefaultAddressSpaces() (string, string, error) { // RequestPool returns an address pool along with its unique id. func (a *Allocator) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error) { log.Debugf("RequestPool(%s, %s, %s, %v, %t)", addressSpace, pool, subPool, options, v6) - k, nw, aw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) + k, nw, ipr, err := a.parsePoolRequest(addressSpace, pool, subPool, v6) if err != nil { return "", nil, nil, ipamapi.ErrInvalidPool } @@ -157,7 +156,7 @@ retry: goto retry } - return k.String(), aw, nil, insert() + return k.String(), nw, nil, insert() } // ReleasePool releases the address pool identified by the passed id @@ -205,41 +204,38 @@ func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) { return aSpace, nil } -func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *net.IPNet, *AddressRange, error) { +func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool) (*SubnetKey, *net.IPNet, *AddressRange, error) { var ( - nw, aw *net.IPNet - ipr *AddressRange - err error + nw *net.IPNet + ipr *AddressRange + err error ) if addressSpace == "" { - return nil, nil, nil, nil, ipamapi.ErrInvalidAddressSpace + return nil, nil, nil, ipamapi.ErrInvalidAddressSpace } if pool == "" && subPool != "" { - return nil, nil, nil, nil, ipamapi.ErrInvalidSubPool + return nil, nil, nil, ipamapi.ErrInvalidSubPool } if pool != "" { if _, nw, err = net.ParseCIDR(pool); err != nil { - return nil, nil, nil, nil, ipamapi.ErrInvalidPool + return nil, nil, nil, ipamapi.ErrInvalidPool } if subPool != "" { if ipr, err = getAddressRange(subPool); err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } } } else { if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } } - if aw, err = adjustAndCheckSubnetSize(nw); err != nil { - return nil, nil, nil, nil, err - } - return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, aw, ipr, nil + return &SubnetKey{AddressSpace: addressSpace, Subnet: nw.String(), ChildSubnet: subPool}, nw, ipr, nil } func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { @@ -252,23 +248,27 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { ipVer := getAddressVersion(pool.IP) ones, bits := pool.Mask.Size() - numAddresses := uint32(1 << uint(bits-ones)) + 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-- + } + // Generate the new address masks. AddressMask content may come from datastore h, err := bitseq.NewHandle(dsDataKey, store, key.String(), numAddresses) if err != nil { return err } - if ipVer == v4 { - // Do not let network identifier address be reserved - h.Set(0) - } + // Do not let network identifier address be reserved + // Do the same for IPv6 so that bridge ip starts with XXXX...::1 + h.Set(0) a.Lock() a.addresses[key] = h @@ -438,6 +438,7 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error { if p.Range != nil { mask = p.Range.Sub.Mask } + h, err := types.GetHostPartIP(address, mask) if err != nil { return fmt.Errorf("failed to release address %s: %v", address.String(), err) @@ -448,12 +449,13 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error { return fmt.Errorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v", k.String(), address, poolID, err) } - return bm.Unset(ipToUint32(h)) + + return bm.Unset(ipToUint64(h)) } func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ipr *AddressRange) (net.IP, error) { var ( - ordinal uint32 + ordinal uint64 err error base *net.IPNet ) @@ -470,7 +472,7 @@ func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddres if e != nil { return nil, fmt.Errorf("failed to allocate preferred address %s: %v", prefAddress.String(), e) } - ordinal = ipToUint32(types.GetMinimalIP(hostPart)) + ordinal = ipToUint64(types.GetMinimalIP(hostPart)) err = bitmask.Set(ordinal) } else { base.IP = ipr.Sub.IP diff --git a/libnetwork/ipam/allocator_test.go b/libnetwork/ipam/allocator_test.go index e38d08ce40..82ec43d84e 100644 --- a/libnetwork/ipam/allocator_test.go +++ b/libnetwork/ipam/allocator_test.go @@ -66,10 +66,10 @@ func getAllocator() (*Allocator, error) { } func TestInt2IP2IntConversion(t *testing.T) { - for i := uint32(0); i < 256*256*256; i++ { + for i := uint64(0); i < 256*256*256; i++ { var array [4]byte // new array at each cycle addIntToIP(array[:], i) - j := ipToUint32(array[:]) + j := ipToUint64(array[:]) if j != i { t.Fatalf("Failed to convert ordinal %d to IP % x and back to ordinal. Got %d", i, array, j) } @@ -502,31 +502,6 @@ func TestPredefinedPool(t *testing.T) { } } -func TestAdjustAndCheckSubnet(t *testing.T) { - _, sub6, _ := net.ParseCIDR("1003:1:2:300::/63") - _, err := adjustAndCheckSubnetSize(sub6) - if err == nil { - t.Fatalf("Failed detect too big v6 subnet") - } - - _, sub, _ := net.ParseCIDR("192.0.0.0/7") - _, err = adjustAndCheckSubnetSize(sub) - if err == nil { - t.Fatalf("Failed detect too big v4 subnet") - } - - subnet := "1004:1:2:6::/64" - _, sub6, _ = net.ParseCIDR(subnet) - subnetToSplit, err := adjustAndCheckSubnetSize(sub6) - if err != nil { - t.Fatalf("Unexpected error returned by adjustAndCheckSubnetSize()") - } - ones, _ := subnetToSplit.Mask.Size() - if ones < minNetSizeV6Eff { - t.Fatalf("Wrong effective network size for %s. Expected: %d. Got: %d", subnet, minNetSizeV6Eff, ones) - } -} - func TestRemoveSubnet(t *testing.T) { a, err := getAllocator() if err != nil { @@ -757,7 +732,7 @@ func TestRequestSyntaxCheck(t *testing.T) { err = a.ReleaseAddress(pid, ip) if err != nil { - t.Fatalf("Unexpected failure: %v", err) + t.Fatalf("Unexpected failure: %v: %s, %s", err, pid, ip) } } @@ -873,7 +848,7 @@ func assertGetAddress(t *testing.T, subnet string) { zeroes := bits - ones numAddresses := 1 << uint(zeroes) - bm, err := bitseq.NewHandle("ipam_test", nil, "default/"+subnet, uint32(numAddresses)) + bm, err := bitseq.NewHandle("ipam_test", nil, "default/"+subnet, uint64(numAddresses)) if err != nil { t.Fatal(err) } diff --git a/libnetwork/ipam/structures.go b/libnetwork/ipam/structures.go index 71a5690aa0..9ac171887c 100644 --- a/libnetwork/ipam/structures.go +++ b/libnetwork/ipam/structures.go @@ -43,7 +43,7 @@ type addrSpace struct { // identify a range in a a pool of addresses type AddressRange struct { Sub *net.IPNet - Start, End uint32 + Start, End uint64 } // String returns the string form of the AddressRange object @@ -71,8 +71,8 @@ func (r *AddressRange) UnmarshalJSON(data []byte) error { if r.Sub, err = types.ParseCIDR(m["Sub"].(string)); err != nil { return err } - r.Start = uint32(m["Start"].(float64)) - r.End = uint32(m["End"].(float64)) + r.Start = uint64(m["Start"].(float64)) + r.End = uint64(m["End"].(float64)) return nil } diff --git a/libnetwork/ipam/utils.go b/libnetwork/ipam/utils.go index ebb9b5dbc7..2d9c6b17bf 100644 --- a/libnetwork/ipam/utils.go +++ b/libnetwork/ipam/utils.go @@ -33,32 +33,12 @@ func getAddressRange(pool string) (*AddressRange, error) { return nil, fmt.Errorf("failed to compute range's highest ip address: %v", e) } nw.IP = ip - return &AddressRange{nw, ipToUint32(types.GetMinimalIP(lIP)), ipToUint32(types.GetMinimalIP(hIP))}, nil -} - -// Check subnets size. In case configured subnet is v6 and host size is -// greater than 32 bits, adjust subnet to /96. -func adjustAndCheckSubnetSize(subnet *net.IPNet) (*net.IPNet, error) { - ones, bits := subnet.Mask.Size() - if v6 == getAddressVersion(subnet.IP) { - if ones < minNetSizeV6 { - return nil, ipamapi.ErrInvalidPool - } - if ones < minNetSizeV6Eff { - newMask := net.CIDRMask(minNetSizeV6Eff, bits) - return &net.IPNet{IP: subnet.IP, Mask: newMask}, nil - } - } else { - if ones < minNetSize { - return nil, ipamapi.ErrInvalidPool - } - } - return subnet, nil + return &AddressRange{nw, ipToUint64(types.GetMinimalIP(lIP)), ipToUint64(types.GetMinimalIP(hIP))}, nil } // It generates the ip address in the passed subnet specified by // the passed host address ordinal -func generateAddress(ordinal uint32, network *net.IPNet) net.IP { +func generateAddress(ordinal uint64, network *net.IPNet) net.IP { var address [16]byte // Get network portion of IP @@ -83,7 +63,7 @@ func getAddressVersion(ip net.IP) ipVersion { // Adds the ordinal IP to the current array // 192.168.0.0 + 53 => 192.168.53 -func addIntToIP(array []byte, ordinal uint32) { +func addIntToIP(array []byte, ordinal uint64) { for i := len(array) - 1; i >= 0; i-- { array[i] |= (byte)(ordinal & 0xff) ordinal >>= 8 @@ -91,11 +71,11 @@ func addIntToIP(array []byte, ordinal uint32) { } // Convert an ordinal to the respective IP address -func ipToUint32(ip []byte) uint32 { - value := uint32(0) - for i := 0; i < len(ip); i++ { - j := len(ip) - 1 - i - value += uint32(ip[i]) << uint(j*8) +func ipToUint64(ip []byte) (value uint64) { + cip := types.GetMinimalIP(ip) + for i := 0; i < len(cip); i++ { + j := len(cip) - 1 - i + value += uint64(cip[i]) << uint(j*8) } return value } diff --git a/libnetwork/libnetwork_test.go b/libnetwork/libnetwork_test.go index 2d6a3e4772..e324f2de8c 100644 --- a/libnetwork/libnetwork_test.go +++ b/libnetwork/libnetwork_test.go @@ -276,7 +276,7 @@ func TestBridge(t *testing.T) { }, } ipamV4ConfList := []*libnetwork.IpamConf{&libnetwork.IpamConf{PreferredPool: "192.168.100.0/24", Gateway: "192.168.100.1"}} - ipamV6ConfList := []*libnetwork.IpamConf{&libnetwork.IpamConf{PreferredPool: "fe90::/98", Gateway: "fe90::22"}} + ipamV6ConfList := []*libnetwork.IpamConf{&libnetwork.IpamConf{PreferredPool: "fe90::/64", Gateway: "fe90::22"}} network, err := createTestNetwork(bridgeNetType, "testnetwork", netOption, ipamV4ConfList, ipamV6ConfList) if err != nil { @@ -1641,7 +1641,7 @@ func TestEnableIPv6(t *testing.T) { "BridgeName": "testnetwork", }, } - ipamV6ConfList := []*libnetwork.IpamConf{&libnetwork.IpamConf{PreferredPool: "fe80::/98"}} + ipamV6ConfList := []*libnetwork.IpamConf{&libnetwork.IpamConf{PreferredPool: "fe80::/64"}} n, err := createTestNetwork("bridge", "testnetwork", netOption, nil, ipamV6ConfList) if err != nil { From c2064dc18d91a69fb0a0383a73d21c06748cb019 Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Fri, 9 Oct 2015 12:43:11 -0700 Subject: [PATCH 2/2] Reduce logging verbosity in allocator Signed-off-by: Alessandro Boch --- libnetwork/ipam/allocator.go | 2 +- libnetwork/sandbox_store.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libnetwork/ipam/allocator.go b/libnetwork/ipam/allocator.go index 33164bd83a..44811ba89a 100644 --- a/libnetwork/ipam/allocator.go +++ b/libnetwork/ipam/allocator.go @@ -239,7 +239,7 @@ func (a *Allocator) parsePoolRequest(addressSpace, pool, subPool string, v6 bool } func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error { - log.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String()) + //log.Debugf("Inserting bitmask (%s, %s)", key.String(), pool.String()) store := a.getStore(key.AddressSpace) if store == nil { diff --git a/libnetwork/sandbox_store.go b/libnetwork/sandbox_store.go index 56abbb6424..2a86cbc4cc 100644 --- a/libnetwork/sandbox_store.go +++ b/libnetwork/sandbox_store.go @@ -168,7 +168,6 @@ func (c *controller) sandboxCleanup() { for _, kvo := range kvol { sbs := kvo.(*sbState) - logrus.Printf("sandboxcleanup sbs = %+v", sbs) sb := &sandbox{ id: sbs.ID, controller: sbs.c,