From 55e0fe24db68b16edccb2fa49c3b1b9d3a9ce58c Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 14 Mar 2018 12:44:22 +0100 Subject: [PATCH] Update libnetwork with fixes for duplicate IP addresses This updates libnetwork to 8892d7537c67232591f1f3af60587e3e77e61d41 to bring in IPAM fixes for duplicate IP addresses. - IPAM tests (libnetwork PR 2104) (no changes in vendored files) - Fix for Duplicate IP issues (libnetwork PR 2105) Also bump golang/x/sync to match libnetwork (no code-changes, other than the README being updated) Signed-off-by: Sebastiaan van Stijn --- hack/dockerfile/install/proxy.installer | 2 +- vendor.conf | 4 +- .../docker/libnetwork/bitseq/sequence.go | 73 +++++++++++++------ .../docker/libnetwork/ipam/allocator.go | 8 +- .../github.com/docker/libnetwork/vendor.conf | 1 + vendor/golang.org/x/sync/README | 2 - vendor/golang.org/x/sync/README.md | 18 +++++ 7 files changed, 75 insertions(+), 33 deletions(-) delete mode 100644 vendor/golang.org/x/sync/README create mode 100644 vendor/golang.org/x/sync/README.md diff --git a/hack/dockerfile/install/proxy.installer b/hack/dockerfile/install/proxy.installer index ed9ea7cbce..5a0cd585dc 100755 --- a/hack/dockerfile/install/proxy.installer +++ b/hack/dockerfile/install/proxy.installer @@ -3,7 +3,7 @@ # LIBNETWORK_COMMIT is used to build the docker-userland-proxy binary. When # updating the binary version, consider updating github.com/docker/libnetwork # in vendor.conf accordingly -LIBNETWORK_COMMIT=ed2130d117c11c542327b4d5216a5db36770bc65 +LIBNETWORK_COMMIT=8892d7537c67232591f1f3af60587e3e77e61d41 install_proxy() { case "$1" in diff --git a/vendor.conf b/vendor.conf index b769d4206a..9b5d5693cc 100644 --- a/vendor.conf +++ b/vendor.conf @@ -26,7 +26,7 @@ github.com/google/go-cmp v0.1.0 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 github.com/imdario/mergo 0.2.1 -golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 +golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5 github.com/moby/buildkit aaff9d591ef128560018433fe61beb802e149de8 github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 @@ -34,7 +34,7 @@ github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 #get libnetwork packages # When updating, also update LIBNETWORK_COMMIT in hack/dockerfile/install/proxy accordingly -github.com/docker/libnetwork 3aca383eb555510f3f17696f9505f7bfbd25f0e5 +github.com/docker/libnetwork 8892d7537c67232591f1f3af60587e3e77e61d41 github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec diff --git a/vendor/github.com/docker/libnetwork/bitseq/sequence.go b/vendor/github.com/docker/libnetwork/bitseq/sequence.go index a1a9810dc5..0069d495b7 100644 --- a/vendor/github.com/docker/libnetwork/bitseq/sequence.go +++ b/vendor/github.com/docker/libnetwork/bitseq/sequence.go @@ -108,6 +108,12 @@ func (s *sequence) getAvailableBit(from uint64) (uint64, uint64, error) { bitSel >>= 1 bits++ } + // Check if the loop exited because it could not + // find any available bit int block starting from + // "from". Return invalid pos in that case. + if bitSel == 0 { + return invalidPos, invalidPos, ErrNoBitAvailable + } return bits / 8, bits % 8, nil } @@ -313,14 +319,14 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial curr := uint64(0) h.Lock() store = h.store - h.Unlock() if store != nil { + h.Unlock() // The lock is acquired in the GetObject if err := store.GetObject(datastore.Key(h.Key()...), h); err != nil && err != datastore.ErrKeyNotFound { return ret, err } + h.Lock() // Acquire the lock back } - - h.Lock() + logrus.Debugf("Received set for ordinal %v, start %v, end %v, any %t, release %t, serial:%v curr:%d \n", ordinal, start, end, any, release, serial, h.curr) if serial { curr = h.curr } @@ -346,7 +352,6 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial // Create a private copy of h and work on it nh := h.getCopy() - h.Unlock() nh.head = pushReservation(bytePos, bitPos, nh.head, release) if release { @@ -355,22 +360,25 @@ func (h *Handle) set(ordinal, start, end uint64, any bool, release bool, serial nh.unselected-- } - // Attempt to write private copy to store - if err := nh.writeToStore(); err != nil { - if _, ok := err.(types.RetryError); !ok { - return ret, fmt.Errorf("internal failure while setting the bit: %v", err) + if h.store != nil { + h.Unlock() + // Attempt to write private copy to store + if err := nh.writeToStore(); err != nil { + if _, ok := err.(types.RetryError); !ok { + return ret, fmt.Errorf("internal failure while setting the bit: %v", err) + } + // Retry + continue } - // Retry - continue + h.Lock() } // Previous atomic push was succesfull. Save private copy to local copy - h.Lock() - defer h.Unlock() h.unselected = nh.unselected h.head = nh.head h.dbExists = nh.dbExists h.dbIndex = nh.dbIndex + h.Unlock() return ret, nil } } @@ -498,24 +506,40 @@ func (h *Handle) UnmarshalJSON(data []byte) 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) - + current, _, precBlocks, inBlockBytePos := findSequence(head, byteStart) // Derive the this sequence offsets byteOffset := byteStart - inBlockBytePos bitOffset := inBlockBytePos*8 + bitStart - var firstOffset uint64 - if current == head { - firstOffset = byteOffset - } for current != nil { if current.block != blockMAX { + // If the current block is not full, check if there is any bit + // from the current bit in the current block. If not, before proceeding to the + // next block node, make sure we check for available bit in the next + // instance of the same block. Due to RLE same block signature will be + // compressed. + retry: bytePos, bitPos, err := current.getAvailableBit(bitOffset) + if err != nil && precBlocks == current.count-1 { + // This is the last instance in the same block node, + // so move to the next block. + goto next + } + if err != nil { + // There are some more instances of the same block, so add the offset + // and be optimistic that you will find the available bit in the next + // instance of the same block. + bitOffset = 0 + byteOffset += blockBytes + precBlocks++ + goto retry + } return byteOffset + bytePos, bitPos, err } // Moving to next block: Reset bit offset. + next: bitOffset = 0 - byteOffset += (current.count * blockBytes) - firstOffset - firstOffset = 0 + byteOffset += (current.count * blockBytes) - (precBlocks * blockBytes) + precBlocks = 0 current = current.next } return invalidPos, invalidPos, ErrNoBitAvailable @@ -526,19 +550,20 @@ func getFirstAvailable(head *sequence, start uint64) (uint64, uint64, error) { // 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 + var err error if curr != 0 && curr > start { - bytePos, bitPos, _ = getFirstAvailable(head, curr) + bytePos, bitPos, err = getFirstAvailable(head, curr) ret := posToOrdinal(bytePos, bitPos) - if end < ret { + if end < ret || err != nil { goto begin } return bytePos, bitPos, nil } begin: - bytePos, bitPos, _ = getFirstAvailable(head, start) + bytePos, bitPos, err = getFirstAvailable(head, start) ret := posToOrdinal(bytePos, bitPos) - if end < ret { + if end < ret || err != nil { return invalidPos, invalidPos, ErrNoBitAvailable } return bytePos, bitPos, nil diff --git a/vendor/github.com/docker/libnetwork/ipam/allocator.go b/vendor/github.com/docker/libnetwork/ipam/allocator.go index 5beb429dfc..d1a91c077f 100644 --- a/vendor/github.com/docker/libnetwork/ipam/allocator.go +++ b/vendor/github.com/docker/libnetwork/ipam/allocator.go @@ -402,15 +402,15 @@ func (a *Allocator) getPredefinedPool(as string, ipV6 bool) (*net.IPNet, error) continue } aSpace.Lock() - _, ok := aSpace.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}] - aSpace.Unlock() - if ok { + if _, ok := aSpace.subnets[SubnetKey{AddressSpace: as, Subnet: nw.String()}]; ok { + aSpace.Unlock() continue } - if !aSpace.contains(as, nw) { + aSpace.Unlock() return nw, nil } + aSpace.Unlock() } return nil, types.NotFoundErrorf("could not find an available, non-overlapping IPv%d address pool among the defaults to assign to the network", v) diff --git a/vendor/github.com/docker/libnetwork/vendor.conf b/vendor/github.com/docker/libnetwork/vendor.conf index 73e2a6495b..3e7181564b 100644 --- a/vendor/github.com/docker/libnetwork/vendor.conf +++ b/vendor/github.com/docker/libnetwork/vendor.conf @@ -50,5 +50,6 @@ github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5 +golang.org/x/sync fd80eb99c8f653c847d294a001bdf2a3a6f768f5 github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 github.com/ishidawataru/sctp 07191f837fedd2f13d1ec7b5f885f0f3ec54b1cb diff --git a/vendor/golang.org/x/sync/README b/vendor/golang.org/x/sync/README deleted file mode 100644 index 59c9dcb498..0000000000 --- a/vendor/golang.org/x/sync/README +++ /dev/null @@ -1,2 +0,0 @@ -This repository provides Go concurrency primitives in addition to the -ones provided by the language and "sync" and "sync/atomic" packages. diff --git a/vendor/golang.org/x/sync/README.md b/vendor/golang.org/x/sync/README.md new file mode 100644 index 0000000000..1f8436cc9c --- /dev/null +++ b/vendor/golang.org/x/sync/README.md @@ -0,0 +1,18 @@ +# Go Sync + +This repository provides Go concurrency primitives in addition to the +ones provided by the language and "sync" and "sync/atomic" packages. + +## Download/Install + +The easiest way to install is to run `go get -u golang.org/x/sync`. You can +also manually git clone the repository to `$GOPATH/src/golang.org/x/sync`. + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://golang.org/doc/contribute.html. + +The main issue tracker for the sync repository is located at +https://github.com/golang/go/issues. Prefix your issue with "x/sync:" in the +subject line, so it is easy to find.