Skip to content

Commit

Permalink
Basic NMR integration for MsQuic (#3961)
Browse files Browse the repository at this point in the history
The PR adds an NMR interface (NMR provider) for kernel mode msquic. The MsQuic provide only exposes 2 interfaces, MsQuicOpenVersion and MsQuicClose, which are the same as what are exposed in msquic.sys. This PR does not remove the exports.
  • Loading branch information
csujedihy authored Nov 22, 2023
1 parent 332c1cc commit ab10cd5
Show file tree
Hide file tree
Showing 13 changed files with 605 additions and 7 deletions.
1 change: 1 addition & 0 deletions scripts/clog.inputs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
../src/bin/winuser/dllmain.c
../src/bin/winkernel/driver.c
../src/bin/winkernel/msquicpcw.c
../src/bin/winkernel/nmrprovider.c
../src/bin/static/empty.c
../src/core/operation.h
../src/core/stream.h
Expand Down
21 changes: 21 additions & 0 deletions src/bin/winkernel/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ MsQuicPcwCleanup(
void
);

_No_competing_thread_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
MsQuicRegisterNmrProvider(
void
);

_No_competing_thread_
_IRQL_requires_max_(PASSIVE_LEVEL)
void
MsQuicDeregisterNmrProvider(
void
);

INITCODE DRIVER_INITIALIZE DriverEntry;
PAGEDX EVT_WDF_DRIVER_UNLOAD EvtDriverUnload;

Expand Down Expand Up @@ -118,6 +132,11 @@ Return Value:
goto Error;
}

Status = MsQuicRegisterNmrProvider();
if (!NT_SUCCESS(Status)) {
goto Error;
}

Error:

if (!NT_SUCCESS(Status)) {
Expand Down Expand Up @@ -151,6 +170,8 @@ Routine Description:
UNREFERENCED_PARAMETER(Driver);

PAGED_CODE();

MsQuicDeregisterNmrProvider();
MsQuicPcwCleanup();
MsQuicLibraryUnload();
}
1 change: 1 addition & 0 deletions src/bin/winkernel/msquic.kernel.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<ItemGroup>
<ClCompile Include="driver.c" />
<ClCompile Include="msquicpcw.c" />
<ClCompile Include="nmrprovider.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
Expand Down
1 change: 1 addition & 0 deletions src/bin/winkernel/msquicpriv.kernel.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<ItemGroup>
<ClCompile Include="driver.c" />
<ClCompile Include="msquicpcw.c" />
<ClCompile Include="nmrprovider.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
Expand Down
133 changes: 133 additions & 0 deletions src/bin/winkernel/nmrprovider.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*++
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
Abstract:
NMR provider for MsQuic.
--*/

#include "quic_platform.h"
#include <wdm.h>
#include "msquic.h"
#include "quic_trace.h"
#ifdef QUIC_CLOG
#include "nmrprovider.c.clog.h"
#endif

typedef struct MSQUIC_NMR_PROVIDER {
NPI_PROVIDER_CHARACTERISTICS NpiProviderCharacteristics;
HANDLE NmrProviderHandle;
NPI_MODULEID ModuleId;
} MSQUIC_NMR_PROVIDER;

MSQUIC_NMR_PROVIDER NmrProvider;

const MSQUIC_NMR_DISPATCH MsQuicNmrDispatch = {
.Version = 0,
.Reserved = 0,
.MsQuicOpenVersion = MsQuicOpenVersion,
.MsQuicClose = MsQuicClose,
};

NTSTATUS
MsQuicNmrProviderAttachClient(
_In_ HANDLE NmrBindingHandle,
_In_ void *ProviderContext,
_In_ const NPI_REGISTRATION_INSTANCE *ClientRegistrationInstance,
_In_ void *ClientBindingContext,
_In_ const void *ClientDispatch,
_Out_ void **ProviderBindingContext,
_Out_ const void **ProviderDispatch
)
{
UNREFERENCED_PARAMETER(ClientBindingContext);
UNREFERENCED_PARAMETER(ProviderContext);
UNREFERENCED_PARAMETER(ClientDispatch);

*ProviderBindingContext = NmrBindingHandle;
*ProviderDispatch = &MsQuicNmrDispatch;

QuicTraceLogInfo(
ProviderAttachClient,
"[ nmr][%p] Client attached Ver %hu Size %hu Number %u ModuleID { %x-%x-%x-%llx }",
NmrBindingHandle,
ClientRegistrationInstance->Version,
ClientRegistrationInstance->Size,
ClientRegistrationInstance->Number,
ClientRegistrationInstance->ModuleId->Guid.Data1,
ClientRegistrationInstance->ModuleId->Guid.Data2,
ClientRegistrationInstance->ModuleId->Guid.Data3,
*((uint64_t*)ClientRegistrationInstance->ModuleId->Guid.Data4));
return STATUS_SUCCESS;
}

NTSTATUS
MsQuicNmrProviderDetachClient(
_In_ void *ProviderBindingContext
)
{
QuicTraceLogInfo(
ProviderDetachClient,
"[ nmr][%p] Client detached",
ProviderBindingContext);
return STATUS_SUCCESS;
}

_No_competing_thread_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
MsQuicRegisterNmrProvider(
void
)
{
NTSTATUS Status = STATUS_SUCCESS;
NPI_REGISTRATION_INSTANCE *ProviderRegistrationInstance;

NmrProvider.ModuleId.Length = sizeof(NmrProvider.ModuleId);
NmrProvider.ModuleId.Type = MIT_GUID;
NmrProvider.ModuleId.Guid = MSQUIC_MODULE_ID;

NmrProvider.NpiProviderCharacteristics.Version = 0;
NmrProvider.NpiProviderCharacteristics.Length = sizeof(NmrProvider.NpiProviderCharacteristics);
NmrProvider.NpiProviderCharacteristics.ProviderAttachClient = MsQuicNmrProviderAttachClient;
NmrProvider.NpiProviderCharacteristics.ProviderDetachClient = MsQuicNmrProviderDetachClient;

ProviderRegistrationInstance = &NmrProvider.NpiProviderCharacteristics.ProviderRegistrationInstance;
ProviderRegistrationInstance->Version = 0;
ProviderRegistrationInstance->Size = sizeof(*ProviderRegistrationInstance);
ProviderRegistrationInstance->NpiId = &MSQUIC_NPI_ID;
ProviderRegistrationInstance->ModuleId = &NmrProvider.ModuleId;

Status =
NmrRegisterProvider(
&NmrProvider.NpiProviderCharacteristics,
&NmrProvider,
&NmrProvider.NmrProviderHandle);
if (!NT_SUCCESS(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"NmrRegisterProvider");
goto Exit;
}

Exit:
return Status;
}

void
MsQuicDeregisterNmrProvider(
void
)
{
if (NmrProvider.NmrProviderHandle != NULL) {
NTSTATUS Status = NmrDeregisterProvider(NmrProvider.NmrProviderHandle);
CXPLAT_FRE_ASSERTMSG(Status == STATUS_PENDING, "deregistration failed");
NmrWaitForProviderDeregisterComplete(NmrProvider.NmrProviderHandle);
NmrProvider.NmrProviderHandle = NULL;
}
}
103 changes: 103 additions & 0 deletions src/generated/linux/nmrprovider.c.clog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#ifndef CLOG_DO_NOT_INCLUDE_HEADER
#include <clog.h>
#endif
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER CLOG_NMRPROVIDER_C
#undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE
#undef TRACEPOINT_INCLUDE
#define TRACEPOINT_INCLUDE "nmrprovider.c.clog.h.lttng.h"
#if !defined(DEF_CLOG_NMRPROVIDER_C) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define DEF_CLOG_NMRPROVIDER_C
#include <lttng/tracepoint.h>
#define __int64 __int64_t
#include "nmrprovider.c.clog.h.lttng.h"
#endif
#include <lttng/tracepoint-event.h>
#ifndef _clog_MACRO_QuicTraceLogInfo
#define _clog_MACRO_QuicTraceLogInfo 1
#define QuicTraceLogInfo(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))
#endif
#ifndef _clog_MACRO_QuicTraceEvent
#define _clog_MACRO_QuicTraceEvent 1
#define QuicTraceEvent(a, ...) _clog_CAT(_clog_ARGN_SELECTOR(__VA_ARGS__), _clog_CAT(_,a(#a, __VA_ARGS__)))
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------
// Decoder Ring for ProviderAttachClient
// [ nmr][%p] Client attached Ver %hu Size %hu Number %u ModuleID { %x-%x-%x-%llx }
// QuicTraceLogInfo(
ProviderAttachClient,
"[ nmr][%p] Client attached Ver %hu Size %hu Number %u ModuleID { %x-%x-%x-%llx }",
NmrBindingHandle,
ClientRegistrationInstance->Version,
ClientRegistrationInstance->Size,
ClientRegistrationInstance->Number,
ClientRegistrationInstance->ModuleId->Guid.Data1,
ClientRegistrationInstance->ModuleId->Guid.Data2,
ClientRegistrationInstance->ModuleId->Guid.Data3,
*((uint64_t*)ClientRegistrationInstance->ModuleId->Guid.Data4));
// arg2 = arg2 = NmrBindingHandle = arg2
// arg3 = arg3 = ClientRegistrationInstance->Version = arg3
// arg4 = arg4 = ClientRegistrationInstance->Size = arg4
// arg5 = arg5 = ClientRegistrationInstance->Number = arg5
// arg6 = arg6 = ClientRegistrationInstance->ModuleId->Guid.Data1 = arg6
// arg7 = arg7 = ClientRegistrationInstance->ModuleId->Guid.Data2 = arg7
// arg8 = arg8 = ClientRegistrationInstance->ModuleId->Guid.Data3 = arg8
// arg9 = arg9 = *((uint64_t*)ClientRegistrationInstance->ModuleId->Guid.Data4) = arg9
----------------------------------------------------------*/
#ifndef _clog_10_ARGS_TRACE_ProviderAttachClient
#define _clog_10_ARGS_TRACE_ProviderAttachClient(uniqueId, encoded_arg_string, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)\
tracepoint(CLOG_NMRPROVIDER_C, ProviderAttachClient , arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);\

#endif




/*----------------------------------------------------------
// Decoder Ring for ProviderDetachClient
// [ nmr][%p] Client detached
// QuicTraceLogInfo(
ProviderDetachClient,
"[ nmr][%p] Client detached",
ProviderBindingContext);
// arg2 = arg2 = ProviderBindingContext = arg2
----------------------------------------------------------*/
#ifndef _clog_3_ARGS_TRACE_ProviderDetachClient
#define _clog_3_ARGS_TRACE_ProviderDetachClient(uniqueId, encoded_arg_string, arg2)\
tracepoint(CLOG_NMRPROVIDER_C, ProviderDetachClient , arg2);\

#endif




/*----------------------------------------------------------
// Decoder Ring for LibraryErrorStatus
// [ lib] ERROR, %u, %s.
// QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"NmrRegisterProvider");
// arg2 = arg2 = Status = arg2
// arg3 = arg3 = "NmrRegisterProvider" = arg3
----------------------------------------------------------*/
#ifndef _clog_4_ARGS_TRACE_LibraryErrorStatus
#define _clog_4_ARGS_TRACE_LibraryErrorStatus(uniqueId, encoded_arg_string, arg2, arg3)\
tracepoint(CLOG_NMRPROVIDER_C, LibraryErrorStatus , arg2, arg3);\

#endif




#ifdef __cplusplus
}
#endif
#ifdef CLOG_INLINE_IMPLEMENTATION
#include "quic.clog_nmrprovider.c.clog.h.c"
#endif
89 changes: 89 additions & 0 deletions src/generated/linux/nmrprovider.c.clog.h.lttng.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@



/*----------------------------------------------------------
// Decoder Ring for ProviderAttachClient
// [ nmr][%p] Client attached Ver %hu Size %hu Number %u ModuleID { %x-%x-%x-%llx }
// QuicTraceLogInfo(
ProviderAttachClient,
"[ nmr][%p] Client attached Ver %hu Size %hu Number %u ModuleID { %x-%x-%x-%llx }",
NmrBindingHandle,
ClientRegistrationInstance->Version,
ClientRegistrationInstance->Size,
ClientRegistrationInstance->Number,
ClientRegistrationInstance->ModuleId->Guid.Data1,
ClientRegistrationInstance->ModuleId->Guid.Data2,
ClientRegistrationInstance->ModuleId->Guid.Data3,
*((uint64_t*)ClientRegistrationInstance->ModuleId->Guid.Data4));
// arg2 = arg2 = NmrBindingHandle = arg2
// arg3 = arg3 = ClientRegistrationInstance->Version = arg3
// arg4 = arg4 = ClientRegistrationInstance->Size = arg4
// arg5 = arg5 = ClientRegistrationInstance->Number = arg5
// arg6 = arg6 = ClientRegistrationInstance->ModuleId->Guid.Data1 = arg6
// arg7 = arg7 = ClientRegistrationInstance->ModuleId->Guid.Data2 = arg7
// arg8 = arg8 = ClientRegistrationInstance->ModuleId->Guid.Data3 = arg8
// arg9 = arg9 = *((uint64_t*)ClientRegistrationInstance->ModuleId->Guid.Data4) = arg9
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_NMRPROVIDER_C, ProviderAttachClient,
TP_ARGS(
const void *, arg2,
unsigned short, arg3,
unsigned short, arg4,
unsigned int, arg5,
unsigned int, arg6,
unsigned int, arg7,
unsigned int, arg8,
unsigned long long, arg9),
TP_FIELDS(
ctf_integer_hex(uint64_t, arg2, arg2)
ctf_integer(unsigned short, arg3, arg3)
ctf_integer(unsigned short, arg4, arg4)
ctf_integer(unsigned int, arg5, arg5)
ctf_integer(unsigned int, arg6, arg6)
ctf_integer(unsigned int, arg7, arg7)
ctf_integer(unsigned int, arg8, arg8)
ctf_integer(uint64_t, arg9, arg9)
)
)



/*----------------------------------------------------------
// Decoder Ring for ProviderDetachClient
// [ nmr][%p] Client detached
// QuicTraceLogInfo(
ProviderDetachClient,
"[ nmr][%p] Client detached",
ProviderBindingContext);
// arg2 = arg2 = ProviderBindingContext = arg2
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_NMRPROVIDER_C, ProviderDetachClient,
TP_ARGS(
const void *, arg2),
TP_FIELDS(
ctf_integer_hex(uint64_t, arg2, arg2)
)
)



/*----------------------------------------------------------
// Decoder Ring for LibraryErrorStatus
// [ lib] ERROR, %u, %s.
// QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"NmrRegisterProvider");
// arg2 = arg2 = Status = arg2
// arg3 = arg3 = "NmrRegisterProvider" = arg3
----------------------------------------------------------*/
TRACEPOINT_EVENT(CLOG_NMRPROVIDER_C, LibraryErrorStatus,
TP_ARGS(
unsigned int, arg2,
const char *, arg3),
TP_FIELDS(
ctf_integer(unsigned int, arg2, arg2)
ctf_string(arg3, arg3)
)
)
Loading

0 comments on commit ab10cd5

Please sign in to comment.