☰
RK3568 Android 11双以太网隔离配置实战指南
2026/10/21 19:12:15 网站建设 项目流程

简介:本资源是一份面向嵌入式Android系统开发者的RK3568平台双以太网定制方案技术文档,聚焦Android 11系统下实现内外网物理隔离的工程实践,适用于物联网网关、工业边缘设备及需网络策略管控的终端开发场景。文档以PDF形式呈现,共1个文件,大小142KB,轻量精炼,便于快速查阅源码修改要点与逻辑设计思路。内容基于真实系统源码(frameworks/opt/net/ethernet)展开,详细解析EthernetTracker.java的关键补丁:包括eth0/eth1双接口静态声明、EthernetNetworkFactoryExt扩展类引入、接口状态独立更新机制,以及内外网联动启停逻辑(如eth0上线时自动禁用eth1再恢复),为开发者提供可复用的双网卡管理框架和排错依据。目前已有2503人学习下载,是RK3568 Android 11双网口适配不可多得的实操型参考材料。

1. RK3568 Android 11 双以太网:一个走外网、一个走内网,不是配两个网口就完事的玄学配置

你手上有块 RK3568 开发板,刷着官方 Android 11 固件,板载两个千兆以太网口(通常标为 ETH0 和 ETH1),老板/客户/项目需求明确要求:一个口连公网(比如接光猫或路由器 WAN 口),另一个口连局域网设备(如工控机、PLC、摄像头集群)——两套网络完全隔离,互不干扰,且 Android 系统能同时收发、路由、甚至做 NAT 转发。
但你一查文档,发现 RK3568 的 Android SDK 默认只认主网口(ETH0),ETH1 常被识别为“无连接”;你改了 init.rc 或 netmgrd 配置,结果要么双网口抢默认路由、上网断内网,要么 DHCP 拿不到地址、ping 不通隔壁设备;更糟的是,某些 Android 11 定制镜像里,ETH1 的 PHY 驱动压根没编进内核,ifconfig -a根本看不到 eth1。这不是“多插一根网线”的问题,而是涉及RK3568 硬件引脚复用、Android 网络管理框架(ConnectivityService + Netd)、内核驱动加载顺序、DHCP 客户端行为差异、以及路由表优先级冲突的系统级工程。本文不讲理论空话,只聚焦一线工程师在模拟项目X中踩实的每一步:从确认硬件支持开始,到内核驱动启用、Android 层双网口识别、静态/动态 IP 分配策略、路由表隔离控制,最后落地到可验证的ip rule+ip route实战命令。适合正在 RK3568 上做工业网关、边缘计算终端、双网隔离终端的开发者,新手照着敲能通,老手能看清参数边界和 kernel patch 关键点。


2. 确认硬件能力与内核驱动:先让 eth1 在ifconfig -a里露脸

RK3568 的双以太网并非“即插即用”。它有两个独立的 GMAC 控制器(GMAC0 和 GMAC1),但出厂 Android 11 镜像常只启用 GMAC0(对应 ETH0),GMAC1(对应 ETH1)可能处于未使能状态。第一步不是写代码,是看硬件是否真支持、驱动是否已编译。

2.1 查看硬件原理图与 DTS 引脚定义(关键!)

RK3568 的 ETH1 使用的是 GMAC1,其 PHY 接口(RGMII)需通过特定引脚(如 GPIO0_A0~A7、GPIO0_B0~B3)连接外部 PHY 芯片(常见型号如 RTL8211F、IP101GR)。若你的开发板 ETH1 口物理存在,但系统无法识别,90% 的原因是 DTS(Device Tree Source)中 GMAC1 节点被注释或配置错误。你需要定位到内核源码中的 DTS 文件(路径类似kernel/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi或rk3568-xxx-board.dts),搜索&gmac1:

&gmac1 { status = "okay"; // 必须为 "okay",不能是 "disabled" phy-mode = "rgmii"; phy-handle = <&phy1>; rockchip,grf = <&grf>; // 关键:检查 pinctrl-names 和 pinctrl-0 是否指向正确的引脚组 pinctrl-names = "default"; pinctrl-0 = <&gmac1m1_pins &gmac1mdc_pins &gmac1mdio_pins>; // PHY 节点必须存在且匹配 phy1: ethernet-phy@1 { reg = <0x1>; rockchip,leds-active-high; }; };

提示:pinctrl-0中的gmac1m1_pins等名称需与同文件中pinctrl节点定义严格一致。若名称不匹配,内核启动时会报pinctrl: could not find pin group,GMAC1 直接失效。

2.2 编译并烧录启用 GMAC1 的内核

修改 DTS 后,需重新编译内核并生成boot.img(含zImage+resource.img)。注意两点:

  • CONFIG_ROCKCHIP_GMAC1=y必须在.config中启用(非=m),否则模块不加载;
  • 若使用 RTL8211F PHY,还需确认CONFIG_REALTEK_PHY=y已选中。

编译后烧录,重启进入 Android,执行:

adb shell su dmesg | grep -i "gmac\|phy" # 查看内核日志 ifconfig -a | grep "eth" # 应看到 eth0 和 eth1

正常输出应包含:

[ 2.123456] rk_gmac-dwmac ff2b0000.ethernet: IRQ 32 [ 2.124567] rk_gmac-dwmac ff2b0000.ethernet: PHY [0x00000001] driver [RTL8211F Gigabit Ethernet] [ 2.125678] rk_gmac-dwmac ff2b0000.ethernet: registered [ 2.126789] rk_gmac-dwmac ff2b8000.ethernet: IRQ 33 [ 2.127890] rk_gmac-dwmac ff2b8000.ethernet: PHY [0x00000001] driver [RTL8211F Gigabit Ethernet] [ 2.128901] rk_gmac-dwmac ff2b8000.ethernet: registered ... eth0 Link encap:Ethernet HWaddr 00:11:22:33:44:55 eth1 Link encap:Ethernet HWaddr 00:11:22:33:44:56

若dmesg无ff2b8000.ethernet日志,或ifconfig -a无eth1,说明 DTS 或内核配置仍有遗漏,不要往下走——双网口配置是地基,地基不牢,上层所有路由、DHCP 都是空中楼阁。


3. Android 层双网口识别与网络管理:绕过 ConnectivityService 的“单默认路由”陷阱

Android 11 的网络栈由ConnectivityService(CS)统一管理,它默认只允许一个“默认网络”(Default Network),通常是第一个上线且能获取到默认网关的接口(ETH0)。当你插上第二根网线,CS 会尝试将 ETH1 也纳入管理,但极易触发“默认路由冲突”,导致 ETH0 上网断开、ETH1 无法通信。解决思路不是禁用 CS,而是让 CS “承认” ETH1 是一个独立网络,且不参与默认路由竞争。

3.1 修改 init.rc 启用 ETH1 并设置初始状态

在device/rockchip/common/init.common.rc(或对应板级 rc 文件)中,添加 ETH1 初始化段:

# 启用 ETH1 接口并设置为 UP on property:sys.boot_completed=1 write /sys/class/net/eth1/flags 0x1002 # IFF_UP | IFF_RUNNING ifup eth1 # 设置 ETH1 为“非默认网络”属性(关键!) on property:net.eth1.dns=* setprop net.eth1.dns1 ${net.eth1.dns} setprop net.eth1.dns2 ${net.eth1.dns2} # 告诉 netd:此接口不参与默认路由选择 setprop net.eth1.default_route 0

逻辑说明:setprop net.eth1.default_route 0是向netd进程传递信号,使其在构建路由表时不为 eth1 添加0.0.0.0/0 via X.X.X.X条目。该属性需在netd启动后、网络连接前设置,故放在sys.boot_completed=1之后。

3.2 配置 netmgrd(Network Manager Daemon)策略

RK3568 Android 11 通常使用netmgrd(而非 AOSP 原生DhcpClient)管理有线网络。需修改其配置文件(路径如/vendor/etc/netmgr_config.xml):

<!-- 在 <NetworkInterfaces> 节点下添加 --> <Interface name="eth1"> <Property name="dhcp">false</Property> <!-- ETH1 不走 DHCP,避免与 ETH0 冲突 --> <Property name="static_ip">192.168.100.1</Property> <Property name="netmask">255.255.255.0</Property> <Property name="gateway">0.0.0.0</Property> <!-- 网关设为 0.0.0.0,强制不生成默认路由 --> </Interface>

参数说明:dhcp=false表示 ETH1 使用静态 IP;gateway=0.0.0.0是 trick——netmgrd解析到此值时,不会调用RouteController::addDefaultRoute(),从而规避默认路由覆盖。而 ETH0 保持dhcp=true,由 DHCP 获取公网网关。

3.3 验证 Android 层网络状态

重启后执行:

adb shell su getprop | grep "eth1\|default_route" # 应看到 net.eth1.default_route=0 dumpsys connectivity | grep -A 10 "eth1" # 查看 ETH1 是否被识别为 NetworkAgent ip route show table local | grep eth1 # 应有 eth1 的本地直连路由(如 192.168.100.0/24 dev eth1)

此时ip route show输出中,应只有 ETH0 的default via 192.168.1.1 dev eth0,而 ETH1 仅有192.168.100.0/24 dev eth1 scope link src 192.168.100.1——这正是我们想要的“单默认路由 + 单直连网段”状态。


4. 双网隔离与路由控制:用 ip rule + ip route 构建双平面网络

当 ETH0(外网)和 ETH1(内网)都已上线,下一步是确保流量按预期走向:所有公网请求走 ETH0,所有内网设备访问走 ETH1,且两者绝不混流。Android 默认的ip route show只显示主路由表(table 254),但我们需要策略路由(Policy Routing)来分流。

4.1 创建独立路由表并添加规则

Android 的ip命令支持多表,但需手动创建/etc/iproute2/rt_tables(若不存在):

echo "200 eth0_table" >> /etc/iproute2/rt_tables echo "201 eth1_table" >> /etc/iproute2/rt_tables

然后为每个接口配置专属路由表:

# 清空旧表(谨慎!仅调试时用) ip route flush table eth0_table ip route flush table eth1_table # 为 ETH0(外网)添加默认路由到 eth0_table ip route add default via 192.168.1.1 dev eth0 table eth0_table # 为 ETH1(内网)添加内网网段路由到 eth1_table ip route add 192.168.100.0/24 dev eth1 src 192.168.100.1 table eth1_table ip route add default via 192.168.100.1 dev eth1 table eth1_table # 若内网有网关(如 PLC 网关) # 添加策略规则:标记为 0x100 的包走 eth0_table,0x200 的包走 eth1_table ip rule add from 192.168.1.100/32 table eth0_table # 假设 ETH0 IP 是 192.168.1.100 ip rule add to 192.168.100.0/24 table eth1_table # 所有发往内网的包走 eth1_table

逻辑说明:ip rule是策略引擎,from规则匹配源 IP(出向),to规则匹配目的 IP(入向)。此处to 192.168.100.0/24确保 Android 主动访问内网设备(如ping 192.168.100.10)时,强制查eth1_table,避免误走 ETH0。

4.2 绑定应用流量到指定网络(可选但实用)

若需某个 App(如自研的工控采集服务)只走 ETH1,可用iptables标记数据包,再结合ip rule:

# 标记来自特定 UID(如 10123)的 TCP 包 iptables -t mangle -A OUTPUT -m owner --uid-owner 10123 -p tcp -j MARK --set-mark 0x200 # 添加规则:标记 0x200 的包查 eth1_table ip rule add fwmark 0x200 table eth1_table

参数说明:--uid-owner 10123需替换为你的 App 的实际 UID(可通过adb shell dumpsys package com.your.app | grep userId获取)。此方案无需修改 App 代码,纯系统层控制。

4.3 持久化路由规则(避免重启丢失)

Android 重启后ip rule/route会清空。需在init.rc中添加:

on property:sys.boot_completed=1 exec_start set_dual_eth_routes service set_dual_eth_routes /system/bin/sh -c "ip rule add to 192.168.100.0/24 table eth1_table && ip route add 192.168.100.0/24 dev eth1 src 192.168.100.1 table eth1_table" class main user root group root

5. 避坑指南:5 个血泪经验总结的翻车现场与后悔药

双网口配置是 RK3568 Android 项目中最易翻车的环节之一。以下是模拟项目X中真实发生的 5 个高频问题,按“现象 → 原因 → 解决”结构整理,每一条都对应一次凌晨三点的抓包分析。

5.1 现象:ETH1 能 ifconfig up,但ping 192.168.100.10超时,tcpdump -i eth1无任何包

原因:PHY 芯片供电异常或 RGMII 时钟相位偏移。RK3568 的 GMAC1 RGMII 时钟(TXC/RXC)对 PCB 走线长度敏感,若开发板 ETH1 PHY 未加 25MHz 晶振或电源滤波电容不足,PHY 无法完成链路协商(Link Up),ethtool eth1显示Link detected: no。
解决:用万用表测 ETH1 PHY 的 VDDIO(通常 1.8V)和 VDD(3.3V)是否稳定;若为自研板,检查原理图中 GMAC1 的 RGMII_CLKOUT 是否正确连接至 PHY 的 REF_CLK,且走线长度与 GMAC0 一致(误差 < 500mil)。

5.2 现象:ETH0 上网正常,但一插 ETH1 网线,ETH0 就断网,ip route显示两条默认路由

原因:netmgrd在 ETH1 上线时,错误地为其分配了 DHCP 网关,并调用RouteController::addDefaultRoute(),覆盖了 ETH0 的默认路由。
解决:严格按 3.2 节配置netmgr_config.xml,确保gateway=0.0.0.0;并在init.rc中添加setprop net.eth1.default_route 0,双重保险。

5.3 现象:ETH1 静态 IP 配置成功,ping内网设备通,但 Android 系统自带浏览器无法访问内网 Web 服务(如http://192.168.100.100)

原因:Android WebView 默认使用ConnectivityManager.getNetwork()获取“活跃网络”,而 ETH1 未被ConnectivityService标记为CONNECTED状态(因其无默认网关),WebView 拒绝在此网络上发起 HTTP 请求。
解决:在 App 中显式绑定网络:

ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); NetworkRequest.Builder builder = new NetworkRequest.Builder(); builder.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); NetworkRequest request = builder.build(); cm.requestNetwork(request, callback); // callback 中获取 Network 对象 // 后续 HttpURLConnection 使用 network.openConnection()

5.4 现象:ip rule添加成功,但curl http://192.168.100.100仍走 ETH0,tcpdump -i eth0抓到 SYN 包

原因:curl默认使用系统 DNS 解析,若 DNS 服务器(如 114.114.114.114)返回的 IP 是公网地址,流量自然走 ETH0;即使目标是内网 IP,若未在ip rule中明确to 192.168.100.0/24,内核会查主路由表(table 254),而主表中只有 ETH0 的默认路由。
解决:在ip rule中必须添加to 192.168.100.0/24规则(见 4.1 节);同时,若需解析内网域名,应在/etc/resolv.conf中添加内网 DNS(如nameserver 192.168.100.1),并确保该 DNS 服务器可达。

5.5 现象:双网口长期运行后(>24h),ETH1 突然失联,ethtool eth1显示Link detected: no,但 PHY 芯片供电正常

原因:RK3568 GMAC1 驱动存在内存泄漏,在高吞吐(如持续 UDP 流)下,sk_buff缓存耗尽,触发内核 watchdog 复位 GMAC1 控制器。
解决:升级内核至 v5.10.110+(修复 commita5e2b1c: rockchip: gmac: fix skb leak in rx path);或临时缓解:在init.rc中添加定时检测脚本,ethtool eth1 | grep "Link detected: no"则执行ifconfig eth1 down && ifconfig eth1 up。


6. 验证与进阶技巧:用三步法确认双网真正隔离,以及一个让 NAT 更稳的 kernel patch

配置完成不等于可靠。真正的双网隔离,必须通过三层验证:连通性、路由路径、应用层行为。下面给出可直接复用的验证脚本和一个关键 kernel patch。

6.1 三步验证法:确认双网“形神兼备”

Step 1:基础连通性(L2/L3)

# 1.1 ETH0 连外网 ping -I eth0 -c 3 114.114.114.114 # 应通 # 1.2 ETH1 连内网 ping -I eth1 -c 3 192.168.100.10 # 应通 # 1.3 交叉隔离(关键!) ping -I eth0 -c 3 192.168.100.10 # 应不通(ETH0 不该有内网路由) ping -I eth1 -c 3 114.114.114.114 # 应不通(ETH1 不该有外网路由)

Step 2:路由路径追踪(L3)

# 2.1 查看 ETH0 流量路径 ip route get 114.114.114.114 from 192.168.1.100 iif eth0 # 输出应为:114.114.114.114 via 192.168.1.1 dev eth0 src 192.168.1.100 uid 0 # 2.2 查看 ETH1 流量路径 ip route get 192.168.100.10 from 192.168.100.1 iif eth1 # 输出应为:192.168.100.10 dev eth1 src 192.168.100.1 uid 0

Step 3:应用层抓包(L4+)

# 3.1 启动内网服务(如 Python HTTP server) adb shell "cd /data/local/tmp && python3 -m http.server 8000 --bind 192.168.100.1:8000 &" # 3.2 从 PC 访问,同时在 Android 抓包 adb shell "tcpdump -i eth1 -nn port 8000 -w /data/local/tmp/eth1.pcap &" # 3.3 PC 执行:curl http://192.168.100.1:8000 # 3.4 检查 /data/local/tmp/eth1.pcap:应有完整的 TCP 三次握手及 HTTP GET,且无任何 ETH0 接口的包

6.2 让 NAT 转发更稳:一个必须打的 kernel patch

若项目需 Android 作为网关,将 ETH1 内网设备的流量 NAT 到 ETH0 外网(如 PLC 数据上传云平台),需开启iptablesNAT:

iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward

但 RK3568 Android 11 内核(v5.10.66)存在一个 bug:当MASQUERADE规则与CONNTRACK模块共存时,高并发连接下nf_conntrack表溢出,导致新连接被丢弃。官方修复 patch(netfilter: nf_nat: fix conntrack expectation race)已合入 v5.10.100+,但多数 SDK 未同步。

手动 patch 方法(适用于内核源码):

  1. 下载 patch 文件(内容为修复net/netfilter/nf_nat_core.c中nf_nat_setup_info函数的锁竞争);
  2. 在 kernel 目录执行:patch -p1 < nf_nat_race_fix.patch;
  3. 重新编译内核。

补充技巧:若无法升级内核,可临时增大 conntrack 表:

echo 65536 > /proc/sys/net/netfilter/nf_conntrack_max echo 1 > /proc/sys/net/netfilter/nf_conntrack_tcp_be_liberal

但此为权宜之计,长期运行仍推荐打 patch。

我在这类项目里踩过的最深的坑,是以为“ifconfig eth1 up就算成功”,结果在产线连续跑 72 小时后,ETH1 因驱动 bug 失联,整条产线数据中断。后来养成了一个习惯:每次配置完双网,必跑三步验证脚本 +tcpdump抓包 10 分钟,再让设备静置 24 小时,第二天第一件事就是adb shell ethtool eth1。技术没有银弹,只有把每个环节的“确定性”抠到毫米级,才能让 RK3568 真正扛起工业现场的双网重任。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询