RE: Implicitly opened streams and exposing stream IDs

"Lubashev, Igor" <ilubashe@akamai.com> Thu, 05 April 2018 14:12 UTC

Return-Path: <ilubashe@akamai.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 C2188129C6B for <quic@ietfa.amsl.com>; Thu, 5 Apr 2018 07:12:03 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.7
X-Spam-Level:
X-Spam-Status: No, score=-2.7 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, 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=akamai.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 k9BH8LezxRDB for <quic@ietfa.amsl.com>; Thu, 5 Apr 2018 07:11:56 -0700 (PDT)
Received: from mx0a-00190b01.pphosted.com (mx0a-00190b01.pphosted.com [IPv6:2620:100:9001:583::1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 5D5B2127599 for <quic@ietf.org>; Thu, 5 Apr 2018 07:11:56 -0700 (PDT)
Received: from pps.filterd (m0122332.ppops.net [127.0.0.1]) by mx0a-00190b01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w35E7N8f000344; Thu, 5 Apr 2018 15:11:52 +0100
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akamai.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=jan2016.eng; bh=PNKELAGXd1lcFoVVTbqcKSPZQUlGYxOzOqAeIlaWQbA=; b=dtnkvygxorPkfG4HX7uM7KFvOs1y6PSZAESlc/7nBEnVvEavx2mwCfya9AETedu9DlcE HxgRewjStEvsW1UvY/PK5/cKcXDptlOvEMR/J/rRPhOl0FS0BlkMxz7VaoFyt8LfjOWU mFUngL7YEZpB4NiQW/F/Eb1/8Ojvq0sfRyV+SjQvxrpW7JIpkszrrnb/tCsYPYTZKONx 1PIisd5/WHI524nsZ8JtOuh5og/gwzyEEE/0xLYJNEhRs4zR9HhE4/fs8JRLVLwJajxN ZtdGj6IO8JHuN7+oLr//0NE0Vq57VD5gX7X//kZUXY4DuWSEQpUGBEHAd/hKFxq3Mfu2 7w==
Received: from prod-mail-ppoint2 (prod-mail-ppoint2.akamai.com [184.51.33.19]) by mx0a-00190b01.pphosted.com with ESMTP id 2h5awk1d8h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 05 Apr 2018 15:11:51 +0100
Received: from pps.filterd (prod-mail-ppoint2.akamai.com [127.0.0.1]) by prod-mail-ppoint2.akamai.com (8.16.0.21/8.16.0.21) with SMTP id w35E6cfw004807; Thu, 5 Apr 2018 10:11:49 -0400
Received: from email.msg.corp.akamai.com ([172.27.123.34]) by prod-mail-ppoint2.akamai.com with ESMTP id 2h25nvb0jq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 05 Apr 2018 10:11:49 -0400
Received: from USMA1EX-DAG1MB5.msg.corp.akamai.com (172.27.123.105) by usma1ex-dag1mb1.msg.corp.akamai.com (172.27.123.101) with Microsoft SMTP Server (TLS) id 15.0.1365.1; Thu, 5 Apr 2018 10:11:48 -0400
Received: from USMA1EX-DAG1MB5.msg.corp.akamai.com ([172.27.123.105]) by usma1ex-dag1mb5.msg.corp.akamai.com ([172.27.123.105]) with mapi id 15.00.1365.000; Thu, 5 Apr 2018 10:11:48 -0400
From: "Lubashev, Igor" <ilubashe@akamai.com>
To: Martin Thomson <martin.thomson@gmail.com>, Marten Seemann <martenseemann@gmail.com>
CC: Lucas Pardue <Lucas.Pardue@bbc.co.uk>, QUIC WG <quic@ietf.org>
Subject: RE: Implicitly opened streams and exposing stream IDs
Thread-Topic: Implicitly opened streams and exposing stream IDs
Thread-Index: AQHTynfbGUCX+ewXh0mMrL6WkO0VQ6PttMSAgAEvEICAAAT5gIAAFESAgAAL9oCAAzFIoA==
Date: Thu, 05 Apr 2018 14:11:47 +0000
Message-ID: <52f75966fb254e9abcc58ddc5f25ff53@usma1ex-dag1mb5.msg.corp.akamai.com>
References: <CAOYVs2qp3L-dTdFfBNDQT0Q=nCu+6Ew3gmF=0GMS2vVw1JfWCg@mail.gmail.com> <7CF7F94CB496BF4FAB1676F375F9666A3BB0D858@bgb01xud1012> <CAOYVs2qb+FmrC1GssCNrWvce0d=c_o4kii361vahoraNEZO=Zg@mail.gmail.com> <CABkgnnWBZ0nRxoJB9XdqQ8JF6etAnCEpjT6c=2ZD76XcghismQ@mail.gmail.com> <CAOYVs2pKOX741JSK3wSzrWKYXUZs2xoObuSSfX21swHZG4MV1A@mail.gmail.com> <CABkgnnXtz3bVjDvtf7trwyF0xXPLGG5K579ihfzxmkYo1cViFA@mail.gmail.com>
In-Reply-To: <CABkgnnXtz3bVjDvtf7trwyF0xXPLGG5K579ihfzxmkYo1cViFA@mail.gmail.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach:
X-MS-TNEF-Correlator:
x-ms-exchange-transport-fromentityheader: Hosted
x-originating-ip: [172.19.36.160]
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
MIME-Version: 1.0
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-04-05_07:, , signatures=0
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 malwarescore=0 phishscore=0 bulkscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1804050149
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-04-05_07:, , signatures=0
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1804050148
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic/qdoHaCMhU4ZgIBZUd4ON140ISWw>
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: Thu, 05 Apr 2018 14:12:04 -0000

> Creation isn't an observable action, so we need to use observable actions to drive what the spec says.

Creation is a wire-observable action, if an endpoint creates just a single stream, when MAX_STREAMS allows creation of streams n through n+m.  If a single stream is created, there will only be a single STREAM(id=x, off=0) on the wire (possibly retransmitted).  It will be very observable if x != n.

- Igor


-----Original Message-----
From: Martin Thomson [mailto:martin.thomson@gmail.com] 
Sent: Tuesday, April 03, 2018 5:24 AM
To: Marten Seemann <martenseemann@gmail.com>
Cc: Lucas Pardue <Lucas.Pardue@bbc.co.uk>; QUIC WG <quic@ietf.org>
Subject: Re: Implicitly opened streams and exposing stream IDs

Creation isn't an observable action, so we need to use observable actions to drive what the spec says.  So that would seem to be equivalent to restoring implicit open in my mind.  Which - for the record - I was a proponent of.  But you don't need to convince me :)

As you say, the observable difference is in whether sending MAX_STREAM_DATA on stream N is permitted once stream N+4 has been opened.  (And similar such things.)

I found the rather strident arguments in favour of dropping implicit open convincing, in the sense that a strict requirement for in order creation was onerous for those who want to parallelize stream consumption.  But it's entirely possible that that could be dealt with by saying that the streams are still created in order, but used out of order.  I don't know.  Those who argued for a lifting of the requirement should weigh in.

On Tue, Apr 3, 2018 at 6:40 PM, Marten Seemann <martenseemann@gmail.com> wrote:
> 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.
>> >> -----------------------------