mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +00:00
[NDIS]
- Implement NdisReturnPackets and do proper reference tracking of packets sent to ProtocolReceivePacket - Plug a massive memory leak that resulted in leaking every packet descriptor that any deserialized miniport indicated to TCP/IP svn path=/trunk/; revision=54559
This commit is contained in:
parent
f5fda30d65
commit
77ed514f64
|
@ -487,25 +487,6 @@ NdisIMInitializeDeviceInstanceEx(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @unimplemented
|
|
||||||
*/
|
|
||||||
VOID
|
|
||||||
EXPORT
|
|
||||||
NdisReturnPackets(
|
|
||||||
IN PNDIS_PACKET *PacketsToReturn,
|
|
||||||
IN UINT NumberOfPackets)
|
|
||||||
/*
|
|
||||||
* FUNCTION: Releases ownership of one or more packets
|
|
||||||
* ARGUMENTS:
|
|
||||||
* PacketsToReturn = Pointer to an array of pointers to packet descriptors
|
|
||||||
* NumberOfPackets = Number of pointers in descriptor pointer array
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @unimplemented
|
* @unimplemented
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -245,7 +245,41 @@ MiniIndicateData(
|
||||||
NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
|
NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
EXPORT
|
||||||
|
NdisReturnPackets(
|
||||||
|
IN PNDIS_PACKET *PacketsToReturn,
|
||||||
|
IN UINT NumberOfPackets)
|
||||||
|
/*
|
||||||
|
* FUNCTION: Releases ownership of one or more packets
|
||||||
|
* ARGUMENTS:
|
||||||
|
* PacketsToReturn = Pointer to an array of pointers to packet descriptors
|
||||||
|
* NumberOfPackets = Number of pointers in descriptor pointer array
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
PLOGICAL_ADAPTER Adapter;
|
||||||
|
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Returning %d packets\n", NumberOfPackets));
|
||||||
|
|
||||||
|
for (i = 0; i < NumberOfPackets; i++)
|
||||||
|
{
|
||||||
|
PacketsToReturn[i]->WrapperReserved[0]--;
|
||||||
|
if (PacketsToReturn[i]->WrapperReserved[0] == 0)
|
||||||
|
{
|
||||||
|
Adapter = (PVOID)(ULONG_PTR)PacketsToReturn[i]->Reserved[1];
|
||||||
|
|
||||||
|
NDIS_DbgPrint(MAX_TRACE, ("Freeing packet %d (adapter = 0x%p)\n", i, Adapter));
|
||||||
|
|
||||||
|
Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
|
||||||
|
Adapter->NdisMiniportBlock.MiniportAdapterContext,
|
||||||
|
PacketsToReturn[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
MiniIndicateReceivePacket(
|
MiniIndicateReceivePacket(
|
||||||
IN NDIS_HANDLE MiniportAdapterHandle,
|
IN NDIS_HANDLE MiniportAdapterHandle,
|
||||||
|
@ -260,87 +294,139 @@ MiniIndicateReceivePacket(
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
|
PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
|
||||||
PLIST_ENTRY CurrentEntry;
|
PLIST_ENTRY CurrentEntry;
|
||||||
PADAPTER_BINDING AdapterBinding;
|
PADAPTER_BINDING AdapterBinding;
|
||||||
KIRQL OldIrql;
|
KIRQL OldIrql;
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
|
KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
|
||||||
|
|
||||||
CurrentEntry = Adapter->ProtocolListHead.Flink;
|
CurrentEntry = Adapter->ProtocolListHead.Flink;
|
||||||
|
|
||||||
while (CurrentEntry != &Adapter->ProtocolListHead)
|
while (CurrentEntry != &Adapter->ProtocolListHead)
|
||||||
{
|
{
|
||||||
AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
|
AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING, AdapterListEntry);
|
||||||
|
|
||||||
for (i = 0; i < NumberOfPackets; i++)
|
for (i = 0; i < NumberOfPackets; i++)
|
||||||
{
|
{
|
||||||
if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
|
/* Store the indicating miniport in the packet */
|
||||||
NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
|
PacketArray[i]->Reserved[1] = (ULONG_PTR)Adapter;
|
||||||
{
|
|
||||||
(*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
|
|
||||||
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
|
|
||||||
PacketArray[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
|
|
||||||
PNDIS_BUFFER NdisBuffer;
|
|
||||||
PVOID NdisBufferVA, LookAheadBuffer;
|
|
||||||
NDIS_STATUS NdisStatus;
|
|
||||||
|
|
||||||
|
if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler &&
|
||||||
|
NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
|
||||||
|
{
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's ReceivePacket handler\n"));
|
||||||
|
PacketArray[i]->WrapperReserved[0] += (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
|
||||||
|
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
|
||||||
|
PacketArray[i]);
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Protocol is holding %d references to the packet\n", PacketArray[i]->WrapperReserved[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
|
||||||
|
PNDIS_BUFFER NdisBuffer;
|
||||||
|
PVOID NdisBufferVA, LookAheadBuffer;
|
||||||
|
|
||||||
NdisGetFirstBufferFromPacket(PacketArray[i],
|
NdisGetFirstBufferFromPacket(PacketArray[i],
|
||||||
&NdisBuffer,
|
&NdisBuffer,
|
||||||
&NdisBufferVA,
|
&NdisBufferVA,
|
||||||
&FirstBufferLength,
|
&FirstBufferLength,
|
||||||
&TotalBufferLength);
|
&TotalBufferLength);
|
||||||
|
|
||||||
|
HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
|
||||||
|
|
||||||
HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
|
if (Adapter->NdisMiniportBlock.CurrentLookahead < (TotalBufferLength - HeaderSize))
|
||||||
|
{
|
||||||
|
LookAheadSize = Adapter->NdisMiniportBlock.CurrentLookahead;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LookAheadSize = TotalBufferLength - HeaderSize;
|
||||||
|
}
|
||||||
|
|
||||||
if (Adapter->NdisMiniportBlock.CurrentLookahead < (TotalBufferLength - HeaderSize))
|
LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
|
||||||
{
|
if (!LookAheadBuffer)
|
||||||
LookAheadSize = Adapter->NdisMiniportBlock.CurrentLookahead;
|
{
|
||||||
}
|
NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
|
||||||
else
|
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
|
||||||
{
|
return;
|
||||||
LookAheadSize = TotalBufferLength - HeaderSize;
|
}
|
||||||
}
|
|
||||||
|
CopyBufferChainToBuffer(LookAheadBuffer,
|
||||||
|
NdisBuffer,
|
||||||
|
HeaderSize,
|
||||||
|
LookAheadSize);
|
||||||
|
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Indicating packet to protocol's legacy Receive handler\n"));
|
||||||
|
(*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
|
||||||
|
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
|
||||||
|
AdapterBinding->NdisOpenBlock.MacHandle,
|
||||||
|
NdisBufferVA,
|
||||||
|
HeaderSize,
|
||||||
|
LookAheadBuffer,
|
||||||
|
LookAheadSize,
|
||||||
|
TotalBufferLength - HeaderSize);
|
||||||
|
|
||||||
|
ExFreePool(LookAheadBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
|
/* Loop the packet array to get everything
|
||||||
if (!LookAheadBuffer)
|
* set up for return the packets to the miniport */
|
||||||
{
|
for (i = 0; i < NumberOfPackets; i++)
|
||||||
NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead buffer!\n"));
|
{
|
||||||
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
|
/* First, check the initial packet status */
|
||||||
return;
|
if (NDIS_GET_PACKET_STATUS(PacketArray[i]) == NDIS_STATUS_RESOURCES)
|
||||||
}
|
{
|
||||||
|
/* The miniport driver gets it back immediately so nothing to do here */
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Miniport needs the packet back immediately\n"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
CopyBufferChainToBuffer(LookAheadBuffer,
|
/* Different behavior depending on whether it's serialized or not */
|
||||||
NdisBuffer,
|
if (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
|
||||||
HeaderSize,
|
{
|
||||||
LookAheadSize);
|
/* We need to check the reference count */
|
||||||
|
if (PacketArray[i]->WrapperReserved[0] == 0)
|
||||||
|
{
|
||||||
|
/* NOTE: Unlike serialized miniports, this is REQUIRED to be called for each
|
||||||
|
* packet received that can be reused immediately, it is not implied! */
|
||||||
|
Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.ReturnPacketHandler(
|
||||||
|
Adapter->NdisMiniportBlock.MiniportAdapterContext,
|
||||||
|
PacketArray[i]);
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Deserialized)\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Packet will be returned by the protocol's call to NdisReturnPackets */
|
||||||
|
NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Deserialized)\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check the reference count */
|
||||||
|
if (PacketArray[i]->WrapperReserved[0] == 0)
|
||||||
|
{
|
||||||
|
/* NDIS_STATUS_SUCCESS means the miniport can have the packet back immediately */
|
||||||
|
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS);
|
||||||
|
|
||||||
NdisStatus = (*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
|
NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport (Serialized)\n"));
|
||||||
AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
|
}
|
||||||
AdapterBinding->NdisOpenBlock.MacHandle,
|
else
|
||||||
NdisBufferVA,
|
{
|
||||||
HeaderSize,
|
/* NDIS_STATUS_PENDING means the miniport needs to wait for MiniportReturnPacket */
|
||||||
LookAheadBuffer,
|
NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_PENDING);
|
||||||
LookAheadSize,
|
|
||||||
TotalBufferLength - HeaderSize);
|
|
||||||
|
|
||||||
NDIS_SET_PACKET_STATUS(PacketArray[i], NdisStatus);
|
NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later (Serialized)\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ExFreePool(LookAheadBuffer);
|
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentEntry = CurrentEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue