зеркало из https://github.com/microsoft/msquic.git
Perf Protocol Refactor (#785)
This commit is contained in:
Родитель
f8e42f0d31
Коммит
1f4bfd765b
|
@ -7,7 +7,7 @@
|
|||
"Arch": ["x64", "x86", "arm", "arm64"],
|
||||
"Exe": "quicperf",
|
||||
"Arguments": {
|
||||
"All": "-TestName:Throughput -ServerMode:1 -port:4433 -peer_uni:1 -connections:10",
|
||||
"All": "-ServerMode:1",
|
||||
"Loopback": "-selfsign:1",
|
||||
"Remote": "-thumbprint:$Thumbprint -machine_cert:1 -cert_store:My"
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
|||
"Arch": ["x64", "x86", "arm", "arm64"],
|
||||
"Exe": "quicperf",
|
||||
"Arguments": {
|
||||
"All": "-TestName:Throughput -target:$RemoteAddress -port:4433 -bind:$LocalAddress:4434 -ip:4 -core:0 -uni:1 -length:2000000000",
|
||||
"All": "-ServerMode:0 -TestName:Throughput -target:$RemoteAddress -bind:$LocalAddress:4434 -ip:4 -core:0 -uni:1 -length:2000000000",
|
||||
"Loopback": "",
|
||||
"Remote": ""
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
|||
},
|
||||
"Remote": {
|
||||
"On": "",
|
||||
"Off": "-encrypt:0"
|
||||
"Off": ""
|
||||
},
|
||||
"Default": "On"
|
||||
},
|
||||
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
"Remote": {
|
||||
"On": "",
|
||||
"Off": "-sendbuf:0"
|
||||
"Off": ""
|
||||
},
|
||||
"Default": "Off"
|
||||
}
|
||||
|
@ -63,7 +63,7 @@
|
|||
"Arch": ["x64", "arm"],
|
||||
"Exe": "quicperf",
|
||||
"Arguments": {
|
||||
"All": "-TestName:Throughput -ServerMode:1 -port:4433 -selfsign:1 -peer_uni:1 -connections:10",
|
||||
"All": "-ServerMode:1 -selfsign:1",
|
||||
"Loopback": "",
|
||||
"Remote": ""
|
||||
}
|
||||
|
@ -74,7 +74,7 @@
|
|||
"Arch": ["x64", "arm"],
|
||||
"Exe": "quicperf",
|
||||
"Arguments": {
|
||||
"All": "-TestName:Throughput -target:$RemoteAddress -port:4433 -uni:1 -length:2000000000",
|
||||
"All": "-ServerMode:0 -TestName:Throughput -target:$RemoteAddress -uni:1 -length:2000000000",
|
||||
"Loopback": "",
|
||||
"Remote": ""
|
||||
}
|
||||
|
@ -88,7 +88,7 @@
|
|||
},
|
||||
"Remote": {
|
||||
"On": "",
|
||||
"Off": "-encrypt:0"
|
||||
"Off": ""
|
||||
},
|
||||
"Default": "On"
|
||||
},
|
||||
|
@ -100,7 +100,7 @@
|
|||
},
|
||||
"Remote": {
|
||||
"On": "",
|
||||
"Off": "-sendbuf:0"
|
||||
"Off": ""
|
||||
},
|
||||
"Default": "Off"
|
||||
}
|
||||
|
@ -119,7 +119,7 @@
|
|||
"Arch": ["x64", "x86", "arm", "arm64"],
|
||||
"Exe": "quicperf",
|
||||
"Arguments": {
|
||||
"All": "-TestName:RPS -ServerMode:1 -iter:10",
|
||||
"All": "-ServerMode:1",
|
||||
"Loopback": "-selfsign:1",
|
||||
"Remote": "-thumbprint:$Thumbprint -machine_cert:1 -cert_store:My"
|
||||
}
|
||||
|
@ -130,7 +130,7 @@
|
|||
"Arch": ["x64", "x86", "arm", "arm64"],
|
||||
"Exe": "quicperf",
|
||||
"Arguments": {
|
||||
"All": "-TestName:RPS -target:$RemoteAddress",
|
||||
"All": "-ServerMode:0 -TestName:RPS -target:$RemoteAddress",
|
||||
"Loopback": "",
|
||||
"Remote": ""
|
||||
}
|
||||
|
@ -160,17 +160,17 @@
|
|||
{
|
||||
"Name": "ResponseSize",
|
||||
"Local": {
|
||||
"0": "",
|
||||
"512": "",
|
||||
"4096": "",
|
||||
"16384": ""
|
||||
},
|
||||
"Remote": {
|
||||
"0": "-response:0",
|
||||
"512": "-response:512",
|
||||
"4096": "-response:4096",
|
||||
"16384": "-response:16384"
|
||||
},
|
||||
"Remote": {
|
||||
"0": "",
|
||||
"512": "",
|
||||
"4096": "",
|
||||
"16384": ""
|
||||
},
|
||||
"Default": "4096"
|
||||
}
|
||||
],
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
# Licensed under the MIT License.
|
||||
|
||||
set(SOURCES
|
||||
PerfServer.cpp
|
||||
quicmain.cpp
|
||||
ThroughputServer.cpp
|
||||
ThroughputClient.cpp
|
||||
RpsServer.cpp
|
||||
RpsClient.cpp
|
||||
ThroughputClient.cpp
|
||||
)
|
||||
|
||||
# Allow CLOG to preprocess all the source files.
|
||||
|
|
|
@ -12,28 +12,24 @@ Abstract:
|
|||
|
||||
#pragma once
|
||||
|
||||
#define THROUGHPUT_DEFAULT_PORT 4433
|
||||
#define THROUGHPUT_ALPN "tput"
|
||||
#define THROUGHPUT_DEFAULT_DISCONNECT_TIMEOUT (10 * 1000)
|
||||
#define THROUGHPUT_DEFAULT_IDLE_TIMEOUT 1000
|
||||
#define THROUGHPUT_SERVER_PEER_UNI 1
|
||||
#define THROUGHPUT_CLIENT_UNI 1
|
||||
#define THROUGHPUT_DEFAULT_IO_SIZE_BUFFERED 0x10000
|
||||
#define THROUGHPUT_DEFAULT_IO_SIZE_NONBUFFERED 0x100000
|
||||
#define THROGHTPUT_DEFAULT_SEND_COUNT_BUFFERED 1
|
||||
#define THROUGHPUT_DEFAULT_SEND_COUNT_NONBUFFERED 8
|
||||
#define PERF_ALPN "perf"
|
||||
#define PERF_DEFAULT_PORT 4433
|
||||
#define PERF_DEFAULT_DISCONNECT_TIMEOUT (10 * 1000)
|
||||
#define PERF_DEFAULT_IDLE_TIMEOUT (30 * 1000)
|
||||
#define PERF_DEFAULT_STREAM_COUNT 100
|
||||
|
||||
#define RPS_ALPN "rps"
|
||||
#define RPS_MAX_CLIENT_PORT_COUNT 256
|
||||
#define RPS_MAX_BIDI_STREAM_COUNT 100
|
||||
#define RPS_DEFAULT_PORT 4433
|
||||
#define RPS_DEFAULT_DISCONNECT_TIMEOUT (10 * 1000)
|
||||
#define RPS_DEFAULT_IDLE_TIMEOUT 30000
|
||||
#define RPS_DEFAULT_ITERATIONS 1
|
||||
#define RPS_DEFAULT_RUN_TIME 10000
|
||||
#define RPS_DEFAULT_CONNECTION_COUNT 1000
|
||||
#define RPS_DEFAULT_PARALLEL_REQUEST_COUNT 2
|
||||
#define RPS_DEFAULT_REQUEST_LENGTH 0
|
||||
#define RPS_DEFAULT_RESPONSE_LENGTH 0
|
||||
#define RPS_ALL_CONNECT_TIMEOUT 10000
|
||||
#define RPS_IDLE_WAIT 2000
|
||||
#define PERF_DEFAULT_IO_SIZE_BUFFERED 0x10000
|
||||
#define PERF_DEFAULT_IO_SIZE_NONBUFFERED 0x100000
|
||||
#define PERF_DEFAULT_SEND_COUNT_BUFFERED 1
|
||||
#define PERF_DEFAULT_SEND_COUNT_NONBUFFERED 8
|
||||
|
||||
#define TPUT_DEFAULT_IDLE_TIMEOUT (1 * 1000)
|
||||
|
||||
#define RPS_MAX_CLIENT_PORT_COUNT 256
|
||||
#define RPS_DEFAULT_RUN_TIME (10 * 1000)
|
||||
#define RPS_DEFAULT_CONNECTION_COUNT 1000
|
||||
#define RPS_DEFAULT_PARALLEL_REQUEST_COUNT 2
|
||||
#define RPS_DEFAULT_REQUEST_LENGTH 0
|
||||
#define RPS_DEFAULT_RESPONSE_LENGTH 0
|
||||
#define RPS_ALL_CONNECT_TIMEOUT 10000
|
||||
#define RPS_IDLE_WAIT 2000
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License.
|
||||
|
||||
Abstract:
|
||||
|
||||
QUIC Perf Server Implementation.
|
||||
|
||||
--*/
|
||||
|
||||
#include "PerfServer.h"
|
||||
|
||||
#ifdef QUIC_CLOG
|
||||
#include "PerfServer.cpp.clog.h"
|
||||
#endif
|
||||
|
||||
static
|
||||
void
|
||||
PrintHelp(
|
||||
) {
|
||||
WriteOutput(
|
||||
"\n"
|
||||
"Perf Server options:\n"
|
||||
"\n"
|
||||
" -port:<####> The UDP port of the server. (def:%u)\n"
|
||||
" -selfsign:<0/1> Uses a self-signed server certificate.\n"
|
||||
" -thumbprint:<cert_hash> The hash or thumbprint of the certificate to use.\n"
|
||||
" -cert_store:<store name> The certificate store to search for the thumbprint in.\n"
|
||||
" -machine_cert:<0/1> Use the machine, or current user's, certificate store. (def:0)\n"
|
||||
"\n",
|
||||
PERF_DEFAULT_PORT
|
||||
);
|
||||
}
|
||||
|
||||
PerfServer::PerfServer(
|
||||
_In_ PerfSelfSignedConfiguration* SelfSignedConfig
|
||||
) : SelfSignedConfig{SelfSignedConfig} {
|
||||
if (Session.IsValid()) {
|
||||
Session.SetAutoCleanup();
|
||||
Session.SetPeerBidiStreamCount(PERF_DEFAULT_STREAM_COUNT);
|
||||
Session.SetPeerUnidiStreamCount(PERF_DEFAULT_STREAM_COUNT);
|
||||
Session.SetDisconnectTimeout(PERF_DEFAULT_DISCONNECT_TIMEOUT);
|
||||
Session.SetIdleTimeout(PERF_DEFAULT_IDLE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
PerfServer::~PerfServer() {
|
||||
if (DataBufferBuffered) {
|
||||
QUIC_FREE(DataBufferBuffered);
|
||||
}
|
||||
if (DataBufferNonBuffered) {
|
||||
QUIC_FREE(DataBufferNonBuffered);
|
||||
}
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
PerfServer::Init(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Null_terminated_ char* argv[]
|
||||
) {
|
||||
if (argc > 0 && (IsArg(argv[0], "?") || IsArg(argv[0], "help"))) {
|
||||
PrintHelp();
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!Listener.IsValid()) {
|
||||
return Listener.GetInitStatus();
|
||||
}
|
||||
|
||||
TryGetValue(argc, argv, "port", &Port);
|
||||
|
||||
QUIC_STATUS Status = SecurityConfig.Initialize(argc, argv, Registration, SelfSignedConfig);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
PrintHelp();
|
||||
return Status;
|
||||
}
|
||||
|
||||
DataBufferBuffered = (QUIC_BUFFER*)QUIC_ALLOC_NONPAGED(sizeof(QUIC_BUFFER) + PERF_DEFAULT_IO_SIZE_BUFFERED);
|
||||
if (!DataBufferBuffered) {
|
||||
return QUIC_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
DataBufferBuffered->Length = PERF_DEFAULT_IO_SIZE_BUFFERED;
|
||||
DataBufferBuffered->Buffer = (uint8_t*)(DataBufferBuffered + 1);
|
||||
for (uint32_t i = 0; i < PERF_DEFAULT_IO_SIZE_BUFFERED; ++i) {
|
||||
DataBufferBuffered->Buffer[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
DataBufferNonBuffered = (QUIC_BUFFER*)QUIC_ALLOC_NONPAGED(sizeof(QUIC_BUFFER) + PERF_DEFAULT_IO_SIZE_NONBUFFERED);
|
||||
if (!DataBufferNonBuffered) {
|
||||
return QUIC_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
DataBufferNonBuffered->Length = PERF_DEFAULT_IO_SIZE_BUFFERED;
|
||||
DataBufferNonBuffered->Buffer = (uint8_t*)(DataBufferNonBuffered + 1);
|
||||
for (uint32_t i = 0; i < PERF_DEFAULT_IO_SIZE_BUFFERED; ++i) {
|
||||
DataBufferNonBuffered->Buffer[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
PerfServer::Start(
|
||||
_In_ QUIC_EVENT* _StopEvent
|
||||
) {
|
||||
QUIC_ADDR Address;
|
||||
QuicAddrSetFamily(&Address, AF_UNSPEC);
|
||||
QuicAddrSetPort(&Address, Port);
|
||||
|
||||
StopEvent = _StopEvent;
|
||||
|
||||
return
|
||||
Listener.Start(
|
||||
&Address,
|
||||
[](HQUIC Handle, void* Context, QUIC_LISTENER_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((PerfServer*)Context)->ListenerCallback(Handle, Event);
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
PerfServer::Wait(
|
||||
_In_ int Timeout
|
||||
) {
|
||||
if (Timeout > 0) {
|
||||
QuicEventWaitWithTimeout(*StopEvent, Timeout);
|
||||
} else {
|
||||
QuicEventWaitForever(*StopEvent);
|
||||
}
|
||||
Session.Shutdown(QUIC_CONNECTION_SHUTDOWN_FLAG_NONE, 0);
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
PerfServer::ListenerCallback(
|
||||
_In_ HQUIC /*ListenerHandle*/,
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_LISTENER_EVENT_NEW_CONNECTION: {
|
||||
BOOLEAN value = TRUE;
|
||||
if (QUIC_FAILED(
|
||||
MsQuic->SetParam(
|
||||
Event->NEW_CONNECTION.Connection,
|
||||
QUIC_PARAM_LEVEL_CONNECTION,
|
||||
QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION,
|
||||
sizeof(value),
|
||||
&value))) {
|
||||
WriteOutput("MsQuic->SetParam (CONN_DISABLE_1RTT_ENCRYPTION) failed!\n");
|
||||
}
|
||||
QUIC_CONNECTION_CALLBACK_HANDLER Handler =
|
||||
[](HQUIC Conn, void* Context, QUIC_CONNECTION_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((PerfServer*)Context)->
|
||||
ConnectionCallback(
|
||||
Conn,
|
||||
Event);
|
||||
};
|
||||
MsQuic->SetCallbackHandler(Event->NEW_CONNECTION.Connection, (void*)Handler, this);
|
||||
Event->NEW_CONNECTION.SecurityConfig = SecurityConfig;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
PerfServer::ConnectionCallback(
|
||||
_In_ HQUIC ConnectionHandle,
|
||||
_Inout_ QUIC_CONNECTION_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE:
|
||||
MsQuic->ConnectionClose(ConnectionHandle);
|
||||
break;
|
||||
case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED: {
|
||||
auto Context = StreamContextAllocator.Alloc(this, Event->PEER_STREAM_STARTED.Flags & QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL);
|
||||
if (!Context) {
|
||||
return QUIC_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
QUIC_STREAM_CALLBACK_HANDLER Handler =
|
||||
[](HQUIC Stream, void* Context, QUIC_STREAM_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((PerfServer::StreamContext*)Context)->Server->
|
||||
StreamCallback(
|
||||
(PerfServer::StreamContext*)Context,
|
||||
Stream,
|
||||
Event);
|
||||
};
|
||||
MsQuic->SetCallbackHandler(Event->PEER_STREAM_STARTED.Stream, (void*)Handler, Context);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
PerfServer::StreamCallback(
|
||||
_In_ PerfServer::StreamContext* Context,
|
||||
_In_ HQUIC StreamHandle,
|
||||
_Inout_ QUIC_STREAM_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_STREAM_EVENT_RECEIVE:
|
||||
if (!Context->ResponseSizeSet) {
|
||||
uint8_t* Dest = (uint8_t*)&Context->ResponseSize;
|
||||
uint64_t Offset = Event->RECEIVE.AbsoluteOffset;
|
||||
for (uint32_t i = 0; Offset < sizeof(uint64_t) && i < Event->RECEIVE.BufferCount; ++i) {
|
||||
uint32_t Length = min((uint32_t)(sizeof(uint64_t) - Offset), Event->RECEIVE.Buffers[i].Length);
|
||||
memcpy(Dest + Offset, Event->RECEIVE.Buffers[i].Buffer, Length);
|
||||
Offset += Length;
|
||||
}
|
||||
if (Offset == sizeof(uint64_t)) {
|
||||
Context->ResponseSize = QuicByteSwapUint64(Context->ResponseSize);
|
||||
Context->ResponseSizeSet = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_SEND_COMPLETE:
|
||||
Context->OutstandingSends--;
|
||||
if (!Event->SEND_COMPLETE.Canceled) {
|
||||
SendResponse(Context, StreamHandle);
|
||||
}
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN:
|
||||
if (!Context->ResponseSizeSet) {
|
||||
MsQuic->StreamShutdown(StreamHandle, QUIC_STREAM_SHUTDOWN_FLAG_ABORT, 0);
|
||||
} else if (Context->ResponseSize != 0) {
|
||||
if (Context->Unidirectional) {
|
||||
// TODO - Not supported right now
|
||||
MsQuic->StreamShutdown(StreamHandle, QUIC_STREAM_SHUTDOWN_FLAG_ABORT, 0);
|
||||
} else {
|
||||
SendResponse(Context, StreamHandle);
|
||||
}
|
||||
} else if (!Context->Unidirectional) {
|
||||
MsQuic->StreamShutdown(StreamHandle, QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, 0);
|
||||
}
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_PEER_SEND_ABORTED:
|
||||
case QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED:
|
||||
MsQuic->StreamShutdown(StreamHandle, QUIC_STREAM_SHUTDOWN_FLAG_ABORT, 0);
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE: {
|
||||
MsQuic->StreamClose(StreamHandle);
|
||||
StreamContextAllocator.Free(Context);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
PerfServer::SendResponse(
|
||||
_In_ PerfServer::StreamContext* Context,
|
||||
_In_ HQUIC StreamHandle
|
||||
)
|
||||
{
|
||||
while (Context->BytesSent < Context->ResponseSize &&
|
||||
Context->OutstandingSends < Context->MaxOutstandingSends) {
|
||||
|
||||
uint64_t BytesLeftToSend = Context->ResponseSize - Context->BytesSent;
|
||||
uint32_t IoSize = Context->IoSize;
|
||||
QUIC_BUFFER* Buffer = DataBufferNonBuffered; // TODO - Support buffered
|
||||
QUIC_SEND_FLAGS Flags = QUIC_SEND_FLAG_NONE;
|
||||
|
||||
if ((uint64_t)IoSize >= BytesLeftToSend) {
|
||||
IoSize = (uint32_t)BytesLeftToSend;
|
||||
Context->LastBuffer.Buffer = Buffer->Buffer;
|
||||
Context->LastBuffer.Length = IoSize;
|
||||
Buffer = &Context->LastBuffer;
|
||||
Flags = QUIC_SEND_FLAG_FIN;
|
||||
}
|
||||
|
||||
Context->BytesSent += IoSize;
|
||||
Context->OutstandingSends++;
|
||||
|
||||
MsQuic->StreamSend(StreamHandle, Buffer, 1, Flags, nullptr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License.
|
||||
|
||||
Abstract:
|
||||
|
||||
QUIC Perf Server declaration. Defines the functions and
|
||||
variables used in the PerfServer class.
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PerfHelpers.h"
|
||||
#include "PerfBase.h"
|
||||
#include "PerfCommon.h"
|
||||
|
||||
class PerfServer : public PerfBase {
|
||||
public:
|
||||
PerfServer(
|
||||
_In_ PerfSelfSignedConfiguration* SelfSignedConfig
|
||||
);
|
||||
|
||||
~PerfServer() override;
|
||||
|
||||
QUIC_STATUS
|
||||
Init(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Null_terminated_ char* argv[]
|
||||
) override;
|
||||
|
||||
QUIC_STATUS
|
||||
Start(
|
||||
_In_ QUIC_EVENT* StopEvent
|
||||
) override;
|
||||
|
||||
QUIC_STATUS
|
||||
Wait(
|
||||
int Timeout
|
||||
) override;
|
||||
|
||||
private:
|
||||
|
||||
struct StreamContext {
|
||||
StreamContext(
|
||||
PerfServer* Server, bool Unidirectional) :
|
||||
Server{Server}, Unidirectional{Unidirectional} { }
|
||||
PerfServer* Server;
|
||||
bool Unidirectional;
|
||||
bool BufferedIo{false};
|
||||
bool ResponseSizeSet{false};
|
||||
uint64_t ResponseSize{0};
|
||||
uint64_t BytesSent{0};
|
||||
uint32_t OutstandingSends{0};
|
||||
uint32_t MaxOutstandingSends{PERF_DEFAULT_SEND_COUNT_NONBUFFERED};
|
||||
uint32_t IoSize{PERF_DEFAULT_IO_SIZE_NONBUFFERED};
|
||||
QUIC_BUFFER LastBuffer;
|
||||
};
|
||||
|
||||
QUIC_STATUS
|
||||
ListenerCallback(
|
||||
_In_ HQUIC ListenerHandle,
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
ConnectionCallback(
|
||||
_In_ HQUIC ConnectionHandle,
|
||||
_Inout_ QUIC_CONNECTION_EVENT* Event
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
StreamCallback(
|
||||
_In_ StreamContext* Context,
|
||||
_In_ HQUIC StreamHandle,
|
||||
_Inout_ QUIC_STREAM_EVENT* Event
|
||||
);
|
||||
|
||||
void
|
||||
SendResponse(
|
||||
_In_ StreamContext* Context,
|
||||
_In_ HQUIC StreamHandle
|
||||
);
|
||||
|
||||
MsQuicRegistration Registration;
|
||||
MsQuicSession Session {Registration, PERF_ALPN};
|
||||
MsQuicListener Listener {Session};
|
||||
PerfSelfSignedConfiguration* SelfSignedConfig;
|
||||
PerfSecurityConfig SecurityConfig;
|
||||
uint16_t Port {PERF_DEFAULT_PORT};
|
||||
QUIC_EVENT* StopEvent {nullptr};
|
||||
QUIC_BUFFER* DataBufferBuffered {nullptr};
|
||||
QUIC_BUFFER* DataBufferNonBuffered {nullptr};
|
||||
QuicPoolAllocator<StreamContext> StreamContextAllocator;
|
||||
};
|
|
@ -23,17 +23,20 @@ PrintHelp(
|
|||
"\n"
|
||||
"RPS Client options:\n"
|
||||
"\n"
|
||||
" -target:<####> The target server to connect to.\n"
|
||||
" -runtime:<####> The total runtime (in ms). (def:%u)\n"
|
||||
" -port:<####> The UDP port of the server. (def:%u)\n"
|
||||
" -conns:<####> The number of connections to use. (def:%u)\n"
|
||||
" -parallel:<####> The number of parallel requests per connection. (def:%u)\n"
|
||||
" -request:<####> The length of request payloads. (def:%u)\n"
|
||||
" -response:<####> The length of request payloads. (def:%u)\n"
|
||||
"\n",
|
||||
RPS_DEFAULT_RUN_TIME,
|
||||
THROUGHPUT_DEFAULT_PORT,
|
||||
PERF_DEFAULT_PORT,
|
||||
RPS_DEFAULT_CONNECTION_COUNT,
|
||||
RPS_DEFAULT_PARALLEL_REQUEST_COUNT,
|
||||
RPS_DEFAULT_REQUEST_LENGTH
|
||||
RPS_DEFAULT_REQUEST_LENGTH,
|
||||
RPS_DEFAULT_RESPONSE_LENGTH
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -41,8 +44,8 @@ RpsClient::RpsClient() {
|
|||
QuicEventInitialize(&AllConnected, TRUE, FALSE);
|
||||
if (Session.IsValid()) {
|
||||
Session.SetAutoCleanup();
|
||||
Session.SetDisconnectTimeout(RPS_DEFAULT_DISCONNECT_TIMEOUT);
|
||||
Session.SetIdleTimeout(RPS_DEFAULT_IDLE_TIMEOUT);
|
||||
Session.SetDisconnectTimeout(PERF_DEFAULT_DISCONNECT_TIMEOUT);
|
||||
Session.SetIdleTimeout(PERF_DEFAULT_IDLE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,15 +89,17 @@ RpsClient::Init(
|
|||
TryGetValue(argc, argv, "port", &Port);
|
||||
TryGetValue(argc, argv, "conns", &ConnectionCount);
|
||||
TryGetValue(argc, argv, "request", &RequestLength);
|
||||
TryGetValue(argc, argv, "response", &ResponseLength);
|
||||
|
||||
RequestBuffer = (QUIC_BUFFER*)QUIC_ALLOC_NONPAGED(sizeof(QUIC_BUFFER) + RequestLength);
|
||||
RequestBuffer = (QUIC_BUFFER*)QUIC_ALLOC_NONPAGED(sizeof(QUIC_BUFFER) + sizeof(uint64_t) + RequestLength);
|
||||
if (!RequestBuffer) {
|
||||
return QUIC_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
RequestBuffer->Length = RequestLength;
|
||||
RequestBuffer->Length = sizeof(uint64_t) + RequestLength;
|
||||
RequestBuffer->Buffer = (uint8_t*)(RequestBuffer + 1);
|
||||
*(uint64_t*)(RequestBuffer->Buffer) = QuicByteSwapUint64(ResponseLength);
|
||||
for (uint32_t i = 0; i < RequestLength; ++i) {
|
||||
RequestBuffer->Buffer[i] = (uint8_t)i;
|
||||
RequestBuffer->Buffer[sizeof(uint64_t) + i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
|
|
|
@ -59,13 +59,14 @@ private:
|
|||
);
|
||||
|
||||
MsQuicRegistration Registration;
|
||||
MsQuicSession Session{Registration, RPS_ALPN};
|
||||
uint16_t Port {RPS_DEFAULT_PORT};
|
||||
MsQuicSession Session{Registration, PERF_ALPN};
|
||||
uint16_t Port {PERF_DEFAULT_PORT};
|
||||
UniquePtr<char[]> Target;
|
||||
uint32_t RunTime {RPS_DEFAULT_RUN_TIME};
|
||||
uint32_t ConnectionCount {RPS_DEFAULT_CONNECTION_COUNT};
|
||||
uint32_t ParallelRequests {RPS_DEFAULT_PARALLEL_REQUEST_COUNT};
|
||||
uint32_t RequestLength {RPS_DEFAULT_REQUEST_LENGTH};
|
||||
uint32_t ResponseLength {RPS_DEFAULT_RESPONSE_LENGTH};
|
||||
QUIC_BUFFER* RequestBuffer {nullptr};
|
||||
QUIC_EVENT* CompletionEvent {nullptr};
|
||||
QUIC_ADDR LocalAddresses[RPS_MAX_CLIENT_PORT_COUNT];
|
||||
|
|
|
@ -1,205 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License.
|
||||
|
||||
Abstract:
|
||||
|
||||
QUIC Perf RPS Server Implementation.
|
||||
|
||||
--*/
|
||||
|
||||
#include "RpsServer.h"
|
||||
|
||||
#ifdef QUIC_CLOG
|
||||
#include "RpsServer.cpp.clog.h"
|
||||
#endif
|
||||
|
||||
static
|
||||
void
|
||||
PrintHelp(
|
||||
) {
|
||||
WriteOutput(
|
||||
"\n"
|
||||
"RPS Server options:\n"
|
||||
"\n"
|
||||
" -iter:<####> The number of client iterations run. (def:%u)\n"
|
||||
" -port:<####> The UDP port of the server. (def:%u)\n"
|
||||
" -thumbprint:<cert_hash> The hash or thumbprint of the certificate to use.\n"
|
||||
" -cert_store:<store name> The certificate store to search for the thumbprint in.\n"
|
||||
" -machine_cert:<0/1> Use the machine, or current user's, certificate store. (def:0)\n"
|
||||
" -response:<####> The length of response payloads. (def:%u)\n"
|
||||
"\n",
|
||||
RPS_DEFAULT_ITERATIONS,
|
||||
RPS_DEFAULT_PORT,
|
||||
RPS_DEFAULT_RESPONSE_LENGTH
|
||||
);
|
||||
}
|
||||
|
||||
RpsServer::RpsServer(
|
||||
_In_ PerfSelfSignedConfiguration* SelfSignedConfig
|
||||
) : SelfSignedConfig(SelfSignedConfig) {
|
||||
if (Session.IsValid()) {
|
||||
Session.SetAutoCleanup();
|
||||
Session.SetPeerBidiStreamCount(RPS_MAX_BIDI_STREAM_COUNT);
|
||||
Session.SetDisconnectTimeout(RPS_DEFAULT_DISCONNECT_TIMEOUT);
|
||||
Session.SetIdleTimeout(RPS_DEFAULT_IDLE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
RpsServer::~RpsServer() {
|
||||
if (ResponseBuffer) {
|
||||
QUIC_FREE(ResponseBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
RpsServer::Init(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Null_terminated_ char* argv[]
|
||||
) {
|
||||
if (argc > 0 && (IsArg(argv[0], "?") || IsArg(argv[0], "help"))) {
|
||||
PrintHelp();
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!Listener.IsValid()) {
|
||||
return Listener.GetInitStatus();
|
||||
}
|
||||
|
||||
TryGetValue(argc, argv, "iter", &Iterations);
|
||||
TryGetValue(argc, argv, "port", &Port);
|
||||
TryGetValue(argc, argv, "response", &ResponseLength);
|
||||
|
||||
ResponseBuffer = (QUIC_BUFFER*)QUIC_ALLOC_NONPAGED(sizeof(QUIC_BUFFER) + ResponseLength);
|
||||
if (!ResponseBuffer) {
|
||||
return QUIC_STATUS_OUT_OF_MEMORY;
|
||||
}
|
||||
ResponseBuffer->Length = ResponseLength;
|
||||
ResponseBuffer->Buffer = (uint8_t*)(ResponseBuffer + 1);
|
||||
for (uint32_t i = 0; i < ResponseLength; ++i) {
|
||||
ResponseBuffer->Buffer[i] = (uint8_t)i;
|
||||
}
|
||||
|
||||
return SecurityConfig.Initialize(argc, argv, Registration, SelfSignedConfig);
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
RpsServer::Start(
|
||||
_In_ QUIC_EVENT* StopEvent
|
||||
) {
|
||||
QUIC_ADDR Address;
|
||||
QuicAddrSetFamily(&Address, AF_UNSPEC);
|
||||
QuicAddrSetPort(&Address, Port);
|
||||
|
||||
CompletionEvent = StopEvent;
|
||||
|
||||
return
|
||||
Listener.Start(
|
||||
&Address,
|
||||
[](HQUIC Handle, void* Context, QUIC_LISTENER_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((RpsServer*)Context)->ListenerCallback(Handle, Event);
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
RpsServer::Wait(
|
||||
_In_ int Timeout
|
||||
) {
|
||||
if (Timeout > 0) {
|
||||
QuicEventWaitWithTimeout(*CompletionEvent, Timeout);
|
||||
} else {
|
||||
QuicEventWaitForever(*CompletionEvent);
|
||||
}
|
||||
Session.Shutdown(QUIC_CONNECTION_SHUTDOWN_FLAG_NONE, 0);
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
RpsServer::ListenerCallback(
|
||||
_In_ HQUIC /* ListenerHandle */,
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_LISTENER_EVENT_NEW_CONNECTION: {
|
||||
Event->NEW_CONNECTION.SecurityConfig = SecurityConfig;
|
||||
QUIC_CONNECTION_CALLBACK_HANDLER Handler =
|
||||
[](HQUIC Conn, void* Context, QUIC_CONNECTION_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((RpsServer*)Context)->
|
||||
ConnectionCallback(
|
||||
Conn,
|
||||
Event);
|
||||
};
|
||||
BOOLEAN Opt = FALSE;
|
||||
MsQuic->SetParam(
|
||||
Event->NEW_CONNECTION.Connection,
|
||||
QUIC_PARAM_LEVEL_CONNECTION,
|
||||
QUIC_PARAM_CONN_SEND_BUFFERING,
|
||||
sizeof(Opt),
|
||||
&Opt);
|
||||
MsQuic->SetCallbackHandler(
|
||||
Event->NEW_CONNECTION.Connection,
|
||||
(void*)Handler,
|
||||
this);
|
||||
InterlockedIncrement((volatile long*)&ActiveConnectionCount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
RpsServer::ConnectionCallback(
|
||||
_In_ HQUIC ConnectionHandle,
|
||||
_Inout_ QUIC_CONNECTION_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE:
|
||||
MsQuic->ConnectionClose(ConnectionHandle);
|
||||
if (InterlockedDecrement((volatile long*)&ActiveConnectionCount) == 0) {
|
||||
if (InterlockedDecrement((volatile long*)&Iterations) == 0) {
|
||||
QuicEventSet(*CompletionEvent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED: {
|
||||
QUIC_STREAM_CALLBACK_HANDLER Handler =
|
||||
[](HQUIC Stream, void* Context, QUIC_STREAM_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((RpsServer*)Context)->
|
||||
StreamCallback(
|
||||
Stream,
|
||||
Event);
|
||||
};
|
||||
MsQuic->SetCallbackHandler(Event->PEER_STREAM_STARTED.Stream, (void*)Handler, this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
RpsServer::StreamCallback(
|
||||
_In_ HQUIC StreamHandle,
|
||||
_Inout_ QUIC_STREAM_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN:
|
||||
MsQuic->StreamSend(StreamHandle, ResponseBuffer, 1, QUIC_SEND_FLAG_FIN, nullptr);
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_PEER_SEND_ABORTED:
|
||||
case QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED:
|
||||
MsQuic->StreamShutdown(StreamHandle, QUIC_STREAM_SHUTDOWN_FLAG_ABORT, 0);
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE:
|
||||
MsQuic->StreamClose(StreamHandle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License.
|
||||
|
||||
Abstract:
|
||||
|
||||
QUIC Perf RPS Server declaration. Defines the functions and variables used
|
||||
in the RpsServer class.
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PerfHelpers.h"
|
||||
#include "PerfBase.h"
|
||||
#include "PerfCommon.h"
|
||||
|
||||
class RpsServer : public PerfBase {
|
||||
public:
|
||||
RpsServer(
|
||||
_In_ PerfSelfSignedConfiguration* SelfSignedConfig
|
||||
);
|
||||
|
||||
~RpsServer() override;
|
||||
|
||||
QUIC_STATUS
|
||||
Init(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Null_terminated_ char* argv[]
|
||||
) override;
|
||||
|
||||
QUIC_STATUS
|
||||
Start(
|
||||
_In_ QUIC_EVENT* StopEvent
|
||||
) override;
|
||||
|
||||
QUIC_STATUS
|
||||
Wait(
|
||||
int Timeout
|
||||
) override;
|
||||
|
||||
private:
|
||||
|
||||
QUIC_STATUS
|
||||
ListenerCallback(
|
||||
_In_ HQUIC ListenerHandle,
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
ConnectionCallback(
|
||||
_In_ HQUIC ConnectionHandle,
|
||||
_Inout_ QUIC_CONNECTION_EVENT* Event
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
StreamCallback(
|
||||
_In_ HQUIC StreamHandle,
|
||||
_Inout_ QUIC_STREAM_EVENT* Event
|
||||
);
|
||||
|
||||
MsQuicRegistration Registration;
|
||||
MsQuicSession Session {Registration, RPS_ALPN};
|
||||
MsQuicListener Listener {Session};
|
||||
PerfSelfSignedConfiguration* SelfSignedConfig;
|
||||
PerfSecurityConfig SecurityConfig;
|
||||
uint32_t Iterations {RPS_DEFAULT_ITERATIONS};
|
||||
uint16_t Port {RPS_DEFAULT_PORT};
|
||||
uint32_t ResponseLength {RPS_DEFAULT_RESPONSE_LENGTH};
|
||||
uint32_t ActiveConnectionCount {0};
|
||||
QUIC_BUFFER* ResponseBuffer {nullptr};
|
||||
QUIC_EVENT* CompletionEvent {nullptr};
|
||||
};
|
|
@ -23,6 +23,7 @@ PrintHelp(
|
|||
"\n"
|
||||
"Throughput Client options:\n"
|
||||
"\n"
|
||||
" -target:<####> The target server to connect to.\n"
|
||||
#if _WIN32
|
||||
" -comp:<####> The compartment ID to run in.\n"
|
||||
" -core:<####> The CPU core to use for the main thread.\n"
|
||||
|
@ -36,9 +37,9 @@ PrintHelp(
|
|||
" -iosize:<####> The size of each send request queued. (buffered def:%u) (nonbuffered def:%u)\n"
|
||||
" -iocount:<####> The number of outstanding send requests to queue per stream. (buffered def:%u) (nonbuffered def:%u)\n"
|
||||
"\n",
|
||||
THROUGHPUT_DEFAULT_PORT,
|
||||
THROUGHPUT_DEFAULT_IO_SIZE_BUFFERED, THROUGHPUT_DEFAULT_IO_SIZE_NONBUFFERED,
|
||||
THROGHTPUT_DEFAULT_SEND_COUNT_BUFFERED, THROUGHPUT_DEFAULT_SEND_COUNT_NONBUFFERED
|
||||
PERF_DEFAULT_PORT,
|
||||
PERF_DEFAULT_IO_SIZE_BUFFERED, PERF_DEFAULT_IO_SIZE_NONBUFFERED,
|
||||
PERF_DEFAULT_SEND_COUNT_BUFFERED, PERF_DEFAULT_SEND_COUNT_NONBUFFERED
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -46,6 +47,7 @@ ThroughputClient::ThroughputClient(
|
|||
) {
|
||||
QuicZeroMemory(&LocalIpAddr, sizeof(LocalIpAddr));
|
||||
if (Session.IsValid()) {
|
||||
Session.SetIdleTimeout(TPUT_DEFAULT_IDLE_TIMEOUT);
|
||||
Session.SetAutoCleanup();
|
||||
}
|
||||
}
|
||||
|
@ -115,10 +117,10 @@ ThroughputClient::Init(
|
|||
|
||||
TryGetValue(argc, argv, "sendbuf", &UseSendBuffer);
|
||||
|
||||
IoSize = UseSendBuffer ? THROUGHPUT_DEFAULT_IO_SIZE_BUFFERED : THROUGHPUT_DEFAULT_IO_SIZE_NONBUFFERED;
|
||||
IoSize = UseSendBuffer ? PERF_DEFAULT_IO_SIZE_BUFFERED : PERF_DEFAULT_IO_SIZE_NONBUFFERED;
|
||||
TryGetValue(argc, argv, "iosize", &IoSize);
|
||||
|
||||
IoCount = UseSendBuffer ? THROGHTPUT_DEFAULT_SEND_COUNT_BUFFERED : THROUGHPUT_DEFAULT_SEND_COUNT_NONBUFFERED;
|
||||
IoCount = UseSendBuffer ? PERF_DEFAULT_SEND_COUNT_BUFFERED : PERF_DEFAULT_SEND_COUNT_NONBUFFERED;
|
||||
TryGetValue(argc, argv, "iocount", &IoCount);
|
||||
|
||||
size_t Len = strlen(Target);
|
||||
|
@ -274,6 +276,9 @@ ThroughputClient::Start(
|
|||
while (StrmData->BytesSent < Length && SendRequestCount < IoCount) {
|
||||
SendRequest* SendReq = SendRequestAllocator.Alloc(&BufferAllocator, IoSize, true);
|
||||
SendReq->SetLength(Length - StrmData->BytesSent);
|
||||
if (StrmData->BytesSent == 0) {
|
||||
QuicZeroMemory(SendReq->QuicBuffer.Buffer, sizeof(uint64_t));
|
||||
}
|
||||
StrmData->BytesSent += SendReq->QuicBuffer.Length;
|
||||
++SendRequestCount;
|
||||
Status =
|
||||
|
@ -300,7 +305,7 @@ ThroughputClient::Start(
|
|||
WriteOutput("Failed ConnectionStart 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
WriteOutput("Started!\n");
|
||||
|
||||
Shutdown.ConnHandle = nullptr;
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -82,13 +82,13 @@ private:
|
|||
);
|
||||
|
||||
MsQuicRegistration Registration;
|
||||
MsQuicSession Session{Registration, THROUGHPUT_ALPN};
|
||||
MsQuicSession Session{Registration, PERF_ALPN};
|
||||
QuicPoolAllocator<StreamData> StreamDataAllocator;
|
||||
QuicPoolAllocator<ConnectionData> ConnectionDataAllocator;
|
||||
QuicPoolAllocator<SendRequest> SendRequestAllocator;
|
||||
QuicPoolBufferAllocator BufferAllocator;
|
||||
UniquePtr<char[]> TargetData;
|
||||
uint16_t Port {THROUGHPUT_DEFAULT_PORT};
|
||||
uint16_t Port {PERF_DEFAULT_PORT};
|
||||
QUIC_EVENT* StopEvent {nullptr};
|
||||
uint64_t Length {0};
|
||||
// FIXME: unused: bool ConstructionSuccess {false};
|
||||
|
|
|
@ -1,202 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License.
|
||||
|
||||
Abstract:
|
||||
|
||||
QUIC Perf Throughput Server Implementation.
|
||||
|
||||
--*/
|
||||
|
||||
#include "ThroughputServer.h"
|
||||
|
||||
#ifdef QUIC_CLOG
|
||||
#include "ThroughputServer.cpp.clog.h"
|
||||
#endif
|
||||
|
||||
static
|
||||
void
|
||||
PrintHelp(
|
||||
) {
|
||||
WriteOutput(
|
||||
"\n"
|
||||
"Throughput Server options:\n"
|
||||
"\n"
|
||||
" -thumbprint:<cert_hash> The hash or thumbprint of the certificate to use.\n"
|
||||
" -cert_store:<store name> The certificate store to search for the thumbprint in.\n"
|
||||
" -machine_cert:<0/1> Use the machine, or current user's, certificate store. (def:0)\n"
|
||||
" -connections:<####> The number of connections to create. (def:0)\n"
|
||||
" -port:<####> The UDP port of the server. (def:%u)\n"
|
||||
"\n",
|
||||
THROUGHPUT_DEFAULT_PORT
|
||||
);
|
||||
}
|
||||
|
||||
ThroughputServer::ThroughputServer(
|
||||
_In_ PerfSelfSignedConfiguration* SelfSignedConfig
|
||||
) : SelfSignedConfig{SelfSignedConfig} {
|
||||
if (Session.IsValid()) {
|
||||
Session.SetAutoCleanup();
|
||||
Session.SetPeerUnidiStreamCount(THROUGHPUT_SERVER_PEER_UNI);
|
||||
Session.SetDisconnectTimeout(THROUGHPUT_DEFAULT_DISCONNECT_TIMEOUT);
|
||||
Session.SetIdleTimeout(THROUGHPUT_DEFAULT_IDLE_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
ThroughputServer::Init(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Null_terminated_ char* argv[]
|
||||
) {
|
||||
if (argc > 0 && (IsArg(argv[0], "?") || IsArg(argv[0], "help"))) {
|
||||
PrintHelp();
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!Listener.IsValid()) {
|
||||
return Listener.GetInitStatus();
|
||||
}
|
||||
|
||||
TryGetValue(argc, argv, "port", &Port);
|
||||
TryGetValue(argc, argv, "connections", &NumberOfConnections);
|
||||
|
||||
QUIC_STATUS Status = SecurityConfig.Initialize(argc, argv, Registration, SelfSignedConfig);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
PrintHelp();
|
||||
return Status;
|
||||
}
|
||||
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
ThroughputServer::Start(
|
||||
_In_ QUIC_EVENT* StopEvent
|
||||
) {
|
||||
QUIC_ADDR Address;
|
||||
QuicAddrSetFamily(&Address, AF_UNSPEC);
|
||||
QuicAddrSetPort(&Address, Port);
|
||||
|
||||
QUIC_STATUS Status =
|
||||
Listener.Start(
|
||||
&Address,
|
||||
[](HQUIC Handle, void* Context, QUIC_LISTENER_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((ThroughputServer*)Context)->ListenerCallback(Handle, Event);
|
||||
},
|
||||
this);
|
||||
if (QUIC_FAILED(Status)) {
|
||||
return Status;
|
||||
}
|
||||
RefCount = CountHelper{StopEvent};
|
||||
if (NumberOfConnections > 0) {
|
||||
for (uint32_t i = 0; i < NumberOfConnections; i++) {
|
||||
RefCount.AddItem();
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Add a single item so we can wait on the Count Helper
|
||||
//
|
||||
RefCount.AddItem();
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
ThroughputServer::Wait(
|
||||
_In_ int Timeout
|
||||
) {
|
||||
if (Timeout > 0) {
|
||||
RefCount.Wait(Timeout);
|
||||
} else {
|
||||
RefCount.WaitForever();
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
ThroughputServer::ListenerCallback(
|
||||
_In_ HQUIC /*ListenerHandle*/,
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_LISTENER_EVENT_NEW_CONNECTION: {
|
||||
Event->NEW_CONNECTION.SecurityConfig = SecurityConfig;
|
||||
QUIC_CONNECTION_CALLBACK_HANDLER Handler =
|
||||
[](HQUIC Conn, void* Context, QUIC_CONNECTION_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((ThroughputServer*)Context)->
|
||||
ConnectionCallback(
|
||||
Conn,
|
||||
Event);
|
||||
};
|
||||
MsQuic->SetCallbackHandler(
|
||||
Event->NEW_CONNECTION.Connection,
|
||||
(void*)Handler,
|
||||
this);
|
||||
BOOLEAN value = TRUE;
|
||||
if (QUIC_FAILED(
|
||||
MsQuic->SetParam(
|
||||
Event->NEW_CONNECTION.Connection,
|
||||
QUIC_PARAM_LEVEL_CONNECTION,
|
||||
QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION,
|
||||
sizeof(value),
|
||||
&value))) {
|
||||
WriteOutput("MsQuic->SetParam (CONN_DISABLE_1RTT_ENCRYPTION) failed!\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
ThroughputServer::ConnectionCallback(
|
||||
_In_ HQUIC ConnectionHandle,
|
||||
_Inout_ QUIC_CONNECTION_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE:
|
||||
MsQuic->ConnectionClose(ConnectionHandle);
|
||||
if (NumberOfConnections > 0) {
|
||||
RefCount.CompleteItem();
|
||||
}
|
||||
break;
|
||||
case QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED: {
|
||||
QUIC_STREAM_CALLBACK_HANDLER Handler =
|
||||
[](HQUIC Stream, void* Context, QUIC_STREAM_EVENT* Event) -> QUIC_STATUS {
|
||||
return ((ThroughputServer*)Context)->
|
||||
StreamCallback(
|
||||
Stream,
|
||||
Event);
|
||||
};
|
||||
MsQuic->SetCallbackHandler(Event->PEER_STREAM_STARTED.Stream, (void*)Handler, this);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QUIC_STATUS
|
||||
ThroughputServer::StreamCallback(
|
||||
_In_ HQUIC StreamHandle,
|
||||
_Inout_ QUIC_STREAM_EVENT* Event
|
||||
) {
|
||||
switch (Event->Type) {
|
||||
case QUIC_STREAM_EVENT_PEER_SEND_ABORTED:
|
||||
case QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED:
|
||||
MsQuic->StreamShutdown(
|
||||
StreamHandle,
|
||||
QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND | QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE,
|
||||
0);
|
||||
break;
|
||||
case QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE: {
|
||||
MsQuic->StreamClose(StreamHandle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QUIC_STATUS_SUCCESS;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License.
|
||||
|
||||
Abstract:
|
||||
|
||||
QUIC Perf Throughput Server declaration. Defines the functions and
|
||||
variables used in the ThroughputServer class.
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PerfHelpers.h"
|
||||
#include "PerfBase.h"
|
||||
#include "PerfCommon.h"
|
||||
|
||||
class ThroughputServer : public PerfBase {
|
||||
public:
|
||||
ThroughputServer(
|
||||
_In_ PerfSelfSignedConfiguration* SelfSignedConfig
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
Init(
|
||||
_In_ int argc,
|
||||
_In_reads_(argc) _Null_terminated_ char* argv[]
|
||||
) override;
|
||||
|
||||
QUIC_STATUS
|
||||
Start(
|
||||
_In_ QUIC_EVENT* StopEvent
|
||||
) override;
|
||||
|
||||
QUIC_STATUS
|
||||
Wait(
|
||||
int Timeout
|
||||
) override;
|
||||
|
||||
private:
|
||||
|
||||
QUIC_STATUS
|
||||
ListenerCallback(
|
||||
_In_ HQUIC ListenerHandle,
|
||||
_Inout_ QUIC_LISTENER_EVENT* Event
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
ConnectionCallback(
|
||||
_In_ HQUIC ConnectionHandle,
|
||||
_Inout_ QUIC_CONNECTION_EVENT* Event
|
||||
);
|
||||
|
||||
QUIC_STATUS
|
||||
StreamCallback(
|
||||
_In_ HQUIC StreamHandle,
|
||||
_Inout_ QUIC_STREAM_EVENT* Event
|
||||
);
|
||||
|
||||
MsQuicRegistration Registration;
|
||||
MsQuicSession Session {Registration, THROUGHPUT_ALPN};
|
||||
MsQuicListener Listener {Session};
|
||||
PerfSelfSignedConfiguration* SelfSignedConfig;
|
||||
PerfSecurityConfig SecurityConfig;
|
||||
uint16_t Port {THROUGHPUT_DEFAULT_PORT};
|
||||
uint32_t NumberOfConnections {0};
|
||||
CountHelper RefCount;
|
||||
};
|
|
@ -35,11 +35,10 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="PerfServer.cpp" />
|
||||
<ClCompile Include="quicmain.cpp" />
|
||||
<ClCompile Include="ThroughputClient.cpp" />
|
||||
<ClCompile Include="ThroughputServer.cpp" />
|
||||
<ClCompile Include="RpsClient.cpp" />
|
||||
<ClCompile Include="RpsServer.cpp" />
|
||||
<ClCompile Include="ThroughputClient.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="PerfHelpers.h" />
|
||||
|
|
|
@ -10,9 +10,8 @@ Abstract:
|
|||
--*/
|
||||
|
||||
#include "PerfHelpers.h"
|
||||
#include "ThroughputServer.h"
|
||||
#include "PerfServer.h"
|
||||
#include "ThroughputClient.h"
|
||||
#include "RpsServer.h"
|
||||
#include "RpsClient.h"
|
||||
|
||||
#ifdef QUIC_CLOG
|
||||
|
@ -39,7 +38,7 @@ PrintHelp(
|
|||
) {
|
||||
WriteOutput(
|
||||
"\n"
|
||||
"Usage: quicperf -TestName:<Throughput|RPS> [-ServerMode:<1:0>] [options]\n"
|
||||
"Usage: quicperf -ServerMode:<1:0> [-TestName:<Throughput|RPS>] [options]\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
@ -58,21 +57,16 @@ QuicMainStart(
|
|||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!IsArg(argv[0], "TestName")) {
|
||||
WriteOutput("Must specify -TestName argument\n");
|
||||
ServerMode = 0;
|
||||
if (!IsArg(argv[0], "ServerMode")) {
|
||||
WriteOutput("Must specify -ServerMode argument\n");
|
||||
PrintHelp();
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const char* TestName = GetValue(argc, argv, "TestName");
|
||||
TryGetValue(argc, argv, "ServerMode", &ServerMode);
|
||||
argc--; argv++;
|
||||
|
||||
ServerMode = 0;
|
||||
if (argc != 0 && IsArg(argv[0], "ServerMode")) {
|
||||
TryGetValue(argc, argv, "ServerMode", &ServerMode);
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
QUIC_STATUS Status;
|
||||
|
||||
if (ServerMode) {
|
||||
|
@ -91,7 +85,6 @@ QuicMainStart(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
MsQuic = new(std::nothrow) QuicApiTable;
|
||||
if (MsQuic == nullptr) {
|
||||
return QUIC_STATUS_OUT_OF_MEMORY;
|
||||
|
@ -102,21 +95,29 @@ QuicMainStart(
|
|||
return Status;
|
||||
}
|
||||
|
||||
if (IsValue(TestName, "Throughput")) {
|
||||
if (ServerMode) {
|
||||
TestToRun = new(std::nothrow) ThroughputServer(SelfSignedConfig);
|
||||
} else {
|
||||
TestToRun = new(std::nothrow) ThroughputClient;
|
||||
}
|
||||
} else if (IsValue(TestName, "RPS")) {
|
||||
if (ServerMode) {
|
||||
TestToRun = new(std::nothrow) RpsServer(SelfSignedConfig);
|
||||
} else {
|
||||
TestToRun = new(std::nothrow) RpsClient;
|
||||
}
|
||||
if (ServerMode) {
|
||||
TestToRun = new(std::nothrow) PerfServer(SelfSignedConfig);
|
||||
|
||||
} else {
|
||||
delete MsQuic;
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
if (!IsArg(argv[0], "TestName")) {
|
||||
WriteOutput("Must specify -TestName argument\n");
|
||||
PrintHelp();
|
||||
delete MsQuic;
|
||||
MsQuic = nullptr;
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const char* TestName = GetValue(argc, argv, "TestName");
|
||||
argc--; argv++;
|
||||
|
||||
if (IsValue(TestName, "Throughput")) {
|
||||
TestToRun = new(std::nothrow) ThroughputClient;
|
||||
} else if (IsValue(TestName, "RPS")) {
|
||||
TestToRun = new(std::nothrow) RpsClient;
|
||||
} else {
|
||||
delete MsQuic;
|
||||
return QUIC_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
if (TestToRun != nullptr) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче