blob: 871914c86d1070a238658de48a41d82792df33ab [file] [edit]
/*
* 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 <optional>
#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<Timestamp> 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<Timestamp> last_send_time_;
bool logged_send_ect1_ = false;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_ECT1_POLICY_H_