diff options
author | Xiao Ma <xiaom@google.com> | 2019-07-24 16:27:50 +0900 |
---|---|---|
committer | Xiao Ma <xiaom@google.com> | 2019-12-11 11:26:49 +0900 |
commit | 859ceabd04daece392d42d37dbc2092cb88996f1 (patch) | |
tree | 2a2adec6473fee85f7aff6971238eb58beaff56e /src/android/net | |
parent | 762f239387423bf2250139f49972d2afa14c7428 (diff) |
Add Rapid Commit option support in DHCP Server side.
Bug:136216415
Test: atest FrameworksNetTests NetworkStackTests
Test: atest NetworkStackIntegrationTests
Test: manual tethering
Change-Id: I0f9483c72374bab271eb18549a1a41812f32f2dd
Diffstat (limited to 'src/android/net')
-rw-r--r-- | src/android/net/dhcp/DhcpAckPacket.java | 8 | ||||
-rw-r--r-- | src/android/net/dhcp/DhcpClient.java | 3 | ||||
-rw-r--r-- | src/android/net/dhcp/DhcpDiscoverPacket.java | 3 | ||||
-rw-r--r-- | src/android/net/dhcp/DhcpLeaseRepository.java | 19 | ||||
-rw-r--r-- | src/android/net/dhcp/DhcpPacket.java | 13 | ||||
-rw-r--r-- | src/android/net/dhcp/DhcpServer.java | 62 | ||||
-rw-r--r-- | src/android/net/util/NetworkStackUtils.java | 9 |
7 files changed, 86 insertions, 31 deletions
diff --git a/src/android/net/dhcp/DhcpAckPacket.java b/src/android/net/dhcp/DhcpAckPacket.java index 052af35..9e981ef 100644 --- a/src/android/net/dhcp/DhcpAckPacket.java +++ b/src/android/net/dhcp/DhcpAckPacket.java @@ -30,10 +30,12 @@ public class DhcpAckPacket extends DhcpPacket { private final Inet4Address mSrcIp; DhcpAckPacket(int transId, short secs, boolean broadcast, Inet4Address serverAddress, - Inet4Address relayIp, Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac) { + Inet4Address relayIp, Inet4Address clientIp, Inet4Address yourIp, byte[] clientMac, + boolean rapidCommit) { super(transId, secs, clientIp, yourIp, serverAddress, relayIp, clientMac, broadcast); mBroadcast = broadcast; mSrcIp = serverAddress; + mRapidCommit = rapidCommit; } public String toString() { @@ -70,8 +72,10 @@ public class DhcpAckPacket extends DhcpPacket { void finishPacket(ByteBuffer buffer) { addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_ACK); addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier); - addCommonServerTlvs(buffer); + if (mRapidCommit) { + addTlv(buffer, DHCP_RAPID_COMMIT); + } addTlvEnd(buffer); } diff --git a/src/android/net/dhcp/DhcpClient.java b/src/android/net/dhcp/DhcpClient.java index e7d53ee..dc0175e 100644 --- a/src/android/net/dhcp/DhcpClient.java +++ b/src/android/net/dhcp/DhcpClient.java @@ -1171,7 +1171,8 @@ public class DhcpClient extends StateMachine { final DhcpResults results = packet.toDhcpResults(); if (results != null) { confirmDhcpLease(packet, results); - transitionTo(mConfiguringInterfaceState); + transitionTo(isDhcpIpConflictDetectEnabled() + ? mIpAddressConflictDetectingState : mConfiguringInterfaceState); } } } diff --git a/src/android/net/dhcp/DhcpDiscoverPacket.java b/src/android/net/dhcp/DhcpDiscoverPacket.java index a749796..15c20cf 100644 --- a/src/android/net/dhcp/DhcpDiscoverPacket.java +++ b/src/android/net/dhcp/DhcpDiscoverPacket.java @@ -32,9 +32,10 @@ public class DhcpDiscoverPacket extends DhcpPacket { * Generates a DISCOVER packet with the specified parameters. */ DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac, - boolean broadcast, Inet4Address srcIp) { + boolean broadcast, Inet4Address srcIp, boolean rapidCommit) { super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast); mSrcIp = srcIp; + mRapidCommit = rapidCommit; } public String toString() { diff --git a/src/android/net/dhcp/DhcpLeaseRepository.java b/src/android/net/dhcp/DhcpLeaseRepository.java index d22193b..4e74dc8 100644 --- a/src/android/net/dhcp/DhcpLeaseRepository.java +++ b/src/android/net/dhcp/DhcpLeaseRepository.java @@ -190,6 +190,25 @@ class DhcpLeaseRepository { return newLease; } + /** + * Get a rapid committed DHCP Lease, to reply to a DHCPDISCOVER w/ Rapid Commit option. + * + * @param clientId Client identifier option if specified, or {@link #CLIENTID_UNSPEC} + * @param relayAddr Internet address of the relay (giaddr), can be {@link Inet4Address#ANY} + * @param hostname Client-provided hostname, or {@link DhcpLease#HOSTNAME_NONE} + * @throws OutOfAddressesException The server does not have any available address + * @throws InvalidSubnetException The lease was requested from an unsupported subnet + */ + @NonNull + public DhcpLease getCommittedLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr, + @NonNull Inet4Address relayAddr, @Nullable String hostname) + throws OutOfAddressesException, InvalidSubnetException { + final DhcpLease newLease = getOffer(clientId, hwAddr, relayAddr, null /* reqAddr */, + hostname); + commitLease(newLease); + return newLease; + } + private void checkValidRelayAddr(@Nullable Inet4Address relayAddr) throws InvalidSubnetException { // As per #4.3.1, addresses are assigned based on the relay address if present. This diff --git a/src/android/net/dhcp/DhcpPacket.java b/src/android/net/dhcp/DhcpPacket.java index 5ab769b..c5700b3 100644 --- a/src/android/net/dhcp/DhcpPacket.java +++ b/src/android/net/dhcp/DhcpPacket.java @@ -1179,7 +1179,7 @@ public abstract class DhcpPacket { "No DHCP message type option"); case DHCP_MESSAGE_TYPE_DISCOVER: newPacket = new DhcpDiscoverPacket(transactionId, secs, relayIp, clientMac, - broadcast, ipSrc); + broadcast, ipSrc, rapidCommit); break; case DHCP_MESSAGE_TYPE_OFFER: newPacket = new DhcpOfferPacket( @@ -1196,7 +1196,8 @@ public abstract class DhcpPacket { break; case DHCP_MESSAGE_TYPE_ACK: newPacket = new DhcpAckPacket( - transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac); + transactionId, secs, broadcast, ipSrc, relayIp, clientIp, yourIp, clientMac, + rapidCommit); break; case DHCP_MESSAGE_TYPE_NAK: newPacket = new DhcpNakPacket( @@ -1238,7 +1239,6 @@ public abstract class DhcpPacket { newPacket.mT2 = T2; newPacket.mVendorId = vendorId; newPacket.mVendorInfo = vendorInfo; - newPacket.mRapidCommit = rapidCommit; if ((optionOverload & OPTION_OVERLOAD_SNAME) == 0) { newPacket.mServerHostName = serverHostName; } else { @@ -1330,9 +1330,8 @@ public abstract class DhcpPacket { short secs, byte[] clientMac, boolean broadcast, byte[] expectedParams, boolean rapidCommit) { DhcpPacket pkt = new DhcpDiscoverPacket(transactionId, secs, INADDR_ANY /* relayIp */, - clientMac, broadcast, INADDR_ANY /* srcIp */); + clientMac, broadcast, INADDR_ANY /* srcIp */, rapidCommit); pkt.mRequestedParams = expectedParams; - pkt.mRapidCommit = rapidCommit; return pkt.buildPacket(encap, DHCP_SERVER, DHCP_CLIENT); } @@ -1372,10 +1371,10 @@ public abstract class DhcpPacket { Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers, Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered, - short mtu) { + short mtu, boolean rapidCommit) { DhcpPacket pkt = new DhcpAckPacket( transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp, - mac); + mac, rapidCommit); pkt.mGateways = gateways; pkt.mDnsServers = dnsServers; pkt.mLeaseTime = timeout; diff --git a/src/android/net/dhcp/DhcpServer.java b/src/android/net/dhcp/DhcpServer.java index 37dd972..4fc213a 100644 --- a/src/android/net/dhcp/DhcpServer.java +++ b/src/android/net/dhcp/DhcpServer.java @@ -22,6 +22,8 @@ import static android.net.dhcp.DhcpPacket.DHCP_SERVER; import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP; import static android.net.shared.Inet4AddressUtils.getBroadcastAddress; import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address; +import static android.net.util.NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION; +import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; @@ -38,6 +40,7 @@ import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingP import static java.lang.Integer.toUnsignedLong; +import android.content.Context; import android.net.INetworkStackStatusCallback; import android.net.MacAddress; import android.net.TrafficStats; @@ -92,6 +95,8 @@ public class DhcpServer extends IDhcpServer.Stub { private static final int CMD_UPDATE_PARAMS = 3; @NonNull + private final Context mContext; + @NonNull private final HandlerThread mHandlerThread; @NonNull private final String mIfName; @@ -107,6 +112,8 @@ public class DhcpServer extends IDhcpServer.Stub { @Nullable private volatile ServerHandler mHandler; + private final boolean mDhcpRapidCommitEnabled; + // Accessed only on the handler thread @Nullable private DhcpPacketListener mPacketListener; @@ -176,6 +183,14 @@ public class DhcpServer extends IDhcpServer.Stub { * @throws SecurityException The caller is not allowed to call public methods on DhcpServer. */ void checkCaller() throws SecurityException; + + /** + * Check whether or not one specific experimental feature for connectivity namespace is + * enabled. + * @param context The global context information about an app environment. + * @param name Specific experimental flag name. + */ + boolean isFeatureEnabled(@NonNull Context context, @NonNull String name); } private class DependenciesImpl implements Dependencies { @@ -214,6 +229,11 @@ public class DhcpServer extends IDhcpServer.Stub { public void checkCaller() { enforceNetworkStackCallingPermission(); } + + @Override + public boolean isFeatureEnabled(@NonNull Context context, @NonNull String name) { + return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name); + } } private static class MalformedPacketException extends Exception { @@ -222,19 +242,20 @@ public class DhcpServer extends IDhcpServer.Stub { } } - public DhcpServer(@NonNull String ifName, + public DhcpServer(@NonNull Context context, @NonNull String ifName, @NonNull DhcpServingParams params, @NonNull SharedLog log) { - this(new HandlerThread(DhcpServer.class.getSimpleName() + "." + ifName), + this(context, new HandlerThread(DhcpServer.class.getSimpleName() + "." + ifName), ifName, params, log, null); } @VisibleForTesting - DhcpServer(@NonNull HandlerThread handlerThread, @NonNull String ifName, - @NonNull DhcpServingParams params, @NonNull SharedLog log, + DhcpServer(@NonNull Context context, @NonNull HandlerThread handlerThread, + @NonNull String ifName, @NonNull DhcpServingParams params, @NonNull SharedLog log, @Nullable Dependencies deps) { if (deps == null) { deps = new DependenciesImpl(); } + mContext = context; mHandlerThread = handlerThread; mIfName = ifName; mServingParams = params; @@ -242,6 +263,7 @@ public class DhcpServer extends IDhcpServer.Stub { mDeps = deps; mClock = deps.makeClock(); mLeaseRepo = deps.makeLeaseRepository(mServingParams, mLog, mClock); + mDhcpRapidCommitEnabled = deps.isFeatureEnabled(context, DHCP_RAPID_COMMIT_VERSION); } /** @@ -388,17 +410,20 @@ public class DhcpServer extends IDhcpServer.Stub { final DhcpLease lease; final MacAddress clientMac = getMacAddr(packet); try { - lease = mLeaseRepo.getOffer(packet.getExplicitClientIdOrNull(), clientMac, - packet.mRelayIp, packet.mRequestedIp, packet.mHostName); + if (mDhcpRapidCommitEnabled && packet.mRapidCommit) { + lease = mLeaseRepo.getCommittedLease(packet.getExplicitClientIdOrNull(), clientMac, + packet.mRelayIp, packet.mHostName); + transmitAck(packet, lease, clientMac); + } else { + lease = mLeaseRepo.getOffer(packet.getExplicitClientIdOrNull(), clientMac, + packet.mRelayIp, packet.mRequestedIp, packet.mHostName); + transmitOffer(packet, lease, clientMac); + } } catch (DhcpLeaseRepository.OutOfAddressesException e) { transmitNak(packet, "Out of addresses to offer"); - return; } catch (DhcpLeaseRepository.InvalidSubnetException e) { logIgnoredPacketInvalidSubnet(e); - return; } - - transmitOffer(packet, lease, clientMac); } private void processRequest(@NonNull DhcpRequestPacket packet) throws MalformedPacketException { @@ -492,23 +517,24 @@ public class DhcpServer extends IDhcpServer.Stub { return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag); } - private boolean transmitAck(@NonNull DhcpPacket request, @NonNull DhcpLease lease, + private boolean transmitAck(@NonNull DhcpPacket packet, @NonNull DhcpLease lease, @NonNull MacAddress clientMac) { // TODO: replace DhcpPacket's build methods with real builders and use common code with // transmitOffer above - final boolean broadcastFlag = getBroadcastFlag(request, lease); + final boolean broadcastFlag = getBroadcastFlag(packet, lease); final int timeout = getLeaseTimeout(lease); - final String hostname = getHostnameIfRequested(request, lease); - final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, request.mTransId, - broadcastFlag, mServingParams.getServerInet4Addr(), request.mRelayIp, - lease.getNetAddr(), request.mClientIp, request.mClientMac, timeout, + final String hostname = getHostnameIfRequested(packet, lease); + final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, packet.mTransId, + broadcastFlag, mServingParams.getServerInet4Addr(), packet.mRelayIp, + lease.getNetAddr(), packet.mClientIp, packet.mClientMac, timeout, mServingParams.getPrefixMaskAsAddress(), mServingParams.getBroadcastAddress(), new ArrayList<>(mServingParams.defaultRouters), new ArrayList<>(mServingParams.dnsServers), mServingParams.getServerInet4Addr(), null /* domainName */, hostname, - mServingParams.metered, (short) mServingParams.linkMtu); + mServingParams.metered, (short) mServingParams.linkMtu, + packet.mRapidCommit && mDhcpRapidCommitEnabled); - return transmitOfferOrAckPacket(ackPacket, request, lease, clientMac, broadcastFlag); + return transmitOfferOrAckPacket(ackPacket, packet, lease, clientMac, broadcastFlag); } private boolean transmitNak(DhcpPacket request, String message) { diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java index 993f3cb..45ed367 100644 --- a/src/android/net/util/NetworkStackUtils.java +++ b/src/android/net/util/NetworkStackUtils.java @@ -112,13 +112,18 @@ public class NetworkStackUtils { public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; /** - * Experiment flag to enable DHCP INIT-REBOOT state, default value is false. + * @deprecated Considering boolean experiment flag is likely to cause misconfiguration + * particularly when NetworkStack module rolls back to previous version. It's + * much safer to determine whether or not to enable one specific experimental + * feature by comparing flag version with module version. */ + @Deprecated public static final String DHCP_INIT_REBOOT_ENABLED = "dhcp_init_reboot_enabled"; /** - * Experiment flag to enable DHCP Rapid Commit option, default value is false. + * @deprecated See above explanation. */ + @Deprecated public static final String DHCP_RAPID_COMMIT_ENABLED = "dhcp_rapid_commit_enabled"; /** |