Hi all, In another thread, I was asked whether I thought I had gotten a complete list of issues, and I said it is hard to know when one is done realizing all the things one hasn't realized yet. Particularly in the process of implementing things. That seems to have been correct. Here's another topic for the list. :-)
So, Section 7 says the ACK contains: > A list of the records containing handshake messages in the current flight which the endpoint has received and either processed or buffered, in numerically increasing order. https://www.rfc-editor.org/rfc/rfc9147.html#name-ack-message First, it is ambiguous what "numerically increasing order" means when there are two integers in a packet number, not one. But, more importantly, I'm not sure this matches what implementations do. I haven't tested carefully, so I may be wrong about this, but at a glance, I don't think either NSS or wolfSSL's DTLS 1.3 implementations (are there any other DTLS 1.3 implementations yet) do this? Keep in mind that appending records to the list as you receive them will *not* result in numerical order because packets may be reordered. If no one is following this rule anyway, perhaps we should just remove it? In particular, it seems a natural implementation will result in receive order, not numerical order. Implementations should bound their ACK buffers to avoid DoS, and are expected to preferentially ACK more recent records: > Implementations MAY acknowledge the records corresponding to each transmission of each flight or simply acknowledge the most recent one. In general, implementations SHOULD ACK as many received packets as can fit into the ACK record, as this provides the most complete information and thus reduces the chance of spurious retransmission; if space is limited, implementations SHOULD favor including records which have not yet been acknowledged. Given that, the natural implementation is some kind of bounded MRU queue of records, where old ones fall off the end. (I'm planning to use a ring buffer for our implementation.) To get numerical order, you'd need to re-sort when sending an ACK. That is not hard, but it's unclear to me what's the point. Next, the spec's guidance on when to clear the ACK buffer seems odd to me. Section 7 also says: > During the handshake, ACKs only cover the current outstanding flight (this is possible because DTLS is generally a lock-step protocol). In particular, receiving a message from a handshake flight implicitly acknowledges all messages from the previous flight(s). Accordingly, an ACK from the server would not cover both the ClientHello and the client's Certificate message, because the ClientHello and client Certificate are in different flights. Implementations can accomplish this by clearing their ACK list upon receiving the start of the next flight. The claim that clearing this ACK list accomplishes this is not true, for several reasons: First, there's nothing stopping you from receiving a (redundant) portion of the previous flight while you're receiving the new one. You'll notice all the sequence numbers are old and ignore them when processing, but that still keeps the record eligible for an ACK. Moreover, it's still important ACK to old fragments. When the old fragment is in the *current* flight, the peer may have lost an earlier ACK and not realize they can stop retransmitting. It's only old fragments in *previous* flights that are unnecessary to ACK, but the specification does not suggest to distinguish them. (Distinguishing them would require extra state in the record layer to store a low watermark for the flight, and that seems a waste. There's no real harm in adding that record to the ACK buffer.) Next, packets can be reordered. You might receive not the start of the next flight, but the middle of the next flight. In general, any DTLS record layer rule keyed on the start of a flight is suspect because of packet reordering. But actually I'm not sure if the spirit of this rule is correct at all. If the peer sent flight N-1, you sent N, and now you're in the middle of receiving flight N+1, you can stop ACKing flight N-1 as soon as you start *sending* N. You don't need to wait to receive N+1. *Every* fragment of N implicitly ACKs all of N-1, so as soon as you're ready to send any part of N, you may as well send that instead of ACKing individual records because then you also make progress in the connection. The spec instead says to wait until receiving part of N+1, which seems later than needed and may not even exist. (Neither version achieves the stated goal in the spec. The stated goal seems to require tracking extra state.) With all that said, it seems odd to be clearing the ACK buffer at all. I've gathered the reason to ACK by record number instead of message ranges (and thus require the implementation keep around some state) was so that RTT measurements could work despite retransmits. Is that right? But if the happy path doesn't ACK most records in the first place, you won't actually get an estimate out of it. David
_______________________________________________ TLS mailing list -- tls@ietf.org To unsubscribe send an email to tls-le...@ietf.org