1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-08-05 11:21:09 +03:00

Write control streams before other streams.`

Summary: For protocols like HTTP/3, lacking an actual priority scheme, it's a good idea to write control streams before non control streams. Implement this in a round robin fashion in the same way we do for other streams.

Reviewed By: afrind

Differential Revision: D18236010

fbshipit-source-id: faee9af7fff7736679bfea262ac18d677a7cbf78
This commit is contained in:
Matt Joras
2019-11-04 14:17:51 -08:00
committed by Facebook Github Bot
parent af58963fe4
commit 1c0794abd7
8 changed files with 143 additions and 18 deletions

View File

@@ -762,6 +762,70 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobin) {
EXPECT_EQ(*frames[2].asWriteStreamFrame(), f3);
}
TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobinControl) {
QuicClientConnectionState conn;
conn.streamManager->setMaxLocalBidirectionalStreams(10);
conn.flowControlState.peerAdvertisedMaxOffset = 100000;
conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote = 100000;
auto connId = getTestConnectionId();
StreamFrameScheduler scheduler(conn);
ShortHeader shortHeader1(
ProtectionType::KeyPhaseZero,
connId,
getNextPacketNum(conn, PacketNumberSpace::AppData));
RegularQuicPacketBuilder builder1(
conn.udpSendPacketLen,
std::move(shortHeader1),
conn.ackStates.appDataAckState.largestAckedByPeer);
auto stream1 = conn.streamManager->createNextBidirectionalStream().value();
auto stream2 = conn.streamManager->createNextBidirectionalStream().value();
auto stream3 = conn.streamManager->createNextBidirectionalStream().value();
auto stream4 = conn.streamManager->createNextBidirectionalStream().value();
conn.streamManager->setStreamAsControl(*stream2);
conn.streamManager->setStreamAsControl(*stream4);
auto largeBuf = folly::IOBuf::createChain(conn.udpSendPacketLen * 2, 4096);
auto curBuf = largeBuf.get();
do {
curBuf->append(curBuf->capacity());
curBuf = curBuf->next();
} while (curBuf != largeBuf.get());
auto chainLen = largeBuf->computeChainDataLength();
writeDataToQuicStream(*stream1, std::move(largeBuf), false);
writeDataToQuicStream(*stream2, folly::IOBuf::copyBuffer("some data"), false);
writeDataToQuicStream(*stream3, folly::IOBuf::copyBuffer("some data"), false);
writeDataToQuicStream(*stream4, folly::IOBuf::copyBuffer("some data"), false);
// Force the wraparound initially.
conn.schedulingState.nextScheduledStream = stream4->id + 8;
scheduler.writeStreams(builder1);
EXPECT_EQ(conn.schedulingState.nextScheduledStream, stream3->id);
EXPECT_EQ(conn.schedulingState.nextScheduledControlStream, stream2->id);
// Should write frames for stream2, stream4, followed by stream 3 then 1.
MockQuicPacketBuilder builder2;
EXPECT_CALL(builder2, remainingSpaceInPkt()).WillRepeatedly(Return(4096));
EXPECT_CALL(builder2, appendFrame(_)).WillRepeatedly(Invoke([&](auto f) {
builder2.frames_.push_back(f);
}));
scheduler.writeStreams(builder2);
auto& frames = builder2.frames_;
ASSERT_EQ(frames.size(), 4);
WriteStreamFrame f1(stream2->id, 0, 9, false);
WriteStreamFrame f2(stream4->id, 0, 9, false);
WriteStreamFrame f3(stream3->id, 0, 9, false);
WriteStreamFrame f4(stream1->id, 0, chainLen, false);
ASSERT_TRUE(frames[0].asWriteStreamFrame());
EXPECT_EQ(*frames[0].asWriteStreamFrame(), f1);
ASSERT_TRUE(frames[1].asWriteStreamFrame());
EXPECT_EQ(*frames[1].asWriteStreamFrame(), f2);
ASSERT_TRUE(frames[2].asWriteStreamFrame());
EXPECT_EQ(*frames[2].asWriteStreamFrame(), f3);
ASSERT_TRUE(frames[3].asWriteStreamFrame());
EXPECT_EQ(*frames[3].asWriteStreamFrame(), f4);
EXPECT_EQ(conn.schedulingState.nextScheduledStream, stream3->id);
EXPECT_EQ(conn.schedulingState.nextScheduledControlStream, stream2->id);
}
TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerOneStream) {
QuicClientConnectionState conn;
conn.streamManager->setMaxLocalBidirectionalStreams(10);
@@ -808,7 +872,7 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRemoveOne) {
// Manually remove a stream and set the next scheduled to that stream.
builder.frames_.clear();
conn.streamManager->removeWritable(stream2->id);
conn.streamManager->removeWritable(*stream2);
conn.schedulingState.nextScheduledStream = stream2->id;
scheduler.writeStreams(builder);
ASSERT_EQ(builder.frames_.size(), 1);