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

split fast retransmit modes #1226

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 58 additions & 38 deletions draft-ietf-quic-recovery.md
Expand Up @@ -201,6 +201,21 @@ implemented in QUIC.

### Fast Retransmit

Fast retransmit can be run two different modes: packet number based and time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run in

based.

We derive this default from recommendations for TCP loss recovery {{?RFC5681}}
{{?RFC6675}}. It is possible for networks to exhibit higher degrees of
reordering, causing a sender to detect spurious losses. Making QUIC deal with
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would phrase it as "spuriously detect losses."

such networks is important open research, and implementers are encouraged to
explore this space. Detecting spurious losses leads to unnecessary
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spuriously detecting losses

retransmissions and may result in degraded performance due to the actions of
the congestion controller upon detecting loss. Implementers MAY use algorithms
developed for TCP, such as TCP-NCR {{?RFC4653}}, to improve QUIC's reordering
resilience, though care should be taken to map TCP specifics to QUIC correctly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth commenting that both modes could be run simultaneously, but the psuedocode only describes how to run one at once.


#### Packet number based Fast Retransmit

An unacknowledged packet is marked as lost when an acknowledgment is received
for a packet that was sent a threshold number of packets (kReorderingThreshold)
after the unacknowledged packet. Receipt of the ack indicates that a later
Expand All @@ -209,20 +224,19 @@ reordering of packets in the network.

The RECOMMENDED initial value for kReorderingThreshold is 3.

We derive this default from recommendations for TCP loss recovery {{?RFC5681}}
{{?RFC6675}}. It is possible for networks to exhibit higher degrees of
reordering, causing a sender to detect spurious losses. Detecting spurious
losses leads to unnecessary retransmissions and may result in degraded
performance due to the actions of the congestion controller upon detecting
loss. Implementers MAY use algorithms developed for TCP, such as TCP-NCR
{{?RFC4653}}, to improve QUIC's reordering resilience, though care should be
taken to map TCP specifics to QUIC correctly. Similarly, using time-based loss
detection to deal with reordering, such as in PR-TCP, should be more readily
usable in QUIC. Making QUIC deal with such networks is important open research,
and implementers are encouraged to explore this space.
#### Time-based Fast Retransmit

Using time-based loss detection to deal with reordering, such as in PR-TCP,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a reference to PR-TCP here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly would you link here?

should be more readily usable in QUIC. An unacknowledged packet is marked as
lost when an acknowledgment for a higher packet number is received, and the
packet was sent before(1 + kTimeReorderingFraction) * max(SRTT, latest_RTT).

### Early Retransmit

Early Retransmit is only used in packet number Fast Retransmit mode. Since
time-based Fast Retransmit already sets a timer there is no need to set an early
Retransmit timer.

Unacknowledged packets close to the tail may have fewer than
kReorderingThreshold retransmittable packets sent after them.
Loss of such packets cannot be detected via Fast Retransmit. To enable
Expand Down Expand Up @@ -467,11 +481,11 @@ kReorderingThreshold (default 3):
considers a packet lost.

kTimeReorderingFraction (default 1/8):
: Maximum reordering in time space before time based loss detection considers
: Maximum reordering in time space before time-based loss detection considers
a packet lost. In fraction of an RTT.

kUsingTimeLossDetection (default false):
: Whether time based loss detection is in use. If false, uses FACK style
: Whether time-based loss detection is in use. If false, uses FACK style
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is called FACK style here, but probably should be called "packet number based loss detection" for consistency? It may be worth referencing FACK above when describing packet number based loss detection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not familiar with FACK. Can you suggest something?

loss detection.

kMinTLPTimeout (default 10ms):
Expand Down Expand Up @@ -540,14 +554,6 @@ max_ack_delay:
Excludes ack delays for ack only packets and those that create an
RTT sample less than min_rtt.

reordering_threshold:
: The largest packet number gap between the largest acked
retransmittable packet and an unacknowledged
retransmittable packet before it is declared lost.

time_reordering_fraction:
: The reordering window as a fraction of max(smoothed_rtt, latest_rtt).

loss_time:
: The time at which the next packet will be considered lost based on early
transmit or exceeding the reordering window in time.
Expand All @@ -569,12 +575,6 @@ follows:
handshake_count = 0
tlp_count = 0
rto_count = 0
if (kUsingTimeLossDetection)
reordering_threshold = infinite
time_reordering_fraction = kTimeReorderingFraction
else:
reordering_threshold = kReorderingThreshold
time_reordering_fraction = infinite
loss_time = 0
smoothed_rtt = 0
rttvar = 0
Expand Down Expand Up @@ -725,9 +725,9 @@ sent, and then the RTO timer is set.

#### Early Retransmit Alarm

Early retransmit {{?RFC5827}} is implemented with a 1/4 RTT timer. It is
part of QUIC's time based loss detection, but is always enabled, even when
only packet reordering loss detection is enabled.
Early retransmit {{?RFC5827}} is only used when using Fast Retransmit in packet
number mode. It is implemented with a 1/4 RTT timer. It is part of QUIC's time

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems a bit confusing, i think we could say something like

``We expect to receive feedback about the sent packet within 1 RTT of the time_since_sent. Early retransmit is implemented by setting a (1 + 1/4) RTT timer since the time the packet is sent. ```

based loss detection.

#### Pseudocode

Expand Down Expand Up @@ -819,21 +819,18 @@ identical to other packets.

#### Pseudocode

DetectLostPackets takes one parameter, acked, which is the largest acked packet.
DetectLostPackets takes one parameter, largest_acked, which is the largest acked
packet.

Pseudocode for DetectLostPackets follows:
When detecting reordering in packet number space:

~~~
DetectLostPackets(largest_acked):
loss_time = 0
lost_packets = {}
delay_until_lost = infinite
if (kUsingTimeLossDetection):
delay_until_lost =
(1 + time_reordering_fraction) *
max(latest_rtt, smoothed_rtt)
else if (largest_acked.packet_number == largest_sent_packet):
// Early retransmit alarm.
// Early retransmit
if (largest_acked.packet_number == largest_sent_packet):
delay_until_lost = 5/4 * max(latest_rtt, smoothed_rtt)
foreach (unacked < largest_acked.packet_number):
time_since_sent = now() - unacked.time_sent
Expand All @@ -846,6 +843,29 @@ DetectLostPackets(largest_acked):
else if (loss_time == 0 && delay_until_lost != infinite):
loss_time = now() + delay_until_lost - time_since_sent

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this might be cleaner to split this up to the end of the loop.

it looks like the intention is to the early retransmit timer to be the loss time of the first packet not lost by packet ordering. It might be cleaner like

 last_unacked = largest_acked.packet_number
 foreach (unacked < largest_acked.packet_number):
     ....
     last_unacked = unacked
 if (last_unacked < largest_acked.packet_number) :
    lost_time = now() + delay_until_lost - sent_packets[last_unacked].time_since_sent

and similarly in the other one as well

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry i meant first_unacked.


// Inform the congestion controller of lost packets and
// lets it decide whether to retransmit immediately.
if (!lost_packets.empty())
OnPacketsLost(lost_packets)
~~~

When using time-based reordering detection:

~~~
DetectLostPackets(largest_acked):
loss_time = 0
lost_packets = {}
delay_until_lost =
(1 + kTimeReorderingFraction) * max(latest_rtt, smoothed_rtt)
foreach (unacked < largest_acked.packet_number):
time_since_sent = now() - unacked.time_sent
if (time_since_sent > delay_until_lost):
sent_packets.remove(unacked.packet_number)
if (!unacked.is_ack_only):
lost_packets.insert(unacked)
else if (loss_time == 0):
loss_time = now() + delay_until_lost - time_since_sent

// Inform the congestion controller of lost packets and
// lets it decide whether to retransmit immediately.
if (!lost_packets.empty()):
Expand Down