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 }