Re: [TLS] New Internet Draft: The qpack_static_table_version TLS extension

A few upcoming changes for version-01:

1. A published version of the QPACK static table (see #2 for publishing
details) will have a Length and a Version, and the QSTVExtension will be
defined like this:

struct {
    uint8 StaticTableVersion;
    uint8 StaticTableLength;
} qpack_static_table_version;

where:

StaticTableVersion - the version of the table. Initial version is 0.
StaticTableLength - the maximum number of entries supported in the table.
Initial length is 99

So the first version of the table (currently defined in Appendix A in RFC
2904 (https://www.rfc-editor.org/rfc/rfc9204.html#name-static-table-2) will
be 0,99.



2. I will specify that a new IETF registry should be created (and
*nominally* maintained by IANA) with myself and others as designated
experts. On an ongoing basis, we will sample traffic (likely from the HTTP
Archive, since they already do significant web traffic sampling). Where new
HTTP field names or name/value combinations (collectively 'header lines')
have become more prevalent than the current last entry in the latest table
, they will be appended as new entries in the table, increasing its length.

Additionally, on an ongoing basis, new Versions of the table will be
created. This will involve re-ordering the table to ensure that the entries
are ordered in the most efficient manner possible.

Example
=======

The initial table is 0,99 (Version 0, Length 99) and is published in the
registry.

A year from now, we re-sample traffic and discover 12 new header lines
which are more common than "x-frame-options: sameorigin" (entry 99 in the
current table). These 12 header lines are ordered by prevalence to each
other and appended as entries in the table in the registry - this is
referred to as 0,111 (Version 0, Length 111) and REPLACES table 0,99 in the
registry.

A year after that, we re-sample traffic again and discover 5 new prevalent
header lines, so we order these entries and append them, giving table
0,116, which REPLACES table 0,111.

Crucially, there is no reordering of entries in Version 0 - only appending
of new entries.

At that point, we ALSO reorder ALL the table entries in order of total
prevalence and increment the Version, giving 1,116 and publish that as a
separate table in the registry.

So now we have two published tables:

* 0,116 - Version 0 with 116 entries. Entries 0-98 are in the same order as
the current QPACK table. Entries 99-111 are ordered by prevalence with one
another, but not with any prevalence order to entries 0-98. Same goes for
entries 112-116 - ordered in relationship to one another but with
relationship to entries 0-111.
* 1,116 - Version 1 with 116 entries. All entries are ordered by prevalence
compared to every other entry.

Over time, the registry could end up containing multiple Versions. Older
versions MAY be deprecated if we can reasonably determine that they are no
longer used (TBD). Only one table per Version will be published at any time.

Clients and servers MUST always support Version 0. They MAY also support
other Versions as long as they support all intermediate versions between
Version 0 and the Version for which they advertise support in
qpack_static_table_version. This allows both client and server to simply
downgrade to a shared supported Version without the client needing to
advertise multiple supported Versions (c.f. TLS cipher suites) and possibly
missing intermediate versions.

Client and servers can still negotiate both the highest Version the support
and the Length (number of entries) within that Version in a manner similar
to that in version-00 of the I-D as follows:

Client processing
=================

Initialize variable CV to supported StaticTableVersion value
Initialize variable CL to supported StaticTableLength value
Include qpack_static_table_version in ClientHello
if (ServerHello does not contain qpack_static_table_version or if
qpack_static_table_version contains invalid values) {
    set CV to 0
    set CL to lesser of default value and CL
} else {
    save qpack_static_table_version from ServerHello as SV,SL
    if (SV < CV) {
        set CV to SV
    }
    if (SL < CL) {
        set CL to SL
    }
}
use CV,CL for static table index processing

Server processing
=================

Initialize variable SV to supported StaticTableVersion value
Initialize variable SL to supported StaticTableLength value
if (ClientHello does not contain qpack_static_table_version or if
qpack_static_table_version contains invalid values) {
    set SV to 0
    set SL to lesser of default value and SL
} else {
    save qpack_static_table_version from ClientHello as CV,CL
    if (CV < SV) {
        set SV to CV
    }
    if (CL < SL) {
        set SL to CL
    }
    Include qpack_static_table_version in ServerHello
}
Use SV,SL for static table index processing



3. A client or server can specify any positive value for StaticTableLength.
A negative value is invalid and the default value (99) MUST be assumed by
the receiver.

Thus a client or server which may have very limited memory and/or which
expects to send/receive only a few known headers can specify 0,30,
indicating that they support only the first 30 entries in Version 0 of the
static table and any other header lines must be specified in the dynamic
table.

Thoughts?

Rory

On Wed, Oct 4, 2023 at 12:16 PM Kazuho Oku <kazuhooku@gmail.com> wrote:

>
>
> 2023年9月29日(金) 3:18 Marten Seemann <martenseemann@gmail.com>:
>
>> Some thoughts:
>>
>>    - Putting it into a TLS extension seems like a layering violation. At
>>    that point during the handshake, we don't know yet which ALPN will be
>>    negotiated. In the best case scenario, this would render
>>    the qpack_static_table_version extension useless, but things might get
>>    more complicated once a different protocol (HTTP/3.1?) starts using QPACK
>>    (potentially with a different static table).
>>    - I've never been a big fan of the one-size-fits-all approach of
>>    QPACK's static table, so a replacement mechanism would be much more
>>    interesting to me.
>>
>> I might echo the hesitation of using indices as a way extension point,
> but in a more technical way.
>
> The problem of extending the static table as proposed is that it is prone
> to ossification; there's no way of reclaiming a slot once that slot is
> occupied by anything, that being an individual draft, WG draft, private
> experiment, or whatever.
>
> If anybody makes use of a slot and we want to take back, what we'd be
> doing is to use a different code point in the negotiation scheme,
> regardless of the scheme being TLS extensions or HTTP settings.
>
> But if we are to use code points to indicate different ways of extending
> the static table, wouldn't it better to just use different IDs to indicate
> different tables being used, from day one?
>
> Then, we can have a huge number space to indicate many many kinds of
> static tables. Some of them can be extensions of the current static table,
> some can be entirely different.
>
> Separately, I think it would be great if the I-D was accompanied by a
> scheme that makes actual use of the extension, rather than just proposing a
> mechanism to extend. That's because without an actual use-case it is hard
> to test interop and the correctness of the design.
> --
> Kazuho Oku
>

Received on Wednesday, 4 October 2023 21:12:46 UTC