-
Notifications
You must be signed in to change notification settings - Fork 881
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serializing bitseq alloc #1788
Serializing bitseq alloc #1788
Conversation
c043f63
to
62472f3
Compare
bitseq/sequence.go
Outdated
@@ -511,6 +513,29 @@ func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) { | |||
return invalidPos, invalidPos, ErrNoBitAvailable | |||
} | |||
|
|||
//getAvailableFromCurrent will look for available ordinal from the current ordinal. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will make change
bitseq/sequence.go
Outdated
@@ -511,6 +513,29 @@ func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) { | |||
return invalidPos, invalidPos, ErrNoBitAvailable | |||
} | |||
|
|||
//getAvailableFromCurrent will look for available ordinal from the current ordinal. | |||
// If none found then it will loop back to the start to check of the available bit. | |||
//This can be further optimized to check from start till curr in case of a rollover |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space missing
if end < ret { | ||
err = ErrNoBitAvailable | ||
if err == nil { | ||
h.curr = ret + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when the last bit is allocated is there the risk that doing the +1 the number wraps to 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that will result in failure and cause the allocation from the start=
bitseq/sequence.go
Outdated
//This can be further optimized to check from start till curr in case of a rollover | ||
func getAvailableFromCurrent(head *sequence, start, curr, end uint64) (uint64, uint64, error) { | ||
var bytePos, bitPos uint64 | ||
if curr != 0 && curr > start { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it necessary curr != 0? is it not the same as the starting case where start == 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but start need not be 0 . but curr could be if not allocated yet
bytePos, bitPos, _ = getFirstAvailable(head, curr) | ||
ret := posToOrdinal(bytePos, bitPos) | ||
if end < ret { | ||
goto begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't really need a goto here.
If start < ret < end then the result is valid and you can return the result. Else you continue you just continue with the other lookup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoding multiple condition in if. IMO this would be cleaner.
bitseq/sequence_test.go
Outdated
@@ -939,9 +941,6 @@ func TestAllocateRandomDeallocate(t *testing.T) { | |||
if hnd.Unselected() != uint64(numBits/2) { | |||
t.Fatalf("Expected half sequence. Instead found %d free bits.\nSeed: %d\n%s", hnd.unselected, seed, hnd) | |||
} | |||
if !hnd.head.equal(expected) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a check that we may still want to have to validate the consistency of the allocation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allocation not be part of the head. So this verification will not hold true with new change.
idm/idm_test.go
Outdated
@@ -110,7 +110,7 @@ func TestUninitialized(t *testing.T) { | |||
} | |||
|
|||
func TestAllocateInRange(t *testing.T) { | |||
i, err := New(nil, "myset", 5, 10) | |||
i, err := New(nil, "myset", 5, 12) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason to change this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes since the allocation is serial and not the first available expanding the range to suit the test
bitseq/sequence.go
Outdated
for current != nil { | ||
if current.block != blockMAX { | ||
bytePos, bitPos, err := current.getAvailableBit(bitOffset) | ||
return byteOffset + bytePos, bitPos, err | ||
} | ||
// Moving to next block: Reset bit offset. | ||
bitOffset = 0 | ||
byteOffset += current.count * blockBytes | ||
byteOffset += (current.count * blockBytes) - firstOffset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so is this because the current.count of the first byte is not 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its because the offset is already calculated and we readd the whole node block count here. This is effective only in scenario where the start is not the from 0 byte and its part of the head RLE node
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry maybe I'm missing something but if it is part of the head, the current.count should not equal to 0 and so the byteOffset is not modified by the original code?
6180b85
to
61b4076
Compare
74740ea
to
2ce82e5
Compare
Have not reviewed the code, but very much like the concept. This will provide the gossip control plane maximum time to settle during task churn. |
@trapier gossip control plane is a transportation mean, does not take any decision on IP matter also the key of every element is the endpoint ID that is unique. |
Understood @fcrisciani. What I was thinking is if there are many joins and leaves occurring at the same time on a particular network (and despite the fact that it has a lamport clock), numerically ordered ip allocation will reduce the likelihood of same-time same-address events on the control plane. |
@trapier sure, but the problem would be in the application layer, because from a networkdb point of view each single event will have a different endpoint ID so a different key and no collision would be possible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor Comment. LGTM otherwise.
Can you pls address all other open comments ?
ipamapi/labels.go
Outdated
|
||
// AllocSerialPrefix constant marks the reserved label space for libnetwork ipam | ||
// allocation ordering.(serial/first available) | ||
AllocSerialPrefix = Prefix + ".serial" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you pls make this .ipam.serial
@abhi ping @fcrisciani are you good with this change ? |
Previously the bitseq alloc was allocating the first available bit from the begining of the sequence. With this commit the bitseq alloc will proceed from the current allocation. This change will affect the way ipam and vni allocation is done currently. The ip allocation will be done sequentially from the previous allocation as opposed to the first available IP. Signed-off-by: Abhinandan Prativadi <[email protected]>
Since bit allocation is no longer first available from the start some verfications are removed/modified to the change allocation model Signed-off-by: Abhinandan Prativadi <[email protected]>
Codecov Report
@@ Coverage Diff @@
## master #1788 +/- ##
=========================================
Coverage ? 38.02%
=========================================
Files ? 137
Lines ? 27313
Branches ? 0
=========================================
Hits ? 10386
Misses ? 15656
Partials ? 1271
Continue to review full report at Codecov.
|
@mavenugo will give another pass within the eod |
idm/idm.go
Outdated
@@ -38,7 +38,7 @@ func (i *Idm) GetID() (uint64, error) { | |||
if i.handle == nil { | |||
return 0, errors.New("ID set is not initialized") | |||
} | |||
ordinal, err := i.handle.SetAny() | |||
ordinal, err := i.handle.SetAny(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't we need the same sequential allocation for the vxlan? else we are going to hit the vxlan interface file already exists
correct?
ipamapi/labels.go
Outdated
|
||
// AllocSerialPrefix constant marks the reserved label space for libnetwork ipam | ||
// allocation ordering.(serial/first available) | ||
AllocSerialPrefix = Prefix + "ipam.serial" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't we need a point in the middle?
com.docker.network . ipam.serial?
Please sign your commits following these rules: $ git clone -b "ipam_alloc" [email protected]:abhi/libnetwork.git somewhere
$ cd somewhere
$ git rebase -i HEAD~842354211816
editor opens
change each 'pick' to 'edit'
save the file and quit
$ git commit --amend -s --no-edit
$ git rebase --continue # and repeat the amend for each commit
$ git push -f Amending updates the existing PR. You DO NOT need to open a new one. |
Signed-off-by: Abhinandan Prativadi <[email protected]>
@@ -56,7 +56,7 @@ func (i *Idm) GetSpecificID(id uint64) error { | |||
} | |||
|
|||
// GetIDInRange returns the first available id in the set within a [start,end] range |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this is anymore accurate, correct? (being a comment it's not critical, can be handled on top)
|
||
i.Release(52) | ||
err = i.GetSpecificID(52) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you check that is also 52 the value?
2 small comments, rest LGTM |
Backport Serializing bitseq alloc (#1788)
Previously the bitseq alloc was allocating the first available bit from the beginning of the bit sequence for each sequence handle. With this commit the bitseq alloc will proceed
from the current allocation. This change will affect the way ipam and vni
allocation is done currently. The ip allocation will prcoeeed sequentially from the previous allocation as opposed to the first available IP. So even if the IPs are released it will not be reused until the allocator rolls over to the beginner of the bit sequence.
The commit also contains a fix for byteoffset allocation which plays a role in calculating the allocated ordinal. This scenerio play when the starting ordinal is part of the head sequence block and the available bit is part of subsequent blocks in the bitseq.
Signed-off-by: Abhinandan Prativadi [email protected]