GrumpyOldTroll / draft-jholland-quic-multicast

Work in progress to propose a multicast extension to quic.
Other
6 stars 6 forks source link

Can the same stream ID be used in multiple channels? #29

Closed MaxF12 closed 2 years ago

MaxF12 commented 2 years ago

Since the stream ID space is shared between all channels and the connection, would it be possible for two channels to send data on the same stream?

4.4 says: a server can always avoid stream ID collisions with the stream IDs carried in sessions Does this mean it MUST avoid collisions?

I guess it depends on where the stream data is processed, if there is a sub process for each channel it might be ok, but if they all end up in the same place you would presumably see different packets with the same ACK number (since each channel uses its own ACK number space, so they have to overlap), which would probably lead to issues.

In either case I think it is something that should be clarified.

GrumpyOldTroll commented 2 years ago

Yes, probably something should be clarified.

A rough answer to your questions: Stream frames for the same stream can appear on different channels, yes.

However, all stream frames for the same stream still have to represent data from a single continuous stream of bytes, such that data at the same offset is identical regardless of what path a stream frame arrived on. So for example, as explained in 2.2 of 9000, "The data at a given offset MUST NOT change if it is sent multiple times; an endpoint MAY treat receipt of different data at the same offset within a stream as a connection error of type PROTOCOL_VIOLATION".

You could send a frame with bytes 0-15 for stream 3 on channel 1, and then send a frame with bytes 16-30 for stream 3 on channel 2, then send a frame with bytes 10-25 over unicast. While probably inefficient, this would all be correct behavior that can be properly interpreted by the client as long as the byte at each offset of that stream is the same no matter where it came from.

The more likely real scenario is recovery. You send a packet 14 on channel 1 and it contains bytes 50-100 of stream 3, but the MP_CHANNEL_ACKS the server sees suggest the packet has probably been lost. Server then sends packet 70 on its unicast channel, and it contains a copy of the frame that was lost in packet 14 of channel 1, thus filling in the missing data. If packet 70 is lost as well, maybe later it'll send packet 80 with another copy of the same frame (or maybe it'll break up the frame into smaller pieces, which is fine as long as each byte at each offet is still the same.)

It doesn't matter for the stream that there's different packet number spaces. The server is responsible for knowing what stream frames the receiver has received on each path according to the acks (and what the contents of those frames were, so it can retransmit). As an optimization, the collection of servers using the same channel might also notice that many receivers on the same channel lost the same packet, and you might send a new packet on that channel containing the frames that need retransmitting, rather than using unicast for the recovery.

GrumpyOldTroll commented 2 years ago

The comment about stream ID collisions is maybe a mistake. It's ok to coordinate sending of stream data on different channels, provided it's the same stream data. What's not ok is if the different channels each think they're independently in charge of the data that goes out in a particular stream id, and therefore produce different data for the stream at any of the same offsets. "Collision" is probably too ambiguous a term there, sorry for the confusion.

GrumpyOldTroll commented 2 years ago

As a matter of operational practice, the way I imagine actually running is that there's one thing generating the stream, and the stream data might be mirrored on a few channels (for instance, an ipv4 and an ipv6 channel, or maybe channels with different encryption algorithms, in order to support different sets of receivers with different capabilities). The IPv4 channel will probably break the stream up into frames at different offsets from the IPv6 channel, because they'll have different packet payload sizes. This is ok, provided that they carry the same sequence of data.

A receiver might leave one network and join another network, and as a result might switch (at server's direction, after passing new client limits derived from its network change) from the ip4 channel to the ip6 channel. Maybe it misses a few packets, which the server notices via the mp_channel_acks, so server fills in the missing stream data with unicast-transmitted data of the same stream (this might or might not have offset boundaries for the frames that get generated that are different from the channels' frame boundaries). Although each of these paths has a different packet number space, since they're all using the same stream id and the data at each offset in the stream id is the same no matter where it came from, they can always avoid confusion.

This kind of stream handling is all the same as in multipath and connection migration, I believe. It doesn't matter what packet number space stream data arrived on for the client, just the stream id and the offset.

The packet number space is what gets acked, so the server has to keep track of which frames were in which packets so it can retransmit frames with the stream data that the client is still missing. (It doesn't have to be the same frames, it just has to carry the same data. 2 frames from 50-100 and 101-150 is the same as 1 frame from 50-150, is the same as 3 frames from 50-75, 76-125, and 126-150, as long as they're the same stream id and the byte at every offset is the same.)