Android 多网卡机制

android 12

Posted by LXG on August 3, 2023

ifconfig


rk3588_s:/ $ ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0 
          inet6 addr: ::1/128 Scope: Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:40 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:40 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:3422 TX bytes:3422 

dummy0    Link encap:Ethernet  HWaddr 82:10:b8:a3:c2:aa
          inet6 addr: fe80::8010:b8ff:fea3:c2aa/64 Scope: Link
          UP BROADCAST RUNNING NOARP  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:5 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:0 TX bytes:350 

eth0      Link encap:Ethernet  HWaddr 4e:27:42:9f:ef:90  Driver rk_gmac-dwmac
          inet addr:192.168.0.95  Bcast:192.168.0.255  Mask:255.255.255.0 
          inet6 addr: fe80::c753:c959:5a7d:a7e7/64 Scope: Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:70 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:15 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:4200 TX bytes:1262 
          Interrupt:74 

eth1      Link encap:Ethernet  HWaddr 36:e2:71:5a:11:d3  Driver r8168
          inet addr:192.168.43.5  Bcast:192.168.255.255  Mask:255.255.0.0 
          inet6 addr: fe80::d21d:3f3a:bad4:3402/64 Scope: Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:68 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:65 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:4080 TX bytes:4962 
          Interrupt:154 Base address:0xf000 

usb0      Link encap:Ethernet  HWaddr ae:0c:29:a3:9b:6d  Driver cdc_ether
          inet addr:10.18.216.73  Bcast:10.255.255.255  Mask:255.0.0.0 
          inet6 addr: 2409:8d80:9000:34b3:ac0c:29ff:fea3:9b6d/64 Scope: Global
          inet6 addr: fe80::ac0c:29ff:fea3:9b6d/64 Scope: Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:268 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:345 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:82071 TX bytes:41386

lo 回环接口

虚拟网络接口: 并非真实存在,并不真实地从外界接收和发送数据包,而是在系统内部接收和发送数据包,因此虚拟网络接口不需要驱动程序。

用于与本地内部通信的网卡

dummy0

dummy网卡 (dummy network interface)用于在断网的环境下,假装网络可以通,仍然可以通过类似 192.168.1.1 这样的IP 访问服务。因为断网环境下只有本地环回地址127.0.0.1能被内核解析, 因此如果想要解析 192.168.1.1 这种IP,就要将其设置为 dummy类型

dummy 接口主要有两个用途:

  1. 用于主机内的程序通信
  2. 在拥有多个物理接口的网络上,可以将 service 地址设置为 loopback 接口或 dummy 接口的地址,这样 service 地址不会因为物理接口的状态而受影响。

Android 多网卡

  1. Android默认只支持一个网卡, Mobile/Ethernet/Wi-Fi不能同时存在
  2. linux是可以同时支持多网卡存在的
  3. 去掉Android Framework中只允许一个网卡存在的逻辑
  4. 可以通过修改网卡的优先级,再加上把AndroidFW中关掉低优先级的网卡的代码注释掉来实现。当前还有其他方法来实现,比如让AndroidFW不监听linux的指定种类的网卡事件,也可以避免AndroidFW关闭该种类的网卡。
  5. 为AndroidFramework没有支持的另外的网卡,配置路由规则(ip rule/ ip route)

Android 双以太网

rk3588 eth0(内网) log


// 驱动上卡
2023-08-03 14:57:37.740   268-268   <no-tag>                pid-268                              I  rk_gmac-dwmac fe1c0000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
2023-08-03 14:57:37.740   268-268   <no-tag>                pid-268                              W  [dhd] CFG80211-ERROR) wl_cfg80211_netdev_notifier_call : wdev null. Do nothing

// 加载网卡
2023-08-03 14:57:35.788   627-647   EthernetTracker         system_process                       I  interfaceLinkStateChanged, iface: eth0, up: true
2023-08-03 14:57:35.788   627-776   EthernetNe...FactoryExt system_process                       D  interfaceLinkStateChanged: iface = eth0, mIface = eth0,up:true,mLinkUp:false

// 设置静态IP
2023-08-03 14:57:36.790   627-2211  EthernetNe...FactoryExt system_process                       D  setStaticIpAddress:android.net.StaticIpConfiguration$Builder@68bbd8b
2023-08-03 14:57:36.790   627-2211  EthernetNe...FactoryExt system_process                       D  IpClient.startProvisioning


2023-08-03 14:57:36.791   431-431   netd                    pid-431                              I  interfaceSetEnableIPv6(eth0, false) <0.04ms>
2023-08-03 14:57:36.792   431-431   netd                    pid-431                              I  interfaceClearAddrs(eth0) <0.10ms>
2023-08-03 14:57:36.792   627-2212  IpClient.eth0           system_process                       E  Failed to set accept_ra to 2
2023-08-03 14:57:36.794   431-431   netd                    pid-431                              I  interfaceSetIPv6PrivacyExtensions(eth0, true) <0.04ms>
2023-08-03 14:57:36.794   431-431   netd                    pid-431                              I  setIPv6AddrGenMode(eth0, 2) <0.03ms>
2023-08-03 14:57:36.794   431-431   netd                    pid-431                              I  interfaceSetEnableIPv6(eth0, true) <0.11ms>
2023-08-03 14:57:36.795   431-431   netd                    pid-431                              I  interfaceSetCfg(InterfaceConfigurationParcel{ifName: eth0, hwAddr: , ipv4Addr: 192.168.0.95, prefixLength: 24, flags: []}) <0.09ms>
2023-08-03 14:57:36.795   627-2212  EthernetNe...FactoryExt system_process                       D  onLinkPropertiesChange
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(4, 2, eth0, retrans_time_ms, 750) <0.03ms>
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(4, 2, eth0, ucast_solicit, 5) <0.02ms>
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(6, 2, eth0, retrans_time_ms, 750) <0.03ms>
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(6, 2, eth0, ucast_solicit, 5) <0.02ms>
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(4, 2, eth0, retrans_time_ms, 750) <0.02ms>
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(4, 2, eth0, ucast_solicit, 10) <0.01ms>
2023-08-03 14:57:36.796   431-431   netd                    pid-431                              I  setProcSysNet(6, 2, eth0, retrans_time_ms, 750) <0.02ms>
2023-08-03 14:57:36.797   431-431   netd                    pid-431                              I  setProcSysNet(6, 2, eth0, ucast_solicit, 10) <0.01ms>
2023-08-03 14:57:36.798   627-2212  EthernetNe...FactoryExt system_process                       D  onProvisioningSuccess
2023-08-03 14:57:36.798   627-2212  EthernetNe...FactoryExt system_process                       D  addToLocalNetwork: iface = eth0

// 设置路由表
2023-08-03 14:57:36.799   431-431   netd                    pid-431                              I  networkAddInterface(99, eth0) <0.81ms>
2023-08-03 14:57:36.799   431-431   netd                    pid-431                              I  networkAddRoute(99, eth0, fe80::/64, ) <0.08ms>
2023-08-03 14:57:36.799   431-431   netd                    pid-431                              I  networkAddRoute(99, eth0, 192.168.0.0/24, ) <0.04ms>
2023-08-03 14:57:36.799   431-431   netd                    pid-431                              I  networkAddRoute(99, eth0, 255.255.0.0/32, ) <0.05ms>
2023-08-03 14:57:36.799   431-431   libnetd_resolv          pid-431                              E  Error adding route fe80::/64 -> (null) eth0 to table 97: File exists
2023-08-03 14:57:36.799   431-431   netd                    pid-431                              I  networkAddRoute(99, eth0, fe80::/64, ) <0.05ms>

``
**rk3588 eth1() log**

```txt

// 加载网卡
2023-08-03 16:17:14.297     0-0     [    C6] r8168          pid-0                                I  eth1: link up
2023-08-03 16:17:14.297   190-190   <no-tag>                pid-190                              W  [dhd] CFG80211-ERROR) wl_cfg80211_netdev_notifier_call : wdev null. Do nothing


2023-08-03 16:17:12.342   617-646   EthernetTracker         system_process                       I  interfaceLinkStateChanged, iface: eth1, up: true
2023-08-03 16:17:12.342   617-774   EthernetNetworkFactory  system_process                       D  updateInterfaceLinkState, iface: eth1, up: true
2023-08-03 16:17:12.342   617-774   EthernetNetworkFactory  system_process                       D  Starting Ethernet IpClient(eth1)
2023-08-03 16:17:12.343   617-774   EthernetNe...FactoryExt system_process                       D  interfaceLinkStateChanged: iface = eth1, mIface = eth0,up:true,mLinkUp:false
2023-08-03 16:17:12.344   617-2329  IpClient.eth1           system_process                       E  Failed to set accept_ra to 2


2023-08-03 16:17:12.350   617-774   ConnectivityService     system_process                       D  registerNetworkAgent NetworkAgentInfo{network{104}  handle{450082295821}  ni{Ethernet CONNECTING extra: fa:41:32:8f:77:bc} Score(70 ; KeepConnected : 0 ; Policies : IS_UNMETERED)   lp  nc{[ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_ROAMING&FOREGROUND&NOT_CONGESTED&NOT_SUSPENDED&NOT_VCN_MANAGED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps]}}
2023-08-03 16:17:12.351   617-735   ConnectivityService     system_process                       D  [104 ETHERNET] EVENT_NETWORK_INFO_CHANGED, going from CONNECTING to CONNECTING
2023-08-03 16:17:12.351   617-735   ConnectivityService     system_process                       D  [104 ETHERNET] EVENT_NETWORK_INFO_CHANGED, going from CONNECTING to CONNECTED


2023-08-03 16:17:12.352   617-735   DnsManager              system_process                       W  updatePrivateDns(104, PrivateDnsConfig{true:/[]})
2023-08-03 16:17:12.352   617-735   ConnectivityService     system_process                       D  Setting DNS servers for network 104 to [/192.168.43.1]
2023-08-03 16:17:12.352   617-735   DnsManager              system_process                       D  sendDnsConfigurationForNetwork(104, [192.168.43.1], [], 1800, 25, 8, 64, 0, 0, , [192.168.43.1])
2023-08-03 16:17:12.352   426-2331  resolv                  pid-426                              W  Validating DnsTlsServer 192.168.43.1 with mark 0xf0068
2023-08-03 16:17:12.352   617-735   ConnectivityService     system_process                       D  Adding iface eth1 to network 104


2023-08-03 16:17:12.352   426-2331  resolv                  pid-426                              W  Socket failed to connect: Network is unreachable
2023-08-03 16:17:12.353   426-2331  resolv                  pid-426                              W  TCP Handshake failed: 101
2023-08-03 16:17:12.353   426-2331  resolv                  pid-426                              W  query failed
2023-08-03 16:17:12.353   426-2331  resolv                  pid-426                              W  validateDnsTlsServer returned 0 for 192.168.43.1
2023-08-03 16:17:12.353   426-2331  resolv                  pid-426                              W  Validation failed
2023-08-03 16:17:12.354   617-735   ConnectivityService     system_process                       D  Setting DNS servers for network 104 to [/192.168.43.1]
2023-08-03 16:17:12.354   617-735   DnsManager              system_process                       D  sendDnsConfigurationForNetwork(104, [192.168.43.1], [], 1800, 25, 8, 64, 0, 0, , [192.168.43.1])
2023-08-03 16:17:12.355   426-2332  resolv                  pid-426                              W  Validating DnsTlsServer 192.168.43.1 with mark 0xf0068
2023-08-03 16:17:12.388   617-735   ConnectivityService     system_process                       D  NetReassign [no changes]
2023-08-03 16:17:14.676   617-2329  IpClient.eth1           system_process                       W  [IpReachabilityMonitor] WARN ALERT neighbor went from: null to: NeighborEvent{@284903,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]}
2023-08-03 16:17:14.676   426-2332  resolv                  pid-426                              W  SSL_connect ssl error =5, mark 0xf0068: No route to host
2023-08-03 16:17:14.676   426-2332  resolv                  pid-426                              W  TLS Handshake failed
2023-08-03 16:17:14.676   617-2329  IpReachabilityMonitor   system_process                       W  FAILURE: LOST_PROVISIONING, NeighborEvent{@284903,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]}
2023-08-03 16:17:14.676   426-2332  resolv                  pid-426                              W  query failed
2023-08-03 16:17:14.676   426-2332  resolv                  pid-426                              W  validateDnsTlsServer returned 0 for 192.168.43.1
2023-08-03 16:17:14.676   426-2332  resolv                  pid-426                              W  Validation failed
2023-08-03 16:17:16.996   617-2329  IpClient.eth1           system_process                       W  [IpReachabilityMonitor] WARN ALERT neighbor went from: NeighborEvent{@284903,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]} to: NeighborEvent{@287223,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]}
2023-08-03 16:17:16.996   617-2329  IpReachabilityMonitor   system_process                       W  FAILURE: LOST_PROVISIONING, NeighborEvent{@287223,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]}
2023-08-03 16:17:17.387   617-735   ConnectivityService     system_process                       D  handleLingerComplete for [104 ETHERNET]
2023-08-03 16:17:19.716   617-2329  IpClient.eth1           system_process                       W  [IpReachabilityMonitor] WARN ALERT neighbor went from: NeighborEvent{@287223,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]} to: NeighborEvent{@289943,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]}
2023-08-03 16:17:19.716   617-2329  IpReachabilityMonitor   system_process                       W  FAILURE: LOST_PROVISIONING, NeighborEvent{@289943,RTM_NEWNEIGH,if=9,192.168.43.1,NUD_FAILED,[null]}
2023-08-03 16:17:22.401   617-617   DnsResolver             system_process                       W  resNetworkResult:android.system.ErrnoException: resNetworkResult failed: ETIMEDOUT (Connection timed out)
2023-08-03 16:17:22.401   617-2335  NetworkMonitor/104      system_process                       D  PROBE_DNS www.google.cn 10011ms FAIL in type ADDRCONFIG android.net.DnsResolver$DnsException: android.system.ErrnoException: resNetworkResult failed: ETIMEDOUT (Connection timed out)
2023-08-03 16:17:24.894   617-2334  NetworkMonitor/104      system_process                       D  PROBE_DNS www.google.cn 12503ms FAIL in type ADDRCONFIG Timeout
2023-08-03 16:17:25.402   617-2333  NetworkMonitor/104      system_process                       D  PROBE_FALLBACK http://www.googleapis.cn/generate_204 Probe failed with exception java.net.UnknownHostException: Unable to resolve host "www.googleapis.cn": No address associated with hostname
2023-08-03 16:17:32.414   617-2335  NetworkMonitor/104      system_process                       D  PROBE_HTTP http://www.google.cn/generate_204 Probe failed with exception java.net.UnknownHostException: Unable to resolve 
2023-08-03 16:17:42.423   617-2334  NetworkMonitor/104      system_process                       D  PROBE_HTTPS https://www.google.cn/generate_204 Probe failed with exception java.net.UnknownHostException: Unable to resolve host "www.google.cn": No address associated with hostname
2023-08-03 16:17:42.423   617-2333  NetworkMonitor/104      system_process                       D  isCaptivePortal: isSuccessful()=false isPortal()=false RedirectUrl=null isPartialConnectivity()=false Time=30034ms
2023-08-03 16:17:42.424   617-735   ConnectivityService     system_process                       D  [104 ETHERNET] validation failed

dumpsys ethernet


rk3588_s:/ $ dumpsys ethernet
Current Ethernet state: 
  EthernetTracker
  Ethernet interface name filter: eth1
  Default interface: eth1
  Default interface mode: 1
  Tethered interface requests: 0
  Listeners: 0
  IP Configurations:
    eth1: IP assignment: STATIC
    Static configuration: IP address 192.168.43.5/16 Gateway 192.168.43.1  DNS servers: [ 192.168.43.1 0.0.0.0 ] Domains 
    Proxy settings: NONE
    
    eth0: IP assignment: STATIC
    Static configuration: IP address 192.168.0.95/16 Gateway 192.168.0.1  DNS servers: [ 192.168.0.1 0.0.0.0 ] Domains 
    Proxy settings: NONE
    
  
  Network Capabilities:
  
  providerId=1, ScoreFilter=Score(70 ; Policies : 0), Filter=[ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_ROAMING&NOT_CONGESTED&NOT_SUSPENDED&NOT_VCN_MANAGED], requests=12
    {NetworkRequest [ REQUEST id=25, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10047 RequestorUid: 10047 RequestorPkg: com.android.systemui] ], requested=false}
    {NetworkRequest [ REQUEST id=7, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 1000 RequestorUid: 1000 RequestorPkg: android] ], requested=false}
    {NetworkRequest [ REQUEST id=18, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 1000 RequestorUid: 1000 RequestorPkg: com.android.networkstack.inprocess] ], requested=false}
    {NetworkRequest [ REQUEST id=14, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10033 RequestorUid: 1000 RequestorPkg: android] ], requested=false}
    {NetworkRequest [ REQUEST id=16, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 1000 RequestorUid: 1000 RequestorPkg: android] ], requested=false}
    {NetworkRequest [ REQUEST id=1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_VCN_MANAGED RequestorUid: 1000 RequestorPkg: android] ], requested=false}
    {NetworkRequest [ REQUEST id=23, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10047 RequestorUid: 10047 RequestorPkg: com.android.systemui] ], requested=false}
    {NetworkRequest [ REQUEST id=29, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 1001 RequestorUid: 1001 RequestorPkg: com.android.phone] ], requested=false}
    {NetworkRequest [ REQUEST id=33, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 1000 RequestorUid: 1000 RequestorPkg: android] ], requested=true}
    {NetworkRequest [ REQUEST id=34, [ Capabilities: NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_VCN_MANAGED Uid: 1000 RequestorUid: 1000 RequestorPkg: com.wif.baseservice] ], requested=true}
    {NetworkRequest [ REQUEST id=40, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10043 RequestorUid: 1000 RequestorPkg: android] ], requested=true}
    {NetworkRequest [ REQUEST id=42, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED Uid: 10003 RequestorUid: 1000 RequestorPkg: android] ], requested=true}
  EthernetNetworkFactory
  Tracking interfaces:
    eth1:NetworkInterfaceState{ refCount: 4, iface: eth1, up: true, hwAddress: fa:41:32:8f:77:bc, networkCapabilities: [ Transports: ETHERNET Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN&NOT_ROAMING&NOT_CONGESTED&NOT_SUSPENDED&NOT_VCN_MANAGED LinkUpBandwidth>=100000Kbps LinkDnBandwidth>=100000Kbps], networkAgent: com.android.server.ethernet.EthernetNetworkFactory$NetworkInterfaceState$1@595c638, score: 70, ipClient: android.net.ip.IIpClient$Stub$Proxy@a7aa611,linkProperties: {InterfaceName: eth1 LinkAddresses: [ fe80::421b:260f:1da:f2dd/64,192.168.43.5/16 ] DnsAddresses: [ /192.168.43.1 ] Domains: null MTU: 0 TcpBufferSizes: 524288,1048576,3145728,524288,1048576,2097152 Routes: [ fe80::/64 -> :: eth1 mtu 0,192.168.0.0/16 -> 0.0.0.0 eth1 mtu 0,0.0.0.0/0 -> 192.168.43.1 eth1 mtu 0 ]}}
      IpClient logs have moved to dumpsys network_stack
Handler:
  EthernetServiceImplHandler (android.os.Handler) {be88fea} @ 971345
  EthernetServiceImpl  Looper (EthernetServiceThread, tid 127) {6dac2db}
  EthernetServiceImpl    (Total messages: 0, polling=true, quitting=false)


源码流程区别

EthernetTracker


final class EthernetTracker {

    void start() {
        mConfigStore.read();

        // Default interface is just the first one we want to track.
        mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface();
        final ArrayMap<String, IpConfiguration> configs = mConfigStore.getIpConfigurations();
        for (int i = 0; i < configs.size(); i++) {
            mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i));
        }

        try {
            mNMService.registerObserver(new InterfaceObserver());
        } catch (RemoteException e) {
            Log.e(TAG, "Could not register InterfaceObserver " + e);
        }

        mHandler.post(this::trackAvailableInterfaces);
    }

    private class InterfaceObserver extends BaseNetworkObserver {

        @Override
        public void interfaceLinkStateChanged(String iface, boolean up) {
            if (DBG) {
                Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
            }

            if(isEthernetInterfaceActive())
                mHandler.post(() -> updateInterfaceState(iface, up));
            else{
                if (iface.matches(mIfaceMatch)){
                       mHandler.post(() -> updateInterfaceState(iface, false));
                       Settings.System.putInt(mContext.getContentResolver(),Settings.System.ETHERNET_ON,0);
            }}

            mHandler.post(() -> mEthernetNetworkFactoryExt.interfaceLinkStateChanged(iface, up));
        }

        @Override
        public void interfaceAdded(String iface) {
            mHandler.post(() -> maybeTrackInterface(iface));
            mHandler.post(() -> mEthernetNetworkFactoryExt.interfaceAdded(iface));
        }

        @Override
        public void interfaceRemoved(String iface) {
            mHandler.post(() -> stopTrackingInterface(iface));
            mHandler.post(() -> mEthernetNetworkFactoryExt.interfaceRemoved(iface));
        }
    }

}

EthernetNetworkFactoryExt 管理内网


class EthernetNetworkFactoryExt {

    public void interfaceLinkStateChanged(String iface, boolean up) {
        Log.d(TAG, "interfaceLinkStateChanged: iface = " + iface + ", mIface = " + mIface+",up:"+up+",mLinkUp:"+mLinkUp);
        if (!mIface.equals(iface))
            return;
        if (mLinkUp == up)
            return;

        mLinkUp = up;
        if (up) {
            mHandler.removeMessages(EVENT_INTERFACE_LINK_STATE_CHANGED);
            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INTERFACE_LINK_STATE_CHANGED, 1, 0),
                            EVENT_INTERFACE_LINK_STATE_CHANGED_DELAY_MS);
        } else {
            mHandler.removeMessages(EVENT_INTERFACE_LINK_STATE_CHANGED);
            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INTERFACE_LINK_STATE_CHANGED, 0, 0),
                            0);            
        }
    }
    
    private class EthernetNetworkFactoryExtHandler extends Handler {
        private EthernetNetworkFactoryExt mEthernetNetworkFactoryExt;

        public EthernetNetworkFactoryExtHandler(Looper looper, EthernetNetworkFactoryExt factory) {
            super(looper);
            mEthernetNetworkFactoryExt = factory;
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case EVENT_INTERFACE_LINK_STATE_CHANGED:
                    if(msg.arg1 == 1) {
                        mEthernetNetworkFactoryExt.connect();
                    } else {
                        mEthernetNetworkFactoryExt.disconnect();
                    }
                break;
            }
        }
    }

    private void connect() {
	    Thread connectThread = new Thread(new Runnable() {
		public void run() {
		    if (mConnectState == 1) {
		        Log.d(TAG, "already connected, skip");
		        return;
		    }
		    mConnectState = 2;
		    mMode = SystemProperties.get("persist.eth.ext.mode", "0");
		    if (mMode.equals("0")) { // DHCP
		        mIpConfiguration.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
		        if (!startDhcp(mIface, mIpConfiguration)) {
		            Log.e(TAG, "startDhcp failed for " + mIface);
		            mConnectState = 0;
		            sendEthernetStateChangedBroadcast(EthernetManager.ETHER_STATE_DISCONNECTED);
		            return;
		        }
		        Log.d(TAG, "startDhcp success for " + mIface);
		        sendEthernetStateChangedBroadcast(EthernetManager.ETHER_STATE_CONNECTED);
		    } else { // Static
		        setStaticIpConfiguration();
		        if (!setStaticIpAddress(mStaticIpConfiguration)) {
		            // We've already logged an error.
		            if (DBG) Log.i(TAG, "setStaticIpAddress error,set again");
		            try {
		                Thread.sleep(200);    
		            } catch (InterruptedException e) {
		                e.printStackTrace();
		            }
		            if (!setStaticIpAddress(mStaticIpConfiguration)) {
		                mConnectState = 0;
		                sendEthernetStateChangedBroadcast(EthernetManager.ETHER_STATE_DISCONNECTED);
		                return;
		            }
		        }

		        //add dhcpserver
		        if (SystemProperties.get("persist.dhcpserver.enable", "0").equals("1")) {
		            startDhcpServer();
		        }

		        sendEthernetStateChangedBroadcast(EthernetManager.ETHER_STATE_CONNECTED);
		    }
		    mConnectState = 1;
		}
	    });
	    connectThread.start();
    }

    /* For Android 7.x */
    private boolean startDhcp(String iface, IpConfiguration ipconfig) {
        Log.d(TAG, "IpClient.startProvisioning");

        stopDhcp(iface);
        sendEthernetStateChangedBroadcast(EthernetManager.ETHER_STATE_CONNECTING);
        mIpClientCallback = new IpClientCallbacksImpl();
        IpClientUtil.makeIpClient(mContext, mIface, mIpClientCallback);
        mIpClientCallback.awaitIpClientStart();

        final ProvisioningConfiguration config;
        if (ipconfig.getIpAssignment() == IpAssignment.STATIC) {
            config = new ProvisioningConfiguration.Builder()
                .withStaticConfiguration(ipconfig.getStaticIpConfiguration())
                .build();
        } else {
                config = new ProvisioningConfiguration.Builder()
                .withProvisioningTimeoutMs(0)
                .build();
	}
        try {
            mIpClient.startProvisioning(config.toStableParcelable());
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
        return true;
    }

}

EthernetNetworkFactory管理外网

APP 指定某个网络上网

APP


        NetworkRequest request = new NetworkRequest.Builder()
                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                .build();

        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(final Network network) {    // 找到可用网络后的回调
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // requires android.permission.INTERNET
                      if (!mConnectivityManager.bindProcessToNetwork(network)) {
                        } else {
                            Log.d(TAG, "Network available");
                        }
                    }
                });
            }
        connectivityManager.requestNetwork(request, callback);

framework–ConnectivityManager


public class ConnectivityManager {


    @SystemApi
    @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
    public void requestNetwork(@NonNull NetworkRequest request,
            int timeoutMs, int legacyType, @NonNull Handler handler,
            @NonNull NetworkCallback networkCallback) {
        if (legacyType == TYPE_NONE) {
            throw new IllegalArgumentException("TYPE_NONE is meaningless legacy type");
        }
        CallbackHandler cbHandler = new CallbackHandler(handler);
        NetworkCapabilities nc = request.networkCapabilities;
        sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler);
    }

    private NetworkRequest sendRequestForNetwork(int asUid, NetworkCapabilities need,
            NetworkCallback callback, int timeoutMs, NetworkRequest.Type reqType, int legacyType,
            CallbackHandler handler) {
        printStackTrace();
        checkCallbackNotNull(callback);
        if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) {
            throw new IllegalArgumentException("null NetworkCapabilities");
        }
        final NetworkRequest request;
        final String callingPackageName = mContext.getOpPackageName();
        try {
            synchronized(sCallbacks) {
                if (callback.networkRequest != null
                        && callback.networkRequest != ALREADY_UNREGISTERED) {
                    // TODO: throw exception instead and enforce 1:1 mapping of callbacks
                    // and requests (http://b/20701525).
                    Log.e(TAG, "NetworkCallback was already registered");
                }
                Messenger messenger = new Messenger(handler);
                Binder binder = new Binder();
                final int callbackFlags = callback.mFlags;
                if (reqType == LISTEN) {
                    request = mService.listenForNetwork(
                            need, messenger, binder, callbackFlags, callingPackageName,
                            getAttributionTag());
                } else {
                    request = mService.requestNetwork(
                            asUid, need, reqType.ordinal(), messenger, timeoutMs, binder,
                            legacyType, callbackFlags, callingPackageName, getAttributionTag());
                }
                if (request != null) {
                    sCallbacks.put(request, callback);
                }
                callback.networkRequest = request;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (ServiceSpecificException e) {
            throw convertServiceException(e);
        }
        return request;
    }

    private class CallbackHandler extends Handler {

        @Override
        public void handleMessage(Message message) {
            if (message.what == EXPIRE_LEGACY_REQUEST) {
                expireRequest((NetworkCapabilities) message.obj, message.arg1);
                return;
            }

            final NetworkRequest request = getObject(message, NetworkRequest.class);
            final Network network = getObject(message, Network.class);
            final NetworkCallback callback;
            synchronized (sCallbacks) {
                callback = sCallbacks.get(request);
                if (callback == null) {
                    Log.w(TAG,
                            "callback not found for " + getCallbackName(message.what) + " message");
                    return;
                }
                if (message.what == CALLBACK_UNAVAIL) {
                    sCallbacks.remove(request);
                    callback.networkRequest = ALREADY_UNREGISTERED;
                }
            }
            if (DBG) {
                Log.d(TAG, getCallbackName(message.what) + " for network " + network);
            }

            switch (message.what) {
                case CALLBACK_PRECHECK: {
                    callback.onPreCheck(network);
                    break;
                }
                case CALLBACK_AVAILABLE: {
                    NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
                    LinkProperties lp = getObject(message, LinkProperties.class);
                    callback.onAvailable(network, cap, lp, message.arg1);                        // 回调到app里面
                    break;
                }
                case CALLBACK_LOSING: {
                    callback.onLosing(network, message.arg1);
                    break;
                }
                case CALLBACK_LOST: {
                    callback.onLost(network);
                    break;
                }
                case CALLBACK_UNAVAIL: {
                    callback.onUnavailable();
                    break;
                }
                case CALLBACK_CAP_CHANGED: {
                    NetworkCapabilities cap = getObject(message, NetworkCapabilities.class);
                    callback.onCapabilitiesChanged(network, cap);
                    break;
                }
                case CALLBACK_IP_CHANGED: {
                    LinkProperties lp = getObject(message, LinkProperties.class);
                    callback.onLinkPropertiesChanged(network, lp);
                    break;
                }
                case CALLBACK_SUSPENDED: {
                    callback.onNetworkSuspended(network);
                    break;
                }
                case CALLBACK_RESUMED: {
                    callback.onNetworkResumed(network);
                    break;
                }
                case CALLBACK_BLK_CHANGED: {
                    callback.onBlockedStatusChanged(network, message.arg1);
                }
            }
        }


    }

    public boolean bindProcessToNetwork(@Nullable Network network) {
        // Forcing callers to call through non-static function ensures ConnectivityManager
        // instantiated.
        return setProcessDefaultNetwork(network);
    }


    @Deprecated
    public static boolean setProcessDefaultNetwork(@Nullable Network network) {
        int netId = (network == null) ? NETID_UNSET : network.netId;
        boolean isSameNetId = (netId == NetworkUtils.getBoundNetworkForProcess());

        if (netId != NETID_UNSET) {
            netId = network.getNetIdForResolv();
        }

        if (!NetworkUtils.bindProcessToNetwork(netId)) {
            return false;
        }

        if (!isSameNetId) {
            // Set HTTP proxy system properties to match network.
            // TODO: Deprecate this static method and replace it with a non-static version.
            try {
                Proxy.setHttpProxyConfiguration(getInstance().getDefaultProxy());
            } catch (SecurityException e) {
                // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy.
                Log.e(TAG, "Can't set proxy properties", e);
            }
            // Must flush DNS cache as new network may have different DNS resolutions.
            InetAddress.clearDnsCache();
            // Must flush socket pool as idle sockets will be bound to previous network and may
            // cause subsequent fetches to be performed on old network.
            NetworkEventDispatcher.getInstance().dispatchNetworkConfigurationChange();
        }

        return true;
    }

}

NetworkUtils.java


    private static native boolean bindProcessToNetworkHandle(long netHandle);


    public static boolean bindProcessToNetwork(int netId) {
        return bindProcessToNetworkHandle(new Network(netId).getNetworkHandle());
    }

dumpsys netd


rk3588_s:/ $ dumpsys netd   
ppid:1 -> pid:432 -> tid:432
total running time: 0d0h32m38s213ms (1958213ms)
user: 0s160ms sys: 0s219ms
maxrss: 9728kB


  NetworkController
    Default network: 102   // netId

    Networks:
      51 DUMMY dummy0

      52 UNREACHABLE

      99 LOCAL eth1

      102 PHYSICAL usb0
        Required permission: NONE

      106 PHYSICAL eth0
        Required permission: NONE


    Interface <-> last network map:
      Ifindex: 4 NetId: 106
      Ifindex: 12 NetId: 102

    Interface addresses:
      address: 192.168.0.95/24 ifindices: [9]
      address: fe80::c1d0:6f3b:e7c8:56ce/64 ifindices: [9]
      address: fe80::c753:c959:5a7d:a7e7/64 ifindices: [4]
      address: 192.168.0.95/16 ifindices: [4]
      address: 10.200.241.183/8 ifindices: [12]
      address: fe80::ac0c:29ff:fea3:9b6d/64 ifindices: [12]

  TrafficController

    mCookieTagMap status: OK
    mUidCounterSetMap status: OK
    mAppUidStatsMap status: OK
    mStatsMapA status: OK
    mStatsMapB status: OK
    mIfaceIndexNameMap status: OK
    mIfaceStatsMap status: OK
    mConfigurationMap status: OK
    mUidOwnerMap status: OK

    Cgroup ingress program status: OK
    Cgroup egress program status: OK
    xt_bpf ingress program status: OK
    xt_bpf egress program status: OK
    xt_bpf bandwidth allowlist program status: OK
    xt_bpf bandwidth denylist program status: OK

  XfrmController
    XFRM-I support: 1

  ClatdController
    Trackers: iif[iface] nat64Prefix v6Addr -> v4Addr v4iif[v4iface] [fwmark]
    BPF ingress map: iif(iface) nat64Prefix v6Addr -> v4Addr oif(iface)
    BPF egress map: iif(iface) v4Addr -> v6Addr nat64Prefix oif(iface)

  TetherController
    Forwarding requests: 
    Interface pairs:

    Log:
      08-03 09:41:09.188 netd 1.0 starting
      08-03 09:41:09.198 Pid file removed
      08-03 09:41:09.198 SIGPIPE is blocked
      08-03 09:41:09.198 setCloseOnExec(dnsproxyd)