From 377260f70485c95c7e9a10c7865a1e0110684860 Mon Sep 17 00:00:00 2001 From: Konstantin Tsoy Date: Thu, 23 Feb 2023 20:11:24 -0800 Subject: [PATCH] Remove d6d code Summary: we're not using it Reviewed By: mjoras Differential Revision: D43482344 fbshipit-source-id: 05ac6792848e32e7c1bcf53a2df172852b5def62 --- cmake/mvfst-config.cmake.in | 4 +- quic/CMakeLists.txt | 1 - quic/QuicConstants.h | 49 -- quic/api/QuicPacketScheduler.cpp | 87 +- quic/api/QuicPacketScheduler.h | 27 - quic/api/QuicTransportBase.cpp | 81 -- quic/api/QuicTransportBase.h | 55 -- quic/api/QuicTransportFunctions.cpp | 68 +- quic/api/QuicTransportFunctions.h | 9 - quic/api/test/Mocks.h | 11 - quic/api/test/QuicPacketSchedulerTest.cpp | 92 --- quic/api/test/QuicTransportFunctionsTest.cpp | 79 -- quic/client/QuicClientTransport.cpp | 75 -- quic/client/QuicClientTransport.h | 3 - quic/common/test/TestPacketBuilders.cpp | 7 - quic/common/test/TestPacketBuilders.h | 2 - quic/common/test/TestUtils.cpp | 1 - quic/d6d/BinarySearchProbeSizeRaiser.h | 53 -- quic/d6d/CMakeLists.txt | 104 --- quic/d6d/ConstantStepProbeSizeRaiser.h | 35 - quic/d6d/ProbeSizeRaiser.h | 29 - quic/d6d/QuicD6DStateFunctions.cpp | 280 ------- quic/d6d/QuicD6DStateFunctions.h | 26 - quic/d6d/Types.cpp | 39 - quic/d6d/Types.h | 53 -- quic/d6d/test/CMakeLists.txt | 26 - quic/d6d/test/Mocks.h | 29 - quic/d6d/test/ProbeSizeRaiserTest.cpp | 99 --- quic/d6d/test/QuicD6DStateFunctionsTest.cpp | 741 ------------------ .../client/test/QuicClientTransportTest.cpp | 19 - quic/loss/CMakeLists.txt | 2 - quic/loss/QuicLossFunctions.h | 49 +- quic/loss/test/QuicLossFunctionsTest.cpp | 269 ------- quic/observer/SocketObserverInterface.h | 83 -- .../test/SocketObserverInterfaceTest.cpp | 1 - quic/samples/echo/LogQuicStats.h | 16 - quic/server/QuicServerTransport.cpp | 69 -- quic/server/QuicServerTransport.h | 1 - quic/server/state/ServerStateMachine.cpp | 64 +- quic/server/test/QuicServerTransportTest.cpp | 36 - quic/server/test/ServerStateMachineTest.cpp | 83 -- quic/state/AckHandlers.cpp | 11 - quic/state/CMakeLists.txt | 4 - quic/state/OutstandingPacket.h | 36 - quic/state/QuicTransportStatsCallback.h | 8 - quic/state/StateData.h | 81 -- quic/state/TransportSettings.h | 68 -- quic/state/test/AckHandlersTest.cpp | 2 - quic/state/test/MockQuicStats.h | 4 - quic/tools/tperf/tperf.cpp | 85 -- 50 files changed, 16 insertions(+), 3140 deletions(-) delete mode 100644 quic/d6d/BinarySearchProbeSizeRaiser.h delete mode 100644 quic/d6d/CMakeLists.txt delete mode 100644 quic/d6d/ConstantStepProbeSizeRaiser.h delete mode 100644 quic/d6d/ProbeSizeRaiser.h delete mode 100644 quic/d6d/QuicD6DStateFunctions.cpp delete mode 100644 quic/d6d/QuicD6DStateFunctions.h delete mode 100644 quic/d6d/Types.cpp delete mode 100644 quic/d6d/Types.h delete mode 100644 quic/d6d/test/CMakeLists.txt delete mode 100644 quic/d6d/test/Mocks.h delete mode 100644 quic/d6d/test/ProbeSizeRaiserTest.cpp delete mode 100644 quic/d6d/test/QuicD6DStateFunctionsTest.cpp diff --git a/cmake/mvfst-config.cmake.in b/cmake/mvfst-config.cmake.in index 9d34a0dea..39262dce2 100644 --- a/cmake/mvfst-config.cmake.in +++ b/cmake/mvfst-config.cmake.in @@ -27,7 +27,7 @@ if(NOT TARGET mvfst::mvfst_transport) get_target_property(mvfst_INCLUDE_DIRS mvfst::mvfst_transport INTERFACE_INCLUDE_DIRECTORIES) endif() -set(mvfst_LIBRARIES +set(mvfst_LIBRARIES mvfst::mvfst_constants mvfst::mvfst_exception mvfst::mvfst_transport @@ -64,8 +64,6 @@ set(mvfst_LIBRARIES mvfst::mvfst_state_functions mvfst::mvfst_state_simple_frame_functions mvfst::mvfst_state_stream - mvfst::mvfst_d6d_state_functions - mvfst::mvfst_d6d_types ) if(NOT mvfst_FIND_QUIETLY) diff --git a/quic/CMakeLists.txt b/quic/CMakeLists.txt index e2ae19d9f..d89179fc3 100644 --- a/quic/CMakeLists.txt +++ b/quic/CMakeLists.txt @@ -84,4 +84,3 @@ add_subdirectory(samples) add_subdirectory(server) add_subdirectory(state) add_subdirectory(tools) -add_subdirectory(d6d) diff --git a/quic/QuicConstants.h b/quic/QuicConstants.h index 0c9a16c31..0d65a73c4 100644 --- a/quic/QuicConstants.h +++ b/quic/QuicConstants.h @@ -49,43 +49,6 @@ constexpr uint16_t kDefaultMsgSizeBackOffSize = 50; // larger than this, unless configured otherwise. constexpr uint16_t kDefaultUDPReadBufferSize = 1500; -// Default base PMTU used by d6d probing -constexpr uint16_t kDefaultD6DBasePMTU = kDefaultUDPSendPacketLen; - -// Default maximum number of consecutive d6d probe losses we can -// tolerate -constexpr uint16_t kDefaultD6DMaxOutstandingProbes = 2; - -// The default d6d raise timeout, recommended by the spec -constexpr std::chrono::seconds kDefaultD6DRaiseTimeout = 600s; - -// The minimum d6d raise timeout -constexpr std::chrono::seconds kMinD6DRaiseTimeout = 50s; - -// The default d6d probe timeout, recommended by the spec -constexpr std::chrono::seconds kDefaultD6DProbeTimeout = 15s; - -// The minimum d6d probe timeout, recommended by the spec -constexpr std::chrono::seconds kMinD6DProbeTimeout = 1s; - -// The default d6d start delay -constexpr std::chrono::milliseconds kDefaultD6DKickStartDelay = 1000ms; - -// Default delay for the next probe when the last one is acked -constexpr std::chrono::milliseconds kDefaultD6DProbeDelayWhenAcked = 500ms; - -// Default delay for the next probe when the last one is lost -constexpr std::chrono::milliseconds kDefaultD6DProbeDelayWhenLost = 2000ms; - -// The default pmtu step size, currently only useful for ConstantStep raiser -constexpr uint16_t kDefaultD6DProbeStepSize = 10; - -// Default window of detecting blackhole caused by invalid pmtu -constexpr std::chrono::seconds kDefaultD6DBlackholeDetectionWindow = 5s; - -// Default threshold for detecting blackhole caused by invalid pmtu -constexpr uint64_t kDefaultD6DBlackholeDetectionThreshold = 8; - // Number of GRO buffers to use // 1 means GRO is not enabled // 64 is the max possible value @@ -168,8 +131,6 @@ BETTER_ENUM( UNKNOWN = 0x0, // No-op NO_OP = 0x1, - // Disabling pmtu blackhole detection - ZERO_PMTU_BLACKHOLE_DETECTION = 0x8830, // Force udp payload size to be equal to max // udp payload size FORCIBLY_SET_UDP_PAYLOAD_SIZE = 0xba92, @@ -359,16 +320,6 @@ enum class QuicVersion : uint32_t { using QuicVersionType = std::underlying_type::type; -/** - * Parameter ids for private transport parameter - */ - -constexpr uint16_t kD6DBasePMTUParameterId = 0xFF77; - -constexpr uint16_t kD6DRaiseTimeoutParameterId = 0xFF95; - -constexpr uint16_t kD6DProbeTimeoutParameterId = 0xFF12; - constexpr uint32_t kDrainFactor = 3; // batching mode diff --git a/quic/api/QuicPacketScheduler.cpp b/quic/api/QuicPacketScheduler.cpp index 6b51f4e81..0e0001ef3 100644 --- a/quic/api/QuicPacketScheduler.cpp +++ b/quic/api/QuicPacketScheduler.cpp @@ -848,11 +848,8 @@ CloningScheduler::CloningScheduler( cipherOverhead_(cipherOverhead) {} bool CloningScheduler::hasData() const { - // TODO: I'm not completely convinced d6d.outstandingProbes has been updated - // correctly. return frameScheduler_.hasData() || - conn_.outstandings.numOutstanding() > - conn_.d6d.outstandingProbes + conn_.outstandings.dsrCount; + conn_.outstandings.numOutstanding() > conn_.outstandings.dsrCount; } SchedulingResult CloningScheduler::scheduleFramesForPacket( @@ -879,9 +876,7 @@ SchedulingResult CloningScheduler::scheduleFramesForPacket( std::move(builder).releaseOutputBuffer(); // Look for an outstanding packet that's no larger than the writableBytes for (auto& outstandingPacket : conn_.outstandings.packets) { - if (outstandingPacket.declaredLost || - outstandingPacket.metadata.isD6DProbe || - outstandingPacket.isDSRPacket) { + if (outstandingPacket.declaredLost || outstandingPacket.isDSRPacket) { continue; } auto opPnSpace = outstandingPacket.packet.header.getPacketNumberSpace(); @@ -973,82 +968,4 @@ folly::StringPiece CloningScheduler::name() const { return name_; } -D6DProbeScheduler::D6DProbeScheduler( - QuicConnectionStateBase& conn, - folly::StringPiece name, - uint64_t cipherOverhead, - uint32_t probeSize) - : conn_(conn), - name_(name), - cipherOverhead_(cipherOverhead), - probeSize_(probeSize) {} - -/** - * This scheduler always has data since all it does is send PING with PADDINGs - */ -bool D6DProbeScheduler::hasData() const { - return !probeSent_; -} - -/** - * D6DProbeScheduler ignores writableBytes because it does not respect - * congestion control. The reasons it doesn't are that - * - d6d probes are occasional burst of bytes in a single packet - * - no rtx needed when probe lost - */ -SchedulingResult D6DProbeScheduler::scheduleFramesForPacket( - PacketBuilderInterface&& builder, - uint32_t /* writableBytes */) { - builder.encodePacketHeader(); - int res = writeFrame(PingFrame(), builder); - CHECK_GT(res, 0) << __func__ << " " - << "failed to write ping frame" - << "remainingBytes: " << builder.remainingSpaceInPkt(); - CHECK(builder.canBuildPacket()) << __func__ << " " - << "inner builder cannot build packet"; - - auto pingOnlyPacket = std::move(builder).buildPacket(); - - std::unique_ptr sizeEnforcedBuilder; - if (conn_.transportSettings.dataPathType == DataPathType::ChainedMemory) { - sizeEnforcedBuilder = std::make_unique( - std::move(pingOnlyPacket), probeSize_, cipherOverhead_); - } else { - CHECK(conn_.bufAccessor && conn_.bufAccessor->ownsBuffer()); - sizeEnforcedBuilder = std::make_unique( - *conn_.bufAccessor, - std::move(pingOnlyPacket), - probeSize_, - cipherOverhead_); - } - CHECK(sizeEnforcedBuilder->canBuildPacket()) - << __func__ << " " - << "sizeEnforcedBuilder cannot build packet"; - - auto resultPacket = std::move(*sizeEnforcedBuilder).buildPacket(); - - auto resultPacketSize = resultPacket.header->computeChainDataLength() + - resultPacket.body->computeChainDataLength() + cipherOverhead_; - CHECK_EQ(resultPacketSize, probeSize_) - << __func__ << " " - << "result packet does not have enforced size," - << " expecting: " << probeSize_ << " getting: " << resultPacketSize; - - VLOG_IF(4, conn_.d6d.lastProbe.has_value()) - << __func__ << " " - << "invalidating old non-acked d6d probe," - << " seq: " << conn_.d6d.lastProbe->packetNum - << " packet size: " << conn_.d6d.lastProbe->packetSize; - - conn_.d6d.lastProbe = D6DProbePacket( - resultPacket.packet.header.getPacketSequenceNum(), probeSize_); - - probeSent_ = true; - return SchedulingResult(folly::none, std::move(resultPacket)); -} - -folly::StringPiece D6DProbeScheduler::name() const { - return name_; -} - } // namespace quic diff --git a/quic/api/QuicPacketScheduler.h b/quic/api/QuicPacketScheduler.h index e7de51e9a..e956958e1 100644 --- a/quic/api/QuicPacketScheduler.h +++ b/quic/api/QuicPacketScheduler.h @@ -369,31 +369,4 @@ class CloningScheduler : public QuicPacketScheduler { uint64_t cipherOverhead_; }; -/** - * This is the packet scheduler for D6D probe packets. It only schedule a PING - * frame followed by many PADDING frames, forming a probeSize-sized packet. - */ -class D6DProbeScheduler : public QuicPacketScheduler { - public: - D6DProbeScheduler( - QuicConnectionStateBase& conn, - folly::StringPiece name, - uint64_t cipherOverhead, - uint32_t probSize); - - FOLLY_NODISCARD bool hasData() const override; - - SchedulingResult scheduleFramesForPacket( - PacketBuilderInterface&& builder, - uint32_t writableBytes) override; - - FOLLY_NODISCARD folly::StringPiece name() const override; - - private: - QuicConnectionStateBase& conn_; - folly::StringPiece name_; - uint64_t cipherOverhead_; - uint32_t probeSize_; - bool probeSent_{false}; -}; } // namespace quic diff --git a/quic/api/QuicTransportBase.cpp b/quic/api/QuicTransportBase.cpp index db3f8f60f..10bab4ddc 100644 --- a/quic/api/QuicTransportBase.cpp +++ b/quic/api/QuicTransportBase.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -40,9 +39,6 @@ QuicTransportBase::QuicTransportBase( keepaliveTimeout_(this), drainTimeout_(this), pingTimeout_(this), - d6dProbeTimeout_(this), - d6dRaiseTimeout_(this), - d6dTxTimeout_(this), readLooper_(new FunctionLooper( evb, [this]() { invokeReadDataAndCallbacks(); }, @@ -1929,13 +1925,6 @@ void QuicTransportBase::onNetworkData( // Received data could contain valid path response, in which case // path validation timeout should be canceled schedulePathValidationTimeout(); - // Received data could contain an ack to a d6d probe, in which case we - // need to cancel the current d6d probe timeout. The ack might change d6d - // state to SEARCH_COMPLETE, in which case we need to schedule d6d raise - // timeout. We might also need to schedule the next probe. - scheduleD6DProbeTimeout(); - scheduleD6DRaiseTimeout(); - scheduleD6DTxTimeout(); } else { // In the closed state, we would want to write a close if possible however // the write looper will not be set. @@ -2668,10 +2657,6 @@ void QuicTransportBase::lossTimeoutExpired() noexcept { if (conn_->qLogger) { conn_->qLogger->addTransportStateUpdate(kLossTimeoutExpired); } - // loss detection might cancel d6d raise timeout, and might cause the next - // probe to be scheduled - scheduleD6DRaiseTimeout(); - scheduleD6DTxTimeout(); pacedWriteDataToSocket(); } catch (const QuicTransportException& ex) { VLOG(4) << __func__ << " " << ex.what() << " " << *this; @@ -2752,26 +2737,6 @@ void QuicTransportBase::keepaliveTimeoutExpired() noexcept { updateWriteLooper(true); } -void QuicTransportBase::d6dProbeTimeoutExpired() noexcept { - VLOG(4) << __func__ << " " << *this; - FOLLY_MAYBE_UNUSED auto self = sharedGuard(); - conn_->pendingEvents.d6d.scheduleProbeTimeout = false; - onD6DProbeTimeoutExpired(*conn_); -} - -void QuicTransportBase::d6dRaiseTimeoutExpired() noexcept { - VLOG(4) << __func__ << " " << *this; - FOLLY_MAYBE_UNUSED auto self = sharedGuard(); - conn_->pendingEvents.d6d.scheduleRaiseTimeout = false; - onD6DRaiseTimeoutExpired(*conn_); -} - -void QuicTransportBase::d6dTxTimeoutExpired() noexcept { - VLOG(4) << __func__ << " " << *this; - conn_->pendingEvents.d6d.sendProbeDelay = folly::none; - conn_->pendingEvents.d6d.sendProbePacket = true; -} - void QuicTransportBase::scheduleLossTimeout(std::chrono::milliseconds timeout) { if (closeState_ == CloseState::CLOSED) { return; @@ -2851,49 +2816,6 @@ void QuicTransportBase::schedulePathValidationTimeout() { } } -void QuicTransportBase::scheduleD6DProbeTimeout() { - if (conn_->pendingEvents.d6d.scheduleProbeTimeout) { - if (!d6dProbeTimeout_.isScheduled()) { - VLOG(10) << __func__ << "timeout=" << conn_->d6d.probeTimeout.count() - << "ms " << *this; - getEventBase()->timer().scheduleTimeout( - &d6dProbeTimeout_, conn_->d6d.probeTimeout); - } - } else { - if (d6dProbeTimeout_.isScheduled()) { - VLOG(10) << __func__ << " cancel timeout " << *this; - d6dProbeTimeout_.cancelTimeout(); - } - } -} - -void QuicTransportBase::scheduleD6DRaiseTimeout() { - if (conn_->pendingEvents.d6d.scheduleRaiseTimeout) { - if (!d6dRaiseTimeout_.isScheduled()) { - VLOG(10) << __func__ << "timeout=" << conn_->d6d.raiseTimeout.count() - << "s " << *this; - getEventBase()->timer().scheduleTimeout( - &d6dRaiseTimeout_, conn_->d6d.raiseTimeout); - } - } else { - if (d6dRaiseTimeout_.isScheduled()) { - VLOG(10) << __func__ << " cancel timeout " << *this; - d6dRaiseTimeout_.cancelTimeout(); - } - } -} - -void QuicTransportBase::scheduleD6DTxTimeout() { - auto& delay = conn_->pendingEvents.d6d.sendProbeDelay; - if (delay) { - if (!d6dTxTimeout_.isScheduled()) { - VLOG(10) << __func__ << "timeout=" << conn_->d6d.raiseTimeout.count() - << "s " << *this; - getEventBase()->timer().scheduleTimeout(&d6dTxTimeout_, *delay); - } - } -} - void QuicTransportBase::cancelLossTimeout() { if (lossTimeout_.isScheduled()) { lossTimeout_.cancelTimeout(); @@ -3261,9 +3183,6 @@ void QuicTransportBase::writeSocketData() { // effect. scheduleAckTimeout(); schedulePathValidationTimeout(); - // Writing data could write out a d6d probe, for which we need to schedule a - // probe timeout - scheduleD6DProbeTimeout(); updateWriteLooper(false); } diff --git a/quic/api/QuicTransportBase.h b/quic/api/QuicTransportBase.h index 25b0e0484..9ce773dc3 100644 --- a/quic/api/QuicTransportBase.h +++ b/quic/api/QuicTransportBase.h @@ -586,51 +586,6 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver { QuicTransportBase* transport_; }; - class D6DProbeTimeout : public folly::HHWheelTimer::Callback { - public: - ~D6DProbeTimeout() override = default; - - explicit D6DProbeTimeout(QuicTransportBase* transport) - : transport_(transport) {} - - void timeoutExpired() noexcept override { - transport_->d6dProbeTimeoutExpired(); - } - - private: - QuicTransportBase* transport_; - }; - - class D6DRaiseTimeout : public folly::HHWheelTimer::Callback { - public: - ~D6DRaiseTimeout() override = default; - - explicit D6DRaiseTimeout(QuicTransportBase* transport) - : transport_(transport) {} - - void timeoutExpired() noexcept override { - transport_->d6dRaiseTimeoutExpired(); - } - - private: - QuicTransportBase* transport_; - }; - - class D6DTxTimeout : public folly::HHWheelTimer::Callback { - public: - ~D6DTxTimeout() override = default; - - explicit D6DTxTimeout(QuicTransportBase* transport) - : transport_(transport) {} - - void timeoutExpired() noexcept override { - transport_->d6dTxTimeoutExpired(); - } - - private: - QuicTransportBase* transport_; - }; - void scheduleLossTimeout(std::chrono::milliseconds timeout); void cancelLossTimeout(); bool isLossTimeoutScheduled() const; @@ -807,9 +762,6 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver { void keepaliveTimeoutExpired() noexcept; void drainTimeoutExpired() noexcept; void pingTimeoutExpired() noexcept; - void d6dProbeTimeoutExpired() noexcept; - void d6dRaiseTimeoutExpired() noexcept; - void d6dTxTimeoutExpired() noexcept; void setIdleTimer(); void scheduleAckTimeout(); @@ -817,9 +769,6 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver { void schedulePingTimeout( PingCallback* callback, std::chrono::milliseconds pingTimeout); - void scheduleD6DRaiseTimeout(); - void scheduleD6DProbeTimeout(); - void scheduleD6DTxTimeout(); void validateCongestionAndPacing(CongestionControlType& type); @@ -917,7 +866,6 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver { CloseState closeState_{CloseState::OPEN}; bool transportReadyNotified_{false}; bool handshakeDoneNotified_{false}; - bool d6dProbingStarted_{false}; LossTimeout lossTimeout_; AckTimeout ackTimeout_; @@ -926,9 +874,6 @@ class QuicTransportBase : public QuicSocket, QuicStreamPrioritiesObserver { KeepaliveTimeout keepaliveTimeout_; DrainTimeout drainTimeout_; PingTimeout pingTimeout_; - D6DProbeTimeout d6dProbeTimeout_; - D6DRaiseTimeout d6dRaiseTimeout_; - D6DTxTimeout d6dTxTimeout_; FunctionLooper::Ptr readLooper_; FunctionLooper::Ptr peekLooper_; FunctionLooper::Ptr writeLooper_; diff --git a/quic/api/QuicTransportFunctions.cpp b/quic/api/QuicTransportFunctions.cpp index 44d610056..10b263e7a 100644 --- a/quic/api/QuicTransportFunctions.cpp +++ b/quic/api/QuicTransportFunctions.cpp @@ -291,10 +291,7 @@ DataPathResult continuousMemoryBuildScheduleEncrypt( // Include previous packets back. packetBuf->prepend(prevSize); connection.bufAccessor->release(std::move(packetBuf)); - bool isD6DProbe = pnSpace == PacketNumberSpace::AppData && - connection.d6d.lastProbe.hasValue() && - connection.d6d.lastProbe->packetNum == packetNum; - if (!isD6DProbe && encodedSize > connection.udpSendPacketLen) { + if (encodedSize > connection.udpSendPacketLen) { VLOG(3) << "Quic sending pkt larger than limit, encodedSize=" << encodedSize; } @@ -632,9 +629,6 @@ void updateConnection( uint32_t newStreamBytesSent = 0; OutstandingPacket::Metadata::DetailsPerStream detailsPerStream; auto packetNumberSpace = packet.header.getPacketNumberSpace(); - bool isD6DProbe = packetNumberSpace == PacketNumberSpace::AppData && - conn.d6d.lastProbe.hasValue() && - conn.d6d.lastProbe->packetNum == packetNum; VLOG(10) << nodeToString(conn.nodeType) << " sent packetNum=" << packetNum << " in space=" << packetNumberSpace << " size=" << encodedSize << " bodySize: " << encodedBodySize << " isDSR=" << isDSRPacket @@ -782,15 +776,7 @@ void updateConnection( break; } case QuicWriteFrame::Type::PingFrame: - // If this is a d6d probe, the it does not consume the sendPing request - // from application, because this packet, albeit containing a ping - // frame, is larger than the current PMTU and will potentially get - // dropped in the path. Additionally, the loss of this packet will not - // trigger retransmission, therefore tying it with the sendPing event - // will make this api unreliable. - if (!isD6DProbe) { - conn.pendingEvents.sendPing = false; - } + conn.pendingEvents.sendPing = false; isPing = true; break; case QuicWriteFrame::Type::QuicSimpleFrame: { @@ -865,7 +851,6 @@ void updateConnection( encodedSize, encodedBodySize, isHandshake, - isD6DProbe, // these numbers should all _include_ the current packet // conn.lossState.inflightBytes isn't updated until below // conn.outstandings.numOutstanding() + 1 since we're emplacing here @@ -878,10 +863,6 @@ void updateConnection( std::move(detailsPerStream), conn.appLimitedTracker.getTotalAppLimitedTime()); - if (isD6DProbe) { - ++conn.d6d.outstandingProbes; - ++conn.d6d.meta.totalTxedProbes; - } pkt.isAppLimited = conn.congestionController ? conn.congestionController->isAppLimited() : false; @@ -1563,51 +1544,6 @@ uint64_t writeProbingDataToSocket( return written; } -uint64_t writeD6DProbeToSocket( - folly::AsyncUDPSocket& sock, - QuicConnectionStateBase& connection, - const ConnectionId& srcConnId, - const ConnectionId& dstConnId, - const Aead& aead, - const PacketNumberCipher& headerCipher, - QuicVersion version) { - if (!connection.pendingEvents.d6d.sendProbePacket) { - return 0; - } - auto builder = ShortHeaderBuilder(); - // D6D probe is always in AppData pnSpace - auto pnSpace = PacketNumberSpace::AppData; - // Skip a packet number for probing packets to elicit acks - increaseNextPacketNum(connection, pnSpace); - D6DProbeScheduler d6dProbeScheduler( - connection, - "D6DProbeScheduler", - aead.getCipherOverhead(), - connection.d6d.currentProbeSize); - auto written = writeConnectionDataToSocket( - sock, - connection, - srcConnId, - dstConnId, - builder, - pnSpace, - d6dProbeScheduler, - unlimitedWritableBytes, - 1, - aead, - headerCipher, - version, - Clock::now()) - .packetsWritten; - VLOG_IF(10, written > 0) << nodeToString(connection.nodeType) - << " writing d6d probes using scheduler=D6DScheduler" - << connection; - if (written > 0) { - connection.pendingEvents.d6d.sendProbePacket = false; - } - return written; -} - WriteDataReason shouldWriteData(/*const*/ QuicConnectionStateBase& conn) { auto& numProbePackets = conn.pendingEvents.numProbePackets; bool shouldWriteInitialProbes = diff --git a/quic/api/QuicTransportFunctions.h b/quic/api/QuicTransportFunctions.h index b91bcc11a..1b5ba258d 100644 --- a/quic/api/QuicTransportFunctions.h +++ b/quic/api/QuicTransportFunctions.h @@ -310,15 +310,6 @@ uint64_t writeProbingDataToSocket( QuicVersion version, const std::string& token = std::string()); -uint64_t writeD6DProbeToSocket( - folly::AsyncUDPSocket& sock, - QuicConnectionStateBase& connection, - const ConnectionId& srcConnId, - const ConnectionId& dstConnId, - const Aead& aead, - const PacketNumberCipher& headerCipher, - QuicVersion version); - HeaderBuilder LongHeaderBuilder(LongHeader::Types packetType); HeaderBuilder ShortHeaderBuilder(); diff --git a/quic/api/test/Mocks.h b/quic/api/test/Mocks.h index 203d33b19..52122f3a6 100644 --- a/quic/api/test/Mocks.h +++ b/quic/api/test/Mocks.h @@ -359,17 +359,6 @@ class MockLegacyObserver : public LegacyObserver { rttSampleGenerated, (QuicSocket*, const PacketRTT&), (noexcept)); - MOCK_METHOD((void), pmtuProbingStarted, (QuicSocket*), (noexcept)); - MOCK_METHOD( - (void), - pmtuBlackholeDetected, - (QuicSocket*, const PMTUBlackholeEvent&), - (noexcept)); - MOCK_METHOD( - (void), - pmtuUpperBoundDetected, - (QuicSocket*, const PMTUUpperBoundEvent&), - (noexcept)); MOCK_METHOD( (void), spuriousLossDetected, diff --git a/quic/api/test/QuicPacketSchedulerTest.cpp b/quic/api/test/QuicPacketSchedulerTest.cpp index ad18f5ab2..9d756d370 100644 --- a/quic/api/test/QuicPacketSchedulerTest.cpp +++ b/quic/api/test/QuicPacketSchedulerTest.cpp @@ -29,45 +29,6 @@ enum PacketBuilderType { Regular, Inplace }; namespace { -SchedulingResult sendD6DProbe( - QuicConnectionStateBase& conn, - uint64_t cipherOverhead, - uint32_t probeSize, - PacketBuilderType builderType) { - auto connId = quic::test::getTestConnectionId(); - D6DProbeScheduler d6dProbeScheduler( - conn, "d6d probe", cipherOverhead, probeSize); - EXPECT_TRUE(d6dProbeScheduler.hasData()); - - ShortHeader shortHeader( - ProtectionType::KeyPhaseZero, - connId, - getNextPacketNum(conn, PacketNumberSpace::AppData)); - if (builderType == PacketBuilderType::Regular) { - RegularQuicPacketBuilder builder( - conn.udpSendPacketLen, - std::move(shortHeader), - conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0)); - auto result = d6dProbeScheduler.scheduleFramesForPacket( - std::move(builder), kDefaultUDPSendPacketLen); - EXPECT_FALSE(d6dProbeScheduler.hasData()); - return result; - } else { - // Just enough to build the probe - auto simpleBufAccessor = std::make_unique(probeSize); - InplaceQuicPacketBuilder builder( - *simpleBufAccessor, - conn.udpSendPacketLen, - std::move(shortHeader), - conn.ackStates.appDataAckState.largestAckedByPeer.value_or(0)); - auto result = d6dProbeScheduler.scheduleFramesForPacket( - std::move(builder), kDefaultUDPSendPacketLen); - EXPECT_FALSE(d6dProbeScheduler.hasData()); - return result; - } - folly::assume_unreachable(); -} - PacketNum addInitialOutstandingPacket(QuicConnectionStateBase& conn) { PacketNum nextPacketNum = getNextPacketNum(conn, PacketNumberSpace::Initial); std::vector zeroConnIdData(quic::kDefaultConnectionIdSize, 0); @@ -566,54 +527,6 @@ TEST_F(QuicPacketSchedulerTest, CloningSchedulerTest) { EXPECT_EQ(packetNum, result.packetEvent->packetNumber); } -TEST_P(QuicPacketSchedulerTest, D6DProbeSchedulerTest) { - QuicClientConnectionState conn( - FizzClientQuicHandshakeContext::Builder().build()); - uint64_t cipherOverhead = 2; - uint32_t probeSize = 1450; - auto connId = getTestConnectionId(); - D6DProbeScheduler d6dProbeScheduler( - conn, "d6d probe", cipherOverhead, probeSize); - EXPECT_TRUE(d6dProbeScheduler.hasData()); - - ShortHeader shortHeader( - ProtectionType::KeyPhaseZero, - connId, - getNextPacketNum(conn, PacketNumberSpace::AppData)); - auto param = GetParam(); - auto result = sendD6DProbe(conn, cipherOverhead, probeSize, param); - ASSERT_TRUE(result.packet.has_value()); - auto packetSize = result.packet->header->computeChainDataLength() + - result.packet->body->computeChainDataLength() + cipherOverhead; - EXPECT_EQ(packetSize, probeSize); -} - -TEST_P(QuicPacketSchedulerTest, NoCloningWithOnlyD6DProbes) { - QuicClientConnectionState conn( - FizzClientQuicHandshakeContext::Builder().build()); - uint64_t cipherOverhead = 2; - uint32_t probeSize = 1450; - auto param = GetParam(); - auto result = sendD6DProbe(conn, cipherOverhead, probeSize, param); - ASSERT_TRUE(result.packet.has_value()); - auto packetSize = result.packet->header->computeChainDataLength() + - result.packet->body->computeChainDataLength() + cipherOverhead; - updateConnection( - conn, - folly::none, - result.packet->packet, - Clock::now(), - packetSize, - result.packet->body->computeChainDataLength(), - false /* isDSRPacket */); - ASSERT_EQ(1, conn.outstandings.packets.size()); - EXPECT_TRUE(conn.outstandings.packets.back().metadata.isD6DProbe); - FrameScheduler noopScheduler("noopScheduler", conn); - CloningScheduler cloningScheduler( - noopScheduler, conn, "MarShall Mathers", cipherOverhead); - EXPECT_FALSE(cloningScheduler.hasData()); -} - TEST_F(QuicPacketSchedulerTest, WriteOnlyOutstandingPacketsTest) { QuicClientConnectionState conn( FizzClientQuicHandshakeContext::Builder().build()); @@ -2437,10 +2350,5 @@ TEST_F(QuicPacketSchedulerTest, ImmediateAckFrameSchedulerNotRequested) { EXPECT_LT(packetLength, conn.udpSendPacketLen); } -INSTANTIATE_TEST_SUITE_P( - QuicPacketSchedulerTests, - QuicPacketSchedulerTest, - Values(PacketBuilderType::Regular, PacketBuilderType::Inplace)); - } // namespace test } // namespace quic diff --git a/quic/api/test/QuicTransportFunctionsTest.cpp b/quic/api/test/QuicTransportFunctionsTest.cpp index 666c9a694..3223c2052 100644 --- a/quic/api/test/QuicTransportFunctionsTest.cpp +++ b/quic/api/test/QuicTransportFunctionsTest.cpp @@ -737,48 +737,6 @@ TEST_F( conn->flowControlState.sumCurWriteOffset); } -TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionD6DNotConsumeSendPing) { - auto conn = createConn(); - conn->pendingEvents.sendPing = true; // Simulate application sendPing() - auto packet = buildEmptyPacket(*conn, PacketNumberSpace::AppData); - packet.packet.frames.push_back(PingFrame()); - auto packetNum = packet.packet.header.getPacketSequenceNum(); - conn->d6d.lastProbe = D6DProbePacket(packetNum, 50); - updateConnection( - *conn, - folly::none, - packet.packet, - Clock::now(), - 50, - 0, - false /* isDSRPacket */); - EXPECT_EQ(1, conn->outstandings.packets.size()); - EXPECT_TRUE(conn->outstandings.packets.front().metadata.isD6DProbe); - EXPECT_EQ(1, conn->d6d.outstandingProbes); - // sendPing should still be active since d6d probe should be "hidden" from - // application - EXPECT_TRUE(conn->pendingEvents.sendPing); -} - -TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionD6DNeedsAppDataPNSpace) { - auto conn = createConn(); - auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake); - packet.packet.frames.push_back(PingFrame()); - auto packetNum = packet.packet.header.getPacketSequenceNum(); - conn->d6d.lastProbe = D6DProbePacket(packetNum, 50); - updateConnection( - *conn, - folly::none, - packet.packet, - Clock::now(), - 50, - 0, - false /* isDSRPacket */); - EXPECT_EQ(1, conn->outstandings.packets.size()); - EXPECT_FALSE(conn->outstandings.packets.front().metadata.isD6DProbe); - EXPECT_EQ(0, conn->d6d.outstandingProbes); -} - TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionPacketSorting) { auto conn = createConn(); conn->qLogger = std::make_shared(VantagePoint::Client); @@ -4377,43 +4335,6 @@ TEST_F(QuicTransportFunctionsTest, WriteProbingWithInplaceBuilder) { EXPECT_EQ(conn->outstandings.packets.size(), outstandingPacketsCount + 3); } -TEST_F(QuicTransportFunctionsTest, WriteD6DProbesWithInplaceBuilder) { - auto conn = createConn(); - conn->transportSettings.dataPathType = DataPathType::ContinuousMemory; - conn->d6d.currentProbeSize = 1450; - conn->pendingEvents.d6d.sendProbePacket = true; - auto simpleBufAccessor = - std::make_unique(kDefaultMaxUDPPayload * 16); - auto outputBuf = simpleBufAccessor->obtain(); - auto bufPtr = outputBuf.get(); - simpleBufAccessor->release(std::move(outputBuf)); - conn->bufAccessor = simpleBufAccessor.get(); - conn->transportSettings.batchingMode = QuicBatchingMode::BATCHING_MODE_GSO; - EventBase evb; - folly::test::MockAsyncUDPSocket mockSock(&evb); - EXPECT_CALL(mockSock, getGSO()).WillRepeatedly(Return(true)); - EXPECT_CALL(mockSock, write(_, _)) - .Times(1) - .WillOnce(Invoke([&](const SocketAddress&, - const std::unique_ptr& sockBuf) { - EXPECT_EQ(sockBuf->length(), conn->d6d.currentProbeSize); - EXPECT_EQ(sockBuf.get(), bufPtr); - EXPECT_TRUE(folly::IOBufEqualTo()(*sockBuf, *bufPtr)); - EXPECT_FALSE(sockBuf->isChained()); - return sockBuf->computeChainDataLength(); - })); - writeD6DProbeToSocket( - mockSock, - *conn, - *conn->clientConnectionId, - *conn->serverConnectionId, - *aead, - *headerCipher, - getVersion(*conn)); - EXPECT_EQ(0, bufPtr->length()); - EXPECT_EQ(0, bufPtr->headroom()); -} - TEST_F(QuicTransportFunctionsTest, UpdateConnectionWithBufferMeta) { auto conn = createConn(); // Builds a fake packet to test with. diff --git a/quic/client/QuicClientTransport.cpp b/quic/client/QuicClientTransport.cpp index e6b2de34a..c17f2b0cf 100644 --- a/quic/client/QuicClientTransport.cpp +++ b/quic/client/QuicClientTransport.cpp @@ -1021,9 +1021,6 @@ void QuicClientTransport::startCryptoHandshake() { conn_->initialHeaderCipher = cryptoFactory.makeClientInitialHeaderCipher( *clientConn_->initialDestinationConnectionId, version); - setD6DBasePMTUTransportParameter(); - setD6DRaiseTimeoutTransportParameter(); - setD6DProbeTimeoutTransportParameter(); setSupportedExtensionTransportParameters(); maybeEnableStreamGroups(); auto paramsExtension = std::make_shared( @@ -1657,78 +1654,6 @@ void QuicClientTransport::setSelfOwning() { selfOwning_ = shared_from_this(); } -void QuicClientTransport::setD6DBasePMTUTransportParameter() { - if (!conn_->transportSettings.d6dConfig.enabled) { - return; - } - - uint64_t basePMTUSetting = - conn_->transportSettings.d6dConfig.advertisedBasePMTU; - - // Sanity check - if (basePMTUSetting < kMinMaxUDPPayload || - basePMTUSetting > kDefaultMaxUDPPayload) { - LOG(ERROR) << "insane base PMTU, skipping: " << basePMTUSetting; - return; - } - - auto basePMTUCustomParam = std::make_unique( - kD6DBasePMTUParameterId, basePMTUSetting); - - if (!setCustomTransportParameter( - std::move(basePMTUCustomParam), customTransportParameters_)) { - LOG(ERROR) << "failed to set D6D base PMTU transport parameter"; - } -} - -void QuicClientTransport::setD6DRaiseTimeoutTransportParameter() { - if (!conn_->transportSettings.d6dConfig.enabled) { - return; - } - - std::chrono::seconds raiseTimeoutSetting = - conn_->transportSettings.d6dConfig.advertisedRaiseTimeout; - - // Sanity check - if (raiseTimeoutSetting < kMinD6DRaiseTimeout) { - LOG(ERROR) << "d6d raise timeout exceeding lower bound, skipping: " - << raiseTimeoutSetting.count(); - } - - auto raiseTimeoutCustomParam = - std::make_unique( - kD6DRaiseTimeoutParameterId, raiseTimeoutSetting.count()); - - if (!setCustomTransportParameter( - std::move(raiseTimeoutCustomParam), customTransportParameters_)) { - LOG(ERROR) << "failed to set D6D raise timeout transport parameter"; - } -} - -void QuicClientTransport::setD6DProbeTimeoutTransportParameter() { - if (!conn_->transportSettings.d6dConfig.enabled) { - return; - } - - std::chrono::seconds probeTimeoutSetting = - conn_->transportSettings.d6dConfig.advertisedProbeTimeout; - - // Sanity check - if (probeTimeoutSetting < kMinD6DProbeTimeout) { - LOG(ERROR) << "d6d probe timeout below lower bound, skipping: " - << probeTimeoutSetting.count(); - } - - auto probeTimeoutCustomParam = - std::make_unique( - kD6DProbeTimeoutParameterId, probeTimeoutSetting.count()); - - if (!setCustomTransportParameter( - std::move(probeTimeoutCustomParam), customTransportParameters_)) { - LOG(ERROR) << "failed to set D6D probe timeout transport parameter"; - } -} - void QuicClientTransport::setSupportedExtensionTransportParameters() { if (conn_->transportSettings.minAckDelay.hasValue()) { auto minAckDelayParam = std::make_unique( diff --git a/quic/client/QuicClientTransport.h b/quic/client/QuicClientTransport.h index fbc5abd25..63aab307f 100644 --- a/quic/client/QuicClientTransport.h +++ b/quic/client/QuicClientTransport.h @@ -249,9 +249,6 @@ class QuicClientTransport void resize(size_t numPackets); }; - void setD6DBasePMTUTransportParameter(); - void setD6DRaiseTimeoutTransportParameter(); - void setD6DProbeTimeoutTransportParameter(); void setSupportedExtensionTransportParameters(); void adjustGROBuffers(); void trackDatagramReceived(size_t len); diff --git a/quic/common/test/TestPacketBuilders.cpp b/quic/common/test/TestPacketBuilders.cpp index 950ceceee..e8bfa9c5a 100644 --- a/quic/common/test/TestPacketBuilders.cpp +++ b/quic/common/test/TestPacketBuilders.cpp @@ -172,12 +172,6 @@ OutstandingPacketBuilder&& OutstandingPacketBuilder::setIsHandshake( return std::move(*this); } -OutstandingPacketBuilder&& OutstandingPacketBuilder::setIsD6DProbe( - const bool& isD6DProbeIn) { - maybeIsD6DProbe = isD6DProbeIn; - return std::move(*this); -} - OutstandingPacketBuilder&& OutstandingPacketBuilder::setTotalBytesSent( const uint64_t& totalBytesSentIn) { maybeTotalBytesSent = totalBytesSentIn; @@ -234,7 +228,6 @@ OutstandingPacket OutstandingPacketBuilder::build() && { *CHECK_NOTNULL(maybeEncodedSize.get_pointer()), *CHECK_NOTNULL(maybeEncodedBodySize.get_pointer()), *CHECK_NOTNULL(maybeIsHandshake.get_pointer()), - *CHECK_NOTNULL(maybeIsD6DProbe.get_pointer()), *CHECK_NOTNULL(maybeTotalBytesSent.get_pointer()), *CHECK_NOTNULL(maybeTotalBodyBytesSent.get_pointer()), *CHECK_NOTNULL(maybeInflightBytes.get_pointer()), diff --git a/quic/common/test/TestPacketBuilders.h b/quic/common/test/TestPacketBuilders.h index 8059a967f..b069470c9 100644 --- a/quic/common/test/TestPacketBuilders.h +++ b/quic/common/test/TestPacketBuilders.h @@ -53,7 +53,6 @@ struct OutstandingPacketBuilderFields { folly::Optional maybeEncodedSize; folly::Optional maybeEncodedBodySize; folly::Optional maybeIsHandshake; - folly::Optional maybeIsD6DProbe; folly::Optional maybeTotalBytesSent; folly::Optional maybeTotalBodyBytesSent; folly::Optional maybeInflightBytes; @@ -73,7 +72,6 @@ struct OutstandingPacketBuilder : public OutstandingPacketBuilderFields { Builder&& setEncodedSize(const uint32_t& encodedSizeIn); Builder&& setEncodedBodySize(const uint32_t& encodedBodySizeIn); Builder&& setIsHandshake(const bool& isHandshakeIn); - Builder&& setIsD6DProbe(const bool& isD6DProbeIn); Builder&& setTotalBytesSent(const uint64_t& totalBytesSentIn); Builder&& setTotalBodyBytesSent(const uint64_t& totalBodyBytesSentIn); Builder&& setInflightBytes(const uint64_t& inflightBytesIn); diff --git a/quic/common/test/TestUtils.cpp b/quic/common/test/TestUtils.cpp index 809be6e09..56f23efad 100644 --- a/quic/common/test/TestUtils.cpp +++ b/quic/common/test/TestUtils.cpp @@ -558,7 +558,6 @@ CongestionController::AckEvent makeAck( ackedSize /* encodedSize */, ackedSize /* encodedBodySize */, false /* isHandshake */, - false /* isD6DProbe */, 0 /* totalBytesSent */, 0 /* totalBodyBytesSent */, 0 /* inflightBytes */, diff --git a/quic/d6d/BinarySearchProbeSizeRaiser.h b/quic/d6d/BinarySearchProbeSizeRaiser.h deleted file mode 100644 index a0d966959..000000000 --- a/quic/d6d/BinarySearchProbeSizeRaiser.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include - -namespace quic { - -class BinarySearchProbeSizeRaiser : public ProbeSizeRaiser { - public: - explicit BinarySearchProbeSizeRaiser(uint16_t minSize, uint16_t maxSize) - : minSize_(minSize), maxSize_(maxSize) {} - - void onProbeLost(uint16_t lastProbeSize) override { - if (!sanityCheck(lastProbeSize)) { - return; - } - maxSize_ = lastProbeSize - 1; - } - - folly::Optional raiseProbeSize(uint16_t lastProbeSize) override { - if (!sanityCheck(lastProbeSize)) { - return folly::none; - } - minSize_ = lastProbeSize; - if (minSize_ == maxSize_) { - return folly::none; - } - return (minSize_ + maxSize_ + 1) / 2; - } - - private: - bool sanityCheck(uint16_t lastProbeSize) { - if (lastProbeSize < minSize_) { - VLOG(2) - << __func__ - << " lastProbeSize is less than minSize, possibly re-odering, skipping"; - return false; - } - return true; - } - - uint16_t minSize_; - uint16_t maxSize_; -}; - -} // namespace quic diff --git a/quic/d6d/CMakeLists.txt b/quic/d6d/CMakeLists.txt deleted file mode 100644 index 4b981c65e..000000000 --- a/quic/d6d/CMakeLists.txt +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -# Probe Raiser -add_library( - mvfst_d6d_probe_raiser INTERFACE -) - -target_include_directories( - mvfst_d6d_probe_raiser INTERFACE - $ - $ -) - -# State Functions -add_library( - mvfst_d6d_state_functions STATIC - QuicD6DStateFunctions.cpp -) - -target_include_directories( - mvfst_d6d_state_functions PUBLIC - $ - $ -) - -target_compile_options( - mvfst_d6d_state_functions - PRIVATE - ${_QUIC_COMMON_COMPILE_OPTIONS} -) - -add_dependencies( - mvfst_d6d_state_functions - mvfst_state_machine -) - -target_link_libraries( - mvfst_d6d_state_functions PUBLIC - Folly::folly - mvfst_state_machine -) - -# Types -add_library( - mvfst_d6d_types STATIC - Types.cpp -) - -target_include_directories( - mvfst_d6d_types PUBLIC - $ - $ -) - -target_compile_options( - mvfst_d6d_types - PRIVATE - ${_QUIC_COMMON_COMPILE_OPTIONS} -) - -add_dependencies( - mvfst_d6d_types - mvfst_codec_types -) - -target_link_libraries( - mvfst_d6d_types PUBLIC - Folly::folly - mvfst_codec_types -) - -file( - GLOB_RECURSE QUIC_API_HEADERS_TOINSTALL - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - *.h -) - -list(FILTER QUIC_API_HEADERS_TOINSTALL EXCLUDE REGEX test/) -foreach(header ${QUIC_API_HEADERS_TOINSTALL}) - get_filename_component(header_dir ${header} DIRECTORY) - install(FILES ${header} DESTINATION include/quic/d6d/${header_dir}) -endforeach() - -install( - TARGETS mvfst_d6d_probe_raiser - EXPORT mvfst-exports -) - -install( - TARGETS mvfst_d6d_state_functions - EXPORT mvfst-exports - DESTINATION lib -) - -install( - TARGETS mvfst_d6d_types - EXPORT mvfst-exports - DESTINATION lib -) - -add_subdirectory(test) diff --git a/quic/d6d/ConstantStepProbeSizeRaiser.h b/quic/d6d/ConstantStepProbeSizeRaiser.h deleted file mode 100644 index 665c3edc9..000000000 --- a/quic/d6d/ConstantStepProbeSizeRaiser.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace quic { - -/** - * A very naive constant step probe size raiser that does not care - * about any upper bound, because that's already controlled by d6d - * state functions. - **/ -class ConstantStepProbeSizeRaiser : public ProbeSizeRaiser { - public: - explicit ConstantStepProbeSizeRaiser(uint16_t stepSize) - : stepSize_(stepSize) {} - - // Do nothing - void onProbeLost(uint16_t /* lastProbeSize */) override {} - - folly::Optional raiseProbeSize(uint16_t lastProbeSize) override { - return lastProbeSize + stepSize_; - } - - private: - uint16_t stepSize_; -}; - -} // namespace quic diff --git a/quic/d6d/ProbeSizeRaiser.h b/quic/d6d/ProbeSizeRaiser.h deleted file mode 100644 index a895c017a..000000000 --- a/quic/d6d/ProbeSizeRaiser.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace quic { - -// Abstract class used for raising the probe size. Making it abstract so that -// applications can choose their own implementation -class ProbeSizeRaiser { - public: - virtual ~ProbeSizeRaiser() = default; - - // Notify the stepper that probe is lost, useful for updating its internal - // state - virtual void onProbeLost(uint16_t lastProbeSize) = 0; - - // Raise and returns the next probe size. Returns folly::none if the - // raiser cannot do so - virtual folly::Optional raiseProbeSize(uint16_t lastProbeSize) = 0; -}; - -} // namespace quic diff --git a/quic/d6d/QuicD6DStateFunctions.cpp b/quic/d6d/QuicD6DStateFunctions.cpp deleted file mode 100644 index 309770c26..000000000 --- a/quic/d6d/QuicD6DStateFunctions.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include - -namespace quic { - -inline void scheduleProbeAfterDelay( - QuicConnectionStateBase& conn, - std::chrono::milliseconds delay) { - conn.pendingEvents.d6d.sendProbeDelay = delay; -} - -/** - * A helper function that reports PMTU Upper Bound event. - * Returns the event timestamp - */ -static TimePoint reportUpperBound(QuicConnectionStateBase& conn) { - auto& d6d = conn.d6d; - const auto lastProbeSize = d6d.lastProbe->packetSize; - const auto now = Clock::now(); - QUIC_STATS(conn.statsCallback, onConnectionPMTUUpperBoundDetected); - - // notify observers - { - const auto socketObserverContainer = conn.getSocketObserverContainer(); - if (socketObserverContainer && - socketObserverContainer->hasObserversForEvent< - SocketObserverInterface::Events::pmtuEvents>()) { - socketObserverContainer - ->invokeInterfaceMethod( - [event = SocketObserverInterface::PMTUUpperBoundEvent( - now, - std::chrono::duration_cast( - now - d6d.meta.timeLastNonSearchState), - d6d.meta.lastNonSearchState, - lastProbeSize, - d6d.meta.totalTxedProbes, - conn.transportSettings.d6dConfig.raiserType)]( - auto observer, auto observed) { - observer->pmtuUpperBoundDetected(observed, event); - }); - } - } - - return now; -} - -/** - * Helper function that reports PMTU blackhole event. - * Returns the event timestamp - */ -static TimePoint reportBlackhole( - QuicConnectionStateBase& conn, - const OutstandingPacket& packet) { - QUIC_STATS(conn.statsCallback, onConnectionPMTUBlackholeDetected); - auto& d6d = conn.d6d; - const auto now = Clock::now(); - - // notify observers - { - const auto socketObserverContainer = conn.getSocketObserverContainer(); - if (socketObserverContainer && - socketObserverContainer->hasObserversForEvent< - SocketObserverInterface::Events::pmtuEvents>()) { - socketObserverContainer - ->invokeInterfaceMethod( - [event = SocketObserverInterface::PMTUBlackholeEvent( - now, - std::chrono::duration_cast( - now - d6d.meta.timeLastNonSearchState), - d6d.meta.lastNonSearchState, - d6d.state, - conn.udpSendPacketLen, - d6d.lastProbe->packetSize, - d6d.thresholdCounter->getWindow(), - d6d.thresholdCounter->getThreshold(), - packet)](auto observer, auto observed) { - observer->pmtuBlackholeDetected(observed, event); - }); - } - } - return now; -} - -static void onD6DLastProbeAckedInSearching( - QuicConnectionStateBase& conn, - uint32_t lastProbeSize, - folly::Optional maybeNextProbeSize) { - auto& d6d = conn.d6d; - // Temporary mitigation - if (lastProbeSize <= conn.udpSendPacketLen) { - LOG(ERROR) << "D6D lastProbeSize <= udpSendPacketLen"; - return; - } - QUIC_STATS(conn.statsCallback, onConnectionPMTURaised); - conn.udpSendPacketLen = lastProbeSize; - if (maybeNextProbeSize.hasValue() && - *maybeNextProbeSize > conn.udpSendPacketLen && - *maybeNextProbeSize <= d6d.maxPMTU) { - d6d.currentProbeSize = *maybeNextProbeSize; - scheduleProbeAfterDelay(conn, kDefaultD6DProbeDelayWhenAcked); - } else { - // We've reached either the PMTU upper bound or the probe size - // raiser's internal upper bound, in both cases the search is - // completed - d6d.state = D6DMachineState::SEARCH_COMPLETE; - conn.pendingEvents.d6d.scheduleRaiseTimeout = true; - conn.pendingEvents.d6d.scheduleProbeTimeout = false; - reportUpperBound(conn); - } -} - -void onD6DProbeTimeoutExpired(QuicConnectionStateBase& conn) { - onD6DLastProbeLost(conn); -} - -void onD6DRaiseTimeoutExpired(QuicConnectionStateBase& conn) { - auto& d6d = conn.d6d; - if (d6d.state == D6DMachineState::SEARCH_COMPLETE) { - d6d.state = D6DMachineState::SEARCHING; - conn.pendingEvents.d6d.sendProbePacket = true; - } else { - LOG(ERROR) << "d6d: raise timeout expired in state: " - << toString(d6d.state); - } -} - -void onD6DLastProbeAcked(QuicConnectionStateBase& conn) { - auto& d6d = conn.d6d; - const auto lastProbeSize = d6d.lastProbe->packetSize; - - // Reset outstanding probes to 0 - d6d.outstandingProbes = 0; - auto maybeNextProbeSize = d6d.raiser->raiseProbeSize(lastProbeSize); - - switch (d6d.state) { - case D6DMachineState::BASE: - // There could be a series of events leading to receiving ack for probe of - // size larger basePMTU in BASE state: - // 1. the connection was in the SEARCHING state, sending probes of size - // larger than basePMTU - // 2. blackhole detection signals a false positive due to congestion, - // setting the state back to BASE - // 3. the ack for the probe sent prior to the blackhole is received, the - // next probe size will therefore exceed raiseProbeSize(basePMTU) - // In such situations, we can be certain that the previous blackhole is a - // false positive, and we should treat this ack as a valid ack. - if (lastProbeSize != d6d.basePMTU) { - // TODO(xtt) report false positive pmtu blackholes - d6d.state = D6DMachineState::SEARCHING; - onD6DLastProbeAckedInSearching(conn, lastProbeSize, maybeNextProbeSize); - } else { - if (maybeNextProbeSize.hasValue() && - *maybeNextProbeSize > conn.udpSendPacketLen && - *maybeNextProbeSize <= d6d.maxPMTU) { - d6d.currentProbeSize = *maybeNextProbeSize; - d6d.state = D6DMachineState::SEARCHING; - scheduleProbeAfterDelay(conn, kDefaultD6DProbeDelayWhenAcked); - } else { - // This means either the probe size raiser is poorly configured or we - // have a very small maxPMTU. In either case, we've reached the - // upperbound, which is sadly only basePMTU - d6d.state = D6DMachineState::SEARCH_COMPLETE; - conn.pendingEvents.d6d.scheduleRaiseTimeout = true; - conn.pendingEvents.d6d.scheduleProbeTimeout = false; - reportUpperBound(conn); - } - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = Clock::now(); - } - break; - case D6DMachineState::SEARCHING: - onD6DLastProbeAckedInSearching(conn, lastProbeSize, maybeNextProbeSize); - break; - case D6DMachineState::ERROR: - // This means that a smaller probe went through the network. - // We should try sending base pmtu-sized packet now. - d6d.currentProbeSize = d6d.basePMTU; - d6d.state = D6DMachineState::BASE; - d6d.meta.lastNonSearchState = D6DMachineState::ERROR; - d6d.meta.timeLastNonSearchState = Clock::now(); - scheduleProbeAfterDelay(conn, kDefaultD6DProbeDelayWhenAcked); - break; - default: - LOG(ERROR) << "d6d: receive probe ack in state: " << toString(d6d.state); - } -} - -void onD6DLastProbeLost(QuicConnectionStateBase& conn) { - auto& d6d = conn.d6d; - switch (d6d.state) { - case D6DMachineState::BASE: - if (d6d.outstandingProbes >= kDefaultD6DMaxOutstandingProbes) { - // This indicates serious issue with the effective PMTU, a possible - // remedy is to probe much smaller - d6d.state = D6DMachineState::ERROR; - d6d.currentProbeSize = kMinMaxUDPPayload; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = Clock::now(); - - // TODO: reduce udpSendPacketLen below base once we can trust - // this signal. Currently assuming quic is going to terminate - // connection prior to this state. - } - // In both BASE and ERROR state, we need to keep sending probes - scheduleProbeAfterDelay(conn, kDefaultD6DProbeDelayWhenLost); - break; - case D6DMachineState::SEARCHING: - if (d6d.outstandingProbes >= kDefaultD6DMaxOutstandingProbes) { - // We've lost enough consecutive probes, which should indicate - // that the upper bound is reached - d6d.state = D6DMachineState::SEARCH_COMPLETE; - conn.pendingEvents.d6d.scheduleRaiseTimeout = true; - conn.pendingEvents.d6d.scheduleProbeTimeout = false; - reportUpperBound(conn); - return; - } - // Otherwise, the loss could be due to congestion, so we keep - // sending probe - // TODO: pace d6d probing when there's congestion - scheduleProbeAfterDelay(conn, kDefaultD6DProbeDelayWhenLost); - break; - case D6DMachineState::ERROR: - // Keep probing with min probe size - scheduleProbeAfterDelay(conn, kDefaultD6DProbeDelayWhenLost); - break; - default: - LOG(ERROR) << "d6d: probe timeout expired in state: " - << toString(d6d.state); - return; - } -} - -/** - * D6D blackhole detection mechanism for non-probe packets, which - * signals blackhole due to invalid PMTU by detetcing consecutive loss - * of big packets (i.e. packet size greater than base pmtu) - * https://tools.ietf.org/id/draft-ietf-tsvwg-datagram-plpmtud-21.html#name-black-hole-detection-and-re - */ -void detectPMTUBlackhole( - QuicConnectionStateBase& conn, - const OutstandingPacket& packet) { - auto& d6d = conn.d6d; - // If d6d is not activated, or it's a d6d probe, or that the packet size is - // less than base pmtu, then the loss is not caused by pmtu blackhole - if (d6d.state == D6DMachineState::DISABLED || packet.metadata.isD6DProbe || - packet.metadata.encodedSize <= d6d.basePMTU || - conn.udpSendPacketLen <= d6d.basePMTU || d6d.noBlackholeDetection) { - return; - } - - // We use a windowed threshold counter to detect excessive loss of - // large packets. - if (d6d.thresholdCounter && - d6d.thresholdCounter->update( - std::chrono::duration_cast( - packet.metadata.time.time_since_epoch()) - .count())) { - LOG(ERROR) << "PMTU blackhole detected on packet loss, reducing PMTU from " - << conn.udpSendPacketLen << " to base " << d6d.basePMTU; - - auto eventTime = reportBlackhole(conn, packet); - if (d6d.state != D6DMachineState::SEARCHING) { - d6d.meta.lastNonSearchState = d6d.state; - d6d.meta.timeLastNonSearchState = eventTime; - } - d6d.state = D6DMachineState::BASE; - d6d.currentProbeSize = d6d.basePMTU; - conn.udpSendPacketLen = d6d.basePMTU; - // Cancel existing raise timeout if any - conn.pendingEvents.d6d.scheduleRaiseTimeout = false; - } -} -} // namespace quic diff --git a/quic/d6d/QuicD6DStateFunctions.h b/quic/d6d/QuicD6DStateFunctions.h deleted file mode 100644 index c1bead559..000000000 --- a/quic/d6d/QuicD6DStateFunctions.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once -#include -#include - -namespace quic { - -void onD6DProbeTimeoutExpired(QuicConnectionStateBase& conn); - -void onD6DRaiseTimeoutExpired(QuicConnectionStateBase& conn); - -void onD6DLastProbeAcked(QuicConnectionStateBase& conn); - -void onD6DLastProbeLost(QuicConnectionStateBase& conn); - -void detectPMTUBlackhole( - QuicConnectionStateBase& conn, - const OutstandingPacket& packet); - -} // namespace quic diff --git a/quic/d6d/Types.cpp b/quic/d6d/Types.cpp deleted file mode 100644 index cd71da2d7..000000000 --- a/quic/d6d/Types.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include - -#include - -namespace quic { -std::string toString(const D6DMachineState state) { - switch (state) { - case D6DMachineState::DISABLED: - return "DISABLED"; - case D6DMachineState::BASE: - return "BASE"; - case D6DMachineState::SEARCHING: - return "SEARCHING"; - case D6DMachineState::SEARCH_COMPLETE: - return "SEARCH_COMPLETE"; - case D6DMachineState::ERROR: - return "ERROR"; - } - folly::assume_unreachable(); -} - -std::string toString(const ProbeSizeRaiserType type) { - switch (type) { - case ProbeSizeRaiserType::ConstantStep: - return "ConstantStep"; - case ProbeSizeRaiserType::BinarySearch: - return "BinarySearch"; - } - folly::assume_unreachable(); -} - -} // namespace quic diff --git a/quic/d6d/Types.h b/quic/d6d/Types.h deleted file mode 100644 index 238cc37f3..000000000 --- a/quic/d6d/Types.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include - -namespace quic { -struct D6DProbePacket { - D6DProbePacket() = delete; - - explicit D6DProbePacket(PacketNum packetNumIn, uint32_t packetSizeIn) - : packetNum(packetNumIn), packetSize(packetSizeIn) {} - - // Packet num - PacketNum packetNum; - - // Udp packet payload size - uint32_t packetSize; -}; - -// States of d6d state machine, see -// https://tools.ietf.org/id/draft-ietf-tsvwg-datagram-plpmtud-21.html#name-state-machine -enum class D6DMachineState : uint8_t { - // Connection is not established yet - DISABLED = 0, - // Probe using base pmtu - BASE = 1, - // Incrementally probe using larger pmtu - SEARCHING = 2, - // Sleep for raise timeout before going to SEARCHING - SEARCH_COMPLETE = 3, - // Effective pmtu is less than base pmtu, continue probing with smaller - // packet - ERROR = 4 -}; - -/** - * Two simple probe size raiser. Only server makes use of this value. - * ConstantSize: raise pmtu at constant step size - * BinarySearch: raise pmtu using binary search - */ -enum class ProbeSizeRaiserType : uint8_t { ConstantStep = 0, BinarySearch = 1 }; - -std::string toString(const D6DMachineState state); -std::string toString(const ProbeSizeRaiserType type); - -} // namespace quic diff --git a/quic/d6d/test/CMakeLists.txt b/quic/d6d/test/CMakeLists.txt deleted file mode 100644 index 9327909fb..000000000 --- a/quic/d6d/test/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -if(NOT BUILD_TESTS) - return() -endif() - -quic_add_test(TARGET QuicD6DProbeSizeRaiserTest - SOURCES - ProbeSizeRaiserTest.cpp - DEPENDS - Folly::folly - mvfst_d6d_probe_raiser -) - -quic_add_test(TARGET QuicD6DStateFunctionTest - SOURCES - QuicD6DStateFunctionsTest.cpp - DEPENDS - Folly::folly - mvfst_d6d_probe_raiser - mvfst_d6d_state_functions - mvfst_test_utils -) diff --git a/quic/d6d/test/Mocks.h b/quic/d6d/test/Mocks.h deleted file mode 100644 index 289c18197..000000000 --- a/quic/d6d/test/Mocks.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include - -namespace quic { -namespace test { - -// Mock -class MockProbeSizeRaiser : public ProbeSizeRaiser { - public: - ~MockProbeSizeRaiser() override {} - - MOCK_METHOD(void, onProbeLost, (uint16_t lastProbeSize)); - MOCK_METHOD( - folly::Optional, - raiseProbeSize, - (uint16_t lastProbeSize)); -}; - -} // namespace test -} // namespace quic diff --git a/quic/d6d/test/ProbeSizeRaiserTest.cpp b/quic/d6d/test/ProbeSizeRaiserTest.cpp deleted file mode 100644 index 5866a96d4..000000000 --- a/quic/d6d/test/ProbeSizeRaiserTest.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include -#include - -namespace quic { -namespace test { - -struct ProbeSizeRaiserTestFixture { - struct TestUnit { - uint16_t probeSize; - bool pass; - folly::Optional nextProbeSize; - }; - uint16_t groundTruth; - std::vector testUnits; -}; - -void run(ProbeSizeRaiser* raiser, ProbeSizeRaiserTestFixture& fixture) { - folly::Optional lastGoodProbeSize; - for (size_t i = 0; i < fixture.testUnits.size(); i++) { - auto& t = fixture.testUnits[i]; - if (t.probeSize > fixture.groundTruth) { - EXPECT_FALSE(t.pass) << "Test unit " << i; - raiser->onProbeLost(t.probeSize); - auto result = raiser->raiseProbeSize(*lastGoodProbeSize); - // Either both are none, or they have the same value - EXPECT_TRUE( - (!result.hasValue() && !t.nextProbeSize.hasValue()) || - (*result == *t.nextProbeSize)) - << "Test unit " << i; - } else { - EXPECT_TRUE(t.pass) << "Test unit " << i; - auto result = raiser->raiseProbeSize(t.probeSize); - EXPECT_TRUE( - (!result.hasValue() && !t.nextProbeSize.hasValue()) || - (*result == *t.nextProbeSize)) - << "Test unit " << i; - lastGoodProbeSize = t.probeSize; - } - } -} - -TEST(BinarySearchProbeSizeRaiserTest, CloseMinAndMax) { - BinarySearchProbeSizeRaiser raiser(1000, 1001); - auto result = raiser.raiseProbeSize(1000); - EXPECT_EQ(*result, 1001); - result = raiser.raiseProbeSize(1001); - EXPECT_FALSE(result.hasValue()); -} - -TEST(BinarySearchProbeSizeRaiserTest, ReachMax) { - BinarySearchProbeSizeRaiser raiser(1200, 1499); - ProbeSizeRaiserTestFixture fixture = { - 1499, - { - {1200, true, 1350}, - {1350, true, 1425}, - {1425, true, 1462}, - {1462, true, 1481}, - {1481, true, 1490}, - {1490, true, 1495}, - {1495, true, 1497}, - {1497, true, 1498}, - {1498, true, 1499}, - {1499, true, folly::none}, - }, - }; - run(dynamic_cast(&raiser), fixture); -} - -TEST(BinarySearchProbeSizeRaiserTest, StopInTheMiddle) { - BinarySearchProbeSizeRaiser raiser(1200, 1499); - ProbeSizeRaiserTestFixture fixture = { - 1399, - { - {1200, true, 1350}, - {1350, true, 1425}, - {1425, false, 1387}, - {1387, true, 1406}, - {1406, false, 1396}, - {1396, true, 1401}, - {1401, false, 1398}, - {1398, true, 1399}, - {1399, true, 1400}, - {1400, false, folly::none}, - }, - }; - run(dynamic_cast(&raiser), fixture); -} - -} // namespace test -} // namespace quic diff --git a/quic/d6d/test/QuicD6DStateFunctionsTest.cpp b/quic/d6d/test/QuicD6DStateFunctionsTest.cpp deleted file mode 100644 index afa0f15ad..000000000 --- a/quic/d6d/test/QuicD6DStateFunctionsTest.cpp +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace testing; - -namespace quic { -namespace test { - -// timeLastNonSearchState can only increase -enum class TimeLastNonSearchStateEnd : uint8_t { EQ, GE }; - -struct D6DProbeLostTestFixture { - D6DMachineState stateBegin; - D6DMachineState stateEnd; - bool sendProbeBegin; - folly::Optional sendProbeDelayEnd; - // probe loss doesn't change outstanding probes, so a begin value - // is enough - uint64_t outstandingProbes; - uint32_t currentProbeSizeBegin; - uint32_t currentProbeSizeEnd; - D6DProbePacket lastProbe; - D6DMachineState lastNonSearchStateBegin; - D6DMachineState lastNonSearchStateEnd; - TimePoint timeLastNonSearchStateBegin; - TimeLastNonSearchStateEnd timeLastNonSearchStateEndE; -}; - -RegularQuicWritePacket makeTestShortPacket() { - ShortHeader header( - ProtectionType::KeyPhaseZero, getTestConnectionId(), 2 /* packetNum */); - RegularQuicWritePacket packet(std::move(header)); - return packet; -} - -class QuicD6DStateFunctionsTest : public Test { - public: - void runD6DProbeLostTest( - QuicConnectionStateBase& conn, - D6DProbeLostTestFixture fixture) { - conn.d6d.state = fixture.stateBegin; - conn.d6d.outstandingProbes = fixture.outstandingProbes; - conn.d6d.currentProbeSize = fixture.currentProbeSizeBegin; - conn.d6d.lastProbe = fixture.lastProbe; - conn.pendingEvents.d6d.sendProbePacket = fixture.sendProbeBegin; - conn.d6d.meta.lastNonSearchState = fixture.lastNonSearchStateBegin; - conn.d6d.meta.timeLastNonSearchState = fixture.timeLastNonSearchStateBegin; - onD6DLastProbeLost(conn); - EXPECT_EQ(conn.d6d.state, fixture.stateEnd); - EXPECT_EQ(conn.d6d.currentProbeSize, fixture.currentProbeSizeEnd); - if (fixture.sendProbeDelayEnd.hasValue()) { - ASSERT_TRUE(conn.pendingEvents.d6d.sendProbeDelay.hasValue()); - EXPECT_EQ( - *conn.pendingEvents.d6d.sendProbeDelay, *fixture.sendProbeDelayEnd); - } else { - ASSERT_FALSE(conn.pendingEvents.d6d.sendProbeDelay.hasValue()); - } - EXPECT_EQ(conn.d6d.meta.lastNonSearchState, fixture.lastNonSearchStateEnd); - switch (fixture.timeLastNonSearchStateEndE) { - case TimeLastNonSearchStateEnd::EQ: - EXPECT_EQ( - conn.d6d.meta.timeLastNonSearchState, - fixture.timeLastNonSearchStateBegin); - break; - default: - EXPECT_GE( - conn.d6d.meta.timeLastNonSearchState, - fixture.timeLastNonSearchStateBegin); - } - } -}; - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeTimeoutExpiredOneInBase) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto now = Clock::now(); - // One probe lost in BASE state - D6DProbeLostTestFixture oneProbeLostInBase = { - D6DMachineState::BASE, // stateBegin - D6DMachineState::BASE, // stateEnd - false, // sendProbeBegin - kDefaultD6DProbeDelayWhenLost, // sendProbeEnd - 1, // outstandingProbes - conn.d6d.basePMTU, // currentProbeSizeBegin - conn.d6d.basePMTU, // currentProbeSizeEnd - D6DProbePacket(0, conn.d6d.basePMTU + 10), - D6DMachineState::DISABLED, // lastNonSearchStateBegin - D6DMachineState::DISABLED, // lastNonSearchStateEnd - now, // timeLastNonSearchStateBegin - TimeLastNonSearchStateEnd::EQ // timeLastNonSearchStateEndE - }; - runD6DProbeLostTest(conn, oneProbeLostInBase); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeTimeoutExpiredMaxInBase) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto now = Clock::now(); - // max number of probes lost in BASE state - D6DProbeLostTestFixture maxNumProbesLostInBase = { - D6DMachineState::BASE, - D6DMachineState::ERROR, - false, - kDefaultD6DProbeDelayWhenLost, - kDefaultD6DMaxOutstandingProbes, - conn.d6d.basePMTU, - kMinMaxUDPPayload, - D6DProbePacket(0, conn.d6d.basePMTU + 10), - D6DMachineState::DISABLED, - D6DMachineState::BASE, - now, - TimeLastNonSearchStateEnd::GE}; - runD6DProbeLostTest(conn, maxNumProbesLostInBase); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeTimeoutExpiredOneInSearching) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto now = Clock::now(); - // One probe lots in SEARCHING state - D6DProbeLostTestFixture oneProbeLostInSearching = { - D6DMachineState::SEARCHING, - D6DMachineState::SEARCHING, - false, - kDefaultD6DProbeDelayWhenLost, - 1, - static_cast(conn.d6d.basePMTU + 10), - static_cast(conn.d6d.basePMTU + 10), - D6DProbePacket(0, conn.d6d.basePMTU + 10), - D6DMachineState::BASE, - D6DMachineState::BASE, - now, - TimeLastNonSearchStateEnd::EQ}; - runD6DProbeLostTest(conn, oneProbeLostInSearching); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeTimeoutExpiredMaxInSearching) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto now = Clock::now(); - // Max number of probes lost in SEARCHING state - D6DProbeLostTestFixture maxProbesLostInSearching = { - D6DMachineState::SEARCHING, - D6DMachineState::SEARCH_COMPLETE, - false, - folly::none, - kDefaultD6DMaxOutstandingProbes, - static_cast(conn.d6d.basePMTU + 10), - static_cast(conn.d6d.basePMTU + 10), - D6DProbePacket(0, conn.d6d.basePMTU + 10), - D6DMachineState::BASE, - D6DMachineState::BASE, - now, - TimeLastNonSearchStateEnd::EQ}; - runD6DProbeLostTest(conn, maxProbesLostInSearching); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeTimeoutExpiredOneInError) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto now = Clock::now(); - // Probe lost in ERROR state - D6DProbeLostTestFixture probeLostInError = { - D6DMachineState::ERROR, - D6DMachineState::ERROR, - false, - kDefaultD6DProbeDelayWhenLost, - kDefaultD6DMaxOutstandingProbes + 1, - kMinMaxUDPPayload, - kMinMaxUDPPayload, - D6DProbePacket(0, conn.d6d.basePMTU + 10), - D6DMachineState::BASE, - D6DMachineState::BASE, - now, - TimeLastNonSearchStateEnd::EQ}; - runD6DProbeLostTest(conn, probeLostInError); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeAckedInBase) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - const uint16_t expectPMTU = 1400; - auto& d6d = conn.d6d; - const auto now = Clock::now(); - d6d.state = D6DMachineState::BASE; - d6d.outstandingProbes = 1; - d6d.currentProbeSize = d6d.basePMTU; - d6d.meta.lastNonSearchState = D6DMachineState::DISABLED; - d6d.meta.timeLastNonSearchState = now; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(expectPMTU)); - EXPECT_CALL(*obs1, pmtuUpperBoundDetected(_, _)).Times(0); - onD6DLastProbeAcked(conn); - - EXPECT_EQ(d6d.state, D6DMachineState::SEARCHING); - EXPECT_EQ(d6d.currentProbeSize, expectPMTU); - EXPECT_EQ(conn.udpSendPacketLen, d6d.basePMTU); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_GE(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeAckedInSearchingOne) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - const uint16_t expectPMTU = 1400; - auto& d6d = conn.d6d; - const auto now = Clock::now(); - d6d.state = D6DMachineState::SEARCHING; - d6d.outstandingProbes = 1; - conn.udpSendPacketLen = 1250; - d6d.currentProbeSize = 1300; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(expectPMTU)); - EXPECT_CALL(*obs1, pmtuUpperBoundDetected(_, _)).Times(0); - onD6DLastProbeAcked(conn); - - EXPECT_EQ(d6d.state, D6DMachineState::SEARCHING); - EXPECT_EQ(d6d.currentProbeSize, expectPMTU); - EXPECT_EQ(conn.udpSendPacketLen, 1300); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_EQ(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeAckedInSearchingMax) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - const uint16_t oversize = 1500; - auto& d6d = conn.d6d; - const auto now = Clock::now(); - d6d.state = D6DMachineState::SEARCHING; - d6d.outstandingProbes = 3; - conn.udpSendPacketLen = 1400; - d6d.currentProbeSize = 1450; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - d6d.meta.totalTxedProbes = 10; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(oversize)); - EXPECT_CALL(*obs1, pmtuUpperBoundDetected(_, _)) - .Times(1) - .WillOnce(Invoke( - [&](QuicSocket* /* qSocket */, - const SocketObserverInterface::PMTUUpperBoundEvent& event) { - EXPECT_LT(now, event.upperBoundTime); - EXPECT_LT(0us, event.timeSinceLastNonSearchState); - EXPECT_EQ(D6DMachineState::BASE, event.lastNonSearchState); - EXPECT_EQ(1450, event.upperBoundPMTU); - EXPECT_EQ(10, event.cumulativeProbesSent); - EXPECT_EQ( - ProbeSizeRaiserType::ConstantStep, event.probeSizeRaiserType); - })); - onD6DLastProbeAcked(conn); - - EXPECT_EQ(d6d.state, D6DMachineState::SEARCH_COMPLETE); - EXPECT_EQ(d6d.currentProbeSize, 1450); - EXPECT_EQ(conn.udpSendPacketLen, 1450); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_EQ(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F(QuicD6DStateFunctionsTest, D6DProbeAckedInError) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - auto& d6d = conn.d6d; - const auto now = Clock::now(); - d6d.state = D6DMachineState::ERROR; - d6d.outstandingProbes = 3; - conn.udpSendPacketLen = d6d.basePMTU; - d6d.currentProbeSize = d6d.basePMTU - 20; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(1300)); // Won't be used - EXPECT_CALL(*obs1, pmtuUpperBoundDetected(_, _)).Times(0); - onD6DLastProbeAcked(conn); - - EXPECT_EQ(d6d.state, D6DMachineState::BASE); - EXPECT_EQ(d6d.currentProbeSize, d6d.basePMTU); - EXPECT_EQ(conn.udpSendPacketLen, d6d.basePMTU); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::ERROR); - EXPECT_GE(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F(QuicD6DStateFunctionsTest, BlackholeInSearching) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - auto& d6d = conn.d6d; - const auto now = Clock::now(); - d6d.state = D6DMachineState::SEARCHING; - d6d.outstandingProbes = 2; - conn.udpSendPacketLen = d6d.basePMTU + 20; - d6d.currentProbeSize = d6d.basePMTU + 30; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - now + 10s, - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - - auto lostPacket = OutstandingPacket( - makeTestShortPacket(), - now + 8s, - conn.udpSendPacketLen, - 0, - false, - conn.udpSendPacketLen + d6d.currentProbeSize, - 0, - conn.udpSendPacketLen + d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - - d6d.thresholdCounter = std::make_unique>( - std::chrono::microseconds(kDefaultD6DBlackholeDetectionWindow).count(), - 1); // Threshold of 1 will cause window to be set to 0 - - EXPECT_CALL(*obs1, pmtuBlackholeDetected(_, _)) - .Times(1) - .WillOnce( - Invoke([&](QuicSocket* /* qSocket */, - const SocketObserverInterface::PMTUBlackholeEvent& event) { - EXPECT_LE(d6d.meta.timeLastNonSearchState, event.blackholeTime); - EXPECT_EQ(D6DMachineState::BASE, event.lastNonSearchState); - EXPECT_EQ(D6DMachineState::SEARCHING, event.currentState); - EXPECT_EQ(d6d.basePMTU + 20, event.udpSendPacketLen); - EXPECT_EQ(d6d.basePMTU + 30, event.lastProbeSize); - EXPECT_EQ(0, event.blackholeDetectionWindow); - EXPECT_EQ(1, event.blackholeDetectionThreshold); - EXPECT_EQ( - d6d.basePMTU + 20, event.triggeringPacketMetadata.encodedSize); - })); - detectPMTUBlackhole(conn, lostPacket); - - EXPECT_EQ(d6d.state, D6DMachineState::BASE); - EXPECT_EQ(d6d.currentProbeSize, d6d.basePMTU); - EXPECT_EQ(conn.udpSendPacketLen, d6d.basePMTU); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_GE(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F(QuicD6DStateFunctionsTest, BlackholeInSearchComplete) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - auto& d6d = conn.d6d; - auto now = Clock::now(); - d6d.state = D6DMachineState::SEARCH_COMPLETE; - conn.udpSendPacketLen = d6d.basePMTU + 20; - d6d.currentProbeSize = d6d.basePMTU + 20; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - now + 10s, - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - - auto lostPacket = OutstandingPacket( - makeTestShortPacket(), - now + 12s, - conn.udpSendPacketLen, - 0, - false, - conn.udpSendPacketLen + d6d.currentProbeSize, - 0, - conn.udpSendPacketLen + d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - - d6d.thresholdCounter = std::make_unique>( - std::chrono::microseconds(kDefaultD6DBlackholeDetectionWindow).count(), - 1); // Threshold of 1 will cause window to be set to 0 - - EXPECT_CALL(*obs1, pmtuBlackholeDetected(_, _)) - .Times(1) - .WillOnce( - Invoke([&](QuicSocket* /* qSocket */, - const SocketObserverInterface::PMTUBlackholeEvent& event) { - EXPECT_LE(d6d.meta.timeLastNonSearchState, event.blackholeTime); - EXPECT_EQ(D6DMachineState::BASE, event.lastNonSearchState); - EXPECT_EQ(D6DMachineState::SEARCH_COMPLETE, event.currentState); - EXPECT_EQ(d6d.basePMTU + 20, event.udpSendPacketLen); - EXPECT_EQ(d6d.basePMTU + 20, event.lastProbeSize); - EXPECT_EQ(0, event.blackholeDetectionWindow); - EXPECT_EQ(1, event.blackholeDetectionThreshold); - EXPECT_EQ( - d6d.basePMTU + 20, event.triggeringPacketMetadata.encodedSize); - })); - detectPMTUBlackhole(conn, lostPacket); - - EXPECT_EQ(d6d.state, D6DMachineState::BASE); - EXPECT_EQ(d6d.currentProbeSize, d6d.basePMTU); - EXPECT_EQ(conn.udpSendPacketLen, d6d.basePMTU); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::SEARCH_COMPLETE); - EXPECT_GE(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F(QuicD6DStateFunctionsTest, ReachMaxPMTU) { - auto socket = std::make_shared(); - const auto observerContainer = - std::make_shared(socket.get()); - - QuicConnectionStateBase conn(QuicNodeType::Server); - conn.observerContainer = observerContainer; - - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - auto obs1 = std::make_unique>(eventSet); - observerContainer->addObserver(obs1.get()); - - auto& d6d = conn.d6d; - const auto now = Clock::now(); - d6d.state = D6DMachineState::SEARCHING; - d6d.maxPMTU = 1452; - d6d.outstandingProbes = 1; - conn.udpSendPacketLen = 1400; - d6d.currentProbeSize = 1442; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - d6d.meta.totalTxedProbes = 10; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(1452)); - onD6DLastProbeAcked(conn); - EXPECT_EQ(d6d.state, D6DMachineState::SEARCHING); - EXPECT_EQ(d6d.currentProbeSize, 1452); - EXPECT_EQ(conn.udpSendPacketLen, 1442); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_EQ(d6d.meta.timeLastNonSearchState, now); - - observerContainer->removeObserver(obs1.get()); -} - -TEST_F( - QuicD6DStateFunctionsTest, - MaintainStateWhenFalsePositiveBlackholeDetected) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto& d6d = conn.d6d; - auto now = Clock::now(); - d6d.state = D6DMachineState::SEARCHING; - d6d.maxPMTU = 1452; - d6d.outstandingProbes = 1; - conn.udpSendPacketLen = 1400; - d6d.currentProbeSize = 1442; - d6d.meta.lastNonSearchState = D6DMachineState::BASE; - d6d.meta.timeLastNonSearchState = now; - d6d.meta.totalTxedProbes = 10; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(1452)); - d6d.thresholdCounter = std::make_unique>( - std::chrono::microseconds(kDefaultD6DBlackholeDetectionWindow).count(), - 1); // Threshold of 1 will cause window to be set to 0 - - auto lostPacket = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - false, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - // Generate a false positive blackhole signal - detectPMTUBlackhole(conn, lostPacket); - EXPECT_EQ(d6d.state, D6DMachineState::BASE); - EXPECT_EQ(conn.udpSendPacketLen, d6d.basePMTU); - - // The ack of a non-stale probe should bring us back to SEARCHING state and - // correct probe size - onD6DLastProbeAcked(conn); - EXPECT_EQ(d6d.state, D6DMachineState::SEARCHING); - EXPECT_EQ(d6d.currentProbeSize, 1452); - EXPECT_EQ(conn.udpSendPacketLen, 1442); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_EQ(d6d.meta.timeLastNonSearchState, now); -} - -TEST_F(QuicD6DStateFunctionsTest, UpperboundIsBase) { - QuicConnectionStateBase conn(QuicNodeType::Server); - auto& d6d = conn.d6d; - auto now = Clock::now(); - d6d.state = D6DMachineState::BASE; - d6d.basePMTU = 1400; - d6d.maxPMTU = 1400; - d6d.outstandingProbes = 1; - conn.udpSendPacketLen = 1400; - d6d.currentProbeSize = 1400; - d6d.meta.lastNonSearchState = D6DMachineState::DISABLED; - d6d.meta.timeLastNonSearchState = now; - d6d.meta.totalTxedProbes = 10; - auto pkt = OutstandingPacket( - makeTestShortPacket(), - Clock::now(), - d6d.currentProbeSize, - 0, - false, - true, - d6d.currentProbeSize, - d6d.currentProbeSize, - 0, - LossState(), - 0, - OutstandingPacketMetadata::DetailsPerStream()); - d6d.lastProbe = D6DProbePacket( - pkt.packet.header.getPacketSequenceNum(), pkt.metadata.encodedSize); - d6d.raiser = std::make_unique(); - auto mockRaiser = dynamic_cast(d6d.raiser.get()); - EXPECT_CALL(*mockRaiser, raiseProbeSize(d6d.currentProbeSize)) - .Times(1) - .WillOnce(Return(1452)); - - // The ack of a non-stale probe should bring us back to SEARCHING state and - // correct probe size - onD6DLastProbeAcked(conn); - EXPECT_EQ(d6d.state, D6DMachineState::SEARCH_COMPLETE); - EXPECT_EQ(d6d.currentProbeSize, 1400); - EXPECT_EQ(conn.udpSendPacketLen, 1400); - EXPECT_EQ(d6d.meta.lastNonSearchState, D6DMachineState::BASE); - EXPECT_GT(d6d.meta.timeLastNonSearchState, now); -} - -} // namespace test -} // namespace quic diff --git a/quic/fizz/client/test/QuicClientTransportTest.cpp b/quic/fizz/client/test/QuicClientTransportTest.cpp index 2fe39b6b5..2c0ffe98c 100644 --- a/quic/fizz/client/test/QuicClientTransportTest.cpp +++ b/quic/fizz/client/test/QuicClientTransportTest.cpp @@ -962,25 +962,6 @@ TEST_P(QuicClientTransportIntegrationTest, TestStatelessResetToken) { EXPECT_EQ(token1.value(), token2.value()); } -TEST_P(QuicClientTransportIntegrationTest, D6DEnabledTest) { - expectTransportCallbacks(); - TransportSettings settings; - settings.d6dConfig.enabled = true; - client->setTransportSettings(settings); - - TransportSettings serverSettings; - serverSettings.d6dConfig.enabled = true; - serverSettings.statelessResetTokenSecret = getRandSecret(); - server_->setTransportSettings(serverSettings); - - // we only use 1 worker in test - client->start(&clientConnSetupCallback, &clientConnCallback); - EXPECT_EQ(1, statsCallbacks_.size()); - EXPECT_CALL(*statsCallbacks_[0], onConnectionD6DStarted()) - .WillOnce(Invoke([&] { eventbase_.terminateLoopSoon(); })); - eventbase_.loopForever(); -} - INSTANTIATE_TEST_SUITE_P( QuicClientTransportIntegrationTests, QuicClientTransportIntegrationTest, diff --git a/quic/loss/CMakeLists.txt b/quic/loss/CMakeLists.txt index 90feaf63c..8935e7494 100644 --- a/quic/loss/CMakeLists.txt +++ b/quic/loss/CMakeLists.txt @@ -29,7 +29,6 @@ add_dependencies( mvfst_state_functions mvfst_state_machine mvfst_state_simple_frame_functions - mvfst_d6d_state_functions ) target_link_libraries( @@ -42,7 +41,6 @@ target_link_libraries( mvfst_state_functions mvfst_state_machine mvfst_state_simple_frame_functions - mvfst_d6d_state_functions ) file( diff --git a/quic/loss/QuicLossFunctions.h b/quic/loss/QuicLossFunctions.h index c66d5fe32..4352a07d2 100644 --- a/quic/loss/QuicLossFunctions.h +++ b/quic/loss/QuicLossFunctions.h @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -121,22 +120,19 @@ void setLossDetectionAlarm(QuicConnectionStateBase& conn, Timeout& timeout) { bool hasDataToWrite = hasAckDataToWrite(conn) || (hasNonAckDataToWrite(conn) != WriteDataReason::NO_WRITE); auto totalPacketsOutstanding = conn.outstandings.numOutstanding(); - auto totalD6DProbesOutstanding = conn.d6d.outstandingProbes; /* * We have this condition to disambiguate the case where we have. - * (1) All outstanding packets (except for d6d probes) that are clones that - * are processed and there is no data to write. - * (2) All outstanding (except for d6d probes) are clones that are processed - * and there is data to write. - * If there are only clones with no data, then we don't need to set the timer. - * This will free up the evb. However after a PTO verified event, clones take - * up space in cwnd. If we have data left to write, we would not be able to - * write them since we could be blocked by cwnd. So we must set the loss timer - * so that we can write this data with the slack packet space for the clones. + * (1) All outstanding packets that are clones that are processed and there is + * no data to write. (2) All outstanding are clones that are processed and + * there is data to write. If there are only clones with no data, then we + * don't need to set the timer. This will free up the evb. However after a PTO + * verified event, clones take up space in cwnd. If we have data left to + * write, we would not be able to write them since we could be blocked by + * cwnd. So we must set the loss timer so that we can write this data with the + * slack packet space for the clones. */ if (!hasDataToWrite && conn.outstandings.packetEvents.empty() && - (totalPacketsOutstanding - totalD6DProbesOutstanding) == - conn.outstandings.numClonedPackets()) { + totalPacketsOutstanding == conn.outstandings.numClonedPackets()) { VLOG(10) << __func__ << " unset alarm pure ack or processed packets only" << " outstanding=" << totalPacketsOutstanding << " handshakePackets=" @@ -309,33 +305,6 @@ folly::Optional detectLossPackets( shouldSetTimer = true; break; } - if (pkt.metadata.isD6DProbe) { - // It's a D6D probe, we'll mark it as lost to avoid its stale - // ack from affecting PMTU. We don't add it to loss event to - // avoid affecting congestion control when there's probably no - // congestion - CHECK(conn.d6d.lastProbe.hasValue()); - // Check the decalredLost field first, to avoid double counting - // the lost probe since we don't erase them from op list yet - if (!pkt.declaredLost) { - ++conn.outstandings.declaredLostCount; - pkt.declaredLost = true; - if (lostByTimeout && rttSample.count() > 0) { - pkt.lossTimeoutDividend = (lossTime - pkt.metadata.time) * - conn.transportSettings.timeReorderingThreshDivisor / rttSample; - } - if (lostByReorder) { - pkt.lossReorderDistance = reorderDistance; - } - ++conn.d6d.meta.totalLostProbes; - if (currentPacketNum == conn.d6d.lastProbe->packetNum) { - onD6DLastProbeLost(conn); - } - } - iter++; - continue; - } - detectPMTUBlackhole(conn, pkt); lossEvent.addLostPacket(pkt); if (observerLossEvent) { observerLossEvent->addLostPacket(lostByTimeout, lostByReorder, pkt); diff --git a/quic/loss/test/QuicLossFunctionsTest.cpp b/quic/loss/test/QuicLossFunctionsTest.cpp index e140fb4f4..5b255e9bc 100644 --- a/quic/loss/test/QuicLossFunctionsTest.cpp +++ b/quic/loss/test/QuicLossFunctionsTest.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -76,8 +75,6 @@ enum class PacketType { OneRtt, }; -struct PMTUBlackholeDetectionTestFixture; // Forward declaration - class QuicLossFunctionsTest : public TestWithParam { public: void SetUp() override { @@ -95,7 +92,6 @@ class QuicLossFunctionsTest : public TestWithParam { TimePoint time, folly::Optional associatedEvent, PacketType packetType, - bool isD6DProbe = false, folly::Optional forcedSize = folly::none); std::unique_ptr createConn() { @@ -154,10 +150,6 @@ class QuicLossFunctionsTest : public TestWithParam { return conn; } - void runDetectPMTUBlackholeTest( - QuicConnectionStateBase* conn, - PMTUBlackholeDetectionTestFixture fixture); - EventBase evb; std::unique_ptr aead; std::unique_ptr headerCipher; @@ -190,7 +182,6 @@ PacketNum QuicLossFunctionsTest::sendPacket( TimePoint time, folly::Optional associatedEvent, PacketType packetType, - bool isD6DProbe, folly::Optional forcedSize) { folly::Optional header; bool isHandshake = false; @@ -263,7 +254,6 @@ PacketNum QuicLossFunctionsTest::sendPacket( encodedSize, encodedBodySize, isHandshake, - isD6DProbe, encodedSize, encodedBodySize, 0, @@ -302,11 +292,6 @@ PacketNum QuicLossFunctionsTest::sendPacket( conn.lossState.largestSent = getNextPacketNum(conn, packetNumberSpace); increaseNextPacketNum(conn, packetNumberSpace); conn.pendingEvents.setLossDetectionAlarm = true; - if (isD6DProbe) { - ++conn.d6d.outstandingProbes; - conn.d6d.lastProbe = - D6DProbePacket(encodedSize, conn.lossState.largestSent.value()); - } return conn.lossState.largestSent.value(); } @@ -353,257 +338,6 @@ TEST_F(QuicLossFunctionsTest, HasDataToWrite) { EXPECT_FALSE(conn->pendingEvents.setLossDetectionAlarm); } -TEST_F(QuicLossFunctionsTest, D6DProbeDoesNotSetLossDetectionAlarms) { - auto conn = createConn(); - sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt, true); - conn->pendingEvents.setLossDetectionAlarm = true; - EXPECT_CALL(timeout, cancelLossTimeout()).Times(1); - EXPECT_CALL(timeout, scheduleLossTimeout(_)).Times(0); - setLossDetectionAlarm(*conn, timeout); - EXPECT_FALSE(conn->pendingEvents.setLossDetectionAlarm); -} - -TEST_F(QuicLossFunctionsTest, D6DProbeExcludedInLossEvent) { - auto conn = createConn(); - // 0 rtt means all packets are automatically lost upon sending - conn->lossState.srtt = 0s; - conn->lossState.lrtt = 0s; - auto currentTime = Clock::now(); - auto firstPacketNum = - sendPacket(*conn, currentTime, folly::none, PacketType::OneRtt, true); - auto secondPacketNum = - sendPacket(*conn, currentTime, folly::none, PacketType::OneRtt, true); - ASSERT_GT(secondPacketNum, firstPacketNum); - ASSERT_EQ(2, conn->outstandings.packets.size()); - auto lossVisitor = [](auto&, auto&, bool) { ASSERT_FALSE(true); }; - auto lossEvent = detectLossPackets( - *conn, - secondPacketNum, - lossVisitor, - Clock::now(), - PacketNumberSpace::AppData); - // We should not set loss timer for un-acked d6d probes - ASSERT_FALSE(earliestLossTimer(*conn).first.has_value()); - ASSERT_FALSE(lossEvent); -} - -TEST_F(QuicLossFunctionsTest, NonExclusiveD6DProbeLossIncludedInLossEvent) { - auto conn = createConn(); - // 0 rtt means all packets are automatically lost upon sending - conn->lossState.srtt = 0s; - conn->lossState.lrtt = 0s; - conn->d6d.raiser = std::make_unique(); - auto currentTime = Clock::now(); - auto firstPacketNum = - sendPacket(*conn, currentTime, folly::none, PacketType::OneRtt, true); - auto secondPacketNum = - sendPacket(*conn, currentTime, folly::none, PacketType::OneRtt, false); - ASSERT_GT(secondPacketNum, firstPacketNum); - ASSERT_EQ(2, conn->outstandings.packets.size()); - auto lossVisitor = [&](auto&, auto& packet, bool) { - EXPECT_EQ(packet.header.getPacketSequenceNum(), secondPacketNum); - }; - auto lossEvent = detectLossPackets( - *conn, - secondPacketNum + 1, - lossVisitor, - Clock::now(), - PacketNumberSpace::AppData); - // We should not set loss timer for un-acked d6d probes - ASSERT_TRUE(lossEvent.hasValue()); - ASSERT_FALSE(earliestLossTimer(*conn).first.has_value()); - ASSERT_EQ(lossEvent->lostPackets, 1); -} - -struct PMTUBlackholeDetectionTestFixture { - uint32_t beginPMTU; - uint32_t endPMTU; - size_t threshold; - bool hasLossEvent; - uint64_t lostBytes; - uint32_t lostPackets; - std::chrono::seconds window; - PacketNum largestAckedPacketNum; - std::chrono::microseconds detectLossTimeDelta; - std::chrono::microseconds largestLostTimeDelta; - std::chrono::microseconds smallestLostTimeDelta; - D6DMachineState beginState; - D6DMachineState endState; - - struct PacketSpec { - std::chrono::microseconds timeDelta; - bool isD6DProbe; - uint32_t encodedSize; - }; - std::vector packetSpecs; -}; - -void QuicLossFunctionsTest::runDetectPMTUBlackholeTest( - QuicConnectionStateBase* conn, - PMTUBlackholeDetectionTestFixture fixture) { - // 0 rtt means all packets are automatically lost upon sending - conn->lossState.srtt = 0s; - conn->lossState.lrtt = 0s; - conn->d6d.state = D6DMachineState::BASE; - conn->d6d.currentProbeSize = fixture.beginPMTU; - conn->udpSendPacketLen = fixture.beginPMTU; - conn->d6d.thresholdCounter = - std::make_unique>( - std::chrono::microseconds(fixture.window).count(), fixture.threshold); - conn->d6d.raiser = std::make_unique(); - conn->d6d.state = fixture.beginState; - auto currentTime = Clock::now(); - for (auto& spec : fixture.packetSpecs) { - sendPacket( - *conn, - currentTime + spec.timeDelta, - folly::none, - PacketType::OneRtt, - spec.isD6DProbe, - spec.encodedSize); - } - auto lossVisitor = [](auto&, auto&, bool) {}; - ASSERT_EQ(conn->outstandings.packets.size(), fixture.packetSpecs.size()); - auto lossEvent = detectLossPackets( - *conn, - fixture.largestAckedPacketNum, - lossVisitor, - currentTime + fixture.detectLossTimeDelta, - PacketNumberSpace::AppData); - EXPECT_EQ(lossEvent.has_value(), fixture.hasLossEvent); - if (fixture.hasLossEvent) { - EXPECT_EQ(lossEvent->lostPackets, fixture.lostPackets); - EXPECT_EQ(lossEvent->lostBytes, fixture.lostBytes); - EXPECT_EQ( - lossEvent->largestLostSentTime.value(), - currentTime + fixture.largestLostTimeDelta); - EXPECT_EQ( - lossEvent->smallestLostSentTime.value(), - currentTime + fixture.smallestLostTimeDelta); - EXPECT_EQ(conn->d6d.state, fixture.endState); - EXPECT_EQ(conn->d6d.currentProbeSize, fixture.endPMTU); - EXPECT_EQ(conn->udpSendPacketLen, fixture.endPMTU); - } -} - -TEST_F(QuicLossFunctionsTest, DetectPMTUBlackholeAllNonProbes) { - // clang-format off - PMTUBlackholeDetectionTestFixture fixture { - 1400, // beginPMTU - kDefaultUDPSendPacketLen, // endPMTU - 3, // threshold - true, // hasLossEvent - 1400 * 3, // lostBytes - 3, // lostPackets - 10s, // window - 3 + kReorderingThreshold, // largestAckedPacketNum - 11s, // detectLossTimeDelta - 10s, // largestLostTimeDelta - 0s, // smallestLostTimeDelta - D6DMachineState::SEARCH_COMPLETE, // beginState - D6DMachineState::BASE, // beginState - { // packetSpecs - {0s, false, 1400}, - {1s, false, 1400}, - {10s, false, 1400}, - } - }; - // clang-format on - auto conn = createConn(); - runDetectPMTUBlackholeTest(conn.get(), fixture); -} - -TEST_F(QuicLossFunctionsTest, DetectPMTUBlackholeAllProbes) { - // clang-format off - PMTUBlackholeDetectionTestFixture fixture { - 1400, // beginPMTU - 1400, // endPMTU - 3, // threshold - false, // hasLossEvent - 0, // lostBytes - 0, // lostPackets - 10s, // window - 3 + kReorderingThreshold, // largestAckedPacketNum - 11s, // detectLossTimeDelta - 10s, // largestLostTimeDelta - 0s, // smallestLostTimeDelta - D6DMachineState::SEARCH_COMPLETE, // beginState - D6DMachineState::SEARCH_COMPLETE, // beginState - { // packetSpecs - {0s, true, 1400}, - {1s, true, 1400}, - {10s, true, 1400}, - } - }; - // clang-format on - auto conn = createConn(); - runDetectPMTUBlackholeTest(conn.get(), fixture); -} - -TEST_F(QuicLossFunctionsTest, DetectPMTUBlackholeSparseProbes) { - // clang-format off - PMTUBlackholeDetectionTestFixture fixture { - 1400, // beginPMTU - 1400, // endPMTU - 3, // threshold - true, // hasLossEvent - 1400 * 5 + 200, // lostBytes - 6, // lostPackets - 10s, // window - 6 + kReorderingThreshold, // largestAckedPacketNum - 23s, // detectLossTimeDelta - 22s, // largestLostTimeDelta - 0s, // smallestLostTimeDelta - D6DMachineState::SEARCH_COMPLETE, // beginState - D6DMachineState::SEARCH_COMPLETE, // beginState - { // packetSpecs - {0s, false, 1400}, - {1s, false, 1400}, - {11s, false, 1400}, - {10s, false, 200}, - {12s, false, 1400}, - {22s, false, 1400} - } - }; - // clang-format on - auto conn = createConn(); - runDetectPMTUBlackholeTest(conn.get(), fixture); -} - -TEST_F(QuicLossFunctionsTest, DetectPMTUBlackholeRandomData) { - // clang-format off - PMTUBlackholeDetectionTestFixture fixture { - 1400, // beginPMTU - 1400, // endPMTU - 3, // threshold - true, // hasLossEvent - 876 + 249 + 1291 + 1400 * 4 + 1109, // lostBytes - 8, // lostPackets - 10s, // window - 9 + kReorderingThreshold, // largestAckedPacketNum - 90s, // detectLossTimeDelta - 83s, // largestLostTimeDelta - 5s, // smallestLostTimeDelta - D6DMachineState::SEARCHING, // beginState - D6DMachineState::SEARCHING, // beginState - { // packetSpecs - { 5s, false, 876 }, - { 15s, false, 249 }, - { 19s, false, 1291 }, - { 31s, false, 1400 }, - { 40s, true, 1400 }, - { 51s, false, 1400 }, - { 61s, false, 1400 }, - { 73s, false, 1400 }, - { 83s, false, 1109 }, - { 85s, true, 1400 } - } - }; - // clang-format on - auto conn = createConn(); - runDetectPMTUBlackholeTest(conn.get(), fixture); -} - TEST_F(QuicLossFunctionsTest, ClearEarlyRetranTimer) { auto conn = createConn(); // make delayUntilLoss relatively large @@ -2058,7 +1792,6 @@ TEST_F(QuicLossFunctionsTest, PersistentCongestionAckOutsideWindow) { 0 /* encodedSize */, 0 /* encodedBodySize */, false /* isHandshake */, - false /* isD6DProbe */, 0 /* totalBytesSent */, 0 /* totalBodyBytesSent */, 0 /* inflightBytes */, @@ -2094,7 +1827,6 @@ TEST_F(QuicLossFunctionsTest, PersistentCongestionAckInsideWindow) { 0 /* encodedSize */, 0 /* encodedBodySize */, false /* isHandshake */, - false /* isD6DProbe */, 0 /* totalBytesSent */, 0 /* totalBodyBytesSent */, 0 /* inflightBytes */, @@ -2129,7 +1861,6 @@ TEST_F(QuicLossFunctionsTest, PersistentCongestionNoPTO) { 0 /* encodedSize */, 0 /* encodedBodySize */, false /* isHandshake */, - false /* isD6DProbe */, 0 /* totalBytesSent */, 0 /* totalBodyBytesSent */, 0 /* inflightBytes */, diff --git a/quic/observer/SocketObserverInterface.h b/quic/observer/SocketObserverInterface.h index 69e6b96bf..01c5237ec 100644 --- a/quic/observer/SocketObserverInterface.h +++ b/quic/observer/SocketObserverInterface.h @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -36,7 +35,6 @@ class SocketObserverInterface { rttSamples = 4, lossEvents = 5, spuriousLossEvents = 6, - pmtuEvents = 7, knobFrameEvents = 8, streamEvents = 9, acksProcessedEvents = 10, @@ -358,62 +356,6 @@ class SocketObserverInterface { lastAckedPacketInfo; }; - struct PMTUBlackholeEvent { - explicit PMTUBlackholeEvent( - TimePoint blackholeTimeIn, - std::chrono::microseconds timeSinceLastNonSearchStateIn, - D6DMachineState lastNonSearchStateIn, - D6DMachineState currentStateIn, - uint64_t udpSendPacketLenIn, - uint64_t lastProbeSizeIn, - uint64_t blackholeDetectionWindowIn, - uint64_t blackholeDetectionThresholdIn, - const quic::OutstandingPacket& pkt) - : blackholeTime(blackholeTimeIn), - timeSinceLastNonSearchState(timeSinceLastNonSearchStateIn), - lastNonSearchState(lastNonSearchStateIn), - currentState(currentStateIn), - udpSendPacketLen(udpSendPacketLenIn), - lastProbeSize(lastProbeSizeIn), - blackholeDetectionWindow(blackholeDetectionWindowIn), - blackholeDetectionThreshold(blackholeDetectionThresholdIn), - triggeringPacketMetadata(pkt.metadata) {} - TimePoint blackholeTime; - // How long since last "stable" state - std::chrono::microseconds timeSinceLastNonSearchState; - D6DMachineState lastNonSearchState; - D6DMachineState currentState; - uint64_t udpSendPacketLen; - uint64_t lastProbeSize; - uint64_t blackholeDetectionWindow; - uint64_t blackholeDetectionThreshold; - // The metadata of the packet that triggerred blackhole signal - const quic::OutstandingPacketMetadata triggeringPacketMetadata; - }; - - struct PMTUUpperBoundEvent { - explicit PMTUUpperBoundEvent( - TimePoint upperBoundTimeIn, - std::chrono::microseconds timeSinceLastNonSearchStateIn, - D6DMachineState lastNonSearchStateIn, - uint64_t upperBoundPMTUIn, - uint64_t cumulativeProbesSentIn, - ProbeSizeRaiserType probeSizeRaiserTypeIn) - : upperBoundTime(upperBoundTimeIn), - timeSinceLastNonSearchState(timeSinceLastNonSearchStateIn), - lastNonSearchState(lastNonSearchStateIn), - upperBoundPMTU(upperBoundPMTUIn), - cumulativeProbesSent(cumulativeProbesSentIn), - probeSizeRaiserType(probeSizeRaiserTypeIn) {} - TimePoint upperBoundTime; - // How long it took to reach upperbound - std::chrono::microseconds timeSinceLastNonSearchState; - D6DMachineState lastNonSearchState; - uint64_t upperBoundPMTU; - uint64_t cumulativeProbesSent; - ProbeSizeRaiserType probeSizeRaiserType; - }; - struct SpuriousLossEvent { explicit SpuriousLossEvent(const TimePoint rcvTimeIn = Clock::now()) : rcvTime(rcvTimeIn) {} @@ -583,31 +525,6 @@ class SocketObserverInterface { QuicSocket*, /* socket */ const PacketRTT& /* event */) {} - /** - * pmtuProbingStarted() is invoked when server starts d6d. - * - * @param socket Socket when the callback is processed. - */ - virtual void pmtuProbingStarted(QuicSocket* /* socket */) {} - - /** - * pmtuBlackholeDetected() is invoked when a PMTU blackhole is detected. - * - * @param pmtuBlackholeEvent const reference to the PMTU blackhole event - */ - virtual void pmtuBlackholeDetected( - QuicSocket*, /* socket */ - const PMTUBlackholeEvent& /* event */) {} - - /** - * pmtuUpperBoundDetected() is invoked when a PMTU upperbound is detected. - * - * @param pmtuUpperBoundEvent const reference to the PMTU upperbound event - */ - virtual void pmtuUpperBoundDetected( - QuicSocket*, /* socket */ - const PMTUUpperBoundEvent& /* event */) {} - /** * spuriousLossDetected() is invoked when an ACK arrives for a packet that is * declared lost diff --git a/quic/observer/test/SocketObserverInterfaceTest.cpp b/quic/observer/test/SocketObserverInterfaceTest.cpp index 36aab9327..26c9d1aab 100644 --- a/quic/observer/test/SocketObserverInterfaceTest.cpp +++ b/quic/observer/test/SocketObserverInterfaceTest.cpp @@ -55,7 +55,6 @@ class SocketObserverInterfaceTest : public ::testing::Test { .setEncodedSize(0) .setEncodedBodySize(0) .setIsHandshake(false) - .setIsD6DProbe(false) .setTotalBytesSent(0) .setTotalBodyBytesSent(0) .setInflightBytes(0) diff --git a/quic/samples/echo/LogQuicStats.h b/quic/samples/echo/LogQuicStats.h index 2bbd670d5..b7e991699 100644 --- a/quic/samples/echo/LogQuicStats.h +++ b/quic/samples/echo/LogQuicStats.h @@ -181,22 +181,6 @@ class LogQuicStats : public quic::QuicTransportStatsCallback { VLOG(2) << prefix_ << __func__ << " errorType=" << toString(errorType); } - void onConnectionD6DStarted() override { - VLOG(2) << prefix_ << __func__; - } - - void onConnectionPMTURaised() override { - VLOG(2) << prefix_ << __func__; - } - - void onConnectionPMTUBlackholeDetected() override { - VLOG(2) << prefix_ << __func__; - } - - void onConnectionPMTUUpperBoundDetected() override { - VLOG(2) << prefix_ << __func__; - } - void onTransportKnobApplied(TransportKnobParamId knobType) override { VLOG(2) << prefix_ << __func__ << " knobType=" << knobType._to_string(); } diff --git a/quic/server/QuicServerTransport.cpp b/quic/server/QuicServerTransport.cpp index 3e2b022e6..a7f75c9ea 100644 --- a/quic/server/QuicServerTransport.cpp +++ b/quic/server/QuicServerTransport.cpp @@ -7,8 +7,6 @@ #include #include -#include -#include #include #include #include @@ -187,7 +185,6 @@ void QuicServerTransport::onReadData( maybeNotifyHandshakeFinished(); maybeNotifyConnectionIdRetired(); maybeIssueConnectionIds(); - maybeStartD6DProbing(); maybeNotifyTransportReady(); } @@ -350,18 +347,6 @@ void QuicServerTransport::writeData() { *conn_->oneRttWriteCipher, writeLoopBeginTime); } - - // D6D probes should be paced - if (packetLimit && conn_->pendingEvents.d6d.sendProbePacket) { - writeD6DProbeToSocket( - *socket_, - *conn_, - srcConnId, - destConnId, - *conn_->oneRttWriteCipher, - *conn_->oneRttWriteHeaderCipher, - version); - } } } @@ -630,45 +615,6 @@ void QuicServerTransport::maybeNotifyTransportReady() { } } -void QuicServerTransport::maybeStartD6DProbing() { - if (!d6dProbingStarted_ && hasReadCipher() && - conn_->d6d.state == D6DMachineState::BASE) { - d6dProbingStarted_ = true; - auto& d6d = conn_->d6d; - switch (conn_->transportSettings.d6dConfig.raiserType) { - case ProbeSizeRaiserType::ConstantStep: - d6d.raiser = std::make_unique( - conn_->transportSettings.d6dConfig.probeRaiserConstantStepSize); - break; - case ProbeSizeRaiserType::BinarySearch: - d6d.raiser = std::make_unique( - kMinMaxUDPPayload, d6d.maxPMTU); - } - d6d.thresholdCounter = - std::make_unique>( - std::chrono::microseconds(kDefaultD6DBlackholeDetectionWindow) - .count(), - kDefaultD6DBlackholeDetectionThreshold); - d6d.currentProbeSize = d6d.basePMTU; - // Start probing after some delay. This filters out short-lived - // connections, for which probing is relatively expensive and less - // valuable - conn_->pendingEvents.d6d.sendProbeDelay = kDefaultD6DKickStartDelay; - QUIC_STATS(conn_->statsCallback, onConnectionD6DStarted); - - if (getSocketObserverContainer() && - getSocketObserverContainer() - ->hasObserversForEvent< - SocketObserverInterface::Events::pmtuEvents>()) { - getSocketObserverContainer() - ->invokeInterfaceMethod( - [](auto observer, auto observed) { - observer->pmtuProbingStarted(observed); - }); - } - } -} - void QuicServerTransport::registerTransportKnobParamHandler( uint64_t paramId, std::function&& @@ -721,21 +667,6 @@ void QuicServerTransport::verifiedClientAddress() { } void QuicServerTransport::registerAllTransportKnobParamHandlers() { - registerTransportKnobParamHandler( - static_cast( - TransportKnobParamId::ZERO_PMTU_BLACKHOLE_DETECTION), - [](QuicServerTransport* serverTransport, TransportKnobParam::Val val) { - CHECK(serverTransport); - auto server_conn = serverTransport->serverConn_; - // TODO(dvn) TransportKnobParam::Val can probably hold bool value as - // well - if (static_cast(std::get(val))) { - server_conn->d6d.noBlackholeDetection = true; - VLOG(3) - << "Knob param received, pmtu blackhole detection is turned off"; - } - }); - registerTransportKnobParamHandler( static_cast( TransportKnobParamId::FORCIBLY_SET_UDP_PAYLOAD_SIZE), diff --git a/quic/server/QuicServerTransport.h b/quic/server/QuicServerTransport.h index 0c82e8250..0d7291f35 100644 --- a/quic/server/QuicServerTransport.h +++ b/quic/server/QuicServerTransport.h @@ -193,7 +193,6 @@ class QuicServerTransport void maybeIssueConnectionIds(); void maybeNotifyHandshakeFinished(); bool hasReadCipher() const; - void maybeStartD6DProbing(); void registerAllTransportKnobParamHandlers(); private: diff --git a/quic/server/state/ServerStateMachine.cpp b/quic/server/state/ServerStateMachine.cpp index 55616820b..829fd9297 100644 --- a/quic/server/state/ServerStateMachine.cpp +++ b/quic/server/state/ServerStateMachine.cpp @@ -206,15 +206,6 @@ void processClientInitialParams( auto activeConnectionIdLimit = getIntegerParameter( TransportParameterId::active_connection_id_limit, clientParams.parameters); - auto d6dBasePMTU = getIntegerParameter( - static_cast(kD6DBasePMTUParameterId), - clientParams.parameters); - auto d6dRaiseTimeout = getIntegerParameter( - static_cast(kD6DRaiseTimeoutParameterId), - clientParams.parameters); - auto d6dProbeTimeout = getIntegerParameter( - static_cast(kD6DProbeTimeoutParameterId), - clientParams.parameters); auto minAckDelay = getIntegerParameter( TransportParameterId::min_ack_delay, clientParams.parameters); auto maxAckDelay = getIntegerParameter( @@ -359,55 +350,6 @@ void processClientInitialParams( conn.peerActiveConnectionIdLimit = activeConnectionIdLimit.value_or(kDefaultActiveConnectionIdLimit); - if (conn.transportSettings.d6dConfig.enabled) { - // Sanity check - if (d6dBasePMTU) { - if (*d6dBasePMTU >= kMinMaxUDPPayload && - *d6dBasePMTU <= kDefaultMaxUDPPayload) { - // The reason to take the max is because we don't want d6d to send - // probes with a smaller packet size than udpSendPacketLen, which would - // be useless and cause meaningless delay on finding the upper bound. - conn.d6d.basePMTU = std::max(*d6dBasePMTU, conn.udpSendPacketLen); - conn.d6d.maxPMTU = maxUdpPayloadSize; - VLOG(10) << "conn.d6d.basePMTU=" << conn.d6d.basePMTU; - - // Start from base - conn.d6d.state = D6DMachineState::BASE; - conn.d6d.meta.lastNonSearchState = D6DMachineState::DISABLED; - conn.d6d.meta.timeLastNonSearchState = Clock::now(); - - // Temporary, should be removed after transport knob pipeline works - conn.d6d.noBlackholeDetection = true; - } else { - LOG(ERROR) << "client d6dBasePMTU fails sanity check: " << *d6dBasePMTU; - // We treat base pmtu transport param as client's swich to activate d6d, - // so not receiving that means there's no need to configure the rest d6d - // params - return; - } - } - - if (d6dRaiseTimeout) { - if (*d6dRaiseTimeout >= kMinD6DRaiseTimeout.count()) { - conn.d6d.raiseTimeout = std::chrono::seconds(*d6dRaiseTimeout); - VLOG(10) << "conn.d6d.raiseTimeout=" << conn.d6d.raiseTimeout.count(); - } else { - LOG(ERROR) << "client d6dRaiseTimeout fails sanity check: " - << *d6dRaiseTimeout; - } - } - - if (d6dProbeTimeout) { - if (*d6dProbeTimeout >= kMinD6DProbeTimeout.count()) { - conn.d6d.probeTimeout = std::chrono::seconds(*d6dProbeTimeout); - VLOG(10) << "conn.d6d.probeTimeout=" << conn.d6d.probeTimeout.count(); - } else { - LOG(ERROR) << "client d6dProbeTimeout fails sanity check: " - << *d6dProbeTimeout; - } - } - } - if (peerAdvertisedMaxStreamGroups) { conn.peerAdvertisedMaxStreamGroups = *peerAdvertisedMaxStreamGroups; } @@ -1086,7 +1028,7 @@ void onServerReadDataFromOpen( conn, packetNumberSpace, ackFrame, - [&](const OutstandingPacket& packet, + [&](const OutstandingPacket&, const QuicWriteFrame& packetFrame, const ReadAckFrame&) { switch (packetFrame.type()) { @@ -1133,9 +1075,7 @@ void onServerReadDataFromOpen( break; } case QuicWriteFrame::Type::PingFrame: - if (!packet.metadata.isD6DProbe) { - conn.pendingEvents.cancelPingTimeout = true; - } + conn.pendingEvents.cancelPingTimeout = true; return; case QuicWriteFrame::Type::QuicSimpleFrame: { const QuicSimpleFrame& frame = diff --git a/quic/server/test/QuicServerTransportTest.cpp b/quic/server/test/QuicServerTransportTest.cpp index 26f84e610..dfe81f1b9 100644 --- a/quic/server/test/QuicServerTransportTest.cpp +++ b/quic/server/test/QuicServerTransportTest.cpp @@ -4657,34 +4657,6 @@ TEST_P( testSetupConnection(); } -TEST_P(QuicServerTransportHandshakeTest, TestD6DStartCallback) { - LegacyObserver::EventSet eventSet; - eventSet.enable(SocketObserverInterface::Events::pmtuEvents); - - auto obs1 = std::make_unique(); - auto obs2 = std::make_unique(eventSet); - auto obs3 = std::make_unique(eventSet); - server->addObserver(obs1.get()); - server->addObserver(obs2.get()); - server->addObserver(obs3.get()); - - // Set oneRttReader so that maybeStartD6DPriobing passes its check - auto codec = std::make_unique(QuicNodeType::Server); - codec->setOneRttReadCipher(createNoOpAead()); - server->getNonConstConn().readCodec = std::move(codec); - // And the state too - server->getNonConstConn().d6d.state = D6DMachineState::BASE; - EXPECT_CALL(*obs1, pmtuProbingStarted(_)).Times(0); // not enabled - EXPECT_CALL(*obs2, pmtuProbingStarted(_)).Times(1); - EXPECT_CALL(*obs3, pmtuProbingStarted(_)).Times(1); - // CHLO should be enough to trigger probing - recvClientHello(); - - server->removeObserver(obs1.get()); - server->removeObserver(obs2.get()); - server->removeObserver(obs3.get()); -} - TEST_F(QuicUnencryptedServerTransportTest, DuplicateOneRttWriteCipher) { setupClientReadCodec(); recvClientHello(); @@ -4751,14 +4723,6 @@ TEST_F( server->handleKnobParams({{knobParamId, uint64_t{1234}}}); } -TEST_F(QuicServerTransportTest, TestRegisterPMTUZeroBlackholeDetection) { - server->handleKnobParams( - {{static_cast( - TransportKnobParamId::ZERO_PMTU_BLACKHOLE_DETECTION), - uint64_t{1}}}); - EXPECT_TRUE(server->getConn().d6d.noBlackholeDetection); -} - TEST_F(QuicServerTransportTest, TestCCExperimentalKnobHandler) { auto mockCongestionController = std::make_unique>(); diff --git a/quic/server/test/ServerStateMachineTest.cpp b/quic/server/test/ServerStateMachineTest.cpp index 3ddf48c4f..9486c1ace 100644 --- a/quic/server/test/ServerStateMachineTest.cpp +++ b/quic/server/test/ServerStateMachineTest.cpp @@ -278,89 +278,6 @@ TEST(ServerStateMachineTest, TestEncodeKnobFrameSupportedParamDisabled) { testing::Eq(TransportParameterId::knob_frames_supported))))); } -struct MaxPacketSizeTestUnit { - uint64_t maxPacketSize; - bool canIgnorePathMTU; - folly::Optional d6dBasePMTU; - uint64_t expectUdpSendPacketLen; - uint64_t expectD6DBasePMTU; -}; - -void runMaxPacketSizeTestWithFixture( - const std::vector& fixture) { - for (size_t i = 0; i < fixture.size(); i++) { - const auto& unit = fixture[i]; - QuicServerConnectionState serverConn( - FizzServerQuicHandshakeContext::Builder().build()); - std::vector transportParams; - transportParams.push_back(encodeIntegerParameter( - TransportParameterId::max_packet_size, unit.maxPacketSize)); - if (unit.d6dBasePMTU) { - transportParams.push_back(encodeIntegerParameter( - static_cast(kD6DBasePMTUParameterId), - *unit.d6dBasePMTU)); - serverConn.transportSettings.d6dConfig.enabled = true; - } - ClientTransportParameters clientTransportParams = { - std::move(transportParams)}; - - serverConn.transportSettings.canIgnorePathMTU = unit.canIgnorePathMTU; - processClientInitialParams(serverConn, clientTransportParams); - - EXPECT_EQ(serverConn.udpSendPacketLen, unit.expectUdpSendPacketLen) - << "Test unit " << i; - EXPECT_EQ(serverConn.d6d.maxPMTU, unit.expectD6DBasePMTU) - << "Test unit " << i; - } -} - -TEST(ServerStateMachineTest, TestProcessMaxRecvPacketSizeParams) { - std::vector fixture = { - {kDefaultMaxUDPPayload + 1, - false, - folly::none, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload}, - {kDefaultMaxUDPPayload - 10, - false, - folly::none, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload}, - {kDefaultMaxUDPPayload + 1, - true, - folly::none, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload}, - {kDefaultMaxUDPPayload - 10, - true, - folly::none, - kDefaultMaxUDPPayload - 10, - kDefaultMaxUDPPayload}, - {kDefaultMaxUDPPayload + 1, - false, - kDefaultUDPSendPacketLen, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload}, - {kDefaultMaxUDPPayload - 10, - false, - kDefaultUDPSendPacketLen, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload - 10}, - {kDefaultMaxUDPPayload + 1, - true, - kDefaultUDPSendPacketLen, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload}, - {kDefaultMaxUDPPayload - 10, - true, - kDefaultUDPSendPacketLen, - kDefaultMaxUDPPayload - 10, - kDefaultMaxUDPPayload - 10}, - }; - - runMaxPacketSizeTestWithFixture(fixture); -} - struct advertisedMaxStreamGroupstestStruct { uint64_t peerMaxGroupsIn; folly::Optional expectedTransportSettingVal; diff --git a/quic/state/AckHandlers.cpp b/quic/state/AckHandlers.cpp index af0079416..917399c0a 100644 --- a/quic/state/AckHandlers.cpp +++ b/quic/state/AckHandlers.cpp @@ -255,17 +255,6 @@ AckEvent processAckFrame( } // if (rttSample != rttSample.zero()) } // if (!ack.implicit && currentPacketNum == frame.largestAcked) - // D6D probe acked. Only if it's for the last probe do we - // trigger state change - if (rPacketIt->metadata.isD6DProbe) { - CHECK(conn.d6d.lastProbe); - if (!rPacketIt->declaredLost) { - ++conn.d6d.meta.totalAckedProbes; - if (currentPacketNum == conn.d6d.lastProbe->packetNum) { - onD6DLastProbeAcked(conn); - } - } - } // Remove this PacketEvent from the outstandings.packetEvents set if (rPacketIt->associatedEvent) { conn.outstandings.packetEvents.erase(*rPacketIt->associatedEvent); diff --git a/quic/state/CMakeLists.txt b/quic/state/CMakeLists.txt index 37dce8668..34e6daac1 100644 --- a/quic/state/CMakeLists.txt +++ b/quic/state/CMakeLists.txt @@ -35,8 +35,6 @@ add_dependencies( mvfst_codec_types mvfst_dsr_sender mvfst_handshake - mvfst_d6d_types - mvfst_d6d_probe_raiser ) target_link_libraries( @@ -49,8 +47,6 @@ target_link_libraries( mvfst_codec_types mvfst_dsr_sender mvfst_handshake - mvfst_d6d_types - mvfst_d6d_probe_raiser ) add_library( diff --git a/quic/state/OutstandingPacket.h b/quic/state/OutstandingPacket.h index 70fbc9f8f..f0bed874c 100644 --- a/quic/state/OutstandingPacket.h +++ b/quic/state/OutstandingPacket.h @@ -23,8 +23,6 @@ struct OutstandingPacketMetadata { uint32_t encodedBodySize; // Whether this packet has any data from stream 0 bool isHandshake; - // Whether the packet is a d6d probe - bool isD6DProbe; // Total sent bytes on this connection including this packet itself when this // packet is sent. uint64_t totalBytesSent; @@ -114,7 +112,6 @@ struct OutstandingPacketMetadata { uint32_t encodedSizeIn, uint32_t encodedBodySizeIn, bool isHandshakeIn, - bool isD6DProbeIn, uint64_t totalBytesSentIn, uint64_t totalBodyBytesSentIn, uint64_t inflightBytesIn, @@ -127,7 +124,6 @@ struct OutstandingPacketMetadata { encodedSize(encodedSizeIn), encodedBodySize(encodedBodySizeIn), isHandshake(isHandshakeIn), - isD6DProbe(isD6DProbeIn), totalBytesSent(totalBytesSentIn), totalBodyBytesSent(totalBodyBytesSentIn), inflightBytes(inflightBytesIn), @@ -221,38 +217,6 @@ struct OutstandingPacket { encodedSizeIn, encodedBodySizeIn, isHandshakeIn, - false /* isD6DProbeIn */, - totalBytesSentIn, - totalBodyBytesSentIn, - inflightBytesIn, - packetsInflightIn, - lossStateIn, - writeCount, - std::move(detailsPerStream), - totalAppLimitedTimeUsecs)) {} - - OutstandingPacket( - RegularQuicWritePacket packetIn, - TimePoint timeIn, - uint32_t encodedSizeIn, - uint32_t encodedBodySizeIn, - bool isHandshakeIn, - bool isD6DProbeIn, - uint64_t totalBytesSentIn, - uint64_t totalBodyBytesSentIn, - uint64_t inflightBytesIn, - uint64_t packetsInflightIn, - const LossState& lossStateIn, - uint64_t writeCount, - Metadata::DetailsPerStream detailsPerStream, - std::chrono::microseconds totalAppLimitedTimeUsecs = 0us) - : packet(std::move(packetIn)), - metadata(OutstandingPacketMetadata( - timeIn, - encodedSizeIn, - encodedBodySizeIn, - isHandshakeIn, - isD6DProbeIn, totalBytesSentIn, totalBodyBytesSentIn, inflightBytesIn, diff --git a/quic/state/QuicTransportStatsCallback.h b/quic/state/QuicTransportStatsCallback.h index c7b4b7a8f..ff344c683 100644 --- a/quic/state/QuicTransportStatsCallback.h +++ b/quic/state/QuicTransportStatsCallback.h @@ -122,14 +122,6 @@ class QuicTransportStatsCallback { virtual void onUDPSocketWriteError(SocketErrorType errorType) = 0; - virtual void onConnectionD6DStarted() = 0; - - virtual void onConnectionPMTURaised() = 0; - - virtual void onConnectionPMTUBlackholeDetected() = 0; - - virtual void onConnectionPMTUUpperBoundDetected() = 0; - virtual void onTransportKnobApplied(TransportKnobParamId knobType) = 0; virtual void onTransportKnobError(TransportKnobParamId knobType) = 0; diff --git a/quic/state/StateData.h b/quic/state/StateData.h index 3e11674c9..a63f1b113 100644 --- a/quic/state/StateData.h +++ b/quic/state/StateData.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -474,32 +473,12 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction { uint64_t nextSelfConnectionIdSequence{0}; - // D6D related events - struct PendingD6DEvents { - // If we should schedule/cancel d6d raise timeout, if it's not - // already scheduled/canceled - bool scheduleRaiseTimeout{false}; - - // If we should schedule/cancel d6d probe timeout, if it's not - // already scheduled/canceled - bool scheduleProbeTimeout{false}; - - // To send a d6d probe packet - bool sendProbePacket{false}; - - // The delay after which sendD6DProbePacket will be set - folly::Optional sendProbeDelay; - }; - struct PendingEvents { Resets resets; folly::Optional pathChallenge; FrameList frames; - // D6D related events - PendingD6DEvents d6d; - std::vector knobs; // Number of probing packets to send after PTO @@ -624,66 +603,6 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction { // Track stats for various server events QuicTransportStatsCallback* statsCallback{nullptr}; - // Meta state of d6d, mostly useful for analytics. D6D can operate without it. - struct D6DMetaState { - // Cumulative count of acked packets - uint64_t totalAckedProbes{0}; - - // Cumulative count of lost packets - uint64_t totalLostProbes{0}; - - // Cumulative count of transmitted packets - uint64_t totalTxedProbes{0}; - - // Timepoint of when d6d reaches a non-search state - // this helps us understand the convergence speed - TimePoint timeLastNonSearchState; - - // Last non-search state - D6DMachineState lastNonSearchState; - }; - - struct D6DState { - // The lastest d6d probe packet transmitted - folly::Optional lastProbe; - - // The raise timeout - std::chrono::seconds raiseTimeout{kDefaultD6DRaiseTimeout}; - - // The probe timeout - std::chrono::seconds probeTimeout{kDefaultD6DProbeTimeout}; - - // The number of outstanding probe packets - uint64_t outstandingProbes{0}; - - // The base PMTU to start probing with - uint16_t basePMTU{kDefaultD6DBasePMTU}; - - // The max PMTU, determined by max_packet_size transport parameter - uint16_t maxPMTU{kDefaultMaxUDPPayload}; - - // Current probe size, dynamically adjusted by the probing algorithm - uint32_t currentProbeSize{kDefaultD6DBasePMTU}; - - // Probe size raiser - std::unique_ptr raiser; - - // ThresholdCounter to help detect PMTU blackhole - std::unique_ptr> thresholdCounter{ - nullptr}; - - // Meta state - D6DMetaState meta; - - // Turn off blackhole detection - bool noBlackholeDetection{false}; - - // D6D Machine State - D6DMachineState state{D6DMachineState::DISABLED}; - }; - - D6DState d6d; - // Debug information. Currently only used to debug busy loop of Transport // WriteLooper. struct WriteDebugState { diff --git a/quic/state/TransportSettings.h b/quic/state/TransportSettings.h index 00eeca489..c0ad0fe39 100644 --- a/quic/state/TransportSettings.h +++ b/quic/state/TransportSettings.h @@ -9,7 +9,6 @@ #include #include -#include #include #include @@ -60,71 +59,6 @@ struct CcpConfig { std::string alg_args = ""; }; -struct D6DConfig { - /** - * Currently, only server does probing, so this flags means different things - * for server and client. For server, it means whether it should enable d6d - * when it receives the base PMTU transport parameter. For client, it means - * whether it will send the base PMTU transport parameter during handshake. - * As a result, d6d is activated for a connection only when *both* client and - * server enables d6d. - * - * TODO: Please make sure QuicConnectionStateBase::D6DState::outstandingProbes - * are mutated correctly throughout Mvfst. - */ - bool enabled{false}; - - /** - * Base PMTU that client advertises to server. This is needed because - * depending on the situation there are clients who want to start from a - * larger/smaller base PMTU. Server makes no use of this value, but should - * rely on the transport parameter received from client. - */ - uint16_t advertisedBasePMTU{kDefaultD6DBasePMTU}; - - /** - * The number of "big" packet losses we can tolerate before signalling PMTU - * blackhole. - */ - uint64_t blackholeDetectionThreshold{kDefaultD6DBlackholeDetectionThreshold}; - - /** - * The constant pmtu step size used for ConstantStep probe size raiser - */ - uint16_t probeRaiserConstantStepSize{kDefaultD6DProbeStepSize}; - - /** - * The D6D raise timeout that client advertises to server. We might need to - * tune this value for different paths. Again, server makes no use of this - * value, but should rely on the transport parameter. - */ - std::chrono::seconds advertisedRaiseTimeout{kDefaultD6DRaiseTimeout}; - - /** - * The D6D probe timeout. When it expires, we either send another - * probe with the same size, or sleep for raise timeout, depending - * on the d6d state. There are other events (e.g. probe gets acked - * or probe is determined lost) that might cancel this timeout. - * Client sends this value as a transport parameter during - * handshake. - */ - std::chrono::seconds advertisedProbeTimeout{kDefaultD6DProbeTimeout}; - - /** - * The moving window within which we check if the detection threshold has been - * crossed - */ - std::chrono::seconds blackholeDetectionWindow{ - kDefaultD6DBlackholeDetectionWindow}; - - /** - * Default raiser is constant step , since overshot caused by binary - * search slows down convergence. Might change in the future when we - * have more context. - */ - ProbeSizeRaiserType raiserType{ProbeSizeRaiserType::ConstantStep}; -}; - struct DatagramConfig { bool enabled{false}; bool framePerPacket{true}; @@ -286,8 +220,6 @@ struct TransportSettings { bool streamFramePerPacket{false}; // Ensure read callbacks are ordered by Stream ID. bool orderedReadCallbacks{false}; - // Config struct for D6D - D6DConfig d6dConfig; // Quic knobs std::vector knobs; // Datagram config diff --git a/quic/state/test/AckHandlersTest.cpp b/quic/state/test/AckHandlersTest.cpp index 3704d85c3..7db014f87 100644 --- a/quic/state/test/AckHandlersTest.cpp +++ b/quic/state/test/AckHandlersTest.cpp @@ -2719,8 +2719,6 @@ TEST_P(AckHandlersTest, ImplictAckEventCreation) { OutstandingPacketMetadata::DetailsPerStream()); sentPacket.isAppLimited = (packetNum % 2); conn.outstandings.packets.emplace_back(sentPacket); - LOG(INFO) << "sentPacket.metadata.isD6DProbe = " - << sentPacket.metadata.isD6DProbe; packetNum++; } diff --git a/quic/state/test/MockQuicStats.h b/quic/state/test/MockQuicStats.h index 29047d7da..e5730deeb 100644 --- a/quic/state/test/MockQuicStats.h +++ b/quic/state/test/MockQuicStats.h @@ -52,10 +52,6 @@ class MockQuicStats : public QuicTransportStatsCallback { MOCK_METHOD(void, onRead, (size_t)); MOCK_METHOD(void, onWrite, (size_t)); MOCK_METHOD(void, onUDPSocketWriteError, (SocketErrorType)); - MOCK_METHOD(void, onConnectionD6DStarted, ()); - MOCK_METHOD(void, onConnectionPMTURaised, ()); - MOCK_METHOD(void, onConnectionPMTUBlackholeDetected, ()); - MOCK_METHOD(void, onConnectionPMTUUpperBoundDetected, ()); MOCK_METHOD(void, onTransportKnobApplied, (TransportKnobParamId)); MOCK_METHOD(void, onTransportKnobError, (TransportKnobParamId)); MOCK_METHOD(void, onTransportKnobOutOfOrder, (TransportKnobParamId)); diff --git a/quic/tools/tperf/tperf.cpp b/quic/tools/tperf/tperf.cpp index 2b5eafece..a05afc669 100644 --- a/quic/tools/tperf/tperf.cpp +++ b/quic/tools/tperf/tperf.cpp @@ -83,38 +83,6 @@ DEFINE_uint32( DEFINE_bool(log_rtt_sample, false, "Log rtt sample events"); DEFINE_bool(log_loss, false, "Log packet loss events"); DEFINE_bool(log_app_rate_limited, false, "Log app rate limited events"); -DEFINE_bool(log_pmtu_probing_started, false, "Log pmtu probing started events"); -DEFINE_bool(log_pmtu_upperbound, false, "Log pmtu upper bound events"); -DEFINE_bool(log_pmtu_blackhole, false, "Log pmtu blackbole events"); -DEFINE_bool(d6d_enabled, false, "Enable d6d"); -DEFINE_uint32( - d6d_probe_raiser_constant_step_size, - 10, - "Server only. The constant step size used to increase PMTU, only meaningful to ConstantStep probe size raiser"); -DEFINE_uint32( - d6d_probe_raiser_type, - 0, - "Server only. The type of probe size raiser. 0: ConstantStep, 1: BinarySearch"); -DEFINE_uint32( - d6d_blackhole_detection_window_secs, - 5, - "Server only. PMTU blackhole detection window in secs"); -DEFINE_uint32( - d6d_blackhole_detection_threshold, - 5, - "Server only. PMTU blackhole detection threshold, in # of packets"); -DEFINE_uint32( - d6d_base_pmtu, - 1252, - "Client only. The base PMTU advertised to server"); -DEFINE_uint32( - d6d_raise_timeout_secs, - 600, - "Client only. The raise timeout advertised to server"); -DEFINE_uint32( - d6d_probe_timeout_secs, - 600, - "Client only. The probe timeout advertised to server"); DEFINE_string( transport_knob_params, "", @@ -126,17 +94,6 @@ namespace tperf { namespace { -ProbeSizeRaiserType parseRaiserType(uint32_t type) { - auto maybeRaiserType = static_cast(type); - switch (maybeRaiserType) { - case ProbeSizeRaiserType::ConstantStep: - case ProbeSizeRaiserType::BinarySearch: - return maybeRaiserType; - default: - throw std::runtime_error("Invalid raiser type, must be 0 or 1."); - } -} - class TPerfObserver : public LegacyObserver { public: using LegacyObserver::LegacyObserver; @@ -165,30 +122,6 @@ class TPerfObserver : public LegacyObserver { LOG(INFO) << "rttSample generated"; } } - - void pmtuProbingStarted(QuicSocket* /* socket */) override { - if (FLAGS_log_pmtu_probing_started) { - LOG(INFO) << "pmtu probing started"; - } - } - - void pmtuBlackholeDetected( - QuicSocket*, /* socket */ - const PMTUBlackholeEvent& /* Blackhole event */) override { - if (FLAGS_log_pmtu_blackhole) { - LOG(INFO) << "pmtuBlackhole detected"; - } - } - - void pmtuUpperBoundDetected( - QuicSocket*, /* socket */ - const PMTUUpperBoundEvent& event) override { - if (FLAGS_log_pmtu_upperbound) { - LOG(INFO) << "pmtuUpperBound detected after " - << event.cumulativeProbesSent << " d6d probes\n" - << "pmtu upperbound is " << event.upperBoundPMTU; - } - } }; /** @@ -203,7 +136,6 @@ class TPerfAcceptObserver : public AcceptObserver { LegacyObserver::EventSet eventSet; eventSet.enable( SocketObserverInterface::Events::appRateLimitedEvents, - SocketObserverInterface::Events::pmtuEvents, SocketObserverInterface::Events::rttSamples, SocketObserverInterface::Events::lossEvents); tperfObserver_ = std::make_unique(eventSet); @@ -520,17 +452,7 @@ class TPerfServer { settings.maxBatchSize = writesPerLoop; } settings.maxRecvPacketSize = maxReceivePacketSize; - settings.canIgnorePathMTU = !FLAGS_d6d_enabled; settings.copaDeltaParam = FLAGS_latency_factor; - settings.d6dConfig.enabled = FLAGS_d6d_enabled; - settings.d6dConfig.probeRaiserConstantStepSize = - FLAGS_d6d_probe_raiser_constant_step_size; - settings.d6dConfig.raiserType = - parseRaiserType(FLAGS_d6d_probe_raiser_type); - settings.d6dConfig.blackholeDetectionWindow = - std::chrono::seconds(FLAGS_d6d_blackhole_detection_window_secs); - settings.d6dConfig.blackholeDetectionThreshold = - FLAGS_d6d_blackhole_detection_threshold; server_->setCongestionControllerFactory( std::make_shared()); server_->setTransportSettings(settings); @@ -739,13 +661,6 @@ class TPerfClient : public quic::QuicSocket::ConnectionSetupCallback, settings.maxBatchSize = 16; } settings.maxRecvPacketSize = maxReceivePacketSize_; - settings.canIgnorePathMTU = !FLAGS_d6d_enabled; - settings.d6dConfig.enabled = FLAGS_d6d_enabled; - settings.d6dConfig.advertisedBasePMTU = FLAGS_d6d_base_pmtu; - settings.d6dConfig.advertisedRaiseTimeout = - std::chrono::seconds(FLAGS_d6d_raise_timeout_secs); - settings.d6dConfig.advertisedProbeTimeout = - std::chrono::seconds(FLAGS_d6d_probe_timeout_secs); if (!FLAGS_transport_knob_params.empty()) { settings.knobs.push_back( {kDefaultQuicTransportKnobSpace,