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_;