EthernetTetheringTest: add testIcmpv4Echo
Bug: 237369591
Test: atest EthernetTetheringTest
Change-Id: I96278c17ce97b63860b9379675c6ac2941b4016f
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 6b9f916..e694907 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -1547,7 +1547,7 @@
// TODO: move ICMPv4 packet build function to common utilis.
@NonNull
private ByteBuffer buildIcmpEchoPacketV4(
- @NonNull final MacAddress srcMac, @NonNull final MacAddress dstMac,
+ @Nullable final MacAddress srcMac, @Nullable final MacAddress dstMac,
@NonNull final Inet4Address srcIp, @NonNull final Inet4Address dstIp,
int type, short id, short seq) throws Exception {
if (type != ICMP_ECHO && type != ICMP_ECHOREPLY) {
@@ -1560,30 +1560,41 @@
payload.putShort(seq);
payload.rewind();
- final int etherHeaderLen = Struct.getSize(EthernetHeader.class);
+ final boolean hasEther = (srcMac != null && dstMac != null);
+ final int etherHeaderLen = hasEther ? Struct.getSize(EthernetHeader.class) : 0;
final int ipv4HeaderLen = Struct.getSize(Ipv4Header.class);
final int Icmpv4HeaderLen = Struct.getSize(Icmpv4Header.class);
final int payloadLen = payload.limit();
final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv4HeaderLen
+ Icmpv4HeaderLen + payloadLen);
- final EthernetHeader ethHeader = new EthernetHeader(dstMac, srcMac, ETHER_TYPE_IPV4);
+ // [1] Ethernet header
+ if (hasEther) {
+ final EthernetHeader ethHeader = new EthernetHeader(dstMac, srcMac, ETHER_TYPE_IPV4);
+ ethHeader.writeToByteBuffer(packet);
+ }
+
+ // [2] IP header
final Ipv4Header ipv4Header = new Ipv4Header(TYPE_OF_SERVICE,
(short) 0 /* totalLength, calculate later */, ID,
FLAGS_AND_FRAGMENT_OFFSET, TIME_TO_LIVE, (byte) IPPROTO_ICMP,
(short) 0 /* checksum, calculate later */, srcIp, dstIp);
+ ipv4Header.writeToByteBuffer(packet);
+
+ // [3] ICMP header
final Icmpv4Header icmpv4Header = new Icmpv4Header((byte) type, ICMPECHO_CODE,
(short) 0 /* checksum, calculate later */);
-
- ethHeader.writeToByteBuffer(packet);
- ipv4Header.writeToByteBuffer(packet);
icmpv4Header.writeToByteBuffer(packet);
+
+ // [4] Payload
packet.put(payload);
packet.flip();
- // Used for updating IP header fields. IPv4 header offset in buffer equals ethernet header
- // length because IPv4 header is located next to ethernet header.
- final int ipv4HeaderOffset = etherHeaderLen;
+ // [5] Finalize packet
+ // Used for updating IP header fields. If there is Ehternet header, IPv4 header offset
+ // in buffer equals ethernet header length because IPv4 header is located next to ethernet
+ // header. Otherwise, IPv4 header offset is 0.
+ final int ipv4HeaderOffset = hasEther ? etherHeaderLen : 0;
// Populate the IPv4 totalLength field.
packet.putShort(ipv4HeaderOffset + IPV4_LENGTH_OFFSET,
@@ -1600,6 +1611,43 @@
return packet;
}
+ @NonNull
+ private ByteBuffer buildIcmpEchoPacketV4(@NonNull final Inet4Address srcIp,
+ @NonNull final Inet4Address dstIp, int type, short id, short seq)
+ throws Exception {
+ return buildIcmpEchoPacketV4(null /* srcMac */, null /* dstMac */, srcIp, dstIp,
+ type, id, seq);
+ }
+
+ @Test
+ public void testIcmpv4Echo() throws Exception {
+ final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
+ toList(TEST_IP4_DNS));
+ final TetheredDevice tethered = tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
+
+ // TODO: remove the connectivity verification for upstream connected notification race.
+ // See the same reason in runUdp4Test().
+ probeV4TetheringConnectivity(tester, tethered, false /* is4To6 */);
+
+ final ByteBuffer request = buildIcmpEchoPacketV4(tethered.macAddr /* srcMac */,
+ tethered.routerMacAddr /* dstMac */, tethered.ipv4Addr /* srcIp */,
+ REMOTE_IP4_ADDR /* dstIp */, ICMP_ECHO, ICMPECHO_ID, ICMPECHO_SEQ);
+ tester.verifyUpload(request, p -> {
+ Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
+
+ return isExpectedIcmpPacket(p, false /* hasEth */, true /* isIpv4 */, ICMP_ECHO);
+ });
+
+ final ByteBuffer reply = buildIcmpEchoPacketV4(REMOTE_IP4_ADDR /* srcIp*/,
+ (Inet4Address) TEST_IP4_ADDR.getAddress() /* dstIp */, ICMP_ECHOREPLY, ICMPECHO_ID,
+ ICMPECHO_SEQ);
+ tester.verifyDownload(reply, p -> {
+ Log.d(TAG, "Packet in downstream: " + dumpHexString(p));
+
+ return isExpectedIcmpPacket(p, true /* hasEth */, true /* isIpv4 */, ICMP_ECHOREPLY);
+ });
+ }
+
// TODO: support R device. See b/234727688.
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)