1. Introduction

OpenThread, publié par Google, est une implémentation Open Source du protocole réseau Thread. Google Nest a publié OpenThread pour mettre la technologie utilisée dans les produits Nest à la disposition des développeurs afin d'accélérer le développement de produits pour la maison connectée.
La spécification Thread définit un protocole de communication sans fil fiable, sécurisé et basse consommation basé sur IPv6 pour les applications domotiques. OpenThread implémente toutes les couches réseau Thread, y compris IPv6, 6LoWPAN, IEEE 802.15.4 avec sécurité MAC, établissement de liens Mesh et routage Mesh.
Cet atelier de programmation vous explique comment simuler un réseau Thread sur des appareils simulés.
Points abordés
- Configurer la chaîne d'outils de compilation OpenThread
- Simuler un réseau Thread
- Authentifier les nœuds Thread
- Gérer un réseau Thread avec OpenThread Daemon
Prérequis
- git
- Connaissances de base de Linux et du routage réseau
2. Configurer le système de compilation
Git
Git est requis pour suivre cet atelier de programmation. Téléchargez et installez-le avant de continuer.
Une fois installé, suivez les instructions spécifiques à votre OS pour télécharger et compiler OpenThread.
Xcode pour Mac OS X
XCode est requis pour installer et compiler OpenThread sur Mac OS X.
Après avoir installé Xcode, installez les outils de ligne de commande Xcode :
$ xcode-select --install
Compiler sur Linux / Mac OS X
Ces instructions d'installation ont été testées sur Ubuntu Server 14.04 LTS et Mac OS X Sierra 10.12.6.
Installez OpenThread. Les commandes bootstrap permettent de s'assurer que la chaîne d'outils est installée et que l'environnement est correctement configuré :
$ mkdir -p ~/src $ cd ~/src $ git clone --recursive https://github.com/openthread/openthread.git $ cd openthread $ ./script/bootstrap
Utiliser Windows
Si vous préférez Windows, nous vous recommandons d'essayer la version Docker de cet atelier de programmation.
3. Compiler les applications OpenThread
Une fois l'installation terminée, créez l'exemple d'application OpenThread. Pour cet atelier de programmation, nous utilisons l'exemple de simulation.
$ cd ~/src/openthread $ ./script/cmake-build simulation
Créez maintenant le daemon OpenThread :
$ ./script/cmake-build posix -DOT_DAEMON=ON
4. Simuler un réseau Thread
L'exemple d'application que vous utiliserez pour cet atelier de programmation présente une application OpenThread minimale qui expose les interfaces de configuration et de gestion OpenThread via une interface de ligne de commande (CLI) de base.
Cet exercice vous guide à travers les étapes minimales requises pour envoyer un ping d'un appareil Thread simulé à un autre.
La figure ci-dessous décrit une topologie de réseau Thread de base. Pour cet exercice, nous allons simuler les deux nœuds situés dans le cercle vert : un leader Thread et un routeur Thread avec une seule connexion entre eux.

Envoyer un ping à un nœud
1. Nœud de départ 1
Accédez au répertoire openthread et lancez le processus CLI pour un appareil Thread simulé à l'aide du binaire ot-cli-ftd.
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 1
Remarque : Si l'invite > ne s'affiche pas après l'exécution de cette commande, appuyez sur enter.
Ce binaire implémente un appareil OpenThread simulé sur POSIX. Le pilote radio IEEE 802.15.4 est implémenté au-dessus d'UDP (les trames IEEE 802.15.4 sont transmises dans les charges utiles UDP).
L'argument de 1 est un descripteur de fichier qui représente les bits les moins significatifs de l'IEEE EUI-64 "attribué en usine" pour l'appareil simulé. Cette valeur est également utilisée lors de la liaison à un port UDP pour l'émulation radio IEEE 802.15.4 (port = 9000 + descripteur de fichier). Chaque instance d'un appareil Thread simulé dans cet atelier de programmation utilisera un descripteur de fichier différent.
Remarque : N'utilisez que des descripteurs de fichier de 1 ou plus, comme indiqué dans cet atelier de programmation, lorsque vous générez le processus pour un appareil simulé. Un descripteur de fichier 0 est réservé à d'autres utilisations.
Créez un ensemble de données opérationnelles et définissez-le comme actif. L'ensemble de données opérationnelles correspond à la configuration du réseau Thread que vous créez.
> 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
Validez cet ensemble de données comme actif :
> dataset commit active Done
Activez l'interface IPv6 :
> ifconfig up Done
Démarrer l'opération du protocole Thread :
> thread start Done
Attendez quelques secondes, puis vérifiez que l'appareil est devenu le leader Thread. Le leader est l'appareil chargé de gérer l'attribution des ID de routeur.
> state leader Done
Affichez les adresses IPv6 attribuées à l'interface Thread du nœud 1 (votre résultat sera différent) :
> 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
Notez les types d'adresses IPv6 spécifiques :
- Commence par
fd= mesh-local - Commence par
fe80= liaison locale
Les types d'adresses locales au réseau maillé sont classés comme suit :
- Contient
ff:fe00= Router Locator (RLOC) - Ne contient pas
ff:fe00= identifiant du point de terminaison (EID)
Identifiez l'EID dans la sortie de la console et notez-le pour une utilisation ultérieure. Dans l'exemple de résultat ci-dessus, l'EID est le suivant :
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
2. Démarrer le nœud 2
Ouvrez un nouveau terminal, accédez au répertoire openthread et lancez le processus CLI. Voici votre deuxième appareil Thread simulé :
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 2
Remarque : Si l'invite > ne s'affiche pas après l'exécution de cette commande, appuyez sur enter.
Configurez la clé du réseau Thread et l'ID PAN en utilisant les mêmes valeurs que celles de l'ensemble de données opérationnelles du nœud 1 :
> dataset networkkey e4344ca17d1dca2a33f064992f31f786 Done > dataset panid 0xc169 Done
Validez cet ensemble de données comme actif :
> dataset commit active Done
Activez l'interface IPv6 :
> ifconfig up Done
Démarrer l'opération du protocole Thread :
> thread start Done
L'appareil s'initialise en tant qu'enfant. Un nœud enfant Thread équivaut à un appareil final, qui est un appareil Thread qui transmet et reçoit le trafic en monodiffusion uniquement avec un nœud parent.
> state child Done
Au bout de deux minutes, l'état devrait passer de child à router. Un routeur Thread est capable de router le trafic entre les appareils Thread. Il est également appelé "parent".
> state router Done
Vérifier le réseau
Pour vérifier facilement le réseau maillé, consultez la table de routage.
1. Vérifiez la connectivité
Sur le nœud 2, obtenez le RLOC16. RLOC16 correspond aux 16 derniers bits de l'adresse IPv6 RLOC de l'appareil.
> rloc16 5800 Done
Sur le nœud 1, vérifiez la table de routage pour le RLOC16 du nœud 2. Assurez-vous d'abord que le nœud 2 est passé à l'état de routeur.
> 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 |
Le RLOC 0xa800 du nœud 1 se trouve dans le tableau, ce qui confirme qu'il est connecté au réseau maillé.
2. Pinguer le nœud 1 depuis le nœud 2
Vérifiez la connectivité entre les deux appareils Thread simulés. Dans le nœud 2, ping l'EID attribué au nœud 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
Appuyez sur enter pour revenir à l'invite de la CLI >.
Tester le réseau
Maintenant que vous pouvez effectuer un ping entre deux appareils Thread simulés, testez le réseau maillé en mettant un nœud hors connexion.
Revenez au nœud 1 et arrêtez Thread :
> thread stop Done
Passez au nœud 2 et vérifiez l'état. Dans un délai de deux minutes, le nœud 2 détecte que le nœud principal (nœud 1) est hors connexion. Vous devriez voir le nœud 2 devenir le leader du réseau :
> state router Done ... > state leader Done
Une fois la confirmation reçue, arrêtez Thread et rétablissez la configuration d'usine du nœud 2 avant de quitter. La réinitialisation des paramètres d'usine permet de s'assurer que les identifiants du réseau Thread que nous avons utilisés dans cet exercice ne sont pas conservés pour le prochain exercice.
> thread stop Done > factoryreset > > exit
Rétablissez également la configuration d'usine et quittez le nœud 1 :
> factoryreset > > exit
Consultez la documentation de référence sur la CLI OpenThread pour découvrir toutes les commandes de CLI disponibles.
5. Authentifier les nœuds avec la mise en service
Dans l'exercice précédent, vous avez configuré un réseau Thread avec deux appareils simulés et vérifié la connectivité. Toutefois, cela ne permet que le trafic IPv6 link-local non authentifié de transiter entre les appareils. Pour acheminer le trafic IPv6 global entre eux (et vers Internet via un routeur de bordure Thread), les nœuds doivent être authentifiés.
Pour s'authentifier, un appareil doit agir en tant que commissaire. Le commissaire est le serveur d'authentification actuellement élu pour les nouveaux appareils Thread. Il est également l'auteur de l'autorisation permettant de fournir les identifiants réseau nécessaires aux appareils pour rejoindre le réseau.
Dans cet exercice, nous allons utiliser la même topologie à deux nœuds que précédemment. Pour l'authentification, le leader Thread fera office de commissaire et le routeur Thread de participant.

1. Créer un réseau
Si vous continuez à partir de l'exercice précédent, vous devriez déjà avoir deux fenêtres de terminal ouvertes. Sinon, assurez-vous que deux sont ouverts et prêts à être utilisés. L'une servira de nœud 1 et l'autre de nœud 2.
Dans le nœud 1, lancez le processus CLI :
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 1
Remarque : Si l'invite > ne s'affiche pas après l'exécution de cette commande, appuyez sur enter.
Créez un ensemble de données opérationnelles, validez-le comme ensemble de données actif et démarrez 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
Validez cet ensemble de données comme actif :
> dataset commit active Done
Activez l'interface IPv6 :
> ifconfig up Done
Démarrer l'opération du protocole Thread :
> thread start Done
Attendez quelques secondes, puis vérifiez que l'appareil est devenu un leader Thread :
> state leader Done
2. Commencer avec le rôle de commissaire
Toujours sur le nœud 1, démarrez le rôle de commissaire :
> commissioner start Done
Autorisez n'importe quel associé (en utilisant le caractère générique *) avec l'identifiant d'associé J01NME à mettre en service le réseau. Un Joiner est un appareil ajouté par un administrateur humain à un réseau Thread mis en service.
> commissioner joiner add * J01NME Done
3. Démarrer le rôle de participant
Dans une deuxième fenêtre de terminal, générez un processus CLI. Il s'agit du nœud 2.
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 2
Sur le nœud 2, activez le rôle "Joiner" (Joigneur) à l'aide de l'identifiant Joiner J01NME.
> ifconfig up Done > joiner start J01NME Done
... patientez quelques secondes pour obtenir la confirmation ...
Join success
En tant que nœud participant, l'appareil (nœud 2) s'est authentifié auprès du commissaire (nœud 1) et a reçu les identifiants du réseau Thread.
Maintenant que le nœud 2 est authentifié, démarrez Thread :
> thread start Done
4. Valider l'authentification réseau
Vérifiez le state sur le nœud 2 pour confirmer qu'il a rejoint le réseau. Au bout de deux minutes, le nœud 2 passe de child à router :
> state child Done ... > state router Done
5. Réinitialiser la configuration
Pour préparer le prochain exercice, réinitialisez la configuration. Sur chaque nœud, arrêtez Thread, rétablissez la configuration d'usine et quittez l'appareil Thread simulé :
> thread stop Done > factoryreset > > exit
Vous devrez peut-être appuyer plusieurs fois sur enter pour faire réapparaître l'invite > après une commande factoryreset.
6. Gérer le réseau avec OpenThread Daemon
Pour cet exercice, nous allons simuler une instance CLI (un seul appareil SoC Thread intégré) et une instance RCP (Radio Co-Processor).
ot-daemon est un mode de l'application OpenThread POSIX qui utilise un socket UNIX comme entrée et sortie, afin que le cœur d'OpenThread puisse s'exécuter en tant que service. Un client peut communiquer avec ce service en se connectant au socket à l'aide de l'interface de ligne de commande OpenThread comme protocole.
ot-ctl est une CLI fournie par ot-daemon pour gérer et configurer le RCP. Nous allons l'utiliser pour connecter le RCP au réseau créé par l'appareil Thread.
Utiliser ot-daemon
Cet exercice utilise trois fenêtres de terminal, correspondant aux éléments suivants :
- Instance CLI de l'appareil Thread simulé (nœud 1)
- Nœud de traitement
ot-daemon - Instance de la CLI
ot-ctl
Si vous continuez à partir de l'exercice précédent, vous devriez déjà avoir deux fenêtres de terminal ouvertes. Ouvrez-en une troisième pour vous assurer d'avoir trois fenêtres de terminal disponibles pour cet exercice.
1. Nœud de départ 1
Dans la première fenêtre de terminal, lancez le processus CLI pour votre appareil Thread simulé :
$ cd ~/src/openthread $ ./build/simulation/examples/apps/cli/ot-cli-ftd 1
Remarque : Si l'invite > ne s'affiche pas après l'exécution de cette commande, appuyez sur enter.
Créez un ensemble de données opérationnelles, validez-le comme ensemble de données actif et démarrez 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
Validez cet ensemble de données comme actif :
> dataset commit active Done
Activez l'interface IPv6 :
> ifconfig up Done
Démarrer l'opération du protocole Thread :
> thread start Done
Affichez les adresses IPv6 attribuées à l'interface Thread du nœud 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 >
Comme expliqué dans l'étape Simuler un réseau Thread, une adresse est de portée locale (fe80) et trois sont de portée réseau (fd). L'EID est l'adresse de portée réseau qui ne contient pas ff:fe00 dans l'adresse. Dans cet exemple de résultat, l'EID est fd55:cf34:dea5:7994:460:872c:e807:c4ab.
Identifiez l'EID spécifique à partir de la sortie ipaddr, qui sera utilisé pour communiquer avec le nœud.
2. Démarrer ot-daemon
Dans la deuxième fenêtre de terminal, accédez au répertoire openthread et démarrez ot-daemon pour un nœud RCP, que nous appellerons "Nœud 2". Utilisez l'option détaillée -v pour afficher la sortie du journal et confirmer qu'il est en cours d'exécution, et assurez-vous d'utiliser 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'
Si l'opération réussit, ot-daemon en mode verbeux génère un résultat semblable à celui-ci :
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
Laissez ce terminal ouvert et en cours d'exécution en arrière-plan. Vous n'y saisirez aucune autre commande.
3. Utiliser ot-ctl pour rejoindre le réseau
Nous n'avons pas encore mis en service le nœud 2 (le RCP ot-daemon) sur un réseau Thread. C'est là qu'intervient ot-ctl. ot-ctl utilise la même CLI que l'application OpenThread CLI. Vous pouvez donc contrôler les nœuds ot-daemon de la même manière que les autres appareils Thread simulés.
Dans une troisième fenêtre de terminal, démarrez ot-ctl :
$ sudo ./build/posix/src/posix/ot-ctl >
Remarque : Si l'invite > ne s'affiche pas après l'exécution de cette commande, appuyez sur enter.
Vous utiliserez ot-ctl dans cette troisième fenêtre de terminal pour gérer le nœud 2 (le nœud RCP) que vous avez démarré dans la deuxième fenêtre de terminal avec ot-daemon. Vérifiez le state du nœud 2 :
> state disabled Done
Obtenez le eui64 du nœud 2 pour limiter l'association à un Associateur spécifique :
> eui64 18b4300000000001 Done
Sur le nœud 1 (première fenêtre de terminal), démarrez le commissaire et limitez l'association à cet eui64 :
> commissioner start Done > commissioner joiner add 18b4300000000001 J01NME Done
Sur le nœud 2 (troisième fenêtre de terminal), activez l'interface réseau et rejoignez le réseau :
> ifconfig up Done > joiner start J01NME Done
... patientez quelques secondes pour obtenir la confirmation ...
Join success
En tant que nœud participant, le RCP (nœud 2) s'est authentifié avec succès auprès du commissaire (nœud 1) et a reçu les identifiants du réseau Thread.
Connectez maintenant le nœud 2 au réseau Thread :
> thread start Done
4. Valider l'authentification réseau
Vérifiez le state sur le nœud 2 pour confirmer qu'il a rejoint le réseau. Au bout de deux minutes, le nœud 2 passe de child à router :
> state child Done ... > state router Done
5. Valider la connectivité
Quittez ot-ctl en utilisant Ctrl+D ou la commande exit, puis, sur la ligne de commande de votre machine hôte, envoyez un ping au nœud 1 en utilisant son EID avec la commande ping6. Si l'instance ot-daemon RCP a bien rejoint le réseau Thread et communique avec lui, le ping réussit :
$ 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. Félicitations !
Vous avez réussi à simuler votre premier réseau Thread à l'aide d'OpenThread. Formidable !
Dans cet atelier de programmation, vous avez appris à :
- Configurer la chaîne d'outils de compilation OpenThread
- Simuler un réseau Thread
- Authentifier les nœuds Thread
- Gérer un réseau Thread avec OpenThread Daemon
Pour en savoir plus, consultez les références suivantes :