在 Docker 中使用 OpenThread 模擬 Thread 網路

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

1. 簡介

26b7f4f6b3ea0700.png

Google 發布的 OpenThreadThread 網路通訊協定的開放原始碼實作。Google Nest 已發布 OpenThread,讓開發人員以廣泛的方式使用 Nest 產品所採用的技術,加快智慧聯網家庭的產品開發速度。

Thread 規格定義了以 IPv6 為基礎的可靠、低功耗的無線裝置對裝置通訊通訊協定,適用於家庭應用程式。OpenThread 實作所有 Thread 網路層,包括 IPv6、6LoWPAN、IEEE 802.15.4 及 MAC 安全、網格連結建立和網格轉送。

本程式碼研究室將逐步引導您使用 Docker 模擬裝置模擬 Thread 網路。

課程內容

  • 如何設定 OpenThread 建構工具鍊
  • 如何模擬 Thread 網路
  • 如何驗證執行緒節點
  • 如何使用 OpenThread Daemon 管理 Thread 網路

軟硬體需求

  • Docker
  • 瞭解 Linux、網路轉送的基本知識

2. 設定 Docker

本程式碼研究室旨在在 Linux、Mac OS X 或 Windows 電腦上使用 Docker。建議您使用 Linux。

安裝 Docker

在您選擇的 OS 上安裝 Docker。

提取 Docker 映像檔

安裝 Docker 後,請開啟終端機視窗,然後提取 openthread/environment Docker 映像檔。這個映像檔使用預先建構的 OpenThread 和 OpenThread Daemon,可用於本程式碼研究室。

$ docker pull openthread/environment:latest

請注意,整個下載作業可能需要幾分鐘才能完成。

在終端機視窗中,從映像檔啟動 Docker 容器並連線到其 bash 殼層:

$ docker run --name codelab_otsim_ctnr -it --rm \
   --sysctl net.ipv6.conf.all.disable_ipv6=0 \
   --cap-add=net_admin openthread/environment bash

請注意本程式碼研究室所需的旗標:

  • --sysctl net.ipv6.conf.all.disable_ipv6=0:這會啟用容器中的 IPv6
  • --cap-add=net_admin — 啟用 NET_ADMIN 功能,可讓您執行網路相關作業,例如新增 IP 路徑

進入容器後,您應該會看到類似下列的提示:

root@c0f3912a74ff:/#

在上述範例中,c0f3912a74ff 是容器 ID。Docker 容器執行個體的容器 ID 與本程式碼研究室提示中顯示的容器不同。

使用 Docker

本程式碼研究室假設您已瞭解使用 Docker 的基本概念。整個程式碼研究室應留在 Docker 容器中。

3. 模擬 Thread 網路

您在本程式碼研究室中使用的範例應用程式,示範了最低的 OpenThread 應用程式,並透過基本指令列介面 (CLI) 顯示 OpenThread 設定和管理介面。

這個練習會逐步引導您從其他模擬的 Thread 裝置連線偵測一個虛擬執行緒裝置所需的基本步驟。

下圖說明基本的執行緒網路拓撲。在本練習中,我們會模擬綠色圓圈中的兩個節點:執行緒主管和執行緒路由器,在兩者之間有一個連線。

6e3aa07675f902dc.png

建立網路

1. 啟動節點 1

如果您尚未在終端機視窗中啟動 Docker 容器,請先啟動 Docker 容器並連線至其 bash 殼層:

$ docker run --name codelab_otsim_ctnr -it --rm \
   --sysctl net.ipv6.conf.all.disable_ipv6=0 \
   --cap-add=net_admin openthread/environment bash

在 Docker 容器中,使用 ot-cli-ftd 二進位檔為模擬的 Thread 裝置建立 CLI 程序。

root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 1

注意:如果執行這個指令後,沒有看到 > 提示,請按下 enter

這個二進位檔會實作 OpenThread 裝置。IEEE 802.15.4 無線電驅動程式可在 UDP 之上實作 (IEEE 802.15.4 影格會在 UDP 酬載中傳遞)。

1 的引數是檔案描述元,代表「工廠指派」的 IEEE EUI-64 最低位元位元。繫結至 IEEE 802.15.4 無線電模擬 (通訊埠 = 9000 + 檔案描述元) 的 UDP 通訊埠時,也會使用這個值。本程式碼研究室中模擬的 Thread 裝置的各個執行個體,都會使用不同的檔案描述元。

注意:只有在為模擬裝置建立程序時,僅如本程式碼研究室所述,使用 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

等待幾秒鐘,確認裝置已成為 Thread 領導者。「領導者」是指負責管理路由器 ID 的裝置。

> state
leader
Done

查看指派給節點 1's 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 = vertical-local
  • 開頭為 fe80 = link-local

網格本機位址類型會進一步分類:

  • 包含「ff:fe00」= 路由器定位器 (RLOC)
  • 不包含 ff:fe00 = 端點 ID (EID)

在主控台的輸出內容中識別 EID,並記下該 ID,以供日後使用。在上方的範例輸出中,EID 為:

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

2. 啟動節點 2

開啟新的終端機,並在執行中的 Docker 容器中執行 bash 殼層,以便用於節點 2。

$ docker exec -it codelab_otsim_ctnr bash

在這個新的 bash 提示中,使用引數 2 來產生 CLI 程序。這是您第二個模擬的 Thread 裝置:

root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2

注意:如果執行這個指令後,沒有看到 > 提示,請按下 enter

使用與節點 1's 作業資料集相同的值來設定執行緒網路金鑰和 PAN ID:

> dataset networkkey e4344ca17d1dca2a33f064992f31f786
Done
> dataset panid 0xc169
Done

將這個資料集設為使用中的資料集:

> dataset commit active
Done

啟動 IPv6 介面:

> ifconfig up
Done

啟動 Thread 通訊協定作業:

> thread start
Done

裝置將會自行初始化為子項。「Thread Child」值等同於「End Device」裝置,這是一種 Thread 裝置,只能透過家長裝置傳輸及接收非個人化流量。

> state
child
Done

您應該會在 2 分鐘內看到狀態從「child」切換為「router」。Thread 路由器可讓您在 Thread 裝置之間轉送流量。也稱為「上層」。

> state
router
Done

驗證網路

如要驗證網狀網路,最簡單的方法就是查看路由器表格。

1. 檢查連線狀態

在節點 2 上取得 RLOC16。RLOC16 是裝置 RLOC IPv6 位址的最後 16 位元。

> rloc16
5800
Done

在節點 1 上,檢查節點 2's RLOC16 的路由器表格。請確認節點 2 已先切換至路由器狀態。

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

在表格中找到 0x5800 的節點 2' 的 RLOC,確認其已連上網格。

2. 從節點 2 連線節點 1

確認兩部模擬的 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 恢復原廠設定,然後再返回 Docker bash 提示。手機會恢復原廠設定,確保這項練習中使用的 Thread 網路憑證不會套用到下一個練習。

> thread stop
Done
> factoryreset
>
> exit
root@c0f3912a74ff:/#

執行 factoryreset 指令後,您可能需要按 enter 幾次,才能恢復 > 提示。請勿退出 Docker 容器。

一併恢復原廠設定並結束節點 1:

> factoryreset
>
> exit
root@c0f3912a74ff:/#

請參閱 OpenThread CLI 參考資料,探索所有可用的 CLI 指令。

4. 使用佣金驗證節點

在先前的練習中,您使用兩個模擬裝置和經過驗證的連線設定 Thread 網路。不過,這個選項只允許未驗證的 IPv6 連結本機流量在裝置之間傳輸。如要在兩者之間轉送全域 IPv6 流量 (並透過執行緒邊界路由器轉送網際網路),就必須驗證節點。

為完成驗證,一部裝置必須擔任專員。委員會目前是新的 Thread 裝置所選擇的驗證伺服器,並且是提供裝置加入網路所需的網路憑證的授權器。

在本練習中,我們會使用和之前一樣的雙節點拓撲。為進行驗證,執行緒主管將擔任者,執行緒路由器則視為彙整者。

d6a67e8a0d0b5dcb.png

Docker

針對其餘練習中的每個節點 (終端機視窗),請務必以 OpenThread 建構執行 Docker 容器。如果接續先前的練習,同一個 Docker 容器中應已開啟兩個 bash 提示。否則,請參閱 Docker 疑難排解步驟,或單純重新執行「Simulate a Thread network」(模擬執行緒網路) 練習。

1. 建立網路

在節點 1 中,產生 CLI 程序:

root@c0f3912a74ff:/# /openthread/build/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

等待幾秒鐘,確認裝置已成為 Thread 主管:

> state
leader
Done

2. 開始建立專員角色

在 Node 1 上,啟動 Commissioner 角色:

> commissioner start
Done

允許任何使用 J01NME 加入會議憑證的 * 萬用字元加入網路。「彙整者」是一種由人工管理員新增至受管 Thread 網路的裝置。

> commissioner joiner add * J01NME
Done

3. 啟動「加入者」角色

在第二個終端機視窗中,在 Docker 容器中啟動新的 CLI 程序。這是節點 2。

root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2

在節點 2 上,使用 J01NME 聯合憑證憑證啟用彙整工具角色。

> ifconfig up
Done
> joiner start J01NME
Done

... 請稍候片刻,以便確認 ...

Join success

作為加入者,裝置 (節點 2) 已成功通過委員會 (節點 1) 的驗證,並已收到 Thread Network 憑證。

節點 2 現已通過驗證,請開始執行 Thread:

> thread start
Done

4. 驗證網路驗證

檢查節點 2 的 state,確認現已加入網路。2 分鐘內,節點 2 從 child 轉換至 router

> state
child
Done
...
> state
router
Done

5. 重新設定

如要為下一個練習做準備,請重設設定。在每個節點上停止 Thread 恢復原廠設定,然後退出模擬 Thread 裝置:

> thread stop
Done
> factoryreset
>
> exit
root@c0f3912a74ff:/#

執行 factoryreset 指令後,您可能需要按 enter 幾次,才能恢復 > 提示。

5. 使用 OpenThread Daemon 管理網路

在本練習中,我們會模擬一個 CLI 執行個體 (一個嵌入式 SoC Thread 裝置) 和一個無線電共同處理器 (RCP) 執行個體。

ot-daemon 是 OpenThread Posix 應用程式的模式,使用 UNIX 通訊端做為輸入和輸出,以便 OpenThread 核心以服務形式執行。用戶端可以使用 OpenThread CLI 做為通訊協定來連線至通訊端,藉此與這項服務進行通訊。

ot-ctlot-daemon 提供的 CLI,用於管理及設定 RCP。我們透過這個機制將 RCP 連線至 Thread 裝置建立的網路。

Docker

針對此練習中的每個節點 (終端機視窗),請確認您使用 OpenThread 建構的 Docker 容器。如果接續先前的操作,同一個 Docker 容器中應已開啟兩個 bash 提示。否則,請參閱 Docker 疑難排解步驟。

使用 ot-daemon

這個練習將使用三個終端機視窗,如下所示:

  1. 模擬 Thread 裝置的 CLI 執行個體 (節點 1)
  2. ot-daemon 項程序
  3. ot-ctl 個 CLI 執行個體

1. 啟動節點 1

在第一個終端機視窗中,為模擬的 Thread 裝置產生 CLI 程序:

root@c0f3912a74ff:/# /openthread/build/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's 執行緒介面的 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
>

如「模擬執行緒網路」步驟所述,一個位址是連結本機 (fe80),而三個位址是網格本機 (fd)。EID 是不含本機 ff:fe00 的網格本機位址。在這個範例中,EID 為 fd55:cf34:dea5:7994:460:872c:e807:c4ab

找出 ipaddr 輸出中的特定 EID,用於與節點通訊。

2. 開始 ot-daemon

在第二個終端機視窗中建立 tun 裝置節點,並設定讀取/寫入權限:

root@c0f3912a74ff:/# mkdir -p /dev/net && mknod /dev/net/tun c 10 200
root@c0f3912a74ff:/# chmod 600 /dev/net/tun

可用來在虛擬裝置上傳送封包和接收裝置。如果裝置已建立,您可能會收到錯誤訊息,這是正常現象,您可以忽略。

為 RCP 節點啟動 ot-daemon,我們將呼叫節點 2。使用 -v 詳細標記以便查看記錄輸出並確認其正在執行:

root@c0f3912a74ff:/# /openthread/build/posix/src/posix/ot-daemon -v \
'spinel+hdlc+forkpty:///openthread/build/examples/apps/ncp/ot-rcp?forkpty-arg=2'

如果成功,詳細模式中的 ot-daemon 會產生類似以下的輸出內容:

ot-daemon[31]: Running OPENTHREAD/297a880; POSIX; Feb  1 2022 04:43:39
ot-daemon[31]: Thread version: 3
ot-daemon[31]: Thread interface: wpan0
ot-daemon[31]: RCP version: OPENTHREAD/297a880; SIMULATION; Feb  1 2022 04:42:50

將此終端機保持開啟並在背景中執行。請勿在其中輸入任何其他指令。

3. 使用 ot-ctl 加入網路

我們尚未將節點 2 (ot-daemon RCP) 提交至任何 Thread 網路。這時 ot-ctl 就能派上用場。ot-ctl 使用與 OpenThread CLI 應用程式相同的 CLI。因此,您可以使用與其他模擬 Thread 裝置相同的方式控制 ot-daemon 節點。

開啟第三個終端機視窗,然後執行現有容器:

$ docker exec -it codelab_otsim_ctnr bash

進入容器後,啟動 ot-ctl

root@c0f3912a74ff:/# /openthread/build/posix/src/posix/ot-ctl
>

您會在這個第三個終端機視窗中使用 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 分鐘內,節點 2 從 child 轉換至 router

> state
child
Done
...
> state
router
Done

5. 驗證連線

在第三個終端機視窗中,使用 Ctrl+Dexit 指令退出 ot-ctl,然後返回容器的 bash 主控台。在這個控制台中,透過 ping6 使用 EID 對 EID 進行連線偵測 (ping)。如果 ot-daemon RCP 執行個體已成功加入 Thread 網路並與其通訊,則連線偵測 (ping) 會成功:

root@c0f3912a74ff:/# 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

6. Docker 疑難排解

如果您已退出 Docker 容器

bash 提示,您可能需要確認裝置是否正在運作,然後視需要重新啟動 / 重新輸入。

如要顯示正在執行的 Docker 容器:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
505fc57ffc72        environment       "bash"              10 minutes ago      Up 10 minutes                           codelab_otsim_ctnr

如要顯示所有 Docker 容器 (同時執行中和已停止):

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
505fc57ffc72        environment       "bash"              10 minutes ago      Up 10 minutes                           codelab_otsim_ctnr

如果您未在任一 docker ps 指令的輸出內容中看到容器 codelab_otsim_ctnr,請重新執行容器:

$ docker run --name codelab_otsim_ctnr -it --rm \
   --sysctl net.ipv6.conf.all.disable_ipv6=0 \
   --cap-add=net_admin openthread/environment bash

如果容器已停止 (顯示在 docker ps -a 中但不是 docker ps),請重新啟動容器:

$ docker start -i codelab_otsim_ctnr

如果 Docker 容器已在運作中 (列在 docker ps 中),請重新連線至每個終端機中的容器:

$ docker exec -it codelab_otsim_ctnr bash

"汽車不允許操作"error

如果在建立新的 OpenThread 節點時遇到 Operation not permitted 錯誤 (使用 mknod 指令),請務必根據本程式碼研究室提供的指令,以超級使用者的身分執行 Docker。本程式碼研究室不支援以無根模式執行 Docker。

7. 恭喜!

您已成功使用 OpenThread 模擬第一個 Thread 網路。太棒了!

在本程式碼研究室中,您瞭解如何:

  • 啟動及管理 OpenThread 模擬 Docker 容器
  • 模擬 Thread 網路
  • 驗證執行緒節點
  • 使用 OpenThread Daemon 管理 Thread 網路

如要進一步瞭解 Thread 和 OpenThread,請參閱下列探索:

或者,請嘗試在 Docker 容器中使用 OpenThread Border 路由器