Subject: [Masque] Layered or integrated protocols

From: "Martin Thomson" <[email-masked]>
Date: Wed, 21 Jul 2021 16:51:14 +1000

I was originally just going to announce here that I've made a contribution to the discussion on how to map WebTransport semantics to HTTP.  To be honest this isn't a mapping to HTTP, it's more of a burrow into.

In case you want to read it, here it is: https://www.ietf.org/archive/id/draft-thomson-webtrans-hwtq-00.html

However, in discussing this with Alan Frindell and Eric Kinnear I realized that the designs we are all proposing are based on a bunch of assumptions.

The HTTP/2 integration in draft-ietf-webtrans-http2-00 assumes that the shortest path to expressing WebTransport semantics in HTTP/2 is to reuse HTTP/2 stream semantics as much as possible, adjusting where necessary.  That has a lot of merit, especially when you consider the potential reuse you get of multiplexing, priority, and whatnot.  It's not perfect, but you can make it work with a few precise tweaks.

Then I looked at where MASQUE is headed.  Despite a lot of similarities in what we are seeking to do, the differences there are nearly complete.  Extended CONNECT vs. CONNECT-UDP and capsules vs. frames mean that the two things might look similar, but they share very few design elements.  We are headed toward building one protocol for MASQUE and two completely different protocols for WebTransport.

I don't know what happened to the design of MASQUE that I originally saw, but to me that was a much cleaner layering.  That is, you establish a tunnel (using CONNECT-whatever) and then you use the resulting bidirectional stream to do whatever is necessary.  Then, if you have something better (as you do if you are using QUIC) you move things to their own streams or datagrams as the opportunity arises.

That basic design works for both WebTransport and MASQUE regardless of the HTTP version.  The cost is that a light integration with the underlying protocol forces the design to provide its own resource management and prioritization features.  Multiplexing without flow control is a good way to get bad outcomes, after all.  That might result in some duplication of effort, even bad interactions as you move from a two layer system (connection>stream) to a three layer system (connection>session>stream) in the extreme case.

What we have right now is deep integrations.  That has the aforementioned advantages, but it means that you need to own your stack before you can implement the extension.  That is, in their current form, you can't build WebTransport or MASQUE by taking an HTTP implementation and building *on* it, you have to build *in* the stack.

Deep integrations have a few advantages, particularly when it comes to reusing existing mechanisms.  The HTTP/{2,3} mapping can use HTTP/{2,3} stream flow control and prioritization (assuming that you have already replaced the RFC 7540 scheme for priority, that is).  But they are invasive and can be high maintenance.

Layering protocols avoids coupling at the cost of being constrained by the abstractions of the layers that are used.

One thing that I wanted to do by suggesting a layered design - aside from the architectural split - was to isolate the resource management for WebTransport sessions from the other resources consumed on the connection.  For instance, it would help if two sessions share a connection, then maybe they can each make progress if the other is determined to exhaust the stream limit.  Per session limits are a natural consequence of a layered design.  However, if we don't need that capability, it's not necessarily an advantage.  We should talk about whether we need per-session limits for WebTransport.  Same for MASQUE.

Eric mentioned one point that I hadn't considered.  A generic mapping of QUIC stream and datagram semantics to a stream transport might be more broadly useful.  If that has multiple uses, then that might be good motivation for a layered design.

I don't have a concrete example in mind, but I can offer is the fact that people want to use QUIC in other contexts and they probably do want a TCP fallback also.  If they can't just use WebTransport (which is possible), a generic mapping could be helpful where an HTTP/2 implementation might not be.  An HTTP/1.1 mapping would be the next best thing.  (From my perspective, however, I would never seek to make a purely generic mapping, but rather seek to make large parts of the design trivially reusable in a new mapping.  That's almost the same thing, but I've never seen a generic protocol mapping design that didn't end up full of weird stuff that handled irregularities in one substrate or other.  Or, for programming nerds: monomorphism > generics.)

Anyway, this is a long message to basically ask that we be deliberate about our choices.  I don't think that anyone has chosen the integrated path thoughtlessly, but I want to ask that we collectively step back and make sure that this is really what we want.  That might mean talking about the reasons that push toward integrated designs or more about our resource management requirements.

Cheers,
Martin

p.s., https://datatracker.ietf.org/doc/html/rfc1958#section-3 contains some wrongness (3.9) and some points that can be read any number of ways here (3.5), but I think that point 3.6 argues for layering.

---

From: Tommy Pauly <[email-masked]>
Date: Fri, 23 Jul 2021 16:08:52 -0700

Thanks for these thoughts, Martin.

I definitely agree with the sentiment on the direction, particularly this comment:

Of course, I know how we got to where we are in the conversation for MASQUE, and the considerations are reasonable taken as they are, but it’s certainly true that it’s building in a lot of complexity.

My other concern with some of these directions is that deeply integrated designs, particularly those that have many different extension points, end up being attractive for implementation bugs (see draft-iab-use-it-or-lose-it, heh). That’s a risk when MASQUE and WebTransport go in different directions, and have a menu of options that is too long.

Best,
Tommy

> On Jul 20, 2021, at 11:51 PM, Martin Thomson <[email-masked]> wrote:
> 
> -- 
> Webtransport mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/webtransport

---

From: David Schinazi <[email-masked]>
Date: Fri, 23 Jul 2021 16:29:15 -0700

[ WebTransport to BCC ]

Thanks for writing this up, Martin.

The original design for MASQUE [1] was indeed simpler, but it also didn't
play as nicely with HTTP - it started off by using HTTP semantics to
perform negotiation, then would pretty much hijack the entire QUIC
connection. That doesn't work well with HTTP intermediaries and connection
reuse. So when you suggested that we instead define a new method, we did
integrate more into HTTP, and added complexity, but I think we got real
benefits from that design change.

The new design with capsules does what you describe here though:
> That is, you establish a tunnel (using CONNECT-whatever) and then you use
the resulting bidirectional stream to do whatever is necessary.  Then, if
you have something better (as you do if you are using QUIC) you move things
to their own streams or datagrams as the opportunity arises.

In the latest MASQUE drafts, the client creates a new client-initiated
bidirectional stream, sends its HEADERS to indicate MASQUE by using the
CONNECT-UDP method and then it can start communicating on that stream with
capsules. The capsules allow this to work even in the presence of
intermediaries. And once you've registered, you can also use datagrams for
better performance.

And WebTransport (the version over HTTP/3) does the same thing. I'm not
sure what you mean when you say that they're very different. Using
CONNECT-UDP vs extended CONNECT with the :protocol pseudo-header is a
cosmetic choice that I'm happy to bikeshed, since both work just as well.
It doesn't impact the design at all.

I agree that it would have been great to have been able to build all of
this *over* HTTP instead *inside* HTTP, but if we wish to support
intermediaries I don't see any way to build datagrams over HTTP - you'll
need a way for the HTTP intermediary to know where to forward the datagram.

Do you have a concrete proposal for how to have datagrams not be as
integrated for HTTP/3?

David

[1] https://datatracker.ietf.org/doc/html/draft-schinazi-masque-00

On Fri, Jul 23, 2021 at 4:09 PM Tommy Pauly <tpauly=
[email-masked]> wrote:

> I don't know what happened to the design of MASQUE that I originally saw,
> but to me that was a much cleaner layering.  That is, you establish a
> tunnel (using CONNECT-whatever) and then you use the resulting
> bidirectional stream to do whatever is necessary.  Then, if you have
> something better (as you do if you are using QUIC) you move things to their
> own streams or datagrams as the opportunity arises.
>
> Of course, I know how we got to where we are in the conversation for
> MASQUE, and the considerations are reasonable taken as they are, but it’s
> certainly true that it’s building in a lot of complexity.
>
> My other concern with some of these directions is that deeply integrated
> designs, particularly those that have many different extension points, end
> up being attractive for implementation bugs (see
> draft-iab-use-it-or-lose-it, heh). That’s a risk when MASQUE and
> WebTransport go in different directions, and have a menu of options that is
> too long.
>
> Best,
> Tommy
>
> I was originally just going to announce here that I've made a contribution
> to the discussion on how to map WebTransport semantics to HTTP.  To be
> honest this isn't a mapping to HTTP, it's more of a burrow into.
>
> In case you want to read it, here it is:
> https://www.ietf.org/archive/id/draft-thomson-webtrans-hwtq-00.html
>
> However, in discussing this with Alan Frindell and Eric Kinnear I realized
> that the designs we are all proposing are based on a bunch of assumptions.
>
> The HTTP/2 integration in draft-ietf-webtrans-http2-00 assumes that the
> shortest path to expressing WebTransport semantics in HTTP/2 is to reuse
> HTTP/2 stream semantics as much as possible, adjusting where necessary.
> That has a lot of merit, especially when you consider the potential reuse
> you get of multiplexing, priority, and whatnot.  It's not perfect, but you
> can make it work with a few precise tweaks.
>
> Then I looked at where MASQUE is headed.  Despite a lot of similarities in
> what we are seeking to do, the differences there are nearly complete.
> Extended CONNECT vs. CONNECT-UDP and capsules vs. frames mean that the two
> things might look similar, but they share very few design elements.  We are
> headed toward building one protocol for MASQUE and two completely different
> protocols for WebTransport.
>
> I don't know what happened to the design of MASQUE that I originally saw,
> but to me that was a much cleaner layering.  That is, you establish a
> tunnel (using CONNECT-whatever) and then you use the resulting
> bidirectional stream to do whatever is necessary.  Then, if you have
> something better (as you do if you are using QUIC) you move things to their
> own streams or datagrams as the opportunity arises.
>
> That basic design works for both WebTransport and MASQUE regardless of the
> HTTP version.  The cost is that a light integration with the underlying
> protocol forces the design to provide its own resource management and
> prioritization features.  Multiplexing without flow control is a good way
> to get bad outcomes, after all.  That might result in some duplication of
> effort, even bad interactions as you move from a two layer system
> (connection>stream) to a three layer system (connection>session>stream) in
> the extreme case.
>
> What we have right now is deep integrations.  That has the aforementioned
> advantages, but it means that you need to own your stack before you can
> implement the extension.  That is, in their current form, you can't build
> WebTransport or MASQUE by taking an HTTP implementation and building *on*
> it, you have to build *in* the stack.
>
> Deep integrations have a few advantages, particularly when it comes to
> reusing existing mechanisms.  The HTTP/{2,3} mapping can use HTTP/{2,3}
> stream flow control and prioritization (assuming that you have already
> replaced the RFC 7540 scheme for priority, that is).  But they are invasive
> and can be high maintenance.
>
> Layering protocols avoids coupling at the cost of being constrained by the
> abstractions of the layers that are used.
>
> One thing that I wanted to do by suggesting a layered design - aside from
> the architectural split - was to isolate the resource management for
> WebTransport sessions from the other resources consumed on the connection.
> For instance, it would help if two sessions share a connection, then maybe
> they can each make progress if the other is determined to exhaust the
> stream limit.  Per session limits are a natural consequence of a layered
> design.  However, if we don't need that capability, it's not necessarily an
> advantage.  We should talk about whether we need per-session limits for
> WebTransport.  Same for MASQUE.
>
> Eric mentioned one point that I hadn't considered.  A generic mapping of
> QUIC stream and datagram semantics to a stream transport might be more
> broadly useful.  If that has multiple uses, then that might be good
> motivation for a layered design.
>
> I don't have a concrete example in mind, but I can offer is the fact that
> people want to use QUIC in other contexts and they probably do want a TCP
> fallback also.  If they can't just use WebTransport (which is possible), a
> generic mapping could be helpful where an HTTP/2 implementation might not
> be.  An HTTP/1.1 mapping would be the next best thing.  (From my
> perspective, however, I would never seek to make a purely generic mapping,
> but rather seek to make large parts of the design trivially reusable in a
> new mapping.  That's almost the same thing, but I've never seen a generic
> protocol mapping design that didn't end up full of weird stuff that handled
> irregularities in one substrate or other.  Or, for programming nerds:
> monomorphism > generics.)
>
> Anyway, this is a long message to basically ask that we be deliberate
> about our choices.  I don't think that anyone has chosen the integrated
> path thoughtlessly, but I want to ask that we collectively step back and
> make sure that this is really what we want.  That might mean talking about
> the reasons that push toward integrated designs or more about our resource
> management requirements.
>
> Cheers,
> Martin
>
> p.s., https://datatracker.ietf.org/doc/html/rfc1958#section-3 contains
> some wrongness (3.9) and some points that can be read any number of ways
> here (3.5), but I think that point 3.6 argues for layering.
>
> --

---

From: Lucas Pardue <[email-masked]>
Date: Sat, 24 Jul 2021 02:49:44 +0100

Good points on this thread. Too many to respond to directly.

WebTransport and MASQUE remind me of the UK comedy duo known as the Chuckle
Brothers [1]. They were related, looked vaguely similar, and had a
catchphrase "to me, to you" that was used often when they were trying to
deliver hard to manage items and shuffling back and forth.

There's a lot of similarity between the WebTransport and MASQUE. I think
we've been hitting problems that might have occurred in either as we
progress at different rates. And the solutions designed in one WG or spec
aren't as synchronised as we might like.

A Capsule semantic, that can be mapped to HTTP versions, can go a long way
to aligning WebTransport and MASQUE. It's currently defined in the HTTP/3
DGRAM spec out of necessity of invention, but it could be extracted it
people really wanted. When reading draft-thomson-webtrans-hwtq-00 my early
thoughts were that you could define capsule types to model the proposed
QUIC subset - this is basically what the datagram capsules are doing for
QUIC DATAGRAM frames.

There's benefits to in-stack and on-stack. I think that on-stack, in
simplistic terms, either requires treating everything as content (e.g. DATA
frames) and running a sub-protocol on top, or it requires  H2/H3 stacks to
treat new frames as opaque blobs that they throw to an upper layer to deal
with. The problem with the latter is where those frames have some
interaction or dependency that is not normally exposed to upper layers. I'd
hope our designs can allow implementations of in-stack and on-stack.

Cheers
Lucas

[1] - https://en.m.wikipedia.org/wiki/Chuckle_Brothers