1
16
17 package ipallocator
18
19 import (
20 "fmt"
21 "net"
22 "testing"
23
24 "k8s.io/apimachinery/pkg/util/sets"
25 "k8s.io/component-base/metrics/testutil"
26 api "k8s.io/kubernetes/pkg/apis/core"
27 netutils "k8s.io/utils/net"
28 )
29
30 func TestAllocate(t *testing.T) {
31 testCases := []struct {
32 name string
33 cidr string
34 family api.IPFamily
35 free int
36 released string
37 outOfRange []string
38 alreadyAllocated string
39 }{
40 {
41 name: "IPv4",
42 cidr: "192.168.1.0/24",
43 family: api.IPv4Protocol,
44 free: 254,
45 released: "192.168.1.5",
46 outOfRange: []string{
47 "192.168.0.1",
48 "192.168.1.0",
49 "192.168.1.255",
50 "192.168.2.2",
51 },
52 alreadyAllocated: "192.168.1.1",
53 },
54 {
55 name: "IPv4 large",
56 cidr: "10.0.0.0/15",
57 family: api.IPv4Protocol,
58 free: 131070,
59 released: "10.0.0.5",
60 outOfRange: []string{
61 "10.0.0.0",
62 "10.15.255.255",
63 "10.255.255.2",
64 },
65 alreadyAllocated: "10.0.0.1",
66 },
67 {
68 name: "IPv6",
69 cidr: "2001:db8:1::/48",
70 family: api.IPv6Protocol,
71 free: 65535,
72 released: "2001:db8:1::5",
73 outOfRange: []string{
74 "2001:db8::1",
75 "2001:db8:1::",
76 "2001:db8:1::1:0",
77 "2001:db8:2::2",
78 },
79 alreadyAllocated: "2001:db8:1::1",
80 },
81 }
82 for _, tc := range testCases {
83 t.Run(tc.name, func(t *testing.T) {
84 _, cidr, err := netutils.ParseCIDRSloppy(tc.cidr)
85 if err != nil {
86 t.Fatal(err)
87 }
88 r, err := NewInMemory(cidr)
89 if err != nil {
90 t.Fatal(err)
91 }
92 if f := r.Free(); f != tc.free {
93 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, tc.free, f)
94 }
95
96 rCIDR := r.CIDR()
97 if rCIDR.String() != tc.cidr {
98 t.Errorf("[%s] wrong CIDR: expected %v, got %v", tc.name, tc.cidr, rCIDR.String())
99 }
100
101 if r.IPFamily() != tc.family {
102 t.Errorf("[%s] wrong IP family: expected %v, got %v", tc.name, tc.family, r.IPFamily())
103 }
104
105 if f := r.Used(); f != 0 {
106 t.Errorf("[%s]: wrong used: expected %d, got %d", tc.name, 0, f)
107 }
108 found := sets.NewString()
109 count := 0
110 for r.Free() > 0 {
111 ip, err := r.AllocateNext()
112 if err != nil {
113 t.Fatalf("[%s] error @ %d: %v", tc.name, count, err)
114 }
115 count++
116 if !cidr.Contains(ip) {
117 t.Fatalf("[%s] allocated %s which is outside of %s", tc.name, ip, cidr)
118 }
119 if found.Has(ip.String()) {
120 t.Fatalf("[%s] allocated %s twice @ %d", tc.name, ip, count)
121 }
122 found.Insert(ip.String())
123 }
124 if _, err := r.AllocateNext(); err != ErrFull {
125 t.Fatal(err)
126 }
127
128 released := netutils.ParseIPSloppy(tc.released)
129 if err := r.Release(released); err != nil {
130 t.Fatal(err)
131 }
132 if f := r.Free(); f != 1 {
133 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, 1, f)
134 }
135 if f := r.Used(); f != (tc.free - 1) {
136 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, tc.free-1, f)
137 }
138 ip, err := r.AllocateNext()
139 if err != nil {
140 t.Fatal(err)
141 }
142 if !released.Equal(ip) {
143 t.Errorf("[%s] unexpected %s : %s", tc.name, ip, released)
144 }
145
146 if err := r.Release(released); err != nil {
147 t.Fatal(err)
148 }
149 for _, outOfRange := range tc.outOfRange {
150 err = r.Allocate(netutils.ParseIPSloppy(outOfRange))
151 if _, ok := err.(*ErrNotInRange); !ok {
152 t.Fatal(err)
153 }
154 }
155 if err := r.Allocate(netutils.ParseIPSloppy(tc.alreadyAllocated)); err != ErrAllocated {
156 t.Fatal(err)
157 }
158 if f := r.Free(); f != 1 {
159 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, 1, f)
160 }
161 if f := r.Used(); f != (tc.free - 1) {
162 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, tc.free-1, f)
163 }
164 if err := r.Allocate(released); err != nil {
165 t.Fatal(err)
166 }
167 if f := r.Free(); f != 0 {
168 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, 0, f)
169 }
170 if f := r.Used(); f != tc.free {
171 t.Errorf("[%s] wrong free: expected %d, got %d", tc.name, tc.free, f)
172 }
173 })
174 }
175 }
176
177 func TestAllocateTiny(t *testing.T) {
178 _, cidr, err := netutils.ParseCIDRSloppy("192.168.1.0/32")
179 if err != nil {
180 t.Fatal(err)
181 }
182 r, err := NewInMemory(cidr)
183 if err != nil {
184 t.Fatal(err)
185 }
186 if f := r.Free(); f != 0 {
187 t.Errorf("free: %d", f)
188 }
189 if _, err := r.AllocateNext(); err != ErrFull {
190 t.Error(err)
191 }
192 }
193
194 func TestAllocateReserved(t *testing.T) {
195 _, cidr, err := netutils.ParseCIDRSloppy("192.168.1.0/25")
196 if err != nil {
197 t.Fatal(err)
198 }
199 r, err := NewInMemory(cidr)
200 if err != nil {
201 t.Fatal(err)
202 }
203
204
205 dynamicOffset := calculateRangeOffset(cidr)
206 dynamicBlockSize := r.max - dynamicOffset
207 for i := 0; i < dynamicBlockSize; i++ {
208 if _, err := r.AllocateNext(); err != nil {
209 t.Errorf("Unexpected error trying to allocate: %v", err)
210 }
211 }
212 for i := dynamicOffset; i < r.max; i++ {
213 ip := fmt.Sprintf("192.168.1.%d", i+1)
214 if !r.Has(netutils.ParseIPSloppy(ip)) {
215 t.Errorf("IP %s expected to be allocated", ip)
216 }
217 }
218 if f := r.Free(); f != dynamicOffset {
219 t.Errorf("expected %d free addresses, got %d", dynamicOffset, f)
220 }
221
222 for i := 0; i < dynamicOffset; i++ {
223 ip := fmt.Sprintf("192.168.1.%d", i+1)
224 if err := r.Allocate(netutils.ParseIPSloppy(ip)); err != nil {
225 t.Errorf("Unexpected error trying to allocate IP %s: %v", ip, err)
226 }
227 }
228 if f := r.Free(); f != 0 {
229 t.Errorf("expected free equal to 0 got: %d", f)
230 }
231
232 if err := r.Release(netutils.ParseIPSloppy("192.168.1.10")); err != nil {
233 t.Fatalf("Unexpected error trying to release ip 192.168.1.10: %v", err)
234 }
235 if _, err := r.AllocateNext(); err != nil {
236 t.Error(err)
237 }
238 if f := r.Free(); f != 0 {
239 t.Errorf("expected free equal to 0 got: %d", f)
240 }
241 }
242
243 func TestAllocateSmall(t *testing.T) {
244 _, cidr, err := netutils.ParseCIDRSloppy("192.168.1.240/30")
245 if err != nil {
246 t.Fatal(err)
247 }
248 r, err := NewInMemory(cidr)
249 if err != nil {
250 t.Fatal(err)
251 }
252 if f := r.Free(); f != 2 {
253 t.Errorf("expected free equal to 2 got: %d", f)
254 }
255 found := sets.NewString()
256 for i := 0; i < 2; i++ {
257 ip, err := r.AllocateNext()
258 if err != nil {
259 t.Fatal(err)
260 }
261 if found.Has(ip.String()) {
262 t.Fatalf("address %s has been already allocated", ip)
263 }
264 found.Insert(ip.String())
265 }
266 for s := range found {
267 if !r.Has(netutils.ParseIPSloppy(s)) {
268 t.Fatalf("missing: %s", s)
269 }
270 if err := r.Allocate(netutils.ParseIPSloppy(s)); err != ErrAllocated {
271 t.Fatal(err)
272 }
273 }
274 for i := 0; i < 100; i++ {
275 if _, err := r.AllocateNext(); err != ErrFull {
276 t.Fatalf("suddenly became not-full: %#v", r)
277 }
278 }
279
280 if f := r.Free(); f != 0 {
281 t.Errorf("expected free equal to 0 got: %d", f)
282 }
283
284 if r.max != 2 {
285 t.Fatalf("expected range equal to 2, got: %v", r)
286 }
287 }
288
289 func TestForEach(t *testing.T) {
290 _, cidr, err := netutils.ParseCIDRSloppy("192.168.1.0/24")
291 if err != nil {
292 t.Fatal(err)
293 }
294
295 testCases := []sets.String{
296 sets.NewString(),
297 sets.NewString("192.168.1.1"),
298 sets.NewString("192.168.1.1", "192.168.1.254"),
299 sets.NewString("192.168.1.1", "192.168.1.128", "192.168.1.254"),
300 }
301
302 for i, tc := range testCases {
303 r, err := NewInMemory(cidr)
304 if err != nil {
305 t.Fatal(err)
306 }
307 for ips := range tc {
308 ip := netutils.ParseIPSloppy(ips)
309 if err := r.Allocate(ip); err != nil {
310 t.Errorf("[%d] error allocating IP %v: %v", i, ip, err)
311 }
312 if !r.Has(ip) {
313 t.Errorf("[%d] expected IP %v allocated", i, ip)
314 }
315 }
316 calls := sets.NewString()
317 r.ForEach(func(ip net.IP) {
318 calls.Insert(ip.String())
319 })
320 if len(calls) != len(tc) {
321 t.Errorf("[%d] expected %d calls, got %d", i, len(tc), len(calls))
322 }
323 if !calls.Equal(tc) {
324 t.Errorf("[%d] expected calls to equal testcase: %v vs %v", i, calls.List(), tc.List())
325 }
326 }
327 }
328
329 func TestSnapshot(t *testing.T) {
330 _, cidr, err := netutils.ParseCIDRSloppy("192.168.1.0/24")
331 if err != nil {
332 t.Fatal(err)
333 }
334 r, err := NewInMemory(cidr)
335 if err != nil {
336 t.Fatal(err)
337 }
338 ip := []net.IP{}
339 for i := 0; i < 10; i++ {
340 n, err := r.AllocateNext()
341 if err != nil {
342 t.Fatal(err)
343 }
344 ip = append(ip, n)
345 }
346
347 var dst api.RangeAllocation
348 err = r.Snapshot(&dst)
349 if err != nil {
350 t.Fatal(err)
351 }
352
353 _, network, err := netutils.ParseCIDRSloppy(dst.Range)
354 if err != nil {
355 t.Fatal(err)
356 }
357
358 if !network.IP.Equal(cidr.IP) || network.Mask.String() != cidr.Mask.String() {
359 t.Fatalf("mismatched networks: %s : %s", network, cidr)
360 }
361
362 _, otherCidr, err := netutils.ParseCIDRSloppy("192.168.2.0/24")
363 if err != nil {
364 t.Fatal(err)
365 }
366 _, err = NewInMemory(otherCidr)
367 if err != nil {
368 t.Fatal(err)
369 }
370 if err := r.Restore(otherCidr, dst.Data); err != ErrMismatchedNetwork {
371 t.Fatal(err)
372 }
373 other, err := NewInMemory(network)
374 if err != nil {
375 t.Fatal(err)
376 }
377 if err := other.Restore(network, dst.Data); err != nil {
378 t.Fatal(err)
379 }
380
381 for _, n := range ip {
382 if !other.Has(n) {
383 t.Errorf("restored range does not have %s", n)
384 }
385 }
386 if other.Free() != r.Free() {
387 t.Errorf("counts do not match: %d", other.Free())
388 }
389 }
390
391 func TestNewFromSnapshot(t *testing.T) {
392 _, cidr, err := netutils.ParseCIDRSloppy("192.168.0.0/24")
393 if err != nil {
394 t.Fatal(err)
395 }
396 r, err := NewInMemory(cidr)
397 if err != nil {
398 t.Fatal(err)
399 }
400 allocated := []net.IP{}
401 for i := 0; i < 128; i++ {
402 ip, err := r.AllocateNext()
403 if err != nil {
404 t.Fatal(err)
405 }
406 allocated = append(allocated, ip)
407 }
408
409 snapshot := api.RangeAllocation{}
410 if err = r.Snapshot(&snapshot); err != nil {
411 t.Fatal(err)
412 }
413
414 r, err = NewFromSnapshot(&snapshot)
415 if err != nil {
416 t.Fatal(err)
417 }
418
419 if x := r.Free(); x != 126 {
420 t.Fatalf("expected 126 free IPs, got %d", x)
421 }
422 if x := r.Used(); x != 128 {
423 t.Fatalf("expected 128 used IPs, got %d", x)
424 }
425
426 for _, ip := range allocated {
427 if !r.Has(ip) {
428 t.Fatalf("expected IP to be allocated, but it was not")
429 }
430 }
431 }
432
433 func TestClusterIPMetrics(t *testing.T) {
434 clearMetrics()
435
436 cidrIPv4 := "10.0.0.0/24"
437 _, clusterCIDRv4, _ := netutils.ParseCIDRSloppy(cidrIPv4)
438 a, err := NewInMemory(clusterCIDRv4)
439 if err != nil {
440 t.Fatalf("unexpected error creating CidrSet: %v", err)
441 }
442 a.EnableMetrics()
443
444 cidrIPv6 := "2001:db8::/112"
445 _, clusterCIDRv6, _ := netutils.ParseCIDRSloppy(cidrIPv6)
446 b, err := NewInMemory(clusterCIDRv6)
447 b.EnableMetrics()
448 if err != nil {
449 t.Fatalf("unexpected error creating CidrSet: %v", err)
450 }
451
452
453 em := testMetrics{
454 free: 0,
455 used: 0,
456 allocated: 0,
457 errors: 0,
458 }
459 expectMetrics(t, cidrIPv4, em)
460 em = testMetrics{
461 free: 0,
462 used: 0,
463 allocated: 0,
464 errors: 0,
465 }
466 expectMetrics(t, cidrIPv6, em)
467
468
469 found := sets.NewString()
470 for i := 0; i < 2; i++ {
471 ip, err := a.AllocateNext()
472 if err != nil {
473 t.Fatal(err)
474 }
475 if found.Has(ip.String()) {
476 t.Fatalf("already reserved: %s", ip)
477 }
478 found.Insert(ip.String())
479 }
480
481 em = testMetrics{
482 free: 252,
483 used: 2,
484 allocated: 2,
485 errors: 0,
486 }
487 expectMetrics(t, cidrIPv4, em)
488
489
490 for s := range found {
491 if !a.Has(netutils.ParseIPSloppy(s)) {
492 t.Fatalf("missing: %s", s)
493 }
494 if err := a.Allocate(netutils.ParseIPSloppy(s)); err != ErrAllocated {
495 t.Fatal(err)
496 }
497 }
498 em = testMetrics{
499 free: 252,
500 used: 2,
501 allocated: 2,
502 errors: 2,
503 }
504 expectMetrics(t, cidrIPv4, em)
505
506
507 for s := range found {
508 if !a.Has(netutils.ParseIPSloppy(s)) {
509 t.Fatalf("missing: %s", s)
510 }
511 if err := a.Release(netutils.ParseIPSloppy(s)); err != nil {
512 t.Fatal(err)
513 }
514 }
515 em = testMetrics{
516 free: 254,
517 used: 0,
518 allocated: 2,
519 errors: 2,
520 }
521 expectMetrics(t, cidrIPv4, em)
522
523
524
525 for i := 0; i < 264; i++ {
526 a.AllocateNext()
527 b.AllocateNext()
528 }
529 em = testMetrics{
530 free: 0,
531 used: 254,
532 allocated: 256,
533 errors: 12,
534 }
535 expectMetrics(t, cidrIPv4, em)
536 em = testMetrics{
537 free: 65271,
538 used: 264,
539 allocated: 264,
540 errors: 0,
541 }
542 expectMetrics(t, cidrIPv6, em)
543 }
544
545 func TestClusterIPAllocatedMetrics(t *testing.T) {
546 clearMetrics()
547
548 cidrIPv4 := "10.0.0.0/25"
549 _, clusterCIDRv4, _ := netutils.ParseCIDRSloppy(cidrIPv4)
550 a, err := NewInMemory(clusterCIDRv4)
551 if err != nil {
552 t.Fatalf("unexpected error creating CidrSet: %v", err)
553 }
554 a.EnableMetrics()
555
556 em := testMetrics{
557 free: 0,
558 used: 0,
559 allocated: 0,
560 errors: 0,
561 }
562 expectMetrics(t, cidrIPv4, em)
563
564
565 found := sets.NewString()
566 for i := 0; i < 2; i++ {
567 ip, err := a.AllocateNext()
568 if err != nil {
569 t.Fatal(err)
570 }
571 if found.Has(ip.String()) {
572 t.Fatalf("already reserved: %s", ip)
573 }
574 found.Insert(ip.String())
575 }
576
577 dynamic_allocated, err := testutil.GetCounterMetricValue(clusterIPAllocations.WithLabelValues(cidrIPv4, "dynamic"))
578 if err != nil {
579 t.Errorf("failed to get %s value, err: %v", clusterIPAllocations.Name, err)
580 }
581 if dynamic_allocated != 2 {
582 t.Fatalf("Expected 2 received %f", dynamic_allocated)
583 }
584
585
586 for s := range found {
587 if !a.Has(netutils.ParseIPSloppy(s)) {
588 t.Fatalf("missing: %s", s)
589 }
590 if err := a.Allocate(netutils.ParseIPSloppy(s)); err != ErrAllocated {
591 t.Fatal(err)
592 }
593 }
594
595 static_errors, err := testutil.GetCounterMetricValue(clusterIPAllocationErrors.WithLabelValues(cidrIPv4, "static"))
596 if err != nil {
597 t.Errorf("failed to get %s value, err: %v", clusterIPAllocationErrors.Name, err)
598 }
599 if static_errors != 2 {
600 t.Fatalf("Expected 2 received %f", dynamic_allocated)
601 }
602 }
603
604 func TestMetricsDisabled(t *testing.T) {
605
606 cidrIPv4 := "10.0.0.0/24"
607 _, clusterCIDRv4, _ := netutils.ParseCIDRSloppy(cidrIPv4)
608 a, err := NewInMemory(clusterCIDRv4)
609 if err != nil {
610 t.Fatalf("unexpected error creating CidrSet: %v", err)
611 }
612 a.EnableMetrics()
613
614
615
616 b, err := NewInMemory(clusterCIDRv4)
617 if err != nil {
618 t.Fatalf("unexpected error creating CidrSet: %v", err)
619 }
620
621
622 em := testMetrics{
623 free: 0,
624 used: 0,
625 allocated: 0,
626 errors: 0,
627 }
628 expectMetrics(t, cidrIPv4, em)
629
630
631 for i := 0; i < 100; i++ {
632 _, err := a.AllocateNext()
633 if err != nil {
634 t.Fatal(err)
635 }
636 }
637 em = testMetrics{
638 free: 154,
639 used: 100,
640 allocated: 100,
641 errors: 0,
642 }
643 expectMetrics(t, cidrIPv4, em)
644
645
646 for i := 0; i < 200; i++ {
647 _, err := b.AllocateNext()
648 if err != nil {
649 t.Fatal(err)
650 }
651 }
652
653 expectMetrics(t, cidrIPv4, em)
654 }
655
656
657 func clearMetrics() {
658 clusterIPAllocated.Reset()
659 clusterIPAvailable.Reset()
660 clusterIPAllocations.Reset()
661 clusterIPAllocationErrors.Reset()
662 }
663
664 type testMetrics struct {
665 free float64
666 used float64
667 allocated float64
668 errors float64
669 }
670
671 func expectMetrics(t *testing.T, label string, em testMetrics) {
672 var m testMetrics
673 var err error
674 m.free, err = testutil.GetGaugeMetricValue(clusterIPAvailable.WithLabelValues(label))
675 if err != nil {
676 t.Errorf("failed to get %s value, err: %v", clusterIPAvailable.Name, err)
677 }
678 m.used, err = testutil.GetGaugeMetricValue(clusterIPAllocated.WithLabelValues(label))
679 if err != nil {
680 t.Errorf("failed to get %s value, err: %v", clusterIPAllocated.Name, err)
681 }
682 static_allocated, err := testutil.GetCounterMetricValue(clusterIPAllocations.WithLabelValues(label, "static"))
683 if err != nil {
684 t.Errorf("failed to get %s value, err: %v", clusterIPAllocations.Name, err)
685 }
686 static_errors, err := testutil.GetCounterMetricValue(clusterIPAllocationErrors.WithLabelValues(label, "static"))
687 if err != nil {
688 t.Errorf("failed to get %s value, err: %v", clusterIPAllocationErrors.Name, err)
689 }
690 dynamic_allocated, err := testutil.GetCounterMetricValue(clusterIPAllocations.WithLabelValues(label, "dynamic"))
691 if err != nil {
692 t.Errorf("failed to get %s value, err: %v", clusterIPAllocations.Name, err)
693 }
694 dynamic_errors, err := testutil.GetCounterMetricValue(clusterIPAllocationErrors.WithLabelValues(label, "dynamic"))
695 if err != nil {
696 t.Errorf("failed to get %s value, err: %v", clusterIPAllocationErrors.Name, err)
697 }
698
699 m.allocated = static_allocated + dynamic_allocated
700 m.errors = static_errors + dynamic_errors
701
702 if m != em {
703 t.Fatalf("metrics error: expected %v, received %v", em, m)
704 }
705 }
706
707 func TestDryRun(t *testing.T) {
708 testCases := []struct {
709 name string
710 cidr string
711 family api.IPFamily
712 }{{
713 name: "IPv4",
714 cidr: "192.168.1.0/24",
715 family: api.IPv4Protocol,
716 }, {
717 name: "IPv6",
718 cidr: "2001:db8:1::/48",
719 family: api.IPv6Protocol,
720 }}
721 for _, tc := range testCases {
722 t.Run(tc.name, func(t *testing.T) {
723 _, cidr, err := netutils.ParseCIDRSloppy(tc.cidr)
724 if err != nil {
725 t.Fatalf("unexpected failure: %v", err)
726 }
727 r, err := NewInMemory(cidr)
728 if err != nil {
729 t.Fatalf("unexpected failure: %v", err)
730 }
731
732 baseUsed := r.Used()
733
734 rCIDR := r.DryRun().CIDR()
735 if rCIDR.String() != tc.cidr {
736 t.Errorf("allocator returned a different cidr")
737 }
738
739 if r.DryRun().IPFamily() != tc.family {
740 t.Errorf("allocator returned wrong IP family")
741 }
742
743 expectUsed := func(t *testing.T, r *Range, expect int) {
744 t.Helper()
745 if u := r.Used(); u != expect {
746 t.Errorf("unexpected used count: got %d, wanted %d", u, expect)
747 }
748 }
749 expectUsed(t, r, baseUsed)
750
751 err = r.DryRun().Allocate(netutils.AddIPOffset(netutils.BigForIP(cidr.IP), 1))
752 if err != nil {
753 t.Fatalf("unexpected failure: %v", err)
754 }
755 expectUsed(t, r, baseUsed)
756
757 _, err = r.DryRun().AllocateNext()
758 if err != nil {
759 t.Fatalf("unexpected failure: %v", err)
760 }
761 expectUsed(t, r, baseUsed)
762
763 if err := r.DryRun().Release(cidr.IP); err != nil {
764 t.Fatalf("unexpected failure: %v", err)
765 }
766 expectUsed(t, r, baseUsed)
767 })
768 }
769 }
770
771 func Test_calculateRangeOffset(t *testing.T) {
772
773 tests := []struct {
774 name string
775 cidr string
776 want int
777 }{
778 {
779 name: "full mask IPv4",
780 cidr: "192.168.1.1/32",
781 want: 0,
782 },
783 {
784 name: "full mask IPv6",
785 cidr: "fd00::1/128",
786 want: 0,
787 },
788 {
789 name: "very small mask IPv4",
790 cidr: "192.168.1.1/30",
791 want: 0,
792 },
793 {
794 name: "very small mask IPv6",
795 cidr: "fd00::1/126",
796 want: 0,
797 },
798 {
799 name: "small mask IPv4",
800 cidr: "192.168.1.1/28",
801 want: 0,
802 },
803 {
804 name: "small mask IPv4",
805 cidr: "192.168.1.1/27",
806 want: 16,
807 },
808 {
809 name: "small mask IPv6",
810 cidr: "fd00::1/124",
811 want: 0,
812 },
813 {
814 name: "small mask IPv6",
815 cidr: "fd00::1/122",
816 want: 16,
817 },
818 {
819 name: "medium mask IPv4",
820 cidr: "192.168.1.1/22",
821 want: 64,
822 },
823 {
824 name: "medium mask IPv6",
825 cidr: "fd00::1/118",
826 want: 64,
827 },
828 {
829 name: "large mask IPv4",
830 cidr: "192.168.1.1/8",
831 want: 256,
832 },
833 {
834 name: "large mask IPv6",
835 cidr: "fd00::1/12",
836 want: 256,
837 },
838 }
839 for _, tt := range tests {
840 t.Run(tt.name, func(t *testing.T) {
841
842 _, cidr, err := netutils.ParseCIDRSloppy(tt.cidr)
843 if err != nil {
844 t.Fatalf("Unexpected error parsing CIDR %s: %v", tt.cidr, err)
845 }
846 if got := calculateRangeOffset(cidr); got != tt.want {
847 t.Errorf("DynamicRangeOffset() = %v, want %v", got, tt.want)
848 }
849 })
850 }
851 }
852
853
854
855
856 func BenchmarkAllocateNextIPv4Size1048574(b *testing.B) {
857 _, cidr, err := netutils.ParseCIDRSloppy("10.0.0.0/12")
858 if err != nil {
859 b.Fatal(err)
860 }
861 r, err := NewInMemory(cidr)
862 if err != nil {
863 b.Fatal(err)
864 }
865 for n := 0; n < b.N; n++ {
866 r.AllocateNext()
867 }
868 }
869
870
871
872
873
874 func BenchmarkAllocateNextIPv6Size65535(b *testing.B) {
875 _, cidr, err := netutils.ParseCIDRSloppy("fd00::/24")
876 if err != nil {
877 b.Fatal(err)
878 }
879 r, err := NewInMemory(cidr)
880 if err != nil {
881 b.Fatal(err)
882 }
883 for n := 0; n < b.N; n++ {
884 r.AllocateNext()
885 }
886 }
887
View as plain text