gfe-relnote: Default-initialize QUIC BBRv2 loss event threshold for exiting STARTUP from a flag. Protected by --gfe2_reloadable_flag_quic_default_to_bbr_v2.

PiperOrigin-RevId: 264298542
Change-Id: I304ab19e4820dec51d3f8ef53762a393f6b175fd
diff --git a/quic/qbone/bonnet/tun_device_packet_exchanger.cc b/quic/qbone/bonnet/tun_device_packet_exchanger.cc
new file mode 100644
index 0000000..1d246a2
--- /dev/null
+++ b/quic/qbone/bonnet/tun_device_packet_exchanger.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/qbone/bonnet/tun_device_packet_exchanger.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
+
+namespace quic {
+
+TunDevicePacketExchanger::TunDevicePacketExchanger(
+    int fd,
+    size_t mtu,
+    KernelInterface* kernel,
+    QbonePacketExchanger::Visitor* visitor,
+    size_t max_pending_packets, StatsInterface* stats)
+    : QbonePacketExchanger(visitor, max_pending_packets),
+      fd_(fd),
+      mtu_(mtu),
+      kernel_(kernel),
+      stats_(stats) {}
+
+bool TunDevicePacketExchanger::WritePacket(const char* packet,
+                                           size_t size,
+                                           bool* blocked,
+                                           string* error) {
+  *blocked = false;
+  if (fd_ < 0) {
+    *error = QuicStrCat("Invalid file descriptor of the TUN device: ", fd_);
+    stats_->OnWriteError(error);
+    return false;
+  }
+
+  int result = kernel_->write(fd_, packet, size);
+  if (result == -1) {
+    if (errno == EWOULDBLOCK || errno == EAGAIN) {
+      // The tunnel is blocked. Note that this does not mean the receive buffer
+      // of a TCP connection is filled. This simply means the TUN device itself
+      // is blocked on handing packets to the rest part of the kernel.
+      *error = QuicStrCat("Write to the TUN device was blocked: ", errno);
+      *blocked = true;
+      stats_->OnWriteError(error);
+    }
+    return false;
+  }
+  stats_->OnPacketWritten();
+
+  return true;
+}
+
+std::unique_ptr<QuicData> TunDevicePacketExchanger::ReadPacket(bool* blocked,
+                                                               string* error) {
+  *blocked = false;
+  if (fd_ < 0) {
+    *error = QuicStrCat("Invalid file descriptor of the TUN device: ", fd_);
+    stats_->OnReadError(error);
+    return nullptr;
+  }
+  // Reading on a TUN device returns a packet at a time. If the packet is longer
+  // than the buffer, it's truncated.
+  auto read_buffer = QuicMakeUnique<char[]>(mtu_);
+  int result = kernel_->read(fd_, read_buffer.get(), mtu_);
+  // Note that 0 means end of file, but we're talking about a TUN device - there
+  // is no end of file. Therefore 0 also indicates error.
+  if (result <= 0) {
+    if (errno == EAGAIN || errno == EWOULDBLOCK) {
+      *error = QuicStrCat("Read from the TUN device was blocked: ", errno);
+      *blocked = true;
+      stats_->OnReadError(error);
+    }
+    return nullptr;
+  }
+  stats_->OnPacketRead();
+  return QuicMakeUnique<QuicData>(read_buffer.release(), result, true);
+}
+
+int TunDevicePacketExchanger::file_descriptor() const {
+  return fd_;
+}
+
+}  // namespace quic