Como simular uma rede Thread com OpenThread

1. Introdução

26b7f4f6b3ea0700.png

O OpenThread lançado pelo Google é uma implementação de código aberto do protocolo de rede Thread. O Google Nest lançou o OpenThread para disponibilizar amplamente aos desenvolvedores a tecnologia usada nos produtos Nest e acelerar o desenvolvimento de produtos para a casa conectada.

A especificação Thread define um protocolo de comunicação sem fio confiável, seguro e de baixo consumo de energia entre dispositivos com base em IPv6 para aplicações domésticas. O OpenThread implementa todas as camadas de rede Thread, incluindo IPv6, 6LoWPAN, IEEE 802.15.4 com segurança MAC, estabelecimento de link de malha e roteamento de malha.

Este codelab mostra como simular uma rede Thread em dispositivos simulados.

O que você vai aprender

  • Como configurar a cadeia de ferramentas de build do OpenThread
  • Como simular uma rede Thread
  • Como autenticar nós do Thread
  • Como gerenciar uma rede Thread com o daemon OpenThread

O que é necessário

  • git
  • Conhecimento básico de Linux e roteamento de rede

2. Configurar o sistema de build

Git

O Git é necessário para concluir este codelab. Faça o download e instale antes de continuar.

Depois da instalação, siga as instruções do seu SO específico para fazer o download e criar o OpenThread.

XCode para Mac OS X

O XCode é necessário para instalar e criar o OpenThread no Mac OS X.

Depois de instalar o Xcode, instale as ferramentas de linha de comando do Xcode:

$ xcode-select --install

Criar no Linux / Mac OS X

Estas instruções de instalação foram testadas no Ubuntu Server 14.04 LTS e no Mac OS X Sierra 10.12.6.

Instale o OpenThread. Os comandos bootstrap garantem que o conjunto de ferramentas esteja instalado e que o ambiente esteja configurado corretamente:

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

Como usar o Windows

Se você preferir o Windows, recomendamos testar a versão do Docker deste codelab.

3. Criar os aplicativos OpenThread

Quando a instalação estiver concluída, crie o aplicativo de exemplo OpenThread. Neste codelab, vamos usar o exemplo de simulação.

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

Agora crie o daemon OpenThread:

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

4. Simular uma rede Thread

O aplicativo de exemplo que você vai usar neste codelab demonstra um aplicativo OpenThread mínimo que expõe as interfaces de configuração e gerenciamento do OpenThread por uma interface de linha de comando (CLI) básica.

Este exercício mostra as etapas mínimas necessárias para fazer ping de um dispositivo Thread simulado para outro.

A figura abaixo descreve uma topologia básica de rede Thread. Neste exercício, vamos simular os dois nós dentro do círculo verde: um líder e um roteador do Thread com uma única conexão entre eles.

6e3aa07675f902dc.png

Dar um ping em um nó

1. Nó de início 1

Acesse o diretório openthread e crie o processo da CLI para um dispositivo Thread simulado usando o binário ot-cli-ftd.

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

Observação:se o prompt > não aparecer depois de executar esse comando, pressione enter.

Esse binário implementa um dispositivo OpenThread simulado no POSIX. O driver de rádio IEEE 802.15.4 é implementado sobre o UDP (os frames IEEE 802.15.4 são transmitidos em payloads UDP).

O argumento de 1 é um descritor do arquivo que representa os bits menos significativos do IEEE EUI-64 "atribuído pela fábrica" para o dispositivo simulado. Esse valor também é usado ao vincular a uma porta UDP para emulação de rádio IEEE 802.15.4 (porta = 9000 + descritor do arquivo). Cada instância de um dispositivo Thread simulado neste codelab vai usar um descritor do arquivo diferente.

Observação:use apenas descritores de arquivo 1 ou superior, conforme observado neste codelab, ao gerar o processo para um dispositivo simulado. Um descritor do arquivo de 0 é reservado para outro uso.

Crie um novo conjunto de dados operacionais e o confirme como o ativo. O conjunto de dados operacional é a configuração da rede Thread que você está criando.

> 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

Faça o commit desse conjunto de dados como o ativo:

> dataset commit active
Done

Ative a interface IPv6:

> ifconfig up
Done

Iniciar operação do protocolo de conversa:

> thread start
Done

Aguarde alguns segundos e verifique se o dispositivo se tornou o líder do Thread. O líder é o dispositivo responsável por gerenciar a atribuição de ID do roteador.

> state
leader
Done

Confira os endereços IPv6 atribuídos à interface Thread do nó 1 (sua saída será diferente):

> 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

Observe os tipos específicos de endereços IPv6:

  • Começa com fd = mesh-local
  • Começa com fe80 = link-local

Os tipos de endereços locais da malha são classificados da seguinte forma:

  • Contém ff:fe00 = localizador de roteador (RLOC)
  • Não contém ff:fe00 = identificador de endpoint (EID)

Identifique o EID na saída do console e anote para usar depois. Na saída de exemplo acima, o EID é:

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

2. Nó de início 2

Abra um novo terminal, navegue até o diretório openthread e gere o processo da CLI. Este é o segundo dispositivo Thread simulado:

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

Observação:se o prompt > não aparecer depois de executar esse comando, pressione enter.

Configure a chave de rede Thread e o ID do PAN usando os mesmos valores do conjunto de dados operacionais do nó 1:

> dataset networkkey e4344ca17d1dca2a33f064992f31f786
Done
> dataset panid 0xc169
Done

Faça o commit desse conjunto de dados como o ativo:

> dataset commit active
Done

Ative a interface IPv6:

> ifconfig up
Done

Iniciar operação do protocolo de conversa:

> thread start
Done

O dispositivo vai se inicializar como uma criança. Um filho de thread é equivalente a um dispositivo final, que é um dispositivo de thread que transmite e recebe tráfego unicast apenas com um dispositivo pai.

> state
child
Done

Em até 2 minutos, o estado vai mudar de child para router. Um roteador Thread é capaz de rotear o tráfego entre dispositivos Thread. Ele também é chamado de "Parent".

> state
router
Done

Verificar a rede

Uma maneira fácil de verificar a rede mesh é consultar a tabela de roteadores.

1. Verificar a conectividade:

No nó 2, receba o RLOC16. O RLOC16 são os últimos 16 bits do endereço IPv6 RLOC do dispositivo.

> rloc16
5800
Done

No nó 1, verifique a tabela de roteamento do RLOC16 do nó 2. Verifique se o nó 2 mudou para o estado do roteador primeiro.

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

O RLOC 0xa800 do nó 1 é encontrado na tabela, confirmando que ele está conectado à malha.

2. Pingue o nó 1 do nó 2

Verifique a conectividade entre os dois dispositivos simulados do Thread. No nó 2, ping o EID atribuído ao nó 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

Pressione enter para voltar ao prompt da CLI >.

Testar a rede

Agora que você pode fazer ping entre dois dispositivos Thread simulados, teste a rede mesh colocando um nó off-line.

Volte ao nó 1 e interrompa a linha de execução:

> thread stop
Done

Mude para o nó 2 e verifique o estado. Em até dois minutos, o nó 2 detecta que o líder (nó 1) está off-line, e você vai notar que o nó 2 passa a ser o leader da rede:

> state
router
Done
...
> state
leader
Done

Depois de confirmar, pare o Thread e faça uma redefinição de fábrica no nó 2 antes de sair. A redefinição de fábrica é feita para garantir que as credenciais da rede Thread usadas neste exercício não sejam transferidas para o próximo.

> thread stop
Done
> factoryreset
>
> exit

Também faça uma redefinição de fábrica e saia do nó 1:

> factoryreset
>
> exit

Consulte a referência da CLI do OpenThread para conferir todos os comandos disponíveis.

5. Autenticar nós com o Commissioning

No exercício anterior, você configurou uma rede Thread com dois dispositivos simulados e verificou a conectividade. No entanto, isso só permite que o tráfego local de link IPv6 não autenticado passe entre dispositivos. Para rotear o tráfego IPv6 global entre eles (e a Internet por um roteador de borda Thread), os nós precisam ser autenticados.

Para autenticar, um dispositivo precisa agir como um comissário. O comissário é o servidor de autenticação eleito no momento para novos dispositivos Thread e o autorizador para fornecer as credenciais de rede necessárias para que os dispositivos entrem na rede.

Neste exercício, vamos usar a mesma topologia de dois nós de antes. Para autenticação, o líder do Thread vai atuar como o comissário, e o roteador do Thread como um participante.

d6a67e8a0d0b5dcb.png

1. Criar uma rede

Se você estiver continuando do exercício anterior, já terá duas janelas de terminal abertas. Caso contrário, abra dois e deixe-os prontos para uso. Um vai servir como nó 1 e o outro como nó 2.

No Node 1, crie o processo da CLI:

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

Observação:se o prompt > não aparecer depois de executar esse comando, pressione enter.

Crie um novo conjunto de dados operacionais, faça commit dele como o ativo e inicie a linha de execução:

> 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

Faça o commit desse conjunto de dados como o ativo:

> dataset commit active
Done

Ative a interface IPv6:

> ifconfig up
Done

Iniciar operação do protocolo de conversa:

> thread start
Done

Aguarde alguns segundos e verifique se o dispositivo se tornou um líder do Thread:

> state
leader
Done

2. Iniciar a função de comissário

Ainda no nó 1, inicie a função de comissário:

> commissioner start
Done

Permitir que qualquer participante (usando o caractere curinga *) com a credencial de participante J01NME faça a ativação na rede. Um Joiner é um dispositivo adicionado por um administrador humano a uma rede Thread comissionada.

> commissioner joiner add * J01NME
Done

3. Iniciar a função de participante

Em uma segunda janela de terminal, gere um novo processo de CLI. Este é o nó 2.

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

No nó 2, ative a função de junção usando a credencial de junção J01NME.

> ifconfig up
Done
> joiner start J01NME
Done

... aguarde alguns segundos para confirmação ...

Join success

Como um participante, o dispositivo (Node 2) se autenticou com o comissário (Node 1) e recebeu as credenciais da rede Thread.

Agora que o nó 2 está autenticado, inicie o Thread:

> thread start
Done

4. Validar a autenticação de rede

Verifique o state no nó 2 para validar se ele agora faz parte da rede. Em dois minutos, o nó 2 faz a transição de child para router:

> state
child
Done
...
> state
router
Done

5. Redefinir configuração

Para se preparar para o próximo exercício, redefina a configuração. Em cada nó, pare a linha de execução, faça uma redefinição de fábrica e saia do dispositivo de linha de execução simulado:

> thread stop
Done
> factoryreset
>
> exit

Talvez seja necessário pressionar enter algumas vezes para trazer de volta o prompt > depois de um comando factoryreset.

6. Gerenciar a rede com o daemon OpenThread

Para este exercício, vamos simular uma instância da CLI (um único dispositivo SoC Thread incorporado) e uma instância de coprocessador de rádio (RCP, na sigla em inglês).

ot-daemon é um modo do app OpenThread Posix que usa um soquete UNIX como entrada e saída para que o núcleo do OpenThread possa ser executado como um serviço. Um cliente pode se comunicar com esse serviço conectando-se ao soquete usando a CLI OpenThread como protocolo.

O ot-ctl é uma CLI fornecida pelo ot-daemon para gerenciar e configurar o RCP. Com isso, vamos conectar o RCP à rede criada pelo dispositivo Thread.

Usar o ot-daemon

Este exercício vai usar três janelas de terminal, correspondentes ao seguinte:

  1. Instância da CLI do dispositivo Thread simulado (nó 1)
  2. Processo ot-daemon
  3. Instância da CLI ot-ctl

Se você estiver continuando do exercício anterior, já terá duas janelas de terminal abertas. Abra uma terceira para garantir que você tenha três janelas de terminal disponíveis para este exercício.

1. Nó de início 1

Na primeira janela do terminal, crie o processo da CLI para o dispositivo Thread simulado:

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

Observação:se o prompt > não aparecer depois de executar esse comando, pressione enter.

Crie um novo conjunto de dados operacionais, faça commit dele como o ativo e inicie a linha de execução:

> 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

Faça o commit desse conjunto de dados como o ativo:

> dataset commit active
Done

Ative a interface IPv6:

> ifconfig up
Done

Iniciar operação do protocolo de conversa:

> thread start
Done

Confira os endereços IPv6 atribuídos à interface Thread do nó 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
>

Conforme explicado na etapa Simular uma rede Thread, um endereço é link-local (fe80) e três são mesh-local (fd). O EID é o endereço mesh-local que não contém ff:fe00 no endereço. Neste exemplo de saída, o EID é fd55:cf34:dea5:7994:460:872c:e807:c4ab.

Identifique o EID específico na saída ipaddr, que será usado para se comunicar com o nó.

2. Iniciar ot-daemon

Na segunda janela do terminal, navegue até o diretório openthread e inicie ot-daemon para um nó RCP, que vamos chamar de Nó 2. Use a flag detalhada -v para ver a saída do registro e confirmar se ele está em execução. Não se esqueça de usar 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'

Quando bem-sucedido, o comando ot-daemon no modo detalhado gera uma saída semelhante a esta:

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

Deixe esse terminal aberto e em execução em segundo plano. Não insira mais comandos nele.

3. Use ot-ctl para participar da rede

Ainda não comissionamos o nó 2 (o ot-daemon RCP) em nenhuma rede Thread. É aí que entra o ot-ctl. O ot-ctl usa a mesma CLI que o app OpenThread CLI. Portanto, é possível controlar os nós ot-daemon da mesma maneira que os outros dispositivos Thread simulados.

Em uma terceira janela de terminal, inicie ot-ctl:

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

Observação:se o prompt > não aparecer depois de executar esse comando, pressione enter.

Você vai usar ot-ctl nesta terceira janela do terminal para gerenciar o nó 2 (o nó RCP) que você iniciou na segunda janela do terminal com ot-daemon. Verifique o state do nó 2:

> state
disabled
Done

Receba o eui64 do nó 2 para restringir a junção ao Joiner específico:

> eui64
18b4300000000001
Done

No nó 1 (primeira janela do terminal), inicie o comissário e restrinja a junção apenas a esse eui64:

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

No nó 2 (terceira janela do terminal), mostre a interface de rede e entre na rede:

> ifconfig up
Done
> joiner start J01NME
Done

... aguarde alguns segundos para confirmação ...

Join success

Como um participante, o RCP (nó 2) se autenticou com o comissário (nó 1) e recebeu as credenciais da rede Thread.

Agora, conecte o nó 2 à rede Thread:

> thread start
Done

4. Validar a autenticação de rede

Verifique o state no nó 2 para validar se ele agora faz parte da rede. Em dois minutos, o nó 2 faz a transição de child para router:

> state
child
Done
...
> state
router
Done

5. Validar a conectividade

Saia do ot-ctl usando Ctrl+D ou o comando exit. Na linha de comando da máquina host, faça ping no nó 1 usando o EID dele com o comando ping6. Se a instância ot-daemon RCP for associada e se comunicar com a rede Thread, o ping será bem-sucedido:

$ 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. Parabéns!

Você simulou sua primeira rede Thread usando o OpenThread. Incrível!

Neste codelab, você aprendeu a:

  • Configurar o conjunto de ferramentas de build do OpenThread
  • Simular uma rede Thread
  • Autenticar nós do Thread
  • Gerenciar uma rede Thread com o daemon OpenThread

Para saber mais, consulte estas referências: