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/50stubs.c?rev=54559&r1=54558&r2=54559&view=diff
==============================================================================
--- 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/miniport.c?rev=54559&r1=54558&r2=54559&view=diff
==============================================================================
--- 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);
 }
 
 


Reply via email to