Code change:
7.1.2. <ins> When sending to a zero-length CID receiver, senders may receive acknowledgements that combine packet numbers received over multiple paths.  However, even if one packet number space is used on multiple path the sender MUST maintain separate congestion control state for each path.  Therefore, senders MUST be able to infer the sending path from the acknowledged packet numbers, for example by remembering which packet was sent on what path.  The senders MUST use that information to perform congestion control on the relevant paths, and to correctly estimate the transmission delays on each path.  (See ack-delay-and-zero-length-cid-considerations for specific considerations about using the ACK Delay field of ACK frames, and ecn-handling for issues on using ECN marks.) Loss detection as specified in QUIC-RECOVERY uses algorithms based on timers and on sequence numbers.  When packets are sent over multiple paths, loss detection must be adapted to allow for different RTTs on different paths.  When sending to zero-length CID receivers, packets sent on different paths may be received out of order.  Therefore senders cannot directly use the packet sequence numbers to compute the Packet Thresholds defined in Section 6.1.1 of QUIC-RECOVERY. Relying only on Time Thresholds produces correct results, but is somewhat suboptimal.  Some implementations have been getting good results by not just remembering the path over which a packet was sent, but also maintaining an order list of packets sent on each path.  That ordered list can then be used to compute acknowledgement gaps per path in Packet Threshold tests. 7.1.3. </ins> The ACK Delay field of the ACK frame is relative to the largest acknowledged packet number (see Section 13.2.5 of QUIC-TRANSPORT). When using paths with different transmission delays, the reported

Related discussion:
text: However, that required significant improvements in the code: to obtain good loss efficiency, picoquic remembers not just the path on which a packet was sent, but also the order of the packet on this path, i.e. a "virtual sequence number". The loss detection logic then operates on that virtual sequence number. to contain ACK size, picoquic implements a prioritization logic to select the most important ranges in an ACK, avoid acking the same range more than 3 or 4 times, and keep knowledge of already acknowledged ranges so range coalescing works. I think these improvements are good in general, and I will keep them in the implementations whether we go for single space or not. The virtual sequence number is for example useful if the CID changes for reasons not related to path changes in multiple number space variants. It is also useful in unipath variants to avoid interference between sequence numbers used in probes and the RACK logic. The ACK size improvements do reduce the size of ACKs in presence of out of order delivery, e.g., if the network is doing some kind of internal load balancing. On the other hand, the improvements are somewhat complex, would need to be described in separate drafts, and pretty much contradicts the "simplicity of code" argument. So we are left with the "Null length CID" issue. I see for cases: Client CID Priority ----------------------- long Used by many implementations NULL Preferred configuration of many big deployments long Rarely used, server load balancing does not work NULL Only mentioned in some P2P deployments The point here is that it is somewhat hard to deploy a large server with NULL CID and use server load balancing. This configuration is mostly favored by planned P2P deployments.
The big debate is for the configuration with NULL CID on client, long CID on server. The packets from server to client do not carry a CID, and only the last bytes of the sequence number. The client will need some logic to infer the full sequence number before decrypting the packet. The client could maybe use the incoming 5 tuple as part of the logic, but it is not obvious. It is much simpler to assume a direct map from destination CID to number space. That means, if a peer uses a NULL CID, all packets sent to that peer are in the same number space.