Migrate IcmpReachable to use QuicEventLoop API.
This changes internal time precision of IcmpReachable from ns to us, but otherwise should be a no-op.
PiperOrigin-RevId: 469545543
diff --git a/quiche/quic/bindings/quic_libevent.h b/quiche/quic/bindings/quic_libevent.h
index d8aa493..b06ab4e 100644
--- a/quiche/quic/bindings/quic_libevent.h
+++ b/quiche/quic/bindings/quic_libevent.h
@@ -36,6 +36,7 @@
bool ArtificiallyNotifyEvent(QuicUdpSocketFd fd,
QuicSocketEventMask events) override;
void RunEventLoopOnce(QuicTime::Delta default_timeout) override;
+ const QuicClock* GetClock() override { return clock_; }
// Can be called from another thread to wake up the event loop from a blocking
// RunEventLoopOnce() call.
diff --git a/quiche/quic/core/io/quic_event_loop.h b/quiche/quic/core/io/quic_event_loop.h
index 1b09562..e02a0f0 100644
--- a/quiche/quic/core/io/quic_event_loop.h
+++ b/quiche/quic/core/io/quic_event_loop.h
@@ -75,6 +75,10 @@
// Returns an alarm factory that allows alarms to be scheduled on this event
// loop.
virtual std::unique_ptr<QuicAlarmFactory> CreateAlarmFactory() = 0;
+
+ // Returns the clock that is used by the alarm factory that the event loop
+ // provides.
+ virtual const QuicClock* GetClock() = 0;
};
// A factory object for the event loop. Every implementation is expected to have
diff --git a/quiche/quic/core/io/quic_poll_event_loop.h b/quiche/quic/core/io/quic_poll_event_loop.h
index 4e19ff9..6b2ec49 100644
--- a/quiche/quic/core/io/quic_poll_event_loop.h
+++ b/quiche/quic/core/io/quic_poll_event_loop.h
@@ -51,6 +51,7 @@
QuicUdpSocketFd fd, QuicSocketEventMask events) override;
void RunEventLoopOnce(QuicTime::Delta default_timeout) override;
std::unique_ptr<QuicAlarmFactory> CreateAlarmFactory() override;
+ const QuicClock* GetClock() override { return clock_; }
protected:
// Allows poll(2) calls to be mocked out in unit tests.
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable.cc b/quiche/quic/qbone/bonnet/icmp_reachable.cc
index fac964b..8f85190 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable.cc
+++ b/quiche/quic/qbone/bonnet/icmp_reachable.cc
@@ -8,16 +8,18 @@
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/quic_random.h"
+#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_mutex.h"
#include "quiche/quic/qbone/platform/icmp_packet.h"
-#include "quiche/common/quiche_endian.h"
+#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/quiche_text_utils.h"
namespace quic {
namespace {
-constexpr int kEpollFlags = EPOLLIN | EPOLLET;
+constexpr QuicSocketEventMask kEventMask =
+ kSocketEventReadable | kSocketEventWritable;
constexpr size_t kMtu = 1280;
constexpr size_t kIPv6AddrSize = sizeof(in6_addr);
@@ -28,13 +30,15 @@
const char kNoSource[] = "N/A";
IcmpReachable::IcmpReachable(QuicIpAddress source, QuicIpAddress destination,
- absl::Duration timeout, KernelInterface* kernel,
- QuicEpollServer* epoll_server,
- StatsInterface* stats)
+ QuicTime::Delta timeout, KernelInterface* kernel,
+ QuicEventLoop* event_loop, StatsInterface* stats)
: timeout_(timeout),
+ event_loop_(event_loop),
+ clock_(event_loop->GetClock()),
+ alarm_factory_(event_loop->CreateAlarmFactory()),
cb_(this),
+ alarm_(alarm_factory_->CreateAlarm(new AlarmCallback(this))),
kernel_(kernel),
- epoll_server_(epoll_server),
stats_(stats),
send_fd_(0),
recv_fd_(0) {
@@ -50,9 +54,8 @@
kernel_->close(send_fd_);
}
if (recv_fd_ > 0) {
- if (!epoll_server_->ShutdownCalled()) {
- epoll_server_->UnregisterFD(recv_fd_);
- }
+ bool success = event_loop_->UnregisterSocket(recv_fd_);
+ QUICHE_DCHECK(success);
kernel_->close(recv_fd_);
}
@@ -93,8 +96,11 @@
return false;
}
- epoll_server_->RegisterFD(recv_fd_, &cb_, kEpollFlags);
- epoll_server_->RegisterAlarm(0, this);
+ if (!event_loop_->RegisterSocket(recv_fd_, kEventMask, &cb_)) {
+ QUIC_LOG(ERROR) << "Unable to register recv ICMP socket";
+ return false;
+ }
+ alarm_->Set(clock_->Now());
QuicWriterMutexLock mu(&header_lock_);
icmp_header_.icmp6_type = ICMP6_ECHO_REQUEST;
@@ -135,9 +141,8 @@
<< " seq: " << icmp_header_.icmp6_seq;
return true;
}
- end_ = absl::Now();
- QUIC_VLOG(1) << "Received ping response in "
- << absl::ToInt64Microseconds(end_ - start_) << "us.";
+ end_ = clock_->Now();
+ QUIC_VLOG(1) << "Received ping response in " << (end_ - start_);
std::string source;
QuicIpAddress source_ip;
@@ -152,14 +157,12 @@
return true;
}
-int64 /* allow-non-std-int */ IcmpReachable::OnAlarm() {
- EpollAlarm::OnAlarm();
-
+void IcmpReachable::OnAlarm() {
QuicWriterMutexLock mu(&header_lock_);
if (end_ < start_) {
QUIC_VLOG(1) << "Timed out on sequence: " << icmp_header_.icmp6_seq;
- stats_->OnEvent({Status::UNREACHABLE, absl::ZeroDuration(), kNoSource});
+ stats_->OnEvent({Status::UNREACHABLE, QuicTime::Delta::Zero(), kNoSource});
}
icmp_header_.icmp6_seq++;
@@ -175,10 +178,10 @@
if (size < packet.size()) {
stats_->OnWriteError(errno);
}
- start_ = absl::Now();
+ start_ = clock_->Now();
});
- return absl::ToUnixMicros(absl::Now() + timeout_);
+ alarm_->Set(clock_->ApproximateNow() + timeout_);
}
absl::string_view IcmpReachable::StatusName(IcmpReachable::Status status) {
@@ -192,19 +195,15 @@
}
}
-void IcmpReachable::EpollCallback::OnEvent(int fd, QuicEpollEvent* event) {
+void IcmpReachable::EpollCallback::OnSocketEvent(QuicEventLoop* event_loop,
+ QuicUdpSocketFd fd,
+ QuicSocketEventMask events) {
bool can_read_more = reachable_->OnEvent(fd);
if (can_read_more) {
- event->out_ready_mask |= EPOLLIN;
+ bool success =
+ event_loop->ArtificiallyNotifyEvent(fd, kSocketEventReadable);
+ QUICHE_DCHECK(success);
}
}
-void IcmpReachable::EpollCallback::OnShutdown(QuicEpollServer* eps, int fd) {
- eps->UnregisterFD(fd);
-}
-
-std::string IcmpReachable::EpollCallback::Name() const {
- return "ICMP Reachable";
-}
-
} // namespace quic
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable.h b/quiche/quic/qbone/bonnet/icmp_reachable.h
index a4ecdee..529ccc7 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable.h
+++ b/quiche/quic/qbone/bonnet/icmp_reachable.h
@@ -7,7 +7,14 @@
#include <netinet/icmp6.h>
+#include <memory>
+
#include "absl/strings/string_view.h"
+#include "quiche/quic/core/io/quic_event_loop.h"
+#include "quiche/quic/core/quic_alarm.h"
+#include "quiche/quic/core/quic_alarm_factory.h"
+#include "quiche/quic/core/quic_clock.h"
+#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_mutex.h"
#include "quiche/quic/qbone/bonnet/icmp_reachable_interface.h"
@@ -29,7 +36,7 @@
struct ReachableEvent {
Status status;
- absl::Duration response_time;
+ QuicTime::Delta response_time;
std::string source;
};
@@ -65,8 +72,8 @@
// |stats| is not owned, but should outlive this instance. It will be called
// back on Echo Replies, timeouts, and I/O errors.
IcmpReachable(QuicIpAddress source, QuicIpAddress destination,
- absl::Duration timeout, KernelInterface* kernel,
- QuicEpollServer* epoll_server, StatsInterface* stats);
+ QuicTime::Delta timeout, KernelInterface* kernel,
+ QuicEventLoop* event_loop, StatsInterface* stats);
~IcmpReachable() override;
@@ -74,13 +81,12 @@
// |epoll_server|'s thread.
bool Init() QUIC_LOCKS_EXCLUDED(header_lock_) override;
- int64 /* allow-non-std-int */ OnAlarm()
- QUIC_LOCKS_EXCLUDED(header_lock_) override;
+ void OnAlarm() QUIC_LOCKS_EXCLUDED(header_lock_);
static absl::string_view StatusName(Status status);
private:
- class EpollCallback : public QuicEpollCallbackInterface {
+ class EpollCallback : public QuicSocketEventListener {
public:
explicit EpollCallback(IcmpReachable* reachable) : reachable_(reachable) {}
@@ -90,18 +96,18 @@
EpollCallback(EpollCallback&&) = delete;
EpollCallback& operator=(EpollCallback&&) = delete;
- void OnRegistration(QuicEpollServer* eps, int fd,
- int event_mask) override{};
+ void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd,
+ QuicSocketEventMask events) override;
- void OnModification(int fd, int event_mask) override{};
+ private:
+ IcmpReachable* reachable_;
+ };
- void OnEvent(int fd, QuicEpollEvent* event) override;
+ class AlarmCallback : public QuicAlarm::DelegateWithoutContext {
+ public:
+ explicit AlarmCallback(IcmpReachable* reachable) : reachable_(reachable) {}
- void OnUnregistration(int fd, bool replaced) override{};
-
- void OnShutdown(QuicEpollServer* eps, int fd) override;
-
- std::string Name() const override;
+ void OnAlarm() override { reachable_->OnAlarm(); }
private:
IcmpReachable* reachable_;
@@ -109,15 +115,19 @@
bool OnEvent(int fd) QUIC_LOCKS_EXCLUDED(header_lock_);
- const absl::Duration timeout_;
+ const QuicTime::Delta timeout_;
+
+ QuicEventLoop* event_loop_;
+ const QuicClock* clock_;
+ std::unique_ptr<QuicAlarmFactory> alarm_factory_;
EpollCallback cb_;
+ std::unique_ptr<QuicAlarm> alarm_;
sockaddr_in6 src_{};
sockaddr_in6 dst_{};
KernelInterface* kernel_;
- QuicEpollServer* epoll_server_;
StatsInterface* stats_;
@@ -127,8 +137,8 @@
QuicMutex header_lock_;
icmp6_hdr icmp_header_ QUIC_GUARDED_BY(header_lock_){};
- absl::Time start_ = absl::InfinitePast();
- absl::Time end_ = absl::InfinitePast();
+ QuicTime start_ = QuicTime::Zero();
+ QuicTime end_ = QuicTime::Zero();
};
} // namespace quic
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable_interface.h b/quiche/quic/qbone/bonnet/icmp_reachable_interface.h
index 20bf489..2426670 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable_interface.h
+++ b/quiche/quic/qbone/bonnet/icmp_reachable_interface.h
@@ -5,13 +5,12 @@
#ifndef QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_INTERFACE_H_
#define QUICHE_QUIC_QBONE_BONNET_ICMP_REACHABLE_INTERFACE_H_
-#include "quiche/quic/platform/api/quic_epoll.h"
-
namespace quic {
-class IcmpReachableInterface : public QuicEpollAlarmBase {
+class IcmpReachableInterface {
public:
IcmpReachableInterface() = default;
+ virtual ~IcmpReachableInterface() = default;
IcmpReachableInterface(const IcmpReachableInterface&) = delete;
IcmpReachableInterface& operator=(const IcmpReachableInterface&) = delete;
diff --git a/quiche/quic/qbone/bonnet/icmp_reachable_test.cc b/quiche/quic/qbone/bonnet/icmp_reachable_test.cc
index 7a0ebe6..ae48ddc 100644
--- a/quiche/quic/qbone/bonnet/icmp_reachable_test.cc
+++ b/quiche/quic/qbone/bonnet/icmp_reachable_test.cc
@@ -6,8 +6,12 @@
#include <netinet/ip6.h>
+#include <memory>
+
#include "absl/container/node_hash_map.h"
-#include "quiche/quic/platform/api/quic_epoll.h"
+#include "quiche/quic/core/io/quic_default_event_loop.h"
+#include "quiche/quic/core/io/quic_event_loop.h"
+#include "quiche/quic/core/quic_default_clock.h"
#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/qbone/platform/mock_kernel.h"
@@ -79,7 +83,8 @@
class IcmpReachableTest : public QuicTest {
public:
- IcmpReachableTest() {
+ IcmpReachableTest()
+ : event_loop_(GetDefaultEventLoop()->Create(QuicDefaultClock::Get())) {
QUICHE_CHECK(source_.FromString(kSourceAddress));
QUICHE_CHECK(destination_.FromString(kDestinationAddress));
@@ -113,13 +118,13 @@
int read_src_fd_;
StrictMock<MockKernel> kernel_;
- QuicEpollServer epoll_server_;
+ std::unique_ptr<QuicEventLoop> event_loop_;
StatsInterface stats_;
};
TEST_F(IcmpReachableTest, SendsPings) {
- IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
- &epoll_server_, &stats_);
+ IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+ &kernel_, event_loop_.get(), &stats_);
SetFdExpectations();
ASSERT_TRUE(reachable.Init());
@@ -133,15 +138,13 @@
return len;
}));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_FALSE(stats_.HasWriteErrors());
-
- epoll_server_.Shutdown();
}
TEST_F(IcmpReachableTest, HandlesUnreachableEvents) {
- IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
- &epoll_server_, &stats_);
+ IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+ &kernel_, event_loop_.get(), &stats_);
SetFdExpectations();
ASSERT_TRUE(reachable.Init());
@@ -152,20 +155,18 @@
int flags, const struct sockaddr* dest_addr,
socklen_t addrlen) { return len; }));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_EQ(stats_.unreachable_count(), 0);
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_FALSE(stats_.HasWriteErrors());
EXPECT_EQ(stats_.unreachable_count(), 1);
EXPECT_EQ(stats_.current_source(), kNoSource);
-
- epoll_server_.Shutdown();
}
TEST_F(IcmpReachableTest, HandlesReachableEvents) {
- IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
- &epoll_server_, &stats_);
+ IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+ &kernel_, event_loop_.get(), &stats_);
SetFdExpectations();
ASSERT_TRUE(reachable.Init());
@@ -193,7 +194,7 @@
return read(sockfd, buf, len);
}));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_EQ(stats_.reachable_count(), 0);
icmp6_hdr response = last_request_hdr;
@@ -202,18 +203,16 @@
write(read_src_fd_, reinterpret_cast<const void*>(&response),
sizeof(icmp6_hdr));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_FALSE(stats_.HasReadErrors());
EXPECT_FALSE(stats_.HasWriteErrors());
EXPECT_EQ(stats_.reachable_count(), 1);
EXPECT_EQ(stats_.current_source(), source_.ToString());
-
- epoll_server_.Shutdown();
}
TEST_F(IcmpReachableTest, HandlesWriteErrors) {
- IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
- &epoll_server_, &stats_);
+ IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+ &kernel_, event_loop_.get(), &stats_);
SetFdExpectations();
ASSERT_TRUE(reachable.Init());
@@ -225,15 +224,13 @@
return 0;
}));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_EQ(stats_.WriteErrorCount(EAGAIN), 1);
-
- epoll_server_.Shutdown();
}
TEST_F(IcmpReachableTest, HandlesReadErrors) {
- IcmpReachable reachable(source_, destination_, absl::ZeroDuration(), &kernel_,
- &epoll_server_, &stats_);
+ IcmpReachable reachable(source_, destination_, QuicTime::Delta::Zero(),
+ &kernel_, event_loop_.get(), &stats_);
SetFdExpectations();
ASSERT_TRUE(reachable.Init());
@@ -255,11 +252,9 @@
write(read_src_fd_, reinterpret_cast<const void*>(&response),
sizeof(icmp6_hdr));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
+ event_loop_->RunEventLoopOnce(QuicTime::Delta::FromSeconds(1));
EXPECT_EQ(stats_.reachable_count(), 0);
EXPECT_EQ(stats_.ReadErrorCount(EIO), 1);
-
- epoll_server_.Shutdown();
}
} // namespace