feature/conn25: return expired assignments to address pools
Make it possible to remove the least recently used expired address assignment from addrAssignments. Before checking out a new address from the IP pools, return a handful of expired addresses. Updates tailscale/corp#39975 Signed-off-by: Fran Bull <fran@tailscale.com>
This commit is contained in:
@@ -4,17 +4,20 @@
|
||||
package conn25
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"tailscale.com/tstest"
|
||||
)
|
||||
|
||||
func TestAssignmentsExpire(t *testing.T) {
|
||||
clock := tstest.NewClock(tstest.ClockOpts{Start: time.Now()})
|
||||
assignments := addrAssignments{clock: clock}
|
||||
as := addrs{
|
||||
as := &addrs{
|
||||
dst: netip.MustParseAddr("0.0.0.1"),
|
||||
magic: netip.MustParseAddr("0.0.0.2"),
|
||||
transit: netip.MustParseAddr("0.0.0.3"),
|
||||
@@ -64,3 +67,83 @@ func TestAssignmentsExpire(t *testing.T) {
|
||||
t.Fatalf("expected foundAs to expire after now")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPopExpired(t *testing.T) {
|
||||
clock := tstest.NewClock(tstest.ClockOpts{Start: time.Now()})
|
||||
assignments := addrAssignments{clock: clock}
|
||||
makeAndAddAddrs := func(n int) *addrs {
|
||||
t.Helper()
|
||||
as := &addrs{
|
||||
dst: netip.MustParseAddr(fmt.Sprintf("0.0.1.%d", n)),
|
||||
magic: netip.MustParseAddr(fmt.Sprintf("0.0.2.%d", n)),
|
||||
transit: netip.MustParseAddr(fmt.Sprintf("0.0.3.%d", n)),
|
||||
app: "a",
|
||||
domain: "example.com.",
|
||||
}
|
||||
err := assignments.insert(as)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return as
|
||||
}
|
||||
// cmp.Diff addrs ignoring expiresAt
|
||||
doDiff := func(want, got *addrs) string {
|
||||
t.Helper()
|
||||
return cmp.Diff(
|
||||
want,
|
||||
got,
|
||||
cmp.AllowUnexported(addrs{}),
|
||||
cmpopts.EquateComparable(netip.Addr{}),
|
||||
cmpopts.IgnoreFields(addrs{}, "expiresAt"),
|
||||
)
|
||||
}
|
||||
testAddrs := []*addrs{}
|
||||
for i := range 2 {
|
||||
testAddrs = append(testAddrs, makeAndAddAddrs(i+1))
|
||||
clock.Advance(1 * time.Second)
|
||||
}
|
||||
if len(assignments.byMagicIP) != 2 {
|
||||
t.Fatalf("test setup wrong")
|
||||
}
|
||||
|
||||
nn := assignments.popExpired(clock.Now())
|
||||
want := &addrs{} // invalid addr
|
||||
if diff := doDiff(want, nn); diff != "" {
|
||||
t.Fatalf("only expired addresses are removed: %s", diff)
|
||||
}
|
||||
if len(assignments.byMagicIP) != 2 {
|
||||
t.Fatalf("nothing should have been removed")
|
||||
}
|
||||
if nn.isValid() {
|
||||
t.Fatal("empty addrs should be invalid")
|
||||
}
|
||||
|
||||
clock.Advance(2 * defaultExpiry) // all addrs are now expired
|
||||
|
||||
want = testAddrs[0]
|
||||
nn = assignments.popExpired(clock.Now())
|
||||
if diff := doDiff(want, nn); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
if len(assignments.byMagicIP) != 1 {
|
||||
t.Fatalf("an assignment should have been removed")
|
||||
}
|
||||
|
||||
want = testAddrs[1]
|
||||
nn = assignments.popExpired(clock.Now())
|
||||
if diff := doDiff(want, nn); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
if len(assignments.byMagicIP) != 0 {
|
||||
t.Fatalf("an assignment should have been removed")
|
||||
}
|
||||
|
||||
want = &addrs{}
|
||||
nn = assignments.popExpired(clock.Now())
|
||||
if diff := doDiff(want, nn); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
if len(assignments.byMagicIP) != 0 {
|
||||
t.Fatalf("there should have been no change")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user