Defer TUN device creation until after the quic connection has been established.

IOS XR's XR container takes a few seconds for networking state to be sync'd from the host -- during which time any manipulations to the linux contaier's host networking stack breaks the synchronization process.

This has the nice side-benefit of re-initializing the TUN device each time a new quic connection is established, ensuring the local interface is in a good state on each reconnect. Previously, if the interface was down'd or deleted externally, the client would just fail continuously without attempting to recover.

PiperOrigin-RevId: 372620094
diff --git a/quic/qbone/bonnet/tun_device.cc b/quic/qbone/bonnet/tun_device.cc
index 3ca52e8..c0f635d 100644
--- a/quic/qbone/bonnet/tun_device.cc
+++ b/quic/qbone/bonnet/tun_device.cc
@@ -103,6 +103,10 @@
 }
 
 bool TunDevice::OpenDevice() {
+  if (file_descriptor_ != kInvalidFd) {
+    CleanUpFileDescriptor();
+  }
+
   struct ifreq if_request;
   memset(&if_request, 0, sizeof(if_request));
   // copy does not zero-terminate the result string, but we've memset the entire
diff --git a/quic/qbone/bonnet/tun_device_packet_exchanger.cc b/quic/qbone/bonnet/tun_device_packet_exchanger.cc
index 2119671..4783e9c 100644
--- a/quic/qbone/bonnet/tun_device_packet_exchanger.cc
+++ b/quic/qbone/bonnet/tun_device_packet_exchanger.cc
@@ -11,14 +11,12 @@
 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) {}
@@ -78,8 +76,8 @@
   return std::make_unique<QuicData>(read_buffer.release(), result, true);
 }
 
-int TunDevicePacketExchanger::file_descriptor() const {
-  return fd_;
+void TunDevicePacketExchanger::set_file_descriptor(int fd) {
+  fd_ = fd;
 }
 
 const TunDevicePacketExchanger::StatsInterface*
diff --git a/quic/qbone/bonnet/tun_device_packet_exchanger.h b/quic/qbone/bonnet/tun_device_packet_exchanger.h
index 1d28fee..115f5b5 100644
--- a/quic/qbone/bonnet/tun_device_packet_exchanger.h
+++ b/quic/qbone/bonnet/tun_device_packet_exchanger.h
@@ -35,8 +35,6 @@
     ABSL_MUST_USE_RESULT virtual int64_t PacketsWritten() const = 0;
   };
 
-  // |fd| is a open file descriptor on a TUN device that's opened for both read
-  // and write.
   // |mtu| is the mtu of the TUN device.
   // |kernel| is not owned but should out live objects of this class.
   // |visitor| is not owned but should out live objects of this class.
@@ -44,14 +42,13 @@
   // the TUN device become blocked.
   // |stats| is notified about packet read/write statistics. It is not owned,
   // but should outlive objects of this class.
-  TunDevicePacketExchanger(int fd,
-                           size_t mtu,
+  TunDevicePacketExchanger(size_t mtu,
                            KernelInterface* kernel,
                            QbonePacketExchanger::Visitor* visitor,
                            size_t max_pending_packets,
                            StatsInterface* stats);
 
-  ABSL_MUST_USE_RESULT int file_descriptor() const;
+  void set_file_descriptor(int fd);
 
   ABSL_MUST_USE_RESULT const StatsInterface* stats_interface() const;
 
diff --git a/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc b/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
index 4a00c60..c8f3ff0 100644
--- a/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
+++ b/quic/qbone/bonnet/tun_device_packet_exchanger_test.cc
@@ -30,14 +30,15 @@
 class TunDevicePacketExchangerTest : public QuicTest {
  protected:
   TunDevicePacketExchangerTest()
-      : exchanger_(kFd,
-                   kMtu,
+      : exchanger_(kMtu,
                    &mock_kernel_,
                    &mock_visitor_,
                    kMaxPendingPackets,
-                   &mock_stats_) {}
+                   &mock_stats_) {
+    exchanger_.set_file_descriptor(kFd);
+  }
 
-  ~TunDevicePacketExchangerTest() override {}
+  ~TunDevicePacketExchangerTest() override = default;
 
   MockKernel mock_kernel_;
   StrictMock<MockVisitor> mock_visitor_;