962  6LoWPAN Fragmentation and Reassembly

962.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Explain Fragmentation Need: Understand why IPv6’s 1280-byte MTU requires fragmentation over 802.15.4
  • Analyze Fragment Headers: Parse FRAG1 and FRAGN header formats
  • Calculate Reliability Impact: Compute end-to-end delivery rates for fragmented packets
  • Implement Reassembly: Design buffer management for fragment collection
  • Avoid Fragmentation Pitfalls: Apply best practices to minimize fragmentation overhead

962.2 Prerequisites

Before diving into this chapter, you should be familiar with:

962.3 The Fragmentation Problem

Problem: IPv6 requires a 1280-byte minimum MTU, but 802.15.4 frames are only 127 bytes.

Solution: 6LoWPAN fragments large IPv6 packets across multiple 802.15.4 frames.

Artistic visualization of 6LoWPAN fragmentation showing IPv6 packet decomposition into multiple 802.15.4 frame fragments with dispatch headers, datagram tags, and offset fields for reassembly at destination node

6LoWPAN Fragmentation Process
Figure 962.1: The fragmentation mechanism demonstrates how 6LoWPAN handles IPv6’s 1280-byte minimum MTU requirement over 802.15.4’s constrained 127-byte frame size. Each fragment carries identification tags enabling the receiving node to reassemble the original packet correctly.

962.3.1 Fragmentation Thresholds

802.15.4 Max Frame Size: 127 bytes
MAC Header: ~21 bytes (addressing, sequence, FCS)
Security Header (if AES-128): ~21 bytes
Usable Payload (no security): 102 bytes
Usable Payload (with AES-128): 81 bytes

When Fragmentation Triggers:

  • Compressed IPv6/UDP header (6 bytes) + Application payload > 102 bytes
  • Example: 6-byte header + 97-byte CoAP payload = 103 bytes -> REQUIRES FRAGMENTATION

962.4 Fragment Header Formats

962.4.1 First Fragment (FRAG1)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D'}}}%%
flowchart LR
    subgraph FRAG1["First Fragment (FRAG1) Header"]
        direction LR
        Disp["11000<br/>000<br/>5 bits<br/>Dispatch"]
        Size["Datagram<br/>Size<br/>11 bits<br/>(0-2047 bytes)"]
        Tag["Datagram<br/>Tag<br/>16 bits<br/>(Unique ID)"]
        Pay["Payload<br/>Variable<br/>(Headers + Data)"]
    end

    Disp --> Size --> Tag --> Pay

    style Disp fill:#2C3E50,stroke:#16A085,color:#fff
    style Size fill:#16A085,stroke:#2C3E50,color:#fff
    style Tag fill:#E67E22,stroke:#2C3E50,color:#fff
    style Pay fill:#7F8C8D,stroke:#2C3E50,color:#fff

FRAG1 header format: 5-bit dispatch (11000), 11-bit datagram size, 16-bit unique tag, followed by compressed headers and first payload chunk.

962.4.2 Subsequent Fragments (FRAGN)

%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22', 'tertiaryColor': '#7F8C8D'}}}%%
flowchart LR
    subgraph FRAGN["Subsequent Fragment (FRAGN) Header"]
        direction LR
        Disp2["11100<br/>000<br/>5 bits<br/>Dispatch"]
        Size2["Datagram<br/>Size<br/>11 bits"]
        Tag2["Datagram<br/>Tag<br/>16 bits"]
        Off["Offset<br/>/8 bytes<br/>8 bits<br/>(0-2040)"]
        Pay2["Payload<br/>Variable"]
    end

    Disp2 --> Size2 --> Tag2 --> Off --> Pay2

    style Disp2 fill:#2C3E50,stroke:#16A085,color:#fff
    style Size2 fill:#16A085,stroke:#2C3E50,color:#fff
    style Tag2 fill:#E67E22,stroke:#2C3E50,color:#fff
    style Off fill:#E67E22,stroke:#2C3E50,color:#fff
    style Pay2 fill:#7F8C8D,stroke:#2C3E50,color:#fff

FRAGN header format: 5-bit dispatch (11100), 11-bit size, 16-bit tag matching FRAG1, 8-bit offset (position/8, max 255 x 8 = 2040 bytes), followed by payload chunk.

962.5 Fragmentation Example

Scenario: Fragmenting a 307-byte packet

Original packet: 7-byte compressed header + 300-byte payload = 307 bytes
802.15.4 payload available: 102 bytes

Fragment 1:
  FRAG1 header: 4 bytes (11000 + size=307 + tag=0x5A3C)
  Compressed headers: 7 bytes (IPHC + NHC)
  Payload chunk 1: 91 bytes
  Total: 4 + 7 + 91 = 102 bytes

Fragment 2:
  FRAGN header: 5 bytes (11100 + size=307 + tag=0x5A3C + offset=91/8=11)
  Payload chunk 2: 97 bytes
  Total: 5 + 97 = 102 bytes

Fragment 3:
  FRAGN header: 5 bytes (offset=188/8=23)
  Payload chunk 3: 97 bytes
  Total: 102 bytes

Fragment 4:
  FRAGN header: 5 bytes (offset=285/8=35)
  Payload chunk 4: 22 bytes (final chunk)
  Total: 27 bytes

Total: 91 + 97 + 97 + 22 = 307 bytes
Overhead: 4 + 5 + 5 + 5 = 19 bytes (6.2% overhead)

962.6 Fragmentation Overhead Summary

Packet Size Fragments Header Overhead Overhead %
102 bytes 1 0 bytes 0%
307 bytes 4 19 bytes 6.2%
512 bytes 6 29 bytes 5.7%
1280 bytes 14 69 bytes 5.4%

962.7 Reliability Impact: The Fragment Loss Problem

Critical Challenge: If ANY fragment is lost, the ENTIRE IPv6 packet must be discarded and retransmitted.

962.7.1 Reliability Calculation

With 5% per-fragment loss rate:

1 fragment:  (0.95)^1  = 95.0% success
4 fragments: (0.95)^4  = 81.5% success
12 fragments: (0.95)^12 = 54.0% success
20 fragments: (0.95)^20 = 35.8% success

Best practice: Keep packets under 102 bytes to avoid fragmentation!

ImportantPitfall: Ignoring MTU Mismatch Between IPv6 and 802.15.4

The Trap: Sending standard IPv6 packets (1280+ bytes) to 6LoWPAN devices without considering fragmentation overhead.

The Math That Hurts:

Standard IPv6 MTU: 1280 bytes
6LoWPAN fragment payload: ~97 bytes (after FRAGN header)
Fragments needed: ceiling(1280 / 97) = 14 fragments

Per-fragment loss rate: 5% (typical wireless)
All 14 must succeed: 0.95^14 = 48.8%

More than half of all packets FAIL to deliver!

Real-World Impact: - CoAP block-wise transfer degrades to single-fragment blocks - DTLS handshakes (typically 1000+ bytes) require 10+ fragments - Firmware updates become extremely unreliable

The Fix: 1. Application layer: Use CoAP block-wise transfer with 64-byte blocks 2. Transport layer: Keep DTLS records small (disable extensions) 3. Network layer: Configure IPv6 path MTU discovery 4. Border router: Fragment toward 6LoWPAN, reassemble toward internet

962.8 Knowledge Check: Fragmentation Reliability

Question: A factory monitoring system sends 1200-byte CoAP responses (sensor logs) from 6LoWPAN devices to a cloud server every 5 minutes. The network has 5% packet loss rate on each 802.15.4 hop, and packets traverse 3 hops average. Each 6LoWPAN device has 4 KB RAM for reassembly buffers. If a 1200-byte IPv6 packet requires 12 fragments (each 102 bytes usable payload), what is the end-to-end delivery success rate and minimum RAM buffer requirement per device for concurrent reassembly of 3 packets?

Calculation:

Per-fragment success rate:

Per-hop success: 1 - 0.05 = 0.95 (95%)
Over 3 hops: 0.95^3 = 0.857 (85.7% per fragment)

Complete packet success rate (all 12 fragments must arrive):

P(all fragments succeed) = 0.857^12 = 0.537 = 53.7% ~ 54%

Buffer Requirement: Each reassembly context allocates the complete IPv6 packet size upon receiving the first fragment:

Per packet: 1200 bytes
Concurrent packets: 3
Total: 3 x 1200 = 3600 bytes = 3.6 KB

Why 3.6 KB, not 1.2 KB? Fragments arrive in any order, so the full buffer must be allocated upfront. You can’t grow the buffer dynamically on constrained devices.

Key Insight: Even with 85.7% per-fragment success, requiring all 12 fragments to arrive drops overall success to only 54%.

962.9 Reassembly Process

962.9.1 Reassembly Steps

  1. Receive FRAG1: Allocate reassembly buffer (full datagram size), start 60-second timer
  2. Store fragments: Place payload at correct offset (derived from offset field x 8)
  3. Track completion: Mark which bytes have been received using bitmap
  4. Receive final fragment: When all bytes filled, pass complete packet to IPv6 layer
  5. Timeout handling: If timer expires before completion, discard all fragments

962.9.2 Memory Requirements

Per concurrent fragmented packet:
  - Reassembly buffer: Up to 2047 bytes (11-bit size limit)
  - Fragment bitmap: 256 bits (track which 8-byte chunks received)
  - Metadata: Tag, size, timer, source address
  - Total: ~2.3 KB per concurrent reassembly

Typical device (4 KB RAM):
  - Can handle 1-2 concurrent fragmentations
  - Important: Limit application payload sizes!

962.9.3 Code Example: Reassembly Implementation

// Contiki-NG: 6LoWPAN fragmentation buffer management
#include "net/ipv6/sicslowpan.h"

#define SICSLOWPAN_REASS_CONTEXTS  3   // Concurrent reassembly contexts
#define SICSLOWPAN_FRAGMENT_TIMEOUT 60  // Seconds

// Reassembly context structure
struct sicslowpan_frag_buf {
  uint16_t datagram_size;      // Total IPv6 packet size (e.g., 1200 bytes)
  uint16_t datagram_tag;       // Fragment group identifier
  uint8_t *reassembly_buffer;  // Buffer holding fragments as they arrive
  uint8_t *bitmap;             // Track which fragments received
  clock_time_t timeout;        // When to discard incomplete datagram
};

static struct sicslowpan_frag_buf frag_contexts[SICSLOWPAN_REASS_CONTEXTS];

// Allocate buffer for new fragmented datagram
int sicslowpan_fragment_alloc(uint16_t datagram_size, uint16_t datagram_tag) {
  int i;

  // Find free reassembly context
  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
    if(frag_contexts[i].datagram_size == 0) {
      // Allocate buffer for full IPv6 packet
      frag_contexts[i].reassembly_buffer = malloc(datagram_size);
      if(frag_contexts[i].reassembly_buffer == NULL) {
        printf("ERROR: Out of memory for reassembly (need %u bytes)\n", datagram_size);
        return -1;  // Out of memory!
      }

      frag_contexts[i].datagram_size = datagram_size;
      frag_contexts[i].datagram_tag = datagram_tag;
      frag_contexts[i].timeout = clock_time() + SICSLOWPAN_FRAGMENT_TIMEOUT * CLOCK_SECOND;

      return i;
    }
  }

  printf("ERROR: No free reassembly context (all %d in use)\n", SICSLOWPAN_REASS_CONTEXTS);
  return -1;  // All contexts in use
}

// Timeout handler - discard incomplete datagrams
void sicslowpan_fragment_timeout_check(void) {
  int i;
  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
    if(frag_contexts[i].datagram_size > 0 &&
       clock_time() > frag_contexts[i].timeout) {
      printf("Timeout: Discarding incomplete datagram tag=%u\n",
             frag_contexts[i].datagram_tag);

      // Free resources
      free(frag_contexts[i].reassembly_buffer);
      free(frag_contexts[i].bitmap);
      frag_contexts[i].datagram_size = 0;
    }
  }
}

962.10 Avoiding Fragmentation: Best Practices

962.10.1 Payload Size Guidelines

Payload Size Fragments Reliability Recommendation
0-60 bytes 1 95%+ Sweet spot
60-100 bytes 1-2 90%+ Acceptable
100-200 bytes 2-3 80-90% Caution
200-500 bytes 3-6 60-80% Avoid if possible
500+ bytes 6+ <60% Use different approach

962.10.2 Alternative Approaches

1. Application-Layer Segmentation (CoAP Block-Wise Transfer)

Split large data into 64-byte CoAP blocks:
- Each block fits in single 802.15.4 frame
- CoAP handles acknowledgment per block
- Selective retransmission (only failed blocks)
- Much more reliable than fragmentation

2. Border Router Handling

Sensor -> [Small packets] -> Border Router
Border Router -> [Reassemble/Fragment] -> Internet

Keep 6LoWPAN side small, let border router handle
internet-size packets on the Ethernet side.

3. Use Different Protocol for Large Data

- Wi-Fi for camera sensors (if power permits)
- NB-IoT/LTE-M for occasional large uploads
- 6LoWPAN only for small telemetry
WarningNever Fragment Multicast Traffic

Multicast + Fragmentation = Disaster: - Each receiver has different fragment loss patterns - Sender can’t retransmit (no ACKs in multicast) - If 10 receivers all miss different fragments, 100% packet loss

Rule: NEVER use fragmentation with multicast! Keep multicast payloads under 60 bytes.

962.11 Summary

This chapter explored 6LoWPAN’s fragmentation and reassembly mechanism:

  • Fragmentation is necessary because IPv6 requires 1280-byte MTU but 802.15.4 frames are only 127 bytes
  • FRAG1 and FRAGN headers carry size, tag, and offset for reassembly tracking
  • Reliability drops exponentially with fragment count: 12 fragments at 85.7% per-fragment success yields only 54% overall
  • Memory requirements are significant: each concurrent reassembly needs full datagram buffer allocation
  • Best practice: Keep payloads under 60-100 bytes to avoid fragmentation entirely
  • Alternatives: CoAP block-wise transfer, border router handling, or different protocols for large data

962.12 What’s Next

Continue to: