Skip to content
Philipp M. Scholl edited this page Dec 4, 2015 · 2 revisions

Connecting (and Emulating) Contiki Nodes to a Network

This tutorial is about connecting your own Contiki nodes to the outside world. This will help you in getting an understanding of IPv6 (and why you want to use it for WSNs), how it is implemented in Contiki and your Contiki-based software can be emulated on your local machine. For this we assume that you have a basic understanding of the Linux Process Model, and of IPv4/6 networking. You should already be familar with the Contiki Build System, which is what you used with Cooja the last times.

Setup your Edison

Follow http://intel.com/edison/getstarted to get to an interactive shell on your Edison. Make sure to connect via ssh and use the serial port only for setup. We will use this platform throughout the project as a powerful sensor node. It does run Linux as its Operating System, providing hardware abstraction, process isolation etc. for your applications. This makes debugging, building and changing your application easier. Edison will also be used as the border router, the special node which connects the WSN with the outside world. This will be done via Wifi.

Contiki will be used as an emulated Linux process on this platform, i.e. as one of the applications. Contiki provides its own IPv6 stack and will not use the one provided by Linux. The minimal-net target provides connectivity to the Linux networking stack via a virtual networking device, called tap. This tap device is connected to the Linux networking stack on one side and to the Contiki stack on the other side, exchanging packets in a format that you would see on a real wire. This packet includes the MAC-header of standard ethernet. In this way the tap device emulates a "real" network device. Compare this to the next figure, in which three different setups of running Contiki are documented: running natively (with minimal-net), running in the cooja simulator with the msp430 cpu (and the sky or z1 target) and running natively on an msp- and x86-hardware.

The layers of different implementations

The "tap" device, or virtual networking card, is a wireless networking chip in a real device. For this lab we will only look at networking chips which run the IEEE802.15.4 mac protocol. Like any other Medium-Access-Control protocol it defines how to access the medium, how to identify participanting nodes via the MAC-Address and specifies the transfer unit (TU). We will mostly look at the IPv6 suite of networking stacks built on top of this MAC-Layer (RIME is an alternative to IPv6, however incompatible with other OSes like Linux, Windows or Mac). For IEEE802.15.4 and IPv6 a special layer between MAC and IP-stack is neccessary, called 6lowpan. 6lowpan increases the supported single maximum transfer unit's (MTU) from 127 bytes to the 1.2kb required for IPv6 compliancy via a mechanism called fragmentation.

Building a Contiki project from the command line

Once you have an interactive shell running via ssh, install the latest Contiki version from github. Either by downloading the current master zip, or by installing git on the edison. The next step is to compile one of the Contiki examples for the "minimal-net" target. Remember targets in Contiki are actual platforms, which bind a host CPU, a networking stack and other hardware abstraction together into one application. This can be devices like the bare-metal Zolertia Z1 or OS-supported platforms like the Edison. To get a webserver, with an IPv6 stack running as a Linux process, you can use the following commands:

$ cd examples/webserver-ipv6
$ make TARGET=minimal-net

This instruct the Contiki build system to build the webserver, the ipv6 stack for the minimal-net target, which uses the aforementioned virtual networking device. The result of this process is an executable (also called application), which can be run directly by typing:

$ ./webserver6.minimal-net
ifconfig tap0 up

*******Contiki-3.x-1817-g6def22b online*******
IPV6 Addresss: [aaaa::206:98ff:fe00:232]
IPV6 Addresss: [fe80::206:98ff:fe00:232]

In this output you get the link-local address of the node (fe80:: prefix), the global address (aaaa:: prefix) and a copy of the "ifconfig tap0 up" command execution. This last command is used to create the virtual ethernet device connected to this process. You can use the standard "ip", "ifconfig", "tcpdump" etc. tools to change settings on the tap0 device, as well as sniff traffic.

The aaaa::206:98ff:fe00:232 address is the ip-address which identifies the end of the tap device for the Contiki process. Let's check the output of ifconfig tap0 to see what the Linux side looks like:

$ ifconfig tap0
tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet6 fe80::68a6:21ff:fee0:578b  prefixlen 64  scopeid 0x20<link>
    ether 6a:a6:21:e0:57:8b  txqueuelen 500  (Ethernet)
    RX packets 2  bytes 156 (156.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 5  bytes 418 (418.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

There is a lot of information about this network device. And you should be able to identify the link-local address of this network device: fe80::68a6:21ff:fee0:578b. This is the address of the Linux end of the virtual ethernet device. We can now try and reach the Contiki node by pinging its link-local address:

$ ping6 -c 2 fe80::206:98ff:fe00:232%tap0
PING fe80::206:98ff:fe00:232%tap0(fe80::206:98ff:fe00:232) 56 data bytes
64 bytes from fe80::206:98ff:fe00:232: icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from fe80::206:98ff:fe00:232: icmp_seq=2 ttl=64 time=0.049 ms

--- fe80::206:98ff:fe00:232%tap0 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.049/0.062/0.076/0.015 ms

You should notice the modified address fe80::206:98ff:fe00:232%tap0, which now includes the network device's name. This is because the link-local prefix is the same on each interface in the machine, i.e. the kernel would not know on which device to send ping requests. Which is why we add this explicitly. Now we can also try to ping the global address of the Contiki node:

$ ping6 aaaa::206:98ff:fe00:232

This will not work. For the same reason, the linux kernel does not know where to reach nodes with a prefix of aaaa::, since the network is not known yet. As in IPv4 we can instruct the kernel about this however. In the abscene of any routers, which will route traffic to the aaaa:: network, we manually assign an aaaa:: address to the tap0 device:

$ sudo ifconfig tap0 inet6 add aaaa::68a6:21ff:fee0:578b/64

Note that the aaaa:: address, is constructed by simply replacing the link-local address prefix (fe80) of the Linux side with the global prefix (aaaa::).

$ ping6 -c 2 aaaa::206:98ff:fe00:232
PING aaaa::206:98ff:fe00:232(aaaa::206:98ff:fe00:232) 56 data bytes
64 bytes from aaaa::206:98ff:fe00:232: icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from aaaa::206:98ff:fe00:232: icmp_seq=2 ttl=64 time=0.070 ms

--- aaaa::206:98ff:fe00:232 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.064/0.067/0.070/0.003 ms

For the adventurous among you, try to do a simple system test of the networking infrastructure by flood-pinging (sending ping requests as fast as possible):

$ sudo ping6 aaaa::206:98ff:fe00:232 -f
PING aaaa::206:98ff:fe00:232(aaaa::206:98ff:fe00:232) 56 data bytes

The number of displayed dots should stay constant. Otherwise there is an implementation problem on the networking infrastructure. You should now also be able to connect to the webserver by using it's IPv6 address in brackets:

$ curl http://[aaaa::206:98ff:fe00:232]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>Welcome to the Contiki web server!</title>
    <link rel="stylesheet" type="text/css" href="/style.css">  
  </head>
  <body bgcolor="#fffeec" text="black">

  <div class="menublock">

  <div class="menu">
  <p class="border-title">Menu</p>
  <p class="menu">
  
  <a href="/">Front page</a><br>
  <a href="status.shtml">Status</a><br>
  <a href="files.shtml">File statistics</a><br>
  <a href="tcp.shtml">Network connections</a><br>
  <a href="processes.shtml">System processes</a><br>

  </p>
  </div>
  </div>

  <div class="contentblock">
  <p class="border-title">
  Welcome to the <a href="http://www.Contiki-os.org">Contiki</a>
  web server!
  </p>
        
    <p class="intro">
      The web pages you are watching are served by a web
      server running under the <a
      href="http://www.contiki-os.org">Contiki operating
      system</a>.
    </p>

    
   
  </body>
</html>

You now have an application with its own IPv6 stack, which serves webpages. This application could now be compiled for µController (e.g. msp430), combined with a network driver and would serve webpages like a normal webserver. All in a size-range of 1-4 kilo-bytes. Great Stuff!

Routing IPv6 Traffic in the WSN

However, you might wonder why you needed to join the aaaa:: network manually, since you remember reading something about network address auto-configuration in the IPv6 networking guide. And you know about DHCP, which does exactly that for you in IPv4. So, what's the deal here? There is no router, i.e. a machine that forwards traffic between prefixes/networks, which would forward traffic to the network on the tap0 device from the outside world. In a sense only the Contiki process (and you) know that this network exists.

For Contiki and other WSN OSes, these special nodes are called border routers. They translate and forward traffic from the WSN radio medium to IP-compliant networks. The implementations of this vary, and you already looked into one the last time.

There you used the tunslip6 tool to pick up network traffic from the Cooja Simulator. A special border router node forwarded network traffic via the serial line ip protocol (SLIP) on a serial line. This line was emulated by Cooja through a network socket, which tunslip6 picked up and forwarded to the linux kernel via the virtual network device tap. On real hardware this emulated serial line would be replaced with a real serial line. And the simulated cooja-nodes with real hardware. You were also able to checkout multi-hop routing via the RPL protocol, which requires a special node, the DAG root, as well, which serves both as the node controlling the RPL tree and as a border router. When using tapslip6, IP-only packets are sent via the serial line, removing the underlying MAC-layer and the border router has additional work to do.

An alternative is to directly sent 15.4 mac packets via the serial line and have a special process pick them up on the Linux side, and process them etc. This is supported by Contiki in the ipv6/native-border-router and its accompying ipv6/slip-radio example. You run the slip-radio on the network node, which only forwards traffic then, and compile the native-border-router for the native target and run this on the linux machine with the serial line connected. With this solution there is more control over networking parameters. Try this option with Cooja, by creating udp-client nodes, a slip-radio/slip-radio.c node and the native-border-router!

Both alternatives allow you to do RPL compliant multi-hop networking via IPv6 on the network node. All this while being able to communicate with the WSN from your local linux machine.

Building an IPv6 auto-configuring Access Point

Still you can only access the WSN from your local node and not via any other network node - quite limiting. We can do better by building an IPv6 compliant router. For this you need to run the router advertisment daemon (radvd) on your linux machine, which tells the rest of the connected nodes about the existence of the WSN. Follow this guide for configuring a simple ipv6 network. After this has been setup you do not need to manually configure the network prefix anymore.

Additional Material