Re: Implicitly opened streams and exposing stream IDs

Marten Seemann <martenseemann@gmail.com> Tue, 03 April 2018 08:41 UTC

Return-Path: <martenseemann@gmail.com>
X-Original-To: quic@ietfa.amsl.com
Delivered-To: quic@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 6F3FB12DA6A for <quic@ietfa.amsl.com>; Tue, 3 Apr 2018 01:41:08 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.698
X-Spam-Level:
X-Spam-Status: No, score=-2.698 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EgnPzyjXCqjc for <quic@ietfa.amsl.com>; Tue, 3 Apr 2018 01:41:05 -0700 (PDT)
Received: from mail-io0-x22e.google.com (mail-io0-x22e.google.com [IPv6:2607:f8b0:4001:c06::22e]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 23444126DFB for <quic@ietf.org>; Tue, 3 Apr 2018 01:41:05 -0700 (PDT)
Received: by mail-io0-x22e.google.com with SMTP id x77so14766123ioi.2 for <quic@ietf.org>; Tue, 03 Apr 2018 01:41:05 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=NZQPJcpwASLOSkGC+gXr0OVpsPJZ9fXanOPq6zzUgGU=; b=q+MGx6N2wQeGsg8YxlgT0Luv0Ia0dc9au4lSu4FsUH4JEOnE5r+LfGgZv/w1SGu5F4 p3HS++KBZTqfMqKnoM+tXuD7BIInO6YxDnvzBIMFLfEYUV556ZPrQh0/Lz3Oo/Q7mkEa nglXl5oM7hmqUVPRJ/2WSA+osYveWZE0NWCJuYo9QEzauyeMuqHSrctZdtf6t4FVRMdD Cg/CmVdnrDRRdUeUbVvpA9K4jgJQTm8+Cq05VlwPfGd8ruJFc5VEDz6guHNhHYXHiBsh aCS30tmuHk3n0GjNa94bqj8o9NLAaQLwBPXbrQ4LL1QJss7fNC+Pnbt9CRaEiAP+0wbr vbaA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=NZQPJcpwASLOSkGC+gXr0OVpsPJZ9fXanOPq6zzUgGU=; b=OzjcprjKzMiFQGGidseH5fpskUt6weC9SKOEpjiQHuzrpe19raCmHr5fmWQdA9spQz ns75mKLwtKTdTRF0PZ7ETXcqQAgSUFYDe7XAP6yHgpA5blRtY7EPuNoAOHNCEhdqvCsO 63q1K2qhGof0XyUfx7f+5VJxc1axR4svD62VnoedycbpJUbMMpLnEd12IfBfrvR0zMjP Qzqk4Mxry82SeGUl4vFCICJL40NYGcmDv0BcbvAU97VsjRfHTDPmOSTCbPMBAuasEsGW XbiC/UjBC/MpEXfMa/Js81EU2DqxVIJnqT74jXKcM7Hc+2CMWBSLfN25U7b6lVYSNCcS BPOQ==
X-Gm-Message-State: AElRT7GIdOfxZYXtO+9DNtVsaf3EttS3hqHoYumabC4wRe0JCHKWppYE djHjUYNIkDyrHKMdA0pX/KTwg9KswGFzGIjvXU0=
X-Google-Smtp-Source: AIpwx49zVLARE4QW0cte8BXXkozLKfNjU4Mvx4JzDEpSpnsEU7PX3ufKqNG/kDT/jHJAtWnm3hQT3BBYoHxG/O2CQf0=
X-Received: by 10.107.28.15 with SMTP id c15mr11803221ioc.247.1522744863878; Tue, 03 Apr 2018 01:41:03 -0700 (PDT)
MIME-Version: 1.0
References: <CAOYVs2qp3L-dTdFfBNDQT0Q=nCu+6Ew3gmF=0GMS2vVw1JfWCg@mail.gmail.com> <7CF7F94CB496BF4FAB1676F375F9666A3BB0D858@bgb01xud1012> <CAOYVs2qb+FmrC1GssCNrWvce0d=c_o4kii361vahoraNEZO=Zg@mail.gmail.com> <CABkgnnWBZ0nRxoJB9XdqQ8JF6etAnCEpjT6c=2ZD76XcghismQ@mail.gmail.com>
In-Reply-To: <CABkgnnWBZ0nRxoJB9XdqQ8JF6etAnCEpjT6c=2ZD76XcghismQ@mail.gmail.com>
From: Marten Seemann <martenseemann@gmail.com>
Date: Tue, 03 Apr 2018 08:40:53 +0000
Message-ID: <CAOYVs2pKOX741JSK3wSzrWKYXUZs2xoObuSSfX21swHZG4MV1A@mail.gmail.com>
Subject: Re: Implicitly opened streams and exposing stream IDs
To: Martin Thomson <martin.thomson@gmail.com>
Cc: Lucas Pardue <Lucas.Pardue@bbc.co.uk>, QUIC WG <quic@ietf.org>
Content-Type: multipart/alternative; boundary="001a11409812b1f2ac0568edaa2b"
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic/RNCKbcsTdbNBv2ZnT68c5pl6NDI>
X-BeenThere: quic@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: Main mailing list of the IETF QUIC working group <quic.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic>, <mailto:quic-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic/>
List-Post: <mailto:quic@ietf.org>
List-Help: <mailto:quic-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic>, <mailto:quic-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 03 Apr 2018 08:41:08 -0000

Hi Martin,

I don't think delayed stream usage is a problem here. To be precise, what I
mean is not opening the stream (as in actually sending a frame on this
stream), but creation of the stream. So all I want is to REQUIRE here is
that peers *create* streams in order.

There's an important difference in how the receiving peer is allowed to
act. Assume for example the receiver wants to grant a higher flow control
limit than it advertised during the handshake:

   - If streams MUST be created in order, the receiver can send a
   MAX_STREAM_DATA for streams N and N+4 as soon as it receives a frame for
   N+4.
   - If streams only SHOULD be created in order, sending a MAX_STREAM_DATA
   for stream N (after receiving a frame for N+4) will cause a connection
   error, if the sender decided to skip stream N.

I'm not saying that this is an important use case, but this example shows
that implementations *only* have the two options for handling out of order
streams described in my last email *if* we require in order stream creation.

I'd therefore suggest to change the text in the spec to something like
this: "Endpoints MUST create the send side of streams for each type in
order".

Best,
Marten

On Tue, Apr 3, 2018 at 2:28 PM Martin Thomson <martin.thomson@gmail.com>
wrote:

> Requiring in-order opening is harder than it sounds.  Say you have a
> multithreaded application that is initiating requests.  The usual
> process is something like:
>
> s = connection.OpenStream()
> s.Write(request.Headers.Encode())
>
> That is, there is time between acquisition of the stream and its use.
> Do that with enough concurrency and you end up having to add late
> binding of stream identifiers to streams, which complicates the design
> of the stack considerably.  It also complicates usage because now
> there is a period where s.Id() returns an undefined result.
>
> Alternatively, you could track the highest stream ID on which data has
> been sent and send an empty, offset 0 STREAM frame rather than create
> a gap.
>
> Or, you could decide that a MUST here is unenforceable (even more so
> than the flow control limits one) and just wantonly ignore that
> requirement if this race condition happens.  While it is in theory
> possible to catch someone in a violation, it requires some interesting
> conditions (like zero packet loss).
>
> BTW, I also wish to make it possible to avoid relying on specific
> stream IDs for special functions.  I hadn't considered opening order
> as a way to do that though and had assumed that we'd use an in-stream
> header for that.  I don't think that makes the complexity worse, or at
> least no worse than having to deal with different frame types for
> different functions.
>
>
> On Tue, Apr 3, 2018 at 5:10 PM, Marten Seemann <martenseemann@gmail.com>
> wrote:
> > Hello,
> >
> > Sure, the application could deal with it by starting every stream with
> some
> > kind of header, to signal what kind of stream type this is. I'm not sure
> if
> > I like this solution, since it creates additional complexity, and it is
> only
> > necessary because we removed a useful feature from the spec.
> > What did we actually gain from removing implicit stream opening from the
> > protocol? As far as I can see, we were able to relax the requirement
> > "endpoints MUST open the send side of streams for each type in order" to
> > "endpoints SHOULD open the send side of streams for each type in order".
> > This might seem nice from a conceptual viewpoint, but honestly, I don't
> > really see why anyone would actually want to do this. I think the main
> > argument against the MUST was that it's not enforceable anyway, but this
> > applies to a lot of other MUSTs in the spec as well (e.g. that flow
> control
> > limits can't be decreased).
> >
> > The fix for this is straightforward: We should REQUIRE a peer to open
> > streams in order. How the receiver handles out of order streams then is
> an
> > implementation and API decision. I see two ways that an implementation
> could
> > reasonably deal with this:
> >
> > Return streams in the order they are received, e.g. return N+4 before N,
> if
> > packets are reordered.
> > Return streams ordered by stream ID, i.e. return first N and then N+4 if
> a
> > frame for N+4 is received.
> >
> > This way, we wouldn't need to reintroduce implicitly opened streams, but
> > leave this up to implementations. I should have named this thread
> > differently, if only I had realized this earlier ;)
> >
> > Regards,
> > Marten
> >
> > On Mon, Apr 2, 2018 at 7:05 PM Lucas Pardue <Lucas.Pardue@bbc.co.uk>
> wrote:
> >>
> >> Hi Marten,
> >>
> >> Would Stream headers fix this problem? I.e. anything that requires
> special
> >> behaviour other than "bulk data" has some bytes of of magic at the
> start of
> >> the stream.
> >>
> >> Regards
> >> Lucas
> >> ________________________________________
> >> From: QUIC [quic-bounces@ietf.org] on behalf of Marten Seemann
> >> [martenseemann@gmail.com]
> >> Sent: 02 April 2018 12:43
> >> To: QUIC WG
> >> Subject: Implicitly opened streams and exposing stream IDs
> >>
> >> Recently, the implicit opening of streams (i.e. that when a receiver
> >> receives a frame for stream N+4, it can assume that stream N was already
> >> opened, but the packet might have been reordered) was removed from the
> >> draft. I think this change has some consequences that we haven't
> discussed
> >> so far.
> >>
> >> For the purpose of writing some pseudocode, I'm assuming a QUIC API that
> >> provides an AcceptStream() method, but the conclusions will be the same
> for
> >> a callback-based API.
> >>
> >>   *   If QUIC has implicit stream opening, AcceptStream() would return
> the
> >> streams in order (and if a frame opening stream N+4 is received before
> >> stream n is opened, AcceptStream() will first return stream N and then
> >> stream N+4).
> >>   *   Without implicit stream opening, AcceptStream() just returns
> >> whatever stream is received first. Streams might be returned in
> arbitrary
> >> order, if the peer doesn't open streams consecutively or if packets are
> >> reordered.
> >>
> >> Now imagine an application protocol where the first unidirectional
> stream
> >> opened by the client is a control stream, and all higher unidirectional
> >> streams are data streams. The application on the server side needs to
> find
> >> out which stream is the control stream, because it needs to be handled
> >> separately.
> >>
> >> With implicit stream opening, the server code would be:
> >>
> >>     control_stream = AcceptStream() // is guaranteed to open the first
> >> stream
> >>     // handle the control stream
> >>      while true:
> >>          stream = AcceptStream()
> >>          // handle the data stream
> >>
> >> and without implicit stream opening:
> >>
> >>     while true:
> >>         stream = AcceptStream()
> >>         if stream.ID() == kControlStreamID:
> >>             // handle the control stream
> >>         else:
> >>             // handle the data stream
> >>
> >> In this case, after accepting a stream, we first have to check the
> stream
> >> ID, since there's no guarantee if the control stream will actually be
> >> received first.
> >>
> >> For this stream mapping, it seems like the removal of implicitly opened
> >> streams implies that QUIC has to expose stream IDs to the application
> layer.
> >> I'm not sure if this was intended when making the change, especially
> since
> >> we're considering to change HQ such that it doesn't rely on QUIC stream
> IDs
> >> any more.
> >> We only manage to avoid the problem described here in our HTTP mapping,
> >> because the HTTP control streams are unidirectional and the request
> streams
> >> are bidirectional, and can therefore be told apart by their
> directionality.
> >> However, as a general transport protocol, other applications built on
> top of
> >> QUIC will have to find some way to deal with it.
> >>
> >>
> >> -----------------------------
> >> http://www.bbc.co.uk
> >> This e-mail (and any attachments) is confidential and
> >> may contain personal views which are not the views of the BBC unless
> >> specifically stated.
> >> If you have received it in
> >> error, please delete it from your system.
> >> Do not use, copy or disclose the
> >> information in any way nor act in reliance on it and notify the sender
> >> immediately.
> >> Please note that the BBC monitors e-mails
> >> sent or received.
> >> Further communication will signify your consent to
> >> this.
> >> -----------------------------
>