1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #624 from aboch/bs6

Remove num bit limitation in bitsequence
This commit is contained in:
Madhu Venugopal 2015-10-10 06:11:24 -07:00
commit 648393ef5f
10 changed files with 121 additions and 165 deletions

View file

@ -17,10 +17,10 @@ import (
// If needed we can think of making these configurable // If needed we can think of making these configurable
const ( const (
blockLen = uint32(32) blockLen = uint32(32)
blockBytes = blockLen / 8 blockBytes = uint64(blockLen / 8)
blockMAX = uint32(1<<blockLen - 1) blockMAX = uint32(1<<blockLen - 1)
blockFirstBit = uint32(1) << (blockLen - 1) blockFirstBit = uint32(1) << (blockLen - 1)
invalidPos = blockMAX invalidPos = uint64(0xFFFFFFFFFFFFFFFF)
) )
var ( var (
@ -29,8 +29,8 @@ var (
// Handle contains the sequece representing the bitmask and its identifier // Handle contains the sequece representing the bitmask and its identifier
type Handle struct { type Handle struct {
bits uint32 bits uint64
unselected uint32 unselected uint64
head *sequence head *sequence
app string app string
id string id string
@ -41,7 +41,7 @@ type Handle struct {
} }
// NewHandle returns a thread-safe instance of the bitmask handler // NewHandle returns a thread-safe instance of the bitmask handler
func NewHandle(app string, ds datastore.DataStore, id string, numElements uint32) (*Handle, error) { func NewHandle(app string, ds datastore.DataStore, id string, numElements uint64) (*Handle, error) {
h := &Handle{ h := &Handle{
app: app, app: app,
id: id, id: id,
@ -76,7 +76,7 @@ func NewHandle(app string, ds datastore.DataStore, id string, numElements uint32
// sequence represents a recurring sequence of 32 bits long bitmasks // sequence represents a recurring sequence of 32 bits long bitmasks
type sequence struct { type sequence struct {
block uint32 // block is a symbol representing 4 byte long allocation bitmask block uint32 // block is a symbol representing 4 byte long allocation bitmask
count uint32 // number of consecutive blocks (symbols) count uint64 // number of consecutive blocks (symbols)
next *sequence // next sequence next *sequence // next sequence
} }
@ -92,7 +92,7 @@ func (s *sequence) toString() string {
} }
// GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence // GetAvailableBit returns the position of the first unset bit in the bitmask represented by this sequence
func (s *sequence) getAvailableBit(from uint32) (uint32, uint32, error) { func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) {
if s.block == blockMAX || s.count == 0 { if s.block == blockMAX || s.count == 0 {
return invalidPos, invalidPos, errNoBitAvailable return invalidPos, invalidPos, errNoBitAvailable
} }
@ -145,9 +145,9 @@ func (s *sequence) toByteArray() ([]byte, error) {
p := s p := s
for p != nil { for p != nil {
b := make([]byte, 8) b := make([]byte, 12)
binary.BigEndian.PutUint32(b[0:], p.block) binary.BigEndian.PutUint32(b[0:], p.block)
binary.BigEndian.PutUint32(b[4:], p.count) binary.BigEndian.PutUint64(b[4:], p.count)
bb = append(bb, b...) bb = append(bb, b...)
p = p.next p = p.next
} }
@ -158,7 +158,7 @@ func (s *sequence) toByteArray() ([]byte, error) {
// fromByteArray construct the sequence from the byte array // fromByteArray construct the sequence from the byte array
func (s *sequence) fromByteArray(data []byte) error { func (s *sequence) fromByteArray(data []byte) error {
l := len(data) l := len(data)
if l%8 != 0 { if l%12 != 0 {
return fmt.Errorf("cannot deserialize byte sequence of lenght %d (%v)", l, data) return fmt.Errorf("cannot deserialize byte sequence of lenght %d (%v)", l, data)
} }
@ -166,8 +166,8 @@ func (s *sequence) fromByteArray(data []byte) error {
i := 0 i := 0
for { for {
p.block = binary.BigEndian.Uint32(data[i : i+4]) p.block = binary.BigEndian.Uint32(data[i : i+4])
p.count = binary.BigEndian.Uint32(data[i+4 : i+8]) p.count = binary.BigEndian.Uint64(data[i+4 : i+12])
i += 8 i += 12
if i == l { if i == l {
break break
} }
@ -192,7 +192,7 @@ func (h *Handle) getCopy() *Handle {
} }
// SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal // SetAnyInRange atomically sets the first unset bit in the specified range in the sequence and returns the corresponding ordinal
func (h *Handle) SetAnyInRange(start, end uint32) (uint32, error) { func (h *Handle) SetAnyInRange(start, end uint64) (uint64, error) {
if end-start <= 0 || end >= h.bits { if end-start <= 0 || end >= h.bits {
return invalidPos, fmt.Errorf("invalid bit range [%d, %d]", start, end) 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 // 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 { if h.Unselected() == 0 {
return invalidPos, errNoBitAvailable return invalidPos, errNoBitAvailable
} }
@ -211,7 +211,7 @@ func (h *Handle) SetAny() (uint32, error) {
} }
// Set atomically sets the corresponding bit in the sequence // 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 { if err := h.validateOrdinal(ordinal); err != nil {
return err return err
} }
@ -220,7 +220,7 @@ func (h *Handle) Set(ordinal uint32) error {
} }
// Unset atomically unsets the corresponding bit in the sequence // 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 { if err := h.validateOrdinal(ordinal); err != nil {
return err 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 // IsSet atomically checks if the ordinal bit is set. In case ordinal
// is outside of the bit sequence limits, false is returned. // 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 { if err := h.validateOrdinal(ordinal); err != nil {
return false return false
} }
@ -241,11 +241,11 @@ func (h *Handle) IsSet(ordinal uint32) bool {
} }
// set/reset the bit // 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 ( var (
bitPos uint32 bitPos uint64
bytePos uint32 bytePos uint64
ret uint32 ret uint64
err error 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 // 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 { if ordinal >= h.bits {
return fmt.Errorf("bit does not belong to the sequence") return fmt.Errorf("bit does not belong to the sequence")
} }
@ -341,9 +341,9 @@ func (h *Handle) ToByteArray() ([]byte, error) {
h.Lock() h.Lock()
defer h.Unlock() defer h.Unlock()
ba := make([]byte, 8) ba := make([]byte, 16)
binary.BigEndian.PutUint32(ba[0:], h.bits) binary.BigEndian.PutUint64(ba[0:], h.bits)
binary.BigEndian.PutUint32(ba[4:], h.unselected) binary.BigEndian.PutUint64(ba[8:], h.unselected)
bm, err := h.head.toByteArray() bm, err := h.head.toByteArray()
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to serialize head: %s", err.Error()) return nil, fmt.Errorf("failed to serialize head: %s", err.Error())
@ -360,27 +360,27 @@ func (h *Handle) FromByteArray(ba []byte) error {
} }
nh := &sequence{} nh := &sequence{}
err := nh.fromByteArray(ba[8:]) err := nh.fromByteArray(ba[16:])
if err != nil { if err != nil {
return fmt.Errorf("failed to deserialize head: %s", err.Error()) return fmt.Errorf("failed to deserialize head: %s", err.Error())
} }
h.Lock() h.Lock()
h.head = nh h.head = nh
h.bits = binary.BigEndian.Uint32(ba[0:4]) h.bits = binary.BigEndian.Uint64(ba[0:8])
h.unselected = binary.BigEndian.Uint32(ba[4:8]) h.unselected = binary.BigEndian.Uint64(ba[8:16])
h.Unlock() h.Unlock()
return nil return nil
} }
// Bits returns the length of the bit sequence // Bits returns the length of the bit sequence
func (h *Handle) Bits() uint32 { func (h *Handle) Bits() uint64 {
return h.bits return h.bits
} }
// Unselected returns the number of bits which are not selected // Unselected returns the number of bits which are not selected
func (h *Handle) Unselected() uint32 { func (h *Handle) Unselected() uint64 {
h.Lock() h.Lock()
defer h.Unlock() defer h.Unlock()
return h.unselected 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 // 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 // Find sequence which contains the start bit
byteStart, bitStart := ordinalToPos(start) byteStart, bitStart := ordinalToPos(start)
current, _, _, inBlockBytePos := findSequence(head, byteStart) 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 // 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 // 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) bytePos, bitPos := ordinalToPos(ordinal)
// Find the sequence containing this byte // 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, // 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. // 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) // 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 // Find the sequence containing this byte
previous := head previous := head
current := 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] // 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] // 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] // 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 // Store list's head
newHead := head newHead := head
@ -599,18 +599,18 @@ func mergeSequences(seq *sequence) {
} }
} }
func getNumBlocks(numBits uint32) uint32 { func getNumBlocks(numBits uint64) uint64 {
numBlocks := numBits / blockLen numBlocks := numBits / uint64(blockLen)
if numBits%blockLen != 0 { if numBits%uint64(blockLen) != 0 {
numBlocks++ numBlocks++
} }
return numBlocks return numBlocks
} }
func ordinalToPos(ordinal uint32) (uint32, uint32) { func ordinalToPos(ordinal uint64) (uint64, uint64) {
return ordinal / 8, ordinal % 8 return ordinal / 8, ordinal % 8
} }
func posToOrdinal(bytePos, bitPos uint32) uint32 { func posToOrdinal(bytePos, bitPos uint64) uint64 {
return bytePos*8 + bitPos return bytePos*8 + bitPos
} }

View file

@ -9,9 +9,9 @@ import (
func TestSequenceGetAvailableBit(t *testing.T) { func TestSequenceGetAvailableBit(t *testing.T) {
input := []struct { input := []struct {
head *sequence head *sequence
from uint32 from uint64
bytePos uint32 bytePos uint64
bitPos uint32 bitPos uint64
}{ }{
{&sequence{block: 0x0, count: 0}, 0, invalidPos, invalidPos}, {&sequence{block: 0x0, count: 0}, 0, invalidPos, invalidPos},
{&sequence{block: 0x0, count: 1}, 0, 0, 0}, {&sequence{block: 0x0, count: 1}, 0, 0, 0},
@ -120,8 +120,8 @@ func TestSequenceCopy(t *testing.T) {
func TestGetFirstAvailable(t *testing.T) { func TestGetFirstAvailable(t *testing.T) {
input := []struct { input := []struct {
mask *sequence mask *sequence
bytePos uint32 bytePos uint64
bitPos uint32 bitPos uint64
}{ }{
{&sequence{block: 0xffffffff, count: 2048}, invalidPos, invalidPos}, {&sequence{block: 0xffffffff, count: 2048}, invalidPos, invalidPos},
{&sequence{block: 0x0, count: 8}, 0, 0}, {&sequence{block: 0x0, count: 8}, 0, 0},
@ -167,9 +167,9 @@ func TestGetFirstAvailable(t *testing.T) {
func TestFindSequence(t *testing.T) { func TestFindSequence(t *testing.T) {
input := []struct { input := []struct {
head *sequence head *sequence
bytePos uint32 bytePos uint64
precBlocks uint32 precBlocks uint64
inBlockBytePos uint32 inBlockBytePos uint64
}{ }{
{&sequence{block: 0xffffffff, count: 0}, 0, 0, invalidPos}, {&sequence{block: 0xffffffff, count: 0}, 0, 0, invalidPos},
{&sequence{block: 0xffffffff, count: 0}, 31, 0, invalidPos}, {&sequence{block: 0xffffffff, count: 0}, 31, 0, invalidPos},
@ -202,9 +202,9 @@ func TestFindSequence(t *testing.T) {
func TestCheckIfAvailable(t *testing.T) { func TestCheckIfAvailable(t *testing.T) {
input := []struct { input := []struct {
head *sequence head *sequence
ordinal uint32 ordinal uint64
bytePos uint32 bytePos uint64
bitPos uint32 bitPos uint64
}{ }{
{&sequence{block: 0xffffffff, count: 0}, 0, invalidPos, invalidPos}, {&sequence{block: 0xffffffff, count: 0}, 0, invalidPos, invalidPos},
{&sequence{block: 0xffffffff, count: 0}, 31, invalidPos, invalidPos}, {&sequence{block: 0xffffffff, count: 0}, 31, invalidPos, invalidPos},
@ -274,8 +274,8 @@ func TestMergeSequences(t *testing.T) {
func TestPushReservation(t *testing.T) { func TestPushReservation(t *testing.T) {
input := []struct { input := []struct {
mask *sequence mask *sequence
bytePos uint32 bytePos uint64
bitPos uint32 bitPos uint64
newMask *sequence newMask *sequence
}{ }{
// Create first sequence and fill in 8 addresses starting from address 0 // Create first sequence and fill in 8 addresses starting from address 0
@ -445,8 +445,8 @@ func TestSet(t *testing.T) {
} }
hnd.head = getTestSequence() hnd.head = getTestSequence()
firstAv := uint32(32*100 + 31) firstAv := uint64(32*100 + 31)
last := uint32(1024*32 - 1) last := uint64(1024*32 - 1)
if hnd.IsSet(100000) { if hnd.IsSet(100000) {
t.Fatal("IsSet() returned wrong result") t.Fatal("IsSet() returned wrong result")
@ -497,7 +497,7 @@ func TestSet(t *testing.T) {
} }
func TestSetUnset(t *testing.T) { func TestSetUnset(t *testing.T) {
numBits := uint32(64 * 1024) numBits := uint64(64 * 1024)
hnd, err := NewHandle("", nil, "", numBits) hnd, err := NewHandle("", nil, "", numBits)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -508,7 +508,7 @@ func TestSetUnset(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
} }
i := uint32(0) i := uint64(0)
for hnd.Unselected() < numBits { for hnd.Unselected() < numBits {
if err := hnd.Unset(i); err != nil { if err := hnd.Unset(i); err != nil {
t.Fatal(err) t.Fatal(err)
@ -518,14 +518,14 @@ func TestSetUnset(t *testing.T) {
} }
func TestSetInRange(t *testing.T) { func TestSetInRange(t *testing.T) {
numBits := uint32(1024 * blockLen) numBits := uint64(1024 * blockLen)
hnd, err := NewHandle("", nil, "", numBits) hnd, err := NewHandle("", nil, "", numBits)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
hnd.head = getTestSequence() hnd.head = getTestSequence()
firstAv := uint32(100*blockLen + blockLen - 1) firstAv := uint64(100*blockLen + blockLen - 1)
if o, err := hnd.SetAnyInRange(4, 3); err == nil { if o, err := hnd.SetAnyInRange(4, 3); err == nil {
t.Fatalf("Expected failure. Got success with ordinal:%d", o) 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) 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 { if err != nil {
t.Fatalf("Unexpected failure: (%d, %v)", o, err) t.Fatalf("Unexpected failure: (%d, %v)", o, err)
} }
@ -547,7 +547,7 @@ func TestSetInRange(t *testing.T) {
t.Fatalf("Unexpected ordinal: %d", o) 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) 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) 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) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if o != 161*blockLen+30 { if o != 161*uint64(blockLen)+30 {
t.Fatalf("Unexpected ordinal: %d", o) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if o != 161*blockLen+31 { if o != 161*uint64(blockLen)+31 {
t.Fatalf("Unexpected ordinal: %d", o) 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 { if err == nil {
t.Fatalf("Expected failure. Got success with ordinal:%d", o) t.Fatalf("Expected failure. Got success with ordinal:%d", o)
} }

View file

@ -475,7 +475,7 @@ func (n *network) releaseVxlanID() error {
} }
for _, s := range n.subnets { for _, s := range n.subnets {
n.driver.vxlanIdm.Release(n.vxlanID(s)) n.driver.vxlanIdm.Release(uint64(n.vxlanID(s)))
n.setVxlanID(s, 0) n.setVxlanID(s, 0)
} }
return nil return nil
@ -502,9 +502,9 @@ func (n *network) obtainVxlanID(s *subnet) error {
return fmt.Errorf("failed to allocate vxlan id: %v", err) 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 { 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) n.setVxlanID(s, 0)
if err == datastore.ErrKeyModified { if err == datastore.ErrKeyModified {
continue continue

View file

@ -10,13 +10,13 @@ import (
// Idm manages the reservation/release of numerical ids from a contiguos set // Idm manages the reservation/release of numerical ids from a contiguos set
type Idm struct { type Idm struct {
start uint32 start uint64
end uint32 end uint64
handle *bitseq.Handle handle *bitseq.Handle
} }
// New returns an instance of id manager for a set of [start-end] numerical ids // 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 == "" { if id == "" {
return nil, fmt.Errorf("Invalid 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 // 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 { if i.handle == nil {
return 0, fmt.Errorf("ID set is not initialized") 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 // 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 { if i.handle == nil {
return fmt.Errorf("ID set is not initialized") return fmt.Errorf("ID set is not initialized")
} }
@ -55,6 +55,6 @@ func (i *Idm) GetSpecificID(id uint32) error {
} }
// Release releases the specified id // Release releases the specified id
func (i *Idm) Release(id uint32) { func (i *Idm) Release(id uint64) {
i.handle.Unset(id - i.start) i.handle.Unset(id - i.start)
} }

View file

@ -17,9 +17,8 @@ const (
localAddressSpace = "LocalDefault" localAddressSpace = "LocalDefault"
globalAddressSpace = "GlobalDefault" globalAddressSpace = "GlobalDefault"
// The biggest configurable host subnets // The biggest configurable host subnets
minNetSize = 8 minNetSize = 8
minNetSizeV6 = 64 minNetSizeV6 = 64
minNetSizeV6Eff = 96
// datastore keyes for ipam objects // datastore keyes for ipam objects
dsConfigKey = "ipam/" + ipamapi.DefaultIPAM + "/config" dsConfigKey = "ipam/" + ipamapi.DefaultIPAM + "/config"
dsDataKey = "ipam/" + ipamapi.DefaultIPAM + "/data" 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. // 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) { 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) 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 { if err != nil {
return "", nil, nil, ipamapi.ErrInvalidPool return "", nil, nil, ipamapi.ErrInvalidPool
} }
@ -157,7 +156,7 @@ retry:
goto 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 // ReleasePool releases the address pool identified by the passed id
@ -205,45 +204,42 @@ func (a *Allocator) getAddrSpace(as string) (*addrSpace, error) {
return aSpace, nil 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 ( var (
nw, aw *net.IPNet nw *net.IPNet
ipr *AddressRange ipr *AddressRange
err error err error
) )
if addressSpace == "" { if addressSpace == "" {
return nil, nil, nil, nil, ipamapi.ErrInvalidAddressSpace return nil, nil, nil, ipamapi.ErrInvalidAddressSpace
} }
if pool == "" && subPool != "" { if pool == "" && subPool != "" {
return nil, nil, nil, nil, ipamapi.ErrInvalidSubPool return nil, nil, nil, ipamapi.ErrInvalidSubPool
} }
if pool != "" { if pool != "" {
if _, nw, err = net.ParseCIDR(pool); err != nil { if _, nw, err = net.ParseCIDR(pool); err != nil {
return nil, nil, nil, nil, ipamapi.ErrInvalidPool return nil, nil, nil, ipamapi.ErrInvalidPool
} }
if subPool != "" { if subPool != "" {
if ipr, err = getAddressRange(subPool); err != nil { if ipr, err = getAddressRange(subPool); err != nil {
return nil, nil, nil, nil, err return nil, nil, nil, err
} }
} }
} else { } else {
if nw, err = a.getPredefinedPool(addressSpace, v6); err != nil { 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 { 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) store := a.getStore(key.AddressSpace)
if store == nil { if store == nil {
@ -252,23 +248,27 @@ func (a *Allocator) insertBitMask(key SubnetKey, pool *net.IPNet) error {
ipVer := getAddressVersion(pool.IP) ipVer := getAddressVersion(pool.IP)
ones, bits := pool.Mask.Size() ones, bits := pool.Mask.Size()
numAddresses := uint32(1 << uint(bits-ones)) numAddresses := uint64(1 << uint(bits-ones))
if ipVer == v4 { if ipVer == v4 {
// Do not let broadcast address be reserved // Do not let broadcast address be reserved
numAddresses-- numAddresses--
} }
// Allow /64 subnet
if ipVer == v6 && numAddresses == 0 {
numAddresses--
}
// Generate the new address masks. AddressMask content may come from datastore // Generate the new address masks. AddressMask content may come from datastore
h, err := bitseq.NewHandle(dsDataKey, store, key.String(), numAddresses) h, err := bitseq.NewHandle(dsDataKey, store, key.String(), numAddresses)
if err != nil { if err != nil {
return err return err
} }
if ipVer == v4 { // Do not let network identifier address be reserved
// Do not let network identifier address be reserved // Do the same for IPv6 so that bridge ip starts with XXXX...::1
h.Set(0) h.Set(0)
}
a.Lock() a.Lock()
a.addresses[key] = h a.addresses[key] = h
@ -438,6 +438,7 @@ func (a *Allocator) ReleaseAddress(poolID string, address net.IP) error {
if p.Range != nil { if p.Range != nil {
mask = p.Range.Sub.Mask mask = p.Range.Sub.Mask
} }
h, err := types.GetHostPartIP(address, mask) h, err := types.GetHostPartIP(address, mask)
if err != nil { if err != nil {
return fmt.Errorf("failed to release address %s: %v", address.String(), err) 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", return fmt.Errorf("could not find bitmask in datastore for %s on address %v release from pool %s: %v",
k.String(), address, poolID, err) 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) { func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ipr *AddressRange) (net.IP, error) {
var ( var (
ordinal uint32 ordinal uint64
err error err error
base *net.IPNet base *net.IPNet
) )
@ -470,7 +472,7 @@ func (a *Allocator) getAddress(nw *net.IPNet, bitmask *bitseq.Handle, prefAddres
if e != nil { if e != nil {
return nil, fmt.Errorf("failed to allocate preferred address %s: %v", prefAddress.String(), e) 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) err = bitmask.Set(ordinal)
} else { } else {
base.IP = ipr.Sub.IP base.IP = ipr.Sub.IP

View file

@ -66,10 +66,10 @@ func getAllocator() (*Allocator, error) {
} }
func TestInt2IP2IntConversion(t *testing.T) { 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 var array [4]byte // new array at each cycle
addIntToIP(array[:], i) addIntToIP(array[:], i)
j := ipToUint32(array[:]) j := ipToUint64(array[:])
if j != i { if j != i {
t.Fatalf("Failed to convert ordinal %d to IP % x and back to ordinal. Got %d", i, array, j) 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) { func TestRemoveSubnet(t *testing.T) {
a, err := getAllocator() a, err := getAllocator()
if err != nil { if err != nil {
@ -757,7 +732,7 @@ func TestRequestSyntaxCheck(t *testing.T) {
err = a.ReleaseAddress(pid, ip) err = a.ReleaseAddress(pid, ip)
if err != nil { 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 zeroes := bits - ones
numAddresses := 1 << uint(zeroes) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -43,7 +43,7 @@ type addrSpace struct {
// identify a range in a a pool of addresses // identify a range in a a pool of addresses
type AddressRange struct { type AddressRange struct {
Sub *net.IPNet Sub *net.IPNet
Start, End uint32 Start, End uint64
} }
// String returns the string form of the AddressRange object // 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 { if r.Sub, err = types.ParseCIDR(m["Sub"].(string)); err != nil {
return err return err
} }
r.Start = uint32(m["Start"].(float64)) r.Start = uint64(m["Start"].(float64))
r.End = uint32(m["End"].(float64)) r.End = uint64(m["End"].(float64))
return nil return nil
} }

View file

@ -33,32 +33,12 @@ func getAddressRange(pool string) (*AddressRange, error) {
return nil, fmt.Errorf("failed to compute range's highest ip address: %v", e) return nil, fmt.Errorf("failed to compute range's highest ip address: %v", e)
} }
nw.IP = ip nw.IP = ip
return &AddressRange{nw, ipToUint32(types.GetMinimalIP(lIP)), ipToUint32(types.GetMinimalIP(hIP))}, nil return &AddressRange{nw, ipToUint64(types.GetMinimalIP(lIP)), ipToUint64(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
} }
// It generates the ip address in the passed subnet specified by // It generates the ip address in the passed subnet specified by
// the passed host address ordinal // 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 var address [16]byte
// Get network portion of IP // Get network portion of IP
@ -83,7 +63,7 @@ func getAddressVersion(ip net.IP) ipVersion {
// Adds the ordinal IP to the current array // Adds the ordinal IP to the current array
// 192.168.0.0 + 53 => 192.168.53 // 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-- { for i := len(array) - 1; i >= 0; i-- {
array[i] |= (byte)(ordinal & 0xff) array[i] |= (byte)(ordinal & 0xff)
ordinal >>= 8 ordinal >>= 8
@ -91,11 +71,11 @@ func addIntToIP(array []byte, ordinal uint32) {
} }
// Convert an ordinal to the respective IP address // Convert an ordinal to the respective IP address
func ipToUint32(ip []byte) uint32 { func ipToUint64(ip []byte) (value uint64) {
value := uint32(0) cip := types.GetMinimalIP(ip)
for i := 0; i < len(ip); i++ { for i := 0; i < len(cip); i++ {
j := len(ip) - 1 - i j := len(cip) - 1 - i
value += uint32(ip[i]) << uint(j*8) value += uint64(cip[i]) << uint(j*8)
} }
return value return value
} }

View file

@ -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"}} 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) network, err := createTestNetwork(bridgeNetType, "testnetwork", netOption, ipamV4ConfList, ipamV6ConfList)
if err != nil { if err != nil {
@ -1641,7 +1641,7 @@ func TestEnableIPv6(t *testing.T) {
"BridgeName": "testnetwork", "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) n, err := createTestNetwork("bridge", "testnetwork", netOption, nil, ipamV6ConfList)
if err != nil { if err != nil {

View file

@ -168,7 +168,6 @@ func (c *controller) sandboxCleanup() {
for _, kvo := range kvol { for _, kvo := range kvol {
sbs := kvo.(*sbState) sbs := kvo.(*sbState)
logrus.Printf("sandboxcleanup sbs = %+v", sbs)
sb := &sandbox{ sb := &sandbox{
id: sbs.ID, id: sbs.ID,
controller: sbs.c, controller: sbs.c,