Add test for tetherOffloadClient{Add, Remove, Clear} am: dad664748a

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1744606

Change-Id: Ifb777d6cccdd15ee3a5c0af81c9541d7c54ebdc6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hungming Chen
2022-03-30 12:12:10 +00:00
committed by Automerger Merge Worker
2 changed files with 98 additions and 11 deletions

View File

@@ -2033,5 +2033,13 @@ public class BpfCoordinator {
return mBpfConntrackEventConsumer;
}
// Return tethering client information. This is used for testing only.
@NonNull
@VisibleForTesting
final HashMap<IpServer, HashMap<Inet4Address, ClientInfo>>
getTetherClientsForTesting() {
return mTetherClients;
}
private static native String[] getBpfCounterNames();
}

View File

@@ -224,8 +224,6 @@ public class BpfCoordinatorTest {
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);
@@ -250,8 +248,6 @@ public class BpfCoordinatorTest {
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);
@@ -279,8 +275,6 @@ public class BpfCoordinatorTest {
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);
@@ -301,8 +295,6 @@ public class BpfCoordinatorTest {
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);
@@ -321,8 +313,6 @@ public class BpfCoordinatorTest {
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);
@@ -377,6 +367,7 @@ public class BpfCoordinatorTest {
// Late init since the object must be initialized by the BPF coordinator instance because
// it has to access the non-static function of BPF coordinator.
private BpfConntrackEventConsumer mConsumer;
private HashMap<IpServer, HashMap<Inet4Address, ClientInfo>> mTetherClients;
private long mElapsedRealtimeNanos = 0;
private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
@@ -482,6 +473,8 @@ public class BpfCoordinatorTest {
final BpfCoordinator coordinator = new BpfCoordinator(mDeps);
mConsumer = coordinator.getBpfConntrackEventConsumerForTesting();
mTetherClients = coordinator.getTetherClientsForTesting();
final ArgumentCaptor<BpfCoordinator.BpfTetherStatsProvider>
tetherStatsProviderCaptor =
ArgumentCaptor.forClass(BpfCoordinator.BpfTetherStatsProvider.class);
@@ -1943,14 +1936,41 @@ public class BpfCoordinatorTest {
assertEquals(DOWNSTREAM4_RULE_VALUE_B, mBpfDownstream4Map.getValue(
DOWNSTREAM4_RULE_KEY_B));
// Clear client information for the first downstream only.
assertNull(mTetherClients.get(mIpServer));
assertNotNull(mTetherClients.get(mIpServer2));
// [2] Remove the second downstream. Remove the rule set B which is on the second
// downstream.
coordinator.tetherOffloadClientClear(mIpServer2);
assertNull(mBpfUpstream4Map.getValue(UPSTREAM4_RULE_KEY_B));
assertNull(mBpfDownstream4Map.getValue(DOWNSTREAM4_RULE_KEY_B));
// Clear client information for the second downstream.
assertNull(mTetherClients.get(mIpServer2));
}
private void asseertClientInfoExist(@NonNull IpServer ipServer,
@NonNull ClientInfo clientInfo) {
HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
assertNotNull(clients);
assertEquals(clientInfo, clients.get(clientInfo.clientAddress));
}
// Although either ClientInfo for a given downstream (IpServer) is not found or a given
// client address is not found on a given downstream can be treated "ClientInfo not
// exist", we still want to know the real reason exactly. For example, we don't the
// exact reason in the following:
// assertNull(clients == null ? clients : clients.get(clientInfo.clientAddress));
// This helper only verifies the case that the downstream still has at least one client.
// In other words, ClientInfo for a given IpServer has not been removed yet.
private void asseertClientInfoNotExist(@NonNull IpServer ipServer,
@NonNull ClientInfo clientInfo) {
HashMap<Inet4Address, ClientInfo> clients = mTetherClients.get(ipServer);
assertNotNull(clients);
assertNull(clients.get(clientInfo.clientAddress));
}
// TODO: check the client information is not removed.
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)
public void testTetherOffloadRule4Clear_ChangeOrRemoveUpstream() throws Exception {
@@ -1982,5 +2002,64 @@ public class BpfCoordinatorTest {
// all rules.
setUpstreamInformationTo(coordinator, INVALID_IFINDEX);
checkRule4NotExistInUpstreamDownstreamMap();
// Client information should be not deleted.
asseertClientInfoExist(mIpServer, CLIENT_INFO_A);
asseertClientInfoExist(mIpServer2, CLIENT_INFO_B);
}
@Test
@IgnoreUpTo(Build.VERSION_CODES.R)
public void testTetherOffloadClientAddRemove() throws Exception {
final BpfCoordinator coordinator = makeBpfCoordinator();
// [1] Add client information A and B on on the same downstream.
final ClientInfo clientA = new ClientInfo(DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC,
PRIVATE_ADDR, MAC_A);
final ClientInfo clientB = new ClientInfo(DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC,
PRIVATE_ADDR2, MAC_B);
coordinator.tetherOffloadClientAdd(mIpServer, clientA);
coordinator.tetherOffloadClientAdd(mIpServer, clientB);
asseertClientInfoExist(mIpServer, clientA);
asseertClientInfoExist(mIpServer, clientB);
// Add the rules for client A and client B.
final Tether4Key upstream4KeyA = makeUpstream4Key(
DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC, PRIVATE_ADDR, PRIVATE_PORT);
final Tether4Value upstream4ValueA = makeUpstream4Value(PUBLIC_PORT);
final Tether4Key downstream4KeyA = makeDownstream4Key(PUBLIC_PORT);
final Tether4Value downstream4ValueA = makeDownstream4Value(
DOWNSTREAM_IFINDEX, MAC_A, DOWNSTREAM_MAC, PRIVATE_ADDR, PRIVATE_PORT);
final Tether4Key upstream4KeyB = makeUpstream4Key(
DOWNSTREAM_IFINDEX, DOWNSTREAM_MAC2, PRIVATE_ADDR2, PRIVATE_PORT2);
final Tether4Value upstream4ValueB = makeUpstream4Value(PUBLIC_PORT2);
final Tether4Key downstream4KeyB = makeDownstream4Key(PUBLIC_PORT2);
final Tether4Value downstream4ValueB = makeDownstream4Value(
DOWNSTREAM_IFINDEX, MAC_B, DOWNSTREAM_MAC2, PRIVATE_ADDR2, PRIVATE_PORT2);
mBpfUpstream4Map.insertEntry(upstream4KeyA, upstream4ValueA);
mBpfDownstream4Map.insertEntry(downstream4KeyA, downstream4ValueA);
mBpfUpstream4Map.insertEntry(upstream4KeyB, upstream4ValueB);
mBpfDownstream4Map.insertEntry(downstream4KeyB, downstream4ValueB);
// [2] Remove client information A. Only the rules on client A should be removed and
// the rules on client B should exist.
coordinator.tetherOffloadClientRemove(mIpServer, clientA);
asseertClientInfoNotExist(mIpServer, clientA);
asseertClientInfoExist(mIpServer, clientB);
assertNull(mBpfUpstream4Map.getValue(upstream4KeyA));
assertNull(mBpfDownstream4Map.getValue(downstream4KeyA));
assertEquals(upstream4ValueB, mBpfUpstream4Map.getValue(upstream4KeyB));
assertEquals(downstream4ValueB, mBpfDownstream4Map.getValue(downstream4KeyB));
// [3] Remove client information B. The rules on client B should be removed.
// Exactly, ClientInfo for a given IpServer is removed because the last client B
// has been removed from the downstream. Can't use the helper #asseertClientInfoExist
// to check because the container ClientInfo for a given downstream has been removed.
// See #asseertClientInfoExist.
coordinator.tetherOffloadClientRemove(mIpServer, clientB);
assertNull(mTetherClients.get(mIpServer));
assertNull(mBpfUpstream4Map.getValue(upstream4KeyB));
assertNull(mBpfDownstream4Map.getValue(downstream4KeyB));
}
}