[Tether09] Use INetd to call netd directly

- Using INetd to communicate with netd directly instead of using
NetworkManagementService which is a wrapper of INetd and don't have plan
to be updatable.
- Also replace InterfaceConfiguration by InterfaceController.
- Remove redundant interface flags. Only set interface up/down flag to
netd because netd only use these two flags for INetd#interfaceSetCfg.
- Note that tethering still use NetworkManagementService
to register tethering stats provider and it would also be replaced with
other way in follow up change.

Bug: 136040414
Test: -build, flash, boot
      -atest TetheringTests

Change-Id: I4ab0ad387d4bd1773ff94d3b380c1720df07f8d5
Merged-In: I4ab0ad387d4bd1773ff94d3b380c1720df07f8d5
This commit is contained in:
markchien
2020-01-07 14:43:17 +08:00
committed by Mark Chien
parent e13d884aa3
commit 12c5bb8103
5 changed files with 341 additions and 328 deletions

View File

@@ -28,7 +28,6 @@ import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetworkStackStatusCallback;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -38,11 +37,11 @@ import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.DhcpServingParamsParcelExt;
import android.net.dhcp.IDhcpServer;
import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.shared.NetdUtils;
import android.net.shared.RouteUtils;
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
import android.net.util.NetdService;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -144,10 +143,6 @@ public class IpServer extends StateMachine {
return InterfaceParams.getByName(ifName);
}
public INetd getNetdService() {
return NetdService.getInstance();
}
/** Create a DhcpServer instance to be used by IpServer. */
public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
DhcpServerCallbacks cb);
@@ -180,7 +175,6 @@ public class IpServer extends StateMachine {
private final State mUnavailableState;
private final SharedLog mLog;
private final INetworkManagementService mNMService;
private final INetd mNetd;
private final INetworkStatsService mStatsService;
private final Callback mCallback;
@@ -210,15 +204,15 @@ public class IpServer extends StateMachine {
private int mDhcpServerStartIndex = 0;
private IDhcpServer mDhcpServer;
private RaParams mLastRaParams;
private LinkAddress mIpv4Address;
public IpServer(
String ifaceName, Looper looper, int interfaceType, SharedLog log,
INetworkManagementService nMService, INetworkStatsService statsService,
Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
INetd netd, INetworkStatsService statsService, Callback callback,
boolean usingLegacyDhcp, Dependencies deps) {
super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName);
mNMService = nMService;
mNetd = deps.getNetdService();
mNetd = netd;
mStatsService = statsService;
mCallback = callback;
mInterfaceCtrl = new InterfaceController(ifaceName, mNetd, mLog);
@@ -347,7 +341,7 @@ public class IpServer extends StateMachine {
}
});
} catch (RemoteException e) {
e.rethrowFromSystemServer();
throw new IllegalStateException(e);
}
});
}
@@ -395,7 +389,8 @@ public class IpServer extends StateMachine {
});
mDhcpServer = null;
} catch (RemoteException e) {
e.rethrowFromSystemServer();
mLog.e("Error stopping DHCP", e);
// Not much more we can do here
}
}
}
@@ -414,85 +409,69 @@ public class IpServer extends StateMachine {
// NOTE: All of configureIPv4() will be refactored out of existence
// into calls to InterfaceController, shared with startIPv4().
mInterfaceCtrl.clearIPv4Address();
mIpv4Address = null;
}
// TODO: Refactor this in terms of calls to InterfaceController.
private boolean configureIPv4(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
// TODO: Replace this hard-coded information with dynamically selected
// config passed down to us by a higher layer IP-coordinating element.
String ipAsString = null;
final Inet4Address srvAddr;
int prefixLen = 0;
if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
ipAsString = USB_NEAR_IFACE_ADDR;
prefixLen = USB_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
ipAsString = getRandomWifiIPv4Address();
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
ipAsString = WIFI_P2P_IFACE_ADDR;
prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
} else {
// BT configures the interface elsewhere: only start DHCP.
final Inet4Address srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
try {
if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
prefixLen = USB_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
srvAddr = (Inet4Address) parseNumericAddress(getRandomWifiIPv4Address());
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR);
prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
} else {
// BT configures the interface elsewhere: only start DHCP.
// TODO: make all tethering types behave the same way, and delete the bluetooth
// code that calls into NetworkManagementService directly.
srvAddr = (Inet4Address) parseNumericAddress(BLUETOOTH_IFACE_ADDR);
mIpv4Address = new LinkAddress(srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
return configureDhcp(enabled, srvAddr, BLUETOOTH_DHCP_PREFIX_LENGTH);
}
mIpv4Address = new LinkAddress(srvAddr, prefixLen);
} catch (IllegalArgumentException e) {
mLog.e("Error selecting ipv4 address", e);
if (!enabled) stopDhcp();
return false;
}
final LinkAddress linkAddr;
try {
final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName);
if (ifcg == null) {
mLog.e("Received null interface config");
return false;
}
final Boolean setIfaceUp;
if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
// The WiFi stack has ownership of the interface up/down state.
// It is unclear whether the Bluetooth or USB stacks will manage their own
// state.
setIfaceUp = null;
} else {
setIfaceUp = enabled;
}
if (!mInterfaceCtrl.setInterfaceConfiguration(mIpv4Address, setIfaceUp)) {
mLog.e("Error configuring interface");
if (!enabled) stopDhcp();
return false;
}
InetAddress addr = parseNumericAddress(ipAsString);
linkAddr = new LinkAddress(addr, prefixLen);
ifcg.setLinkAddress(linkAddr);
if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
// The WiFi stack has ownership of the interface up/down state.
// It is unclear whether the Bluetooth or USB stacks will manage their own
// state.
ifcg.ignoreInterfaceUpDownStatus();
} else {
if (enabled) {
ifcg.setInterfaceUp();
} else {
ifcg.setInterfaceDown();
}
}
ifcg.clearFlag("running");
// TODO: this may throw if the interface is already gone. Do proper handling and
// simplify the DHCP server start/stop.
mNMService.setInterfaceConfig(mIfaceName, ifcg);
if (!configureDhcp(enabled, (Inet4Address) addr, prefixLen)) {
return false;
}
} catch (Exception e) {
mLog.e("Error configuring interface " + e);
if (!enabled) {
try {
// Calling stopDhcp several times is fine
stopDhcp();
} catch (Exception dhcpError) {
mLog.e("Error stopping DHCP", dhcpError);
}
}
if (!configureDhcp(enabled, srvAddr, prefixLen)) {
return false;
}
// Directly-connected route.
final IpPrefix ipv4Prefix = new IpPrefix(linkAddr.getAddress(),
linkAddr.getPrefixLength());
final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
mIpv4Address.getPrefixLength());
final RouteInfo route = new RouteInfo(ipv4Prefix, null, null, RTN_UNICAST);
if (enabled) {
mLinkProperties.addLinkAddress(linkAddr);
mLinkProperties.addLinkAddress(mIpv4Address);
mLinkProperties.addRoute(route);
} else {
mLinkProperties.removeLinkAddress(linkAddr);
mLinkProperties.removeLinkAddress(mIpv4Address);
mLinkProperties.removeRoute(route);
}
return true;
@@ -584,14 +563,12 @@ public class IpServer extends StateMachine {
if (!deprecatedPrefixes.isEmpty()) {
final ArrayList<RouteInfo> toBeRemoved =
getLocalRoutesFor(mIfaceName, deprecatedPrefixes);
try {
final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved);
if (removalFailures > 0) {
mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
removalFailures));
}
} catch (RemoteException e) {
mLog.e("Failed to remove IPv6 routes from local table: " + e);
// Remove routes from local network.
final int removalFailures = RouteUtils.removeRoutesFromLocalNetwork(
mNetd, toBeRemoved);
if (removalFailures > 0) {
mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
removalFailures));
}
for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
@@ -608,13 +585,18 @@ public class IpServer extends StateMachine {
final ArrayList<RouteInfo> toBeAdded =
getLocalRoutesFor(mIfaceName, addedPrefixes);
try {
// It's safe to call addInterfaceToLocalNetwork() even if
// the interface is already in the local_network. Note also
// that adding routes that already exist does not cause an
// error (EEXIST is silently ignored).
mNMService.addInterfaceToLocalNetwork(mIfaceName, toBeAdded);
} catch (Exception e) {
mLog.e("Failed to add IPv6 routes to local table: " + e);
// It's safe to call networkAddInterface() even if
// the interface is already in the local_network.
mNetd.networkAddInterface(INetd.LOCAL_NET_ID, mIfaceName);
try {
// Add routes from local network. Note that adding routes that
// already exist does not cause an error (EEXIST is silently ignored).
RouteUtils.addRoutesToLocalNetwork(mNetd, mIfaceName, toBeAdded);
} catch (IllegalStateException e) {
mLog.e("Failed to add IPv6 routes to local table: " + e);
}
} catch (ServiceSpecificException | RemoteException e) {
mLog.e("Failed to add " + mIfaceName + " to local table: ", e);
}
for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
@@ -762,8 +744,10 @@ public class IpServer extends StateMachine {
}
try {
mNMService.tetherInterface(mIfaceName);
} catch (Exception e) {
final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
mIpv4Address.getPrefixLength());
NetdUtils.tetherInterface(mNetd, mIfaceName, ipv4Prefix);
} catch (RemoteException | ServiceSpecificException e) {
mLog.e("Error Tethering: " + e);
mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
return;
@@ -784,8 +768,8 @@ public class IpServer extends StateMachine {
stopIPv6();
try {
mNMService.untetherInterface(mIfaceName);
} catch (Exception e) {
NetdUtils.untetherInterface(mNetd, mIfaceName);
} catch (RemoteException | ServiceSpecificException e) {
mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
mLog.e("Failed to untether interface: " + e);
}
@@ -901,17 +885,17 @@ public class IpServer extends StateMachine {
// About to tear down NAT; gather remaining statistics.
mStatsService.forceUpdate();
} catch (Exception e) {
if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
mLog.e("Exception in forceUpdate: " + e.toString());
}
try {
mNMService.stopInterfaceForwarding(mIfaceName, upstreamIface);
} catch (Exception e) {
if (VDBG) Log.e(TAG, "Exception in removeInterfaceForward: " + e.toString());
mNetd.ipfwdRemoveInterfaceForward(mIfaceName, upstreamIface);
} catch (RemoteException | ServiceSpecificException e) {
mLog.e("Exception in ipfwdRemoveInterfaceForward: " + e.toString());
}
try {
mNMService.disableNat(mIfaceName, upstreamIface);
} catch (Exception e) {
if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
mNetd.tetherRemoveForward(mIfaceName, upstreamIface);
} catch (RemoteException | ServiceSpecificException e) {
mLog.e("Exception in disableNat: " + e.toString());
}
}
@@ -947,10 +931,10 @@ public class IpServer extends StateMachine {
for (String ifname : added) {
try {
mNMService.enableNat(mIfaceName, ifname);
mNMService.startInterfaceForwarding(mIfaceName, ifname);
} catch (Exception e) {
mLog.e("Exception enabling NAT: " + e);
mNetd.tetherAddForward(mIfaceName, ifname);
mNetd.ipfwdAddInterfaceForward(mIfaceName, ifname);
} catch (RemoteException | ServiceSpecificException e) {
mLog.e("Exception enabling NAT: " + e.toString());
cleanupUpstream();
mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
transitionTo(mInitialState);