├── netcx ├── ec │ ├── lib │ │ ├── km │ │ │ └── precompiled.hpp │ │ ├── executioncontextstatistics.hpp │ │ ├── pollreserved.cpp │ │ ├── pollreserved.hpp │ │ ├── irqlcontroller.h │ │ ├── notificationreserved.hpp │ │ ├── timebudgetwarninglogger.h │ │ ├── irqlcontroller.cpp │ │ ├── executioncontexttask.cpp │ │ ├── executioncontexttask.hpp │ │ ├── notificationreserved.cpp │ │ ├── timebudget.h │ │ ├── executioncontextstatistics.cpp │ │ ├── thread.hpp │ │ ├── activitytracker.cpp │ │ ├── activitytracker.hpp │ │ ├── dpc.h │ │ └── timebudgetwarninglogger.cpp │ ├── inc │ │ ├── executioncontexttask.h │ │ ├── executioncontextnotification.h │ │ ├── executioncontext.h │ │ ├── executioncontextpoll.h │ │ └── executioncontextregistry.h │ └── driver │ │ ├── precompiled.hpp │ │ └── trace.hpp ├── statistics │ ├── km │ │ └── precompiled.hpp │ ├── histogramapi.h │ ├── histogramapi.cpp │ ├── histogramhub.h │ ├── histogram.h │ └── histogramtimer.h ├── adapter │ ├── nxdefaultdatapath.hpp │ ├── config │ │ └── netclientdriverconfigurationprecomp.hpp │ ├── nxextension.hpp │ ├── powerpolicy │ │ ├── nxpowerentry.cpp │ │ ├── nxpowerentry.hpp │ │ ├── nxpowerlist.hpp │ │ ├── nxidlerestrictions.hpp │ │ ├── nxpoweroffload.hpp │ │ └── nxpowerlist.cpp │ ├── nxadaptercollection.hpp │ ├── extension │ │ ├── nxextension.hpp │ │ └── nxextensionlayout.hpp │ ├── types │ │ ├── nxadapterextensiontypes.hpp │ │ ├── nxadaptertypes.hpp │ │ └── nxadapterextensiontypes.cpp │ ├── nx.hpp │ ├── nxexecutioncontext.hpp │ ├── version.hpp │ ├── nxextension.cpp │ ├── nxprivateglobals.hpp │ ├── idle │ │ ├── powerreferenceholder.hpp │ │ ├── idlestatemachine.hpp │ │ └── powerreferenceholder.cpp │ ├── nxadaptercollection.cpp │ ├── monitor │ │ └── nxpacketmonitor.hpp │ ├── nxqueueverifier.hpp │ ├── nxdriver.hpp │ ├── queue │ │ └── queue.hpp │ ├── rxscaling │ │ └── nxrxscaling.hpp │ ├── nxexecutioncontext.cpp │ ├── nxexecutioncontexttask.hpp │ └── nxadapterdriverapi.cpp ├── bm │ ├── bmprecomp.hpp │ ├── nonpagedallocator.hpp │ ├── ibuffervector.cpp │ ├── ibuffervectorallocator.hpp │ ├── mdl.hpp │ ├── dmaallocator.hpp │ ├── ibuffervector.hpp │ ├── commonbuffervector.hpp │ ├── nonpagedbuffervector.hpp │ ├── buffermanager.hpp │ ├── commonbuffervector.cpp │ ├── nonpagedbuffervector.cpp │ ├── mdl.cpp │ ├── nonpagedallocator.cpp │ ├── dmaallocator.cpp │ ├── bufferheader.hpp │ └── bufferpool.hpp └── translator │ ├── framelayout │ ├── layoutparser.hpp │ ├── layoutparser.cpp │ ├── layer4layout.hpp │ ├── layer4layout.cpp │ └── layer3layout.hpp │ ├── nxtxdemux.cpp │ ├── nxsignal.hpp │ ├── txwmminfodemux.hpp │ ├── txuserprioritydemux.hpp │ ├── nxpacketlayout.hpp │ ├── txpeeraddressdemux.hpp │ ├── nxxlatcommon.hpp │ ├── nxtxdemux.hpp │ ├── nxnblqueue.hpp │ ├── nxxlatprecomp.hpp │ ├── nxtxnblcontext.hpp │ ├── nxringcontext.cpp │ ├── checksum │ ├── checksum.cpp │ ├── checksum.hpp │ └── km │ │ └── checksumkm.cpp │ ├── segmentation │ ├── segmentation.cpp │ └── segmentation.hpp │ ├── txwmminfodemux.cpp │ ├── nxringcontext.hpp │ ├── txuserprioritydemux.cpp │ ├── nxrxnblcontext.hpp │ ├── nxbouncebufferpool.hpp │ ├── nxextensions.hpp │ ├── nxringbuffer.cpp │ ├── coalescing │ └── coalescing.hpp │ ├── txscaling.hpp │ ├── nxnblqueue.cpp │ ├── nxnblsequence.h │ ├── queue.hpp │ ├── nxstatistics.cpp │ ├── txpeeraddressdemux.cpp │ └── nxstatistics.hpp ├── rtl └── inc │ ├── kdebug.h │ ├── RtlHomogenousSequence.h │ ├── kpushlock.h │ ├── kdeletepolicy.h │ ├── krefinline.h │ ├── kcriticalregion.h │ ├── kbitmap.h │ ├── kunits.h │ ├── kintrusivelist.h │ ├── klockholder.h │ └── kmacros.h ├── CONTRIBUTING.md ├── LICENSE └── SECURITY.md /netcx/ec/lib/km/precompiled.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | -------------------------------------------------------------------------------- /netcx/statistics/km/precompiled.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | -------------------------------------------------------------------------------- /netcx/adapter/nxdefaultdatapath.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | NET_ADAPTER_DATAPATH_CALLBACKS 6 | GetDefaultDatapathCallbacks( 7 | void 8 | ); 9 | -------------------------------------------------------------------------------- /netcx/ec/inc/executioncontexttask.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | typedef 5 | _IRQL_requires_max_(DISPATCH_LEVEL) 6 | void 7 | EVT_EXECUTION_CONTEXT_TASK( 8 | _In_ void * Context 9 | ); 10 | 11 | typedef EVT_EXECUTION_CONTEXT_TASK *PFN_EXECUTION_CONTEXT_TASK; 12 | -------------------------------------------------------------------------------- /netcx/adapter/config/netclientdriverconfigurationprecomp.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | #define NTSTRSAFE_LIB 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /netcx/ec/driver/precompiled.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "trace.hpp" 13 | -------------------------------------------------------------------------------- /netcx/bm/bmprecomp.hpp: -------------------------------------------------------------------------------- 1 | 2 | #include "umwdm.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #ifndef _KERNEL_MODE 12 | #include 13 | #endif 14 | 15 | #define BUFFER_MANAGER_POOL_TAG 'mbxc' 16 | 17 | -------------------------------------------------------------------------------- /netcx/ec/lib/executioncontextstatistics.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Statistics 7 | { 8 | class Hub; 9 | class Histogram; 10 | } 11 | 12 | NONPAGED 13 | Statistics::Hub& 14 | GetGlobalEcStatistics(); 15 | 16 | PAGED 17 | void 18 | FreeGlobalEcStatistics(); 19 | 20 | PAGED 21 | NTSTATUS 22 | InitializeGlobalEcStatistic(); 23 | -------------------------------------------------------------------------------- /netcx/bm/nonpagedallocator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "IBufferVectorAllocator.hpp" 5 | 6 | class PAGED NonPagedAllocator : public IBufferVectorAllocator 7 | { 8 | public: 9 | 10 | IBufferVector * 11 | AllocateVector( 12 | _In_ size_t BufferCount, 13 | _In_ size_t BufferSize, 14 | _In_ size_t BufferOffset, 15 | _In_ NODE_REQUIREMENT 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /netcx/translator/framelayout/layoutparser.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | typedef 8 | bool 9 | FUNC_PARSE_LAYER_LAYOUT ( 10 | _Inout_ NET_PACKET_LAYOUT & Layout, 11 | _In_reads_(Offset + Length) UINT8 const * Pointer, 12 | _Inout_ size_t & Offset, 13 | _Inout_ size_t & Length 14 | ); 15 | 16 | extern FUNC_PARSE_LAYER_LAYOUT* const ParseLayerDispatch[3]; 17 | -------------------------------------------------------------------------------- /netcx/bm/ibuffervector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "BmPrecomp.hpp" 3 | 4 | #include "IBufferVector.hpp" 5 | #include "IBufferVector.tmh" 6 | 7 | _Use_decl_annotations_ 8 | IBufferVector::IBufferVector( 9 | size_t BufferCount, 10 | size_t BufferOffset, 11 | size_t BufferCapacity 12 | ) 13 | : m_BufferCount(BufferCount) 14 | , m_BufferOffset(BufferOffset) 15 | , m_BufferCapacity(BufferCapacity) 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /netcx/ec/lib/pollreserved.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | #include "PollReserved.hpp" 4 | #include "ExecutionContextPoll.h" 5 | 6 | NONPAGEDX 7 | _Use_decl_annotations_ 8 | PollReserved & 9 | ContextFromPoll( 10 | EXECUTION_CONTEXT_POLL * Poll 11 | ) 12 | { 13 | static_assert(sizeof(PollReserved) <= FIELD_SIZE(EXECUTION_CONTEXT_POLL, Reserved[0])); 14 | return reinterpret_cast(Poll->Reserved[0]); 15 | } 16 | -------------------------------------------------------------------------------- /netcx/adapter/nxextension.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "extension/NxExtension.hpp" 9 | 10 | class NxExtension 11 | { 12 | 13 | public: 14 | 15 | NTSTATUS 16 | Initialize( 17 | _In_ NET_EXTENSION_PRIVATE const * Extension 18 | ); 19 | 20 | NET_EXTENSION_PRIVATE 21 | m_extension = {}; 22 | 23 | private: 24 | 25 | KPoolPtr 26 | m_extensionName; 27 | 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /netcx/ec/lib/pollreserved.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "ExecutionContextStatistics.hpp" 5 | #include 6 | 7 | typedef struct _EXECUTION_CONTEXT_POLL EXECUTION_CONTEXT_POLL; 8 | 9 | // This structure is stored in EXECUTION_CONTEXT_POLL's Reserved field. 10 | struct PollReserved 11 | { 12 | KPoolPtr 13 | histogram; 14 | }; 15 | 16 | NONPAGED 17 | PollReserved & 18 | ContextFromPoll( 19 | _In_ EXECUTION_CONTEXT_POLL * Poll 20 | ); 21 | -------------------------------------------------------------------------------- /netcx/translator/nxtxdemux.cpp: -------------------------------------------------------------------------------- 1 | #include "NxXlatPrecomp.hpp" 2 | #include "NxXlatCommon.hpp" 3 | 4 | #include "NxTxDemux.tmh" 5 | #include "NxTxDemux.hpp" 6 | 7 | NxTxDemux::NxTxDemux( 8 | NxTxDemux::Type Type, 9 | size_t Range 10 | ) noexcept 11 | : m_type(Type) 12 | , m_range(Range) 13 | { 14 | } 15 | 16 | NxTxDemux::Type 17 | NxTxDemux::GetType( 18 | void 19 | ) const 20 | { 21 | return m_type; 22 | } 23 | 24 | size_t 25 | NxTxDemux::GetRange( 26 | void 27 | ) const 28 | { 29 | return m_range; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /netcx/translator/framelayout/layoutparser.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #ifdef _KERNEL_MODE 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #include 12 | 13 | #include "LayoutParser.hpp" 14 | 15 | #include "Layer2Layout.hpp" 16 | #include "Layer3Layout.hpp" 17 | #include "Layer4Layout.hpp" 18 | 19 | FUNC_PARSE_LAYER_LAYOUT* const ParseLayerDispatch[3] = { 20 | Layer2::ParseLayout, 21 | Layer3::ParseLayout, 22 | Layer4::ParseLayout 23 | }; 24 | -------------------------------------------------------------------------------- /netcx/statistics/histogramapi.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace Statistics 8 | { 9 | class Hub; 10 | } 11 | 12 | NONPAGED 13 | NTSTATUS 14 | CollectHistogramsForIoctl( 15 | const Statistics::Hub& hub, 16 | _Out_writes_bytes_(cbOut) NDIS_COLLECT_HISTOGRAM_OUT *out, 17 | _In_ ULONG cbOut, 18 | _Out_ ULONG &bytesNeeded 19 | ); 20 | 21 | NONPAGED 22 | void 23 | ResetHistogramsValues( 24 | Statistics::Hub& hub 25 | ); 26 | -------------------------------------------------------------------------------- /netcx/bm/ibuffervectorallocator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "IBufferVector.hpp" 5 | 6 | class PAGED IBufferVectorAllocator : 7 | public PAGED_OBJECT<'amxn'> 8 | { 9 | public: 10 | 11 | //individual buffer size must be always page aligned and is the multiple of PAGE_SIZE. 12 | 13 | virtual 14 | IBufferVector * 15 | AllocateVector( 16 | _In_ size_t BufferCount, 17 | _In_ size_t BufferSize, 18 | _In_ size_t BufferOffset, 19 | _In_ NODE_REQUIREMENT PreferredNode 20 | ) = 0; 21 | }; 22 | -------------------------------------------------------------------------------- /rtl/inc/kdebug.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | template 7 | struct KRTL_CLASS NdisDebugBlock 8 | { 9 | #if DBG 10 | PAGED ~NdisDebugBlock() 11 | { 12 | ASSERT_VALID(); 13 | Signature |= 0x80; 14 | } 15 | #endif 16 | 17 | _IRQL_requires_max_(HIGH_LEVEL) 18 | NONPAGEDX bool ASSERT_VALID() const 19 | { 20 | #if DBG 21 | return NT_VERIFY(Signature == SIGNATURE); 22 | #else 23 | return true; 24 | #endif 25 | } 26 | 27 | private: 28 | #if DBG 29 | ULONG Signature = SIGNATURE; 30 | #endif 31 | }; 32 | -------------------------------------------------------------------------------- /netcx/statistics/histogramapi.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | #include "HistogramHub.h" 4 | #include "HistogramApi.h" 5 | 6 | NONPAGEDX 7 | _Use_decl_annotations_ 8 | NTSTATUS 9 | CollectHistogramsForIoctl( 10 | const Statistics::Hub& hub, 11 | NDIS_COLLECT_HISTOGRAM_OUT *out, 12 | ULONG cbOut, 13 | ULONG &bytesNeeded 14 | ) 15 | { 16 | return hub.Serialize(out, cbOut, bytesNeeded); 17 | } 18 | 19 | NONPAGED 20 | void 21 | ResetHistogramsValues( 22 | Statistics::Hub& hub 23 | ) 24 | { 25 | hub.ResetHistogramsValues(); 26 | } 27 | -------------------------------------------------------------------------------- /netcx/translator/nxsignal.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | The NxRingBuffer wraps a NET_RING, providing simple accessor methods 8 | for inserting and removing items into the ring buffer. 9 | 10 | --*/ 11 | 12 | #pragma once 13 | 14 | class NxInterlockedFlag 15 | { 16 | _Interlocked_ volatile LONG m_flag = false; 17 | 18 | public: 19 | 20 | _IRQL_requires_max_(DISPATCH_LEVEL) 21 | void Set() { InterlockedExchange(&m_flag, true); } 22 | 23 | _IRQL_requires_max_(DISPATCH_LEVEL) 24 | bool TestAndClear() { return !!InterlockedExchange(&m_flag, false); } 25 | }; 26 | -------------------------------------------------------------------------------- /netcx/translator/txwmminfodemux.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "NxTxDemux.hpp" 6 | 7 | class TxWmmInfoDemux 8 | : public NxTxDemux 9 | { 10 | 11 | public: 12 | 13 | TxWmmInfoDemux( 14 | size_t Range 15 | ) noexcept; 16 | 17 | size_t 18 | Demux( 19 | _In_ NET_BUFFER_LIST const * NetBufferList 20 | ) const; 21 | 22 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 23 | GenerateDemuxProperty( 24 | _In_ NET_BUFFER_LIST const * NetBufferList 25 | ) override; 26 | 27 | private: 28 | 29 | size_t 30 | Demux( 31 | _In_ UINT8 Value 32 | ) const; 33 | 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /netcx/translator/txuserprioritydemux.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "NxTxDemux.hpp" 6 | 7 | class TxUserPriorityDemux 8 | : public NxTxDemux 9 | { 10 | 11 | public: 12 | 13 | TxUserPriorityDemux( 14 | size_t Range 15 | ) noexcept; 16 | 17 | size_t 18 | Demux( 19 | _In_ NET_BUFFER_LIST const * NetBufferList 20 | ) const; 21 | 22 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 23 | GenerateDemuxProperty( 24 | _In_ NET_BUFFER_LIST const * NetBufferList 25 | ) override; 26 | 27 | private: 28 | 29 | size_t 30 | Demux( 31 | UINT8 Value 32 | ) const; 33 | 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /netcx/adapter/powerpolicy/nxpowerentry.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | 4 | #include "NxPowerEntry.hpp" 5 | 6 | #include "NxPowerEntry.tmh" 7 | 8 | _Use_decl_annotations_ 9 | NxPowerEntry::NxPowerEntry( 10 | NETADAPTER Adapter 11 | ) 12 | : m_adapter(Adapter) 13 | { 14 | } 15 | 16 | NETADAPTER 17 | NxPowerEntry::GetAdapter( 18 | void 19 | ) const 20 | { 21 | return m_adapter; 22 | } 23 | 24 | _Use_decl_annotations_ 25 | void 26 | NxPowerEntry::SetEnabled( 27 | bool Enabled 28 | ) 29 | { 30 | m_enabled = Enabled; 31 | } 32 | 33 | bool 34 | NxPowerEntry::IsEnabled( 35 | void 36 | ) const 37 | { 38 | return m_enabled; 39 | } 40 | -------------------------------------------------------------------------------- /netcx/translator/nxpacketlayout.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | NET_PACKET_LAYER2_TYPE 8 | TranslateMedium( 9 | _In_ NDIS_MEDIUM Medium 10 | ); 11 | 12 | void 13 | NxGetPacketLayout( 14 | _In_ NDIS_MEDIUM MediaType, 15 | _In_ NET_RING_COLLECTION const * Descriptor, 16 | _In_ NET_EXTENSION const & VirtualAddressExtension, 17 | _Inout_ NET_PACKET * Packet, 18 | _In_ size_t PayloadBackfill = 0 19 | ); 20 | 21 | enum class AddressType : UINT8 22 | { 23 | Unicast = 0x1, 24 | Multicast = 0x2, 25 | Broadcast = 0x3, 26 | }; 27 | 28 | AddressType 29 | NxGetPacketAddressType( 30 | _In_ NET_PACKET_LAYER2_TYPE Layer2Type, 31 | _In_ NET_BUFFER const & NetBuffer 32 | ); 33 | -------------------------------------------------------------------------------- /netcx/bm/mdl.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | 6 | struct RtlMdl : public MDL 7 | { 8 | 9 | static 10 | RtlMdl * 11 | Make( 12 | _In_ void * VirtualAddress, 13 | _In_ size_t Length 14 | ); 15 | 16 | PFN_NUMBER * 17 | GetPfnArray( 18 | void 19 | ); 20 | 21 | PFN_NUMBER const * 22 | GetPfnArray( 23 | void 24 | ) const; 25 | 26 | size_t 27 | GetPfnArrayCount( 28 | void 29 | ) const; 30 | 31 | private: 32 | 33 | void * 34 | operator new( 35 | _In_ size_t BaseSize, 36 | _In_ void * VirtualAddress, 37 | _In_ size_t Length 38 | ); 39 | 40 | }; 41 | 42 | static_assert(sizeof(RtlMdl) == sizeof(MDL)); 43 | -------------------------------------------------------------------------------- /netcx/bm/dmaallocator.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "IBufferVectorAllocator.hpp" 5 | 6 | class PAGED DmaAllocator : public IBufferVectorAllocator 7 | { 8 | public: 9 | 10 | DmaAllocator( 11 | _In_ NET_CLIENT_MEMORY_CONSTRAINTS::DMA & Dma 12 | ); 13 | 14 | IBufferVector * 15 | AllocateVector( 16 | _In_ size_t BufferCount, 17 | _In_ size_t BufferSize, 18 | _In_ size_t BufferOffset, 19 | _In_ NODE_REQUIREMENT PreferredNode 20 | ); 21 | 22 | private: 23 | 24 | DMA_ADAPTER * 25 | m_DmaAdapter; 26 | 27 | PHYSICAL_ADDRESS 28 | m_MaximumPhysicalAddress; 29 | 30 | bool 31 | m_CacheEnabled; 32 | 33 | NODE_REQUIREMENT 34 | m_PreferredNode; 35 | }; 36 | -------------------------------------------------------------------------------- /netcx/bm/ibuffervector.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | class PAGED IBufferVector : 5 | public NONPAGED_OBJECT<'vmxn'> 6 | { 7 | friend class BufferPool; 8 | 9 | public: 10 | 11 | IBufferVector( 12 | _In_ size_t BufferCount, 13 | _In_ size_t BufferOffset, 14 | _In_ size_t BufferCapacity 15 | ); 16 | 17 | virtual 18 | ~IBufferVector( 19 | void 20 | ) = default; 21 | 22 | virtual 23 | void 24 | GetEntryByIndex( 25 | _In_ size_t Index, 26 | _Out_ NET_DATA_HEADER* NetDataHeader 27 | ) const = 0; 28 | 29 | protected: 30 | 31 | size_t 32 | m_BufferCount = 0; 33 | 34 | size_t 35 | m_BufferOffset = 0; 36 | 37 | size_t 38 | m_BufferCapacity = 0; 39 | }; 40 | -------------------------------------------------------------------------------- /netcx/adapter/nxadaptercollection.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "netadaptercx_triage.h" 6 | 7 | #include 8 | 9 | class NxAdapter; 10 | 11 | using unique_miniport_reference = wil::unique_any; 12 | 13 | class NxAdapterCollection 14 | : public NxCollection 15 | { 16 | public: 17 | 18 | static 19 | void 20 | GetTriageInfo( 21 | void 22 | ); 23 | 24 | unique_miniport_reference 25 | FindAndReferenceMiniportByInstanceName( 26 | _In_ UNICODE_STRING const * InstanceName 27 | ) const; 28 | 29 | NxAdapter * 30 | FindAndReferenceAdapterByBaseName( 31 | _In_ UNICODE_STRING const * BaseName 32 | ) const; 33 | }; 34 | -------------------------------------------------------------------------------- /netcx/translator/txpeeraddressdemux.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "NxTxDemux.hpp" 6 | 7 | class NxTranslationApp; 8 | 9 | class TxPeerAddressDemux 10 | : public NxTxDemux 11 | { 12 | 13 | public: 14 | 15 | TxPeerAddressDemux( 16 | size_t Range, 17 | NxTranslationApp const & App 18 | ) noexcept; 19 | 20 | size_t 21 | Demux( 22 | _In_ NET_BUFFER_LIST const * NetBufferList 23 | ) const; 24 | 25 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 26 | GenerateDemuxProperty( 27 | _In_ NET_BUFFER_LIST const * NetBufferList 28 | ) override; 29 | 30 | private: 31 | 32 | NxTranslationApp const & 33 | m_app; 34 | 35 | size_t 36 | Demux( 37 | _In_ NET_CLIENT_EUI48_ADDRESS const * Address 38 | ) const; 39 | 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /netcx/adapter/extension/nxextension.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #define MAXIMUM_ALLOWED_EXTENSION_SIZE 1024 8 | 9 | struct NET_EXTENSION_PRIVATE 10 | { 11 | /// Name of the packet extension. String buffer is allocated with the 12 | /// NET_EXTENSION_PRIVATE block itself. 13 | PCWSTR Name = nullptr; 14 | 15 | /// Number of bytes requested to add to each packet. 16 | SIZE_T Size = 0; 17 | ULONG Version = 0; 18 | /// Alignment of the block to add to each packet. 19 | ULONG NonWdfStyleAlignment = 0; 20 | 21 | NET_EXTENSION_TYPE Type; 22 | 23 | /// The actual offset that was assigned to the packet extension, as 24 | /// measured from the start of the NET_PACKET. Or, zero if no offset 25 | /// has been assigned yet. 26 | SIZE_T AssignedOffset = 0; 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /rtl/inc/RtlHomogenousSequence.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // RtlHomogenousSequence is a utility class that detects whether a sequence of 4 | // integers is homogenous, i.e., consists entirely of the same value repeated. 5 | // 6 | // RtlHomogenousSequence s; 7 | // s.AddValue(42); 8 | // s.AddValue(42); 9 | // s.AddValue(42); 10 | // Assert(s.IsHomogenous()); 11 | // 12 | // s.AddValue(43); 13 | // Assert(!s.IsHomogenous()); 14 | // 15 | 16 | template 17 | class RtlHomogenousSequence 18 | { 19 | public: 20 | 21 | void AddValue(TINTEGER i) 22 | { 23 | m_setBits |= i; 24 | m_clearBits |= ~i; 25 | } 26 | 27 | bool IsHomogenous() const 28 | { 29 | return m_setBits == static_cast(~m_clearBits); 30 | } 31 | 32 | private: 33 | 34 | TINTEGER m_setBits = 0; 35 | TINTEGER m_clearBits = 0; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /netcx/translator/nxxlatcommon.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | Shared header for the entire XLAT app. 8 | 9 | --*/ 10 | 11 | #pragma once 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include "NetClientApi.h" 19 | #include "NxApp.hpp" 20 | 21 | #define MS_TO_100NS_CONVERSION 10000 22 | 23 | 24 | #define NBL_SEND_COMPLETION_BATCH_SIZE 64 25 | 26 | // both TCPIP and NWIFI currently process NBLs in batch of 32 27 | // so we use the same batch size here too for now. In the future, 28 | // this can be integrated into EC tunable 29 | #define NBL_RECEIVE_BATCH_SIZE 32 30 | 31 | // we cap the total number of bouce buffers preallocated if the NIC 32 | // supports larger than standard packet size, e.g. jumbo frame, LSO 33 | #define MAX_NUMBER_OF_BOUCE_BUFFERS_FOR_LARGE_PACKETS 256 34 | -------------------------------------------------------------------------------- /netcx/bm/commonbuffervector.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "IBufferVector.hpp" 5 | 6 | class PAGED CommonBufferVector : public IBufferVector 7 | { 8 | friend class DmaAllocator; 9 | 10 | public: 11 | 12 | CommonBufferVector( 13 | _In_ DMA_ADAPTER * DmaAdapter, 14 | _In_ size_t BufferCount, 15 | _In_ size_t BufferSize, 16 | _In_ size_t BufferOffset 17 | ); 18 | 19 | ~CommonBufferVector( 20 | void 21 | ); 22 | 23 | NONPAGED 24 | void 25 | GetEntryByIndex( 26 | _In_ size_t Index, 27 | _Out_ NET_DATA_HEADER * NetDataHeader 28 | ) const override; 29 | 30 | private: 31 | 32 | DMA_ADAPTER * 33 | m_DmaAdapter; 34 | 35 | PDMA_COMMON_BUFFER_VECTOR 36 | m_CommonBufferVector = nullptr; 37 | 38 | size_t 39 | m_BufferOffset = 0; 40 | }; 41 | -------------------------------------------------------------------------------- /netcx/bm/nonpagedbuffervector.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "IBufferVector.hpp" 5 | 6 | class PAGED NonPagedBufferVector : public IBufferVector 7 | { 8 | friend class NonPagedAllocator; 9 | 10 | struct Buffer 11 | { 12 | void * 13 | VirtualAddress = nullptr; 14 | 15 | MDL * 16 | Mdl = nullptr; 17 | }; 18 | 19 | public: 20 | 21 | NonPagedBufferVector( 22 | _In_ size_t BufferCount, 23 | _In_ size_t BufferSize, 24 | _In_ size_t BufferOffset 25 | ); 26 | 27 | ~NonPagedBufferVector( 28 | void 29 | ); 30 | 31 | NONPAGED 32 | void 33 | GetEntryByIndex( 34 | size_t Index, 35 | NET_DATA_HEADER* NetDataHeader 36 | ) const override; 37 | 38 | private: 39 | 40 | Rtl::KArray 41 | m_NonPagedBufferVector; 42 | }; 43 | -------------------------------------------------------------------------------- /netcx/translator/nxtxdemux.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class NxTxDemux 8 | : public NxNonpagedAllocation<'TxtN'> 9 | { 10 | 11 | public: 12 | 13 | enum class Type 14 | { 15 | UserPriority = 1, 16 | Peer, 17 | WmmInfo, 18 | }; 19 | 20 | NxTxDemux( 21 | NxTxDemux::Type, 22 | size_t Range 23 | ) noexcept; 24 | 25 | NxTxDemux::Type 26 | GetType( 27 | void 28 | ) const; 29 | 30 | size_t 31 | GetRange( 32 | void 33 | ) const; 34 | 35 | virtual 36 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 37 | GenerateDemuxProperty( 38 | _In_ NET_BUFFER_LIST const * NetBufferList 39 | ) = 0; 40 | 41 | private: 42 | 43 | NxTxDemux::Type const 44 | m_type; 45 | 46 | size_t const 47 | m_range = SIZE_T_MAX; 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Policy 2 | 3 | We welcome bug reports or feature suggestions. 4 | You can file theme here on our GitHub repository's issue tracker, or email us at NetAdapter@microsoft.com. 5 | 6 | NetAdapterCx.sys is under heavy development, so its implementation is changing quite a bit. 7 | Currently, we do that development internally at Microsoft, so you won't see the in-progress changes here on GitHub. 8 | The code here is a snapshot of the last shipping version of NetAdapterCx. 9 | That means we cannot take pull requests through GitHub. 10 | If you would like to collaborate with us on the code, please contact us first. 11 | 12 | This project has adopted the [Microsoft Open Source Code of 13 | Conduct](https://opensource.microsoft.com/codeofconduct/). 14 | For more information see the [Code of Conduct 15 | FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 16 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) 17 | with any additional questions or comments. 18 | -------------------------------------------------------------------------------- /netcx/ec/lib/irqlcontroller.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | class IrqlController 5 | { 6 | public: 7 | 8 | _IRQL_requires_max_(DISPATCH_LEVEL) 9 | explicit 10 | IrqlController( 11 | _In_ bool RaiseToDispatch 12 | ); 13 | 14 | IrqlController( 15 | IrqlController const & 16 | ) = delete; 17 | 18 | IrqlController & 19 | operator=( 20 | IrqlController const & 21 | ) = delete; 22 | 23 | _IRQL_requires_max_(DISPATCH_LEVEL) 24 | ~IrqlController( 25 | void 26 | ); 27 | 28 | _IRQL_requires_max_(DISPATCH_LEVEL) 29 | bool 30 | WasRaised( 31 | void 32 | ) const; 33 | 34 | _IRQL_requires_max_(DISPATCH_LEVEL) 35 | void 36 | Lower( 37 | void 38 | ) const; 39 | 40 | private: 41 | 42 | KIRQL 43 | m_prevIrql {}; 44 | 45 | bool const 46 | m_raiseToDispatchRequested; 47 | }; 48 | -------------------------------------------------------------------------------- /netcx/adapter/types/nxadapterextensiontypes.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "NxPrivateGlobals.hpp" 5 | 6 | class NxAdapterNdisPmCapabilities 7 | { 8 | public: 9 | 10 | // Fields from version 2.0 11 | ULONG 12 | Size = {}; 13 | 14 | ULONG 15 | MediaSpecificWakeUpEvents = {}; 16 | 17 | // Fields from version 2.1 18 | ULONG 19 | SupportedProtocolOffloads = {}; 20 | 21 | NxAdapterNdisPmCapabilities( 22 | void 23 | ) = default; 24 | 25 | NxAdapterNdisPmCapabilities( 26 | _In_ NX_PRIVATE_GLOBALS const & ClientGlobals, 27 | _In_ NET_ADAPTER_NDIS_PM_CAPABILITIES const & Capabilities 28 | ); 29 | 30 | explicit 31 | operator bool( 32 | void 33 | ) const; 34 | 35 | void 36 | Assign( 37 | _In_ NX_PRIVATE_GLOBALS const & ClientGlobals, 38 | _In_ NET_ADAPTER_NDIS_PM_CAPABILITIES const & Capabilities 39 | ); 40 | 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /netcx/adapter/powerpolicy/nxpowerentry.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | class NxPowerEntry : public KALLOCATOR<'EPxN'> 5 | { 6 | friend class NxPowerPolicy; 7 | friend class NxPowerList; 8 | friend class NxPowerOffloadList; 9 | friend class NxWakeSourceList; 10 | 11 | public: 12 | 13 | NxPowerEntry( 14 | _In_ NETADAPTER Adapter 15 | ); 16 | 17 | virtual 18 | ~NxPowerEntry( 19 | void 20 | ) = default; 21 | 22 | NETADAPTER 23 | GetAdapter( 24 | void 25 | ) const; 26 | 27 | void 28 | SetEnabled( 29 | _In_ bool Enabled 30 | ); 31 | 32 | bool 33 | IsEnabled( 34 | void 35 | ) const; 36 | 37 | protected: 38 | 39 | NETADAPTER const 40 | m_adapter; 41 | 42 | bool 43 | m_enabled = false; 44 | 45 | SINGLE_LIST_ENTRY 46 | m_powerPolicyLinkage = {}; 47 | 48 | SINGLE_LIST_ENTRY 49 | m_clientListLinkage = {}; 50 | 51 | }; 52 | -------------------------------------------------------------------------------- /netcx/adapter/nx.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | This is the main Ndis class extension library include file. 8 | 9 | --*/ 10 | 11 | #pragma once 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | 49 | #define NETADAPTERCX_TAG 'xCdN' 50 | -------------------------------------------------------------------------------- /netcx/ec/lib/notificationreserved.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | 6 | // This structure is stored in EXECUTION_CONTEXT_NOTIFICATION's Reserved field. 7 | // All member variables will be zero initialized 8 | struct NotificationReserved 9 | { 10 | BOOLEAN 11 | Enabled; 12 | 13 | _IRQL_requires_max_(DISPATCH_LEVEL) 14 | static 15 | NotificationReserved * 16 | FromNotificationEntry( 17 | _In_ LIST_ENTRY * NotificationEntry 18 | ); 19 | 20 | _IRQL_requires_max_(DISPATCH_LEVEL) 21 | EXECUTION_CONTEXT_NOTIFICATION * 22 | GetNotification( 23 | void 24 | ); 25 | 26 | _IRQL_requires_max_(DISPATCH_LEVEL) 27 | void 28 | Enable( 29 | void 30 | ); 31 | 32 | _IRQL_requires_max_(DISPATCH_LEVEL) 33 | void 34 | Disable( 35 | void 36 | ); 37 | }; 38 | 39 | static_assert( 40 | sizeof(NotificationReserved) <= 41 | sizeof(EXECUTION_CONTEXT_NOTIFICATION::Reserved)); 42 | -------------------------------------------------------------------------------- /netcx/bm/buffermanager.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "IBufferVectorAllocator.hpp" 6 | 7 | class PAGED BufferManager : 8 | public PAGED_OBJECT<'mbxn'> // 'nxbm' 9 | { 10 | 11 | public: 12 | 13 | NTSTATUS 14 | AddMemoryConstraints( 15 | _In_ NET_CLIENT_MEMORY_CONSTRAINTS* MemoryConstraints 16 | ); 17 | 18 | NTSTATUS 19 | InitializeBufferVectorAllocator( 20 | void 21 | ); 22 | 23 | NTSTATUS 24 | AllocateBufferVector( 25 | _In_ size_t BufferCount, 26 | _In_ size_t BufferSize, 27 | _In_ size_t BufferAlignment, 28 | _In_ size_t BufferAlignmentOffset, 29 | _In_ NODE_REQUIREMENT PreferredNode, 30 | _Out_ IBufferVector** BufferVector 31 | ); 32 | 33 | private: 34 | 35 | UINT64 36 | m_Id; 37 | 38 | Rtl::KArray 39 | m_MemoryConstraints; 40 | 41 | wistd::unique_ptr 42 | m_BufferVectorAllocator; 43 | 44 | }; 45 | -------------------------------------------------------------------------------- /netcx/translator/nxnblqueue.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | The NxNblQueue is a FIFO queues of NET_BUFFER_LISTs, with 8 | built-in synchronization. 9 | 10 | --*/ 11 | 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | class NxNblQueue 18 | { 19 | public: 20 | 21 | PAGED NxNblQueue(); 22 | 23 | _IRQL_requires_max_(DISPATCH_LEVEL) 24 | void Enqueue(_In_ PNET_BUFFER_LIST pNbl); 25 | 26 | _IRQL_requires_max_(DISPATCH_LEVEL) 27 | void Enqueue(_Inout_ NBL_COUNTED_QUEUE *queue); 28 | 29 | _IRQL_requires_max_(DISPATCH_LEVEL) 30 | void DequeueAll(_Out_ NBL_QUEUE *destination); 31 | 32 | _IRQL_requires_max_(DISPATCH_LEVEL) 33 | NET_BUFFER_LIST *DequeueAll(); 34 | 35 | _IRQL_requires_max_(DISPATCH_LEVEL) 36 | ULONG64 GetNblQueueDepth() const; 37 | 38 | _IRQL_requires_max_(DISPATCH_LEVEL) 39 | NET_BUFFER_LIST const * PeekNbl() const; 40 | 41 | private: 42 | 43 | NBL_COUNTED_QUEUE m_nblQueue; 44 | KSpinLock m_SpinLock; 45 | }; 46 | -------------------------------------------------------------------------------- /rtl/inc/kpushlock.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | typedef struct _KTHREAD *PKTHREAD; 8 | 9 | class KPushLockBase 10 | { 11 | public: 12 | 13 | KPushLockBase() = default; 14 | KPushLockBase(KPushLockBase &) = delete; 15 | KPushLockBase & operator=(KPushLockBase &) = delete; 16 | 17 | PAGED void AcquireShared(); 18 | 19 | PAGED void ReleaseShared(); 20 | 21 | PAGED void AcquireExclusive(); 22 | 23 | PAGED void ReleaseExclusive(); 24 | 25 | PAGED void AssertLockHeld(); 26 | 27 | PAGED void AssertLockNotHeld(); 28 | 29 | protected: 30 | 31 | PAGED void InitializeInner(); 32 | 33 | private: 34 | 35 | #ifdef _KERNEL_MODE 36 | EX_PUSH_LOCK m_Lock; 37 | #else 38 | SRWLOCK m_Lock; 39 | #endif 40 | 41 | #if DBG 42 | PKTHREAD m_ExclusiveOwner; 43 | #endif 44 | }; 45 | 46 | class KPushLock : public KPushLockBase 47 | { 48 | public: 49 | 50 | PAGED KPushLock() noexcept; 51 | 52 | PAGED ~KPushLock(); 53 | }; 54 | 55 | class KPushLockManualConstruct : public KPushLockBase 56 | { 57 | public: 58 | 59 | PAGED void Initialize(); 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /netcx/translator/nxxlatprecomp.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | Precompiled header. 8 | 9 | Do not put any local header files in here. 10 | (Local header files change more often, which makes it more likely you'll 11 | need to recompile the pch to see those changes.) 12 | 13 | --*/ 14 | 15 | #pragma once 16 | 17 | #ifdef _KERNEL_MODE 18 | #include 19 | #include 20 | #include 21 | #else 22 | #include 23 | #include 24 | #include 25 | #include 26 | #endif // _KERNEL_MODE 27 | 28 | #ifdef _KERNEL_MODE 29 | #include 30 | #include 31 | #else 32 | #include "umwdm.h" 33 | #include 34 | #endif // _KERNEL_MODE 35 | 36 | #include 37 | 38 | #ifndef _KERNEL_MODE 39 | typedef PHYSICAL_ADDRESS NDIS_PHYSICAL_ADDRESS, *PNDIS_PHYSICAL_ADDRESS; 40 | #include 41 | #include 42 | #include 43 | #endif // _KERNEL_MODE 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | -------------------------------------------------------------------------------- /rtl/inc/kdeletepolicy.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | template 8 | using KDeletePtr = wistd::default_delete; 9 | 10 | template 11 | struct KFreePool 12 | { 13 | PAGED KFreePool() {} 14 | 15 | template 16 | PAGED KFreePool(const KFreePool&) { } 17 | 18 | PAGED void operator()(T *p) const 19 | { 20 | if (p != nullptr) 21 | { 22 | p->~T(); 23 | ExFreePool(p); 24 | } 25 | } 26 | }; 27 | 28 | template 29 | struct KFreePoolNP 30 | { 31 | NONPAGED KFreePoolNP() {} 32 | 33 | template 34 | NONPAGED KFreePoolNP(const KFreePoolNP&) { } 35 | 36 | NONPAGED void operator()(T *p) const 37 | { 38 | if (p != nullptr) 39 | { 40 | p->~T(); 41 | ExFreePool(p); 42 | } 43 | } 44 | }; 45 | 46 | template 47 | struct KInplaceDelete 48 | { 49 | PAGED KInplaceDelete() { } 50 | 51 | template 52 | PAGED KInplaceDelete(const KInplaceDelete&) { } 53 | 54 | PAGED void operator()(T *p) const { p->~T(); } 55 | }; 56 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /netcx/ec/inc/executioncontextnotification.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | typedef 5 | _IRQL_requires_max_(DISPATCH_LEVEL) 6 | void 7 | EVT_EXECUTION_CONTEXT_SET_NOTIFICATION_ENABLED( 8 | _In_ void * Context, 9 | _In_ BOOLEAN NotificationEnabled 10 | ); 11 | 12 | typedef EVT_EXECUTION_CONTEXT_SET_NOTIFICATION_ENABLED *PFN_EXECUTION_CONTEXT_SET_NOTIFICATION_ENABLED; 13 | 14 | typedef struct _EXECUTION_CONTEXT_NOTIFICATION 15 | { 16 | void * 17 | Context; 18 | 19 | PFN_EXECUTION_CONTEXT_SET_NOTIFICATION_ENABLED 20 | SetNotificationFn; 21 | 22 | LIST_ENTRY 23 | Link; 24 | 25 | void * 26 | Reserved[4]; 27 | } EXECUTION_CONTEXT_NOTIFICATION; 28 | 29 | inline 30 | void 31 | INITIALIZE_EXECUTION_CONTEXT_NOTIFICATION( 32 | _Out_ EXECUTION_CONTEXT_NOTIFICATION * Notification, 33 | _In_opt_ void * Context, 34 | _In_ PFN_EXECUTION_CONTEXT_SET_NOTIFICATION_ENABLED SetNotificationFn 35 | ) 36 | { 37 | RtlZeroMemory(Notification, sizeof(*Notification)); 38 | Notification->Context = Context; 39 | Notification->SetNotificationFn = SetNotificationFn; 40 | InitializeListHead(&Notification->Link); 41 | } 42 | -------------------------------------------------------------------------------- /netcx/ec/lib/timebudgetwarninglogger.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include "TimeBudget.h" 7 | 8 | class TimeBudgetWarningLogger 9 | { 10 | public: 11 | PAGED 12 | TimeBudgetWarningLogger( 13 | const GUID& ClientIdentifier, 14 | const ULONG DispatchTimeWarningInterval 15 | ); 16 | 17 | NONPAGED 18 | void LogWarningIfOvertime( 19 | _In_ const TimeBudget& timeBudget 20 | ); 21 | 22 | PAGED 23 | void SetFriendlyName( 24 | UNICODE_STRING const * FriendlyName 25 | ); 26 | 27 | PAGED 28 | void SetWatermark( 29 | _In_ ULONG DispatchIrqlWarningWatermarkMs 30 | ); 31 | 32 | private: 33 | 34 | NONPAGED 35 | void ReportWarning(ULONG TimeSinceLastReportMs); 36 | 37 | UNICODE_STRING const * m_friendlyEcName {}; 38 | const GUID m_clientIdentifier {}; 39 | 40 | UINT32 m_iterationsOverTimeCount {0}; 41 | ULONG m_watermarkMs {0}; 42 | ULONG const m_dispatchTimeWarningIntervalMs {0}; 43 | 44 | LARGE_INTEGER m_nextReportingDeadlineTicks {0}; 45 | ULONG const m_reportIntervalTicks {0}; 46 | ULONG m_watermarkTicks {0}; 47 | }; 48 | -------------------------------------------------------------------------------- /netcx/translator/nxtxnblcontext.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | // GSO auxilary information stored inplace NBL. 8 | struct GSO_CONTEXT 9 | { 10 | bool 11 | Segmented = false; 12 | 13 | ULONG 14 | DataOffset = 0U; 15 | }; 16 | 17 | struct TX_NBL_CONTEXT 18 | { 19 | GSO_CONTEXT 20 | gsoNblContext = {}; 21 | }; 22 | 23 | static_assert(sizeof(TX_NBL_CONTEXT) <= FIELD_SIZE(NET_BUFFER_LIST, MiniportReserved), 24 | "the size of TX_NBL_CONTEXT struct is larger than available space on NBL reserved for miniport"); 25 | 26 | inline 27 | _IRQL_requires_(PASSIVE_LEVEL) 28 | GSO_CONTEXT * 29 | GetGsoContextFromNetBufferList( 30 | NET_BUFFER_LIST * NetBufferList 31 | ) 32 | { 33 | auto txNblContext = reinterpret_cast(&NetBufferList->MiniportReserved[0]); 34 | 35 | return &txNblContext->gsoNblContext; 36 | } 37 | 38 | inline 39 | _IRQL_requires_(PASSIVE_LEVEL) 40 | bool 41 | IsNetBufferListSoftwareSegmented( 42 | _In_ NET_BUFFER_LIST const * NetBufferList 43 | ) 44 | { 45 | return GetGsoContextFromNetBufferList(const_cast(NetBufferList))->Segmented; 46 | } 47 | -------------------------------------------------------------------------------- /rtl/inc/krefinline.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | Copyright (c) Microsoft Corporation 3 | 4 | Module Name: 5 | 6 | KRefInline.h 7 | 8 | Abstract: 9 | 10 | Complements KRef.h; refer to that file for details 11 | 12 | This file is a workaround for a poor design in the debugger. 13 | The debugger unfortunately uses line numbers to encode metadata, 14 | including information about whether an assembly instruction 15 | is compiler-generated, and thus, uninteresting. 16 | 17 | So if we want to tell the debugger to skip over boring lines 18 | of code, we have to mess with the actual line numbering of 19 | source code. This cannot be done cleanly without messing up 20 | debugging in the rest of the source file. Therefore, we move 21 | certain parts of the code to a separate source file, to avoid 22 | tainting the original file's line numbering. 23 | 24 | --*/ 25 | 26 | #line 0x00f00f00 // always step over this routine in the debugger 27 | PAGED T &operator*() const { return **_p; } 28 | 29 | #line 0x00f00f00 // always step over this routine in the debugger 30 | PAGED T *operator->() const { return &**this; } 31 | 32 | #line 0x00f00f00 // always step over this routine in the debugger 33 | PAGED T *get() const { return &**_p; } 34 | 35 | 36 | -------------------------------------------------------------------------------- /netcx/ec/lib/irqlcontroller.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | #include "IrqlController.h" 4 | 5 | _Use_decl_annotations_ 6 | IrqlController::IrqlController( 7 | bool RaiseToDispatch 8 | ) 9 | : m_raiseToDispatchRequested(RaiseToDispatch) 10 | { 11 | #ifdef _KERNEL_MODE 12 | m_prevIrql = KeGetCurrentIrql(); 13 | if (m_prevIrql < DISPATCH_LEVEL && m_raiseToDispatchRequested) 14 | { 15 | m_prevIrql = KeRaiseIrqlToDpcLevel(); 16 | } 17 | #else 18 | UNREFERENCED_PARAMETER(RaiseToDispatch); 19 | #endif 20 | } 21 | 22 | _Use_decl_annotations_ 23 | IrqlController::~IrqlController( 24 | void 25 | ) 26 | { 27 | Lower(); 28 | } 29 | 30 | _Use_decl_annotations_ 31 | bool 32 | IrqlController::WasRaised( 33 | void 34 | ) const 35 | { 36 | #ifdef _KERNEL_MODE 37 | return m_prevIrql < DISPATCH_LEVEL && m_raiseToDispatchRequested; 38 | #else 39 | return false; 40 | #endif 41 | } 42 | 43 | _Use_decl_annotations_ 44 | void 45 | IrqlController::Lower( 46 | void 47 | ) const 48 | { 49 | #ifdef _KERNEL_MODE 50 | if (m_prevIrql < DISPATCH_LEVEL && m_raiseToDispatchRequested) 51 | { 52 | KeLowerIrql(m_prevIrql); 53 | } 54 | #endif 55 | } 56 | -------------------------------------------------------------------------------- /netcx/ec/lib/executioncontexttask.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | 4 | #include "ExecutionContextTask.hpp" 5 | 6 | _Use_decl_annotations_ 7 | ExecutionContextTask * 8 | ExecutionContextTask::FromLink( 9 | LIST_ENTRY * Link 10 | ) 11 | { 12 | return CONTAINING_RECORD( 13 | Link, 14 | ExecutionContextTask, 15 | m_linkage); 16 | } 17 | 18 | _Use_decl_annotations_ 19 | ExecutionContextTask::ExecutionContextTask( 20 | void * TaskContext, 21 | PFN_EXECUTION_CONTEXT_TASK TaskFunction, 22 | bool SignalCompletion 23 | ) 24 | : m_context(TaskContext) 25 | , m_taskFn(TaskFunction) 26 | , m_signalCompletion(SignalCompletion) 27 | { 28 | InitializeListHead(&m_linkage); 29 | } 30 | 31 | _Use_decl_annotations_ 32 | bool 33 | ExecutionContextTask::AddToList( 34 | LIST_ENTRY * ListHead 35 | ) 36 | { 37 | if (!IsListEmpty(&m_linkage)) 38 | { 39 | return false; 40 | } 41 | 42 | InsertTailList(ListHead, &m_linkage); 43 | 44 | return true; 45 | } 46 | 47 | _Use_decl_annotations_ 48 | void 49 | ExecutionContextTask::WaitForCompletion( 50 | void 51 | ) 52 | { 53 | NT_FRE_ASSERT(m_signalCompletion); 54 | m_completed.Wait(); 55 | } 56 | -------------------------------------------------------------------------------- /netcx/adapter/nxexecutioncontext.hpp: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (C) Microsoft Corporation. All rights reserved. 3 | 4 | #pragma once 5 | 6 | #include "Nx.hpp" 7 | #include "ExecutionContext.hpp" 8 | 9 | class NxExecutionContext 10 | : public ExecutionContext 11 | { 12 | public: 13 | 14 | _IRQL_requires_(PASSIVE_LEVEL) 15 | NxExecutionContext( 16 | _In_ WDFDEVICE Device, 17 | _In_ NET_EXECUTION_CONTEXT_CONFIG const * Config 18 | ); 19 | 20 | _IRQL_requires_max_(DISPATCH_LEVEL) 21 | ~NxExecutionContext( 22 | void 23 | ); 24 | 25 | _IRQL_requires_(PASSIVE_LEVEL) 26 | NTSTATUS 27 | Initialize( 28 | void 29 | ); 30 | 31 | _IRQL_requires_max_(DISPATCH_LEVEL) 32 | WDFDEVICE 33 | GetDevice( 34 | void 35 | ) const; 36 | 37 | private: 38 | 39 | NETEXECUTIONCONTEXT const 40 | m_handle; 41 | 42 | WDFDEVICE const 43 | m_device; 44 | 45 | NET_EXECUTION_CONTEXT_CONFIG 46 | m_config = {}; 47 | 48 | EXECUTION_CONTEXT_NOTIFICATION 49 | m_driverNotification; 50 | 51 | EXECUTION_CONTEXT_POLL 52 | m_preAdvancePoll; 53 | 54 | EXECUTION_CONTEXT_POLL 55 | m_postAdvancePoll; 56 | }; 57 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NxExecutionContext, GetExecutionContextFromHandle); 58 | -------------------------------------------------------------------------------- /rtl/inc/kcriticalregion.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | class KCriticalRegion 7 | { 8 | public: 9 | 10 | PAGED KCriticalRegion() : m_Entered(false) { } 11 | 12 | PAGED ~KCriticalRegion() { if (m_Entered) Leave(); } 13 | 14 | KCriticalRegion(KCriticalRegion &) = delete; 15 | KCriticalRegion &operator=(KCriticalRegion &) = delete; 16 | 17 | PAGED void Enter() 18 | { 19 | ASSERT(m_Entered == false); 20 | UnbalancedEnter(); 21 | m_Entered = true; 22 | } 23 | 24 | PAGED void Leave() 25 | { 26 | ASSERT(m_Entered == true); 27 | m_Entered = false; 28 | UnbalancedLeave(); 29 | } 30 | 31 | static PAGED void UnbalancedEnter() 32 | { 33 | #if _KERNEL_MODE 34 | KeEnterCriticalRegion(); 35 | #endif 36 | } 37 | 38 | static PAGED void UnbalancedLeave() 39 | { 40 | #if _KERNEL_MODE 41 | KeLeaveCriticalRegion(); 42 | #endif 43 | } 44 | 45 | private: 46 | 47 | bool m_Entered; 48 | }; 49 | 50 | struct KDefaultRegion 51 | { 52 | void Enter() { } 53 | void Leave() { } 54 | }; 55 | 56 | struct KIrqlRegion 57 | { 58 | KIrqlRegion() { } 59 | ~KIrqlRegion() { } 60 | 61 | void Enter() { } 62 | void Leave() { } 63 | 64 | KIRQL m_OldIrql; 65 | }; 66 | 67 | 68 | -------------------------------------------------------------------------------- /netcx/translator/nxringcontext.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "NxXlatPrecomp.hpp" 6 | #include "NxXlatCommon.hpp" 7 | 8 | #include "NxRingContext.tmh" 9 | #include "NxRingContext.hpp" 10 | 11 | #include 12 | 13 | NxRingContext::NxRingContext( 14 | _In_ NET_RING_COLLECTION const & Rings, 15 | _In_ size_t RingIndex 16 | ) : 17 | m_rings(Rings), 18 | m_ringIndex(RingIndex) 19 | { 20 | } 21 | 22 | NTSTATUS 23 | NxRingContext::Initialize( 24 | _In_ size_t ElementSize 25 | ) 26 | { 27 | auto const ringSize = m_rings.Rings[m_ringIndex]->NumberOfElements * ElementSize; 28 | auto const allocationSize = ringSize + FIELD_OFFSET(NET_RING, Buffer[0]); 29 | 30 | auto context = reinterpret_cast( 31 | ExAllocatePoolWithTag(NonPagedPoolNxCacheAligned, allocationSize, 'BRxN')); 32 | if (! context) 33 | { 34 | return STATUS_INSUFFICIENT_RESOURCES; 35 | } 36 | 37 | RtlZeroMemory(context, allocationSize); 38 | context->ElementStride = static_cast(ElementSize); 39 | context->NumberOfElements = m_rings.Rings[m_ringIndex]->NumberOfElements; 40 | context->ElementIndexMask = m_rings.Rings[m_ringIndex]->ElementIndexMask; 41 | 42 | m_context.reset(context); 43 | 44 | return STATUS_SUCCESS; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /netcx/statistics/histogramhub.h: -------------------------------------------------------------------------------- 1 | 2 | // Copyright (C) Microsoft Corporation. All rights reserved. 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | #include "Histogram.h" 9 | 10 | namespace Statistics 11 | { 12 | class Hub 13 | : public NONPAGED_OBJECT<'bhTS'> 14 | { 15 | public: 16 | PAGED 17 | bool 18 | AddHistogramReference( 19 | _In_ Histogram& histogram 20 | ); 21 | 22 | PAGED 23 | void 24 | RemoveHistogramReference( 25 | _In_ Histogram& histogram 26 | ); 27 | 28 | PAGED 29 | void 30 | ResetHistogramsValues( 31 | void 32 | ); 33 | 34 | template 35 | PAGED 36 | ULONG 37 | SerializedSize( 38 | void 39 | ) const; 40 | 41 | template 42 | PAGED 43 | NTSTATUS 44 | Serialize( 45 | _Out_writes_bytes_(cbOut) T *out, 46 | _In_ ULONG cbOut, 47 | _Out_ ULONG &bytesNeeded 48 | ) const; 49 | 50 | private: 51 | _Guarded_by_(m_histogramsListLock) 52 | Rtl::KArray 53 | m_histogramsArray { 50 }; 54 | 55 | mutable KPushLock 56 | m_histogramsListLock; 57 | }; 58 | } 59 | -------------------------------------------------------------------------------- /netcx/translator/checksum/checksum.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include 4 | 5 | #include "Checksum.hpp" 6 | 7 | // Rx 8 | 9 | // Depending on the packet contents, one of the following 3 functions will 10 | // be called from NxRxXlat::TransferDataBufferFromNetPacketToNbl() to validate 11 | // the packet and discard if necessary. We will do this only if the NET_PACKET 12 | // checksum is NetPacketRxChecksumEvaluationNotChecked and the checksum offload 13 | // is requested. 14 | 15 | _Use_decl_annotations_ 16 | bool 17 | Checksum::IsIpv4ChecksumValid( 18 | UINT8 const * Buffer, 19 | size_t Length 20 | ) 21 | { 22 | // Km: Call SegLibPvtChecksumBuffer() for validation of Rx packet 23 | UNREFERENCED_PARAMETER(Buffer); 24 | UNREFERENCED_PARAMETER(Length); 25 | 26 | return true; 27 | } 28 | 29 | _Use_decl_annotations_ 30 | bool 31 | Checksum::IsUdpChecksumValid( 32 | UINT8 const * Buffer, 33 | size_t Length 34 | ) 35 | { 36 | UNREFERENCED_PARAMETER(Buffer); 37 | UNREFERENCED_PARAMETER(Length); 38 | 39 | return true; 40 | } 41 | 42 | _Use_decl_annotations_ 43 | bool 44 | Checksum::IsTcpChecksumValid( 45 | UINT8 const * Buffer, 46 | size_t Length 47 | ) 48 | { 49 | UNREFERENCED_PARAMETER(Buffer); 50 | UNREFERENCED_PARAMETER(Length); 51 | 52 | return true; 53 | } 54 | -------------------------------------------------------------------------------- /netcx/adapter/extension/nxextensionlayout.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "NxExtension.hpp" 9 | 10 | #ifdef TEST_HARNESS_CLASS_NAME 11 | #define TEST_HARNESS_FRIEND_DECLARATION friend class TEST_HARNESS_CLASS_NAME 12 | #else 13 | #define TEST_HARNESS_FRIEND_DECLARATION 14 | #endif 15 | 16 | class NxExtensionLayout 17 | { 18 | TEST_HARNESS_FRIEND_DECLARATION; 19 | 20 | public: 21 | 22 | NxExtensionLayout( 23 | size_t StartOffset, 24 | size_t MinimumAlignment 25 | ); 26 | 27 | size_t 28 | Generate( 29 | void 30 | ); 31 | 32 | NET_EXTENSION_PRIVATE const * 33 | GetExtension( 34 | PCWSTR Name, 35 | UINT32 Version, 36 | NET_EXTENSION_TYPE Type 37 | ) const; 38 | 39 | NTSTATUS 40 | PutExtension( 41 | PCWSTR Name, 42 | UINT32 Version, 43 | NET_EXTENSION_TYPE Type, 44 | size_t Size, 45 | size_t Alignment 46 | ); 47 | 48 | private: 49 | 50 | size_t 51 | m_startOffset = 0; 52 | 53 | size_t 54 | m_minimumAlignment = 0; 55 | 56 | Rtl::KArray 57 | m_extensions; 58 | 59 | Rtl::KArray 60 | m_temporary; 61 | 62 | }; 63 | 64 | 65 | -------------------------------------------------------------------------------- /netcx/bm/commonbuffervector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "BmPrecomp.hpp" 3 | 4 | #include "CommonBufferVector.hpp" 5 | #include "CommonBufferVector.tmh" 6 | 7 | _Use_decl_annotations_ 8 | CommonBufferVector::CommonBufferVector( 9 | DMA_ADAPTER * DmaAdapter, 10 | size_t BufferCount, 11 | size_t BufferSize, 12 | size_t BufferOffset 13 | ) 14 | : IBufferVector(BufferCount, BufferSize, BufferOffset) 15 | , m_DmaAdapter(DmaAdapter) 16 | { 17 | } 18 | 19 | CommonBufferVector::~CommonBufferVector( 20 | void 21 | ) 22 | { 23 | // Free the common buffer vector if one was allocated 24 | if (m_CommonBufferVector != nullptr) 25 | { 26 | m_DmaAdapter->DmaOperations->FreeCommonBufferVector(m_DmaAdapter, m_CommonBufferVector); 27 | m_CommonBufferVector = nullptr; 28 | } 29 | } 30 | 31 | NONPAGED 32 | _Use_decl_annotations_ 33 | void 34 | CommonBufferVector::GetEntryByIndex( 35 | size_t Index, 36 | NET_DATA_HEADER * NetDataHeader 37 | ) const 38 | { 39 | m_DmaAdapter->DmaOperations->GetCommonBufferFromVectorByIndex( 40 | m_DmaAdapter, 41 | m_CommonBufferVector, 42 | static_cast(Index), 43 | &NetDataHeader->VirtualAddress, 44 | reinterpret_cast(&NetDataHeader->LogicalAddress)); 45 | 46 | NetDataHeader->Mdl = nullptr; 47 | } 48 | -------------------------------------------------------------------------------- /netcx/bm/nonpagedbuffervector.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "BmPrecomp.hpp" 3 | 4 | #include "NonPagedBufferVector.hpp" 5 | #include "NonPagedBufferVector.tmh" 6 | 7 | NonPagedBufferVector::NonPagedBufferVector( 8 | _In_ size_t BufferCount, 9 | _In_ size_t BufferSize, 10 | _In_ size_t BufferOffset 11 | ) 12 | : IBufferVector(BufferCount, BufferSize, BufferOffset) 13 | { 14 | } 15 | 16 | NonPagedBufferVector::~NonPagedBufferVector( 17 | void 18 | ) 19 | { 20 | for (size_t i = 0; i < m_BufferCount; i++) 21 | { 22 | if (m_NonPagedBufferVector[i].VirtualAddress) 23 | { 24 | ExFreePool(m_NonPagedBufferVector[i].VirtualAddress); 25 | m_NonPagedBufferVector[i].VirtualAddress = nullptr; 26 | } 27 | 28 | if (m_NonPagedBufferVector[i].Mdl) 29 | { 30 | ExFreePool(m_NonPagedBufferVector[i].Mdl); 31 | m_NonPagedBufferVector[i].Mdl = nullptr; 32 | } 33 | } 34 | } 35 | 36 | NONPAGED 37 | _Use_decl_annotations_ 38 | void 39 | NonPagedBufferVector::GetEntryByIndex( 40 | size_t Index, 41 | NET_DATA_HEADER * NetDataHeader 42 | ) const 43 | { 44 | NetDataHeader->VirtualAddress = m_NonPagedBufferVector[Index].VirtualAddress; 45 | NetDataHeader->LogicalAddress = 0ULL; 46 | NetDataHeader->Mdl = m_NonPagedBufferVector[Index].Mdl; 47 | } 48 | -------------------------------------------------------------------------------- /netcx/translator/segmentation/segmentation.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include 4 | 5 | #include "Segmentation.hpp" 6 | #include "../NxTxNblContext.hpp" 7 | 8 | 9 | _IRQL_requires_(PASSIVE_LEVEL) 10 | void 11 | MarkNetBufferListSoftwareSegmented( 12 | _Inout_ NET_BUFFER_LIST * NetBufferList, 13 | _In_ ULONG DataOffset, 14 | _In_ NDIS_NET_BUFFER_LIST_INFO OffloadType 15 | ) 16 | /*++ 17 | 18 | Routine Description: 19 | 20 | Mark NetBufferList as segmented, store info needed for later freeing NetBufferList, 21 | and clear segmented NBL's LSO/USO info. 22 | 23 | --*/ 24 | { 25 | NT_FRE_ASSERT( 26 | OffloadType == TcpLargeSendNetBufferListInfo || 27 | OffloadType == UdpSegmentationOffloadInfo); 28 | 29 | auto gsoNblContext = GetGsoContextFromNetBufferList(NetBufferList); 30 | gsoNblContext->Segmented = true; 31 | gsoNblContext->DataOffset = DataOffset; 32 | 33 | if (OffloadType == TcpLargeSendNetBufferListInfo) 34 | { 35 | NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO clearLsoInfo = {}; 36 | NetBufferList->NetBufferListInfo[TcpLargeSendNetBufferListInfo] = clearLsoInfo.Value; 37 | } 38 | else 39 | { 40 | NDIS_UDP_SEGMENTATION_OFFLOAD_NET_BUFFER_LIST_INFO clearUsoInfo = {}; 41 | NetBufferList->NetBufferListInfo[UdpSegmentationOffloadInfo] = clearUsoInfo.Value; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /netcx/adapter/version.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #define INIT_GUID 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "NxPrivateGlobals.hpp" 13 | #include "NxCollection.hpp" 14 | #include "NxDevice.hpp" 15 | 16 | class CxDriverContext 17 | { 18 | public: 19 | // 20 | // Built-in datapath apps: NBL translator 21 | // 22 | NxTranslationAppFactory 23 | TranslationAppFactory; 24 | 25 | NTSTATUS 26 | Init( 27 | _In_ UNICODE_STRING const * RegistryPath 28 | ); 29 | 30 | static void 31 | Destroy( 32 | _In_ WDFOBJECT Driver 33 | ); 34 | 35 | NxCollection & 36 | GetDeviceCollection( 37 | void 38 | ); 39 | 40 | UNICODE_STRING const * 41 | GetRegistryPath( 42 | void 43 | ) const; 44 | 45 | private: 46 | NxCollection 47 | m_deviceCollection; 48 | 49 | KPoolPtr 50 | m_registryPath; 51 | 52 | }; 53 | 54 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CxDriverContext, GetCxDriverContextFromHandle); 55 | 56 | 57 | FORCEINLINE 58 | void 59 | NxDbgBreak( 60 | NX_PRIVATE_GLOBALS * PrivateGlobals 61 | ) 62 | { 63 | if (PrivateGlobals->CxVerifierOn && ! KdRefreshDebuggerNotPresent()) 64 | { 65 | DbgBreakPoint(); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /netcx/ec/lib/executioncontexttask.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class ExecutionContextTask 8 | { 9 | friend class 10 | ExecutionContext; 11 | 12 | public: 13 | 14 | _IRQL_requires_max_(PASSIVE_LEVEL) 15 | ExecutionContextTask( 16 | _In_ void * TaskContext, 17 | _In_ PFN_EXECUTION_CONTEXT_TASK TaskFn, 18 | _In_ bool SignalCompletion = true 19 | ); 20 | 21 | _IRQL_requires_max_(PASSIVE_LEVEL) 22 | virtual 23 | ~ExecutionContextTask( 24 | void 25 | ) = default; 26 | 27 | _IRQL_requires_max_(PASSIVE_LEVEL) 28 | virtual 29 | void 30 | WaitForCompletion( 31 | void 32 | ); 33 | 34 | private: 35 | 36 | _IRQL_requires_max_(DISPATCH_LEVEL) 37 | static 38 | ExecutionContextTask * 39 | FromLink( 40 | _In_ LIST_ENTRY * Link 41 | ); 42 | 43 | _IRQL_requires_max_(DISPATCH_LEVEL) 44 | bool 45 | AddToList( 46 | _In_ LIST_ENTRY * ListHead 47 | ); 48 | 49 | private: 50 | 51 | void * const 52 | m_context; 53 | 54 | PFN_EXECUTION_CONTEXT_TASK const 55 | m_taskFn; 56 | 57 | LIST_ENTRY 58 | m_linkage = {}; 59 | 60 | bool const 61 | m_signalCompletion; 62 | 63 | KAutoEvent 64 | m_completed; 65 | }; 66 | -------------------------------------------------------------------------------- /netcx/translator/txwmminfodemux.cpp: -------------------------------------------------------------------------------- 1 | #include "NxXlatPrecomp.hpp" 2 | #include "NxXlatCommon.hpp" 3 | #include 4 | 5 | #include "TxWmmInfoDemux.tmh" 6 | #include "TxWmmInfoDemux.hpp" 7 | 8 | static 9 | UINT8 10 | ParseWmmInfo( 11 | NET_BUFFER_LIST const * NetBufferList 12 | ) 13 | { 14 | auto const & info = *reinterpret_cast( 15 | &NetBufferList->NetBufferListInfo[Ieee8021QNetBufferListInfo]); 16 | 17 | return info.WLanTagHeader.WMMInfo; 18 | } 19 | 20 | TxWmmInfoDemux::TxWmmInfoDemux( 21 | size_t Range 22 | ) noexcept 23 | : NxTxDemux(NxTxDemux::Type::WmmInfo, Range) 24 | { 25 | } 26 | 27 | _Use_decl_annotations_ 28 | size_t 29 | TxWmmInfoDemux::Demux( 30 | NET_BUFFER_LIST const * NetBufferList 31 | ) const 32 | { 33 | return ParseWmmInfo(NetBufferList); 34 | } 35 | 36 | _Use_decl_annotations_ 37 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 38 | TxWmmInfoDemux::GenerateDemuxProperty( 39 | NET_BUFFER_LIST const * NetBufferList 40 | ) 41 | { 42 | auto const priority = ParseWmmInfo(NetBufferList); 43 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY property = { 44 | TxDemuxTypeWmmInfo, 45 | Demux(priority), 46 | }; 47 | property.Property.WmmInfo = priority; 48 | 49 | return wistd::move(property); 50 | } 51 | 52 | size_t 53 | TxWmmInfoDemux::Demux( 54 | _In_ UINT8 Value 55 | ) const 56 | { 57 | return Value; 58 | } 59 | -------------------------------------------------------------------------------- /netcx/ec/lib/notificationreserved.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | 4 | #include "NotificationReserved.hpp" 5 | 6 | _Use_decl_annotations_ 7 | NotificationReserved * 8 | NotificationReserved::FromNotificationEntry( 9 | LIST_ENTRY * NotificationEntry 10 | ) 11 | { 12 | auto notification = CONTAINING_RECORD( 13 | NotificationEntry, 14 | EXECUTION_CONTEXT_NOTIFICATION, 15 | Link); 16 | 17 | return reinterpret_cast(¬ification->Reserved[0]); 18 | } 19 | 20 | _Use_decl_annotations_ 21 | EXECUTION_CONTEXT_NOTIFICATION * 22 | NotificationReserved::GetNotification( 23 | void 24 | ) 25 | { 26 | return CONTAINING_RECORD( 27 | this, 28 | EXECUTION_CONTEXT_NOTIFICATION, 29 | Reserved); 30 | } 31 | 32 | _Use_decl_annotations_ 33 | void 34 | NotificationReserved::Enable( 35 | void 36 | ) 37 | { 38 | if (!Enabled) 39 | { 40 | Enabled = TRUE; 41 | 42 | auto notification = GetNotification(); 43 | notification->SetNotificationFn(notification->Context, Enabled); 44 | } 45 | } 46 | 47 | _Use_decl_annotations_ 48 | void 49 | NotificationReserved::Disable( 50 | void 51 | ) 52 | { 53 | if (Enabled) 54 | { 55 | Enabled = FALSE; 56 | 57 | auto notification = GetNotification(); 58 | notification->SetNotificationFn(notification->Context, Enabled); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /netcx/translator/nxringcontext.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class NxRingContext 8 | { 9 | 10 | public: 11 | 12 | NxRingContext( 13 | _In_ NET_RING_COLLECTION const & Rings, 14 | _In_ size_t RingIndex); 15 | 16 | NTSTATUS 17 | Initialize( 18 | _In_ size_t ElementSize); 19 | 20 | template 21 | TContext & 22 | GetContext( 23 | _In_ size_t Index 24 | ) const 25 | { 26 | return *static_cast( 27 | NetRingGetElementAtIndex( 28 | m_context.get(), 29 | static_cast(Index))); 30 | } 31 | 32 | template 33 | TContext & 34 | GetContextByElement( 35 | _In_ TElement const & Element 36 | ) const 37 | { 38 | auto const buffer = m_rings.Rings[m_ringIndex]->Buffer; 39 | auto const offset = reinterpret_cast(&Element) - buffer; 40 | 41 | NT_ASSERT(offset % m_rings.Rings[m_ringIndex]->ElementStride == 0); 42 | 43 | return GetContext(offset / m_rings.Rings[m_ringIndex]->ElementStride); 44 | } 45 | 46 | private: 47 | 48 | NET_RING_COLLECTION const & 49 | m_rings; 50 | 51 | size_t const 52 | m_ringIndex; 53 | 54 | KPoolPtr 55 | m_context; 56 | }; 57 | 58 | -------------------------------------------------------------------------------- /netcx/translator/txuserprioritydemux.cpp: -------------------------------------------------------------------------------- 1 | #include "NxXlatPrecomp.hpp" 2 | #include "NxXlatCommon.hpp" 3 | #include 4 | 5 | #include "TxUserPriorityDemux.tmh" 6 | #include "TxUserPriorityDemux.hpp" 7 | 8 | static 9 | UINT8 10 | ParseUserPriority( 11 | NET_BUFFER_LIST const * NetBufferList 12 | ) 13 | { 14 | auto const & info = *reinterpret_cast( 15 | &NetBufferList->NetBufferListInfo[Ieee8021QNetBufferListInfo]); 16 | 17 | return info.TagHeader.UserPriority; 18 | } 19 | 20 | TxUserPriorityDemux::TxUserPriorityDemux( 21 | size_t Range 22 | ) noexcept 23 | : NxTxDemux(NxTxDemux::Type::UserPriority, Range) 24 | { 25 | } 26 | 27 | _Use_decl_annotations_ 28 | size_t 29 | TxUserPriorityDemux::Demux( 30 | NET_BUFFER_LIST const * NetBufferList 31 | ) const 32 | { 33 | return ParseUserPriority(NetBufferList); 34 | } 35 | 36 | _Use_decl_annotations_ 37 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 38 | TxUserPriorityDemux::GenerateDemuxProperty( 39 | NET_BUFFER_LIST const * NetBufferList 40 | ) 41 | { 42 | auto const priority = ParseUserPriority(NetBufferList); 43 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY property = { 44 | TxDemuxType8021p, 45 | Demux(priority), 46 | }; 47 | property.Property.UserPriority = priority; 48 | 49 | return wistd::move(property); 50 | } 51 | 52 | size_t 53 | TxUserPriorityDemux::Demux( 54 | UINT8 Value 55 | ) const 56 | { 57 | return Value; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /netcx/statistics/histogram.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Statistics 9 | { 10 | const UINT32 HIST_NAME_SIZE = 128; 11 | 12 | class Histogram 13 | : public NONPAGED_OBJECT<'mrGH'> 14 | { 15 | friend class Hub; 16 | public: 17 | NONPAGED 18 | Histogram( 19 | // 600 buckets with 50 ms width cover 30 seconds 20 | _In_ ULONG64 HistogramSmallestValue = 0, 21 | _In_ ULONG64 HistogramBucketWidth = 50, 22 | _In_ ULONG HistogramNumBuckets = 600 23 | ); 24 | 25 | NONPAGED 26 | void 27 | AddValue( 28 | _In_ ULONG64 Value 29 | ); 30 | 31 | PAGED 32 | void 33 | SetName( 34 | _In_ UNICODE_STRING const & Name 35 | ); 36 | 37 | PAGED 38 | void 39 | ResetValues( 40 | void 41 | ); 42 | 43 | template 44 | PAGED 45 | ULONG 46 | SerializedSize() const; 47 | 48 | template 49 | PAGED 50 | NTSTATUS 51 | Serialize( 52 | _Out_writes_bytes_(cbOut) T *out, 53 | _In_ ULONG cbOut, 54 | _Out_ ULONG &bytesNeeded 55 | ) const; 56 | 57 | private: 58 | KPtr 59 | m_histogram; 60 | 61 | WCHAR 62 | m_name[HIST_NAME_SIZE] = {}; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /netcx/translator/nxrxnblcontext.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | class NxRxXlat; 8 | 9 | union COALEASCING_FALLBACK_INFO 10 | { 11 | struct 12 | { 13 | ULONG 14 | Layer2Type: 4; 15 | 16 | ULONG 17 | Layer2HeaderLength: 7; 18 | 19 | ULONG 20 | Reserved: 21; 21 | } Info; 22 | 23 | PVOID 24 | Value; 25 | }; 26 | 27 | struct RX_NBL_CONTEXT 28 | { 29 | NxRxXlat * 30 | Queue; 31 | 32 | COALEASCING_FALLBACK_INFO 33 | CoaleascingFallbackInfo; 34 | }; 35 | 36 | static_assert( 37 | sizeof(RX_NBL_CONTEXT) <= FIELD_SIZE(NET_BUFFER_LIST, MiniportReserved), 38 | "the size of RX_NBL_CONTEXT struct is larger than available space on NBL reserved for miniport"); 39 | 40 | inline 41 | RX_NBL_CONTEXT * 42 | GetRxContextFromNbl( 43 | NET_BUFFER_LIST * NetBufferList 44 | ) 45 | { 46 | return reinterpret_cast( 47 | &NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList)[0]); 48 | } 49 | 50 | struct RX_NB_CONTEXT 51 | { 52 | // 53 | // this NB's NET_BUFFER_MINIPORT_RESERVED(NB)[0] 54 | // field is used for the following purpose: 55 | // 56 | // if the packet has multiple fragments 57 | // 58 | bool HasMultipleFragments = false; 59 | }; 60 | 61 | inline 62 | RX_NB_CONTEXT* 63 | GetRxContextFromNb(PNET_BUFFER Nb) 64 | { 65 | return reinterpret_cast( 66 | &NET_BUFFER_MINIPORT_RESERVED(Nb)[0]); 67 | } 68 | -------------------------------------------------------------------------------- /netcx/adapter/nxextension.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "Nx.hpp" 6 | #include "NxExtension.hpp" 7 | 8 | #include "NxExtension.tmh" 9 | 10 | _Use_decl_annotations_ 11 | NTSTATUS 12 | NxExtension::Initialize( 13 | NET_EXTENSION_PRIVATE const * Extension 14 | ) 15 | { 16 | CX_RETURN_NTSTATUS_IF( 17 | STATUS_INVALID_PARAMETER, 18 | !WIN_VERIFY(RTL_IS_POWER_OF_TWO(Extension->NonWdfStyleAlignment))); 19 | 20 | auto const alignment = Extension->Type == NetExtensionTypePacket ? 21 | alignof(NET_PACKET) : 22 | alignof(NET_FRAGMENT); 23 | 24 | CX_RETURN_NTSTATUS_IF( 25 | STATUS_INVALID_PARAMETER, 26 | !WIN_VERIFY(Extension->NonWdfStyleAlignment <= alignment)); 27 | 28 | CX_RETURN_NTSTATUS_IF( 29 | STATUS_INVALID_PARAMETER, 30 | !WIN_VERIFY(Extension->Size <= MAXIMUM_ALLOWED_EXTENSION_SIZE)); 31 | 32 | CX_RETURN_NTSTATUS_IF( 33 | STATUS_INVALID_PARAMETER, 34 | !WIN_VERIFY(Extension->Size != 0)); 35 | 36 | auto const nameSize = sizeof(WCHAR) * (wcslen(Extension->Name) + 1); 37 | m_extensionName = MakeSizedPoolPtr('xExN', nameSize); 38 | 39 | CX_RETURN_NTSTATUS_IF( 40 | STATUS_INSUFFICIENT_RESOURCES, 41 | ! m_extensionName); 42 | 43 | RtlCopyMemory(m_extensionName.get(), Extension->Name, nameSize); 44 | 45 | m_extension = *Extension; 46 | m_extension.AssignedOffset = 0; 47 | m_extension.Name = m_extensionName.get(); 48 | 49 | return STATUS_SUCCESS; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /netcx/translator/nxbouncebufferpool.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class NxBounceBufferPool 8 | { 9 | 10 | public: 11 | 12 | NxBounceBufferPool( 13 | NET_RING_COLLECTION const & Rings, 14 | NET_EXTENSION const & VirtualAddressExtension, 15 | NET_EXTENSION const & LogicalAddressExtension, 16 | NET_EXTENSION const & MdlExtension 17 | ); 18 | 19 | ~NxBounceBufferPool( 20 | void 21 | ); 22 | 23 | NTSTATUS 24 | Initialize( 25 | _In_ NET_CLIENT_DISPATCH const &ClientDispatch, 26 | _In_ NET_CLIENT_ADAPTER_DATAPATH_CAPABILITIES &DatapathCapabilities, 27 | _In_ size_t NumberOfBuffers 28 | ); 29 | 30 | bool 31 | BounceNetBuffer( 32 | _In_ NET_BUFFER const &NetBuffer, 33 | _Inout_ NET_PACKET &NetPacket 34 | ); 35 | 36 | void 37 | FreeBounceBuffers( 38 | _Inout_ NET_PACKET &NetPacket 39 | ); 40 | 41 | private: 42 | 43 | NxRingContext 44 | m_fragmentContext; 45 | 46 | NET_EXTENSION const & 47 | m_virtualAddressExtension; 48 | 49 | NET_EXTENSION const & 50 | m_logicalAddressExtension; 51 | 52 | NET_EXTENSION const & 53 | m_mdlExtension; 54 | 55 | NET_CLIENT_BUFFER_POOL m_bufferPool = nullptr; 56 | NET_CLIENT_BUFFER_POOL_DISPATCH const *m_bufferPoolDispatch = nullptr; 57 | 58 | NET_RING_COLLECTION const * m_rings = nullptr; 59 | 60 | size_t m_bufferSize = 0; 61 | size_t m_txPayloadBackfill = 0; 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /netcx/adapter/nxprivateglobals.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | class NxDriver; 6 | enum class MediaExtensionType; 7 | 8 | #define NX_PRIVATE_GLOBALS_SIG 'IxNG' 9 | 10 | constexpr 11 | ULONG64 12 | MAKEVER( 13 | ULONG major, 14 | ULONG minor 15 | ) 16 | { 17 | return (static_cast(major) << 16) | minor; 18 | } 19 | 20 | struct NX_PRIVATE_GLOBALS 21 | { 22 | // 23 | // Equal to GLOBALS_SIG 24 | // 25 | ULONG 26 | Signature; 27 | 28 | // 29 | // Enable runtime verification checks for the client driver. 30 | // 31 | BOOLEAN 32 | CxVerifierOn; 33 | 34 | // 35 | // Public part of the globals 36 | // 37 | NET_DRIVER_GLOBALS 38 | Public; 39 | 40 | // 41 | // Pointer to the NxDriver 42 | // 43 | NxDriver * 44 | NxDriver; 45 | 46 | // 47 | // Pointer to the client driver's WDF globals 48 | // 49 | WDF_DRIVER_GLOBALS * 50 | ClientDriverGlobals; 51 | 52 | MediaExtensionType 53 | ExtensionType; 54 | 55 | // 56 | // Target NetAdapterCx version the client driver is bound to 57 | // 58 | WDF_CLASS_VERSION 59 | ClientVersion; 60 | 61 | bool 62 | IsClientVersionGreaterThanOrEqual( 63 | _In_ WDF_MAJOR_VERSION Major, 64 | _In_ WDF_MINOR_VERSION Minor 65 | ); 66 | }; 67 | 68 | inline 69 | NX_PRIVATE_GLOBALS * 70 | GetPrivateGlobals( 71 | NET_DRIVER_GLOBALS * PublicGlobals 72 | ) 73 | { 74 | return CONTAINING_RECORD( 75 | PublicGlobals, 76 | NX_PRIVATE_GLOBALS, 77 | Public); 78 | } 79 | -------------------------------------------------------------------------------- /netcx/bm/mdl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include "bmprecomp.hpp" 4 | #include "Mdl.hpp" 5 | #include "Mdl.tmh" 6 | 7 | _Use_decl_annotations_ 8 | RtlMdl * 9 | RtlMdl::Make( 10 | void * VirtualAddress, 11 | size_t Length 12 | ) 13 | { 14 | auto mdl = new (VirtualAddress, Length) RtlMdl(); 15 | 16 | if (mdl == nullptr) 17 | { 18 | return nullptr; 19 | } 20 | 21 | MmInitializeMdl( 22 | mdl, 23 | VirtualAddress, 24 | Length); 25 | 26 | return mdl; 27 | } 28 | 29 | _Use_decl_annotations_ 30 | void * 31 | RtlMdl::operator new( 32 | size_t BaseSize, 33 | void * VirtualAddress, 34 | size_t Length 35 | ) 36 | { 37 | auto allocationSize = MmSizeOfMdl( 38 | VirtualAddress, 39 | Length); 40 | 41 | NT_FRE_ASSERT(allocationSize > BaseSize); 42 | 43 | auto storage = ExAllocatePoolWithTag( 44 | NonPagedPoolNx, 45 | allocationSize, 46 | BUFFER_MANAGER_POOL_TAG); 47 | 48 | if (storage == nullptr) 49 | { 50 | return nullptr; 51 | } 52 | 53 | RtlZeroMemory(storage, allocationSize); 54 | return storage; 55 | } 56 | 57 | PFN_NUMBER * 58 | RtlMdl::GetPfnArray( 59 | void 60 | ) 61 | { 62 | return MmGetMdlPfnArray(this); 63 | } 64 | 65 | PFN_NUMBER const * 66 | RtlMdl::GetPfnArray( 67 | void 68 | ) const 69 | { 70 | return MmGetMdlPfnArray(this); 71 | } 72 | 73 | size_t 74 | RtlMdl::GetPfnArrayCount( 75 | void 76 | ) const 77 | { 78 | return ADDRESS_AND_SIZE_TO_SPAN_PAGES( 79 | MmGetMdlVirtualAddress(this), 80 | MmGetMdlByteCount(this)); 81 | } 82 | -------------------------------------------------------------------------------- /netcx/ec/lib/timebudget.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | enum class OutOfBudgetReason 5 | { 6 | None, 7 | SingleDpcWatchdog, 8 | CumulativeDpcWatchdog, 9 | KeShouldYield, 10 | DpcTimeEplapsed 11 | }; 12 | 13 | class TimeBudget 14 | { 15 | public: 16 | 17 | _IRQL_requires_max_(DISPATCH_LEVEL) 18 | TimeBudget( 19 | _In_ ULONG MaxTimeMs, 20 | _In_ bool TryExtendMaxTime, 21 | _In_ UINT32 WatchdogDpcStarvationLimit, 22 | _In_ KIRQL CurrentIrql 23 | ); 24 | 25 | _IRQL_requires_max_(DISPATCH_LEVEL) 26 | bool 27 | IsOutOfBudget( 28 | void 29 | ); 30 | 31 | _IRQL_requires_max_(DISPATCH_LEVEL) 32 | ULONG 33 | TotalTimeInDispatch( 34 | void 35 | ) const; 36 | 37 | _IRQL_requires_max_(DISPATCH_LEVEL) 38 | void 39 | Reset( 40 | void 41 | ); 42 | 43 | private: 44 | 45 | _IRQL_requires_max_(DISPATCH_LEVEL) 46 | bool 47 | IsDpcWatchdogStarving( 48 | void 49 | ); 50 | 51 | private: 52 | 53 | bool const 54 | m_tryExtendMaxTime {}; 55 | 56 | ULONG const 57 | m_timeIncrement {}; 58 | 59 | ULONG const 60 | m_allowedTimeDurationInTicks {}; 61 | 62 | UINT32 63 | m_watchdogDpcStarvationLimit {}; 64 | 65 | LARGE_INTEGER 66 | m_desiredEndTimeTicks {}; 67 | 68 | KIRQL 69 | m_irql {}; 70 | 71 | LARGE_INTEGER 72 | m_startTimeTicks {}; 73 | 74 | ULONG 75 | m_totalTimeInDispatch {}; 76 | 77 | OutOfBudgetReason 78 | m_outOfBudgetReason = OutOfBudgetReason::None; 79 | }; 80 | -------------------------------------------------------------------------------- /rtl/inc/kbitmap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Rtl 6 | { 7 | class KRTL_CLASS KBitmap 8 | { 9 | public: 10 | 11 | KBitmap() = default; 12 | ~KBitmap() = default; 13 | 14 | bool Initialize(size_t numberOfBits) 15 | { 16 | #ifdef _WIN64 17 | size_t bitsPerMachineWord = 64; 18 | #else 19 | size_t bitsPerMachineWord = 32; 20 | #endif 21 | 22 | if (!m_storage.resize((numberOfBits + bitsPerMachineWord - 1) / bitsPerMachineWord)) 23 | return false; 24 | 25 | RtlInitializeBitMapEx(&m_bitmap, &m_storage[0], numberOfBits); 26 | RtlClearAllBitsEx(&m_bitmap); 27 | return true; 28 | } 29 | 30 | NONPAGED 31 | bool TestBit(size_t bitNumber) 32 | { 33 | return RtlCheckBitEx(&m_bitmap, bitNumber); 34 | } 35 | 36 | NONPAGED 37 | void SetBit(size_t bitNumber) 38 | { 39 | RtlSetBitEx(&m_bitmap, bitNumber); 40 | } 41 | 42 | NONPAGED 43 | void ClearBit(size_t bitNumber) 44 | { 45 | RtlClearBitEx(&m_bitmap, bitNumber); 46 | } 47 | 48 | size_t FindSetBits(size_t numberToFind, size_t hintIndex) 49 | { 50 | return RtlFindSetBitsEx(&m_bitmap, numberToFind, hintIndex); 51 | } 52 | 53 | size_t FindSetBitsAndClear(size_t numberToFind, size_t hintIndex) 54 | { 55 | return RtlFindSetBitsAndClearEx(&m_bitmap, numberToFind, hintIndex); 56 | } 57 | 58 | private: 59 | RTL_BITMAP_EX m_bitmap; 60 | Rtl::KArray m_storage; 61 | }; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /netcx/adapter/idle/powerreferenceholder.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class PowerReferenceHolder 8 | { 9 | friend class 10 | IdleStateMachine; 11 | 12 | private: 13 | 14 | enum class Type 15 | { 16 | None, 17 | WDF, 18 | Rundown, 19 | }; 20 | 21 | _IRQL_requires_max_(DISPATCH_LEVEL) 22 | PowerReferenceHolder( 23 | _In_ KRundown & Rundown 24 | ); 25 | 26 | _IRQL_requires_max_(DISPATCH_LEVEL) 27 | PowerReferenceHolder( 28 | _In_ WDFDEVICE Device, 29 | _In_ void const * Tag, 30 | _In_ NTSTATUS NtStatus 31 | ); 32 | 33 | public: 34 | 35 | _IRQL_requires_max_(DISPATCH_LEVEL) 36 | PowerReferenceHolder( 37 | void 38 | ) = default; 39 | 40 | _IRQL_requires_max_(DISPATCH_LEVEL) 41 | PowerReferenceHolder( 42 | PowerReferenceHolder const & 43 | ) = delete; 44 | 45 | _IRQL_requires_max_(DISPATCH_LEVEL) 46 | PowerReferenceHolder( 47 | _Inout_ PowerReferenceHolder && Other 48 | ); 49 | 50 | _IRQL_requires_max_(DISPATCH_LEVEL) 51 | PowerReferenceHolder & 52 | operator=( 53 | PowerReferenceHolder && Other 54 | ); 55 | 56 | _IRQL_requires_max_(DISPATCH_LEVEL) 57 | ~PowerReferenceHolder( 58 | void 59 | ); 60 | 61 | private: 62 | 63 | KRundown * 64 | m_rundown = nullptr; 65 | 66 | WDFDEVICE 67 | m_device = WDF_NO_HANDLE; 68 | 69 | Type 70 | m_type = Type::None; 71 | 72 | void const * 73 | m_tag = nullptr; 74 | 75 | NTSTATUS 76 | m_ntStatus = STATUS_UNSUCCESSFUL; 77 | }; 78 | -------------------------------------------------------------------------------- /netcx/bm/nonpagedallocator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "BmPrecomp.hpp" 3 | 4 | #include 5 | 6 | #include "NonPagedBufferVector.hpp" 7 | #include "NonPagedAllocator.hpp" 8 | #include "NonPagedAllocator.tmh" 9 | 10 | _Use_decl_annotations_ 11 | IBufferVector * 12 | NonPagedAllocator::AllocateVector( 13 | size_t BufferCount, 14 | size_t BufferSize, 15 | size_t BufferOffset, 16 | NODE_REQUIREMENT 17 | ) 18 | { 19 | auto bufferVector = wil::make_unique_nothrow( 20 | BufferCount, 21 | BufferSize, 22 | BufferOffset); 23 | 24 | if (!bufferVector) 25 | { 26 | return nullptr; 27 | } 28 | 29 | if (!bufferVector->m_NonPagedBufferVector.resize(BufferCount)) 30 | { 31 | return nullptr; 32 | } 33 | 34 | for (size_t i = 0; i < BufferCount; i++) 35 | { 36 | auto memory = MakeSizedPoolPtrNP( 37 | BUFFER_MANAGER_POOL_TAG, 38 | BufferSize); 39 | 40 | if (!memory) 41 | { 42 | return nullptr; 43 | } 44 | 45 | auto const mdlSize = MmSizeOfMdl( 46 | memory.get(), 47 | BufferSize); 48 | 49 | auto mdl = MakeSizedPoolPtrNP(BUFFER_MANAGER_POOL_TAG, mdlSize); 50 | 51 | if (!mdl) 52 | { 53 | return nullptr; 54 | } 55 | 56 | MmInitializeMdl(mdl.get(), memory.get(), BufferSize); 57 | MmBuildMdlForNonPagedPool(mdl.get()); 58 | 59 | bufferVector->m_NonPagedBufferVector[i].VirtualAddress = memory.release(); 60 | bufferVector->m_NonPagedBufferVector[i].Mdl = mdl.release(); 61 | } 62 | 63 | return bufferVector.release(); 64 | } 65 | -------------------------------------------------------------------------------- /netcx/adapter/nxadaptercollection.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include "Nx.hpp" 4 | 5 | #include "NxAdapterCollection.hpp" 6 | #include "NxAdapter.hpp" 7 | 8 | #include "NxAdapterCollection.tmh" 9 | 10 | void 11 | NxAdapterCollection::GetTriageInfo( 12 | void 13 | ) 14 | { 15 | g_NetAdapterCxTriageBlock.NxAdapterCollectionCountOffset = FIELD_OFFSET(NxAdapterCollection, m_Count); 16 | } 17 | 18 | _Use_decl_annotations_ 19 | unique_miniport_reference 20 | NxAdapterCollection::FindAndReferenceMiniportByInstanceName( 21 | UNICODE_STRING const * InstanceName 22 | ) const 23 | { 24 | KLockThisShared lock(m_ListLock); 25 | 26 | for (LIST_ENTRY *link = m_ListHead.Flink; 27 | link != &m_ListHead; 28 | link = link->Flink) 29 | { 30 | auto nxAdapter = CONTAINING_RECORD(link, NxAdapter, m_linkage); 31 | 32 | if (RtlEqualUnicodeString(&nxAdapter->m_instanceName, InstanceName, TRUE)) 33 | { 34 | return nxAdapter->GetMiniportReference(); 35 | } 36 | } 37 | 38 | return nullptr; 39 | } 40 | 41 | _Use_decl_annotations_ 42 | NxAdapter * 43 | NxAdapterCollection::FindAndReferenceAdapterByBaseName( 44 | UNICODE_STRING const * BaseName 45 | ) const 46 | { 47 | KLockThisShared lock(m_ListLock); 48 | 49 | for (LIST_ENTRY *link = m_ListHead.Flink; 50 | link != &m_ListHead; 51 | link = link->Flink) 52 | { 53 | auto nxAdapter = CONTAINING_RECORD(link, NxAdapter, m_linkage); 54 | 55 | if (RtlEqualUnicodeString(&nxAdapter->m_baseName, BaseName, TRUE)) 56 | { 57 | return NdisWdfMiniportTryReference(nxAdapter->GetNdisHandle()) ? nxAdapter : nullptr; 58 | } 59 | } 60 | 61 | return nullptr; 62 | } 63 | -------------------------------------------------------------------------------- /netcx/ec/lib/executioncontextstatistics.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | #include 4 | #include "HistogramHub.h" 5 | #include "ExecutionContextStatistics.hpp" 6 | 7 | static Statistics::Hub *ecStatistics = nullptr; 8 | 9 | static RTL_RUN_ONCE ecRunOnce = RTL_RUN_ONCE_INIT; 10 | static PAGEDX RTL_RUN_ONCE_INIT_FN InitializeEcStatOnce; 11 | 12 | PAGED 13 | NTSTATUS 14 | InitializeGlobalEcStatistic() 15 | { 16 | PAGED_CODE(); 17 | // assuming creation can only happen once, and is never concurrent with getGlobalEcStatistics(); 18 | auto ntStatus = RtlRunOnceExecuteOnce( 19 | &ecRunOnce, 20 | InitializeEcStatOnce, 21 | nullptr, 22 | nullptr); 23 | 24 | if (STATUS_SUCCESS != ntStatus) 25 | return ntStatus; 26 | 27 | return STATUS_SUCCESS; 28 | } 29 | 30 | PAGEDX 31 | static 32 | ULONG 33 | NTAPI 34 | InitializeEcStatOnce( 35 | PRTL_RUN_ONCE RunOnce, 36 | PVOID Parameter, 37 | PVOID *Context) 38 | { 39 | UNREFERENCED_PARAMETER((RunOnce, Parameter, Context)); 40 | NT_FRE_ASSERT(ecStatistics == nullptr); 41 | ecStatistics = new(std::nothrow) Statistics::Hub {}; 42 | if (!ecStatistics) 43 | { 44 | return FALSE; 45 | } 46 | return TRUE; 47 | } 48 | 49 | NONPAGED 50 | Statistics::Hub& 51 | GetGlobalEcStatistics() 52 | { 53 | NT_FRE_ASSERT(ecStatistics != nullptr); 54 | return *ecStatistics; 55 | } 56 | 57 | PAGED 58 | void 59 | FreeGlobalEcStatistics() 60 | { 61 | if (ecStatistics == nullptr) 62 | { 63 | return; 64 | } 65 | 66 | ecStatistics->~Hub(); 67 | ExFreePool(ecStatistics); 68 | ecStatistics = nullptr; 69 | ecRunOnce = RTL_RUN_ONCE_INIT; 70 | } 71 | -------------------------------------------------------------------------------- /netcx/translator/checksum/checksum.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | DECLARE_HANDLE( CHECKSUMLIB_SL_HANDLE ); 8 | DECLARE_HANDLE( CHECKSUMLIB_BL_HANDLE ); 9 | 10 | struct _NET_BUFFER; 11 | typedef struct _NET_BUFFER NET_BUFFER; 12 | 13 | struct _NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO; 14 | typedef struct _NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO; 15 | 16 | class Checksum 17 | { 18 | 19 | public: 20 | 21 | _IRQL_requires_(PASSIVE_LEVEL) 22 | ~Checksum( 23 | void 24 | ); 25 | 26 | _IRQL_requires_(PASSIVE_LEVEL) 27 | NTSTATUS 28 | Initialize( 29 | void 30 | ); 31 | 32 | _IRQL_requires_max_(DISPATCH_LEVEL) 33 | bool 34 | IsIpv4ChecksumValid( 35 | _In_reads_(Length) UINT8 const * Buffer, 36 | _In_ size_t Length 37 | ); 38 | 39 | _IRQL_requires_max_(DISPATCH_LEVEL) 40 | bool 41 | IsUdpChecksumValid( 42 | _In_reads_(Length) UINT8 const * Buffer, 43 | _In_ size_t Length 44 | ); 45 | 46 | _IRQL_requires_max_(DISPATCH_LEVEL) 47 | bool 48 | IsTcpChecksumValid( 49 | _In_reads_(Length) UINT8 const * Buffer, 50 | _In_ size_t Length 51 | ); 52 | 53 | _IRQL_requires_max_(DISPATCH_LEVEL) 54 | NTSTATUS 55 | CalculateChecksum( 56 | _Inout_ NET_BUFFER * Buffer, 57 | _In_ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO const & ChecksumInfo, 58 | _In_ NET_PACKET_LAYOUT const & PacketLayout 59 | ); 60 | 61 | private: 62 | 63 | CHECKSUMLIB_BL_HANDLE 64 | m_batchingLibContext = nullptr; 65 | 66 | CHECKSUMLIB_SL_HANDLE 67 | m_segLibContext = nullptr; 68 | 69 | }; 70 | -------------------------------------------------------------------------------- /netcx/translator/nxextensions.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #pragma warning(push) 8 | #pragma warning(default:4820) // warn if the compiler inserted padding 9 | 10 | union TxExtensions { 11 | 12 | // order of structure members shall match TxQueueExtensions 13 | struct { 14 | 15 | NET_EXTENSION 16 | Checksum; 17 | 18 | NET_EXTENSION 19 | Gso; 20 | 21 | NET_EXTENSION 22 | WifiExemptionAction; 23 | 24 | NET_EXTENSION 25 | LogicalAddress; 26 | 27 | NET_EXTENSION 28 | VirtualAddress; 29 | 30 | NET_EXTENSION 31 | Mdl; 32 | 33 | NET_EXTENSION 34 | Ieee8021q; 35 | 36 | } Extension; 37 | 38 | NET_EXTENSION 39 | Extensions[sizeof(Extension) / sizeof(NET_EXTENSION)]; 40 | 41 | }; 42 | 43 | union RxExtensions { 44 | 45 | // order of structure members shall match RxQueueExtensions 46 | struct { 47 | 48 | NET_EXTENSION 49 | Checksum; 50 | 51 | NET_EXTENSION 52 | Rsc; 53 | 54 | NET_EXTENSION 55 | RscTimestamp; 56 | 57 | NET_EXTENSION 58 | DataBuffer; 59 | 60 | NET_EXTENSION 61 | LogicalAddress; 62 | 63 | NET_EXTENSION 64 | VirtualAddress; 65 | 66 | NET_EXTENSION 67 | ReturnContext; 68 | 69 | NET_EXTENSION 70 | Ieee8021q; 71 | 72 | NET_EXTENSION 73 | Hash; 74 | } Extension; 75 | 76 | NET_EXTENSION 77 | Extensions[sizeof(Extension) / sizeof(NET_EXTENSION)]; 78 | 79 | }; 80 | 81 | #pragma warning(pop) 82 | 83 | -------------------------------------------------------------------------------- /netcx/translator/nxringbuffer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | The NxRingBuffer wraps a NET_RING, providing simple accessor methods 8 | for inserting and removing items into the ring buffer. 9 | 10 | --*/ 11 | 12 | #include "NxXlatPrecomp.hpp" 13 | #include "NxXlatCommon.hpp" 14 | #include "NxRingBuffer.tmh" 15 | #include "NxRingBuffer.hpp" 16 | 17 | #include "NxRingBufferRange.hpp" 18 | 19 | PAGED 20 | NxRingBuffer::~NxRingBuffer() 21 | { 22 | } 23 | 24 | PAGED 25 | NTSTATUS 26 | NxRingBuffer::Initialize( 27 | NET_RING * RingBuffer 28 | ) 29 | { 30 | m_rb = RingBuffer; 31 | 32 | return STATUS_SUCCESS; 33 | } 34 | 35 | _IRQL_requires_max_(DISPATCH_LEVEL) 36 | NET_PACKET * 37 | NxRingBuffer::GetNextPacketToGiveToNic() 38 | { 39 | // Can't give the last packet to the NIC. 40 | if (AvailablePackets().Count() == 0) 41 | return nullptr; 42 | 43 | return NetRingGetPacketAtIndex(m_rb, m_rb->EndIndex); 44 | } 45 | 46 | _IRQL_requires_max_(DISPATCH_LEVEL) 47 | void 48 | NxRingBuffer::GiveNextPacketToNic() 49 | { 50 | WIN_ASSERT(AvailablePackets().Count() != 0); 51 | 52 | m_rb->EndIndex = NetRingIncrementIndex(m_rb, m_rb->EndIndex); 53 | } 54 | 55 | _IRQL_requires_max_(DISPATCH_LEVEL) 56 | NET_PACKET * 57 | NxRingBuffer::TakeNextPacketFromNic() 58 | { 59 | auto &index = GetNextOSIndex(); 60 | 61 | // We've processed all the packets. 62 | if (index == m_rb->BeginIndex) 63 | return nullptr; 64 | 65 | auto packet = NetRingGetPacketAtIndex(m_rb, index); 66 | index = NetRingIncrementIndex(m_rb, index); 67 | 68 | return packet; 69 | } 70 | 71 | UINT32 72 | NxRingBuffer::Count() const 73 | { 74 | return Get()->NumberOfElements; 75 | } 76 | -------------------------------------------------------------------------------- /netcx/translator/coalescing/coalescing.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #ifdef _KERNEL_MODE 8 | 9 | #include 10 | 11 | #else 12 | 13 | using RSCLIB_SERIAL_COALESCING_CONTEXT = HANDLE; 14 | using RSCLIB_STATS = HANDLE; 15 | 16 | #endif 17 | 18 | struct _NET_BUFFER_LIST; 19 | typedef struct _NET_BUFFER_LIST NET_BUFFER_LIST; 20 | 21 | 22 | class ReceiveSegmentCoalescing 23 | { 24 | 25 | public: 26 | 27 | _IRQL_requires_(PASSIVE_LEVEL) 28 | void 29 | Initialize( 30 | void 31 | ); 32 | 33 | _IRQL_requires_max_(DISPATCH_LEVEL) 34 | void 35 | PerformReceiveSegmentCoalescing( 36 | _Inout_ NET_BUFFER_LIST * & NblChain, 37 | _In_ bool Ipv4HardwareCapabilities, 38 | _In_ bool Ipv6HardwareCapabilities, 39 | _Out_ NET_BUFFER_LIST * & OutputNblChainTail, 40 | _Out_ ULONG & NumberOfNbls 41 | ); 42 | 43 | _IRQL_requires_max_(DISPATCH_LEVEL) 44 | void 45 | PerformReceiveSegmentUncoalescing( 46 | _Inout_ NET_BUFFER_LIST * & NblChain, 47 | _Out_ NET_BUFFER_LIST * & OutputNblChainTail, 48 | _Out_ ULONG & NumberOfNbls 49 | ); 50 | 51 | _IRQL_requires_max_(DISPATCH_LEVEL) 52 | USHORT 53 | GetNblsCoalescedCount( 54 | void 55 | ) const; 56 | 57 | _IRQL_requires_max_(DISPATCH_LEVEL) 58 | USHORT 59 | GetScusGeneratedCount( 60 | void 61 | ) const; 62 | 63 | _IRQL_requires_max_(DISPATCH_LEVEL) 64 | ULONG 65 | GetBytesCoalescedCount( 66 | void 67 | ) const; 68 | 69 | private: 70 | 71 | RSCLIB_SERIAL_COALESCING_CONTEXT 72 | m_rsclibContext = {}; 73 | 74 | RSCLIB_STATS 75 | m_rscStats = {}; 76 | 77 | }; 78 | -------------------------------------------------------------------------------- /netcx/adapter/monitor/nxpacketmonitor.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | class NxAdapter; 10 | 11 | class NxPacketMonitor 12 | { 13 | 14 | public: 15 | 16 | _IRQL_requires_max_(PASSIVE_LEVEL) 17 | NxPacketMonitor( 18 | NxAdapter & Adapter 19 | ); 20 | 21 | _IRQL_requires_max_(PASSIVE_LEVEL) 22 | ~NxPacketMonitor( 23 | void 24 | ); 25 | 26 | _IRQL_requires_max_(PASSIVE_LEVEL) 27 | static 28 | void 29 | EnumerateAndRegisterAdapters( 30 | void 31 | ); 32 | 33 | _IRQL_requires_max_(PASSIVE_LEVEL) 34 | static 35 | void 36 | EnumerateAndUnRegisterAdapters( 37 | void 38 | ); 39 | 40 | _IRQL_requires_max_(PASSIVE_LEVEL) 41 | NTSTATUS 42 | RegisterAdapter( 43 | void 44 | ); 45 | 46 | _IRQL_requires_max_(PASSIVE_LEVEL) 47 | void 48 | UnregisterAdapter( 49 | void 50 | ); 51 | 52 | _IRQL_requires_max_(PASSIVE_LEVEL) 53 | PKTMON_EDGE_CONTEXT const & 54 | GetLowerEdgeContext( 55 | void 56 | ) const; 57 | 58 | _IRQL_requires_max_(PASSIVE_LEVEL) 59 | PKTMON_COMPONENT_CONTEXT const & 60 | GetComponentContext( 61 | void 62 | ) const; 63 | 64 | public: 65 | 66 | KPushLock 67 | m_registrationLock; 68 | 69 | private: 70 | 71 | NxAdapter & 72 | m_adapter; 73 | 74 | _Guarded_by_(m_registrationLock) 75 | PKTMON_COMPONENT_CONTEXT 76 | m_clientComponentContext = {}; 77 | 78 | _Guarded_by_(m_registrationLock) 79 | bool 80 | m_isRegistered = false; 81 | 82 | PKTMON_EDGE_CONTEXT 83 | m_clientLowerEdgeContext = {}; 84 | }; 85 | -------------------------------------------------------------------------------- /netcx/adapter/idle/idlestatemachine.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include "PowerReferenceHolder.hpp" 8 | 9 | class IdleStateMachine 10 | { 11 | public: 12 | 13 | IdleStateMachine( 14 | IdleStateMachine const & 15 | ) = delete; 16 | 17 | IdleStateMachine( 18 | IdleStateMachine && 19 | ) = delete; 20 | 21 | _IRQL_requires_(PASSIVE_LEVEL) 22 | IdleStateMachine( 23 | _In_ WDFDEVICE const * Device 24 | ); 25 | 26 | _IRQL_requires_(PASSIVE_LEVEL) 27 | void 28 | D0Entry( 29 | void 30 | ); 31 | 32 | _IRQL_requires_(PASSIVE_LEVEL) 33 | void 34 | HardwareEnabled( 35 | void 36 | ); 37 | 38 | _IRQL_requires_(PASSIVE_LEVEL) 39 | void 40 | SelfManagedIoStart( 41 | void 42 | ); 43 | 44 | _IRQL_requires_(PASSIVE_LEVEL) 45 | void 46 | SelfManagedIoSuspend( 47 | void 48 | ); 49 | 50 | _IRQL_requires_(PASSIVE_LEVEL) 51 | void 52 | HardwareDisabled( 53 | _In_ bool TargetStateIsD3Final 54 | ); 55 | 56 | _IRQL_requires_(PASSIVE_LEVEL) 57 | void 58 | D0Exit( 59 | void 60 | ); 61 | 62 | _IRQL_requires_max_(DISPATCH_LEVEL) 63 | PowerReferenceHolder 64 | StopIdle( 65 | _In_ bool WaitForD0, 66 | _In_ void const * Tag 67 | ); 68 | 69 | private: 70 | 71 | WDFDEVICE const * const 72 | m_device; 73 | 74 | KRundown 75 | m_dxRundown; 76 | 77 | KSpinLock 78 | m_lock; 79 | 80 | _Guarded_by_(m_lock) 81 | KWaitEvent 82 | m_hardwareEnabled; 83 | 84 | _Guarded_by_(m_lock) 85 | ULONG_PTR 86 | m_powerUpThread = 0; 87 | }; 88 | -------------------------------------------------------------------------------- /netcx/statistics/histogramtimer.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace Statistics 8 | { 9 | class Histogram; 10 | 11 | struct PreciseStopwatch 12 | { 13 | using Type = KStopwatch; 14 | }; 15 | 16 | struct FastStopwatch 17 | { 18 | using Type = KTickCounterStopwatch; 19 | }; 20 | 21 | template 22 | class Timer 23 | { 24 | public: 25 | NONPAGED 26 | Timer( 27 | _In_ Histogram *histogram, 28 | bool measureTime = true 29 | ) 30 | : m_timeHistogram(histogram) 31 | { 32 | if (measureTime) 33 | { 34 | Start(); 35 | } 36 | } 37 | 38 | NONPAGED 39 | ~Timer() 40 | { 41 | Stop(); 42 | } 43 | 44 | NONPAGED 45 | void 46 | Start( 47 | void 48 | ) 49 | { 50 | m_started = true; 51 | m_stopwatch.Start(); 52 | } 53 | 54 | NONPAGED 55 | ULONG64 56 | Stop( 57 | void 58 | ) 59 | { 60 | if (!m_started) 61 | { 62 | return 0; 63 | } 64 | 65 | auto value = m_stopwatch.Stop(); 66 | if (m_timeHistogram) 67 | { 68 | m_timeHistogram->AddValue(value); 69 | } 70 | return value; 71 | } 72 | 73 | private: 74 | typename Stopwatch::Type 75 | m_stopwatch {}; 76 | 77 | bool 78 | m_started = false; 79 | 80 | Histogram * 81 | m_timeHistogram {}; 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /netcx/ec/driver/trace.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | // 5 | // Tracing Definitions: 6 | // 7 | // Control GUID: 8 | // {94C9795A-DF87-4B51-8DC4-21E82539F158} 9 | // 10 | 11 | #define WPP_CONTROL_GUIDS \ 12 | WPP_DEFINE_CONTROL_GUID( \ 13 | ECTraceGuid, \ 14 | (94c9795a,df87,4b51,8dc4,21e82539f158), \ 15 | WPP_DEFINE_BIT(FLAG_GENERAL) \ 16 | ) 17 | 18 | #define MACRO_START do { 19 | #define MACRO_END } while(0) 20 | 21 | #define WPP_RECORDER_LEVEL_FLAGS_ARGS(level, flags) \ 22 | WPP_CONTROL(WPP_BIT_ ## flags).AutoLogContext, 0, WPP_BIT_ ## flags 23 | #define WPP_RECORDER_LEVEL_FLAGS_FILTER(level, flags) \ 24 | (level < TRACE_LEVEL_VERBOSE || WPP_CONTROL(WPP_BIT_ ## flags).AutoLogVerboseEnabled) 25 | 26 | // WPP Macros: RETURN_IF_NOT_SUCCESS 27 | // 28 | // begin_wpp config 29 | // FUNC RETURN_IF_NOT_SUCCESS{COMPNAME=FLAG_GENERAL,LEVEL=TRACE_LEVEL_ERROR}(NTEXPR); 30 | // USESUFFIX (RETURN_IF_NOT_SUCCESS, " [status=%!STATUS!]", nt__wpp); 31 | // end_wpp 32 | 33 | #define WPP_COMPNAME_LEVEL_NTEXPR_PRE(comp, level, ntexpr) MACRO_START NTSTATUS nt__wpp = (ntexpr); if (STATUS_SUCCESS != nt__wpp) { 34 | #define WPP_COMPNAME_LEVEL_NTEXPR_POST(comp, level, ntexpr); NT_FRE_ASSERTMSG("Success code other than STATUS_SUCCESS will be ignored", NT_ERROR(nt__wpp)); return nt__wpp; } MACRO_END 35 | #define WPP_RECORDER_COMPNAME_LEVEL_NTEXPR_FILTER(comp, level, ntexpr) WPP_RECORDER_LEVEL_FLAGS_FILTER(level, comp) 36 | #define WPP_RECORDER_COMPNAME_LEVEL_NTEXPR_ARGS(comp, level, ntexpr) WPP_RECORDER_LEVEL_FLAGS_ARGS(level, comp) 37 | 38 | // 39 | // This can be made reg. configurable. 40 | // 41 | #define DEFAULT_WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE) 42 | #define DEFAULT_WPP_ERROR_PARTITION_SIZE (DEFAULT_WPP_TOTAL_BUFFER_SIZE/2) 43 | -------------------------------------------------------------------------------- /netcx/adapter/types/nxadaptertypes.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "NxPrivateGlobals.hpp" 5 | 6 | class NxAdapterLinkLayerCapabilities 7 | { 8 | public: 9 | 10 | // Fields from version 2.0 11 | ULONG 12 | Size = {}; 13 | 14 | ULONG64 15 | MaxTxLinkSpeed = {}; 16 | 17 | ULONG64 18 | MaxRxLinkSpeed = {}; 19 | 20 | NxAdapterLinkLayerCapabilities( 21 | void 22 | ) = default; 23 | 24 | NxAdapterLinkLayerCapabilities( 25 | _In_ NX_PRIVATE_GLOBALS const & ClientGlobals, 26 | _In_ NET_ADAPTER_LINK_LAYER_CAPABILITIES const & Capabilities 27 | ); 28 | 29 | explicit 30 | operator bool( 31 | void 32 | ) const; 33 | 34 | void 35 | Assign( 36 | _In_ NX_PRIVATE_GLOBALS const & ClientGlobals, 37 | _In_ NET_ADAPTER_LINK_LAYER_CAPABILITIES const & Capabilities 38 | ); 39 | 40 | }; 41 | 42 | class NxAdapterReceiveFilterCapabilities 43 | { 44 | public: 45 | 46 | // Fields from version 2.1 47 | ULONG 48 | Size = {}; 49 | 50 | NET_PACKET_FILTER_FLAGS 51 | SupportedPacketFilters = {}; 52 | 53 | SIZE_T 54 | MaximumMulticastAddresses = {}; 55 | 56 | PFN_NET_ADAPTER_SET_RECEIVE_FILTER 57 | EvtSetReceiveFilter = {}; 58 | 59 | NxAdapterReceiveFilterCapabilities( 60 | void 61 | ) = default; 62 | 63 | NxAdapterReceiveFilterCapabilities( 64 | _In_ NX_PRIVATE_GLOBALS const & ClientGlobals, 65 | _In_ NET_ADAPTER_RECEIVE_FILTER_CAPABILITIES const & Capabilities 66 | ); 67 | 68 | explicit 69 | operator bool( 70 | void 71 | ) const; 72 | 73 | void 74 | Assign( 75 | _In_ NX_PRIVATE_GLOBALS const & ClientGlobals, 76 | _In_ NET_ADAPTER_RECEIVE_FILTER_CAPABILITIES const & Capabilities 77 | ); 78 | 79 | }; 80 | 81 | -------------------------------------------------------------------------------- /netcx/adapter/nxqueueverifier.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | class NxQueueVerifier 5 | { 6 | public: 7 | 8 | NxQueueVerifier( 9 | _In_ NX_PRIVATE_GLOBALS const & PrivateGlobals, 10 | _In_ WDFOBJECT ParentObject, 11 | _In_ NETPACKETQUEUE Queue 12 | ); 13 | 14 | NTSTATUS 15 | Initialize( 16 | _In_ NET_RING_COLLECTION const * Rings 17 | ); 18 | 19 | void 20 | PreStart( 21 | void 22 | ); 23 | 24 | void 25 | PreAdvance( 26 | _In_ NET_RING_COLLECTION const * Rings 27 | ); 28 | 29 | void 30 | PostAdvance( 31 | _In_ NET_RING_COLLECTION const * Rings 32 | ) const; 33 | 34 | private: 35 | 36 | NTSTATUS 37 | CreateRing( 38 | _In_ size_t ElementSize, 39 | _In_ UINT32 ElementCount, 40 | _In_ NET_RING_TYPE RingType 41 | ); 42 | 43 | private: 44 | 45 | NxAdapter * 46 | m_adapter = nullptr; 47 | 48 | NxQueue * 49 | m_queue = nullptr; 50 | 51 | NX_PRIVATE_GLOBALS const & 52 | m_privateGlobals; 53 | 54 | UINT32 55 | m_verifiedPacketIndex = 0; 56 | 57 | UINT32 58 | m_verifiedFragmentIndex = 0; 59 | 60 | UINT32 61 | m_verifiedDataBufferIndex = 0; 62 | 63 | KPoolPtr 64 | m_verifiedRings[NetRingTypeDataBuffer + 1]; 65 | 66 | NET_RING_COLLECTION 67 | m_verifiedRingCollection; 68 | 69 | UINT8 70 | m_toggle = 0; 71 | 72 | KIRQL 73 | m_irql = PASSIVE_LEVEL; 74 | }; 75 | 76 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NxQueueVerifier, GetNxQueueVerifierFromHandle); 77 | 78 | NTSTATUS 79 | PacketQueueVerifierCreate( 80 | _In_ NX_PRIVATE_GLOBALS const & PrivateGlobals, 81 | _In_ WDFOBJECT ParentObject, 82 | _In_ NETPACKETQUEUE PacketQueue, 83 | _Out_ NxQueueVerifier ** QueueVerifier 84 | ); 85 | -------------------------------------------------------------------------------- /netcx/translator/txscaling.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "NxTxXlat.hpp" 9 | #include "TxPeerAddressDemux.hpp" 10 | #include "TxUserPriorityDemux.hpp" 11 | #include "TxWmmInfoDemux.hpp" 12 | 13 | class NxTranslationApp; 14 | 15 | class TxScaling 16 | : public INxNblTx 17 | , public NxNonpagedAllocation<'TxtN'> 18 | { 19 | 20 | public: 21 | 22 | _IRQL_requires_(PASSIVE_LEVEL) 23 | TxScaling( 24 | NxTranslationApp & App, 25 | INxNblDispatcher * NblDispatcher, 26 | Rtl::KArray, NonPagedPoolNx> const & Queues 27 | ) noexcept; 28 | 29 | _IRQL_requires_(PASSIVE_LEVEL) 30 | NTSTATUS 31 | Initialize( 32 | NET_CLIENT_ADAPTER_TX_DEMUX_CONFIGURATION const & Configuration 33 | ); 34 | 35 | _IRQL_requires_(PASSIVE_LEVEL) 36 | size_t 37 | GetNumberOfQueues( 38 | void 39 | ) const; 40 | 41 | _IRQL_requires_(PASSIVE_LEVEL) 42 | void 43 | GenerateDemuxProperties( 44 | _In_ NET_BUFFER_LIST const * NetBufferList, 45 | _In_ Rtl::KArray & Properties 46 | ) const; 47 | 48 | _IRQL_requires_max_(DISPATCH_LEVEL) 49 | void 50 | SendNetBufferLists( 51 | _In_ NET_BUFFER_LIST * Nbl, 52 | _In_ ULONG PortNumber, 53 | _In_ ULONG NblCount, 54 | _In_ ULONG SendFlags 55 | ) override; 56 | 57 | private: 58 | 59 | NxTranslationApp & 60 | m_app; 61 | 62 | INxNblDispatcher * 63 | m_nblDispatcher = nullptr; 64 | 65 | size_t 66 | m_numberOfQueues = 1U; 67 | 68 | Rtl::KArray, NonPagedPoolNx> const & 69 | m_queues; 70 | 71 | Rtl::KArray, NonPagedPoolNx> 72 | m_demux; 73 | }; 74 | 75 | -------------------------------------------------------------------------------- /rtl/inc/kunits.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | Copyright (c) Microsoft Corporation 3 | 4 | Module Name: 5 | 6 | KUnits.h 7 | 8 | Abstract: 9 | 10 | Implements simple user-defined literals for bits, bytes, etc. 11 | 12 | Environment: 13 | 14 | Kernel mode or usermode unittest 15 | 16 | --*/ 17 | 18 | #pragma once 19 | 20 | namespace KUnits 21 | { 22 | namespace Bytes 23 | { 24 | 25 | constexpr unsigned long long operator "" _gigabytes(unsigned long long gb) 26 | { 27 | return gb * 1024 * 1024 * 1024; 28 | } 29 | 30 | constexpr unsigned long long operator "" _gigabyte(unsigned long long gb) 31 | { 32 | return gb * 1024 * 1024 * 1024; 33 | } 34 | 35 | constexpr unsigned long long operator "" _megabytes(unsigned long long mb) 36 | { 37 | return mb * 1024 * 1024; 38 | } 39 | 40 | constexpr unsigned long long operator "" _megabyte(unsigned long long mb) 41 | { 42 | return mb * 1024 * 1024; 43 | } 44 | 45 | constexpr unsigned long long operator "" _kilobytes(unsigned long long kb) 46 | { 47 | return kb * 1024; 48 | } 49 | 50 | constexpr unsigned long long operator "" _kilobyte(unsigned long long kb) 51 | { 52 | return kb * 1024; 53 | } 54 | 55 | constexpr unsigned long long operator "" _bytes(unsigned long long b) 56 | { 57 | return b; 58 | } 59 | 60 | constexpr unsigned long long operator "" _byte(unsigned long long b) 61 | { 62 | return b; 63 | } 64 | 65 | } 66 | 67 | namespace BitsPerSecond 68 | { 69 | 70 | constexpr unsigned long long operator "" _gbps(unsigned long long gb) 71 | { 72 | return gb * 1024 * 1024 * 1024; 73 | } 74 | 75 | constexpr unsigned long long operator "" _mbps(unsigned long long mb) 76 | { 77 | return mb * 1024 * 1024; 78 | } 79 | 80 | constexpr unsigned long long operator "" _kbps(unsigned long long kb) 81 | { 82 | return kb * 1024; 83 | } 84 | 85 | constexpr unsigned long long operator "" _bps(unsigned long long b) 86 | { 87 | return b; 88 | } 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /rtl/inc/kintrusivelist.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | template 5 | class KIntrusiveListIterator 6 | { 7 | public: 8 | using value_type = TElement; 9 | using pointer = value_type *; 10 | 11 | private: 12 | pointer m_pElement; 13 | 14 | pointer GetNext() 15 | { 16 | return FAdvance()(m_pElement); 17 | } 18 | 19 | public: 20 | 21 | KIntrusiveListIterator() : m_pElement(nullptr) {} 22 | KIntrusiveListIterator(pointer pElement) : m_pElement(pElement) {} 23 | 24 | KIntrusiveListIterator & operator++() 25 | { 26 | m_pElement = GetNext(); 27 | return *this; 28 | } 29 | 30 | KIntrusiveListIterator operator++(int) 31 | { 32 | auto copy = *this; 33 | ++*this; 34 | return copy; 35 | } 36 | 37 | value_type & operator*() 38 | { 39 | return *m_pElement; 40 | } 41 | 42 | value_type const & operator*() const 43 | { 44 | return *m_pElement; 45 | } 46 | 47 | pointer operator->() const 48 | { 49 | return m_pElement; 50 | } 51 | 52 | bool operator==(KIntrusiveListIterator const &other) const 53 | { 54 | return m_pElement == other.m_pElement; 55 | } 56 | 57 | bool operator!=(KIntrusiveListIterator const &other) const 58 | { 59 | return m_pElement != other.m_pElement; 60 | } 61 | }; 62 | 63 | #define MAKE_INTRUSIVE_LIST_ENUMERABLE_FUNCTOR(Type, Functor) \ 64 | namespace std \ 65 | { \ 66 | inline auto begin(Type *pHead) { return KIntrusiveListIterator(pHead); } \ 67 | inline auto end(Type *) { return KIntrusiveListIterator(); } \ 68 | } 69 | 70 | #define MAKE_INTRUSIVE_LIST_ENUMERABLE(Type, Field) \ 71 | struct _K_ ## Type ## _Advance \ 72 | { \ 73 | Type *operator()(Type *current) const \ 74 | { \ 75 | return current->Field; \ 76 | } \ 77 | }; \ 78 | \ 79 | MAKE_INTRUSIVE_LIST_ENUMERABLE_FUNCTOR(Type, _K_ ## Type ## _Advance) 80 | -------------------------------------------------------------------------------- /netcx/ec/lib/thread.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | #ifdef _KERNEL_MODE 8 | 9 | using EC_START_ROUTINE = KSTART_ROUTINE; 10 | using EC_RETURN = VOID; 11 | using EC_THREAD = PKTHREAD; 12 | static const EC_THREAD EC_THREAD_INVALID = nullptr; 13 | using EC_THREAD_PRIORITY = LONG; 14 | #define EC_INVALID_THREAD_PRIORITY MAXLONG 15 | 16 | using unique_zw_handle = wil::unique_any; 17 | using unique_pkthread = wil::unique_any; 18 | 19 | struct unique_thread 20 | { 21 | unique_zw_handle 22 | NtHandle; 23 | 24 | unique_pkthread 25 | ObHandle; 26 | 27 | operator bool( 28 | void 29 | ) const; 30 | 31 | void reset( 32 | ); 33 | }; 34 | 35 | #else 36 | using EC_START_ROUTINE = wistd::remove_pointer::type; 37 | using EC_RETURN = DWORD; 38 | using EC_THREAD = DWORD; 39 | static const EC_THREAD EC_THREAD_INVALID = 0; 40 | using EC_THREAD_PRIORITY = int; 41 | #define EC_INVALID_THREAD_PRIORITY THREAD_PRIORITY_ERROR_RETURN 42 | 43 | using unique_thread = wil::unique_handle; 44 | #endif 45 | 46 | EC_THREAD 47 | EcGetCurrentThread( 48 | void 49 | ); 50 | 51 | NTSTATUS 52 | EcThreadCreate( 53 | _In_ EC_START_ROUTINE StartRoutine, 54 | _In_opt_ void * Context, 55 | _Out_ unique_thread & Thread 56 | ); 57 | 58 | void 59 | EcThreadSetDescription( 60 | _In_ unique_thread & Thread, 61 | _In_ UNICODE_STRING const & Description 62 | ); 63 | 64 | void 65 | EcThreadSetPriority( 66 | _In_ unique_thread & Thread, 67 | _In_ EC_THREAD_PRIORITY Priority 68 | ); 69 | 70 | EC_THREAD_PRIORITY 71 | EcThreadGetPriority( 72 | _In_ unique_thread & Thread 73 | ); 74 | 75 | void 76 | EcThreadSetAffinity( 77 | _In_ PGROUP_AFFINITY GroupAffinity, 78 | _Out_opt_ PGROUP_AFFINITY PreviousAffinity 79 | ); 80 | 81 | void 82 | EcThreadWaitForTermination( 83 | _In_ unique_thread & Thread 84 | ); 85 | -------------------------------------------------------------------------------- /netcx/adapter/powerpolicy/nxpowerlist.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "NxWakeSource.hpp" 5 | #include "NxPowerOffload.hpp" 6 | 7 | #define NX_POWER_OFFLOAD_LIST_SIGNATURE 'LPxN' 8 | #define NX_WAKE_SOURCE_LIST_SIGNATURE 'SWxN' 9 | 10 | class NxPowerList 11 | { 12 | public: 13 | 14 | ULONG const 15 | Signature; 16 | 17 | size_t 18 | GetCount( 19 | void 20 | ) const; 21 | 22 | void 23 | PushEntry( 24 | _In_ NxPowerEntry * Entry 25 | ); 26 | 27 | protected: 28 | 29 | NxPowerList( 30 | _In_ ULONG Signature 31 | ); 32 | 33 | SINGLE_LIST_ENTRY 34 | m_listHead = {}; 35 | 36 | size_t 37 | m_count = 0; 38 | }; 39 | 40 | static_assert(sizeof(NxPowerList) <= sizeof(NET_POWER_OFFLOAD_LIST::Reserved)); 41 | 42 | class NxPowerOffloadList : public NxPowerList 43 | { 44 | public: 45 | 46 | NxPowerOffloadList( 47 | void 48 | ) noexcept; 49 | 50 | void * 51 | operator new( 52 | _In_ size_t, 53 | _In_ NET_POWER_OFFLOAD_LIST * NetPowerOffloadList 54 | ); 55 | 56 | NxPowerOffload * 57 | GetPowerOffloadByIndex( 58 | _In_ size_t Index 59 | ) const; 60 | }; 61 | 62 | static_assert(sizeof(NxPowerOffloadList) <= sizeof(NET_POWER_OFFLOAD_LIST::Reserved)); 63 | 64 | class NxWakeSourceList : public NxPowerList 65 | { 66 | public: 67 | 68 | NxWakeSourceList( 69 | void 70 | ) noexcept; 71 | 72 | void * 73 | operator new( 74 | _In_ size_t, 75 | _In_ NET_WAKE_SOURCE_LIST * NetWakeSourceList 76 | ); 77 | 78 | NxWakeSource * 79 | GetWakeSourceByIndex( 80 | _In_ size_t Index 81 | ) const; 82 | }; 83 | 84 | static_assert(sizeof(NxWakeSourceList) <= sizeof(NET_POWER_OFFLOAD_LIST::Reserved)); 85 | 86 | NxPowerOffloadList const * 87 | GetNxPowerListFromOffloadList( 88 | _In_ NET_POWER_OFFLOAD_LIST const * List 89 | ); 90 | 91 | NxWakeSourceList const * 92 | GetNxPowerListFromWakeList( 93 | _In_ NET_WAKE_SOURCE_LIST const * List 94 | ); 95 | -------------------------------------------------------------------------------- /netcx/adapter/powerpolicy/nxidlerestrictions.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include "KSpinLock.h" 6 | 7 | class NxIdleRestrictions 8 | { 9 | public: 10 | 11 | NxIdleRestrictions(NETADAPTER adapter, WDFDEVICE device); 12 | 13 | ~NxIdleRestrictions(); 14 | 15 | NxIdleRestrictions(const NxIdleRestrictions&) = delete; 16 | NxIdleRestrictions& operator=(const NxIdleRestrictions&) = delete; 17 | 18 | enum class IdleRestrictionSettings 19 | { 20 | None = 0, 21 | HighLatencyResume, 22 | }; 23 | 24 | _Requires_lock_not_held_(m_lock) 25 | NTSTATUS SetMinimumIdleCondition(NDIS_IDLE_CONDITION minimumIdleCondition); 26 | 27 | _Requires_lock_not_held_(m_lock) 28 | NTSTATUS SetCurrentIdleCondition(NDIS_IDLE_CONDITION idleCondition); 29 | 30 | _Requires_lock_not_held_(m_lock) 31 | void OnWdfStopIdleRefsSupported(); 32 | 33 | private: 34 | const NETADAPTER m_adapter; 35 | const WDFDEVICE m_device; 36 | 37 | KSpinLock m_lock; 38 | 39 | bool m_powerReferenceAcquired = false; 40 | 41 | // Represents the most restrictive NDIS_IDLE_CONDITION whose requirements can be met while 42 | // allowing idle power transitions. We will block idle power transitions when m_currentIdleCondition 43 | // is more restrictive. 44 | NDIS_IDLE_CONDITION m_minimumIdleCondition = NdisIdleConditionAnyLowLatency; 45 | 46 | // Current NDIS_IDLE_CONDITION received from WCM 47 | NDIS_IDLE_CONDITION m_currentIdleCondition = NdisIdleConditionAnyLowLatency; 48 | 49 | // Acquires or Releases power reference based on current state. Should be called whenever 50 | // any state relevant to idle restriction is updated. 51 | _Requires_lock_not_held_(m_lock) 52 | NTSTATUS RestrictS0IdleByIdleCondition(); 53 | 54 | // Acquires power reference, no-op if a reference is already held. 55 | _Requires_lock_held_(m_lock) 56 | NTSTATUS AcquirePowerReference(); 57 | 58 | // Releases power reference if one is aquired, no-op otherwise. 59 | _Requires_lock_held_(m_lock) 60 | void ReleasePowerReference(); 61 | }; 62 | -------------------------------------------------------------------------------- /netcx/ec/inc/executioncontext.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | DECLARE_HANDLE(NET_EXECUTION_CONTEXT); 5 | 6 | typedef enum _EXECUTION_CONTEXT_FLAGS 7 | { 8 | ExecutionContextFlagNone = 0, 9 | ExecutionContextFlagRunDpcForFirstLoop = 1 << 0, 10 | ExecutionContextFlagRunWorkerThreadAtDispatch = 1 << 1, 11 | ExecutionContextFlagTryExtendMaxTimeAtDispatch = 1 << 2, 12 | } EXECUTION_CONTEXT_FLAGS; 13 | 14 | DEFINE_ENUM_FLAG_OPERATORS(EXECUTION_CONTEXT_FLAGS) 15 | 16 | typedef struct _EXECUTION_CONTEXT_WORK_UNIT_KNOBS 17 | { 18 | UINT32 AtPassive; 19 | UINT32 AtDispatch; 20 | } EXECUTION_CONTEXT_WORK_UNIT_KNOBS; 21 | 22 | typedef struct _EXECUTION_CONTEXT_RUNTIME_KNOBS 23 | { 24 | ULONG Size; 25 | 26 | EXECUTION_CONTEXT_FLAGS Flags; 27 | UINT32 MaxTimeAtDispatch; 28 | UINT32 DispatchTimeWarning; 29 | UINT32 DispatchTimeWarningInterval; 30 | UINT32 DpcWatchdogTimerThreshold; 31 | UINT32 WorkerThreadPriority; 32 | 33 | EXECUTION_CONTEXT_WORK_UNIT_KNOBS MaxPacketsSend; 34 | EXECUTION_CONTEXT_WORK_UNIT_KNOBS MaxPacketsSendComplete; 35 | EXECUTION_CONTEXT_WORK_UNIT_KNOBS MaxPacketsReceive; 36 | EXECUTION_CONTEXT_WORK_UNIT_KNOBS MaxPacketsReceiveComplete; 37 | 38 | } EXECUTION_CONTEXT_RUNTIME_KNOBS; 39 | 40 | typedef struct _EXECUTION_CONTEXT_CONFIGURATION 41 | { 42 | ULONG Size; 43 | EXECUTION_CONTEXT_RUNTIME_KNOBS const * RuntimeKnobs; 44 | GUID const * ClientIdentifier; 45 | UNICODE_STRING ClientFriendlyName; 46 | } EXECUTION_CONTEXT_CONFIGURATION; 47 | 48 | inline 49 | void 50 | INITIALIZE_EXECUTION_CONTEXT_CONFIGURATION( 51 | _Out_ EXECUTION_CONTEXT_CONFIGURATION * Configuration 52 | ) 53 | { 54 | RtlZeroMemory(Configuration, sizeof(*Configuration)); 55 | Configuration->Size = sizeof(*Configuration); 56 | } 57 | 58 | inline 59 | void 60 | INITIALIZE_EXECUTION_CONTEXT_RUNTIME_KNOBS( 61 | _Out_ EXECUTION_CONTEXT_RUNTIME_KNOBS * RuntimeKnobs 62 | ) 63 | { 64 | RtlZeroMemory(RuntimeKnobs, sizeof(*RuntimeKnobs)); 65 | RuntimeKnobs->Size = sizeof(*RuntimeKnobs); 66 | RuntimeKnobs->Flags = ExecutionContextFlagNone; 67 | } 68 | -------------------------------------------------------------------------------- /netcx/adapter/nxdriver.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | // 8 | // The NxDriver is an object that represents a NetAdapterCx Client Driver 9 | // 10 | 11 | struct NX_PRIVATE_GLOBALS; 12 | 13 | class NxDriver; 14 | 15 | FORCEINLINE 16 | NxDriver * 17 | GetNxDriverFromWdfDriver( 18 | _In_ WDFDRIVER Driver 19 | ); 20 | 21 | class NxDriver 22 | : public CFxObject 23 | { 24 | 25 | private: 26 | 27 | NDIS_HANDLE 28 | m_ndisMiniportDriverHandle = nullptr; 29 | 30 | NX_PRIVATE_GLOBALS * 31 | m_privateGlobals = nullptr; 32 | 33 | NxDriver( 34 | _In_ WDFDRIVER Driver, 35 | _In_ NX_PRIVATE_GLOBALS * NxPrivateGlobals 36 | ); 37 | 38 | public: 39 | 40 | static 41 | NTSTATUS 42 | _CreateAndRegisterIfNeeded( 43 | _In_ NX_PRIVATE_GLOBALS * NxPrivateGlobals 44 | ); 45 | 46 | static 47 | NTSTATUS 48 | _CreateIfNeeded( 49 | _In_ WDFDRIVER Driver, 50 | _In_ NX_PRIVATE_GLOBALS * NxPrivateGlobals 51 | ); 52 | 53 | NTSTATUS 54 | Register( 55 | void 56 | ); 57 | 58 | void 59 | Deregister( 60 | void 61 | ); 62 | 63 | NDIS_HANDLE 64 | GetNdisMiniportDriverHandle( 65 | void 66 | ) const; 67 | 68 | NX_PRIVATE_GLOBALS * 69 | GetPrivateGlobals( 70 | void 71 | ) const; 72 | }; 73 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NxDriver, _GetNxDriverFromWdfDriver); 74 | 75 | FORCEINLINE 76 | NxDriver * 77 | GetNxDriverFromWdfDriver( 78 | _In_ WDFDRIVER Driver 79 | ) 80 | /*++ 81 | Routine Description: 82 | 83 | This routine is just a wrapper around the _GetNxDriverFromWdfDriver function. 84 | To be able to define a the NxDriver class above, we need a forward declaration of the 85 | accessor function. Since _GetNxDriverFromWdfDriver is defined by Wdf, we dont want to 86 | assume a prototype of that function for the foward declaration. 87 | 88 | --*/ 89 | 90 | { 91 | return _GetNxDriverFromWdfDriver(Driver); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /netcx/translator/nxnblqueue.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | /*++ 4 | 5 | Abstract: 6 | 7 | The NxNblQueue is a FIFO queues of NET_BUFFER_LISTs, with 8 | built-in synchronization. 9 | 10 | --*/ 11 | 12 | #include "NxXlatPrecomp.hpp" 13 | #include "NxXlatCommon.hpp" 14 | #include "NxNblQueue.tmh" 15 | #include "NxNblQueue.hpp" 16 | #include 17 | 18 | PAGED 19 | NxNblQueue::NxNblQueue() 20 | { 21 | NdisInitializeNblCountedQueue(&m_nblQueue); 22 | } 23 | 24 | _IRQL_requires_max_(DISPATCH_LEVEL) 25 | void 26 | NxNblQueue::Enqueue(_In_ PNET_BUFFER_LIST pNbl) 27 | { 28 | SIZE_T nblCount = 0; 29 | auto lastNbl = NdisLastNblInNblChainWithCount(pNbl, &nblCount); 30 | 31 | KAcquireSpinLock lock(m_SpinLock); 32 | m_nblQueue.NblCount += nblCount; 33 | NdisAppendNblChainToNblQueueFast(&m_nblQueue.Queue, pNbl, lastNbl); 34 | } 35 | 36 | _IRQL_requires_max_(DISPATCH_LEVEL) 37 | void 38 | NxNblQueue::Enqueue(_Inout_ NBL_COUNTED_QUEUE *queue) 39 | { 40 | KAcquireSpinLock lock(m_SpinLock); 41 | NdisAppendNblQueueToNblQueueFast(&m_nblQueue.Queue, &(queue->Queue)); 42 | m_nblQueue.NblCount += queue->NblCount; 43 | } 44 | 45 | _IRQL_requires_max_(DISPATCH_LEVEL) 46 | void 47 | NxNblQueue::DequeueAll( 48 | _Out_ NBL_QUEUE *destination) 49 | { 50 | KAcquireSpinLock lock(m_SpinLock); 51 | NdisInitializeNblQueue(destination); 52 | NdisAppendNblQueueToNblQueueFast(destination, &m_nblQueue.Queue); 53 | m_nblQueue.NblCount = 0; 54 | } 55 | 56 | _IRQL_requires_max_(DISPATCH_LEVEL) 57 | NET_BUFFER_LIST * 58 | NxNblQueue::DequeueAll() 59 | { 60 | KAcquireSpinLock lock(m_SpinLock); 61 | m_nblQueue.NblCount = 0; 62 | return NdisPopAllFromNblQueue(&m_nblQueue.Queue); 63 | } 64 | 65 | _IRQL_requires_max_(DISPATCH_LEVEL) 66 | ULONG64 67 | NxNblQueue::GetNblQueueDepth() const 68 | { 69 | return m_nblQueue.NblCount; 70 | } 71 | 72 | _IRQL_requires_max_(DISPATCH_LEVEL) 73 | NET_BUFFER_LIST const * 74 | NxNblQueue::PeekNbl() const 75 | { 76 | if (m_nblQueue.NblCount > 0U) 77 | { 78 | return m_nblQueue.Queue.First; 79 | } 80 | 81 | return nullptr; 82 | } 83 | -------------------------------------------------------------------------------- /netcx/translator/framelayout/layer4layout.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace Layer4 8 | { 9 | 10 | union TCP 11 | { 12 | struct { 13 | UINT16 14 | SourcePort; 15 | UINT16 16 | DestinationPort; 17 | UINT32 18 | SequenceNumber; 19 | UINT32 20 | AcknowledgementNumber; 21 | union { 22 | struct { 23 | UINT8 24 | Reserved:4; 25 | UINT8 26 | DataOffset:4; 27 | } DataOffset; 28 | struct { 29 | UINT16 30 | Reserved:7; 31 | UINT16 32 | ControlBits:6; 33 | UINT16 34 | ExplicitCongestionControl:3; 35 | } ControlBits; 36 | UINT8 37 | Bytes[2]; 38 | }; 39 | UINT16 40 | Window; 41 | UINT16 42 | Checksum; 43 | UINT16 44 | UrgentPointer; 45 | } Header; 46 | 47 | static_assert(sizeof(Header) == 20U); 48 | 49 | UINT8 50 | Value[sizeof(Header)]; 51 | 52 | }; 53 | 54 | union UDP 55 | { 56 | struct { 57 | UINT16 58 | SourcePort; 59 | UINT16 60 | DestinationPort; 61 | UINT16 62 | Length; 63 | UINT16 64 | Checksum; 65 | } Header; 66 | 67 | static_assert(sizeof(Header) == 8U); 68 | 69 | UINT8 70 | Value[sizeof(Header)]; 71 | 72 | }; 73 | 74 | bool 75 | ParseLayout( 76 | _Inout_ NET_PACKET_LAYOUT & Layout, 77 | _In_ UINT8 const * Pointer, 78 | _Inout_ size_t & Offset, 79 | _Inout_ size_t & Length 80 | ); 81 | 82 | bool 83 | ParseTcpLayout( 84 | _Inout_ NET_PACKET_LAYOUT & Layout, 85 | _In_ UINT8 const * Pointer, 86 | _Inout_ size_t & Offset, 87 | _Inout_ size_t & Length 88 | ); 89 | 90 | bool 91 | ParseUdpLayout( 92 | _Inout_ NET_PACKET_LAYOUT & Layout, 93 | _In_ UINT8 const * Pointer, 94 | _Inout_ size_t & Offset, 95 | _Inout_ size_t & Length 96 | ); 97 | 98 | } 99 | -------------------------------------------------------------------------------- /netcx/ec/inc/executioncontextpoll.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | // Keep the enum values sorted by polling priority 5 | typedef enum _EXECUTION_CONTEXT_POLL_TYPE 6 | { 7 | ExecutionContextPollTypePreAdvance = 2000, 8 | ExecutionContextPollTypeNdisMiniportDriverPoll = 4000, 9 | ExecutionContextPollTypeAdvance = 4000, 10 | ExecutionContextPollTypeNdisMiniportPostDriverPoll = 6000, 11 | ExecutionContextPollTypePostAdvance = 6000, 12 | } EXECUTION_CONTEXT_POLL_TYPE; 13 | 14 | typedef struct _EXECUTION_CONTEXT_POLL_PARAMETERS 15 | { 16 | _In_ KIRQL Irql; 17 | _Reserved_ UCHAR Reserved1[3]; 18 | 19 | _Out_ ULONG WorkCounter; 20 | 21 | void *Reserved3[3]; 22 | } EXECUTION_CONTEXT_POLL_PARAMETERS; 23 | 24 | typedef 25 | _IRQL_requires_max_(DISPATCH_LEVEL) 26 | void 27 | EVT_EXECUTION_CONTEXT_POLL( 28 | _In_ void * Context, 29 | _Inout_ EXECUTION_CONTEXT_POLL_PARAMETERS * Parameters 30 | ); 31 | 32 | typedef EVT_EXECUTION_CONTEXT_POLL *PFN_EXECUTION_CONTEXT_POLL; 33 | 34 | typedef struct _EXECUTION_CONTEXT_POLL 35 | { 36 | EXECUTION_CONTEXT_POLL_TYPE 37 | Type; 38 | 39 | ULONG 40 | Tag; 41 | 42 | void * 43 | Context; 44 | 45 | PFN_EXECUTION_CONTEXT_POLL 46 | PollFn; 47 | 48 | LIST_ENTRY 49 | Link; 50 | 51 | void * 52 | Reserved[4]; 53 | } EXECUTION_CONTEXT_POLL; 54 | 55 | inline 56 | void 57 | INITIALIZE_EXECUTION_CONTEXT_POLL( 58 | _Out_ EXECUTION_CONTEXT_POLL * Poll, 59 | _In_ _EXECUTION_CONTEXT_POLL_TYPE Type, 60 | _In_opt_ void * Context, 61 | _In_ PFN_EXECUTION_CONTEXT_POLL PollFn 62 | ) 63 | { 64 | RtlZeroMemory(Poll, sizeof(*Poll)); 65 | Poll->Type = Type; 66 | Poll->Context = Context; 67 | Poll->PollFn = PollFn; 68 | InitializeListHead(&Poll->Link); 69 | } 70 | 71 | inline 72 | void 73 | INITIALIZE_EXECUTION_CONTEXT_POLL_WITH_TAG( 74 | _Out_ EXECUTION_CONTEXT_POLL * Poll, 75 | _In_ _EXECUTION_CONTEXT_POLL_TYPE Type, 76 | _In_opt_ void * Context, 77 | _In_ PFN_EXECUTION_CONTEXT_POLL PollFn, 78 | _In_ ULONG Tag 79 | ) 80 | { 81 | INITIALIZE_EXECUTION_CONTEXT_POLL( 82 | Poll, 83 | Type, 84 | Context, 85 | PollFn); 86 | 87 | Poll->Tag = Tag; 88 | } 89 | -------------------------------------------------------------------------------- /netcx/ec/lib/activitytracker.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | 4 | #include "ActivityTracker.hpp" 5 | #include "ExecutionContext.hpp" 6 | #include "EcEvents.h" 7 | 8 | _Use_decl_annotations_ 9 | ActivityTracker::ActivityTracker( 10 | _In_ GUID const & Identifier 11 | ) 12 | : m_identifier(Identifier) 13 | { 14 | } 15 | 16 | _Use_decl_annotations_ 17 | void 18 | ActivityTracker::Initialize( 19 | UNICODE_STRING const * Name 20 | ) 21 | { 22 | m_friendlyName = Name; 23 | } 24 | 25 | _Use_decl_annotations_ 26 | void 27 | ActivityTracker::LogEvent( 28 | ExecutionContextEvent Event 29 | ) 30 | { 31 | m_entries[m_entryIndex].Type = Entry::Type::Event; 32 | m_entries[m_entryIndex].u.Event.EventType = Event; 33 | 34 | m_entryIndex = (m_entryIndex + 1) % NumberOfEntries; 35 | } 36 | 37 | _Use_decl_annotations_ 38 | void 39 | ActivityTracker::LogStateChange( 40 | ExecutionContextStateChangeReason Reason, 41 | ExecutionContextState PreviousState, 42 | ExecutionContextState NewState 43 | ) 44 | { 45 | auto & entry = m_entries[m_entryIndex]; 46 | entry.Type = Entry::Type::StateChange; 47 | entry.u.StateChange.Reason = Reason; 48 | entry.u.StateChange.PreviousState = PreviousState; 49 | entry.u.StateChange.NewState = NewState; 50 | 51 | m_entryIndex = (m_entryIndex + 1) % NumberOfEntries; 52 | 53 | EventWriteExecutionContextStateChange( 54 | &m_identifier, 55 | static_cast(Reason), 56 | static_cast(PreviousState), 57 | static_cast(NewState), 58 | m_taskCounter, 59 | m_iterationCounter, 60 | m_workCounter, 61 | m_friendlyName->Length / sizeof(UNICODE_NULL), 62 | m_friendlyName->Buffer); 63 | } 64 | 65 | _Use_decl_annotations_ 66 | void 67 | ActivityTracker::LogIteration( 68 | UINT64 Work 69 | ) 70 | { 71 | m_iterationCounter++; 72 | m_workCounter += Work; 73 | } 74 | 75 | _Use_decl_annotations_ 76 | void 77 | ActivityTracker::LogTask( 78 | void 79 | ) 80 | { 81 | m_taskCounter++; 82 | } 83 | 84 | _Use_decl_annotations_ 85 | void 86 | ActivityTracker::ResetCounters( 87 | void 88 | ) 89 | { 90 | m_iterationCounter = 0; 91 | m_workCounter = 0; 92 | m_taskCounter = 0; 93 | } 94 | -------------------------------------------------------------------------------- /netcx/bm/dmaallocator.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "bmprecomp.hpp" 3 | 4 | #include "CommonBufferVector.hpp" 5 | #include "DmaAllocator.hpp" 6 | #include "DmaAllocator.tmh" 7 | 8 | _Use_decl_annotations_ 9 | DmaAllocator::DmaAllocator( 10 | NET_CLIENT_MEMORY_CONSTRAINTS::DMA & Dma 11 | ) 12 | : m_DmaAdapter(reinterpret_cast(Dma.DmaAdapter)) 13 | , m_MaximumPhysicalAddress(Dma.MaximumPhysicalAddress) 14 | , m_PreferredNode(Dma.PreferredNode) 15 | { 16 | if (Dma.CacheEnabled == NET_CLIENT_TRI_STATE_DEFAULT) 17 | { 18 | #if _AMD64_ || _X86_ 19 | m_CacheEnabled = true; 20 | #else 21 | m_CacheEnabled = false; 22 | #endif 23 | } 24 | else 25 | { 26 | m_CacheEnabled = Dma.CacheEnabled; 27 | } 28 | } 29 | 30 | _Use_decl_annotations_ 31 | IBufferVector * 32 | DmaAllocator::AllocateVector( 33 | size_t BufferCount, 34 | size_t BufferSize, 35 | size_t BufferOffset, 36 | NODE_REQUIREMENT PreferredNode 37 | ) 38 | { 39 | NODE_REQUIREMENT node = PreferredNode == MM_ANY_NODE_OK 40 | ? m_PreferredNode 41 | : PreferredNode; 42 | 43 | auto bufferVector = wil::make_unique_nothrow( 44 | m_DmaAdapter, 45 | BufferCount, 46 | BufferSize, 47 | BufferOffset); 48 | 49 | if (!bufferVector) 50 | { 51 | return nullptr; 52 | } 53 | 54 | // Currently AllocateCommonBufferVector takes in MI_NODE_NUMBER_ZERO_BASED 55 | // as NUMA node parameter, so we have to convert MM_ANY_NODE_OK to an actual 56 | // node id ourself - pick node 0 57 | if (node == MM_ANY_NODE_OK) 58 | { 59 | node = 0; 60 | } 61 | 62 | auto const status = m_DmaAdapter->DmaOperations->AllocateCommonBufferVector( 63 | m_DmaAdapter, 64 | PHYSICAL_ADDRESS{}, 65 | m_MaximumPhysicalAddress.QuadPart != 0 ? m_MaximumPhysicalAddress : PHYSICAL_ADDRESS{ 0xffffffff, -1 }, 66 | m_CacheEnabled ? MmCached : MmNonCached, 67 | node, 68 | 0, 69 | static_cast(BufferCount), 70 | static_cast(BufferSize), 71 | &bufferVector->m_CommonBufferVector); 72 | 73 | if (status != STATUS_SUCCESS) 74 | { 75 | return nullptr; 76 | } 77 | 78 | return bufferVector.release(); 79 | } 80 | -------------------------------------------------------------------------------- /netcx/adapter/types/nxadapterextensiontypes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #pragma warning(push) 12 | #pragma warning(disable:4201) 13 | #include 14 | #include 15 | #pragma warning(pop) 16 | 17 | #include "verifier.hpp" 18 | #include "NxAdapterExtensionTypes.hpp" 19 | 20 | static 21 | size_t 22 | sizeof_NET_ADAPTER_NDIS_PM_CAPABILITIES_version( 23 | _In_ WDF_CLASS_VERSION const & Version 24 | ) 25 | { 26 | switch (MAKEVER(Version.Major, Version.Minor)) 27 | { 28 | case MAKEVER(2,0): 29 | 30 | return sizeof(NET_ADAPTER_NDIS_PM_CAPABILITIES_V2_0); 31 | 32 | case MAKEVER(2,1): 33 | 34 | return sizeof(NET_ADAPTER_NDIS_PM_CAPABILITIES_V2_1); 35 | 36 | default: 37 | 38 | return 0; 39 | } 40 | } 41 | 42 | NxAdapterNdisPmCapabilities::NxAdapterNdisPmCapabilities( 43 | NX_PRIVATE_GLOBALS const & ClientGlobals, 44 | NET_ADAPTER_NDIS_PM_CAPABILITIES const & Capabilities 45 | ) 46 | { 47 | Assign(ClientGlobals, Capabilities); 48 | } 49 | 50 | NxAdapterNdisPmCapabilities::operator bool( 51 | void 52 | ) const 53 | { 54 | return Size != 0; 55 | } 56 | 57 | _Use_decl_annotations_ 58 | void 59 | NxAdapterNdisPmCapabilities::Assign( 60 | NX_PRIVATE_GLOBALS const & ClientGlobals, 61 | NET_ADAPTER_NDIS_PM_CAPABILITIES const & Capabilities 62 | ) 63 | { 64 | auto const expectedSize = sizeof_NET_ADAPTER_NDIS_PM_CAPABILITIES_version(ClientGlobals.ClientVersion); 65 | 66 | if (Capabilities.Size != expectedSize) 67 | { 68 | Verifier_ReportViolation( 69 | &ClientGlobals, 70 | VerifierAction_BugcheckAlways, 71 | FailureCode_InvalidStructTypeSize, 72 | Capabilities.Size, 73 | expectedSize); 74 | } 75 | 76 | switch (MAKEVER(ClientGlobals.ClientVersion.Major, ClientGlobals.ClientVersion.Minor)) 77 | { 78 | case MAKEVER(2,1): 79 | SupportedProtocolOffloads = Capabilities.SupportedProtocolOffloads; 80 | __fallthrough; 81 | 82 | case MAKEVER(2,0): 83 | Size = Capabilities.Size; 84 | MediaSpecificWakeUpEvents = Capabilities.MediaSpecificWakeUpEvents; 85 | 86 | break; 87 | 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /netcx/translator/nxnblsequence.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "RtlHomogenousSequence.h" 6 | 7 | // Utility class that builds on top of a simple NBL_QUEUE. 8 | // 9 | // In addition to tracking how many NBLs are in the queue, this class also 10 | // tracks additional data needed to populate 11 | // NdisMIndicateReceiveNetBufferLists, including the length of the NBL chain 12 | // and whether all the NBLs have the same EtherType. 13 | 14 | class NxNblSequence 15 | { 16 | public: 17 | 18 | NxNblSequence() 19 | { 20 | NdisInitializeNblQueue(&m_queue); 21 | } 22 | 23 | void AddNbl(_In_ NET_BUFFER_LIST *nbl) 24 | { 25 | WIN_ASSERT(nbl->Next == nullptr); 26 | 27 | m_frameTypes.AddValue((USHORT)nbl->NetBufferListInfo[NetBufferListFrameType]); 28 | 29 | m_count += 1; 30 | NdisAppendNblChainToNblQueueFast(&m_queue, nbl, nbl); 31 | } 32 | 33 | operator bool() const 34 | { 35 | return m_count > 0; 36 | } 37 | 38 | NBL_QUEUE &GetNblQueue() 39 | { 40 | return m_queue; 41 | } 42 | 43 | ULONG GetCount() const 44 | { 45 | return m_count; 46 | } 47 | 48 | ULONG GetReceiveFlags() const 49 | { 50 | ULONG receiveFlags = 0; 51 | 52 | if (m_frameTypes.IsHomogenous()) 53 | receiveFlags |= NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE; 54 | 55 | return receiveFlags; 56 | } 57 | 58 | // Calling PopAllNblsFromNblQueue() + PushNblsToNblQueue() will temporarily 59 | // get the NBL chain out of NBL_QUEUE, perform coalescing, 60 | // and then put NBL chain back to NBL_QUEUE. 61 | // Frame type of coalesced NBLs is not changed, so m_frameTypes remain unchanged. 62 | NET_BUFFER_LIST * 63 | PopAllNblsFromNblQueue( 64 | void 65 | ) 66 | { 67 | NET_BUFFER_LIST * nblChain = NdisPopAllFromNblQueue(&m_queue); 68 | m_count = 0U; 69 | 70 | return nblChain; 71 | } 72 | 73 | void 74 | PushNblsToNblQueue( 75 | _In_ NET_BUFFER_LIST * NblChainHead, 76 | _In_ NET_BUFFER_LIST * NblChainTail, 77 | _In_ ULONG NblCount 78 | ) 79 | { 80 | NdisAppendNblChainToNblQueueFast(&GetNblQueue(), NblChainHead, NblChainTail); 81 | m_count += NblCount; 82 | } 83 | 84 | private: 85 | 86 | ULONG m_count = 0; 87 | RtlHomogenousSequence m_frameTypes; 88 | 89 | NBL_QUEUE m_queue; 90 | }; 91 | 92 | -------------------------------------------------------------------------------- /netcx/translator/framelayout/layer4layout.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #ifdef _KERNEL_MODE 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | #include 12 | 13 | #include "Layer4Layout.hpp" 14 | 15 | namespace Layer4 16 | { 17 | 18 | bool 19 | ParseLayout( 20 | NET_PACKET_LAYOUT & Layout, 21 | UINT8 const * Pointer, 22 | size_t & Offset, 23 | size_t & Length 24 | ) 25 | { 26 | NT_FRE_ASSERT(Layout.Layer4HeaderLength == 0U); 27 | 28 | switch (Layout.Layer4Type) 29 | { 30 | 31 | case NetPacketLayer4TypeTcp: 32 | 33 | return ParseTcpLayout(Layout, Pointer, Offset, Length); 34 | 35 | case NetPacketLayer4TypeUdp: 36 | 37 | return ParseUdpLayout(Layout, Pointer, Offset, Length); 38 | 39 | } 40 | 41 | return false; 42 | } 43 | 44 | _Use_decl_annotations_ 45 | bool 46 | ParseTcpLayout( 47 | NET_PACKET_LAYOUT & Layout, 48 | UINT8 const * Pointer, 49 | size_t & Offset, 50 | size_t & Length 51 | ) 52 | { 53 | NT_FRE_ASSERT(Layout.Layer4Type == NetPacketLayer4TypeTcp); 54 | NT_FRE_ASSERT(Layout.Layer4HeaderLength == 0U); 55 | 56 | auto const tcp = reinterpret_cast(&Pointer[Offset]); 57 | auto const size = sizeof(*tcp); 58 | if (size > Length) 59 | { 60 | return false; 61 | } 62 | 63 | auto const headersz = static_cast(tcp->Header.DataOffset.DataOffset) << 2; 64 | if (headersz > Length) 65 | { 66 | return false; 67 | } 68 | 69 | Layout.Layer4HeaderLength = headersz; 70 | 71 | Offset += Layout.Layer4HeaderLength; 72 | Length -= Layout.Layer4HeaderLength; 73 | 74 | return true; 75 | } 76 | 77 | _Use_decl_annotations_ 78 | bool 79 | ParseUdpLayout( 80 | NET_PACKET_LAYOUT & Layout, 81 | UINT8 const * Pointer, 82 | size_t & Offset, 83 | size_t & Length 84 | ) 85 | { 86 | NT_FRE_ASSERT(Layout.Layer4Type == NetPacketLayer4TypeUdp); 87 | NT_FRE_ASSERT(Layout.Layer4HeaderLength == 0U); 88 | 89 | auto const udp = reinterpret_cast(&Pointer[Offset]); 90 | auto const size = sizeof(*udp); 91 | if (size > Length) 92 | { 93 | return false; 94 | } 95 | 96 | Layout.Layer4HeaderLength = size; 97 | 98 | Offset += Layout.Layer4HeaderLength; 99 | Length -= Layout.Layer4HeaderLength; 100 | 101 | return true; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /netcx/adapter/queue/queue.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | class BufferPool; 6 | 7 | namespace NetCx::Core { 8 | 9 | class Queue 10 | { 11 | public: 12 | 13 | enum class Type 14 | { 15 | Rx, 16 | Tx, 17 | }; 18 | 19 | Queue( 20 | void 21 | ); 22 | 23 | NTSTATUS 24 | Initialize( 25 | _In_ Rtl::KArray & Extensions, 26 | _In_ UINT32 NumberOfPackets, 27 | _In_ UINT32 NumberOfFragments, 28 | _In_ UINT32 NumberOfDataBuffers, 29 | _In_ BufferPool * BufferPool 30 | ); 31 | 32 | void 33 | GetExtension( 34 | _In_ const NET_EXTENSION_PRIVATE * ExtensionToQuery, 35 | _Out_ NET_EXTENSION* Extension 36 | ) const; 37 | 38 | NET_RING_COLLECTION const * 39 | GetRingCollection( 40 | void 41 | ) const; 42 | 43 | private: 44 | 45 | NTSTATUS 46 | CreateRing( 47 | _In_ size_t ElementSize, 48 | _In_ UINT32 ElementCount, 49 | _In_ NET_RING_TYPE RingType 50 | ); 51 | 52 | static 53 | void 54 | EnumerateCallback( 55 | _In_ PVOID Context, 56 | _In_ SIZE_T Index, 57 | _In_ UINT64 LogicalAddress, 58 | _In_ PVOID VirtualAddress 59 | ); 60 | 61 | protected: 62 | 63 | void 64 | PreAdvancePostDataBuffer( 65 | void 66 | ); 67 | 68 | void 69 | PostAdvanceRefCounting( 70 | void 71 | ); 72 | 73 | void 74 | PostStopReclaimDataBuffers( 75 | void 76 | ); 77 | 78 | protected: 79 | 80 | NxExtensionLayout 81 | m_packetLayout; 82 | 83 | NxExtensionLayout 84 | m_fragmentLayout; 85 | 86 | NxExtensionLayout 87 | m_bufferLayout; 88 | 89 | KPoolPtr 90 | m_rings[NetRingTypeDataBuffer + 1]; 91 | 92 | NET_RING_COLLECTION 93 | m_ringCollection; 94 | 95 | private: 96 | 97 | NET_RING 98 | m_shadowRings[NetRingTypeDataBuffer + 1]; 99 | 100 | BufferPool * 101 | m_bufferPool = nullptr; 102 | 103 | KPoolPtrNP 104 | m_laLookupTable; 105 | 106 | KPoolPtrNP 107 | m_vaLookupTable; 108 | 109 | NET_EXTENSION 110 | m_fragmentDataBufferExt; 111 | 112 | NET_EXTENSION 113 | m_fragmentVaExt; 114 | 115 | NET_EXTENSION 116 | m_bufferVaExt; 117 | 118 | NET_EXTENSION 119 | m_bufferLaExt; 120 | }; 121 | 122 | } // namespace NetCx::Core 123 | -------------------------------------------------------------------------------- /netcx/adapter/rxscaling/nxrxscaling.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | struct _NET_CLIENT_ADAPTER_RECEIVE_SCALING_CAPABILITIES; 6 | typedef _NET_CLIENT_ADAPTER_RECEIVE_SCALING_CAPABILITIES NET_CLIENT_ADAPTER_RECEIVE_SCALING_CAPABILITIES; 7 | 8 | class NxRxScaling 9 | { 10 | 11 | public: 12 | 13 | _IRQL_requires_(PASSIVE_LEVEL) 14 | NxRxScaling( 15 | _In_ NETADAPTER AdapterHandle 16 | ); 17 | 18 | _IRQL_requires_(PASSIVE_LEVEL) 19 | void 20 | SetCapabilities( 21 | _In_ NET_ADAPTER_RECEIVE_SCALING_CAPABILITIES const & Capabilities 22 | ); 23 | 24 | _IRQL_requires_(PASSIVE_LEVEL) 25 | void 26 | GetCapabilities( 27 | _Out_ NET_CLIENT_ADAPTER_RECEIVE_SCALING_CAPABILITIES * Capabilities 28 | ) const; 29 | 30 | _IRQL_requires_(PASSIVE_LEVEL) 31 | NTSTATUS 32 | Enable( 33 | void 34 | ); 35 | 36 | _IRQL_requires_(PASSIVE_LEVEL) 37 | void 38 | Disable( 39 | void 40 | ); 41 | 42 | _IRQL_requires_(PASSIVE_LEVEL) 43 | NTSTATUS 44 | SetHashSecretKey( 45 | _In_ NET_CLIENT_RECEIVE_SCALING_HASH_SECRET_KEY const * HashSecretKey 46 | ); 47 | 48 | _IRQL_requires_max_(DISPATCH_LEVEL) 49 | NTSTATUS 50 | SetIndirectionEntries( 51 | _Inout_ NET_CLIENT_RECEIVE_SCALING_INDIRECTION_ENTRIES * Entries 52 | ); 53 | 54 | _IRQL_requires_(PASSIVE_LEVEL) 55 | NTSTATUS 56 | SetHashInfo( 57 | _In_ NET_CLIENT_RECEIVE_SCALING_HASH_INFO const * HashInfo 58 | ); 59 | 60 | _IRQL_requires_(PASSIVE_LEVEL) 61 | NTSTATUS 62 | CheckHashInfoCapabilities( 63 | _In_ NET_CLIENT_RECEIVE_SCALING_HASH_INFO const * HashInfo 64 | ) const; 65 | 66 | _IRQL_requires_(PASSIVE_LEVEL) 67 | bool 68 | IsSupported( 69 | void 70 | ); 71 | 72 | bool 73 | RssKeywordEnabled = false; 74 | 75 | NDIS_RECEIVE_SCALE_CAPABILITIES * 76 | RecvScaleCapabilities = nullptr; 77 | 78 | ULONG 79 | DefaultNumberOfQueues = 0; 80 | 81 | private: 82 | 83 | NETADAPTER 84 | m_adapter = WDF_NO_HANDLE; 85 | 86 | NET_ADAPTER_RECEIVE_SCALING_CAPABILITIES 87 | m_capabilities = {}; 88 | 89 | NDIS_RECEIVE_SCALE_CAPABILITIES 90 | m_recvScaleCapabilities = {}; 91 | 92 | NET_ADAPTER_RECEIVE_SCALING_HASH_TYPE 93 | m_hashType = NetAdapterReceiveScalingHashTypeNone; 94 | 95 | NET_ADAPTER_RECEIVE_SCALING_PROTOCOL_TYPE 96 | m_protocolType = NetAdapterReceiveScalingProtocolTypeNone; 97 | 98 | bool 99 | m_enabled = false; 100 | }; 101 | -------------------------------------------------------------------------------- /netcx/adapter/idle/powerreferenceholder.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #ifdef _KERNEL_MODE 3 | #include 4 | #else 5 | #include 6 | #define ASSERT(x) 7 | #endif 8 | #include 9 | #include 10 | #include 11 | 12 | #include "PowerReferenceHolder.hpp" 13 | 14 | #include "PowerReferenceHolder.tmh" 15 | 16 | _Use_decl_annotations_ 17 | PowerReferenceHolder::PowerReferenceHolder( 18 | KRundown & Rundown 19 | ) 20 | : m_type(Type::Rundown) 21 | , m_rundown(&Rundown) 22 | , m_ntStatus(STATUS_SUCCESS) 23 | { 24 | } 25 | 26 | _Use_decl_annotations_ 27 | PowerReferenceHolder::PowerReferenceHolder( 28 | WDFDEVICE Device, 29 | void const * Tag, 30 | NTSTATUS NtStatus 31 | ) 32 | : m_type(Type::WDF) 33 | , m_device(Device) 34 | , m_tag(Tag) 35 | , m_ntStatus(NtStatus) 36 | { 37 | } 38 | 39 | _Use_decl_annotations_ 40 | PowerReferenceHolder::PowerReferenceHolder( 41 | PowerReferenceHolder && Other 42 | ) 43 | : m_rundown(Other.m_rundown) 44 | , m_device(Other.m_device) 45 | , m_ntStatus(Other.m_ntStatus) 46 | , m_tag(Other.m_tag) 47 | , m_type(Other.m_type) 48 | { 49 | Other.m_rundown = nullptr; 50 | Other.m_device = WDF_NO_HANDLE; 51 | Other.m_ntStatus = STATUS_UNSUCCESSFUL; 52 | Other.m_tag = nullptr; 53 | Other.m_type = Type::None; 54 | } 55 | 56 | _Use_decl_annotations_ 57 | PowerReferenceHolder & 58 | PowerReferenceHolder::operator=( 59 | PowerReferenceHolder && Other 60 | ) 61 | { 62 | if (this != &Other) 63 | { 64 | this->m_device = Other.m_device; 65 | this->m_ntStatus = Other.m_ntStatus; 66 | this->m_rundown = Other.m_rundown; 67 | this->m_tag = Other.m_tag; 68 | this->m_type = Other.m_type; 69 | 70 | Other.m_device = WDF_NO_HANDLE; 71 | Other.m_ntStatus = STATUS_UNSUCCESSFUL; 72 | Other.m_rundown = nullptr; 73 | Other.m_tag = nullptr; 74 | Other.m_type = Type::None; 75 | } 76 | 77 | return *this; 78 | } 79 | 80 | _Use_decl_annotations_ 81 | PowerReferenceHolder::~PowerReferenceHolder( 82 | void 83 | ) 84 | { 85 | switch (m_type) 86 | { 87 | case Type::Rundown: 88 | 89 | NT_FRE_ASSERT(NT_SUCCESS(m_ntStatus)); 90 | m_rundown->Release(); 91 | 92 | break; 93 | 94 | case Type::WDF: 95 | 96 | if (NT_SUCCESS(m_ntStatus)) 97 | { 98 | WdfDeviceResumeIdleWithTag(m_device, const_cast(m_tag)); 99 | } 100 | 101 | break; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /rtl/inc/klockholder.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class KRTL_CLASS KLockHolder 8 | { 9 | private: 10 | 11 | enum { Unlocked, Shared, Exclusive } m_State; 12 | 13 | public: 14 | 15 | PAGED KLockHolder(KPushLockBase &lock) : m_Lock(lock), m_State(Unlocked) { } 16 | PAGED ~KLockHolder() 17 | { 18 | switch (m_State) 19 | { 20 | case Shared: 21 | ReleaseShared(); 22 | break; 23 | case Exclusive: 24 | ReleaseExclusive(); 25 | break; 26 | } 27 | } 28 | 29 | KLockHolder(KLockHolder &) = delete; 30 | KLockHolder &operator=(KLockHolder &) = delete; 31 | 32 | _IRQL_requires_(PASSIVE_LEVEL) 33 | PAGED void AcquireShared() 34 | { 35 | m_Region.Enter(); 36 | ASSERT(m_State == Unlocked); 37 | m_Lock.AcquireShared(); 38 | m_State = Shared; 39 | } 40 | 41 | _IRQL_requires_(PASSIVE_LEVEL) 42 | PAGED void ReleaseShared() 43 | { 44 | ASSERT(m_State == Shared); 45 | m_Lock.ReleaseShared(); 46 | m_State = Unlocked; 47 | m_Region.Leave(); 48 | } 49 | 50 | _IRQL_requires_(PASSIVE_LEVEL) 51 | PAGED void AcquireExclusive() 52 | { 53 | m_Region.Enter(); 54 | ASSERT(m_State == Unlocked); 55 | m_Lock.AcquireExclusive(); 56 | m_State = Exclusive; 57 | } 58 | 59 | _IRQL_requires_(PASSIVE_LEVEL) 60 | PAGED void ReleaseExclusive() 61 | { 62 | ASSERT(m_State == Exclusive); 63 | m_Lock.ReleaseExclusive(); 64 | m_State = Unlocked; 65 | m_Region.Leave(); 66 | } 67 | 68 | private: 69 | 70 | KPushLockBase &m_Lock; 71 | KCriticalRegion m_Region; 72 | }; 73 | 74 | class KRTL_CLASS KLockThisShared : protected KLockHolder 75 | { 76 | public: 77 | 78 | PAGED KLockThisShared(KPushLockBase &lock) : KLockHolder(lock) 79 | { 80 | AcquireShared(); 81 | } 82 | 83 | PAGED void Acquire() 84 | { 85 | AcquireShared(); 86 | } 87 | 88 | PAGED void Release() 89 | { 90 | ReleaseShared(); 91 | } 92 | }; 93 | 94 | class KRTL_CLASS KLockThisExclusive : protected KLockHolder 95 | { 96 | public: 97 | 98 | PAGED KLockThisExclusive(KPushLockBase &lock) : KLockHolder(lock) 99 | { 100 | AcquireExclusive(); 101 | } 102 | 103 | PAGED void Acquire() 104 | { 105 | AcquireExclusive(); 106 | } 107 | 108 | PAGED void Release() 109 | { 110 | ReleaseExclusive(); 111 | } 112 | }; 113 | 114 | 115 | -------------------------------------------------------------------------------- /netcx/adapter/nxexecutioncontext.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include "NxExecutionContext.hpp" 4 | #include "NxExecutionContext.tmh" 5 | 6 | _Use_decl_annotations_ 7 | NxExecutionContext::NxExecutionContext( 8 | WDFDEVICE Device, 9 | NET_EXECUTION_CONTEXT_CONFIG const * Config 10 | ) 11 | : ExecutionContext(&g_staticEcClientIdentier, &g_staticEcKnobs) 12 | , m_handle(static_cast(WdfObjectContextGetObject(this))) 13 | , m_device(Device) 14 | { 15 | RtlCopyMemory( 16 | &m_config, 17 | Config, 18 | Config->Size); 19 | 20 | INITIALIZE_EXECUTION_CONTEXT_POLL( 21 | &m_preAdvancePoll, 22 | ExecutionContextPollTypePreAdvance, 23 | m_handle, 24 | reinterpret_cast(m_config.EvtPreAdvance)); 25 | 26 | INITIALIZE_EXECUTION_CONTEXT_POLL( 27 | &m_postAdvancePoll, 28 | ExecutionContextPollTypePostAdvance, 29 | m_handle, 30 | reinterpret_cast(m_config.EvtPostAdvance)); 31 | 32 | INITIALIZE_EXECUTION_CONTEXT_NOTIFICATION( 33 | &m_driverNotification, 34 | m_handle, 35 | reinterpret_cast(m_config.EvtSetNotificationEnabled)); 36 | } 37 | 38 | _Use_decl_annotations_ 39 | NxExecutionContext::~NxExecutionContext( 40 | void 41 | ) 42 | { 43 | if (!IsListEmpty(&m_postAdvancePoll.Link)) 44 | { 45 | this->UnregisterPoll(&m_postAdvancePoll); 46 | } 47 | 48 | if (!IsListEmpty(&m_preAdvancePoll.Link)) 49 | { 50 | this->UnregisterPoll(&m_preAdvancePoll); 51 | } 52 | 53 | if (!IsListEmpty(&m_driverNotification.Link)) 54 | { 55 | this->UnregisterNotification(&m_driverNotification); 56 | } 57 | } 58 | 59 | _Use_decl_annotations_ 60 | NTSTATUS 61 | NxExecutionContext::Initialize( 62 | void 63 | ) 64 | { 65 | DECLARE_UNICODE_STRING_SIZE(name, ARRAYSIZE(L"NETEXECUTIONCONTEXT xxxxxxxxxxxxxxxx")); 66 | 67 | CX_RETURN_IF_NOT_NT_SUCCESS( 68 | RtlUnicodeStringPrintf( 69 | &name, 70 | L"NETEXECUTIONCONTEXT %p", 71 | m_handle)); 72 | 73 | CX_RETURN_IF_NOT_NT_SUCCESS(ExecutionContext::Initialize(&name)); 74 | 75 | if (m_config.EvtPreAdvance != nullptr) 76 | { 77 | RegisterPoll(&m_preAdvancePoll); 78 | } 79 | 80 | if (m_config.EvtPostAdvance != nullptr) 81 | { 82 | RegisterPoll(&m_postAdvancePoll); 83 | } 84 | 85 | RegisterNotification(&m_driverNotification); 86 | 87 | return STATUS_SUCCESS; 88 | } 89 | 90 | _Use_decl_annotations_ 91 | WDFDEVICE 92 | NxExecutionContext::GetDevice( 93 | void 94 | ) const 95 | { 96 | return m_device; 97 | } 98 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /netcx/ec/lib/activitytracker.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum class ExecutionContextEvent; 9 | enum class ExecutionContextState; 10 | enum class ExecutionContextStateChangeReason; 11 | 12 | class ActivityTracker 13 | { 14 | private: 15 | 16 | static const 17 | size_t NumberOfEntries = 64; 18 | 19 | static_assert(RTL_IS_POWER_OF_TWO(NumberOfEntries)); 20 | 21 | struct Entry 22 | { 23 | enum class Type 24 | { 25 | Event = 1, 26 | StateChange, 27 | }; 28 | 29 | Type Type; 30 | 31 | union 32 | { 33 | // Used if Type == StateChange 34 | struct 35 | { 36 | ExecutionContextStateChangeReason Reason; 37 | ExecutionContextState PreviousState; 38 | ExecutionContextState NewState; 39 | } StateChange; 40 | 41 | // Used if Type == Event 42 | struct 43 | { 44 | ExecutionContextEvent EventType; 45 | } Event; 46 | } u; 47 | }; 48 | 49 | public: 50 | 51 | _IRQL_requires_(PASSIVE_LEVEL) 52 | ActivityTracker( 53 | _In_ GUID const & Identifier 54 | ); 55 | 56 | _IRQL_requires_(PASSIVE_LEVEL) 57 | void 58 | Initialize( 59 | _In_ UNICODE_STRING const * Name 60 | ); 61 | 62 | _IRQL_requires_max_(DISPATCH_LEVEL) 63 | void 64 | LogEvent( 65 | _In_ ExecutionContextEvent Event 66 | ); 67 | 68 | _IRQL_requires_max_(DISPATCH_LEVEL) 69 | void 70 | LogStateChange( 71 | _In_ ExecutionContextStateChangeReason Reason, 72 | _In_ ExecutionContextState PreviousState, 73 | _In_ ExecutionContextState NewState 74 | ); 75 | 76 | _IRQL_requires_max_(DISPATCH_LEVEL) 77 | void 78 | LogIteration( 79 | _In_ UINT64 Work 80 | ); 81 | 82 | _IRQL_requires_max_(DISPATCH_LEVEL) 83 | void 84 | LogTask( 85 | void 86 | ); 87 | 88 | _IRQL_requires_max_(DISPATCH_LEVEL) 89 | void 90 | ResetCounters( 91 | void 92 | ); 93 | 94 | private: 95 | 96 | GUID const 97 | m_identifier; 98 | 99 | UNICODE_STRING const * 100 | m_friendlyName = nullptr; 101 | 102 | Entry 103 | m_entries[NumberOfEntries]; 104 | 105 | size_t 106 | m_entryIndex = 0; 107 | 108 | UINT64 109 | m_iterationCounter = 0; 110 | 111 | UINT64 112 | m_workCounter = 0; 113 | 114 | UINT32 115 | m_taskCounter = 0; 116 | }; 117 | -------------------------------------------------------------------------------- /netcx/translator/checksum/km/checksumkm.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "Checksum.hpp" 9 | #include "ChecksumKm.tmh" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | NTSTATUS 17 | Checksum::Initialize( 18 | void 19 | ) 20 | { 21 | NT_FRE_ASSERT(m_batchingLibContext == nullptr && m_segLibContext == nullptr); 22 | 23 | auto blContext = reinterpret_cast( 24 | ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(BATCHING_LIB_CONTEXT), 'kCxN')); 25 | CX_RETURN_NTSTATUS_IF(STATUS_INSUFFICIENT_RESOURCES, !blContext); 26 | 27 | auto slContext = reinterpret_cast( 28 | ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(SEGLIB_CONTEXT), 'kCxN')); 29 | if (!slContext) 30 | { 31 | ExFreePool(blContext); 32 | return STATUS_INSUFFICIENT_RESOURCES; 33 | } 34 | 35 | BLInitialize(blContext); 36 | m_batchingLibContext = reinterpret_cast(blContext); 37 | SegLibInitialize(blContext, slContext); 38 | m_segLibContext = reinterpret_cast(slContext); 39 | 40 | return STATUS_SUCCESS; 41 | } 42 | 43 | _Use_decl_annotations_ 44 | NTSTATUS 45 | Checksum::CalculateChecksum( 46 | NET_BUFFER * Buffer, 47 | NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO const & ChecksumInfo, 48 | NET_PACKET_LAYOUT const & PacketLayout 49 | ) 50 | { 51 | BATCHING_BUFFER_CONTEXT context; 52 | 53 | BLInitializeBatchOpContext(reinterpret_cast(m_batchingLibContext), 54 | &context, 55 | FALSE, 56 | FALSE, 57 | NULL); 58 | 59 | UINT8 const layer3HeaderOffset = PacketLayout.Layer2HeaderLength; 60 | UINT16 const layer4HeaderOffset = layer3HeaderOffset + PacketLayout.Layer3HeaderLength; 61 | 62 | // Update checksum in the headers. 63 | NTSTATUS status = SegLibDeferredChecksumPacket(&context, 64 | Buffer, 65 | ChecksumInfo, 66 | layer3HeaderOffset, 67 | layer4HeaderOffset, 68 | ChecksumInfo.Transmit.IsIPv6); 69 | 70 | BLFlushBatchOpContext(&context); 71 | 72 | return status; 73 | } 74 | 75 | Checksum::~Checksum( 76 | void 77 | ) 78 | { 79 | if (m_segLibContext) 80 | { 81 | auto slContext = reinterpret_cast(m_segLibContext); 82 | SegLibUninitialize(slContext); 83 | ExFreePool(slContext); 84 | } 85 | 86 | if (m_batchingLibContext) 87 | { 88 | auto blContext = reinterpret_cast(m_batchingLibContext); 89 | BLUninitialize(blContext); 90 | ExFreePool(blContext); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /netcx/translator/segmentation/segmentation.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #ifdef _KERNEL_MODE 8 | 9 | #include 10 | #include 11 | 12 | #else 13 | 14 | // Define mock structures for usermode. 15 | struct BATCHING_LIB_CONTEXT 16 | { 17 | }; 18 | 19 | struct SEGLIB_CONTEXT 20 | { 21 | }; 22 | 23 | #endif 24 | 25 | struct _NET_BUFFER_LIST; 26 | typedef struct _NET_BUFFER_LIST NET_BUFFER_LIST; 27 | 28 | // Wraps the segmentation operations performed by SegLib for both TCP (LSO) and UDP (USO). 29 | // Plus helpers for translator to handle LSOed and USOed NBLs. 30 | class GenericSegmentationOffload 31 | { 32 | 33 | public: 34 | 35 | _IRQL_requires_(PASSIVE_LEVEL) 36 | GenericSegmentationOffload::GenericSegmentationOffload( 37 | void 38 | ); 39 | 40 | _IRQL_requires_(PASSIVE_LEVEL) 41 | ~GenericSegmentationOffload( 42 | void 43 | ); 44 | 45 | // Perform GSO (LSO or USO) WITHOUT checksum, returns a duplicated and segmented NBL. 46 | // OutputNbl's LSO/USO info are cleared comparing to SourceNbl. 47 | _IRQL_requires_max_(DISPATCH_LEVEL) 48 | NTSTATUS 49 | PerformLso( 50 | _In_ NET_BUFFER_LIST const * SourceNbl, 51 | _In_ NET_PACKET_LAYOUT const & PacketLayout, 52 | _Out_ NET_BUFFER_LIST * & OutputNbl 53 | ); 54 | 55 | _IRQL_requires_max_(DISPATCH_LEVEL) 56 | NTSTATUS 57 | PerformUso( 58 | _In_ NET_BUFFER_LIST const * SourceNbl, 59 | _In_ NET_PACKET_LAYOUT const & PacketLayout, 60 | _Out_ NET_BUFFER_LIST * & OutputNbl 61 | ); 62 | 63 | // Free the duplicated and segmented NBL returned from PerformGso. 64 | _IRQL_requires_(PASSIVE_LEVEL) 65 | void 66 | FreeSoftwareSegmentedNetBufferList( 67 | _In_ NET_BUFFER_LIST * NetBufferList 68 | ); 69 | 70 | private: 71 | 72 | _IRQL_requires_max_(DISPATCH_LEVEL) 73 | NTSTATUS 74 | PerformGso( 75 | _In_ NET_BUFFER_LIST const * SourceNbl, 76 | _In_ NET_PACKET_LAYOUT const & PacketLayout, 77 | _In_ ULONG RequestedOffload, 78 | _Out_ NET_BUFFER_LIST * & OutputNbl 79 | ); 80 | 81 | SEGLIB_CONTEXT 82 | m_segLibContext = {}; 83 | 84 | // The NPAGED_LOOKASIDE_LIST field in BATCHING_LIB_CONTEXT_INTERNAL struct 85 | // must meet MEMORY_ALLOCATION_ALIGNMENT required by InitializeSListHead. 86 | // This alignas works because NPAGED_LOOKASIDE_LIST's offset is 0x40. 87 | alignas(MEMORY_ALLOCATION_ALIGNMENT) 88 | BATCHING_LIB_CONTEXT 89 | m_batchingLibContext = {}; 90 | 91 | // Number of live software segmented NBLs. 92 | // Used for signaling invalid freeing or NBL leaking. 93 | size_t 94 | m_nblRefcount = 0U; 95 | 96 | }; 97 | -------------------------------------------------------------------------------- /netcx/adapter/nxexecutioncontexttask.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "Nx.hpp" 6 | 7 | #include 8 | #include 9 | 10 | #include "ExecutionContextTask.hpp" 11 | 12 | 13 | // Wraps what the client driver want to run as task, so that we can 14 | // maintain EC and EcTask's reference count: 15 | // 1) increment/decrement when the task is queued/finished. 16 | // 2) increment/decrement when waiting task completion. 17 | class NxExecutionContextTask 18 | : public ExecutionContextTask 19 | { 20 | 21 | public: 22 | 23 | NxExecutionContextTask( 24 | _In_ NETEXECUTIONCONTEXT NetExecutionContextHandle, 25 | _In_ PFN_NET_EXECUTION_CONTEXT_TASK EvtTask 26 | ); 27 | 28 | _IRQL_requires_(PASSIVE_LEVEL) 29 | NTSTATUS 30 | Initialize( 31 | void 32 | ); 33 | 34 | _IRQL_requires_(PASSIVE_LEVEL) 35 | void 36 | OnDelete( 37 | void 38 | ); 39 | 40 | _IRQL_requires_max_(DISPATCH_LEVEL) 41 | NETEXECUTIONCONTEXTTASK 42 | GetHandle( 43 | void 44 | ); 45 | 46 | _IRQL_requires_max_(DISPATCH_LEVEL) 47 | void 48 | Enqueue( 49 | void 50 | ); 51 | 52 | _IRQL_requires_max_(PASSIVE_LEVEL) 53 | void 54 | WaitForCompletion( 55 | void 56 | ) override; 57 | 58 | _IRQL_requires_max_(PASSIVE_LEVEL) 59 | bool 60 | IsTaskQueued( 61 | void 62 | ); 63 | 64 | private: 65 | 66 | NETEXECUTIONCONTEXTTASK const 67 | m_handle; 68 | 69 | wil::unique_wdf_work_item 70 | m_deferredDelete; 71 | 72 | // What the driver really wants to run. 73 | PFN_NET_EXECUTION_CONTEXT_TASK 74 | m_callback; 75 | 76 | KSpinLock 77 | m_lock; 78 | 79 | _Guarded_by_(m_lock) 80 | KWaitEvent 81 | m_taskCompleted; 82 | 83 | // To prevent requeueing unfinished task. 84 | _Guarded_by_(m_lock) 85 | bool 86 | m_taskQueued = false; 87 | 88 | // Used to dereference the EC where the task is running. 89 | NETEXECUTIONCONTEXT const 90 | m_executionContext; 91 | 92 | // Used to detect if WdfObjectDelete is being called from task function 93 | PKTHREAD 94 | m_taskThread = nullptr; 95 | 96 | // Protect TaskHandler from external use by 97 | // making EvtExecutionContextTask a friend function. 98 | _IRQL_requires_max_(PASSIVE_LEVEL) 99 | void 100 | TaskHandler( 101 | void 102 | ); 103 | 104 | friend void EvtExecutionContextTask(void * TaskContext); 105 | 106 | }; 107 | 108 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(NxExecutionContextTask, GetNxExecutionContextTaskFromHandle); 109 | -------------------------------------------------------------------------------- /netcx/translator/queue.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #include 8 | 9 | class NxTranslationApp; 10 | 11 | class Queue 12 | : public NxNonpagedAllocation<'uQrT'> 13 | { 14 | 15 | public: 16 | 17 | static 18 | EVT_EXECUTION_CONTEXT_TASK 19 | EcTaskCancel; 20 | 21 | static 22 | EVT_EXECUTION_CONTEXT_SET_NOTIFICATION_ENABLED 23 | EvtSetNblNotification; 24 | 25 | _IRQL_requires_(PASSIVE_LEVEL) 26 | Queue( 27 | NxTranslationApp & App, 28 | size_t QueueId, 29 | PFN_EXECUTION_CONTEXT_POLL EvtPollQueueStarted, 30 | PFN_EXECUTION_CONTEXT_POLL EvtPollQueueStopping 31 | ) noexcept; 32 | 33 | virtual 34 | ~Queue( 35 | void 36 | ) = default; 37 | 38 | _IRQL_requires_max_(DISPATCH_LEVEL) 39 | size_t 40 | GetQueueId( 41 | void 42 | ) const; 43 | 44 | _IRQL_requires_(PASSIVE_LEVEL) 45 | void 46 | Start( 47 | void 48 | ); 49 | 50 | _IRQL_requires_max_(DISPATCH_LEVEL) 51 | bool 52 | IsStarted( 53 | void 54 | ) const; 55 | 56 | _IRQL_requires_(PASSIVE_LEVEL) 57 | void 58 | Cancel( 59 | void 60 | ); 61 | 62 | _IRQL_requires_(PASSIVE_LEVEL) 63 | bool 64 | IsStopping( 65 | void 66 | ) const; 67 | 68 | _IRQL_requires_(PASSIVE_LEVEL) 69 | void 70 | Stop( 71 | void 72 | ); 73 | 74 | protected: 75 | 76 | NxTranslationApp & 77 | m_app; 78 | 79 | NET_CLIENT_QUEUE 80 | m_queue = nullptr; 81 | 82 | NET_CLIENT_QUEUE_DISPATCH const * 83 | m_queueDispatch = nullptr; 84 | 85 | // 86 | // Executing Tx/Rx datapath logic as polling work in EC. 87 | // 88 | 89 | NET_EXECUTION_CONTEXT 90 | m_executionContext = nullptr; 91 | 92 | NET_EXECUTION_CONTEXT_DISPATCH const * 93 | m_executionContextDispatch = nullptr; 94 | 95 | EXECUTION_CONTEXT_POLL 96 | m_executionContextPoll; 97 | 98 | EXECUTION_CONTEXT_NOTIFICATION 99 | m_nblNotification; 100 | 101 | _Interlocked_ volatile 102 | LONG 103 | m_nblNotificationEnabled = 0; 104 | 105 | PFN_EXECUTION_CONTEXT_POLL const 106 | m_pollQueueStarted; 107 | 108 | PFN_EXECUTION_CONTEXT_POLL const 109 | m_pollQueueStopping; 110 | 111 | // 112 | // To signal the completion of client queue Stop() 113 | // 114 | KWaitEvent 115 | m_readyToStop; 116 | 117 | private: 118 | 119 | bool 120 | m_started = false; 121 | 122 | bool 123 | m_stopping = false; 124 | 125 | size_t const 126 | m_queueId = SIZE_T_MAX; 127 | }; 128 | 129 | -------------------------------------------------------------------------------- /netcx/bm/bufferheader.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include 5 | 6 | class BufferPool2; 7 | 8 | static const ULONG 9 | BufferSignature = 0xa60c; 10 | 11 | class BufferHeader 12 | { 13 | #ifdef TEST_HARNESS_CLASS_NAME 14 | friend class 15 | TEST_HARNESS_CLASS_NAME; 16 | #endif 17 | 18 | public: 19 | 20 | _IRQL_requires_max_(DISPATCH_LEVEL) 21 | static 22 | BufferHeader * 23 | FromListEntry( 24 | LIST_ENTRY * ListEntry 25 | ); 26 | 27 | _IRQL_requires_max_(DISPATCH_LEVEL) 28 | static 29 | BufferHeader * 30 | FromMdl( 31 | MDL * Mdl 32 | ); 33 | 34 | _IRQL_requires_(PASSIVE_LEVEL) 35 | BufferHeader( 36 | _In_ LIST_ENTRY * FreeListHead, 37 | _In_ LIST_ENTRY * UsedListHead, 38 | _In_ UINT64 BaseLogicalAddress, 39 | _In_ SIZE_T BufferSize, 40 | _In_ SIZE_T BufferOffset, 41 | _In_ SIZE_T BufferPaddingSize 42 | ); 43 | 44 | _IRQL_requires_(PASSIVE_LEVEL) 45 | NTSTATUS 46 | Initialize( 47 | void 48 | ); 49 | 50 | _IRQL_requires_max_(DISPATCH_LEVEL) 51 | void 52 | ASSERT_VALID( 53 | void 54 | ) const; 55 | 56 | _IRQL_requires_max_(DISPATCH_LEVEL) 57 | void * 58 | GetVirtualAddress( 59 | void 60 | ) const; 61 | 62 | _IRQL_requires_max_(DISPATCH_LEVEL) 63 | UINT64 64 | GetLogicalAddress( 65 | void 66 | ) const; 67 | 68 | _IRQL_requires_max_(DISPATCH_LEVEL) 69 | void 70 | MarkAsUsed( 71 | void 72 | ); 73 | 74 | _IRQL_requires_max_(DISPATCH_LEVEL) 75 | void 76 | Reference( 77 | void 78 | ); 79 | 80 | _IRQL_requires_max_(DISPATCH_LEVEL) 81 | void 82 | Dereference( 83 | void 84 | ); 85 | 86 | _IRQL_requires_max_(DISPATCH_LEVEL) 87 | void 88 | Free( 89 | void 90 | ); 91 | 92 | _IRQL_requires_max_(DISPATCH_LEVEL) 93 | MDL * 94 | GetMdl( 95 | void 96 | ); 97 | 98 | private: 99 | 100 | ULONG const 101 | m_signature1 = BufferSignature; 102 | 103 | struct 104 | { 105 | ULONG 106 | Freed : 1; 107 | 108 | ULONG 109 | NotUsed : 31; 110 | } m_flags = {}; 111 | 112 | LIST_ENTRY 113 | m_linkage = {}; 114 | 115 | LIST_ENTRY * const 116 | m_freeListHead; 117 | 118 | LIST_ENTRY * const 119 | m_usedListHead; 120 | 121 | UINT64 122 | m_baseLogicalAddress; 123 | 124 | SIZE_T const 125 | m_bufferSize; 126 | 127 | SIZE_T const 128 | m_bufferOffset; 129 | 130 | SIZE_T const 131 | m_bufferPaddingSize; 132 | 133 | KPoolPtrNP 134 | m_mdl; 135 | 136 | ULONG 137 | m_referenceCount = 0; 138 | 139 | ULONG const 140 | m_signature2 = BufferSignature; 141 | }; 142 | -------------------------------------------------------------------------------- /rtl/inc/kmacros.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | #ifdef _KERNEL_MODE 8 | 9 | // nullptr_t is normally automatically defined by the CRT headers, but it 10 | // doesn't get included by kernel code. 11 | namespace std { typedef decltype(__nullptr) nullptr_t; } 12 | using ::std::nullptr_t; 13 | 14 | // The stddef.h used for kernel code has the old offsetof macro. 15 | // Let's use the new one instead. 16 | #undef offsetof 17 | #define offsetof(s,m) __builtin_offsetof(s,m) 18 | 19 | #endif // _KERNEL_MODE 20 | 21 | #define BEGIN_MACRO do { 22 | #define END_MACRO } while (0) 23 | 24 | #ifdef _KERNEL_MODE 25 | #define CODE_SEG(segment) __declspec(code_seg(segment)) 26 | #else 27 | #define CODE_SEG(segment) 28 | #endif 29 | 30 | #ifndef KRTL_PAGE_SEGMENT 31 | # define KRTL_PAGE_SEGMENT "PAGE" 32 | #endif 33 | #ifndef KRTL_INIT_SEGMENT 34 | # define KRTL_INIT_SEGMENT "INIT" 35 | #endif 36 | #ifndef KRTL_NONPAGED_SEGMENT 37 | # define KRTL_NONPAGED_SEGMENT ".text" 38 | #endif 39 | 40 | /// Use on pageable functions. 41 | #define PAGED CODE_SEG(KRTL_PAGE_SEGMENT) _IRQL_always_function_max_(PASSIVE_LEVEL) 42 | 43 | /// Use on pageable functions, where you don't want the SAL IRQL annotation to say PASSIVE_LEVEL. 44 | #define PAGEDX CODE_SEG(KRTL_PAGE_SEGMENT) 45 | 46 | /// Use on code in the INIT segment. (Code is discarded after DriverEntry returns.) 47 | #define INITCODE CODE_SEG(KRTL_INIT_SEGMENT) 48 | 49 | /// Use on code that must always be locked in memory. 50 | #define NONPAGED CODE_SEG(KRTL_NONPAGED_SEGMENT) _IRQL_requires_max_(DISPATCH_LEVEL) 51 | 52 | /// Use on code that must always be locked in memory, where you don't want SAL IRQL annotations. 53 | #define NONPAGEDX CODE_SEG(KRTL_NONPAGED_SEGMENT) 54 | 55 | #ifndef _KERNEL_MODE 56 | 57 | #ifndef PAGED_CODE 58 | #define PAGED_CODE() (void)0 59 | #endif // PAGED_CODE 60 | 61 | #endif // _KERNEL_MODE 62 | 63 | /// Use on classes or structs. Class member functions & compiler-generated code 64 | /// will default to the PAGE segment. You can override any member function with `NONPAGED`. 65 | #define KRTL_CLASS CODE_SEG(KRTL_PAGE_SEGMENT) __declspec(empty_bases) 66 | 67 | /// Use on classes or structs. Class member functions & compiler-generated code 68 | /// will default to the NONPAGED segment. You can override any member function with `PAGED`. 69 | #define KRTL_CLASS_DPC_ALLOC __declspec(empty_bases) 70 | 71 | enum CallRunMode 72 | { 73 | // This call should complete synchronously on the current thread 74 | RunSynchronous, 75 | // This call should return immediately, and complete the operation in a background thread 76 | RunAsynchronous, 77 | // This call can return immediately, OR complete synchronously 78 | // (Use this if you're running on a workitem thread already, and you 79 | // don't mind if the callee uses your thread to do its work, but you 80 | // can tolerate the call completing asynchronously if the callee doesn't 81 | // need your thread.) 82 | RunAsynchronousButOkayToBlock, 83 | }; 84 | 85 | -------------------------------------------------------------------------------- /netcx/adapter/powerpolicy/nxpoweroffload.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #include "NxPowerEntry.hpp" 5 | 6 | class NxPowerOffload : public NxPowerEntry 7 | { 8 | 9 | public: 10 | 11 | NxPowerOffload( 12 | _In_ NET_POWER_OFFLOAD_TYPE Type, 13 | _In_ NETADAPTER Adapter, 14 | _In_ ULONG Id 15 | ); 16 | 17 | NETPOWEROFFLOAD 18 | GetHandle( 19 | void 20 | ); 21 | 22 | NET_POWER_OFFLOAD_TYPE 23 | GetType( 24 | void 25 | ) const; 26 | 27 | ULONG 28 | GetID( 29 | void 30 | ) const; 31 | 32 | protected: 33 | 34 | NET_POWER_OFFLOAD_TYPE const 35 | m_type; 36 | 37 | ULONG const 38 | m_id; 39 | }; 40 | 41 | class NxArpOffload : public NxPowerOffload 42 | { 43 | 44 | public: 45 | 46 | static 47 | NTSTATUS 48 | CreateFromNdisPmOffload( 49 | _In_ NETADAPTER Adapter, 50 | _In_ NDIS_PM_PROTOCOL_OFFLOAD const * NdisPmOffload, 51 | _Outptr_result_nullonfailure_ NxPowerOffload ** ArpOffload 52 | ); 53 | 54 | public: 55 | 56 | NxArpOffload( 57 | _In_ NETADAPTER Adapter, 58 | _In_ ULONG Id, 59 | _In_ NET_IPV4_ADDRESS RemoteIPv4Address, 60 | _In_ NET_IPV4_ADDRESS HostIPv4Address, 61 | _In_ NET_ADAPTER_LINK_LAYER_ADDRESS LinkLayerAddress 62 | ); 63 | 64 | void 65 | GetParameters( 66 | _Inout_ NET_POWER_OFFLOAD_ARP_PARAMETERS * Parameters 67 | ) const; 68 | 69 | private: 70 | 71 | NET_IPV4_ADDRESS const 72 | m_remoteIPv4Address; 73 | 74 | NET_IPV4_ADDRESS const 75 | m_hostIPv4Address; 76 | 77 | NET_ADAPTER_LINK_LAYER_ADDRESS const 78 | m_linkLayerAddress; 79 | 80 | }; 81 | 82 | class NxNSOffload : public NxPowerOffload 83 | { 84 | 85 | public: 86 | 87 | static 88 | NTSTATUS 89 | CreateFromNdisPmOffload( 90 | _In_ NETADAPTER Adapter, 91 | _In_ NDIS_PM_PROTOCOL_OFFLOAD const * NdisPmOffload, 92 | _Outptr_result_nullonfailure_ NxPowerOffload ** NSOffload 93 | ); 94 | 95 | public: 96 | 97 | NxNSOffload( 98 | _In_ NETADAPTER Adapter, 99 | _In_ ULONG Id, 100 | _In_ NET_IPV6_ADDRESS RemoteIPv6Address, 101 | _In_ NET_IPV6_ADDRESS SolicitedNodeIPv6Address, 102 | _In_ NET_IPV6_ADDRESS TargetIPv6Addresses0, 103 | _In_ NET_IPV6_ADDRESS TargetIPv6Addresses1, 104 | _In_ NET_ADAPTER_LINK_LAYER_ADDRESS LinkLayerAddress 105 | ); 106 | 107 | void 108 | GetParameters( 109 | _Inout_ NET_POWER_OFFLOAD_NS_PARAMETERS * Parameters 110 | ) const; 111 | 112 | private: 113 | 114 | NET_IPV6_ADDRESS const 115 | m_remoteIPv6Address; 116 | 117 | NET_IPV6_ADDRESS const 118 | m_solicitedNodeIPv6Address; 119 | 120 | NET_IPV6_ADDRESS const 121 | m_targetIPv6Addresses[2]; 122 | 123 | NET_ADAPTER_LINK_LAYER_ADDRESS const 124 | m_linkLayerAddress; 125 | }; 126 | -------------------------------------------------------------------------------- /netcx/bm/bufferpool.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "KPtr.h" 6 | #include "KBitmap.h" 7 | #include "kStackstorage.h" 8 | #include "BufferHeader.hpp" 9 | #include "IBufferVector.hpp" 10 | #include "IBufferVectorAllocator.hpp" 11 | 12 | typedef struct _NET_DATA_REF 13 | { 14 | UINT32 OsRefCount; 15 | BOOLEAN OsOwned; 16 | } NET_DATA_REF; 17 | 18 | class PAGED BufferPool : 19 | public KStackPool // 'nxbp' 20 | { 21 | 22 | public: 23 | 24 | ~BufferPool( 25 | void 26 | ); 27 | 28 | NTSTATUS 29 | Fill( 30 | _In_ IBufferVector* BufferVector 31 | ); 32 | 33 | NONPAGED 34 | NTSTATUS 35 | Allocate( 36 | _Out_ SIZE_T * BufferIndex 37 | ); 38 | 39 | NONPAGED 40 | VOID 41 | AddRef( 42 | _In_ size_t BufferIndex 43 | ); 44 | 45 | NONPAGED 46 | VOID 47 | DeRef( 48 | _In_ size_t BufferIndex 49 | ); 50 | 51 | NONPAGED 52 | VOID 53 | Free( 54 | _In_ size_t BufferIndex 55 | ); 56 | 57 | NONPAGED 58 | VOID 59 | Preview( 60 | _In_ size_t BufferIndex, 61 | _Out_ NET_DATA_HEADER* NetDataHeader 62 | ); 63 | 64 | NONPAGED 65 | VOID 66 | OwnedByOs( 67 | _In_ size_t BufferIndex 68 | ); 69 | 70 | void 71 | Enumerate( 72 | _In_ ENUMERATE_CALLBACK Callback, 73 | _In_ void* Context 74 | ); 75 | 76 | size_t 77 | GetOffset(); 78 | 79 | size_t 80 | GetCapacity(); 81 | 82 | size_t 83 | GetPoolSize(); 84 | 85 | private: 86 | 87 | size_t 88 | m_PoolSize = 0; 89 | 90 | wistd::unique_ptr 91 | m_BufferVector; 92 | 93 | Rtl::KArray 94 | m_BuffersRef; 95 | 96 | Rtl::KBitmap 97 | m_BuffersInUseFlag; 98 | }; 99 | 100 | class BufferPool2 : public NONPAGED_OBJECT<'2lPB'> 101 | { 102 | #ifdef TEST_HARNESS_CLASS_NAME 103 | friend class 104 | TEST_HARNESS_CLASS_NAME; 105 | #endif 106 | 107 | public: 108 | 109 | _IRQL_requires_(PASSIVE_LEVEL) 110 | BufferPool2( 111 | _In_ size_t BufferSize, 112 | _In_ size_t BufferAlignment 113 | ); 114 | 115 | _IRQL_requires_max_(DISPATCH_LEVEL) 116 | ~BufferPool2( 117 | void 118 | ); 119 | 120 | _IRQL_requires_(PASSIVE_LEVEL) 121 | NTSTATUS 122 | Initialize( 123 | _In_ IBufferVectorAllocator * Allocator, 124 | _In_ size_t InitialNumberOfBuffers 125 | ); 126 | 127 | _IRQL_requires_max_(DISPATCH_LEVEL) 128 | BufferHeader * 129 | Allocate( 130 | void 131 | ); 132 | 133 | private: 134 | 135 | wistd::unique_ptr 136 | m_bufferVector; 137 | 138 | size_t const 139 | m_bufferSize; 140 | 141 | size_t const 142 | m_bufferAlignment; 143 | 144 | LIST_ENTRY 145 | m_freeBufferList; 146 | 147 | LIST_ENTRY 148 | m_usedBufferList; 149 | }; 150 | -------------------------------------------------------------------------------- /netcx/ec/lib/dpc.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | template 5 | class EcDpc 6 | { 7 | public: 8 | 9 | using DpcRoutine = void (*)(ContextType*); 10 | 11 | _IRQL_requires_(PASSIVE_LEVEL) 12 | EcDpc( 13 | _In_ DpcRoutine ExternalDpcRoutine, 14 | _In_ ContextType * Context 15 | ) 16 | : m_externalDpcRoutine(ExternalDpcRoutine) 17 | , m_context(Context) 18 | { 19 | #ifdef _KERNEL_MODE 20 | KeInitializeDpc( 21 | &m_dpc, 22 | EcDpc::InternalDpcRoutine, 23 | this); 24 | #else 25 | m_mockDpc = CreateThreadpoolWork( 26 | EcDpc::InternalDpcRoutine, 27 | this, 28 | nullptr); 29 | 30 | FAIL_FAST_IF_MSG(m_mockDpc == nullptr, "Failed to create threadpool work to mock DPC"); 31 | #endif 32 | } 33 | 34 | #ifndef _KERNEL_MODE 35 | ~EcDpc( 36 | void 37 | ) 38 | { 39 | if (m_mockDpc != nullptr) 40 | { 41 | CloseThreadpoolWork(m_mockDpc); 42 | } 43 | } 44 | #endif 45 | 46 | // Queues a new DPC 47 | _IRQL_requires_max_(HIGH_LEVEL) 48 | bool 49 | InsertQueueDpc( 50 | void 51 | ) 52 | { 53 | #ifdef _KERNEL_MODE 54 | return KeInsertQueueDpc(&m_dpc, NULL, NULL); 55 | #else 56 | SubmitThreadpoolWork(m_mockDpc); 57 | return true; 58 | #endif 59 | } 60 | 61 | _IRQL_requires_max_(HIGH_LEVEL) 62 | NTSTATUS 63 | SetTargetProcessorDpcEx( 64 | _In_ const PPROCESSOR_NUMBER ProcessorNumber 65 | ) 66 | { 67 | #ifdef _KERNEL_MODE 68 | return KeSetTargetProcessorDpcEx(&m_dpc, ProcessorNumber); 69 | #else 70 | UNREFERENCED_PARAMETER(ProcessorNumber); 71 | return STATUS_UNSUCCESSFUL; 72 | #endif 73 | } 74 | 75 | private: 76 | 77 | #ifdef _KERNEL_MODE 78 | static 79 | void 80 | InternalDpcRoutine( 81 | PKDPC Dpc, 82 | PVOID DeferredContext, 83 | PVOID SystemArgument1, 84 | PVOID SystemArgument2 85 | ) 86 | { 87 | UNREFERENCED_PARAMETER(Dpc); 88 | UNREFERENCED_PARAMETER(SystemArgument1); 89 | UNREFERENCED_PARAMETER(SystemArgument2); 90 | 91 | auto internalContext = static_cast(DeferredContext); 92 | internalContext->m_externalDpcRoutine(internalContext->m_context); 93 | } 94 | 95 | KDPC 96 | m_dpc{}; 97 | #else 98 | static 99 | void 100 | InternalDpcRoutine( 101 | _Inout_ PTP_CALLBACK_INSTANCE Instance, 102 | _Inout_opt_ void * Context, 103 | _Inout_ PTP_WORK Work 104 | ) 105 | { 106 | UNREFERENCED_PARAMETER((Instance, Work)); 107 | auto internalContext = static_cast(Context); 108 | internalContext->m_externalDpcRoutine(internalContext->m_context); 109 | } 110 | 111 | PTP_WORK 112 | m_mockDpc{}; 113 | #endif 114 | 115 | DpcRoutine const 116 | m_externalDpcRoutine; 117 | 118 | ContextType * const 119 | m_context; 120 | }; 121 | -------------------------------------------------------------------------------- /netcx/ec/lib/timebudgetwarninglogger.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include "precompiled.hpp" 4 | #include "TimeBudgetWarningLogger.h" 5 | #include "EcEvents.h" 6 | 7 | static const ULONG MS_TO_TIME_INCREMENT_MULT = 10ul * 1000ul; 8 | 9 | #ifndef _KERNEL_MODE 10 | ULONG KeQueryTimeIncrement() 11 | { 12 | return 1L; 13 | } 14 | 15 | VOID KeQueryTickCount ( 16 | _Out_ PLARGE_INTEGER CurrentCount 17 | ) 18 | { 19 | CurrentCount->QuadPart = 0L; 20 | } 21 | #endif 22 | 23 | PAGED 24 | TimeBudgetWarningLogger::TimeBudgetWarningLogger( 25 | const GUID& ClientIdentifier, 26 | const ULONG DispatchTimeWarningInterval 27 | ) 28 | : m_reportIntervalTicks(DispatchTimeWarningInterval * MS_TO_TIME_INCREMENT_MULT / KeQueryTimeIncrement()) 29 | , m_clientIdentifier(ClientIdentifier) 30 | , m_dispatchTimeWarningIntervalMs(DispatchTimeWarningInterval) 31 | { 32 | } 33 | 34 | PAGED 35 | void TimeBudgetWarningLogger::SetWatermark( 36 | _In_ ULONG DispatchIrqlWarningWatermarkMs 37 | ) 38 | { 39 | m_watermarkTicks = DispatchIrqlWarningWatermarkMs * MS_TO_TIME_INCREMENT_MULT / KeQueryTimeIncrement(); 40 | m_watermarkMs = DispatchIrqlWarningWatermarkMs; 41 | } 42 | 43 | NONPAGED 44 | void TimeBudgetWarningLogger::LogWarningIfOvertime( 45 | _In_ const TimeBudget& timeBudget 46 | ) 47 | { 48 | const auto totalTimeInDispatch = timeBudget.TotalTimeInDispatch(); 49 | if (m_watermarkTicks == 0 || totalTimeInDispatch == 0) 50 | { 51 | return; 52 | } 53 | 54 | if (totalTimeInDispatch >= m_watermarkTicks) 55 | { 56 | m_iterationsOverTimeCount++; 57 | } 58 | 59 | LARGE_INTEGER currentSystemTimeTicks; 60 | KeQueryTickCount(¤tSystemTimeTicks); 61 | 62 | if (currentSystemTimeTicks.QuadPart > m_nextReportingDeadlineTicks.QuadPart) 63 | { 64 | if (m_iterationsOverTimeCount != 0) 65 | { 66 | ULONG timeSinceLastReportMs = 0; 67 | if (m_nextReportingDeadlineTicks.QuadPart != 0) 68 | { 69 | auto overtimeTicks = static_cast(currentSystemTimeTicks.QuadPart - m_nextReportingDeadlineTicks.QuadPart); 70 | timeSinceLastReportMs = overtimeTicks * KeQueryTimeIncrement() / MS_TO_TIME_INCREMENT_MULT; 71 | timeSinceLastReportMs += m_dispatchTimeWarningIntervalMs; 72 | } 73 | 74 | ReportWarning(timeSinceLastReportMs); 75 | 76 | m_nextReportingDeadlineTicks.QuadPart = currentSystemTimeTicks.QuadPart + m_reportIntervalTicks; 77 | m_iterationsOverTimeCount = 0; 78 | } 79 | } 80 | } 81 | 82 | NONPAGED 83 | void TimeBudgetWarningLogger::ReportWarning(ULONG TimeSinceLastReportMs) 84 | { 85 | EventWriteExecutionTimeExceededWarning( 86 | &m_clientIdentifier, 87 | m_friendlyEcName->Buffer, 88 | m_watermarkMs, 89 | m_iterationsOverTimeCount, 90 | TimeSinceLastReportMs 91 | ); 92 | } 93 | 94 | PAGED 95 | void TimeBudgetWarningLogger::SetFriendlyName( 96 | UNICODE_STRING const * FriendlyName 97 | ) 98 | { 99 | m_friendlyEcName = FriendlyName; 100 | } 101 | -------------------------------------------------------------------------------- /netcx/adapter/powerpolicy/nxpowerlist.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #include "precompiled.hpp" 3 | 4 | #include "NxPowerList.hpp" 5 | #include "NxPowerPolicy.hpp" 6 | 7 | #include "NxPowerList.tmh" 8 | 9 | _Use_decl_annotations_ 10 | NxPowerOffloadList const * 11 | GetNxPowerListFromOffloadList( 12 | NET_POWER_OFFLOAD_LIST const * List 13 | ) 14 | { 15 | auto powerList = reinterpret_cast(&List->Reserved[0]); 16 | NT_FRE_ASSERT(powerList->Signature == NX_POWER_OFFLOAD_LIST_SIGNATURE); 17 | return powerList; 18 | } 19 | 20 | _Use_decl_annotations_ 21 | NxWakeSourceList const * 22 | GetNxPowerListFromWakeList( 23 | NET_WAKE_SOURCE_LIST const * List 24 | ) 25 | { 26 | auto powerList = reinterpret_cast(&List->Reserved[0]); 27 | NT_FRE_ASSERT(powerList->Signature == NX_WAKE_SOURCE_LIST_SIGNATURE); 28 | return powerList; 29 | } 30 | 31 | _Use_decl_annotations_ 32 | NxPowerList::NxPowerList( 33 | ULONG TypeSignature 34 | ) 35 | : Signature(TypeSignature) 36 | { 37 | } 38 | 39 | size_t 40 | NxPowerList::GetCount( 41 | void 42 | ) const 43 | { 44 | return m_count; 45 | } 46 | 47 | _Use_decl_annotations_ 48 | void 49 | NxPowerList::PushEntry( 50 | NxPowerEntry * Entry 51 | ) 52 | { 53 | PushEntryList(&m_listHead, &Entry->m_clientListLinkage); 54 | m_count++; 55 | } 56 | 57 | NxPowerOffloadList::NxPowerOffloadList( 58 | void 59 | ) noexcept 60 | : NxPowerList(NX_POWER_OFFLOAD_LIST_SIGNATURE) 61 | { 62 | } 63 | 64 | _Use_decl_annotations_ 65 | void * 66 | NxPowerOffloadList::operator new( 67 | size_t, 68 | NET_POWER_OFFLOAD_LIST * NetPowerOffloadList 69 | ) 70 | { 71 | return &NetPowerOffloadList->Reserved[0]; 72 | } 73 | 74 | NxWakeSourceList::NxWakeSourceList( 75 | void 76 | ) noexcept 77 | : NxPowerList(NX_WAKE_SOURCE_LIST_SIGNATURE) 78 | { 79 | } 80 | 81 | _Use_decl_annotations_ 82 | void * 83 | NxWakeSourceList::operator new( 84 | size_t, 85 | NET_WAKE_SOURCE_LIST * NetWakeSourceList 86 | ) 87 | { 88 | return &NetWakeSourceList->Reserved[0]; 89 | } 90 | 91 | _Use_decl_annotations_ 92 | NxWakeSource * 93 | NxWakeSourceList::GetWakeSourceByIndex( 94 | size_t Index 95 | ) const 96 | { 97 | size_t i = 0; 98 | 99 | for ( 100 | auto link = m_listHead.Next; 101 | link != nullptr; 102 | link = link->Next 103 | ) 104 | { 105 | if (i == Index) 106 | { 107 | return CONTAINING_RECORD(link, NxWakeSource, m_clientListLinkage); 108 | } 109 | 110 | i++; 111 | } 112 | 113 | return nullptr; 114 | } 115 | 116 | NxPowerOffload * 117 | NxPowerOffloadList::GetPowerOffloadByIndex( 118 | _In_ size_t Index 119 | ) const 120 | { 121 | size_t i = 0; 122 | 123 | for (auto link = m_listHead.Next; link != nullptr; link = link->Next) 124 | { 125 | if (i == Index) 126 | { 127 | return CONTAINING_RECORD(link, NxPowerOffload, m_clientListLinkage); 128 | } 129 | 130 | i++; 131 | } 132 | 133 | return nullptr; 134 | } 135 | -------------------------------------------------------------------------------- /netcx/translator/nxstatistics.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include "NxXlatPrecomp.hpp" 4 | #include "NxXlatCommon.hpp" 5 | 6 | #include "NxStatistics.tmh" 7 | #include "NxStatistics.hpp" 8 | 9 | _Use_decl_annotations_ 10 | void 11 | NxRxCounters::Add( 12 | _In_ const NxRxCounters & rxCounters 13 | ) 14 | { 15 | Perf.IterationCount += rxCounters.Perf.IterationCount; 16 | Perf.QueueDepth += rxCounters.Perf.QueueDepth; 17 | Perf.NblPending += rxCounters.Perf.NblPending; 18 | Perf.PacketsCompleted += rxCounters.Perf.PacketsCompleted; 19 | } 20 | 21 | _Use_decl_annotations_ 22 | void 23 | NxRxCounters::GetPerfCounter(NETADAPTER_QUEUE_PC & perfCounter) const 24 | { 25 | perfCounter.IterationCount = Perf.IterationCount; 26 | perfCounter.QueueDepth = Perf.QueueDepth; 27 | perfCounter.NblPending = Perf.NblPending; 28 | perfCounter.PacketsCompleted = Perf.PacketsCompleted; 29 | perfCounter.IterationCountBase = static_cast(perfCounter.IterationCount); 30 | } 31 | 32 | _Use_decl_annotations_ 33 | void 34 | NxTxCounters::Add( 35 | _In_ const NxTxCounters & txCounters 36 | ) 37 | { 38 | Perf.IterationCount += txCounters.Perf.IterationCount; 39 | Perf.QueueDepth += txCounters.Perf.QueueDepth; 40 | Perf.NblPending += txCounters.Perf.NblPending; 41 | Perf.PacketsCompleted += txCounters.Perf.PacketsCompleted; 42 | 43 | Packet.BounceSuccess += txCounters.Packet.BounceSuccess; 44 | Packet.BounceFailure += txCounters.Packet.BounceFailure; 45 | Packet.CannotTranslate += txCounters.Packet.CannotTranslate; 46 | Packet.UnalignedBuffer += txCounters.Packet.UnalignedBuffer; 47 | 48 | DMA.InsufficientResources += txCounters.DMA.InsufficientResources; 49 | DMA.BufferTooSmall += txCounters.DMA.BufferTooSmall; 50 | DMA.CannotMapSglToFragments += txCounters.DMA.CannotMapSglToFragments; 51 | DMA.PhysicalAddressTooLarge += txCounters.DMA.PhysicalAddressTooLarge; 52 | DMA.OtherErrors += txCounters.DMA.OtherErrors; 53 | } 54 | 55 | _Use_decl_annotations_ 56 | void 57 | NxTxCounters::GetPerfCounter(NETADAPTER_QUEUE_PC & perfCounter) const 58 | { 59 | perfCounter.IterationCount = Perf.IterationCount; 60 | perfCounter.QueueDepth = Perf.QueueDepth; 61 | perfCounter.NblPending = Perf.NblPending; 62 | perfCounter.PacketsCompleted = Perf.PacketsCompleted; 63 | perfCounter.IterationCountBase = static_cast(perfCounter.IterationCount); 64 | } 65 | 66 | _Use_decl_annotations_ 67 | const NxTxCounters & 68 | NxStatistics::GetTxCounters( 69 | void 70 | ) const 71 | { 72 | return m_txStatistics; 73 | } 74 | 75 | _Use_decl_annotations_ 76 | const NxRxCounters & 77 | NxStatistics::GetRxCounters( 78 | void 79 | ) const 80 | { 81 | return m_rxStatistics; 82 | } 83 | 84 | _Use_decl_annotations_ 85 | void 86 | NxStatistics::UpdateRxCounters( 87 | _In_ const NxRxCounters & rxCounters 88 | ) 89 | { 90 | m_rxStatistics.Add(rxCounters); 91 | } 92 | 93 | _Use_decl_annotations_ 94 | void 95 | NxStatistics::UpdateTxCounters( 96 | _In_ const NxTxCounters & txCounters 97 | ) 98 | { 99 | m_txStatistics.Add(txCounters); 100 | } 101 | -------------------------------------------------------------------------------- /netcx/translator/framelayout/layer3layout.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | namespace Layer3 8 | { 9 | 10 | bool 11 | ParseLayout( 12 | _Inout_ NET_PACKET_LAYOUT & Layout, 13 | _In_ UINT8 const * Pointer, 14 | _Inout_ size_t & Offset, 15 | _Inout_ size_t & Length 16 | ); 17 | 18 | bool 19 | ParseIPv4orIPv6Layout( 20 | _Inout_ NET_PACKET_LAYOUT & Layout, 21 | _In_ UINT8 const * Pointer, 22 | _Inout_ size_t & Offset, 23 | _Inout_ size_t & Length 24 | ); 25 | 26 | enum class Protocol : UINT8 27 | { 28 | ICMPv4 = 0x01, 29 | TCP = 0x06, 30 | UDP = 0x11, 31 | }; 32 | 33 | union IPv4 34 | { 35 | struct { 36 | UINT8 37 | HeaderLength:4; 38 | UINT8 39 | Version:4; 40 | UINT8 41 | DifferentiatedServices; 42 | UINT16 43 | TotalLength; 44 | UINT32 45 | Unused0; 46 | UINT8 47 | TimeToLive; 48 | UINT8 49 | Protocol; 50 | UINT16 51 | Checksum; 52 | UINT32 53 | Unused1; 54 | UINT32 55 | Unused2; 56 | } Header; 57 | 58 | static_assert(sizeof(Header) == 20U); 59 | 60 | UINT8 61 | Value[sizeof(Header)]; 62 | 63 | }; 64 | 65 | bool 66 | ParseIPv4Layout( 67 | _Inout_ NET_PACKET_LAYOUT & Layout, 68 | _In_ UINT8 const * Pointer, 69 | _Inout_ size_t & Offset, 70 | _Inout_ size_t & Length 71 | ); 72 | 73 | enum class NextHeader : UINT8 74 | { 75 | ICMPv4 = Protocol::ICMPv4, 76 | TCP = Protocol::TCP, 77 | UDP = Protocol::UDP, 78 | ICMPv6 = 58, 79 | NoNextHeader = 59, 80 | }; 81 | 82 | union IPv6 83 | { 84 | struct { 85 | union 86 | { 87 | struct { 88 | UINT8 89 | Reserved1:4; 90 | UINT8 91 | Version:4; 92 | UINT16 93 | Reserved2; 94 | } VersionClassFlow; 95 | 96 | UINT32 97 | Reserved3; 98 | }; 99 | 100 | UINT16 101 | Length; 102 | UINT8 103 | NextHeader; 104 | UINT8 105 | HopLimit; 106 | UINT64 107 | SourceAddress[2]; 108 | UINT64 109 | DestinationAddress[2]; 110 | } Header; 111 | 112 | static_assert(sizeof(Header) == 40U); 113 | 114 | UINT8 115 | Value[sizeof(Header)]; 116 | }; 117 | 118 | union IPv6Extension 119 | { 120 | struct { 121 | UINT8 122 | NextHeader; 123 | UINT8 124 | Length; 125 | UINT16 126 | Reserved0; 127 | UINT32 128 | Reserved1; 129 | } Header; 130 | 131 | static_assert(sizeof(Header) == 8U); 132 | 133 | UINT8 134 | Value[sizeof(Header)]; 135 | }; 136 | 137 | bool 138 | ParseIPv6Layout( 139 | _Inout_ NET_PACKET_LAYOUT & Layout, 140 | _In_ UINT8 const * Pointer, 141 | _Inout_ size_t & Offset, 142 | _Inout_ size_t & Length 143 | ); 144 | 145 | } 146 | -------------------------------------------------------------------------------- /netcx/translator/txpeeraddressdemux.cpp: -------------------------------------------------------------------------------- 1 | #include "NxXlatPrecomp.hpp" 2 | #include "NxXlatCommon.hpp" 3 | 4 | #include "TxPeerAddressDemux.tmh" 5 | #include "TxPeerAddressDemux.hpp" 6 | 7 | #pragma warning(push) 8 | #pragma warning(disable:4201) // nonstandard extension used: nameless struct/union 9 | #include <80211hdr.h> 10 | #pragma warning(pop) 11 | 12 | #include "NxTranslationApp.hpp" 13 | 14 | static 15 | NET_CLIENT_EUI48_ADDRESS const * 16 | ParsePeerAddress( 17 | NET_BUFFER_LIST const * NetBufferList 18 | ) 19 | { 20 | auto const nb = NetBufferList->FirstNetBuffer; 21 | auto const mdl = nb->CurrentMdl; 22 | auto const size = MmGetMdlByteCount(mdl) - nb->CurrentMdlOffset; 23 | auto const pointer = static_cast( 24 | MmGetSystemAddressForMdlSafe(mdl, LowPagePriority | MdlMappingNoExecute)); 25 | auto const header = reinterpret_cast(&pointer[nb->CurrentMdlOffset]); 26 | 27 | if (size >= sizeof(*header)) 28 | { 29 | return reinterpret_cast(header->Address1); 30 | } 31 | 32 | return nullptr; 33 | } 34 | 35 | TxPeerAddressDemux::TxPeerAddressDemux( 36 | size_t Range, 37 | NxTranslationApp const & App 38 | ) noexcept 39 | : NxTxDemux(NxTxDemux::Type::Peer, Range) 40 | , m_app(App) 41 | { 42 | } 43 | 44 | _Use_decl_annotations_ 45 | size_t 46 | TxPeerAddressDemux::Demux( 47 | NET_BUFFER_LIST const * NetBufferList 48 | ) const 49 | { 50 | auto const peerAddress = ParsePeerAddress(NetBufferList); 51 | 52 | if (! peerAddress) 53 | { 54 | return SIZE_T_MAX; 55 | } 56 | 57 | return Demux(peerAddress); 58 | } 59 | 60 | _Use_decl_annotations_ 61 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY 62 | TxPeerAddressDemux::GenerateDemuxProperty( 63 | NET_BUFFER_LIST const * NetBufferList 64 | ) 65 | { 66 | auto const address = ParsePeerAddress(NetBufferList); 67 | NET_CLIENT_QUEUE_TX_DEMUX_PROPERTY property = { 68 | TxDemuxTypePeerAddress, 69 | reinterpret_cast(NetBufferList->Scratch), 70 | }; 71 | 72 | NT_FRE_ASSERT(property.Value <= GetRange()); 73 | 74 | // as a matter of presentation we generate broadcast address for 75 | // any queue that has the multicast bit set instead of using the 76 | // multicast address that triggered the generation. 77 | 78 | if (address->Value[0] & 0x01) 79 | { 80 | property.Property.PeerAddress = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 81 | } 82 | else 83 | { 84 | property.Property.PeerAddress = *address; 85 | } 86 | 87 | return wistd::move(property); 88 | } 89 | 90 | size_t 91 | TxPeerAddressDemux::Demux( 92 | NET_CLIENT_EUI48_ADDRESS const * Address 93 | ) const 94 | { 95 | if (Address->Value[0] & 0x01) 96 | { 97 | return 0U; 98 | } 99 | 100 | // lookup failure returns a special value of ~0U so if 101 | // the lookup fails do not overflow the value back to 0U 102 | // which would return the demux for the broadcast queue. 103 | 104 | auto const demux = m_app.WifiTxPeerAddressDemux(Address); 105 | 106 | return demux == SIZE_T_MAX ? SIZE_T_MAX : demux + 1; 107 | } 108 | -------------------------------------------------------------------------------- /netcx/adapter/nxadapterdriverapi.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | 3 | #include "Nx.hpp" 4 | 5 | #include 6 | 7 | #include "NxDriver.hpp" 8 | #include "verifier.hpp" 9 | #include "version.hpp" 10 | 11 | #include "NxAdapterDriverApi.tmh" 12 | 13 | extern 14 | WDFWAITLOCK 15 | g_RegistrationLock; 16 | 17 | _Must_inspect_result_ 18 | _IRQL_requires_max_(PASSIVE_LEVEL) 19 | WDFAPI 20 | NTSTATUS 21 | NETEXPORT(NetAdapterDriverRegister)( 22 | _In_ NET_DRIVER_GLOBALS * Globals, 23 | _In_ WDFDRIVER Driver 24 | ) 25 | /*++ 26 | Routine Description: 27 | The client driver calls this method to register itself as a NetAdapterDriver 28 | At the backend we register with NDIS. 29 | The registration is optional as we would auto-register (if needed) at the 30 | time the client creates a NetAdapter object 31 | 32 | Arguments: 33 | 34 | Driver : A handle to a WDFDRIVER object that represents the cleint driver. 35 | 36 | Return Value: 37 | 38 | STATUS_SUCCESS upon success. 39 | Returns other NTSTATUS values. 40 | 41 | --*/ 42 | { 43 | auto const nxPrivateGlobals = GetPrivateGlobals(Globals); 44 | 45 | Verifier_VerifyPrivateGlobals(nxPrivateGlobals); 46 | Verifier_VerifyIrqlPassive(nxPrivateGlobals); 47 | 48 | { 49 | auto exclusive = wil::acquire_wdf_wait_lock(g_RegistrationLock); 50 | 51 | // 52 | // First see if we need create a NxDriver. 53 | // 54 | CX_RETURN_IF_NOT_NT_SUCCESS( 55 | NxDriver::_CreateIfNeeded(Driver, nxPrivateGlobals)); 56 | 57 | NxDriver *nxDriver = GetNxDriverFromWdfDriver(Driver); 58 | 59 | if (nxDriver->GetNdisMiniportDriverHandle() != NULL) { 60 | LogError(FLAG_DRIVER, "Driver already registered"); 61 | CX_RETURN_IF_NOT_NT_SUCCESS(STATUS_INVALID_DEVICE_STATE); 62 | } 63 | 64 | CX_RETURN_IF_NOT_NT_SUCCESS(nxDriver->Register()); 65 | } 66 | 67 | return STATUS_SUCCESS; 68 | } 69 | 70 | _IRQL_requires_max_(DISPATCH_LEVEL) 71 | WDFAPI 72 | NDIS_HANDLE 73 | NETEXPORT(NetAdapterDriverWdmGetHandle)( 74 | _In_ NET_DRIVER_GLOBALS * Globals, 75 | _In_ WDFDRIVER Driver 76 | ) 77 | /*++ 78 | Routine Description: 79 | The client driver calls this method to retrieve a NDIS_HANDLE corresponding 80 | to the WDFDRIVER and input DriverType 81 | 82 | This routine can only be called after the client has either: 83 | 84 | - explictly successfully registered itself as a NetAdapterDriver using 85 | NetAdapterDriverRegister 86 | OR 87 | - implicilty registered itself as a NetAdapterDriver since it successfuly 88 | created a NETADAPTER object 89 | 90 | Arguments: 91 | 92 | Driver : A handle to a WDFDRIVER object that represents the cleint driver. 93 | 94 | Return Value: 95 | 96 | NDIS_HANDLE 97 | --*/ 98 | { 99 | UNREFERENCED_PARAMETER(Driver); 100 | 101 | auto const nxPrivateGlobals = GetPrivateGlobals(Globals); 102 | 103 | Verifier_VerifyPrivateGlobals(nxPrivateGlobals); 104 | Verifier_VerifyIrqlLessThanOrEqualDispatch(nxPrivateGlobals); 105 | 106 | return nxPrivateGlobals->NxDriver->GetNdisMiniportDriverHandle(); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /netcx/ec/inc/executioncontextregistry.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define EXECUTION_CONTEXT_REGISTRY_BUILTIN_PROFILE_ROOT_WIN32 \ 9 | L"SYSTEM\\CurrentControlSet\\Services\\NDIS\\Parameters" 10 | #define EXECUTION_CONTEXT_REGISTRY_BUILTIN_PROFILE_ROOT_NT \ 11 | L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\NDIS\\Parameters" 12 | #define EXECUTION_CONTEXT_REGISTRY_BUILTIN_PROFILE_PATH \ 13 | L"Reserved\\ExecutionContextProfiles" 14 | 15 | #define EXECUTION_CONTEXT_REGISTRY_CUSTOM_PROFILE_ROOT_WIN32 \ 16 | L"SYSTEM\\CurrentControlSet\\Services\\NDIS\\State" 17 | #define EXECUTION_CONTEXT_REGISTRY_CUSTOM_PROFILE_ROOT_NT \ 18 | L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\NDIS\\State" 19 | #define EXECUTION_CONTEXT_REGISTRY_CUSTOM_PROFILE_PATH \ 20 | L"Reserved\\ExecutionContextProfiles" 21 | 22 | #define EXECUTION_CONTEXT_REGISTRY_PROFILE_MAX_NAME_LENGTH 256 // num characters, including trailing null 23 | 24 | #define EXECUTION_CONTEXT_REGISTRY_DEFAULTPROFILE_NAME \ 25 | L"DefaultProfile" 26 | 27 | #define EXECUTION_CONTEXT_REGISTRY_FLAGS_NAME \ 28 | L"Flags" 29 | #define EXECUTION_CONTEXT_REGISTRY_MAXTIMEATDISPATCH_NAME \ 30 | L"MaxTimeAtDispatch" 31 | #define EXECUTION_CONTEXT_REGISTRY_DPCWATCHDOGTIMERTHRESHOLD_NAME \ 32 | L"DpcWatchdogTimerThreshold" 33 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDATPASSIVE_NAME \ 34 | L"MaxPacketsSendAtPassive" 35 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDCOMPELTEATPASSIVE_NAME \ 36 | L"MaxPacketsSendCompleteAtPassive" 37 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVEATPASSIVE_NAME \ 38 | L"MaxPacketsReceiveAtPassive" 39 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVECOMPLETEATPASSIVE_NAME \ 40 | L"MaxPacketsReceiveCompleteAtPassive" 41 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDATDISPATCH_NAME \ 42 | L"MaxPacketsSendAtDispatch" 43 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDCOMPELTEATDISPATCH_NAME \ 44 | L"MaxPacketsSendCompleteAtDispatch" 45 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVEATDISPATCH_NAME \ 46 | L"MaxPacketsReceiveAtDispatch" 47 | #define EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVECOMPLETEATDISPATCH_NAME \ 48 | L"MaxPacketsReceiveCompleteAtDispatch" 49 | 50 | #define EXECUTION_CONTEXT_ALL_REGISTRY_VALUES \ 51 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_FLAGS_NAME) \ 52 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXTIMEATDISPATCH_NAME) \ 53 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_DPCWATCHDOGTIMERTHRESHOLD_NAME) \ 54 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDATPASSIVE_NAME) \ 55 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDCOMPELTEATPASSIVE_NAME) \ 56 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVEATPASSIVE_NAME) \ 57 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVECOMPLETEATPASSIVE_NAME) \ 58 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDATDISPATCH_NAME) \ 59 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSSENDCOMPELTEATDISPATCH_NAME) \ 60 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVEATDISPATCH_NAME) \ 61 | ECVALUE(REG_DWORD, EXECUTION_CONTEXT_REGISTRY_MAXPACKETSRECEIVECOMPLETEATDISPATCH_NAME) \ 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /netcx/translator/nxstatistics.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) Microsoft Corporation. All rights reserved. 2 | #pragma once 3 | 4 | struct NETADAPTER_QUEUE_PC 5 | { 6 | UINT64 NumberOfPackets; 7 | UINT64 IterationCount; 8 | UINT64 QueueDepth; 9 | UINT64 NblPending; 10 | UINT64 PacketsCompleted; 11 | UINT32 IterationCountBase; 12 | }; 13 | 14 | struct PerfCounter 15 | { 16 | UINT64 IterationCount = 0; // # of times polling loop runs 17 | UINT64 QueueDepth = 0; // # of packets own by the client driver 18 | UINT64 NblPending = 0; // # of NBL pending 19 | UINT64 PacketsCompleted = 0; // # of packets done processing 20 | }; 21 | 22 | struct NblTranslationPacketCounter 23 | { 24 | UINT64 BounceSuccess = 0; 25 | UINT64 BounceFailure = 0; 26 | UINT64 CannotTranslate = 0; 27 | UINT64 UnalignedBuffer = 0; 28 | }; 29 | 30 | struct NblTranslationSoftwareChecksum 31 | { 32 | UINT64 Required = 0; 33 | UINT64 Failure = 0; // Success = Required - Failure 34 | }; 35 | 36 | struct NblTranslationSoftwareSegment 37 | { 38 | UINT64 TcpSuccess = 0; 39 | UINT64 TcpFailure = 0; 40 | UINT64 UdpSuccess = 0; 41 | UINT64 UdpFailure = 0; 42 | }; 43 | 44 | struct NblTranslationDMACounter 45 | { 46 | UINT64 InsufficientResources = 0; 47 | UINT64 BufferTooSmall = 0; 48 | UINT64 CannotMapSglToFragments = 0; 49 | UINT64 PhysicalAddressTooLarge = 0; 50 | UINT64 OtherErrors = 0; 51 | }; 52 | 53 | class NxRxCounters 54 | { 55 | 56 | public: 57 | 58 | PerfCounter 59 | Perf = {}; 60 | 61 | _IRQL_requires_(PASSIVE_LEVEL) 62 | void 63 | Add( 64 | _In_ const NxRxCounters & rxCounters 65 | ); 66 | 67 | void 68 | GetPerfCounter( 69 | _Out_ NETADAPTER_QUEUE_PC & perfCounter 70 | ) const; 71 | 72 | }; 73 | 74 | class NxTxCounters 75 | { 76 | 77 | public: 78 | 79 | PerfCounter 80 | Perf = {}; 81 | 82 | NblTranslationPacketCounter 83 | Packet = {}; 84 | 85 | NblTranslationDMACounter 86 | DMA = {}; 87 | 88 | NblTranslationSoftwareChecksum 89 | Checksum = {}; 90 | 91 | NblTranslationSoftwareSegment 92 | Segment = {}; 93 | 94 | _IRQL_requires_(PASSIVE_LEVEL) 95 | void 96 | Add( 97 | _In_ const NxTxCounters & txCounters 98 | ); 99 | 100 | void 101 | GetPerfCounter( 102 | _Out_ NETADAPTER_QUEUE_PC & perfCounter 103 | ) const; 104 | 105 | }; 106 | 107 | class DECLSPEC_CACHEALIGN NxStatistics 108 | { 109 | 110 | private: 111 | 112 | NxRxCounters 113 | m_rxStatistics = {}; 114 | 115 | NxTxCounters 116 | m_txStatistics = {}; 117 | 118 | public: 119 | 120 | _IRQL_requires_(PASSIVE_LEVEL) 121 | const NxTxCounters & 122 | GetTxCounters( 123 | void 124 | ) const; 125 | 126 | _IRQL_requires_(PASSIVE_LEVEL) 127 | const NxRxCounters & 128 | GetRxCounters( 129 | void 130 | ) const; 131 | 132 | _IRQL_requires_(PASSIVE_LEVEL) 133 | void 134 | UpdateRxCounters( 135 | _In_ const NxRxCounters & rxCounters 136 | ); 137 | 138 | _IRQL_requires_(PASSIVE_LEVEL) 139 | void 140 | UpdateTxCounters( 141 | _In_ const NxTxCounters & txCounters 142 | ); 143 | }; 144 | --------------------------------------------------------------------------------