Account for IP and UDP headers in emulated network

Add header size both for network emulation and stats.

Bug: webrtc:11003
Change-Id: I6f5b6bc1e761bdc40da4e2e0f10a9696e8a45c88
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/155442
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29382}
This commit is contained in:
Niels Möller 2019-10-04 13:54:39 +02:00 committed by Commit Bot
parent ed8eadcb56
commit 7536bc5395
5 changed files with 44 additions and 16 deletions

View File

@ -73,6 +73,7 @@ CallClient* CreateVideoSendingClient(
}
void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") {
ScopedFieldTrials trial("WebRTC-SendSideBwe-WithOverhead/Enabled/");
auto factory = CreateFeedbackOnlyFactory();
Scenario s("googcc_unit/target_capacity" + test_name, false);
CallClientConfig config;
@ -643,7 +644,8 @@ TEST_F(GoogCcNetworkControllerTest, CutsHighRateInSafeResetTrial) {
TEST_F(GoogCcNetworkControllerTest, DetectsHighRateInSafeResetTrial) {
ScopedFieldTrials trial(
"WebRTC-Bwe-SafeResetOnRouteChange/Enabled,ack/"
"WebRTC-Bwe-ProbeRateFallback/Enabled/");
"WebRTC-Bwe-ProbeRateFallback/Enabled/"
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
const DataRate kInitialLinkCapacity = DataRate::kbps(200);
const DataRate kNewLinkCapacity = DataRate::kbps(800);
const DataRate kStartRate = DataRate::kbps(300);
@ -674,7 +676,9 @@ TEST_F(GoogCcNetworkControllerTest, DetectsHighRateInSafeResetTrial) {
// than the starting rate.
EXPECT_NEAR(client->send_bandwidth().kbps(), kInitialLinkCapacity.kbps(), 50);
// However, probing should have made us detect the higher rate.
s.RunFor(TimeDelta::ms(2000));
// NOTE: This test causes high loss rate, and the loss-based estimator reduces
// the bitrate, making the test fail if we wait longer than one second here.
s.RunFor(TimeDelta::ms(1000));
EXPECT_GT(client->send_bandwidth().kbps(), kNewLinkCapacity.kbps() - 300);
}

View File

@ -27,6 +27,8 @@ namespace webrtc {
namespace test {
namespace {
constexpr uint32_t kTestIpAddress = 0xC0A80011; // 192.168.0.17
class CountingReceiver : public EmulatedNetworkReceiverInterface {
public:
void OnPacketReceived(EmulatedIpPacket packet) override {
@ -41,8 +43,8 @@ struct TrafficCounterFixture {
SimulatedClock clock{0};
CountingReceiver counter;
TaskQueueForTest task_queue_;
EmulatedEndpoint endpoint{/*id=*/1, rtc::IPAddress(), /*is_enabled=*/true,
&task_queue_, &clock};
EmulatedEndpoint endpoint{/*id=*/1, rtc::IPAddress(kTestIpAddress),
/*is_enabled=*/true, &task_queue_, &clock};
};
} // namespace

View File

@ -20,19 +20,31 @@
namespace webrtc {
namespace {
constexpr size_t kIPv4HeaderSize = 20;
constexpr size_t kIPv6HeaderSize = 40;
} // namespace
EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer data,
Timestamp arrival_time)
: from(from), to(to), data(data), arrival_time(arrival_time) {}
: from(from),
to(to),
data(data),
ip_header_size((to.family() == AF_INET) ? kIPv4HeaderSize
: kIPv6HeaderSize),
arrival_time(arrival_time) {
RTC_DCHECK(to.family() == AF_INET || to.family() == AF_INET6);
}
void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
RTC_DCHECK_RUN_ON(task_queue_);
uint64_t packet_id = next_packet_id_++;
bool sent = network_behavior_->EnqueuePacket(
PacketInFlightInfo(packet.size(), packet.arrival_time.us(), packet_id));
bool sent = network_behavior_->EnqueuePacket(PacketInFlightInfo(
packet.ip_packet_size(), packet.arrival_time.us(), packet_id));
if (sent) {
packets_.emplace_back(StoredPacket{packet_id, std::move(packet), false});
}
@ -206,11 +218,11 @@ void EmulatedEndpoint::SendPacket(const rtc::SocketAddress& from,
Timestamp current_time = clock_->CurrentTime();
if (stats_.first_packet_sent_time.IsInfinite()) {
stats_.first_packet_sent_time = current_time;
stats_.first_sent_packet_size = DataSize::bytes(packet.size());
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.size());
stats_.bytes_sent += DataSize::bytes(packet.ip_packet_size());
router_.OnPacketReceived(std::move(packet));
});
@ -282,7 +294,7 @@ void EmulatedEndpoint::OnPacketReceived(EmulatedIpPacket packet) {
RTC_LOG(INFO) << "Drop packet: no receiver registered in " << id_
<< " on port " << packet.to.port();
stats_.packets_dropped++;
stats_.bytes_dropped += DataSize::bytes(packet.size());
stats_.bytes_dropped += DataSize::bytes(packet.ip_packet_size());
return;
}
// Endpoint assumes frequent calls to bind and unbind methods, so it holds
@ -318,11 +330,12 @@ void EmulatedEndpoint::UpdateReceiveStats(const EmulatedIpPacket& packet) {
Timestamp current_time = clock_->CurrentTime();
if (stats_.first_packet_received_time.IsInfinite()) {
stats_.first_packet_received_time = current_time;
stats_.first_received_packet_size = DataSize::bytes(packet.size());
stats_.first_received_packet_size =
DataSize::bytes(packet.ip_packet_size());
}
stats_.last_packet_received_time = current_time;
stats_.packets_received++;
stats_.bytes_received += DataSize::bytes(packet.size());
stats_.bytes_received += DataSize::bytes(packet.ip_packet_size());
}
EndpointsContainer::EndpointsContainer(

View File

@ -35,6 +35,8 @@ namespace webrtc {
struct EmulatedIpPacket {
public:
static constexpr int kUdpHeaderSize = 8;
EmulatedIpPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer data,
@ -50,9 +52,14 @@ struct EmulatedIpPacket {
size_t size() const { return data.size(); }
const uint8_t* cdata() const { return data.cdata(); }
size_t ip_packet_size() const {
return size() + kUdpHeaderSize + ip_header_size;
}
rtc::SocketAddress from;
rtc::SocketAddress to;
// Holds the UDP payload.
rtc::CopyOnWriteBuffer data;
int ip_header_size;
Timestamp arrival_time;
};

View File

@ -30,6 +30,7 @@ namespace {
constexpr int kNetworkPacketWaitTimeoutMs = 100;
constexpr int kStatsWaitTimeoutMs = 1000;
constexpr int kOverheadIpv4Udp = 20 + 8;
class SocketReader : public sigslot::has_slots<> {
public:
@ -235,7 +236,7 @@ TEST(NetworkEmulationManagerTest, Run) {
delete s2;
}
int64_t single_packet_size = data.size();
const int64_t single_packet_size = data.size() + kOverheadIpv4Udp;
std::atomic<int> received_stats_count{0};
nt1->GetStats([&](EmulatedNetworkStats st) {
EXPECT_EQ(st.packets_sent, 2000l);
@ -277,8 +278,9 @@ TEST(NetworkEmulationManagerTest, ThroughputStats) {
EmulatedNetworkManagerInterface* nt2 =
network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint});
int64_t single_packet_size = 100;
rtc::CopyOnWriteBuffer data(single_packet_size);
constexpr int64_t kUdpPayloadSize = 100;
constexpr int64_t kSinglePacketSize = kUdpPayloadSize + kOverheadIpv4Udp;
rtc::CopyOnWriteBuffer data(kUdpPayloadSize);
auto* s1 = nt1->network_thread()->socketserver()->CreateAsyncSocket(
AF_INET, SOCK_DGRAM);
auto* s2 = nt2->network_thread()->socketserver()->CreateAsyncSocket(
@ -311,7 +313,7 @@ TEST(NetworkEmulationManagerTest, ThroughputStats) {
std::atomic<int> received_stats_count{0};
nt1->GetStats([&](EmulatedNetworkStats st) {
EXPECT_EQ(st.packets_sent, kNumPacketsSent);
EXPECT_EQ(st.bytes_sent.bytes(), single_packet_size * kNumPacketsSent);
EXPECT_EQ(st.bytes_sent.bytes(), kSinglePacketSize * kNumPacketsSent);
const double tolerance = 0.99; // Accept 1% tolerance for timing.
EXPECT_GE(st.last_packet_sent_time - st.first_packet_sent_time,