RFC 8260
Stream Schedulers and User Message Interleaving for the Stream Control Transmission Protocol
RFC 8260 ๐ Stream Schedulers and User Message Interleaving for the Stream Control Transmission Protocol
Who wrote it: R. Stewart (Netflix, Inc.), M. Tuexen (Muenster Univ. of Appl. Sciences), S. Loreto (Ericsson), and R. Seggelmann (Metafinanz Informationssysteme GmbH) ๐
Category: Standards Track ๐ ISSN: 2070-1721 Date: November 2017 ๐
Obsoletes / Updates: the title block doesn't list anything it obsoletes or updates ๐ฆ
Series: Internet Engineering Task Force (IETF), Request for Comments 8260 โจ
Abstract โจ
okay so SCTP (the Stream Control Transmission Protocol) is a message-oriented transport protocol that can handle arbitrarily large user messages ๐ง this doc adds a brand new chunk for carrying payload data ๐ the whole point is that a sender can interleave different user messages, which stops them from getting stuck behind each other (that's head-of-line blocking at the sender, bestie ๐ญ). interleaving is required for WebRTC data channels, so it's kind of a big deal ๐ฅ
whenever an SCTP sender is allowed to send user data, it can pick from multiple outgoing SCTP streams ๐ this doc defines several ways to make that pick, called stream schedulers ๐ a stream scheduler can either implement user message interleaving or not, your choice ๐ซถ
Status of This Memo ๐ธ
this is an Internet Standards Track document ๐
it's a product of the Internet Engineering Task Force (IETF) and it represents the consensus of the IETF community โจ it got public review and was approved for publication by the Internet Engineering Steering Group (IESG) ๐ if you want more on Internet Standards, check out Section 2 of RFC 7841 ๐
info about the current status of this document, any errata, and how to send feedback lives at https://www.rfc-editor.org/info/rfc8260 ๐
Copyright Notice ๐ฆ
Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved. ๐
this document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date ๐ please actually read these, because they spell out your rights and restrictions for this doc ๐ any Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as the Simplified BSD License describes ๐ฅ
Table of Contents ๐
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2. Conventions . . . . . . . . . . . . . . . . . . . . . . . 6
2. User Message Interleaving . . . . . . . . . . . . . . . . . . 6
2.1. The I-DATA Chunk Supporting User Message Interleaving . . 7
2.2. Procedures . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.1. Negotiation . . . . . . . . . . . . . . . . . . . . . 10
2.2.2. Sender-Side Considerations . . . . . . . . . . . . . 10
2.2.3. Receiver-Side Considerations . . . . . . . . . . . . 11
2.3. Interaction with Other SCTP Extensions . . . . . . . . . 11
2.3.1. SCTP Partial Reliability Extension . . . . . . . . . 11
2.3.2. SCTP Stream Reconfiguration Extension . . . . . . . . 13
3. Stream Schedulers . . . . . . . . . . . . . . . . . . . . . . 14
3.1. First-Come, First-Served Scheduler (SCTP_SS_FCFS) . . . . 14
3.2. Round-Robin Scheduler (SCTP_SS_RR) . . . . . . . . . . . 14
3.3. Round-Robin Scheduler per Packet (SCTP_SS_RR_PKT) . . . . 14
3.4. Priority-Based Scheduler (SCTP_SS_PRIO) . . . . . . . . . 14
3.5. Fair Capacity Scheduler (SCTP_SS_FC) . . . . . . . . . . 15
3.6. Weighted Fair Queueing Scheduler (SCTP_SS_WFQ) . . . . . 15
4. Socket API Considerations . . . . . . . . . . . . . . . . . . 15
4.1. Exposure of the Stream Sequence Number (SSN) . . . . . . 15
4.2. SCTP_ASSOC_CHANGE Notification . . . . . . . . . . . . . 16
4.3. Socket Options . . . . . . . . . . . . . . . . . . . . . 16
4.3.1. Enable or Disable the Support of User Message
Interleaving (SCTP_INTERLEAVING_SUPPORTED) . . . . . 16
4.3.2. Get or Set the Stream Scheduler
(SCTP_STREAM_SCHEDULER) . . . . . . . . . . . . . . . 17
4.3.3. Get or Set the Stream Scheduler Parameter
(SCTP_STREAM_SCHEDULER_VALUE) . . . . . . . . . . . . 18
4.4. Explicit EOR Marking . . . . . . . . . . . . . . . . . . 19
5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19
5.1. I-DATA Chunk . . . . . . . . . . . . . . . . . . . . . . 19
5.2. I-FORWARD-TSN Chunk . . . . . . . . . . . . . . . . . . . 20
6. Security Considerations . . . . . . . . . . . . . . . . . . . 20
7. References . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.1. Normative References . . . . . . . . . . . . . . . . . . 21
7.2. Informative References . . . . . . . . . . . . . . . . . 22
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 22
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 23
1. Introduction โจ
1.1. Overview ๐ฆ
okay so when SCTP [RFC4960] was first designed, it was mostly meant for small signaling messages ๐ฅบ later in the design, they decided to add fragmentation and reassembly for bigger messages, because someday signaling messages like the ones in Session Initiation Protocol (SIP) [RFC3261] might need SCTP too, and one message that fits in a single Maximum Transmission Unit (MTU) would be too small ๐ the catch is that this choice made sense back then, but it didn't account for other apps that would send large messages over SCTP ๐ญ sending those big messages as specified in [RFC4960] can cause a sender-side form of head-of-line blocking. for example, a message can get blocked from being sent because the sender already started sending a different message, which might be huge too ๐ this blocking happens because the Transmission Sequence Number (TSN) gets used for three different jobs:
- As an identifier for DATA chunks to provide a reliable transfer.
- As an identifier for the sequence of fragments to allow reassembly.
- As a sequence number allowing up to
2**16 - 1Stream Sequence Numbers (SSNs) outstanding.
the protocol requires all fragments of a user message to have consecutive TSNs ๐ this document lets an SCTP sender interleave different user messages, which is the fix โจ
this document also defines several stream schedulers for general SCTP associations, and each one treats the streams differently relative to each other ๐ how a stream scheduler behaves can depend on whether user message interleaving was negotiated for the association ๐ฅ
Figure 1 shows a round-robin stream scheduler using DATA chunks, with three streams (Stream Identifiers (SIDs) 0, 1, and 2) ๐ the queue for SID 0 and the queue for SID 2 each hold one user message that needs three chunks. the queue for SID 1 holds three user messages that each need only a single chunk. the figure shows how these user messages get wrapped into chunks using TSN 0 to TSN 8 ๐ง heads up: this kind of scheduler implies late TSN assignment, but it can be used with an implementation that complies with [RFC4960] and doesn't support user message interleaving ๐ late TSN assignment means the sender makes chunks from user messages and assigns the TSN as late as possible while sending them ๐ซถ
+---+---+---+
| 0/0 |-+
+---+---+---+ |
| +---+---+---+---+---+---+---+---+---+
+---+---+---+ +->|1/2|1/1|2/0|2/0|2/0|1/0|0/0|0/0|0/0|
|1/2|1/1|1/0|--->|---|---|---|---|---|---|---|---|---|
+---+---+---+ +->| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| +---+---+---+---+---+---+---+---+---+
+---+---+---+ |
| 2/0 |-+
+---+---+---+
+-------+
+-------+ |SID/SSN|
|SID/SSN| |-------|
+-------+ | TSN |
+-------+
Figure 1: Round-Robin Scheduler without User Message Interleaving
this document describes a new chunk for payload data called I-DATA ๐ฆ it keeps all the properties, flags, and fields of the current SCTP DATA chunk except the Stream Sequence Number (SSN), and it adds two new fields to its chunk header: the Fragment Sequence Number (FSN) and the Message Identifier (MID) ๐ the FSN is only used to reassemble all fragments that share the same MID and the same ordering property ๐ธ the TSN is only used for reliable transfer together with Selective Acknowledgment (SACK) chunks ๐
the MID also takes over ensuring ordered delivery, instead of the stream sequence number (the I-DATA chunk leaves out the SSN entirely) ๐
Figure 2 shows an interleaving round-robin stream scheduler using I-DATA chunks ๐ง
+---+---+---+
| 0/0 |-+
+---+---+---+ |
| +-----+-----+-----+-----+-----+-----+-----+-----+-----+
+---+---+---+ +->|2/0/2|1/2/0|0/0/2|2/0/1|1/1/0|0/0/1|2/0/0|1/0/0|0/0/0|
|1/2|1/1|1/0|--->|-----|-----|-----|-----|-----|-----|-----|-----|-----|
+---+---+---+ +->| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| +-----+-----+-----+-----+-----+-----+-----+-----+-----+
+---+---+---+ |
| 2/0 |-+
+---+---+---+
+-----------+
+-------+ |SID/MID/FSN|
|SID/MID| |-----------|
+-------+ | TSN |
+-----------+
Figure 2: Round-Robin Scheduler with User Message Interleaving
the I-DATA chunk gets negotiated during association setup, using the Supported Extensions Parameter defined in [RFC5061] ๐ฅ if I-DATA support was negotiated for an association, I-DATA chunks are used for all user messages ๐ โโ๏ธ DATA chunks are not permitted once I-DATA support has been negotiated ๐ also worth knowing: an SCTP implementation that supports I-DATA chunks needs to let associations using DATA chunks and associations using I-DATA chunks coexist ๐ซถ
in Section 2, this document specifies user message interleaving by defining the I-DATA chunk, the procedures for using it, and how it interacts with other SCTP extensions โจ Section 3 defines multiple stream schedulers, and Section 4 describes an extension to the socket API for using the mechanism in this document ๐
1.2. Conventions ๐ธ
the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐
2. User Message Interleaving โจ
okay so this section is the main event ๐ The mechanisms here let user messages on different streams get interleaved (aka mixed together on the wire). They do NOT let multiple messages, ordered or unordered, get interleaved on the same stream. no cap, that distinction matters a lot ๐ซถ
Interleaving of user messages is required for WebRTC data channels, as specified in [DATA-CHAN]. so this is literally the feature that makes data channels work, iconic ๐
An SCTP implementation that supports user message interleaving MUST support associations that use DATA chunks and associations that use I-DATA chunks existing side by side. And if an SCTP implementation supports user message interleaving and the Partial Reliability extension from [RFC3758] or the Stream Reconfiguration Extension from [RFC6525], it MUST implement the matching changes from Section 2.3. the vibe is "if you're doing all the things, you gotta do all the things" ๐
2.1. The I-DATA Chunk Supporting User Message Interleaving
Here's the new I-DATA chunk that makes interleaving possible, shown in Figure 3 ๐ฆ
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 64 | Res |I|U|B|E| Length = Variable |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TSN |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stream Identifier | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Protocol Identifier / Fragment Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ User Data /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 3: I-DATA Chunk Format
so the big difference between I-DATA and the regular DATA chunk (from [RFC4960] and [RFC7053]) is that I-DATA adds a new Message Identifier (MID) and a new Fragment Sequence Number (FSN), and it drops the Stream Sequence Number (SSN) ๐ง The PPID (which already existed for DATA chunks in [RFC4960]) and the new FSN share the same spot in the packet. The B bit tells you which one is living there right now ๐ฅ And the I-DATA chunk header is 20 bytes, which is 4 bytes bigger than the DATA chunk header from [RFC4960] and [RFC7053]. fr fr, a little extra, but worth it ๐
here's the rundown of the old fields first:
- Res: 4 bits: these bits are reserved. They MUST be set to 0 by the sender and MUST be ignored by the receiver.
- I bit: 1 bit: the (I)mmediate bit. If set, it says the receiver SHOULD NOT delay sending the corresponding SACK chunk. It's the same as the I bit for DATA chunks, per [RFC7053].
- U bit: 1 bit: the (U)nordered bit. If set, the user message is unordered. Same as the U bit for DATA chunks, per [RFC4960].
- B bit: 1 bit: the (B)eginning fragment bit. If set, this is the first fragment of a user message. Same as the B bit for DATA chunks, per [RFC4960].
- E bit: 1 bit: the (E)nding fragment bit. If set, this is the last fragment of a user message. Same as the E bit for DATA chunks, per [RFC4960].
- Length: 16 bits (unsigned integer): the length in bytes of the chunk, from the start of the Type field to the end of the User Data field, not counting padding. Similar to the Length for DATA chunks, per [RFC4960].
- TSN: 32 bits (unsigned integer): the TSN for this I-DATA chunk. Same as the TSN for DATA chunks, per [RFC4960].
- Stream Identifier: 16 bits (unsigned integer): says which stream the user data belongs to. Same as the Stream Identifier for DATA chunks, per [RFC4960].
and the new fields:
- Reserved: 16 bits (unsigned integer): reserved. It MUST be set to 0 by the sender and MUST be ignored by the receiver.
- Message Identifier (MID): 32 bits (unsigned integer): the MID is the same for every fragment of a user message. It's how you figure out which fragments (numbered by the FSN) belong to the same message ๐ซถ For ordered user messages, the SCTP receiver also uses the MID to deliver messages in the right order to the upper layer (kind of like the SSN of the DATA chunk in [RFC4960]). The sender keeps two counters per outgoing stream, one for ordered messages and one for unordered messages. They're independent, they start at 0, and they go up by 1 for each user message. Also, serial number arithmetic from [RFC1982] with SERIAL_BITS = 32 applies here. So the sender MUST NOT have more than 231 - 1 ordered messages in flight for each outgoing stream, and MUST NOT have more than 231 - 1 unordered messages in flight for each outgoing stream. A message counts as in flight if at least one of its I-DATA chunks hasn't been acknowledged in a way that can't be reneged (meaning, not acknowledged by the cumulative TSN Ack). And the MID is in "network byte order", a.k.a. Big Endian ๐
- Payload Protocol Identifier (PPID) / Fragment Sequence Number (FSN): 32 bits (unsigned integer): if the B bit is set, this field holds the PPID of the user message. In that case, SCTP doesn't touch this field, so its byte order isn't necessarily network byte order. The upper layer handles any byte order conversion for it, same as the PPID of DATA chunks. Also in that case, the FSN is implicitly 0. If the B bit is not set, this field holds the FSN. The FSN numbers all the fragments of one user message, starting at 0 and going up by 1. The last fragment of a message MUST have the E bit set. The FSN MAY wrap all the way around multiple times, which is how you get arbitrarily large user messages ๐ For the FSN, serial number arithmetic from [RFC1982] applies with SERIAL_BITS = 32. So a sender MUST NOT have more than 2**31 - 1 fragments of a single user message in flight. A fragment is in flight if it hasn't been acknowledged in a way that can't be reneged. And the FSN is in "network byte order", a.k.a. Big Endian ๐
2.2. Procedures
This part is all about how I-DATA support gets negotiated and how the sender and receiver actually use the I-DATA chunk ๐
The way the I bit is handled for I-DATA chunks matches how it's handled for DATA chunks in [RFC7053]. same energy, different chunk ๐
2.2.1. Negotiation
An SCTP endpoint says it supports user message interleaving by listing the I-DATA chunk in the Supported Extensions Parameter, as defined in [RFC5061]. Interleaving is negotiated for an association only if both endpoints have indicated I-DATA support. so it's a both-or-nothing thing ๐
If interleaving has been negotiated for an association, I-DATA chunks MUST be used for all user messages, and DATA chunks MUST NOT be used. If it hasn't been negotiated, DATA chunks MUST be used for all user messages, and I-DATA chunks MUST NOT be used. no mixing and matching ๐
An endpoint that implements the socket API from [RFC6458] MUST NOT indicate user message interleaving support unless the user has asked for it (for example, through the socket API; see Section 4.3). This rule exists because using this chunk means the application has to be able to handle interleaved messages as they come in on an association. That's not the default in the socket API (see the SCTP_FRAGMENT_INTERLEAVE socket option in Section 8.1.20 of [RFC6458]), so the user MUST tell the SCTP implementation that they can handle receiving completely interleaved messages. protect the app, bestie ๐ง
Stacks that don't implement [RFC6458] may use other ways to say they support interleaved messages, and therefore indicate user message interleaving support. The key thing is that the SCTP stack MUST know the application can handle interleaved messages before it indicates I-DATA support ๐ฆ
2.2.2. Sender-Side Considerations
The sender's side is honestly pretty simple โจ Instead of using the TSN for fragmentation, the sender uses the new FSN field to say which fragment number is being sent. The first fragment MUST have the B bit set. The last fragment MUST have the E bit set. All other fragments MUST NOT have the B or E bit set. Everything else that applies to the existing SCTP DATA chunk also applies to I-DATA chunks. That means congestion control and receiver window conditions MUST be observed, as defined in [RFC4960] ๐
the way this works is that the sender assigns the actual TSN to any chunk at the last possible moment. Each I-DATA chunk uses one TSN. That's what lets messages from other streams slip in between the pieces of a fragmented message ๐ธ Keep in mind this is the only form of interleaving supported. For example, you can't interleave multiple ordered or unordered user messages from the same stream. no cap, that's the whole rule ๐ โโ๏ธ
The sender MUST NOT process more than one user message on any given stream at any time. (Processing here means moving user data into I-DATA chunks and assigning a TSN to it.) At any time, a sender MAY process multiple user messages, as long as each one is on a different stream ๐
The sender MUST assign TSNs to I-DATA chunks in a way that lets the receiver make progress. One way to do that is to give the later fragments of a user message higher TSNs, and send the I-DATA chunks so that their TSNs are in sequence ๐
2.2.3. Receiver-Side Considerations
When an SCTP packet comes in with an I-DATA chunk whose user message needs reassembly, the receiver MUST do a few things in order. First, use the SID to identify the stream. Then, check the U bit to tell whether it's part of an ordered or unordered message. Next, find the user message identified by the MID. Finally, use the FSN for reassembly, not the TSN. The receiver MUST NOT make any assumptions about how the sender assigned TSNs. Also, a non-fragmented message is recognizable because both the E and B bits are set. A message (ordered or unordered) whose E and B bits aren't both set may be identified as fragmented ๐
If I-DATA support has been negotiated for an association, receiving a DATA chunk breaks the rules above. So the receiver of that DATA chunk MUST abort the association by sending an ABORT chunk. The ABORT chunk MAY include the 'Protocol Violation' error cause. The same goes for the opposite situation: if I-DATA support has NOT been negotiated and an I-DATA chunk shows up, that's also a violation ๐ญ๐ซถ
2.3. Interaction with Other SCTP Extensions โจ
okay so the I-DATA chunk can totally clash with other SCTP extensions ๐, which is why any future extension MUST describe if and how it interferes with I-DATA chunks ๐ซถ. For the extensions that already existed when this document was published, the tea is spilled in the subsections below ๐.
2.3.1. SCTP Partial Reliability Extension ๐ฆ
when the SCTP extension from [RFC3758] is used together with user message interleaving, the new I-FORWARD-TSN chunk MUST be used instead of the FORWARD-TSN chunk ๐. the big glow-up is that the 16-bit Stream Sequence Number (SSN) gets replaced by a 32-bit Message Identifier (MID) ๐, and the largest skipped MID can also be shared for unordered messages ๐. so the rule that ordered messages followed with FORWARD-TSN chunks now applies to ordered and unordered messages with I-FORWARD-TSN chunks. it's giving consistency ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 194 | Flags = 0x00 | Length = Variable |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| New Cumulative TSN |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stream Identifier | Reserved |U|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ /
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stream Identifier | Reserved |U|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 4: I-FORWARD-TSN Chunk Format ๐ง
here's the breakdown of the old fields ๐:
Flags: 8 bits (unsigned integer). these bits are reserved ๐. they MUST be set to 0 by the sender and MUST be ignored by the receiver. same deal as the Flags for FORWARD TSN chunks, per [RFC3758] โจ
Length: 16 bits (unsigned integer). this is the length of the chunk, just like the Length for FORWARD TSN chunks in [RFC3758] ๐
New Cumulative TSN: 32 bits (unsigned integer). this tells the data receiver the New Cumulative TSN, same as FORWARD TSN chunks in [RFC3758] ๐ธ
and here are the new fields ๐ฆ:
Stream Identifier (SID): 16 bits (unsigned integer). this holds the stream number this entry is about ๐
Reserved: 15 bits. this one is reserved too ๐. it MUST be set to 0 by the sender and MUST be ignored by the receiver.
U bit: 1 bit. this tells you whether the Message Identifier of this entry is about unordered messages (U bit set) or ordered messages (U bit not set) ๐
Message Identifier (MID): 32 bits (unsigned integer). this is the largest Message Identifier for ordered or unordered messages (picked by the U bit) that got skipped for the stream named by the Stream Identifier ๐ฅ. for ordered messages it works like FORWARD-TSN, just with the 16-bit SSN swapped for the 32-bit MID ๐
support for I-FORWARD-TSN gets negotiated during association setup through the Supported Extensions Parameter, as defined in [RFC5061] ๐ค. the partial reliability extension only gets negotiated (and can only be combined with user message interleaving) if BOTH endpoints said they support user message interleaving and the I-FORWARD-TSN chunk ๐ซถ
the rules are strict, bestie ๐จ: the FORWARD-TSN chunk MUST be used with the DATA chunk and MUST NOT be used with the I-DATA chunk. the I-FORWARD-TSN chunk MUST be used with the I-DATA chunk and MUST NOT be used with the DATA chunk.
if I-FORWARD-TSN support was negotiated for an association and a FORWARD-TSN chunk shows up anyway, that breaks the rules above ๐ญ. so the receiver of that FORWARD-TSN chunk MUST abort the association by sending an ABORT chunk ๐. the ABORT chunk MAY include the 'Protocol Violation' error cause ๐. same goes if I-FORWARD-TSN support was NOT negotiated and a FORWARD-TSN chunk gets received anyway ๐
2.3.2. SCTP Stream Reconfiguration Extension ๐
when an association resets the SSN using the SCTP extension from [RFC6525], the two counters used for the MIDs (one for ordered messages, one for unordered messages) MUST be reset to 0 โจ
also, most schedulers (especially all the ones that support user message interleaving) need late TSN assignment, so it should be noted that the implementation of [RFC6525] needs to handle this ๐ง
3. Stream Schedulers ๐
this section defines a bunch of stream schedulers ๐. they may act differently depending on whether user message interleaving got negotiated for the association ๐ฆ. an implementation MAY implement any subset of them ๐ธ. but if the implementation is used for WebRTC data channels (see [DATA-CHAN]), it MUST implement the Weighted Fair Queueing Scheduler from Section 3.6 ๐ฅ
the sender picks the stream scheduler ๐. there's no mechanism for signaling which scheduler is in use to the receiver, and the receiver can't even influence which one the sender chooses ๐
3.1. First-Come, First-Served Scheduler (SCTP_SS_FCFS) ๐
this is the simple one ๐. user messages just go out in the order the application handed them over ๐ธ. the order doesn't get changed at all. user message interleaving doesn't really change how chunks get sent, except that I-DATA chunks are used instead of DATA chunks ๐ฆ
3.2. Round-Robin Scheduler (SCTP_SS_RR) ๐
without interleaving, this scheduler is fair based on the number of user messages ๐. it cycles around the non-empty stream queues ๐. with interleaving, it's fair based on the number of I-DATA chunks instead, still cycling around non-empty stream queues โจ
3.3. Round-Robin Scheduler per Packet (SCTP_SS_RR_PKT) ๐ง
this is a round-robin scheduler that only switches streams when it starts filling a new packet ๐. each packet only bundles DATA or I-DATA chunks for the same stream ๐. the upside is that it minimizes head-of-line blocking when a packet is lost, because only a single stream gets hit ๐ซถ
3.4. Priority-Based Scheduler (SCTP_SS_PRIO) ๐
this one schedules user messages with strict priorities ๐ฅ. the priority is configurable per outgoing SCTP stream ๐ . higher-priority streams get scheduled first, and when streams share the same priority, how they're scheduled between each other is implementation dependent ๐คทโโ๏ธ. when interleaving is on, sending a big, lower-priority user message won't hold up the higher-priority ones ๐ฆ
3.5. Fair Capacity Scheduler (SCTP_SS_FC) ๐ธ
this one aims for fair capacity across streams ๐. it looks at the lengths of each stream's messages and schedules them in a specific way to keep capacity equal for all streams ๐. the details are implementation dependent. Interleaving user messages lets you realize fair capacity usage even better ๐
3.6. Weighted Fair Queueing Scheduler (SCTP_SS_WFQ) ๐
this is a Weighted Fair Queueing scheduler between the streams ๐. each outgoing SCTP stream gets its own configurable weight ๐. it looks at message lengths too, and schedules them so capacity gets used according to the weights ๐ง. if stream S1's weight is n times stream S2's weight, the scheduler should give S1 n times the capacity it gives S2 โจ. the details are implementation dependent. interleaving user messages gives you an even better realization of capacity usage based on those weights ๐ฅ
this scheduler, combined with user message interleaving, is what WebRTC data channels use (see [DATA-CHAN]) ๐ซถ
4. Socket API Considerations ๐
this section explains how the socket API from [RFC6458] gets extended so apps can use what's in this document ๐ . heads up: this section is informational only ๐
4.1. Exposure of the Stream Sequence Number (SSN) ๐ฆ
the socket API from [RFC6458] has a few structures that expose the SSN of a received user message to the app ๐. the list includes:
struct sctp_sndrcvinfo: specified in Section 5.3.2 of [RFC6458] and marked as deprecated ๐struct sctp_extrcvinfo: specified in Section 5.3.3 of [RFC6458] and marked as deprecated ๐struct sctp_rcvinfo: specified in Section 5.3.5 of [RFC6458] โจ
if user message interleaving is used, the lower-order 16 bits of the MID are used as the SSN when filling out these structures ๐ธ
4.2. SCTP_ASSOC_CHANGE Notification ๐
when an SCTP_ASSOC_CHANGE notification (specified in Section 6.1.1 of [RFC6458]) gets delivered with a sac_state of SCTP_COMM_UP or SCTP_RESTART, for an association where both peers support the I-DATA chunk, SCTP_ASSOC_SUPPORTS_INTERLEAVING should be listed in the sac_info field ๐ง
4.3. Socket Options ๐
here are the socket options, in one glorious table ๐:
+-----------------------------+-------------------------+-----+-----+
| Option Name | Data Type | Get | Set |
+-----------------------------+-------------------------+-----+-----+
| SCTP_INTERLEAVING_SUPPORTED | struct sctp_assoc_value | X | X |
| SCTP_STREAM_SCHEDULER | struct sctp_assoc_value | X | X |
| SCTP_STREAM_SCHEDULER_VALUE | struct | X | X |
| | sctp_stream_value | | |
+-----------------------------+-------------------------+-----+-----+
4.3.1. Enable or Disable the Support of User Message Interleaving (SCTP_INTERLEAVING_SUPPORTED) โจ
Okay bestie, this socket option is the on/off switch for user message interleaving negotiation ๐. You can use it to turn negotiation on or off for future associations, and for existing ones you can check whether interleaving was actually negotiated on a particular association ๐.
It uses IPPROTO_SCTP as its level and SCTP_INTERLEAVING_SUPPORTED as its name. You can use it with getsockopt() and setsockopt(), and the value is this struct from [RFC6458]:
struct sctp_assoc_value {
sctp_assoc_t assoc_id;
uint32_t assoc_value;
};
Here's the breakdown ๐ :
assoc_id: This gets ignored on one-to-one style sockets. On one-to-many style sockets, it tells you which association you're acting on. You can also use the specialSCTP_FUTURE_ASSOC. UsingSCTP_{CURRENT|ALL}_ASSOChere is an error, so don't ๐assoc_value: A non-zero value turns user message interleaving on, and a zero value turns it off.
sctp_opt_info() needs to be extended to support SCTP_INTERLEAVING_SUPPORTED.
Important bit ๐จ An app that uses user message interleaving should also set the fragment interleave level to 2 with the SCTP_FRAGMENT_INTERLEAVE socket option from Section 8.1.20 of [RFC6458]. This lets user messages from different streams get interleaved. It does not allow user messages (ordered or unordered) on the same stream to interleave, ngl ๐. If you skip this step, you can possibly end up with an application deadlock ๐. Some implementations might put restrictions on which combinations of these values you're allowed to set. Setting the interleaving level to at least 2 before you enable negotiation of user message interleaving should work on all platforms ๐. And since the default fragment interleave level isn't 2, user message interleaving is disabled by default. Plot twist, but it makes sense ๐ง
4.3.2. Get or Set the Stream Scheduler (SCTP_STREAM_SCHEDULER) ๐ฆ
You pick a stream scheduler with the SCTP_STREAM_SCHEDULER option for setsockopt(). The struct sctp_assoc_value tells it which association to change and which algorithm you want ๐.
That struct is the same one defined in [RFC6458]:
struct sctp_assoc_value {
sctp_assoc_t assoc_id;
uint32_t assoc_value;
};
assoc_id: The identifier of the association whose scheduler you want to change. You can also use the specialSCTP_{FUTURE|CURRENT|ALL}_ASSOC. This gets ignored on one-to-one style sockets.assoc_value: This picks the scheduler. Your options are:SCTP_SS_DEFAULT: The default scheduler the SCTP implementation uses. Typical values areSCTP_SS_FCFSorSCTP_SS_RR.SCTP_SS_FCFS: Use the scheduler from Section 3.1.SCTP_SS_RR: Use the scheduler from Section 3.2.SCTP_SS_RR_PKT: Use the scheduler from Section 3.3.SCTP_SS_PRIO: Use the scheduler from Section 3.4. You can assign priorities with thesctp_stream_valuestruct. The higher the assigned value, the lower the priority ๐. So the default value 0 is the highest priority, and that means default scheduling kicks in if you haven't assigned any priorities ๐.SCTP_SS_FB: Use the scheduler from Section 3.5.SCTP_SS_WFQ: Use the scheduler from Section 3.6. You can assign the weight with thesctp_stream_valuestruct.
sctp_opt_info() needs to be extended to support SCTP_STREAM_SCHEDULER.
4.3.3. Get or Set the Stream Scheduler Parameter (SCTP_STREAM_SCHEDULER_VALUE) ๐
Some schedulers need extra info set for individual streams. Here's who needs it ๐:
+-----------------+-----------------+
| Name | Per-Stream Info |
+-----------------+-----------------+
| SCTP_SS_DEFAULT | n/a |
| SCTP_SS_FCFS | no |
| SCTP_SS_RR | no |
| SCTP_SS_RR_PKT | no |
| SCTP_SS_PRIO | yes |
| SCTP_SS_FB | no |
| SCTP_SS_WFQ | yes |
+-----------------+-----------------+
You do this with the SCTP_STREAM_SCHEDULER_VALUE option and the matching struct sctp_stream_value, which looks like this ๐ง:
struct sctp_stream_value {
sctp_assoc_t assoc_id;
uint16_t stream_id;
uint16_t stream_value;
};
assoc_id: The identifier of the association whose scheduler you're changing. You can also use the specialSCTP_{FUTURE|CURRENT|ALL}_ASSOC. This gets ignored on one-to-one style sockets.stream_id: The identifier of the stream you're giving extra info to.stream_value: What this means depends on the scheduler you picked. It gets ignored when the scheduler doesn't need any extra info.
sctp_opt_info() needs to be extended to support SCTP_STREAM_SCHEDULER_VALUE.
4.4. Explicit EOR Marking ๐ซถ
Using explicit End of Record (EOR) marking on an SCTP association that supports user message interleaving lets you interleave the sending of user messages across different streams. It's giving flexibility ๐ค
5. IANA Considerations ๐ธ
Two new chunk types were assigned by IANA. Let's gooo ๐
5.1. I-DATA Chunk
IANA assigned the chunk type for this chunk from the pool of chunks with the upper two bits set to '01'. It shows up in the "Chunk Types" registry for SCTP like this:
+----------+--------------------------------------------+-----------+
| ID Value | Chunk Type | Reference |
+----------+--------------------------------------------+-----------+
| 64 | Payload Data supporting Interleaving | RFC 8260 |
| | (I-DATA) | |
+----------+--------------------------------------------+-----------+
The registration table (as defined in [RFC6096]) for the chunk flags of this chunk type starts out like this ๐ฆ:
+------------------+-----------------+-----------+
| Chunk Flag Value | Chunk Flag Name | Reference |
+------------------+-----------------+-----------+
| 0x01 | E bit | RFC 8260 |
| 0x02 | B bit | RFC 8260 |
| 0x04 | U bit | RFC 8260 |
| 0x08 | I bit | RFC 8260 |
| 0x10 | Unassigned | |
| 0x20 | Unassigned | |
| 0x40 | Unassigned | |
| 0x80 | Unassigned | |
+------------------+-----------------+-----------+
5.2. I-FORWARD-TSN Chunk
IANA assigned the chunk type for this chunk from the pool of chunks with the upper two bits set to '11'. It shows up in the "Chunk Types" registry for SCTP like this:
+----------+---------------+-----------+
| ID Value | Chunk Type | Reference |
+----------+---------------+-----------+
| 194 | I-FORWARD-TSN | RFC 8260 |
+----------+---------------+-----------+
The registration table (as defined in [RFC6096]) for the chunk flags of this chunk type starts out empty ๐ซฅ.
6. Security Considerations ๐
Okay, serious moment ๐. This document doesn't add any security considerations beyond the ones in [RFC4960] and [RFC6458]. Phew ๐ฎโ๐จ
That said, the application has to actually consent to doing the more complex reassembly that user message interleaving needs. When it does, the application has to provide a reassembly buffer for each incoming stream, and it has to protect itself from those buffers hogging too many resources ๐จ. If user message interleaving isn't used, only a single reassembly buffer needs to be provided for each association. But the application still has to protect itself from excessive resource usage there too. Don't sleep on this one, bestie ๐ซ
7. References ๐
7.1. Normative References
[RFC1982] Elz, R. and R. Bush, "Serial Number Arithmetic", RFC 1982, DOI 10.17487/RFC1982, August 1996, <https://www.rfc-editor.org/info/rfc1982>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.
[RFC3758] Stewart, R., Ramalho, M., Xie, Q., Tuexen, M., and P. Conrad, "Stream Control Transmission Protocol (SCTP) Partial Reliability Extension", RFC 3758, DOI 10.17487/RFC3758, May 2004, <https://www.rfc-editor.org/info/rfc3758>.
[RFC4960] Stewart, R., Ed., "Stream Control Transmission Protocol", RFC 4960, DOI 10.17487/RFC4960, September 2007, <https://www.rfc-editor.org/info/rfc4960>.
[RFC5061] Stewart, R., Xie, Q., Tuexen, M., Maruyama, S., and M. Kozuka, "Stream Control Transmission Protocol (SCTP) Dynamic Address Reconfiguration", RFC 5061, DOI 10.17487/RFC5061, September 2007, <https://www.rfc-editor.org/info/rfc5061>.
[RFC6096] Tuexen, M. and R. Stewart, "Stream Control Transmission Protocol (SCTP) Chunk Flags Registration", RFC 6096, DOI 10.17487/RFC6096, January 2011, <https://www.rfc-editor.org/info/rfc6096>.
[RFC6525] Stewart, R., Tuexen, M., and P. Lei, "Stream Control Transmission Protocol (SCTP) Stream Reconfiguration", RFC 6525, DOI 10.17487/RFC6525, February 2012, <https://www.rfc-editor.org/info/rfc6525>.
[RFC7053] Tuexen, M., Ruengeler, I., and R. Stewart, "SACK-IMMEDIATELY Extension for the Stream Control Transmission Protocol", RFC 7053, DOI 10.17487/RFC7053, November 2013, <https://www.rfc-editor.org/info/rfc7053>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.
7.2. Informative References
[DATA-CHAN] Jesup, R., Loreto, S., and M. Tuexen, "WebRTC Data Channels", Work in Progress, draft-ietf-rtcweb-data-channel-13, January 2015.
[RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, DOI 10.17487/RFC3261, June 2002, <https://www.rfc-editor.org/info/rfc3261>.
[RFC6458] Stewart, R., Tuexen, M., Poon, K., Lei, P., and V. Yasevich, "Sockets API Extensions for the Stream Control Transmission Protocol (SCTP)", RFC 6458, DOI 10.17487/RFC6458, December 2011, <https://www.rfc-editor.org/info/rfc6458>.
Acknowledgments โจ
bestie, the authors really want to thank Benoit Claise, Julian Cordes, Spencer Dawkins, Gorry Fairhurst, Lennart Grahl, Christer Holmberg, Mirja Kuehlewind, Marcelo Ricardo Leitner, Karen E. Egede Nielsen, Maksim Proshin, Eric Rescorla, Irene Ruengeler, Felix Weinrank, Michael Welzl, Magnus Westerlund, and Lixia Zhang ๐ซถ for their invaluable comments. these people showed up and made the spec better, and that's iconic behavior ๐
this work also got funding from the European Union's Horizon 2020 research and innovation program under grant agreement No. 644334 (NEAT) ๐. the views expressed are solely those of the authors, so if anything in here is a little too spicy, blame the authors and not the EU ๐
Authors' Addresses ๐ฆ
okay so here are the four authors and where to find them. it's giving "reach out with your questions" energy ๐ธ
Randall R. Stewart is at Netflix, Inc., in Chapin, SC 29036, United States of America ๐
Randall R. Stewart
Netflix, Inc.
Chapin, SC 29036
United States of America
Email: randall@lakerest.net
Michael Tuexen is at Muenster University of Applied Sciences, Stegerwaldstrasse 39, 48565 Steinfurt, Germany ๐
Michael Tuexen
Muenster University of Applied Sciences
Stegerwaldstrasse 39
48565 Steinfurt
Germany
Email: tuexen@fh-muenster.de
Salvatore Loreto is at Ericsson, Torshamnsgatan 21, 164 80 Stockholm, Sweden ๐ง
Salvatore Loreto
Ericsson
Torshamnsgatan 21
164 80 Stockholm
Sweden
Email: Salvatore.Loreto@ericsson.com
Robin Seggelmann is at Metafinanz Informationssysteme GmbH, Leopoldstrasse 146, 80804 Muenchen, Germany ๐
Robin Seggelmann
Metafinanz Informationssysteme GmbH
Leopoldstrasse 146
80804 Muenchen
Germany
Email: rfc@robin-seggelmann.com
๐ฆ where this page comes from
- ietf: rfc8260 2017-11
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms