github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/ipam/allocator_test.go (about)

     1  package ipam
     2  
     3  import (
     4  	"encoding/json"
     5  	"flag"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"math/rand"
     9  	"net"
    10  	"strconv"
    11  	"sync"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/docker/libkv/store"
    16  	"github.com/docker/libkv/store/boltdb"
    17  	"github.com/docker/libnetwork/bitseq"
    18  	"github.com/docker/libnetwork/datastore"
    19  	"github.com/docker/libnetwork/ipamapi"
    20  	_ "github.com/docker/libnetwork/testutils"
    21  	"github.com/docker/libnetwork/types"
    22  	"gotest.tools/v3/assert"
    23  	is "gotest.tools/v3/assert/cmp"
    24  )
    25  
    26  const (
    27  	defaultPrefix = "/tmp/libnetwork/test/ipam"
    28  )
    29  
    30  func init() {
    31  	boltdb.Register()
    32  }
    33  
    34  // OptionBoltdbWithRandomDBFile function returns a random dir for local store backend
    35  func randomLocalStore(needStore bool) (datastore.DataStore, error) {
    36  	if !needStore {
    37  		return nil, nil
    38  	}
    39  	tmp, err := ioutil.TempFile("", "libnetwork-")
    40  	if err != nil {
    41  		return nil, fmt.Errorf("Error creating temp file: %v", err)
    42  	}
    43  	if err := tmp.Close(); err != nil {
    44  		return nil, fmt.Errorf("Error closing temp file: %v", err)
    45  	}
    46  	return datastore.NewDataStore(datastore.LocalScope, &datastore.ScopeCfg{
    47  		Client: datastore.ScopeClientCfg{
    48  			Provider: "boltdb",
    49  			Address:  defaultPrefix + tmp.Name(),
    50  			Config: &store.Config{
    51  				Bucket:            "libnetwork",
    52  				ConnectionTimeout: 3 * time.Second,
    53  			},
    54  		},
    55  	})
    56  }
    57  
    58  func getAllocator(store bool) (*Allocator, error) {
    59  	ds, err := randomLocalStore(store)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	return NewAllocator(ds, nil)
    64  }
    65  
    66  func TestInt2IP2IntConversion(t *testing.T) {
    67  	for i := uint64(0); i < 256*256*256; i++ {
    68  		var array [4]byte // new array at each cycle
    69  		addIntToIP(array[:], i)
    70  		j := ipToUint64(array[:])
    71  		if j != i {
    72  			t.Fatalf("Failed to convert ordinal %d to IP % x and back to ordinal. Got %d", i, array, j)
    73  		}
    74  	}
    75  }
    76  
    77  func TestGetAddressVersion(t *testing.T) {
    78  	if v4 != getAddressVersion(net.ParseIP("172.28.30.112")) {
    79  		t.Fatal("Failed to detect IPv4 version")
    80  	}
    81  	if v4 != getAddressVersion(net.ParseIP("0.0.0.1")) {
    82  		t.Fatal("Failed to detect IPv4 version")
    83  	}
    84  	if v6 != getAddressVersion(net.ParseIP("ff01::1")) {
    85  		t.Fatal("Failed to detect IPv6 version")
    86  	}
    87  	if v6 != getAddressVersion(net.ParseIP("2001:db8::76:51")) {
    88  		t.Fatal("Failed to detect IPv6 version")
    89  	}
    90  }
    91  
    92  func TestKeyString(t *testing.T) {
    93  	k := &SubnetKey{AddressSpace: "default", Subnet: "172.27.0.0/16"}
    94  	expected := "default/172.27.0.0/16"
    95  	if expected != k.String() {
    96  		t.Fatalf("Unexpected key string: %s", k.String())
    97  	}
    98  
    99  	k2 := &SubnetKey{}
   100  	err := k2.FromString(expected)
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	if k2.AddressSpace != k.AddressSpace || k2.Subnet != k.Subnet {
   105  		t.Fatalf("SubnetKey.FromString() failed. Expected %v. Got %v", k, k2)
   106  	}
   107  
   108  	expected = fmt.Sprintf("%s/%s", expected, "172.27.3.0/24")
   109  	k.ChildSubnet = "172.27.3.0/24"
   110  	if expected != k.String() {
   111  		t.Fatalf("Unexpected key string: %s", k.String())
   112  	}
   113  
   114  	err = k2.FromString(expected)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	if k2.AddressSpace != k.AddressSpace || k2.Subnet != k.Subnet || k2.ChildSubnet != k.ChildSubnet {
   119  		t.Fatalf("SubnetKey.FromString() failed. Expected %v. Got %v", k, k2)
   120  	}
   121  }
   122  
   123  func TestPoolDataMarshal(t *testing.T) {
   124  	_, nw, err := net.ParseCIDR("172.28.30.1/24")
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  
   129  	p := &PoolData{
   130  		ParentKey: SubnetKey{AddressSpace: "Blue", Subnet: "172.28.0.0/16"},
   131  		Pool:      nw,
   132  		Range:     &AddressRange{Sub: &net.IPNet{IP: net.IP{172, 28, 20, 0}, Mask: net.IPMask{255, 255, 255, 0}}, Start: 0, End: 255},
   133  		RefCount:  4,
   134  	}
   135  
   136  	ba, err := json.Marshal(p)
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  	var q PoolData
   141  	err = json.Unmarshal(ba, &q)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  
   146  	if p.ParentKey != q.ParentKey || !types.CompareIPNet(p.Range.Sub, q.Range.Sub) ||
   147  		p.Range.Start != q.Range.Start || p.Range.End != q.Range.End || p.RefCount != q.RefCount ||
   148  		!types.CompareIPNet(p.Pool, q.Pool) {
   149  		t.Fatalf("\n%#v\n%#v", p, &q)
   150  	}
   151  
   152  	p = &PoolData{
   153  		ParentKey: SubnetKey{AddressSpace: "Blue", Subnet: "172.28.0.0/16"},
   154  		Pool:      nw,
   155  		RefCount:  4,
   156  	}
   157  
   158  	ba, err = json.Marshal(p)
   159  	if err != nil {
   160  		t.Fatal(err)
   161  	}
   162  	err = json.Unmarshal(ba, &q)
   163  	if err != nil {
   164  		t.Fatal(err)
   165  	}
   166  
   167  	if q.Range != nil {
   168  		t.Fatal("Unexpected Range")
   169  	}
   170  }
   171  
   172  func TestSubnetsMarshal(t *testing.T) {
   173  	for _, store := range []bool{false, true} {
   174  		a, err := getAllocator(store)
   175  		if err != nil {
   176  			t.Fatal(err)
   177  		}
   178  		pid0, _, _, err := a.RequestPool(localAddressSpace, "192.168.0.0/16", "", nil, false)
   179  		if err != nil {
   180  			t.Fatal(err)
   181  		}
   182  		pid1, _, _, err := a.RequestPool(localAddressSpace, "192.169.0.0/16", "", nil, false)
   183  		if err != nil {
   184  			t.Fatal(err)
   185  		}
   186  		_, _, err = a.RequestAddress(pid0, nil, nil)
   187  		if err != nil {
   188  			t.Fatal(err)
   189  		}
   190  
   191  		cfg, err := a.getAddrSpace(localAddressSpace)
   192  		if err != nil {
   193  			t.Fatal(err)
   194  		}
   195  
   196  		ba := cfg.Value()
   197  		if err := cfg.SetValue(ba); err != nil {
   198  			t.Fatal(err)
   199  		}
   200  
   201  		expIP := &net.IPNet{IP: net.IP{192, 168, 0, 2}, Mask: net.IPMask{255, 255, 0, 0}}
   202  		ip, _, err := a.RequestAddress(pid0, nil, nil)
   203  		if err != nil {
   204  			t.Fatal(err)
   205  		}
   206  		if !types.CompareIPNet(expIP, ip) {
   207  			t.Fatalf("Got unexpected ip after pool config restore: %s", ip)
   208  		}
   209  
   210  		expIP = &net.IPNet{IP: net.IP{192, 169, 0, 1}, Mask: net.IPMask{255, 255, 0, 0}}
   211  		ip, _, err = a.RequestAddress(pid1, nil, nil)
   212  		if err != nil {
   213  			t.Fatal(err)
   214  		}
   215  		if !types.CompareIPNet(expIP, ip) {
   216  			t.Fatalf("Got unexpected ip after pool config restore: %s", ip)
   217  		}
   218  	}
   219  }
   220  
   221  func TestAddSubnets(t *testing.T) {
   222  	for _, store := range []bool{false, true} {
   223  		a, err := getAllocator(store)
   224  		if err != nil {
   225  			t.Fatal(err)
   226  		}
   227  		a.addrSpaces["abc"] = a.addrSpaces[localAddressSpace]
   228  
   229  		pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
   230  		if err != nil {
   231  			t.Fatal("Unexpected failure in adding subnet")
   232  		}
   233  
   234  		pid1, _, _, err := a.RequestPool("abc", "10.0.0.0/8", "", nil, false)
   235  		if err != nil {
   236  			t.Fatalf("Unexpected failure in adding overlapping subnets to different address spaces: %v", err)
   237  		}
   238  
   239  		if pid0 == pid1 {
   240  			t.Fatal("returned same pool id for same subnets in different namespaces")
   241  		}
   242  
   243  		_, _, _, err = a.RequestPool("abc", "10.0.0.0/8", "", nil, false)
   244  		if err == nil {
   245  			t.Fatalf("Expected failure requesting existing subnet")
   246  		}
   247  
   248  		_, _, _, err = a.RequestPool("abc", "10.128.0.0/9", "", nil, false)
   249  		if err == nil {
   250  			t.Fatal("Expected failure on adding overlapping base subnet")
   251  		}
   252  
   253  		_, _, _, err = a.RequestPool("abc", "10.0.0.0/8", "10.128.0.0/9", nil, false)
   254  		if err != nil {
   255  			t.Fatalf("Unexpected failure on adding sub pool: %v", err)
   256  		}
   257  		_, _, _, err = a.RequestPool("abc", "10.0.0.0/8", "10.128.0.0/9", nil, false)
   258  		if err == nil {
   259  			t.Fatalf("Expected failure on adding overlapping sub pool")
   260  		}
   261  
   262  		_, _, _, err = a.RequestPool(localAddressSpace, "10.20.2.0/24", "", nil, false)
   263  		if err == nil {
   264  			t.Fatal("Failed to detect overlapping subnets")
   265  		}
   266  
   267  		_, _, _, err = a.RequestPool(localAddressSpace, "10.128.0.0/9", "", nil, false)
   268  		if err == nil {
   269  			t.Fatal("Failed to detect overlapping subnets")
   270  		}
   271  
   272  		_, _, _, err = a.RequestPool(localAddressSpace, "1003:1:2:3:4:5:6::/112", "", nil, false)
   273  		if err != nil {
   274  			t.Fatalf("Failed to add v6 subnet: %s", err.Error())
   275  		}
   276  
   277  		_, _, _, err = a.RequestPool(localAddressSpace, "1003:1:2:3::/64", "", nil, false)
   278  		if err == nil {
   279  			t.Fatal("Failed to detect overlapping v6 subnet")
   280  		}
   281  	}
   282  }
   283  
   284  // TestDoublePoolRelease tests that releasing a pool which has already
   285  // been released raises an error.
   286  func TestDoublePoolRelease(t *testing.T) {
   287  	for _, store := range []bool{false, true} {
   288  		a, err := getAllocator(store)
   289  		assert.NilError(t, err)
   290  
   291  		pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
   292  		assert.NilError(t, err)
   293  
   294  		err = a.ReleasePool(pid0)
   295  		assert.NilError(t, err)
   296  
   297  		err = a.ReleasePool(pid0)
   298  		assert.Check(t, is.ErrorContains(err, ""))
   299  	}
   300  }
   301  
   302  func TestAddReleasePoolID(t *testing.T) {
   303  	for _, store := range []bool{false, true} {
   304  		a, err := getAllocator(store)
   305  		assert.NilError(t, err)
   306  
   307  		var k0, k1 SubnetKey
   308  		aSpace, err := a.getAddrSpace(localAddressSpace)
   309  		if err != nil {
   310  			t.Fatal(err)
   311  		}
   312  
   313  		pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
   314  		if err != nil {
   315  			t.Fatal("Unexpected failure in adding pool")
   316  		}
   317  		if err := k0.FromString(pid0); err != nil {
   318  			t.Fatal(err)
   319  		}
   320  
   321  		aSpace, err = a.getAddrSpace(localAddressSpace)
   322  		if err != nil {
   323  			t.Fatal(err)
   324  		}
   325  
   326  		subnets := aSpace.subnets
   327  
   328  		if subnets[k0].RefCount != 1 {
   329  			t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
   330  		}
   331  
   332  		pid1, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false)
   333  		if err != nil {
   334  			t.Fatal("Unexpected failure in adding sub pool")
   335  		}
   336  		if err := k1.FromString(pid1); err != nil {
   337  			t.Fatal(err)
   338  		}
   339  
   340  		if pid0 == pid1 {
   341  			t.Fatalf("Incorrect poolIDs returned %s, %s", pid0, pid1)
   342  		}
   343  
   344  		aSpace, err = a.getAddrSpace(localAddressSpace)
   345  		if err != nil {
   346  			t.Fatal(err)
   347  		}
   348  
   349  		subnets = aSpace.subnets
   350  		if subnets[k1].RefCount != 1 {
   351  			t.Fatalf("Unexpected ref count for %s: %d", k1, subnets[k1].RefCount)
   352  		}
   353  
   354  		_, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false)
   355  		if err == nil {
   356  			t.Fatal("Expected failure in adding sub pool")
   357  		}
   358  
   359  		aSpace, err = a.getAddrSpace(localAddressSpace)
   360  		if err != nil {
   361  			t.Fatal(err)
   362  		}
   363  
   364  		subnets = aSpace.subnets
   365  
   366  		if subnets[k0].RefCount != 2 {
   367  			t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
   368  		}
   369  
   370  		if err := a.ReleasePool(pid1); err != nil {
   371  			t.Fatal(err)
   372  		}
   373  
   374  		aSpace, err = a.getAddrSpace(localAddressSpace)
   375  		if err != nil {
   376  			t.Fatal(err)
   377  		}
   378  
   379  		subnets = aSpace.subnets
   380  		if subnets[k0].RefCount != 1 {
   381  			t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
   382  		}
   383  		if err := a.ReleasePool(pid0); err != nil {
   384  			t.Fatal(err)
   385  		}
   386  
   387  		pid00, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
   388  		if err != nil {
   389  			t.Fatal("Unexpected failure in adding pool")
   390  		}
   391  		if pid00 != pid0 {
   392  			t.Fatal("main pool should still exist")
   393  		}
   394  
   395  		aSpace, err = a.getAddrSpace(localAddressSpace)
   396  		if err != nil {
   397  			t.Fatal(err)
   398  		}
   399  
   400  		subnets = aSpace.subnets
   401  		if subnets[k0].RefCount != 1 {
   402  			t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
   403  		}
   404  
   405  		if err := a.ReleasePool(pid00); err != nil {
   406  			t.Fatal(err)
   407  		}
   408  
   409  		aSpace, err = a.getAddrSpace(localAddressSpace)
   410  		if err != nil {
   411  			t.Fatal(err)
   412  		}
   413  
   414  		subnets = aSpace.subnets
   415  		if bp, ok := subnets[k0]; ok {
   416  			t.Fatalf("Base pool %s is still present: %v", k0, bp)
   417  		}
   418  
   419  		_, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false)
   420  		if err != nil {
   421  			t.Fatal("Unexpected failure in adding pool")
   422  		}
   423  
   424  		aSpace, err = a.getAddrSpace(localAddressSpace)
   425  		if err != nil {
   426  			t.Fatal(err)
   427  		}
   428  
   429  		subnets = aSpace.subnets
   430  		if subnets[k0].RefCount != 1 {
   431  			t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount)
   432  		}
   433  	}
   434  }
   435  
   436  func TestPredefinedPool(t *testing.T) {
   437  	for _, store := range []bool{false, true} {
   438  		a, err := getAllocator(store)
   439  		assert.NilError(t, err)
   440  
   441  		if _, err := a.getPredefinedPool("blue", false); err == nil {
   442  			t.Fatal("Expected failure for non default addr space")
   443  		}
   444  
   445  		pid, nw, _, err := a.RequestPool(localAddressSpace, "", "", nil, false)
   446  		if err != nil {
   447  			t.Fatal(err)
   448  		}
   449  
   450  		nw2, err := a.getPredefinedPool(localAddressSpace, false)
   451  		if err != nil {
   452  			t.Fatal(err)
   453  		}
   454  		if types.CompareIPNet(nw, nw2) {
   455  			t.Fatalf("Unexpected default network returned: %s = %s", nw2, nw)
   456  		}
   457  
   458  		if err := a.ReleasePool(pid); err != nil {
   459  			t.Fatal(err)
   460  		}
   461  	}
   462  }
   463  
   464  func TestRemoveSubnet(t *testing.T) {
   465  	for _, store := range []bool{false, true} {
   466  		a, err := getAllocator(store)
   467  		assert.NilError(t, err)
   468  
   469  		a.addrSpaces["splane"] = &addrSpace{
   470  			id:      dsConfigKey + "/" + "splane",
   471  			ds:      a.addrSpaces[localAddressSpace].ds,
   472  			alloc:   a.addrSpaces[localAddressSpace].alloc,
   473  			scope:   a.addrSpaces[localAddressSpace].scope,
   474  			subnets: map[SubnetKey]*PoolData{},
   475  		}
   476  
   477  		input := []struct {
   478  			addrSpace string
   479  			subnet    string
   480  			v6        bool
   481  		}{
   482  			{localAddressSpace, "192.168.0.0/16", false},
   483  			{localAddressSpace, "172.17.0.0/16", false},
   484  			{localAddressSpace, "10.0.0.0/8", false},
   485  			{localAddressSpace, "2001:db8:1:2:3:4:ffff::/112", false},
   486  			{"splane", "172.17.0.0/16", false},
   487  			{"splane", "10.0.0.0/8", false},
   488  			{"splane", "2001:db8:1:2:3:4:5::/112", true},
   489  			{"splane", "2001:db8:1:2:3:4:ffff::/112", true},
   490  		}
   491  
   492  		poolIDs := make([]string, len(input))
   493  
   494  		for ind, i := range input {
   495  			if poolIDs[ind], _, _, err = a.RequestPool(i.addrSpace, i.subnet, "", nil, i.v6); err != nil {
   496  				t.Fatalf("Failed to apply input. Can't proceed: %s", err.Error())
   497  			}
   498  		}
   499  
   500  		for ind, id := range poolIDs {
   501  			if err := a.ReleasePool(id); err != nil {
   502  				t.Fatalf("Failed to release poolID %s (%d)", id, ind)
   503  			}
   504  		}
   505  	}
   506  }
   507  
   508  func TestGetSameAddress(t *testing.T) {
   509  	for _, store := range []bool{false, true} {
   510  		a, err := getAllocator(store)
   511  		assert.NilError(t, err)
   512  
   513  		a.addrSpaces["giallo"] = &addrSpace{
   514  			id:      dsConfigKey + "/" + "giallo",
   515  			ds:      a.addrSpaces[localAddressSpace].ds,
   516  			alloc:   a.addrSpaces[localAddressSpace].alloc,
   517  			scope:   a.addrSpaces[localAddressSpace].scope,
   518  			subnets: map[SubnetKey]*PoolData{},
   519  		}
   520  
   521  		pid, _, _, err := a.RequestPool("giallo", "192.168.100.0/24", "", nil, false)
   522  		if err != nil {
   523  			t.Fatal(err)
   524  		}
   525  
   526  		ip := net.ParseIP("192.168.100.250")
   527  		_, _, err = a.RequestAddress(pid, ip, nil)
   528  		if err != nil {
   529  			t.Fatal(err)
   530  		}
   531  
   532  		_, _, err = a.RequestAddress(pid, ip, nil)
   533  		if err == nil {
   534  			t.Fatal(err)
   535  		}
   536  	}
   537  }
   538  
   539  func TestPoolAllocationReuse(t *testing.T) {
   540  	for _, store := range []bool{false, true} {
   541  		a, err := getAllocator(store)
   542  		assert.NilError(t, err)
   543  
   544  		// First get all pools until they are exhausted to
   545  		pList := []string{}
   546  		pool, _, _, err := a.RequestPool(localAddressSpace, "", "", nil, false)
   547  		for err == nil {
   548  			pList = append(pList, pool)
   549  			pool, _, _, err = a.RequestPool(localAddressSpace, "", "", nil, false)
   550  		}
   551  		nPools := len(pList)
   552  		for _, pool := range pList {
   553  			if err := a.ReleasePool(pool); err != nil {
   554  				t.Fatal(err)
   555  			}
   556  		}
   557  
   558  		// Now try to allocate then free nPool pools sequentially.
   559  		// Verify that we don't see any repeat networks even though
   560  		// we have freed them.
   561  		seen := map[string]bool{}
   562  		for i := 0; i < nPools; i++ {
   563  			pool, nw, _, err := a.RequestPool(localAddressSpace, "", "", nil, false)
   564  			if err != nil {
   565  				t.Fatal(err)
   566  			}
   567  			if _, ok := seen[nw.String()]; ok {
   568  				t.Fatalf("Network %s was reused before exhausing the pool list", nw.String())
   569  			}
   570  			seen[nw.String()] = true
   571  			if err := a.ReleasePool(pool); err != nil {
   572  				t.Fatal(err)
   573  			}
   574  		}
   575  	}
   576  }
   577  
   578  func TestGetAddressSubPoolEqualPool(t *testing.T) {
   579  	for _, store := range []bool{false, true} {
   580  		a, err := getAllocator(store)
   581  		assert.NilError(t, err)
   582  
   583  		// Requesting a subpool of same size of the master pool should not cause any problem on ip allocation
   584  		pid, _, _, err := a.RequestPool(localAddressSpace, "172.18.0.0/16", "172.18.0.0/16", nil, false)
   585  		if err != nil {
   586  			t.Fatal(err)
   587  		}
   588  
   589  		_, _, err = a.RequestAddress(pid, nil, nil)
   590  		if err != nil {
   591  			t.Fatal(err)
   592  		}
   593  	}
   594  }
   595  
   596  func TestRequestReleaseAddressFromSubPool(t *testing.T) {
   597  	for _, store := range []bool{false, true} {
   598  		a, err := getAllocator(store)
   599  		assert.NilError(t, err)
   600  
   601  		a.addrSpaces["rosso"] = &addrSpace{
   602  			id:      dsConfigKey + "/" + "rosso",
   603  			ds:      a.addrSpaces[localAddressSpace].ds,
   604  			alloc:   a.addrSpaces[localAddressSpace].alloc,
   605  			scope:   a.addrSpaces[localAddressSpace].scope,
   606  			subnets: map[SubnetKey]*PoolData{},
   607  		}
   608  
   609  		poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false)
   610  		if err != nil {
   611  			t.Fatal(err)
   612  		}
   613  
   614  		var ip *net.IPNet
   615  		expected := &net.IPNet{IP: net.IP{172, 28, 30, 255}, Mask: net.IPMask{255, 255, 0, 0}}
   616  		for err == nil {
   617  			var c *net.IPNet
   618  			if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil {
   619  				ip = c
   620  			}
   621  		}
   622  		if err != ipamapi.ErrNoAvailableIPs {
   623  			t.Fatal(err)
   624  		}
   625  		if !types.CompareIPNet(expected, ip) {
   626  			t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip)
   627  		}
   628  		rp := &net.IPNet{IP: net.IP{172, 28, 30, 97}, Mask: net.IPMask{255, 255, 0, 0}}
   629  		if err = a.ReleaseAddress(poolID, rp.IP); err != nil {
   630  			t.Fatal(err)
   631  		}
   632  		if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil {
   633  			t.Fatal(err)
   634  		}
   635  		if !types.CompareIPNet(rp, ip) {
   636  			t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip)
   637  		}
   638  
   639  		_, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false)
   640  		if err != nil {
   641  			t.Fatal(err)
   642  		}
   643  		poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false)
   644  		if err != nil {
   645  			t.Fatal(err)
   646  		}
   647  		expected = &net.IPNet{IP: net.IP{10, 0, 0, 255}, Mask: net.IPMask{255, 255, 0, 0}}
   648  		for err == nil {
   649  			var c *net.IPNet
   650  			if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil {
   651  				ip = c
   652  			}
   653  		}
   654  		if err != ipamapi.ErrNoAvailableIPs {
   655  			t.Fatal(err)
   656  		}
   657  		if !types.CompareIPNet(expected, ip) {
   658  			t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip)
   659  		}
   660  		rp = &net.IPNet{IP: net.IP{10, 0, 0, 79}, Mask: net.IPMask{255, 255, 0, 0}}
   661  		if err = a.ReleaseAddress(poolID, rp.IP); err != nil {
   662  			t.Fatal(err)
   663  		}
   664  		if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil {
   665  			t.Fatal(err)
   666  		}
   667  		if !types.CompareIPNet(rp, ip) {
   668  			t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip)
   669  		}
   670  
   671  		// Request any addresses from subpool after explicit address request
   672  		unoExp, _ := types.ParseCIDR("10.2.2.0/16")
   673  		dueExp, _ := types.ParseCIDR("10.2.2.2/16")
   674  		treExp, _ := types.ParseCIDR("10.2.2.1/16")
   675  
   676  		if poolID, _, _, err = a.RequestPool("rosso", "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil {
   677  			t.Fatal(err)
   678  		}
   679  		tre, _, err := a.RequestAddress(poolID, treExp.IP, nil)
   680  		if err != nil {
   681  			t.Fatal(err)
   682  		}
   683  		if !types.CompareIPNet(tre, treExp) {
   684  			t.Fatalf("Unexpected address: %v", tre)
   685  		}
   686  
   687  		uno, _, err := a.RequestAddress(poolID, nil, nil)
   688  		if err != nil {
   689  			t.Fatal(err)
   690  		}
   691  		if !types.CompareIPNet(uno, unoExp) {
   692  			t.Fatalf("Unexpected address: %v", uno)
   693  		}
   694  
   695  		due, _, err := a.RequestAddress(poolID, nil, nil)
   696  		if err != nil {
   697  			t.Fatal(err)
   698  		}
   699  		if !types.CompareIPNet(due, dueExp) {
   700  			t.Fatalf("Unexpected address: %v", due)
   701  		}
   702  
   703  		if err = a.ReleaseAddress(poolID, uno.IP); err != nil {
   704  			t.Fatal(err)
   705  		}
   706  		uno, _, err = a.RequestAddress(poolID, nil, nil)
   707  		if err != nil {
   708  			t.Fatal(err)
   709  		}
   710  		if !types.CompareIPNet(uno, unoExp) {
   711  			t.Fatalf("Unexpected address: %v", uno)
   712  		}
   713  
   714  		if err = a.ReleaseAddress(poolID, tre.IP); err != nil {
   715  			t.Fatal(err)
   716  		}
   717  		tre, _, err = a.RequestAddress(poolID, nil, nil)
   718  		if err != nil {
   719  			t.Fatal(err)
   720  		}
   721  		if !types.CompareIPNet(tre, treExp) {
   722  			t.Fatalf("Unexpected address: %v", tre)
   723  		}
   724  	}
   725  }
   726  
   727  func TestSerializeRequestReleaseAddressFromSubPool(t *testing.T) {
   728  	opts := map[string]string{
   729  		ipamapi.AllocSerialPrefix: "true"}
   730  	for _, store := range []bool{false, true} {
   731  		a, err := getAllocator(store)
   732  		assert.NilError(t, err)
   733  
   734  		a.addrSpaces["rosso"] = &addrSpace{
   735  			id:      dsConfigKey + "/" + "rosso",
   736  			ds:      a.addrSpaces[localAddressSpace].ds,
   737  			alloc:   a.addrSpaces[localAddressSpace].alloc,
   738  			scope:   a.addrSpaces[localAddressSpace].scope,
   739  			subnets: map[SubnetKey]*PoolData{},
   740  		}
   741  
   742  		poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false)
   743  		if err != nil {
   744  			t.Fatal(err)
   745  		}
   746  
   747  		var ip *net.IPNet
   748  		expected := &net.IPNet{IP: net.IP{172, 28, 30, 255}, Mask: net.IPMask{255, 255, 0, 0}}
   749  		for err == nil {
   750  			var c *net.IPNet
   751  			if c, _, err = a.RequestAddress(poolID, nil, opts); err == nil {
   752  				ip = c
   753  			}
   754  		}
   755  		if err != ipamapi.ErrNoAvailableIPs {
   756  			t.Fatal(err)
   757  		}
   758  		if !types.CompareIPNet(expected, ip) {
   759  			t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip)
   760  		}
   761  		rp := &net.IPNet{IP: net.IP{172, 28, 30, 97}, Mask: net.IPMask{255, 255, 0, 0}}
   762  		if err = a.ReleaseAddress(poolID, rp.IP); err != nil {
   763  			t.Fatal(err)
   764  		}
   765  		if ip, _, err = a.RequestAddress(poolID, nil, opts); err != nil {
   766  			t.Fatal(err)
   767  		}
   768  		if !types.CompareIPNet(rp, ip) {
   769  			t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip)
   770  		}
   771  
   772  		_, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false)
   773  		if err != nil {
   774  			t.Fatal(err)
   775  		}
   776  		poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false)
   777  		if err != nil {
   778  			t.Fatal(err)
   779  		}
   780  		expected = &net.IPNet{IP: net.IP{10, 0, 0, 255}, Mask: net.IPMask{255, 255, 0, 0}}
   781  		for err == nil {
   782  			var c *net.IPNet
   783  			if c, _, err = a.RequestAddress(poolID, nil, opts); err == nil {
   784  				ip = c
   785  			}
   786  		}
   787  		if err != ipamapi.ErrNoAvailableIPs {
   788  			t.Fatal(err)
   789  		}
   790  		if !types.CompareIPNet(expected, ip) {
   791  			t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip)
   792  		}
   793  		rp = &net.IPNet{IP: net.IP{10, 0, 0, 79}, Mask: net.IPMask{255, 255, 0, 0}}
   794  		if err = a.ReleaseAddress(poolID, rp.IP); err != nil {
   795  			t.Fatal(err)
   796  		}
   797  		if ip, _, err = a.RequestAddress(poolID, nil, opts); err != nil {
   798  			t.Fatal(err)
   799  		}
   800  		if !types.CompareIPNet(rp, ip) {
   801  			t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip)
   802  		}
   803  
   804  		// Request any addresses from subpool after explicit address request
   805  		unoExp, _ := types.ParseCIDR("10.2.2.0/16")
   806  		dueExp, _ := types.ParseCIDR("10.2.2.2/16")
   807  		treExp, _ := types.ParseCIDR("10.2.2.1/16")
   808  		quaExp, _ := types.ParseCIDR("10.2.2.3/16")
   809  		fivExp, _ := types.ParseCIDR("10.2.2.4/16")
   810  		if poolID, _, _, err = a.RequestPool("rosso", "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil {
   811  			t.Fatal(err)
   812  		}
   813  		tre, _, err := a.RequestAddress(poolID, treExp.IP, opts)
   814  		if err != nil {
   815  			t.Fatal(err)
   816  		}
   817  		if !types.CompareIPNet(tre, treExp) {
   818  			t.Fatalf("Unexpected address: %v", tre)
   819  		}
   820  
   821  		uno, _, err := a.RequestAddress(poolID, nil, opts)
   822  		if err != nil {
   823  			t.Fatal(err)
   824  		}
   825  		if !types.CompareIPNet(uno, unoExp) {
   826  			t.Fatalf("Unexpected address: %v", uno)
   827  		}
   828  
   829  		due, _, err := a.RequestAddress(poolID, nil, opts)
   830  		if err != nil {
   831  			t.Fatal(err)
   832  		}
   833  		if !types.CompareIPNet(due, dueExp) {
   834  			t.Fatalf("Unexpected address: %v", due)
   835  		}
   836  
   837  		if err = a.ReleaseAddress(poolID, uno.IP); err != nil {
   838  			t.Fatal(err)
   839  		}
   840  		uno, _, err = a.RequestAddress(poolID, nil, opts)
   841  		if err != nil {
   842  			t.Fatal(err)
   843  		}
   844  		if !types.CompareIPNet(uno, quaExp) {
   845  			t.Fatalf("Unexpected address: %v", uno)
   846  		}
   847  
   848  		if err = a.ReleaseAddress(poolID, tre.IP); err != nil {
   849  			t.Fatal(err)
   850  		}
   851  		tre, _, err = a.RequestAddress(poolID, nil, opts)
   852  		if err != nil {
   853  			t.Fatal(err)
   854  		}
   855  		if !types.CompareIPNet(tre, fivExp) {
   856  			t.Fatalf("Unexpected address: %v", tre)
   857  		}
   858  	}
   859  }
   860  
   861  func TestGetAddress(t *testing.T) {
   862  	input := []string{
   863  		/*"10.0.0.0/8", "10.0.0.0/9", "10.0.0.0/10",*/ "10.0.0.0/11", "10.0.0.0/12", "10.0.0.0/13", "10.0.0.0/14",
   864  		"10.0.0.0/15", "10.0.0.0/16", "10.0.0.0/17", "10.0.0.0/18", "10.0.0.0/19", "10.0.0.0/20", "10.0.0.0/21",
   865  		"10.0.0.0/22", "10.0.0.0/23", "10.0.0.0/24", "10.0.0.0/25", "10.0.0.0/26", "10.0.0.0/27", "10.0.0.0/28",
   866  		"10.0.0.0/29", "10.0.0.0/30", "10.0.0.0/31"}
   867  
   868  	for _, subnet := range input {
   869  		assertGetAddress(t, subnet)
   870  	}
   871  }
   872  
   873  func TestRequestSyntaxCheck(t *testing.T) {
   874  	var (
   875  		pool    = "192.168.0.0/16"
   876  		subPool = "192.168.0.0/24"
   877  		as      = "green"
   878  	)
   879  
   880  	for _, store := range []bool{false, true} {
   881  		a, err := getAllocator(store)
   882  		assert.NilError(t, err)
   883  
   884  		a.addrSpaces[as] = &addrSpace{
   885  			id:      dsConfigKey + "/" + as,
   886  			ds:      a.addrSpaces[localAddressSpace].ds,
   887  			alloc:   a.addrSpaces[localAddressSpace].alloc,
   888  			scope:   a.addrSpaces[localAddressSpace].scope,
   889  			subnets: map[SubnetKey]*PoolData{},
   890  		}
   891  
   892  		_, _, _, err = a.RequestPool("", pool, "", nil, false)
   893  		if err == nil {
   894  			t.Fatal("Failed to detect wrong request: empty address space")
   895  		}
   896  
   897  		_, _, _, err = a.RequestPool("", pool, subPool, nil, false)
   898  		if err == nil {
   899  			t.Fatal("Failed to detect wrong request: empty address space")
   900  		}
   901  
   902  		_, _, _, err = a.RequestPool(as, "", subPool, nil, false)
   903  		if err == nil {
   904  			t.Fatal("Failed to detect wrong request: subPool specified and no pool")
   905  		}
   906  
   907  		pid, _, _, err := a.RequestPool(as, pool, subPool, nil, false)
   908  		if err != nil {
   909  			t.Fatalf("Unexpected failure: %v", err)
   910  		}
   911  
   912  		_, _, err = a.RequestAddress("", nil, nil)
   913  		if err == nil {
   914  			t.Fatal("Failed to detect wrong request: no pool id specified")
   915  		}
   916  
   917  		ip := net.ParseIP("172.17.0.23")
   918  		_, _, err = a.RequestAddress(pid, ip, nil)
   919  		if err == nil {
   920  			t.Fatal("Failed to detect wrong request: requested IP from different subnet")
   921  		}
   922  
   923  		ip = net.ParseIP("192.168.0.50")
   924  		_, _, err = a.RequestAddress(pid, ip, nil)
   925  		if err != nil {
   926  			t.Fatalf("Unexpected failure: %v", err)
   927  		}
   928  
   929  		err = a.ReleaseAddress("", ip)
   930  		if err == nil {
   931  			t.Fatal("Failed to detect wrong request: no pool id specified")
   932  		}
   933  
   934  		err = a.ReleaseAddress(pid, nil)
   935  		if err == nil {
   936  			t.Fatal("Failed to detect wrong request: no pool id specified")
   937  		}
   938  
   939  		err = a.ReleaseAddress(pid, ip)
   940  		if err != nil {
   941  			t.Fatalf("Unexpected failure: %v: %s, %s", err, pid, ip)
   942  		}
   943  	}
   944  }
   945  
   946  func TestRequest(t *testing.T) {
   947  	// Request N addresses from different size subnets, verifying last request
   948  	// returns expected address. Internal subnet host size is Allocator's default, 16
   949  	input := []struct {
   950  		subnet string
   951  		numReq int
   952  		lastIP string
   953  	}{
   954  		{"192.168.59.0/24", 254, "192.168.59.254"},
   955  		{"192.168.240.0/20", 255, "192.168.240.255"},
   956  		{"192.168.0.0/16", 255, "192.168.0.255"},
   957  		{"192.168.0.0/16", 256, "192.168.1.0"},
   958  		{"10.16.0.0/16", 255, "10.16.0.255"},
   959  		{"10.128.0.0/12", 255, "10.128.0.255"},
   960  		{"10.0.0.0/8", 256, "10.0.1.0"},
   961  
   962  		{"192.168.128.0/18", 4*256 - 1, "192.168.131.255"},
   963  		/*
   964  			{"192.168.240.0/20", 16*256 - 2, "192.168.255.254"},
   965  
   966  			{"192.168.0.0/16", 256*256 - 2, "192.168.255.254"},
   967  			{"10.0.0.0/8", 2 * 256, "10.0.2.0"},
   968  			{"10.0.0.0/8", 5 * 256, "10.0.5.0"},
   969  			{"10.0.0.0/8", 100 * 256 * 254, "10.99.255.254"},
   970  		*/
   971  	}
   972  
   973  	for _, d := range input {
   974  		assertNRequests(t, d.subnet, d.numReq, d.lastIP)
   975  	}
   976  }
   977  
   978  // TestOverlappingRequests tests that overlapping subnets cannot be allocated.
   979  // Requests for subnets which are supersets or subsets of existing allocations,
   980  // or which overlap at the beginning or end, should not be permitted.
   981  func TestOverlappingRequests(t *testing.T) {
   982  	input := []struct {
   983  		environment []string
   984  		subnet      string
   985  		ok          bool
   986  	}{
   987  		// IPv4
   988  		// Previously allocated network does not overlap with request
   989  		{[]string{"10.0.0.0/8"}, "11.0.0.0/8", true},
   990  		{[]string{"74.0.0.0/7"}, "9.111.99.72/30", true},
   991  		{[]string{"110.192.0.0/10"}, "16.0.0.0/10", true},
   992  
   993  		// Previously allocated network entirely contains request
   994  		{[]string{"10.0.0.0/8"}, "10.0.0.0/8", false}, // exact overlap
   995  		{[]string{"0.0.0.0/1"}, "16.182.0.0/15", false},
   996  		{[]string{"16.0.0.0/4"}, "17.11.66.0/23", false},
   997  
   998  		// Previously allocated network overlaps beginning of request
   999  		{[]string{"0.0.0.0/1"}, "0.0.0.0/0", false},
  1000  		{[]string{"64.0.0.0/6"}, "64.0.0.0/3", false},
  1001  		{[]string{"112.0.0.0/6"}, "112.0.0.0/4", false},
  1002  
  1003  		// Previously allocated network overlaps end of request
  1004  		{[]string{"96.0.0.0/3"}, "0.0.0.0/1", false},
  1005  		{[]string{"192.0.0.0/2"}, "128.0.0.0/1", false},
  1006  		{[]string{"95.0.0.0/8"}, "92.0.0.0/6", false},
  1007  
  1008  		// Previously allocated network entirely contained within request
  1009  		{[]string{"10.0.0.0/8"}, "10.0.0.0/6", false}, // non-canonical
  1010  		{[]string{"10.0.0.0/8"}, "8.0.0.0/6", false},  // canonical
  1011  		{[]string{"25.173.144.0/20"}, "0.0.0.0/0", false},
  1012  
  1013  		// IPv6
  1014  		// Previously allocated network entirely contains request
  1015  		{[]string{"::/0"}, "f656:3484:c878:a05:e540:a6ed:4d70:3740/123", false},
  1016  		{[]string{"8000::/1"}, "8fe8:e7c4:5779::/49", false},
  1017  		{[]string{"f000::/4"}, "ffc7:6000::/19", false},
  1018  
  1019  		// Previously allocated network overlaps beginning of request
  1020  		{[]string{"::/2"}, "::/0", false},
  1021  		{[]string{"::/3"}, "::/1", false},
  1022  		{[]string{"::/6"}, "::/5", false},
  1023  
  1024  		// Previously allocated network overlaps end of request
  1025  		{[]string{"c000::/2"}, "8000::/1", false},
  1026  		{[]string{"7c00::/6"}, "::/1", false},
  1027  		{[]string{"cf80::/9"}, "c000::/4", false},
  1028  
  1029  		// Previously allocated network entirely contained within request
  1030  		{[]string{"ff77:93f8::/29"}, "::/0", false},
  1031  		{[]string{"9287:2e20:5134:fab6:9061:a0c6:bfe3:9400/119"}, "8000::/1", false},
  1032  		{[]string{"3ea1:bfa9:8691:d1c6:8c46:519b:db6d:e700/120"}, "3000::/4", false},
  1033  	}
  1034  
  1035  	for _, store := range []bool{false, true} {
  1036  		for _, tc := range input {
  1037  			a, err := getAllocator(store)
  1038  			assert.NilError(t, err)
  1039  
  1040  			// Set up some existing allocations.  This should always succeed.
  1041  			for _, env := range tc.environment {
  1042  				_, _, _, err = a.RequestPool(localAddressSpace, env, "", nil, false)
  1043  				assert.NilError(t, err)
  1044  			}
  1045  
  1046  			// Make the test allocation.
  1047  			_, _, _, err = a.RequestPool(localAddressSpace, tc.subnet, "", nil, false)
  1048  			if tc.ok {
  1049  				assert.NilError(t, err)
  1050  			} else {
  1051  				assert.Check(t, is.ErrorContains(err, ""))
  1052  			}
  1053  		}
  1054  	}
  1055  }
  1056  
  1057  func TestRelease(t *testing.T) {
  1058  	var (
  1059  		subnet = "192.168.0.0/23"
  1060  	)
  1061  
  1062  	for _, store := range []bool{false, true} {
  1063  		a, err := getAllocator(store)
  1064  		assert.NilError(t, err)
  1065  
  1066  		pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false)
  1067  		if err != nil {
  1068  			t.Fatal(err)
  1069  		}
  1070  
  1071  		bm := a.addresses[SubnetKey{localAddressSpace, subnet, ""}]
  1072  
  1073  		// Allocate all addresses
  1074  		for err != ipamapi.ErrNoAvailableIPs {
  1075  			_, _, err = a.RequestAddress(pid, nil, nil)
  1076  		}
  1077  
  1078  		toRelease := []struct {
  1079  			address string
  1080  		}{
  1081  			{"192.168.0.1"},
  1082  			{"192.168.0.2"},
  1083  			{"192.168.0.3"},
  1084  			{"192.168.0.4"},
  1085  			{"192.168.0.5"},
  1086  			{"192.168.0.6"},
  1087  			{"192.168.0.7"},
  1088  			{"192.168.0.8"},
  1089  			{"192.168.0.9"},
  1090  			{"192.168.0.10"},
  1091  			{"192.168.0.30"},
  1092  			{"192.168.0.31"},
  1093  			{"192.168.1.32"},
  1094  
  1095  			{"192.168.0.254"},
  1096  			{"192.168.1.1"},
  1097  			{"192.168.1.2"},
  1098  
  1099  			{"192.168.1.3"},
  1100  
  1101  			{"192.168.1.253"},
  1102  			{"192.168.1.254"},
  1103  		}
  1104  
  1105  		// One by one, release the address and request again. We should get the same IP
  1106  		for i, inp := range toRelease {
  1107  			ip0 := net.ParseIP(inp.address)
  1108  			a.ReleaseAddress(pid, ip0)
  1109  			bm = a.addresses[SubnetKey{localAddressSpace, subnet, ""}]
  1110  			if bm.Unselected() != 1 {
  1111  				t.Fatalf("Failed to update free address count after release. Expected %d, Found: %d", i+1, bm.Unselected())
  1112  			}
  1113  
  1114  			nw, _, err := a.RequestAddress(pid, nil, nil)
  1115  			if err != nil {
  1116  				t.Fatalf("Failed to obtain the address: %s", err.Error())
  1117  			}
  1118  			ip := nw.IP
  1119  			if !ip0.Equal(ip) {
  1120  				t.Fatalf("Failed to obtain the same address. Expected: %s, Got: %s", ip0, ip)
  1121  			}
  1122  		}
  1123  	}
  1124  }
  1125  
  1126  func assertGetAddress(t *testing.T, subnet string) {
  1127  	var (
  1128  		err       error
  1129  		printTime = false
  1130  		a         = &Allocator{}
  1131  	)
  1132  
  1133  	_, sub, _ := net.ParseCIDR(subnet)
  1134  	ones, bits := sub.Mask.Size()
  1135  	zeroes := bits - ones
  1136  	numAddresses := 1 << uint(zeroes)
  1137  
  1138  	bm, err := bitseq.NewHandle("ipam_test", nil, "default/"+subnet, uint64(numAddresses))
  1139  	if err != nil {
  1140  		t.Fatal(err)
  1141  	}
  1142  
  1143  	start := time.Now()
  1144  	run := 0
  1145  	for err != ipamapi.ErrNoAvailableIPs {
  1146  		_, err = a.getAddress(sub, bm, nil, nil, false)
  1147  		run++
  1148  	}
  1149  	if printTime {
  1150  		fmt.Printf("\nTaken %v, to allocate all addresses on %s. (nemAddresses: %d. Runs: %d)", time.Since(start), subnet, numAddresses, run)
  1151  	}
  1152  	if bm.Unselected() != 0 {
  1153  		t.Fatalf("Unexpected free count after reserving all addresses: %d", bm.Unselected())
  1154  	}
  1155  	/*
  1156  		if bm.Head.Block != expectedMax || bm.Head.Count != numBlocks {
  1157  			t.Fatalf("Failed to effectively reserve all addresses on %s. Expected (0x%x, %d) as first sequence. Found (0x%x,%d)",
  1158  				subnet, expectedMax, numBlocks, bm.Head.Block, bm.Head.Count)
  1159  		}
  1160  	*/
  1161  }
  1162  
  1163  func assertNRequests(t *testing.T, subnet string, numReq int, lastExpectedIP string) {
  1164  	var (
  1165  		nw        *net.IPNet
  1166  		printTime = false
  1167  	)
  1168  
  1169  	lastIP := net.ParseIP(lastExpectedIP)
  1170  	for _, store := range []bool{false, true} {
  1171  		a, err := getAllocator(store)
  1172  		assert.NilError(t, err)
  1173  
  1174  		pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false)
  1175  		if err != nil {
  1176  			t.Fatal(err)
  1177  		}
  1178  
  1179  		i := 0
  1180  		start := time.Now()
  1181  		for ; i < numReq; i++ {
  1182  			nw, _, err = a.RequestAddress(pid, nil, nil)
  1183  		}
  1184  		if printTime {
  1185  			fmt.Printf("\nTaken %v, to allocate %d addresses on %s\n", time.Since(start), numReq, subnet)
  1186  		}
  1187  
  1188  		if !lastIP.Equal(nw.IP) {
  1189  			t.Fatalf("Wrong last IP. Expected %s. Got: %s (err: %v, ind: %d)", lastExpectedIP, nw.IP.String(), err, i)
  1190  		}
  1191  	}
  1192  }
  1193  
  1194  func benchmarkRequest(b *testing.B, a *Allocator, subnet string) {
  1195  	pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false)
  1196  	for err != ipamapi.ErrNoAvailableIPs {
  1197  		_, _, err = a.RequestAddress(pid, nil, nil)
  1198  	}
  1199  }
  1200  
  1201  func benchMarkRequest(subnet string, b *testing.B) {
  1202  	a, _ := getAllocator(true)
  1203  	for n := 0; n < b.N; n++ {
  1204  		benchmarkRequest(b, a, subnet)
  1205  	}
  1206  }
  1207  
  1208  func BenchmarkRequest(b *testing.B) {
  1209  
  1210  	subnets := []string{
  1211  		"10.0.0.0/24",
  1212  		"10.0.0.0/16",
  1213  		"10.0.0.0/8",
  1214  	}
  1215  
  1216  	for _, subnet := range subnets {
  1217  		name := fmt.Sprintf("%vSubnet", subnet)
  1218  		b.Run(name, func(b *testing.B) {
  1219  			a, _ := getAllocator(true)
  1220  			benchmarkRequest(b, a, subnet)
  1221  		})
  1222  	}
  1223  }
  1224  
  1225  func TestAllocateRandomDeallocate(t *testing.T) {
  1226  	for _, store := range []bool{false, true} {
  1227  		testAllocateRandomDeallocate(t, "172.25.0.0/16", "", 384, store)
  1228  		testAllocateRandomDeallocate(t, "172.25.0.0/16", "172.25.252.0/22", 384, store)
  1229  	}
  1230  }
  1231  
  1232  func testAllocateRandomDeallocate(t *testing.T, pool, subPool string, num int, store bool) {
  1233  	ds, err := randomLocalStore(store)
  1234  	assert.NilError(t, err)
  1235  
  1236  	a, err := NewAllocator(ds, nil)
  1237  	if err != nil {
  1238  		t.Fatal(err)
  1239  	}
  1240  
  1241  	pid, _, _, err := a.RequestPool(localAddressSpace, pool, subPool, nil, false)
  1242  	if err != nil {
  1243  		t.Fatal(err)
  1244  	}
  1245  
  1246  	// Allocate num ip addresses
  1247  	indices := make(map[int]*net.IPNet, num)
  1248  	allocated := make(map[string]bool, num)
  1249  	for i := 0; i < num; i++ {
  1250  		ip, _, err := a.RequestAddress(pid, nil, nil)
  1251  		if err != nil {
  1252  			t.Fatal(err)
  1253  		}
  1254  		ips := ip.String()
  1255  		if _, ok := allocated[ips]; ok {
  1256  			t.Fatalf("Address %s is already allocated", ips)
  1257  		}
  1258  		allocated[ips] = true
  1259  		indices[i] = ip
  1260  	}
  1261  	if len(indices) != len(allocated) || len(indices) != num {
  1262  		t.Fatalf("Unexpected number of allocated addresses: (%d,%d).", len(indices), len(allocated))
  1263  	}
  1264  
  1265  	seed := time.Now().Unix()
  1266  	rand.Seed(seed)
  1267  
  1268  	// Deallocate half of the allocated addresses following a random pattern
  1269  	pattern := rand.Perm(num)
  1270  	for i := 0; i < num/2; i++ {
  1271  		idx := pattern[i]
  1272  		ip := indices[idx]
  1273  		err := a.ReleaseAddress(pid, ip.IP)
  1274  		if err != nil {
  1275  			t.Fatalf("Unexpected failure on deallocation of %s: %v.\nSeed: %d.", ip, err, seed)
  1276  		}
  1277  		delete(indices, idx)
  1278  		delete(allocated, ip.String())
  1279  	}
  1280  
  1281  	// Request a quarter of addresses
  1282  	for i := 0; i < num/2; i++ {
  1283  		ip, _, err := a.RequestAddress(pid, nil, nil)
  1284  		if err != nil {
  1285  			t.Fatal(err)
  1286  		}
  1287  		ips := ip.String()
  1288  		if _, ok := allocated[ips]; ok {
  1289  			t.Fatalf("\nAddress %s is already allocated.\nSeed: %d.", ips, seed)
  1290  		}
  1291  		allocated[ips] = true
  1292  	}
  1293  	if len(allocated) != num {
  1294  		t.Fatalf("Unexpected number of allocated addresses: %d.\nSeed: %d.", len(allocated), seed)
  1295  	}
  1296  }
  1297  
  1298  func TestRetrieveFromStore(t *testing.T) {
  1299  	num := 200
  1300  	ds, err := randomLocalStore(true)
  1301  	if err != nil {
  1302  		t.Fatal(err)
  1303  	}
  1304  	a, err := NewAllocator(ds, nil)
  1305  	if err != nil {
  1306  		t.Fatal(err)
  1307  	}
  1308  	pid, _, _, err := a.RequestPool(localAddressSpace, "172.25.0.0/16", "", nil, false)
  1309  	if err != nil {
  1310  		t.Fatal(err)
  1311  	}
  1312  	for i := 0; i < num; i++ {
  1313  		if _, _, err := a.RequestAddress(pid, nil, nil); err != nil {
  1314  			t.Fatal(err)
  1315  		}
  1316  	}
  1317  
  1318  	// Restore
  1319  	a1, err := NewAllocator(ds, nil)
  1320  	if err != nil {
  1321  		t.Fatal(err)
  1322  	}
  1323  	a1.refresh(localAddressSpace)
  1324  	db := a.DumpDatabase()
  1325  	db1 := a1.DumpDatabase()
  1326  	if db != db1 {
  1327  		t.Fatalf("Unexpected db change.\nExpected:%s\nGot:%s", db, db1)
  1328  	}
  1329  	checkDBEquality(a, a1, t)
  1330  	pid, _, _, err = a1.RequestPool(localAddressSpace, "172.25.0.0/16", "172.25.1.0/24", nil, false)
  1331  	if err != nil {
  1332  		t.Fatal(err)
  1333  	}
  1334  	for i := 0; i < num/2; i++ {
  1335  		if _, _, err := a1.RequestAddress(pid, nil, nil); err != nil {
  1336  			t.Fatal(err)
  1337  		}
  1338  	}
  1339  
  1340  	// Restore
  1341  	a2, err := NewAllocator(ds, nil)
  1342  	if err != nil {
  1343  		t.Fatal(err)
  1344  	}
  1345  	a2.refresh(localAddressSpace)
  1346  	checkDBEquality(a1, a2, t)
  1347  	pid, _, _, err = a2.RequestPool(localAddressSpace, "172.25.0.0/16", "172.25.2.0/24", nil, false)
  1348  	if err != nil {
  1349  		t.Fatal(err)
  1350  	}
  1351  	for i := 0; i < num/2; i++ {
  1352  		if _, _, err := a2.RequestAddress(pid, nil, nil); err != nil {
  1353  			t.Fatal(err)
  1354  		}
  1355  	}
  1356  
  1357  	// Restore
  1358  	a3, err := NewAllocator(ds, nil)
  1359  	if err != nil {
  1360  		t.Fatal(err)
  1361  	}
  1362  	a3.refresh(localAddressSpace)
  1363  	checkDBEquality(a2, a3, t)
  1364  	pid, _, _, err = a3.RequestPool(localAddressSpace, "172.26.0.0/16", "", nil, false)
  1365  	if err != nil {
  1366  		t.Fatal(err)
  1367  	}
  1368  	for i := 0; i < num/2; i++ {
  1369  		if _, _, err := a3.RequestAddress(pid, nil, nil); err != nil {
  1370  			t.Fatal(err)
  1371  		}
  1372  	}
  1373  
  1374  	// Restore
  1375  	a4, err := NewAllocator(ds, nil)
  1376  	if err != nil {
  1377  		t.Fatal(err)
  1378  	}
  1379  	a4.refresh(localAddressSpace)
  1380  	checkDBEquality(a3, a4, t)
  1381  }
  1382  
  1383  func checkDBEquality(a1, a2 *Allocator, t *testing.T) {
  1384  	for k, cnf1 := range a1.addrSpaces[localAddressSpace].subnets {
  1385  		cnf2 := a2.addrSpaces[localAddressSpace].subnets[k]
  1386  		if cnf1.String() != cnf2.String() {
  1387  			t.Fatalf("%s\n%s", cnf1, cnf2)
  1388  		}
  1389  		if cnf1.Range == nil {
  1390  			a2.retrieveBitmask(k, cnf1.Pool)
  1391  		}
  1392  	}
  1393  
  1394  	for k, bm1 := range a1.addresses {
  1395  		bm2 := a2.addresses[k]
  1396  		if bm1.String() != bm2.String() {
  1397  			t.Fatalf("%s\n%s", bm1, bm2)
  1398  		}
  1399  	}
  1400  }
  1401  
  1402  const (
  1403  	numInstances = 5
  1404  	first        = 0
  1405  	last         = numInstances - 1
  1406  )
  1407  
  1408  var (
  1409  	allocator *Allocator
  1410  	start     = make(chan struct{})
  1411  	done      = make(chan chan struct{}, numInstances-1)
  1412  	pools     = make([]*net.IPNet, numInstances)
  1413  )
  1414  
  1415  func runParallelTests(t *testing.T, instance int) {
  1416  	var err error
  1417  
  1418  	t.Parallel()
  1419  
  1420  	pTest := flag.Lookup("test.parallel")
  1421  	if pTest == nil {
  1422  		t.Skip("Skipped because test.parallel flag not set;")
  1423  	}
  1424  	numParallel, err := strconv.Atoi(pTest.Value.String())
  1425  	if err != nil {
  1426  		t.Fatal(err)
  1427  	}
  1428  	if numParallel < numInstances {
  1429  		t.Skip("Skipped because t.parallel was less than ", numInstances)
  1430  	}
  1431  
  1432  	// The first instance creates the allocator, gives the start
  1433  	// and finally checks the pools each instance was assigned
  1434  	if instance == first {
  1435  		allocator, err = getAllocator(true)
  1436  		if err != nil {
  1437  			t.Fatal(err)
  1438  		}
  1439  		close(start)
  1440  	}
  1441  
  1442  	if instance != first {
  1443  		select {
  1444  		case <-start:
  1445  		}
  1446  
  1447  		instDone := make(chan struct{})
  1448  		done <- instDone
  1449  		defer close(instDone)
  1450  
  1451  		if instance == last {
  1452  			defer close(done)
  1453  		}
  1454  	}
  1455  
  1456  	_, pools[instance], _, err = allocator.RequestPool(localAddressSpace, "", "", nil, false)
  1457  	if err != nil {
  1458  		t.Fatal(err)
  1459  	}
  1460  
  1461  	if instance == first {
  1462  		for instDone := range done {
  1463  			select {
  1464  			case <-instDone:
  1465  			}
  1466  		}
  1467  		// Now check each instance got a different pool
  1468  		for i := 0; i < numInstances; i++ {
  1469  			for j := i + 1; j < numInstances; j++ {
  1470  				if types.CompareIPNet(pools[i], pools[j]) {
  1471  					t.Fatalf("Instance %d and %d were given the same predefined pool: %v", i, j, pools)
  1472  				}
  1473  			}
  1474  		}
  1475  	}
  1476  }
  1477  
  1478  func TestRequestReleaseAddressDuplicate(t *testing.T) {
  1479  	a, err := getAllocator(false)
  1480  	if err != nil {
  1481  		t.Fatal(err)
  1482  	}
  1483  	type IP struct {
  1484  		ip  *net.IPNet
  1485  		ref int
  1486  	}
  1487  	ips := []IP{}
  1488  	allocatedIPs := []*net.IPNet{}
  1489  	a.addrSpaces["rosso"] = &addrSpace{
  1490  		id:      dsConfigKey + "/" + "rosso",
  1491  		ds:      a.addrSpaces[localAddressSpace].ds,
  1492  		alloc:   a.addrSpaces[localAddressSpace].alloc,
  1493  		scope:   a.addrSpaces[localAddressSpace].scope,
  1494  		subnets: map[SubnetKey]*PoolData{},
  1495  	}
  1496  	var wg sync.WaitGroup
  1497  	opts := map[string]string{
  1498  		ipamapi.AllocSerialPrefix: "true",
  1499  	}
  1500  	var l sync.Mutex
  1501  
  1502  	poolID, _, _, err := a.RequestPool("rosso", "198.168.0.0/23", "", nil, false)
  1503  	if err != nil {
  1504  		t.Fatal(err)
  1505  	}
  1506  
  1507  	for err == nil {
  1508  		var c *net.IPNet
  1509  		if c, _, err = a.RequestAddress(poolID, nil, opts); err == nil {
  1510  			l.Lock()
  1511  			ips = append(ips, IP{c, 1})
  1512  			l.Unlock()
  1513  			allocatedIPs = append(allocatedIPs, c)
  1514  			if len(allocatedIPs) > 500 {
  1515  				i := rand.Intn(len(allocatedIPs) - 1)
  1516  				wg.Add(1)
  1517  				go func(ip *net.IPNet) {
  1518  					if err = a.ReleaseAddress(poolID, ip.IP); err != nil {
  1519  						t.Error(err)
  1520  					}
  1521  					l.Lock()
  1522  					ips = append(ips, IP{ip, -1})
  1523  					l.Unlock()
  1524  					wg.Done()
  1525  				}(allocatedIPs[i])
  1526  				allocatedIPs = append(allocatedIPs[:i], allocatedIPs[i+1:]...)
  1527  			}
  1528  		}
  1529  	}
  1530  	wg.Wait()
  1531  	refMap := make(map[string]int)
  1532  	for _, ip := range ips {
  1533  		refMap[ip.ip.String()] = refMap[ip.ip.String()] + ip.ref
  1534  		if refMap[ip.ip.String()] < 0 {
  1535  			t.Fatalf("IP %s was previously released", ip.ip.String())
  1536  		}
  1537  		if refMap[ip.ip.String()] > 1 {
  1538  			t.Fatalf("IP %s was previously allocated", ip.ip.String())
  1539  		}
  1540  	}
  1541  }
  1542  
  1543  func TestParallelPredefinedRequest1(t *testing.T) {
  1544  	runParallelTests(t, 0)
  1545  }
  1546  
  1547  func TestParallelPredefinedRequest2(t *testing.T) {
  1548  	runParallelTests(t, 1)
  1549  }
  1550  
  1551  func TestParallelPredefinedRequest3(t *testing.T) {
  1552  	runParallelTests(t, 2)
  1553  }
  1554  
  1555  func TestParallelPredefinedRequest4(t *testing.T) {
  1556  	runParallelTests(t, 3)
  1557  }
  1558  
  1559  func TestParallelPredefinedRequest5(t *testing.T) {
  1560  	runParallelTests(t, 4)
  1561  }