diff --git a/daemon/networkdriver/bridge/driver.go b/daemon/networkdriver/bridge/driver.go index b8dfdf9488..f0fa772bdb 100644 --- a/daemon/networkdriver/bridge/driver.go +++ b/daemon/networkdriver/bridge/driver.go @@ -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) } } diff --git a/daemon/networkdriver/ipallocator/allocator.go b/daemon/networkdriver/ipallocator/allocator.go index a728d1bac4..628500d0d9 100644 --- a/daemon/networkdriver/ipallocator/allocator.go +++ b/daemon/networkdriver/ipallocator/allocator.go @@ -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 diff --git a/daemon/networkdriver/ipallocator/allocator_test.go b/daemon/networkdriver/ipallocator/allocator_test.go index 8e0d8fdca6..fffe6e3389 100644 --- a/daemon/networkdriver/ipallocator/allocator_test.go +++ b/daemon/networkdriver/ipallocator/allocator_test.go @@ -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() } }