Сейчас я работаю над проектом, в котором у нас есть встроенная система Linux с некоторыми функциями управления датчиками/двигателями, и мы создаем приложение с графическим интерфейсом, позволяющее пользователю управлять системой. В будущем мы можем запускать оба приложения в одной системе, но на данный момент мы хотим иметь возможность установить это как обновление для существующих машин, а существующие платы контроллеров не имеют возможности запускать графический интерфейс как он разработан, поэтому он будет работать на отдельном SBC (в настоящее время мы создаем прототип с ODroid C4 под управлением Android 9)
Мы разработали API связи между двумя системами, и я провел начальное тестирование, запустив прямое соединение Ethernet между двумя системами со статическими IP-адресами, однако из-за требований к развертыванию и ограничений Android мне нужно выяснить другой метод подключения для фактического развертывания продукта. Нам нужно, чтобы клиент мог подключаться к Интернету в системе с графическим интерфейсом через Wi-Fi или Ethernet, поэтому встроенный порт Ethernet на ODroid не может использоваться для этой цели, и, кроме того, ядро Android имеет некоторое внутреннее поведение. это позволяет только одному сетевому соединению быть активным в любой момент времени.
Исключением из правил определения приоритетов сети Android являются сетевые интерфейсы USB. И система контроллера Linux, и само устройство Android могут отображаться как сетевой интерфейс для удаленного хоста — в системе контроллера у нас есть доступный USB-порт для гаджета, и я включил g_эфир
модуль ядра в нашем образе системы, а в системе с графическим интерфейсом у нас есть порт USB OTG, и я могу включить USB-модем в настройках системы Android.
Мне удалось установить связь между любой из этих систем и моей системой разработки Windows, используя их соответствующие интерфейсы, но я до сих пор не понял, как заставить одно решение взаимодействовать с другим.
Система Linux в качестве удаленного интерфейса (USB-гаджет с драйвером g_ether)
- Загрузка модуля ядра g_ether в системе Linux создает
usb0
интерфейс:
# modprobe g_ether
# есликонфиг
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
инет 10.42.128.107 сетевая маска 255.255.255.0 широковещательная рассылка 10.42.128.255
inet6 fe80::206:cff:fe01:1027 prefixlen 64 scopeid 0x20<ссылка>
эфир 00:06:0c:01:10:27 txqueuelen 1000 (Ethernet)
RX-пакеты 500 байт 54062 (52,7 КиБ)
Ошибки RX 0 отброшено 46 переполнение 0 кадр 0
Пакеты TX 0 байт 24423 (23,8 КиБ)
Ошибки передачи 0 отброшено 0 превышение пропускной способности 0 несущей 0 коллизий 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
инет 127.0.0.1 сетевая маска 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<хост>
loop txqueuelen 0 (локальная петля)
Пакеты RX 0 байт 0 (0,0 Б)
Ошибки RX 0 отброшено 0 переполнение 0 кадр 0
Пакеты TX 0 байт 0 (0,0 Б)
Ошибки передачи 0 отброшено 0 превышение пропускной способности 0 несущей 0 коллизий 0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::24b:5bfc:8a9e:b148 prefixlen 64 scopeid 0x20<ссылка>
эфир 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
Пакеты RX 0 байт 0 (0,0 Б)
Ошибки RX 0 отброшено 0 переполнение 0 кадр 0
Пакеты TX 1 байт 96 (96,0 Б)
Ошибки передачи 0 отброшено 0 превышение пропускной способности 0 несущей 0 коллизий 0
- Подключение USB-кабеля от порта гаджета в системе Linux к хост-порту в системе Android немедленно создает
usb0
интерфейс на Android и генерирует IP-адрес для usb0
интерфейс в линуксе:
Андроид:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Драйвер cdc_subset
МУЛЬТИКАНСИРОВАННАЯ ТРАНСЛЯЦИЯ MTU: 1500 Метрика: 1
Пакеты RX: 0 ошибки: 0 отброшены: 0 переполнение: 0 кадр: 0
Пакеты TX: 0 ошибки: 0 отброшены: 0 переполнения: 0 оператор: 0
коллизии: 0 txqueuelen: 1000
Байты RX:0 Байты TX:0
Линукс:
# если конфиг usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
инет 169.254.119.94 сетевая маска 255.255.0.0 широковещательная рассылка 169.254.255.255
inet6 fe80::24b:5bfc:8a9e:b148 prefixlen 64 scopeid 0x20<ссылка>
эфир 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
Пакеты RX 0 байт 0 (0,0 Б)
Ошибки RX 0 отброшено 0 переполнение 0 кадр 0
Пакеты TX 1 байт 96 (96,0 Б)
Ошибки передачи 0 отброшено 0 превышение пропускной способности 0 несущей 0 коллизий 0
- При открытии интерфейса в системе Android не назначается IP-адрес, поэтому мне приходится назначать его вручную, используя пространство 169.254/16, которое система Linux назначает самостоятельно.
odroidc4:/ # ifconfig usb0 up
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Драйвер cdc_subset
адрес inet6: fe80::f84c:95ff:fec0:8d18/64 Область действия: ссылка
ВВЕРХ ТРАНСЛЯЦИЯ РАБОТАЕТ MULTICAST MTU:1500 Метрика:1
Пакеты RX: 117, ошибки: 4, отброшенные: 75, переполнение: 0, кадр: 4.
Пакеты TX: 27, ошибки: 0, отброшенные: 0, превышения: 0, носитель: 0.
коллизии: 0 txqueuelen: 1000
Байты RX: 5080 Байты TX: 4897
odroidc4:/ # ip addr add 169.254.1.1/16 широковещательный 169.254.255.255 dev usb0
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Драйвер cdc_subset
инет адрес: 169.254.1.1 Bcast: 169.254.255.255 Маска: 255.255.0.0
адрес inet6: fe80::f84c:95ff:fec0:8d18/64 Область действия: ссылка
ВВЕРХ ТРАНСЛЯЦИЯ РАБОТАЕТ MULTICAST MTU:1500 Метрика:1
Пакеты RX: 117, ошибки: 4, отброшенные: 75, переполнение: 0, кадр: 4.
Пакеты TX: 44 ошибки: 0 отброшены: 0 переполнены: 0 перевозчик: 0
коллизии: 0 txqueuelen: 1000
Байты RX: 5080 Байты TX: 8528
На данный момент у меня есть 2 проблемы: во-первых, пинг любого устройства с другого не дает ответа. Глядя на количество пакетов на стороне Android, создается впечатление, что он получает эхо-запросы со стороны Linux, но не отвечает, что может быть вызвано второй проблемой, заключающейся в том, что таблицы маршрутизации не работают должным образом. на стороне андроида. Учитывая, что мне нужно, чтобы это работало, когда в системе Android также есть активное подключение к Интернету, у меня одновременно подключен Ethernet, и это то, что я вижу при просмотре маршрутизации:
odroidc4:/ # список маршрутов ip
169.254.0.0/16 dev usb0 ссылка на область ядра proto src 169.254.1.1
10.42.128.0/24 dev eth0 прото-область ядра ссылка src 10.42.128.166
odroidc4:/ # ip route get 169.254.119.94
169.254.119.94 через 10.42.128.2 dev eth0 таблица eth0 src 10.42.128.166 uid 0
тайник
odroidc4:/ # ip route show table 0
по умолчанию через 10.42.128.2 dev eth0 table eth0 proto static
...
Система Android в качестве удаленного интерфейса (USB-модем с портом OTG)
Этот сценарий, кажется, немного приближает меня, поскольку я могу заставить работать одностороннюю связь.
- После добавления необходимых драйверов в мой образ Linux, подключение кабеля от порта Android OTG к порту хоста Linux показывает, что система распознает USB-устройство в
dmesg
:
[235.710937] usb 1-2.3: новое полноскоростное USB-устройство номер 7 с использованием at91_ohci
[ 235.862304] rndis_host 1-2.3:1.0 usb0: зарегистрируйте 'rndis_host' на usb-at91-2.3, устройство RNDIS, 32:1d:e8:fc:dd:8
- А
usb0
интерфейс немедленно создается и ему назначается IP-адрес на стороне Linux:
# если конфиг usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
инет 169.254.249.80 сетевая маска 255.255.0.0 широковещательная рассылка 169.254.255.255
inet6 fe80::e341:f9b1:b676:99b7 prefixlen 64 scopeid 0x20<ссылка>
эфир 32:1d:e8:fc:dd:80 txqueuelen 1000 (Ethernet)
RX-пакеты 69 байт 13572 (13,2 КиБ)
Ошибки RX 0 отброшено 0 переполнение 0 кадр 0
Пакеты TX 73 байта 18251 (17,8 КиБ)
Ошибки передачи 8 отброшено 0 превышение пропускной способности 0 несущей 0 коллизий 0
- На стороне Android с включенным USB-модемом в настройках появляется интерфейс usb0, но
начинается вниз. Поднятие этого не дает ему IP-адрес, поэтому я назначил его вручную, но, как и в первом сценарии, таблица маршрутизации не работает должным образом:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
МУЛЬТИКАНСИРОВАННАЯ ТРАНСЛЯЦИЯ MTU: 1500 Метрика: 1
Пакеты RX: 0 ошибки: 0 отброшены: 0 переполнение: 0 кадр: 0
Пакеты TX: 0 ошибки: 0 отброшены: 0 переполнения: 0 оператор: 0
коллизии: 0 txqueuelen: 1000
Байты RX:0 Байты TX:0
odroidc4:/ # ifconfig usb0 up
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
адрес inet6: fe80::dc75:5cff:fe41:2ae6/64 Область действия: ссылка
ВВЕРХ ТРАНСЛЯЦИЯ РАБОТАЕТ MULTICAST MTU:1500 Метрика:1
RX-пакетов: 10 ошибок: 0 отброшено: 0 превышено: 0 кадр: 0
Пакеты TX: 12, ошибки: 0, отброшенные: 0, переполнение: 0, носитель: 0.
коллизии: 0 txqueuelen: 1000
Байты RX: 1090 Байты TX: 2751
odroidc4:/ # ip addr add 169.254.1.1/16 широковещательный 169.254.255.255 dev usb0
odroidc4:/ # ip-маршрут
10.42.128.0/24 dev eth0 прото-область ядра ссылка src 10.42.128.166
169.254.0.0/16 dev usb0 ссылка на область ядра proto src 169.254.1.1
odroidc4:/ # ip route get 169.254.249.80
169.254.249.80 через 10.42.128.2 dev eth0 таблица eth0 src 10.42.128.166 uid 0
тайник
- Однако в этом случае я могу получить успешную связь со стороны Android, вручную указав интерфейс:
odroidc4:/ # ping -c 5 -I usb0 169.254.249.80
PING 169.254.249.80 (169.254.249.80) от 169.254.1.1 usb0: 56(84) байт данных.
64 байта от 169.254.249.80: icmp_seq=1 ttl=64 время=1,56 мс
64 байта от 169.254.249.80: icmp_seq=2 ttl=64 время=1,89 мс
64 байта от 169.254.249.80: icmp_seq=3 ttl=64 время=1,71 мс
64 байта от 169.254.249.80: icmp_seq=4 ttl=64 время=1,75 мс
64 байта от 169.254.249.80: icmp_seq=5 ttl=64 время=1,85 мс
--- Статистика пинга 169.254.249.80 ---
5 пакетов передано, 5 получено, 0% потери пакетов, время 4006 мс
2|odroidc4:/ # ping6 -c5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 байт данных
64 байта из fe80::dc75:5cff:fe41:2ae6: icmp_seq=1 ttl=64 time=0,202 мс
64 байта от fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=1,91 мс (DUP!)
64 байта из fe80::dc75:5cff:fe41:2ae6: icmp_seq=2 ttl=64 time=0,196 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=1,80 мс (DUP!)
64 байта от fe80::dc75:5cff:fe41:2ae6: icmp_seq=3 ttl=64 time=0,199 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=1,37 мс (DUP!)
64 байта от fe80::dc75:5cff:fe41:2ae6: icmp_seq=4 ttl=64 time=0,199 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=1,85 мс (DUP!)
64 байта из fe80::dc75:5cff:fe41:2ae6: icmp_seq=5 ttl=64 time=0,205 мс
--- статистика пинга ff02::1%usb0 ---
5 пакетов передано, 5 получено, +4 дубликата, 0% потери пакетов, время 4004 мс
rtt min/avg/max/mdev = 0,196/0,883/1,914/0,776 мс
- Я все еще не могу заставить работать трафик, исходящий со стороны Linux, предположительно из-за проблемы маршрутизации на стороне Android, препятствующей правильной маршрутизации обратного трафика:
# ping -c 5 -I usb0 169.254.1.1
PING 169.254.1.1 (169.254.1.1) от 169.254.249.80 usb0: 56 (84) байт данных.
--- Статистика пинга 169.254.1.1 ---
5 пакетов передано, 0 получено, 100% потери пакетов, время 4295 мс
# ping6 -c 5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 байт данных
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=0,522 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=0,302 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=0,376 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=0,383 мс
64 байта из fe80::e341:f9b1:b676:99b7: icmp_seq=5 ttl=64 time=0,385 мс
--- статистика пинга ff02::1%usb0 ---
5 пакетов передано, 5 получено, 0% потери пакетов, время 4009 мс
rtt min/avg/max/mdev = 0,302/0,393/0,522/0,074 мс
В обоих сценариях похоже, что корень проблемы заключается в том, что таблица маршрутизации на стороне Android неправильно маршрутизирует трафик через интерфейс USB, а сторона Android не назначает IP-адрес автоматически, в то время как сторона Linux делает это. С интерфейсом гаджета Linux / хостом Android я могу в некоторой степени понять эти проблемы, но с привязкой порта Android OTG / хостом Linux я ожидаю, что он будет правильно маршрутизироваться, поскольку система Android контролирует подключение модема.