[PR #6829] [CLOSED] [client] Preserve routed allowed IPs across lazy connection switch #29942

Open
opened 2026-08-05 08:09:29 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/6829
Author: @pappz
Created: 7/19/2026
Status: Closed

Base: mainHead: fix/lazyconn-idle-keep-wg-peer


📝 Commits (2)

  • 13433af [client] Preserve routed allowed IPs across lazy connection idle transitions
  • f1c06ef [client] Return empty map from test mock GetStats to satisfy nilnil linter

📊 Changes

21 files changed (+457 additions, -34 deletions)

View changed files

📝 client/iface/configurer/common.go (+38 -0)
📝 client/iface/configurer/kernel_unix.go (+34 -0)
📝 client/iface/configurer/usp.go (+58 -0)
client/iface/configurer/usp_idle_test.go (+158 -0)
📝 client/iface/device/interface.go (+1 -0)
📝 client/iface/iface.go (+13 -0)
📝 client/internal/conn_mgr.go (+1 -1)
📝 client/internal/engine.go (+1 -1)
📝 client/internal/engine_test.go (+8 -0)
📝 client/internal/iface_common.go (+1 -0)
📝 client/internal/lazyconn/activity/listener_bind.go (+1 -1)
📝 client/internal/lazyconn/activity/listener_bind_test.go (+1 -2)
📝 client/internal/lazyconn/activity/listener_udp.go (+1 -1)
📝 client/internal/lazyconn/activity/manager.go (+1 -3)
📝 client/internal/lazyconn/activity/manager_test.go (+1 -2)
📝 client/internal/lazyconn/manager/manager.go (+2 -2)
📝 client/internal/lazyconn/wgiface.go (+1 -4)
📝 client/internal/peer/conn.go (+20 -4)
📝 client/internal/peer/endpoint.go (+10 -0)
client/internal/peer/endpoint_test.go (+101 -0)

...and 1 more files

📄 Description

Describe your changes

When a routing peer goes idle under lazy connections, the WireGuard peer is removed and re-created as a wake endpoint. The route manager deliberately keeps routed prefixes installed on idle peers, but its asynchronous re-add uses update_only, which is a silent no-op while the peer is absent. When the re-add races into the removal/re-arm window, the routed subnet is left out of the peer's allowed IPs — and since the peer's status does not change again, nothing retries the add: traffic to the subnet is black-holed until the peer is woken by other means (e.g. a ping to its overlay IP).

Split the idle transition from the full close: Conn.Idle tears down transports, cancels pending delayed endpoint updates and updates the status without touching the WireGuard peer. The activity listener then arms the wake endpoint via the new IdlePeerEndpoint operation, which removes and re-creates the peer in a single transaction: handshake state is dropped (keeping the handshake-first wake semantics of packet staging and first-packet capture/reinjection) while the currently installed allowed IPs are preserved. The read-modify-write runs under the interface mutex, serializing it against concurrent allowed IP updates from the route manager — a concurrent add either lands before the read (included in the re-created set) or after the transaction (on the existing peer), so the race window is gone by construction.

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)
  • This change does not modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — OR I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See CONTRIBUTING.md.

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

https://github.com/netbirdio/docs/pull/__


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Summary by CodeRabbit

  • New Features

    • Improved lazy connection handling by switching peers to a wake (“idle”) endpoint while preserving configured allowed IPs/routes.
    • Automatically recreates peers when they’re missing during lazy connection setup.
    • Idle behavior now retains the existing peer configuration to support faster reconnection.
  • Bug Fixes

    • Prevents scheduled/queued endpoint updates from applying after a peer becomes idle.
    • Refined close/idle transitions and cleanup to ensure consistent peer endpoint behavior.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/6829 **Author:** [@pappz](https://github.com/pappz) **Created:** 7/19/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/lazyconn-idle-keep-wg-peer` --- ### 📝 Commits (2) - [`13433af`](https://github.com/netbirdio/netbird/commit/13433af4a50a2b77a9f50562af05b88c31428ee8) [client] Preserve routed allowed IPs across lazy connection idle transitions - [`f1c06ef`](https://github.com/netbirdio/netbird/commit/f1c06ef1a47adbb4cecce9c88c1f792d0cbc764c) [client] Return empty map from test mock GetStats to satisfy nilnil linter ### 📊 Changes **21 files changed** (+457 additions, -34 deletions) <details> <summary>View changed files</summary> 📝 `client/iface/configurer/common.go` (+38 -0) 📝 `client/iface/configurer/kernel_unix.go` (+34 -0) 📝 `client/iface/configurer/usp.go` (+58 -0) ➕ `client/iface/configurer/usp_idle_test.go` (+158 -0) 📝 `client/iface/device/interface.go` (+1 -0) 📝 `client/iface/iface.go` (+13 -0) 📝 `client/internal/conn_mgr.go` (+1 -1) 📝 `client/internal/engine.go` (+1 -1) 📝 `client/internal/engine_test.go` (+8 -0) 📝 `client/internal/iface_common.go` (+1 -0) 📝 `client/internal/lazyconn/activity/listener_bind.go` (+1 -1) 📝 `client/internal/lazyconn/activity/listener_bind_test.go` (+1 -2) 📝 `client/internal/lazyconn/activity/listener_udp.go` (+1 -1) 📝 `client/internal/lazyconn/activity/manager.go` (+1 -3) 📝 `client/internal/lazyconn/activity/manager_test.go` (+1 -2) 📝 `client/internal/lazyconn/manager/manager.go` (+2 -2) 📝 `client/internal/lazyconn/wgiface.go` (+1 -4) 📝 `client/internal/peer/conn.go` (+20 -4) 📝 `client/internal/peer/endpoint.go` (+10 -0) ➕ `client/internal/peer/endpoint_test.go` (+101 -0) _...and 1 more files_ </details> ### 📄 Description ## Describe your changes When a routing peer goes idle under lazy connections, the WireGuard peer is removed and re-created as a wake endpoint. The route manager deliberately keeps routed prefixes installed on idle peers, but its asynchronous re-add uses update_only, which is a silent no-op while the peer is absent. When the re-add races into the removal/re-arm window, the routed subnet is left out of the peer's allowed IPs — and since the peer's status does not change again, nothing retries the add: traffic to the subnet is black-holed until the peer is woken by other means (e.g. a ping to its overlay IP). Split the idle transition from the full close: Conn.Idle tears down transports, cancels pending delayed endpoint updates and updates the status without touching the WireGuard peer. The activity listener then arms the wake endpoint via the new IdlePeerEndpoint operation, which removes and re-creates the peer in a single transaction: handshake state is dropped (keeping the handshake-first wake semantics of packet staging and first-packet capture/reinjection) while the currently installed allowed IPs are preserved. The read-modify-write runs under the interface mutex, serializing it against concurrent allowed IP updates from the route manager — a concurrent add either lands before the read (included in the re-created set) or after the transaction (on the existing peer), so the race window is gone by construction. ## Issue ticket number and link ## Stack <!-- branch-stack --> ### Checklist - [x] Is it a bug fix - [ ] Is a typo/documentation fix - [ ] Is a feature enhancement - [ ] It is a refactor - [ ] Created tests that fail without the change (if possible) - [ ] This change does **not** modify the public API, gRPC protocols, functionality behavior, CLI / service flags, or introduce a new feature — **OR** I have discussed it with the NetBird team beforehand (link the issue / Slack thread in the description). See [CONTRIBUTING.md](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTING.md#discuss-changes-with-the-netbird-team-first). > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) ### Docs PR URL (required if "docs added" is checked) Paste the PR link from https://github.com/netbirdio/docs here: https://github.com/netbirdio/docs/pull/__ <!-- codesmith:footer --> --- <a href="https://app.blacksmith.sh/netbirdio/codesmith/netbird/pr/6829"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with Codesmith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1787082043&installation_id=146802194&pr_number=6829&repository=netbirdio%2Fnetbird&return_to=https%3A%2F%2Fgithub.com%2Fnetbirdio%2Fnetbird%2Fpull%2F6829&signature=0b721db25e04e4d7d509a430ba02c9a88f3c1f890a68f20b1aecb806633cfdb9"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with Codesmith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a> <sup>Need help on this PR? Tag <code>/codesmith</code> with what you need. Autofix is disabled.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved lazy connection handling by switching peers to a wake (“idle”) endpoint while preserving configured allowed IPs/routes. * Automatically recreates peers when they’re missing during lazy connection setup. * Idle behavior now retains the existing peer configuration to support faster reconnection. * **Bug Fixes** * Prevents scheduled/queued endpoint updates from applying after a peer becomes idle. * Refined close/idle transitions and cleanup to ensure consistent peer endpoint behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 08:09:29 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#29942