Replace network layer stats struct with interface
It is a follow up CL to https://webrtc-review.googlesource.com/c/src/+/179368. Now when network stats became more complex structure it's better to hide its implementation details and provide an interface for read-only access. Bug: webrtc:11756 Change-Id: I1980ef938f8de0c6aa90092d1dc90a14a82e0ee1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/179840 Commit-Queue: Tommi <tommi@webrtc.org> Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Tommi <tommi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31784}
This commit is contained in:
@ -17,6 +17,7 @@ rtc_library("network_emulation") {
|
|||||||
]
|
]
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
|
"../..:array_view",
|
||||||
"../../../rtc_base",
|
"../../../rtc_base",
|
||||||
"../../../rtc_base:checks",
|
"../../../rtc_base:checks",
|
||||||
"../../../rtc_base:rtc_base_approved",
|
"../../../rtc_base:rtc_base_approved",
|
||||||
|
@ -11,9 +11,11 @@
|
|||||||
#define API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
|
#define API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
|
#include "api/array_view.h"
|
||||||
#include "api/units/data_rate.h"
|
#include "api/units/data_rate.h"
|
||||||
#include "api/units/data_size.h"
|
#include "api/units/data_size.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
@ -86,107 +88,48 @@ struct EmulatedNetworkIncomingStats {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EmulatedNetworkStats {
|
class EmulatedNetworkStats {
|
||||||
int64_t packets_sent = 0;
|
public:
|
||||||
DataSize bytes_sent = DataSize::Zero();
|
virtual ~EmulatedNetworkStats() = default;
|
||||||
|
|
||||||
DataSize first_sent_packet_size = DataSize::Zero();
|
virtual int64_t PacketsSent() const = 0;
|
||||||
Timestamp first_packet_sent_time = Timestamp::PlusInfinity();
|
|
||||||
Timestamp last_packet_sent_time = Timestamp::MinusInfinity();
|
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.
|
||||||
std::vector<rtc::IPAddress> local_addresses;
|
virtual std::vector<rtc::IPAddress> LocalAddresses() const = 0;
|
||||||
|
|
||||||
std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
|
virtual DataSize FirstSentPacketSize() const = 0;
|
||||||
incoming_stats_per_source;
|
// Returns time of the first packet sent or infinite value if no packets were
|
||||||
|
// sent.
|
||||||
DataRate AverageSendRate() const {
|
virtual Timestamp FirstPacketSentTime() const = 0;
|
||||||
RTC_DCHECK_GE(packets_sent, 2);
|
// Returns time of the last packet sent or infinite value if no packets were
|
||||||
return (bytes_sent - first_sent_packet_size) /
|
// sent.
|
||||||
(last_packet_sent_time - first_packet_sent_time);
|
virtual Timestamp LastPacketSentTime() const = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
virtual DataRate AverageSendRate() const = 0;
|
||||||
// Total amount of packets received regardless of the destination address.
|
// Total amount of packets received regardless of the destination address.
|
||||||
int64_t PacketsReceived() const {
|
virtual int64_t PacketsReceived() const = 0;
|
||||||
int64_t packets_received = 0;
|
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
|
||||||
packets_received += incoming_stats.second.packets_received;
|
|
||||||
}
|
|
||||||
return packets_received;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Total amount of bytes in received packets.
|
// Total amount of bytes in received packets.
|
||||||
DataSize BytesReceived() const {
|
virtual DataSize BytesReceived() const = 0;
|
||||||
DataSize bytes_received = DataSize::Zero();
|
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
|
||||||
bytes_received += incoming_stats.second.bytes_received;
|
|
||||||
}
|
|
||||||
return bytes_received;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 PacketsDropped() const {
|
virtual int64_t PacketsDropped() const = 0;
|
||||||
int64_t packets_dropped = 0;
|
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
|
||||||
packets_dropped += incoming_stats.second.packets_dropped;
|
|
||||||
}
|
|
||||||
return packets_dropped;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Total amount of bytes in dropped packets.
|
// Total amount of bytes in dropped packets.
|
||||||
DataSize BytesDropped() const {
|
virtual DataSize BytesDropped() const = 0;
|
||||||
DataSize bytes_dropped = DataSize::Zero();
|
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
|
||||||
bytes_dropped += incoming_stats.second.bytes_dropped;
|
|
||||||
}
|
|
||||||
return bytes_dropped;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataSize FirstReceivedPacketSize() const {
|
virtual DataSize FirstReceivedPacketSize() const = 0;
|
||||||
Timestamp first_packet_received_time = Timestamp::PlusInfinity();
|
// Returns time of the first packet received or infinite value if no packets
|
||||||
DataSize first_received_packet_size = DataSize::Zero();
|
// were received.
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
virtual Timestamp FirstPacketReceivedTime() const = 0;
|
||||||
if (first_packet_received_time >
|
// Returns time of the last packet received or infinite value if no packets
|
||||||
incoming_stats.second.first_packet_received_time) {
|
// were received.
|
||||||
first_packet_received_time =
|
virtual Timestamp LastPacketReceivedTime() const = 0;
|
||||||
incoming_stats.second.first_packet_received_time;
|
|
||||||
first_received_packet_size =
|
|
||||||
incoming_stats.second.first_received_packet_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return first_received_packet_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timestamp FirstPacketReceivedTime() const {
|
virtual DataRate AverageReceiveRate() const = 0;
|
||||||
Timestamp first_packet_received_time = Timestamp::PlusInfinity();
|
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
|
||||||
if (first_packet_received_time >
|
|
||||||
incoming_stats.second.first_packet_received_time) {
|
|
||||||
first_packet_received_time =
|
|
||||||
incoming_stats.second.first_packet_received_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return first_packet_received_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
Timestamp LastPacketReceivedTime() const {
|
virtual std::map<rtc::IPAddress, EmulatedNetworkIncomingStats>
|
||||||
Timestamp last_packet_received_time = Timestamp::MinusInfinity();
|
IncomingStatsPerSource() const = 0;
|
||||||
for (const auto& incoming_stats : incoming_stats_per_source) {
|
|
||||||
if (last_packet_received_time <
|
|
||||||
incoming_stats.second.last_packet_received_time) {
|
|
||||||
last_packet_received_time =
|
|
||||||
incoming_stats.second.last_packet_received_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return last_packet_received_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataRate AverageReceiveRate() const {
|
|
||||||
RTC_DCHECK_GE(PacketsReceived(), 2);
|
|
||||||
return (BytesReceived() - FirstReceivedPacketSize()) /
|
|
||||||
(LastPacketReceivedTime() - FirstPacketReceivedTime());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// EmulatedEndpoint is an abstraction for network interface on device. Instances
|
// EmulatedEndpoint is an abstraction for network interface on device. Instances
|
||||||
@ -218,7 +161,7 @@ class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
|
|||||||
virtual void UnbindReceiver(uint16_t port) = 0;
|
virtual void UnbindReceiver(uint16_t port) = 0;
|
||||||
virtual rtc::IPAddress GetPeerLocalAddress() const = 0;
|
virtual rtc::IPAddress GetPeerLocalAddress() const = 0;
|
||||||
|
|
||||||
virtual EmulatedNetworkStats stats() = 0;
|
virtual std::unique_ptr<EmulatedNetworkStats> stats() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Ensure that there can be no other subclass than EmulatedEndpointImpl. This
|
// Ensure that there can be no other subclass than EmulatedEndpointImpl. This
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#ifndef API_TEST_NETWORK_EMULATION_MANAGER_H_
|
#ifndef API_TEST_NETWORK_EMULATION_MANAGER_H_
|
||||||
#define API_TEST_NETWORK_EMULATION_MANAGER_H_
|
#define API_TEST_NETWORK_EMULATION_MANAGER_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -69,7 +70,8 @@ class EmulatedNetworkManagerInterface {
|
|||||||
|
|
||||||
// Returns summarized network stats for endpoints for this manager.
|
// Returns summarized network stats for endpoints for this manager.
|
||||||
virtual void GetStats(
|
virtual void GetStats(
|
||||||
std::function<void(EmulatedNetworkStats)> stats_callback) const = 0;
|
std::function<void(std::unique_ptr<EmulatedNetworkStats>)> stats_callback)
|
||||||
|
const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TimeMode { kRealTime, kSimulated };
|
enum class TimeMode { kRealTime, kSimulated };
|
||||||
|
@ -35,6 +35,7 @@ rtc_library("emulated_network") {
|
|||||||
"traffic_route.h",
|
"traffic_route.h",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
|
"../../api:array_view",
|
||||||
"../../api:network_emulation_manager_api",
|
"../../api:network_emulation_manager_api",
|
||||||
"../../api:simulated_network_api",
|
"../../api:simulated_network_api",
|
||||||
"../../api:time_controller",
|
"../../api:time_controller",
|
||||||
|
@ -80,7 +80,8 @@ void EmulatedNetworkManager::StopUpdating() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmulatedNetworkManager::GetStats(
|
void EmulatedNetworkManager::GetStats(
|
||||||
std::function<void(EmulatedNetworkStats)> stats_callback) const {
|
std::function<void(std::unique_ptr<EmulatedNetworkStats>)> stats_callback)
|
||||||
|
const {
|
||||||
task_queue_->PostTask([stats_callback, this]() {
|
task_queue_->PostTask([stats_callback, this]() {
|
||||||
stats_callback(endpoints_container_->GetStats());
|
stats_callback(endpoints_container_->GetStats());
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#ifndef TEST_NETWORK_EMULATED_NETWORK_MANAGER_H_
|
#ifndef TEST_NETWORK_EMULATED_NETWORK_MANAGER_H_
|
||||||
#define TEST_NETWORK_EMULATED_NETWORK_MANAGER_H_
|
#define TEST_NETWORK_EMULATED_NETWORK_MANAGER_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -49,8 +50,8 @@ class EmulatedNetworkManager : public rtc::NetworkManagerBase,
|
|||||||
// EmulatedNetworkManagerInterface API
|
// EmulatedNetworkManagerInterface API
|
||||||
rtc::Thread* network_thread() override { return network_thread_.get(); }
|
rtc::Thread* network_thread() override { return network_thread_.get(); }
|
||||||
rtc::NetworkManager* network_manager() override { return this; }
|
rtc::NetworkManager* network_manager() override { return this; }
|
||||||
void GetStats(
|
void GetStats(std::function<void(std::unique_ptr<EmulatedNetworkStats>)>
|
||||||
std::function<void(EmulatedNetworkStats)> stats_callback) const override;
|
stats_callback) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateNetworksOnce();
|
void UpdateNetworksOnce();
|
||||||
|
@ -20,6 +20,121 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
DataSize packet_size) {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
|
RTC_CHECK_GE(packet_size, DataSize::Zero());
|
||||||
|
if (first_packet_sent_time_.IsInfinite()) {
|
||||||
|
first_packet_sent_time_ = sent_time;
|
||||||
|
first_sent_packet_size_ = packet_size;
|
||||||
|
}
|
||||||
|
last_packet_sent_time_ = sent_time;
|
||||||
|
packets_sent_++;
|
||||||
|
bytes_sent_ += 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmulatedNetworkStatsBuilder::AppendEmulatedNetworkStats(
|
||||||
|
std::unique_ptr<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()) {
|
||||||
|
local_addresses_.push_back(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::map<rtc::IPAddress, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<EmulatedNetworkStats> EmulatedNetworkStatsBuilder::Build()
|
||||||
|
const {
|
||||||
|
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
|
||||||
void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
|
void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
|
||||||
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_);
|
||||||
@ -179,7 +294,8 @@ EmulatedEndpointImpl::EmulatedEndpointImpl(uint64_t id,
|
|||||||
clock_(clock),
|
clock_(clock),
|
||||||
task_queue_(task_queue),
|
task_queue_(task_queue),
|
||||||
router_(task_queue_),
|
router_(task_queue_),
|
||||||
next_port_(kFirstEphemeralPort) {
|
next_port_(kFirstEphemeralPort),
|
||||||
|
stats_builder_(peer_local_addr_) {
|
||||||
constexpr int kIPv4NetworkPrefixLength = 24;
|
constexpr int kIPv4NetworkPrefixLength = 24;
|
||||||
constexpr int kIPv6NetworkPrefixLength = 64;
|
constexpr int kIPv6NetworkPrefixLength = 64;
|
||||||
|
|
||||||
@ -196,7 +312,6 @@ EmulatedEndpointImpl::EmulatedEndpointImpl(uint64_t id,
|
|||||||
network_->AddIP(ip);
|
network_->AddIP(ip);
|
||||||
|
|
||||||
enabled_state_checker_.Detach();
|
enabled_state_checker_.Detach();
|
||||||
stats_.local_addresses.push_back(peer_local_addr_);
|
|
||||||
}
|
}
|
||||||
EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
|
EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
|
||||||
|
|
||||||
@ -213,14 +328,8 @@ 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_);
|
||||||
Timestamp current_time = clock_->CurrentTime();
|
stats_builder_.OnPacketSent(clock_->CurrentTime(),
|
||||||
if (stats_.first_packet_sent_time.IsInfinite()) {
|
DataSize::Bytes(packet.ip_packet_size()));
|
||||||
stats_.first_packet_sent_time = current_time;
|
|
||||||
stats_.first_sent_packet_size = DataSize::Bytes(packet.ip_packet_size());
|
|
||||||
}
|
|
||||||
stats_.last_packet_sent_time = current_time;
|
|
||||||
stats_.packets_sent++;
|
|
||||||
stats_.bytes_sent += DataSize::Bytes(packet.ip_packet_size());
|
|
||||||
|
|
||||||
router_.OnPacketReceived(std::move(packet));
|
router_.OnPacketReceived(std::move(packet));
|
||||||
});
|
});
|
||||||
@ -283,7 +392,8 @@ void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
|
|||||||
<< packet.to.ipaddr().ToString()
|
<< packet.to.ipaddr().ToString()
|
||||||
<< "; Receiver peer_local_addr_=" << peer_local_addr_.ToString();
|
<< "; Receiver peer_local_addr_=" << peer_local_addr_.ToString();
|
||||||
rtc::CritScope crit(&receiver_lock_);
|
rtc::CritScope crit(&receiver_lock_);
|
||||||
UpdateReceiveStats(packet);
|
stats_builder_.OnPacketReceived(clock_->CurrentTime(), packet.from.ipaddr(),
|
||||||
|
DataSize::Bytes(packet.ip_packet_size()));
|
||||||
auto it = port_to_receiver_.find(packet.to.port());
|
auto it = port_to_receiver_.find(packet.to.port());
|
||||||
if (it == port_to_receiver_.end()) {
|
if (it == port_to_receiver_.end()) {
|
||||||
// It can happen, that remote peer closed connection, but there still some
|
// It can happen, that remote peer closed connection, but there still some
|
||||||
@ -291,9 +401,8 @@ void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
|
|||||||
// process: one peer closed connection, second still sending data.
|
// process: one peer closed connection, second still sending data.
|
||||||
RTC_LOG(INFO) << "Drop packet: no receiver registered in " << id_
|
RTC_LOG(INFO) << "Drop packet: no receiver registered in " << id_
|
||||||
<< " on port " << packet.to.port();
|
<< " on port " << packet.to.port();
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()].packets_dropped++;
|
stats_builder_.OnPacketDropped(packet.from.ipaddr(),
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()].bytes_dropped +=
|
DataSize::Bytes(packet.ip_packet_size()));
|
||||||
DataSize::Bytes(packet.ip_packet_size());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Endpoint assumes frequent calls to bind and unbind methods, so it holds
|
// Endpoint assumes frequent calls to bind and unbind methods, so it holds
|
||||||
@ -319,26 +428,9 @@ bool EmulatedEndpointImpl::Enabled() const {
|
|||||||
return is_enabled_;
|
return is_enabled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmulatedNetworkStats EmulatedEndpointImpl::stats() {
|
std::unique_ptr<EmulatedNetworkStats> EmulatedEndpointImpl::stats() const {
|
||||||
RTC_DCHECK_RUN_ON(task_queue_);
|
RTC_DCHECK_RUN_ON(task_queue_);
|
||||||
return stats_;
|
return stats_builder_.Build();
|
||||||
}
|
|
||||||
|
|
||||||
void EmulatedEndpointImpl::UpdateReceiveStats(const EmulatedIpPacket& packet) {
|
|
||||||
RTC_DCHECK_RUN_ON(task_queue_);
|
|
||||||
Timestamp current_time = clock_->CurrentTime();
|
|
||||||
if (stats_.incoming_stats_per_source[packet.from.ipaddr()]
|
|
||||||
.first_packet_received_time.IsInfinite()) {
|
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()]
|
|
||||||
.first_packet_received_time = current_time;
|
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()]
|
|
||||||
.first_received_packet_size = DataSize::Bytes(packet.ip_packet_size());
|
|
||||||
}
|
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()]
|
|
||||||
.last_packet_received_time = current_time;
|
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()].packets_received++;
|
|
||||||
stats_.incoming_stats_per_source[packet.from.ipaddr()].bytes_received +=
|
|
||||||
DataSize::Bytes(packet.ip_packet_size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EndpointsContainer::EndpointsContainer(
|
EndpointsContainer::EndpointsContainer(
|
||||||
@ -377,42 +469,12 @@ EndpointsContainer::GetEnabledNetworks() const {
|
|||||||
return networks;
|
return networks;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmulatedNetworkStats EndpointsContainer::GetStats() const {
|
std::unique_ptr<EmulatedNetworkStats> EndpointsContainer::GetStats() const {
|
||||||
EmulatedNetworkStats stats;
|
EmulatedNetworkStatsBuilder stats_builder;
|
||||||
for (auto* endpoint : endpoints_) {
|
for (auto* endpoint : endpoints_) {
|
||||||
EmulatedNetworkStats endpoint_stats = endpoint->stats();
|
stats_builder.AppendEmulatedNetworkStats(endpoint->stats());
|
||||||
stats.packets_sent += endpoint_stats.packets_sent;
|
|
||||||
stats.bytes_sent += endpoint_stats.bytes_sent;
|
|
||||||
if (stats.first_packet_sent_time > endpoint_stats.first_packet_sent_time) {
|
|
||||||
stats.first_packet_sent_time = endpoint_stats.first_packet_sent_time;
|
|
||||||
stats.first_sent_packet_size = endpoint_stats.first_sent_packet_size;
|
|
||||||
}
|
|
||||||
if (stats.last_packet_sent_time < endpoint_stats.last_packet_sent_time) {
|
|
||||||
stats.last_packet_sent_time = endpoint_stats.last_packet_sent_time;
|
|
||||||
}
|
|
||||||
for (const rtc::IPAddress& addr : endpoint_stats.local_addresses) {
|
|
||||||
stats.local_addresses.push_back(addr);
|
|
||||||
}
|
|
||||||
for (auto& entry : endpoint_stats.incoming_stats_per_source) {
|
|
||||||
const EmulatedNetworkIncomingStats& source = entry.second;
|
|
||||||
EmulatedNetworkIncomingStats& in_stats =
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return stats;
|
return stats_builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
|
#include "api/array_view.h"
|
||||||
#include "api/test/network_emulation_manager.h"
|
#include "api/test/network_emulation_manager.h"
|
||||||
#include "api/test/simulated_network.h"
|
#include "api/test/simulated_network.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#include "rtc_base/network.h"
|
#include "rtc_base/network.h"
|
||||||
#include "rtc_base/network_constants.h"
|
#include "rtc_base/network_constants.h"
|
||||||
#include "rtc_base/socket_address.h"
|
#include "rtc_base/socket_address.h"
|
||||||
|
#include "rtc_base/synchronization/sequence_checker.h"
|
||||||
#include "rtc_base/task_queue_for_test.h"
|
#include "rtc_base/task_queue_for_test.h"
|
||||||
#include "rtc_base/task_utils/repeating_task.h"
|
#include "rtc_base/task_utils/repeating_task.h"
|
||||||
#include "rtc_base/thread_checker.h"
|
#include "rtc_base/thread_checker.h"
|
||||||
@ -34,6 +36,142 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
// This class is immutable and so is thread safe.
|
||||||
|
class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats {
|
||||||
|
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)
|
||||||
|
: 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;
|
||||||
|
|
||||||
|
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_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timestamp FirstPacketSentTime() const override {
|
||||||
|
return first_packet_sent_time_;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timestamp LastPacketSentTime() const override {
|
||||||
|
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_;
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
incoming_stats_per_source_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// All methods of EmulatedNetworkStatsBuilder have to be used on a single
|
||||||
|
// thread. It may be created on another thread.
|
||||||
|
class EmulatedNetworkStatsBuilder {
|
||||||
|
public:
|
||||||
|
EmulatedNetworkStatsBuilder();
|
||||||
|
explicit EmulatedNetworkStatsBuilder(rtc::IPAddress local_ip);
|
||||||
|
|
||||||
|
void OnPacketSent(Timestamp sent_time, DataSize packet_size);
|
||||||
|
|
||||||
|
void OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size);
|
||||||
|
|
||||||
|
void OnPacketReceived(Timestamp received_time,
|
||||||
|
rtc::IPAddress source_ip,
|
||||||
|
DataSize packet_size);
|
||||||
|
|
||||||
|
void AppendEmulatedNetworkStats(std::unique_ptr<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>
|
||||||
|
incoming_stats_per_source_ RTC_GUARDED_BY(sequence_checker_);
|
||||||
|
};
|
||||||
|
|
||||||
class LinkEmulation : public EmulatedNetworkReceiverInterface {
|
class LinkEmulation : public EmulatedNetworkReceiverInterface {
|
||||||
public:
|
public:
|
||||||
@ -161,12 +299,11 @@ class EmulatedEndpointImpl : public EmulatedEndpoint {
|
|||||||
|
|
||||||
const rtc::Network& network() const { return *network_.get(); }
|
const rtc::Network& network() const { return *network_.get(); }
|
||||||
|
|
||||||
EmulatedNetworkStats stats() override;
|
std::unique_ptr<EmulatedNetworkStats> stats() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr uint16_t kFirstEphemeralPort = 49152;
|
static constexpr uint16_t kFirstEphemeralPort = 49152;
|
||||||
uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
|
uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
|
||||||
void UpdateReceiveStats(const EmulatedIpPacket& packet);
|
|
||||||
|
|
||||||
rtc::RecursiveCriticalSection receiver_lock_;
|
rtc::RecursiveCriticalSection receiver_lock_;
|
||||||
rtc::ThreadChecker enabled_state_checker_;
|
rtc::ThreadChecker enabled_state_checker_;
|
||||||
@ -185,7 +322,7 @@ class EmulatedEndpointImpl : public EmulatedEndpoint {
|
|||||||
std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
|
std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
|
||||||
RTC_GUARDED_BY(receiver_lock_);
|
RTC_GUARDED_BY(receiver_lock_);
|
||||||
|
|
||||||
EmulatedNetworkStats stats_ RTC_GUARDED_BY(task_queue_);
|
EmulatedNetworkStatsBuilder stats_builder_ RTC_GUARDED_BY(task_queue_);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmulatedRoute {
|
class EmulatedRoute {
|
||||||
@ -212,7 +349,7 @@ class EndpointsContainer {
|
|||||||
// Returns list of networks for enabled endpoints. Caller takes ownership of
|
// Returns list of networks for enabled endpoints. Caller takes ownership of
|
||||||
// returned rtc::Network objects.
|
// returned rtc::Network objects.
|
||||||
std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
|
std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
|
||||||
EmulatedNetworkStats GetStats() const;
|
std::unique_ptr<EmulatedNetworkStats> GetStats() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<EmulatedEndpointImpl*> endpoints_;
|
const std::vector<EmulatedEndpointImpl*> endpoints_;
|
||||||
|
@ -247,59 +247,60 @@ TEST(NetworkEmulationManagerTest, Run) {
|
|||||||
|
|
||||||
const int64_t single_packet_size = data.size() + kOverheadIpv4Udp;
|
const int64_t single_packet_size = data.size() + kOverheadIpv4Udp;
|
||||||
std::atomic<int> received_stats_count{0};
|
std::atomic<int> received_stats_count{0};
|
||||||
nt1->GetStats([&](EmulatedNetworkStats st) {
|
nt1->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) {
|
||||||
EXPECT_EQ(st.packets_sent, 2000l);
|
EXPECT_EQ(st->PacketsSent(), 2000l);
|
||||||
EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 2000l);
|
EXPECT_EQ(st->BytesSent().bytes(), single_packet_size * 2000l);
|
||||||
EXPECT_THAT(st.local_addresses,
|
EXPECT_THAT(st->LocalAddresses(),
|
||||||
ElementsAreArray({alice_endpoint->GetPeerLocalAddress()}));
|
ElementsAreArray({alice_endpoint->GetPeerLocalAddress()}));
|
||||||
EXPECT_EQ(st.PacketsReceived(), 2000l);
|
EXPECT_EQ(st->PacketsReceived(), 2000l);
|
||||||
EXPECT_EQ(st.BytesReceived().bytes(), single_packet_size * 2000l);
|
EXPECT_EQ(st->BytesReceived().bytes(), single_packet_size * 2000l);
|
||||||
EXPECT_EQ(st.PacketsDropped(), 0l);
|
EXPECT_EQ(st->PacketsDropped(), 0l);
|
||||||
EXPECT_EQ(st.BytesDropped().bytes(), 0l);
|
EXPECT_EQ(st->BytesDropped().bytes(), 0l);
|
||||||
|
|
||||||
EXPECT_EQ(st.incoming_stats_per_source[bob_endpoint->GetPeerLocalAddress()]
|
std::map<rtc::IPAddress, EmulatedNetworkIncomingStats> source_st =
|
||||||
.packets_received,
|
st->IncomingStatsPerSource();
|
||||||
2000l);
|
ASSERT_EQ(source_st.size(), 1lu);
|
||||||
EXPECT_EQ(st.incoming_stats_per_source[bob_endpoint->GetPeerLocalAddress()]
|
EXPECT_EQ(
|
||||||
|
source_st.at(bob_endpoint->GetPeerLocalAddress()).packets_received,
|
||||||
|
2000l);
|
||||||
|
EXPECT_EQ(source_st.at(bob_endpoint->GetPeerLocalAddress())
|
||||||
.bytes_received.bytes(),
|
.bytes_received.bytes(),
|
||||||
single_packet_size * 2000l);
|
single_packet_size * 2000l);
|
||||||
EXPECT_EQ(st.incoming_stats_per_source[bob_endpoint->GetPeerLocalAddress()]
|
EXPECT_EQ(source_st.at(bob_endpoint->GetPeerLocalAddress()).packets_dropped,
|
||||||
.packets_dropped,
|
|
||||||
0l);
|
|
||||||
EXPECT_EQ(st.incoming_stats_per_source[bob_endpoint->GetPeerLocalAddress()]
|
|
||||||
.bytes_dropped.bytes(),
|
|
||||||
0l);
|
0l);
|
||||||
|
EXPECT_EQ(
|
||||||
|
source_st.at(bob_endpoint->GetPeerLocalAddress()).bytes_dropped.bytes(),
|
||||||
|
0l);
|
||||||
received_stats_count++;
|
received_stats_count++;
|
||||||
});
|
});
|
||||||
nt2->GetStats([&](EmulatedNetworkStats st) {
|
nt2->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) {
|
||||||
EXPECT_EQ(st.packets_sent, 2000l);
|
EXPECT_EQ(st->PacketsSent(), 2000l);
|
||||||
EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * 2000l);
|
EXPECT_EQ(st->BytesSent().bytes(), single_packet_size * 2000l);
|
||||||
EXPECT_THAT(st.local_addresses,
|
EXPECT_THAT(st->LocalAddresses(),
|
||||||
ElementsAreArray({bob_endpoint->GetPeerLocalAddress()}));
|
ElementsAreArray({bob_endpoint->GetPeerLocalAddress()}));
|
||||||
EXPECT_EQ(st.PacketsReceived(), 2000l);
|
EXPECT_EQ(st->PacketsReceived(), 2000l);
|
||||||
EXPECT_EQ(st.BytesReceived().bytes(), single_packet_size * 2000l);
|
EXPECT_EQ(st->BytesReceived().bytes(), single_packet_size * 2000l);
|
||||||
EXPECT_EQ(st.PacketsDropped(), 0l);
|
EXPECT_EQ(st->PacketsDropped(), 0l);
|
||||||
EXPECT_EQ(st.BytesDropped().bytes(), 0l);
|
EXPECT_EQ(st->BytesDropped().bytes(), 0l);
|
||||||
EXPECT_GT(st.FirstReceivedPacketSize(), DataSize::Zero());
|
EXPECT_GT(st->FirstReceivedPacketSize(), DataSize::Zero());
|
||||||
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 =
|
||||||
|
st->IncomingStatsPerSource();
|
||||||
|
ASSERT_EQ(source_st.size(), 1lu);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
st.incoming_stats_per_source[alice_endpoint->GetPeerLocalAddress()]
|
source_st.at(alice_endpoint->GetPeerLocalAddress()).packets_received,
|
||||||
.packets_received,
|
|
||||||
2000l);
|
2000l);
|
||||||
|
EXPECT_EQ(source_st.at(alice_endpoint->GetPeerLocalAddress())
|
||||||
|
.bytes_received.bytes(),
|
||||||
|
single_packet_size * 2000l);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
st.incoming_stats_per_source[alice_endpoint->GetPeerLocalAddress()]
|
source_st.at(alice_endpoint->GetPeerLocalAddress()).packets_dropped,
|
||||||
.bytes_received.bytes(),
|
|
||||||
single_packet_size * 2000l);
|
|
||||||
EXPECT_EQ(
|
|
||||||
st.incoming_stats_per_source[alice_endpoint->GetPeerLocalAddress()]
|
|
||||||
.packets_dropped,
|
|
||||||
0l);
|
|
||||||
EXPECT_EQ(
|
|
||||||
st.incoming_stats_per_source[alice_endpoint->GetPeerLocalAddress()]
|
|
||||||
.bytes_dropped.bytes(),
|
|
||||||
0l);
|
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,
|
||||||
@ -363,14 +364,14 @@ TEST(NetworkEmulationManagerTest, ThroughputStats) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::atomic<int> received_stats_count{0};
|
std::atomic<int> received_stats_count{0};
|
||||||
nt1->GetStats([&](EmulatedNetworkStats st) {
|
nt1->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) {
|
||||||
EXPECT_EQ(st.packets_sent, kNumPacketsSent);
|
EXPECT_EQ(st->PacketsSent(), kNumPacketsSent);
|
||||||
EXPECT_EQ(st.bytes_sent.bytes(), kSinglePacketSize * kNumPacketsSent);
|
EXPECT_EQ(st->BytesSent().bytes(), kSinglePacketSize * kNumPacketsSent);
|
||||||
|
|
||||||
const double tolerance = 0.95; // Accept 5% tolerance for timing.
|
const double tolerance = 0.95; // Accept 5% tolerance for timing.
|
||||||
EXPECT_GE(st.last_packet_sent_time - st.first_packet_sent_time,
|
EXPECT_GE(st->LastPacketSentTime() - st->FirstPacketSentTime(),
|
||||||
(kNumPacketsSent - 1) * kDelay * tolerance);
|
(kNumPacketsSent - 1) * kDelay * tolerance);
|
||||||
EXPECT_GT(st.AverageSendRate().bps(), 0);
|
EXPECT_GT(st->AverageSendRate().bps(), 0);
|
||||||
received_stats_count++;
|
received_stats_count++;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,12 +34,13 @@ void NetworkQualityMetricsReporter::Start(
|
|||||||
const TrackIdStreamInfoMap* /*reporter_helper*/) {
|
const TrackIdStreamInfoMap* /*reporter_helper*/) {
|
||||||
test_case_name_ = std::string(test_case_name);
|
test_case_name_ = std::string(test_case_name);
|
||||||
// Check that network stats are clean before test execution.
|
// Check that network stats are clean before test execution.
|
||||||
EmulatedNetworkStats alice_stats = PopulateStats(alice_network_);
|
std::unique_ptr<EmulatedNetworkStats> alice_stats =
|
||||||
RTC_CHECK_EQ(alice_stats.packets_sent, 0);
|
PopulateStats(alice_network_);
|
||||||
RTC_CHECK_EQ(alice_stats.PacketsReceived(), 0);
|
RTC_CHECK_EQ(alice_stats->PacketsSent(), 0);
|
||||||
EmulatedNetworkStats bob_stats = PopulateStats(bob_network_);
|
RTC_CHECK_EQ(alice_stats->PacketsReceived(), 0);
|
||||||
RTC_CHECK_EQ(bob_stats.packets_sent, 0);
|
std::unique_ptr<EmulatedNetworkStats> bob_stats = PopulateStats(bob_network_);
|
||||||
RTC_CHECK_EQ(bob_stats.PacketsReceived(), 0);
|
RTC_CHECK_EQ(bob_stats->PacketsSent(), 0);
|
||||||
|
RTC_CHECK_EQ(bob_stats->PacketsReceived(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkQualityMetricsReporter::OnStatsReports(
|
void NetworkQualityMetricsReporter::OnStatsReports(
|
||||||
@ -69,12 +70,15 @@ void NetworkQualityMetricsReporter::OnStatsReports(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NetworkQualityMetricsReporter::StopAndReportResults() {
|
void NetworkQualityMetricsReporter::StopAndReportResults() {
|
||||||
EmulatedNetworkStats alice_stats = PopulateStats(alice_network_);
|
std::unique_ptr<EmulatedNetworkStats> alice_stats =
|
||||||
EmulatedNetworkStats bob_stats = PopulateStats(bob_network_);
|
PopulateStats(alice_network_);
|
||||||
ReportStats("alice", alice_stats,
|
std::unique_ptr<EmulatedNetworkStats> bob_stats = PopulateStats(bob_network_);
|
||||||
alice_stats.packets_sent - bob_stats.PacketsReceived());
|
int64_t alice_packets_loss =
|
||||||
ReportStats("bob", bob_stats,
|
alice_stats->PacketsSent() - bob_stats->PacketsReceived();
|
||||||
bob_stats.packets_sent - alice_stats.PacketsReceived());
|
int64_t bob_packets_loss =
|
||||||
|
bob_stats->PacketsSent() - alice_stats->PacketsReceived();
|
||||||
|
ReportStats("alice", std::move(alice_stats), alice_packets_loss);
|
||||||
|
ReportStats("bob", std::move(bob_stats), bob_packets_loss);
|
||||||
|
|
||||||
if (!webrtc::field_trial::IsEnabled(kUseStandardBytesStats)) {
|
if (!webrtc::field_trial::IsEnabled(kUseStandardBytesStats)) {
|
||||||
RTC_LOG(LS_ERROR)
|
RTC_LOG(LS_ERROR)
|
||||||
@ -87,12 +91,13 @@ void NetworkQualityMetricsReporter::StopAndReportResults() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EmulatedNetworkStats NetworkQualityMetricsReporter::PopulateStats(
|
std::unique_ptr<EmulatedNetworkStats>
|
||||||
|
NetworkQualityMetricsReporter::PopulateStats(
|
||||||
EmulatedNetworkManagerInterface* network) {
|
EmulatedNetworkManagerInterface* network) {
|
||||||
rtc::Event wait;
|
rtc::Event wait;
|
||||||
EmulatedNetworkStats stats;
|
std::unique_ptr<EmulatedNetworkStats> stats;
|
||||||
network->GetStats([&](const EmulatedNetworkStats& s) {
|
network->GetStats([&](std::unique_ptr<EmulatedNetworkStats> s) {
|
||||||
stats = s;
|
stats = std::move(s);
|
||||||
wait.Set();
|
wait.Set();
|
||||||
});
|
});
|
||||||
bool stats_received = wait.Wait(kStatsWaitTimeoutMs);
|
bool stats_received = wait.Wait(kStatsWaitTimeoutMs);
|
||||||
@ -102,26 +107,26 @@ EmulatedNetworkStats NetworkQualityMetricsReporter::PopulateStats(
|
|||||||
|
|
||||||
void NetworkQualityMetricsReporter::ReportStats(
|
void NetworkQualityMetricsReporter::ReportStats(
|
||||||
const std::string& network_label,
|
const std::string& network_label,
|
||||||
const EmulatedNetworkStats& stats,
|
std::unique_ptr<EmulatedNetworkStats> stats,
|
||||||
int64_t packet_loss) {
|
int64_t packet_loss) {
|
||||||
ReportResult("bytes_sent", network_label, stats.bytes_sent.bytes(),
|
ReportResult("bytes_sent", network_label, stats->BytesSent().bytes(),
|
||||||
"sizeInBytes");
|
"sizeInBytes");
|
||||||
ReportResult("packets_sent", network_label, stats.packets_sent, "unitless");
|
ReportResult("packets_sent", network_label, stats->PacketsSent(), "unitless");
|
||||||
ReportResult(
|
ReportResult(
|
||||||
"average_send_rate", network_label,
|
"average_send_rate", network_label,
|
||||||
stats.packets_sent >= 2 ? stats.AverageSendRate().bytes_per_sec() : 0,
|
stats->PacketsSent() >= 2 ? stats->AverageSendRate().bytes_per_sec() : 0,
|
||||||
"bytesPerSecond");
|
"bytesPerSecond");
|
||||||
ReportResult("bytes_dropped", network_label, stats.BytesDropped().bytes(),
|
ReportResult("bytes_dropped", network_label, stats->BytesDropped().bytes(),
|
||||||
"sizeInBytes");
|
"sizeInBytes");
|
||||||
ReportResult("packets_dropped", network_label, stats.PacketsDropped(),
|
ReportResult("packets_dropped", network_label, stats->PacketsDropped(),
|
||||||
"unitless");
|
"unitless");
|
||||||
ReportResult("bytes_received", network_label, stats.BytesReceived().bytes(),
|
ReportResult("bytes_received", network_label, stats->BytesReceived().bytes(),
|
||||||
"sizeInBytes");
|
"sizeInBytes");
|
||||||
ReportResult("packets_received", network_label, stats.PacketsReceived(),
|
ReportResult("packets_received", network_label, stats->PacketsReceived(),
|
||||||
"unitless");
|
"unitless");
|
||||||
ReportResult("average_receive_rate", network_label,
|
ReportResult("average_receive_rate", network_label,
|
||||||
stats.PacketsReceived() >= 2
|
stats->PacketsReceived() >= 2
|
||||||
? stats.AverageReceiveRate().bytes_per_sec()
|
? stats->AverageReceiveRate().bytes_per_sec()
|
||||||
: 0,
|
: 0,
|
||||||
"bytesPerSecond");
|
"bytesPerSecond");
|
||||||
ReportResult("sent_packets_loss", network_label, packet_loss, "unitless");
|
ReportResult("sent_packets_loss", network_label, packet_loss, "unitless");
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#ifndef TEST_PC_E2E_NETWORK_QUALITY_METRICS_REPORTER_H_
|
#ifndef TEST_PC_E2E_NETWORK_QUALITY_METRICS_REPORTER_H_
|
||||||
#define TEST_PC_E2E_NETWORK_QUALITY_METRICS_REPORTER_H_
|
#define TEST_PC_E2E_NETWORK_QUALITY_METRICS_REPORTER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "absl/strings/string_view.h"
|
#include "absl/strings/string_view.h"
|
||||||
@ -47,10 +48,10 @@ class NetworkQualityMetricsReporter
|
|||||||
DataSize payload_sent = DataSize::Zero();
|
DataSize payload_sent = DataSize::Zero();
|
||||||
};
|
};
|
||||||
|
|
||||||
static EmulatedNetworkStats PopulateStats(
|
static std::unique_ptr<EmulatedNetworkStats> PopulateStats(
|
||||||
EmulatedNetworkManagerInterface* network);
|
EmulatedNetworkManagerInterface* network);
|
||||||
void ReportStats(const std::string& network_label,
|
void ReportStats(const std::string& network_label,
|
||||||
const EmulatedNetworkStats& stats,
|
std::unique_ptr<EmulatedNetworkStats> stats,
|
||||||
int64_t packet_loss);
|
int64_t packet_loss);
|
||||||
void ReportPCStats(const std::string& pc_label, const PCStats& stats);
|
void ReportPCStats(const std::string& pc_label, const PCStats& stats);
|
||||||
void ReportResult(const std::string& metric_name,
|
void ReportResult(const std::string& metric_name,
|
||||||
|
Reference in New Issue
Block a user