Draft: draft-ietf-quic-recovery

Commentary: Sending in multiple PN spaces on PTO is particularly useful when the peer only has receive keys for 1 pn space , and the you do n't know which . 
 ( deleted comment , because the initially mentioned problem was incorrect . the requirement to arm the PTO timer after the handshake finishes is in Section 5.2.2 ) 
 There 's some architectural inconsistency around the treatment of 1RTT PTOs at the end of the handshake . On the one hand , we are not supposed to set the PTO timer for 1RTT before the handshake is complete . This is to prevent us from retransmitting stuff the peer may not be able to process . On the other hand , we are supposed to arm the PTO timer when the handshake is confirmed . This is the point where we 're guaranteed that the peer has receive keys . So there is a weird gap between handshake complete and handshake confirmed where new 1RTT packets will arm the PTO , but outstanding  or 1RTT packets from before handshake complete will not have an active PTO timer . This is n't the end of the world -- the connection will recover -- but it does n't make any sense , and could result in either excessive PTO delays , or 1RTT probes that the peer ca n't decode . 
 can we get a status update ? 
 The PTO is always armed when there are bytes in flight(except when the loss timer is armed ) , it 's just a matter of what PN spaces it can be armed for at a given point in time . Once the connection is handshake complete , it 's immediately allowed to arm it for inflight 1 - RTT ack - eliciting packets . Re - reading the text , I could n't find anything explicitly calling out that the alarm may need to be recomputed and reset in the handshake confirmed case , though it is stated for discarding keys . As clarified in when the client is handshake complete but not confirmed , it is unsure whether the server has Handshake keys or ApplicationData keys , but it 's very unlikely to have both . As such , sending something ack - eliciting from both PN spaces is safest . 
 The packet number space that endpoint should send probe packet is determined by GetEarliestTimeAndSpace function . It chooses packet number space where the latest packet has earliest dispatch time . Suppose client sent 2 packets : Handshake(clienthandshake ) and Short packet(clientshort ) . Somehow it did n't get any ACK for them , on first PTO timeout , it resent Handshake ( client_handshake ) . This makes Short packet number space becomes the earliest packet number space and next PTO timeout , client sent Short probe packet assuming that IsHandshakeCompleted ( ) means handshake completion not handshake confirmation . I think it should instead send Handshake probe packet in this case . We have unified PTO timer and sending probe in alternate manner is a bit strange . 
 I agree that this is weird . It 's worse than you describe because the exponent on the intervals between Handshake packets is 4 , not 2 . We send probes ( just a PING ) when probing the short packet as recommended , so it is n't too , too bad , but it is also not that great . I looked into this in mozilla / neqo if people want more context . I did n't have the time to think through what the ideal solution might be . 
 As discussed in neqo issue thread , which packet number spaces should be chosen depends on the situation .  sends Initial and Handshake probes at the same time if server sees they are in - flight when PTO timer fires so that it can coalesce them and also handle the situation that client might drop Initial key . This is a deviation from the draft-27 . For the particular situation that this issue describes , I think client can just send Handshake probe packet . If server still has Handshake key , it will respond with Handshake packet . If not , then it will send HANDSHAKE_DONE frame in Short packet , and client confirms handshake completion . Sending Short probe with Handshake packet might reduce the time before client reacts the lost Short packet , but might be discarded if server does not have appropriate key . 
 In this case , I believe alternating is the right thing to do , because the server either has Handshake receive keys or 1 - RTT receive keys , and the client does n't know which . Because of HANDSHAKEDONE , the client will eventually complete the handshake and drop the Handshake PN space as long as the client 's Handshake packet(containing the finished ) gets to the server . However , this case is an excellent motivation for this text : This text was written prior to HANDSHAKEDONE , but I think there may be other reasons to use handshake complete and not confirmed in this case , so I would be very hesitant to change it without a lot of consideration . Is there a part of mozilla / neqo I should focus on ? The text talks a lot about packets being marked as lost when the PTO timer fires , which makes me very confused , since QUIC does n't mark packets as lost when the PTO fires . 
 Leaving aside that recommendation for the moment ( which I agree is close to mandatory ) , the experience is pretty poor if there is only one key . You just moved to a 4x exponent on the PTO timer rather than a 2x timer . I guess that 's why we have the recommendation . ( For reference , neqo tells the frame sending apparatus that it lost some data when a PTO timer fires . That causes those older frames to be sent again rather than trying to find fresh data to send . That 's on the principle that older data is more important . But that is n't relevant to this discussion . The main comment to look at is , which shows how the interleaving can be a little janky . ) I realize that we have n't reconciled this with the requirement not to arm the application data PTO when there are handshake / initial packets outstanding . That might limit this to the one case of interleaving Initial and Handshake . 
 Yes , you move to 4x instead of 2x , but it 's worth understanding what packets need to be lost for the 2x vs 4x to come into play . 1 ) The client 's Handshake packet is lost twice in a row . Not that unlikely , but it 's known the Client Finished blocks the server from processing 1 - RTT packets , so I think there 's an understanding of its importance . 2 ) ( case from this issue ) The client 's Handshake packet is delivered , but the ACK is lost so the client retransmits it then that packet is lost AND both the first HANDSHAKEDONE packet and its retransmission are lost . I 'm sure there are many other permutations of these , but the first case seems a lot more likely than the second case . In this case , the HANDSHAKEDONE does a nice job of mitigating some potential issues . 
 LGTM
Paragraph (version A):
In addition to sending data in the packet number space for which the
timer expired, the sender SHOULD send ack-eliciting packets from
other packet number spaces with in-flight data, coalescing packets if
possible.
Paragraph (version B):
In addition to sending data in the packet number space for which the
timer expired, the sender SHOULD send ack-eliciting packets from
other packet number spaces with in-flight data, coalescing packets if
possible.  This is particularly valuable when the server has both
Initial and Handshake data in-flight or the client has both Handshake
and ApplicationData in-flight, because the peer might only have
receive keys for one of the two packet number spaces.