mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Use a structure to keep the allocated ips pool.
Fixes #11624. Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
bcb369af11
commit
7e95b13460
3 changed files with 128 additions and 111 deletions
|
@ -80,6 +80,7 @@ var (
|
|||
|
||||
defaultBindingIP = net.ParseIP("0.0.0.0")
|
||||
currentInterfaces = ifaces{c: make(map[string]*networkInterface)}
|
||||
ipAllocator = ipallocator.New()
|
||||
)
|
||||
|
||||
func InitDriver(job *engine.Job) engine.Status {
|
||||
|
@ -244,7 +245,7 @@ func InitDriver(job *engine.Job) engine.Status {
|
|||
return job.Error(err)
|
||||
}
|
||||
log.Debugf("Subnet: %v", subnet)
|
||||
if err := ipallocator.RegisterSubnet(bridgeIPv4Network, subnet); err != nil {
|
||||
if err := ipAllocator.RegisterSubnet(bridgeIPv4Network, subnet); err != nil {
|
||||
return job.Error(err)
|
||||
}
|
||||
}
|
||||
|
@ -255,14 +256,14 @@ func InitDriver(job *engine.Job) engine.Status {
|
|||
return job.Error(err)
|
||||
}
|
||||
log.Debugf("Subnet: %v", subnet)
|
||||
if err := ipallocator.RegisterSubnet(subnet, subnet); err != nil {
|
||||
if err := ipAllocator.RegisterSubnet(subnet, subnet); err != nil {
|
||||
return job.Error(err)
|
||||
}
|
||||
globalIPv6Network = subnet
|
||||
}
|
||||
|
||||
// Block BridgeIP in IP allocator
|
||||
ipallocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
|
||||
ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP)
|
||||
|
||||
// https://github.com/docker/docker/issues/2768
|
||||
job.Eng.Hack_SetGlobalVar("httpapi.bridgeIP", bridgeIPv4Network.IP)
|
||||
|
@ -509,7 +510,7 @@ func Allocate(job *engine.Job) engine.Status {
|
|||
globalIPv6 net.IP
|
||||
)
|
||||
|
||||
ip, err = ipallocator.RequestIP(bridgeIPv4Network, requestedIP)
|
||||
ip, err = ipAllocator.RequestIP(bridgeIPv4Network, requestedIP)
|
||||
if err != nil {
|
||||
return job.Error(err)
|
||||
}
|
||||
|
@ -530,7 +531,7 @@ func Allocate(job *engine.Job) engine.Status {
|
|||
}
|
||||
}
|
||||
|
||||
globalIPv6, err = ipallocator.RequestIP(globalIPv6Network, requestedIPv6)
|
||||
globalIPv6, err = ipAllocator.RequestIP(globalIPv6Network, requestedIPv6)
|
||||
if err != nil {
|
||||
log.Errorf("Allocator: RequestIP v6: %v", err)
|
||||
return job.Error(err)
|
||||
|
@ -591,11 +592,11 @@ func Release(job *engine.Job) engine.Status {
|
|||
}
|
||||
}
|
||||
|
||||
if err := ipallocator.ReleaseIP(bridgeIPv4Network, containerInterface.IP); err != nil {
|
||||
if err := ipAllocator.ReleaseIP(bridgeIPv4Network, containerInterface.IP); err != nil {
|
||||
log.Infof("Unable to release IPv4 %s", err)
|
||||
}
|
||||
if globalIPv6Network != nil {
|
||||
if err := ipallocator.ReleaseIP(globalIPv6Network, containerInterface.IPv6); err != nil {
|
||||
if err := ipAllocator.ReleaseIP(globalIPv6Network, containerInterface.IPv6); err != nil {
|
||||
log.Infof("Unable to release IPv6 %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,19 +41,24 @@ var (
|
|||
ErrBadSubnet = errors.New("network does not contain specified subnet")
|
||||
)
|
||||
|
||||
var (
|
||||
lock = sync.Mutex{}
|
||||
allocatedIPs = networkSet{}
|
||||
)
|
||||
type IPAllocator struct {
|
||||
allocatedIPs networkSet
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
func New() *IPAllocator {
|
||||
return &IPAllocator{networkSet{}, sync.Mutex{}}
|
||||
}
|
||||
|
||||
// RegisterSubnet registers network in global allocator with bounds
|
||||
// defined by subnet. If you want to use network range you must call
|
||||
// this method before first RequestIP, otherwise full network range will be used
|
||||
func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
func (a *IPAllocator) RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
|
||||
a.mutex.Lock()
|
||||
defer a.mutex.Unlock()
|
||||
|
||||
key := network.String()
|
||||
if _, ok := allocatedIPs[key]; ok {
|
||||
if _, ok := a.allocatedIPs[key]; ok {
|
||||
return ErrNetworkAlreadyRegistered
|
||||
}
|
||||
n := newAllocatedMap(network)
|
||||
|
@ -68,7 +73,7 @@ func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
|
|||
n.begin.Set(begin)
|
||||
n.end.Set(end)
|
||||
n.last.Sub(begin, big.NewInt(1))
|
||||
allocatedIPs[key] = n
|
||||
a.allocatedIPs[key] = n
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -76,14 +81,15 @@ func RegisterSubnet(network *net.IPNet, subnet *net.IPNet) error {
|
|||
// will return the next available ip if the ip provided is nil. If the
|
||||
// ip provided is not nil it will validate that the provided ip is available
|
||||
// for use or return an error
|
||||
func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
func (a *IPAllocator) RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
|
||||
a.mutex.Lock()
|
||||
defer a.mutex.Unlock()
|
||||
|
||||
key := network.String()
|
||||
allocated, ok := allocatedIPs[key]
|
||||
allocated, ok := a.allocatedIPs[key]
|
||||
if !ok {
|
||||
allocated = newAllocatedMap(network)
|
||||
allocatedIPs[key] = allocated
|
||||
a.allocatedIPs[key] = allocated
|
||||
}
|
||||
|
||||
if ip == nil {
|
||||
|
@ -94,10 +100,11 @@ func RequestIP(network *net.IPNet, ip net.IP) (net.IP, error) {
|
|||
|
||||
// ReleaseIP adds the provided ip back into the pool of
|
||||
// available ips to be returned for use.
|
||||
func ReleaseIP(network *net.IPNet, ip net.IP) error {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if allocated, exists := allocatedIPs[network.String()]; exists {
|
||||
func (a *IPAllocator) ReleaseIP(network *net.IPNet, ip net.IP) error {
|
||||
a.mutex.Lock()
|
||||
defer a.mutex.Unlock()
|
||||
|
||||
if allocated, exists := a.allocatedIPs[network.String()]; exists {
|
||||
delete(allocated.p, ip.String())
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -7,10 +7,6 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func reset() {
|
||||
allocatedIPs = networkSet{}
|
||||
}
|
||||
|
||||
func TestConversion(t *testing.T) {
|
||||
ip := net.ParseIP("127.0.0.1")
|
||||
i := ipToBigInt(ip)
|
||||
|
@ -52,7 +48,8 @@ func TestConversionIPv6(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRequestNewIps(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -62,7 +59,7 @@ func TestRequestNewIps(t *testing.T) {
|
|||
var err error
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
ip, err = RequestIP(network, nil)
|
||||
ip, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -72,10 +69,10 @@ func TestRequestNewIps(t *testing.T) {
|
|||
}
|
||||
}
|
||||
value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip, err = RequestIP(network, nil)
|
||||
ip, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -85,7 +82,8 @@ func TestRequestNewIps(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRequestNewIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
|
@ -94,7 +92,7 @@ func TestRequestNewIpV6(t *testing.T) {
|
|||
var ip net.IP
|
||||
var err error
|
||||
for i := 1; i < 10; i++ {
|
||||
ip, err = RequestIP(network, nil)
|
||||
ip, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -104,10 +102,10 @@ func TestRequestNewIpV6(t *testing.T) {
|
|||
}
|
||||
}
|
||||
value := bigIntToIP(big.NewInt(0).Add(ipToBigInt(ip), big.NewInt(1))).String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip, err = RequestIP(network, nil)
|
||||
ip, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -117,68 +115,70 @@ func TestRequestNewIpV6(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestReleaseIp(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
}
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
}
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetReleasedIp(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
}
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value := ip.String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < 253; i++ {
|
||||
_, err = RequestIP(network, nil)
|
||||
_, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ReleaseIP(network, ip)
|
||||
err = a.ReleaseIP(network, ip)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
ip, err = RequestIP(network, nil)
|
||||
ip, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -189,34 +189,35 @@ func TestGetReleasedIp(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetReleasedIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0},
|
||||
}
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
value := ip.String()
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < 253; i++ {
|
||||
_, err = RequestIP(network, nil)
|
||||
_, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ReleaseIP(network, ip)
|
||||
err = a.ReleaseIP(network, ip)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
ip, err = RequestIP(network, nil)
|
||||
ip, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -227,7 +228,8 @@ func TestGetReleasedIpV6(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRequestSpecificIp(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 224},
|
||||
|
@ -236,23 +238,24 @@ func TestRequestSpecificIp(t *testing.T) {
|
|||
ip := net.ParseIP("192.168.0.5")
|
||||
|
||||
// Request a "good" IP.
|
||||
if _, err := RequestIP(network, ip); err != nil {
|
||||
if _, err := a.RequestIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Request the same IP again.
|
||||
if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||||
if _, err := a.RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||||
t.Fatalf("Got the same IP twice: %#v", err)
|
||||
}
|
||||
|
||||
// Request an out of range IP.
|
||||
if _, err := RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
|
||||
if _, err := a.RequestIP(network, net.ParseIP("192.168.0.42")); err != ErrIPOutOfRange {
|
||||
t.Fatalf("Got an out of range IP: %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequestSpecificIpV6(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{0x2a, 0x00, 0x14, 0x50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}, // /64 netmask
|
||||
|
@ -261,22 +264,24 @@ func TestRequestSpecificIpV6(t *testing.T) {
|
|||
ip := net.ParseIP("2a00:1450::5")
|
||||
|
||||
// Request a "good" IP.
|
||||
if _, err := RequestIP(network, ip); err != nil {
|
||||
if _, err := a.RequestIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Request the same IP again.
|
||||
if _, err := RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||||
if _, err := a.RequestIP(network, ip); err != ErrIPAlreadyAllocated {
|
||||
t.Fatalf("Got the same IP twice: %#v", err)
|
||||
}
|
||||
|
||||
// Request an out of range IP.
|
||||
if _, err := RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
|
||||
if _, err := a.RequestIP(network, net.ParseIP("2a00:1500::1")); err != ErrIPOutOfRange {
|
||||
t.Fatalf("Got an out of range IP: %#v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPAllocator(t *testing.T) {
|
||||
a := New()
|
||||
|
||||
expectedIPs := []net.IP{
|
||||
0: net.IPv4(127, 0, 0, 1),
|
||||
1: net.IPv4(127, 0, 0, 2),
|
||||
|
@ -296,7 +301,7 @@ func TestIPAllocator(t *testing.T) {
|
|||
// Check that we get 6 IPs, from 127.0.0.1–127.0.0.6, in that
|
||||
// order.
|
||||
for i := 0; i < 6; i++ {
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -332,25 +337,25 @@ func TestIPAllocator(t *testing.T) {
|
|||
// ↑
|
||||
|
||||
// Check that there are no more IPs
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err == nil {
|
||||
t.Fatalf("There shouldn't be any IP addresses at this point, got %s\n", ip)
|
||||
}
|
||||
|
||||
// Release some IPs in non-sequential order
|
||||
if err := ReleaseIP(network, expectedIPs[3]); err != nil {
|
||||
if err := a.ReleaseIP(network, expectedIPs[3]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// 1(u) - 2(u) - 3(u) - 4(f) - 5(u) - 6(u)
|
||||
// ↑
|
||||
|
||||
if err := ReleaseIP(network, expectedIPs[2]); err != nil {
|
||||
if err := a.ReleaseIP(network, expectedIPs[2]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// 1(u) - 2(u) - 3(f) - 4(f) - 5(u) - 6(u)
|
||||
// ↑
|
||||
|
||||
if err := ReleaseIP(network, expectedIPs[4]); err != nil {
|
||||
if err := a.ReleaseIP(network, expectedIPs[4]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// 1(u) - 2(u) - 3(f) - 4(f) - 5(f) - 6(u)
|
||||
|
@ -360,7 +365,7 @@ func TestIPAllocator(t *testing.T) {
|
|||
// with the first released IP
|
||||
newIPs := make([]net.IP, 3)
|
||||
for i := 0; i < 3; i++ {
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -371,14 +376,15 @@ func TestIPAllocator(t *testing.T) {
|
|||
assertIPEquals(t, expectedIPs[3], newIPs[1])
|
||||
assertIPEquals(t, expectedIPs[4], newIPs[2])
|
||||
|
||||
_, err = RequestIP(network, nil)
|
||||
_, err = a.RequestIP(network, nil)
|
||||
if err == nil {
|
||||
t.Fatal("There shouldn't be any IP addresses at this point")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateFirstIP(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 0},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -387,7 +393,7 @@ func TestAllocateFirstIP(t *testing.T) {
|
|||
firstIP := network.IP.To4().Mask(network.Mask)
|
||||
first := big.NewInt(0).Add(ipToBigInt(firstIP), big.NewInt(1))
|
||||
|
||||
ip, err := RequestIP(network, nil)
|
||||
ip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -399,7 +405,8 @@ func TestAllocateFirstIP(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAllocateAllIps(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -412,7 +419,7 @@ func TestAllocateAllIps(t *testing.T) {
|
|||
)
|
||||
|
||||
for err == nil {
|
||||
current, err = RequestIP(network, nil)
|
||||
current, err = a.RequestIP(network, nil)
|
||||
if isFirst {
|
||||
first = current
|
||||
isFirst = false
|
||||
|
@ -423,15 +430,15 @@ func TestAllocateAllIps(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||||
if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ReleaseIP(network, first); err != nil {
|
||||
if err := a.ReleaseIP(network, first); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
again, err := RequestIP(network, nil)
|
||||
again, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -439,17 +446,17 @@ func TestAllocateAllIps(t *testing.T) {
|
|||
assertIPEquals(t, first, again)
|
||||
|
||||
// ensure that alloc.last == alloc.begin won't result in dead loop
|
||||
if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||||
if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test by making alloc.last the only free ip and ensure we get it back
|
||||
// #1. first of the range, (alloc.last == ipToInt(first) already)
|
||||
if err := ReleaseIP(network, first); err != nil {
|
||||
if err := a.ReleaseIP(network, first); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ret, err := RequestIP(network, nil)
|
||||
ret, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -458,9 +465,9 @@ func TestAllocateAllIps(t *testing.T) {
|
|||
|
||||
// #2. last of the range, note that current is the last one
|
||||
last := net.IPv4(192, 168, 0, 254)
|
||||
setLastTo(t, network, last)
|
||||
setLastTo(t, a, network, last)
|
||||
|
||||
ret, err = RequestIP(network, nil)
|
||||
ret, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -469,9 +476,9 @@ func TestAllocateAllIps(t *testing.T) {
|
|||
|
||||
// #3. middle of the range
|
||||
mid := net.IPv4(192, 168, 0, 7)
|
||||
setLastTo(t, network, mid)
|
||||
setLastTo(t, a, network, mid)
|
||||
|
||||
ret, err = RequestIP(network, nil)
|
||||
ret, err = a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -481,25 +488,25 @@ func TestAllocateAllIps(t *testing.T) {
|
|||
|
||||
// make sure the pool is full when calling setLastTo.
|
||||
// we don't cheat here
|
||||
func setLastTo(t *testing.T, network *net.IPNet, ip net.IP) {
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
func setLastTo(t *testing.T, a *IPAllocator, network *net.IPNet, ip net.IP) {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ret, err := RequestIP(network, nil)
|
||||
ret, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertIPEquals(t, ip, ret)
|
||||
|
||||
if err := ReleaseIP(network, ip); err != nil {
|
||||
if err := a.ReleaseIP(network, ip); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateDifferentSubnets(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
network1 := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -528,39 +535,39 @@ func TestAllocateDifferentSubnets(t *testing.T) {
|
|||
8: net.ParseIP("2a00:1632::2"),
|
||||
}
|
||||
|
||||
ip11, err := RequestIP(network1, nil)
|
||||
ip11, err := a.RequestIP(network1, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip12, err := RequestIP(network1, nil)
|
||||
ip12, err := a.RequestIP(network1, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip21, err := RequestIP(network2, nil)
|
||||
ip21, err := a.RequestIP(network2, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip22, err := RequestIP(network2, nil)
|
||||
ip22, err := a.RequestIP(network2, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip31, err := RequestIP(network3, nil)
|
||||
ip31, err := a.RequestIP(network3, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip32, err := RequestIP(network3, nil)
|
||||
ip32, err := a.RequestIP(network3, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip33, err := RequestIP(network3, nil)
|
||||
ip33, err := a.RequestIP(network3, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip41, err := RequestIP(network4, nil)
|
||||
ip41, err := a.RequestIP(network4, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ip42, err := RequestIP(network4, nil)
|
||||
ip42, err := a.RequestIP(network4, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -576,7 +583,7 @@ func TestAllocateDifferentSubnets(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRegisterBadTwice(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 1, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -586,20 +593,20 @@ func TestRegisterBadTwice(t *testing.T) {
|
|||
Mask: []byte{255, 255, 255, 248},
|
||||
}
|
||||
|
||||
if err := RegisterSubnet(network, subnet); err != nil {
|
||||
if err := a.RegisterSubnet(network, subnet); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
subnet = &net.IPNet{
|
||||
IP: []byte{192, 168, 1, 16},
|
||||
Mask: []byte{255, 255, 255, 248},
|
||||
}
|
||||
if err := RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
|
||||
if err := a.RegisterSubnet(network, subnet); err != ErrNetworkAlreadyRegistered {
|
||||
t.Fatalf("Expecteded ErrNetworkAlreadyRegistered error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterBadRange(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 1, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -608,13 +615,13 @@ func TestRegisterBadRange(t *testing.T) {
|
|||
IP: []byte{192, 168, 1, 1},
|
||||
Mask: []byte{255, 255, 0, 0},
|
||||
}
|
||||
if err := RegisterSubnet(network, subnet); err != ErrBadSubnet {
|
||||
if err := a.RegisterSubnet(network, subnet); err != ErrBadSubnet {
|
||||
t.Fatalf("Expected ErrBadSubnet error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllocateFromRange(t *testing.T) {
|
||||
defer reset()
|
||||
a := New()
|
||||
network := &net.IPNet{
|
||||
IP: []byte{192, 168, 0, 1},
|
||||
Mask: []byte{255, 255, 255, 0},
|
||||
|
@ -625,7 +632,7 @@ func TestAllocateFromRange(t *testing.T) {
|
|||
Mask: []byte{255, 255, 255, 248},
|
||||
}
|
||||
|
||||
if err := RegisterSubnet(network, subnet); err != nil {
|
||||
if err := a.RegisterSubnet(network, subnet); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedIPs := []net.IP{
|
||||
|
@ -637,19 +644,19 @@ func TestAllocateFromRange(t *testing.T) {
|
|||
5: net.IPv4(192, 168, 0, 14),
|
||||
}
|
||||
for _, ip := range expectedIPs {
|
||||
rip, err := RequestIP(network, nil)
|
||||
rip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertIPEquals(t, ip, rip)
|
||||
}
|
||||
|
||||
if _, err := RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||||
if _, err := a.RequestIP(network, nil); err != ErrNoAvailableIPs {
|
||||
t.Fatalf("Expected ErrNoAvailableIPs error, got %v", err)
|
||||
}
|
||||
for _, ip := range expectedIPs {
|
||||
ReleaseIP(network, ip)
|
||||
rip, err := RequestIP(network, nil)
|
||||
a.ReleaseIP(network, ip)
|
||||
rip, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -669,13 +676,15 @@ func BenchmarkRequestIP(b *testing.B) {
|
|||
Mask: []byte{255, 255, 255, 0},
|
||||
}
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
a := New()
|
||||
|
||||
for j := 0; j < 253; j++ {
|
||||
_, err := RequestIP(network, nil)
|
||||
_, err := a.RequestIP(network, nil)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue