1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-06 22:22:38 +03:00

Always send flow control updates again when lost.

Summary: This was probably a premature optimization and introduces complexity for dubious gain. Additionally a sequence of losses could potentially cause multiple updates to be delayed.

Reviewed By: yangchi

Differential Revision: D23628058

fbshipit-source-id: d6cf70baec8c34f0209ea791dadc724795fe0c21
This commit is contained in:
Matt Joras
2020-09-10 14:57:26 -07:00
committed by Facebook GitHub Bot
parent ac705d0b71
commit 325a6465ec
17 changed files with 127 additions and 263 deletions

View File

@@ -575,8 +575,7 @@ void updateConnection(
VLOG(10) << nodeToString(conn.nodeType)
<< " sent conn window update in packetNum=" << packetNum << " "
<< conn;
onConnWindowUpdateSent(
conn, packetNum, maxDataFrame.maximumData, sentTime);
onConnWindowUpdateSent(conn, maxDataFrame.maximumData, sentTime);
break;
}
case QuicWriteFrame::Type::DataBlockedFrame_E: {
@@ -597,7 +596,7 @@ void updateConnection(
<< " sent packet with window update packetNum=" << packetNum
<< " stream=" << maxStreamDataFrame.streamId << " " << conn;
onStreamWindowUpdateSent(
*stream, packetNum, maxStreamDataFrame.maximumData, sentTime);
*stream, maxStreamDataFrame.maximumData, sentTime);
break;
}
case QuicWriteFrame::Type::StreamDataBlockedFrame_E: {
@@ -1461,7 +1460,7 @@ void implicitAckCryptoStream(
},
// We shouldn't mark anything as lost from the implicit ACK, as it should
// be ACKing the entire rangee.
[](auto&, auto&, auto, auto) {
[](auto&, auto&, auto) {
LOG(FATAL) << "Got loss from implicit crypto ACK.";
},
implicitAckTime);

View File

@@ -2292,17 +2292,14 @@ TEST_F(QuicTransportImplTest, AsyncStreamFlowControlWrite) {
auto stream = transport->createBidirectionalStream().value();
auto streamState = transport->transportConn->streamManager->getStream(stream);
transport->setServerConnectionId();
EXPECT_FALSE(streamState->latestMaxStreamDataPacket.has_value());
transport->writeLooper()->stop();
streamState->flowControlState.advertisedMaxOffset = 0; // Easier to calculate
transport->setStreamFlowControlWindow(stream, 4000);
EXPECT_EQ(0, streamState->flowControlState.advertisedMaxOffset);
EXPECT_FALSE(streamState->latestMaxStreamDataPacket.has_value());
// Loop it:
EXPECT_TRUE(transport->writeLooper()->isRunning());
transport->writeLooper()->runLoopCallback();
EXPECT_EQ(4000, streamState->flowControlState.advertisedMaxOffset);
EXPECT_TRUE(streamState->latestMaxStreamDataPacket.has_value());
}
TEST_F(QuicTransportImplTest, ExceptionInWriteLooperDoesNotCrash) {

View File

@@ -1023,7 +1023,6 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionStreamWindowUpdate) {
auto conn = createConn();
conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
auto packetNum = packet.packet.header.getPacketSequenceNum();
auto stream = conn->streamManager->createNextBidirectionalStream().value();
MaxStreamDataFrame streamWindowUpdate(stream->id, 0);
conn->streamManager->queueWindowUpdate(stream->id);
@@ -1049,18 +1048,13 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionStreamWindowUpdate) {
auto frame = static_cast<MaxStreamDataFrameLog*>(event->frames[0].get());
EXPECT_EQ(frame->streamId, stream->id);
EXPECT_EQ(frame->maximumData, 0);
EXPECT_EQ(packetNum, *stream->latestMaxStreamDataPacket);
EXPECT_FALSE(conn->latestMaxDataPacket.has_value());
}
TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionConnWindowUpdate) {
auto conn = createConn();
conn->qLogger = std::make_shared<quic::FileQLogger>(VantagePoint::Client);
auto packet = buildEmptyPacket(*conn, PacketNumberSpace::Handshake);
auto packetNum = packet.packet.header.getPacketSequenceNum();
conn->pendingEvents.connWindowUpdate = true;
auto stream = conn->streamManager->createNextBidirectionalStream().value();
MaxDataFrame connWindowUpdate(conn->flowControlState.advertisedMaxOffset);
packet.packet.frames.push_back(std::move(connWindowUpdate));
updateConnection(
@@ -1082,9 +1076,6 @@ TEST_F(QuicTransportFunctionsTest, TestUpdateConnectionConnWindowUpdate) {
EXPECT_EQ(event->frames.size(), 1);
auto frame = static_cast<MaxDataFrameLog*>(event->frames[0].get());
EXPECT_EQ(frame->maximumData, conn->flowControlState.advertisedMaxOffset);
EXPECT_FALSE(stream->latestMaxStreamDataPacket.has_value());
EXPECT_EQ(packetNum, *conn->latestMaxDataPacket);
}
TEST_F(QuicTransportFunctionsTest, WriteQuicDataToSocketWithCC) {

View File

@@ -1196,7 +1196,7 @@ TEST_F(QuicTransportTest, ResendPathChallengeOnLoss) {
->packet;
EXPECT_FALSE(conn.pendingEvents.pathChallenge);
markPacketLoss(conn, packet, false, 2);
markPacketLoss(conn, packet, false);
EXPECT_EQ(*conn.pendingEvents.pathChallenge, pathChallenge);
}
@@ -1221,7 +1221,7 @@ TEST_F(QuicTransportTest, DoNotResendLostPathChallengeIfNotOutstanding) {
transport_->getPathValidationTimeout().timeoutExpired();
EXPECT_FALSE(conn.pendingEvents.pathChallenge);
markPacketLoss(conn, packet, false, 2);
markPacketLoss(conn, packet, false);
EXPECT_FALSE(conn.pendingEvents.pathChallenge);
}
@@ -1332,7 +1332,7 @@ TEST_F(QuicTransportTest, DoNotResendPathResponseOnLoss) {
auto packet =
getLastOutstandingPacket(conn, PacketNumberSpace::AppData)->packet;
markPacketLoss(conn, packet, false, 2);
markPacketLoss(conn, packet, false);
EXPECT_EQ(conn.pendingEvents.frames.size(), 0);
}
@@ -1469,7 +1469,7 @@ TEST_F(QuicTransportTest, ResendNewConnectionIdOnLoss) {
->packet;
EXPECT_TRUE(conn.pendingEvents.frames.empty());
markPacketLoss(conn, packet, false, 2);
markPacketLoss(conn, packet, false);
EXPECT_EQ(conn.pendingEvents.frames.size(), 1);
NewConnectionIdFrame* connIdFrame =
conn.pendingEvents.frames.front().asNewConnectionIdFrame();
@@ -1557,7 +1557,7 @@ TEST_F(QuicTransportTest, ResendRetireConnectionIdOnLoss) {
->packet;
EXPECT_TRUE(conn.pendingEvents.frames.empty());
markPacketLoss(conn, packet, false, 2);
markPacketLoss(conn, packet, false);
EXPECT_EQ(conn.pendingEvents.frames.size(), 1);
RetireConnectionIdFrame* retireFrame =
conn.pendingEvents.frames.front().asRetireConnectionIdFrame();

View File

@@ -553,7 +553,7 @@ TEST_F(BbrTest, BytesCounting) {
ackFrame.largestAcked = packetNum;
ackFrame.ackBlocks.emplace_back(packetNum, packetNum);
auto ackVisitor = [&](auto&, auto&, auto&) {};
auto lossVisitor = [&](auto&, auto&, bool, PacketNum) {};
auto lossVisitor = [&](auto&, auto&, bool) {};
processAckFrame(
conn,
PacketNumberSpace::AppData,

View File

@@ -4706,8 +4706,7 @@ TEST_F(QuicClientTransportAfterStartTest, ResetClearsPendingLoss) {
RegularQuicWritePacket* forceLossPacket =
CHECK_NOTNULL(findPacketWithStream(client->getNonConstConn(), streamId));
auto packetNum = forceLossPacket->header.getPacketSequenceNum();
markPacketLoss(client->getNonConstConn(), *forceLossPacket, false, packetNum);
markPacketLoss(client->getNonConstConn(), *forceLossPacket, false);
auto& pendingLossStreams = client->getConn().streamManager->lossStreams();
auto it =
std::find(pendingLossStreams.begin(), pendingLossStreams.end(), streamId);
@@ -4733,8 +4732,7 @@ TEST_F(QuicClientTransportAfterStartTest, LossAfterResetStream) {
RegularQuicWritePacket* forceLossPacket =
CHECK_NOTNULL(findPacketWithStream(client->getNonConstConn(), streamId));
auto packetNum = forceLossPacket->header.getPacketSequenceNum();
markPacketLoss(client->getNonConstConn(), *forceLossPacket, false, packetNum);
markPacketLoss(client->getNonConstConn(), *forceLossPacket, false);
auto stream = CHECK_NOTNULL(
client->getNonConstConn().streamManager->getStream(streamId));
ASSERT_TRUE(stream->lossBuffer.empty());

View File

@@ -362,12 +362,9 @@ uint64_t getRecvConnFlowControlBytes(const QuicConnectionStateBase& conn) {
void onConnWindowUpdateSent(
QuicConnectionStateBase& conn,
PacketNum packetNum,
uint64_t maximumDataSent,
TimePoint sentTime) {
DCHECK_GE(maximumDataSent, conn.flowControlState.advertisedMaxOffset);
DCHECK_LE(conn.latestMaxDataPacket.value_or(packetNum), packetNum);
conn.latestMaxDataPacket = packetNum;
conn.flowControlState.advertisedMaxOffset = maximumDataSent;
conn.flowControlState.timeOfLastFlowControlUpdate = sentTime;
conn.pendingEvents.connWindowUpdate = false;
@@ -376,11 +373,8 @@ void onConnWindowUpdateSent(
void onStreamWindowUpdateSent(
QuicStreamState& stream,
PacketNum packetNum,
uint64_t maximumDataSent,
TimePoint sentTime) {
DCHECK_LE(stream.latestMaxStreamDataPacket.value_or(packetNum), packetNum);
stream.latestMaxStreamDataPacket = packetNum;
stream.flowControlState.advertisedMaxOffset = maximumDataSent;
stream.flowControlState.timeOfLastFlowControlUpdate = sentTime;
stream.conn.streamManager->removeWindowUpdate(stream.id);

View File

@@ -60,13 +60,11 @@ void handleConnBlocked(QuicConnectionStateBase& conn);
void onStreamWindowUpdateSent(
QuicStreamState& stream,
PacketNum packetNum,
uint64_t maximumData,
TimePoint sentTime);
void onConnWindowUpdateSent(
QuicConnectionStateBase& conn,
PacketNum pacektNum,
uint64_t maximumData,
TimePoint sentTime);

View File

@@ -157,21 +157,13 @@ TEST_F(QuicFlowControlTest, GenerateMaxDataFrameChangeWindowLarger) {
conn_.flowControlState.sumCurReadOffset = 301;
auto frame = generateMaxDataFrame(conn_);
EXPECT_EQ(801, frame.maximumData);
onConnWindowUpdateSent(
conn_,
conn_.ackStates.appDataAckState.nextPacketNum,
frame.maximumData,
Clock::now());
onConnWindowUpdateSent(conn_, frame.maximumData, Clock::now());
EXPECT_EQ(801, conn_.flowControlState.advertisedMaxOffset);
conn_.flowControlState.windowSize = 1001;
auto frame2 = generateMaxDataFrame(conn_);
EXPECT_EQ(1302, frame2.maximumData);
onConnWindowUpdateSent(
conn_,
conn_.ackStates.appDataAckState.nextPacketNum,
frame2.maximumData,
Clock::now());
onConnWindowUpdateSent(conn_, frame2.maximumData, Clock::now());
EXPECT_EQ(
frame2.maximumData,
conn_.flowControlState.sumCurReadOffset +
@@ -262,13 +254,7 @@ TEST_F(QuicFlowControlTest, MaybeSendStreamWindowUpdateChangeWindowSmaller) {
ASSERT_TRUE(conn_.streamManager->pendingWindowUpdate(stream.id));
auto sendTime = Clock::now();
onStreamWindowUpdateSent(
stream,
conn_.ackStates.appDataAckState.nextPacketNum,
generateMaxStreamDataFrame(stream).maximumData,
sendTime);
EXPECT_EQ(
conn_.ackStates.appDataAckState.nextPacketNum,
*stream.latestMaxStreamDataPacket);
stream, generateMaxStreamDataFrame(stream).maximumData, sendTime);
stream.flowControlState.windowSize = 10;
// change the read bytes to be within the maybeSendUpdate size of the previous
@@ -346,13 +332,7 @@ TEST_F(QuicFlowControlTest, MaybeSendStreamWindowUpdateChangeWindowLarger) {
maybeSendStreamWindowUpdate(stream, Clock::now());
EXPECT_TRUE(conn_.streamManager->pendingWindowUpdate(stream.id));
onStreamWindowUpdateSent(
stream,
conn_.ackStates.appDataAckState.nextPacketNum,
generateMaxStreamDataFrame(stream).maximumData,
Clock::now());
EXPECT_EQ(
conn_.ackStates.appDataAckState.nextPacketNum,
*stream.latestMaxStreamDataPacket);
stream, generateMaxStreamDataFrame(stream).maximumData, Clock::now());
EXPECT_FALSE(conn_.streamManager->pendingWindowUpdate(stream.id));
stream.flowControlState.windowSize = 1001;
@@ -378,14 +358,7 @@ TEST_F(QuicFlowControlTest, SendingConnectionWindowUpdate) {
// Clear out the window update.
auto sendTime = Clock::now();
onConnWindowUpdateSent(
conn_,
conn_.ackStates.appDataAckState.nextPacketNum,
frameOffset,
sendTime);
EXPECT_EQ(
conn_.ackStates.appDataAckState.nextPacketNum,
*conn_.latestMaxDataPacket);
onConnWindowUpdateSent(conn_, frameOffset, sendTime);
EXPECT_FALSE(conn_.pendingEvents.connWindowUpdate);
EXPECT_EQ(conn_.flowControlState.advertisedMaxOffset, frameOffset);
EXPECT_EQ(*conn_.flowControlState.timeOfLastFlowControlUpdate, sendTime);
@@ -406,14 +379,7 @@ TEST_F(QuicFlowControlTest, SendingStreamWindowUpdate) {
EXPECT_EQ(800, frameOffset);
auto sendTime = Clock::now();
onStreamWindowUpdateSent(
stream,
conn_.ackStates.appDataAckState.nextPacketNum,
frameOffset,
sendTime);
EXPECT_EQ(
conn_.ackStates.appDataAckState.nextPacketNum,
*stream.latestMaxStreamDataPacket);
onStreamWindowUpdateSent(stream, frameOffset, sendTime);
EXPECT_FALSE(conn_.streamManager->pendingWindowUpdate(stream.id));
EXPECT_EQ(stream.flowControlState.advertisedMaxOffset, frameOffset);
EXPECT_EQ(*stream.flowControlState.timeOfLastFlowControlUpdate, sendTime);
@@ -844,11 +810,7 @@ TEST_F(QuicFlowControlTest, OnConnWindowUpdateSentWithoutPendingEvent) {
conn_.flowControlState.windowSize = 1000;
conn_.flowControlState.advertisedMaxOffset = 0;
conn_.flowControlState.sumCurReadOffset = 0;
onConnWindowUpdateSent(
conn_, conn_.ackStates.appDataAckState.nextPacketNum, 1000, Clock::now());
EXPECT_EQ(
conn_.ackStates.appDataAckState.nextPacketNum,
*conn_.latestMaxDataPacket);
onConnWindowUpdateSent(conn_, 1000, Clock::now());
EXPECT_EQ(1000, conn_.flowControlState.advertisedMaxOffset);
EXPECT_FALSE(conn_.pendingEvents.connWindowUpdate);
}
@@ -859,14 +821,7 @@ TEST_F(QuicFlowControlTest, OnStreamWindowUpdateSentWithoutPendingEvent) {
stream.currentReadOffset = 0;
stream.flowControlState.advertisedMaxOffset = 0;
stream.flowControlState.windowSize = 1000;
onStreamWindowUpdateSent(
stream,
conn_.ackStates.appDataAckState.nextPacketNum,
1000,
Clock::now());
EXPECT_EQ(
conn_.ackStates.appDataAckState.nextPacketNum,
*stream.latestMaxStreamDataPacket);
onStreamWindowUpdateSent(stream, 1000, Clock::now());
EXPECT_EQ(1000, stream.flowControlState.advertisedMaxOffset);
EXPECT_FALSE(conn_.streamManager->pendingWindowUpdate(id));
}

View File

@@ -63,8 +63,7 @@ void onPTOAlarm(QuicConnectionStateBase& conn) {
void markPacketLoss(
QuicConnectionStateBase& conn,
RegularQuicWritePacket& packet,
bool processed,
PacketNum currentPacketNum) {
bool processed) {
QUIC_STATS(conn.statsCallback, onPacketLoss);
for (auto& packetFrame : packet.frames) {
switch (packetFrame.type()) {
@@ -72,26 +71,19 @@ void markPacketLoss(
MaxStreamDataFrame& frame = *packetFrame.asMaxStreamDataFrame();
// For all other frames, we process it if it's not from a clone
// packet, or if the clone and its siblings have never been processed.
// But for both MaxData and MaxStreamData, clone and its siblings may
// have different values. So we process it if it matches the
// latestMaxDataPacket or latestMaxStreamDataPacket. If an older
// packet also has such frames, it's ok to skip process of such loss
// since newer value is already sent in later packets.
// But for both MaxData and MaxStreamData, we opportunistically send
// an update to avoid stalling the peer.
auto stream = conn.streamManager->getStream(frame.streamId);
if (!stream) {
break;
}
// TODO: check for the stream is in Open or HalfClosedLocal state, the
// peer doesn't need a flow control update in these cases.
if (stream->latestMaxStreamDataPacket == currentPacketNum) {
onStreamWindowUpdateLost(*stream);
}
break;
}
case QuicWriteFrame::Type::MaxDataFrame_E: {
if (conn.latestMaxDataPacket == currentPacketNum) {
onConnWindowUpdateLost(conn);
}
break;
}
// For other frame types, we only process them if the packet is not a

View File

@@ -236,7 +236,7 @@ folly::Optional<CongestionController::LossEvent> detectLossPackets(
// or if the PacketEvent is present in conn.outstandings.packetEvents.
bool processed = pkt.associatedEvent &&
!conn.outstandings.packetEvents.count(*pkt.associatedEvent);
lossVisitor(conn, pkt.packet, processed, currentPacketNum);
lossVisitor(conn, pkt.packet, processed);
// Remove the PacketEvent from the outstandings.packetEvents set
if (pkt.associatedEvent) {
conn.outstandings.packetEvents.erase(*pkt.associatedEvent);
@@ -354,8 +354,7 @@ void onLossDetectionAlarm(
void markPacketLoss(
QuicConnectionStateBase& conn,
RegularQuicWritePacket& packet,
bool processed,
PacketNum currentPacketNum);
bool processed);
template <class LossVisitor>
folly::Optional<CongestionController::LossEvent> handleAckForLoss(
@@ -408,10 +407,9 @@ void markZeroRttPacketsLost(
if (isZeroRttPacket) {
auto& pkt = *iter;
DCHECK(!pkt.isHandshake);
auto currentPacketNum = pkt.packet.header.getPacketSequenceNum();
bool processed = pkt.associatedEvent &&
!conn.outstandings.packetEvents.count(*pkt.associatedEvent);
lossVisitor(conn, pkt.packet, processed, currentPacketNum);
lossVisitor(conn, pkt.packet, processed);
// Remove the PacketEvent from the outstandings.packetEvents set
if (pkt.associatedEvent) {
conn.outstandings.packetEvents.erase(*pkt.associatedEvent);

View File

@@ -124,8 +124,7 @@ class QuicLossFunctionsTest : public TestWithParam<PacketNumberSpace> {
};
auto testingLossMarkFunc(std::vector<PacketNum>& lostPackets) {
return [&lostPackets](
auto& /* conn */, auto& packet, bool processed, PacketNum) {
return [&lostPackets](auto& /* conn */, auto& packet, bool processed) {
if (!processed) {
auto packetNum = packet.header.getPacketSequenceNum();
lostPackets.push_back(packetNum);
@@ -279,7 +278,7 @@ TEST_F(QuicLossFunctionsTest, ClearEarlyRetranTimer) {
ASSERT_GT(secondPacketNum, firstPacketNum);
ASSERT_EQ(2, conn->outstandings.packets.size());
// detectLossPackets will set lossTime on Initial space.
auto lossVisitor = [](auto&, auto&, bool, PacketNum) { ASSERT_FALSE(true); };
auto lossVisitor = [](auto&, auto&, bool) { ASSERT_FALSE(true); };
detectLossPackets(
*conn,
secondPacketNum,
@@ -420,8 +419,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLoss) {
EXPECT_EQ(1, conn->outstandings.packets.size());
auto& packet =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet.header.getPacketSequenceNum();
markPacketLoss(*conn, packet, false, packetNum);
markPacketLoss(*conn, packet, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 0);
EXPECT_EQ(stream2->retransmissionBuffer.size(), 0);
EXPECT_EQ(stream1->lossBuffer.size(), 1);
@@ -471,13 +469,13 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossMerge) {
auto& packet1 =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet1.header.getPacketSequenceNum();
markPacketLoss(*conn, packet1, false, packetNum);
markPacketLoss(*conn, packet1, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
EXPECT_EQ(stream1->lossBuffer.size(), 1);
auto& packet2 =
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
packetNum = packet2.header.getPacketSequenceNum();
markPacketLoss(*conn, packet2, false, packetNum);
markPacketLoss(*conn, packet2, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 0);
EXPECT_EQ(stream1->lossBuffer.size(), 1);
@@ -540,13 +538,13 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossNoMerge) {
auto& packet1 =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet1.header.getPacketSequenceNum();
markPacketLoss(*conn, packet1, false, packetNum);
markPacketLoss(*conn, packet1, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 2);
EXPECT_EQ(stream1->lossBuffer.size(), 1);
auto& packet3 =
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
packetNum = packet3.header.getPacketSequenceNum();
markPacketLoss(*conn, packet3, false, packetNum);
markPacketLoss(*conn, packet3, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
EXPECT_EQ(stream1->lossBuffer.size(), 2);
@@ -592,8 +590,7 @@ TEST_F(QuicLossFunctionsTest, RetxBufferSortedAfterLoss) {
EXPECT_EQ(3, stream->retransmissionBuffer.size());
EXPECT_EQ(3, conn->outstandings.packets.size());
auto packet = conn->outstandings.packets[folly::Random::rand32() % 3];
markPacketLoss(
*conn, packet.packet, false, packet.packet.header.getPacketSequenceNum());
markPacketLoss(*conn, packet.packet, false);
EXPECT_EQ(2, stream->retransmissionBuffer.size());
}
@@ -624,9 +621,8 @@ TEST_F(QuicLossFunctionsTest, TestMarkCryptoLostAfterCancelRetransmission) {
ASSERT_EQ(conn->outstandings.packets.size(), 1);
EXPECT_GT(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
auto& packet = conn->outstandings.packets.front().packet;
auto packetNum = packet.header.getPacketSequenceNum();
cancelHandshakeCryptoStreamRetransmissions(*conn->cryptoState);
markPacketLoss(*conn, packet, false, packetNum);
markPacketLoss(*conn, packet, false);
EXPECT_EQ(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
EXPECT_EQ(conn->cryptoState->handshakeStream.lossBuffer.size(), 0);
}
@@ -658,8 +654,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkCryptoLostCancel) {
ASSERT_EQ(conn->outstandings.packets.size(), 1);
EXPECT_GT(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
auto& packet = conn->outstandings.packets.front().packet;
auto packetNum = packet.header.getPacketSequenceNum();
markPacketLoss(*conn, packet, false, packetNum);
markPacketLoss(*conn, packet, false);
EXPECT_EQ(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
EXPECT_EQ(conn->cryptoState->handshakeStream.lossBuffer.size(), 1);
cancelHandshakeCryptoStreamRetransmissions(*conn->cryptoState);
@@ -684,7 +679,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossAfterStreamReset) {
true);
sendRstSMHandler(*stream1, GenericApplicationErrorCode::UNKNOWN);
markPacketLoss(*conn, packet, false, packet.header.getPacketSequenceNum());
markPacketLoss(*conn, packet, false);
EXPECT_TRUE(stream1->lossBuffer.empty());
EXPECT_TRUE(stream1->retransmissionBuffer.empty());
@@ -701,8 +696,7 @@ TEST_F(QuicLossFunctionsTest, TestReorderingThreshold) {
EXPECT_CALL(*rawCongestionController, onPacketSent(_))
.WillRepeatedly(Return());
auto testingLossMarkFunc =
[&lostPacket](auto& /*conn*/, auto& packet, bool, PacketNum) {
auto testingLossMarkFunc = [&lostPacket](auto& /*conn*/, auto& packet, bool) {
auto packetNum = packet.header.getPacketSequenceNum();
lostPacket.push_back(packetNum);
};
@@ -771,7 +765,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckForLoss) {
OutstandingPacket(outstandingRegularPacket, now, 0, false, 0));
bool testLossMarkFuncCalled = false;
auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool, PacketNum) {
auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool) {
testLossMarkFuncCalled = true;
};
EXPECT_CALL(*mockQLogger, addPacketsLost(1, 0, 1));
@@ -809,7 +803,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckedPacket) {
conn->lossState.largestSent.value_or(0));
bool testLossMarkFuncCalled = false;
auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool, PacketNum) {
auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool) {
testLossMarkFuncCalled = true;
};
@@ -858,7 +852,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkRstLoss) {
EXPECT_TRUE(conn->pendingEvents.resets.empty());
auto& packet =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
markPacketLoss(*conn, packet, false, packet.header.getPacketSequenceNum());
markPacketLoss(*conn, packet, false);
EXPECT_EQ(1, conn->pendingEvents.resets.size());
EXPECT_EQ(1, conn->pendingEvents.resets.count(stream->id));
@@ -897,10 +891,8 @@ TEST_F(QuicLossFunctionsTest, TestMarkRstLoss) {
TEST_F(QuicLossFunctionsTest, ReorderingThresholdChecksSamePacketNumberSpace) {
auto conn = createConn();
uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool processed,
PacketNum /* currentPacketNum */) {
auto countingLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool processed) {
if (!processed) {
lossVisitorCount++;
}
@@ -950,8 +942,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkWindowUpdateLoss) {
auto& packet =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet.header.getPacketSequenceNum();
markPacketLoss(*conn, packet, false, packetNum);
markPacketLoss(*conn, packet, false);
EXPECT_TRUE(conn->streamManager->pendingWindowUpdate(stream->id));
}
@@ -1178,10 +1169,8 @@ TEST_F(QuicLossFunctionsTest, NoSkipLossVisitor) {
// make srtt large so delayUntilLost won't kick in
conn->lossState.srtt = 1000000000us;
uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool processed,
PacketNum /* currentPacketNum */) {
auto countingLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool processed) {
if (!processed) {
lossVisitorCount++;
}
@@ -1206,10 +1195,8 @@ TEST_F(QuicLossFunctionsTest, SkipLossVisitor) {
// make srtt large so delayUntilLost won't kick in
conn->lossState.srtt = 1000000000us;
uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool processed,
PacketNum /* currentPacketNum */) {
auto countingLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool processed) {
if (!processed) {
lossVisitorCount++;
}
@@ -1237,10 +1224,8 @@ TEST_F(QuicLossFunctionsTest, NoDoubleProcess) {
conn->lossState.srtt = 1000000000us;
uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool processed,
PacketNum /* currentPacketNum */) {
auto countingLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool processed) {
if (!processed) {
lossVisitorCount++;
}
@@ -1283,7 +1268,7 @@ TEST_F(QuicLossFunctionsTest, DetectPacketLossClonedPacketsCounter) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt);
auto ackedPacket =
sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt);
auto noopLossMarker = [](auto&, auto&, bool, PacketNum) {};
auto noopLossMarker = [](auto&, auto&, bool) {};
detectLossPackets<decltype(noopLossMarker)>(
*conn,
ackedPacket,
@@ -1305,7 +1290,6 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
conn->streamManager->createNextBidirectionalStream().value()->id;
conn->streamManager->queueWindowUpdate(stream2Id);
conn->pendingEvents.connWindowUpdate = true;
auto nextPacketNum = conn->ackStates.appDataAckState.nextPacketNum;
// writeQuicPacket will call writeQuicDataToSocket which will also take care
// of sending the MaxStreamDataFrame for stream2
auto stream1 = conn->streamManager->findStream(stream1Id);
@@ -1345,7 +1329,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
EXPECT_EQ(1, streamWindowUpdateCounter);
EXPECT_EQ(1, connWindowUpdateCounter);
// Force this packet to be a processed clone
markPacketLoss(*conn, packet, true, nextPacketNum);
markPacketLoss(*conn, packet, true);
EXPECT_EQ(1, stream1->retransmissionBuffer.size());
EXPECT_TRUE(stream1->lossBuffer.empty());
@@ -1389,10 +1373,8 @@ TEST_F(QuicLossFunctionsTest, TotalLossCount) {
}
EXPECT_EQ(10, conn->outstandings.packets.size());
uint32_t lostPackets = 0;
auto countingLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool processed,
PacketNum /* currentPacketNum */) {
auto countingLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool processed) {
if (!processed) {
lostPackets++;
}
@@ -1423,17 +1405,16 @@ TEST_F(QuicLossFunctionsTest, TestZeroRttRejected) {
}
EXPECT_FALSE(conn->outstandings.packets.empty());
EXPECT_EQ(4, conn->outstandings.packets.size());
std::vector<std::pair<PacketNum, bool>> lostPackets;
std::vector<bool> lostPackets;
// onRemoveBytesFromInflight should still happen
EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(1);
markZeroRttPacketsLost(
*conn, [&lostPackets](auto&, auto&, bool processed, PacketNum packetNum) {
lostPackets.emplace_back(packetNum, processed);
markZeroRttPacketsLost(*conn, [&lostPackets](auto&, auto&, bool processed) {
lostPackets.emplace_back(processed);
});
EXPECT_EQ(2, conn->outstandings.packets.size());
EXPECT_EQ(lostPackets.size(), 2);
for (auto lostPacket : lostPackets) {
EXPECT_FALSE(lostPacket.second);
EXPECT_FALSE(lostPacket);
}
for (size_t i = 0; i < conn->outstandings.packets.size(); ++i) {
auto longHeader = conn->outstandings.packets[i].packet.header.asLong();
@@ -1473,12 +1454,11 @@ TEST_F(QuicLossFunctionsTest, TestZeroRttRejectedWithClones) {
ASSERT_EQ(conn->outstandings.clonedPacketsCount, 6);
ASSERT_EQ(conn->outstandings.packetEvents.size(), 2);
std::vector<std::pair<PacketNum, bool>> lostPackets;
std::vector<bool> lostPackets;
// onRemoveBytesFromInflight should still happen
EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(1);
markZeroRttPacketsLost(
*conn, [&lostPackets](auto&, auto&, bool processed, PacketNum packetNum) {
lostPackets.emplace_back(packetNum, processed);
markZeroRttPacketsLost(*conn, [&lostPackets](auto&, auto&, bool processed) {
lostPackets.emplace_back(processed);
});
ASSERT_EQ(conn->outstandings.packetEvents.size(), 0);
EXPECT_EQ(3, conn->outstandings.packets.size());
@@ -1486,7 +1466,7 @@ TEST_F(QuicLossFunctionsTest, TestZeroRttRejectedWithClones) {
ASSERT_EQ(conn->outstandings.clonedPacketsCount, 3);
size_t numProcessed = 0;
for (auto lostPacket : lostPackets) {
numProcessed += lostPacket.second;
numProcessed += lostPacket;
}
EXPECT_EQ(numProcessed, 1);
for (size_t i = 0; i < conn->outstandings.packets.size(); ++i) {
@@ -1521,11 +1501,8 @@ TEST_F(QuicLossFunctionsTest, TimeThreshold) {
referenceTime + conn->lossState.srtt / 2,
folly::none,
PacketType::OneRtt);
auto lossVisitor = [&](const auto& /*conn*/,
const auto& /*packet*/,
bool,
PacketNum packetNum) {
EXPECT_EQ(packet1, packetNum);
auto lossVisitor = [&](const auto& /*conn*/, const auto& packet, bool) {
EXPECT_EQ(packet1, packet.header.getPacketSequenceNum());
};
detectLossPackets<decltype(lossVisitor)>(
*conn,
@@ -1545,10 +1522,9 @@ TEST_F(QuicLossFunctionsTest, OutstandingInitialCounting) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::Initial);
}
EXPECT_EQ(10, conn->outstandings.initialPacketsCount);
auto noopLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool /* processed */,
PacketNum /* currentPacketNum */) {};
auto noopLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool /* processed */
) {};
detectLossPackets(
*conn,
largestSent,
@@ -1569,10 +1545,9 @@ TEST_F(QuicLossFunctionsTest, OutstandingHandshakeCounting) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::Handshake);
}
EXPECT_EQ(10, conn->outstandings.handshakePacketsCount);
auto noopLossVisitor = [&](auto& /* conn */,
auto& /* packet */,
bool /* processed */,
PacketNum /* currentPacketNum */) {};
auto noopLossVisitor =
[&](auto& /* conn */, auto& /* packet */, bool /* processed */
) {};
detectLossPackets(
*conn,
largestSent,

View File

@@ -1733,11 +1733,7 @@ TEST_F(QuicServerTransportTest, StopSendingLoss) {
ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket();
markPacketLoss(
server->getNonConstConn(),
packet.packet,
false,
clientNextAppDataPacketNum);
markPacketLoss(server->getNonConstConn(), packet.packet, false);
EXPECT_EQ(server->getNonConstConn().pendingEvents.frames.size(), 1);
StopSendingFrame* stopFrame = server->getNonConstConn()
.pendingEvents.frames.front()
@@ -1769,11 +1765,7 @@ TEST_F(QuicServerTransportTest, StopSendingLossAfterStreamClosed) {
// clear out all the streams, this is not a great way to simulate closed
// streams, but good enough for this test.
server->getNonConstConn().streamManager->clearOpenStreams();
markPacketLoss(
server->getNonConstConn(),
packet.packet,
false,
server->getNonConstConn().ackStates.appDataAckState.nextPacketNum);
markPacketLoss(server->getNonConstConn(), packet.packet, false);
EXPECT_EQ(server->getNonConstConn().pendingEvents.frames.size(), 0);
}

View File

@@ -19,7 +19,7 @@ using AckVisitor = std::function<
void(const OutstandingPacket&, const QuicWriteFrame&, const ReadAckFrame&)>;
using LossVisitor = std::function<
void(QuicConnectionStateBase&, RegularQuicWritePacket&, bool, PacketNum)>;
void(QuicConnectionStateBase&, RegularQuicWritePacket&, bool)>;
/**
* Processes an ack frame and removes any outstanding packets

View File

@@ -757,10 +757,6 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
PacketSchedulingState schedulingState;
// The packet number of the latest packet that contains a MaxDataFrame sent
// out by us.
folly::Optional<PacketNum> latestMaxDataPacket;
// Logger for this connection.
std::shared_ptr<Logger> logger;

View File

@@ -193,10 +193,6 @@ struct QuicStreamState : public QuicStreamLike {
// State machine data
StreamRecvState recvState{StreamRecvState::Open_E};
// The packet number of the latest packet that contains a MaxStreamDataFrame
// sent out by us.
folly::Optional<PacketNum> latestMaxStreamDataPacket;
// Tells whether this stream is a control stream.
// It is set by the app via setControlStream and the transport can use this
// knowledge for optimizations e.g. for setting the app limited state on

View File

@@ -28,8 +28,7 @@ namespace test {
class AckHandlersTest : public TestWithParam<PacketNumberSpace> {};
auto testLossHandler(std::vector<PacketNum>& lostPackets) -> decltype(auto) {
return
[&lostPackets](QuicConnectionStateBase&, auto& packet, bool, PacketNum) {
return [&lostPackets](QuicConnectionStateBase&, auto& packet, bool) {
auto packetNum = packet.header.getPacketSequenceNum();
lostPackets.push_back(packetNum);
};
@@ -214,7 +213,7 @@ TEST_P(AckHandlersTest, TestAckMultipleSequentialBlocksLoss) {
GetParam(),
ackFrame,
[](auto, auto, auto) {},
[](auto&, auto&, auto, auto) {},
[](auto&, auto&, auto) {},
Clock::now());
itr = std::find_if(
conn.outstandings.packets.begin(),
@@ -231,7 +230,7 @@ TEST_P(AckHandlersTest, TestAckMultipleSequentialBlocksLoss) {
GetParam(),
ackFrame,
[](auto, auto, auto) {},
[](auto&, auto&, auto, auto) {},
[](auto&, auto&, auto) {},
Clock::now() + 2 * calculatePTO(conn));
numDeclaredLost = std::count_if(
@@ -477,10 +476,8 @@ TEST_P(AckHandlersTest, AckVisitorForAckTest) {
commonAckVisitorForAckFrame(conn.ackStates.appDataAckState, *frame);
}
},
[](auto& /* conn */,
auto& /* packet */,
bool /* processed */,
PacketNum /* currentPacketNum */) {},
[](auto& /* conn */, auto& /* packet */, bool /* processed */
) {},
Clock::now());
EXPECT_EQ(2, conn.ackStates.appDataAckState.acks.size());
EXPECT_EQ(
@@ -503,10 +500,8 @@ TEST_P(AckHandlersTest, AckVisitorForAckTest) {
commonAckVisitorForAckFrame(conn.ackStates.appDataAckState, *frame);
}
},
[](auto& /* conn */,
auto& /* packet */,
bool /* processed */,
PacketNum /* currentPacketNum */) {},
[](auto& /* conn */, auto& /* packet */, bool /* processed */
) {},
Clock::now());
EXPECT_TRUE(conn.ackStates.appDataAckState.acks.empty());
}
@@ -532,7 +527,7 @@ TEST_P(AckHandlersTest, NoNewAckedPacket) {
GetParam(),
ackFrame,
[](const auto&, const auto&, const auto&) {},
[](auto&, auto&, bool, PacketNum) {},
[](auto&, auto&, bool) {},
Clock::now());
EXPECT_TRUE(conn.pendingEvents.setLossDetectionAlarm);
EXPECT_EQ(conn.lossState.ptoCount, 1);
@@ -553,7 +548,7 @@ TEST_P(AckHandlersTest, LossByAckedRecovered) {
GetParam(),
ackFrame,
[](const auto&, const auto&, const auto&) {},
[](auto&, auto&, bool, PacketNum) {},
[](auto&, auto&, bool) {},
Clock::now());
}
@@ -586,7 +581,7 @@ TEST_P(AckHandlersTest, AckPacketNumDoesNotExist) {
GetParam(),
ackFrame,
[](const auto&, const auto&, const auto&) {},
[](auto&, auto&, bool, PacketNum) {},
[](auto&, auto&, bool) {},
Clock::now());
EXPECT_EQ(1, conn.outstandings.packets.size());
}
@@ -705,10 +700,8 @@ TEST_P(AckHandlersTest, NoSkipAckVisitor) {
GetParam(),
ackFrame,
countingAckVisitor,
[&](auto& /*conn*/,
auto& /* packet */,
bool /* processed */,
PacketNum) { /* no-op lossVisitor */ },
[&](auto& /*conn*/, auto& /* packet */, bool /* processed */
) { /* no-op lossVisitor */ },
Clock::now());
EXPECT_EQ(1, ackVisitorCounter);
}
@@ -755,10 +748,8 @@ TEST_P(AckHandlersTest, SkipAckVisitor) {
GetParam(),
ackFrame,
countingAckVisitor,
[&](auto& /*conn*/,
auto& /* packet */,
bool /* processed */,
PacketNum) { /* no-op lossVisitor */ },
[&](auto& /*conn*/, auto& /* packet */, bool /* processed */
) { /* no-op lossVisitor */ },
Clock::now());
EXPECT_EQ(0, ackVisitorCounter);
}
@@ -809,10 +800,8 @@ TEST_P(AckHandlersTest, NoDoubleProcess) {
GetParam(),
ackFrame1,
countingAckVisitor,
[&](auto& /*conn*/,
auto& /* packet */,
bool /* processed */,
PacketNum) { /* no-op lossVisitor */ },
[&](auto& /*conn*/, auto& /* packet */, bool /* processed */
) { /* no-op lossVisitor */ },
Clock::now());
EXPECT_EQ(1, ackVisitorCounter);
@@ -825,10 +814,8 @@ TEST_P(AckHandlersTest, NoDoubleProcess) {
GetParam(),
ackFrame2,
countingAckVisitor,
[&](auto& /* conn */,
auto& /* packet */,
bool /* processed */,
PacketNum) { /* no-op */ },
[&](auto& /* conn */, auto& /* packet */, bool /* processed */
) { /* no-op */ },
Clock::now());
EXPECT_EQ(1, ackVisitorCounter);
}
@@ -874,10 +861,8 @@ TEST_P(AckHandlersTest, ClonedPacketsCounter) {
GetParam(),
ackFrame,
countingAckVisitor,
[&](auto& /* conn */,
auto& /* packet */,
bool /* processed */,
PacketNum) { /* no-op */ },
[&](auto& /* conn */, auto& /* packet */, bool /* processed */
) { /* no-op */ },
Clock::now());
EXPECT_EQ(2, ackVisitorCounter);
EXPECT_EQ(0, conn.outstandings.clonedPacketsCount);
@@ -906,7 +891,7 @@ TEST_P(AckHandlersTest, UpdateMaxAckDelay) {
GetParam(),
ackFrame,
[&](const auto&, const auto&, const auto&) { /* ackVisitor */ },
[&](auto&, auto&, bool, PacketNum) { /* lossVisitor */ },
[&](auto&, auto&, bool) { /* lossVisitor */ },
receiveTime);
EXPECT_EQ(10us, conn.lossState.mrtt);
}
@@ -971,10 +956,8 @@ TEST_P(AckHandlersTest, AckNotOutstandingButLoss) {
PacketNumberSpace::AppData,
ackFrame,
countingAckVisitor,
[&](auto& /*conn*/,
auto& /* packet */,
bool /* processed */,
PacketNum) { /* no-op lossVisitor */ },
[&](auto& /*conn*/, auto& /* packet */, bool /* processed */
) { /* no-op lossVisitor */ },
Clock::now());
EXPECT_EQ(0, ackVisitorCounter);
}
@@ -1006,7 +989,7 @@ TEST_P(AckHandlersTest, UpdatePendingAckStates) {
GetParam(),
ackFrame,
[&](auto, auto, auto) { /* ackVisitor */ },
[&](auto&, auto&, auto, auto) { /* lossVisitor */ },
[&](auto&, auto&, auto) { /* lossVisitor */ },
receiveTime);
EXPECT_EQ(2468 + 111, conn.lossState.totalBytesSentAtLastAck);
EXPECT_EQ(1357 + 111, conn.lossState.totalBytesAckedAtLastAck);
@@ -1065,7 +1048,7 @@ TEST_P(AckHandlersTest, AckEventCreation) {
GetParam(),
ackFrame,
[](const auto&, const auto&, const auto&) {},
[](auto&, auto&, bool, PacketNum) {},
[](auto&, auto&, bool) {},
ackTime);
}