|
@@ -3,6 +3,7 @@ package ipam
|
|
import (
|
|
import (
|
|
"fmt"
|
|
"fmt"
|
|
"net"
|
|
"net"
|
|
|
|
+ "sync"
|
|
|
|
|
|
"github.com/docker/libnetwork/bitseq"
|
|
"github.com/docker/libnetwork/bitseq"
|
|
)
|
|
)
|
|
@@ -25,6 +26,7 @@ type Allocator struct {
|
|
subnetsInfo map[subnetKey]*subnetData
|
|
subnetsInfo map[subnetKey]*subnetData
|
|
// Allocated addresses in each address space's internal subnet
|
|
// Allocated addresses in each address space's internal subnet
|
|
addresses map[isKey]*bitmask
|
|
addresses map[isKey]*bitmask
|
|
|
|
+ sync.Mutex
|
|
}
|
|
}
|
|
|
|
|
|
// NewAllocator returns an instance of libnetwork ipam
|
|
// 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
|
|
// Store the configured subnet information
|
|
subnetKey := subnetKey{addrSpace, subnetInfo.Subnet.String()}
|
|
subnetKey := subnetKey{addrSpace, subnetInfo.Subnet.String()}
|
|
info := &subnetData{info: subnetInfo, intSubKeyes: make([]*isKey, len(subnetList))}
|
|
info := &subnetData{info: subnetInfo, intSubKeyes: make([]*isKey, len(subnetList))}
|
|
|
|
+ a.Lock()
|
|
a.subnetsInfo[subnetKey] = info
|
|
a.subnetsInfo[subnetKey] = info
|
|
|
|
+ a.Unlock()
|
|
|
|
|
|
// Create and insert the internal subnet(s) addresses masks into the address database
|
|
// Create and insert the internal subnet(s) addresses masks into the address database
|
|
for i, sub := range subnetList {
|
|
for i, sub := range subnetList {
|
|
@@ -111,11 +115,13 @@ func (a *Allocator) AddSubnet(addrSpace AddressSpace, subnetInfo *SubnetInfo) er
|
|
info.intSubKeyes[i] = smallKey
|
|
info.intSubKeyes[i] = smallKey
|
|
|
|
|
|
// Add the new address masks
|
|
// Add the new address masks
|
|
|
|
+ a.Lock()
|
|
a.addresses[*smallKey] = &bitmask{
|
|
a.addresses[*smallKey] = &bitmask{
|
|
subnet: sub,
|
|
subnet: sub,
|
|
addressMask: bitseq.New(uint32(numAddresses)),
|
|
addressMask: bitseq.New(uint32(numAddresses)),
|
|
freeAddresses: numAddresses,
|
|
freeAddresses: numAddresses,
|
|
}
|
|
}
|
|
|
|
+ a.Unlock()
|
|
}
|
|
}
|
|
|
|
|
|
return nil
|
|
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
|
|
// 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 {
|
|
func (a *Allocator) contains(space AddressSpace, subInfo *SubnetInfo) bool {
|
|
|
|
+ a.Lock()
|
|
|
|
+ defer a.Unlock()
|
|
for k, v := range a.subnetsInfo {
|
|
for k, v := range a.subnetsInfo {
|
|
if space == k.addressSpace {
|
|
if space == k.addressSpace {
|
|
if subInfo.Subnet.Contains(v.info.Subnet.IP) ||
|
|
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
|
|
// Look for the respective subnet configuration data
|
|
// Remove it along with the internal subnets
|
|
// Remove it along with the internal subnets
|
|
subKey := subnetKey{addrSpace, subnet.String()}
|
|
subKey := subnetKey{addrSpace, subnet.String()}
|
|
|
|
+ a.Lock()
|
|
subData, ok := a.subnetsInfo[subKey]
|
|
subData, ok := a.subnetsInfo[subKey]
|
|
|
|
+ a.Unlock()
|
|
if !ok {
|
|
if !ok {
|
|
return ErrSubnetNotFound
|
|
return ErrSubnetNotFound
|
|
}
|
|
}
|
|
|
|
|
|
for _, key := range subData.intSubKeyes {
|
|
for _, key := range subData.intSubKeyes {
|
|
|
|
+ a.Lock()
|
|
delete(a.addresses, *key)
|
|
delete(a.addresses, *key)
|
|
|
|
+ a.Unlock()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ a.Lock()
|
|
delete(a.subnetsInfo, subKey)
|
|
delete(a.subnetsInfo, subKey)
|
|
|
|
+ a.Unlock()
|
|
|
|
|
|
return nil
|
|
return nil
|
|
|
|
|
|
@@ -259,7 +273,9 @@ func (a *Allocator) request(addrSpace AddressSpace, req *AddressRequest, version
|
|
if err == nil {
|
|
if err == nil {
|
|
// Populate response
|
|
// Populate response
|
|
response.Address = ip
|
|
response.Address = ip
|
|
|
|
+ a.Lock()
|
|
response.Subnet = *a.subnetsInfo[subnetKey{addrSpace, req.Subnet.String()}].info
|
|
response.Subnet = *a.subnetsInfo[subnetKey{addrSpace, req.Subnet.String()}].info
|
|
|
|
+ a.Unlock()
|
|
}
|
|
}
|
|
|
|
|
|
return response, err
|
|
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
|
|
// Get the list of pointers to the internal subnets
|
|
if subnet != nil {
|
|
if subnet != nil {
|
|
|
|
+ a.Lock()
|
|
keyList = a.subnetsInfo[subnetKey{addrSpace, subnet.String()}].intSubKeyes
|
|
keyList = a.subnetsInfo[subnetKey{addrSpace, subnet.String()}].intSubKeyes
|
|
|
|
+ a.Unlock()
|
|
} else {
|
|
} else {
|
|
|
|
+ a.Lock()
|
|
keyList = a.getSubnetList(addrSpace, ver)
|
|
keyList = a.getSubnetList(addrSpace, ver)
|
|
|
|
+ a.Unlock()
|
|
}
|
|
}
|
|
if len(keyList) == 0 {
|
|
if len(keyList) == 0 {
|
|
return nil, nil, ErrNoAvailableSubnet
|
|
return nil, nil, ErrNoAvailableSubnet
|
|
}
|
|
}
|
|
|
|
|
|
for _, key := range keyList {
|
|
for _, key := range keyList {
|
|
|
|
+ a.Lock()
|
|
smallSubnet := a.addresses[*key]
|
|
smallSubnet := a.addresses[*key]
|
|
|
|
+ a.Unlock()
|
|
address, err := a.getAddress(smallSubnet, prefAddress, ver)
|
|
address, err := a.getAddress(smallSubnet, prefAddress, ver)
|
|
if err == nil {
|
|
if err == nil {
|
|
return address, subnet, 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 {
|
|
func (a *Allocator) getSubnetList(addrSpace AddressSpace, ver ipVersion) []*isKey {
|
|
var list [1024]*isKey
|
|
var list [1024]*isKey
|
|
ind := 0
|
|
ind := 0
|
|
|
|
+ a.Lock()
|
|
for subKey := range a.addresses {
|
|
for subKey := range a.addresses {
|
|
_, s, _ := net.ParseCIDR(subKey.subnet)
|
|
_, s, _ := net.ParseCIDR(subKey.subnet)
|
|
subVer := getAddressVersion(s.IP)
|
|
subVer := getAddressVersion(s.IP)
|
|
@@ -324,6 +347,7 @@ func (a *Allocator) getSubnetList(addrSpace AddressSpace, ver ipVersion) []*isKe
|
|
ind++
|
|
ind++
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ a.Unlock()
|
|
return list[0:ind]
|
|
return list[0:ind]
|
|
}
|
|
}
|
|
|
|
|
|
@@ -364,6 +388,8 @@ again:
|
|
|
|
|
|
// DumpDatabase dumps the internal info
|
|
// DumpDatabase dumps the internal info
|
|
func (a *Allocator) DumpDatabase() {
|
|
func (a *Allocator) DumpDatabase() {
|
|
|
|
+ a.Lock()
|
|
|
|
+ defer a.Unlock()
|
|
for _, config := range a.subnetsInfo {
|
|
for _, config := range a.subnetsInfo {
|
|
fmt.Printf("\n\n%s:", config.info.Subnet.String())
|
|
fmt.Printf("\n\n%s:", config.info.Subnet.String())
|
|
for _, internKey := range config.intSubKeyes {
|
|
for _, internKey := range config.intSubKeyes {
|