Subject: Design: Ignored Unknown Frame Types and Intermediaries

From: James M Snell <[email-masked]>
Date: Sat, 11 May 2013 08:27:40 -0700

In the current draft, endpoints are required to "ignore" unknown and
unsupported frame types. What's not yet clear, however, is whether
such frames are required to be forwarded on by intermediaries that do
not support them.

In other words, A talks to C via reverse proxy B. A sends a stream
that includes EXTENSION_FRAME_TYPE that is unknown to B. Is B...

A) Required to drop the frame silently without forwarding it on to C
B) Required to always forward the frame on to C
C) Neither, B can do whatever it wants

There is an obvious impact here on the future deployment of new
extension frame types. If the answer is A or C, we'll have to wait on
infrastructure support to use new frame types, which would be
unfortunate.

- James

---

From: Yoav Nir <[email-masked]>
Date: Sun, 12 May 2013 04:58:02 +0000

> infrastructure support to use new frame types, which would be

I think (C) is the only answer. Consider two types of proxies: an SSL accelerator and a firewall. The SSL accelerator doesn't want to break anything, so it will forward everything (B), while a firewall doesn't let things pass which it doesn't understand (A). I think this will be the behavior for these two kinds of proxy regardless of what we specify. 

Since the UA can never know in advance what the server will support, there has to be some "extension support discovery" anyways. Perhaps if we had that in the SETTINGS frame, the proxy could filter out.  For example, add a SETTINGS_SUPPORTED_EXTENSION, which will hold an extension supported by the sender. You will need multiple settings values for multiple extensions. The server would send the same list as the client, filtered down to the list of extensions that it supports. A proxy could trim the list further to remove things it's going to drop.

Yoav

---

From: Roberto Peon <[email-masked]>
Date: Sun, 12 May 2013 11:15:01 -0700

I believe that the simplest thing is that, when you don't understand it,
you ignore it.

If that frame was required at some semantic level, then you should have
rev'd the version number or changed the version string in some other way at
the start of communication. That is easy and robust.

This does imply that changing any state which the baseline protocol of that
version depends upon is a no-no, but doesn't preclude changing state which
the baseline protocol of that version *doesn't* know about.

Making that a MUST, i.e. something like:
And endpoint may use frames with opcodes other than those defined in this
specification, however it MUST NOT do so if ignoring such a frame would
cause an unexpected stream or session error, either directly or indirectly.
-=R

On Sat, May 11, 2013 at 9:58 PM, Yoav Nir <[email-masked]> wrote:

> I think (C) is the only answer. Consider two types of proxies: an SSL
> accelerator and a firewall. The SSL accelerator doesn't want to break
> anything, so it will forward everything (B), while a firewall doesn't let
> things pass which it doesn't understand (A). I think this will be the
> behavior for these two kinds of proxy regardless of what we specify.
>
> Since the UA can never know in advance what the server will support, there
> has to be some "extension support discovery" anyways. Perhaps if we had
> that in the SETTINGS frame, the proxy could filter out.  For example, add a
> SETTINGS_SUPPORTED_EXTENSION, which will hold an extension supported by the
> sender. You will need multiple settings values for multiple extensions. The
> server would send the same list as the client, filtered down to the list of
> extensions that it supports. A proxy could trim the list further to remove
> things it's going to drop.
>
> Yoav
>

---

From: Yoav Nir <[email-masked]>
Date: Mon, 13 May 2013 04:11:35 +0000

That's fine for interoperability. And I believe that middleware such as caching proxies or reverse proxies will simply ignore unrecognized frames and pass them on.

Firewalls will either remove the unknown frames or reset the entire connection, and they'll do so regardless of what the spec says. I think that we should have text that says that middleware MAY remove frames not specified in the base draft. The reason is that otherwise the only choice is to reset the entire connection, which makes extending the protocol almost impossible - you'll get into the unhappy place TLS is with "retry at TLS1.0 without extensions, and if that doesn't work go to SSL3", except it's worse for HTTP because the unknown frame could happen at any point during the connection.

Yoav

On May 12, 2013, at 9:15 PM, Roberto Peon <[email-masked]<mailto:[email-masked]>> wrote:

I believe that the simplest thing is that, when you don't understand it, you ignore it.

If that frame was required at some semantic level, then you should have rev'd the version number or changed the version string in some other way at the start of communication. That is easy and robust.

This does imply that changing any state which the baseline protocol of that version depends upon is a no-no, but doesn't preclude changing state which the baseline protocol of that version *doesn't* know about.

Making that a MUST, i.e. something like:
And endpoint may use frames with opcodes other than those defined in this specification, however it MUST NOT do so if ignoring such a frame would cause an unexpected stream or session error, either directly or indirectly.
-=R

On Sat, May 11, 2013 at 9:58 PM, Yoav Nir <[email-masked]<mailto:[email-masked]>> wrote:

Yoav

Email secured by Check Point

---

From: James M Snell <[email-masked]>
Date: Sun, 12 May 2013 21:25:21 -0700

-1. "ignore it" is not a sufficient answer to ensure interoperability
on the new extension points being defined. This needs to be tightened
up.

On Sun, May 12, 2013 at 11:15 AM, Roberto Peon <[email-masked]> wrote:
>> has to be some "extension support discovery" anyways. Perhaps if we had that
>> in the SETTINGS frame, the proxy could filter out.  For example, add a

---

From: James M Snell <[email-masked]>
Date: Sun, 12 May 2013 21:29:34 -0700

On Sun, May 12, 2013 at 9:11 PM, Yoav Nir <[email-masked]> wrote:
> That's fine for interoperability. And I believe that middleware such as
> caching proxies or reverse proxies will simply ignore unrecognized frames
> and pass them on.
>

Belief does not ensure interoperability.

> Firewalls will either remove the unknown frames or reset the entire
> connection, and they'll do so regardless of what the spec says. I think that
> we should have text that says that middleware MAY remove frames not
> specified in the base draft. The reason is that otherwise the only choice is
> to reset the entire connection, which makes extending the protocol almost
> impossible - you'll get into the unhappy place TLS is with "retry at TLS1.0
> without extensions, and if that doesn't work go to SSL3", except it's worse
> for HTTP because the unknown frame could happen at any point during the
> connection.
>

Some frames might need to be removed, some might be ok to leave it.
Some might not matter to the middleware at all. It's better to be
explicit and allow for both cases.

For instance, we can say that frame types in the range 0x00-7F are
hop-by-hop and never forwarded on, but frame types in the range
0x80-0xFF are end-to-end and MUST be forwarded on, even if they are
completely ignored by the middleware. That would not only ensure
interoperability but would make use of the new extension points
possible.

- James

> Yoav
>
> On May 12, 2013, at 9:15 PM, Roberto Peon <[email-masked]> wrote:
>

---

From: Roberto Peon <[email-masked]>
Date: Mon, 13 May 2013 11:37:41 -0700

James:
Can you construct a case where, if you follow the rule spelled out in my
earlier email, you fail to achieve interop (because I can't)?

The rule is, essentially:
If a party to the communication ignores (or removes) something it don't
understand, that must not screw up the session.

That implies that, when you add anything that must be interpreted, it then
must be declared in the version string (i.e. new version) and thus agreed
upon by both parties up front, and if you don't negotiate that other
version, you don't get to add frames whose removal would screw up the
session.

Yoav:
I agree that intermediaries must be able to remove things they'd don't
understand, and saying so in the spec is reasonable, since it'll happen
anyway.

-=R

On Sun, May 12, 2013 at 9:29 PM, James M Snell <[email-masked]> wrote:

> you
> > ignore it.
> that

---

From: Martin Thomson <[email-masked]>
Date: Mon, 13 May 2013 14:13:37 -0700

> earlier email, you fail to achieve interop (because I can't)?

It's trivially possible to construct a scenario where this happens,
but only if you don't write down a "MUST ignore" rule.  Once the rule
is in place, then you are constraining future extensibility.  A "MUST
ignore" rule is the easiest rule to get right, but there are other
models you can use.

> understand, that must not screw up the session.

The ignore/remove distinction is very important.  You can't
selectively remove; it's all or nothing.  Either remove everything you
don't know about or leave it all in.

This consideration, along with James' hop-by-hop question does suggest
a relatively simple way out:

All unsupported/unknown frames that have a non-zero stream identifier
MUST be ignored.  If a stream is forwarded by an intermediary, all
unsupported/unknown frames MUST either be forwarded or removed; an
intermediary MUST NOT selectively forward unsupported frame types.
Unsupported/unknown frames with a zero stream identifier MUST be
ignored and MUST NOT be forwarded.

> version, you don't get to add frames whose removal would screw up the

Yeah, we addressed that early on.  If you want to guarantee that the
other guy is going to support something, either work out how to agree
in-session (with those ignored frames) or negotiate a new protocol.

---

From: James M Snell <[email-masked]>
Date: Mon, 13 May 2013 14:54:06 -0700

> ignored and MUST NOT be forwarded.

I would go one step further and say that if an intermediary does not
wish to forward an unknown frame, it MUST NOT forward ANY additional
frames and ought to respond with an RST_STREAM. Removing only some
frames from the stream could cause significant data corruption or data
loss, especially if you don't know why those frames are there.

> in-session (with those ignored frames) or negotiate a new protocol.

Agreeing without prior coordination (must ignore or reject the stream)
is, in my opinion, the best approach for long term evolution and
growth. The "come up with a new version string" reminds me far too
much of things like XML namespaces. It's one of those things that
sounds like it ought to work in theory but when it gets down to real
world implementation, it ends up being a bigger mess than anticipated.

- James

---

From: Roberto Peon <[email-masked]>
Date: Mon, 13 May 2013 15:08:18 -0700

I believe that, if one does remove/ignore such frames the session may not
be as optimal as it might otherwise be, but the rule, by definition,
precludes the use of anything which would hinder interop if emitted, but
then ignored by the receiver.
The rule is that one MUST NOT send a frame if its removal would cause
session corruption/termination/problems.
So, can you provide an example? :)

I think the version string is the most robust way to ensure that an
intermediary does the right thing-- If an intermediary sees a version
string it doesn't recognize, it simply doesn't allow the negotiation of
that variant.
This is more simple because the lack of an explicit negotiation for this
will lead to either:
1) implementations which ignore the spec, since their mission is to provide
security and consistency
2) Clients, servers, and proxies all maintaining a heuristic and
table/history about when and why sessions were terminated when a not
standardized opcode was
 I don't want to have to have maintain a table of endpoints which have sent
me some error-code or terminated my session because I included an unknown
opcode type (that would be pretty complicated). This would have to be done
for both sides, for that matter.

I'd prefer to say that an intermediary MUST NOT touch things in the session
which it does not recognize if it doesn't know the version, but allowed the
version to be negotiated, and it MAY remove things it doesn't know from a
session when the version is one which is fully specified.

That allows the intermediary to simply not negotiate things it doesn't like
on a per-connection basis, instead of having to have this complex cache of
'this feature doesn't work when X,Y,Z'.

James has pointed out that a reverse proxy may still have some difficulties
with this, assuming it wishes to support an unknown extention, but, I think
that trade (no longer requiring clients and servers to have to worry about
this, while having the proxy continue to worry about it) is reasonable.

-=R

---

From: James M Snell <[email-masked]>
Date: Mon, 13 May 2013 15:35:42 -0700

On Mon, May 13, 2013 at 3:08 PM, Roberto Peon <[email-masked]> wrote:
> I believe that, if one does remove/ignore such frames the session may not be
> as optimal as it might otherwise be, but the rule, by definition, precludes
> the use of anything which would hinder interop if emitted, but then ignored
> by the receiver.

The challenge with this is that the sender may know what it and the
origin server supports, it will generally have absolutely no clue what
everything in the middle supports... this means the default position
would be: don't ever send anything other than the core frame types,
which kills the whole point of allowing extensibility in the first
place (and yes, I know your position on extensibility ;-) ...).

In the worse case, what you'll end up with are implementations that
use DATA frames to tunnel (hack) their extension stuff through..
(because they know those will make it thru). We see that anti-pattern
repeated time and time again with things like X-Post-Method-Override,
DNS TXT records, SOA POST tunneling, Deletes-using-GET or POST
methods, etc. I'd rather not encourage similar abuse here.

> intermediary does the right thing-- If an intermediary sees a version string
> it doesn't recognize, it simply doesn't allow the negotiation of that
> variant.

Imo, Having a rule that says either forward everything or forward
nothing achieves the same result, without the need for any additional
"negotiation".

> for both sides, for that matter.

Such a table would not be necessary. If my user agent sends a
particular extension frame and a middlebox responds with a
RST_STREAM('UNSUPPORTED_FRAME') then I just move on and either try
something else or give up. Otherwise, if the middlebox forwards those
frames on, things just work. There's no reason to terminate the
session, just cancel the stream within the session. There's also no
reason to keep any kind of table for what frame types work or don't...
you either use it and it doesn't work, or you use it and it does.

- James

---

From: Roberto Peon <[email-masked]>
Date: Mon, 13 May 2013 16:15:07 -0700

Everything in the middle would have had its chance to do something when the
initial negotiation goes through its end-to-end route.

Using DATA frames with a format that the intermediary doesn't understand
(many of them do examine content) doesn't guarantee that the session will
work properly either.

A RST_STREAM is insufficient if any modification to shared state has
occurred. It still requires that the client or server keep state about when
it should not use these unknown opcodes when speaking to an endpoint from a
specific network (since the client likely roams amongst different
typologies these days).

Things that wouldn't cause session-level problems, nor stream-level
problems if removed:

   - An unknown opcode which provides a more detailed hint about
   prioritization
   - An unknown opcode which provides data about the state of the browser
   cache
   - An unknown opcode which provides data about connection-state, number
   of connections, etc.
   - An unknown opcode which points out when flow control is blocked

The above are examples of things I'm saying should be allowed in a known
version of the protocol, and which are fine to remove/ignore if not
understood.

The section below contains examples of things which shouldn't be allowed in
a known version of the protocol, but should be fine in some variant of it
if all parties agree to it.
Things that would obviously cause session-level problems if removed:

   - An unknown opcode which touches on flow control
   - An unknown opcode which modifies compression state
   - An unknown opcode which reserves/assigns/changes stream IDs
   - An unknown opcode which closes multiple streams.

These I'm not sure about either way. I've already had the displeasure of
dealing with things that cause stream-level problems, and I'm not excited
about the prospect of having to figure this out (second hand, as it usually
happens as some tiny segment of the populace is having problems and the
percentage of them who actually *tell* you about it small, and then those
who are willing to help you debug it is even smaller...).

Things that wouldn't cause session-level problems, but would cause
stream-level problems if removed:

   - An unknown opcode which indicates that byte ranges come out of order
   (and which specifies that order)
   - An unknown opcode which indicates that the encoding type has changed.
   - An unknown opcode which indicates that the rest of the payload is
   being sent uncompressed or compressed (when it was the opposite before).

As I've said before, I believe that this should be a living protocol, and
not ossified. That does imply that both experimentation needs to be
accommodated and that successful experimentation becomes interoperable.

ALPN and NPN work/worked because their addition to TLS caused no failure
when ignored or not understood. Now that we have ALPN and NPN, and now that
using a new version is so amazingly easy in comparison to what it was
before, it makes sense to use that fact to reduce complexity instead of
falling into the same trap that HTTP fell into w.r.t. extensions and unused
features. I believe that this will allow for more experimentation, more
quickly, and much faster standardized interop than will extensions that
require significant work and complexity to deal with failure scenarios.

-=R

On Mon, May 13, 2013 at 3:35 PM, James M Snell <[email-masked]> wrote:

> string
> > On Mon, May 13, 2013 at 2:13 PM, Martin Thomson <
> [email-masked]>
> > wrote:
> >>

---

From: Yoav Nir <[email-masked]>
Date: Tue, 14 May 2013 09:46:19 +0000

Hi Roberto

The beauty of extensions as opposed to protocol versions, is that it's easier to run several of these experiments at once.

So it's great that you can have versions "HTTP/2.1NewFlowControlModel" and "HTTP/2.1DynamicPriorities" and "HTTP/2.1NewHeadersFormat", but then the server can only choose one of these experiments. And the safest route for middleboxes to take will be to force the protocol down to the HTTP/2.0 which they understand. That may be what we want firewalls to do, but other proxies may not be affected by some of these.

But I agree that we should limit what non-version-changing extensions are allowed to do. We should require that if the extension is either ignored by the recipient or removed by a middlebox, no harm would be done (except the new functionality not working)

Yoav

On May 14, 2013, at 2:15 AM, Roberto Peon <[email-masked]<mailto:[email-masked]>> wrote:

Everything in the middle would have had its chance to do something when the initial negotiation goes through its end-to-end route.

Using DATA frames with a format that the intermediary doesn't understand (many of them do examine content) doesn't guarantee that the session will work properly either.

A RST_STREAM is insufficient if any modification to shared state has occurred. It still requires that the client or server keep state about when it should not use these unknown opcodes when speaking to an endpoint from a specific network (since the client likely roams amongst different typologies these days).

Things that wouldn't cause session-level problems, nor stream-level problems if removed:

  *   An unknown opcode which provides a more detailed hint about prioritization
  *   An unknown opcode which provides data about the state of the browser cache
  *   An unknown opcode which provides data about connection-state, number of connections, etc.
  *   An unknown opcode which points out when flow control is blocked

The above are examples of things I'm saying should be allowed in a known version of the protocol, and which are fine to remove/ignore if not understood.

The section below contains examples of things which shouldn't be allowed in a known version of the protocol, but should be fine in some variant of it if all parties agree to it.
Things that would obviously cause session-level problems if removed:

  *   An unknown opcode which touches on flow control
  *   An unknown opcode which modifies compression state
  *   An unknown opcode which reserves/assigns/changes stream IDs
  *   An unknown opcode which closes multiple streams.

These I'm not sure about either way. I've already had the displeasure of dealing with things that cause stream-level problems, and I'm not excited about the prospect of having to figure this out (second hand, as it usually happens as some tiny segment of the populace is having problems and the percentage of them who actually *tell* you about it small, and then those who are willing to help you debug it is even smaller...).

Things that wouldn't cause session-level problems, but would cause stream-level problems if removed:

  *   An unknown opcode which indicates that byte ranges come out of order (and which specifies that order)
  *   An unknown opcode which indicates that the encoding type has changed.
  *   An unknown opcode which indicates that the rest of the payload is being sent uncompressed or compressed (when it was the opposite before).

As I've said before, I believe that this should be a living protocol, and not ossified. That does imply that both experimentation needs to be accommodated and that successful experimentation becomes interoperable.

ALPN and NPN work/worked because their addition to TLS caused no failure when ignored or not understood. Now that we have ALPN and NPN, and now that using a new version is so amazingly easy in comparison to what it was before, it makes sense to use that fact to reduce complexity instead of falling into the same trap that HTTP fell into w.r.t. extensions and unused features. I believe that this will allow for more experimentation, more quickly, and much faster standardized interop than will extensions that require significant work and complexity to deal with failure scenarios.

-=R

On Mon, May 13, 2013 at 3:35 PM, James M Snell <[email-masked]<mailto:[email-masked]>> wrote:

- James

> On Mon, May 13, 2013 at 2:13 PM, Martin Thomson <[email-masked]<mailto:[email-masked]>>
> wrote:
>>
>> On 13 May 2013 11:37, Roberto Peon <[email-masked]<mailto:[email-masked]>> wrote:
>> > James:

---

From: Albert Lunde <[email-masked]>
Date: Tue, 14 May 2013 08:39:19 -0500

On 5/14/2013 4:46 AM, Yoav Nir wrote:
> But I agree that we should limit what non-version-changing extensions
> are allowed to do. We should require that if the extension is either
> ignored by the recipient or removed by a middlebox, no harm would be
> done (except the new functionality not working)

It's hard to tell if an extension may be safely ignored at the protocol 
level.  Would there be any use in having a "critical extension" bit, 
indicating an extension frame that must not be silently dropped by 
intermediaries or ignored by the destination server?

---

From: Yoav Nir <[email-masked]>
Date: Tue, 14 May 2013 14:36:49 +0000

On May 14, 2013, at 4:39 PM, Albert Lunde <[email-masked]> wrote:

> It's hard to tell if an extension may be safely ignored at the protocol level.  Would there be any use in having a "critical extension" bit, indicating an extension frame that must not be silently dropped by intermediaries or ignored by the destination server?
> 

I don't know. If you send a critical extension to an old(*) server, it's going to reset the stream or the connection. If you send a critical extension through an old firewall, it will reset your stream or connection, so that the new extension would sometimes work and sometimes won't. 

Any proxy other than a firewall cannot tell whether the critical extension is something that should affect it or not. So it has the choice of resetting the stream (which goes against the design goal of such proxies to be as transparent to the client as possible) or it could forward the frame, which is equivalent to ignoring it. There is no way to know if it should have changed its behavior because of that ignored frame.

So you could have two bits, one as your described, and the other for whether an intermediary can ignore it (similar to the ranges of types that James suggested). But that assumes that whoever designs these extensions knows about all the kinds of proxies that exist, and what is relevant for them.

We could have some kind of negotiation on extension capability in the SETTINGS frame, and explicitly allow middleware to remove capabilities that they don't support to prevent their use. But if we've gone to negotiate it at the start, I can see Roberto's point that we might as well negotiate it in version strings.

Yoav

(*) "old" means a server conforming to the base HTTP/2.0 specification

---

From: James M Snell <[email-masked]>
Date: Tue, 14 May 2013 08:00:38 -0700

I personally think that's getting all too complicated. It ought to be
very simple.

1. The middlebox can choose to ignore extension frames and pass them
thru untouched, or
2. The middlebox can choose to reject extension frames, in which case
it rejects the remainder of the stream using an RST_STREAM with a
specific error code.

If a client receives an RST_STREAM[UNSUPPORTED_FRAME] error, the
connection remains intact but that one extended stream is closed.
That's really not that big of a deal, the client can fall back to some
alternative behavior or just give up. There's nothing wrong with that.
No negotiation is required, and I don't need to know in advance
whether something is going to work or not.

Which, btw, is EXACTLY how things work today... I can send, for
instance, a PATCH request to any server I want. When I do, I have
absolutely no guarantees that some piece of middleware in the path is
going to let that method thru... I just have to be prepared to deal
with the possible "Method Not Allowed" response.

The range types that I suggested (CONTROL vs. DATA frames) do not
require that we keep track of any kind of proxy. Consider, in HTTP/1
today we already have the notion of Hop-by-hop headers and end-to-end
headers. We specifically define that some headers are connection
specific and MUST NOT be forwarded, and we specifically define that
some headers MUST always be forwarded. What I'm suggesting is
absolutely no different than this... only instead of using a header to
define which items are end-to-end vs. connection-specific, we would
just use a range of type codes.

These kinds of distinctions ALREADY exist in HTTP/1 and do not, imho,
add unwarranted complexity to HTTP/2. No negotiation is required, no
tracking table of who supports what is required, no prior knowledge of
what kinds of proxies are deployed in the path are required...
extension frames are either passed thru or the whole stream is
rejected; it either works or it doesn't. Simple.

The issue of whether or not extension frames ought to be flow
controlled is very closely related to this, which is another
justification for the CONTROL vs. DATA frame distinction. We cannot
predict exactly how extension frames will be defined. Some may be
intended to provide *optional* extension to the connection -- for
instance, a checksum frame that provides an ok-to-ignore hash of
previously received frames. Some may be intended to provide structured
application data as opposed to just using a DATA frame blob. It stands
to reason that some extension frames might make sense to flow control
while others do not.

- James

---

From: Roberto Peon <[email-masked]>
Date: Tue, 14 May 2013 11:06:42 -0700

Yoav--

I think of it even more simply than you describe in your example.
We have standards-conformant versions of HTTP/2, which are well known.
Then we have variations on these versions, which will have different
identifying names, but at a minimum we'd have one *known* version,
HTTP/2.0-experimental. Any server/proxy/client which allows that version to
be negotiated is making a promise to pass along frames it doesn't recognize
without modification.

Later, perhaps some extensions become widely known and useful. At that
point someone helpfully assigns a version of HTTP/2-0-pre-1, which now is
expected to mean HTTP/2 plus whatever extensions. If we continue to do our
job, assuming there is wide acceptance of those extensions, we'll get those
extensions spec'd and get that version documented.

-=R

On Tue, May 14, 2013 at 7:36 AM, Yoav Nir <[email-masked]> wrote:

> I don't know. If you send a critical extension to an old(*) server, it's
> going to reset the stream or the connection. If you send a critical
> extension through an old firewall, it will reset your stream or connection,
> so that the new extension would sometimes work and sometimes won't.
>
> Any proxy other than a firewall cannot tell whether the critical extension
> is something that should affect it or not. So it has the choice of
> resetting the stream (which goes against the design goal of such proxies to
> be as transparent to the client as possible) or it could forward the frame,
> which is equivalent to ignoring it. There is no way to know if it should
> have changed its behavior because of that ignored frame.
>
> So you could have two bits, one as your described, and the other for
> whether an intermediary can ignore it (similar to the ranges of types that
> James suggested). But that assumes that whoever designs these extensions
> knows about all the kinds of proxies that exist, and what is relevant for
> them.
>
> We could have some kind of negotiation on extension capability in the
> SETTINGS frame, and explicitly allow middleware to remove capabilities that
> they don't support to prevent their use. But if we've gone to negotiate it
> at the start, I can see Roberto's point that we might as well negotiate it
> in version strings.
>
> Yoav
>