RFC 7242

Delay-Tolerant Networking TCP Convergence-Layer Protocol

πŸ“… published June 2014, from ietf

Delay-Tolerant Networking TCP Convergence-Layer Protocol 🌸

okay bestie, this is RFC 7242 πŸ’– It's written by M. Demmer (UC Berkeley), J. Ott (Aalto University), and S. Perreault. It's an Experimental doc from the Internet Research Task Force (IRTF), with ISSN 2070-1721, dated June 2014. The title block doesn't list anything it obsoletes or updates πŸ‘€

Abstract ✨

This doc describes the protocol for the TCP-based convergence layer for Delay-Tolerant Networking (DTN). It's the product of the IRTF's DTN Research Group (DTNRG) 🫢

Status of This Memo πŸ“œ

This doc is not an Internet Standards Track spec. It's published so people can examine it, implement it experimentally, and evaluate it πŸ§ͺ

This doc defines an Experimental Protocol for the Internet community, and it's a product of the Internet Research Task Force (IRTF). The IRTF shares results of Internet-related research and development. Those results might not be ready for deployment 🚧 This RFC represents the consensus of the Delay-Tolerant Networking Research Group of the IRTF. Docs approved for publication by the IRSG are not a candidate for any level of Internet Standard, see Section 2 of RFC 5741 πŸ™…β€β™€οΈ

For the latest status, errata, and how to send feedback, check http://www.rfc-editor.org/info/rfc7242 πŸ”Ž

Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stand on the publication date. Read these carefully, because they spell out your rights and restrictions for this doc πŸ“–

Table of Contents πŸ“‘

1. Introduction ....................................................2
2. Definitions .....................................................4
   2.1. Definitions Specific to the TCPCL Protocol .................4
3. General Protocol Description ....................................5
   3.1. Bidirectional Use of TCP Connection ........................6
   3.2. Example Message Exchange ...................................6
4. Connection Establishment ........................................7
   4.1. Contact Header .............................................8
   4.2. Validation and Parameter Negotiation ......................10
5. Established Connection Operation ...............................11
   5.1. Message Type Codes ........................................11
   5.2. Bundle Data Transmission (DATA_SEGMENT) ...................12
   5.3. Bundle Acknowledgments (ACK_SEGMENT) ......................13
   5.4. Bundle Refusal (REFUSE_BUNDLE) ............................14
   5.5. Bundle Length (LENGTH) ....................................15
   5.6. KEEPALIVE Feature (KEEPALIVE) .............................16
6. Connection Termination .........................................17
   6.1. Shutdown Message (SHUTDOWN) ...............................17
   6.2. Idle Connection Shutdown ..................................18
7. Security Considerations ........................................19
8. IANA Considerations ............................................20
   8.1. Port Number ...............................................20
   8.2. Protocol Versions .........................................20
   8.3. Message Types .............................................20
   8.4. REFUSE_BUNDLE Reason Codes ................................21
   8.5. SHUTDOWN Reason Codes .....................................21
9. Acknowledgments ................................................21
10. References ....................................................21
   10.1. Normative References .....................................21
   10.2. Informative References ...................................21

1. Introduction πŸ¦‹

okay so this doc describes the TCP-based convergence-layer protocol for Delay-Tolerant Networking 🌈 DTN is an end-to-end architecture that gives you communications in and/or through highly stressed environments. We're talking intermittent connectivity, long and/or variable delays, and high bit error rates. Yikes, but iconic πŸ’€ You can find more detail on the rationale and capabilities of these networks in "Delay-Tolerant Network Architecture" [RFC4838] ✨

A big goal of the DTN architecture is to fit a wide range of networking technologies and environments 🌍 The protocol DTN uses is the Bundle Protocol (BP) [RFC5050]. It's an application-layer protocol that builds a store-and-forward overlay network πŸ“¦ As the Bundle Protocol spec explains [RFC5050], BP needs a "convergence-layer adapter" (CLA) to send and receive bundles over some "native" link, network, or Internet protocol πŸ”— This doc describes one such CLA, the one that uses the well-known Transmission Control Protocol (TCP). That convergence layer is called TCPCL πŸ’œ

Where TCPCL and BP sit in the Internet model protocol stack is shown in Figure 1. When BP uses TCP as its bearer with TCPCL as its convergence layer, both BP and TCPCL live at the application layer of the Internet model 🧚

  +-------------------------+
  |     DTN Application     | -\
  +-------------------------|   |
  |  Bundle Protocol (BP)   |   -> Application Layer
  +-------------------------+   |
  | TCP Conv. Layer (TCPCL) | -/
  +-------------------------+
  |          TCP            | ---> Transport Layer
  +-------------------------+
  |           IP            | ---> Network Layer
  +-------------------------+
  |   Link-Layer Protocol   | ---> Link Layer
  +-------------------------+
  |    Physical Medium      | ---> Physical Layer
  +-------------------------+

    Figure 1: The Locations of the Bundle Protocol and the TCP
     Convergence-Layer Protocol in the Internet Protocol Stack

This doc describes the format of the protocol data units passed between entities taking part in TCPCL communications. It does not cover:

  • The format of Bundle Protocol protocol data units, since those are defined elsewhere [RFC5050].
  • Mechanisms for locating or identifying other bundle nodes within an internet.

Heads up: this doc describes version 3 of the protocol πŸ”’ Versions 0, 1, and 2 never got specified in an Internet-Draft, an RFC, or any other public doc. They did get implemented in the DTN reference implementation [DTNIMPL] in earlier releases, so the current version number reflects those prior versions πŸ•°οΈ

This is an experimental protocol made within the IRTF's Delay-Tolerant Networking Research Group (DTNRG), and it represents the consensus of all active contributors to that group 🀝 If this protocol gets used on the Internet, IETF standard protocols for security and congestion control should be used πŸ›‘οΈ

2. Definitions πŸ’…

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this doc are to be interpreted as described in [RFC2119] πŸ”‘

The terms defined in Section 3.1 of [RFC5050] get used all over this doc, so keep them handy πŸ“š

2.1. Definitions Specific to the TCPCL Protocol 🧚

This section has definitions that are specific to how the TCPCL protocol operates, as described below πŸ’­

TCP Connection -- A TCP connection is a transport connection that uses TCP as its transport protocol πŸ”Œ

TCPCL Connection -- A TCPCL connection (as opposed to a TCP connection) is a TCPCL communication relationship between two bundle nodes. Its lifetime is tied to the lifetime of an underlying TCP connection. So a TCPCL connection starts when a bundle node initiates a TCP connection to be established for bundle communication. It ends when the TCP connection ends, either because one or both nodes actively terminate the TCP connection, or because network errors make the TCP connection fail πŸ’” For the rest of this doc, the term "connection" without the prefix "TCPCL" shall refer to a TCPCL connection 🫢

Connection parameters -- The connection parameters are a set of values that affect how TCPCL operates for a given connection. How these parameters get conveyed to the bundle node, and so to the TCPCL, is implementation dependent. But the way two bundle nodes exchange and negotiate the values for a session is described in Section 4.2 πŸ€“

Transmission -- Transmission refers to the procedures and mechanisms (described below) for conveying a bundle from one node to another 🚚

3. General Protocol Description ✨

okay so bestie, the whole point of this protocol is moving DTN bundles around over TCP πŸš€ πŸŽ€ This spec covers how bundles get wrapped up (encapsulation), how TCP gets set up and torn down, and a bunch of messages and node requirements. Here's the vibe of how it all goes down πŸ’–

First, one node starts a TCPCL connection by opening a TCP connection to the other node. Once that TCP connection is up, both sides swap an initial contact header 🫢 It sets the connection parameters and gives each node a singleton endpoint identifier. That's the bundle-layer identity of each DTN node, NOT the singleton Endpoint Identifier (EID) of any app running on the node πŸ’… Nodes use it to help with routing and forwarding, like making sure nothing goes around in circles πŸ”

Once the TCPCL connection is set up and configured like that, bundles can go either direction πŸ¦‹ Each bundle gets sent as one or more logical segments of formatted bundle data. Every logical data segment has a DATA_SEGMENT message header, then a Self-Delimiting Numeric Value (SDNV) as defined in [RFC5050] (see also [RFC6256]) holding the length of the segment, and then the byte range of the bundle data 🌸 How long each segment is? That's an implementation matter, so you pick 🧚 The first segment for a bundle must set the 'start' flag, and the last one must set the 'end' flag in its DATA_SEGMENT message header. Main character energy for the first and last segments πŸ‘‘

If multiple bundles go over one TCPCL connection, they MUST be sent consecutively. Interleaving data segments from different bundles is not allowed, so no mixing them up, bestie πŸ™…β€β™€οΈ Bundle interleaving can be done by fragmentation at the BP layer instead πŸ“

An optional feature here is that the receiving node can send acknowledgments as bundle data segments arrive (ACK_SEGMENT). The whole reason for these is so the sender can figure out how much of the bundle has landed. That way, if the connection gets interrupted, it can do reactive fragmentation and skip re-sending the part that already went through 🧠✨ It's giving efficiency, honestly 😭

When acknowledgments are enabled, the receiving node sends an ACK_SEGMENT code for every data segment it gets, followed by an SDNV holding the cumulative length of the bundle received so far πŸ’œ The sending node may send multiple DATA_SEGMENT messages without waiting for the matching ACK_SEGMENT responses. That's pipelining of messages on a channel, and it's so cute πŸŽ€ Also, there's no explicit flow control at the TCPCL layer, so keep that in mind 🌈

Another optional feature: a receiver can interrupt a bundle's transmission at any point by replying with a REFUSE_BUNDLE message. The sender then stops sending the current bundle, but only after it finishes the partially sent data segment πŸ›‘ > Note: this enables a cross-layer optimization. A receiver that already has a certain bundle can cut the transmission off as early as possible and save capacity for other bundles. Literally genius πŸ§šπŸ’…

For connections that sit idle, a KEEPALIVE message may optionally be sent at a negotiated interval πŸ’“ It's used to show the connection is still alive, which is lowkey so important 🫢

Finally, before connections close, a SHUTDOWN message gets sent on the channel πŸ‘‹ After sending SHUTDOWN, the sender can still send acknowledgments (ACK_SEGMENT or REFUSE_BUNDLE) but NO more data messages (DATA_SEGMENT) πŸ™ˆ Oh, and a SHUTDOWN can also be used to refuse a peer's connection setup ✨


3.1. Bidirectional Use of TCP Connection πŸ¦‹

There are specific messages for sending and receiving operations, on top of the connection setup and teardown ones πŸ’… TCPCL is symmetric, meaning both sides can start sending data segments on a connection. One side's bundle transfer doesn't have to finish before the other side can start sending its own data segments πŸŽ€ So the protocol supports bi-directional communication, and that's iconic πŸ‘‘

Note that when both directions are transmitting at the same time, acknowledgment segments may be interleaved with data segments 🌸

3.2. Example Message Exchange πŸ“

This figure shows the protocol exchange for a simple session. It covers connection establishment and the sending of one bundle split into three data segments (lengths L1, L2, and L3) from Node A to Node B πŸ’–

Again, the sending node may send multiple DATA_SEGMENT messages without waiting for the matching ACK_SEGMENT responses, which is pipelining on a channel 🧚 Even though this example only shows one bundle, you can also pipeline DATA_SEGMENT messages for different bundles without waiting for ACK_SEGMENT messages for each one. Just remember that interleaving data segments from different bundles is still not allowed πŸ™…β€β™€οΈ

No errors or rejections are shown in this example, so it's all good vibes only ✨

              Node A                              Node B
              ======                              ======

    +-------------------------+         +-------------------------+
    |     Contact Header      | ->   <- |     Contact Header      |
    +-------------------------+         +-------------------------+

    +-------------------------+
    |   DATA_SEGMENT (start)  | ->
    |    SDNV length [L1]     | ->
    |  Bundle Data 0..(L1-1)  | ->
    +-------------------------+
    +-------------------------+         +-------------------------+
    |     DATA_SEGMENT        | ->   <- |       ACK_SEGMENT       |
    |    SDNV length [L2]     | ->   <- |     SDNV length [L1]    |
    |Bundle Data L1..(L1+L2-1)| ->      +-------------------------+
    +-------------------------+
    +-------------------------+         +-------------------------+
    |    DATA_SEGMENT (end)   | ->   <- |       ACK_SEGMENT       |
    |     SDNV length [L3]    | ->   <- |   SDNV length [L1+L2]   |
    |Bundle Data              | ->      +-------------------------+
    |    (L1+L2)..(L1+L2+L3-1)|
    +-------------------------+
                                        +-------------------------+
                                     <- |       ACK_SEGMENT       |
                                     <- |  SDNV length [L1+L2+L3] |
                                        +-------------------------+

    +-------------------------+         +-------------------------+
    |       SHUTDOWN          | ->   <- |         SHUTDOWN        |
    +-------------------------+         +-------------------------+

Figure 2: A Simple Visual Example of the Flow of Protocol Messages on a Single TCP Session between Two Nodes (A and B) πŸ¦‹

4. Connection Establishment 🌈

Before any bundle transmissions can happen over TCPCL, a TCPCL connection has to be set up between the nodes talking to each other πŸ’Œ How and when setup gets triggered is up to the implementation 🧚 Some connections might be opened proactively and kept up for as long as the network conditions allow. Others might only get opened when a bundle is queued up for sending and the routing algorithm picks a certain next-hop node 🚦

To set up a TCPCL connection, a node first has to establish a TCP connection with the intended peer, usually using the services the operating system provides πŸ–₯️ Port number 4556 was assigned by IANA as the well-known port number for the TCP convergence layer πŸŽ€ Other port numbers MAY be used per local configuration. Figuring out a peer's port number (if it's different from the well-known TCPCL port) is up to the implementation πŸ’…

If a node can't establish a TCP connection for any reason, how it handles that failure is an implementation matter 🫠 A node MAY decide to try again. If it does, it MUST NOT overwhelm its target with repeated connection attempts πŸ™ˆ So the node MUST wait some delay before retrying the connection setup (a 1-second minimum is RECOMMENDED), and it SHOULD use a (binary) exponential backoff to grow that delay when failures keep happening πŸ“ˆ If a SHUTDOWN message specifying a reconnection delay gets received, that delay becomes the initial delay πŸ’« The default initial delay SHOULD be at least 1 second, but it SHOULD be configurable, since it depends on the application and network type 🌸

A node MAY declare failure after one or more connection attempts, and it MAY try to find an alternate route for bundle data πŸ—ΊοΈ Those decisions belong to the higher layer (the BP) πŸ‘‘

Once a TCP connection is established, each node MUST immediately send a contact header over that TCP connection 🫢 The format of the contact header is described in Section 4.1 πŸ“–

When the contact header arrives, both nodes do the validation and negotiation procedures defined in Section 4.2 ✨

After getting the contact header from the other node, either node MAY also refuse the connection by sending a SHUTDOWN message πŸ›‘ If connection setup is refused, a reason MUST be included in the SHUTDOWN message πŸ’€

4.1. Contact Header πŸ’–

okay so once the TCP connection is up, both sides swap a contact header πŸŽ€ this section is the tea on what that header looks like and what each field means ✨

the format goes like this πŸ‘‡

                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
+---------------+---------------+---------------+---------------+
|                          magic='dtn!'                         |
+---------------+---------------+---------------+---------------+
|     version   |     flags     |      keepalive_interval       |
+---------------+---------------+---------------+---------------+
|                     local EID length (SDNV)                   |
+---------------+---------------+---------------+---------------+
|                                                               |
+                      local EID (variable)                     +
|                                                               |
+---------------+---------------+---------------+---------------+

                   Figure 3: Contact Header Format

and here's what each field is doing 🧚

  • magic: a four-byte field that always holds the byte sequence 0x64 0x74 0x6e 0x21, which is the text string "dtn!" in US-ASCII 🌸
  • version: a one-byte field with the value 3, the current version of the protocol πŸ¦‹
  • flags: a one-byte field for optional connection flags. the first four bits are unused and MUST be set to zero upon transmission and MUST be ignored upon reception. the last four bits are read as shown in Table 1 below πŸ’…
  • keepalive_interval: a two-byte integer that holds the number of seconds between exchanges of KEEPALIVE messages on the connection (see Section 5.6). this value is in network byte order, and so are all the other multi-byte fields in this protocol 🫢
  • local EID length: a variable-length SDNV that holds the length of the endpoint identifier (EID) for some singleton endpoint the sending node is a member of. a four-byte SDNV is drawn in the figure, just for clarity πŸ“
  • local EID: a byte string with the EID of some singleton endpoint the sending node is a member of, in the canonical format of <scheme name>:<scheme-specific part>. an eight-byte EID is shown in the figure, just for clarity 🌈

the flags are where it gets fun πŸ”₯

+----------+--------------------------------------------------------+
|  Value   | Meaning                                                |
+----------+--------------------------------------------------------+
| 00000001 | Request acknowledgment of bundle segments.             |
| 00000010 | Request enabling of reactive fragmentation.            |
| 00000100 | Indicate support for bundle refusal.  This flag MUST   |
|          | NOT be set to '1' unless support for acknowledgments   |
|          | is also indicated.                                     |
| 00001000 | Request sending of LENGTH messages.                    |
+----------+--------------------------------------------------------+

                   Table 1: Contact Header Flags
how the values get configured and picked for these flags and parameters is totally implementation dependent, so it's up to each implementation to decide πŸ™ˆ

4.2. Validation and Parameter Negotiation ✨

once a node gets the contact header, it runs a couple of checks to make sure the TCPCL connection is legit and to work out the connection parameters together 🀝

if the magic string is missing or isn't valid, the connection MUST be terminated. the whole point of the magic string is to protect against a TCP connection that was accidentally opened by some other protocol than the one in this document πŸ’€ and to stop a misconfigured app from flooding you with repeated connections, a node MAY decide to hold an invalid connection open and idle for a while before closing it πŸ›‘

about versions: if a node gets a contact header with a version greater than the current version it implements, the node SHOULD interpret all fields and messages just like it normally would πŸ‘‘. if the version is lower than the one the node implements, the node may either end the connection because of the version mismatch, or adapt its operation to match the older version. which one it picks is an implementation matter πŸŽ€

now the negotiation part πŸ¦‹ a node works out the connection parameters by mixing its own preferences (the ones in the contact header it sent) with the preferences of its peer (the ones in the contact header it received). this negotiation MUST go like this:

  • the parameter for requesting acknowledgment of bundle segments is set to true iff the corresponding flag is set in both contact headers.
  • the parameter for enabling reactive fragmentation is set to true iff the corresponding flag is set in both contact headers.
  • the bundle refusal capability is set to true if the corresponding flag is set in both contact headers and if segment acknowledgment has been enabled.
  • the keepalive_interval parameter is set to the minimum value from both contact headers. if one or both contact headers contain the value zero, then the keepalive feature (described in Section 5.6) is disabled.
  • the flag requesting sending of LENGTH messages is handled as described in Section 5.5.

once parameter negotiation is done, the protocol doesn't define any other way to change the parameters of an established connection. if you need a change, the connection MUST be terminated and a new one established 🌸


5. Established Connection Operation πŸŽ€

this section is about how things run for the whole life of an established connection, including how bundles get sent over it πŸš€

5.1. Message Type Codes 🧚

after the initial contact header exchange, every message sent over the connection is identified by a one-byte header with this structure πŸ‘‡

                     0 1 2 3 4 5 6 7
                    +-+-+-+-+-+-+-+-+
                    | type  | flags |
                    +-+-+-+-+-+-+-+-+

      Figure 4: Format of the One-Byte Message Header
  • type: says what kind of message it is, as listed in Table 2 below πŸ’–
  • flags: optional flags, defined based on the message type 🌈

here are the types and their codes πŸ’…

+----------------+---------+----------------------------------------+
|      Type      | Code    | Description                            |
+----------------+---------+----------------------------------------+
|                | 0x0     | Reserved.                              |
|                |         |                                        |
|  DATA_SEGMENT  | 0x1     | Indicates the transmission of a        |
|                |         | segment of bundle data, as described   |
|                |         | in Section 5.2.                        |
|                |         |                                        |
|  ACK_SEGMENT   | 0x2     | Acknowledges reception of a data       |
|                |         | segment, as described in Section 5.3   |
|                |         |                                        |
| REFUSE_BUNDLE  | 0x3     | Indicates that the transmission of the |
|                |         | current bundle shall be stopped, as    |
|                |         | described in Section 5.4.              |
|                |         |                                        |
|   KEEPALIVE    | 0x4     | KEEPALIVE message for the connection,  |
|                |         | as described in Section 5.6.           |
|                |         |                                        |
|    SHUTDOWN    | 0x5     | Indicates that one of the nodes        |
|                |         | participating in the connection wishes |
|                |         | to cleanly terminate the connection,   |
|                |         | as described in Section 6.             |
|                |         |                                        |
|     LENGTH     | 0x6     | Contains the length (in bytes) of the  |
|                |         | next bundle, as described in Section   |
|                |         | 5.5.                                   |
|                |         |                                        |
|                | 0x7-0xf | Unassigned.                            |
|                |         |                                        |
+----------------+---------+----------------------------------------+

                   Table 2: TCPCL Message Types

5.2. Bundle Data Transmission (DATA_SEGMENT) πŸ¦‹

each bundle gets sent in one or more data segments ✨ here's the DATA_SEGMENT message format πŸ‘‡

                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  0x1  |0|0|S|E|   length ...    |  contents....               |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

             Figure 5: Format of DATA_SEGMENT Messages

the type portion of the message header holds the value 0x1 🌸

the flags portion of the header byte has two optional values in the two low-order bits, marked 'S' and 'E' in the figure. the 'S' bit MUST be set to one if it comes right before the transmission of the first segment of a new bundle. the 'E' bit MUST be set to one when transmitting the last segment of a bundle πŸ”₯

after the message header, the length field is an SDNV holding the number of bytes of bundle data sent in this segment. right after that length comes the actual data contents πŸ’…

how big a segment is depends on the implementation πŸŽ€ a node might, based on local policy or configuration, only ever send bundle data in a single segment. in that case, both the 'S' and 'E' bits MUST be set to one πŸ‘‘

in the Bundle Protocol specification [RFC5050], a single bundle is made up of a primary bundle block, a payload block, and zero or more additional bundle blocks. how the protocol blocks relate to the convergence-layer segments is an implementation-specific decision 🧚 a segment MAY contain more than one protocol block, and a single protocol block (such as the payload) MAY be split across multiple segments 🌈

but a single segment MUST NOT contain data from more than one bundle. that one's a hard rule, bestie 🚨

once a bundle transmission has started, the node MUST only send segments with sequential portions of that bundle until it sends a segment with the 'E' bit set 🫢

5.3. Bundle Acknowledgments (ACK_SEGMENT) πŸ’Œ

okay so TCP is already super reliable, right? πŸ¦‹ But the typical BSD sockets interface doesn't tell the sending app when the receiving app has actually processed the data. ngl that's a whole vibe check gap. So after a Bundle Protocol agent sends some data, it needs another way to know whether the receiving agent really got the segment. πŸ’…

That's where the TCPCL's optional acknowledgment feature comes in. The receiving node can send back acknowledgments saying it got each data segment. This feature is turned on if, and only if, both parties set the flag saying segment acknowledgments are enabled during the contact header exchange (see Section 4.1). If it's on, the receiver MUST transmit a bundle acknowledgment message when it successfully receives each data segment. no skipping, bestie 🫢

Here's what an acknowledgment looks like:

                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  0x2  |0|0|0|0|   acknowledged length ...                     |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 6: Format of ACK_SEGMENT Messages

To send an acknowledgment, a node first sends a message header with the ACK_SEGMENT type code and all flags set to zero. Then it sends an SDNV holding the cumulative length in bytes of the received segment(s) of the current bundle. The length MUST fall on a segment boundary, so only full segments can be acknowledged. πŸ“

Let's do an example! ✨ Say the sender transmits four segments of bundle data with lengths 100, 200, 500, and 1000. After the first segment arrives, the node sends an acknowledgment of length 100. After the second, it sends one of length 300. The third and fourth acknowledgments are of length 800 and 1800. it's giving running total, iykyk πŸ“ˆ


5.4. Bundle Refusal (REFUSE_BUNDLE) πŸ™…β€β™€οΈ

bundles can be HUGE, so the TCPCL has an optional mechanism that lets a receiving node tell the sender "nope, I don't want this bundle." 🌸

To do that, after receiving a DATA_SEGMENT message, the node MAY transmit a REFUSE_BUNDLE message. Data segments and acknowledgments can cross on the wire, so the refused bundle is implicitly identified by the order in which acknowledgments and refusals are received. it's a whole choreography, periodt πŸ’ƒ

Here's the REFUSE_BUNDLE format:

                             0 1 2 3 4 5 6 7
                            +-+-+-+-+-+-+-+-+
                            |  0x3  | RCode |
                            +-+-+-+-+-+-+-+-+

Figure 7: Format of REFUSE_BUNDLE Messages

The RCode field stands for "reason code," and it holds a value explaining why the bundle got refused. The table below covers the semantics for some values. Other values may be registered with IANA, as defined in Section 8. πŸ‘‘

+---------+---------------------------------------------------------+
|  RCode  | Semantics                                               |
+---------+---------------------------------------------------------+
|   0x0   | Reason for refusal is unknown or not specified.         |
|   0x1   | The receiver now has the complete bundle.  The sender   |
|         | may now consider the bundle as completely received.     |
|   0x2   | The receiver's resources are exhausted.  The sender     |
|         | SHOULD apply reactive bundle fragmentation before       |
|         | retrying.                                               |
|   0x3   | The receiver has encountered a problem that requires    |
|         | the bundle to be retransmitted in its entirety.         |
| 0x4-0x7 | Unassigned.                                             |
| 0x8-0xf | Reserved for future usage.                              |
+---------+---------------------------------------------------------+

Table 3: REFUSE_BUNDLE Reason Codes

The receiver MUST, for each bundle before the one being refused, have either acknowledged all DATA_SEGMENTs or refused the bundle. That's how the sender can match up accepted and refused bundles using a simple FIFO list of segments and acknowledgments. the ordering is everything 🧚

The bundle refusal MAY be sent before the whole data segment has arrived. If a sender gets a REFUSE_BUNDLE message, the sender MUST finish sending any partially sent DATA_SEGMENT message, so the receiver stays in sync. After that, the sender MUST NOT start sending any more segments of the rejected bundle. ngl this is the rule that keeps everybody on the same page πŸ“–

Now, this doesn't guarantee that a node won't get another DATA_SEGMENT for the same bundle after it sends a REFUSE_BUNDLE message, because messages can cross on the wire. If that happens, subsequent segments of the bundle SHOULD also be refused with a REFUSE_BUNDLE message. πŸ”

Note: If a bundle transmission is aborted this way, the receiver may not receive a segment with the 'E' flag set to '1' for the aborted bundle. The start of the next bundle is identified by the 'S' bit set to '1', which signals the start of a new bundle. 🚩

5.5. Bundle Length (LENGTH) πŸ“

The LENGTH message carries the total length, in bytes, of the next bundle, formatted as an SDNV. Its job is to let nodes preemptively refuse bundles that would blow past their resources. It's an optimization, so it's a nice-to-have, not a must-have. 🌈

Here's the LENGTH format:

                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  0x6  |0|0|0|0|     total bundle length ...                   |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 8: Format of LENGTH Messages

LENGTH messages MUST NOT be sent unless the corresponding flag bit is set in the contact header. If that flag bit is set, LENGTH messages MAY be sent whenever the sender feels like it. Also, LENGTH messages MUST NOT be sent unless the next DATA_SEGMENT message has the 'S' bit set to "1" (so, just before the start of a new bundle). these are strict, bestie πŸ™ˆ

A receiver MAY send a BUNDLE_REFUSE message as soon as it gets a LENGTH message, without waiting for the next DATA_SEGMENT message. The sender MUST be ready for this and MUST associate the refusal with the right bundle. πŸ’œ


5.6. KEEPALIVE Feature (KEEPALIVE) πŸ’“

The protocol has a provision for sending KEEPALIVE messages over the TCP connection, which helps figure out whether the connection has been disrupted. 🫧

As described in Section 4.1, one of the parameters in the contact header is the keepalive_interval. Both sides fill in this field with the interval (in seconds) they'd like between KEEPALIVE messages. πŸŽ€

A KEEPALIVE message is just a one-byte message type code of KEEPALIVE (as described in Table 2) with no extra data. Both sides SHOULD send a KEEPALIVE message whenever the negotiated interval has elapsed with no transmission of any message (KEEPALIVE or otherwise). πŸ’–

If no message (KEEPALIVE or otherwise) has been received for at least twice the keepalive_interval, then either party MAY end the session by sending a one-byte SHUTDOWN message (as described in Table 2) and then closing the TCP connection. πŸŒ™

Note: The keepalive_interval should not be chosen too short, as TCP retransmissions may occur in case of packet loss. Those have to be triggered by a timeout (TCP retransmission timeout (RTO)), which depends on the measured RTT for the TCP connection, so KEEPALIVE messages may experience noticeable latency. ⏳

6. Connection Termination πŸšͺ

okay this section is all about the procedures for ending a TCPCL connection. Let's see how the goodbye works! πŸ‘‹βœ¨

6.1. Shutdown Message (SHUTDOWN) πŸ’–

okay bestie, so to cleanly shut a connection down, a SHUTDOWN message MUST be transmitted by either node at any point after it has finished sending any other message πŸ’…. If acknowledgments were negotiated, a node SHOULD acknowledge all the data segments it received first, and then shut the connection down 🫢.

The format of the SHUTDOWN message is as follows:

                       1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |  0x5  |0|0|R|D| reason (opt)  | reconnection delay (opt)      |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 9: Format of Bundle SHUTDOWN Messages

It's possible for a node to share extra info about why the connection is ending πŸ“. To do that, the node MUST set the 'R' bit in the message header flags and send a one-byte reason code right after the message header. The specified reason codes are:

   +-----------+------------------+------------------------------------+
   |    Code   | Meaning          | Description                        |
   +-----------+------------------+------------------------------------+
   |    0x00   | Idle timeout     | The connection is being closed due |
   |           |                  | to idleness.                       |
   |           |                  |                                    |
   |    0x01   | Version mismatch | The node cannot conform to the     |
   |           |                  | specified TCPCL protocol version.  |
   |           |                  |                                    |
   |    0x02   | Busy             | The node is too busy to handle the |
   |           |                  | current connection.                |
   |           |                  |                                    |
   | 0x03-0xff |                  | Unassigned.                        |
   +-----------+------------------+------------------------------------+

Table 4: SHUTDOWN Reason Codes

It's also possible to request a reconnection delay, which tells the other node how long to wait before trying to re-establish the connection πŸ¦‹. To do that, the node sets the 'D' bit in the message header flags and then sends an SDNV with the requested delay, in seconds, right after the message header (and optionally, after the SHUTDOWN reason code). The value 0 SHALL be interpreted as an infinite delay, i.e., that the connecting node MUST NOT re-establish the connection πŸ™ˆ. On the flip side, if the node doesn't want to request a delay, it SHOULD omit the reconnection delay field (and set the 'D' bit to zero). Also, the figure above shows the reconnection delay SDNV as a two-byte field, just for convenience ✨.

A connection shutdown MAY happen right after TCP connection establishment or after receiving a contact header (and before any further data exchange) 🌸. This could be useful for saying "hey, I'm not able or willing to talk right now." However, a node MUST always send the contact header to its peer before sending a SHUTDOWN message, no exceptions πŸ‘‘.

If either node ends a connection early like this, it SHOULD send a SHUTDOWN message and MUST include a reason code, unless the incoming connection didn't include the magic string πŸ’…. If a node doesn't want its peer to reopen the connection right away, it SHOULD set the 'D' bit and include a reconnection delay so the peer knows when it's allowed to try again πŸ’œ.

If a connection needs to end before another protocol message has finished, then the node MUST NOT transmit the SHUTDOWN message, but it still SHOULD close the TCP connection 😭. This matters a LOT when a node is in the middle of sending a bundle data segment. The receiving node is still expecting segment data, so it might mistakenly read the SHUTDOWN message as part of that data segment πŸ’€.

6.2. Idle Connection Shutdown πŸŒ™

The protocol has a provision for cleanly shutting down idle TCP connections 🧚. Figuring out how long to wait before closing idle connections, if they get closed at all, is an implementation and configuration matter.

If there's a configured time to close idle links, and no bundle data (other than KEEPALIVE messages) has been received for at least that long, then either node MAY end the connection by sending a SHUTDOWN message with the reason code 'Idle timeout' (as described in Table 4) πŸƒ. After receiving a SHUTDOWN message in response, both sides may close the TCP connection.

7. Security Considerations 🚨

Okay, this part is seriously important, so please read it all πŸ”₯. One security concern is that nodes present their endpoint identifier as part of the connection header exchange. A node could fake this value and claim the identity of a singleton endpoint it isn't a member of, basically masquerading as another DTN node 😱. If that identifier gets used without any further verification to decide which bundles get sent over the connection, then the node that faked its identity might be able to get bundles it should never have seen. So, a node SHALL NOT use the endpoint identifier conveyed in the TCPCL connection message to derive a peer node's identity unless it can confirm it through other means. No shortcuts, periodt πŸ’….

These concerns may be reduced by using the Bundle Security Protocol [RFC6257] ✨. In particular, the Bundle Authentication Block defines a mechanism for securely exchanging bundles between DTN nodes. That means an implementation could hold off on trusting the presented endpoint identifier until the node can securely confirm that its peer really is the only member of that singleton endpoint πŸ”.

Overall, TCPCL doesn't provide any security services by itself. The mechanisms defined in [RFC6257] are meant to be used instead 🫢.

Nothing in TCPCL stops you from using the Transport Layer Security (TLS) protocol [RFC5246] to secure a connection 🌈.

Another concern is denial-of-service attacks 😬. A node may send a huge amount of data over a TCP connection, forcing the receiving node to handle it. The receiver might then try to stop the flood by sending a REFUSE_BUNDLE message, or just forcibly terminate the connection. That burden could cause denial of service for other, well-behaving connections. Nothing stops a malicious node from constantly establishing connections and repeatedly trying to send tons of bundle data either πŸ’€. A listening node MAY take countermeasures, such as ignoring TCP SYN messages, closing TCP connections as soon as they're established, waiting before sending the contact header, or sending a SHUTDOWN message quickly or with a delay, etc πŸ›‘οΈ.

8. IANA Considerations πŸ“‹

In this section, registration procedures are as defined in [RFC5226] πŸ’œ.

8.1. Port Number πŸ”Œ

Port number 4556 has been assigned as the default port for the TCP convergence layer πŸŽ€.

Service Name:  dtn-bundle

Transport Protocol(s):  TCP

Assignee:  Simon Perreault <simon@per.reau.lt>

Contact:  Simon Perreault <simon@per.reau.lt>

Description:  DTN Bundle TCP CL Protocol

Reference:  [RFC7242]

Port Number:  4556

8.2. Protocol Versions πŸ”’

IANA has created, under the "Bundle Protocol" registry, a sub-registry titled "Bundle Protocol TCP Convergence-Layer Version Numbers" and initialized it with the following:

                    +-------+-------------+-----------+
                    | Value | Description | Reference |
                    +-------+-------------+-----------+
                    |   0   | Reserved    | [RFC7242] |
                    |   1   | Reserved    | [RFC7242] |
                    |   2   | Reserved    | [RFC7242] |
                    |   3   | TCPCL       | [RFC7242] |
                    | 4-255 | Unassigned  | [RFC7242] |
                    +-------+-------------+-----------+

The registration procedure is RFC Required 🌟.

8.3. Message Types πŸ“¨

IANA has created, under the "Bundle Protocol" registry, a sub-registry titled "Bundle Protocol TCP Convergence-Layer Message Types" and initialized it with the contents of Table 2. The registration procedure is RFC Required πŸ’….

8.4. REFUSE_BUNDLE Reason Codes πŸ™…

IANA has created, under the "Bundle Protocol" registry, a sub-registry titled "Bundle Protocol TCP Convergence-Layer REFUSE_BUNDLE Reason Codes" and initialized it with the contents of Table 3. The registration procedure is RFC Required 🫢.

8.5. SHUTDOWN Reason Codes πŸšͺ

IANA has created, under the "Bundle Protocol" registry, a sub-registry titled "Bundle Protocol TCP Convergence-Layer SHUTDOWN Reason Codes" and initialized it with the contents of Table 4. The registration procedure is RFC Required ✨.

9. Acknowledgments 🌸

The authors would like to thank the following people who took part in drafting, reviewing, and discussing this memo, because they're the real MVPs πŸ‘‘: Alex McMahon, Brenton Walker, Darren Long, Dirk Kutscher, Elwyn Davies, Jean-Philippe Dionne, Joseph Ishac, Keith Scott, Kevin Fall, Lloyd Wood, Marc Blanchet, Peter Lovell, Scott Burleigh, Stephen Farrell, Vint Cerf, and William Ivancic 🫢.

10. References πŸ“š

10.1. Normative References πŸ”’

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC5050]  Scott, K. and S. Burleigh, "Bundle Protocol
           Specification", RFC 5050, November 2007.

[RFC5226]  Narten, T. and H. Alvestrand, "Guidelines for Writing an
           IANA Considerations Section in RFCs", BCP 26, RFC 5226,
           May 2008.

10.2. Informative References πŸ“–

[DTNIMPL]  DTNRG, "Delay-Tolerant Networking Reference
           Implementation", <https://sites.google.com/site/dtnresgroup/home/code>.

[RFC4838]  Cerf, V., Burleigh, S., Hooke, A., Torgerson, L., Durst,
           R., Scott, K., Fall, K., and H. Weiss, "Delay-Tolerant
           Networking Architecture", RFC 4838, April 2007.

[RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
           (TLS) Protocol Version 1.2", RFC 5246, August 2008.

[RFC6256]  Eddy, W. and E. Davies, "Using Self-Delimiting Numeric
           Values in Protocols", RFC 6256, May 2011.

[RFC6257]  Symington, S., Farrell, S., Weiss, H., and P. Lovell,
           "Bundle Security Protocol Specification", RFC 6257, May
           2011.

Authors' Addresses πŸ’Œ

Michael J. Demmer
University of California, Berkeley
Computer Science Division
445 Soda Hall
Berkeley, CA  94720-1776
US

EMail: demmer@cs.berkeley.edu


Joerg Ott
Aalto University
Department of Communications and Networking
PO Box 13000
AALTO  02015
Finland

EMail: jo@netlab.tkk.fi


Simon Perreault
Quebec, QC
Canada

EMail: simon@per.reau.lt
πŸ“¦ where this page comes from