diff options
| author | Hungming Chen <nuccachen@google.com> | 2021-10-01 19:11:06 +0800 |
|---|---|---|
| committer | Nucca Chen <nuccachen@google.com> | 2022-01-03 07:16:16 +0000 |
| commit | bb8e9dae7fcaeda09ef8266fe83ac91c66fa354d (patch) | |
| tree | 6affee4236d7061e766c71e1f7a9e807e4b5024d /Tethering/tests/integration/src/android/net/TetheringTester.java | |
| parent | e4ee88f108f30269663449f3bafad430d8fb6e3f (diff) | |
Add tethering IPv4 UDP forwarding test
This is a preparation for testing IPv4 BPF offload.
- Add an ARP responder.
- Add a basic UDP forwarding test.
Test: atest EthernetTetheringTest
Change-Id: I720a5a2c4b97493eb6a5570cecd73dfc1eabf5cd
Diffstat (limited to 'Tethering/tests/integration/src/android/net/TetheringTester.java')
| -rw-r--r-- | Tethering/tests/integration/src/android/net/TetheringTester.java | 103 |
1 files changed, 96 insertions, 7 deletions
diff --git a/Tethering/tests/integration/src/android/net/TetheringTester.java b/Tethering/tests/integration/src/android/net/TetheringTester.java index d61bbb3665..d24661acbf 100644 --- a/Tethering/tests/integration/src/android/net/TetheringTester.java +++ b/Tethering/tests/integration/src/android/net/TetheringTester.java @@ -16,6 +16,12 @@ package android.net; +import static com.android.net.module.util.NetworkStackConstants.ARP_REPLY; +import static com.android.net.module.util.NetworkStackConstants.ARP_REQUEST; +import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN; +import static com.android.net.module.util.NetworkStackConstants.ETHER_BROADCAST; + +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import android.net.dhcp.DhcpAckPacket; @@ -24,6 +30,9 @@ import android.net.dhcp.DhcpPacket; import android.util.ArrayMap; import android.util.Log; +import androidx.annotation.Nullable; + +import com.android.networkstack.arp.ArpPacket; import com.android.testutils.TapPacketReader; import java.net.Inet4Address; @@ -72,15 +81,17 @@ public final class TetheringTester { } public class TetheredDevice { - private final MacAddress mMacAddr; - - public final Inet4Address mIpv4Addr; + public final MacAddress macAddr; + public final MacAddress routerMacAddr; + public final Inet4Address ipv4Addr; private TetheredDevice(MacAddress mac) throws Exception { - mMacAddr = mac; + macAddr = mac; - DhcpResults dhcpResults = runDhcp(mMacAddr.toByteArray()); - mIpv4Addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); + DhcpResults dhcpResults = runDhcp(macAddr.toByteArray()); + ipv4Addr = (Inet4Address) dhcpResults.ipAddress.getAddress(); + routerMacAddr = getRouterMacAddressFromArp(ipv4Addr, macAddr, + dhcpResults.serverAddress); } } @@ -146,12 +157,84 @@ public final class TetheringTester { DhcpPacket.decodeFullPacket(packet, packet.length, DhcpPacket.ENCAP_L2); } + @Nullable + private ArpPacket parseArpPacket(final byte[] packet) { + try { + return ArpPacket.parseArpPacket(packet, packet.length); + } catch (ArpPacket.ParseException e) { + return null; + } + } + + private void maybeReplyArp(byte[] packet) { + ByteBuffer buf = ByteBuffer.wrap(packet); + + final ArpPacket arpPacket = parseArpPacket(packet); + if (arpPacket == null || arpPacket.opCode != ARP_REQUEST) return; + + for (int i = 0; i < mTetheredDevices.size(); i++) { + TetheredDevice tethered = mTetheredDevices.valueAt(i); + if (!arpPacket.targetIp.equals(tethered.ipv4Addr)) continue; + + final ByteBuffer arpReply = ArpPacket.buildArpPacket( + arpPacket.senderHwAddress.toByteArray() /* dst */, + tethered.macAddr.toByteArray() /* srcMac */, + arpPacket.senderIp.getAddress() /* target IP */, + arpPacket.senderHwAddress.toByteArray() /* target HW address */, + tethered.ipv4Addr.getAddress() /* sender IP */, + (short) ARP_REPLY); + try { + sendPacket(arpReply); + } catch (Exception e) { + fail("Failed to reply ARP for " + tethered.ipv4Addr); + } + return; + } + } + + private MacAddress getRouterMacAddressFromArp(final Inet4Address tetherIp, + final MacAddress tetherMac, final Inet4Address routerIp) throws Exception { + final ByteBuffer arpProbe = ArpPacket.buildArpPacket(ETHER_BROADCAST /* dst */, + tetherMac.toByteArray() /* srcMac */, routerIp.getAddress() /* target IP */, + new byte[ETHER_ADDR_LEN] /* target HW address */, + tetherIp.getAddress() /* sender IP */, (short) ARP_REQUEST); + sendPacket(arpProbe); + + final byte[] packet = getNextMatchedPacket((p) -> { + final ArpPacket arpPacket = parseArpPacket(p); + if (arpPacket == null || arpPacket.opCode != ARP_REPLY) return false; + return arpPacket.targetIp.equals(tetherIp); + }); + + if (packet != null) { + Log.d(TAG, "Get Mac address from ARP"); + final ArpPacket arpReply = ArpPacket.parseArpPacket(packet, packet.length); + return arpReply.senderHwAddress; + } + + fail("Could not get ARP packet"); + return null; + } + public void sendPacket(ByteBuffer packet) throws Exception { mDownstreamReader.sendResponse(packet); } public byte[] getNextMatchedPacket(Predicate<byte[]> filter) { - return mDownstreamReader.poll(PACKET_READ_TIMEOUT_MS, filter); + byte[] packet; + while ((packet = mDownstreamReader.poll(PACKET_READ_TIMEOUT_MS)) != null) { + if (filter.test(packet)) return packet; + + maybeReplyArp(packet); + } + + return null; + } + + public void verifyUpload(final RemoteResponder dst, final ByteBuffer packet, + final Predicate<byte[]> filter) throws Exception { + sendPacket(packet); + assertNotNull("Upload fail", dst.getNextMatchedPacket(filter)); } public static class RemoteResponder { @@ -167,5 +250,11 @@ public final class TetheringTester { public byte[] getNextMatchedPacket(Predicate<byte[]> filter) throws Exception { return mUpstreamReader.poll(PACKET_READ_TIMEOUT_MS, filter); } + + public void verifyDownload(final TetheringTester dst, final ByteBuffer packet, + final Predicate<byte[]> filter) throws Exception { + sendPacket(packet); + assertNotNull("Download fail", dst.getNextMatchedPacket(filter)); + } } } |
