RE: Split error codes in two

"Lubashev, Igor" <ilubashe@akamai.com> Wed, 13 September 2017 14:40 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 75A941321C7 for <quic@ietfa.amsl.com>; Wed, 13 Sep 2017 07:40:35 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.018
X-Spam-Level:
X-Spam-Status: No, score=-2.018 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, LOTS_OF_MONEY=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01, 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 GGbHpd9iCe3r for <quic@ietfa.amsl.com>; Wed, 13 Sep 2017 07:40:31 -0700 (PDT)
Received: from mx0b-00190b01.pphosted.com (mx0b-00190b01.pphosted.com [67.231.157.127]) (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 27B25124239 for <quic@ietf.org>; Wed, 13 Sep 2017 07:40:31 -0700 (PDT)
Received: from pps.filterd (m0122330.ppops.net [127.0.0.1]) by m0122330.ppops.net-00190b01. (8.16.0.21/8.16.0.21) with SMTP id v8DEWlfG020786; Wed, 13 Sep 2017 15:40:20 +0100
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akamai.com; h=from : to : subject : date : message-id : references : in-reply-to : content-type : mime-version; s=jan2016.eng; bh=6aaRSP8r1or5DV2XO8GhG4AhLKAXBRwUFLh7A8HkNWY=; b=OpL+aksIErz5mCVX404UzzZfmysp1YJ0+/zPn9AERsV+rGR7HlA1ZYLz+S1QAHPuKnES FJSfyeVAYxnaGvztFxW/YtF0yqjAFxvIrAXoc4Jl0puTmPLlkCwawGT2N7Jb7vpO3Ttd +ooKJLcnkHgGpDUsnmbqgAOktLs3oZoSZU6dtE5CR6AwtzHeMNu84EpzKC1SLqh+8sff rMTqTDGnBB/8Bz/Uq3fKNfUYqPe+TzBmbf/pK+08Fx1QVAwRmbCCFNT4ma8Razkw6U+f /ZYXagP92Um6Qidr4ovGgkWxjpXRXo72dD/rMwDXtQr9PcSxCPm7fUbPtXKNvL2x6ccA NA==
Received: from prod-mail-ppoint1 (prod-mail-ppoint1.akamai.com [184.51.33.18]) by mx0b-00190b01.pphosted.com with ESMTP id 2cx7rfrat9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 13 Sep 2017 15:40:20 +0100
Received: from pps.filterd (prod-mail-ppoint1.akamai.com [127.0.0.1]) by prod-mail-ppoint1.akamai.com (8.16.0.21/8.16.0.21) with SMTP id v8DEUeR9016170; Wed, 13 Sep 2017 10:40:19 -0400
Received: from email.msg.corp.akamai.com ([172.27.25.33]) by prod-mail-ppoint1.akamai.com with ESMTP id 2cwwqk8333-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Wed, 13 Sep 2017 10:40:19 -0400
Received: from USTX2EX-DAG1MB5.msg.corp.akamai.com (172.27.27.105) by ustx2ex-dag1mb6.msg.corp.akamai.com (172.27.27.107) with Microsoft SMTP Server (TLS) id 15.0.1263.5; Wed, 13 Sep 2017 07:40:17 -0700
Received: from USTX2EX-DAG1MB5.msg.corp.akamai.com ([172.27.27.105]) by ustx2ex-dag1mb5.msg.corp.akamai.com ([172.27.27.105]) with mapi id 15.00.1263.000; Wed, 13 Sep 2017 09:40:17 -0500
From: "Lubashev, Igor" <ilubashe@akamai.com>
To: "Lubashev, Igor" <ilubashe@akamai.com>, "quic@ietf.org" <quic@ietf.org>, "huitema@huitema.net" <huitema@huitema.net>
Subject: RE: Split error codes in two
Thread-Topic: Split error codes in two
Thread-Index: AQHTJTn9U7CZmvfU3U+AKlwSnR9wwKKmV3WAgAASqICAAAONAIAA0yCAgAAOnACAAAMMAIAAAK4AgACXxwCAAJELAIABpR2AgABJmoCAAAS/AIAANHEAgAFsKYCABkENAP//wQ6QgACQnID//7TCB4AAkG+w
Date: Wed, 13 Sep 2017 14:40:16 +0000
Message-ID: <7627246bc06b402c9352238d8a3c0c4a@ustx2ex-dag1mb5.msg.corp.akamai.com>
References: <CABkgnnWwGAyHzkST9o9ueVmBw3_TpJun=dv2X+HL2snXSZJgew@mail.gmail.com> <CACdeXiLS7W8cJbnT=orHkcd9reH=8QqhOzxWnUEpWZmfcdvd2g@mail.gmail.com> <CAGD1bZa-h0ZVh7kUYQtG3r93eH6TqRXnQ6YXAcscCrCQHk8LeA@mail.gmail.com> <CABkgnnXMFUP_c+2r6YeJouJXanHd8tFcqDKgU=C9UF0stPcXOw@mail.gmail.com> <CAGD1bZZZG9L0_d7Tmo8vfdAx+=LU+yi97N42vKFGo82K16Zycw@mail.gmail.com> <05505C10-8737-4C58-BC91-E401D2659AF0@in-panik.de> <MWHPR21MB0141F305CCE2B686F09549F887970@MWHPR21MB0141.namprd21.prod.outlook.com> <CAGD1bZY5xo5Krn=U3SBVUCPU4x2UAOcv2AnvzaRac9qJGM9KBg@mail.gmail.com> <DM5PR15MB14497BB2F1971C5965882875B6940@DM5PR15MB1449.namprd15.prod.outlook.com> <CAGD1bZbnpCxjdaEV_m_5XWEjtjmdxYTGh2VBoS8AgZdhxfsDhw@mail.gmail.com> <CABkgnnWRy17vuFRGhpvLBCKte3WeCdGa1M1feOBygQv+-AB2+A@mail.gmail.com> <CAGD1bZZL-4HzArTQfWrC+CbHYsyB6Wdx4cbz7+0X7YOiuc-+Qg@mail.gmail.com> <BN6PR21MB01302C7E8A43AF9DB7A63335876E0@BN6PR21MB0130.namprd21.prod.outlook.com> <bca00829d58049fb8a644f3787011fca@ustx2ex-dag1mb5.msg.corp.akamai.com>, <d63880bf-7eaa-158b-a3f8-04142f288853@huitema.net> <5fdf8fb2f4ad4b2eb2285a227c1e5b8d@ustx2ex-dag1mb5.msg.corp.akamai.com>
In-Reply-To: <5fdf8fb2f4ad4b2eb2285a227c1e5b8d@ustx2ex-dag1mb5.msg.corp.akamai.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.32.249]
Content-Type: multipart/alternative; boundary="_000_7627246bc06b402c9352238d8a3c0c4austx2exdag1mb5msgcorpak_"
MIME-Version: 1.0
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-09-13_04:, , signatures=0
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1709130228
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-09-13_04:, , 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 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1709130228
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic/9-zsOOF3x-OASPTwRrKxRo1P_eQ>
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: Wed, 13 Sep 2017 14:40:35 -0000

Thinking about this a bit more, it seems that the key difference between "tcp socket" and "two pipe pairs" models is independence of the send and receive directions.

In "two pipe pairs", send and receive directions are completely independent (they are just two unidirectional streams with some syntactic sugar that allows them to be opened and closed together, if needed).  To be faithful to this model, we'd need to support each direction getting closed independently by either endpoint.

For "tcp socket", the two directions are not independent, and streams in both directions are reset if some data sent in either direction cannot be delivered (including when the receiver decided it does not want that data).  To be faithful to this model, we'd need transport to send RST_STREAM in response to RST_STREAM automatically, not because it needs to reset the other direction (the other direction is already semantically reset) but just for flow control accounting.  And there is also no STOP_SENDING, as this is just asking for a complete reset.

I am not yet seeing what "middle ground" can be here, while maintaining a coherent model/philosophy behind the choices.

From: Lubashev, Igor [mailto:ilubashe@akamai.com]
Sent: Wednesday, September 13, 2017 1:27 AM
To: quic@ietf.org; huitema@huitema.net
Subject: RE: Split error codes in two

This can be accomplished in either "tcp socket" or "pipe pairs" model, given a sufficiently large buffer and an ability of the API to poll on "EOS received" before consuming all buffered bytes (not normally a part of traditional APIs).

-----Original Message-----
From: Christian Huitema [huitema@huitema.net]
Received: Wednesday, 13 Sep 2017, 12:57AM
To: quic@ietf.org<mailto:quic@ietf.org> [quic@ietf.org]
Subject: Re: Split error codes in two

There is another abstraction -- streams as messages. Application pushes a message that is the entire content of the stream, and receives a message once the entire stream has been received. That's the model used by DNS over QUIC.

On 9/12/2017 9:23 PM, Lubashev, Igor wrote:
This is a very good idea to decide what we want to model streams on.  Starting with well-known, simple abstractions seems like the best path to adoption.

There are two such abstractions that come to mind:


  1.  "TCP Stream sockets".  These only support signaling "orderly" closing of the write direction.  Closing of the read direction can only be done via close(), but that may leave the write direction in an undefined state (writing will complete, unless there was unread data in the read buffer or any data is received after close - see RFC 1122 4.2.2.13 $3).

I think the current spec allows for QUIC API to emulate TCP stream socket abstraction.  Current spec  also adds signaling "abort" closing of the write direction (RST_STREAM does not require an immediate RST_STREAM in the opposite direction), although there was some talk of removing this feature.


  1.  "A POSIX pipe pair", as Mike is proposing (one pair in each direction).  Connected pipes are very clean ('symmetric') abstractions, and they communicate close events (you close the 'write' pipe, 'read' pipe get EOS; you close the 'read' pipe, 'write' pipe gets an exception).



With read-direction close signaling, however, it is important to not to cause often-unnecessary STOP_SENDING frames sent for every common-case stream.close(). I think that could be done via one of the following ways:
a.       Unidirectional streams. Send STOP_SENDING on close() by the receiver (if the steam is open).
b.       API convention: "only send STOP_SENDING on stream.inputStream().close()". On stream.close(), only send STOP_SENDING if there is unread data or new data comes in later.
c.       Actually signal that read direction is closed in stream.close() by defining STREAM-with-FIN frame as "close both write and read directions" (common case).  Have separate frame types for WRITE_CLOSE, WRITE_ABORT (aka RST_STREAM), and READ_ABORT (aka STOP_SENDING).


From: Mike Bishop [mailto:Michael.Bishop@microsoft.com]
Sent: Tuesday, September 12, 2017 8:04 PM
To: Jana Iyengar <jri@google.com><mailto:jri@google.com>; Martin Thomson <martin.thomson@gmail.com><mailto:martin.thomson@gmail.com>
Cc: Philipp S. Tiesel <phils@in-panik.de><mailto:phils@in-panik.de>; Subodh Iyengar <subodh@fb.com><mailto:subodh@fb.com>; Nick Harper <nharper@google.com><mailto:nharper@google.com>; QUIC WG <quic@ietf.org><mailto:quic@ietf.org>; Victor Vasiliev <vasilvv@google.com><mailto:vasilvv@google.com>
Subject: RE: Split error codes in two

Jana and I were discussing this today, and part of the difference comes down to how you conceive of the API a QUIC implementation will expose.  My mental model has been that a stream/stream-pair consists of an InputStream and an OutputStream; you can read on one, you can write on the other.  For the write stream, you can write your data to completion and close the stream, or you can decide to abort writing.  The wire expressions of these are FIN and RST_STREAM, respectively.  For the read stream, you can read the incoming data to the end or you can abort reading and discard the remainder of the stream; the wire expression of this would be flow control updates and STOP_SENDING, respectively.  On the other side, receipt of a RST_STREAM surfaces as a read error and receipt of a STOP_SENDING surfaces as a write error.  (Jana commented that in this mental model it might be clearer to call the frames WRITE_ABORT and READ_ABORT.)

If we take Martin's proposition that streams only close by application action, there would never be a write error surfaced to the application unless the underlying transport went away entirely.  Instead, it's the responsibility of the application protocol to communicate (on another stream, in this case) that you should abort writing, even if you've already written to completion, and then to do so.  That implies that the application needs the ability to return to streams on which it's done writing, in case it's later asked to go back and reset them.

Much of our discussions around unidirectional streams, stream state transitions, etc. including the question of whether STOP_SENDING belongs at the transport layer, stem from the fact that we all have different implicit mental models of the functional surface QUIC exposes.  Perhaps we should take a step back and agree on that first, as I believe Christian has suggested in the past?

From: Jana Iyengar [mailto:jri@google.com]
Sent: Friday, September 8, 2017 5:34 PM
To: Martin Thomson <martin.thomson@gmail.com<mailto:martin.thomson@gmail.com>>
Cc: Subodh Iyengar <subodh@fb.com<mailto:subodh@fb.com>>; Mike Bishop <Michael.Bishop@microsoft.com<mailto:Michael.Bishop@microsoft.com>>; Philipp S. Tiesel <phils@in-panik.de<mailto:phils@in-panik.de>>; QUIC WG <quic@ietf.org<mailto:quic@ietf.org>>; Nick Harper <nharper@google.com<mailto:nharper@google.com>>; Victor Vasiliev <vasilvv@google.com<mailto:vasilvv@google.com>>
Subject: Re: Split error codes in two

On Thu, Sep 7, 2017 at 7:50 PM, Martin Thomson <martin.thomson@gmail.com<mailto:martin.thomson@gmail.com>> wrote:
On Fri, Sep 8, 2017 at 9:42 AM, Jana Iyengar <jri@google.com<mailto:jri@google.com>> wrote:
> I don't think it makes sense to design an app protocol that doesn't send a
> RST in response to a RST.

I've been told not to invoke this particular demon, but you just
invoked the Unidirectional streams problem.  I think that we get there
because of this meme that says that data in the one direction is
somehow necessarily bound to data in the other direction.  That's an
entirely constructed notion.  A useful construct at times, certainly,
but that's not the point here.

I think that's the most common use of a RST -- to close both directions.

So I disagree.  There are many protocols in which you send messages
(== streams) in one direction but not another.  One of the ways you
get into a unidirectional state in the current draft is to end one
side.  A FIN is only one way to do that, a unidirectional RST can be
faster and even superior in other ways.  The HTTP use case clearly
illustrates that.

FIN is the primary way in which half-close is achieved, which is what you're talking about. The HTTP use case is a complete one-off -- STOP_SENDING is an odd enough use case that I'm always left wondering who actually uses it.

Also, as Igor observes, we don't require a reciprocal RST_STREAM in
the current draft.

Yes, we don't. Recall that the RST_STREAM was, prior to the change that doesn't require reciprocity, a bidirectional signal, which was simplified to a unidirectional one, with the general expectation that apps would close the other side when they receive this signal from QUIC. It's surely going to be true of HTTP. It's possible for an app to receive a RST and then keep sending, but that is a use case I haven't seen in practice.




--

Christian Huitema