mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-23 22:09:09 +02:00
[client] Keep a converging map when an older one arrives
The first pass of a new target replaced syncTargetMap before the serial check in updateNetworkMap ran. An outdated map arriving mid-convergence took the place of the newer one, was then ignored as stale and reported as converged, so the newer map's remaining peer batches were never applied until the next update. A stale map now leaves the pending one in place.
This commit is contained in:
@@ -1075,6 +1075,7 @@ func (e *Engine) applySyncPass(update *mgmProto.SyncResponse, firstPass bool) (b
|
||||
// when the update carries one. A config-only update leaves syncTargetMap nil. The
|
||||
// caller holds syncMsgMux.
|
||||
func (e *Engine) loadSyncTarget(update *mgmProto.SyncResponse) error {
|
||||
pending := e.syncTargetMap
|
||||
e.syncTargetMap = nil
|
||||
|
||||
e.ApplySessionDeadline(update.GetSessionExpiresAt())
|
||||
@@ -1158,6 +1159,14 @@ func (e *Engine) loadSyncTarget(update *mgmProto.SyncResponse) error {
|
||||
e.latestComponents = components
|
||||
}
|
||||
|
||||
// updateNetworkMap ignores a stale map and reports convergence, which would
|
||||
// strand the remaining peer batches of a newer map still being applied.
|
||||
if pending != nil && nm.GetSerial() < e.networkSerial {
|
||||
log.Debugf("ignoring network map with serial %d while serial %d is converging", nm.GetSerial(), e.networkSerial)
|
||||
e.syncTargetMap = pending
|
||||
return nil
|
||||
}
|
||||
|
||||
e.syncTargetMap = nm
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1798,3 +1798,23 @@ func TestEngine_ApplySyncPassDecodesOncePerTarget(t *testing.T) {
|
||||
_, err = e.applySyncPass(undecodable, true)
|
||||
assert.Error(t, err, "the first pass of a target decodes it")
|
||||
}
|
||||
|
||||
// A map older than the one still converging must not take its place: the
|
||||
// stale guard in updateNetworkMap would ignore it and report convergence,
|
||||
// leaving the newer map's remaining peer batches unapplied.
|
||||
func TestEngine_LoadSyncTargetKeepsNewerPendingMap(t *testing.T) {
|
||||
pending := &mgmtProto.NetworkMap{Serial: 10}
|
||||
e := &Engine{
|
||||
ctx: context.Background(),
|
||||
syncMsgMux: &sync.Mutex{},
|
||||
networkSerial: 10,
|
||||
syncTargetMap: pending,
|
||||
}
|
||||
|
||||
require.NoError(t, e.loadSyncTarget(&mgmtProto.SyncResponse{NetworkMap: &mgmtProto.NetworkMap{Serial: 9}}))
|
||||
assert.Same(t, pending, e.syncTargetMap, "a stale map should leave the pending newer map in place")
|
||||
|
||||
newer := &mgmtProto.NetworkMap{Serial: 11}
|
||||
require.NoError(t, e.loadSyncTarget(&mgmtProto.SyncResponse{NetworkMap: newer}))
|
||||
assert.Same(t, newer, e.syncTargetMap, "a newer map should replace the pending one")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user