From b3c8ee231376bcaaea7a06d369f403c45a3733ba Mon Sep 17 00:00:00 2001 From: Francesco Cheinasso Date: Tue, 3 Dec 2024 15:38:39 +0100 Subject: [PATCH] fixup! fixup! feat: ipam timestamp --- pkg/ipam/core/ipam.go | 34 ++++++++++++++++++++++++++++++++-- pkg/ipam/core/node.go | 22 +++++++++++----------- pkg/ipam/ips.go | 2 +- pkg/ipam/sync_test.go | 25 +++++++++++++++++++++---- 4 files changed, 65 insertions(+), 18 deletions(-) diff --git a/pkg/ipam/core/ipam.go b/pkg/ipam/core/ipam.go index 75e6ad27b4..655c7ff906 100644 --- a/pkg/ipam/core/ipam.go +++ b/pkg/ipam/core/ipam.go @@ -164,9 +164,9 @@ func (ipam *Ipam) ListIPs(prefix netip.Prefix) ([]netip.Addr, error) { return nil, nil } -// IsAllocatedIP checks if the IP address is allocated from the given prefix. +// IPIsAlocated checks if the IP address is allocated from the given prefix. // It returns true if the IP address is allocated, false otherwise. -func (ipam *Ipam) IsAllocatedIP(prefix netip.Prefix, addr netip.Addr) (bool, error) { +func (ipam *Ipam) IPIsAlocated(prefix netip.Prefix, addr netip.Addr) (bool, error) { node, err := ipam.search(prefix) if err != nil { return false, err @@ -220,3 +220,33 @@ func checkRoots(roots []netip.Prefix) error { } return nil } + +// NetworkSetLastUpdateTimestamp sets the last update time of the network with the given prefix. +// This function is for testing purposes only. +func (ipam *Ipam) NetworkSetLastUpdateTimestamp(prefix netip.Prefix, lastUpdateTimestamp time.Time) error { + node, err := ipam.search(prefix) + if err != nil { + return err + } + if node == nil { + return fmt.Errorf("prefix %s not found", prefix) + } + node.lastUpdateTimestamp = lastUpdateTimestamp + return nil +} + +// IPSetCreationTimestamp sets the creation timestamp of the IP address with the given address. +// This function is for testing purposes only. +func (ipam *Ipam) IPSetCreationTimestamp(addr netip.Addr, prefix netip.Prefix, creationTimestamp time.Time) error { + node, err := ipam.search(prefix) + if err != nil { + return err + } + for i := range node.ips { + if node.ips[i].addr.Compare(addr) == 0 { + node.ips[i].creationTimestamp = creationTimestamp + return nil + } + } + return nil +} diff --git a/pkg/ipam/core/node.go b/pkg/ipam/core/node.go index a98aa60e12..4984ea7a20 100644 --- a/pkg/ipam/core/node.go +++ b/pkg/ipam/core/node.go @@ -32,7 +32,7 @@ type nodeIP struct { // node represents a node in the binary tree. type node struct { - lastUpdate time.Time + lastUpdateTimestamp time.Time prefix netip.Prefix acquired bool @@ -53,7 +53,7 @@ const ( ) func newNode(prefix netip.Prefix) node { - return node{prefix: prefix, lastUpdate: time.Now()} + return node{prefix: prefix, lastUpdateTimestamp: time.Now()} } func allocateNetwork(size int, node *node) *netip.Prefix { @@ -63,7 +63,7 @@ func allocateNetwork(size int, node *node) *netip.Prefix { if node.prefix.Bits() == size { if !node.isSplitted() { node.acquired = true - node.lastUpdate = time.Now() + node.lastUpdateTimestamp = time.Now() return &node.prefix } return nil @@ -88,7 +88,7 @@ func allocateNetworkWithPrefix(prefix netip.Prefix, node *node) *netip.Prefix { if node.prefix.Addr().Compare(prefix.Addr()) == 0 && node.prefix.Bits() == prefix.Bits() { if !node.acquired && node.left == nil && node.right == nil { node.acquired = true - node.lastUpdate = time.Now() + node.lastUpdateTimestamp = time.Now() return &node.prefix } return nil @@ -115,10 +115,10 @@ func networkRelease(prefix netip.Prefix, node *node, gracePeriod time.Duration) return nil } - if node.prefix.Addr().Compare(prefix.Addr()) == 0 && node.prefix.Bits() == prefix.Bits() && node.lastUpdate.Add(gracePeriod).Before(time.Now()) { + if node.prefix.Addr().Compare(prefix.Addr()) == 0 && node.prefix.Bits() == prefix.Bits() && node.lastUpdateTimestamp.Add(gracePeriod).Before(time.Now()) { if node.acquired { node.acquired = false - node.lastUpdate = time.Now() + node.lastUpdateTimestamp = time.Now() return &node.prefix } return nil @@ -191,7 +191,7 @@ func (n *node) ipAcquire() *netip.Addr { if !n.isAllocatedIP(addr) { n.ips = append(n.ips, nodeIP{addr: addr, creationTimestamp: time.Now()}) n.lastip = addr - n.lastUpdate = time.Now() + n.lastUpdateTimestamp = time.Now() return &addr } addr = addr.Next() @@ -215,7 +215,7 @@ func (n *node) allocateIPWithAddr(addr netip.Addr) *netip.Addr { } n.ips = append(n.ips, nodeIP{addr: addr, creationTimestamp: time.Now()}) - n.lastUpdate = time.Now() + n.lastUpdateTimestamp = time.Now() return &n.ips[len(n.ips)-1].addr } @@ -231,7 +231,7 @@ func (n *node) ipRelease(ip netip.Addr, gracePeriod time.Duration) *netip.Addr { } if nodeIP.addr.Compare(ip) == 0 { n.ips = append(n.ips[:i], n.ips[i+1:]...) - n.lastUpdate = time.Now() + n.lastUpdateTimestamp = time.Now() return &nodeIP.addr } } @@ -270,7 +270,7 @@ func (n *node) merge(gracePeriod time.Duration) { if n.left == nil || n.right == nil { return } - if !n.left.lastUpdate.Add(gracePeriod).Before(time.Now()) || !n.right.lastUpdate.Add(gracePeriod).Before(time.Now()) { + if !n.left.lastUpdateTimestamp.Add(gracePeriod).Before(time.Now()) || !n.right.lastUpdateTimestamp.Add(gracePeriod).Before(time.Now()) { return // grace period not expired } if !n.left.isLeaf() || !n.right.isLeaf() { @@ -282,7 +282,7 @@ func (n *node) merge(gracePeriod time.Duration) { n.left = nil n.right = nil - n.lastUpdate = time.Now() + n.lastUpdateTimestamp = time.Now() } func (n *node) insert(nd nodeDirection, prefix netip.Prefix) { diff --git a/pkg/ipam/ips.go b/pkg/ipam/ips.go index 317b4cea71..228e0cf80c 100644 --- a/pkg/ipam/ips.go +++ b/pkg/ipam/ips.go @@ -81,7 +81,7 @@ func (lipam *LiqoIPAM) ipRelease(addr netip.Addr, prefix netip.Prefix, gracePeri // isIPAvailable checks if an IP is available. func (lipam *LiqoIPAM) isIPAvailable(addr netip.Addr, prefix netip.Prefix) (bool, error) { - allocated, err := lipam.IpamCore.IsAllocatedIP(prefix, addr) + allocated, err := lipam.IpamCore.IPIsAlocated(prefix, addr) return !allocated, err } diff --git a/pkg/ipam/sync_test.go b/pkg/ipam/sync_test.go index c4f5e4d0c2..4be589c451 100644 --- a/pkg/ipam/sync_test.go +++ b/pkg/ipam/sync_test.go @@ -30,7 +30,7 @@ import ( var _ = Describe("Sync routine tests", func() { const ( - syncGracePeriod = time.Millisecond * 100 + syncGracePeriod = time.Second * 5 testNamespace = "test" ) @@ -109,8 +109,14 @@ var _ = Describe("Sync routine tests", func() { Expect(fakeIpamServer.networkIsAvailable(netip.MustParsePrefix("10.4.0.0/16"))).To(Equal(false)) Expect(fakeIpamServer.networkIsAvailable(netip.MustParsePrefix("10.5.0.0/16"))).To(Equal(false)) - time.Sleep(syncGracePeriod) - // Run sync + newLastUpdate := time.Now().Add(-syncGracePeriod) + Expect(fakeIpamServer.IpamCore.NetworkSetLastUpdateTimestamp(netip.MustParsePrefix("10.0.0.0/16"), newLastUpdate)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.NetworkSetLastUpdateTimestamp(netip.MustParsePrefix("10.1.0.0/16"), newLastUpdate)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.NetworkSetLastUpdateTimestamp(netip.MustParsePrefix("10.2.0.0/16"), newLastUpdate)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.NetworkSetLastUpdateTimestamp(netip.MustParsePrefix("10.3.0.0/16"), newLastUpdate)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.NetworkSetLastUpdateTimestamp(netip.MustParsePrefix("10.4.0.0/16"), newLastUpdate)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.NetworkSetLastUpdateTimestamp(netip.MustParsePrefix("10.5.0.0/16"), newLastUpdate)).Should(Succeed()) + Expect(fakeIpamServer.syncNetworks(ctx)).To(Succeed()) // Check the cache after grace period @@ -170,7 +176,18 @@ var _ = Describe("Sync routine tests", func() { Expect(fakeIpamServer.isIPAvailable(netip.MustParseAddr("10.0.0.3"), netip.MustParsePrefix("10.0.0.0/24"))).To(Equal(false)) Expect(fakeIpamServer.isIPAvailable(netip.MustParseAddr("10.0.0.4"), netip.MustParsePrefix("10.0.0.0/24"))).To(Equal(false)) - time.Sleep(syncGracePeriod) + newCreationTimestamp := time.Now().Add(-syncGracePeriod) + Expect(fakeIpamServer.IpamCore.IPSetCreationTimestamp( + netip.MustParseAddr("10.0.0.0"), netip.MustParsePrefix("10.0.0.0/24"), newCreationTimestamp)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.IPSetCreationTimestamp( + netip.MustParseAddr("10.0.0.1"), netip.MustParsePrefix("10.0.0.0/24"), newCreationTimestamp)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.IPSetCreationTimestamp( + netip.MustParseAddr("10.0.0.2"), netip.MustParsePrefix("10.0.0.0/24"), newCreationTimestamp)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.IPSetCreationTimestamp( + netip.MustParseAddr("10.0.0.3"), netip.MustParsePrefix("10.0.0.0/24"), newCreationTimestamp)).Should(Succeed()) + Expect(fakeIpamServer.IpamCore.IPSetCreationTimestamp( + netip.MustParseAddr("10.0.0.4"), netip.MustParsePrefix("10.0.0.0/24"), newCreationTimestamp)).Should(Succeed()) + // Run sync Expect(fakeIpamServer.syncIPs(ctx)).To(Succeed())