Add counter of ECN marking to EmulatedNetwork stats
Bug: webrtc:42225697 Change-Id: I99c68afafe20fcdbc785d489a8b484cec3b3987d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/368941 Reviewed-by: Artem Titov <titovartem@webrtc.org> Commit-Queue: Per Kjellander <perkj@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43455}
This commit is contained in:
parent
ff88950833
commit
0a69daf38b
@ -38,6 +38,8 @@ rtc_library("network_emulation") {
|
||||
|
||||
sources = [
|
||||
"cross_traffic.h",
|
||||
"ecn_marking_counter.cc",
|
||||
"ecn_marking_counter.h",
|
||||
"network_emulation_interfaces.cc",
|
||||
"network_emulation_interfaces.h",
|
||||
]
|
||||
|
||||
40
api/test/network_emulation/ecn_marking_counter.cc
Normal file
40
api/test/network_emulation/ecn_marking_counter.cc
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2024 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#include "api/test/network_emulation/ecn_marking_counter.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
void EcnMarkingCounter::Add(EcnMarking ecn) {
|
||||
switch (ecn) {
|
||||
case EcnMarking::kNotEct:
|
||||
++not_ect_;
|
||||
break;
|
||||
case EcnMarking::kEct0:
|
||||
++ect_0_;
|
||||
break;
|
||||
case EcnMarking::kEct1:
|
||||
++ect_1_;
|
||||
break;
|
||||
case EcnMarking::kCe:
|
||||
++ce_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EcnMarkingCounter& EcnMarkingCounter::operator+=(
|
||||
const EcnMarkingCounter& counter) {
|
||||
not_ect_ += counter.not_ect();
|
||||
ect_0_ += counter.ect_0();
|
||||
ect_1_ += counter.ect_1();
|
||||
ce_ += counter.ce();
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
41
api/test/network_emulation/ecn_marking_counter.h
Normal file
41
api/test/network_emulation/ecn_marking_counter.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2024 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
#ifndef API_TEST_NETWORK_EMULATION_ECN_MARKING_COUNTER_H_
|
||||
#define API_TEST_NETWORK_EMULATION_ECN_MARKING_COUNTER_H_
|
||||
|
||||
#include "api/transport/ecn_marking.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Counts Explicit Congestion Notifaction marks in IP packets.
|
||||
// https://www.rfc-editor.org/rfc/rfc9331.html
|
||||
class EcnMarkingCounter {
|
||||
public:
|
||||
// Number of packets without ECT explicitly set sent through the network.
|
||||
int not_ect() const { return not_ect_; }
|
||||
// Number of packets with ECT(1) sent through the network.
|
||||
int ect_0() const { return ect_0_; }
|
||||
// Number of packets with ECT(1) sent through the network.
|
||||
int ect_1() const { return ect_1_; }
|
||||
// Number of packets the network has marked as CE (congestion experienced).
|
||||
int ce() const { return ce_; }
|
||||
|
||||
void Add(EcnMarking ecn);
|
||||
EcnMarkingCounter& operator+=(const EcnMarkingCounter& counter);
|
||||
|
||||
private:
|
||||
int not_ect_ = 0;
|
||||
int ect_0_ = 0; // Not used by WebRTC or L4S.
|
||||
int ect_1_ = 0;
|
||||
int ce_ = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
#endif // API_TEST_NETWORK_EMULATION_ECN_MARKING_COUNTER_H_
|
||||
@ -18,6 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "api/numerics/samples_stats_counter.h"
|
||||
#include "api/test/network_emulation/ecn_marking_counter.h"
|
||||
#include "api/transport/ecn_marking.h"
|
||||
#include "api/units/data_rate.h"
|
||||
#include "api/units/data_size.h"
|
||||
@ -83,6 +84,8 @@ struct EmulatedNetworkOutgoingStats {
|
||||
// Time of the last packet sent or infinite value if no packets were sent.
|
||||
Timestamp last_packet_sent_time = Timestamp::MinusInfinity();
|
||||
|
||||
EcnMarkingCounter ecn_count;
|
||||
|
||||
// Returns average send rate. Requires that at least 2 packets were sent.
|
||||
DataRate AverageSendRate() const;
|
||||
};
|
||||
@ -118,6 +121,8 @@ struct EmulatedNetworkIncomingStats {
|
||||
// received.
|
||||
Timestamp last_packet_received_time = Timestamp::MinusInfinity();
|
||||
|
||||
EcnMarkingCounter ecn_count;
|
||||
|
||||
DataRate AverageReceiveRate() const;
|
||||
};
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "api/transport/ecn_marking.h"
|
||||
#include "api/units/data_size.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/logging.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -77,19 +78,21 @@ EmulatedNetworkOutgoingStatsBuilder::EmulatedNetworkOutgoingStatsBuilder(
|
||||
sequence_checker_.Detach();
|
||||
}
|
||||
|
||||
void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent(Timestamp sent_time,
|
||||
DataSize packet_size) {
|
||||
void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent(
|
||||
Timestamp sent_time,
|
||||
const EmulatedIpPacket& packet) {
|
||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||
RTC_CHECK_GE(packet_size, DataSize::Zero());
|
||||
RTC_CHECK_GE(packet.size(), 0);
|
||||
if (stats_.first_packet_sent_time.IsInfinite()) {
|
||||
stats_.first_packet_sent_time = sent_time;
|
||||
stats_.first_sent_packet_size = packet_size;
|
||||
stats_.first_sent_packet_size = DataSize::Bytes(packet.ip_packet_size());
|
||||
}
|
||||
stats_.last_packet_sent_time = sent_time;
|
||||
stats_.packets_sent++;
|
||||
stats_.bytes_sent += packet_size;
|
||||
stats_.bytes_sent += DataSize::Bytes(packet.ip_packet_size());
|
||||
stats_.ecn_count.Add(packet.ecn);
|
||||
if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) {
|
||||
stats_.sent_packets_size.AddSample(packet_size.bytes());
|
||||
stats_.sent_packets_size.AddSample(packet.ip_packet_size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,6 +109,7 @@ void EmulatedNetworkOutgoingStatsBuilder::AddOutgoingStats(
|
||||
if (stats_.last_packet_sent_time < stats.last_packet_sent_time) {
|
||||
stats_.last_packet_sent_time = stats.last_packet_sent_time;
|
||||
}
|
||||
stats_.ecn_count += stats.ecn_count;
|
||||
}
|
||||
|
||||
EmulatedNetworkOutgoingStats EmulatedNetworkOutgoingStatsBuilder::Build()
|
||||
@ -132,18 +136,20 @@ void EmulatedNetworkIncomingStatsBuilder::OnPacketDropped(
|
||||
|
||||
void EmulatedNetworkIncomingStatsBuilder::OnPacketReceived(
|
||||
Timestamp received_time,
|
||||
DataSize packet_size) {
|
||||
const EmulatedIpPacket& packet) {
|
||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||
RTC_CHECK_GE(packet_size, DataSize::Zero());
|
||||
RTC_CHECK_GE(packet.size(), 0);
|
||||
if (stats_.first_packet_received_time.IsInfinite()) {
|
||||
stats_.first_packet_received_time = received_time;
|
||||
stats_.first_received_packet_size = packet_size;
|
||||
stats_.first_received_packet_size =
|
||||
DataSize::Bytes(packet.ip_packet_size());
|
||||
}
|
||||
stats_.last_packet_received_time = received_time;
|
||||
stats_.packets_received++;
|
||||
stats_.bytes_received += packet_size;
|
||||
stats_.ecn_count.Add(packet.ecn);
|
||||
stats_.bytes_received += DataSize::Bytes(packet.ip_packet_size());
|
||||
if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) {
|
||||
stats_.received_packets_size.AddSample(packet_size.bytes());
|
||||
stats_.received_packets_size.AddSample(packet.ip_packet_size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,6 +170,7 @@ void EmulatedNetworkIncomingStatsBuilder::AddIncomingStats(
|
||||
if (stats_.last_packet_received_time < stats.last_packet_received_time) {
|
||||
stats_.last_packet_received_time = stats.last_packet_received_time;
|
||||
}
|
||||
stats_.ecn_count += stats.ecn_count;
|
||||
}
|
||||
|
||||
EmulatedNetworkIncomingStats EmulatedNetworkIncomingStatsBuilder::Build()
|
||||
@ -186,23 +193,22 @@ EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder(
|
||||
sequence_checker_.Detach();
|
||||
}
|
||||
|
||||
void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp queued_time,
|
||||
Timestamp sent_time,
|
||||
rtc::IPAddress destination_ip,
|
||||
DataSize packet_size) {
|
||||
void EmulatedNetworkStatsBuilder::OnPacketSent(Timestamp sent_time,
|
||||
const EmulatedIpPacket& packet) {
|
||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||
if (stats_gathering_mode_ == EmulatedNetworkStatsGatheringMode::kDebug) {
|
||||
sent_packets_queue_wait_time_us_.AddSample((sent_time - queued_time).us());
|
||||
sent_packets_queue_wait_time_us_.AddSample(
|
||||
(sent_time - packet.arrival_time).us());
|
||||
}
|
||||
auto it = outgoing_stats_per_destination_.find(destination_ip);
|
||||
auto it = outgoing_stats_per_destination_.find(packet.to.ipaddr());
|
||||
if (it == outgoing_stats_per_destination_.end()) {
|
||||
outgoing_stats_per_destination_
|
||||
.emplace(destination_ip,
|
||||
.emplace(packet.to.ipaddr(),
|
||||
std::make_unique<EmulatedNetworkOutgoingStatsBuilder>(
|
||||
stats_gathering_mode_))
|
||||
.first->second->OnPacketSent(sent_time, packet_size);
|
||||
.first->second->OnPacketSent(sent_time, packet);
|
||||
} else {
|
||||
it->second->OnPacketSent(sent_time, packet_size);
|
||||
it->second->OnPacketSent(sent_time, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,19 +227,19 @@ void EmulatedNetworkStatsBuilder::OnPacketDropped(rtc::IPAddress source_ip,
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatedNetworkStatsBuilder::OnPacketReceived(Timestamp received_time,
|
||||
rtc::IPAddress source_ip,
|
||||
DataSize packet_size) {
|
||||
void EmulatedNetworkStatsBuilder::OnPacketReceived(
|
||||
Timestamp received_time,
|
||||
const EmulatedIpPacket& packet) {
|
||||
RTC_DCHECK_RUN_ON(&sequence_checker_);
|
||||
auto it = incoming_stats_per_source_.find(source_ip);
|
||||
auto it = incoming_stats_per_source_.find(packet.from.ipaddr());
|
||||
if (it == incoming_stats_per_source_.end()) {
|
||||
incoming_stats_per_source_
|
||||
.emplace(source_ip,
|
||||
.emplace(packet.from.ipaddr(),
|
||||
std::make_unique<EmulatedNetworkIncomingStatsBuilder>(
|
||||
stats_gathering_mode_))
|
||||
.first->second->OnPacketReceived(received_time, packet_size);
|
||||
.first->second->OnPacketReceived(received_time, packet);
|
||||
} else {
|
||||
it->second->OnPacketReceived(received_time, packet_size);
|
||||
it->second->OnPacketReceived(received_time, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@ -627,10 +633,7 @@ void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
|
||||
clock_->CurrentTime(), application_overhead, ecn);
|
||||
task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
|
||||
RTC_DCHECK_RUN_ON(task_queue_);
|
||||
stats_builder_.OnPacketSent(packet.arrival_time, clock_->CurrentTime(),
|
||||
packet.to.ipaddr(),
|
||||
DataSize::Bytes(packet.ip_packet_size()));
|
||||
|
||||
stats_builder_.OnPacketSent(clock_->CurrentTime(), packet);
|
||||
if (packet.to.ipaddr() == options_.ip) {
|
||||
OnPacketReceived(std::move(packet));
|
||||
} else {
|
||||
@ -734,8 +737,7 @@ void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
<< "; Receiver options_.ip=" << options_.ip.ToString();
|
||||
}
|
||||
MutexLock lock(&receiver_lock_);
|
||||
stats_builder_.OnPacketReceived(clock_->CurrentTime(), packet.from.ipaddr(),
|
||||
DataSize::Bytes(packet.ip_packet_size()));
|
||||
stats_builder_.OnPacketReceived(clock_->CurrentTime(), packet);
|
||||
auto it = port_to_receiver_.find(packet.to.port());
|
||||
if (it == port_to_receiver_.end()) {
|
||||
if (default_receiver_.has_value()) {
|
||||
|
||||
@ -52,7 +52,7 @@ class EmulatedNetworkOutgoingStatsBuilder {
|
||||
explicit EmulatedNetworkOutgoingStatsBuilder(
|
||||
EmulatedNetworkStatsGatheringMode stats_gathering_mode);
|
||||
|
||||
void OnPacketSent(Timestamp sent_time, DataSize packet_size);
|
||||
void OnPacketSent(Timestamp sent_time, const EmulatedIpPacket& packet);
|
||||
|
||||
void AddOutgoingStats(const EmulatedNetworkOutgoingStats& stats);
|
||||
|
||||
@ -74,7 +74,8 @@ class EmulatedNetworkIncomingStatsBuilder {
|
||||
|
||||
void OnPacketDropped(DataSize packet_size);
|
||||
|
||||
void OnPacketReceived(Timestamp received_time, DataSize packet_size);
|
||||
void OnPacketReceived(Timestamp received_time,
|
||||
const EmulatedIpPacket& packet);
|
||||
|
||||
// Adds stats collected from another endpoints to the builder.
|
||||
void AddIncomingStats(const EmulatedNetworkIncomingStats& stats);
|
||||
@ -98,16 +99,12 @@ class EmulatedNetworkStatsBuilder {
|
||||
rtc::IPAddress local_ip,
|
||||
EmulatedNetworkStatsGatheringMode stats_gathering_mode);
|
||||
|
||||
void OnPacketSent(Timestamp queued_time,
|
||||
Timestamp sent_time,
|
||||
rtc::IPAddress destination_ip,
|
||||
DataSize packet_size);
|
||||
void OnPacketSent(Timestamp send_time, const EmulatedIpPacket& packet);
|
||||
|
||||
void OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size);
|
||||
|
||||
void OnPacketReceived(Timestamp received_time,
|
||||
rtc::IPAddress source_ip,
|
||||
DataSize packet_size);
|
||||
const EmulatedIpPacket& packet);
|
||||
|
||||
void AddEmulatedNetworkStats(const EmulatedNetworkStats& stats);
|
||||
|
||||
|
||||
@ -423,6 +423,27 @@ TEST(NetworkEmulationManagerTest, EcnMarkingIsPropagated) {
|
||||
EXPECT_EQ(r2.ReceivedCount(), 1);
|
||||
EXPECT_EQ(r2.LastEcnMarking(), webrtc::EcnMarking::kEct1);
|
||||
|
||||
std::atomic<int> received_stats_count{0};
|
||||
nt1->GetStats([&](EmulatedNetworkStats st) {
|
||||
EXPECT_EQ(st.overall_incoming_stats.packets_received, 0);
|
||||
EXPECT_EQ(st.overall_outgoing_stats.packets_sent, 1);
|
||||
EXPECT_EQ(st.overall_outgoing_stats.ecn_count.ect_1(), 1);
|
||||
EXPECT_EQ(st.overall_outgoing_stats.ecn_count.ce(), 0);
|
||||
EXPECT_EQ(st.overall_outgoing_stats.ecn_count.not_ect(), 0);
|
||||
++received_stats_count;
|
||||
});
|
||||
nt2->GetStats([&](EmulatedNetworkStats st) {
|
||||
EXPECT_EQ(st.overall_incoming_stats.packets_received, 1);
|
||||
EXPECT_EQ(st.overall_outgoing_stats.packets_sent, 0);
|
||||
EXPECT_EQ(st.overall_incoming_stats.ecn_count.ect_1(), 1);
|
||||
EXPECT_EQ(st.overall_incoming_stats.ecn_count.ce(), 0);
|
||||
EXPECT_EQ(st.overall_incoming_stats.ecn_count.not_ect(), 0);
|
||||
++received_stats_count;
|
||||
});
|
||||
ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2,
|
||||
kStatsWaitTimeout.ms(),
|
||||
*network_manager.time_controller());
|
||||
|
||||
SendTask(t1, [&] { delete s1; });
|
||||
SendTask(t2, [&] { delete s2; });
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user