Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Designing odd/even path-id, or not. #328

Open
huitema opened this issue Apr 3, 2024 · 13 comments
Open

Designing odd/even path-id, or not. #328

huitema opened this issue Apr 3, 2024 · 13 comments

Comments

@huitema
Copy link
Contributor

huitema commented Apr 3, 2024

During the processing of PR #272, we discussed separating the path identifiers in two classes: client initiated path identifiers, with even numbers, and server initiated path identifiers, with odd numbers.

Separating the identifiers in two classes allows clients and servers to both initiate paths, without risking identifier collisions. The current single-class design only works because only the client initiates paths. Otherwise, we would have the risk of both client and servers picking the same path identifiers, and simultaneously sending "path challenges" with the same identifier, but using different IP addresses and UDP ports. This would create confusion.

The design itself is fairly simple: both endpoints advertise odd and even path identified connection identifiers. When the client creates a path, the client picks an available even numbered identifier advertised by the server; when the server creates a path, it picks an odd numbered identifier. When receiving a packet for a new path, each endpoint verifies that the new number is authorized. For example, if the client receives from the server a message on a new path, it verifies that the path identifier of the connection ID chosen by the server is odd. If not, it MAY signal an MP protocol violation. When responding, the endpoint picks a connection ID with the same path identifier as that of the incoming packet.

That much is clear, but then we have to look at the impact of the odd/even design on the number of paths in the initial_max_paths transport parameter, and in the MAX_PATHS frame. If we follow the design of the max streams design in RFC 9000, we should replace the initial_max_paths parameters by two separate parameters:

  • initial_max_paths_client: maximum number of path that the client may inititiate,
  • initial_max_paths_server: maximum number of path that the server may inititiate.

For each of those, the maximum would be the minimum of the values advertised by client and server. Instead of writing that the multipath option is not used if the initial_max_paths parameter is not present, we would have something a bit more complicated, i.e., stating that the frames are only used if at least one of the parameters is present.

Then we would also have to split the MAX_PATHS frame into MAX_PATHS_CLIENT and MAX_PATHS_SERVER.

All that is doable, but I wonder whether this complexity is justified. Maybe what we need instead is just a way to resolve the "path identifier collision". For example, assuming just on path identifier space, we could have a "client win" rule: if the client creates path N with a specific 4 tuple and then receives a path message with identifier N from the server using a different 4 tuple, it just ignores it; if the server sends a path challenge four path N with a four tuple, and then receives a path message from the client with a different 4 tuple, it consider its initial challenge as lost and only responds to the client's message.

So, I have a question: bite the complexity of 2 parallel path identifier sequences; or, simply add a "collisions" rule. What do people think?

initial_max_stream_data_bidi_local
initial_max_stream_data_bidi_remote

@huitema huitema changed the title Designing odd/even path-id Designing odd/even path-id, or not. Apr 3, 2024
@LPardue
Copy link
Member

LPardue commented Apr 4, 2024

I'm not sure I follow the frame split argument. Stream IDs are split 4 ways and don't require 4 different 4 types of MAX_STREAMS to manage vending credits - they only use 2 types for the bidi/uni split, not the client/server split.

I'm not sure I follow the argument that an initial_max_paths_client maximum would have to resolve to the minimum of what both endpoints sent. A client doesn't need to send the parameter at all.

My understanding during IETF is that it wasnt clear if people wanted server IDs today, socall we were doing is making space for some future extwnsion. In that case, it would be simple enough to define a parameter initial_max_paths_client sent only by the server, and then a frame to manage increasing that value sent only by the server. A future extension could use a new TP in the opposite direction and reuse the frame.

@huitema
Copy link
Contributor Author

huitema commented Apr 4, 2024

@LPardue I started writing up a copy of the stream-id design, but there is a difference. The "max path" parameter does not just control the "number of paths". It also controls "the number of paths for which the endpoint is willing to accept connection ID". So, suppose the server sends "initial_max_paths_client=0xffff", but the client is unwilling to accept connection IDs for more than 3 paths? The client will need to send "initial_max_paths_client=3" to constrain the server.

@mirjak
Copy link
Collaborator

mirjak commented May 14, 2024

The more I think it about it, I'm also not sure if the even/odd split is really the easiest solution or maybe just an unnecessary restriction. I think a collision rule is probably good enough, especially as I would think it is a very rare case that the client and server want to open a new path at the same time.

I'm not sure if ignoring the server initiated path challenge is best approach. It's probably the simplest and it should work as a path challenges can alway be lost. The other option (maybe more clean option?) would to send an path abandon and try again with a different path ID and then define a rule how to deconflict. E.g. the client picks the next and the server the one after or just waits for a while...? But that seems more fiddly than the "client-wins" rule @huitema proposed.

@huitema
Copy link
Contributor Author

huitema commented May 14, 2024

Shades of ALOHA, CDMA, CDMA-CD, etc... Yes, there are multiple ways to detect collisions. We can pick anyone we want, with two main goals:

  • the result should be ambiguous, i.e., both client and server agree on which path ID is in use with what 4-tuple.
  • the collision resolution allows for a reliable and timely initiation of paths by either peer.

I like "client wins" because of the timeliness properties, but I agree that "ignoring the server path challenge" does create ambiguity. Maybe we need some kind of explicit "Challenge Reject", with an "already in use" or "collision" rule. Or maybe just call it "challenge collision".

I don't know how far we want to go for detailing the collision resolution. If the path-id is the last available path, there is no resolution possible. If there is just one more available path, there is no need to specify it. So maybe better not say anything.

Stepping back, the question is whether we should do anything at all regarding server initiation. We could decide to just not allow it for now, and maybe just add a paragraph explaining that there are plausible collision resolution rules, give a plausible example, and let the designer of the "server initiated path" extension provide the full design.

@michael-eriksson
Copy link

FWIW, I am convinced that paths initiated from different endpoints should use separate sets of path IDs -- that is a trivial way to avoid designing and implementing (and debugging) collision handling logic. Also note that bidirectional streams work exactly this way in QUIC with good results.

Reserving odd path IDs for server-initiated paths already in this specification is OK with me, even if I don't really see the need.

@mirjak
Copy link
Collaborator

mirjak commented May 15, 2024

It's maybe not that complicated but it means you have to hold separate state for each side. I'm just not sure if that is necessarily at all. As such not splitting the path id space and use the "client-win" strategy is probably even more trivial.

@MikeBishop
Copy link
Contributor

This is reminiscent of the discussion about whether bidi/uni streams should be split by frame type or by stream ID. Stream ID won out, and I suspect we should follow QUIC precedent here.

@mirjak
Copy link
Collaborator

mirjak commented May 31, 2024

Even if we want to go for even/odd split, why do we have to already specify this now? If we anyway want to specify server-initiated path in an extension with a new transport parameter, we can also split up the path ID space then. I don't think there is a need to do anything now.

However, I still think we should allow to open new paths by the server and specify a simply conflict resolution rule. I don't see any reason why we could not allow for server-initiated paths. Specifying a conflict rule is the simplest solution without any overhead if you don't open paths by the server. Again if we need/want to do more and anyway need a new transport parameter for an extension we can still change and specify it then.

@mirjak
Copy link
Collaborator

mirjak commented Jun 2, 2024

To summarize the options:

  1. if we want to allow server initiated paths:
    1a) allow multiple paths with the same 4-tuple but clarify carefully when it is a migration event or not
    1b) specify a simple deconflict rule like client-wins
    1c) split the path ID space and add additional signal for client and server paths limits separately

  2. if we don’t want to allow for server-initiated right now:
    2a) reserve halve the path ID space for later
    3b) do nothing because we anyway need a new transport parameter and can even specify the split later

@huitema
Copy link
Contributor Author

huitema commented Jun 2, 2024

I am not sure about your option "1a". Why are you worried about "the same 4-tuple"?

@mirjak
Copy link
Collaborator

mirjak commented Jun 3, 2024

Ah sorry, I confused myself. The problem is not when you open the same 5-tuple with different paths ID but when you open different 5-tuples with the same path ID. However, I'm not sure we have a problem here either. RFC9000 only allows client-side migration. Therefore if a client receives a path validation for a path ID that is believes is already in use, it should simply ignore it. If the server receives a path validation that it believes is already in use, it should treat it as migration event.

@mirjak
Copy link
Collaborator

mirjak commented Jun 3, 2024

To complete the discussion: If both ends open the same 4-tuple path with different path IDs at the same time, this is currently also not really allowed by the specific as we say that one 4-tuple can only have one path. However, we could simply allow that. If then only one path is used for sending, the other path would time out. If both path are used, we could make recommendation about use of coupled congestion control but not sure if it really makes sense to try to enforce that only one path can be opened per 4-tuple.

@LPardue
Copy link
Member

LPardue commented Jun 3, 2024

Discussed during meeting: Agreement that we need to make the decision now. No strong use cases for server-chosen right now. Some concerns the split could add complexity; there may also be some complexity in the single space approach. Some propoents of the split can live with single space. Interest in giving single space a go, we can split later if we really have to.

Outcome: consesus call to close this issue with no action to be sent to list

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants