Subject: Repurpose of priority | Re: SETTINGS_PRIORITY_SCHEME | Re: Setting to disable HTTP/2 Priorities

From: Kari Hurtta <[email-masked]>
Date: Thu, 1 Aug 2019 19:46:26 +0300 (EEST)

> It's difficult for a server to guess at the client intent. Not sending
> PRIORITY information is also a signal to prioritise the request with
> default RFC7540 parameters (depend on root node with weight 16). So having
> a clear signal from client to server along the lines of "I don't intend to
> send, and don't infer any RFC7540 meaning from it" avoids that problem and
> my impression from Montreal was that this is a desirable goal. In Montreal
> we also discussed a possible experiment where the H2 PRIORITY frame
> contents would be repurposed, which requires a compatible server to read it
> correctly. In this case the signal would be more like "will send in an
> RFC7540-incompatible format".
> 
> Lucas

Note that http client may send data before it is read SETTINGS frame
which is part of the server connection preface.

https://tools.ietf.org/html/rfc7540#section-3.5https://tools.ietf.org/html/rfc7540#section-3.5

|   To avoid unnecessary latency, clients are permitted to send
|   additional frames to the server immediately after sending the client
|   connection preface, without waiting to receive the server connection
|   preface.  It is important to note, however, that the server
|   connection preface SETTINGS frame might include parameters that
|   necessarily alter how a client is expected to communicate with the
|   server.  Upon receiving the SETTINGS frame, the client is expected to
|   honor any parameters established.  In some configurations, it is
|   possible for the server to transmit SETTINGS before the client sends
|   additional frames, providing an opportunity to avoid this issue.

So if SETTINGS frame changes meaning of PRIORITY data which is already
sent, that causes that server will interpreted it different than
what http client intended.

There may be also Stream Dependency field on HEADERS frame.

And also PRIORITY frame may be send before HEADERS frame when stream
is on idle state. 

So that repurpose will not work.

/ Kari Hurtta

---

From: Lucas Pardue <[email-masked]>
Date: Thu, 1 Aug 2019 18:47:22 +0100

> So that repurpose will not work.
Any client that is taking the chance to make a semantic change to the
frames it is sending would be foolish to not wait on an affirmative signal
from the server. RFC 7540 Section 5.5. calls specific attention to such a
repurposing:

>    Extensions that could change the semantics of existing protocol
   components MUST be negotiated before being used.  For example, an
   extension that changes the layout of the HEADERS frame cannot be used
   until the peer has given a positive signal that this is acceptable.

Lucas

---

From: Kari Hurtta <[email-masked]>
Date: Sat, 3 Aug 2019 10:58:22 +0300 (EEST)

>    until the peer has given a positive signal that this is acceptable.

Okei,

Generally repurpose of protocol element requires 3 values (or 2
bits from bitmask) for SETTINGS parameter SETTINGS_ENABLE_{feature}.
For example values

 •  0       {feature}_NOT_SUPPORTED,
 •  1       {feature}_AVAILABLE
 •  3       SENDING_{feature}       

Recipient of repurposed protocol element sends first
SETTINGS parameter SETTINGS_ENABLE_{feature} with value
1 ({feature}_AVAILABLE).

Sender of repurposed protocol element sends SETTINGS parameter 
SETTINGS_ENABLE_{feature} with value 3 (SENDING_{feature})
before it starts sending repurposed protocol element.

Recipient interprets protocol element without {feature}
until it receives SETTINGS parameter SETTINGS_ENABLE_{feature} 
with value 3 (SENDING_{feature}).

Sending SETTINGS parameter SETTINGS_ENABLE_{feature} with
value 3 (SENDING_{feature}) is protocol violation unless
SETTINGS parameter SETTINGS_ENABLE_{feature} with value
1 ({feature}_AVAILABLE) or 3 (SENDING_{feature}) is received
first.

Both directions needs separately send SETTINGS parameter 
SETTINGS_ENABLE_{feature} with value 3 (SENDING_{feature})
before repurposed protocol element can be sent.

SETTINGS parameter SETTINGS_ENABLE_{feature} value 3 (SENDING_{feature})
imply total ordering of frames, so this means HTTP/2. ( Also
HTTP/3 do not allow several SETTINGS frames.)

SETTINGS frame with parameter SETTINGS_ENABLE_{feature} with 
value 3 (SENDING_{feature}) indicates time when change
on purpose of protocol element happens.

It is not just enough to know that change is acceptable
for recipient. Recipient must know when change happens.

Introducing of new protocol elements do not require
sending SETTINGS parameter SETTINGS_ENABLE_{feature}
with value 3 (SENDING_{feature}) when frame content
indicates precense of protocol element.

/ Kari Hurtta

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 7 Aug 2019 15:41:02 +0100

Hi Kari,

Thanks for sharing your thoughts on this thread (and also thanks to you and
Matthew Kerwin for sharing your thoughts on other threads).

To best track things, I plan to summarize some of the discussed options as
an issue on the I-D's repo. When I get around to that, I'll share the link
back to the list.

Cheers
Lucas

---

From: Kari Hurtta <[email-masked]>
Date: Thu, 8 Aug 2019 20:38:58 +0300 (EEST)

<  ⋯ >
> > In Montreal we also discussed a possible experiment where the H2 PRIORITY
> > frame contents would be repurposed, which requires a compatible server to
> > read it correctly. In this case the signal would be more like "will send in
> > an RFC7540-incompatible format".
> >
> > Lucas
> >
> 
> Eurgh, why?  Are we that short on frame types?
> 
> Cheers
> -- 
>   Matthew Kerwin
>   https://matthew.kerwin.net.au/

Yes, it makes sense to allocate new type number for PRIORITY when frame
content is repurposed.

Also is make sense to allocate new type number for HEADERS when 
"Stream Dependency" or "Weight" field of HEADERS frame conrent is repurposed.

That avaind dance about on what point on time change of  "Stream Dependency" / "Weight" field"
field happens.

If you are running out of framer's type numbers, reserve some number for
"extended type number". ☻

/ Kari Hurtta

---

From: Lucas Pardue <[email-masked]>
Date: Thu, 8 Aug 2019 18:56:57 +0100

Note that it is not my suggestion to do the experiment this way. However,
one could theorise that the work required to support generating, sending,
receiving and processing new non-core frame types is greater than
implementing some conditional code inside the frame parser.

Yes frames are cheap, but they also offer an API surface that things get
sticky to. For example, reporting and metrics based on frame type counts
etc. That adds more overhead to an ad-hoc short-lived data-gathering
experiment.

Lucas

---

From: Matthew Kerwin <[email-masked]>
Date: Fri, 9 Aug 2019 08:16:06 +1000

> implementing some conditional code inside the frame parser.

One could also theorise the opposite.  For example: if someone had thought
to construct their core H2 engine in such a way that it offloads extension
values to modular/pluggable handlers.

It doesn't make sense to override an auxiliary frame like that, especially
just to appease implementers -- it's not like PRIORITY is welded to the
heart of the machine, like HEADERS.

> etc. That adds more overhead to an ad-hoc short-lived data-gathering

Good?  Resist the sticky interface.  (BTW, on metrics: how much easier is
it to report on "unknown frame type 0xD" as opposed to "frame that looks
like 0x2 but actually isn't because of the contents of some settings frames
sent elsewhere on this connection"?)

Cheers

---

From: Lucas Pardue <[email-masked]>
Date: Thu, 8 Aug 2019 23:38:50 +0100

> heart of the machine, like HEADERS.

HEADERS contain priority information. To experiment with priority requires
a change to how HEADERS are used. Theres no avoiding that. We can split
hairs on what the best way to design an experiment like this would be but
it feels like wasted effort.

Anyone that designed and produced an implementation that allows an easily
usable extension mechanism that can completely substitute aspects of the
core HTTP/2 machinery deserves a gold star.

> like 0x2 but actually isn't because of the contents of some settings
> frames sent elsewhere on this connection"?)
>

Simple frame counts have a place but there are likely higher-order things
going on. A reporting pipeline for HEADERS information is likely more
focused on the header contents characteristics than the priority
information. Defining a substitute HEADERS extension frame could require a
duplicate pipeline. Things like that provide resistance to experimentation.

---

From: Kari Hurtta <[email-masked]>
Date: Fri, 9 Aug 2019 08:26:49 +0300 (EEST)

> That avaind dance about on what point on time change of  "Stream Dependency" / "Weight" field"

Then there is also third possibility:

Invent new field for new stype priority information (say "PRIORITY2").

Indicate presense of PRIORITY2 field with (currently) reserved bit from Flags field (which
is on part 9-octet header of all frames).

There is unused flags bit available for both HEADERS and PRIORITY frame.

And fourth possibility is indicate repurpose of current "Stream Dependency" / "Weight" field"
with (currently) reserved bit from Flags field.

These possibilities also avoid dance on what point on time change of  "Stream Dependency" / "Weight" field"
field happens.

/ Kari Hurtta

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 9 Aug 2019 11:08:52 +0100

> "Stream Dependency" / "Weight" field"
I'd treat both options as a class of change that RFC 7540 says MUST be
negotiated:

Changing frame flags relies on implementations both understanding the flag
and its meaning, which is difficult to do in an uncoordinated and robust
way. For example, adding a field and setting a flag that no one knows to
check will likely result in extant HEADERS frame parsers detecting a . size
error, resulting in a connection error. That's pretty high risk.

Lucas

---

From: Kari Hurtta <[email-masked]>
Date: Fri, 9 Aug 2019 14:14:06 +0300 (EEST)

Lucas Pardue <[email-masked]>: (Fri Aug  9 13:08:52 2019)
> error, resulting in a connection error. That's pretty high risk.

Yes. Recipient of these changed frames needs send first SETTINGS frame
(for example) which it tells that that change is supported.

Also new type codes for HEADERS and PRIORITY frames need similar negotiation
(because accounting of frames and HPACK is affected; they can not just
ignored as unknwon frame type codes are ignored).

/ Kari Hurtta

---

From: Kari Hurtta <[email-masked]>
Date: Fri, 9 Aug 2019 14:40:51 +0300 (EEST)

Kari Hurtta <[email-masked]>: (Fri Aug  9 14:14:06 2019)
> ignored as unknwon frame type codes are ignored).

Or actually only HPACK is affected.

( Only DATA frames are flow control controlled. )

If only new PRIORITY frame (type code) is introduced, but no changes on HEADER frame
(or no new HEADER frame (type code)), then negation is not needed before sending frame.

/ Kari Hurtta

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 9 Aug 2019 13:05:23 +0100

> (or no new HEADER frame (type code)), then negation is not needed before

It really depends. The absence of priority fields in HEADERS *is* priority
information for HTTP/2's default priority scheme.

Negotiation provides feedback. Without it, a client that opportunistically
sends new_priority_scheme instructions and neglects to send the default
priority scheme's instructions may cause unintended behaviour when the
server ignores the new signal and instead prioritizes everything to the
root with the same weight. That results in a round-robin priority scheme
which is demonstrably worse for web browsing performance.

---

From: Mike Bishop <[email-masked]>
Date: Tue, 13 Aug 2019 18:48:48 +0000

This form of negotiation appears to presuppose sending multiple SETTINGS frames.  First you advertise that something is available, and only if it's available on the other side do you then declare that you're sending it.

HTTP/3 only permits a single SETTINGS frame in each direction, and for latency reasons you really shouldn't wait to see the peer's values before sending your own.  Therefore, I think you wind up in one of three postures for negotiating something like this:

  *   Each side declares their supported schemes.  There is a defined algorithm by which each side, having both declarations, can conclude the most mutually-preferred scheme.  Clients can’t generate PRIORITY frames until they’ve seen the server’s declaration.
  *   The server declares its supported schemes, each of which will use different frame types.  The client SHOULD NOT send more than one scheme simultaneously (but perhaps MAY send all of them until it sees the SETTINGS frame).
  *   Define a separate extension which is used for negotiation separate from SETTINGS.

-----Original Message-----
From: Kari Hurtta <[email-masked]>
Sent: Saturday, August 3, 2019 3:58 AM
To: Lucas Pardue <[email-masked]>; HTTP Working Group <[email-masked]>
Cc: Kari Hurtta <[email-masked]>; HTTP Working Group <[email-masked]>; Matthew Kerwin <[email-masked]>; Brad Lassey <[email-masked]>; Dmitri Tikhonov <[email-masked]>
Subject: Repurpose of protocol elements | Re: Repurpose of priority | ⋯ | Re: Setting to disable HTTP/2 Priorities

> frames it is sending would be foolish to not wait on an affirmative

> signal from the server. RFC 7540 Section 5.5. calls specific attention

> to such a

Okei,

Generally repurpose of protocol element requires 3 values (or 2 bits from bitmask) for SETTINGS parameter SETTINGS_ENABLE_{feature}.

For example values

•  1       {feature}_AVAILABLE

•  3       SENDING_{feature}

Recipient of repurposed protocol element sends first SETTINGS parameter SETTINGS_ENABLE_{feature} with value

1 ({feature}_AVAILABLE).

Sender of repurposed protocol element sends SETTINGS parameter SETTINGS_ENABLE_{feature} with value 3 (SENDING_{feature}) before it starts sending repurposed protocol element.

first.

/ Kari Hurtta

---

From: Lucas Pardue <[email-masked]>
Date: Tue, 13 Aug 2019 20:48:39 +0100

Hi Mike,

On Tue, 13 Aug 2019, 19:48 Mike Bishop, <[email-masked]> wrote:

> This form of negotiation appears to presuppose sending multiple SETTINGS
> frames.  First you advertise that something is available, and only if it's
> available on the other side do you then declare that you're sending it.
>
>
>
> HTTP/3 only permits a single SETTINGS frame in each direction, and for
> latency reasons you really shouldn't wait to see the peer's values before
> sending your own.  Therefore, I think you wind up in one of three postures
> for negotiating something like this:
>
>    - Each side declares their supported schemes.  There is a defined
>    algorithm by which each side, having both declarations, can conclude the
>    most mutually-preferred scheme.  Clients can’t generate PRIORITY frames
>    until they’ve seen the server’s declaration.
>    - The server declares its supported schemes, each of which will use
>    different frame types.  The client SHOULD NOT send more than one scheme
>    simultaneously (but perhaps MAY send all of them until it sees the SETTINGS
>    frame).
>    - Define a separate extension which is used for negotiation separate
>    from SETTINGS.
>
>
>

I agree. If I were to enumerate your points, then for point 1 Brad has some
WIP text that makes our initial proposal more robust in this sense.  And
for point 3 I have a strawman not-yet-shared negotiation mechanism that
uses extension frames in the manner you describe. Though seeing it written
down I'm not convinced it doesn't generate another set of complication.

Lucas

> Cc: Kari Hurtta <[email-masked]>; HTTP Working Group <
> [email-masked]>; Matthew Kerwin <[email-masked]>; Brad Lassey
> <[email-masked]>; Dmitri Tikhonov <[email-masked]>
> Generally repurpose of protocol element requires 3 values (or 2 bits from
> bitmask) for SETTINGS parameter SETTINGS_ENABLE_{feature}.
>
> For example values
>
>
>
> SETTINGS_ENABLE_{feature} with value 3 (SENDING_{feature}) before it starts
> sending repurposed protocol element.
>
>
>
>
>