Symulowanie sieci Thread przy użyciu OpenThread

1. Wprowadzenie

26b7f4f6b3ea0700.png

Opublikowana przez Google implementacja OpenThread to implementacja protokołu sieciowego Thread typu open source. Firma Google Nest udostępniła rozwiązanie OpenThread, aby udostępnić deweloperom technologię wykorzystywaną w produktach Nest i przyspieszyć proces opracowywania produktów do domów inteligentnych.

Specyfikacja Thread definiuje oparty na protokole IPv6 niezawodny, bezpieczny i oszczędny, bezprzewodowy protokół komunikacyjny między urządzeniami domowymi. OpenThread implementuje wszystkie warstwy sieciowe Thread, w tym IPv6, 6LoWPAN, IEEE 802.15.4 z zabezpieczeniami MAC, ustanowieniem linku mesh i routingiem sieci typu mesh.

Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak symulować sieć Thread na symulowanych urządzeniach.

Czego się nauczysz

  • Jak skonfigurować łańcuch narzędzi do kompilacji OpenThread
  • Jak symulować sieć Thread
  • Jak uwierzytelniać węzły Thread
  • Jak zarządzać siecią Thread przy użyciu OpenThread Daemon

Czego potrzebujesz

  • git
  • Podstawowa znajomość systemu Linux i routingu sieci

2. Konfigurowanie systemu kompilacji

Git

Do ukończenia tego ćwiczenia z programowania wymagany jest Git. Pobierz go i zainstaluj, zanim przejdziesz dalej.

Po zainstalowaniu postępuj zgodnie z instrukcjami dotyczącymi używanego systemu operacyjnego, aby pobrać i skompilować OpenThread.

XCode na Mac OS X

Do zainstalowania i skompilowania OpenThread w systemie macOS X jest wymagany XCode.

Po zainstalowaniu XCode zainstaluj narzędzia wiersza poleceń XCode:

$ xcode-select --install

Kompilacja w systemach Linux / Mac OS X

Te instrukcje instalacji zostały przetestowane w systemach Ubuntu Server 14.04 LTS i Mac OS X Sierra 10.12.6.

Zainstaluj OpenThread. Polecenia bootstrap pozwalają sprawdzić, czy łańcuch narzędzi jest zainstalowany, a środowisko jest prawidłowo skonfigurowane:

$ mkdir -p ~/src
$ cd ~/src
$ git clone --recursive https://github.com/openthread/openthread.git
$ cd openthread
$ ./script/bootstrap

Korzystanie z systemu Windows

Jeśli wolisz korzystać z systemu Windows, zalecamy wypróbowanie wersji Dockera tego ćwiczenia z programowania.

3. Tworzenie aplikacji OpenThread

Po zakończeniu instalacji utwórz przykładową aplikację OpenThread. W tym ćwiczeniach z programowania posługujemy się przykładem symulacji.

$ cd ~/src/openthread
$ ./script/cmake-build simulation

Teraz skompiluj Daemona OpenThread:

$ ./script/cmake-build posix -DOT_DAEMON=ON

4. Symulowanie sieci Thread

Przykładowa aplikacja, której użyjesz w tym module Codelab, przedstawia minimalną aplikację OpenThread, która udostępnia interfejsy konfiguracji i zarządzania OpenThread za pomocą podstawowego interfejsu wiersza poleceń (CLI).

To ćwiczenie przedstawia minimalne kroki wymagane do wysłania pingu do jednego symulowanego urządzenia Thread z innego symulowanego urządzenia Thread.

Poniższy rysunek przedstawia podstawową topologię sieci Thread. W tym ćwiczeniu będziemy symulować dwa węzły znajdujące się w zielonym kółku: lider wątków i router wątków – z jednym połączeniem między nimi.

6e3aa07675f902dc.png

Pingowanie węzła

1. Uruchom węzeł 1

Przejdź do katalogu openthread i utwórz proces interfejsu wiersza poleceń dla symulowanego urządzenia Thread przy użyciu pliku binarnego ot-cli-ftd.

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

Uwaga: jeśli po uruchomieniu tego polecenia nie widzisz znaku >, naciśnij enter.

Ten plik binarny implementuje urządzenie OpenThread symulowane w klastrze POSIX. Sterownik radiowy IEEE 802.15.4 jest zaimplementowany razem z UDP (ramki IEEE 802.15.4 są przekazywane w ładunkach UDP).

Argument funkcji 1 to deskryptor pliku, który reprezentuje najmniej istotne informacje z „przypisanego fabrycznie” IEEE EUI-64 dla symulowanego urządzenia. Ta wartość jest też używana podczas wiązania z portem UDP na potrzeby emulacji radiowej IEEE 802.15.4 (port = 9000 + deskryptor pliku). Każde wystąpienie symulowanego urządzenia Thread w tym ćwiczeniach z programowania używa innego deskryptora pliku.

Uwaga: podczas tworzenia tego procesu na symulowanym urządzeniu używaj deskryptorów plików o wartości 1 lub większej, zgodnie z opisem w tym ćwiczeniu z programowania. Deskryptor pliku 0 jest zarezerwowany do innego zastosowania.

Utwórz nowy operacyjny zbiór danych i zatwierdź go jako aktywny. Działający zbiór danych to konfiguracja tworzonej sieci 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

Zatwierdź ten zbiór danych jako aktywny:

> dataset commit active
Done

Wyświetl interfejs IPv6:

> ifconfig up
Done

Rozpoczynanie operacji protokołu Thread:

> thread start
Done

Poczekaj kilka sekund i sprawdź, czy urządzenie jest liderem wątku. Lider to urządzenie odpowiedzialne za zarządzanie przypisywaniem identyfikatora routera.

> state
leader
Done

Wyświetl adresy IPv6 przypisane do interfejsu Thread węzła 1 (dane wyjściowe będą inne):

> 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

Zwróć uwagę na konkretne typy adresów IPv6:

  • Zaczyna się od fd = sieć typu mesh-local
  • Zaczyna się od fe80 = link-local

Typy adresów lokalnych sieci typu mesh są klasyfikowane dalej:

  • Zawiera ff:fe00 = lokalizator routera (RLOC)
  • Nie zawiera identyfikatora punktu końcowego (ff:fe00) = identyfikatora punktu końcowego (EID)

Zidentyfikuj EID w danych wyjściowych konsoli, zapisz go do późniejszego użycia. W przykładowych danych wyjściowych powyżej identyfikator EID to:

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

2. Uruchamianie węzła 2

Otwórz nowy terminal i przejdź do katalogu openthread, a następnie uruchom proces interfejsu wiersza poleceń. To Twoje drugie symulowane urządzenie Thread:

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

Uwaga: jeśli po uruchomieniu tego polecenia nie widzisz znaku >, naciśnij enter.

Skonfiguruj klucz sieciowy wątku i identyfikator PAN, używając tych samych wartości co w zbiorze danych operacyjnych węzła 1:

> dataset networkkey e4344ca17d1dca2a33f064992f31f786
Done
> dataset panid 0xc169
Done

Zatwierdź ten zbiór danych jako aktywny:

> dataset commit active
Done

Wyświetl interfejs IPv6:

> ifconfig up
Done

Rozpoczynanie operacji protokołu Thread:

> thread start
Done

Urządzenie uruchomi się jako dziecko. Element podrzędny Thread jest odpowiednikiem urządzenia końcowego Thread, które przesyła i odbiera ruch pojedynczy wyłącznie na urządzeniu rodzica.

> state
child
Done

W ciągu 2 minut stan powinien się zmienić z child na router. Router Thread może kierować ruch między urządzeniami Thread. Nazywa się go też elementem nadrzędnym.

> state
router
Done

Sprawdzanie sieci

Łatwym sposobem na sprawdzenie sieci typu mesh jest sprawdzenie tabeli routera.

1. Sprawdź połączenie

W węźle Node 2 pobierz RLOC16. RLOC16 to ostatnie 16 bitów adresu IPv6 RLOC urządzenia.

> rloc16
5800
Done

W węźle 1 sprawdź w tabeli routerów wartość RLOC16 węzła. Upewnij się, że Node 2 przełączy się najpierw na router.

> 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 |

W tabeli znajduje się wartość RLOC węzła 1 wynosząca 0xa800, co potwierdza, że jest on połączony z siatką.

2. Pingowanie węzła Node 1 z Node 2

Sprawdź połączenia między 2 symulowanymi urządzeniami Thread. W węźle ping identyfikator EID przypisany do węzła 1:

> 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

Naciśnij enter, aby wrócić do promptu interfejsu wiersza poleceń >.

Testowanie sieci

Po pomyślnym wysłaniu pingów do 2 symulowanych urządzeń Thread przetestuj sieć typu mesh, przełączając 1 węzeł w tryb offline.

Wróć do węzła 1 i zatrzymaj Thread:

> thread stop
Done

Przełącz się na węzeł 2 i sprawdź stan. W ciągu 2 minut Node 2 wykryje, że najlepszy wariant (węzeł 1) jest offline, i powinien przełączyć się na węzeł 2 jako leader sieci:

> state
router
Done
...
> state
leader
Done

Po potwierdzeniu zatrzymaj aplikację Thread i przywróć w węźle 2 ustawienia fabryczne, zanim ją zamkniesz. Przeprowadzamy przywrócenie do ustawień fabrycznych, aby mieć pewność, że dane logowania do sieci Thread, które użyliśmy w tym ćwiczeniu, nie zostaną przeniesione do następnego ćwiczenia.

> thread stop
Done
> factoryreset
>
> exit

Oprócz tego przywróć urządzenie do ustawień fabrycznych i zamknij węzeł 1:

> factoryreset
>
> exit

Zapoznaj się z dokumentacją interfejsu wiersza poleceń OpenThread, aby poznać wszystkie dostępne polecenia interfejsu wiersza poleceń.

5. Uwierzytelnianie węzłów za pomocą przekazywania

W poprzednim ćwiczeniu udało Ci się skonfigurować sieć Thread z 2 symulowanymi urządzeniami i zweryfikowanymi połączeniami. Pozwala to jednak przesyłać między urządzeniami tylko nieuwierzytelniony ruch związany z lokalnym połączeniem IPv6. Aby można było kierować globalny ruch IPv6 między nimi (a internetem przez router graniczny Thread), węzły muszą być uwierzytelnione.

Aby można było dokonać uwierzytelnienia, jedno urządzenie musi działać jako komisarz. Komisarz to obecnie wybierany serwer uwierzytelniania dla nowych urządzeń Thread i autoryzacja do podawania danych logowania do sieci, które są wymagane, by urządzenia mogły połączyć się z siecią.

W tym ćwiczeniu użyjemy tej samej topologii dwóch węzłów co poprzednio. W przypadku uwierzytelniania lider Thread będzie pełnił rolę komisarza, a router wątków jako łącznik.

d6a67e8a0d0b5dcb.png

1. Utwórz sieć

Jeśli chcesz kontynuować poprzednie ćwiczenie, powinny być już otwarte 2 okna terminala. Jeśli nie, upewnij się, że 2 urządzenia są otwarte i gotowe do użycia. Jeden będzie działać jako węzeł 1, a drugi jako węzeł 2.

W węźle 1 utwórz proces interfejsu wiersza poleceń:

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

Uwaga: jeśli po uruchomieniu tego polecenia nie widzisz znaku >, naciśnij enter.

Utwórz nowy operacyjny zbiór danych, zatwierdź go jako aktywny i uruchom 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

Zatwierdź ten zbiór danych jako aktywny:

> dataset commit active
Done

Wyświetl interfejs IPv6:

> ifconfig up
Done

Rozpoczynanie operacji protokołu Thread:

> thread start
Done

Poczekaj kilka sekund i sprawdź, czy urządzenie jest liderem wątku:

> state
leader
Done

2. Nadanie roli komisarza

Nie wychodząc z węzła 1, rozpocznij rolę komisarza:

> commissioner start
Done

Zezwól dowolnemu Joinerowi (korzystając z symbolu wieloznacznego *) z danymi logowania łączenia kont J01NME na prowizje w sieci. Łącznik to urządzenie dodawane przez administratora do zamówionej sieci Thread.

> commissioner joiner add * J01NME
Done

3. Rozpoczynanie roli Łącznik

W drugim oknie terminala utwórz nowy proces interfejsu wiersza poleceń. To jest Node 2.

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

W węźle Node 2 włącz rolę łączenia za pomocą danych logowania łączenia J01NME.

> ifconfig up
Done
> joiner start J01NME
Done

... odczekaj kilka sekund na potwierdzenie ...

Join success

W ramach łączenia urządzenie (węzeł 2) uwierzytelniło się za pomocą komisarza (węzeł 1) i otrzymało dane logowania do sieci Thread.

Teraz gdy Node 2 jest uwierzytelniony, uruchom Thread:

> thread start
Done

4. Weryfikowanie uwierzytelniania sieci

Sprawdź interfejs state w węźle 2, aby upewnić się, że połączył się on z siecią. W ciągu dwóch minut węzeł 2 przełącza się z child na router:

> state
child
Done
...
> state
router
Done

5. Resetuj konfigurację

Aby przygotować się do następnego ćwiczenia, zresetuj konfigurację. W każdym węźle zatrzymaj aplikację Thread, przywróć ją do ustawień fabrycznych i zamknij symulowane urządzenie Thread:

> thread stop
Done
> factoryreset
>
> exit

Konieczne może być kilkukrotne naciśnięcie enter, aby przywrócić wiersz > po poleceniu factoryreset.

6. Zarządzanie siecią za pomocą OpenThread Daemon

W tym ćwiczeniu symulujemy 1 instancję interfejsu wiersza poleceń (pojedyncze osadzone urządzenie SoC Thread) i 1 instancję koprocesora radiowego (RCP).

ot-daemon to tryb aplikacji OpenThread Posix, który jako dane wejściowe i wyjściowe wykorzystuje gniazdo UNIX, dzięki czemu Core OpenThread może działać jako usługa. Klient może komunikować się z tą usługą, łącząc się z gniazdem za pomocą interfejsu wiersza poleceń OpenThread jako protokołu.

ot-ctl to interfejs wiersza poleceń udostępniany przez usługę ot-daemon, który służy do zarządzania RCP i jego konfigurowania. Za jego pomocą połączymy RCP z siecią utworzoną przez urządzenie Thread.

Użyj polecenia ot-daemon

W tym ćwiczeniu będą używane 3 okna terminala, odpowiadające tym:

  1. Instancja interfejsu wiersza poleceń symulowanego urządzenia Thread (węzeł 1)
  2. Proces usługi ot-daemon
  3. ot-ctl instancja interfejsu wiersza poleceń

Jeśli chcesz kontynuować poprzednie ćwiczenie, powinny być już otwarte dwa okna terminala. Otwórz jedną trzecią, aby mieć pewność, że masz trzy okna terminala dla tego ćwiczenia.

1. Uruchom węzeł 1

W pierwszym oknie terminala utwórz proces interfejsu wiersza poleceń dla symulowanego urządzenia Thread:

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

Uwaga: jeśli po uruchomieniu tego polecenia nie widzisz znaku >, naciśnij enter.

Utwórz nowy operacyjny zbiór danych, zatwierdź go jako aktywny i uruchom 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

Zatwierdź ten zbiór danych jako aktywny:

> dataset commit active
Done

Wyświetl interfejs IPv6:

> ifconfig up
Done

Rozpoczynanie operacji protokołu Thread:

> thread start
Done

Wyświetl adresy IPv6 przypisane do interfejsu Thread węzła 1:

> 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
>

Jak wyjaśniliśmy w kroku Symuluj sieć Thread, 1 adres ma połączenie lokalne (fe80), a 3 to sieć typu mesh (fd). Identyfikator EID to lokalny adres sieci typu mesh, który nie zawiera fragmentu ff:fe00. W tych przykładowych danych wyjściowych identyfikator EID ma wartość fd55:cf34:dea5:7994:460:872c:e807:c4ab.

Określ konkretny EID na podstawie danych wyjściowych ipaddr, który będzie używany do komunikacji z węzłem.

2. Uruchom demona

W drugim oknie terminala przejdź do katalogu openthread i uruchom ot-daemon, aby utworzyć węzeł RCP, który nazwiemy Node 2. Użyj flagi szczegółowej -v, aby wyświetlić dane wyjściowe logu i sprawdzić, czy działają. Pamiętaj, by użyć polecenia 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'

Jeśli operacja się uda, ot-daemon w trybie szczegółowym generuje dane wyjściowe podobne do tych:

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

Pozostaw terminal otwarty i uruchomiony w tle. Nie będzie w nim kolejnych poleceń.

3. Użyj ot-ctl, by dołączyć do sieci

Nie zleciliśmy jeszcze węzła 2 (RCP ot-daemon) żadnej sieci Thread. Właśnie tutaj do akcji wkracza usługa ot-ctl. ot-ctl używa tego samego interfejsu wiersza poleceń co aplikacja interfejsu wiersza poleceń OpenThread. Dlatego możesz sterować ot-daemon węzłami w taki sam sposób jak w przypadku innych symulowanych urządzeń Thread.

W trzecim oknie terminala uruchom ot-ctl:

$ sudo ./build/posix/src/posix/ot-ctl
>

Uwaga: jeśli po uruchomieniu tego polecenia nie widzisz znaku >, naciśnij enter.

Użyjesz ot-ctl w tym trzecim oknie terminala do zarządzania węzłem 2 (węzłem RCP), który został uruchomiony w drugim oknie terminala przy użyciu ot-daemon. Sprawdź state w węźle Node 2:

> state
disabled
Done

Pobierz eui64 w Node.2, aby ograniczyć możliwość dołączania do konkretnego łącznika:

> eui64
18b4300000000001
Done

W węźle 1 (pierwsze okno terminala) uruchom komisarza i ogranicz łączenie tylko do tego węzła (eui64):

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

Na węźle 2 (trzecie okno terminala) otwórz interfejs sieci i połącz się z siecią:

> ifconfig up
Done
> joiner start J01NME
Done

... odczekaj kilka sekund na potwierdzenie ...

Join success

Jako łącznik RCP (Node 2) uwierzytelnił się u komisarza (węzeł 1) i otrzymał dane logowania do sieci Thread.

Połącz teraz węzeł 2 z siecią Thread:

> thread start
Done

4. Weryfikowanie uwierzytelniania sieci

Sprawdź interfejs state w węźle 2, aby upewnić się, że połączył się on z siecią. W ciągu dwóch minut węzeł 2 przełącza się z child na router:

> state
child
Done
...
> state
router
Done

5. Zweryfikuj połączenia

Zakończ ot-ctl za pomocą polecenia Ctrl+D lub exit i w wierszu poleceń hosta hosta wyślij ping do węzła 1, używając jego identyfikatora EID w poleceniu ping6. Jeśli instancja RCP ot-daemon zostanie połączona z siecią Thread i komunikuje się z nią, ping zakończy się powodzeniem:

$ 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. Gratulacje!

Udało Ci się symulować pierwszą sieć Thread przy użyciu OpenThread. Świetnie!

Dzięki temu ćwiczeniu z programowania omówiliśmy, jak:

  • Konfigurowanie łańcucha narzędzi do kompilacji OpenThread
  • Symulowanie sieci Thread
  • Uwierzytelnianie węzłów Thread
  • Zarządzanie siecią Thread przy użyciu OpenThread Daemon

Aby dowiedzieć się więcej, przejrzyj te materiały: