Skip to content

fix(connect): install the peer's real address, not a guessed derivation - #20

Closed
wighawag wants to merge 9 commits into
tunnetio:mainfrom
wighawag:fix/connect-collision-index
Closed

fix(connect): install the peer's real address, not a guessed derivation#20
wighawag wants to merge 9 commits into
tunnetio:mainfrom
wighawag:fix/connect-collision-index

Conversation

@wighawag

@wighawag wighawag commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

accept_pending derived the peer's mesh address with derive_ipv4(id, 0), hardcoding collision_index to 0 (connect.rs:221). A peer the coordinator had to deconflict has a non-zero index and a completely different address, so accepting its request installed a route to the wrong address.

The information was never available on that side. connect_response carries ipv4, so the requester learns the responder's real address and only falls back to derivation if it is missing. connect_request carried no address at all, leaving the responder with nothing but a guess.

This adds ipv4 to connect_request, persists it on the pending record, and uses it when accepting.

Backward compatible in both directions: an older peer omits the field and the responder falls back to derivation (with a warning explaining why it may be wrong); an older responder ignores the extra field; and connect_pending.json records written before this change deserialize with ipv4: None, covered by a test.

Flagging for review: this touches the connect_request JSON. It is purely additive, but it is a protocol message rather than local state, so it deserves a look given the datapath work in flight.

Found while investigating #18, but unrelated to the CIDR collision.

Refs #18

orielhaim and others added 9 commits September 4, 2026 02:11
…er ownership

Linux TUN writer staged [32B frame headroom][12B virtio][IP] but passed
offset 12, so the kernel received zeros instead of IPv4 and dropped every
inbound packet silently. Writer now owns dedicated [12B][IP] buffers.

Also: unify BatchSlot AsRef/AsMut on the receive area, drop dead
detach/recycle APIs, fix v3 net prefix in reject fallback, single reader
ownership (adopt/hook), ingress generation guard, dataplane health states
(up/degraded/restarting/down) with restart counters, git-hash + ALPN in
status with CLI/daemon mismatch warning, privileged TUN round-trip test.
…ch honesty, A/B knobs

Scheduler reports every drop: EnqueueOutcome (Accepted/AcceptedEvicted/
Rejected) with victim lengths for exact gauge reconcile; drain_drops()
surfaces CoDel/emergency deltas exactly once; pump + agent sites report
all of flow/peer/codel/emergency/transport-full to telemetry.

Diagnostic A/B knobs (env): TUNNET_FLOW_PACKET_CAP, TUNNET_TUN_OFFLOAD,
TUNNET_QUIC_DATAGRAM_BUFFER_KB, TUNNET_PUMP_BACKOFF_MAX_US.

Eager preconnect of routed peers on keep-alive bring-up (kills first-
ping-timeout). bench.ps1/sh: exit codes + stderr captured everywhere,
no invented 50 Mbps fallback (TCP failure stops), UDP sender/receiver
split with sum_received delivered, size x direction matrix, valid flags.

Audit section 18.
`accept_pending` derived the peer's mesh address with `derive_ipv4(id, 0)`,
hardcoding `collision_index` to 0. A peer the coordinator had to deconflict
has a non-zero index and a completely different address, so accepting its
request installed a route to the wrong address.

The information was never available on that side: `connect_response`
carries `ipv4`, so the requester learns the responder's real address, but
`connect_request` carried none, leaving the responder to guess.

Add `ipv4` to `connect_request` and persist it on the pending record, then
use it when accepting. Both halves are additive and backward compatible: an
older peer simply omits the field, an older responder ignores it, and
records written before this change deserialize with `ipv4: None`. The
derivation remains as a fallback, now with a warning that says why it may
be wrong.

Note this touches the connect_request JSON. It is purely additive, but
flagging it since it is a protocol message rather than local state.
@wighawag

wighawag commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #24. Closing rather than rebasing.

accept_pending guessed the peer's address with derive_ipv4(id, 0), hardcoding collision_index to 0, so accepting a request from a peer the coordinator had deconflicted installed a route to the wrong address. My fix added ipv4 to connect_request so the responder was told the real address instead of deriving it.

#24 removes the premise. derive_ipv4 and collision_index no longer exist in the source on fix/direct-addressing-authority; signed membership is the only EndpointId -> IP authority, so neither side derives an address that the other can disagree with.

That is the better outcome specifically because it does NOT touch the wire format. I flagged the connect_request change for review precisely because it was a protocol message rather than local state, and adding a field to accommodate a guess is worse than removing the guess. Closing this avoids shipping a compatibility shim for a code path that is being deleted.

The backward-compatibility work here is therefore moot, including the connect_pending.json ipv4: None deserialization test. If #24 is abandoned, this branch is untouched and still applies, but it should not be revived while #24 is live.

@wighawag wighawag closed this Sep 6, 2026
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