Tag Archives: monologue

Running Contiki examples on your linux system

Contiki has a bunch of examples, and most of it can be compiled to run on your local system, “native” and also in a special platform called “minimal-net”

So, let’s go and try and build one, say, [contiki-root]/examples/webserver That should be nice and easy.

contiki-minimal-net.a(contiki-main.o): In function `main':
/home/karlp/src/contiki-locm3/examples/webserver/../../platform/minimal-net/./contiki-main.c:298: undefined reference to `uip_ds6_if'
/home/karlp/src/contiki-locm3/examples/webserver/../../platform/minimal-net/./contiki-main.c:304: undefined reference to `uip_ds6_if'
contiki-minimal-net.a(tcpip.o): In function `tcpip_input':
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:532: undefined reference to `uip_ext_len'
contiki-minimal-net.a(tcpip.o): In function `tcpip_ipv6_output':
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:562: undefined reference to `uip_ds6_is_addr_onlink'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:566: undefined reference to `uip_ds6_route_lookup'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:568: undefined reference to `uip_ds6_defrt_choose'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:597: undefined reference to `rpl_update_header_final'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:602: undefined reference to `uip_ds6_nbr_lookup'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:603: undefined reference to `uip_ds6_nbr_add'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:620: undefined reference to `uip_ds6_addr_lookup'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:621: undefined reference to `uip_nd6_ns_output'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:623: undefined reference to `uip_nd6_ns_output'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:626: undefined reference to `uip_ds6_if'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:677: undefined reference to `uip_ext_len'
contiki-minimal-net.a(tcpip.o): In function `process_thread_tcpip_process':
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:769: undefined reference to `rpl_init'
contiki-minimal-net.a(tcpip.o): In function `eventhandler':
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:479: undefined reference to `uip_ds6_timer_periodic'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:480: undefined reference to `uip_ds6_timer_periodic'
/home/karlp/src/contiki-locm3/examples/webserver/../../core/net/tcpip.c:481: undefined reference to `uip_ds6_periodic'
collect2: error: ld returned 1 exit status
make: *** [webserver-example.minimal-net] Error 1

Oops. In commit 2d50a406 IPv6 was turned on by default, but the minimal-net platform doesn’t seem to support ipv6 (yet) I fully believe this to be a short term problem, but it’s extremely disheartening when you see it straight away.

So, to work around this, you can edit [contiki-root]/core/contiki-default-conf.h. About line 100, comment out the line #define UIP_CONF_IPV6 1. (I would not have found this myself, but one of the users of #contiki-os helped me out)

Ok, so you build. And you run. And… it fails again.

~/src/contiki-locm3/examples/webserver $ ./webserver-example.minimal-net 
RPL enabled
ioctl(TUNSETIFF): Operation not permitted
~/src/contiki-locm3/examples/webserver $

This time, it’s because the minimal-net platform actually makes some tricks. It tries to create and set up a tun/tap interface, creating a virtual network cable to your application. Remember, your application is a complete operating system with a full networking stack. But regular users can go doing that sort of thing, so… let’s run it with sudo…

~/src/contiki-locm3/examples/webserver $ sudo ./webserver-example.minimal-net 
[sudo] password for karlp: 
RPL enabled
ifconfig tap0 inet 172.18.0.1/16
route add -net 172.18.0.0/16 dev tap0
IP Address:  172.18.0.2
Subnet Mask: 255.255.0.0
Def. Router: 172.18.0.1

*******Contiki-2.6-487-g96e85cc online*******

Cool! That looks better! I can ping 172.18.0.2, and ifconfig shows me this virtual network. (At this point nmap should be able to fingerprint the OS (according to the contiki docs) but it totally fails for me at least.) Anyway, we built a webserver! Let’s check it out!

So that failed hard. Curl/wget doesn’t work either. And there was nothing on the console log, even after turning on logging. (A story in it’s own right, why would that not be on by default for the example running on the native host?)

I went down a rabbit hole here trying to work out what was going on. I got into gdb and could see action when I made a webrequest, but couldn’t follow the code well enough through Contiki’s protothreads to see what happened next. Still suspecting some ipv6 difficulties, I went and had a look through the [contiki-root]/core/contiki-default-conf.h file again. And found this gem…

/* UIP_CONF_BUFFER_SIZE specifies how much memory should be reserved
   for the uIP packet buffer. This sets an upper bound on the largest
   IP packet that can be received by the system. */
#ifndef UIP_CONF_BUFFER_SIZE
#define UIP_CONF_BUFFER_SIZE 128
#endif /* UIP_CONF_BUFFER_SIZE */

Now, that’s pretty small. It doesn’t say what happens when it gets a bigger packet, but I’m guessing it’s not pretty, and from the behaviour, it’s probably just terminating the connection if it runs out of buffer space. (“The connection was interrupted” in chrome and “* Recv failure: Connection reset by peer” from curl)

Ok, let’s change that to something bigger, 512 for starters. And…..

We’re finally working! Whee!

It turns out, you can get this to respond properly from curl by setting the useragent to something much smaller, but that’s not really all that helpful is it? So, in my mind, this is something that needs to be updated for contiki for the minimal-net platform. It’s totally reasonable to have a limit on the IP packet size for the final sensor nodes, when you know what you’re doing, but the example code, which is meant to run on your host system by default, using the minimal-net platform, should just work!. I’m trying to work up a clean pull request for this. (I can’t seem to get “project-conf.h” based overrides to work, and it’s late, so it will be another day)