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