Merge "[TestOnly]Remove RemoteResponder from TetheringTester"

This commit is contained in:
Treehugger Robot
2022-06-13 11:59:54 +00:00
committed by Gerrit Code Review
2 changed files with 71 additions and 71 deletions

View File

@@ -26,7 +26,6 @@ import static android.net.InetAddresses.parseNumericAddress;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL;
import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL;
import static android.net.TetheringManager.TETHERING_ETHERNET; import static android.net.TetheringManager.TETHERING_ETHERNET;
import static android.net.TetheringTester.RemoteResponder;
import static android.net.TetheringTester.isIcmpv6Type; import static android.net.TetheringTester.isIcmpv6Type;
import static android.system.OsConstants.IPPROTO_IP; import static android.system.OsConstants.IPPROTO_IP;
import static android.system.OsConstants.IPPROTO_IPV6; import static android.system.OsConstants.IPPROTO_IPV6;
@@ -816,10 +815,10 @@ public class EthernetTetheringTest {
mDownstreamReader = makePacketReader(mDownstreamIface); mDownstreamReader = makePacketReader(mDownstreamIface);
mUpstreamReader = makePacketReader(mUpstreamTracker.getTestIface()); mUpstreamReader = makePacketReader(mUpstreamTracker.getTestIface());
runPing6Test(new TetheringTester(mDownstreamReader), new RemoteResponder(mUpstreamReader)); runPing6Test(new TetheringTester(mDownstreamReader, mUpstreamReader));
} }
private void runPing6Test(TetheringTester tester, RemoteResponder remote) throws Exception { private void runPing6Test(TetheringTester tester) throws Exception {
// Currently tethering don't have API to tell when ipv6 tethering is available. Thus, let // Currently tethering don't have API to tell when ipv6 tethering is available. Thus, let
// TetheringTester test ipv6 tethering connectivity before testing ipv6. // TetheringTester test ipv6 tethering connectivity before testing ipv6.
// TODO: move to a common place to avoid that every IPv6 test needs to call this function. // TODO: move to a common place to avoid that every IPv6 test needs to call this function.
@@ -830,24 +829,18 @@ public class EthernetTetheringTest {
Inet6Address remoteIp6Addr = (Inet6Address) parseNumericAddress("2400:222:222::222"); Inet6Address remoteIp6Addr = (Inet6Address) parseNumericAddress("2400:222:222::222");
ByteBuffer request = Ipv6Utils.buildEchoRequestPacket(tethered.macAddr, ByteBuffer request = Ipv6Utils.buildEchoRequestPacket(tethered.macAddr,
tethered.routerMacAddr, tethered.ipv6Addr, remoteIp6Addr); tethered.routerMacAddr, tethered.ipv6Addr, remoteIp6Addr);
tester.sendPacket(request); tester.verifyUpload(request, p -> {
final byte[] echoRequest = remote.getNextMatchedPacket((p) -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isIcmpv6Type(p, false /* hasEth */, ICMPV6_ECHO_REQUEST_TYPE); return isIcmpv6Type(p, false /* hasEth */, ICMPV6_ECHO_REQUEST_TYPE);
}); });
assertNotNull("No icmpv6 echo request in upstream", echoRequest);
ByteBuffer reply = Ipv6Utils.buildEchoReplyPacket(remoteIp6Addr, tethered.ipv6Addr); ByteBuffer reply = Ipv6Utils.buildEchoReplyPacket(remoteIp6Addr, tethered.ipv6Addr);
remote.sendPacket(reply); tester.verifyDownload(reply, p -> {
final byte[] echoReply = tester.getNextMatchedPacket((p) -> {
Log.d(TAG, "Packet in downstream: " + dumpHexString(p)); Log.d(TAG, "Packet in downstream: " + dumpHexString(p));
return isIcmpv6Type(p, true /* hasEth */, ICMPV6_ECHO_REPLY_TYPE); return isIcmpv6Type(p, true /* hasEth */, ICMPV6_ECHO_REPLY_TYPE);
}); });
assertNotNull("No icmpv6 echo reply in downstream", echoReply);
} }
// Test network topology: // Test network topology:
@@ -964,7 +957,7 @@ public class EthernetTetheringTest {
// TODO: remove this verification once upstream connected notification race is fixed. // TODO: remove this verification once upstream connected notification race is fixed.
// See #runUdp4Test. // See #runUdp4Test.
private boolean isIpv4TetherConnectivityVerified(TetheringTester tester, private boolean isIpv4TetherConnectivityVerified(TetheringTester tester,
RemoteResponder remote, TetheredDevice tethered) throws Exception { TetheredDevice tethered) throws Exception {
final ByteBuffer probePacket = buildUdpPacket(tethered.macAddr, final ByteBuffer probePacket = buildUdpPacket(tethered.macAddr,
tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */, tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */,
REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */,
@@ -972,8 +965,7 @@ public class EthernetTetheringTest {
// Send a UDP packet from client and check the packet can be found on upstream interface. // Send a UDP packet from client and check the packet can be found on upstream interface.
for (int i = 0; i < TETHER_REACHABILITY_ATTEMPTS; i++) { for (int i = 0; i < TETHER_REACHABILITY_ATTEMPTS; i++) {
tester.sendPacket(probePacket); byte[] expectedPacket = tester.testUpload(probePacket, p -> {
byte[] expectedPacket = remote.getNextMatchedPacket(p -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */,
TEST_REACHABILITY_PAYLOAD); TEST_REACHABILITY_PAYLOAD);
@@ -983,8 +975,7 @@ public class EthernetTetheringTest {
return false; return false;
} }
private void runUdp4Test(TetheringTester tester, RemoteResponder remote, boolean usingBpf) private void runUdp4Test(TetheringTester tester, boolean usingBpf) throws Exception {
throws Exception {
final TetheredDevice tethered = tester.createTetheredDevice(MacAddress.fromString( final TetheredDevice tethered = tester.createTetheredDevice(MacAddress.fromString(
"1:2:3:4:5:6"), false /* hasIpv6 */); "1:2:3:4:5:6"), false /* hasIpv6 */);
@@ -994,14 +985,14 @@ public class EthernetTetheringTest {
// For short term plan, consider using IPv6 RA to get MAC address because the prefix comes // For short term plan, consider using IPv6 RA to get MAC address because the prefix comes
// from upstream. That can guarantee that the routing is ready. Long term plan is that // from upstream. That can guarantee that the routing is ready. Long term plan is that
// refactors upstream connected notification from async to sync. // refactors upstream connected notification from async to sync.
assertTrue(isIpv4TetherConnectivityVerified(tester, remote, tethered)); assertTrue(isIpv4TetherConnectivityVerified(tester, tethered));
// Send a UDP packet in original direction. // Send a UDP packet in original direction.
final ByteBuffer originalPacket = buildUdpPacket(tethered.macAddr, final ByteBuffer originalPacket = buildUdpPacket(tethered.macAddr,
tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */, tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */,
REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */,
PAYLOAD /* payload */); PAYLOAD /* payload */);
tester.verifyUpload(remote, originalPacket, p -> { tester.verifyUpload(originalPacket, p -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, PAYLOAD); return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, PAYLOAD);
}); });
@@ -1011,7 +1002,7 @@ public class EthernetTetheringTest {
final ByteBuffer replyPacket = buildUdpPacket(REMOTE_IP4_ADDR /* srcIp */, final ByteBuffer replyPacket = buildUdpPacket(REMOTE_IP4_ADDR /* srcIp */,
publicIp4Addr /* dstIp */, REMOTE_PORT /* srcPort */, LOCAL_PORT /* dstPort */, publicIp4Addr /* dstIp */, REMOTE_PORT /* srcPort */, LOCAL_PORT /* dstPort */,
PAYLOAD2 /* payload */); PAYLOAD2 /* payload */);
remote.verifyDownload(tester, replyPacket, p -> { tester.verifyDownload(replyPacket, p -> {
Log.d(TAG, "Packet in downstream: " + dumpHexString(p)); Log.d(TAG, "Packet in downstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, true /* hasEther */, true /* isIpv4 */, PAYLOAD2); return isExpectedUdpPacket(p, true /* hasEther */, true /* isIpv4 */, PAYLOAD2);
}); });
@@ -1030,7 +1021,7 @@ public class EthernetTetheringTest {
tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */, tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */,
REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */,
REMOTE_PORT /* dstPort */, PAYLOAD3 /* payload */); REMOTE_PORT /* dstPort */, PAYLOAD3 /* payload */);
tester.verifyUpload(remote, originalPacket2, p -> { tester.verifyUpload(originalPacket2, p -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, PAYLOAD3); return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, PAYLOAD3);
}); });
@@ -1066,7 +1057,7 @@ public class EthernetTetheringTest {
// Send packets on original direction. // Send packets on original direction.
for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) { for (int i = 0; i < TX_UDP_PACKET_COUNT; i++) {
tester.verifyUpload(remote, originalPacket, p -> { tester.verifyUpload(originalPacket, p -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, PAYLOAD); return isExpectedUdpPacket(p, false /* hasEther */, true /* isIpv4 */, PAYLOAD);
}); });
@@ -1074,7 +1065,7 @@ public class EthernetTetheringTest {
// Send packets on reply direction. // Send packets on reply direction.
for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) { for (int i = 0; i < RX_UDP_PACKET_COUNT; i++) {
remote.verifyDownload(tester, replyPacket, p -> { tester.verifyDownload(replyPacket, p -> {
Log.d(TAG, "Packet in downstream: " + dumpHexString(p)); Log.d(TAG, "Packet in downstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, true /* hasEther */, true /* isIpv4 */, PAYLOAD2); return isExpectedUdpPacket(p, true /* hasEther */, true /* isIpv4 */, PAYLOAD2);
}); });
@@ -1130,8 +1121,7 @@ public class EthernetTetheringTest {
@IgnoreAfter(Build.VERSION_CODES.R) @IgnoreAfter(Build.VERSION_CODES.R)
public void testTetherUdpV4UpToR() throws Exception { public void testTetherUdpV4UpToR() throws Exception {
initializeTethering(toList(TEST_IP4_ADDR), toList(TEST_IP4_DNS)); initializeTethering(toList(TEST_IP4_ADDR), toList(TEST_IP4_DNS));
runUdp4Test(new TetheringTester(mDownstreamReader), new RemoteResponder(mUpstreamReader), runUdp4Test(new TetheringTester(mDownstreamReader, mUpstreamReader), false /* usingBpf */);
false /* usingBpf */);
} }
private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) { private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
@@ -1172,8 +1162,7 @@ public class EthernetTetheringTest {
Log.i(TAG, "testTetherUdpV4AfterR will skip BPF offload test for kernel " Log.i(TAG, "testTetherUdpV4AfterR will skip BPF offload test for kernel "
+ kernelVersion); + kernelVersion);
} }
runUdp4Test(new TetheringTester(mDownstreamReader), new RemoteResponder(mUpstreamReader), runUdp4Test(new TetheringTester(mDownstreamReader, mUpstreamReader), usingBpf);
usingBpf);
} }
@Nullable @Nullable
@@ -1233,8 +1222,8 @@ public class EthernetTetheringTest {
} }
@Nullable @Nullable
private Inet6Address getClatIpv6Address(TetheringTester tester, private Inet6Address getClatIpv6Address(TetheringTester tester, TetheredDevice tethered)
RemoteResponder remote, TetheredDevice tethered) throws Exception { throws Exception {
final ByteBuffer probePacket = buildUdpPacket(tethered.macAddr, final ByteBuffer probePacket = buildUdpPacket(tethered.macAddr,
tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */, tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */,
REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */,
@@ -1245,8 +1234,7 @@ public class EthernetTetheringTest {
// packet. // packet.
byte[] expectedPacket = null; byte[] expectedPacket = null;
for (int i = 0; i < TETHER_REACHABILITY_ATTEMPTS; i++) { for (int i = 0; i < TETHER_REACHABILITY_ATTEMPTS; i++) {
tester.sendPacket(probePacket); expectedPacket = tester.verifyUpload(probePacket, p -> {
expectedPacket = remote.getNextMatchedPacket(p -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, false /* hasEther */, false /* isIpv4 */, return isExpectedUdpPacket(p, false /* hasEther */, false /* isIpv4 */,
TEST_REACHABILITY_PAYLOAD); TEST_REACHABILITY_PAYLOAD);
@@ -1275,8 +1263,7 @@ public class EthernetTetheringTest {
// sending out an IPv4 packet and extracting the source address from CLAT translated IPv6 // sending out an IPv4 packet and extracting the source address from CLAT translated IPv6
// packet. // packet.
// //
private void runClatUdpTest(TetheringTester tester, RemoteResponder remote) private void runClatUdpTest(TetheringTester tester) throws Exception {
throws Exception {
// Currently tethering don't have API to tell when ipv6 tethering is available. Thus, let // Currently tethering don't have API to tell when ipv6 tethering is available. Thus, let
// TetheringTester test ipv6 tethering connectivity before testing ipv6. // TetheringTester test ipv6 tethering connectivity before testing ipv6.
// TODO: move to a common place to avoid that every IPv6 test needs to call this function. // TODO: move to a common place to avoid that every IPv6 test needs to call this function.
@@ -1286,7 +1273,7 @@ public class EthernetTetheringTest {
"1:2:3:4:5:6"), true /* hasIpv6 */); "1:2:3:4:5:6"), true /* hasIpv6 */);
// Get CLAT IPv6 address. // Get CLAT IPv6 address.
final Inet6Address clatAddr6 = getClatIpv6Address(tester, remote, tethered); final Inet6Address clatAddr6 = getClatIpv6Address(tester, tethered);
assertNotNull(clatAddr6); assertNotNull(clatAddr6);
// Send an IPv4 UDP packet in original direction. // Send an IPv4 UDP packet in original direction.
@@ -1295,7 +1282,7 @@ public class EthernetTetheringTest {
tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */, tethered.routerMacAddr, tethered.ipv4Addr /* srcIp */,
REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */, REMOTE_IP4_ADDR /* dstIp */, LOCAL_PORT /* srcPort */, REMOTE_PORT /* dstPort */,
PAYLOAD /* payload */); PAYLOAD /* payload */);
tester.verifyUpload(remote, originalPacket, p -> { tester.verifyUpload(originalPacket, p -> {
Log.d(TAG, "Packet in upstream: " + dumpHexString(p)); Log.d(TAG, "Packet in upstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, false /* hasEther */, false /* isIpv4 */, PAYLOAD); return isExpectedUdpPacket(p, false /* hasEther */, false /* isIpv4 */, PAYLOAD);
}); });
@@ -1305,7 +1292,7 @@ public class EthernetTetheringTest {
final ByteBuffer replyPacket = buildUdpPacket(REMOTE_NAT64_ADDR /* srcIp */, final ByteBuffer replyPacket = buildUdpPacket(REMOTE_NAT64_ADDR /* srcIp */,
clatAddr6 /* dstIp */, REMOTE_PORT /* srcPort */, LOCAL_PORT /* dstPort */, clatAddr6 /* dstIp */, REMOTE_PORT /* srcPort */, LOCAL_PORT /* dstPort */,
PAYLOAD2 /* payload */); PAYLOAD2 /* payload */);
remote.verifyDownload(tester, replyPacket, p -> { tester.verifyDownload(replyPacket, p -> {
Log.d(TAG, "Packet in downstream: " + dumpHexString(p)); Log.d(TAG, "Packet in downstream: " + dumpHexString(p));
return isExpectedUdpPacket(p, true /* hasEther */, true /* isIpv4 */, PAYLOAD2); return isExpectedUdpPacket(p, true /* hasEther */, true /* isIpv4 */, PAYLOAD2);
}); });
@@ -1318,8 +1305,7 @@ public class EthernetTetheringTest {
public void testTetherClatUdp() throws Exception { public void testTetherClatUdp() throws Exception {
// CLAT only starts on IPv6 only network. // CLAT only starts on IPv6 only network.
initializeTethering(toList(TEST_IP6_ADDR), toList(TEST_IP6_DNS)); initializeTethering(toList(TEST_IP6_ADDR), toList(TEST_IP6_DNS));
runClatUdpTest(new TetheringTester(mDownstreamReader), runClatUdpTest(new TetheringTester(mDownstreamReader, mUpstreamReader));
new RemoteResponder(mUpstreamReader));
} }
private <T> List<T> toList(T... array) { private <T> List<T> toList(T... array) {

View File

@@ -42,6 +42,7 @@ import android.net.dhcp.DhcpPacket;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.net.module.util.Ipv6Utils; import com.android.net.module.util.Ipv6Utils;
@@ -88,11 +89,17 @@ public final class TetheringTester {
private final ArrayMap<MacAddress, TetheredDevice> mTetheredDevices; private final ArrayMap<MacAddress, TetheredDevice> mTetheredDevices;
private final TapPacketReader mDownstreamReader; private final TapPacketReader mDownstreamReader;
private final TapPacketReader mUpstreamReader;
public TetheringTester(TapPacketReader downstream) { public TetheringTester(TapPacketReader downstream) {
this(downstream, null);
}
public TetheringTester(TapPacketReader downstream, TapPacketReader upstream) {
if (downstream == null) fail("Downstream reader could not be NULL"); if (downstream == null) fail("Downstream reader could not be NULL");
mDownstreamReader = downstream; mDownstreamReader = downstream;
mUpstreamReader = upstream;
mTetheredDevices = new ArrayMap<>(); mTetheredDevices = new ArrayMap<>();
} }
@@ -170,7 +177,7 @@ public final class TetheringTester {
} }
private DhcpPacket getNextDhcpPacket() throws Exception { private DhcpPacket getNextDhcpPacket() throws Exception {
final byte[] packet = getNextMatchedPacket((p) -> { final byte[] packet = getDownloadPacket((p) -> {
// Test whether this is DHCP packet. // Test whether this is DHCP packet.
try { try {
DhcpPacket.decodeFullPacket(p, p.length, DhcpPacket.ENCAP_L2); DhcpPacket.decodeFullPacket(p, p.length, DhcpPacket.ENCAP_L2);
@@ -213,7 +220,7 @@ public final class TetheringTester {
tethered.ipv4Addr.getAddress() /* sender IP */, tethered.ipv4Addr.getAddress() /* sender IP */,
(short) ARP_REPLY); (short) ARP_REPLY);
try { try {
sendPacket(arpReply); sendUploadPacket(arpReply);
} catch (Exception e) { } catch (Exception e) {
fail("Failed to reply ARP for " + tethered.ipv4Addr); fail("Failed to reply ARP for " + tethered.ipv4Addr);
} }
@@ -227,9 +234,9 @@ public final class TetheringTester {
tetherMac.toByteArray() /* srcMac */, routerIp.getAddress() /* target IP */, tetherMac.toByteArray() /* srcMac */, routerIp.getAddress() /* target IP */,
new byte[ETHER_ADDR_LEN] /* target HW address */, new byte[ETHER_ADDR_LEN] /* target HW address */,
tetherIp.getAddress() /* sender IP */, (short) ARP_REQUEST); tetherIp.getAddress() /* sender IP */, (short) ARP_REQUEST);
sendPacket(arpProbe); sendUploadPacket(arpProbe);
final byte[] packet = getNextMatchedPacket((p) -> { final byte[] packet = getDownloadPacket((p) -> {
final ArpPacket arpPacket = parseArpPacket(p); final ArpPacket arpPacket = parseArpPacket(p);
if (arpPacket == null || arpPacket.opCode != ARP_REPLY) return false; if (arpPacket == null || arpPacket.opCode != ARP_REPLY) return false;
return arpPacket.targetIp.equals(tetherIp); return arpPacket.targetIp.equals(tetherIp);
@@ -252,7 +259,7 @@ public final class TetheringTester {
// connectivity is ready. We don't extract the router mac address from RA because // connectivity is ready. We don't extract the router mac address from RA because
// we get the router mac address from IPv4 ARP packet. See #getRouterMacAddressFromArp. // we get the router mac address from IPv4 ARP packet. See #getRouterMacAddressFromArp.
for (int i = 0; i < READ_RA_ATTEMPTS; i++) { for (int i = 0; i < READ_RA_ATTEMPTS; i++) {
final byte[] raPacket = getNextMatchedPacket((p) -> { final byte[] raPacket = getDownloadPacket((p) -> {
return isIcmpv6Type(p, true /* hasEth */, ICMPV6_ROUTER_ADVERTISEMENT); return isIcmpv6Type(p, true /* hasEth */, ICMPV6_ROUTER_ADVERTISEMENT);
}); });
if (raPacket != null) return; if (raPacket != null) return;
@@ -290,13 +297,10 @@ public final class TetheringTester {
private Inet6Address runSlaac(MacAddress srcMac, MacAddress dstMac) throws Exception { private Inet6Address runSlaac(MacAddress srcMac, MacAddress dstMac) throws Exception {
sendRsPacket(srcMac, dstMac); sendRsPacket(srcMac, dstMac);
final byte[] raPacket = getNextMatchedPacket((p) -> { final byte[] raPacket = verifyPacketNotNull("Receive RA fail", getDownloadPacket(p -> {
return isIcmpv6Type(p, true /* hasEth */, ICMPV6_ROUTER_ADVERTISEMENT); return isIcmpv6Type(p, true /* hasEth */, ICMPV6_ROUTER_ADVERTISEMENT);
}); }));
if (raPacket == null) {
fail("Could not get ra for prefix options");
}
final List<PrefixInformationOption> options = getRaPrefixOptions(raPacket); final List<PrefixInformationOption> options = getRaPrefixOptions(raPacket);
for (PrefixInformationOption pio : options) { for (PrefixInformationOption pio : options) {
@@ -322,7 +326,7 @@ public final class TetheringTester {
ByteBuffer rs = Ipv6Utils.buildRsPacket(srcMac, dstMac, (Inet6Address) LINK_LOCAL, ByteBuffer rs = Ipv6Utils.buildRsPacket(srcMac, dstMac, (Inet6Address) LINK_LOCAL,
IPV6_ADDR_ALL_NODES_MULTICAST, slla); IPV6_ADDR_ALL_NODES_MULTICAST, slla);
sendPacket(rs); sendUploadPacket(rs);
} }
private void maybeReplyNa(byte[] packet) { private void maybeReplyNa(byte[] packet) {
@@ -347,7 +351,7 @@ public final class TetheringTester {
ByteBuffer ns = Ipv6Utils.buildNaPacket(tethered.macAddr, tethered.routerMacAddr, ByteBuffer ns = Ipv6Utils.buildNaPacket(tethered.macAddr, tethered.routerMacAddr,
nsHdr.target, ipv6Hdr.srcIp, flags, nsHdr.target, tlla); nsHdr.target, ipv6Hdr.srcIp, flags, nsHdr.target, tlla);
try { try {
sendPacket(ns); sendUploadPacket(ns);
} catch (Exception e) { } catch (Exception e) {
fail("Failed to reply NA for " + tethered.ipv6Addr); fail("Failed to reply NA for " + tethered.ipv6Addr);
} }
@@ -380,11 +384,17 @@ public final class TetheringTester {
return false; return false;
} }
public void sendPacket(ByteBuffer packet) throws Exception { private void sendUploadPacket(ByteBuffer packet) throws Exception {
mDownstreamReader.sendResponse(packet); mDownstreamReader.sendResponse(packet);
} }
public byte[] getNextMatchedPacket(Predicate<byte[]> filter) { private void sendDownloadPacket(ByteBuffer packet) throws Exception {
assertNotNull("Can't deal with upstream interface in local only mode", mUpstreamReader);
mUpstreamReader.sendResponse(packet);
}
private byte[] getDownloadPacket(Predicate<byte[]> filter) {
byte[] packet; byte[] packet;
while ((packet = mDownstreamReader.poll(PACKET_READ_TIMEOUT_MS)) != null) { while ((packet = mDownstreamReader.poll(PACKET_READ_TIMEOUT_MS)) != null) {
if (filter.test(packet)) return packet; if (filter.test(packet)) return packet;
@@ -396,30 +406,34 @@ public final class TetheringTester {
return null; return null;
} }
public void verifyUpload(final RemoteResponder dst, final ByteBuffer packet, private byte[] getUploadPacket(Predicate<byte[]> filter) {
final Predicate<byte[]> filter) throws Exception { assertNotNull("Can't deal with upstream interface in local only mode", mUpstreamReader);
sendPacket(packet);
assertNotNull("Upload fail", dst.getNextMatchedPacket(filter));
}
public static class RemoteResponder {
final TapPacketReader mUpstreamReader;
public RemoteResponder(TapPacketReader reader) {
mUpstreamReader = reader;
}
public void sendPacket(ByteBuffer packet) throws Exception {
mUpstreamReader.sendResponse(packet);
}
public byte[] getNextMatchedPacket(Predicate<byte[]> filter) throws Exception {
return mUpstreamReader.poll(PACKET_READ_TIMEOUT_MS, filter); return mUpstreamReader.poll(PACKET_READ_TIMEOUT_MS, filter);
} }
public void verifyDownload(final TetheringTester dst, final ByteBuffer packet, private @NonNull byte[] verifyPacketNotNull(String message, @Nullable byte[] packet) {
final Predicate<byte[]> filter) throws Exception { assertNotNull(message, packet);
sendPacket(packet);
assertNotNull("Download fail", dst.getNextMatchedPacket(filter)); return packet;
} }
public byte[] testUpload(final ByteBuffer packet, final Predicate<byte[]> filter)
throws Exception {
sendUploadPacket(packet);
return getUploadPacket(filter);
}
public byte[] verifyUpload(final ByteBuffer packet, final Predicate<byte[]> filter)
throws Exception {
return verifyPacketNotNull("Upload fail", testUpload(packet, filter));
}
public byte[] verifyDownload(final ByteBuffer packet, final Predicate<byte[]> filter)
throws Exception {
sendDownloadPacket(packet);
return verifyPacketNotNull("Download fail", getDownloadPacket(filter));
} }
} }