Subject: Negotiating compression

From: Martin Thomson <[email-masked]>
Date: Tue, 27 May 2014 10:54:14 -0700

The long and rambling thread on schedule has again started to discuss
HPACK.  A point was made regarding negotiation for its use.

I don't think that negotiation is necessary.  The argument regarding
the physics, which would dictate the use of an entire RTT for
negotiation, is compelling, but I have others.  The only reason you
want negotiation is if you want to be able to influence the behaviour
of a counterparty.

A sizable advantage can be gained by modifying your own behaviour,
which HPACK always permits.  Given that the data you care most about
protecting is usually the stuff that you send, I'm willing to bet that
this is good enough in the unlikely event that an attack is
discovered.

---

From: Michael Sweet <[email-masked]>
Date: Tue, 27 May 2014 14:24:31 -0400

Martin,

> this is good enough in the unlikely event that an attack is

A parameter in the initial settings frame would be enough - we already have one for controlling the size of the header table.

All that would seem to be missing is a parameter to disable Huffman coding (issue #485) to enable simpler implementations that use the literal representations for headers (with names and/or the static table indices).

_________________________________________________________
Michael Sweet, Senior Printing System Engineer, PWG Chair

---

From: Martin Thomson <[email-masked]>
Date: Tue, 27 May 2014 11:29:50 -0700

> All that would seem to be missing is a parameter to disable Huffman coding (issue #485) to enable simpler implementations that use the literal representations for headers (with names and/or the sta…

Declaring something missing is a value judgment.  My conclusion is
that it's not needed.

---

From: Nicholas Hurley <[email-masked]>
Date: Tue, 27 May 2014 11:31:57 -0700

+1

HPACK is not so horrendously complex that it should be considered a barrier
to entry (it's actually pretty simple, even including Huffman encoding).
Plus, I can always start sending only literal encodings if the security
situation suddenly becomes an issue.

Not to mention the fact that, the more things that can be negotiated, the
more possibility there is for state mismatches at each endpoint, and the
more possibility there is to break interop (even with ACKed SETTINGS).

--
Peace,
  -Nick

---

From: Michael Sweet <[email-masked]>
Date: Tue, 27 May 2014 14:52:31 -0400

-1

You might be able to fix your end, but how do you tell the other side to stop?

Right now you can set the header table size to 0 (good), but you can't disable Huffman (not so good). The fix for Huffman would just be a parameter in the initial SETTINGS frame.

And the issue is not just complexity but overhead - Huffman coding alone requires relatively slow bit manipulations, the header tables add to the memory overhead of every connection, and proxies get to do header processing twice...  Not a big deal on a desktop machine with a dozen connections, but embedded devices and proxies have tighter constraints.

On May 27, 2014, at 2:31 PM, Nicholas Hurley <[email-masked]> wrote:

> +1
> 
> HPACK is not so horrendously complex that it should be considered a barrier to entry (it's actually pretty simple, even including Huffman encoding). Plus, I can always start sending only literal encodings if the security situation suddenly becomes an issue.
> 
> Not to mention the fact that, the more things that can be negotiated, the more possibility there is for state mismatches at each endpoint, and the more possibility there is to break interop (even with ACKed SETTINGS).
> 
> --
> Peace,
>   -Nick
> 
> 
> On Tue, May 27, 2014 at 10:54 AM, Martin Thomson <[email-masked]> wrote:

---

From: Martin Thomson <[email-masked]>
Date: Tue, 27 May 2014 13:40:13 -0700

On 27 May 2014 11:52, Michael Sweet <[email-masked]> wrote:
> And the issue is not just complexity but overhead - Huffman coding alone
> requires relatively slow bit manipulations, the header tables add to the
> memory overhead of every connection, and proxies get to do header processing
> twice...  Not a big deal on a desktop machine with a dozen connections, but
> embedded devices and proxies have tighter constraints.

Let's be very clear about the costs here.  The only cost you cannot
avoid is the cost of Huffman decoding.  At a proxy, processing costs
can be turned into memory costs relatively trivially and then
amortized across multiple connections.  A constrained device pays one
way or other, but those costs are trivial in comparison to other costs
that device incurs.

The argument for a setting incurs complexity that is - at least in my
opinion - a wash when compared to a simple Huffman decoder.

My original point was focused on the concerns some raised regarding security.

---

From: "Richard Wheeldon (rwheeldo)" <[email-masked]>
Date: Tue, 27 May 2014 23:34:13 +0000

Realistically, the smallest embedded device are still orders of magnitude more powerful that the computers I was using at Uni or before then. If running compression was a good idea on a 286 or M68K, I'm struggling to see what classes of device you'd be concerned about where compression is a bad idea but where HTTP would still be a sensible choice?

I also don't see a case in which enforcing support for compression of data (C-E : GZip et al.) is a good idea but compression of headers isn't, unless you have some data or observation which suggests that HPACK is significantly worse than GZip in terms of performance?

Richard

From: Michael Sweet [mailto:[email-masked]]
Sent: 27 May 2014 13:53
To: Nicholas Hurley
Cc: Martin Thomson; HTTP Working Group
Subject: Re: Negotiating compression

-1

On May 27, 2014, at 2:31 PM, Nicholas Hurley <[email-masked]<mailto:[email-masked]>> wrote:

+1

--
Peace,
  -Nick

On Tue, May 27, 2014 at 10:54 AM, Martin Thomson <[email-masked]<mailto:[email-masked]>> wrote:
The long and rambling thread on schedule has again started to discuss
HPACK.  A point was made regarding negotiation for its use.

---

From: David Krauss <[email-masked]>
Date: Wed, 28 May 2014 09:59:15 +0800

The smallest embedded devices today are still 8 bit, 8051 derivatives. The smallest I’ve seen with an Ethernet interface has a M68K (ColdFire) core, 128K of program space, 32K RAM. It comes with a free HTTP client. IIRC the included demo is a webserver, but I don’t know whether that fits into that particular MCU.

In the internet of things, HTTP is a sensible choice for anything, and you can be certain the device will be more susceptible to firewalls if it tries to use anything else.

Better applicability to the embedded domain is the most attractive thing about HTTP/2 to me. However, although I haven’t yet implemented HPACK, the Huffman code doesn’t look particularly scary. My main concern is that it’s not very efficient. As for the rest, it goes away when you set the table size to zero, no?

And if the total variety of headers ever sent by the client fits into 4K, it can in theory verify that the server header table is at least so much, and then hard-code the transmitted headers against the presumed remote state, rather than actually encoding them from scratch.

I’ve not implemented HPACK, but what works for a big server handling a million connections should usually work for a tiny MCU.

On 2014–05–28, at 7:34 AM, Richard Wheeldon (rwheeldo) <[email-masked]> wrote:

> Realistically, the smallest embedded device are still orders of magnitude more powerful that the computers I was using at Uni or before then. If running compression was a good idea on a 286 or M68K, I’m struggling to see what classes of device you’d be concerned about where compression is a bad idea but where HTTP would still be a sensible choice?
>  
> I also don’t see a case in which enforcing support for compression of data (C-E : GZip et al.) is a good idea but compression of headers isn’t, unless you have some data or observation which suggests that HPACK is significantly worse than GZip in terms of performance?

---

From: Simone Bordet <[email-masked]>
Date: Wed, 28 May 2014 11:41:38 +0200

Hi,

> this is good enough in the unlikely event that an attack is

Can you please expand on what is plan B in the unlikely event ?
I am guessing that it would require to bump the HTTP version, and a
worldwide update of all servers to the new version (or drop to HTTP
1.1) ?

Also, if a different, better, header compression algorithm is found,
that also would require a HTTP version bump ?

I'd really like to be as confident as you are, but I'd like to have a
plan B for one of the most used protocols in the world.
So far, IIUC, there is no plan B, right ?

-- 
Simone Bordet
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless.   Victoria Livschitz

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 28 May 2014 12:19:55 +0200

On 28 May 2014 03:59, David Krauss <[email-masked]> wrote:

> I’ve not implemented HPACK, but what works for a big server handling a
> million connections should usually work for a tiny MCU.

Indeed this is very true!

As somebody who has implement a server handling a million connections, I've
very much concerned by the resource requirements implied by HTTP/2 for a
server.   Not only does a server have to commit to storing the headers that
can result from a 16k compressed header frames, but it may receive
unlimited CONTINUATION frames after that.

Sure a server can opt not to accept large headers, but if HTTP/2 is going
to facilitate a web where browsers can and do send such large headers, then
all that would do would be for that server to opt out of the web.

I just do not see the need for the transport meta data channel for HTTP/2
to grow beyond the current size.  After all, we are only trying to support
what is done with HTTP/1.1 now, so 8K headers should be sufficient and any
new applications for large metadata can put it in a data stream!

So with my tin foil hat on, I see conspiracy!) I'm told nobody is going to
send servers such big headers... so why then are going to such lengths to
support them in the protocol?

cheers

-- 
Greg Wilkins <[email-masked]>
http://eclipse.org/jetty HTTP, SPDY, Websocket server and client that scales
http://www.webtide.com  advice and support for jetty and cometd.

---

From: Roland Zink <[email-masked]>
Date: Wed, 28 May 2014 13:01:40 +0200

Partly the responsibility if compression can be used is given to the 
applications. With a potential new API they may specify that some 
headers should not be compressed. So a plan B could be to always use 
this (or simply blame the application that they were not following the 
recommendations).

Roland

draft-ietf-httpbis-header-compression-07 in section 5.1. 
Compression-based Attacks:

HPACK enables an endpoint to indicate that a header field must never be 
compressed, across any hop up to the other endpoint (see Section 4.3.3 
<http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-4.3.3>). 
An endpoint MUST use this feature to prevent the compression of any 
header field whose value contains a secret which could be put at risk by 
a brute-force attack.

---

From: Michael Sweet <[email-masked]>
Date: Wed, 28 May 2014 08:07:40 -0400

Richard,

Many of the printers I work with are still using *16-bit* microcontrollers, so asking them to do Huffman encoding/decoding on top of everything else is not an easy sell (they can barely manage as it is).  But regardless of the class of device, Huffman is going to be much slower than uncompressed, and there should be a way for HTTP/2 to adapt (even a little bit) to the capabilities of each device in the chain, particularly if network bandwidth is not a constraint (think local access to devices and the first hop to a proxy).

---

From: Eliot Lear <[email-masked]>
Date: Wed, 28 May 2014 14:38:08 +0200

Hi Michael,

Are the printers ones whose implementation you control? Also, do you
have some reason to believe that they will ever go to HTTP/2?  What I'm
getting at is if they're not going to do HTTP/2 anyway, then this isn't
an issue.  If they ARE going to HTTP/2 and they are not in your control,
that is not your problem.  If they ARE in your control, this amounts to
a COGS argument.  Does the COGS argument rise to an implementation barrier?

Speaking more broadly, and not really addressing Michael, as I've
repeatedly said, I think this comes down to applicability of the
protocol.  Quite frankly it was not designed to make printing faster or
more efficient, and to the best of my knowledge nobody has tested for
that case.  This is not a fault of the protocol.  Good engineers
constrain their design space.  HTTP/1.1 has suffered from wild success
(RFC 5218) and is well beyond its design space.  I see nothing wrong in
constraining the design space, so long as what's left is useful to a
significant population.

Eliot

On 5/28/14, 2:07 PM, Michael Sweet wrote:
> Richard,
>
> Many of the printers I work with are still using *16-bit*
> microcontrollers, so asking them to do Huffman encoding/decoding on
> top of everything else is not an easy sell (they can barely manage as
> it is).  But regardless of the class of device, Huffman is going to be
> much slower than uncompressed, and there should be a way for HTTP/2 to
> adapt (even a little bit) to the capabilities of each device in the
> chain, particularly if network bandwidth is not a constraint (think
> local access to devices and the first hop to a proxy).
>
>
> On May 27, 2014, at 7:34 PM, Richard Wheeldon (rwheeldo)
> <[email-masked] <mailto:[email-masked]>> wrote:
>
>> Realistically, the smallest embedded device are still orders of
>> magnitude more powerful that the computers I was using at Uni or
>> before then. If running compression was a good idea on a 286 or M68K,
>> I’m struggling to see what classes of device you’d be concerned about
>> where compression is a bad idea but where HTTP would still be a
>> sensible choice?
>>
>>  
>>
>> I also don’t see a case in which enforcing support for compression of
>> data (C-E : GZip et al.) is a good idea but compression of headers
>> isn’t, unless you have some data or observation which suggests that
>> HPACK is significantly worse than GZip in terms of performance?
>>
>>  
>>
>> Richard
>>
>>  
>>
>> *From:*Michael Sweet [mailto:[email-masked]]
>> *Sent:* 27 May 2014 13:53
>> *To:* Nicholas Hurley
>> *Cc:* Martin Thomson; HTTP Working Group
>> *Subject:* Re: Negotiating compression
>>
>>  
>>
>> -1
>>
>>  
>>
>> Right now you can set the header table size to 0 (good), but you
>> can't disable Huffman (not so good). The fix for Huffman would just
>> be a parameter in the initial SETTINGS frame.
>>
>>  
>>
>> And the issue is not just complexity but overhead - Huffman coding
>> alone requires relatively slow bit manipulations, the header tables
>> add to the memory overhead of every connection, and proxies get to do
>> header processing twice...  Not a big deal on a desktop machine with
>> a dozen connections, but embedded devices and proxies have tighter
>> constraints.
>>
>>  
>>
>>  
>>
>> HPACK is not so horrendously complex that it should be considered a
>> barrier to entry (it's actually pretty simple, even including Huffman
>> encoding). Plus, I can always start sending only literal encodings if
>> the security situation suddenly becomes an issue.
>>
>> Not to mention the fact that, the more things that can be negotiated,
>> the more possibility there is for state mismatches at each endpoint,
>> and the more possibility there is to break interop (even with ACKed
>> SETTINGS).
>>
>>
>> --
>> Peace,
>>
>>   -Nick
>>
>>  
>>
>> <[email-masked] <mailto:[email-masked]>> wrote:
>>

---

From: Michael Sweet <[email-masked]>
Date: Wed, 28 May 2014 11:03:21 -0400

Eliot,

On May 28, 2014, at 8:38 AM, Eliot Lear <[email-masked]> wrote:
> Hi Michael,
> 
> Are the printers ones whose implementation you control?

Just indirectly through the standards I and others write.

> Also, do you have some reason to believe that they will ever go to HTTP/2?

We have been pushing hard to get TLS support in all printers, and since TLS connections have a high overhead (both for bringing the connection up and maintaining state) we are all looking at HTTP/2 to provide some savings and potentially some minor performance benefit for these printers.

But on the low end we are *very* interested in adopting HTTP/2 for IPP USB where the number of available interfaces (== number of simultaneous connections that can be supported) is typically only 2.  Right now we are multiplexing access to these interfaces using a network proxy, but that means you can't have more than 2 requests in flight...  HTTP/2 would lift that limitation, but we need to be very careful about what resources we require since the current generation of SoCs used by the vendors can't do much more than they already do (printers are complicated pieces of hardware and the lowest cost SoC is used...)

I'm aware that "we are on our own" for non-network usage of HTTP - that's fine - but I would like to keep our usage as close to the standard as is feasible, otherwise vendors can't use the same HTTP/IPP software stack for USB and network printing.

(and in case you are wondering, yes they do TLS with 16-bit processors, it just works slowly...)

> ...
> Speaking more broadly, and not really addressing Michael, as I've repeatedly said, I think this comes down to applicability of the protocol.  Quite frankly it was not designed to make printing faster or more efficient, and to the best of my knowledge nobody has tested for that case.  This is not a fault of the protocol.  Good engineers constrain their design space.  HTTP/1.1 has suffered from wild success (RFC 5218) and is well beyond its design space.  I see nothing wrong in constraining the design space, so long as what's left is useful to a significant population.

Frankly, this attitude about printing being outside the design space of HTTP is crap.  IPP is a web service, exactly as envisioned in the original HTTP specs.  Every IPP request is a POST with a message body.  The message body happens to be a binary encoded message (application/ipp) rather than XML or JSON or HTML form data, but it is exactly the same usage as any other web service and compatible with the semantics of HTTP.

The only real difference between IPP and a typical web page load is the sheer volume of data - gigabytes for a raster printer versus megabytes for a typical web page without video (you'll get gigabytes for HD video).

Rather than claiming that HTTP was never designed to support such usage after the fact, perhaps it would be more constructive to accept that HTTP *is* used for things not directly connected to a web browser or web page.  I will also point out that all versions of the HTTP specs going back to RFC 1945 (HTTP/1.0) talk about HTTP being used for more than just web browsers.  Developers didn't just decide to subvert HTTP, *they were given permission and encouraged to use HTTP as a generic communication protocol*.

---

From: "Kennedy, Smith (Wireless Architect)" <[email-masked]>
Date: Wed, 28 May 2014 15:38:39 +0000

+2

_Every_ modern print protocol is based on HTTP: IPP, Google Cloud Print, and Microsoft WS-Print.  And this ignores the cloud print protocols, which are almost always either SOAP or RESTful web services.

Beyond that, most other protocols implemented by printers, scanners, and many, many and growing other peripherals also use HTTP.  To ignore the pervasive broader use of HTTP beyond delivering content to a browser, and to disqualify or discount those uses within the context of the design of HTTP/2, is quite frankly baffling.

Smith

/**
    Smith Kennedy
    ATB Wireless Architect - PPS
    Hewlett-Packard Co.
*/

---

From: Eliot Lear <[email-masked]>
Date: Wed, 28 May 2014 17:42:28 +0200

Michael,

On 5/28/14, 5:03 PM, Michael Sweet wrote:
> But on the low end we are *very* interested in adopting HTTP/2 for IPP
> USB where the number of available interfaces (== number of
> simultaneous connections that can be supported) is typically only 2.
>  Right now we are multiplexing access to these interfaces using a
> network proxy, but that means you can't have more than 2 requests in
> flight...  HTTP/2 would lift that limitation, but we need to be very
> careful about what resources we require since the current generation
> of SoCs used by the vendors can't do much more than they already do
> (printers are complicated pieces of hardware and the lowest cost SoC
> is used...)
>
Fair enough.  However...
> I'm aware that "we are on our own" for non-network usage of HTTP -
> that's fine - but I would like to keep our usage as close to the
> standard as is feasible, otherwise vendors can't use the same HTTP/IPP
> software stack for USB and network printing.
>
>> protocol.  Quite frankly it was not designed to make printing faster
>> or more efficient, and to the best of my knowledge nobody has tested
>> for that case.  This is not a fault of the protocol.  Good engineers
>> constrain their design space.  HTTP/1.1 has suffered from wild
>> success (RFC 5218) and is well beyond its design space.  I see
>> nothing wrong in constraining the design space, so long as what's
>> left is useful to a significant population.
>
> Frankly, this attitude about printing being outside the design space
> of HTTP is crap.  IPP is a web service, exactly as envisioned in the
> original HTTP specs.  Every IPP request is a POST with a message body.
>  The message body happens to be a binary encoded message
> (application/ipp) rather than XML or JSON or HTML form data, but it is
> exactly the same usage as any other web service and compatible with
> the semantics of HTTP.

There is the design space for "HTTP" and the design space for "HTTP/2". 
We have made the assumption that they are both the same, and I have
repeatedly questioned that point.
>
> The only real difference between IPP and a typical web page load is
> the sheer volume of data - gigabytes for a raster printer versus
> megabytes for a typical web page without video (you'll get gigabytes
> for HD video).

Well that's right.  Tell me why you need the additional layer of framing
in these circumstances.

Eliot

---

From: James M Snell <[email-masked]>
Date: Wed, 28 May 2014 08:52:59 -0700

So are we getting back to the "they can just keep using http/1.1" argument
or do I misunderstand your point?

On May 28, 2014 8:48 AM, "Eliot Lear" <[email-masked]> wrote:
[snip]
>
>>
>> The only real difference between IPP and a typical web page load is the
sheer volume of data - gigabytes for a raster printer versus megabytes for
a typical web page without video (you'll get gigabytes for HD video).
in these circumstances.

---

From: Eliot Lear <[email-masked]>
Date: Wed, 28 May 2014 17:57:07 +0200

On 5/28/14, 5:52 PM, James M Snell wrote:
>
> So are we getting back to the "they can just keep using http/1.1"
> argument or do I misunderstand your point?
>

Yes.  That's not to say people shouldn't adapt HTTP/2 to other uses. 
Just that HTTP/2 needn't adapt to *all* uses.  And perhaps the onus
should be on those who don't want to do compression to indicate that
HTTP/2 to them is still useful.  If there are enough of them, this is an
easily solved problem: just use another identifier of HTTP/2 in ALPN
that indicates no compression. h2c is taken.

Eliot

---

From: Johnny Graettinger <[email-masked]>
Date: Wed, 28 May 2014 11:58:21 -0400

> a typical web page without video (you'll get gigabytes for HD video).

Forgive me as IANAE, but isn't the bit-manipulation cost from
Huffman-decoding small meta-data blocks on a stream, overwhelmed by the
cost of transferring gigabytes of data on that same stream over a TLS link?

>
> Rather than claiming that HTTP was never designed to support such usage
> after the fact, perhaps it would be more constructive to accept that HTTP
> *is* used for things not directly connected to a web browser or web page.
>  I will also point out that all versions of the HTTP specs going back to
> RFC 1945 (HTTP/1.0) talk about HTTP being used for more than just web
> browsers.  Developers didn't just decide to subvert HTTP, *they were given
> permission and encouraged to use HTTP as a generic communication protocol*.
>

---

From: Michael Sweet <[email-masked]>
Date: Wed, 28 May 2014 13:16:35 -0400

Johnny,

On May 28, 2014, at 11:58 AM, Johnny Graettinger <[email-masked]> wrote:
> Forgive me as IANAE, but isn't the bit-manipulation cost from Huffman-decoding small meta-data blocks on a stream, overwhelmed by the cost of transferring gigabytes of data on that same stream over a TLS link?

Gigabytes stretched over many minutes or hours (low end printers are typically slow, too...)  And these printers offload encryption and print data processing to dedicated silicon (wouldn't be feasible otherwise).

Anyways, not all printers support encryption (like I said, we are pushing for universal TLS support but haven't gotten there yet) and anything not handled by silicon gets handled by the underpowered CPU core.

---

From: Michael Sweet <[email-masked]>
Date: Wed, 28 May 2014 13:27:29 -0400

Eliot,

On May 28, 2014, at 11:42 AM, Eliot Lear <[email-masked]> wrote:
> ...
> There is the design space for "HTTP" and the design space for "HTTP/2".  We have made the assumption that they are both the same, and I have repeatedly questioned that point.

There is no assumption.  From the HTTPbis charter:

  The Working Group will produce a specification of a new expression of HTTP's
  current semantics in ordered, bi-directional streams. As with HTTP/1.x,
  the primary target transport is TCP, but it should be possible to use
  other transports.

There is a lot of other text, but basically the charter says that HTTP/2.0 will provide the same semantics and functionality as HTTP/1.1, and allow for 1.1->2.0 and 2.0->1.1 gateways.

> Well that's right.  Tell me why you need the additional layer of framing in these circumstances.

Because while we are sending those gigabytes to the printer to get dots on paper, it is important to monitor the status of the printer and job, and allow for job control in parallel with submission.

Currently that means opening a separate connection, which consumes resources that are constrained.  With HTTP/2 we can perform these status and control operations on the same connection.

---

From: Martin Thomson <[email-masked]>
Date: Wed, 28 May 2014 10:32:44 -0700

> worldwide update of all servers to the new version (or drop to HTTP

That's extreme, but I think reasonable.  Given that you are talking
about trying to force behaviour on a counterparty, I don't see there
being any virtue in finer grained control over counterparty behaviour.

---

From: Roberto Peon <[email-masked]>
Date: Wed, 28 May 2014 10:40:25 -0700

The DoS surface with HTTP headers is not increased over HTTP/1 (which also
would suffer from a requirement to tear down the transport when that kind
if thing happens, unlike HTTP2).

I believe I've mentioned before seeing rare, but multi-Mb headers in the
past. We had, before that experience, amusingly assumed that 16k was enough
for anyone, and were wrong by orders of magnitude.

If our proxy sees something like this unexpectedly, it will terminate that
request. If it is expected, it is allowed through.

If one takes into account the resources needed for os/system and
cryptographic needs, you should find that HTTP2 uses less resources than
http/1 at just about any level of concurrency above 1, and even more so
when the receiver has set max state to zero.

Our experience also shows that the second order effects work to further
decrease connection load as people realize that domain sharding doesn't
help latency with HTTP2, and un-sharding ends up reducing connection count
by a factor of more than 6. This reduces CPU, memory, and bandwidth load.

-=R
On May 28, 2014 3:25 AM, "Greg Wilkins" <[email-masked]> wrote:

> As somebody who has implement a server handling a million connections,
> I've very much concerned by the resource requirements implied by HTTP/2 for
> a server.   Not only does a server have to commit to storing the headers
> that can result from a 16k compressed header frames, but it may receive

---

From: "Richard Wheeldon (rwheeldo)" <[email-masked]>
Date: Wed, 28 May 2014 19:09:51 +0000

> And these printers offload encryption and print data processing to dedicated silicon (wouldn't be feasible otherwise).

Now that's an interesting argument against HPACK - the lack of dedicated silicon to support it. Not having played in the embedded space for a few years, how easy is that to get around?

---

From: Yoav Nir <[email-masked]>
Date: Wed, 28 May 2014 22:18:53 +0300

On May 28, 2014, at 8:40 PM, Roberto Peon <[email-masked]> wrote:

> The DoS surface with HTTP headers is not increased over HTTP/1 (which also would suffer from a requirement to tear down the transport when that kind if thing happens, unlike HTTP2).
> 
> I believe I've mentioned before seeing rare, but multi-Mb headers in the past. We had, before that experience, amusingly assumed that 16k was enough for anyone, and were wrong by orders of magnitude.
> 
So I’m wondering. Some of us (not all) seem to be OK with telling some use cases to stick with HTTP/1, like printing or IoT or many of the other places that are outside HTTP/2 “design space”. Why are we going to such lengths to support this abuse of the protocol. Is it just because HTTP/1 allows it?

Yoav

---

From: Michael Sweet <[email-masked]>
Date: Wed, 28 May 2014 15:28:06 -0400

Richard,

> Now that's an interesting argument against HPACK - the lack of dedicated silicon to support it. Not having played in the embedded space for a few years, how easy is that to get around?

You can still do a software solution, but depending on how constrained you are that solution might cause unwanted performance degradation or prevent you from doing some key function (like answer an incoming fax).  I'm hoping this kind of constraint will work itself out in another 5 years (price of faster SoCs keeps coming down, more network connected services for MFPs, etc.) but in the meantime I'm bringing this up as an issue for today's HTTP-using hardware.

(FWIW, if I am reading Richard's CWS stats correctly on request header sizes, it looks like the vast majority of all web requests use less than 1k of headers, which with the static header table would be further reduced - sure seems like we can get the initial GET to the server out in one packet even without Huffman...)

---

From: Roberto Peon <[email-masked]>
Date: Wed, 28 May 2014 12:28:39 -0700

I can't answer why for everyone, but yes, for this part at least, the
motivation was to be able to deploy an HTTP2 proxy that wouldn't break any
of our consumers, be they clients or servers.

I'm not convinced that large headers are an abuse of the protocol, btw.
There were some uses that I had to shake my head at and admit that there
weren't many other reasonable ways around it, e.g. clearing out all
possible permutations of all cookie-names, so that an auth cookie could
actually be successfully registered.

Certainly, that particular problem could be solved in a different way with
HTTP/2, but it would require changing other semantics, and would require
the server to realize there was a difference, which would cause deployment
headaches, etc. For all I know this has been fixed by additions to HTTP of
which I'm unaware.

I'll note that it is definitely a rare case, but when I saw it used, it was
also important for user interaction (else one would have to somehow
communicate to the user that they'd have to blow away their cache).
In cases where it is unexpected, I'd expect an endpoint to take action to
shutdown the stream. Attacks, whether malicious or not, are a fact of life,
and it is good to be able to identify them and blow them away without
affecting other users overly much.
-=R

On Wed, May 28, 2014 at 12:18 PM, Yoav Nir <[email-masked]> wrote:

> So I’m wondering. Some of us (not all) seem to be OK with telling some use
> cases to stick with HTTP/1, like printing or IoT or many of the other
> places that are outside HTTP/2 “design space”. Why are we going to such
> lengths to support this abuse of the protocol. Is it just because HTTP/1
> allows it?
>
> Yoav
>
>
>

---

From: Jason Greene <[email-masked]>
Date: Wed, 28 May 2014 14:32:28 -0500

> Now that's an interesting argument against HPACK - the lack of dedicated silicon to support it. Not having played in the embedded space for a few years, how easy is that to get around?

I think he addressed that in his subsequent reply (https://github.com/http2/http2-spec/issues/485) 

-Jason

---

From: "Richard Wheeldon (rwheeldo)" <[email-masked]>
Date: Wed, 28 May 2014 22:10:58 +0000

> if I am reading Richard's CWS stats correctly on request header sizes, it looks like the vast majority of all web requests use less than 1k of headers

Less than 2 certainly. They're rounded down to the nearest KB. I can get more numbers if folks have a particular interest to drill down in,

Richard

---

From: David Krauss <[email-masked]>
Date: Thu, 29 May 2014 10:46:17 +0800

> So I’m wondering. Some of us (not all) seem to be OK with telling some use cases to stick with HTTP/1, like printing or IoT or many of the other places that are outside HTTP/2 “design space”. Why a…

The Internet Of Things is here to stay, and physically as transistors shrink, microcontrollers and radio sets get smaller and cheaper, and internet connections get more ubiquitous *without* an increase in computing power.

I think this discussion is getting sidetracked, though, because:

1. There is no real evidence that stateless Huffman decoding is computationally intensive even for an 8-bit micro. Let’s see some code and some numbers.

2. Embedded application protocols can be designed to avoid ever Huffman-encoding anything of interest to the device. If a printer is using some HTTP/1.1 response headers, the upgrade to HTTP/2 is enough opportunity to change that metadata to DATA frame data. The only unavoidable case I can think of is :status, but it’s “safe enough” to assume that will be either encode 200 OK by the static table, or anything else represents failure. Correct me if I’m wrong.

3. A Huffman decoding proxy can be inserted at the USB socket relay. I’m working on a very generalized library that should hopefully handle such a task, but it doesn’t sound like such a tall order for other proxy packages even if I never finish.

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 29 May 2014 08:24:17 +0200

> that indicates no compression. h2c is taken.

My opinion has always been that HTTP/2 should be able to replace HTTP/1
in all situations, even if not optimally in some cases. Having to maintain
dual-stack in many products will remain a security challenge and at some
point client developers will start to emit warnings when using 1.1 :
"Warning: the site you are trying to visit uses an obsolete version of HTTP
 which can cause your system to malfunction, do you want to continue ?"

And just because of that, all commonly used devices will have to support
2.0 even with the minimal feature set.

So I'd like HTTP/2 to be able to replace HTTP/1 in all use cases even if
that's not optimal nor justified by technical reasons.

Willy

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 29 May 2014 08:28:44 +0200

On Wed, May 28, 2014 at 10:10:58PM +0000, Richard Wheeldon (rwheeldo) wrote:
> Less than 2 certainly. They're rounded down to the nearest KB. I can get more
> numbers if folks have a particular interest to drill down in,

It would be nice to filter only on those which were actually accepted by
the server (eg: returned a 2xx or 3xx status code only). But that's clearly
very interesting data, I only had the opportunity to work on a much smaller
data set in the past!

Willy

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 29 May 2014 08:34:15 +0200

> being any virtue in finer grained control over counterparty behaviour.

I tend to think that a failsafe, non-optimal fallback without the bells
and whistles could significantly drive adoption. Devices could start by
only supporting this minimal subset, and later implement the large one.
These ones could be advertised in the ALPN name (h2 = failsafe, h2h =
hpack version for example) so that we don't need an extra round trip
to know what is supported.

That way if a CRIME-like attack surfaces, simply disable h2h for the
time it takes to design a new encoding and applications relying on
passing everything in the same connection continue to work, just
slightly slower.

And devices with limited capabilities can only implement the non-optimal
mode which is cheaper for them.

Willy

---

From: Simone Bordet <[email-masked]>
Date: Thu, 29 May 2014 09:02:58 +0200

Hi,

> mode which is cheaper for them.

I wholeheartedly agree with this approach.
There need not to be a full negotiation mechanism, h2 and h2h are
enough for now, and failing that negotiation, fall back to HTTP 1.1.

---

From: Matthew Kerwin <[email-masked]>
Date: Thu, 29 May 2014 17:36:59 +1000

> to know what is supported.

I'm happy with this idea, as long as it doesn't start to do the
multiple-permutations or alpn-token-per-feature thing. How does it interact
with h2c, for example? (I'd suggest h2c implies h2h, and no fourth
variant.) I guess it's safe as long as there are no other non-negotiable
features *coughgzipcough* , or things that need a settings rtt to disable,
that need to be avoided independently from HPACK.

Perhaps it would be better to use h2f for failsafe mode, to make it clear
that h2 is the benchmark, and h2f is an acceptable variant/subset. It's
more of an all-or-nothing approach that way. It also fits the "add a
letter, remove a feature" pattern established with h2c and security.

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 29 May 2014 13:47:27 +0200

On Thu, May 29, 2014 at 07:41:05AM -0400, Jason T. Greene wrote:
> 
> > On May 29, 2014, at 1:40 AM, Willy Tarreau <[email-masked]> wrote:
> > 
> You mean disable/disallow the Huffman encoding bit in HPACK right? HPACK with
> a size 0 table is easy for embedded devices (and everyone else), offers
> decent reduction in header sizes, and runs no risk of a CRIME style attack.

Yes possibly, but anyway this is the general idea. What features should
remain in the failsafe, cheap an suboptimal fallback have to be determined.

> If you did the above if likely wouldn't be slower, it would even be
> computationally faster, and might still be small enough to limit round
> trips

I think so as well.

Willy

---

From: Jason Greene <[email-masked]>
Date: Thu, 29 May 2014 08:51:24 -0500

> to know what is supported.

You mean disable/disallow the Huffman encoding bit in HPACK right? HPACK with a size 0 table is easy for embedded devices (and everyone else), offers decent reduction in header sizes, and runs no risk of a CRIME style attack.

> passing everything in the same connection continue to work, just

If you did the above if likely wouldn't be slower, it would even be computationally faster, and might still be small enough to limit round trips

---

From: David Krauss <[email-masked]>
Date: Thu, 29 May 2014 22:27:52 +0800

> You mean disable/disallow the Huffman encoding bit in HPACK right? HPACK with a size 0 table is easy for embedded devices (and everyone else), offers decent reduction in header sizes, and runs no r…

I’ve just started debugging an 8-bit friendly Huffman decoder. It looks like under a kilobyte of code & tables, and on the order of 100 instructions executed per symbol. (Could be less than a hundred, could be more. Haven’t profiled yet.)

Huffman is just a drop in the bucket. I’ll share the code when it’s working.

---

From: Michael Sweet <[email-masked]>
Date: Thu, 29 May 2014 11:00:32 -0400

David,

> Huffman is just a drop in the bucket. I’ll share the code when it’s working.

I do appreciate your efforts.  But 100 instructions per byte is at least one order of magnitude more instructions than a literal copy of those bytes requires...  For 16k worth of header data that translates into 1.6 million instructions executed just for one header frame - fairly significant for an embedded processor...

For point of reference, proxying Richard's ~6B requests would require on the order of 10^15 instructions to be executed to decode all of the headers, and then perhaps another 10^15 instructions to re-encode them (depends on how it stores its header tables).  Perhaps not unreasonable for fast proxy hardware over a period of a day, but is it necessary?

---

From: David Krauss <[email-masked]>
Date: Thu, 29 May 2014 23:12:07 +0800

On 2014–05–29, at 11:00 PM, Michael Sweet <[email-masked]> wrote:

> I do appreciate your efforts.  But 100 instructions per byte is at least one order of magnitude more instructions than a literal copy of those bytes requires...  For 16k worth of header data that translates into 1.6 million instructions executed just for one header frame - fairly significant for an embedded processor…

If the MCU sees more than a hundred Huffman-encoded bytes per stream, you’re Doing It Wrong.

There are plenty of other ways for a malicious party to crash a printer. 1.6 million instructions is still only a blink of an eye even for a small MCU.

> For point of reference, proxying Richard's ~6B requests would require on the order of 10^15 instructions to be executed to decode all of the headers, and then perhaps another 10^15 instructions to…

Yes, byte-by-byte decoding is inherently branchy and may cause branch misprediction. However, the topic was low-end embedded processors and they aren’t pipelined. Anyway, my code is not optimized for that, and there’s no extrapolating MCU cycles to Xeon cycles.

---

From: "Kennedy, Smith (Wireless Architect)" <[email-masked]>
Date: Thu, 29 May 2014 15:35:21 +0000

+1

Smith

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 29 May 2014 18:01:10 +0200

On Thu, May 29, 2014 at 11:12:07PM +0800, David Krauss wrote:
> 
> On 2014?05?29, at 11:00 PM, Michael Sweet <[email-masked]> wrote:
> 
> > I do appreciate your efforts.  But 100 instructions per byte is at least one order of magnitude more instructions than a literal copy of those bytes requires...  For 16k worth of header data that translates into 1.6 million instructions executed just for one header frame - fairly significant for an embedded processor?
> 
> If the MCU sees more than a hundred Huffman-encoded bytes per stream, you?re Doing It Wrong.
> 
> There are plenty of other ways for a malicious party to crash a printer. 1.6
> million instructions is still only a blink of an eye even for a small MCU.

Well, 1.6M instructions for a request is huge, whatever the processor size.
That would basically limit a 3 GHz CPU to 2000 requests/s when it can currently
do 300000 in http/1.1. I'm starting to be really worried...

Willy

---

From: Martin Thomson <[email-masked]>
Date: Thu, 29 May 2014 09:12:55 -0700

> do 300000 in http/1.1. I'm starting to be really worried...

That assumes that you need to decode header fields.  There's no reason
you can't do a byte-by-byte comparison in many cases.

---

From: Martin Thomson <[email-masked]>
Date: Thu, 29 May 2014 09:24:49 -0700

On 29 May 2014 00:36, Matthew Kerwin <[email-masked]> wrote:
> that h2 is the benchmark, and h2f is an acceptable variant/subset. It's more
> of an all-or-nothing approach that way. It also fits the "add a letter,
> remove a feature" pattern established with h2c and security.

Please no.  That's not a pattern worth repeating.  I know that we've
discussed a limited profile in the past, but that was used to prime
initial state.

I haven't seen any justification for creating a protocol variation.
See Section 3.4 of RFC 6709:
http://tools.ietf.org/html/rfc6709#section-3.4

Note: h2c is a protocol variation in some ways, but it's merely
propagating an existing variation.

---

From: David Krauss <[email-masked]>
Date: Fri, 30 May 2014 00:36:34 +0800

On 2014–05–30, at 12:01 AM, Willy Tarreau <[email-masked]> wrote:

> do 300000 in http/1.1. I'm starting to be really worried…

3 GHz CPUs don’t do only one instruction per cycle. See the caveats I mentioned.

If you want to overwhelm the network hardware in a printer, you can easily do so just given its IP address. Aside from malicious inputs, a printer protocol with so many headers would be simply broken. That is my only point.

Also, the 100 instructions figure is just a guesstimate from looking at my compiled binary. I’ve debugged using only the first example from the spec, but it’s past my bedtime, so maybe someone would like to test further or profile the code. But, again, it is designed for embedded MCUs and not really network-oriented hardware.

https://code.google.com/p/lightweight-http2-huffman-decoder/

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 29 May 2014 18:45:18 +0200

On Fri, May 30, 2014 at 12:36:34AM +0800, David Krauss wrote:
> 
> On 2014?05?30, at 12:01 AM, Willy Tarreau <[email-masked]> wrote:
> 
> > do 300000 in http/1.1. I'm starting to be really worried?
> 
> 3 GHz CPUs don?t do only one instruction per cycle. See the caveats I mentioned.

No but my experience tells me that bit manipulation operations are very
rarely parallelizable. And anyway,even if they were, we wouldn't run 100
instructions in parallel :-)

> If you want to overwhelm the network hardware in a printer, you can easily do
> so just given its IP address. Aside from malicious inputs, a printer protocol
> with so many headers would be simply broken. That is my only point.

I agree and am not trying to "protect" the small devices from being attacked,
just trying to figure what optimal performance we can get with/without certain
encoding options. Being used to optimize code to reach hundreds of thousands
of requests per second with hundreds of thousands of concurrent connections,
I'm facing the same challenges as Michael with his MCU in that I'm having a
very limited amount of memory and CPU cycles per request, except that I have
a wider choice of instructions.

> Also, the 100 instructions figure is just a guesstimate from looking at my
> compiled binary. I?ve debugged using only the first example from the spec,
> but it?s past my bedtime, so maybe someone would like to test further or
> profile the code. But, again, it is designed for embedded MCUs and not really
> network-oriented hardware.

OK.

> https://code.google.com/p/lightweight-http2-huffman-decoder/

Thanks for sharing the code, that's really helpful.

Willy

---

From: Eliot Lear <[email-masked]>
Date: Thu, 29 May 2014 18:57:45 +0200

Hi Martin,

> http://tools.ietf.org/html/rfc6709#section-3.4

That's really not the intent, if not the reading, of that section.  A
variation occurs within a protocol, and the key focus of that text is
one of assuring interoperability with means to identify among the
communicating systems that different rules in play.  Here there are
clear mechanisms to do that.  They are talking about a separate clearly
identified protocol.  Whether or not a separate protocol is warranted is
a different discussion.  Michael says yes.  You say no.  Generally fewer
code paths are better, and so that's why I would say the onus is on the
proponents of the additional code path.

Eliot

---

From: Jason Greene <[email-masked]>
Date: Thu, 29 May 2014 11:58:52 -0500

> you can't do a byte-by-byte comparison in many cases.

That’s true. An optimal reverse proxy, for example, could do method/location/path matching using bitmasks, and pass the message as a direct copy.

--
Jason T. Greene
WildFly Lead / JBoss EAP Platform Architect
JBoss, a division of Red Hat

---

From: Roberto Peon <[email-masked]>
Date: Thu, 29 May 2014 10:37:00 -0700

...And this could be faster than the "bare" strings given it is a smaller
number of bytes.

In 2012, a not optimized delta encoder (which included Huffman encoding +
delta encoding) got the following results on a single core of my
workstation, which wasn't a particularly fast machine:

"Delta-coding took: 0.642199 seconds for: 104300 header frames or
6.15723e-06 per header or 162411 headers/sec or 8.88429e+07 bytes/sec"

Huffman decoding itself is *significantly* faster than this, when necessary
at all.

-=R

> you can't do a byte-by-byte comparison in many cases.

That’s true. An optimal reverse proxy, for example, could do
method/location/path matching using bitmasks, and pass the message as a
direct copy.

---

From: Michael Sweet <[email-masked]>
Date: Thu, 29 May 2014 13:41:14 -0400

Martin,

> you can't do a byte-by-byte comparison in many cases.

Perhaps for the field names (which is a stretch but all of the standard headers can be encoded using the static header table indices so let's go with it), but any value that gets used (not just matched against a constant string) will need to be decoded.

For argument's sake, let's say that half of the request header bytes are from the names and delimiters, and then we only really need to use half of the values (we don't care about User-Agent, etc.) - that still leaves 400,000 instructions per header frame or approximately 2.5x10^14 instructions for 6B requests.

---

From: Michael Sweet <[email-masked]>
Date: Fri, 30 May 2014 10:08:49 -0400

Eliot,

On May 29, 2014, at 12:57 PM, Eliot Lear <[email-masked]> wrote:
> a different discussion.  Michael says yes.

I didn't say anything about a separate protocol.  I have filed an issue and mentioned on several occasions that I would like a setting (that can be passed in the initial HTTP/2 setup) to disable Huffman, just as we have a setting for the header table size.

I don't think that would be overwhelming to test or implement, and since we are already asking implementations to track header representations that must be preserved (literal headers without indexing) I don't think it would be stretch to have a way to say "do not Huffman compress at all".

---

From: Jason Greene <[email-masked]>
Date: Fri, 30 May 2014 10:05:03 -0500

> I don't think that would be overwhelming to test or implement, and since we are already asking implementations to track header representations that must be preserved (literal headers without indexi…

On this topic, has there been any consideration given to a potential need to alter the huffman code table after release? Perhaps after real world deployment someone determines that slightly different weighting would lead to improved packet size. My apologies if this was discussed in a past thread.

---

From: Martin Thomson <[email-masked]>
Date: Fri, 30 May 2014 09:30:04 -0700

> On this topic, has there been any consideration given to a potential need to alter the huffman code table after release? Perhaps after real world deployment someone determines that slightly differe…

Yes, we put this in the "significant change" category.  That means
"h3", most likely.  If we bring back extensions, then there will be
other ways to move to an arithmetic coder or typed fields or something
crazy.

---

From: Roberto Peon <[email-masked]>
Date: Fri, 30 May 2014 11:04:09 -0700

The huffman design (using canonical huffman) was chosen such that replacing
the table would be cheap (as transmitted on the wire), if, in the
far-future it is needed to change tables, it will be cheap/possible.
That is something to play around with, but not something that I'd guess
would fit in the protocol today, as it has uncertain security ramifications.

-=R

On Fri, May 30, 2014 at 9:30 AM, Martin Thomson <[email-masked]>
wrote:

> > On this topic, has there been any consideration given to a potential
> need to alter the huffman code table after release? Perhaps after real
> world deployment someone determines that slightly different weighting would
> lead to improved packet size. My apologies if this was discussed in a past
> thread.
>

---

From: Amos Jeffries <[email-masked]>
Date: Sun, 01 Jun 2014 17:30:21 +1200

> would fit in the protocol today, as it has uncertain security ramifications.

As a result we need a halfway operation to prevent the existing huffman
table being used. The best proposal for that so far is the
disable-huffman SETTING. Which downgrades it from the existing table to
none rather that changing to an arbitrary alternative table.

The simplicity gained for naive implementations is an added bonus.

Amo

---

From: Matthew Kerwin <[email-masked]>
Date: Sun, 1 Jun 2014 16:31:53 +1000

> The simplicity gained for naive implementations is an added bonus.
I assume the default behaviour would be to use HPACK, and the setting would
disable it. ​Because a client is allowed to send requests without waiting
for the server's settings (§3.5) would it be alright for the server to
respond with RST_STREAM(REFUSED_STREAM) to any streams with compressed
headers that arrive before the ACK? Or does REFUSED_STREAM imply that
headers have passed through/modified the HPACK context before being
refused? In this case we don't want to tear down the connection with a
COMPRESSION_ERROR;  if REFUSED_STREAM is inappropriate, perhaps we could
use RST_STREAM(COMPRESSION_ERROR) to signal that it was refused *before*
HPACK.

Incidentally, as an editorial issue, I'd personally appreciate some text
that clearly states whether REFUSED_STREAM comes before or after HPACK. It
says "prior to any processing", does that include HPACK?

-- 
  Matthew Kerwin
  http://matthew.kerwin.net.au/