Subject: Re: Spencer Dawkins' Discuss on draft-ietf-httpbis-http2-16: (with DISCUSS and COMMENT)

From: Mark Nottingham <[email-masked]>
Date: Thu, 22 Jan 2015 19:21:08 +1100

Hi Spencer,

> On 22 Jan 2015, at 6:07 pm, Spencer Dawkins <[email-masked]> wrote:
> 
> I'm confused between these two statements:
> 
>   1.  Flow control is specific to a connection; i.e., it is "hop-by-
>       hop", not "end-to-end".
> 
> and 
> 
>   Both types of flow control are hop-by-hop; that is, only between the
>   two endpoints.
> 
> Could you help me get unconfused?

In HTTP, "hop by hop" means the immediate HTTP connection, whereas "end to end" means the path between the user agent (the ultimate client) and the origin server (the ultimate server), potentially taking in any number of intermediaries on the way.

It might clarify a bit to change the end of the latter one to "... between the client and server of a single connection."

Cheers,

--
Mark Nottingham   https://www.mnot.net/

---

From: Barry Leiba <[email-masked]>
Date: Thu, 22 Jan 2015 10:19:25 -0500

On Thu, Jan 22, 2015 at 3:21 AM, Mark Nottingham <[email-masked]> wrote:
> In HTTP, "hop by hop" means the immediate HTTP connection, whereas
> "end to end" means the path between the user agent (the ultimate
> client) and the origin server (the ultimate server), potentially
> taking in any number of intermediaries on the way.
>
> It might clarify a bit to change the end of the latter one to "...
> between the client and server of a single connection."

Spencer's confusion is with the word "endpoints" in the second quote,
and I don't think this change fixes that, as "client and server" can
also be misconstrued (and even with the "of a single connection"
there, they might be).

Why not try to stay with the same terminology?:  "Both types of flow
control are between the endpoints of a single hop, and not over the
entire end-to-end path."

Barry

---

From: Mark Nottingham <[email-masked]>
Date: Fri, 23 Jan 2015 06:36:53 +1100

> On 23 Jan 2015, at 2:19 am, Barry Leiba <[email-masked]> wrote:
> 

Works for me.

---

From: Martin Thomson <[email-masked]>
Date: Fri, 23 Jan 2015 07:04:03 -0800

Spencer, your pull request is:
https://github.com/http2/http2-spec/pull/702

In case you want to review changes.

> Could you help me get unconfused?

I'm going to take Barry's recommendation for the first (and leave the
second alone).

> This is a very minor point, but this text
>
>    In particular, HTTP/1.0 allowed only one request to be outstanding at
>    a time on a given TCP connection.  HTTP/1.1 added request pipelining,
>    but this only partially addressed request concurrency and still
>    suffers from head-of-line blocking.  Therefore, HTTP/1.1 clients that
>    need to make many requests typically use multiple connections to a
>    server in order to achieve concurrency and thereby reduce latency.
>
> doesn't seem quite right to me. HTTP/1.0 (without persistent connections)
> closed TCP connections to give an indication that the resource
> represented by the URL had been completely transferred. "one request to
> be outstanding at a time on a given TCP connection" sounds like you could
> send a second request on that TCP connection after you receive a response
> to the first request, but that's not possible. And HTTP/1.0 clients
> certainly opened multiple connections to a server as well. Could you look
> at this text one more time?

I think that the HTTP/1.0 text is is largely OK, at least at the level
of detail that we require here (it's strictly true, regardless of
whether connections are closed, and sometimes the implication is true
too).

The point about the last sentence is worth fixing though.  I think
adding "HTTP/1.0 or " should make it less problematic.

> In this text
>
>    Endpoints MUST NOT exceed the limit set by their peer.  An endpoint
>    that receives a HEADERS frame that causes their advertised concurrent
>    stream limit to be exceeded MUST treat this as a stream error
>    (Section 5.4.2) of type PROTOCOL_ERROR or REFUSED_STREAM.
>
> I'm wondering why both of these stream error types are appropriate here.
> Is there any guidance about when to choose one type or the other?

This is explained elsewhere, specifically the description of those
error codes.  But you are right, a little hint wouldn't hurt.

The rationale here, as I explain in the PR, is that we sometimes want
to signal that automatic retries are possible for whatever the stream
carried.  That's REFUSED_STREAM.  However, we also want to permit a
zero-tolerance approach where this serious violation of the
specification can be made more visible.  REFUSED_STREAM can
effectively hide what is a fairly serious error.  That's
PROTOCOL_ERROR.

> In this text:
>
>    After sending a SETTINGS frame that reduces the initial flow control
>    window size, a receiver has two options for handling streams that
>    exceed flow control limits:
>
>    1.  The receiver can immediately send RST_STREAM with
>        FLOW_CONTROL_ERROR error code for the affected streams.
>
>    2.  The receiver can accept the streams and tolerate the resulting
>        head of line blocking, sending WINDOW_UPDATE frames as it
>        consumes data.
>
> I found myself wondering how a receiver would choose between these
> options. Is there any guidance you could provide?

This already contains a fair clue as to the ramifications of either
choice.  The first means that you lose requests or responses.  The
second, that you potentially stall progress on those requests or
responses.

I personally think that if you can keep the requests, that is going to
cost less in the long run, but if you absolutely don't have the RAM to
deal with them, something has to give.

Would the follow restructuring address your concern?

   After sending a SETTINGS frame that reduces the initial flow control
   window size, a receiver MAY continue to process streams that exceed
   flow control limits.  Allowing streams to continue does not allow the
   receiver to immediately reduce the space it reserves for flow control
   windows.  Progress on these streams can also stall, since
   WINDOW_UPDATE frames are needed to allow the sender to resume
   sending.  The receiver MAY instead send a RST_STREAM with
   FLOW_CONTROL_ERROR error code for the affected streams.

Does that additional sentence in the middle, plus the reordering of
concerns, work?

> For this reference:
>
>    [TCP]      Postel, J., "Transmission Control Protocol", STD 7, RFC
>               793, September 1981.
>
> perhaps https://tools.ietf.org/html/draft-ietf-tcpm-tcp-rfc4614bis-08,
> currently in the RFC Editor's queue, would be more appropriate?

I notice that this is destined to be informational.  We do have a
normative dependency on TCP.  But I do recognize the inadequacy of 793
on its own.  I'll defer to others on this one.

---

From: Barry Leiba <[email-masked]>
Date: Fri, 23 Jan 2015 15:22:50 -0500

> "New rule: anyone who uses RFC 793 as shorthand for TCP has to use TCP as
> defined in RFC 793. It doesn't even have Slow Start"
>
> So I hope that the others you're deferring to, do the right thing!

OK, well, here's the thing:

1. Most uses of TCP don't even use a reference.  We consider TCP to be
sufficiently well known that we don't expect to have to provide a
reference for it.

2. That said, we do rather say that STD 7 is TCP.

3. Whenever this comes up, the bottom line is that there's no good
reference that we SHOULD use for TCP.

If we want to have a proper reference for TCP, someone or some working
group (TSVWG, maybe?) needs to do one of two things:

a) update STD 7 to include the other documents that properly define
TCP today, so that STD 7, as a group of documents, can be used as a
reference, or

b) create a new "TCP roadmap" document that explains what people who
need to refer to documents about TCP need to know in order to find the
right documents for their purpose, and then have us reference *that*
new RFC.

It's simply not useful to have this keep coming up, and to have the
discussion continue to result in "Well, there's not really a good
reference that we can use."

Barry