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}
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index 4404ae8..5cbb73d 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -73,6 +73,7 @@
 }
 
 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, 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 @@
   // 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);
 }
 
diff --git a/test/network/cross_traffic_unittest.cc b/test/network/cross_traffic_unittest.cc
index bab020b..19d3bc3 100644
--- a/test/network/cross_traffic_unittest.cc
+++ b/test/network/cross_traffic_unittest.cc
@@ -27,6 +27,8 @@
 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 @@
   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
diff --git a/test/network/network_emulation.cc b/test/network/network_emulation.cc
index f41f266..04ac744 100644
--- a/test/network/network_emulation.cc
+++ b/test/network/network_emulation.cc
@@ -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 @@
     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 @@
     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 @@
   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(
diff --git a/test/network/network_emulation.h b/test/network/network_emulation.h
index e825c65..f23f575 100644
--- a/test/network/network_emulation.h
+++ b/test/network/network_emulation.h
@@ -35,6 +35,8 @@
 
 struct EmulatedIpPacket {
  public:
+  static constexpr int kUdpHeaderSize = 8;
+
   EmulatedIpPacket(const rtc::SocketAddress& from,
                    const rtc::SocketAddress& to,
                    rtc::CopyOnWriteBuffer data,
@@ -50,9 +52,14 @@
   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;
 };
 
diff --git a/test/network/network_emulation_unittest.cc b/test/network/network_emulation_unittest.cc
index b119442..e661d51 100644
--- a/test/network/network_emulation_unittest.cc
+++ b/test/network/network_emulation_unittest.cc
@@ -30,6 +30,7 @@
 
 constexpr int kNetworkPacketWaitTimeoutMs = 100;
 constexpr int kStatsWaitTimeoutMs = 1000;
+constexpr int kOverheadIpv4Udp = 20 + 8;
 
 class SocketReader : public sigslot::has_slots<> {
  public:
@@ -235,7 +236,7 @@
     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 @@
   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 @@
   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,