EthernetTetheringTest: add testIcmpv4Echo

Bug: 237369591
Test: atest EthernetTetheringTest
Change-Id: I96278c17ce97b63860b9379675c6ac2941b4016f
This commit is contained in:
Hungming Chen
2022-07-25 19:03:44 +08:00
parent 90551145ae
commit e2fb681aec

View File

@@ -1547,7 +1547,7 @@ public class EthernetTetheringTest {
// TODO: move ICMPv4 packet build function to common utilis. // TODO: move ICMPv4 packet build function to common utilis.
@NonNull @NonNull
private ByteBuffer buildIcmpEchoPacketV4( 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, @NonNull final Inet4Address srcIp, @NonNull final Inet4Address dstIp,
int type, short id, short seq) throws Exception { int type, short id, short seq) throws Exception {
if (type != ICMP_ECHO && type != ICMP_ECHOREPLY) { if (type != ICMP_ECHO && type != ICMP_ECHOREPLY) {
@@ -1560,30 +1560,41 @@ public class EthernetTetheringTest {
payload.putShort(seq); payload.putShort(seq);
payload.rewind(); 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 ipv4HeaderLen = Struct.getSize(Ipv4Header.class);
final int Icmpv4HeaderLen = Struct.getSize(Icmpv4Header.class); final int Icmpv4HeaderLen = Struct.getSize(Icmpv4Header.class);
final int payloadLen = payload.limit(); final int payloadLen = payload.limit();
final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv4HeaderLen final ByteBuffer packet = ByteBuffer.allocate(etherHeaderLen + ipv4HeaderLen
+ Icmpv4HeaderLen + payloadLen); + 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, final Ipv4Header ipv4Header = new Ipv4Header(TYPE_OF_SERVICE,
(short) 0 /* totalLength, calculate later */, ID, (short) 0 /* totalLength, calculate later */, ID,
FLAGS_AND_FRAGMENT_OFFSET, TIME_TO_LIVE, (byte) IPPROTO_ICMP, FLAGS_AND_FRAGMENT_OFFSET, TIME_TO_LIVE, (byte) IPPROTO_ICMP,
(short) 0 /* checksum, calculate later */, srcIp, dstIp); (short) 0 /* checksum, calculate later */, srcIp, dstIp);
ipv4Header.writeToByteBuffer(packet);
// [3] ICMP header
final Icmpv4Header icmpv4Header = new Icmpv4Header((byte) type, ICMPECHO_CODE, final Icmpv4Header icmpv4Header = new Icmpv4Header((byte) type, ICMPECHO_CODE,
(short) 0 /* checksum, calculate later */); (short) 0 /* checksum, calculate later */);
ethHeader.writeToByteBuffer(packet);
ipv4Header.writeToByteBuffer(packet);
icmpv4Header.writeToByteBuffer(packet); icmpv4Header.writeToByteBuffer(packet);
// [4] Payload
packet.put(payload); packet.put(payload);
packet.flip(); packet.flip();
// Used for updating IP header fields. IPv4 header offset in buffer equals ethernet header // [5] Finalize packet
// length because IPv4 header is located next to ethernet header. // Used for updating IP header fields. If there is Ehternet header, IPv4 header offset
final int ipv4HeaderOffset = etherHeaderLen; // 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. // Populate the IPv4 totalLength field.
packet.putShort(ipv4HeaderOffset + IPV4_LENGTH_OFFSET, packet.putShort(ipv4HeaderOffset + IPV4_LENGTH_OFFSET,
@@ -1600,6 +1611,43 @@ public class EthernetTetheringTest {
return packet; 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. // TODO: support R device. See b/234727688.
@Test @Test
@IgnoreUpTo(Build.VERSION_CODES.R) @IgnoreUpTo(Build.VERSION_CODES.R)