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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -63,8 +63,7 @@ void onPTOAlarm(QuicConnectionStateBase& conn) {
void markPacketLoss( void markPacketLoss(
QuicConnectionStateBase& conn, QuicConnectionStateBase& conn,
RegularQuicWritePacket& packet, RegularQuicWritePacket& packet,
bool processed, bool processed) {
PacketNum currentPacketNum) {
QUIC_STATS(conn.statsCallback, onPacketLoss); QUIC_STATS(conn.statsCallback, onPacketLoss);
for (auto& packetFrame : packet.frames) { for (auto& packetFrame : packet.frames) {
switch (packetFrame.type()) { switch (packetFrame.type()) {
@@ -72,26 +71,19 @@ void markPacketLoss(
MaxStreamDataFrame& frame = *packetFrame.asMaxStreamDataFrame(); MaxStreamDataFrame& frame = *packetFrame.asMaxStreamDataFrame();
// For all other frames, we process it if it's not from a clone // 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. // packet, or if the clone and its siblings have never been processed.
// But for both MaxData and MaxStreamData, clone and its siblings may // But for both MaxData and MaxStreamData, we opportunistically send
// have different values. So we process it if it matches the // an update to avoid stalling the peer.
// 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.
auto stream = conn.streamManager->getStream(frame.streamId); auto stream = conn.streamManager->getStream(frame.streamId);
if (!stream) { if (!stream) {
break; break;
} }
// TODO: check for the stream is in Open or HalfClosedLocal state, the // TODO: check for the stream is in Open or HalfClosedLocal state, the
// peer doesn't need a flow control update in these cases. // peer doesn't need a flow control update in these cases.
if (stream->latestMaxStreamDataPacket == currentPacketNum) { onStreamWindowUpdateLost(*stream);
onStreamWindowUpdateLost(*stream);
}
break; break;
} }
case QuicWriteFrame::Type::MaxDataFrame_E: { case QuicWriteFrame::Type::MaxDataFrame_E: {
if (conn.latestMaxDataPacket == currentPacketNum) { onConnWindowUpdateLost(conn);
onConnWindowUpdateLost(conn);
}
break; break;
} }
// For other frame types, we only process them if the packet is not a // 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. // or if the PacketEvent is present in conn.outstandings.packetEvents.
bool processed = pkt.associatedEvent && bool processed = pkt.associatedEvent &&
!conn.outstandings.packetEvents.count(*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 // Remove the PacketEvent from the outstandings.packetEvents set
if (pkt.associatedEvent) { if (pkt.associatedEvent) {
conn.outstandings.packetEvents.erase(*pkt.associatedEvent); conn.outstandings.packetEvents.erase(*pkt.associatedEvent);
@@ -354,8 +354,7 @@ void onLossDetectionAlarm(
void markPacketLoss( void markPacketLoss(
QuicConnectionStateBase& conn, QuicConnectionStateBase& conn,
RegularQuicWritePacket& packet, RegularQuicWritePacket& packet,
bool processed, bool processed);
PacketNum currentPacketNum);
template <class LossVisitor> template <class LossVisitor>
folly::Optional<CongestionController::LossEvent> handleAckForLoss( folly::Optional<CongestionController::LossEvent> handleAckForLoss(
@@ -408,10 +407,9 @@ void markZeroRttPacketsLost(
if (isZeroRttPacket) { if (isZeroRttPacket) {
auto& pkt = *iter; auto& pkt = *iter;
DCHECK(!pkt.isHandshake); DCHECK(!pkt.isHandshake);
auto currentPacketNum = pkt.packet.header.getPacketSequenceNum();
bool processed = pkt.associatedEvent && bool processed = pkt.associatedEvent &&
!conn.outstandings.packetEvents.count(*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 // Remove the PacketEvent from the outstandings.packetEvents set
if (pkt.associatedEvent) { if (pkt.associatedEvent) {
conn.outstandings.packetEvents.erase(*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) { auto testingLossMarkFunc(std::vector<PacketNum>& lostPackets) {
return [&lostPackets]( return [&lostPackets](auto& /* conn */, auto& packet, bool processed) {
auto& /* conn */, auto& packet, bool processed, PacketNum) {
if (!processed) { if (!processed) {
auto packetNum = packet.header.getPacketSequenceNum(); auto packetNum = packet.header.getPacketSequenceNum();
lostPackets.push_back(packetNum); lostPackets.push_back(packetNum);
@@ -279,7 +278,7 @@ TEST_F(QuicLossFunctionsTest, ClearEarlyRetranTimer) {
ASSERT_GT(secondPacketNum, firstPacketNum); ASSERT_GT(secondPacketNum, firstPacketNum);
ASSERT_EQ(2, conn->outstandings.packets.size()); ASSERT_EQ(2, conn->outstandings.packets.size());
// detectLossPackets will set lossTime on Initial space. // 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( detectLossPackets(
*conn, *conn,
secondPacketNum, secondPacketNum,
@@ -420,8 +419,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLoss) {
EXPECT_EQ(1, conn->outstandings.packets.size()); EXPECT_EQ(1, conn->outstandings.packets.size());
auto& packet = auto& packet =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet; getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet.header.getPacketSequenceNum(); markPacketLoss(*conn, packet, false);
markPacketLoss(*conn, packet, false, packetNum);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 0); EXPECT_EQ(stream1->retransmissionBuffer.size(), 0);
EXPECT_EQ(stream2->retransmissionBuffer.size(), 0); EXPECT_EQ(stream2->retransmissionBuffer.size(), 0);
EXPECT_EQ(stream1->lossBuffer.size(), 1); EXPECT_EQ(stream1->lossBuffer.size(), 1);
@@ -471,13 +469,13 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossMerge) {
auto& packet1 = auto& packet1 =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet; getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet1.header.getPacketSequenceNum(); auto packetNum = packet1.header.getPacketSequenceNum();
markPacketLoss(*conn, packet1, false, packetNum); markPacketLoss(*conn, packet1, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1); EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
EXPECT_EQ(stream1->lossBuffer.size(), 1); EXPECT_EQ(stream1->lossBuffer.size(), 1);
auto& packet2 = auto& packet2 =
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet; getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
packetNum = packet2.header.getPacketSequenceNum(); packetNum = packet2.header.getPacketSequenceNum();
markPacketLoss(*conn, packet2, false, packetNum); markPacketLoss(*conn, packet2, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 0); EXPECT_EQ(stream1->retransmissionBuffer.size(), 0);
EXPECT_EQ(stream1->lossBuffer.size(), 1); EXPECT_EQ(stream1->lossBuffer.size(), 1);
@@ -540,13 +538,13 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossNoMerge) {
auto& packet1 = auto& packet1 =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet; getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet1.header.getPacketSequenceNum(); auto packetNum = packet1.header.getPacketSequenceNum();
markPacketLoss(*conn, packet1, false, packetNum); markPacketLoss(*conn, packet1, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 2); EXPECT_EQ(stream1->retransmissionBuffer.size(), 2);
EXPECT_EQ(stream1->lossBuffer.size(), 1); EXPECT_EQ(stream1->lossBuffer.size(), 1);
auto& packet3 = auto& packet3 =
getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet; getLastOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
packetNum = packet3.header.getPacketSequenceNum(); packetNum = packet3.header.getPacketSequenceNum();
markPacketLoss(*conn, packet3, false, packetNum); markPacketLoss(*conn, packet3, false);
EXPECT_EQ(stream1->retransmissionBuffer.size(), 1); EXPECT_EQ(stream1->retransmissionBuffer.size(), 1);
EXPECT_EQ(stream1->lossBuffer.size(), 2); EXPECT_EQ(stream1->lossBuffer.size(), 2);
@@ -592,8 +590,7 @@ TEST_F(QuicLossFunctionsTest, RetxBufferSortedAfterLoss) {
EXPECT_EQ(3, stream->retransmissionBuffer.size()); EXPECT_EQ(3, stream->retransmissionBuffer.size());
EXPECT_EQ(3, conn->outstandings.packets.size()); EXPECT_EQ(3, conn->outstandings.packets.size());
auto packet = conn->outstandings.packets[folly::Random::rand32() % 3]; auto packet = conn->outstandings.packets[folly::Random::rand32() % 3];
markPacketLoss( markPacketLoss(*conn, packet.packet, false);
*conn, packet.packet, false, packet.packet.header.getPacketSequenceNum());
EXPECT_EQ(2, stream->retransmissionBuffer.size()); EXPECT_EQ(2, stream->retransmissionBuffer.size());
} }
@@ -624,9 +621,8 @@ TEST_F(QuicLossFunctionsTest, TestMarkCryptoLostAfterCancelRetransmission) {
ASSERT_EQ(conn->outstandings.packets.size(), 1); ASSERT_EQ(conn->outstandings.packets.size(), 1);
EXPECT_GT(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0); EXPECT_GT(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
auto& packet = conn->outstandings.packets.front().packet; auto& packet = conn->outstandings.packets.front().packet;
auto packetNum = packet.header.getPacketSequenceNum();
cancelHandshakeCryptoStreamRetransmissions(*conn->cryptoState); 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.retransmissionBuffer.size(), 0);
EXPECT_EQ(conn->cryptoState->handshakeStream.lossBuffer.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); ASSERT_EQ(conn->outstandings.packets.size(), 1);
EXPECT_GT(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0); EXPECT_GT(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
auto& packet = conn->outstandings.packets.front().packet; auto& packet = conn->outstandings.packets.front().packet;
auto packetNum = packet.header.getPacketSequenceNum(); markPacketLoss(*conn, packet, false);
markPacketLoss(*conn, packet, false, packetNum);
EXPECT_EQ(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0); EXPECT_EQ(conn->cryptoState->handshakeStream.retransmissionBuffer.size(), 0);
EXPECT_EQ(conn->cryptoState->handshakeStream.lossBuffer.size(), 1); EXPECT_EQ(conn->cryptoState->handshakeStream.lossBuffer.size(), 1);
cancelHandshakeCryptoStreamRetransmissions(*conn->cryptoState); cancelHandshakeCryptoStreamRetransmissions(*conn->cryptoState);
@@ -684,7 +679,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossAfterStreamReset) {
true); true);
sendRstSMHandler(*stream1, GenericApplicationErrorCode::UNKNOWN); sendRstSMHandler(*stream1, GenericApplicationErrorCode::UNKNOWN);
markPacketLoss(*conn, packet, false, packet.header.getPacketSequenceNum()); markPacketLoss(*conn, packet, false);
EXPECT_TRUE(stream1->lossBuffer.empty()); EXPECT_TRUE(stream1->lossBuffer.empty());
EXPECT_TRUE(stream1->retransmissionBuffer.empty()); EXPECT_TRUE(stream1->retransmissionBuffer.empty());
@@ -701,11 +696,10 @@ TEST_F(QuicLossFunctionsTest, TestReorderingThreshold) {
EXPECT_CALL(*rawCongestionController, onPacketSent(_)) EXPECT_CALL(*rawCongestionController, onPacketSent(_))
.WillRepeatedly(Return()); .WillRepeatedly(Return());
auto testingLossMarkFunc = auto testingLossMarkFunc = [&lostPacket](auto& /*conn*/, auto& packet, bool) {
[&lostPacket](auto& /*conn*/, auto& packet, bool, PacketNum) { auto packetNum = packet.header.getPacketSequenceNum();
auto packetNum = packet.header.getPacketSequenceNum(); lostPacket.push_back(packetNum);
lostPacket.push_back(packetNum); };
};
for (int i = 0; i < 6; ++i) { for (int i = 0; i < 6; ++i) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::Handshake); sendPacket(*conn, Clock::now(), folly::none, PacketType::Handshake);
} }
@@ -771,7 +765,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckForLoss) {
OutstandingPacket(outstandingRegularPacket, now, 0, false, 0)); OutstandingPacket(outstandingRegularPacket, now, 0, false, 0));
bool testLossMarkFuncCalled = false; bool testLossMarkFuncCalled = false;
auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool, PacketNum) { auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool) {
testLossMarkFuncCalled = true; testLossMarkFuncCalled = true;
}; };
EXPECT_CALL(*mockQLogger, addPacketsLost(1, 0, 1)); EXPECT_CALL(*mockQLogger, addPacketsLost(1, 0, 1));
@@ -809,7 +803,7 @@ TEST_F(QuicLossFunctionsTest, TestHandleAckedPacket) {
conn->lossState.largestSent.value_or(0)); conn->lossState.largestSent.value_or(0));
bool testLossMarkFuncCalled = false; bool testLossMarkFuncCalled = false;
auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool, PacketNum) { auto testLossMarkFunc = [&](auto& /* conn */, auto&, bool) {
testLossMarkFuncCalled = true; testLossMarkFuncCalled = true;
}; };
@@ -858,7 +852,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkRstLoss) {
EXPECT_TRUE(conn->pendingEvents.resets.empty()); EXPECT_TRUE(conn->pendingEvents.resets.empty());
auto& packet = auto& packet =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->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.size());
EXPECT_EQ(1, conn->pendingEvents.resets.count(stream->id)); EXPECT_EQ(1, conn->pendingEvents.resets.count(stream->id));
@@ -897,14 +891,12 @@ TEST_F(QuicLossFunctionsTest, TestMarkRstLoss) {
TEST_F(QuicLossFunctionsTest, ReorderingThresholdChecksSamePacketNumberSpace) { TEST_F(QuicLossFunctionsTest, ReorderingThresholdChecksSamePacketNumberSpace) {
auto conn = createConn(); auto conn = createConn();
uint16_t lossVisitorCount = 0; uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */, auto countingLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool processed) {
bool processed, if (!processed) {
PacketNum /* currentPacketNum */) { lossVisitorCount++;
if (!processed) { }
lossVisitorCount++; };
}
};
PacketNum latestSent = 0; PacketNum latestSent = 0;
for (size_t i = 0; i < conn->lossState.reorderingThreshold + 1; i++) { for (size_t i = 0; i < conn->lossState.reorderingThreshold + 1; i++) {
latestSent = latestSent =
@@ -950,8 +942,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkWindowUpdateLoss) {
auto& packet = auto& packet =
getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet; getFirstOutstandingPacket(*conn, PacketNumberSpace::AppData)->packet;
auto packetNum = packet.header.getPacketSequenceNum(); markPacketLoss(*conn, packet, false);
markPacketLoss(*conn, packet, false, packetNum);
EXPECT_TRUE(conn->streamManager->pendingWindowUpdate(stream->id)); EXPECT_TRUE(conn->streamManager->pendingWindowUpdate(stream->id));
} }
@@ -1178,14 +1169,12 @@ TEST_F(QuicLossFunctionsTest, NoSkipLossVisitor) {
// make srtt large so delayUntilLost won't kick in // make srtt large so delayUntilLost won't kick in
conn->lossState.srtt = 1000000000us; conn->lossState.srtt = 1000000000us;
uint16_t lossVisitorCount = 0; uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */, auto countingLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool processed) {
bool processed, if (!processed) {
PacketNum /* currentPacketNum */) { lossVisitorCount++;
if (!processed) { }
lossVisitorCount++; };
}
};
// Send 5 packets, so when we ack the last one, we mark the first one loss // Send 5 packets, so when we ack the last one, we mark the first one loss
PacketNum lastSent; PacketNum lastSent;
for (size_t i = 0; i < 5; i++) { for (size_t i = 0; i < 5; i++) {
@@ -1206,14 +1195,12 @@ TEST_F(QuicLossFunctionsTest, SkipLossVisitor) {
// make srtt large so delayUntilLost won't kick in // make srtt large so delayUntilLost won't kick in
conn->lossState.srtt = 1000000000us; conn->lossState.srtt = 1000000000us;
uint16_t lossVisitorCount = 0; uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */, auto countingLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool processed) {
bool processed, if (!processed) {
PacketNum /* currentPacketNum */) { lossVisitorCount++;
if (!processed) { }
lossVisitorCount++; };
}
};
// Send 5 packets, so when we ack the last one, we mark the first one loss // Send 5 packets, so when we ack the last one, we mark the first one loss
PacketNum lastSent; PacketNum lastSent;
for (size_t i = 0; i < 5; i++) { for (size_t i = 0; i < 5; i++) {
@@ -1237,14 +1224,12 @@ TEST_F(QuicLossFunctionsTest, NoDoubleProcess) {
conn->lossState.srtt = 1000000000us; conn->lossState.srtt = 1000000000us;
uint16_t lossVisitorCount = 0; uint16_t lossVisitorCount = 0;
auto countingLossVisitor = [&](auto& /* conn */, auto countingLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool processed) {
bool processed, if (!processed) {
PacketNum /* currentPacketNum */) { lossVisitorCount++;
if (!processed) { }
lossVisitorCount++; };
}
};
// Send 6 packets, so when we ack the last one, we mark the first two loss // Send 6 packets, so when we ack the last one, we mark the first two loss
PacketNum lastSent; PacketNum lastSent;
PacketEvent event(PacketNumberSpace::AppData, 0); PacketEvent event(PacketNumberSpace::AppData, 0);
@@ -1283,7 +1268,7 @@ TEST_F(QuicLossFunctionsTest, DetectPacketLossClonedPacketsCounter) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt); sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt);
auto ackedPacket = auto ackedPacket =
sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt); sendPacket(*conn, Clock::now(), folly::none, PacketType::OneRtt);
auto noopLossMarker = [](auto&, auto&, bool, PacketNum) {}; auto noopLossMarker = [](auto&, auto&, bool) {};
detectLossPackets<decltype(noopLossMarker)>( detectLossPackets<decltype(noopLossMarker)>(
*conn, *conn,
ackedPacket, ackedPacket,
@@ -1305,7 +1290,6 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
conn->streamManager->createNextBidirectionalStream().value()->id; conn->streamManager->createNextBidirectionalStream().value()->id;
conn->streamManager->queueWindowUpdate(stream2Id); conn->streamManager->queueWindowUpdate(stream2Id);
conn->pendingEvents.connWindowUpdate = true; conn->pendingEvents.connWindowUpdate = true;
auto nextPacketNum = conn->ackStates.appDataAckState.nextPacketNum;
// writeQuicPacket will call writeQuicDataToSocket which will also take care // writeQuicPacket will call writeQuicDataToSocket which will also take care
// of sending the MaxStreamDataFrame for stream2 // of sending the MaxStreamDataFrame for stream2
auto stream1 = conn->streamManager->findStream(stream1Id); auto stream1 = conn->streamManager->findStream(stream1Id);
@@ -1345,7 +1329,7 @@ TEST_F(QuicLossFunctionsTest, TestMarkPacketLossProcessedPacket) {
EXPECT_EQ(1, streamWindowUpdateCounter); EXPECT_EQ(1, streamWindowUpdateCounter);
EXPECT_EQ(1, connWindowUpdateCounter); EXPECT_EQ(1, connWindowUpdateCounter);
// Force this packet to be a processed clone // Force this packet to be a processed clone
markPacketLoss(*conn, packet, true, nextPacketNum); markPacketLoss(*conn, packet, true);
EXPECT_EQ(1, stream1->retransmissionBuffer.size()); EXPECT_EQ(1, stream1->retransmissionBuffer.size());
EXPECT_TRUE(stream1->lossBuffer.empty()); EXPECT_TRUE(stream1->lossBuffer.empty());
@@ -1389,14 +1373,12 @@ TEST_F(QuicLossFunctionsTest, TotalLossCount) {
} }
EXPECT_EQ(10, conn->outstandings.packets.size()); EXPECT_EQ(10, conn->outstandings.packets.size());
uint32_t lostPackets = 0; uint32_t lostPackets = 0;
auto countingLossVisitor = [&](auto& /* conn */, auto countingLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool processed) {
bool processed, if (!processed) {
PacketNum /* currentPacketNum */) { lostPackets++;
if (!processed) { }
lostPackets++; };
}
};
conn->lossState.rtxCount = 135; conn->lossState.rtxCount = 135;
detectLossPackets( detectLossPackets(
@@ -1423,17 +1405,16 @@ TEST_F(QuicLossFunctionsTest, TestZeroRttRejected) {
} }
EXPECT_FALSE(conn->outstandings.packets.empty()); EXPECT_FALSE(conn->outstandings.packets.empty());
EXPECT_EQ(4, conn->outstandings.packets.size()); EXPECT_EQ(4, conn->outstandings.packets.size());
std::vector<std::pair<PacketNum, bool>> lostPackets; std::vector<bool> lostPackets;
// onRemoveBytesFromInflight should still happen // onRemoveBytesFromInflight should still happen
EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(1); EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(1);
markZeroRttPacketsLost( markZeroRttPacketsLost(*conn, [&lostPackets](auto&, auto&, bool processed) {
*conn, [&lostPackets](auto&, auto&, bool processed, PacketNum packetNum) { lostPackets.emplace_back(processed);
lostPackets.emplace_back(packetNum, processed); });
});
EXPECT_EQ(2, conn->outstandings.packets.size()); EXPECT_EQ(2, conn->outstandings.packets.size());
EXPECT_EQ(lostPackets.size(), 2); EXPECT_EQ(lostPackets.size(), 2);
for (auto lostPacket : lostPackets) { for (auto lostPacket : lostPackets) {
EXPECT_FALSE(lostPacket.second); EXPECT_FALSE(lostPacket);
} }
for (size_t i = 0; i < conn->outstandings.packets.size(); ++i) { for (size_t i = 0; i < conn->outstandings.packets.size(); ++i) {
auto longHeader = conn->outstandings.packets[i].packet.header.asLong(); auto longHeader = conn->outstandings.packets[i].packet.header.asLong();
@@ -1473,20 +1454,19 @@ TEST_F(QuicLossFunctionsTest, TestZeroRttRejectedWithClones) {
ASSERT_EQ(conn->outstandings.clonedPacketsCount, 6); ASSERT_EQ(conn->outstandings.clonedPacketsCount, 6);
ASSERT_EQ(conn->outstandings.packetEvents.size(), 2); ASSERT_EQ(conn->outstandings.packetEvents.size(), 2);
std::vector<std::pair<PacketNum, bool>> lostPackets; std::vector<bool> lostPackets;
// onRemoveBytesFromInflight should still happen // onRemoveBytesFromInflight should still happen
EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(1); EXPECT_CALL(*rawCongestionController, onRemoveBytesFromInflight(_)).Times(1);
markZeroRttPacketsLost( markZeroRttPacketsLost(*conn, [&lostPackets](auto&, auto&, bool processed) {
*conn, [&lostPackets](auto&, auto&, bool processed, PacketNum packetNum) { lostPackets.emplace_back(processed);
lostPackets.emplace_back(packetNum, processed); });
});
ASSERT_EQ(conn->outstandings.packetEvents.size(), 0); ASSERT_EQ(conn->outstandings.packetEvents.size(), 0);
EXPECT_EQ(3, conn->outstandings.packets.size()); EXPECT_EQ(3, conn->outstandings.packets.size());
EXPECT_EQ(lostPackets.size(), 3); EXPECT_EQ(lostPackets.size(), 3);
ASSERT_EQ(conn->outstandings.clonedPacketsCount, 3); ASSERT_EQ(conn->outstandings.clonedPacketsCount, 3);
size_t numProcessed = 0; size_t numProcessed = 0;
for (auto lostPacket : lostPackets) { for (auto lostPacket : lostPackets) {
numProcessed += lostPacket.second; numProcessed += lostPacket;
} }
EXPECT_EQ(numProcessed, 1); EXPECT_EQ(numProcessed, 1);
for (size_t i = 0; i < conn->outstandings.packets.size(); ++i) { for (size_t i = 0; i < conn->outstandings.packets.size(); ++i) {
@@ -1521,11 +1501,8 @@ TEST_F(QuicLossFunctionsTest, TimeThreshold) {
referenceTime + conn->lossState.srtt / 2, referenceTime + conn->lossState.srtt / 2,
folly::none, folly::none,
PacketType::OneRtt); PacketType::OneRtt);
auto lossVisitor = [&](const auto& /*conn*/, auto lossVisitor = [&](const auto& /*conn*/, const auto& packet, bool) {
const auto& /*packet*/, EXPECT_EQ(packet1, packet.header.getPacketSequenceNum());
bool,
PacketNum packetNum) {
EXPECT_EQ(packet1, packetNum);
}; };
detectLossPackets<decltype(lossVisitor)>( detectLossPackets<decltype(lossVisitor)>(
*conn, *conn,
@@ -1545,10 +1522,9 @@ TEST_F(QuicLossFunctionsTest, OutstandingInitialCounting) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::Initial); sendPacket(*conn, Clock::now(), folly::none, PacketType::Initial);
} }
EXPECT_EQ(10, conn->outstandings.initialPacketsCount); EXPECT_EQ(10, conn->outstandings.initialPacketsCount);
auto noopLossVisitor = [&](auto& /* conn */, auto noopLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool /* processed */
bool /* processed */, ) {};
PacketNum /* currentPacketNum */) {};
detectLossPackets( detectLossPackets(
*conn, *conn,
largestSent, largestSent,
@@ -1569,10 +1545,9 @@ TEST_F(QuicLossFunctionsTest, OutstandingHandshakeCounting) {
sendPacket(*conn, Clock::now(), folly::none, PacketType::Handshake); sendPacket(*conn, Clock::now(), folly::none, PacketType::Handshake);
} }
EXPECT_EQ(10, conn->outstandings.handshakePacketsCount); EXPECT_EQ(10, conn->outstandings.handshakePacketsCount);
auto noopLossVisitor = [&](auto& /* conn */, auto noopLossVisitor =
auto& /* packet */, [&](auto& /* conn */, auto& /* packet */, bool /* processed */
bool /* processed */, ) {};
PacketNum /* currentPacketNum */) {};
detectLossPackets( detectLossPackets(
*conn, *conn,
largestSent, largestSent,

View File

@@ -1733,11 +1733,7 @@ TEST_F(QuicServerTransportTest, StopSendingLoss) {
ASSERT_TRUE(builder.canBuildPacket()); ASSERT_TRUE(builder.canBuildPacket());
writeFrame(QuicSimpleFrame(stopSendingFrame), builder); writeFrame(QuicSimpleFrame(stopSendingFrame), builder);
auto packet = std::move(builder).buildPacket(); auto packet = std::move(builder).buildPacket();
markPacketLoss( markPacketLoss(server->getNonConstConn(), packet.packet, false);
server->getNonConstConn(),
packet.packet,
false,
clientNextAppDataPacketNum);
EXPECT_EQ(server->getNonConstConn().pendingEvents.frames.size(), 1); EXPECT_EQ(server->getNonConstConn().pendingEvents.frames.size(), 1);
StopSendingFrame* stopFrame = server->getNonConstConn() StopSendingFrame* stopFrame = server->getNonConstConn()
.pendingEvents.frames.front() .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 // clear out all the streams, this is not a great way to simulate closed
// streams, but good enough for this test. // streams, but good enough for this test.
server->getNonConstConn().streamManager->clearOpenStreams(); server->getNonConstConn().streamManager->clearOpenStreams();
markPacketLoss( markPacketLoss(server->getNonConstConn(), packet.packet, false);
server->getNonConstConn(),
packet.packet,
false,
server->getNonConstConn().ackStates.appDataAckState.nextPacketNum);
EXPECT_EQ(server->getNonConstConn().pendingEvents.frames.size(), 0); 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&)>; void(const OutstandingPacket&, const QuicWriteFrame&, const ReadAckFrame&)>;
using LossVisitor = std::function< using LossVisitor = std::function<
void(QuicConnectionStateBase&, RegularQuicWritePacket&, bool, PacketNum)>; void(QuicConnectionStateBase&, RegularQuicWritePacket&, bool)>;
/** /**
* Processes an ack frame and removes any outstanding packets * Processes an ack frame and removes any outstanding packets

View File

@@ -757,10 +757,6 @@ struct QuicConnectionStateBase : public folly::DelayedDestruction {
PacketSchedulingState schedulingState; 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. // Logger for this connection.
std::shared_ptr<Logger> logger; std::shared_ptr<Logger> logger;

View File

@@ -193,10 +193,6 @@ struct QuicStreamState : public QuicStreamLike {
// State machine data // State machine data
StreamRecvState recvState{StreamRecvState::Open_E}; 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. // Tells whether this stream is a control stream.
// It is set by the app via setControlStream and the transport can use this // 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 // knowledge for optimizations e.g. for setting the app limited state on

View File

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