allocator_test.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. package ipam
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. "testing"
  7. "time"
  8. "github.com/docker/libnetwork/bitseq"
  9. "github.com/docker/libnetwork/config"
  10. "github.com/docker/libnetwork/datastore"
  11. _ "github.com/docker/libnetwork/netutils"
  12. )
  13. var ds datastore.DataStore
  14. // enable w/ upper case
  15. func testMain(m *testing.M) {
  16. var err error
  17. ds, err = datastore.NewDataStore(&config.DatastoreCfg{Embedded: false, Client: config.DatastoreClientCfg{Provider: "consul", Address: "127.0.0.1:8500"}})
  18. if err != nil {
  19. fmt.Println(err)
  20. }
  21. os.Exit(m.Run())
  22. }
  23. func getAllocator(t *testing.T, subnet *net.IPNet) *Allocator {
  24. a, err := NewAllocator(ds)
  25. if err != nil {
  26. t.Fatal(err)
  27. }
  28. a.AddSubnet("default", &SubnetInfo{Subnet: subnet})
  29. return a
  30. }
  31. func TestInt2IP2IntConversion(t *testing.T) {
  32. for i := uint32(0); i < 256*256*256; i++ {
  33. var array [4]byte // new array at each cycle
  34. addIntToIP(array[:], i)
  35. j := ipToUint32(array[:])
  36. if j != i {
  37. t.Fatalf("Failed to convert ordinal %d to IP % x and back to ordinal. Got %d", i, array, j)
  38. }
  39. }
  40. }
  41. func TestGetAddressVersion(t *testing.T) {
  42. if v4 != getAddressVersion(net.ParseIP("172.28.30.112")) {
  43. t.Fatalf("Failed to detect IPv4 version")
  44. }
  45. if v4 != getAddressVersion(net.ParseIP("0.0.0.1")) {
  46. t.Fatalf("Failed to detect IPv4 version")
  47. }
  48. if v6 != getAddressVersion(net.ParseIP("ff01::1")) {
  49. t.Fatalf("Failed to detect IPv6 version")
  50. }
  51. if v6 != getAddressVersion(net.ParseIP("2001:56::76:51")) {
  52. t.Fatalf("Failed to detect IPv6 version")
  53. }
  54. }
  55. func TestKeyString(t *testing.T) {
  56. k := &subnetKey{addressSpace: "default", subnet: "172.27.0.0/16"}
  57. expected := "default/172.27.0.0/16"
  58. if expected != k.String() {
  59. t.Fatalf("Unexpected key string: %s", k.String())
  60. }
  61. k2 := &subnetKey{}
  62. err := k2.FromString(expected)
  63. if err != nil {
  64. t.Fatal(err)
  65. }
  66. if k2.addressSpace != k.addressSpace || k2.subnet != k.subnet {
  67. t.Fatalf("subnetKey.FromString() failed. Expected %v. Got %v", k, k2)
  68. }
  69. expected = fmt.Sprintf("%s/%s", expected, "172.27.3.0/24")
  70. k.childSubnet = "172.27.3.0/24"
  71. if expected != k.String() {
  72. t.Fatalf("Unexpected key string: %s", k.String())
  73. }
  74. err = k2.FromString(expected)
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. if k2.addressSpace != k.addressSpace || k2.subnet != k.subnet {
  79. t.Fatalf("subnetKey.FromString() failed. Expected %v. Got %v", k, k2)
  80. }
  81. }
  82. func TestAddSubnets(t *testing.T) {
  83. a, err := NewAllocator(nil)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. _, sub0, _ := net.ParseCIDR("10.0.0.0/8")
  88. err = a.AddSubnet("default", &SubnetInfo{Subnet: sub0})
  89. if err != nil {
  90. t.Fatalf("Unexpected failure in adding subent")
  91. }
  92. err = a.AddSubnet("abc", &SubnetInfo{Subnet: sub0})
  93. if err != nil {
  94. t.Fatalf("Unexpected failure in adding overlapping subents to different address spaces")
  95. }
  96. err = a.AddSubnet("abc", &SubnetInfo{Subnet: sub0})
  97. if err == nil {
  98. t.Fatalf("Failed to detect overlapping subnets: %s and %s", sub0, sub0)
  99. }
  100. _, sub1, _ := net.ParseCIDR("10.20.2.0/24")
  101. err = a.AddSubnet("default", &SubnetInfo{Subnet: sub1})
  102. if err == nil {
  103. t.Fatalf("Failed to detect overlapping subnets: %s and %s", sub0, sub1)
  104. }
  105. _, sub2, _ := net.ParseCIDR("10.128.0.0/9")
  106. err = a.AddSubnet("default", &SubnetInfo{Subnet: sub2})
  107. if err == nil {
  108. t.Fatalf("Failed to detect overlapping subnets: %s and %s", sub1, sub2)
  109. }
  110. _, sub6, err := net.ParseCIDR("1003:1:2:3:4:5:6::/112")
  111. if err != nil {
  112. t.Fatalf("Wrong input, Can't proceed: %s", err.Error())
  113. }
  114. err = a.AddSubnet("default", &SubnetInfo{Subnet: sub6})
  115. if err != nil {
  116. t.Fatalf("Failed to add v6 subnet: %s", err.Error())
  117. }
  118. _, sub6, err = net.ParseCIDR("1003:1:2:3::/64")
  119. if err != nil {
  120. t.Fatalf("Wrong input, Can't proceed: %s", err.Error())
  121. }
  122. err = a.AddSubnet("default", &SubnetInfo{Subnet: sub6})
  123. if err == nil {
  124. t.Fatalf("Failed to detect overlapping v6 subnet")
  125. }
  126. }
  127. func TestAdjustAndCheckSubnet(t *testing.T) {
  128. _, sub6, _ := net.ParseCIDR("1003:1:2:300::/63")
  129. _, err := adjustAndCheckSubnetSize(sub6)
  130. if err == nil {
  131. t.Fatalf("Failed detect too big v6 subnet")
  132. }
  133. _, sub, _ := net.ParseCIDR("192.0.0.0/7")
  134. _, err = adjustAndCheckSubnetSize(sub)
  135. if err == nil {
  136. t.Fatalf("Failed detect too big v4 subnet")
  137. }
  138. subnet := "1004:1:2:6::/64"
  139. _, sub6, _ = net.ParseCIDR(subnet)
  140. subnetToSplit, err := adjustAndCheckSubnetSize(sub6)
  141. if err != nil {
  142. t.Fatalf("Unexpected error returned by adjustAndCheckSubnetSize()")
  143. }
  144. ones, _ := subnetToSplit.Mask.Size()
  145. if ones < minNetSizeV6Eff {
  146. t.Fatalf("Wrong effective network size for %s. Expected: %d. Got: %d", subnet, minNetSizeV6Eff, ones)
  147. }
  148. }
  149. func TestRemoveSubnet(t *testing.T) {
  150. a, err := NewAllocator(nil)
  151. if err != nil {
  152. t.Fatal(err)
  153. }
  154. input := []struct {
  155. addrSpace AddressSpace
  156. subnet string
  157. }{
  158. {"default", "192.168.0.0/16"},
  159. {"default", "172.17.0.0/16"},
  160. {"default", "10.0.0.0/8"},
  161. {"default", "2002:1:2:3:4:5:ffff::/112"},
  162. {"splane", "172.17.0.0/16"},
  163. {"splane", "10.0.0.0/8"},
  164. {"splane", "2002:1:2:3:4:5:6::/112"},
  165. {"splane", "2002:1:2:3:4:5:ffff::/112"},
  166. }
  167. for _, i := range input {
  168. _, sub, err := net.ParseCIDR(i.subnet)
  169. if err != nil {
  170. t.Fatalf("Wrong input, Can't proceed: %s", err.Error())
  171. }
  172. err = a.AddSubnet(i.addrSpace, &SubnetInfo{Subnet: sub})
  173. if err != nil {
  174. t.Fatalf("Failed to apply input. Can't proceed: %s", err.Error())
  175. }
  176. }
  177. _, sub, _ := net.ParseCIDR("172.17.0.0/16")
  178. a.RemoveSubnet("default", sub)
  179. if len(a.subnets) != 7 {
  180. t.Fatalf("Failed to remove subnet info")
  181. }
  182. list := a.getSubnetList("default", v4)
  183. if len(list) != 257 {
  184. t.Fatalf("Failed to effectively remove subnet address space")
  185. }
  186. _, sub, _ = net.ParseCIDR("2002:1:2:3:4:5:ffff::/112")
  187. a.RemoveSubnet("default", sub)
  188. if len(a.subnets) != 6 {
  189. t.Fatalf("Failed to remove subnet info")
  190. }
  191. list = a.getSubnetList("default", v6)
  192. if len(list) != 0 {
  193. t.Fatalf("Failed to effectively remove subnet address space")
  194. }
  195. _, sub, _ = net.ParseCIDR("2002:1:2:3:4:5:6::/112")
  196. a.RemoveSubnet("splane", sub)
  197. if len(a.subnets) != 5 {
  198. t.Fatalf("Failed to remove subnet info")
  199. }
  200. list = a.getSubnetList("splane", v6)
  201. if len(list) != 1 {
  202. t.Fatalf("Failed to effectively remove subnet address space")
  203. }
  204. }
  205. func TestGetInternalSubnets(t *testing.T) {
  206. // This function tests the splitting of a parent subnet in small host subnets.
  207. // The splitting is controlled by the max host size, which is the first parameter
  208. // passed to the function. It basically says if the parent subnet host size is
  209. // greater than the max host size, split the parent subnet into N internal small
  210. // subnets with host size = max host size to cover the same address space.
  211. input := []struct {
  212. internalHostSize int
  213. parentSubnet string
  214. firstIntSubnet string
  215. lastIntSubnet string
  216. }{
  217. // Test 8 bits prefix network
  218. {24, "10.0.0.0/8", "10.0.0.0/8", "10.0.0.0/8"},
  219. {16, "10.0.0.0/8", "10.0.0.0/16", "10.255.0.0/16"},
  220. {8, "10.0.0.0/8", "10.0.0.0/24", "10.255.255.0/24"},
  221. // Test 16 bits prefix network
  222. {16, "192.168.0.0/16", "192.168.0.0/16", "192.168.0.0/16"},
  223. {8, "192.168.0.0/16", "192.168.0.0/24", "192.168.255.0/24"},
  224. // Test 24 bits prefix network
  225. {16, "192.168.57.0/24", "192.168.57.0/24", "192.168.57.0/24"},
  226. {8, "192.168.57.0/24", "192.168.57.0/24", "192.168.57.0/24"},
  227. // Test non byte multiple host size
  228. {24, "10.0.0.0/8", "10.0.0.0/8", "10.0.0.0/8"},
  229. {20, "10.0.0.0/12", "10.0.0.0/12", "10.0.0.0/12"},
  230. {20, "10.128.0.0/12", "10.128.0.0/12", "10.128.0.0/12"},
  231. {12, "10.16.0.0/16", "10.16.0.0/20", "10.16.240.0/20"},
  232. {13, "10.0.0.0/8", "10.0.0.0/19", "10.255.224.0/19"},
  233. {15, "10.0.0.0/8", "10.0.0.0/17", "10.255.128.0/17"},
  234. // Test v6 network
  235. {16, "2002:1:2:3:4:5:6000::/110", "2002:1:2:3:4:5:6000:0/112", "2002:1:2:3:4:5:6003:0/112"},
  236. {16, "2002:1:2:3:4:5:ff00::/104", "2002:1:2:3:4:5:ff00:0/112", "2002:1:2:3:4:5:ffff:0/112"},
  237. {12, "2002:1:2:3:4:5:ffff::/112", "2002:1:2:3:4:5:ffff:0/116", "2002:1:2:3:4:5:ffff:f000/116"},
  238. {11, "2002:1:2:3:4:5:ffff::/112", "2002:1:2:3:4:5:ffff:0/117", "2002:1:2:3:4:5:ffff:f800/117"},
  239. }
  240. for _, d := range input {
  241. assertInternalSubnet(t, d.internalHostSize, d.parentSubnet, d.firstIntSubnet, d.lastIntSubnet)
  242. }
  243. }
  244. func TestGetSameAddress(t *testing.T) {
  245. a, err := NewAllocator(nil)
  246. if err != nil {
  247. t.Fatal(err)
  248. }
  249. addSpace := AddressSpace("giallo")
  250. _, subnet, _ := net.ParseCIDR("192.168.100.0/24")
  251. if err := a.AddSubnet(addSpace, &SubnetInfo{Subnet: subnet}); err != nil {
  252. t.Fatal(err)
  253. }
  254. ip := net.ParseIP("192.168.100.250")
  255. req := &AddressRequest{Subnet: *subnet, Address: ip}
  256. _, err = a.Request(addSpace, req)
  257. if err != nil {
  258. t.Fatal(err)
  259. }
  260. _, err = a.Request(addSpace, req)
  261. if err == nil {
  262. t.Fatal(err)
  263. }
  264. }
  265. func TestGetAddress(t *testing.T) {
  266. input := []string{
  267. /*"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",
  268. "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",
  269. "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",
  270. "10.0.0.0/29", "10.0.0.0/30", "10.0.0.0/31"}
  271. for _, subnet := range input {
  272. assertGetAddress(t, subnet)
  273. }
  274. }
  275. func TestGetSubnetList(t *testing.T) {
  276. a, err := NewAllocator(nil)
  277. if err != nil {
  278. t.Fatal(err)
  279. }
  280. input := []struct {
  281. addrSpace AddressSpace
  282. subnet string
  283. }{
  284. {"default", "192.168.0.0/16"},
  285. {"default", "172.17.0.0/16"},
  286. {"default", "10.0.0.0/8"},
  287. {"default", "2002:1:2:3:4:5:6::/112"},
  288. {"default", "2002:1:2:3:4:5:ffff::/112"},
  289. {"splane", "172.17.0.0/16"},
  290. {"splane", "10.0.0.0/8"},
  291. {"splane", "2002:1:2:3:4:5:ff00::/104"},
  292. }
  293. for _, i := range input {
  294. _, sub, err := net.ParseCIDR(i.subnet)
  295. if err != nil {
  296. t.Fatalf("Wrong input, Can't proceed: %s", err.Error())
  297. }
  298. err = a.AddSubnet(i.addrSpace, &SubnetInfo{Subnet: sub})
  299. if err != nil {
  300. t.Fatalf("Failed to apply input. Can't proceed: %s", err.Error())
  301. }
  302. }
  303. list := a.getSubnetList("default", v4)
  304. if len(list) != 258 {
  305. t.Fatalf("Incorrect number of internal subnets for ipv4 version. Expected 258. Got %d.", len(list))
  306. }
  307. list = a.getSubnetList("splane", v4)
  308. if len(list) != 257 {
  309. t.Fatalf("Incorrect number of internal subnets for ipv4 version. Expected 257. Got %d.", len(list))
  310. }
  311. list = a.getSubnetList("default", v6)
  312. if len(list) != 2 {
  313. t.Fatalf("Incorrect number of internal subnets for ipv6 version. Expected 2. Got %d.", len(list))
  314. }
  315. list = a.getSubnetList("splane", v6)
  316. if len(list) != 256 {
  317. t.Fatalf("Incorrect number of internal subnets for ipv6 version. Expected 256. Got %d.", len(list))
  318. }
  319. }
  320. func TestRequestSyntaxCheck(t *testing.T) {
  321. var (
  322. subnet = "192.168.0.0/16"
  323. addSpace = AddressSpace("green")
  324. )
  325. a, err := NewAllocator(nil)
  326. if err != nil {
  327. t.Fatal(err)
  328. }
  329. // Add subnet and create base request
  330. _, sub, _ := net.ParseCIDR(subnet)
  331. a.AddSubnet(addSpace, &SubnetInfo{Subnet: sub})
  332. req := &AddressRequest{Subnet: *sub}
  333. // Empty address space request
  334. _, err = a.Request("", req)
  335. if err == nil {
  336. t.Fatalf("Failed to detect wrong request: empty address space")
  337. }
  338. // Preferred address from different subnet in request
  339. req.Address = net.ParseIP("172.17.0.23")
  340. _, err = a.Request(addSpace, req)
  341. if err == nil {
  342. t.Fatalf("Failed to detect wrong request: preferred IP from different subnet")
  343. }
  344. // Preferred address specified and nil subnet
  345. req = &AddressRequest{Address: net.ParseIP("172.17.0.23")}
  346. _, err = a.Request(addSpace, req)
  347. if err == nil {
  348. t.Fatalf("Failed to detect wrong request: subnet not specified but preferred address specified")
  349. }
  350. }
  351. func TestRequest(t *testing.T) {
  352. // Request N addresses from different size subnets, verifying last request
  353. // returns expected address. Internal subnet host size is Allocator's default, 16
  354. input := []struct {
  355. subnet string
  356. numReq int
  357. lastIP string
  358. }{
  359. {"192.168.59.0/24", 254, "192.168.59.254"},
  360. {"192.168.240.0/20", 255, "192.168.240.255"},
  361. {"192.168.0.0/16", 255, "192.168.0.255"},
  362. {"192.168.0.0/16", 256, "192.168.1.0"},
  363. {"10.16.0.0/16", 255, "10.16.0.255"},
  364. {"10.128.0.0/12", 255, "10.128.0.255"},
  365. {"10.0.0.0/8", 256, "10.0.1.0"},
  366. {"192.168.128.0/18", 4*256 - 1, "192.168.131.255"},
  367. {"192.168.240.0/20", 16*256 - 2, "192.168.255.254"},
  368. {"192.168.0.0/16", 256*256 - 2, "192.168.255.254"},
  369. {"10.0.0.0/8", 2 * 256, "10.0.2.0"},
  370. {"10.0.0.0/8", 5 * 256, "10.0.5.0"},
  371. //{"10.0.0.0/8", 100 * 256 * 254, "10.99.255.254"},
  372. }
  373. for _, d := range input {
  374. assertNRequests(t, d.subnet, d.numReq, d.lastIP)
  375. }
  376. }
  377. func TestRelease(t *testing.T) {
  378. var (
  379. err error
  380. req *AddressRequest
  381. subnet = "192.168.0.0/16"
  382. )
  383. _, sub, _ := net.ParseCIDR(subnet)
  384. a := getAllocator(t, sub)
  385. req = &AddressRequest{Subnet: *sub}
  386. bm := a.addresses[subnetKey{"default", subnet, subnet}]
  387. // Allocate all addresses
  388. for err != ErrNoAvailableIPs {
  389. _, err = a.Request("default", req)
  390. }
  391. toRelease := []struct {
  392. address string
  393. }{
  394. {"192.168.0.1"},
  395. {"192.168.0.2"},
  396. {"192.168.0.3"},
  397. {"192.168.0.4"},
  398. {"192.168.0.5"},
  399. {"192.168.0.6"},
  400. {"192.168.0.7"},
  401. {"192.168.0.8"},
  402. {"192.168.0.9"},
  403. {"192.168.0.10"},
  404. {"192.168.0.30"},
  405. {"192.168.0.31"},
  406. {"192.168.1.32"},
  407. {"192.168.0.254"},
  408. {"192.168.1.1"},
  409. {"192.168.1.2"},
  410. {"192.168.1.3"},
  411. {"192.168.255.253"},
  412. {"192.168.255.254"},
  413. }
  414. // One by one, relase the address and request again. We should get the same IP
  415. req = &AddressRequest{Subnet: *sub}
  416. for i, inp := range toRelease {
  417. address := net.ParseIP(inp.address)
  418. a.Release("default", address)
  419. if bm.Unselected() != 1 {
  420. t.Fatalf("Failed to update free address count after release. Expected %d, Found: %d", i+1, bm.Unselected())
  421. }
  422. rsp, err := a.Request("default", req)
  423. if err != nil {
  424. t.Fatalf("Failed to obtain the address: %s", err.Error())
  425. }
  426. if !address.Equal(rsp.Address) {
  427. t.Fatalf("Failed to obtain the same address. Expected: %s, Got: %s", address, rsp.Address)
  428. }
  429. }
  430. }
  431. func assertInternalSubnet(t *testing.T, hostSize int, bigSubnet, firstSmall, lastSmall string) {
  432. _, subnet, _ := net.ParseCIDR(bigSubnet)
  433. list, _ := getInternalSubnets(subnet, hostSize)
  434. count := 1
  435. ones, bits := subnet.Mask.Size()
  436. diff := bits - ones - int(hostSize)
  437. if diff > 0 {
  438. count <<= uint(diff)
  439. }
  440. if len(list) != count {
  441. t.Fatalf("Wrong small subnets number. Expected: %d, Got: %d", count, len(list))
  442. }
  443. if firstSmall != list[0].String() {
  444. t.Fatalf("Wrong first small subent. Expected: %v, Got: %v", firstSmall, list[0])
  445. }
  446. if lastSmall != list[count-1].String() {
  447. t.Fatalf("Wrong last small subent. Expected: %v, Got: %v", lastSmall, list[count-1])
  448. }
  449. }
  450. func assertGetAddress(t *testing.T, subnet string) {
  451. var (
  452. err error
  453. printTime = false
  454. a = &Allocator{}
  455. )
  456. _, sub, _ := net.ParseCIDR(subnet)
  457. ones, bits := sub.Mask.Size()
  458. zeroes := bits - ones
  459. numAddresses := 1 << uint(zeroes)
  460. bm, err := bitseq.NewHandle("ipam_test", nil, "default/192.168.0.0/24", uint32(numAddresses))
  461. if err != nil {
  462. t.Fatal(err)
  463. }
  464. start := time.Now()
  465. run := 0
  466. for err != ErrNoAvailableIPs {
  467. _, err = a.getAddress(sub, bm, nil, v4)
  468. run++
  469. }
  470. if printTime {
  471. fmt.Printf("\nTaken %v, to allocate all addresses on %s. (nemAddresses: %d. Runs: %d)", time.Since(start), subnet, numAddresses, run)
  472. }
  473. if bm.Unselected() != 0 {
  474. t.Fatalf("Unexpected free count after reserving all addresses: %d", bm.Unselected())
  475. }
  476. /*
  477. if bm.Head.Block != expectedMax || bm.Head.Count != numBlocks {
  478. t.Fatalf("Failed to effectively reserve all addresses on %s. Expected (0x%x, %d) as first sequence. Found (0x%x,%d)",
  479. subnet, expectedMax, numBlocks, bm.Head.Block, bm.Head.Count)
  480. }
  481. */
  482. }
  483. func assertNRequests(t *testing.T, subnet string, numReq int, lastExpectedIP string) {
  484. var (
  485. err error
  486. req *AddressRequest
  487. rsp *AddressResponse
  488. printTime = false
  489. )
  490. _, sub, _ := net.ParseCIDR(subnet)
  491. lastIP := net.ParseIP(lastExpectedIP)
  492. a := getAllocator(t, sub)
  493. req = &AddressRequest{Subnet: *sub}
  494. i := 0
  495. start := time.Now()
  496. for ; i < numReq; i++ {
  497. rsp, err = a.Request("default", req)
  498. }
  499. if printTime {
  500. fmt.Printf("\nTaken %v, to allocate %d addresses on %s\n", time.Since(start), numReq, subnet)
  501. }
  502. if !lastIP.Equal(rsp.Address) {
  503. t.Fatalf("Wrong last IP. Expected %s. Got: %s (err: %v, ind: %d)", lastExpectedIP, rsp.Address.String(), err, i)
  504. }
  505. }
  506. func benchmarkRequest(subnet *net.IPNet) {
  507. var err error
  508. a, _ := NewAllocator(nil)
  509. a.internalHostSize = 20
  510. a.AddSubnet("default", &SubnetInfo{Subnet: subnet})
  511. req := &AddressRequest{Subnet: *subnet}
  512. for err != ErrNoAvailableIPs {
  513. _, err = a.Request("default", req)
  514. }
  515. }
  516. func benchMarkRequest(subnet *net.IPNet, b *testing.B) {
  517. for n := 0; n < b.N; n++ {
  518. benchmarkRequest(subnet)
  519. }
  520. }
  521. func BenchmarkRequest_24(b *testing.B) {
  522. benchmarkRequest(&net.IPNet{IP: []byte{10, 0, 0, 0}, Mask: []byte{255, 255, 255, 0}})
  523. }
  524. func BenchmarkRequest_16(b *testing.B) {
  525. benchmarkRequest(&net.IPNet{IP: []byte{10, 0, 0, 0}, Mask: []byte{255, 255, 0, 0}})
  526. }
  527. func BenchmarkRequest_8(b *testing.B) {
  528. benchmarkRequest(&net.IPNet{IP: []byte{10, 0, 0, 0}, Mask: []byte{255, 0xfc, 0, 0}})
  529. }