Система Linux как удаленный интерфейс (USB-гаджет с драйвером g_ether)

Система Linux как удаленный интерфейс (USB-гаджет с драйвером g_ether)

Я работаю над проектом прямо сейчас, где у нас есть встроенная система 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

Связанный контент