RFC 8931

IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Selective Fragment Recovery

๐Ÿ“… published November 2020, from ietf

๐ŸŽ€ RFC 8931: IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Selective Fragment Recovery ๐Ÿฆ‹

bestie, this one is titled "IPv6 over 6LoWPAN Selective Fragment Recovery" and it's from the IETF ๐ŸŒˆ. It's a Standards Track doc (so it's a real, official spec, not just an idea) written by P. Thubert, Ed. from Cisco Systems ๐Ÿ’ผ. It came out in November 2020 ๐Ÿ‚, and its ISSN is 2070-1721 ๐Ÿ”ข. The big news is that it updates RFC 4944 ๐Ÿ”„, which is the original 6LoWPAN fragmentation spec, so this one is literally upgrading it. The doc doesn't say it obsoletes anything, so nothing is getting retired here ๐Ÿ™…โ€โ™€๏ธ.

Abstract โœจ

okay so the whole pitch is this: this doc updates RFC 4944 with a protocol that forwards individual fragments across a route-over mesh and then recovers them end to end ๐Ÿซถ. It also brings congestion control so the network doesn't get overwhelmed ๐Ÿ’….

Status of This Memo ๐Ÿ“œ

This is an Internet Standards Track document. ๐Ÿ”ฅ

This document is a product of the Internet Engineering Task Force (IETF) ๐ŸŒธ. It represents the consensus of the IETF community, so a lot of people agreed on it. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG) ๐Ÿ‘‘. If you want more info on Internet Standards, check Section 2 of RFC 7841 ๐Ÿงš.

For the current status, any errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc8931 ๐Ÿ’–.

Copyright (c) 2020 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 stood on the publication date. Please actually read these, because they spell out your rights and restrictions for this doc ๐Ÿ™ˆ. 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 with no warranty, as the Simplified BSD License describes ๐ŸŒˆ.

Table of Contents ๐Ÿ—‚๏ธ

   1.  Introduction
   2.  Terminology
     2.1.  Requirements Language
     2.2.  Background
     2.3.  Other Terms
   3.  Updating RFC 4944
   4.  Extending RFC 8930
     4.1.  Slack in the First Fragment
     4.2.  Gap between Frames
     4.3.  Congestion Control
     4.4.  Modifying the First Fragment
   5.  New Dispatch Types and Headers
     5.1.  Recoverable Fragment Dispatch Type and Header
     5.2.  RFRAG Acknowledgment Dispatch Type and Header
   6.  Fragment Recovery
     6.1.  Forwarding Fragments
       6.1.1.  Receiving the First Fragment
       6.1.2.  Receiving the Next Fragments
     6.2.  Receiving RFRAG Acknowledgments
     6.3.  Aborting the Transmission of a Fragmented Packet
     6.4.  Applying Recoverable Fragmentation along a Diverse Path
   7.  Management Considerations
     7.1.  Protocol Parameters
     7.2.  Observing the Network
   8.  Security Considerations
   9.  IANA Considerations
   10. References
     10.1.  Normative References
     10.2.  Informative References
   Appendix A.  Rationale
   Appendix B.  Requirements
   Appendix C.  Considerations on Congestion Control
   Acknowledgments
   Author's Address

1. Introduction ๐ŸŒธ

okay so in most Low-Power and Lossy Network (LLN) apps, the traffic is mostly tiny chunks of data, like a few bytes to a few tens of bytes at a time ๐Ÿฆ‹. An IEEE Std 802.15.4 [IEEE.802.15.4] frame can carry a payload of 74 bytes or more, so fragmentation is usually not needed ๐Ÿ™Œ. BUT (and this is the plot twist) a bunch of mission-critical apps do need to move bigger chunks, like firmware upgrades for LLN nodes or pulling logs off them ๐Ÿ“ฆ.

In the firmware case, the big chunk flows into the LLN node. In the logs case, it flows away from it ๐Ÿ”„. Either way, we're talking about something around 10 KB or more, and an end-to-end reliable transport is required ๐Ÿ’….

"Transmission of IPv6 Packets over IEEE 802.15.4 Networks" [RFC4944] is where the original 6LoWPAN datagram fragmentation mechanism for LLNs came from ๐Ÿงš. The big problem with that original design is that routing an IPv6 [RFC8200] packet across a route-over mesh means the packet gets reassembled at every hop ๐Ÿ˜ญ. "An Architecture for IPv6 over the TSCH mode of IEEE 802.15.4" [6TiSCH] says this can add latency along a path and eat into critical resources like memory and battery ๐Ÿ”‹. To help with that, it recommends using a 6LoWPAN Fragment Forwarding (6LFF) technique ๐Ÿ’–.

"On Forwarding 6LoWPAN Fragments over a Multihop IPv6 Network" [RFC8930] lays out the generic behavior that all 6LFF techniques, this spec included, follow, and it also covers the caveats ๐ŸŽ€. The main thing is that the routing info is fully in the first fragment, which always goes first ๐Ÿš€. In this spec, the first fragment is identified by a Sequence of 0, instead of by a dispatch type like in [RFC4944] โœจ. A state gets formed and then used to forward all the next fragments along that same path ๐Ÿ›ค๏ธ. The Datagram_Tag is only locally significant to the Layer 2 source of the packet, and it gets swapped at each hop (see Section 6) ๐Ÿ”. This spec encodes the Datagram_Tag in 1 byte, which will saturate if more than 256 datagrams transit in fragmented form over a single hop at the same time ๐Ÿ’€. That's not realistic as of this writing ๐Ÿ™ˆ. If it ever happens in a new 6LoWPAN technology, a node will need to use several link-layer addresses to increase its indexing capacity ๐Ÿงฉ.

"Virtual reassembly buffers in 6LoWPAN" [LWIG-FRAG] proposes a 6LFF technique that's compatible with [RFC4944] without needing a new protocol ๐Ÿซง. But just adding that capability to the local implementation of the original 6LoWPAN fragmentation wouldn't fix the inherent fragility of fragmentation (see [RFC8900]) ๐Ÿ˜ฉ. The two issues it wouldn't fix are resources getting locked up on the reassembling endpoint, and wasted transmissions when a single fragment gets lost in a whole datagram ๐Ÿฅฒ.

[Kent] compares the unreliable delivery of fragments with a mechanism it calls "selective acknowledgments," which recovers the loss of a fragment individually ๐Ÿคฏ. The paper shows the benefits you can get from that method, see Figures 1, 2, and 3 in Section 2.3 of [Kent] ๐Ÿ“Š. [RFC4944] has no selective recovery, so the whole datagram fails when one fragment doesn't reach the reassembling endpoint ๐Ÿ’”. Constrained memory stays blocked on that endpoint until it times out, which can make later packets get lost because there are no buffers left for them ๐Ÿ˜ต.

It gets worse when fragments are forwarded over multiple hops, since a loss at an intermediate hop won't be discovered by either the fragmenting or the reassembling endpoints ๐Ÿ‘€. When that happens, the source keeps sending fragments and wastes even more network resources, because the datagram can never arrive in full, and that might even add to the condition that caused the loss ๐ŸŒ€. [RFC4944] has no congestion control, so it can't avoid piling onto a saturation that may have caused the fragment loss in the first place ๐Ÿšฆ. It also has no signaling to abort a multi-fragment transmission at any time from either end, and if forwarding fragments is implemented, there's no way to clean up the related state in the network ๐Ÿงน.

This spec gives you a method to forward fragments over, typically, a few hops in a route-over 6LoWPAN mesh, plus a selective acknowledgment to recover individual fragments between 6LoWPAN endpoints ๐Ÿฆ‹. The method can help limit congestion loss in the network and meets the requirements in Appendix B ๐Ÿ’œ. Flow control is out of scope, because the endpoints are expected to be able to store the full datagram ๐Ÿ“ฆ. Deployments are expected to be managed and homogeneous, and moving over incrementally requires a flag day ๐Ÿณ๏ธ.

2. Terminology ๐Ÿง 

2.1. Requirements Language ๐Ÿ’…

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.2. Background ๐Ÿ“š

This doc uses 6LoWPAN terms and concepts from "IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs): Overview, Assumptions, Problem Statement, and Goals" [RFC4919], "Transmission of IPv6 Packets over IEEE 802.15.4 Networks" [RFC4944], and "Problem Statement and Requirements for IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Routing" [RFC6606] ๐Ÿง.

[RFC8930] talks about the generic concept of a Virtual Reassembly Buffer (VRB). It also specifies behaviors and caveats shared by a big family of 6LFF techniques, including the mechanism in this doc, which fully inherits from that spec ๐Ÿซถ. It defines some terms this doc uses too: Compressed Form, Datagram_Tag, Datagram_Size, Fragment_Offset, and 6LoWPAN Fragment Forwarding endpoint (usually just shortened to "endpoint") ๐Ÿท๏ธ.

Past experience with fragmentation has shown that misassociated or lost fragments can lead to poor network behavior and, sometimes, trouble at the application layer ๐Ÿ˜ฌ. Go read "IPv4 Reassembly Errors at High Data Rates" [RFC4963] and follow its references if you want more ๐Ÿ“–. That experience is what led to "Path MTU Discovery for IP version 6" [RFC8201], which limits fragmentation over the Internet ๐ŸŒ. For UDP specifically, "UDP Usage Guidelines" [RFC8085] has valuable extra info ๐Ÿ’ป.

"The Benefits of Using Explicit Congestion Notification (ECN)" [RFC8087] has useful info on the potential benefits and pitfalls of using ECN ๐Ÿšฆ.

Quoting "Multiprotocol Label Switching Architecture" [RFC3031]:

| With MPLS, "packets are "labeled" before they are forwarded [along | a Label Switched Path (LSP)]. At subsequent hops, there is no | further analysis of the packet's network layer header. Rather, | the label is used as an index into a table which specifies the | next hop, and a new label".

[RFC8930] borrows the MPLS idea to forward fragments that don't actually have a network-layer header, since fragmentation happens below IP ๐Ÿช„. This spec makes that reversible, so the reverse path can be followed as well ๐Ÿ”.

2.3. Other Terms ๐Ÿซง

This specification uses the following terms:

  • RFRAG: Recoverable Fragment ๐Ÿงฉ
  • RFRAG-ACK: Recoverable Fragment Acknowledgment ๐Ÿ’Œ
  • RFRAG Acknowledgment Request: An RFRAG with the Acknowledgment Request flag ("X" flag) set. ๐Ÿ™‹โ€โ™€๏ธ
  • NULL bitmap: Refers to a bitmap with all bits set to zero. 0๏ธโƒฃ
  • FULL bitmap: Refers to a bitmap with all bits set to one. 1๏ธโƒฃ
  • Reassembling endpoint: The receiving endpoint. ๐Ÿ“ฅ
  • Fragmenting endpoint: The sending endpoint. ๐Ÿ“ค
  • Forward direction: The direction of a path, which is followed by the RFRAG. โžก๏ธ
  • Reverse direction: The reverse direction of a path, which is taken by the RFRAG-ACK. โฌ…๏ธ

3. Updating RFC 4944 ๐ŸŽ€

okay bestie, so this section is basically about how RFC 4944 fragmentation gets upgraded for route-over LLNs ๐Ÿ’… The big glow-up is that fragments can now be forwarded end to end across a 6LoWPAN LLN, and if one gets lost on the way, it can be recovered on its own instead of redoing the whole datagram ๐Ÿฆ‹ A new fragment format shows up, and the new dispatch types are defined in Section 5 โœจ

[RFC8138] lets the packet shrink en route by removing consumed hops from a compressed Routing Header ๐Ÿ“ ngl that means Fragment_Offset and Datagram_Size (from Section 5.1) also have to change along the way, and that's a pain to do in the uncompressed form ๐Ÿ˜ญ So this spec puts those fields in compressed form so they can be modified en route easily ๐Ÿ’œ (more in Section 4.4 ๐Ÿซถ)

and here's the consistency part ๐Ÿ™ˆ To match Section 2 of [RFC6282], for the fragmentation mechanism in Section 5.3 of [RFC4944], any header that can't fit inside the first fragment MUST NOT be compressed when you use the fragmentation mechanism described here ๐ŸŒธ

4. Extending RFC 8930 ๐ŸŒˆ

this spec implements the generic 6LFF technique from [RFC8930] and adds end-to-end fragment recovery and congestion control on top ๐Ÿ‘‘

4.1. Slack in the First Fragment ๐Ÿงš

[RFC8930] allows a refragmentation operation at intermediate nodes, where the trailing bytes of a fragment can be left in the VRB and added as the heading bytes of the next fragment โœจ That solves the case where the outgoing fragment needs more space than the incoming one. This can happen when 6LoWPAN header compression is less efficient on the outgoing link, or when the Link MTU gets reduced ๐Ÿซ 

this spec cannot allow that refragmentation operation ๐Ÿ™…โ€โ™€๏ธ because fragments are recovered end to end based on a sequence number. The Fragment_Size MUST be tailored to fit the minimal MTU along the path, and the first fragment that contains a 6LoWPAN compressed header MUST have enough slack so a less-efficient compression at the next hops still fits within the Link MTU ๐Ÿ’–

for example, if the fragmenting endpoint is also the 6LoWPAN compression endpoint, it'll elide the Interface ID (IID) of the source IPv6 address when it matches the link-layer address [RFC6282] ๐Ÿฆ‹ In that case it MUST leave slack in the first fragment, as if the MTU on the first hop were 8 bytes less, so the next hop can expand the IID within the same fragment within MTU ๐ŸŒธ

4.2. Gap between Frames ๐Ÿ’…

[RFC8930] requires a configurable interval of time between transmissions to the same next hop, and in particular between fragments of the same datagram โณ On half duplex interfaces, this inter-frame gap makes sure the next hop is done forwarding the previous frame and is ready to receive the next one ๐ŸŽง

in a mesh running at a single frequency with omnidirectional antennas, a larger inter-frame gap is needed to protect the frame against hidden terminal collisions with the previous frame of the same flow, which is still moving along a common path ๐Ÿ™ˆ

the inter-frame gap is useful even for unfragmented datagrams ๐Ÿ’œ but it becomes a necessity for fragments, which are typically generated in a fast sequence and all sent over the exact same path ๐Ÿ˜ญ

4.3. Congestion Control ๐Ÿ”ฅ

the inter-frame gap is the only protection that [RFC8930] imposes by default ๐Ÿฅบ this document lets you group fragments into windows and request intermediate acknowledgments, so the number of in-flight fragments can be bounded ๐ŸŽ€ It also adds an ECN mechanism that can protect the network by adapting the window size, the fragment size, and/or the inter-frame gap โœจ

this spec lets the fragmenting endpoint apply a congestion control mechanism to tune those parameters, but the mechanism itself is out of scope ๐Ÿ™‹โ€โ™€๏ธ Usually, most datagrams only need a few fragments, and only the last fragment gets acknowledged ๐Ÿ“ A basic implementation of the fragmenting endpoint is NOT REQUIRED to vary the window size, the inter-frame gap duration, or the size of a fragment in the middle of a datagram's transmission ๐Ÿ’… It MAY ignore the ECN signal, or simply reset the window to 1 (see Appendix C) until the end of that datagram once congestion is detected ๐Ÿซถ

an intermediate node that experiences congestion MAY set the ECN bit in a fragment, and the reassembling endpoint echoes the ECN bit at most once at the next opportunity to acknowledge back ๐Ÿ‘‘

the size of the fragments is typically computed from the Link MTU to maximize the size of the resulting frames ๐Ÿงš The size of the window and the duration of the inter-frame gap SHOULD be configurable, to reduce the chances of congestion and to follow the general recommendations in [RFC8930], respectively โœจ

4.4. Modifying the First Fragment ๐Ÿฆ‹

the compression of the hop limit, of the source and destination addresses in the IPv6 header, and of the Routing Header (all in the first fragment) may change en route in a route-over mesh LLN ๐ŸŒˆ If the size of the first fragment is modified, the intermediate node MUST adapt the Datagram_Size, encoded in the Fragment_Size field, to reflect that difference ๐Ÿ’–

the intermediate node MUST also save the difference in Datagram_Size of the first fragment in the VRB and add it to the Fragment_Offset of all the subsequent fragments it forwards for that datagram ๐ŸŒธ In the case of a Source Routing Header 6LoWPAN Routing Header (SRH-6LoRH) [RFC8138] being consumed and therefore reduced, that difference is negative, meaning the Fragment_Offset gets decremented by the number of bytes that were consumed ๐Ÿ˜ญ

5. New Dispatch Types and Headers ๐Ÿ’œ

this document specifies an alternative to the 6LoWPAN fragmentation sub-layer [RFC4944] that emulates a Link MTU up to 2048 bytes for the upper layer ๐ŸŽ€ That upper layer can be the 6LoWPAN header compression sub-layer defined in "Compression Format for IPv6 Datagrams over IEEE 802.15.4-Based Networks" [RFC6282] โœจ This spec also provides reliable transmission of fragments over a multi-hop 6LoWPAN route-over mesh network, plus minimal congestion control to reduce the chances of congestion loss ๐Ÿ”ฅ

a 6LoWPAN Fragment Forwarding [RFC8930] technique derived from MPLS lets individual fragments be forwarded across a 6LoWPAN route-over mesh without reassembly at each hop ๐Ÿงš The Datagram_Tag is used as a label. It's locally unique to the node that owns the source link-layer address of the fragment, so together the link-layer address and the label can identify the fragment globally within the datagram's lifetime ๐Ÿฆ‹ A node may build the Datagram_Tag in its own locally significant way, as long as the chosen Datagram_Tag stays unique to that particular datagram for its lifetime ๐ŸŒธ So the label doesn't need to be globally unique, but it MUST be swapped at each hop as the source link-layer address changes ๐Ÿ’…

in the following sections, a Datagram_Tag extends the semantics defined in "Fragmentation Type and Header" (see Section 5.3 of [RFC4944]) ๐Ÿซถ The Datagram_Tag is a locally unique identifier for the datagram from the sender's perspective, which means it identifies a datagram uniquely in the network when associated with the datagram's source ๐Ÿ‘‘ As the datagram gets forwarded, the source changes, and the Datagram_Tag MUST be swapped as detailed in [RFC8930] ๐Ÿฅบ

this specification extends [RFC4944] with two new dispatch types, one for RFRAG and one for the RFRAG-ACK that comes back ๐ŸŒˆ The new 6LoWPAN dispatch types are taken from [RFC8025], as indicated in Table 1 of Section 9 ๐Ÿ’–

5.1. Recoverable Fragment Dispatch Type and Header

Okay so, here's the vibe: if the packet is compressed, the size and offset of each fragment are measured against the compressed form of the packet, not the uncompressed native one. Main character energy for the compressed version ๐Ÿ’…โœจ

The fragment header in Figure 1 is the same for every fragment, even though Fragment_Offset is doing double duty ๐Ÿฆ‹. It has a length, an offset, and a Sequence field. You might think that's redundant because the offset could be computed as Sequence times length, but it's not! The spot a fragment occupies in the reassembly buffer has nothing to do with its Sequence value or the order it arrives in ๐Ÿ™ˆ. This is what lets you split fragments when the MTU shrinks. Look at fragment Sequence 5 getting retried end to end as the smaller fragments Sequences 13 and 14 in Section 6.2. Iconic ๐Ÿ‘‘

The first fragment is the one with Sequence 0. It carries its Fragment_Size and the Datagram_Size of the compressed packet before it got fragmented. Every other fragment carries its Fragment_Size and Fragment_Offset instead ๐ŸŽ€. The last fragment shows up when its Fragment_Offset plus its Fragment_Size add up to the stored Datagram_Size of the packet, which is identified by the sender's link-layer address and the Datagram_Tag ๐ŸŒธ.

                              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
                                       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                       |1 1 1 0 1 0 0|E|  Datagram_Tag |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |X| Sequence|   Fragment_Size   |       Fragment_Offset         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

                                                X set == Ack-Request

                  Figure 1: RFRAG Dispatch Type and Header

Here's what each field does ๐Ÿ“:

  • X: 1 bit, Ack-Request. When it's set, the fragmenting endpoint needs an RFRAG Acknowledgment from the reassembling endpoint.
  • E: 1 bit, Explicit Congestion Notification. The source of the fragment clears this flag, and intermediate routers set it to signal that the fragment ran into congestion along its path ๐ŸŒˆ.
  • Fragment_Size: a 10-bit unsigned integer giving the size of this fragment, in a unit that depends on the link-layer technology. Unless a more specific specification says otherwise, that unit is the byte, which means fragments can be up to 1023 bytes โญ.
  • Datagram_Tag: 8 bits. An identifier for the datagram that's locally unique to the link-layer sender ๐Ÿงš.
  • Sequence: a 5-bit unsigned integer, the sequence number of the fragment in the acknowledgment bitmap. Fragments are numbered [0..N], where N is in [0..31]. A Sequence of 0 marks the first fragment in a datagram, but non-zero values don't tell you where the fragment sits in the reassembly buffer ๐Ÿ’œ.
  • Fragment_Offset: a 16-bit unsigned integer. When it's set to a non-zero value, what it means depends on the Sequence field, like this ๐Ÿ”ฅ:
    • For a first fragment (Sequence of 0), this field gives the Datagram_Size of the compressed datagram, so the reassembling endpoint can allocate a suitably sized buffer for reception and reassembly. The fragment may be stored for local reassembly. Or it may be routed based on the destination IPv6 address. In that case, a VRB state must be installed, as described in Section 6.1.1.
    • When the Sequence isn't 0, this field gives the offset of the fragment within the compressed form of the datagram. The fragment may go into a local reassembly buffer, or it may be forwarded based on an existing VRB, as described in Section 6.1.2.

A Fragment_Offset set to 0 is an abort signal ๐Ÿšซ. All the state about the datagram should get cleaned up once the fragment is processed. What happens next depends on whether a VRB already exists for this datagram and whether the next hop is still reachable:

  • If a VRB already exists and the next hop is still reachable, the fragment gets forwarded along the associated LSP as described in Section 6.1.2, without checking the Sequence field.
  • Otherwise, if the Sequence is 0, the fragment is routed as described in Section 6.1.1, but no state is kept afterwards. In that case, the session gets aborted if it exists, and the packet is forwarded too, to clean up the next hops along the path indicated by the IPv6 header (which may include a Routing Header) ๐Ÿงน.
  • Otherwise (the Sequence is non-zero and either no VRB exists or the next hop is unavailable), the fragment can't be forwarded or routed. It gets discarded, and an abort RFRAG-ACK is sent back to the source, as described in Section 6.1.2 ๐Ÿ’€.

Recoverable Fragments are sequenced, and an RFRAG Acknowledgment uses a bitmap to show which fragments arrived. Each received fragment sets the bit that matches its sequence number ๐Ÿฆ‹.

The reassembling endpoint isn't required to check that received fragments are consecutive and non-overlapping. This is especially handy when the MTU changes and a fragment Sequence gets retried with a smaller Fragment_Size, while the rest of the original fragment gets retried under new Sequence values ๐Ÿซถ. The fragmenting endpoint knows the datagram is fully received once the acknowledged fragments cover the whole datagram. That's what a FULL bitmap means โœจ.

5.2. RFRAG Acknowledgment Dispatch Type and Header

This specification also defines a 4-byte RFRAG Acknowledgment Bitmap ๐ŸŽ€. The reassembling endpoint uses it to selectively confirm individual fragments. Each offset in the bitmap maps one to one with a sequence number, and it tells you whether that fragment was acknowledged, like in Figure 2 ๐Ÿ‘‘:

                            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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |           RFRAG Acknowledgment Bitmap                         |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        ^                 ^
        |                 |    bitmap indicating whether:
        |                 +----- Fragment with Sequence 9 was received
        +----------------------- Fragment with Sequence 0 was received

               Figure 2: RFRAG Acknowledgment Bitmap Encoding

Figure 3 is an example bitmap. It shows that every fragment from Sequence 0 to 20 arrived, except fragments 1, 2, and 16. Those got lost, so they must be retried ๐Ÿ˜ญ.

                            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
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |1|0|0|1|1|1|1|1|1|1|1|1|1|1|1|1|0|1|1|1|1|0|0|0|0|0|0|0|0|0|0|0|
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

               Figure 3: Example RFRAG Acknowledgment Bitmap

The RFRAG Acknowledgment Bitmap rides inside an RFRAG Acknowledgment header, shown in Figure 4 ๐Ÿงš:

                            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
                                       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                                       |1 1 1 0 1 0 1|E|  Datagram_Tag |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |          RFRAG Acknowledgment Bitmap (32 bits)                |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

          Figure 4: RFRAG Acknowledgment Dispatch Type and Header

Here's the breakdown ๐Ÿ’–:

  • E: 1 bit, Explicit Congestion Notification Echo. When it's set, the fragmenting endpoint learns that at least one of the acknowledged fragments arrived with an Explicit Congestion Notification. That means the path the fragments took is congested. See Appendix C for more details ๐ŸŒŠ.
  • Datagram_Tag: 8 bits, an identifier for the datagram that's locally unique to the link-layer recipient ๐ŸŒธ.
  • RFRAG Acknowledgment Bitmap: setting the bit at offset x means fragment x was received, as shown in Figure 2. A NULL bitmap means the fragmentation process is aborted ๐Ÿšซ. A FULL bitmap means the fragmentation process is complete, since every fragment reached the reassembling endpoint ๐ŸŽ‰.

6. Fragment Recovery โœจ

okay so the RFRAG header is basically the carrier for a fragment, and it can optionally ask for an RFRAG-ACK ๐Ÿ’Œ that says "yep, got these fragments" ๐Ÿซถ. An RFRAG-ACK is a standalone fragment header with no 6LoWPAN payload, and it travels back to the fragmenting endpoint. Every hop that did an MPLS-like operation on the fragments undoes it for the RFRAG-ACK by sending a frame from the next hop back to the previous hop, using the link-layer address it has stored in the VRB ๐Ÿฆ‹. The Datagram_Tag in the RFRAG-ACK is unique to the reassembling endpoint, and that's enough for an intermediate hop to find the VRB holding the Datagram_Tag the previous hop used, plus the Layer 2 info tied to it (interface and link-layer address). the way that's so clever ๐Ÿ˜ญ๐Ÿ”ฅ

The fragmenting endpoint (the node doing the 6LoWPAN-level fragmenting) is also the one in charge of how many acknowledgments you get, because it sets the Ack-Request flag in the RFRAG packets ๐Ÿ‘‘.

The fragmenting endpoint may set the Ack-Request flag on any fragment to do congestion control by capping the number of outstanding fragments, which means fragments that have been sent but whose reception or loss hasn't been positively confirmed by the reassembling endpoint ๐ŸŒธ. The cap is the Window-Size. It's configurable and may change when ECN notification shows up ๐Ÿ’…. When the reassembling endpoint gets a fragment with Ack-Request set, it MUST send an RFRAG-ACK back to the originator to confirm reception of all the fragments it has received so far ๐Ÿ’–.

The Ack-Request ("X") marks the end of a window ๐ŸŽ€. This flag MUST be set on the last fragment if the fragmenting endpoint wants to run an automatic repeat request (ARQ) process for the datagram, and it MAY be set on any intermediate fragment for congestion control reasons ๐Ÿงš.

This ARQ process MUST be protected by a Retransmission Timeout (RTO) timer ๐Ÿ“. The fragment carrying the "X" flag MAY be retried after a timeout, for a configurable number of times (see Section 7.1), with an exponential backoff โณ. Once the retries run out, the fragmenting endpoint may either abort the transmission of the datagram, or resend the first fragment with an "X" flag set. That second option is a glow-up move ๐Ÿ’œ: it establishes a new path for the datagram and gets the list of fragments that were received over the old path in the acknowledgment bitmap. And if the fragmenting endpoint knows an underlying link-layer mechanism already protects the fragments, it may skip the RFRAG Acknowledgment mechanism entirely and never set the Ack-Request bit ๐ŸŒˆ.

The reassembling endpoint MAY issue unsolicited acknowledgments ๐Ÿฆ‹. An unsolicited acknowledgment tells the fragmenting endpoint that it can start sending again if it had hit its maximum number of outstanding fragments. It can also let the fragmenting endpoint know that the reassembling endpoint aborted the processing of one particular datagram ๐Ÿ™ˆ.

The RFRAG Acknowledgment carries an ECN indication for congestion control (see Appendix C) โœจ. When the reassembling endpoint of a fragment with the "E" (ECN) flag set gets it, it MUST echo that info at most once, by setting the "E" (ECN) flag in the next RFRAG-ACK ๐Ÿซง.

To protect the datagram, the fragmenting endpoint sends a controlled number of fragments, and it puts an RFRAG Acknowledgment Request on the last fragment of each window ๐ŸŽฏ. The reassembling endpoint MUST acknowledge a fragment whose acknowledgment request bit is set ๐Ÿ’Œ. If any fragment right before an acknowledgment request is still missing, the reassembling endpoint MAY intentionally delay its acknowledgment so in-transit fragments have time to arrive ๐Ÿข. Heads up though: that can mess up the round-trip time computation, so delaying the acknowledgment should be configurable and not enabled by default โš ๏ธ.

Once enough fragments have arrived to cover the whole datagram, the reassembling endpoint rebuilds the packet, passes it up to the upper layer, sends an RFRAG-ACK on the reverse path with a FULL bitmap, and arms a short timer, for example on the order of an average round-trip time in the network โฑ๏ธ. The FULL bitmap is used instead of a bitmap that only acknowledges the fragments received, so the intermediate nodes know the datagram is fully received ๐Ÿซถ. While the timer runs, the reassembling endpoint absorbs the fragments still in flight for that datagram without creating new state, and it acknowledges the ones bearing an Ack-Request with an FRAG Acknowledgment and the FULL bitmap ๐Ÿงš. If fragments with a matching source and Datagram-Tag keep arriving after the timer expires, the reassembling endpoint aborts the communication ๐Ÿ›‘.

Acknowledgments can eat up precious resources, so the use of unsolicited acknowledgments SHOULD be configurable and not enabled by default ๐Ÿ’….

Here's the vibe: streamlining how fragments get forwarded generally cuts latency over the LLN mesh, which leaves room for retries inside the existing upper-layer reliability mechanisms ๐ŸŒธ. The fragmenting endpoint protects transmission over the LLN mesh with a retry timer configured for a particular use case, and that timer may be adjusted dynamically, for example using the method in [RFC6298] ๐Ÿ“. The upper-layer retry mechanism is expected to follow the recommendations in [RFC8085], and if it does, a single round of fragment recovery should fit inside the upper-layer recovery timers ๐Ÿ’–.

Fragments MUST be sent round-robin style: the sender MUST send all the fragments for the first time before it retries any lost fragment, and lost fragments MUST be retried in sequence, oldest first ๐Ÿ”. This lets the receiver acknowledge fragments that got delayed in the network before they're retried ๐ŸŽ€.

When a single radio frequency is used by contiguous hops, the fragmenting endpoint SHOULD insert a delay between the frames (for example, the ones carrying fragments) that go to the same next hop ๐ŸŒˆ. That delay SHOULD cover multiple transmissions, so a frame can progress a few hops and dodge hidden terminal issues ๐Ÿฆ‹. This precaution is not required on channel hopping technologies such as Time-Slotted Channel Hopping (TSCH) [RFC6554], where nodes communicating at Layer 2 are scheduled to send and receive, respectively, and different hops operate on different channels ๐Ÿงš.


6.1. Forwarding Fragments

This spec builds on [RFC8930] and proposes a Virtual Reassembly Buffer technique to forward fragments without reconstructing the whole datagram in the middle ๐Ÿ’œ.

The IPv6 header MUST be placed in full in the first fragment so the routing decision can happen ๐Ÿ‘‘. The first fragment gets routed and creates an LSP from the fragmenting endpoint to the reassembling endpoint ๐Ÿ›ฃ๏ธ. The next fragments get label switched along that LSP, which means they can only follow the path the first fragment set up. They can't take an alternate route ๐Ÿ™…โ€โ™€๏ธ. The Datagram_Tag carries the label, and the label gets swapped at each hop ๐Ÿ”„.

If the first fragment is too large for the path MTU, it'll keep failing and never set up an LSP ๐Ÿ˜ฉ. In that case, the fragmenting endpoint MAY retry the same datagram with a smaller Fragment_Size, and when it does, it MUST abort the original attempt and use a new Datagram_Tag for the new attempt ๐ŸŒŸ.

6.1.1. Receiving the First Fragment

In route-over mode, the source and destination link-layer addresses in a frame change at each hop ๐Ÿ—บ๏ธ. The label the sender forms and puts in the Datagram_Tag is tied to the source link-layer address, and it's only valid (and temporarily unique) for that source link-layer address ๐ŸŽŸ๏ธ.

When an intermediate router gets the first fragment (the one with a Sequence of 0), it creates a VRB and the matching LSP state, indexed by the incoming interface, the previous-hop link-layer address, and the Datagram_Tag ๐Ÿ“ฆ. Then it forwards the fragment along the IPv6 route matching the destination IPv6 address in the IPv6 header, until it reaches the reassembling endpoint, as prescribed by [RFC8930] โœˆ๏ธ. The LSP state lets the router match the next incoming fragments of a datagram to the abstract forwarding info of the next interface, source and next-hop link-layer addresses, and the swapped Datagram_Tag ๐Ÿงฉ.

The router also builds a reverse LSP state, indexed by the interface to the next hop, the link-layer address the router uses as source for that datagram, and the swapped Datagram_Tag ๐Ÿ”™. This reverse state lets the router match the tuple (interface, destination link-layer address, Datagram_Tag) found in an RFRAG-ACK to the abstract forwarding info (previous interface, previous link-layer address, Datagram_Tag) used to send the RFRAG-ACK back to the fragmenting endpoint ๐Ÿ’ซ.

6.1.2. Receiving the Next Fragments

When an intermediate router gets the next fragment (one with a non-zero Sequence), it looks up an LSP indexed by the tuple (incoming interface, previous-hop link-layer address, Datagram_Tag) found in the fragment ๐Ÿ”Ž. If it finds one, the router forwards the fragment using the associated VRB, as prescribed by [RFC8930] ๐Ÿ’Œ.

If the router can't find a VRB for that tuple, it builds an RFRAG-ACK to abort the transmission of the packet ๐Ÿšซ. The resulting message has the following info:

  • The source and destination link-layer addresses are swapped from the ones found in the fragment, and the same interface is used
  • The Datagram_Tag is set to the Datagram_Tag found in the fragment
  • A NULL bitmap is used to signal the abort condition

At this point the router is all set and can send the RFRAG-ACK back to the previous router ๐Ÿซก. The RFRAG-ACK should normally be forwarded all the way to the source, using the reverse LSP state in the VRBs of the intermediate routers, as described in the next section ๐Ÿ›ค๏ธ.

[RFC8930] says the reassembling endpoint stores "the actual packet data from the fragments received so far, in a form that makes it possible to detect when the whole packet has been received and can be processed or forwarded" ๐Ÿ“š. How that's computed is implementation specific, but it relies on receiving all the bytes up to the Datagram_Size indicated in the first fragment ๐Ÿงฎ. An implementation may receive overlapping fragments as the result of retries after an MTU change ๐ŸŒˆ.

6.2. Receiving RFRAG Acknowledgments โœจ

okay so when an RFRAG-ACK shows up, the router looks for a reverse LSP ๐Ÿงš that matches the interface and the destination link-layer address of the frame it came in on, plus the Datagram_Tag inside the RFRAG-ACK. If it finds one, it forwards the fragment using the associated VRB, just like [RFC8930] says, except it uses the reverse LSP so the RFRAG-ACK flows back to the fragmenting endpoint. main character routing ๐Ÿ’…

If the reverse LSP is not found, the router MUST silently drop the RFRAG-ACK message. no drama, just gone ๐Ÿซฅ

Either way, if the RFRAG-ACK says the fragment was entirely received (the FULL bitmap), the router arms a short timer. When that timer goes off, the VRB and all the associated states are destroyed ๐Ÿ’€. Until the timer runs out, fragments of that datagram can still show up. This happens if the RFRAG-ACK got lost on the way back and the source retried the last fragment ๐Ÿ™ˆ. In that case, the router generates an RFRAG-ACK with a FULL bitmap back to the fragmenting endpoint if an acknowledgment was requested. If not, it silently drops the fragment.

This specification does not provide a method to discover the number of hops or the minimal value of MTU along those hops. In a typical case, the MTU is constant and is the same across the network ๐ŸŒธ. But should the minimal MTU along the path decrease, it is possible to retry a long fragment (say a Sequence of 5) with several shorter fragments that use a Sequence not used before (e.g., 13 and 14). Fragment 5 is marked as abandoned and will not be retried anymore ๐Ÿซถ. Note that when this mechanism is in place, it is hard to predict the total number of fragments that will be needed or the final shape of the bitmap that would cover the whole packet. This is why the FULL bitmap is used when the reassembling endpoint gets the whole datagram, regardless of which fragments were actually used to do so. Intermediate nodes will know unambiguously that the process is complete โœจ. Note that Path MTU Discovery is out of scope for this document.

6.3. Aborting the Transmission of a Fragmented Packet

A reset is signaled on the forward path with a pseudo fragment that has the Fragment_Offset set to 0. The sender of a reset SHOULD also set the Sequence and Fragment_Size fields to 0 ๐ŸŽ€.

When the fragmenting endpoint or a router on the path decides that a packet should be dropped and the fragmentation process aborted, it generates a reset pseudo fragment and forwards it down the fragment path ๐Ÿฅ€.

Each router along the path forwards the pseudo fragment in turn, based on the VRB state. If an acknowledgment is not requested, the VRB and all associated states are destroyed ๐Ÿงน.

When the reassembling endpoint receives the pseudo fragment, it cleans up all resources for the packet associated with the Datagram_Tag. If an acknowledgment is requested, the reassembling endpoint responds with a NULL bitmap ๐Ÿ™Œ.

On the other hand, the reassembling endpoint might need to abort the processing of a fragmented packet for internal reasons. For instance, it might be out of reassembly buffers, it might already be using all 256 possible values of the Datagram_Tag, or it might keep receiving fragments long after a reasonable time, even though it thinks this packet is already fully reassembled and was passed to the upper layer ๐Ÿ˜ค. In that case, the reassembling endpoint SHOULD indicate so to the fragmenting endpoint with a NULL bitmap in an RFRAG-ACK.

The RFRAG-ACK is forwarded all the way back to the source of the packet, and it cleans up all resources on the path ๐Ÿงผ. Upon an acknowledgment with a NULL bitmap, the fragmenting endpoint MUST abort the transmission of the fragmented datagram, with one exception. In the particular case of the first fragment, it MAY decide to retry via an alternate next hop instead ๐Ÿฆ‹.

6.4. Applying Recoverable Fragmentation along a Diverse Path

Everything above can be read with the assumption of a serial path between a source and a destination ๐Ÿ›ค๏ธ. But the IPv6 over the TSCH mode of IEEE 802.15.4e (6TiSCH) architecture (see Section 4.5.3 of [6TiSCH]) defines the concept of a Track. A Track can be a complex path between a source and a destination, with Packet ARQ, Replication, Elimination, and Overhearing (PAREO) along the Track ๐ŸŒˆ. This specification can be used along any subset of the complex Track where the first fragment is flooded. The last RFRAG Acknowledgment is flooded on that same subset in the reverse direction. Intermediate RFRAG Acknowledgments can be flooded on any sub-subset of that reverse subset that reaches back to the source ๐Ÿซง.

7. Management Considerations โญ

This specification extends [RFC8930] and requires the same parameters in the reassembling endpoint and on intermediate nodes. There is no new parameter, because echoing ECN is always on ๐Ÿ”ฅ. These parameters typically include the reassembly timeout at the reassembling endpoint, an inactivity cleanup timer on the intermediate nodes, and the number of messages that can be processed in parallel in all nodes.

The configuration settings introduced by this specification only apply to the fragmenting endpoint, which is in full control of the transmission. LLNs vary a lot. They can have thousands of nodes in a mesh, they can run in speeds from 10 Kbps to several Mbps at the PHY layer, they can have very different traffic densities, and they can want very different optimizations. For example, the selection of a Routing Protocol for LLNs (RPL) [RFC6550] Objective Function [RFC6552] impacts the shape of the routing graph ๐Ÿ•ธ๏ธ.

For that reason, only very generic guidance can be given on the settings of the fragmenting endpoint. The same goes for whether complex algorithms are needed to perform congestion control or to estimate the round-trip time ๐Ÿค”. To cover the most complex use cases, this specification enables the fragmenting endpoint to vary the fragment size, the window size, and the inter-frame gap based on the number of losses, the observed variations of the round-trip time, and the setting of the ECN bit ๐Ÿ’œ.

7.1. Protocol Parameters ๐Ÿ’–

okay bestie, the management system SHOULD be capable of providing the parameters in this section โœจ and an implementation MUST abide by those parameters and, like, never exceed the minimum and maximum configured boundaries ๐Ÿ™…โ€โ™€๏ธ no exceptions!!

an implementation should look at the generic recs from the IETF on congestion control and rate management for IP datagrams in [RFC8085] ๐Ÿซถ an implementation may do congestion control by using a dynamic value of Window_Size, adapting Fragment_Size, and possibly lowering the load by adding an inter-frame gap that's longer than it needs to be ๐ŸŒˆ in a big network where nodes fight over bandwidth, a larger Fragment_Size uses less bandwidth but also hurts fluidity and has a higher chance of getting lost in transmission ๐Ÿ˜ญ

these are controlled by the following parameters:

inter-frame gap

the inter-frame gap is the minimum amount of time between transmissions โฑ๏ธ it controls how fast fragments get sent, the ratio of air time, and how much memory intermediate nodes use for a particular datagram ๐Ÿง  it can be used as flow control, congestion control, and/or collision control, which is honestly so versatile ๐Ÿ’… it MUST be set at a minimum to a value that protects the propagation of one transmission against collision with the next [RFC8930] ๐Ÿ”ฅ in a wireless network that uses the same frequency along a path, this might be the time for a frame to make its way over multiple hops (more on that in Section 4.2) ๐Ÿฆ‹ it SHOULD be augmented beyond this as needed to protect the network against congestion โœจ

MinFragmentSize

MinFragmentSize is the minimum value for the Fragment_Size ๐ŸŽ€ it MUST be lower than the minimum value of smallest 1-hop MTU that can be encountered along the path ๐Ÿ™ˆ

OptFragmentSize

OptFragmentSize is the value for the Fragment_Size that the fragmenting endpoint should start with ๐ŸŒธ it is greater than or equal to MinFragmentSize and less than or equal to MaxFragmentSize ๐Ÿ’œ for the first fragment, it must account for the expansion of the IPv6 addresses and of the Hop Limit field within the MTU ๐Ÿงš for all fragments, it's a balance between the expected fluidity and the overhead of link-layer and 6LoWPAN headers โš–๏ธ for a small MTU, the idea is to keep it close to the maximum, but for larger MTUs it might make sense to keep it short enough that the duty cycle of the transmitter stays bounded, e.g., to transmit at least 10 frames per second ๐Ÿ“

MaxFragmentSize

MaxFragmentSize is the maximum value for the Fragment_Size ๐Ÿšซ it MUST be lower than the maximum value of the smallest 1-hop MTU that can be encountered along the path ๐Ÿ’€ a large value ups the chances of buffer bloat and transmission loss, so be careful!! ๐Ÿ˜ฌ the value MUST be less than 512 if the unit that is defined for the PHY layer is the byte ๐Ÿ”ฅ

Window_Size

Window_Size MUST be at least 1 and less than 33 ๐Ÿฆ„

  • If the round-trip time is known, the Window_Size SHOULD be set to the round-trip time divided by the time per fragment, which is the time to transmit a fragment plus the inter-frame gap ๐Ÿงฎ

Otherwise:

  • A window_size of 32 means that only the last fragment is acknowledged in each round ๐Ÿซง this is the RECOMMENDED value in a half-duplex LLN, where the fragment acknowledgment eats roughly the same bandwidth on the same links as the fragments themselves ๐Ÿ™ƒ
  • If it's set to a smaller value, more acks get generated ๐Ÿ“ฌ in a full-duplex network, the load on the forward path will be lower, and a small value of 3 SHOULD be configured ๐ŸŒˆ

an implementation may do its own estimate of the RTO or use a configured one โณ the ARQ process is controlled by the following parameters:

MinARQTimeOut

MinARQTimeOut is the minimum amount of time a node should wait for an RFRAG Acknowledgment before it takes the next action ๐Ÿ•ฐ๏ธ it MUST be more than the maximum expected round-trip time in the respective network ๐ŸŒŸ

OptARQTimeOut

OptARQTimeOut is the initial value of the RTO, which is the amount of time that a fragmenting endpoint should wait for an RFRAG Acknowledgment before it takes the next action ๐ŸŽฏ it is greater than or equal to MinARQTimeOut and less than or equal to MaxARQTimeOut ๐Ÿ’– see Appendix C for recs on computing the round-trip time ๐Ÿ“– by default, a value of 3 times the maximum expected round-trip time in the respective network is RECOMMENDED โœจ

MaxARQTimeOut

MaxARQTimeOut is the maximum amount of time a node should wait for the RFRAG Acknowledgment before it takes the next action โฐ it must cover the longest expected round-trip time and be several times less than the timeout that covers the recomposition buffer at the reassembling endpoint, which is typically on the order of the minute ๐Ÿซ  an upper bound can be estimated so the datagram is either fully transmitted or dropped before an upper layer decides to retry it ๐ŸŽ€

MaxFragRetries

MaxFragRetries is the maximum number of retries for a particular fragment ๐Ÿ” a default value of 3 is RECOMMENDED ๐Ÿ’… an upper bound can be estimated so the datagram is either fully transmitted or dropped before an upper layer decides to retry it ๐ŸŒธ

MaxDatagramRetries

MaxDatagramRetries is the maximum number of retries from scratch for a particular datagram ๐Ÿช„ a default value of 1 is RECOMMENDED ๐Ÿ™Œ an upper bound can be estimated so the datagram is either fully transmitted or dropped before an upper layer decides to retry it ๐Ÿซถ

an implementation may be capable of doing congestion control based on ECN, see Appendix C ๐ŸŒŠ this is controlled by the following parameter:

UseECN

UseECN indicates whether the fragmenting endpoint should react to ECN ๐Ÿšฆ the fragmenting endpoint may react to ECN by varying the Window_Size between MinWindowSize and MaxWindowSize, varying the Fragment_Size between MinFragmentSize and MaxFragmentSize, and/or increasing or reducing the inter-frame gap ๐ŸŽ›๏ธ with this specification, if UseECN is set and a fragmenting endpoint detects a congestion, it may apply a congestion control method until the end of the datagram ๐ŸŒˆ whereas if UseECN is reset, the endpoint does not react to congestion ๐Ÿ™…โ€โ™€๏ธ future specifications may provide additional parameters and capabilities ๐Ÿ”ฎ


7.2. Observing the Network ๐Ÿ‘€

the management system should monitor the number of retries and ECN settings that can be observed from the perspective of the fragmenting endpoint with respect to the reassembling endpoint, and reciprocally ๐Ÿ” it may then tune the optimum size of Fragment_Size and of Window_Size, OptFragmentSize, and OptWindowSize, respectively, at the fragmenting endpoint toward a particular reassembling endpoint, which applies to the next datagrams ๐Ÿ“ˆ it will preferably tune the inter-frame gap to increase the spacing between fragments of the same datagram and reduce the buffer bloat in the intermediate node that holds one or more fragments of that datagram ๐Ÿซงโœจ


8. Security Considerations ๐Ÿ”

this document specifies an instantiation of a 6LFF technique and inherits from the generic description in [RFC8930] ๐Ÿ›ก๏ธ the considerations in the Security Considerations section of [RFC8930] equally apply to this document ๐Ÿซก

in addition to the threats detailed there, an attacker that is on path can prematurely end the transmission of a datagram by sending an RFRAG Acknowledgment to the fragmenting endpoint ๐Ÿ˜ฑ it can also cause extra transmissions of fragments by resetting bits in the RFRAG Acknowledgment Bitmap, and of RFRAG Acknowledgments by forcing the Ack-Request bit in fragments that it forwards ๐Ÿšจ

as indicated in [RFC8930], secure joining and link-layer security are REQUIRED to protect against those attacks, because the fragmentation protocol does not include any native security mechanisms ๐Ÿ”’ this is non-negotiable, bestie ๐Ÿ’€

this specification does not recommend a particular algorithm for estimating the duration of the RTO that covers the detection of the loss of a fragment with the "X" flag set ๐Ÿซฃ regardless, an attacker on the path may slow down or discard packets, which in turn can affect the throughput of fragmented packets ๐Ÿฅ€

compared to [RFC4944], this specification reduces the Datagram_Tag to 8 bits, and the tag wraps faster than with [RFC4944] ๐ŸŒ€ but for a constrained network where a node is expected to hold only one or a few large packets in memory, 256 is still a large number ๐Ÿ”ข also, the acknowledgment mechanism lets you clean up state rapidly once the packet is fully transmitted or aborted ๐Ÿงน

the abstract Virtual Recovery Buffer from [RFC8930] may be used to perform a Denial-of-Service (DoS) attack against the intermediate routers, since the routers need to maintain state per flow ๐Ÿšง the particular VRB implementation technique described in [LWIG-FRAG] allows realigning which data goes in which fragment, which causes the intermediate node to store a portion of the data and adds an attack vector that is not present with this specification ๐Ÿ˜ฌ with this specification, the data transported in each fragment is conserved, and the state to keep does not include any data that would not fit in the previous fragment ๐Ÿ’–


9. IANA Considerations ๐ŸŒธ

this document allocates two patterns for a total of four dispatch values for Recoverable Fragments from the "Dispatch Type Field" registry that was created by [RFC4944] and reformatted by "IPv6 over Low-Power Wireless Personal Area Network (6LoWPAN) Paging Dispatch" [RFC8025] ๐Ÿ—‚๏ธ

+-------------+------+----------------------------------+-----------+
| Bit Pattern | Page | Header Type                      | Reference |
+-------------+------+----------------------------------+-----------+
| 11 10100x   | 0    | RFRAG - Recoverable Fragment     | RFC 8931  |
+-------------+------+----------------------------------+-----------+
| 11 10100x   | 1-14 | Unassigned                       |           |
+-------------+------+----------------------------------+-----------+
| 11 10100x   | 15   | Reserved for Experimental Use    | RFC 8025  |
+-------------+------+----------------------------------+-----------+
| 11 10101x   | 0    | RFRAG-ACK - RFRAG                | RFC 8931  |
|             |      | Acknowledgment                   |           |
+-------------+------+----------------------------------+-----------+
| 11 10101x   | 1-14 | Unassigned                       |           |
+-------------+------+----------------------------------+-----------+
| 11 10101x   | 15   | Reserved for Experimental Use    | RFC 8025  |
+-------------+------+----------------------------------+-----------+

Table 1: Additional Dispatch Value Bit Patterns ๐Ÿ“Š


10. References ๐Ÿ“š

10.1. Normative References

Okay bestie, these are the must-read sources the spec builds on ๐Ÿ“šโœจ Here are the exact details so you can look them up:

   [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>.

   [RFC4919]  Kushalnagar, N., Montenegro, G., and C. Schumacher, "IPv6
              over Low-Power Wireless Personal Area Networks (6LoWPANs):
              Overview, Assumptions, Problem Statement, and Goals",
              RFC 4919, DOI 10.17487/RFC4919, August 2007,
              <https://www.rfc-editor.org/info/rfc4919>.

   [RFC4944]  Montenegro, G., Kushalnagar, N., Hui, J., and D. Culler,
              "Transmission of IPv6 Packets over IEEE 802.15.4
              Networks", RFC 4944, DOI 10.17487/RFC4944, September 2007,
              <https://www.rfc-editor.org/info/rfc4944>.

   [RFC6282]  Hui, J., Ed. and P. Thubert, "Compression Format for IPv6
              Datagrams over IEEE 802.15.4-Based Networks", RFC 6282,
              DOI 10.17487/RFC6282, September 2011,
              <https://www.rfc-editor.org/info/rfc6282>.

   [RFC6298]  Paxson, V., Allman, M., Chu, J., and M. Sargent,
              "Computing TCP's Retransmission Timer", RFC 6298,
              DOI 10.17487/RFC6298, June 2011,
              <https://www.rfc-editor.org/info/rfc6298>.

   [RFC6606]  Kim, E., Kaspar, D., Gomez, C., and C. Bormann, "Problem
              Statement and Requirements for IPv6 over Low-Power
              Wireless Personal Area Network (6LoWPAN) Routing",
              RFC 6606, DOI 10.17487/RFC6606, May 2012,
              <https://www.rfc-editor.org/info/rfc6606>.

   [RFC8025]  Thubert, P., Ed. and R. Cragie, "IPv6 over Low-Power
              Wireless Personal Area Network (6LoWPAN) Paging Dispatch",
              RFC 8025, DOI 10.17487/RFC8025, November 2016,
              <https://www.rfc-editor.org/info/rfc8025>.

   [RFC8138]  Thubert, P., Ed., Bormann, C., Toutain, L., and R. Cragie,
              "IPv6 over Low-Power Wireless Personal Area Network
              (6LoWPAN) Routing Header", RFC 8138, DOI 10.17487/RFC8138,
              April 2017, <https://www.rfc-editor.org/info/rfc8138>.

   [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>.

   [RFC8200]  Deering, S. and R. Hinden, "Internet Protocol, Version 6
              (IPv6) Specification", STD 86, RFC 8200,
              DOI 10.17487/RFC8200, July 2017,
              <https://www.rfc-editor.org/info/rfc8200>.

   [RFC8930]  Watteyne, T., Ed., Thubert, P., Ed., and C. Bormann, "On
              Forwarding 6LoWPAN (IPv6 over Low-Power Wireless Personal
              Area Network) Fragments over a Multi-Hop IPv6 Network",
              RFC 8930, DOI 10.17487/RFC8930, November 2020,
              <https://www.rfc-editor.org/info/rfc8930>.

10.2. Informative References

These ones are the extra reading for the curious ๐Ÿงš They give background and context, and you don't need them to get the core spec:

   [6TiSCH]   Thubert, P., "An Architecture for IPv6 over the TSCH mode
              of IEEE 802.15.4", Work in Progress, Internet-Draft,
              draft-ietf-6tisch-architecture-29, 27 August 2020,
              <https://tools.ietf.org/html/draft-ietf-6tisch-
              architecture-29>.

   [IEEE.802.15.4]
              IEEE, "IEEE Standard for Low-Rate Wireless Networks",
              IEEE Standard 802.15.4-2015,
              DOI 10.1109/IEEESTD.2016.7460875, April 2016,
              <http://ieeexplore.ieee.org/document/7460875/>.

   [Kent]     Kent, C. and J. Mogul, "Fragmentation Considered Harmful",
              SIGCOMM '87: Proceedings of the ACM workshop on Frontiers
              in computer communications technology, pp. 390-401,
              DOI 10.1145/55483.55524, August 1987,
              <http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-
              87-3.pdf>.

   [LWIG-FRAG]
              Bormann, C. and T. Watteyne, "Virtual reassembly buffers
              in 6LoWPAN", Work in Progress, Internet-Draft, draft-ietf-
              lwig-6lowpan-virtual-reassembly-02, 9 March 2020,
              <https://tools.ietf.org/html/draft-ietf-lwig-6lowpan-
              virtual-reassembly-02>.

   [RFC2914]  Floyd, S., "Congestion Control Principles", BCP 41,
              RFC 2914, DOI 10.17487/RFC2914, September 2000,
              <https://www.rfc-editor.org/info/rfc2914>.

   [RFC3031]  Rosen, E., Viswanathan, A., and R. Callon, "Multiprotocol
              Label Switching Architecture", RFC 3031,
              DOI 10.17487/RFC3031, January 2001,
              <https://www.rfc-editor.org/info/rfc3031>.

   [RFC3168]  Ramakrishnan, K., Floyd, S., and D. Black, "The Addition
              of Explicit Congestion Notification (ECN) to IP",
              RFC 3168, DOI 10.17487/RFC3168, September 2001,
              <https://www.rfc-editor.org/info/rfc3168>.

   [RFC4963]  Heffner, J., Mathis, M., and B. Chandler, "IPv4 Reassembly
              Errors at High Data Rates", RFC 4963,
              DOI 10.17487/RFC4963, July 2007,
              <https://www.rfc-editor.org/info/rfc4963>.

   [RFC5033]  Floyd, S. and M. Allman, "Specifying New Congestion
              Control Algorithms", BCP 133, RFC 5033,
              DOI 10.17487/RFC5033, August 2007,
              <https://www.rfc-editor.org/info/rfc5033>.

   [RFC5681]  Allman, M., Paxson, V., and E. Blanton, "TCP Congestion
              Control", RFC 5681, DOI 10.17487/RFC5681, September 2009,
              <https://www.rfc-editor.org/info/rfc5681>.

   [RFC6550]  Winter, T., Ed., Thubert, P., Ed., Brandt, A., Hui, J.,
              Kelsey, R., Levis, P., Pister, K., Struik, R., Vasseur,
              JP., and R. Alexander, "RPL: IPv6 Routing Protocol for
              Low-Power and Lossy Networks", RFC 6550,
              DOI 10.17487/RFC6550, March 2012,
              <https://www.rfc-editor.org/info/rfc6550>.

   [RFC6552]  Thubert, P., Ed., "Objective Function Zero for the Routing
              Protocol for Low-Power and Lossy Networks (RPL)",
              RFC 6552, DOI 10.17487/RFC6552, March 2012,
              <https://www.rfc-editor.org/info/rfc6552>.

   [RFC6554]  Hui, J., Vasseur, JP., Culler, D., and V. Manral, "An IPv6
              Routing Header for Source Routes with the Routing Protocol
              for Low-Power and Lossy Networks (RPL)", RFC 6554,
              DOI 10.17487/RFC6554, March 2012,
              <https://www.rfc-editor.org/info/rfc6554>.

   [RFC7554]  Watteyne, T., Ed., Palattella, M., and L. Grieco, "Using
              IEEE 802.15.4e Time-Slotted Channel Hopping (TSCH) in the
              Internet of Things (IoT): Problem Statement", RFC 7554,
              DOI 10.17487/RFC7554, May 2015,
              <https://www.rfc-editor.org/info/rfc7554>.

   [RFC7567]  Baker, F., Ed. and G. Fairhurst, Ed., "IETF
              Recommendations Regarding Active Queue Management",
              BCP 197, RFC 7567, DOI 10.17487/RFC7567, July 2015,
              <https://www.rfc-editor.org/info/rfc7567>.

   [RFC8085]  Eggert, L., Fairhurst, G., and G. Shepherd, "UDP Usage
              Guidelines", BCP 145, RFC 8085, DOI 10.17487/RFC8085,
              March 2017, <https://www.rfc-editor.org/info/rfc8085>.

   [RFC8087]  Fairhurst, G. and M. Welzl, "The Benefits of Using
              Explicit Congestion Notification (ECN)", RFC 8087,
              DOI 10.17487/RFC8087, March 2017,
              <https://www.rfc-editor.org/info/rfc8087>.

   [RFC8201]  McCann, J., Deering, S., Mogul, J., and R. Hinden, Ed.,
              "Path MTU Discovery for IP version 6", STD 87, RFC 8201,
              DOI 10.17487/RFC8201, July 2017,
              <https://www.rfc-editor.org/info/rfc8201>.

   [RFC8900]  Bonica, R., Baker, F., Huston, G., Hinden, R., Troan, O.,
              and F. Gont, "IP Fragmentation Considered Fragile",
              BCP 230, RFC 8900, DOI 10.17487/RFC8900, September 2020,
              <https://www.rfc-editor.org/info/rfc8900>.

Appendix A. Rationale ๐ŸŒธ

Okay so large packets in Wireless Sensor Networks aren't the everyday vibe, but there are actually a bunch of uses for them ๐Ÿฆ‹ These usages might not be the most typical or make up the biggest chunk of traffic over the LLN. Still, the functionality they support can be so important that it's worth extra care to get large packets across the LLN properly ๐Ÿ’…

The list of those usages includes:

Towards the LLN node:

  • Firmware update ๐Ÿ”ฅ: For example, a new version of the LLN node software is downloaded from a system manager over unicast or multicast services. Such a reflashing operation typically involves updating a large number of similar LLN nodes over a relatively short period of time.
  • Packages of commands ๐Ÿ“ฆ: A number of commands or a full configuration can be packaged as a single message to ensure consistency and enable atomic execution or complete rollback. Until such commands are fully received and interpreted, the intended operation will not take effect.

From the LLN node:

  • Waveform captures ๐ŸŒŠ: A number of consecutive samples are measured at a high rate for a short time and then are transferred from a sensor to a gateway or an edge server as a single large report.
  • Data logs ๐Ÿงพ: LLN nodes may generate large logs of sampled data for later extraction. LLN nodes may also generate system logs to assist in diagnosing problems on the node or network.
  • Large data packets ๐Ÿ’–: Rich data types might require more than one fragment.

Uncontrolled firmware download or waveform upload can easily result in a massive increase of the traffic and saturate the network. Not it. ๐Ÿ™ˆ

When a fragment is lost in transmission, the lack of recovery in the original fragmentation system of RFC 4944 implies that all fragments would need to be resent. That further contributes to the congestion that caused the initial loss and potentially leads to congestion collapse ๐Ÿ’€

This saturation may lead to excessive radio interference or random early discard (leaky bucket) in relaying nodes. Additional queuing and memory congestion may result while waiting for a low-power next hop to emerge from its sleep state ๐Ÿ˜ญ

Considering that RFC 4944 defines an MTU as 1280 bytes, and that in most incarnations (except 802.15.4g) an IEEE Std 802.15.4 frame can limit the link-layer payload to as few as 74 bytes, a packet might be fragmented into at least 18 fragments at the 6LoWPAN shim layer. Taking into account the worst-case header overhead for 6LoWPAN Fragmentation and Mesh Addressing headers will increase the number of required fragments to around 32. This level of fragmentation is much higher than what's traditionally experienced over the Internet with IPv4 fragments. At the same time, the use of radios increases the probability of transmission loss, and mesh-under techniques compound that risk over multiple hops โœจ

Mechanisms such as TCP or application-layer segmentation could be used to support end-to-end reliable transport. One option to support bulk data transfer over a frame-size-constrained LLN is to set the Maximum Segment Size to fit within the link maximum frame size. However, doing so can add significant header overhead to each 802.15.4 frame and cause extraneous acknowledgments across the LLN compared to the method in this specification ๐ŸŽ€

Appendix B. Requirements โœจ

okay bestie, so for one-hop stuff a bunch of LLN link layers already have a local acknowledgment mechanism that's honestly enough to spot and recover lost fragments ๐Ÿฆ‹. But in a multi-hop setup, an end-to-end fragment recovery mechanism can be a really good sidekick to hop-by-hop Medium Access Control (MAC) recovery ๐Ÿ’–. So this doc brings in a simple protocol to recover individual fragments between 6LFF endpoints that might be multiple hops away ๐ŸŒธ.

The method is built around these LLN requirements, and it's giving very specific vibes ๐Ÿ‘‘:

  • Number of fragments: the recovery mechanism must support highly fragmented packets, with a maximum of 32 fragments per packet ๐Ÿงš.
  • Minimum acknowledgment overhead: the radio is half duplex, and there's silent time spent in the various medium access mechanisms, so an acknowledgment eats up roughly as many resources as a data fragment ๐Ÿ˜ญ. The new end-to-end fragment recovery mechanism should be able to acknowledge multiple fragments in a single message, and it should not require an acknowledgment at all if fragments are already protected at a lower layer ๐Ÿ’….
  • Controlled latency: the recovery mechanism must succeed or give up within the time boundary imposed by the recovery process of the upper-layer protocols โฐ.
  • Optional congestion control: when lots of concurrent flows aggregate, the radio network can get saturated and tip into congestion collapse ๐Ÿ’€. The recovery mechanism should provide means for controlling the number of fragments in transit over the LLN ๐Ÿซถ.

Appendix C. Considerations on Congestion Control ๐ŸŒˆ

So a multi-hop LLN is a super sensitive environment, because a large population of its nodes has limited queuing capabilities ๐Ÿฅบ. That's why this document recommends a simple and conservative approach to congestion control, based on TCP congestion avoidance ๐ŸŽ€.

Congestion on the forward path is assumed in case of packet loss, and packet loss is assumed upon timeout โณ. This document lets you control the number of outstanding fragments, meaning the ones that have been transmitted, haven't been acknowledged yet, and are still covered by the ARQ timer ๐Ÿฆ‹.

Congestion on the forward path can also be indicated by an ECN mechanism ๐ŸŒธ. Whether and how ECN [RFC3168] is carried out over the LoWPAN is out of scope, though ๐Ÿ™ˆ. What this document does provide is a way for the destination endpoint to echo an ECN indication back to the fragmenting endpoint in an acknowledgment message, as shown in Figure 4 in Section 5.2 ๐Ÿ’–.

Echoing ECN at the reassembling endpoint is mandatory ๐Ÿ”ฅ. The fragmenting side, though, only gets minimalistic behavior in this spec. If an "E" flag is received, the window SHOULD be reduced at least by 1 and at max to 1 โœจ. Halving the window for each "E" flag received could be a good compromise, but it needs further experimentation ๐Ÿงช. A very simple implementation may just reset the window to 1, so the fragments are sent and acknowledged one by one ๐Ÿ“.

Also, any action taken upon detecting congestion only applies to the transmission of one datagram ๐Ÿ’…. The next datagram starts with the configured Window_Size again ๐ŸŒท.

The exact use of the Acknowledgment Request flag and of the window is left to implementation ๐Ÿซง. An optimistic implementation could send all the fragments up to Window_Size, setting the Acknowledgment Request "X" flag only on the last fragment ๐Ÿš€. Then it waits for the bitmap, which means a gap of half a round-trip time, and resends the losses ๐Ÿ˜ค. A pessimistic implementation could set the "X" flag on the first fragment to check that the path works, and only open the window upon receiving the RFRAG-ACK ๐Ÿข. It could then set an "X" flag again on the second fragment and use the window as a credit to send up to Window_Size before it gets blocked ๐Ÿ’œ. In that case, if the RFRAG-ACK comes back before the window starves, the gating factor is the inter-frame gap โญ. If the RFRAG-ACK doesn't arrive in time, the Window_Size is the gating factor, and the transmission of the datagram is delayed ๐Ÿ˜ฉ.

Now here's the plot twist ๐ŸŽญ: even though the inter-frame gap can be used as a flow control or congestion control measure, it also plays a critical role in wireless collision avoidance ๐Ÿšฆ. When a mesh operates on the same channel over multiple hops, forwarding one fragment over a certain hop may collide with forwarding the next fragment, which is following over a previous hop but sits in the same interference domain ๐Ÿ’ฅ. To prevent this, the fragmenting endpoint is required to pace individual fragments within a transmit window with an inter-frame gap ๐Ÿ•ฐ๏ธ. This makes sure a given fragment is only sent once the previous fragment has had a chance to progress beyond the interference domain of this hop ๐ŸŒŠ. For 6TiSCH [6TiSCH], which operates over the Time-Slotted Channel Hopping (TSCH) mode of operation of IEEE 802.15.4 [RFC7554], a fragment is forwarded over a different channel at a different time ๐ŸŽถ. So it makes full sense to transmit the next fragment as soon as the previous fragment has had its chance to be forwarded at the next hop ๐Ÿ™Œ.

Depending on the setting of the Window_Size and the inter-frame gap, how the window is used, and the number of hops, the Window_Size may or may not become the gating factor that blocks transmission ๐Ÿคทโ€โ™€๏ธ. If the sender uses the Window_Size as a credit:

  • a conservative Window_Size of, say, 3 will be the gating factor that limits the transmission rate of the sender, and causes transmission gaps longer than the inter-frame gap, as soon as the number of hops exceeds 3 in a TSCH network and 5-9 in a single frequency mesh ๐ŸŒ. The more hops, the more the starving window will add to the latency of the transmission ๐Ÿ˜ต.
  • Aligning the Window-Size to the round-trip time divided by the time per fragment is recommended, because it lines the Window-Size up with the time it takes to get the RFAG_ACK back before the window starves โฑ๏ธ. A Window-Size higher than that increases the chances of congestion but doesn't improve the forward throughput ๐Ÿ“‰. Since the RFRAG-ACK takes the same path as the fragment, with the assumption that it travels at roughly the same speed, an inter-frame gap that separates fragments by 2 hops leads to a Window_Size that is roughly the number of hops ๐Ÿง .
  • Setting the Window-Size to 32 minimizes the cost of the acknowledgment in a constrained network and frees bandwidth for the fragments in a half-duplex network ๐Ÿ™Œ. Using it increases the risk of congestion if a bottleneck forms, but it optimizes the use of resources under normal conditions ๐Ÿ’ซ. When it's used, the only protection for the network is the inter-frame gap, which must be chosen wisely to prevent a bottleneck from forming ๐Ÿ›ก๏ธ.

From the standpoint of a source 6LoWPAN endpoint, an outstanding fragment is one that was sent but for which no explicit acknowledgment has been received yet ๐Ÿ“ฌ. That means the fragment might still be on the path, received but not yet acknowledged, or the acknowledgment might be on its way back ๐Ÿ”™. It's also possible that either the fragment or the acknowledgment was lost on the way ๐Ÿ˜ฟ.

From the fragmenting endpoint's standpoint, all outstanding fragments might still be in the network and contributing to its congestion ๐ŸŒซ๏ธ. There's an assumption, though, that after a certain amount of time, a frame is either received or lost, so it's no longer causing congestion โœ…. That amount of time can be estimated based on the round-trip time between the 6LoWPAN endpoints โŒ›. For lack of a more adapted technique, the method detailed in "Computing TCP's Retransmission Timer" [RFC6298] may be used for that computation ๐Ÿงฎ.

This specification provides the necessary tools for the fragmenting endpoint to take congestion control actions and protect the network, but it leaves the implementation free to select which action to take ๐ŸŽ›๏ธ. The plan is to use it to build experience and specify the congestion control actions more precisely in one or more future specifications ๐Ÿ”ฎ. "Congestion Control Principles" [RFC2914] and "Specifying New Congestion Control Algorithms" [RFC5033] offer hints and wisdom that should help along the way ๐Ÿ“š.

[RFC7567] and [RFC5681] go deeper on why congestion control is needed and how TCP handles it ๐Ÿค“. Basically, the goal here is to manage the number of fragments in the network ๐ŸŽฏ. That's achieved by reducing the number of outstanding fragments over a congested path, which means throttling the sources ๐Ÿšฐ.


Acknowledgments ๐Ÿซถ

The author would like to thank Michel Veillette, Dario Tedeschi, Laurent Toutain, Carles Gomez Montenegro, Thomas Watteyne, and Michael Richardson for their in-depth reviews and comments ๐Ÿ’œ. Many thanks also to Roman Danyliw, Peter Yee, Colin Perkins, Tirumaleswar Reddy.K, ร‰ric Vyncke, Warren Kumari, Magnus Westerlund, Erik Nordmark, and especially Benjamin Kaduk and Mirja Kรผhlewind for their careful reviews and help during the IETF Last Call and IESG review process ๐Ÿ‘‘. Thanks to Jonathan Hui, Jay Werb, Christos Polyzois, Soumitri Kolavennu, Pat Kinney, Margaret Wasserman, Richard Kelsey, Carsten Bormann, and Harry Courtice for their various contributions in the long process that led to this document ๐ŸŒธ.

Author's Address ๐Ÿฆ‹

Pascal Thubert (editor)
Cisco Systems, Inc.
Building D
45 Allee des Ormes - BP1200
06254 MOUGINS - Sophia Antipolis
France

Phone: +33 497 23 26 34
Email: pthubert@cisco.com
๐Ÿ“ฆ where this page comes from