Automated g4 rollback of changelist 373010349.
*** Reason for rollback ***
This change no longer downs the interface when taking down the qbone tunnel. Instead, we close the fd we have for interacting with the TUN -- this has the effect of removing the interface when nopersist is set on the device.
*** Original change description ***
Automated g4 rollback of changelist 372620094.
*** Reason for rollback ***
Breaking Endor because we bring down the TUN Device when tearing down the bonnet in the init container.
*** Original change description ***
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 synchronizatio...
***
PiperOrigin-RevId: 373210829
diff --git a/quic/qbone/bonnet/mock_tun_device.h b/quic/qbone/bonnet/mock_tun_device.h
index d593913..056346c 100644
--- a/quic/qbone/bonnet/mock_tun_device.h
+++ b/quic/qbone/bonnet/mock_tun_device.h
@@ -18,6 +18,8 @@
MOCK_METHOD(bool, Down, (), (override));
+ MOCK_METHOD(void, CloseDevice, (), (override));
+
MOCK_METHOD(int, GetFileDescriptor, (), (const, override));
};
diff --git a/quic/qbone/bonnet/tun_device.cc b/quic/qbone/bonnet/tun_device.cc
index 3ca52e8..86e68d7 100644
--- a/quic/qbone/bonnet/tun_device.cc
+++ b/quic/qbone/bonnet/tun_device.cc
@@ -39,7 +39,7 @@
if (!persist_) {
Down();
}
- CleanUpFileDescriptor();
+ CloseDevice();
}
bool TunDevice::Init() {
@@ -63,39 +63,33 @@
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::Up() {
- if (setup_tun_ && !is_interface_up_) {
- 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 struct.
- interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
- if_request.ifr_flags = IFF_UP;
-
- is_interface_up_ =
- NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
- return is_interface_up_;
- } else {
+ if (!setup_tun_) {
return true;
}
+ 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 struct.
+ interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
+ if_request.ifr_flags = IFF_UP;
+
+ return NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
}
// TODO(pengg): might be better to use netlink socket, once we have a library to
// use
bool TunDevice::Down() {
- if (setup_tun_ && is_interface_up_) {
- 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 struct.
- interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
- if_request.ifr_flags = 0;
-
- is_interface_up_ =
- !NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
- return !is_interface_up_;
- } else {
+ if (!setup_tun_) {
return true;
}
+ 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 struct.
+ interface_name_.copy(if_request.ifr_name, IFNAMSIZ);
+ if_request.ifr_flags = 0;
+
+ return NetdeviceIoctl(SIOCSIFFLAGS, reinterpret_cast<void*>(&if_request));
}
int TunDevice::GetFileDescriptor() const {
@@ -103,6 +97,10 @@
}
bool TunDevice::OpenDevice() {
+ if (file_descriptor_ != kInvalidFd) {
+ CloseDevice();
+ }
+
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
@@ -117,7 +115,7 @@
if_request.ifr_flags = IFF_TUN | IFF_MULTI_QUEUE | IFF_NO_PI;
// TODO(pengg): port MakeCleanup to quic/platform? This makes the call to
- // CleanUpFileDescriptor nicer and less error-prone.
+ // CloseDevice nicer and less error-prone.
// When the device is running with IFF_MULTI_QUEUE set, each call to open will
// create a queue which can be used to read/write packets from/to the device.
const std::string tun_device_path =
@@ -125,18 +123,18 @@
int fd = kernel_.open(tun_device_path.c_str(), O_RDWR);
if (fd < 0) {
QUIC_PLOG(WARNING) << "Failed to open " << tun_device_path;
- CleanUpFileDescriptor();
+ CloseDevice();
return false;
}
file_descriptor_ = fd;
if (!CheckFeatures(fd)) {
- CleanUpFileDescriptor();
+ CloseDevice();
return false;
}
if (kernel_.ioctl(fd, TUNSETIFF, reinterpret_cast<void*>(&if_request)) != 0) {
QUIC_PLOG(WARNING) << "Failed to TUNSETIFF on fd(" << fd << ")";
- CleanUpFileDescriptor();
+ CloseDevice();
return false;
}
@@ -144,7 +142,7 @@
fd, TUNSETPERSIST,
persist_ ? reinterpret_cast<void*>(&if_request) : nullptr) != 0) {
QUIC_PLOG(WARNING) << "Failed to TUNSETPERSIST on fd(" << fd << ")";
- CleanUpFileDescriptor();
+ CloseDevice();
return false;
}
@@ -166,7 +164,7 @@
if_request.ifr_mtu = mtu_;
if (!NetdeviceIoctl(SIOCSIFMTU, reinterpret_cast<void*>(&if_request))) {
- CleanUpFileDescriptor();
+ CloseDevice();
return false;
}
@@ -206,7 +204,7 @@
return true;
}
-void TunDevice::CleanUpFileDescriptor() {
+void TunDevice::CloseDevice() {
if (file_descriptor_ != kInvalidFd) {
kernel_.close(file_descriptor_);
file_descriptor_ = kInvalidFd;
diff --git a/quic/qbone/bonnet/tun_device.h b/quic/qbone/bonnet/tun_device.h
index bff85f5..129e1d1 100644
--- a/quic/qbone/bonnet/tun_device.h
+++ b/quic/qbone/bonnet/tun_device.h
@@ -49,6 +49,11 @@
// Marks the interface down to stop receiving packets.
bool Down() override;
+ // Closes the open file descriptor for the TUN device (if one exists).
+ // It is safe to reinitialize and reuse this TunDevice after calling
+ // CloseDevice.
+ void CloseDevice() override;
+
// Gets the file descriptor that can be used to send/receive packets.
// This returns -1 when the TUN device is in an invalid state.
int GetFileDescriptor() const override;
@@ -63,10 +68,6 @@
// Checks if the required kernel features exists.
bool CheckFeatures(int tun_device_fd);
- // Closes the opened file descriptor and makes sure the file descriptor
- // is no longer available from GetFileDescriptor;
- void CleanUpFileDescriptor();
-
// Opens a socket and makes netdevice ioctl call
bool NetdeviceIoctl(int request, void* argp);
@@ -76,7 +77,6 @@
const bool setup_tun_;
int file_descriptor_;
KernelInterface& kernel_;
- bool is_interface_up_ = false;
};
} // namespace quic
diff --git a/quic/qbone/bonnet/tun_device_interface.h b/quic/qbone/bonnet/tun_device_interface.h
index e99c547..3c6f962 100644
--- a/quic/qbone/bonnet/tun_device_interface.h
+++ b/quic/qbone/bonnet/tun_device_interface.h
@@ -12,7 +12,7 @@
// An interface with methods for interacting with a TUN device.
class TunDeviceInterface {
public:
- virtual ~TunDeviceInterface() {}
+ virtual ~TunDeviceInterface() = default;
// Actually creates/reopens and configures the device.
virtual bool Init() = 0;
@@ -23,6 +23,11 @@
// Marks the interface down to stop receiving packets.
virtual bool Down() = 0;
+ // Closes the open file descriptor for the TUN device (if one exists).
+ // It is safe to reinitialize and reuse this TunDevice after calling
+ // CloseDevice.
+ virtual void CloseDevice() = 0;
+
// Gets the file descriptor that can be used to send/receive packets.
// This returns -1 when the TUN device is in an invalid state.
virtual int GetFileDescriptor() const = 0;
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_;
diff --git a/quic/qbone/bonnet/tun_device_test.cc b/quic/qbone/bonnet/tun_device_test.cc
index 9c216af..6a02f07 100644
--- a/quic/qbone/bonnet/tun_device_test.cc
+++ b/quic/qbone/bonnet/tun_device_test.cc
@@ -139,6 +139,7 @@
TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
+ ExpectDown(false);
}
TEST_F(TunDeviceTest, FailToCheckFeature) {
@@ -147,6 +148,7 @@
TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
+ ExpectDown(false);
}
TEST_F(TunDeviceTest, TooFewFeature) {
@@ -160,6 +162,7 @@
TunDevice tun_device(kDeviceName, 1500, false, true, &mock_kernel_);
EXPECT_FALSE(tun_device.Init());
EXPECT_EQ(tun_device.GetFileDescriptor(), -1);
+ ExpectDown(false);
}
TEST_F(TunDeviceTest, FailToSetFlag) {