diff --git a/client/internal/conn_mgr.go b/client/internal/conn_mgr.go index ad0f00c5d..1b37a9486 100644 --- a/client/internal/conn_mgr.go +++ b/client/internal/conn_mgr.go @@ -192,23 +192,23 @@ func (e *ConnMgr) SetExcludeList(ctx context.Context, peerIDs map[string]bool) { } } -func (e *ConnMgr) AddPeerConn(ctx context.Context, peerKey string, conn *peer.Conn) (exists bool) { +// AddPeerConn stores the peer connection and registers it with the lazy connection manager. +// active marks a peer whose connection was already established, e.g. one re-added after a +// network map modification: it is registered as active and its connection stays open, so the +// remote side does not have to signal a wake for a connection it still considers established. +func (e *ConnMgr) AddPeerConn(ctx context.Context, peerKey string, conn *peer.Conn, active bool) (exists bool) { if success := e.peerStore.AddPeerConn(peerKey, conn); !success { return true } if !e.isStartedWithLazyMgr() { - if err := conn.Open(ctx); err != nil { - conn.Log.Errorf("failed to open connection: %v", err) - } + e.openConn(ctx, conn) return } if !lazyconn.IsSupported(conn.AgentVersionString()) { conn.Log.Warnf("peer does not support lazy connection (%s), open permanent connection", conn.AgentVersionString()) - if err := conn.Open(ctx); err != nil { - conn.Log.Errorf("failed to open connection: %v", err) - } + e.openConn(ctx, conn) return } @@ -218,20 +218,23 @@ func (e *ConnMgr) AddPeerConn(ctx context.Context, peerKey string, conn *peer.Co PeerConnID: conn.ConnID(), Log: conn.Log, } - excluded, err := e.lazyConnMgr.AddPeer(lazyPeerCfg) + + excluded, err := e.addToLazyManager(lazyPeerCfg, active) if err != nil { conn.Log.Errorf("failed to add peer to lazyconn manager: %v", err) - if err := conn.Open(ctx); err != nil { - conn.Log.Errorf("failed to open connection: %v", err) - } + e.openConn(ctx, conn) return } if excluded { conn.Log.Infof("peer is on lazy conn manager exclude list, opening connection") - if err := conn.Open(ctx); err != nil { - conn.Log.Errorf("failed to open connection: %v", err) - } + e.openConn(ctx, conn) + return + } + + if active { + conn.Log.Infof("peer added to lazy conn manager as active") + e.openConn(ctx, conn) return } @@ -239,6 +242,19 @@ func (e *ConnMgr) AddPeerConn(ctx context.Context, peerKey string, conn *peer.Co return } +func (e *ConnMgr) addToLazyManager(cfg lazyconn.PeerConfig, active bool) (excluded bool, err error) { + if active { + return e.lazyConnMgr.AddActivePeer(cfg) + } + return e.lazyConnMgr.AddPeer(cfg) +} + +func (e *ConnMgr) openConn(ctx context.Context, conn *peer.Conn) { + if err := conn.Open(ctx); err != nil { + conn.Log.Errorf("failed to open connection: %v", err) + } +} + func (e *ConnMgr) RemovePeerConn(peerKey string) { conn, ok := e.peerStore.Remove(peerKey) if !ok { diff --git a/client/internal/engine.go b/client/internal/engine.go index fddaa1722..786f35095 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -886,17 +886,9 @@ func (e *Engine) modifyPeers(peersUpdate []*mgmProto.RemotePeerConfig) error { // offers, so a previously active peer left idle cannot reconnect until the // remote's connection expires. for _, p := range modified { - if err := e.addNewPeer(p); err != nil { + if err := e.addNewPeer(p, active[p.GetWgPubKey()]); err != nil { return err } - if !active[p.GetWgPubKey()] { - continue - } - conn, ok := e.peerStore.PeerConn(p.GetWgPubKey()) - if !ok { - continue - } - e.connMgr.ActivatePeer(e.ctx, conn) } return nil } @@ -1847,7 +1839,7 @@ func addrToString(addr netip.Addr) string { // addNewPeers adds peers that were not know before but arrived from the Management service with the update func (e *Engine) addNewPeers(peersUpdate []*mgmProto.RemotePeerConfig) error { for _, p := range peersUpdate { - err := e.addNewPeer(p) + err := e.addNewPeer(p, false) if err != nil { return err } @@ -1855,8 +1847,9 @@ func (e *Engine) addNewPeers(peersUpdate []*mgmProto.RemotePeerConfig) error { return nil } -// addNewPeer add peer if connection doesn't exist -func (e *Engine) addNewPeer(peerConfig *mgmProto.RemotePeerConfig) error { +// addNewPeer add peer if connection doesn't exist. active registers the peer with an +// already established connection instead of an idle lazy one. +func (e *Engine) addNewPeer(peerConfig *mgmProto.RemotePeerConfig, active bool) error { peerKey := peerConfig.GetWgPubKey() peerIPs := make([]netip.Prefix, 0, len(peerConfig.GetAllowedIps())) if _, ok := e.peerStore.PeerConn(peerKey); ok { @@ -1890,7 +1883,7 @@ func (e *Engine) addNewPeer(peerConfig *mgmProto.RemotePeerConfig) error { log.Warnf("error adding peer %s to status recorder, got error: %v", peerKey, err) } - if exists := e.connMgr.AddPeerConn(e.ctx, peerKey, conn); exists { + if exists := e.connMgr.AddPeerConn(e.ctx, peerKey, conn, active); exists { conn.Close(false) return fmt.Errorf("peer already exists: %s", peerKey) } diff --git a/client/internal/lazyconn/manager/manager.go b/client/internal/lazyconn/manager/manager.go index b7424bb2f..3443a483c 100644 --- a/client/internal/lazyconn/manager/manager.go +++ b/client/internal/lazyconn/manager/manager.go @@ -229,6 +229,20 @@ func (m *Manager) AddPeer(peerCfg lazyconn.PeerConfig) (bool, error) { return false, nil } +// AddActivePeer adds a peer whose connection is already established, so it goes +// straight to inactivity monitoring instead of waiting for a wake signal. +// Returns true if the peer is on the exclude list and is not managed lazily. +func (m *Manager) AddActivePeer(peerCfg lazyconn.PeerConfig) (bool, error) { + m.managedPeersMu.Lock() + defer m.managedPeersMu.Unlock() + + if _, ok := m.excludes[peerCfg.PublicKey]; ok { + return true, nil + } + + return false, m.addActivePeer(&peerCfg) +} + // AddActivePeers adds a list of peers to the lazy connection manager // suppose these peers was in connected or in connecting states func (m *Manager) AddActivePeers(peerCfg []lazyconn.PeerConfig) error {