Windows otLwf Tunnel Mode (#984)

* Integrate 'Tunnel Mode' otLwf code and a few other minor changes in the Windows code/projects.
This commit is contained in:
Nick Banks
2016-12-05 16:35:56 -08:00
committed by Jonathan Hui
parent 55e17533b9
commit f435735582
23 changed files with 6370 additions and 1266 deletions
+21
View File
@@ -57,6 +57,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenThread", "OpenThread.vc
{ED0EA262-C222-42C7-98D3-E70C72978ED2} = {ED0EA262-C222-42C7-98D3-E70C72978ED2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spinel_k", "spinel_k.vcxproj", "{A55766B5-58B6-4519-835E-5A4B7C164B5A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -291,6 +293,24 @@ Global
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.ActiveCfg = Release|Win32
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.Build.0 = Release|Win32
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB}.Release|x86.Deploy.0 = Release|Win32
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|ARM.ActiveCfg = Debug|ARM
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|ARM.Build.0 = Debug|ARM
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|ARM.Deploy.0 = Debug|ARM
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x64.ActiveCfg = Debug|x64
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x64.Build.0 = Debug|x64
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x64.Deploy.0 = Debug|x64
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x86.ActiveCfg = Debug|Win32
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x86.Build.0 = Debug|Win32
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Debug|x86.Deploy.0 = Debug|Win32
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|ARM.ActiveCfg = Release|ARM
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|ARM.Build.0 = Release|ARM
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|ARM.Deploy.0 = Release|ARM
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x64.ActiveCfg = Release|x64
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x64.Build.0 = Release|x64
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x64.Deploy.0 = Release|x64
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x86.ActiveCfg = Release|Win32
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x86.Build.0 = Release|Win32
{A55766B5-58B6-4519-835E-5A4B7C164B5A}.Release|x86.Deploy.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -313,5 +333,6 @@ Global
{B7C6F344-7287-4930-AF38-223622BD8CBB} = {61E8A4A0-8138-49DB-97B4-3BEC87C8E133}
{D5577E51-FA31-4802-8669-1DB32805935E} = {35F6AB71-5BD2-4D53-8A51-D75CCD4CCC3D}
{F8C22844-9B93-4978-80DF-8AF2B37A7ABB} = {76EA541E-CAB1-4DB5-A39F-E3DB2A78CDDD}
{A55766B5-58B6-4519-835E-5A4B7C164B5A} = {95BD0669-04C8-4EEB-B3CC-0535B03F4468}
EndGlobalSection
EndGlobal
+11
View File
@@ -49,6 +49,7 @@
..\..\include;
..\..\examples\drivers\windows\include;
..\..\examples\drivers\windows\otLwf;
..\..\src;
..\..\src\core;
..\..\src\missing\stdint;
..\..\src\missing\stdbool;
@@ -78,6 +79,9 @@
cng.lib;
</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command Condition="'$(Platform)'=='ARM'">inf2cat /driver:$(TargetDir) /os:8_ARM</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\examples\drivers\windows\otLwf\address.c" />
@@ -87,6 +91,8 @@
<ClCompile Include="..\..\examples\drivers\windows\otLwf\eventprocessing.c" />
<ClCompile Include="..\..\examples\drivers\windows\otLwf\iocontrol.c" />
<ClCompile Include="..\..\examples\drivers\windows\otLwf\settings.c" />
<ClCompile Include="..\..\examples\drivers\windows\otLwf\thread.c" />
<ClCompile Include="..\..\examples\drivers\windows\otLwf\tunnel.c" />
<ClCompile Include="..\..\examples\drivers\windows\otLwf\oid.c" />
<ClCompile Include="..\..\examples\drivers\windows\otLwf\precomp.c">
<AdditionalIncludeDirectories>..;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -103,6 +109,8 @@
<ClInclude Include="..\..\examples\drivers\windows\otLwf\nsihelper.h" />
<ClInclude Include="..\..\examples\drivers\windows\otLwf\oid.h" />
<ClInclude Include="..\..\examples\drivers\windows\otLwf\radio.h" />
<ClInclude Include="..\..\examples\drivers\windows\otLwf\thread.h" />
<ClInclude Include="..\..\examples\drivers\windows\otLwf\tunnel.h" />
<ClInclude Include="..\..\examples\drivers\windows\otLwf\precomp.h" />
<ClInclude Include="..\..\examples\drivers\windows\otLwf\filter.h" />
<ResourceCompile Include="..\..\examples\drivers\windows\otLwf\filter.rc" />
@@ -118,6 +126,9 @@
<ProjectReference Include="mbedtls_k.vcxproj">
<Project>{69be8e8c-cf1e-46d6-932b-db435f47059b}</Project>
</ProjectReference>
<ProjectReference Include="spinel_k.vcxproj">
<Project>{a55766b5-58b6-4519-835e-5a4b7c164b5a}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
+12
View File
@@ -48,6 +48,12 @@
<ClInclude Include="..\..\examples\drivers\windows\otLwf\radio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\examples\drivers\windows\otLwf\thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\examples\drivers\windows\otLwf\tunnel.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\examples\drivers\windows\otLwf\filter.c">
@@ -83,6 +89,12 @@
<ClCompile Include="..\..\examples\drivers\windows\otLwf\address.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\examples\drivers\windows\otLwf\tunnel.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\examples\drivers\windows\otLwf\thread.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\examples\drivers\windows\otLwf\settings.c">
<Filter>Source Files</Filter>
</ClCompile>
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="openthread.configuration.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{A55766B5-58B6-4519-835E-5A4B7C164B5A}</ProjectGuid>
<TemplateGuid>{8c0e3d8b-df43-455b-815a-4a0e72973bc6}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<Configuration>Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
<RootNamespace>Thread</RootNamespace>
<DriverType>KMDF</DriverType>
<DriverTargetPlatform>Universal</DriverTargetPlatform>
</PropertyGroup>
<PropertyGroup Label="PropertySheets">
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<TargetVersion>Windows10</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup>
<OutDir>..\..\build\bin\$(Platform)\$(Configuration)\lib\</OutDir>
<IntDir>..\..\build\obj\$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>
%(PreprocessorDefinitions);
HAVE_STRNLEN=1;
SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR=1;
</PreprocessorDefinitions>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories);
..\..\include;
..\..\src\missing\stdint;
..\..\src\missing\stdbool;
</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4100;4706;4748;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<TreatWarningAsError>true</TreatWarningAsError>
<WppEnabled>true</WppEnabled>
<WppScanConfigurationData>..\..\include\platform\logging-windows.h</WppScanConfigurationData>
<WppAdditionalOptions>-km %(WppAdditionalOptions)</WppAdditionalOptions>
<WppModuleName>otCore</WppModuleName>
<WppSearchString>WPP_INIT_TRACING</WppSearchString>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ncp\spinel.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ncp\spinel.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{C034F7F4-3CBD-4B9A-A033-0D76A195B581}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{7A95885E-AD23-439A-B283-9BDE0E39D84E}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{1E1DF93E-9746-4688-A1F0-7B59378CF28F}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\ncp\spinel.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\ncp\spinel.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
+5
View File
@@ -36,6 +36,11 @@
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.Background>
<ImageBrush ImageSource="ms-appx:///Assets/Wide310x150Logo.png" Opacity="0.25" Stretch="Uniform"/>
</Grid.Background>
</Grid>
<!-- Interface List -->
<TextBlock
Text="Thread UX"
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="7926e3f9-835e-421c-94c1-2812f3569f4a" Publisher="CN=nibanks" Version="1.0.10.0" />
<Identity Name="7926e3f9-835e-421c-94c1-2812f3569f4a" Publisher="CN=nibanks" Version="1.0.12.0" />
<mp:PhoneIdentity PhoneProductId="7926e3f9-835e-421c-94c1-2812f3569f4a" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>OpenThread</DisplayName>
@@ -256,10 +256,12 @@ typedef enum _OTLWF_NOTIF_TYPE
// GUID - InterfaceGuid
// otShortAddress - aShortAddress
/* NOT USED
#define IOCTL_OTLWF_OT_UNICAST_ADDRESSES \
OTLWF_CTL_CODE(120, METHOD_BUFFERED, FILE_READ_DATA)
// GUID - InterfaceGuid
// otNetifAddress[] - aAddresses
*/
#define IOCTL_OTLWF_OT_ACTIVE_DATASET \
OTLWF_CTL_CODE(121, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
@@ -616,6 +618,7 @@ typedef struct otCommissionConfig
// GUID - InterfaceGuid
// uint8_t - aLength
// uint8_t[aLength] - aTlvTypes
// otIp6Address - aAddress (optional)
#define IOCTL_OTLWF_OT_SEND_ACTIVE_SET \
OTLWF_CTL_CODE(186, METHOD_BUFFERED, FILE_WRITE_DATA)
@@ -629,6 +632,7 @@ typedef struct otCommissionConfig
// GUID - InterfaceGuid
// uint8_t - aLength
// uint8_t[aLength] - aTlvTypes
// otIp6Address - aAddress (optional)
#define IOCTL_OTLWF_OT_SEND_PENDING_SET \
OTLWF_CTL_CODE(188, METHOD_BUFFERED, FILE_WRITE_DATA)
@@ -654,9 +658,13 @@ typedef struct otCommissionConfig
OTLWF_CTL_CODE(191, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
// GUID - InterfaceGuid
// uint32_t - aKeySwitchGuardTime
#define IOCTL_OTLWF_OT_FACTORY_RESET \
OTLWF_CTL_CODE(192, METHOD_BUFFERED, FILE_WRITE_DATA)
// GUID - InterfaceGuid
// OpenThread function IOCTL codes
#define MIN_OTLWF_IOCTL_FUNC_CODE 100
#define MAX_OTLWF_IOCTL_FUNC_CODE 191
#define MAX_OTLWF_IOCTL_FUNC_CODE 192
#endif //__OTLWFIOCTL_H__
+20 -9
View File
@@ -35,7 +35,7 @@ using namespace std;
// The maximum time we will wait for an overlapped result. Essentially, the maximum
// amount of time each synchronous IOCTL should take.
const DWORD c_MaxOverlappedWaitTimeMS = 10 * 1000;
const DWORD c_MaxOverlappedWaitTimeMS = 5 * 1000;
// Version string returned by the API
const char c_Version[] = "Windows"; // TODO - What should we really put here?
@@ -2144,6 +2144,7 @@ otSendActiveGet(
if (aTlvTypes == nullptr && aLength != 0) return kThreadError_InvalidArgs;
DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
if (aAddress) BufferSize += sizeof(otIp6Address);
PBYTE Buffer = (PBYTE)malloc(BufferSize);
if (Buffer == nullptr) return kThreadError_NoBufs;
@@ -2151,9 +2152,8 @@ otSendActiveGet(
memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), &aLength, sizeof(aLength));
if (aLength > 0)
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(uint8_t), aTlvTypes, aLength);
// TODO - include aAddress
UNREFERENCED_PARAMETER(aAddress);
if (aAddress)
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + aLength, BufferSize - sizeof(GUID) - sizeof(uint8_t) - aLength, aAddress, sizeof(otIp6Address));
ThreadError result =
DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_ACTIVE_GET, Buffer, BufferSize, nullptr, 0));
@@ -2206,6 +2206,7 @@ otSendPendingGet(
if (aTlvTypes == nullptr && aLength != 0) return kThreadError_InvalidArgs;
DWORD BufferSize = sizeof(GUID) + sizeof(uint8_t) + aLength;
if (aAddress) BufferSize += sizeof(otIp6Address);
PBYTE Buffer = (PBYTE)malloc(BufferSize);
if (Buffer == nullptr) return kThreadError_NoBufs;
@@ -2213,9 +2214,8 @@ otSendPendingGet(
memcpy_s(Buffer + sizeof(GUID), BufferSize - sizeof(GUID), &aLength, sizeof(aLength));
if (aLength > 0)
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), BufferSize - sizeof(GUID) - sizeof(uint8_t), aTlvTypes, aLength);
// TODO - include aAddress
UNREFERENCED_PARAMETER(aAddress);
if (aAddress)
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + aLength, BufferSize - sizeof(GUID) - sizeof(uint8_t) - aLength, aAddress, sizeof(otIp6Address));
ThreadError result =
DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_SEND_PENDING_GET, Buffer, BufferSize, nullptr, 0));
@@ -2844,8 +2844,7 @@ otFactoryReset(
_In_ otInstance *aInstance
)
{
UNREFERENCED_PARAMETER(aInstance);
// TODO ...
if (aInstance) (void)SetIOCTL(aInstance, IOCTL_OTLWF_OT_FACTORY_RESET);
}
OTAPI
@@ -3042,6 +3041,18 @@ otGetMacCounters(
return aCounters;
}
OTAPI
void
OTCALL
otGetMessageBufferInfo(
_In_ otInstance *,
_Out_ otBufferInfo *aBufferInfo
)
{
// Not supported on Windows
ZeroMemory(aBufferInfo, sizeof(otBufferInfo));
}
OTAPI
bool
OTCALL
+76 -1
View File
@@ -373,7 +373,7 @@ otLwfEventProcessingAddressChanged(
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfAddressesUpdated(
otLwfRadioAddressesUpdated(
_In_ PMS_FILTER pFilter
)
{
@@ -382,6 +382,8 @@ otLwfAddressesUpdated(
ULONG FoundInOpenThread = 0; // Bit field
ULONG OriginalCacheLength = pFilter->otCachedAddrCount;
NT_ASSERT(pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO);
const otNetifAddress* addr = otGetUnicastAddresses(pFilter->otCtx);
// Process the addresses
@@ -411,3 +413,76 @@ otLwfAddressesUpdated(
LogFuncExit(DRIVER_DEFAULT);
}
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfTunAddressesUpdated(
_In_ PMS_FILTER pFilter,
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
_In_ spinel_size_t value_data_len,
_Out_ uint32_t *aNotifFlags
)
{
ULONG FoundInOpenThread = 0; // Bit field
ULONG OriginalCacheLength = pFilter->otCachedAddrCount;
LogFuncEntry(DRIVER_DEFAULT);
NT_ASSERT (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD);
*aNotifFlags = 0;
while (value_data_len > 0)
{
const uint8_t *entry_ptr = NULL;
spinel_size_t entry_len = 0;
spinel_ssize_t len = spinel_datatype_unpack(value_data_ptr, value_data_len, "D.", &entry_ptr, &entry_len);
if (len < 1) break;
{
PIN6_ADDR pAddr = NULL;
otNetifAddress addr = { { 0 }, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, 0, NULL };
spinel_datatype_unpack(
entry_ptr,
entry_len,
"6CLL",
&pAddr,
&addr.mPrefixLength,
&addr.mValidLifetime,
&addr.mPreferredLifetime);
if (pAddr)
{
int index = otLwfFindCachedAddrIndex(pFilter, pAddr);
if (index == -1)
{
memcpy_s(&addr.mAddress, sizeof(addr.mAddress), pAddr, sizeof(IN6_ADDR));
otLwfOnAddressAdded(pFilter, &addr, TRUE);
*aNotifFlags |= OT_IP6_ADDRESS_ADDED;
}
else
{
NT_ASSERT(index < 8 * sizeof(FoundInOpenThread));
FoundInOpenThread |= 1 << index;
}
}
}
value_data_len -= len;
value_data_ptr += len;
}
// Look for missing addresses and mark them as removed
for (int i = OriginalCacheLength - 1; i >= 0; i--)
{
if ((FoundInOpenThread & (1 << i)) == 0)
{
otLwfOnAddressRemoved(pFilter, (ULONG)i, TRUE);
*aNotifFlags |= OT_IP6_ADDRESS_REMOVED;
}
}
LogFuncExit(DRIVER_DEFAULT);
}
+118 -38
View File
@@ -148,14 +148,34 @@ Arguments:
--*/
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
UNREFERENCED_PARAMETER(SendCompleteFlags);
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p", FilterModuleContext, NetBufferLists);
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, NBL: %p %!STATUS!", FilterModuleContext, NetBufferLists, NetBufferLists->Status);
NT_ASSERT(NetBufferLists == pFilter->SendNetBufferList);
NT_ASSERT(kStateTransmit == pFilter->otPhyState);
KeSetEvent(&pFilter->SendNetBufferListComplete, 0, FALSE);
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
NT_ASSERT(NetBufferLists == pFilter->SendNetBufferList);
NT_ASSERT(kStateTransmit == pFilter->otPhyState);
KeSetEvent(&pFilter->SendNetBufferListComplete, 0, FALSE);
}
else
{
NT_ASSERT(NET_BUFFER_LIST_NEXT_NBL(NetBufferLists) == NULL);
PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferLists);
// Cancel command if we failed to send the NBL
if (!NT_SUCCESS(NetBufferLists->Status))
{
spinel_tid_t tid = (spinel_tid_t)(ULONG_PTR)NetBuffer->ProtocolReserved[1];
if (tid != 0)
{
otLwfCancelCommandHandler(pFilter, NDIS_TEST_SEND_COMPLETE_AT_DISPATCH_LEVEL(SendCompleteFlags), tid);
}
}
NetBuffer->DataLength = (ULONG)(ULONG_PTR)NetBuffer->ProtocolReserved[0];
NdisAdvanceNetBufferDataStart(NetBuffer, NetBuffer->DataLength, TRUE, NULL);
NdisFreeNetBufferList(NetBufferLists);
}
LogFuncExit(DRIVER_DATA_PATH);
}
@@ -214,14 +234,39 @@ Arguments:
}
else
{
// Indicate a new NBL to process on our worker thread
otLwfEventProcessingIndicateNewNetBufferLists(
pFilter,
DispatchLevel,
FALSE,
PortNumber,
NetBufferLists
);
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
// Indicate a new NBL to process on our worker thread
otLwfEventProcessingIndicateNewNetBufferLists(
pFilter,
DispatchLevel,
FALSE,
PortNumber,
NetBufferLists
);
}
else
{
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
while (CurrNbl)
{
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
while (CurrNb)
{
otLwfSendTunnelPacket(pFilter, DispatchLevel, CurrNb, TRUE);
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
}
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_SUCCESS;
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
}
NdisFSendNetBufferListsComplete(
pFilter->FilterHandle,
NetBufferLists,
DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0
);
}
// Release the data path ref now
ExReleaseRundownProtection(&pFilter->DataPathRundown);
@@ -273,15 +318,19 @@ Arguments:
{
LogVerbose(DRIVER_DATA_PATH, "NBL failed on return: %!STATUS!", CurrNbl->Status);
}
//if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO ||
// pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
{
PNET_BUFFER_LIST NblToFree = CurrNbl;
PNET_BUFFER NbToFree = NET_BUFFER_LIST_FIRST_NB(NblToFree);
PNET_BUFFER_LIST NblToFree = CurrNbl;
PNET_BUFFER NbToFree = NET_BUFFER_LIST_FIRST_NB(NblToFree);
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
NET_BUFFER_LIST_NEXT_NBL(NblToFree) = NULL;
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
NET_BUFFER_LIST_NEXT_NBL(NblToFree) = NULL;
NdisAdvanceNetBufferDataStart(NbToFree, NET_BUFFER_DATA_LENGTH(NbToFree), TRUE, NULL);
NdisFreeNetBufferList(NblToFree);
NdisAdvanceNetBufferDataStart(NbToFree, NET_BUFFER_DATA_LENGTH(NbToFree), TRUE, NULL);
NdisFreeNetBufferList(NblToFree);
}
}
LogFuncExit(DRIVER_DATA_PATH);
@@ -343,8 +392,46 @@ N.B.: It is important to check the ReceiveFlags in NDIS_TEST_RECEIVE_CANNOT_PEND
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
}
}
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
{
PNET_BUFFER_LIST CurrNbl = NetBufferLists;
while (CurrNbl)
{
PNET_BUFFER CurrNb = NET_BUFFER_LIST_FIRST_NB(CurrNbl);
while (CurrNb)
{
PUCHAR Buffer = (PUCHAR)NdisGetDataBuffer(CurrNb, CurrNb->DataLength, NULL, 1, 0);
if (Buffer == NULL)
{
Buffer = (PUCHAR)FILTER_ALLOC_MEM(pFilter->FilterHandle, CurrNb->DataLength);
if (Buffer != NULL)
{
PUCHAR _Buffer = (PUCHAR)NdisGetDataBuffer(CurrNb, CurrNb->DataLength, Buffer, 1, 0);
NT_ASSERT(_Buffer == Buffer);
UNREFERENCED_PARAMETER(_Buffer);
otLwfReceiveTunnelPacket(pFilter, DispatchLevel, Buffer, CurrNb->DataLength);
FILTER_FREE_MEM(Buffer);
}
}
else
{
otLwfReceiveTunnelPacket(pFilter, DispatchLevel, Buffer, CurrNb->DataLength);
}
CurrNb = NET_BUFFER_NEXT_NB(CurrNb);
}
NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_SUCCESS;
CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
}
NdisFReturnNetBufferLists(
pFilter->FilterHandle,
NetBufferLists,
DispatchLevel ? NDIS_RETURN_FLAGS_DISPATCH_LEVEL : 0
);
}
// Try to grab a ref on the data path first, to make sure we are allowed
else if(pFilter->otPhyState == kStateDisabled || !ExAcquireRundownProtection(&pFilter->DataPathRundown))
else if (pFilter->otPhyState == kStateDisabled || !ExAcquireRundownProtection(&pFilter->DataPathRundown))
{
LogVerbose(DRIVER_DATA_PATH, "Failing ReceiveNetBufferLists because data path isn't active.");
@@ -415,26 +502,19 @@ Arguments:
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
LogFuncEntryMsg(DRIVER_DATA_PATH, "Filter: %p, CancelId: %p", FilterModuleContext, CancelId);
otLwfEventProcessingIndicateNetBufferListsCancelled(pFilter, CancelId);
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
otLwfEventProcessingIndicateNetBufferListsCancelled(pFilter, CancelId);
}
else
{
NT_ASSERT(FALSE); // TODO
}
LogFuncExit(DRIVER_DATA_PATH);
}
#pragma pack(push)
#pragma pack(1)
typedef struct UDPHeader
{
USHORT SourcePort;
USHORT DestinationPort;
USHORT TotalLength;
USHORT Checksum;
} UDPHeader;
#pragma pack(pop)
// Callback received from OpenThread when it has an IPv6 packet ready for
// delivery to TCPIP.
void
+1 -1
View File
@@ -532,7 +532,7 @@ otLwfIndicateNotification(
{
LogWarning(DRIVER_IOCTL, "Dropping old notification!");
otLwfReleaseNotification(DeviceClient->PendingNotifications[DeviceClient->NotificationOffset]);
DeviceClient->NotificationOffset++;
DeviceClient->NotificationOffset = (DeviceClient->NotificationOffset + 1) % OTLWF_MAX_PENDING_NOTIFICATIONS_PER_CLIENT;
}
else
{
@@ -142,6 +142,8 @@ otLwfEventProcessingStop(
_In_ PMS_FILTER pFilter
)
{
PLIST_ENTRY Link = NULL;
LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", pFilter);
// By this point, we have disabled the Data Path, so no more
@@ -172,57 +174,66 @@ otLwfEventProcessingStop(
}
// Clean up any left over events
PLIST_ENTRY Link = pFilter->AddressChangesHead.Flink;
while (Link != &pFilter->AddressChangesHead)
if (pFilter->AddressChangesHead.Flink)
{
POTLWF_ADDR_EVENT Event = CONTAINING_RECORD(Link, OTLWF_ADDR_EVENT, Link);
Link = Link->Flink;
Link = pFilter->AddressChangesHead.Flink;
while (Link != &pFilter->AddressChangesHead)
{
POTLWF_ADDR_EVENT Event = CONTAINING_RECORD(Link, OTLWF_ADDR_EVENT, Link);
Link = Link->Flink;
// Delete the event
NdisFreeMemory(Event, 0, 0);
// Delete the event
NdisFreeMemory(Event, 0, 0);
}
}
// Clean up any left over events
Link = pFilter->NBLsHead.Flink;
while (Link != &pFilter->NBLsHead)
if (pFilter->NBLsHead.Flink)
{
POTLWF_NBL_EVENT Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link);
Link = Link->Flink;
Link = pFilter->NBLsHead.Flink;
while (Link != &pFilter->NBLsHead)
{
POTLWF_NBL_EVENT Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link);
Link = Link->Flink;
otLwfCompleteNBLs(pFilter, FALSE, Event->Received, Event->NetBufferLists, STATUS_CANCELLED);
otLwfCompleteNBLs(pFilter, FALSE, Event->Received, Event->NetBufferLists, STATUS_CANCELLED);
// Delete the event
NdisFreeMemory(Event, 0, 0);
// Delete the event
NdisFreeMemory(Event, 0, 0);
}
}
// Reinitialize the list head
InitializeListHead(&pFilter->AddressChangesHead);
InitializeListHead(&pFilter->NBLsHead);
FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, FALSE);
// Clean up any left over IRPs
Link = pFilter->EventIrpListHead.Flink;
while (Link != &pFilter->EventIrpListHead)
if (pFilter->EventIrpListHead.Flink)
{
PIRP Irp = CONTAINING_RECORD(Link, IRP, Tail.Overlay.ListEntry);
Link = Link->Flink;
// Before we are allowed to complete the pending IRP, we must remove the cancel routine
KIRQL irql;
IoAcquireCancelSpinLock(&irql);
IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(irql);
FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, FALSE);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Clean up any left over IRPs
Link = pFilter->EventIrpListHead.Flink;
while (Link != &pFilter->EventIrpListHead)
{
PIRP Irp = CONTAINING_RECORD(Link, IRP, Tail.Overlay.ListEntry);
Link = Link->Flink;
// Before we are allowed to complete the pending IRP, we must remove the cancel routine
KIRQL irql;
IoAcquireCancelSpinLock(&irql);
IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(irql);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
// Reinitialize the list head
InitializeListHead(&pFilter->EventIrpListHead);
FILTER_RELEASE_LOCK(&pFilter->EventsLock, FALSE);
}
// Reinitialize the list head
InitializeListHead(&pFilter->EventIrpListHead);
FILTER_RELEASE_LOCK(&pFilter->EventsLock, FALSE);
LogFuncExit(DRIVER_DEFAULT);
}
@@ -307,23 +318,31 @@ otLwfEventProcessingIndicateAddressChange(
_In_ PIN6_ADDR pAddr
)
{
POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT));
if (Event == NULL)
if (pFilter->InternalStateInitialized == FALSE)
{
LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_ADDR_EVENT");
return;
}
Event->NotificationType = NotificationType;
Event->Address = *pAddr;
// Add the event to the queue
NdisAcquireSpinLock(&pFilter->EventsLock);
InsertTailList(&pFilter->AddressChangesHead, &Event->Link);
NdisReleaseSpinLock(&pFilter->EventsLock);
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT));
if (Event == NULL)
{
LogWarning(DRIVER_DATA_PATH, "Failed to alloc new OTLWF_ADDR_EVENT");
return;
}
// Set the event to indicate we have a new address to process
KeSetEvent(&pFilter->EventWorkerThreadProcessAddressChanges, 0, FALSE);
Event->NotificationType = NotificationType;
Event->Address = *pAddr;
// Add the event to the queue
NdisAcquireSpinLock(&pFilter->EventsLock);
InsertTailList(&pFilter->AddressChangesHead, &Event->Link);
NdisReleaseSpinLock(&pFilter->EventsLock);
// Set the event to indicate we have a new address to process
KeSetEvent(&pFilter->EventWorkerThreadProcessAddressChanges, 0, FALSE);
}
}
// Called to indicate that we have a NetBufferLists to process
@@ -689,7 +708,7 @@ otLwfEventWorkerThread(
return;
}
#if DBG
#if DEBUG_ALLOC
// Initialize the list head for allocations
InitializeListHead(&pFilter->otOutStandingAllocations);
@@ -1017,7 +1036,7 @@ exit:
otInstanceFinalize(pFilter->otCtx);
pFilter->otCtx = NULL;
#if DBG
#if DEBUG_ALLOC
{
NT_ASSERT(pFilter->otOutstandingAllocationCount == 0);
NT_ASSERT(pFilter->otOutstandingMemoryAllocated == 0);
+124 -504
View File
@@ -93,7 +93,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
NTSTATUS NtStatus;
NDIS_FILTER_ATTRIBUTES FilterAttributes;
ULONG Size;
PNET_BUFFER SendNetBuffer;
ULONG bytesProcessed = 0;
COMPARTMENT_ID OriginalCompartmentID;
@@ -119,8 +118,7 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
break;
}
Size = sizeof(MS_FILTER) +
AttachParameters->BaseMiniportInstanceName->Length;
Size = sizeof(MS_FILTER) + AttachParameters->BaseMiniportInstanceName->Length;
pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size);
if (pFilter == NULL)
@@ -135,8 +133,7 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
// Format of "\DEVICE\{5BA90C49-0D7E-455B-8D3B-614F6714A212}"
AttachParameters->BaseMiniportName->Buffer += 8;
AttachParameters->BaseMiniportName->Length -= 8 * sizeof(WCHAR);
NtStatus = RtlGUIDFromString(AttachParameters->BaseMiniportName,
&pFilter->InterfaceGuid);
NtStatus = RtlGUIDFromString(AttachParameters->BaseMiniportName, &pFilter->InterfaceGuid);
AttachParameters->BaseMiniportName->Buffer -= 8;
AttachParameters->BaseMiniportName->Length += 8 * sizeof(WCHAR);
if (!NT_SUCCESS(NtStatus))
@@ -164,15 +161,27 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
FilterAttributes.Flags = 0;
NDIS_DECLARE_FILTER_MODULE_CONTEXT(MS_FILTER);
Status = NdisFSetAttributes(NdisFilterHandle,
pFilter,
&FilterAttributes);
Status = NdisFSetAttributes(NdisFilterHandle, pFilter, &FilterAttributes);
if (Status != NDIS_STATUS_SUCCESS)
{
LogWarning(DRIVER_DEFAULT, "Failed to set attributes, %!NDIS_STATUS!", Status);
LogError(DRIVER_DEFAULT, "Failed to set attributes, %!NDIS_STATUS!", Status);
break;
}
// Filter initially in Paused state
pFilter->State = FilterPaused;
NdisInitializeEvent(&pFilter->FilterPauseComplete);
// Initialize initial ref count on IoControl to 1, which we release on shutdown
RtlInitializeReferenceCount(&pFilter->IoControlReferences);
NdisInitializeEvent(&pFilter->IoControlShutdownComplete);
// Initialize PendingOidRequest lock
NdisAllocateSpinLock(&pFilter->PendingOidRequestLock);
// Initialize datapath to disabled with no active references
pFilter->DataPathRundown.Count = EX_RUNDOWN_ACTIVE;
// Create the NDIS pool for creating the SendNetBufferList
NET_BUFFER_LIST_POOL_PARAMETERS PoolParams =
{
@@ -191,111 +200,30 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
break;
}
// Create the SendNetBufferList
pFilter->SendNetBufferList =
NdisAllocateNetBufferAndNetBufferList(
pFilter->NetBufferListPool, // PoolHandle
0, // ContextSize
0, // ContextBackFill
NULL, // MdlChain
0, // DataOffset
0 // DataLength
// Query the compartment ID for this interface to use for the IP stack
pFilter->InterfaceCompartmentID = GetInterfaceCompartmentID(&pFilter->InterfaceLuid);
LogVerbose(DRIVER_DEFAULT, "Interface %!GUID! is in Compartment %u", &pFilter->InterfaceGuid, (ULONG)pFilter->InterfaceCompartmentID);
// Make sure we are in the right compartment
(VOID)otLwfSetCompartment(pFilter, &OriginalCompartmentID);
// Register for address changed notifications
NtStatus =
NotifyUnicastIpAddressChange(
AF_INET6,
otLwfAddressChangeCallback,
pFilter,
FALSE,
&pFilter->AddressChangeHandle
);
if (pFilter->SendNetBufferList == NULL)
// Revert the compartment, now that we have the table
otLwfRevertCompartment(OriginalCompartmentID);
if (!NT_SUCCESS(NtStatus))
{
NdisFreeNetBufferListPool(pFilter->NetBufferListPool);
Status = NDIS_STATUS_RESOURCES;
LogWarning(DRIVER_DEFAULT, "Failed to create Send NetBufferList");
break;
}
// Initialize NetBuffer fields
SendNetBuffer = NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList);
NET_BUFFER_CURRENT_MDL(SendNetBuffer) = NULL;
NET_BUFFER_CURRENT_MDL_OFFSET(SendNetBuffer) = 0;
NET_BUFFER_DATA_LENGTH(SendNetBuffer) = 0;
NET_BUFFER_DATA_OFFSET(SendNetBuffer) = 0;
NET_BUFFER_FIRST_MDL(SendNetBuffer) = NULL;
// Allocate the NetBuffer for SendNetBufferList
Status = NdisRetreatNetBufferDataStart(SendNetBuffer, kMaxPHYPacketSize, 0, NULL);
if (Status != NDIS_STATUS_SUCCESS)
{
NdisFreeNetBufferList(pFilter->SendNetBufferList);
NdisFreeNetBufferListPool(pFilter->NetBufferListPool);
LogError(DRIVER_DEFAULT, "Failed to allocate NB for Send NetBufferList, %!NDIS_STATUS!", Status);
break;
}
// Filter initially in Paused state
pFilter->State = FilterPaused;
NdisInitializeEvent(&pFilter->FilterPauseComplete);
// Initialize initial ref count on IoControl to 1, which we release on shutdown
RtlInitializeReferenceCount(&pFilter->IoControlReferences);
NdisInitializeEvent(&pFilter->IoControlShutdownComplete);
// Initialize PendingOidRequest lock
NdisAllocateSpinLock(&pFilter->PendingOidRequestLock);
// Initialize datapath to disabled with no active references
pFilter->DataPathRundown.Count = EX_RUNDOWN_ACTIVE;
KeInitializeEvent(
&pFilter->SendNetBufferListComplete,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
// Initialize the event processing
pFilter->EventWorkerThread = NULL;
NdisAllocateSpinLock(&pFilter->EventsLock);
InitializeListHead(&pFilter->AddressChangesHead);
InitializeListHead(&pFilter->NBLsHead);
InitializeListHead(&pFilter->EventIrpListHead);
KeInitializeEvent(
&pFilter->EventWorkerThreadStopEvent,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadWaitTimeUpdated,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessTasklets,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessAddressChanges,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessNBLs,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessIrp,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadEnergyScanComplete,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
pFilter->EventHighPrecisionTimer =
ExAllocateTimer(
otLwfEventProcessingTimer,
pFilter,
EX_TIMER_HIGH_RESOLUTION
);
if (pFilter->EventHighPrecisionTimer == NULL)
{
LogError(DRIVER_DEFAULT, "Failed to allocate timer!");
LogError(DRIVER_DEFAULT, "NotifyUnicastIpAddressChange failed, %!STATUS!", NtStatus);
Status = NDIS_STATUS_FAILURE;
break;
}
@@ -330,37 +258,11 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
}
// Make sure we are in RADIO mode
if (pFilter->MiniportCapabilities.MiniportMode != OT_MP_MODE_RADIO)
if (pFilter->MiniportCapabilities.MiniportMode != OT_MP_MODE_RADIO &&
pFilter->MiniportCapabilities.MiniportMode != OT_MP_MODE_THREAD)
{
Status = NDIS_STATUS_NOT_SUPPORTED;
LogError(DRIVER_DEFAULT, "Miniport indicated it isn't running in RADIO mode!");
break;
}
// Query the compartment ID for this interface to use for the IP stack
pFilter->InterfaceCompartmentID = GetInterfaceCompartmentID(&pFilter->InterfaceLuid);
LogVerbose(DRIVER_DEFAULT, "Interface %!GUID! is in Compartment %u", &pFilter->InterfaceGuid, (ULONG)pFilter->InterfaceCompartmentID);
// Make sure we are in the right compartment
(VOID)otLwfSetCompartment(pFilter, &OriginalCompartmentID);
// Register for address changed notifications
NtStatus =
NotifyUnicastIpAddressChange(
AF_INET6,
otLwfAddressChangeCallback,
pFilter,
FALSE,
&pFilter->AddressChangeHandle
);
// Revert the compartment, now that we have the table
otLwfRevertCompartment(OriginalCompartmentID);
if (!NT_SUCCESS(NtStatus))
{
LogError(DRIVER_DEFAULT, "NotifyUnicastIpAddressChange failed, %!STATUS!", NtStatus);
Status = NDIS_STATUS_FAILURE;
LogError(DRIVER_DEFAULT, "Miniport indicated it isn't running in RADIO or THREAD mode!");
break;
}
@@ -369,16 +271,6 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
InsertTailList(&FilterModuleList, &pFilter->FilterModuleLink);
NdisReleaseSpinLock(&FilterListLock);
// Initialize the event processing thread
if (!NT_SUCCESS(otLwfEventProcessingStart(pFilter)))
{
NdisAcquireSpinLock(&FilterListLock);
RemoveEntryList(&pFilter->FilterModuleLink);
NdisReleaseSpinLock(&FilterListLock);
Status = NDIS_STATUS_RESOURCES;
break;
}
LogVerbose(DRIVER_DEFAULT, "Created Filter: %p", pFilter);
} while (FALSE);
@@ -392,11 +284,13 @@ N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper
CancelMibChangeNotify2(pFilter->AddressChangeHandle);
pFilter->AddressChangeHandle = NULL;
}
// Stop event processing thread
otLwfEventProcessingStop(pFilter);
if (pFilter->EventHighPrecisionTimer) ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
// Free NBL Pool
if (pFilter->NetBufferListPool)
{
NdisFreeNetBufferPool(pFilter->NetBufferListPool);
}
NdisFreeMemory(pFilter, 0, 0);
}
}
@@ -456,21 +350,29 @@ NOTE: Called at PASSIVE_LEVEL and the filter is in paused state
CancelMibChangeNotify2(pFilter->AddressChangeHandle);
pFilter->AddressChangeHandle = NULL;
// Stop event processing thread
otLwfEventProcessingStop(pFilter);
if (pFilter->InternalStateInitialized)
{
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
otLwfUninitializeThreadMode(pFilter);
}
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
{
otLwfUninitializeTunnelMode(pFilter);
}
else
{
NT_ASSERT(FALSE);
}
}
// Remove this Filter from the global list
NdisAcquireSpinLock(&FilterListLock);
RemoveEntryList(&pFilter->FilterModuleLink);
NdisReleaseSpinLock(&FilterListLock);
// Free NBL & Pools
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList), kMaxPHYPacketSize, TRUE, NULL);
NdisFreeNetBufferList(pFilter->SendNetBufferList);
// Free NBL Pool
NdisFreeNetBufferPool(pFilter->NetBufferListPool);
// Free timer
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
// Free the memory allocated
NdisFreeMemory(pFilter, 0, 0);
@@ -557,6 +459,37 @@ Return Value:
//
NdisGeneralAttributes->LookaheadSize = 128;
}
// Initialize the processing logic
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
NtStatus = otLwfInitializeThreadMode(pFilter);
if (!NT_SUCCESS(NtStatus))
{
LogError(DRIVER_DEFAULT, "otLwfInitializeThreadMode failed, %!STATUS!", NtStatus);
NdisStatus = NDIS_STATUS_FAILURE;
goto exit;
}
pFilter->InternalStateInitialized = TRUE;
}
else if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_THREAD)
{
NtStatus = otLwfInitializeTunnelMode(pFilter);
if (!NT_SUCCESS(NtStatus))
{
LogError(DRIVER_DEFAULT, "otLwfInitializeTunnelMode failed, %!STATUS!", NtStatus);
NdisStatus = NDIS_STATUS_FAILURE;
goto exit;
}
pFilter->InternalStateInitialized = TRUE;
}
else
{
NT_ASSERT(FALSE);
NdisStatus = NDIS_STATUS_FAILURE;
goto exit;
}
key.Luid = pFilter->InterfaceLuid;
NlInitializeInterfaceRw(&interfaceRw);
@@ -600,6 +533,19 @@ exit:
if (NdisStatus != NDIS_STATUS_SUCCESS)
{
pFilter->State = FilterPaused;
if (pFilter->InternalStateInitialized)
{
pFilter->InternalStateInitialized = FALSE;
if (pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO)
{
otLwfUninitializeThreadMode(pFilter);
}
else
{
otLwfUninitializeTunnelMode(pFilter);
}
}
}
LogFuncExitNDIS(DRIVER_DEFAULT, NdisStatus);
@@ -654,13 +600,6 @@ N.B.: When the filter is in Pausing state, it can still process OID requests,
//
NT_ASSERT(pFilter->State == FilterRunning);
pFilter->State = FilterPausing;
//
// Make sure we are disconnected from the network
//
// TODO ...
//otBecomeDetached(pFilter->otCtx); // TODO - This should block or we wait for it to complete
//otDisable(pFilter->otCtx);
otLwfNotifyDeviceAvailabilityChange(pFilter, FALSE);
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! removal.", &pFilter->InterfaceGuid);
@@ -724,6 +663,7 @@ NOTE: called at <= DISPATCH_LEVEL
LogInfo(DRIVER_DEFAULT, "Filter: %p, completed energy scan: Rssi:%d, Status:%!NDIS_STATUS!", FilterModuleContext, ScanResult->MaxRssi, ScanResult->Status);
// Marshal to OpenThread worker to indicate back
NT_ASSERT(pFilter->MiniportCapabilities.MiniportMode == OT_MP_MODE_RADIO);
otLwfEventProcessingIndicateEnergyScanResult(pFilter, ScanResult->MaxRssi);
}
@@ -872,6 +812,13 @@ otLwfSetCompartment(
_In_ PMS_FILTER pFilter,
_Out_ COMPARTMENT_ID* pOriginalCompartment
)
/*++
Routine Description:
Sets the current thread's compartment ID to match the filter instance.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
@@ -899,6 +846,13 @@ VOID
otLwfRevertCompartment(
_In_ COMPARTMENT_ID OriginalCompartment
)
/*++
Routine Description:
Resets the current thread's compartment ID.
--*/
{
// Revert the compartment if it is set
if (OriginalCompartment != 0)
@@ -906,337 +860,3 @@ otLwfRevertCompartment(
(VOID)NdisSetCurrentThreadCompartmentId(OriginalCompartment);
}
}
#if DBG
PMS_FILTER
otLwfFindFromCurrentThread()
{
PMS_FILTER pOutput = NULL;
HANDLE CurThreadId = PsGetCurrentThreadId();
NdisAcquireSpinLock(&FilterListLock);
for (PLIST_ENTRY Link = FilterModuleList.Flink; Link != &FilterModuleList; Link = Link->Flink)
{
PMS_FILTER pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink);
if (pFilter->otThreadId == CurThreadId)
{
pOutput = pFilter;
break;
}
}
NdisReleaseSpinLock(&FilterListLock);
NT_ASSERT(pOutput);
return pOutput;
}
#endif
void *otPlatCAlloc(size_t aNum, size_t aSize)
{
size_t totalSize = aNum * aSize;
#if DBG
totalSize += sizeof(OT_ALLOC);
#endif
PVOID mem = ExAllocatePoolWithTag(NonPagedPoolNx, totalSize, 'OTDM');
if (mem)
{
RtlZeroMemory(mem, totalSize);
#if DBG
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
//LogVerbose(DRIVER_DEFAULT, "otPlatAlloc(%u) = ID:%u %p", (ULONG)totalSize, pFilter->otAllocationID, mem);
OT_ALLOC* AllocHeader = (OT_ALLOC*)mem;
AllocHeader->Length = (LONG)totalSize;
AllocHeader->ID = pFilter->otAllocationID++;
InsertTailList(&pFilter->otOutStandingAllocations, &AllocHeader->Link);
InterlockedIncrement(&pFilter->otOutstandingAllocationCount);
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, AllocHeader->Length);
mem = (PUCHAR)(mem) + sizeof(OT_ALLOC);
#endif
}
return mem;
}
void otPlatFree(void *aPtr)
{
if (aPtr == NULL) return;
#if DBG
aPtr = (PUCHAR)(aPtr) - sizeof(OT_ALLOC);
//LogVerbose(DRIVER_DEFAULT, "otPlatFree(%p)", aPtr);
OT_ALLOC* AllocHeader = (OT_ALLOC*)aPtr;
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
InterlockedDecrement(&pFilter->otOutstandingAllocationCount);
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, -AllocHeader->Length);
RemoveEntryList(&AllocHeader->Link);
#endif
ExFreePoolWithTag(aPtr, 'OTDM');
}
uint32_t otPlatRandomGet()
{
LARGE_INTEGER Counter = KeQueryPerformanceCounter(NULL);
return (uint32_t)RtlRandomEx(&Counter.LowPart);
}
ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength)
{
// Just use the system-preferred random number generator algorithm
NTSTATUS status =
BCryptGenRandom(
NULL,
aOutput,
(ULONG)aInputLength,
BCRYPT_USE_SYSTEM_PREFERRED_RNG
);
NT_ASSERT(NT_SUCCESS(status));
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "BCryptGenRandom failed, %!STATUS!", status);
return kThreadError_Failed;
}
*aOutputLength = aInputLength;
return kThreadError_None;
}
void otSignalTaskletPending(_In_ otInstance *otCtx)
{
LogVerbose(DRIVER_DEFAULT, "otSignalTaskletPending");
PMS_FILTER pFilter = otCtxToFilter(otCtx);
otLwfEventProcessingIndicateNewTasklet(pFilter);
}
// Process a role state change
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfProcessRoleStateChange(
_In_ PMS_FILTER pFilter
)
{
otDeviceRole prevRole = pFilter->otCachedRole;
pFilter->otCachedRole = otGetDeviceRole(pFilter->otCtx);
if (prevRole == pFilter->otCachedRole) return;
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! new role: %!otDeviceRole!", &pFilter->InterfaceGuid, pFilter->otCachedRole);
// Make sure we are in the correct media connect state
otLwfIndicateLinkState(
pFilter,
IsAttached(pFilter->otCachedRole) ?
MediaConnectStateConnected :
MediaConnectStateDisconnected);
}
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
//
// Process the notification internally
//
if ((aFlags & OT_IP6_ADDRESS_ADDED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_ADDED", pFilter);
otLwfAddressesUpdated(pFilter);
}
if ((aFlags & OT_IP6_ADDRESS_REMOVED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_REMOVED", pFilter);
otLwfAddressesUpdated(pFilter);
}
if ((aFlags & OT_NET_ROLE) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_ROLE", pFilter);
otLwfProcessRoleStateChange(pFilter);
}
if ((aFlags & OT_NET_PARTITION_ID) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_PARTITION_ID", pFilter);
}
if ((aFlags & OT_NET_KEY_SEQUENCE_COUNTER) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_KEY_SEQUENCE_COUNTER", pFilter);
}
if ((aFlags & OT_THREAD_CHILD_ADDED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_ADDED", pFilter);
}
if ((aFlags & OT_THREAD_CHILD_REMOVED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_REMOVED", pFilter);
}
if ((aFlags & OT_THREAD_NETDATA_UPDATED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_NETDATA_UPDATED", pFilter);
otSlaacUpdate(pFilter->otCtx, pFilter->otAutoAddresses, ARRAYSIZE(pFilter->otAutoAddresses), otCreateRandomIid, NULL);
}
if ((aFlags & OT_IP6_ML_ADDR_CHANGED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ML_ADDR_CHANGED", pFilter);
}
//
// Queue the notification for clients
//
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE;
NotifEntry->Notif.StateChangePayload.Flags = aFlags;
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ACTIVE_SCAN;
if (aResult)
{
NotifEntry->Notif.ActiveScanPayload.Valid = TRUE;
NotifEntry->Notif.ActiveScanPayload.Results = *aResult;
}
else
{
NotifEntry->Notif.ActiveScanPayload.Valid = FALSE;
}
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ENERGY_SCAN;
if (aResult)
{
NotifEntry->Notif.EnergyScanPayload.Valid = TRUE;
NotifEntry->Notif.EnergyScanPayload.Results = *aResult;
}
else
{
NotifEntry->Notif.EnergyScanPayload.Valid = FALSE;
}
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_DISCOVER;
if (aResult)
{
NotifEntry->Notif.DiscoverPayload.Valid = TRUE;
NotifEntry->Notif.DiscoverPayload.Results = *aResult;
}
else
{
NotifEntry->Notif.DiscoverPayload.Valid = FALSE;
}
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_ENERGY_REPORT;
// Limit the number of reports if necessary
if (aEnergyListLength > MAX_ENERGY_REPORT_LENGTH) aEnergyListLength = MAX_ENERGY_REPORT_LENGTH;
NotifEntry->Notif.CommissionerEnergyReportPayload.ChannelMask = aChannelMask;
NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyListLength = aEnergyListLength;
memcpy(NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyList, aEnergyList, aEnergyListLength);
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_PANID_QUERY;
NotifEntry->Notif.CommissionerPanIdQueryPayload.PanId = aPanId;
NotifEntry->Notif.CommissionerPanIdQueryPayload.ChannelMask = aChannelMask;
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
+120 -162
View File
@@ -124,102 +124,113 @@ typedef struct _MS_FILTER
NDIS_EVENT IoControlShutdownComplete;
//
// Event processing
//
PVOID EventWorkerThread;
KEVENT EventWorkerThreadStopEvent;
KEVENT EventWorkerThreadProcessAddressChanges;
KEVENT EventWorkerThreadProcessNBLs;
NDIS_SPIN_LOCK EventsLock;
LIST_ENTRY AddressChangesHead;
LIST_ENTRY NBLsHead;
ULONG CountPendingRecvNBLs;
LARGE_INTEGER NextAlarmTickCount;
KEVENT EventWorkerThreadWaitTimeUpdated;
KEVENT EventWorkerThreadProcessTasklets;
PEX_TIMER EventHighPrecisionTimer;
UCHAR EventTimerState;
LIST_ENTRY EventIrpListHead;
KEVENT EventWorkerThreadProcessIrp;
KEVENT EventWorkerThreadEnergyScanComplete;
//
// Data Path Synchronization
// Data Path
//
EX_RUNDOWN_REF DataPathRundown;
NDIS_HANDLE NetBufferListPool;
BOOLEAN SendPending;
PNET_BUFFER_LIST SendNetBufferList;
KEVENT SendNetBufferListComplete;
//
// OpenThread state management
//
otDeviceRole otCachedRole;
BOOLEAN InternalStateInitialized;
//
// OpenThread addresses
//
IN6_ADDR otCachedAddr[OT_MAX_ADDRESSES];
ULONG otCachedAddrCount;
IN6_ADDR otLinkLocalAddr;
otNetifAddress otAutoAddresses[OT_MAX_AUTO_ADDRESSES];
IN6_ADDR otCachedAddr[OT_MAX_ADDRESSES];
ULONG otCachedAddrCount;
IN6_ADDR otLinkLocalAddr;
otNetifAddress otAutoAddresses[OT_MAX_AUTO_ADDRESSES];
union
{
struct // Thread Mode Variables
{
//
// OpenThread Event processing
//
PVOID EventWorkerThread;
KEVENT EventWorkerThreadStopEvent;
KEVENT EventWorkerThreadProcessAddressChanges;
KEVENT EventWorkerThreadProcessNBLs;
NDIS_SPIN_LOCK EventsLock;
LIST_ENTRY AddressChangesHead;
LIST_ENTRY NBLsHead;
ULONG CountPendingRecvNBLs;
LARGE_INTEGER NextAlarmTickCount;
KEVENT EventWorkerThreadWaitTimeUpdated;
KEVENT EventWorkerThreadProcessTasklets;
PEX_TIMER EventHighPrecisionTimer;
UCHAR EventTimerState;
LIST_ENTRY EventIrpListHead;
KEVENT EventWorkerThreadProcessIrp;
KEVENT EventWorkerThreadEnergyScanComplete;
//
// OpenThread state management
//
otDeviceRole otCachedRole;
//
// OpenThread data path state
//
BOOLEAN SendPending;
PNET_BUFFER_LIST SendNetBufferList;
KEVENT SendNetBufferListComplete;
//
// OpenThread radio variables
//
otRadioCaps otRadioCapabilities;
PhyState otPhyState;
uint8_t otCurrentListenChannel;
uint8_t otReceiveMessage[kMaxPHYPacketSize];
uint8_t otTransmitMessage[kMaxPHYPacketSize];
RadioPacket otReceiveFrame;
RadioPacket otTransmitFrame;
CHAR otLastEnergyScanMaxRssi;
//
// OpenThread radio variables
//
otRadioCaps otRadioCapabilities;
PhyState otPhyState;
uint8_t otCurrentListenChannel;
uint8_t otReceiveMessage[kMaxPHYPacketSize];
uint8_t otTransmitMessage[kMaxPHYPacketSize];
RadioPacket otReceiveFrame;
RadioPacket otTransmitFrame;
CHAR otLastEnergyScanMaxRssi;
BOOLEAN otPromiscuous;
uint16_t otPanID;
uint64_t otFactoryAddress;
uint64_t otExtendedAddress;
uint16_t otShortAddress;
BOOLEAN otPromiscuous;
uint16_t otPanID;
uint64_t otFactoryAddress;
uint64_t otExtendedAddress;
uint16_t otShortAddress;
BOOLEAN otPendingMacOffloadEnabled;
uint8_t otPendingShortAddressCount;
uint16_t otPendingShortAddresses[MAX_PENDING_MAC_SIZE];
uint8_t otPendingExtendedAddressCount;
uint64_t otPendingExtendedAddresses[MAX_PENDING_MAC_SIZE];
BOOLEAN otPendingMacOffloadEnabled;
uint8_t otPendingShortAddressCount;
uint16_t otPendingShortAddresses[MAX_PENDING_MAC_SIZE];
uint8_t otPendingExtendedAddressCount;
uint64_t otPendingExtendedAddresses[MAX_PENDING_MAC_SIZE];
#if DBG
// Used for tracking memory allocations
HANDLE otThreadId;
volatile LONG otOutstandingAllocationCount;
volatile LONG otOutstandingMemoryAllocated;
LIST_ENTRY otOutStandingAllocations;
ULONG otAllocationID;
#if DEBUG_ALLOC
// Used for tracking memory allocations
HANDLE otThreadId;
volatile LONG otOutstandingAllocationCount;
volatile LONG otOutstandingMemoryAllocated;
LIST_ENTRY otOutStandingAllocations;
ULONG otAllocationID;
#endif
//
// OpenThread context buffer
//
otInstance* otCtx;
PUCHAR otInstanceBuffer;
//
// OpenThread context buffer
//
otInstance* otCtx;
PUCHAR otInstanceBuffer;
};
struct // Tunnel Mode Variables
{
NDIS_SPIN_LOCK tunCommandLock;
LIST_ENTRY tunCommandHandlers;
USHORT tunTIDsInUse;
spinel_tid_t tunNextTID;
PVOID TunWorkerThread;
KEVENT TunWorkerThreadStopEvent;
KEVENT TunWorkerThreadAddressChangedEvent;
};
};
} MS_FILTER, * PMS_FILTER;
// Helper function that converts an otInstance pointer to a MS_FILTER pointer
__inline PMS_FILTER otCtxToFilter(_In_ otInstance* otCtx)
{
return *(PMS_FILTER*)((PUCHAR)otCtx - sizeof(PMS_FILTER));
}
// Helper function to indicate if a role means it is attached or not
_inline BOOLEAN IsAttached(_In_ otDeviceRole role)
{
return role > kDeviceRoleDetached;
}
//
// function prototypes
// NDIS Filter Functions
//
FILTER_ATTACH FilterAttach;
@@ -235,6 +246,10 @@ FILTER_SEND_NET_BUFFER_LISTS_COMPLETE FilterSendNetBufferListsComplete;
FILTER_RECEIVE_NET_BUFFER_LISTS FilterReceiveNetBufferLists;
FILTER_CANCEL_SEND_NET_BUFFER_LISTS FilterCancelSendNetBufferLists;
//
// Link State Functions
//
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfIndicateLinkState(
@@ -259,76 +274,6 @@ otLwfRevertCompartment(
_In_ COMPARTMENT_ID OriginalCompartment
);
//
// Event Processing Functions
//
EXT_CALLBACK otLwfEventProcessingTimer;
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfEventProcessingStart(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingStop(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateNewWaitTime(
_In_ PMS_FILTER pFilter,
_In_ ULONG waitTime
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateNewTasklet(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateAddressChange(
_In_ PMS_FILTER pFilter,
_In_ MIB_NOTIFICATION_TYPE NotificationType,
_In_ PIN6_ADDR pAddr
);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateNewNetBufferLists(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN DispatchLevel,
_In_ BOOLEAN Received,
_In_ NDIS_PORT_NUMBER PortNumber,
_In_ PNET_BUFFER_LIST NetBufferLists
);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateNetBufferListsCancelled(
_In_ PMS_FILTER pFilter,
_In_ PVOID CancelId
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateIrp(
_In_ PMS_FILTER pFilter,
_In_ PIRP Irp
);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateEnergyScanResult(
_In_ PMS_FILTER pFilter,
_In_ CHAR MaxRssi
);
//
// Data Path functions
//
@@ -345,18 +290,6 @@ otLwfDisableDataPath(
_In_ PMS_FILTER pFilter
);
//
// OpenThread callbacks
//
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext);
void otLwfReceiveIp6DatagramCallback(_In_ otMessage aMessage, _In_ void *aContext);
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext);
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext);
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext);
//
// Address Functions
//
@@ -386,16 +319,41 @@ otLwfInitializeAddresses(
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfAddressesUpdated(
otLwfRadioAddressesUpdated(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfTunAddressesUpdated(
_In_ PMS_FILTER pFilter,
_In_reads_bytes_(value_data_len) const uint8_t* value_data_ptr,
_In_ spinel_size_t value_data_len,
_Out_ uint32_t *aNotifFlags
);
int
otLwfFindCachedAddrIndex(
_In_ PMS_FILTER pFilter,
_In_ PIN6_ADDR addr
);
//
// Tunnel Logic Functions
//
_IRQL_requires_max_(PASSIVE_LEVEL)
NDIS_STATUS
otLwfInitializeTunnelMode(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
otLwfUninitializeTunnelMode(
_In_ PMS_FILTER pFilter
);
//
// Logging Helper
//
@@ -412,7 +370,7 @@ otLogBuffer(
// Debug Helpers
//
#if DBG
#if DEBUG_ALLOC
typedef struct _OT_ALLOC
{
File diff suppressed because it is too large Load Diff
+139 -91
View File
@@ -32,6 +32,7 @@
//
// Function prototype for general Io Control functions
//
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
@@ -69,9 +70,16 @@ otLwfCompleteOpenThreadIrp(
_In_ PIRP Irp
);
// Helper for converting IoCtl to string
const char*
IoCtlString(
ULONG IoControlCode
);
//
// Function prototype for OpenThread Io Control functions
//
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
@@ -85,96 +93,136 @@ OTLWF_OT_IOCTL_FUNC(
_Inout_ PULONG OutBufferLength
);
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otInterface;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otThread;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otActiveScan;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otDiscover;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChannel;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChildTimeout;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otExtendedAddress;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otExtendedPanId;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderRloc;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLinkMode;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMasterKey;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMeshLocalEid;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMeshLocalPrefix;
//OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkDataLeader
//OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkDataLocal
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkName;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPanId;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterRollEnabled;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otShortAddress;
//OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otUnicastAddresses
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otActiveDataset;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPendingDataset;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLocalLeaderWeight;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddBorderRouter;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveBorderRouter;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddExternalRoute;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveExternalRoute;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendServerData;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otContextIdReuseDelay;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otKeySequenceCounter;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkIdTimeout;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterUpgradeThreshold;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otReleaseRouterId;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacWhitelistEnabled;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddMacWhitelist;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveMacWhitelist;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacWhitelistEntry;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otClearMacWhitelist;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otDeviceRole;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChildInfoById;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otChildInfoByIndex;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otEidCacheEntry;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderData;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderRouterId;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLeaderWeight;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNetworkDataVersion;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPartitionId;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRloc16;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterIdSequence;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterInfo;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otStableNetworkDataVersion;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacBlacklistEnabled;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAddMacBlacklist;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRemoveMacBlacklist;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacBlacklistEntry;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otClearMacBlacklist;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMaxTransmitPower;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otNextOnMeshPrefix;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPollPeriod;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otLocalLeaderPartitionId;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otAssignLinkQuality;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otPlatformReset;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otParentInfo;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSingleton;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMacCounters;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otMaxChildren;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerStart;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerStop;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otJoinerStart;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otJoinerStop;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otFactoryAssignedIeeeEui64;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otHashMacAddress;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterDowngradeThreshold;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerPanIdQuery;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerEnergyScan;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otRouterSelectionJitter;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otJoinerUdpPort;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendDiagnosticGet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendDiagnosticReset;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerAddJoiner;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerRemoveJoiner;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerProvisioningUrl;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otCommissionerAnnounceBegin;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otEnergyScan;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendActiveGet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendActiveSet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendPendingGet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendPendingSet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendMgmtCommissionerGet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otSendMgmtCommissionerSet;
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_otKeySwitchGuardtime;
typedef
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
OTLWF_TUN_IOCTL_FUNC(
_In_ PMS_FILTER pFilter,
_In_ PIRP Irp,
_In_reads_bytes_(InBufferLength)
PUCHAR InBuffer,
_In_ ULONG InBufferLength,
_In_ ULONG OutBufferLength
);
typedef
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
(SPINEL_IRP_CMD_HANDLER)(
_In_ spinel_prop_key_t Key,
_In_reads_bytes_(DataLength) const uint8_t* Data,
_In_ spinel_size_t DataLength,
_Out_writes_bytes_(*OutBufferLength)
PVOID OutBuffer,
_Inout_ PULONG OutBufferLength
);
#define DECL_IOCTL_FUNC(X) \
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_##X
#define DECL_IOCTL_FUNC_WITH_TUN(X) \
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_##X; \
OTLWF_TUN_IOCTL_FUNC otLwfTunIoCtl_##X
#define DECL_IOCTL_FUNC_WITH_TUN2(X) \
OTLWF_OT_IOCTL_FUNC otLwfIoCtl_##X; \
OTLWF_TUN_IOCTL_FUNC otLwfTunIoCtl_##X; \
SPINEL_IRP_CMD_HANDLER otLwfTunIoCtl_##X##_Handler
#define REF_IOCTL_FUNC(X) otLwfIoCtl_##X , NULL
#define REF_IOCTL_FUNC_WITH_TUN(X) otLwfIoCtl_##X , otLwfTunIoCtl_##X
DECL_IOCTL_FUNC_WITH_TUN2(otInterface);
DECL_IOCTL_FUNC_WITH_TUN2(otThread);
DECL_IOCTL_FUNC_WITH_TUN2(otActiveScan);
DECL_IOCTL_FUNC(otDiscover);
DECL_IOCTL_FUNC_WITH_TUN2(otChannel);
DECL_IOCTL_FUNC_WITH_TUN2(otChildTimeout);
DECL_IOCTL_FUNC_WITH_TUN2(otExtendedAddress);
DECL_IOCTL_FUNC_WITH_TUN2(otExtendedPanId);
DECL_IOCTL_FUNC_WITH_TUN2(otLeaderRloc);
DECL_IOCTL_FUNC_WITH_TUN2(otLinkMode);
DECL_IOCTL_FUNC_WITH_TUN2(otMasterKey);
DECL_IOCTL_FUNC_WITH_TUN2(otMeshLocalEid);
DECL_IOCTL_FUNC_WITH_TUN2(otMeshLocalPrefix);
//DECL_IOCTL_FUNC(otNetworkDataLeader);
//DECL_IOCTL_FUNC(otNetworkDataLocal);
DECL_IOCTL_FUNC_WITH_TUN2(otNetworkName);
DECL_IOCTL_FUNC_WITH_TUN2(otPanId);
DECL_IOCTL_FUNC_WITH_TUN2(otRouterRollEnabled);
DECL_IOCTL_FUNC_WITH_TUN2(otShortAddress);
DECL_IOCTL_FUNC(otActiveDataset);
DECL_IOCTL_FUNC(otPendingDataset);
DECL_IOCTL_FUNC_WITH_TUN2(otLocalLeaderWeight);
DECL_IOCTL_FUNC_WITH_TUN(otAddBorderRouter);
DECL_IOCTL_FUNC_WITH_TUN(otRemoveBorderRouter);
DECL_IOCTL_FUNC_WITH_TUN(otAddExternalRoute);
DECL_IOCTL_FUNC_WITH_TUN(otRemoveExternalRoute);
DECL_IOCTL_FUNC(otSendServerData);
DECL_IOCTL_FUNC_WITH_TUN2(otContextIdReuseDelay);
DECL_IOCTL_FUNC_WITH_TUN2(otKeySequenceCounter);
DECL_IOCTL_FUNC_WITH_TUN2(otNetworkIdTimeout);
DECL_IOCTL_FUNC_WITH_TUN2(otRouterUpgradeThreshold);
DECL_IOCTL_FUNC_WITH_TUN(otReleaseRouterId);
DECL_IOCTL_FUNC_WITH_TUN2(otMacWhitelistEnabled);
DECL_IOCTL_FUNC_WITH_TUN(otAddMacWhitelist);
DECL_IOCTL_FUNC_WITH_TUN(otRemoveMacWhitelist);
DECL_IOCTL_FUNC(otMacWhitelistEntry);
DECL_IOCTL_FUNC_WITH_TUN(otClearMacWhitelist);
DECL_IOCTL_FUNC_WITH_TUN2(otDeviceRole);
DECL_IOCTL_FUNC(otChildInfoById);
DECL_IOCTL_FUNC(otChildInfoByIndex);
DECL_IOCTL_FUNC(otEidCacheEntry);
DECL_IOCTL_FUNC(otLeaderData);
DECL_IOCTL_FUNC_WITH_TUN2(otLeaderRouterId);
DECL_IOCTL_FUNC_WITH_TUN2(otLeaderWeight);
DECL_IOCTL_FUNC_WITH_TUN2(otNetworkDataVersion);
DECL_IOCTL_FUNC_WITH_TUN2(otPartitionId);
DECL_IOCTL_FUNC_WITH_TUN2(otRloc16);
DECL_IOCTL_FUNC(otRouterIdSequence);
DECL_IOCTL_FUNC(otRouterInfo);
DECL_IOCTL_FUNC_WITH_TUN2(otStableNetworkDataVersion);
DECL_IOCTL_FUNC(otMacBlacklistEnabled);
DECL_IOCTL_FUNC(otAddMacBlacklist);
DECL_IOCTL_FUNC(otRemoveMacBlacklist);
DECL_IOCTL_FUNC(otMacBlacklistEntry);
DECL_IOCTL_FUNC(otClearMacBlacklist);
DECL_IOCTL_FUNC(otMaxTransmitPower);
DECL_IOCTL_FUNC(otNextOnMeshPrefix);
DECL_IOCTL_FUNC(otPollPeriod);
DECL_IOCTL_FUNC(otLocalLeaderPartitionId);
DECL_IOCTL_FUNC(otAssignLinkQuality);
DECL_IOCTL_FUNC_WITH_TUN(otPlatformReset);
DECL_IOCTL_FUNC_WITH_TUN2(otParentInfo);
DECL_IOCTL_FUNC(otSingleton);
DECL_IOCTL_FUNC(otMacCounters);
DECL_IOCTL_FUNC_WITH_TUN2(otMaxChildren);
DECL_IOCTL_FUNC(otCommissionerStart);
DECL_IOCTL_FUNC(otCommissionerStop);
DECL_IOCTL_FUNC(otJoinerStart);
DECL_IOCTL_FUNC(otJoinerStop);
DECL_IOCTL_FUNC(otFactoryAssignedIeeeEui64);
DECL_IOCTL_FUNC(otHashMacAddress);
DECL_IOCTL_FUNC_WITH_TUN2(otRouterDowngradeThreshold);
DECL_IOCTL_FUNC(otCommissionerPanIdQuery);
DECL_IOCTL_FUNC(otCommissionerEnergyScan);
DECL_IOCTL_FUNC_WITH_TUN2(otRouterSelectionJitter);
DECL_IOCTL_FUNC(otJoinerUdpPort);
DECL_IOCTL_FUNC(otSendDiagnosticGet);
DECL_IOCTL_FUNC(otSendDiagnosticReset);
DECL_IOCTL_FUNC(otCommissionerAddJoiner);
DECL_IOCTL_FUNC(otCommissionerRemoveJoiner);
DECL_IOCTL_FUNC(otCommissionerProvisioningUrl);
DECL_IOCTL_FUNC(otCommissionerAnnounceBegin);
DECL_IOCTL_FUNC_WITH_TUN2(otEnergyScan);
DECL_IOCTL_FUNC(otSendActiveGet);
DECL_IOCTL_FUNC(otSendActiveSet);
DECL_IOCTL_FUNC(otSendPendingGet);
DECL_IOCTL_FUNC(otSendPendingSet);
DECL_IOCTL_FUNC(otSendMgmtCommissionerGet);
DECL_IOCTL_FUNC(otSendMgmtCommissionerSet);
DECL_IOCTL_FUNC_WITH_TUN2(otKeySwitchGuardtime);
DECL_IOCTL_FUNC(otFactoryReset);
#endif // _IOCONTROL_H
+18
View File
@@ -72,6 +72,7 @@ RtlCopyBufferToMdl(
#include <platform/misc.h>
#include <platform/alarm.h>
#include <platform/settings.h>
#include <ncp/spinel.h>
#include <otLwfIoctl.h>
#include <otOID.h>
@@ -89,7 +90,22 @@ RtlCopyBufferToMdl(
typedef struct _MS_FILTER MS_FILTER, *PMS_FILTER;
#pragma pack(push)
#pragma pack(1)
typedef struct UDPHeader
{
USHORT SourcePort;
USHORT DestinationPort;
USHORT TotalLength;
USHORT Checksum;
} UDPHeader;
#pragma pack(pop)
//#define DEBUG_TIMING
//#define DEBUG_ALLOC
//#define LOG_BUFFERS
//#define FORCE_SYNCHRONOUS_RECEIVE
@@ -99,3 +115,5 @@ typedef struct _MS_FILTER MS_FILTER, *PMS_FILTER;
#include "oid.h"
#include "radio.h"
#include "filter.h"
#include "thread.h"
#include "tunnel.h"
+533
View File
@@ -0,0 +1,533 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief
* This file implements the Thread mode (Radio Miniport) functions required for the OpenThread library.
*/
#include "precomp.h"
#include "thread.tmh"
_IRQL_requires_max_(PASSIVE_LEVEL)
NDIS_STATUS
otLwfInitializeThreadMode(
_In_ PMS_FILTER pFilter
)
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNET_BUFFER SendNetBuffer;
LogFuncEntry(DRIVER_DEFAULT);
do
{
// Create the SendNetBufferList
pFilter->SendNetBufferList =
NdisAllocateNetBufferAndNetBufferList(
pFilter->NetBufferListPool, // PoolHandle
0, // ContextSize
0, // ContextBackFill
NULL, // MdlChain
0, // DataOffset
0 // DataLength
);
if (pFilter->SendNetBufferList == NULL)
{
Status = NDIS_STATUS_RESOURCES;
LogWarning(DRIVER_DEFAULT, "Failed to create Send NetBufferList");
break;
}
// Initialize NetBuffer fields
SendNetBuffer = NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList);
NET_BUFFER_CURRENT_MDL(SendNetBuffer) = NULL;
NET_BUFFER_CURRENT_MDL_OFFSET(SendNetBuffer) = 0;
NET_BUFFER_DATA_LENGTH(SendNetBuffer) = 0;
NET_BUFFER_DATA_OFFSET(SendNetBuffer) = 0;
NET_BUFFER_FIRST_MDL(SendNetBuffer) = NULL;
// Allocate the NetBuffer for SendNetBufferList
Status = NdisRetreatNetBufferDataStart(SendNetBuffer, kMaxPHYPacketSize, 0, NULL);
if (Status != NDIS_STATUS_SUCCESS)
{
LogError(DRIVER_DEFAULT, "Failed to allocate NB for Send NetBufferList, %!NDIS_STATUS!", Status);
break;
}
KeInitializeEvent(
&pFilter->SendNetBufferListComplete,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
// Initialize the event processing
pFilter->EventWorkerThread = NULL;
NdisAllocateSpinLock(&pFilter->EventsLock);
InitializeListHead(&pFilter->AddressChangesHead);
InitializeListHead(&pFilter->NBLsHead);
InitializeListHead(&pFilter->EventIrpListHead);
KeInitializeEvent(
&pFilter->EventWorkerThreadStopEvent,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadWaitTimeUpdated,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessTasklets,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessAddressChanges,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessNBLs,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadProcessIrp,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
KeInitializeEvent(
&pFilter->EventWorkerThreadEnergyScanComplete,
SynchronizationEvent, // auto-clearing event
FALSE // event initially non-signalled
);
pFilter->EventHighPrecisionTimer =
ExAllocateTimer(
otLwfEventProcessingTimer,
pFilter,
EX_TIMER_HIGH_RESOLUTION
);
if (pFilter->EventHighPrecisionTimer == NULL)
{
LogError(DRIVER_DEFAULT, "Failed to allocate timer!");
break;
}
// Initialize the event processing thread
if (!NT_SUCCESS(otLwfEventProcessingStart(pFilter)))
{
Status = NDIS_STATUS_RESOURCES;
break;
}
} while (FALSE);
if (Status != NDIS_STATUS_SUCCESS)
{
// Stop event processing thread
otLwfEventProcessingStop(pFilter);
// Stop and free the timer
if (pFilter->EventHighPrecisionTimer)
{
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
}
// Free NBL
if (pFilter->SendNetBufferList)
{
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList), kMaxPHYPacketSize, TRUE, NULL);
NdisFreeNetBufferList(pFilter->SendNetBufferList);
}
}
LogFuncExitNDIS(DRIVER_DEFAULT, Status);
return Status;
}
_IRQL_requires_max_(PASSIVE_LEVEL)
void
otLwfUninitializeThreadMode(
_In_ PMS_FILTER pFilter
)
{
LogFuncEntry(DRIVER_DEFAULT);
// Stop event processing thread
otLwfEventProcessingStop(pFilter);
// Free timer
ExDeleteTimer(pFilter->EventHighPrecisionTimer, TRUE, FALSE, NULL);
// Free NBL & Pools
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pFilter->SendNetBufferList), kMaxPHYPacketSize, TRUE, NULL);
NdisFreeNetBufferList(pFilter->SendNetBufferList);
LogFuncExit(DRIVER_DEFAULT);
}
#if DEBUG_ALLOC
PMS_FILTER
otLwfFindFromCurrentThread()
{
PMS_FILTER pOutput = NULL;
HANDLE CurThreadId = PsGetCurrentThreadId();
NdisAcquireSpinLock(&FilterListLock);
for (PLIST_ENTRY Link = FilterModuleList.Flink; Link != &FilterModuleList; Link = Link->Flink)
{
PMS_FILTER pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink);
if (pFilter->otThreadId == CurThreadId)
{
pOutput = pFilter;
break;
}
}
NdisReleaseSpinLock(&FilterListLock);
NT_ASSERT(pOutput);
return pOutput;
}
#endif
//
// OpenThread Platform functions
//
void *otPlatCAlloc(size_t aNum, size_t aSize)
{
size_t totalSize = aNum * aSize;
#if DEBUG_ALLOC
totalSize += sizeof(OT_ALLOC);
#endif
PVOID mem = ExAllocatePoolWithTag(NonPagedPoolNx, totalSize, 'OTDM');
if (mem)
{
RtlZeroMemory(mem, totalSize);
#if DEBUG_ALLOC
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
//LogVerbose(DRIVER_DEFAULT, "otPlatAlloc(%u) = ID:%u %p", (ULONG)totalSize, pFilter->otAllocationID, mem);
OT_ALLOC* AllocHeader = (OT_ALLOC*)mem;
AllocHeader->Length = (LONG)totalSize;
AllocHeader->ID = pFilter->otAllocationID++;
InsertTailList(&pFilter->otOutStandingAllocations, &AllocHeader->Link);
InterlockedIncrement(&pFilter->otOutstandingAllocationCount);
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, AllocHeader->Length);
mem = (PUCHAR)(mem) + sizeof(OT_ALLOC);
#endif
}
return mem;
}
void otPlatFree(void *aPtr)
{
if (aPtr == NULL) return;
#if DEBUG_ALLOC
aPtr = (PUCHAR)(aPtr) - sizeof(OT_ALLOC);
//LogVerbose(DRIVER_DEFAULT, "otPlatFree(%p)", aPtr);
OT_ALLOC* AllocHeader = (OT_ALLOC*)aPtr;
PMS_FILTER pFilter = otLwfFindFromCurrentThread();
InterlockedDecrement(&pFilter->otOutstandingAllocationCount);
InterlockedAdd(&pFilter->otOutstandingMemoryAllocated, -AllocHeader->Length);
RemoveEntryList(&AllocHeader->Link);
#endif
ExFreePoolWithTag(aPtr, 'OTDM');
}
uint32_t otPlatRandomGet()
{
LARGE_INTEGER Counter = KeQueryPerformanceCounter(NULL);
return (uint32_t)RtlRandomEx(&Counter.LowPart);
}
ThreadError otPlatRandomSecureGet(uint16_t aInputLength, uint8_t *aOutput, uint16_t *aOutputLength)
{
// Just use the system-preferred random number generator algorithm
NTSTATUS status =
BCryptGenRandom(
NULL,
aOutput,
(ULONG)aInputLength,
BCRYPT_USE_SYSTEM_PREFERRED_RNG
);
NT_ASSERT(NT_SUCCESS(status));
if (!NT_SUCCESS(status))
{
LogError(DRIVER_DEFAULT, "BCryptGenRandom failed, %!STATUS!", status);
return kThreadError_Failed;
}
*aOutputLength = aInputLength;
return kThreadError_None;
}
void otSignalTaskletPending(_In_ otInstance *otCtx)
{
LogVerbose(DRIVER_DEFAULT, "otSignalTaskletPending");
PMS_FILTER pFilter = otCtxToFilter(otCtx);
otLwfEventProcessingIndicateNewTasklet(pFilter);
}
// Process a role state change
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfProcessRoleStateChange(
_In_ PMS_FILTER pFilter
)
{
otDeviceRole prevRole = pFilter->otCachedRole;
pFilter->otCachedRole = otGetDeviceRole(pFilter->otCtx);
if (prevRole == pFilter->otCachedRole) return;
LogInfo(DRIVER_DEFAULT, "Interface %!GUID! new role: %!otDeviceRole!", &pFilter->InterfaceGuid, pFilter->otCachedRole);
// Make sure we are in the correct media connect state
otLwfIndicateLinkState(
pFilter,
IsAttached(pFilter->otCachedRole) ?
MediaConnectStateConnected :
MediaConnectStateDisconnected);
}
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
//
// Process the notification internally
//
if ((aFlags & OT_IP6_ADDRESS_ADDED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_ADDED", pFilter);
otLwfRadioAddressesUpdated(pFilter);
}
if ((aFlags & OT_IP6_ADDRESS_REMOVED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ADDRESS_REMOVED", pFilter);
otLwfRadioAddressesUpdated(pFilter);
}
if ((aFlags & OT_NET_ROLE) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_ROLE", pFilter);
otLwfProcessRoleStateChange(pFilter);
}
if ((aFlags & OT_NET_PARTITION_ID) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_PARTITION_ID", pFilter);
}
if ((aFlags & OT_NET_KEY_SEQUENCE_COUNTER) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_NET_KEY_SEQUENCE_COUNTER", pFilter);
}
if ((aFlags & OT_THREAD_CHILD_ADDED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_ADDED", pFilter);
}
if ((aFlags & OT_THREAD_CHILD_REMOVED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_CHILD_REMOVED", pFilter);
}
if ((aFlags & OT_THREAD_NETDATA_UPDATED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_THREAD_NETDATA_UPDATED", pFilter);
otSlaacUpdate(pFilter->otCtx, pFilter->otAutoAddresses, ARRAYSIZE(pFilter->otAutoAddresses), otCreateRandomIid, NULL);
}
if ((aFlags & OT_IP6_ML_ADDR_CHANGED) != 0)
{
LogVerbose(DRIVER_DEFAULT, "Filter %p received OT_IP6_ML_ADDR_CHANGED", pFilter);
}
//
// Queue the notification for clients
//
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE;
NotifEntry->Notif.StateChangePayload.Flags = aFlags;
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ACTIVE_SCAN;
if (aResult)
{
NotifEntry->Notif.ActiveScanPayload.Valid = TRUE;
NotifEntry->Notif.ActiveScanPayload.Results = *aResult;
}
else
{
NotifEntry->Notif.ActiveScanPayload.Valid = FALSE;
}
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_ENERGY_SCAN;
if (aResult)
{
NotifEntry->Notif.EnergyScanPayload.Valid = TRUE;
NotifEntry->Notif.EnergyScanPayload.Results = *aResult;
}
else
{
NotifEntry->Notif.EnergyScanPayload.Valid = FALSE;
}
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_DISCOVER;
if (aResult)
{
NotifEntry->Notif.DiscoverPayload.Valid = TRUE;
NotifEntry->Notif.DiscoverPayload.Results = *aResult;
}
else
{
NotifEntry->Notif.DiscoverPayload.Valid = FALSE;
}
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_ENERGY_REPORT;
// Limit the number of reports if necessary
if (aEnergyListLength > MAX_ENERGY_REPORT_LENGTH) aEnergyListLength = MAX_ENERGY_REPORT_LENGTH;
NotifEntry->Notif.CommissionerEnergyReportPayload.ChannelMask = aChannelMask;
NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyListLength = aEnergyListLength;
memcpy(NotifEntry->Notif.CommissionerEnergyReportPayload.EnergyList, aEnergyList, aEnergyListLength);
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext)
{
LogFuncEntry(DRIVER_DEFAULT);
PMS_FILTER pFilter = (PMS_FILTER)aContext;
PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
if (NotifEntry)
{
RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
NotifEntry->Notif.NotifType = OTLWF_NOTIF_COMMISSIONER_PANID_QUERY;
NotifEntry->Notif.CommissionerPanIdQueryPayload.PanId = aPanId;
NotifEntry->Notif.CommissionerPanIdQueryPayload.ChannelMask = aChannelMask;
otLwfIndicateNotification(NotifEntry);
}
LogFuncExit(DRIVER_DEFAULT);
}
+148
View File
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief
* This file defines the functions for the otLwf Filter Thread mode.
*/
#ifndef _THREAD_H_
#define _THREAD_H_
// Helper function that converts an otInstance pointer to a MS_FILTER pointer
__inline PMS_FILTER otCtxToFilter(_In_ otInstance* otCtx)
{
return *(PMS_FILTER*)((PUCHAR)otCtx - sizeof(PMS_FILTER));
}
// Helper function to indicate if a role means it is attached or not
_inline BOOLEAN IsAttached(_In_ otDeviceRole role)
{
return role > kDeviceRoleDetached;
}
//
// Initialization functions
//
_IRQL_requires_max_(PASSIVE_LEVEL)
NDIS_STATUS
otLwfInitializeThreadMode(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
otLwfUninitializeThreadMode(
_In_ PMS_FILTER pFilter
);
//
// Event Processing Functions
//
EXT_CALLBACK otLwfEventProcessingTimer;
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfEventProcessingStart(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingStop(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateNewWaitTime(
_In_ PMS_FILTER pFilter,
_In_ ULONG waitTime
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateNewTasklet(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateAddressChange(
_In_ PMS_FILTER pFilter,
_In_ MIB_NOTIFICATION_TYPE NotificationType,
_In_ PIN6_ADDR pAddr
);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateNewNetBufferLists(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN DispatchLevel,
_In_ BOOLEAN Received,
_In_ NDIS_PORT_NUMBER PortNumber,
_In_ PNET_BUFFER_LIST NetBufferLists
);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateNetBufferListsCancelled(
_In_ PMS_FILTER pFilter,
_In_ PVOID CancelId
);
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
otLwfEventProcessingIndicateIrp(
_In_ PMS_FILTER pFilter,
_In_ PIRP Irp
);
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
otLwfEventProcessingIndicateEnergyScanResult(
_In_ PMS_FILTER pFilter,
_In_ CHAR MaxRssi
);
//
// OpenThread callbacks
//
void otLwfStateChangedCallback(uint32_t aFlags, _In_ void *aContext);
void otLwfReceiveIp6DatagramCallback(_In_ otMessage aMessage, _In_ void *aContext);
void otLwfActiveScanCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
void otLwfEnergyScanCallback(_In_ otEnergyScanResult *aResult, _In_ void *aContext);
void otLwfDiscoverCallback(_In_ otActiveScanResult *aResult, _In_ void *aContext);
void otLwfCommissionerEnergyReportCallback(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext);
void otLwfCommissionerPanIdConflictCallback(uint16_t aPanId, uint32_t aChannelMask, _In_ void *aContext);
#endif //_THREAD_H_
File diff suppressed because it is too large Load Diff
+195
View File
@@ -0,0 +1,195 @@
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* @brief
* This file defines the functions for the otLwf Filter Tunnel mode.
*/
#ifndef _TUNNEL_H_
#define _TUNNEL_H_
typedef
_IRQL_requires_max_(DISPATCH_LEVEL)
VOID
(SPINEL_CMD_HANDLER)(
_In_ PMS_FILTER pFilter,
_In_ PVOID Context,
_In_ UINT Command,
_In_ spinel_prop_key_t Key,
_In_reads_bytes_(DataLength) const uint8_t* Data,
_In_ spinel_size_t DataLength
);
typedef struct _SPINEL_CMD_HANDLER_ENTRY
{
LIST_ENTRY Link;
SPINEL_CMD_HANDLER *Handler;
PVOID Context;
spinel_tid_t TransactionId;
} SPINEL_CMD_HANDLER_ENTRY;
//
// Initialization Functions
//
_IRQL_requires_max_(PASSIVE_LEVEL)
NDIS_STATUS
otLwfInitializeTunnelMode(
_In_ PMS_FILTER pFilter
);
_IRQL_requires_max_(PASSIVE_LEVEL)
void
otLwfUninitializeTunnelMode(
_In_ PMS_FILTER pFilter
);
//
// Spinel Packet Functions
//
_IRQL_requires_max_(DISPATCH_LEVEL)
BOOLEAN
otLwfCancelCommandHandler(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN DispatchLevel,
_In_ spinel_tid_t tid
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfSendTunnelCommandWithHandlerV(
_In_ PMS_FILTER pFilter,
_In_opt_ SPINEL_CMD_HANDLER *Handler,
_In_opt_ PVOID HandlerContext,
_Out_opt_ spinel_tid_t *pTid,
_In_ UINT Command,
_In_ spinel_prop_key_t Key,
_In_ ULONG MaxDataLength,
_In_opt_ const char *pack_format,
_In_opt_ va_list args
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfSendTunnelCommandWithHandler(
_In_ PMS_FILTER pFilter,
_In_opt_ SPINEL_CMD_HANDLER *Handler,
_In_opt_ PVOID HandlerContext,
_Out_opt_ spinel_tid_t *pTid,
_In_ UINT Command,
_In_ spinel_prop_key_t Key,
_In_ ULONG MaxDataLength,
_In_opt_ const char *pack_format,
...
);
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
otLwfSendTunnelPacket(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN DispatchLevel,
_In_ PNET_BUFFER IpNetBuffer,
_In_ BOOLEAN Secured
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
otLwfReceiveTunnelPacket(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN DispatchLevel,
_In_reads_bytes_(BufferLength) const PUCHAR Buffer,
_In_ ULONG BufferLength
);
_IRQL_requires_max_(DISPATCH_LEVEL)
void
otLwfProcessSpinelIPv6Packet(
_In_ PMS_FILTER pFilter,
_In_ BOOLEAN DispatchLevel,
_In_ BOOLEAN Secure,
_In_reads_bytes_(BufferLength) const uint8_t* Buffer,
_In_ UINT BufferLength
);
//
// Irp Commands
//
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfSendTunnelCommandForIrp(
_In_ PMS_FILTER pFilter,
_In_ PIRP Irp,
_In_opt_ SPINEL_IRP_CMD_HANDLER *Handler,
_In_ UINT Command,
_In_ spinel_prop_key_t Key,
_In_ ULONG MaxDataLength,
_In_opt_ const char *pack_format,
...
);
//
// Spinel Helper Functions
//
ThreadError
SpinelStatusToThreadError(
spinel_status_t error
);
BOOLEAN
try_spinel_datatype_unpack(
const uint8_t *data_in,
spinel_size_t data_len,
const char *pack_format,
...
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfGetTunProp(
_In_ PMS_FILTER pFilter,
_Out_opt_ PVOID *DataBuffer,
_In_ spinel_prop_key_t Key,
_In_ const char *pack_format,
...
);
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
otLwfSetTunProp(
_In_ PMS_FILTER pFilter,
_In_ spinel_prop_key_t Key,
_In_ const char *pack_format,
...
);
#endif //_TUNNEL_H_
+9 -2
View File
@@ -70,6 +70,12 @@
#define EINVAL 1
#endif
#ifdef _KERNEL_MODE
#define va_copy(destination, source) ((destination) = (source))
#undef errno
#define assert_printf(fmt, ...)
#endif
#if defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
#error "SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR is set but errno is already defined."
#endif
@@ -443,7 +449,7 @@ spinel_datatype_vunpack_(const uint8_t *data_ptr, spinel_size_t data_len, const
*block_len_ptr = block_len;
}
block_len += pui_len;
block_len += (uint16_t)pui_len;
ret += block_len;
data_ptr += block_len;
data_len -= block_len;
@@ -480,7 +486,7 @@ spinel_datatype_vunpack_(const uint8_t *data_ptr, spinel_size_t data_len, const
if (pui_len)
{
block_len += pui_len;
block_len += (uint16_t)pui_len;
}
else
{
@@ -525,6 +531,7 @@ spinel_datatype_unpack(const uint8_t *data_ptr, spinel_size_t data_len, const ch
return ret;
}
spinel_ssize_t
spinel_datatype_vunpack(const uint8_t *data_ptr, spinel_size_t data_len, const char *pack_format, va_list args)
{