1. 简介
什么是线程边界路由器?
Thread 是一种基于 IP 的低功耗无线网状网络协议,支持安全的设备到设备和设备到云通信。线程网络可以适应拓扑变化,以避免单点故障。
Thread Border Router 可将 Thread 网络连接到其他基于 IP 的网络,例如 Wi-Fi 或以太网。Thread 网络要求边界路由器连接到其他网络。线程边界路由器至少支持以下函数:
- Thread 和 Wi-Fi/以太网网络之间的双向 IP 连接。
- 通过 mDNS(通过 Wi-Fi/以太网链路)和 SRP(在 Thread 网络上)进行双向服务发现。
- 基于 IP 的链路合并 Thread 分区的 Thread-over-基础架构。
- 外部线程调试(例如手机),用于验证 Thread 设备并将其加入 Thread 网络。
Google 发布的 OpenThread 边界路由器 (OTBR) 是线程边界路由器的开源实现。
构建内容
在此 Codelab 中,您将设置 Thread 边界路由器,并通过边界路由器将手机连接到 Thread 终端设备。
学习内容
- 如何设置 OTBR
- 如何通过 OTBR 构建 Thread 网络
- 如何构建具有 SRP 功能的 OpenThread CLI 设备
- 如何通过 SRP 注册服务
- 如何发现和访问 Thread 终端设备。
所需条件
- 一部 Raspberry Pi 3/4 设备和一张至少具有 8 GB 性能的 SD 卡。
- 2 块北欧半导体 nRF52840 开发板。
- 路由器上未启用 IPv6 Router Advertisement Guard 的 Wi-Fi AP。
- 搭载 iOS 14 或更高版本的 iOS 手机或搭载 Android 8.1 或更高版本的 Android 手机。
2. 设置 OTBR
设置 Raspberry Pi
按照 raspberrypi.org 上的说明,使用 rpi-imager
工具设置全新的 Raspberry Pi 设备非常简单(无需在该工具中使用最新的 Raspberry Pi 操作系统,请自行下载 2021-05-07-raspios-buster-armhf-lite)。为了完成此 Codelab 中的手机步骤,您需要将 Raspberry Pi 连接到 Wi-Fi AP。请按照此指南设置无线连接。使用 SSH 登录 Raspberry Pi 比较方便,您可以在此处找到相关说明。
获取 OTBR 代码
登录您的 Raspberry Pi 并从 GitHub 克隆 ot-br-posix
:
$ git clone https://github.com/openthread/ot-br-posix.git --depth 1
构建和安装 OTBR
OTBR 有两个用于引导和设置线程边界路由器的脚本:
$ cd ot-br-posix $ ./script/bootstrap $ INFRA_IF_NAME=wlan0 ./script/setup
OTBR 适用于通过 INFRA_IF_NAME
指定的 Thread 接口和基础架构网络接口(例如 Wi-Fi/以太网)。Thread 接口由 OTBR 本身创建,默认命名为 wpan0
。如果未明确指定 INFRA_IF_NAME
,则基础架构接口的默认值为 wlan0
。如果您的 Raspberry Pi 是通过以太网网线连接的,请指定以太网接口名称(例如 eth0
):
$ INFRA_IF_NAME=eth0 ./script/setup
检查 OTBR 是否已成功安装:
$ sudo service otbr-agent status ● otbr-agent.service - Border Router Agent Loaded: loaded (/lib/systemd/system/otbr-agent.service; enabled; vendor preset: enabled) Active: activating (auto-restart) (Result: exit-code) since Mon 2021-03-01 05:43:38 GMT; 2s ago Process: 2444 ExecStart=/usr/sbin/otbr-agent $OTBR_AGENT_OPTS (code=exited, status=2) Main PID: 2444 (code=exited, status=2)
otbr-agent
服务应未处于活跃状态,因为它需要 RCP
芯片才能运行。
重新启动 Raspberry Pi 以使更改生效。
构建并刷写 RCP 固件
OTBR 在无线装置协同处理器 (RCP) 模式下支持 15.4 无线装置芯片。在此模式下,OpenThread 堆栈在主机端运行,并通过 IEEE802.15.4 收发器发送/接收帧。
按照 Build a Thread network with nRF52840 boards and OpenThread Codelab 中的第 4 步构建并刷写 nRF52840 RCP 设备:
$ script/build nrf52840 USB_trans
启动 OTBR 并验证状态
将 nRF52840 开发板连接到 Raspberry Pi 并启动 otbr-agent
服务:
$ sudo service otbr-agent restart
验证 otbr-agent
服务是否处于活跃状态:
$ sudo service otbr-agent status ● otbr-agent.service - Border Router Agent Loaded: loaded (/lib/systemd/system/otbr-agent.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2021-03-01 05:46:26 GMT; 2s ago Main PID: 2997 (otbr-agent) Tasks: 1 (limit: 4915) CGroup: /system.slice/otbr-agent.service └─2997 /usr/sbin/otbr-agent -I wpan0 -B wlan0 spinel+hdlc+uart:///dev/ttyACM0 Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Stop publishing service Mar 01 05:46:26 raspberrypi otbr-agent[2997]: [adproxy] Stopped Mar 01 05:46:26 raspberrypi otbr-agent[2997]: PSKc is not initialized Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Check if PSKc is initialized: OK Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Initialize OpenThread Border Router Agent: OK Mar 01 05:46:26 raspberrypi otbr-agent[2997]: Border router agent started. Mar 01 05:46:26 raspberrypi otbr-agent[2997]: [INFO]-CORE----: Notifier: StateChanged (0x00038200) [NetData PanId NetName ExtPanId] Mar 01 05:46:26 raspberrypi otbr-agent[2997]: [INFO]-PLAT----: Host netif is down
3. 建立 Thread 网络
ot-ctl
命令可用于控制 otbr-agent
服务。ot-ctl
接受所有 OpenThread CLI 命令,请参阅 OpenThread CLI 指南了解详情。
通过 OTBR 构建 Thread 网络:
$ sudo ot-ctl dataset init new Done $ sudo ot-ctl dataset commit active Done $ sudo ot-ctl ifconfig up Done $ sudo ot-ctl thread start Done
等待几秒钟,我们应该能够看到 OTBR 充当线程 leader
,并且 Thread 网络数据中有一个 off-mesh-routable
(OMR) 前缀:
$ sudo ot-ctl state leader Done $ sudo ot-ctl netdata show Prefixes: Prefixes: fd76:a5d1:fcb0:1707::/64 paos med 4000 Routes: fd49:7770:7fc5:0::/64 s med 4000 Services: 44970 5d c000 s 4000 44970 01 9a04b000000e10 s 4000 Done $ sudo ot-ctl ipaddr fda8:5ce9:df1e:6620:0:ff:fe00:fc11 fda8:5ce9:df1e:6620:0:0:0:fc38 fda8:5ce9:df1e:6620:0:ff:fe00:fc10 fd76:a5d1:fcb0:1707:f3c7:d88c:efd1:24a9 fda8:5ce9:df1e:6620:0:ff:fe00:fc00 fda8:5ce9:df1e:6620:0:ff:fe00:4000 fda8:5ce9:df1e:6620:3593:acfc:10db:1a8d fe80:0:0:0:a6:301c:3e9f:2f5b Done
4. 设置 SRP 客户端终端设备
构建并刷写 OT CLI
按照使用 nRF52840 开发板和 OpenThread Codelab 构建 Thread 网络第 5 步,构建并刷写 nRF52840 CLI 终端设备。
但是,CLI 节点需要 OT_SRP_CLIENT
和 OT_ECDSA
功能,而不是启用 OT_COMMISSIONER
和 OT_JOINER
。
因此,完整的构建调用应如下所示:
$ script/build nrf52840 USB_trans -DOT_SRP_CLIENT=ON -DOT_ECDSA=ON
加入 OTBR 网络
如需加入由 otbr-agent
服务创建的 Thread 网络,我们需要从 OTBR 设备获取活跃操作数据集。让我们返回 otbr-agent
命令行并获取活跃数据集:
$ sudo ot-ctl dataset active -x 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff Done
返回到 SRP 客户端节点屏幕会话,并设置活跃数据集:
> dataset set active 0e080000000000010000000300001235060004001fffe002083d3818dc1c8db63f0708fda85ce9df1e662005101d81689e4c0a32f3b4aa112994d29692030f4f70656e5468726561642d35326532010252e204103f23f6b8875d4b05541eeb4f9718d2f40c0302a0ff Done
然后,启动 Thread 接口:
> ifconfig up Done > thread start Done
等待几秒钟,并验证加入 Thread 网络是否成功:
> state child Done > netdata show Prefixes: fd76:a5d1:fcb0:1707::/64 paos med 4000 Routes: fd49:7770:7fc5:0::/64 s med 4000 Services: 44970 5d c000 s 4000 44970 01 9a04b000000e10 s 4000 Done > ipaddr fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 fda8:5ce9:df1e:6620:0:ff:fe00:4001 fda8:5ce9:df1e:6620:ed74:123:cc5d:74ba fe80:0:0:0:d4a9:39a0:abce:b02e Done
请确保网络数据与印在 OTBR 上的数据一致。我们现在可以 ping OTBR 的 OMR 地址:
> ping fd76:a5d1:fcb0:1707:f3c7:d88c:efd1:24a9 Done > 16 bytes from fd76:a5d1:fcb0:1707:f3c7:d88c:efd1:24a9: icmp_seq=1 hlim=64 time=49ms
5. 在最终设备上发布服务
mDNS 已广泛用于在链路本地上发布 DNS-SD 服务。但是多播消息会消耗过多带宽,并且很快就会耗尽低功耗设备的电池电量。Thread 使用单播 SRP 协议向边界路由器注册其服务,并依赖边界路由器通过 Wi-Fi 或以太网链路通告服务。
我们可以使用 srp client
命令注册服务。
前往 SRP 客户端节点屏幕会话,并自动启动 SRP 客户端:
> srp client autostart enable Done
设置将通过 Wi-Fi/以太网链路通告的主机名:
> srp client host name ot-host Done
为了让通过 Wi-Fi/以太网链路的设备连接到 Thread 终端设备,需要通告该终端设备的 OMR 地址:
> srp client host address fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 Done
最后,注册一项虚构 _ipps._tcp
服务:
> srp client service add ot-service _ipps._tcp 12345 Done
等待几秒钟,我们应该能够看到已注册的服务:
> srp client service instance:"ot-service", name:"_ipps._tcp", state:Registered, port:12345, priority:0, weight:0 Done
我们已完成所有设置工作,应该已经通过 Wi-Fi/以太网链路通告了 _ipps._tcp
服务。是时候探索并到达最终设备了!
6. 探索 Service
通过手机探索该服务
我们使用服务浏览器应用来发现 Android 手机上的 mDNS 服务,您也可以在 iOS 移动设备上找到等效应用。打开该应用后,系统应该会显示 _ipps._tcp
服务。
使用 Linux 主机发现服务
如果要从其他 Linux 主机发现该服务,您可以使用 avahi-browse
命令。
安装 avahi-daemon
和 avahi-utils
:
$ sudo apt-get install -y avahi-daemon avahi-utils
解析服务:
$ sudo service avahi-daemon start # Ensure the avahi daemon is started. $ avahi-browse -r _ipps._tcp + wlan0 IPv6 ot-service Secure Internet Printer local = wlan0 IPv6 ot-service Secure Internet Printer local hostname = [ot-host.local] address = [fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927] port = [12345] txt = [] ...
使用 macOS 主机发现服务
您可以在 macOS 上使用 dns-sd
来解析该服务:
$ dns-sd -Z _ipps._tcp local. Browsing for _ipps._tcp.local. DATE: ---Sun 14 Mar 2021--- 21:31:42.125 ...STARTING... ; To direct clients to browse a different domain, substitute that domain in place of '@' lb._dns-sd._udp PTR @ ; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names. ; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local ; names with the correct fully-qualified (unicast) domain name of the target host offering the service. _ipps._tcp PTR ot-service._ipps._tcp ot-service._ipps._tcp SRV 0 0 12345 ot-host.local. ; Replace with unicast FQDN of target host ot-service._ipps._tcp TXT "" ...
7. Ping 最终设备
通过手机执行 ping 操作
以 Pixel 手机为例,我们可以找出之前注册的服务“ot-service”的 OMR 地址。
现在,我们可以使用另一个 Network Analyzer 应用 ping OMR 地址。
遗憾的是,Android 版网络分析器应用不支持 ping 实用程序的 mDNS 查询,并且我们无法直接对主机名 ot-host.local
执行 ping 操作(我们可以使用该应用的 iOS 版本对主机名执行 ping 操作)。
从 Linux/macOS 主机执行 ping 操作
线程边界路由器会发送 ICMPv6 路由器通告 (RA),以便在 Wi-Fi/以太网链路上通告前缀(通过前缀信息选项)和路由(通过路由信息选项)。
准备 Linux 主机
请务必在您的主机上启用 RA 和 RIO:
- 如果未启用 IP 转发,
net.ipv6.conf.wlan0.accept_ra
应至少为1
,否则为2
。 - “
net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen
”不得小于64
。
对于大多数发行版,accept_ra
默认为 1
。但可能会有其他网络守护程序替换此选项(例如,Raspberry Pi 上的 dhcpcd
会将 accept_ra
替换成 0
)。您可以使用以下命令检查 accept_ra
值:
$ sudo sysctl -n net.ipv6.conf.wlan0.accept_ra 0
并将值设置为 1
(如果启用了 IP 转发,则为 2
),请使用以下命令:
$ sudo sysctl -w net.ipv6.conf.wlan0.accept_ra=1 Net.ipv6.conf.wlan0.accept_ra = 1
在大多数 Linux 发行版上,accept_ra_rt_info_max_plen
选项默认为 0
,请使用以下命令将其设置为 64
:
$ sudo sysctl -w net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen=64 net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen = 64
重新启动主机后,更改将会丢失。例如,将以下命令附加到 /etc/sysctl.conf
以永久启用 RIO:
$ net.ipv6.conf.wlan0.accept_ra_rt_info_max_plen = 64
现在更改这些配置可能为时已晚,因为 OTBR 已经在发送 RA 消息,并且两条未经请求的 RA 消息之间的间隔可能是几百秒。一种方法是断开 Wi-Fi AP 的连接并重新连接到 Wi-Fi AP 以发送路由器请求消息,这样 OTBR 会使用应求 RA 进行响应。另一种方法是在边界路由器上重启边界路由功能:
$ sudo ot-ctl br disable Done $ sudo ot-ctl br enable Done
如果您正在尝试重新连接 Wi-Fi 或重新启动以太网接口,请确保未使用 dhcpcd 来管理您的 Wi-Fi/以太网 IPv6 网络。因为每次重启接口时,dhcpcd 都会替换 accept_ra
选项,而您的 accept_ra
配置将会丢失。将以下几行内容附加到 dhcpcd 配置文件(例如 /etc/dhcpcd.conf
)中,以明确停用 dhcpcd 中的 IPv6:
noipv6 noipv6rs
您需要重新启动,才能使更改生效。
准备 macOS 主机
这两个 accept_ra*
选项默认处于启用状态,但您需要将系统至少升级到 macOS Big Sur。
Ping 主机名或 IPv6 地址
现在,我们可以使用命令 ping -6
(在 macOS 上为 ping6
)对主机名 ot-host.local
进行 ping 操作:
$ ping -6 ot-host.local. PING ot-host.local.(fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927)) 56 data bytes 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=1 ttl=63 time=170 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=2 ttl=63 time=64.2 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=3 ttl=63 time=22.8 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=4 ttl=63 time=37.7 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 (fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927): icmp_seq=5 ttl=63 time=28.7 ms ...
在 Linux 主机上,此命令可能会失败并显示 "Name or service not known"
错误。这是因为 ping
命令不会使用 mDNS 查询解析 ot-host.local.
名称。打开 /etc/nsswitch.conf
并将 mdns6_minimal
添加到以 hosts
开头的行:
hosts: files mdns4_minimal mdns6_minimal dns
当然,您可以随时直接 ping IPv6 地址:
$ ping -6 fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927 PING fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927(fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927) 56 data bytes 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=1 ttl=63 time=32.9 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=2 ttl=63 time=27.8 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=3 ttl=63 time=29.9 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=4 ttl=63 time=73.5 ms 64 bytes from fd76:a5d1:fcb0:1707:d3dc:26d3:f70b:b927: icmp_seq=5 ttl=63 time=26.4 ms ...
8. 为最终设备取消发布服务
要移除从 SRP 客户端节点注册的地址和服务,请执行以下操作:
> srp client host remove Done
您现在应该无法发现 _ipps._tcp
服务。
9. 恭喜
恭喜!您已成功将 OTBR 设置为线程边界路由器,以便为 Thread 终端设备提供双向 IP 连接和服务发现。
后续操作
查看下列 Codelab…