使用 OTNS 模擬 Thread 網路

1. 簡介

Thread 網狀網路拓撲的印象

什麼是 Thread 和 OTNS

Thread 是以 IP 為基礎的低功耗無線網狀網路通訊協定,可讓裝置之間及裝置與雲端之間安全通訊。Thread 網路可因應拓撲變化,避免單點故障。

Google 發布的 OpenThread 是 Thread 的開放原始碼實作項目。OpenThread 的程式碼和記憶體用量都很小,但支援 Thread 規格中定義的所有功能。

OpenThread 網路模擬器 (OTNS) 可在 posix 平台上執行模擬的 OpenThread 節點,藉此模擬 Thread 網路。OTNS 提供簡單易用的網頁介面 (OTNS-Web),可讓您查看及操作模擬的 Thread 網路。您也可以使用 Python 編寫指令碼來模擬。

課程內容

  • 安裝 OTNS 及其依附元件
  • 瞭解 OTNS-CLI 的基本概念
  • 如何在 OTNS-Web 中新增/移動/刪除 OpenThread 節點
  • 使用 OTNS-Web 的其他實用功能控制網路模擬
  • 驗證 OpenThread 的無單點故障
  • 在 Wireshark 中查看 OpenThread 節點之間的資料流量

本程式碼研究室著重於 OTNS-CLI 和 OTNS-Web 的互動式使用方式。本文不包含 OTNS 的其他功能,例如 Python 腳本。

軟硬體需求

  • Thread 基礎知識。您必須瞭解執行緒的基本概念,才能瞭解本程式碼研究室的內容。
  • 建議使用 Linux x86_64,或安裝 Homebrew 的 Mac OS。Windows WSL2 中的 Ubuntu 24 以上版本也應適用,但可能需要手動調整部分設定。
  • Git
  • 網路瀏覽器。OTNS-Web 會使用網路瀏覽器顯示模擬結果。
  • Wireshark 網路通訊協定分析器 (選用)。
  • Go 1.23 以上版本。
    • 安裝指令碼會檢查已安裝的 Go 版本。
    • 如果未安裝 Go,系統會安裝版本 >= 1.23 (如果套件管理工具提供)。
    • 如果套件管理工具無法提供,則必須手動安裝。
    • 請注意,Ubuntu 24.04 以下版本不會自動支援 Go 1.23。詳情請參閱 Ubuntu 說明文件的「Available Golang versions」(可用的 Golang 版本) 頁面。您可以手動安裝、使用 snap 或其他程序。
  • Python 3.9 以上版本。
    • 安裝指令碼會檢查已安裝的 Python 版本。
    • 如果尚未安裝 Python 3,系統會從套件管理工具安裝版本 >= 3.9 (如有)。
    • 如果套件管理工具無法提供,則必須手動安裝。

術語

「路由器」一詞是 Thread 網狀網路擴充器的技術用語,最初稱為 Thread 路由器。「節點」是指 OTNS 模擬中的任何模擬 OpenThread 裝置。

2. 安裝

取得 OTNS 驗證碼

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

本程式碼研究室中後續的所有控制台指令,都是從 otns 目錄執行。

啟動並安裝

bootstrap 指令碼會安裝依附元件 (包括 Python 3 和 Go/Golang,視需要) 並安裝 OTNS。請注意,如果無法自動安裝特定依附元件 (例如 Python 版本 >= 3.9 或 Go 版本 >= 1.23),指令碼可能會停止執行。如要自動安裝,必須在作業系統設定的套件存放區中找到套件。

指令碼也會建構各種 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),並啟動網路瀏覽器,以進行網路視覺化和管理 (OTNS-Web):

啟動時的 OTNS-Web 視窗

如果 OTNS-Web 僅顯示空白頁面,可能是因為瀏覽器未啟用 WebGL。請參閱 https://superuser.com/a/836833,瞭解如何啟用 WebGL。

在接下來的章節中,您將瞭解如何透過 OTNS-CLIOTNS-Web 管理 OTNS 模擬。

4. 瞭解 OTNS-CLI 和 OTNS-Web

OTNS-CLI

OTNS-CLI 是用來管理 OTNS 模擬的指令列介面 (CLI)。

$ otns
>_ ← OTNS-CLI prompt

您可以透過 OTNS-CLI 輸入指令。如需完整指令清單,請參閱 OTNS CLI 參考資料。別擔心,在本程式碼研究室中,您只會用到其中幾個指令。

輸入 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 的網路視覺化和管理工具。可提供模擬 Thread 網路的節點、訊息和連結視覺化表示法。請注意 OTNS-Web 的各種元素:

OTNS-Web 元素說明

5. 新增節點

透過 OTNS-CLI 新增節點

在模擬中新增 Thread 路由器:

> 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 個節點的 Thread 網路,已選取節點 1

透過 OTNS-Web 新增節點

您也可以透過 OTNS-Web 新增節點。按一下 Action BarNew Router 按鈕。您應該會看到所選節點右側建立的節點。新路由器應加入現有的 Thread 分割區:

新增路由器,總共 5 個節點

此外,您也可以按一下動作列上的 FED、MED、SSED 和 BR 按鈕,建立其他類型的節點。現在應該總共有 9 個節點。如要建立不同的實體網路拓撲,請視需要將節點拖曳到其他位置。

新增多個節點,總共 9 個節點

您已建立一個包含多個節點的單一分割區 Thread 網路。在下一節中,我們將調整模擬速度,加快模擬執行速度。

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 中找到速度控制按鈕 速度控制按鈕。按鈕會顯示目前的模擬速度,可用於調整模擬速度,以及暫停/繼續模擬。

加快模擬速度

按一下 加快速度按鈕 按鈕,直到速度達到 MAXMAX 模擬速度指標,即可加快模擬速度。

減緩模擬速度

按一下 降低速度按鈕 按鈕即可放慢模擬速度。

暫停模擬

按一下 暫停按鈕 按鈕,即可在模擬作業執行時暫停。按鈕會變更為「「播放」按鈕」。

繼續模擬

如要繼續模擬,請在模擬暫停時點選 「播放」按鈕 按鈕。按鈕會變回 暫停按鈕

將模擬速度設為 10X

為節省時間,請使用

OTNS-CLI 調整模擬速度

10X 這樣我們就能更快觀察網路中的拓撲變更。

> speed 10
Done

7. 開啟/關閉電台

現在,模擬作業應包含至少 2 個路由器 (六邊形)、可能包含一個邊界路由器 (正方形) 和許多子項,並以 10 倍速度執行。

找出 2 部路由器目前的領導者 (紅色邊框),然後按一下選取:

已選取領導者節點 1 的 Thread 網路

關閉無線通訊

按一下動作列上的 「關閉」按鈕 按鈕,關閉 Leader 節點的無線電。如果無線電關閉,領導者就無法傳送或接收訊息。

等待約 12 秒 (模擬時間為 120 秒),讓其他路由器或邊界路由器成為新的領導者:

以節點 9 為新領導者,形成新的分割區

Thread 網路會自動從領導者故障中復原,方法是與新的領導者形成新的分割區。新分區也會有新的分區顏色。

開啟無線通訊

選取無線電已關閉的領導者。按一下 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 之間舊路由器對路由器連結的過時資訊。(或者,在這種情況下,甚至是轉譯錯誤)。適當逾時後,節點上過時的資訊最終會清除。

9. 刪除節點

透過「OTNS-CLI」刪除節點

刪除節點 5:

> del 5
Done

節點 5 應會從模擬中消失:

從模擬中刪除節點 5

透過「OTNS-Web」刪除節點

選取 Border Router 節點 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。然後依序按一下「確定」和「確定」。現在載入 OTNS PCAP 檔案時,應該可以正確解密。

「時間」欄中顯示的時間戳記 (以秒為單位),對應於 OpenThread 節點記錄中顯示的絕對模擬時間值。這樣一來,您就能更輕鬆地將記錄訊息與傳送或接收的無線電訊框建立關聯。不過,這些值通常不會完全相同,最多只會精確到微秒:在 OpenThread 堆疊要求傳送無線電訊框後,模擬的 IEEE 802.15.4 無線電硬體可能會增加一些額外延遲。

12. 恭喜

恭喜,您已成功執行第一次 OTNS 模擬!

您已瞭解如何安裝 OTNS 和相關依附元件。您已使用 OpenThread 模擬節點啟動 OTNS 模擬。您已瞭解如何透過 OTNS-CLIOTNS-Web,以各種方式操控模擬。

您現在已瞭解 OTNS,以及如何使用 OTNS 模擬 OpenThread 網路。

後續步驟

查看一些程式碼研究室…

參考文件