Original text:
8.2. <del> Path validation is used during connection migration (see migration) by the migrating endpoint to verify reachability of a peer from a new local address.  In path validation, endpoints test reachability between a specific local address and a specific peer address, where an address is the two-tuple of IP address and port. </del>  Path validation tests that packets sent on a path to a peer are received by that peer.  Path validation is used to ensure that address. Path validation does not validate that a peer can send in the return <del> direction.  The peer performs independent validation of the return path. </del>  Path validation can be used at any time by either endpoint.  For instance, an endpoint might check that a peer is still in possession packet on that path.  Effective NAT traversal needs additional synchronization mechanisms that are not provided here. <del> An endpoint MAY include PATH_CHALLENGE and PATH_RESPONSE frames that are used for path validation with other frames.  In particular, an endpoint can pad a packet carrying a PATH_CHALLENGE for Path Maximum Transfer Unit (PMTU) discovery (see pmtud), or an endpoint can include a PATH_RESPONSE with its own PATH_CHALLENGE. </del>  <del> When probing a new path, an endpoint might want to ensure that its peer has an unused connection ID available for responses.  The endpoint can send NEW_CONNECTION_ID and PATH_CHALLENGE frames in the same packet.  This ensures that an unused connection ID will be available to the peer when sending a response. </del>  <del> 8.3. </del>  To initiate path validation, an endpoint sends a PATH_CHALLENGE frame containing an unpredictable payload on the path to be validated. An endpoint MAY send multiple PATH_CHALLENGE frames to guard against packet loss.  However, an endpoint SHOULD NOT send multiple <del> PATH_CHALLENGE frames in a single packet.  An endpoint SHOULD NOT send a PATH_CHALLENGE more frequently than it would an Initial packet, ensuring that connection migration is no more load on a new path than establishing a new connection. </del>  The endpoint MUST use unpredictable data in every PATH_CHALLENGE frame so that it can associate the peer's response with the corresponding PATH_CHALLENGE. <del> 8.4. </del>  On receiving a PATH_CHALLENGE frame, an endpoint MUST respond by echoing the data contained in the PATH_CHALLENGE frame in a information.  The peer is expected to send more PATH_CHALLENGE frames as necessary to evoke additional PATH_RESPONSE frames. <del> 8.5. </del>  Path validation succeeds when a PATH_RESPONSE frame is received that contains the data that was sent in a previous PATH_CHALLENGE frame. frame is not adequate validation, since the acknowledgment can be spoofed by a malicious peer. <del> 8.6. </del>  Path validation only fails when the endpoint attempting to validate the path abandons its attempt to validate the path. Failure to validate a path does not cause the connection to end unless there are no valid alternative paths available. <del> An endpoint uses a new connection ID for probes sent from a new local address; see migration-linkability for further discussion.  An endpoint that uses a new local address needs to ensure that at least one new connection ID is available at the peer.  That can be achieved by including a NEW_CONNECTION_ID frame in the probe. Receiving a PATH_CHALLENGE frame from a peer indicates that the peer is probing for reachability on a path.  An endpoint sends a PATH_RESPONSE frame in response, as per migrate-validate. </del> PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, and PADDING frames are "probing frames", and all other frames are "non-probing frames". A packet containing only probing frames is a "probing packet", and a address.  Thus an endpoint can migrate to a new local address without first validating the peer's address.  When migrating, the new path might not support the endpoint's current sending rate.  Therefore, the endpoint resets its congestion controller and RTT estimate, as described in migration-cc. The new path might not have the same ECN capability.  Therefore, the endpoint verifies ECN capability as described in ecn. <del> To establish reachability on the new path, an endpoint initiates path validation (migrate-validate) on the new path.  An endpoint MAY defer path validation until after a peer sends the next non-probing frame to its new address. Path validation is necessary to verify reachability of a peer on a new network path.  Acknowledgments cannot be used for path validation as they contain insufficient entropy and might be spoofed.  No method is provided to establish return reachability, as endpoints independently determine reachability on each direction of a path. </del> 9.3. Receiving a packet from a new peer address containing a non-probing frame indicates that the peer has migrated to that address. <del> In response to such a packet, an endpoint MUST start sending subsequent packets to the new peer address and MUST initiate path validation (migrate-validate) to verify the peer's ownership of the unvalidated address. </del>  An endpoint MAY send data to an unvalidated peer address, but it MUST protect against potential attacks as described in address-spoofing loss detection and congestion state can reduce the performance impact of the attack. <del> An endpoint only changes the address that it sends packets to in response to the highest-numbered non-probing packet.  This ensures that an endpoint does not send packets to an old peer address in the case that it receives reordered packets. </del> After changing the address to which it sends non-probing packets, an endpoint could abandon any path validation for other addresses.

Reviewer comments:
I tried to be conservative about changes, but there were a few paragraphs I thought should be moved. Otherwise, the changes are minimal. URL is the commit that adds a paragraph to clarify the main confusion on
Something to look into...
NAME I was previously finding the text confusing and potentially contradictory. When I read it all at once, I believe I understand the intent, but hopefully this change makes each portion clearer and less dependent upon adjacent sections. There's probably a bit more worth doing, but at some point I'm willing to call it good enough.
We decided to only specify client-initiated connection migration in QUIC v1. The section about Connection Migration mostly talks about endpoint and peer though, which makes it really hard to parse. I haven't implement migration yet in quic-go, and reading this section confused me at multiple places. I believe that specifying the role of the endpoint would make things a lot clearer, and could offer to come up with a PR.
I don't think this is worth doing, but would look at a PR.
To clarify, this would only apply to connection migration, not the path validation section that immediately precedes it.
NAME The idea was to keep the migration mechanisms generic, since they can be applied to either endpoint. However, this isn't adequate if we support migration at both ends, since you'd have to deal with other situations, such as simultaneous migration. v1 simply limits the scope of where these mechanisms ought to be applied. There's value in that, but I understand your reservations. Like NAME I'm not keen to follow the premise of this issue, but I'd be open to a PR. I'd also be open to clarifying the parts you found confusing.
Looking at that section again, I don't believe I want to do anything about this issue.
This choice was deliberate. Maybe it's nicer, but now is not really a good time.
Update: I thought simultaneous path validation wasn't necessary, but it looks like I misunderstood. Changing this to an editorial issue so I can re-read this text and hopefully make it clearer. I believe this is already implied, but I couldn't find it stated anywhere. I think it'd be ideal to set expectations that servers are not expected to validate multiple paths at the same time. Validating multiple paths seems like a plausible feature for multipath, but adds undue complexity for connection migration.
Does that imply that a client can only probe a single path at a time? What's the time it has to wait after apparent unsuccessful probing of one path until it can probe the next?
NAME I'm not sure if I agree. It has been my assumption that a server is expected to respond to clients probing multiple paths concurrently. Note that in , we added the following text:
Hmm, I didn't think this was already implied. You're not expected (or allowed) to send non-probing packets on multiple paths, but you can certainly get probes in from multiple different remote endpoints. This is somewhat necessary if we're to be resilient to the various packet racing attacks -- if an attacker can cause you to be upset about a packet coming in from a different destination then they can really mess you up.
I'm a bit confused about why a client needs to probe multiple paths simultaneously, given we have connection migration, not multipath. To me, it just adds complexity. I guess I can just give out a single CID to mitigate the issue, but do we really expect servers to correctly implement probing on multiple paths? What if they all succeed? A client can still only use one. NAME can you clarify the packet racing issue a bit more or point me to text that already does? I'd like to draw a state transition diagram for path validation, but if we can have multiple paths being validated at once, I'm not sure that's practical.
NAME So the scenario is that a client is using one path and has 2 or more new ones available? I've heard future hardware could make that possible, though I've never seen that case myself. The short of this is now that we're trying to move to IETF QUIC style connection migration and path validation, and I'm finding it fairly confusing.
I think there's a pretty big distinction between probing a path to establish the potential for connectivity and migrating the connection to that path. For example, I would not be at all surprised if a client were to probe all available paths and choose the "best" one to migrate to when the need arises (often, although not always, there is some warning that conditions are worsening on the current path which provides the opportunity to evaluate alternatives). That said, I think a large part of the reason to allow probing on multiple paths is to avoid requiring synchronization of a shared understanding as to the state of current probes. We don't want to add a bunch of machinery to establish failure of a probe on a different path. So even if we don't think that a client would ever intentionally probe multiple paths, if a client probes one path and hears no response, it seems completely reasonable to think that it would switch and probe a different path if it had one available. If it turns out that there was just some delay for that initial path, say it had a 1.5s RTT, now the server is going to think the client probed two paths at the same time, when in reality the client thinks it's just talking to one. It also doesn't seem particularly harmful to allow this? As NAME noted, there's some good text in there about limiting state required on the server, and of course path validation can happen at any time, so it seems completely reasonable to "forget" that any given path was validated if a client probes and then doesn't end up using the path. (Note that you'd likely want to retire the CID used on that path, so as to replace it with a new one when you did that forgetting, which also serves as a nice heuristic for the other endpoint to say "oh, hmm, they don't think they're talking to me over there", but we can dig into that later.) The packet racing thing is a reference to and the previous section. This led us to require endpoints to validate both the current and the new path when it changes, which conveniently provokes some traffic to reconfirm the active path and makes it more difficult to disrupt a connection that's gone idle. While technically this is only discussing one "new" path and then the old path being validated at the same time, it seems as though it would be trivial for such an attacker to convince an endpoint that it was seeing "probes" (since we've discussed that it's not that difficult to identify a probing packet as an observer) from multiple paths and therefore be quite upset if such behavior were restricted. I'm not saying this happens all the time, but it seems pretty reasonable to have a Wi-Fi interface and then a dual SIM device with multiple cellular interfaces. Overall, it seems as though (even if this isn't crazy common) it's not unreasonable to expect that this behavior might happen, and it doesn't seem like there's a big benefit to restricting it, nor harm in allowing it, beyond the existing text reminding endpoints to be careful with the amount of state they're willing to allocate to any individual client (which is a thing outside of any probing/migration concept anyways).
+1 to what NAME says. The resolution of (which ended up as PR ) was that a server has to remember state of N paths where N is the number of CIDs active at one time. As NAME says, a client cannot tell when a server thinks that it received two probes concurrently. Therefore, it is very tricky to have this kind of restriction within a specification that allows clients to retain multiple backup paths.
I agree with NAME and NAME here. If a client sends a probe on interface A, and then interface A disconnects and then interface B appears immediately, the client should be able to probe on interface B even though to the server will receive two independent probes at roughly the same time. Servers need to be able to handle multiple concurrent probes in order for migration to be reliable.
Note that while the server needs to respond to the probes (so the client can validate the paths), I don't think there's any requirement that the server continue to regard all those paths as validated. When the client actually migrates, if the server wants to treat the migration as an unvalidated path and initiate validation again, that seems fine.
Well, the paths aren't validated until the server explicitly validates them, so it seems like the cost is pretty minimal until the server decides to engage resources for that path. The server can also respond on the old path if the client is just probing.
NAME do you want to think about how you reached your conclusion here and see if there is something we can do to avoid that? It seems to me that the cost to a server is limited by how many paths it wants to probe, not how many the client probes, so the state is well managed. It's a little less neat if the client actively migrates multiple times. But I would say that the server can abandon probes to keep the number of active probes down to at most 2 (one for the most recent validated path, one for the most recent active path). Is that something we need to explain more thoroughly?
I have read this text quite a bit, but not end-to-end in quite a long time, so I believe that's the cause of my confusion. I'm planning to re-read all the path validation and connection migration text and I'll send out a PR if there are points that I think I are unclear.
NAME have you had a chance to do this?
Unfortunately, not yet.
Note that man-on-the-side attacker can take a valid packet and resend it from a different address. The crypto does not protect against that. If the attacker somehow isolates probe packets, the server will end up receiving probes from a variety of endpoints. Better not do something silly in that condition.
Would people please take a final look at the PR?
A few comments, but pretty close.

Revised text:
8.2.  <ins> Path validation is used by both peers during connection migration (see migration) to verify reachability after a change of address.  In path validation, endpoints test reachability between a specific local address and a specific peer address, where an address is the two- tuple of IP address and port. </ins> Path validation tests that packets sent on a path to a peer are received by that peer.  Path validation is used to ensure that address. Path validation does not validate that a peer can send in the return  <ins> direction.  Acknowledgments cannot be used for return path validation as they contain insufficient entropy and might be spoofed.  Endpoints independently determine reachability on each direction of a path, and therefore return reachability can only be established by the peer. </ins> Path validation can be used at any time by either endpoint.  For instance, an endpoint might check that a peer is still in possession packet on that path.  Effective NAT traversal needs additional synchronization mechanisms that are not provided here.  <ins> An endpoint MAY include other frames with the PATH_CHALLENGE and PATH_RESPONSE frames used for path validation.  In particular, an endpoint can include PADDING frames with a PATH_CHALLENGE frame for Path Maximum Transfer Unit (PMTU) discovery (see pmtud); it can also include a PATH_CHALLENGE frame with its own PATH_RESPONSE frame. </ins>  <ins> An endpoint uses a new connection ID for probes sent from a new local address; see migration-linkability.  When probing a new path, an endpoint expecting responses on the new path needs to ensure that its peer has an unused connection ID.  Sending NEW_CONNECTION_ID and PATH_CHALLENGE frames in the same packet ensures that an unused connection ID will be available to the peer when sending a response. An endpoint can choose to simultaneously probe multiple paths.  The number of simultaneous paths used for probes is limited by the number of extra connection IDs its peer has previously supplied, since each new local address used for a probe requires a previously unused connection ID. </ins>  <ins> 8.2.1. </ins> To initiate path validation, an endpoint sends a PATH_CHALLENGE frame containing an unpredictable payload on the path to be validated. An endpoint MAY send multiple PATH_CHALLENGE frames to guard against packet loss.  However, an endpoint SHOULD NOT send multiple  <ins> PATH_CHALLENGE frames in a single packet. An endpoint SHOULD NOT probe a new path with packets containing a PATH_CHALLENGE frame more frequently than it would send an Initial packet.  This ensures that connection migration is no more load on a new path than establishing a new connection. </ins> The endpoint MUST use unpredictable data in every PATH_CHALLENGE frame so that it can associate the peer's response with the corresponding PATH_CHALLENGE.  <ins> 8.2.2. </ins> On receiving a PATH_CHALLENGE frame, an endpoint MUST respond by echoing the data contained in the PATH_CHALLENGE frame in a information.  The peer is expected to send more PATH_CHALLENGE frames as necessary to evoke additional PATH_RESPONSE frames.  <ins> 8.2.3. </ins> Path validation succeeds when a PATH_RESPONSE frame is received that contains the data that was sent in a previous PATH_CHALLENGE frame. frame is not adequate validation, since the acknowledgment can be spoofed by a malicious peer.  <ins> 8.2.4. </ins> Path validation only fails when the endpoint attempting to validate the path abandons its attempt to validate the path. Failure to validate a path does not cause the connection to end unless there are no valid alternative paths available.  PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, and PADDING frames are "probing frames", and all other frames are "non-probing frames". A packet containing only probing frames is a "probing packet", and a address.  Thus an endpoint can migrate to a new local address without first validating the peer's address. <ins> To establish reachability on the new path, an endpoint initiates path validation (migrate-validate) on the new path.  An endpoint MAY defer path validation until after a peer sends the next non-probing frame to its new address. </ins> When migrating, the new path might not support the endpoint's current sending rate.  Therefore, the endpoint resets its congestion controller and RTT estimate, as described in migration-cc. The new path might not have the same ECN capability.  Therefore, the endpoint verifies ECN capability as described in ecn.  9.3. Receiving a packet from a new peer address containing a non-probing frame indicates that the peer has migrated to that address.  <ins> An endpoint only changes the address that it sends packets to in response to the highest-numbered non-probing packet.  This ensures that an endpoint does not send packets to an old peer address in the case that it receives reordered packets. In response to such a packet, an endpoint MUST send subsequent packets to the new peer address and MUST initiate path validation (migrate-validate) to verify the peer's ownership of the address if validation is not already underway. </ins> An endpoint MAY send data to an unvalidated peer address, but it MUST protect against potential attacks as described in address-spoofing loss detection and congestion state can reduce the performance impact of the attack.  After changing the address to which it sends non-probing packets, an endpoint could abandon any path validation for other addresses.