Fixed connection locking in tcp.c

Added a work item in lan.c re: dpc callback from the adapter.  This keeps
us from needing mdl functions at dpc level.
Track IRPs to be completed with memtrack.

svn path=/trunk/; revision=11051
This commit is contained in:
Art Yerkes 2004-09-25 20:24:00 +00:00
parent ee0f0ee26f
commit 3725308f3e
12 changed files with 167 additions and 43 deletions

View file

@ -10,11 +10,23 @@
#include "precomp.h"
typedef struct _LAN_WQ_ITEM {
LIST_ENTRY ListEntry;
PNDIS_PACKET Packet;
PLAN_ADAPTER Adapter;
UINT BytesTransferred;
} LAN_WQ_ITEM, *PLAN_WQ_ITEM;
NDIS_HANDLE NdisProtocolHandle = (NDIS_HANDLE)NULL;
BOOLEAN ProtocolRegistered = FALSE;
LIST_ENTRY AdapterListHead;
KSPIN_LOCK AdapterListLock;
/* Work around being called back into afd at Dpc level */
KSPIN_LOCK LanWorkLock;
LIST_ENTRY LanWorkList;
WORK_QUEUE_ITEM LanWorkItem;
NDIS_STATUS NDISCall(
PLAN_ADAPTER Adapter,
NDIS_REQUEST_TYPE Type,
@ -178,35 +190,31 @@ VOID STDCALL ProtocolSendComplete(
TI_DbgPrint(DEBUG_DATALINK, ("Finished\n"));
}
VOID STDCALL ProtocolTransferDataComplete(
NDIS_HANDLE BindingContext,
PNDIS_PACKET Packet,
NDIS_STATUS Status,
UINT BytesTransferred)
/*
* FUNCTION: Called by NDIS to complete reception of data
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Packet = Pointer to a packet descriptor
* Status = Status of the operation
* BytesTransferred = Number of bytes transferred
* NOTES:
* If the packet was successfully received, determine the protocol
* type and pass it to the correct receive handler
*/
{
VOID STDCALL LanReceiveWorker( PVOID Context ) {
UINT PacketType;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
PLIST_ENTRY ListEntry;
PLAN_WQ_ITEM WorkItem;
PNDIS_PACKET Packet;
PLAN_ADAPTER Adapter;
UINT BytesTransferred;
PNDIS_BUFFER NdisBuffer;
IP_PACKET IPPacket;
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
if (Status == NDIS_STATUS_SUCCESS) {
PNDIS_BUFFER NdisBuffer;
IP_PACKET IPPacket;
while( (ListEntry =
ExInterlockedRemoveHeadList( &LanWorkList, &LanWorkLock )) ) {
WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry);
Packet = WorkItem->Packet;
Adapter = WorkItem->Adapter;
BytesTransferred = WorkItem->BytesTransferred;
ExFreePool( WorkItem );
IPPacket.NdisPacket = Packet;
NdisGetFirstBufferFromPacket(Packet,
&NdisBuffer,
&IPPacket.Header,
@ -241,11 +249,46 @@ VOID STDCALL ProtocolTransferDataComplete(
default:
break;
}
}
FreeNdisPacket( Packet );
FreeNdisPacket( Packet );
}
}
VOID STDCALL ProtocolTransferDataComplete(
NDIS_HANDLE BindingContext,
PNDIS_PACKET Packet,
NDIS_STATUS Status,
UINT BytesTransferred)
/*
* FUNCTION: Called by NDIS to complete reception of data
* ARGUMENTS:
* BindingContext = Pointer to a device context (LAN_ADAPTER)
* Packet = Pointer to a packet descriptor
* Status = Status of the operation
* BytesTransferred = Number of bytes transferred
* NOTES:
* If the packet was successfully received, determine the protocol
* type and pass it to the correct receive handler
*/
{
BOOLEAN WorkStart;
PLAN_WQ_ITEM WQItem;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
if( Status != NDIS_STATUS_SUCCESS ) return;
WQItem = ExAllocatePool( NonPagedPool, sizeof(LAN_WQ_ITEM) );
if( !WQItem ) return;
KeAcquireSpinLockAtDpcLevel( &LanWorkLock );
WorkStart = IsListEmpty( &LanWorkList );
WQItem->Packet = Packet;
WQItem->Adapter = Adapter;
WQItem->BytesTransferred = BytesTransferred;
InsertTailList( &LanWorkList, &WQItem->ListEntry );
if( WorkStart )
ExQueueWorkItem( &LanWorkItem, CriticalWorkQueue );
KeReleaseSpinLockFromDpcLevel( &LanWorkLock );
}
NDIS_STATUS STDCALL ProtocolReceive(
NDIS_HANDLE BindingContext,
@ -313,7 +356,11 @@ NDIS_STATUS STDCALL ProtocolReceive(
KeAcquireSpinLockAtDpcLevel(&Adapter->Lock);
NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL, Adapter->MTU );
if( NdisStatus != NDIS_STATUS_SUCCESS ) return NDIS_STATUS_NOT_ACCEPTED;
if( NdisStatus != NDIS_STATUS_SUCCESS ) {
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
return NDIS_STATUS_NOT_ACCEPTED;
}
TI_DbgPrint(DEBUG_DATALINK, ("pretransfer LookaheadBufferSize %d packsize %d\n",LookaheadBufferSize,PacketSize));
{
UINT temp;
@ -350,14 +397,15 @@ NDIS_STATUS STDCALL ProtocolReceive(
#endif
TI_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));
/* Release the packet descriptor */
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
if (NdisStatus != NDIS_STATUS_PENDING)
ProtocolTransferDataComplete(BindingContext,
NdisPacket,
NdisStatus,
PacketSize + HeaderBufferSize);
PacketSize + HeaderBufferSize);
/* Release the packet descriptor */
KeReleaseSpinLockFromDpcLevel(&Adapter->Lock);
TI_DbgPrint(DEBUG_DATALINK, ("leaving\n"));
return NDIS_STATUS_SUCCESS;
@ -448,6 +496,7 @@ VOID LANTransmit(
NDIS_STATUS NdisStatus;
PETH_HEADER EHeader;
PVOID Data;
KIRQL OldIrql;
PLAN_ADAPTER Adapter = (PLAN_ADAPTER)Context;
TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
@ -502,7 +551,10 @@ VOID LANTransmit(
break;
}
KeAcquireSpinLock( &Adapter->Lock, &OldIrql );
NdisSend(&NdisStatus, Adapter->NdisHandle, NdisPacket);
KeReleaseSpinLock( &Adapter->Lock, OldIrql );
if (NdisStatus != NDIS_STATUS_PENDING)
ProtocolSendComplete((NDIS_HANDLE)Context, NdisPacket, NdisStatus);
} else {
@ -1021,4 +1073,24 @@ VOID LANUnregisterProtocol(
}
}
VOID LANStartup() {
InitializeListHead( &LanWorkList );
ExInitializeWorkItem( &LanWorkItem, LanReceiveWorker, NULL );
}
VOID LANShutdown() {
KIRQL OldIrql;
PLAN_WQ_ITEM WorkItem;
PLIST_ENTRY ListEntry;
KeAcquireSpinLock( &LanWorkLock, &OldIrql );
while( !IsListEmpty( &LanWorkList ) ) {
ListEntry = RemoveHeadList( &LanWorkList );
WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry);
FreeNdisPacket( WorkItem->Packet );
ExFreePool( WorkItem );
}
KeReleaseSpinLock( &LanWorkLock, OldIrql );
}
/* EOF */

View file

@ -7,6 +7,13 @@
#ifndef __IRP_H
#define __IRP_H
VOID IRPRemember( PIRP Irp, PCHAR File, UINT Line );
NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status );
#ifdef MEMTRACK
#define RIRP(x) IRPRemember(x,__FILE__,__LINE__)
#else
#define RIRP(x)
#endif
#endif/*__IRP_H*/

View file

@ -33,6 +33,9 @@ typedef struct ETH_HEADER {
/* Offset of broadcast address */
#define BCAST_ETH_OFFSET 0x00
/* Max packets queued for a single adapter */
#define IP_MAX_RECV_BACKLOG 0x20
/* Per adapter information */
typedef struct LAN_ADAPTER {
LIST_ENTRY ListEntry; /* Entry on list */
@ -92,6 +95,9 @@ NTSTATUS LANRegisterProtocol(
VOID LANUnregisterProtocol(
VOID);
VOID LANStartup();
VOID LANShutdown();
NDIS_STATUS NDISCall(
PLAN_ADAPTER Adapter,
NDIS_REQUEST_TYPE Type,

View file

@ -7,6 +7,7 @@
#define FBSD_MALLOC FOURCC('d','s','b','f')
#define EXALLOC_TAG FOURCC('E','x','A','l')
#define IRP_TAG FOURCC('P','I','R','P')
#define AllocatePacketWithBuffer(x,y,z) AllocatePacketWithBufferX(x,y,z,__FILE__,__LINE__)
#define FreeNdisPacket(x) FreeNdisPacketX(x,__FILE__,__LINE__)

View file

@ -1,6 +1,7 @@
#include <limits.h>
#include <ddk/ntddk.h>
#include <rosrtl/string.h>
#include <rosrtl/recmutex.h>
#include <roscfg.h>
#include <tcpip.h>
#include <loopback.h>

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.20 2004/08/19 21:38:58 arty Exp $
# $Id: makefile,v 1.21 2004/09/25 20:23:59 arty Exp $
PATH_TO_TOP = ../../..
@ -21,7 +21,9 @@ TARGET_CFLAGS = \
-I$(PATH_TO_TOP)/w32api/include \
-I$(PATH_TO_TOP)/include
TARGET_DDKLIBS = ndis.a $(PATH_TO_TOP)/dk/w32/lib/oskittcp.a
TARGET_DDKLIBS = ndis.a \
$(PATH_TO_TOP)/dk/w32/lib/oskittcp.a \
$(PATH_TO_TOP)/dk/w32/lib/rosrtl.a
TARGET_CLEAN = \
tcpip/*.o \

View file

@ -130,7 +130,6 @@ VOID DispCancelRequest(
/* Try canceling the request */
switch(MinorFunction) {
case TDI_SEND:
case TDI_RECEIVE:
/* FIXME: Close connection */
break;

View file

@ -11,10 +11,19 @@
#include "precomp.h"
VOID IRPRemember( PIRP Irp, PCHAR File, UINT Line ) {
#ifdef MEMTRACK
TrackWithTag( IRP_TAG, Irp, File, Line );
#endif
}
NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status ) {
TI_DbgPrint(MID_TRACE,("Called: Irp %x, Status %x Event %x\n", Irp, Status, Irp->UserEvent));
#ifdef MEMTRACK
UntrackFL( __FILE__, __LINE__, Irp );
#endif
IoSetCancelRoutine( Irp, NULL );
if( Status == STATUS_PENDING )

View file

@ -9,7 +9,7 @@
*/
#include "precomp.h"
#define NDEBUG
//#define NDEBUG
#ifndef NDEBUG
DWORD DebugTraceLevel = 0x7fffffff;
@ -425,6 +425,8 @@ TiDispatchOpenClose(
NTSTATUS Status;
PTRANSPORT_CONTEXT Context;
RIRP(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
IoMarkIrpPending(Irp);
@ -483,6 +485,8 @@ TiDispatchInternal(
BOOL Complete = TRUE;
PIO_STACK_LOCATION IrpSp;
RIRP(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
@ -584,6 +588,8 @@ TiDispatch(
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
RIRP(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp));
@ -658,6 +664,9 @@ VOID STDCALL TiUnload(
/* Shutdown network level protocol subsystem */
IPShutdown();
/* Shutdown the lan worker */
LANShutdown();
/* Free NDIS buffer descriptors */
if (GlobalBufferPool)
NdisFreeBufferPool(GlobalBufferPool);
@ -807,6 +816,9 @@ DriverEntry(
InitializeListHead(&InterfaceListHead);
KeInitializeSpinLock(&InterfaceListLock);
/* Initialize the lan worker */
LANStartup();
/* Initialize network level protocol subsystem */
IPStartup(DriverObject, RegistryPath);

View file

@ -594,13 +594,13 @@ VOID FreeNdisPacketX
NdisGetNextBuffer(Buffer, &NextBuffer);
NdisQueryBuffer(Buffer, &Data, &Length);
NdisFreeBuffer(Buffer);
UntrackFL(File,Line,Buffer);
ExFreePool(Data);
NdisFreeBuffer(Buffer);
UntrackFL(File,Line,Data);
ExFreePool(Data);
}
/* Finally free the NDIS packet discriptor */
NdisFreePacket(Packet);
UntrackFL(File,Line,Packet);
NdisFreePacket(Packet);
}

View file

@ -13,6 +13,7 @@
extern ULONG TCP_IPIdentification;
extern LIST_ENTRY SleepingThreadsList;
extern FAST_MUTEX SleepingThreadsLock;
extern RECURSIVE_MUTEX TcpMutex;
int TCPSocketState(void *ClientData,
void *WhichSocket,

View file

@ -10,12 +10,12 @@
#include "precomp.h"
LONG TCP_IPIdentification = 0;
static BOOLEAN TCPInitialized = FALSE;
static NPAGED_LOOKASIDE_LIST TCPSegmentList;
LIST_ENTRY SleepingThreadsList;
FAST_MUTEX SleepingThreadsLock;
RECURSIVE_MUTEX TcpMutex;
VOID TCPReceive(PNET_TABLE_ENTRY NTE, PIP_PACKET IPPacket)
/*
@ -30,7 +30,7 @@ VOID TCPReceive(PNET_TABLE_ENTRY NTE, PIP_PACKET IPPacket)
TI_DbgPrint(MID_TRACE,("Sending packet %d (%d) to oskit\n",
IPPacket->TotalSize,
IPPacket->HeaderSize));
OskitTCPReceiveDatagram( IPPacket->Header,
IPPacket->TotalSize,
IPPacket->HeaderSize );
@ -121,7 +121,7 @@ NTSTATUS TCPShutdown(VOID)
TCPInitialized = FALSE;
DeinitOskitTCP();
return STATUS_SUCCESS;
}
@ -227,13 +227,14 @@ NTSTATUS TCPConnect
&RemoteAddress->Address.IPv4Address,
sizeof(AddressToConnect.sin_addr) );
AddressToConnect.sin_port = RemotePort;
KeReleaseSpinLock(&Connection->Lock, OldIrql);
Status = OskitTCPConnect(Connection->SocketContext,
Connection,
&AddressToConnect,
sizeof(AddressToConnect));
KeReleaseSpinLock(&Connection->Lock, OldIrql);
if( Status == OSK_EINPROGRESS || Status == STATUS_SUCCESS )
return STATUS_PENDING;
else
@ -242,13 +243,18 @@ NTSTATUS TCPConnect
NTSTATUS TCPClose
( PTDI_REQUEST Request ) {
KIRQL OldIrql;
PCONNECTION_ENDPOINT Connection;
NTSTATUS Status;
Connection = Request->Handle.ConnectionContext;
TI_DbgPrint(MID_TRACE,("TCPClose started\n"));
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError( OskitTCPClose( Connection->SocketContext ) );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(MID_TRACE,("TCPClose finished %x\n", Status));
@ -259,11 +265,19 @@ NTSTATUS TCPListen
( PTDI_REQUEST Request,
UINT Backlog ) {
PCONNECTION_ENDPOINT Connection;
NTSTATUS Status;
KIRQL OldIrql;
Connection = Request->Handle.ConnectionContext;
return TCPTranslateError( OskitTCPListen( Connection->SocketContext,
Backlog ) );
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext,
Backlog ) );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
return Status;
}
NTSTATUS TCPAccept