mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-08-08 09:42:06 +03:00
Add TransportSetting and knob for default priority.
Summary: Allows the default stream priority (which also means scheduling policy) to be set via TransportSettings. Reviewed By: jbeshay, hanidamlaj Differential Revision: D45881729 fbshipit-source-id: fcb72022cd6eac2f1dafc55173d5a46a72a95dbc
This commit is contained in:
committed by
Facebook GitHub Bot
parent
1c6e089f9e
commit
b89882a772
@@ -167,7 +167,8 @@ BETTER_ENUM(
|
||||
// Controls whether to fire write loops early when pacing
|
||||
FIRE_LOOP_EARLY = 0x10001,
|
||||
// Controls the timer tick used for pacing
|
||||
PACING_TIMER_TICK = 0x10002)
|
||||
PACING_TIMER_TICK = 0x10002,
|
||||
DEFAULT_STREAM_PRIORITY = 0x10003)
|
||||
|
||||
enum class FrameType : uint64_t {
|
||||
PADDING = 0x00,
|
||||
|
@@ -1430,6 +1430,73 @@ TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerSequential) {
|
||||
EXPECT_EQ(*frames[2].asWriteStreamFrame(), f3);
|
||||
}
|
||||
|
||||
TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerSequentialDefault) {
|
||||
QuicClientConnectionState conn(
|
||||
FizzClientQuicHandshakeContext::Builder().build());
|
||||
conn.streamManager->setMaxLocalBidirectionalStreams(10);
|
||||
conn.flowControlState.peerAdvertisedMaxOffset = 100000;
|
||||
conn.flowControlState.peerAdvertisedInitialMaxStreamOffsetBidiRemote = 100000;
|
||||
conn.transportSettings.defaultPriority = Priority(0, false);
|
||||
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.value_or(0));
|
||||
auto stream1 =
|
||||
conn.streamManager->createNextBidirectionalStream().value()->id;
|
||||
auto stream2 =
|
||||
conn.streamManager->createNextBidirectionalStream().value()->id;
|
||||
auto stream3 =
|
||||
conn.streamManager->createNextBidirectionalStream().value()->id;
|
||||
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(
|
||||
*conn.streamManager->findStream(stream1), std::move(largeBuf), false);
|
||||
writeDataToQuicStream(
|
||||
*conn.streamManager->findStream(stream2),
|
||||
folly::IOBuf::copyBuffer("some data"),
|
||||
false);
|
||||
writeDataToQuicStream(
|
||||
*conn.streamManager->findStream(stream3),
|
||||
folly::IOBuf::copyBuffer("some data"),
|
||||
false);
|
||||
// The default is to wraparound initially.
|
||||
scheduler.writeStreams(builder1);
|
||||
EXPECT_EQ(
|
||||
conn.streamManager->writableStreams().getNextScheduledStream(
|
||||
Priority(0, false)),
|
||||
stream1);
|
||||
|
||||
// Should write frames for stream1, stream2, stream3, in that order.
|
||||
NiceMock<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(), 3);
|
||||
WriteStreamFrame f1(stream1, 0, chainLen, false);
|
||||
WriteStreamFrame f2(stream2, 0, 9, false);
|
||||
WriteStreamFrame f3(stream3, 0, 9, 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);
|
||||
}
|
||||
|
||||
TEST_F(QuicPacketSchedulerTest, StreamFrameSchedulerRoundRobinControl) {
|
||||
QuicClientConnectionState conn(
|
||||
FizzClientQuicHandshakeContext::Builder().build());
|
||||
|
@@ -1046,6 +1046,31 @@ void QuicServerTransport::registerAllTransportKnobParamHandlers() {
|
||||
std::chrono::microseconds(val);
|
||||
VLOG(3) << "PACING_TIMER_TICK KnobParam received: " << val;
|
||||
});
|
||||
registerTransportKnobParamHandler(
|
||||
static_cast<uint64_t>(TransportKnobParamId::DEFAULT_STREAM_PRIORITY),
|
||||
[](QuicServerTransport* serverTransport, TransportKnobParam::Val value) {
|
||||
CHECK(serverTransport);
|
||||
auto val = std::get<std::string>(value);
|
||||
auto serverConn = serverTransport->serverConn_;
|
||||
uint8_t level;
|
||||
bool incremental;
|
||||
bool parseSuccess = false;
|
||||
try {
|
||||
parseSuccess = folly::split(",", val, level, incremental);
|
||||
} catch (std::exception&) {
|
||||
parseSuccess = false;
|
||||
}
|
||||
if (!parseSuccess) {
|
||||
auto errMsg = fmt::format(
|
||||
"Received invalid KnobParam for DEFAULT_STREAM_PRIORITY: {}",
|
||||
val);
|
||||
VLOG(3) << errMsg;
|
||||
throw std::runtime_error(errMsg);
|
||||
}
|
||||
serverConn->transportSettings.defaultPriority =
|
||||
Priority(level, incremental);
|
||||
VLOG(3) << "DEFAULT_STREAM_PRIORITY KnobParam received: " << val;
|
||||
});
|
||||
}
|
||||
|
||||
QuicConnectionStats QuicServerTransport::getConnectionsStats() const {
|
||||
|
@@ -4825,7 +4825,18 @@ TEST_F(QuicServerTransportTest, TestAckFrequencyPolicyKnobHandler) {
|
||||
server->handleKnobParams(
|
||||
{{static_cast<uint64_t>(TransportKnobParamId::ACK_FREQUENCY_POLICY),
|
||||
"1,3,1,1"}});
|
||||
EXPECT_FALSE(server->getTransportSettings().bbrConfig.ackFrequencyConfig);
|
||||
server->handleKnobParams(
|
||||
{{static_cast<uint64_t>(TransportKnobParamId::DEFAULT_STREAM_PRIORITY),
|
||||
"1,1"}});
|
||||
EXPECT_EQ(server->getTransportSettings().defaultPriority, Priority(1, true));
|
||||
server->handleKnobParams(
|
||||
{{static_cast<uint64_t>(TransportKnobParamId::DEFAULT_STREAM_PRIORITY),
|
||||
"4,0"}});
|
||||
EXPECT_EQ(server->getTransportSettings().defaultPriority, Priority(4, false));
|
||||
server->handleKnobParams(
|
||||
{{static_cast<uint64_t>(TransportKnobParamId::DEFAULT_STREAM_PRIORITY),
|
||||
"4,0,10"}});
|
||||
EXPECT_EQ(server->getTransportSettings().defaultPriority, Priority(4, false));
|
||||
}
|
||||
|
||||
TEST_F(QuicServerTransportTest, TestSetMaxPacingRateLifecycle) {
|
||||
|
@@ -38,6 +38,7 @@ QuicStreamState::QuicStreamState(StreamId idIn, QuicConnectionStateBase& connIn)
|
||||
sendState = StreamSendState::Invalid;
|
||||
}
|
||||
}
|
||||
priority = connIn.transportSettings.defaultPriority;
|
||||
}
|
||||
|
||||
QuicStreamState::QuicStreamState(
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <folly/Optional.h>
|
||||
#include <quic/QuicConstants.h>
|
||||
#include <quic/state/QuicPriorityQueue.h>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -267,6 +268,9 @@ struct TransportSettings {
|
||||
bool advertisedKnobFrameSupport{true};
|
||||
bool removeStreamAfterEomCallbackUnset{false};
|
||||
|
||||
// The default priority to instantiate streams with.
|
||||
Priority defaultPriority{kDefaultPriority};
|
||||
|
||||
// Local configuration for ACK receive timestamps.
|
||||
//
|
||||
// Determines the ACK receive timestamp configuration sent to peer,
|
||||
|
Reference in New Issue
Block a user