diff --git a/reactos/drivers/net/tcpip/datalink/lan.c b/reactos/drivers/net/tcpip/datalink/lan.c index b79fda965e0..5c02f25c837 100644 --- a/reactos/drivers/net/tcpip/datalink/lan.c +++ b/reactos/drivers/net/tcpip/datalink/lan.c @@ -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 */ diff --git a/reactos/drivers/net/tcpip/include/irp.h b/reactos/drivers/net/tcpip/include/irp.h index d49231b4411..8ca1b55c727 100644 --- a/reactos/drivers/net/tcpip/include/irp.h +++ b/reactos/drivers/net/tcpip/include/irp.h @@ -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*/ diff --git a/reactos/drivers/net/tcpip/include/lan.h b/reactos/drivers/net/tcpip/include/lan.h index 18d9b8ddaa9..bbfeda5bd88 100644 --- a/reactos/drivers/net/tcpip/include/lan.h +++ b/reactos/drivers/net/tcpip/include/lan.h @@ -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, diff --git a/reactos/drivers/net/tcpip/include/memtrack.h b/reactos/drivers/net/tcpip/include/memtrack.h index 85eca16f2e5..72121cbd058 100644 --- a/reactos/drivers/net/tcpip/include/memtrack.h +++ b/reactos/drivers/net/tcpip/include/memtrack.h @@ -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__) diff --git a/reactos/drivers/net/tcpip/include/precomp.h b/reactos/drivers/net/tcpip/include/precomp.h index 8532a9ff6e5..147673cfb47 100644 --- a/reactos/drivers/net/tcpip/include/precomp.h +++ b/reactos/drivers/net/tcpip/include/precomp.h @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/drivers/net/tcpip/makefile b/reactos/drivers/net/tcpip/makefile index f2924533430..7a782b4a3d1 100644 --- a/reactos/drivers/net/tcpip/makefile +++ b/reactos/drivers/net/tcpip/makefile @@ -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 \ diff --git a/reactos/drivers/net/tcpip/tcpip/dispatch.c b/reactos/drivers/net/tcpip/tcpip/dispatch.c index 423cb0344c7..12bd63f3adc 100644 --- a/reactos/drivers/net/tcpip/tcpip/dispatch.c +++ b/reactos/drivers/net/tcpip/tcpip/dispatch.c @@ -130,7 +130,6 @@ VOID DispCancelRequest( /* Try canceling the request */ switch(MinorFunction) { case TDI_SEND: - case TDI_RECEIVE: /* FIXME: Close connection */ break; diff --git a/reactos/drivers/net/tcpip/tcpip/irp.c b/reactos/drivers/net/tcpip/tcpip/irp.c index e6a93677300..1b235a01614 100644 --- a/reactos/drivers/net/tcpip/tcpip/irp.c +++ b/reactos/drivers/net/tcpip/tcpip/irp.c @@ -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 ) diff --git a/reactos/drivers/net/tcpip/tcpip/main.c b/reactos/drivers/net/tcpip/tcpip/main.c index c69282a3418..ab6c7e5592b 100644 --- a/reactos/drivers/net/tcpip/tcpip/main.c +++ b/reactos/drivers/net/tcpip/tcpip/main.c @@ -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); diff --git a/reactos/drivers/net/tcpip/tcpip/routines.c b/reactos/drivers/net/tcpip/tcpip/routines.c index 340782e2be1..be6b43fda47 100644 --- a/reactos/drivers/net/tcpip/tcpip/routines.c +++ b/reactos/drivers/net/tcpip/tcpip/routines.c @@ -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); } diff --git a/reactos/drivers/net/tcpip/transport/tcp/event.c b/reactos/drivers/net/tcpip/transport/tcp/event.c index f29f5bbd47d..e014d9a79f3 100644 --- a/reactos/drivers/net/tcpip/transport/tcp/event.c +++ b/reactos/drivers/net/tcpip/transport/tcp/event.c @@ -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, diff --git a/reactos/drivers/net/tcpip/transport/tcp/tcp.c b/reactos/drivers/net/tcpip/transport/tcp/tcp.c index d298c13c18d..7c1eae4165d 100644 --- a/reactos/drivers/net/tcpip/transport/tcp/tcp.c +++ b/reactos/drivers/net/tcpip/transport/tcp/tcp.c @@ -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