Linux系統作為遠端介面(帶有g_ether驅動程式的USB小工具)

Linux系統作為遠端介面(帶有g_ether驅動程式的USB小工具)

我現在正在開發一個項目,其中我們有一個運行一些感測器/馬達控制功能的嵌入式 Linux 系統,並且我們正在創建一個 GUI 應用程式以允許用戶控制系統。將來我們可能會在一個系統上運行這兩個應用程序,但目前,我們希望能夠將其安裝為現有機器的升級,而現有的控制器板不具備運行 GUI 的能力它是經過設計的,因此它將在單獨的SBC 上運行(目前我們正在使用一個ODroid C4運行安卓9)

我們已經制定了兩個系統之間的通訊API,我一直在透過使用靜態IP 位址在兩個系統之間運行直接乙太網路連線來進行初步測試,但由於部署要求和Android 的限制,我需要找出不同的方法產品實際部署的連接方式。我們需要客戶能夠透過 WiFi 或乙太網路連接到 GUI 系統上的互聯網,因此 ODroid 的板載乙太網路連接埠不能用於此目的,除此之外,Android 核心還有一些內部行為只允許單一網路連接在任何給定時間處於活動狀態。

Android 網路優先權規則的例外是 USB 網路介面。 Linux 控制器系統和 Android 設備本身都能夠顯示為遠端主機的網路介面 - 在控制器系統上,我們有一個可用的 USB 小工具端口,我g_ether在系統映像中啟用了核心模組,並且在GUI 系統有一個USB OTG 端口,我可以在Android 系統設定中啟用USB 網路共享。

我已經能夠使用它們各自的介面在這兩個系統和我的 Windows 開發系統之間進行通信,但到目前為止我還沒有弄清楚如何讓任一解決方案與另一個解決方案進行通信。

Linux系統作為遠端介面(帶有g_ether驅動程式的USB小工具)

  • 在linux系統上載入g_ether核心模組會建立一個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 系統上的主機端口,會立即在 Android 上創建一個接口,並為Linux 上的接口usb0生成一個 IP 地址:usb0

安卓:

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
  • Android系統上調出介面並沒有分配IP位址,所以我必須手動分配一個,使用Linux系統自行分配的169.254/16空間
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

我現在有兩個問題:首先是從另一個裝置 ping 任何一個裝置都沒有回應。查看 Android 端的資料包計數,看起來好像正在接收來自 Linux 端的 ping,但沒有回應,這可能是由第二個問題引起的,即路由表似乎沒有按預期工作在Android端。鑑於我需要這個工作,同時 Android 系統上也有活動的互聯網連接,我同時連接了以太網,這就是我在查看路由時看到的內容:

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系統作為遠端介面(附OTG連接埠的USB網路共用)

這種情況似乎讓我更接近一點,因為我可以進行單向通訊。

  • 在我的 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
  • usb0Linux 端會立即建立一個介面並指派一個 IP 位址:
# 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
  • 在設定中啟用 USB 網路共享的 Android 端,會出現 usb0 接口,但開始時會關閉。啟動它不會為其提供 IP 位址,因此我手動分配了一個 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 端會自動分配 IP 位址。使用 Linux 小工具介面/Android 主機,我可以在一定程度上理解這些問題,但使用 Android OTG 連接埠共享/Linux 主機,我希望它能夠正確路由,因為 Android 系統控制共享連接。

答案1

你好@rdowell,

要解決此問題,需要在 Android 裝置上新增主路由表:

ip rule add from all lookup main pref 1

相關內容