It's still doing the calculations in milliseconds, which will be updated in follow-up CLs. Bug: webrtc:15593 Change-Id: I7fb93d4687d58f409db182db40db720d82feb3dd Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/325524 Commit-Queue: Victor Boivie <boivie@webrtc.org> Reviewed-by: Florent Castelli <orphis@webrtc.org> Cr-Commit-Position: refs/heads/main@{#41074}
184 lines
6.5 KiB
C++
184 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
#include "net/dcsctp/tx/retransmission_timeout.h"
|
|
|
|
#include "net/dcsctp/public/dcsctp_options.h"
|
|
#include "rtc_base/gunit.h"
|
|
#include "test/gmock.h"
|
|
|
|
namespace dcsctp {
|
|
namespace {
|
|
using ::webrtc::TimeDelta;
|
|
|
|
constexpr TimeDelta kMaxRtt = TimeDelta::Millis(8'000);
|
|
constexpr TimeDelta kInitialRto = TimeDelta::Millis(200);
|
|
constexpr TimeDelta kMaxRto = TimeDelta::Millis(800);
|
|
constexpr TimeDelta kMinRto = TimeDelta::Millis(120);
|
|
constexpr TimeDelta kMinRttVariance = TimeDelta::Millis(220);
|
|
|
|
DcSctpOptions MakeOptions() {
|
|
DcSctpOptions options;
|
|
options.rtt_max = DurationMs(kMaxRtt);
|
|
options.rto_initial = DurationMs(kInitialRto);
|
|
options.rto_max = DurationMs(kMaxRto);
|
|
options.rto_min = DurationMs(kMinRto);
|
|
options.min_rtt_variance = DurationMs(kMinRttVariance);
|
|
return options;
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, HasValidInitialRto) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
EXPECT_EQ(rto_.rto(), kInitialRto);
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, HasValidInitialSrtt) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
EXPECT_EQ(rto_.srtt(), kInitialRto);
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, NegativeValuesDoNotAffectRTO) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
// Initial negative value
|
|
rto_.ObserveRTT(TimeDelta::Millis(-10));
|
|
EXPECT_EQ(rto_.rto(), kInitialRto);
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
// Subsequent negative value
|
|
rto_.ObserveRTT(TimeDelta::Millis(-10));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, TooLargeValuesDoNotAffectRTO) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
// Initial too large value
|
|
rto_.ObserveRTT(kMaxRtt + TimeDelta::Millis(100));
|
|
EXPECT_EQ(rto_.rto(), kInitialRto);
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
// Subsequent too large value
|
|
rto_.ObserveRTT(kMaxRtt + TimeDelta::Millis(100));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, WillNeverGoBelowMinimumRto) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
for (int i = 0; i < 1000; ++i) {
|
|
rto_.ObserveRTT(TimeDelta::Millis(1));
|
|
}
|
|
EXPECT_GE(rto_.rto(), kMinRto);
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, WillNeverGoAboveMaximumRto) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
for (int i = 0; i < 1000; ++i) {
|
|
rto_.ObserveRTT(kMaxRtt - TimeDelta::Millis(1));
|
|
// Adding jitter, which would make it RTO be well above RTT.
|
|
rto_.ObserveRTT(kMaxRtt - TimeDelta::Millis(100));
|
|
}
|
|
EXPECT_LE(rto_.rto(), kMaxRto);
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, CalculatesRtoForStableRtt) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
rto_.ObserveRTT(TimeDelta::Millis(128));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(344));
|
|
rto_.ObserveRTT(TimeDelta::Millis(123));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(344));
|
|
rto_.ObserveRTT(TimeDelta::Millis(125));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(344));
|
|
rto_.ObserveRTT(TimeDelta::Millis(127));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(344));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, CalculatesRtoForUnstableRtt) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
rto_.ObserveRTT(TimeDelta::Millis(402));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(622));
|
|
rto_.ObserveRTT(TimeDelta::Millis(728));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(800));
|
|
rto_.ObserveRTT(TimeDelta::Millis(89));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(800));
|
|
rto_.ObserveRTT(TimeDelta::Millis(126));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(800));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, WillStabilizeAfterAWhile) {
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
rto_.ObserveRTT(TimeDelta::Millis(402));
|
|
rto_.ObserveRTT(TimeDelta::Millis(728));
|
|
rto_.ObserveRTT(TimeDelta::Millis(89));
|
|
rto_.ObserveRTT(TimeDelta::Millis(126));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(800));
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(800));
|
|
rto_.ObserveRTT(TimeDelta::Millis(122));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(710));
|
|
rto_.ObserveRTT(TimeDelta::Millis(123));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(631));
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(562));
|
|
rto_.ObserveRTT(TimeDelta::Millis(122));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(505));
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(454));
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(410));
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(372));
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(367));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, WillAlwaysStayAboveRTT) {
|
|
// In simulations, it's quite common to have a very stable RTT, and having an
|
|
// RTO at the same value will cause issues as expiry timers will be scheduled
|
|
// to be expire exactly when a packet is supposed to arrive. The RTO must be
|
|
// larger than the RTT. In non-simulated environments, this is a non-issue as
|
|
// any jitter will increase the RTO.
|
|
RetransmissionTimeout rto_(MakeOptions());
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
}
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(344));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, CanSpecifySmallerMinimumRttVariance) {
|
|
DcSctpOptions options = MakeOptions();
|
|
options.min_rtt_variance =
|
|
DurationMs(kMinRttVariance - TimeDelta::Millis(100));
|
|
RetransmissionTimeout rto_(options);
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
}
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(244));
|
|
}
|
|
|
|
TEST(RetransmissionTimeoutTest, CanSpecifyLargerMinimumRttVariance) {
|
|
DcSctpOptions options = MakeOptions();
|
|
options.min_rtt_variance =
|
|
DurationMs(kMinRttVariance + TimeDelta::Millis(100));
|
|
RetransmissionTimeout rto_(options);
|
|
|
|
for (int i = 0; i < 1000; ++i) {
|
|
rto_.ObserveRTT(TimeDelta::Millis(124));
|
|
}
|
|
EXPECT_EQ(rto_.rto(), TimeDelta::Millis(444));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace dcsctp
|