使用 OTNS 模拟线程网络

关于此 Codelab
schedule30 分钟
subject上次更新时间:2025年5月15日
account_circleSimon Lin, Colin Tan, Esko Dijk 编写

1. 简介

Thread 网状网络拓扑示意图

什么是 Thread 和 OTNS

Thread 是一种基于 IP 的低功耗无线网状网络协议,可实现安全的设备到设备通信和设备到云通信。线程网络可以适应拓扑变化,以避免单点故障。

Google 发布的 OpenThread 是 Thread 的开源实现。尽管代码大小和内存占用空间较小,但 OpenThread 支持 线程规范中定义的所有功能。

OpenThread 网络模拟器 (OTNS) 可用于通过在 posix 平台上运行模拟的 OpenThread 节点来模拟 Thread 网络。OTNS 提供了一个简单易用的 Web 界面 (OTNS-Web),用于可视化和操作模拟的 Thread 网络。还可以使用 Python 编写脚本进行模拟。

学习内容

  • 安装 OTNS 及其依赖项
  • 了解 OTNS-CLI 的基础知识
  • 如何在 OTNS-Web 中添加/移动/删除 OpenThread 节点
  • 使用 OTNS-Web 的其他实用功能来控制网络模拟
  • 验证 OpenThread 的无单点故障
  • 在 Wireshark 中查看 OpenThread 节点之间的数据流量

本 Codelab 重点介绍了 OTNS-CLI 和 OTNS-Web 的互动使用。不涵盖 OTNS 的其他功能(例如 Python 脚本)。

所需条件

  • 最好是 Linux x86_64,或安装了 Homebrew 的 Mac OS。Windows WSL2 中的 Ubuntu 22/24 也应该可以,但可能需要手动调整一些设置。
  • Git
  • 网络浏览器。OTNS-Web 使用网络浏览器显示模拟。
  • 线程入门。您需要了解线程的基本概念,才能理解此 Codelab 中介绍的内容。

术语

“路由器”一词是 Thread Mesh 扩展器(最初称为 Thread 路由器)的技术术语。“节点”是指 OTNS 模拟中的任何模拟 OpenThread 设备。

2. 安装

获取 OTNS 代码

$ git clone https://github.com/openthread/ot-ns.git ./otns
$ cd otns

此 Codelab 中的所有后续控制台命令均从 otns 目录运行。

引导和安装

bootstrap 脚本将安装依赖项(包括 Python3 和 Go/Golang,如果需要)并安装 OTNS。它还会构建可直接在模拟中使用的各种 OT 节点类型,并执行一些基本测试。由于节点构建,此过程可能需要几分钟。

$ ./script/bootstrap
....
....
OTNS installed - use 'otns' to start it.
$

系统可能会要求您输入 sudo 的密码。

如果 otns 未正确安装

脚本可能会报告如下错误:

....
OTNS installed - please add ~/go/bin to your PATH variable first, to use it.
$

在这种情况下,您需要向 $PATH. 添加 $(go env GOPATH)/bin

如果出现其他错误,您可以创建 GitHub 问题

3. 首次运行 OTNS

运行 otns

$ otns
>_ ← OTNS-CLI prompt

成功启动后,OTNS 将进入 CLI 控制台 (OTNS-CLI) 并启动网络可视化和管理的 Web 浏览器 (OTNS-Web):

启动时的 OTNS-Web 窗口

如果您在 OTNS-Web 中看到的只有空白页面,则可能是因为您的浏览器未启用 WebGL。如需了解如何启用 WebGL,请参阅 https://superuser.com/a/836833

在以下部分中,您将学习如何通过 OTNS-CLIOTNS-Web 管理 OTNS 模拟。

4. 了解 OTNS-CLI 和 OTNS-Web

OTNS-CLI

OTNS-CLI 是用于管理 OTNS 模拟的命令行界面 (CLI)。

$ otns
>_ ← OTNS-CLI prompt

您可以通过 OTNS-CLI 输入命令。如需查看完整的命令列表,请参阅 OTNS CLI 参考文档。别担心,您只需在此 Codelab 中使用其中的几个命令。

输入 help 命令可大致了解 CLI 命令。此列表与 CLI 参考文档完全相同。

> help
add             Add a node to the simulation and get the node ID.
....
....
Done
> 

如需获取有关特定命令的更多帮助,请使用该命令的名称,例如:

> help add
add
  Add a node to the simulation and get the node ID.
  
Definition:
....
....
> 

OTNS-Web

OTNS-Web 是 OTNS 的网络可视化和管理工具。它可直观地显示模拟线程网络的节点、消息和链接。请注意 OTNS-Web 的各种元素:

OTNS-Web 元素说明

5. 添加节点

通过 OTNS-CLI 添加节点

将线程路由器添加到模拟中:

> add router
1
Done

您应该会看到在 OTNS-Web 中创建的节点。该节点最初是路由器,几秒钟后便会成为主副本:

一个节点处于主导角色

为了便于以交互方式启动模拟,默认情况下,每个新的 OpenThread 节点都使用一组标准网络参数进行调试。

通过 OTNS-CLI 添加更多节点

现在,我们将添加一些不同类型的节点。

> add fed
2
Done
> add med
3
Done
> add sed
4
Done

等待几秒钟,让节点合并到一个分区中。您应该会在 OTNS-Web 中看到这些节点:

包含 4 个节点的 Thread 网络

此外,在 OTNS-Web 中,您还可以选择任意节点,以获取包含该节点的更多信息的面板。例如,在下图中,选择了节点 1。该面板中的“角色”条目确认它是领先变体。

包含 4 个节点的线程网络,其中节点 1 处于选中状态

通过 OTNS-Web 添加节点

您还可以通过 OTNS-Web 添加节点。点击 Action BarNew Router 按钮。您应该会在所选节点的右侧看到一个正在创建的节点。新路由器应加入现有的线程分区:

添加了路由器,总计 5 个节点

此外,您还可以点击操作栏上的 FED、MED、SSED 和 BR 按钮,创建其他类型的节点。现在,总共有 9 个节点。如果需要,您可以将某些节点拖动到其他位置,以创建不同的物理网络拓扑。

添加了多个新节点,总计 9 个节点

现在,您已创建一个包含多个节点的分区线程网络。在下一部分中,我们将调整模拟速度,以加快模拟速度。

6. 调整速度

目前,模拟应该以 1X 的速度运行,这意味着,模拟到目前为止所用的时间与我们创建第一个节点以来的实际时间相同。

通过 OTNS-CLI 调整速度

您可以通过 OTNS-CLI 调整模拟速度。

将模拟速度设为 100X

> speed 100
Done

您应该会发现节点发送消息的频率比之前高得多。

将模拟速度设为 MAX

> speed max
Done

现在,OTNS 会尽可能快速地进行模拟,因此您应该会看到节点发送大量消息。

暂停模拟

> speed 0
Done

将模拟速度设置为 0 会暂停模拟。

以正常速度恢复模拟

> speed 1
Done

将模拟速度设置为大于 0 的值会恢复模拟。

通过 OTNS-Web 调整速度

速度控制按钮

Action Bar 上找到速度控制按钮 速度控制按钮。这些按钮会显示当前的模拟速度,可用于调整模拟速度以及暂停/继续模拟。

加快模拟速度

您可以点击 提高速度按钮 按钮加快模拟速度,直到速度达到 MAX: 最大模拟速度指示器

减慢模拟速度

您可以点击 “减速”按钮 按钮来减慢模拟速度。

暂停模拟

在模拟运行时,点击 “暂停”按钮 按钮可暂停模拟。该按钮将更改为 “播放”按钮

恢复模拟

在模拟暂停时,点击 “播放”按钮 按钮可恢复模拟。该按钮将恢复为 “暂停”按钮

将模拟速度设为 10X

为节省时间,请使用

OTNS-CLI 将模拟速度调整为

10X以便我们更快地观察网络中的拓扑变化。

> speed 10
Done

7. 开启/关闭收音机

现在,模拟场景应至少包含 2 个路由器(六边形)、可能包含一个边界路由器(方形)和许多子路由器,并且以 10 倍的速度运行。

找到 2 个路由器中的当前主路由器(红色边框),然后点击一次以将其选中:

已选择主节点 1 的线程网络

关闭无线通信

点击操作栏上的 “关闭收音机”按钮 按钮,关闭主节点的无线电。关闭无线电后,主讲者将无法发送或接收消息。

等待大约 12 秒(在模拟时间中为 120 秒),让另一个路由器或边界路由器成为新的主路由器:

系统会创建一个新分区,并将节点 9 作为新的主副本

线程网络会通过使用新的主副本形成新的分区,自动从主副本故障中恢复。新分区还具有新的分区颜色。

打开无线通信

选择已关闭无线电的领导设备。点击 Action Bar 上的 “开启”无线电按钮 按钮以恢复无线电连接:

节点 1 在其无线装置重新开启后加入分区

恢复无线连接后,主副本应重新连接到网络。

8. 移动节点

借助 OTNS,用户可以通过 OTNS-CLIOTNS-Web 轻松移动节点。

通过 OTNS-CLI 移动节点

将边界路由器节点 9 移至新位置:

> move 9 50 50
Done

通过 OTNS-Web 移动节点

通过拖动将节点 5 一直移动到右下角。由于节点 5 现在不在其他路由器的无线覆盖范围内,因此它会使用新的分区 ID 形成自己的分区。您可以在节点信息面板中点击节点,查看分区 ID。

节点 5 移离其他节点,并形成一个新的分区

请注意,节点 5 和节点 9 之间仍然会绘制一条绿色线。这通常是因为子项的过时信息仍保留在之前父项的子表中。或者,它可能是关于节点 9 和节点 5 之间之前路由器到路由器链接的过时信息。(在本例中,可能还存在渲染 bug。)最终,在适当的超时后,节点上的过时信息会被清理。

9. 删除节点

通过 OTNS-CLI 删除节点

删除节点 5:

> del 5
Done

节点 5 应从模拟中消失:

将节点 5 从模拟中删除

通过 OTNS-Web 删除节点

选择边界路由器节点 9,然后点击 Action Bar 上的 “删除”按钮 按钮以删除节点 9:

边界路由器节点 9 已被删除

Node 1 应成为新分区的主副本,所有其余节点都将作为子副本附加到节点 1。

10. OTNS-CLI 节点上下文

OTNS-CLI 提供了节点上下文模式,可让开发者轻松与节点互动,以便诊断节点的状态。此外,还可以在此模式下启动节点操作。

进入节点上下文模式

输入节点 1 的节点上下文:

> node 1
Done
node 1>

CLI 提示符已更改为 node 1>,表示当前节点上下文。您可以输入要在节点上执行的 OpenThread CLI 命令,就像直接与节点交互一样。

在节点上下文中执行命令

node 1> state
leader
Done
node 1> channel
11
Done
node 1> panid
0xface
Done
node 1> networkname
otns
Done
node 1> ipaddr
fdde:ad00:beef:0:0:ff:fe00:fc00
fdde:ad00:beef:0:0:ff:fe00:b400
fd00:f00d:cafe:0:2505:8719:3685:ebfb
fdde:ad00:beef:0:4fd9:b9ba:44e0:96cb
fe80:0:0:0:e86a:e07:ec97:777
Done

切换到其他节点上下文

node 1> node 2
Done
node 2> 

退出节点上下文

node 1> exit
Done
>

退出节点上下文的另一种方法是使用 node 0 命令。

11. 查看节点日志和数据包捕获

OpenThread 节点日志

默认情况下,OTNS 会为所有模拟的 OpenThread 节点生成详细的日志文件。您可以在 ./tmp 目录中查看这些文件。文件名为 0_.log。例如,日志文件摘录如下所示:

7616488 00:00:06.326 [I] MeshForwarder-: Received IPv6 UDP msg, len:90, chksum:5915, ecn:no, from:ca72650db7b856af, sec:no, prio:net, rss:-58.0
7616488 00:00:06.326 [I] MeshForwarder-:     src:[fe80:0:0:0:c872:650d:b7b8:56af]:19788
7616488 00:00:06.326 [I] MeshForwarder-:     dst:[ff02:0:0:0:0:0:0:1]:19788
7616488 00:00:06.326 [D] Mle-----------: Receive MLE message
7616488 00:00:06.326 [D] Mac-----------: Idle mode: Radio receiving on channel 11
7657544 00:00:06.367 [D] Mac-----------: ==============================[RX len=063]==============================
7657544 00:00:06.367 [D] Mac-----------: | 41 D8 7F CE FA FF FF 46 | 74 5A 33 9E 76 51 4E 7F | A......FtZ3.vQN. |
7657544 00:00:06.367 [D] Mac-----------: | 3B 02 F0 4D 4C 4D 4C 81 | E6 00 15 03 00 00 00 00 | ;..MLML......... |
7657544 00:00:06.367 [D] Mac-----------: | 00 00 00 01 46 86 7D FE | 06 CC DB 94 86 9C 88 0B | ....F.}......... |
7657544 00:00:06.367 [D] Mac-----------: | 1C 1E 26 9B 8D 21 2E 65 | 53 5A 43 4E A2 59 D6    | ..&..!.eSZCN.Y.  |
7657544 00:00:06.367 [D] Mac-----------: ------------------------------------------------------------------------
7657544 00:00:06.367 [I] MeshForwarder-: Received IPv6 UDP msg, len:84, chksum:81e6, ecn:no, from:4e51769e335a7446, sec:no, prio:net, rss:-48.0
7657544 00:00:06.367 [I] MeshForwarder-:     src:[fe80:0:0:0:4c51:769e:335a:7446]:19788
7657544 00:00:06.367 [I] MeshForwarder-:     dst:[ff02:0:0:0:0:0:0:2]:19788
7657544 00:00:06.367 [D] Mac-----------: Idle mode: Radio receiving on channel 11
7833912 00:00:06.543 [I] Mle-----------: AttachState ParentReq -> Idle
7833912 00:00:06.543 [N] RouterTable---: Allocate router id 12
7833912 00:00:06.543 [N] Mle-----------: RLOC16 fffe -> 3000
7833912 set node RLOC16: fffe -> 3000
7833912 00:00:06.543 [D] SubMac--------: RadioShortAddress: 0x3000
7833912 00:00:06.543 [N] Mle-----------: Role detached -> leader
7833912 00:00:06.543 [N] Mle-----------: Partition ID 0x24c35f10
7833912 00:00:06.543 [I] RouterTable---: Route table
7833912 00:00:06.543 [I] RouterTable---:     12 0x3000 - me - leader

左侧显示的是绝对模拟时间(以微秒为单位)。hh:mm:ss 时间戳显示的是 OpenThread 节点自己的日志时间戳,该时间戳可能与绝对模拟时间不同。

Wireshark 数据包捕获

默认情况下,所有传输的 IEEE 802.15.4 帧都会捕获到 PCAP 文件 current.pcap 中。在模拟期间或之后,Wireshark 可以读取此文件。由于 Thread 采用链路层加密,因此需要在 Wireshark 中执行一次性配置操作,才能正确为 OTNS 设置解密密钥。默认情况下,系统会使用一个众所周知的网络密钥,以便 Wireshark 轻松解密帧。

请参阅以下屏幕截图,了解 Wireshark 中 OpenThread 数据包检查的示例。

Wireshark 中 OpenThread 数据包分析的屏幕截图

如需配置解密密钥,请在菜单中依次选择修改 -> 偏好设置。然后,在偏好设置窗口中,依次选择 Protocols -> IEEE 802.15.4。点击“解密密钥”旁边的修改...按钮。点击 + 以创建新条目,输入键 00112233445566778899aabbccddeeff(32 个字符),然后在“键哈希”字段中选择“线程哈希”。“解密密钥索引”可以保留为 0。然后点击 OK(确定),然后再次点击 OK(确定)。现在,OTNS PCAP 文件在加载时应正确解密。

“时间”列中显示的时间戳(以秒为单位)对应于 OpenThread 节点日志中显示的绝对模拟时间值。这样,您就可以更轻松地将日志消息与传输或接收的无线帧相关联。不过,在精确到微秒级的情况下,这些值通常并不完全相同:在 OpenThread 堆栈请求发送无线电帧后,模拟的 IEEE 802.15.4 无线电硬件可能会增加一些额外的延迟时间。

12. 恭喜

恭喜,您已成功执行第一个 OTNS 模拟!

您已了解如何安装 OTNS 及其依赖项。您使用 OpenThread 模拟节点启动了 OTNS 模拟。您已经学习了如何通过 OTNS-CLIOTNS-Web 以各种方式操控模拟。

现在,您已经了解了 OTNS 是什么以及如何使用 OTNS 来模拟 OpenThread 网络。

后续操作

查看下列 Codelab…

参考文档