1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-11-24 04:01:07 +03:00

Keep track of the minimum reliable size ACKed

Summary:
With normal resets, we transition from `StreamSendState::ResetSent` to `StreamSendState::Closed` when we get an ACK for a RESET_STREAM frame.

With reliable resets, this is going to be a little more complicated. We can't automatically transition from `StreamSendState::ResetSent` to `StreamSendState::Closed` when we get an ACK for a RESET_STREAM_AT frame because it's possible that the peer hasn't yet received all data until the reliable reset offset.

My idea is the following: Keep track of the `minReliableSizeAcked`, which is the lowest value of the reliable size in any RESET_STREAM_AT frame that was ACKed by the peer. We set it to 0 if a RESET_STREAM frame was ACKed by the peer.

Then, we can transition from `StreamSendState::ResetSent` to `StreamSendState::Closed` if any one of the following two events happen:
* We get an ACK for a RESET_STREAM_AT or a RESET_STREAM frame, and all data until the `minReliableSizeAcked` has been ACKed by the peer.
* We get an ACK for stream data, and this puts us in a state where all data until the `minReliableSizeAcked` has been ACKed by the peer.

Note: This diff doesn't have any functional change. The only change is that we're keeping track of the `minReliableSizeAcked`, but aren't using it anywhere.

Reviewed By: mjoras

Differential Revision: D66781199

fbshipit-source-id: 2aa5138a18f70e9801e59e747460558ba706939c
This commit is contained in:
Aman Sharma
2024-12-10 16:39:37 -08:00
committed by Facebook GitHub Bot
parent 1695ecc575
commit fca90d483b
8 changed files with 119 additions and 10 deletions

View File

@@ -96,7 +96,8 @@ TEST_F(QuicOpenStateTest, InvalidEvent) {
StreamId id = 5;
QuicStreamState stream(id, *conn);
RstStreamFrame frame(1, GenericApplicationErrorCode::UNKNOWN, 0);
EXPECT_THROW(sendRstAckSMHandler(stream), QuicTransportException);
EXPECT_THROW(
sendRstAckSMHandler(stream, folly::none), QuicTransportException);
}
TEST_F(QuicOpenStateTest, ReceiveStreamFrameWithFIN) {
@@ -299,11 +300,103 @@ TEST_F(QuicResetSentStateTest, RstAck) {
stream.readBuffer.emplace_back(
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
sendRstAckSMHandler(stream);
sendRstAckSMHandler(stream, folly::none);
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
EXPECT_FALSE(stream.finalReadOffset);
EXPECT_FALSE(stream.readBuffer.empty());
EXPECT_EQ(*stream.minReliableSizeAcked, 0);
}
// A reset with a reliable size of 3 was previously ACKed.
// Now, we're getting an ACK for a reset with a reliable size of 5,
// and should therefore not see a reduction in minReliableSizeAcked
TEST_F(QuicResetSentStateTest, ReliableRstAckNoReduction) {
auto conn = createConn();
StreamId id = 5;
QuicStreamState stream(id, *conn);
stream.minReliableSizeAcked = 3;
stream.sendState = StreamSendState::ResetSent;
stream.currentReadOffset = 0xABCD;
stream.finalWriteOffset = 0xACDC;
stream.readBuffer.emplace_back(
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
sendRstAckSMHandler(stream, 5);
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
EXPECT_FALSE(stream.finalReadOffset);
EXPECT_FALSE(stream.readBuffer.empty());
EXPECT_EQ(*stream.minReliableSizeAcked, 3);
}
// A reset with a reliable size of 3 was previously ACKed.
// Now, we're getting an ACK for a reset with a reliable size
// of 1, and should therefore see a reduction in minReliableSizeAcked
TEST_F(QuicResetSentStateTest, ReliableRstAckReduction) {
auto conn = createConn();
StreamId id = 5;
QuicStreamState stream(id, *conn);
stream.minReliableSizeAcked = 3;
stream.sendState = StreamSendState::ResetSent;
stream.currentReadOffset = 0xABCD;
stream.finalWriteOffset = 0xACDC;
stream.readBuffer.emplace_back(
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
sendRstAckSMHandler(stream, 1);
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
EXPECT_FALSE(stream.finalReadOffset);
EXPECT_FALSE(stream.readBuffer.empty());
EXPECT_EQ(*stream.minReliableSizeAcked, 1);
}
// There were no previously ACKed resets. Therefore, when we get an
// ACK for a reset with a reliable size of 1, we should set the
// minReliableSizeAcked to 1.
TEST_F(QuicResetSentStateTest, ReliableRstAckFirstTime) {
auto conn = createConn();
StreamId id = 5;
QuicStreamState stream(id, *conn);
stream.sendState = StreamSendState::ResetSent;
stream.currentReadOffset = 0xABCD;
stream.finalWriteOffset = 0xACDC;
stream.readBuffer.emplace_back(
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
sendRstAckSMHandler(stream, 1);
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
EXPECT_FALSE(stream.finalReadOffset);
EXPECT_FALSE(stream.readBuffer.empty());
EXPECT_EQ(*stream.minReliableSizeAcked, 1);
}
// A reset with a reliable size of 3 was previously ACKed.
// Now, we're getting an ACK for a non-reliable reset, and should
// therefore set the minReliableSizeAcked to 0.
TEST_F(QuicResetSentStateTest, RstAfterReliableRst) {
auto conn = createConn();
StreamId id = 5;
QuicStreamState stream(id, *conn);
stream.minReliableSizeAcked = 3;
stream.sendState = StreamSendState::ResetSent;
stream.currentReadOffset = 0xABCD;
stream.finalWriteOffset = 0xACDC;
stream.readBuffer.emplace_back(
folly::IOBuf::copyBuffer("One more thing"), 0xABCD, false);
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
sendRstAckSMHandler(stream, folly::none);
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
EXPECT_FALSE(stream.finalReadOffset);
EXPECT_FALSE(stream.readBuffer.empty());
EXPECT_EQ(*stream.minReliableSizeAcked, 0);
}
class QuicClosedStateTest : public Test {};
@@ -314,7 +407,7 @@ TEST_F(QuicClosedStateTest, RstAck) {
QuicStreamState stream(id, *conn);
stream.sendState = StreamSendState::Closed;
RstStreamFrame frame(id, GenericApplicationErrorCode::UNKNOWN, 0);
sendRstAckSMHandler(stream);
sendRstAckSMHandler(stream, folly::none);
EXPECT_EQ(stream.sendState, StreamSendState::Closed);
}