Merge "BpfCoordinator: avoid attach/deatach duplicate downstream program"
This commit is contained in:
@@ -905,10 +905,16 @@ public class BpfCoordinator {
|
|||||||
|
|
||||||
if (forwardingPairExists(intIface, extIface)) return;
|
if (forwardingPairExists(intIface, extIface)) return;
|
||||||
|
|
||||||
|
boolean firstUpstreamForThisDownstream = !isAnyForwardingPairOnDownstream(intIface);
|
||||||
boolean firstDownstreamForThisUpstream = !isAnyForwardingPairOnUpstream(extIface);
|
boolean firstDownstreamForThisUpstream = !isAnyForwardingPairOnUpstream(extIface);
|
||||||
forwardingPairAdd(intIface, extIface);
|
forwardingPairAdd(intIface, extIface);
|
||||||
|
|
||||||
mBpfCoordinatorShim.attachProgram(intIface, UPSTREAM);
|
// Attach if the downstream is the first time to be used in a forwarding pair.
|
||||||
|
// Ex: IPv6 only interface has two forwarding pair, iface and v4-iface, on the
|
||||||
|
// same downstream.
|
||||||
|
if (firstUpstreamForThisDownstream) {
|
||||||
|
mBpfCoordinatorShim.attachProgram(intIface, UPSTREAM);
|
||||||
|
}
|
||||||
// Attach if the upstream is the first time to be used in a forwarding pair.
|
// Attach if the upstream is the first time to be used in a forwarding pair.
|
||||||
if (firstDownstreamForThisUpstream) {
|
if (firstDownstreamForThisUpstream) {
|
||||||
mBpfCoordinatorShim.attachProgram(extIface, DOWNSTREAM);
|
mBpfCoordinatorShim.attachProgram(extIface, DOWNSTREAM);
|
||||||
@@ -922,7 +928,9 @@ public class BpfCoordinator {
|
|||||||
forwardingPairRemove(intIface, extIface);
|
forwardingPairRemove(intIface, extIface);
|
||||||
|
|
||||||
// Detaching program may fail because the interface has been removed already.
|
// Detaching program may fail because the interface has been removed already.
|
||||||
mBpfCoordinatorShim.detachProgram(intIface);
|
if (!isAnyForwardingPairOnDownstream(intIface)) {
|
||||||
|
mBpfCoordinatorShim.detachProgram(intIface);
|
||||||
|
}
|
||||||
// Detach if no more forwarding pair is using the upstream.
|
// Detach if no more forwarding pair is using the upstream.
|
||||||
if (!isAnyForwardingPairOnUpstream(extIface)) {
|
if (!isAnyForwardingPairOnUpstream(extIface)) {
|
||||||
mBpfCoordinatorShim.detachProgram(extIface);
|
mBpfCoordinatorShim.detachProgram(extIface);
|
||||||
@@ -1827,6 +1835,13 @@ public class BpfCoordinator {
|
|||||||
return mForwardingPairs.containsKey(extIface);
|
return mForwardingPairs.containsKey(extIface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAnyForwardingPairOnDownstream(@NonNull String intIface) {
|
||||||
|
for (final HashSet downstreams : mForwardingPairs.values()) {
|
||||||
|
if (downstreams.contains(intIface)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private NetworkStats buildNetworkStats(@NonNull StatsType type, int ifIndex,
|
private NetworkStats buildNetworkStats(@NonNull StatsType type, int ifIndex,
|
||||||
@NonNull final ForwardedStats diff) {
|
@NonNull final ForwardedStats diff) {
|
||||||
|
|||||||
@@ -1277,47 +1277,62 @@ public class BpfCoordinatorTest {
|
|||||||
try {
|
try {
|
||||||
final String intIface1 = "wlan1";
|
final String intIface1 = "wlan1";
|
||||||
final String intIface2 = "rndis0";
|
final String intIface2 = "rndis0";
|
||||||
final String extIface = "rmnet_data0";
|
final String extIface1 = "rmnet_data0";
|
||||||
|
final String extIface2 = "v4-rmnet_data0";
|
||||||
final String virtualIface = "ipsec0";
|
final String virtualIface = "ipsec0";
|
||||||
final BpfUtils mockMarkerBpfUtils = staticMockMarker(BpfUtils.class);
|
final BpfUtils mockMarkerBpfUtils = staticMockMarker(BpfUtils.class);
|
||||||
final BpfCoordinator coordinator = makeBpfCoordinator();
|
final BpfCoordinator coordinator = makeBpfCoordinator();
|
||||||
|
|
||||||
// [1] Add the forwarding pair <wlan1, rmnet_data0>. Expect that attach both wlan1 and
|
// [1] Add the forwarding pair <wlan1, rmnet_data0>. Expect that attach both wlan1 and
|
||||||
// rmnet_data0.
|
// rmnet_data0.
|
||||||
coordinator.maybeAttachProgram(intIface1, extIface);
|
coordinator.maybeAttachProgram(intIface1, extIface1);
|
||||||
ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface, DOWNSTREAM));
|
ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface1, DOWNSTREAM));
|
||||||
ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM));
|
ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM));
|
||||||
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
// [2] Add the forwarding pair <wlan1, rmnet_data0> again. Expect no more action.
|
// [2] Add the forwarding pair <wlan1, rmnet_data0> again. Expect no more action.
|
||||||
coordinator.maybeAttachProgram(intIface1, extIface);
|
coordinator.maybeAttachProgram(intIface1, extIface1);
|
||||||
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
// [3] Add the forwarding pair <rndis0, rmnet_data0>. Expect that attach rndis0 only.
|
// [3] Add the forwarding pair <rndis0, rmnet_data0>. Expect that attach rndis0 only.
|
||||||
coordinator.maybeAttachProgram(intIface2, extIface);
|
coordinator.maybeAttachProgram(intIface2, extIface1);
|
||||||
ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface2, UPSTREAM));
|
ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface2, UPSTREAM));
|
||||||
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
// [4] Remove the forwarding pair <rndis0, rmnet_data0>. Expect detach rndis0 only.
|
// [4] Add the forwarding pair <rndis0, v4-rmnet_data0>. Expect that attach
|
||||||
coordinator.maybeDetachProgram(intIface2, extIface);
|
// v4-rmnet_data0 only.
|
||||||
|
coordinator.maybeAttachProgram(intIface2, extIface2);
|
||||||
|
ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface2, DOWNSTREAM));
|
||||||
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
|
// [5] Remove the forwarding pair <rndis0, v4-rmnet_data0>. Expect detach
|
||||||
|
// v4-rmnet_data0 only.
|
||||||
|
coordinator.maybeDetachProgram(intIface2, extIface2);
|
||||||
|
ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface2));
|
||||||
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
|
// [6] Remove the forwarding pair <rndis0, rmnet_data0>. Expect detach rndis0 only.
|
||||||
|
coordinator.maybeDetachProgram(intIface2, extIface1);
|
||||||
ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface2));
|
ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface2));
|
||||||
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
// [5] Remove the forwarding pair <wlan1, rmnet_data0>. Expect that detach both wlan1
|
// [7] Remove the forwarding pair <wlan1, rmnet_data0>. Expect that detach both wlan1
|
||||||
// and rmnet_data0.
|
// and rmnet_data0.
|
||||||
coordinator.maybeDetachProgram(intIface1, extIface);
|
coordinator.maybeDetachProgram(intIface1, extIface1);
|
||||||
ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface));
|
ExtendedMockito.verify(() -> BpfUtils.detachProgram(extIface1));
|
||||||
ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface1));
|
ExtendedMockito.verify(() -> BpfUtils.detachProgram(intIface1));
|
||||||
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|
||||||
// [6] Skip attaching if upstream is virtual interface.
|
// [8] Skip attaching if upstream is virtual interface.
|
||||||
coordinator.maybeAttachProgram(intIface1, virtualIface);
|
coordinator.maybeAttachProgram(intIface1, virtualIface);
|
||||||
ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface, DOWNSTREAM), never());
|
ExtendedMockito.verify(() -> BpfUtils.attachProgram(extIface1, DOWNSTREAM), never());
|
||||||
ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM), never());
|
ExtendedMockito.verify(() -> BpfUtils.attachProgram(intIface1, UPSTREAM), never());
|
||||||
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
ExtendedMockito.verifyNoMoreInteractions(mockMarkerBpfUtils);
|
||||||
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
ExtendedMockito.clearInvocations(mockMarkerBpfUtils);
|
||||||
|
|||||||
Reference in New Issue
Block a user