1. Введение

OpenThread, выпущенный Google, — это реализация сетевого протокола Thread с открытым исходным кодом. Google Nest выпустил OpenThread, чтобы сделать технологию, используемую в продуктах Nest, широко доступной для разработчиков и ускорить разработку продуктов для «умного дома».
Спецификация Thread определяет надежный, безопасный и энергоэффективный протокол беспроводной связи между устройствами на основе IPv6 для домашних приложений. OpenThread реализует все сетевые уровни Thread, включая IPv6, 6LoWPAN, IEEE 802.15.4 с защитой MAC, установление соединения в ячеистой сети и маршрутизацию в ячеистой сети.
В этом практическом занятии вы узнаете, как смоделировать сеть Thread на эмулируемых устройствах с помощью Docker.
Что вы узнаете
- Как настроить цепочку инструментов сборки OpenThread
- Как смоделировать сеть Thread
- Как аутентифицировать узлы Thread
- Как управлять сетью потоков с помощью демона OpenThread
Что вам понадобится
- Docker
- Базовые знания Linux, сетевой маршрутизации.
2. Настройка Docker
Данная практическая работа предназначена для использования Docker на компьютерах под управлением Linux, Mac OS X или Windows. Рекомендуемая среда — Linux.
Установите Docker.
Установите Docker на выбранную вами операционную систему.
Загрузите образ Docker.
После установки Docker откройте окно терминала и загрузите образ Docker openthread/environment . Этот образ содержит предварительно собранные OpenThread и демон OpenThread, готовые к использованию в данном практическом занятии.
$ 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 — это идентификатор контейнера. Идентификатор контейнера для вашего экземпляра Docker будет отличаться от того, который указан в подсказках к этому практическому заданию.
Использование Docker
В этом практическом занятии предполагается, что вы знакомы с основами использования Docker. На протяжении всего занятия вы должны оставаться в контейнере Docker.
3. Смоделируйте сеть потоков.
В этом практическом занятии вы будете использовать пример приложения, демонстрирующий минимальное приложение OpenThread, которое предоставляет доступ к интерфейсам конфигурации и управления OpenThread через базовый интерфейс командной строки (CLI).
В этом упражнении описаны минимальные шаги, необходимые для отправки ping-запроса с одного эмулируемого устройства 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 запустите процесс CLI для эмулируемого устройства Thread, используя бинарный файл ot-cli-ftd .
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 для эмулируемого устройства. Это значение также используется при привязке к UDP-порту для эмуляции радиосвязи IEEE 802.15.4 (порт = 9000 + дескриптор файла). Каждый экземпляр эмулируемого устройства Thread в этом практическом задании будет использовать свой собственный дескриптор файла.
Примечание: При запуске процесса для эмулируемого устройства используйте только файловые дескрипторы с номерами 1 или больше, как указано в этом руководстве. Файловый дескриптор с номером 0 зарезервирован для других целей.
Создайте новый оперативный набор данных и зафиксируйте его как активный. Операционный набор данных — это конфигурация для создаваемой вами сети потоков.
> 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 start Done
Подождите несколько секунд и убедитесь, что устройство стало лидером потока. Лидером является устройство, отвечающее за управление назначением идентификаторов маршрутизатора.
> state leader Done
Просмотрите IPv6-адреса, назначенные интерфейсу Thread узла 1 (ваш вывод будет отличаться):
> 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= Router Locator (RLOC) - Не содержит
ff:fe00= Идентификатор конечной точки (EID)
Найдите EID в выводе консоли и запишите его для дальнейшего использования. В приведенном выше примере вывода EID следующий:
fd61:2344:9a52:ede0:d041:c5ba:a7bc:5ce6
2. Запуск узла 2
Откройте новый терминал и запустите оболочку bash в запущенном в данный момент контейнере Docker, который будет использоваться для Node 2.
$ docker exec -it codelab_otsim_ctnr bash
В новой командной строке bash запустите процесс CLI с аргументом 2 Это ваше второе эмулируемое устройство Thread:
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2
Примечание: Если после выполнения этой команды вы не видите приглашение > , нажмите enter .
Настройте сетевой ключ потока и идентификатор PAN, используя те же значения, что и в операционном наборе данных узла 1:
> dataset networkkey e4344ca17d1dca2a33f064992f31f786 Done > dataset panid 0xc169 Done
Зафиксируйте этот набор данных как активный:
> dataset commit active Done
Активируйте интерфейс IPv6:
> ifconfig up Done
Запуск операции протокола потока:
> thread start Done
Устройство инициализируется как дочерний элемент. Дочерний элемент потока эквивалентен конечному устройству, которое представляет собой потоковое устройство, передающее и принимающее одноадресный трафик только с родительским устройством.
> state child Done
В течение 2 минут вы должны увидеть, как состояние изменится с child на router . Маршрутизатор потоков способен маршрутизировать трафик между устройствами потоков. Его также называют родительским устройством.
> state router Done
Проверьте сеть.
Простой способ проверить работоспособность ячеистой сети — посмотреть на таблицу маршрутизации.
1. Проверьте подключение.
На узле 2 получите RLOC16. RLOC16 — это последние 16 бит IPv6-адреса RLOC устройства.
> rloc16 5800 Done
На узле 1 проверьте таблицу маршрутизатора на наличие записи RLOC16 узла 2. Убедитесь, что узел 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 |
В таблице обнаружен код RLOC узла 2, равный 0x5800 , что подтверждает его подключение к сети.
2. Проверьте связь с узлом 2, отправив пинг на узел 1.
Проверьте соединение между двумя эмулируемыми устройствами Thread. На узле 2 ping для EID, назначенного узлу 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
Нажмите enter , чтобы вернуться к > строке.
Проверьте сеть
Теперь, когда вы можете успешно обмениваться данными между двумя эмулированными устройствами Thread, протестируйте ячеистую сеть, отключив один узел.
Вернитесь к узлу 1 и остановите поток:
> thread stop Done
Переключитесь на узел 2 и проверьте его состояние. В течение двух минут узел 2 обнаружит, что лидер (узел 1) отключен, и вы должны увидеть, как узел 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 .
4. Аутентификация узлов с помощью процедуры ввода в эксплуатацию.
В предыдущем упражнении вы настроили сеть Thread с двумя имитированными устройствами и проверили их соединение. Однако это позволяет передавать между устройствами только неаутентифицированный локальный трафик IPv6. Для маршрутизации глобального трафика IPv6 между ними (и Интернетом через пограничный маршрутизатор Thread) узлы должны быть аутентифицированы.
Для аутентификации одно из устройств должно выступать в роли Комиссара. Комиссар — это выбранный в данный момент сервер аутентификации для новых устройств Thread, а также лицо, предоставляющее сетевые учетные данные, необходимые для подключения устройств к сети.
В этом упражнении мы будем использовать ту же двухузловую топологию, что и раньше. Для аутентификации лидер потока будет выступать в роли уполномоченного лица, а маршрутизатор потока — в роли присоединившегося.

Docker
Для каждого узла (окна терминала) в оставшихся упражнениях убедитесь, что вы запускаете контейнер Docker со сборкой OpenThread. Если вы продолжаете с предыдущего упражнения, у вас должны быть открыты две командные строки bash в одном и том же контейнере Docker. Если это не так, обратитесь к шагу «Устранение неполадок Docker» или просто повторите упражнение «Имитация сетевого потока» .
1. Создайте сеть.
На узле 1 запустите процесс командной строки:
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 start Done
Подождите несколько секунд и убедитесь, что устройство стало лидером потока:
> state leader Done
2. Начать работу в должности комиссара.
Оставаясь на узле 1, запустите роль комиссара:
> commissioner start Done
Разрешите любому пользователю Joiner (используя символ подстановки * ) с учетными данными Joiner J01NME подключаться к сети. Joiner — это устройство, которое добавляется администратором к уже подключенной сети Thread Network.
> commissioner joiner add * J01NME Done
3. Начните работу в роли "Присоединяющийся"
Во втором окне терминала, в контейнере Docker, запустите новый процесс CLI. Это Node 2.
root@c0f3912a74ff:/# /openthread/build/examples/apps/cli/ot-cli-ftd 2
На узле 2 активируйте роль «Присоединяющийся», используя учетные данные J01NME Joiner Credential.
> ifconfig up Done > joiner start J01NME Done
...подождите несколько секунд для подтверждения...
Join success
В качестве участника, устройство (Узел 2) успешно прошло аутентификацию у Комиссара (Узел 1) и получило учетные данные сети Thread Network.
Теперь, когда узел 2 аутентифицирован, запустите поток:
> thread start Done
4. Проверка сетевой аутентификации
Проверьте state узла 2, чтобы убедиться, что он подключился к сети. В течение двух минут узел 2 переходит из child узла в router :
> state child Done ... > state router Done
5. Сброс конфигурации
Для подготовки к следующему упражнению сбросьте конфигурацию. На каждом узле остановите Thread, выполните сброс до заводских настроек и выйдите из эмулируемого устройства Thread:
> thread stop Done > factoryreset > > exit root@c0f3912a74ff:/#
Возможно, вам придётся несколько раз нажать enter , чтобы после команды factoryreset снова появилось приглашение > .
5. Управление сетью с помощью демона OpenThread.
В рамках этого упражнения мы будем моделировать работу одного экземпляра CLI (одного встроенного устройства SoC Thread) и одного экземпляра радиосопроцессора (RCP).
ot-daemon — это режим приложения OpenThread Posix, использующий UNIX-сокет в качестве входа и выхода, позволяющий ядру OpenThread работать как служба. Клиент может взаимодействовать с этой службой, подключаясь к сокету с помощью протокола OpenThread CLI.
ot-ctl — это интерфейс командной строки, предоставляемый ot-daemon для управления и настройки RCP. С его помощью мы подключим RCP к сети, созданной устройством Thread.
Docker
Для каждого узла (окна терминала) в этом упражнении убедитесь, что вы запускаете контейнер Docker со сборкой OpenThread. Если вы продолжаете с предыдущего упражнения, у вас должны быть открыты две командные строки bash в одном и том же контейнере Docker. Если нет, см. шаг «Устранение неполадок Docker» .
Используйте ot-daemon
В этом упражнении будут использоваться три окна терминала, соответствующие следующим:
- Экземпляр командной строки имитированного устройства Thread (Узел 1)
- процесс
ot-daemon - экземпляр CLI
ot-ctl
1. Запустите узел 1.
В первом окне терминала запустите процесс командной строки для эмулируемого устройства Thread:
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 start Done
Просмотрите IPv6-адреса, назначенные интерфейсу Thread узла 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 >
Как пояснялось в шаге «Имитация сети потоков» , один адрес является локальным ( fe80 ), а три — локальными ( fd ). EID — это локальный адрес, который не содержит ff:fe00 . В этом примере выходных данных EID равен fd55:cf34:dea5:7994:460:872c:e807:c4ab .
Определите конкретный EID из выходных данных ipaddr , который будет использоваться для связи с узлом.
2. Запустите ot-daemon
Во втором окне терминала создайте узел устройства tun и установите права на чтение/запись:
root@c0f3912a74ff:/# mkdir -p /dev/net && mknod /dev/net/tun c 10 200 root@c0f3912a74ff:/# chmod 600 /dev/net/tun
Это устройство используется для передачи и приема пакетов в виртуальных устройствах. Если устройство уже создано, может возникнуть ошибка — это нормально и может быть проигнорировано.
Запустите ot-daemon для узла RCP, который мы назовем Узел 2. Используйте флаг -v verbose, чтобы просмотреть вывод логов и убедиться, что он запущен:
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 (RCP-контроллер ot-daemon ) ни к одной сети Thread. Вот тут-то и пригодится ot-ctl . ot-ctl использует тот же интерфейс командной строки, что и приложение OpenThread CLI. Поэтому вы можете управлять узлами ot-daemon так же, как и другими имитируемыми устройствами Thread.
Откройте третье окно терминала и запустите существующий контейнер:
$ docker exec -it codelab_otsim_ctnr bash
После входа в контейнер запустите ot-ctl :
root@c0f3912a74ff:/# /openthread/build/posix/src/posix/ot-ctl >
В третьем окне терминала вы будете использовать ot-ctl для управления узлом 2 (узлом RCP), который вы запустили во втором окне терминала с помощью ot-daemon . Проверьте state узла 2:
> state disabled Done
Используйте eui64 из Node 2, чтобы ограничить присоединение только определенным участником:
> eui64 18b4300000000001 Done
На узле 1 (первое окно терминала) запустите Commissioner и ограничьте возможность подключения только для этого eui64:
> commissioner start Done > commissioner joiner add 18b4300000000001 J01NME Done
В третьем окне терминала отобразите сетевой интерфейс узла 2 и подключитесь к сети:
> ifconfig up Done > joiner start J01NME Done
...подождите несколько секунд для подтверждения...
Join success
В качестве участника, RCP (Узел 2) успешно прошел аутентификацию у Комиссара (Узел 1) и получил учетные данные сети Thread Network.
Теперь подключите узел 2 к сети Thread (снова в третьем окне терминала):
> thread start Done
4. Проверка сетевой аутентификации
В третьем терминале проверьте state узла 2, чтобы убедиться, что он подключился к сети. В течение двух минут узел 2 перейдет из child в router :
> state child Done ... > state router Done
5. Проверьте подключение.
В третьем окне терминала завершите работу ot-ctl , используя Ctrl+D или команду exit , и вернитесь в консоль bash контейнера. Из этой консоли выполните команду ping6 для проверки связи с узлом 1, используя его EID. Если экземпляр RCP ot-daemon успешно подключен к сети Thread и взаимодействует с ней, проверка связи будет успешной:
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 может потребоваться проверить, запущен ли контейнер, и перезапустить/ввести его при необходимости. Все контейнеры Docker, созданные без использования опции --rm должны по-прежнему существовать.
Чтобы показать, какие контейнеры 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 (с помощью команды mknod ) вы сталкиваетесь с ошибками Operation not permitted , убедитесь, что Docker запускается от имени пользователя root в соответствии с командами, приведенными в этом руководстве. Данное руководство не поддерживает запуск Docker в режиме без прав root .
7. Поздравляем!
Вы успешно смоделировали свою первую нейронную сеть Thread с использованием OpenThread. Отлично!
В этом практическом занятии вы научились:
- Запуск и управление контейнером Docker для моделирования OpenThread
- Имитация сети потоков
- Аутентификация узлов потоков
- Управление сетью потоков с помощью демона OpenThread
Чтобы узнать больше о Thread и OpenThread, ознакомьтесь с этими справочными материалами:
- Обзор Thread Primer на openthread.io
- Спецификация резьбы
- Репозиторий OpenThread на GitHub
- Справочник по интерфейсу командной строки OpenThread
- Дополнительная поддержка OpenThread в Docker.
Или попробуйте использовать OpenThread Border Router в контейнере Docker !