SCHC

Compressed headers, to allow convergence between non-IP and IP technologies

Connected objects are generally very limited in terms of bandwidth. The headers then represent a significant proportion of the total size that can be sent. The maximum size of packets that can be sent over the network (the MTU) can also be very limited.

SCHC stands for Static Context Header Compression (pronounced "chic") is a technology designed to overcome these problems.

For a complete overview of SCHC, refer to RFC 8724.

The principle of SCHC

SCHC has 2 main functions: compression and fragmentation.

Compression

SCHC is useful in situations where the size of packets that can be sent is limited.

The headers described below relate to the concatenation of protocol headers from the Network layer to the Application layer. This concatenation of headers for the packet to be sent will be defined by "original header".

The compression by SCHC can be roughly presented as follows:

  • A header or a set of headers is described by a Rule.

  • A list of all Rules is built. This list is called a Context. Both sender and receiver know the Context.

  • Each Rule is associated with a number, the RuleID.

When a sender wants to send an IP packet, it sends the RuleID associated with the packet it intends to send, followed by the payload.

The receiver gets the RuleID and the payload. Thanks to the Context, it can reconstitute the original header: this is the decompression step. In the case where the Rule describes a set of headers, additional data is sent by the sender to resolve the ambiguity during the reconstruction of the header. This additional data forms the Compression Residue.

We then obtain a packet with a much lighter header.

                    +--------------------------------------------- ... --------+--------------+
Before compression  |                  Header                       |              Payload    |
                    +--------------------------------------------- ... --------+--------------+


                    |------- Compressed header -------|
                    +---------------------------------+--------------+
After compression   | RuleID |  Compression Residue   |   Payload    |
                    +---------------------------------+--------------+    

Schema of a packet, before and after compression

Fragmentation

Despite the compression described above, there may be times when the MTU is so low that it is not enough. SCHC allows the payload to be sent in several packets: this is fragmentation.

An example with LoRa

LoRaWAN is the acronym for Long Range Wide-area network which can be translated as “long-range wide area network”. It is a telecommunications protocol allowing long distance communication, by radio, of low-power consumption objects communicating using LoRa technology and connected to the Internet via gateways, thus participating in the Internet of Things.

This protocol is used in the context of smart cities, industrial monitoring and even agriculture. The modulation technology related to LoRaWAN is LoRa. The LoRaWAN protocol, based on the LoRa physical layer, makes it possible to connect sensors or objects requiring a long battery life (counted in years), in a volume (size of a box of matches) and reduced cost.

We won't review all characteristics, but we'll focus on one specific issue that explains the fragmentation between non-IP protocols (such as LoRa) and IP protocols: the maximum payload size. For LoRA, it needs to be below 256 bytes, which makes it impractical to embed IP headers.

SCHC as a way to enable convergence

SCHC compression enables an IoT network stack compatible with IP technologies.

The mediam project implemented a prototype to demonstrate that, using CoAP and HTTP3. The github repository is available at TODO

Example in python:

  • BME280.py, to read the data returned by the sensors

  • join.py, to test the connection to the LoRa Network Server (LNS, LoRa Network Server)

from network import LoRa
import time
import pycom
import binascii


lora = LoRa(mode=LoRa.LORAWAN)


# create an OTAA authentication parameters
app_eui = binascii.unhexlify('00 00 00 00 00 00 00 00'.replace(' ',''))
app_key = binascii.unhexlify('11 22 33 44 55 66 77 88 11 22 33 44 55 66 77 88'.replace(' ',''))


pycom.heartbeat(False)
pycom.rgbled(0x111111)

# join a network using OTAA (Over the Air Activation)
lora.join(activation=LoRa.OTAA, auth=(app_eui, app_key),  timeout=0)

# wait until the module has joined the network
while not lora.has_joined():
    time.sleep(2.5)
    print('Not yet joined...')

pycom.rgbled(0x000000)
  • SendAndReceive.py, to test the sending of data from the pycom and the reception of responses from the resource server

  • CBOR.py, for serialization of data in CBOR, binary or even data transmitted in hexadecimal

  • CoAP.py, for the definition of CoAP standards and classes for client-server communication

  • send-coap-TPH.py, for sending data to the CoAP server with the URI the path to the resource (here TPH = temperature pression humidity as an example)

  • icmp.json, for the description of the Rules.

"RuleID": 6,
	    "RuleIDLength": 3,
	    "Compression": [
		{"FID": "IPV6.VER",                   "TV": 6,                        "MO": "equal",  "CDA": "not-sent"},
		{"FID": "IPV6.TC",                    "TV": 0,                        "MO": "equal",  "CDA": "not-sent"},
		{"FID": "IPV6.FL",                    "TV": 0,                        "MO": "ignore", "CDA": "not-sent"},
		{"FID": "IPV6.LEN",                                                   "MO": "ignore", "CDA": "compute-length"},
		{"FID": "IPV6.NXT",                   "TV": 58,                       "MO": "equal",  "CDA": "not-sent"},
		{"FID": "IPV6.HOP_LMT",               "TV": 255,                      "MO": "ignore", "CDA": "not-sent"},
		{"FID": "IPV6.DEV_PREFIX",            "TV": "2001:470:1F21:1D2::/64", "MO": "equal",  "CDA": "not-sent"},
		{"FID": "IPV6.DEV_IID",               "TV": "::1",                    "MO": "equal",  "CDA": "not-sent"},
		{"FID": "IPV6.APP_PREFIX",                                            "MO": "ignore", "CDA": "value-sent"},
		{"FID": "IPV6.APP_IID",                                               "MO": "ignore", "CDA": "value-sent"},
		{"FID": "ICMPV6.TYPE",    "DI": "DW", "TV": 128,                      "MO": "equal",  "CDA": "not-sent"},
		{"FID": "ICMPV6.TYPE",    "DI": "UP", "TV": 129,                      "MO": "equal",  "CDA": "not-sent"},
		{"FID": "ICMPV6.CODE",                "TV": 0,                        "MO": "equal",  "CDA": "not-sent"},
		{"FID": "ICMPV6.CKSUM",               "TV": 0,                        "MO": "ignore", "CDA": "compute-checksum"},
		{"FID": "ICMPV6.IDENT",               "TV": 0,                        "MO": "ignore", "CDA": "value-sent"},
		{"FID": "ICMPV6.SEQNO",               "TV": 0,                        "MO": "ignore", "CDA": "value-sent"}
	    ]

These programs kind of allow Pycom (the client) to send the serialized data in CBOR from the BME280 sensor to the resource server using the CoAP application protocol and the LoRa network.

from network import LoRa
import pycom

lora = LoRa(mode=LoRa.LORAWAN)
mac = lora.mac()

print ('devEUI: ',  end='')

for i in range (0,  8):
        print(hex(mac[i]), end='-')

print ()

Last updated