Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(transport/cc): don't reenter recovery #2409

Closed
wants to merge 1 commit into from

Conversation

mxinden
Copy link
Collaborator

@mxinden mxinden commented Feb 3, 2025

A NewReno sender enters a recovery period when it detects the loss of a packet or when the ECN-CE count reported by its peer increases. A sender that is already in a recovery period stays in it and does not reenter it.

https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.2

When in a transient state (i.e. State::RecoveryStart and State::PersistentCongestion) we return early, i.e. don't reenter recovery:

/// Handle a congestion event.
/// Returns true if this was a true congestion event.
fn on_congestion_event(&mut self, last_packet: &SentPacket, now: Instant) -> bool {
// Start a new congestion event if lost or ECN CE marked packet was sent
// after the start of the previous congestion recovery period.
if !self.after_recovery_start(last_packet) {
return false;
}

But when in State::Recovery, we do reenter Recovery, i.e. call self.cc_algorithm.reduce_cwnd:

self.set_state(State::RecoveryStart, now);

Thus in the following scenario we might reduce the cwnd twice in the same loss episode:

  1. Send packet A.
  2. Declare packet A as lost, reduce cwnd and transitioning into RecoveryStart.
  3. Send packet B and transitioning into Recovery.
  4. Declare packet B as lost and reduce cwnd a second time in the same loss epoch.

Test for #2408.

> A NewReno sender enters a recovery period when it detects the loss of
> a packet or when the ECN-CE count reported by its peer increases. A
> sender that is already in a recovery period stays in it and does not
> reenter it.

https://www.rfc-editor.org/rfc/rfc9002.html#section-7.3.2

When in a transient state (i.e. `State::RecoveryStart` and `State::PersistentCongestion`) we return early, i.e. don't reenter recovery:

https://github.com/mozilla/neqo/blob/6cdbc0c33197aaf3cfc6240bed9cb6681afcafc7/neqo-transport/src/cc/classic_cc.rs#L546-L553

But when in `State::Recovery`, as far as I can tell, we do reenter `Recovery`, i.e. call `self.cc_algorithm.reduce_cwnd`:

https://github.com/mozilla/neqo/blob/e3657305dcba2842f505d941e94d5a805a1f50aa/neqo-transport/src/cc/classic_cc.rs#L577

Thus in the following scenario we might reduce the cwnd twice in the same loss episode:

1. Send packet A.
2. Declare packet A as lost, reduce cwnd and transitioning into `RecoveryStart`.
3. Send packet B and transitioning into `Recovery`.
4. Declare packet B as lost, thus reduce cwnd a second time in the same loss epoch.
Copy link

github-actions bot commented Feb 3, 2025

Failed Interop Tests

QUIC Interop Runner, client vs. server, differences relative to 108fb8d.

neqo-latest as client

neqo-latest as server

All results

Succeeded Interop Tests

QUIC Interop Runner, client vs. server

neqo-latest as client

neqo-latest as server

Unsupported Interop Tests

QUIC Interop Runner, client vs. server

neqo-latest as client

neqo-latest as server

@mxinden
Copy link
Collaborator Author

mxinden commented Feb 3, 2025

Closing here, see #2408 (comment).

@mxinden mxinden closed this Feb 3, 2025
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