[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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user