1. 简介

什么是 Thread?
Thread 是一种基于 IP 的低功耗无线网状网络协议,可实现安全的设备到设备和设备到云通信。Thread 网络可以适应拓扑变化,从而避免单点故障。
什么是 OpenThread?
Google 发布的 OpenThread 是 Thread® 的开源实现。
什么是 OpenThread 边界路由器?
Google 发布的 OpenThread 边界路由器 (OTBR) 是 Thread 边界路由器的开源实现。
IPv6 多播
Thread 定义了一系列功能,以支持在异构网络(Thread 和 Wi-Fi/以太网段)中针对范围大于领域本地的多播地址进行多播。
Thread 边界路由器会注册其主干路由器 (BBR) 数据集,而所选的 BBR 服务是主主干路由器 (PBBR),负责多播入站/出站转发。
如果多播地址大于领域本地地址,Thread 设备会发送 CoAP 消息,以向 PBBR 注册该多播地址(多播监听器注册,简称 MLR)。PBBR 在其外部接口上使用 MLDv2,以代表其本地 Thread 网络向更广泛的 IPv6 LAN/WAN 通信,告知其需要监听的 IPv6 多播组。并且,只有在至少一个 Thread 设备订阅了多播流量的目标时,PBBR 才会将多播流量转发到 Thread 网络中。
对于 Thread Minimal End Device,它们可能需要依赖其父设备来聚合多播地址并代表它们执行 MLR,或者在父设备属于 Thread 1.1 时自行注册。
如需了解详情,请参阅 Thread 规范。
构建内容
在此 Codelab 中,您将设置一个 Thread 边界路由器和两个 Thread 设备,然后在 Thread 设备和 Wi-Fi 设备上启用并验证多播功能。
学习内容
- 如何构建支持 IPv6 多播的 nRF52840 固件。
- 如何在 Thread 设备上订阅 IPv6 多播地址。
所需条件
- Linux 工作站,用于构建和刷写 Thread RCP、OpenThread CLI,以及测试 IPv6 多播。
- 用于 Thread 边界路由器的 Raspberry Pi。
- 2 个 Nordic Semiconductor nRF52840 USB 软件狗(一个用于 RCP,两个用于 Thread 终端设备)。
2. 设置 OTBR
设置 OTBR 的最快方法是按照 OTBR 设置指南操作。
OTBR 设置完成后,使用 ot-ctl 验证 OTBR 是否在几秒钟内成为主干路由器。
> bbr state Primary Done > bbr BBR Primary: server16: 0xF800 seqno: 21 delay: 5 secs timeout: 3600 secs Done
3. 构建和刷写 Thread 设备
使用多播构建 Thread CLI 应用,并刷写两个 nRF52840 DK 板。
构建 nRF52840 DK 固件
按照说明克隆项目并构建 nRF52840 固件。
$ cd ~/src/ot-nrf528xx $ rm -rf build $ script/build nrf52840 USB_trans -DOT_MLR=ON
继续按照编写的使用 nRF52840 板和 OpenThread 构建 Thread 网络 Codelab 进行操作。使用 CLI 映像刷写终端设备后,按照将第二个节点加入 Thread 网络中的说明将 Thread 设备添加到 Thread 网络。对第二个 Thread 终端设备重复上述步骤。
4. 订阅 IPv6 多播地址
在 nRF52840 终端设备 1 上订阅 ff05::abcd:
> ipmaddr add ff05::abcd Done
验证 ff05::abcd 是否已成功订阅:
> ipmaddr ff05:0:0:0:0:0:0:abcd <--- ff05::abcd subscribed ff33:40:fdde:ad00:beef:0:0:1 ff32:40:fdde:ad00:beef:0:0:1 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
在笔记本电脑上订阅 ff05::abcd:
我们需要一个 Python 脚本 subscribe6.py 来订阅笔记本电脑上的多播地址。
复制以下代码并将其保存为 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.')
运行 subscribe6.py 以在 Wi-Fi 网络接口(例如 wlan0)上订阅 ff05::abcd:
$ sudo python3 subscribe6.py wlan0 ff05::abcd Subscribed ff05::abcd on interface wlan0. Press ENTER to quit.
最终的网络拓扑(包含多播订阅)如下所示:

现在,我们已在 Thread 网络中的 nRF52840 端设备 1 和 Wi-Fi 网络中的笔记本电脑上订阅了 IPv6 多播地址,接下来将在以下部分中验证双向 IPv6 多播可达性。
5. 验证入站 IPv6 多播
现在,我们应该能够从 Wi-Fi 网络使用 IPv6 多播地址 ff05::abcd 同时访问 Thread 网络中的 nRF52840 终端设备 1 和笔记本电脑。
通过 Wi-Fi 接口在 OTBR 上 ping ff05::abcd:
$ 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
我们可以看到,OTBR 可以从 nRF52840 终端设备 1 和笔记本电脑收到两个 ping 回复,因为它们都订阅了 ff05::abcd。这表明 OTBR 可以将来自 Wi-Fi 网络的 IPv6 Ping 请求多播数据包转发到 Thread 网络。
6. 验证出站 IPv6 多播
在 nRF52840 终端设备 2 上 Ping ff05::abcd:
> 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 端设备 2 可以接收来自 nRF52840 端设备 1 和笔记本电脑的 ping 响应。这表明 OTBR 可以将 IPv6 Ping Reply 多播数据包从 Thread 网络转发到 Wi-Fi 网络。
7. 恭喜
恭喜,您已成功设置 Thread 边界路由器并验证了双向 IPv6 多播!
如需详细了解 OpenThread,请访问 openthread.io。
参考文档: