mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-13 14:43:19 +00:00
net/art: allow non-pointers as values
Values are still turned into pointers internally to maintain the invariants of strideTable, but from the user's perspective it's now possible to tbl.Insert(pfx, true) rather than tbl.Insert(pfx, ptr.To(true)). Updates #7781 Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:

committed by
Dave Anderson

parent
bc0eb6b914
commit
e92adfe5e4
@@ -12,8 +12,6 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
func TestRegression(t *testing.T) {
|
||||
@@ -30,17 +28,16 @@ func TestRegression(t *testing.T) {
|
||||
slow := slowPrefixTable[int]{}
|
||||
p := netip.MustParsePrefix
|
||||
|
||||
v := ptr.To(1)
|
||||
tbl.Insert(p("226.205.197.0/24"), v)
|
||||
slow.insert(p("226.205.197.0/24"), v)
|
||||
v = ptr.To(2)
|
||||
tbl.Insert(p("226.205.0.0/16"), v)
|
||||
slow.insert(p("226.205.0.0/16"), v)
|
||||
tbl.Insert(p("226.205.197.0/24"), 1)
|
||||
slow.insert(p("226.205.197.0/24"), 1)
|
||||
tbl.Insert(p("226.205.0.0/16"), 2)
|
||||
slow.insert(p("226.205.0.0/16"), 2)
|
||||
|
||||
probe := netip.MustParseAddr("226.205.121.152")
|
||||
got, want := tbl.Get(probe), slow.get(probe)
|
||||
if got != want {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
got, gotOK := tbl.Get(probe)
|
||||
want, wantOK := slow.get(probe)
|
||||
if !getsEqual(got, gotOK, want, wantOK) {
|
||||
t.Fatalf("got (%v, %v), want (%v, %v)", got, gotOK, want, wantOK)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -49,18 +46,18 @@ func TestRegression(t *testing.T) {
|
||||
// within computePrefixSplit.
|
||||
t1, t2 := &Table[int]{}, &Table[int]{}
|
||||
p := netip.MustParsePrefix
|
||||
v1, v2 := ptr.To(1), ptr.To(2)
|
||||
|
||||
t1.Insert(p("136.20.0.0/16"), v1)
|
||||
t1.Insert(p("136.20.201.62/32"), v2)
|
||||
t1.Insert(p("136.20.0.0/16"), 1)
|
||||
t1.Insert(p("136.20.201.62/32"), 2)
|
||||
|
||||
t2.Insert(p("136.20.201.62/32"), v2)
|
||||
t2.Insert(p("136.20.0.0/16"), v1)
|
||||
t2.Insert(p("136.20.201.62/32"), 2)
|
||||
t2.Insert(p("136.20.0.0/16"), 1)
|
||||
|
||||
a := netip.MustParseAddr("136.20.54.139")
|
||||
got, want := t2.Get(a), t1.Get(a)
|
||||
if got != want {
|
||||
t.Errorf("Get(%q) is insertion order dependent (t1=%v, t2=%v)", a, want, got)
|
||||
got1, ok1 := t1.Get(a)
|
||||
got2, ok2 := t2.Get(a)
|
||||
if !getsEqual(got1, ok1, got2, ok2) {
|
||||
t.Errorf("Get(%q) is insertion order dependent: t1=(%v, %v), t2=(%v, %v)", a, got1, ok1, got2, ok2)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -99,7 +96,7 @@ func TestInsert(t *testing.T) {
|
||||
p := netip.MustParsePrefix
|
||||
|
||||
// Create a new leaf strideTable, with compressed path
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", -1},
|
||||
@@ -114,7 +111,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert into previous leaf, no tree changes
|
||||
tbl.Insert(p("192.168.0.2/32"), ptr.To(2))
|
||||
tbl.Insert(p("192.168.0.2/32"), 2)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -129,7 +126,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert into previous leaf, unaligned prefix covering the /32s
|
||||
tbl.Insert(p("192.168.0.0/26"), ptr.To(7))
|
||||
tbl.Insert(p("192.168.0.0/26"), 7)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -144,7 +141,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Create a different leaf elsewhere
|
||||
tbl.Insert(p("10.0.0.0/27"), ptr.To(3))
|
||||
tbl.Insert(p("10.0.0.0/27"), 3)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -159,7 +156,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert that creates a new intermediate table and a new child
|
||||
tbl.Insert(p("192.168.1.1/32"), ptr.To(4))
|
||||
tbl.Insert(p("192.168.1.1/32"), 4)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -174,7 +171,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert that creates a new intermediate table but no new child
|
||||
tbl.Insert(p("192.170.0.0/16"), ptr.To(5))
|
||||
tbl.Insert(p("192.170.0.0/16"), 5)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -190,7 +187,7 @@ func TestInsert(t *testing.T) {
|
||||
|
||||
// New leaf in a different subtree, so the next insert can test a
|
||||
// variant of decompression.
|
||||
tbl.Insert(p("192.180.0.1/32"), ptr.To(8))
|
||||
tbl.Insert(p("192.180.0.1/32"), 8)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -206,7 +203,7 @@ func TestInsert(t *testing.T) {
|
||||
|
||||
// Insert that creates a new intermediate table but no new child,
|
||||
// with an unaligned intermediate
|
||||
tbl.Insert(p("192.180.0.0/21"), ptr.To(9))
|
||||
tbl.Insert(p("192.180.0.0/21"), 9)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -221,7 +218,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert a default route, those have their own codepath.
|
||||
tbl.Insert(p("0.0.0.0/0"), ptr.To(6))
|
||||
tbl.Insert(p("0.0.0.0/0"), 6)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -238,7 +235,7 @@ func TestInsert(t *testing.T) {
|
||||
// Now all of the above again, but for IPv6.
|
||||
|
||||
// Create a new leaf strideTable, with compressed path
|
||||
tbl.Insert(p("ff:aaaa::1/128"), ptr.To(1))
|
||||
tbl.Insert(p("ff:aaaa::1/128"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", -1},
|
||||
@@ -253,7 +250,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert into previous leaf, no tree changes
|
||||
tbl.Insert(p("ff:aaaa::2/128"), ptr.To(2))
|
||||
tbl.Insert(p("ff:aaaa::2/128"), 2)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -268,7 +265,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert into previous leaf, unaligned prefix covering the /128s
|
||||
tbl.Insert(p("ff:aaaa::/125"), ptr.To(7))
|
||||
tbl.Insert(p("ff:aaaa::/125"), 7)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -283,7 +280,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Create a different leaf elsewhere
|
||||
tbl.Insert(p("ffff:bbbb::/120"), ptr.To(3))
|
||||
tbl.Insert(p("ffff:bbbb::/120"), 3)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -298,7 +295,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert that creates a new intermediate table and a new child
|
||||
tbl.Insert(p("ff:aaaa:aaaa::1/128"), ptr.To(4))
|
||||
tbl.Insert(p("ff:aaaa:aaaa::1/128"), 4)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -313,7 +310,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert that creates a new intermediate table but no new child
|
||||
tbl.Insert(p("ff:aaaa:aaaa:bb00::/56"), ptr.To(5))
|
||||
tbl.Insert(p("ff:aaaa:aaaa:bb00::/56"), 5)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -329,7 +326,7 @@ func TestInsert(t *testing.T) {
|
||||
|
||||
// New leaf in a different subtree, so the next insert can test a
|
||||
// variant of decompression.
|
||||
tbl.Insert(p("ff:cccc::1/128"), ptr.To(8))
|
||||
tbl.Insert(p("ff:cccc::1/128"), 8)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -345,7 +342,7 @@ func TestInsert(t *testing.T) {
|
||||
|
||||
// Insert that creates a new intermediate table but no new child,
|
||||
// with an unaligned intermediate
|
||||
tbl.Insert(p("ff:cccc::/37"), ptr.To(9))
|
||||
tbl.Insert(p("ff:cccc::/37"), 9)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -360,7 +357,7 @@ func TestInsert(t *testing.T) {
|
||||
})
|
||||
|
||||
// Insert a default route, those have their own codepath.
|
||||
tbl.Insert(p("::/0"), ptr.To(6))
|
||||
tbl.Insert(p("::/0"), 6)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"ff:aaaa::1", 1},
|
||||
{"ff:aaaa::2", 2},
|
||||
@@ -384,7 +381,7 @@ func TestDelete(t *testing.T) {
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
|
||||
tbl.Insert(p("10.0.0.0/8"), ptr.To(1))
|
||||
tbl.Insert(p("10.0.0.0/8"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"10.0.0.1", 1},
|
||||
{"255.255.255.255", -1},
|
||||
@@ -403,7 +400,7 @@ func TestDelete(t *testing.T) {
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"255.255.255.255", -1},
|
||||
@@ -421,8 +418,8 @@ func TestDelete(t *testing.T) {
|
||||
// Create an intermediate with 2 children, then delete one leaf.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.180.0.1/32"), ptr.To(2))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
tbl.Insert(p("192.180.0.1/32"), 2)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.180.0.1", 2},
|
||||
@@ -442,9 +439,9 @@ func TestDelete(t *testing.T) {
|
||||
// Same, but the intermediate carries a route as well.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.180.0.1/32"), ptr.To(2))
|
||||
tbl.Insert(p("192.0.0.0/10"), ptr.To(3))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
tbl.Insert(p("192.180.0.1/32"), 2)
|
||||
tbl.Insert(p("192.0.0.0/10"), 3)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.180.0.1", 2},
|
||||
@@ -466,9 +463,9 @@ func TestDelete(t *testing.T) {
|
||||
// Intermediate with 3 leaves, then delete one leaf.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.180.0.1/32"), ptr.To(2))
|
||||
tbl.Insert(p("192.200.0.1/32"), ptr.To(3))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
tbl.Insert(p("192.180.0.1/32"), 2)
|
||||
tbl.Insert(p("192.200.0.1/32"), 3)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.180.0.1", 2},
|
||||
@@ -490,7 +487,7 @@ func TestDelete(t *testing.T) {
|
||||
// Delete non-existent prefix, missing strideTable path.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.255.0.1", -1},
|
||||
@@ -509,7 +506,7 @@ func TestDelete(t *testing.T) {
|
||||
// with a wrong turn.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.255.0.1", -1},
|
||||
@@ -528,7 +525,7 @@ func TestDelete(t *testing.T) {
|
||||
// leaf doesn't contain route.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.255.0.1", -1},
|
||||
@@ -547,8 +544,8 @@ func TestDelete(t *testing.T) {
|
||||
// compactable.
|
||||
tbl := &Table[int]{}
|
||||
checkSize(t, tbl, 2)
|
||||
tbl.Insert(p("192.168.0.1/32"), ptr.To(1))
|
||||
tbl.Insert(p("192.168.0.0/22"), ptr.To(2))
|
||||
tbl.Insert(p("192.168.0.1/32"), 1)
|
||||
tbl.Insert(p("192.168.0.0/22"), 2)
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
{"192.168.0.1", 1},
|
||||
{"192.168.0.2", 2},
|
||||
@@ -568,7 +565,7 @@ func TestDelete(t *testing.T) {
|
||||
// Default routes have a special case in the code.
|
||||
tbl := &Table[int]{}
|
||||
|
||||
tbl.Insert(p("0.0.0.0/0"), ptr.To(1))
|
||||
tbl.Insert(p("0.0.0.0/0"), 1)
|
||||
tbl.Delete(p("0.0.0.0/0"))
|
||||
|
||||
checkRoutes(t, tbl, []tableTest{
|
||||
@@ -595,20 +592,20 @@ func TestInsertCompare(t *testing.T) {
|
||||
t.Logf(fast.debugSummary())
|
||||
}
|
||||
|
||||
seenVals4 := map[*int]bool{}
|
||||
seenVals6 := map[*int]bool{}
|
||||
seenVals4 := map[int]bool{}
|
||||
seenVals6 := map[int]bool{}
|
||||
for i := 0; i < 10_000; i++ {
|
||||
a := randomAddr()
|
||||
slowVal := slow.get(a)
|
||||
fastVal := fast.Get(a)
|
||||
slowVal, slowOK := slow.get(a)
|
||||
fastVal, fastOK := fast.Get(a)
|
||||
if !getsEqual(slowVal, slowOK, fastVal, fastOK) {
|
||||
t.Fatalf("get(%q) = (%v, %v), want (%v, %v)", a, fastVal, fastOK, slowVal, slowOK)
|
||||
}
|
||||
if a.Is6() {
|
||||
seenVals6[fastVal] = true
|
||||
} else {
|
||||
seenVals4[fastVal] = true
|
||||
}
|
||||
if slowVal != fastVal {
|
||||
t.Fatalf("get(%q) = %p, want %p", a, fastVal, slowVal)
|
||||
}
|
||||
}
|
||||
|
||||
// Empirically, 10k probes into 5k v4 prefixes and 5k v6 prefixes results in
|
||||
@@ -667,13 +664,10 @@ func TestInsertShuffled(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, a := range addrs {
|
||||
val1 := rt.Get(a)
|
||||
val2 := rt2.Get(a)
|
||||
if val1 == nil && val2 == nil {
|
||||
continue
|
||||
}
|
||||
if (val1 == nil && val2 != nil) || (val1 != nil && val2 == nil) || (*val1 != *val2) {
|
||||
t.Fatalf("get(%q) = %s, want %s", a, printIntPtr(val2), printIntPtr(val1))
|
||||
val1, ok1 := rt.Get(a)
|
||||
val2, ok2 := rt2.Get(a)
|
||||
if !getsEqual(val1, ok1, val2, ok2) {
|
||||
t.Fatalf("get(%q) = (%v, %v), want (%v, %v)", a, val2, ok2, val1, ok1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -727,20 +721,20 @@ func TestDeleteCompare(t *testing.T) {
|
||||
fast.Delete(pfx.pfx)
|
||||
}
|
||||
|
||||
seenVals4 := map[*int]bool{}
|
||||
seenVals6 := map[*int]bool{}
|
||||
seenVals4 := map[int]bool{}
|
||||
seenVals6 := map[int]bool{}
|
||||
for i := 0; i < numProbes; i++ {
|
||||
a := randomAddr()
|
||||
slowVal := slow.get(a)
|
||||
fastVal := fast.Get(a)
|
||||
slowVal, slowOK := slow.get(a)
|
||||
fastVal, fastOK := fast.Get(a)
|
||||
if !getsEqual(slowVal, slowOK, fastVal, fastOK) {
|
||||
t.Fatalf("get(%q) = (%v, %v), want (%v, %v)", a, fastVal, fastOK, slowVal, slowOK)
|
||||
}
|
||||
if a.Is6() {
|
||||
seenVals6[fastVal] = true
|
||||
} else {
|
||||
seenVals4[fastVal] = true
|
||||
}
|
||||
if slowVal != fastVal {
|
||||
t.Fatalf("get(%q) = %p, want %p", a, fastVal, slowVal)
|
||||
}
|
||||
}
|
||||
// Empirically, 10k probes into 5k v4 prefixes and 5k v6 prefixes results in
|
||||
// ~1k distinct values for v4 and ~300 for v6. distinct routes. This sanity
|
||||
@@ -814,13 +808,10 @@ func TestDeleteShuffled(t *testing.T) {
|
||||
// test for equivalence statistically with random probes instead.
|
||||
for i := 0; i < numProbes; i++ {
|
||||
a := randomAddr()
|
||||
val1 := rt.Get(a)
|
||||
val2 := rt2.Get(a)
|
||||
if val1 == nil && val2 == nil {
|
||||
continue
|
||||
}
|
||||
if (val1 == nil && val2 != nil) || (val1 != nil && val2 == nil) || (*val1 != *val2) {
|
||||
t.Errorf("get(%q) = %s, want %s", a, printIntPtr(val2), printIntPtr(val1))
|
||||
val1, ok1 := rt.Get(a)
|
||||
val2, ok2 := rt2.Get(a)
|
||||
if !getsEqual(val1, ok1, val2, ok2) {
|
||||
t.Errorf("get(%q) = (%v, %v), want (%v, %v)", a, val2, ok2, val1, ok1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -868,12 +859,12 @@ type tableTest struct {
|
||||
func checkRoutes(t *testing.T, tbl *Table[int], tt []tableTest) {
|
||||
t.Helper()
|
||||
for _, tc := range tt {
|
||||
v := tbl.Get(netip.MustParseAddr(tc.addr))
|
||||
if v == nil && tc.want != -1 {
|
||||
t.Errorf("lookup %q got nil, want %d", tc.addr, tc.want)
|
||||
v, ok := tbl.Get(netip.MustParseAddr(tc.addr))
|
||||
if !ok && tc.want != -1 {
|
||||
t.Errorf("lookup %q got (%v, %v), want (_, false)", tc.addr, v, ok)
|
||||
}
|
||||
if v != nil && *v != tc.want {
|
||||
t.Errorf("lookup %q got %d, want %d", tc.addr, *v, tc.want)
|
||||
if ok && v != tc.want {
|
||||
t.Errorf("lookup %q got (%v, %v), want (%v, true)", tc.addr, v, ok, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1005,7 +996,7 @@ func BenchmarkTableGet(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
addr := genAddr()
|
||||
t.Start()
|
||||
writeSink = rt.Get(addr)
|
||||
writeSink, _ = rt.Get(addr)
|
||||
t.Stop()
|
||||
}
|
||||
})
|
||||
@@ -1112,7 +1103,7 @@ type slowPrefixTable[T any] struct {
|
||||
|
||||
type slowPrefixEntry[T any] struct {
|
||||
pfx netip.Prefix
|
||||
val *T
|
||||
val T
|
||||
}
|
||||
|
||||
func (t *slowPrefixTable[T]) delete(pfx netip.Prefix) {
|
||||
@@ -1127,7 +1118,7 @@ func (t *slowPrefixTable[T]) delete(pfx netip.Prefix) {
|
||||
t.prefixes = ret
|
||||
}
|
||||
|
||||
func (t *slowPrefixTable[T]) insert(pfx netip.Prefix, val *T) {
|
||||
func (t *slowPrefixTable[T]) insert(pfx netip.Prefix, val T) {
|
||||
pfx = pfx.Masked()
|
||||
for i, ent := range t.prefixes {
|
||||
if ent.pfx == pfx {
|
||||
@@ -1138,11 +1129,8 @@ func (t *slowPrefixTable[T]) insert(pfx netip.Prefix, val *T) {
|
||||
t.prefixes = append(t.prefixes, slowPrefixEntry[T]{pfx, val})
|
||||
}
|
||||
|
||||
func (t *slowPrefixTable[T]) get(addr netip.Addr) *T {
|
||||
var (
|
||||
ret *T
|
||||
bestLen = -1
|
||||
)
|
||||
func (t *slowPrefixTable[T]) get(addr netip.Addr) (ret T, ok bool) {
|
||||
bestLen := -1
|
||||
|
||||
for _, pfx := range t.prefixes {
|
||||
if pfx.pfx.Contains(addr) && pfx.pfx.Bits() > bestLen {
|
||||
@@ -1150,7 +1138,7 @@ func (t *slowPrefixTable[T]) get(addr netip.Addr) *T {
|
||||
bestLen = pfx.pfx.Bits()
|
||||
}
|
||||
}
|
||||
return ret
|
||||
return ret, bestLen != -1
|
||||
}
|
||||
|
||||
// randomPrefixes returns n randomly generated prefixes and associated values,
|
||||
@@ -1176,7 +1164,7 @@ func randomPrefixes4(n int) []slowPrefixEntry[int] {
|
||||
|
||||
ret := make([]slowPrefixEntry[int], 0, len(pfxs))
|
||||
for pfx := range pfxs {
|
||||
ret = append(ret, slowPrefixEntry[int]{pfx, ptr.To(rand.Int())})
|
||||
ret = append(ret, slowPrefixEntry[int]{pfx, rand.Int()})
|
||||
}
|
||||
|
||||
return ret
|
||||
@@ -1197,7 +1185,7 @@ func randomPrefixes6(n int) []slowPrefixEntry[int] {
|
||||
|
||||
ret := make([]slowPrefixEntry[int], 0, len(pfxs))
|
||||
for pfx := range pfxs {
|
||||
ret = append(ret, slowPrefixEntry[int]{pfx, ptr.To(rand.Int())})
|
||||
ret = append(ret, slowPrefixEntry[int]{pfx, rand.Int()})
|
||||
}
|
||||
|
||||
return ret
|
||||
@@ -1230,14 +1218,6 @@ func randomAddr6() netip.Addr {
|
||||
return netip.AddrFrom16(b)
|
||||
}
|
||||
|
||||
// printIntPtr returns *v as a string, or the literal "<nil>" if v is nil.
|
||||
func printIntPtr(v *int) string {
|
||||
if v == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return fmt.Sprint(*v)
|
||||
}
|
||||
|
||||
// roundFloat64 rounds f to 2 decimal places, for display.
|
||||
//
|
||||
// It round-trips through a float->string->float conversion, so should not be
|
||||
|
Reference in New Issue
Block a user