RK3576 双以太网

android 14

Posted by LXG on July 16, 2025

配置内部以太网

Android 12 对比 14 在多以太网差异

Android 14 确实在框架层面更好地处理了多个以太网接口的并行工作,尤其是在 Automotive OS 的推动下,对多网卡的支持成为了核心需求。

项目 Android 12 Android 14
🌐 多以太网接口支持 ⚠️ 初步支持,仅 eth0 稳定;eth1 需定制 ✅ 原生支持多接口,eth0/eth1 并行
⚙️ 接口识别机制 仅支持 config_ethernet_iface_regex ✅ 支持 config_ethernet_interfaces 精确控制
🔌 接口注册机制 默认只注册第一个接口 ✅ 每个接口都通过 NetworkOffer 注册
📶 NetworkAgent 支持 仅 eth0 被注册为 NetworkAgent ✅ eth0 和 eth1 均注册为独立 NetworkAgent
📊 网络能力判定 固定能力集合,优先级不可控 ✅ 可配置能力(如 NOT_METERED)以调整优先级
📈 网络优先级控制 ❌ 固定优先级顺序 ✅ 可通过 persist.net.preferred.transports.order 配置
🔄 Failover 自动切换 ❌ 无法自动切换 ✅ 支持网络断线自动切换
🔐 路由稳定性与多网支持 ❌ 多接口路由易冲突 ✅ netd 添加低优先级 rule 避免路由丢失
🧠 常驻连接策略 ❌ 无机制 ✅ 支持 ethernet_always_requested 设置
🛠️ 设置可控性 仅可通过修改源码实现 ✅ 可通过 adb settings 和 SystemProperties 控制
🚗 Automotive 多域网络支持 ❌ 无现成支持 ✅ 与 Automotive 框架集成,支持域分离(如 IVI/TCU)
💡 Overlay 灵活性 配置点少,需改 framework ✅ 支持多个 config_xxx,便于产品差异化

android 14 源码

rk3576_android_14/packages/modules/Connectivity/service-t/src/com/android/server/ethernet


.
├── EthernetCallback.java
├── EthernetConfigStore.java
├── EthernetNetworkAgent.java
├── EthernetNetworkFactory.java
├── EthernetServiceImpl.java
├── EthernetService.java
└── EthernetTracker.java

补丁实现原理

  1. Kernel:eth1 接口由驱动层创建,如 USB 网卡或 MAC1 启用;
  2. EthernetTracker:系统监测到 eth1 接口上线,触发注册流程;
  3. EthernetNetworkFactory:通过 registerNetworkOffer() 注册 eth1 网络能力;
  4. ConnectivityService:接受 NetworkAgent 注册,构建 NetworkAgentInfo 实例;
  5. NetworkAgentInfo:表示 eth1 成为系统中的一个活跃网络;
  6. NetworkRanker:系统根据你配置的优先级(如 Ethernet > WiFi)决定 eth1 是否为默认;
  7. RouteController (netd):添加路由规则,防止 eth1 的网关丢失或路由冲突。

eth0 与 eth1 并存时的系统路由选择流程图


flowchart TD
    A[eth0 接口上线] --> B[EthernetTracker 注册 eth0]
    C[eth1 接口上线] --> D[EthernetTracker 注册 eth1]

    B --> E[EthernetNetworkFactory 注册 eth0 NetworkOffer]
    D --> F[EthernetNetworkFactory 注册 eth1 NetworkOffer(降权)]

    E --> G[ConnectivityService 注册 eth0 NetworkAgent]
    F --> H[ConnectivityService 注册 eth1 NetworkAgent]

    G --> I[NetworkCapabilities: eth0\nNOT_METERED, INTERNET]
    H --> J[NetworkCapabilities: eth1\nMETERED, INTERNET]

    I --> K[NetworkRanker 获取优先级]
    J --> K

    K --> L{优先级比较}
    L -- eth0 优先 --> M[eth0 设置为默认网络]
    L -- eth1 优先 --> N[eth1 设置为默认网络]

    M --> O[netd 设置默认路由 via eth0]
    N --> P[netd 设置默认路由 via eth1]

    G --> Q[netd 添加 eth0 直连路由]
    H --> R[netd 添加 eth1 直连路由]


  • eth0 一般具有更高优先级,因为它带有 NOT_METERED,系统认为它是免费/主链路;
  • eth1 被补丁刻意降级(去掉 NOT_METERED),系统会优先选择 eth0 为默认;
  • 即便如此,eth1 仍注册为 NetworkAgent,可用于 failover、或特定请求;
  • netd 会为两个接口都添加 addDirectlyConnectedRule,避免路由冲突或丢失。

EthernetNetworkFactory.java

在注册 NetworkOffer 时,如果接口名是 eth1,就降权处理, 让系统识别 eth1 是次要网络,不抢占默认路由;但又注册为可用网络


        private void registerNetworkOffer() {
            // If mNetworkOfferCallback is already set, it should be reused to update the existing
            // offer.
            if (mNetworkOfferCallback == null) {
                mNetworkOfferCallback = new EthernetNetworkOfferCallback();
            }

            //lixiaogang add start
            if(name != null && name.equals("eth1")) {
                //mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
                mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
                //mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
                Log.d(TAG, "hcq mCapabilities: " + mCapabilities);
            }
            //lixiaogang add end

            mNetworkProvider.registerNetworkOffer(getNetworkScore(),
                    new NetworkCapabilities(mCapabilities), cmd -> mHandler.post(cmd),
                    mNetworkOfferCallback);
        }

ConnectivityService.java

强制注册并激活以太网 eth1 的连接请求


    private void handleConfigureAlwaysOnNetworks() {
        handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest,
                ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */);
        //modify defaultValue to true by lixiaogang
        handleAlwaysOnNetworkRequest(mDefaultWifiRequest,
                ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, true /* defaultValue */);
        final boolean vehicleAlwaysRequested = mResources.get().getBoolean(
                R.bool.config_vehicleInternalNetworkAlwaysRequested);
        handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, vehicleAlwaysRequested);

        //lixiaogang add start
        handleAlwaysOnNetworkRequest(mDefaultEthernetRequest,
                ConnectivitySettingsManager.ETHERNET_ALWAYS_REQUESTED, true /* defaultValue */);

        handleAlwaysOnNetworkRequest(mDefaultEthernetRequest,
                ConnectivitySettingsManager.BLUETOOTH_ALWAYS_REQUESTED, true /* defaultValue */);
        //lixiaogang add end
    }

    // 意图:避免系统主动断开 eth 网络连接(尤其是 eth1)
    private void teardownUnneededNetwork(NetworkAgentInfo nai) {
        if (nai.numRequestNetworkRequests() != 0) {
            for (int i = 0; i < nai.numNetworkRequests(); i++) {
                NetworkRequest nr = nai.requestAt(i);
                // Ignore listening and track default requests.
                if (!nr.isRequest()) continue;
                loge("Dead network still had at least " + nr);
                break;
            }
        }
        // delete by lixiaogang start
        // nai.disconnect();
        // delete by lixiaogang end
    }

RouteController.cpp

注册一条低优先级 IP rule,用于查找主路由表中直连网关地址,避免多个接口存在时路由冲突。


constexpr int32_t RULE_PRIORITY_DIRECTLY_CONNECTED                = 9999;


int RouteController::Init(unsigned localNetId) {
    if (int ret = flushRules()) {
        return ret;
    }
    if (int ret = addLegacyRouteRules()) {
        return ret;
    }
    if (int ret = addLocalNetworkRules(localNetId)) {
        return ret;
    }
    //lixiaogang add start
    if (int ret = addDirectlyConnectedRule()) {
       return ret;
    }
    //lixiaogang add end
    if (int ret = addUnreachableRule()) {
        return ret;
    }
    // Don't complain if we can't add the dummy network, since not all devices support it.
    configureDummyNetwork();

    updateTableNamesFile();
    return 0;
}