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}
This commit is contained in:
Artem Titov 2020-07-31 12:57:24 +02:00 committed by Commit Bot
parent 81bbd7199a
commit 14b46a77b2
5 changed files with 481 additions and 202 deletions

View File

@ -61,45 +61,66 @@ class EmulatedNetworkReceiverInterface {
virtual void OnPacketReceived(EmulatedIpPacket packet) = 0; 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. // 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. // 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. // 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. // 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 // Returns time of the first packet received or infinite value if no packets
// computations. Client have to assume that it is some infinite value // were received.
// if unset. Client mustn't consider sign of infinit value. virtual Timestamp FirstPacketReceivedTime() const = 0;
Timestamp first_packet_received_time = Timestamp::PlusInfinity();
Timestamp last_packet_received_time = Timestamp::MinusInfinity();
DataRate AverageReceiveRate() const { // Returns time of the last packet received or infinite value if no packets
RTC_DCHECK_GE(packets_received, 2); // were received.
RTC_DCHECK(first_packet_received_time.IsFinite()); virtual Timestamp LastPacketReceivedTime() const = 0;
RTC_DCHECK(last_packet_received_time.IsFinite());
return (bytes_received - first_received_packet_size) / virtual DataRate AverageReceiveRate() const = 0;
(last_packet_received_time - first_packet_received_time);
}
}; };
class EmulatedNetworkStats { class EmulatedNetworkStats {
public: public:
virtual ~EmulatedNetworkStats() = default; 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 // List of IP addresses that were used to send data considered in this stats
// object. // object.
virtual std::vector<rtc::IPAddress> LocalAddresses() const = 0; virtual std::vector<rtc::IPAddress> LocalAddresses() const = 0;
virtual int64_t PacketsSent() const = 0;
virtual DataSize BytesSent() const = 0;
virtual DataSize FirstSentPacketSize() const = 0; virtual DataSize FirstSentPacketSize() const = 0;
// Returns time of the first packet sent or infinite value if no packets were // Returns time of the first packet sent or infinite value if no packets were
// sent. // sent.
@ -128,7 +149,12 @@ class EmulatedNetworkStats {
virtual DataRate AverageReceiveRate() const = 0; 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; IncomingStatsPerSource() const = 0;
}; };

View File

@ -20,36 +20,65 @@
namespace webrtc { namespace webrtc {
EmulatedNetworkIncomingStats EmulatedNetworkStatsImpl::GetOverallIncomingStats() DataRate EmulatedNetworkOutgoingStatsImpl::AverageSendRate() const {
const { RTC_DCHECK_GE(packets_sent_, 2);
EmulatedNetworkIncomingStats stats; 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 out;
}
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_) { for (const auto& entry : incoming_stats_per_source_) {
const EmulatedNetworkIncomingStats& source = entry.second; out.emplace(entry.first, std::make_unique<EmulatedNetworkIncomingStatsImpl>(
stats.packets_received += source.packets_received; *entry.second));
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) { return out;
stats.last_packet_received_time = source.last_packet_received_time;
}
}
return stats;
} }
EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder() { std::unique_ptr<EmulatedNetworkOutgoingStats>
sequence_checker_.Detach(); EmulatedNetworkStatsImpl::GetOverallOutgoingStats() const {
EmulatedNetworkOutgoingStatsBuilder builder;
for (const auto& entry : outgoing_stats_per_destination_) {
builder.AddOutgoingStats(*entry.second);
}
return builder.Build();
} }
EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder(
rtc::IPAddress local_ip) { std::unique_ptr<EmulatedNetworkIncomingStats>
local_addresses_.push_back(local_ip); 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(); sequence_checker_.Detach();
} }
void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time, void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent(Timestamp sent_time,
DataSize packet_size) { DataSize packet_size) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_CHECK_GE(packet_size, DataSize::Zero()); RTC_CHECK_GE(packet_size, DataSize::Zero());
@ -62,77 +91,150 @@ void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time,
bytes_sent_ += packet_size; bytes_sent_ += packet_size;
} }
void EmulatedNetworkStatsBuilder::OnPacketDropped(rtc::IPAddress source_ip, 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) { DataSize packet_size) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_CHECK_GE(packet_size, DataSize::Zero()); RTC_CHECK_GE(packet_size, DataSize::Zero());
EmulatedNetworkIncomingStats& source_stats = if (first_packet_received_time_.IsInfinite()) {
incoming_stats_per_source_[source_ip]; first_packet_received_time_ = received_time;
source_stats.packets_dropped++; first_received_packet_size_ = packet_size;
source_stats.bytes_dropped += 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_);
incoming_stats_per_source_[source_ip].OnPacketDropped(packet_size);
} }
void EmulatedNetworkStatsBuilder::OnPacketReceived(Timestamp received_time, void EmulatedNetworkStatsBuilder::OnPacketReceived(Timestamp received_time,
rtc::IPAddress source_ip, rtc::IPAddress source_ip,
DataSize packet_size) { DataSize packet_size) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_CHECK_GE(packet_size, DataSize::Zero()); incoming_stats_per_source_[source_ip].OnPacketReceived(received_time,
EmulatedNetworkIncomingStats& source_stats = packet_size);
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;
} }
void EmulatedNetworkStatsBuilder::AppendEmulatedNetworkStats( void EmulatedNetworkStatsBuilder::AddEmulatedNetworkStats(
std::unique_ptr<EmulatedNetworkStats> stats) { const EmulatedNetworkStats& stats) {
RTC_DCHECK_RUN_ON(&sequence_checker_); RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_CHECK(stats);
packets_sent_ += stats->PacketsSent(); // Append IPs from other endpoints stats to the builder.
bytes_sent_ += stats->BytesSent(); for (const rtc::IPAddress& addr : stats.LocalAddresses()) {
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()) {
local_addresses_.push_back(addr); local_addresses_.push_back(addr);
} }
const std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> // Add outgoing stats from other endpoints to the builder.
incoming_stats_per_source = stats->IncomingStatsPerSource(); 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) { for (const auto& entry : incoming_stats_per_source) {
const EmulatedNetworkIncomingStats& source = entry.second; incoming_stats_per_source_[entry.first].AddIncomingStats(*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;
}
} }
} }
std::unique_ptr<EmulatedNetworkStats> EmulatedNetworkStatsBuilder::Build() std::unique_ptr<EmulatedNetworkStats> EmulatedNetworkStatsBuilder::Build()
const { const {
RTC_DCHECK_RUN_ON(&sequence_checker_); 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>( return std::make_unique<EmulatedNetworkStatsImpl>(
packets_sent_, bytes_sent_, local_addresses_, first_sent_packet_size_, local_addresses_, std::move(outgoing_stats), std::move(incoming_stats));
first_packet_sent_time_, last_packet_sent_time_,
incoming_stats_per_source_);
} }
void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) { void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
@ -328,7 +430,7 @@ void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
clock_->CurrentTime(), application_overhead); clock_->CurrentTime(), application_overhead);
task_queue_->PostTask([this, packet = std::move(packet)]() mutable { task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
RTC_DCHECK_RUN_ON(task_queue_); 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())); DataSize::Bytes(packet.ip_packet_size()));
router_.OnPacketReceived(std::move(packet)); router_.OnPacketReceived(std::move(packet));
@ -476,7 +578,7 @@ std::vector<EmulatedEndpoint*> EndpointsContainer::endpoints() const {
std::unique_ptr<EmulatedNetworkStats> EndpointsContainer::GetStats() const { std::unique_ptr<EmulatedNetworkStats> EndpointsContainer::GetStats() const {
EmulatedNetworkStatsBuilder stats_builder; EmulatedNetworkStatsBuilder stats_builder;
for (auto* endpoint : endpoints_) { for (auto* endpoint : endpoints_) {
stats_builder.AppendEmulatedNetworkStats(endpoint->stats()); stats_builder.AddEmulatedNetworkStats(*endpoint->stats());
} }
return stats_builder.Build(); return stats_builder.Build();
} }

View File

@ -36,35 +36,33 @@
namespace webrtc { namespace webrtc {
// This class is immutable and so is thread safe. // This class is immutable and so thread safe.
class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats { class EmulatedNetworkOutgoingStatsImpl final
: public EmulatedNetworkOutgoingStats {
public: public:
EmulatedNetworkStatsImpl( EmulatedNetworkOutgoingStatsImpl(int64_t packets_sent,
int64_t packets_sent,
DataSize bytes_sent, DataSize bytes_sent,
std::vector<rtc::IPAddress> local_addresses,
DataSize first_sent_packet_size, DataSize first_sent_packet_size,
Timestamp first_packet_sent_time, Timestamp first_packet_sent_time,
Timestamp last_packet_sent_time, Timestamp last_packet_sent_time)
std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
incoming_stats_per_source)
: packets_sent_(packets_sent), : packets_sent_(packets_sent),
bytes_sent_(bytes_sent), bytes_sent_(bytes_sent),
local_addresses_(std::move(local_addresses)),
first_sent_packet_size_(first_sent_packet_size), first_sent_packet_size_(first_sent_packet_size),
first_packet_sent_time_(first_packet_sent_time), first_packet_sent_time_(first_packet_sent_time),
last_packet_sent_time_(last_packet_sent_time), last_packet_sent_time_(last_packet_sent_time) {}
incoming_stats_per_source_(std::move(incoming_stats_per_source)) {} explicit EmulatedNetworkOutgoingStatsImpl(
~EmulatedNetworkStatsImpl() override = default; 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_; } int64_t PacketsSent() const override { return packets_sent_; }
DataSize BytesSent() const override { return bytes_sent_; } DataSize BytesSent() const override { return bytes_sent_; }
std::vector<rtc::IPAddress> LocalAddresses() const override {
return local_addresses_;
}
DataSize FirstSentPacketSize() const override { DataSize FirstSentPacketSize() const override {
return first_sent_packet_size_; return first_sent_packet_size_;
} }
@ -77,64 +75,220 @@ class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats {
return last_packet_sent_time_; return last_packet_sent_time_;
} }
DataRate AverageSendRate() const override { 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_;
}
private: private:
EmulatedNetworkIncomingStats GetOverallIncomingStats() const;
const int64_t packets_sent_; const int64_t packets_sent_;
const DataSize bytes_sent_; const DataSize bytes_sent_;
const std::vector<rtc::IPAddress> local_addresses_;
const DataSize first_sent_packet_size_; const DataSize first_sent_packet_size_;
const Timestamp first_packet_sent_time_; const Timestamp first_packet_sent_time_;
const Timestamp last_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_; 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 // All methods of EmulatedNetworkStatsBuilder have to be used on a single
// thread. It may be created on another thread. // thread. It may be created on another thread.
class EmulatedNetworkStatsBuilder { class EmulatedNetworkStatsBuilder {
@ -142,7 +296,9 @@ class EmulatedNetworkStatsBuilder {
EmulatedNetworkStatsBuilder(); EmulatedNetworkStatsBuilder();
explicit EmulatedNetworkStatsBuilder(rtc::IPAddress local_ip); 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); void OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size);
@ -150,26 +306,18 @@ class EmulatedNetworkStatsBuilder {
rtc::IPAddress source_ip, rtc::IPAddress source_ip,
DataSize packet_size); DataSize packet_size);
void AppendEmulatedNetworkStats(std::unique_ptr<EmulatedNetworkStats> stats); void AddEmulatedNetworkStats(const EmulatedNetworkStats& stats);
std::unique_ptr<EmulatedNetworkStats> Build() const; std::unique_ptr<EmulatedNetworkStats> Build() const;
private: private:
SequenceChecker sequence_checker_; 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_ std::vector<rtc::IPAddress> local_addresses_
RTC_GUARDED_BY(sequence_checker_); RTC_GUARDED_BY(sequence_checker_);
std::map<rtc::IPAddress, EmulatedNetworkOutgoingStatsBuilder>
DataSize first_sent_packet_size_ RTC_GUARDED_BY(sequence_checker_) = outgoing_stats_per_destination_ RTC_GUARDED_BY(sequence_checker_);
DataSize::Zero(); std::map<rtc::IPAddress, EmulatedNetworkIncomingStatsBuilder>
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>
incoming_stats_per_source_ RTC_GUARDED_BY(sequence_checker_); incoming_stats_per_source_ RTC_GUARDED_BY(sequence_checker_);
}; };

View File

@ -301,7 +301,7 @@ void NetworkEmulationManagerImpl::GetStats(
task_queue_.PostTask([endpoints, stats_callback]() { task_queue_.PostTask([endpoints, stats_callback]() {
EmulatedNetworkStatsBuilder stats_builder; EmulatedNetworkStatsBuilder stats_builder;
for (auto* endpoint : endpoints) { for (auto* endpoint : endpoints) {
stats_builder.AppendEmulatedNetworkStats(endpoint->stats()); stats_builder.AddEmulatedNetworkStats(*endpoint->stats());
} }
stats_callback(stats_builder.Build()); stats_callback(stats_builder.Build());
}); });

View File

@ -257,20 +257,22 @@ TEST(NetworkEmulationManagerTest, Run) {
EXPECT_EQ(st->PacketsDropped(), 0l); EXPECT_EQ(st->PacketsDropped(), 0l);
EXPECT_EQ(st->BytesDropped().bytes(), 0l); EXPECT_EQ(st->BytesDropped().bytes(), 0l);
std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> source_st = rtc::IPAddress bob_ip = bob_endpoint->GetPeerLocalAddress();
st->IncomingStatsPerSource(); std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
source_st = st->IncomingStatsPerSource();
ASSERT_EQ(source_st.size(), 1lu); ASSERT_EQ(source_st.size(), 1lu);
EXPECT_EQ( EXPECT_EQ(source_st.at(bob_ip)->PacketsReceived(), 2000l);
source_st.at(bob_endpoint->GetPeerLocalAddress()).packets_received, EXPECT_EQ(source_st.at(bob_ip)->BytesReceived().bytes(),
2000l); single_packet_size * 2000l);
EXPECT_EQ(source_st.at(bob_endpoint->GetPeerLocalAddress()) EXPECT_EQ(source_st.at(bob_ip)->PacketsDropped(), 0l);
.bytes_received.bytes(), 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); 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++; received_stats_count++;
}); });
nt2->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) { nt2->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) {
@ -286,21 +288,22 @@ TEST(NetworkEmulationManagerTest, Run) {
EXPECT_TRUE(st->FirstPacketReceivedTime().IsFinite()); EXPECT_TRUE(st->FirstPacketReceivedTime().IsFinite());
EXPECT_TRUE(st->LastPacketReceivedTime().IsFinite()); EXPECT_TRUE(st->LastPacketReceivedTime().IsFinite());
std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> source_st = rtc::IPAddress alice_ip = alice_endpoint->GetPeerLocalAddress();
st->IncomingStatsPerSource(); std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
source_st = st->IncomingStatsPerSource();
ASSERT_EQ(source_st.size(), 1lu); ASSERT_EQ(source_st.size(), 1lu);
EXPECT_EQ( EXPECT_EQ(source_st.at(alice_ip)->PacketsReceived(), 2000l);
source_st.at(alice_endpoint->GetPeerLocalAddress()).packets_received, EXPECT_EQ(source_st.at(alice_ip)->BytesReceived().bytes(),
2000l); single_packet_size * 2000l);
EXPECT_EQ(source_st.at(alice_endpoint->GetPeerLocalAddress()) EXPECT_EQ(source_st.at(alice_ip)->PacketsDropped(), 0l);
.bytes_received.bytes(), 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); 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++; received_stats_count++;
}); });
ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2, ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2,