Subject: [quicwg/base-drafts] Unidirectional stream all the control things in HTTP/3 (#2678)

From: Mike Bishop <[email-masked]>
Date: Wed, 08 May 2019 09:14:45 -0700

Separating out discussion from #2502:

@martinthomson:
> That suggests the creation of a "priority" stream...

@LPardue:
> A priority stream, in our current scheme, has some desireable properties because it aligns with the asymmetry, i.e. only client can create a priority stream. If anyone cared you could borrow QPACK encoder/decoder model so that the client has clear indication when priorities were processed. One could go as far as adopting that model further,
> 
> 1. priority stream(s) contains unframed instructions
> 2. PRIORITY frame on request is just a shell that contains references to priority state.
> 
> This opens a possibility to have alternative priority schemes based on opening different types of priority streams.
> 
> It all sounds terribly complicated though :D

@martinthomson:
> Not really complicated. Possibly less complicated, especially if you consider that dropping the priority stream could be permitted if it were separated from SETTINGS. And SETTINGS could get its own stream too :)
> 
> I wouldn't go so far as to say unframed priority signals, but the possibility to dispense with framing is appealing to some extent. Complicated comes when you have a marked in a stream saying what priority state you are depending on. That wouldn't necessarily be a blocking signal in the same way that QPACK is, but it certainly drives complexity upward slightly.

More generally, the control stream provides stronger ordering guarantees than are needed, and produces head-of-line blocking if a frame can't be immediately consumed for some reason (a possibility being discussed in #2502).

We have a small set of frames which are sent on the control stream:
- SETTINGS (sent only once)
- PRIORITY (ordering requirements only with respect to each other)
- CANCEL_PUSH (no ordering requirements)
- GOAWAY (currently ordering requirements only with respect to each other; could be unordered without loss of information)
- MAX_PUSH_ID (currently ordering requirements only with respect to each other; could be unordered without loss of information)

Some of these might be reasonable candidates for unidirectional streams of possibly-unframed instructions, similar to QPACK. If enough things fall into this category, we could potentially eliminate the control stream.  While this has implications for extensions being ported to HTTP/3, saying that what was a new frame type on the control stream becomes a new unidirectional stream type with length-prefixed payloads of known type isn't as big a leap as it might initially seem.

Note that this would make #2559 even more of a problem.  What do you do without enough unidirectional stream ID space to send your GOAWAY, for example?

I don't necessarily advocate this change, given how late we are in the process, but I'd rather have it as a separate issue for discussion than get it intertwined with the discussion on #2502.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 08 May 2019 09:26:34 -0700

Lest we forget #2418 which discusses the MAX_PUSH_ID stream idea.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-490555859

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 08 May 2019 09:31:39 -0700

> Note that this would make #2559 even more of a problem. What do you do without enough unidirectional stream ID space to send your GOAWAY, for example?

One mitigation is to get more explicit with how these "very important" streams are made. I.e. for the standard profile of QUIC we state that there is an absolute minimum number of streams and, more importantly, the peer's create them in a standard and deterministic way.

This backtracks a little, to how things were before unidirectional stream type, but it still allows extension streams to be deployed in a less coordinated way.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-490557581

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 09 May 2019 00:05:21 -0700

I think I am opposed to having a dedicated stream for PRIORITY frames.

If I understand correctly, the suggestion is based on either of the following two conceptions:
* sending priority information only on a dedicated stream is better than allowing the initial priority to be specified on the request stream
* it is a good idea to block processing of PRIORITY frames if there is a unresolved inter-stream dependency

I am not sure if either of the two is true. For the first point, the increased chance of not having prioritization information when receiving a request is a concern (see https://github.com/quicwg/base-drafts/issues/2502#issuecomment-490330136). For the second point, my understanding is that the ideal behavior is different. It is my understanding that the server should solely refer to the weight of the request stream when the stream's location within the tree cannot be resolved (see https://github.com/quicwg/base-drafts/issues/2502#issuecomment-490689310).

Considering these points, I am not sure if we want to incentivize servers processing PRIORITY frames in order. I might also point out that the servers willing to process them in order can buffer the PRIORITY frames after reading them out from the receive buffer of the control stream, and that the clients willing to send all the prioritization information in order can do that by sending the PRIORITY frames only on the control stream.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-490770664

---

From: Dmitri Tikhonov <[email-masked]>
Date: Thu, 09 May 2019 07:02:16 -0700

Stopping processing _PRIORITY_ frames has the effect of -- well, **stopping** processing _PRIORITY_ frames.  In other words, in addition to the presumed packet loss (discussed in #2502 as part of @rmarx original scenario), this approach effectively simulates even more packet loss.

Consider what happens when there are many existing streams that need to be reprioritized.  A loss of a possibly unrelated (different subtree) _STREAM_ packet would now cause delay in applying priorities of one or more RTTs.

Then there are the corner cases.  For example, what happens when the client decides to cancel the stream whose lost _STREAM_ packet caused the priority stream blockage?  Do we need a special _CANCELLED_STREAM_ instruction on the control stream that would allow the server to resume processing the priority stream?  If so, this would introduce even more dependencies between streams.

Similar to QPACK design, stream prioritization mechanism should minimize the number of stream interdependencies and potential for priority inversion.  The current (http-20) spec is not perfect, but it has the profitable feature of stream independence.  Combined with the guarantee of eventual consistency, it strikes a good balance between complexity and performance.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-490917885

---

From: ianswett <[email-masked]>
Date: Tue, 14 May 2019 11:36:00 -0700

@dtikhonov Q on "Then there are the corner cases. For example, what happens when the client decides to cancel the stream whose lost STREAM packet caused the priority stream blockage?" 

In this case, the server would either have to block until the stream was reset or buffer priority operations for later use.  I agree both of these options are fairly unappealing, but is there a reason it's worse than that?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-492357584

---

From: Dmitri Tikhonov <[email-masked]>
Date: Tue, 14 May 2019 12:01:31 -0700

I state that buffering priority frames because of a lost packet on an unrelated stream is not just unappealing, it's bad design.  This is because the client wants those priorities changed 1/2 RTT ago.  Expedient reprioritization of streams is a design goal.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-492367028

---

From: ianswett <[email-masked]>
Date: Tue, 14 May 2019 19:13:45 +0000 (UTC)

I agree it's a bad design.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2678#issuecomment-492371492