Skip to content

feat(core): exit-node forwarding over NyUnicast#122

Open
Evsio0n wants to merge 1 commit into
encodeous:mainfrom
Evsio0n:feat/exit-node-v2
Open

feat(core): exit-node forwarding over NyUnicast#122
Evsio0n wants to merge 1 commit into
encodeous:mainfrom
Evsio0n:feat/exit-node-v2

Conversation

@Evsio0n
Copy link
Copy Markdown

@Evsio0n Evsio0n commented May 27, 2026

Adds explicit exit-node forwarding as a new node-to-node packet type on top of polyamide TC, reworking the earlier exit-only encapsulation in response to maintainer review on #121:

  • binary NodeIdBin (uint16) replaces variable-length node id strings in the on-the-wire header. The mapping is rebuilt deterministically from CentralCfg on every apply so all peers agree.

  • the dataplane filter reads an atomic ExitFilterSnapshot pointer instead of touching n.LocalCfg / n.CentralCfg / RouterState. The snapshot is rebuilt on the dispatch goroutine on config apply and on every route mutation, and bundles the per-node next-hop table so the filter performs a single atomic.Load per packet.

  • the wire format is documented in core/nylon_unicast.go as a generic NyUnicast envelope (fixed 6-byte header, subtype/hop_limit/dst/src), leaving room for future node-targeted subtypes (state query, config push) without re-inventing the encoding.

LocalCfg gains AdvertiseExitNode and ExitNode; the corresponding NylonOptions overrides are wired through entrypoint.go. ComputeSysRouteTable adds 0.0.0.0/0 when ExitNode is set and excludes the default-local ranges (loopback, link-local, multicast) so they never tunnel.

Tests:

  • state: NodeIdBin map determinism, zero reserved.
  • core: header round-trip, source-ownership rule, sys route table.
  • e2e (tagged): three-node client/relay/exit topology with ExitEncap/ExitTransit/ExitDecap traces.

Refs #121

Adds explicit exit-node forwarding as a new node-to-node packet type on
top of polyamide TC, reworking the earlier exit-only encapsulation in
response to maintainer review on encodeous#121:

  - binary NodeIdBin (uint16) replaces variable-length node id strings
    in the on-the-wire header. The mapping is rebuilt deterministically
    from CentralCfg on every apply so all peers agree.

  - the dataplane filter reads an atomic ExitFilterSnapshot pointer
    instead of touching n.LocalCfg / n.CentralCfg / RouterState. The
    snapshot is rebuilt on the dispatch goroutine on config apply and
    on every route mutation, and bundles the per-node next-hop table
    so the filter performs a single atomic.Load per packet.

  - the wire format is documented in core/nylon_unicast.go as a generic
    NyUnicast envelope (fixed 6-byte header, subtype/hop_limit/dst/src),
    leaving room for future node-targeted subtypes (state query, config
    push) without re-inventing the encoding.

LocalCfg gains AdvertiseExitNode and ExitNode; the corresponding
NylonOptions overrides are wired through entrypoint.go. ComputeSysRouteTable
adds 0.0.0.0/0 when ExitNode is set and excludes the default-local
ranges (loopback, link-local, multicast) so they never tunnel.

Tests:
  - state: NodeIdBin map determinism, zero reserved.
  - core: header round-trip, source-ownership rule, sys route table.
  - e2e (tagged): three-node client/relay/exit topology with
    ExitEncap/ExitTransit/ExitDecap traces.

Refs encodeous#121
@Evsio0n Evsio0n marked this pull request as ready for review May 27, 2026 14:09
@encodeous
Copy link
Copy Markdown
Owner

encodeous commented May 29, 2026

Thanks for the PR! I will review this over the weekend.

:)

Edit: I might not get to it this weekend... :(

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.

2 participants