Tôi hiện đang làm việc trên một dự án nơi chúng tôi có một hệ thống Linux nhúng chạy một số chức năng điều khiển cảm biến/động cơ và chúng tôi đang tạo một ứng dụng GUI để cho phép người dùng điều khiển hệ thống. Trong tương lai, chúng tôi có thể chạy cả hai ứng dụng trên một hệ thống, nhưng hiện tại, chúng tôi muốn có thể cài đặt ứng dụng này như một bản nâng cấp cho các máy hiện có và các bảng điều khiển hiện tại không có khả năng chạy GUI như nó được thiết kế, vì vậy nó sẽ chạy trên một SBC riêng biệt (hiện tại chúng tôi đang tạo nguyên mẫu với một Android C4 chạy Android 9)
Chúng tôi đã tìm ra API giao tiếp giữa hai hệ thống và tôi đã thực hiện thử nghiệm ban đầu bằng cách chạy kết nối ethernet trực tiếp giữa hai hệ thống bằng địa chỉ IP tĩnh, tuy nhiên do các yêu cầu triển khai và giới hạn của Android, tôi cần tìm ra một cách khác phương thức kết nối để triển khai thực tế sản phẩm. Chúng tôi cần khách hàng có thể kết nối internet trên hệ thống GUI thông qua WiFi hoặc ethernet, do đó, cổng ethernet trên bo mạch của ODroid không thể được sử dụng cho mục đích đó và trên hết, nhân Android có một số hành vi bên trong chỉ cho phép một kết nối mạng duy nhất hoạt động tại bất kỳ thời điểm nào.
Ngoại lệ đối với quy tắc ưu tiên mạng của Android là giao diện mạng USB. Cả hệ thống bộ điều khiển Linux và bản thân thiết bị Android đều có khả năng xuất hiện dưới dạng giao diện mạng với máy chủ từ xa - trên hệ thống bộ điều khiển, chúng tôi có sẵn một cổng tiện ích USB và tôi đã bật g_ether
mô-đun hạt nhân trong hình ảnh hệ thống của chúng tôi và trên hệ thống GUI, chúng tôi có cổng USB OTG và tôi có thể bật tính năng chia sẻ kết nối qua USB trong cài đặt hệ thống Android.
Tôi đã có thể liên lạc giữa một trong hai hệ thống này và hệ thống phát triển Windows của mình bằng giao diện tương ứng của chúng, nhưng cho đến nay tôi vẫn chưa tìm ra cách để một trong hai giải pháp nói chuyện với nhau.
Hệ thống Linux dưới dạng giao diện từ xa (tiện ích USB có trình điều khiển g_ether)
- Tải mô-đun hạt nhân g_ether trên hệ thống linux sẽ tạo ra một
usb0
giao diện:
# modprobe g_ether
# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.42.128.107 netmask 255.255.255.0 phát sóng 10.42.128.255
inet6 fe80::206:cff:fe01:1027 tiền tốlen 64 phạm vi 0x20<link>
ether 00:06:0c:01:10:27 txqueuelen 1000 (Ethernet)
Gói RX 500 byte 54062 (52,7 KiB)
Lỗi RX 0 bị rớt 46 tràn 0 khung hình 0
Gói TX 0 byte 24423 (23,8 KiB)
Lỗi TX 0 bị rớt 0 tràn 0 sóng mang 0 va chạm 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 mặt nạ mạng 255.0.0.0
inet6 ::1 tiền tốlen 128 phạm vi 0x10<máy chủ>
vòng lặp txqueuelen 0 (Local Loopback)
Gói RX 0 byte 0 (0,0 B)
Lỗi RX 0 bị rớt 0 tràn 0 khung hình 0
Gói TX 0 byte 0 (0,0 B)
Lỗi TX 0 bị rớt 0 tràn 0 sóng mang 0 va chạm 0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::24b:5bfc:8a9e:b148 tiền tốlen 64 scopeid 0x20<link>
ether 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
Gói RX 0 byte 0 (0,0 B)
Lỗi RX 0 bị rớt 0 tràn 0 khung hình 0
Gói TX 1 byte 96 (96,0 B)
Lỗi TX 0 bị rớt 0 tràn 0 sóng mang 0 va chạm 0
- Kết nối cáp USB từ cổng tiện ích trên hệ thống linux với cổng máy chủ trên hệ thống Android ngay lập tức tạo ra một
usb0
giao diện trên Android và tạo địa chỉ IP cho usb0
giao diện trên Linux:
Android:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Trình điều khiển cdc_subset
TRUYỀN HÌNH ĐA NĂNG MTU:1500 Số liệu:1
Gói RX: 0 lỗi: 0 bị rớt: 0 tràn: 0 khung hình: 0
Gói TX: 0 lỗi: 0 bị rớt: 0 tràn: 0 nhà cung cấp dịch vụ: 0
va chạm: 0 txqueuelen: 1000
Byte RX:0 Byte TX:0
Linux:
#ifconfigusb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 169.254.119.94 netmask 255.255.0.0 phát sóng 169.254.255.255
inet6 fe80::24b:5bfc:8a9e:b148 tiền tốlen 64 scopeid 0x20<link>
ether 9a:8c:fa:85:ec:a1 txqueuelen 1000 (Ethernet)
Gói RX 0 byte 0 (0,0 B)
Lỗi RX 0 bị rớt 0 tràn 0 khung hình 0
Gói TX 1 byte 96 (96,0 B)
Lỗi TX 0 bị rớt 0 tràn 0 sóng mang 0 va chạm 0
- Giao diện trên hệ thống Android không gán địa chỉ IP nên tôi phải gán thủ công, sử dụng không gian 169.254/16 mà hệ thống Linux tự gán
odroidc4:/ # ifconfig usb0 lên
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Trình điều khiển cdc_subset
inet6 addr: fe80::f84c:95ff:fec0:8d18/64 Phạm vi: Liên kết
CHẠY PHÁT SÓNG TRÊN ĐA NĂNG MTU:1500 Số liệu:1
Gói RX: 117 lỗi: 4 bị rớt: 75 lần tràn: 0 khung hình: 4
Gói TX: 27 lỗi: 0 bị rớt: 0 tràn: 0 nhà cung cấp dịch vụ: 0
va chạm: 0 txqueuelen: 1000
Byte RX:5080 Byte TX:4897
odroidc4:/ # ip addr add 169.254.1.1/16 phát 169.254.255.255 dev usb0
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr fa:4c:95:c0:8d:18 Trình điều khiển cdc_subset
inet addr:169.254.1.1 Bcast:169.254.255.255 Mặt nạ:255.255.0.0
inet6 addr: fe80::f84c:95ff:fec0:8d18/64 Phạm vi: Liên kết
CHẠY PHÁT SÓNG TRÊN ĐA NĂNG MTU:1500 Số liệu:1
Gói RX: 117 lỗi: 4 bị rớt: 75 lần tràn: 0 khung hình: 4
Gói TX: 44 lỗi: 0 bị rớt: 0 tràn: 0 nhà cung cấp dịch vụ: 0
va chạm: 0 txqueuelen: 1000
Byte RX:5080 Byte TX:8528
Tôi có 2 vấn đề vào thời điểm này: Đầu tiên là việc ping một trong hai thiết bị từ thiết bị kia không có phản hồi. Nhìn vào số lượng gói ở phía Android, có vẻ như nó đang nhận được ping từ phía Linux nhưng không phản hồi, điều này có thể do sự cố thứ hai gây ra, đó là các bảng định tuyến dường như không hoạt động như mong đợi về phía Android. Cho rằng tôi cần cái này hoạt động trong khi cũng có kết nối internet đang hoạt động trên hệ thống Android, tôi đã kết nối ethernet cùng lúc và đây là những gì tôi thấy khi xem định tuyến:
odroidc4:/ # ip danh sách lộ trình
169.254.0.0/16 dev usb0 liên kết phạm vi kernel proto src 169.254.1.1
10.42.128.0/24 dev eth0 liên kết phạm vi kernel proto src 10.42.128.166
odroidc4:/ # ip nhận 169.254.119.94
169.254.119.94 qua 10.42.128.2 bảng dev eth0 eth0 src 10.42.128.166 uid 0
bộ đệm
odroidc4:/ # ip hiển thị bảng 0
mặc định qua 10.42.128.2 bảng dev eth0 eth0 proto tĩnh
...
Hệ thống Android làm giao diện từ xa (kết nối USB với cổng OTG)
Kịch bản này dường như đưa tôi đến gần hơn một chút vì tôi có thể làm cho giao tiếp một chiều hoạt động.
- Sau khi thêm các trình điều khiển cần thiết vào hình ảnh Linux của tôi, việc kết nối cáp từ cổng OTG của Android với cổng máy chủ Linux cho thấy hệ thống nhận ra thiết bị USB trong
dmesg
:
[ 235.710937] usb 1-2.3: thiết bị USB tốc độ tối đa mới số 7 sử dụng at91_ohci
[ 235.862304] rndis_host 1-2.3:1.0 usb0: đăng ký 'rndis_host' tại usb-at91-2.3, thiết bị RNDIS, 32:1d:e8:fc:dd:8
- Một
usb0
giao diện được tạo ngay lập tức và được gán một địa chỉ IP ở đầu Linux:
#ifconfigusb0
usb0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 169.254.249.80 netmask 255.255.0.0 phát sóng 169.254.255.255
inet6 fe80::e341:f9b1:b676:99b7 tiền tốlen 64 phạm vi 0x20<link>
ether 32:1d:e8:fc:dd:80 txqueuelen 1000 (Ethernet)
Gói RX 69 byte 13572 (13,2 KiB)
Lỗi RX 0 bị rớt 0 tràn 0 khung hình 0
Gói TX 73 byte 18251 (17,8 KiB)
Lỗi TX 8 bị rơi 0 tràn 0 sóng mang 0 va chạm 0
- Trên đầu Android có bật chia sẻ kết nối qua USB trong cài đặt, giao diện usb0 xuất hiện nhưng
bắt đầu đi xuống. Đưa nó lên không cung cấp cho nó một địa chỉ IP, vì vậy tôi đã gán một địa chỉ theo cách thủ công, nhưng với trường hợp đầu tiên, bảng định tuyến dường như không hoạt động như mong đợi:
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
TRUYỀN HÌNH ĐA NĂNG MTU:1500 Số liệu:1
Gói RX: 0 lỗi: 0 bị rớt: 0 tràn: 0 khung hình: 0
Gói TX: 0 lỗi: 0 bị rớt: 0 tràn: 0 nhà cung cấp dịch vụ: 0
va chạm: 0 txqueuelen: 1000
Byte RX:0 Byte TX:0
odroidc4:/ # ifconfig usb0 lên
odroidc4:/ # ifconfig usb0
usb0 Link encap:Ethernet HWaddr de:75:5c:41:2a:e6
inet6 addr: fe80::dc75:5cff:fe41:2ae6/64 Phạm vi: Liên kết
CHẠY PHÁT SÓNG TRÊN ĐA NĂNG MTU:1500 Số liệu:1
Gói RX: 10 lỗi: 0 bị rớt: 0 tràn: 0 khung hình: 0
Gói TX: 12 lỗi: 0 bị rớt: 0 tràn: 0 nhà cung cấp dịch vụ: 0
va chạm: 0 txqueuelen: 1000
Byte RX:1090 Byte TX:2751
odroidc4:/ # ip addr add 169.254.1.1/16 phát 169.254.255.255 dev usb0
tuyến đường odroidc4:/ # ip
10.42.128.0/24 dev eth0 liên kết phạm vi kernel proto src 10.42.128.166
169.254.0.0/16 dev usb0 liên kết phạm vi kernel proto src 169.254.1.1
odroidc4:/ # ip định tuyến nhận 169.254.249.80
169.254.249.80 qua 10.42.128.2 bảng dev eth0 eth0 src 10.42.128.166 uid 0
bộ đệm
- Tuy nhiên, trong trường hợp này, tôi có thể nhận được giao tiếp thành công bắt nguồn từ đầu Android bằng cách chỉ định giao diện theo cách thủ công:
odroidc4:/ # ping -c 5 -I usb0 169.254.249.80
PING 169.254.249.80 (169.254.249.80) từ 169.254.1.1 usb0: 56(84) byte dữ liệu.
64 byte từ 169.254.249.80: icmp_seq=1 ttl=64 time=1,56 ms
64 byte từ 169.254.249.80: icmp_seq=2 ttl=64 time=1,89 ms
64 byte từ 169.254.249.80: icmp_seq=3 ttl=64 time=1,71 ms
64 byte từ 169.254.249.80: icmp_seq=4 ttl=64 time=1,75 ms
64 byte từ 169.254.249.80: icmp_seq=5 ttl=64 time=1,85 ms
--- Thống kê ping 169.254.249.80 ---
Truyền 5 gói, nhận 5 gói, mất gói 0%, thời gian 4006ms
2|odroidc4:/ # ping6 -c5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 byte dữ liệu
64 byte từ fe80::dc75:5cff:fe41:2ae6: icmp_seq=1 ttl=64 time=0,202 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=1,91 ms (DUP!)
64 byte từ fe80::dc75:5cff:fe41:2ae6: icmp_seq=2 ttl=64 time=0,196 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=1,80 ms (DUP!)
64 byte từ fe80::dc75:5cff:fe41:2ae6: icmp_seq=3 ttl=64 time=0,199 mili giây
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=1,37 ms (DUP!)
64 byte từ fe80::dc75:5cff:fe41:2ae6: icmp_seq=4 ttl=64 time=0,199 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=1,85 ms (DUP!)
64 byte từ fe80::dc75:5cff:fe41:2ae6: icmp_seq=5 ttl=64 time=0,205 mili giây
--- ff02::1%thống kê ping usb0 ---
Truyền 5 gói, nhận 5, +4 trùng lặp, mất gói 0%, thời gian 4004ms
rtt tối thiểu/trung bình/tối đa/mdev = 0,196/0,883/1,914/0,776 mili giây
- Tôi vẫn không thể khiến bất kỳ lưu lượng truy cập nào bắt nguồn từ phía Linux hoạt động, có lẽ là do sự cố định tuyến ở đầu Android ngăn không cho lưu lượng trả về được định tuyến chính xác:
# ping -c 5 -Tôi usb0 169.254.1.1
PING 169.254.1.1 (169.254.1.1) từ 169.254.249.80 usb0: 56(84) byte dữ liệu.
--- Thống kê ping 169.254.1.1 ---
Truyền 5 gói, nhận 0 gói, mất gói 100%, thời gian 4295ms
# ping6 -c 5 ff02::1%usb0
PING ff02::1%usb0(ff02::1) 56 byte dữ liệu
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=1 ttl=64 time=0,522 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=2 ttl=64 time=0,302 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=3 ttl=64 time=0,376 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=4 ttl=64 time=0,383 ms
64 byte từ fe80::e341:f9b1:b676:99b7: icmp_seq=5 ttl=64 time=0,385 ms
--- ff02::1%thống kê ping usb0 ---
Truyền 5 gói, nhận 5 gói, mất gói 0%, thời gian 4009ms
rtt tối thiểu/trung bình/tối đa/mdev = 0,302/0,393/0,522/0,074 mili giây
Trong cả hai trường hợp, có vẻ như gốc rễ của sự cố là do bảng định tuyến ở đầu Android không định tuyến chính xác lưu lượng qua giao diện USB và đầu Android không tự động gán địa chỉ IP trong khi đầu Linux thực hiện. Với giao diện tiện ích Linux/máy chủ Android, tôi có thể phần nào hiểu được những vấn đề này nhưng với tính năng chia sẻ kết nối qua cổng OTG của Android/máy chủ Linux, tôi mong đợi nó định tuyến chính xác vì hệ thống Android kiểm soát kết nối chia sẻ kết nối.