Original text:
When an endpoint issues a connection ID, it MUST accept packets that carry this connection ID for the duration of the connection or until its peer invalidates the connection ID via a RETIRE_CONNECTION_ID <del> frame (frame-retire-connection-id). </del>  An endpoint SHOULD ensure that its peer has a sufficient number of available and unused connection IDs.  Endpoints store received send to a value that has not been used on another path. An endpoint MUST use a new connection ID if it initiates connection <del> migration.  Using a new connection ID eliminates the use of the connection ID for linking activity from the same connection on different networks.  Header protection ensures that packet numbers cannot be used to correlate activity.  This does not prevent other properties of packets, such as timing and size, from being used to correlate activity. </del>  Unintentional changes in path without a change in connection ID are possible.  For example, after a period of network inactivity, NAT reset its congestion state (see migration-cc), so the port SHOULD only be changed infrequently. <del> An endpoint that exhausts available connection IDs cannot migrate. To ensure that migration is possible and packets sent on different paths cannot be correlated, endpoints SHOULD provide new connection IDs before peers migrate. </del>  9.6.

Reviewer comments:
This closes the rather serious hole we left when we attempted to limit the effect of perpetual changing of connection IDs. This uses a narrower formulation, that I believe will avoid perpetual changes. But it does require reciprocal connection ID changes where endpoints genuinely do migrate. It's a design change unfortunately, but I hope non-controversial.
Latest changes look great!
There are bunch of changes in migration recently, and they suggests that new CID is required only when endpoint sends a packet from new local address and an endpoint of migrating peer is no longer required to change its CID when sending a packet using new path as long as its local address does not change. But there are several lines of text left to suggest that an endpoint changes CID: Are they just remnants of old text and should be removed? or does changing CID in response to migration still a requirement?
Changing CID in response to migration is a soft requirement since it cannot always be enforced since NAT rebinding might happen without endpoint interference. It can hurt privacy though. CID changes can also happen without migration. One reason is for the peer to do so after an idle period because the risk of NAT rebinding is high. Another reason is to ensure CIDs do not get stale on long living connections since the peers routing infrastructure might regroup or move valid CID patterns to a new epoch. The last reason could perhaps be replaced by the proposed explicit retire prior to facility.
So what does implementation actually need to do in response to migrating peer? Just keep using same CID or not? Use same CID to do path validation? I know that peer can change CID at anytime it likes.
The key principle is to not reuse a CID on a new path if it can be avoided. I'm not sure about the CID terminating if the pool is exhausted - in your quoted text. I think it may choose to do so (and is encouraged to do so) but I'm not sure it is required to. Changing CID in response to a peers migration is therefore relevant but changing CID just because the peer changes CID is problematic because it might never end.
Thank you. I thought that new CID should be used on new path, but I couldn't find normative text for it now. Other than quoted text, draft says new CID is required if endpoint migrates to new local address. I remember the discussion of changing CID in response to CID change which is not required and sorted out with the recent PRs.
I think at one point we said "SHOULD change if the peer changes, but be careful not to loop". Otherwise it's pretty trivial to establish linkability, so everything is structured about trying to make sure you can do it, but not falling over too hard in the edge cases where you may not be able to.
We agreed that changing CID wouldn't trigger a change in response, but the only hard rule was "if you use a new path, use a new connection ID".
Ah, interesting. I thought you were still expected to attempt to change if you could.
... if you know that you change path - but you don’t always know.
Is there an underling issue here, or has the question been answered?
I couldn't find the hard rule "if you use a new path, use a new connection ID" in the draft in clear manner. What I found is endpoint MUST change CID when using new local address. It does not mention about change on remote address.
Background context for this issue: In NAT rebinding test, quic tracker does not send any NEWCONNECTIONID. My server implementation refuses to use new path because there is no new CID left and cannot verify new path assuming that new CID is required for new path. But they say that using NEWCONNECTIONID for new path is not written in draft as requirement, so server should follow the new path. If using new CID for new path is a requirement, quic tracker should send NEWCONNECTIONID. If it is just a recommendation, server probably should use new path with same CID.
I think the issue is that there are two types of migration: "Direct" migration, where an endpoint changes to a new path and it is in their interest to also change the CID (to reduce trackability), and "indirect" migration, i.e., NAT rebinding, where a middlebox changes the path for an endpoint in a way that they are unaware of and therefore cannot initiate a CID migration for. Both of there are valid, but they are slightly different. Is it sufficient to clarify that for a direct migration, a CID change SHOULD happen, and for an indirect migration, it (generally) cannot, and that the peer must handle both?
NAME I like the way you categorize migration. Does that mean in practical sense that clients SHOULD change CID on direct migration, and that servers SHOULD respond to a CID change with a CID change? Assuming that is what we are seeking, I think it might be a good idea to clarify using a non-RFC2199 term that is effectively what we recommend (I understand that we prefer talking about "endpoints").
Client doesn't change CID in indirect migration because it does not aware of it. Regardless of direct or indirect migration, server knows the packet is coming from new path (new remote address and/or port). So the question is server MAY/SHOULD/MUST change CID when sending a packet to new path. Current draft says that it is MUST to change CID on direct migration:
An option would also to keep MUST change CID on direct migration and add that a en endpoint SHOULD not reject a migration that doesn't change CID because it might be a valid indirect migration. An endpoint MAY, however, reject indirect migrations that do not change CID if this is privacy is considered more important than broad interop (this is controversial).
Either way, I think it would be beneficial if the text has a section with clear definition of the terms "direction migration" and "indirect migration".
NAME bit when a server sees the client using a new path (because of a NAT rebind) the server is not the one initiating the migration
In reviewing this, I think we've messed up badly. We currently only mandate the use of a new connection ID for the initiator of a migration. A peer that responds to a connection migration has to change a connection ID if the initiator changed their connection ID. That needs to be fixed promptly. Then the concerns that NAME raises here might seem less surprising. NAME NAME can we recategorize this as design? Thanks.
This has been discussed at length and while I tend to agree that this is not a good design, I believe things ended up as they are due to concerns about endless CID change loops. I think that can be prevented without too much complexity, but that argument was one of the drivers, as I recall.
The problem was that we over-rotated. Now we don't require any change on the responding endpoint's part, which means we have near-perfect linkability across migrations. I think that the proposed change is the minimal one we can mandate. I might prefer to have something slightly better, but doing that without also flirting with the infinite loop was too hard.
Agreed. IIUC, the only endpoint that "initiates" a CID change is the client, because only the client side that migrates (or probes) a new path. This is the case for SPA too. Therefore, I believe that stating something along the lines of the following is sufficient: a server MUST respond with a new CID to a packet that has been received on a new path with a new CID.
I definitely agree that we should change this to require a change in response, it would be worth wordsmithing something that achieves this -- the PR is a good start. Differentiating by client/server might be interesting, although there appear to be two cases: A CID change on a link without any address change. A change in any part of address (IP/port) We can talk about initiator/responder to migration rather than client/server and that might be a good approach (which is pretty close to what the PR does right now).
I thought where we landed (in concept, not necessarily text) was that you MUST change CID any time you're using a different local or remote IP:port. That means the client MUST change if it knows it's migrating (new source address); the server will change in response because it's going to a new destination. The client SHOULD change if it has been quiescent and anticipates a NAT-rebind (i.e. uncertain about source address); if it actually got rebound, the server would change as well (new destination address). If it turns out the client didn't get rebound, then IP:port already correlate it; perhaps slightly better if the server rotates, but it's not required to.
LGTM. Thank you for the changes.Thanks for writing this up! Latest content looks great, just two minor wording questions and this looks ready to go.

Revised text:
When an endpoint issues a connection ID, it MUST accept packets that carry this connection ID for the duration of the connection or until its peer invalidates the connection ID via a RETIRE_CONNECTION_ID  <ins> frame (frame-retire-connection-id).  Connection IDs that are issued and not retired are considered active; any active connection ID can be used. </ins> An endpoint SHOULD ensure that its peer has a sufficient number of available and unused connection IDs.  Endpoints store received send to a value that has not been used on another path. An endpoint MUST use a new connection ID if it initiates connection  <ins> migration as described in initiating-migration or probes a new network path as described in probing.  An endpoint MUST use a new connection ID in response to a change in the address of a peer if the packet with the new peer address uses an active connection ID that has not been previously used by the peer. Using different connection IDs for packets sent in both directions on each new network path eliminates the use of the connection ID for linking packets from the same connection across different network paths.  Header protection ensures that packet numbers cannot be used to correlate activity.  This does not prevent other properties of packets, such as timing and size, from being used to correlate activity. </ins> Unintentional changes in path without a change in connection ID are possible.  For example, after a period of network inactivity, NAT reset its congestion state (see migration-cc), so the port SHOULD only be changed infrequently.  <ins> An endpoint that exhausts available connection IDs cannot probe new paths or initiate migration, nor can it respond to probes or attempts by its peer to migrate.  To ensure that migration is possible and packets sent on different paths cannot be correlated, endpoints SHOULD provide new connection IDs before peers migrate; see issue- cid.  If a peer might have exhausted available connection IDs, a migrating endpoint could include a NEW_CONNECTION_ID frame in all packets sent on a new network path. </ins> 9.6.