Skip to content

Commit

Permalink
Merge pull request #292 from MrKevinWeiss/pr/automate0803
Browse files Browse the repository at this point in the history
Automate spec08 task03 contiki interop tests
  • Loading branch information
miri64 authored Nov 3, 2023
2 parents ec29270 + e83224e commit 6a14ffc
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 85 deletions.
195 changes: 113 additions & 82 deletions 08-interop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,103 +14,134 @@ Task #02 - ICMPv6 echo between iotlab-m3 and Linux with 6LowPAN
ICMPv6 echo request/reply exchange between an iotlab-m3 node running RIOT and
a Raspberry Pi running Linux with 6LoWPAN support.

Task #03 - UDP exchange between iotlab-m3 and Contiki
Task #03 - ICMPv6 echo between RIOT and Contiki-NG
=====================================================
### Description

UDP packet exchange between an iotlab-m3 node running RIOT and a Contiki node.
ICMPv6 echo request/reply exchange between a node running RIOT and a Contiki node.

### Testing procedure
1. Get your hands on a [CC2538DK evaluation board][cc2538dk]
1. Clone the Contiki repository to your machine
```sh
git clone http://github.com/contiki-os/contiki.git && cd contiki/
```
2. Go to the `udp-ipv6-echo-server` for the CC2538DK:
```sh
cd examples/cc2538dk/udp-ipv6-echo-server
```
3. Apply the following patch
```sh
echo 'diff --git a/examples/cc2538dk/udp-ipv6-echo-server/Makefile b/examples/cc2538dk/udp-ipv6-echo-server/Makefile
index 5bbbdd6..92ec1c5 100644
--- a/examples/cc2538dk/udp-ipv6-echo-server/Makefile
+++ b/examples/cc2538dk/udp-ipv6-echo-server/Makefile
@@ -1,8 +1,12 @@
+DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
CONTIKI_PROJECT = udp-echo-server
all: $(CONTIKI_PROJECT)
CONTIKI = ../../..
+CONTIKI_WITH_RIME = 0
CONTIKI_WITH_IPV6 = 1
CFLAGS += -DUIP_CONF_ND6_SEND_NS=1
+CFLAGS += -DRF_CHANNEL=26
+CFLAGS += -DIEEE802154_CONF_PANID=0x23
include $(CONTIKI)/Makefile.include
diff --git a/examples/cc2538dk/udp-ipv6-echo-server/project-conf.h b/examples/cc2538dk/udp-ipv6-echo-server/project-conf.h
new file mode 100644
index 0000000..1718ded
--- /dev/null
+++ b/examples/cc2538dk/udp-ipv6-echo-server/project-conf.h
@@ -0,0 +1,4 @@
+#ifndef PROJECT_CONF_H_
+#define PROJECT_CONF_H_
+#define NETSTACK_CONF_RDC nullrdc_driver
+#endif /* PROJECT_CONF_H_ */' | git apply
```
4. Build the application with
```
make
```
5. **Switch to your RIOT repository**
6. Switch the CC2538DK into bootloader mode by holding SELECT, then pressing
EM RESET, and then releasing SELECT (there should be no LED blinking when
you release RESET)
7. Use `dist/tools/cc2538-bsl/cc2538-bsl.py` to flash the *Contiki* application
to the CC2538DK.
You first need to fetch it from upstream.
```sh
make -C examples/hello-world/ ${PWD}/dist/tools/cc2538-bsl/cc2538-bsl.py
dist/tools/cc2538-bsl/cc2538-bsl.py -e -w -v -p /dev/ttyUSB1 \
"<contiki repo>"/examples/cc2538dk/udp-ipv6-echo-server/udp-echo-server.bin
```
*Note:* If you encounter any problems the [cc2538dk] documentation might help
you.
8. Use either `pyterm` or a sniffer to find out the Contiki node's link local
address. With the sniffer just copy the source address of the first RPL
package you see (assuming there are no other IEEE 802.15.4 nodes around you
😉). With `pyterm` you will see something like
This assummes Docker is installed and configured. The steps for configuring
Contiki-NG are based on the [official documentation](https://docs.contiki-ng.org/en/master/doc/getting-started/index.html)

1. Clone Contiki-NG

```bash
git clone https://github.com/contiki-ng/contiki-ng.git
cd contiki-ng
git submodule update --init --recursive

```

2. Pull the Contiki-NG Docker image

```bash
docker pull contiker/contiki-ng
```

3. Create a `contiker` alias to start the Contiki-NG environment
```bash

export CNG_PATH=<absolute-path-to-your-contiki-ng>
alias contiker="docker run --privileged --sysctl net.ipv6.conf.all.disable_ipv6=0 --mount type=bind,source=$CNG_PATH,destination=/home/user/contiki-ng -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v /dev/bus/usb:/dev/bus/usb -ti contiker/contiki-ng"

Rime configured with address 00:12:34:56:78:9a:bc:de
```

in the output.
4. Add the `shell` service to the `examples/hello-world` application.
```diff
diff --git a/examples/hello-world/Makefile b/examples/hello-world/Makefile
index 0a79167ae..710496368 100644
--- a/examples/hello-world/Makefile
+++ b/examples/hello-world/Makefile
@@ -1,5 +1,7 @@
CONTIKI_PROJECT = hello-world
all: $(CONTIKI_PROJECT)

+MODULES += os/services/shell
+
CONTIKI = ../..
include $(CONTIKI)/Makefile.include
```

You might have seen this address also during flashing
5. Run the Contiki-NG environment using the `contiker` alias.

Primary IEEE Address: 00:12:34:56:78:9A:BC:DE
```bash
contiker
```
6. Compile the `hello-world` application for your target platform. Check the
[platform documentation](https://docs.contiki-ng.org/en/master/doc/platforms/index.html)
for board specific steps. E.g for `nrf52840dk`:
```
make -C examples/hello-world TARGET=nrf52840 hello-world
make -C examples/hello-world TARGET=nrf52840 hello-world.upload
```

You can get the IPv6 link local address of the node by toggling the second
bit of the MSB of the address and prepending `fe80::`. So for the example
above that would be `fe80::0212:3456:789a:bcde`.
7. For the `iotlab-m3` side just use [gnrc_networking] or the [gnrc_udp] test
application, whichever you prefer. There start a UDP server on port 3000 with
7. Use any serial terminal (e.g `pyterm`) to get the link-local IP address of
the Contiki-NG node:
```
ip-addr
2023-04-14 15:23:36,732 # #f4ce.36c6.d8d1.e340> Node IPv6 addresses:
2023-04-14 15:23:36,735 # -- fe80::f6ce:36c6:d8d1:e340
```

> udp server start 3000
8. For the RIOT side just use [gnrc_networking](https://github.com/RIOT-OS/RIOT/tree/master/examples/gnrc_networking). Get the link-local IP address with `ifconfig`:

and send a UDP packet to port 3000 of the CC2538DK/Contiki node:
```
2023-04-14 15:11:12,614 # ifconfig
2023-04-14 15:11:12,620 # Iface 6 HWaddr: 06:EE Channel: 26 NID: 0xabcd PHY: O-QPSK
2023-04-14 15:11:12,622 #
2023-04-14 15:11:12,626 # Long HWaddr: 00:04:25:19:18:01:86:EE
2023-04-14 15:11:12,633 # TX-Power: 0dBm State: IDLE max. Retrans.: 3 CSMA Retries: 4
2023-04-14 15:11:12,640 # AUTOACK ACK_REQ CSMA L2-PDU:102 MTU:1280 HL:64 RTR
2023-04-14 15:11:12,643 # RTR_ADV 6LO IPHC
2023-04-14 15:11:12,646 # Source address length: 8
2023-04-14 15:11:12,649 # Link type: wireless
2023-04-14 15:11:12,655 # inet6 addr: fe80::204:2519:1801:86ee scope: link VAL
2023-04-14 15:11:12,665 # inet6 group: ff02::2
2023-04-14 15:11:12,668 # inet6 group: ff02::1
2023-04-14 15:11:12,672 # inet6 group: ff02::1:ff01:86ee
2023-04-14 15:11:12,674 # inet6 group: ff02::1a
2023-04-14 15:11:12,675 #
2023-04-14 15:11:12,678 # Statistics for Layer 2
2023-04-14 15:11:12,682 # RX packets 16174 bytes 1812690
2023-04-14 15:11:12,688 # TX packets 14824 (Multicast: 82) bytes 1715052
2023-04-14 15:11:12,692 # TX succeeded 14694 errors 130
2023-04-14 15:11:12,694 # Statistics for IPv6
2023-04-14 15:11:12,698 # RX packets 3194 bytes 1453638
2023-04-14 15:11:12,704 # TX packets 2545 (Multicast: 82) bytes 1430068
2023-04-14 15:11:12,707 # TX succeeded 2545 errors 0
2023-04-14 15:11:12,707 #
```

> udp send <contiki ll-addr> 3000 <data>
9. Set the PAN ID of the RIOT node to `abcd` (default PAN ID of Contiki)

Every packet you send should be echoed by the CC2538DK/Contiki node and
printed to the console (you might need to send more than once since the
neighbor discovery of Contiki is not queueing packets for unknown
destinations).
```
ifconfig 6 set pan_id abcd
```

10. Run the `ping` command on both the RIOT and the Contiki-NG node:

Contiki-NG:
```
ping fe80::204:2519:1801:86ee
2023-04-14 15:23:29,960 # #f4ce.36c6.d8d1.e340> Pinging fe80::204:2519:1801:86ee
2023-04-14 15:23:29,974 # Received ping reply from fe80::204:2519:1801:86ee, len 4, ttl 64, delay 15 ms
```

RIOT
```
ping fe80::f6ce:36c6:d8d1:e340
2023-04-14 15:30:20,415 # ping fe80::f6ce:36c6:d8d1:e340
2023-04-14 15:30:20,449 # 12 bytes from fe80::f6ce:36c6:d8d1:e340%6: icmp_seq=0 ttl=64 rssi=-46 dBm time=24.320 ms
2023-04-14 15:30:21,441 # 12 bytes from fe80::f6ce:36c6:d8d1:e340%6: icmp_seq=1 ttl=64 rssi=-46 dBm time=6.031 ms
2023-04-14 15:30:22,455 # 12 bytes from fe80::f6ce:36c6:d8d1:e340%6: icmp_seq=2 ttl=64 rssi=-46 dBm time=8.237 ms
2023-04-14 15:30:22,455 #
2023-04-14 15:30:22,460 # --- fe80::f6ce:36c6:d8d1:e340 PING statistics ---
2023-04-14 15:30:22,465 # 3 packets transmitted, 3 packets received, 0% packet loss
2023-04-14 15:30:22,469 # round-trip min/avg/max = 6.031/12.862/24.320 ms
```

[cc2538dk]: http://doc.riot-os.org/group__boards__cc2538dk.html
[gnrc_networking]: https://github.com/RIOT-OS/RIOT/tree/master/examples/gnrc_networking
[gnrc_udp]: https://github.com/RIOT-OS/RIOT/tree/master/examples/gnrc_networking
Every packet should be echoed by the target node and printed to the console.

Task #04 - ICMPv6 echo between iotlab-m3 and Internet host through Linux with 6LowPAN
=====================================================================================
Expand Down
25 changes: 25 additions & 0 deletions 08-interop/compile_contiki.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

cd /tmp

# Clone Contiki-NG
git clone https://github.com/contiki-ng/contiki-ng.git; cd contiki-ng || \
cd contiki-ng; git pull
git submodule update --init --recursive

# Pull the Contiki-NG Docker image
docker pull contiker/contiki-ng

# Add the `shell` service to the `examples/hello-world` application.
if ! grep -q "MODULES += os/services/shell" examples/hello-world/Makefile; then
sed -i '/all: $(CONTIKI_PROJECT)/a\\nMODULES += os/services/shell\n' examples/hello-world/Makefile
fi


# Compile the `examples/hello-world` application for the nRF52840 platform.
export CNG_PATH=/tmp/contiki-ng
docker run \
--sysctl net.ipv6.conf.all.disable_ipv6=0 \
--mount type=bind,source=$CNG_PATH,destination=/home/user/contiki-ng \
contiker/contiki-ng \
make -C examples/hello-world TARGET=nrf52840 hello-world
46 changes: 46 additions & 0 deletions 08-interop/test_spec08.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import os
import re
import sys
import subprocess


import pexpect.replwrap
import pytest
Expand Down Expand Up @@ -49,6 +52,49 @@ def test_task01(riot_ctrl, log_nodes):
assert res["stats"]["packet_loss"] < 1


@pytest.mark.flaky(reruns=1, reruns_delay=30)
@pytest.mark.iotlab_creds
# nodes passed to riot_ctrl fixture
@pytest.mark.parametrize(
'nodes', [pytest.param(['nrf52840dk', 'nrf52840dk'])], indirect=['nodes']
)
def test_task03(riot_ctrl):
# run `./compile_contiki.sh` relative to this file
subprocess.check_call(
["./compile_contiki.sh"],
cwd=os.path.dirname(os.path.realpath(__file__)),
)

build_path = "build/nrf52840/dk/hello-world.nrf52840"
flashfile = f"/tmp/contiki-ng/examples/hello-world/{build_path}"

gnrc_node, contiki_node = (
riot_ctrl(0, GNRC_APP, Shell),
riot_ctrl(
1,
'examples/hello-world',
riotctrl.shell.ShellInteraction,
extras={"BINFILE": flashfile},
),
)

gnrc_netif, gnrc_addr = lladdr(gnrc_node.ifconfig_list())

# get the address of the contiki node, ie a substring after "-- "
res = contiki_node.cmd("ip-addr")
match = re.search("-- (.+)", res)
assert match
contiki_addr = match[1]

gnrc_node.ifconfig_set(gnrc_netif, "pan_id", "abcd")

res = contiki_node.cmd(f"ping {gnrc_addr}")
assert f"Received ping reply from {gnrc_addr}" in res

res = ping6(gnrc_node, contiki_addr, 3, 12, 1)
assert res['stats']['packet_loss'] < 10


@pytest.mark.flaky(reruns=3, reruns_delay=30)
@pytest.mark.iotlab_creds
# nodes passed to riot_ctrl fixture
Expand Down
14 changes: 11 additions & 3 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,8 @@ def nodes(local, request, boards, iotlab_site):
RUNNING_EXPERIMENTS.remove(exp)


def update_env(node, modules=None, cflags=None, port=None, termflags=None):
def update_env(node, modules=None, cflags=None, port=None, termflags=None, extras=None):
# pylint: disable=too-many-arguments
node.env['QUIETER'] = '1'
if not isinstance(modules, str) and isinstance(modules, Iterable):
node.env['USEMODULE'] = ' '.join(str(m) for m in modules)
Expand All @@ -322,6 +323,8 @@ def update_env(node, modules=None, cflags=None, port=None, termflags=None):
node.env['PORT'] = port
if termflags is not None:
node.env['TERMFLAGS'] = termflags
if extras is not None:
node.env.update(extras)


@pytest.fixture
Expand All @@ -333,6 +336,7 @@ def riot_ctrl(log_nodes, log_file_fmt, nodes, riotbase, request):
factory_ctrls = []

# pylint: disable=R0913
# flake8: noqa: C901
def ctrl(
nodes_idx,
application_dir,
Expand All @@ -342,12 +346,13 @@ def ctrl(
cflags=None,
port=None,
termflags=None,
extras=None,
):
if board_type is not None:
node = next(n for n in nodes if n.board() == board_type)
else:
node = nodes[nodes_idx]
update_env(node, modules, cflags, port, termflags)
update_env(node, modules, cflags, port, termflags, extras)
# if the nodes are not logged, there is no sense in logging to a file
# so check if nodes are logged as well as if they should be logged to a
# file
Expand All @@ -366,8 +371,11 @@ def ctrl(
# need to access private member here isn't possible otherwise sadly :(
# pylint: disable=W0212
node._application_directory = os.path.join(riotbase, application_dir)
flash_cmd = "flash"
if "BINFILE" in node.env:
flash_cmd = "flash-only"
node.make_run(
['flash'],
[flash_cmd],
check=True,
stdout=None if log_nodes else subprocess.DEVNULL,
stderr=None if log_nodes else subprocess.DEVNULL,
Expand Down

0 comments on commit 6a14ffc

Please sign in to comment.