diff --git a/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index 206523a6e9..3619253749 100644
--- a/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -64,6 +64,12 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor {
private static final int PACKET_LOSS_PERCENT_UNAVAILABLE = -1;
+ // Ignore the packet loss detection result if the expected packet number is smaller than 10.
+ // Solarwinds NPM uses 10 ICMP echos to calculate packet loss rate (as per
+ // https://thwack.solarwinds.com/products/network-performance-monitor-npm/f/forum/63829/how-is-packet-loss-calculated)
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int MIN_VALID_EXPECTED_RX_PACKET_NUM = 10;
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(
prefix = {"PACKET_LOSS_"},
@@ -85,6 +91,8 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor {
*
* - The replay window did not proceed and thus all packets might have been delivered out of
* order
+ *
- The expected received packet number is too small and thus the detection result is not
+ * reliable
*
- There are unexpected errors
*
*/
@@ -113,7 +121,7 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor {
private static final int MAX_SEQ_NUM_INCREASE_DEFAULT_DISABLED = -1;
private long mPollIpSecStateIntervalMs;
- private final int mPacketLossRatePercentThreshold;
+ private int mPacketLossRatePercentThreshold;
private int mMaxSeqNumIncreasePerSecond;
@NonNull private final Handler mHandler;
@@ -273,6 +281,7 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor {
mPollIpSecStateIntervalMs = getPollIpSecStateIntervalMs(carrierConfig);
if (Flags.handleSeqNumLeap()) {
+ mPacketLossRatePercentThreshold = getPacketLossRatePercentThreshold(carrierConfig);
mMaxSeqNumIncreasePerSecond = getMaxSeqNumIncreasePerSecond(carrierConfig);
}
}
@@ -476,6 +485,11 @@ public class IpSecPacketLossDetector extends NetworkMetricMonitor {
+ " actualPktCntDiff: "
+ actualPktCntDiff);
+ if (Flags.handleSeqNumLeap() && expectedPktCntDiff < MIN_VALID_EXPECTED_RX_PACKET_NUM) {
+ // The sample size is too small to ensure a reliable detection result
+ return PacketLossCalculationResult.invalid();
+ }
+
if (expectedPktCntDiff < 0
|| expectedPktCntDiff == 0
|| actualPktCntDiff < 0
diff --git a/Vcn/tests/unit/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java b/Vcn/tests/unit/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
index 68a2ad7e1a..c8b60e5c33 100644
--- a/Vcn/tests/unit/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
+++ b/Vcn/tests/unit/java/com/android/server/vcn/routeselection/IpSecPacketLossDetectorTest.java
@@ -20,6 +20,7 @@ import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_MAX_SEQ_NUM_INCREASE_PER_SECOND_KEY;
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY;
+import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.MIN_VALID_EXPECTED_RX_PACKET_NUM;
import static com.android.server.vcn.routeselection.IpSecPacketLossDetector.getMaxSeqNumIncreasePerSecond;
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
@@ -436,6 +437,21 @@ public class IpSecPacketLossDetectorTest extends NetworkEvaluationTestBase {
mTransformStateInitial, 3000, 2000, 2000, PacketLossCalculationResult.invalid());
}
+ @Test
+ public void testGetPacketLossRate_expectedPacketNumTooFew() throws Exception {
+ final int oldRxNo = 4096;
+ final int oldPktCnt = 4096;
+ final int pktCntDiff = MIN_VALID_EXPECTED_RX_PACKET_NUM - 1;
+ final byte[] bitmapReceiveAll = newReplayBitmap(4096);
+
+ final IpSecTransformState oldState =
+ newTransformState(oldRxNo, oldPktCnt, bitmapReceiveAll);
+ final IpSecTransformState newState =
+ newTransformState(oldRxNo + pktCntDiff, oldPktCnt + pktCntDiff, bitmapReceiveAll);
+
+ checkGetPacketLossRate(oldState, newState, PacketLossCalculationResult.invalid());
+ }
+
@Test
public void testGetPacketLossRate_againstInitialState() throws Exception {
checkGetPacketLossRate(mTransformStateInitial, 7000, 7001, 4096, 0);