Wireless Testbed based on Raspberry Pi

De fablab
Aller à : navigation, rechercher

Project's frame

Subject's description

Introduction

When it comes to sensor networks or distributed systems, tests take an important place. To fix the dysfunctions we need to deploy an architecture of test :

  • a little infrastrcuture handmade allowing us to do a few tests. But this requires time and has to be deployed each time tests have to be done.
  • a public infrastructure constituted of many nodes. But this kind of architecture is not directly accessible and implies a lack of flexibility (we can't modify the deployed equipment).

Therefore the purpose of this project is to conceive a software architecture which can resolve these problems. This architecture has to be cheap, easily reusable and adaptable for every kind of network tests.

Our architecture will support two kind of configuration :

Simulation of a smartphone based network
Administred network of captors, with remote flash of ST MB851 cards

  • First scenario :

In this case, the nodes (Raspberry Pi boards) are connected through the filaire architecture to be configured. They boot on an Android OS and communicate between each other through the wifi network obtained with usb wifi keys. This configuration will be able to emulate a smartphones' network.

















  • Second scenario :

In this case, the nodes (Raspberry Pi boards) are used as a link to one or several boards MB851 connected through USB. The nodes allow us to monitor a network of sensors, the boards MB851 which used their radio 802.15.4 to communicate one to each other. The nodes will be able to launch a Linux OS. This scenario corresponds to standard experiments in the domain of sensors' networks.














Aims

  • Given that, the aim of the project is to be able to choose the operating system, we have to :
- Install a minimal bootloader on the SD cards of each Raspberry Pi.
  • Select the 2nd OS to launch among :
- An Android distribution adapted to our Raspberry Pi and our architecture, stored on the NFS server.
- A Linux distribution adapted to our Raspberry and our architecture, stored on the NFS server, able to flash the MB851 boards and to communicate with them.
  • Propose an application (in command lines and graphical) able to :
- Start, restart and stop each board.
- Select the OS to boot.
- Get the IPs of each board, so that the user may take control of the boards.

Equipment required

Herebelow the equipment required for this project :

Material Details

A switch

with PoE (Power over Ethernet) functions

Raspberry Pi boards

...

Ethernet PoE to 5V USB adaptors

one for each Raspberry Pi board

SD cards

one for each Raspberry Pi board

Ethernet and USB cables

...

One computer

At least one computer for the DHCP, TFTP and NFS servers

Tools installation

The configuration described here assumes that the main computer which will hold the DHCP, TFTP, and NFS servers, is connected to the switch with its interface eth0 with the @IP 192.168.0.1.

Folders setup

Creation of the mains folders which will be shared by TFTP and NFS with the RPi

$ sudo mkdir /tftpboot
$ sudo mkdir /tftpboot/kernels
$ sudo chmod -R 777 /tftpboot
$ sudo chown -R nobody /tftpboot
$ sudo mkdir /nfs

The architecture of the tftpboot folder will be the following :

/tftpboot
  /kernels
     kernel_Debian
     kernel_Android
     kernel_Gentoo
  kernel

where kernel is the kernel file which will be loaded by the RPi at boot.

Consequently to select an OS, you have to select one kernel from the kernels folder and then copy it to replace the kernel file.
This task will be automatically done by a java application given at the end of this page.

The NFS folder will contain the root filesystems of each OS which will be read by the RPi

/nfs
  /Debian
  /Gentoo
  /Android

Compilation tools

As the RPi is a tiny computer, the compilation of the kernels will be done on a more performant machine.
Installation of the cross-compiler :
We assume here that you are using Ubuntu.

$ sudo apt-get install gcc-arm-linux-gnueabi- make ncurses-dev

The cross-compiler prefix will be

$ export CCPREFIX=arm-linux-gnueabi-

Creation of the SD-Card

You can find here the .img of the card we used, Fichier:Card.img.zip
Simply copy it on a formatted card with this command :

$ sudo dd bs=4M if=<.img file> of=/dev/sdc

Assuming /dev/sdc is your card

The following lines explain how to re-create this card :

  • The bootloader

The main constraint of this project was to use a read-only SD-Card on each Rpi. The chosen solution is to put on these cards a light bootloader, uBoot which is a bootloader commonly used on embedded systems.
The port for the Raspberry Pi of this loader has already been done and the instructions to install it can be found here : http://elinux.org/RPi_U-Boot.
We will use here the following uBoot script :

set autostart yes
usb start
dhcp
bootm

Put it in a script.txt file and you'll be able to generate the boot.scr file to copy on the SD-Card via :

$ mkimage -A arm -T script -C none -d script.txt boot.scr
  • Preparation of the SD-Card

Create a 32MB FAT32 partition on the card and copy the bootloader on it.
Edit cmdline.txt with the following line :

dwc_otg.lpm_enable=0 console=tty1 ip=dhcp

DHCP Server

In order to have an automatic IP attribution for each RPi, we will install a dhcp server on the main computer.

$ sudo apt-get install isc-dhcp-server

Then, create a dhcpd.conf file :

# allow network boot
allow bootp;
allow booting;
# Network Setup # Subnet 192.168.0.* subnet 192.168.0.0 netmask 255.255.255.0 { # Broadcast address option broadcast-address 192.168.0.255;
# IP range range 192.168.0.10 192.168.0.100;
# kernel file to load on the TFTP Server filename "kernel";
# TFTP Server next-server 192.168.0.1;
# Check if the IP is already used ping-check = 1;
# Static IP for the switch host netgear { hardware ethernet 00:28:c6:8e:05:87:5a; fixed-address 192.168.0.10; } }

To start the dhcp server, simply use

$ sudo dhcpd -cf dhcpd.conf eth0

where eth0 is the interface connected to the switch
You can stop it with

$ sudo killall dhcpd

TFTP Server

The TFTP (Trivial File Transfer Protocol) server shares the kernel image with the Raspberry Pi at boot.
We will use tftpd

$ sudo apt-get install tftpd

Its config file is /etc/xinetd.d/tftp, create it with these lines :

service tftp
{
  protocol = udp
  port     = 69
  socket_type     = dgram
  wait            = yes
  user            = nobody
  server          = /usr/sbin/in.tftpd
  server_args     = /tftpboot
  disable         = no
}

You can now start it with

$ sudo /etc/init.d/xinetd start

NFS Server

A NFS server is used to share different folders. Here we use it to share the files from our different OS: After starting, the kernel needs to use some files to boot the system, but those files can't all be stored on the SDcard. That's why the kernel is configured to search it on the nfs server.

  • Install

To install a nfs server on your computer, you need to get this packages :

$ sudo apt-get install nfs-kernel-server nfs-common
  • Configuration

Then you need to modify the file /etc/exports like this :

/nfs/Android 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check)
/nfs/Debian 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check)
/nfs/Gentoo 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check)

This specify which folders are shared for which ip address. The last element of each line gives the right the clients have.

  • Start

The first time you want to start this server the shared folder have to be known by the server, that's why you need to load the exports. Then you can start it.

$ sudo service nfs-kernel-server reload
$ sudo invoke-rc.d nfs-kernel-server restart

Boot sequence

The boot sequence will be the following :

  • The RPi loads and executes the bootloader uBoot from the SD-Card.
  • This loader gets an IP and the kernel filename to load from the DHCP information.
  • The kernel is loaded from the TFTP server
  • The cmdline is read from the kernel file and gives the root filesystem location (NFS Server).
  • The filesystem is mounted via NFS and then the system is ready.

Nb: See the uBoot bug descibed below.

Installation of a system

  • Assuming that you have already the root filesystem of the system you want to boot on the Raspberry Pi, put it in a subfolder of the /nfs directory. Use the cp -a command to preserve the access permissions of the files.

Note that you may have to change the /etc/fstab of the system to remove the mount of SD-Card partition at boot.

General kernel compilation instructions :

  • You have to recompile the kernel, including the cmdline which contains the path to the root filesystem on the nfs server</br>

All the instruction can be found at this page http://elinux.org/RPi_Kernel_Compilation.
Remember that the cross-compiler prefix is

CCPREFIX=arm-linux-gnueabi-
  • Once you have set up a config file to the compilation (as explained in the previous link), you have to define the cmdline, we'll use the config menu :
$ sudo make -j2 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig

Go to the Boot Options menu and edit the cmdline (example is given below, depending of the OS kernel you are trying to compile)

  • In this menu, also change Kernel command line type to Extend bootloader kernel arguments.

You can now compile the kernel in uImage format with

$ sudo make -j2 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage
  • Also check that the NFS Boot is enabled in the kernel options : File Systems/Networking File Systems/NFS Client Support
  • Now get the uImage generated file from the arch/arm/boot subfolder of your kernel sources and copy it to your /tftpboot/kernels folder (you can rename it).
  • Don't forget to also recompile the modules (as indicated at http://elinux.org/RPi_Kernel_Compilation)

Android

CyanogenMOD 7.2 RPI

Android is an adapted OS for smartphone but not for raspberry Pi, that's why we had to found an adapted version for raspberry and supporting Ethernet connection : CyanogenMOD 7.2 is an android based OS developed under the razdroid project. This system contains a module allowing the raspberry to connect to an Ethernet network running a dhcp server.
In order to recompile the kernel we downloaded the razdroid-kernel files.

The cmdline to use in the kernel configuration is :

console=ttyAMA0,115200 root=/dev/nfs rw nfsroot=192.168.0.1:/nfs/Android,nolock,wsize=1024,rsize=1024 rootdelay=2 init=init

SSH connection

To take control of the raspberry, a ssh server has to run on the different OS. For Debian sshd is launched by default, but for Android a specific application has to be installed. We downloaded SSHDroid.apk and configured it to be launched during startup and to take an ip address thanks to the dhcp.

Debian

Kernel compilation

The used files to recompile the kernel can be found here : Debian-kernel. It's important to note that the kernel version we used is the 3.6.y. The newer version 3.8.y doesn't work with our configuration. To compile the kernel we use the following commandline :

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/nfs rw nfsroot=192.168.0.1:/nfs/Debian,vers=3 rootfstype=nfs rootwait

Flash the mb851 cards

In order to flash your mb851 cards through the Raspberry Pi, you will need to install serialdump and the stm32w flasher on the Raspberry. These applications can be found on this git in the folder tools. This git contains the contiki tools to compile your firmwares too.

  • Serialdump

Serialdump is an application used to read and send serial data on an usb port. In order to use it on the raspberry you can compile the file serial.c on the raspberry using gcc :

$ gcc -o serial serialdump.c

Now, you can easily see the informations sent by the mb851 cards specifying the rate (b115200 corresponds to the baud rate) and the device.

$ ./serial -b115200 /dev/ttyACM0
  • Stm32w_flasher

In the py_files folder you can find this program for linux written in python language. This uses different packages that have to be installed.
To install this you may need an internet connection which can be get with several methods :
Use a wifi key to connect to a wifi network.

Use a connected computer as a router :
On the PC

$ sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o wlan0 -j MASQUERADE
$ sudo sysctl -w net.ipv4.ip_forward=1

On the RPi

$ sudo route add default gw 192.168.0.1

Then you can install the different usefull packages

$ sudo apt-get install python-serial python-ftdi
$ sudo apt-get install hal
  • Interface_mb851

The Fichier:Main.java is a java application developped in order to control, from a PC, the flashing of mb851 cards connected to a raspberry Pi running Debian. This application opens a ssh connection to the raspberry with the specified IP adress and runs serialdump or stm32w_flasher depending on the selected options. This uses the jsch package. To run this application we built folder with specific path and name :

/NFS/Debian/contiki-stm32w/         #contains all the flashable .bin files 
~/stm32w/                           #contains serialdump 
~/stm32w_flasher/py_files/          #contains stm32w_flasher

This application allows you to get the different informations from serialdump or stm32w_flasher back. Here is an example :

$ java Main
Connexion [host] [options] [mb851 number] [file] 
       host :
		Specify the ip address of the raspberry running Debian
       options :
               -f : flash the card
               -r : restart the card
               -t : recover traces
               for more options : use directly the flasher on the raspberry 
       mb851 number :
               the card is associated to a specific device like ttyACM0 on the raspberry
               Just specify 0,1 ...
       file :
               only used for flashing a .bin file on the mb851. 
$ java Main 192.168.0.11 -r 0
INFO: STM32W flasher utility version 2.0.1b2-20130611 for Linux
INFO: Starting application from address: 08000000
INFO: Done

You can find the source code here

Gentoo

Kernel compilation

The kernel is the same than the Debian's one.
We used this command line :

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.0.1:/nfs/Gentoo,vers=3 rootfstype=nfs elevator=deadline rootwait

SSH connexion

By default there is no ssh server running on Gentoo. We need to configure it directly on the Raspberry PI once :
You need to modify the ./etc/conf.d/net :

auto_eth0="true"
config_eth0="null"

You need to enable networking on boot

root #  cd /etc/init.d/
root #  ln -s net.lo net.eth0
root #  rc-config start net.eth0
root #  rc-update add net.eth0 boot

You need to enable SSH Daemon

root #  rc-update add sshd default
root #  /etc/init.d/sshd start

Application to monitor the Raspberry Pi boards

In this part, you will find an application java that we have implemented in order to facilitate the monitoring of the boards. The application, named Command Center, allows the user to :

- start / restart or stop the Raspberry Pi with a remote access.
- get the Ip addresses of each board in order to interact with the boards.

This application has been implemented with a switch Netgear GS110TP.

Installation and use

Here you can find the zip file to download, and unzip on your computer : Fichier:Command center.tar.gz or here

Go to the unzip folder, and compile with :

$ ant

To use it you have to run the command in the folder /bin :

$ java -jar interface.jar @IP Path option

with the arguments :

  • @IP : Ip address of the switch
  • PATH : Path to the TFTP directory, (it is named tftpboot in our case)
  • option :
-g  : for the graphical interface
-p <PortNumber> <DesiredState> <kernelName>

The DesiredState value can be 0 to stop the board, or 1 to start/restart the board.

The application can be launched in a command line mode or with a graphical interface.

The command lines mode

You can choose to launch the same OS on the 8 ports of the switch (PortNumber=0), or to launch a different OS on each port, as you can see below :

$ java -jar interface.jar @IP PATH -p 0 1 kernelName    #same OS for the 8 boards
$ java -jar interface.jar @IP PATH -p 1 1 kernelName -p 2 1 kernelName2 -p 3 1 kernelName3 ... #OS for each board

You can also get all the Ip addresses of the boards with the command :

$ java -jar interface.jar @IP PATH -all

For more details, you can show the help menu with the command :

$ java -jar interface.jar -h

Warning !!
If you are not on the computer which contains the TFTP directory, you will have to mount a remote directory on your local files system.
First check that nfs-common is installed on your computer, then enter the command :

$ sudo mount -t nfs @IP_of_the_computer_with_TFTP_directory:/Path_to_the_directory

Graphical interface

To use the application in the graphical mode, launch the command :

$ java -jar interface.jar @IP PATH -g
Graphical interface

The Ip addresses are directly visible on the interface in front of the corresponding port of the switch and are refreshed every 5 seconds.
You can make a series of start/restart instructions, no matter the port, they will be executed one after the others. The port which is actually being processed is represented in yellow with written "loading", the ports which are waiting to be processed are also represented in yellow with written "waiting". In case you press a stop button it cancels all the waiting and running actions previously selected on the corresponding port and turns this port OFF.

For other switches

This application has been implemented for Netgear switches but you can easily use it with another switch.

For that, you have to know the OID (Object identifier) of the table which controls the PoE (Power over Ethernet) of the ports, and the OID of the MAC addresses' table.
If you encounter difficulties in finding these OID's, you can use the software, MachineEngine_opUtils installed on a Windows virtual machine. Then you have to change these OIDs in the source code of the class snmp.java.

Link to the source code

github : Source code

Issues (updated by E.Duble on june 18, 2013)

Wifi on Android

We tried to make the wifi operational on Android, by adding to the Rapsberry Pi a TP-Link TL-WN722N USB wifi dongle. Unfortunately there is no driver adapted natively on our Android distribution, so we added the ATH9K driver to the kernel and the firmware to the Android filesystem, but the wifi device is unrecognised by the system. We didn't have the time to find a proper solution and to perfectly understand how the system recognizes the device.

uBoot bug

A bug in the uBoot loader prevents it to directly get its DHCP IP (the network card driver seems bugged and the ethernet interface doesn't react until it receives any paquet). The solution is to do a broadcast ping on the network from another computer (for example the DHCP server), to wake up the RPi's network card.

Electrical ground issues

We had problems with electrical ground when connecting several equipments. There may be a problem with our home-made cables.

Cmdline embedded in the kernel image

The fact of having to specify the command line in the kernel image is not convenient, but we did not manage to make it work in any other way.

References

  • Raspberry Pi website

http://www.raspberrypi.org/

  • Help on ubuntu

http://doc.ubuntu-fr.org/

  • uBoot

http://www.denx.de/wiki/U-Boot

  • Port of uBoot to RPi and boot of FreeBSD over network

http://kernelnomicon.org/

  • Help on uBoot use and kernel compilation for the RPi

http://elinux.org

  • Porting android to the RPi

http://blogs.arm.com/software-enablement/498-from-zero-to-boot-porting-android-to-your-arm-platform/

  • Guide to add wifi drivers on android

http://nagaraj-embedded.blogspot.fr/2011/02/guide-on-adding-wifi-drivers-on-android.html
http://blog.linuxconsulting.ro/2010/04/porting-wifi-drivers-to-android.html

  • OIDs viewer

http://www.oidview.com/mibs/2/md-2-1.html

  • Javadoc of the SNMP Package used in the application command_center

http://gicl.cs.drexel.edu/people/sevy/snmp/docs/index.html

  • Javadoc of the jsch version 0.1.50 used in the application interface_mb851

http://arm.koji.fedoraproject.org/koji/rpminfo?rpmID=772024