Commit Graph

5226 Commits

Author SHA1 Message Date
Frando 9213552c13 fix(proto): only mark the Available path suspect, not idle backups
A Backup path (e.g. relay, once a direct path takes over) stops
carrying new application data, but can still have in-flight packets
sent right before the switch whose PTOs keep firing with nothing sent
since to compare against. Keep-alive doesn't help: it only covers idle
gaps going forward from when its timer is armed, not data already
in-flight at the moment the path became idle. Neither reflects the
path's own health, so a Backup path could go suspect purely from being
temporarily unused, not from actually being dead.

Suspect is meant to answer "is the path we're currently relying on
still working", so it should only ever apply to the Available path.
Gate PathEvent::Suspect on that.
2026-07-24 16:05:19 +02:00
Frando a29df8afe9 feat(proto): emit PathEvent::Suspect/Recovered for dead paths
A path that stops acknowledging data currently just keeps accumulating
PTOs with no signal to the application or path selector, so a dead
path can keep winning path selection on stale RTT samples.

PathData::suspect_since_pn now tracks the Data-space packet number a
path was about to send when it crossed SUSPECT_PTO_THRESHOLD
consecutive PTOs on an established, validated path; Some(pn) doubles
as the suspect flag, since the two were always set and cleared
together. PathEvent::Suspect fires on that transition, and Recovered
fires once an ACK arrives that covers a packet sent at or after that
watermark.

The watermark matters because multipath QUIC lets an ACK for one path
be coalesced onto any other path's outgoing packet (PathAck names the
acked path explicitly, independent of the carrier path). A path that
has genuinely gone dead can still have older, honestly-delivered
packets whose ACK was pending and only goes out once some other path
becomes available; without the watermark such a late, pre-suspect ACK
would spuriously clear suspect on a path that will never carry
anything again.

path_stats() exposes the new PathStats::suspect for external path
selectors. The tokio-layer event dispatch now forwards both variants
to PathEvents subscribers (previously silently dropped, since no arm
existed for them).
2026-07-24 12:39:04 +02:00
Diva Martínez 5cf07f4830 deps: run cargo update and adjust deny.toml accordingly (#762)
## Description

Updates deps to latest and adjusts deny.toml entries accordingly. Pins
the aws-lc crates to the current version. New versions generate cryptic
errors

## Breaking Changes

n/a

## Notes & open questions

prompted by several dependabot commits from quinn that were not applied
in the latest sync.
These were not applied due to several reasons:
- Cherry picking `Cargo.lock` updates often gives wrong results.
`Cargo.lock` must always be generated by cargo itself.
- We still should keep our deps updated within compatible versions.

## Change checklist
- [x] Self-review.
- [x] This PR was created by a human that thought critically about the
      proposed change and wrote an as clear and concise description as
      they could.
- [x] This PR isn't slop, and is carefully crafted to do have the
      intented effect.
- [x] `cargo make` passes locally.
2026-07-22 22:37:41 +00:00
Floris Bruynooghe 8cae43aed1 chore: Run daily CI even two hours earlier (#767)
## Description

Currently they start finishing at around 9 CEST. Let's move them 2h
earlier.

## Breaking Changes

n/a

## Notes & open questions

n/a

## Change checklist

- [x] Self-review.
- [x] This PR was created by a human that thought critically about the
      proposed change and wrote an as clear and concise description as
      they could.
- [x] This PR isn't slop, and is carefully crafted to do have the
      intented effect.
- [x] `cargo make` passes locally.
2026-07-21 14:34:26 +00:00
Diva Martínez c31c53ee0d sane CHANGELOG (#766)
fix changelog
2026-07-20 19:54:00 +00:00
Diva Martínez 7cd89bfbd7 restore changelog 2026-07-20 14:36:44 -05:00
“ramfox” 92a164ec47 chore: Release noq-proto-v1.1.0 noq-udp-v1.1.0 noq-v1.1.0 2026-07-20 14:22:23 -04:00
“ramfox” 474d034949 chore: update proto and udp dependency versions in noq. 2026-07-20 14:18:23 -04:00
“ramfox” 14853b4d29 chore: remove version number from noq dependency in the docs/book 2026-07-20 13:37:43 -04:00
Diva Martínez 193b807957 chore: improve CONTRIBUTING.md (#761)
## Description

Updates `CONTRIBUTING.md` to include some basic guidance to new
contributors
and instructions for maintainers for syncing quinn

## Breaking Changes

n/a

## Notes & open questions

Not meant to be super extensive. We could add more as we find what works
best
for this repo

## Change checklist
<!-- Remove any that are not relevant. -->
- [x] Self-review.
- [x] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
- [x] This PR was created by a human that thought critically about the
      proposed change and wrote an as clear and concise description as
      they could.
- [x] This PR isn't slop, and is carefully crafted to do have the
      intented effect.
- [x] `cargo make` passes locally.
2026-07-20 09:18:59 +00:00
Floris Bruynooghe 603c5e64cd fix(udp): log sendmsg errors on debug (#759)
## Description

Because of dualstack hosts that can be on IPv4-only networks getting
errors is very normal. It is a bit strange to emit full on warnings
for these. Telling folks that they just shouldn't be trying to connect
to such an unreachable hosts is also a bit strange. Simply trying this
is the normal thing to do.

Fixes https://github.com/n0-computer/iroh/issues/4345

## Breaking Changes

n/a

## Notes & open questions

It feels a bit odd, but I'm like 99% sure this is the right thing to do.

## Change checklist

- [x] Self-review.
- [x] This PR was created by a human that thought critically about the
      proposed change and wrote an as clear and concise description as
      they could.
- [x] This PR isn't slop, and is carefully crafted to do have the
      intented effect.
- [x] `cargo make` passes locally.
2026-07-17 20:26:56 +00:00
Diva Martínez 2e71727994 Merge commit '92cd707c9' into quinn-integration-july 2026-07-17 08:44:56 -05:00
syszery f165c03e99 fix(noq): handle overdue timers without polling the async timer
drive_timer() used AsyncTimer::poll() to determine whether a protocol
deadline had elapsed. Under Tokio's cooperative task budget,
Sleep::poll() may return Poll::Pending for an already-expired deadline
once the task's budget is exhausted, which can happen when
process_conn_events() drains a busy channel.

As a result, handle_timeout() is not called even though the deadline has
already elapsed. For QUIC, timers such as PTO, loss detection, and idle
timeouts are correctness-critical and should not be deferred to a later
scheduling round.

Fix this by checking runtime.now() >= deadline before consulting the
async timer. The clock is not subject to cooperative budgeting. The
timer remains responsible only for registering a wakeup when the
deadline lies in the future.

(cherry picked from commit 76020ba4ab)
2026-07-17 08:43:32 -05:00
syszery ef3fce8327 refactor(noq): use let-else in drive_timer
(cherry picked from commit 485f9b65fa)
2026-07-17 08:43:32 -05:00
Dmitry Adamushka f2968cf886 fix(proto): drop Initials silently when saturated
When the `max_incoming` queue is full (or CIDs are exhausted), quinn
replied to each Initial with CONNECTION_REFUSED. Building that reply
derives the packet's initial keys, which is computationally expensive.
A flood of Initials then forces the endpoint's packet-processing task
to do per-Initial crypto work, leaving it less time for legitimate
packets and degrading already-established connections.

(cherry picked from commit d4fc3efd5e)
2026-07-17 08:43:32 -05:00
dependabot[bot] 2e010a72a1 deps: bump libfuzzer-sys to 0.4.13
Bumps [libfuzzer-sys](https://github.com/rust-fuzz/libfuzzer) to 0.4.13.
- [Changelog](https://github.com/rust-fuzz/libfuzzer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-fuzz/libfuzzer/compare/0.4.10...0.4.13)

---
updated-dependencies:
- dependency-name: libfuzzer-sys
  dependency-version: 0.4.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 00b4b7493f)
2026-07-17 08:43:32 -05:00
Fabien Savy ba90d786a3 fix(proto): Use binary search in ArrayRangeSet
(cherry picked from commit 00cc7c4694)
2026-07-17 08:43:31 -05:00
Thomas Habets a17cb24292 feat(proto): Make Connection::poll_timeout immutable
(cherry picked from commit cb6ac60c86)
2026-07-17 08:43:31 -05:00
syszery b454d1799f feat(udp): implement kernel receive timestamps on Linux/Android
Enable SO_TIMESTAMPNS on Linux and Android, parse SCM_TIMESTAMPNS
ancillary messages, and expose timestamps via RecvMeta::timestamp.

(cherry picked from commit 9849790f02)
2026-07-17 08:43:31 -05:00
zerox80 1e8a5a9963 fix(proto): Reject DATAGRAMs larger than the send buffer
(cherry picked from commit c50f83bc4f)
2026-07-17 08:43:31 -05:00
zerox80 5bdd94493c Account for new DATAGRAMs in send buffer pruning
(cherry picked from commit 88c4e96d11)
2026-07-17 08:43:31 -05:00
zerox80 445bc4a924 Extract DATAGRAM send buffer space check
(cherry picked from commit 107b6ef5e0)
2026-07-17 08:43:31 -05:00
zerox80 4206142b80 Move DATAGRAM send buffer pruning into helper
(cherry picked from commit 8da45f49af)
2026-07-17 08:43:31 -05:00
zerox80 24eae4cf73 Bind DATAGRAM send buffer size locally
(cherry picked from commit 7b497af351)
2026-07-17 08:43:31 -05:00
dependabot[bot] a2db989f82 deps: bump codecov/codecov-action from 5 to 7
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5 to 7.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v5...v7)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 81c0363fac)
2026-07-17 08:43:31 -05:00
Dirkjan Ochtman 34530a8238 chore: Warn for unused_qualifications
(cherry picked from commit 531b6dd347)
2026-07-17 08:43:31 -05:00
Dirkjan Ochtman 2cc4e3f25b refactor(udp): extract apple_fast module
(cherry picked from commit 517028f4bd)
2026-07-17 08:43:31 -05:00
Dirkjan Ochtman 0fcc14bc18 refactor(udp): extract linux module
(cherry picked from commit 35ba3c4511)
2026-07-17 08:43:31 -05:00
Heiko ab91554446 fix(readme): Use correct crates.io badge link in README.md (#756)
Co-authored-by: Floris Bruynooghe <flub@n0.computer>
2026-07-17 13:10:42 +00:00
Floris Bruynooghe b57068277c feat(proto): use path idle timeout for validation when opening a new path (#721)
## Description

When we open a new path we send a path challenge, if that is lost
it is retried using the normal PTO schedule for tail-loss probes.
However the opening of the entire path was only tried for 3 * PTO,
which does only leave time for 2 retries. This makes opening a path
much more brittle wrt to packet loss than establishing a new
connection.

Instead this changes this to use the same mechanism to abandon a path
as when abandoning opening a new connection: keep sending tail-loss
probes, in this case path challenges, until the interval between the
tail-loss probes is larger than the path idle timeout. At which point
the normal idle timer will fire and abandon the path.

This removes the need for a separate timer to abort validation
of a path. It also removes a user-visible event as there is one less
reason a path can be abandoned for.

Another nice effect is that the poll_transmit no longer has to
figure out why an on-path path challenge is being sent in order to
set the right timer. It only has to arm the challenge PTO.

Fixes #686
Fixes #687 

## Breaking Changes

none

## Notes & open questions

This replaces 3 tests with one new one. I believe this together with
the open_path_validation_fails_* tests ensures the timers are set as
intended. The previous manual triggering of path challenges had a very
tight coupling between the code under test and how to trigger it. So
much that I felt directly adopting it would just be re-implementing
the same logic again.

The new test opens a new path and ensures lost challenges are reset
appropriately, which is exactly what needs to be tested. On an
existing path we never send new challenges, so those tests were very
artificial.

## Change checklist

- [x] Self-review.
- [x] Tests if relevant.
2026-07-17 10:11:17 +00:00
Philipp Krüger 5a60897ac4 chore(deps): Update cfg_aliases, remove unnecessary #[allow]s (#757)
## Description

A fix was merged, nightly shouldn't complain anymore.

## Breaking Changes

None


## Change checklist

- [x] Self-review.
- [x] This PR was created by a human that thought critically about the
      proposed change and wrote an as clear and concise description as
      they could.
- [x] This PR isn't slop, and is carefully crafted to do have the
      intented effect.
- [x] `cargo make` passes locally.
2026-07-17 09:44:36 +00:00
Floris Bruynooghe 403ce63073 ci: Run daily CI jobs 2 hours earlier (#758)
## Description

We have a lot of these jobs running way to long into the Europe
day. 04:00 UTC is 23:00 in the latest dev timezone so should be fine.

## Breaking Changes

n/a

## Notes & open questions

n/a

## Change checklist

- [x] Self-review.
- [x] This PR was created by a human that thought critically about the
      proposed change and wrote an as clear and concise description as
      they could.
- [x] This PR isn't slop, and is carefully crafted to do have the
      intented effect.
- [x] `cargo make` passes locally.
2026-07-17 09:29:23 +00:00
Philipp Krüger 0a445ddf82 fix(proto): Fix coalescing loop to avoid coalescing in Initial space (#747)
## Description

- Adds a regression test that triggers the `debug_assert!(max_size >=
min_size);` in `packet_builder.rs`
- Fixes the coalescing logic in `poll_transmit_path_space` to not exit
the loop & function to go to the next space when coalescing.
- Adds a bunch of useful `trace!` logs to see what the server is doing
in response.

## Breaking Changes

None

## Notes & open questions

A bit more on what was going on:
There are two loops for building datagrams: `poll_transmit_on_path`,
which goes over `Initial`, `Handshake` and `Data`, as well as
`poll_transmit_path_space`, which loops *within* the same space to
produce *separate* datagrams (e.g. for producing multiple loss probes as
a GSO batch).
The regression test generated a situation where two things were true at
the same: The `Initial` space wants to send a small `PATH_ACK` (nothing
else), and the `Handshake` space wants to send some `CRYPTO`.
Inside `poll_transmit_path_space` when we were checking for coalescing,
we call `self.has_pending_packet`, which iterates through all spaces
starting at `Initial`. It's false for `Initial`, but ends up being true
for `Handshake`, because that has `CRYPTO` pending.
However, we then keep on looping inside `poll_transmit_path_space`,
creating packets again and again in the same `space_id = Initial`,
instead of exiting out of the loop to the next space.
Eventually we fill the datagram with enough packets such that the
`debug_assert!(max_size >= min_size);` in `packet_builder.rs` triggers,
because it doesn't take into account the retry tokens in the QUIC header
for `Initial` packets (which I think it shouldn't do? because we should
never be coalescing these anyways.).

## Change checklist

- [x] Self-review.
- [x] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
- [x] Tests if relevant.
- [x] All breaking changes documented.
2026-07-16 16:15:59 +00:00
Philipp Krüger 22fbed2ffa refactor(proto): Make state.rs handle emitting events instead of callers (#753)
## Description

Follow-up from #748 
- Refactors how `Draining` and `Drained` endpoint events are emitted:
They're now handled within state.rs.
- `move_to_draining` and `move_to_drained` are now passed `&mut
self.endpoint_events`.

This is a pure refactor without behavioral changes.

## Breaking Changes

None

## Change checklist

- [x] Self-review.
- [x] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
2026-07-16 14:29:16 +00:00
Floris Bruynooghe b6b47f148d chore: add more guidance on llm use (#752)
## Description

Copied and adjusted from iroh.

## Breaking Changes

n/a

## Notes & open questions

Move the `cargo make` to a checkbox might be a bit harsh, but honestly
I more or less am in that habit already so probably ok.

## Change checklist

- [x] Self-review.
2026-07-16 12:59:22 +00:00
Philipp Krüger 883ca63fa9 fix(proto): Avoid double-emitting Draining event, causing an active_connections underflow (#748)
## Description

- Fixes a bug where the `Draining` event was emitted twice when a
stateless reset token was duplicated and received twice
- Adds a regression test for the above scenario

This is one of those bugs that triggers an underflow in
`active_connections` in noq.

## Breaking Changes

None

## Notes & open questions

I'm still investigating whether there are further such cases.

## Change checklist

- [x] Self-review.
- [x] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
- [x] Tests if relevant.
- [x] All breaking changes documented.
2026-07-16 12:28:55 +00:00
Asmir Avdicevic d0456ce2c7 chore(ci): fix docs cleanup job (#751)
## Description

Sets the correct user config for the action (we never ported this from
iroh) and lands some fixes to the script (numerical instead of lexical
sort, plus avoids negative head counts)

## Breaking Changes

<!-- Optional, if there are any breaking changes document them,
including how to migrate older code. -->

## Notes & open questions

<!-- Any notes, remarks or open questions you have to make about the -->
<!-- PR. -->

## Change checklist
<!-- Remove any that are not relevant. -->
- [ ] Self-review.
- [ ] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
- [ ] Tests if relevant.
- [ ] All breaking changes documented.

<!--
tip:
Run `cargo make` in the workspace root to check many light-weight CI
steps locally.
-->
2026-07-14 11:50:26 +00:00
Floris Bruynooghe 966398681f chore: improve semver checks for stable releases (#734)
## Description

This updates semver checks with the following behaviour:

- The baseline for the check is now the latest published release on
  crates.io

- If you make a semver-breaking change you must also bump the package
  version number so that the semver check will pass. Because we like
  to bump the versions of all crates at the same time you can not use
  pre-releases since cargo does not allow mixing those and the iroh
  patchbay tests has 2nd-level dependencies on noq-udp (via netwatch).

- Adding deprecated items is allowed in minor version bumps, matching
  https://semver.org/#how-should-i-handle-deprecating-functionality

- Bump noq-proto version because we previously added deprecations.

- Now the baseline is somewhat stable, enable caching.


## Breaking Changes

none

## Notes & open questions

I tested this first by not bumping the noq-proto version number and it
fails in that case. Which is due to #725.

Once this is merged I will make the semver check required in noq.

The version bumping required to make semver-checks pass could be a bit
annoying. It will also make patching iroh for noq a little bit harder.
As shown by what the patchbay check has to do now. I'm tempted to think
for now that this is worth it, but happy to think about how to tweak
this as we gain experience.

OTOH having to bump to the right version means that come to a release we
do know what the next version should be. Which is probably good.

## Change checklist

- [x] Self-review.
2026-07-13 16:40:27 +00:00
Floris Bruynooghe 21eea63fbc chore: Update for rust 1.97 (#745)
## Description

This uses the new CARGO_BUILD_WARNINGS in Makefile.toml so that it no
longer needs to invalidate all of rust's cache for -Dwarnings.

The code changes are new clippy fixes.

## Breaking Changes

none

## Notes & open questions

We're forcing contributors to get the last rust, but that's not that
bad I think. And cargo-make is kind of still optional.

## Change checklist

- [x] Self-review.
2026-07-10 09:10:10 +00:00
Philipp Krüger 41cbdbe26d test(proto): Implement bandwidth-limited routing (#720)
## Description

- Refactors the `RoutingDecision::Deliver` case to give it a `recv_time:
Instant` field. This allows `Routing` to decide when to deliver packets.
- Adds a `now: Instant` parameter to `Routing::route_client_to_server`
and `Routing::route_server_to_client` to make it possible for it to
compute the correct `RoutingDecision::recv_time`
- Adds `Routing::set_latency` to set the one-way-latency that `Routing`
now owns
- Adds a `BwLimitedRouting` routing implementation that implements a
queue that delays packets the more packets are queued and tail-drops
packets at a certain max queue length.
- Adds a `throughput` test as a quick way of testing noq-proto and its
congestion control against `BwLimitedRouting`.

## Breaking Changes

None. Test changes only.

## Notes & open questions

Started this work because it might be really useful in catching
regressions in congestion control, and to prepare work for when we send
on multiple paths simultaneously.

We can now generate neat pictures from noq-proto itself!
<img width="3750" height="1639" alt="image"
src="https://github.com/user-attachments/assets/d6e02727-40e5-42e3-b72a-2b528b7de9ea"
/>

The qlog file for this is generated in 0.2 seconds on my machine, even
though it is a simulated 10MB transfer over a 1MB/s connection, so this
simulates ~10s of actual time.
The other neat thing about it is that it is *fairly* deterministic.
There's still some sources of randomness in noq, but all of the
"measured" transfer speeds fall into a 1% range.

## Change checklist

- [x] Self-review.
- [x] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
- [x] Tests if relevant.
2026-07-09 07:20:24 +00:00
Philipp Krüger bbfd02472c chore(proto): Demote error! log to debug! log (#741)
## Description

Demotes this `error!` log to a `debug!` log instead.
Although we don't *expect* this situation to happen, it's benign when it
*does* happen, it just wastes some cycles and indicates that we have not
upheld some weak invariants somewhere.

## Breaking Changes

None

## Notes & open questions

Could also change it to a `warn!` log instead, but IMO even that is a
bit too much. There's nothing the user can do about this and it doesn't
really indicate that something dangerous is going on to be "warned"
about. The system is left in a good state and immediately heals on its
own.

## Change checklist

- [x] Self-review.
2026-07-08 09:48:45 +00:00
dignifiedquire a2b5572dce chore: record quinn integration up to 3ca0ff137 (#739) 2026-07-08 10:47:40 +02:00
dignifiedquire 9573207b66 chore(noq-udp): remove orphaned apple_fast/linux modules 2026-07-08 10:47:40 +02:00
Diva Martínez 5eb6120430 fix merge 2026-07-07 21:30:58 -05:00
Dirkjan Ochtman db4ae654cb refactor(udp): extract apple_fast module 2026-07-03 19:18:37 -05:00
Dirkjan Ochtman aa95f97927 refactor(udp): extract linux module 2026-07-03 18:51:16 -05:00
Dirkjan Ochtman f14b1b4521 style(udp): move CMSG_LEN to cmsg::LEN 2026-07-03 17:50:55 -05:00
Dirkjan Ochtman fc6b02ba72 style(udp): move msghdr_x and IpTosTy definitions down 2026-07-03 14:21:25 -05:00
Dirkjan Ochtman 141181495b docs(udp): clean up docstrings
For consistent punctuation and concise first lines.

Adapted to noq, which uses standard doc norms with final period on every
sentence.
2026-07-03 11:13:14 -05:00
Dirkjan Ochtman 4586890ef8 docs(proto): tweak Window docstrings 2026-07-03 10:14:02 -05:00