diff --git a/pkg/ipam/core/core_suite_test.go b/pkg/ipam/core/core_suite_test.go new file mode 100644 index 0000000000..75ba3b46d0 --- /dev/null +++ b/pkg/ipam/core/core_suite_test.go @@ -0,0 +1,27 @@ +// Copyright 2019-2024 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipamcore_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestCore(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Core Suite") +} diff --git a/pkg/ipam/core/coverage/coverage.html b/pkg/ipam/core/coverage/coverage.html new file mode 100644 index 0000000000..0fd30ad780 --- /dev/null +++ b/pkg/ipam/core/coverage/coverage.html @@ -0,0 +1,866 @@ + + + + + + core: Go Coverage Report + + + +
+ +
+ not tracked + + not covered + covered + +
+
+
+ + + + + + + +
+ + + diff --git a/pkg/ipam/core/ipam.go b/pkg/ipam/core/ipam.go index e2adb94203..8e75201054 100644 --- a/pkg/ipam/core/ipam.go +++ b/pkg/ipam/core/ipam.go @@ -26,19 +26,14 @@ type Ipam struct { } // NewIpam creates a new IPAM instance. -func NewIpam(pools []string) (*Ipam, error) { - ipamRootsPrefixes := make([]netip.Prefix, len(pools)) - for i, root := range pools { - ipamRootsPrefixes[i] = netip.MustParsePrefix(root) - } - - if err := checkRoots(ipamRootsPrefixes); err != nil { +func NewIpam(pools []netip.Prefix) (*Ipam, error) { + if err := checkRoots(pools); err != nil { return nil, err } ipamRoots := make([]node, len(pools)) - for i := range ipamRootsPrefixes { - ipamRoots[i] = newNode(ipamRootsPrefixes[i]) + for i := range pools { + ipamRoots[i] = newNode(pools[i]) } ipam := &Ipam{ diff --git a/pkg/ipam/core/ipam_test.go b/pkg/ipam/core/ipam_test.go new file mode 100644 index 0000000000..5d98926cfb --- /dev/null +++ b/pkg/ipam/core/ipam_test.go @@ -0,0 +1,459 @@ +// Copyright 2019-2024 The Liqo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ipamcore + +import ( + "fmt" + "math" + "net/netip" + "os" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("Ipam", func() { + var ( + err error + ipam *Ipam + validPools = []netip.Prefix{ + netip.MustParsePrefix("10.0.0.0/8"), + netip.MustParsePrefix("192.168.0.0/16"), + netip.MustParsePrefix("172.16.0.0/12"), + } + invalidPools = []netip.Prefix{ + netip.MustParsePrefix("10.0.1.0/8"), + netip.MustParsePrefix("192.168.1.0/16"), + netip.MustParsePrefix("172.16.0.5/12"), + } + prefixOutOfPools = netip.MustParsePrefix("11.0.0.0/8") + ) + + Context("Ipam Creation", func() { + When("Using valid pools", func() { + It("should create an Ipam object", func() { + ipam, err = NewIpam(validPools) + Expect(err).NotTo(HaveOccurred()) + Expect(ipam).NotTo(BeNil()) + }) + }) + When("Using invalid pools", func() { + It("should return an error", func() { + _, err := NewIpam(invalidPools) + Expect(err).To(HaveOccurred()) + }) + }) + }) + + Context("Ipam Utilities", func() { + When("checking if a prefix is child of another one", func() { + It("should return true", func() { + parentPrefix := netip.MustParsePrefix("10.0.0.0/16") + childPrefixes := []netip.Prefix{ + netip.MustParsePrefix("10.0.0.0/24"), + netip.MustParsePrefix("10.0.1.0/24"), + netip.MustParsePrefix("10.0.1.6/24"), + netip.MustParsePrefix("10.0.0.0/16"), + } + + for _, childPrefix := range childPrefixes { + Expect(isPrefixChildOf(parentPrefix, childPrefix)).To(BeTrue()) + } + }) + It("should return false", func() { + parentPrefix := netip.MustParsePrefix("10.0.0.0/16") + childPrefixes := []netip.Prefix{ + netip.MustParsePrefix("0.0.0.0/0"), + netip.MustParsePrefix("10.0.0.0/15"), + netip.MustParsePrefix("10.0.0.0/8"), + netip.MustParsePrefix("10.0.1.0/8"), + } + + for _, childPrefix := range childPrefixes { + Expect(isPrefixChildOf(parentPrefix, childPrefix)).To(BeFalse()) + } + }) + }) + }) + + Context("Ipam networks", func() { + BeforeEach(func() { + var err error + ipam, err = NewIpam(validPools) + Expect(err).NotTo(HaveOccurred()) + }) + + When("creating an Ipam object", func() { + It("should succeed", func() { + Expect(ipam).NotTo(BeNil()) + }) + }) + + When("listing networks", func() { + It("should succeed", func() { + networks := ipam.ListNetworks() + Expect(networks).Should(HaveLen(0)) + + acquiredNetworks := []netip.Prefix{} + acquiredNetworks = append(acquiredNetworks, *ipam.NetworkAcquire(24)) + acquiredNetworks = append(acquiredNetworks, *ipam.NetworkAcquire(25)) + acquiredNetworks = append(acquiredNetworks, *ipam.NetworkAcquire(26)) + acquiredNetworks = append(acquiredNetworks, *ipam.NetworkAcquire(27)) + acquiredNetworks = append(acquiredNetworks, *ipam.NetworkAcquire(28)) + + networks = ipam.ListNetworks() + Expect(networks).Should(HaveLen(5)) + for i := range acquiredNetworks { + Expect(networks).Should(ContainElement(acquiredNetworks[i])) + } + }) + }) + + When("acquiring networks", func() { + It("should succeed", func() { + network := ipam.NetworkAcquire(24) + Expect(network).ShouldNot(BeNil()) + Expect(ipam.NetworkIsAvailable(*network)).To(BeFalse()) + }) + It("should not succeed", func() { + network := ipam.NetworkAcquire(4) + Expect(network).Should(BeNil()) + }) + }) + + When("releasing networks", func() { + It("should succeed", func() { + network := ipam.NetworkAcquire(16) + Expect(network).ShouldNot(BeNil()) + Expect(ipam.NetworkIsAvailable(*network)).To(BeFalse()) + Expect(ipam.NetworkRelease(*network, 0).String()).To(Equal(network.String())) + Expect(ipam.NetworkIsAvailable(*network)).To(BeTrue()) + }) + It("should succeed (with grace period)", func() { + network := ipam.NetworkAcquire(16) + Expect(network).ShouldNot(BeNil()) + Expect(ipam.NetworkIsAvailable(*network)).To(BeFalse()) + Expect(ipam.NetworkRelease(*network, time.Second*0).String()).To(Equal(network.String())) + Expect(ipam.NetworkIsAvailable(*network)).To(BeTrue()) + }) + + It("should not succeed", func() { + networks := []netip.Prefix{ + netip.MustParsePrefix("10.0.1.0/24"), + netip.MustParsePrefix("10.0.2.0/24"), + netip.MustParsePrefix("10.1.0.0/16"), + netip.MustParsePrefix("10.2.0.0/16"), + netip.MustParsePrefix("10.3.0.0/30"), + netip.MustParsePrefix("10.4.0.0/27"), + } + for _, network := range networks { + Expect(ipam.NetworkIsAvailable(network)).To(BeTrue()) + Expect(ipam.NetworkRelease(network, 0)).To(BeNil()) + Expect(ipam.NetworkRelease(network, time.Second*5)).To(BeNil()) + } + }) + }) + + When("acquiring networks with prefix", func() { + It("should succeed", func() { + networks := []netip.Prefix{ + netip.MustParsePrefix("10.0.1.0/24"), + netip.MustParsePrefix("10.0.2.0/24"), + netip.MustParsePrefix("10.1.0.0/16"), + netip.MustParsePrefix("10.2.0.0/16"), + netip.MustParsePrefix("10.3.8.0/21"), + netip.MustParsePrefix("10.4.16.0/20"), + netip.MustParsePrefix("10.128.0.0/20"), + netip.MustParsePrefix("10.130.64.0/18"), + netip.MustParsePrefix("10.4.2.0/27"), + netip.MustParsePrefix("10.3.0.0/30"), + netip.MustParsePrefix("10.4.0.0/27"), + netip.MustParsePrefix("10.5.0.0/16"), + netip.MustParsePrefix("10.4.2.128/25"), + netip.MustParsePrefix("10.4.3.0/27"), + netip.MustParsePrefix("10.3.0.24/29"), + } + + for _, network := range networks { + Expect(ipam.NetworkIsAvailable(network)).To(BeTrue()) + } + + for _, network := range networks { + networkAcquired := ipam.NetworkAcquireWithPrefix(network) + Expect(networkAcquired).NotTo(BeNil()) + Expect(networkAcquired.String()).To(Equal(network.String())) + } + + for _, network := range networks { + Expect(ipam.NetworkIsAvailable(network)).To(BeFalse()) + } + + for _, network := range networks { + Expect(ipam.NetworkRelease(network, 0).String()).To(Equal(network.String())) + } + + for _, network := range networks { + Expect(ipam.NetworkIsAvailable(network)).To(BeTrue()) + } + }) + + It("should not succeed", func() { + networks := []netip.Prefix{ + netip.MustParsePrefix("10.0.1.0/8"), + netip.MustParsePrefix("11.0.2.0/24"), + netip.MustParsePrefix("11.1.0.0/16"), + netip.MustParsePrefix("11.2.0.0/16"), + netip.MustParsePrefix("12.0.0.0/8"), + netip.MustParsePrefix("13.4.0.0/8"), + } + for _, network := range networks { + Expect(ipam.NetworkAcquireWithPrefix(network)).To(BeNil()) + } + + }) + }) + + When("acquiring a network", func() { + BeforeEach(func() { + prefix := netip.MustParsePrefix("10.0.0.0/16") + Expect(ipam.NetworkAcquireWithPrefix(prefix)).NotTo(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.5.0.0/16") + Expect(ipam.NetworkAcquireWithPrefix(prefix)).NotTo(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + }) + It("parent networks should not be available", func() { + prefix := netip.MustParsePrefix("10.0.0.0/14") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.0.0.0/15") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.4.0.0/15") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.4.0.0/14") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.0.0.0/13") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + }) + + It("child networks should not be available", func() { + prefix := netip.MustParsePrefix("10.0.0.0/17") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.0.0.0/18") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("10.5.0.0/20") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("11.0.0.0/16") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + + prefix = netip.MustParsePrefix("0.0.0.0/0") + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + Expect(ipam.NetworkAcquireWithPrefix(prefix)).To(BeNil()) + Expect(ipam.NetworkIsAvailable(prefix)).To(BeFalse()) + }) + }) + + When("generating graphviz", func() { + BeforeEach(func() { + sizes := []int{21, 26, 27, 22, 30, 25, 28, 24, 16, 10, 29} + for _, size := range sizes { + for i := 0; i < 3; i++ { + network := ipam.NetworkAcquire(size) + Expect(network).ShouldNot(BeNil()) + } + } + }) + It("it should succeed", func() { + Expect(ipam.ToGraphviz()).Should(Succeed()) + }) + AfterEach(func() { + _, err := os.Stat(graphvizFolder) + Expect(err).ShouldNot(HaveOccurred()) + Expect(os.RemoveAll(graphvizFolder)).ShouldNot(HaveOccurred()) + }) + }) + }) + + Context("Ipam IPs", func() { + var ( + availableIPs = 8 + prefixAcquired = netip.MustParsePrefix(fmt.Sprintf("10.0.0.0/%d", int(32-math.Sqrt(8)))) + prefixNotAcquired = netip.MustParsePrefix(fmt.Sprintf("10.1.0.0/%d", int(32-math.Sqrt(8)))) + ) + BeforeEach(func() { + var err error + ipam, err = NewIpam(validPools) + Expect(err).NotTo(HaveOccurred()) + + Expect(ipam.NetworkIsAvailable(prefixAcquired)).To(BeTrue()) + Expect(ipam.NetworkAcquireWithPrefix(prefixAcquired)).NotTo(BeNil()) + Expect(ipam.NetworkIsAvailable(prefixAcquired)).To(BeFalse()) + }) + + When("acquiring an IP from not existing network", func() { + It("should not succeed (out of pools)", func() { + addr, err := ipam.IPAcquire(prefixOutOfPools) + Expect(err).To(HaveOccurred()) + Expect(addr).To(BeNil()) + }) + It("should not succeed (prefix not acquired)", func() { + addr, err := ipam.IPAcquire(prefixNotAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).To(BeNil()) + }) + }) + When("acquiring an IP from existing network", func() { + It("should succeed", func() { + addr, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).NotTo(BeNil()) + Expect(ipam.IPIsAllocated(prefixAcquired, *addr)).To(BeTrue()) + }) + + It("should succeed, with specific IP", func() { + addr, err := ipam.IPAcquireWithAddr(prefixAcquired, prefixAcquired.Addr()) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).NotTo(BeNil()) + Expect(addr.String()).To(Equal(prefixAcquired.Addr().String())) + Expect(ipam.IPIsAllocated(prefixAcquired, *addr)).To(BeTrue()) + }) + + It("should not overflow available IPs)", func() { + for i := 0; i < availableIPs; i++ { + addr, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).NotTo(BeNil()) + Expect(ipam.IPIsAllocated(prefixAcquired, *addr)).To(BeTrue()) + } + for i := 0; i < availableIPs; i++ { + addr, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).To(BeNil()) + } + }) + + It("should not overflow available IPs, with specific IPs)", func() { + addr := prefixAcquired.Addr() + for i := 0; i < availableIPs; i++ { + result, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(result).NotTo(BeNil()) + Expect(ipam.IPIsAllocated(prefixAcquired, *result)).To(BeTrue()) + addr = addr.Next() + } + for i := 0; i < availableIPs; i++ { + result, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeNil()) + addr = addr.Next() + } + }) + + It("should succeed (after an ip has been released)", func() { + addrs := []netip.Addr{} + for i := 0; i < availableIPs; i++ { + addr, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).NotTo(BeNil()) + addrs = append(addrs, *addr) + } + + addr, err := ipam.IPRelease(prefixAcquired, addrs[availableIPs/2], 0) + Expect(err).To(BeNil()) + Expect(addr).NotTo(BeNil()) + Expect(addr.String()).To(Equal(addrs[availableIPs/2].String())) + Expect(ipam.IPIsAllocated(prefixAcquired, *addr)).To(BeFalse()) + + addr, err = ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).NotTo(BeNil()) + Expect(ipam.IPIsAllocated(prefixAcquired, *addr)).To(BeTrue()) + }) + }) + When("releasing an IP from not existing network", func() { + It("should not succeed", func() { + addr := prefixAcquired.Addr() + for i := 0; i < availableIPs*2; i++ { + result, err := ipam.IPRelease(prefixNotAcquired, addr, 0) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeNil()) + addr = addr.Next() + } + }) + It("should not succeed (out of pools)", func() { + addr := prefixAcquired.Addr() + for i := 0; i < availableIPs*2; i++ { + result, err := ipam.IPRelease(prefixOutOfPools, addr, 0) + Expect(err).To(HaveOccurred()) + Expect(result).To(BeNil()) + addr = addr.Next() + } + }) + }) + When("releasing an IP from existing network", func() { + It("should not succeed", func() { + addr := prefixAcquired.Addr() + for i := 0; i < availableIPs*2; i++ { + result, err := ipam.IPRelease(prefixAcquired, addr, 0) + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(BeNil()) + addr = addr.Next() + } + }) + It("should succeed", func() { + addrs := []netip.Addr{} + for i := 0; i < availableIPs; i++ { + addr, err := ipam.IPAcquire(prefixAcquired) + Expect(err).NotTo(HaveOccurred()) + Expect(addr).NotTo(BeNil()) + addrs = append(addrs, *addr) + } + for i := range addrs { + addr, err := ipam.IPRelease(prefixAcquired, addrs[i], 0) + Expect(err).To(BeNil()) + Expect(addr).NotTo(BeNil()) + Expect(addr.String()).To(Equal(addrs[i].String())) + } + }) + + }) + }) +}) diff --git a/pkg/ipam/core/node.go b/pkg/ipam/core/node.go index 4b1058eee9..f9a55e67da 100644 --- a/pkg/ipam/core/node.go +++ b/pkg/ipam/core/node.go @@ -82,7 +82,7 @@ func allocateNetwork(size int, node *node) *netip.Prefix { } func allocateNetworkWithPrefix(prefix netip.Prefix, node *node) *netip.Prefix { - if node.acquired || !node.prefix.Overlaps(prefix) { + if node.acquired || !isPrefixChildOf(node.prefix, prefix) { return nil } if node.prefix.Addr().Compare(prefix.Addr()) == 0 && node.prefix.Bits() == prefix.Bits() { @@ -124,11 +124,10 @@ func networkRelease(prefix netip.Prefix, node *node, gracePeriod time.Duration) } return nil } - - if node.left != nil && node.left.prefix.Overlaps(prefix) { + if node.left != nil && isPrefixChildOf(node.left.prefix, prefix) { result = networkRelease(prefix, node.left, gracePeriod) } - if node.right != nil && node.right.prefix.Overlaps(prefix) { + if node.right != nil && isPrefixChildOf(node.right.prefix, prefix) { result = networkRelease(prefix, node.right, gracePeriod) } @@ -138,10 +137,10 @@ func networkRelease(prefix netip.Prefix, node *node, gracePeriod time.Duration) func networkIsAvailable(prefix netip.Prefix, node *node) bool { if node.prefix.Addr().Compare(prefix.Addr()) == 0 && node.prefix.Bits() == prefix.Bits() { - if node.left != nil && node.left.left.isSplitted() { + if node.left != nil && (node.left.isSplitted() || node.left.acquired) { return false } - if node.right != nil && node.right.isSplitted() { + if node.right != nil && (node.right.isSplitted() || node.right.acquired) { return false } @@ -153,10 +152,10 @@ func networkIsAvailable(prefix netip.Prefix, node *node) bool { return true } - if node.left != nil && node.left.prefix.Overlaps(prefix) && !node.left.acquired { + if node.left != nil && isPrefixChildOf(node.left.prefix, prefix) && !node.left.acquired { return networkIsAvailable(prefix, node.left) } - if node.right != nil && node.right.prefix.Overlaps(prefix) && !node.right.acquired { + if node.right != nil && isPrefixChildOf(node.right.prefix, prefix) && !node.right.acquired { return networkIsAvailable(prefix, node.right) } @@ -275,10 +274,10 @@ func search(prefix netip.Prefix, node *node) *node { return node } - if node.left != nil && node.left.prefix.Overlaps(prefix) { + if node.left != nil && isPrefixChildOf(node.left.prefix, prefix) { return search(prefix, node.left) } - if node.right != nil && node.right.prefix.Overlaps(prefix) { + if node.right != nil && isPrefixChildOf(node.right.prefix, prefix) { return search(prefix, node.right) } diff --git a/pkg/ipam/initialize_test.go b/pkg/ipam/initialize_test.go index 75d19a63d6..8baed358f9 100644 --- a/pkg/ipam/initialize_test.go +++ b/pkg/ipam/initialize_test.go @@ -64,7 +64,11 @@ var _ = Describe("Initialize routine tests", func() { testutil.FakeNetwork("net6", testNamespace, "172.16.1.0/24", nil), ).Build() - ipamCore, err := ipamcore.NewIpam([]string{"10.0.0.0/8", "192.168.0.0/16", "172.16.1.0/24"}) + ipamCore, err := ipamcore.NewIpam([]netip.Prefix{ + netip.MustParsePrefix("10.0.0.0/8"), + netip.MustParsePrefix("192.168.0.0/16"), + netip.MustParsePrefix("172.16.1.0/24"), + }) Expect(err).To(BeNil()) // Init ipam server diff --git a/pkg/ipam/ipam.go b/pkg/ipam/ipam.go index 7c0e71f6d2..93bea650d6 100644 --- a/pkg/ipam/ipam.go +++ b/pkg/ipam/ipam.go @@ -56,7 +56,16 @@ func New(ctx context.Context, cl client.Client, roots []string, opts *ServerOpti hs := health.NewServer() hs.SetServingStatus(IPAM_ServiceDesc.ServiceName, grpc_health_v1.HealthCheckResponse_NOT_SERVING) - ipam, err := ipamcore.NewIpam(roots) + prefixRoots := make([]netip.Prefix, len(roots)) + for i, r := range roots { + p, err := netip.ParsePrefix(r) + if err != nil { + return nil, fmt.Errorf("failed to parse prefix %q: %w", r, err) + } + prefixRoots[i] = p + } + + ipam, err := ipamcore.NewIpam(prefixRoots) if err != nil { return nil, err } diff --git a/pkg/ipam/sync_test.go b/pkg/ipam/sync_test.go index 4c601c9238..1f36e20cb7 100644 --- a/pkg/ipam/sync_test.go +++ b/pkg/ipam/sync_test.go @@ -72,7 +72,7 @@ var _ = Describe("Sync routine tests", func() { testutil.FakeNetwork("net4", testNamespace, "10.4.0.0/16", nil), ).Build() - ipamCore, err := ipamcore.NewIpam([]string{"10.0.0.0/8"}) + ipamCore, err := ipamcore.NewIpam([]netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")}) Expect(err).To(BeNil()) // Populate the cache @@ -156,7 +156,7 @@ var _ = Describe("Sync routine tests", func() { testutil.FakeIP("ip3", testNamespace, "10.0.0.2", "10.0.0.0/24", nil, nil, false), ).Build() - ipamCore, err := ipamcore.NewIpam([]string{"10.0.0.0/8"}) + ipamCore, err := ipamcore.NewIpam([]netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")}) Expect(err).To(BeNil()) // Populate the cache