Skip to content

Commit f16f0c7

Browse files
authored
[client] Fix HA router switch (#3889)
* Fix HA router switch. - Simplify the notification filter logic. Always send notification if a state has been changed - Remove IP changes check because we never modify * Notify only the proper listeners * Fix test * Fix TestGetPeerStateChangeNotifierLogic test * Before lazy connection, when the peer disconnected, the status switched to disconnected. After implementing lazy connection, the peer state is connecting, so we did not decrease the reference counters on the routes. * When switch to idle notify the route mgr
1 parent aa07b3b commit f16f0c7

File tree

3 files changed

+57
-57
lines changed

3 files changed

+57
-57
lines changed

client/internal/peer/status.go

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,7 @@ func (d *Status) UpdatePeerState(receivedState State) error {
289289
return errors.New("peer doesn't exist")
290290
}
291291

292-
if receivedState.IP != "" {
293-
peerState.IP = receivedState.IP
294-
}
295-
296-
skipNotification := shouldSkipNotify(receivedState.ConnStatus, peerState)
292+
oldState := peerState.ConnStatus
297293

298294
if receivedState.ConnStatus != peerState.ConnStatus {
299295
peerState.ConnStatus = receivedState.ConnStatus
@@ -309,11 +305,15 @@ func (d *Status) UpdatePeerState(receivedState State) error {
309305

310306
d.peers[receivedState.PubKey] = peerState
311307

312-
if skipNotification {
313-
return nil
308+
if hasConnStatusChanged(oldState, receivedState.ConnStatus) {
309+
d.notifyPeerListChanged()
314310
}
315311

316-
d.notifyPeerListChanged()
312+
// when we close the connection we will not notify the router manager
313+
if receivedState.ConnStatus == StatusIdle {
314+
d.notifyPeerStateChangeListeners(receivedState.PubKey)
315+
316+
}
317317
return nil
318318
}
319319

@@ -380,11 +380,8 @@ func (d *Status) UpdatePeerICEState(receivedState State) error {
380380
return errors.New("peer doesn't exist")
381381
}
382382

383-
if receivedState.IP != "" {
384-
peerState.IP = receivedState.IP
385-
}
386-
387-
skipNotification := shouldSkipNotify(receivedState.ConnStatus, peerState)
383+
oldState := peerState.ConnStatus
384+
oldIsRelayed := peerState.Relayed
388385

389386
peerState.ConnStatus = receivedState.ConnStatus
390387
peerState.ConnStatusUpdate = receivedState.ConnStatusUpdate
@@ -397,12 +394,13 @@ func (d *Status) UpdatePeerICEState(receivedState State) error {
397394

398395
d.peers[receivedState.PubKey] = peerState
399396

400-
if skipNotification {
401-
return nil
397+
if hasConnStatusChanged(oldState, receivedState.ConnStatus) {
398+
d.notifyPeerListChanged()
402399
}
403400

404-
d.notifyPeerStateChangeListeners(receivedState.PubKey)
405-
d.notifyPeerListChanged()
401+
if hasStatusOrRelayedChange(oldState, receivedState.ConnStatus, oldIsRelayed, receivedState.Relayed) {
402+
d.notifyPeerStateChangeListeners(receivedState.PubKey)
403+
}
406404
return nil
407405
}
408406

@@ -415,7 +413,8 @@ func (d *Status) UpdatePeerRelayedState(receivedState State) error {
415413
return errors.New("peer doesn't exist")
416414
}
417415

418-
skipNotification := shouldSkipNotify(receivedState.ConnStatus, peerState)
416+
oldState := peerState.ConnStatus
417+
oldIsRelayed := peerState.Relayed
419418

420419
peerState.ConnStatus = receivedState.ConnStatus
421420
peerState.ConnStatusUpdate = receivedState.ConnStatusUpdate
@@ -425,12 +424,13 @@ func (d *Status) UpdatePeerRelayedState(receivedState State) error {
425424

426425
d.peers[receivedState.PubKey] = peerState
427426

428-
if skipNotification {
429-
return nil
427+
if hasConnStatusChanged(oldState, receivedState.ConnStatus) {
428+
d.notifyPeerListChanged()
430429
}
431430

432-
d.notifyPeerStateChangeListeners(receivedState.PubKey)
433-
d.notifyPeerListChanged()
431+
if hasStatusOrRelayedChange(oldState, receivedState.ConnStatus, oldIsRelayed, receivedState.Relayed) {
432+
d.notifyPeerStateChangeListeners(receivedState.PubKey)
433+
}
434434
return nil
435435
}
436436

@@ -443,7 +443,8 @@ func (d *Status) UpdatePeerRelayedStateToDisconnected(receivedState State) error
443443
return errors.New("peer doesn't exist")
444444
}
445445

446-
skipNotification := shouldSkipNotify(receivedState.ConnStatus, peerState)
446+
oldState := peerState.ConnStatus
447+
oldIsRelayed := peerState.Relayed
447448

448449
peerState.ConnStatus = receivedState.ConnStatus
449450
peerState.Relayed = receivedState.Relayed
@@ -452,12 +453,13 @@ func (d *Status) UpdatePeerRelayedStateToDisconnected(receivedState State) error
452453

453454
d.peers[receivedState.PubKey] = peerState
454455

455-
if skipNotification {
456-
return nil
456+
if hasConnStatusChanged(oldState, receivedState.ConnStatus) {
457+
d.notifyPeerListChanged()
457458
}
458459

459-
d.notifyPeerStateChangeListeners(receivedState.PubKey)
460-
d.notifyPeerListChanged()
460+
if hasStatusOrRelayedChange(oldState, receivedState.ConnStatus, oldIsRelayed, receivedState.Relayed) {
461+
d.notifyPeerStateChangeListeners(receivedState.PubKey)
462+
}
461463
return nil
462464
}
463465

@@ -470,7 +472,8 @@ func (d *Status) UpdatePeerICEStateToDisconnected(receivedState State) error {
470472
return errors.New("peer doesn't exist")
471473
}
472474

473-
skipNotification := shouldSkipNotify(receivedState.ConnStatus, peerState)
475+
oldState := peerState.ConnStatus
476+
oldIsRelayed := peerState.Relayed
474477

475478
peerState.ConnStatus = receivedState.ConnStatus
476479
peerState.Relayed = receivedState.Relayed
@@ -482,12 +485,13 @@ func (d *Status) UpdatePeerICEStateToDisconnected(receivedState State) error {
482485

483486
d.peers[receivedState.PubKey] = peerState
484487

485-
if skipNotification {
486-
return nil
488+
if hasConnStatusChanged(oldState, receivedState.ConnStatus) {
489+
d.notifyPeerListChanged()
487490
}
488491

489-
d.notifyPeerStateChangeListeners(receivedState.PubKey)
490-
d.notifyPeerListChanged()
492+
if hasStatusOrRelayedChange(oldState, receivedState.ConnStatus, oldIsRelayed, receivedState.Relayed) {
493+
d.notifyPeerStateChangeListeners(receivedState.PubKey)
494+
}
491495
return nil
492496
}
493497

@@ -510,17 +514,12 @@ func (d *Status) UpdateWireGuardPeerState(pubKey string, wgStats configurer.WGSt
510514
return nil
511515
}
512516

513-
func shouldSkipNotify(receivedConnStatus ConnStatus, curr State) bool {
514-
switch {
515-
case receivedConnStatus == StatusConnecting:
516-
return true
517-
case receivedConnStatus == StatusIdle && curr.ConnStatus == StatusConnecting:
518-
return true
519-
case receivedConnStatus == StatusIdle && curr.ConnStatus == StatusIdle:
520-
return curr.IP != ""
521-
default:
522-
return false
523-
}
517+
func hasStatusOrRelayedChange(oldConnStatus, newConnStatus ConnStatus, oldRelayed, newRelayed bool) bool {
518+
return oldRelayed != newRelayed || hasConnStatusChanged(newConnStatus, oldConnStatus)
519+
}
520+
521+
func hasConnStatusChanged(oldStatus, newStatus ConnStatus) bool {
522+
return newStatus != oldStatus
524523
}
525524

526525
// UpdatePeerFQDN update peer's state fqdn only

client/internal/peer/status_test.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"sync"
66
"testing"
7+
"time"
78

89
"github.com/stretchr/testify/assert"
910
)
@@ -42,16 +43,16 @@ func TestGetPeer(t *testing.T) {
4243
func TestUpdatePeerState(t *testing.T) {
4344
key := "abc"
4445
ip := "10.10.10.10"
46+
fqdn := "peer-a.netbird.local"
4547
status := NewRecorder("https://mgm")
48+
_ = status.AddPeer(key, fqdn, ip)
49+
4650
peerState := State{
47-
PubKey: key,
48-
Mux: new(sync.RWMutex),
51+
PubKey: key,
52+
ConnStatusUpdate: time.Now(),
53+
ConnStatus: StatusConnecting,
4954
}
5055

51-
status.peers[key] = peerState
52-
53-
peerState.IP = ip
54-
5556
err := status.UpdatePeerState(peerState)
5657
assert.NoError(t, err, "shouldn't return error")
5758

@@ -83,17 +84,17 @@ func TestGetPeerStateChangeNotifierLogic(t *testing.T) {
8384
key := "abc"
8485
ip := "10.10.10.10"
8586
status := NewRecorder("https://mgm")
86-
peerState := State{
87-
PubKey: key,
88-
Mux: new(sync.RWMutex),
89-
}
90-
91-
status.peers[key] = peerState
87+
_ = status.AddPeer(key, "abc.netbird", ip)
9288

9389
ch := status.GetPeerStateChangeNotifier(key)
9490
assert.NotNil(t, ch, "channel shouldn't be nil")
9591

96-
peerState.IP = ip
92+
peerState := State{
93+
PubKey: key,
94+
ConnStatus: StatusConnecting,
95+
Relayed: false,
96+
ConnStatusUpdate: time.Now(),
97+
}
9798

9899
err := status.UpdatePeerRelayedStateToDisconnected(peerState)
99100
assert.NoError(t, err, "shouldn't return error")

client/internal/routemanager/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func (c *clientNetwork) watchPeerStatusChanges(ctx context.Context, peerKey stri
232232
return
233233
case <-c.statusRecorder.GetPeerStateChangeNotifier(peerKey):
234234
state, err := c.statusRecorder.GetPeer(peerKey)
235-
if err != nil || state.ConnStatus == peer.StatusConnecting {
235+
if err != nil {
236236
continue
237237
}
238238
peerStateUpdate <- struct{}{}

0 commit comments

Comments
 (0)