From 14b46a77b2d8d30582648cca027cfbefefece9d4 Mon Sep 17 00:00:00 2001 From: Artem Titov Date: Fri, 31 Jul 2020 12:57:24 +0200 Subject: [PATCH] Provide per destination statistic for network outgoing stats Network emulation layer provides per source split for incoming stats for endpoint. Do the same for outgoing stats per destination. Bug: webrtc:11756 Change-Id: I2369ae8906546c27133273b1be17ce74c253c6e8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180500 Reviewed-by: Christoffer Rodbro Reviewed-by: Andrey Logvin Commit-Queue: Artem Titov Cr-Commit-Position: refs/heads/master@{#31820} --- .../network_emulation_interfaces.h | 72 +++-- test/network/network_emulation.cc | 250 +++++++++----- test/network/network_emulation.h | 306 +++++++++++++----- test/network/network_emulation_manager.cc | 2 +- test/network/network_emulation_unittest.cc | 53 +-- 5 files changed, 481 insertions(+), 202 deletions(-) diff --git a/api/test/network_emulation/network_emulation_interfaces.h b/api/test/network_emulation/network_emulation_interfaces.h index b1aa0d2809..ebb1eedc78 100644 --- a/api/test/network_emulation/network_emulation_interfaces.h +++ b/api/test/network_emulation/network_emulation_interfaces.h @@ -61,45 +61,66 @@ class EmulatedNetworkReceiverInterface { virtual void OnPacketReceived(EmulatedIpPacket packet) = 0; }; -struct EmulatedNetworkIncomingStats { +class EmulatedNetworkOutgoingStats { + public: + virtual ~EmulatedNetworkOutgoingStats() = default; + + virtual int64_t PacketsSent() const = 0; + + virtual DataSize BytesSent() const = 0; + + virtual DataSize FirstSentPacketSize() const = 0; + + // Returns time of the first packet sent or infinite value if no packets were + // sent. + virtual Timestamp FirstPacketSentTime() const = 0; + + // Returns time of the last packet sent or infinite value if no packets were + // sent. + virtual Timestamp LastPacketSentTime() const = 0; + + // Returns average send rate. Requires that at least 2 packets were sent. + virtual DataRate AverageSendRate() const = 0; +}; + +class EmulatedNetworkIncomingStats { + public: + virtual ~EmulatedNetworkIncomingStats() = default; + // Total amount of packets received with or without destination. - int64_t packets_received = 0; + virtual int64_t PacketsReceived() const = 0; // Total amount of bytes in received packets. - DataSize bytes_received = DataSize::Zero(); + virtual DataSize BytesReceived() const = 0; // Total amount of packets that were received, but no destination was found. - int64_t packets_dropped = 0; + virtual int64_t PacketsDropped() const = 0; // Total amount of bytes in dropped packets. - DataSize bytes_dropped = DataSize::Zero(); + virtual DataSize BytesDropped() const = 0; - DataSize first_received_packet_size = DataSize::Zero(); + virtual DataSize FirstReceivedPacketSize() const = 0; - // Timestamps are initialized to different infinities for simplifying - // computations. Client have to assume that it is some infinite value - // if unset. Client mustn't consider sign of infinit value. - Timestamp first_packet_received_time = Timestamp::PlusInfinity(); - Timestamp last_packet_received_time = Timestamp::MinusInfinity(); + // Returns time of the first packet received or infinite value if no packets + // were received. + virtual Timestamp FirstPacketReceivedTime() const = 0; - DataRate AverageReceiveRate() const { - RTC_DCHECK_GE(packets_received, 2); - RTC_DCHECK(first_packet_received_time.IsFinite()); - RTC_DCHECK(last_packet_received_time.IsFinite()); - return (bytes_received - first_received_packet_size) / - (last_packet_received_time - first_packet_received_time); - } + // Returns time of the last packet received or infinite value if no packets + // were received. + virtual Timestamp LastPacketReceivedTime() const = 0; + + virtual DataRate AverageReceiveRate() const = 0; }; class EmulatedNetworkStats { public: virtual ~EmulatedNetworkStats() = default; - virtual int64_t PacketsSent() const = 0; - - virtual DataSize BytesSent() const = 0; - // List of IP addresses that were used to send data considered in this stats // object. virtual std::vector LocalAddresses() const = 0; + virtual int64_t PacketsSent() const = 0; + + virtual DataSize BytesSent() const = 0; + virtual DataSize FirstSentPacketSize() const = 0; // Returns time of the first packet sent or infinite value if no packets were // sent. @@ -128,7 +149,12 @@ class EmulatedNetworkStats { virtual DataRate AverageReceiveRate() const = 0; - virtual std::map + virtual std::map> + OutgoingStatsPerDestination() const = 0; + + virtual std::map> IncomingStatsPerSource() const = 0; }; diff --git a/test/network/network_emulation.cc b/test/network/network_emulation.cc index 2a76725247..8de4cba78b 100644 --- a/test/network/network_emulation.cc +++ b/test/network/network_emulation.cc @@ -20,37 +20,66 @@ namespace webrtc { -EmulatedNetworkIncomingStats EmulatedNetworkStatsImpl::GetOverallIncomingStats() - const { - EmulatedNetworkIncomingStats stats; - for (const auto& entry : incoming_stats_per_source_) { - const EmulatedNetworkIncomingStats& source = entry.second; - stats.packets_received += source.packets_received; - stats.bytes_received += source.bytes_received; - stats.packets_dropped += source.packets_dropped; - stats.bytes_dropped += source.bytes_dropped; - if (stats.first_packet_received_time > source.first_packet_received_time) { - stats.first_packet_received_time = source.first_packet_received_time; - stats.first_received_packet_size = source.first_received_packet_size; - } - if (stats.last_packet_received_time < source.last_packet_received_time) { - stats.last_packet_received_time = source.last_packet_received_time; - } +DataRate EmulatedNetworkOutgoingStatsImpl::AverageSendRate() const { + RTC_DCHECK_GE(packets_sent_, 2); + RTC_DCHECK(first_packet_sent_time_.IsFinite()); + RTC_DCHECK(last_packet_sent_time_.IsFinite()); + return (bytes_sent_ - first_sent_packet_size_) / + (last_packet_sent_time_ - first_packet_sent_time_); +} + +DataRate EmulatedNetworkIncomingStatsImpl::AverageReceiveRate() const { + RTC_DCHECK_GE(packets_received_, 2); + RTC_DCHECK(first_packet_received_time_.IsFinite()); + RTC_DCHECK(last_packet_received_time_.IsFinite()); + return (bytes_received_ - first_received_packet_size_) / + (last_packet_received_time_ - first_packet_received_time_); +} + +std::map> +EmulatedNetworkStatsImpl::OutgoingStatsPerDestination() const { + std::map> out; + for (const auto& entry : outgoing_stats_per_destination_) { + out.emplace(entry.first, std::make_unique( + *entry.second)); } - return stats; + return out; } -EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder() { - sequence_checker_.Detach(); +std::map> +EmulatedNetworkStatsImpl::IncomingStatsPerSource() const { + std::map> out; + for (const auto& entry : incoming_stats_per_source_) { + out.emplace(entry.first, std::make_unique( + *entry.second)); + } + return out; } -EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder( - rtc::IPAddress local_ip) { - local_addresses_.push_back(local_ip); + +std::unique_ptr +EmulatedNetworkStatsImpl::GetOverallOutgoingStats() const { + EmulatedNetworkOutgoingStatsBuilder builder; + for (const auto& entry : outgoing_stats_per_destination_) { + builder.AddOutgoingStats(*entry.second); + } + return builder.Build(); +} + +std::unique_ptr +EmulatedNetworkStatsImpl::GetOverallIncomingStats() const { + EmulatedNetworkIncomingStatsBuilder builder; + for (const auto& entry : incoming_stats_per_source_) { + builder.AddIncomingStats(*entry.second); + } + return builder.Build(); +} + +EmulatedNetworkOutgoingStatsBuilder::EmulatedNetworkOutgoingStatsBuilder() { sequence_checker_.Detach(); } -void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time, - DataSize packet_size) { +void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent(Timestamp sent_time, + DataSize packet_size) { RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_CHECK_GE(packet_size, DataSize::Zero()); if (first_packet_sent_time_.IsInfinite()) { @@ -62,77 +91,150 @@ void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time, bytes_sent_ += packet_size; } +void EmulatedNetworkOutgoingStatsBuilder::AddOutgoingStats( + const EmulatedNetworkOutgoingStats& stats) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + packets_sent_ += stats.PacketsSent(); + bytes_sent_ += stats.BytesSent(); + if (first_packet_sent_time_ > stats.FirstPacketSentTime()) { + first_packet_sent_time_ = stats.FirstPacketSentTime(); + first_sent_packet_size_ = stats.FirstSentPacketSize(); + } + if (last_packet_sent_time_ < stats.LastPacketSentTime()) { + last_packet_sent_time_ = stats.LastPacketSentTime(); + } +} + +std::unique_ptr +EmulatedNetworkOutgoingStatsBuilder::Build() const { + RTC_DCHECK_RUN_ON(&sequence_checker_); + return std::make_unique( + packets_sent_, bytes_sent_, first_sent_packet_size_, + first_packet_sent_time_, last_packet_sent_time_); +} + +EmulatedNetworkIncomingStatsBuilder::EmulatedNetworkIncomingStatsBuilder() { + sequence_checker_.Detach(); +} + +void EmulatedNetworkIncomingStatsBuilder::OnPacketDropped( + DataSize packet_size) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + packets_dropped_++; + bytes_dropped_ += packet_size; +} + +void EmulatedNetworkIncomingStatsBuilder::OnPacketReceived( + Timestamp received_time, + DataSize packet_size) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + RTC_CHECK_GE(packet_size, DataSize::Zero()); + if (first_packet_received_time_.IsInfinite()) { + first_packet_received_time_ = received_time; + first_received_packet_size_ = packet_size; + } + last_packet_received_time_ = received_time; + packets_received_++; + bytes_received_ += packet_size; +} + +void EmulatedNetworkIncomingStatsBuilder::AddIncomingStats( + const EmulatedNetworkIncomingStats& stats) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + packets_received_ += stats.PacketsReceived(); + bytes_received_ += stats.BytesReceived(); + packets_dropped_ += stats.PacketsDropped(); + bytes_dropped_ += stats.BytesDropped(); + if (first_packet_received_time_ > stats.FirstPacketReceivedTime()) { + first_packet_received_time_ = stats.FirstPacketReceivedTime(); + first_received_packet_size_ = stats.FirstReceivedPacketSize(); + } + if (last_packet_received_time_ < stats.LastPacketReceivedTime()) { + last_packet_received_time_ = stats.LastPacketReceivedTime(); + } +} + +std::unique_ptr +EmulatedNetworkIncomingStatsBuilder::Build() const { + RTC_DCHECK_RUN_ON(&sequence_checker_); + return std::make_unique( + packets_received_, bytes_received_, packets_dropped_, bytes_dropped_, + first_received_packet_size_, first_packet_received_time_, + last_packet_received_time_); +} + +EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder() { + sequence_checker_.Detach(); +} + +EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder( + rtc::IPAddress local_ip) { + local_addresses_.push_back(local_ip); + sequence_checker_.Detach(); +} + +void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time, + rtc::IPAddress destination_ip, + DataSize packet_size) { + RTC_DCHECK_RUN_ON(&sequence_checker_); + outgoing_stats_per_destination_[destination_ip].OnPacketSent(sent_time, + packet_size); +} + void EmulatedNetworkStatsBuilder::OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size) { RTC_DCHECK_RUN_ON(&sequence_checker_); - RTC_CHECK_GE(packet_size, DataSize::Zero()); - EmulatedNetworkIncomingStats& source_stats = - incoming_stats_per_source_[source_ip]; - source_stats.packets_dropped++; - source_stats.bytes_dropped += packet_size; + incoming_stats_per_source_[source_ip].OnPacketDropped(packet_size); } void EmulatedNetworkStatsBuilder::OnPacketReceived(Timestamp received_time, rtc::IPAddress source_ip, DataSize packet_size) { RTC_DCHECK_RUN_ON(&sequence_checker_); - RTC_CHECK_GE(packet_size, DataSize::Zero()); - EmulatedNetworkIncomingStats& source_stats = - incoming_stats_per_source_[source_ip]; - if (source_stats.first_packet_received_time.IsInfinite()) { - source_stats.first_packet_received_time = received_time; - source_stats.first_received_packet_size = packet_size; - } - source_stats.last_packet_received_time = received_time; - source_stats.packets_received++; - source_stats.bytes_received += packet_size; + incoming_stats_per_source_[source_ip].OnPacketReceived(received_time, + packet_size); } -void EmulatedNetworkStatsBuilder::AppendEmulatedNetworkStats( - std::unique_ptr stats) { +void EmulatedNetworkStatsBuilder::AddEmulatedNetworkStats( + const EmulatedNetworkStats& stats) { RTC_DCHECK_RUN_ON(&sequence_checker_); - RTC_CHECK(stats); - packets_sent_ += stats->PacketsSent(); - bytes_sent_ += stats->BytesSent(); - if (first_packet_sent_time_ > stats->FirstPacketSentTime()) { - first_packet_sent_time_ = stats->FirstPacketSentTime(); - first_sent_packet_size_ = stats->FirstSentPacketSize(); - } - if (last_packet_sent_time_ < stats->LastPacketSentTime()) { - last_packet_sent_time_ = stats->LastPacketSentTime(); - } - for (const rtc::IPAddress& addr : stats->LocalAddresses()) { + + // Append IPs from other endpoints stats to the builder. + for (const rtc::IPAddress& addr : stats.LocalAddresses()) { local_addresses_.push_back(addr); } - const std::map - incoming_stats_per_source = stats->IncomingStatsPerSource(); + // Add outgoing stats from other endpoints to the builder. + const std::map> + outgoing_stats_per_destination = stats.OutgoingStatsPerDestination(); + for (const auto& entry : outgoing_stats_per_destination) { + outgoing_stats_per_destination_[entry.first].AddOutgoingStats( + *entry.second); + } + + // Add incoming stats from other endpoints to the builder. + const std::map> + incoming_stats_per_source = stats.IncomingStatsPerSource(); for (const auto& entry : incoming_stats_per_source) { - const EmulatedNetworkIncomingStats& source = entry.second; - EmulatedNetworkIncomingStats& in_stats = - incoming_stats_per_source_[entry.first]; - in_stats.packets_received += source.packets_received; - in_stats.bytes_received += source.bytes_received; - in_stats.packets_dropped += source.packets_dropped; - in_stats.bytes_dropped += source.bytes_dropped; - if (in_stats.first_packet_received_time > - source.first_packet_received_time) { - in_stats.first_packet_received_time = source.first_packet_received_time; - in_stats.first_received_packet_size = source.first_received_packet_size; - } - if (in_stats.last_packet_received_time < source.last_packet_received_time) { - in_stats.last_packet_received_time = source.last_packet_received_time; - } + incoming_stats_per_source_[entry.first].AddIncomingStats(*entry.second); } } std::unique_ptr EmulatedNetworkStatsBuilder::Build() const { RTC_DCHECK_RUN_ON(&sequence_checker_); + std::map> + outgoing_stats; + for (const auto& entry : outgoing_stats_per_destination_) { + outgoing_stats.emplace(entry.first, entry.second.Build()); + } + std::map> + incoming_stats; + for (const auto& entry : incoming_stats_per_source_) { + incoming_stats.emplace(entry.first, entry.second.Build()); + } return std::make_unique( - packets_sent_, bytes_sent_, local_addresses_, first_sent_packet_size_, - first_packet_sent_time_, last_packet_sent_time_, - incoming_stats_per_source_); + local_addresses_, std::move(outgoing_stats), std::move(incoming_stats)); } void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) { @@ -328,7 +430,7 @@ void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from, clock_->CurrentTime(), application_overhead); task_queue_->PostTask([this, packet = std::move(packet)]() mutable { RTC_DCHECK_RUN_ON(task_queue_); - stats_builder_.OnPacketSent(clock_->CurrentTime(), + stats_builder_.OnPacketSent(clock_->CurrentTime(), packet.to.ipaddr(), DataSize::Bytes(packet.ip_packet_size())); router_.OnPacketReceived(std::move(packet)); @@ -476,7 +578,7 @@ std::vector EndpointsContainer::endpoints() const { std::unique_ptr EndpointsContainer::GetStats() const { EmulatedNetworkStatsBuilder stats_builder; for (auto* endpoint : endpoints_) { - stats_builder.AppendEmulatedNetworkStats(endpoint->stats()); + stats_builder.AddEmulatedNetworkStats(*endpoint->stats()); } return stats_builder.Build(); } diff --git a/test/network/network_emulation.h b/test/network/network_emulation.h index 1525d881d8..5531efd041 100644 --- a/test/network/network_emulation.h +++ b/test/network/network_emulation.h @@ -36,35 +36,33 @@ namespace webrtc { -// This class is immutable and so is thread safe. -class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats { +// This class is immutable and so thread safe. +class EmulatedNetworkOutgoingStatsImpl final + : public EmulatedNetworkOutgoingStats { public: - EmulatedNetworkStatsImpl( - int64_t packets_sent, - DataSize bytes_sent, - std::vector local_addresses, - DataSize first_sent_packet_size, - Timestamp first_packet_sent_time, - Timestamp last_packet_sent_time, - std::map - incoming_stats_per_source) + EmulatedNetworkOutgoingStatsImpl(int64_t packets_sent, + DataSize bytes_sent, + DataSize first_sent_packet_size, + Timestamp first_packet_sent_time, + Timestamp last_packet_sent_time) : packets_sent_(packets_sent), bytes_sent_(bytes_sent), - local_addresses_(std::move(local_addresses)), first_sent_packet_size_(first_sent_packet_size), first_packet_sent_time_(first_packet_sent_time), - last_packet_sent_time_(last_packet_sent_time), - incoming_stats_per_source_(std::move(incoming_stats_per_source)) {} - ~EmulatedNetworkStatsImpl() override = default; + last_packet_sent_time_(last_packet_sent_time) {} + explicit EmulatedNetworkOutgoingStatsImpl( + const EmulatedNetworkOutgoingStats& stats) + : packets_sent_(stats.PacketsSent()), + bytes_sent_(stats.BytesSent()), + first_sent_packet_size_(stats.FirstSentPacketSize()), + first_packet_sent_time_(stats.FirstPacketSentTime()), + last_packet_sent_time_(stats.LastPacketSentTime()) {} + ~EmulatedNetworkOutgoingStatsImpl() override = default; int64_t PacketsSent() const override { return packets_sent_; } DataSize BytesSent() const override { return bytes_sent_; } - std::vector LocalAddresses() const override { - return local_addresses_; - } - DataSize FirstSentPacketSize() const override { return first_sent_packet_size_; } @@ -77,64 +75,220 @@ class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats { return last_packet_sent_time_; } - DataRate AverageSendRate() const override { - RTC_DCHECK_GE(packets_sent_, 2); - return (bytes_sent_ - first_sent_packet_size_) / - (last_packet_sent_time_ - first_packet_sent_time_); - } - - int64_t PacketsReceived() const override { - return GetOverallIncomingStats().packets_received; - } - - DataSize BytesReceived() const override { - return GetOverallIncomingStats().bytes_received; - } - - int64_t PacketsDropped() const override { - return GetOverallIncomingStats().packets_dropped; - } - - DataSize BytesDropped() const override { - return GetOverallIncomingStats().bytes_dropped; - } - - DataSize FirstReceivedPacketSize() const override { - return GetOverallIncomingStats().first_received_packet_size; - } - - Timestamp FirstPacketReceivedTime() const override { - return GetOverallIncomingStats().first_packet_received_time; - } - - Timestamp LastPacketReceivedTime() const override { - return GetOverallIncomingStats().last_packet_received_time; - } - - DataRate AverageReceiveRate() const override { - return GetOverallIncomingStats().AverageReceiveRate(); - } - - std::map - IncomingStatsPerSource() const override { - return incoming_stats_per_source_; - } + DataRate AverageSendRate() const override; private: - EmulatedNetworkIncomingStats GetOverallIncomingStats() const; - const int64_t packets_sent_; const DataSize bytes_sent_; - const std::vector local_addresses_; - const DataSize first_sent_packet_size_; const Timestamp first_packet_sent_time_; const Timestamp last_packet_sent_time_; +}; - const std::map +// This class is immutable and so thread safe. +class EmulatedNetworkIncomingStatsImpl final + : public EmulatedNetworkIncomingStats { + public: + EmulatedNetworkIncomingStatsImpl(int64_t packets_received, + DataSize bytes_received, + int64_t packets_dropped, + DataSize bytes_dropped, + DataSize first_received_packet_size, + Timestamp first_packet_received_time, + Timestamp last_packet_received_time) + : packets_received_(packets_received), + bytes_received_(bytes_received), + packets_dropped_(packets_dropped), + bytes_dropped_(bytes_dropped), + first_received_packet_size_(first_received_packet_size), + first_packet_received_time_(first_packet_received_time), + last_packet_received_time_(last_packet_received_time) {} + explicit EmulatedNetworkIncomingStatsImpl( + const EmulatedNetworkIncomingStats& stats) + : packets_received_(stats.PacketsReceived()), + bytes_received_(stats.BytesReceived()), + packets_dropped_(stats.PacketsDropped()), + bytes_dropped_(stats.BytesDropped()), + first_received_packet_size_(stats.FirstReceivedPacketSize()), + first_packet_received_time_(stats.FirstPacketReceivedTime()), + last_packet_received_time_(stats.LastPacketReceivedTime()) {} + ~EmulatedNetworkIncomingStatsImpl() override = default; + + int64_t PacketsReceived() const override { return packets_received_; } + + DataSize BytesReceived() const override { return bytes_received_; } + + int64_t PacketsDropped() const override { return packets_dropped_; } + + DataSize BytesDropped() const override { return bytes_dropped_; } + + DataSize FirstReceivedPacketSize() const override { + return first_received_packet_size_; + } + + Timestamp FirstPacketReceivedTime() const override { + return first_packet_received_time_; + } + + Timestamp LastPacketReceivedTime() const override { + return last_packet_received_time_; + } + + DataRate AverageReceiveRate() const override; + + private: + const int64_t packets_received_; + const DataSize bytes_received_; + const int64_t packets_dropped_; + const DataSize bytes_dropped_; + const DataSize first_received_packet_size_; + const Timestamp first_packet_received_time_; + const Timestamp last_packet_received_time_; +}; + +// This class is immutable and so is thread safe. +class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats { + public: + EmulatedNetworkStatsImpl( + std::vector local_addresses, + std::map> + outgoing_stats_per_destination, + std::map> + incoming_stats_per_source) + : local_addresses_(std::move(local_addresses)), + outgoing_stats_per_destination_( + std::move(outgoing_stats_per_destination)), + incoming_stats_per_source_(std::move(incoming_stats_per_source)) {} + ~EmulatedNetworkStatsImpl() override = default; + + std::vector LocalAddresses() const override { + return local_addresses_; + } + + int64_t PacketsSent() const override { + return GetOverallOutgoingStats()->PacketsSent(); + } + + DataSize BytesSent() const override { + return GetOverallOutgoingStats()->BytesSent(); + } + + DataSize FirstSentPacketSize() const override { + return GetOverallOutgoingStats()->FirstSentPacketSize(); + } + + Timestamp FirstPacketSentTime() const override { + return GetOverallOutgoingStats()->FirstPacketSentTime(); + } + + Timestamp LastPacketSentTime() const override { + return GetOverallOutgoingStats()->LastPacketSentTime(); + } + + DataRate AverageSendRate() const override { + return GetOverallOutgoingStats()->AverageSendRate(); + } + + int64_t PacketsReceived() const override { + return GetOverallIncomingStats()->PacketsReceived(); + } + + DataSize BytesReceived() const override { + return GetOverallIncomingStats()->BytesReceived(); + } + + int64_t PacketsDropped() const override { + return GetOverallIncomingStats()->PacketsDropped(); + } + + DataSize BytesDropped() const override { + return GetOverallIncomingStats()->BytesDropped(); + } + + DataSize FirstReceivedPacketSize() const override { + return GetOverallIncomingStats()->FirstReceivedPacketSize(); + } + + Timestamp FirstPacketReceivedTime() const override { + return GetOverallIncomingStats()->FirstPacketReceivedTime(); + } + + Timestamp LastPacketReceivedTime() const override { + return GetOverallIncomingStats()->LastPacketReceivedTime(); + } + + DataRate AverageReceiveRate() const override { + return GetOverallIncomingStats()->AverageReceiveRate(); + } + + std::map> + OutgoingStatsPerDestination() const override; + + std::map> + IncomingStatsPerSource() const override; + + private: + std::unique_ptr GetOverallOutgoingStats() const; + std::unique_ptr GetOverallIncomingStats() const; + + const std::vector local_addresses_; + const std::map> + outgoing_stats_per_destination_; + const std::map> incoming_stats_per_source_; }; +class EmulatedNetworkOutgoingStatsBuilder { + public: + EmulatedNetworkOutgoingStatsBuilder(); + + void OnPacketSent(Timestamp sent_time, DataSize packet_size); + + void AddOutgoingStats(const EmulatedNetworkOutgoingStats& stats); + + std::unique_ptr Build() const; + + private: + SequenceChecker sequence_checker_; + + int64_t packets_sent_ RTC_GUARDED_BY(sequence_checker_) = 0; + DataSize bytes_sent_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero(); + DataSize first_sent_packet_size_ RTC_GUARDED_BY(sequence_checker_) = + DataSize::Zero(); + Timestamp first_packet_sent_time_ RTC_GUARDED_BY(sequence_checker_) = + Timestamp::PlusInfinity(); + Timestamp last_packet_sent_time_ RTC_GUARDED_BY(sequence_checker_) = + Timestamp::MinusInfinity(); +}; + +class EmulatedNetworkIncomingStatsBuilder { + public: + EmulatedNetworkIncomingStatsBuilder(); + + void OnPacketDropped(DataSize packet_size); + + void OnPacketReceived(Timestamp received_time, DataSize packet_size); + + // Adds stats collected from another endpoints to the builder. + void AddIncomingStats(const EmulatedNetworkIncomingStats& stats); + + std::unique_ptr Build() const; + + private: + SequenceChecker sequence_checker_; + + int64_t packets_received_ RTC_GUARDED_BY(sequence_checker_) = 0; + DataSize bytes_received_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero(); + int64_t packets_dropped_ RTC_GUARDED_BY(sequence_checker_) = 0; + DataSize bytes_dropped_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero(); + DataSize first_received_packet_size_ RTC_GUARDED_BY(sequence_checker_) = + DataSize::Zero(); + Timestamp first_packet_received_time_ RTC_GUARDED_BY(sequence_checker_) = + Timestamp::PlusInfinity(); + Timestamp last_packet_received_time_ RTC_GUARDED_BY(sequence_checker_) = + Timestamp::MinusInfinity(); +}; + // All methods of EmulatedNetworkStatsBuilder have to be used on a single // thread. It may be created on another thread. class EmulatedNetworkStatsBuilder { @@ -142,7 +296,9 @@ class EmulatedNetworkStatsBuilder { EmulatedNetworkStatsBuilder(); explicit EmulatedNetworkStatsBuilder(rtc::IPAddress local_ip); - void OnPacketSent(Timestamp sent_time, DataSize packet_size); + void OnPacketSent(Timestamp sent_time, + rtc::IPAddress destination_ip, + DataSize packet_size); void OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size); @@ -150,26 +306,18 @@ class EmulatedNetworkStatsBuilder { rtc::IPAddress source_ip, DataSize packet_size); - void AppendEmulatedNetworkStats(std::unique_ptr stats); + void AddEmulatedNetworkStats(const EmulatedNetworkStats& stats); std::unique_ptr Build() const; private: SequenceChecker sequence_checker_; - int64_t packets_sent_ RTC_GUARDED_BY(sequence_checker_) = 0; - DataSize bytes_sent_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero(); std::vector local_addresses_ RTC_GUARDED_BY(sequence_checker_); - - DataSize first_sent_packet_size_ RTC_GUARDED_BY(sequence_checker_) = - DataSize::Zero(); - Timestamp first_packet_sent_time_ RTC_GUARDED_BY(sequence_checker_) = - Timestamp::PlusInfinity(); - Timestamp last_packet_sent_time_ RTC_GUARDED_BY(sequence_checker_) = - Timestamp::MinusInfinity(); - - std::map + std::map + outgoing_stats_per_destination_ RTC_GUARDED_BY(sequence_checker_); + std::map incoming_stats_per_source_ RTC_GUARDED_BY(sequence_checker_); }; diff --git a/test/network/network_emulation_manager.cc b/test/network/network_emulation_manager.cc index afe5033e30..b5ba4545ba 100644 --- a/test/network/network_emulation_manager.cc +++ b/test/network/network_emulation_manager.cc @@ -301,7 +301,7 @@ void NetworkEmulationManagerImpl::GetStats( task_queue_.PostTask([endpoints, stats_callback]() { EmulatedNetworkStatsBuilder stats_builder; for (auto* endpoint : endpoints) { - stats_builder.AppendEmulatedNetworkStats(endpoint->stats()); + stats_builder.AddEmulatedNetworkStats(*endpoint->stats()); } stats_callback(stats_builder.Build()); }); diff --git a/test/network/network_emulation_unittest.cc b/test/network/network_emulation_unittest.cc index 6914c6e039..f9f088a693 100644 --- a/test/network/network_emulation_unittest.cc +++ b/test/network/network_emulation_unittest.cc @@ -257,20 +257,22 @@ TEST(NetworkEmulationManagerTest, Run) { EXPECT_EQ(st->PacketsDropped(), 0l); EXPECT_EQ(st->BytesDropped().bytes(), 0l); - std::map source_st = - st->IncomingStatsPerSource(); + rtc::IPAddress bob_ip = bob_endpoint->GetPeerLocalAddress(); + std::map> + source_st = st->IncomingStatsPerSource(); ASSERT_EQ(source_st.size(), 1lu); - EXPECT_EQ( - source_st.at(bob_endpoint->GetPeerLocalAddress()).packets_received, - 2000l); - EXPECT_EQ(source_st.at(bob_endpoint->GetPeerLocalAddress()) - .bytes_received.bytes(), + EXPECT_EQ(source_st.at(bob_ip)->PacketsReceived(), 2000l); + EXPECT_EQ(source_st.at(bob_ip)->BytesReceived().bytes(), + single_packet_size * 2000l); + EXPECT_EQ(source_st.at(bob_ip)->PacketsDropped(), 0l); + EXPECT_EQ(source_st.at(bob_ip)->BytesDropped().bytes(), 0l); + + std::map> + dest_st = st->OutgoingStatsPerDestination(); + ASSERT_EQ(dest_st.size(), 1lu); + EXPECT_EQ(dest_st.at(bob_ip)->PacketsSent(), 2000l); + EXPECT_EQ(dest_st.at(bob_ip)->BytesSent().bytes(), single_packet_size * 2000l); - EXPECT_EQ(source_st.at(bob_endpoint->GetPeerLocalAddress()).packets_dropped, - 0l); - EXPECT_EQ( - source_st.at(bob_endpoint->GetPeerLocalAddress()).bytes_dropped.bytes(), - 0l); received_stats_count++; }); nt2->GetStats([&](std::unique_ptr st) { @@ -286,21 +288,22 @@ TEST(NetworkEmulationManagerTest, Run) { EXPECT_TRUE(st->FirstPacketReceivedTime().IsFinite()); EXPECT_TRUE(st->LastPacketReceivedTime().IsFinite()); - std::map source_st = - st->IncomingStatsPerSource(); + rtc::IPAddress alice_ip = alice_endpoint->GetPeerLocalAddress(); + std::map> + source_st = st->IncomingStatsPerSource(); ASSERT_EQ(source_st.size(), 1lu); - EXPECT_EQ( - source_st.at(alice_endpoint->GetPeerLocalAddress()).packets_received, - 2000l); - EXPECT_EQ(source_st.at(alice_endpoint->GetPeerLocalAddress()) - .bytes_received.bytes(), + EXPECT_EQ(source_st.at(alice_ip)->PacketsReceived(), 2000l); + EXPECT_EQ(source_st.at(alice_ip)->BytesReceived().bytes(), + single_packet_size * 2000l); + EXPECT_EQ(source_st.at(alice_ip)->PacketsDropped(), 0l); + EXPECT_EQ(source_st.at(alice_ip)->BytesDropped().bytes(), 0l); + + std::map> + dest_st = st->OutgoingStatsPerDestination(); + ASSERT_EQ(dest_st.size(), 1lu); + EXPECT_EQ(dest_st.at(alice_ip)->PacketsSent(), 2000l); + EXPECT_EQ(dest_st.at(alice_ip)->BytesSent().bytes(), single_packet_size * 2000l); - EXPECT_EQ( - source_st.at(alice_endpoint->GetPeerLocalAddress()).packets_dropped, - 0l); - EXPECT_EQ(source_st.at(alice_endpoint->GetPeerLocalAddress()) - .bytes_dropped.bytes(), - 0l); received_stats_count++; }); ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2,