.png)
Estoy trabajando en un proyecto en este momento en el que tenemos un sistema Linux integrado que ejecuta alguna funcionalidad de control de sensores/motores y estamos creando una aplicación GUI para permitir al usuario controlar el sistema. En el futuro podremos ejecutar ambas aplicaciones en un solo sistema, pero por el momento, queremos poder instalar esto como una actualización de las máquinas existentes, y las placas controladoras existentes no tienen la capacidad de ejecutar la GUI como está diseñado, por lo que se ejecutará en un SBC separado (actualmente estamos creando un prototipo con unODroid C4ejecutando Android 9)
Hemos resuelto la API de comunicación entre los dos sistemas y he estado realizando pruebas iniciales ejecutando una conexión Ethernet directa entre los dos sistemas con direcciones IP estáticas; sin embargo, debido a los requisitos de implementación y las limitaciones de Android, necesito encontrar una API diferente. método de conexión para la implementación real del producto. Necesitamos que el cliente pueda conectarse a Internet en el sistema GUI a través de WiFi o Ethernet, por lo que el puerto Ethernet integrado del ODroid no se puede utilizar para ese propósito y, además, el kernel de Android tiene algún comportamiento interno. que solo permite que una única conexión de red esté activa en un momento dado.
La excepción a las reglas de priorización de red de Android son las interfaces de red USB. Tanto el sistema controlador Linux como el propio dispositivo Android tienen la capacidad de aparecer como una interfaz de red para un host remoto: en el sistema controlador tenemos un puerto de dispositivo USB disponible y habilité el g_ether
módulo del kernel en la imagen de nuestro sistema, y en el Sistema GUI, tenemos un puerto USB OTG y puedo habilitar la conexión USB en la configuración del sistema Android.
He podido establecer comunicación entre cualquiera de estos sistemas y mi sistema de desarrollo Windows utilizando sus respectivas interfaces, pero hasta ahora no he descubierto cómo hacer que ninguna de las soluciones se comunique con la otra.
Sistema Linux como interfaz remota (dispositivo USB con controlador g_ether)
- Al cargar el módulo del kernel g_ether en el sistema Linux se crea una
usb0
interfaz:
# 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
- Al conectar un cable USB desde el puerto del dispositivo en el sistema Linux a un puerto host en el sistema Android, se crea inmediatamente una
usb0
interfaz en Android y genera una dirección IP para lausb0
interfaz en Linux:
Androide:
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
Linux:
# 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
- Abrir la interfaz en el sistema Android no asigna una dirección IP, por lo que tengo que asignar una manualmente, utilizando el espacio 169.254/16 que el sistema Linux autoasigna.
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
Tengo 2 problemas en este punto: Primero, hacer ping a cualquiera de los dispositivos desde el otro no genera respuesta. Observar el recuento de paquetes en el lado de Android hace que parezca que está recibiendo los pings del lado de Linux pero no responde, lo que puede deberse al segundo problema, que es que las tablas de enrutamiento no parecen funcionar como se esperaba. en el lado de Android. Dado que necesito que esto funcione mientras también hay una conexión a Internet activa en el sistema Android, tengo Ethernet conectado al mismo tiempo, y esto es lo que veo cuando miro el enrutamiento:
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
...
Sistema Android como interfaz remota (conexión USB con puerto OTG)
Este escenario parece acercarme un poco más, ya que puedo lograr que funcione la comunicación unidireccional.
- Después de agregar los controladores necesarios en mi imagen de Linux, conectar un cable desde el puerto OTG de Android a un puerto host de Linux muestra que el sistema reconoce el dispositivo USB en
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
Se crea inmediatamente una interfaz y se le asigna una dirección IP en el extremo de 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
- En el extremo de Android con la conexión USB habilitada en la configuración, aparece la interfaz usb0 pero comienza hacia abajo. Abrirlo no le da una dirección IP, así que le asigné una manualmente, pero al igual que en el primer escenario, la tabla de enrutamiento no parece funcionar como se esperaba:
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
- Sin embargo, en este escenario puedo obtener una comunicación exitosa que se origine desde el extremo de Android especificando manualmente la interfaz:
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
- Todavía no puedo hacer que funcione el tráfico que se origina en el lado de Linux, presumiblemente debido al problema de enrutamiento en el extremo de Android que impide que el tráfico de retorno se enrute correctamente:
# 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
En ambos escenarios, parece que la raíz del problema es que la tabla de enrutamiento en el extremo de Android no enruta correctamente el tráfico a través de la interfaz USB, y el extremo de Android no asigna automáticamente una dirección IP mientras que el extremo de Linux sí lo hace. Con la interfaz del dispositivo Linux/host de Android puedo entender de alguna manera estos problemas, pero con el anclaje del puerto OTG de Android/host de Linux esperaría que se enrute correctamente ya que el sistema Android tiene el control de la conexión de anclaje.
Respuesta1
Hola @rdowell,
Para solucionar este problema, es necesario agregar la tabla de rutas principal en su dispositivo Android:
ip rule add from all lookup main pref 1