mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-08 09:42:06 +03:00
Rename RTO to PTO
Summary: To conform to the current specs. Reviewed By: mjoras Differential Revision: D15215018 fbshipit-source-id: 4dcc495aea1cd7cebf2bc84f7367cb2e4a55df19
This commit is contained in:
committed by
Facebook Github Bot
parent
d92acd1225
commit
c35e3d6e84
@@ -212,7 +212,7 @@ constexpr std::chrono::microseconds kGranularity =
|
|||||||
|
|
||||||
constexpr uint32_t kReorderingThreshold = 3;
|
constexpr uint32_t kReorderingThreshold = 3;
|
||||||
|
|
||||||
constexpr auto kPacketToSendForRTO = 2;
|
constexpr auto kPacketToSendForPTO = 2;
|
||||||
|
|
||||||
// Maximum number of packets to write per writeConnectionDataToSocket call.
|
// Maximum number of packets to write per writeConnectionDataToSocket call.
|
||||||
constexpr uint64_t kDefaultWriteConnectionDataPacketLimit = 5;
|
constexpr uint64_t kDefaultWriteConnectionDataPacketLimit = 5;
|
||||||
@@ -327,8 +327,8 @@ constexpr size_t kMaxReasonPhraseLength = 1024;
|
|||||||
// Minimum size of an initial packet
|
// Minimum size of an initial packet
|
||||||
constexpr size_t kMinInitialPacketSize = 1200;
|
constexpr size_t kMinInitialPacketSize = 1200;
|
||||||
|
|
||||||
// Default maximum RTOs that will happen before tearing down the connection
|
// Default maximum PTOs that will happen before tearing down the connection
|
||||||
constexpr uint16_t kDefaultMaxNumRTO = 7;
|
constexpr uint16_t kDefaultMaxNumPTO = 7;
|
||||||
|
|
||||||
// Maximum early data size that we need to negotiate in TLS
|
// Maximum early data size that we need to negotiate in TLS
|
||||||
constexpr uint32_t kRequiredMaxEarlyDataSize = 0xffffffff;
|
constexpr uint32_t kRequiredMaxEarlyDataSize = 0xffffffff;
|
||||||
|
@@ -130,12 +130,12 @@ class QuicSocket {
|
|||||||
uint64_t congestionWindow;
|
uint64_t congestionWindow;
|
||||||
uint32_t packetsRetransmitted;
|
uint32_t packetsRetransmitted;
|
||||||
uint32_t timeoutBasedLoss;
|
uint32_t timeoutBasedLoss;
|
||||||
std::chrono::microseconds rto;
|
std::chrono::microseconds pto;
|
||||||
uint64_t bytesSent;
|
uint64_t bytesSent;
|
||||||
uint64_t bytesRecvd;
|
uint64_t bytesRecvd;
|
||||||
uint64_t totalBytesRetransmitted;
|
uint64_t totalBytesRetransmitted;
|
||||||
uint32_t rtoCount;
|
uint32_t ptoCount;
|
||||||
uint32_t totalRTOCount;
|
uint32_t totalPTOCount;
|
||||||
PacketNum largestPacketAckedByPeer;
|
PacketNum largestPacketAckedByPeer;
|
||||||
PacketNum largestPacketSent;
|
PacketNum largestPacketSent;
|
||||||
};
|
};
|
||||||
|
@@ -348,7 +348,7 @@ void QuicTransportBase::closeImpl(
|
|||||||
getEventBase()->timer().scheduleTimeout(
|
getEventBase()->timer().scheduleTimeout(
|
||||||
&drainTimeout_,
|
&drainTimeout_,
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
kDrainFactor * calculateRTO(*conn_)));
|
kDrainFactor * calculatePTO(*conn_)));
|
||||||
} else {
|
} else {
|
||||||
drainTimeoutExpired();
|
drainTimeoutExpired();
|
||||||
}
|
}
|
||||||
@@ -445,11 +445,11 @@ QuicSocket::TransportInfo QuicTransportBase::getTransportInfo() const {
|
|||||||
transportInfo.timeoutBasedLoss = conn_->lossState.timeoutBasedRetxCount;
|
transportInfo.timeoutBasedLoss = conn_->lossState.timeoutBasedRetxCount;
|
||||||
transportInfo.totalBytesRetransmitted =
|
transportInfo.totalBytesRetransmitted =
|
||||||
conn_->lossState.totalBytesRetransmitted;
|
conn_->lossState.totalBytesRetransmitted;
|
||||||
transportInfo.rto = calculateRTO(*conn_);
|
transportInfo.pto = calculatePTO(*conn_);
|
||||||
transportInfo.bytesSent = conn_->lossState.totalBytesSent;
|
transportInfo.bytesSent = conn_->lossState.totalBytesSent;
|
||||||
transportInfo.bytesRecvd = conn_->lossState.totalBytesRecvd;
|
transportInfo.bytesRecvd = conn_->lossState.totalBytesRecvd;
|
||||||
transportInfo.rtoCount = conn_->lossState.rtoCount;
|
transportInfo.ptoCount = conn_->lossState.ptoCount;
|
||||||
transportInfo.totalRTOCount = conn_->lossState.totalRTOCount;
|
transportInfo.totalPTOCount = conn_->lossState.totalPTOCount;
|
||||||
transportInfo.largestPacketAckedByPeer =
|
transportInfo.largestPacketAckedByPeer =
|
||||||
conn_->ackStates.appDataAckState.largestAckedByPeer;
|
conn_->ackStates.appDataAckState.largestAckedByPeer;
|
||||||
transportInfo.largestPacketSent = conn_->lossState.largestSent;
|
transportInfo.largestPacketSent = conn_->lossState.largestSent;
|
||||||
|
@@ -984,7 +984,7 @@ uint64_t writeProbingDataToSocket(
|
|||||||
|
|
||||||
bool shouldWriteData(const QuicConnectionStateBase& conn) {
|
bool shouldWriteData(const QuicConnectionStateBase& conn) {
|
||||||
if (conn.pendingEvents.numProbePackets) {
|
if (conn.pendingEvents.numProbePackets) {
|
||||||
VLOG(10) << nodeToString(conn.nodeType) << " needs write because of RTO"
|
VLOG(10) << nodeToString(conn.nodeType) << " needs write because of PTO"
|
||||||
<< conn;
|
<< conn;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ class MockQuicStats : public QuicTransportStatsCallback {
|
|||||||
MOCK_METHOD0(onStreamFlowControlUpdate, void());
|
MOCK_METHOD0(onStreamFlowControlUpdate, void());
|
||||||
MOCK_METHOD0(onStreamFlowControlBlocked, void());
|
MOCK_METHOD0(onStreamFlowControlBlocked, void());
|
||||||
MOCK_METHOD0(onCwndBlocked, void());
|
MOCK_METHOD0(onCwndBlocked, void());
|
||||||
MOCK_METHOD0(onRTO, void());
|
MOCK_METHOD0(onPTO, void());
|
||||||
MOCK_METHOD1(onRead, void(size_t));
|
MOCK_METHOD1(onRead, void(size_t));
|
||||||
MOCK_METHOD1(onWrite, void(size_t));
|
MOCK_METHOD1(onWrite, void(size_t));
|
||||||
};
|
};
|
||||||
|
@@ -944,7 +944,7 @@ TEST_F(QuicTransportTest, ClonePathChallenge) {
|
|||||||
|
|
||||||
// Force a timeout with no data so that it clones the packet
|
// Force a timeout with no data so that it clones the packet
|
||||||
transport_->lossTimeout().timeoutExpired();
|
transport_->lossTimeout().timeoutExpired();
|
||||||
// On RTO, endpoint sends 2 probing packets, thus 1+2=3
|
// On PTO, endpoint sends 2 probing packets, thus 1+2=3
|
||||||
EXPECT_EQ(conn.outstandingPackets.size(), 3);
|
EXPECT_EQ(conn.outstandingPackets.size(), 3);
|
||||||
numPathChallengePackets = std::count_if(
|
numPathChallengePackets = std::count_if(
|
||||||
conn.outstandingPackets.begin(),
|
conn.outstandingPackets.begin(),
|
||||||
|
@@ -19,9 +19,6 @@ namespace test {
|
|||||||
|
|
||||||
class CubicHystartTest : public Test {};
|
class CubicHystartTest : public Test {};
|
||||||
|
|
||||||
// TODO: add test of currSampledRtt gets reset once the onRTOVerified is
|
|
||||||
// implemented
|
|
||||||
|
|
||||||
TEST_F(CubicHystartTest, SendAndAck) {
|
TEST_F(CubicHystartTest, SendAndAck) {
|
||||||
QuicConnectionStateBase conn(QuicNodeType::Client);
|
QuicConnectionStateBase conn(QuicNodeType::Client);
|
||||||
conn.udpSendPacketLen = 100;
|
conn.udpSendPacketLen = 100;
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace quic {
|
namespace quic {
|
||||||
|
|
||||||
std::chrono::microseconds calculateRTO(const QuicConnectionStateBase& conn) {
|
std::chrono::microseconds calculatePTO(const QuicConnectionStateBase& conn) {
|
||||||
return conn.lossState.srtt + 4 * conn.lossState.rttvar +
|
return conn.lossState.srtt + 4 * conn.lossState.rttvar +
|
||||||
conn.lossState.maxAckDelay;
|
conn.lossState.maxAckDelay;
|
||||||
}
|
}
|
||||||
@@ -22,26 +22,26 @@ bool isPersistentCongestion(
|
|||||||
if (conn.lossState.srtt == std::chrono::microseconds::zero()) {
|
if (conn.lossState.srtt == std::chrono::microseconds::zero()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto rto = calculateRTO(conn);
|
auto pto = calculatePTO(conn);
|
||||||
return (lostPeriodEnd - lostPeriodStart) >=
|
return (lostPeriodEnd - lostPeriodStart) >=
|
||||||
rto * kPersistentCongestionPeriodFactor;
|
pto * kPersistentCongestionPeriodFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRTOAlarm(QuicConnectionStateBase& conn) {
|
void onPTOAlarm(QuicConnectionStateBase& conn) {
|
||||||
VLOG(10) << __func__ << " " << conn;
|
VLOG(10) << __func__ << " " << conn;
|
||||||
QUIC_TRACE(
|
QUIC_TRACE(
|
||||||
rto_alarm,
|
pto_alarm,
|
||||||
conn,
|
conn,
|
||||||
conn.lossState.largestSent,
|
conn.lossState.largestSent,
|
||||||
conn.lossState.rtoCount,
|
conn.lossState.ptoCount,
|
||||||
(uint64_t)conn.outstandingPackets.size());
|
(uint64_t)conn.outstandingPackets.size());
|
||||||
QUIC_STATS(conn.infoCallback, onRTO);
|
QUIC_STATS(conn.infoCallback, onPTO);
|
||||||
conn.lossState.rtoCount++;
|
conn.lossState.ptoCount++;
|
||||||
conn.lossState.totalRTOCount++;
|
conn.lossState.totalPTOCount++;
|
||||||
if (conn.lossState.rtoCount == conn.transportSettings.maxNumRTOs) {
|
if (conn.lossState.ptoCount == conn.transportSettings.maxNumPTOs) {
|
||||||
throw QuicInternalException("Exceeded max RTO", LocalErrorCode::NO_ERROR);
|
throw QuicInternalException("Exceeded max PTO", LocalErrorCode::NO_ERROR);
|
||||||
}
|
}
|
||||||
conn.pendingEvents.numProbePackets = kPacketToSendForRTO;
|
conn.pendingEvents.numProbePackets = kPacketToSendForPTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void markPacketLoss(
|
void markPacketLoss(
|
||||||
|
@@ -26,7 +26,7 @@ namespace quic {
|
|||||||
bool hasAckDataToWrite(const QuicConnectionStateBase& conn);
|
bool hasAckDataToWrite(const QuicConnectionStateBase& conn);
|
||||||
bool hasNonAckDataToWrite(const QuicConnectionStateBase& conn);
|
bool hasNonAckDataToWrite(const QuicConnectionStateBase& conn);
|
||||||
|
|
||||||
std::chrono::microseconds calculateRTO(const QuicConnectionStateBase& conn);
|
std::chrono::microseconds calculatePTO(const QuicConnectionStateBase& conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether conn is having persistent congestion.
|
* Whether conn is having persistent congestion.
|
||||||
@@ -50,8 +50,8 @@ inline std::ostream& operator<<(
|
|||||||
case LossState::AlarmMethod::EarlyRetransmitOrReordering:
|
case LossState::AlarmMethod::EarlyRetransmitOrReordering:
|
||||||
os << "EarlyRetransmitOrReordering";
|
os << "EarlyRetransmitOrReordering";
|
||||||
break;
|
break;
|
||||||
case LossState::AlarmMethod::RTO:
|
case LossState::AlarmMethod::PTO:
|
||||||
os << "RTO";
|
os << "PTO";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return os;
|
return os;
|
||||||
@@ -88,10 +88,10 @@ calculateAlarmDuration(const QuicConnectionStateBase& conn) {
|
|||||||
}
|
}
|
||||||
alarmMethod = LossState::AlarmMethod::EarlyRetransmitOrReordering;
|
alarmMethod = LossState::AlarmMethod::EarlyRetransmitOrReordering;
|
||||||
} else {
|
} else {
|
||||||
auto rtoTimeout = calculateRTO(conn);
|
auto ptoTimeout = calculatePTO(conn);
|
||||||
rtoTimeout *= 1 << std::min(conn.lossState.rtoCount, (uint32_t)31);
|
ptoTimeout *= 1 << std::min(conn.lossState.ptoCount, (uint32_t)31);
|
||||||
alarmDuration = rtoTimeout;
|
alarmDuration = ptoTimeout;
|
||||||
alarmMethod = LossState::AlarmMethod::RTO;
|
alarmMethod = LossState::AlarmMethod::PTO;
|
||||||
}
|
}
|
||||||
TimePoint now = ClockType::now();
|
TimePoint now = ClockType::now();
|
||||||
std::chrono::milliseconds adjustedAlarmDuration{0};
|
std::chrono::milliseconds adjustedAlarmDuration{0};
|
||||||
@@ -130,11 +130,11 @@ void setLossDetectionAlarm(QuicConnectionStateBase& conn, Timeout& timeout) {
|
|||||||
conn.outstandingPackets.size(), conn.outstandingPureAckPacketsCount);
|
conn.outstandingPackets.size(), conn.outstandingPureAckPacketsCount);
|
||||||
/*
|
/*
|
||||||
* We might have new data or lost data to send even if we don't have any
|
* We might have new data or lost data to send even if we don't have any
|
||||||
* outstanding packets. When we get an RTO event, it is possible that only
|
* outstanding packets. When we get a PTO event, it is possible that only
|
||||||
* cloned packets might be outstanding. Since cwnd might be set to min cwnd,
|
* cloned packets might be outstanding. Since cwnd might be set to min cwnd,
|
||||||
* we might not be able to send data. However we might still have data sitting
|
* we might not be able to send data. However we might still have data sitting
|
||||||
* in the buffers which is unsent or known to be lost. We should set a timer
|
* in the buffers which is unsent or known to be lost. We should set a timer
|
||||||
* in this case to be able to send this data on the next RTO.
|
* in this case to be able to send this data on the next PTO.
|
||||||
*/
|
*/
|
||||||
bool hasDataToWrite = hasAckDataToWrite(conn) || hasNonAckDataToWrite(conn);
|
bool hasDataToWrite = hasAckDataToWrite(conn) || hasNonAckDataToWrite(conn);
|
||||||
auto totalPacketsOutstanding = conn.outstandingPackets.size();
|
auto totalPacketsOutstanding = conn.outstandingPackets.size();
|
||||||
@@ -155,7 +155,7 @@ void setLossDetectionAlarm(QuicConnectionStateBase& conn, Timeout& timeout) {
|
|||||||
* (2) All outstanding are clones that are processed and there is data to
|
* (2) All outstanding are clones that are processed and there is data to
|
||||||
* write.
|
* write.
|
||||||
* If there are only clones with no data, then we don't need to set the timer.
|
* 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 an RTO verified event, clones take
|
* 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
|
* 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
|
* 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.
|
* so that we can write this data with the slack packet space for the clones.
|
||||||
@@ -307,7 +307,7 @@ folly::Optional<CongestionController::LossEvent> detectLossPackets(
|
|||||||
return folly::none;
|
return folly::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRTOAlarm(QuicConnectionStateBase& conn);
|
void onPTOAlarm(QuicConnectionStateBase& conn);
|
||||||
|
|
||||||
template <class LossVisitor, class ClockType = Clock>
|
template <class LossVisitor, class ClockType = Clock>
|
||||||
void onHandshakeAlarm(
|
void onHandshakeAlarm(
|
||||||
@@ -357,7 +357,7 @@ void onHandshakeAlarm(
|
|||||||
if (conn.nodeType == QuicNodeType::Client && conn.oneRttWriteCipher) {
|
if (conn.nodeType == QuicNodeType::Client && conn.oneRttWriteCipher) {
|
||||||
// When sending client finished, we should also send a 1-rtt probe packet to
|
// When sending client finished, we should also send a 1-rtt probe packet to
|
||||||
// elicit an ack.
|
// elicit an ack.
|
||||||
conn.pendingEvents.numProbePackets = kPacketToSendForRTO;
|
conn.pendingEvents.numProbePackets = kPacketToSendForPTO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +395,7 @@ void onLossDetectionAlarm(
|
|||||||
folly::none, std::move(lossEvent));
|
folly::none, std::move(lossEvent));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onRTOAlarm(conn);
|
onPTOAlarm(conn);
|
||||||
}
|
}
|
||||||
conn.pendingEvents.setLossDetectionAlarm =
|
conn.pendingEvents.setLossDetectionAlarm =
|
||||||
(conn.outstandingPackets.size() > conn.outstandingPureAckPacketsCount);
|
(conn.outstandingPackets.size() > conn.outstandingPureAckPacketsCount);
|
||||||
@@ -428,7 +428,7 @@ folly::Optional<CongestionController::LossEvent> handleAckForLoss(
|
|||||||
if (ack.largestAckedPacket.hasValue()) {
|
if (ack.largestAckedPacket.hasValue()) {
|
||||||
// TODO: Should we NOT reset these counters if the received Ack frame
|
// TODO: Should we NOT reset these counters if the received Ack frame
|
||||||
// doesn't ack anything that's in OP list?
|
// doesn't ack anything that's in OP list?
|
||||||
conn.lossState.rtoCount = 0;
|
conn.lossState.ptoCount = 0;
|
||||||
conn.lossState.handshakeAlarmCount = 0;
|
conn.lossState.handshakeAlarmCount = 0;
|
||||||
largestAcked = std::max(largestAcked, *ack.largestAckedPacket);
|
largestAcked = std::max(largestAcked, *ack.largestAckedPacket);
|
||||||
}
|
}
|
||||||
|
@@ -224,7 +224,7 @@ PacketNum QuicLossFunctionsTest::sendPacket(
|
|||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, AllPacketsProcessed) {
|
TEST_F(QuicLossFunctionsTest, AllPacketsProcessed) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO()).Times(0);
|
EXPECT_CALL(*transportInfoCb_, onPTO()).Times(0);
|
||||||
auto pkt1 = conn->ackStates.appDataAckState.nextPacketNum;
|
auto pkt1 = conn->ackStates.appDataAckState.nextPacketNum;
|
||||||
sendPacket(*conn, Clock::now(), false, pkt1, PacketType::OneRtt);
|
sendPacket(*conn, Clock::now(), false, pkt1, PacketType::OneRtt);
|
||||||
auto pkt2 = conn->ackStates.appDataAckState.nextPacketNum;
|
auto pkt2 = conn->ackStates.appDataAckState.nextPacketNum;
|
||||||
@@ -301,33 +301,33 @@ TEST_F(QuicLossFunctionsTest, TestOnLossDetectionAlarm) {
|
|||||||
MockClock::mockNow = []() { return TimePoint(123ms); };
|
MockClock::mockNow = []() { return TimePoint(123ms); };
|
||||||
std::vector<PacketNum> lostPacket;
|
std::vector<PacketNum> lostPacket;
|
||||||
MockClock::mockNow = []() { return TimePoint(23ms); };
|
MockClock::mockNow = []() { return TimePoint(23ms); };
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO());
|
EXPECT_CALL(*transportInfoCb_, onPTO());
|
||||||
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
||||||
EXPECT_EQ(LossState::AlarmMethod::RTO, conn->lossState.currentAlarmMethod);
|
EXPECT_EQ(LossState::AlarmMethod::PTO, conn->lossState.currentAlarmMethod);
|
||||||
onLossDetectionAlarm<decltype(testingLossMarkFunc(lostPacket)), MockClock>(
|
onLossDetectionAlarm<decltype(testingLossMarkFunc(lostPacket)), MockClock>(
|
||||||
*conn, testingLossMarkFunc(lostPacket));
|
*conn, testingLossMarkFunc(lostPacket));
|
||||||
EXPECT_EQ(conn->lossState.rtoCount, 1);
|
EXPECT_EQ(conn->lossState.ptoCount, 1);
|
||||||
EXPECT_TRUE(conn->pendingEvents.setLossDetectionAlarm);
|
EXPECT_TRUE(conn->pendingEvents.setLossDetectionAlarm);
|
||||||
// RTO shouldn't mark loss
|
// PTO shouldn't mark loss
|
||||||
EXPECT_TRUE(lostPacket.empty());
|
EXPECT_TRUE(lostPacket.empty());
|
||||||
|
|
||||||
MockClock::mockNow = []() { return TimePoint(3ms); };
|
MockClock::mockNow = []() { return TimePoint(3ms); };
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO());
|
EXPECT_CALL(*transportInfoCb_, onPTO());
|
||||||
sendPacket(*conn, TimePoint(), false, folly::none, PacketType::OneRtt);
|
sendPacket(*conn, TimePoint(), false, folly::none, PacketType::OneRtt);
|
||||||
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
||||||
EXPECT_CALL(*rawCongestionController, onPacketAckOrLoss(_, _)).Times(0);
|
EXPECT_CALL(*rawCongestionController, onPacketAckOrLoss(_, _)).Times(0);
|
||||||
onLossDetectionAlarm<decltype(testingLossMarkFunc(lostPacket)), MockClock>(
|
onLossDetectionAlarm<decltype(testingLossMarkFunc(lostPacket)), MockClock>(
|
||||||
*conn, testingLossMarkFunc(lostPacket));
|
*conn, testingLossMarkFunc(lostPacket));
|
||||||
EXPECT_EQ(conn->lossState.rtoCount, 2);
|
EXPECT_EQ(conn->lossState.ptoCount, 2);
|
||||||
// RTO doesn't take anything out of outstandingPackets
|
// PTO doesn't take anything out of outstandingPackets
|
||||||
EXPECT_FALSE(conn->outstandingPackets.empty());
|
EXPECT_FALSE(conn->outstandingPackets.empty());
|
||||||
EXPECT_EQ(0, conn->outstandingPureAckPacketsCount);
|
EXPECT_EQ(0, conn->outstandingPureAckPacketsCount);
|
||||||
EXPECT_TRUE(conn->pendingEvents.setLossDetectionAlarm);
|
EXPECT_TRUE(conn->pendingEvents.setLossDetectionAlarm);
|
||||||
// RTO shouldn't mark loss
|
// PTO shouldn't mark loss
|
||||||
EXPECT_TRUE(lostPacket.empty());
|
EXPECT_TRUE(lostPacket.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TestOnRTOSkipProcessed) {
|
TEST_F(QuicLossFunctionsTest, TestOnPTOSkipProcessed) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
auto mockCongestionController = std::make_unique<MockCongestionController>();
|
auto mockCongestionController = std::make_unique<MockCongestionController>();
|
||||||
auto rawCongestionController = mockCongestionController.get();
|
auto rawCongestionController = mockCongestionController.get();
|
||||||
@@ -342,8 +342,8 @@ TEST_F(QuicLossFunctionsTest, TestOnRTOSkipProcessed) {
|
|||||||
EXPECT_EQ(10, conn->outstandingPackets.size());
|
EXPECT_EQ(10, conn->outstandingPackets.size());
|
||||||
std::vector<PacketNum> lostPackets;
|
std::vector<PacketNum> lostPackets;
|
||||||
EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(0);
|
EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(0);
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO());
|
EXPECT_CALL(*transportInfoCb_, onPTO());
|
||||||
onRTOAlarm(*conn);
|
onPTOAlarm(*conn);
|
||||||
EXPECT_EQ(10, conn->outstandingPackets.size());
|
EXPECT_EQ(10, conn->outstandingPackets.size());
|
||||||
EXPECT_TRUE(lostPackets.empty());
|
EXPECT_TRUE(lostPackets.empty());
|
||||||
}
|
}
|
||||||
@@ -529,7 +529,7 @@ TEST_F(QuicLossFunctionsTest, TestReorderingThreshold) {
|
|||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TestHandleAckForLoss) {
|
TEST_F(QuicLossFunctionsTest, TestHandleAckForLoss) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
conn->lossState.rtoCount = 100;
|
conn->lossState.ptoCount = 100;
|
||||||
conn->lossState.reorderingThreshold = 10;
|
conn->lossState.reorderingThreshold = 10;
|
||||||
|
|
||||||
LongHeader longHeader(
|
LongHeader longHeader(
|
||||||
@@ -554,7 +554,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckForLoss) {
|
|||||||
handleAckForLoss(
|
handleAckForLoss(
|
||||||
*conn, testLossMarkFunc, ackEvent, PacketNumberSpace::Handshake);
|
*conn, testLossMarkFunc, ackEvent, PacketNumberSpace::Handshake);
|
||||||
|
|
||||||
EXPECT_EQ(0, conn->lossState.rtoCount);
|
EXPECT_EQ(0, conn->lossState.ptoCount);
|
||||||
EXPECT_TRUE(conn->outstandingPackets.empty());
|
EXPECT_TRUE(conn->outstandingPackets.empty());
|
||||||
EXPECT_EQ(0, conn->outstandingPureAckPacketsCount);
|
EXPECT_EQ(0, conn->outstandingPureAckPacketsCount);
|
||||||
EXPECT_FALSE(conn->pendingEvents.setLossDetectionAlarm);
|
EXPECT_FALSE(conn->pendingEvents.setLossDetectionAlarm);
|
||||||
@@ -563,7 +563,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckForLoss) {
|
|||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TestHandleAckedPacket) {
|
TEST_F(QuicLossFunctionsTest, TestHandleAckedPacket) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
conn->lossState.rtoCount = 10;
|
conn->lossState.ptoCount = 10;
|
||||||
conn->lossState.handshakeAlarmCount = 5;
|
conn->lossState.handshakeAlarmCount = 5;
|
||||||
conn->lossState.reorderingThreshold = 10;
|
conn->lossState.reorderingThreshold = 10;
|
||||||
|
|
||||||
@@ -590,7 +590,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckedPacket) {
|
|||||||
testLossMarkFunc,
|
testLossMarkFunc,
|
||||||
Clock::now());
|
Clock::now());
|
||||||
|
|
||||||
EXPECT_EQ(0, conn->lossState.rtoCount);
|
EXPECT_EQ(0, conn->lossState.ptoCount);
|
||||||
EXPECT_EQ(0, conn->lossState.handshakeAlarmCount);
|
EXPECT_EQ(0, conn->lossState.handshakeAlarmCount);
|
||||||
EXPECT_TRUE(conn->outstandingPackets.empty());
|
EXPECT_TRUE(conn->outstandingPackets.empty());
|
||||||
EXPECT_EQ(0, conn->outstandingPureAckPacketsCount);
|
EXPECT_EQ(0, conn->outstandingPureAckPacketsCount);
|
||||||
@@ -769,7 +769,7 @@ TEST_F(QuicLossFunctionsTest, TestTimeReordering) {
|
|||||||
EXPECT_TRUE(conn->lossState.lossTime);
|
EXPECT_TRUE(conn->lossState.lossTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, RTONoLongerMarksPacketsToBeRetransmitted) {
|
TEST_F(QuicLossFunctionsTest, PTONoLongerMarksPacketsToBeRetransmitted) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
auto mockCongestionController = std::make_unique<MockCongestionController>();
|
auto mockCongestionController = std::make_unique<MockCongestionController>();
|
||||||
auto rawCongestionController = mockCongestionController.get();
|
auto rawCongestionController = mockCongestionController.get();
|
||||||
@@ -780,17 +780,17 @@ TEST_F(QuicLossFunctionsTest, RTONoLongerMarksPacketsToBeRetransmitted) {
|
|||||||
TimePoint startTime(123ms);
|
TimePoint startTime(123ms);
|
||||||
MockClock::mockNow = [&]() { return startTime; };
|
MockClock::mockNow = [&]() { return startTime; };
|
||||||
std::vector<PacketNum> lostPackets;
|
std::vector<PacketNum> lostPackets;
|
||||||
for (auto i = 0; i < kPacketToSendForRTO + 10; i++) {
|
for (auto i = 0; i < kPacketToSendForPTO + 10; i++) {
|
||||||
sendPacket(*conn, startTime, false, folly::none, PacketType::OneRtt);
|
sendPacket(*conn, startTime, false, folly::none, PacketType::OneRtt);
|
||||||
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
||||||
startTime += std::chrono::milliseconds(1);
|
startTime += std::chrono::milliseconds(1);
|
||||||
}
|
}
|
||||||
EXPECT_CALL(*rawCongestionController, onPacketAckOrLoss(_, _)).Times(0);
|
EXPECT_CALL(*rawCongestionController, onPacketAckOrLoss(_, _)).Times(0);
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO());
|
EXPECT_CALL(*transportInfoCb_, onPTO());
|
||||||
onLossDetectionAlarm<decltype(testingLossMarkFunc(lostPackets)), MockClock>(
|
onLossDetectionAlarm<decltype(testingLossMarkFunc(lostPackets)), MockClock>(
|
||||||
*conn, testingLossMarkFunc(lostPackets));
|
*conn, testingLossMarkFunc(lostPackets));
|
||||||
EXPECT_EQ(1, conn->lossState.rtoCount);
|
EXPECT_EQ(1, conn->lossState.ptoCount);
|
||||||
// Hey RTOs are not losses either from now on
|
// Hey PTOs are not losses either from now on
|
||||||
EXPECT_TRUE(lostPackets.empty());
|
EXPECT_TRUE(lostPackets.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,7 +849,7 @@ TEST_F(QuicLossFunctionsTest, HandshakeAlarmWithOneRttCipher) {
|
|||||||
// Half should be marked as loss
|
// Half should be marked as loss
|
||||||
EXPECT_EQ(lostPackets.size(), 1);
|
EXPECT_EQ(lostPackets.size(), 1);
|
||||||
EXPECT_EQ(conn->lossState.handshakeAlarmCount, 1);
|
EXPECT_EQ(conn->lossState.handshakeAlarmCount, 1);
|
||||||
EXPECT_EQ(conn->pendingEvents.numProbePackets, kPacketToSendForRTO);
|
EXPECT_EQ(conn->pendingEvents.numProbePackets, kPacketToSendForPTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, PureAckSkipsCongestionControl) {
|
TEST_F(QuicLossFunctionsTest, PureAckSkipsCongestionControl) {
|
||||||
@@ -976,13 +976,13 @@ TEST_F(QuicLossFunctionsTest, AlarmDurationNonHandshakeOutstanding) {
|
|||||||
MockClock::mockNow = [=]() { return lastPacketSentTime; };
|
MockClock::mockNow = [=]() { return lastPacketSentTime; };
|
||||||
sendPacket(*conn, lastPacketSentTime, false, folly::none, PacketType::OneRtt);
|
sendPacket(*conn, lastPacketSentTime, false, folly::none, PacketType::OneRtt);
|
||||||
auto duration = calculateAlarmDuration<MockClock>(*conn);
|
auto duration = calculateAlarmDuration<MockClock>(*conn);
|
||||||
EXPECT_EQ(duration.second, LossState::AlarmMethod::RTO);
|
EXPECT_EQ(duration.second, LossState::AlarmMethod::PTO);
|
||||||
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
setLossDetectionAlarm<decltype(timeout), MockClock>(*conn, timeout);
|
||||||
EXPECT_EQ(conn->lossState.currentAlarmMethod, LossState::AlarmMethod::RTO);
|
EXPECT_EQ(conn->lossState.currentAlarmMethod, LossState::AlarmMethod::PTO);
|
||||||
|
|
||||||
conn->lossState.rtoCount = 2;
|
conn->lossState.ptoCount = 2;
|
||||||
auto newDuration = calculateAlarmDuration<MockClock>(*conn);
|
auto newDuration = calculateAlarmDuration<MockClock>(*conn);
|
||||||
EXPECT_EQ(duration.second, LossState::AlarmMethod::RTO);
|
EXPECT_EQ(duration.second, LossState::AlarmMethod::PTO);
|
||||||
EXPECT_LT(duration.first, newDuration.first);
|
EXPECT_LT(duration.first, newDuration.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1151,21 +1151,21 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
|
|||||||
EXPECT_TRUE(conn->pendingEvents.connWindowUpdate);
|
EXPECT_TRUE(conn->pendingEvents.connWindowUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TestTotalRTOCount) {
|
TEST_F(QuicLossFunctionsTest, TestTotalPTOCount) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
conn->lossState.totalRTOCount = 100;
|
conn->lossState.totalPTOCount = 100;
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO());
|
EXPECT_CALL(*transportInfoCb_, onPTO());
|
||||||
onRTOAlarm(*conn);
|
onPTOAlarm(*conn);
|
||||||
EXPECT_EQ(101, conn->lossState.totalRTOCount);
|
EXPECT_EQ(101, conn->lossState.totalPTOCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TestExceedsMaxRTOThrows) {
|
TEST_F(QuicLossFunctionsTest, TestExceedsMaxPTOThrows) {
|
||||||
auto conn = createConn();
|
auto conn = createConn();
|
||||||
conn->transportSettings.maxNumRTOs = 3;
|
conn->transportSettings.maxNumPTOs = 3;
|
||||||
EXPECT_CALL(*transportInfoCb_, onRTO()).Times(3);
|
EXPECT_CALL(*transportInfoCb_, onPTO()).Times(3);
|
||||||
onRTOAlarm(*conn);
|
onPTOAlarm(*conn);
|
||||||
onRTOAlarm(*conn);
|
onPTOAlarm(*conn);
|
||||||
EXPECT_THROW(onRTOAlarm(*conn), QuicInternalException);
|
EXPECT_THROW(onPTOAlarm(*conn), QuicInternalException);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TotalLossCount) {
|
TEST_F(QuicLossFunctionsTest, TotalLossCount) {
|
||||||
@@ -1286,10 +1286,10 @@ TEST_F(QuicLossFunctionsTest, TestZeroRttRejectedWithClones) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, RTOLargerThanMaxDelay) {
|
TEST_F(QuicLossFunctionsTest, PTOLargerThanMaxDelay) {
|
||||||
QuicConnectionStateBase conn(QuicNodeType::Client);
|
QuicConnectionStateBase conn(QuicNodeType::Client);
|
||||||
conn.lossState.maxAckDelay = std::chrono::seconds(20);
|
conn.lossState.maxAckDelay = std::chrono::seconds(20);
|
||||||
EXPECT_GE(calculateRTO(conn), std::chrono::seconds(20));
|
EXPECT_GE(calculatePTO(conn), std::chrono::seconds(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QuicLossFunctionsTest, TimeThreshold) {
|
TEST_F(QuicLossFunctionsTest, TimeThreshold) {
|
||||||
@@ -1334,8 +1334,8 @@ TEST_P(QuicLossFunctionsTest, CappedShiftNoCrash) {
|
|||||||
conn->lossState.handshakeAlarmCount = 0;
|
conn->lossState.handshakeAlarmCount = 0;
|
||||||
conn->outstandingHandshakePacketsCount = 0;
|
conn->outstandingHandshakePacketsCount = 0;
|
||||||
conn->outstandingPackets.clear();
|
conn->outstandingPackets.clear();
|
||||||
conn->lossState.rtoCount =
|
conn->lossState.ptoCount =
|
||||||
std::numeric_limits<decltype(conn->lossState.rtoCount)>::max();
|
std::numeric_limits<decltype(conn->lossState.ptoCount)>::max();
|
||||||
sendPacket(*conn, Clock::now(), false, folly::none, PacketType::OneRtt);
|
sendPacket(*conn, Clock::now(), false, folly::none, PacketType::OneRtt);
|
||||||
calculateAlarmDuration(*conn);
|
calculateAlarmDuration(*conn);
|
||||||
}
|
}
|
||||||
|
@@ -100,7 +100,7 @@ class QuicTransportStatsCallback {
|
|||||||
virtual void onCwndBlocked() = 0;
|
virtual void onCwndBlocked() = 0;
|
||||||
|
|
||||||
// retransmission timeout counter
|
// retransmission timeout counter
|
||||||
virtual void onRTO() = 0;
|
virtual void onPTO() = 0;
|
||||||
|
|
||||||
// metrics to track bytes read from / written to wire
|
// metrics to track bytes read from / written to wire
|
||||||
virtual void onRead(size_t bufSize) = 0;
|
virtual void onRead(size_t bufSize) = 0;
|
||||||
|
@@ -287,7 +287,7 @@ using Resets = std::unordered_map<StreamId, RstStreamFrame>;
|
|||||||
using FrameList = std::vector<QuicSimpleFrame>;
|
using FrameList = std::vector<QuicSimpleFrame>;
|
||||||
|
|
||||||
struct LossState {
|
struct LossState {
|
||||||
enum class AlarmMethod { EarlyRetransmitOrReordering, Handshake, RTO };
|
enum class AlarmMethod { EarlyRetransmitOrReordering, Handshake, PTO };
|
||||||
// Smooth rtt
|
// Smooth rtt
|
||||||
std::chrono::microseconds srtt{std::chrono::microseconds::zero()};
|
std::chrono::microseconds srtt{std::chrono::microseconds::zero()};
|
||||||
// Latest rtt
|
// Latest rtt
|
||||||
@@ -295,7 +295,7 @@ struct LossState {
|
|||||||
// Rtt var
|
// Rtt var
|
||||||
std::chrono::microseconds rttvar{std::chrono::microseconds::zero()};
|
std::chrono::microseconds rttvar{std::chrono::microseconds::zero()};
|
||||||
// Number of packet loss timer fired before receiving an ack
|
// Number of packet loss timer fired before receiving an ack
|
||||||
uint32_t rtoCount{0};
|
uint32_t ptoCount{0};
|
||||||
// The number of times the handshake packets have been retransmitted without
|
// The number of times the handshake packets have been retransmitted without
|
||||||
// receiving an ack.
|
// receiving an ack.
|
||||||
uint16_t handshakeAlarmCount{0};
|
uint16_t handshakeAlarmCount{0};
|
||||||
@@ -314,10 +314,10 @@ struct LossState {
|
|||||||
// Total number of packet retransmitted on this connection, including packet
|
// Total number of packet retransmitted on this connection, including packet
|
||||||
// clones, retransmitted clones, handshake and rejected zero rtt packets.
|
// clones, retransmitted clones, handshake and rejected zero rtt packets.
|
||||||
uint32_t rtxCount{0};
|
uint32_t rtxCount{0};
|
||||||
// Total number of retransmission due to RTO
|
// Total number of retransmission due to PTO
|
||||||
uint32_t timeoutBasedRetxCount{0};
|
uint32_t timeoutBasedRetxCount{0};
|
||||||
// Total number of RTO count
|
// Total number of PTO count
|
||||||
uint32_t totalRTOCount{0};
|
uint32_t totalPTOCount{0};
|
||||||
// Total number of bytes sent on this connection. This is after encoding.
|
// Total number of bytes sent on this connection. This is after encoding.
|
||||||
uint64_t totalBytesSent{0};
|
uint64_t totalBytesSent{0};
|
||||||
// Total number of bytes received on this connection. This is before decoding.
|
// Total number of bytes received on this connection. This is before decoding.
|
||||||
@@ -492,7 +492,7 @@ struct QuicConnectionStateBase {
|
|||||||
// If there is a pending loss detection alarm update
|
// If there is a pending loss detection alarm update
|
||||||
bool setLossDetectionAlarm{false};
|
bool setLossDetectionAlarm{false};
|
||||||
|
|
||||||
// Number of probing packets to send after RTO
|
// Number of probing packets to send after PTO
|
||||||
uint8_t numProbePackets{0};
|
uint8_t numProbePackets{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -41,8 +41,8 @@ struct TransportSettings {
|
|||||||
// only be used in environments where you know your IP address does not
|
// only be used in environments where you know your IP address does not
|
||||||
// change. See AsyncUDPSocket::connect for the caveats.
|
// change. See AsyncUDPSocket::connect for the caveats.
|
||||||
bool connectUDP{false};
|
bool connectUDP{false};
|
||||||
// Maximum number of consecutive RTOs before the connection is torn down.
|
// Maximum number of consecutive PTOs before the connection is torn down.
|
||||||
uint16_t maxNumRTOs{kDefaultMaxNumRTO};
|
uint16_t maxNumPTOs{kDefaultMaxNumPTO};
|
||||||
// Whether to turn off PMTUD on the socket
|
// Whether to turn off PMTUD on the socket
|
||||||
bool turnoffPMTUD{false};
|
bool turnoffPMTUD{false};
|
||||||
// Whether to listen to socket error
|
// Whether to listen to socket error
|
||||||
|
@@ -425,7 +425,7 @@ TEST_P(AckHandlersTest, NoNewAckedPacket) {
|
|||||||
auto rawController = mockController.get();
|
auto rawController = mockController.get();
|
||||||
conn.congestionController = std::move(mockController);
|
conn.congestionController = std::move(mockController);
|
||||||
|
|
||||||
conn.lossState.rtoCount = 1;
|
conn.lossState.ptoCount = 1;
|
||||||
PacketNum packetAfterRtoNum = 10;
|
PacketNum packetAfterRtoNum = 10;
|
||||||
auto packetAfterRto = createNewPacket(packetAfterRtoNum, GetParam());
|
auto packetAfterRto = createNewPacket(packetAfterRtoNum, GetParam());
|
||||||
conn.outstandingPackets.emplace_back(OutstandingPacket(
|
conn.outstandingPackets.emplace_back(OutstandingPacket(
|
||||||
@@ -442,7 +442,7 @@ TEST_P(AckHandlersTest, NoNewAckedPacket) {
|
|||||||
[](auto&, auto&, bool, PacketNum) {},
|
[](auto&, auto&, bool, PacketNum) {},
|
||||||
Clock::now());
|
Clock::now());
|
||||||
EXPECT_TRUE(conn.pendingEvents.setLossDetectionAlarm);
|
EXPECT_TRUE(conn.pendingEvents.setLossDetectionAlarm);
|
||||||
EXPECT_EQ(conn.lossState.rtoCount, 1);
|
EXPECT_EQ(conn.lossState.ptoCount, 1);
|
||||||
EXPECT_EQ(conn.ackStates.appDataAckState.largestAckedByPeer, 0);
|
EXPECT_EQ(conn.ackStates.appDataAckState.largestAckedByPeer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user