Re: HTTP/2 GREASE, Results, and Implications

Willy Tarreau <> Fri, 15 November 2019 16:02 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 7D5C9120801 for <>; Fri, 15 Nov 2019 08:02:11 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.652
X-Spam-Status: No, score=-2.652 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, MAILING_LIST_MULTI=-1, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id korrfdIJzCy4 for <>; Fri, 15 Nov 2019 08:02:05 -0800 (PST)
Received: from ( [IPv6:2603:400a:ffff:804:801e:34:0:38]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id A4C03120892 for <>; Fri, 15 Nov 2019 08:01:56 -0800 (PST)
Received: from lists by with local (Exim 4.89) (envelope-from <>) id 1iVe0L-0000tM-T0 for; Fri, 15 Nov 2019 15:59:25 +0000
Resent-Date: Fri, 15 Nov 2019 15:59:25 +0000
Resent-Message-Id: <>
Received: from ([2603:400a:ffff:804:801e:34:0:4c]) by with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from <>) id 1iVe0K-0000sT-1x for; Fri, 15 Nov 2019 15:59:24 +0000
Received: from ([] by with esmtp (Exim 4.92) (envelope-from <>) id 1iVe0I-0006dQ-DJ for; Fri, 15 Nov 2019 15:59:23 +0000
Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id xAFFxDtd025399; Fri, 15 Nov 2019 16:59:13 +0100
Date: Fri, 15 Nov 2019 16:59:13 +0100
From: Willy Tarreau <>
To: Tom Bergan <>
Cc: Bence =?iso-8859-1?Q?B=E9ky?= <>, Stefan Eissing <>, Mike Bishop <>, HTTP Working Group <>
Message-ID: <>
References: <> <> <> <> <> <> <> <> <> <>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <>
User-Agent: Mutt/1.6.1 (2016-04-27)
Received-SPF: pass client-ip=;;
X-W3C-Hub-Spam-Status: No, score=-7.9
X-W3C-Hub-Spam-Report: BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, W3C_AA=-1, W3C_IRA=-1, W3C_IRR=-3, W3C_WL=-1
X-W3C-Scan-Sig: 1iVe0I-0006dQ-DJ 9e840a880f4db96938e255173e89a744
Subject: Re: HTTP/2 GREASE, Results, and Implications
Archived-At: <>
X-Mailing-List: <> archive/latest/37136
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>

Hi Tom,

first, thanks for reloading this.

On Fri, Nov 15, 2019 at 07:10:31AM -0800, Tom Bergan wrote:
> I would like to revisit the ambiguity that Willy pointed out in this
> thread. On the one hand, we have this statement, which appears in Sections
> 4.1 and 5.5:
> 1. Implementations MUST discard frames that have unknown or unsupported
> types.
> For this reason, I propose that this ambiguity should be resolved in favor
> of Section 5.5. We should release an errata which clarifies that the rules
> in Section 5.1 do not apply to frames of unknown type.

If we do this, we should really change the wording to never use "other than"
and instead explicitly mention the list of frame types that are not permitted
in each state.

> If an extension
> defines a new frame type, it must explicitly enumerate the states in which
> that frame can be sent and received. Willy also raised a concern about new
> frame types that include END_STREAM. I think this is covered by Section
> 5.5, which says "Extensions that could change the semantics of existing
> protocol components MUST be negotiated before being used." If a new frame
> type can end the stream, this adds an edge to the state diagram in Section
> 5.1, therefore, support for the new frame type must be negotiated before it
> can be used.

I'm fine with this point. However I do have a real concern regarding
deployed code now based on the fact that the way this ambiguity is present
can have caused solid roots to be set inside some software. For example
when trying to address the issue in haproxy, I noticed that we've used
bit fields of permitted frame types to more easily match what's allowed
or not. When working around them I figured that changing tests constructed
this way to think in terms of exclusion instead wasn't always as riskfree
as I initially imagined, and if we relax certain rules we need to be sure
that (almost) all implementations will accept to revisit their code and
take such risks in maintenance versions to allow smooth updates of deployed
components, or we really risk the same type of fragmentation that we've
known with HTTP/1.1.

I have been wondering if we could classify frame types into 2 or 3
categories :
  - those permitted on stream 0
  - those permitted on an open stream
  - those permitted after END_STREAM or on an idle stream

I even suspect that the last one should be cut into two. The question
was whether we could have imagined simplifying the handling of extra
frame types by saying that only certain ranges of frame types will be
permitted in certain situations which would allow to better handle
extensions in the future, but after checking in my code I'm not
convinced anymore that this could really help. Thus I think that your
point about any frame type adding a new arc on the state graph should
only be used through negotiation is probably the only option.

But I still do have some concerns about our ability to extend the
protocol even without this. What if a new frame expects an ACK for
example ? Probably this one will also require an extension. And for
those plugged on the stream without the ability to really participate
(typically a firewall or a wireshark dissector), maybe declaring that
the ACK flag is always the same bit 0 and that any frame type holding
an ACK should be ignored regardless of the context could make sense.

Just a few thoughts.