1. 簡介
Google 發布的 OpenThread 是 Thread 網路通訊協定的開放原始碼實作。Google Nest 已發布 OpenThread,開放開發人員廣泛使用 Nest 產品中的技術,加快智慧聯網家庭產品的開發速度。
Thread 規格定義了適用於家用應用程式的 IPv6 型可靠、安全低功率無線裝置對裝置通訊協定。OpenThread 實作所有 Thread 網路層,包括 IPv6、6LoWPAN、IEEE 802.15.4,以及 MAC 安全性、網狀連結建立和網格轉送。
本程式碼研究室將逐步引導您使用 Docker,在模擬裝置上模擬 Thread 網路。
課程內容
- 如何設定 OpenThread 建構工具鍊
- 如何模擬 Thread 網路
- 如何驗證 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
--rm
選項會在您離開容器時刪除容器。如果您不想刪除容器,請勿使用這個選項。
請留意本程式碼研究室的必要標記:
--sysctl net.ipv6.conf.all.disable_ipv6=0
:這會啟用容器內的 IPv6--cap-add=net_admin
:啟用 NET_ADMIN 功能,即可執行網路相關作業,例如新增 IP 路徑
進入容器後,您應該會看到類似以下的提示:
root@c0f3912a74ff:/#
在上述範例中,c0f3912a74ff
是容器 ID。Docker 容器執行個體的容器 ID 與這個程式碼研究室提示中的容器 ID 不同。
使用 Docker
本程式碼研究室假設您瞭解 Docker 的基本使用概念。您應在整個程式碼研究室中留在 Docker 容器中。
3. 模擬 Thread 網路
在這個程式碼研究室中,您會使用的範例應用程式示範最小的 OpenThread 應用程式,讓應用程式透過基本指令列介面 (CLI) 公開 OpenThread 設定和管理介面。
本練習會逐步引導你採用最少的步驟,對一部模擬的 Thread 裝置執行連線偵測 (ping) 模擬的 Thread 裝置。
下圖說明基本的 Thread 網路拓撲。在本練習中,我們會模擬綠色圓圈內的兩個節點:Thread 領導者和 Thread 路由器,這兩者之間使用單一連線。
建立網路
1. 啟動節點 1
如果您尚未在終端機視窗中啟動 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 無線電模擬的 UDP 通訊埠 (通訊埠 = 9000 + 檔案描述元) 時,也會使用這個值。在這個程式碼研究室中,模擬 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
等待幾秒鐘,然後確認該裝置已成為執行緒領導者。領導者是負責管理路由器 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
= 端點 ID (EID)
在控制台輸出內容中找出 EID,請記下這個 EID 供日後使用。以上範例的輸出內容中的 EID 為:
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
2. 啟動節點 2
開啟新的終端機,然後在目前執行中的 Docker 容器中執行 bash
殼層,用於 Node 2。
$ docker exec -it codelab_otsim_ctnr bash
在這個新的 bash
提示中,使用引數 2
產生 CLI 程序。以下是第二部模擬的 Thread 裝置:
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2
注意:如果在執行這個指令後沒有看到 >
提示,請按下 enter
。
使用與 Node 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 Child 則等同於終端裝置,這種 Thread 裝置僅會透過上層裝置傳輸及接收單點傳播流量。
> state child Done
2 分鐘內,狀態應該就會從 child
切換為 router
。Thread 路由器能在 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 | LQ In | LQ Out | Age | Extended MAC | +----+--------+----------+-----------+--------+-------+---+--------------------+ | 20 | 0x5000 | 63 | 0 | 0 | 0 | 0 | 96da92ea13534f3b | | 22 | 0x5800 | 63 | 0 | 3 | 3 | 23 | 5a4eb647eb6bc66c |
資料表中發現節點 2 0x5800
的 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:
> thread stop Done
切換至節點 2 並檢查狀態。節點 2 會在兩分鐘內偵測到主要版本 (Node 1) 處於離線狀態,您應該會看到 Node 2 轉換至網路的 leader
:
> state router Done ... > state leader Done
確認後,請停止 Thread 並恢復原廠設定 Node 2,再結束顯示 Docker bash
提示。系統已恢復原廠設定,確保我們在此練習中使用的 Thread 網路憑證不會轉移到下一次練習。
> thread stop Done > factoryreset > > exit root@c0f3912a74ff:/#
您可能需要多次按下 enter
,才能在執行 factoryreset
指令後再次顯示 >
提示。請勿結束 Docker 容器。
一併恢復原廠設定並結束節點 1:
> factoryreset > > exit root@c0f3912a74ff:/#
請參閱 OpenThread CLI 參考資料,探索所有可用的 CLI 指令。
4. 透過調校功能驗證節點
在先前的練習中,您設定了包含兩部模擬裝置和已驗證連線的 Thread 網路。不過,這項設定只允許未經驗證的 IPv6 連結本機流量在裝置之間傳遞。如要在節點之間轉送全域 IPv6 流量 (透過 Thread 邊界路由器和網際網路),必須驗證節點。
必須有一部裝置擔任委員會驗證者,才能進行驗證。委員會是目前為新 Thread 裝置選取的驗證伺服器,以及授權者提供裝置加入網路所需的網路憑證。
在本練習中,我們將使用和之前一樣使用相同的雙節點拓撲。在驗證方面,Thread 主管會擔任委員會 (Commissioner),Thread Router 做為彙整者。
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
。
建立新的作業資料集,將其修訂為有效資料集,並啟動執行緒:
> 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. 啟動「佣金」角色
在節點 1 中,啟動「佣金」角色:
> 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
作為彙整器,裝置 (Node 2) 已成功透過 Commissioner (Node 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 root@c0f3912a74ff:/#
您可能需要多次按下 enter
,才能在執行 factoryreset
指令後再次顯示 >
提示。
5. 使用 OpenThread Daemon 管理網路
在這個練習中,我們將模擬一個 CLI 執行個體 (一個嵌入式 SoC Thread 裝置) 和一個無線電合作處理器 (RCP) 執行個體。
ot-daemon
是 OpenThread Posix 應用程式的模式,使用 UNIX 通訊端做為輸入和輸出內容,因此 OpenThread 核心能以服務形式執行。用戶端可以使用 OpenThread CLI 做為通訊協定連線至通訊端,藉此與這項服務通訊。
ot-ctl
是 ot-daemon
提供的 CLI,用於管理及設定 RCP。這樣就能將 RCP 連線到 Thread 裝置建立的網路。
Docker
在這個練習中,每個節點 (終端機視窗) 都必須以 OpenThread 版本執行 Docker 容器。如果繼續先前的練習,同一個 Docker 容器中應該有兩個 bash
提示。如果仍未解決,請查看 Docker 疑難排解步驟。
使用 ot-daemon
這項練習會使用三個終端機視窗,對應以下項目:
- 模擬 Thread 裝置的 CLI 執行個體 (節點 1)
ot-daemon
處理節點ot-ctl
個 CLI 執行個體
1. 啟動節點 1
在第一個終端機視窗中,為模擬 Thread 裝置產生 CLI 程序:
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 1
注意:如果在執行這個指令後沒有看到 >
提示,請按下 enter
。
建立新的作業資料集,將其修訂為有效資料集,並啟動執行緒:
> 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,這會用來與節點通訊。
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
,我們將將其稱為 Node 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 (第一個終端機視窗) 中,啟動 Agenter,然後限制只有該 eui64 能加入會議:
> commissioner start Done > commissioner joiner add 18b4300000000001 J01NME Done
在第三個終端機視窗中,開啟節點 2 的網路介面並加入網路:
> ifconfig up Done > joiner start J01NME Done
... 請稍待片刻的確認 ...
Join success
RCP (Node 2) 作為彙整工具,已成功透過委員會 (Node 1) 驗證自身,並收到 Thread 網路憑證。
現在,在第三個終端機視窗中將節點 2 加入 Thread 網路:
> thread start Done
4. 驗證網路驗證
在第三個終端機中,檢查節點 2 上的 state
,確認已加入網路。節點 2 會在兩分鐘內從 child
轉換至 router
:
> state child Done ... > state router Done
5. 驗證連線能力
在第三個終端機視窗中,使用 Ctrl+D 或 exit
指令結束 ot-ctl
,然後返回容器的 bash
控制台。在這個控制台中,對節點 1 進行連線偵測 (ping),方法是搭配使用節點 1 和 ping6
指令。如果 ot-daemon
RCP 執行個體已成功加入 Thread 網路並與 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
提示:您可能需要確認應用程式是否正在運作,並視需要重新啟動 / 重新輸入。您未曾使用 --rm
選項建立的所有 Docker 容器仍應存在。
如要顯示正在執行的 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
只有在您想在離開容器時刪除容器的情況下,才需要使用 --rm
選項。
如果容器停止 (列在 docker ps -a
中,但不在 docker ps
中),請重新啟動:
$ docker start -i codelab_otsim_ctnr
如果 Docker 容器已在執行 (列在 docker ps
中),請在每個終端機中重新連線至容器:
$ docker exec -it codelab_otsim_ctnr bash
「不允許操作」錯誤數
如果在建立新的 OpenThread 節點時遇到 Operation not permitted
錯誤 (使用 mknod
指令),請務必根據本程式碼研究室提供的指令,以超級使用者的身分執行 Docker。這個程式碼研究室不支援在無根模式中執行 Docker。
7. 恭喜!
您已成功使用 OpenThread 模擬第一個 Thread 網路。太棒了!
在本程式碼研究室中,您已瞭解如何:
- 啟動及管理 OpenThread 模擬 Docker 容器
- 模擬 Thread 網路
- 驗證 Thread 節點
- 使用 OpenThread Daemon 管理 Thread 網路
如要進一步瞭解 Thread 和 OpenThread,請參閱下列參考資料:
- Thread Primer 開啟 openthread.io
- 執行緒規格
- OpenThread GitHub 存放區
- OpenThread CLI 參考資料
- 其他 OpenThread Docker 支援
或者,您也可以嘗試使用 Docker 容器中的 OpenThread 邊界路由器!