RPL Routing
The IPv6 Routing Protocol for Low-Power and Lossy Networks (RPL) is a routing protocol for constrained networks. See RFC 6550 for more information on RPL.
This tutorial shows how to use the RPL shell command to configure routing in a RIOT multi-hop network. We will configure one node as the RPL root and verify that the other nodes have joined the RPL Destination Oriented Directed Acyclic Graph (DODAG) and can ping each other using ICMPv6 echo requests.
Prerequisites
Section titled “Prerequisites”Please have a look at The Getting Started and Creating an Application.
Preparation
Section titled “Preparation”For routing capabilities, it is necessary that the RPL implementation is
compiled into your RIOT application.
This can be achieved by adding gnrc_rpl to the USEMODULE variable in your
application’s Makefile.
You can consult this Makefile
for a complete example.
For the following tutorials, the gnrc_networking
example will be used.
All commands listed here will be issued from within the
examples/networking/gnrc/networking directory.
You may use your own application after adjusting the Makefile as described
above.
Starting RIOT
Section titled “Starting RIOT”You can run the tutorial either on local hardware, native, or the FIT IoT-Lab.
Using Local Hardware
Section titled “Using Local Hardware”If you have three or more hardware boards with IEEE 802.15.4 radio capabilities, you can run the tutorial on actual hardware. This allows you to experiment with different distances between the boards and, e.g., create multi-hop topologies.
This tutorial is based on the Adafruit Feather nRF52840 Sense board.
If you are using different hardware, simply replace the BOARD value in the
commands below with your board name.
Handling Multiple Boards
Section titled “Handling Multiple Boards”A detailed description of development with multiple boards can be found in the
build system guide.
For the sake of simplicity, we are setting the PORT and DEBUG_ADAPTER_ID
values for each board manually in this tutorial.
List all connected boards, their port, and serial number.
make list-ttyspath | driver | vendor | model | model_db | serial | ctime | iface_num-------------|---------|-------------|---------------------------------|----------|------------------|----------|----------/dev/ttyACM0 | cdc_acm | RIOT-os.org | adafruit-feather-nrf52840-sense | None | AD57F0199B27E0C5 | 14:27:03 | 0/dev/ttyACM1 | cdc_acm | RIOT-os.org | adafruit-feather-nrf52840-sense | None | A595DD98EC28FB7C | 14:27:07 | 0/dev/ttyACM2 | cdc_acm | RIOT-os.org | adafruit-feather-nrf52840-sense | None | A766F77F8FC7A4A4 | 14:27:13 | 0Open one terminal window for each board and set the BOARD, PORT, and
DEBUG_ADAPTER_ID for each board.
Set the DEBUG_ADAPTER_ID to the printed serial value.
export BOARD=adafruit-feather-nrf52840-sense PORT=/dev/ttyACM0 DEBUG_ADAPTER_ID=AD57F0199B27E0C5In each window, compile and flash RIOT. Please note that you can not have multiple compilations running at the same time in a RIOT directory, so you have to compile and flash one at a time.
make flash termYou will be greeted by RIOT’s shell in all three terminals.
In the following sections, the term node{0,1,2} will be used to refer to the RIOT instances running on the boards connected to /dev/ttyACM{0,1,2}, respectively.
Using Native
Section titled “Using Native”Information about the native port of RIOT can be found in Family:-native.
Downside
Section titled “Downside”Because all nodes are connected via the tapbr0 bridge, all nodes are
reachable from each other within a single hop.
Therefore, it is not possible to test real multi-hop communication with this
method.
Virtual-riot-network
describes how native nodes can be deployed with a virtualized network topology
using tap interfaces.
See README.desvirt.md
for more information.
Creating Tap Interfaces
Section titled “Creating Tap Interfaces”The native RIOT instances communicate through tap interfaces. We provide a script that supports the setup and cleanup of such interfaces.
To set up tap interfaces and a bridge that connects each tap interface:
../../../../dist/tools/tapsetup/tapsetup -c 4With the -c parameter, you can specify how many tap interfaces you want to
create (default: 2).
To delete all tap interfaces, you can execute:
../../../../dist/tools/tapsetup/tapsetup -dSee the help for further information about additional parameters:
../../../../dist/tools/tapsetup/tapsetup -hYou can verify that the tap interfaces have been created successfully by
looking at the output of the ip l shell command.
This list should include the new interfaces tapbr0, tap0, tap1, tap2,
and tap3.
Compiling for Native
Section titled “Compiling for Native”make clean allType the following command in three different terminals, using tap0, tap1,
and tap2, respectively.
make term PORT=tap{0,1,2}RIOT native interrupts/signals initialized.TZ not set, setting UTCRIOT native board initialized.RIOT native hardware initialization complete.
main(): This is RIOT! (Version: XXX)RIOT network stack example applicationAll up, running the shell now>You will be greeted by RIOT’s shell in all three terminals.
In the following sections, the term node{0,1,2} will be used to refer to the nodes at tap{0,1,2}.
Using the IoT-Lab Testbed
Section titled “Using the IoT-Lab Testbed”Basic information about the IoT-Lab Testbed can be found in their
wiki.
This tutorial will cover only the iotlab-m3 nodes, but the following commands
should also be applicable to the wsn430 nodes.
Compiling for the iotlab-m3 Nodes
Section titled “Compiling for the iotlab-m3 Nodes”To compile the gnrc_networking example for the iotlab-m3, the following
command can be executed.
BOARD=iotlab-m3 make allStarting an Experiment
Section titled “Starting an Experiment”An experiment can be started either by using the IoT-Lab
dashboard or by using a
Makefile
provided by RIOT.
In this tutorial, the Makefile method will be used.
Add the iotlab Makefile to your own Makefile:
include $(RIOTBASE)/dist/testbed-support/Makefile.iotlabTo start an experiment and directly flash the reserved nodes, execute:
IOTLAB_USER=<iotlab_user> IOTLAB_PHY_NODES=10-12+14-16 IOTLAB_EXP_NAME=test IOTLAB_DURATION=60 BOARD=iotlab-m3 make iotlab-expThis command may prompt for a password to authenticate your IoT-Lab account. You will need to use the same password that you use for the IoT-Lab dashboard.
| Parameter | Description |
|---|---|
| IOTLAB_USER | Specify your IoT-Lab account name. The same name used for the dashboard |
| IOTLAB_PHY_NODES | Choose the nodes for the experiment. If a node is not available, the Makefile will return an error specifying which nodes are busy |
| IOTLAB_EXP_NAME | Name of the experiment |
| IOTLAB_DURATION | Duration in minutes |
| BOARD | The board to use: iotlab-m3 |
More information and further parameters can be found in the README.
Assuming the experiment started successfully, you can then communicate with the nodes directly from the command line like this:
IOTLAB_USER=<iotlab_user> BOARD=iotlab-m3 make iotlab-termOnce you are connected, the serial aggregator of the IoT-Lab testbed will be started, and you will have a console from which you can control every node.
(Re-)flashing Nodes
Section titled “(Re-)flashing Nodes”If you want to flash the nodes again at a later point in time, use the
iotlab-flash command:
IOTLAB_USER=<iotlab_user> BOARD=iotlab-m3 make iotlab-flashAlternatively, you can flash individual nodes or get their serial I/O by
setting IOTLAB_NODE and using the usual make flash / make term commands,
e.g.:
IOTLAB_NODE=m3-10.grenoble.iot-lab.info BOARD=iotlab-m3 make flash termUsing the Serial Aggregator
Section titled “Using the Serial Aggregator”Each command issued in the serial aggregator will be transmitted to all nodes used for the current experiment. To direct a command specifically to a single node, the node ID must be prepended to the command.
E.g., start RPL on interface 5 for all nodes:
rpl init 5m3-10;> rpl init 5m3-10;successfully initialized RPL on interface 5m3-11;> rpl init 5m3-11;successfully initialized RPL on interface 5m3-12;> rpl init 5m3-12;successfully initialized RPL on interface 5m3-14;> rpl init 5m3-14;successfully initialized RPL on interface 5m3-15;> rpl init 5m3-15;successfully initialized RPL on interface 5m3-16;> rpl init 5m3-16;successfully initialized RPL on interface 5Start RPL only on one node:
m3-10; rpl init 5m3-10;successfully initialized RPL on interface 5In the tutorial below we use node{0,1,2} to refer to specific nodes.
These commands should be prepended with the node ids, e.g., m3-10;, m3-11;,
and m3-12; for node0, node1, and node2, respectively.
Initializing RPL
Section titled “Initializing RPL”In order to use RPL, we have to choose a RPL root node. We will choose node0 as the RPL root.
With the ifconfig command, we can get the configured interfaces for a
particular RIOT node.
An example output for node0 is shown below. It may look slightly different
if you are using different hardware or are running on native.
ifconfigIface 6 HWaddr: 68:C5 Channel: 26 NID: 0x23 PHY: O-QPSK Long HWaddr: AE:57:F0:19:9B:27:E8:C5 TX-Power: 0dBm State: IDLE ACK_REQ L2-PDU:102 MTU:1280 HL:64 RTR RTR_ADV 6LO IPHC Source address length: 8 Link type: wireless inet6 addr: fe80::ac57:f019:9b27:e8c5 scope: link VAL inet6 group: ff02::2 inet6 group: ff02::1 inet6 group: ff02::1:ff27:e8c5 inet6 group: ff02::1aAt first, we need to configure a global IPv6 address for one node, the root node.
ifconfig 6 add 2001:db8::1success: added 2001:db8::1/64 to interface 6ifconfigIface 6 HWaddr: 68:C5 Channel: 26 NID: 0x23 PHY: O-QPSK Long HWaddr: AE:57:F0:19:9B:27:E8:C5 TX-Power: 0dBm State: IDLE ACK_REQ L2-PDU:102 MTU:1280 HL:64 RTR RTR_ADV 6LO IPHC Source address length: 8 Link type: wireless inet6 addr: fe80::ac57:f019:9b27:e8c5 scope: link VAL inet6 addr: 2001:db8::1 scope: global VAL inet6 group: ff02::2 inet6 group: ff02::1 inet6 group: ff02::1:ff27:e8c5 inet6 group: ff02::1aNow, RPL must be initialized on that particular interface for all nodes:
rpl init 6successfully initialized RPL on interface 6Starting RPL
Section titled “Starting RPL”On the root node (node0 in this tutorial), type:
rpl root 1 2001:db8::1successfully added a new RPL DODAGNote, however, that the DODAG ID 2001:db8::1 matches a global IPv6 address
configured on an interface, as done in Initializing RPL.
The 1 before 2001:db8::1 is the Instance ID and can be adjusted if desired.
To see the RPL status, type rpl.
rplinstance table: [X]parent table: [ ] [ ] [ ]
instance [1 | Iface: 5 | mop: 2 | ocp: 0 | mhri: 256 | mri 0] dodag [2001:db8::1 | R: 256 | OP: Router | PIO: on | TR(I=[8,20], k=10, c=1)] rplThe root node has a rank of R: 256.
Now type rpl in the other terminals (here is an example for node1):
rplinstance table: [X]parent table: [X] [ ] [ ]
instance [1 | Iface: 5 | mop: 2 | ocp: 0 | mhri: 256 | mri 0] dodag [2001:db8::1 | R: 512 | OP: Router | PIO: on | TR(I=[8,20], k=10, c=1)] parent [addr: fe80::ac57:f019:9b27:e8c5 | rank: 256]This node is part of the RPL DODAG with the DODAG ID 2001:db8::1 and
Instance ID 1.
Furthermore, this node’s rank is R: 512, and the preferred parent has the
link-local IPv6 address fe80::d069:49ff:fede:b38c.
This parent’s rank is 256, therefore we know that this parent must be the
root of this RPL DODAG.
Note that all participating nodes in the RPL DODAG automatically configure a
global IPv6 address matching the prefix from the DODAG ID. Verify this with
ifconfig.
RPL should now start to fill the NIB (Neighbor Information Base) table, which is consulted when forwarding packets. On the root node (node0):
nib route2001:db8::/64 dev #62001:db8::14f3:36ff:fe6f:6395/128 via fe80::14f3:36ff:fe6f:6395 dev #62001:db8::d8bc:8aff:feaa:7c46/128 via fe80::d8bc:8aff:feaa:7c46 dev #6and on the participating node (node1):
nib route2001:db8::/64 dev #6default* via fe80::ac57:f019:9b27:e8c5 dev #6The nodes can now ping each other using the public IP addresses (replace the destination IP):
ping 2001:db8::14f3:36ff:fe6f:639512 bytes from 2001:db8::14f3:36ff:fe6f:6395: icmp_seq=0 ttl=64 time=1.728 ms12 bytes from 2001:db8::14f3:36ff:fe6f:6395: icmp_seq=1 ttl=64 time=1.070 ms12 bytes from 2001:db8::14f3:36ff:fe6f:6395: icmp_seq=2 ttl=64 time=1.010 ms
--- 2001:db8::14f3:36ff:fe6f:6395 PING statistics ---3 packets transmitted, 3 packets received, 0% packet lossround-trip min/avg/max = 1.010/1.269/1.728 ms