Skip to content

[client] Fix forwarder peers never excluded from lazy connections#6674

Open
riccardomanfrin wants to merge 4 commits into
mainfrom
fix/forwarders_exclusion_from_lazy_conn
Open

[client] Fix forwarder peers never excluded from lazy connections#6674
riccardomanfrin wants to merge 4 commits into
mainfrom
fix/forwarders_exclusion_from_lazy_conn

Conversation

@riccardomanfrin

@riccardomanfrin riccardomanfrin commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Describe your changes

toExcludedLazyPeers compared each peer's AllowedIPs (CIDR, e.g. an overlay IP as /32) against ForwardRule.TranslatedAddress.String() (unmasked), so the match never fired and forward-target peers were never excluded from lazy connections — inbound forwarded traffic can't wake a lazy peer, so those peers must stay permanent. Extracted a peerRoutesAddr helper and switched to prefix containment.

Issue ticket number and link

Internal bug found while investigating lazy-connection DNS/forwarding breakage. Broken line on main: https://github.com/netbirdio/netbird/blob/main/client/internal/engine.go#L2568

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)

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)

Internal lazy-connection exclusion fix. No public API, config, or CLI change.

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

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

N/A

Summary by CodeRabbit

  • Bug Fixes

    • Improved forwarding behavior so peers are excluded using their actual routed address ranges, reducing missed matches from exact string comparisons.
    • Fixed lazy-connection exclusion logic for inbound forwarded targets, including IPv4 and IPv6 cases.
  • Tests

    • Added coverage for address-range matching and forward-target exclusion behavior.
    • Added checks for empty-rule handling and negative match cases.

riccardomanfrin and others added 3 commits July 6, 2026 11:05
Pure stylistic refactor: pull the AllowedIPs match into a named
peerRoutesAddr helper and document why forward-target peers are excluded
from lazy connections. No behavior change; the existing address match is
preserved as-is.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
toExcludedLazyPeers compares AllowedIPs (CIDR) against the unmasked
TranslatedAddress, so forward-target peers are never excluded. This test
asserts the peer is excluded and fails on the current behavior; the fix
follows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
peerRoutesAddr compared AllowedIPs (CIDR, e.g. a peer's overlay IP as /32)
against the unmasked TranslatedAddress string, so the match never fired and
forward-target peers were never excluded from lazy connections. Use prefix
containment so a routed address matches the peer's AllowedIP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@riccardomanfrin riccardomanfrin requested a review from lixmal July 6, 2026 09:42
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR changes how Engine.toExcludedLazyPeers determines whether a peer should be excluded from lazy connection handling. Instead of string-comparing forwarded translated addresses against peer AllowedIPs, it now queries typed netip.Prefix values from the peer store via new peerRoutesAddr and prefixesContain helpers. Unit tests were added to validate the new logic.

Changes

Lazy peer exclusion logic

Layer / File(s) Summary
Route-containment exclusion logic and helpers
client/internal/engine.go
toExcludedLazyPeers now uses typed AllowedIP prefixes from the peer store and new peerRoutesAddr/prefixesContain helpers to check whether a peer routes the forwarded TranslatedAddress, replacing the prior string-equality comparison against p.GetAllowedIps().
Regression tests for exclusion logic and helpers
client/internal/engine_lazy_exclude_test.go
New tests TestPrefixesContain, TestToExcludedLazyPeers_ForwardTarget, and TestToExcludedLazyPeers_NoRules, plus a newTestConn helper, validate prefix containment and correct peer exclusion with and without forward rules.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ToExcludedLazyPeers
  participant peerRoutesAddr
  participant prefixesContain
  participant ExcludedPeerSet
  ToExcludedLazyPeers->>peerRoutesAddr: check peer AllowedIps for TranslatedAddress
  peerRoutesAddr->>prefixesContain: check prefixes contain address
  prefixesContain-->>peerRoutesAddr: contains result
  peerRoutesAddr-->>ToExcludedLazyPeers: contains result
  ToExcludedLazyPeers->>ExcludedPeerSet: add matching peer
Loading

Suggested reviewers: lixmal

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly summarizes the main bug fix in the changeset.
Description check ✅ Passed Mostly matches the template; the issue ticket/link section is the only incomplete part.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/forwarders_exclusion_from_lazy_conn

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Release artifacts

Built for PR head 8732d3c in workflow run #16511.

Artifact Link
All release artifacts Download
Linux packages Download
Windows packages Download
macOS packages Download
UI artifacts Download
UI macOS artifacts Download

GHCR images (amd64)

This comment is updated by the Release workflow. Artifact links expire according to the workflow retention policy.

Instead of re-parsing the network map AllowedIPs strings, look up the
already-parsed []netip.Prefix from peerStore.AllowedIPs (the same typed
value the lazy manager itself consumes). A down/lazy peer still has its
conn in the store, so exclusion is unaffected by connection state. Extract
a pure prefixesContain helper and unit-test it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Jul 6, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
client/internal/engine_lazy_exclude_test.go (1)

44-67: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider adding a case where the target peer isn't yet in peerStore.

This test only covers the scenario where the peer's peerStore entry already has matching AllowedIps. It doesn't cover the case where toExcludedLazyPeers is invoked for a peer that hasn't been added to peerStore yet (i.e., AllowedIPs returns ok=false), which is the scenario flagged as a potential regression risk in engine.go. Adding this case would confirm the intended fallback behavior (or expose the gap).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/internal/engine_lazy_exclude_test.go` around lines 44 - 67, Add a test
case for Engine.toExcludedLazyPeers covering the fallback path when the
forward-target peer is not yet present in peerStore and AllowedIPs returns
ok=false. Reuse the existing TestToExcludedLazyPeers_ForwardTarget structure,
but omit the target peer from the ConnStore and assert the intended exclusion
behavior for that peer while keeping the non-target peer unaffected. This will
validate the Engine.peerStore/AllowedIPs lookup path and protect the regression
risk called out in engine.go.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@client/internal/engine_lazy_exclude_test.go`:
- Around line 44-67: Add a test case for Engine.toExcludedLazyPeers covering the
fallback path when the forward-target peer is not yet present in peerStore and
AllowedIPs returns ok=false. Reuse the existing
TestToExcludedLazyPeers_ForwardTarget structure, but omit the target peer from
the ConnStore and assert the intended exclusion behavior for that peer while
keeping the non-target peer unaffected. This will validate the
Engine.peerStore/AllowedIPs lookup path and protect the regression risk called
out in engine.go.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 839b8185-0b73-44f7-bb23-a312d43cf21a

📥 Commits

Reviewing files that changed from the base of the PR and between c9d387b and 8732d3c.

📒 Files selected for processing (2)
  • client/internal/engine.go
  • client/internal/engine_lazy_exclude_test.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant