/* * Copyright (c) 2026 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. */ #ifndef MODULES_CONGESTION_CONTROLLER_ECT1_POLICY_H_ #define MODULES_CONGESTION_CONTROLLER_ECT1_POLICY_H_ #include #include "api/units/time_delta.h" #include "api/units/timestamp.h" namespace webrtc { // Decides if RTP packets should be sent with an ECT(1) marking, for example to // support L4S as described in RFC 9331. // // ECT(1) is used if the negotiated feedback format reports the ECN marking of // received packets and the congestion controller adapts to ECN. It is disabled // until the network route changes if the network path bleaches the marking to // Not-ECT, or if feedback stops arriving while packets are sent as ECT(1). The // latter can happen when feedback is lost due to temporary network issues, so // it is retried once per route. // // A path that drops ECT(1) from the start is detected quickly, since no // feedback has been received on the route yet. Once ECT(1) is known to work, // a much longer time without feedback is needed, so that a temporary outage // is not mistaken for the same thing. A working path can start dropping the // marking mid call, since traffic can be rerouted over a different middlebox // without the ICE candidate pair changing. class Ect1Policy { public: // Whether the remote peer reports the ECN marking of received packets back to // the sender, for example with the RTCP feedback message in RFC 8888. void SetFeedbackSupportsEcn(bool supports_ecn); // Whether the congestion controller reacts to reported CE markings. void SetCongestionControllerSupportsEcn(bool supports_ecn); void OnNetworkRouteChanged(); // `has_bleached_ect1` is true if a feedback report showed at least one // packet that was sent as ECT(1) arriving as Not-ECT. `has_preserved_ect1` // is true if it showed at least one arriving still ECN capable. Both are // false if the report said nothing about the marking, which is the case // until the first packet sent as ECT(1) is reported received. void OnPacketsFeedback(bool has_bleached_ect1, bool has_preserved_ect1); // Must be called for every sent RTP packet. `sent_as_ect1` is whether the // packet actually carried the marking. void OnPacketSent(Timestamp send_time, bool sent_as_ect1); bool ShouldSendEct1() const; private: void LogIfDecisionChanged(); // How long to wait for feedback before assuming ECT(1) packets are dropped. TimeDelta Ect1FeedbackTimeout() const; bool feedback_supports_ecn_ = false; bool congestion_controller_supports_ecn_ = false; bool route_bleaches_ect1_ = false; // When the route was judged to drop ECT(1) packets. Unset if it was not. std::optional ect1_drop_detected_time_; // Whether the single retry allowed on this route has been used. bool ect1_drop_retried_ = false; bool ect1_preserved_on_route_ = false; // Does not count time when nothing was sent. TimeDelta time_sending_ect1_without_feedback_ = TimeDelta::Zero(); // Send time of the last RTP packet, whatever its marking. std::optional last_send_time_; bool logged_send_ect1_ = false; }; } // namespace webrtc #endif // MODULES_CONGESTION_CONTROLLER_ECT1_POLICY_H_