Академический Документы
Профессиональный Документы
Культура Документы
Abstract. There exist several open source 6LoWPAN stacks for re-
searchers to experiment with. However, they often lack sufficient and
in-depth description of the internal operation, which makes extending
the stacks difficult for many of us. This paper provides detailed documen-
tation of the internal logic of an implemented and working 6LoWPAN
stack, Nanostack (v1.1). We present first the main architecture of the
stack and subsequently describe the path followed by a packet transiting
the different layers. The logic in each one of the layers is explained with
exception of the ICMP layer. Finally at the end of the paper we observe
Nanostack from user’s perspective and discuss features and problems
that we noticed in the stack.
1 Introduction
N. Meghanathan et al. (Eds.): NeCoM, WiMoN, and WeST 2010, CCIS 90, pp. 619–633, 2010.
c Springer-Verlag Berlin Heidelberg 2010
620 S. Lembo, J. Kuusisto, and J. Manner
release, version 1.1, and hereafter refer to it simply as Nanostack. Nanostack im-
plements most of the RFC4944 [1], namely, processing of Mesh-Header, Dispatch-
Header (and its alternatives LOWPAN HC1, LOWPAN BC0 and IPv6), mesh-
under addressing and compression of IP and UDP headers. The implementation
currently does not support 6LoWPAN fragmentation and we are unable to re-
port at what extent unicast and multicast address mapping is supported since
code related to the processing of native (non-compressed) IPv6 addresses was
not considered in our study. The stack was written in C language and designed
to work on top of FreeRTOS kernel [4].
Despite Nanostack being an open-source stack, Nanostack authors and users
never created proper documentation of the internal logic of the stack. Our main
contribution in this paper is to document and analyze the internal architecture
of Nanostack, followed by explanations about how it works in detail. The given
details help to cope with the missing documentation and explain the internal
logic at the code level. By exposing the architecture and logic of the stack, the
reader can evaluate at what extent Nanostack is suitable for an intended purpose
given different requirements and constraints (modularity, concurrency, real-time
operation, energy consumption, memory size, etc.).
In the following sections we document the stack architecture and logic. In
Section 2 we introduce the architecture of the stack. In the sections that follow
(3, 4, 5, and 6) we introduce and explain the operation of each one of the layers in
the stack, except the ICMP layer that is not covered in our descriptions. Finally,
we present discussions and conclusions in Section 7.
2 Stack Architecture
In this section, we first introduce the main data structure used in the stack for
processing packets, followed by the description of a key component in the core
architecture, the ”dispatcher” module. We also illustrate the overall architecture
with the dispatcher module and all the layers in the stack.
Possible destination layers are depicted below the box representing task
stack main(). In the figure we observe the following layers; MAC, cIPV6, mesh
and cUDP. Actually the stack contains also an ICMP layer that we do not include
in the current description. The details of the operation of each one of these layers
are described in Sections 3, 4, 5 and 6.1. Note in the figure that the application
layer is positioned outside the brace that expands under the dispatcher. The
application layer is independent of the stack in the sense that it is not related
to the dispatcher and instead receives/sends packets by calling socket functions.
We clarify here that the authors of the stack proposed the name cIPV6 for the
layer in charge of processing the headers Mesh-Header, Dispatch-Header, and its
alternatives LOWPAN HC1, LOWPAN BC0, IPv6, etc. (defined in [1]). And the
name cUDP for the layer that processes the compressed UDP ports (HC UDP
encoding) [1]. In addition each layer is associated to a module of code that can
be enabled/disabled in the stack. In this paper we assume that a module and a
layer are equivalent and talk always about layers in the rest of the paper.
Internal Map of the Nanostack 6LoWPAN Stack 623
Sockets. When an incoming packet leaves the cUDP layer in the stack, it is
pushed to queue events as usual. At this point the dispatcher recognizes that
there is no concrete destination layer (b.to = MODULE NONE), and that the
624 S. Lembo, J. Kuusisto, and J. Manner
packet is heading BUFFER UP. At this point the dispatcher looks for an existing
socket for the destination address and port number stated in the packet and if
the socket exists it moves the instance b to a dedicated queue located inside the
corresponding socket (queue socket ) (Fig. 2).
Incoming packets redirected to queue socket are retrieved at application layer
by calling socket read() function.
Outgoing packets are generated at application layer by invoking function
socket sendto(), which will set b.dir = BUFFER DOWN in the instance b that
holds the packet, and finally b is pushed to queue events.
3 MAC Layer
The processing of a packet in the MAC layer comprises the identification and
incorporation of the MAC headers in the MAC sublayer part of a IEEE 802.15.4
data frame. In the following subsections we discuss the processing of a packet in
the BUFFER UP and BUFFER DOWN direction.
packet in a ring buffer named mac tx[] and triggers an event MAC TRANSMIT.
Posterior processing in the system task mac task() (mentioned in the previous
subsection) will process this event and retrieve the packet from the ring buffer
by calling mac tx pull(). Next mac buffer out() is called and the MAC header is
generated by mac header generate(). Finally the packet is output of the stack; in
the case of Nanostack distribution the packet is delivered to the radio by calling
rf write(), function that does not belong to the stack but to the platform port
for radio chip TI CC2420 in file rf.c.
The return status of mac buffer out() can have different states
(MAC TX OK ACK, MAC TX BUSY, etc). If an ACK is expected the packet
b is kept in the system and a timer is launched. Then mac handle() waits
for a MAC ACK RX event; if an ACK never arrives the transmission is at-
tempted up to 3 times. When an ACK is received b is returned to the pool
(stack buffer pool[] ).
4 cIPV6 Layer
On the top of Fig. 4 the first two conditional branches verify particular exception
messages set in b.options. The first verification is related to an option to refresh a
Time-To-Live clock counter in entries of neighbor and routing tables (described
in Section 5). The second verification is related to an exception labeled broken-
link that occurs when the stack does not receive in time an acknowledgement
about the reception of a delivered packet from the destination node, or when the
transmission of a packet does not succeed after exceeding a maximum number of
attempts due to the unavailability of the transmitter to perform the transmission.
In the broken-link case the MAC layer adds a flag in the packet that is identified
Internal Map of the Nanostack 6LoWPAN Stack 627
Fig. 5. cIPv6 and mesh layers in the stack: BUFFER DOWN case
case the packet is pushed to queue events for further processing in the next layer
in the stack (cUDP).
A packet with a mesh final address other than the address of this node is a
packet that reaches this node and requires forwarding. From now on the packet
enters in a forwarding stage. In order to forward the packet to the proper desti-
nation its traveling direction in the stack will be now changed from BUFFER UP
to BUFFER DOWN direction.
The first step in forwarding a packet is to check if the destination address
(mesh final address) is the same that the own address of the node. If this is
the case the packet is being sent to itself, so it is discarded. Next the number
of hops left is checked. If the number of hops left is zero, a broken-link event is
generated. Note that this broken-link event is a different event to the mentioned
at the beginning of this section; in this case an ICMP message is delivered to the
destination address set in the packet. If the number of hops is greater than zero
the packet is pushed to queue events for further processing in the next layer in
the stack, in this case the mesh layer.
As additional information we mention that at the beginning of the logic ex-
plained in this subsection, the logic checks the presence of an IPv6 header. This
is not considered here and not depicted in the figure.
The upper part of Fig. 5 depicts the logic followed by a packet moving in the
BUFFER DOWN direction in this layer. In the figure we can observe a condi-
tional branch that checks if the packet contains a broadcast address. The broad-
cast case is not considered in this document. Non-broadcast packets are pushed
to the queue events for further processing in the next layer in the stack, in this
case the mesh layer.
5 Mesh Layer
The processing of a packet in the mesh layer when it is moving in the BUFFER UP
direction comprises the execution of mesh-under routing relying on the informa-
tion retrieved from the 6LoWPAN Mesh-Header in the cIPv6 layer. In the
BUFFER DOWN direction the processing comprises the incorporation of the
6LoWPAN Mesh-Header defined in RFC 4944 [1].
Routing information is stored in two main tables, Neighbor Table and Routing
Table. Neighbor Table contains contact information related to nodes that were
heard in the past, either by broadcast or unicast packets addressed to the node.
Routing Table contains contact information for nodes that are not neighbor
nodes. New entries in this table are added with callings to update routing table()
setting a value b.event other than REMOVE ROUTE and ROUTE ERR in the
instance b. In the stack we identified two calls to update routing table() for adding
new entries in the Routing Table, both mentioned in Sections 4.2 and 5.2. Here
we point out that these function calls are inconsistent in the sense that the logic
630 S. Lembo, J. Kuusisto, and J. Manner
distributed in different points of the stack does not present a definite criterion to
add initial entries in the table: The conditional statement mentioned in Section
4.2 requires the packet to have a 6LoWPAN Mesh-Header before an entry in the
table can be processed, and the conditional statement mentioned in Section 5.2
requires an entry in the table before adding a 6LoWPAN Mesh-Header in the
packet. Both conditions lock each other.
The lower part of Fig. 4 and 5 shows the logic involved in this layer when the
packet moves in the BUFFER UP and BUFFER DOWN directions respectively.
In the subsequent subsections we describe the different conditional branches that
form the logic of this layer for the cases BUFFER UP and BUFFER DOWN.
6 Higher Layers
In this section we describe the remaining layers that form part of the stack;
cUDP layer and Application layer.
In our opinion some outstanding points of this stack are: 1) The architecture
offers a modularized approach. Layers can be added/removed. 2) It is suitable
for researching mesh-under routing protocols, (in contrast of other stacks that
adopt route-over routing [2]). 3) It is based on FreeRTOS, a well positioned real-
time kernel supported by a large community of developers and in continuous
evolution.
Some problems we are still facing with Nanostack are the following: 1) Despite
the good architecture of the stack, some parts of the code need to be tidied up.
2) The footprint of the stack, kernel and application is just enough to fit in a
node with 128 kB of flash memory. For example the footprint of the stack, kernel
and a basic application to receive packets occupy around 68 kB. Expanding the
functionality of the application to use an AD converter to gather data from an
external sensor, report back the data, report the state of neighbor tables upon
request and perform GW discovery takes around 126 kB, leaving no room for
additional features.
The stack is distributed along with a platform port for the radio chip TI
CC2420, programmer, tools, etc., but the required compiler is not included in
the distribution. The compiler in use is a variant of SDCC with modifications
to support memory banking. A notable observation is that the programming
time of sensor nodes via UART takes about 4.5 minutes; not very productive for
code development. Our proposed solution for this last problem is the suggestion
to create a Nanostack development framework for the FreeRTOS Posix/Linux
Simulator [4].
We do not have detailed knowledge of the internal characteristics of other
existing open source 6LoWPAN stacks [2] to make a concise and fair comparison
of advantages and disadvantages between stacks. We acknowledge that uIPv6 [8]
[9] is a renowned stack; in contrast to Nanostack it is certified by the IPv6 Ready
Logo Program [10] and it is maintained by a considerable number of developers
and researchers. Despite these essential facts, in our selection process we favored
Nanostack for several reasons. First, Nanostack supports mesh-under routing,
following RFC 4944, whereas uIPv6 implements route-over routing [11]. Second,
due that we needed a protocol stack based on a real time kernel (FreeRTOS),
suitable for real time control processes and network synchronization [12]. And
third, due that despite the complexity of the stack, the programming at appli-
cation level is extremely simple, facilitated by FreeRTOS and the socket API
available in the stack. We note that our selection criteria is biased by our par-
ticular needs and experiences, and acknowledge that other stacks may be more
suitable under a different evaluation criteria.
As final remark we conclude that Nanostack v1.1 is a stack designed with a
modular architecture that operates moving pointers to instances of data struc-
tures, and hence without misusing memory size or reducing performance. In
addition the stack operates in a concurrent fashion using multiple tasks, and
over a real-time kernel system. The drawbacks of the stack are the lack of doc-
umentation, the lack of code maintenance and a small community of users.
Internal Map of the Nanostack 6LoWPAN Stack 633
References
1. Montenegro, G., Kushalnagar, N., Hui, J., Culler, D.: Transmission of IPv6 Packets
over IEEE 802.15.4 Networks. RFC 4944 (Proposed Standard) (September 2007)
2. Mazzer, Y., Tourancheau, B.: Comparisons of 6lowpan implementations on wireless
sensor networks. In: Third International Conference on Sensor Technologies and
Applications, SENSORCOMM 2009, 18-23 pp. 689–692 (2009)
3. NanoStack 6lowpan: Nanostack v1.1 (2008),
http://sourceforge.net/projects/nanostack/
4. FreeRTOS: The FreeRTOS project (2009), http://www.freertos.org/
5. Rio, M.: A map of the networking code in linux kernel 2.4.20. Technical Report
Data TAG-2004-1 (March 2004)
6. Wehrle, K.: The Linux networking architecture: design and implementation of net-
work protocols in the Linux kernel. Pearson Prentice Hall, Upper Saddle River
(cop. 2005)
7. IEEE Computer Society: IEEE standard 802.15.4-2006 (2006)
8. Durvy, M., Abeillé, J., Wetterwald, P., O’Flynn, C., Leverett, B., Gnoske, E., Vi-
dales, M., Mulligan, G., Tsiftes, N., Finne, N., Dunkels, A.: Making sensor networks
ipv6 ready. In: Proceedings of the Sixth ACM Conference on Networked Embedded
Sensor Systems (ACM SenSys 2008), poster session, Raleigh, North Carolina, USA
(November 2008)
9. Dunkels, A.: The uIP TCP/IP stack: uIP IPv6 specific features (May 2010),
http://www.sics.se/~ adam/contiki/docs-uipv6/a01110.html/
10. IPv6 Ready Logo Program (2010), http://www.ipv6ready.org/
11. Dunkels, A.: The uIP TCP/IP stack: 6LoWPAN implementation (May 2010),
http://www.sics.se/~ adam/contiki/docs-uipv6/a01109.html/
12. Mahmood, A., Jäntti, R.: Time synchronization accuracy for real-time wireless
sensor networks. In: Ninth Malaysia International Conference on Communications,
MICC 2009 (December 2009)