1. Introduction
What is Thread?
Thread is an IP-based low-power wireless mesh networking protocol that enables secure device-to-device and device-to-cloud communications. Thread networks can adapt to topology changes to avoid single-point failures.
What is OpenThread?
OpenThread released by Google is an open-source implementation of Thread®.
What is an OpenThread Border Router?
OpenThread Border Router (OTBR) released by Google is an open-source implementation of the Thread Border Router.
Thread 1.2 Multicast
Thread 1.2 defines a series of features to support multicast across a heterogeneous network (Thread and Wi-Fi/Ethernet Network segments) for multicast addresses with scope larger than realm local.
A Thread 1.2 Border Router registers its Backbone Router (BBR) Dataset, and the selected BBR service is the Primary Backbone Router (PBBR), which is responsible for the multicast inbounding/outbounding forward.
A Thread 1.2 Device sends a CoAP message to register the multicast address to the PBBR (Multicast Listener Registration, MLR for short) if the address is larger than realm local. PBBR uses MLDv2 on its External Interface to communicate to the wider IPv6 LAN/WAN about IPv6 multicast groups it needs to listen to, on behalf of its local Thread Network. And PBBR only forwards multicast traffic into the Thread Network if the destination is subscribed to by at least one Thread device.
For Thread 1.2 Minimal End Devices, they may depend on their parent to aggregate the multicast address and do MLR on their behalf, or register themselves if their parent is of Thread 1.1.
For more details, please refer to Thread 1.2 Specification Section 5.24 Multicast Forwarding for larger than Realm-Local Scope.
What you will build
In this codelab, you're going to set up a Thread Border Router and two Thread devices, then enable and verify Multicast features on Thread devices and Wi-Fi devices.
What you will learn
- How to build nRF52840 firmware with Thread 1.2 Multicast features.
- How to subscribe to IPv6 multicast addresses on Thread devices.
What you will need
- A Raspberry Pi 3/4 device and a SD card with at least 8 GB capability.
- 3 Nordic Semiconductor nRF52840 DK boards.
- A Wi-Fi AP without IPv6 Router Advertisement Guard enabled on the router.
- Linux/macOS Laptop (Raspberry Pi also works) with Python3 installed.
2. Setup OTBR
Follow the Thread Border Router - Bidirectional IPv6 Connectivity and DNS-Based Service Discovery codelab to set up a Thread Border Router on the Raspberry Pi.
When completed, the Raspberry Pi should have created a working Thread network and be connected to a Wi-Fi network.
OTBR should become the Primary Backbone Router within seconds.
$ sudo ot-ctl bbr state Primary Done $ sudo ot-ctl bbr BBR Primary: server16: 0xD800 seqno: 23 delay: 1200 secs timeout: 3600 secs Done
3. Build and Flash Thread devices
Build the Thread 1.2 CLI application with Multicast and flash the two nRF52840 DK boards.
Build nRF52840 DK firmware
Follow instructions to clone the project and build nRF52840 firmware.
$ mkdir -p ~/src $ cd ~/src $ git clone --recurse-submodules --depth 1 https://github.com/openthread/ot-nrf528xx.git $ cd ot-nrf528xx/ $ script/build nrf52840 USB_trans -DOT_MLR=ON -DOT_THREAD_VERSION=1.2 $ arm-none-eabi-objcopy -O ihex build/bin/ot-cli-ftd ot-cli-ftd.hex
We can find the successfully built HEX firmware at ot-cli-ftd.hex
.
Flash nRF52840 DK firmware
Flash the firmware onto nRF52840 DK using nrfjprog
, which is part of the nRF Command Line Tools.
$ nrfjprog -f nrf52 --chiperase --program ot-cli-ftd.hex --reset
4. Attach Thread devices to the Thread network
OTBR has created a Thread network in previous steps. We can now add the nRF52840 DKs to the Thread network:
Get raw Active Dataset from OTBR:
$ sudo ot-ctl dataset active -x 0e080000000000000000000300000b35060004001fffc00208dead00beef00cafe0708fddead00beef00000510e50d3d0931b3430a59c261c684585a07030a4f70656e54687265616401022715041021cf5e5f1d80d2258d5cfd43416525e90c0302a0ff
Connect to a nRF52840 DK board:
$ screen /dev/ttyACM0 115200
Configure the Active Dataset for the nRF52840 DK:
> dataset set active 0e080000000000000000000300000b35060004001fffc00208dead00beef00cafe0708fddead00beef00000510e50d3d0931b3430a59c261c684585a07030a4f70656e54687265616401022715041021cf5e5f1d80d2258d5cfd43416525e90c0302a0ff Done
Start the Thread stack and wait for a few seconds and verify the device has successfully attached:
> ifconfig up Done > thread start Done > state child
Repeat the above steps to attach the other nRF52840 DK board to the Thread network.
We have now successfully set up the Thread network with 3 Thread devices: OTBR and two nRF52840 DK boards.
5. Setup Wi-Fi Network
Setup the Wi-Fi network on OTBR and the Laptop so that they are connected to the same Wi-Fi AP.
We can use raspi-config to setup the Wi-Fi SSID and passphrase on the Raspberry Pi OTBR.
The final network topology is shown below:
6. Subscribe to the IPv6 multicast address
Subscribe to ff05::abcd on nRF52840 End Device 1:
> ipmaddr add ff05::abcd Done
Verify ff05::abcd
is successfully subscribed:
> ipmaddr ff33:40:fdde:ad00:beef:0:0:1 ff32:40:fdde:ad00:beef:0:0:1 ff05:0:0:0:0:0:0:abcd <--- ff05::abcd subscribed ff02:0:0:0:0:0:0:2 ff03:0:0:0:0:0:0:2 ff02:0:0:0:0:0:0:1 ff03:0:0:0:0:0:0:1 ff03:0:0:0:0:0:0:fc Done
Subscribe to ff05::abcd on the Laptop:
We need a Python script subscribe6.py
to subscribe to a multicast address on the Laptop.
Copy the code below and save it as subscribe6.py
:
import ctypes
import ctypes.util
import socket
import struct
import sys
libc = ctypes.CDLL(ctypes.util.find_library('c'))
ifname, group = sys.argv[1:]
addrinfo = socket.getaddrinfo(group, None)[0]
assert addrinfo[0] == socket.AF_INET6
s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
interface_index = libc.if_nametoindex(ifname.encode('ascii'))
mreq = group_bin + struct.pack('@I', interface_index)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
print("Subscribed %s on interface %s." % (group, ifname))
input('Press ENTER to quit.')
Run subscribe6.py
to subscribe ff05::abcd
on the Wi-Fi network interface (e.g. wlan0):
$ sudo python3 subscribe6.py wlan0 ff05::abcd Subscribed ff05::abcd on interface wlan0. Press ENTER to quit.
The final network topology with multicast subscriptions are shown below:
Now that we have subscribed the IPv6 multicast address on both the nRF52840 End Device 1 in Thread network and the Laptop in the Wi-Fi network, we are going to verify bi-directional IPv6 multicast reachability in the following sections.
7. Verify Inbound IPv6 Multicast
Now, we should be able to reach both nRF52840 End Device 1 in the Thread network and the Laptop using IPv6 multicast address ff05::abcd
from the Wi-Fi network.
Ping ff05::abcd on OTBR via the Wi-Fi interface:
$ ping -6 -b -t 5 -I wlan0 ff05::abcd PING ff05::abcd(ff05::abcd) from 2401:fa00:41:801:83c1:a67:ae22:5346 wlan0: 56 data bytes 64 bytes from fdb5:8d36:6af9:7669:e43b:8e1b:6f2a:b8fa: icmp_seq=1 ttl=64 time=57.4 ms 64 bytes from 2401:fa00:41:801:8c09:1765:4ba8:48e8: icmp_seq=1 ttl=64 time=84.9 ms (DUP!) 64 bytes from fdb5:8d36:6af9:7669:e43b:8e1b:6f2a:b8fa: icmp_seq=2 ttl=64 time=54.8 ms 64 bytes from 2401:fa00:41:801:8c09:1765:4ba8:48e8: icmp_seq=2 ttl=64 time=319 ms (DUP!) 64 bytes from fdb5:8d36:6af9:7669:e43b:8e1b:6f2a:b8fa: icmp_seq=3 ttl=64 time=57.5 ms 64 bytes from 2401:fa00:41:801:8c09:1765:4ba8:48e8: icmp_seq=3 ttl=64 time=239 ms (DUP!) # If using MacOS, use this command. The interface is typically not "wlan0" for Mac. $ ping6 -h 5 -I wlan0 ff05::abcd
We can see that OTBR can receive two ping replies from both the nRF52840 End Device 1 and the Laptop because they both have subscribed to ff05::abcd
. This shows that the OTBR can forward the IPv6 Ping Request multicast packets from the Wi-Fi network to the Thread network.
8. Verify Outbound IPv6 Multicast
Ping ff05::abcd on nRF52840 End Device 2:
> ping ff05::abcd 100 10 1 108 bytes from fdb5:8d36:6af9:7669:e43b:8e1b:6f2a:b8fa: icmp_seq=12 hlim=64 time=297ms 108 bytes from 2401:fa00:41:801:64cb:6305:7c3a:d704: icmp_seq=12 hlim=63 time=432ms 108 bytes from fdb5:8d36:6af9:7669:e43b:8e1b:6f2a:b8fa: icmp_seq=13 hlim=64 time=193ms 108 bytes from 2401:fa00:41:801:64cb:6305:7c3a:d704: icmp_seq=13 hlim=63 time=306ms 108 bytes from fdb5:8d36:6af9:7669:e43b:8e1b:6f2a:b8fa: icmp_seq=14 hlim=64 time=230ms 108 bytes from 2401:fa00:41:801:64cb:6305:7c3a:d704: icmp_seq=14 hlim=63 time=279ms
nRF52840 End Device 2 can receive ping replies from both the nRF52840 End Device 1 and the Laptop. This shows that the OTBR can forward the IPv6 Ping Reply multicast packages from the Thread network to the Wi-Fi network.
9. Congratulations
Congratulations, you've successfully set up a Thread Border Router and verified bi-directional IPv6 multicast!
For more on OpenThread, visit openthread.io.
Reference docs: