Draft: draft-ietf-quic-transport

Commentary: Section 12.2 makes two quasi - conflicting statements about coalesced packets . In a connection where the sender has multiple CIDs in hand , using two different CIDs in the two coalesced packets is entirely consistent with the guidance to the sender , but would be dropped based on the guidance to the receiver . We should align these two statements . 
 Fixing this would require a change to normative language . I 'm of the opinion that the first should change to different connection IDs rather than connections ; the second might change to a MUST NOT , but it could remain a SHOULD and achieve the same end . The main reason for this is that routing will be based on the first packet . But there is also a secondary benefit in not creating a strong correlation between different connection IDs for the same connection . 
 But this complicates the coalescing logic , because you no longer only need to look at packet types but now also CID fields . At least in my stack , that is an ugly change to make at this stage . 
 The alternative , which I can now see is probably a smaller change is : 
 What motivated this was two observations : we do n't coalesce except during the handshake , where we are not migrating some stacks generate packets for coalescing while processing , and so they might generate a datagram with multiple connection IDs 
 writes : This is much simpler alternative than what is being proposed . Now an implementation can only drop a packet after doing a connection lookup , whereas before it could just compare the CID to the previous value . If this is just a matter of personal preference , I vote for this approach , so now the score is 1:1 ( with being on the opposite side ) . To take a step back : why is recommendation to drop packets exist in the first place ? If a sender wants to coalesce packets from different connections , why not let it ? 
 I think it should not allow having multiple packets for different connections in a single UDP datagram - please . Currently I see implementations ( including mine ) have something like : Receive UDP packet . Parse packet header . Check CID , find the connection handler . Pass the packet to the respective connection ( thread ) to handle the packet . I think it makes implementations much more complicated ( already ) . Also I wonder it may cause security issue if having bad assumption ? 
 The classic example would be coalescing Handshake packets , whose DCID is the SCID used by the server , and Initial or Zero - RTT packets , whose DCID is the client - chosen Initial DCID . The client MAY switch to using the server chosen CID for Initial packets . Maybe we should say that it MUST do that if it is going to coalesce Initial and Handshake packets . Not so clear about 0 - RTT packets . Is it actually allowed to send them with a different DCID than the Initial DCID ? 
 : Our assumption has been that load balancers , for instance , can simply route on the CID in the first header they see in the UDP datagram . If we allow different connections to be coalesced , that complicates things . It may also start to leak some things about the way load is distributed within the server network : if some CIDs when combined cause loss and some do n't , that reveals some things about how the server load is distributed . Is there a strong argument for changing this behavior ? This new language in was always the intent . I suspect it did n't change when we started allowing multiple CIDs within a connection . Unless there 's an argument for changing behavior , this is really an editorial PR . 
 If I understand correctly , every time you change the connection ID , you change the connection ID for all packet number spaces . Assuming that my reading of the spec is correct in this regard , it seems like there 's no compelling reason for making this change ? 
 the spec actually says ( 7.2 ): The first flight of 0 - RTT packets use the same Destination Connection ID and Source Connection ID values as the client 's first Initial packet . Upon first receiving an Initial or Retry packet from the server , the client uses the Source Connection ID supplied by the server as the Destination Connection ID for subsequent packets , including any 0 - RTT packets . SO you are correct , there is no ambiguity . 
 Thank you for looking this up . Then I 'm opposed to making any change here . Not only is it unnecessary ( that alone should be enough ) , it would also make it more difficult to evolve the way we deal with coalesced packets in the future : I can imagine a future QUIC version introducing a way to authenticate the entire coalesced packet , while at the same time compressing the header . This will be easier if we keep the explicit property that all connection IDs of the coalesced packets match . 
 I 'm not sure if I agree . Coalescing of QUIC packets is a feature specific to v1 , entities that operate without the knowledge of the connection ( e.g. , load balancers , datagram dispatchers ) are not expected to consult the CID values of QUIC packets that are appended . Therefore , what we are talking here does not affect what we can do in the future . 
 That argument was based on the thought that it will be easier in a future QUIC version because the diff to v1 would be smaller . My main point is that this change is unnecessary because when endpoints change connection IDs , they change it for all packer types at the same time . 
 Thank you for the clarification . I think I do not agree to this , too . IIUC , the consensus we reached with was that the CID of a Handshake packet and that of the 1 - RTT packet can be different . While it is true that the initial DCID set by the client is expected to change when the client receives the first " active " connection ID supplied by the server , the fact does not mean that the CIDs of all QUIC packets within a datagram has to be the same in all the cases . 
 I think we need to make a change , in one direction or the other . It 's unfortunate to mix CIDs , since it clearly links them to any observer , but does n't seem like a big deal . For some implementations , it sounds like it 's a big deal to avoid mixing them . Therefore , while I 'm content with either resolution , it seems like it makes more sense to resolve toward being more permissive ; e.g. . Mixing packets from different connections seems like a generally bad idea , since it assumes an implementation structure on the far end for it to work . The more likely outcome is that coalesced packets from other connections will simply be dropped as invalid . ( Of course , this very property could be used for padding / misleading observers . ) 
 Hi  , Can you say more about why you do n't see this as an issue ? Is it because this use case is most likely during the handshake ? Or is there some other linkability already present that makes this less of an issue ? regards ,   Some implementations try to change the CID as soon as possible , to avoid linking 1RTT traffic with the CID visible during the handshake and to improve privacy . There will be a brief window when they still need to send both some handshake packets and some 1RTT packets . But coalescing a Handshake packet with the old CID and a 1RTT packet with the new CID links old and new CID and thus negates the effort . And just in case someone asks , no , you do n't really need to decrypt the packets to access the second CID . You just need the coalesced packet and another 1RTT packet . Not hard . 
 If that is the concern , would n't it be better for endpoints to migrate to a new CID after learning that the peer has dropped the Handshake keys ? If an endpoint switches to the new CID before the handshake keys are dropped by the peer , there 's chance that the peer might use a new CID in the Handshake packets that the peer sends . That at least leaks when the connection was established for that CID . 
 yes , the simplest way to not run into coalescing problems is to not start migrations or CID changes before Handshake Done . 
 Apologies , I 'm getting lost in the weeds here . I agree with that we need to make a change , and that is really meant to fix the text to what the intent always was . Are we all agreeing on this point ? 
 That is my view . I think to be an editorial amendment of . Regarding linkability problem , the simple and safe way of mitigating the problem ( as proposed in ) does not interfere with the proposed resolution . 
 I personally prefer the old version , force single CID in coalesced packet . Loosening the text to allow multiple CID requires a code change in my implementation . 
 I 'm with Single CID . 
 Both , actually . This occurs during the handshake , when addresses are required to be stable . Unless you 're running a large number of parallel connections , all CIDs used on that 4 - tuple during the handshake belong to the same connection with very high probability . You can break that linkage by deliberately changing CID and port at the same time , but you ca n't do that until the handshake is confirmed . If you want the linkage broken , you need to do that jump post - handshake anyway . 
 Hi  , I think " high probability " is probably app - dependent , because there may be cases where there are significant numbers of parallel connections . In the case of proxied queries , for example , the use of the same 4 - tuple but a different CID could turn out to be common , because the proxy may prefer to keep traffic from its different clients separate even if they could be served by the same upstream server . A DNS example : if you have an DNS resolver talking to an upstream proxy or a common authoritative server , that resolver may want to set a different   for different query streams , so that input can be used to determine the preferred reply . In the presence of a NAT or CGNAT , there could be interesting interaction with the dwell timers in the state table of the middlebox . If you change it too late , the middlebox may recycle the most recently freed port , which could result in you getting the same 4 - tuple to an observer on that part of the path . Speaking strictly as an individual , I think using a single CID per coalesced packet as Christian prefers is cleaner and leaves open app behaviors we may not have yet identified . regards  I 'm not a big fan of   , and these particular parallel connections may or may not pose a risk ; it 's just a proxy situation where the parallelism might occur . 
 The discussion is active , I 'm marking this as design . 
 I might be missing something , but if an endpoint wants to cut linkability between the packets used during the handshake and the packets used in 1 - RTT , that endpoint has to switch to a new CID after the peer has dropped its Initial and Handshake keys , regardless of the outcome of this issue . That is because if the endpoint switches to a new CID while the peer is still sending Initial or Handshake packets , we allow the peer to use that new CID in the long header packets sent in response . Therefore , I do not think that requiring endpoints to use one DCID in all the coalesced QUIC packets help us in practice . 
 In my implementation ,  , it processes packet in the way that PR proposes ; which means I just over looked existing text , but anyway , I think that processing a packet atomically is cleaner approach in implementation wise rather than passing a some kind of pointer to the very first packet header . 
 Once a non - coalesced packet is passed to a connection , in my implementation I do n't have to do any checking . The server already makes sure to pass packets to the correct connection based on the DCID . So there 's additional validation logic required for coalesced packets . And the easiest way is to just check that all DCIDs match . Sure , it would be possible to somehow query which other DCIDs would also be valid for the same session , but it 's more complicated . And given that nobody has come up with any good reason to coalesce packets with different DCIDs in the first place , I 'm wondering how this additional complexitiy would be justified . 
 I do n't foresee a large problem with the proposed change , but I also do n't think it 's necessary . 
 Do we have a proposed resolution for this one ? 
 I think we settled on requiring connection IDs to be the same , but I have n't had the time to write that up , so not just yet . 
 FTR , discussion happened on the mailing list . My sense is that it 's still not clear to some ( including me ) why the current fix in ( requiring " connections " to be the same ) does n't work , but nobody is arguing strongly against what said above ( requiring " connection IDs " to be the same ) . So that might be the least common denominator .
Paragraph (version A):
Receivers MAY route based on the information in the first packet
contained in a UDP datagram.  Senders MUST NOT coalesce QUIC packets
for different connections into a single UDP datagram.  Receivers
SHOULD ignore any subsequent packets with a different Destination
Connection ID than the first packet in the datagram.
Paragraph (version B):
Receivers MAY route based on the information in the first packet
contained in a UDP datagram.  Senders MUST NOT coalesce QUIC packets
with different connection IDs into a single UDP datagram.  Receivers
SHOULD ignore any subsequent packets with a different Destination
Connection ID than the first packet in the datagram.