Original text:
13.2.4. <del> To limit ACK Ranges (see ack-ranges) to those that have not yet been received by the sender, the receiver SHOULD track which ACK frames have been acknowledged by its peer.  The receiver SHOULD exclude already acknowledged packets from future ACK frames whenever these packets would unnecessarily contribute to the ACK frame size.  When the receiver is only sending non-ack-eliciting packets, it can bundle a PING or other small ack-eliciting frame with a fraction of them, such as once per round trip, to enable dropping unnecessary ACK ranges and any state for previously sent packets.  The receiver MUST NOT bundle an ack-eliciting frame, such as a PING, with all packets that would otherwise be non-ack-eliciting, in order to avoid an infinite feedback loop of acknowledgements. To limit receiver state or the size of ACK frames, a receiver MAY limit the number of ACK Ranges it sends.  A receiver can do this even without receiving acknowledgment of its ACK frames, with the knowledge this could cause the sender to unnecessarily retransmit some data.  Standard QUIC algorithms (QUIC-RECOVERY) declare packets lost after sufficiently newer packets are acknowledged.  Therefore, the receiver SHOULD repeatedly acknowledge newly received packets in preference to packets received in the past. </del>  13.2.5.

Reviewer comments:
This PR does not substantively change the recommendations, but it does remove one SHOULD that did not make any sense. I would prefer to go through with this as a design change.
NAME might want to scrub this up a little and land it.
Ok, comments incorporated, PTAL.
Woo!
In , NAME notes that added this "MUST": My understanding is that this prevents the largest acknowledged packet from going backwards. We use the monotonic increase of the Largest Acknowledged field in two ways: In ECN validation, this is used to filter out ACK frames that might have arrived out of order, which might have lower counts legitimately. In key updates, where the value of the largest acknowledged is used to drive the change to new keys and to prevent use of old keys after an update. In my view, having ECN validation fail is quite unfortunate, but likely workable. On the other hand, uncertainty about largest acknowledged could introduce instability in the key update process. If an endpoint's conception of what the value is changes, I doubt that we'll see extra key updates (I think that the AEAD would protect us from that), but we might leave open the possibility of interleaving of packets from two different key phases. I would suggest that we retain this "MUST".
For out of order ACK frames, you can use the packet number the ACK arrives in. I realize that we have tried to allow frames to be retransmitted, but I think retransmitting ACK frames without modifying the ACK delay/etc is so harmful we should probably prohibit that one frame from being retransmitted, since it creates a bunch of edge cases. Or we could let ECN validation could fail, but that'd be a bit sad. I'm confused about what the issue with key updates is? The largest acked you've ever seen doesn't change, just the largest acked from the last ACK frame. When determining the size of the packet number, we say: "The sender MUST use a packet number size able to represent more than twice as large a range than the difference between the largest acknowledged packet and packet number being sent." I'd rather not make this a MUST unless we have a good reason. There are valid use cases that become more complex with this constraint.
I really want to understand the use cases that you think that this might break. Because key updates very much depend on tracking largest acknowledged. The key updates case has a fairly simple example. Say you receive packet 10 in key phase 1. Then 11 in key phase 2. That's valid. But if you ACK those and then only remember up to packet 8, packet 9 can use key phase 2 and you won't know that it is invalid.
I'd like to suggest tracking largest acknowledged from forcing all ACK frames to contain the largest acknowledged and have that value never decrease. Given you need to track largest acknowledged locally(ie: not only in the in-flight ACK frame), I don't think there are any problems there. I have two cases in mind where the largest acked could validly decrease: 1) A receiver that tracks a limited number of ACK blocks and the oldest block happens to be the one containing largest acked. 2) If an application was reordering tolerant(ie: from URL) then two different senders on a single 'connection' may be sending packets with disparate packet numbers, causing what appears to be very large scale reordering. In this case, it'd be valuable to discard the older ACK ranges even if they contained the largest acked. Maybe the first is an edge case we don't care about in a use case we aren't optimizing for and the latter is solvable with careful issuing of packet number ranges. Even so, I'm not sure what the motivation is for this change? I guess the ECN case could be, but using largest acked as a proxy for retransmitted ACKs is a very bad design in my opinion.
I don't think we really need to cater for retransmitted ACK frames in any way. What I'm concerned about is reordering. Yes, using the increase of largest acknowledged as a proxy for strict ordering is a little weird, but the assumption is that frame handling is distinct from packet handling and packet numbers are not available when frames are handled. (I think that's the principle we agreed on; that's why it's OK to use packet numbers in key updates, for example, something that I can confirm is borne out by implementation experience.) The case you describe here has the appearance of exactly that type of reordering if the two senders also generate their own ACK frames (though this seems very strange). But I think that the consequences of that sort of design are not our responsibility to deal with.
I don't recall on us agreeing that packet numbers weren't available when frames are handled, can you clarify why that property is important?
I agree with NAME on the principle of not requiring the enclosing packet's packet number during frame handling, and we use sequence numbers within frames to help with reordering. This was at least true in an earlier version of NCID frames, and we had discussed this principle then. This is also why the ACK_FREQUENCY frame in URL includes a sequence number. That said, I don't understand the issue with key updates here. Largest acked so far is a connection-level state variable that can be used for key updates. I suspect that I'm not understanding the example scenario. NAME can you elaborate on your key update example? NAME Is your example motivated by a receiver that does not remember the largest acked or one that does not wish to ack anything but the packet that was just received?
I was under the impression that the argument was that largest acknowledged was not being tracked, but Ian made it clear that the concern was about not signaling it. That removes key updates as a concern. If remains unclear, then I can't really do better.
NAME my example was motivated by either case, but primarily not wanting to ACK anything besides what was just received.
Perhaps it's a naive model, but I had envisioned an implementation remembering a chain of ranges of packet numbers it had received or not. The implementation would save space by forgetting the earliest packet numbers when the chain got too long, and would construct an ACK frame out of the latest set of these ranges it had room for. In that mental model, at least, there's not really room for the idea that you might drop the largest-acked frame number from your memory because it's too old -- it's always at the most-recent end of your chain, even if you currently happen to be receiving packets that fill in the middle for some implementation-specific reason. (Implementation-specific to the peer, which you obviously can't know about or code for!)
That matches my model for this. It is also likely the case that the next packet you receive is largest+1, so there is no real advantage to forgetting the largest acknowledged. Not sending largest acknowledged is slightly different though. I can understand how an implementation might choose to send only ranges that have recently changed. My contention is that this is not a good choice and we should recommend against that.
NAME to produce some text here that separates retention policy (MUST) from signaling policy (SHOULD).
In trying to do a simple fix for , I found other irrelevant or poorly-written recommendations in how a receiver could limit ACK ranges it sends. This section needs to be rewritten. Specifically, the sentence below is a poor recommendation and contradicts earlier recommendation on acking until the ACK frame is acknowledged. The recommendation below is fine, but the rationale does not make sense: This should be a design change.
I'm not in love with this (entire) section either, but I'd like to better understand this issue. I agree that sentence is mis-written, though I think the intent was fine. On the rationale, can you clarify why it does not make sense?
The of the Transport Draft should explain what to do when generated ACK is too large to fit in a packet: Generate a shorter ACK frame (instead of aborting connection or erroring out). To generate the shorter frame, don't include older (smaller) packet numbers. (As opposed to not including newer packet numbers.)
There is a good amount of existing text about what ranges to send, ie "ACK frames SHOULD always acknowledge the most recently received packets," I think this can be solved with some editorial additions to 13.2.2. URL
The text we already have in 13.2.4 has the right context:
Ok, this became a bigger fix. See and .
LGTM modulo one paragraph.

Revised text:
13.2.4.  <ins> A receiver limits the number of ACK Ranges (ack-ranges) it remembers and sends in ACK frames, both to limit the size of ACK frames and to avoid resource exhaustion.  After receiving acknowledgments for an ACK frame, the receiver SHOULD stop tracking those acknowledged ACK Ranges. It is possible that retaining many ACK Ranges could cause an ACK frame to become too large.  A receiver can discard unacknowledged ACK Ranges to limit ACK frame size, at the cost of increased retransmissions from the sender.  This is necessary if an ACK frame would be too large to fit in a packet, however receivers MAY also limit ACK frame size further to preserve space for other frames. When discarding unacknowledged ACK Ranges, a receiver MUST retain the largest received packet number.  A receiver SHOULD retain ACK Ranges containing newly received packets or higher-numbered packets. A receiver that sends only non-ack-eliciting packets, such as ACK frames, might not receive an acknowledgement for a long period of time.  This could cause the receiver to maintain state for a large number of ACK frames for a long period of time, and ACK frames it sends could be unnecessarily large.  In such a case, a receiver could bundle a PING or other small ack-eliciting frame occasionally, such as once per round trip, to elicit an ACK from the peer. A receiver MUST NOT bundle an ack-eliciting frame with all packets that would otherwise be non-ack-eliciting, to avoid an infinite feedback loop of acknowledgements. </ins> 13.2.5.