OpenThread での Thread ネットワークのシミュレート

1. はじめに

26b7f4f6b3ea0700.png

Google がリリースした OpenThread は、Thread ネットワーク プロトコルのオープンソース実装です。Google Nest は、Google Nest 製品で使用されている技術を広くデベロッパーに提供し、スマートホーム製品の開発を加速させるために、OpenThread をリリースしました。

Thread 仕様は、ホーム アプリケーション向けの、IPv6 ベースの、信頼性が高く、安全で、低電力のワイヤレス デバイス間通信プロトコルを定義しています。OpenThread は、IPv6、6LoWPAN、IEEE 802.15.4 を含むすべての Thread ネットワーク レイヤ、MAC セキュリティ、メッシュリンクの確立、メッシュ ルーティングを実装します。

この Codelab では、シミュレートしたデバイスで Thread ネットワークをシミュレートする方法について説明します。

学習内容

  • OpenThread ビルド ツールチェーンの設定方法
  • Thread ネットワークをシミュレートする方法
  • Thread ノードを認証する方法
  • OpenThread Daemon を使用して Thread ネットワークを管理する方法

必要なもの

  • git
  • Linux、ネットワーク ルーティングの基礎知識

2. ビルドシステムをセットアップする

Git

この Codelab を完了するには Git が必要です。続行する前にダウンロードしてインストールしてください。

インストールが完了したら、お使いの OS の手順に沿って OpenThread をダウンロードしてビルドします。

Mac OS X 向け XCode

Mac OS X に OpenThread をインストールしてビルドするには XCode が必要です。

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 で使用するサンプル アプリケーションは、基本的なコマンドライン インターフェース(CLI)を介して OpenThread 構成と管理インターフェースを公開する、最小限の OpenThread アプリケーションのデモを行います。

この演習では、シミュレートした別の Thread デバイスからシミュレートした Thread デバイスに対して ping を実行するために必要な最小手順について説明します。

次の図は、Thread の基本的なネットワーク トポロジを示しています。この演習では、緑色の丸で囲まれた 2 つのノード(Thread Leader と Thread Router 間)をシミュレーションします。

6e3aa07675f902dc.png

ノードに 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 の最下位ビットを表すファイル記述子です。この値は、IEEE 802.15.4 無線エミュレーション(ポート = 9000 + ファイル記述子)の UDP ポートにバインドする場合にも使用されます。この Codelab のシミュレートされた Thread デバイスのインスタンスでは、それぞれ異なるファイル記述子を使用します。

注: この Codelab で説明したように、1 以上のファイル記述子は、シミュレートされたデバイスのプロセスを生成する場合にのみ使用してください。0 のファイル記述子は他の用途用に予約されています。

新しいオペレーショナル データセットを作成し、アクティブなデータセットとして commit します。オペレーショナル データセットは、作成する 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

このデータセットをアクティブなデータセットとして commit します。

> dataset commit active
Done

IPv6 インターフェースを起動します。

> ifconfig up
Done

Thread プロトコル オペレーションを開始します。

> thread start
Done

数秒待ってから、デバイスが Thread リーダーになりました。リーダーは、ルーター ID の割り当てを管理するデバイスです。

> state
leader
Done

ノード 1 のスレッド インターフェースに割り当てられた 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 = メッシュローカル
  • fe80 = link-local で始まる

メッシュローカルのアドレスタイプはさらに分類されます。

  • ff:fe00 = Router ロケーター(RLOC)を含む
  • 次を含まない: ff:fe00 = エンドポイント識別子(EID)

コンソール出力で EID を特定し、後で使用するためにメモしておきます。上の出力例の EID は次のとおりです。

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

2. ノード 2 を起動します。

新しいターミナルを開いて、openthread ディレクトリに移動し、CLI プロセスを生成します。シミュレーションした 2 つ目の 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

このデータセットをアクティブなデータセットとして commit します。

> 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 | 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. ノード 1 からノード 2 に対して ping を実行する

シミュレートされた 2 つの Thread デバイス間の接続を検証します。ノード 2 で、ノード 1 に割り当てられた EID を次のように作成します。ping

> 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 のプロンプトに戻ります。

ネットワークをテストする

シミュレートされた 2 つの Thread デバイス間で正常に ping が通ったので、1 つのノードをオフラインにしてメッシュ ネットワークをテストします。

ノード 1 に戻ってスレッドを停止します。

> thread stop
Done

ノード 2 に切り替えて、状態を確認します。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. コミッショニングでノードを認証する

前の演習では、シミュレートされた 2 つのデバイスと確認済みの接続を備えた Thread ネットワークをセットアップしました。ただし、これでデバイス間で未認証の IPv6 リンクローカル トラフィックしか通過できなくなります。ノード間(および Thread ボーダー ルーター経由のインターネット)でグローバル IPv6 トラフィックをルーティングするには、ノードを認証する必要があります。

認証するには、1 台のデバイスがコミッショナーとして機能する必要があります。コミッショナーは、現在選択されている新しい Thread デバイス用の認証サーバーであり、デバイスがネットワークに接続するために必要なネットワーク認証情報を提供する承認者です。

この演習では、前と同じ 2 ノードのトポロジを使用します。Thread リーダーは認証の際、コミッショナーとして機能し、Thread Router は Joiner として機能します。

d6a67e8a0d0b5dcb.png

1. ネットワークの作成

前の演習から続行する場合は、すでに 2 つのターミナル ウィンドウが開いているはずです。2 つとも開いていない場合は、2 つを開いて開いていることを確認します。1 つはノード 1 として、もう 1 つはノード 2 として機能します。

ノード 1 で CLI プロセスを生成します。

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

注: このコマンドを実行した後に > のプロンプトが表示されない場合は、enter を押します。

新しいオペレーショナル データセットを作成し、それをアクティブなデータセットとして commit して、スレッドを開始します。

> 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

このデータセットをアクティブなデータセットとして commit します。

> dataset commit active
Done

IPv6 インターフェースを起動します。

> ifconfig up
Done

Thread プロトコル オペレーションを開始します。

> thread start
Done

数秒待ってから、デバイスが Thread リーダーになったことを確認します。

> state
leader
Done

2. コミッショナーのロールを開始する

ノード 1 で、コミッショナーのロールを開始します。

> commissioner start
Done

J01NME ジョイナー認証情報を持つ任意のジョイナーが、* ワイルドカードを使用してネットワークへのコミッションを許可します。Joiner は、人間が管理者によって追加された Thread ネットワークに追加されるデバイスです。

> commissioner joiner add * J01NME
Done

3. Joiner のロールを開始する

第 2 のターミナル ウィンドウで、新しい CLI プロセスを生成します。これはノード 2 です。

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

ノード 2 で、J01NME Joiner Credential を使用して Joiner ロールを有効にします。

> ifconfig up
Done
> joiner start J01NME
Done

... 確認されるまで数秒お待ちください ...

Join success

Joiner として、デバイス(ノード 2)はコミッショナー(ノード 1)で自己認証され、Thread ネットワーク認証情報を受信しました。

ノード 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

factoryreset コマンドの後に > プロンプトに戻るには、enter を数回押す必要がある場合があります。

6. OpenThread Daemon を使用してネットワークを管理する

この演習では、1 つの CLI インスタンス(1 つの組み込み SoC スレッド デバイス)と 1 つの Radio Co-Processor(RCP)インスタンスをシミュレートします。

ot-daemon は、OpenThread Posix アプリのモードであり、UNIX ソケットを入力および出力として使用するため、OpenThread コアはサービスとして実行できます。クライアントは、OpenThread CLI をプロトコルとして使用してソケットに接続することで、このサービスと通信できます。

ot-ctl は、RCP を管理および構成するために ot-daemon によって提供される CLI です。これを使用して、RCP が Thread デバイスによって作成されたネットワークに接続されます。

ot-daemon を使用する

この演習では、次の 3 つのターミナル ウィンドウを使用します。

  1. シミュレートされた Thread デバイスの CLI インスタンス(ノード 1)
  2. ot-daemon プロセス
  3. ot-ctl CLI インスタンス

前の演習から続けると、すでに 2 つのターミナル ウィンドウが開いているはずです。1/3 を開いて、この演習に使用できるターミナル ウィンドウが 3 つあることを確認します。

1. ノード 1 を起動します

最初のターミナル ウィンドウで、シミュレートされた Thread デバイスに対して CLI プロセスを生成します。

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

注: このコマンドを実行した後に > のプロンプトが表示されない場合は、enter を押します。

新しいオペレーショナル データセットを作成し、それをアクティブなデータセットとして commit して、スレッドを開始します。

> 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

このデータセットをアクティブなデータセットとして commit します。

> dataset commit active
Done

IPv6 インターフェースを起動します。

> ifconfig up
Done

Thread プロトコル オペレーションを開始します。

> thread start
Done

ノード 1 のスレッド インターフェースに割り当てられた 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 ネットワークをシミュレートするのステップで説明したように、1 つのアドレスはリンクローカル(fe80)で、3 つのアドレスはメッシュローカル(fd)です。EID は、アドレスに ff:fe00 を含まないメッシュローカル アドレスです。このサンプル出力では、EID は fd55:cf34:dea5:7994:460:872c:e807:c4ab です。

ipaddr 出力から特定の EID を特定します。この EID は、ノードとの通信に使用されます。

2. ot-daemon を起動する

第 2 のターミナル ウィンドウで 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 を押します。

この 3 つ目のターミナル ウィンドウで ot-ctl を使用し、2 つ目のターミナル ウィンドウで ot-daemon を使用して開始したノード 2(RCP ノード)を管理します。ノード 2 の state を確認します。

> state
disabled
Done

ノード 2 の eui64 を取得して、参加を特定の Joiner に制限します。

> eui64
18b4300000000001
Done

ノード 1(最初のターミナル ウィンドウ)で、コミッショナーを起動して参加をその eui64 のみに制限します。

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

ノード 2(第 3 のターミナル ウィンドウ)で、ネットワーク インターフェースを起動してネットワークに接続します。

> ifconfig up
Done
> joiner start J01NME
Done

... 確認されるまで数秒お待ちください ...

Join success

Joiner として、RCP(ノード 2)はコミッショナー(ノード 1)で自己認証され、Thread ネットワーク認証情報を受信しました。

次に、ノード 2 を Thread ネットワークに接続します。

> thread start
Done

4. ネットワーク認証を検証する

ノード 2 の state で、ネットワークに接続されたことを確認します。ノード 2 は 2 分以内に child から router に移行します。

> state
child
Done
...
> state
router
Done

5. 接続の検証

Ctrl+D または exit コマンドを使用して ot-ctl を終了し、ホストマシンのコマンドラインでノード 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 Daemon を使用して Thread ネットワークを管理する

詳しくは、以下の資料をご覧ください。