ipn/ipnlocal: update netmap cache after peer deltas are applied (#20111)
Add an UpdatePeers method to the cache. This allows us to support netmap peer deltas, by allowing just the peers to be updated in an existing cache. As a safety check, reject an update if there was no base netmap data to apply a change to. Then, when processing peer mutations in the backend, capture any changes that should be applied to the cache and update it, if one is enabled. Updates #12542 Change-Id: I2f8790a8fdc5e85fce6700ba4821a8cb10dddffa Signed-off-by: M. J. Fromberger <fromberger@tailscale.com>
This commit is contained in:
@@ -307,6 +307,55 @@ func TestUpdateSelfOnly(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePeers(t *testing.T) {
|
||||
modNode1 := (&tailcfg.Node{
|
||||
ID: 99001,
|
||||
StableID: "n99001FAKE",
|
||||
Name: "test1altered.example.com.",
|
||||
}).View() // a modified version of testNode1
|
||||
newNode3 := (&tailcfg.Node{
|
||||
ID: 99003,
|
||||
StableID: "n99003FAKE",
|
||||
Name: "test3.example.com.",
|
||||
}).View() // a new node hitherto unseen
|
||||
|
||||
update := []tailcfg.NodeView{newNode3, modNode1}
|
||||
remove := []tailcfg.StableNodeID{testNode2.StableID()}
|
||||
|
||||
// Modify a shallow copy of the map so we can perform an update and verify
|
||||
// that it round-trips through a Load after calling UpdatePeers.
|
||||
updated := *testMap
|
||||
updated.Peers = []tailcfg.NodeView{modNode1, newNode3} // N.B. sorted
|
||||
|
||||
s := make(testStore)
|
||||
c := netmapcache.NewCache(s)
|
||||
|
||||
// Prior to storing anything, the cache should reject an update because it
|
||||
// has no base netmap to apply changes to.
|
||||
if err := c.UpdatePeers(t.Context(), update, remove); err == nil {
|
||||
t.Error("UpdatePeers on empty cache unexpectedly succeeded")
|
||||
} else {
|
||||
t.Logf("UpdatePeers on empty cache: %v (OK)", err)
|
||||
}
|
||||
|
||||
// Initialize the cache with the test map so we get a baseline.
|
||||
if err := c.Store(t.Context(), testMap); err != nil {
|
||||
t.Fatalf("Store initial netmap: %v", err)
|
||||
}
|
||||
|
||||
if err := c.UpdatePeers(t.Context(), update, remove); err != nil {
|
||||
t.Fatalf("UpdatePeers failed; %v", err)
|
||||
}
|
||||
|
||||
got, err := c.Load(t.Context())
|
||||
if err != nil {
|
||||
t.Fatalf("Load netmap failed: %v", err)
|
||||
}
|
||||
if diff := diffNetMaps(got, &updated); diff != "" {
|
||||
t.Fatalf("Updated map differs (-got, +want):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// skippedMapFields are the names of fields that should not be considered by
|
||||
// network map caching, and thus skipped when comparing test results.
|
||||
var skippedMapFields = []string{
|
||||
|
||||
Reference in New Issue
Block a user