diff --git a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java index 2ef1d5b820..225bd5830e 100644 --- a/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java +++ b/Tethering/src/com/android/networkstack/tethering/BpfCoordinator.java @@ -1487,7 +1487,8 @@ public class BpfCoordinator { } @NonNull - private byte[] toIpv4MappedAddressBytes(Inet4Address ia4) { + @VisibleForTesting + static byte[] toIpv4MappedAddressBytes(Inet4Address ia4) { final byte[] addr4 = ia4.getAddress(); final byte[] addr6 = new byte[16]; addr6[10] = (byte) 0xff; diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java index c614046c6c..179fc8af01 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/BpfCoordinatorTest.java @@ -47,6 +47,7 @@ import static com.android.networkstack.tethering.BpfCoordinator.NON_OFFLOADED_UP import static com.android.networkstack.tethering.BpfCoordinator.StatsType; import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_IFACE; import static com.android.networkstack.tethering.BpfCoordinator.StatsType.STATS_PER_UID; +import static com.android.networkstack.tethering.BpfCoordinator.toIpv4MappedAddressBytes; import static com.android.networkstack.tethering.BpfUtils.DOWNSTREAM; import static com.android.networkstack.tethering.BpfUtils.UPSTREAM; import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; @@ -129,6 +130,7 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; @RunWith(AndroidJUnit4.class) @@ -138,22 +140,225 @@ public class BpfCoordinatorTest { public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); private static final int TEST_NET_ID = 24; + private static final int TEST_NET_ID2 = 25; + private static final int INVALID_IFINDEX = 0; private static final int UPSTREAM_IFINDEX = 1001; - private static final int DOWNSTREAM_IFINDEX = 1002; + private static final int UPSTREAM_IFINDEX2 = 1002; + private static final int DOWNSTREAM_IFINDEX = 1003; + private static final int DOWNSTREAM_IFINDEX2 = 1004; private static final String UPSTREAM_IFACE = "rmnet0"; + private static final String UPSTREAM_IFACE2 = "wlan0"; private static final MacAddress DOWNSTREAM_MAC = MacAddress.fromString("12:34:56:78:90:ab"); + private static final MacAddress DOWNSTREAM_MAC2 = MacAddress.fromString("ab:90:78:56:34:12"); + private static final MacAddress MAC_A = MacAddress.fromString("00:00:00:00:00:0a"); private static final MacAddress MAC_B = MacAddress.fromString("11:22:33:00:00:0b"); private static final InetAddress NEIGH_A = InetAddresses.parseNumericAddress("2001:db8::1"); private static final InetAddress NEIGH_B = InetAddresses.parseNumericAddress("2001:db8::2"); + private static final Inet4Address REMOTE_ADDR = + (Inet4Address) InetAddresses.parseNumericAddress("140.112.8.116"); + private static final Inet4Address PUBLIC_ADDR = + (Inet4Address) InetAddresses.parseNumericAddress("1.0.0.1"); + private static final Inet4Address PUBLIC_ADDR2 = + (Inet4Address) InetAddresses.parseNumericAddress("1.0.0.2"); + private static final Inet4Address PRIVATE_ADDR = + (Inet4Address) InetAddresses.parseNumericAddress("192.168.80.12"); + private static final Inet4Address PRIVATE_ADDR2 = + (Inet4Address) InetAddresses.parseNumericAddress("192.168.90.12"); + + // Generally, public port and private port are the same in the NAT conntrack message. + // TODO: consider using different private port and public port for testing. + private static final short REMOTE_PORT = (short) 443; + private static final short PUBLIC_PORT = (short) 62449; + private static final short PUBLIC_PORT2 = (short) 62450; + private static final short PRIVATE_PORT = (short) 62449; + private static final short PRIVATE_PORT2 = (short) 62450; + private static final InterfaceParams UPSTREAM_IFACE_PARAMS = new InterfaceParams( UPSTREAM_IFACE, UPSTREAM_IFINDEX, null /* macAddr, rawip */, NetworkStackConstants.ETHER_MTU); + private static final InterfaceParams UPSTREAM_IFACE_PARAMS2 = new InterfaceParams( + UPSTREAM_IFACE2, UPSTREAM_IFINDEX2, MacAddress.fromString("44:55:66:00:00:0c"), + NetworkStackConstants.ETHER_MTU); + + private static final HashMap UPSTREAM_INFORMATIONS = + new HashMap() {{ + put(UPSTREAM_IFINDEX, new UpstreamInformation(UPSTREAM_IFACE_PARAMS, + PUBLIC_ADDR, NetworkCapabilities.TRANSPORT_CELLULAR, TEST_NET_ID)); + put(UPSTREAM_IFINDEX2, new UpstreamInformation(UPSTREAM_IFACE_PARAMS2, + PUBLIC_ADDR2, NetworkCapabilities.TRANSPORT_WIFI, TEST_NET_ID2)); + }}; + + private static final ClientInfo CLIENT_INFO_A = new ClientInfo(DOWNSTREAM_IFINDEX, + DOWNSTREAM_MAC, PRIVATE_ADDR, MAC_A); + private static final ClientInfo CLIENT_INFO_B = new ClientInfo(DOWNSTREAM_IFINDEX2, + DOWNSTREAM_MAC2, PRIVATE_ADDR2, MAC_B); + + private static class UpstreamInformation { + public final InterfaceParams interfaceParams; + public final Inet4Address address; + public final int transportType; + public final int netId; + + UpstreamInformation(final InterfaceParams interfaceParams, + final Inet4Address address, int transportType, int netId) { + this.interfaceParams = interfaceParams; + this.address = address; + this.transportType = transportType; + this.netId = netId; + } + } + + private static class TestUpstream4Key { + public static class Builder { + private long mIif = DOWNSTREAM_IFINDEX; + private MacAddress mDstMac = DOWNSTREAM_MAC; + private short mL4proto = (short) IPPROTO_TCP; + private byte[] mSrc4 = PRIVATE_ADDR.getAddress(); + private byte[] mDst4 = REMOTE_ADDR.getAddress(); + private int mSrcPort = PRIVATE_PORT; + private int mDstPort = REMOTE_PORT; + + Builder() {} + + public Builder setProto(int proto) { + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) { + fail("Not support protocol " + proto); + } + mL4proto = (short) proto; + return this; + } + + public Tether4Key build() { + return new Tether4Key(mIif, mDstMac, mL4proto, mSrc4, mDst4, mSrcPort, mDstPort); + } + } + } + + private static class TestDownstream4Key { + public static class Builder { + private long mIif = UPSTREAM_IFINDEX; + private MacAddress mDstMac = MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */; + private short mL4proto = (short) IPPROTO_TCP; + private byte[] mSrc4 = REMOTE_ADDR.getAddress(); + private byte[] mDst4 = PUBLIC_ADDR.getAddress(); + private int mSrcPort = REMOTE_PORT; + private int mDstPort = PUBLIC_PORT; + + Builder() {} + + public Builder setProto(int proto) { + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) { + fail("Not support protocol " + proto); + } + mL4proto = (short) proto; + return this; + } + + public Tether4Key build() { + return new Tether4Key(mIif, mDstMac, mL4proto, mSrc4, mDst4, mSrcPort, mDstPort); + } + } + } + + private static class TestUpstream4Value { + public static class Builder { + private long mOif = UPSTREAM_IFINDEX; + private MacAddress mEthDstMac = MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */; + private MacAddress mEthSrcMac = MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */; + private int mEthProto = ETH_P_IP; + private short mPmtu = NetworkStackConstants.ETHER_MTU; + private byte[] mSrc46 = toIpv4MappedAddressBytes(PUBLIC_ADDR); + private byte[] mDst46 = toIpv4MappedAddressBytes(REMOTE_ADDR); + private int mSrcPort = PUBLIC_PORT; + private int mDstPort = REMOTE_PORT; + private long mLastUsed = 0; + + Builder() {} + + public Tether4Value build() { + return new Tether4Value(mOif, mEthDstMac, mEthSrcMac, mEthProto, mPmtu, + mSrc46, mDst46, mSrcPort, mDstPort, mLastUsed); + } + } + } + + private static class TestDownstream4Value { + public static class Builder { + private long mOif = DOWNSTREAM_IFINDEX; + private MacAddress mEthDstMac = MAC_A /* client mac */; + private MacAddress mEthSrcMac = DOWNSTREAM_MAC; + private int mEthProto = ETH_P_IP; + private short mPmtu = NetworkStackConstants.ETHER_MTU; + private byte[] mSrc46 = toIpv4MappedAddressBytes(REMOTE_ADDR); + private byte[] mDst46 = toIpv4MappedAddressBytes(PRIVATE_ADDR); + private int mSrcPort = REMOTE_PORT; + private int mDstPort = PRIVATE_PORT; + private long mLastUsed = 0; + + Builder() {} + + public Tether4Value build() { + return new Tether4Value(mOif, mEthDstMac, mEthSrcMac, mEthProto, mPmtu, + mSrc46, mDst46, mSrcPort, mDstPort, mLastUsed); + } + } + } + + private static class TestConntrackEvent { + public static class Builder { + private short mMsgType = IPCTNL_MSG_CT_NEW; + private short mProto = (short) IPPROTO_TCP; + private Inet4Address mPrivateAddr = PRIVATE_ADDR; + private Inet4Address mPublicAddr = PUBLIC_ADDR; + private Inet4Address mRemoteAddr = REMOTE_ADDR; + private short mPrivatePort = PRIVATE_PORT; + private short mPublicPort = PUBLIC_PORT; + private short mRemotePort = REMOTE_PORT; + + Builder() {} + + public Builder setMsgType(short msgType) { + if (msgType != IPCTNL_MSG_CT_NEW && msgType != IPCTNL_MSG_CT_DELETE) { + fail("Not support message type " + msgType); + } + mMsgType = (short) msgType; + return this; + } + + public Builder setProto(int proto) { + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) { + fail("Not support protocol " + proto); + } + mProto = (short) proto; + return this; + } + + public Builder setRemotePort(int remotePort) { + mRemotePort = (short) remotePort; + return this; + } + + public ConntrackEvent build() { + final int status = (mMsgType == IPCTNL_MSG_CT_NEW) ? ESTABLISHED_MASK : DYING_MASK; + final int timeoutSec = (mMsgType == IPCTNL_MSG_CT_NEW) ? 100 /* nonzero, new */ + : 0 /* unused, delete */; + return new ConntrackEvent( + (short) (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 | mMsgType), + new Tuple(new TupleIpv4(mPrivateAddr, mRemoteAddr), + new TupleProto((byte) mProto, mPrivatePort, mRemotePort)), + new Tuple(new TupleIpv4(mRemoteAddr, mPublicAddr), + new TupleProto((byte) mProto, mRemotePort, mPublicPort)), + status, + timeoutSec); + } + } + } @Mock private NetworkStatsManager mStatsManager; @Mock private INetd mNetd; @@ -161,8 +366,6 @@ public class BpfCoordinatorTest { @Mock private IpServer mIpServer2; @Mock private TetheringConfiguration mTetherConfig; @Mock private ConntrackMonitor mConntrackMonitor; - @Mock private BpfMap mBpfDownstream4Map; - @Mock private BpfMap mBpfUpstream4Map; @Mock private BpfMap mBpfDownstream6Map; @Mock private BpfMap mBpfUpstream6Map; @Mock private BpfMap mBpfDevMap; @@ -179,6 +382,10 @@ public class BpfCoordinatorTest { private final ArgumentCaptor mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private final TestLooper mTestLooper = new TestLooper(); + private final BpfMap mBpfDownstream4Map = + spy(new TestBpfMap<>(Tether4Key.class, Tether4Value.class)); + private final BpfMap mBpfUpstream4Map = + spy(new TestBpfMap<>(Tether4Key.class, Tether4Value.class)); private final TestBpfMap mBpfStatsMap = spy(new TestBpfMap<>(TetherStatsKey.class, TetherStatsValue.class)); private final TestBpfMap mBpfLimitMap = @@ -1244,140 +1451,67 @@ public class BpfCoordinatorTest { // | Sever +---------+ Upstream | Downstream +---------+ Client | // +------------+ +------------+------------+ +------------+ // remote ip public ip private ip - // 140.112.8.116:443 100.81.179.1:62449 192.168.80.12:62449 + // 140.112.8.116:443 1.0.0.1:62449 192.168.80.12:62449 // - private static final Inet4Address REMOTE_ADDR = - (Inet4Address) InetAddresses.parseNumericAddress("140.112.8.116"); - private static final Inet4Address PUBLIC_ADDR = - (Inet4Address) InetAddresses.parseNumericAddress("100.81.179.1"); - private static final Inet4Address PRIVATE_ADDR = - (Inet4Address) InetAddresses.parseNumericAddress("192.168.80.12"); - // IPv4-mapped IPv6 addresses - // Remote addrress ::ffff:140.112.8.116 - // Public addrress ::ffff:100.81.179.1 - // Private addrress ::ffff:192.168.80.12 - private static final byte[] REMOTE_ADDR_V4MAPPED_BYTES = new byte[] { - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, - (byte) 0x8c, (byte) 0x70, (byte) 0x08, (byte) 0x74 }; - private static final byte[] PUBLIC_ADDR_V4MAPPED_BYTES = new byte[] { - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, - (byte) 0x64, (byte) 0x51, (byte) 0xb3, (byte) 0x01 }; - private static final byte[] PRIVATE_ADDR_V4MAPPED_BYTES = new byte[] { - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, - (byte) 0xc0, (byte) 0xa8, (byte) 0x50, (byte) 0x0c }; - - // Generally, public port and private port are the same in the NAT conntrack message. - // TODO: consider using different private port and public port for testing. - private static final short REMOTE_PORT = (short) 443; - private static final short PUBLIC_PORT = (short) 62449; - private static final short PRIVATE_PORT = (short) 62449; - - @NonNull - private Tether4Key makeUpstream4Key(int proto) { - if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) { - fail("Not support protocol " + proto); - } - return new Tether4Key(DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC, (short) proto, - PRIVATE_ADDR.getAddress(), REMOTE_ADDR.getAddress(), PRIVATE_PORT, REMOTE_PORT); - } - - @NonNull - private Tether4Key makeDownstream4Key(int proto) { - if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) { - fail("Not support protocol " + proto); - } - return new Tether4Key(UPSTREAM_IFINDEX, - MacAddress.ALL_ZEROS_ADDRESS /* dstMac (rawip) */, (short) proto, - REMOTE_ADDR.getAddress(), PUBLIC_ADDR.getAddress(), REMOTE_PORT, PUBLIC_PORT); - } - - @NonNull - private Tether4Value makeUpstream4Value() { - return new Tether4Value(UPSTREAM_IFINDEX, - MacAddress.ALL_ZEROS_ADDRESS /* ethDstMac (rawip) */, - MacAddress.ALL_ZEROS_ADDRESS /* ethSrcMac (rawip) */, ETH_P_IP, - NetworkStackConstants.ETHER_MTU, PUBLIC_ADDR_V4MAPPED_BYTES, - REMOTE_ADDR_V4MAPPED_BYTES, PUBLIC_PORT, REMOTE_PORT, 0 /* lastUsed */); - } - - @NonNull - private Tether4Value makeDownstream4Value() { - return new Tether4Value(DOWNSTREAM_IFINDEX, MAC_A /* client mac */, DOWNSTREAM_MAC, - ETH_P_IP, NetworkStackConstants.ETHER_MTU, REMOTE_ADDR_V4MAPPED_BYTES, - PRIVATE_ADDR_V4MAPPED_BYTES, REMOTE_PORT, PRIVATE_PORT, 0 /* lastUsed */); - } - - @NonNull - private Tether4Key makeDownstream4Key() { - return makeDownstream4Key(IPPROTO_TCP); - } - - @NonNull - private ConntrackEvent makeTestConntrackEvent(short msgType, int proto, short remotePort) { - if (msgType != IPCTNL_MSG_CT_NEW && msgType != IPCTNL_MSG_CT_DELETE) { - fail("Not support message type " + msgType); - } - if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) { - fail("Not support protocol " + proto); + // Setup upstream interface to BpfCoordinator. + // + // @param coordinator BpfCoordinator instance. + // @param upstreamIfindex upstream interface index. can be the following values. + // INVALID_IFINDEX: no upstream interface + // UPSTREAM_IFINDEX: CELLULAR (raw ip interface) + // UPSTREAM_IFINDEX2: WIFI (ethernet interface) + private void setUpstreamInformationTo(final BpfCoordinator coordinator, + @Nullable Integer upstreamIfindex) { + if (upstreamIfindex == INVALID_IFINDEX) { + coordinator.updateUpstreamNetworkState(null); + return; } - final int status = (msgType == IPCTNL_MSG_CT_NEW) ? ESTABLISHED_MASK : DYING_MASK; - final int timeoutSec = (msgType == IPCTNL_MSG_CT_NEW) ? 100 /* nonzero, new */ - : 0 /* unused, delete */; - return new ConntrackEvent( - (short) (NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 | msgType), - new Tuple(new TupleIpv4(PRIVATE_ADDR, REMOTE_ADDR), - new TupleProto((byte) proto, PRIVATE_PORT, remotePort)), - new Tuple(new TupleIpv4(REMOTE_ADDR, PUBLIC_ADDR), - new TupleProto((byte) proto, remotePort, PUBLIC_PORT)), - status, - timeoutSec); - } - - @NonNull - private ConntrackEvent makeTestConntrackEvent(short msgType, int proto) { - return makeTestConntrackEvent(msgType, proto, REMOTE_PORT); - } - - private void setUpstreamInformationTo(final BpfCoordinator coordinator) { - final LinkProperties lp = new LinkProperties(); - lp.setInterfaceName(UPSTREAM_IFACE); - lp.addLinkAddress(new LinkAddress(PUBLIC_ADDR, 32 /* prefix length */)); - final NetworkCapabilities capabilities = new NetworkCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); - coordinator.updateUpstreamNetworkState(new UpstreamNetworkState(lp, capabilities, - new Network(TEST_NET_ID))); - } - - private void setDownstreamAndClientInformationTo(final BpfCoordinator coordinator) { - final ClientInfo clientInfo = new ClientInfo(DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC, - PRIVATE_ADDR, MAC_A /* client mac */); - coordinator.tetherOffloadClientAdd(mIpServer, clientInfo); - } - - private void initBpfCoordinatorForRule4(final BpfCoordinator coordinator) throws Exception { - // Needed because addUpstreamIfindexToMap only updates upstream information when polling - // was started. - coordinator.startPolling(); - - // Needed because two reasons: (1) BpfConntrackEventConsumer#accept only performs cleanup - // when both upstream and downstream rules are removed. (2) tetherOffloadRuleRemove of - // api31.BpfCoordinatorShimImpl only decreases the count while the entry is deleted. - // In the other words, deleteEntry returns true. - doReturn(true).when(mBpfUpstream4Map).deleteEntry(any()); - doReturn(true).when(mBpfDownstream4Map).deleteEntry(any()); + final UpstreamInformation upstreamInfo = UPSTREAM_INFORMATIONS.get(upstreamIfindex); + if (upstreamInfo == null) { + fail("Not support upstream interface index " + upstreamIfindex); + } // Needed because BpfCoordinator#addUpstreamIfindexToMap queries interface parameter for // interface index. - doReturn(UPSTREAM_IFACE_PARAMS).when(mDeps).getInterfaceParams(UPSTREAM_IFACE); + doReturn(upstreamInfo.interfaceParams).when(mDeps).getInterfaceParams( + upstreamInfo.interfaceParams.name); + coordinator.addUpstreamNameToLookupTable(upstreamInfo.interfaceParams.index, + upstreamInfo.interfaceParams.name); - coordinator.addUpstreamNameToLookupTable(UPSTREAM_IFINDEX, UPSTREAM_IFACE); - setUpstreamInformationTo(coordinator); - setDownstreamAndClientInformationTo(coordinator); + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(upstreamInfo.interfaceParams.name); + lp.addLinkAddress(new LinkAddress(upstreamInfo.address, 32 /* prefix length */)); + final NetworkCapabilities capabilities = new NetworkCapabilities() + .addTransportType(upstreamInfo.transportType); + coordinator.updateUpstreamNetworkState(new UpstreamNetworkState(lp, capabilities, + new Network(upstreamInfo.netId))); + } + + // Setup downstream interface and its client information to BpfCoordinator. + // + // @param coordinator BpfCoordinator instance. + // @param downstreamIfindex downstream interface index. can be the following values. + // DOWNSTREAM_IFINDEX: a client information which uses MAC_A is added. + // DOWNSTREAM_IFINDEX2: a client information which uses MAC_B is added. + // TODO: refactor this function once the client switches between each downstream interface. + private void addDownstreamAndClientInformationTo(final BpfCoordinator coordinator, + int downstreamIfindex) { + if (downstreamIfindex != DOWNSTREAM_IFINDEX && downstreamIfindex != DOWNSTREAM_IFINDEX2) { + fail("Not support downstream interface index " + downstreamIfindex); + } + + if (downstreamIfindex == DOWNSTREAM_IFINDEX) { + coordinator.tetherOffloadClientAdd(mIpServer, CLIENT_INFO_A); + } else { + coordinator.tetherOffloadClientAdd(mIpServer2, CLIENT_INFO_B); + } + } + + private void initBpfCoordinatorForRule4(final BpfCoordinator coordinator) throws Exception { + setUpstreamInformationTo(coordinator, UPSTREAM_IFINDEX); + addDownstreamAndClientInformationTo(coordinator, DOWNSTREAM_IFINDEX); } // TODO: Test the IPv4 and IPv6 exist concurrently. @@ -1401,18 +1535,25 @@ public class BpfCoordinatorTest { // because the protocol is not an element of the value. Consider using different address // or port to make them different for better testing. // TODO: Make the values of {TCP, UDP} rules different. - final Tether4Key expectedUpstream4KeyTcp = makeUpstream4Key(IPPROTO_TCP); - final Tether4Key expectedDownstream4KeyTcp = makeDownstream4Key(IPPROTO_TCP); - final Tether4Value expectedUpstream4ValueTcp = makeUpstream4Value(); - final Tether4Value expectedDownstream4ValueTcp = makeDownstream4Value(); + final Tether4Key expectedUpstream4KeyTcp = new TestUpstream4Key.Builder() + .setProto(IPPROTO_TCP).build(); + final Tether4Key expectedDownstream4KeyTcp = new TestDownstream4Key.Builder() + .setProto(IPPROTO_TCP).build(); + final Tether4Value expectedUpstream4ValueTcp = new TestUpstream4Value.Builder().build(); + final Tether4Value expectedDownstream4ValueTcp = new TestDownstream4Value.Builder().build(); - final Tether4Key expectedUpstream4KeyUdp = makeUpstream4Key(IPPROTO_UDP); - final Tether4Key expectedDownstream4KeyUdp = makeDownstream4Key(IPPROTO_UDP); - final Tether4Value expectedUpstream4ValueUdp = makeUpstream4Value(); - final Tether4Value expectedDownstream4ValueUdp = makeDownstream4Value(); + final Tether4Key expectedUpstream4KeyUdp = new TestUpstream4Key.Builder() + .setProto(IPPROTO_UDP).build(); + final Tether4Key expectedDownstream4KeyUdp = new TestDownstream4Key.Builder() + .setProto(IPPROTO_UDP).build(); + final Tether4Value expectedUpstream4ValueUdp = new TestUpstream4Value.Builder().build(); + final Tether4Value expectedDownstream4ValueUdp = new TestDownstream4Value.Builder().build(); // [1] Adding the first rule on current upstream immediately sends the quota. - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_TCP)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_TCP) + .build()); verifyTetherOffloadSetInterfaceQuota(inOrder, UPSTREAM_IFINDEX, limit, true /* isInit */); inOrder.verify(mBpfUpstream4Map) .insertEntry(eq(expectedUpstream4KeyTcp), eq(expectedUpstream4ValueTcp)); @@ -1421,7 +1562,10 @@ public class BpfCoordinatorTest { inOrder.verifyNoMoreInteractions(); // [2] Adding the second rule on current upstream does not send the quota. - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_UDP)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_UDP) + .build()); verifyNeverTetherOffloadSetInterfaceQuota(inOrder); inOrder.verify(mBpfUpstream4Map) .insertEntry(eq(expectedUpstream4KeyUdp), eq(expectedUpstream4ValueUdp)); @@ -1430,7 +1574,10 @@ public class BpfCoordinatorTest { inOrder.verifyNoMoreInteractions(); // [3] Removing the second rule on current upstream does not send the quota. - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_DELETE, IPPROTO_UDP)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_DELETE) + .setProto(IPPROTO_UDP) + .build()); verifyNeverTetherOffloadSetInterfaceQuota(inOrder); inOrder.verify(mBpfUpstream4Map).deleteEntry(eq(expectedUpstream4KeyUdp)); inOrder.verify(mBpfDownstream4Map).deleteEntry(eq(expectedDownstream4KeyUdp)); @@ -1439,7 +1586,10 @@ public class BpfCoordinatorTest { // [4] Removing the last rule on current upstream immediately sends the cleanup stuff. updateStatsEntryForTetherOffloadGetAndClearStats( buildTestTetherStatsParcel(UPSTREAM_IFINDEX, 0, 0, 0, 0)); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_DELETE, IPPROTO_TCP)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_DELETE) + .setProto(IPPROTO_TCP) + .build()); inOrder.verify(mBpfUpstream4Map).deleteEntry(eq(expectedUpstream4KeyTcp)); inOrder.verify(mBpfDownstream4Map).deleteEntry(eq(expectedDownstream4KeyTcp)); verifyTetherOffloadGetAndClearStats(inOrder, UPSTREAM_IFINDEX); @@ -1472,14 +1622,20 @@ public class BpfCoordinatorTest { final BpfCoordinator coordinator = makeBpfCoordinator(); initBpfCoordinatorForRule4(coordinator); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_TCP)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_TCP) + .build()); verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(UPSTREAM_IFINDEX)), eq(new TetherDevValue(UPSTREAM_IFINDEX))); verify(mBpfDevMap).updateEntry(eq(new TetherDevKey(DOWNSTREAM_IFINDEX)), eq(new TetherDevValue(DOWNSTREAM_IFINDEX))); clearInvocations(mBpfDevMap); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_UDP)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_UDP) + .build()); verify(mBpfDevMap, never()).updateEntry(any(), any()); } @@ -1559,10 +1715,10 @@ public class BpfCoordinatorTest { new TestBpfMap<>(Tether4Key.class, Tether4Value.class); doReturn(bpfUpstream4Map).when(mDeps).getBpfUpstream4Map(); - final Tether4Key tcpKey = makeUpstream4Key(IPPROTO_TCP); - final Tether4Key udpKey = makeUpstream4Key(IPPROTO_UDP); - final Tether4Value tcpValue = makeUpstream4Value(); - final Tether4Value udpValue = makeUpstream4Value(); + final Tether4Key tcpKey = new TestUpstream4Key.Builder().setProto(IPPROTO_TCP).build(); + final Tether4Key udpKey = new TestUpstream4Key.Builder().setProto(IPPROTO_UDP).build(); + final Tether4Value tcpValue = new TestUpstream4Value.Builder().build(); + final Tether4Value udpValue = new TestUpstream4Value.Builder().build(); checkRefreshConntrackTimeout(bpfUpstream4Map, tcpKey, tcpValue, udpKey, udpValue); } @@ -1575,10 +1731,10 @@ public class BpfCoordinatorTest { new TestBpfMap<>(Tether4Key.class, Tether4Value.class); doReturn(bpfDownstream4Map).when(mDeps).getBpfDownstream4Map(); - final Tether4Key tcpKey = makeDownstream4Key(IPPROTO_TCP); - final Tether4Key udpKey = makeDownstream4Key(IPPROTO_UDP); - final Tether4Value tcpValue = makeDownstream4Value(); - final Tether4Value udpValue = makeDownstream4Value(); + final Tether4Key tcpKey = new TestDownstream4Key.Builder().setProto(IPPROTO_TCP).build(); + final Tether4Key udpKey = new TestDownstream4Key.Builder().setProto(IPPROTO_UDP).build(); + final Tether4Value tcpValue = new TestDownstream4Value.Builder().build(); + final Tether4Value udpValue = new TestDownstream4Value.Builder().build(); checkRefreshConntrackTimeout(bpfDownstream4Map, tcpKey, tcpValue, udpKey, udpValue); } @@ -1592,26 +1748,46 @@ public class BpfCoordinatorTest { final short offloadedPort = 42; assertFalse(CollectionUtils.contains(NON_OFFLOADED_UPSTREAM_IPV4_TCP_PORTS, offloadedPort)); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_TCP, offloadedPort)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_TCP) + .setRemotePort(offloadedPort) + .build()); verify(mBpfUpstream4Map).insertEntry(any(), any()); verify(mBpfDownstream4Map).insertEntry(any(), any()); clearInvocations(mBpfUpstream4Map, mBpfDownstream4Map); for (final short port : NON_OFFLOADED_UPSTREAM_IPV4_TCP_PORTS) { - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_TCP, port)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_TCP) + .setRemotePort(port) + .build()); verify(mBpfUpstream4Map, never()).insertEntry(any(), any()); verify(mBpfDownstream4Map, never()).insertEntry(any(), any()); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_DELETE, IPPROTO_TCP, port)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_DELETE) + .setProto(IPPROTO_TCP) + .setRemotePort(port) + .build()); verify(mBpfUpstream4Map, never()).deleteEntry(any()); verify(mBpfDownstream4Map, never()).deleteEntry(any()); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_NEW, IPPROTO_UDP, port)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_NEW) + .setProto(IPPROTO_UDP) + .setRemotePort(port) + .build()); verify(mBpfUpstream4Map).insertEntry(any(), any()); verify(mBpfDownstream4Map).insertEntry(any(), any()); clearInvocations(mBpfUpstream4Map, mBpfDownstream4Map); - mConsumer.accept(makeTestConntrackEvent(IPCTNL_MSG_CT_DELETE, IPPROTO_UDP, port)); + mConsumer.accept(new TestConntrackEvent.Builder() + .setMsgType(IPCTNL_MSG_CT_DELETE) + .setProto(IPPROTO_UDP) + .setRemotePort(port) + .build()); verify(mBpfUpstream4Map).deleteEntry(any()); verify(mBpfDownstream4Map).deleteEntry(any()); clearInvocations(mBpfUpstream4Map, mBpfDownstream4Map);