fn persistent_congestion()

in quic/s2n-quic-transport/src/recovery/manager/tests.rs [2191:2366]


fn persistent_congestion() {
    //= https://www.rfc-editor.org/rfc/rfc9002#section-7.6.2
    //= type=test
    //# A sender that does not have state for all packet
    //# number spaces or an implementation that cannot compare send times
    //# across packet number spaces MAY use state for just the packet number
    //# space that was acknowledged.
    let space = PacketNumberSpace::ApplicationData;
    let mut manager = ServerManager::new(space);
    let mut path_manager = helper_generate_path_manager(Duration::from_millis(10));
    let ecn = ExplicitCongestionNotification::default();
    let mut context = MockContext::new(&mut path_manager);
    let mut publisher = Publisher::snapshot();

    let time_zero = time::now() + Duration::from_secs(10);
    // The RFC doesn't mention it, but it is implied that the first RTT sample has already
    // been received when this example begins, otherwise packet #2 would not be considered
    // part of the persistent congestion period.
    context.path_mut().rtt_estimator.update_rtt(
        Duration::from_millis(10),
        Duration::from_millis(600),
        time::now(),
        true,
        space,
    );

    let mut outcome = transmission::Outcome {
        ack_elicitation: AckElicitation::Eliciting,
        is_congestion_controlled: true,
        bytes_sent: 1,
        bytes_progressed: 0,
    };

    // t=0: Send packet #1 (app data)
    manager.on_packet_sent(
        space.new_packet_number(VarInt::from_u8(1)),
        outcome,
        time_zero,
        ecn,
        transmission::Mode::Normal,
        None,
        &mut context,
        &mut publisher,
    );

    // t=1: Send packet #2 (app data)
    manager.on_packet_sent(
        space.new_packet_number(VarInt::from_u8(2)),
        outcome,
        time_zero + Duration::from_secs(1),
        ecn,
        transmission::Mode::Normal,
        None,
        &mut context,
        &mut publisher,
    );

    // t=1.2: Recv acknowledgement of #1
    ack_packets(
        1..=1,
        time_zero + Duration::from_millis(1200),
        &mut context,
        &mut manager,
        None,
        &mut publisher,
    );

    // t=2-6: Send packets #3 - #7 (app data)
    // These packets are NonEliciting, which are allowed to be part of a Persistent Congestion Period
    // as long as they are not the start or end of the period.
    outcome.ack_elicitation = AckElicitation::NonEliciting;
    for t in 2..=6 {
        manager.on_packet_sent(
            space.new_packet_number(VarInt::from_u8(t + 1)),
            outcome,
            time_zero + Duration::from_secs(t.into()),
            ecn,
            transmission::Mode::Normal,
            None,
            &mut context,
            &mut publisher,
        );
    }
    outcome.ack_elicitation = AckElicitation::Eliciting;

    // t=8: Send packet #8 (PTO 1)
    manager.on_packet_sent(
        space.new_packet_number(VarInt::from_u8(8)),
        outcome,
        time_zero + Duration::from_secs(8),
        ecn,
        transmission::Mode::Normal,
        None,
        &mut context,
        &mut publisher,
    );

    // t=12: Send packet #9 (PTO 2)
    manager.on_packet_sent(
        space.new_packet_number(VarInt::from_u8(9)),
        outcome,
        time_zero + Duration::from_secs(12),
        ecn,
        transmission::Mode::Normal,
        None,
        &mut context,
        &mut publisher,
    );

    // t=12.2: Recv acknowledgement of #9
    ack_packets(
        9..=9,
        time_zero + Duration::from_millis(12200),
        &mut context,
        &mut manager,
        None,
        &mut publisher,
    );

    //= https://www.rfc-editor.org/rfc/rfc9002#section-7.6.3
    //# Packets 2 through 8 are declared lost when the acknowledgment for
    //# packet 9 is received at "t = 12.2".
    assert_eq!(7, context.on_packet_loss_count);

    //= https://www.rfc-editor.org/rfc/rfc9002#section-7.6.3
    //# The congestion period is calculated as the time between the oldest
    //# and newest lost packets: "8 - 1 = 7".
    assert!(
        context
            .path()
            .rtt_estimator
            .persistent_congestion_threshold()
            < Duration::from_secs(7)
    );
    assert_eq!(
        Some(true),
        context.path().congestion_controller.persistent_congestion
    );
    assert_eq!(context.path().rtt_estimator.first_rtt_sample(), None);
    assert_eq!(1, context.path().congestion_controller.loss_bursts);

    // t=20: Send packet #10
    manager.on_packet_sent(
        space.new_packet_number(VarInt::from_u8(10)),
        outcome,
        time_zero + Duration::from_secs(20),
        ecn,
        transmission::Mode::Normal,
        None,
        &mut context,
        &mut publisher,
    );

    // t=21: Recv acknowledgement of #10
    ack_packets(
        10..=10,
        time_zero + Duration::from_secs(21),
        &mut context,
        &mut manager,
        None,
        &mut publisher,
    );

    //= https://www.rfc-editor.org/rfc/rfc9002#section-5.2
    //= type=test
    //# Endpoints SHOULD set the min_rtt to the newest RTT sample after
    //# persistent congestion is established.
    assert_eq!(
        context.path().rtt_estimator.min_rtt(),
        Duration::from_secs(1)
    );
    assert_eq!(
        context.path().rtt_estimator.smoothed_rtt(),
        Duration::from_secs(1)
    );
}