Subject: Lost initial MAX_PUSH_ID is unfortunate

From: Ryan Hamilton <[email-masked]>
Date: Tue, 27 Aug 2019 15:47:38 -0700

Howdy Folks,

In some testing we've been doing, we realized that if the packet
containing the initial MAX_PUSH_ID frame is lost (or reordered until after
the first request) then the server is unable to push responses. This is a
bit unfortunate. We could, of course, bundle the MAX_PUSH_ID with all
packets that send a new request until the MAX_PUSH_ID is ACK'd. This feels
a tad inelegant and I wondered if there's any appetite for an alternative.

We've been talking about the prospect of putting SETTINGS into transport
params. If we did this, we could add a new setting for the initial max push
id value which would be guaranteed to be delivered before requests. This
seems like a much more elegant solution to the problem.

What do folks think?

Cheers,

Ryan

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 28 Aug 2019 00:06:18 +0100

Hi Ryan,

This doesn't sound any different to the case when a server receives a
request when the push ID limit is reached; a client may have attempted to
update the limit but the delivery or processing of the frame happened after
the request was received.

Because this can happen at any time during a connection, I would be opposed
to adding special case code for the initial max value; it seems it would be
simpler for implementations to have one path for dealing with this
eventuality.

Cheers
Lucas

---

From: "Martin Thomson" <[email-masked]>
Date: Wed, 28 Aug 2019 13:00:09 +1000

On Wed, Aug 28, 2019, at 08:48, Ryan Hamilton wrote:
> containing the initial MAX_PUSH_ID frame is lost (or reordered until 
> after the first request) then the server is unable to push responses. 
> This is a bit unfortunate. We could, of course, bundle the MAX_PUSH_ID 
> with all packets that send a new request until the MAX_PUSH_ID is 
> ACK'd. This feels a tad inelegant and I wondered if there's any 
> appetite for an alternative.

I don't think that this is great justification for that sort of change.  We explicitly removed head of line blocking from the processing of SETTINGS.  In practice, I suspect that this situation also results in no access to QPACK also.

Performance might suffer, but at least you can send something sensible in a round trip when you would otherwise (with h2 for instance) be twiddling thumbs.

---

From: Nick Harper <[email-masked]>
Date: Wed, 28 Aug 2019 11:38:42 -0700

On Tue, Aug 27, 2019 at 8:00 PM Martin Thomson <[email-masked]> wrote:

> I don't think that this is great justification for that sort of change.
> We explicitly removed head of line blocking from the processing of
> SETTINGS.  In practice, I suspect that this situation also results in no
> access to QPACK also.
>
> Performance might suffer, but at least you can send something sensible in
> a round trip when you would otherwise (with h2 for instance) be twiddling
> thumbs.
>
> Why can't we have the best of both worlds? If we put this signal in the
crypto handshake, the application protocol can guarantee that it arrives
before any STREAM frames, and we don't introduce any more head of line
blocking because the connection is already blocked on the crypto handshake
messages to derive 0-RTT or 1-RTT application data keys.

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 28 Aug 2019 20:27:26 +0100

Lets take an extreme case, the client sends an initial max push ID of 1. On
the first request the server sends a push promise - now its out of credit
when chances are it wanted to push more than one thing. So it's back to
"waiting" for a MAX_PUSH_ID or just giving up on push. The server needs all
the logic to manage this exhaustion case.

I think we are ok with what we have. But if we want off the wall ideas:
allow MAX_PUSH_ID frames on request streams before HEADERS (solving the
sequencing problem) and relax the rules for connection errors on limit
decrement.

---

From: "Martin Thomson" <[email-masked]>
Date: Thu, 29 Aug 2019 09:49:32 +1000

On Thu, Aug 29, 2019, at 04:39, Nick Harper wrote:
> crypto handshake, the application protocol can guarantee that it 
> arrives before any STREAM frames, and we don't introduce any more head 
> of line blocking because the connection is already blocked on the 
> crypto handshake messages to derive 0-RTT or 1-RTT application data 
> keys.

You can already have that.  Coalescing the packet containing SETTINGS/MAX_PUSH_ID with the last Handshake packet is entirely possible and has the same net effect.  And most implementations will be able to manage that (at least on the client side, coalescing 0.5RTT from the server is a little challenging).

But it's not best of both worlds, that would be forcing head of line blocking.  Right now, implementations choose their level of exposure.

---

From: Ryan Hamilton <[email-masked]>
Date: Thu, 29 Aug 2019 06:51:43 -0700

On Wed, Aug 28, 2019 at 4:50 PM Martin Thomson <[email-masked]> wrote:

> You can already have that.  Coalescing the packet containing
> SETTINGS/MAX_PUSH_ID with the last Handshake packet is entirely possible
> and has the same net effect.  And most implementations will be able to
> manage that (at least on the client side, coalescing 0.5RTT from the server
> is a little challenging).
>
> But it's not best of both worlds, that would be forcing head of line
> blocking.  Right now, implementations choose their level of exposure.
>

Yeah, coalescing SETTINGS/MAX_PUSH_ID along with the last handshake packet
is definitely a possibility, and is the option I'm planning to pursue in
our implementation if the proposal to put SETTINGS in Transport Params is
really dead :) On the other hand if that proposal gains traction, I'd love
to see an initial max push id setting.