tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1fec77666a6b27729c339c2b796972faab1e3d7e
parent 500a1c331ce8d9f116fe0f3729163df509f46359
Author: Michael Froman <mfroman@mozilla.com>
Date:   Wed,  8 Oct 2025 23:28:41 -0500

Bug 1993083 - Vendor libwebrtc from ba4a04a43b

Upstream commit: https://webrtc.googlesource.com/src/+/ba4a04a43b1d873ca63fe1c2ff4e42a631922875
    Reland "Introduce NetworkQueue interface"

    This reverts commit 833369b1fcc1ce08023cab19c8242eb9268c07c3.
    Original cl in the first patchset.

    Original cl description:

    The purpose of the interface is to allow network simulations to implement their own queueing.

    The existing SimulatedNetwork is refactored to use a NetworkQueue interface.
    Per default a simple LeayBucket is used that has the same behavior as
    SimulatedNetwork today.

    Bug: webrtc:42225697
    Change-Id: Ic728a5e5f711cf380a38543fac02849da3861ab6
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/399480
    Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
    Commit-Queue: Per Kjellander <perkj@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45119}

Diffstat:
Mthird_party/libwebrtc/BUILD.gn | 1+
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/api/BUILD.gn | 3+++
Mthird_party/libwebrtc/api/test/network_emulation/BUILD.gn | 31+++++++++++++++++++++++++++++++
Athird_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue.cc | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Athird_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue.h | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Athird_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue_unittest.cc | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Athird_party/libwebrtc/api/test/network_emulation/network_queue.h | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mthird_party/libwebrtc/api/test/network_emulation_manager.cc | 19++++++++++++++++++-
Mthird_party/libwebrtc/api/test/network_emulation_manager.h | 4++++
Mthird_party/libwebrtc/api/test/simulated_network.h | 15+++++++++++++++
Mthird_party/libwebrtc/moz-patch-stack/s0027.patch | 8++++----
Mthird_party/libwebrtc/moz-patch-stack/s0034.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0045.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0055.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0084.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0093.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0095.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0103.patch | 8++++----
Mthird_party/libwebrtc/moz-patch-stack/s0106.patch | 4++--
Mthird_party/libwebrtc/moz-patch-stack/s0108.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0112.patch | 2+-
Mthird_party/libwebrtc/moz-patch-stack/s0130.patch | 2+-
Mthird_party/libwebrtc/test/network/BUILD.gn | 3+++
Mthird_party/libwebrtc/test/network/simulated_network.cc | 189+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mthird_party/libwebrtc/test/network/simulated_network.h | 45+++++++++++++++++++++++++--------------------
Mthird_party/libwebrtc/test/network/simulated_network_unittest.cc | 62+++++++++++++++++++++++++++++++++++++++++++++++++++++---------
27 files changed, 543 insertions(+), 136 deletions(-)

diff --git a/third_party/libwebrtc/BUILD.gn b/third_party/libwebrtc/BUILD.gn @@ -705,6 +705,7 @@ if (rtc_include_tests && !build_with_chromium) { "api/numerics:numerics_unittests", "api/task_queue:pending_task_safety_flag_unittests", "api/test/metrics:metrics_unittests", + "api/test/network_emulation:network_queue_unittests", "api/transport:stun_unittest", "api/transport/rtp:corruption_detection_message_unittest", "api/video/test:rtc_api_video_unittests", diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor @@ -1,4 +1,4 @@ # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc -libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-09T04:27:25.996834+00:00. +libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-09T04:28:30.584667+00:00. # base of lastest vendoring -c9c68ef81e +ba4a04a43b diff --git a/third_party/libwebrtc/api/BUILD.gn b/third_party/libwebrtc/api/BUILD.gn @@ -945,6 +945,8 @@ rtc_source_set("simulated_network_api") { "../rtc_base:random", "transport:ecn_marking", "units:data_rate", + "units:data_size", + "units:timestamp", "//third_party/abseil-cpp/absl/functional:any_invocable", ] } @@ -970,6 +972,7 @@ rtc_library("network_emulation_manager_api") { "../rtc_base:socket_address", "../test/network:simulated_network", "test/network_emulation", + "test/network_emulation:network_queue", "units:data_rate", "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/strings:string_view", diff --git a/third_party/libwebrtc/api/test/network_emulation/BUILD.gn b/third_party/libwebrtc/api/test/network_emulation/BUILD.gn @@ -76,3 +76,34 @@ rtc_library("create_cross_traffic") { "../../../test/network:emulated_network", ] } + +rtc_library("network_queue") { + visibility = [ "*" ] + + sources = [ + "leaky_bucket_network_queue.cc", + "leaky_bucket_network_queue.h", + "network_queue.h", + ] + + deps = [ + "../..:sequence_checker", + "../..:simulated_network_api", + "../../../rtc_base:checks", + "../../../rtc_base:macromagic", + "../../units:timestamp", + ] +} + +rtc_library("network_queue_unittests") { + sources = [ "leaky_bucket_network_queue_unittest.cc" ] + + testonly = true + deps = [ + ":network_queue", + "../..:simulated_network_api", + "../../../test:test_support", + "../../units:data_size", + "../../units:timestamp", + ] +} diff --git a/third_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue.cc b/third_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue.cc @@ -0,0 +1,71 @@ +/* + * Copyright 2025 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 "api/test/network_emulation/leaky_bucket_network_queue.h" + +#include <cstddef> +#include <optional> +#include <vector> + +#include "api/test/simulated_network.h" +#include "api/units/timestamp.h" +#include "rtc_base/checks.h" + +namespace webrtc { + +bool LeakyBucketNetworkQueue::EnqueuePacket( + const PacketInFlightInfo& packet_info) { + if (max_packet_capacity_ <= queue_.size()) { + return false; + } + queue_.push(packet_info); + return true; +} + +std::optional<PacketInFlightInfo> LeakyBucketNetworkQueue::PeekNextPacket() + const { + if (queue_.empty()) { + return std::nullopt; + } + return queue_.front(); +} + +std::optional<PacketInFlightInfo> LeakyBucketNetworkQueue::DequeuePacket( + Timestamp time_now) { + if (queue_.empty()) { + return std::nullopt; + } + RTC_DCHECK_LE(queue_.front().send_time(), time_now); + PacketInFlightInfo packet_info = queue_.front(); + queue_.pop(); + return packet_info; +} + +void LeakyBucketNetworkQueue::SetMaxPacketCapacity(size_t max_capactiy) { + max_packet_capacity_ = max_capactiy; +} + +bool LeakyBucketNetworkQueue::empty() const { + return queue_.empty(); +} + +void LeakyBucketNetworkQueue::DropOldestPacket() { + dropped_packets_.push_back(queue_.front()); + queue_.pop(); +} + +std::vector<PacketInFlightInfo> +LeakyBucketNetworkQueue::DequeueDroppedPackets() { + std::vector<PacketInFlightInfo> dropped_packets; + dropped_packets.swap(dropped_packets_); + return dropped_packets; +} + +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue.h b/third_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue.h @@ -0,0 +1,59 @@ +/* + * Copyright 2025 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 API_TEST_NETWORK_EMULATION_LEAKY_BUCKET_NETWORK_QUEUE_H_ +#define API_TEST_NETWORK_EMULATION_LEAKY_BUCKET_NETWORK_QUEUE_H_ + +#include <cstddef> +#include <memory> +#include <optional> +#include <queue> +#include <vector> + +#include "api/test/network_emulation/network_queue.h" +#include "api/test/simulated_network.h" +#include "api/units/timestamp.h" + +namespace webrtc { + +// A network queue that uses a leaky bucket to limit the number of packets that +// can be queued. +class LeakyBucketNetworkQueue : public NetworkQueue { + public: + LeakyBucketNetworkQueue() = default; + // If `max_capacity` is larger than current queue length, existing packets are + // not dropped. But the queue will not accept new packets until queue length + // is below `max_capacity`, + void SetMaxPacketCapacity(size_t max_capactiy) override; + + bool EnqueuePacket(const PacketInFlightInfo& packet_info) override; + std::optional<PacketInFlightInfo> PeekNextPacket() const override; + std::optional<PacketInFlightInfo> DequeuePacket(Timestamp time_now) override; + std::vector<PacketInFlightInfo> DequeueDroppedPackets() override; + bool empty() const override; + + void DropOldestPacket(); + + private: + size_t max_packet_capacity_ = kMaxPacketCapacity; + + std::queue<PacketInFlightInfo> queue_; + std::vector<PacketInFlightInfo> dropped_packets_; +}; + +class LeakyBucketNetworkQueueFactory : public NetworkQueueFactory { + public: + std::unique_ptr<NetworkQueue> CreateQueue() override { + return std::make_unique<LeakyBucketNetworkQueue>(); + } +}; +} // namespace webrtc + +#endif // API_TEST_NETWORK_EMULATION_LEAKY_BUCKET_NETWORK_QUEUE_H_ diff --git a/third_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue_unittest.cc b/third_party/libwebrtc/api/test/network_emulation/leaky_bucket_network_queue_unittest.cc @@ -0,0 +1,74 @@ +/* + * Copyright 2025 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 "api/test/network_emulation/leaky_bucket_network_queue.h" + +#include <optional> + +#include "api/test/simulated_network.h" +#include "api/units/data_size.h" +#include "api/units/timestamp.h" +#include "test/gmock.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +using ::testing::Field; +using ::testing::Optional; +using ::testing::Property; + +TEST(LeakyBucketNetworkQueueTest, EnqueuePacketReturnsFalseIfQueueIsFull) { + LeakyBucketNetworkQueue queue; + queue.SetMaxPacketCapacity(1); + PacketInFlightInfo packet_info(DataSize::Bytes(123), Timestamp::Zero(), + /*packet_id=*/1); + EXPECT_TRUE(queue.EnqueuePacket(packet_info)); + EXPECT_FALSE(queue.EnqueuePacket(packet_info)); +} + +TEST(LeakyBucketNetworkQueueTest, + EnqueuePacketReturnsFalseIfQueueIsFullAfterCapacityChange) { + LeakyBucketNetworkQueue queue; + PacketInFlightInfo packet_info(DataSize::Bytes(123), Timestamp::Zero(), + /*packet_id=*/1); + ASSERT_TRUE(queue.EnqueuePacket(packet_info)); + ASSERT_TRUE(queue.EnqueuePacket(packet_info)); + + queue.SetMaxPacketCapacity(2); + EXPECT_FALSE(queue.EnqueuePacket(packet_info)); + EXPECT_NE(queue.DequeuePacket(Timestamp::Seconds(125)), std::nullopt); + EXPECT_TRUE(queue.EnqueuePacket(packet_info)); +} + +TEST(LeakyBucketNetworkQueueTest, ReturnsNullOptWhenEmtpy) { + LeakyBucketNetworkQueue queue; + EXPECT_TRUE(queue.empty()); + EXPECT_EQ(queue.DequeuePacket(Timestamp::Zero()), std::nullopt); + EXPECT_EQ(queue.PeekNextPacket(), std::nullopt); +} + +TEST(LeakyBucketNetworkQueueTest, DequeueDoesNotChangePacketInfo) { + LeakyBucketNetworkQueue queue; + EXPECT_TRUE(queue.empty()); + PacketInFlightInfo packet_info(DataSize::Bytes(123), Timestamp::Seconds(123), + /*packet_id=*/1); + queue.EnqueuePacket(packet_info); + + EXPECT_THAT( + queue.DequeuePacket(Timestamp::Seconds(125)), + Optional(AllOf( + Field(&PacketInFlightInfo::packet_id, packet_info.packet_id), + Property(&PacketInFlightInfo::packet_size, packet_info.packet_size()), + Property(&PacketInFlightInfo::send_time, packet_info.send_time())))); +} + +} // namespace +} // namespace webrtc diff --git a/third_party/libwebrtc/api/test/network_emulation/network_queue.h b/third_party/libwebrtc/api/test/network_emulation/network_queue.h @@ -0,0 +1,61 @@ +/* + * Copyright 2025 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 API_TEST_NETWORK_EMULATION_NETWORK_QUEUE_H_ +#define API_TEST_NETWORK_EMULATION_NETWORK_QUEUE_H_ + +#include <cstddef> +#include <memory> +#include <optional> +#include <vector> + +#include "api/test/simulated_network.h" +#include "api/units/timestamp.h" + +namespace webrtc { + +// NetworkQueue defines the interface for a queue used in network simulation. +// The purpose is to allow for different AQM implementations. +// A queue should not modify PacketInFlightInfo except for the explicit +// congestion notification field (ecn). +class NetworkQueue { + public: + // Max capacity a queue is expected to handle. + constexpr static size_t kMaxPacketCapacity = 10000; + + virtual ~NetworkQueue() = default; + // Sets the max capacity of the queue. If there are already more than + // `max_capacitiy` packets in the queue, the behaviour depends on the + // implementation. + virtual void SetMaxPacketCapacity(size_t max_capactiy) = 0; + // Enqueues a packet. + // Must return true if the packet is enqueued successfully, false otherwise. + virtual bool EnqueuePacket(const PacketInFlightInfo& packet_info) = 0; + // Next packet that can be dequeued. + virtual std::optional<PacketInFlightInfo> PeekNextPacket() const = 0; + // Dequeues a packet. + // or std::nullopt if there are no enqueued packets. + virtual std::optional<PacketInFlightInfo> DequeuePacket( + Timestamp time_now) = 0; + + // Dequeues all packets that are dropped by the queue itself after being + // enqueued. + virtual std::vector<PacketInFlightInfo> DequeueDroppedPackets() = 0; + virtual bool empty() const = 0; +}; + +class NetworkQueueFactory { + public: + virtual ~NetworkQueueFactory() = default; + virtual std::unique_ptr<NetworkQueue> CreateQueue() = 0; +}; + +} // namespace webrtc +#endif // API_TEST_NETWORK_EMULATION_NETWORK_QUEUE_H_ diff --git a/third_party/libwebrtc/api/test/network_emulation_manager.cc b/third_party/libwebrtc/api/test/network_emulation_manager.cc @@ -9,12 +9,15 @@ */ #include "api/test/network_emulation_manager.h" +#include <cstddef> #include <cstdint> #include <memory> #include <string> #include <utility> #include "absl/strings/string_view.h" +#include "api/test/network_emulation/leaky_bucket_network_queue.h" +#include "api/test/network_emulation/network_queue.h" #include "api/test/simulated_network.h" #include "api/units/data_rate.h" #include "rtc_base/checks.h" @@ -55,6 +58,13 @@ NetworkEmulationManager::SimulatedNetworkNode::Builder::config( } NetworkEmulationManager::SimulatedNetworkNode::Builder& +NetworkEmulationManager::SimulatedNetworkNode::Builder::queue_factory( + NetworkQueueFactory& queue_factory) { + queue_factory_ = &queue_factory; + return *this; +} + +NetworkEmulationManager::SimulatedNetworkNode::Builder& NetworkEmulationManager::SimulatedNetworkNode::Builder::delay_ms( int queue_delay_ms) { config_.queue_delay_ms = queue_delay_ms; @@ -143,8 +153,15 @@ NetworkEmulationManager::SimulatedNetworkNode::Builder::Build( uint64_t random_seed) const { RTC_CHECK(net); RTC_CHECK(net_ == nullptr || net_ == net); + std::unique_ptr<NetworkQueue> network_queue; + if (queue_factory_ != nullptr) { + network_queue = queue_factory_->CreateQueue(); + } else { + network_queue = std::make_unique<LeakyBucketNetworkQueue>(); + } SimulatedNetworkNode res; - auto behavior = std::make_unique<SimulatedNetwork>(config_, random_seed); + auto behavior = std::make_unique<SimulatedNetwork>(config_, random_seed, + std::move(network_queue)); res.simulation = behavior.get(); res.node = net->CreateEmulatedNode(std::move(behavior)); return res; diff --git a/third_party/libwebrtc/api/test/network_emulation_manager.h b/third_party/libwebrtc/api/test/network_emulation_manager.h @@ -25,6 +25,7 @@ #include "api/field_trials_view.h" #include "api/test/network_emulation/cross_traffic.h" #include "api/test/network_emulation/network_emulation_interfaces.h" +#include "api/test/network_emulation/network_queue.h" #include "api/test/peer_network_dependencies.h" #include "api/test/simulated_network.h" #include "api/test/time_controller.h" @@ -190,6 +191,8 @@ class NetworkEmulationManager { // Sets the config state, note that this will replace any previously set // values. Builder& config(BuiltInNetworkBehaviorConfig config); + // If set, `queue_factory` must outlive the Builder. + Builder& queue_factory(NetworkQueueFactory& queue_factory); Builder& delay_ms(int queue_delay_ms); Builder& capacity(DataRate link_capacity); Builder& capacity_kbps(int link_capacity_kbps); @@ -207,6 +210,7 @@ class NetworkEmulationManager { private: NetworkEmulationManager* const net_; BuiltInNetworkBehaviorConfig config_; + NetworkQueueFactory* queue_factory_ = nullptr; }; }; virtual ~NetworkEmulationManager() = default; diff --git a/third_party/libwebrtc/api/test/simulated_network.h b/third_party/libwebrtc/api/test/simulated_network.h @@ -21,6 +21,8 @@ #include "absl/functional/any_invocable.h" #include "api/transport/ecn_marking.h" #include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/timestamp.h" namespace webrtc { @@ -33,11 +35,24 @@ struct PacketInFlightInfo { send_time_us(send_time_us), packet_id(packet_id), ecn(ecn) {} + PacketInFlightInfo(DataSize size, + Timestamp send_time, + uint64_t packet_id, + EcnMarking ecn) + : PacketInFlightInfo(size.bytes(), send_time.us(), packet_id, ecn) {} + PacketInFlightInfo(DataSize size, Timestamp send_time, uint64_t packet_id) + : PacketInFlightInfo(size.bytes(), + send_time.us(), + packet_id, + EcnMarking::kNotEct) {} PacketInFlightInfo(size_t size, int64_t send_time_us, uint64_t packet_id) : PacketInFlightInfo(size, send_time_us, packet_id, EcnMarking::kNotEct) { } + DataSize packet_size() const { return DataSize::Bytes(size); } + Timestamp send_time() const { return Timestamp::Micros(send_time_us); } + size_t size; int64_t send_time_us; // Unique identifier for the packet in relation to other packets in flight. diff --git a/third_party/libwebrtc/moz-patch-stack/s0027.patch b/third_party/libwebrtc/moz-patch-stack/s0027.patch @@ -116,7 +116,7 @@ index 1b112b34c0..18cf5d67f7 100644 # TODO(https://bugs.webrtc.org/14437): Remove this section if general # Chromium fix resolves the problem. diff --git a/BUILD.gn b/BUILD.gn -index fd77e776cd..9d79e5e129 100644 +index 1565aeb592..cfbba26987 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -33,7 +33,7 @@ if (is_android) { @@ -203,7 +203,7 @@ index fd77e776cd..9d79e5e129 100644 } diff --git a/api/BUILD.gn b/api/BUILD.gn -index 4ee76f6757..f0dc1684d9 100644 +index 2dbc1c17ba..f1c2c2e3a4 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -44,6 +44,9 @@ rtc_library("enable_media") { @@ -332,7 +332,7 @@ index 4ee76f6757..f0dc1684d9 100644 rtc_source_set("data_channel_event_observer_interface") { visibility = [ "*" ] -@@ -1001,6 +1034,7 @@ rtc_source_set("refcountedbase") { +@@ -1004,6 +1037,7 @@ rtc_source_set("refcountedbase") { } rtc_library("ice_transport_factory") { @@ -340,7 +340,7 @@ index 4ee76f6757..f0dc1684d9 100644 visibility = [ "*" ] sources = [ "ice_transport_factory.cc", -@@ -1024,6 +1058,7 @@ rtc_library("ice_transport_factory") { +@@ -1027,6 +1061,7 @@ rtc_library("ice_transport_factory") { "rtc_event_log:rtc_event_log", ] } diff --git a/third_party/libwebrtc/moz-patch-stack/s0034.patch b/third_party/libwebrtc/moz-patch-stack/s0034.patch @@ -20,7 +20,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/58f47eacaf10d12e2 11 files changed, 27 insertions(+), 27 deletions(-) diff --git a/BUILD.gn b/BUILD.gn -index 9d79e5e129..acf69ea940 100644 +index cfbba26987..887cfbac2f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -438,12 +438,12 @@ config("common_config") { diff --git a/third_party/libwebrtc/moz-patch-stack/s0045.patch b/third_party/libwebrtc/moz-patch-stack/s0045.patch @@ -18,7 +18,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0300b32b7de70fb89 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/BUILD.gn b/BUILD.gn -index acf69ea940..d55f06b52b 100644 +index 887cfbac2f..ec62984044 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -222,6 +222,9 @@ config("common_inherited_config") { diff --git a/third_party/libwebrtc/moz-patch-stack/s0055.patch b/third_party/libwebrtc/moz-patch-stack/s0055.patch @@ -11,7 +11,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b0658888969395dca 2 files changed, 10 insertions(+) diff --git a/BUILD.gn b/BUILD.gn -index d55f06b52b..21ce290a12 100644 +index ec62984044..25b8dddb8b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -621,6 +621,10 @@ if (!build_with_chromium) { diff --git a/third_party/libwebrtc/moz-patch-stack/s0084.patch b/third_party/libwebrtc/moz-patch-stack/s0084.patch @@ -11,7 +11,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2185cab977988fd4a 3 files changed, 16 insertions(+) diff --git a/BUILD.gn b/BUILD.gn -index 21ce290a12..9a4f0f1b97 100644 +index 25b8dddb8b..11d7fec9d2 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -606,6 +606,7 @@ if (!build_with_chromium) { diff --git a/third_party/libwebrtc/moz-patch-stack/s0093.patch b/third_party/libwebrtc/moz-patch-stack/s0093.patch @@ -10,7 +10,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b050c455caa1d24a0 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/BUILD.gn b/BUILD.gn -index 9a4f0f1b97..74f7c78e12 100644 +index 11d7fec9d2..29fa9ffdc7 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -278,6 +278,7 @@ config("rtc_prod_config") { diff --git a/third_party/libwebrtc/moz-patch-stack/s0095.patch b/third_party/libwebrtc/moz-patch-stack/s0095.patch @@ -9,7 +9,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/6baf67202c67b27c6 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/test/network_emulation/BUILD.gn b/api/test/network_emulation/BUILD.gn -index d22cc09d00..3d7bc005f4 100644 +index de58887b07..665af721e3 100644 --- a/api/test/network_emulation/BUILD.gn +++ b/api/test/network_emulation/BUILD.gn @@ -6,10 +6,10 @@ diff --git a/third_party/libwebrtc/moz-patch-stack/s0103.patch b/third_party/libwebrtc/moz-patch-stack/s0103.patch @@ -75,7 +75,7 @@ index cdbd705ec2..4ee826ec58 100644 # The python interpreter to use by default. On Windows, this will look # for vpython3.exe and vpython3.bat. diff --git a/BUILD.gn b/BUILD.gn -index 74f7c78e12..f5aa3cc9fe 100644 +index 29fa9ffdc7..5f3497a925 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -21,15 +21,15 @@ @@ -107,7 +107,7 @@ index 74f7c78e12..f5aa3cc9fe 100644 defines = [] deps = [ -@@ -845,7 +845,7 @@ rtc_static_library("dcsctp") { +@@ -846,7 +846,7 @@ rtc_static_library("dcsctp") { visibility = [ "//:default" ] sources = [] complete_static_lib = true @@ -116,7 +116,7 @@ index 74f7c78e12..f5aa3cc9fe 100644 defines = [] deps = [ "net/dcsctp/public:factory", -@@ -880,7 +880,7 @@ group("poison_software_video_codecs") { +@@ -881,7 +881,7 @@ group("poison_software_video_codecs") { if (!build_with_chromium) { # Write debug logs to gn_logs.txt. # This is also required for Siso builds. @@ -126,7 +126,7 @@ index 74f7c78e12..f5aa3cc9fe 100644 "Generated during 'gn gen' by //BUILD.gn.", "", diff --git a/api/BUILD.gn b/api/BUILD.gn -index f0dc1684d9..089f04a873 100644 +index f1c2c2e3a4..9e605c4920 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -8,8 +8,8 @@ diff --git a/third_party/libwebrtc/moz-patch-stack/s0106.patch b/third_party/libwebrtc/moz-patch-stack/s0106.patch @@ -9,7 +9,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/90a33b06e51017d25 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BUILD.gn b/BUILD.gn -index f5aa3cc9fe..9f8d5e314f 100644 +index 5f3497a925..3cb7c1f623 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -562,6 +562,7 @@ if (!build_with_chromium) { @@ -20,7 +20,7 @@ index f5aa3cc9fe..9f8d5e314f 100644 "logging:rtc_event_log_api", "media", "modules", -@@ -842,7 +843,7 @@ if (rtc_include_tests && !build_with_chromium) { +@@ -843,7 +844,7 @@ if (rtc_include_tests && !build_with_chromium) { # Build target for standalone dcsctp rtc_static_library("dcsctp") { # Only the root target should depend on this. diff --git a/third_party/libwebrtc/moz-patch-stack/s0108.patch b/third_party/libwebrtc/moz-patch-stack/s0108.patch @@ -16,7 +16,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/4527c41ef71d7683c 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/BUILD.gn b/BUILD.gn -index 9f8d5e314f..67d6d66a9e 100644 +index 3cb7c1f623..9e801948e5 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -519,6 +519,9 @@ if (!rtc_build_ssl) { diff --git a/third_party/libwebrtc/moz-patch-stack/s0112.patch b/third_party/libwebrtc/moz-patch-stack/s0112.patch @@ -10,7 +10,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/27c29807e6f46562d 1 file changed, 1 insertion(+) diff --git a/BUILD.gn b/BUILD.gn -index 67d6d66a9e..398ddc540e 100644 +index 9e801948e5..2166174786 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -612,6 +612,7 @@ if (!build_with_chromium) { diff --git a/third_party/libwebrtc/moz-patch-stack/s0130.patch b/third_party/libwebrtc/moz-patch-stack/s0130.patch @@ -9,7 +9,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/43de54a6e52daf0a0 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/BUILD.gn b/BUILD.gn -index 398ddc540e..ad8d9970ee 100644 +index 2166174786..f80f81a6fd 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -313,6 +313,17 @@ config("common_config") { diff --git a/third_party/libwebrtc/test/network/BUILD.gn b/third_party/libwebrtc/test/network/BUILD.gn @@ -261,6 +261,7 @@ rtc_library("simulated_network") { deps = [ "../../api:sequence_checker", "../../api:simulated_network_api", + "../../api/test/network_emulation:network_queue", "../../api/units:data_rate", "../../api/units:data_size", "../../api/units:time_delta", @@ -283,7 +284,9 @@ if (rtc_include_tests) { ":simulated_network", "..:test_support", "../../api:simulated_network_api", + "../../api/test/network_emulation:network_queue", "../../api/units:data_rate", + "../../api/units:data_size", "../../api/units:time_delta", "../../api/units:timestamp", ] diff --git a/third_party/libwebrtc/test/network/simulated_network.cc b/third_party/libwebrtc/test/network/simulated_network.cc @@ -14,11 +14,14 @@ #include <cmath> #include <cstdint> #include <functional> +#include <memory> #include <optional> #include <utility> #include <vector> #include "absl/functional/any_invocable.h" +#include "api/test/network_emulation/leaky_bucket_network_queue.h" +#include "api/test/network_emulation/network_queue.h" #include "api/test/simulated_network.h" #include "api/units/data_rate.h" #include "api/units/data_size.h" @@ -56,17 +59,33 @@ Timestamp CalculateArrivalTime(Timestamp start_time, } // namespace -SimulatedNetwork::SimulatedNetwork(Config config, uint64_t random_seed) - : random_(random_seed), bursting_(false), last_enqueue_time_us_(0) { +SimulatedNetwork::SimulatedNetwork(Config config, + uint64_t random_seed, + std::unique_ptr<NetworkQueue> queue) + : queue_(std::move(queue)), random_(random_seed) { SetConfig(config); } +SimulatedNetwork::SimulatedNetwork(Config config, uint64_t random_seed) + : SimulatedNetwork(config, + random_seed, + std::make_unique<LeakyBucketNetworkQueue>()) {} + SimulatedNetwork::~SimulatedNetwork() = default; void SimulatedNetwork::SetConfig(const Config& config) { - MutexLock lock(&config_lock_); - config_state_.config = config; // Shallow copy of the struct. + MutexLock lock(&lock_); + SetConfigLocked(config); +} + +void SimulatedNetwork::SetConfigLocked(const Config& config) { + queue_->SetMaxPacketCapacity( + /*max_length=*/config.queue_length_packets > 0 + ? config.queue_length_packets - 1 // -1 to account for the + // packet in the capacity link. + : NetworkQueue::kMaxPacketCapacity); + config_state_.config = config; // Shallow copy of the struct. double prob_loss = config.loss_percent / 100.0; if (config_state_.config.avg_burst_loss_length == -1) { // Uniform loss @@ -93,21 +112,25 @@ void SimulatedNetwork::SetConfig(const BuiltInNetworkBehaviorConfig& new_config, Timestamp config_update_time) { RTC_DCHECK_RUNS_SERIALIZED(&process_checker_); - if (!capacity_link_.empty()) { - // Calculate and update how large portion of the packet first in the - // capacity link is left to to send at time `config_update_time`. - const BuiltInNetworkBehaviorConfig& current_config = - GetConfigState().config; - TimeDelta duration_with_current_config = - config_update_time - capacity_link_.front().last_update_time; - RTC_DCHECK_GE(duration_with_current_config, TimeDelta::Zero()); - capacity_link_.front().bits_left_to_send -= std::min( - duration_with_current_config.ms() * current_config.link_capacity.kbps(), - capacity_link_.front().bits_left_to_send); - capacity_link_.front().last_update_time = config_update_time; - } - SetConfig(new_config); - UpdateCapacityQueue(GetConfigState(), config_update_time); + { + MutexLock lock(&lock_); + if (capacity_link_.has_value()) { + // Calculate and update how large portion of the packet first in the + // capacity link is left to to send at time `config_update_time`. + const BuiltInNetworkBehaviorConfig& current_config = config_state_.config; + TimeDelta duration_with_current_config = + config_update_time - capacity_link_->last_update_time; + RTC_DCHECK_GE(duration_with_current_config, TimeDelta::Zero()); + capacity_link_->bits_left_to_send -= + std::min(duration_with_current_config.ms() * + current_config.link_capacity.kbps(), + capacity_link_->bits_left_to_send); + capacity_link_->last_update_time = config_update_time; + } + SetConfigLocked(new_config); + UpdateCapacityLink(config_state_, config_update_time); + }; + if (UpdateNextProcessTime() && next_process_time_changed_callback_) { next_process_time_changed_callback_(); } @@ -115,18 +138,17 @@ void SimulatedNetwork::SetConfig(const BuiltInNetworkBehaviorConfig& new_config, void SimulatedNetwork::UpdateConfig( std::function<void(BuiltInNetworkBehaviorConfig*)> config_modifier) { - MutexLock lock(&config_lock_); + MutexLock lock(&lock_); config_modifier(&config_state_.config); } void SimulatedNetwork::PauseTransmissionUntil(int64_t until_us) { - MutexLock lock(&config_lock_); + MutexLock lock(&lock_); config_state_.pause_transmission_until_us = until_us; } bool SimulatedNetwork::EnqueuePacket(PacketInFlightInfo packet) { RTC_DCHECK_RUNS_SERIALIZED(&process_checker_); - // Check that old packets don't get enqueued, the SimulatedNetwork expect that // the packets' send time is monotonically increasing. The tolerance for // non-monotonic enqueue events is 0.5 ms because on multi core systems @@ -137,35 +159,34 @@ bool SimulatedNetwork::EnqueuePacket(PacketInFlightInfo packet) { // At the moment, we see more than 130ms between non-monotonic events, which // is more than expected. // RTC_DCHECK_GE(packet.send_time_us - last_enqueue_time_us_, -2000); + last_enqueue_time_us_ = packet.send_time_us; - ConfigState state = GetConfigState(); + MutexLock lock(&lock_); // If the network config requires packet overhead, let's apply it as early as // possible. - packet.size += state.config.packet_overhead; + packet.size += config_state_.config.packet_overhead; - // If `queue_length_packets` is 0, the queue size is infinite. - if (state.config.queue_length_packets > 0 && - capacity_link_.size() >= state.config.queue_length_packets) { - // Too many packet on the link, drop this one. - return false; + Timestamp enqueue_time = packet.send_time(); + bool packet_enqueued = queue_->EnqueuePacket(packet); + // A packet can not enter the narrow section before the last packet has exit. + if (capacity_link_.has_value()) { + // A packet is already in the capacity link. Wait until it exits. + return packet_enqueued; + } + PacketInFlightInfo next_packet = packet; + if (!queue_->empty()) { + next_packet = *queue_->DequeuePacket(enqueue_time); } + Timestamp arrival_time = CalculateArrivalTime( + std::max(next_packet.send_time(), last_capacity_link_exit_time_), + packet.size * 8, config_state_.config.link_capacity); - // Note that arrival time will be updated when previous packets are dequeued - // from the capacity link. - // A packet can not enter the narrow section before the last packet has exit. - Timestamp enqueue_time = Timestamp::Micros(packet.send_time_us); - Timestamp arrival_time = - capacity_link_.empty() - ? CalculateArrivalTime( - std::max(enqueue_time, last_capacity_link_exit_time_), - packet.size * 8, state.config.link_capacity) - : Timestamp::PlusInfinity(); - capacity_link_.push( - {.packet = packet, - .last_update_time = enqueue_time, - .bits_left_to_send = 8 * static_cast<int64_t>(packet.size), - .arrival_time = arrival_time}); + capacity_link_ = { + .packet = next_packet, + .last_update_time = enqueue_time, + .bits_left_to_send = 8 * static_cast<int64_t>(next_packet.size), + .arrival_time = arrival_time}; // Only update `next_process_time_` if not already set. Otherwise, // next_process_time_ is calculated when a packet is dequeued. Note that this @@ -174,11 +195,8 @@ bool SimulatedNetwork::EnqueuePacket(PacketInFlightInfo packet) { // config.delay_standard_deviation_ms is set. // TODO(bugs.webrtc.org/14525): Consider preventing this. if (next_process_time_.IsInfinite() && arrival_time.IsFinite()) { - RTC_DCHECK_EQ(capacity_link_.size(), 1); next_process_time_ = arrival_time; } - - last_enqueue_time_us_ = packet.send_time_us; return true; } @@ -190,24 +208,20 @@ std::optional<int64_t> SimulatedNetwork::NextDeliveryTimeUs() const { return std::nullopt; } -void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, - Timestamp time_now) { - // Only the first packet in capacity_link_ have a calculated arrival time - // (when packet leave the narrow section), and time when it entered the narrow - // section. Also, the configuration may have changed. Thus we need to - // calculate the arrival time again before maybe moving the packet to the - // delay link. - if (!capacity_link_.empty()) { - capacity_link_.front().last_update_time = std::max( - capacity_link_.front().last_update_time, last_capacity_link_exit_time_); - capacity_link_.front().arrival_time = CalculateArrivalTime( - capacity_link_.front().last_update_time, - capacity_link_.front().bits_left_to_send, state.config.link_capacity); +void SimulatedNetwork::UpdateCapacityLink(ConfigState state, + Timestamp time_now) { + RTC_DCHECK_RUNS_SERIALIZED(&process_checker_); + if (capacity_link_.has_value()) { + // Recalculate the arrival time of the packet currently in the capacity link + // since it may have changed if the capacity has changed. + capacity_link_->last_update_time = std::max( + capacity_link_->last_update_time, last_capacity_link_exit_time_); + capacity_link_->arrival_time = CalculateArrivalTime( + capacity_link_->last_update_time, capacity_link_->bits_left_to_send, + state.config.link_capacity); } - // The capacity link is empty or the first packet is not expected to exit yet. - if (capacity_link_.empty() || - time_now < capacity_link_.front().arrival_time) { + if (!capacity_link_.has_value() || time_now < capacity_link_->arrival_time) { return; } bool reorder_packets = false; @@ -215,9 +229,9 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, do { // Time to get this packet (the original or just updated arrival_time is // smaller or equal to time_now_us). - PacketInfo packet = capacity_link_.front(); + PacketInfo packet = *capacity_link_; RTC_DCHECK(packet.arrival_time.IsFinite()); - capacity_link_.pop(); + capacity_link_ = std::nullopt; // If the network is paused, the pause will be implemented as an extra delay // to be spent in the `delay_link_` queue. @@ -227,8 +241,8 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, } // Store the original arrival time, before applying packet loss or extra - // delay. This is needed to know when it is the first available time the - // next packet in the `capacity_link_` queue can start transmitting. + // delay. This is needed to know when it is possible for the next packet + // in the queue to start transmitting. last_capacity_link_exit_time_ = packet.arrival_time; // Drop packets at an average rate of `state.config.loss_percent` with @@ -265,19 +279,24 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, delay_link_.emplace_back(packet); // If there are no packets in the queue, there is nothing else to do. - if (capacity_link_.empty()) { + std::optional<PacketInFlightInfo> peek_packet = queue_->PeekNextPacket(); + if (!peek_packet) { break; } - // If instead there is another packet in the `capacity_link_` queue, let's - // calculate its arrival_time based on the latest config (which might - // have been changed since it was enqueued). - Timestamp next_start = std::max(last_capacity_link_exit_time_, - capacity_link_.front().last_update_time); - capacity_link_.front().arrival_time = - CalculateArrivalTime(next_start, capacity_link_.front().packet.size * 8, - state.config.link_capacity); + // It is possible that the next packet in the queue has a send time (at + // least in tests) after the previous packet left the capacity link. + Timestamp next_start = + std::max(last_capacity_link_exit_time_, peek_packet->send_time()); + std::optional<PacketInFlightInfo> next_packet = + queue_->DequeuePacket(next_start); + capacity_link_ = { + .packet = *next_packet, + .last_update_time = next_start, + .bits_left_to_send = 8 * static_cast<int64_t>(next_packet->size), + .arrival_time = CalculateArrivalTime(next_start, next_packet->size * 8, + state.config.link_capacity)}; // And if the next packet in the queue needs to exit, let's dequeue it. - } while (capacity_link_.front().arrival_time <= time_now); + } while (capacity_link_->arrival_time <= time_now); if (state.config.allow_reordering && reorder_packets) { // Packets arrived out of order and since the network config allows @@ -290,19 +309,19 @@ void SimulatedNetwork::UpdateCapacityQueue(ConfigState state, } } -SimulatedNetwork::ConfigState SimulatedNetwork::GetConfigState() const { - MutexLock lock(&config_lock_); - return config_state_; -} - std::vector<PacketDeliveryInfo> SimulatedNetwork::DequeueDeliverablePackets( int64_t receive_time_us) { RTC_DCHECK_RUNS_SERIALIZED(&process_checker_); Timestamp receive_time = Timestamp::Micros(receive_time_us); - UpdateCapacityQueue(GetConfigState(), receive_time); + MutexLock lock(&lock_); + UpdateCapacityLink(config_state_, receive_time); std::vector<PacketDeliveryInfo> packets_to_deliver; + for (const PacketInFlightInfo& packet : queue_->DequeueDroppedPackets()) { + packets_to_deliver.emplace_back(packet, PacketDeliveryInfo::kNotReceived); + } + // Check the extra delay queue. while (!delay_link_.empty() && receive_time >= delay_link_.front().arrival_time) { @@ -331,8 +350,8 @@ bool SimulatedNetwork::UpdateNextProcessTime() { break; } } - if (next_process_time_.IsInfinite() && !capacity_link_.empty()) { - next_process_time_ = capacity_link_.front().arrival_time; + if (next_process_time_.IsInfinite() && capacity_link_.has_value()) { + next_process_time_ = capacity_link_->arrival_time; } return next_process_time != next_process_time_; } diff --git a/third_party/libwebrtc/test/network/simulated_network.h b/third_party/libwebrtc/test/network/simulated_network.h @@ -15,12 +15,13 @@ #include <cstdint> #include <deque> #include <functional> +#include <memory> #include <optional> -#include <queue> #include <vector> #include "absl/functional/any_invocable.h" #include "api/sequence_checker.h" +#include "api/test/network_emulation/network_queue.h" #include "api/test/simulated_network.h" #include "api/units/timestamp.h" #include "rtc_base/race_checker.h" @@ -39,11 +40,15 @@ namespace webrtc { // packet through at the time with a limited capacity. // - Extra delay with or without packets reorder // - Packet overhead -// - Queue max capacity +// Per default a simple leaky bucket queue is used that allows setting a max +// capacity. But more advanced AQM can be used. class RTC_EXPORT SimulatedNetwork : public SimulatedNetworkInterface { public: using Config = BuiltInNetworkBehaviorConfig; explicit SimulatedNetwork(Config config, uint64_t random_seed = 1); + SimulatedNetwork(Config config, + uint64_t random_seed, + std::unique_ptr<NetworkQueue> queue); ~SimulatedNetwork() override; // Sets a new configuration. This will affect packets that will be sent with @@ -107,27 +112,27 @@ class RTC_EXPORT SimulatedNetwork : public SimulatedNetworkInterface { // Moves packets from capacity- to delay link. // If `previouse_config` is set, it is the config that was used until // `time_now_us` - void UpdateCapacityQueue(ConfigState state, Timestamp time_now) - RTC_RUN_ON(&process_checker_); - ConfigState GetConfigState() const; + void UpdateCapacityLink(ConfigState state, Timestamp time_now) + RTC_EXCLUSIVE_LOCKS_REQUIRED(&lock_); + void SetConfigLocked(const Config& config) + RTC_EXCLUSIVE_LOCKS_REQUIRED(&lock_); - mutable Mutex config_lock_; + // A note about threads: + // Some tests run the SimulatedNetwork on multiple threads. FakeNetworkPipe + // may call several methods on separate threads. Other tests call SetConfig + // on a thread other than the the other methods. + mutable Mutex lock_; // Guards the data structures involved in delay and loss processing, such as // the packet queues. RaceChecker process_checker_; - // Models the capacity of the network by rejecting packets if the queue is - // full and keeping them in the queue until they are ready to exit (according - // to the link capacity, which cannot be violated, e.g. a 1 kbps link will - // only be able to deliver 1000 bits per second). - // - // Invariant: - // The head of the `capacity_link_` has arrival_time correctly set to the - // time when the packet is supposed to be delivered (without accounting - // potential packet loss or potential extra delay and without accounting for a - // new configuration of the network, which requires a re-computation of the - // arrival_time). - std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_); + + // Queue of packets that have not yet entered the capacity link. + std::unique_ptr<webrtc::NetworkQueue> queue_ RTC_GUARDED_BY(lock_); + // Models the capacity of the network. There can only be one packet at the + // time in the capacity link. The time spend in the capacity link depends on + // the link capacity. + std::optional<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_); // Models the extra delay of the network (see `queue_delay_ms` // and `delay_standard_deviation_ms` in BuiltInNetworkBehaviorConfig), packets // in the `delay_link_` have technically already left the network and don't @@ -141,11 +146,11 @@ class RTC_EXPORT SimulatedNetwork : public SimulatedNetworkInterface { absl::AnyInvocable<void()> next_process_time_changed_callback_ RTC_GUARDED_BY(process_checker_) = nullptr; - ConfigState config_state_ RTC_GUARDED_BY(config_lock_); + ConfigState config_state_ RTC_GUARDED_BY(lock_); Random random_ RTC_GUARDED_BY(process_checker_); // Are we currently dropping a burst of packets? - bool bursting_; + bool bursting_ = false; // The send time of the last enqueued packet, this is only used to check that // the send time of enqueued packets is monotonically increasing. diff --git a/third_party/libwebrtc/test/network/simulated_network_unittest.cc b/third_party/libwebrtc/test/network/simulated_network_unittest.cc @@ -11,11 +11,15 @@ #include <cstddef> #include <cstdint> +#include <memory> #include <optional> +#include <utility> #include <vector> +#include "api/test/network_emulation/leaky_bucket_network_queue.h" #include "api/test/simulated_network.h" #include "api/units/data_rate.h" +#include "api/units/data_size.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "test/gmock.h" @@ -25,8 +29,10 @@ namespace webrtc { namespace { using ::testing::ElementsAre; +using ::testing::Field; using ::testing::MockFunction; using ::testing::SizeIs; +using ::testing::UnorderedElementsAre; PacketInFlightInfo PacketWithSize(size_t size) { return PacketInFlightInfo(/*size=*/size, /*send_time_us=*/0, /*packet_id=*/1); @@ -106,6 +112,20 @@ TEST(SimulatedNetworkTest, EnqueueFailsWhenQueueLengthIsReached) { /*packet_id=*/3))); } +TEST(SimulatedNetworkTest, CanChangeQueueLength) { + SimulatedNetwork network = + SimulatedNetwork({.link_capacity = DataRate::KilobitsPerSec(1)}); + ASSERT_TRUE(network.EnqueuePacket( + PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/1))); + ASSERT_TRUE(network.EnqueuePacket( + PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/2))); + + network.SetConfig({.queue_length_packets = 1, + .link_capacity = DataRate::KilobitsPerSec(1)}); + EXPECT_FALSE(network.EnqueuePacket( + PacketInFlightInfo(/*size=*/125, /*send_time_us=*/0, /*packet_id=*/3))); +} + TEST(SimulatedNetworkTest, PacketOverhead) { // A packet of 125 bytes that gets enqueued on a network with 1 kbps capacity // should be ready to exit the network in 1 second, but since there is an @@ -462,7 +482,7 @@ TEST(SimulatedNetworkTest, QueueDelayMsWithStandardDeviationAndReorderAllowed) { /*receive_time_us=*/TimeDelta::Seconds(5).us()); ASSERT_EQ(delivered_packets.size(), 4ul); - // And they have been reordered accorting to the applied extra delay. + // And they have been reordered according to the applied extra delay. EXPECT_EQ(delivered_packets[0].packet_id, 3ul); EXPECT_EQ(delivered_packets[1].packet_id, 1ul); EXPECT_GE(delivered_packets[1].receive_time_us, @@ -561,18 +581,17 @@ TEST(SimulatedNetworkTest, PacketLossBurst) { EXPECT_EQ(delivered_packets.size(), 20ul); // Results in a burst of lost packets after the first packet lost. - // With the current random seed, the first 12 are not lost, while the - // last 8 are. - int current_packet = 0; + // With the current random seed, at least 5 packets are lost. + int num_lost_packets = 0; for (const auto& packet : delivered_packets) { - if (current_packet < 12) { - EXPECT_NE(packet.receive_time_us, PacketDeliveryInfo::kNotReceived); - current_packet++; - } else { + if (packet.receive_time_us == PacketDeliveryInfo::kNotReceived) { + num_lost_packets++; + } + if (num_lost_packets > 0) { EXPECT_EQ(packet.receive_time_us, PacketDeliveryInfo::kNotReceived); - current_packet++; } } + EXPECT_GT(num_lost_packets, 5); } TEST(SimulatedNetworkTest, PauseTransmissionUntil) { @@ -668,6 +687,31 @@ TEST(SimulatedNetworkTest, EnqueuePacketWithSubSecondNonMonotonicBehaviour) { EXPECT_EQ(delivered_packets[0].receive_time_us, TimeDelta::Seconds(3).us()); } +TEST(SimulatedNetworkTest, CanUseInjectedQueueAndDropPacketsAtQueueHead) { + auto queue = std::make_unique<LeakyBucketNetworkQueue>(); + LeakyBucketNetworkQueue* queue_ptr = queue.get(); + SimulatedNetwork network = + SimulatedNetwork({.link_capacity = DataRate::KilobitsPerSec(1)}, + /*random_seed=*/1, std::move(queue)); + ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( + DataSize::Bytes(125), Timestamp::Seconds(1), /*packet_id=*/0))); + ASSERT_TRUE(network.EnqueuePacket(PacketInFlightInfo( + DataSize::Bytes(125), Timestamp::Seconds(1), /*packet_id=*/1))); + + // packet 0 is already sent, packet 1 is in the queue and will be dropped. + queue_ptr->DropOldestPacket(); + + std::vector<PacketDeliveryInfo> delivered_packets = + network.DequeueDeliverablePackets(network.NextDeliveryTimeUs().value()); + ASSERT_EQ(delivered_packets.size(), 2ul); + EXPECT_THAT( + delivered_packets, + UnorderedElementsAre(Field(&PacketDeliveryInfo::packet_id, 0), + AllOf(Field(&PacketDeliveryInfo::packet_id, 1), + Field(&PacketDeliveryInfo::receive_time_us, + PacketDeliveryInfo::kNotReceived)))); +} + // TODO(bugs.webrtc.org/14525): Re-enable when the DCHECK will be uncommented // and the non-monotonic events on real time clock tests is solved/understood. // TEST(SimulatedNetworkDeathTest, EnqueuePacketExpectMonotonicSendTime) {