diff options
| -rw-r--r-- | services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java | 108 | ||||
| -rw-r--r-- | tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java | 40 |
2 files changed, 129 insertions, 19 deletions
diff --git a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java index ed9fa65dee15..c5d333317013 100644 --- a/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java +++ b/services/core/java/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java @@ -16,8 +16,10 @@ package com.android.server.vcn.routeselection; +import static com.android.internal.annotations.VisibleForTesting.Visibility; import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.BroadcastReceiver; @@ -38,6 +40,10 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; import com.android.server.vcn.VcnContext; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.BitSet; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -56,8 +62,32 @@ import java.util.concurrent.TimeUnit; public class IpSecPacketLossDetector extends NetworkMetricMonitor { private static final String TAG = IpSecPacketLossDetector.class.getSimpleName(); - @VisibleForTesting(visibility = Visibility.PRIVATE) - static final int PACKET_LOSS_UNAVALAIBLE = -1; + private static final int PACKET_LOSS_PERCENT_UNAVAILABLE = -1; + + @Retention(RetentionPolicy.SOURCE) + @IntDef( + prefix = {"PACKET_LOSS_"}, + value = { + PACKET_LOSS_RATE_VALID, + PACKET_LOSS_RATE_INVALID, + }) + @Target({ElementType.TYPE_USE}) + private @interface PacketLossResultType {} + + /** Indicates a valid packet loss rate is available */ + private static final int PACKET_LOSS_RATE_VALID = 0; + + /** + * Indicates that the detector cannot get a valid packet loss rate due to one of the following + * reasons: + * + * <ul> + * <li>The replay window did not proceed and thus all packets might have been delivered out of + * order + * <li>There are unexpected errors + * </ul> + */ + private static final int PACKET_LOSS_RATE_INVALID = 1; // For VoIP, losses between 5% and 10% of the total packet stream will affect the quality // significantly (as per "Computer Networking for LANS to WANS: Hardware, Software and @@ -307,24 +337,24 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { return; } - final int packetLossRate = + final PacketLossCalculationResult calculateResult = mPacketLossCalculator.getPacketLossRatePercentage( mLastIpSecTransformState, state, getLogPrefix()); - if (packetLossRate == PACKET_LOSS_UNAVALAIBLE) { + if (calculateResult.getResultType() == PACKET_LOSS_RATE_INVALID) { return; } final String logMsg = - "packetLossRate: " - + packetLossRate + "calculateResult: " + + calculateResult + "% in the past " + (state.getTimestampMillis() - mLastIpSecTransformState.getTimestampMillis()) + "ms"; mLastIpSecTransformState = state; - if (packetLossRate < mPacketLossRatePercentThreshold) { + if (calculateResult.getPacketLossRatePercent() < mPacketLossRatePercentThreshold) { logV(logMsg); onValidationResultReceivedInternal(false /* isFailed */); } else { @@ -343,7 +373,7 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { @VisibleForTesting(visibility = Visibility.PRIVATE) public static class PacketLossCalculator { /** Calculate the packet loss rate between two timestamps */ - public int getPacketLossRatePercentage( + public PacketLossCalculationResult getPacketLossRatePercentage( @NonNull IpSecTransformState oldState, @NonNull IpSecTransformState newState, String logPrefix) { @@ -359,7 +389,7 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { if (oldSeqHi == newSeqHi || newSeqHi < replayWindowSize) { // The replay window did not proceed and all packets might have been delivered out // of order - return PACKET_LOSS_UNAVALAIBLE; + return PacketLossCalculationResult.invalid(); } // Get the expected packet count by assuming there is no packet loss. In this case, SA @@ -386,10 +416,11 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { || actualPktCntDiff < 0 || actualPktCntDiff > expectedPktCntDiff) { logWtf(TAG, "Impossible values for expectedPktCntDiff or" + " actualPktCntDiff"); - return PACKET_LOSS_UNAVALAIBLE; + return PacketLossCalculationResult.invalid(); } - return 100 - (int) (actualPktCntDiff * 100 / expectedPktCntDiff); + final int percent = 100 - (int) (actualPktCntDiff * 100 / expectedPktCntDiff); + return PacketLossCalculationResult.valid(percent); } } @@ -409,4 +440,59 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor { private static long getPacketCntInReplayWindow(@NonNull IpSecTransformState state) { return BitSet.valueOf(state.getReplayBitmap()).cardinality(); } + + @VisibleForTesting(visibility = Visibility.PRIVATE) + public static class PacketLossCalculationResult { + @PacketLossResultType private final int mResultType; + private final int mPacketLossRatePercent; + + private PacketLossCalculationResult(@PacketLossResultType int type, int percent) { + mResultType = type; + mPacketLossRatePercent = percent; + } + + /** Construct an instance that contains a valid packet loss rate */ + public static PacketLossCalculationResult valid(int percent) { + return new PacketLossCalculationResult(PACKET_LOSS_RATE_VALID, percent); + } + + /** Construct an instance indicating the inability to get a valid packet loss rate */ + public static PacketLossCalculationResult invalid() { + return new PacketLossCalculationResult( + PACKET_LOSS_RATE_INVALID, PACKET_LOSS_PERCENT_UNAVAILABLE); + } + + @PacketLossResultType + public int getResultType() { + return mResultType; + } + + public int getPacketLossRatePercent() { + return mPacketLossRatePercent; + } + + @Override + public int hashCode() { + return Objects.hash(mResultType, mPacketLossRatePercent); + } + + @Override + public boolean equals(@Nullable Object other) { + if (!(other instanceof PacketLossCalculationResult)) { + return false; + } + + final PacketLossCalculationResult rhs = (PacketLossCalculationResult) other; + return mResultType == rhs.mResultType + && mPacketLossRatePercent == rhs.mPacketLossRatePercent; + } + + @Override + public String toString() { + return "mResultType: " + + mResultType + + " | mPacketLossRatePercent: " + + mPacketLossRatePercent; + } + } } diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java index fdf8fb8d3c41..0a83a53a7b59 100644 --- a/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java +++ b/tests/vcn/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java @@ -19,7 +19,6 @@ package com.android.server.vcn.routeselection; import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY; import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY; -import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.PACKET_LOSS_UNAVALAIBLE; import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper; import static org.junit.Assert.assertEquals; @@ -44,6 +43,7 @@ import android.net.IpSecTransformState; import android.os.OutcomeReceiver; import android.os.PowerManager; +import com.android.server.vcn.routeselection.IpSecPacketLossDetector.PacketLossCalculationResult; import com.android.server.vcn.routeselection.IpSecPacketLossDetector.PacketLossCalculator; import com.android.server.vcn.routeselection.NetworkMetricMonitor.IpSecTransformWrapper; import com.android.server.vcn.routeselection.NetworkMetricMonitor.NetworkMetricMonitorCallback; @@ -293,7 +293,9 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase { } private void checkHandleLossRate( - int mockPacketLossRate, boolean isLastStateExpectedToUpdate, boolean isCallbackExpected) + PacketLossCalculationResult mockPacketLossRate, + boolean isLastStateExpectedToUpdate, + boolean isCallbackExpected) throws Exception { final OutcomeReceiver<IpSecTransformState, RuntimeException> xfrmStateReceiver = startMonitorAndCaptureStateReceiver(); @@ -327,26 +329,32 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase { @Test public void testHandleLossRate_validationPass() throws Exception { checkHandleLossRate( - 2, true /* isLastStateExpectedToUpdate */, true /* isCallbackExpected */); + PacketLossCalculationResult.valid(2), + true /* isLastStateExpectedToUpdate */, + true /* isCallbackExpected */); } @Test public void testHandleLossRate_validationFail() throws Exception { checkHandleLossRate( - 22, true /* isLastStateExpectedToUpdate */, true /* isCallbackExpected */); + PacketLossCalculationResult.valid(22), + true /* isLastStateExpectedToUpdate */, + true /* isCallbackExpected */); verify(mConnectivityManager).reportNetworkConnectivity(mNetwork, false); } @Test public void testHandleLossRate_resultUnavalaible() throws Exception { checkHandleLossRate( - PACKET_LOSS_UNAVALAIBLE, + PacketLossCalculationResult.invalid(), false /* isLastStateExpectedToUpdate */, false /* isCallbackExpected */); } private void checkGetPacketLossRate( - IpSecTransformState oldState, IpSecTransformState newState, int expectedLossRate) + IpSecTransformState oldState, + IpSecTransformState newState, + PacketLossCalculationResult expectedLossRate) throws Exception { assertEquals( expectedLossRate, @@ -362,14 +370,30 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase { throws Exception { final IpSecTransformState newState = newTransformState(rxSeqNo, packetCount, newReplayBitmap(packetInWin)); + checkGetPacketLossRate( + oldState, newState, PacketLossCalculationResult.valid(expectedDataLossRate)); + } + + private void checkGetPacketLossRate( + IpSecTransformState oldState, + int rxSeqNo, + int packetCount, + int packetInWin, + PacketLossCalculationResult expectedDataLossRate) + throws Exception { + final IpSecTransformState newState = + newTransformState(rxSeqNo, packetCount, newReplayBitmap(packetInWin)); checkGetPacketLossRate(oldState, newState, expectedDataLossRate); } @Test public void testGetPacketLossRate_replayWindowUnchanged() throws Exception { checkGetPacketLossRate( - mTransformStateInitial, mTransformStateInitial, PACKET_LOSS_UNAVALAIBLE); - checkGetPacketLossRate(mTransformStateInitial, 3000, 2000, 2000, PACKET_LOSS_UNAVALAIBLE); + mTransformStateInitial, + mTransformStateInitial, + PacketLossCalculationResult.invalid()); + checkGetPacketLossRate( + mTransformStateInitial, 3000, 2000, 2000, PacketLossCalculationResult.invalid()); } @Test |