Add locking to libnetwork ipam
Signed-off-by: Alessandro Boch <aboch@docker.com>
This commit is contained in:
parent
75443aaf72
commit
a0e0d07250
|
@ -3,6 +3,7 @@ package ipam
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/libnetwork/bitseq"
|
||||
)
|
||||
|
@ -25,6 +26,7 @@ type Allocator struct {
|
|||
subnetsInfo map[subnetKey]*subnetData
|
||||
// Allocated addresses in each address space's internal subnet
|
||||
addresses map[isKey]*bitmask
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewAllocator returns an instance of libnetwork ipam
|
||||
|
@ -99,7 +101,9 @@ func (a *Allocator) AddSubnet(addrSpace AddressSpace, subnetInfo *SubnetInfo) er
|
|||
// Store the configured subnet information
|
||||
subnetKey := subnetKey{addrSpace, subnetInfo.Subnet.String()}
|
||||
info := &subnetData{info: subnetInfo, intSubKeyes: make([]*isKey, len(subnetList))}
|
||||
a.Lock()
|
||||
a.subnetsInfo[subnetKey] = info
|
||||
a.Unlock()
|
||||
|
||||
// Create and insert the internal subnet(s) addresses masks into the address database
|
||||
for i, sub := range subnetList {
|
||||
|
@ -111,11 +115,13 @@ func (a *Allocator) AddSubnet(addrSpace AddressSpace, subnetInfo *SubnetInfo) er
|
|||
info.intSubKeyes[i] = smallKey
|
||||
|
||||
// Add the new address masks
|
||||
a.Lock()
|
||||
a.addresses[*smallKey] = &bitmask{
|
||||
subnet: sub,
|
||||
addressMask: bitseq.New(uint32(numAddresses)),
|
||||
freeAddresses: numAddresses,
|
||||
}
|
||||
a.Unlock()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -143,6 +149,8 @@ func adjustAndCheckSubnetSize(subnet *net.IPNet) (*net.IPNet, error) {
|
|||
|
||||
// Checks whether the passed subnet is a superset or subset of any of the subset in the db
|
||||
func (a *Allocator) contains(space AddressSpace, subInfo *SubnetInfo) bool {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
for k, v := range a.subnetsInfo {
|
||||
if space == k.addressSpace {
|
||||
if subInfo.Subnet.Contains(v.info.Subnet.IP) ||
|
||||
|
@ -200,16 +208,22 @@ func (a *Allocator) RemoveSubnet(addrSpace AddressSpace, subnet *net.IPNet) erro
|
|||
// Look for the respective subnet configuration data
|
||||
// Remove it along with the internal subnets
|
||||
subKey := subnetKey{addrSpace, subnet.String()}
|
||||
a.Lock()
|
||||
subData, ok := a.subnetsInfo[subKey]
|
||||
a.Unlock()
|
||||
if !ok {
|
||||
return ErrSubnetNotFound
|
||||
}
|
||||
|
||||
for _, key := range subData.intSubKeyes {
|
||||
a.Lock()
|
||||
delete(a.addresses, *key)
|
||||
a.Unlock()
|
||||
}
|
||||
|
||||
a.Lock()
|
||||
delete(a.subnetsInfo, subKey)
|
||||
a.Unlock()
|
||||
|
||||
return nil
|
||||
|
||||
|
@ -259,7 +273,9 @@ func (a *Allocator) request(addrSpace AddressSpace, req *AddressRequest, version
|
|||
if err == nil {
|
||||
// Populate response
|
||||
response.Address = ip
|
||||
a.Lock()
|
||||
response.Subnet = *a.subnetsInfo[subnetKey{addrSpace, req.Subnet.String()}].info
|
||||
a.Unlock()
|
||||
}
|
||||
|
||||
return response, err
|
||||
|
@ -293,16 +309,22 @@ func (a *Allocator) reserveAddress(addrSpace AddressSpace, subnet *net.IPNet, pr
|
|||
|
||||
// Get the list of pointers to the internal subnets
|
||||
if subnet != nil {
|
||||
a.Lock()
|
||||
keyList = a.subnetsInfo[subnetKey{addrSpace, subnet.String()}].intSubKeyes
|
||||
a.Unlock()
|
||||
} else {
|
||||
a.Lock()
|
||||
keyList = a.getSubnetList(addrSpace, ver)
|
||||
a.Unlock()
|
||||
}
|
||||
if len(keyList) == 0 {
|
||||
return nil, nil, ErrNoAvailableSubnet
|
||||
}
|
||||
|
||||
for _, key := range keyList {
|
||||
a.Lock()
|
||||
smallSubnet := a.addresses[*key]
|
||||
a.Unlock()
|
||||
address, err := a.getAddress(smallSubnet, prefAddress, ver)
|
||||
if err == nil {
|
||||
return address, subnet, nil
|
||||
|
@ -316,6 +338,7 @@ func (a *Allocator) reserveAddress(addrSpace AddressSpace, subnet *net.IPNet, pr
|
|||
func (a *Allocator) getSubnetList(addrSpace AddressSpace, ver ipVersion) []*isKey {
|
||||
var list [1024]*isKey
|
||||
ind := 0
|
||||
a.Lock()
|
||||
for subKey := range a.addresses {
|
||||
_, s, _ := net.ParseCIDR(subKey.subnet)
|
||||
subVer := getAddressVersion(s.IP)
|
||||
|
@ -324,6 +347,7 @@ func (a *Allocator) getSubnetList(addrSpace AddressSpace, ver ipVersion) []*isKe
|
|||
ind++
|
||||
}
|
||||
}
|
||||
a.Unlock()
|
||||
return list[0:ind]
|
||||
}
|
||||
|
||||
|
@ -364,6 +388,8 @@ again:
|
|||
|
||||
// DumpDatabase dumps the internal info
|
||||
func (a *Allocator) DumpDatabase() {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
for _, config := range a.subnetsInfo {
|
||||
fmt.Printf("\n\n%s:", config.info.Subnet.String())
|
||||
for _, internKey := range config.intSubKeyes {
|
||||
|
|
Loading…
Reference in New Issue