diff options
-rw-r--r-- | src/android/net/ip/IpClient.java | 39 | ||||
-rw-r--r-- | src/com/android/server/util/NetworkStackConstants.java | 2 | ||||
-rw-r--r-- | tests/integration/Android.bp | 1 | ||||
-rw-r--r-- | tests/integration/src/android/net/ip/IpClientIntegrationTest.java | 70 | ||||
-rw-r--r-- | tests/unit/src/android/net/ip/IpClientTest.java | 2 |
5 files changed, 93 insertions, 21 deletions
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java index 799184e..bff30b6 100644 --- a/src/android/net/ip/IpClient.java +++ b/src/android/net/ip/IpClient.java @@ -19,6 +19,7 @@ package android.net.ip; import static android.net.RouteInfo.RTN_UNICAST; import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable; +import static com.android.server.util.NetworkStackConstants.ETHER_MTU; import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission; import android.annotation.NonNull; @@ -48,6 +49,7 @@ import android.os.ConditionVariable; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.os.SystemClock; import android.text.TextUtils; import android.util.LocalLog; @@ -69,6 +71,8 @@ import com.android.server.NetworkStackService.NetworkStackServiceManager; import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -380,6 +384,8 @@ public class IpClient extends StateMachine { private final ConditionVariable mApfDataSnapshotComplete = new ConditionVariable(); public static class Dependencies { + private static final String TAG = "IpClient.Dependencies"; + /** * Get interface parameters for the specified interface. */ @@ -388,6 +394,18 @@ public class IpClient extends StateMachine { } /** + * Get the current MTU for the specified interface. + */ + public int getInterfaceMtu(String ifname) { + try { + return NetworkInterface.getByName(ifname).getMTU(); + } catch (SocketException e) { + Log.e(TAG, "unexpected failure to get the interface MTU"); + return ETHER_MTU; + } + } + + /** * Get a INetd connector. */ public INetd getNetd(Context context) { @@ -850,10 +868,14 @@ public class IpClient extends StateMachine { return shouldLog; } - private void logError(String fmt, Object... args) { + private void logError(String fmt, Throwable e, Object... args) { final String msg = "ERROR " + String.format(fmt, args); - Log.e(mTag, msg); - mLog.log(msg); + Log.e(mTag, msg, e); + mLog.e(msg, e); + } + + private void logError(String fmt, Object... args) { + logError(fmt, null, args); } // This needs to be called with care to ensure that our LinkProperties @@ -1351,6 +1373,17 @@ public class IpClient extends StateMachine { // There's no DHCPv4 for which to wait; proceed to stopped. deferMessage(obtainMessage(CMD_JUMP_STOPPING_TO_STOPPED)); } + + // Restore the interface MTU to initial value if it has changed. + final int mtu = mDependencies.getInterfaceMtu(mInterfaceName); + try { + if (mtu != mInterfaceParams.defaultMtu) { + mNetd.interfaceSetMtu(mInterfaceName, mInterfaceParams.defaultMtu); + } + } catch (RemoteException | ServiceSpecificException e) { + logError("Couldn't reset MTU from " + + mtu + " to " + mInterfaceParams.defaultMtu + ": " + e); + } } @Override diff --git a/src/com/android/server/util/NetworkStackConstants.java b/src/com/android/server/util/NetworkStackConstants.java index 804765e..3174a9b 100644 --- a/src/com/android/server/util/NetworkStackConstants.java +++ b/src/com/android/server/util/NetworkStackConstants.java @@ -54,6 +54,7 @@ public final class NetworkStackConstants { public static final int ETHER_TYPE_IPV4 = 0x0800; public static final int ETHER_TYPE_IPV6 = 0x86dd; public static final int ETHER_HEADER_LEN = 14; + public static final int ETHER_MTU = 1500; /** * ARP constants. @@ -97,6 +98,7 @@ public final class NetworkStackConstants { public static final int IPV6_PROTOCOL_OFFSET = 6; public static final int IPV6_SRC_ADDR_OFFSET = 8; public static final int IPV6_DST_ADDR_OFFSET = 24; + public static final int IPV6_MIN_MTU = 1280; /** * ICMPv6 constants. diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp index ec8257f..ec16467 100644 --- a/tests/integration/Android.bp +++ b/tests/integration/Android.bp @@ -23,6 +23,7 @@ android_test { "androidx.annotation_annotation", "androidx.test.rules", "mockito-target-extended-minus-junit4", + "net-tests-utils", "NetworkStackBase", "testables", ], diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java index 16e92ef..48fd7da 100644 --- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java +++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java @@ -77,6 +77,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; +import com.android.testutils.HandlerUtilsKt; import org.junit.After; import org.junit.Before; @@ -158,7 +159,8 @@ public class IpClientIntegrationTest { private static final Inet4Address BROADCAST_ADDR = getBroadcastAddress( SERVER_ADDR, PREFIX_LENGTH); private static final String HOSTNAME = "testhostname"; - private static final short MTU = 1500; + private static final int TEST_DEFAULT_MTU = 1500; + private static final int TEST_MIN_MTU = 1280; private static class TapPacketReader extends PacketReader { private final ParcelFileDescriptor mTapFd; @@ -203,6 +205,7 @@ public class IpClientIntegrationTest { private class Dependencies extends IpClient.Dependencies { private boolean mIsDhcpLeaseCacheEnabled; private boolean mIsDhcpRapidCommitEnabled; + private int mMtu = TEST_DEFAULT_MTU; public void setDhcpLeaseCacheEnabled(final boolean enable) { mIsDhcpLeaseCacheEnabled = enable; @@ -212,6 +215,10 @@ public class IpClientIntegrationTest { mIsDhcpRapidCommitEnabled = enable; } + public void setMtu(final int mtu) { + mMtu = mtu; + } + @Override public INetd getNetd(Context context) { return mNetd; @@ -242,6 +249,11 @@ public class IpClientIntegrationTest { } }; } + + @Override + public int getInterfaceMtu(String ifName) { + return mMtu; + } } @Before @@ -345,7 +357,7 @@ public class IpClientIntegrationTest { } private static ByteBuffer buildDhcpOfferPacket(final DhcpPacket packet, - final Integer leaseTimeSec) { + final Integer leaseTimeSec, final short mtu) { return DhcpPacket.buildOfferPacket(DhcpPacket.ENCAP_L2, packet.getTransactionId(), false /* broadcast */, SERVER_ADDR, INADDR_ANY /* relayIp */, CLIENT_ADDR /* yourIp */, packet.getClientMac(), leaseTimeSec, @@ -353,11 +365,11 @@ public class IpClientIntegrationTest { Collections.singletonList(SERVER_ADDR) /* gateways */, Collections.singletonList(SERVER_ADDR) /* dnsServers */, SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, HOSTNAME, - false /* metered */, MTU); + false /* metered */, mtu); } private static ByteBuffer buildDhcpAckPacket(final DhcpPacket packet, - final Integer leaseTimeSec) { + final Integer leaseTimeSec, final short mtu) { return DhcpPacket.buildAckPacket(DhcpPacket.ENCAP_L2, packet.getTransactionId(), false /* broadcast */, SERVER_ADDR, INADDR_ANY /* relayIp */, CLIENT_ADDR /* yourIp */, CLIENT_ADDR /* requestIp */, packet.getClientMac(), @@ -365,7 +377,7 @@ public class IpClientIntegrationTest { Collections.singletonList(SERVER_ADDR) /* gateways */, Collections.singletonList(SERVER_ADDR) /* dnsServers */, SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, HOSTNAME, - false /* metered */, MTU); + false /* metered */, mtu); } private static ByteBuffer buildDhcpNakPacket(final DhcpPacket packet) { @@ -397,7 +409,7 @@ public class IpClientIntegrationTest { } private void assertIpMemoryStoreNetworkAttributes(final Integer leaseTimeSec, - final long startTime) { + final long startTime, final int mtu) { final ArgumentCaptor<NetworkAttributes> networkAttributes = ArgumentCaptor.forClass(NetworkAttributes.class); @@ -416,7 +428,7 @@ public class IpClientIntegrationTest { assertTrue(lowerBound < expiry); } assertEquals(Collections.singletonList(SERVER_ADDR), naValueCaptured.dnsAddresses); - assertEquals(new Integer((int) MTU), naValueCaptured.mtu); + assertEquals(new Integer(mtu), naValueCaptured.mtu); } private void assertIpMemoryNeverStoreNetworkAttributes() { @@ -433,13 +445,16 @@ public class IpClientIntegrationTest { while ((packet = getNextDhcpPacket()) != null) { if (packet instanceof DhcpDiscoverPacket) { if (isDhcpRapidCommitEnabled) { - sendResponse(buildDhcpAckPacket(packet, leaseTimeSec)); + sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, + (short) mDependencies.getInterfaceMtu(mIfaceName))); } else { - sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec)); + sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec, + (short) mDependencies.getInterfaceMtu(mIfaceName))); } } else if (packet instanceof DhcpRequestPacket) { final ByteBuffer byteBuffer = isSuccessLease - ? buildDhcpAckPacket(packet, leaseTimeSec) + ? buildDhcpAckPacket(packet, leaseTimeSec, + (short) mDependencies.getInterfaceMtu(mIfaceName)) : buildDhcpNakPacket(packet); sendResponse(byteBuffer); } else { @@ -487,7 +502,7 @@ public class IpClientIntegrationTest { final long currentTime = System.currentTimeMillis(); performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */); - assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime); + assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_DEFAULT_MTU); } @Test @@ -502,7 +517,7 @@ public class IpClientIntegrationTest { final long currentTime = System.currentTimeMillis(); performDhcpHandshake(true /* isSuccessLease */, INFINITE_LEASE, true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */); - assertIpMemoryStoreNetworkAttributes(INFINITE_LEASE, currentTime); + assertIpMemoryStoreNetworkAttributes(INFINITE_LEASE, currentTime, TEST_DEFAULT_MTU); } @Test @@ -510,7 +525,7 @@ public class IpClientIntegrationTest { final long currentTime = System.currentTimeMillis(); performDhcpHandshake(true /* isSuccessLease */, null /* no lease time */, true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */); - assertIpMemoryStoreNetworkAttributes(null, currentTime); + assertIpMemoryStoreNetworkAttributes(null, currentTime, TEST_DEFAULT_MTU); } @Test @@ -527,7 +542,7 @@ public class IpClientIntegrationTest { final long currentTime = System.currentTimeMillis(); performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, true /* isDhcpRapidCommitEnabled */); - assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime); + assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_DEFAULT_MTU); } @Test @@ -536,7 +551,7 @@ public class IpClientIntegrationTest { new NetworkAttributes.Builder() .setAssignedV4Address(CLIENT_ADDR) .setAssignedV4AddressExpiry(Long.MAX_VALUE) // lease is always valid - .setMtu(new Integer(MTU)) + .setMtu(new Integer(TEST_DEFAULT_MTU)) .setGroupHint(TEST_GROUPHINT) .setDnsAddresses(Collections.singletonList(SERVER_ADDR)) .build(), false /* timeout */); @@ -549,7 +564,7 @@ public class IpClientIntegrationTest { new NetworkAttributes.Builder() .setAssignedV4Address(CLIENT_ADDR) .setAssignedV4AddressExpiry(EXPIRED_LEASE) - .setMtu(new Integer(MTU)) + .setMtu(new Integer(TEST_DEFAULT_MTU)) .setGroupHint(TEST_GROUPHINT) .setDnsAddresses(Collections.singletonList(SERVER_ADDR)) .build(), false /* timeout */); @@ -568,7 +583,7 @@ public class IpClientIntegrationTest { new NetworkAttributes.Builder() .setAssignedV4Address(CLIENT_ADDR) .setAssignedV4AddressExpiry(System.currentTimeMillis() + 3_600_000) - .setMtu(new Integer(MTU)) + .setMtu(new Integer(TEST_DEFAULT_MTU)) .setGroupHint(TEST_GROUPHINT) .setDnsAddresses(Collections.singletonList(SERVER_ADDR)) .build(), true /* timeout */); @@ -579,7 +594,7 @@ public class IpClientIntegrationTest { public void testDhcpClientStartWithCachedLeaseWithoutIPAddress() throws Exception { final DhcpPacket packet = getReplyFromDhcpLease( new NetworkAttributes.Builder() - .setMtu(new Integer(MTU)) + .setMtu(new Integer(TEST_DEFAULT_MTU)) .setGroupHint(TEST_GROUPHINT) .setDnsAddresses(Collections.singletonList(SERVER_ADDR)) .build(), false /* timeout */); @@ -593,4 +608,23 @@ public class IpClientIntegrationTest { final DhcpPacket packet = getNextDhcpPacket(); assertTrue(DhcpDiscoverPacket.class.isInstance(packet)); } + + @Test + public void testRestoreInitialInterfaceMtu() throws Exception { + final long currentTime = System.currentTimeMillis(); + + // check the initial interface MTU + assertTrue(mDependencies.getInterfaceMtu(mIfaceName) == TEST_DEFAULT_MTU); + + // change the MTU and pass the new MTU into DHCPOFFER and DHCPACK packet + mDependencies.setMtu(TEST_MIN_MTU); + performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, + true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */); + assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_MIN_MTU); + + mIpc.shutdown(); + HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS); + // verify that mtu indeed has been restored + verify(mNetd, times(1)).interfaceSetMtu(mIfaceName, TEST_DEFAULT_MTU); + } } diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java index 1d6ce6e..212e0ed 100644 --- a/tests/unit/src/android/net/ip/IpClientTest.java +++ b/tests/unit/src/android/net/ip/IpClientTest.java @@ -83,6 +83,7 @@ public class IpClientTest { private static final String INVALID = "INVALID"; private static final String TEST_IFNAME = "test_wlan0"; private static final int TEST_IFINDEX = 1001; + private static final int TEST_MTU = 1500; // See RFC 7042#section-2.1.2 for EUI-48 documentation values. private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01"); private static final int TEST_TIMEOUT_MS = 400; @@ -122,6 +123,7 @@ public class IpClientTest { when(mDependencies.getInterfaceParams(any())).thenReturn(mInterfaceParams); when(mDependencies.getIpMemoryStore(mContext, mNetworkStackServiceManager)) .thenReturn(mIpMemoryStore); + when(mDependencies.getInterfaceMtu(TEST_IFNAME)).thenReturn(TEST_MTU); mIfParams = null; } |