aboutsummaryrefslogtreecommitdiff
path: root/net/dcsctp/tx/retransmission_timeout.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/dcsctp/tx/retransmission_timeout.cc')
-rw-r--r--net/dcsctp/tx/retransmission_timeout.cc69
1 files changed, 69 insertions, 0 deletions
diff --git a/net/dcsctp/tx/retransmission_timeout.cc b/net/dcsctp/tx/retransmission_timeout.cc
new file mode 100644
index 0000000000..7d545a07d0
--- /dev/null
+++ b/net/dcsctp/tx/retransmission_timeout.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 <cmath>
+#include <cstdint>
+
+#include "net/dcsctp/public/dcsctp_options.h"
+
+namespace dcsctp {
+namespace {
+// https://tools.ietf.org/html/rfc4960#section-15
+constexpr double kRtoAlpha = 0.125;
+constexpr double kRtoBeta = 0.25;
+} // namespace
+
+RetransmissionTimeout::RetransmissionTimeout(const DcSctpOptions& options)
+ : min_rto_(*options.rto_min),
+ max_rto_(*options.rto_max),
+ max_rtt_(*options.rtt_max),
+ rto_(*options.rto_initial) {}
+
+void RetransmissionTimeout::ObserveRTT(DurationMs measured_rtt) {
+ double rtt = *measured_rtt;
+
+ // Unrealistic values will be skipped. If a wrongly measured (or otherwise
+ // corrupt) value was processed, it could change the state in a way that would
+ // take a very long time to recover.
+ if (rtt < 0.0 || rtt > max_rtt_) {
+ return;
+ }
+
+ if (first_measurement_) {
+ // https://tools.ietf.org/html/rfc4960#section-6.3.1
+ // "When the first RTT measurement R is made, set
+ // SRTT <- R,
+ // RTTVAR <- R/2, and
+ // RTO <- SRTT + 4 * RTTVAR."
+ srtt_ = rtt;
+ rttvar_ = rtt * 0.5;
+ rto_ = srtt_ + 4 * rttvar_;
+ first_measurement_ = false;
+ } else {
+ // https://tools.ietf.org/html/rfc4960#section-6.3.1
+ // "When a new RTT measurement R' is made, set
+ // RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'|
+ // SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R'
+ // RTO <- SRTT + 4 * RTTVAR."
+ rttvar_ = (1 - kRtoBeta) * rttvar_ + kRtoBeta * std::abs(srtt_ - rtt);
+ srtt_ = (1 - kRtoAlpha) * srtt_ + kRtoAlpha * rtt;
+ rto_ = srtt_ + 4 * rttvar_;
+ }
+
+ // If the RTO becomes smaller or equal to RTT, expiration timers will be
+ // scheduled at the same time as packets are expected. Only happens in
+ // extremely stable RTTs, i.e. in simulations.
+ rto_ = std::fmax(rto_, rtt + 1);
+
+ // Clamp RTO between min and max.
+ rto_ = std::fmin(std::fmax(rto_, min_rto_), max_rto_);
+}
+} // namespace dcsctp