使用 OpenThread 模拟 Thread 网络

1. 简介

26b7f4f6b3ea0700

Google 发布的 OpenThreadThread 网络协议的开源实现。Google Nest 发布了 OpenThread,供开发者广泛使用 Nest 产品中使用的技术,以加快智能互联家居产品的开发。

Thread 规范为家庭应用定义了基于 IPv6 的可靠、安全、低功耗的无线设备到设备通信协议。OpenThread 实现了所有 Thread 网络层,包括 IPv6、6LoWPAN、IEEE 802.15.4,以及 MAC 安全、网状链路建立和网格路由。

此 Codelab 将引导您在模拟设备上模拟 Thread 网络。

学习内容

  • 如何设置 OpenThread 构建工具链
  • 如何模拟 Thread 网络
  • 如何对 Thread 节点进行身份验证
  • 如何使用 OpenThread 守护程序管理 Thread 网络

所需条件

  • git
  • 具备 Linux、网络路由的基础知识

2. 设置构建系统

Git

您必须安装 Git 才能完成此 Codelab。请先下载并安装,然后再继续。

安装后,请按照针对特定操作系统的说明下载并构建 OpenThread。

适用于 Mac OS X 的 XCode

需要使用 XCode 才能在 Mac OS X 上安装和构建 OpenThread。

安装 XCode 后,再安装 XCode 命令行工具:

$ xcode-select --install

在 Linux / Mac OS X 上构建

以下安装说明已在 Ubuntu Server 14.04 LTS 和 Mac OS X Sierra 10.12.6 上进行了测试。

安装 OpenThread。bootstrap 命令可确保工具链已安装并且已正确配置环境:

$ mkdir -p ~/src
$ cd ~/src
$ git clone --recursive https://github.com/openthread/openthread.git
$ cd openthread
$ ./script/bootstrap

使用 Windows

如果您更喜欢 Windows,建议您试用此 Codelab 的 Docker 版本。

3. 构建 OpenThread 应用

安装完成后,构建示例 OpenThread 应用。在此 Codelab 中,我们使用的是模拟示例。

$ cd ~/src/openthread
$ ./script/cmake-build simulation

现在,构建 OpenThread 守护程序:

$ ./script/cmake-build posix -DOT_DAEMON=ON

4. 模拟 Thread 网络

您将在此 Codelab 中使用的示例应用演示了一个超小的 OpenThread 应用,该应用通过基本命令行界面 (CLI) 公开 OpenThread 配置和管理界面。

本练习将引导您完成从另一个模拟 Thread 设备 ping 一台模拟 Thread 设备所需的最少步骤。

下图介绍了基本的 Thread 网络拓扑。在本练习中,我们将模拟绿色圆圈内的两个节点:一个 Thread Leader 和 Thread Router,它们之间只有一个连接。

6e3aa07675f902dc

Ping 节点

1. 启动节点 1

进入 openthread 目录,并使用 ot-cli-ftd 二进制文件为模拟的 Thread 设备生成 CLI 进程。

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 1

注意:如果运行此命令后没有看到 > 提示,请按 enter

此二进制文件会实现在 POSIX 上模拟的 OpenThread 设备。IEEE 802.15.4 无线电驱动程序基于 UDP 实现(IEEE 802.15.4 帧在 UDP 有效负载内传递)。

1 的参数是一个文件描述符,表示“出厂分配”的最小有效位适用于模拟设备的 IEEE EUI-64。在绑定到 UDP 端口以进行 IEEE 802.15.4 无线电模拟时(端口 = 9000 + 文件描述符),也会使用此值。此 Codelab 中模拟 Thread 设备的每个实例将使用不同的文件描述符。

注意:在为模拟设备生成进程时,只能使用此 Codelab 中所述的 1 或更高版本的文件描述符。文件描述符 0 已预留作其他用途。

创建一个新的操作数据集,并将其提交为活跃数据集。操作数据集是您要创建的 Thread 网络的配置。

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 20
Channel Mask: 07fff800
Ext PAN ID: d6263b6d857647da
Mesh Local Prefix: fd61:2344:9a52:ede0/64
Network Key: e4344ca17d1dca2a33f064992f31f786
Network Name: OpenThread-c169
PAN ID: 0xc169
PSKc: ebb4f2f8a68026fc55bcf3d7be3e6fe4
Security Policy: 0, onrcb
Done

提交此数据集作为活跃数据集:

> dataset commit active
Done

启动 IPv6 接口:

> ifconfig up
Done

启动 Thread 协议操作:

> thread start
Done

等待几秒钟,并验证设备是否已成为线程主要设备。主要设备是负责管理路由器 ID 分配的设备。

> state
leader
Done

查看分配给节点 1 的 Thread 接口的 IPv6 地址(输出将有所不同):

> ipaddr
fd61:2344:9a52:ede0:0:ff:fe00:fc00
fd61:2344:9a52:ede0:0:ff:fe00:5000
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
fe80:0:0:0:94da:92ea:1353:4f3b
Done

请注意特定的 IPv6 地址类型:

  • fd 开头 = Mesh-local
  • fe80 开头 = link-local

网格本地地址类型进一步分类:

  • 包含 ff:fe00 = 路由器定位器 (RLOC)
  • 不包含 ff:fe00 = 端点标识符 (EID)

在控制台输出中找到此 EID,请记下此 ID 以备日后使用。在上面的示例输出中,EID 为:

fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6

2. 启动节点 2

打开新终端,导航到 openthread 目录并生成 CLI 进程。这是您的第二个模拟 Thread 设备:

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 2

注意:如果运行此命令后没有看到 > 提示,请按 enter

使用与节点 1 的操作数据集相同的值配置 Thread 网络密钥和 PAN ID:

> dataset networkkey e4344ca17d1dca2a33f064992f31f786
Done
> dataset panid 0xc169
Done

提交此数据集作为活跃数据集:

> dataset commit active
Done

启动 IPv6 接口:

> ifconfig up
Done

启动 Thread 协议操作:

> thread start
Done

设备会将自身初始化为子级。Thread 子级等同于终端设备,这是一种 Thread 设备,仅通过父级设备传输和接收单播流量。

> state
child
Done

您应该会在 2 分钟内看到状态从 child 切换到 router。Thread Router 能够在 Thread 设备之间路由流量。它也称为父级。

> state
router
Done

验证网络

验证网状网络的一种简单方法是查看路由器表。

1. 检查连接情况

在节点 2 上,获取 RLOC16。RLOC16 是设备的 RLOC IPv6 地址的最后 16 位。

> rloc16
5800
Done

在节点 1 上,检查节点 2 的 RLOC16 的路由器表。首先确保节点 2 已切换到路由器状态。

> router table
| ID | RLOC16 | Next Hop | Path Cost | LQI In | LQI Out | Age | Extended MAC  |
+----+--------+----------+----------+-------+---------+-----+------------------+
| 20 | 0x5000 |       63 |         0 |     0 |      0 |   0 | 96da92ea13534f3b |
| 22 | 0x5800 |       63 |         0 |     3 |      3 |  23 | 5a4eb647eb6bc66c |

在表中找到了节点 1 的 RLOC (0xa800),确认它已连接到网格。

2. 从节点 2 对节点 1 执行 ping 操作

验证两个模拟 Thread 设备之间的连接。在节点 2 中,使用 ping 指定分配给节点 1 的 EID:

> ping fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
> 16 bytes from fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6: icmp_seq=1
hlim=64 time=12ms

enter 以返回到 > CLI 提示符。

测试网络

现在,您可以在两台模拟 Thread 设备之间成功执行 ping 操作,接下来可以将一个节点离线以测试网状网络。

返回到节点 1 并停止线程:

> thread stop
Done

切换到节点 2 并检查状态。在两分钟内,节点 2 检测到主要节点(节点 1)已离线,您应该会看到节点 2 转换为网络的 leader

> state
router
Done
...
> state
leader
Done

确认后,停止 Thread 并将节点 2 恢复出厂设置,然后再退出。恢复出厂设置,以确保我们在本练习中使用的 Thread 网络凭据不会转移到下一个练习中。

> thread stop
Done
> factoryreset
>
> exit

同时恢复出厂设置并退出节点 1:

> factoryreset
>
> exit

如需了解所有可用的 CLI 命令,请参阅 OpenThread CLI 参考

5. 通过“调试”功能对节点进行身份验证

在之前的练习中,您设置了一个包含两台模拟设备的 Thread 网络,并已验证连接情况。但是,这仅允许未经身份验证的 IPv6 链路本地流量在设备之间传递。如需在节点之间路由全局 IPv6 流量(通过 Thread 边界路由器与互联网),必须对节点进行身份验证。

为了进行身份验证,一台设备必须充当调试器。该 Commissioner 是目前为新 Thread 设备选择的身份验证服务器,也是为设备提供加入网络所需的网络凭据的授权方。

在本练习中,我们将使用与之前相同的双节点拓扑。对于身份验证,Thread Leader 将充当 Commissioner,Thread Router 将作为 Joiner。

d6a67e8a0d0b5dcb.png

1. 创建网络

如果从之前的练习继续,您应该已经打开了两个终端窗口。如果没有,请确保两个设备已打开并可供使用。其中一个将用作节点 1,另一个将用作节点 2。

在 Node 1 中,生成 CLI 进程:

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 1

注意:如果运行此命令后没有看到 > 提示,请按 enter

创建一个新的操作数据集,将其提交为活动数据集,然后启动 Thread:

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 12
Channel Mask: 07fff800
Ext PAN ID: e68d05794bf13052
Mesh Local Prefix: fd7d:ddf7:877b:8756/64
Network Key: a77fe1d03b0e8028a4e13213de38080e
Network Name: OpenThread-8f37
PAN ID: 0x8f37
PSKc: f9debbc1532487984b17f92cd55b21fc
Security Policy: 0, onrcb
Done

提交此数据集作为活跃数据集:

> dataset commit active
Done

启动 IPv6 接口:

> ifconfig up
Done

启动 Thread 协议操作:

> thread start
Done

等待几秒钟,并验证设备是否已成为线程主要设备:

> state
leader
Done

2. 开始担任“专员”角色

在节点 1 上,启动 Commissioner 角色:

> commissioner start
Done

允许具有 J01NME 连接者凭据的任何连接者(通过使用 * 通配符)代理网络。连接者是由真人管理员添加到委托 Thread 网络的设备。

> commissioner joiner add * J01NME
Done

3. 开始“Joiner”角色

在第二个终端窗口中,生成一个新的 CLI 进程。这是节点 2。

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 2

在节点 2 上,使用 J01NME Joiner 凭据启用 Joiner 角色。

> ifconfig up
Done
> joiner start J01NME
Done

... 请等待几秒钟以进行确认 ...

Join success

作为连接器,设备(节点 2)已成功通过调试器(节点 1)进行身份验证并收到 Thread 网络凭据。

现在节点 2 已通过身份验证,请启动 Thread:

> thread start
Done

4. 验证网络身份验证

检查节点 2 上的 state,以验证它现在是否已加入网络。在两分钟内,节点 2 从 child 转换为 router

> state
child
Done
...
> state
router
Done

5. 重置配置

重置配置,为下一个练习做准备。在每个节点上,停止 Thread,恢复出厂设置,然后退出模拟 Thread 设备:

> thread stop
Done
> factoryreset
>
> exit

您可能需要按几次 enter,才能在执行 factoryreset 命令之后再次显示 > 提示符。

6. 使用 OpenThread 守护程序管理网络

在本练习中,我们将模拟一个 CLI 实例(单个嵌入式 SoC 线程设备)和一个无线装置协同处理器 (RCP) 实例。

ot-daemon 是 OpenThread Posix 应用的一种模式,使用 UNIX 套接字作为输入和输出,以便 OpenThread 核心可以作为服务运行。客户端可以使用 OpenThread CLI 作为协议连接到套接字,从而与此服务进行通信。

ot-ctlot-daemon 提供的 CLI,用于管理和配置 RCP。使用此参数,我们会将 RCP 连接到 Thread 设备创建的网络。

使用 ot-daemon

本练习将使用三个终端窗口,分别与以下内容相对应:

  1. 模拟 Thread 设备的 CLI 实例(节点 1)
  2. ot-daemon流程
  3. ot-ctl 个 CLI 实例

如果从之前的练习继续,您应该已经打开了两个终端窗口。打开第三个终端窗口,确保有三个终端窗口可用于本练习。

1. 启动节点 1

在第一个终端窗口中,为您的模拟 Thread 设备生成 CLI 进程:

$ cd ~/src/openthread
$ ./build/simulation/examples/apps/cli/ot-cli-ftd 1

注意:如果运行此命令后没有看到 > 提示,请按 enter

创建一个新的操作数据集,将其提交为活动数据集,然后启动 Thread:

> dataset init new
Done
> dataset
Active Timestamp: 1
Channel: 13
Channel Mask: 07fff800
Ext PAN ID: 97d584bcd493b824
Mesh Local Prefix: fd55:cf34:dea5:7994/64
Network Key: ba6e886c7af50598df1115fa07658a83
Network Name: OpenThread-34e4
PAN ID: 0x34e4
PSKc: 38d6fd32c866927a4dfcc06d79ae1192
Security Policy: 0, onrcb
Done

提交此数据集作为活跃数据集:

> dataset commit active
Done

启动 IPv6 接口:

> ifconfig up
Done

启动 Thread 协议操作:

> thread start
Done

查看分配给节点 1 的 Thread 接口的 IPv6 地址:

> ipaddr
fd55:cf34:dea5:7994:0:ff:fe00:fc00
fd55:cf34:dea5:7994:0:ff:fe00:d000
fd55:cf34:dea5:7994:460:872c:e807:c4ab
fe80:0:0:0:9cd8:aab6:482f:4cdc
Done
>

模拟 Thread 网络步骤中所述,一个地址是链路本地 (fe80),三个地址是网状网本地 (fd)。EID 是地址中不包含 ff:fe00 的网状网本地地址。在此示例输出中,EID 为 fd55:cf34:dea5:7994:460:872c:e807:c4ab

ipaddr 输出中找出特定 EID,该 EID 将用于与该节点通信。

2. 启动 ot-daemon

在第二个终端窗口中,转到 openthread 目录,然后为 RCP 节点启动 ot-daemon(我们称为节点 2)。使用 -v 详细标志,以便查看日志输出并确认其正在运行,并确保使用 sudo

$ cd ~/src/openthread
$ sudo ./build/posix/src/posix/ot-daemon -v \
    'spinel+hdlc+forkpty://build/simulation/examples/apps/ncp/ot-rcp?forkpty-arg=2'

如果成功,详细模式下的 ot-daemon 会生成类似于以下内容的输出:

ot-daemon[12463]: Running OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; POSIX; Aug 30 2022 10:55:05
ot-daemon[12463]: Thread version: 4
ot-daemon[12463]: Thread interface: wpan0
ot-daemon[12463]: RCP version: OPENTHREAD/thread-reference-20200818-1938-g0f10480ed; SIMULATION; Aug 30 2022 10:54:10

请将此终端保持打开状态,并在后台运行。您无需再在其中输入任何命令。

3. 使用 ot-ctl 加入网络

我们尚未委托节点 2 (ot-daemon RCP) 连接到任何 Thread 网络。这正是 ot-ctl 的用武之地。ot-ctl 使用与 OpenThread CLI 应用相同的 CLI。因此,您可以采用与其他模拟 Thread 设备相同的方式控制 ot-daemon 节点。

在第三个终端窗口中,启动 ot-ctl

$ sudo ./build/posix/src/posix/ot-ctl
>

注意:如果运行此命令后没有看到 > 提示,请按 enter

您将在第三个终端窗口中使用 ot-ctl 来管理您通过 ot-daemon 在第二个终端窗口中启动的节点 2(RCP 节点)。检查节点 2 的 state

> state
disabled
Done

获取节点 2 的 eui64,以限制联接到特定连接符:

> eui64
18b4300000000001
Done

在节点 1(第一个终端窗口)上,启动调试器并将联接限制为仅连接到该 eui64:

> commissioner start
Done
> commissioner joiner add 18b4300000000001 J01NME
Done

在节点 2(第三个终端窗口)上,打开网络接口并加入网络:

> ifconfig up
Done
> joiner start J01NME
Done

... 请等待几秒钟以进行确认 ...

Join success

作为连接者,RCP(节点 2)已成功通过调试器(节点 1)进行身份验证并收到 Thread 网络凭据。

现在,将节点 2 加入 Thread 网络:

> thread start
Done

4. 验证网络身份验证

检查节点 2 上的 state,以验证它现在是否已加入网络。在两分钟内,节点 2 从 child 转换为 router

> state
child
Done
...
> state
router
Done

5. 验证连接

使用 Ctrl+Dexit 命令退出 ot-ctl,在主机命令行中 ping 节点 1(使用其 EID 和 ping6 命令)。如果 ot-daemon RCP 实例已成功加入 Thread 网络并与之通信,则 ping 操作会成功:

$ ping6 -c 4 fd55:cf34:dea5:7994:460:872c:e807:c4ab
PING fd55:cf34:dea5:7994:460:872c:e807:c4ab (fd55:cf34:dea5:7994:460:872c:e807:c4ab): 56 data bytes
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=0 ttl=64 time=4.568 ms
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=1 ttl=64 time=6.396 ms
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=2 ttl=64 time=7.594 ms
64 bytes from fd55:cf34:dea5:7994:460:872c:e807:c4ab: icmp_seq=3 ttl=64 time=5.461 ms
--- fd55:cf34:dea5:7994:460:872c:e807:c4ab ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max/stddev = 4.568/6.005/7.594/1.122 ms

7. 恭喜!

您已成功使用 OpenThread 模拟了您的第一个 Thread 网络。也很棒!

在此 Codelab 中,你学习了如何:

  • 设置 OpenThread 构建工具链
  • 模拟 Thread 网络
  • 对 Thread 节点进行身份验证
  • 使用 OpenThread 守护程序管理 Thread 网络

如需了解更多信息,请查看以下参考资料: