github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/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 "testing" 12 "time" 13 14 "github.com/docker/libkv/store" 15 "github.com/docker/libkv/store/boltdb" 16 "github.com/docker/libnetwork/bitseq" 17 "github.com/docker/libnetwork/datastore" 18 "github.com/docker/libnetwork/ipamapi" 19 "github.com/docker/libnetwork/ipamutils" 20 _ "github.com/docker/libnetwork/testutils" 21 "github.com/docker/libnetwork/types" 22 ) 23 24 const ( 25 defaultPrefix = "/tmp/libnetwork/test/ipam" 26 ) 27 28 func init() { 29 boltdb.Register() 30 } 31 32 // OptionBoltdbWithRandomDBFile function returns a random dir for local store backend 33 func randomLocalStore() (datastore.DataStore, error) { 34 tmp, err := ioutil.TempFile("", "libnetwork-") 35 if err != nil { 36 return nil, fmt.Errorf("Error creating temp file: %v", err) 37 } 38 if err := tmp.Close(); err != nil { 39 return nil, fmt.Errorf("Error closing temp file: %v", err) 40 } 41 return datastore.NewDataStore(datastore.LocalScope, &datastore.ScopeCfg{ 42 Client: datastore.ScopeClientCfg{ 43 Provider: "boltdb", 44 Address: defaultPrefix + tmp.Name(), 45 Config: &store.Config{ 46 Bucket: "libnetwork", 47 ConnectionTimeout: 3 * time.Second, 48 }, 49 }, 50 }) 51 } 52 53 func getAllocator() (*Allocator, error) { 54 ipamutils.InitNetworks() 55 ds, err := randomLocalStore() 56 if err != nil { 57 return nil, err 58 } 59 a, err := NewAllocator(ds, nil) 60 if err != nil { 61 return nil, err 62 } 63 return a, 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.Fatalf("Failed to detect IPv4 version") 80 } 81 if v4 != getAddressVersion(net.ParseIP("0.0.0.1")) { 82 t.Fatalf("Failed to detect IPv4 version") 83 } 84 if v6 != getAddressVersion(net.ParseIP("ff01::1")) { 85 t.Fatalf("Failed to detect IPv6 version") 86 } 87 if v6 != getAddressVersion(net.ParseIP("2001:db8::76:51")) { 88 t.Fatalf("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.Fatalf("Unexpected Range") 169 } 170 } 171 172 func TestSubnetsMarshal(t *testing.T) { 173 a, err := getAllocator() 174 if err != nil { 175 t.Fatal(err) 176 } 177 pid0, _, _, err := a.RequestPool(localAddressSpace, "192.168.0.0/16", "", nil, false) 178 if err != nil { 179 t.Fatal(err) 180 } 181 pid1, _, _, err := a.RequestPool(localAddressSpace, "192.169.0.0/16", "", nil, false) 182 if err != nil { 183 t.Fatal(err) 184 } 185 _, _, err = a.RequestAddress(pid0, nil, nil) 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 cfg, err := a.getAddrSpace(localAddressSpace) 191 if err != nil { 192 t.Fatal(err) 193 } 194 195 ba := cfg.Value() 196 if err := cfg.SetValue(ba); err != nil { 197 t.Fatal(err) 198 } 199 200 expIP := &net.IPNet{IP: net.IP{192, 168, 0, 2}, Mask: net.IPMask{255, 255, 0, 0}} 201 ip, _, err := a.RequestAddress(pid0, nil, nil) 202 if err != nil { 203 t.Fatal(err) 204 } 205 if !types.CompareIPNet(expIP, ip) { 206 t.Fatalf("Got unexpected ip after pool config restore: %s", ip) 207 } 208 209 expIP = &net.IPNet{IP: net.IP{192, 169, 0, 1}, Mask: net.IPMask{255, 255, 0, 0}} 210 ip, _, err = a.RequestAddress(pid1, nil, nil) 211 if err != nil { 212 t.Fatal(err) 213 } 214 if !types.CompareIPNet(expIP, ip) { 215 t.Fatalf("Got unexpected ip after pool config restore: %s", ip) 216 } 217 } 218 219 func TestAddSubnets(t *testing.T) { 220 a, err := getAllocator() 221 if err != nil { 222 t.Fatal(err) 223 } 224 a.addrSpaces["abc"] = a.addrSpaces[localAddressSpace] 225 226 pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false) 227 if err != nil { 228 t.Fatalf("Unexpected failure in adding subnet") 229 } 230 231 pid1, _, _, err := a.RequestPool("abc", "10.0.0.0/8", "", nil, false) 232 if err != nil { 233 t.Fatalf("Unexpected failure in adding overlapping subnets to different address spaces: %v", err) 234 } 235 236 if pid0 == pid1 { 237 t.Fatalf("returned same pool id for same subnets in different namespaces") 238 } 239 240 pid, _, _, err := a.RequestPool("abc", "10.0.0.0/8", "", nil, false) 241 if err != nil { 242 t.Fatalf("Unexpected failure requesting existing subnet: %v", err) 243 } 244 if pid != pid1 { 245 t.Fatalf("returned different pool id for same subnet requests") 246 } 247 248 _, _, _, err = a.RequestPool("abc", "10.128.0.0/9", "", nil, false) 249 if err == nil { 250 t.Fatalf("Expected failure on adding overlapping base subnet") 251 } 252 253 pid2, _, _, 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 pid3, _, _, err := a.RequestPool("abc", "10.0.0.0/8", "10.128.0.0/9", nil, false) 258 if err != nil { 259 t.Fatalf("Unexpected failure on adding overlapping sub pool: %v", err) 260 } 261 if pid2 != pid3 { 262 t.Fatalf("returned different pool id for same sub pool requests") 263 } 264 265 pid, _, _, err = a.RequestPool(localAddressSpace, "10.20.2.0/24", "", nil, false) 266 if err == nil { 267 t.Fatalf("Failed to detect overlapping subnets") 268 } 269 270 _, _, _, err = a.RequestPool(localAddressSpace, "10.128.0.0/9", "", nil, false) 271 if err == nil { 272 t.Fatalf("Failed to detect overlapping subnets") 273 } 274 275 _, _, _, err = a.RequestPool(localAddressSpace, "1003:1:2:3:4:5:6::/112", "", nil, false) 276 if err != nil { 277 t.Fatalf("Failed to add v6 subnet: %s", err.Error()) 278 } 279 280 _, _, _, err = a.RequestPool(localAddressSpace, "1003:1:2:3::/64", "", nil, false) 281 if err == nil { 282 t.Fatalf("Failed to detect overlapping v6 subnet") 283 } 284 } 285 286 func TestAddReleasePoolID(t *testing.T) { 287 var k0, k1, k2 SubnetKey 288 289 a, err := getAllocator() 290 if err != nil { 291 t.Fatal(err) 292 } 293 294 aSpace, err := a.getAddrSpace(localAddressSpace) 295 if err != nil { 296 t.Fatal(err) 297 } 298 299 subnets := aSpace.subnets 300 pid0, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false) 301 if err != nil { 302 t.Fatalf("Unexpected failure in adding pool") 303 } 304 if err := k0.FromString(pid0); err != nil { 305 t.Fatal(err) 306 } 307 308 aSpace, err = a.getAddrSpace(localAddressSpace) 309 if err != nil { 310 t.Fatal(err) 311 } 312 313 subnets = aSpace.subnets 314 315 if subnets[k0].RefCount != 1 { 316 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 317 } 318 319 pid1, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false) 320 if err != nil { 321 t.Fatalf("Unexpected failure in adding sub pool") 322 } 323 if err := k1.FromString(pid1); err != nil { 324 t.Fatal(err) 325 } 326 327 aSpace, err = a.getAddrSpace(localAddressSpace) 328 if err != nil { 329 t.Fatal(err) 330 } 331 332 subnets = aSpace.subnets 333 if subnets[k1].RefCount != 1 { 334 t.Fatalf("Unexpected ref count for %s: %d", k1, subnets[k1].RefCount) 335 } 336 337 pid2, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "10.0.0.0/16", nil, false) 338 if err != nil { 339 t.Fatalf("Unexpected failure in adding sub pool") 340 } 341 if pid0 == pid1 || pid0 == pid2 || pid1 != pid2 { 342 t.Fatalf("Incorrect poolIDs returned %s, %s, %s", pid0, pid1, pid2) 343 } 344 if err := k2.FromString(pid2); err != nil { 345 t.Fatal(err) 346 } 347 348 aSpace, err = a.getAddrSpace(localAddressSpace) 349 if err != nil { 350 t.Fatal(err) 351 } 352 353 subnets = aSpace.subnets 354 if subnets[k2].RefCount != 2 { 355 t.Fatalf("Unexpected ref count for %s: %d", k2, subnets[k2].RefCount) 356 } 357 358 if subnets[k0].RefCount != 3 { 359 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 360 } 361 362 if err := a.ReleasePool(pid1); err != nil { 363 t.Fatal(err) 364 } 365 366 aSpace, err = a.getAddrSpace(localAddressSpace) 367 if err != nil { 368 t.Fatal(err) 369 } 370 371 subnets = aSpace.subnets 372 if subnets[k0].RefCount != 2 { 373 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 374 } 375 if err := a.ReleasePool(pid0); err != nil { 376 t.Fatal(err) 377 } 378 379 aSpace, err = a.getAddrSpace(localAddressSpace) 380 if err != nil { 381 t.Fatal(err) 382 } 383 384 subnets = aSpace.subnets 385 if subnets[k0].RefCount != 1 { 386 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 387 } 388 389 pid00, _, _, err := a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false) 390 if err != nil { 391 t.Fatalf("Unexpected failure in adding pool") 392 } 393 if pid00 != pid0 { 394 t.Fatalf("main pool should still exist") 395 } 396 397 aSpace, err = a.getAddrSpace(localAddressSpace) 398 if err != nil { 399 t.Fatal(err) 400 } 401 402 subnets = aSpace.subnets 403 if subnets[k0].RefCount != 2 { 404 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 405 } 406 407 if err := a.ReleasePool(pid2); err != nil { 408 t.Fatal(err) 409 } 410 411 aSpace, err = a.getAddrSpace(localAddressSpace) 412 if err != nil { 413 t.Fatal(err) 414 } 415 416 subnets = aSpace.subnets 417 if subnets[k0].RefCount != 1 { 418 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 419 } 420 421 if err := a.ReleasePool(pid00); err != nil { 422 t.Fatal(err) 423 } 424 425 aSpace, err = a.getAddrSpace(localAddressSpace) 426 if err != nil { 427 t.Fatal(err) 428 } 429 430 subnets = aSpace.subnets 431 if bp, ok := subnets[k0]; ok { 432 t.Fatalf("Base pool %s is still present: %v", k0, bp) 433 } 434 435 _, _, _, err = a.RequestPool(localAddressSpace, "10.0.0.0/8", "", nil, false) 436 if err != nil { 437 t.Fatalf("Unexpected failure in adding pool") 438 } 439 440 aSpace, err = a.getAddrSpace(localAddressSpace) 441 if err != nil { 442 t.Fatal(err) 443 } 444 445 subnets = aSpace.subnets 446 if subnets[k0].RefCount != 1 { 447 t.Fatalf("Unexpected ref count for %s: %d", k0, subnets[k0].RefCount) 448 } 449 } 450 451 func TestPredefinedPool(t *testing.T) { 452 a, err := getAllocator() 453 if err != nil { 454 t.Fatal(err) 455 } 456 457 if _, err := a.getPredefinedPool("blue", false); err == nil { 458 t.Fatalf("Expected failure for non default addr space") 459 } 460 461 pid, nw, _, err := a.RequestPool(localAddressSpace, "", "", nil, false) 462 if err != nil { 463 t.Fatal(err) 464 } 465 466 nw2, err := a.getPredefinedPool(localAddressSpace, false) 467 if err != nil { 468 t.Fatal(err) 469 } 470 if types.CompareIPNet(nw, nw2) { 471 t.Fatalf("Unexpected default network returned: %s = %s", nw2, nw) 472 } 473 474 if err := a.ReleasePool(pid); err != nil { 475 t.Fatal(err) 476 } 477 } 478 479 func TestRemoveSubnet(t *testing.T) { 480 a, err := getAllocator() 481 if err != nil { 482 t.Fatal(err) 483 } 484 a.addrSpaces["splane"] = &addrSpace{ 485 id: dsConfigKey + "/" + "splane", 486 ds: a.addrSpaces[localAddressSpace].ds, 487 alloc: a.addrSpaces[localAddressSpace].alloc, 488 scope: a.addrSpaces[localAddressSpace].scope, 489 subnets: map[SubnetKey]*PoolData{}, 490 } 491 492 input := []struct { 493 addrSpace string 494 subnet string 495 v6 bool 496 }{ 497 {localAddressSpace, "192.168.0.0/16", false}, 498 {localAddressSpace, "172.17.0.0/16", false}, 499 {localAddressSpace, "10.0.0.0/8", false}, 500 {localAddressSpace, "2001:db8:1:2:3:4:ffff::/112", false}, 501 {"splane", "172.17.0.0/16", false}, 502 {"splane", "10.0.0.0/8", false}, 503 {"splane", "2001:db8:1:2:3:4:5::/112", true}, 504 {"splane", "2001:db8:1:2:3:4:ffff::/112", true}, 505 } 506 507 poolIDs := make([]string, len(input)) 508 509 for ind, i := range input { 510 if poolIDs[ind], _, _, err = a.RequestPool(i.addrSpace, i.subnet, "", nil, i.v6); err != nil { 511 t.Fatalf("Failed to apply input. Can't proceed: %s", err.Error()) 512 } 513 } 514 515 for ind, id := range poolIDs { 516 if err := a.ReleasePool(id); err != nil { 517 t.Fatalf("Failed to release poolID %s (%d)", id, ind) 518 } 519 } 520 } 521 522 func TestGetSameAddress(t *testing.T) { 523 a, err := getAllocator() 524 if err != nil { 525 t.Fatal(err) 526 } 527 a.addrSpaces["giallo"] = &addrSpace{ 528 id: dsConfigKey + "/" + "giallo", 529 ds: a.addrSpaces[localAddressSpace].ds, 530 alloc: a.addrSpaces[localAddressSpace].alloc, 531 scope: a.addrSpaces[localAddressSpace].scope, 532 subnets: map[SubnetKey]*PoolData{}, 533 } 534 535 pid, _, _, err := a.RequestPool("giallo", "192.168.100.0/24", "", nil, false) 536 if err != nil { 537 t.Fatal(err) 538 } 539 540 ip := net.ParseIP("192.168.100.250") 541 _, _, err = a.RequestAddress(pid, ip, nil) 542 if err != nil { 543 t.Fatal(err) 544 } 545 546 _, _, err = a.RequestAddress(pid, ip, nil) 547 if err == nil { 548 t.Fatal(err) 549 } 550 } 551 552 func TestGetAddressSubPoolEqualPool(t *testing.T) { 553 a, err := getAllocator() 554 if err != nil { 555 t.Fatal(err) 556 } 557 // Requesting a subpool of same size of the master pool should not cause any problem on ip allocation 558 pid, _, _, err := a.RequestPool(localAddressSpace, "172.18.0.0/16", "172.18.0.0/16", nil, false) 559 if err != nil { 560 t.Fatal(err) 561 } 562 563 _, _, err = a.RequestAddress(pid, nil, nil) 564 if err != nil { 565 t.Fatal(err) 566 } 567 } 568 569 func TestRequestReleaseAddressFromSubPool(t *testing.T) { 570 a, err := getAllocator() 571 if err != nil { 572 t.Fatal(err) 573 } 574 a.addrSpaces["rosso"] = &addrSpace{ 575 id: dsConfigKey + "/" + "rosso", 576 ds: a.addrSpaces[localAddressSpace].ds, 577 alloc: a.addrSpaces[localAddressSpace].alloc, 578 scope: a.addrSpaces[localAddressSpace].scope, 579 subnets: map[SubnetKey]*PoolData{}, 580 } 581 582 poolID, _, _, err := a.RequestPool("rosso", "172.28.0.0/16", "172.28.30.0/24", nil, false) 583 if err != nil { 584 t.Fatal(err) 585 } 586 587 var ip *net.IPNet 588 expected := &net.IPNet{IP: net.IP{172, 28, 30, 255}, Mask: net.IPMask{255, 255, 0, 0}} 589 for err == nil { 590 var c *net.IPNet 591 if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil { 592 ip = c 593 } 594 } 595 if err != ipamapi.ErrNoAvailableIPs { 596 t.Fatal(err) 597 } 598 if !types.CompareIPNet(expected, ip) { 599 t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip) 600 } 601 rp := &net.IPNet{IP: net.IP{172, 28, 30, 97}, Mask: net.IPMask{255, 255, 0, 0}} 602 if err = a.ReleaseAddress(poolID, rp.IP); err != nil { 603 t.Fatal(err) 604 } 605 if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil { 606 t.Fatal(err) 607 } 608 if !types.CompareIPNet(rp, ip) { 609 t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip) 610 } 611 612 _, _, _, err = a.RequestPool("rosso", "10.0.0.0/8", "10.0.0.0/16", nil, false) 613 if err != nil { 614 t.Fatal(err) 615 } 616 poolID, _, _, err = a.RequestPool("rosso", "10.0.0.0/16", "10.0.0.0/24", nil, false) 617 if err != nil { 618 t.Fatal(err) 619 } 620 expected = &net.IPNet{IP: net.IP{10, 0, 0, 255}, Mask: net.IPMask{255, 255, 0, 0}} 621 for err == nil { 622 var c *net.IPNet 623 if c, _, err = a.RequestAddress(poolID, nil, nil); err == nil { 624 ip = c 625 } 626 } 627 if err != ipamapi.ErrNoAvailableIPs { 628 t.Fatal(err) 629 } 630 if !types.CompareIPNet(expected, ip) { 631 t.Fatalf("Unexpected last IP from subpool. Expected: %s. Got: %v.", expected, ip) 632 } 633 rp = &net.IPNet{IP: net.IP{10, 0, 0, 79}, Mask: net.IPMask{255, 255, 0, 0}} 634 if err = a.ReleaseAddress(poolID, rp.IP); err != nil { 635 t.Fatal(err) 636 } 637 if ip, _, err = a.RequestAddress(poolID, nil, nil); err != nil { 638 t.Fatal(err) 639 } 640 if !types.CompareIPNet(rp, ip) { 641 t.Fatalf("Unexpected IP from subpool. Expected: %s. Got: %v.", rp, ip) 642 } 643 644 // Request any addresses from subpool after explicit address request 645 unoExp, _ := types.ParseCIDR("10.2.2.0/16") 646 dueExp, _ := types.ParseCIDR("10.2.2.2/16") 647 treExp, _ := types.ParseCIDR("10.2.2.1/16") 648 if poolID, _, _, err = a.RequestPool("rosso", "10.2.0.0/16", "10.2.2.0/24", nil, false); err != nil { 649 t.Fatal(err) 650 } 651 tre, _, err := a.RequestAddress(poolID, treExp.IP, nil) 652 if err != nil { 653 t.Fatal(err) 654 } 655 if !types.CompareIPNet(tre, treExp) { 656 t.Fatalf("Unexpected address: %v", tre) 657 } 658 659 uno, _, err := a.RequestAddress(poolID, nil, nil) 660 if err != nil { 661 t.Fatal(err) 662 } 663 if !types.CompareIPNet(uno, unoExp) { 664 t.Fatalf("Unexpected address: %v", uno) 665 } 666 667 due, _, err := a.RequestAddress(poolID, nil, nil) 668 if err != nil { 669 t.Fatal(err) 670 } 671 if !types.CompareIPNet(due, dueExp) { 672 t.Fatalf("Unexpected address: %v", due) 673 } 674 675 if err = a.ReleaseAddress(poolID, uno.IP); err != nil { 676 t.Fatal(err) 677 } 678 uno, _, err = a.RequestAddress(poolID, nil, nil) 679 if err != nil { 680 t.Fatal(err) 681 } 682 if !types.CompareIPNet(uno, unoExp) { 683 t.Fatalf("Unexpected address: %v", uno) 684 } 685 686 if err = a.ReleaseAddress(poolID, tre.IP); err != nil { 687 t.Fatal(err) 688 } 689 tre, _, err = a.RequestAddress(poolID, nil, nil) 690 if err != nil { 691 t.Fatal(err) 692 } 693 if !types.CompareIPNet(tre, treExp) { 694 t.Fatalf("Unexpected address: %v", tre) 695 } 696 } 697 698 func TestGetAddress(t *testing.T) { 699 input := []string{ 700 /*"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", 701 "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", 702 "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", 703 "10.0.0.0/29", "10.0.0.0/30", "10.0.0.0/31"} 704 705 for _, subnet := range input { 706 assertGetAddress(t, subnet) 707 } 708 } 709 710 func TestRequestSyntaxCheck(t *testing.T) { 711 var ( 712 pool = "192.168.0.0/16" 713 subPool = "192.168.0.0/24" 714 as = "green" 715 err error 716 ) 717 718 a, err := getAllocator() 719 if err != nil { 720 t.Fatal(err) 721 } 722 a.addrSpaces[as] = &addrSpace{ 723 id: dsConfigKey + "/" + as, 724 ds: a.addrSpaces[localAddressSpace].ds, 725 alloc: a.addrSpaces[localAddressSpace].alloc, 726 scope: a.addrSpaces[localAddressSpace].scope, 727 subnets: map[SubnetKey]*PoolData{}, 728 } 729 730 _, _, _, err = a.RequestPool("", pool, "", nil, false) 731 if err == nil { 732 t.Fatalf("Failed to detect wrong request: empty address space") 733 } 734 735 _, _, _, err = a.RequestPool("", pool, subPool, nil, false) 736 if err == nil { 737 t.Fatalf("Failed to detect wrong request: empty address space") 738 } 739 740 _, _, _, err = a.RequestPool(as, "", subPool, nil, false) 741 if err == nil { 742 t.Fatalf("Failed to detect wrong request: subPool specified and no pool") 743 } 744 745 pid, _, _, err := a.RequestPool(as, pool, subPool, nil, false) 746 if err != nil { 747 t.Fatalf("Unexpected failure: %v", err) 748 } 749 750 _, _, err = a.RequestAddress("", nil, nil) 751 if err == nil { 752 t.Fatalf("Failed to detect wrong request: no pool id specified") 753 } 754 755 ip := net.ParseIP("172.17.0.23") 756 _, _, err = a.RequestAddress(pid, ip, nil) 757 if err == nil { 758 t.Fatalf("Failed to detect wrong request: requested IP from different subnet") 759 } 760 761 ip = net.ParseIP("192.168.0.50") 762 _, _, err = a.RequestAddress(pid, ip, nil) 763 if err != nil { 764 t.Fatalf("Unexpected failure: %v", err) 765 } 766 767 err = a.ReleaseAddress("", ip) 768 if err == nil { 769 t.Fatalf("Failed to detect wrong request: no pool id specified") 770 } 771 772 err = a.ReleaseAddress(pid, nil) 773 if err == nil { 774 t.Fatalf("Failed to detect wrong request: no pool id specified") 775 } 776 777 err = a.ReleaseAddress(pid, ip) 778 if err != nil { 779 t.Fatalf("Unexpected failure: %v: %s, %s", err, pid, ip) 780 } 781 } 782 783 func TestRequest(t *testing.T) { 784 // Request N addresses from different size subnets, verifying last request 785 // returns expected address. Internal subnet host size is Allocator's default, 16 786 input := []struct { 787 subnet string 788 numReq int 789 lastIP string 790 }{ 791 {"192.168.59.0/24", 254, "192.168.59.254"}, 792 {"192.168.240.0/20", 255, "192.168.240.255"}, 793 {"192.168.0.0/16", 255, "192.168.0.255"}, 794 {"192.168.0.0/16", 256, "192.168.1.0"}, 795 {"10.16.0.0/16", 255, "10.16.0.255"}, 796 {"10.128.0.0/12", 255, "10.128.0.255"}, 797 {"10.0.0.0/8", 256, "10.0.1.0"}, 798 799 {"192.168.128.0/18", 4*256 - 1, "192.168.131.255"}, 800 /* 801 {"192.168.240.0/20", 16*256 - 2, "192.168.255.254"}, 802 803 {"192.168.0.0/16", 256*256 - 2, "192.168.255.254"}, 804 {"10.0.0.0/8", 2 * 256, "10.0.2.0"}, 805 {"10.0.0.0/8", 5 * 256, "10.0.5.0"}, 806 {"10.0.0.0/8", 100 * 256 * 254, "10.99.255.254"}, 807 */ 808 } 809 810 for _, d := range input { 811 assertNRequests(t, d.subnet, d.numReq, d.lastIP) 812 } 813 } 814 815 func TestRelease(t *testing.T) { 816 var ( 817 subnet = "192.168.0.0/23" 818 ) 819 820 a, err := getAllocator() 821 if err != nil { 822 t.Fatal(err) 823 } 824 pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false) 825 if err != nil { 826 t.Fatal(err) 827 } 828 829 bm := a.addresses[SubnetKey{localAddressSpace, subnet, ""}] 830 831 // Allocate all addresses 832 for err != ipamapi.ErrNoAvailableIPs { 833 _, _, err = a.RequestAddress(pid, nil, nil) 834 } 835 836 toRelease := []struct { 837 address string 838 }{ 839 {"192.168.0.1"}, 840 {"192.168.0.2"}, 841 {"192.168.0.3"}, 842 {"192.168.0.4"}, 843 {"192.168.0.5"}, 844 {"192.168.0.6"}, 845 {"192.168.0.7"}, 846 {"192.168.0.8"}, 847 {"192.168.0.9"}, 848 {"192.168.0.10"}, 849 {"192.168.0.30"}, 850 {"192.168.0.31"}, 851 {"192.168.1.32"}, 852 853 {"192.168.0.254"}, 854 {"192.168.1.1"}, 855 {"192.168.1.2"}, 856 857 {"192.168.1.3"}, 858 859 {"192.168.1.253"}, 860 {"192.168.1.254"}, 861 } 862 863 // One by one, relase the address and request again. We should get the same IP 864 for i, inp := range toRelease { 865 ip0 := net.ParseIP(inp.address) 866 a.ReleaseAddress(pid, ip0) 867 bm = a.addresses[SubnetKey{localAddressSpace, subnet, ""}] 868 if bm.Unselected() != 1 { 869 t.Fatalf("Failed to update free address count after release. Expected %d, Found: %d", i+1, bm.Unselected()) 870 } 871 872 nw, _, err := a.RequestAddress(pid, nil, nil) 873 if err != nil { 874 t.Fatalf("Failed to obtain the address: %s", err.Error()) 875 } 876 ip := nw.IP 877 if !ip0.Equal(ip) { 878 t.Fatalf("Failed to obtain the same address. Expected: %s, Got: %s", ip0, ip) 879 } 880 } 881 } 882 883 func assertGetAddress(t *testing.T, subnet string) { 884 var ( 885 err error 886 printTime = false 887 a = &Allocator{} 888 ) 889 890 _, sub, _ := net.ParseCIDR(subnet) 891 ones, bits := sub.Mask.Size() 892 zeroes := bits - ones 893 numAddresses := 1 << uint(zeroes) 894 895 bm, err := bitseq.NewHandle("ipam_test", nil, "default/"+subnet, uint64(numAddresses)) 896 if err != nil { 897 t.Fatal(err) 898 } 899 900 start := time.Now() 901 run := 0 902 for err != ipamapi.ErrNoAvailableIPs { 903 _, err = a.getAddress(sub, bm, nil, nil) 904 run++ 905 } 906 if printTime { 907 fmt.Printf("\nTaken %v, to allocate all addresses on %s. (nemAddresses: %d. Runs: %d)", time.Since(start), subnet, numAddresses, run) 908 } 909 if bm.Unselected() != 0 { 910 t.Fatalf("Unexpected free count after reserving all addresses: %d", bm.Unselected()) 911 } 912 /* 913 if bm.Head.Block != expectedMax || bm.Head.Count != numBlocks { 914 t.Fatalf("Failed to effectively reserve all addresses on %s. Expected (0x%x, %d) as first sequence. Found (0x%x,%d)", 915 subnet, expectedMax, numBlocks, bm.Head.Block, bm.Head.Count) 916 } 917 */ 918 } 919 920 func assertNRequests(t *testing.T, subnet string, numReq int, lastExpectedIP string) { 921 var ( 922 nw *net.IPNet 923 printTime = false 924 ) 925 926 lastIP := net.ParseIP(lastExpectedIP) 927 a, err := getAllocator() 928 if err != nil { 929 t.Fatal(err) 930 } 931 pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false) 932 if err != nil { 933 t.Fatal(err) 934 } 935 936 i := 0 937 start := time.Now() 938 for ; i < numReq; i++ { 939 nw, _, err = a.RequestAddress(pid, nil, nil) 940 } 941 if printTime { 942 fmt.Printf("\nTaken %v, to allocate %d addresses on %s\n", time.Since(start), numReq, subnet) 943 } 944 945 if !lastIP.Equal(nw.IP) { 946 t.Fatalf("Wrong last IP. Expected %s. Got: %s (err: %v, ind: %d)", lastExpectedIP, nw.IP.String(), err, i) 947 } 948 } 949 950 func benchmarkRequest(b *testing.B, a *Allocator, subnet string) { 951 pid, _, _, err := a.RequestPool(localAddressSpace, subnet, "", nil, false) 952 for err != ipamapi.ErrNoAvailableIPs { 953 _, _, err = a.RequestAddress(pid, nil, nil) 954 } 955 } 956 957 func benchMarkRequest(subnet string, b *testing.B) { 958 a, _ := getAllocator() 959 for n := 0; n < b.N; n++ { 960 benchmarkRequest(b, a, subnet) 961 } 962 } 963 964 func BenchmarkRequest_24(b *testing.B) { 965 a, _ := getAllocator() 966 benchmarkRequest(b, a, "10.0.0.0/24") 967 } 968 969 func BenchmarkRequest_16(b *testing.B) { 970 a, _ := getAllocator() 971 benchmarkRequest(b, a, "10.0.0.0/16") 972 } 973 974 func BenchmarkRequest_8(b *testing.B) { 975 a, _ := getAllocator() 976 benchmarkRequest(b, a, "10.0.0.0/8") 977 } 978 979 func TestAllocateRandomDeallocate(t *testing.T) { 980 testAllocateRandomDeallocate(t, "172.25.0.0/16", "", 384) 981 testAllocateRandomDeallocate(t, "172.25.0.0/16", "172.25.252.0/22", 384) 982 } 983 984 func testAllocateRandomDeallocate(t *testing.T, pool, subPool string, num int) { 985 ds, err := randomLocalStore() 986 if err != nil { 987 t.Fatal(err) 988 } 989 990 a, err := NewAllocator(ds, nil) 991 if err != nil { 992 t.Fatal(err) 993 } 994 995 pid, _, _, err := a.RequestPool(localAddressSpace, pool, subPool, nil, false) 996 if err != nil { 997 t.Fatal(err) 998 } 999 1000 // Allocate num ip addresses 1001 indices := make(map[int]*net.IPNet, num) 1002 allocated := make(map[string]bool, num) 1003 for i := 0; i < num; i++ { 1004 ip, _, err := a.RequestAddress(pid, nil, nil) 1005 if err != nil { 1006 t.Fatal(err) 1007 } 1008 ips := ip.String() 1009 if _, ok := allocated[ips]; ok { 1010 t.Fatalf("Address %s is already allocated", ips) 1011 } 1012 allocated[ips] = true 1013 indices[i] = ip 1014 } 1015 if len(indices) != len(allocated) || len(indices) != num { 1016 t.Fatalf("Unexpected number of allocated addresses: (%d,%d).", len(indices), len(allocated)) 1017 } 1018 1019 seed := time.Now().Unix() 1020 rand.Seed(seed) 1021 1022 // Deallocate half of the allocated addresses following a random pattern 1023 pattern := rand.Perm(num) 1024 for i := 0; i < num/2; i++ { 1025 idx := pattern[i] 1026 ip := indices[idx] 1027 err := a.ReleaseAddress(pid, ip.IP) 1028 if err != nil { 1029 t.Fatalf("Unexpected failure on deallocation of %s: %v.\nSeed: %d.", ip, err, seed) 1030 } 1031 delete(indices, idx) 1032 delete(allocated, ip.String()) 1033 } 1034 1035 // Request a quarter of addresses 1036 for i := 0; i < num/2; i++ { 1037 ip, _, err := a.RequestAddress(pid, nil, nil) 1038 if err != nil { 1039 t.Fatal(err) 1040 } 1041 ips := ip.String() 1042 if _, ok := allocated[ips]; ok { 1043 t.Fatalf("\nAddress %s is already allocated.\nSeed: %d.", ips, seed) 1044 } 1045 allocated[ips] = true 1046 } 1047 if len(allocated) != num { 1048 t.Fatalf("Unexpected number of allocated addresses: %d.\nSeed: %d.", len(allocated), seed) 1049 } 1050 } 1051 1052 func TestRetrieveFromStore(t *testing.T) { 1053 num := 200 1054 ds, err := randomLocalStore() 1055 if err != nil { 1056 t.Fatal(err) 1057 } 1058 a, err := NewAllocator(ds, nil) 1059 if err != nil { 1060 t.Fatal(err) 1061 } 1062 pid, _, _, err := a.RequestPool(localAddressSpace, "172.25.0.0/16", "", nil, false) 1063 if err != nil { 1064 t.Fatal(err) 1065 } 1066 for i := 0; i < num; i++ { 1067 if _, _, err := a.RequestAddress(pid, nil, nil); err != nil { 1068 t.Fatal(err) 1069 } 1070 } 1071 1072 // Restore 1073 a1, err := NewAllocator(ds, nil) 1074 if err != nil { 1075 t.Fatal(err) 1076 } 1077 a1.refresh(localAddressSpace) 1078 db := a.DumpDatabase() 1079 db1 := a1.DumpDatabase() 1080 if db != db1 { 1081 t.Fatalf("Unexpected db change.\nExpected:%s\nGot:%s", db, db1) 1082 } 1083 checkDBEquality(a, a1, t) 1084 pid, _, _, err = a1.RequestPool(localAddressSpace, "172.25.0.0/16", "172.25.1.0/24", nil, false) 1085 if err != nil { 1086 t.Fatal(err) 1087 } 1088 for i := 0; i < num/2; i++ { 1089 if _, _, err := a1.RequestAddress(pid, nil, nil); err != nil { 1090 t.Fatal(err) 1091 } 1092 } 1093 1094 // Restore 1095 a2, err := NewAllocator(ds, nil) 1096 if err != nil { 1097 t.Fatal(err) 1098 } 1099 a2.refresh(localAddressSpace) 1100 checkDBEquality(a1, a2, t) 1101 pid, _, _, err = a2.RequestPool(localAddressSpace, "172.25.0.0/16", "172.25.2.0/24", nil, false) 1102 if err != nil { 1103 t.Fatal(err) 1104 } 1105 for i := 0; i < num/2; i++ { 1106 if _, _, err := a2.RequestAddress(pid, nil, nil); err != nil { 1107 t.Fatal(err) 1108 } 1109 } 1110 1111 // Restore 1112 a3, err := NewAllocator(ds, nil) 1113 if err != nil { 1114 t.Fatal(err) 1115 } 1116 a3.refresh(localAddressSpace) 1117 checkDBEquality(a2, a3, t) 1118 pid, _, _, err = a3.RequestPool(localAddressSpace, "172.26.0.0/16", "", nil, false) 1119 if err != nil { 1120 t.Fatal(err) 1121 } 1122 for i := 0; i < num/2; i++ { 1123 if _, _, err := a3.RequestAddress(pid, nil, nil); err != nil { 1124 t.Fatal(err) 1125 } 1126 } 1127 1128 // Restore 1129 a4, err := NewAllocator(ds, nil) 1130 if err != nil { 1131 t.Fatal(err) 1132 } 1133 a4.refresh(localAddressSpace) 1134 checkDBEquality(a3, a4, t) 1135 } 1136 1137 func checkDBEquality(a1, a2 *Allocator, t *testing.T) { 1138 for k, cnf1 := range a1.addrSpaces[localAddressSpace].subnets { 1139 cnf2 := a2.addrSpaces[localAddressSpace].subnets[k] 1140 if cnf1.String() != cnf2.String() { 1141 t.Fatalf("%s\n%s", cnf1, cnf2) 1142 } 1143 if cnf1.Range == nil { 1144 a2.retrieveBitmask(k, cnf1.Pool) 1145 } 1146 } 1147 1148 for k, bm1 := range a1.addresses { 1149 bm2 := a2.addresses[k] 1150 if bm1.String() != bm2.String() { 1151 t.Fatalf("%s\n%s", bm1, bm2) 1152 } 1153 } 1154 } 1155 1156 const ( 1157 numInstances = 5 1158 first = 0 1159 last = numInstances - 1 1160 ) 1161 1162 var ( 1163 allocator *Allocator 1164 start = make(chan struct{}) 1165 done = make(chan chan struct{}, numInstances-1) 1166 pools = make([]*net.IPNet, numInstances) 1167 ) 1168 1169 func runParallelTests(t *testing.T, instance int) { 1170 var err error 1171 1172 t.Parallel() 1173 1174 pTest := flag.Lookup("test.parallel") 1175 if pTest == nil { 1176 t.Skip("Skipped because test.parallel flag not set;") 1177 } 1178 numParallel, err := strconv.Atoi(pTest.Value.String()) 1179 if err != nil { 1180 t.Fatal(err) 1181 } 1182 if numParallel < numInstances { 1183 t.Skip("Skipped because t.parallel was less than ", numInstances) 1184 } 1185 1186 // The first instance creates the allocator, gives the start 1187 // and finally checks the pools each instance was assigned 1188 if instance == first { 1189 allocator, err = getAllocator() 1190 if err != nil { 1191 t.Fatal(err) 1192 } 1193 close(start) 1194 } 1195 1196 if instance != first { 1197 select { 1198 case <-start: 1199 } 1200 1201 instDone := make(chan struct{}) 1202 done <- instDone 1203 defer close(instDone) 1204 1205 if instance == last { 1206 defer close(done) 1207 } 1208 } 1209 1210 _, pools[instance], _, err = allocator.RequestPool(localAddressSpace, "", "", nil, false) 1211 if err != nil { 1212 t.Fatal(err) 1213 } 1214 1215 if instance == first { 1216 for instDone := range done { 1217 select { 1218 case <-instDone: 1219 } 1220 } 1221 // Now check each instance got a different pool 1222 for i := 0; i < numInstances; i++ { 1223 for j := i + 1; j < numInstances; j++ { 1224 if types.CompareIPNet(pools[i], pools[j]) { 1225 t.Fatalf("Instance %d and %d were given the same predefined pool: %v", i, j, pools) 1226 } 1227 } 1228 } 1229 } 1230 } 1231 1232 func TestParallelPredefinedRequest1(t *testing.T) { 1233 runParallelTests(t, 0) 1234 } 1235 1236 func TestParallelPredefinedRequest2(t *testing.T) { 1237 runParallelTests(t, 1) 1238 } 1239 1240 func TestParallelPredefinedRequest3(t *testing.T) { 1241 runParallelTests(t, 2) 1242 } 1243 1244 func TestParallelPredefinedRequest4(t *testing.T) { 1245 runParallelTests(t, 3) 1246 } 1247 1248 func TestParallelPredefinedRequest5(t *testing.T) { 1249 runParallelTests(t, 4) 1250 }