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
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
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
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
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.
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:
Subscribe to ff05::abcd on nRF52840 End Device 1:
> ipmaddr add ff05::abcd Done
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
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) assert addrinfo == socket.AF_INET6 s = socket.socket(addrinfo, socket.SOCK_DGRAM) group_bin = socket.inet_pton(addrinfo, addrinfo) 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.')
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.
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!)
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.
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.
Congratulations, you've successfully set up a Thread Border Router and verified bi-directional IPv6 multicast!
For more on OpenThread, visit openthread.io.