Support FIFO and Round Robin Priority Schemes (#47)

This commit is contained in:
Nick Banks 2020-05-04 10:19:28 -07:00 коммит произвёл GitHub
Родитель e2892cfad6
Коммит 60716dea32
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 161 добавлений и 30 удалений

Просмотреть файл

@ -13,14 +13,12 @@ jobs:
submodules: recursive
- task: VSBuild@1
continueOnError: true
inputs:
solution: msquic.kernel.sln
platform: ${{ parameters.arch }}
configuration: debug
- task: VSBuild@1
continueOnError: true
inputs:
solution: msquic.kernel.sln
platform: ${{ parameters.arch }}

Просмотреть файл

@ -4868,6 +4868,34 @@ QuicConnParamSet(
Status = QUIC_STATUS_SUCCESS;
break;
case QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME: {
if (BufferLength != sizeof(QUIC_STREAM_SCHEDULING_SCHEME)) {
Status = QUIC_STATUS_INVALID_PARAMETER;
break;
}
QUIC_STREAM_SCHEDULING_SCHEME Scheme =
*(QUIC_STREAM_SCHEDULING_SCHEME*)Buffer;
if (Scheme >= QUIC_STREAM_SCHEDULING_SCHEME_COUNT) {
Status = QUIC_STATUS_INVALID_PARAMETER;
break;
}
Connection->State.UseRoundRobinStreamScheduling =
Scheme == QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN;
QuicTraceLogConnInfo(
UpdateStreamSchedulingScheme,
Connection,
"Updated Stream Scheduling Scheme = %u",
Scheme);
Status = QUIC_STATUS_SUCCESS;
break;
}
case QUIC_PARAM_CONN_FORCE_KEY_UPDATE:
if (!Connection->State.Connected ||
@ -5395,6 +5423,27 @@ QuicConnParamGet(
Status = QUIC_STATUS_SUCCESS;
break;
case QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME:
if (*BufferLength < sizeof(QUIC_STREAM_SCHEDULING_SCHEME)) {
*BufferLength = sizeof(QUIC_STREAM_SCHEDULING_SCHEME);
Status = QUIC_STATUS_BUFFER_TOO_SMALL;
break;
}
if (Buffer == NULL) {
Status = QUIC_STATUS_INVALID_PARAMETER;
break;
}
*BufferLength = sizeof(QUIC_STREAM_SCHEDULING_SCHEME);
*(QUIC_STREAM_SCHEDULING_SCHEME*)Buffer =
Connection->State.UseRoundRobinStreamScheduling ?
QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN : QUIC_STREAM_SCHEDULING_SCHEME_FIFO;
Status = QUIC_STATUS_SUCCESS;
break;
default:
Status = QUIC_STATUS_INVALID_PARAMETER;
break;

Просмотреть файл

@ -131,10 +131,16 @@ typedef union QUIC_CONNECTION_STATE {
BOOLEAN ShareBinding : 1;
//
// Indicate the TestTransportParameter variable has been set by the app.
// Indicates the TestTransportParameter variable has been set by the app.
//
BOOLEAN TestTransportParameterSet : 1;
//
// Indicates the connection is using the round robin stream scheduling
// scheme.
//
BOOLEAN UseRoundRobinStreamScheduling : 1;
#ifdef QuicVerifierEnabledByAddr
//
// The calling app is being verified (app or driver verifier).

Просмотреть файл

@ -159,7 +159,7 @@ typedef struct QUIC_PATH QUIC_PATH;
// The number of packets we write for a single stream before going to the next
// one in the round robin.
//
#define QUIC_STREAM_SEND_BATCH_COUNT 4
#define QUIC_STREAM_SEND_BATCH_COUNT 8
//
// The maximum number of received packets to batch process at a time.

Просмотреть файл

@ -803,7 +803,8 @@ QuicSendGetNextStream(
_Out_ uint32_t* PacketCount
)
{
QUIC_DBG_ASSERT(!QuicConnIsClosed(QuicSendGetConnection(Send)) || QuicListIsEmpty(&Send->SendStreams));
QUIC_CONNECTION* Connection = QuicSendGetConnection(Send);
QUIC_DBG_ASSERT(!QuicConnIsClosed(Connection) || QuicListIsEmpty(&Send->SendStreams));
QUIC_LIST_ENTRY* Entry = Send->SendStreams.Flink;
while (Entry != &Send->SendStreams) {
@ -821,13 +822,19 @@ QuicSendGetNextStream(
//
if (QuicSendCanSendStreamNow(Stream)) {
//
// Move the stream to the end of the queue.
//
QuicListEntryRemove(&Stream->SendLink);
QuicListInsertTail(&Send->SendStreams, &Stream->SendLink);
if (Connection->State.UseRoundRobinStreamScheduling) {
//
// Move the stream to the end of the queue.
//
QuicListEntryRemove(&Stream->SendLink);
QuicListInsertTail(&Send->SendStreams, &Stream->SendLink);
*PacketCount = QUIC_STREAM_SEND_BATCH_COUNT;
} else { // FIFO prioritization scheme
*PacketCount = UINT32_MAX;
}
*PacketCount = QUIC_STREAM_SEND_BATCH_COUNT;
return Stream;
}

Просмотреть файл

@ -106,6 +106,12 @@ typedef enum QUIC_CONNECTION_SHUTDOWN_FLAGS {
DEFINE_ENUM_FLAG_OPERATORS(QUIC_CONNECTION_SHUTDOWN_FLAGS);
typedef enum QUIC_STREAM_SCHEDULING_SCHEME {
QUIC_STREAM_SCHEDULING_SCHEME_FIFO = 0x0000, // Sends stream data first come, first served. (Default)
QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN = 0x0001, // Sends stream data evenly multiplexed.
QUIC_STREAM_SCHEDULING_SCHEME_COUNT // The number of stream scheduling schemes.
} QUIC_STREAM_SCHEDULING_SCHEME;
typedef enum QUIC_STREAM_OPEN_FLAGS {
QUIC_STREAM_OPEN_FLAG_NONE = 0x0000,
QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL = 0x0001, // Indicates the stream is unidirectional.
@ -358,6 +364,7 @@ typedef enum QUIC_PARAM_LEVEL {
#define QUIC_PARAM_CONN_SHARE_UDP_BINDING 17 // uint8_t (BOOLEAN)
#define QUIC_PARAM_CONN_IDEAL_PROCESSOR 18 // uint8_t
#define QUIC_PARAM_CONN_MAX_STREAM_IDS 19 // uint64_t[4]
#define QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME 20 // QUIC_STREAM_SCHEDULING_SCHEME
#ifdef WIN32 // Windows certificate validation ignore flags.
#define QUIC_CERTIFICATE_FLAG_IGNORE_REVOCATION 0x00000080

Просмотреть файл

@ -122,7 +122,8 @@ QuicTestConnectAndPing(
_In_ bool ServerRejectZeroRtt,
_In_ bool UseSendBuffer,
_In_ bool UnidirectionalStreams,
_In_ bool ServerInitiatedStreams
_In_ bool ServerInitiatedStreams,
_In_ bool FifoScheduling
);
//
@ -379,6 +380,7 @@ typedef struct {
uint8_t UseSendBuffer;
uint8_t UnidirectionalStreams;
uint8_t ServerInitiatedStreams;
uint8_t FifoScheduling;
} QUIC_RUN_CONNECT_AND_PING_PARAMS;
#pragma pack(pop)

Просмотреть файл

@ -529,11 +529,12 @@ TEST_P(WithSendArgs1, Send) {
0, // StreamBurstDelayMs
0, // ServerStatelessRetry
0, // ClientRebind
0, // ClientZeroRtt,
0, // ClientZeroRtt
0, // ServerRejectZeroRtt
(uint8_t)GetParam().UseSendBuffer,
(uint8_t)GetParam().UnidirectionalStreams,
(uint8_t)GetParam().ServerInitiatedStreams
(uint8_t)GetParam().ServerInitiatedStreams,
0 // FifoScheduling
};
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_CONNECT_AND_PING, Params));
} else {
@ -550,7 +551,8 @@ TEST_P(WithSendArgs1, Send) {
false, // ServerRejectZeroRtt
GetParam().UseSendBuffer,
GetParam().UnidirectionalStreams,
GetParam().ServerInitiatedStreams);
GetParam().ServerInitiatedStreams,
false); // FifoScheduling
}
}
@ -570,7 +572,8 @@ TEST_P(WithSendArgs2, SendLarge) {
0, // ServerRejectZeroRtt
(uint8_t)GetParam().UseSendBuffer,
0, // UnidirectionalStreams
0 // ServerInitiatedStreams
0, // ServerInitiatedStreams
1 // FifoScheduling
};
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_CONNECT_AND_PING, Params));
} else {
@ -587,7 +590,8 @@ TEST_P(WithSendArgs2, SendLarge) {
false, // ServerRejectZeroRtt
GetParam().UseSendBuffer,
false, // UnidirectionalStreams
false); // ServerInitiatedStreams
false, // ServerInitiatedStreams
true); // FifoScheduling
}
}
@ -607,7 +611,8 @@ TEST_P(WithSendArgs3, SendIntermittently) {
0, // ServerRejectZeroRtt
(uint8_t)GetParam().UseSendBuffer,
0, // UnidirectionalStreams
0 // ServerInitiatedStreams
0, // ServerInitiatedStreams
0 // FifoScheduling
};
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_CONNECT_AND_PING, Params));
} else {
@ -624,7 +629,8 @@ TEST_P(WithSendArgs3, SendIntermittently) {
false, // ServerRejectZeroRtt
GetParam().UseSendBuffer,
false, // UnidirectionalStreams
false); // ServerInitiatedStreams
false, // ServerInitiatedStreams
false); // FifoScheduling
}
}
@ -646,7 +652,8 @@ TEST_P(WithSend0RttArgs1, Send0Rtt) {
0, // ServerRejectZeroRtt
(uint8_t)GetParam().UseSendBuffer,
(uint8_t)GetParam().UnidirectionalStreams,
0 // ServerInitiatedStreams
0, // ServerInitiatedStreams
0 // FifoScheduling
};
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_CONNECT_AND_PING, Params));
} else {
@ -663,7 +670,8 @@ TEST_P(WithSend0RttArgs1, Send0Rtt) {
false, // ServerRejectZeroRtt
GetParam().UseSendBuffer,
GetParam().UnidirectionalStreams,
false); // ServerInitiatedStreams
false, // ServerInitiatedStreams
false); // FifoScheduling
}
}
@ -683,7 +691,8 @@ TEST_P(WithSend0RttArgs2, Reject0Rtt) {
1, // ServerRejectZeroRtt
0, // UseSendBuffer
0, // UnidirectionalStreams
0 // ServerInitiatedStreams
0, // ServerInitiatedStreams
0 // FifoScheduling
};
ASSERT_TRUE(DriverClient.Run(IOCTL_QUIC_RUN_CONNECT_AND_PING, Params));
} else {
@ -700,7 +709,8 @@ TEST_P(WithSend0RttArgs2, Reject0Rtt) {
true, // ServerRejectZeroRtt
false, // UseSendBuffer
false, // UnidirectionalStreams
false); // ServerInitiatedStreams
false, // ServerInitiatedStreams
false); // FifoScheduling
}
}

Просмотреть файл

@ -703,7 +703,8 @@ QuicTestCtlEvtIoDeviceControl(
Params->Params2.ServerRejectZeroRtt != 0,
Params->Params2.UseSendBuffer != 0,
Params->Params2.UnidirectionalStreams != 0,
Params->Params2.ServerInitiatedStreams != 0
Params->Params2.ServerInitiatedStreams != 0,
Params->Params2.FifoScheduling != 0
));
break;

Просмотреть файл

@ -607,6 +607,7 @@ struct PingStats
const uint64_t PayloadLength;
const uint32_t ConnectionCount;
const uint32_t StreamCount;
const bool FifoScheduling;
const bool UnidirectionalStreams;
const bool ServerInitiatedStreams;
const bool ZeroRtt;
@ -622,6 +623,7 @@ struct PingStats
uint64_t _PayloadLength,
uint32_t _ConnectionCount,
uint32_t _StreamCount,
bool _FifoScheduling,
bool _UnidirectionalStreams,
bool _ServerInitiatedStreams,
bool _ZeroRtt,
@ -632,6 +634,7 @@ struct PingStats
PayloadLength(_PayloadLength),
ConnectionCount(_ConnectionCount),
StreamCount(_StreamCount),
FifoScheduling(_FifoScheduling),
UnidirectionalStreams(_UnidirectionalStreams),
ServerInitiatedStreams(_ServerInitiatedStreams),
ZeroRtt(_ZeroRtt),
@ -701,6 +704,7 @@ PingStreamShutdown(
#if !QUIC_SEND_FAKE_LOSS
if (!ConnState->GetPingStats()->ServerInitiatedStreams &&
!ConnState->GetPingStats()->FifoScheduling &&
ConnState->GetPingStats()->ZeroRtt) {
if (Stream->GetBytesReceived() != 0 && // TODO - Support 0-RTT indication for Stream Open callback.
!Stream->GetUsedZeroRtt()) {
@ -811,6 +815,11 @@ ListenerAcceptPingConnection(
}
}
Connection->SetPriorityScheme(
Stats->FifoScheduling ?
QUIC_STREAM_SCHEDULING_SCHEME_FIFO :
QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN);
if (Stats->ServerInitiatedStreams) {
SendPingBurst(
Connection,
@ -849,6 +858,11 @@ NewPingConnection(
Connection->SetShutdownCompleteCallback(PingConnectionShutdown);
Connection->SetExpectedResumed(ClientStats->ZeroRtt);
Connection->SetPriorityScheme(
ClientStats->FifoScheduling ?
QUIC_STREAM_SCHEDULING_SCHEME_FIFO :
QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN);
if (ClientStats->ServerInitiatedStreams) {
Connection->SetPeerUnidiStreamCount((uint16_t)ClientStats->StreamCount);
Connection->SetPeerBidiStreamCount((uint16_t)ClientStats->StreamCount);
@ -875,14 +889,15 @@ QuicTestConnectAndPing(
_In_ bool ServerRejectZeroRtt,
_In_ bool UseSendBuffer,
_In_ bool UnidirectionalStreams,
_In_ bool ServerInitiatedStreams
_In_ bool ServerInitiatedStreams,
_In_ bool FifoScheduling
)
{
const uint32_t TimeoutMs = EstimateTimeoutMs(Length) * StreamBurstCount;
const uint16_t TotalStreamCount = (uint16_t)(StreamCount * StreamBurstCount);
PingStats ServerStats(Length, ConnectionCount, TotalStreamCount, UnidirectionalStreams, ServerInitiatedStreams, ClientZeroRtt && !ServerRejectZeroRtt, false, QUIC_STATUS_SUCCESS);
PingStats ClientStats(Length, ConnectionCount, TotalStreamCount, UnidirectionalStreams, ServerInitiatedStreams, ClientZeroRtt && !ServerRejectZeroRtt);
PingStats ServerStats(Length, ConnectionCount, TotalStreamCount, FifoScheduling, UnidirectionalStreams, ServerInitiatedStreams, ClientZeroRtt && !ServerRejectZeroRtt, false, QUIC_STATUS_SUCCESS);
PingStats ClientStats(Length, ConnectionCount, TotalStreamCount, FifoScheduling, UnidirectionalStreams, ServerInitiatedStreams, ClientZeroRtt && !ServerRejectZeroRtt);
MsQuicSession Session;
TEST_TRUE(Session.IsValid());
@ -1098,8 +1113,8 @@ QuicTestServerDisconnect(
void
)
{
PingStats ServerStats(UINT64_MAX - 1, 1, 1, TRUE, TRUE, FALSE, TRUE, QUIC_STATUS_CONNECTION_TIMEOUT);
PingStats ClientStats(UINT64_MAX - 1, 1, 1, TRUE, TRUE, FALSE, TRUE);
PingStats ServerStats(UINT64_MAX - 1, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE, QUIC_STATUS_CONNECTION_TIMEOUT);
PingStats ClientStats(UINT64_MAX - 1, 1, 1, TRUE, TRUE, TRUE, FALSE, TRUE);
{
MsQuicSession Session;
@ -1206,7 +1221,7 @@ QuicTestClientDisconnect(
// back to the client as it continues to receive the client's UDP packets.
//
PingStats ClientStats(UINT64_MAX - 1, 1, 1, TRUE, FALSE, FALSE, TRUE,
PingStats ClientStats(UINT64_MAX - 1, 1, 1, TRUE, TRUE, FALSE, FALSE, TRUE,
StopListenerFirst ? QUIC_STATUS_CONNECTION_TIMEOUT : QUIC_STATUS_ABORTED);
{

Просмотреть файл

@ -643,6 +643,39 @@ TestConnection::SetShareUdpBinding(
&bValue);
}
QUIC_STREAM_SCHEDULING_SCHEME
TestConnection::GetPriorityScheme()
{
QUIC_STREAM_SCHEDULING_SCHEME value;
uint32_t valueSize = sizeof(value);
QUIC_STATUS Status =
MsQuic->GetParam(
QuicConnection,
QUIC_PARAM_LEVEL_CONNECTION,
QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME,
&valueSize,
&value);
if (QUIC_FAILED(Status)) {
value = QUIC_STREAM_SCHEDULING_SCHEME_FIFO;
TEST_FAILURE("MsQuic->GetParam(CONN_PRIORITY_SCHEME) failed, 0x%x.", Status);
}
return value;
}
QUIC_STATUS
TestConnection::SetPriorityScheme(
QUIC_STREAM_SCHEDULING_SCHEME value
)
{
return
MsQuic->SetParam(
QuicConnection,
QUIC_PARAM_LEVEL_CONNECTION,
QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME,
sizeof(value),
&value);
}
QUIC_STATUS
TestConnection::SetSecurityConfig(
QUIC_SEC_CONFIG* value

Просмотреть файл

@ -210,6 +210,9 @@ public:
bool GetShareUdpBinding();
QUIC_STATUS SetShareUdpBinding(bool value);
QUIC_STREAM_SCHEDULING_SCHEME GetPriorityScheme();
QUIC_STATUS SetPriorityScheme(QUIC_STREAM_SCHEDULING_SCHEME value);
QUIC_STATUS SetSecurityConfig(QUIC_SEC_CONFIG* value);
bool HasNewZeroRttTicket();