From: tzachid Date: Mon, 21 Nov 2005 12:19:58 +0000 (+0000) Subject: Implementation of Listen Bind and accept. (Rev 273) X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=22dc2bc15a9bbdc273746c1f16ada3c1f0b7c755;p=~shefty%2Frdma-win.git Implementation of Listen Bind and accept. (Rev 273) git-svn-id: svn://openib.tc.cornell.edu/gen1@171 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/ulp/sdp/include/SdpShared.h b/trunk/ulp/sdp/include/SdpShared.h index 2c4a8d5d..f647de4e 100644 --- a/trunk/ulp/sdp/include/SdpShared.h +++ b/trunk/ulp/sdp/include/SdpShared.h @@ -15,6 +15,9 @@ #define IOCTL_WSP_CONNECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED ,FILE_ANY_ACCESS) #define IOCTL_WSP_SEND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED ,FILE_ANY_ACCESS) #define IOCTL_WSP_RECV CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED ,FILE_ANY_ACCESS) +#define IOCTL_WSP_BIND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED ,FILE_ANY_ACCESS) +#define IOCTL_WSP_LISTEN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED ,FILE_ANY_ACCESS) +#define IOCTL_WSP_ACCEPT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED ,FILE_ANY_ACCESS) @@ -63,5 +66,35 @@ struct WspRecvOut { ULONG dwFlags; }; +struct WspBindIn { + VOID *pSocket; + ULONG IP; + USHORT Port; +}; + +struct WspBindOut { + int Errno; +}; + +struct WspListenIn { + VOID *pSocket; + int backlog; +}; + +struct WspListenOut { + int Errno; +}; + +struct WspAcceptIn { + VOID *pSocket; +}; + +struct WspAcceptOut { + int Errno; + VOID *pAccaptedSocket; + ULONG IP; + USHORT Port; +}; + #endif //_SDP_SHARED_H diff --git a/trunk/ulp/sdp/kernel/Precompile.h b/trunk/ulp/sdp/kernel/Precompile.h index 3f31442a..ffcdb34f 100644 --- a/trunk/ulp/sdp/kernel/Precompile.h +++ b/trunk/ulp/sdp/kernel/Precompile.h @@ -25,6 +25,7 @@ class SdpArp; #include "SdpUserFile.h" #include "SdpBufferPool.h" #include "SdpRecvPool.h" +#include "SdpConnectionList.h" #include "SdpSocket.h" #include "SdpArp.h" diff --git a/trunk/ulp/sdp/kernel/SOURCES b/trunk/ulp/sdp/kernel/SOURCES index a675f0ad..83f1c428 100644 --- a/trunk/ulp/sdp/kernel/SOURCES +++ b/trunk/ulp/sdp/kernel/SOURCES @@ -9,6 +9,7 @@ SOURCES= SdpDriver.cpp \ SdpArp.cpp \ SdpBufferPool.cpp \ SdpRecvPool.cpp \ + SdpConnectionList.cpp \ SdpTrace.cpp INCLUDES=..\include;\ diff --git a/trunk/ulp/sdp/kernel/SdpArp.h b/trunk/ulp/sdp/kernel/SdpArp.h index 5ad62369..0ce51357 100644 --- a/trunk/ulp/sdp/kernel/SdpArp.h +++ b/trunk/ulp/sdp/kernel/SdpArp.h @@ -28,11 +28,11 @@ public: if (DestIp == 11 * 256*256*256 + 4 * 256*256 + 8 * 256 + - + 124) { + + 170) { *SrcIp = 11 * 256*256*256 + 4 * 256*256 + 8 * 256 + - + 120; + + 159; return STATUS_SUCCESS; } ASSERT(FALSE); @@ -54,7 +54,6 @@ public: } - NTSTATUS SourcePortGidFromIP( IN ULONG SourceAddr, OUT ib_net64_t *SrcPortGuid, @@ -64,11 +63,11 @@ public: if (SourceAddr == 11 * 256*256*256 + 4 * 256*256 + 8 * 256 + - + 120) { + + 159) { // *SrcPortGuid = CL_NTOH64(0x2c90200002001);//????? swlab120 // *SrcCaGuid = CL_NTOH64(0x2c90200002000); - *SrcPortGuid = CL_NTOH64(0x2c9010b7c4362);//????? swlab159 + *SrcPortGuid = CL_NTOH64(0x2c9010b7c4361);//????? swlab159 *SrcCaGuid = CL_NTOH64(0x2c9010b7c4360); return STATUS_SUCCESS; } @@ -87,8 +86,11 @@ public: if (DestAddr == 11 * 256*256*256 + 4 * 256*256 + 8 * 256 + - + 124) { - *DestPortGuid = CL_NTOH64(0x0000c900012a3a41);//????? swlab124 + + 170) { + //*DestPortGuid = CL_NTOH64(0x0000c900012a3a41);//????? swlab124 + //*DestPortGuid = CL_NTOH64(0x0002c90200400301);//????? swlab170 + *DestPortGuid = CL_NTOH64(0x0002c902004002fe);//????? swlab170 + return STATUS_SUCCESS; } ASSERT(FALSE); diff --git a/trunk/ulp/sdp/kernel/SdpConnectionList.cpp b/trunk/ulp/sdp/kernel/SdpConnectionList.cpp new file mode 100644 index 00000000..4888cccd --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpConnectionList.cpp @@ -0,0 +1,136 @@ +/* Copyright mellanox */ + +#include "Precompile.h" + +VOID +ConnectionList::Init(SdpSocket *pSdpSocket) +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + m_pSdpSocket = pSdpSocket; + m_ClientWaiting = false; + KeInitializeEvent(&m_WaitForConnection, NotificationEvent , FALSE ); +} + +VOID ConnectionList::Shutdown() +{ + //???????? + //?????AssertLocked(); + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + +} + +bool +ConnectionList::IsFull() +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + AssertLocked(); + int CurrentConnections = + m_ReplySentConnections.Size() + m_ReadyConnections.Size(); + return CurrentConnections >= m_BackLog; +} + +NTSTATUS +ConnectionList::AddConnectionToReplySent(SdpSocket *pNewSocket) +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + AssertLocked(); + m_ReplySentConnections.InsertTailList(&pNewSocket->m_ListeningSocketList); + pNewSocket->AddRef(); + return 0; +} + +// Go over the list of connections and verify that such a connection +// exists +NTSTATUS +ConnectionList::VerifyConnictionInReplySent(SdpSocket *pNewSocket) +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + AssertLocked(); + SdpSocket *pSocket = NULL; +#if DBG + LIST_ENTRY *item = m_ReplySentConnections.Head(); + while (item->Flink != m_ReplySentConnections.Head()) { + pSocket = CONTAINING_RECORD(item, SdpSocket , m_ListeningSocketList); + if (pSocket == pNewSocket) { + // We have found what we were looking for + return STATUS_SUCCESS; + } + } + // Not found, return error + ASSERT(FALSE); + return STATUS_UNEXPECTED_IO_ERROR; +#else + return STATUS_SUCCESS; + +#endif // DBG + +} + +VOID +ConnectionList::MoveConnectionFromReplyToReady(SdpSocket *pNewSocket) +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + AssertLocked(); + pNewSocket->AssertLocked(); + // just take it out from one list and put it in the other + RemoveEntryList(&pNewSocket->m_ListeningSocketList); + m_ReadyConnections.InsertTailList(&pNewSocket->m_ListeningSocketList); +} + +VOID +ConnectionList::FreeWaitingIfCan() +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + AssertLocked(); + if (m_ClientWaiting) { + ASSERT(m_ReadyConnections.Size() > 0); + KeSetEvent( &m_WaitForConnection, IO_NO_INCREMENT, FALSE ); + m_ClientWaiting = false; + } +} + +NTSTATUS +ConnectionList::AcceptAReadyConnection( + SdpSocket **ppNewSocket, + KEVENT **ppEvent + ) +{ + SDP_PRINT(SDP_TRACE, SDP_CONNECTION_LIST, ("this = 0x%p \n", this)); + + ASSERT(*ppEvent == NULL); + ASSERT(*ppNewSocket == NULL); + LIST_ENTRY *item = NULL; + + if (m_ClientWaiting) { + ASSERT(m_ClientWaiting == false); + // This is very likely caused because of two threads that are calling + // accept (not supported currently) + //?????? print ????? + return STATUS_UNEXPECTED_IO_ERROR; + } + if (m_ReadyConnections.Size() > 0) { + // We have a connection to return + // TODO: This connection might be in a bad state. What should we do + item = m_ReadyConnections.RemoveHeadList(); + *ppNewSocket = CONTAINING_RECORD(item, SdpSocket , m_ListeningSocketList); + // There is no change of the referance count, since we are taking + // the socket from the list, but we are also giving it to someone else + return STATUS_SUCCESS; + } + + // We don't have a ready socket to return, the caller will have + // to wait + KeClearEvent(&m_WaitForConnection); + m_ClientWaiting = true; + *ppEvent = &m_WaitForConnection; + return STATUS_SUCCESS; +} + + +VOID +ConnectionList::AssertLocked() { +#if DBG + m_pSdpSocket->AssertLocked(); +#endif +} + diff --git a/trunk/ulp/sdp/kernel/SdpConnectionList.h b/trunk/ulp/sdp/kernel/SdpConnectionList.h new file mode 100644 index 00000000..cb95896f --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpConnectionList.h @@ -0,0 +1,47 @@ +/* Copyright mellanox */ + +#ifndef H_SDP_CONNECTION_LIST_H +#define H_SDP_CONNECTION_LIST_H + +// All functions here (including shutdown, should be called with +// the lock taken) + +class ConnectionList { + +public: + VOID Init(SdpSocket *pSdpSocket); + VOID Shutdown(); + + bool IsFull(); + VOID SetBackLog(int BackLog) { + m_BackLog = BackLog; + }; + NTSTATUS AddConnectionToReplySent(SdpSocket *pNewSocket); + + // Go over the list of connections and verify that such a connection + // exists + NTSTATUS VerifyConnictionInReplySent(SdpSocket *pNewSocket); + + VOID MoveConnectionFromReplyToReady(SdpSocket *pNewSocket); + + VOID FreeWaitingIfCan(); + + NTSTATUS AcceptAReadyConnection( + SdpSocket **ppNewSocket, + KEVENT **ppEvent + ); + +private: + + VOID AssertLocked(); + + SdpSocket *m_pSdpSocket; // No refcount as we are part of this socket + + int m_BackLog; + LinkedList m_ReplySentConnections; + LinkedList m_ReadyConnections; + KEVENT m_WaitForConnection; + bool m_ClientWaiting; + +}; +#endif //H_SDP_CONNECTION_LIST_H diff --git a/trunk/ulp/sdp/kernel/SdpDriver.cpp b/trunk/ulp/sdp/kernel/SdpDriver.cpp index e262f0da..29a12710 100644 --- a/trunk/ulp/sdp/kernel/SdpDriver.cpp +++ b/trunk/ulp/sdp/kernel/SdpDriver.cpp @@ -339,6 +339,7 @@ NTSTATUS SdpDriver::DispatchDeviceIoControl( NTSTATUS rc = STATUS_SUCCESS; SdpUserFile *pSdpUserFile = NULL; SdpSocket *pSdpSocket = NULL; + SdpSocket *pAcceptedSdpSocket = NULL; switch (IoControlCode) { case IOCTL_WSP_SOCKET : @@ -446,6 +447,89 @@ NTSTATUS SdpDriver::DispatchDeviceIoControl( } break; + case IOCTL_WSP_BIND: + { + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_BIND recieved\n" )); + VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspBindIn, WspBindOut); + OutputDataSize = sizeof (WspBindOut); + + // get the socket based on the users pointer + WspBindIn wspBindIn = *(WspBindIn *) pInputBuffer; + WspBindOut *pWspBindOut = (WspBindOut *) pOutputBuffer; + pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext; + pSdpSocket = pSdpUserFile->SocketByPointer(wspBindIn.pSocket); + if (pSdpSocket == NULL) { + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_BIND socket %x not found\n", wspBindIn.pSocket)); + // This is a well defined winsock error + pWspBindOut->Errno = WSAENOTSOCK; + goto Cleanup; + } + rc = pSdpSocket->WSPBind(&wspBindIn, pWspBindOut); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPBind failed rc = 0x%x\n", rc )); + goto Cleanup; + } + } + break; + + case IOCTL_WSP_LISTEN: + { + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_LISTEN recieved\n" )); + VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspListenIn, WspListenOut); + OutputDataSize = sizeof (WspListenOut); + + // get the socket based on the users pointer + WspListenIn wspListenIn = *(WspListenIn *) pInputBuffer; + WspListenOut *pWspListenOut = (WspListenOut *) pOutputBuffer; + pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext; + pSdpSocket = pSdpUserFile->SocketByPointer(wspListenIn.pSocket); + if (pSdpSocket == NULL) { + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_LISTEN socket %x not found\n",wspListenIn.pSocket)); + // This is a well defined winsock error + pWspListenOut->Errno = WSAENOTSOCK; + goto Cleanup; + } + rc = pSdpSocket->WSPListen(&wspListenIn, pWspListenOut); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPRecv failed rc = 0x%x\n", rc )); + goto Cleanup; + } + } + break; + + case IOCTL_WSP_ACCEPT: + { + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_ACCEPT recieved\n" )); + VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspAcceptIn, WspAcceptOut); + OutputDataSize = sizeof (WspAcceptOut); + + // get the socket based on the users pointer + WspAcceptIn wspAcceptIn = *(WspAcceptIn *) pInputBuffer; + WspAcceptOut *pWspAcceptOut = (WspAcceptOut *) pOutputBuffer; + pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext; + pSdpSocket = pSdpUserFile->SocketByPointer(wspAcceptIn.pSocket); + if (pSdpSocket == NULL) { + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_ACCEPT socket %x not found\n",wspAcceptIn.pSocket)); + // This is a well defined winsock error + pWspAcceptOut->Errno = WSAENOTSOCK; + goto Cleanup; + } + rc = pSdpSocket->WSPAccept(&wspAcceptIn, pWspAcceptOut); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPAccept failed rc = 0x%x\n", rc )); + goto Cleanup; + } + if (pWspAcceptOut->pAccaptedSocket != NULL) { + pAcceptedSdpSocket = (SdpSocket *) pWspAcceptOut->pAccaptedSocket; + rc = pSdpUserFile->AddSocket(pAcceptedSdpSocket); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->AddSocket failed rc = 0x%x\n", rc )); + pAcceptedSdpSocket->Shutdown(); + goto Cleanup; + } + } + } + break; default: @@ -461,6 +545,10 @@ Cleanup: if (pSdpSocket) { pSdpSocket->Release(); } + if (pAcceptedSdpSocket) { + pAcceptedSdpSocket->Release(); + } + return rc; } diff --git a/trunk/ulp/sdp/kernel/SdpGenUtils.cpp b/trunk/ulp/sdp/kernel/SdpGenUtils.cpp index 5f246978..cad9a834 100644 --- a/trunk/ulp/sdp/kernel/SdpGenUtils.cpp +++ b/trunk/ulp/sdp/kernel/SdpGenUtils.cpp @@ -141,6 +141,34 @@ int abs(int i){ return -i; } +/* Convert an IBAL error to a Winsock error. */ +int IbalToWsaError(const ib_api_status_t ib_status ) +{ + switch( ib_status ) + { + case IB_SUCCESS: + return 0; + + case IB_INVALID_QP_HANDLE: + return WSAENOTCONN; + + case IB_INVALID_PARAMETER: + return WSAEINVAL; + + case IB_INSUFFICIENT_RESOURCES: + return WSAENOBUFS; + + case IB_INVALID_WR_TYPE: + return WSAEINVAL; + + case IB_INVALID_QP_STATE: + return WSAENOTCONN; + + default: + return WSAEINVAL; + } +} + void* __cdecl operator new(size_t n ) throw() { return ExAllocatePoolWithTag(NonPagedPool , n, GLOBAL_ALLOCATION_TAG); } diff --git a/trunk/ulp/sdp/kernel/SdpGenUtils.h b/trunk/ulp/sdp/kernel/SdpGenUtils.h index 497b8059..98f2256d 100644 --- a/trunk/ulp/sdp/kernel/SdpGenUtils.h +++ b/trunk/ulp/sdp/kernel/SdpGenUtils.h @@ -72,9 +72,13 @@ VOID UpdateRc(NTSTATUS *rc, NTSTATUS rc1); int abs(int i); +/* Convert an IBAL error to a Winsock error. */ +int IbalToWsaError(const ib_api_status_t ib_status ); + +#define INADDR_ANY (ULONG)0x00000000 // This error codes are taken from winsock2.h (the file can not) -// be included from user mode +// be included from kernel mode /* * All Windows Sockets error constants are biased by WSABASEERR from diff --git a/trunk/ulp/sdp/kernel/SdpMsgs.h b/trunk/ulp/sdp/kernel/SdpMsgs.h index 1895d67e..fcf1b839 100644 --- a/trunk/ulp/sdp/kernel/SdpMsgs.h +++ b/trunk/ulp/sdp/kernel/SdpMsgs.h @@ -169,7 +169,7 @@ static inline void sdp_msg_swap_hh(struct msg_hdr_hh *header) /* * sdp_msg_swap_hah - SDP header endian byte swapping */ -static inline void sdp_msg_net_to_cpu_hah(struct msg_hdr_hah *header) +static inline void sdp_msg_swap_hah(struct msg_hdr_hah *header) { header->l_rcv_size = CL_NTOH32(header->l_rcv_size); } diff --git a/trunk/ulp/sdp/kernel/SdpRecvPool.cpp b/trunk/ulp/sdp/kernel/SdpRecvPool.cpp index 3928c99a..bfa4d2f4 100644 --- a/trunk/ulp/sdp/kernel/SdpRecvPool.cpp +++ b/trunk/ulp/sdp/kernel/SdpRecvPool.cpp @@ -49,6 +49,10 @@ RecvPool::RecievedBuffer(BufferDescriptor *pBufferDescriptor, bool error) ,this, pBufferDescriptor, error ? "true" : "false")); AssertLocked(); NTSTATUS rc = STATUS_SUCCESS; + + m_CurrentlyPostedRecievedBuffers--; + ASSERT(m_CurrentlyPostedRecievedBuffers >= 0); + if (error) { // Not much that we can do in this case (only return the packet) m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList); @@ -75,22 +79,27 @@ RecvPool::RecievedBuffer(BufferDescriptor *pBufferDescriptor, bool error) (int)pHeader->seq_ack); m_pSdpSocket->m_SendBufferPool.SetRemoteRecvBuf(rRecvBuf); + // ???? Handle state changes here ???? + if (pHeader->mid != 0xFF) { + // This is a message without data, we currently ignore it + m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList); + } else { - if(pHeader->size > sizeof msg_hdr_bsdh) { - m_FullPackets.InsertTailList(&pBufferDescriptor->BuffersList); - ASSERT(m_FullPackets.Size() <= m_MaxBuffers); + if(pHeader->size > sizeof msg_hdr_bsdh) { + m_FullPackets.InsertTailList(&pBufferDescriptor->BuffersList); + ASSERT(m_FullPackets.Size() <= m_MaxBuffers); - // we need to notify the client that is waiting - if (m_ClientWaiting) { - KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE ); - m_ClientWaiting = false; + // we need to notify the client that is waiting + if (m_ClientWaiting) { + KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE ); + m_ClientWaiting = false; + } + } else { + // This is an empty buffer + ASSERT(pHeader->size == sizeof msg_hdr_bsdh); + m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList); } - } else { - // This is an empty buffer - ASSERT(pHeader->size == sizeof msg_hdr_bsdh); - m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList); - } - // ???? Handle state changes here ???? + } // Check if we have to send more credits to the remote side ASSERT(m_LocaleAdvertisedBuffers > 0); @@ -112,10 +121,6 @@ RecvPool::RecievedBuffer(BufferDescriptor *pBufferDescriptor, bool error) SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("SendBuffersIfCan failed rc = 0x%x\n", rc )); goto Cleanup; } - - m_CurrentlyPostedRecievedBuffers--; - - ASSERT(m_CurrentlyPostedRecievedBuffers >= 0); // We might be able to post a new recieve buffer now ASSERT(m_CurrentlyPostedRecievedBuffers < m_MaxConcurrentRecieves); rc = ReceiveIfCan(); @@ -149,7 +154,8 @@ RecvPool::GetData( uint32_t CopySize, uint32_t *Copied, KEVENT **ppEvent, - bool FirstBuffer + bool FirstBuffer, + bool *pNoMoreData ) { SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p FirstBuffer = %s\n",this, @@ -157,6 +163,7 @@ RecvPool::GetData( AssertLocked(); bool BufferFreed = false; *Copied = 0; + *pNoMoreData = false; BufferDescriptor *pBufferDescriptor = NULL; uint32_t OldDataSize = 0; @@ -207,6 +214,11 @@ RecvPool::GetData( } } else { + *pNoMoreData = true; + // If data was already supplied, then we shouldn't wait any more + if ((*Copied > 0) || (FirstBuffer == false)) { + break; + } // No buffers available, we have to wait ASSERT(m_ClientWaiting == false); KeClearEvent(&m_WaitingClients); diff --git a/trunk/ulp/sdp/kernel/SdpRecvPool.h b/trunk/ulp/sdp/kernel/SdpRecvPool.h index b25a8334..715b03ae 100644 --- a/trunk/ulp/sdp/kernel/SdpRecvPool.h +++ b/trunk/ulp/sdp/kernel/SdpRecvPool.h @@ -24,7 +24,8 @@ public: uint32_t CopySize, uint32_t *Copied, KEVENT **ppEvent, - bool FirstBuffer + bool FirstBuffer, + bool *pNoMoreData ); VOID AllowOthersToGet(); diff --git a/trunk/ulp/sdp/kernel/SdpSocket.cpp b/trunk/ulp/sdp/kernel/SdpSocket.cpp index c35c720d..d6d7e9ec 100644 --- a/trunk/ulp/sdp/kernel/SdpSocket.cpp +++ b/trunk/ulp/sdp/kernel/SdpSocket.cpp @@ -5,6 +5,7 @@ #pragma warning(disable: 4244 ) NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack); +NTSTATUS sdp_cm_hello_check(struct sdp_msg_hello *msg_hello); static NTSTATUS __send_cb2(SdpSocket * pSdpSocket); static NTSTATUS __recv_cb2(SdpSocket * pSdpSocket); @@ -19,9 +20,6 @@ static void AL_API cm_rep_callback( IN ib_cm_rep_rec_t *p_cm_rep_rec ) { - - - SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_rep_callback called\n")); SdpSocket *pSocket = (SdpSocket *) p_cm_rep_rec->qp_context; pSocket->CmRepCallback(p_cm_rep_rec); } @@ -52,11 +50,61 @@ cm_dreq_callback(IN ib_cm_dreq_rec_t *p_cm_dreq_rec ) SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("dispatch level = %d\n", KeGetCurrentIrql())); ASSERT(FALSE); } + +static void AL_API +cm_lap_callback( + IN ib_cm_lap_rec_t *p_cm_lap_rec ) +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("dispatch level = %d\n", KeGetCurrentIrql())); + ASSERT(FALSE); +} + +void +cm_rtu_callback( + IN ib_cm_rtu_rec_t *p_cm_rtu_rec ) +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("dispatch level = %d\n", KeGetCurrentIrql())); + // Note - Referance count is not increased here since this is a call + // back, and we are gurantied that shuting down ibal will only end + // after all callbacks are finished. + SdpSocket *pSocket = (SdpSocket *) p_cm_rtu_rec->qp_context; + SdpSocket *pListeningSocket = pSocket->m_pListeningSocket; + pListeningSocket->CmRtuCallback(p_cm_rtu_rec); + +} +/* + * A user-specified callback that is invoked after an error has occurred on + * a listen request. + */ +static void AL_API +listen_err_callback( + IN ib_listen_err_rec_t *p_listen_err_rec ) +{ + /* TODO ??????????????*/ + UNUSED_PARAM( p_listen_err_rec ); + ASSERT( 0 ); +} + +static void AL_API +cm_req_callback( + IN ib_cm_req_rec_t *p_cm_req_rec ) +{ + // Pass the request to the approperiate socket + SdpSocket *pSocket = (SdpSocket *) p_cm_req_rec->context; + pSocket->CmReqCallback(p_cm_req_rec); +} + SdpSocket::SdpSocket() { m_CreationFlags = 0; m_SrcPort = 0; m_SrcIp = 0; + m_DstPort = 0; + m_DstIp = 0; + + m_SrcPortGuid = 0; + m_SrcCaGuid = 0; + m_ListenHandle = NULL; mh_Ca = NULL; m_pd = NULL; @@ -66,6 +114,7 @@ SdpSocket::SdpSocket() m_mr = NULL; m_state = SS_IDLE; + m_pListeningSocket = NULL; } VOID SdpSocket::AssertLocked() @@ -89,6 +138,8 @@ NTSTATUS SdpSocket::Init( pSocketOutParam->pSocket = this; // give the user a handle to the socket KeInitializeEvent(&m_ShutdownCompleteEvent, NotificationEvent , FALSE ); + m_ConnectionList.Init(this); + return rc; } @@ -124,6 +175,9 @@ NTSTATUS SdpSocket::WSPSend( Locked = true; ASSERT(pBuffersEvent == NULL); + //??? Verify connected state (or whatever)????????????? + + rc = m_SendBufferPool.GetBuffer(&pBufferDescriptor, &pBuffersEvent, First); if (!NT_SUCCESS(rc)) { SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_SendBufferPool.GetBuffer failed rc = 0x%x\n", rc )); @@ -217,13 +271,14 @@ SdpSocket::WSPRecv( WspRecvOut *pWspRecvOut ) { - SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p \n",this)); + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p BufferSize = %d\n",this, pWspRecvIn->BufferSize)); NTSTATUS rc = STATUS_SUCCESS; bool First = true; uint32_t Coppied = 0, ThisCopy = 0; bool Locked = false; PRKEVENT pBuffersEvent = NULL; + bool NoMoreData; if (pWspRecvIn->BufferSize == 0) { SDP_PRINT(SDP_WARN, SDP_SOCKET, ("this = 0x%p - zero size recv \n",this)); @@ -239,12 +294,15 @@ SdpSocket::WSPRecv( Locked = true; ASSERT(pBuffersEvent == NULL); + //??? Verify connected state (or whatever)????????????? + rc = m_RecvBufferPool.GetData( pWspRecvIn->pData + Coppied, pWspRecvIn->BufferSize - Coppied, &ThisCopy, &pBuffersEvent, - First + First, + &NoMoreData ); if (!NT_SUCCESS(rc)) { SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.GetData failed rc = 0x%x\n", rc )); @@ -252,8 +310,15 @@ SdpSocket::WSPRecv( Locked = false; goto Cleanup; } - First = false; Coppied += ThisCopy; + + if (NoMoreData && (Coppied > 0)) { + // this means that there is nothing to copy, and we should return + ASSERT(pBuffersEvent == NULL); + break; + } + + First = false; if (pBuffersEvent != NULL) { // We are told to wait on this event @@ -298,15 +363,17 @@ SdpSocket::WSPRecv( Cleanup: if (NT_SUCCESS(rc) ) { pWspRecvOut->Errno = 0; - ASSERT(pWspRecvIn->BufferSize == Coppied); + ASSERT(pWspRecvIn->BufferSize >= Coppied); pWspRecvOut->NumberOfBytesRecieved = Coppied; } else { // Make sure that we have the error setted ASSERT(pWspRecvOut->Errno != 0); // BUGBUG: Need to make sure that this + pWspRecvOut->NumberOfBytesRecieved = 0; // is indeed the case. } // Currently in any case, the flags are not being used: - pWspRecvOut->dwFlags = 0; + pWspRecvOut->dwFlags = 0; + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p returning %d bytes \n",this, pWspRecvOut->NumberOfBytesRecieved)); return rc; } @@ -318,7 +385,6 @@ NTSTATUS SdpSocket::WSPConnect( { NTSTATUS rc = STATUS_SUCCESS; ib_api_status_t ib_status; - ib_net64_t SrcPortGuid; ib_net64_t DestPortGuid; ib_path_rec_t path_rec; @@ -338,7 +404,7 @@ NTSTATUS SdpSocket::WSPConnect( } // check socket state - // BUGBUG: Do a better work here + // BUGBUG: Do a better work here (it might be localy bounded ?????) m_Lock.Lock();//??? retval if (m_state != SS_IDLE) { // We can not connect in this state @@ -369,13 +435,18 @@ NTSTATUS SdpSocket::WSPConnect( if (m_SrcPort == 0) { rc = g_pSdpDriver->m_pSdpArp->GetPort(m_SrcIp, &m_SrcPort); if (!NT_SUCCESS(rc)) { - SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc )); + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->GetPort failed rc = 0x%x\n", rc )); pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error m_Lock.Unlock(); // Error ignored as this is already an error pass goto Cleanup; } + } else { + // We need to connect to the global table of ports + } - rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(m_SrcIp, &SrcPortGuid, &m_CaGuid); + + + rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(m_SrcIp, &m_SrcPortGuid, &m_SrcCaGuid); if (!NT_SUCCESS(rc)) { SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc )); pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error @@ -399,7 +470,7 @@ NTSTATUS SdpSocket::WSPConnect( m_state = SS_CONNECTING_QPR_SENT; m_Lock.Unlock(); //????? - rc = g_pSdpDriver->m_pSdpArp->QueryPathRecord( SrcPortGuid, DestPortGuid, &path_rec ); + rc = g_pSdpDriver->m_pSdpArp->QueryPathRecord( m_SrcPortGuid, DestPortGuid, &path_rec ); if (!NT_SUCCESS(rc)) { SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->QueryPathRecord failed rc = 0x%x\n", rc )); pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error @@ -501,6 +572,315 @@ Cleanup: } +NTSTATUS +SdpSocket::WSPBind( + WspBindIn *pWspBindIn, + WspBindOut *pWspBindOut + ) +{ + NTSTATUS rc = STATUS_SUCCESS; + + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p bind address ip=%d.%d.%d.%d:%d\n", + this, + (pWspBindIn->IP & 0XFF000000) >> 24, + (pWspBindIn->IP & 0XFF0000) >> 16, + (pWspBindIn->IP & 0XFF00) >> 8, + (pWspBindIn->IP & 0XFF), + pWspBindIn->Port + )); + + if (!m_Lock.Lock()) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this)); + rc = STATUS_SHUTDOWN_IN_PROGRESS; + goto Cleanup; + } + + /* Verify the state of the socket */ + if( m_state != SS_IDLE) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("socket is in invalid state %s this = 0x%p \n", + this, + SS2String(m_state))); + m_Lock.Unlock(); // Error ignored as this is already an error pass + rc = STATUS_INVALID_DEVICE_STATE; + pWspBindOut->Errno = WSAEINVAL; + goto Cleanup; + } + + + /* Check if the ip address is assigned to one of our IBoIB HCA. */ + if( pWspBindIn->IP != INADDR_ANY ) + { + ASSERT(m_SrcCaGuid == NULL); + rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(pWspBindIn->IP, &m_SrcPortGuid, &m_SrcCaGuid); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc )); + pWspBindOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error + m_Lock.Unlock(); // Error ignored as this is already an error pass + goto Cleanup; + } + } + else + { + m_SrcPortGuid = 0; + } + + if( pWspBindIn->IP != INADDR_ANY ) { + /* Time to allocate our IB QP */ + rc = CreateQp(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("CreateQp failed rc = 0x%x\n", rc )); + pWspBindOut->Errno = WSAENOBUFS; + m_Lock.Unlock(); // Error ignored as this is already an error pass + goto Cleanup; + } + } + + // If the src port is 0, we need to allocate a port for the caller. + if (pWspBindIn->Port == 0) { + m_SrcPort = 0; + rc = g_pSdpDriver->m_pSdpArp->GetPort(pWspBindIn->IP, &m_SrcPort); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->GetPort failed rc = 0x%x\n", rc )); + pWspBindOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error + m_Lock.Unlock(); // Error ignored as this is already an error pass + goto Cleanup; + } + } else { + // We have to allocate the needed port in the table??????? + + } + + // Everything went OK + m_SrcPort = pWspBindIn->Port; + m_SrcIp = pWspBindIn->IP; + + m_state = SS_BOUND; + rc = m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + goto Cleanup; + } + +Cleanup: + if (NT_SUCCESS(rc) ) { + pWspBindOut->Errno = 0; + } else { + // Make sure that we have the error setted + ASSERT(pWspBindOut->Errno != 0); // BUGBUG: Need to make sure that this + // is indeed the case. + //??????????? Make sure that we clean this function on exit + } + return rc; + +} + +NTSTATUS SdpSocket::WSPListen( + WspListenIn *pWspListenIn, + WspListenOut *pWspListenOut + ) +{ + NTSTATUS rc = STATUS_SUCCESS; + ib_cm_listen_t param; + ib_api_status_t ib_status; + + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p \n",this)); + if (!m_Lock.Lock()) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this)); + rc = STATUS_SHUTDOWN_IN_PROGRESS; + goto Cleanup; + } + + /* Verify the state of the socket */ + if( m_state != SS_BOUND) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("socket is in invalid state %s this = 0x%p \n", + this, + SS2String(m_state))); + m_Lock.Unlock(); // Error ignored as this is already an error pass + rc = STATUS_INVALID_DEVICE_STATE; + pWspListenOut->Errno = WSAEINVAL; + goto Cleanup; + } + + m_ConnectionList.SetBackLog(pWspListenIn->backlog); + + // Create the CM request + memset( ¶m, 0, sizeof(param) ); + + ASSERT(m_SrcPort != 0); + param.svc_id = get_service_id_for_port( m_SrcPort); + if( m_SrcPortGuid ) + { + /* The socket is bound to an IP address */ + param.ca_guid = m_SrcCaGuid; + param.port_guid = m_SrcPortGuid; + } + else + { + /* The socket is bound to INADDR_ANY */ + param.ca_guid = IB_ALL_CAS; + param.port_guid = IB_ALL_PORTS; + } + + param.lid = IB_ALL_LIDS; + + /* Currently no compare function ????? + param.p_compare_buffer = (uint8_t *) & socket_info->info.listen.listen_req_param; + param.compare_length = sizeof(struct listen_req_param); + param.compare_offset = offsetof(struct cm_req_params, listen_req_param); + */ + + param.pfn_cm_req_cb = cm_req_callback; + + param.qp_type = IB_QPT_RELIABLE_CONN; + + ASSERT(m_ListenHandle == NULL); + + ib_status = ib_cm_listen( + g_pSdpDriver->m_al_handle , + ¶m, + listen_err_callback, + this, + &m_ListenHandle + ); + + if( ib_status != IB_SUCCESS ) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_cm_listen failed ib_status = 0x%d\n", ib_status )); + rc = IB2Status(ib_status); + pWspListenOut->Errno = IbalToWsaError( ib_status ); + goto Cleanup; + } + + // SUCCESS - change the state + m_state = SS_LISTENING; + rc = m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + goto Cleanup; + } + +Cleanup: + if (NT_SUCCESS(rc) ) { + pWspListenOut->Errno = 0; + } else { + // Make sure that we have the error setted + ASSERT(pWspListenOut->Errno != 0); // BUGBUG: Need to make sure that this + // is indeed the case. + } + return rc; +} + +NTSTATUS +SdpSocket::WSPAccept( + WspAcceptIn *pWspAcceptIn, + WspAcceptOut *pWspAcceptOut + ) +{ + NTSTATUS rc = STATUS_SUCCESS; + bool Locked = false; + SdpSocket *pNewSocket = NULL; + PRKEVENT pAcceptEvent = NULL; + + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p \n",this)); + + while (true) { + if ((Locked == false) && !m_Lock.Lock()) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this)); + rc = STATUS_SHUTDOWN_IN_PROGRESS; + goto Cleanup; + } + Locked = true; + ASSERT(pNewSocket == NULL); + + /* Verify the state of the socket */ + if( m_state != SS_LISTENING) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("socket is in invalid state %s this = 0x%p \n", + this, + SS2String(m_state))); + m_Lock.Unlock(); // Error ignored as this is already an error pass + Locked = false; + rc = STATUS_INVALID_DEVICE_STATE; + pWspAcceptOut->Errno = WSAEINVAL; + goto Cleanup; + } + + rc = m_ConnectionList.AcceptAReadyConnection(&pNewSocket, &pAcceptEvent); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_ConnectionList.AcceptAReadyConnection failed rc = 0x%x\n", rc )); + m_Lock.Unlock(); // Error ignored as this is already an error pass + Locked = false; + goto Cleanup; + } + + if (pNewSocket != NULL) { + ASSERT(pAcceptEvent == NULL); + break; + } + + ASSERT(pAcceptEvent != NULL); + + // We are told to wait on this event + rc = m_Lock.Unlock(); + Locked = false; + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + goto Cleanup; + } + + rc = MyKeWaitForSingleObject( + pAcceptEvent, + UserRequest, + UserMode, + FALSE, + NULL + ); + pAcceptEvent = NULL; + if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) { + // BUGBUG: Think what to do here, we should be able to stop the + // connect, and quit (probably shutdown should be enough) + SDP_PRINT(SDP_WARN, SDP_SOCKET, ("MyKeWaitForSingleObject was alerted = 0x%x\n", rc )); + rc = STATUS_UNEXPECTED_IO_ERROR; + //pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error + Shutdown(); + goto Cleanup; + } + // try getting the socket again + } + + // I want to copy this data before releasing the lock + ULONG IP = m_DstIp; + USHORT Port = m_DstPort; + + ASSERT(Locked == true); + rc = m_Lock.Unlock(); + Locked = false; + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + goto Cleanup; + } + +Cleanup: + ASSERT(Locked == false); + if (NT_SUCCESS(rc) ) { + pWspAcceptOut->pAccaptedSocket = pNewSocket; + pWspAcceptOut->IP = IP; + pWspAcceptOut->Port = Port; + pWspAcceptOut->Errno = 0; + // We need to "register" this socket in the global list + + } else { + // Make sure that we have the error setted + ASSERT(pWspAcceptOut->Errno != 0); // BUGBUG: Need to make sure that this + ASSERT(pNewSocket == NULL); + pWspAcceptOut->pAccaptedSocket = NULL; + // is indeed the case. + } + // referance on pNewSocket is not currently released, since we are + // returning them to the next level + return rc; + + +} + NTSTATUS SdpSocket::CmSendRTU() { @@ -614,14 +994,14 @@ NTSTATUS SdpSocket::CmSendRTU() rc = m_Lock.Lock(); if (!NT_SUCCESS(rc)) { - SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.Init failed rc = 0x%x\n", rc )); + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Lock failed rc = 0x%x\n", rc )); goto Cleanup; } rc = m_RecvBufferPool.ReceiveIfCan(); //??? error m_Lock.Unlock(); // error ???? if (!NT_SUCCESS(rc)) { - SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.Init failed rc = 0x%x\n", rc )); + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.ReceiveIfCan failed rc = 0x%x\n", rc )); goto Cleanup; } @@ -632,10 +1012,13 @@ Cleanup: VOID SdpSocket::CmRepCallback(IN ib_cm_rep_rec_t *p_cm_rep_rec) { + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%x\n", this)); + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + if (m_state != SS_CONNECTING_REQ_SENT) { // This is not the state that we waited for, not much that we can // do. (This might happen in shutdown) - SDP_PRINT(SDP_ERR, SDP_SOCKET, ("SdpSocket::CmRepCallback Not the expacted state %s\n", SS2String(m_state))); + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Not the expacted state %s\n", SS2String(m_state))); ASSERT(FALSE); return; } @@ -648,6 +1031,364 @@ VOID SdpSocket::CmRepCallback(IN ib_cm_rep_rec_t *p_cm_rep_rec) KeSetEvent(&m_ConnectCmCompleteEvent, IO_NO_INCREMENT, FALSE); } +VOID +SdpSocket::CmReqCallback(IN ib_cm_req_rec_t *p_cm_req_rec) +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%x\n", this)); + NTSTATUS rc = STATUS_SUCCESS; + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + net64_t SrcCaGuid; + ib_net64_t SrcPortGuid; + ib_api_status_t ib_status; + SdpSocket *pNewSocket = NULL; + + sdp_msg_hello *msg_hello = (sdp_msg_hello *)p_cm_req_rec->p_req_pdata; + + rc = sdp_cm_hello_check(msg_hello); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("sdp_cm_hello_ack_check failed rc = 0x%x\n", rc )); + goto Cleanup; + } + + // Take the lock and verify the state + rc = m_Lock.Lock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Lock failed rc = 0x%x\n", rc )); + goto Cleanup; + } + + if (m_state != SS_LISTENING) { + // This is not the state that we waited for, we drop the request + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Not the expacted state %s\n", SS2String(m_state))); + ASSERT(FALSE); + goto ErrorLocked; + } + + // Check that we haven't passed the backlog for this connection + if (m_ConnectionList.IsFull()) { + SDP_PRINT(SDP_WARN, SDP_SOCKET, ("Dropping the connection, because of a backlog that is too small\n")); + goto ErrorLocked; + } + + // Create a new socket for this request + pNewSocket = new SdpSocket; + if (pNewSocket == NULL) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket failed\n")); + goto ErrorLocked; + } + + // Code here is a little dirty to allow us to use the existing infrastructure + WspSocketIn SocketInParam; + WspSocketOut SocketOutParam; + SocketInParam.dwFlags = 0; + rc = pNewSocket->Init(&SocketInParam, &SocketOutParam); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket.Init() failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + ASSERT(SocketOutParam.Errno == 0); + ASSERT(SocketOutParam.pSocket == pNewSocket); + + // Connect the new socket to it's creator + ASSERT(pNewSocket->m_pListeningSocket == NULL); + pNewSocket->m_pListeningSocket = this; + pNewSocket->m_pListeningSocket->AddRef(); + + /* + * save hello parameters. + */ + pNewSocket->m_state = SS_REQ_RECV; //?????? do we really need this state????? + + pNewSocket->m_SrcIp = msg_hello->hh.dst.ipv4.addr; + ASSERT(m_SrcPort != 0); + pNewSocket->m_SrcPort = m_SrcPort; + pNewSocket->m_DstIp = msg_hello->hh.src.ipv4.addr; + pNewSocket->m_DstPort = msg_hello->hh.port; + + // Initiate parameters based on what we recieve from the remote side +// pNewSocket->send_size = msg_hello->hh.l_rcv_size; ??? MAX_Message_size when calling init on the buffers ??? +//??? pNewSocket->r_max_adv = msg_hello->hh.max_adv; ??????????? +//???? pNewSocket->r_recv_bf = msg_hello->bsdh.recv_bufs; <= m_pSdpSocket->m_SendBufferPool.SetRemoteRecvBuf(rRecvBuf); +//??? pNewSocket->recv_seq = msg_hello->bsdh.seq_num; +//??? pNewSocket->advt_seq = msg_hello->bsdh.seq_num; + + /* + * The maximum amount of data that can be sent to the remote + * peer is the smaller of the local and remote buffer sizes, + * minus the size of the message header. + */ +// conn->send_size = min((u16)sdp_buff_pool_buff_size(), +// (u16)conn->send_size) - SDP_MSG_HDR_SIZE; ?????????? + + // We will now allocate our QP. + + rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(pNewSocket->m_SrcIp, &SrcPortGuid, &SrcCaGuid); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + + if (pNewSocket->m_SrcCaGuid == 0) { + pNewSocket->m_SrcCaGuid = SrcCaGuid; + } else { + ASSERT(pNewSocket->m_SrcCaGuid == CL_NTOH64(p_cm_req_rec->primary_path.sgid.unicast.interface_id)); + } + + // MAke sure that the port that was recieved muches the one that we + // get based on the source IP. + if (SrcPortGuid != p_cm_req_rec->primary_path.sgid.unicast.interface_id) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Recieved guid is not what we have expected\n" )); + ASSERT(0); + goto ErrorLocked; + } + + rc = pNewSocket->CreateQp(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket.CreateQp() failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + + // We will now call init on the sender and the reciever + int MaxMessageSize = min(msg_hello->hh.l_rcv_size, MAX_SEND_BUFFER_SIZE); + + rc = pNewSocket->m_SendBufferPool.Init(MAX_SEND_PACKETS, QP_ATTRIB_SQ_DEPTH, MaxMessageSize, pNewSocket->m_pd, pNewSocket->m_qp, pNewSocket->m_lkey, pNewSocket); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_SendBufferPool.Init failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + + rc = pNewSocket->m_RecvBufferPool.Init(MAX_RECV_PACKETS, QP_ATTRIB_RQ_DEPTH, MaxMessageSize, pNewSocket->m_pd, pNewSocket->m_qp, pNewSocket->m_lkey, pNewSocket); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.Init failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + pNewSocket->m_SendBufferPool.SetRemoteRecvBuf(msg_hello->bsdh.recv_bufs); + + // It won't be used, but I want to make sure that there won't be + // problems later + pNewSocket->m_ConnectionList.Init(pNewSocket); + +#if 0 // ??????????????????????? + /* + * Save connect request info for QP modify in cm_accept(). + */ + conn->d_lid = event->param.req_rcvd.primary_path->dlid; + conn->s_lid = event->param.req_rcvd.primary_path->slid; + conn->d_qpn = event->param.req_rcvd.remote_qpn; + + conn->path_mtu = event->param.req_rcvd.primary_path->mtu; + /* + * inherit listener properties + */ + sdp_cm_listen_inherit(listen_conn, conn); + /* + * initiate a CM response message. + */ +#endif + + // + // Send the ib_cm_rep message to the remote side + // + ib_cm_rep_t cm_rep; + + memset( &cm_rep, 0, sizeof(cm_rep) ); + + cm_rep.qp_type = IB_QPT_RELIABLE_CONN; + cm_rep.h_qp = pNewSocket->m_qp; +// TODO: Add more cababilities once we start using RDMA +// cm_rep.access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE; + cm_rep.access_ctrl = IB_AC_LOCAL_WRITE; +#if 0 + // Bug in TAVOR + cm_rep.sq_depth = QP_ATTRIB_SQ_DEPTH; + cm_rep.rq_depth = QP_ATTRIB_RQ_DEPTH; +#endif + // We need to prepare the hello mesage for the CM + sdp_msg_hello_ack hello_ack_msg; + CreateHelloAckHeader(&hello_ack_msg); + + cm_rep.p_rep_pdata = (uint8_t *) &hello_ack_msg; + cm_rep.rep_length = sizeof(hello_ack_msg); + + cm_rep.init_depth = QP_ATTRIB_INITIATOR_DEPTH; + cm_rep.target_ack_delay = 10; + cm_rep.failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED; + cm_rep.flow_ctrl = p_cm_req_rec->flow_ctrl; + cm_rep.rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT; + cm_rep.rnr_retry_cnt = p_cm_req_rec->rnr_retry_cnt; + cm_rep.pfn_cm_mra_cb = cm_mra_callback; + cm_rep.pfn_cm_rej_cb = cm_rej_callback; + cm_rep.pfn_cm_rtu_cb = cm_rtu_callback; + cm_rep.pfn_cm_lap_cb = cm_lap_callback; + cm_rep.pfn_cm_dreq_cb = cm_dreq_callback; + + ib_status = ib_cm_rep( p_cm_req_rec->h_cm_req, &cm_rep ); + if( ib_status != IB_SUCCESS ) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_cm_rep failed ib_status = 0x%d\n", ib_status )); + rc = IB2Status(ib_status); + goto Cleanup; + } + + // Add this socket to the list of sockets ?????? should this also be done on errors ???? + rc = m_ConnectionList.AddConnectionToReplySent(pNewSocket); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket.Init() failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + + rc = pNewSocket->m_Lock.Lock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket.Init() failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + + rc = pNewSocket->m_RecvBufferPool.ReceiveIfCan(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket.Init() failed rc = 0x%x\n", rc )); + pNewSocket->m_Lock.Unlock(); // Error is ignored, since this is already an error path + goto ErrorLocked; + } + + // we now arm the CQs (after that a call back might happen) + ib_status = ib_rearm_cq(pNewSocket->m_rcq, FALSE); + if( ib_status != IB_SUCCESS ) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_rearm_cq failed ib_status = 0x%d\n", ib_status )); + rc = IB2Status(ib_status); + pNewSocket->m_Lock.Unlock(); // Error is ignored, since this is already an error path + goto ErrorLocked; + } + + ib_status = ib_rearm_cq(pNewSocket->m_scq, FALSE); + if( ib_status != IB_SUCCESS ) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_rearm_cq failed ib_status = 0x%d\n", ib_status )); + rc = IB2Status(ib_status); + pNewSocket->m_Lock.Unlock(); // Error is ignored, since this is already an error path + goto ErrorLocked; + } + + // Sucess - we can now release the lock and update our state + pNewSocket->m_state = SS_REP_SENT; + + rc = pNewSocket->m_Lock.Unlock(); // Error is ignored, since this is already an error path + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pNewSocket->m_Lock.Unlock() failed rc = 0x%x\n", rc )); + // BUGBUG: who is responsibale for the cleanup ??????? + goto ErrorLocked; + } + + rc = m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + // BUGBUG: who is responsibale for the cleanup ??????? + } + +Cleanup: + if (pNewSocket != NULL) { + pNewSocket->Release(); + } + return; + +ErrorLocked: + // Previous rc doesn't mater as this function is void + rc = m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + // BUGBUG: who is responsibale for the cleanup ??????? + } + goto Cleanup; + +} + +VOID +SdpSocket::CmRtuCallback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec) +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%x\n", this)); + NTSTATUS rc = STATUS_SUCCESS; + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + + SdpSocket *pSocket = (SdpSocket *) p_cm_rtu_rec->qp_context; + // In order to make our model more consistent we increase the refcount here. + // (This is not a must since this is a callback and we are gurantied that the last + // callback won't happen untill we free IBAL) + pSocket->AddRef(); + + + // Take the lock and verify the state + rc = m_Lock.Lock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Lock failed rc = 0x%x\n", rc )); + goto Cleanup; + } + + if (m_state != SS_LISTENING) { + // This is not the state that we waited for, we drop the request + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Not the expacted state %s\n", SS2String(m_state))); + ASSERT(FALSE); // Can this happen on shutdown ? + goto ErrorLocked; + } + + // First step is to verify that we have the new socket + rc = m_ConnectionList.VerifyConnictionInReplySent(pSocket); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_ConnectionList.GetConnection failed (got a call back on a not existing connection) rc = 0x%x\n", rc )); + ASSERT(FALSE); + goto ErrorLocked; + } + + // Next step is to move the new socket to the SS_CONNECTED state + rc = pSocket->m_Lock.Lock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Lock failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + if (pSocket->m_state != SS_REP_SENT) { + ASSERT(pSocket->m_state == SS_REP_SENT); + // This is not the expected state (probably shutdown). + // we should signal an error also on the one that is waiting + pSocket->m_Lock.Unlock(); // Error is ignored since this is already + // an error path + pSocket->Shutdown(); + rc = STATUS_UNEXPECTED_IO_ERROR; + goto ErrorLocked; + } + + pSocket->m_state = SS_CONNECTED; + + m_ConnectionList.MoveConnectionFromReplyToReady(pSocket); + rc = pSocket->m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("pSocket->m_Lock.Lock failed rc = 0x%x\n", rc )); + goto ErrorLocked; + } + + // if needed we will free the one that is waiting + m_ConnectionList.FreeWaitingIfCan(); + rc = m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Lock failed rc = 0x%x\n", rc )); + goto Cleanup; + } + +Cleanup: + + if (pSocket != NULL) { + pSocket->Release(); + } + + // Who should take care of the errors that were found here (if found)???????? + return; + +ErrorLocked: + // Previous rc doesn't mater as this function is void + rc = m_Lock.Unlock(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc )); + // BUGBUG: who is responsibale for the cleanup ??????? + } + goto Cleanup; + +} + VOID SdpSocket::__recv_cb1( @@ -924,11 +1665,12 @@ NTSTATUS SdpSocket::CreateQp() net32_t rkey; - SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("CreateQp called this = 0x%p\n", this)); + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p\n", this)); + ASSERT(m_SrcCaGuid != 0); /* Open the CA. */ ib_status = ib_open_ca( g_pSdpDriver->m_al_handle, - m_CaGuid, + m_SrcCaGuid, NULL, this, &mh_Ca @@ -1059,7 +1801,7 @@ VOID SdpSocket::CreateHelloHeader( ) { - SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::CreateHelloHeader called this = 0x%p\n", this)); + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p\n", this)); ASSERT(DestIp != 0); ASSERT(m_SrcPort != 0); ASSERT(m_SrcIp != 0); @@ -1087,9 +1829,36 @@ VOID SdpSocket::CreateHelloHeader( sdp_msg_swap_bsdh(&hello_msg->bsdh); sdp_msg_swap_hh(&hello_msg->hh); +} + +VOID SdpSocket::CreateHelloAckHeader( + sdp_msg_hello_ack* hello_ack_msg + ) +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("called this = 0x%p\n", this)); + + memset(hello_ack_msg, 0, sizeof(struct sdp_msg_hello_ack)); + hello_ack_msg->bsdh.recv_bufs = QP_ATTRIB_RQ_DEPTH; //????conn->l_advt_bf; + hello_ack_msg->bsdh.flags = SDP_MSG_FLAG_NON_FLAG; + hello_ack_msg->bsdh.mid = SDP_MID_HELLO_ACK; + hello_ack_msg->bsdh.size = sizeof(struct sdp_msg_hello_ack); + hello_ack_msg->bsdh.seq_num = m_SendBufferPool.GetAndIncreaseSendSeq();//conn->send_seq; ??? + hello_ack_msg->bsdh.seq_ack = m_RecvBufferPool.GetRecvSeq();//conn->advt_seq; ??? + + hello_ack_msg->hah.max_adv = QP_ATTRIB_RQ_DEPTH;// ??? conn->l_max_adv; + hello_ack_msg->hah.version = SDP_MSG_VERSION; + hello_ack_msg->hah.l_rcv_size = 4096;//???conn->recv_size; + + /* + * endian swap + */ + sdp_msg_swap_bsdh(&hello_ack_msg->bsdh); + sdp_msg_swap_hah(&hello_ack_msg->hah); + } + VOID SdpSocket::CreateCmRequest( ib_cm_req_t *cm_req, sdp_msg_hello *hello_msg, @@ -1176,6 +1945,20 @@ VOID SdpSocket::Shutdown() m_Lock.SignalShutdown(); + if (m_ListenHandle != NULL) { + ib_status = ib_cm_cancel( m_ListenHandle, ShutdownCB ); + if( ib_status != IB_SUCCESS ) { + SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_cm_cancel failed ib_status = 0x%d\n", ib_status )); + rc = IB2Status(ib_status); + } else { + WaitForShutdownEvent(&m_ShutdownCompleteEvent); + m_ListenHandle = NULL; + } + } + + m_ConnectionList.Shutdown(); + + if (m_qp != NULL) { ib_status = ib_destroy_qp(m_qp, ShutdownCB); ASSERT(ib_status == IB_SUCCESS); @@ -1206,6 +1989,11 @@ VOID SdpSocket::Shutdown() mh_Ca = NULL; WaitForShutdownEvent(&m_ShutdownCompleteEvent); } + + if (m_pListeningSocket != NULL) { + m_pListeningSocket->Release(); + m_pListeningSocket = NULL; + } // Now that all ibal operations have finished we can free the memory @@ -1236,7 +2024,7 @@ NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack) * endian swap */ sdp_msg_swap_bsdh(&hello_ack->bsdh); - sdp_msg_net_to_cpu_hah(&hello_ack->hah); + sdp_msg_swap_hah(&hello_ack->hah); /* * validation and consistency checks */ @@ -1283,5 +2071,70 @@ NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack) return STATUS_SUCCESS; } +NTSTATUS sdp_cm_hello_check(struct sdp_msg_hello *msg_hello) +{ + /* + * endian swap + */ + sdp_msg_swap_bsdh(&msg_hello->bsdh); + sdp_msg_swap_hh(&msg_hello->hh); + /* + * validation and consistency checks + */ + + if (msg_hello->bsdh.size != sizeof(struct sdp_msg_hello)) { + SDP_PRINT(SDP_WARN, SDP_SOCKET,( "hello msg size mismatch. (2) <%d:%Zu>", + msg_hello->bsdh.size, + sizeof(struct sdp_msg_hello))); + return STATUS_UNEXPECTED_IO_ERROR; + } + + if (SDP_MID_HELLO != msg_hello->bsdh.mid) { + SDP_PRINT(SDP_WARN, SDP_SOCKET,("hello msg unexpected ID. <%d>", + msg_hello->bsdh.mid)); + return STATUS_UNEXPECTED_IO_ERROR; + } + if (msg_hello->hh.max_adv <= 0) { + SDP_PRINT(SDP_WARN, SDP_SOCKET,("hello msg, bad zcopy count <%d>", + msg_hello->hh.max_adv)); + return STATUS_UNEXPECTED_IO_ERROR; + } + + if ((0xF0 & msg_hello->hh.version) != (0xF0 & SDP_MSG_VERSION)) { + SDP_PRINT(SDP_WARN, SDP_SOCKET,("hello msg, version mismatch. <%d:%d>", + ((0xF0 & msg_hello->hh.version) >> 4), + ((0xF0 & SDP_MSG_VERSION) >> 4))); + return STATUS_UNEXPECTED_IO_ERROR; + } +#ifdef _SDP_MS_APRIL_ERROR_COMPAT + if ((SDP_MSG_IPVER & 0x0F) != (msg_hello->hh.ip_ver & 0x0F)) +#else + if ((SDP_MSG_IPVER & 0xF0) != (msg_hello->hh.ip_ver & 0xF0)) { +#endif + SDP_PRINT(SDP_WARN, SDP_SOCKET,( "hello msg, ip version mismatch. <%d:%d>", + msg_hello->hh.ip_ver, SDP_MSG_IPVER)); + return STATUS_UNEXPECTED_IO_ERROR; + } + + SDP_PRINT(SDP_TRACE, SDP_SOCKET,("Hello BSDH <%04x:%02x:%02x:%08x:%08x:%08x>", + msg_hello->bsdh.recv_bufs, + msg_hello->bsdh.flags, + msg_hello->bsdh.mid, + msg_hello->bsdh.size, + msg_hello->bsdh.seq_num, + msg_hello->bsdh.seq_ack)); + SDP_PRINT(SDP_TRACE, SDP_SOCKET,( + "Hello HH <%02x:%02x:%02x:%08x:%08x:%04x:%08x:%08x>", + msg_hello->hh.max_adv, + msg_hello->hh.ip_ver, + msg_hello->hh.version, + msg_hello->hh.r_rcv_size, + msg_hello->hh.l_rcv_size, + msg_hello->hh.port, + msg_hello->hh.src.ipv4.addr, + msg_hello->hh.dst.ipv4.addr)); + + return STATUS_SUCCESS; +} diff --git a/trunk/ulp/sdp/kernel/SdpSocket.h b/trunk/ulp/sdp/kernel/SdpSocket.h index 61c7c24c..3e03021c 100644 --- a/trunk/ulp/sdp/kernel/SdpSocket.h +++ b/trunk/ulp/sdp/kernel/SdpSocket.h @@ -18,6 +18,11 @@ const int MAX_RECV_PACKETS = 200; // This is the maximum number #define QP_ATTRIB_SQ_DEPTH 64 #define QP_ATTRIB_SQ_SGE 1 /* Set based on inline data requirements */ +//#define QP_ATTRIB_RESPONDER_RESOURCES 4 +#define QP_ATTRIB_INITIATOR_DEPTH 4 +//#define QP_ATTRIB_RETRY_COUNT 6 +//#define QP_ATTRIB_RNR_RETRY 6 +#define QP_ATTRIB_RNR_NAK_TIMEOUT 6 /* * TODO: During testing, the switch has been observed to post @@ -37,12 +42,20 @@ enum SocketStates { SS_CONNECTING_REQ_SENT, SS_CONNECTING_RTU_SENT, SS_CONNECTED, + SS_BOUND, + SS_LISTENING, + SS_REQ_RECV, + SS_REP_SENT, SS_INSHUTDOWN }; +void cm_rtu_callback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec ); class SdpSocket : public RefCountImpl { + + friend void cm_rtu_callback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec ); + friend class ConnectionList; private: SocketStates m_state; @@ -54,13 +67,17 @@ private: USHORT m_SrcPort; ULONG m_SrcIp; + USHORT m_DstPort; + ULONG m_DstIp; + bool m_shutdown; // Make sure this is synced w SdpLock m_Lock; // A handle to the ca that is being used (in connect) and its guid ib_ca_handle_t mh_Ca; - net64_t m_CaGuid; + net64_t m_SrcCaGuid; // The guid of the CA that is used + ib_net64_t m_SrcPortGuid; // The guid of the port that is used ib_pd_handle_t m_pd; ib_cq_handle_t m_rcq; @@ -72,6 +89,17 @@ private: net32_t m_lkey; + // This handle is used if this is a socket that is listening for new connections + ib_listen_handle_t m_ListenHandle; + + // If this socket was created fron a listening socket, this is a + // pointer to the "mother socket" + SdpSocket* m_pListeningSocket; + + // If this socket is in a listners list of socket, this is the place that is + // used for puting it in the list + LIST_ENTRY m_ListeningSocketList; + KEVENT m_ConnectCmCompleteEvent; KEVENT m_ShutdownCompleteEvent; @@ -95,6 +123,7 @@ public: BufferPool m_SendBufferPool; RecvPool m_RecvBufferPool; + ConnectionList m_ConnectionList; SdpSocket(); @@ -119,6 +148,22 @@ public: WspRecvOut *pWspRecvOut ); + NTSTATUS WSPBind( + WspBindIn *pWspBindIn, + WspBindOut *pWspBindOut + ); + + NTSTATUS WSPListen( + WspListenIn *pWspListenIn, + WspListenOut *pWspListenOut + ); + + NTSTATUS WSPAccept( + WspAcceptIn *pWspAcceptIn, + WspAcceptOut *pWspAcceptOut + ); + + VOID Shutdown(); static VOID ShutdownCB(VOID* pContext); @@ -133,6 +178,10 @@ public: ULONG DestIp ); + VOID CreateHelloAckHeader( + sdp_msg_hello_ack* hello_ack_msg + ); + VOID CreateCmRequest( ib_cm_req_t *cm_req, sdp_msg_hello *hello_msg, @@ -141,6 +190,9 @@ public: ); VOID CmRepCallback(IN ib_cm_rep_rec_t *p_cm_rep_rec); + VOID CmReqCallback(IN ib_cm_req_rec_t *p_cm_req_rec); + VOID CmRtuCallback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec); + // Two varibales that are needed for passing REP data struct sdp_msg_hello_ack m_hello_ack; ib_cm_handle_t m_cm_handle_t; // BUGBUG: Check how this is used / locked diff --git a/trunk/ulp/sdp/kernel/SdpTrace.h b/trunk/ulp/sdp/kernel/SdpTrace.h index 45403e0c..247b3408 100644 --- a/trunk/ulp/sdp/kernel/SdpTrace.h +++ b/trunk/ulp/sdp/kernel/SdpTrace.h @@ -18,6 +18,7 @@ #define SDP_BUFFER_POOL 0x000020 #define SDP_LOCK 0x000040 #define SDP_PERFORMANCE 0x000080 +#define SDP_CONNECTION_LIST 0x000100 // BUGBUG: CONVERT TO A FUNCTION