Моделирование сети потоков с использованием OpenThread в Docker

1. Введение

26b7f4f6b3ea0700.png

OpenThread выпущенного Google является реализацией открытого источника Thread сетевого протокола. Google Nest выпустил OpenThread, чтобы сделать технологию, используемую в продуктах Nest, широко доступной для разработчиков, чтобы ускорить разработку продуктов для подключенного дома.

Спецификация Thread определяет IPv6 на основе надежной, безопасной и протокол беспроводной связи с низким энергопотреблением устройство-устройство для домашнего применения. OpenThread реализует все сетевые уровни потоков, включая IPv6, 6LoWPAN, IEEE 802.15.4 с безопасностью MAC, установлением Mesh Link и Mesh Routing.

Эта Codelab проведет вас через моделирование сети потоков на эмулируемых устройствах с помощью Docker.

Что ты узнаешь

  • Как настроить набор инструментов для сборки OpenThread
  • Как смоделировать сеть потоков
  • Как аутентифицировать ноды Thread
  • Как управлять сетью потоков с помощью OpenThread Daemon

Что тебе понадобится

  • Докер
  • Базовые знания Linux, сетевая маршрутизация

2. Настройте Docker.

Эта Codelab предназначена для использования Docker на компьютерах с Linux, Mac OS X или Windows. Linux - рекомендуемая среда.

Установить Docker

Установите Docker на выбранную вами ОС.

Скачать Docker

Вытащите образ Docker

После установки Docker, откройте окно терминала и потяните openthread/codelab_otsim Docker изображение. Этот образ содержит предварительно созданные и готовые к использованию OpenThread и OpenThread Daemon для этой Codelab.

$ docker pull openthread/codelab_otsim:latest

Обратите внимание, что полная загрузка может занять несколько минут.

В окне терминала, начните контейнер DOCKER с изображения и соединить его bash оболочки:

$ docker run --name codelab_otsim_ctnr -it --rm \
   --sysctl net.ipv6.conf.all.disable_ipv6=0 \
   --cap-add=net_admin openthread/codelab_otsim bash

Обратите внимание на флаги, которые требуются для этой Codelab:

  • --sysctl net.ipv6.conf.all.disable_ipv6=0 - это позволяет IPv6 внутри контейнера
  • --cap-add=net_admin - позволяет возможность NET_ADMIN, что позволяет выполнять сетевые связанные операции, такие как добавление IP - маршрутов

Оказавшись в контейнере, у вас должно появиться приглашение, подобное этому:

root@c0f3912a74ff:/#

В приведенном выше примере, c0f3912a74ff является Идентификатор контейнера. Идентификатор контейнера для вашего экземпляра контейнера Docker будет отличаться от того, который отображается в подсказках для этой Codelab.

Использование Docker

В этой Codelab предполагается, что вы знаете основы использования Docker. Вы должны оставаться в контейнере Docker на протяжении всей Codelab.

3. Моделируйте сеть потоков.

Пример приложения, которое вы будете использовать для этой Codelab, демонстрирует минимальное приложение OpenThread, которое предоставляет интерфейсы конфигурации и управления OpenThread через базовый интерфейс командной строки (CLI).

Это упражнение проведет вас через минимальные шаги, необходимые для проверки связи одного эмулируемого устройства Thread с другого устройства эмулируемого потока.

На рисунке ниже описана базовая топология сети Thread. В этом упражнении мы будем имитировать два узла в зеленом круге: лидер потока и маршрутизатор потока с одним соединением между ними.

6e3aa07675f902dc.png

Создайте сеть

1. Начальный узел 1

Если вы еще не сделали этого, в окне терминала, запустите контейнер Докер и подключить его bash оболочки:

$ docker run --name codelab_otsim_ctnr -it --rm \
   --sysctl net.ipv6.conf.all.disable_ipv6=0 \
   --cap-add=net_admin openthread/codelab_otsim bash

В контейнере Докера, перейдите к openthread директории и нерест процесса CLI для сэмулированной резьбы с использованием ot-cli-ftd двоичных.

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/simulation/bin/ot-cli-ftd 1

Примечание: Если вы не видите > выводится после выполнения этой команды, нажмите enter .

Этот двоичный файл реализует устройство OpenThread, эмулируемое поверх POSIX. Радиодрайвер IEEE 802.15.4 реализован поверх UDP (кадры IEEE 802.15.4 передаются в полезных данных UDP).

Аргумент 1 представляет собой дескриптор файла , который представляет наименее значащие биты «фабрика-присвоенную» IEEE EUI-64 для устройства эмуляции. Это значение также используется при привязке к порту UDP для эмуляции радио IEEE 802.15.4 (порт = 9000 + дескриптор файла). Каждый экземпляр эмулируемого устройства Thread в этой Codelab будет использовать другой дескриптор файла.

Примечание: только дескрипторы использование файлов из 1 или больше , как указано в этом Codelab при порождении процесса для сэмулированных. Файл дескриптор 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 = меш-местный
  • Начинается с fe80 = локальной связью

Типы локальных ячеистых адресов подразделяются на следующие категории:

  • Содержит ff:fe00 = Router Locator (Rloc)
  • Не содержит ff:fe00 = идентификатора конечной точки (ВИЗ)

Определите EID в выводе консоли, запишите его для дальнейшего использования. В приведенном выше примере выходных данных EID:

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

2. Начальный узел 2

Откройте новый терминал и выполнить bash оболочки в настоящее время работает контейнер Докер использовать для узла 2.

$ docker exec -it codelab_otsim_ctnr bash

В этом новом bash строке перейдите к openthread директории и икру процесса CLI. Это ваше второе эмулируемое устройство Thread:

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/simulation/bin/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 . Маршрутизатор потоков может маршрутизировать трафик между устройствами Thread. Его также называют Родителем.

> state
router
Done

Проверить сеть

Простой способ проверить ячеистую сеть - посмотреть на таблицу маршрутизаторов.

1. Проверьте подключение.

На узле 2 возьмите RLOC16. RLOC16 - это последние 16 бит адреса RLOC IPv6 устройства.

> 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. Проверка связи с узлом 1 от узла 2

Проверьте подключение между двумя эмулируемыми устройствами Thread. В узле 2, ping Ид , назначенный узел 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 для возврата > CLI строки.

Протестируйте сеть

Теперь, когда вы можете успешно выполнить эхо-запрос между двумя эмулированными потоковыми устройствами, протестируйте ячеистую сеть, отключив один узел.

Вернитесь к Узлу 1 и остановите поток:

> thread stop
Done

Переключитесь на Узел 2 и проверьте состояние. В течение двух минут, узел 2 обнаруживает , что лидер (Node 1) отсутствует, и вы должны увидеть узел 2 перехода , чтобы быть leader в сети:

> state
router
Done
...
> state
leader
Done

После подтверждения остановки резьбы и возврата к заводским узла 2 перед выходом обратно к Docker bash строки. Сброс к заводским настройкам выполняется, чтобы гарантировать, что учетные данные сети потоков, которые мы использовали в этом упражнении, не были перенесены в следующее упражнение.

> thread stop
Done
> factoryreset
>
> exit
root@c0f3912a74ff:/#

Вы можете нажать enter несколько раз , чтобы принести > подсказки обратно после factoryreset команды. Не выходите из контейнера Docker.

Также сброс к заводским настройкам и выход из Узла 1:

> factoryreset
>
> exit
root@c0f3912a74ff:/#

См OpenThread CLI Reference , чтобы изучить все доступные команды CLI.

4. Аутентифицировать узлы при вводе в эксплуатацию.

В предыдущем упражнении вы настроили сеть потоков с двумя смоделированными устройствами и проверенным подключением. Однако это позволяет передавать между устройствами только неаутентифицированный локальный трафик IPv6. Для маршрутизации глобального трафика IPv6 между ними (и Интернетом через граничный маршрутизатор потока) узлы должны быть аутентифицированы.

Для аутентификации одно устройство должно действовать как комиссар. Комиссар является в настоящее время выбранным сервером аутентификации для новых устройств Thread и авторизатором для предоставления сетевых учетных данных, необходимых для подключения устройств к сети.

В этом упражнении мы будем использовать ту же двухузловую топологию, что и раньше. Для аутентификации руководитель потока будет действовать как уполномоченный, а маршрутизатор потока - как участник.

d6a67e8a0d0b5dcb.png

Докер

Для каждого узла (окна терминала) в оставшихся упражнениях убедитесь, что вы запускаете контейнер Docker со сборкой OpenThread. Если продолжается из предыдущего упражнения, вы все равно должны иметь два bash подсказки в пределах одной и той же Докер контейнер уже открыт. Если нет, см шаг Docker Устранение неполадок, или просто Пересоединть симулировать сети Thread упражнения.

1. Создайте сеть

В узле 1 создайте процесс CLI:

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/simulation/bin/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

Разрешить любой Столяр (с помощью * подстановочные) с J01NME Столяр удостоверени комиссии в сеть. Присоединяющийся - это устройство, добавляемое администратором-человеком к заказанной сети потоков.

> commissioner joiner add * J01NME
Done

3. Запустите роль Joiner.

Во втором окне терминала в контейнере Docker создайте новый процесс CLI. Это Узел 2.

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/simulation/bin/ot-cli-ftd 2

На узле 2, включить роль столяра с помощью J01NME Столяр Credential.

> ifconfig up
Done
> joiner start J01NME
Done

... подождите несколько секунд для подтверждения ...

Join success

В качестве присоединяемого устройство (узел 2) успешно аутентифицировалось с помощью уполномоченного (узел 1) и получило учетные данные потоковой сети.

Теперь, когда Узел 2 аутентифицирован, запустите Thread:

> thread start
Done

4. Подтвердите сетевую аутентификацию.

Проверьте state на узле 2, чтобы подтвердить , что он теперь присоединился к сети. В течение двух минут, Узел 2 перехода от child к router :

> state
child
Done
...
> state
router
Done

5. Сбросить конфигурацию.

Чтобы подготовиться к следующему упражнению, сбросьте конфигурацию. На каждом узле остановите поток, выполните сброс настроек до заводских и выйдите из эмулируемого устройства потока:

> thread stop
Done
> factoryreset
>
> exit
root@c0f3912a74ff:/#

Вы можете нажать enter несколько раз , чтобы принести > подсказки обратно после factoryreset команды.

5. Управляйте сетью с помощью OpenThread Daemon.

В этом упражнении мы собираемся смоделировать один экземпляр CLI (одно встроенное устройство SoC Thread) и один экземпляр Radio Co-Processor (RCP).

ot-daemon является режимом приложения OpenThread Posix , который использует сокет UNIX в качестве входа и выхода, так что сердечник OpenThread может работать в качестве службы. Клиент может взаимодействовать с этой службой, подключившись к сокету, используя OpenThread CLI в качестве протокола.

ot-ctl является CLI обеспечивает ot-daemon для управления и настройки RCP. Используя это, мы подключим RCP к сети, созданной устройством Thread.

Докер

Для каждого узла (окна терминала) в этом упражнении убедитесь, что вы запускаете контейнер Docker со сборкой OpenThread. Если продолжается из предыдущего упражнения, вы должны иметь два bash подсказки в пределах одной и той же Докер контейнер уже открыт. Если нет, см шаг Docker Устранение неполадок.

Используйте ot-daemon

В этом упражнении будут использоваться три окна терминала, соответствующие следующему:

  1. Экземпляр CLI моделируемого устройства Thread (узел 1)
  2. ot-daemon процесс
  3. ot-ctl экземпляр консоли

1. Начальный узел 1

В первом окне терминала создайте процесс CLI для вашего эмулируемого устройства Thread:

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/simulation/bin/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 ). ВИЗ является сетка-локальный адрес , который не содержит ff:fe00 в адресе. В этом примере выход, Ид является 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

Это устройство используется для передачи и приема пакетов в виртуальных устройствах. Вы можете получить сообщение об ошибке, если устройство уже было создано - это нормально, и на это можно не обращать внимания.

Перейдите к openthread каталога и запустить ot-daemon для узла RCP, который мы называем Node 2. Используйте -v подробного флага , так что вы можете видеть вывод журнала и убедитесь , что он работает:

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/posix/bin/ot-daemon -v \
    'spinel+hdlc+forkpty://output/simulation/bin/ot-rcp?forkpty-arg=2'

В случае успеха, ot-daemon в режиме многословным генерирует выходной сигнал , аналогичный приведенному ниже:

ot-daemon[228024]: Running OPENTHREAD/20191113-00831-gfb399104; POSIX; Jun 7 2020 18:05:15
ot-daemon[228024]: Thread version: 2
ot-daemon[228024]: RCP version: OPENTHREAD/20191113-00831-gfb399104; SIMULATION; Jun 7 2020 18:06:08

Оставьте этот терминал открытым и работайте в фоновом режиме. Вы не будете вводить в него никаких дальнейших команд.

3. Используйте ot-ctl, чтобы присоединиться к сети.

Мы не введен в эксплуатацию узел 2 ( ot-daemon RCP) в любой сети Thread еще. Это где ot-ctl приходит. ot-ctl использует тот же интерфейс командной строки , как приложение OpenThread CLI. Таким образом, вы можете управлять ot-daemon узлов таким же образом , как и другие моделируемых устройств темы.

Откройте третье окно терминала и выполните существующий контейнер:

$ docker exec -it codelab_otsim_ctnr bash

После того, как в контейнере, начать ot-ctl :

root@c0f3912a74ff:/# cd ~/src/openthread
root@c0f3912a74ff:/# ./output/posix/bin/ot-ctl
>

Вы будете использовать ot-ctl в третьем окне терминала для управления узлом 2 (RCP узла) , который вы начали во втором окне терминала с ot-daemon . Проверьте state узла , 2:

> state
disabled
Done

Получить узла 2 в eui64 , чтобы ограничить присоединение к конкретному Joiner:

> eui64
18b4300000000001
Done

На Узле 1 (первое окно терминала) запустите Комиссар и ограничьте присоединение только этим eui64:

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

На узле 2 (третье окно терминала) откройте сетевой интерфейс и подключитесь к сети:

> ifconfig up
Done
> joiner start J01NME
Done

... подождите несколько секунд для подтверждения ...

Join success

В качестве присоединяющегося RCP (узел 2) успешно аутентифицировал себя с помощью уполномоченного (узел 1) и получил учетные данные потоковой сети.

Теперь присоедините узел 2 к сети потоков:

> thread start
Done

4. Подтвердите сетевую аутентификацию.

Проверьте state на узле 2, чтобы подтвердить , что он теперь присоединился к сети. В течение двух минут, Узел 2 перехода от child к router :

> state
child
Done
...
> state
router
Done

5. Подтвердите подключение.

Выход ot-ctl с помощью Ctrl + D и в командной строке вашего хост - машины, пинг узел 1, используя его EID с ping6 команды. Если ot-daemon экземпляр RCP успешно присоединен и обменивается данными с сетью 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 запущены:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
505fc57ffc72        codelab_otsim       "bash"              10 minutes ago      Up 10 minutes                           codelab_otsim_ctnr

Чтобы показать все контейнеры Docker (запущенные и остановленные):

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
505fc57ffc72        codelab_otsim       "bash"              10 minutes ago      Up 10 minutes                           codelab_otsim_ctnr

Если вы не видите контейнер codelab_otsim_ctnr на выходе либо docker ps команды, запустить его снова:

$ docker run --name codelab_otsim_ctnr -it --rm \
   --sysctl net.ipv6.conf.all.disable_ipv6=0 \
   --cap-add=net_admin openthread/codelab_otsim bash

Если контейнер остановлен (перечислены в docker ps -a , но не docker ps ), перезапустить его:

$ docker start -i codelab_otsim_ctnr

Если контейнер Докер уже запущен (перечислены в docker ps ), переподключение к контейнеру в каждом терминале:

$ docker exec -it codelab_otsim_ctnr bash

Ошибки «Операция запрещена»

При запуске в Operation not permitted ошибки при создании новых узлов OpenThread ( с помощью mknod команды), убедитесь , что вы работаете в Докер в качестве корневого пользователя в соответствии с командами , описанными в этом Codelab. Это Codelab не поддерживает работу Докер в режиме безродным .

7. Поздравляем!

Вы успешно смоделировали свою первую сеть потоков с помощью OpenThread. Потрясающие!

В этом Codelab вы узнали, как:

  • Запуск и управление контейнером OpenThread Simulation Docker
  • Имитация сети потоков
  • Аутентифицировать узлы потока
  • Управление сетью потоков с помощью OpenThread Daemon

Чтобы узнать больше о Thread и OpenThread, изучите эти ссылки:

Или попробуйте использовать OpenThread пограничный маршрутизатор в контейнере Докер !