.png)
Я работаю над проектом прямо сейчас, где у нас есть встроенная система Linux, которая запускает некоторые функции управления датчиками/двигателями, и мы создаем приложение GUI, чтобы позволить пользователю управлять системой. В будущем мы можем запустить оба приложения на одной системе, но на данный момент мы хотим иметь возможность установить это как обновление для существующих машин, а существующие платы контроллеров не имеют возможности запускать GUI в том виде, в котором он разработан, поэтому он будет работать на отдельном SBC (в настоящее время мы создаем прототип сОдроид C4на базе Android 9)
Мы разработали API связи между двумя системами, и я провел начальное тестирование, запустив прямое соединение Ethernet между двумя системами со статическими IP-адресами, однако из-за требований к развертыванию и ограничений Android мне нужно придумать другой метод подключения для фактического развертывания продукта. Нам нужно, чтобы клиент мог подключаться к Интернету в системе GUI через WiFi или Ethernet, поэтому встроенный порт Ethernet ODroid не может использоваться для этой цели, и, вдобавок ко всему, ядро Android имеет некоторое внутреннее поведение, которое позволяет активировать только одно сетевое соединение в любой момент времени.
Исключением из правил приоритета сети Android являются сетевые интерфейсы USB. Как система контроллера Linux, так и само устройство Android имеют возможность отображаться как сетевой интерфейс для удаленного хоста — в системе контроллера у нас есть порт USB-гаджета, и я включил модуль ядра g_ether
в нашем образе системы, а в системе GUI у нас есть порт USB OTG, и я могу включить USB-модем в настройках системы Android.
Мне удалось наладить связь между любой из этих систем и моей системой разработки Windows, используя их соответствующие интерфейсы, но я пока не понял, как заставить одно решение взаимодействовать с другим.
Система Linux как удаленный интерфейс (USB-гаджет с драйвером g_ether)
- Загрузка модуля ядра g_ether в системе Linux создает
usb0
интерфейс:
# modprobe g_ether
# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.42.128.107 netmask 255.255.255.0 broadcast 10.42.128.255
inet6 fe80::206:cff:fe01:1027 prefixlen 64 scopeid 0x20<link>
ether 00:06:0c:01:10:27 txqueuelen 1000 (Ethernet)
RX packets 500 bytes 54062 (52.7 KiB)
RX errors 0 dropped 46 overruns 0 frame 0
TX packets 0 bytes 24423 (23.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::24b:5bfc:8a9e:b148 prefixlen 64 scopeid 0x20<link>
ether 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 96 (96.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- Подключение USB-кабеля от порта гаджета в системе Linux к порту хоста в системе Android немедленно создает
usb0
интерфейс в Android и генерирует IP-адрес дляusb0
интерфейса в Linux:
Андроид:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Driver cdc_subset
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
Линукс:
# ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 169.254.119.94 netmask 255.255.0.0 broadcast 169.254.255.255
inet6 fe80::24b:5bfc:8a9e:b148 prefixlen 64 scopeid 0x20<link>
ether 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 96 (96.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 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 Driver cdc_subset
inet6 addr: fe80::f84c:95ff:fec0:8d18/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:117 errors:4 dropped:75 overruns:0 frame:4
TX packets:27 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5080 TX bytes:4897
odroidc4:/ # ip addr add 169.254.1.1/16 broadcast 169.254.255.255 dev usb0
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Driver cdc_subset
inet addr:169.254.1.1 Bcast:169.254.255.255 Mask:255.255.0.0
inet6 addr: fe80::f84c:95ff:fec0:8d18/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:117 errors:4 dropped:75 overruns:0 frame:4
TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:5080 TX bytes:8528
На данный момент у меня 2 проблемы: во-первых, пингование одного из устройств с другого не приводит к ответу. Если посмотреть на количество пакетов на стороне Android, то создается впечатление, что оно получает пинги со стороны Linux, но не отвечает, что может быть вызвано второй проблемой, которая заключается в том, что таблицы маршрутизации на стороне Android работают не так, как ожидалось. Учитывая, что мне нужно, чтобы это работало, пока на системе Android также есть активное подключение к Интернету, я одновременно подключил Ethernet, и вот что я вижу при просмотре маршрутизации:
odroidc4:/ # ip route list
169.254.0.0/16 dev usb0 proto kernel scope link src 169.254.1.1
10.42.128.0/24 dev eth0 proto kernel scope link src 10.42.128.166
odroidc4:/ # ip route get 169.254.119.94
169.254.119.94 via 10.42.128.2 dev eth0 table eth0 src 10.42.128.166 uid 0
cache
odroidc4:/ # ip route show table 0
default via 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: new full-speed USB device number 7 using at91_ohci
[ 235.862304] rndis_host 1-2.3:1.0 usb0: register 'rndis_host' at usb-at91-2.3, RNDIS device, 32:1d:e8:fc:dd:8
- Интерфейс
usb0
немедленно создается и ему назначается IP-адрес на стороне Linux:
# ifconfig usb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 169.254.249.80 netmask 255.255.0.0 broadcast 169.254.255.255
inet6 fe80::e341:f9b1:b676:99b7 prefixlen 64 scopeid 0x20<link>
ether 32:1d:e8:fc:dd:80 txqueuelen 1000 (Ethernet)
RX packets 69 bytes 13572 (13.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 73 bytes 18251 (17.8 KiB)
TX errors 8 dropped 0 overruns 0 carrier 0 collisions 0
- На стороне Android с включенным в настройках USB-модемом интерфейс usb0 появляется, но запускается вниз. При его включении ему не дается IP-адрес, поэтому я назначил его вручную, но, как и в первом сценарии, таблица маршрутизации, похоже, не функционирует так, как ожидалось:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 TX bytes:0
odroidc4:/ # ifconfig usb0 up
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
inet6 addr: fe80::dc75:5cff:fe41:2ae6/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1090 TX bytes:2751
odroidc4:/ # ip addr add 169.254.1.1/16 broadcast 169.254.255.255 dev usb0
odroidc4:/ # ip route
10.42.128.0/24 dev eth0 proto kernel scope link src 10.42.128.166
169.254.0.0/16 dev usb0 proto kernel scope link src 169.254.1.1
odroidc4:/ # ip route get 169.254.249.80
169.254.249.80 via 10.42.128.2 dev eth0 table eth0 src 10.42.128.166 uid 0
cache
- Однако в этом сценарии я могу добиться успешного взаимодействия со стороны Android, вручную указав интерфейс:
odroidc4:/ # ping -c 5 -I usb0 169.254.249.80
PING 169.254.249.80 (169.254.249.80) from 169.254.1.1 usb0: 56(84) bytes of data.
64 bytes from 169.254.249.80: icmp_seq=1 ttl=64 time=1.56 ms
64 bytes from 169.254.249.80: icmp_seq=2 ttl=64 time=1.89 ms
64 bytes from 169.254.249.80: icmp_seq=3 ttl=64 time=1.71 ms
64 bytes from 169.254.249.80: icmp_seq=4 ttl=64 time=1.75 ms
64 bytes from 169.254.249.80: icmp_seq=5 ttl=64 time=1.85 ms
--- 169.254.249.80 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
2|odroidc4:/ # ping6 -c5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 data bytes
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=1 ttl=64 time=0.202 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=1.91 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=2 ttl=64 time=0.196 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=1.80 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=3 ttl=64 time=0.199 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=1.37 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=4 ttl=64 time=0.199 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=1.85 ms (DUP!)
64 bytes from fe80::dc75:5cff:fe41:2ae6: icmp_seq=5 ttl=64 time=0.205 ms
--- ff02::1%usb0 ping statistics ---
5 packets transmitted, 5 received, +4 duplicates, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 0.196/0.883/1.914/0.776 ms
- Я по-прежнему не могу заставить работать трафик, исходящий со стороны Linux, предположительно из-за проблемы маршрутизации на стороне Android, которая не позволяет правильно направлять обратный трафик:
# ping -c 5 -I usb0 169.254.1.1
PING 169.254.1.1 (169.254.1.1) from 169.254.249.80 usb0: 56(84) bytes of data.
--- 169.254.1.1 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4295ms
# ping6 -c 5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 data bytes
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=0.522 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=0.302 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=0.376 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=0.383 ms
64 bytes from fe80::e341:f9b1:b676:99b7: icmp_seq=5 ttl=64 time=0.385 ms
--- ff02::1%usb0 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4009ms
rtt min/avg/max/mdev = 0.302/0.393/0.522/0.074 ms
В обоих сценариях, похоже, корень проблемы в таблице маршрутизации на стороне Android, которая неправильно маршрутизирует трафик через интерфейс USB, и сторона Android не назначает IP-адрес автоматически, в то время как сторона Linux это делает. С интерфейсом гаджета Linux/хостом Android я могу в некоторой степени понять эти проблемы, но с привязкой порта OTG Android/хостом Linux я бы ожидал, что маршрутизация будет правильной, поскольку система Android контролирует подключение привязки.
решение1
Привет @rdowell,
Чтобы устранить эту проблему, необходимо добавить основную таблицу маршрутизации на ваше Android-устройство:
ip rule add from all lookup main pref 1