Stack

Stack

Stack Organization

Overview

Protocol layers are wired together to form a stack. Click on the image to the right to see the stack organization diagram of the OpenWSN protocol stack. Send functions are used to push packets down the stack; Receive functions to pull them up. The bytes of a packet live in the OpenQueue component. A packet is a variable of type OpenQueueEntry_t and is defined in openwsn.h; components pass a pointer to an OpenQueueEntry_t variables in the Send and Receive functions.

OpenQueueEntry_t and metadata

An OpenQueueEntry_t consists of the actual bytes in the packet, plus a number of metadata fields. Metadata is used for an upper (resp. lower) layer to set parameters a lower (resp. upper) layer will need, when sending a packet down (resp. up) the stack. One example is that the MAC layer sets l1_channel to instruct the driver about which channel it needs to transmit the packet on. Another example is that RPL layer specifies l2_nextORpreviousHop, indicating to the MAC layer to which neighbor this packet needs to go.

No parameters are sent in the Send interfaces other than the pointer to the OpenQueueEntry_t. All Send interfaces have the same two functions:

error_t send (OpenQueueEntry_t* msg); void sendDone(OpenQueueEntry_t* msg, error_t error);

Similarly, when receiving:

void receive(OpenQueueEntry_t* msg);

Instead of adding and adding parameters in the interface, they go as metadata as are attached to the OpenQueueEntry_t variable. A packet is thereby self-contained: a component should never have to maintain state linked to a particular packet.

Metadata fields have names which indicates which layer should use them, from l7_ for the application to l1_ for the radio driver. Some field are used for administration by all the layers:

  • creator indicates the component which created this packet, i.e. which requested an unused OpenQueueEntry_t to the OpenQueue component. When sending a packet down the stack, the convention is that only the creator of a packet can free that packet, i.e. instruct the OpenQueue component it doesn't need it anymore. Typically, OpenQueueEntry_t variables will be created by all application-layer component when sending a packet, or by the drivers when receiving.

  • owner indicates the components which currently holds the packet. The convention is that a component can only change the content of an OpenQueueEntry_t if it is currently the owner.

  • The packet part of the OpenQueueEntry_t holds the actual bytes of the packet. Because OpenWSN does not allow for dynamic memory allocation, packet is the maximal allowed size. payload is a pointer to the first used by in packetlength indicates how many bytes are used.

Adding/removing protocol headers

When a component requests an unused OpenQueueEntry_t from the OpenQueue component, payload points to the end packet and length is zero. If a components needs to add n bytes of data to the packet pkt, it calls:

packetfunctions_reserveHeaderSize(OpenQueueEntry_t* pkt, uint8_t header_length)

This function modifies the payload and length fields of the OpenQueueEntry_t to make space for a header of header_length bytes. After this function is called, you can write a header starting at the byte pointed at by pkt->payload, of exactly header_length bytes.

Similarly, when a components needs to remove n bytes of data from the packet pkt, it does:

void packetfunctions_tossHeader(OpenQueueEntry_t* pkt, uint8_t header_length)

In practice, fixed-length header might be defined in a header file. The TCP header, for example, is defined in tcp.h as

typedef struct { uint16_t source_port; uint16_t destination_port; uint32_t sequence_number; uint32_t ack_number; uint8_t data_offset; uint8_t control_bits; uint16_t window_size; uint16_t checksum; uint16_t urgent_pointer; } tcp_ht;

tcp.c, which implements the TCP protocol, reserves space for the header by calling:

packetfunctions_reserveHeaderSize(msg,sizeof(tcp_ht));

Story of a packet

This section tells the story about what each layer does in the OpenWSN implementation, including which layers read and write metadata. There are two parts: one which details what happens when a packet is generated at the application layer, and travels down the stack until the drivers; one the other way.

Each of these sections end with a table stating which layer write (w) or read (r) which metadata.

  • Down the stack*

  • Application

    • gets a free OpenQueueEntry_t

    • fills in the following metadata:

      • creator (to itself)

      • owner (to itself)

      • l4_source_port (to be used by self to route to appropriate L4)

      • l4_destination_port (to be used by L4 to build header)

      • l3_destinationORsource ADDR_128B (to be used by RPL to find next hop)

    • fills in the payload according to its own format

    • sends to L4

  • L4(TCP or UDP)

    • fills in the following metadata:

      • owner (to itself)

      • l4_payload (to remember where the l4 payload starts, in case needs to resend)

      • l4_length (to remember where the l4 payload starts, in case needs to resend)

    • adds transport header based on:

      • l4_source_port (filled in by Application)

      • l4_destination_port (filled in by Application)

    • sends to RPL

  • RPL

    • fills in the following metadata:

      • owner (to itself)

      • l2_nextORpreviousHop (which is obtains by calling getNextHop)

    • sends to IPHC

  • IPHC

    • fills in the following metadata:

      • owner (to itself)

    • add 6LoWPAN header

    • sends to RES

  • RES

    • fills in the following metadata:

      • owner (to itself)

      • l2_frameType (to data if from above, to beacon if from Neighbors)

    • sends to MAC

  • MAC(IEEE802154E or stupidMAC)

    • fills in the following metadata:

      • owner (to itself)

      • l2_retriesLeft

      • l1_txPower

      • l1_channel

    • adds the MAC header based on:

      • l2_nextORpreviousHop (filled in by RPL)

      • l2_frameType (filled in by RES)

    • sends to drivers

  • drivers

    • does not put owner to itself to allow MAC to retransmit (in case something goes wrong in the drivers)

    • configures the radio according to:

      • l1_txPower (set by MAC)

      • l1_channel (set by MAC)

 

App

L4

RPL

IPHC

RES

MAC

drivers

creator

w

 

 

 

 

 

 

owner

w

w

w

w

w

w

 

l4_protocol

w/r

 

 

 

 

 

 

l4_source_port

w

r

 

 

 

 

 

l4_destination_port

w

r

 

 

 

 

 

l4_payload

 

w/r

 

 

 

 

 

l4_length

 

w/r

 

 

 

 

 

l3_destinationORsource

w

 

r

r

 

 

 

l2_nextORpreviousHop

 

 

w

 

 

r

 

l2_frameType

 

 

 

 

w

r

 

l2_retriesLeft

 

 

 

 

 

w/r

 

l1_txPower

 

 

 

 

 

w

r

l1_channel

 

 

 

 

 

w

r

l1_rssi

 

 

 

 

 

 

 

l1_lqi

 

 

 

 

 

 

 

l1_crc

 

 

 

 

 

 

 

l1_rxTimestamp

 

 

 

 

 

 

 

  • Up the stack*

  • drivers

    • gets a free an OpenQueueEntry_t

    • fills in the following metadata:

      • creator (to itself)

      • owner (to itself)

      • l1_rxTimestamp (for the MAC layer to possibly resynchronize)

      • l1_crc (in fact always true as in the current drivers a packet with a false CRC is discarded)

      • l1_lqi (not used in upper layers, for the moment)

      • l1_rssi (used by the Neighbors components to select stable neighbors)

    • sends to MAC

  • MAC(IEEE802154E or stupidMAC)

    • fills in the following metadata:

      • owner (to itself)

      • l2_frameType

      • l2_nextORpreviousHop to the 64b/16b address of the previous hop

    • if IEEE802.15.4E, resynchronizes using l1_rxTimestamp filled in by the drivers

    • removes the MAC header

    • sends to RES

  • RES

    • fills in the following metadata:

      • owner (to itself)

    • filters using l2_frameType filled in by MAC

    • sends to IPHC

  • IPHC

    • fills in the following metadata:

      • owner (to itself)

    • inflates the IPv6 header

    • removes the 6LoWPAN header

    • sends the message with the inflated IPv6 header to RPL

  • RPL

    • fills in the following metadata:

      • owner (to itself)

      • l4_protocol (according to the next_header field in the inflated IPv6 header provided by the IPHC componnent)

    • sends to the appropriate L4 according to l4_protocol

  • L4(TCP or UDP)

    • fills in the following metadata:

      • owner (to itself)

      • l4_source_port

      • l4_destination_port

    • remove the L4 header

    • sends to App

  • Application

    • discards the packet

 

drivers

MAC

RES

IPHC

RPL