Subject: partially unreliable quic streams

From: Mikkel Fahnøe Jørgensen <[email-masked]>
Date: Tue, 19 Sep 2017 00:21:58 -0700

Hi Anja und Jörg

Regarding
https://tools.ietf.org/html/draft-tiesel-quic-unreliable-streams-00

I’m not sure where this draft fits into to the QUIC design process process
since my understanding is that unreliable streams is for a later charter in
the design process.

A quick read through the draft makes me wonder if you considering some
partial reliable ideas that have emerged out of the currently unfinished
concept of unidirectional streams and if you can incorporate these ideas
into your draft?

Essentially the idea is each stream is sequence of messages which are
reliable but suffer head of line blocking when each message is separated by
an application specific message header. In the simplest form the stream is
just one message.

For unreliable streams, the concept is inverted: each stream is a single
message which starts an application specific unreliable stream identifier
embedded in the stream/message. The ordering of messages is given by the
QUIC level stream id which always increases (effectively a message id in
this context) but there is no head of line blocking nor any delivery
ordering because each message is independent.

Thus the space consumed is the same for the two concepts but the
interpretation is different.

An implementation can further cooperate by not retransmitting sufficiently
old or otherwise outdate messages. Currently QUIC has no way to explicitly
configure this and dropping retransmission of frames might affect
congestion control. Therefore in its current form QUIC cannot properly
unreliable streams, only prevent head of line blocking.

It is worth noting that with once message per stream there can be many
messages per packet which can significantly increase the messages per
second rate and therefore also requires efficiently management of stream
state - such as discarding send state immediately after sending FIN (except
retransmission machinery).

Kind Regards,
Mikkel Fahnøe Jørgensen

---

From: Mikkel Fahnøe Jørgensen <[email-masked]>
Date: Tue, 19 Sep 2017 00:44:58 -0700

Sorry, forgot all authors

Kind Regards,
Mikkel Fahnøe Jørgensen

On 19 September 2017 at 09.21.58, Mikkel Fahnøe Jørgensen (
[email-masked]) wrote:

Hi Anja und Jörg

Regarding

Kind Regards,
Mikkel Fahnøe Jørgensen

---

From: "Philipp S. Tiesel" <[email-masked]>
Date: Tue, 19 Sep 2017 19:49:10 +0200

Hi Mikkel,

as I wrote most of the draft, I’ll to answer your questions and clarify some details. 

> On 19. Sep 2017, at 09:21, Mikkel Fahnøe Jørgensen <[email-masked]> wrote:
> 
> Hi Anja und Jörg
> 
> 
> Regarding https://tools.ietf.org/html/draft-tiesel-quic-unreliable-streams-00
> 
> I’m not sure where this draft fits into to the QUIC design process process since my understanding is that unreliable streams is for a later charter in the design process.

I understand your criticism, but we decided to go forward and publish our observations about unreliable streams. The QUIC WG was chartered to exclude reliable streams from the first release to speed up the design process. That does not mean unreliable streams are explicitly out of scope for later releases. Therefore, I think that documenting how unreliable streams fit into the current QUIC drafts are useful feedback for the design process.

As already stated in the draft announcement, the primary feedback is:
a) unreliable streams can be added to QUIC as drafted so far
   => No action required, current design is fine for that aspect
b) one more flag bit in the stream header makes unreliable streams much easier to implement
   => As the problem also arose for other desirable features, reserving a few bits in the stream frame header sounds like a good idea.

> A quick read through the draft makes me wonder if you considering some partial reliable ideas that have emerged out of the currently unfinished concept of unidirectional streams and if you can incorporate these ideas into your draft?
> 
> Essentially the idea is each stream is sequence of messages which are reliable but suffer head of line blocking when each message is separated by an application specific message header. In the simplest form the stream is just one message.
> 
> For unreliable streams, the concept is inverted: each stream is a single message which starts an application specific unreliable stream identifier embedded in the stream/message. The ordering of messages is given by the QUIC level stream id which always increases (effectively a message id in this context) but there is no head of line blocking nor any delivery ordering because each message is independent.
> 
> Thus the space consumed is the same for the two concepts but the interpretation is different.

I see unreliable streams and “stream as a message abstraction” as orthogonal concepts.

In QUIC, streams are byte streams, not message streams.
Thus, their content are completely oblivious to the transport layer.
If you want a message abstraction on top of QUIC, you either send exactly one message per stream or use your own framing.

Whether the bytes of a stream are delivered reliable or not does not change the head of line blocking problem when waiting for the message delimiter.
If the message delimiter is in “a hole" of the unreliable stream, you either have to discard both messages or wait for retransmission (which can still be done if the sender decides to).
But with unreliable streams, you could search for complete messages in the received parts after "a hole” .  

> An implementation can further cooperate by not retransmitting sufficiently old or otherwise outdate messages. Currently QUIC has no way to explicitly configure this and dropping retransmission of frames might affect congestion control. Therefore in its current form QUIC cannot properly unreliable streams, only prevent head of line blocking.

The draft exactly discusses the design space for such a mechanism.
It concludes that a mechanism to control retransmits, when sender-controled, requires only few considerations at the wire-protocol (e.g., requires not loosing FINs), but has much impact on the API used by the application.

I don’t see how dropping retransmissions effects congestion control as the only inputs to CC are acked/lost packets and bytes send.

> It is worth noting that with once message per stream there can be many messages per packet which can significantly increase the messages per second rate and therefore also requires efficiently management of stream state - such as discarding send state immediately after sending FIN (except retransmission machinery).

This definitely is an issue of the “stream as a message abstraction”.
It gets more ugly if combined with reliable streams as the “FIN” of unreliable streams needs to be retransmitted to prevent stale state (or “zombie-streams”, as we call in in the draft).
As the recovery draft does not tell you how to retransmit the retransmitable contents of a lost packet, closing a unreliable stream by (re)transmitting the FIN only (as an empty stream frame with final offset and FIN set) is fine.

AVE!
  Philipp S. Tiesel

---

From: Mikkel Fahnøe Jørgensen <[email-masked]>
Date: Tue, 19 Sep 2017 20:09:43 +0200

Hi Philipp, thanks for getting back - I’m not really criticising nor am I
an official representative of the QUIC design body, I was just asking where
this was fitting into the QUIC context.

Just one clarification on message abstraction:

The intention is not inherently to provide messages over streams as much as
points where it makes sense to create holes as you mention (though this is
also useful).  However, dealing with holes in a stream, is more complicated
than consider a stream broken up by messages, notably “virtual streams”
where each true stream is a message in the virtual, or partially reliable
stream.

I earlier made some design proposals on how to frame partial reliability.
However, with the new unidirectional stream proposal, the same can be
achieved much simpler by viewing streams as messages - where a message can
be a video frame or whatever. This very transparently allows low-level
machinery to deal with what is delivered and skipped because boundaries are
communicated efficiently via separate streams.

On the retransmission part of the message abstraction - this is definitely
something that require additional protocol support to prevent zombies, as
you say.

The earlier design notes I added in comments can be found in these closed
issues

https://github.com/quicwg/base-drafts/issues/489
https://github.com/quicwg/base-drafts/issues/433

However, here each frame has a bit to indicate where a boundary in the
stream begins, i.e. where a hole is permitted - the API becomes more
complicated due to friction of concepts.

I’m not saying what is the ideal solution - just that the message
abstraction came out very naturally once Martin Thomson provided the
unidirectional proposal. Ian Sweet hat earlier argued for similar use of
light weight streams in bidi streams, but in my opinion they were to heavy
weight because a sender must wait for the receiver to close the other end -
with uni streams state can be purged must faster make the concept feasible
at high frequencies.

Kind Regards,
Mikkel Fahnøe Jørgensen

On 19 September 2017 at 19.49.31, Philipp S. Tiesel ([email-masked])
wrote:

Hi Mikkel,

as I wrote most of the draft, I’ll to answer your questions and clarify
some details.

>
> I’m not sure where this draft fits into to the QUIC design process
process since my understanding is that unreliable streams is for a later
charter in the design process.

I understand your criticism, but we decided to go forward and publish our
observations about unreliable streams. The QUIC WG was chartered to exclude
reliable streams from the first release to speed up the design process.
That does not mean unreliable streams are explicitly out of scope for later
releases. Therefore, I think that documenting how unreliable streams fit
into the current QUIC drafts are useful feedback for the design process.

As already stated in the draft announcement, the primary feedback is:
a) unreliable streams can be added to QUIC as drafted so far
=> No action required, current design is fine for that aspect
b) one more flag bit in the stream header makes unreliable streams much
easier to implement
=> As the problem also arose for other desirable features, reserving a few
bits in the stream frame header sounds like a good idea.

I see unreliable streams and “stream as a message abstraction” as
orthogonal concepts.

In QUIC, streams are byte streams, not message streams.
Thus, their content are completely oblivious to the transport layer.
If you want a message abstraction on top of QUIC, you either send exactly
one message per stream or use your own framing.

Whether the bytes of a stream are delivered reliable or not does not change
the head of line blocking problem when waiting for the message delimiter.
If the message delimiter is in “a hole" of the unreliable stream, you
either have to discard both messages or wait for retransmission (which can
still be done if the sender decides to).
But with unreliable streams, you could search for complete messages in the
received parts after "a hole” .

> An implementation can further cooperate by not retransmitting
sufficiently old or otherwise outdate messages. Currently QUIC has no way
to explicitly configure this and dropping retransmission of frames might
affect congestion control. Therefore in its current form QUIC cannot
properly unreliable streams, only prevent head of line blocking.

The draft exactly discusses the design space for such a mechanism.
It concludes that a mechanism to control retransmits, when
sender-controled, requires only few considerations at the wire-protocol
(e.g., requires not loosing FINs), but has much impact on the API used by
the application.

I don’t see how dropping retransmissions effects congestion control as the
only inputs to CC are acked/lost packets and bytes send.

This definitely is an issue of the “stream as a message abstraction”.
It gets more ugly if combined with reliable streams as the “FIN” of
unreliable streams needs to be retransmitted to prevent stale state (or
“zombie-streams”, as we call in in the draft).
As the recovery draft does not tell you how to retransmit the
retransmitable contents of a lost packet, closing a unreliable stream by
(re)transmitting the FIN only (as an empty stream frame with final offset
and FIN set) is fine.

AVE!
Philipp S. Tiesel