Author: cgutman
Date: Fri Dec 2 01:56:10 2011
New Revision: 54559
URL:
http://svn.reactos.org/svn/reactos?rev=54559&view=rev
Log:
[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
Modified:
trunk/reactos/drivers/network/ndis/ndis/50stubs.c
trunk/reactos/drivers/network/ndis/ndis/miniport.c
Modified: trunk/reactos/drivers/network/ndis/ndis/50stubs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/ndis/ndis/…
==============================================================================
--- trunk/reactos/drivers/network/ndis/ndis/50stubs.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/ndis/ndis/50stubs.c [iso-8859-1] Fri Dec 2 01:56:10
2011
@@ -490,25 +490,6 @@
/*
* @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
- */
UINT
EXPORT
NdisPacketPoolUsage(
Modified: trunk/reactos/drivers/network/ndis/ndis/miniport.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/ndis/ndis/…
==============================================================================
--- trunk/reactos/drivers/network/ndis/ndis/miniport.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/network/ndis/ndis/miniport.c [iso-8859-1] Fri Dec 2 01:56:10
2011
@@ -245,7 +245,41 @@
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
MiniIndicateReceivePacket(
IN NDIS_HANDLE MiniportAdapterHandle,
@@ -260,87 +294,139 @@
*
*/
{
- PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
- PLIST_ENTRY CurrentEntry;
- PADAPTER_BINDING AdapterBinding;
- KIRQL OldIrql;
- UINT i;
-
- KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-
- CurrentEntry = Adapter->ProtocolListHead.Flink;
-
- while (CurrentEntry != &Adapter->ProtocolListHead)
- {
- AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING,
AdapterListEntry);
-
- for (i = 0; i < NumberOfPackets; i++)
- {
- if (AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler
&&
- NDIS_GET_PACKET_STATUS(PacketArray[i]) != NDIS_STATUS_RESOURCES)
- {
- (*AdapterBinding->ProtocolBinding->Chars.ReceivePacketHandler)(
- AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
- PacketArray[i]);
- }
- else
- {
- UINT FirstBufferLength, TotalBufferLength, LookAheadSize, HeaderSize;
- PNDIS_BUFFER NdisBuffer;
- PVOID NdisBufferVA, LookAheadBuffer;
- NDIS_STATUS NdisStatus;
-
-
- NdisGetFirstBufferFromPacket(PacketArray[i],
- &NdisBuffer,
- &NdisBufferVA,
- &FirstBufferLength,
- &TotalBufferLength);
-
- HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
-
- if (Adapter->NdisMiniportBlock.CurrentLookahead < (TotalBufferLength
- HeaderSize))
- {
- LookAheadSize = Adapter->NdisMiniportBlock.CurrentLookahead;
- }
- else
- {
- LookAheadSize = TotalBufferLength - HeaderSize;
- }
-
-
- LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
- if (!LookAheadBuffer)
- {
- NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead
buffer!\n"));
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
- return;
- }
-
- CopyBufferChainToBuffer(LookAheadBuffer,
- NdisBuffer,
- HeaderSize,
- LookAheadSize);
-
- NdisStatus =
(*AdapterBinding->ProtocolBinding->Chars.ReceiveHandler)(
- AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
- AdapterBinding->NdisOpenBlock.MacHandle,
- NdisBufferVA,
- HeaderSize,
- LookAheadBuffer,
- LookAheadSize,
- TotalBufferLength - HeaderSize);
-
- NDIS_SET_PACKET_STATUS(PacketArray[i], NdisStatus);
-
- ExFreePool(LookAheadBuffer);
- }
- }
-
- CurrentEntry = CurrentEntry->Flink;
- }
-
- KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
+ PLIST_ENTRY CurrentEntry;
+ PADAPTER_BINDING AdapterBinding;
+ KIRQL OldIrql;
+ UINT i;
+
+ KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+
+ CurrentEntry = Adapter->ProtocolListHead.Flink;
+
+ while (CurrentEntry != &Adapter->ProtocolListHead)
+ {
+ AdapterBinding = CONTAINING_RECORD(CurrentEntry, ADAPTER_BINDING,
AdapterListEntry);
+
+ for (i = 0; i < NumberOfPackets; i++)
+ {
+ /* Store the indicating miniport in the packet */
+ PacketArray[i]->Reserved[1] = (ULONG_PTR)Adapter;
+
+ 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],
+ &NdisBuffer,
+ &NdisBufferVA,
+ &FirstBufferLength,
+ &TotalBufferLength);
+
+ HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(PacketArray[i]);
+
+ if (Adapter->NdisMiniportBlock.CurrentLookahead <
(TotalBufferLength - HeaderSize))
+ {
+ LookAheadSize = Adapter->NdisMiniportBlock.CurrentLookahead;
+ }
+ else
+ {
+ LookAheadSize = TotalBufferLength - HeaderSize;
+ }
+
+ LookAheadBuffer = ExAllocatePool(NonPagedPool, LookAheadSize);
+ if (!LookAheadBuffer)
+ {
+ NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate lookahead
buffer!\n"));
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+ return;
+ }
+
+ 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;
+ }
+
+ /* Loop the packet array to get everything
+ * set up for return the packets to the miniport */
+ for (i = 0; i < NumberOfPackets; i++)
+ {
+ /* First, check the initial packet status */
+ 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;
+ }
+
+ /* Different behavior depending on whether it's serialized or not */
+ if (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
+ {
+ /* 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);
+
+ NDIS_DbgPrint(MID_TRACE, ("Packet has been returned to miniport
(Serialized)\n"));
+ }
+ else
+ {
+ /* NDIS_STATUS_PENDING means the miniport needs to wait for
MiniportReturnPacket */
+ NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_PENDING);
+
+ NDIS_DbgPrint(MID_TRACE, ("Packet will be returned to miniport later
(Serialized)\n"));
+ }
+ }
+ }
+
+ KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
}