Subject: Retire Connection ID requirements

From: Martin Duke <[email-masked]>
Date: Wed, 18 Mar 2020 13:30:55 -0700

In Sec 19.15 it sayeth:
An endpoint that receives a NEW_CONNECTION_ID frame with a sequence number
smaller than the Retire Prior To field of a previously received
NEW_CONNECTION_ID frame MUST immediately send a corresponding
RETIRE_CONNECTION_ID frame that retires the newly received connection ID.

We're trying to do a lightweight implementation of the CID handling that
doesn't require potentially large amounts of state to keep track of
long-retired CIDs. Without diving deeply in the details, it's annoying to
have to do this for sequence numbers where we *know* the RCID has already
been acknowledged. We have three uncomfortable choices in dour design.
1) Add a bunch more state to deal with the case where the client is doing
something malicious or stupid
2) Violate the spec; or
3) Send a potentially large storm of RCID frames (if the sequence number is
well below the lowest active one)

I personally don't see the purpose of this requirement at all. I MUST send
RCID for everything below retire-prior-to, whether or not I've seen the
NCID for it. This RCID is ack-eliciting and retransmitted as needed. What
service am I providing the peer by sending it an additional time, if the
peer has acknowledged receipt of the RCID?

---

From: Mikkel Fahnøe Jørgensen <[email-masked]>
Date: Wed, 18 Mar 2020 13:39:55 -0700

Yeah, I also found this “immediately” a bit odd. I would rather do that
expediently, but not immediately, similar to how ACK works.

Kind Regards,
Mikkel Fahnøe Jørgensen

On 18 March 2020 at 21.31.32, Martin Duke ([email-masked]) wrote:

In Sec 19.15 it sayeth:

---

From: Martin Duke <[email-masked]>
Date: Wed, 18 Mar 2020 13:43:47 -0700

I'm going in the other direction in time. When I get the retire-prior-to
I'm retiring the sequence number even if I haven't gotten the corresponding
NCID. If that RCID has been acked, I shouldn't have to tell the client
again.

As I read the spec, the behavior I've described is not allowed.

On Wed, Mar 18, 2020 at 1:39 PM Mikkel Fahnøe Jørgensen <[email-masked]>
wrote:

> 3) Send a potentially large storm of RCID frames (if the sequence number
> is well below the lowest active one)
>

---

From: Eric Kinnear <[email-masked]>
Date: Wed, 18 Mar 2020 13:59:20 -0700

Isn’t this only acted upon in the event that a peer attempts to send you a NCID frame that it “shouldn’t” send? 
That shouldn’t require any state beyond knowing the highest Retire Prior To value that you’ve received, and when you get an invalid NCID you don’t save it anywhere, you just send RCID (effectively NACK-ing it).

We could argue whether that should just be a flat protocol violation and how that would potentially have interesting effects due to reordering of packets, but I’m not sure I’m understanding the large amounts of state required for this?

Thanks,
Eric

> On Mar 18, 2020, at 1:43 PM, Martin Duke <[email-masked]> wrote:
> 
> I'm going in the other direction in time. When I get the retire-prior-to I'm retiring the sequence number even if I haven't gotten the corresponding NCID. If that RCID has been acked, I shouldn't have to tell the client again.
> 
> On Wed, Mar 18, 2020 at 1:39 PM Mikkel Fahnøe Jørgensen <[email-masked] <mailto:[email-masked]>> wrote:
> Yeah, I also found this “immediately” a bit odd. I would rather do that expediently, but not immediately, similar to how ACK works.
> 
> Kind Regards,
> Mikkel Fahnøe Jørgensen
> 
> 
> On 18 March 2020 at 21.31.32, Martin Duke ([email-masked] <mailto:[email-masked]>) wrote:
> 
>> In Sec 19.15 it sayeth:
>> An endpoint that receives a NEW_CONNECTION_ID frame with a sequence number smaller than the Retire Prior To field of a previously received NEW_CONNECTION_ID frame MUST immediately send a corresponding RETIRE_CONNECTION_ID frame that retires the newly received connection ID. 
>> 
>> We're trying to do a lightweight implementation of the CID handling that doesn't require potentially large amounts of state to keep track of long-retired CIDs. Without diving deeply in the details, it's annoying to have to do this for sequence numbers where we *know* the RCID has already been acknowledged. We have three uncomfortable choices in dour design.
>> 1) Add a bunch more state to deal with the case where the client is doing something malicious or stupid
>> 2) Violate the spec; or
>> 3) Send a potentially large storm of RCID frames (if the sequence number is well below the lowest active one)
>> 
>> I personally don't see the purpose of this requirement at all. I MUST send RCID for everything below retire-prior-to, whether or not I've seen the NCID for it. This RCID is ack-eliciting and retransmitted as needed. What service am I providing the peer by sending it an additional time, if the peer has acknowledged receipt of the RCID?

---

From: Martin Duke <[email-masked]>
Date: Wed, 18 Mar 2020 14:17:35 -0700

I might not be able to send a QUIC packet immediately because of congestion
control or rate pacing. I can't just send it, it has to be in the PCB.

I wouldn't say it's large amounts of state, but it's state that solely
exists to handle this dumb case. Otherwise I only need to keep track of the
window of sequence numbers between what's been acked and retire-prior-to.

On Wed, Mar 18, 2020 at 1:59 PM Eric Kinnear <[email-masked]> wrote:

> That shouldn’t require any state beyond knowing the highest Retire Prior
> To value that you’ve received, and when you get an invalid NCID you don’t
> save it anywhere, you just send RCID (effectively NACK-ing it).
>
> We could argue whether that should just be a flat protocol violation and
> how that would potentially have interesting effects due to reordering of
> packets, but I’m not sure I’m understanding the large amounts of state
> required for this?
>
> Thanks,
> Eric
>
>
> On Wed, Mar 18, 2020 at 1:39 PM Mikkel Fahnøe Jørgensen <
> [email-masked]> wrote:
>
>> An endpoint that receives a NEW_CONNECTION_ID frame with a sequence
>> number smaller than the Retire Prior To field of a previously received
>> I personally don't see the purpose of this requirement at all. I MUST
>> send RCID for everything below retire-prior-to, whether or not I've seen
>> the NCID for it. This RCID is ack-eliciting and retransmitted as needed.
>> What service am I providing the peer by sending it an additional time, if
>> the peer has acknowledged receipt of the RCID?
>>
>>
>

---

From: Dmitri Tikhonov <[email-masked]>
Date: Thu, 19 Mar 2020 08:40:32 -0400

Hi Martin,

On Wed, Mar 18, 2020 at 01:30:55PM -0700, Martin Duke wrote:
> I MUST send RCID for everything below retire-prior-to,
> whether or not I've seen the NCID for it.
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I don't believe that's the requirement:  Why send an RCID frame
for a CID one has never seen or is no longer in possession of
(it's already been retired)?

  - Dmitri.

---

From: Martin Duke <[email-masked]>
Date: Thu, 19 Mar 2020 07:08:36 -0700

I don't think I stated that clearly. The spec is a little ambiguous on
whether unseen CIDs have to be retired; in fact, it probably is not doing
so. However, I'm arguing I should be allowed to retire them immediately and
then ignore subsequent NCIDs with those sequence numbers.

---

From: Dmitri Tikhonov <[email-masked]>
Date: Thu, 19 Mar 2020 10:31:19 -0400

I agree with ignoring subsequent NCID after a CID has been retired.

I don't understand what the alternative is.  In our code, once a
CID is retired, the connection no longer has a record of it.  There
is no way to retire a CID again.

---

From: Martin Duke <[email-masked]>
Date: Thu, 19 Mar 2020 07:45:43 -0700

I'm going to file an issue. Thanks