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 <crodbro@webrtc.org>
Reviewed-by: Andrey Logvin <landrey@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31820}
diff --git a/api/test/network_emulation/network_emulation_interfaces.h b/api/test/network_emulation/network_emulation_interfaces.h
index b1aa0d2..ebb1eed 100644
--- a/api/test/network_emulation/network_emulation_interfaces.h
+++ b/api/test/network_emulation/network_emulation_interfaces.h
@@ -61,45 +61,66 @@
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<rtc::IPAddress> 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 @@
virtual DataRate AverageReceiveRate() const = 0;
- virtual std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
+ virtual std::map<rtc::IPAddress,
+ std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ OutgoingStatsPerDestination() const = 0;
+
+ virtual std::map<rtc::IPAddress,
+ std::unique_ptr<EmulatedNetworkIncomingStats>>
IncomingStatsPerSource() const = 0;
};
diff --git a/test/network/network_emulation.cc b/test/network/network_emulation.cc
index 2a76725..8de4cba 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<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+EmulatedNetworkStatsImpl::OutgoingStatsPerDestination() const {
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> out;
+ for (const auto& entry : outgoing_stats_per_destination_) {
+ out.emplace(entry.first, std::make_unique<EmulatedNetworkOutgoingStatsImpl>(
+ *entry.second));
}
- return stats;
+ return out;
}
-EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder() {
- sequence_checker_.Detach();
+std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+EmulatedNetworkStatsImpl::IncomingStatsPerSource() const {
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> out;
+ for (const auto& entry : incoming_stats_per_source_) {
+ out.emplace(entry.first, std::make_unique<EmulatedNetworkIncomingStatsImpl>(
+ *entry.second));
+ }
+ return out;
}
-EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder(
- rtc::IPAddress local_ip) {
- local_addresses_.push_back(local_ip);
+
+std::unique_ptr<EmulatedNetworkOutgoingStats>
+EmulatedNetworkStatsImpl::GetOverallOutgoingStats() const {
+ EmulatedNetworkOutgoingStatsBuilder builder;
+ for (const auto& entry : outgoing_stats_per_destination_) {
+ builder.AddOutgoingStats(*entry.second);
+ }
+ return builder.Build();
+}
+
+std::unique_ptr<EmulatedNetworkIncomingStats>
+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 @@
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<EmulatedNetworkOutgoingStats>
+EmulatedNetworkOutgoingStatsBuilder::Build() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ return std::make_unique<EmulatedNetworkOutgoingStatsImpl>(
+ 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<EmulatedNetworkIncomingStats>
+EmulatedNetworkIncomingStatsBuilder::Build() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ return std::make_unique<EmulatedNetworkIncomingStatsImpl>(
+ 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<EmulatedNetworkStats> 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<rtc::IPAddress, EmulatedNetworkIncomingStats>
- incoming_stats_per_source = stats->IncomingStatsPerSource();
+ // Add outgoing stats from other endpoints to the builder.
+ const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ 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<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+ 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<EmulatedNetworkStats> EmulatedNetworkStatsBuilder::Build()
const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ outgoing_stats;
+ for (const auto& entry : outgoing_stats_per_destination_) {
+ outgoing_stats.emplace(entry.first, entry.second.Build());
+ }
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+ incoming_stats;
+ for (const auto& entry : incoming_stats_per_source_) {
+ incoming_stats.emplace(entry.first, entry.second.Build());
+ }
return std::make_unique<EmulatedNetworkStatsImpl>(
- 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 @@
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::unique_ptr<EmulatedNetworkStats> 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 1525d88..5531efd 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<rtc::IPAddress> local_addresses,
- DataSize first_sent_packet_size,
- Timestamp first_packet_sent_time,
- Timestamp last_packet_sent_time,
- std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
- 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<rtc::IPAddress> LocalAddresses() const override {
- return local_addresses_;
- }
-
DataSize FirstSentPacketSize() const override {
return first_sent_packet_size_;
}
@@ -77,64 +75,220 @@
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<rtc::IPAddress, EmulatedNetworkIncomingStats>
- 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<rtc::IPAddress> local_addresses_;
-
const DataSize first_sent_packet_size_;
const Timestamp first_packet_sent_time_;
const Timestamp last_packet_sent_time_;
+};
- const std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
+// 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<rtc::IPAddress> local_addresses,
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ outgoing_stats_per_destination,
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+ 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<rtc::IPAddress> 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<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ OutgoingStatsPerDestination() const override;
+
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+ IncomingStatsPerSource() const override;
+
+ private:
+ std::unique_ptr<EmulatedNetworkOutgoingStats> GetOverallOutgoingStats() const;
+ std::unique_ptr<EmulatedNetworkIncomingStats> GetOverallIncomingStats() const;
+
+ const std::vector<rtc::IPAddress> local_addresses_;
+ const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ outgoing_stats_per_destination_;
+ const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
incoming_stats_per_source_;
};
+class EmulatedNetworkOutgoingStatsBuilder {
+ public:
+ EmulatedNetworkOutgoingStatsBuilder();
+
+ void OnPacketSent(Timestamp sent_time, DataSize packet_size);
+
+ void AddOutgoingStats(const EmulatedNetworkOutgoingStats& stats);
+
+ std::unique_ptr<EmulatedNetworkOutgoingStats> 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<EmulatedNetworkIncomingStats> 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 @@
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 @@
rtc::IPAddress source_ip,
DataSize packet_size);
- void AppendEmulatedNetworkStats(std::unique_ptr<EmulatedNetworkStats> stats);
+ void AddEmulatedNetworkStats(const EmulatedNetworkStats& stats);
std::unique_ptr<EmulatedNetworkStats> 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<rtc::IPAddress> 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<rtc::IPAddress, EmulatedNetworkIncomingStats>
+ std::map<rtc::IPAddress, EmulatedNetworkOutgoingStatsBuilder>
+ outgoing_stats_per_destination_ RTC_GUARDED_BY(sequence_checker_);
+ std::map<rtc::IPAddress, EmulatedNetworkIncomingStatsBuilder>
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 afe5033..b5ba454 100644
--- a/test/network/network_emulation_manager.cc
+++ b/test/network/network_emulation_manager.cc
@@ -301,7 +301,7 @@
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 6914c6e..f9f088a 100644
--- a/test/network/network_emulation_unittest.cc
+++ b/test/network/network_emulation_unittest.cc
@@ -257,20 +257,22 @@
EXPECT_EQ(st->PacketsDropped(), 0l);
EXPECT_EQ(st->BytesDropped().bytes(), 0l);
- std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> source_st =
- st->IncomingStatsPerSource();
+ rtc::IPAddress bob_ip = bob_endpoint->GetPeerLocalAddress();
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+ 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_endpoint->GetPeerLocalAddress()).packets_dropped,
- 0l);
- EXPECT_EQ(
- source_st.at(bob_endpoint->GetPeerLocalAddress()).bytes_dropped.bytes(),
- 0l);
+ EXPECT_EQ(source_st.at(bob_ip)->PacketsDropped(), 0l);
+ EXPECT_EQ(source_st.at(bob_ip)->BytesDropped().bytes(), 0l);
+
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ 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);
received_stats_count++;
});
nt2->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) {
@@ -286,21 +288,22 @@
EXPECT_TRUE(st->FirstPacketReceivedTime().IsFinite());
EXPECT_TRUE(st->LastPacketReceivedTime().IsFinite());
- std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> source_st =
- st->IncomingStatsPerSource();
+ rtc::IPAddress alice_ip = alice_endpoint->GetPeerLocalAddress();
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
+ 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_endpoint->GetPeerLocalAddress()).packets_dropped,
- 0l);
- EXPECT_EQ(source_st.at(alice_endpoint->GetPeerLocalAddress())
- .bytes_dropped.bytes(),
- 0l);
+ EXPECT_EQ(source_st.at(alice_ip)->PacketsDropped(), 0l);
+ EXPECT_EQ(source_st.at(alice_ip)->BytesDropped().bytes(), 0l);
+
+ std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
+ 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);
received_stats_count++;
});
ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2,