example, if reliable delivery was requested for a Message handed over before calling Close, the Closed Event will signify that this Message has indeed been delivered.  If the Remote Endpoint still has data to <del> send, it cannot be received after this call. </del>  The Closed Event informs the application that the Remote Endpoint has closed the Connection.  There is no guarantee that a remote Close will indeed be signaled. <del> Abort terminates a Connection without delivering any remaining data: </del>  A ConnectionError informs the application that: 1) data could not be delivered to the peer after a timeout, or 2) the Connection has been

Should taps-interface provide a way to close a connection group? I don't see an obvious way to close an HTTP/2 or QUIC connection just using connection-level commands. You could make TAPS automatically close a connection if all user streams are closed, but that's... not great?
What's the problem with closing a connection (I presume you mean the underlying transport's one, not the one exposed by TAPS) once all user streams (i.e., grouped TAPS Connections) are closed? I think this would obviously happen. If I, as a user, want to avoid delay for connection establishment and tear-down, I'm not closing my Connection... Else, closing a group containing multiple open Connections in one go would be a matter of issuing "Close" for all of them... e.g., by checking the Connection's group number, in a loop. We could spec that as part of the API, but it doesn't seem to be extremely useful to me, as this function could very easily be written on top of the TAPS API.
This works for me, Gorry
Alternative discussed: make ConnectionGroup an explicit object (as opposed to just a []Connection), and add (at least) an AbortGroup call on it. Another option: add AbortGroup to a Connection, which aborts all connections in the group. Discussion at December interim leans toward the second: don't create a new object for only one operation.
Also, make sure to be clear that Abort() does NOT close all entangled Connections. (same thing for Close())

example, if reliable delivery was requested for a Message handed over before calling Close, the Closed Event will signify that this Message has indeed been delivered.  If the Remote Endpoint still has data to  <ins> send, it cannot be received after this call.  This action does not affect any other Connection that is entangled with this one in a Connection Group. </ins> The Closed Event informs the application that the Remote Endpoint has closed the Connection.  There is no guarantee that a remote Close will indeed be signaled.  <ins> Abort terminates a Connection without delivering any remaining data. This action does not affect any other Connection that is entangled with this one in a Connection Group. AbortGroup terminates a Connection and also terminates any other Connections that are entangled with this one in a Connection Group. For example, all of the Connections in a group might be streams of a single session for a multistreaming protocol; aborting the entire group would close the underlying session.  See also groups. </ins> A ConnectionError informs the application that: 1) data could not be delivered to the peer after a timeout, or 2) the Connection has been


possible from previous connections that are not entangled with it. Any state generated by this Connection will only be shared with entangled connections.  Cloned Connections will use saved state from <del> within the Connection Group. </del>  Note that this does not guarantee no leakage of information, as implementations may not be able to fully isolate all caches (e.g. 4.1.8. <del> A Connection Group is a set of Connections that share properties and </del>  caches.  For multiplexing transport protocols, only Connections within the same Connection Group are allowed to be multiplexed <del> together.  An application can explicitly define Connection Groups to control caching boundaries, as discussed in groups. </del>  4.2. thread. The Transport Services API can allow applications to explicitly <del> define Connection Groups that force separation of Cached State and </del>  Protocol Stacks.  For example, a web browser application might use <del> Connection Groups with separate caches for different tabs in the </del>  browser to decrease linkability. <del> The interface to specify a Connection Group can expose fine-grained tuning for which properties and cached state is allowed to be shared with other Connections.  For example, an application might want to allow sharing TCP Fast Open cookies across groups, but not TLS session state. </del> 5. RFC-EDITOR: Please remove this section before publication.

Fix terminology in -arch Add minimal connection contexts in -interface
We had not decided that yet: We agreed that the property was sufficient as portable interface for the purpose We did not yet because did nit fix the inconsistencies between Connection Groups in -architecture and -interface So what we could do (als an alternative to this PR) to - Drop the stuff this PR renamed to "Connection Context" from -arch all-together Merge the changes in -arch, but do not include the minimal Connection Context into -interface an try to squish question about the context missing in -interface in later reviews
Connection Groups used to be about state and context sharing as well as entanglement. Now it's about entanglement. We need to rename Connection Groups ("connection contexts"?) in the architecture to replace the existing "group" concept, and to retain "connection group" in the API for entanglement.
Seems like this could be 360 degrees of rotation in our thinking? (which could be OK, NEAT was written to specify both contexts and flow groups). Let's try some definitions here and see if we converge...
I think brings this back in synch again so no need to rename, possibly the last part of this section in architecture should be removed though as we do not have fine-grained control
Did we decide to explicitly introduce this new connection context?

possible from previous connections that are not entangled with it. Any state generated by this Connection will only be shared with entangled connections.  Cloned Connections will use saved state from  <ins> within the Connection Group.  This is used for separating Connection Contexts as specified in I-D.ietf-taps-arch. </ins> Note that this does not guarantee no leakage of information, as implementations may not be able to fully isolate all caches (e.g. 4.1.8.  <ins> A Connection Group is a set of Connections that shares properties and </ins> caches.  For multiplexing transport protocols, only Connections within the same Connection Group are allowed to be multiplexed  <ins> together.  While Connection Groups are managed by the transport system, an application can define Connection Contexts to control caching boundaries, as discussed in conn-context. </ins> 4.2. thread. The Transport Services API can allow applications to explicitly  <ins> define Connection Contexts that force separation of Cached State and </ins> Protocol Stacks.  For example, a web browser application might use  <ins> Connection Contexts with separate caches for different tabs in the </ins> browser to decrease linkability.  5. RFC-EDITOR: Please remove this section before publication.


should not terminate an earlier child connection attempt upon starting a secondary child. <del> If a child node fails to connect before the delay time has expired for the next child, the next child should be started immediately. </del>  Staggered racing between IP addresses for a generic Connection should follow the Happy Eyeballs algorithm described in RFC8305.  RFC8421

Section 4.2.2 says "If a child node fails to connect before..." without really defining if this means completing the handshake, or making some progress. 4.3.1 does a better job, but for readability there ought to be a reference or rewording in 4.2.2.
/to connect/ is problematic for me also, but /establish connectivity/ is less problematic, although always good to explain!

should not terminate an earlier child connection attempt upon starting a secondary child.  <ins> If a child node fails to establish connectivity (as in determining- successful-establishment) before the delay time has expired for the next child, the next child should be started immediately. </ins> Staggered racing between IP addresses for a generic Connection should follow the Happy Eyeballs algorithm described in RFC8305.  RFC8421


a clear handshake, like TCP, then the obvious choice is to declare that node "connected" when the last packet of the three-way handshake has been received.  If the only protocol being used is an <del> "unconnected" protocol, like UDP, the implementation may consider the node fully "connected" the moment it determines a route is present, before sending any packets on the network, see further unconnected- racing. </del>  For protocol stacks with multiple handshakes, the decision becomes more nuanced.  If the protocol stack involves both TLS and TCP, an While protocols that use an explicit handshake to validate a Connection to a peer can be used for racing multiple establishment <del> attempts in parallel, "unconnected" protocols such as raw UDP do not </del>  offer a way to validate the presence of a peer or the usability of a Connection without application feedback.  An implementation should consider such a protocol stack to be established as soon as the Transport Services system has selected a path on which to send data. However, if a peer is not reachable over the network using the <del> unconnected protocol, or data cannot be exchanged for any other </del>  reason, the application may want to attempt using another candidate Protocol Stack.  The implementation should maintain the list of other candidate Protocol Stacks that were eligible to use. 4.6.2. <del> Unconnected protocols such as UDP and UDP-lite generally do not </del>  provide the same mechanisms that connected protocols do to offer Connection objects.  Implementations should wait for incoming packets <del> for unconnected protocols on a listening port and should perform </del>  four-tuple matching of packets to either existing Connection objects or the creation of new Connection objects.  On platforms with <del> facilities to create a "virtual connection" for unconnected protocols implementations should use these mechanisms to minimise the handling of datagrams intended for already created Connection objects. </del>  4.6.3. Each protocol has a notion of Connectedness.  Possible values for Connectedness are: <del> Unconnected.  Unconnected protocols do not establish explicit state between endpoints, and do not perform a handshake during Connection establishment. </del>  Connected.  Connected protocols establish state between endpoints, and perform a handshake during Connection establishment.  The 10.3. <del> Connectedness: Unconnected </del>  Data Unit: Datagram 10.4. <del> Connectedness: Unconnected </del>  Data Unit: Datagram 10.5. <del> Connectedness: Unconnected </del>  Data Unit: Datagram

Just check "connected" - in case we mean connection-oriented; and that usage of "connect" is sane, we need care.
UDP is best described as connectionless, not unconnected: it has no notion of a connection, where "unconnected" might imply a particular usage pattern for a protocol that also supports connections.
YES! UDP is "connectionless"; confusing APIs do support a "connected mode". Please remove unconnected.

a clear handshake, like TCP, then the obvious choice is to declare that node "connected" when the last packet of the three-way handshake has been received.  If the only protocol being used is an  <ins> connectionless protocol, like UDP, the implementation may consider the node fully "connected" the moment it determines a route is present, before sending any packets on the network, see further connectionless-racing. </ins> For protocol stacks with multiple handshakes, the decision becomes more nuanced.  If the protocol stack involves both TLS and TCP, an While protocols that use an explicit handshake to validate a Connection to a peer can be used for racing multiple establishment  <ins> attempts in parallel, connectionless protocols such as raw UDP do not </ins> offer a way to validate the presence of a peer or the usability of a Connection without application feedback.  An implementation should consider such a protocol stack to be established as soon as the Transport Services system has selected a path on which to send data. However, if a peer is not reachable over the network using the  <ins> connectionless protocol, or data cannot be exchanged for any other </ins> reason, the application may want to attempt using another candidate Protocol Stack.  The implementation should maintain the list of other candidate Protocol Stacks that were eligible to use. 4.6.2.  <ins> Connectionless protocols such as UDP and UDP-lite generally do not </ins> provide the same mechanisms that connected protocols do to offer Connection objects.  Implementations should wait for incoming packets  <ins> for connectionless protocols on a listening port and should perform </ins> four-tuple matching of packets to either existing Connection objects or the creation of new Connection objects.  On platforms with  <ins> facilities to create a "virtual connection" for connectionless protocols implementations should use these mechanisms to minimise the handling of datagrams intended for already created Connection objects. </ins> 4.6.3. Each protocol has a notion of Connectedness.  Possible values for Connectedness are:  <ins> Connectionless.  Connectionless protocols do not establish explicit state between endpoints, and do not perform a handshake during Connection establishment. </ins> Connected.  Connected protocols establish state between endpoints, and perform a handshake during Connection establishment.  The 10.3.  <ins> Connectedness: Connectionless </ins> Data Unit: Datagram 10.4.  <ins> Connectedness: Connectionless </ins> Data Unit: Datagram 10.5.  <ins> Connectedness: Connectionless </ins> Data Unit: Datagram


closed the Connection.  There is no guarantee that a remote Close will indeed be signaled. <del> Abort terminates a Connection without delivering any remaining data. This action does not affect any other Connection that is entangled with this one in a Connection Group. </del>  <del> AbortGroup terminates a Connection and also terminates any other </del>  Connections that are entangled with this one in a Connection Group. For example, all of the Connections in a group might be streams of a <del> single session for a multistreaming protocol; aborting the entire group would close the underlying session.  See also groups. </del>  A ConnectionError informs the application that: 1) data could not be delivered to the peer after a timeout, or 2) the Connection has been

Inspired by the discussion in , I don't think we adequately addressed . Abstracting away from current designs, in a connection group there are four possible termination actions: Clean close a connection Abort a connection Clean close a connection group Abort a connection group TAPS has all but the third. QUIC has three of these; SCTP has two (three with RFC 6525); HTTP/2, IIUC, in principle has all four, though I believe RFC 7540 doesn't envision HTTP/2 ever initiating TCP RST. There is an added complication that in some protocols these are half-closes or half-aborts. I think we're trying to be too cute by not offering all four of these. Let's just have all of them (which means adding CloseGroup) and then figure out how the protocol mappings respond to actions they don't actually support. For example Non-streaming protocols simply apply the close or abort to each of their connections. When QUIC gets CloseGroup, it sends clean close on all connections and then sends group abort. (Note that apps with mandatory streams [like HTTP3] can't use this functionality) When SCTP with 7525 gets ConnectionAbort, it does ConnectionClose instead When SCTP without 7525 gets ConnectionClose or ConnectionAbort, it's a NOP. When HTTP/2 gets AbortGroup, it sends GOAWAY followed by a CloseGroup.
I'm copy+pasting my answer from the PR here. I'm not against "let's just have all of them and then figure out how...", but I'm also not sure if we need to get so complex? Perhaps.... I'll just leave this text here for consideration: [paste from ] About stream abort: not quite, I think. Using a "stream abort" would mean that the TCP-like half-closed behavior wouldn't work - you couldn't send a stream reset and then expect to receive something on a stream. However, that isn't possible anyway, because SCTP streams are only unidirectional. And, there's only a guarantee of a notification by a returning "stream reset" because we define it in this PR. I agree that this is bigger and should be separate from this PR... but what's your plan? Do we really have a big problem here? In the end, it's a matter of having the right semantics at the API level. This began with just picking the strictest possible semantics: no half-closed connections, calling "close" means that what the app already gave to the transport system for transmission before the call will still be sent, but the app cannot expect to send or receive anything after this call. This way, SCTP (which doesn't allow half-closed associations) is covered, and the behavior is "correct" for TCP as well. These semantics also work for SCTP streams with stream reset as above. So... altogether, I thought we'll be safe if we just go strict. Now, quite recently, the wording was changed a bit, because of the need to support TCP half-closed connections (which is implemented via the "Final" Message Property). I felt a bit uneasy about this change, but in the end I couldn't see how things would go wrong with the wording that we now have in the API draft. My high-level view is that we still have this rather strict thing, and then there is the option to use "Final", with no guarantee of it working (because we don't know if we get a protocol that supports half-closed connections). But there may be a devil in the details on how we worded it... definitely worth another careful look.
I agree that our treatment of half and full closes is alright, although it doesn't give us away to do a QUIC STOP_SENDING frame, for example. I think the close and abort semantics are quite clear to the application developer, but it's not sufficient to have them at the Connection level because it can lead to many messages where one would suffice. I don't like that we've merged the SCTP SHUTDOWN and ABORT chunks, for instance.
Re: the need for more primitives to do, e.g., STOP_SENDING, I agree. Re: close and abort not being sufficient: I agree. Re: merging SCTP SHUTDOWN and ABORT chunks: that sounds like a mistake that we shouldn't have made. Which text in which draft gives you this impression? I checked the implementation draft, it talks about CLOSE.SCTP (for Close) and ABORT.SCTP (for Abort), and all of this is preceded by "Below, terms in capitals with a dot (e.g., "CONNECT.SCTP") refer to the primitives with the same name in section 4 of [RFC8303]." In RFC 8303, these terms refer back to the Shutdown and Abort primitives of RFC 4960 (the current spec at the time RFC 8303 was written), where it is explained that these work using the SHUTDOWN and ABORT chunks... so where is the mistake?

Which text in which draft gives you this impression? IIUC, for multistreaming protocols Connection.Close() and Connection.Abort() apply to streams while Connection.AbortGroup() applies to the protocol connection/association. We lack a Connection.CloseGroup() and therefore there is no way to trigger a SHUTDOWN chunk. In practice, since stream closing capabilities are slim in SCTP, we can repurpose Close() and Abort(), but this seems conceptually messier.
discussed at 2021-02-26 interim: we are indeed being a little too cute by pretending an application isn't going to interact with groups. Decision is to add CloseGroup().
Looks good, thanks for doing this!

closed the Connection.  There is no guarantee that a remote Close will indeed be signaled.  <ins> Abort terminates a Connection without delivering any remaining Messages.  This action does not affect any other Connection that is entangled with this one in a Connection Group. </ins>  <ins> CloseGroup gracefully terminates a Connection and any other </ins> Connections that are entangled with this one in a Connection Group. For example, all of the Connections in a group might be streams of a  <ins> single session for a multistreaming protocol; closing the entire group will close the underlying session.  See also groups.  As with Close, any Messages remaining to be processed on a Connection will be handled prior to closing. AbortGroup terminates a Connection and any other Connections that are entangled with this one in a Connection Group without delivering any remaining Messages. </ins> A ConnectionError informs the application that: 1) data could not be delivered to the peer after a timeout, or 2) the Connection has been


Connection establishment is divided into two top-level steps: Candidate Gathering, to identify the paths, protocols, and endpoints <del> to use, and Candidate Racing, in which the necessary protocol handshakes are conducted so that the transport system can select which set to use.  This document structures candidates for racing as a tree. </del>  The most simple example of this process might involve identifying the single IP address to which the implementation wishes to connect,

Oh yes, and it IS editorial ! :-D
Is "racing" really the right term? It might be a term of art that applies even in cases like this, but many of the relationships between different branches in the tree are based on preference rather than lowest latency. I don't feel strongly about this, but I don't know if this has been brought up yet, so I figured I'd mention it.
I agree that it may seem a bit misleading, but I think it's ok - it's just the word we use for it, and the term and how we use it is quite clearly defined in the Architecture draft, section 4.2.2. Just my 2c
I like "racing" - it's just a term....
Racing is defined in the architecture document; add a reference back there.
Thanks for fixing this!

Connection establishment is divided into two top-level steps: Candidate Gathering, to identify the paths, protocols, and endpoints  <ins> to use, and Candidate Racing (see Section 4.2.2 of I-D.ietf-taps- arch), in which the necessary protocol handshakes are conducted so that the transport system can select which set to use.  This document structures candidates for racing as a tree. </ins> The most simple example of this process might involve identifying the single IP address to which the implementation wishes to connect,


The application should be notified whenever a Message or partial Message has been consumed by the Protocol Stack, or has failed to <del> send.  The meaning of the Message being consumed by the stack may vary depending on the protocol.  For a basic datagram protocol like UDP, this may correspond to the time when the packet is sent into the interface driver.  For a protocol that buffers data in queues, like TCP, this may correspond to when the data has entered the send buffer. </del>  5.1.3.

I stared at this sentence for a while before I thought I'd made sense of it. PR forthcoming but I think this might need a little discussion.
lgtm

The application should be notified whenever a Message or partial Message has been consumed by the Protocol Stack, or has failed to  <ins> send.  The time at which a Message is considered to have been consumed by the Protocol Stack may vary depending on the protocol. For example, for a basic datagram protocol like UDP, this may correspond to the time when the packet is sent into the interface driver.  For a protocol that buffers data in queues, like TCP, this may correspond to when the data has entered the send buffer.  The time at which a message has failed to send is after the Protocol Stack or the Transport Services implementation itself has not successfully sent the entire Message content or partial Message content on any open candidate connection; this may depend on protocol-specific timeouts. </ins> 5.1.3.


Ordered: when this is false, this disables the requirement of in- order-delivery for protocols that support configurable ordering.  Safely Replayable: when this is true, this means that the Message can be used by mechanisms that might transfer it multiple times - messages, such as UDP, can only be used with Messages that are Safely Replayable. <del> Final: when this is true, this means that a transport connection can be closed immediately after transmission of the message. </del>  Corruption Protection Length: when this is set to any value other than "Full Coverage", it sets the minimum protection in protocols <del> that allow limiting the checksum length (e.g.  UDP-Lite). </del>  Reliable Data Transfer (Message): When true, the property specifies that the Message must be reliably transmitted.  When multiple small Messages can incur high overhead if each needs to be enqueued separately.  To avoid this, the application can indicate a batch of Send actions through the API.  When this is used, the <del> implementation should hold off on processing Messages until the batch </del>  is complete. 5.2.

Section 5.1.2: "the implementation should hold off on processing Messages until the batch is complete" assumes that there is indeed a context-switch penalty. Batch semantics are only for hints to the implementation/protocol stack, and this advice only applies when that hint allows the stack to reduce context switch penalty. Correct? (If so, this should be noted explicitly)
Actually 5.1.3. This reads odd to me, I'd expected myself more like: "When this is used, the implementation can defer the processing Messages until the batch is complete." (eliminating "off on", also from this sentence?)
Agreed, I think your text reads better NAME should it be "... defer the processing of Messages ..." though? I think it also solves the question from NAME as it is now expressed as an opportunity for the implementation.
I believe these are all editorial. First, this list needs some front matter: "protocols should implement each of the following Message Properties on send as follows" or similar. "Ordered" should state that protocols that do not support configurable ordering may ignore the property. "Final" should note that it is not mandatory to close the connection after a Final message. "Corruption Protection Length" should note that it can be ignored basically everywhere but UDP-Lite. One open question: is it an error to send a Message after a Final message, and does the protocol implementation need to handle this itself?
... "Corruption Protection Length" should note that it can be ignored basically everywhere but UDP-Lite. ... In protocols such as UDP-Lite, various tunnels would, DCCP allows, etc.
I think it should be an error to send a Message after a Final message and the implementation of the transport services system should handle it. If it is not an error, then it will fail sometimes and sometimes not depending on if the connection is closed or not, that seems less useful to me.

Ordered: when this is false, this disables the requirement of in- order-delivery for protocols that support configurable ordering. <ins> When the protocol stack does not support configurable ordering, this property may be ignored. </ins> Safely Replayable: when this is true, this means that the Message can be used by mechanisms that might transfer it multiple times - messages, such as UDP, can only be used with Messages that are Safely Replayable.  <ins> Final: when this is true, this means that the sender will not send any further messages.  The Connection need not be closed (in case the Protocol Stack supports half-close operation, like TCP).  Any messages sent after a Final message will result in a SendError. </ins> Corruption Protection Length: when this is set to any value other than "Full Coverage", it sets the minimum protection in protocols  <ins> that allow limiting the checksum length (e.g.  UDP-Lite).  If the protocol stack does not support checksum length limitation, this property may be ignored. </ins> Reliable Data Transfer (Message): When true, the property specifies that the Message must be reliably transmitted.  When multiple small Messages can incur high overhead if each needs to be enqueued separately.  To avoid this, the application can indicate a batch of Send actions through the API.  When this is used, the  <ins> implementation can defer the processing of Messages until the batch </ins> is complete. 5.2.


API mappings for SCTP are as follows: <del> Connection objects represent a flow of SCTP messages between a client and a server, which may be an SCTP association or a stream in a SCTP association.  How to map Connection objects to streams is described in NEAT-flow-mapping; in the following, a similar method is described.  To map Connection objects to SCTP streams without head-of-line blocking on the sender side, both the sending and receiving SCTP implementation must support message interleaving RFC8260.  Both SCTP implementations must also support stream reconfiguration.  Finally, both communicating endpoints must be aware of this intended multiplexing; NEAT-flow-mapping describes a way for a Transport System to negotiate the stream mapping capability using SCTP's adaptation layer indication, such that this functionality would only take effect if both ends sides are aware of it.  The first flow, for which the SCTP association has been created, will always use stream id zero.  All additional flows are assigned to unused stream ids in growing order.  To avoid a conflict when both endpoints map new flows simultaneously, the peer which initiated the transport connection will use even stream numbers whereas the remote side will map its flows to odd stream numbers.  Both sides maintain a status map of the assigned stream numbers.  Generally, new streams must consume the lowest available (even or odd, depending on the side) stream number; this rule is relevant when lower numbers become available because Connection objects associated to the streams are closed. </del>  If this is the only Connection object that is assigned to the SCTP <del> association or stream mapping has not been negotiated, CONNECT.SCTP is called.  Else, unless the Selection Property "activeReadBeforeSend" is Preferred or Required, a new stream is used: if there are enough streams available, "Initiate" is just a local operation that assigns a new stream number to the Connection object.  The number of streams is negotiated as a parameter of the prior CONNECT.SCTP call, and it represents a trade-off between local resource usage and the number of Connection objects that can be mapped without requiring a reconfiguration signal.  When running out of streams, ADD_STREAM.SCTP must be called. </del>  If this is the only Connection object that is assigned to the SCTP <del> association or stream mapping has not been negotiated, CONNECT.SCTP is called with the "user message" parameter.  Else, a new stream is used (see "Initiate" for how to handle running out of streams), and this just sends the first message on a new stream. </del>  "Initiate" or "InitiateWithSend" returns without an error, i.e. SCTP's four-way handshake has completed.  If an association with <del> the peer already exists, and stream mapping has been negotiated and enough streams are available, a Connection Object instantly becomes Ready after calling "Initiate" or "InitiateWithSend". </del>  Failure of CONNECT.SCTP. TIMEOUT.SCTP or ABORT-EVENT.SCTP. LISTEN.SCTP.  If an association with the peer already exists and <del> stream mapping has been negotiated, "Listen" just expects to receive a new message on a new stream id (chosen in accordance with the stream number assignment procedure described above). </del>  LISTEN.SCTP returns without an error (a result of successful CONNECT.SCTP from the peer), or, in case of stream mapping, the is also invoked). Calling "Clone" on an SCTP association creates a new Connection <del> object and assigns it a new stream number in accordance with the stream number assignment procedure described above.  If there are not enough streams available, ADD_STREAM.SCTP must be called. </del>  When this value is changed, or a Message with Message Property "Priority" is sent, and there are multiple Connection objects "InitiateWithSend" or "Listen" calls.  At the peer, the event RESET_STREAM-EVENT.SCTP will fire, which the peer must answer by issuing RESET_STREAM.SCTP too.  The resulting local RESET_STREAM- <del> EVENT.SCTP informs the transport system that the stream number can now be re-used by the next "Initiate", "InitiateWithSend" or "Listen" calls, and invokes a "Closed" event towards the application. </del>  Abort: If this is the only Connection object that is assigned to the SCTP association, ABORT.SCTP is called.  Else, the Connection object

This is a manual re-application of all the changes to -impl in PR . (Other methods didn't easily work because the master has changed quite a bit during discussion of PR ; at least I found no easy way).
Sec 10.6 of taps-impl is pretty confusing: .. there's yet more. Maybe I should read NEAT-flow-mapping, or remind myself about the details of SCTP, but I think the third sentence (To map Connection Objects...) is not well-constructed. There are three conditions here: both SCTPs must: support 8260,support stream reconfiguration, ANDknow what's going on. But what do these conditions enable? Is it mapping connections to streams at all? Is it mapping them without HOL blocking (i.e., if not met, I still can map but there is HOL blocking)? Something else?
Guilty as charged! I wrote this and I can fix it. Meanwhile, I'll explain: 8260 => to reduce HOL blocking delay. stream reconfiguration => to save memory and be able to re-use stream numbers, and to realize the role of a FIN (stream reset = FIN) know what's going on => yes, but this is an application requirement ... the applications on both sides must be able to handle this. E.g., a server written over a TAPS system could just listen on all protocols, including streams, and get whatever kind of Connection (including, possibly, one that's really only a stream) - and then answer on it (I actually tested exactly this with NEATPy). This server can handle this easily. Another server could be a native TCP server, certainly not expecting SCTP, let alone Connections riding on streams - this server could not handle this. The client application, when connecting, must know what it's doing. I can make a PR to explain these matters in the text.

API mappings for SCTP are as follows:  <ins> Connection objects can be mapped to an SCTP association or a stream in an SCTP association.  Mapping Connection objects to SCTP streams is called "stream mapping" and has additional requirements as follows.  The following explanation assumes a client-server communication model. Stream mapping requires an association to already be in place between the client and the server, and it requires the server to understand that a new incoming stream should be represented as a new Connection Object by the Transport Services system.  A new SCTP stream is created by sending an SCTP message with a new stream id.  Thus, to implement stream mapping, the Transport Services system MUST provide a newly created Connection Object to the application upon the reception of such a message.  The necessary semantics to implement a Transport Services system's Close and Abort primitives are provided by the stream reconfiguration (reset) procedure described in RFC6525. This also allows to re-use a stream id after resetting ("closing") the stream.  To implement this functionality, SCTP stream reconfiguration RFC6525 MUST be supported by both the client and the server side. To avoid head-of-line blocking, stream mapping SHOULD only be implemented when both sides support message interleaving RFC8260. This allows a sender to schedule transmissions between multiple streams without risking that transmission of a large message on one stream might block transmissions on other streams for a long time. To avoid conflicts between stream ids, the following procedure is recommended: the first Connection, for which the SCTP association has been created, MUST always use stream id zero.  All additional Connections are assigned to unused stream ids in growing order.  To avoid a conflict when both endpoints map new Connections simultaneously, the peer which initiated association MUST use even stream ids whereas the remote side MUST map its Connections to odd stream ids.  Both sides maintain a status map of the assigned stream ids.  Generally, new streams SHOULD consume the lowest available (even or odd, depending on the side) stream id; this rule is relevant when lower ids become available because Connection objects associated with the streams are closed. SCTP stream mapping as described here has been implemented in a research prototype; a desription of this implementation is given in NEAT-flow-mapping. </ins> If this is the only Connection object that is assigned to the SCTP  <ins> association or stream mapping is not used, CONNECT.SCTP is called. Else, unless the Selection Property "activeReadBeforeSend" is Preferred or Required, a new stream is used: if there are enough streams available, "Initiate" is just a local operation that assigns a new stream id to the Connection object.  The number of streams is negotiated as a parameter of the prior CONNECT.SCTP call, and it represents a trade-off between local resource usage and the number of Connection objects that can be mapped without requiring a reconfiguration signal.  When running out of streams, ADD_STREAM.SCTP must be called. </ins> If this is the only Connection object that is assigned to the SCTP  <ins> association or stream mapping is not used, CONNECT.SCTP is called with the "user message" parameter.  Else, a new stream is used (see "Initiate" for how to handle running out of streams), and this just sends the first message on a new stream. </ins> "Initiate" or "InitiateWithSend" returns without an error, i.e. SCTP's four-way handshake has completed.  If an association with  <ins> the peer already exists, stream mapping is used and enough streams are available, a Connection Object instantly becomes Ready after calling "Initiate" or "InitiateWithSend". </ins> Failure of CONNECT.SCTP. TIMEOUT.SCTP or ABORT-EVENT.SCTP. LISTEN.SCTP.  If an association with the peer already exists and  <ins> stream mapping is used, "Listen" just expects to receive a new message with a new stream id (chosen in accordance with the stream id assignment procedure described above). </ins> LISTEN.SCTP returns without an error (a result of successful CONNECT.SCTP from the peer), or, in case of stream mapping, the is also invoked). Calling "Clone" on an SCTP association creates a new Connection  <ins> object and assigns it a new stream id in accordance with the stream id assignment procedure described above.  If there are not enough streams available, ADD_STREAM.SCTP must be called. </ins> When this value is changed, or a Message with Message Property "Priority" is sent, and there are multiple Connection objects "InitiateWithSend" or "Listen" calls.  At the peer, the event RESET_STREAM-EVENT.SCTP will fire, which the peer must answer by issuing RESET_STREAM.SCTP too.  The resulting local RESET_STREAM-  <ins> EVENT.SCTP informs the Transport Services system that the stream id can now be re-used by the next "Initiate", "InitiateWithSend" or "Listen" calls, and invokes a "Closed" event towards the application. </ins> Abort: If this is the only Connection object that is assigned to the SCTP association, ABORT.SCTP is called.  Else, the Connection object


Calling Clone on a Connection yields a group of Connections: the parent Connection on which Clone was called, and a resulting cloned <del> Connection.  The connections within a group are "entangled" with each other, and become part of a Connection Group.  Calling Clone on any of these Connections adds another Connection to the Connection Group, and so on.  "Entangled" Connections share all Connection Properties except "Connection Priority" (see conn-priority) .  Like all other Properties, Connection Priority is copied to the new Connection when calling Clone(), but it is not entangled: Changing Connection Priority on one Connection does not change it on the other Connections in the same Connection Group. </del>  The stack of Message Framers associated with a Connection are also copied to the cloned Connection when calling Clone.  In other words,

Clarify that the Connection returned by Clone will send a Ready Event or an InitiateError Event.
Clone() is analogous to Initiate(), so why doesn't it return ready events like initiate()?
This should be OK because Initiate doesn't generate the Ready event, etc, but the Connection does. Both Initiate and Clone return a Connection. We can try to clarify this.

Calling Clone on a Connection yields a group of Connections: the parent Connection on which Clone was called, and a resulting cloned  <ins> Connection.  The new Connection is actively openend, and it will send a Ready Event or an EstablishmentError Event.  The Connections within a group are "entangled" with each other, and become part of a Connection Group.  Calling Clone on any of these Connections adds another Connection to the Connection Group, and so on.  "Entangled" Connections share all Connection Properties except "Connection Priority" (see conn-priority) .  Like all other Properties, Connection Priority is copied to the new Connection when calling Clone(), but it is not entangled: Changing Connection Priority on one Connection does not change it on the other Connections in the same Connection Group. </ins> The stack of Message Framers associated with a Connection are also copied to the cloned Connection when calling Clone.  In other words,


enabling applications written to a single API to make use of transport protocols in terms of the features they provide; <del> Unified interface to datagram and connection-oriented transports, allowing use of a common API for connection-establishment and closing; </del>  Message-orientation, as opposed to stream-orientation, using application-assisted framing and deframing where the underlying

Suggested sentence to unambiguously explain datagram v. connection opening.
For me at least, it would be nice for the implementation draft to also initially remind readers that the Connection objects are relevant to all transports, including those that are not themselves connection-oriented.
Thought to be fixed in
Fixed in
Looks good! Thank you!

enabling applications written to a single API to make use of transport protocols in terms of the features they provide;  <ins> A unified interface to datagram and connection-oriented transports, allowing use of a common API for connection- establishment and closing; </ins> Message-orientation, as opposed to stream-orientation, using application-assisted framing and deframing where the underlying


The application expects to send/receive data at a constant rate after Connection establishment.  Delay and delay variation should be minimized at the expense of efficient use of the available <del> capacity.  This implies that the Connection might fail if the desired rate cannot be maintained across the Path.  A transport can interpret this capacity profile as preferring a circuit breaker RFC8084 to a rate-adaptive congestion controller. Transport system implementations that map the requested capacity profile onto per-connection DSCP signaling without multiplexing SHOULD assign a DSCP Assured Forwarding (AF31,AF32,AF33,AF34) RFC2597 PHB. </del>  The application expects to send/receive data at the maximum rate allowed by its congestion controller over a relatively long period

To address NiTs
I-D.ietf-tsvwg-datagram-plpmtud is now a RFC.
See PR
Resolved in PR
The current text says: Constant-Rate Streaming: The application expects to send/receive data at a constant rate after Connection establishment. Delay and delay variation should be minimized at the expense of efficient use of the available capacity. This implies that the Connection might fail if the desired rate cannot be maintained across the Path. this last sentence sounds a little like the app needs to maintain the rate, rather than the path is expected to offer the rate. Could we change the last sentence to: /This implies that the Connection might fail if the Path is unable to maintain the desired rate. /
See PR
This was fixed in PR
Editorial: This text at the end of the intro reads odd to me: ‘This specific transport stack choice is discouraged for general use, because it can reduce the portability.’ I think it should read more like: ‘This choice, which only permits using a specific transport stack is discouraged for general use, because it can reduce the portability.’ —— Editorial; Is a Connection an instance of the stack? The current text says: ‘A Connection represents a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint’ This may be better as?: ‘A Connection represents an instance if a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint’ —— ‘Editorial ‘through a Message Framer which finds message’ Should this be: ‘through a Message Framer that finds message’
See PR
Resolved in PR
This LGTM, thanks!

The application expects to send/receive data at a constant rate after Connection establishment.  Delay and delay variation should be minimized at the expense of efficient use of the available  <ins> capacity.  This implies that the Connection might fail if the Path is unable to maintain the desired rate.  A transport can interpret this capacity profile as preferring a circuit breaker RFC8084 to a rate-adaptive congestion controller.  Transport system implementations that map the requested capacity profile onto per- connection DSCP signaling without multiplexing SHOULD assign a DSCP Assured Forwarding (AF31,AF32,AF33,AF34) RFC2597 PHB. </ins> The application expects to send/receive data at the maximum rate allowed by its congestion controller over a relatively long period


Abstract This document describes an abstract application programming <del> interface, API, to the transport layer, following the Transport Services Architecture.  It supports the asynchronous, atomic transmission of messages over transport protocols and network paths dynamically selected at runtime.  It is intended to replace the traditional BSD sockets API as the common interface to the transport layer, in an environment where endpoints could select from multiple interfaces and potential transport protocols. </del>  1. This document specifies a modern abstract application programming interface (API) atop the high-level architecture for transport <del> services defined in I-D.ietf-taps-arch.  It supports the asynchronous, atomic transmission of messages over transport protocols and network paths dynamically selected at runtime.  It is intended to replace the traditional BSD sockets API as the common interface to the transport layer, in environments where an endpoint selects from multiple interfaces and potential transport protocols. As applications adopt this interface, they will benefit from a wide set of transport features that can evolve over time, and ensure that the system providing the interface can optimize its behavior based on the application requirements and network conditions, without requiring changes to the applications.  This flexibility enables faster deployment of new features and protocols.  It can also support applications by offering racing and fallback mechanisms, which otherwise need to be separately implemented in each application. </del>  It derives specific path and protocol selection properties and supported transport features from the analysis provided in RFC8095, RFC8923, and RFC8922.  The design encourages implementations underneath the interface to dynamically choose a transport protocol depending on an application's choices rather than statically binding <del> applications to a protocol at compile time.  The Transport Services system implementations should provide applications with a way to </del>  override transport selection and instantiate a specific stack, e.g., <del> to support servers wishing to listen to a specific protocol.  Such a choice to only permit using a specific transport stack is discouraged for general use, because it can reduce the portability. </del>  1.1.

While reviewing for last call, I didn't find the abstract very strong. Given I'm an authors, I thought I make another proposal, however, really just that - a proposal...

Abstract This document describes an abstract application programming  <ins> interface, API, to the transport layer that enables the selection of transport protocols and network paths dynamically at runtime.  This API enables faster deployment of new protocols and protocol features without requiring changes to the applications.  The specified API follows the Transport Services Architecture by providing asynchronous, atomic transmission of messages.  It is intended to replace the traditional BSD sockets API as the common interface to the transport layer, in an environment where endpoints could select from multiple interfaces and potential transport protocols. </ins> 1. This document specifies a modern abstract application programming interface (API) atop the high-level architecture for transport  <ins> services defined in I-D.ietf-taps-arch.  The Transport Services Architecture supports asynchronous, atomic transmission of messages over transport protocols and network paths dynamically selected at runtime, in environments where an endpoint selects from multiple interfaces and potential transport protocols. Applications that adopt this interface will benefit from a wide set of transport features that can evolve over time.  This protocol- independent API ensures that the system providing the interface can optimize its behavior based on the application requirements and network conditions, without requiring changes to the applications. This flexibility enables faster deployment of new features and protocols.  It can support applications by offering racing and fallback mechanisms, which otherwise need to be separately implemented in each application. </ins> It derives specific path and protocol selection properties and supported transport features from the analysis provided in RFC8095, RFC8923, and RFC8922.  The design encourages implementations underneath the interface to dynamically choose a transport protocol depending on an application's choices rather than statically binding  <ins> applications to a protocol at compile time.  Nevertheless, the Transport Services API also provides applications with a way to </ins> override transport selection and instantiate a specific stack, e.g.,  <ins> to support servers wishing to listen to a specific protocol. However, forcing a specific transport stack choice is discouraged for general use, because it can reduce portability. </ins> 1.1.


this property may be ignored. Safely Replayable: when this is true, this means that the Message <del> can be used by mechanisms that might transfer it multiple times - e.g., as a result of racing multiple transports or as part of TCP Fast Open.  Also, protocols that do not protect against duplicated messages, such as UDP, can only be used with Messages that are Safely Replayable. </del>  Final: when this is true, this means that the sender will not send any further messages.  The Connection need not be closed (in case

Addition to clarify what happens when a transport system replays messages -
The current text says: If true, Safely Replayable specifies that a Message is safe to send to the Remote Endpoint more than once for a single Send Action. It marks the data as safe for certain 0-RTT establishment techniques, where retransmission of the 0-RTT data may cause the remote application to receive the Message multiple times. For protocols that do not protect against duplicated messages, e.g., UDP, all messages need to be marked as "Safely Replayable". To enable protocol selection to choose such a protocol, "Safely Replayable" needs to be added to the TransportProperties passed to the Preconnection. If such a protocol was chosen, disabling "Safely Replayable" on individual messages MUST result in a SendError. — I think this could perhaps be misleading, and suggest: 1. I would like to change /UDP/directly over UDP/ .... because clearly it is possible that a transport such as QUIC also uses UDP, but provides this sort of protection above the UDP layer. 2. This is still written from the perspective of the protocol. I think it is important here to also therefore add a sentence then clarifies that the application might be able to designed to detect and ignore such duplication. ‘Protection from replay of messages could be provided by an application when a transport system replays messages’.

this property may be ignored. Safely Replayable: when this is true, this means that the Message  <ins> can be used by a transport mechanism that might transfer it multiple times - e.g., as a result of racing multiple transports or as part of TCP Fast Open.  Also, protocols that do not protect against duplicated messages, such as UDP (when used directly, without a protocol layered atop), can only be used with Messages that are Safely Replayable.  When a transport system is permitted to replay messages, replay protection could be provided by the application. </ins> Final: when this is true, this means that the sender will not send any further messages.  The Connection need not be closed (in case


7.3.2.3. A ReceiveError occurs when data is received by the underlying <del> Protocol Stack that cannot be fully retrieved or parsed, or when some other indication is received that reception has failed.  In contrast, conditions that irrevocably lead to the termination of the Connection are instead signaled using ConnectionError (see termination). The ReceiveError event passes an optional associated MessageContext. This can indicate that a Message that was being partially received previously, but had not completed, encountered an error and will not be completed. </del>  7.3.3.

Actually handling of receive error is also not fully clear to me. Section 7.3.2.3 says: "A ReceiveError occurs when data is received by the underlying Protocol Stack that cannot be fully retrieved or parsed" However, I assume that this error should rather not be called if a transport is reliable because the assumption is that the packet will be retransmitted, right? E.g. in case of QUIC if a packet cannot be decrypted would that trigger an error or not? I assume not, because the QUIC stack cannot even know if a packet contained any payload data, right?
I agree that this is not very clear - to me, the cases that you describe are cases that should not throw this error, because it's a problem of the underlying protocol and not relevant to the application (what's an application going to do with it anyway?). I can only see two relevant cases of errors: the one example that we already give: "a Message that was being partially received previously, but had not completed, encountered an error and will not be completed." - note that this does not assume a fully reliable transfer, because in this case, the underlying stack would solve it, and the fact that there are retransmissions shouldn't be relevant to the application. So this means "you got a partial message from me before, but now I can tell you that you won't get the rest". the case discussed in : a minimum checksum coverage range was required for reception, but this promise was not kept => the Transport Services system will have to be discard the incoming message. There may well be others, but it's probably good to give these two examples, not only one, to make it clearer what kinds of errors are covered by this, and to explicitly state that this is only about errors that are relevant to the application, not protocol-internal reception errors.
I think this is how I see it. These errors should be actionable by the upper layer, in contrast something that fails an auth check is not actionable by an upper layer protocol. A different other use is for logging ... to diagnose fault, where you could want to see what isn’t processed by the lower layers. This is not the use I see here. Gorry
Mich clearer, but need more refinement.

7.3.2.3. A ReceiveError occurs when data is received by the underlying  <ins> Protocol Stack that cannot be fully retrieved or parsed, and when it is useful for the application to be notified of such errors.  For example, a ReceiveError can indicate that a Message (identified via the MessageContext) that was being partially received previously, but had not completed, encountered an error and will not be completed. This can be useful for an application, which may want to use this error as a hint to remove previously received Message parts from memory.  As another example, if an incoming Message does not fulfill the Required Minimum Corruption Protection Coverage for Receiving property (see conn-recv-checksum), an application can use this error as a hint to inform the peer application to adjust the Sending Corruption Protection Length property (see msg-checksum). In contrast, internal protocol reception errors (e.g., loss causing retransmissions in TCP) are not signalled by this Event.  Conditions that irrevocably lead to the termination of the Connection are signaled using ConnectionError (see termination). </ins> 7.3.3.


100 <del> This property represents a hierarchy of priorities.  It can specify the priority of a Message, relative to other Messages sent over the same Connection. </del>  A Message with Priority 0 will yield to a Message with Priority 1, which will yield to a Message with Priority 2, and so on.  Priorities

The text reads quire off when it says a priority property represents a hierarchy of priorities: This property represents a hierarchy of priorities. Could this better be: ‘A priority property is organised within a hierarchy of priorities. ‘?
When reading "hierarchy", it's easy to think that there may be priority sub-groups within priority groups, or something of that nature. Yet, this is not the case, it's just a flat priority assignment. Hence, to me, mentioning "hierarchy" here is misleading altogether. Therefore, I think we'd be much better off removing this sentence, i.e. replacing: with
Seems to resolving the odd wording.

100  <ins> This property specifies the priority of a Message, relative to other Messages sent over the same Connection. </ins> A Message with Priority 0 will yield to a Message with Priority 1, which will yield to a Message with Priority 2, and so on.  Priorities


Preference, which is an Enumeration with five possible values: Prohibit, Avoid, Ignore, Prefer, or Require.  Each of these denotes a level of preference of a given property during protocol <del> selection.  (See selection-props.)  The Preference type is used only on Preconnections, and only for Selection Properties. </del>  3.3. Specify a Local Endpoint using a STUN server: <del> Specify a Local Endpoint using a Any-Source Multicast group to join </del>  on a named local interface: Source-Specific Multicast requires setting both a Local and Remote not be used for sending if the connection was created with the Selection Property "Direction of Communication" set to "unidirectional receive" or if a Message marked as "Final" was <del> sent over this connection.  See msg-final. </del>  Whether the connection can be used to receive data.  A connection cannot be used for reading if the connection was created with the Message (i.e., whether it has actually been transmitted, moved into a buffer on the network interface, moved into a kernel buffer, and so on) when the Sent Event occurs is implementation-specific.  The Sent <del> Event contains a reference to the Message to which it applies. </del>  Sent Events allow an application to obtain an understanding of the amount of buffering it creates.  That is, if an application calls the completion; i.e. when the Message was not sent before its Lifetime (see msg-lifetime) expired.  This is separate from SendError, as it is an expected behavior for partially reliable transports.  The <del> Expired Event contains a reference to the Message to which it applies. </del>  7.2.2.3. system and Protocol Stack to handle, some failure of the underlying Protocol Stack, or a set of Message Properties not consistent with the Connection's transport properties.  The SendError contains a <del> reference to the Message to which it applies. </del>  7.2.3. Each Message Context may contain metadata from protocols in the Protocol Stack; which metadata is available is Protocol Stack <del> dependent.  These are exposed though additional read-only Message </del>  Properties that can be queried from the MessageContext object (see msg-ctx) passed by the receive event.  The following metadata values are supported:

Also spotted some further small nits while reviewing the document, will create a pull request for those.

Preference, which is an Enumeration with five possible values: Prohibit, Avoid, Ignore, Prefer, or Require.  Each of these denotes a level of preference of a given property during protocol  <ins> selection.  (See also selection-props.)  The Preference type is used only on Preconnections, and only for Selection Properties. </ins> 3.3. Specify a Local Endpoint using a STUN server:  <ins> Specify a Local Endpoint using an Any-Source Multicast group to join </ins> on a named local interface: Source-Specific Multicast requires setting both a Local and Remote not be used for sending if the connection was created with the Selection Property "Direction of Communication" set to "unidirectional receive" or if a Message marked as "Final" was  <ins> sent over this connection.  See also msg-final. </ins> Whether the connection can be used to receive data.  A connection cannot be used for reading if the connection was created with the Message (i.e., whether it has actually been transmitted, moved into a buffer on the network interface, moved into a kernel buffer, and so on) when the Sent Event occurs is implementation-specific.  The Sent  <ins> Event contains a reference to the Message Context of the Message to which it applies. </ins> Sent Events allow an application to obtain an understanding of the amount of buffering it creates.  That is, if an application calls the completion; i.e. when the Message was not sent before its Lifetime (see msg-lifetime) expired.  This is separate from SendError, as it is an expected behavior for partially reliable transports.  The  <ins> Expired Event contains a reference to the Message Context of the Message to which it applies. </ins> 7.2.2.3. system and Protocol Stack to handle, some failure of the underlying Protocol Stack, or a set of Message Properties not consistent with the Connection's transport properties.  The SendError contains a  <ins> reference to the Message Context of the Message to which it applies. </ins> 7.2.3. Each Message Context may contain metadata from protocols in the Protocol Stack; which metadata is available is Protocol Stack  <ins> dependent.  These are exposed through additional read-only Message </ins> Properties that can be queried from the MessageContext object (see msg-ctx) passed by the receive event.  The following metadata values are supported:


Properties may be Generic, applying regardless of transport protocol, or Specific, applicable to a single implementation of a single transport protocol stack.  Generic Connection Properties are defined <del> in connection-props below.  Specific Protocol Properties are defined in a transport- and implementation-specific way, and MUST NOT be assumed to apply across different protocols.  Attempts to set Specific Protocol Properties on a protocol stack not containing that specific protocol are simply ignored, and do not raise an error; however, too much reliance by an application on Specific Protocol </del>  Properties can significantly reduce the flexibility of a transport services implementation.

Section 6 says. "Attempts to set Specific Protocol Properties on a protocol stack not containing that specific protocol are simply ignored, and do not raise an error" Should this be normative? "Attempts to set Specific Protocol Properties on a protocol stack not containing that specific protocol MUST be ignored, and MUST NOT raise an error" I note that this a random sentence where spotted that normative language could be used. I don't look for these kind of occasion systematically...
I could see a case that the first requirement to ignore, I think this actually a requirement for predictable interop? (in which case we could motivate that?) I am much less sure of the second MUST, and think an error notification is not an interop issue?
The first MUST is definitely important for code portability, and so I think this is a good suggestion. I'm also less sure of the second MUST, but I think it's good to keep: yes, errors can be ignored by an application, but they can also lead to application code like: adjust QUIC properties if error: adjust TCP properties If an application absolutely must do this and must find out what's going on, it can, it's ok for a Transport Services system to make everything readable... but throwing errors in addition is yet another hint for a programmer to start developing code like this. We should discourage such code. That's why I'd keep the MUST NOT (as a counter-example, "SHOULD NOT" would mean that there would have to be a good reason for the designer of a Transport Services system to make an exception - what would such a reason be? "This particular function of this particular protocol is so important, I think here I should really throw an error after all?" - Nah...).

Properties may be Generic, applying regardless of transport protocol, or Specific, applicable to a single implementation of a single transport protocol stack.  Generic Connection Properties are defined  <ins> in connection-props below. Protocol Specific Properties are defined in a transport- and implementation-specific way, and MUST NOT apply across different protocols.  Too much reliance by an application on Protocol Specific </ins> Properties can significantly reduce the flexibility of a transport services implementation.


Security decisions, especially pertaining to trust, are not static. Once configured, parameters may also be supplied during connection establishment.  These are best handled as client-provided callbacks. <del> Security handshake callbacks that may be invoked during connection establishment include: </del>  Trust verification callback: Invoked when a Remote Endpoint's trust must be validated before the handshake protocol can

Closes issue
We have a “ Terminology and Notation” section, but we don’t define these terms: Clone: Calling Clone on a Connection yields a group of Connections: the parent Connection on which Clone was called, and a resulting cloned Connection. Entangled connection: if we do we need this term, we should define and explain what is different. Callback: can we have a one line definition that explains the different with respect to an event that an application can also asynchronously receive.
I can take care of the first two; regarding callbacks, I think there should also be at least one sentence somewhere explaining the need (why are Events not good enough for security?). I remember that this was clearly said, and I remember understanding it :) but by now, I have forgotten, and I can't find the rationale written anywhere.
As I looked at this now, I felt that such definitions would seem a bit out of place in the "Terminology and Notation" section; rather, if we need to define it globally, the concepts of Cloning and Entanglement should be defined where we also define what our Connections are, what Transport Properties are, etc. - and this is in -arch. Thoughts?
This isn't need for entangled with the way used in PR
I'm adding the arch label so people notice :-)
The one action remaining is defining "callback" within the scope of section 4.3.
Looks like this will be addressed.

Security decisions, especially pertaining to trust, are not static. Once configured, parameters may also be supplied during connection establishment.  These are best handled as client-provided callbacks.  <ins> Callbacks block the progress of the connection establishment, which distinguishes them from other Events in the transport system.  How callbacks and events are implemented is specific to each implementation.  Security handshake callbacks that may be invoked during connection establishment include: </ins> Trust verification callback: Invoked when a Remote Endpoint's trust must be validated before the handshake protocol can


example, if an application indicates a preference for a specific path by specifying an interface, but also a preference for a protocol, a situation might occur in which the preferred protocol is not <del> available on the preferred path.  In such cases, implementations SHOULD prioritize Selection Properties that select paths over those that select protocols.  Therefore, the transport system SHOULD race the path first, ignoring the protocol preference if a specific protocol does not work on the path. </del>  Selection and Connection Properties, as well as defaults for Message Properties, can be added to a Preconnection to configure the

Section 4.2: " In such cases, implementations SHOULD prioritize Selection Properties that select paths over those that select protocols." I think I agree to this recommendation but it comes a little out of nowhere and we should probably provide some reasoning, especially as this is normative.
Proposing to change text to address the application developer: to expect that the path selection properties would be preferred over protocol selection properties. We should also explain a bit of the rationale, to explain that path properties are generally more sensitive around policy/expense.

example, if an application indicates a preference for a specific path by specifying an interface, but also a preference for a protocol, a situation might occur in which the preferred protocol is not  <ins> available on the preferred path.  In such cases, applications can expect properties that determine path selection to be prioritized over properties that determine protocol selection.  The transport system SHOULD determine the preferred path first, regardless of protocol preferences.  This ordering is chosen to provide consistency across implementations, based on the fact that it is more common for the use of a given network path to determine cost to the user (i.e., an interface type preference might be based on a user's preference to avoid being charged more for a cellular data plan). </ins> Selection and Connection Properties, as well as defaults for Message Properties, can be added to a Preconnection to configure the


Integer This property, if applicable, represents the maximum Message size <del> that can be sent without incurring network-layer fragmentation or transport layer segmentation at the sender.  It exposes the Maximum Packet Size (MPS) as described in Datagram PLPMTUD RFC8899. </del>  6.1.11.3. false <del> When set to true, this property requests the network layer at the sending endpoint to not fragment the packets generated by the transport layer.  When running over IPv4, setting this property to true will also cause the Don't Fragment bit to be set in the IP header.  When this property is set, an attempt to send a message size </del>  greater than the transport's current estimate of its maximum packet size (singularTransmissionMsgMaxLen) will result in a SendError. This only takes effect when the transport and network layer support

This attempts to clarify transport segmentation (a sparate PR will propose to clarify Frag)
Closing Set part of the Frag story

Integer This property, if applicable, represents the maximum Message size  <ins> that can be sent without incurring network-layer fragmentation at the sender.  It exposes a value to the application based on the Maximum Packet Size (MPS) as described in Datagram PLPMTUD RFC8899.  This can allow a sending stack to avoid unwanted fragmentation at the network- layer or segmentation by the transport layer. </ins> 6.1.11.3. false  <ins> When set to true, this property requests the transport layer to not provide segmentation of messages larger than the maximum size permitted by the network layer, and also to avoid network-layer source fragmentation of messages.  When running over IPv4, setting this property to true can result in a sending endpount setting the Don't Fragment bit in the IPv4 header of packets generated by the transport layer.  An attempt to send a message that results in a size </ins> greater than the transport's current estimate of its maximum packet size (singularTransmissionMsgMaxLen) will result in a SendError. This only takes effect when the transport and network layer support


false <del> This property specifies that a message should be sent and received as a single packet without network-layer fragmentation, if possible. </del>  This only takes effect when the transport uses a network layer that supports this functionality.  When it does take effect, setting this <del> property to true will cause the Don't Fragment bit to be set in the IP header, and attempts to send a message with this property set to a size greater than the transport's current estimate of its maximum packet size ("singularTransmissionMsgMaxLen") will result in a "SendError". </del>  7.1.3.10.

This attempts to set "no segmentation" as the usual case, and this as a corner case - such as would be from a transport that segments at layer 4, but does not fragment at layer 3. This latter case is what is desired to send one message using a sequence of seprate IP packets.
Closing the Frag part of the story
Closing this and merging the Frag parts
Issue: this describes network Fragmentation, but does not really help a user of the transport system know when to request this property. The current text says: This property specifies that a message should be sent and received as a single packet without network-layer fragmentation, if possible. This only takes effect when the transport uses a network layer that supports this functionality. When it does take effect, setting this property to true will cause the Don't Fragment bit to be set in the IP header, and attempts to send a message with this property set to a size greater than the transport's current estimate of its maximum packet size ("singularTransmissionMsgMaxLen") will result in a "SendError". I was guilty of writing one version of this, which I now think has become wrong. I think this should read: This property specifies that a message should be sent and received as without network-layer fragmentation. When running over IPv4, setting this property to true will also cause the Don't Fragment bit to be set in the IP header. It also requests to not perform network-layer source fragmentation. An attempt to send a message with this property set and a size greater than the transport's current estimate of its maximum packet size ("singularTransmissionMsgMaxLen") will result in a "SendError". This function is needed when PMTUD OR PLPMTUD is implemented above the transport system. It might also be used to avoid blackholing when using a path that does not forward fragmented packets.
Linked to
I assume that this is about the Message Property with name "noFragmentation", in section 7.1.3.9: "No Network-Layer Fragmentation". Your proposed update makes three types of changes that I see: 1) it removes "as a single packet" in "should be sent and received as a single packet without network-layer fragmentation". Why? But anyway, I'd be ok with removing it, I don't think this matters. 2) it adds this sentence: "It also requests to not perform network-layer source fragmentation." I think this is good. 3) it removes qualifiers like "This only takes effect when the transport uses a network layer that supports this functionality.", "if possible", and "When it does take effect". Why? What happens, then, when this is requested, but the Transport Services system runs over TCP? I believe that you may have mistaken this for being a Selection Property. I understand that you're concerned with PMTUD and PLPMTUD being able to operate; I suggest that you take a look at the selection properties in section 4.2 to see if you're ok with what they offer, or if something needs to be extended there.
Let's keep "as a single packet" - it adds context. OK. I want us to think on this point. I'm OK with keeping or removing: "This only takes effect when the transport uses a network layer that supports this functionality.", "if possible", because indeed this needs the cooperation of a stack that allows this. .... In mentioning PMTUD, and avoiding blackholes, I wanted examples of how this might be a useful thing for the application to want to use. I'd be even happier to also suggest another reason why this might be needed. ... A few more comments and I'll make a PR;-) Gorry
We agree about 1 and 2. Do we agree about 3? It sounds like we do. But what is it you're asking, or suggesting to change? Confused about 3) :-) Regarding "I'd be even happier to also suggest another reason why this might be needed": I don't understand what's on your mind, but if you can think of useful text, I'd say just propose it in a PR, to be in the right place, and we can discuss it more clearly.
I see, I'll make a PR.
I made two PRs one on seg; one on frag . This deviates a little to the above, but I think it is clean - I'd love review. UDP would allow no Seg; No Frag; - both are the same, UDP does not segment. UDP-O would allow either; No frag (allowing transport seg); or no Seg. QUIC, TCP would always do no frag; -- does no Seg is not possible? SCTP would do no Frag (note it would still send frags, but avoid their usage).

false  <ins> This property specifies that a message should be sent and received without network-layer fragmentation, if possible.  It can be used to avoid network layer fragmentation when transport segmentation is prefered. </ins> This only takes effect when the transport uses a network layer that supports this functionality.  When it does take effect, setting this  <ins> property to true will cause the sender to avoid network-layer source frgementation.  When using IPv4, this will result in the Don't Fragment bit being set in the IP header. Attempts to send a message with this property that result in a size greater than the transport's current estimate of its maximum packet size ("singularTransmissionMsgMaxLen") can result in transport segmentation when permitted, or in a "SendError". Note: noSegmentation should be used when it is desired to only send a message within a single network packet. </ins> 7.1.3.10.


An application primarily interacts with this API through two Objects: Preconnections and Connections.  A Preconnection represents a set of properties and constraints on the selection and configuration of <del> paths and protocols to establish a Connection with a Endpoint.  A </del>  Connection represents an instance of a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint (i.e., depending on the kind of transport, connections can be bi-

The use of “remote” on its own offends me: “Some types of remote might …” could we make this “Remote Endpoint” to ease my reading? or whatever else is intended? Similarly can we change “locals” and “remote” here to something that is defined: “This can expose some or all of the candidate locals to the remote”
Remote Endpoint

An application primarily interacts with this API through two Objects: Preconnections and Connections.  A Preconnection represents a set of properties and constraints on the selection and configuration of  <ins> paths and protocols to establish a Connection with an Endpoint.  A </ins> Connection represents an instance of a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint (i.e., depending on the kind of transport, connections can be bi-


This property specifies the minimum number of bytes in a received message that need to be covered by a checksum.  A special value of 0 means that a received packet does not need to have a non-zero <del> checksum field.  A receiving Endpoint will not forward messages to the application that have less coverage.  The application is </del>  responsible for handling any corruption within the non-protected part of the message RFC8085.

I was so confused, if people like this PR I think I might be less confused in future.
Thought to
PR for issue:
Why is the name not rather something like perMsgChecksumFullSend?
Happy with a change if making this more consistent.
There are some related changes in
NAME : Did the merged PR 839 happen to address this? - If not please make a PR.
NAME PR 839 updated the name, but still found it confusing so made a PR.
See review.
The Required Minimum Corruption Protection Coverage for Receiving current text says: This property specifies the minimum number of bytes in a received message that need to be covered by a checksum. A special value of 0 means that no checksum is permitted. A receiving Endpoint will not forward messages to the application that have less coverage. The application is responsible for handling any corruption within the non-protected part of the message [RFC8085]. I have thought, and there seem to be various problems with how this finally emerged: in the UDP-Lite API, the. Value 0 indicates full coverage, not zero coverage. If the zero is intentionally redefined this way, what is the expected value for full coverage? The words “No checksum is permitted” can be read in multiple ways.... if this means a message can be received without checking a checksum, then this should be said. Finally, can we specify the receiver outcome when the API requires x bytes of coverage, but the message header protects fewer bytes, is the message discarded, as per UDP-Lite? Section 7.1.3.6. Sending Corruption Protection Length, is the zero case interpreted differently to UDP-LIte? Note: I THINK setting the to zero presently forces IPv4, (since UDP for IPv6 requires a checksum except for an upper-layer that explicitly performs this function).
I have updated your comment to use numbers so I can answer it a little easier here. It's defined as a special value (see: "Type: Integer, with special value Full Coverage"). This answers 4) too: in UDP-Lite, also on sending, "0" indicates full coverage, whereas here it means the opposite "that no checksum is required". [side note, it says "non-negative" for sending, in 7.1.3.6, but it should say so for receiving, in 6.1.1, as well]. I agree. I think this would be good to specify, yes, and I agree that it should be discarded. Clearly, since this is called "required minimum corruption protection length", it is a promise that must be kept. see above I'm lost (yes I'm aware that IPv6 has no checksum, but still). Are you talking about 0 as I write here ("no checksum required"), or 0 as in UDP-Lite (requiring full checksum coverage) ?
Ping NAME
Thanks - great catch about s/perMsgChecksumLenSend/perMsgChecksumSend (and -Recv) in particular, these must have been historical remnants. I added one comment related to English, take a look to see if you agree.

This property specifies the minimum number of bytes in a received message that need to be covered by a checksum.  A special value of 0 means that a received packet does not need to have a non-zero  <ins> checksum field.  A receiving endpoint will not forward messages that have less coverage to the application.  The application is </ins> responsible for handling any corruption within the non-protected part of the message RFC8085.


Listen: Enables a listener to accept incoming Connections.  The Listener will then create Connection objects as incoming connections are accepted (events).  Listeners by default register <del> with multiple paths, protocols, and local endpoints, unless </del>  constrained by Selection Properties and/or the specified Local Endpoint(s).  Connections can be accepted on any of the available paths or endpoints.

NiT
Part of Issue
Merged
The use of “remote” on its own offends me: “Some types of remote might …” could we make this “Remote Endpoint” to ease my reading? or whatever else is intended? Similarly can we change “locals” and “remote” here to something that is defined: “This can expose some or all of the candidate locals to the remote”
Remote Endpoint

Listen: Enables a listener to accept incoming Connections.  The Listener will then create Connection objects as incoming connections are accepted (events).  Listeners by default register  <ins> with multiple paths, protocols, and Local Endpoints, unless </ins> constrained by Selection Properties and/or the specified Local Endpoint(s).  Connections can be accepted on any of the available paths or endpoints.


The process of connection establishment completes when one leaf node of the tree has successfully completed negotiation with the Remote <del> Endpoint , or else all nodes of the tree have failed to connect.  The </del>  first leaf node to complete its connection is then used by the application to send and receive data.

Trying to address use of “remote” and "local"
The use of “remote” on its own offends me: “Some types of remote might …” could we make this “Remote Endpoint” to ease my reading? or whatever else is intended? Similarly can we change “locals” and “remote” here to something that is defined: “This can expose some or all of the candidate locals to the remote”
Remote Endpoint

The process of connection establishment completes when one leaf node of the tree has successfully completed negotiation with the Remote  <ins> Endpoint, or else all nodes of the tree have failed to connect.  The </ins> first leaf node to complete its connection is then used by the application to send and receive data.


4.2.7. <del> perMsgChecksumSend </del>  Preference 4.2.8. <del> perMsgChecksumRecv </del>  Preference

Why is the name not rather something like perMsgChecksumFullSend?
Happy with a change if making this more consistent.
There are some related changes in
NAME : Did the merged PR 839 happen to address this? - If not please make a PR.
NAME PR 839 updated the name, but still found it confusing so made a PR.
See review.
I do not mind what the name is called as long as it is clear. I think the proposal looks good.

4.2.7.  <ins> FullChecksumSend </ins> Preference 4.2.8.  <ins> FullChecksumRecv </ins> Preference


in the TAPS Architecture I-D.ietf-taps-arch. An application primarily interacts with this API through two Objects: <del> Preconnections and Connections.  A Preconnection represents a set of properties and constraints on the selection and configuration of paths and protocols to establish a Connection with an Endpoint.  A Connection represents an instance of a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint (i.e., depending on the kind of transport, connections can be bi- directional or unidirectional).  Connections can be created from Preconnections in three ways: by initiating the Preconnection (i.e., actively opening, as in a client), through listening on the Preconnection (i.e., passively opening, as in a server), or rendezvousing on the Preconnection (i.e.  peer to peer establishment). </del>  Once a Connection is established, data can be sent and received on it in the form of Messages.  The interface supports the preservation of

Tries to clarify that a Connection is a logical connection, and doesn't necessarily require a connection oriented underlying transport protocol. Cross-reference to the descriptions of Preconnection and the connection establishment procedures.
Interface, Section 2, "A unified interface to datagram and connection-oriented transports, allowing use of a common API for connection-establishment and closing". Should this be "…to datagram and stream-oriented transports"? At what point do we explain that and are also used for connectionless protocols? This change would finesse the question here, leaving it for Section 3, or we can restructure the draft to clarify earlier.
Yes to (1): Datagram protocols can be connection-oriented or not; however the point here seems to be either: /interface to datagram and stream-oriented transports/ or /interface to both connection-less and connection-oriented transports/ ... I'd favour the first, it's clear enough and doesn't use terms that we later re-use. Also to (2): I think we could insert a specific sentence after: " A Connection represents an instance of a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint (i.e., depending on the kind of transport, connections can be bi-directional or unidirectional). " That explicitly says something like: "This connections are presently consistently to the application, irrespective of whether the underlying transport is connection-less and connection-oriented."
Looks good. Can we also change to something like this in section 1: /A unified interface to datagram and connection-oriented transport protocols, allowing use of a common API for connection-establishment and closing;/

in the TAPS Architecture I-D.ietf-taps-arch. An application primarily interacts with this API through two Objects:  <ins> Preconnections and Connections.  A Preconnection object (pre- establishment) represents a set of properties and constraints on the selection and configuration of paths and protocols to establish a Connection with an Endpoint.  A Connection object represents an instance of a transport Protocol Stack on which data can be sent to and/or received from a Remote Endpoint (i.e., a logical connection that, depending on the kind of transport, can be bi-directional or unidirectional, and that can use a stream protocol or a datagram protocol).  Connections can be created from Preconnections in three ways: by initiating the Preconnection (i.e., actively opening, as in a client; initiate), through listening on the Preconnection (i.e., passively opening, as in a server listen), or rendezvousing on the Preconnection (i.e.  peer to peer establishment; rendezvous). </ins> Once a Connection is established, data can be sent and received on it in the form of Messages.  The interface supports the preservation of


A request by an application for Protocol Properties that include requirements or prohibitions that cannot be satisfied by any of the available protocols.  For example, if an application requires <del> "Configure Reliability per Message", but no such protocol is available on the host running the transport system this should result in an error, e.g., when SCTP is not supported by the operating system. </del>  A request by an application for Protocol Properties that are in conflict with each other, i.e., the required and prohibited

Nit: Section 3.1: No such protocol…
I’ll argue this “but no such protocol is available on the host running the transport system” is asking for a feature, so I think the text ought to read: “but no such feature is available in any protocol the host running the transport system”
"but no protocol available on the host offers such a feature"
This was fixed in the already merged PR.

A request by an application for Protocol Properties that include requirements or prohibitions that cannot be satisfied by any of the available protocols.  For example, if an application requires  <ins> "Configure Reliability per Message", but no such feature is available in any protocol the host running the transport system on the host running the transport system this should result in an error, e.g., when SCTP is not supported by the operating system. </ins> A request by an application for Protocol Properties that are in conflict with each other, i.e., the required and prohibited