github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/libnetwork/ipam/allocator_test.go (about)

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