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

Use PTO to declare in-flight packets lost #1965

Merged
merged 17 commits into from Dec 27, 2018
Merged

Conversation

ianswett
Copy link
Contributor

@ianswett ianswett commented Nov 5, 2018

QUIC, unlike TCP, allows the connection to get into a situation where there could be packets in flight, and a connection could even be CWND limited, but there may not be any outstanding data to retransmit.

The suggested solution is to send a retransmittable frame.

QUIC, unlike TCP, allows the connection to get into a situation where there could be packets in flight, and a connection could even be CWND limited, but there may not be any outstanding data to retransmit.

The suggested solution is to send a retransmittable frame.
Copy link
Contributor

@martinduke martinduke left a comment

Choose a reason for hiding this comment

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

I agree with the concept, though I have some problems with the explanatory text.

One zoom-out question about TLP in QUIC: If there's a tail loss, you'll have to wait for an entire delayed-ack timeout to send, wait at worst for another DAT to get the ack, then a reordering timeout to declare the intervening packets lost. How does that compare to a plain old RTO?

@@ -418,6 +418,12 @@ used to send a probe into the network prior to establishing any packet loss,
prior unacknowledged packets SHOULD NOT be marked as lost when a TLP timer
expires.

If no new data or unacknowledged data is available to send, a retransmittable
frame SHOULD be sent. Sending a retransmittable frame ensures that any in
flight packets are acknowledged or declared lost in a timely manner,
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think TLP accelerates acknowledgment of in-flight pkts unless you happen to hit what the maximum number of delayed-acked pkts are.

So I would delete "acknowledged or"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, if you TLP, then you haven't received an ACK that contained any information about the in flight packets, because otherwise you'd fast or early retransmit them. So you have some number of in flight packets, and you don't know what their status is. It's possible the ACK was just lost, etc. So in that sense, it accelerates receiving an acknowledgement for them if they were in fact not lost.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yes, ack losses. You're right

If no new data or unacknowledged data is available to send, a retransmittable
frame SHOULD be sent. Sending a retransmittable frame ensures that any in
flight packets are acknowledged or declared lost in a timely manner,
potentially preventing a deadlock if all in flight packets contain no data
Copy link
Contributor

Choose a reason for hiding this comment

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

Delete everything after "deadlock."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I update the text right as you were reviewing, PTAL.

Copy link
Contributor

Choose a reason for hiding this comment

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

New data also prevents a deadlock.

Copy link
Contributor

@martinduke martinduke left a comment

Choose a reason for hiding this comment

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

D'oh! comments passed in flight.

@@ -418,6 +418,12 @@ used to send a probe into the network prior to establishing any packet loss,
prior unacknowledged packets SHOULD NOT be marked as lost when a TLP timer
expires.

If no new data or unacknowledged data is available to send, a retransmittable
frame SHOULD be sent. Sending a retransmittable frame ensures that any in
flight packets are acknowledged or declared lost in a timely manner.
Copy link
Contributor

Choose a reason for hiding this comment

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

"acknowledged or" remains problematic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

howso?

Copy link
Contributor

Choose a reason for hiding this comment

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

Never mind, see above.

frame SHOULD be sent. Sending a retransmittable frame ensures that any in
flight packets are acknowledged or declared lost in a timely manner.
Otherwise, a deadlock results if there is no available congestion window and
all in flight packets contain no data that can be retransmitted.
Copy link
Contributor

Choose a reason for hiding this comment

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

Hyphenate "in-flight" when used before the noun this way.

@ekr
Copy link
Collaborator

ekr commented Nov 5, 2018

I feel like maybe I don't understand this. It's titled "deadlock" but it looks to me like it's really just RTO. Am I misunderstanding?

@ianswett
Copy link
Contributor Author

ianswett commented Nov 5, 2018

Good question, @ekr

It's definitely a detail point, but I think the above approach is likely the ideal fix. But here's what I expect to happen now.

If the implementation stores some state saying "the tlp alarm fired, but I couldn't send anything, and I'll remember that in case there is some data I can send in the near future." then when there's new data, everything should be fixed, though you'll also only be able to send a single packet. And if that packet or the corresponding ACK is lost, it'll be another TLP before you can send a packet.

Alternately, an implementation could fire the alarm, realize it can't send anything, then not re-arm the alarm(since if it was re-armed, it would just fire immediately and you'd spin).

The second approach is a deadlock. The first one is just going to be very slow recovery. Both seem somewhat suboptimal.

There's another solution to this, which is to declare all in-flight packets lost. But that goes against the approach we use throughout QUIC loss recovery where we don't declare packets lost until a larger packet is acknowledged.

OT: @martinduke pointed out that this should be fixed for RTO as well, since it's possible between TLP and RTO(or between two RTOs) in-flight data is cancelled, so now there's nothing to retransmit.

@@ -142,7 +142,7 @@ of frames contained in a packet affect recovery and congestion control logic:

* Packets that contain only ACK frames do not count toward congestion control
limits and are not considered in-flight. Note that this means PADDING frames
cause packets to contribute toward bytes in flight without directly causing an
cause packets to contribute toward bytes in-flight without directly causing an
acknowledgment to be sent.
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 was agreed to spell this "bytes in flight" but I could be wrong.

Copy link
Contributor

@mikkelfj mikkelfj Nov 5, 2018

Choose a reason for hiding this comment

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

If in-flight is used, I think other text needs to be updated also. The motivation for not using hyphen was the confusion with bytes_in_flight as a variable name.

Copy link
Contributor

Choose a reason for hiding this comment

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

"in-flight" when used as a compound modifier (in-flight packets, for example) should usually have a hyphen before the noun. Here, it's after the noun, so this wouldn't get one. See here, for example.

@maolson-msft
Copy link

Rather than adding a new paragraph to patch the hole, I'd update the description of what a "probe" packet is. Currently it's "a packet which is not subject to CC and which contains unsent data (if possible) or sent data (otherwise)."

I'd update this sentence and move it somewhere to apply to both TLP and RTO probes.

@nibanks
Copy link
Member

nibanks commented Nov 5, 2018

@ianswett do you have an example of a case where you have packets in flight but no outstanding data to retransmit? I was trying to come up with one but couldn't. In the case of a stream getting cancelled, you'd still have the RST_STREAM frame that needs to be sent.

@mikkelfj
Copy link
Contributor

mikkelfj commented Nov 5, 2018

@nibanks couldn't RST happen async separate from the pipeline of schedule transmissions. More generally, data might exist, but not (yet) in the low level tranmissions system that deals with retransmission.

@nibanks
Copy link
Member

nibanks commented Nov 5, 2018

@mikkelfj that's really an implementation detail. For me, resetting a stream, queuing the RST_STREAM frame for delivery and removing the actual stream data for retransmission is an atomic operation.

@mikkelfj
Copy link
Contributor

mikkelfj commented Nov 5, 2018

@nibanks I agree, but because it is an implementation detail, the protocol cannot make general assumptions on how implementations work. Forcing an implemtation to operate atomically is not ideal.

EDIT: can->cannot in the above

@nibanks
Copy link
Member

nibanks commented Nov 5, 2018

@mikkelfj I totally agree. I was just trying to understand if there were any non-implementation specific scenarios where this could happen (in other words, does this apply to my implementation or can I ignore this bit of text).

@martinthomson martinthomson added design An issue that affects the design of the protocol; resolution requires consensus. -recovery labels Nov 13, 2018
@ianswett
Copy link
Contributor Author

Given if there is something to be sent, I don't think this is a deadlock, I'm inclined to close this PR, both because it's old and I'm not convinced it's a practical issue.

@martinduke
Copy link
Contributor

@nibanks The simplest way for this to happen is that the first TLP timeout resends some data, and then the original is acked. Thus we have an in-flight packet (the retransmission) but the actual application data is already gone from the send buffer.

The TLP timer will fire again, and there's nothing to send.

@ianswett There are still some problems with the new text. The main practical impact is that we will delay declaring the last packet lost, meaning we won't free up the flightsize or execute a congestion response as quickly. I'm having a little trouble reasoning about the full implications of this for new data.

@ianswett ianswett changed the title Prevent an unlikely deadlock Use PTO to declare in-flight packets lost Dec 19, 2018
@ianswett
Copy link
Contributor Author

I updated this to clarify it's not really a deadlock, but suggest what should be done on PTO in this case: either send an ack-eliciting packet or declare the packets lost.

@martinduke
Copy link
Contributor

For the record, I believe this was a potential deadlock:
Pkt 5 outstanding, flightsize = cwnd = 1 MSS
TLP timeout, resend in pkt 6 (flightsize = 2 MSS)
Pkt 5 acked, no data in send queue (flightsize = cwnd = 1 MSS)
TLP timeout, nothing to send, no new timers.
If new data arrives, there is no way to progress.

@ianswett
Copy link
Contributor Author

Previously, Jana said you should store that the PTO had fired and there was nothing to send, so when data does arrive to send, you can immediately send it. But that wasn't explicitly documented anywhere to my knowledge.

Copy link
Contributor

@janaiyengar janaiyengar left a comment

Choose a reason for hiding this comment

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

I think @martinduke is right that we should handle this particular case, and I'm fine with the resolution in this PR. A few comments (and the text is in teh wrong place)


A sender may not know that a packet being sent is a tail packet. Consequently,
a sender may have to arm or adjust the TLP timer on every sent retransmittable
packet.
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect this para is leftover and should be removed.

draft-ietf-quic-recovery.md Outdated Show resolved Hide resolved
@@ -421,6 +421,15 @@ control and loss recovery state, including resetting any pending timers. Either
packet indicates that the Initial was received but not processed. Neither
packet can be treated as an acknowledgment for the Initial.

If no new data or unacknowledged data is available to send, an ack-eliciting
Copy link
Contributor

Choose a reason for hiding this comment

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

This new text should be further below in the #pto section.

janaiyengar and others added 4 commits December 19, 2018 19:06
Co-Authored-By: ianswett <ianswett@users.noreply.github.com>
A proposal: I think I prefer to mark things as lost instead of suggesting that a sender SHOULD send something when there's really nothing to be sent.  I was starting to rephrase your PR to say "SHOULD send ack-eliciting packet, but MAY mark as lost", and I needed to explain how a sender makes this choice. I realized that if it's been long enough (PTO is long enough) and there's nothing left to send, then maybe it is sensible to mark anything pending as lost. So, I changed my suggestion to that, which is this PR (against your PR).
@janaiyengar
Copy link
Contributor

Hm. I started to think about how to rephrase a bit, which ended up leading to #2212. Take a look.

Copy link
Contributor

@janaiyengar janaiyengar left a comment

Choose a reason for hiding this comment

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

@martinduke : See if this resolves your concerns.

@ianswett
Copy link
Contributor Author

@martinduke Jana and I replaced my text with a version of his PR. We believe this solves the issue you point out as well.

@martinduke
Copy link
Contributor

I like this language a lot. Ship it!

@ianswett ianswett merged commit acf67af into master Dec 27, 2018
@martinthomson martinthomson deleted the ianswett-tlp-deadlock branch January 22, 2019 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-recovery design An issue that affects the design of the protocol; resolution requires consensus.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants